diff options
author | Pete Popov <ppopov@embeddedalley.com> | 2005-04-03 21:06:19 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 14:31:01 -0400 |
commit | 3b495f2bb749b828499135743b9ddec46e34fda8 (patch) | |
tree | 5f787ed9829ef01a457428114ccd3547cf6c88da /drivers | |
parent | 172546bf601356f94f8018af7908a9b7c1c4915c (diff) |
Au1100 FB driver uplift for 2.6.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Acked-by: Antonino Daplas <adaplas@pol.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/au1100fb.c | 971 | ||||
-rw-r--r-- | drivers/video/au1100fb.h | 614 |
3 files changed, 810 insertions, 777 deletions
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 1fff29f48ca8..97c5d03ac8d9 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -86,7 +86,7 @@ obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o | |||
86 | obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o | 86 | obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o |
87 | obj-$(CONFIG_FB_PXA) += pxafb.o | 87 | obj-$(CONFIG_FB_PXA) += pxafb.o |
88 | obj-$(CONFIG_FB_W100) += w100fb.o | 88 | obj-$(CONFIG_FB_W100) += w100fb.o |
89 | obj-$(CONFIG_FB_AU1100) += au1100fb.o fbgen.o | 89 | obj-$(CONFIG_FB_AU1100) += au1100fb.o |
90 | obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o | 90 | obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o |
91 | obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o | 91 | obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o |
92 | obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o | 92 | obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o |
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index b6fe30c3ad62..a5129806172f 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c | |||
@@ -2,6 +2,11 @@ | |||
2 | * BRIEF MODULE DESCRIPTION | 2 | * BRIEF MODULE DESCRIPTION |
3 | * Au1100 LCD Driver. | 3 | * Au1100 LCD Driver. |
4 | * | 4 | * |
5 | * Rewritten for 2.6 by Embedded Alley Solutions | ||
6 | * <source@embeddedalley.com>, based on submissions by | ||
7 | * Karl Lessard <klessard@sunrisetelecom.com> | ||
8 | * <c.pellegrin@exadron.com> | ||
9 | * | ||
5 | * Copyright 2002 MontaVista Software | 10 | * Copyright 2002 MontaVista Software |
6 | * Author: MontaVista Software, Inc. | 11 | * Author: MontaVista Software, Inc. |
7 | * ppopov@mvista.com or source@mvista.com | 12 | * ppopov@mvista.com or source@mvista.com |
@@ -33,298 +38,253 @@ | |||
33 | * with this program; if not, write to the Free Software Foundation, Inc., | 38 | * with this program; if not, write to the Free Software Foundation, Inc., |
34 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 39 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
35 | */ | 40 | */ |
36 | 41 | #include <linux/config.h> | |
37 | #include <linux/module.h> | 42 | #include <linux/module.h> |
38 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
39 | #include <linux/errno.h> | 44 | #include <linux/errno.h> |
40 | #include <linux/string.h> | 45 | #include <linux/string.h> |
41 | #include <linux/mm.h> | 46 | #include <linux/mm.h> |
42 | #include <linux/tty.h> | ||
43 | #include <linux/slab.h> | ||
44 | #include <linux/delay.h> | ||
45 | #include <linux/fb.h> | 47 | #include <linux/fb.h> |
46 | #include <linux/init.h> | 48 | #include <linux/init.h> |
47 | #include <linux/pci.h> | 49 | #include <linux/interrupt.h> |
50 | #include <linux/ctype.h> | ||
51 | #include <linux/dma-mapping.h> | ||
48 | 52 | ||
49 | #include <asm/au1000.h> | 53 | #include <asm/mach-au1x00/au1000.h> |
50 | #include <asm/pb1100.h> | ||
51 | #include "au1100fb.h" | ||
52 | 54 | ||
53 | #include <video/fbcon.h> | 55 | #define DEBUG 0 |
54 | #include <video/fbcon-mfb.h> | 56 | |
55 | #include <video/fbcon-cfb2.h> | 57 | #include "au1100fb.h" |
56 | #include <video/fbcon-cfb4.h> | ||
57 | #include <video/fbcon-cfb8.h> | ||
58 | #include <video/fbcon-cfb16.h> | ||
59 | 58 | ||
60 | /* | 59 | /* |
61 | * Sanity check. If this is a new Au1100 based board, search for | 60 | * Sanity check. If this is a new Au1100 based board, search for |
62 | * the PB1100 ifdefs to make sure you modify the code accordingly. | 61 | * the PB1100 ifdefs to make sure you modify the code accordingly. |
63 | */ | 62 | */ |
64 | #if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_HYDROGEN3) | 63 | #if defined(CONFIG_MIPS_PB1100) |
64 | #include <asm/mach-pb1x00/pb1100.h> | ||
65 | #elif defined(CONFIG_MIPS_DB1100) | ||
66 | #include <asm/mach-db1x00/db1x00.h> | ||
65 | #else | 67 | #else |
66 | error Unknown Au1100 board | 68 | #error "Unknown Au1100 board, Au1100 FB driver not supported" |
67 | #endif | 69 | #endif |
68 | 70 | ||
69 | #define CMAPSIZE 16 | 71 | #define DRIVER_NAME "au1100fb" |
70 | 72 | #define DRIVER_DESC "LCD controller driver for AU1100 processors" | |
71 | static int my_lcd_index; /* default is zero */ | ||
72 | struct known_lcd_panels *p_lcd; | ||
73 | AU1100_LCD *p_lcd_reg = (AU1100_LCD *)AU1100_LCD_ADDR; | ||
74 | |||
75 | struct au1100fb_info { | ||
76 | struct fb_info_gen gen; | ||
77 | unsigned long fb_virt_start; | ||
78 | unsigned long fb_size; | ||
79 | unsigned long fb_phys; | ||
80 | int mmaped; | ||
81 | int nohwcursor; | ||
82 | 73 | ||
83 | struct { unsigned red, green, blue, pad; } palette[256]; | 74 | #define to_au1100fb_device(_info) \ |
75 | (_info ? container_of(_info, struct au1100fb_device, info) : NULL); | ||
84 | 76 | ||
85 | #if defined(FBCON_HAS_CFB16) | 77 | /* Bitfields format supported by the controller. Note that the order of formats |
86 | u16 fbcon_cmap16[16]; | 78 | * SHOULD be the same as in the LCD_CONTROL_SBPPF field, so we can retrieve the |
87 | #endif | 79 | * right pixel format by doing rgb_bitfields[LCD_CONTROL_SBPPF_XXX >> LCD_CONTROL_SBPPF] |
80 | */ | ||
81 | struct fb_bitfield rgb_bitfields[][4] = | ||
82 | { | ||
83 | /* Red, Green, Blue, Transp */ | ||
84 | { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
85 | { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
86 | { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } }, | ||
87 | { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } }, | ||
88 | { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } }, | ||
89 | |||
90 | /* The last is used to describe 12bpp format */ | ||
91 | { { 8, 4, 0 }, { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } }, | ||
88 | }; | 92 | }; |
89 | 93 | ||
90 | 94 | static struct fb_fix_screeninfo au1100fb_fix __initdata = { | |
91 | struct au1100fb_par { | 95 | .id = "AU1100 FB", |
92 | struct fb_var_screeninfo var; | 96 | .xpanstep = 1, |
93 | 97 | .ypanstep = 1, | |
94 | int line_length; // in bytes | 98 | .type = FB_TYPE_PACKED_PIXELS, |
95 | int cmap_len; // color-map length | 99 | .accel = FB_ACCEL_NONE, |
96 | }; | 100 | }; |
97 | 101 | ||
98 | 102 | static struct fb_var_screeninfo au1100fb_var __initdata = { | |
99 | static struct au1100fb_info fb_info; | 103 | .activate = FB_ACTIVATE_NOW, |
100 | static struct au1100fb_par current_par; | 104 | .height = -1, |
101 | static struct display disp; | 105 | .width = -1, |
102 | 106 | .vmode = FB_VMODE_NONINTERLACED, | |
103 | int au1100fb_init(void); | ||
104 | void au1100fb_setup(char *options, int *ints); | ||
105 | static int au1100fb_mmap(struct fb_info *fb, struct file *file, | ||
106 | struct vm_area_struct *vma); | ||
107 | static int au1100_blank(int blank_mode, struct fb_info_gen *info); | ||
108 | static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd, | ||
109 | u_long arg, int con, struct fb_info *info); | ||
110 | |||
111 | void au1100_nocursor(struct display *p, int mode, int xx, int yy){}; | ||
112 | |||
113 | static struct fb_ops au1100fb_ops = { | ||
114 | .owner = THIS_MODULE, | ||
115 | .fb_get_fix = fbgen_get_fix, | ||
116 | .fb_get_var = fbgen_get_var, | ||
117 | .fb_set_var = fbgen_set_var, | ||
118 | .fb_get_cmap = fbgen_get_cmap, | ||
119 | .fb_set_cmap = fbgen_set_cmap, | ||
120 | .fb_pan_display = fbgen_pan_display, | ||
121 | .fb_ioctl = au1100fb_ioctl, | ||
122 | .fb_mmap = au1100fb_mmap, | ||
123 | }; | 107 | }; |
124 | 108 | ||
125 | static void au1100_detect(void) | 109 | static struct au1100fb_drv_info drv_info; |
126 | { | ||
127 | /* | ||
128 | * This function should detect the current video mode settings | ||
129 | * and store it as the default video mode | ||
130 | */ | ||
131 | 110 | ||
132 | /* | 111 | /* |
133 | * Yeh, well, we're not going to change any settings so we're | 112 | * Set hardware with var settings. This will enable the controller with a specific |
134 | * always stuck with the default ... | 113 | * mode, normally validated with the fb_check_var method |
135 | */ | 114 | */ |
136 | 115 | int au1100fb_setmode(struct au1100fb_device *fbdev) | |
137 | } | ||
138 | |||
139 | static int au1100_encode_fix(struct fb_fix_screeninfo *fix, | ||
140 | const void *_par, struct fb_info_gen *_info) | ||
141 | { | 116 | { |
142 | struct au1100fb_info *info = (struct au1100fb_info *) _info; | 117 | struct fb_info *info = &fbdev->info; |
143 | struct au1100fb_par *par = (struct au1100fb_par *) _par; | 118 | u32 words; |
144 | struct fb_var_screeninfo *var = &par->var; | 119 | int index; |
145 | |||
146 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | ||
147 | |||
148 | fix->smem_start = info->fb_phys; | ||
149 | fix->smem_len = info->fb_size; | ||
150 | fix->type = FB_TYPE_PACKED_PIXELS; | ||
151 | fix->type_aux = 0; | ||
152 | fix->visual = (var->bits_per_pixel == 8) ? | ||
153 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | ||
154 | fix->ywrapstep = 0; | ||
155 | fix->xpanstep = 1; | ||
156 | fix->ypanstep = 1; | ||
157 | fix->line_length = current_par.line_length; | ||
158 | return 0; | ||
159 | } | ||
160 | 120 | ||
161 | static void set_color_bitfields(struct fb_var_screeninfo *var) | 121 | if (!fbdev) |
162 | { | 122 | return -EINVAL; |
163 | switch (var->bits_per_pixel) { | 123 | |
164 | case 8: | 124 | /* Update var-dependent FB info */ |
165 | var->red.offset = 0; | 125 | if (panel_is_active(fbdev->panel) || panel_is_color(fbdev->panel)) { |
166 | var->red.length = 8; | 126 | if (info->var.bits_per_pixel <= 8) { |
167 | var->green.offset = 0; | 127 | /* palettized */ |
168 | var->green.length = 8; | 128 | info->var.red.offset = 0; |
169 | var->blue.offset = 0; | 129 | info->var.red.length = info->var.bits_per_pixel; |
170 | var->blue.length = 8; | 130 | info->var.red.msb_right = 0; |
171 | var->transp.offset = 0; | 131 | |
172 | var->transp.length = 0; | 132 | info->var.green.offset = 0; |
173 | break; | 133 | info->var.green.length = info->var.bits_per_pixel; |
174 | case 16: /* RGB 565 */ | 134 | info->var.green.msb_right = 0; |
175 | var->red.offset = 11; | 135 | |
176 | var->red.length = 5; | 136 | info->var.blue.offset = 0; |
177 | var->green.offset = 5; | 137 | info->var.blue.length = info->var.bits_per_pixel; |
178 | var->green.length = 6; | 138 | info->var.blue.msb_right = 0; |
179 | var->blue.offset = 0; | 139 | |
180 | var->blue.length = 5; | 140 | info->var.transp.offset = 0; |
181 | var->transp.offset = 0; | 141 | info->var.transp.length = 0; |
182 | var->transp.length = 0; | 142 | info->var.transp.msb_right = 0; |
183 | break; | 143 | |
144 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
145 | info->fix.line_length = info->var.xres_virtual / | ||
146 | (8/info->var.bits_per_pixel); | ||
147 | } else { | ||
148 | /* non-palettized */ | ||
149 | index = (fbdev->panel->control_base & LCD_CONTROL_SBPPF_MASK) >> LCD_CONTROL_SBPPF_BIT; | ||
150 | info->var.red = rgb_bitfields[index][0]; | ||
151 | info->var.green = rgb_bitfields[index][1]; | ||
152 | info->var.blue = rgb_bitfields[index][2]; | ||
153 | info->var.transp = rgb_bitfields[index][3]; | ||
154 | |||
155 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
156 | info->fix.line_length = info->var.xres_virtual << 1; /* depth=16 */ | ||
157 | } | ||
158 | } else { | ||
159 | /* mono */ | ||
160 | info->fix.visual = FB_VISUAL_MONO10; | ||
161 | info->fix.line_length = info->var.xres_virtual / 8; | ||
184 | } | 162 | } |
185 | 163 | ||
186 | var->red.msb_right = 0; | 164 | info->screen_size = info->fix.line_length * info->var.yres_virtual; |
187 | var->green.msb_right = 0; | ||
188 | var->blue.msb_right = 0; | ||
189 | var->transp.msb_right = 0; | ||
190 | } | ||
191 | 165 | ||
192 | static int au1100_decode_var(const struct fb_var_screeninfo *var, | 166 | /* Determine BPP mode and format */ |
193 | void *_par, struct fb_info_gen *_info) | 167 | fbdev->regs->lcd_control = fbdev->panel->control_base | |
194 | { | 168 | ((info->var.rotate/90) << LCD_CONTROL_SM_BIT); |
195 | 169 | ||
196 | struct au1100fb_par *par = (struct au1100fb_par *)_par; | 170 | fbdev->regs->lcd_intenable = 0; |
171 | fbdev->regs->lcd_intstatus = 0; | ||
197 | 172 | ||
198 | /* | 173 | fbdev->regs->lcd_horztiming = fbdev->panel->horztiming; |
199 | * Don't allow setting any of these yet: xres and yres don't | ||
200 | * make sense for LCD panels. | ||
201 | */ | ||
202 | if (var->xres != p_lcd->xres || | ||
203 | var->yres != p_lcd->yres || | ||
204 | var->xres != p_lcd->xres || | ||
205 | var->yres != p_lcd->yres) { | ||
206 | return -EINVAL; | ||
207 | } | ||
208 | if(var->bits_per_pixel != p_lcd->bpp) { | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | 174 | ||
212 | memset(par, 0, sizeof(struct au1100fb_par)); | 175 | fbdev->regs->lcd_verttiming = fbdev->panel->verttiming; |
213 | par->var = *var; | 176 | |
214 | 177 | fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base; | |
215 | /* FIXME */ | ||
216 | switch (var->bits_per_pixel) { | ||
217 | case 8: | ||
218 | par->var.bits_per_pixel = 8; | ||
219 | break; | ||
220 | case 16: | ||
221 | par->var.bits_per_pixel = 16; | ||
222 | break; | ||
223 | default: | ||
224 | printk("color depth %d bpp not supported\n", | ||
225 | var->bits_per_pixel); | ||
226 | return -EINVAL; | ||
227 | 178 | ||
179 | fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(fbdev->fb_phys); | ||
180 | |||
181 | if (panel_is_dual(fbdev->panel)) { | ||
182 | /* Second panel display seconf half of screen if possible, | ||
183 | * otherwise display the same as the first panel */ | ||
184 | if (info->var.yres_virtual >= (info->var.yres << 1)) { | ||
185 | fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys + | ||
186 | (info->fix.line_length * | ||
187 | (info->var.yres_virtual >> 1))); | ||
188 | } else { | ||
189 | fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys); | ||
190 | } | ||
228 | } | 191 | } |
229 | set_color_bitfields(&par->var); | ||
230 | par->cmap_len = (par->var.bits_per_pixel == 8) ? 256 : 16; | ||
231 | return 0; | ||
232 | } | ||
233 | 192 | ||
234 | static int au1100_encode_var(struct fb_var_screeninfo *var, | 193 | words = info->fix.line_length / sizeof(u32); |
235 | const void *par, struct fb_info_gen *_info) | 194 | if (!info->var.rotate || (info->var.rotate == 180)) { |
236 | { | 195 | words *= info->var.yres_virtual; |
196 | if (info->var.rotate /* 180 */) { | ||
197 | words -= (words % 8); /* should be divisable by 8 */ | ||
198 | } | ||
199 | } | ||
200 | fbdev->regs->lcd_words = LCD_WRD_WRDS_N(words); | ||
237 | 201 | ||
238 | *var = ((struct au1100fb_par *)par)->var; | 202 | fbdev->regs->lcd_pwmdiv = 0; |
239 | return 0; | 203 | fbdev->regs->lcd_pwmhi = 0; |
240 | } | ||
241 | 204 | ||
242 | static void | 205 | /* Resume controller */ |
243 | au1100_get_par(void *_par, struct fb_info_gen *_info) | 206 | fbdev->regs->lcd_control |= LCD_CONTROL_GO; |
244 | { | ||
245 | *(struct au1100fb_par *)_par = current_par; | ||
246 | } | ||
247 | 207 | ||
248 | static void au1100_set_par(const void *par, struct fb_info_gen *info) | 208 | return 0; |
249 | { | ||
250 | /* nothing to do: we don't change any settings */ | ||
251 | } | 209 | } |
252 | 210 | ||
253 | static int au1100_getcolreg(unsigned regno, unsigned *red, unsigned *green, | 211 | /* fb_setcolreg |
254 | unsigned *blue, unsigned *transp, | 212 | * Set color in LCD palette. |
255 | struct fb_info *info) | 213 | */ |
214 | int au1100fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi) | ||
256 | { | 215 | { |
216 | struct au1100fb_device *fbdev = to_au1100fb_device(fbi); | ||
217 | u32 *palette = fbdev->regs->lcd_pallettebase; | ||
218 | u32 value; | ||
257 | 219 | ||
258 | struct au1100fb_info* i = (struct au1100fb_info*)info; | 220 | if (regno > (AU1100_LCD_NBR_PALETTE_ENTRIES - 1)) |
259 | 221 | return -EINVAL; | |
260 | if (regno > 255) | ||
261 | return 1; | ||
262 | 222 | ||
263 | *red = i->palette[regno].red; | 223 | if (fbi->var.grayscale) { |
264 | *green = i->palette[regno].green; | 224 | /* Convert color to grayscale */ |
265 | *blue = i->palette[regno].blue; | 225 | red = green = blue = |
266 | *transp = 0; | 226 | (19595 * red + 38470 * green + 7471 * blue) >> 16; |
227 | } | ||
267 | 228 | ||
268 | return 0; | 229 | if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) { |
269 | } | 230 | /* Place color in the pseudopalette */ |
231 | if (regno > 16) | ||
232 | return -EINVAL; | ||
270 | 233 | ||
271 | static int au1100_setcolreg(unsigned regno, unsigned red, unsigned green, | 234 | palette = (u32*)fbi->pseudo_palette; |
272 | unsigned blue, unsigned transp, | 235 | |
273 | struct fb_info *info) | 236 | red >>= (16 - fbi->var.red.length); |
274 | { | 237 | green >>= (16 - fbi->var.green.length); |
275 | struct au1100fb_info* i = (struct au1100fb_info *)info; | 238 | blue >>= (16 - fbi->var.blue.length); |
276 | u32 rgbcol; | 239 | |
277 | 240 | value = (red << fbi->var.red.offset) | | |
278 | if (regno > 255) | 241 | (green << fbi->var.green.offset)| |
279 | return 1; | 242 | (blue << fbi->var.blue.offset); |
280 | 243 | value &= 0xFFFF; | |
281 | i->palette[regno].red = red; | 244 | |
282 | i->palette[regno].green = green; | 245 | } else if (panel_is_active(fbdev->panel)) { |
283 | i->palette[regno].blue = blue; | 246 | /* COLOR TFT PALLETTIZED (use RGB 565) */ |
284 | 247 | value = (red & 0xF800)|((green >> 5) & 0x07E0)|((blue >> 11) & 0x001F); | |
285 | switch(p_lcd->bpp) { | 248 | value &= 0xFFFF; |
286 | #ifdef FBCON_HAS_CFB8 | 249 | |
287 | case 8: | 250 | } else if (panel_is_color(fbdev->panel)) { |
288 | red >>= 10; | 251 | /* COLOR STN MODE */ |
289 | green >>= 10; | 252 | value = (((panel_swap_rgb(fbdev->panel) ? blue : red) >> 12) & 0x000F) | |
290 | blue >>= 10; | 253 | ((green >> 8) & 0x00F0) | |
291 | p_lcd_reg->lcd_pallettebase[regno] = (blue&0x1f) | | 254 | (((panel_swap_rgb(fbdev->panel) ? red : blue) >> 4) & 0x0F00); |
292 | ((green&0x3f)<<5) | ((red&0x1f)<<11); | 255 | value &= 0xFFF; |
293 | break; | 256 | } else { |
294 | #endif | 257 | /* MONOCHROME MODE */ |
295 | #ifdef FBCON_HAS_CFB16 | 258 | value = (green >> 12) & 0x000F; |
296 | case 16: | 259 | value &= 0xF; |
297 | i->fbcon_cmap16[regno] = | ||
298 | ((red & 0xf800) >> 0) | | ||
299 | ((green & 0xfc00) >> 5) | | ||
300 | ((blue & 0xf800) >> 11); | ||
301 | break; | ||
302 | #endif | ||
303 | default: | ||
304 | break; | ||
305 | } | 260 | } |
306 | 261 | ||
262 | palette[regno] = value; | ||
263 | |||
307 | return 0; | 264 | return 0; |
308 | } | 265 | } |
309 | 266 | ||
310 | 267 | /* fb_blank | |
311 | static int au1100_blank(int blank_mode, struct fb_info_gen *_info) | 268 | * Blank the screen. Depending on the mode, the screen will be |
269 | * activated with the backlight color, or desactivated | ||
270 | */ | ||
271 | int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) | ||
312 | { | 272 | { |
273 | struct au1100fb_device *fbdev = to_au1100fb_device(fbi); | ||
274 | |||
275 | print_dbg("fb_blank %d %p", blank_mode, fbi); | ||
313 | 276 | ||
314 | switch (blank_mode) { | 277 | switch (blank_mode) { |
278 | |||
315 | case VESA_NO_BLANKING: | 279 | case VESA_NO_BLANKING: |
316 | /* turn on panel */ | 280 | /* Turn on panel */ |
317 | //printk("turn on panel\n"); | 281 | fbdev->regs->lcd_control |= LCD_CONTROL_GO; |
318 | #ifdef CONFIG_MIPS_PB1100 | 282 | #ifdef CONFIG_MIPS_PB1100 |
319 | p_lcd_reg->lcd_control |= LCD_CONTROL_GO; | 283 | if (drv_info.panel_idx == 1) { |
320 | au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight, | 284 | au_writew(au_readw(PB1100_G_CONTROL) |
285 | | (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), | ||
321 | PB1100_G_CONTROL); | 286 | PB1100_G_CONTROL); |
322 | #endif | 287 | } |
323 | #ifdef CONFIG_MIPS_HYDROGEN3 | ||
324 | /* Turn controller & power supply on, GPIO213 */ | ||
325 | au_writel(0x20002000, 0xB1700008); | ||
326 | au_writel(0x00040000, 0xB1900108); | ||
327 | au_writel(0x01000100, 0xB1700008); | ||
328 | #endif | 288 | #endif |
329 | au_sync(); | 289 | au_sync(); |
330 | break; | 290 | break; |
@@ -332,12 +292,14 @@ static int au1100_blank(int blank_mode, struct fb_info_gen *_info) | |||
332 | case VESA_VSYNC_SUSPEND: | 292 | case VESA_VSYNC_SUSPEND: |
333 | case VESA_HSYNC_SUSPEND: | 293 | case VESA_HSYNC_SUSPEND: |
334 | case VESA_POWERDOWN: | 294 | case VESA_POWERDOWN: |
335 | /* turn off panel */ | 295 | /* Turn off panel */ |
336 | //printk("turn off panel\n"); | 296 | fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; |
337 | #ifdef CONFIG_MIPS_PB1100 | 297 | #ifdef CONFIG_MIPS_PB1100 |
338 | au_writew(au_readw(PB1100_G_CONTROL) & ~p_lcd->mode_backlight, | 298 | if (drv_info.panel_idx == 1) { |
299 | au_writew(au_readw(PB1100_G_CONTROL) | ||
300 | & ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), | ||
339 | PB1100_G_CONTROL); | 301 | PB1100_G_CONTROL); |
340 | p_lcd_reg->lcd_control &= ~LCD_CONTROL_GO; | 302 | } |
341 | #endif | 303 | #endif |
342 | au_sync(); | 304 | au_sync(); |
343 | break; | 305 | break; |
@@ -348,49 +310,87 @@ static int au1100_blank(int blank_mode, struct fb_info_gen *_info) | |||
348 | return 0; | 310 | return 0; |
349 | } | 311 | } |
350 | 312 | ||
351 | static void au1100_set_disp(const void *unused, struct display *disp, | 313 | /* fb_pan_display |
352 | struct fb_info_gen *info) | 314 | * Pan display in x and/or y as specified |
315 | */ | ||
316 | int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi) | ||
353 | { | 317 | { |
354 | disp->screen_base = (char *)fb_info.fb_virt_start; | 318 | struct au1100fb_device *fbdev = to_au1100fb_device(fbi); |
355 | 319 | int dy; | |
356 | switch (disp->var.bits_per_pixel) { | 320 | |
357 | #ifdef FBCON_HAS_CFB8 | 321 | print_dbg("fb_pan_display %p %p", var, fbi); |
358 | case 8: | 322 | |
359 | disp->dispsw = &fbcon_cfb8; | 323 | if (!var || !fbdev) { |
360 | if (fb_info.nohwcursor) | 324 | return -EINVAL; |
361 | fbcon_cfb8.cursor = au1100_nocursor; | 325 | } |
362 | break; | 326 | |
363 | #endif | 327 | if (var->xoffset - fbi->var.xoffset) { |
364 | #ifdef FBCON_HAS_CFB16 | 328 | /* No support for X panning for now! */ |
365 | case 16: | 329 | return -EINVAL; |
366 | disp->dispsw = &fbcon_cfb16; | 330 | } |
367 | disp->dispsw_data = fb_info.fbcon_cmap16; | 331 | |
368 | if (fb_info.nohwcursor) | 332 | print_dbg("fb_pan_display 2 %p %p", var, fbi); |
369 | fbcon_cfb16.cursor = au1100_nocursor; | 333 | dy = var->yoffset - fbi->var.yoffset; |
370 | break; | 334 | if (dy) { |
371 | #endif | 335 | |
372 | default: | 336 | u32 dmaaddr; |
373 | disp->dispsw = &fbcon_dummy; | 337 | |
374 | disp->dispsw_data = NULL; | 338 | print_dbg("Panning screen of %d lines", dy); |
375 | break; | 339 | |
340 | dmaaddr = fbdev->regs->lcd_dmaaddr0; | ||
341 | dmaaddr += (fbi->fix.line_length * dy); | ||
342 | |||
343 | /* TODO: Wait for current frame to finished */ | ||
344 | fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr); | ||
345 | |||
346 | if (panel_is_dual(fbdev->panel)) { | ||
347 | dmaaddr = fbdev->regs->lcd_dmaaddr1; | ||
348 | dmaaddr += (fbi->fix.line_length * dy); | ||
349 | fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr); | ||
350 | } | ||
351 | } | ||
352 | print_dbg("fb_pan_display 3 %p %p", var, fbi); | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | /* fb_rotate | ||
358 | * Rotate the display of this angle. This doesn't seems to be used by the core, | ||
359 | * but as our hardware supports it, so why not implementing it... | ||
360 | */ | ||
361 | void au1100fb_fb_rotate(struct fb_info *fbi, int angle) | ||
362 | { | ||
363 | struct au1100fb_device *fbdev = to_au1100fb_device(fbi); | ||
364 | |||
365 | print_dbg("fb_rotate %p %d", fbi, angle); | ||
366 | |||
367 | if (fbdev && (angle > 0) && !(angle % 90)) { | ||
368 | |||
369 | fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; | ||
370 | |||
371 | fbdev->regs->lcd_control &= ~(LCD_CONTROL_SM_MASK); | ||
372 | fbdev->regs->lcd_control |= ((angle/90) << LCD_CONTROL_SM_BIT); | ||
373 | |||
374 | fbdev->regs->lcd_control |= LCD_CONTROL_GO; | ||
376 | } | 375 | } |
377 | } | 376 | } |
378 | 377 | ||
379 | static int | 378 | /* fb_mmap |
380 | au1100fb_mmap(struct fb_info *_fb, | 379 | * Map video memory in user space. We don't use the generic fb_mmap method mainly |
381 | struct file *file, | 380 | * to allow the use of the TLB streaming flag (CCA=6) |
382 | struct vm_area_struct *vma) | 381 | */ |
382 | int au1100fb_fb_mmap(struct fb_info *fbi, struct file *file, struct vm_area_struct *vma) | ||
383 | { | 383 | { |
384 | struct au1100fb_device *fbdev = to_au1100fb_device(fbi); | ||
384 | unsigned int len; | 385 | unsigned int len; |
385 | unsigned long start=0, off; | 386 | unsigned long start=0, off; |
386 | struct au1100fb_info *fb = (struct au1100fb_info *)_fb; | ||
387 | 387 | ||
388 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { | 388 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { |
389 | return -EINVAL; | 389 | return -EINVAL; |
390 | } | 390 | } |
391 | 391 | ||
392 | start = fb_info.fb_phys & PAGE_MASK; | 392 | start = fbdev->fb_phys & PAGE_MASK; |
393 | len = PAGE_ALIGN((start & ~PAGE_MASK) + fb_info.fb_size); | 393 | len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); |
394 | 394 | ||
395 | off = vma->vm_pgoff << PAGE_SHIFT; | 395 | off = vma->vm_pgoff << PAGE_SHIFT; |
396 | 396 | ||
@@ -401,276 +401,309 @@ au1100fb_mmap(struct fb_info *_fb, | |||
401 | off += start; | 401 | off += start; |
402 | vma->vm_pgoff = off >> PAGE_SHIFT; | 402 | vma->vm_pgoff = off >> PAGE_SHIFT; |
403 | 403 | ||
404 | pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; | 404 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
405 | //pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; | ||
406 | pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6 | 405 | pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6 |
407 | 406 | ||
408 | /* This is an IO map - tell maydump to skip this VMA */ | ||
409 | vma->vm_flags |= VM_IO; | 407 | vma->vm_flags |= VM_IO; |
410 | 408 | ||
411 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, | 409 | if (io_remap_page_range(vma, vma->vm_start, off, |
412 | vma->vm_end - vma->vm_start, | 410 | vma->vm_end - vma->vm_start, |
413 | vma->vm_page_prot)) { | 411 | vma->vm_page_prot)) { |
414 | return -EAGAIN; | 412 | return -EAGAIN; |
415 | } | 413 | } |
416 | 414 | ||
417 | fb->mmaped = 1; | ||
418 | return 0; | 415 | return 0; |
419 | } | 416 | } |
420 | 417 | ||
421 | int au1100_pan_display(const struct fb_var_screeninfo *var, | 418 | static struct fb_ops au1100fb_ops = |
422 | struct fb_info_gen *info) | ||
423 | { | 419 | { |
424 | return 0; | 420 | .owner = THIS_MODULE, |
425 | } | 421 | .fb_setcolreg = au1100fb_fb_setcolreg, |
422 | .fb_blank = au1100fb_fb_blank, | ||
423 | .fb_pan_display = au1100fb_fb_pan_display, | ||
424 | .fb_fillrect = cfb_fillrect, | ||
425 | .fb_copyarea = cfb_copyarea, | ||
426 | .fb_imageblit = cfb_imageblit, | ||
427 | .fb_rotate = au1100fb_fb_rotate, | ||
428 | .fb_mmap = au1100fb_fb_mmap, | ||
429 | }; | ||
426 | 430 | ||
427 | static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd, | ||
428 | u_long arg, int con, struct fb_info *info) | ||
429 | { | ||
430 | /* nothing to do yet */ | ||
431 | return -EINVAL; | ||
432 | } | ||
433 | 431 | ||
434 | static struct fbgen_hwswitch au1100_switch = { | 432 | /*-------------------------------------------------------------------------*/ |
435 | au1100_detect, | ||
436 | au1100_encode_fix, | ||
437 | au1100_decode_var, | ||
438 | au1100_encode_var, | ||
439 | au1100_get_par, | ||
440 | au1100_set_par, | ||
441 | au1100_getcolreg, | ||
442 | au1100_setcolreg, | ||
443 | au1100_pan_display, | ||
444 | au1100_blank, | ||
445 | au1100_set_disp | ||
446 | }; | ||
447 | 433 | ||
434 | /* AU1100 LCD controller device driver */ | ||
448 | 435 | ||
449 | int au1100_setmode(void) | 436 | int au1100fb_drv_probe(struct device *dev) |
450 | { | 437 | { |
451 | int words; | 438 | struct au1100fb_device *fbdev = NULL; |
452 | 439 | struct resource *regs_res; | |
453 | /* FIXME Need to accomodate for swivel mode and 12bpp, <8bpp*/ | 440 | unsigned long page; |
454 | switch (p_lcd->mode_control & LCD_CONTROL_SM) | 441 | u32 sys_clksrc; |
455 | { | 442 | |
456 | case LCD_CONTROL_SM_0: | 443 | if (!dev) |
457 | case LCD_CONTROL_SM_180: | ||
458 | words = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 32; | ||
459 | break; | ||
460 | case LCD_CONTROL_SM_90: | ||
461 | case LCD_CONTROL_SM_270: | ||
462 | /* is this correct? */ | ||
463 | words = (p_lcd->xres * p_lcd->bpp) / 8; | ||
464 | break; | ||
465 | default: | ||
466 | printk("mode_control reg not initialized\n"); | ||
467 | return -EINVAL; | 444 | return -EINVAL; |
445 | |||
446 | /* Allocate new device private */ | ||
447 | if (!(fbdev = kmalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) { | ||
448 | print_err("fail to allocate device private record"); | ||
449 | return -ENOMEM; | ||
468 | } | 450 | } |
451 | memset((void*)fbdev, 0, sizeof(struct au1100fb_device)); | ||
469 | 452 | ||
470 | /* | 453 | fbdev->panel = &known_lcd_panels[drv_info.panel_idx]; |
471 | * Setup LCD controller | ||
472 | */ | ||
473 | 454 | ||
474 | p_lcd_reg->lcd_control = p_lcd->mode_control; | 455 | dev_set_drvdata(dev, (void*)fbdev); |
475 | p_lcd_reg->lcd_intstatus = 0; | ||
476 | p_lcd_reg->lcd_intenable = 0; | ||
477 | p_lcd_reg->lcd_horztiming = p_lcd->mode_horztiming; | ||
478 | p_lcd_reg->lcd_verttiming = p_lcd->mode_verttiming; | ||
479 | p_lcd_reg->lcd_clkcontrol = p_lcd->mode_clkcontrol; | ||
480 | p_lcd_reg->lcd_words = words - 1; | ||
481 | p_lcd_reg->lcd_dmaaddr0 = fb_info.fb_phys; | ||
482 | 456 | ||
483 | /* turn on panel */ | 457 | /* Allocate region for our registers and map them */ |
484 | #ifdef CONFIG_MIPS_PB1100 | 458 | if (!(regs_res = platform_get_resource(to_platform_device(dev), |
485 | au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight, | 459 | IORESOURCE_MEM, 0))) { |
486 | PB1100_G_CONTROL); | 460 | print_err("fail to retrieve registers resource"); |
487 | #endif | 461 | return -EFAULT; |
488 | #ifdef CONFIG_MIPS_HYDROGEN3 | 462 | } |
489 | /* Turn controller & power supply on, GPIO213 */ | ||
490 | au_writel(0x20002000, 0xB1700008); | ||
491 | au_writel(0x00040000, 0xB1900108); | ||
492 | au_writel(0x01000100, 0xB1700008); | ||
493 | #endif | ||
494 | 463 | ||
495 | p_lcd_reg->lcd_control |= LCD_CONTROL_GO; | 464 | au1100fb_fix.mmio_start = regs_res->start; |
465 | au1100fb_fix.mmio_len = regs_res->end - regs_res->start + 1; | ||
496 | 466 | ||
497 | return 0; | 467 | if (!request_mem_region(au1100fb_fix.mmio_start, au1100fb_fix.mmio_len, |
498 | } | 468 | DRIVER_NAME)) { |
469 | print_err("fail to lock memory region at 0x%08x", | ||
470 | au1100fb_fix.mmio_start); | ||
471 | return -EBUSY; | ||
472 | } | ||
499 | 473 | ||
474 | fbdev->regs = (struct au1100fb_regs*)KSEG1ADDR(au1100fb_fix.mmio_start); | ||
500 | 475 | ||
501 | int __init au1100fb_init(void) | 476 | print_dbg("Register memory map at %p", fbdev->regs); |
502 | { | 477 | print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len); |
503 | uint32 sys_clksrc; | ||
504 | unsigned long page; | ||
505 | 478 | ||
506 | /* | ||
507 | * Get the panel information/display mode and update the registry | ||
508 | */ | ||
509 | p_lcd = &panels[my_lcd_index]; | ||
510 | |||
511 | switch (p_lcd->mode_control & LCD_CONTROL_SM) | ||
512 | { | ||
513 | case LCD_CONTROL_SM_0: | ||
514 | case LCD_CONTROL_SM_180: | ||
515 | p_lcd->xres = | ||
516 | (p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1; | ||
517 | p_lcd->yres = | ||
518 | (p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1; | ||
519 | break; | ||
520 | case LCD_CONTROL_SM_90: | ||
521 | case LCD_CONTROL_SM_270: | ||
522 | p_lcd->yres = | ||
523 | (p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1; | ||
524 | p_lcd->xres = | ||
525 | (p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1; | ||
526 | break; | ||
527 | } | ||
528 | 479 | ||
529 | /* | ||
530 | * Panel dimensions x bpp must be divisible by 32 | ||
531 | */ | ||
532 | if (((p_lcd->yres * p_lcd->bpp) % 32) != 0) | ||
533 | printk("VERT %% 32\n"); | ||
534 | if (((p_lcd->xres * p_lcd->bpp) % 32) != 0) | ||
535 | printk("HORZ %% 32\n"); | ||
536 | 480 | ||
537 | /* | 481 | /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */ |
538 | * Allocate LCD framebuffer from system memory | 482 | fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * |
539 | */ | 483 | (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; |
540 | fb_info.fb_size = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 8; | 484 | |
541 | 485 | fbdev->fb_mem = dma_alloc_coherent(dev, PAGE_ALIGN(fbdev->fb_len), | |
542 | current_par.var.xres = p_lcd->xres; | 486 | &fbdev->fb_phys, GFP_KERNEL); |
543 | current_par.var.xres_virtual = p_lcd->xres; | 487 | if (!fbdev->fb_mem) { |
544 | current_par.var.yres = p_lcd->yres; | 488 | print_err("fail to allocate frambuffer (size: %dK))", |
545 | current_par.var.yres_virtual = p_lcd->yres; | 489 | fbdev->fb_len / 1024); |
546 | current_par.var.bits_per_pixel = p_lcd->bpp; | ||
547 | |||
548 | /* FIX!!! only works for 8/16 bpp */ | ||
549 | current_par.line_length = p_lcd->xres * p_lcd->bpp / 8; /* in bytes */ | ||
550 | fb_info.fb_virt_start = (unsigned long ) | ||
551 | __get_free_pages(GFP_ATOMIC | GFP_DMA, | ||
552 | get_order(fb_info.fb_size + 0x1000)); | ||
553 | if (!fb_info.fb_virt_start) { | ||
554 | printk("Unable to allocate fb memory\n"); | ||
555 | return -ENOMEM; | 490 | return -ENOMEM; |
556 | } | 491 | } |
557 | fb_info.fb_phys = virt_to_bus((void *)fb_info.fb_virt_start); | 492 | |
493 | au1100fb_fix.smem_start = fbdev->fb_phys; | ||
494 | au1100fb_fix.smem_len = fbdev->fb_len; | ||
558 | 495 | ||
559 | /* | 496 | /* |
560 | * Set page reserved so that mmap will work. This is necessary | 497 | * Set page reserved so that mmap will work. This is necessary |
561 | * since we'll be remapping normal memory. | 498 | * since we'll be remapping normal memory. |
562 | */ | 499 | */ |
563 | for (page = fb_info.fb_virt_start; | 500 | for (page = (unsigned long)fbdev->fb_mem; |
564 | page < PAGE_ALIGN(fb_info.fb_virt_start + fb_info.fb_size); | 501 | page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len); |
565 | page += PAGE_SIZE) { | 502 | page += PAGE_SIZE) { |
503 | #if CONFIG_DMA_NONCOHERENT | ||
504 | SetPageReserved(virt_to_page(CAC_ADDR(page))); | ||
505 | #else | ||
566 | SetPageReserved(virt_to_page(page)); | 506 | SetPageReserved(virt_to_page(page)); |
507 | #endif | ||
567 | } | 508 | } |
568 | 509 | ||
569 | memset((void *)fb_info.fb_virt_start, 0, fb_info.fb_size); | 510 | print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); |
570 | 511 | print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); | |
571 | /* set freqctrl now to allow more time to stabilize */ | 512 | |
572 | /* zero-out out LCD bits */ | 513 | /* Setup LCD clock to AUX (48 MHz) */ |
573 | sys_clksrc = au_readl(SYS_CLKSRC) & ~0x000003e0; | 514 | sys_clksrc = au_readl(SYS_CLKSRC) & ~(SYS_CS_ML_MASK | SYS_CS_DL | SYS_CS_CL); |
574 | sys_clksrc |= p_lcd->mode_toyclksrc; | 515 | au_writel((sys_clksrc | (1 << SYS_CS_ML_BIT)), SYS_CLKSRC); |
575 | au_writel(sys_clksrc, SYS_CLKSRC); | 516 | |
576 | 517 | /* load the panel info into the var struct */ | |
577 | /* FIXME add check to make sure auxpll is what is expected! */ | 518 | au1100fb_var.bits_per_pixel = fbdev->panel->bpp; |
578 | au1100_setmode(); | 519 | au1100fb_var.xres = fbdev->panel->xres; |
579 | 520 | au1100fb_var.xres_virtual = au1100fb_var.xres; | |
580 | fb_info.gen.parsize = sizeof(struct au1100fb_par); | 521 | au1100fb_var.yres = fbdev->panel->yres; |
581 | fb_info.gen.fbhw = &au1100_switch; | 522 | au1100fb_var.yres_virtual = au1100fb_var.yres; |
582 | 523 | ||
583 | strcpy(fb_info.gen.info.modename, "Au1100 LCD"); | 524 | fbdev->info.screen_base = fbdev->fb_mem; |
584 | fb_info.gen.info.changevar = NULL; | 525 | fbdev->info.fbops = &au1100fb_ops; |
585 | fb_info.gen.info.node = -1; | 526 | fbdev->info.fix = au1100fb_fix; |
586 | 527 | ||
587 | fb_info.gen.info.fbops = &au1100fb_ops; | 528 | if (!(fbdev->info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL))) { |
588 | fb_info.gen.info.disp = &disp; | 529 | return -ENOMEM; |
589 | fb_info.gen.info.switch_con = &fbgen_switch; | 530 | } |
590 | fb_info.gen.info.updatevar = &fbgen_update_var; | 531 | memset(fbdev->info.pseudo_palette, 0, sizeof(u32) * 16); |
591 | fb_info.gen.info.blank = &fbgen_blank; | 532 | |
592 | fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT; | 533 | if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { |
593 | 534 | print_err("Fail to allocate colormap (%d entries)", | |
594 | /* This should give a reasonable default video mode */ | 535 | AU1100_LCD_NBR_PALETTE_ENTRIES); |
595 | fbgen_get_var(&disp.var, -1, &fb_info.gen.info); | 536 | kfree(fbdev->info.pseudo_palette); |
596 | fbgen_do_set_var(&disp.var, 1, &fb_info.gen); | 537 | return -EFAULT; |
597 | fbgen_set_disp(-1, &fb_info.gen); | 538 | } |
598 | fbgen_install_cmap(0, &fb_info.gen); | 539 | |
599 | if (register_framebuffer(&fb_info.gen.info) < 0) | 540 | fbdev->info.var = au1100fb_var; |
600 | return -EINVAL; | 541 | |
601 | printk(KERN_INFO "fb%d: %s frame buffer device\n", | 542 | /* Set h/w registers */ |
602 | GET_FB_IDX(fb_info.gen.info.node), | 543 | au1100fb_setmode(fbdev); |
603 | fb_info.gen.info.modename); | 544 | |
545 | /* Register new framebuffer */ | ||
546 | if (register_framebuffer(&fbdev->info) < 0) { | ||
547 | print_err("cannot register new framebuffer"); | ||
548 | goto failed; | ||
549 | } | ||
550 | |||
551 | return 0; | ||
552 | |||
553 | failed: | ||
554 | if (fbdev->regs) { | ||
555 | release_mem_region(fbdev->regs_phys, fbdev->regs_len); | ||
556 | } | ||
557 | if (fbdev->fb_mem) { | ||
558 | dma_free_noncoherent(dev, fbdev->fb_len, fbdev->fb_mem, fbdev->fb_phys); | ||
559 | } | ||
560 | if (fbdev->info.cmap.len != 0) { | ||
561 | fb_dealloc_cmap(&fbdev->info.cmap); | ||
562 | } | ||
563 | kfree(fbdev); | ||
564 | dev_set_drvdata(dev, NULL); | ||
604 | 565 | ||
605 | return 0; | 566 | return 0; |
606 | } | 567 | } |
607 | 568 | ||
569 | int au1100fb_drv_remove(struct device *dev) | ||
570 | { | ||
571 | struct au1100fb_device *fbdev = NULL; | ||
572 | |||
573 | if (!dev) | ||
574 | return -ENODEV; | ||
575 | |||
576 | fbdev = (struct au1100fb_device*) dev_get_drvdata(dev); | ||
577 | |||
578 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) | ||
579 | au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info); | ||
580 | #endif | ||
581 | fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; | ||
608 | 582 | ||
609 | void au1100fb_cleanup(struct fb_info *info) | 583 | /* Clean up all probe data */ |
584 | unregister_framebuffer(&fbdev->info); | ||
585 | |||
586 | release_mem_region(fbdev->regs_phys, fbdev->regs_len); | ||
587 | |||
588 | dma_free_coherent(dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys); | ||
589 | |||
590 | fb_dealloc_cmap(&fbdev->info.cmap); | ||
591 | kfree(fbdev->info.pseudo_palette); | ||
592 | kfree((void*)fbdev); | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | int au1100fb_drv_suspend(struct device *dev, u32 state, u32 level) | ||
598 | { | ||
599 | /* TODO */ | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | int au1100fb_drv_resume(struct device *dev, u32 level) | ||
610 | { | 604 | { |
611 | unregister_framebuffer(info); | 605 | /* TODO */ |
606 | return 0; | ||
612 | } | 607 | } |
613 | 608 | ||
609 | static struct device_driver au1100fb_driver = { | ||
610 | .name = "au1100-lcd", | ||
611 | .bus = &platform_bus_type, | ||
614 | 612 | ||
615 | void au1100fb_setup(char *options, int *ints) | 613 | .probe = au1100fb_drv_probe, |
614 | .remove = au1100fb_drv_remove, | ||
615 | .suspend = au1100fb_drv_suspend, | ||
616 | .resume = au1100fb_drv_resume, | ||
617 | }; | ||
618 | |||
619 | /*-------------------------------------------------------------------------*/ | ||
620 | |||
621 | /* Kernel driver */ | ||
622 | |||
623 | int au1100fb_setup(char *options) | ||
616 | { | 624 | { |
617 | char* this_opt; | 625 | char* this_opt; |
618 | int i; | 626 | int num_panels = ARRAY_SIZE(known_lcd_panels); |
619 | int num_panels = sizeof(panels)/sizeof(struct known_lcd_panels); | 627 | char* mode = NULL; |
628 | int panel_idx = 0; | ||
620 | 629 | ||
630 | if (num_panels <= 0) { | ||
631 | print_err("No LCD panels supported by driver!"); | ||
632 | return -EFAULT; | ||
633 | } | ||
621 | 634 | ||
622 | if (!options || !*options) | 635 | if (options) { |
623 | return; | 636 | while ((this_opt = strsep(&options,",")) != NULL) { |
624 | 637 | /* Panel option */ | |
625 | for(this_opt=strtok(options, ","); this_opt; | ||
626 | this_opt=strtok(NULL, ",")) { | ||
627 | if (!strncmp(this_opt, "panel:", 6)) { | 638 | if (!strncmp(this_opt, "panel:", 6)) { |
628 | #if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) | 639 | int i; |
629 | /* Read Pb1100 Switch S10 ? */ | 640 | this_opt += 6; |
630 | if (!strncmp(this_opt+6, "s10", 3)) | 641 | for (i = 0; i < num_panels; i++) { |
631 | { | 642 | if (!strncmp(this_opt, |
632 | int panel; | 643 | known_lcd_panels[i].name, |
633 | panel = *(volatile int *)0xAE000008; /* BCSR SWITCHES */ | ||
634 | panel >>= 8; | ||
635 | panel &= 0x0F; | ||
636 | if (panel >= num_panels) panel = 0; | ||
637 | my_lcd_index = panel; | ||
638 | } | ||
639 | else | ||
640 | #endif | ||
641 | /* Get the panel name, everything else if fixed */ | ||
642 | for (i=0; i<num_panels; i++) { | ||
643 | if (!strncmp(this_opt+6, panels[i].panel_name, | ||
644 | strlen(this_opt))) { | 644 | strlen(this_opt))) { |
645 | my_lcd_index = i; | 645 | panel_idx = i; |
646 | break; | 646 | break; |
647 | } | 647 | } |
648 | } | 648 | } |
649 | if (i >= num_panels) { | ||
650 | print_warn("Panel %s not supported!", this_opt); | ||
651 | } | ||
652 | } | ||
653 | /* Mode option (only option that start with digit) */ | ||
654 | else if (isdigit(this_opt[0])) { | ||
655 | mode = kmalloc(strlen(this_opt) + 1, GFP_KERNEL); | ||
656 | strncpy(mode, this_opt, strlen(this_opt) + 1); | ||
657 | } | ||
658 | /* Unsupported option */ | ||
659 | else { | ||
660 | print_warn("Unsupported option \"%s\"", this_opt); | ||
649 | } | 661 | } |
650 | else if (!strncmp(this_opt, "nohwcursor", 10)) { | ||
651 | printk("nohwcursor\n"); | ||
652 | fb_info.nohwcursor = 1; | ||
653 | } | 662 | } |
654 | } | 663 | } |
655 | 664 | ||
656 | printk("au1100fb: Panel %d %s\n", my_lcd_index, | 665 | drv_info.panel_idx = panel_idx; |
657 | panels[my_lcd_index].panel_name); | 666 | drv_info.opt_mode = mode; |
658 | } | ||
659 | 667 | ||
668 | print_info("Panel=%s Mode=%s", | ||
669 | known_lcd_panels[drv_info.panel_idx].name, | ||
670 | drv_info.opt_mode ? drv_info.opt_mode : "default"); | ||
660 | 671 | ||
672 | return 0; | ||
673 | } | ||
661 | 674 | ||
662 | #ifdef MODULE | 675 | int __init au1100fb_init(void) |
663 | MODULE_LICENSE("GPL"); | ||
664 | int init_module(void) | ||
665 | { | 676 | { |
666 | return au1100fb_init(); | 677 | char* options; |
678 | int ret; | ||
679 | |||
680 | print_info("" DRIVER_DESC ""); | ||
681 | |||
682 | memset(&drv_info, 0, sizeof(drv_info)); | ||
683 | |||
684 | if (fb_get_options(DRIVER_NAME, &options)) | ||
685 | return -ENODEV; | ||
686 | |||
687 | /* Setup driver with options */ | ||
688 | ret = au1100fb_setup(options); | ||
689 | if (ret < 0) { | ||
690 | print_err("Fail to setup driver"); | ||
691 | return ret; | ||
692 | } | ||
693 | |||
694 | return driver_register(&au1100fb_driver); | ||
667 | } | 695 | } |
668 | 696 | ||
669 | void cleanup_module(void) | 697 | void __exit au1100fb_cleanup(void) |
670 | { | 698 | { |
671 | au1100fb_cleanup(void); | 699 | driver_unregister(&au1100fb_driver); |
700 | |||
701 | if (drv_info.opt_mode) | ||
702 | kfree(drv_info.opt_mode); | ||
672 | } | 703 | } |
673 | 704 | ||
674 | MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>"); | 705 | module_init(au1100fb_init); |
675 | MODULE_DESCRIPTION("Au1100 LCD framebuffer device driver"); | 706 | module_exit(au1100fb_cleanup); |
676 | #endif /* MODULE */ | 707 | |
708 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
709 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h index 657c560ab73c..2855534dc235 100644 --- a/drivers/video/au1100fb.h +++ b/drivers/video/au1100fb.h | |||
@@ -30,352 +30,352 @@ | |||
30 | #ifndef _AU1100LCD_H | 30 | #ifndef _AU1100LCD_H |
31 | #define _AU1100LCD_H | 31 | #define _AU1100LCD_H |
32 | 32 | ||
33 | #include <asm/mach-au1x00/au1000.h> | ||
34 | |||
35 | #define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) | ||
36 | #define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) | ||
37 | #define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) | ||
38 | |||
39 | #if DEBUG | ||
40 | #define print_dbg(f, arg...) printk(__FILE__ ": " f "\n", ## arg) | ||
41 | #else | ||
42 | #define print_dbg(f, arg...) do {} while (0) | ||
43 | #endif | ||
44 | |||
45 | #if defined(__BIG_ENDIAN) | ||
46 | #define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11 | ||
47 | #else | ||
48 | #define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00 | ||
49 | #endif | ||
50 | #define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565 | ||
51 | |||
33 | /********************************************************************/ | 52 | /********************************************************************/ |
34 | #define uint32 unsigned long | 53 | |
35 | typedef volatile struct | 54 | /* LCD controller restrictions */ |
36 | { | 55 | #define AU1100_LCD_MAX_XRES 800 |
37 | uint32 lcd_control; | 56 | #define AU1100_LCD_MAX_YRES 600 |
38 | uint32 lcd_intstatus; | 57 | #define AU1100_LCD_MAX_BPP 16 |
39 | uint32 lcd_intenable; | 58 | #define AU1100_LCD_MAX_CLK 48000000 |
40 | uint32 lcd_horztiming; | 59 | #define AU1100_LCD_NBR_PALETTE_ENTRIES 256 |
41 | uint32 lcd_verttiming; | 60 | |
42 | uint32 lcd_clkcontrol; | 61 | /* Default number of visible screen buffer to allocate */ |
43 | uint32 lcd_dmaaddr0; | 62 | #define AU1100FB_NBR_VIDEO_BUFFERS 4 |
44 | uint32 lcd_dmaaddr1; | ||
45 | uint32 lcd_words; | ||
46 | uint32 lcd_pwmdiv; | ||
47 | uint32 lcd_pwmhi; | ||
48 | uint32 reserved[(0x0400-0x002C)/4]; | ||
49 | uint32 lcd_pallettebase[256]; | ||
50 | |||
51 | } AU1100_LCD; | ||
52 | 63 | ||
53 | /********************************************************************/ | 64 | /********************************************************************/ |
54 | 65 | ||
55 | #define AU1100_LCD_ADDR 0xB5000000 | 66 | struct au1100fb_panel |
67 | { | ||
68 | const char name[25]; /* Full name <vendor>_<model> */ | ||
56 | 69 | ||
57 | /* | 70 | u32 control_base; /* Mode-independent control values */ |
58 | * Register bit definitions | 71 | u32 clkcontrol_base; /* Panel pixclock preferences */ |
59 | */ | ||
60 | 72 | ||
61 | /* lcd_control */ | 73 | u32 horztiming; |
62 | #define LCD_CONTROL_SBPPF (7<<18) | 74 | u32 verttiming; |
63 | #define LCD_CONTROL_SBPPF_655 (0<<18) | ||
64 | #define LCD_CONTROL_SBPPF_565 (1<<18) | ||
65 | #define LCD_CONTROL_SBPPF_556 (2<<18) | ||
66 | #define LCD_CONTROL_SBPPF_1555 (3<<18) | ||
67 | #define LCD_CONTROL_SBPPF_5551 (4<<18) | ||
68 | #define LCD_CONTROL_WP (1<<17) | ||
69 | #define LCD_CONTROL_WD (1<<16) | ||
70 | #define LCD_CONTROL_C (1<<15) | ||
71 | #define LCD_CONTROL_SM (3<<13) | ||
72 | #define LCD_CONTROL_SM_0 (0<<13) | ||
73 | #define LCD_CONTROL_SM_90 (1<<13) | ||
74 | #define LCD_CONTROL_SM_180 (2<<13) | ||
75 | #define LCD_CONTROL_SM_270 (3<<13) | ||
76 | #define LCD_CONTROL_DB (1<<12) | ||
77 | #define LCD_CONTROL_CCO (1<<11) | ||
78 | #define LCD_CONTROL_DP (1<<10) | ||
79 | #define LCD_CONTROL_PO (3<<8) | ||
80 | #define LCD_CONTROL_PO_00 (0<<8) | ||
81 | #define LCD_CONTROL_PO_01 (1<<8) | ||
82 | #define LCD_CONTROL_PO_10 (2<<8) | ||
83 | #define LCD_CONTROL_PO_11 (3<<8) | ||
84 | #define LCD_CONTROL_MPI (1<<7) | ||
85 | #define LCD_CONTROL_PT (1<<6) | ||
86 | #define LCD_CONTROL_PC (1<<5) | ||
87 | #define LCD_CONTROL_BPP (7<<1) | ||
88 | #define LCD_CONTROL_BPP_1 (0<<1) | ||
89 | #define LCD_CONTROL_BPP_2 (1<<1) | ||
90 | #define LCD_CONTROL_BPP_4 (2<<1) | ||
91 | #define LCD_CONTROL_BPP_8 (3<<1) | ||
92 | #define LCD_CONTROL_BPP_12 (4<<1) | ||
93 | #define LCD_CONTROL_BPP_16 (5<<1) | ||
94 | #define LCD_CONTROL_GO (1<<0) | ||
95 | |||
96 | /* lcd_intstatus, lcd_intenable */ | ||
97 | #define LCD_INT_SD (1<<7) | ||
98 | #define LCD_INT_OF (1<<6) | ||
99 | #define LCD_INT_UF (1<<5) | ||
100 | #define LCD_INT_SA (1<<3) | ||
101 | #define LCD_INT_SS (1<<2) | ||
102 | #define LCD_INT_S1 (1<<1) | ||
103 | #define LCD_INT_S0 (1<<0) | ||
104 | |||
105 | /* lcd_horztiming */ | ||
106 | #define LCD_HORZTIMING_HN2 (255<<24) | ||
107 | #define LCD_HORZTIMING_HN2_N(N) (((N)-1)<<24) | ||
108 | #define LCD_HORZTIMING_HN1 (255<<16) | ||
109 | #define LCD_HORZTIMING_HN1_N(N) (((N)-1)<<16) | ||
110 | #define LCD_HORZTIMING_HPW (63<<10) | ||
111 | #define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<10) | ||
112 | #define LCD_HORZTIMING_PPL (1023<<0) | ||
113 | #define LCD_HORZTIMING_PPL_N(N) (((N)-1)<<0) | ||
114 | |||
115 | /* lcd_verttiming */ | ||
116 | #define LCD_VERTTIMING_VN2 (255<<24) | ||
117 | #define LCD_VERTTIMING_VN2_N(N) (((N)-1)<<24) | ||
118 | #define LCD_VERTTIMING_VN1 (255<<16) | ||
119 | #define LCD_VERTTIMING_VN1_N(N) (((N)-1)<<16) | ||
120 | #define LCD_VERTTIMING_VPW (63<<10) | ||
121 | #define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<10) | ||
122 | #define LCD_VERTTIMING_LPP (1023<<0) | ||
123 | #define LCD_VERTTIMING_LPP_N(N) (((N)-1)<<0) | ||
124 | |||
125 | /* lcd_clkcontrol */ | ||
126 | #define LCD_CLKCONTROL_IB (1<<18) | ||
127 | #define LCD_CLKCONTROL_IC (1<<17) | ||
128 | #define LCD_CLKCONTROL_IH (1<<16) | ||
129 | #define LCD_CLKCONTROL_IV (1<<15) | ||
130 | #define LCD_CLKCONTROL_BF (31<<10) | ||
131 | #define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10) | ||
132 | #define LCD_CLKCONTROL_PCD (1023<<0) | ||
133 | #define LCD_CLKCONTROL_PCD_N(N) ((N)<<0) | ||
134 | |||
135 | /* lcd_pwmdiv */ | ||
136 | #define LCD_PWMDIV_EN (1<<12) | ||
137 | #define LCD_PWMDIV_PWMDIV (2047<<0) | ||
138 | #define LCD_PWMDIV_PWMDIV_N(N) (((N)-1)<<0) | ||
139 | |||
140 | /* lcd_pwmhi */ | ||
141 | #define LCD_PWMHI_PWMHI1 (2047<<12) | ||
142 | #define LCD_PWMHI_PWMHI1_N(N) ((N)<<12) | ||
143 | #define LCD_PWMHI_PWMHI0 (2047<<0) | ||
144 | #define LCD_PWMHI_PWMHI0_N(N) ((N)<<0) | ||
145 | |||
146 | /* lcd_pallettebase - MONOCHROME */ | ||
147 | #define LCD_PALLETTE_MONO_MI (15<<0) | ||
148 | #define LCD_PALLETTE_MONO_MI_N(N) ((N)<<0) | ||
149 | |||
150 | /* lcd_pallettebase - COLOR */ | ||
151 | #define LCD_PALLETTE_COLOR_BI (15<<8) | ||
152 | #define LCD_PALLETTE_COLOR_BI_N(N) ((N)<<8) | ||
153 | #define LCD_PALLETTE_COLOR_GI (15<<4) | ||
154 | #define LCD_PALLETTE_COLOR_GI_N(N) ((N)<<4) | ||
155 | #define LCD_PALLETTE_COLOR_RI (15<<0) | ||
156 | #define LCD_PALLETTE_COLOR_RI_N(N) ((N)<<0) | ||
157 | |||
158 | /* lcd_palletebase - COLOR TFT PALLETIZED */ | ||
159 | #define LCD_PALLETTE_TFT_DC (65535<<0) | ||
160 | #define LCD_PALLETTE_TFT_DC_N(N) ((N)<<0) | ||
161 | 75 | ||
162 | /********************************************************************/ | 76 | u32 xres; /* Maximum horizontal resolution */ |
77 | u32 yres; /* Maximum vertical resolution */ | ||
78 | u32 bpp; /* Maximum depth supported */ | ||
79 | }; | ||
163 | 80 | ||
164 | struct known_lcd_panels | 81 | struct au1100fb_regs |
165 | { | 82 | { |
166 | uint32 xres; | 83 | u32 lcd_control; |
167 | uint32 yres; | 84 | u32 lcd_intstatus; |
168 | uint32 bpp; | 85 | u32 lcd_intenable; |
169 | unsigned char panel_name[256]; | 86 | u32 lcd_horztiming; |
170 | uint32 mode_control; | 87 | u32 lcd_verttiming; |
171 | uint32 mode_horztiming; | 88 | u32 lcd_clkcontrol; |
172 | uint32 mode_verttiming; | 89 | u32 lcd_dmaaddr0; |
173 | uint32 mode_clkcontrol; | 90 | u32 lcd_dmaaddr1; |
174 | uint32 mode_pwmdiv; | 91 | u32 lcd_words; |
175 | uint32 mode_pwmhi; | 92 | u32 lcd_pwmdiv; |
176 | uint32 mode_toyclksrc; | 93 | u32 lcd_pwmhi; |
177 | uint32 mode_backlight; | 94 | u32 reserved[(0x0400-0x002C)/4]; |
95 | u32 lcd_pallettebase[256]; | ||
96 | }; | ||
97 | |||
98 | struct au1100fb_device { | ||
99 | |||
100 | struct fb_info info; /* FB driver info record */ | ||
178 | 101 | ||
102 | struct au1100fb_panel *panel; /* Panel connected to this device */ | ||
103 | |||
104 | struct au1100fb_regs* regs; /* Registers memory map */ | ||
105 | size_t regs_len; | ||
106 | unsigned int regs_phys; | ||
107 | |||
108 | unsigned char* fb_mem; /* FrameBuffer memory map */ | ||
109 | size_t fb_len; | ||
110 | dma_addr_t fb_phys; | ||
179 | }; | 111 | }; |
180 | 112 | ||
181 | #if defined(__BIG_ENDIAN) | 113 | /********************************************************************/ |
182 | #define LCD_DEFAULT_PIX_FORMAT LCD_CONTROL_PO_11 | ||
183 | #else | ||
184 | #define LCD_DEFAULT_PIX_FORMAT LCD_CONTROL_PO_00 | ||
185 | #endif | ||
186 | 114 | ||
187 | /* | 115 | #define LCD_CONTROL (AU1100_LCD_BASE + 0x0) |
188 | * The fb driver assumes that AUX PLL is at 48MHz. That can | 116 | #define LCD_CONTROL_SBB_BIT 21 |
189 | * cover up to 800x600 resolution; if you need higher resolution, | 117 | #define LCD_CONTROL_SBB_MASK (0x3 << LCD_CONTROL_SBB_BIT) |
190 | * you should modify the driver as needed, not just this structure. | 118 | #define LCD_CONTROL_SBB_1 (0 << LCD_CONTROL_SBB_BIT) |
119 | #define LCD_CONTROL_SBB_2 (1 << LCD_CONTROL_SBB_BIT) | ||
120 | #define LCD_CONTROL_SBB_3 (2 << LCD_CONTROL_SBB_BIT) | ||
121 | #define LCD_CONTROL_SBB_4 (3 << LCD_CONTROL_SBB_BIT) | ||
122 | #define LCD_CONTROL_SBPPF_BIT 18 | ||
123 | #define LCD_CONTROL_SBPPF_MASK (0x7 << LCD_CONTROL_SBPPF_BIT) | ||
124 | #define LCD_CONTROL_SBPPF_655 (0 << LCD_CONTROL_SBPPF_BIT) | ||
125 | #define LCD_CONTROL_SBPPF_565 (1 << LCD_CONTROL_SBPPF_BIT) | ||
126 | #define LCD_CONTROL_SBPPF_556 (2 << LCD_CONTROL_SBPPF_BIT) | ||
127 | #define LCD_CONTROL_SBPPF_1555 (3 << LCD_CONTROL_SBPPF_BIT) | ||
128 | #define LCD_CONTROL_SBPPF_5551 (4 << LCD_CONTROL_SBPPF_BIT) | ||
129 | #define LCD_CONTROL_WP (1<<17) | ||
130 | #define LCD_CONTROL_WD (1<<16) | ||
131 | #define LCD_CONTROL_C (1<<15) | ||
132 | #define LCD_CONTROL_SM_BIT 13 | ||
133 | #define LCD_CONTROL_SM_MASK (0x3 << LCD_CONTROL_SM_BIT) | ||
134 | #define LCD_CONTROL_SM_0 (0 << LCD_CONTROL_SM_BIT) | ||
135 | #define LCD_CONTROL_SM_90 (1 << LCD_CONTROL_SM_BIT) | ||
136 | #define LCD_CONTROL_SM_180 (2 << LCD_CONTROL_SM_BIT) | ||
137 | #define LCD_CONTROL_SM_270 (3 << LCD_CONTROL_SM_BIT) | ||
138 | #define LCD_CONTROL_DB (1<<12) | ||
139 | #define LCD_CONTROL_CCO (1<<11) | ||
140 | #define LCD_CONTROL_DP (1<<10) | ||
141 | #define LCD_CONTROL_PO_BIT 8 | ||
142 | #define LCD_CONTROL_PO_MASK (0x3 << LCD_CONTROL_PO_BIT) | ||
143 | #define LCD_CONTROL_PO_00 (0 << LCD_CONTROL_PO_BIT) | ||
144 | #define LCD_CONTROL_PO_01 (1 << LCD_CONTROL_PO_BIT) | ||
145 | #define LCD_CONTROL_PO_10 (2 << LCD_CONTROL_PO_BIT) | ||
146 | #define LCD_CONTROL_PO_11 (3 << LCD_CONTROL_PO_BIT) | ||
147 | #define LCD_CONTROL_MPI (1<<7) | ||
148 | #define LCD_CONTROL_PT (1<<6) | ||
149 | #define LCD_CONTROL_PC (1<<5) | ||
150 | #define LCD_CONTROL_BPP_BIT 1 | ||
151 | #define LCD_CONTROL_BPP_MASK (0x7 << LCD_CONTROL_BPP_BIT) | ||
152 | #define LCD_CONTROL_BPP_1 (0 << LCD_CONTROL_BPP_BIT) | ||
153 | #define LCD_CONTROL_BPP_2 (1 << LCD_CONTROL_BPP_BIT) | ||
154 | #define LCD_CONTROL_BPP_4 (2 << LCD_CONTROL_BPP_BIT) | ||
155 | #define LCD_CONTROL_BPP_8 (3 << LCD_CONTROL_BPP_BIT) | ||
156 | #define LCD_CONTROL_BPP_12 (4 << LCD_CONTROL_BPP_BIT) | ||
157 | #define LCD_CONTROL_BPP_16 (5 << LCD_CONTROL_BPP_BIT) | ||
158 | #define LCD_CONTROL_GO (1<<0) | ||
159 | |||
160 | #define LCD_INTSTATUS (AU1100_LCD_BASE + 0x4) | ||
161 | #define LCD_INTENABLE (AU1100_LCD_BASE + 0x8) | ||
162 | #define LCD_INT_SD (1<<7) | ||
163 | #define LCD_INT_OF (1<<6) | ||
164 | #define LCD_INT_UF (1<<5) | ||
165 | #define LCD_INT_SA (1<<3) | ||
166 | #define LCD_INT_SS (1<<2) | ||
167 | #define LCD_INT_S1 (1<<1) | ||
168 | #define LCD_INT_S0 (1<<0) | ||
169 | |||
170 | #define LCD_HORZTIMING (AU1100_LCD_BASE + 0xC) | ||
171 | #define LCD_HORZTIMING_HN2_BIT 24 | ||
172 | #define LCD_HORZTIMING_HN2_MASK (0xFF << LCD_HORZTIMING_HN2_BIT) | ||
173 | #define LCD_HORZTIMING_HN2_N(N) ((((N)-1) << LCD_HORZTIMING_HN2_BIT) & LCD_HORZTIMING_HN2_MASK) | ||
174 | #define LCD_HORZTIMING_HN1_BIT 16 | ||
175 | #define LCD_HORZTIMING_HN1_MASK (0xFF << LCD_HORZTIMING_HN1_BIT) | ||
176 | #define LCD_HORZTIMING_HN1_N(N) ((((N)-1) << LCD_HORZTIMING_HN1_BIT) & LCD_HORZTIMING_HN1_MASK) | ||
177 | #define LCD_HORZTIMING_HPW_BIT 10 | ||
178 | #define LCD_HORZTIMING_HPW_MASK (0x3F << LCD_HORZTIMING_HPW_BIT) | ||
179 | #define LCD_HORZTIMING_HPW_N(N) ((((N)-1) << LCD_HORZTIMING_HPW_BIT) & LCD_HORZTIMING_HPW_MASK) | ||
180 | #define LCD_HORZTIMING_PPL_BIT 0 | ||
181 | #define LCD_HORZTIMING_PPL_MASK (0x3FF << LCD_HORZTIMING_PPL_BIT) | ||
182 | #define LCD_HORZTIMING_PPL_N(N) ((((N)-1) << LCD_HORZTIMING_PPL_BIT) & LCD_HORZTIMING_PPL_MASK) | ||
183 | |||
184 | #define LCD_VERTTIMING (AU1100_LCD_BASE + 0x10) | ||
185 | #define LCD_VERTTIMING_VN2_BIT 24 | ||
186 | #define LCD_VERTTIMING_VN2_MASK (0xFF << LCD_VERTTIMING_VN2_BIT) | ||
187 | #define LCD_VERTTIMING_VN2_N(N) ((((N)-1) << LCD_VERTTIMING_VN2_BIT) & LCD_VERTTIMING_VN2_MASK) | ||
188 | #define LCD_VERTTIMING_VN1_BIT 16 | ||
189 | #define LCD_VERTTIMING_VN1_MASK (0xFF << LCD_VERTTIMING_VN1_BIT) | ||
190 | #define LCD_VERTTIMING_VN1_N(N) ((((N)-1) << LCD_VERTTIMING_VN1_BIT) & LCD_VERTTIMING_VN1_MASK) | ||
191 | #define LCD_VERTTIMING_VPW_BIT 10 | ||
192 | #define LCD_VERTTIMING_VPW_MASK (0x3F << LCD_VERTTIMING_VPW_BIT) | ||
193 | #define LCD_VERTTIMING_VPW_N(N) ((((N)-1) << LCD_VERTTIMING_VPW_BIT) & LCD_VERTTIMING_VPW_MASK) | ||
194 | #define LCD_VERTTIMING_LPP_BIT 0 | ||
195 | #define LCD_VERTTIMING_LPP_MASK (0x3FF << LCD_VERTTIMING_LPP_BIT) | ||
196 | #define LCD_VERTTIMING_LPP_N(N) ((((N)-1) << LCD_VERTTIMING_LPP_BIT) & LCD_VERTTIMING_LPP_MASK) | ||
197 | |||
198 | #define LCD_CLKCONTROL (AU1100_LCD_BASE + 0x14) | ||
199 | #define LCD_CLKCONTROL_IB (1<<18) | ||
200 | #define LCD_CLKCONTROL_IC (1<<17) | ||
201 | #define LCD_CLKCONTROL_IH (1<<16) | ||
202 | #define LCD_CLKCONTROL_IV (1<<15) | ||
203 | #define LCD_CLKCONTROL_BF_BIT 10 | ||
204 | #define LCD_CLKCONTROL_BF_MASK (0x1F << LCD_CLKCONTROL_BF_BIT) | ||
205 | #define LCD_CLKCONTROL_BF_N(N) ((((N)-1) << LCD_CLKCONTROL_BF_BIT) & LCD_CLKCONTROL_BF_MASK) | ||
206 | #define LCD_CLKCONTROL_PCD_BIT 0 | ||
207 | #define LCD_CLKCONTROL_PCD_MASK (0x3FF << LCD_CLKCONTROL_PCD_BIT) | ||
208 | #define LCD_CLKCONTROL_PCD_N(N) (((N) << LCD_CLKCONTROL_PCD_BIT) & LCD_CLKCONTROL_PCD_MASK) | ||
209 | |||
210 | #define LCD_DMAADDR0 (AU1100_LCD_BASE + 0x18) | ||
211 | #define LCD_DMAADDR1 (AU1100_LCD_BASE + 0x1C) | ||
212 | #define LCD_DMA_SA_BIT 5 | ||
213 | #define LCD_DMA_SA_MASK (0x7FFFFFF << LCD_DMA_SA_BIT) | ||
214 | #define LCD_DMA_SA_N(N) ((N) & LCD_DMA_SA_MASK) | ||
215 | |||
216 | #define LCD_WORDS (AU1100_LCD_BASE + 0x20) | ||
217 | #define LCD_WRD_WRDS_BIT 0 | ||
218 | #define LCD_WRD_WRDS_MASK (0xFFFFFFFF << LCD_WRD_WRDS_BIT) | ||
219 | #define LCD_WRD_WRDS_N(N) ((((N)-1) << LCD_WRD_WRDS_BIT) & LCD_WRD_WRDS_MASK) | ||
220 | |||
221 | #define LCD_PWMDIV (AU1100_LCD_BASE + 0x24) | ||
222 | #define LCD_PWMDIV_EN (1<<12) | ||
223 | #define LCD_PWMDIV_PWMDIV_BIT 0 | ||
224 | #define LCD_PWMDIV_PWMDIV_MASK (0xFFF << LCD_PWMDIV_PWMDIV_BIT) | ||
225 | #define LCD_PWMDIV_PWMDIV_N(N) ((((N)-1) << LCD_PWMDIV_PWMDIV_BIT) & LCD_PWMDIV_PWMDIV_MASK) | ||
226 | |||
227 | #define LCD_PWMHI (AU1100_LCD_BASE + 0x28) | ||
228 | #define LCD_PWMHI_PWMHI1_BIT 12 | ||
229 | #define LCD_PWMHI_PWMHI1_MASK (0xFFF << LCD_PWMHI_PWMHI1_BIT) | ||
230 | #define LCD_PWMHI_PWMHI1_N(N) (((N) << LCD_PWMHI_PWMHI1_BIT) & LCD_PWMHI_PWMHI1_MASK) | ||
231 | #define LCD_PWMHI_PWMHI0_BIT 0 | ||
232 | #define LCD_PWMHI_PWMHI0_MASK (0xFFF << LCD_PWMHI_PWMHI0_BIT) | ||
233 | #define LCD_PWMHI_PWMHI0_N(N) (((N) << LCD_PWMHI_PWMHI0_BIT) & LCD_PWMHI_PWMHI0_MASK) | ||
234 | |||
235 | #define LCD_PALLETTEBASE (AU1100_LCD_BASE + 0x400) | ||
236 | #define LCD_PALLETTE_MONO_MI_BIT 0 | ||
237 | #define LCD_PALLETTE_MONO_MI_MASK (0xF << LCD_PALLETTE_MONO_MI_BIT) | ||
238 | #define LCD_PALLETTE_MONO_MI_N(N) (((N)<< LCD_PALLETTE_MONO_MI_BIT) & LCD_PALLETTE_MONO_MI_MASK) | ||
239 | |||
240 | #define LCD_PALLETTE_COLOR_RI_BIT 8 | ||
241 | #define LCD_PALLETTE_COLOR_RI_MASK (0xF << LCD_PALLETTE_COLOR_RI_BIT) | ||
242 | #define LCD_PALLETTE_COLOR_RI_N(N) (((N)<< LCD_PALLETTE_COLOR_RI_BIT) & LCD_PALLETTE_COLOR_RI_MASK) | ||
243 | #define LCD_PALLETTE_COLOR_GI_BIT 4 | ||
244 | #define LCD_PALLETTE_COLOR_GI_MASK (0xF << LCD_PALLETTE_COLOR_GI_BIT) | ||
245 | #define LCD_PALLETTE_COLOR_GI_N(N) (((N)<< LCD_PALLETTE_COLOR_GI_BIT) & LCD_PALLETTE_COLOR_GI_MASK) | ||
246 | #define LCD_PALLETTE_COLOR_BI_BIT 0 | ||
247 | #define LCD_PALLETTE_COLOR_BI_MASK (0xF << LCD_PALLETTE_COLOR_BI_BIT) | ||
248 | #define LCD_PALLETTE_COLOR_BI_N(N) (((N)<< LCD_PALLETTE_COLOR_BI_BIT) & LCD_PALLETTE_COLOR_BI_MASK) | ||
249 | |||
250 | #define LCD_PALLETTE_TFT_DC_BIT 0 | ||
251 | #define LCD_PALLETTE_TFT_DC_MASK (0xFFFF << LCD_PALLETTE_TFT_DC_BIT) | ||
252 | #define LCD_PALLETTE_TFT_DC_N(N) (((N)<< LCD_PALLETTE_TFT_DC_BIT) & LCD_PALLETTE_TFT_DC_MASK) | ||
253 | |||
254 | /********************************************************************/ | ||
255 | |||
256 | /* List of panels known to work with the AU1100 LCD controller. | ||
257 | * To add a new panel, enter the same specifications as the | ||
258 | * Generic_TFT one, and MAKE SURE that it doesn't conflicts | ||
259 | * with the controller restrictions. Restrictions are: | ||
260 | * | ||
261 | * STN color panels: max_bpp <= 12 | ||
262 | * STN mono panels: max_bpp <= 4 | ||
263 | * TFT panels: max_bpp <= 16 | ||
264 | * max_xres <= 800 | ||
265 | * max_yres <= 600 | ||
191 | */ | 266 | */ |
192 | struct known_lcd_panels panels[] = | 267 | static struct au1100fb_panel known_lcd_panels[] = |
193 | { | 268 | { |
194 | { /* 0: Pb1100 LCDA: Sharp 320x240 TFT panel */ | 269 | /* 800x600x16bpp CRT */ |
195 | 320, /* xres */ | 270 | [0] = { |
196 | 240, /* yres */ | 271 | .name = "CRT_800x600_16", |
197 | 16, /* bpp */ | 272 | .xres = 800, |
198 | 273 | .yres = 600, | |
199 | "Sharp_320x240_16", | 274 | .bpp = 16, |
200 | /* mode_control */ | 275 | .control_base = 0x0004886A | |
276 | LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_DEFAULT_SBPPF | | ||
277 | LCD_CONTROL_BPP_16, | ||
278 | .clkcontrol_base = 0x00020000, | ||
279 | .horztiming = 0x005aff1f, | ||
280 | .verttiming = 0x16000e57, | ||
281 | }, | ||
282 | /* just the standard LCD */ | ||
283 | [1] = { | ||
284 | .name = "WWPC LCD", | ||
285 | .xres = 240, | ||
286 | .yres = 320, | ||
287 | .bpp = 16, | ||
288 | .control_base = 0x0006806A, | ||
289 | .horztiming = 0x0A1010EF, | ||
290 | .verttiming = 0x0301013F, | ||
291 | .clkcontrol_base = 0x00018001, | ||
292 | }, | ||
293 | /* Sharp 320x240 TFT panel */ | ||
294 | [2] = { | ||
295 | .name = "Sharp_LQ038Q5DR01", | ||
296 | .xres = 320, | ||
297 | .yres = 240, | ||
298 | .bpp = 16, | ||
299 | .control_base = | ||
201 | ( LCD_CONTROL_SBPPF_565 | 300 | ( LCD_CONTROL_SBPPF_565 |
202 | /*LCD_CONTROL_WP*/ | ||
203 | /*LCD_CONTROL_WD*/ | ||
204 | | LCD_CONTROL_C | 301 | | LCD_CONTROL_C |
205 | | LCD_CONTROL_SM_0 | 302 | | LCD_CONTROL_SM_0 |
206 | /*LCD_CONTROL_DB*/ | 303 | | LCD_CONTROL_DEFAULT_PO |
207 | /*LCD_CONTROL_CCO*/ | ||
208 | /*LCD_CONTROL_DP*/ | ||
209 | | LCD_DEFAULT_PIX_FORMAT | ||
210 | /*LCD_CONTROL_MPI*/ | ||
211 | | LCD_CONTROL_PT | 304 | | LCD_CONTROL_PT |
212 | | LCD_CONTROL_PC | 305 | | LCD_CONTROL_PC |
213 | | LCD_CONTROL_BPP_16 ), | 306 | | LCD_CONTROL_BPP_16 ), |
214 | 307 | .horztiming = | |
215 | /* mode_horztiming */ | ||
216 | ( LCD_HORZTIMING_HN2_N(8) | 308 | ( LCD_HORZTIMING_HN2_N(8) |
217 | | LCD_HORZTIMING_HN1_N(60) | 309 | | LCD_HORZTIMING_HN1_N(60) |
218 | | LCD_HORZTIMING_HPW_N(12) | 310 | | LCD_HORZTIMING_HPW_N(12) |
219 | | LCD_HORZTIMING_PPL_N(320) ), | 311 | | LCD_HORZTIMING_PPL_N(320) ), |
220 | 312 | .verttiming = | |
221 | /* mode_verttiming */ | ||
222 | ( LCD_VERTTIMING_VN2_N(5) | 313 | ( LCD_VERTTIMING_VN2_N(5) |
223 | | LCD_VERTTIMING_VN1_N(17) | 314 | | LCD_VERTTIMING_VN1_N(17) |
224 | | LCD_VERTTIMING_VPW_N(1) | 315 | | LCD_VERTTIMING_VPW_N(1) |
225 | | LCD_VERTTIMING_LPP_N(240) ), | 316 | | LCD_VERTTIMING_LPP_N(240) ), |
226 | 317 | .clkcontrol_base = LCD_CLKCONTROL_PCD_N(1), | |
227 | /* mode_clkcontrol */ | ||
228 | ( 0 | ||
229 | /*LCD_CLKCONTROL_IB*/ | ||
230 | /*LCD_CLKCONTROL_IC*/ | ||
231 | /*LCD_CLKCONTROL_IH*/ | ||
232 | /*LCD_CLKCONTROL_IV*/ | ||
233 | | LCD_CLKCONTROL_PCD_N(1) ), | ||
234 | |||
235 | /* mode_pwmdiv */ | ||
236 | 0, | ||
237 | |||
238 | /* mode_pwmhi */ | ||
239 | 0, | ||
240 | |||
241 | /* mode_toyclksrc */ | ||
242 | ((1<<7) | (1<<6) | (1<<5)), | ||
243 | |||
244 | /* mode_backlight */ | ||
245 | 6 | ||
246 | }, | 318 | }, |
247 | 319 | ||
248 | { /* 1: Pb1100 LCDC 640x480 TFT panel */ | 320 | /* Hitachi SP14Q005 and possibly others */ |
249 | 640, /* xres */ | 321 | [3] = { |
250 | 480, /* yres */ | 322 | .name = "Hitachi_SP14Qxxx", |
251 | 16, /* bpp */ | 323 | .xres = 320, |
252 | 324 | .yres = 240, | |
253 | "Generic_640x480_16", | 325 | .bpp = 4, |
254 | 326 | .control_base = | |
255 | /* mode_control */ | 327 | ( LCD_CONTROL_C |
256 | 0x004806a | LCD_DEFAULT_PIX_FORMAT, | 328 | | LCD_CONTROL_BPP_4 ), |
257 | 329 | .horztiming = | |
258 | /* mode_horztiming */ | 330 | ( LCD_HORZTIMING_HN2_N(1) |
259 | 0x3434d67f, | 331 | | LCD_HORZTIMING_HN1_N(1) |
260 | 332 | | LCD_HORZTIMING_HPW_N(1) | |
261 | /* mode_verttiming */ | 333 | | LCD_HORZTIMING_PPL_N(320) ), |
262 | 0x0e0e39df, | 334 | .verttiming = |
263 | 335 | ( LCD_VERTTIMING_VN2_N(1) | |
264 | /* mode_clkcontrol */ | 336 | | LCD_VERTTIMING_VN1_N(1) |
265 | ( 0 | 337 | | LCD_VERTTIMING_VPW_N(1) |
266 | /*LCD_CLKCONTROL_IB*/ | 338 | | LCD_VERTTIMING_LPP_N(240) ), |
267 | /*LCD_CLKCONTROL_IC*/ | 339 | .clkcontrol_base = LCD_CLKCONTROL_PCD_N(4), |
268 | /*LCD_CLKCONTROL_IH*/ | ||
269 | /*LCD_CLKCONTROL_IV*/ | ||
270 | | LCD_CLKCONTROL_PCD_N(1) ), | ||
271 | |||
272 | /* mode_pwmdiv */ | ||
273 | 0, | ||
274 | |||
275 | /* mode_pwmhi */ | ||
276 | 0, | ||
277 | |||
278 | /* mode_toyclksrc */ | ||
279 | ((1<<7) | (1<<6) | (0<<5)), | ||
280 | |||
281 | /* mode_backlight */ | ||
282 | 7 | ||
283 | }, | 340 | }, |
284 | 341 | ||
285 | { /* 2: Pb1100 LCDB 640x480 PrimeView TFT panel */ | 342 | /* Generic 640x480 TFT panel */ |
286 | 640, /* xres */ | 343 | [4] = { |
287 | 480, /* yres */ | 344 | .name = "TFT_640x480_16", |
288 | 16, /* bpp */ | 345 | .xres = 640, |
289 | 346 | .yres = 480, | |
290 | "PrimeView_640x480_16", | 347 | .bpp = 16, |
291 | 348 | .control_base = 0x004806a | LCD_CONTROL_DEFAULT_PO, | |
292 | /* mode_control */ | 349 | .horztiming = 0x3434d67f, |
293 | 0x0004886a | LCD_DEFAULT_PIX_FORMAT, | 350 | .verttiming = 0x0e0e39df, |
294 | 351 | .clkcontrol_base = LCD_CLKCONTROL_PCD_N(1), | |
295 | /* mode_horztiming */ | ||
296 | 0x0e4bfe7f, | ||
297 | |||
298 | /* mode_verttiming */ | ||
299 | 0x210805df, | ||
300 | |||
301 | /* mode_clkcontrol */ | ||
302 | 0x00038001, | ||
303 | |||
304 | /* mode_pwmdiv */ | ||
305 | 0, | ||
306 | |||
307 | /* mode_pwmhi */ | ||
308 | 0, | ||
309 | |||
310 | /* mode_toyclksrc */ | ||
311 | ((1<<7) | (1<<6) | (0<<5)), | ||
312 | |||
313 | /* mode_backlight */ | ||
314 | 7 | ||
315 | }, | 352 | }, |
316 | 353 | ||
317 | { /* 3: Pb1100 800x600x16bpp NEON CRT */ | 354 | /* Pb1100 LCDB 640x480 PrimeView TFT panel */ |
318 | 800, /* xres */ | 355 | [5] = { |
319 | 600, /* yres */ | 356 | .name = "PrimeView_640x480_16", |
320 | 16, /* bpp */ | 357 | .xres = 640, |
321 | 358 | .yres = 480, | |
322 | "NEON_800x600_16", | 359 | .bpp = 16, |
323 | 360 | .control_base = 0x0004886a | LCD_CONTROL_DEFAULT_PO, | |
324 | /* mode_control */ | 361 | .horztiming = 0x0e4bfe7f, |
325 | 0x0004886A | LCD_DEFAULT_PIX_FORMAT, | 362 | .verttiming = 0x210805df, |
326 | 363 | .clkcontrol_base = 0x00038001, | |
327 | /* mode_horztiming */ | ||
328 | 0x005AFF1F, | ||
329 | |||
330 | /* mode_verttiming */ | ||
331 | 0x16000E57, | ||
332 | |||
333 | /* mode_clkcontrol */ | ||
334 | 0x00020000, | ||
335 | |||
336 | /* mode_pwmdiv */ | ||
337 | 0, | ||
338 | |||
339 | /* mode_pwmhi */ | ||
340 | 0, | ||
341 | |||
342 | /* mode_toyclksrc */ | ||
343 | ((1<<7) | (1<<6) | (0<<5)), | ||
344 | |||
345 | /* mode_backlight */ | ||
346 | 7 | ||
347 | }, | 364 | }, |
365 | }; | ||
348 | 366 | ||
349 | { /* 4: Pb1100 640x480x16bpp NEON CRT */ | 367 | struct au1100fb_drv_info { |
350 | 640, /* xres */ | 368 | int panel_idx; |
351 | 480, /* yres */ | 369 | char *opt_mode; |
352 | 16, /* bpp */ | 370 | }; |
353 | |||
354 | "NEON_640x480_16", | ||
355 | |||
356 | /* mode_control */ | ||
357 | 0x0004886A | LCD_DEFAULT_PIX_FORMAT, | ||
358 | |||
359 | /* mode_horztiming */ | ||
360 | 0x0052E27F, | ||
361 | |||
362 | /* mode_verttiming */ | ||
363 | 0x18000DDF, | ||
364 | |||
365 | /* mode_clkcontrol */ | ||
366 | 0x00020000, | ||
367 | 371 | ||
368 | /* mode_pwmdiv */ | 372 | /********************************************************************/ |
369 | 0, | ||
370 | 373 | ||
371 | /* mode_pwmhi */ | 374 | /* Inline helpers */ |
372 | 0, | ||
373 | 375 | ||
374 | /* mode_toyclksrc */ | 376 | #define panel_is_dual(panel) (panel->control_base & LCD_CONTROL_DP) |
375 | ((1<<7) | (1<<6) | (0<<5)), | 377 | #define panel_is_active(panel)(panel->control_base & LCD_CONTROL_PT) |
378 | #define panel_is_color(panel) (panel->control_base & LCD_CONTROL_PC) | ||
379 | #define panel_swap_rgb(panel) (panel->control_base & LCD_CONTROL_CCO) | ||
376 | 380 | ||
377 | /* mode_backlight */ | ||
378 | 7 | ||
379 | }, | ||
380 | }; | ||
381 | #endif /* _AU1100LCD_H */ | 381 | #endif /* _AU1100LCD_H */ |