Commit f969c5672b16b857e5231ad3c78f08d8ef3305aa
Committed by
Linus Torvalds
1 parent
dc10885d68
Exists in
master
and in
4 other branches
fsl-diu-db: compile fix
This patch fixes a compile failure in 2.6.26-rc5-git5. The variable is expected to be called ofdev. Signed-off-by: Jeff Mahoney <jeffm@suse.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 2 additions and 2 deletions Inline Diff
drivers/video/fsl-diu-fb.c
1 | /* | 1 | /* |
2 | * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. | 2 | * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * Freescale DIU Frame Buffer device driver | 4 | * Freescale DIU Frame Buffer device driver |
5 | * | 5 | * |
6 | * Authors: Hongjun Chen <hong-jun.chen@freescale.com> | 6 | * Authors: Hongjun Chen <hong-jun.chen@freescale.com> |
7 | * Paul Widmer <paul.widmer@freescale.com> | 7 | * Paul Widmer <paul.widmer@freescale.com> |
8 | * Srikanth Srinivasan <srikanth.srinivasan@freescale.com> | 8 | * Srikanth Srinivasan <srikanth.srinivasan@freescale.com> |
9 | * York Sun <yorksun@freescale.com> | 9 | * York Sun <yorksun@freescale.com> |
10 | * | 10 | * |
11 | * Based on imxfb.c Copyright (C) 2004 S.Hauer, Pengutronix | 11 | * Based on imxfb.c Copyright (C) 2004 S.Hauer, Pengutronix |
12 | * | 12 | * |
13 | * This program is free software; you can redistribute it and/or modify it | 13 | * This program is free software; you can redistribute it and/or modify it |
14 | * under the terms of the GNU General Public License as published by the | 14 | * under the terms of the GNU General Public License as published by the |
15 | * Free Software Foundation; either version 2 of the License, or (at your | 15 | * Free Software Foundation; either version 2 of the License, or (at your |
16 | * option) any later version. | 16 | * option) any later version. |
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/fb.h> | 25 | #include <linux/fb.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/dma-mapping.h> | 27 | #include <linux/dma-mapping.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/uaccess.h> | 31 | #include <linux/uaccess.h> |
32 | #include <linux/vmalloc.h> | 32 | #include <linux/vmalloc.h> |
33 | 33 | ||
34 | #include <linux/of_platform.h> | 34 | #include <linux/of_platform.h> |
35 | 35 | ||
36 | #include <sysdev/fsl_soc.h> | 36 | #include <sysdev/fsl_soc.h> |
37 | #include "fsl-diu-fb.h" | 37 | #include "fsl-diu-fb.h" |
38 | 38 | ||
39 | /* | 39 | /* |
40 | * These parameters give default parameters | 40 | * These parameters give default parameters |
41 | * for video output 1024x768, | 41 | * for video output 1024x768, |
42 | * FIXME - change timing to proper amounts | 42 | * FIXME - change timing to proper amounts |
43 | * hsync 31.5kHz, vsync 60Hz | 43 | * hsync 31.5kHz, vsync 60Hz |
44 | */ | 44 | */ |
45 | static struct fb_videomode __devinitdata fsl_diu_default_mode = { | 45 | static struct fb_videomode __devinitdata fsl_diu_default_mode = { |
46 | .refresh = 60, | 46 | .refresh = 60, |
47 | .xres = 1024, | 47 | .xres = 1024, |
48 | .yres = 768, | 48 | .yres = 768, |
49 | .pixclock = 15385, | 49 | .pixclock = 15385, |
50 | .left_margin = 160, | 50 | .left_margin = 160, |
51 | .right_margin = 24, | 51 | .right_margin = 24, |
52 | .upper_margin = 29, | 52 | .upper_margin = 29, |
53 | .lower_margin = 3, | 53 | .lower_margin = 3, |
54 | .hsync_len = 136, | 54 | .hsync_len = 136, |
55 | .vsync_len = 6, | 55 | .vsync_len = 6, |
56 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 56 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
57 | .vmode = FB_VMODE_NONINTERLACED | 57 | .vmode = FB_VMODE_NONINTERLACED |
58 | }; | 58 | }; |
59 | 59 | ||
60 | static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | 60 | static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { |
61 | { | 61 | { |
62 | .name = "1024x768-60", | 62 | .name = "1024x768-60", |
63 | .refresh = 60, | 63 | .refresh = 60, |
64 | .xres = 1024, | 64 | .xres = 1024, |
65 | .yres = 768, | 65 | .yres = 768, |
66 | .pixclock = 15385, | 66 | .pixclock = 15385, |
67 | .left_margin = 160, | 67 | .left_margin = 160, |
68 | .right_margin = 24, | 68 | .right_margin = 24, |
69 | .upper_margin = 29, | 69 | .upper_margin = 29, |
70 | .lower_margin = 3, | 70 | .lower_margin = 3, |
71 | .hsync_len = 136, | 71 | .hsync_len = 136, |
72 | .vsync_len = 6, | 72 | .vsync_len = 6, |
73 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 73 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
74 | .vmode = FB_VMODE_NONINTERLACED | 74 | .vmode = FB_VMODE_NONINTERLACED |
75 | }, | 75 | }, |
76 | { | 76 | { |
77 | .name = "1024x768-70", | 77 | .name = "1024x768-70", |
78 | .refresh = 70, | 78 | .refresh = 70, |
79 | .xres = 1024, | 79 | .xres = 1024, |
80 | .yres = 768, | 80 | .yres = 768, |
81 | .pixclock = 16886, | 81 | .pixclock = 16886, |
82 | .left_margin = 3, | 82 | .left_margin = 3, |
83 | .right_margin = 3, | 83 | .right_margin = 3, |
84 | .upper_margin = 2, | 84 | .upper_margin = 2, |
85 | .lower_margin = 2, | 85 | .lower_margin = 2, |
86 | .hsync_len = 40, | 86 | .hsync_len = 40, |
87 | .vsync_len = 18, | 87 | .vsync_len = 18, |
88 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 88 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
89 | .vmode = FB_VMODE_NONINTERLACED | 89 | .vmode = FB_VMODE_NONINTERLACED |
90 | }, | 90 | }, |
91 | { | 91 | { |
92 | .name = "1024x768-75", | 92 | .name = "1024x768-75", |
93 | .refresh = 75, | 93 | .refresh = 75, |
94 | .xres = 1024, | 94 | .xres = 1024, |
95 | .yres = 768, | 95 | .yres = 768, |
96 | .pixclock = 15009, | 96 | .pixclock = 15009, |
97 | .left_margin = 3, | 97 | .left_margin = 3, |
98 | .right_margin = 3, | 98 | .right_margin = 3, |
99 | .upper_margin = 2, | 99 | .upper_margin = 2, |
100 | .lower_margin = 2, | 100 | .lower_margin = 2, |
101 | .hsync_len = 80, | 101 | .hsync_len = 80, |
102 | .vsync_len = 32, | 102 | .vsync_len = 32, |
103 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 103 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
104 | .vmode = FB_VMODE_NONINTERLACED | 104 | .vmode = FB_VMODE_NONINTERLACED |
105 | }, | 105 | }, |
106 | { | 106 | { |
107 | .name = "1280x1024-60", | 107 | .name = "1280x1024-60", |
108 | .refresh = 60, | 108 | .refresh = 60, |
109 | .xres = 1280, | 109 | .xres = 1280, |
110 | .yres = 1024, | 110 | .yres = 1024, |
111 | .pixclock = 9375, | 111 | .pixclock = 9375, |
112 | .left_margin = 38, | 112 | .left_margin = 38, |
113 | .right_margin = 128, | 113 | .right_margin = 128, |
114 | .upper_margin = 2, | 114 | .upper_margin = 2, |
115 | .lower_margin = 7, | 115 | .lower_margin = 7, |
116 | .hsync_len = 216, | 116 | .hsync_len = 216, |
117 | .vsync_len = 37, | 117 | .vsync_len = 37, |
118 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 118 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
119 | .vmode = FB_VMODE_NONINTERLACED | 119 | .vmode = FB_VMODE_NONINTERLACED |
120 | }, | 120 | }, |
121 | { | 121 | { |
122 | .name = "1280x1024-70", | 122 | .name = "1280x1024-70", |
123 | .refresh = 70, | 123 | .refresh = 70, |
124 | .xres = 1280, | 124 | .xres = 1280, |
125 | .yres = 1024, | 125 | .yres = 1024, |
126 | .pixclock = 9380, | 126 | .pixclock = 9380, |
127 | .left_margin = 6, | 127 | .left_margin = 6, |
128 | .right_margin = 6, | 128 | .right_margin = 6, |
129 | .upper_margin = 4, | 129 | .upper_margin = 4, |
130 | .lower_margin = 4, | 130 | .lower_margin = 4, |
131 | .hsync_len = 60, | 131 | .hsync_len = 60, |
132 | .vsync_len = 94, | 132 | .vsync_len = 94, |
133 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 133 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
134 | .vmode = FB_VMODE_NONINTERLACED | 134 | .vmode = FB_VMODE_NONINTERLACED |
135 | }, | 135 | }, |
136 | { | 136 | { |
137 | .name = "1280x1024-75", | 137 | .name = "1280x1024-75", |
138 | .refresh = 75, | 138 | .refresh = 75, |
139 | .xres = 1280, | 139 | .xres = 1280, |
140 | .yres = 1024, | 140 | .yres = 1024, |
141 | .pixclock = 9380, | 141 | .pixclock = 9380, |
142 | .left_margin = 6, | 142 | .left_margin = 6, |
143 | .right_margin = 6, | 143 | .right_margin = 6, |
144 | .upper_margin = 4, | 144 | .upper_margin = 4, |
145 | .lower_margin = 4, | 145 | .lower_margin = 4, |
146 | .hsync_len = 60, | 146 | .hsync_len = 60, |
147 | .vsync_len = 15, | 147 | .vsync_len = 15, |
148 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 148 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
149 | .vmode = FB_VMODE_NONINTERLACED | 149 | .vmode = FB_VMODE_NONINTERLACED |
150 | }, | 150 | }, |
151 | { | 151 | { |
152 | .name = "320x240", /* for AOI only */ | 152 | .name = "320x240", /* for AOI only */ |
153 | .refresh = 60, | 153 | .refresh = 60, |
154 | .xres = 320, | 154 | .xres = 320, |
155 | .yres = 240, | 155 | .yres = 240, |
156 | .pixclock = 15385, | 156 | .pixclock = 15385, |
157 | .left_margin = 0, | 157 | .left_margin = 0, |
158 | .right_margin = 0, | 158 | .right_margin = 0, |
159 | .upper_margin = 0, | 159 | .upper_margin = 0, |
160 | .lower_margin = 0, | 160 | .lower_margin = 0, |
161 | .hsync_len = 0, | 161 | .hsync_len = 0, |
162 | .vsync_len = 0, | 162 | .vsync_len = 0, |
163 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 163 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
164 | .vmode = FB_VMODE_NONINTERLACED | 164 | .vmode = FB_VMODE_NONINTERLACED |
165 | }, | 165 | }, |
166 | { | 166 | { |
167 | .name = "1280x480-60", | 167 | .name = "1280x480-60", |
168 | .refresh = 60, | 168 | .refresh = 60, |
169 | .xres = 1280, | 169 | .xres = 1280, |
170 | .yres = 480, | 170 | .yres = 480, |
171 | .pixclock = 18939, | 171 | .pixclock = 18939, |
172 | .left_margin = 353, | 172 | .left_margin = 353, |
173 | .right_margin = 47, | 173 | .right_margin = 47, |
174 | .upper_margin = 39, | 174 | .upper_margin = 39, |
175 | .lower_margin = 4, | 175 | .lower_margin = 4, |
176 | .hsync_len = 8, | 176 | .hsync_len = 8, |
177 | .vsync_len = 2, | 177 | .vsync_len = 2, |
178 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 178 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
179 | .vmode = FB_VMODE_NONINTERLACED | 179 | .vmode = FB_VMODE_NONINTERLACED |
180 | }, | 180 | }, |
181 | }; | 181 | }; |
182 | 182 | ||
183 | static char *fb_mode = "1024x768-32@60"; | 183 | static char *fb_mode = "1024x768-32@60"; |
184 | static unsigned long default_bpp = 32; | 184 | static unsigned long default_bpp = 32; |
185 | static int monitor_port; | 185 | static int monitor_port; |
186 | 186 | ||
187 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 187 | #if defined(CONFIG_NOT_COHERENT_CACHE) |
188 | static u8 *coherence_data; | 188 | static u8 *coherence_data; |
189 | static size_t coherence_data_size; | 189 | static size_t coherence_data_size; |
190 | static unsigned int d_cache_line_size; | 190 | static unsigned int d_cache_line_size; |
191 | #endif | 191 | #endif |
192 | 192 | ||
193 | static DEFINE_SPINLOCK(diu_lock); | 193 | static DEFINE_SPINLOCK(diu_lock); |
194 | 194 | ||
195 | struct fsl_diu_data { | 195 | struct fsl_diu_data { |
196 | struct fb_info *fsl_diu_info[FSL_AOI_NUM - 1]; | 196 | struct fb_info *fsl_diu_info[FSL_AOI_NUM - 1]; |
197 | /*FSL_AOI_NUM has one dummy AOI */ | 197 | /*FSL_AOI_NUM has one dummy AOI */ |
198 | struct device_attribute dev_attr; | 198 | struct device_attribute dev_attr; |
199 | struct diu_ad *dummy_ad; | 199 | struct diu_ad *dummy_ad; |
200 | void *dummy_aoi_virt; | 200 | void *dummy_aoi_virt; |
201 | unsigned int irq; | 201 | unsigned int irq; |
202 | int fb_enabled; | 202 | int fb_enabled; |
203 | int monitor_port; | 203 | int monitor_port; |
204 | }; | 204 | }; |
205 | 205 | ||
206 | struct mfb_info { | 206 | struct mfb_info { |
207 | int index; | 207 | int index; |
208 | int type; | 208 | int type; |
209 | char *id; | 209 | char *id; |
210 | int registered; | 210 | int registered; |
211 | int blank; | 211 | int blank; |
212 | unsigned long pseudo_palette[16]; | 212 | unsigned long pseudo_palette[16]; |
213 | struct diu_ad *ad; | 213 | struct diu_ad *ad; |
214 | int cursor_reset; | 214 | int cursor_reset; |
215 | unsigned char g_alpha; | 215 | unsigned char g_alpha; |
216 | unsigned int count; | 216 | unsigned int count; |
217 | int x_aoi_d; /* aoi display x offset to physical screen */ | 217 | int x_aoi_d; /* aoi display x offset to physical screen */ |
218 | int y_aoi_d; /* aoi display y offset to physical screen */ | 218 | int y_aoi_d; /* aoi display y offset to physical screen */ |
219 | struct fsl_diu_data *parent; | 219 | struct fsl_diu_data *parent; |
220 | }; | 220 | }; |
221 | 221 | ||
222 | 222 | ||
223 | static struct mfb_info mfb_template[] = { | 223 | static struct mfb_info mfb_template[] = { |
224 | { /* AOI 0 for plane 0 */ | 224 | { /* AOI 0 for plane 0 */ |
225 | .index = 0, | 225 | .index = 0, |
226 | .type = MFB_TYPE_OUTPUT, | 226 | .type = MFB_TYPE_OUTPUT, |
227 | .id = "Panel0", | 227 | .id = "Panel0", |
228 | .registered = 0, | 228 | .registered = 0, |
229 | .count = 0, | 229 | .count = 0, |
230 | .x_aoi_d = 0, | 230 | .x_aoi_d = 0, |
231 | .y_aoi_d = 0, | 231 | .y_aoi_d = 0, |
232 | }, | 232 | }, |
233 | { /* AOI 0 for plane 1 */ | 233 | { /* AOI 0 for plane 1 */ |
234 | .index = 1, | 234 | .index = 1, |
235 | .type = MFB_TYPE_OUTPUT, | 235 | .type = MFB_TYPE_OUTPUT, |
236 | .id = "Panel1 AOI0", | 236 | .id = "Panel1 AOI0", |
237 | .registered = 0, | 237 | .registered = 0, |
238 | .g_alpha = 0xff, | 238 | .g_alpha = 0xff, |
239 | .count = 0, | 239 | .count = 0, |
240 | .x_aoi_d = 0, | 240 | .x_aoi_d = 0, |
241 | .y_aoi_d = 0, | 241 | .y_aoi_d = 0, |
242 | }, | 242 | }, |
243 | { /* AOI 1 for plane 1 */ | 243 | { /* AOI 1 for plane 1 */ |
244 | .index = 2, | 244 | .index = 2, |
245 | .type = MFB_TYPE_OUTPUT, | 245 | .type = MFB_TYPE_OUTPUT, |
246 | .id = "Panel1 AOI1", | 246 | .id = "Panel1 AOI1", |
247 | .registered = 0, | 247 | .registered = 0, |
248 | .g_alpha = 0xff, | 248 | .g_alpha = 0xff, |
249 | .count = 0, | 249 | .count = 0, |
250 | .x_aoi_d = 0, | 250 | .x_aoi_d = 0, |
251 | .y_aoi_d = 480, | 251 | .y_aoi_d = 480, |
252 | }, | 252 | }, |
253 | { /* AOI 0 for plane 2 */ | 253 | { /* AOI 0 for plane 2 */ |
254 | .index = 3, | 254 | .index = 3, |
255 | .type = MFB_TYPE_OUTPUT, | 255 | .type = MFB_TYPE_OUTPUT, |
256 | .id = "Panel2 AOI0", | 256 | .id = "Panel2 AOI0", |
257 | .registered = 0, | 257 | .registered = 0, |
258 | .g_alpha = 0xff, | 258 | .g_alpha = 0xff, |
259 | .count = 0, | 259 | .count = 0, |
260 | .x_aoi_d = 640, | 260 | .x_aoi_d = 640, |
261 | .y_aoi_d = 0, | 261 | .y_aoi_d = 0, |
262 | }, | 262 | }, |
263 | { /* AOI 1 for plane 2 */ | 263 | { /* AOI 1 for plane 2 */ |
264 | .index = 4, | 264 | .index = 4, |
265 | .type = MFB_TYPE_OUTPUT, | 265 | .type = MFB_TYPE_OUTPUT, |
266 | .id = "Panel2 AOI1", | 266 | .id = "Panel2 AOI1", |
267 | .registered = 0, | 267 | .registered = 0, |
268 | .g_alpha = 0xff, | 268 | .g_alpha = 0xff, |
269 | .count = 0, | 269 | .count = 0, |
270 | .x_aoi_d = 640, | 270 | .x_aoi_d = 640, |
271 | .y_aoi_d = 480, | 271 | .y_aoi_d = 480, |
272 | }, | 272 | }, |
273 | }; | 273 | }; |
274 | 274 | ||
275 | static struct diu_hw dr = { | 275 | static struct diu_hw dr = { |
276 | .mode = MFB_MODE1, | 276 | .mode = MFB_MODE1, |
277 | .reg_lock = __SPIN_LOCK_UNLOCKED(diu_hw.reg_lock), | 277 | .reg_lock = __SPIN_LOCK_UNLOCKED(diu_hw.reg_lock), |
278 | }; | 278 | }; |
279 | 279 | ||
280 | static struct diu_pool pool; | 280 | static struct diu_pool pool; |
281 | 281 | ||
282 | /* To allocate memory for framebuffer. First try __get_free_pages(). If it | 282 | /* To allocate memory for framebuffer. First try __get_free_pages(). If it |
283 | * fails, try rh_alloc. The reason is __get_free_pages() cannot allocate | 283 | * fails, try rh_alloc. The reason is __get_free_pages() cannot allocate |
284 | * very large memory (more than 4MB). We don't want to allocate all memory | 284 | * very large memory (more than 4MB). We don't want to allocate all memory |
285 | * in rheap since small memory allocation/deallocation will fragment the | 285 | * in rheap since small memory allocation/deallocation will fragment the |
286 | * rheap and make the furture large allocation fail. | 286 | * rheap and make the furture large allocation fail. |
287 | */ | 287 | */ |
288 | 288 | ||
289 | void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys) | 289 | void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys) |
290 | { | 290 | { |
291 | void *virt; | 291 | void *virt; |
292 | 292 | ||
293 | pr_debug("size=%lu\n", size); | 293 | pr_debug("size=%lu\n", size); |
294 | 294 | ||
295 | virt = (void *)__get_free_pages(GFP_DMA | __GFP_ZERO, get_order(size)); | 295 | virt = (void *)__get_free_pages(GFP_DMA | __GFP_ZERO, get_order(size)); |
296 | if (virt) { | 296 | if (virt) { |
297 | *phys = virt_to_phys(virt); | 297 | *phys = virt_to_phys(virt); |
298 | pr_debug("virt %p, phys=%llx\n", virt, (uint64_t) *phys); | 298 | pr_debug("virt %p, phys=%llx\n", virt, (uint64_t) *phys); |
299 | return virt; | 299 | return virt; |
300 | } | 300 | } |
301 | if (!diu_ops.diu_mem) { | 301 | if (!diu_ops.diu_mem) { |
302 | printk(KERN_INFO "%s: no diu_mem." | 302 | printk(KERN_INFO "%s: no diu_mem." |
303 | " To reserve more memory, put 'diufb=15M' " | 303 | " To reserve more memory, put 'diufb=15M' " |
304 | "in the command line\n", __func__); | 304 | "in the command line\n", __func__); |
305 | return NULL; | 305 | return NULL; |
306 | } | 306 | } |
307 | 307 | ||
308 | virt = (void *)rh_alloc(&diu_ops.diu_rh_info, size, "DIU"); | 308 | virt = (void *)rh_alloc(&diu_ops.diu_rh_info, size, "DIU"); |
309 | if (virt) { | 309 | if (virt) { |
310 | *phys = virt_to_bus(virt); | 310 | *phys = virt_to_bus(virt); |
311 | memset(virt, 0, size); | 311 | memset(virt, 0, size); |
312 | } | 312 | } |
313 | 313 | ||
314 | pr_debug("rh virt=%p phys=%lx\n", virt, *phys); | 314 | pr_debug("rh virt=%p phys=%lx\n", virt, *phys); |
315 | 315 | ||
316 | return virt; | 316 | return virt; |
317 | } | 317 | } |
318 | 318 | ||
319 | void fsl_diu_free(void *p, unsigned long size) | 319 | void fsl_diu_free(void *p, unsigned long size) |
320 | { | 320 | { |
321 | pr_debug("p=%p size=%lu\n", p, size); | 321 | pr_debug("p=%p size=%lu\n", p, size); |
322 | 322 | ||
323 | if (!p) | 323 | if (!p) |
324 | return; | 324 | return; |
325 | 325 | ||
326 | if ((p >= diu_ops.diu_mem) && | 326 | if ((p >= diu_ops.diu_mem) && |
327 | (p < (diu_ops.diu_mem + diu_ops.diu_size))) { | 327 | (p < (diu_ops.diu_mem + diu_ops.diu_size))) { |
328 | pr_debug("rh\n"); | 328 | pr_debug("rh\n"); |
329 | rh_free(&diu_ops.diu_rh_info, (unsigned long) p); | 329 | rh_free(&diu_ops.diu_rh_info, (unsigned long) p); |
330 | } else { | 330 | } else { |
331 | pr_debug("dma\n"); | 331 | pr_debug("dma\n"); |
332 | free_pages((unsigned long)p, get_order(size)); | 332 | free_pages((unsigned long)p, get_order(size)); |
333 | } | 333 | } |
334 | } | 334 | } |
335 | 335 | ||
336 | static int fsl_diu_enable_panel(struct fb_info *info) | 336 | static int fsl_diu_enable_panel(struct fb_info *info) |
337 | { | 337 | { |
338 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; | 338 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; |
339 | struct diu *hw = dr.diu_reg; | 339 | struct diu *hw = dr.diu_reg; |
340 | struct diu_ad *ad = mfbi->ad; | 340 | struct diu_ad *ad = mfbi->ad; |
341 | struct fsl_diu_data *machine_data = mfbi->parent; | 341 | struct fsl_diu_data *machine_data = mfbi->parent; |
342 | int res = 0; | 342 | int res = 0; |
343 | 343 | ||
344 | pr_debug("enable_panel index %d\n", mfbi->index); | 344 | pr_debug("enable_panel index %d\n", mfbi->index); |
345 | if (mfbi->type != MFB_TYPE_OFF) { | 345 | if (mfbi->type != MFB_TYPE_OFF) { |
346 | switch (mfbi->index) { | 346 | switch (mfbi->index) { |
347 | case 0: /* plane 0 */ | 347 | case 0: /* plane 0 */ |
348 | if (hw->desc[0] != ad->paddr) | 348 | if (hw->desc[0] != ad->paddr) |
349 | out_be32(&hw->desc[0], ad->paddr); | 349 | out_be32(&hw->desc[0], ad->paddr); |
350 | break; | 350 | break; |
351 | case 1: /* plane 1 AOI 0 */ | 351 | case 1: /* plane 1 AOI 0 */ |
352 | cmfbi = machine_data->fsl_diu_info[2]->par; | 352 | cmfbi = machine_data->fsl_diu_info[2]->par; |
353 | if (hw->desc[1] != ad->paddr) { /* AOI0 closed */ | 353 | if (hw->desc[1] != ad->paddr) { /* AOI0 closed */ |
354 | if (cmfbi->count > 0) /* AOI1 open */ | 354 | if (cmfbi->count > 0) /* AOI1 open */ |
355 | ad->next_ad = | 355 | ad->next_ad = |
356 | cpu_to_le32(cmfbi->ad->paddr); | 356 | cpu_to_le32(cmfbi->ad->paddr); |
357 | else | 357 | else |
358 | ad->next_ad = 0; | 358 | ad->next_ad = 0; |
359 | out_be32(&hw->desc[1], ad->paddr); | 359 | out_be32(&hw->desc[1], ad->paddr); |
360 | } | 360 | } |
361 | break; | 361 | break; |
362 | case 3: /* plane 2 AOI 0 */ | 362 | case 3: /* plane 2 AOI 0 */ |
363 | cmfbi = machine_data->fsl_diu_info[4]->par; | 363 | cmfbi = machine_data->fsl_diu_info[4]->par; |
364 | if (hw->desc[2] != ad->paddr) { /* AOI0 closed */ | 364 | if (hw->desc[2] != ad->paddr) { /* AOI0 closed */ |
365 | if (cmfbi->count > 0) /* AOI1 open */ | 365 | if (cmfbi->count > 0) /* AOI1 open */ |
366 | ad->next_ad = | 366 | ad->next_ad = |
367 | cpu_to_le32(cmfbi->ad->paddr); | 367 | cpu_to_le32(cmfbi->ad->paddr); |
368 | else | 368 | else |
369 | ad->next_ad = 0; | 369 | ad->next_ad = 0; |
370 | out_be32(&hw->desc[2], ad->paddr); | 370 | out_be32(&hw->desc[2], ad->paddr); |
371 | } | 371 | } |
372 | break; | 372 | break; |
373 | case 2: /* plane 1 AOI 1 */ | 373 | case 2: /* plane 1 AOI 1 */ |
374 | pmfbi = machine_data->fsl_diu_info[1]->par; | 374 | pmfbi = machine_data->fsl_diu_info[1]->par; |
375 | ad->next_ad = 0; | 375 | ad->next_ad = 0; |
376 | if (hw->desc[1] == machine_data->dummy_ad->paddr) | 376 | if (hw->desc[1] == machine_data->dummy_ad->paddr) |
377 | out_be32(&hw->desc[1], ad->paddr); | 377 | out_be32(&hw->desc[1], ad->paddr); |
378 | else /* AOI0 open */ | 378 | else /* AOI0 open */ |
379 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); | 379 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); |
380 | break; | 380 | break; |
381 | case 4: /* plane 2 AOI 1 */ | 381 | case 4: /* plane 2 AOI 1 */ |
382 | pmfbi = machine_data->fsl_diu_info[3]->par; | 382 | pmfbi = machine_data->fsl_diu_info[3]->par; |
383 | ad->next_ad = 0; | 383 | ad->next_ad = 0; |
384 | if (hw->desc[2] == machine_data->dummy_ad->paddr) | 384 | if (hw->desc[2] == machine_data->dummy_ad->paddr) |
385 | out_be32(&hw->desc[2], ad->paddr); | 385 | out_be32(&hw->desc[2], ad->paddr); |
386 | else /* AOI0 was open */ | 386 | else /* AOI0 was open */ |
387 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); | 387 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); |
388 | break; | 388 | break; |
389 | default: | 389 | default: |
390 | res = -EINVAL; | 390 | res = -EINVAL; |
391 | break; | 391 | break; |
392 | } | 392 | } |
393 | } else | 393 | } else |
394 | res = -EINVAL; | 394 | res = -EINVAL; |
395 | return res; | 395 | return res; |
396 | } | 396 | } |
397 | 397 | ||
398 | static int fsl_diu_disable_panel(struct fb_info *info) | 398 | static int fsl_diu_disable_panel(struct fb_info *info) |
399 | { | 399 | { |
400 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; | 400 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; |
401 | struct diu *hw = dr.diu_reg; | 401 | struct diu *hw = dr.diu_reg; |
402 | struct diu_ad *ad = mfbi->ad; | 402 | struct diu_ad *ad = mfbi->ad; |
403 | struct fsl_diu_data *machine_data = mfbi->parent; | 403 | struct fsl_diu_data *machine_data = mfbi->parent; |
404 | int res = 0; | 404 | int res = 0; |
405 | 405 | ||
406 | switch (mfbi->index) { | 406 | switch (mfbi->index) { |
407 | case 0: /* plane 0 */ | 407 | case 0: /* plane 0 */ |
408 | if (hw->desc[0] != machine_data->dummy_ad->paddr) | 408 | if (hw->desc[0] != machine_data->dummy_ad->paddr) |
409 | out_be32(&hw->desc[0], | 409 | out_be32(&hw->desc[0], |
410 | machine_data->dummy_ad->paddr); | 410 | machine_data->dummy_ad->paddr); |
411 | break; | 411 | break; |
412 | case 1: /* plane 1 AOI 0 */ | 412 | case 1: /* plane 1 AOI 0 */ |
413 | cmfbi = machine_data->fsl_diu_info[2]->par; | 413 | cmfbi = machine_data->fsl_diu_info[2]->par; |
414 | if (cmfbi->count > 0) /* AOI1 is open */ | 414 | if (cmfbi->count > 0) /* AOI1 is open */ |
415 | out_be32(&hw->desc[1], cmfbi->ad->paddr); | 415 | out_be32(&hw->desc[1], cmfbi->ad->paddr); |
416 | /* move AOI1 to the first */ | 416 | /* move AOI1 to the first */ |
417 | else /* AOI1 was closed */ | 417 | else /* AOI1 was closed */ |
418 | out_be32(&hw->desc[1], | 418 | out_be32(&hw->desc[1], |
419 | machine_data->dummy_ad->paddr); | 419 | machine_data->dummy_ad->paddr); |
420 | /* close AOI 0 */ | 420 | /* close AOI 0 */ |
421 | break; | 421 | break; |
422 | case 3: /* plane 2 AOI 0 */ | 422 | case 3: /* plane 2 AOI 0 */ |
423 | cmfbi = machine_data->fsl_diu_info[4]->par; | 423 | cmfbi = machine_data->fsl_diu_info[4]->par; |
424 | if (cmfbi->count > 0) /* AOI1 is open */ | 424 | if (cmfbi->count > 0) /* AOI1 is open */ |
425 | out_be32(&hw->desc[2], cmfbi->ad->paddr); | 425 | out_be32(&hw->desc[2], cmfbi->ad->paddr); |
426 | /* move AOI1 to the first */ | 426 | /* move AOI1 to the first */ |
427 | else /* AOI1 was closed */ | 427 | else /* AOI1 was closed */ |
428 | out_be32(&hw->desc[2], | 428 | out_be32(&hw->desc[2], |
429 | machine_data->dummy_ad->paddr); | 429 | machine_data->dummy_ad->paddr); |
430 | /* close AOI 0 */ | 430 | /* close AOI 0 */ |
431 | break; | 431 | break; |
432 | case 2: /* plane 1 AOI 1 */ | 432 | case 2: /* plane 1 AOI 1 */ |
433 | pmfbi = machine_data->fsl_diu_info[1]->par; | 433 | pmfbi = machine_data->fsl_diu_info[1]->par; |
434 | if (hw->desc[1] != ad->paddr) { | 434 | if (hw->desc[1] != ad->paddr) { |
435 | /* AOI1 is not the first in the chain */ | 435 | /* AOI1 is not the first in the chain */ |
436 | if (pmfbi->count > 0) | 436 | if (pmfbi->count > 0) |
437 | /* AOI0 is open, must be the first */ | 437 | /* AOI0 is open, must be the first */ |
438 | pmfbi->ad->next_ad = 0; | 438 | pmfbi->ad->next_ad = 0; |
439 | } else /* AOI1 is the first in the chain */ | 439 | } else /* AOI1 is the first in the chain */ |
440 | out_be32(&hw->desc[1], machine_data->dummy_ad->paddr); | 440 | out_be32(&hw->desc[1], machine_data->dummy_ad->paddr); |
441 | /* close AOI 1 */ | 441 | /* close AOI 1 */ |
442 | break; | 442 | break; |
443 | case 4: /* plane 2 AOI 1 */ | 443 | case 4: /* plane 2 AOI 1 */ |
444 | pmfbi = machine_data->fsl_diu_info[3]->par; | 444 | pmfbi = machine_data->fsl_diu_info[3]->par; |
445 | if (hw->desc[2] != ad->paddr) { | 445 | if (hw->desc[2] != ad->paddr) { |
446 | /* AOI1 is not the first in the chain */ | 446 | /* AOI1 is not the first in the chain */ |
447 | if (pmfbi->count > 0) | 447 | if (pmfbi->count > 0) |
448 | /* AOI0 is open, must be the first */ | 448 | /* AOI0 is open, must be the first */ |
449 | pmfbi->ad->next_ad = 0; | 449 | pmfbi->ad->next_ad = 0; |
450 | } else /* AOI1 is the first in the chain */ | 450 | } else /* AOI1 is the first in the chain */ |
451 | out_be32(&hw->desc[2], machine_data->dummy_ad->paddr); | 451 | out_be32(&hw->desc[2], machine_data->dummy_ad->paddr); |
452 | /* close AOI 1 */ | 452 | /* close AOI 1 */ |
453 | break; | 453 | break; |
454 | default: | 454 | default: |
455 | res = -EINVAL; | 455 | res = -EINVAL; |
456 | break; | 456 | break; |
457 | } | 457 | } |
458 | 458 | ||
459 | return res; | 459 | return res; |
460 | } | 460 | } |
461 | 461 | ||
462 | static void enable_lcdc(struct fb_info *info) | 462 | static void enable_lcdc(struct fb_info *info) |
463 | { | 463 | { |
464 | struct diu *hw = dr.diu_reg; | 464 | struct diu *hw = dr.diu_reg; |
465 | struct mfb_info *mfbi = info->par; | 465 | struct mfb_info *mfbi = info->par; |
466 | struct fsl_diu_data *machine_data = mfbi->parent; | 466 | struct fsl_diu_data *machine_data = mfbi->parent; |
467 | 467 | ||
468 | if (!machine_data->fb_enabled) { | 468 | if (!machine_data->fb_enabled) { |
469 | out_be32(&hw->diu_mode, dr.mode); | 469 | out_be32(&hw->diu_mode, dr.mode); |
470 | machine_data->fb_enabled++; | 470 | machine_data->fb_enabled++; |
471 | } | 471 | } |
472 | } | 472 | } |
473 | 473 | ||
474 | static void disable_lcdc(struct fb_info *info) | 474 | static void disable_lcdc(struct fb_info *info) |
475 | { | 475 | { |
476 | struct diu *hw = dr.diu_reg; | 476 | struct diu *hw = dr.diu_reg; |
477 | struct mfb_info *mfbi = info->par; | 477 | struct mfb_info *mfbi = info->par; |
478 | struct fsl_diu_data *machine_data = mfbi->parent; | 478 | struct fsl_diu_data *machine_data = mfbi->parent; |
479 | 479 | ||
480 | if (machine_data->fb_enabled) { | 480 | if (machine_data->fb_enabled) { |
481 | out_be32(&hw->diu_mode, 0); | 481 | out_be32(&hw->diu_mode, 0); |
482 | machine_data->fb_enabled = 0; | 482 | machine_data->fb_enabled = 0; |
483 | } | 483 | } |
484 | } | 484 | } |
485 | 485 | ||
486 | static void adjust_aoi_size_position(struct fb_var_screeninfo *var, | 486 | static void adjust_aoi_size_position(struct fb_var_screeninfo *var, |
487 | struct fb_info *info) | 487 | struct fb_info *info) |
488 | { | 488 | { |
489 | struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par; | 489 | struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par; |
490 | struct fsl_diu_data *machine_data = mfbi->parent; | 490 | struct fsl_diu_data *machine_data = mfbi->parent; |
491 | int available_height, upper_aoi_bottom, index = mfbi->index; | 491 | int available_height, upper_aoi_bottom, index = mfbi->index; |
492 | int lower_aoi_is_open, upper_aoi_is_open; | 492 | int lower_aoi_is_open, upper_aoi_is_open; |
493 | __u32 base_plane_width, base_plane_height, upper_aoi_height; | 493 | __u32 base_plane_width, base_plane_height, upper_aoi_height; |
494 | 494 | ||
495 | base_plane_width = machine_data->fsl_diu_info[0]->var.xres; | 495 | base_plane_width = machine_data->fsl_diu_info[0]->var.xres; |
496 | base_plane_height = machine_data->fsl_diu_info[0]->var.yres; | 496 | base_plane_height = machine_data->fsl_diu_info[0]->var.yres; |
497 | 497 | ||
498 | switch (index) { | 498 | switch (index) { |
499 | case 0: | 499 | case 0: |
500 | if (mfbi->x_aoi_d != 0) | 500 | if (mfbi->x_aoi_d != 0) |
501 | mfbi->x_aoi_d = 0; | 501 | mfbi->x_aoi_d = 0; |
502 | if (mfbi->y_aoi_d != 0) | 502 | if (mfbi->y_aoi_d != 0) |
503 | mfbi->y_aoi_d = 0; | 503 | mfbi->y_aoi_d = 0; |
504 | break; | 504 | break; |
505 | case 1: /* AOI 0 */ | 505 | case 1: /* AOI 0 */ |
506 | case 3: | 506 | case 3: |
507 | lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par; | 507 | lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par; |
508 | lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0; | 508 | lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0; |
509 | if (var->xres > base_plane_width) | 509 | if (var->xres > base_plane_width) |
510 | var->xres = base_plane_width; | 510 | var->xres = base_plane_width; |
511 | if ((mfbi->x_aoi_d + var->xres) > base_plane_width) | 511 | if ((mfbi->x_aoi_d + var->xres) > base_plane_width) |
512 | mfbi->x_aoi_d = base_plane_width - var->xres; | 512 | mfbi->x_aoi_d = base_plane_width - var->xres; |
513 | 513 | ||
514 | if (lower_aoi_is_open) | 514 | if (lower_aoi_is_open) |
515 | available_height = lower_aoi_mfbi->y_aoi_d; | 515 | available_height = lower_aoi_mfbi->y_aoi_d; |
516 | else | 516 | else |
517 | available_height = base_plane_height; | 517 | available_height = base_plane_height; |
518 | if (var->yres > available_height) | 518 | if (var->yres > available_height) |
519 | var->yres = available_height; | 519 | var->yres = available_height; |
520 | if ((mfbi->y_aoi_d + var->yres) > available_height) | 520 | if ((mfbi->y_aoi_d + var->yres) > available_height) |
521 | mfbi->y_aoi_d = available_height - var->yres; | 521 | mfbi->y_aoi_d = available_height - var->yres; |
522 | break; | 522 | break; |
523 | case 2: /* AOI 1 */ | 523 | case 2: /* AOI 1 */ |
524 | case 4: | 524 | case 4: |
525 | upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par; | 525 | upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par; |
526 | upper_aoi_height = | 526 | upper_aoi_height = |
527 | machine_data->fsl_diu_info[index-1]->var.yres; | 527 | machine_data->fsl_diu_info[index-1]->var.yres; |
528 | upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height; | 528 | upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height; |
529 | upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0; | 529 | upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0; |
530 | if (var->xres > base_plane_width) | 530 | if (var->xres > base_plane_width) |
531 | var->xres = base_plane_width; | 531 | var->xres = base_plane_width; |
532 | if ((mfbi->x_aoi_d + var->xres) > base_plane_width) | 532 | if ((mfbi->x_aoi_d + var->xres) > base_plane_width) |
533 | mfbi->x_aoi_d = base_plane_width - var->xres; | 533 | mfbi->x_aoi_d = base_plane_width - var->xres; |
534 | if (mfbi->y_aoi_d < 0) | 534 | if (mfbi->y_aoi_d < 0) |
535 | mfbi->y_aoi_d = 0; | 535 | mfbi->y_aoi_d = 0; |
536 | if (upper_aoi_is_open) { | 536 | if (upper_aoi_is_open) { |
537 | if (mfbi->y_aoi_d < upper_aoi_bottom) | 537 | if (mfbi->y_aoi_d < upper_aoi_bottom) |
538 | mfbi->y_aoi_d = upper_aoi_bottom; | 538 | mfbi->y_aoi_d = upper_aoi_bottom; |
539 | available_height = base_plane_height | 539 | available_height = base_plane_height |
540 | - upper_aoi_bottom; | 540 | - upper_aoi_bottom; |
541 | } else | 541 | } else |
542 | available_height = base_plane_height; | 542 | available_height = base_plane_height; |
543 | if (var->yres > available_height) | 543 | if (var->yres > available_height) |
544 | var->yres = available_height; | 544 | var->yres = available_height; |
545 | if ((mfbi->y_aoi_d + var->yres) > base_plane_height) | 545 | if ((mfbi->y_aoi_d + var->yres) > base_plane_height) |
546 | mfbi->y_aoi_d = base_plane_height - var->yres; | 546 | mfbi->y_aoi_d = base_plane_height - var->yres; |
547 | break; | 547 | break; |
548 | } | 548 | } |
549 | } | 549 | } |
550 | /* | 550 | /* |
551 | * Checks to see if the hardware supports the state requested by var passed | 551 | * Checks to see if the hardware supports the state requested by var passed |
552 | * in. This function does not alter the hardware state! If the var passed in | 552 | * in. This function does not alter the hardware state! If the var passed in |
553 | * is slightly off by what the hardware can support then we alter the var | 553 | * is slightly off by what the hardware can support then we alter the var |
554 | * PASSED in to what we can do. If the hardware doesn't support mode change | 554 | * PASSED in to what we can do. If the hardware doesn't support mode change |
555 | * a -EINVAL will be returned by the upper layers. | 555 | * a -EINVAL will be returned by the upper layers. |
556 | */ | 556 | */ |
557 | static int fsl_diu_check_var(struct fb_var_screeninfo *var, | 557 | static int fsl_diu_check_var(struct fb_var_screeninfo *var, |
558 | struct fb_info *info) | 558 | struct fb_info *info) |
559 | { | 559 | { |
560 | unsigned long htotal, vtotal; | 560 | unsigned long htotal, vtotal; |
561 | 561 | ||
562 | pr_debug("check_var xres: %d\n", var->xres); | 562 | pr_debug("check_var xres: %d\n", var->xres); |
563 | pr_debug("check_var yres: %d\n", var->yres); | 563 | pr_debug("check_var yres: %d\n", var->yres); |
564 | 564 | ||
565 | if (var->xres_virtual < var->xres) | 565 | if (var->xres_virtual < var->xres) |
566 | var->xres_virtual = var->xres; | 566 | var->xres_virtual = var->xres; |
567 | if (var->yres_virtual < var->yres) | 567 | if (var->yres_virtual < var->yres) |
568 | var->yres_virtual = var->yres; | 568 | var->yres_virtual = var->yres; |
569 | 569 | ||
570 | if (var->xoffset < 0) | 570 | if (var->xoffset < 0) |
571 | var->xoffset = 0; | 571 | var->xoffset = 0; |
572 | 572 | ||
573 | if (var->yoffset < 0) | 573 | if (var->yoffset < 0) |
574 | var->yoffset = 0; | 574 | var->yoffset = 0; |
575 | 575 | ||
576 | if (var->xoffset + info->var.xres > info->var.xres_virtual) | 576 | if (var->xoffset + info->var.xres > info->var.xres_virtual) |
577 | var->xoffset = info->var.xres_virtual - info->var.xres; | 577 | var->xoffset = info->var.xres_virtual - info->var.xres; |
578 | 578 | ||
579 | if (var->yoffset + info->var.yres > info->var.yres_virtual) | 579 | if (var->yoffset + info->var.yres > info->var.yres_virtual) |
580 | var->yoffset = info->var.yres_virtual - info->var.yres; | 580 | var->yoffset = info->var.yres_virtual - info->var.yres; |
581 | 581 | ||
582 | if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) && | 582 | if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) && |
583 | (var->bits_per_pixel != 16)) | 583 | (var->bits_per_pixel != 16)) |
584 | var->bits_per_pixel = default_bpp; | 584 | var->bits_per_pixel = default_bpp; |
585 | 585 | ||
586 | switch (var->bits_per_pixel) { | 586 | switch (var->bits_per_pixel) { |
587 | case 16: | 587 | case 16: |
588 | var->red.length = 5; | 588 | var->red.length = 5; |
589 | var->red.offset = 11; | 589 | var->red.offset = 11; |
590 | var->red.msb_right = 0; | 590 | var->red.msb_right = 0; |
591 | 591 | ||
592 | var->green.length = 6; | 592 | var->green.length = 6; |
593 | var->green.offset = 5; | 593 | var->green.offset = 5; |
594 | var->green.msb_right = 0; | 594 | var->green.msb_right = 0; |
595 | 595 | ||
596 | var->blue.length = 5; | 596 | var->blue.length = 5; |
597 | var->blue.offset = 0; | 597 | var->blue.offset = 0; |
598 | var->blue.msb_right = 0; | 598 | var->blue.msb_right = 0; |
599 | 599 | ||
600 | var->transp.length = 0; | 600 | var->transp.length = 0; |
601 | var->transp.offset = 0; | 601 | var->transp.offset = 0; |
602 | var->transp.msb_right = 0; | 602 | var->transp.msb_right = 0; |
603 | break; | 603 | break; |
604 | case 24: | 604 | case 24: |
605 | var->red.length = 8; | 605 | var->red.length = 8; |
606 | var->red.offset = 0; | 606 | var->red.offset = 0; |
607 | var->red.msb_right = 0; | 607 | var->red.msb_right = 0; |
608 | 608 | ||
609 | var->green.length = 8; | 609 | var->green.length = 8; |
610 | var->green.offset = 8; | 610 | var->green.offset = 8; |
611 | var->green.msb_right = 0; | 611 | var->green.msb_right = 0; |
612 | 612 | ||
613 | var->blue.length = 8; | 613 | var->blue.length = 8; |
614 | var->blue.offset = 16; | 614 | var->blue.offset = 16; |
615 | var->blue.msb_right = 0; | 615 | var->blue.msb_right = 0; |
616 | 616 | ||
617 | var->transp.length = 0; | 617 | var->transp.length = 0; |
618 | var->transp.offset = 0; | 618 | var->transp.offset = 0; |
619 | var->transp.msb_right = 0; | 619 | var->transp.msb_right = 0; |
620 | break; | 620 | break; |
621 | case 32: | 621 | case 32: |
622 | var->red.length = 8; | 622 | var->red.length = 8; |
623 | var->red.offset = 16; | 623 | var->red.offset = 16; |
624 | var->red.msb_right = 0; | 624 | var->red.msb_right = 0; |
625 | 625 | ||
626 | var->green.length = 8; | 626 | var->green.length = 8; |
627 | var->green.offset = 8; | 627 | var->green.offset = 8; |
628 | var->green.msb_right = 0; | 628 | var->green.msb_right = 0; |
629 | 629 | ||
630 | var->blue.length = 8; | 630 | var->blue.length = 8; |
631 | var->blue.offset = 0; | 631 | var->blue.offset = 0; |
632 | var->blue.msb_right = 0; | 632 | var->blue.msb_right = 0; |
633 | 633 | ||
634 | var->transp.length = 8; | 634 | var->transp.length = 8; |
635 | var->transp.offset = 24; | 635 | var->transp.offset = 24; |
636 | var->transp.msb_right = 0; | 636 | var->transp.msb_right = 0; |
637 | 637 | ||
638 | break; | 638 | break; |
639 | } | 639 | } |
640 | /* If the pixclock is below the minimum spec'd value then set to | 640 | /* If the pixclock is below the minimum spec'd value then set to |
641 | * refresh rate for 60Hz since this is supported by most monitors. | 641 | * refresh rate for 60Hz since this is supported by most monitors. |
642 | * Refer to Documentation/fb/ for calculations. | 642 | * Refer to Documentation/fb/ for calculations. |
643 | */ | 643 | */ |
644 | if ((var->pixclock < MIN_PIX_CLK) || (var->pixclock > MAX_PIX_CLK)) { | 644 | if ((var->pixclock < MIN_PIX_CLK) || (var->pixclock > MAX_PIX_CLK)) { |
645 | htotal = var->xres + var->right_margin + var->hsync_len + | 645 | htotal = var->xres + var->right_margin + var->hsync_len + |
646 | var->left_margin; | 646 | var->left_margin; |
647 | vtotal = var->yres + var->lower_margin + var->vsync_len + | 647 | vtotal = var->yres + var->lower_margin + var->vsync_len + |
648 | var->upper_margin; | 648 | var->upper_margin; |
649 | var->pixclock = (vtotal * htotal * 6UL) / 100UL; | 649 | var->pixclock = (vtotal * htotal * 6UL) / 100UL; |
650 | var->pixclock = KHZ2PICOS(var->pixclock); | 650 | var->pixclock = KHZ2PICOS(var->pixclock); |
651 | pr_debug("pixclock set for 60Hz refresh = %u ps\n", | 651 | pr_debug("pixclock set for 60Hz refresh = %u ps\n", |
652 | var->pixclock); | 652 | var->pixclock); |
653 | } | 653 | } |
654 | 654 | ||
655 | var->height = -1; | 655 | var->height = -1; |
656 | var->width = -1; | 656 | var->width = -1; |
657 | var->grayscale = 0; | 657 | var->grayscale = 0; |
658 | 658 | ||
659 | /* Copy nonstd field to/from sync for fbset usage */ | 659 | /* Copy nonstd field to/from sync for fbset usage */ |
660 | var->sync |= var->nonstd; | 660 | var->sync |= var->nonstd; |
661 | var->nonstd |= var->sync; | 661 | var->nonstd |= var->sync; |
662 | 662 | ||
663 | adjust_aoi_size_position(var, info); | 663 | adjust_aoi_size_position(var, info); |
664 | return 0; | 664 | return 0; |
665 | } | 665 | } |
666 | 666 | ||
667 | static void set_fix(struct fb_info *info) | 667 | static void set_fix(struct fb_info *info) |
668 | { | 668 | { |
669 | struct fb_fix_screeninfo *fix = &info->fix; | 669 | struct fb_fix_screeninfo *fix = &info->fix; |
670 | struct fb_var_screeninfo *var = &info->var; | 670 | struct fb_var_screeninfo *var = &info->var; |
671 | struct mfb_info *mfbi = info->par; | 671 | struct mfb_info *mfbi = info->par; |
672 | 672 | ||
673 | strncpy(fix->id, mfbi->id, strlen(mfbi->id)); | 673 | strncpy(fix->id, mfbi->id, strlen(mfbi->id)); |
674 | fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; | 674 | fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; |
675 | fix->type = FB_TYPE_PACKED_PIXELS; | 675 | fix->type = FB_TYPE_PACKED_PIXELS; |
676 | fix->accel = FB_ACCEL_NONE; | 676 | fix->accel = FB_ACCEL_NONE; |
677 | fix->visual = FB_VISUAL_TRUECOLOR; | 677 | fix->visual = FB_VISUAL_TRUECOLOR; |
678 | fix->xpanstep = 1; | 678 | fix->xpanstep = 1; |
679 | fix->ypanstep = 1; | 679 | fix->ypanstep = 1; |
680 | } | 680 | } |
681 | 681 | ||
682 | static void update_lcdc(struct fb_info *info) | 682 | static void update_lcdc(struct fb_info *info) |
683 | { | 683 | { |
684 | struct fb_var_screeninfo *var = &info->var; | 684 | struct fb_var_screeninfo *var = &info->var; |
685 | struct mfb_info *mfbi = info->par; | 685 | struct mfb_info *mfbi = info->par; |
686 | struct fsl_diu_data *machine_data = mfbi->parent; | 686 | struct fsl_diu_data *machine_data = mfbi->parent; |
687 | struct diu *hw; | 687 | struct diu *hw; |
688 | int i, j; | 688 | int i, j; |
689 | char __iomem *cursor_base, *gamma_table_base; | 689 | char __iomem *cursor_base, *gamma_table_base; |
690 | 690 | ||
691 | u32 temp; | 691 | u32 temp; |
692 | 692 | ||
693 | hw = dr.diu_reg; | 693 | hw = dr.diu_reg; |
694 | 694 | ||
695 | if (mfbi->type == MFB_TYPE_OFF) { | 695 | if (mfbi->type == MFB_TYPE_OFF) { |
696 | fsl_diu_disable_panel(info); | 696 | fsl_diu_disable_panel(info); |
697 | return; | 697 | return; |
698 | } | 698 | } |
699 | 699 | ||
700 | diu_ops.set_monitor_port(machine_data->monitor_port); | 700 | diu_ops.set_monitor_port(machine_data->monitor_port); |
701 | gamma_table_base = pool.gamma.vaddr; | 701 | gamma_table_base = pool.gamma.vaddr; |
702 | cursor_base = pool.cursor.vaddr; | 702 | cursor_base = pool.cursor.vaddr; |
703 | /* Prep for DIU init - gamma table, cursor table */ | 703 | /* Prep for DIU init - gamma table, cursor table */ |
704 | 704 | ||
705 | for (i = 0; i <= 2; i++) | 705 | for (i = 0; i <= 2; i++) |
706 | for (j = 0; j <= 255; j++) | 706 | for (j = 0; j <= 255; j++) |
707 | *gamma_table_base++ = j; | 707 | *gamma_table_base++ = j; |
708 | 708 | ||
709 | diu_ops.set_gamma_table(machine_data->monitor_port, pool.gamma.vaddr); | 709 | diu_ops.set_gamma_table(machine_data->monitor_port, pool.gamma.vaddr); |
710 | 710 | ||
711 | pr_debug("update-lcdc: HW - %p\n Disabling DIU\n", hw); | 711 | pr_debug("update-lcdc: HW - %p\n Disabling DIU\n", hw); |
712 | disable_lcdc(info); | 712 | disable_lcdc(info); |
713 | 713 | ||
714 | /* Program DIU registers */ | 714 | /* Program DIU registers */ |
715 | 715 | ||
716 | out_be32(&hw->gamma, pool.gamma.paddr); | 716 | out_be32(&hw->gamma, pool.gamma.paddr); |
717 | out_be32(&hw->cursor, pool.cursor.paddr); | 717 | out_be32(&hw->cursor, pool.cursor.paddr); |
718 | 718 | ||
719 | out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ | 719 | out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ |
720 | out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ | 720 | out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ |
721 | out_be32(&hw->disp_size, (var->yres << 16 | var->xres)); | 721 | out_be32(&hw->disp_size, (var->yres << 16 | var->xres)); |
722 | /* DISP SIZE */ | 722 | /* DISP SIZE */ |
723 | pr_debug("DIU xres: %d\n", var->xres); | 723 | pr_debug("DIU xres: %d\n", var->xres); |
724 | pr_debug("DIU yres: %d\n", var->yres); | 724 | pr_debug("DIU yres: %d\n", var->yres); |
725 | 725 | ||
726 | out_be32(&hw->wb_size, 0); /* WB SIZE */ | 726 | out_be32(&hw->wb_size, 0); /* WB SIZE */ |
727 | out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */ | 727 | out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */ |
728 | 728 | ||
729 | /* Horizontal and vertical configuration register */ | 729 | /* Horizontal and vertical configuration register */ |
730 | temp = var->left_margin << 22 | /* BP_H */ | 730 | temp = var->left_margin << 22 | /* BP_H */ |
731 | var->hsync_len << 11 | /* PW_H */ | 731 | var->hsync_len << 11 | /* PW_H */ |
732 | var->right_margin; /* FP_H */ | 732 | var->right_margin; /* FP_H */ |
733 | 733 | ||
734 | out_be32(&hw->hsyn_para, temp); | 734 | out_be32(&hw->hsyn_para, temp); |
735 | 735 | ||
736 | temp = var->upper_margin << 22 | /* BP_V */ | 736 | temp = var->upper_margin << 22 | /* BP_V */ |
737 | var->vsync_len << 11 | /* PW_V */ | 737 | var->vsync_len << 11 | /* PW_V */ |
738 | var->lower_margin; /* FP_V */ | 738 | var->lower_margin; /* FP_V */ |
739 | 739 | ||
740 | out_be32(&hw->vsyn_para, temp); | 740 | out_be32(&hw->vsyn_para, temp); |
741 | 741 | ||
742 | pr_debug("DIU right_margin - %d\n", var->right_margin); | 742 | pr_debug("DIU right_margin - %d\n", var->right_margin); |
743 | pr_debug("DIU left_margin - %d\n", var->left_margin); | 743 | pr_debug("DIU left_margin - %d\n", var->left_margin); |
744 | pr_debug("DIU hsync_len - %d\n", var->hsync_len); | 744 | pr_debug("DIU hsync_len - %d\n", var->hsync_len); |
745 | pr_debug("DIU upper_margin - %d\n", var->upper_margin); | 745 | pr_debug("DIU upper_margin - %d\n", var->upper_margin); |
746 | pr_debug("DIU lower_margin - %d\n", var->lower_margin); | 746 | pr_debug("DIU lower_margin - %d\n", var->lower_margin); |
747 | pr_debug("DIU vsync_len - %d\n", var->vsync_len); | 747 | pr_debug("DIU vsync_len - %d\n", var->vsync_len); |
748 | pr_debug("DIU HSYNC - 0x%08x\n", hw->hsyn_para); | 748 | pr_debug("DIU HSYNC - 0x%08x\n", hw->hsyn_para); |
749 | pr_debug("DIU VSYNC - 0x%08x\n", hw->vsyn_para); | 749 | pr_debug("DIU VSYNC - 0x%08x\n", hw->vsyn_para); |
750 | 750 | ||
751 | diu_ops.set_pixel_clock(var->pixclock); | 751 | diu_ops.set_pixel_clock(var->pixclock); |
752 | 752 | ||
753 | out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ | 753 | out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ |
754 | out_be32(&hw->thresholds, 0x00037800); /* The Thresholds */ | 754 | out_be32(&hw->thresholds, 0x00037800); /* The Thresholds */ |
755 | out_be32(&hw->int_status, 0); /* INTERRUPT STATUS */ | 755 | out_be32(&hw->int_status, 0); /* INTERRUPT STATUS */ |
756 | out_be32(&hw->plut, 0x01F5F666); | 756 | out_be32(&hw->plut, 0x01F5F666); |
757 | 757 | ||
758 | /* Enable the DIU */ | 758 | /* Enable the DIU */ |
759 | enable_lcdc(info); | 759 | enable_lcdc(info); |
760 | } | 760 | } |
761 | 761 | ||
762 | static int map_video_memory(struct fb_info *info) | 762 | static int map_video_memory(struct fb_info *info) |
763 | { | 763 | { |
764 | phys_addr_t phys; | 764 | phys_addr_t phys; |
765 | 765 | ||
766 | pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); | 766 | pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); |
767 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); | 767 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); |
768 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); | 768 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); |
769 | 769 | ||
770 | info->fix.smem_len = info->fix.line_length * info->var.yres_virtual; | 770 | info->fix.smem_len = info->fix.line_length * info->var.yres_virtual; |
771 | pr_debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len); | 771 | pr_debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len); |
772 | info->screen_base = fsl_diu_alloc(info->fix.smem_len, &phys); | 772 | info->screen_base = fsl_diu_alloc(info->fix.smem_len, &phys); |
773 | if (info->screen_base == 0) { | 773 | if (info->screen_base == 0) { |
774 | printk(KERN_ERR "Unable to allocate fb memory\n"); | 774 | printk(KERN_ERR "Unable to allocate fb memory\n"); |
775 | return -ENOMEM; | 775 | return -ENOMEM; |
776 | } | 776 | } |
777 | info->fix.smem_start = (unsigned long) phys; | 777 | info->fix.smem_start = (unsigned long) phys; |
778 | info->screen_size = info->fix.smem_len; | 778 | info->screen_size = info->fix.smem_len; |
779 | 779 | ||
780 | pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", | 780 | pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", |
781 | info->fix.smem_start, | 781 | info->fix.smem_start, |
782 | info->fix.smem_len); | 782 | info->fix.smem_len); |
783 | pr_debug("screen base %p\n", info->screen_base); | 783 | pr_debug("screen base %p\n", info->screen_base); |
784 | 784 | ||
785 | return 0; | 785 | return 0; |
786 | } | 786 | } |
787 | 787 | ||
788 | static void unmap_video_memory(struct fb_info *info) | 788 | static void unmap_video_memory(struct fb_info *info) |
789 | { | 789 | { |
790 | fsl_diu_free(info->screen_base, info->fix.smem_len); | 790 | fsl_diu_free(info->screen_base, info->fix.smem_len); |
791 | info->screen_base = 0; | 791 | info->screen_base = 0; |
792 | info->fix.smem_start = 0; | 792 | info->fix.smem_start = 0; |
793 | info->fix.smem_len = 0; | 793 | info->fix.smem_len = 0; |
794 | } | 794 | } |
795 | 795 | ||
796 | /* | 796 | /* |
797 | * Using the fb_var_screeninfo in fb_info we set the resolution of this | 797 | * Using the fb_var_screeninfo in fb_info we set the resolution of this |
798 | * particular framebuffer. This function alters the fb_fix_screeninfo stored | 798 | * particular framebuffer. This function alters the fb_fix_screeninfo stored |
799 | * in fb_info. It does not alter var in fb_info since we are using that | 799 | * in fb_info. It does not alter var in fb_info since we are using that |
800 | * data. This means we depend on the data in var inside fb_info to be | 800 | * data. This means we depend on the data in var inside fb_info to be |
801 | * supported by the hardware. fsl_diu_check_var is always called before | 801 | * supported by the hardware. fsl_diu_check_var is always called before |
802 | * fsl_diu_set_par to ensure this. | 802 | * fsl_diu_set_par to ensure this. |
803 | */ | 803 | */ |
804 | static int fsl_diu_set_par(struct fb_info *info) | 804 | static int fsl_diu_set_par(struct fb_info *info) |
805 | { | 805 | { |
806 | unsigned long len; | 806 | unsigned long len; |
807 | struct fb_var_screeninfo *var = &info->var; | 807 | struct fb_var_screeninfo *var = &info->var; |
808 | struct mfb_info *mfbi = info->par; | 808 | struct mfb_info *mfbi = info->par; |
809 | struct fsl_diu_data *machine_data = mfbi->parent; | 809 | struct fsl_diu_data *machine_data = mfbi->parent; |
810 | struct diu_ad *ad = mfbi->ad; | 810 | struct diu_ad *ad = mfbi->ad; |
811 | struct diu *hw; | 811 | struct diu *hw; |
812 | 812 | ||
813 | hw = dr.diu_reg; | 813 | hw = dr.diu_reg; |
814 | 814 | ||
815 | set_fix(info); | 815 | set_fix(info); |
816 | mfbi->cursor_reset = 1; | 816 | mfbi->cursor_reset = 1; |
817 | 817 | ||
818 | len = info->var.yres_virtual * info->fix.line_length; | 818 | len = info->var.yres_virtual * info->fix.line_length; |
819 | /* Alloc & dealloc each time resolution/bpp change */ | 819 | /* Alloc & dealloc each time resolution/bpp change */ |
820 | if (len != info->fix.smem_len) { | 820 | if (len != info->fix.smem_len) { |
821 | if (info->fix.smem_start) | 821 | if (info->fix.smem_start) |
822 | unmap_video_memory(info); | 822 | unmap_video_memory(info); |
823 | pr_debug("SET PAR: smem_len = %d\n", info->fix.smem_len); | 823 | pr_debug("SET PAR: smem_len = %d\n", info->fix.smem_len); |
824 | 824 | ||
825 | /* Memory allocation for framebuffer */ | 825 | /* Memory allocation for framebuffer */ |
826 | if (map_video_memory(info)) { | 826 | if (map_video_memory(info)) { |
827 | printk(KERN_ERR "Unable to allocate fb memory 1\n"); | 827 | printk(KERN_ERR "Unable to allocate fb memory 1\n"); |
828 | return -ENOMEM; | 828 | return -ENOMEM; |
829 | } | 829 | } |
830 | } | 830 | } |
831 | 831 | ||
832 | ad->pix_fmt = | 832 | ad->pix_fmt = |
833 | diu_ops.get_pixel_format(var->bits_per_pixel, | 833 | diu_ops.get_pixel_format(var->bits_per_pixel, |
834 | machine_data->monitor_port); | 834 | machine_data->monitor_port); |
835 | ad->addr = cpu_to_le32(info->fix.smem_start); | 835 | ad->addr = cpu_to_le32(info->fix.smem_start); |
836 | ad->src_size_g_alpha = cpu_to_le32((var->yres << 12) | | 836 | ad->src_size_g_alpha = cpu_to_le32((var->yres << 12) | |
837 | var->xres) | mfbi->g_alpha; | 837 | var->xres) | mfbi->g_alpha; |
838 | /* fix me. AOI should not be greater than display size */ | 838 | /* fix me. AOI should not be greater than display size */ |
839 | ad->aoi_size = cpu_to_le32((var->yres << 16) | var->xres); | 839 | ad->aoi_size = cpu_to_le32((var->yres << 16) | var->xres); |
840 | ad->offset_xyi = 0; | 840 | ad->offset_xyi = 0; |
841 | ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d); | 841 | ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d); |
842 | 842 | ||
843 | /* Disable chroma keying function */ | 843 | /* Disable chroma keying function */ |
844 | ad->ckmax_r = 0; | 844 | ad->ckmax_r = 0; |
845 | ad->ckmax_g = 0; | 845 | ad->ckmax_g = 0; |
846 | ad->ckmax_b = 0; | 846 | ad->ckmax_b = 0; |
847 | 847 | ||
848 | ad->ckmin_r = 255; | 848 | ad->ckmin_r = 255; |
849 | ad->ckmin_g = 255; | 849 | ad->ckmin_g = 255; |
850 | ad->ckmin_b = 255; | 850 | ad->ckmin_b = 255; |
851 | 851 | ||
852 | if (mfbi->index == 0) | 852 | if (mfbi->index == 0) |
853 | update_lcdc(info); | 853 | update_lcdc(info); |
854 | return 0; | 854 | return 0; |
855 | } | 855 | } |
856 | 856 | ||
857 | static inline __u32 CNVT_TOHW(__u32 val, __u32 width) | 857 | static inline __u32 CNVT_TOHW(__u32 val, __u32 width) |
858 | { | 858 | { |
859 | return ((val<<width) + 0x7FFF - val)>>16; | 859 | return ((val<<width) + 0x7FFF - val)>>16; |
860 | } | 860 | } |
861 | 861 | ||
862 | /* | 862 | /* |
863 | * Set a single color register. The values supplied have a 16 bit magnitude | 863 | * Set a single color register. The values supplied have a 16 bit magnitude |
864 | * which needs to be scaled in this function for the hardware. Things to take | 864 | * which needs to be scaled in this function for the hardware. Things to take |
865 | * into consideration are how many color registers, if any, are supported with | 865 | * into consideration are how many color registers, if any, are supported with |
866 | * the current color visual. With truecolor mode no color palettes are | 866 | * the current color visual. With truecolor mode no color palettes are |
867 | * supported. Here a psuedo palette is created which we store the value in | 867 | * supported. Here a psuedo palette is created which we store the value in |
868 | * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited | 868 | * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited |
869 | * color palette. | 869 | * color palette. |
870 | */ | 870 | */ |
871 | static int fsl_diu_setcolreg(unsigned regno, unsigned red, unsigned green, | 871 | static int fsl_diu_setcolreg(unsigned regno, unsigned red, unsigned green, |
872 | unsigned blue, unsigned transp, struct fb_info *info) | 872 | unsigned blue, unsigned transp, struct fb_info *info) |
873 | { | 873 | { |
874 | int ret = 1; | 874 | int ret = 1; |
875 | 875 | ||
876 | /* | 876 | /* |
877 | * If greyscale is true, then we convert the RGB value | 877 | * If greyscale is true, then we convert the RGB value |
878 | * to greyscale no matter what visual we are using. | 878 | * to greyscale no matter what visual we are using. |
879 | */ | 879 | */ |
880 | if (info->var.grayscale) | 880 | if (info->var.grayscale) |
881 | red = green = blue = (19595 * red + 38470 * green + | 881 | red = green = blue = (19595 * red + 38470 * green + |
882 | 7471 * blue) >> 16; | 882 | 7471 * blue) >> 16; |
883 | switch (info->fix.visual) { | 883 | switch (info->fix.visual) { |
884 | case FB_VISUAL_TRUECOLOR: | 884 | case FB_VISUAL_TRUECOLOR: |
885 | /* | 885 | /* |
886 | * 16-bit True Colour. We encode the RGB value | 886 | * 16-bit True Colour. We encode the RGB value |
887 | * according to the RGB bitfield information. | 887 | * according to the RGB bitfield information. |
888 | */ | 888 | */ |
889 | if (regno < 16) { | 889 | if (regno < 16) { |
890 | u32 *pal = info->pseudo_palette; | 890 | u32 *pal = info->pseudo_palette; |
891 | u32 v; | 891 | u32 v; |
892 | 892 | ||
893 | red = CNVT_TOHW(red, info->var.red.length); | 893 | red = CNVT_TOHW(red, info->var.red.length); |
894 | green = CNVT_TOHW(green, info->var.green.length); | 894 | green = CNVT_TOHW(green, info->var.green.length); |
895 | blue = CNVT_TOHW(blue, info->var.blue.length); | 895 | blue = CNVT_TOHW(blue, info->var.blue.length); |
896 | transp = CNVT_TOHW(transp, info->var.transp.length); | 896 | transp = CNVT_TOHW(transp, info->var.transp.length); |
897 | 897 | ||
898 | v = (red << info->var.red.offset) | | 898 | v = (red << info->var.red.offset) | |
899 | (green << info->var.green.offset) | | 899 | (green << info->var.green.offset) | |
900 | (blue << info->var.blue.offset) | | 900 | (blue << info->var.blue.offset) | |
901 | (transp << info->var.transp.offset); | 901 | (transp << info->var.transp.offset); |
902 | 902 | ||
903 | pal[regno] = v; | 903 | pal[regno] = v; |
904 | ret = 0; | 904 | ret = 0; |
905 | } | 905 | } |
906 | break; | 906 | break; |
907 | case FB_VISUAL_STATIC_PSEUDOCOLOR: | 907 | case FB_VISUAL_STATIC_PSEUDOCOLOR: |
908 | case FB_VISUAL_PSEUDOCOLOR: | 908 | case FB_VISUAL_PSEUDOCOLOR: |
909 | break; | 909 | break; |
910 | } | 910 | } |
911 | 911 | ||
912 | return ret; | 912 | return ret; |
913 | } | 913 | } |
914 | 914 | ||
915 | /* | 915 | /* |
916 | * Pan (or wrap, depending on the `vmode' field) the display using the | 916 | * Pan (or wrap, depending on the `vmode' field) the display using the |
917 | * 'xoffset' and 'yoffset' fields of the 'var' structure. If the values | 917 | * 'xoffset' and 'yoffset' fields of the 'var' structure. If the values |
918 | * don't fit, return -EINVAL. | 918 | * don't fit, return -EINVAL. |
919 | */ | 919 | */ |
920 | static int fsl_diu_pan_display(struct fb_var_screeninfo *var, | 920 | static int fsl_diu_pan_display(struct fb_var_screeninfo *var, |
921 | struct fb_info *info) | 921 | struct fb_info *info) |
922 | { | 922 | { |
923 | if ((info->var.xoffset == var->xoffset) && | 923 | if ((info->var.xoffset == var->xoffset) && |
924 | (info->var.yoffset == var->yoffset)) | 924 | (info->var.yoffset == var->yoffset)) |
925 | return 0; /* No change, do nothing */ | 925 | return 0; /* No change, do nothing */ |
926 | 926 | ||
927 | if (var->xoffset < 0 || var->yoffset < 0 | 927 | if (var->xoffset < 0 || var->yoffset < 0 |
928 | || var->xoffset + info->var.xres > info->var.xres_virtual | 928 | || var->xoffset + info->var.xres > info->var.xres_virtual |
929 | || var->yoffset + info->var.yres > info->var.yres_virtual) | 929 | || var->yoffset + info->var.yres > info->var.yres_virtual) |
930 | return -EINVAL; | 930 | return -EINVAL; |
931 | 931 | ||
932 | info->var.xoffset = var->xoffset; | 932 | info->var.xoffset = var->xoffset; |
933 | info->var.yoffset = var->yoffset; | 933 | info->var.yoffset = var->yoffset; |
934 | 934 | ||
935 | if (var->vmode & FB_VMODE_YWRAP) | 935 | if (var->vmode & FB_VMODE_YWRAP) |
936 | info->var.vmode |= FB_VMODE_YWRAP; | 936 | info->var.vmode |= FB_VMODE_YWRAP; |
937 | else | 937 | else |
938 | info->var.vmode &= ~FB_VMODE_YWRAP; | 938 | info->var.vmode &= ~FB_VMODE_YWRAP; |
939 | 939 | ||
940 | return 0; | 940 | return 0; |
941 | } | 941 | } |
942 | 942 | ||
943 | /* | 943 | /* |
944 | * Blank the screen if blank_mode != 0, else unblank. Return 0 if blanking | 944 | * Blank the screen if blank_mode != 0, else unblank. Return 0 if blanking |
945 | * succeeded, != 0 if un-/blanking failed. | 945 | * succeeded, != 0 if un-/blanking failed. |
946 | * blank_mode == 2: suspend vsync | 946 | * blank_mode == 2: suspend vsync |
947 | * blank_mode == 3: suspend hsync | 947 | * blank_mode == 3: suspend hsync |
948 | * blank_mode == 4: powerdown | 948 | * blank_mode == 4: powerdown |
949 | */ | 949 | */ |
950 | static int fsl_diu_blank(int blank_mode, struct fb_info *info) | 950 | static int fsl_diu_blank(int blank_mode, struct fb_info *info) |
951 | { | 951 | { |
952 | struct mfb_info *mfbi = info->par; | 952 | struct mfb_info *mfbi = info->par; |
953 | 953 | ||
954 | mfbi->blank = blank_mode; | 954 | mfbi->blank = blank_mode; |
955 | 955 | ||
956 | switch (blank_mode) { | 956 | switch (blank_mode) { |
957 | case FB_BLANK_VSYNC_SUSPEND: | 957 | case FB_BLANK_VSYNC_SUSPEND: |
958 | case FB_BLANK_HSYNC_SUSPEND: | 958 | case FB_BLANK_HSYNC_SUSPEND: |
959 | /* FIXME: fixes to enable_panel and enable lcdc needed */ | 959 | /* FIXME: fixes to enable_panel and enable lcdc needed */ |
960 | case FB_BLANK_NORMAL: | 960 | case FB_BLANK_NORMAL: |
961 | /* fsl_diu_disable_panel(info);*/ | 961 | /* fsl_diu_disable_panel(info);*/ |
962 | break; | 962 | break; |
963 | case FB_BLANK_POWERDOWN: | 963 | case FB_BLANK_POWERDOWN: |
964 | /* disable_lcdc(info); */ | 964 | /* disable_lcdc(info); */ |
965 | break; | 965 | break; |
966 | case FB_BLANK_UNBLANK: | 966 | case FB_BLANK_UNBLANK: |
967 | /* fsl_diu_enable_panel(info);*/ | 967 | /* fsl_diu_enable_panel(info);*/ |
968 | break; | 968 | break; |
969 | } | 969 | } |
970 | 970 | ||
971 | return 0; | 971 | return 0; |
972 | } | 972 | } |
973 | 973 | ||
974 | static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | 974 | static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, |
975 | unsigned long arg) | 975 | unsigned long arg) |
976 | { | 976 | { |
977 | struct mfb_info *mfbi = info->par; | 977 | struct mfb_info *mfbi = info->par; |
978 | struct diu_ad *ad = mfbi->ad; | 978 | struct diu_ad *ad = mfbi->ad; |
979 | struct mfb_chroma_key ck; | 979 | struct mfb_chroma_key ck; |
980 | unsigned char global_alpha; | 980 | unsigned char global_alpha; |
981 | struct aoi_display_offset aoi_d; | 981 | struct aoi_display_offset aoi_d; |
982 | __u32 pix_fmt; | 982 | __u32 pix_fmt; |
983 | void __user *buf = (void __user *)arg; | 983 | void __user *buf = (void __user *)arg; |
984 | 984 | ||
985 | if (!arg) | 985 | if (!arg) |
986 | return -EINVAL; | 986 | return -EINVAL; |
987 | switch (cmd) { | 987 | switch (cmd) { |
988 | case MFB_SET_PIXFMT: | 988 | case MFB_SET_PIXFMT: |
989 | if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt))) | 989 | if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt))) |
990 | return -EFAULT; | 990 | return -EFAULT; |
991 | ad->pix_fmt = pix_fmt; | 991 | ad->pix_fmt = pix_fmt; |
992 | pr_debug("Set pixel format to 0x%08x\n", ad->pix_fmt); | 992 | pr_debug("Set pixel format to 0x%08x\n", ad->pix_fmt); |
993 | break; | 993 | break; |
994 | case MFB_GET_PIXFMT: | 994 | case MFB_GET_PIXFMT: |
995 | pix_fmt = ad->pix_fmt; | 995 | pix_fmt = ad->pix_fmt; |
996 | if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt))) | 996 | if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt))) |
997 | return -EFAULT; | 997 | return -EFAULT; |
998 | pr_debug("get pixel format 0x%08x\n", ad->pix_fmt); | 998 | pr_debug("get pixel format 0x%08x\n", ad->pix_fmt); |
999 | break; | 999 | break; |
1000 | case MFB_SET_AOID: | 1000 | case MFB_SET_AOID: |
1001 | if (copy_from_user(&aoi_d, buf, sizeof(aoi_d))) | 1001 | if (copy_from_user(&aoi_d, buf, sizeof(aoi_d))) |
1002 | return -EFAULT; | 1002 | return -EFAULT; |
1003 | mfbi->x_aoi_d = aoi_d.x_aoi_d; | 1003 | mfbi->x_aoi_d = aoi_d.x_aoi_d; |
1004 | mfbi->y_aoi_d = aoi_d.y_aoi_d; | 1004 | mfbi->y_aoi_d = aoi_d.y_aoi_d; |
1005 | pr_debug("set AOI display offset of index %d to (%d,%d)\n", | 1005 | pr_debug("set AOI display offset of index %d to (%d,%d)\n", |
1006 | mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); | 1006 | mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); |
1007 | fsl_diu_check_var(&info->var, info); | 1007 | fsl_diu_check_var(&info->var, info); |
1008 | fsl_diu_set_par(info); | 1008 | fsl_diu_set_par(info); |
1009 | break; | 1009 | break; |
1010 | case MFB_GET_AOID: | 1010 | case MFB_GET_AOID: |
1011 | aoi_d.x_aoi_d = mfbi->x_aoi_d; | 1011 | aoi_d.x_aoi_d = mfbi->x_aoi_d; |
1012 | aoi_d.y_aoi_d = mfbi->y_aoi_d; | 1012 | aoi_d.y_aoi_d = mfbi->y_aoi_d; |
1013 | if (copy_to_user(buf, &aoi_d, sizeof(aoi_d))) | 1013 | if (copy_to_user(buf, &aoi_d, sizeof(aoi_d))) |
1014 | return -EFAULT; | 1014 | return -EFAULT; |
1015 | pr_debug("get AOI display offset of index %d (%d,%d)\n", | 1015 | pr_debug("get AOI display offset of index %d (%d,%d)\n", |
1016 | mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); | 1016 | mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); |
1017 | break; | 1017 | break; |
1018 | case MFB_GET_ALPHA: | 1018 | case MFB_GET_ALPHA: |
1019 | global_alpha = mfbi->g_alpha; | 1019 | global_alpha = mfbi->g_alpha; |
1020 | if (copy_to_user(buf, &global_alpha, sizeof(global_alpha))) | 1020 | if (copy_to_user(buf, &global_alpha, sizeof(global_alpha))) |
1021 | return -EFAULT; | 1021 | return -EFAULT; |
1022 | pr_debug("get global alpha of index %d\n", mfbi->index); | 1022 | pr_debug("get global alpha of index %d\n", mfbi->index); |
1023 | break; | 1023 | break; |
1024 | case MFB_SET_ALPHA: | 1024 | case MFB_SET_ALPHA: |
1025 | /* set panel information */ | 1025 | /* set panel information */ |
1026 | if (copy_from_user(&global_alpha, buf, sizeof(global_alpha))) | 1026 | if (copy_from_user(&global_alpha, buf, sizeof(global_alpha))) |
1027 | return -EFAULT; | 1027 | return -EFAULT; |
1028 | ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) | | 1028 | ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) | |
1029 | (global_alpha & 0xff); | 1029 | (global_alpha & 0xff); |
1030 | mfbi->g_alpha = global_alpha; | 1030 | mfbi->g_alpha = global_alpha; |
1031 | pr_debug("set global alpha for index %d\n", mfbi->index); | 1031 | pr_debug("set global alpha for index %d\n", mfbi->index); |
1032 | break; | 1032 | break; |
1033 | case MFB_SET_CHROMA_KEY: | 1033 | case MFB_SET_CHROMA_KEY: |
1034 | /* set panel winformation */ | 1034 | /* set panel winformation */ |
1035 | if (copy_from_user(&ck, buf, sizeof(ck))) | 1035 | if (copy_from_user(&ck, buf, sizeof(ck))) |
1036 | return -EFAULT; | 1036 | return -EFAULT; |
1037 | 1037 | ||
1038 | if (ck.enable && | 1038 | if (ck.enable && |
1039 | (ck.red_max < ck.red_min || | 1039 | (ck.red_max < ck.red_min || |
1040 | ck.green_max < ck.green_min || | 1040 | ck.green_max < ck.green_min || |
1041 | ck.blue_max < ck.blue_min)) | 1041 | ck.blue_max < ck.blue_min)) |
1042 | return -EINVAL; | 1042 | return -EINVAL; |
1043 | 1043 | ||
1044 | if (!ck.enable) { | 1044 | if (!ck.enable) { |
1045 | ad->ckmax_r = 0; | 1045 | ad->ckmax_r = 0; |
1046 | ad->ckmax_g = 0; | 1046 | ad->ckmax_g = 0; |
1047 | ad->ckmax_b = 0; | 1047 | ad->ckmax_b = 0; |
1048 | ad->ckmin_r = 255; | 1048 | ad->ckmin_r = 255; |
1049 | ad->ckmin_g = 255; | 1049 | ad->ckmin_g = 255; |
1050 | ad->ckmin_b = 255; | 1050 | ad->ckmin_b = 255; |
1051 | } else { | 1051 | } else { |
1052 | ad->ckmax_r = ck.red_max; | 1052 | ad->ckmax_r = ck.red_max; |
1053 | ad->ckmax_g = ck.green_max; | 1053 | ad->ckmax_g = ck.green_max; |
1054 | ad->ckmax_b = ck.blue_max; | 1054 | ad->ckmax_b = ck.blue_max; |
1055 | ad->ckmin_r = ck.red_min; | 1055 | ad->ckmin_r = ck.red_min; |
1056 | ad->ckmin_g = ck.green_min; | 1056 | ad->ckmin_g = ck.green_min; |
1057 | ad->ckmin_b = ck.blue_min; | 1057 | ad->ckmin_b = ck.blue_min; |
1058 | } | 1058 | } |
1059 | pr_debug("set chroma key\n"); | 1059 | pr_debug("set chroma key\n"); |
1060 | break; | 1060 | break; |
1061 | case FBIOGET_GWINFO: | 1061 | case FBIOGET_GWINFO: |
1062 | if (mfbi->type == MFB_TYPE_OFF) | 1062 | if (mfbi->type == MFB_TYPE_OFF) |
1063 | return -ENODEV; | 1063 | return -ENODEV; |
1064 | /* get graphic window information */ | 1064 | /* get graphic window information */ |
1065 | if (copy_to_user(buf, ad, sizeof(*ad))) | 1065 | if (copy_to_user(buf, ad, sizeof(*ad))) |
1066 | return -EFAULT; | 1066 | return -EFAULT; |
1067 | break; | 1067 | break; |
1068 | case FBIOGET_HWCINFO: | 1068 | case FBIOGET_HWCINFO: |
1069 | pr_debug("FBIOGET_HWCINFO:0x%08x\n", FBIOGET_HWCINFO); | 1069 | pr_debug("FBIOGET_HWCINFO:0x%08x\n", FBIOGET_HWCINFO); |
1070 | break; | 1070 | break; |
1071 | case FBIOPUT_MODEINFO: | 1071 | case FBIOPUT_MODEINFO: |
1072 | pr_debug("FBIOPUT_MODEINFO:0x%08x\n", FBIOPUT_MODEINFO); | 1072 | pr_debug("FBIOPUT_MODEINFO:0x%08x\n", FBIOPUT_MODEINFO); |
1073 | break; | 1073 | break; |
1074 | case FBIOGET_DISPINFO: | 1074 | case FBIOGET_DISPINFO: |
1075 | pr_debug("FBIOGET_DISPINFO:0x%08x\n", FBIOGET_DISPINFO); | 1075 | pr_debug("FBIOGET_DISPINFO:0x%08x\n", FBIOGET_DISPINFO); |
1076 | break; | 1076 | break; |
1077 | 1077 | ||
1078 | default: | 1078 | default: |
1079 | printk(KERN_ERR "Unknown ioctl command (0x%08X)\n", cmd); | 1079 | printk(KERN_ERR "Unknown ioctl command (0x%08X)\n", cmd); |
1080 | return -ENOIOCTLCMD; | 1080 | return -ENOIOCTLCMD; |
1081 | } | 1081 | } |
1082 | 1082 | ||
1083 | return 0; | 1083 | return 0; |
1084 | } | 1084 | } |
1085 | 1085 | ||
1086 | /* turn on fb if count == 1 | 1086 | /* turn on fb if count == 1 |
1087 | */ | 1087 | */ |
1088 | static int fsl_diu_open(struct fb_info *info, int user) | 1088 | static int fsl_diu_open(struct fb_info *info, int user) |
1089 | { | 1089 | { |
1090 | struct mfb_info *mfbi = info->par; | 1090 | struct mfb_info *mfbi = info->par; |
1091 | int res = 0; | 1091 | int res = 0; |
1092 | 1092 | ||
1093 | spin_lock(&diu_lock); | 1093 | spin_lock(&diu_lock); |
1094 | mfbi->count++; | 1094 | mfbi->count++; |
1095 | if (mfbi->count == 1) { | 1095 | if (mfbi->count == 1) { |
1096 | pr_debug("open plane index %d\n", mfbi->index); | 1096 | pr_debug("open plane index %d\n", mfbi->index); |
1097 | fsl_diu_check_var(&info->var, info); | 1097 | fsl_diu_check_var(&info->var, info); |
1098 | res = fsl_diu_set_par(info); | 1098 | res = fsl_diu_set_par(info); |
1099 | if (res < 0) | 1099 | if (res < 0) |
1100 | mfbi->count--; | 1100 | mfbi->count--; |
1101 | else { | 1101 | else { |
1102 | res = fsl_diu_enable_panel(info); | 1102 | res = fsl_diu_enable_panel(info); |
1103 | if (res < 0) | 1103 | if (res < 0) |
1104 | mfbi->count--; | 1104 | mfbi->count--; |
1105 | } | 1105 | } |
1106 | } | 1106 | } |
1107 | 1107 | ||
1108 | spin_unlock(&diu_lock); | 1108 | spin_unlock(&diu_lock); |
1109 | return res; | 1109 | return res; |
1110 | } | 1110 | } |
1111 | 1111 | ||
1112 | /* turn off fb if count == 0 | 1112 | /* turn off fb if count == 0 |
1113 | */ | 1113 | */ |
1114 | static int fsl_diu_release(struct fb_info *info, int user) | 1114 | static int fsl_diu_release(struct fb_info *info, int user) |
1115 | { | 1115 | { |
1116 | struct mfb_info *mfbi = info->par; | 1116 | struct mfb_info *mfbi = info->par; |
1117 | int res = 0; | 1117 | int res = 0; |
1118 | 1118 | ||
1119 | spin_lock(&diu_lock); | 1119 | spin_lock(&diu_lock); |
1120 | mfbi->count--; | 1120 | mfbi->count--; |
1121 | if (mfbi->count == 0) { | 1121 | if (mfbi->count == 0) { |
1122 | pr_debug("release plane index %d\n", mfbi->index); | 1122 | pr_debug("release plane index %d\n", mfbi->index); |
1123 | res = fsl_diu_disable_panel(info); | 1123 | res = fsl_diu_disable_panel(info); |
1124 | if (res < 0) | 1124 | if (res < 0) |
1125 | mfbi->count++; | 1125 | mfbi->count++; |
1126 | } | 1126 | } |
1127 | spin_unlock(&diu_lock); | 1127 | spin_unlock(&diu_lock); |
1128 | return res; | 1128 | return res; |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | static struct fb_ops fsl_diu_ops = { | 1131 | static struct fb_ops fsl_diu_ops = { |
1132 | .owner = THIS_MODULE, | 1132 | .owner = THIS_MODULE, |
1133 | .fb_check_var = fsl_diu_check_var, | 1133 | .fb_check_var = fsl_diu_check_var, |
1134 | .fb_set_par = fsl_diu_set_par, | 1134 | .fb_set_par = fsl_diu_set_par, |
1135 | .fb_setcolreg = fsl_diu_setcolreg, | 1135 | .fb_setcolreg = fsl_diu_setcolreg, |
1136 | .fb_blank = fsl_diu_blank, | 1136 | .fb_blank = fsl_diu_blank, |
1137 | .fb_pan_display = fsl_diu_pan_display, | 1137 | .fb_pan_display = fsl_diu_pan_display, |
1138 | .fb_fillrect = cfb_fillrect, | 1138 | .fb_fillrect = cfb_fillrect, |
1139 | .fb_copyarea = cfb_copyarea, | 1139 | .fb_copyarea = cfb_copyarea, |
1140 | .fb_imageblit = cfb_imageblit, | 1140 | .fb_imageblit = cfb_imageblit, |
1141 | .fb_ioctl = fsl_diu_ioctl, | 1141 | .fb_ioctl = fsl_diu_ioctl, |
1142 | .fb_open = fsl_diu_open, | 1142 | .fb_open = fsl_diu_open, |
1143 | .fb_release = fsl_diu_release, | 1143 | .fb_release = fsl_diu_release, |
1144 | }; | 1144 | }; |
1145 | 1145 | ||
1146 | static int init_fbinfo(struct fb_info *info) | 1146 | static int init_fbinfo(struct fb_info *info) |
1147 | { | 1147 | { |
1148 | struct mfb_info *mfbi = info->par; | 1148 | struct mfb_info *mfbi = info->par; |
1149 | 1149 | ||
1150 | info->device = NULL; | 1150 | info->device = NULL; |
1151 | info->var.activate = FB_ACTIVATE_NOW; | 1151 | info->var.activate = FB_ACTIVATE_NOW; |
1152 | info->fbops = &fsl_diu_ops; | 1152 | info->fbops = &fsl_diu_ops; |
1153 | info->flags = FBINFO_FLAG_DEFAULT; | 1153 | info->flags = FBINFO_FLAG_DEFAULT; |
1154 | info->pseudo_palette = &mfbi->pseudo_palette; | 1154 | info->pseudo_palette = &mfbi->pseudo_palette; |
1155 | 1155 | ||
1156 | /* Allocate colormap */ | 1156 | /* Allocate colormap */ |
1157 | fb_alloc_cmap(&info->cmap, 16, 0); | 1157 | fb_alloc_cmap(&info->cmap, 16, 0); |
1158 | return 0; | 1158 | return 0; |
1159 | } | 1159 | } |
1160 | 1160 | ||
1161 | static int install_fb(struct fb_info *info) | 1161 | static int install_fb(struct fb_info *info) |
1162 | { | 1162 | { |
1163 | int rc; | 1163 | int rc; |
1164 | struct mfb_info *mfbi = info->par; | 1164 | struct mfb_info *mfbi = info->par; |
1165 | const char *aoi_mode, *init_aoi_mode = "320x240"; | 1165 | const char *aoi_mode, *init_aoi_mode = "320x240"; |
1166 | 1166 | ||
1167 | if (init_fbinfo(info)) | 1167 | if (init_fbinfo(info)) |
1168 | return -EINVAL; | 1168 | return -EINVAL; |
1169 | 1169 | ||
1170 | if (mfbi->index == 0) /* plane 0 */ | 1170 | if (mfbi->index == 0) /* plane 0 */ |
1171 | aoi_mode = fb_mode; | 1171 | aoi_mode = fb_mode; |
1172 | else | 1172 | else |
1173 | aoi_mode = init_aoi_mode; | 1173 | aoi_mode = init_aoi_mode; |
1174 | pr_debug("mode used = %s\n", aoi_mode); | 1174 | pr_debug("mode used = %s\n", aoi_mode); |
1175 | rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db, | 1175 | rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db, |
1176 | ARRAY_SIZE(fsl_diu_mode_db), &fsl_diu_default_mode, default_bpp); | 1176 | ARRAY_SIZE(fsl_diu_mode_db), &fsl_diu_default_mode, default_bpp); |
1177 | 1177 | ||
1178 | switch (rc) { | 1178 | switch (rc) { |
1179 | case 1: | 1179 | case 1: |
1180 | pr_debug("using mode specified in @mode\n"); | 1180 | pr_debug("using mode specified in @mode\n"); |
1181 | break; | 1181 | break; |
1182 | case 2: | 1182 | case 2: |
1183 | pr_debug("using mode specified in @mode " | 1183 | pr_debug("using mode specified in @mode " |
1184 | "with ignored refresh rate\n"); | 1184 | "with ignored refresh rate\n"); |
1185 | break; | 1185 | break; |
1186 | case 3: | 1186 | case 3: |
1187 | pr_debug("using mode default mode\n"); | 1187 | pr_debug("using mode default mode\n"); |
1188 | break; | 1188 | break; |
1189 | case 4: | 1189 | case 4: |
1190 | pr_debug("using mode from list\n"); | 1190 | pr_debug("using mode from list\n"); |
1191 | break; | 1191 | break; |
1192 | default: | 1192 | default: |
1193 | pr_debug("rc = %d\n", rc); | 1193 | pr_debug("rc = %d\n", rc); |
1194 | pr_debug("failed to find mode\n"); | 1194 | pr_debug("failed to find mode\n"); |
1195 | return -EINVAL; | 1195 | return -EINVAL; |
1196 | break; | 1196 | break; |
1197 | } | 1197 | } |
1198 | 1198 | ||
1199 | pr_debug("xres_virtual %d\n", info->var.xres_virtual); | 1199 | pr_debug("xres_virtual %d\n", info->var.xres_virtual); |
1200 | pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel); | 1200 | pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel); |
1201 | 1201 | ||
1202 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); | 1202 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); |
1203 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); | 1203 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); |
1204 | 1204 | ||
1205 | if (mfbi->type == MFB_TYPE_OFF) | 1205 | if (mfbi->type == MFB_TYPE_OFF) |
1206 | mfbi->blank = FB_BLANK_NORMAL; | 1206 | mfbi->blank = FB_BLANK_NORMAL; |
1207 | else | 1207 | else |
1208 | mfbi->blank = FB_BLANK_UNBLANK; | 1208 | mfbi->blank = FB_BLANK_UNBLANK; |
1209 | 1209 | ||
1210 | if (fsl_diu_check_var(&info->var, info)) { | 1210 | if (fsl_diu_check_var(&info->var, info)) { |
1211 | printk(KERN_ERR "fb_check_var failed"); | 1211 | printk(KERN_ERR "fb_check_var failed"); |
1212 | fb_dealloc_cmap(&info->cmap); | 1212 | fb_dealloc_cmap(&info->cmap); |
1213 | return -EINVAL; | 1213 | return -EINVAL; |
1214 | } | 1214 | } |
1215 | 1215 | ||
1216 | if (fsl_diu_set_par(info)) { | 1216 | if (fsl_diu_set_par(info)) { |
1217 | printk(KERN_ERR "fb_set_par failed"); | 1217 | printk(KERN_ERR "fb_set_par failed"); |
1218 | fb_dealloc_cmap(&info->cmap); | 1218 | fb_dealloc_cmap(&info->cmap); |
1219 | return -EINVAL; | 1219 | return -EINVAL; |
1220 | } | 1220 | } |
1221 | 1221 | ||
1222 | if (register_framebuffer(info) < 0) { | 1222 | if (register_framebuffer(info) < 0) { |
1223 | printk(KERN_ERR "register_framebuffer failed"); | 1223 | printk(KERN_ERR "register_framebuffer failed"); |
1224 | unmap_video_memory(info); | 1224 | unmap_video_memory(info); |
1225 | fb_dealloc_cmap(&info->cmap); | 1225 | fb_dealloc_cmap(&info->cmap); |
1226 | return -EINVAL; | 1226 | return -EINVAL; |
1227 | } | 1227 | } |
1228 | 1228 | ||
1229 | mfbi->registered = 1; | 1229 | mfbi->registered = 1; |
1230 | printk(KERN_INFO "fb%d: %s fb device registered successfully.\n", | 1230 | printk(KERN_INFO "fb%d: %s fb device registered successfully.\n", |
1231 | info->node, info->fix.id); | 1231 | info->node, info->fix.id); |
1232 | 1232 | ||
1233 | return 0; | 1233 | return 0; |
1234 | } | 1234 | } |
1235 | 1235 | ||
1236 | static void __exit uninstall_fb(struct fb_info *info) | 1236 | static void __exit uninstall_fb(struct fb_info *info) |
1237 | { | 1237 | { |
1238 | struct mfb_info *mfbi = info->par; | 1238 | struct mfb_info *mfbi = info->par; |
1239 | 1239 | ||
1240 | if (!mfbi->registered) | 1240 | if (!mfbi->registered) |
1241 | return; | 1241 | return; |
1242 | 1242 | ||
1243 | unregister_framebuffer(info); | 1243 | unregister_framebuffer(info); |
1244 | unmap_video_memory(info); | 1244 | unmap_video_memory(info); |
1245 | if (&info->cmap) | 1245 | if (&info->cmap) |
1246 | fb_dealloc_cmap(&info->cmap); | 1246 | fb_dealloc_cmap(&info->cmap); |
1247 | 1247 | ||
1248 | mfbi->registered = 0; | 1248 | mfbi->registered = 0; |
1249 | } | 1249 | } |
1250 | 1250 | ||
1251 | static irqreturn_t fsl_diu_isr(int irq, void *dev_id) | 1251 | static irqreturn_t fsl_diu_isr(int irq, void *dev_id) |
1252 | { | 1252 | { |
1253 | struct diu *hw = dr.diu_reg; | 1253 | struct diu *hw = dr.diu_reg; |
1254 | unsigned int status = in_be32(&hw->int_status); | 1254 | unsigned int status = in_be32(&hw->int_status); |
1255 | 1255 | ||
1256 | if (status) { | 1256 | if (status) { |
1257 | /* This is the workaround for underrun */ | 1257 | /* This is the workaround for underrun */ |
1258 | if (status & INT_UNDRUN) { | 1258 | if (status & INT_UNDRUN) { |
1259 | out_be32(&hw->diu_mode, 0); | 1259 | out_be32(&hw->diu_mode, 0); |
1260 | pr_debug("Err: DIU occurs underrun!\n"); | 1260 | pr_debug("Err: DIU occurs underrun!\n"); |
1261 | udelay(1); | 1261 | udelay(1); |
1262 | out_be32(&hw->diu_mode, 1); | 1262 | out_be32(&hw->diu_mode, 1); |
1263 | } | 1263 | } |
1264 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 1264 | #if defined(CONFIG_NOT_COHERENT_CACHE) |
1265 | else if (status & INT_VSYNC) { | 1265 | else if (status & INT_VSYNC) { |
1266 | unsigned int i; | 1266 | unsigned int i; |
1267 | for (i = 0; i < coherence_data_size; | 1267 | for (i = 0; i < coherence_data_size; |
1268 | i += d_cache_line_size) | 1268 | i += d_cache_line_size) |
1269 | __asm__ __volatile__ ( | 1269 | __asm__ __volatile__ ( |
1270 | "dcbz 0, %[input]" | 1270 | "dcbz 0, %[input]" |
1271 | ::[input]"r"(&coherence_data[i])); | 1271 | ::[input]"r"(&coherence_data[i])); |
1272 | } | 1272 | } |
1273 | #endif | 1273 | #endif |
1274 | return IRQ_HANDLED; | 1274 | return IRQ_HANDLED; |
1275 | } | 1275 | } |
1276 | return IRQ_NONE; | 1276 | return IRQ_NONE; |
1277 | } | 1277 | } |
1278 | 1278 | ||
1279 | static int request_irq_local(int irq) | 1279 | static int request_irq_local(int irq) |
1280 | { | 1280 | { |
1281 | unsigned long status, ints; | 1281 | unsigned long status, ints; |
1282 | struct diu *hw; | 1282 | struct diu *hw; |
1283 | int ret; | 1283 | int ret; |
1284 | 1284 | ||
1285 | hw = dr.diu_reg; | 1285 | hw = dr.diu_reg; |
1286 | 1286 | ||
1287 | /* Read to clear the status */ | 1287 | /* Read to clear the status */ |
1288 | status = in_be32(&hw->int_status); | 1288 | status = in_be32(&hw->int_status); |
1289 | 1289 | ||
1290 | ret = request_irq(irq, fsl_diu_isr, 0, "diu", 0); | 1290 | ret = request_irq(irq, fsl_diu_isr, 0, "diu", 0); |
1291 | if (ret) | 1291 | if (ret) |
1292 | pr_info("Request diu IRQ failed.\n"); | 1292 | pr_info("Request diu IRQ failed.\n"); |
1293 | else { | 1293 | else { |
1294 | ints = INT_PARERR | INT_LS_BF_VS; | 1294 | ints = INT_PARERR | INT_LS_BF_VS; |
1295 | #if !defined(CONFIG_NOT_COHERENT_CACHE) | 1295 | #if !defined(CONFIG_NOT_COHERENT_CACHE) |
1296 | ints |= INT_VSYNC; | 1296 | ints |= INT_VSYNC; |
1297 | #endif | 1297 | #endif |
1298 | if (dr.mode == MFB_MODE2 || dr.mode == MFB_MODE3) | 1298 | if (dr.mode == MFB_MODE2 || dr.mode == MFB_MODE3) |
1299 | ints |= INT_VSYNC_WB; | 1299 | ints |= INT_VSYNC_WB; |
1300 | 1300 | ||
1301 | /* Read to clear the status */ | 1301 | /* Read to clear the status */ |
1302 | status = in_be32(&hw->int_status); | 1302 | status = in_be32(&hw->int_status); |
1303 | out_be32(&hw->int_mask, ints); | 1303 | out_be32(&hw->int_mask, ints); |
1304 | } | 1304 | } |
1305 | return ret; | 1305 | return ret; |
1306 | } | 1306 | } |
1307 | 1307 | ||
1308 | static void free_irq_local(int irq) | 1308 | static void free_irq_local(int irq) |
1309 | { | 1309 | { |
1310 | struct diu *hw = dr.diu_reg; | 1310 | struct diu *hw = dr.diu_reg; |
1311 | 1311 | ||
1312 | /* Disable all LCDC interrupt */ | 1312 | /* Disable all LCDC interrupt */ |
1313 | out_be32(&hw->int_mask, 0x1f); | 1313 | out_be32(&hw->int_mask, 0x1f); |
1314 | 1314 | ||
1315 | free_irq(irq, 0); | 1315 | free_irq(irq, 0); |
1316 | } | 1316 | } |
1317 | 1317 | ||
1318 | #ifdef CONFIG_PM | 1318 | #ifdef CONFIG_PM |
1319 | /* | 1319 | /* |
1320 | * Power management hooks. Note that we won't be called from IRQ context, | 1320 | * Power management hooks. Note that we won't be called from IRQ context, |
1321 | * unlike the blank functions above, so we may sleep. | 1321 | * unlike the blank functions above, so we may sleep. |
1322 | */ | 1322 | */ |
1323 | static int fsl_diu_suspend(struct of_device *dev, pm_message_t state) | 1323 | static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) |
1324 | { | 1324 | { |
1325 | struct fsl_diu_data *machine_data; | 1325 | struct fsl_diu_data *machine_data; |
1326 | 1326 | ||
1327 | machine_data = dev_get_drvdata(&ofdev->dev); | 1327 | machine_data = dev_get_drvdata(&ofdev->dev); |
1328 | disable_lcdc(machine_data->fsl_diu_info[0]); | 1328 | disable_lcdc(machine_data->fsl_diu_info[0]); |
1329 | 1329 | ||
1330 | return 0; | 1330 | return 0; |
1331 | } | 1331 | } |
1332 | 1332 | ||
1333 | static int fsl_diu_resume(struct of_device *dev) | 1333 | static int fsl_diu_resume(struct of_device *ofdev) |
1334 | { | 1334 | { |
1335 | struct fsl_diu_data *machine_data; | 1335 | struct fsl_diu_data *machine_data; |
1336 | 1336 | ||
1337 | machine_data = dev_get_drvdata(&ofdev->dev); | 1337 | machine_data = dev_get_drvdata(&ofdev->dev); |
1338 | enable_lcdc(machine_data->fsl_diu_info[0]); | 1338 | enable_lcdc(machine_data->fsl_diu_info[0]); |
1339 | 1339 | ||
1340 | return 0; | 1340 | return 0; |
1341 | } | 1341 | } |
1342 | 1342 | ||
1343 | #else | 1343 | #else |
1344 | #define fsl_diu_suspend NULL | 1344 | #define fsl_diu_suspend NULL |
1345 | #define fsl_diu_resume NULL | 1345 | #define fsl_diu_resume NULL |
1346 | #endif /* CONFIG_PM */ | 1346 | #endif /* CONFIG_PM */ |
1347 | 1347 | ||
1348 | /* Align to 64-bit(8-byte), 32-byte, etc. */ | 1348 | /* Align to 64-bit(8-byte), 32-byte, etc. */ |
1349 | static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align) | 1349 | static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align) |
1350 | { | 1350 | { |
1351 | u32 offset, ssize; | 1351 | u32 offset, ssize; |
1352 | u32 mask; | 1352 | u32 mask; |
1353 | dma_addr_t paddr = 0; | 1353 | dma_addr_t paddr = 0; |
1354 | 1354 | ||
1355 | ssize = size + bytes_align; | 1355 | ssize = size + bytes_align; |
1356 | buf->vaddr = dma_alloc_coherent(0, ssize, &paddr, GFP_DMA | __GFP_ZERO); | 1356 | buf->vaddr = dma_alloc_coherent(0, ssize, &paddr, GFP_DMA | __GFP_ZERO); |
1357 | if (!buf->vaddr) | 1357 | if (!buf->vaddr) |
1358 | return -ENOMEM; | 1358 | return -ENOMEM; |
1359 | 1359 | ||
1360 | buf->paddr = (__u32) paddr; | 1360 | buf->paddr = (__u32) paddr; |
1361 | 1361 | ||
1362 | mask = bytes_align - 1; | 1362 | mask = bytes_align - 1; |
1363 | offset = (u32)buf->paddr & mask; | 1363 | offset = (u32)buf->paddr & mask; |
1364 | if (offset) { | 1364 | if (offset) { |
1365 | buf->offset = bytes_align - offset; | 1365 | buf->offset = bytes_align - offset; |
1366 | buf->paddr = (u32)buf->paddr + offset; | 1366 | buf->paddr = (u32)buf->paddr + offset; |
1367 | } else | 1367 | } else |
1368 | buf->offset = 0; | 1368 | buf->offset = 0; |
1369 | return 0; | 1369 | return 0; |
1370 | } | 1370 | } |
1371 | 1371 | ||
1372 | static void free_buf(struct diu_addr *buf, u32 size, u32 bytes_align) | 1372 | static void free_buf(struct diu_addr *buf, u32 size, u32 bytes_align) |
1373 | { | 1373 | { |
1374 | dma_free_coherent(0, size + bytes_align, | 1374 | dma_free_coherent(0, size + bytes_align, |
1375 | buf->vaddr, (buf->paddr - buf->offset)); | 1375 | buf->vaddr, (buf->paddr - buf->offset)); |
1376 | return; | 1376 | return; |
1377 | } | 1377 | } |
1378 | 1378 | ||
1379 | static ssize_t store_monitor(struct device *device, | 1379 | static ssize_t store_monitor(struct device *device, |
1380 | struct device_attribute *attr, const char *buf, size_t count) | 1380 | struct device_attribute *attr, const char *buf, size_t count) |
1381 | { | 1381 | { |
1382 | int old_monitor_port; | 1382 | int old_monitor_port; |
1383 | unsigned long val; | 1383 | unsigned long val; |
1384 | struct fsl_diu_data *machine_data = | 1384 | struct fsl_diu_data *machine_data = |
1385 | container_of(attr, struct fsl_diu_data, dev_attr); | 1385 | container_of(attr, struct fsl_diu_data, dev_attr); |
1386 | 1386 | ||
1387 | if (strict_strtoul(buf, 10, &val)) | 1387 | if (strict_strtoul(buf, 10, &val)) |
1388 | return 0; | 1388 | return 0; |
1389 | 1389 | ||
1390 | old_monitor_port = machine_data->monitor_port; | 1390 | old_monitor_port = machine_data->monitor_port; |
1391 | machine_data->monitor_port = diu_ops.set_sysfs_monitor_port(val); | 1391 | machine_data->monitor_port = diu_ops.set_sysfs_monitor_port(val); |
1392 | 1392 | ||
1393 | if (old_monitor_port != machine_data->monitor_port) { | 1393 | if (old_monitor_port != machine_data->monitor_port) { |
1394 | /* All AOIs need adjust pixel format | 1394 | /* All AOIs need adjust pixel format |
1395 | * fsl_diu_set_par only change the pixsel format here | 1395 | * fsl_diu_set_par only change the pixsel format here |
1396 | * unlikely to fail. */ | 1396 | * unlikely to fail. */ |
1397 | fsl_diu_set_par(machine_data->fsl_diu_info[0]); | 1397 | fsl_diu_set_par(machine_data->fsl_diu_info[0]); |
1398 | fsl_diu_set_par(machine_data->fsl_diu_info[1]); | 1398 | fsl_diu_set_par(machine_data->fsl_diu_info[1]); |
1399 | fsl_diu_set_par(machine_data->fsl_diu_info[2]); | 1399 | fsl_diu_set_par(machine_data->fsl_diu_info[2]); |
1400 | fsl_diu_set_par(machine_data->fsl_diu_info[3]); | 1400 | fsl_diu_set_par(machine_data->fsl_diu_info[3]); |
1401 | fsl_diu_set_par(machine_data->fsl_diu_info[4]); | 1401 | fsl_diu_set_par(machine_data->fsl_diu_info[4]); |
1402 | } | 1402 | } |
1403 | return count; | 1403 | return count; |
1404 | } | 1404 | } |
1405 | 1405 | ||
1406 | static ssize_t show_monitor(struct device *device, | 1406 | static ssize_t show_monitor(struct device *device, |
1407 | struct device_attribute *attr, char *buf) | 1407 | struct device_attribute *attr, char *buf) |
1408 | { | 1408 | { |
1409 | struct fsl_diu_data *machine_data = | 1409 | struct fsl_diu_data *machine_data = |
1410 | container_of(attr, struct fsl_diu_data, dev_attr); | 1410 | container_of(attr, struct fsl_diu_data, dev_attr); |
1411 | return diu_ops.show_monitor_port(machine_data->monitor_port, buf); | 1411 | return diu_ops.show_monitor_port(machine_data->monitor_port, buf); |
1412 | } | 1412 | } |
1413 | 1413 | ||
1414 | static int fsl_diu_probe(struct of_device *ofdev, | 1414 | static int fsl_diu_probe(struct of_device *ofdev, |
1415 | const struct of_device_id *match) | 1415 | const struct of_device_id *match) |
1416 | { | 1416 | { |
1417 | struct device_node *np = ofdev->node; | 1417 | struct device_node *np = ofdev->node; |
1418 | struct mfb_info *mfbi; | 1418 | struct mfb_info *mfbi; |
1419 | phys_addr_t dummy_ad_addr; | 1419 | phys_addr_t dummy_ad_addr; |
1420 | int ret, i, error = 0; | 1420 | int ret, i, error = 0; |
1421 | struct resource res; | 1421 | struct resource res; |
1422 | struct fsl_diu_data *machine_data; | 1422 | struct fsl_diu_data *machine_data; |
1423 | 1423 | ||
1424 | machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL); | 1424 | machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL); |
1425 | if (!machine_data) | 1425 | if (!machine_data) |
1426 | return -ENOMEM; | 1426 | return -ENOMEM; |
1427 | 1427 | ||
1428 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { | 1428 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { |
1429 | machine_data->fsl_diu_info[i] = | 1429 | machine_data->fsl_diu_info[i] = |
1430 | framebuffer_alloc(sizeof(struct mfb_info), &ofdev->dev); | 1430 | framebuffer_alloc(sizeof(struct mfb_info), &ofdev->dev); |
1431 | if (!machine_data->fsl_diu_info[i]) { | 1431 | if (!machine_data->fsl_diu_info[i]) { |
1432 | dev_err(&ofdev->dev, "cannot allocate memory\n"); | 1432 | dev_err(&ofdev->dev, "cannot allocate memory\n"); |
1433 | ret = -ENOMEM; | 1433 | ret = -ENOMEM; |
1434 | goto error2; | 1434 | goto error2; |
1435 | } | 1435 | } |
1436 | mfbi = machine_data->fsl_diu_info[i]->par; | 1436 | mfbi = machine_data->fsl_diu_info[i]->par; |
1437 | memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); | 1437 | memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); |
1438 | mfbi->parent = machine_data; | 1438 | mfbi->parent = machine_data; |
1439 | } | 1439 | } |
1440 | 1440 | ||
1441 | ret = of_address_to_resource(np, 0, &res); | 1441 | ret = of_address_to_resource(np, 0, &res); |
1442 | if (ret) { | 1442 | if (ret) { |
1443 | dev_err(&ofdev->dev, "could not obtain DIU address\n"); | 1443 | dev_err(&ofdev->dev, "could not obtain DIU address\n"); |
1444 | goto error; | 1444 | goto error; |
1445 | } | 1445 | } |
1446 | if (!res.start) { | 1446 | if (!res.start) { |
1447 | dev_err(&ofdev->dev, "invalid DIU address\n"); | 1447 | dev_err(&ofdev->dev, "invalid DIU address\n"); |
1448 | goto error; | 1448 | goto error; |
1449 | } | 1449 | } |
1450 | dev_dbg(&ofdev->dev, "%s, res.start: 0x%08x\n", __func__, res.start); | 1450 | dev_dbg(&ofdev->dev, "%s, res.start: 0x%08x\n", __func__, res.start); |
1451 | 1451 | ||
1452 | dr.diu_reg = ioremap(res.start, sizeof(struct diu)); | 1452 | dr.diu_reg = ioremap(res.start, sizeof(struct diu)); |
1453 | if (!dr.diu_reg) { | 1453 | if (!dr.diu_reg) { |
1454 | dev_err(&ofdev->dev, "Err: can't map DIU registers!\n"); | 1454 | dev_err(&ofdev->dev, "Err: can't map DIU registers!\n"); |
1455 | ret = -EFAULT; | 1455 | ret = -EFAULT; |
1456 | goto error2; | 1456 | goto error2; |
1457 | } | 1457 | } |
1458 | 1458 | ||
1459 | out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU anyway*/ | 1459 | out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU anyway*/ |
1460 | 1460 | ||
1461 | /* Get the IRQ of the DIU */ | 1461 | /* Get the IRQ of the DIU */ |
1462 | machine_data->irq = irq_of_parse_and_map(np, 0); | 1462 | machine_data->irq = irq_of_parse_and_map(np, 0); |
1463 | 1463 | ||
1464 | if (!machine_data->irq) { | 1464 | if (!machine_data->irq) { |
1465 | dev_err(&ofdev->dev, "could not get DIU IRQ\n"); | 1465 | dev_err(&ofdev->dev, "could not get DIU IRQ\n"); |
1466 | ret = -EINVAL; | 1466 | ret = -EINVAL; |
1467 | goto error; | 1467 | goto error; |
1468 | } | 1468 | } |
1469 | machine_data->monitor_port = monitor_port; | 1469 | machine_data->monitor_port = monitor_port; |
1470 | 1470 | ||
1471 | /* Area descriptor memory pool aligns to 64-bit boundary */ | 1471 | /* Area descriptor memory pool aligns to 64-bit boundary */ |
1472 | if (allocate_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8)) | 1472 | if (allocate_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8)) |
1473 | return -ENOMEM; | 1473 | return -ENOMEM; |
1474 | 1474 | ||
1475 | /* Get memory for Gamma Table - 32-byte aligned memory */ | 1475 | /* Get memory for Gamma Table - 32-byte aligned memory */ |
1476 | if (allocate_buf(&pool.gamma, 768, 32)) { | 1476 | if (allocate_buf(&pool.gamma, 768, 32)) { |
1477 | ret = -ENOMEM; | 1477 | ret = -ENOMEM; |
1478 | goto error; | 1478 | goto error; |
1479 | } | 1479 | } |
1480 | 1480 | ||
1481 | /* For performance, cursor bitmap buffer aligns to 32-byte boundary */ | 1481 | /* For performance, cursor bitmap buffer aligns to 32-byte boundary */ |
1482 | if (allocate_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32)) { | 1482 | if (allocate_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32)) { |
1483 | ret = -ENOMEM; | 1483 | ret = -ENOMEM; |
1484 | goto error; | 1484 | goto error; |
1485 | } | 1485 | } |
1486 | 1486 | ||
1487 | i = ARRAY_SIZE(machine_data->fsl_diu_info); | 1487 | i = ARRAY_SIZE(machine_data->fsl_diu_info); |
1488 | machine_data->dummy_ad = (struct diu_ad *) | 1488 | machine_data->dummy_ad = (struct diu_ad *) |
1489 | ((u32)pool.ad.vaddr + pool.ad.offset) + i; | 1489 | ((u32)pool.ad.vaddr + pool.ad.offset) + i; |
1490 | machine_data->dummy_ad->paddr = pool.ad.paddr + | 1490 | machine_data->dummy_ad->paddr = pool.ad.paddr + |
1491 | i * sizeof(struct diu_ad); | 1491 | i * sizeof(struct diu_ad); |
1492 | machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr); | 1492 | machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr); |
1493 | if (!machine_data->dummy_aoi_virt) { | 1493 | if (!machine_data->dummy_aoi_virt) { |
1494 | ret = -ENOMEM; | 1494 | ret = -ENOMEM; |
1495 | goto error; | 1495 | goto error; |
1496 | } | 1496 | } |
1497 | machine_data->dummy_ad->addr = cpu_to_le32(dummy_ad_addr); | 1497 | machine_data->dummy_ad->addr = cpu_to_le32(dummy_ad_addr); |
1498 | machine_data->dummy_ad->pix_fmt = 0x88882317; | 1498 | machine_data->dummy_ad->pix_fmt = 0x88882317; |
1499 | machine_data->dummy_ad->src_size_g_alpha = cpu_to_le32((4 << 12) | 4); | 1499 | machine_data->dummy_ad->src_size_g_alpha = cpu_to_le32((4 << 12) | 4); |
1500 | machine_data->dummy_ad->aoi_size = cpu_to_le32((4 << 16) | 2); | 1500 | machine_data->dummy_ad->aoi_size = cpu_to_le32((4 << 16) | 2); |
1501 | machine_data->dummy_ad->offset_xyi = 0; | 1501 | machine_data->dummy_ad->offset_xyi = 0; |
1502 | machine_data->dummy_ad->offset_xyd = 0; | 1502 | machine_data->dummy_ad->offset_xyd = 0; |
1503 | machine_data->dummy_ad->next_ad = 0; | 1503 | machine_data->dummy_ad->next_ad = 0; |
1504 | 1504 | ||
1505 | out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr); | 1505 | out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr); |
1506 | out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr); | 1506 | out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr); |
1507 | out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr); | 1507 | out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr); |
1508 | 1508 | ||
1509 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { | 1509 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { |
1510 | machine_data->fsl_diu_info[i]->fix.smem_start = 0; | 1510 | machine_data->fsl_diu_info[i]->fix.smem_start = 0; |
1511 | mfbi = machine_data->fsl_diu_info[i]->par; | 1511 | mfbi = machine_data->fsl_diu_info[i]->par; |
1512 | mfbi->ad = (struct diu_ad *)((u32)pool.ad.vaddr | 1512 | mfbi->ad = (struct diu_ad *)((u32)pool.ad.vaddr |
1513 | + pool.ad.offset) + i; | 1513 | + pool.ad.offset) + i; |
1514 | mfbi->ad->paddr = pool.ad.paddr + i * sizeof(struct diu_ad); | 1514 | mfbi->ad->paddr = pool.ad.paddr + i * sizeof(struct diu_ad); |
1515 | ret = install_fb(machine_data->fsl_diu_info[i]); | 1515 | ret = install_fb(machine_data->fsl_diu_info[i]); |
1516 | if (ret) { | 1516 | if (ret) { |
1517 | dev_err(&ofdev->dev, | 1517 | dev_err(&ofdev->dev, |
1518 | "Failed to register framebuffer %d\n", | 1518 | "Failed to register framebuffer %d\n", |
1519 | i); | 1519 | i); |
1520 | goto error; | 1520 | goto error; |
1521 | } | 1521 | } |
1522 | } | 1522 | } |
1523 | 1523 | ||
1524 | if (request_irq_local(machine_data->irq)) { | 1524 | if (request_irq_local(machine_data->irq)) { |
1525 | dev_err(machine_data->fsl_diu_info[0]->dev, | 1525 | dev_err(machine_data->fsl_diu_info[0]->dev, |
1526 | "could not request irq for diu."); | 1526 | "could not request irq for diu."); |
1527 | goto error; | 1527 | goto error; |
1528 | } | 1528 | } |
1529 | 1529 | ||
1530 | machine_data->dev_attr.attr.name = "monitor"; | 1530 | machine_data->dev_attr.attr.name = "monitor"; |
1531 | machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR; | 1531 | machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR; |
1532 | machine_data->dev_attr.show = show_monitor; | 1532 | machine_data->dev_attr.show = show_monitor; |
1533 | machine_data->dev_attr.store = store_monitor; | 1533 | machine_data->dev_attr.store = store_monitor; |
1534 | error = device_create_file(machine_data->fsl_diu_info[0]->dev, | 1534 | error = device_create_file(machine_data->fsl_diu_info[0]->dev, |
1535 | &machine_data->dev_attr); | 1535 | &machine_data->dev_attr); |
1536 | if (error) { | 1536 | if (error) { |
1537 | dev_err(machine_data->fsl_diu_info[0]->dev, | 1537 | dev_err(machine_data->fsl_diu_info[0]->dev, |
1538 | "could not create sysfs %s file\n", | 1538 | "could not create sysfs %s file\n", |
1539 | machine_data->dev_attr.attr.name); | 1539 | machine_data->dev_attr.attr.name); |
1540 | } | 1540 | } |
1541 | 1541 | ||
1542 | dev_set_drvdata(&ofdev->dev, machine_data); | 1542 | dev_set_drvdata(&ofdev->dev, machine_data); |
1543 | return 0; | 1543 | return 0; |
1544 | 1544 | ||
1545 | error: | 1545 | error: |
1546 | for (i = ARRAY_SIZE(machine_data->fsl_diu_info); | 1546 | for (i = ARRAY_SIZE(machine_data->fsl_diu_info); |
1547 | i > 0; i--) | 1547 | i > 0; i--) |
1548 | uninstall_fb(machine_data->fsl_diu_info[i - 1]); | 1548 | uninstall_fb(machine_data->fsl_diu_info[i - 1]); |
1549 | if (pool.ad.vaddr) | 1549 | if (pool.ad.vaddr) |
1550 | free_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8); | 1550 | free_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8); |
1551 | if (pool.gamma.vaddr) | 1551 | if (pool.gamma.vaddr) |
1552 | free_buf(&pool.gamma, 768, 32); | 1552 | free_buf(&pool.gamma, 768, 32); |
1553 | if (pool.cursor.vaddr) | 1553 | if (pool.cursor.vaddr) |
1554 | free_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32); | 1554 | free_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32); |
1555 | if (machine_data->dummy_aoi_virt) | 1555 | if (machine_data->dummy_aoi_virt) |
1556 | fsl_diu_free(machine_data->dummy_aoi_virt, 64); | 1556 | fsl_diu_free(machine_data->dummy_aoi_virt, 64); |
1557 | iounmap(dr.diu_reg); | 1557 | iounmap(dr.diu_reg); |
1558 | 1558 | ||
1559 | error2: | 1559 | error2: |
1560 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) | 1560 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) |
1561 | if (machine_data->fsl_diu_info[i]) | 1561 | if (machine_data->fsl_diu_info[i]) |
1562 | framebuffer_release(machine_data->fsl_diu_info[i]); | 1562 | framebuffer_release(machine_data->fsl_diu_info[i]); |
1563 | kfree(machine_data); | 1563 | kfree(machine_data); |
1564 | 1564 | ||
1565 | return ret; | 1565 | return ret; |
1566 | } | 1566 | } |
1567 | 1567 | ||
1568 | 1568 | ||
1569 | static int fsl_diu_remove(struct of_device *ofdev) | 1569 | static int fsl_diu_remove(struct of_device *ofdev) |
1570 | { | 1570 | { |
1571 | struct fsl_diu_data *machine_data; | 1571 | struct fsl_diu_data *machine_data; |
1572 | int i; | 1572 | int i; |
1573 | 1573 | ||
1574 | machine_data = dev_get_drvdata(&ofdev->dev); | 1574 | machine_data = dev_get_drvdata(&ofdev->dev); |
1575 | disable_lcdc(machine_data->fsl_diu_info[0]); | 1575 | disable_lcdc(machine_data->fsl_diu_info[0]); |
1576 | free_irq_local(machine_data->irq); | 1576 | free_irq_local(machine_data->irq); |
1577 | for (i = ARRAY_SIZE(machine_data->fsl_diu_info); i > 0; i--) | 1577 | for (i = ARRAY_SIZE(machine_data->fsl_diu_info); i > 0; i--) |
1578 | uninstall_fb(machine_data->fsl_diu_info[i - 1]); | 1578 | uninstall_fb(machine_data->fsl_diu_info[i - 1]); |
1579 | if (pool.ad.vaddr) | 1579 | if (pool.ad.vaddr) |
1580 | free_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8); | 1580 | free_buf(&pool.ad, sizeof(struct diu_ad) * FSL_AOI_NUM, 8); |
1581 | if (pool.gamma.vaddr) | 1581 | if (pool.gamma.vaddr) |
1582 | free_buf(&pool.gamma, 768, 32); | 1582 | free_buf(&pool.gamma, 768, 32); |
1583 | if (pool.cursor.vaddr) | 1583 | if (pool.cursor.vaddr) |
1584 | free_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32); | 1584 | free_buf(&pool.cursor, MAX_CURS * MAX_CURS * 2, 32); |
1585 | if (machine_data->dummy_aoi_virt) | 1585 | if (machine_data->dummy_aoi_virt) |
1586 | fsl_diu_free(machine_data->dummy_aoi_virt, 64); | 1586 | fsl_diu_free(machine_data->dummy_aoi_virt, 64); |
1587 | iounmap(dr.diu_reg); | 1587 | iounmap(dr.diu_reg); |
1588 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) | 1588 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) |
1589 | if (machine_data->fsl_diu_info[i]) | 1589 | if (machine_data->fsl_diu_info[i]) |
1590 | framebuffer_release(machine_data->fsl_diu_info[i]); | 1590 | framebuffer_release(machine_data->fsl_diu_info[i]); |
1591 | kfree(machine_data); | 1591 | kfree(machine_data); |
1592 | 1592 | ||
1593 | return 0; | 1593 | return 0; |
1594 | } | 1594 | } |
1595 | 1595 | ||
1596 | #ifndef MODULE | 1596 | #ifndef MODULE |
1597 | static int __init fsl_diu_setup(char *options) | 1597 | static int __init fsl_diu_setup(char *options) |
1598 | { | 1598 | { |
1599 | char *opt; | 1599 | char *opt; |
1600 | unsigned long val; | 1600 | unsigned long val; |
1601 | 1601 | ||
1602 | if (!options || !*options) | 1602 | if (!options || !*options) |
1603 | return 0; | 1603 | return 0; |
1604 | 1604 | ||
1605 | while ((opt = strsep(&options, ",")) != NULL) { | 1605 | while ((opt = strsep(&options, ",")) != NULL) { |
1606 | if (!*opt) | 1606 | if (!*opt) |
1607 | continue; | 1607 | continue; |
1608 | if (!strncmp(opt, "monitor=", 8)) { | 1608 | if (!strncmp(opt, "monitor=", 8)) { |
1609 | if (!strict_strtoul(opt + 8, 10, &val) && (val <= 2)) | 1609 | if (!strict_strtoul(opt + 8, 10, &val) && (val <= 2)) |
1610 | monitor_port = val; | 1610 | monitor_port = val; |
1611 | } else if (!strncmp(opt, "bpp=", 4)) { | 1611 | } else if (!strncmp(opt, "bpp=", 4)) { |
1612 | if (!strict_strtoul(opt + 4, 10, &val)) | 1612 | if (!strict_strtoul(opt + 4, 10, &val)) |
1613 | default_bpp = val; | 1613 | default_bpp = val; |
1614 | } else | 1614 | } else |
1615 | fb_mode = opt; | 1615 | fb_mode = opt; |
1616 | } | 1616 | } |
1617 | 1617 | ||
1618 | return 0; | 1618 | return 0; |
1619 | } | 1619 | } |
1620 | #endif | 1620 | #endif |
1621 | 1621 | ||
1622 | static struct of_device_id fsl_diu_match[] = { | 1622 | static struct of_device_id fsl_diu_match[] = { |
1623 | { | 1623 | { |
1624 | .compatible = "fsl,diu", | 1624 | .compatible = "fsl,diu", |
1625 | }, | 1625 | }, |
1626 | {} | 1626 | {} |
1627 | }; | 1627 | }; |
1628 | MODULE_DEVICE_TABLE(of, fsl_diu_match); | 1628 | MODULE_DEVICE_TABLE(of, fsl_diu_match); |
1629 | 1629 | ||
1630 | static struct of_platform_driver fsl_diu_driver = { | 1630 | static struct of_platform_driver fsl_diu_driver = { |
1631 | .owner = THIS_MODULE, | 1631 | .owner = THIS_MODULE, |
1632 | .name = "fsl_diu", | 1632 | .name = "fsl_diu", |
1633 | .match_table = fsl_diu_match, | 1633 | .match_table = fsl_diu_match, |
1634 | .probe = fsl_diu_probe, | 1634 | .probe = fsl_diu_probe, |
1635 | .remove = fsl_diu_remove, | 1635 | .remove = fsl_diu_remove, |
1636 | .suspend = fsl_diu_suspend, | 1636 | .suspend = fsl_diu_suspend, |
1637 | .resume = fsl_diu_resume, | 1637 | .resume = fsl_diu_resume, |
1638 | }; | 1638 | }; |
1639 | 1639 | ||
1640 | static int __init fsl_diu_init(void) | 1640 | static int __init fsl_diu_init(void) |
1641 | { | 1641 | { |
1642 | #ifdef CONFIG_NOT_COHERENT_CACHE | 1642 | #ifdef CONFIG_NOT_COHERENT_CACHE |
1643 | struct device_node *np; | 1643 | struct device_node *np; |
1644 | const u32 *prop; | 1644 | const u32 *prop; |
1645 | #endif | 1645 | #endif |
1646 | int ret; | 1646 | int ret; |
1647 | #ifndef MODULE | 1647 | #ifndef MODULE |
1648 | char *option; | 1648 | char *option; |
1649 | 1649 | ||
1650 | /* | 1650 | /* |
1651 | * For kernel boot options (in 'video=xxxfb:<options>' format) | 1651 | * For kernel boot options (in 'video=xxxfb:<options>' format) |
1652 | */ | 1652 | */ |
1653 | if (fb_get_options("fslfb", &option)) | 1653 | if (fb_get_options("fslfb", &option)) |
1654 | return -ENODEV; | 1654 | return -ENODEV; |
1655 | fsl_diu_setup(option); | 1655 | fsl_diu_setup(option); |
1656 | #endif | 1656 | #endif |
1657 | printk(KERN_INFO "Freescale DIU driver\n"); | 1657 | printk(KERN_INFO "Freescale DIU driver\n"); |
1658 | 1658 | ||
1659 | #ifdef CONFIG_NOT_COHERENT_CACHE | 1659 | #ifdef CONFIG_NOT_COHERENT_CACHE |
1660 | np = of_find_node_by_type(NULL, "cpu"); | 1660 | np = of_find_node_by_type(NULL, "cpu"); |
1661 | if (!np) { | 1661 | if (!np) { |
1662 | printk(KERN_ERR "Err: can't find device node 'cpu'\n"); | 1662 | printk(KERN_ERR "Err: can't find device node 'cpu'\n"); |
1663 | return -ENODEV; | 1663 | return -ENODEV; |
1664 | } | 1664 | } |
1665 | 1665 | ||
1666 | prop = of_get_property(np, "d-cache-size", NULL); | 1666 | prop = of_get_property(np, "d-cache-size", NULL); |
1667 | if (prop == NULL) | 1667 | if (prop == NULL) |
1668 | return -ENODEV; | 1668 | return -ENODEV; |
1669 | 1669 | ||
1670 | /* Freescale PLRU requires 13/8 times the cache size to do a proper | 1670 | /* Freescale PLRU requires 13/8 times the cache size to do a proper |
1671 | displacement flush | 1671 | displacement flush |
1672 | */ | 1672 | */ |
1673 | coherence_data_size = *prop * 13; | 1673 | coherence_data_size = *prop * 13; |
1674 | coherence_data_size /= 8; | 1674 | coherence_data_size /= 8; |
1675 | 1675 | ||
1676 | prop = of_get_property(np, "d-cache-line-size", NULL); | 1676 | prop = of_get_property(np, "d-cache-line-size", NULL); |
1677 | if (prop == NULL) | 1677 | if (prop == NULL) |
1678 | return -ENODEV; | 1678 | return -ENODEV; |
1679 | d_cache_line_size = *prop; | 1679 | d_cache_line_size = *prop; |
1680 | 1680 | ||
1681 | of_node_put(np); | 1681 | of_node_put(np); |
1682 | coherence_data = vmalloc(coherence_data_size); | 1682 | coherence_data = vmalloc(coherence_data_size); |
1683 | if (!coherence_data) | 1683 | if (!coherence_data) |
1684 | return -ENOMEM; | 1684 | return -ENOMEM; |
1685 | #endif | 1685 | #endif |
1686 | ret = of_register_platform_driver(&fsl_diu_driver); | 1686 | ret = of_register_platform_driver(&fsl_diu_driver); |
1687 | if (ret) { | 1687 | if (ret) { |
1688 | printk(KERN_ERR | 1688 | printk(KERN_ERR |
1689 | "fsl-diu: failed to register platform driver\n"); | 1689 | "fsl-diu: failed to register platform driver\n"); |
1690 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 1690 | #if defined(CONFIG_NOT_COHERENT_CACHE) |
1691 | vfree(coherence_data); | 1691 | vfree(coherence_data); |
1692 | #endif | 1692 | #endif |
1693 | iounmap(dr.diu_reg); | 1693 | iounmap(dr.diu_reg); |
1694 | } | 1694 | } |
1695 | return ret; | 1695 | return ret; |
1696 | } | 1696 | } |
1697 | 1697 | ||
1698 | static void __exit fsl_diu_exit(void) | 1698 | static void __exit fsl_diu_exit(void) |
1699 | { | 1699 | { |
1700 | of_unregister_platform_driver(&fsl_diu_driver); | 1700 | of_unregister_platform_driver(&fsl_diu_driver); |
1701 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 1701 | #if defined(CONFIG_NOT_COHERENT_CACHE) |
1702 | vfree(coherence_data); | 1702 | vfree(coherence_data); |
1703 | #endif | 1703 | #endif |
1704 | } | 1704 | } |
1705 | 1705 | ||
1706 | module_init(fsl_diu_init); | 1706 | module_init(fsl_diu_init); |
1707 | module_exit(fsl_diu_exit); | 1707 | module_exit(fsl_diu_exit); |
1708 | 1708 | ||
1709 | MODULE_AUTHOR("York Sun <yorksun@freescale.com>"); | 1709 | MODULE_AUTHOR("York Sun <yorksun@freescale.com>"); |
1710 | MODULE_DESCRIPTION("Freescale DIU framebuffer driver"); | 1710 | MODULE_DESCRIPTION("Freescale DIU framebuffer driver"); |
1711 | MODULE_LICENSE("GPL"); | 1711 | MODULE_LICENSE("GPL"); |
1712 | 1712 | ||
1713 | module_param_named(mode, fb_mode, charp, 0); | 1713 | module_param_named(mode, fb_mode, charp, 0); |
1714 | MODULE_PARM_DESC(mode, | 1714 | MODULE_PARM_DESC(mode, |
1715 | "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); | 1715 | "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); |
1716 | module_param_named(bpp, default_bpp, ulong, 0); | 1716 | module_param_named(bpp, default_bpp, ulong, 0); |
1717 | MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode"); | 1717 | MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode"); |
1718 | module_param_named(monitor, monitor_port, int, 0); | 1718 | module_param_named(monitor, monitor_port, int, 0); |
1719 | MODULE_PARM_DESC(monitor, | 1719 | MODULE_PARM_DESC(monitor, |
1720 | "Specify the monitor port (0, 1 or 2) if supported by the platform"); | 1720 | "Specify the monitor port (0, 1 or 2) if supported by the platform"); |
1721 | 1721 | ||
1722 | 1722 |