Blame view

drivers/video/fbsysfs.c 14.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /*
   * fbsysfs.c - framebuffer device class and attributes
   *
   * Copyright (c) 2004 James Simmons <jsimmons@infradead.org>
   * 
   *	This program is free software you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   */
  
  /*
   * Note:  currently there's only stubs for framebuffer_alloc and
   * framebuffer_release here.  The reson for that is that until all drivers
   * are converted to use it a sysfsification will open OOPSable races.
   */
  
  #include <linux/kernel.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
  #include <linux/fb.h>
  #include <linux/console.h>
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
22
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23

1a6600be3   Antonino A. Daplas   [PATCH] fbdev: Ho...
24
  #define FB_SYSFS_FLAG_ATTR 1
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
29
30
31
32
33
34
  /**
   * framebuffer_alloc - creates a new frame buffer info structure
   *
   * @size: size of driver private data, can be zero
   * @dev: pointer to the device for this fb, this can be NULL
   *
   * Creates a new frame buffer info structure. Also reserves @size bytes
   * for driver private data (info->par). info->par (if any) will be
   * aligned to sizeof(long).
   *
25985edce   Lucas De Marchi   Fix common misspe...
35
   * Returns the new structure, or NULL if an error occurred.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
40
41
42
43
44
45
46
47
   *
   */
  struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
  {
  #define BYTES_PER_LONG (BITS_PER_LONG/8)
  #define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))
  	int fb_info_size = sizeof(struct fb_info);
  	struct fb_info *info;
  	char *p;
  
  	if (size)
  		fb_info_size += PADDING;
def1ededb   Antonino A. Daplas   [PATCH] fbdev: Re...
48
  	p = kzalloc(fb_info_size + size, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
  	if (!p)
  		return NULL;
def1ededb   Antonino A. Daplas   [PATCH] fbdev: Re...
51

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
57
  	info = (struct fb_info *) p;
  
  	if (size)
  		info->par = p + fb_info_size;
  
  	info->device = dev;
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
58
  #ifdef CONFIG_FB_BACKLIGHT
37ce69a57   Richard Purdie   backlight: Rework...
59
  	mutex_init(&info->bl_curve_mutex);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
60
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
64
65
66
67
68
69
70
71
  	return info;
  #undef PADDING
  #undef BYTES_PER_LONG
  }
  EXPORT_SYMBOL(framebuffer_alloc);
  
  /**
   * framebuffer_release - marks the structure available for freeing
   *
   * @info: frame buffer info structure
   *
78cde0887   Greg Kroah-Hartman   Driver core: conv...
72
   * Drop the reference count of the device embedded in the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
76
77
   * framebuffer info structure.
   *
   */
  void framebuffer_release(struct fb_info *info)
  {
1471ca9aa   Marcin Slusarz   fbdev: allow pass...
78
  	kfree(info->apertures);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
83
84
85
86
87
  	kfree(info);
  }
  EXPORT_SYMBOL(framebuffer_release);
  
  static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
  {
  	int err;
  
  	var->activate |= FB_ACTIVATE_FORCE;
ac751efa6   Torben Hohn   console: rename a...
88
  	console_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
91
  	fb_info->flags |= FBINFO_MISC_USEREVENT;
  	err = fb_set_var(fb_info, var);
  	fb_info->flags &= ~FBINFO_MISC_USEREVENT;
ac751efa6   Torben Hohn   console: rename a...
92
  	console_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
95
96
97
98
99
100
101
  	if (err)
  		return err;
  	return 0;
  }
  
  static int mode_string(char *buf, unsigned int offset,
  		       const struct fb_videomode *mode)
  {
  	char m = 'U';
9dac73a4e   Daniel R Thompson   [PATCH] fbdev: ta...
102
  	char v = 'p';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
106
107
108
  	if (mode->flag & FB_MODE_IS_DETAILED)
  		m = 'D';
  	if (mode->flag & FB_MODE_IS_VESA)
  		m = 'V';
  	if (mode->flag & FB_MODE_IS_STANDARD)
  		m = 'S';
9dac73a4e   Daniel R Thompson   [PATCH] fbdev: ta...
109
110
111
112
113
114
115
116
117
  
  	if (mode->vmode & FB_VMODE_INTERLACED)
  		v = 'i';
  	if (mode->vmode & FB_VMODE_DOUBLE)
  		v = 'd';
  
  	return snprintf(&buf[offset], PAGE_SIZE - offset, "%c:%dx%d%c-%d
  ",
  	                m, mode->xres, mode->yres, v, mode->refresh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
119
120
  static ssize_t store_mode(struct device *device, struct device_attribute *attr,
  			  const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
122
  	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  	char mstr[100];
  	struct fb_var_screeninfo var;
  	struct fb_modelist *modelist;
  	struct fb_videomode *mode;
  	struct list_head *pos;
  	size_t i;
  	int err;
  
  	memset(&var, 0, sizeof(var));
  
  	list_for_each(pos, &fb_info->modelist) {
  		modelist = list_entry(pos, struct fb_modelist, list);
  		mode = &modelist->mode;
  		i = mode_string(mstr, 0, mode);
  		if (strncmp(mstr, buf, max(count, i)) == 0) {
  
  			var = fb_info->var;
  			fb_videomode_to_var(&var, mode);
  			if ((err = activate(fb_info, &var)))
  				return err;
  			fb_info->mode = mode;
  			return count;
  		}
  	}
  	return -EINVAL;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
149
150
  static ssize_t show_mode(struct device *device, struct device_attribute *attr,
  			 char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
152
  	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
157
158
  
  	if (!fb_info->mode)
  		return 0;
  
  	return mode_string(buf, 0, fb_info->mode);
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
159
160
161
  static ssize_t store_modes(struct device *device,
  			   struct device_attribute *attr,
  			   const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
163
  	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
168
  	LIST_HEAD(old_list);
  	int i = count / sizeof(struct fb_videomode);
  
  	if (i * sizeof(struct fb_videomode) != count)
  		return -EINVAL;
ac751efa6   Torben Hohn   console: rename a...
169
  	console_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  	list_splice(&fb_info->modelist, &old_list);
9791d763d   Geert Uytterhoeven   [PATCH] fbdev mod...
171
  	fb_videomode_to_modelist((const struct fb_videomode *)buf, i,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
175
176
177
  				 &fb_info->modelist);
  	if (fb_new_modelist(fb_info)) {
  		fb_destroy_modelist(&fb_info->modelist);
  		list_splice(&old_list, &fb_info->modelist);
  	} else
  		fb_destroy_modelist(&old_list);
ac751efa6   Torben Hohn   console: rename a...
178
  	console_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
  
  	return 0;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
182
183
  static ssize_t show_modes(struct device *device, struct device_attribute *attr,
  			  char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
185
  	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
190
191
192
193
194
195
196
197
198
  	unsigned int i;
  	struct list_head *pos;
  	struct fb_modelist *modelist;
  	const struct fb_videomode *mode;
  
  	i = 0;
  	list_for_each(pos, &fb_info->modelist) {
  		modelist = list_entry(pos, struct fb_modelist, list);
  		mode = &modelist->mode;
  		i += mode_string(buf, i, mode);
  	}
  	return i;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
199
200
  static ssize_t store_bpp(struct device *device, struct device_attribute *attr,
  			 const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
202
  	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
204
205
206
207
208
209
210
211
212
  	struct fb_var_screeninfo var;
  	char ** last = NULL;
  	int err;
  
  	var = fb_info->var;
  	var.bits_per_pixel = simple_strtoul(buf, last, 0);
  	if ((err = activate(fb_info, &var)))
  		return err;
  	return count;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
213
214
  static ssize_t show_bpp(struct device *device, struct device_attribute *attr,
  			char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
216
  	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
  	return snprintf(buf, PAGE_SIZE, "%d
  ", fb_info->var.bits_per_pixel);
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
220
221
222
  static ssize_t store_rotate(struct device *device,
  			    struct device_attribute *attr,
  			    const char *buf, size_t count)
a812c94b9   Antonino A. Daplas   [PATCH] fbcon: Co...
223
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
224
  	struct fb_info *fb_info = dev_get_drvdata(device);
a812c94b9   Antonino A. Daplas   [PATCH] fbcon: Co...
225
226
227
228
229
230
231
232
233
234
235
236
  	struct fb_var_screeninfo var;
  	char **last = NULL;
  	int err;
  
  	var = fb_info->var;
  	var.rotate = simple_strtoul(buf, last, 0);
  
  	if ((err = activate(fb_info, &var)))
  		return err;
  
  	return count;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
237
238
  static ssize_t show_rotate(struct device *device,
  			   struct device_attribute *attr, char *buf)
a812c94b9   Antonino A. Daplas   [PATCH] fbcon: Co...
239
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
240
  	struct fb_info *fb_info = dev_get_drvdata(device);
a812c94b9   Antonino A. Daplas   [PATCH] fbcon: Co...
241
242
243
244
  
  	return snprintf(buf, PAGE_SIZE, "%d
  ", fb_info->var.rotate);
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
245
246
247
  static ssize_t store_virtual(struct device *device,
  			     struct device_attribute *attr,
  			     const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
249
  	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
252
253
254
255
256
257
258
259
  	struct fb_var_screeninfo var;
  	char *last = NULL;
  	int err;
  
  	var = fb_info->var;
  	var.xres_virtual = simple_strtoul(buf, &last, 0);
  	last++;
  	if (last - buf >= count)
  		return -EINVAL;
  	var.yres_virtual = simple_strtoul(last, &last, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
262
263
264
  
  	if ((err = activate(fb_info, &var)))
  		return err;
  	return count;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
265
266
  static ssize_t show_virtual(struct device *device,
  			    struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
268
  	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
  	return snprintf(buf, PAGE_SIZE, "%d,%d
  ", fb_info->var.xres_virtual,
e2c164995   Jon Smirl   [PATCH] Typo in f...
271
  			fb_info->var.yres_virtual);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
273
274
  static ssize_t show_stride(struct device *device,
  			   struct device_attribute *attr, char *buf)
c14e2cfc1   James Simmons   [PATCH] Return th...
275
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
276
  	struct fb_info *fb_info = dev_get_drvdata(device);
c14e2cfc1   James Simmons   [PATCH] Return th...
277
278
279
  	return snprintf(buf, PAGE_SIZE, "%d
  ", fb_info->fix.line_length);
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
280
281
282
  static ssize_t store_blank(struct device *device,
  			   struct device_attribute *attr,
  			   const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
284
  	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
  	char *last = NULL;
  	int err;
ac751efa6   Torben Hohn   console: rename a...
287
  	console_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
290
  	fb_info->flags |= FBINFO_MISC_USEREVENT;
  	err = fb_blank(fb_info, simple_strtoul(buf, &last, 0));
  	fb_info->flags &= ~FBINFO_MISC_USEREVENT;
ac751efa6   Torben Hohn   console: rename a...
291
  	console_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
294
295
  	if (err < 0)
  		return err;
  	return count;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
296
297
  static ssize_t show_blank(struct device *device,
  			  struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
299
  //	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
301
  	return 0;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
302
303
304
  static ssize_t store_console(struct device *device,
  			     struct device_attribute *attr,
  			     const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
306
  //	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
  	return 0;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
309
310
  static ssize_t show_console(struct device *device,
  			    struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
312
  //	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
314
  	return 0;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
315
316
317
  static ssize_t store_cursor(struct device *device,
  			    struct device_attribute *attr,
  			    const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
319
  //	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
  	return 0;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
322
323
  static ssize_t show_cursor(struct device *device,
  			   struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
325
  //	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
327
  	return 0;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
328
329
330
  static ssize_t store_pan(struct device *device,
  			 struct device_attribute *attr,
  			 const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
332
  	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
334
335
336
337
338
339
340
341
342
  	struct fb_var_screeninfo var;
  	char *last = NULL;
  	int err;
  
  	var = fb_info->var;
  	var.xoffset = simple_strtoul(buf, &last, 0);
  	last++;
  	if (last - buf >= count)
  		return -EINVAL;
  	var.yoffset = simple_strtoul(last, &last, 0);
ac751efa6   Torben Hohn   console: rename a...
343
  	console_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  	err = fb_pan_display(fb_info, &var);
ac751efa6   Torben Hohn   console: rename a...
345
  	console_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
348
349
350
  
  	if (err < 0)
  		return err;
  	return count;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
351
352
  static ssize_t show_pan(struct device *device,
  			struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
354
  	struct fb_info *fb_info = dev_get_drvdata(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
356
  	return snprintf(buf, PAGE_SIZE, "%d,%d
  ", fb_info->var.xoffset,
c4270637f   Antonino A. Daplas   fbdev: fix obviou...
357
  			fb_info->var.yoffset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
359
360
  static ssize_t show_name(struct device *device,
  			 struct device_attribute *attr, char *buf)
02459eaab   James Simmons   [PATCH] Display n...
361
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
362
  	struct fb_info *fb_info = dev_get_drvdata(device);
02459eaab   James Simmons   [PATCH] Display n...
363
364
365
366
  
  	return snprintf(buf, PAGE_SIZE, "%s
  ", fb_info->fix.id);
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
367
368
369
  static ssize_t store_fbstate(struct device *device,
  			     struct device_attribute *attr,
  			     const char *buf, size_t count)
30420f8f4   Matthew Garrett   [PATCH] Add sysfs...
370
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
371
  	struct fb_info *fb_info = dev_get_drvdata(device);
30420f8f4   Matthew Garrett   [PATCH] Add sysfs...
372
373
374
375
  	u32 state;
  	char *last = NULL;
  
  	state = simple_strtoul(buf, &last, 0);
9e769ff3f   Herton Ronaldo Krzesinski   fb: avoid possibl...
376
377
  	if (!lock_fb_info(fb_info))
  		return -ENODEV;
ac751efa6   Torben Hohn   console: rename a...
378
  	console_lock();
30420f8f4   Matthew Garrett   [PATCH] Add sysfs...
379
  	fb_set_suspend(fb_info, (int)state);
ac751efa6   Torben Hohn   console: rename a...
380
  	console_unlock();
9e769ff3f   Herton Ronaldo Krzesinski   fb: avoid possibl...
381
  	unlock_fb_info(fb_info);
30420f8f4   Matthew Garrett   [PATCH] Add sysfs...
382
383
384
  
  	return count;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
385
386
  static ssize_t show_fbstate(struct device *device,
  			    struct device_attribute *attr, char *buf)
30420f8f4   Matthew Garrett   [PATCH] Add sysfs...
387
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
388
  	struct fb_info *fb_info = dev_get_drvdata(device);
30420f8f4   Matthew Garrett   [PATCH] Add sysfs...
389
390
391
  	return snprintf(buf, PAGE_SIZE, "%d
  ", fb_info->state);
  }
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
392
  #ifdef CONFIG_FB_BACKLIGHT
78cde0887   Greg Kroah-Hartman   Driver core: conv...
393
394
395
  static ssize_t store_bl_curve(struct device *device,
  			      struct device_attribute *attr,
  			      const char *buf, size_t count)
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
396
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
397
  	struct fb_info *fb_info = dev_get_drvdata(device);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
398
399
  	u8 tmp_curve[FB_BACKLIGHT_LEVELS];
  	unsigned int i;
25981de5b   Michael Hanselmann   [PATCH] backlight...
400
401
402
403
404
  	/* Some drivers don't use framebuffer_alloc(), but those also
  	 * don't have backlights.
  	 */
  	if (!fb_info || !fb_info->bl_dev)
  		return -ENODEV;
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
  	if (count != (FB_BACKLIGHT_LEVELS / 8 * 24))
  		return -EINVAL;
  
  	for (i = 0; i < (FB_BACKLIGHT_LEVELS / 8); ++i)
  		if (sscanf(&buf[i * 24],
  			"%2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx
  ",
  			&tmp_curve[i * 8 + 0],
  			&tmp_curve[i * 8 + 1],
  			&tmp_curve[i * 8 + 2],
  			&tmp_curve[i * 8 + 3],
  			&tmp_curve[i * 8 + 4],
  			&tmp_curve[i * 8 + 5],
  			&tmp_curve[i * 8 + 6],
  			&tmp_curve[i * 8 + 7]) != 8)
  			return -EINVAL;
  
  	/* If there has been an error in the input data, we won't
  	 * reach this loop.
  	 */
37ce69a57   Richard Purdie   backlight: Rework...
425
  	mutex_lock(&fb_info->bl_curve_mutex);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
426
427
  	for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i)
  		fb_info->bl_curve[i] = tmp_curve[i];
37ce69a57   Richard Purdie   backlight: Rework...
428
  	mutex_unlock(&fb_info->bl_curve_mutex);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
429
430
431
  
  	return count;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
432
433
  static ssize_t show_bl_curve(struct device *device,
  			     struct device_attribute *attr, char *buf)
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
434
  {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
435
  	struct fb_info *fb_info = dev_get_drvdata(device);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
436
437
  	ssize_t len = 0;
  	unsigned int i;
25981de5b   Michael Hanselmann   [PATCH] backlight...
438
439
440
441
442
  	/* Some drivers don't use framebuffer_alloc(), but those also
  	 * don't have backlights.
  	 */
  	if (!fb_info || !fb_info->bl_dev)
  		return -ENODEV;
37ce69a57   Richard Purdie   backlight: Rework...
443
  	mutex_lock(&fb_info->bl_curve_mutex);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
444
445
446
447
448
449
450
451
452
453
454
455
  	for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8)
  		len += snprintf(&buf[len], PAGE_SIZE,
  				"%02x %02x %02x %02x %02x %02x %02x %02x
  ",
  				fb_info->bl_curve[i + 0],
  				fb_info->bl_curve[i + 1],
  				fb_info->bl_curve[i + 2],
  				fb_info->bl_curve[i + 3],
  				fb_info->bl_curve[i + 4],
  				fb_info->bl_curve[i + 5],
  				fb_info->bl_curve[i + 6],
  				fb_info->bl_curve[i + 7]);
37ce69a57   Richard Purdie   backlight: Rework...
456
  	mutex_unlock(&fb_info->bl_curve_mutex);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
457
458
459
460
  
  	return len;
  }
  #endif
913e7ec54   Jon Smirl   [PATCH] Frame buf...
461
462
463
  /* When cmap is added back in it should be a binary attribute
   * not a text one. Consideration should also be given to converting
   * fbdev to use configfs instead of sysfs */
78cde0887   Greg Kroah-Hartman   Driver core: conv...
464
  static struct device_attribute device_attrs[] = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
  	__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
  	__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
468
469
470
471
472
  	__ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
  	__ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
  	__ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
  	__ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes),
  	__ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan),
  	__ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
02459eaab   James Simmons   [PATCH] Display n...
473
  	__ATTR(name, S_IRUGO, show_name, NULL),
c14e2cfc1   James Simmons   [PATCH] Return th...
474
  	__ATTR(stride, S_IRUGO, show_stride, NULL),
a812c94b9   Antonino A. Daplas   [PATCH] fbcon: Co...
475
  	__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
30420f8f4   Matthew Garrett   [PATCH] Add sysfs...
476
  	__ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
477
478
479
  #ifdef CONFIG_FB_BACKLIGHT
  	__ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve),
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
  };
78cde0887   Greg Kroah-Hartman   Driver core: conv...
481
  int fb_init_device(struct fb_info *fb_info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
  {
1a6600be3   Antonino A. Daplas   [PATCH] fbdev: Ho...
483
  	int i, error = 0;
78cde0887   Greg Kroah-Hartman   Driver core: conv...
484
  	dev_set_drvdata(fb_info->dev, fb_info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485

1a6600be3   Antonino A. Daplas   [PATCH] fbdev: Ho...
486
  	fb_info->class_flag |= FB_SYSFS_FLAG_ATTR;
78cde0887   Greg Kroah-Hartman   Driver core: conv...
487
488
  	for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
  		error = device_create_file(fb_info->dev, &device_attrs[i]);
1a6600be3   Antonino A. Daplas   [PATCH] fbdev: Ho...
489
490
491
492
493
494
495
  
  		if (error)
  			break;
  	}
  
  	if (error) {
  		while (--i >= 0)
78cde0887   Greg Kroah-Hartman   Driver core: conv...
496
  			device_remove_file(fb_info->dev, &device_attrs[i]);
1a6600be3   Antonino A. Daplas   [PATCH] fbdev: Ho...
497
498
  		fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
500
  	return 0;
  }
78cde0887   Greg Kroah-Hartman   Driver core: conv...
501
  void fb_cleanup_device(struct fb_info *fb_info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
  {
  	unsigned int i;
1a6600be3   Antonino A. Daplas   [PATCH] fbdev: Ho...
504
  	if (fb_info->class_flag & FB_SYSFS_FLAG_ATTR) {
78cde0887   Greg Kroah-Hartman   Driver core: conv...
505
506
  		for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
  			device_remove_file(fb_info->dev, &device_attrs[i]);
1a6600be3   Antonino A. Daplas   [PATCH] fbdev: Ho...
507
508
509
  
  		fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
  }
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
511
512
513
514
515
516
517
518
519
520
  #ifdef CONFIG_FB_BACKLIGHT
  /* This function generates a linear backlight curve
   *
   *     0: off
   *   1-7: min
   * 8-127: linear from min to max
   */
  void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
  {
  	unsigned int i, flat, count, range = (max - min);
37ce69a57   Richard Purdie   backlight: Rework...
521
  	mutex_lock(&fb_info->bl_curve_mutex);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
522
  	fb_info->bl_curve[0] = off;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523

5474c120a   Michael Hanselmann   [PATCH] Rewritten...
524
525
526
527
528
529
  	for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
  		fb_info->bl_curve[flat] = min;
  
  	count = FB_BACKLIGHT_LEVELS * 15 / 16;
  	for (i = 0; i < count; ++i)
  		fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count);
37ce69a57   Richard Purdie   backlight: Rework...
530
531
  
  	mutex_unlock(&fb_info->bl_curve_mutex);
5474c120a   Michael Hanselmann   [PATCH] Rewritten...
532
533
534
  }
  EXPORT_SYMBOL_GPL(fb_bl_default_curve);
  #endif