s3c-fb.c revision ff8c91072389491375f6d1ea86ce55942c460a04
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); \
51b73a21fc66fee35b41db755abebfacba48b2fc76Jingoo Han	__raw_writel(v, r); } while (0)
52ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#endif /* FB_S3C_DEBUG_REGWRITE */
53ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
54efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak/* irq_flags bits */
55efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak#define S3C_FB_VSYNC_IRQ_EN	0
56efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
57efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak#define VSYNC_TIMEOUT_MSEC 50
58efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
59ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstruct s3c_fb;
60ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
6150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks#define VALID_BPP(x) (1 << ((x) - 1))
6250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
63c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define OSD_BASE(win, variant) ((variant).osd + ((win) * (variant).osd_stride))
64c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define VIDOSD_A(win, variant) (OSD_BASE(win, variant) + 0x00)
65c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define VIDOSD_B(win, variant) (OSD_BASE(win, variant) + 0x04)
66c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define VIDOSD_C(win, variant) (OSD_BASE(win, variant) + 0x08)
67c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define VIDOSD_D(win, variant) (OSD_BASE(win, variant) + 0x0C)
68c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
6950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks/**
7050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * struct s3c_fb_variant - fb variant information
71c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @is_2443: Set if S3C2443/S3C2416 style hardware.
7250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @nr_windows: The number of windows.
73c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @vidtcon: The base for the VIDTCONx registers
74c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @wincon: The base for the WINxCON registers.
75c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @winmap: The base for the WINxMAP registers.
76c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @keycon: The abse for the WxKEYCON registers.
77c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @buf_start: Offset of buffer start registers.
78c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @buf_size: Offset of buffer size registers.
79c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @buf_end: Offset of buffer end registers.
80c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @osd: The base for the OSD registers.
8150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @palette: Address of palette memory, or 0 if none.
82067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * @has_prtcon: Set if has PRTCON register.
83f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak * @has_shadowcon: Set if has SHADOWCON register.
84b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han * @has_clksel: Set if VIDCON0 register has CLKSEL bit.
8550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks */
8650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstruct s3c_fb_variant {
87c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned int	is_2443:1;
8850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	unsigned short	nr_windows;
89c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	vidtcon;
90c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	wincon;
91c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	winmap;
92c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	keycon;
93c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	buf_start;
94c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	buf_end;
95c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	buf_size;
96c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	osd;
97c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	unsigned short	osd_stride;
9850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	unsigned short	palette[S3C_FB_MAX_WIN];
99067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
100067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	unsigned int	has_prtcon:1;
101f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	unsigned int	has_shadowcon:1;
102b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	unsigned int	has_clksel:1;
10350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
10450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
10550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks/**
10650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * struct s3c_fb_win_variant
10750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @has_osd_c: Set if has OSD C register.
10850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @has_osd_d: Set if has OSD D register.
109f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * @has_osd_alpha: Set if can change alpha transparency for a window.
11050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @palette_sz: Size of palette in entries.
11150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @palette_16bpp: Set if palette is 16bits wide.
112f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * @osd_size_off: If != 0, supports setting up OSD for a window; the appropriate
113f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak *                register is located at the given offset from OSD_BASE.
11450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @valid_bpp: 1 bit per BPP setting to show valid bits-per-pixel.
11550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks *
11650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * valid_bpp bit x is set if (x+1)BPP is supported.
11750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks */
11850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstruct s3c_fb_win_variant {
11950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	unsigned int	has_osd_c:1;
12050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	unsigned int	has_osd_d:1;
121f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	unsigned int	has_osd_alpha:1;
12250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	unsigned int	palette_16bpp:1;
123f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	unsigned short	osd_size_off;
12450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	unsigned short	palette_sz;
12550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	u32		valid_bpp;
12650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
12750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
12850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks/**
12950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * struct s3c_fb_driverdata - per-device type driver data for init time.
13050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @variant: The variant information for this driver.
13150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @win: The window information for each window.
13250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks */
13350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstruct s3c_fb_driverdata {
13450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	struct s3c_fb_variant	variant;
13550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	struct s3c_fb_win_variant *win[S3C_FB_MAX_WIN];
13650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
13750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
138ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
139bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * struct s3c_fb_palette - palette information
140bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * @r: Red bitfield.
141bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * @g: Green bitfield.
142bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * @b: Blue bitfield.
143bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * @a: Alpha bitfield.
144bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks */
145bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooksstruct s3c_fb_palette {
146bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	struct fb_bitfield	r;
147bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	struct fb_bitfield	g;
148bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	struct fb_bitfield	b;
149bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	struct fb_bitfield	a;
150bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks};
151bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks
152bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks/**
153ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * struct s3c_fb_win - per window private data for each framebuffer.
154ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @windata: The platform data supplied for the window configuration.
155ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @parent: The hardware that this window is part of.
156ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @fbinfo: Pointer pack to the framebuffer info for this window.
15750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @varint: The variant information for this window.
158ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @palette_buffer: Buffer/cache to hold palette entries.
159ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/
160ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @index: The window number of this window.
161ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @palette: The bitfields for changing r/g/b into a hardware palette entry.
162ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
163ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstruct s3c_fb_win {
164ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_pd_win	*windata;
165ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb		*parent;
166ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_info		*fbinfo;
167ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_palette	 palette;
16850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	struct s3c_fb_win_variant variant;
169ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
170ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32			*palette_buffer;
171ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32			 pseudo_palette[16];
172ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	unsigned int		 index;
173ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks};
174ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
175ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
176efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * struct s3c_fb_vsync - vsync information
177efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @wait:	a queue for processes waiting for vsync
178efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @count:	vsync interrupt count
179efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak */
180efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakstruct s3c_fb_vsync {
181efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	wait_queue_head_t	wait;
182efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	unsigned int		count;
183efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak};
184efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
185efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak/**
186ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * struct s3c_fb - overall hardware state of the hardware
187b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han * @slock: The spinlock protection for this data sturcture.
188ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @dev: The device that we bound to, for printing, etc.
189ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @regs_res: The resource we claimed for the IO registers.
190ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
191b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han * @lcd_clk: The clk (sclk) feeding pixclk.
192ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @regs: The mapped hardware registers.
19350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @variant: Variant information for this hardware.
194ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @enabled: A bitmask of enabled hardware windows.
195ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pdata: The platform configuration data passed with the device.
196ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @windows: The hardware windows that have been claimed.
197efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @irq_no: IRQ line number
198efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @irq_flags: irq flags
199efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @vsync_info: VSYNC-related information (count, queues...)
200ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
201ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstruct s3c_fb {
202b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han	spinlock_t		slock;
203ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct device		*dev;
204ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct resource		*regs_res;
205ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct clk		*bus_clk;
206b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	struct clk		*lcd_clk;
207ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	void __iomem		*regs;
20850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	struct s3c_fb_variant	 variant;
209ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
210ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	unsigned char		 enabled;
211ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
212ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_platdata	*pdata;
213ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_win	*windows[S3C_FB_MAX_WIN];
214efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
215efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	int			 irq_no;
216efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	unsigned long		 irq_flags;
217efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	struct s3c_fb_vsync	 vsync_info;
218ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks};
219ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
220ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
22150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * s3c_fb_validate_win_bpp - validate the bits-per-pixel for this mode.
22250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @win: The device window.
22350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @bpp: The bit depth.
224ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
22550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstatic bool s3c_fb_validate_win_bpp(struct s3c_fb_win *win, unsigned int bpp)
226ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
22750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	return win->variant.valid_bpp & VALID_BPP(bpp);
228ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
229ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
230ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
231ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_check_var() - framebuffer layer request to verify a given mode.
232ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @var: The screen information to verify.
233ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @info: The framebuffer device.
234ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
235ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Framebuffer layer call to verify the given information and allow us to
236ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * update various information depending on the hardware capabilities.
237ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
238ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_check_var(struct fb_var_screeninfo *var,
239ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			    struct fb_info *info)
240ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
241ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_win *win = info->par;
242ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb *sfb = win->parent;
243ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
244ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "checking parameters\n");
245ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
24613e6af8886f3225fb9141dc3b6915d84bd4ad4deJingoo Han	var->xres_virtual = max(var->xres_virtual, var->xres);
24713e6af8886f3225fb9141dc3b6915d84bd4ad4deJingoo Han	var->yres_virtual = max(var->yres_virtual, var->yres);
248ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
24950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) {
250ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n",
251ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			win->index, var->bits_per_pixel);
252ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return -EINVAL;
253ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
254ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
255ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* always ensure these are zero, for drop through cases below */
256ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	var->transp.offset = 0;
257ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	var->transp.length = 0;
258ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
259ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	switch (var->bits_per_pixel) {
260ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 1:
261ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 2:
262ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 4:
263ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 8:
26450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		if (sfb->variant.palette[win->index] != 0) {
265ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			/* non palletised, A:1,R:2,G:3,B:2 mode */
266ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->red.offset		= 4;
267ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->green.offset	= 2;
268ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->blue.offset	= 0;
269ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->red.length		= 5;
270ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->green.length	= 3;
271ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->blue.length	= 2;
272ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->transp.offset	= 7;
273ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->transp.length	= 1;
274ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		} else {
275ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->red.offset	= 0;
276ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->red.length	= var->bits_per_pixel;
277ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->green	= var->red;
278ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			var->blue	= var->red;
279ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		}
280ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
281ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
282ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 19:
283ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* 666 with one bit alpha/transparency */
284ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->transp.offset	= 18;
285ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->transp.length	= 1;
286ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 18:
287ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->bits_per_pixel	= 32;
288ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
289ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* 666 format */
290ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->red.offset		= 12;
291ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->green.offset	= 6;
292ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->blue.offset	= 0;
293ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->red.length		= 6;
294ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->green.length	= 6;
295ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->blue.length	= 6;
296ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
297ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
298ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 16:
299ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* 16 bpp, 565 format */
300ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->red.offset		= 11;
301ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->green.offset	= 5;
302ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->blue.offset	= 0;
303ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->red.length		= 5;
304ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->green.length	= 6;
305ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->blue.length	= 5;
306ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
307ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
308af1ce6b2fad7d572aef040d61a935da28a861853Jingoo Han	case 32:
309ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 28:
310ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 25:
311ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->transp.length	= var->bits_per_pixel - 24;
312ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->transp.offset	= 24;
313ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* drop through */
314ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 24:
315ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* our 24bpp is unpacked, so 32bpp */
316ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->bits_per_pixel	= 32;
317ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->red.offset		= 16;
318ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->red.length		= 8;
319ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->green.offset	= 8;
320ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->green.length	= 8;
321ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->blue.offset	= 0;
322ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		var->blue.length	= 8;
323ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
324ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
325ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	default:
326ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(sfb->dev, "invalid bpp\n");
327ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
328ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
329ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "%s: verified parameters\n", __func__);
330ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
331ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
332ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
333ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
334ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock.
335ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The hardware state.
336ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pixclock: The pixel clock wanted, in picoseconds.
337ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
338ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Given the specified pixel clock, work out the necessary divider to get
339ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * close to the output frequency.
340ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
341eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brownstatic int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
342ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
343b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	unsigned long clk;
344eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown	unsigned long long tmp;
345ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	unsigned int result;
346ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
347b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	if (sfb->variant.has_clksel)
348b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk = clk_get_rate(sfb->bus_clk);
349b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	else
350b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk = clk_get_rate(sfb->lcd_clk);
351b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
352eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown	tmp = (unsigned long long)clk;
353eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown	tmp *= pixclk;
354eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown
355eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown	do_div(tmp, 1000000000UL);
356eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown	result = (unsigned int)tmp / 1000;
357ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
358ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n",
359ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		pixclk, clk, result, clk / result);
360ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
361ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return result;
362ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
363ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
364ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
365ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_align_word() - align pixel count to word boundary
366ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @bpp: The number of bits per pixel
367ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pix: The value to be aligned.
368ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
369ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Align the given pixel count so that it will start on an 32bit word
370ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * boundary.
371ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
372ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_align_word(unsigned int bpp, unsigned int pix)
373ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
374ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int pix_per_word;
375ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
376ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (bpp > 16)
377ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return pix;
378ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
379ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	pix_per_word = (8 * 32) / bpp;
380ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return ALIGN(pix, pix_per_word);
381ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
382ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
383ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
384f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * vidosd_set_size() - set OSD size for a window
385f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak *
386f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * @win: the window to set OSD size for
387f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * @size: OSD size register value
388f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak */
389f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciakstatic void vidosd_set_size(struct s3c_fb_win *win, u32 size)
390f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak{
391f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	struct s3c_fb *sfb = win->parent;
392f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak
393f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	/* OSD can be set up if osd_size_off != 0 for this window */
394f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	if (win->variant.osd_size_off)
395f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		writel(size, sfb->regs + OSD_BASE(win->index, sfb->variant)
396f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak				+ win->variant.osd_size_off);
397f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak}
398f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak
399f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak/**
400f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * vidosd_set_alpha() - set alpha transparency for a window
401f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak *
402f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * @win: the window to set OSD size for
403f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak * @alpha: alpha register value
404f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak */
405f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciakstatic void vidosd_set_alpha(struct s3c_fb_win *win, u32 alpha)
406f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak{
407f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	struct s3c_fb *sfb = win->parent;
408f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak
409f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	if (win->variant.has_osd_alpha)
410f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		writel(alpha, sfb->regs + VIDOSD_C(win->index, sfb->variant));
411f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak}
412f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak
413f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak/**
414f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak * shadow_protect_win() - disable updating values from shadow registers at vsync
415f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak *
416f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak * @win: window to protect registers for
417f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak * @protect: 1 to protect (disable updates)
418f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak */
419f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciakstatic void shadow_protect_win(struct s3c_fb_win *win, bool protect)
420f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak{
421f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	struct s3c_fb *sfb = win->parent;
422f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	u32 reg;
423f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak
424f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	if (protect) {
425f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		if (sfb->variant.has_prtcon) {
426f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak			writel(PRTCON_PROTECT, sfb->regs + PRTCON);
427f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		} else if (sfb->variant.has_shadowcon) {
428f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak			reg = readl(sfb->regs + SHADOWCON);
429f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak			writel(reg | SHADOWCON_WINx_PROTECT(win->index),
430f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak				sfb->regs + SHADOWCON);
431f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		}
432f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	} else {
433f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		if (sfb->variant.has_prtcon) {
434f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak			writel(0, sfb->regs + PRTCON);
435f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		} else if (sfb->variant.has_shadowcon) {
436f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak			reg = readl(sfb->regs + SHADOWCON);
437f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak			writel(reg & ~SHADOWCON_WINx_PROTECT(win->index),
438f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak				sfb->regs + SHADOWCON);
439f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		}
440f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	}
441f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak}
442f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak
443f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak/**
444ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_set_par() - framebuffer request to set new framebuffer state.
445ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @info: The framebuffer to change.
446ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
447ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Framebuffer layer request to set a new mode for the specified framebuffer
448ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
449ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_set_par(struct fb_info *info)
450ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
451ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_var_screeninfo *var = &info->var;
452ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_win *win = info->par;
453ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb *sfb = win->parent;
454ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	void __iomem *regs = sfb->regs;
455c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	void __iomem *buf = regs;
456ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int win_no = win->index;
457f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	u32 alpha = 0;
458ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32 data;
459ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32 pagewidth;
460ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int clkdiv;
461ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
462ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "setting framebuffer parameters\n");
463ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
464a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak	shadow_protect_win(win, 1);
465a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak
466ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	switch (var->bits_per_pixel) {
467ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 32:
468ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 24:
469ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 16:
470ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 12:
471ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		info->fix.visual = FB_VISUAL_TRUECOLOR;
472ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
473ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 8:
47450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		if (win->variant.palette_sz >= 256)
475ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
476ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		else
477ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			info->fix.visual = FB_VISUAL_TRUECOLOR;
478ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
479ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 1:
480ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		info->fix.visual = FB_VISUAL_MONO01;
481ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
482ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	default:
483ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
484ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
485ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
486ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
487ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
488ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
489067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
490067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
491067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
492ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* disable the window whilst we update it */
493ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	writel(0, regs + WINCON(win_no));
494ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
495ad04490a171915737c9b99d2fa5cb813830f24c1InKi Dae	/* use platform specified window as the basis for the lcd timings */
496ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
497ad04490a171915737c9b99d2fa5cb813830f24c1InKi Dae	if (win_no == sfb->pdata->default_win) {
498eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown		clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock);
499ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
500ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data = sfb->pdata->vidcon0;
501ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
502ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
503ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (clkdiv > 1)
504ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR;
505ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		else
506ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data &= ~VIDCON0_CLKDIR;	/* 1:1 clock */
507ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
508ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* write the timing data to the panel */
509ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
510c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		if (sfb->variant.is_2443)
511c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks			data |= (1 << 5);
512c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
513ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= VIDCON0_ENVID | VIDCON0_ENVID_F;
514ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		writel(data, regs + VIDCON0);
515ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
516ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data = VIDTCON0_VBPD(var->upper_margin - 1) |
517ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		       VIDTCON0_VFPD(var->lower_margin - 1) |
518ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		       VIDTCON0_VSPW(var->vsync_len - 1);
519ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
520c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(data, regs + sfb->variant.vidtcon);
521ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
522ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data = VIDTCON1_HBPD(var->left_margin - 1) |
523ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		       VIDTCON1_HFPD(var->right_margin - 1) |
524ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		       VIDTCON1_HSPW(var->hsync_len - 1);
525ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
526c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		/* VIDTCON1 */
527c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(data, regs + sfb->variant.vidtcon + 4);
528ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
529ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data = VIDTCON2_LINEVAL(var->yres - 1) |
530ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		       VIDTCON2_HOZVAL(var->xres - 1);
531b73a21fc66fee35b41db755abebfacba48b2fc76Jingoo Han		writel(data, regs + sfb->variant.vidtcon + 8);
532ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
533ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
534ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* write the buffer address */
535ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
536c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	/* start and end registers stride is 8 */
537c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	buf = regs + win_no * 8;
538c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
539c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(info->fix.smem_start, buf + sfb->variant.buf_start);
540ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
541ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	data = info->fix.smem_start + info->fix.line_length * var->yres;
542c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(data, buf + sfb->variant.buf_end);
543ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
544ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	pagewidth = (var->xres * var->bits_per_pixel) >> 3;
545ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) |
546ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	       VIDW_BUF_SIZE_PAGEWIDTH(pagewidth);
547c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(data, regs + sfb->variant.buf_size + (win_no * 4));
548ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
549ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* write 'OSD' registers to control position of framebuffer */
550ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
551ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0);
552c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(data, regs + VIDOSD_A(win_no, sfb->variant));
553ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
554ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel,
555ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks						     var->xres - 1)) |
556ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	       VIDOSDxB_BOTRIGHT_Y(var->yres - 1);
557ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
558c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(data, regs + VIDOSD_B(win_no, sfb->variant));
559ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
560ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	data = var->xres * var->yres;
56139000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae
562f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	alpha = VIDISD14C_ALPHA1_R(0xf) |
56339000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae		VIDISD14C_ALPHA1_G(0xf) |
56439000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae		VIDISD14C_ALPHA1_B(0xf);
56539000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae
566f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	vidosd_set_alpha(win, alpha);
567f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak	vidosd_set_size(win, data);
568ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
569fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han	/* Enable DMA channel for this window */
570fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han	if (sfb->variant.has_shadowcon) {
571fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han		data = readl(sfb->regs + SHADOWCON);
572fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han		data |= SHADOWCON_CHx_ENABLE(win_no);
573fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han		writel(data, sfb->regs + SHADOWCON);
574fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han	}
575fab7c5b778b1e0ee89e75679b2d6a1405318bb11Jingoo Han
576ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	data = WINCONx_ENWIN;
5772d9ae7ac48c91e15e693038bf0dff004f7872aafJingoo Han	sfb->enabled |= (1 << win->index);
578ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
579ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* note, since we have to round up the bits-per-pixel, we end up
580ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * relying on the bitfield information for r/g/b/a to work out
581ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * exactly which mode of operation is intended. */
582ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
583ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	switch (var->bits_per_pixel) {
584ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 1:
585ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCON0_BPPMODE_1BPP;
586ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BITSWP;
587ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BURSTLEN_4WORD;
588ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
589ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 2:
590ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCON0_BPPMODE_2BPP;
591ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BITSWP;
592ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BURSTLEN_8WORD;
593ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
594ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 4:
595ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCON0_BPPMODE_4BPP;
596ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BITSWP;
597ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BURSTLEN_8WORD;
598ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
599ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 8:
600ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (var->transp.length != 0)
601ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data |= WINCON1_BPPMODE_8BPP_1232;
602ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		else
603ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data |= WINCON0_BPPMODE_8BPP_PALETTE;
604ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BURSTLEN_8WORD;
605ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BYTSWP;
606ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
607ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 16:
608ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (var->transp.length != 0)
609ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data |= WINCON1_BPPMODE_16BPP_A1555;
610ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		else
611ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data |= WINCON0_BPPMODE_16BPP_565;
612ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_HAWSWP;
613ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BURSTLEN_16WORD;
614ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
615ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 24:
616ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case 32:
617ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (var->red.length == 6) {
618ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			if (var->transp.length != 0)
619ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				data |= WINCON1_BPPMODE_19BPP_A1666;
620ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			else
621ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				data |= WINCON1_BPPMODE_18BPP_666;
62239000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae		} else if (var->transp.length == 1)
62339000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae			data |= WINCON1_BPPMODE_25BPP_A1888
62439000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae				| WINCON1_BLD_PIX;
6254420dd2b306f1997232a13462bca0d420be5b1b8Jingoo Han		else if ((var->transp.length == 4) ||
6264420dd2b306f1997232a13462bca0d420be5b1b8Jingoo Han			(var->transp.length == 8))
62739000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae			data |= WINCON1_BPPMODE_28BPP_A4888
62839000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae				| WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
629ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		else
630ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			data |= WINCON0_BPPMODE_24BPP_888;
631ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
632dc8498c00f6a41a28f01111a3d2ed9f179356a71InKi Dae		data |= WINCONx_WSWP;
633ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		data |= WINCONx_BURSTLEN_16WORD;
634ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
635ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
636ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
637c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	/* Enable the colour keying for the window below this one */
63839000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae	if (win_no > 0) {
63939000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae		u32 keycon0_data = 0, keycon1_data = 0;
640c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		void __iomem *keycon = regs + sfb->variant.keycon;
64139000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae
64239000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae		keycon0_data = ~(WxKEYCON0_KEYBL_EN |
64339000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae				WxKEYCON0_KEYEN_F |
64439000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae				WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
64539000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae
64639000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae		keycon1_data = WxKEYCON1_COLVAL(0xffffff);
64739000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae
648c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		keycon += (win_no - 1) * 8;
649c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
650c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(keycon0_data, keycon + WKEYCON0);
651c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(keycon1_data, keycon + WKEYCON1);
65239000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae	}
65339000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae
654c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(data, regs + sfb->variant.wincon + (win_no * 4));
655c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(0x0, regs + sfb->variant.winmap + (win_no * 4));
656ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
657a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak	shadow_protect_win(win, 0);
658a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak
659ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
660ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
661ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
662ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
663ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_update_palette() - set or schedule a palette update.
664ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The hardware information.
665ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window being updated.
666ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @reg: The palette index being changed.
667ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @value: The computed palette value.
668ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
669ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Change the value of a palette register, either by directly writing to
670ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * the palette (this requires the palette RAM to be disconnected from the
671ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * hardware whilst this is in progress) or schedule the update for later.
672ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
673ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * At the moment, since we have no VSYNC interrupt support, we simply set
674ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * the palette entry directly.
675ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
676ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_update_palette(struct s3c_fb *sfb,
677ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				  struct s3c_fb_win *win,
678ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				  unsigned int reg,
679ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				  u32 value)
680ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
681ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	void __iomem *palreg;
682ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32 palcon;
683ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
68450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	palreg = sfb->regs + sfb->variant.palette[win->index];
685ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
686ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n",
687ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		__func__, win->index, reg, palreg, value);
688ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
689ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win->palette_buffer[reg] = value;
690ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
691ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	palcon = readl(sfb->regs + WPALCON);
692ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON);
693ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
69450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	if (win->variant.palette_16bpp)
69550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		writew(value, palreg + (reg * 2));
696ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	else
69750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		writel(value, palreg + (reg * 4));
698ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
699ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	writel(palcon, sfb->regs + WPALCON);
700ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
701ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
702ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic inline unsigned int chan_to_field(unsigned int chan,
703ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks					 struct fb_bitfield *bf)
704ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
705ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	chan &= 0xffff;
706ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	chan >>= 16 - bf->length;
707ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return chan << bf->offset;
708ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
709ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
710ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
711ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_setcolreg() - framebuffer layer request to change palette.
712ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @regno: The palette index to change.
713ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @red: The red field for the palette data.
714ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @green: The green field for the palette data.
715ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @blue: The blue field for the palette data.
716ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @trans: The transparency (alpha) field for the palette data.
717ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @info: The framebuffer being changed.
718ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
719ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_setcolreg(unsigned regno,
720ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			    unsigned red, unsigned green, unsigned blue,
721ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			    unsigned transp, struct fb_info *info)
722ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
723ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_win *win = info->par;
724ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb *sfb = win->parent;
725ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	unsigned int val;
726ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
727ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n",
728ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		__func__, win->index, regno, red, green, blue);
729ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
730ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	switch (info->fix.visual) {
731ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_VISUAL_TRUECOLOR:
732ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* true-colour, use pseudo-palette */
733ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
734ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (regno < 16) {
735ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			u32 *pal = info->pseudo_palette;
736ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
737ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			val  = chan_to_field(red,   &info->var.red);
738ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			val |= chan_to_field(green, &info->var.green);
739ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			val |= chan_to_field(blue,  &info->var.blue);
740ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
741ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			pal[regno] = val;
742ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		}
743ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
744ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
745ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_VISUAL_PSEUDOCOLOR:
74650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		if (regno < win->variant.palette_sz) {
747ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			val  = chan_to_field(red, &win->palette.r);
748ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			val |= chan_to_field(green, &win->palette.g);
749ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			val |= chan_to_field(blue, &win->palette.b);
750ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
751ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			s3c_fb_update_palette(sfb, win, regno, val);
752ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		}
753ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
754ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
755ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
756ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	default:
757ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return 1;	/* unknown type */
758ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
759ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
760ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
761ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
762ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
763ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
764ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_enable() - Set the state of the main LCD output
765ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The main framebuffer state.
766ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @enable: The state to set.
767ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
768ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_enable(struct s3c_fb *sfb, int enable)
769ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
770ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32 vidcon0 = readl(sfb->regs + VIDCON0);
771ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
772ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (enable)
773ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
774ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	else {
775ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* see the note in the framebuffer datasheet about
776ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		 * why you cannot take both of these bits down at the
777ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		 * same time. */
778ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
779ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (!(vidcon0 & VIDCON0_ENVID))
780ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			return;
781ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
782ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		vidcon0 |= VIDCON0_ENVID;
783ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		vidcon0 &= ~VIDCON0_ENVID_F;
784ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
785ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
786ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	writel(vidcon0, sfb->regs + VIDCON0);
787ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
788ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
789ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
790ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_blank() - blank or unblank the given window
791ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @blank_mode: The blank state from FB_BLANK_*
792ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @info: The framebuffer to blank.
793ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
794ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Framebuffer layer request to change the power state.
795ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
796ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_blank(int blank_mode, struct fb_info *info)
797ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
798ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_win *win = info->par;
799ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb *sfb = win->parent;
800ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	unsigned int index = win->index;
801ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	u32 wincon;
802ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
803ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
804ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
805c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4));
806ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
807ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	switch (blank_mode) {
808ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_BLANK_POWERDOWN:
809ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		wincon &= ~WINCONx_ENWIN;
810ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		sfb->enabled &= ~(1 << index);
811ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* fall through to FB_BLANK_NORMAL */
812ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
813ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_BLANK_NORMAL:
814ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		/* disable the DMA and display 0x0 (black) */
815ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 1);
816ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0),
817c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		       sfb->regs + sfb->variant.winmap + (index * 4));
818ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 0);
819ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
820ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
821ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_BLANK_UNBLANK:
822ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 1);
823c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4));
824ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 0);
825ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		wincon |= WINCONx_ENWIN;
826ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		sfb->enabled |= (1 << index);
827ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		break;
828ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
829ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_BLANK_VSYNC_SUSPEND:
830ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	case FB_BLANK_HSYNC_SUSPEND:
831ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	default:
832ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return 1;
833ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
834ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
835ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han	shadow_protect_win(win, 1);
836c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4));
837ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han	shadow_protect_win(win, 0);
838ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
839ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* Check the enabled state to see if we need to be running the
840ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * main LCD interface, as if there are no active windows then
841ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * it is highly likely that we also do not need to output
842ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * anything.
843ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 */
844ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
845ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* We could do something like the following code, but the current
846ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * system of using framebuffer events means that we cannot make
847ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * the distinction between just window 0 being inactive and all
848ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * the windows being down.
849ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 *
850ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * s3c_fb_enable(sfb, sfb->enabled ? 1 : 0);
851ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	*/
852ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
853ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* we're stuck with this until we can do something about overriding
854ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 * the power control using the blanking event for a single fb.
855ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	 */
856ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han	if (index == sfb->pdata->default_win) {
857ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 1);
858ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0);
859ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 0);
860ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han	}
861ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
862ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
863ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
864ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
865067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak/**
866067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * s3c_fb_pan_display() - Pan the display.
867067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak *
868067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * Note that the offsets can be written to the device at any time, as their
869067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * values are latched at each vsync automatically. This also means that only
870067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * the last call to this function will have any effect on next vsync, but
871067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * there is no need to sleep waiting for it to prevent tearing.
872067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak *
873067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * @var: The screen information to verify.
874067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak * @info: The framebuffer device.
875067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak */
876067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciakstatic int s3c_fb_pan_display(struct fb_var_screeninfo *var,
877067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			      struct fb_info *info)
878067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak{
879067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	struct s3c_fb_win *win	= info->par;
880067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	struct s3c_fb *sfb	= win->parent;
881067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	void __iomem *buf	= sfb->regs + win->index * 8;
882067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	unsigned int start_boff, end_boff;
883067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
884067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	/* Offset in bytes to the start of the displayed area */
885067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	start_boff = var->yoffset * info->fix.line_length;
886067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	/* X offset depends on the current bpp */
887067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	if (info->var.bits_per_pixel >= 8) {
888067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		start_boff += var->xoffset * (info->var.bits_per_pixel >> 3);
889067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	} else {
890067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		switch (info->var.bits_per_pixel) {
891067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		case 4:
892067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			start_boff += var->xoffset >> 1;
893067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			break;
894067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		case 2:
895067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			start_boff += var->xoffset >> 2;
896067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			break;
897067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		case 1:
898067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			start_boff += var->xoffset >> 3;
899067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			break;
900067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		default:
901067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			dev_err(sfb->dev, "invalid bpp\n");
902067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak			return -EINVAL;
903067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		}
904067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	}
905067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	/* Offset in bytes to the end of the displayed area */
906d8e7a74bf1f1c3d8235e1d939d3e1e96da94ed82Laurent Pinchart	end_boff = start_boff + info->var.yres * info->fix.line_length;
907067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
908067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	/* Temporarily turn off per-vsync update from shadow registers until
909067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	 * both start and end addresses are updated to prevent corruption */
910f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	shadow_protect_win(win, 1);
911067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
912067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	writel(info->fix.smem_start + start_boff, buf + sfb->variant.buf_start);
913067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	writel(info->fix.smem_start + end_boff, buf + sfb->variant.buf_end);
914067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
915f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak	shadow_protect_win(win, 0);
916067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
917067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	return 0;
918067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak}
919067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
920efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak/**
921efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * s3c_fb_enable_irq() - enable framebuffer interrupts
922efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @sfb: main hardware state
923efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak */
924efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakstatic void s3c_fb_enable_irq(struct s3c_fb *sfb)
925efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak{
926efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	void __iomem *regs = sfb->regs;
927efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	u32 irq_ctrl_reg;
928efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
929efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (!test_and_set_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
930efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		/* IRQ disabled, enable it */
931efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg = readl(regs + VIDINTCON0);
932efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
933efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg |= VIDINTCON0_INT_ENABLE;
934efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg |= VIDINTCON0_INT_FRAME;
935efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
936efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL0_MASK;
937efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg |= VIDINTCON0_FRAMESEL0_VSYNC;
938efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL1_MASK;
939efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg |= VIDINTCON0_FRAMESEL1_NONE;
940efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
941efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		writel(irq_ctrl_reg, regs + VIDINTCON0);
942efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	}
943efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak}
944efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
945efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak/**
946efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * s3c_fb_disable_irq() - disable framebuffer interrupts
947efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @sfb: main hardware state
948efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak */
949efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakstatic void s3c_fb_disable_irq(struct s3c_fb *sfb)
950efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak{
951efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	void __iomem *regs = sfb->regs;
952efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	u32 irq_ctrl_reg;
953efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
954efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (test_and_clear_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
955efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		/* IRQ enabled, disable it */
956efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg = readl(regs + VIDINTCON0);
957efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
958efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg &= ~VIDINTCON0_INT_FRAME;
959efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		irq_ctrl_reg &= ~VIDINTCON0_INT_ENABLE;
960efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
961efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		writel(irq_ctrl_reg, regs + VIDINTCON0);
962efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	}
963efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak}
964efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
965efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakstatic irqreturn_t s3c_fb_irq(int irq, void *dev_id)
966efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak{
967efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	struct s3c_fb *sfb = dev_id;
968efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	void __iomem  *regs = sfb->regs;
969efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	u32 irq_sts_reg;
970efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
971b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han	spin_lock(&sfb->slock);
972b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han
973efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	irq_sts_reg = readl(regs + VIDINTCON1);
974efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
975efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (irq_sts_reg & VIDINTCON1_INT_FRAME) {
976efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
977efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		/* VSYNC interrupt, accept it */
978efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		writel(VIDINTCON1_INT_FRAME, regs + VIDINTCON1);
979efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
980efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		sfb->vsync_info.count++;
981efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		wake_up_interruptible(&sfb->vsync_info.wait);
982efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	}
983efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
984efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	/* We only support waiting for VSYNC for now, so it's safe
985efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	 * to always disable irqs here.
986efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	 */
987efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	s3c_fb_disable_irq(sfb);
988efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
989b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han	spin_unlock(&sfb->slock);
990efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	return IRQ_HANDLED;
991efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak}
992efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
993efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak/**
994efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * s3c_fb_wait_for_vsync() - sleep until next VSYNC interrupt or timeout
995efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @sfb: main hardware state
996efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak * @crtc: head index.
997efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak */
998efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakstatic int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
999efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak{
1000efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	unsigned long count;
1001efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	int ret;
1002efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1003efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (crtc != 0)
1004efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		return -ENODEV;
1005efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1006efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	count = sfb->vsync_info.count;
1007efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	s3c_fb_enable_irq(sfb);
1008efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
1009efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak				       count != sfb->vsync_info.count,
1010efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak				       msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
1011efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (ret == 0)
1012efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		return -ETIMEDOUT;
1013efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1014efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	return 0;
1015efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak}
1016efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1017efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakstatic int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
1018efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak			unsigned long arg)
1019efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak{
1020efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	struct s3c_fb_win *win = info->par;
1021efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	struct s3c_fb *sfb = win->parent;
1022efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	int ret;
1023efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	u32 crtc;
1024efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1025efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	switch (cmd) {
1026efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	case FBIO_WAITFORVSYNC:
1027efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		if (get_user(crtc, (u32 __user *)arg)) {
1028efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak			ret = -EFAULT;
1029efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak			break;
1030efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		}
1031efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1032efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		ret = s3c_fb_wait_for_vsync(sfb, crtc);
1033efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		break;
1034efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	default:
1035efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		ret = -ENOTTY;
1036efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	}
1037efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1038efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	return ret;
1039efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak}
1040efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1041ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic struct fb_ops s3c_fb_ops = {
1042ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.owner		= THIS_MODULE,
1043ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_check_var	= s3c_fb_check_var,
1044ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_set_par	= s3c_fb_set_par,
1045ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_blank	= s3c_fb_blank,
1046ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_setcolreg	= s3c_fb_setcolreg,
1047ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_fillrect	= cfb_fillrect,
1048ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_copyarea	= cfb_copyarea,
1049ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.fb_imageblit	= cfb_imageblit,
1050067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak	.fb_pan_display	= s3c_fb_pan_display,
1051efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	.fb_ioctl	= s3c_fb_ioctl,
1052ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks};
1053ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1054ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
10552bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere * s3c_fb_missing_pixclock() - calculates pixel clock
10562bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere * @mode: The video mode to change.
10572bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere *
10582bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere * Calculate the pixel clock when none has been given through platform data.
10592bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere */
10602bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaerestatic void __devinit s3c_fb_missing_pixclock(struct fb_videomode *mode)
10612bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere{
10622bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	u64 pixclk = 1000000000000ULL;
10632bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	u32 div;
10642bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere
10652bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	div  = mode->left_margin + mode->hsync_len + mode->right_margin +
10662bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	       mode->xres;
10672bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	div *= mode->upper_margin + mode->vsync_len + mode->lower_margin +
10682bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	       mode->yres;
10692bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	div *= mode->refresh ? : 60;
10702bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere
10712bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	do_div(pixclk, div);
10722bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere
10732bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere	mode->pixclock = pixclk;
10742bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere}
10752bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere
10762bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere/**
1077ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_alloc_memory() - allocate display memory for framebuffer window
1078ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The base resources for the hardware.
1079ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window to initialise memory for.
1080ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
1081ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Allocate memory for the given framebuffer.
1082ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
1083ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb,
1084ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks					 struct s3c_fb_win *win)
1085ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
1086ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_pd_win *windata = win->windata;
1087ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	unsigned int real_size, virt_size, size;
1088ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_info *fbi = win->fbinfo;
1089ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dma_addr_t map_dma;
1090ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1091ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "allocating memory for display\n");
1092ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1093ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	real_size = windata->win_mode.xres * windata->win_mode.yres;
1094ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	virt_size = windata->virtual_x * windata->virtual_y;
1095ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1096ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n",
1097ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		real_size, windata->win_mode.xres, windata->win_mode.yres,
1098ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		virt_size, windata->virtual_x, windata->virtual_y);
1099ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1100ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	size = (real_size > virt_size) ? real_size : virt_size;
1101ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	size *= (windata->max_bpp > 16) ? 32 : windata->max_bpp;
1102ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	size /= 8;
1103ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1104ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbi->fix.smem_len = size;
1105ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	size = PAGE_ALIGN(size);
1106ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1107ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "want %u bytes for window\n", size);
1108ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1109ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbi->screen_base = dma_alloc_writecombine(sfb->dev, size,
1110ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks						  &map_dma, GFP_KERNEL);
1111ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!fbi->screen_base)
1112ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return -ENOMEM;
1113ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1114ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "mapped %x to %p\n",
1115ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		(unsigned int)map_dma, fbi->screen_base);
1116ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1117ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	memset(fbi->screen_base, 0x0, size);
1118ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbi->fix.smem_start = map_dma;
1119ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1120ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
1121ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1122ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1123ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
1124ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_free_memory() - free the display memory for the given window
1125ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The base resources for the hardware.
1126ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window to free the display memory for.
1127ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
1128ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Free the display memory allocated by s3c_fb_alloc_memory().
1129ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
1130ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
1131ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
1132ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_info *fbi = win->fbinfo;
1133ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1134cd7d7e0244955a4694d1e79e8c8a9bef163d6305Pawel Osciak	if (fbi->screen_base)
1135cd7d7e0244955a4694d1e79e8c8a9bef163d6305Pawel Osciak		dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
1136ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			      fbi->screen_base, fbi->fix.smem_start);
1137ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1138ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1139ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
1140ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_release_win() - release resources for a framebuffer window.
1141ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window to cleanup the resources for.
1142ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
1143ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Release the resources that where claimed for the hardware window,
1144ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * such as the framebuffer instance and any memory claimed for it.
1145ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
1146ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win)
1147ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
114804ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak	u32 data;
114904ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak
1150ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt	if (win->fbinfo) {
115104ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak		if (sfb->variant.has_shadowcon) {
115204ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak			data = readl(sfb->regs + SHADOWCON);
115304ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak			data &= ~SHADOWCON_CHx_ENABLE(win->index);
115404ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak			data &= ~SHADOWCON_CHx_LOCAL_ENABLE(win->index);
115504ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak			writel(data, sfb->regs + SHADOWCON);
115604ab9ef97771ba88789672a1f0d0ddcf8dbc0924Pawel Osciak		}
1157ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt		unregister_framebuffer(win->fbinfo);
1158cd7d7e0244955a4694d1e79e8c8a9bef163d6305Pawel Osciak		if (win->fbinfo->cmap.len)
1159cd7d7e0244955a4694d1e79e8c8a9bef163d6305Pawel Osciak			fb_dealloc_cmap(&win->fbinfo->cmap);
1160ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt		s3c_fb_free_memory(sfb, win);
1161ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt		framebuffer_release(win->fbinfo);
1162ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt	}
1163ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1164ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1165ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
1166ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_probe_win() - register an hardware window
1167ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The base resources for the hardware
116850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @variant: The variant information for this window.
1169ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @res: Pointer to where to place the resultant window.
1170ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
1171ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Allocate and do the basic initialisation for one of the hardware's graphics
1172ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * windows.
1173ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
1174ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
117550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks				      struct s3c_fb_win_variant *variant,
1176ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				      struct s3c_fb_win **res)
1177ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
1178ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_var_screeninfo *var;
1179ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_videomode *initmode;
1180ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_pd_win *windata;
1181ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_win *win;
1182ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct fb_info *fbinfo;
1183ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int palette_size;
1184ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int ret;
1185ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1186c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	dev_dbg(sfb->dev, "probing window %d, variant %p\n", win_no, variant);
1187ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1188efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	init_waitqueue_head(&sfb->vsync_info.wait);
1189efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
119050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	palette_size = variant->palette_sz * 4;
1191ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1192ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
1193ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				   palette_size * sizeof(u32), sfb->dev);
1194ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!fbinfo) {
1195ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(sfb->dev, "failed to allocate framebuffer\n");
1196ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return -ENOENT;
1197ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1198ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1199ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	windata = sfb->pdata->win[win_no];
1200ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	initmode = &windata->win_mode;
1201ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1202ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	WARN_ON(windata->max_bpp == 0);
1203ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	WARN_ON(windata->win_mode.xres == 0);
1204ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	WARN_ON(windata->win_mode.yres == 0);
1205ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1206ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win = fbinfo->par;
1207cd7d7e0244955a4694d1e79e8c8a9bef163d6305Pawel Osciak	*res = win;
1208ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	var = &fbinfo->var;
120950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	win->variant = *variant;
1210ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win->fbinfo = fbinfo;
1211ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win->parent = sfb;
1212ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win->windata = windata;
1213ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win->index = win_no;
1214ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	win->palette_buffer = (u32 *)(win + 1);
1215ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1216ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	ret = s3c_fb_alloc_memory(sfb, win);
1217ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (ret) {
1218ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(sfb->dev, "failed to allocate display memory\n");
1219ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt		return ret;
1220ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1221ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1222ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* setup the r/b/g positions for the window's palette */
1223bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	if (win->variant.palette_16bpp) {
1224bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		/* Set RGB 5:6:5 as default */
1225bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.r.offset = 11;
1226bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.r.length = 5;
1227bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.g.offset = 5;
1228bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.g.length = 6;
1229bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.b.offset = 0;
1230bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.b.length = 5;
1231bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks
1232bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	} else {
1233bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		/* Set 8bpp or 8bpp and 1bit alpha */
1234bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.r.offset = 16;
1235bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.r.length = 8;
1236bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.g.offset = 8;
1237bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.g.length = 8;
1238bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.b.offset = 0;
1239bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks		win->palette.b.length = 8;
1240bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks	}
1241ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1242ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* setup the initial video mode from the window */
1243ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fb_videomode_to_var(&fbinfo->var, initmode);
1244ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1245ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->fix.type	= FB_TYPE_PACKED_PIXELS;
1246ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->fix.accel	= FB_ACCEL_NONE;
1247ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->var.activate	= FB_ACTIVATE_NOW;
1248ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->var.vmode	= FB_VMODE_NONINTERLACED;
1249ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->var.bits_per_pixel = windata->default_bpp;
1250ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->fbops		= &s3c_fb_ops;
1251ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->flags		= FBINFO_FLAG_DEFAULT;
1252ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	fbinfo->pseudo_palette  = &win->pseudo_palette;
1253ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1254ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* prepare to actually start the framebuffer */
1255ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1256ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	ret = s3c_fb_check_var(&fbinfo->var, fbinfo);
1257ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (ret < 0) {
1258ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(sfb->dev, "check_var failed on initial video params\n");
1259ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt		return ret;
1260ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1261ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1262ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* create initial colour map */
1263ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
126450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	ret = fb_alloc_cmap(&fbinfo->cmap, win->variant.palette_sz, 1);
1265ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (ret == 0)
1266ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		fb_set_cmap(&fbinfo->cmap, fbinfo);
1267ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	else
1268ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(sfb->dev, "failed to allocate fb cmap\n");
1269ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1270ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	s3c_fb_set_par(fbinfo);
1271ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1272ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(sfb->dev, "about to register framebuffer\n");
1273ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1274ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* run the check_var and set_par on our configuration. */
1275ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1276ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	ret = register_framebuffer(fbinfo);
1277ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (ret < 0) {
1278ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(sfb->dev, "failed to register framebuffer\n");
1279ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt		return ret;
1280ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1281ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1282ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id);
1283ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1284ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
1285ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1286ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1287ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
1288ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_clear_win() - clear hardware window registers.
1289ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The base resources for the hardware.
1290ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window to process.
1291ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
1292ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Reset the specific window registers to a known state.
1293ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
1294ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
1295ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
1296ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	void __iomem *regs = sfb->regs;
1297a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak	u32 reg;
1298ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1299c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(0, regs + sfb->variant.wincon + (win * 4));
1300c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(0, regs + VIDOSD_A(win, sfb->variant));
1301c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(0, regs + VIDOSD_B(win, sfb->variant));
1302c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	writel(0, regs + VIDOSD_C(win, sfb->variant));
1303a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak	reg = readl(regs + SHADOWCON);
1304a8bdabca3ad69de632bd13f1cb65639e9a556e20Pawel Osciak	writel(reg & ~SHADOWCON_WINx_PROTECT(win), regs + SHADOWCON);
1305ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1306ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1307ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __devinit s3c_fb_probe(struct platform_device *pdev)
1308ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
1309b73a21fc66fee35b41db755abebfacba48b2fc76Jingoo Han	const struct platform_device_id *platid;
131050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	struct s3c_fb_driverdata *fbdrv;
1311ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct device *dev = &pdev->dev;
1312ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb_platdata *pd;
1313ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb *sfb;
1314ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct resource *res;
1315ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int win;
1316ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int ret = 0;
1317ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1318b73a21fc66fee35b41db755abebfacba48b2fc76Jingoo Han	platid = platform_get_device_id(pdev);
1319b73a21fc66fee35b41db755abebfacba48b2fc76Jingoo Han	fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
132050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
132150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {
132250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		dev_err(dev, "too many windows, cannot attach\n");
132350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		return -EINVAL;
132450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	}
132550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
1326ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	pd = pdev->dev.platform_data;
1327ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!pd) {
1328ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(dev, "no platform data specified\n");
1329ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return -EINVAL;
1330ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1331ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1332ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	sfb = kzalloc(sizeof(struct s3c_fb), GFP_KERNEL);
1333ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!sfb) {
1334ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(dev, "no memory for framebuffers\n");
1335ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		return -ENOMEM;
1336ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1337ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1338c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	dev_dbg(dev, "allocate new framebuffer %p\n", sfb);
1339c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
1340ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	sfb->dev = dev;
1341ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	sfb->pdata = pd;
134250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	sfb->variant = fbdrv->variant;
1343ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1344b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han	spin_lock_init(&sfb->slock);
1345b07f3bbee12163a6b48991138a37b87a1126462aJingoo Han
1346ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	sfb->bus_clk = clk_get(dev, "lcd");
1347ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (IS_ERR(sfb->bus_clk)) {
1348ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(dev, "failed to get bus clock\n");
1349942b8d05cdf1da396b4449a38b87c677591947c0Axel Lin		ret = PTR_ERR(sfb->bus_clk);
1350ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		goto err_sfb;
1351ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1352ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1353ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	clk_enable(sfb->bus_clk);
1354ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1355b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	if (!sfb->variant.has_clksel) {
1356b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		sfb->lcd_clk = clk_get(dev, "sclk_fimd");
1357b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		if (IS_ERR(sfb->lcd_clk)) {
1358b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			dev_err(dev, "failed to get lcd clock\n");
1359b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			ret = PTR_ERR(sfb->lcd_clk);
1360b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			goto err_bus_clk;
1361b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		}
1362b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
1363b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_enable(sfb->lcd_clk);
1364b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	}
1365b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
13664959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	pm_runtime_enable(sfb->dev);
13674959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1368ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1369ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!res) {
1370ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(dev, "failed to find registers\n");
1371ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		ret = -ENOENT;
1372b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		goto err_lcd_clk;
1373ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1374ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1375ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	sfb->regs_res = request_mem_region(res->start, resource_size(res),
1376ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks					   dev_name(dev));
1377ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!sfb->regs_res) {
1378ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(dev, "failed to claim register region\n");
1379ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		ret = -ENOENT;
1380b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		goto err_lcd_clk;
1381ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1382ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1383ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	sfb->regs = ioremap(res->start, resource_size(res));
1384ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	if (!sfb->regs) {
1385ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		dev_err(dev, "failed to map registers\n");
1386ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		ret = -ENXIO;
1387ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		goto err_req_region;
1388ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1389ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1390efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1391efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (!res) {
1392efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		dev_err(dev, "failed to acquire irq resource\n");
1393efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		ret = -ENOENT;
1394efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		goto err_ioremap;
1395efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	}
1396efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	sfb->irq_no = res->start;
1397efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	ret = request_irq(sfb->irq_no, s3c_fb_irq,
1398efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak			  0, "s3c_fb", sfb);
1399efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	if (ret) {
1400efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		dev_err(dev, "irq request failed\n");
1401efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak		goto err_ioremap;
1402efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	}
1403efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1404ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
1405ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
14064959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	platform_set_drvdata(pdev, sfb);
14074959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	pm_runtime_get_sync(sfb->dev);
14084959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1409ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* setup gpio and output polarity controls */
1410ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1411ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	pd->setup_gpio();
1412ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1413ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	writel(pd->vidcon1, sfb->regs + VIDCON1);
1414ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1415ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* zero all windows before we do anything */
1416ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
141750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	for (win = 0; win < fbdrv->variant.nr_windows; win++)
1418ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		s3c_fb_clear_win(sfb, win);
1419ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1420949470375393e82dc9158d36d675180c8c250388Ben Dooks	/* initialise colour key controls */
142150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	for (win = 0; win < (fbdrv->variant.nr_windows - 1); win++) {
1422c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		void __iomem *regs = sfb->regs + sfb->variant.keycon;
1423c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
1424c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		regs += (win * 8);
1425c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(0xffffff, regs + WKEYCON0);
1426c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		writel(0xffffff, regs + WKEYCON1);
1427949470375393e82dc9158d36d675180c8c250388Ben Dooks	}
1428949470375393e82dc9158d36d675180c8c250388Ben Dooks
1429ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	/* we have the register setup, start allocating framebuffers */
1430ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
143150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	for (win = 0; win < fbdrv->variant.nr_windows; win++) {
1432ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (!pd->win[win])
1433ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			continue;
1434ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
14352bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere		if (!pd->win[win]->win_mode.pixclock)
14362bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere			s3c_fb_missing_pixclock(&pd->win[win]->win_mode);
14372bb567a38950f0917aecfe1a3e46720d8bbb0020Maurus Cuelenaere
143850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
143950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks				       &sfb->windows[win]);
1440ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		if (ret < 0) {
1441ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			dev_err(dev, "failed to create window %d\n", win);
1442ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks			for (; win >= 0; win--)
1443ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks				s3c_fb_release_win(sfb, sfb->windows[win]);
1444efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak			goto err_irq;
1445ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		}
1446ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	}
1447ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1448ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	platform_set_drvdata(pdev, sfb);
1449ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1450ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
1451ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1452efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciakerr_irq:
1453efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	free_irq(sfb->irq_no, sfb);
1454efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1455ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dookserr_ioremap:
1456ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	iounmap(sfb->regs);
1457ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1458ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dookserr_req_region:
1459683e7cdc207f71eef3ff46f5d36ec505c65fbbc6Julia Lawall	release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
1460ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1461b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Hanerr_lcd_clk:
1462b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	if (!sfb->variant.has_clksel) {
1463b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_disable(sfb->lcd_clk);
1464b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_put(sfb->lcd_clk);
1465b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	}
1466b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
1467b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Hanerr_bus_clk:
1468ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	clk_disable(sfb->bus_clk);
1469ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	clk_put(sfb->bus_clk);
1470ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1471ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dookserr_sfb:
1472ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	kfree(sfb);
1473ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return ret;
1474ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1475ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1476ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/**
1477ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_remove() - Cleanup on module finalisation
1478ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pdev: The platform device we are bound to.
1479ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *
1480ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Shutdown and then release all the resources that the driver allocated
1481ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * on initialisation.
1482ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */
1483ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __devexit s3c_fb_remove(struct platform_device *pdev)
1484ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{
1485ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	struct s3c_fb *sfb = platform_get_drvdata(pdev);
1486ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	int win;
1487ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1488c42b110caeb128819104d057acdaa1ae564b7c8dPawel Osciak	for (win = 0; win < S3C_FB_MAX_WIN; win++)
148917663e59704bea838a9236f299104e30909a43b1Marek Szyprowski		if (sfb->windows[win])
149017663e59704bea838a9236f299104e30909a43b1Marek Szyprowski			s3c_fb_release_win(sfb, sfb->windows[win]);
1491ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1492efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak	free_irq(sfb->irq_no, sfb);
1493efdc846d2f7190c8f3092c09975c0ebba30a95baPawel Osciak
1494ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	iounmap(sfb->regs);
1495ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1496b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	if (!sfb->variant.has_clksel) {
1497b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_disable(sfb->lcd_clk);
1498b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_put(sfb->lcd_clk);
1499b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	}
1500b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
1501ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	clk_disable(sfb->bus_clk);
1502ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	clk_put(sfb->bus_clk);
1503ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1504683e7cdc207f71eef3ff46f5d36ec505c65fbbc6Julia Lawall	release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
1505ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
15064959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	pm_runtime_put_sync(sfb->dev);
15074959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	pm_runtime_disable(sfb->dev);
15084959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
150972ba4cb608e7937792f3d61349ef616bbffda832Jingoo Han	kfree(sfb);
1510ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	return 0;
1511ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}
1512ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
151335784b4315d949e431df9a0ffef721a4801b1588Jingoo Han#ifdef CONFIG_PM_SLEEP
15144959212c18669f254daa0ae796ad676b67939ba2Jingoo Hanstatic int s3c_fb_suspend(struct device *dev)
15154959212c18669f254daa0ae796ad676b67939ba2Jingoo Han{
15164959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct platform_device *pdev = to_platform_device(dev);
15174959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct s3c_fb *sfb = platform_get_drvdata(pdev);
15184959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct s3c_fb_win *win;
15194959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	int win_no;
15204959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
15214959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
15224959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		win = sfb->windows[win_no];
15234959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		if (!win)
15244959212c18669f254daa0ae796ad676b67939ba2Jingoo Han			continue;
15254959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
15264959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		/* use the blank function to push into power-down */
15274959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
15284959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	}
15294959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1530b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	if (!sfb->variant.has_clksel)
1531b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_disable(sfb->lcd_clk);
1532b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
15334959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	clk_disable(sfb->bus_clk);
153435784b4315d949e431df9a0ffef721a4801b1588Jingoo Han	pm_runtime_put_sync(sfb->dev);
153535784b4315d949e431df9a0ffef721a4801b1588Jingoo Han
15364959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	return 0;
15374959212c18669f254daa0ae796ad676b67939ba2Jingoo Han}
15384959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
15394959212c18669f254daa0ae796ad676b67939ba2Jingoo Hanstatic int s3c_fb_resume(struct device *dev)
15404959212c18669f254daa0ae796ad676b67939ba2Jingoo Han{
15414959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct platform_device *pdev = to_platform_device(dev);
15424959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct s3c_fb *sfb = platform_get_drvdata(pdev);
15434959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct s3c_fb_platdata *pd = sfb->pdata;
15444959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	struct s3c_fb_win *win;
15454959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	int win_no;
15464959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
154735784b4315d949e431df9a0ffef721a4801b1588Jingoo Han	pm_runtime_get_sync(sfb->dev);
15484959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	clk_enable(sfb->bus_clk);
15494959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1550b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	if (!sfb->variant.has_clksel)
1551b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		clk_enable(sfb->lcd_clk);
1552b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
15536aa9681100303bd467cbd0262eb00da8d492fc7fJingoo Han	/* setup gpio and output polarity controls */
15546aa9681100303bd467cbd0262eb00da8d492fc7fJingoo Han	pd->setup_gpio();
15554959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	writel(pd->vidcon1, sfb->regs + VIDCON1);
15564959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
15574959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	/* zero all windows before we do anything */
15584959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
15594959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		s3c_fb_clear_win(sfb, win_no);
15604959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
15614959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
15624959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		void __iomem *regs = sfb->regs + sfb->variant.keycon;
1563ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		win = sfb->windows[win_no];
1564ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		if (!win)
1565ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han			continue;
15664959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1567ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 1);
15684959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		regs += (win_no * 8);
15694959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		writel(0xffffff, regs + WKEYCON0);
15704959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		writel(0xffffff, regs + WKEYCON1);
1571ff8c91072389491375f6d1ea86ce55942c460a04Jingoo Han		shadow_protect_win(win, 0);
15724959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	}
15734959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
15744959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	/* restore framebuffers */
15754959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
15764959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		win = sfb->windows[win_no];
15774959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		if (!win)
15784959212c18669f254daa0ae796ad676b67939ba2Jingoo Han			continue;
15794959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
15804959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
15814959212c18669f254daa0ae796ad676b67939ba2Jingoo Han		s3c_fb_set_par(win->fbinfo);
15824959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	}
15834959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
15844959212c18669f254daa0ae796ad676b67939ba2Jingoo Han	return 0;
15854959212c18669f254daa0ae796ad676b67939ba2Jingoo Han}
1586ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#endif
1587ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
158835784b4315d949e431df9a0ffef721a4801b1588Jingoo Han#ifdef CONFIG_PM_RUNTIME
158935784b4315d949e431df9a0ffef721a4801b1588Jingoo Hanstatic int s3c_fb_runtime_suspend(struct device *dev)
159035784b4315d949e431df9a0ffef721a4801b1588Jingoo Han{
159135784b4315d949e431df9a0ffef721a4801b1588Jingoo Han	return 0;
159235784b4315d949e431df9a0ffef721a4801b1588Jingoo Han}
159335784b4315d949e431df9a0ffef721a4801b1588Jingoo Han
159435784b4315d949e431df9a0ffef721a4801b1588Jingoo Hanstatic int s3c_fb_runtime_resume(struct device *dev)
159535784b4315d949e431df9a0ffef721a4801b1588Jingoo Han{
159635784b4315d949e431df9a0ffef721a4801b1588Jingoo Han	return 0;
159735784b4315d949e431df9a0ffef721a4801b1588Jingoo Han}
159835784b4315d949e431df9a0ffef721a4801b1588Jingoo Han#endif
159950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
160050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
160150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
160250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
16038cfdcb2393b05cc80f89ed0110c0f90423d2fee1Marek Szyprowskistatic struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = {
160450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	[0] = {
160550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_c	= 1,
1606f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		.osd_size_off	= 0x8,
160750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_sz	= 256,
1608cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
1609cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(18) | VALID_BPP(24)),
161050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
161150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	[1] = {
161250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_c	= 1,
161350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_d	= 1,
1614c9d503e93562e1de093ff16a480fc8801cfa70d9Jingoo Han		.osd_size_off	= 0xc,
1615f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		.has_osd_alpha	= 1,
161650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_sz	= 256,
161750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
161850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks				   VALID_BPP(18) | VALID_BPP(19) |
1619cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1620cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(28)),
162150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
162250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	[2] = {
162350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_c	= 1,
162450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_d	= 1,
1625c9d503e93562e1de093ff16a480fc8801cfa70d9Jingoo Han		.osd_size_off	= 0xc,
1626f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		.has_osd_alpha	= 1,
162750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_sz	= 16,
162850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_16bpp	= 1,
162950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
163050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks				   VALID_BPP(18) | VALID_BPP(19) |
1631cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1632cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(28)),
163350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
163450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	[3] = {
163550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_c	= 1,
1636f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		.has_osd_alpha	= 1,
163750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_sz	= 16,
163850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_16bpp	= 1,
163950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.valid_bpp	= (VALID_BPP124  | VALID_BPP(16) |
164050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks				   VALID_BPP(18) | VALID_BPP(19) |
1641cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1642cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(28)),
164350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
164450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	[4] = {
164550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.has_osd_c	= 1,
1646f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		.has_osd_alpha	= 1,
164750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_sz	= 4,
164850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette_16bpp	= 1,
164950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.valid_bpp	= (VALID_BPP(1) | VALID_BPP(2) |
165050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks				   VALID_BPP(16) | VALID_BPP(18) |
1651cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(19) | VALID_BPP(24) |
1652cd74ebaf7ac18eced59a3983b266be39d7b28ee0Jingoo Han				   VALID_BPP(25) | VALID_BPP(28)),
165350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
165450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
165550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
1656af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Hanstatic struct s3c_fb_win_variant s3c_fb_data_s5p_wins[] = {
1657af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	[0] = {
1658af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_c	= 1,
1659af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.osd_size_off	= 0x8,
1660af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.palette_sz	= 256,
1661af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
1662af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(15) | VALID_BPP(16) |
1663af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(18) | VALID_BPP(19) |
1664af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1665af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(32)),
1666af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	},
1667af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	[1] = {
1668af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_c	= 1,
1669af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_d	= 1,
1670af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.osd_size_off	= 0xc,
1671af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_alpha	= 1,
1672af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.palette_sz	= 256,
1673af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
1674af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(15) | VALID_BPP(16) |
1675af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(18) | VALID_BPP(19) |
1676af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1677af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(32)),
1678af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	},
1679af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	[2] = {
1680af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_c	= 1,
1681af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_d	= 1,
1682af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.osd_size_off	= 0xc,
1683af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_alpha	= 1,
1684af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.palette_sz	= 256,
1685af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
1686af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(15) | VALID_BPP(16) |
1687af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(18) | VALID_BPP(19) |
1688af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1689af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(32)),
1690af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	},
1691af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	[3] = {
1692af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_c	= 1,
1693af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_alpha	= 1,
1694af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.palette_sz	= 256,
1695af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
1696af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(15) | VALID_BPP(16) |
1697af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(18) | VALID_BPP(19) |
1698af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1699af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(32)),
1700af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	},
1701af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	[4] = {
1702af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_c	= 1,
1703af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.has_osd_alpha	= 1,
1704af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.palette_sz	= 256,
1705af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(13) |
1706af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(15) | VALID_BPP(16) |
1707af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(18) | VALID_BPP(19) |
1708af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(24) | VALID_BPP(25) |
1709af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han				   VALID_BPP(32)),
1710af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	},
1711af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han};
1712af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han
17138cfdcb2393b05cc80f89ed0110c0f90423d2fee1Marek Szyprowskistatic struct s3c_fb_driverdata s3c_fb_data_64xx = {
171450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.variant = {
171550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.nr_windows	= 5,
1716c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.vidtcon	= VIDTCON0,
1717c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.wincon		= WINCON(0),
1718c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.winmap		= WINxMAP(0),
1719c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.keycon		= WKEYCON,
1720c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.osd		= VIDOSD_BASE,
1721c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.osd_stride	= 16,
1722c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_start	= VIDW_BUF_START(0),
1723c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_size	= VIDW_BUF_SIZE(0),
1724c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_end	= VIDW_BUF_END(0),
172550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
172650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette = {
172750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[0] = 0x400,
172850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[1] = 0x800,
172950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[2] = 0x300,
173050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[3] = 0x320,
173150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[4] = 0x340,
173250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		},
1733067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
1734067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		.has_prtcon	= 1,
1735b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.has_clksel	= 1,
173650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
173750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.win[0]	= &s3c_fb_data_64xx_wins[0],
173850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.win[1]	= &s3c_fb_data_64xx_wins[1],
173950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.win[2]	= &s3c_fb_data_64xx_wins[2],
174050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.win[3]	= &s3c_fb_data_64xx_wins[3],
174150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.win[4]	= &s3c_fb_data_64xx_wins[4],
174250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
174350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
17448cfdcb2393b05cc80f89ed0110c0f90423d2fee1Marek Szyprowskistatic struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
17454e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak	.variant = {
17464e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.nr_windows	= 5,
17474e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.vidtcon	= VIDTCON0,
17484e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.wincon		= WINCON(0),
17494e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.winmap		= WINxMAP(0),
17504e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.keycon		= WKEYCON,
17514e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.osd		= VIDOSD_BASE,
17524e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.osd_stride	= 16,
17534e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.buf_start	= VIDW_BUF_START(0),
17544e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.buf_size	= VIDW_BUF_SIZE(0),
17554e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.buf_end	= VIDW_BUF_END(0),
17564e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak
17574e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.palette = {
17584e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak			[0] = 0x2400,
17594e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak			[1] = 0x2800,
17604e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak			[2] = 0x2c00,
17614e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak			[3] = 0x3000,
17624e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak			[4] = 0x3400,
17634e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		},
1764067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak
1765067b226b9e8e20463e0937344c93101ac8d8d2b1Pawel Osciak		.has_prtcon	= 1,
1766b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.has_clksel	= 1,
17674e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak	},
1768af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[0]	= &s3c_fb_data_s5p_wins[0],
1769af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[1]	= &s3c_fb_data_s5p_wins[1],
1770af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[2]	= &s3c_fb_data_s5p_wins[2],
1771af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[3]	= &s3c_fb_data_s5p_wins[3],
1772af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[4]	= &s3c_fb_data_s5p_wins[4],
17734e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak};
17744e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak
17758cfdcb2393b05cc80f89ed0110c0f90423d2fee1Marek Szyprowskistatic struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
177650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.variant = {
177750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.nr_windows	= 5,
1778c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.vidtcon	= VIDTCON0,
1779c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.wincon		= WINCON(0),
1780c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.winmap		= WINxMAP(0),
1781c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.keycon		= WKEYCON,
1782c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.osd		= VIDOSD_BASE,
1783c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.osd_stride	= 16,
1784c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_start	= VIDW_BUF_START(0),
1785c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_size	= VIDW_BUF_SIZE(0),
1786c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_end	= VIDW_BUF_END(0),
178750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
178850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.palette = {
178950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[0] = 0x2400,
179050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[1] = 0x2800,
179150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[2] = 0x2c00,
179250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[3] = 0x3000,
179350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks			[4] = 0x3400,
179450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		},
1795f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak
1796f5ec546f1f5e21bfc84ce7a1ac7408702082c65aPawel Osciak		.has_shadowcon	= 1,
1797b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.has_clksel	= 1,
1798b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	},
1799b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	.win[0]	= &s3c_fb_data_s5p_wins[0],
1800b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	.win[1]	= &s3c_fb_data_s5p_wins[1],
1801b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	.win[2]	= &s3c_fb_data_s5p_wins[2],
1802b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	.win[3]	= &s3c_fb_data_s5p_wins[3],
1803b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	.win[4]	= &s3c_fb_data_s5p_wins[4],
1804b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han};
1805b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
1806b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Hanstatic struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
1807b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	.variant = {
1808b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.nr_windows	= 5,
1809b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.vidtcon	= VIDTCON0,
1810b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.wincon		= WINCON(0),
1811b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.winmap		= WINxMAP(0),
1812b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.keycon		= WKEYCON,
1813b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.osd		= VIDOSD_BASE,
1814b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.osd_stride	= 16,
1815b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.buf_start	= VIDW_BUF_START(0),
1816b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.buf_size	= VIDW_BUF_SIZE(0),
1817b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.buf_end	= VIDW_BUF_END(0),
1818b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
1819b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.palette = {
1820b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			[0] = 0x2400,
1821b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			[1] = 0x2800,
1822b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			[2] = 0x2c00,
1823b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			[3] = 0x3000,
1824b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han			[4] = 0x3400,
1825b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		},
1826b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han
1827b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.has_shadowcon	= 1,
182850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
1829af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[0]	= &s3c_fb_data_s5p_wins[0],
1830af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[1]	= &s3c_fb_data_s5p_wins[1],
1831af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[2]	= &s3c_fb_data_s5p_wins[2],
1832af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[3]	= &s3c_fb_data_s5p_wins[3],
1833af4a835bba5fe710b870b8ec8c294e2338cbb112Jingoo Han	.win[4]	= &s3c_fb_data_s5p_wins[4],
183450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
183550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
1836c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks/* S3C2443/S3C2416 style hardware */
18378cfdcb2393b05cc80f89ed0110c0f90423d2fee1Marek Szyprowskistatic struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
1838c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	.variant = {
1839c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.nr_windows	= 2,
1840c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.is_2443	= 1,
1841c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
1842c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.vidtcon	= 0x08,
1843c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.wincon		= 0x14,
1844c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.winmap		= 0xd0,
1845c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.keycon		= 0xb0,
1846c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.osd		= 0x28,
1847c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.osd_stride	= 12,
1848c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_start	= 0x64,
1849c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_size	= 0x94,
1850c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.buf_end	= 0x7c,
1851c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
1852c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.palette = {
1853c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks			[0] = 0x400,
1854c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks			[1] = 0x800,
1855c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		},
1856b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.has_clksel	= 1,
1857c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	},
1858c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	.win[0] = &(struct s3c_fb_win_variant) {
1859c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.palette_sz	= 256,
1860c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.valid_bpp	= VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24),
1861c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	},
1862c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	.win[1] = &(struct s3c_fb_win_variant) {
1863c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.has_osd_c	= 1,
1864f676ec2a3526465dfa7b5c513a0c2bb22fb70b80Pawel Osciak		.has_osd_alpha	= 1,
1865c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.palette_sz	= 256,
1866c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.valid_bpp	= (VALID_BPP1248 | VALID_BPP(16) |
1867c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks				   VALID_BPP(18) | VALID_BPP(19) |
1868c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks				   VALID_BPP(24) | VALID_BPP(25) |
1869c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks				   VALID_BPP(28)),
1870c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	},
1871c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks};
1872c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks
187321b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumarstatic struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = {
187421b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar	.variant = {
187521b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.nr_windows	= 3,
187621b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.vidtcon	= VIDTCON0,
187721b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.wincon		= WINCON(0),
187821b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.winmap		= WINxMAP(0),
187921b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.keycon		= WKEYCON,
188021b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.osd		= VIDOSD_BASE,
188121b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.osd_stride	= 16,
188221b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.buf_start	= VIDW_BUF_START(0),
188321b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.buf_size	= VIDW_BUF_SIZE(0),
188421b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.buf_end	= VIDW_BUF_END(0),
188521b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar
188621b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.palette = {
188721b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar			[0] = 0x2400,
188821b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar			[1] = 0x2800,
188921b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar			[2] = 0x2c00,
189021b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		},
189121b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar	},
189221b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar	.win[0] = &s3c_fb_data_s5p_wins[0],
189321b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar	.win[1] = &s3c_fb_data_s5p_wins[1],
189421b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar	.win[2] = &s3c_fb_data_s5p_wins[2],
189521b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar};
189621b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar
189750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstatic struct platform_device_id s3c_fb_driver_ids[] = {
189850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	{
189950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.name		= "s3c-fb",
190050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks		.driver_data	= (unsigned long)&s3c_fb_data_64xx,
190150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	}, {
19024e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.name		= "s5pc100-fb",
19034e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.driver_data	= (unsigned long)&s3c_fb_data_s5pc100,
19044e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak	}, {
19054e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.name		= "s5pv210-fb",
19064e591ac620269b3f5fb000d75444bbb397576315Pawel Osciak		.driver_data	= (unsigned long)&s3c_fb_data_s5pv210,
1907c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks	}, {
1908b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.name		= "exynos4-fb",
1909b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han		.driver_data	= (unsigned long)&s3c_fb_data_exynos4,
1910b5480ed72e4f299c53d1857faaf4f492650ccc43Jingoo Han	}, {
1911c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.name		= "s3c2443-fb",
1912c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks		.driver_data	= (unsigned long)&s3c_fb_data_s3c2443,
191321b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar	}, {
191421b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.name		= "s5p64x0-fb",
191521b5a3adf9d16a4eb9874b32cfc84af34f697c1dAjay Kumar		.driver_data	= (unsigned long)&s3c_fb_data_s5p64x0,
191650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	},
191750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	{},
191850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks};
191950a5503a9208420e6c59d24504a5e9913d603cf7Ben DooksMODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
192050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks
192135784b4315d949e431df9a0ffef721a4801b1588Jingoo Hanstatic const struct dev_pm_ops s3c_fb_pm_ops = {
192235784b4315d949e431df9a0ffef721a4801b1588Jingoo Han	SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume)
192335784b4315d949e431df9a0ffef721a4801b1588Jingoo Han	SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume, NULL)
192435784b4315d949e431df9a0ffef721a4801b1588Jingoo Han};
19254959212c18669f254daa0ae796ad676b67939ba2Jingoo Han
1926ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic struct platform_driver s3c_fb_driver = {
1927ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.probe		= s3c_fb_probe,
19283163eaba34943967aebb1eefa0d4bdc4e5dc197cPeter Korsgaard	.remove		= __devexit_p(s3c_fb_remove),
192950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks	.id_table	= s3c_fb_driver_ids,
1930ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	.driver		= {
1931ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		.name	= "s3c-fb",
1932ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks		.owner	= THIS_MODULE,
193335784b4315d949e431df9a0ffef721a4801b1588Jingoo Han		.pm	= &s3c_fb_pm_ops,
1934ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks	},
1935ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks};
1936ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
19374277f2c4667187cbbdd3da3be31ee681bc6b8300Axel Linmodule_platform_driver(s3c_fb_driver);
1938ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks
1939ec549a0fdc32171b26677f1ef0b5309faa743362Ben DooksMODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
1940ec549a0fdc32171b26677f1ef0b5309faa743362Ben DooksMODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver");
1941ec549a0fdc32171b26677f1ef0b5309faa743362Ben DooksMODULE_LICENSE("GPL");
1942ec549a0fdc32171b26677f1ef0b5309faa743362Ben DooksMODULE_ALIAS("platform:s3c-fb");
1943