diff options
author | Antonino A. Daplas <adaplas@gmail.com> | 2005-11-09 00:39:15 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-09 10:56:35 -0500 |
commit | a812c94b94e3db76d1af68208fb3edef69070401 (patch) | |
tree | 8dd2ecd1e1981e3423d8c3aaf796aeb3f38f91f1 | |
parent | ed8c0e99f27451a9b980adf0de318d60e6de811f (diff) |
[PATCH] fbcon: Console Rotation - Add ability to control rotation via sysfs
Add ability to set rotation via sysfs. The attributes are located in
/sys/class/graphics/fb[n] and accepts 0 - unrotated; 1 - clockwise; 2 - upside
down; 3 - counterclockwise.
The attributes are:
con_rotate (r/w) - set rotation of the active console
con_rotate_all (w) - set rotation of all consoles
rotate (r/w) - set rotation of the framebuffer, if supported.
Currently, none of the drivers support this.
This is probably temporary, since con_rotate and con_rotate_all are
console-specific and has no business being under the fb device. However,
until the console layer acquires it's own sysfs class, these attributes will
temporarily reside here.
Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/video/console/fbcon.c | 72 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 22 | ||||
-rw-r--r-- | drivers/video/fbsysfs.c | 67 | ||||
-rw-r--r-- | include/linux/fb.h | 7 |
4 files changed, 168 insertions, 0 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index e829ba18e0a5..e7802ffe549a 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -193,6 +193,8 @@ static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *va | |||
193 | int unit); | 193 | int unit); |
194 | static void fbcon_redraw_move(struct vc_data *vc, struct display *p, | 194 | static void fbcon_redraw_move(struct vc_data *vc, struct display *p, |
195 | int line, int count, int dy); | 195 | int line, int count, int dy); |
196 | static void fbcon_modechanged(struct fb_info *info); | ||
197 | static void fbcon_set_all_vcs(struct fb_info *info); | ||
196 | 198 | ||
197 | #ifdef CONFIG_MAC | 199 | #ifdef CONFIG_MAC |
198 | /* | 200 | /* |
@@ -218,6 +220,51 @@ static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) | |||
218 | else | 220 | else |
219 | ops->rotate = 0; | 221 | ops->rotate = 0; |
220 | } | 222 | } |
223 | |||
224 | static void fbcon_rotate(struct fb_info *info, u32 rotate) | ||
225 | { | ||
226 | struct fbcon_ops *ops= info->fbcon_par; | ||
227 | struct fb_info *fb_info; | ||
228 | |||
229 | if (!ops || ops->currcon == -1) | ||
230 | return; | ||
231 | |||
232 | fb_info = registered_fb[con2fb_map[ops->currcon]]; | ||
233 | |||
234 | if (info == fb_info) { | ||
235 | struct display *p = &fb_display[ops->currcon]; | ||
236 | |||
237 | if (rotate < 4) | ||
238 | p->con_rotate = rotate; | ||
239 | else | ||
240 | p->con_rotate = 0; | ||
241 | |||
242 | fbcon_modechanged(info); | ||
243 | } | ||
244 | } | ||
245 | |||
246 | static void fbcon_rotate_all(struct fb_info *info, u32 rotate) | ||
247 | { | ||
248 | struct fbcon_ops *ops = info->fbcon_par; | ||
249 | struct vc_data *vc; | ||
250 | struct display *p; | ||
251 | int i; | ||
252 | |||
253 | if (!ops || ops->currcon < 0 || rotate > 3) | ||
254 | return; | ||
255 | |||
256 | for (i = 0; i < MAX_NR_CONSOLES; i++) { | ||
257 | vc = vc_cons[i].d; | ||
258 | if (!vc || vc->vc_mode != KD_TEXT || | ||
259 | registered_fb[con2fb_map[i]] != info) | ||
260 | continue; | ||
261 | |||
262 | p = &fb_display[vc->vc_num]; | ||
263 | p->con_rotate = rotate; | ||
264 | } | ||
265 | |||
266 | fbcon_set_all_vcs(info); | ||
267 | } | ||
221 | #else | 268 | #else |
222 | static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) | 269 | static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) |
223 | { | 270 | { |
@@ -225,8 +272,25 @@ static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) | |||
225 | 272 | ||
226 | ops->rotate = FB_ROTATE_UR; | 273 | ops->rotate = FB_ROTATE_UR; |
227 | } | 274 | } |
275 | |||
276 | static void fbcon_rotate(struct fb_info *info, u32 rotate) | ||
277 | { | ||
278 | return; | ||
279 | } | ||
280 | |||
281 | static void fbcon_rotate_all(struct fb_info *info, u32 rotate) | ||
282 | { | ||
283 | return; | ||
284 | } | ||
228 | #endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ | 285 | #endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ |
229 | 286 | ||
287 | static int fbcon_get_rotate(struct fb_info *info) | ||
288 | { | ||
289 | struct fbcon_ops *ops = info->fbcon_par; | ||
290 | |||
291 | return (ops) ? ops->rotate : 0; | ||
292 | } | ||
293 | |||
230 | static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) | 294 | static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) |
231 | { | 295 | { |
232 | struct fbcon_ops *ops = info->fbcon_par; | 296 | struct fbcon_ops *ops = info->fbcon_par; |
@@ -2864,6 +2928,14 @@ static int fbcon_event_notify(struct notifier_block *self, | |||
2864 | case FB_EVENT_NEW_MODELIST: | 2928 | case FB_EVENT_NEW_MODELIST: |
2865 | fbcon_new_modelist(info); | 2929 | fbcon_new_modelist(info); |
2866 | break; | 2930 | break; |
2931 | case FB_EVENT_SET_CON_ROTATE: | ||
2932 | fbcon_rotate(info, *(int *)event->data); | ||
2933 | break; | ||
2934 | case FB_EVENT_GET_CON_ROTATE: | ||
2935 | ret = fbcon_get_rotate(info); | ||
2936 | break; | ||
2937 | case FB_EVENT_SET_CON_ROTATE_ALL: | ||
2938 | fbcon_rotate_all(info, *(int *)event->data); | ||
2867 | } | 2939 | } |
2868 | 2940 | ||
2869 | return ret; | 2941 | return ret; |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 7a2a8fa50b3b..81b6cd23ea1d 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1319,6 +1319,28 @@ int fb_new_modelist(struct fb_info *info) | |||
1319 | return err; | 1319 | return err; |
1320 | } | 1320 | } |
1321 | 1321 | ||
1322 | /** | ||
1323 | * fb_con_duit - user<->fbcon passthrough | ||
1324 | * @info: struct fb_info | ||
1325 | * @event: notification event to be passed to fbcon | ||
1326 | * @data: private data | ||
1327 | * | ||
1328 | * DESCRIPTION | ||
1329 | * This function is an fbcon-user event passing channel | ||
1330 | * which bypasses fbdev. This is hopefully temporary | ||
1331 | * until a user interface for fbcon is created | ||
1332 | */ | ||
1333 | int fb_con_duit(struct fb_info *info, int event, void *data) | ||
1334 | { | ||
1335 | struct fb_event evnt; | ||
1336 | |||
1337 | evnt.info = info; | ||
1338 | evnt.data = data; | ||
1339 | |||
1340 | return notifier_call_chain(&fb_notifier_list, event, &evnt); | ||
1341 | } | ||
1342 | EXPORT_SYMBOL(fb_con_duit); | ||
1343 | |||
1322 | static char *video_options[FB_MAX]; | 1344 | static char *video_options[FB_MAX]; |
1323 | static int ofonly; | 1345 | static int ofonly; |
1324 | 1346 | ||
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 007c8e9b2b39..08dac9580d15 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c | |||
@@ -213,6 +213,70 @@ static ssize_t show_bpp(struct class_device *class_device, char *buf) | |||
213 | return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel); | 213 | return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel); |
214 | } | 214 | } |
215 | 215 | ||
216 | static ssize_t store_rotate(struct class_device *class_device, const char *buf, | ||
217 | size_t count) | ||
218 | { | ||
219 | struct fb_info *fb_info = class_get_devdata(class_device); | ||
220 | struct fb_var_screeninfo var; | ||
221 | char **last = NULL; | ||
222 | int err; | ||
223 | |||
224 | var = fb_info->var; | ||
225 | var.rotate = simple_strtoul(buf, last, 0); | ||
226 | |||
227 | if ((err = activate(fb_info, &var))) | ||
228 | return err; | ||
229 | |||
230 | return count; | ||
231 | } | ||
232 | |||
233 | |||
234 | static ssize_t show_rotate(struct class_device *class_device, char *buf) | ||
235 | { | ||
236 | struct fb_info *fb_info = class_get_devdata(class_device); | ||
237 | |||
238 | return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate); | ||
239 | } | ||
240 | |||
241 | static ssize_t store_con_rotate(struct class_device *class_device, | ||
242 | const char *buf, size_t count) | ||
243 | { | ||
244 | struct fb_info *fb_info = class_get_devdata(class_device); | ||
245 | int rotate; | ||
246 | char **last = NULL; | ||
247 | |||
248 | acquire_console_sem(); | ||
249 | rotate = simple_strtoul(buf, last, 0); | ||
250 | fb_con_duit(fb_info, FB_EVENT_SET_CON_ROTATE, &rotate); | ||
251 | release_console_sem(); | ||
252 | return count; | ||
253 | } | ||
254 | |||
255 | static ssize_t store_con_rotate_all(struct class_device *class_device, | ||
256 | const char *buf, size_t count) | ||
257 | { | ||
258 | struct fb_info *fb_info = class_get_devdata(class_device); | ||
259 | int rotate; | ||
260 | char **last = NULL; | ||
261 | |||
262 | acquire_console_sem(); | ||
263 | rotate = simple_strtoul(buf, last, 0); | ||
264 | fb_con_duit(fb_info, FB_EVENT_SET_CON_ROTATE_ALL, &rotate); | ||
265 | release_console_sem(); | ||
266 | return count; | ||
267 | } | ||
268 | |||
269 | static ssize_t show_con_rotate(struct class_device *class_device, char *buf) | ||
270 | { | ||
271 | struct fb_info *fb_info = class_get_devdata(class_device); | ||
272 | int rotate; | ||
273 | |||
274 | acquire_console_sem(); | ||
275 | rotate = fb_con_duit(fb_info, FB_EVENT_GET_CON_ROTATE, NULL); | ||
276 | release_console_sem(); | ||
277 | return snprintf(buf, PAGE_SIZE, "%d\n", rotate); | ||
278 | } | ||
279 | |||
216 | static ssize_t store_virtual(struct class_device *class_device, | 280 | static ssize_t store_virtual(struct class_device *class_device, |
217 | const char * buf, size_t count) | 281 | const char * buf, size_t count) |
218 | { | 282 | { |
@@ -440,6 +504,9 @@ static struct class_device_attribute class_device_attrs[] = { | |||
440 | __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), | 504 | __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), |
441 | __ATTR(name, S_IRUGO, show_name, NULL), | 505 | __ATTR(name, S_IRUGO, show_name, NULL), |
442 | __ATTR(stride, S_IRUGO, show_stride, NULL), | 506 | __ATTR(stride, S_IRUGO, show_stride, NULL), |
507 | __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate), | ||
508 | __ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate), | ||
509 | __ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all), | ||
443 | }; | 510 | }; |
444 | 511 | ||
445 | int fb_init_class_device(struct fb_info *fb_info) | 512 | int fb_init_class_device(struct fb_info *fb_info) |
diff --git a/include/linux/fb.h b/include/linux/fb.h index 357dd3a0a01e..04a58f33ec53 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -508,6 +508,12 @@ struct fb_cursor_user { | |||
508 | /* The resolution of the passed in fb_info about to change and | 508 | /* The resolution of the passed in fb_info about to change and |
509 | all vc's should be changed */ | 509 | all vc's should be changed */ |
510 | #define FB_EVENT_MODE_CHANGE_ALL 0x0A | 510 | #define FB_EVENT_MODE_CHANGE_ALL 0x0A |
511 | /* CONSOLE-SPECIFIC: set console rotation */ | ||
512 | #define FB_EVENT_SET_CON_ROTATE 0x0B | ||
513 | /* CONSOLE-SPECIFIC: get console rotation */ | ||
514 | #define FB_EVENT_GET_CON_ROTATE 0x0C | ||
515 | /* CONSOLE-SPECIFIC: rotate all consoles */ | ||
516 | #define FB_EVENT_SET_CON_ROTATE_ALL 0x0D | ||
511 | 517 | ||
512 | struct fb_event { | 518 | struct fb_event { |
513 | struct fb_info *info; | 519 | struct fb_info *info; |
@@ -836,6 +842,7 @@ extern int fb_get_color_depth(struct fb_var_screeninfo *var, | |||
836 | struct fb_fix_screeninfo *fix); | 842 | struct fb_fix_screeninfo *fix); |
837 | extern int fb_get_options(char *name, char **option); | 843 | extern int fb_get_options(char *name, char **option); |
838 | extern int fb_new_modelist(struct fb_info *info); | 844 | extern int fb_new_modelist(struct fb_info *info); |
845 | extern int fb_con_duit(struct fb_info *info, int event, void *data); | ||
839 | 846 | ||
840 | extern struct fb_info *registered_fb[FB_MAX]; | 847 | extern struct fb_info *registered_fb[FB_MAX]; |
841 | extern int num_registered_fb; | 848 | extern int num_registered_fb; |