1ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/* linux/drivers/video/s3c-fb.c
2ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
3ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Copyright 2008 Openmoko Inc.
450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * Copyright 2008-2010 Simtec Electronics
5ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *      Ben Dooks <ben@simtec.co.uk>
6ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *      http://armlinux.simtec.co.uk/
7ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
8ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Samsung SoC Framebuffer driver
9ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
10ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * This program is free software; you can redistribute it and/or modify
11ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * it under the terms of the GNU General Public License version 2 as
12c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * published by the Free Software FoundatIon.
13ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks*/
14ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
15ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#include <linux/kernel.h>
16ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#include <linux/module.h>
17ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#include <linux/platform_device.h>
18ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#include <linux/dma-mapping.h>
195a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
20ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#include <linux/init.h>
21ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#include <linux/clk.h>
22ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#include <linux/fb.h>
23ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#include <linux/io.h>
24efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak#include <linux/uaccess.h>
25efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak#include <linux/interrupt.h>
264959212c18669f254daa0ae796ad676b67939ba2Jingoo Han#include <linux/pm_runtime.h>
27ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
28ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#include <mach/map.h>
29c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#include <plat/regs-fb-v4.h>
30ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#include <plat/fb.h>
31ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
32ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/* This driver will export a number of framebuffer interfaces depending
33ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * on the configuration passed in via the platform data. Each fb instance
34ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * maps to a hardware window. Currently there is no support for runtime
35ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * setting of the alpha-blending functions that each window has, so only
36ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * window 0 is actually useful.
37ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
38ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Window 0 is treated specially, it is used for the basis of the LCD
39ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * output timings and as the control for the output power-down state.
40ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks*/
41ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
4250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks/* note, the previous use of <mach/regs-fb.h> to get platform specific data
4350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * has been replaced by using the platform device name to pick the correct
4450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * configuration data for the system.
45ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks*/
46ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
47ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#ifdef CONFIG_FB_S3C_DEBUG_REGWRITE
48ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#undef writel
49ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#define writel(v, r) do { \
50ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \
5105e52b4bfba0d1fa4195abbc4ac29c24033c8e96Jingoo Han	__raw_writel(v, r); \
5205e52b4bfba0d1fa4195abbc4ac29c24033c8e96Jingoo Han} while (0)
53ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#endif /* FB_S3C_DEBUG_REGWRITE */
54ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
55efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak/* irq_flags bits */
56efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak#define S3C_FB_VSYNC_IRQ_EN	0
57efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
58efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak#define VSYNC_TIMEOUT_MSEC 50
59efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
60ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstruct s3c_fb;
61ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
6250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks#define VALID_BPP(x) (1 << ((x) - 1))
6350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
64c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define OSD_BASE(win, variant) ((variant).osd + ((win) * (variant).osd_stride))
65c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define VIDOSD_A(win, variant) (OSD_BASE(win, variant) + 0x00)
66c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define VIDOSD_B(win, variant) (OSD_BASE(win, variant) + 0x04)
67c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define VIDOSD_C(win, variant) (OSD_BASE(win, variant) + 0x08)
68c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define VIDOSD_D(win, variant) (OSD_BASE(win, variant) + 0x0C)
69c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
7050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks/**
7150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * struct s3c_fb_variant - fb variant information
72c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @is_2443: Set if S3C2443/S3C2416 style hardware.
7350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @nr_windows: The number of windows.
74c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @vidtcon: The base for the VIDTCONx registers
75c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @wincon: The base for the WINxCON registers.
76c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @winmap: The base for the WINxMAP registers.
77c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @keycon: The abse for the WxKEYCON registers.
78c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @buf_start: Offset of buffer start registers.
79c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @buf_size: Offset of buffer size registers.
80c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @buf_end: Offset of buffer end registers.
81c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @osd: The base for the OSD registers.
8250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @palette: Address of palette memory, or 0 if none.
83067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * @has_prtcon: Set if has PRTCON register.
84f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak * @has_shadowcon: Set if has SHADOWCON register.
85f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han * @has_blendcon: Set if has BLENDCON register.
86b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han * @has_clksel: Set if VIDCON0 register has CLKSEL bit.
87d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han * @has_fixvclk: Set if VIDCON1 register has FIXVCLK bits.
8850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks */
8950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstruct s3c_fb_variant {
90c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned int	is_2443:1;
9150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	unsigned short	nr_windows;
925c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	unsigned int	vidtcon;
93c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	wincon;
94c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	winmap;
95c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	keycon;
96c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	buf_start;
97c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	buf_end;
98c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	buf_size;
99c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	osd;
100c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	osd_stride;
10150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	unsigned short	palette[S3C_FB_MAX_WIN];
102067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
103067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	unsigned int	has_prtcon:1;
104f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	unsigned int	has_shadowcon:1;
105f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han	unsigned int	has_blendcon:1;
106b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	unsigned int	has_clksel:1;
107d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han	unsigned int	has_fixvclk:1;
10850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
10950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
11050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks/**
11150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * struct s3c_fb_win_variant
11250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @has_osd_c: Set if has OSD C register.
11350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @has_osd_d: Set if has OSD D register.
114f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * @has_osd_alpha: Set if can change alpha transparency for a window.
11550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @palette_sz: Size of palette in entries.
11650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @palette_16bpp: Set if palette is 16bits wide.
117f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * @osd_size_off: If != 0, supports setting up OSD for a window; the appropriate
118f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak *                register is located at the given offset from OSD_BASE.
11950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @valid_bpp: 1 bit per BPP setting to show valid bits-per-pixel.
12050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks *
12150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * valid_bpp bit x is set if (x+1)BPP is supported.
12250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks */
12350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstruct s3c_fb_win_variant {
12450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	unsigned int	has_osd_c:1;
12550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	unsigned int	has_osd_d:1;
126f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	unsigned int	has_osd_alpha:1;
12750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	unsigned int	palette_16bpp:1;
128f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	unsigned short	osd_size_off;
12950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	unsigned short	palette_sz;
13050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	u32		valid_bpp;
13150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
13250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
13350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks/**
13450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * struct s3c_fb_driverdata - per-device type driver data for init time.
13550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @variant: The variant information for this driver.
13650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @win: The window information for each window.
13750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks */
13850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstruct s3c_fb_driverdata {
13950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	struct s3c_fb_variant	variant;
14050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	struct s3c_fb_win_variant *win[S3C_FB_MAX_WIN];
14150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
14250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
143ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
144bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * struct s3c_fb_palette - palette information
145bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * @r: Red bitfield.
146bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * @g: Green bitfield.
147bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * @b: Blue bitfield.
148bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * @a: Alpha bitfield.
149bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks */
150bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooksstruct s3c_fb_palette {
151bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	struct fb_bitfield	r;
152bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	struct fb_bitfield	g;
153bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	struct fb_bitfield	b;
154bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	struct fb_bitfield	a;
155bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks};
156bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks
157bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks/**
158ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * struct s3c_fb_win - per window private data for each framebuffer.
159ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @windata: The platform data supplied for the window configuration.
160ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @parent: The hardware that this window is part of.
161ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @fbinfo: Pointer pack to the framebuffer info for this window.
16250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @varint: The variant information for this window.
163ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @palette_buffer: Buffer/cache to hold palette entries.
164ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/
165ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @index: The window number of this window.
166ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @palette: The bitfields for changing r/g/b into a hardware palette entry.
167ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
168ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstruct s3c_fb_win {
169ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_pd_win	*windata;
170ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb		*parent;
171ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_info		*fbinfo;
172ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_palette	 palette;
17350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	struct s3c_fb_win_variant variant;
174ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
175ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32			*palette_buffer;
176ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32			 pseudo_palette[16];
177ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	unsigned int		 index;
178ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks};
179ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
180ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
181efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * struct s3c_fb_vsync - vsync information
182efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @wait:	a queue for processes waiting for vsync
183efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @count:	vsync interrupt count
184efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak */
185efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakstruct s3c_fb_vsync {
186efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	wait_queue_head_t	wait;
187efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	unsigned int		count;
188efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak};
189efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
190efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak/**
191ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * struct s3c_fb - overall hardware state of the hardware
192b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han * @slock: The spinlock protection for this data sturcture.
193ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @dev: The device that we bound to, for printing, etc.
194ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
195b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han * @lcd_clk: The clk (sclk) feeding pixclk.
196ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @regs: The mapped hardware registers.
19750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @variant: Variant information for this hardware.
198ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @enabled: A bitmask of enabled hardware windows.
199f4f514734e3d398cfb70827615f129826ff84b06Mark Brown * @output_on: Flag if the physical output is enabled.
200ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pdata: The platform configuration data passed with the device.
201ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @windows: The hardware windows that have been claimed.
202efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @irq_no: IRQ line number
203efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @irq_flags: irq flags
204efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @vsync_info: VSYNC-related information (count, queues...)
205ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
206ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstruct s3c_fb {
207b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han	spinlock_t		slock;
208ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct device		*dev;
209ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct clk		*bus_clk;
210b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	struct clk		*lcd_clk;
211ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	void __iomem		*regs;
21250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	struct s3c_fb_variant	 variant;
213ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
214ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	unsigned char		 enabled;
215f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	bool			 output_on;
216ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
217ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_platdata	*pdata;
218ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_win	*windows[S3C_FB_MAX_WIN];
219efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
220efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	int			 irq_no;
221efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	unsigned long		 irq_flags;
222efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	struct s3c_fb_vsync	 vsync_info;
223ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks};
224ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
225ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
22650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * s3c_fb_validate_win_bpp - validate the bits-per-pixel for this mode.
22750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @win: The device window.
22850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @bpp: The bit depth.
229ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
23050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstatic bool s3c_fb_validate_win_bpp(struct s3c_fb_win *win, unsigned int bpp)
231ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
23250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	return win->variant.valid_bpp & VALID_BPP(bpp);
233ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
234ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
235ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
236ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_check_var() - framebuffer layer request to verify a given mode.
237ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @var: The screen information to verify.
238ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @info: The framebuffer device.
239ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
240ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Framebuffer layer call to verify the given information and allow us to
241ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * update various information depending on the hardware capabilities.
242ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
243ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_check_var(struct fb_var_screeninfo *var,
244ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			    struct fb_info *info)
245ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
246ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_win *win = info->par;
247ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb *sfb = win->parent;
248ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
249ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "checking parameters\n");
250ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
25113e6af8886f3225fb9141dc3b6915d84bd4ad4deJingoo Han	var->xres_virtual = max(var->xres_virtual, var->xres);
25213e6af8886f3225fb9141dc3b6915d84bd4ad4deJingoo Han	var->yres_virtual = max(var->yres_virtual, var->yres);
253ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
25450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) {
255ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n",
256ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			win->index, var->bits_per_pixel);
257ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return -EINVAL;
258ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
259ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
260ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* always ensure these are zero, for drop through cases below */
261ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	var->transp.offset = 0;
262ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	var->transp.length = 0;
263ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
264ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	switch (var->bits_per_pixel) {
265ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 1:
266ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 2:
267ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 4:
268ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 8:
26950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		if (sfb->variant.palette[win->index] != 0) {
270ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			/* non palletised, A:1,R:2,G:3,B:2 mode */
271ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->red.offset		= 4;
272ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->green.offset	= 2;
273ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->blue.offset	= 0;
274ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->red.length		= 5;
275ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->green.length	= 3;
276ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->blue.length	= 2;
277ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->transp.offset	= 7;
278ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->transp.length	= 1;
279ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		} else {
280ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->red.offset	= 0;
281ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->red.length	= var->bits_per_pixel;
282ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->green	= var->red;
283ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->blue	= var->red;
284ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		}
285ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
286ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
287ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 19:
288ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* 666 with one bit alpha/transparency */
289ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->transp.offset	= 18;
290ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->transp.length	= 1;
291ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 18:
292ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->bits_per_pixel	= 32;
293ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
294ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* 666 format */
295ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->red.offset		= 12;
296ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->green.offset	= 6;
297ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->blue.offset	= 0;
298ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->red.length		= 6;
299ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->green.length	= 6;
300ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->blue.length	= 6;
301ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
302ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
303ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 16:
304ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* 16 bpp, 565 format */
305ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->red.offset		= 11;
306ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->green.offset	= 5;
307ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->blue.offset	= 0;
308ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->red.length		= 5;
309ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->green.length	= 6;
310ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->blue.length	= 5;
311ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
312ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
313af1ce6b2fad7d572aef040d61a935da28a861853Jingoo Han	case 32:
314ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 28:
315ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 25:
316ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->transp.length	= var->bits_per_pixel - 24;
317ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->transp.offset	= 24;
318ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* drop through */
319ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 24:
320ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* our 24bpp is unpacked, so 32bpp */
321ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->bits_per_pixel	= 32;
322ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->red.offset		= 16;
323ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->red.length		= 8;
324ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->green.offset	= 8;
325ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->green.length	= 8;
326ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->blue.offset	= 0;
327ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->blue.length	= 8;
328ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
329ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
330ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	default:
331ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(sfb->dev, "invalid bpp\n");
332ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
333ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
334ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "%s: verified parameters\n", __func__);
335ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
336ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
337ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
338ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
339ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock.
340ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The hardware state.
341ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pixclock: The pixel clock wanted, in picoseconds.
342ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
343ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Given the specified pixel clock, work out the necessary divider to get
344ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * close to the output frequency.
345ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
346eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brownstatic int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
347ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
348b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	unsigned long clk;
349eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown	unsigned long long tmp;
350ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	unsigned int result;
351ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
352b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	if (sfb->variant.has_clksel)
353b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk = clk_get_rate(sfb->bus_clk);
354b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	else
355b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk = clk_get_rate(sfb->lcd_clk);
356b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
357eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown	tmp = (unsigned long long)clk;
358eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown	tmp *= pixclk;
359eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown
360eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown	do_div(tmp, 1000000000UL);
361eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown	result = (unsigned int)tmp / 1000;
362ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
363ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n",
364ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		pixclk, clk, result, clk / result);
365ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
366ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return result;
367ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
368ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
369ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
370ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_align_word() - align pixel count to word boundary
371ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @bpp: The number of bits per pixel
372ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pix: The value to be aligned.
373ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
374ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Align the given pixel count so that it will start on an 32bit word
375ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * boundary.
376ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
377ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_align_word(unsigned int bpp, unsigned int pix)
378ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
379ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int pix_per_word;
380ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
381ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (bpp > 16)
382ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return pix;
383ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
384ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	pix_per_word = (8 * 32) / bpp;
385ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return ALIGN(pix, pix_per_word);
386ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
387ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
388ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
389f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * vidosd_set_size() - set OSD size for a window
390f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak *
391f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * @win: the window to set OSD size for
392f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * @size: OSD size register value
393f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak */
394f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciakstatic void vidosd_set_size(struct s3c_fb_win *win, u32 size)
395f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak{
396f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	struct s3c_fb *sfb = win->parent;
397f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak
398f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	/* OSD can be set up if osd_size_off != 0 for this window */
399f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	if (win->variant.osd_size_off)
400f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		writel(size, sfb->regs + OSD_BASE(win->index, sfb->variant)
401f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak				+ win->variant.osd_size_off);
402f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak}
403f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak
404f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak/**
405f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * vidosd_set_alpha() - set alpha transparency for a window
406f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak *
407f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * @win: the window to set OSD size for
408f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * @alpha: alpha register value
409f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak */
410f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciakstatic void vidosd_set_alpha(struct s3c_fb_win *win, u32 alpha)
411f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak{
412f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	struct s3c_fb *sfb = win->parent;
413f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak
414f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	if (win->variant.has_osd_alpha)
415f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		writel(alpha, sfb->regs + VIDOSD_C(win->index, sfb->variant));
416f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak}
417f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak
418f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak/**
419f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak * shadow_protect_win() - disable updating values from shadow registers at vsync
420f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak *
421f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak * @win: window to protect registers for
422f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak * @protect: 1 to protect (disable updates)
423f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak */
424f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciakstatic void shadow_protect_win(struct s3c_fb_win *win, bool protect)
425f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak{
426f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	struct s3c_fb *sfb = win->parent;
427f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	u32 reg;
428f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak
429f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	if (protect) {
430f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		if (sfb->variant.has_prtcon) {
431f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak			writel(PRTCON_PROTECT, sfb->regs + PRTCON);
432f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		} else if (sfb->variant.has_shadowcon) {
433f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak			reg = readl(sfb->regs + SHADOWCON);
434f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak			writel(reg | SHADOWCON_WINx_PROTECT(win->index),
435f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak				sfb->regs + SHADOWCON);
436f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		}
437f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	} else {
438f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		if (sfb->variant.has_prtcon) {
439f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak			writel(0, sfb->regs + PRTCON);
440f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		} else if (sfb->variant.has_shadowcon) {
441f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak			reg = readl(sfb->regs + SHADOWCON);
442f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak			writel(reg & ~SHADOWCON_WINx_PROTECT(win->index),
443f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak				sfb->regs + SHADOWCON);
444f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		}
445f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	}
446f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak}
447f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak
448f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak/**
449a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown * s3c_fb_enable() - Set the state of the main LCD output
450a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown * @sfb: The main framebuffer state.
451a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown * @enable: The state to set.
452a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown */
453a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brownstatic void s3c_fb_enable(struct s3c_fb *sfb, int enable)
454a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown{
455a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown	u32 vidcon0 = readl(sfb->regs + VIDCON0);
456a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown
457f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	if (enable && !sfb->output_on)
458f4f514734e3d398cfb70827615f129826ff84b06Mark Brown		pm_runtime_get_sync(sfb->dev);
459f4f514734e3d398cfb70827615f129826ff84b06Mark Brown
460f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	if (enable) {
461a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown		vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
462f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	} else {
463a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown		/* see the note in the framebuffer datasheet about
464a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown		 * why you cannot take both of these bits down at the
465a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown		 * same time. */
466a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown
467f4f514734e3d398cfb70827615f129826ff84b06Mark Brown		if (vidcon0 & VIDCON0_ENVID) {
468f4f514734e3d398cfb70827615f129826ff84b06Mark Brown			vidcon0 |= VIDCON0_ENVID;
469f4f514734e3d398cfb70827615f129826ff84b06Mark Brown			vidcon0 &= ~VIDCON0_ENVID_F;
470f4f514734e3d398cfb70827615f129826ff84b06Mark Brown		}
471a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown	}
472a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown
473a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown	writel(vidcon0, sfb->regs + VIDCON0);
474f4f514734e3d398cfb70827615f129826ff84b06Mark Brown
475f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	if (!enable && sfb->output_on)
476f4f514734e3d398cfb70827615f129826ff84b06Mark Brown		pm_runtime_put_sync(sfb->dev);
477f4f514734e3d398cfb70827615f129826ff84b06Mark Brown
478f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	sfb->output_on = enable;
479a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown}
480a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown
481a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown/**
482ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_set_par() - framebuffer request to set new framebuffer state.
483ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @info: The framebuffer to change.
484ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
485ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Framebuffer layer request to set a new mode for the specified framebuffer
486ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
487ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_set_par(struct fb_info *info)
488ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
489ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_var_screeninfo *var = &info->var;
490ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_win *win = info->par;
491ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb *sfb = win->parent;
492ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	void __iomem *regs = sfb->regs;
493c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	void __iomem *buf = regs;
494ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int win_no = win->index;
495f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	u32 alpha = 0;
496ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32 data;
497ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32 pagewidth;
498ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int clkdiv;
499ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
500ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "setting framebuffer parameters\n");
501ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
5025751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown	pm_runtime_get_sync(sfb->dev);
5035751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown
504a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak	shadow_protect_win(win, 1);
505a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak
506ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	switch (var->bits_per_pixel) {
507ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 32:
508ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 24:
509ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 16:
510ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 12:
511ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		info->fix.visual = FB_VISUAL_TRUECOLOR;
512ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
513ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 8:
51450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		if (win->variant.palette_sz >= 256)
515ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
516ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		else
517ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			info->fix.visual = FB_VISUAL_TRUECOLOR;
518ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
519ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 1:
520ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		info->fix.visual = FB_VISUAL_MONO01;
521ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
522ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	default:
523ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
524ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
525ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
526ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
527ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
528ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
529067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
530067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
531067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
532ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* disable the window whilst we update it */
533ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	writel(0, regs + WINCON(win_no));
534ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
535ad04490a171915737c9b99d2fa5cb813830f24c1InKi Dae	/* use platform specified window as the basis for the lcd timings */
536ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
537ad04490a171915737c9b99d2fa5cb813830f24c1InKi Dae	if (win_no == sfb->pdata->default_win) {
538eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown		clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock);
539ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
540ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data = sfb->pdata->vidcon0;
541ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
542ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
543ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (clkdiv > 1)
544ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR;
545ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		else
546ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data &= ~VIDCON0_CLKDIR;	/* 1:1 clock */
547ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
548ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* write the timing data to the panel */
549ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
550c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		if (sfb->variant.is_2443)
551c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks			data |= (1 << 5);
552c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
553ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		writel(data, regs + VIDCON0);
554ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
555a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown		s3c_fb_enable(sfb, 1);
556a2b77dcebf6e968bada4d415d426b39ac199e8aaMark Brown
557ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data = VIDTCON0_VBPD(var->upper_margin - 1) |
558ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		       VIDTCON0_VFPD(var->lower_margin - 1) |
559ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		       VIDTCON0_VSPW(var->vsync_len - 1);
560ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
561c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(data, regs + sfb->variant.vidtcon);
562ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
563ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data = VIDTCON1_HBPD(var->left_margin - 1) |
564ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		       VIDTCON1_HFPD(var->right_margin - 1) |
565ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		       VIDTCON1_HSPW(var->hsync_len - 1);
566ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
567c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		/* VIDTCON1 */
568c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(data, regs + sfb->variant.vidtcon + 4);
569ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
570ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data = VIDTCON2_LINEVAL(var->yres - 1) |
5715c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		       VIDTCON2_HOZVAL(var->xres - 1) |
5725c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		       VIDTCON2_LINEVAL_E(var->yres - 1) |
5735c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		       VIDTCON2_HOZVAL_E(var->xres - 1);
574b73a21fc66fee35b41db755abebfacba48b2fc76Jingoo Han		writel(data, regs + sfb->variant.vidtcon + 8);
575ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
576ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
577ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* write the buffer address */
578ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
579c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	/* start and end registers stride is 8 */
580c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	buf = regs + win_no * 8;
581c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
582c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(info->fix.smem_start, buf + sfb->variant.buf_start);
583ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
584ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	data = info->fix.smem_start + info->fix.line_length * var->yres;
585c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(data, buf + sfb->variant.buf_end);
586ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
587ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	pagewidth = (var->xres * var->bits_per_pixel) >> 3;
588ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) |
5895c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	       VIDW_BUF_SIZE_PAGEWIDTH(pagewidth) |
5905c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	       VIDW_BUF_SIZE_OFFSET_E(info->fix.line_length - pagewidth) |
5915c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	       VIDW_BUF_SIZE_PAGEWIDTH_E(pagewidth);
592c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(data, regs + sfb->variant.buf_size + (win_no * 4));
593ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
594ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* write 'OSD' registers to control position of framebuffer */
595ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
5965c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0) |
5975c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	       VIDOSDxA_TOPLEFT_X_E(0) | VIDOSDxA_TOPLEFT_Y_E(0);
598c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(data, regs + VIDOSD_A(win_no, sfb->variant));
599ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
600ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel,
601ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks						     var->xres - 1)) |
6025c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	       VIDOSDxB_BOTRIGHT_Y(var->yres - 1) |
6035c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	       VIDOSDxB_BOTRIGHT_X_E(s3c_fb_align_word(var->bits_per_pixel,
6045c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han						     var->xres - 1)) |
6055c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	       VIDOSDxB_BOTRIGHT_Y_E(var->yres - 1);
606ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
607c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(data, regs + VIDOSD_B(win_no, sfb->variant));
608ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
609ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	data = var->xres * var->yres;
61039000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae
611f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	alpha = VIDISD14C_ALPHA1_R(0xf) |
61239000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae		VIDISD14C_ALPHA1_G(0xf) |
61339000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae		VIDISD14C_ALPHA1_B(0xf);
61439000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae
615f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	vidosd_set_alpha(win, alpha);
616f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	vidosd_set_size(win, data);
617ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
618fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han	/* Enable DMA channel for this window */
619fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han	if (sfb->variant.has_shadowcon) {
620fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han		data = readl(sfb->regs + SHADOWCON);
621fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han		data |= SHADOWCON_CHx_ENABLE(win_no);
622fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han		writel(data, sfb->regs + SHADOWCON);
623fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han	}
624fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han
625ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	data = WINCONx_ENWIN;
6262d9ae7ac48c91e15e693038bf0dff004f7872aafJingoo Han	sfb->enabled |= (1 << win->index);
627ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
628ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* note, since we have to round up the bits-per-pixel, we end up
629ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * relying on the bitfield information for r/g/b/a to work out
630ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * exactly which mode of operation is intended. */
631ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
632ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	switch (var->bits_per_pixel) {
633ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 1:
634ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCON0_BPPMODE_1BPP;
635ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BITSWP;
636ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BURSTLEN_4WORD;
637ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
638ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 2:
639ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCON0_BPPMODE_2BPP;
640ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BITSWP;
641ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BURSTLEN_8WORD;
642ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
643ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 4:
644ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCON0_BPPMODE_4BPP;
645ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BITSWP;
646ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BURSTLEN_8WORD;
647ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
648ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 8:
649ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (var->transp.length != 0)
650ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data |= WINCON1_BPPMODE_8BPP_1232;
651ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		else
652ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data |= WINCON0_BPPMODE_8BPP_PALETTE;
653ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BURSTLEN_8WORD;
654ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BYTSWP;
655ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
656ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 16:
657ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (var->transp.length != 0)
658ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data |= WINCON1_BPPMODE_16BPP_A1555;
659ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		else
660ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data |= WINCON0_BPPMODE_16BPP_565;
661ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_HAWSWP;
662ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BURSTLEN_16WORD;
663ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
664ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 24:
665ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 32:
666ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (var->red.length == 6) {
667ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			if (var->transp.length != 0)
668ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				data |= WINCON1_BPPMODE_19BPP_A1666;
669ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			else
670ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				data |= WINCON1_BPPMODE_18BPP_666;
67139000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae		} else if (var->transp.length == 1)
67239000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae			data |= WINCON1_BPPMODE_25BPP_A1888
67339000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae				| WINCON1_BLD_PIX;
6744420dd2b306f1997232a13462bca0d420be5b1b8Jingoo Han		else if ((var->transp.length == 4) ||
6754420dd2b306f1997232a13462bca0d420be5b1b8Jingoo Han			(var->transp.length == 8))
67639000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae			data |= WINCON1_BPPMODE_28BPP_A4888
67739000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae				| WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
678ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		else
679ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data |= WINCON0_BPPMODE_24BPP_888;
680ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
681dc8498c00f6a41a28f01111a3d2ed9f179356a71InKi Dae		data |= WINCONx_WSWP;
682ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BURSTLEN_16WORD;
683ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
684ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
685ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
686c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	/* Enable the colour keying for the window below this one */
68739000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae	if (win_no > 0) {
68839000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae		u32 keycon0_data = 0, keycon1_data = 0;
689c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		void __iomem *keycon = regs + sfb->variant.keycon;
69039000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae
69139000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae		keycon0_data = ~(WxKEYCON0_KEYBL_EN |
69239000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae				WxKEYCON0_KEYEN_F |
69339000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae				WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
69439000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae
69539000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae		keycon1_data = WxKEYCON1_COLVAL(0xffffff);
69639000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae
697c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		keycon += (win_no - 1) * 8;
698c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
699c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(keycon0_data, keycon + WKEYCON0);
700c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(keycon1_data, keycon + WKEYCON1);
70139000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae	}
70239000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae
703c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(data, regs + sfb->variant.wincon + (win_no * 4));
704c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(0x0, regs + sfb->variant.winmap + (win_no * 4));
705ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
706f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han	/* Set alpha value width */
707f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han	if (sfb->variant.has_blendcon) {
708f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han		data = readl(sfb->regs + BLENDCON);
709f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han		data &= ~BLENDCON_NEW_MASK;
710f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han		if (var->transp.length > 4)
711f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han			data |= BLENDCON_NEW_8BIT_ALPHA_VALUE;
712f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han		else
713f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han			data |= BLENDCON_NEW_4BIT_ALPHA_VALUE;
714f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han		writel(data, sfb->regs + BLENDCON);
715f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han	}
716f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han
717a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak	shadow_protect_win(win, 0);
718a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak
7195751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown	pm_runtime_put_sync(sfb->dev);
7205751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown
721ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
722ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
723ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
724ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
725ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_update_palette() - set or schedule a palette update.
726ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The hardware information.
727ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window being updated.
728ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @reg: The palette index being changed.
729ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @value: The computed palette value.
730ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
731ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Change the value of a palette register, either by directly writing to
732ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * the palette (this requires the palette RAM to be disconnected from the
733ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * hardware whilst this is in progress) or schedule the update for later.
734ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
735ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * At the moment, since we have no VSYNC interrupt support, we simply set
736ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * the palette entry directly.
737ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
738ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_update_palette(struct s3c_fb *sfb,
739ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				  struct s3c_fb_win *win,
740ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				  unsigned int reg,
741ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				  u32 value)
742ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
743ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	void __iomem *palreg;
744ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32 palcon;
745ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
74650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	palreg = sfb->regs + sfb->variant.palette[win->index];
747ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
748ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n",
749ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		__func__, win->index, reg, palreg, value);
750ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
751ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win->palette_buffer[reg] = value;
752ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
753ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	palcon = readl(sfb->regs + WPALCON);
754ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON);
755ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
75650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	if (win->variant.palette_16bpp)
75750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		writew(value, palreg + (reg * 2));
758ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	else
75950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		writel(value, palreg + (reg * 4));
760ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
761ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	writel(palcon, sfb->regs + WPALCON);
762ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
763ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
764ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic inline unsigned int chan_to_field(unsigned int chan,
765ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks					 struct fb_bitfield *bf)
766ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
767ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	chan &= 0xffff;
768ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	chan >>= 16 - bf->length;
769ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return chan << bf->offset;
770ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
771ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
772ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
773ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_setcolreg() - framebuffer layer request to change palette.
774ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @regno: The palette index to change.
775ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @red: The red field for the palette data.
776ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @green: The green field for the palette data.
777ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @blue: The blue field for the palette data.
778ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @trans: The transparency (alpha) field for the palette data.
779ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @info: The framebuffer being changed.
780ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
781ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_setcolreg(unsigned regno,
782ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			    unsigned red, unsigned green, unsigned blue,
783ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			    unsigned transp, struct fb_info *info)
784ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
785ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_win *win = info->par;
786ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb *sfb = win->parent;
787ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	unsigned int val;
788ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
789ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n",
790ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		__func__, win->index, regno, red, green, blue);
791ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
7925751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown	pm_runtime_get_sync(sfb->dev);
7935751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown
794ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	switch (info->fix.visual) {
795ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_VISUAL_TRUECOLOR:
796ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* true-colour, use pseudo-palette */
797ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
798ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (regno < 16) {
799ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			u32 *pal = info->pseudo_palette;
800ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
801ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			val  = chan_to_field(red,   &info->var.red);
802ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			val |= chan_to_field(green, &info->var.green);
803ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			val |= chan_to_field(blue,  &info->var.blue);
804ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
805ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			pal[regno] = val;
806ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		}
807ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
808ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
809ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_VISUAL_PSEUDOCOLOR:
81050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		if (regno < win->variant.palette_sz) {
811ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			val  = chan_to_field(red, &win->palette.r);
812ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			val |= chan_to_field(green, &win->palette.g);
813ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			val |= chan_to_field(blue, &win->palette.b);
814ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
815ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			s3c_fb_update_palette(sfb, win, regno, val);
816ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		}
817ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
818ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
819ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
820ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	default:
8215751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown		pm_runtime_put_sync(sfb->dev);
822ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return 1;	/* unknown type */
823ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
824ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
8255751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown	pm_runtime_put_sync(sfb->dev);
826ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
827ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
828ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
829ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
830ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_blank() - blank or unblank the given window
831ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @blank_mode: The blank state from FB_BLANK_*
832ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @info: The framebuffer to blank.
833ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
834ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Framebuffer layer request to change the power state.
835ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
836ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_blank(int blank_mode, struct fb_info *info)
837ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
838ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_win *win = info->par;
839ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb *sfb = win->parent;
840ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	unsigned int index = win->index;
841ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32 wincon;
842ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
843ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
844ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
8455751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown	pm_runtime_get_sync(sfb->dev);
8465751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown
847c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4));
848ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
849ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	switch (blank_mode) {
850ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_BLANK_POWERDOWN:
851ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		wincon &= ~WINCONx_ENWIN;
852ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		sfb->enabled &= ~(1 << index);
853ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* fall through to FB_BLANK_NORMAL */
854ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
855ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_BLANK_NORMAL:
856ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* disable the DMA and display 0x0 (black) */
857ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 1);
858ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0),
859c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		       sfb->regs + sfb->variant.winmap + (index * 4));
860ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 0);
861ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
862ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
863ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_BLANK_UNBLANK:
864ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 1);
865c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4));
866ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 0);
867ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		wincon |= WINCONx_ENWIN;
868ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		sfb->enabled |= (1 << index);
869ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
870ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
871ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_BLANK_VSYNC_SUSPEND:
872ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_BLANK_HSYNC_SUSPEND:
873ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	default:
8745751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown		pm_runtime_put_sync(sfb->dev);
875ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return 1;
876ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
877ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
878ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han	shadow_protect_win(win, 1);
879c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4));
880ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han	shadow_protect_win(win, 0);
881ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
882ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* Check the enabled state to see if we need to be running the
883ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * main LCD interface, as if there are no active windows then
884ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * it is highly likely that we also do not need to output
885ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * anything.
886ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 */
887ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
888ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* We could do something like the following code, but the current
889ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * system of using framebuffer events means that we cannot make
890ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * the distinction between just window 0 being inactive and all
891ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * the windows being down.
892ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 *
893ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * s3c_fb_enable(sfb, sfb->enabled ? 1 : 0);
894ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	*/
895ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
896ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* we're stuck with this until we can do something about overriding
897ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * the power control using the blanking event for a single fb.
898ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 */
899ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han	if (index == sfb->pdata->default_win) {
900ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 1);
901ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0);
902ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 0);
903ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han	}
904ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
9055751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown	pm_runtime_put_sync(sfb->dev);
9065751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown
907ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
908ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
909ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
910067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak/**
911067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * s3c_fb_pan_display() - Pan the display.
912067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak *
913067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * Note that the offsets can be written to the device at any time, as their
914067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * values are latched at each vsync automatically. This also means that only
915067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * the last call to this function will have any effect on next vsync, but
916067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * there is no need to sleep waiting for it to prevent tearing.
917067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak *
918067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * @var: The screen information to verify.
919067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * @info: The framebuffer device.
920067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak */
921067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciakstatic int s3c_fb_pan_display(struct fb_var_screeninfo *var,
922067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			      struct fb_info *info)
923067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak{
924067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	struct s3c_fb_win *win	= info->par;
925067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	struct s3c_fb *sfb	= win->parent;
926067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	void __iomem *buf	= sfb->regs + win->index * 8;
927067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	unsigned int start_boff, end_boff;
928067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
9295751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown	pm_runtime_get_sync(sfb->dev);
9305751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown
931067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	/* Offset in bytes to the start of the displayed area */
932067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	start_boff = var->yoffset * info->fix.line_length;
933067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	/* X offset depends on the current bpp */
934067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	if (info->var.bits_per_pixel >= 8) {
935067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		start_boff += var->xoffset * (info->var.bits_per_pixel >> 3);
936067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	} else {
937067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		switch (info->var.bits_per_pixel) {
938067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		case 4:
939067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			start_boff += var->xoffset >> 1;
940067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			break;
941067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		case 2:
942067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			start_boff += var->xoffset >> 2;
943067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			break;
944067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		case 1:
945067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			start_boff += var->xoffset >> 3;
946067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			break;
947067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		default:
948067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			dev_err(sfb->dev, "invalid bpp\n");
9495751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown			pm_runtime_put_sync(sfb->dev);
950067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			return -EINVAL;
951067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		}
952067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	}
953067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	/* Offset in bytes to the end of the displayed area */
954d8e7a74bf1f1c3d8235e1d939d3e1e96da94ed82Laurent Pinchart	end_boff = start_boff + info->var.yres * info->fix.line_length;
955067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
956067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	/* Temporarily turn off per-vsync update from shadow registers until
957067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	 * both start and end addresses are updated to prevent corruption */
958f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	shadow_protect_win(win, 1);
959067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
960067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	writel(info->fix.smem_start + start_boff, buf + sfb->variant.buf_start);
961067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	writel(info->fix.smem_start + end_boff, buf + sfb->variant.buf_end);
962067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
963f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	shadow_protect_win(win, 0);
964067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
9655751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown	pm_runtime_put_sync(sfb->dev);
966067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	return 0;
967067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak}
968067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
969efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak/**
970efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * s3c_fb_enable_irq() - enable framebuffer interrupts
971efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @sfb: main hardware state
972efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak */
973efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakstatic void s3c_fb_enable_irq(struct s3c_fb *sfb)
974efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak{
975efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	void __iomem *regs = sfb->regs;
976efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	u32 irq_ctrl_reg;
977efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
978efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (!test_and_set_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
979efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		/* IRQ disabled, enable it */
980efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg = readl(regs + VIDINTCON0);
981efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
982efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg |= VIDINTCON0_INT_ENABLE;
983efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg |= VIDINTCON0_INT_FRAME;
984efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
985efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL0_MASK;
986efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg |= VIDINTCON0_FRAMESEL0_VSYNC;
987efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL1_MASK;
988efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg |= VIDINTCON0_FRAMESEL1_NONE;
989efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
990efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		writel(irq_ctrl_reg, regs + VIDINTCON0);
991efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	}
992efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak}
993efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
994efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak/**
995efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * s3c_fb_disable_irq() - disable framebuffer interrupts
996efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @sfb: main hardware state
997efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak */
998efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakstatic void s3c_fb_disable_irq(struct s3c_fb *sfb)
999efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak{
1000efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	void __iomem *regs = sfb->regs;
1001efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	u32 irq_ctrl_reg;
1002efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1003efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (test_and_clear_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
1004efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		/* IRQ enabled, disable it */
1005efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg = readl(regs + VIDINTCON0);
1006efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1007efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg &= ~VIDINTCON0_INT_FRAME;
1008efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg &= ~VIDINTCON0_INT_ENABLE;
1009efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1010efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		writel(irq_ctrl_reg, regs + VIDINTCON0);
1011efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	}
1012efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak}
1013efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1014efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakstatic irqreturn_t s3c_fb_irq(int irq, void *dev_id)
1015efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak{
1016efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	struct s3c_fb *sfb = dev_id;
1017efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	void __iomem  *regs = sfb->regs;
1018efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	u32 irq_sts_reg;
1019efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1020b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han	spin_lock(&sfb->slock);
1021b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han
1022efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	irq_sts_reg = readl(regs + VIDINTCON1);
1023efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1024efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (irq_sts_reg & VIDINTCON1_INT_FRAME) {
1025efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1026efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		/* VSYNC interrupt, accept it */
1027efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		writel(VIDINTCON1_INT_FRAME, regs + VIDINTCON1);
1028efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1029efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		sfb->vsync_info.count++;
1030efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		wake_up_interruptible(&sfb->vsync_info.wait);
1031efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	}
1032efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1033efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	/* We only support waiting for VSYNC for now, so it's safe
1034efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	 * to always disable irqs here.
1035efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	 */
1036efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	s3c_fb_disable_irq(sfb);
1037efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1038b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han	spin_unlock(&sfb->slock);
1039efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	return IRQ_HANDLED;
1040efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak}
1041efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1042efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak/**
1043efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * s3c_fb_wait_for_vsync() - sleep until next VSYNC interrupt or timeout
1044efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @sfb: main hardware state
1045efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @crtc: head index.
1046efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak */
1047efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakstatic int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
1048efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak{
1049efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	unsigned long count;
1050efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	int ret;
1051efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1052efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (crtc != 0)
1053efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		return -ENODEV;
1054efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
10555751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown	pm_runtime_get_sync(sfb->dev);
10565751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown
1057efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	count = sfb->vsync_info.count;
1058efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	s3c_fb_enable_irq(sfb);
1059efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
1060efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak				       count != sfb->vsync_info.count,
1061efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak				       msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
10625751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown
10635751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown	pm_runtime_put_sync(sfb->dev);
10645751b23efb1d91db729ac52e78dd9c9e57baf19fMark Brown
1065efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (ret == 0)
1066efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		return -ETIMEDOUT;
1067efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1068efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	return 0;
1069efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak}
1070efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1071efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakstatic int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
1072efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak			unsigned long arg)
1073efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak{
1074efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	struct s3c_fb_win *win = info->par;
1075efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	struct s3c_fb *sfb = win->parent;
1076efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	int ret;
1077efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	u32 crtc;
1078efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1079efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	switch (cmd) {
1080efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	case FBIO_WAITFORVSYNC:
1081efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		if (get_user(crtc, (u32 __user *)arg)) {
1082efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak			ret = -EFAULT;
1083efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak			break;
1084efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		}
1085efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1086efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		ret = s3c_fb_wait_for_vsync(sfb, crtc);
1087efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		break;
1088efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	default:
1089efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		ret = -ENOTTY;
1090efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	}
1091efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1092efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	return ret;
1093efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak}
1094efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1095ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic struct fb_ops s3c_fb_ops = {
1096ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.owner		= THIS_MODULE,
1097ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_check_var	= s3c_fb_check_var,
1098ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_set_par	= s3c_fb_set_par,
1099ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_blank	= s3c_fb_blank,
1100ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_setcolreg	= s3c_fb_setcolreg,
1101ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_fillrect	= cfb_fillrect,
1102ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_copyarea	= cfb_copyarea,
1103ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_imageblit	= cfb_imageblit,
1104067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	.fb_pan_display	= s3c_fb_pan_display,
1105efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	.fb_ioctl	= s3c_fb_ioctl,
1106ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks};
1107ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1108ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
11092bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere * s3c_fb_missing_pixclock() - calculates pixel clock
11102bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere * @mode: The video mode to change.
11112bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere *
11122bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere * Calculate the pixel clock when none has been given through platform data.
11132bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere */
11142bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaerestatic void __devinit s3c_fb_missing_pixclock(struct fb_videomode *mode)
11152bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere{
11162bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	u64 pixclk = 1000000000000ULL;
11172bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	u32 div;
11182bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere
11192bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	div  = mode->left_margin + mode->hsync_len + mode->right_margin +
11202bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	       mode->xres;
11212bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	div *= mode->upper_margin + mode->vsync_len + mode->lower_margin +
11222bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	       mode->yres;
11232bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	div *= mode->refresh ? : 60;
11242bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere
11252bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	do_div(pixclk, div);
11262bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere
11272bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	mode->pixclock = pixclk;
11282bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere}
11292bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere
11302bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere/**
1131ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_alloc_memory() - allocate display memory for framebuffer window
1132ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The base resources for the hardware.
1133ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window to initialise memory for.
1134ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
1135ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Allocate memory for the given framebuffer.
1136ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
1137ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb,
1138ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks					 struct s3c_fb_win *win)
1139ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
1140ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_pd_win *windata = win->windata;
1141ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	unsigned int real_size, virt_size, size;
1142ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_info *fbi = win->fbinfo;
1143ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dma_addr_t map_dma;
1144ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1145ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "allocating memory for display\n");
1146ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1147ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	real_size = windata->win_mode.xres * windata->win_mode.yres;
1148ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	virt_size = windata->virtual_x * windata->virtual_y;
1149ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1150ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n",
1151ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		real_size, windata->win_mode.xres, windata->win_mode.yres,
1152ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		virt_size, windata->virtual_x, windata->virtual_y);
1153ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1154ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	size = (real_size > virt_size) ? real_size : virt_size;
1155ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	size *= (windata->max_bpp > 16) ? 32 : windata->max_bpp;
1156ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	size /= 8;
1157ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1158ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbi->fix.smem_len = size;
1159ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	size = PAGE_ALIGN(size);
1160ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1161ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "want %u bytes for window\n", size);
1162ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1163ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbi->screen_base = dma_alloc_writecombine(sfb->dev, size,
1164ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks						  &map_dma, GFP_KERNEL);
1165ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!fbi->screen_base)
1166ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return -ENOMEM;
1167ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1168ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "mapped %x to %p\n",
1169ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		(unsigned int)map_dma, fbi->screen_base);
1170ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1171ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	memset(fbi->screen_base, 0x0, size);
1172ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbi->fix.smem_start = map_dma;
1173ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1174ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
1175ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1176ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1177ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
1178ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_free_memory() - free the display memory for the given window
1179ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The base resources for the hardware.
1180ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window to free the display memory for.
1181ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
1182ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Free the display memory allocated by s3c_fb_alloc_memory().
1183ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
1184ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
1185ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
1186ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_info *fbi = win->fbinfo;
1187ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1188cd7d7e0244955a4694d1e79e8c8a9bef163d6305Pawel Osciak	if (fbi->screen_base)
1189cd7d7e0244955a4694d1e79e8c8a9bef163d6305Pawel Osciak		dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
1190ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			      fbi->screen_base, fbi->fix.smem_start);
1191ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1192ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1193ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
1194ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_release_win() - release resources for a framebuffer window.
1195ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window to cleanup the resources for.
1196ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
1197ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Release the resources that where claimed for the hardware window,
1198ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * such as the framebuffer instance and any memory claimed for it.
1199ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
1200ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win)
1201ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
120204ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak	u32 data;
120304ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak
1204ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt	if (win->fbinfo) {
120504ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak		if (sfb->variant.has_shadowcon) {
120604ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak			data = readl(sfb->regs + SHADOWCON);
120704ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak			data &= ~SHADOWCON_CHx_ENABLE(win->index);
120804ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak			data &= ~SHADOWCON_CHx_LOCAL_ENABLE(win->index);
120904ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak			writel(data, sfb->regs + SHADOWCON);
121004ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak		}
1211ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt		unregister_framebuffer(win->fbinfo);
1212cd7d7e0244955a4694d1e79e8c8a9bef163d6305Pawel Osciak		if (win->fbinfo->cmap.len)
1213cd7d7e0244955a4694d1e79e8c8a9bef163d6305Pawel Osciak			fb_dealloc_cmap(&win->fbinfo->cmap);
1214ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt		s3c_fb_free_memory(sfb, win);
1215ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt		framebuffer_release(win->fbinfo);
1216ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt	}
1217ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1218ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1219ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
1220ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_probe_win() - register an hardware window
1221ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The base resources for the hardware
122250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @variant: The variant information for this window.
1223ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @res: Pointer to where to place the resultant window.
1224ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
1225ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Allocate and do the basic initialisation for one of the hardware's graphics
1226ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * windows.
1227ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
1228ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
122950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks				      struct s3c_fb_win_variant *variant,
1230ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				      struct s3c_fb_win **res)
1231ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
1232ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_var_screeninfo *var;
1233ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_videomode *initmode;
1234ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_pd_win *windata;
1235ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_win *win;
1236ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_info *fbinfo;
1237ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int palette_size;
1238ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int ret;
1239ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1240c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	dev_dbg(sfb->dev, "probing window %d, variant %p\n", win_no, variant);
1241ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1242efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	init_waitqueue_head(&sfb->vsync_info.wait);
1243efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
124450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	palette_size = variant->palette_sz * 4;
1245ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1246ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
1247ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				   palette_size * sizeof(u32), sfb->dev);
1248ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!fbinfo) {
1249ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(sfb->dev, "failed to allocate framebuffer\n");
1250ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return -ENOENT;
1251ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1252ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1253ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	windata = sfb->pdata->win[win_no];
1254ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	initmode = &windata->win_mode;
1255ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1256ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	WARN_ON(windata->max_bpp == 0);
1257ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	WARN_ON(windata->win_mode.xres == 0);
1258ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	WARN_ON(windata->win_mode.yres == 0);
1259ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1260ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win = fbinfo->par;
1261cd7d7e0244955a4694d1e79e8c8a9bef163d6305Pawel Osciak	*res = win;
1262ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	var = &fbinfo->var;
126350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	win->variant = *variant;
1264ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win->fbinfo = fbinfo;
1265ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win->parent = sfb;
1266ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win->windata = windata;
1267ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win->index = win_no;
1268ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win->palette_buffer = (u32 *)(win + 1);
1269ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1270ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	ret = s3c_fb_alloc_memory(sfb, win);
1271ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (ret) {
1272ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(sfb->dev, "failed to allocate display memory\n");
1273ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt		return ret;
1274ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1275ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1276ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* setup the r/b/g positions for the window's palette */
1277bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	if (win->variant.palette_16bpp) {
1278bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		/* Set RGB 5:6:5 as default */
1279bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.r.offset = 11;
1280bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.r.length = 5;
1281bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.g.offset = 5;
1282bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.g.length = 6;
1283bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.b.offset = 0;
1284bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.b.length = 5;
1285bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks
1286bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	} else {
1287bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		/* Set 8bpp or 8bpp and 1bit alpha */
1288bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.r.offset = 16;
1289bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.r.length = 8;
1290bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.g.offset = 8;
1291bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.g.length = 8;
1292bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.b.offset = 0;
1293bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.b.length = 8;
1294bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	}
1295ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1296ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* setup the initial video mode from the window */
1297ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fb_videomode_to_var(&fbinfo->var, initmode);
1298ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1299ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->fix.type	= FB_TYPE_PACKED_PIXELS;
1300ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->fix.accel	= FB_ACCEL_NONE;
1301ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->var.activate	= FB_ACTIVATE_NOW;
1302ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->var.vmode	= FB_VMODE_NONINTERLACED;
1303ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->var.bits_per_pixel = windata->default_bpp;
1304ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->fbops		= &s3c_fb_ops;
1305ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->flags		= FBINFO_FLAG_DEFAULT;
1306ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->pseudo_palette  = &win->pseudo_palette;
1307ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1308ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* prepare to actually start the framebuffer */
1309ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1310ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	ret = s3c_fb_check_var(&fbinfo->var, fbinfo);
1311ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (ret < 0) {
1312ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(sfb->dev, "check_var failed on initial video params\n");
1313ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt		return ret;
1314ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1315ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1316ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* create initial colour map */
1317ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
131850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	ret = fb_alloc_cmap(&fbinfo->cmap, win->variant.palette_sz, 1);
1319ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (ret == 0)
1320ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		fb_set_cmap(&fbinfo->cmap, fbinfo);
1321ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	else
1322ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(sfb->dev, "failed to allocate fb cmap\n");
1323ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1324ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	s3c_fb_set_par(fbinfo);
1325ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1326ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "about to register framebuffer\n");
1327ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1328ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* run the check_var and set_par on our configuration. */
1329ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1330ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	ret = register_framebuffer(fbinfo);
1331ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (ret < 0) {
1332ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(sfb->dev, "failed to register framebuffer\n");
1333ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt		return ret;
1334ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1335ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1336ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id);
1337ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1338ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
1339ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1340ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1341ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
1342ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_clear_win() - clear hardware window registers.
1343ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The base resources for the hardware.
1344ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window to process.
1345ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
1346ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Reset the specific window registers to a known state.
1347ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
1348ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
1349ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
1350ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	void __iomem *regs = sfb->regs;
1351a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak	u32 reg;
1352ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1353c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(0, regs + sfb->variant.wincon + (win * 4));
1354c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(0, regs + VIDOSD_A(win, sfb->variant));
1355c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(0, regs + VIDOSD_B(win, sfb->variant));
1356c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(0, regs + VIDOSD_C(win, sfb->variant));
1357a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak	reg = readl(regs + SHADOWCON);
1358a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak	writel(reg & ~SHADOWCON_WINx_PROTECT(win), regs + SHADOWCON);
1359ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1360ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1361ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __devinit s3c_fb_probe(struct platform_device *pdev)
1362ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
1363b73a21fc66fee35b41db755abebfacba48b2fc76Jingoo Han	const struct platform_device_id *platid;
136450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	struct s3c_fb_driverdata *fbdrv;
1365ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct device *dev = &pdev->dev;
1366ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_platdata *pd;
1367ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb *sfb;
1368ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct resource *res;
1369ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int win;
1370ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int ret = 0;
1371d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han	u32 reg;
1372ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1373b73a21fc66fee35b41db755abebfacba48b2fc76Jingoo Han	platid = platform_get_device_id(pdev);
1374b73a21fc66fee35b41db755abebfacba48b2fc76Jingoo Han	fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
137550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
137650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {
137750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		dev_err(dev, "too many windows, cannot attach\n");
137850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		return -EINVAL;
137950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	}
138050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
1381ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	pd = pdev->dev.platform_data;
1382ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!pd) {
1383ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(dev, "no platform data specified\n");
1384ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return -EINVAL;
1385ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1386ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1387857a8df9467a6dfe5d3aa309d9bdef31dc817647Mark Brown	sfb = devm_kzalloc(dev, sizeof(struct s3c_fb), GFP_KERNEL);
1388ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!sfb) {
1389ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(dev, "no memory for framebuffers\n");
1390ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return -ENOMEM;
1391ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1392ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1393c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	dev_dbg(dev, "allocate new framebuffer %p\n", sfb);
1394c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
1395ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	sfb->dev = dev;
1396ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	sfb->pdata = pd;
139750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	sfb->variant = fbdrv->variant;
1398ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1399b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han	spin_lock_init(&sfb->slock);
1400b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han
1401ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	sfb->bus_clk = clk_get(dev, "lcd");
1402ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (IS_ERR(sfb->bus_clk)) {
1403ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(dev, "failed to get bus clock\n");
1404942b8d05cdf1da396b4449a38b87c677591947c0Axel Lin		ret = PTR_ERR(sfb->bus_clk);
1405ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		goto err_sfb;
1406ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1407ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1408ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	clk_enable(sfb->bus_clk);
1409ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1410b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	if (!sfb->variant.has_clksel) {
1411b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		sfb->lcd_clk = clk_get(dev, "sclk_fimd");
1412b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		if (IS_ERR(sfb->lcd_clk)) {
1413b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			dev_err(dev, "failed to get lcd clock\n");
1414b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			ret = PTR_ERR(sfb->lcd_clk);
1415b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			goto err_bus_clk;
1416b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		}
1417b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
1418b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_enable(sfb->lcd_clk);
1419b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	}
1420b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
14214959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	pm_runtime_enable(sfb->dev);
14224959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1423ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1424ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!res) {
1425ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(dev, "failed to find registers\n");
1426ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		ret = -ENOENT;
1427b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		goto err_lcd_clk;
1428ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1429ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1430857a8df9467a6dfe5d3aa309d9bdef31dc817647Mark Brown	sfb->regs = devm_request_and_ioremap(dev, res);
1431ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!sfb->regs) {
1432ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(dev, "failed to map registers\n");
1433ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		ret = -ENXIO;
1434857a8df9467a6dfe5d3aa309d9bdef31dc817647Mark Brown		goto err_lcd_clk;
1435ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1436ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1437efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1438efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (!res) {
1439efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		dev_err(dev, "failed to acquire irq resource\n");
1440efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		ret = -ENOENT;
1441857a8df9467a6dfe5d3aa309d9bdef31dc817647Mark Brown		goto err_lcd_clk;
1442efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	}
1443efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	sfb->irq_no = res->start;
1444327e27681c27d3ed5ea470ec483904d1a318cb7fJingoo Han	ret = devm_request_irq(dev, sfb->irq_no, s3c_fb_irq,
1445efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak			  0, "s3c_fb", sfb);
1446efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (ret) {
1447efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		dev_err(dev, "irq request failed\n");
1448857a8df9467a6dfe5d3aa309d9bdef31dc817647Mark Brown		goto err_lcd_clk;
1449efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	}
1450efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1451ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
1452ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
14534959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	platform_set_drvdata(pdev, sfb);
14544959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	pm_runtime_get_sync(sfb->dev);
14554959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1456ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* setup gpio and output polarity controls */
1457ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1458ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	pd->setup_gpio();
1459ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1460ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	writel(pd->vidcon1, sfb->regs + VIDCON1);
1461ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1462d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han	/* set video clock running at under-run */
1463d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han	if (sfb->variant.has_fixvclk) {
1464d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han		reg = readl(sfb->regs + VIDCON1);
1465d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han		reg &= ~VIDCON1_VCLK_MASK;
1466d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han		reg |= VIDCON1_VCLK_RUN;
1467d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han		writel(reg, sfb->regs + VIDCON1);
1468d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han	}
1469d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han
1470ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* zero all windows before we do anything */
1471ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
147250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	for (win = 0; win < fbdrv->variant.nr_windows; win++)
1473ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		s3c_fb_clear_win(sfb, win);
1474ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1475949470375393e82dc9158d36d675180c8c250388Ben Dooks	/* initialise colour key controls */
147650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	for (win = 0; win < (fbdrv->variant.nr_windows - 1); win++) {
1477c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		void __iomem *regs = sfb->regs + sfb->variant.keycon;
1478c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
1479c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		regs += (win * 8);
1480c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(0xffffff, regs + WKEYCON0);
1481c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(0xffffff, regs + WKEYCON1);
1482949470375393e82dc9158d36d675180c8c250388Ben Dooks	}
1483949470375393e82dc9158d36d675180c8c250388Ben Dooks
1484ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* we have the register setup, start allocating framebuffers */
1485ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
148650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	for (win = 0; win < fbdrv->variant.nr_windows; win++) {
1487ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (!pd->win[win])
1488ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			continue;
1489ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
14902bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere		if (!pd->win[win]->win_mode.pixclock)
14912bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere			s3c_fb_missing_pixclock(&pd->win[win]->win_mode);
14922bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere
149350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
149450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks				       &sfb->windows[win]);
1495ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (ret < 0) {
1496ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			dev_err(dev, "failed to create window %d\n", win);
1497ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			for (; win >= 0; win--)
1498ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				s3c_fb_release_win(sfb, sfb->windows[win]);
14993500b0be62c8cc2f93e8022dc70071ec31b067deMark Brown			goto err_pm_runtime;
1500ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		}
1501ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1502ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1503ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	platform_set_drvdata(pdev, sfb);
1504fe05f8b1c3d28e6204a9ec54dec0d68af6cbf4c8Mark Brown	pm_runtime_put_sync(sfb->dev);
1505ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1506ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
1507ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
15083500b0be62c8cc2f93e8022dc70071ec31b067deMark Brownerr_pm_runtime:
15093500b0be62c8cc2f93e8022dc70071ec31b067deMark Brown	pm_runtime_put_sync(sfb->dev);
1510efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1511b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Hanerr_lcd_clk:
15123500b0be62c8cc2f93e8022dc70071ec31b067deMark Brown	pm_runtime_disable(sfb->dev);
15133500b0be62c8cc2f93e8022dc70071ec31b067deMark Brown
1514b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	if (!sfb->variant.has_clksel) {
1515b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_disable(sfb->lcd_clk);
1516b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_put(sfb->lcd_clk);
1517b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	}
1518b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
1519b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Hanerr_bus_clk:
1520ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	clk_disable(sfb->bus_clk);
1521ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	clk_put(sfb->bus_clk);
1522ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1523ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dookserr_sfb:
1524ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return ret;
1525ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1526ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1527ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
1528ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_remove() - Cleanup on module finalisation
1529ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pdev: The platform device we are bound to.
1530ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
1531ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Shutdown and then release all the resources that the driver allocated
1532ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * on initialisation.
1533ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
1534ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __devexit s3c_fb_remove(struct platform_device *pdev)
1535ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
1536ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb *sfb = platform_get_drvdata(pdev);
1537ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int win;
1538ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1539fe05f8b1c3d28e6204a9ec54dec0d68af6cbf4c8Mark Brown	pm_runtime_get_sync(sfb->dev);
1540fe05f8b1c3d28e6204a9ec54dec0d68af6cbf4c8Mark Brown
1541c42b110caeb128819104d057acdaa1ae564b7c8dPawel Osciak	for (win = 0; win < S3C_FB_MAX_WIN; win++)
154217663e59704bea838a9236f299104e30909a43b1Marek Szyprowski		if (sfb->windows[win])
154317663e59704bea838a9236f299104e30909a43b1Marek Szyprowski			s3c_fb_release_win(sfb, sfb->windows[win]);
1544ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1545b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	if (!sfb->variant.has_clksel) {
1546b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_disable(sfb->lcd_clk);
1547b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_put(sfb->lcd_clk);
1548b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	}
1549b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
1550ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	clk_disable(sfb->bus_clk);
1551ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	clk_put(sfb->bus_clk);
1552ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
15534959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	pm_runtime_put_sync(sfb->dev);
15544959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	pm_runtime_disable(sfb->dev);
15554959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1556ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
1557ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1558ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1559f4f514734e3d398cfb70827615f129826ff84b06Mark Brown#ifdef CONFIG_PM_SLEEP
15604959212c18669f254daa0ae796ad676b67939ba2Jingoo Hanstatic int s3c_fb_suspend(struct device *dev)
15614959212c18669f254daa0ae796ad676b67939ba2Jingoo Han{
15624959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct platform_device *pdev = to_platform_device(dev);
15634959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct s3c_fb *sfb = platform_get_drvdata(pdev);
15644959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct s3c_fb_win *win;
15654959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	int win_no;
15664959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
15674959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
15684959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		win = sfb->windows[win_no];
15694959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		if (!win)
15704959212c18669f254daa0ae796ad676b67939ba2Jingoo Han			continue;
15714959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
15724959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		/* use the blank function to push into power-down */
15734959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
15744959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	}
15754959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1576b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	if (!sfb->variant.has_clksel)
1577b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_disable(sfb->lcd_clk);
1578b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
15794959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	clk_disable(sfb->bus_clk);
15804959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	return 0;
15814959212c18669f254daa0ae796ad676b67939ba2Jingoo Han}
15824959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
15834959212c18669f254daa0ae796ad676b67939ba2Jingoo Hanstatic int s3c_fb_resume(struct device *dev)
15844959212c18669f254daa0ae796ad676b67939ba2Jingoo Han{
15854959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct platform_device *pdev = to_platform_device(dev);
15864959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct s3c_fb *sfb = platform_get_drvdata(pdev);
15874959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct s3c_fb_platdata *pd = sfb->pdata;
15884959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct s3c_fb_win *win;
15894959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	int win_no;
1590d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han	u32 reg;
15914959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
15924959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	clk_enable(sfb->bus_clk);
15934959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1594b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	if (!sfb->variant.has_clksel)
1595b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_enable(sfb->lcd_clk);
1596b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
15976aa9681100303bd467cbd0262eb00da8d492fc7fJingoo Han	/* setup gpio and output polarity controls */
15986aa9681100303bd467cbd0262eb00da8d492fc7fJingoo Han	pd->setup_gpio();
15994959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	writel(pd->vidcon1, sfb->regs + VIDCON1);
16004959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1601d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han	/* set video clock running at under-run */
1602d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han	if (sfb->variant.has_fixvclk) {
1603d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han		reg = readl(sfb->regs + VIDCON1);
1604d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han		reg &= ~VIDCON1_VCLK_MASK;
1605d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han		reg |= VIDCON1_VCLK_RUN;
1606d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han		writel(reg, sfb->regs + VIDCON1);
1607d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han	}
1608d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han
16094959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	/* zero all windows before we do anything */
16104959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
16114959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		s3c_fb_clear_win(sfb, win_no);
16124959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
16134959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
16144959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		void __iomem *regs = sfb->regs + sfb->variant.keycon;
1615ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		win = sfb->windows[win_no];
1616ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		if (!win)
1617ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han			continue;
16184959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1619ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 1);
16204959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		regs += (win_no * 8);
16214959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		writel(0xffffff, regs + WKEYCON0);
16224959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		writel(0xffffff, regs + WKEYCON1);
1623ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 0);
16244959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	}
16254959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
16264959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	/* restore framebuffers */
16274959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
16284959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		win = sfb->windows[win_no];
16294959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		if (!win)
16304959212c18669f254daa0ae796ad676b67939ba2Jingoo Han			continue;
16314959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
16324959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
16334959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		s3c_fb_set_par(win->fbinfo);
16344959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	}
16354959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
16364959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	return 0;
16374959212c18669f254daa0ae796ad676b67939ba2Jingoo Han}
1638ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#endif
1639ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1640f4f514734e3d398cfb70827615f129826ff84b06Mark Brown#ifdef CONFIG_PM_RUNTIME
1641f4f514734e3d398cfb70827615f129826ff84b06Mark Brownstatic int s3c_fb_runtime_suspend(struct device *dev)
1642f4f514734e3d398cfb70827615f129826ff84b06Mark Brown{
1643f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	struct platform_device *pdev = to_platform_device(dev);
1644f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	struct s3c_fb *sfb = platform_get_drvdata(pdev);
1645f4f514734e3d398cfb70827615f129826ff84b06Mark Brown
1646f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	if (!sfb->variant.has_clksel)
1647f4f514734e3d398cfb70827615f129826ff84b06Mark Brown		clk_disable(sfb->lcd_clk);
1648f4f514734e3d398cfb70827615f129826ff84b06Mark Brown
1649f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	clk_disable(sfb->bus_clk);
1650f4f514734e3d398cfb70827615f129826ff84b06Mark Brown
1651f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	return 0;
1652f4f514734e3d398cfb70827615f129826ff84b06Mark Brown}
1653f4f514734e3d398cfb70827615f129826ff84b06Mark Brown
1654f4f514734e3d398cfb70827615f129826ff84b06Mark Brownstatic int s3c_fb_runtime_resume(struct device *dev)
1655f4f514734e3d398cfb70827615f129826ff84b06Mark Brown{
1656f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	struct platform_device *pdev = to_platform_device(dev);
1657f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	struct s3c_fb *sfb = platform_get_drvdata(pdev);
1658f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	struct s3c_fb_platdata *pd = sfb->pdata;
1659f4f514734e3d398cfb70827615f129826ff84b06Mark Brown
1660f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	clk_enable(sfb->bus_clk);
1661f4f514734e3d398cfb70827615f129826ff84b06Mark Brown
1662f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	if (!sfb->variant.has_clksel)
1663f4f514734e3d398cfb70827615f129826ff84b06Mark Brown		clk_enable(sfb->lcd_clk);
1664f4f514734e3d398cfb70827615f129826ff84b06Mark Brown
1665f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	/* setup gpio and output polarity controls */
1666f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	pd->setup_gpio();
1667f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	writel(pd->vidcon1, sfb->regs + VIDCON1);
1668f4f514734e3d398cfb70827615f129826ff84b06Mark Brown
1669f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	return 0;
1670f4f514734e3d398cfb70827615f129826ff84b06Mark Brown}
1671f4f514734e3d398cfb70827615f129826ff84b06Mark Brown#endif
167250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
167350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
167450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
167550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
16768cfdcb2393b05cc80f89ed0110c0f90423d2fee1Marek Szyprowskistatic struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = {
167750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	[0] = {
167850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_c	= 1,
1679f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		.osd_size_off	= 0x8,
168050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_sz	= 256,
1681cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
1682cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(18) | VALID_BPP(24)),
168350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
168450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	[1] = {
168550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_c	= 1,
168650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_d	= 1,
1687c9d503e93562e1de093ff16a480fc8801cfa70d9Jingoo Han		.osd_size_off	= 0xc,
1688f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		.has_osd_alpha	= 1,
168950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_sz	= 256,
169050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
169150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks				   VALID_BPP(18) | VALID_BPP(19) |
1692cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1693cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(28)),
169450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
169550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	[2] = {
169650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_c	= 1,
169750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_d	= 1,
1698c9d503e93562e1de093ff16a480fc8801cfa70d9Jingoo Han		.osd_size_off	= 0xc,
1699f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		.has_osd_alpha	= 1,
170050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_sz	= 16,
170150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_16bpp	= 1,
170250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
170350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks				   VALID_BPP(18) | VALID_BPP(19) |
1704cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1705cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(28)),
170650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
170750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	[3] = {
170850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_c	= 1,
1709f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		.has_osd_alpha	= 1,
171050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_sz	= 16,
171150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_16bpp	= 1,
171250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.valid_bpp	= (VALID_BPP124  | VALID_BPP(16) |
171350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks				   VALID_BPP(18) | VALID_BPP(19) |
1714cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1715cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(28)),
171650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
171750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	[4] = {
171850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_c	= 1,
1719f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		.has_osd_alpha	= 1,
172050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_sz	= 4,
172150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_16bpp	= 1,
172250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.valid_bpp	= (VALID_BPP(1) | VALID_BPP(2) |
172350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks				   VALID_BPP(16) | VALID_BPP(18) |
1724cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(19) | VALID_BPP(24) |
1725cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(25) | VALID_BPP(28)),
172650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
172750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
172850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
1729af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Hanstatic struct s3c_fb_win_variant s3c_fb_data_s5p_wins[] = {
1730af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	[0] = {
1731af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_c	= 1,
1732af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.osd_size_off	= 0x8,
1733af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.palette_sz	= 256,
1734af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
1735af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(15) | VALID_BPP(16) |
1736af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(18) | VALID_BPP(19) |
1737af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1738af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(32)),
1739af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	},
1740af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	[1] = {
1741af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_c	= 1,
1742af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_d	= 1,
1743af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.osd_size_off	= 0xc,
1744af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_alpha	= 1,
1745af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.palette_sz	= 256,
1746af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
1747af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(15) | VALID_BPP(16) |
1748af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(18) | VALID_BPP(19) |
1749af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1750af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(32)),
1751af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	},
1752af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	[2] = {
1753af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_c	= 1,
1754af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_d	= 1,
1755af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.osd_size_off	= 0xc,
1756af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_alpha	= 1,
1757af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.palette_sz	= 256,
1758af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
1759af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(15) | VALID_BPP(16) |
1760af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(18) | VALID_BPP(19) |
1761af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1762af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(32)),
1763af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	},
1764af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	[3] = {
1765af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_c	= 1,
1766af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_alpha	= 1,
1767af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.palette_sz	= 256,
1768af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
1769af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(15) | VALID_BPP(16) |
1770af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(18) | VALID_BPP(19) |
1771af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1772af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(32)),
1773af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	},
1774af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	[4] = {
1775af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_c	= 1,
1776af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_alpha	= 1,
1777af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.palette_sz	= 256,
1778af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
1779af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(15) | VALID_BPP(16) |
1780af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(18) | VALID_BPP(19) |
1781af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1782af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(32)),
1783af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	},
1784af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han};
1785af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han
17868cfdcb2393b05cc80f89ed0110c0f90423d2fee1Marek Szyprowskistatic struct s3c_fb_driverdata s3c_fb_data_64xx = {
178750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.variant = {
178850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.nr_windows	= 5,
1789c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.vidtcon	= VIDTCON0,
1790c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.wincon		= WINCON(0),
1791c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.winmap		= WINxMAP(0),
1792c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.keycon		= WKEYCON,
1793c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.osd		= VIDOSD_BASE,
1794c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.osd_stride	= 16,
1795c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_start	= VIDW_BUF_START(0),
1796c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_size	= VIDW_BUF_SIZE(0),
1797c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_end	= VIDW_BUF_END(0),
179850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
179950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette = {
180050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[0] = 0x400,
180150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[1] = 0x800,
180250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[2] = 0x300,
180350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[3] = 0x320,
180450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[4] = 0x340,
180550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		},
1806067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
1807067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		.has_prtcon	= 1,
1808b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.has_clksel	= 1,
180950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
181050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.win[0]	= &s3c_fb_data_64xx_wins[0],
181150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.win[1]	= &s3c_fb_data_64xx_wins[1],
181250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.win[2]	= &s3c_fb_data_64xx_wins[2],
181350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.win[3]	= &s3c_fb_data_64xx_wins[3],
181450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.win[4]	= &s3c_fb_data_64xx_wins[4],
181550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
181650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
18178cfdcb2393b05cc80f89ed0110c0f90423d2fee1Marek Szyprowskistatic struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
18184e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak	.variant = {
18194e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.nr_windows	= 5,
18204e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.vidtcon	= VIDTCON0,
18214e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.wincon		= WINCON(0),
18224e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.winmap		= WINxMAP(0),
18234e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.keycon		= WKEYCON,
18244e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.osd		= VIDOSD_BASE,
18254e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.osd_stride	= 16,
18264e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.buf_start	= VIDW_BUF_START(0),
18274e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.buf_size	= VIDW_BUF_SIZE(0),
18284e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.buf_end	= VIDW_BUF_END(0),
18294e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak
18304e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.palette = {
18314e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak			[0] = 0x2400,
18324e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak			[1] = 0x2800,
18334e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak			[2] = 0x2c00,
18344e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak			[3] = 0x3000,
18354e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak			[4] = 0x3400,
18364e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		},
1837067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
1838067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		.has_prtcon	= 1,
1839f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han		.has_blendcon	= 1,
1840b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.has_clksel	= 1,
18414e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak	},
1842af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[0]	= &s3c_fb_data_s5p_wins[0],
1843af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[1]	= &s3c_fb_data_s5p_wins[1],
1844af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[2]	= &s3c_fb_data_s5p_wins[2],
1845af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[3]	= &s3c_fb_data_s5p_wins[3],
1846af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[4]	= &s3c_fb_data_s5p_wins[4],
18474e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak};
18484e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak
18498cfdcb2393b05cc80f89ed0110c0f90423d2fee1Marek Szyprowskistatic struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
185050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.variant = {
185150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.nr_windows	= 5,
1852c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.vidtcon	= VIDTCON0,
1853c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.wincon		= WINCON(0),
1854c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.winmap		= WINxMAP(0),
1855c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.keycon		= WKEYCON,
1856c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.osd		= VIDOSD_BASE,
1857c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.osd_stride	= 16,
1858c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_start	= VIDW_BUF_START(0),
1859c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_size	= VIDW_BUF_SIZE(0),
1860c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_end	= VIDW_BUF_END(0),
186150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
186250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette = {
186350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[0] = 0x2400,
186450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[1] = 0x2800,
186550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[2] = 0x2c00,
186650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[3] = 0x3000,
186750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[4] = 0x3400,
186850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		},
1869f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak
1870f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		.has_shadowcon	= 1,
1871f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han		.has_blendcon	= 1,
1872b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.has_clksel	= 1,
1873d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han		.has_fixvclk	= 1,
1874b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	},
1875b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	.win[0]	= &s3c_fb_data_s5p_wins[0],
1876b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	.win[1]	= &s3c_fb_data_s5p_wins[1],
1877b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	.win[2]	= &s3c_fb_data_s5p_wins[2],
1878b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	.win[3]	= &s3c_fb_data_s5p_wins[3],
1879b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	.win[4]	= &s3c_fb_data_s5p_wins[4],
1880b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han};
1881b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
1882b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Hanstatic struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
1883b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	.variant = {
1884b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.nr_windows	= 5,
1885b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.vidtcon	= VIDTCON0,
1886b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.wincon		= WINCON(0),
1887b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.winmap		= WINxMAP(0),
1888b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.keycon		= WKEYCON,
1889b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.osd		= VIDOSD_BASE,
1890b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.osd_stride	= 16,
1891b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.buf_start	= VIDW_BUF_START(0),
1892b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.buf_size	= VIDW_BUF_SIZE(0),
1893b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.buf_end	= VIDW_BUF_END(0),
1894b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
1895b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.palette = {
1896b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			[0] = 0x2400,
1897b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			[1] = 0x2800,
1898b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			[2] = 0x2c00,
1899b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			[3] = 0x3000,
1900b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			[4] = 0x3400,
1901b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		},
1902b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
1903b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.has_shadowcon	= 1,
1904f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han		.has_blendcon	= 1,
1905d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han		.has_fixvclk	= 1,
190650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
1907af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[0]	= &s3c_fb_data_s5p_wins[0],
1908af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[1]	= &s3c_fb_data_s5p_wins[1],
1909af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[2]	= &s3c_fb_data_s5p_wins[2],
1910af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[3]	= &s3c_fb_data_s5p_wins[3],
1911af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[4]	= &s3c_fb_data_s5p_wins[4],
191250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
191350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
19145c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Hanstatic struct s3c_fb_driverdata s3c_fb_data_exynos5 = {
19155c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	.variant = {
19165c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.nr_windows	= 5,
19175c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.vidtcon	= VIDTCON0,
19185c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.wincon		= WINCON(0),
19195c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.winmap		= WINxMAP(0),
19205c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.keycon		= WKEYCON,
19215c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.osd		= VIDOSD_BASE,
19225c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.osd_stride	= 16,
19235c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.buf_start	= VIDW_BUF_START(0),
19245c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.buf_size	= VIDW_BUF_SIZE(0),
19255c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.buf_end	= VIDW_BUF_END(0),
19265c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han
19275c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.palette = {
19285c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han			[0] = 0x2400,
19295c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han			[1] = 0x2800,
19305c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han			[2] = 0x2c00,
19315c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han			[3] = 0x3000,
19325c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han			[4] = 0x3400,
19335c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		},
19345c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.has_shadowcon	= 1,
19355c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.has_blendcon	= 1,
19365c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.has_fixvclk	= 1,
19375c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	},
19385c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	.win[0]	= &s3c_fb_data_s5p_wins[0],
19395c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	.win[1]	= &s3c_fb_data_s5p_wins[1],
19405c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	.win[2]	= &s3c_fb_data_s5p_wins[2],
19415c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	.win[3]	= &s3c_fb_data_s5p_wins[3],
19425c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	.win[4]	= &s3c_fb_data_s5p_wins[4],
19435c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han};
19445c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han
1945c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks/* S3C2443/S3C2416 style hardware */
19468cfdcb2393b05cc80f89ed0110c0f90423d2fee1Marek Szyprowskistatic struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
1947c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	.variant = {
1948c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.nr_windows	= 2,
1949c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.is_2443	= 1,
1950c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
1951c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.vidtcon	= 0x08,
1952c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.wincon		= 0x14,
1953c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.winmap		= 0xd0,
1954c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.keycon		= 0xb0,
1955c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.osd		= 0x28,
1956c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.osd_stride	= 12,
1957c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_start	= 0x64,
1958c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_size	= 0x94,
1959c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_end	= 0x7c,
1960c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
1961c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.palette = {
1962c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks			[0] = 0x400,
1963c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks			[1] = 0x800,
1964c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		},
1965b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.has_clksel	= 1,
1966c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	},
1967c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	.win[0] = &(struct s3c_fb_win_variant) {
1968c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.palette_sz	= 256,
1969c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.valid_bpp	= VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24),
1970c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	},
1971c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	.win[1] = &(struct s3c_fb_win_variant) {
1972c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.has_osd_c	= 1,
1973f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		.has_osd_alpha	= 1,
1974c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.palette_sz	= 256,
1975c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
1976c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks				   VALID_BPP(18) | VALID_BPP(19) |
1977c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks				   VALID_BPP(24) | VALID_BPP(25) |
1978c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks				   VALID_BPP(28)),
1979c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	},
1980c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks};
1981c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
198221b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumarstatic struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = {
198321b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar	.variant = {
198421b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.nr_windows	= 3,
198521b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.vidtcon	= VIDTCON0,
198621b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.wincon		= WINCON(0),
198721b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.winmap		= WINxMAP(0),
198821b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.keycon		= WKEYCON,
198921b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.osd		= VIDOSD_BASE,
199021b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.osd_stride	= 16,
199121b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.buf_start	= VIDW_BUF_START(0),
199221b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.buf_size	= VIDW_BUF_SIZE(0),
199321b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.buf_end	= VIDW_BUF_END(0),
199421b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar
199521b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.palette = {
199621b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar			[0] = 0x2400,
199721b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar			[1] = 0x2800,
199821b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar			[2] = 0x2c00,
199921b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		},
2000f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han
2001f7f31e505aa79d91b979a38789b1608744361bdcJingoo Han		.has_blendcon	= 1,
2002d8b97db4c8e40e49985fa5802be914292add64f6Jingoo Han		.has_fixvclk	= 1,
200321b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar	},
200421b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar	.win[0] = &s3c_fb_data_s5p_wins[0],
200521b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar	.win[1] = &s3c_fb_data_s5p_wins[1],
200621b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar	.win[2] = &s3c_fb_data_s5p_wins[2],
200721b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar};
200821b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar
200950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstatic struct platform_device_id s3c_fb_driver_ids[] = {
201050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	{
201150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.name		= "s3c-fb",
201250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.driver_data	= (unsigned long)&s3c_fb_data_64xx,
201350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	}, {
20144e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.name		= "s5pc100-fb",
20154e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.driver_data	= (unsigned long)&s3c_fb_data_s5pc100,
20164e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak	}, {
20174e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.name		= "s5pv210-fb",
20184e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.driver_data	= (unsigned long)&s3c_fb_data_s5pv210,
2019c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	}, {
2020b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.name		= "exynos4-fb",
2021b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.driver_data	= (unsigned long)&s3c_fb_data_exynos4,
2022b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	}, {
20235c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.name		= "exynos5-fb",
20245c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han		.driver_data	= (unsigned long)&s3c_fb_data_exynos5,
20255c44778eb0b8928aabfe039ba6f11ca88be6d650Jingoo Han	}, {
2026c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.name		= "s3c2443-fb",
2027c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.driver_data	= (unsigned long)&s3c_fb_data_s3c2443,
202821b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar	}, {
202921b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.name		= "s5p64x0-fb",
203021b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.driver_data	= (unsigned long)&s3c_fb_data_s5p64x0,
203150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
203250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	{},
203350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
203450a5503a9208420e6c59d24504a5e9913d603cf7Ben DooksMODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
203550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
2036f4f514734e3d398cfb70827615f129826ff84b06Mark Brownstatic const struct dev_pm_ops s3cfb_pm_ops = {
2037f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume)
2038f4f514734e3d398cfb70827615f129826ff84b06Mark Brown	SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume,
2039f4f514734e3d398cfb70827615f129826ff84b06Mark Brown			   NULL)
2040f4f514734e3d398cfb70827615f129826ff84b06Mark Brown};
20414959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
2042ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic struct platform_driver s3c_fb_driver = {
2043ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.probe		= s3c_fb_probe,
20443163eaba34943967aebb1eefa0d4bdc4e5dc197cPeter Korsgaard	.remove		= __devexit_p(s3c_fb_remove),
204550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.id_table	= s3c_fb_driver_ids,
2046ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.driver		= {
2047ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		.name	= "s3c-fb",
2048ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		.owner	= THIS_MODULE,
2049fe05f8b1c3d28e6204a9ec54dec0d68af6cbf4c8Mark Brown		.pm	= &s3cfb_pm_ops,
2050ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	},
2051ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks};
2052ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
20534277f2c4667187cbbdd3da3be31ee681bc6b8300Axel Linmodule_platform_driver(s3c_fb_driver);
2054ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
2055ec549a0fdc32171b26677f1ef0b5309faa743362Ben DooksMODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
2056ec549a0fdc32171b26677f1ef0b5309faa743362Ben DooksMODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver");
2057ec549a0fdc32171b26677f1ef0b5309faa743362Ben DooksMODULE_LICENSE("GPL");
2058ec549a0fdc32171b26677f1ef0b5309faa743362Ben DooksMODULE_ALIAS("platform:s3c-fb");
2059