s3c-fb.c revision bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9
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> 24ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 25ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#include <mach/map.h> 26c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#include <plat/regs-fb-v4.h> 27ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#include <plat/fb.h> 28ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 29ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/* This driver will export a number of framebuffer interfaces depending 30ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * on the configuration passed in via the platform data. Each fb instance 31ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * maps to a hardware window. Currently there is no support for runtime 32ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * setting of the alpha-blending functions that each window has, so only 33ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * window 0 is actually useful. 34ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 35ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Window 0 is treated specially, it is used for the basis of the LCD 36ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * output timings and as the control for the output power-down state. 37ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks*/ 38ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 3950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks/* note, the previous use of <mach/regs-fb.h> to get platform specific data 4050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * has been replaced by using the platform device name to pick the correct 4150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * configuration data for the system. 42ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks*/ 43ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 44ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#ifdef CONFIG_FB_S3C_DEBUG_REGWRITE 45ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#undef writel 46ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#define writel(v, r) do { \ 47ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \ 48ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks __raw_writel(v, r); } while(0) 49ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#endif /* FB_S3C_DEBUG_REGWRITE */ 50ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 51ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstruct s3c_fb; 52ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 5350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks#define VALID_BPP(x) (1 << ((x) - 1)) 5450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 55c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define OSD_BASE(win, variant) ((variant).osd + ((win) * (variant).osd_stride)) 56c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define VIDOSD_A(win, variant) (OSD_BASE(win, variant) + 0x00) 57c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define VIDOSD_B(win, variant) (OSD_BASE(win, variant) + 0x04) 58c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define VIDOSD_C(win, variant) (OSD_BASE(win, variant) + 0x08) 59c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks#define VIDOSD_D(win, variant) (OSD_BASE(win, variant) + 0x0C) 60c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks 6150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks/** 6250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * struct s3c_fb_variant - fb variant information 63c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @is_2443: Set if S3C2443/S3C2416 style hardware. 6450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @nr_windows: The number of windows. 65c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @vidtcon: The base for the VIDTCONx registers 66c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @wincon: The base for the WINxCON registers. 67c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @winmap: The base for the WINxMAP registers. 68c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @keycon: The abse for the WxKEYCON registers. 69c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @buf_start: Offset of buffer start registers. 70c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @buf_size: Offset of buffer size registers. 71c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @buf_end: Offset of buffer end registers. 72c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks * @osd: The base for the OSD registers. 7350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @palette: Address of palette memory, or 0 if none. 7450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks */ 7550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstruct s3c_fb_variant { 76c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks unsigned int is_2443:1; 7750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks unsigned short nr_windows; 78c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks unsigned short vidtcon; 79c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks unsigned short wincon; 80c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks unsigned short winmap; 81c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks unsigned short keycon; 82c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks unsigned short buf_start; 83c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks unsigned short buf_end; 84c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks unsigned short buf_size; 85c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks unsigned short osd; 86c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks unsigned short osd_stride; 8750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks unsigned short palette[S3C_FB_MAX_WIN]; 8850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks}; 8950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 9050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks/** 9150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * struct s3c_fb_win_variant 9250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @has_osd_c: Set if has OSD C register. 9350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @has_osd_d: Set if has OSD D register. 9450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @palette_sz: Size of palette in entries. 9550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @palette_16bpp: Set if palette is 16bits wide. 9650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @valid_bpp: 1 bit per BPP setting to show valid bits-per-pixel. 9750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * 9850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * valid_bpp bit x is set if (x+1)BPP is supported. 9950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks */ 10050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstruct s3c_fb_win_variant { 10150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks unsigned int has_osd_c:1; 10250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks unsigned int has_osd_d:1; 10350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks unsigned int palette_16bpp:1; 10450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks unsigned short palette_sz; 10550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks u32 valid_bpp; 10650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks}; 10750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 10850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks/** 10950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * struct s3c_fb_driverdata - per-device type driver data for init time. 11050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @variant: The variant information for this driver. 11150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @win: The window information for each window. 11250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks */ 11350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstruct s3c_fb_driverdata { 11450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks struct s3c_fb_variant variant; 11550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks struct s3c_fb_win_variant *win[S3C_FB_MAX_WIN]; 11650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks}; 11750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 118ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 119bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * struct s3c_fb_palette - palette information 120bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * @r: Red bitfield. 121bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * @g: Green bitfield. 122bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * @b: Blue bitfield. 123bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks * @a: Alpha bitfield. 124bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks */ 125bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooksstruct s3c_fb_palette { 126bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks struct fb_bitfield r; 127bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks struct fb_bitfield g; 128bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks struct fb_bitfield b; 129bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks struct fb_bitfield a; 130bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks}; 131bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks 132bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks/** 133ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * struct s3c_fb_win - per window private data for each framebuffer. 134ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @windata: The platform data supplied for the window configuration. 135ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @parent: The hardware that this window is part of. 136ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @fbinfo: Pointer pack to the framebuffer info for this window. 13750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @varint: The variant information for this window. 138ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @palette_buffer: Buffer/cache to hold palette entries. 139ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/ 140ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @index: The window number of this window. 141ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @palette: The bitfields for changing r/g/b into a hardware palette entry. 142ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 143ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstruct s3c_fb_win { 144ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_pd_win *windata; 145ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb *parent; 146ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct fb_info *fbinfo; 147ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_palette palette; 14850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks struct s3c_fb_win_variant variant; 149ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 150ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks u32 *palette_buffer; 151ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks u32 pseudo_palette[16]; 152ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks unsigned int index; 153ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}; 154ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 155ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 156ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * struct s3c_fb - overall hardware state of the hardware 157ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @dev: The device that we bound to, for printing, etc. 158ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @regs_res: The resource we claimed for the IO registers. 159ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. 160ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @regs: The mapped hardware registers. 16150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @variant: Variant information for this hardware. 162ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @enabled: A bitmask of enabled hardware windows. 163ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pdata: The platform configuration data passed with the device. 164ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @windows: The hardware windows that have been claimed. 165ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 166ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstruct s3c_fb { 167ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct device *dev; 168ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct resource *regs_res; 169ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct clk *bus_clk; 170ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks void __iomem *regs; 17150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks struct s3c_fb_variant variant; 172ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 173ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks unsigned char enabled; 174ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 175ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_platdata *pdata; 176ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_win *windows[S3C_FB_MAX_WIN]; 177ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}; 178ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 179ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 18050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * s3c_fb_validate_win_bpp - validate the bits-per-pixel for this mode. 18150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @win: The device window. 18250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @bpp: The bit depth. 183ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 18450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstatic bool s3c_fb_validate_win_bpp(struct s3c_fb_win *win, unsigned int bpp) 185ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 18650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks return win->variant.valid_bpp & VALID_BPP(bpp); 187ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 188ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 189ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 190ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_check_var() - framebuffer layer request to verify a given mode. 191ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @var: The screen information to verify. 192ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @info: The framebuffer device. 193ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 194ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Framebuffer layer call to verify the given information and allow us to 195ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * update various information depending on the hardware capabilities. 196ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 197ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_check_var(struct fb_var_screeninfo *var, 198ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct fb_info *info) 199ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 200ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_win *win = info->par; 201ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_pd_win *windata = win->windata; 202ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb *sfb = win->parent; 203ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 204ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "checking parameters\n"); 205ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 206ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres); 207ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres); 208ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 20950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) { 210ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n", 211ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks win->index, var->bits_per_pixel); 212ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return -EINVAL; 213ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 214ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 215ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* always ensure these are zero, for drop through cases below */ 216ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->transp.offset = 0; 217ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->transp.length = 0; 218ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 219ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks switch (var->bits_per_pixel) { 220ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 1: 221ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 2: 222ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 4: 223ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 8: 22450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks if (sfb->variant.palette[win->index] != 0) { 225ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* non palletised, A:1,R:2,G:3,B:2 mode */ 226ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->red.offset = 4; 227ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->green.offset = 2; 228ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->blue.offset = 0; 229ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->red.length = 5; 230ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->green.length = 3; 231ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->blue.length = 2; 232ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->transp.offset = 7; 233ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->transp.length = 1; 234ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } else { 235ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->red.offset = 0; 236ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->red.length = var->bits_per_pixel; 237ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->green = var->red; 238ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->blue = var->red; 239ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 240ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 241ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 242ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 19: 243ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* 666 with one bit alpha/transparency */ 244ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->transp.offset = 18; 245ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->transp.length = 1; 246ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 18: 247ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->bits_per_pixel = 32; 248ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 249ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* 666 format */ 250ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->red.offset = 12; 251ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->green.offset = 6; 252ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->blue.offset = 0; 253ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->red.length = 6; 254ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->green.length = 6; 255ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->blue.length = 6; 256ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 257ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 258ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 16: 259ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* 16 bpp, 565 format */ 260ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->red.offset = 11; 261ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->green.offset = 5; 262ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->blue.offset = 0; 263ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->red.length = 5; 264ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->green.length = 6; 265ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->blue.length = 5; 266ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 267ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 268ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 28: 269ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 25: 270ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->transp.length = var->bits_per_pixel - 24; 271ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->transp.offset = 24; 272ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* drop through */ 273ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 24: 274ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* our 24bpp is unpacked, so 32bpp */ 275ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->bits_per_pixel = 32; 276ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 32: 277ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->red.offset = 16; 278ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->red.length = 8; 279ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->green.offset = 8; 280ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->green.length = 8; 281ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->blue.offset = 0; 282ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->blue.length = 8; 283ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 284ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 285ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks default: 286ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(sfb->dev, "invalid bpp\n"); 287ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 288ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 289ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "%s: verified parameters\n", __func__); 290ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return 0; 291ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 292ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 293ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 294ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. 295ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The hardware state. 296ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pixclock: The pixel clock wanted, in picoseconds. 297ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 298ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Given the specified pixel clock, work out the necessary divider to get 299ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * close to the output frequency. 300ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 301eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brownstatic int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) 302ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 303ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks unsigned long clk = clk_get_rate(sfb->bus_clk); 304eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown unsigned long long tmp; 305ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks unsigned int result; 306ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 307eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown tmp = (unsigned long long)clk; 308eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown tmp *= pixclk; 309eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown 310eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown do_div(tmp, 1000000000UL); 311eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown result = (unsigned int)tmp / 1000; 312ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 313ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", 314ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks pixclk, clk, result, clk / result); 315ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 316ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return result; 317ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 318ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 319ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 320ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_align_word() - align pixel count to word boundary 321ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @bpp: The number of bits per pixel 322ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pix: The value to be aligned. 323ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 324ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Align the given pixel count so that it will start on an 32bit word 325ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * boundary. 326ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 327ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_align_word(unsigned int bpp, unsigned int pix) 328ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 329ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks int pix_per_word; 330ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 331ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (bpp > 16) 332ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return pix; 333ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 334ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks pix_per_word = (8 * 32) / bpp; 335ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return ALIGN(pix, pix_per_word); 336ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 337ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 338ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 339ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_set_par() - framebuffer request to set new framebuffer state. 340ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @info: The framebuffer to change. 341ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 342ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Framebuffer layer request to set a new mode for the specified framebuffer 343ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 344ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_set_par(struct fb_info *info) 345ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 346ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct fb_var_screeninfo *var = &info->var; 347ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_win *win = info->par; 348ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb *sfb = win->parent; 349ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks void __iomem *regs = sfb->regs; 350c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks void __iomem *buf = regs; 351ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks int win_no = win->index; 352600ce1a0faafeed1ce6bcfd421bc040b941cbbc1InKi Dae u32 osdc_data = 0; 353ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks u32 data; 354ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks u32 pagewidth; 355ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks int clkdiv; 356ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 357ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "setting framebuffer parameters\n"); 358ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 359ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks switch (var->bits_per_pixel) { 360ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 32: 361ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 24: 362ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 16: 363ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 12: 364ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks info->fix.visual = FB_VISUAL_TRUECOLOR; 365ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 366ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 8: 36750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks if (win->variant.palette_sz >= 256) 368ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 369ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks else 370ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks info->fix.visual = FB_VISUAL_TRUECOLOR; 371ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 372ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 1: 373ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks info->fix.visual = FB_VISUAL_MONO01; 374ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 375ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks default: 376ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 377ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 378ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 379ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 380ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; 381ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 382ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* disable the window whilst we update it */ 383ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks writel(0, regs + WINCON(win_no)); 384ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 385ad04490a171915737c9b99d2fa5cb813830f24c1InKi Dae /* use platform specified window as the basis for the lcd timings */ 386ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 387ad04490a171915737c9b99d2fa5cb813830f24c1InKi Dae if (win_no == sfb->pdata->default_win) { 388eb29a5cc0b601c458bae9df2f6c3696d75c2d383Mark Brown clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); 389ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 390ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data = sfb->pdata->vidcon0; 391ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); 392ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 393ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (clkdiv > 1) 394ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR; 395ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks else 396ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data &= ~VIDCON0_CLKDIR; /* 1:1 clock */ 397ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 398ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* write the timing data to the panel */ 399ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 400c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks if (sfb->variant.is_2443) 401c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks data |= (1 << 5); 402c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks 403ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= VIDCON0_ENVID | VIDCON0_ENVID_F; 404ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks writel(data, regs + VIDCON0); 405ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 406ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data = VIDTCON0_VBPD(var->upper_margin - 1) | 407ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks VIDTCON0_VFPD(var->lower_margin - 1) | 408ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks VIDTCON0_VSPW(var->vsync_len - 1); 409ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 410c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(data, regs + sfb->variant.vidtcon); 411ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 412ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data = VIDTCON1_HBPD(var->left_margin - 1) | 413ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks VIDTCON1_HFPD(var->right_margin - 1) | 414ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks VIDTCON1_HSPW(var->hsync_len - 1); 415ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 416c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks /* VIDTCON1 */ 417c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(data, regs + sfb->variant.vidtcon + 4); 418ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 419ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data = VIDTCON2_LINEVAL(var->yres - 1) | 420ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks VIDTCON2_HOZVAL(var->xres - 1); 421c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(data, regs +sfb->variant.vidtcon + 8 ); 422ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 423ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 424ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* write the buffer address */ 425ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 426c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks /* start and end registers stride is 8 */ 427c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks buf = regs + win_no * 8; 428c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks 429c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(info->fix.smem_start, buf + sfb->variant.buf_start); 430ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 431ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data = info->fix.smem_start + info->fix.line_length * var->yres; 432c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(data, buf + sfb->variant.buf_end); 433ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 434ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks pagewidth = (var->xres * var->bits_per_pixel) >> 3; 435ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) | 436ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks VIDW_BUF_SIZE_PAGEWIDTH(pagewidth); 437c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(data, regs + sfb->variant.buf_size + (win_no * 4)); 438ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 439ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* write 'OSD' registers to control position of framebuffer */ 440ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 441ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0); 442c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(data, regs + VIDOSD_A(win_no, sfb->variant)); 443ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 444ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel, 445ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var->xres - 1)) | 446ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks VIDOSDxB_BOTRIGHT_Y(var->yres - 1); 447ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 448c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(data, regs + VIDOSD_B(win_no, sfb->variant)); 449ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 450ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data = var->xres * var->yres; 45139000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae 45239000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae osdc_data = VIDISD14C_ALPHA1_R(0xf) | 45339000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae VIDISD14C_ALPHA1_G(0xf) | 45439000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae VIDISD14C_ALPHA1_B(0xf); 45539000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae 45650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks if (win->variant.has_osd_d) { 457c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(data, regs + VIDOSD_D(win_no, sfb->variant)); 458c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(osdc_data, regs + VIDOSD_C(win_no, sfb->variant)); 459ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } else 460c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(data, regs + VIDOSD_C(win_no, sfb->variant)); 461ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 462ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data = WINCONx_ENWIN; 463ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 464ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* note, since we have to round up the bits-per-pixel, we end up 465ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * relying on the bitfield information for r/g/b/a to work out 466ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * exactly which mode of operation is intended. */ 467ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 468ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks switch (var->bits_per_pixel) { 469ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 1: 470ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCON0_BPPMODE_1BPP; 471ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCONx_BITSWP; 472ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCONx_BURSTLEN_4WORD; 473ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 474ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 2: 475ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCON0_BPPMODE_2BPP; 476ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCONx_BITSWP; 477ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCONx_BURSTLEN_8WORD; 478ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 479ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 4: 480ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCON0_BPPMODE_4BPP; 481ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCONx_BITSWP; 482ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCONx_BURSTLEN_8WORD; 483ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 484ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 8: 485ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (var->transp.length != 0) 486ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCON1_BPPMODE_8BPP_1232; 487ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks else 488ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCON0_BPPMODE_8BPP_PALETTE; 489ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCONx_BURSTLEN_8WORD; 490ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCONx_BYTSWP; 491ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 492ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 16: 493ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (var->transp.length != 0) 494ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCON1_BPPMODE_16BPP_A1555; 495ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks else 496ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCON0_BPPMODE_16BPP_565; 497ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCONx_HAWSWP; 498ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCONx_BURSTLEN_16WORD; 499ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 500ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 24: 501ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case 32: 502ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (var->red.length == 6) { 503ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (var->transp.length != 0) 504ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCON1_BPPMODE_19BPP_A1666; 505ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks else 506ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCON1_BPPMODE_18BPP_666; 50739000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae } else if (var->transp.length == 1) 50839000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae data |= WINCON1_BPPMODE_25BPP_A1888 50939000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae | WINCON1_BLD_PIX; 51039000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae else if (var->transp.length == 4) 51139000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae data |= WINCON1_BPPMODE_28BPP_A4888 51239000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; 513ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks else 514ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCON0_BPPMODE_24BPP_888; 515ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 516dc8498c00f6a41a28f01111a3d2ed9f179356a71InKi Dae data |= WINCONx_WSWP; 517ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks data |= WINCONx_BURSTLEN_16WORD; 518ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 519ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 520ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 521c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks /* Enable the colour keying for the window below this one */ 52239000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae if (win_no > 0) { 52339000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae u32 keycon0_data = 0, keycon1_data = 0; 524c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks void __iomem *keycon = regs + sfb->variant.keycon; 52539000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae 52639000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae keycon0_data = ~(WxKEYCON0_KEYBL_EN | 52739000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae WxKEYCON0_KEYEN_F | 52839000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0); 52939000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae 53039000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae keycon1_data = WxKEYCON1_COLVAL(0xffffff); 53139000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae 532c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks keycon += (win_no - 1) * 8; 533c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks 534c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(keycon0_data, keycon + WKEYCON0); 535c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(keycon1_data, keycon + WKEYCON1); 53639000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae } 53739000d654c2a22ca51fe92a39003d5fade59e9e4InKi Dae 538c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(data, regs + sfb->variant.wincon + (win_no * 4)); 539c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(0x0, regs + sfb->variant.winmap + (win_no * 4)); 540ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 541ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return 0; 542ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 543ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 544ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 545ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_update_palette() - set or schedule a palette update. 546ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The hardware information. 547ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window being updated. 548ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @reg: The palette index being changed. 549ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @value: The computed palette value. 550ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 551ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Change the value of a palette register, either by directly writing to 552ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * the palette (this requires the palette RAM to be disconnected from the 553ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * hardware whilst this is in progress) or schedule the update for later. 554ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 555ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * At the moment, since we have no VSYNC interrupt support, we simply set 556ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * the palette entry directly. 557ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 558ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_update_palette(struct s3c_fb *sfb, 559ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_win *win, 560ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks unsigned int reg, 561ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks u32 value) 562ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 563ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks void __iomem *palreg; 564ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks u32 palcon; 565ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 56650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks palreg = sfb->regs + sfb->variant.palette[win->index]; 567ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 568ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n", 569ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks __func__, win->index, reg, palreg, value); 570ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 571ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks win->palette_buffer[reg] = value; 572ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 573ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks palcon = readl(sfb->regs + WPALCON); 574ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON); 575ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 57650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks if (win->variant.palette_16bpp) 57750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks writew(value, palreg + (reg * 2)); 578ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks else 57950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks writel(value, palreg + (reg * 4)); 580ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 581ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks writel(palcon, sfb->regs + WPALCON); 582ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 583ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 584ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic inline unsigned int chan_to_field(unsigned int chan, 585ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct fb_bitfield *bf) 586ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 587ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks chan &= 0xffff; 588ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks chan >>= 16 - bf->length; 589ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return chan << bf->offset; 590ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 591ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 592ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 593ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_setcolreg() - framebuffer layer request to change palette. 594ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @regno: The palette index to change. 595ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @red: The red field for the palette data. 596ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @green: The green field for the palette data. 597ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @blue: The blue field for the palette data. 598ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @trans: The transparency (alpha) field for the palette data. 599ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @info: The framebuffer being changed. 600ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 601ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_setcolreg(unsigned regno, 602ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks unsigned red, unsigned green, unsigned blue, 603ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks unsigned transp, struct fb_info *info) 604ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 605ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_win *win = info->par; 606ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb *sfb = win->parent; 607ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks unsigned int val; 608ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 609ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n", 610ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks __func__, win->index, regno, red, green, blue); 611ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 612ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks switch (info->fix.visual) { 613ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case FB_VISUAL_TRUECOLOR: 614ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* true-colour, use pseudo-palette */ 615ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 616ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (regno < 16) { 617ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks u32 *pal = info->pseudo_palette; 618ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 619ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks val = chan_to_field(red, &info->var.red); 620ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks val |= chan_to_field(green, &info->var.green); 621ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks val |= chan_to_field(blue, &info->var.blue); 622ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 623ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks pal[regno] = val; 624ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 625ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 626ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 627ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case FB_VISUAL_PSEUDOCOLOR: 62850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks if (regno < win->variant.palette_sz) { 629ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks val = chan_to_field(red, &win->palette.r); 630ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks val |= chan_to_field(green, &win->palette.g); 631ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks val |= chan_to_field(blue, &win->palette.b); 632ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 633ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks s3c_fb_update_palette(sfb, win, regno, val); 634ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 635ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 636ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 637ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 638ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks default: 639ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return 1; /* unknown type */ 640ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 641ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 642ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return 0; 643ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 644ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 645ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 646ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_enable() - Set the state of the main LCD output 647ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The main framebuffer state. 648ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @enable: The state to set. 649ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 650ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_enable(struct s3c_fb *sfb, int enable) 651ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 652ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks u32 vidcon0 = readl(sfb->regs + VIDCON0); 653ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 654ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (enable) 655ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F; 656ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks else { 657ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* see the note in the framebuffer datasheet about 658ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * why you cannot take both of these bits down at the 659ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * same time. */ 660ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 661ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (!(vidcon0 & VIDCON0_ENVID)) 662ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return; 663ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 664ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks vidcon0 |= VIDCON0_ENVID; 665ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks vidcon0 &= ~VIDCON0_ENVID_F; 666ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 667ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 668ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks writel(vidcon0, sfb->regs + VIDCON0); 669ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 670ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 671ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 672ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_blank() - blank or unblank the given window 673ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @blank_mode: The blank state from FB_BLANK_* 674ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @info: The framebuffer to blank. 675ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 676ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Framebuffer layer request to change the power state. 677ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 678ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_blank(int blank_mode, struct fb_info *info) 679ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 680ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_win *win = info->par; 681ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb *sfb = win->parent; 682ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks unsigned int index = win->index; 683ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks u32 wincon; 684ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 685ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); 686ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 687c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4)); 688ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 689ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks switch (blank_mode) { 690ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case FB_BLANK_POWERDOWN: 691ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks wincon &= ~WINCONx_ENWIN; 692ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks sfb->enabled &= ~(1 << index); 693ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* fall through to FB_BLANK_NORMAL */ 694ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 695ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case FB_BLANK_NORMAL: 696ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* disable the DMA and display 0x0 (black) */ 697ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0), 698c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks sfb->regs + sfb->variant.winmap + (index * 4)); 699ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 700ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 701ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case FB_BLANK_UNBLANK: 702c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4)); 703ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks wincon |= WINCONx_ENWIN; 704ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks sfb->enabled |= (1 << index); 705ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks break; 706ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 707ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case FB_BLANK_VSYNC_SUSPEND: 708ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks case FB_BLANK_HSYNC_SUSPEND: 709ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks default: 710ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return 1; 711ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 712ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 713c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4)); 714ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 715ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* Check the enabled state to see if we need to be running the 716ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * main LCD interface, as if there are no active windows then 717ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * it is highly likely that we also do not need to output 718ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * anything. 719ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 720ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 721ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* We could do something like the following code, but the current 722ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * system of using framebuffer events means that we cannot make 723ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * the distinction between just window 0 being inactive and all 724ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * the windows being down. 725ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 726ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_enable(sfb, sfb->enabled ? 1 : 0); 727ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 728ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 729ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* we're stuck with this until we can do something about overriding 730ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * the power control using the blanking event for a single fb. 731ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 732ad04490a171915737c9b99d2fa5cb813830f24c1InKi Dae if (index == sfb->pdata->default_win) 733ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); 734ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 735ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return 0; 736ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 737ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 738ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic struct fb_ops s3c_fb_ops = { 739ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .owner = THIS_MODULE, 740ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .fb_check_var = s3c_fb_check_var, 741ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .fb_set_par = s3c_fb_set_par, 742ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .fb_blank = s3c_fb_blank, 743ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .fb_setcolreg = s3c_fb_setcolreg, 744ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .fb_fillrect = cfb_fillrect, 745ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .fb_copyarea = cfb_copyarea, 746ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .fb_imageblit = cfb_imageblit, 747ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}; 748ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 749ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 750ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_alloc_memory() - allocate display memory for framebuffer window 751ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The base resources for the hardware. 752ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window to initialise memory for. 753ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 754ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Allocate memory for the given framebuffer. 755ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 756ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb, 757ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_win *win) 758ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 759ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_pd_win *windata = win->windata; 760ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks unsigned int real_size, virt_size, size; 761ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct fb_info *fbi = win->fbinfo; 762ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dma_addr_t map_dma; 763ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 764ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "allocating memory for display\n"); 765ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 766ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks real_size = windata->win_mode.xres * windata->win_mode.yres; 767ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks virt_size = windata->virtual_x * windata->virtual_y; 768ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 769ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n", 770ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks real_size, windata->win_mode.xres, windata->win_mode.yres, 771ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks virt_size, windata->virtual_x, windata->virtual_y); 772ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 773ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks size = (real_size > virt_size) ? real_size : virt_size; 774ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks size *= (windata->max_bpp > 16) ? 32 : windata->max_bpp; 775ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks size /= 8; 776ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 777ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbi->fix.smem_len = size; 778ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks size = PAGE_ALIGN(size); 779ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 780ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "want %u bytes for window\n", size); 781ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 782ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbi->screen_base = dma_alloc_writecombine(sfb->dev, size, 783ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks &map_dma, GFP_KERNEL); 784ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (!fbi->screen_base) 785ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return -ENOMEM; 786ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 787ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "mapped %x to %p\n", 788ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks (unsigned int)map_dma, fbi->screen_base); 789ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 790ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks memset(fbi->screen_base, 0x0, size); 791ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbi->fix.smem_start = map_dma; 792ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 793ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return 0; 794ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 795ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 796ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 797ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_free_memory() - free the display memory for the given window 798ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The base resources for the hardware. 799ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window to free the display memory for. 800ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 801ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Free the display memory allocated by s3c_fb_alloc_memory(). 802ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 803ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win) 804ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 805ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct fb_info *fbi = win->fbinfo; 806ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 807ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len), 808ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbi->screen_base, fbi->fix.smem_start); 809ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 810ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 811ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 812ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_release_win() - release resources for a framebuffer window. 813ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window to cleanup the resources for. 814ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 815ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Release the resources that where claimed for the hardware window, 816ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * such as the framebuffer instance and any memory claimed for it. 817ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 818ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win) 819ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 820ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt if (win->fbinfo) { 821ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt unregister_framebuffer(win->fbinfo); 822ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt fb_dealloc_cmap(&win->fbinfo->cmap); 823ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt s3c_fb_free_memory(sfb, win); 824ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt framebuffer_release(win->fbinfo); 825ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt } 826ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 827ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 828ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 829ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_probe_win() - register an hardware window 830ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The base resources for the hardware 83150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks * @variant: The variant information for this window. 832ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @res: Pointer to where to place the resultant window. 833ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 834ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Allocate and do the basic initialisation for one of the hardware's graphics 835ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * windows. 836ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 837ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, 83850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks struct s3c_fb_win_variant *variant, 839ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_win **res) 840ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 841ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct fb_var_screeninfo *var; 842ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct fb_videomode *initmode; 843ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_pd_win *windata; 844ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_win *win; 845ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct fb_info *fbinfo; 846ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks int palette_size; 847ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks int ret; 848ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 849c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks dev_dbg(sfb->dev, "probing window %d, variant %p\n", win_no, variant); 850ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 85150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks palette_size = variant->palette_sz * 4; 852ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 853ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) + 854ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks palette_size * sizeof(u32), sfb->dev); 855ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (!fbinfo) { 856ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(sfb->dev, "failed to allocate framebuffer\n"); 857ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return -ENOENT; 858ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 859ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 860ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks windata = sfb->pdata->win[win_no]; 861ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks initmode = &windata->win_mode; 862ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 863ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks WARN_ON(windata->max_bpp == 0); 864ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks WARN_ON(windata->win_mode.xres == 0); 865ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks WARN_ON(windata->win_mode.yres == 0); 866ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 867ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks win = fbinfo->par; 868ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks var = &fbinfo->var; 86950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks win->variant = *variant; 870ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks win->fbinfo = fbinfo; 871ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks win->parent = sfb; 872ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks win->windata = windata; 873ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks win->index = win_no; 874ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks win->palette_buffer = (u32 *)(win + 1); 875ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 876ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks ret = s3c_fb_alloc_memory(sfb, win); 877ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (ret) { 878ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(sfb->dev, "failed to allocate display memory\n"); 879ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt return ret; 880ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 881ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 882ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* setup the r/b/g positions for the window's palette */ 883bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks if (win->variant.palette_16bpp) { 884bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks /* Set RGB 5:6:5 as default */ 885bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks win->palette.r.offset = 11; 886bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks win->palette.r.length = 5; 887bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks win->palette.g.offset = 5; 888bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks win->palette.g.length = 6; 889bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks win->palette.b.offset = 0; 890bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks win->palette.b.length = 5; 891bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks 892bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks } else { 893bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks /* Set 8bpp or 8bpp and 1bit alpha */ 894bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks win->palette.r.offset = 16; 895bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks win->palette.r.length = 8; 896bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks win->palette.g.offset = 8; 897bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks win->palette.g.length = 8; 898bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks win->palette.b.offset = 0; 899bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks win->palette.b.length = 8; 900bc2da1b6fb1a8af9a3226a4f5db3ce32a0a192c9Ben Dooks } 901ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 902ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* setup the initial video mode from the window */ 903ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fb_videomode_to_var(&fbinfo->var, initmode); 904ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 905ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; 906ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbinfo->fix.accel = FB_ACCEL_NONE; 907ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbinfo->var.activate = FB_ACTIVATE_NOW; 908ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbinfo->var.vmode = FB_VMODE_NONINTERLACED; 909ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbinfo->var.bits_per_pixel = windata->default_bpp; 910ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbinfo->fbops = &s3c_fb_ops; 911ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbinfo->flags = FBINFO_FLAG_DEFAULT; 912ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fbinfo->pseudo_palette = &win->pseudo_palette; 913ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 914ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* prepare to actually start the framebuffer */ 915ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 916ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks ret = s3c_fb_check_var(&fbinfo->var, fbinfo); 917ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (ret < 0) { 918ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(sfb->dev, "check_var failed on initial video params\n"); 919ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt return ret; 920ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 921ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 922ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* create initial colour map */ 923ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 92450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks ret = fb_alloc_cmap(&fbinfo->cmap, win->variant.palette_sz, 1); 925ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (ret == 0) 926ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks fb_set_cmap(&fbinfo->cmap, fbinfo); 927ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks else 928ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(sfb->dev, "failed to allocate fb cmap\n"); 929ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 930ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks s3c_fb_set_par(fbinfo); 931ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 932ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(sfb->dev, "about to register framebuffer\n"); 933ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 934ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* run the check_var and set_par on our configuration. */ 935ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 936ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks ret = register_framebuffer(fbinfo); 937ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (ret < 0) { 938ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(sfb->dev, "failed to register framebuffer\n"); 939ddc518d9f88d7cf82bd974737ce977193785335dKrzysztof Helt return ret; 940ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 941ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 942ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks *res = win; 943ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id); 944ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 945ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return 0; 946ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 947ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 948ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 949ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_clear_win() - clear hardware window registers. 950ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @sfb: The base resources for the hardware. 951ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @win: The window to process. 952ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 953ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Reset the specific window registers to a known state. 954ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 955ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void s3c_fb_clear_win(struct s3c_fb *sfb, int win) 956ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 957ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks void __iomem *regs = sfb->regs; 958ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 959c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(0, regs + sfb->variant.wincon + (win * 4)); 960c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(0, regs + VIDOSD_A(win, sfb->variant)); 961c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(0, regs + VIDOSD_B(win, sfb->variant)); 962c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(0, regs + VIDOSD_C(win, sfb->variant)); 963ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 964ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 965ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __devinit s3c_fb_probe(struct platform_device *pdev) 966ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 96750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks struct s3c_fb_driverdata *fbdrv; 968ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct device *dev = &pdev->dev; 969ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_platdata *pd; 970ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb *sfb; 971ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct resource *res; 972ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks int win; 973ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks int ret = 0; 974ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 97550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks fbdrv = (struct s3c_fb_driverdata *)platform_get_device_id(pdev)->driver_data; 97650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 97750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) { 97850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks dev_err(dev, "too many windows, cannot attach\n"); 97950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks return -EINVAL; 98050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks } 98150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 982ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks pd = pdev->dev.platform_data; 983ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (!pd) { 984ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(dev, "no platform data specified\n"); 985ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return -EINVAL; 986ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 987ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 988ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks sfb = kzalloc(sizeof(struct s3c_fb), GFP_KERNEL); 989ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (!sfb) { 990ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(dev, "no memory for framebuffers\n"); 991ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return -ENOMEM; 992ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 993ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 994c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks dev_dbg(dev, "allocate new framebuffer %p\n", sfb); 995c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks 996ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks sfb->dev = dev; 997ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks sfb->pdata = pd; 99850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks sfb->variant = fbdrv->variant; 999ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1000ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks sfb->bus_clk = clk_get(dev, "lcd"); 1001ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (IS_ERR(sfb->bus_clk)) { 1002ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(dev, "failed to get bus clock\n"); 1003ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks goto err_sfb; 1004ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 1005ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1006ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks clk_enable(sfb->bus_clk); 1007ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1008ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1009ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (!res) { 1010ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(dev, "failed to find registers\n"); 1011ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks ret = -ENOENT; 1012ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks goto err_clk; 1013ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 1014ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1015ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks sfb->regs_res = request_mem_region(res->start, resource_size(res), 1016ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_name(dev)); 1017ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (!sfb->regs_res) { 1018ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(dev, "failed to claim register region\n"); 1019ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks ret = -ENOENT; 1020ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks goto err_clk; 1021ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 1022ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1023ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks sfb->regs = ioremap(res->start, resource_size(res)); 1024ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (!sfb->regs) { 1025ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(dev, "failed to map registers\n"); 1026ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks ret = -ENXIO; 1027ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks goto err_req_region; 1028ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 1029ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1030ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); 1031ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1032ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* setup gpio and output polarity controls */ 1033ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1034ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks pd->setup_gpio(); 1035ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1036ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks writel(pd->vidcon1, sfb->regs + VIDCON1); 1037ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1038ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* zero all windows before we do anything */ 1039ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 104050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks for (win = 0; win < fbdrv->variant.nr_windows; win++) 1041ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks s3c_fb_clear_win(sfb, win); 1042ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1043949470375393e82dc9158d36d675180c8c250388Ben Dooks /* initialise colour key controls */ 104450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks for (win = 0; win < (fbdrv->variant.nr_windows - 1); win++) { 1045c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks void __iomem *regs = sfb->regs + sfb->variant.keycon; 1046c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks 1047c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks regs += (win * 8); 1048c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(0xffffff, regs + WKEYCON0); 1049c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(0xffffff, regs + WKEYCON1); 1050949470375393e82dc9158d36d675180c8c250388Ben Dooks } 1051949470375393e82dc9158d36d675180c8c250388Ben Dooks 1052ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* we have the register setup, start allocating framebuffers */ 1053ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 105450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks for (win = 0; win < fbdrv->variant.nr_windows; win++) { 1055ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (!pd->win[win]) 1056ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks continue; 1057ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 105850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win], 105950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks &sfb->windows[win]); 1060ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (ret < 0) { 1061ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_err(dev, "failed to create window %d\n", win); 1062ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks for (; win >= 0; win--) 1063ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks s3c_fb_release_win(sfb, sfb->windows[win]); 1064ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks goto err_ioremap; 1065ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 1066ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 1067ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1068ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks platform_set_drvdata(pdev, sfb); 1069ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1070ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return 0; 1071ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1072ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dookserr_ioremap: 1073ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks iounmap(sfb->regs); 1074ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1075ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dookserr_req_region: 1076ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks release_resource(sfb->regs_res); 1077ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks kfree(sfb->regs_res); 1078ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1079ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dookserr_clk: 1080ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks clk_disable(sfb->bus_clk); 1081ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks clk_put(sfb->bus_clk); 1082ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1083ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dookserr_sfb: 1084ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks kfree(sfb); 1085ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return ret; 1086ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 1087ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1088ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks/** 1089ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * s3c_fb_remove() - Cleanup on module finalisation 1090ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * @pdev: The platform device we are bound to. 1091ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * 1092ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * Shutdown and then release all the resources that the driver allocated 1093ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks * on initialisation. 1094ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks */ 1095ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __devexit s3c_fb_remove(struct platform_device *pdev) 1096ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 1097ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb *sfb = platform_get_drvdata(pdev); 1098ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks int win; 1099ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1100c42b110caeb128819104d057acdaa1ae564b7c8dPawel Osciak for (win = 0; win < S3C_FB_MAX_WIN; win++) 110117663e59704bea838a9236f299104e30909a43b1Marek Szyprowski if (sfb->windows[win]) 110217663e59704bea838a9236f299104e30909a43b1Marek Szyprowski s3c_fb_release_win(sfb, sfb->windows[win]); 1103ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1104ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks iounmap(sfb->regs); 1105ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1106ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks clk_disable(sfb->bus_clk); 1107ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks clk_put(sfb->bus_clk); 1108ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1109ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks release_resource(sfb->regs_res); 1110ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks kfree(sfb->regs_res); 1111ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1112ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks kfree(sfb); 1113ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1114ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return 0; 1115ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 1116ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1117ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#ifdef CONFIG_PM 1118ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state) 1119ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 1120ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb *sfb = platform_get_drvdata(pdev); 1121ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_win *win; 1122ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks int win_no; 1123ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1124c42b110caeb128819104d057acdaa1ae564b7c8dPawel Osciak for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) { 1125ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks win = sfb->windows[win_no]; 1126ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (!win) 1127ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks continue; 1128ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1129ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks /* use the blank function to push into power-down */ 1130ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); 1131ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 1132ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1133ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks clk_disable(sfb->bus_clk); 1134ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return 0; 1135ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 1136ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1137ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int s3c_fb_resume(struct platform_device *pdev) 1138ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 1139ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb *sfb = platform_get_drvdata(pdev); 114017663e59704bea838a9236f299104e30909a43b1Marek Szyprowski struct s3c_fb_platdata *pd = sfb->pdata; 1141ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks struct s3c_fb_win *win; 1142ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks int win_no; 1143ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1144ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks clk_enable(sfb->bus_clk); 1145ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 114617663e59704bea838a9236f299104e30909a43b1Marek Szyprowski /* setup registers */ 114717663e59704bea838a9236f299104e30909a43b1Marek Szyprowski writel(pd->vidcon1, sfb->regs + VIDCON1); 114817663e59704bea838a9236f299104e30909a43b1Marek Szyprowski 114917663e59704bea838a9236f299104e30909a43b1Marek Szyprowski /* zero all windows before we do anything */ 115050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++) 115117663e59704bea838a9236f299104e30909a43b1Marek Szyprowski s3c_fb_clear_win(sfb, win_no); 115217663e59704bea838a9236f299104e30909a43b1Marek Szyprowski 115350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) { 1154c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks void __iomem *regs = sfb->regs + sfb->variant.keycon; 1155c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks 1156c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks regs += (win_no * 8); 1157c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(0xffffff, regs + WKEYCON0); 1158c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks writel(0xffffff, regs + WKEYCON1); 1159949470375393e82dc9158d36d675180c8c250388Ben Dooks } 1160949470375393e82dc9158d36d675180c8c250388Ben Dooks 116117663e59704bea838a9236f299104e30909a43b1Marek Szyprowski /* restore framebuffers */ 1162ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { 1163ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks win = sfb->windows[win_no]; 1164ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks if (!win) 1165ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks continue; 1166ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1167ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks dev_dbg(&pdev->dev, "resuming window %d\n", win_no); 1168ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks s3c_fb_set_par(win->fbinfo); 1169ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks } 1170ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1171ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return 0; 1172ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 1173ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#else 1174ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#define s3c_fb_suspend NULL 1175ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#define s3c_fb_resume NULL 1176ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks#endif 1177ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 117850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 117950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4)) 118050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8)) 118150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 118250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstatic struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] __devinitdata = { 118350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [0] = { 118450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .has_osd_c = 1, 118550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .palette_sz = 256, 118650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .valid_bpp = VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24), 118750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks }, 118850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [1] = { 118950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .has_osd_c = 1, 119050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .has_osd_d = 1, 119150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .palette_sz = 256, 119250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | 119350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks VALID_BPP(18) | VALID_BPP(19) | 119450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks VALID_BPP(24) | VALID_BPP(25)), 119550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks }, 119650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [2] = { 119750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .has_osd_c = 1, 119850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .has_osd_d = 1, 119950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .palette_sz = 16, 120050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .palette_16bpp = 1, 120150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | 120250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks VALID_BPP(18) | VALID_BPP(19) | 120350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks VALID_BPP(24) | VALID_BPP(25)), 120450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks }, 120550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [3] = { 120650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .has_osd_c = 1, 120750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .has_osd_d = 1, 120850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .palette_sz = 16, 120950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .palette_16bpp = 1, 121050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .valid_bpp = (VALID_BPP124 | VALID_BPP(16) | 121150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks VALID_BPP(18) | VALID_BPP(19) | 121250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks VALID_BPP(24) | VALID_BPP(25)), 121350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks }, 121450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [4] = { 121550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .has_osd_c = 1, 121650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .palette_sz = 4, 121750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .palette_16bpp = 1, 121850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .valid_bpp = (VALID_BPP(1) | VALID_BPP(2) | 121950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks VALID_BPP(16) | VALID_BPP(18) | 122050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks VALID_BPP(24) | VALID_BPP(25)), 122150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks }, 122250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks}; 122350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 122450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstatic struct s3c_fb_driverdata s3c_fb_data_64xx __devinitdata = { 122550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .variant = { 122650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .nr_windows = 5, 1227c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .vidtcon = VIDTCON0, 1228c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .wincon = WINCON(0), 1229c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .winmap = WINxMAP(0), 1230c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .keycon = WKEYCON, 1231c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .osd = VIDOSD_BASE, 1232c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .osd_stride = 16, 1233c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .buf_start = VIDW_BUF_START(0), 1234c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .buf_size = VIDW_BUF_SIZE(0), 1235c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .buf_end = VIDW_BUF_END(0), 123650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 123750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .palette = { 123850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [0] = 0x400, 123950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [1] = 0x800, 124050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [2] = 0x300, 124150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [3] = 0x320, 124250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [4] = 0x340, 124350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks }, 124450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks }, 124550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .win[0] = &s3c_fb_data_64xx_wins[0], 124650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .win[1] = &s3c_fb_data_64xx_wins[1], 124750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .win[2] = &s3c_fb_data_64xx_wins[2], 124850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .win[3] = &s3c_fb_data_64xx_wins[3], 124950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .win[4] = &s3c_fb_data_64xx_wins[4], 125050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks}; 125150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 125250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstatic struct s3c_fb_driverdata s3c_fb_data_s5p __devinitdata = { 125350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .variant = { 125450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .nr_windows = 5, 1255c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .vidtcon = VIDTCON0, 1256c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .wincon = WINCON(0), 1257c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .winmap = WINxMAP(0), 1258c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .keycon = WKEYCON, 1259c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .osd = VIDOSD_BASE, 1260c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .osd_stride = 16, 1261c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .buf_start = VIDW_BUF_START(0), 1262c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .buf_size = VIDW_BUF_SIZE(0), 1263c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .buf_end = VIDW_BUF_END(0), 126450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 126550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .palette = { 126650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [0] = 0x2400, 126750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [1] = 0x2800, 126850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [2] = 0x2c00, 126950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [3] = 0x3000, 127050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks [4] = 0x3400, 127150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks }, 127250a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks }, 127350a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .win[0] = &s3c_fb_data_64xx_wins[0], 127450a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .win[1] = &s3c_fb_data_64xx_wins[1], 127550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .win[2] = &s3c_fb_data_64xx_wins[2], 127650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .win[3] = &s3c_fb_data_64xx_wins[3], 127750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .win[4] = &s3c_fb_data_64xx_wins[4], 127850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks}; 127950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 1280c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks/* S3C2443/S3C2416 style hardware */ 1281c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooksstatic struct s3c_fb_driverdata s3c_fb_data_s3c2443 __devinitdata = { 1282c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .variant = { 1283c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .nr_windows = 2, 1284c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .is_2443 = 1, 1285c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks 1286c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .vidtcon = 0x08, 1287c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .wincon = 0x14, 1288c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .winmap = 0xd0, 1289c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .keycon = 0xb0, 1290c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .osd = 0x28, 1291c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .osd_stride = 12, 1292c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .buf_start = 0x64, 1293c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .buf_size = 0x94, 1294c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .buf_end = 0x7c, 1295c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks 1296c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .palette = { 1297c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks [0] = 0x400, 1298c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks [1] = 0x800, 1299c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks }, 1300c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks }, 1301c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .win[0] = &(struct s3c_fb_win_variant) { 1302c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .palette_sz = 256, 1303c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .valid_bpp = VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24), 1304c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks }, 1305c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .win[1] = &(struct s3c_fb_win_variant) { 1306c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .has_osd_c = 1, 1307c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .palette_sz = 256, 1308c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | 1309c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks VALID_BPP(18) | VALID_BPP(19) | 1310c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks VALID_BPP(24) | VALID_BPP(25) | 1311c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks VALID_BPP(28)), 1312c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks }, 1313c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks}; 1314c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks 131550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooksstatic struct platform_device_id s3c_fb_driver_ids[] = { 131650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks { 131750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .name = "s3c-fb", 131850a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .driver_data = (unsigned long)&s3c_fb_data_64xx, 131950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks }, { 132050a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .name = "s5p-fb", 132150a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .driver_data = (unsigned long)&s3c_fb_data_s5p, 1322c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks }, { 1323c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .name = "s3c2443-fb", 1324c4bb6ffa7754e8d0f8b24decd91de259b549fda1Ben Dooks .driver_data = (unsigned long)&s3c_fb_data_s3c2443, 132550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks }, 132650a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks {}, 132750a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks}; 132850a5503a9208420e6c59d24504a5e9913d603cf7Ben DooksMODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); 132950a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks 1330ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic struct platform_driver s3c_fb_driver = { 1331ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .probe = s3c_fb_probe, 13323163eaba34943967aebb1eefa0d4bdc4e5dc197cPeter Korsgaard .remove = __devexit_p(s3c_fb_remove), 1333ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .suspend = s3c_fb_suspend, 1334ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .resume = s3c_fb_resume, 133550a5503a9208420e6c59d24504a5e9913d603cf7Ben Dooks .id_table = s3c_fb_driver_ids, 1336ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .driver = { 1337ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .name = "s3c-fb", 1338ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks .owner = THIS_MODULE, 1339ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks }, 1340ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks}; 1341ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1342ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic int __init s3c_fb_init(void) 1343ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 1344ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks return platform_driver_register(&s3c_fb_driver); 1345ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 1346ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1347ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksstatic void __exit s3c_fb_cleanup(void) 1348ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks{ 1349ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks platform_driver_unregister(&s3c_fb_driver); 1350ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks} 1351ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1352ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksmodule_init(s3c_fb_init); 1353ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooksmodule_exit(s3c_fb_cleanup); 1354ec549a0fdc32171b26677f1ef0b5309faa743362Ben Dooks 1355ec549a0fdc32171b26677f1ef0b5309faa743362Ben DooksMODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 1356ec549a0fdc32171b26677f1ef0b5309faa743362Ben DooksMODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver"); 1357ec549a0fdc32171b26677f1ef0b5309faa743362Ben DooksMODULE_LICENSE("GPL"); 1358ec549a0fdc32171b26677f1ef0b5309faa743362Ben DooksMODULE_ALIAS("platform:s3c-fb"); 1359