aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbsysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbsysfs.c')
-rw-r--r--drivers/video/fbsysfs.c90
1 files changed, 80 insertions, 10 deletions
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index ddc9443254d9..1147b899f007 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -242,10 +242,68 @@ static ssize_t show_virtual(struct class_device *class_device, char *buf)
242 fb_info->var.yres_virtual); 242 fb_info->var.yres_virtual);
243} 243}
244 244
245static ssize_t store_cmap(struct class_device *class_device, const char * buf, 245/* Format for cmap is "%02x%c%4x%4x%4x\n" */
246/* %02x entry %c transp %4x red %4x blue %4x green \n */
247/* 256 rows at 16 chars equals 4096, the normal page size */
248/* the code will automatically adjust for different page sizes */
249static ssize_t store_cmap(struct class_device *class_device, const char *buf,
246 size_t count) 250 size_t count)
247{ 251{
248// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); 252 struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
253 int rc, i, start, length, transp = 0;
254
255 if ((count > PAGE_SIZE) || ((count % 16) != 0))
256 return -EINVAL;
257
258 if (!fb_info->fbops->fb_setcolreg && !fb_info->fbops->fb_setcmap)
259 return -EINVAL;
260
261 sscanf(buf, "%02x", &start);
262 length = count / 16;
263
264 for (i = 0; i < length; i++)
265 if (buf[i * 16 + 2] != ' ')
266 transp = 1;
267
268 /* If we can batch, do it */
269 if (fb_info->fbops->fb_setcmap && length > 1) {
270 struct fb_cmap umap;
271
272 memset(&umap, 0, sizeof(umap));
273 if ((rc = fb_alloc_cmap(&umap, length, transp)))
274 return rc;
275
276 umap.start = start;
277 for (i = 0; i < length; i++) {
278 sscanf(&buf[i * 16 + 3], "%4hx", &umap.red[i]);
279 sscanf(&buf[i * 16 + 7], "%4hx", &umap.blue[i]);
280 sscanf(&buf[i * 16 + 11], "%4hx", &umap.green[i]);
281 if (transp)
282 umap.transp[i] = (buf[i * 16 + 2] != ' ');
283 }
284 rc = fb_info->fbops->fb_setcmap(&umap, fb_info);
285 fb_copy_cmap(&umap, &fb_info->cmap);
286 fb_dealloc_cmap(&umap);
287
288 return rc;
289 }
290 for (i = 0; i < length; i++) {
291 u16 red, blue, green, tsp;
292
293 sscanf(&buf[i * 16 + 3], "%4hx", &red);
294 sscanf(&buf[i * 16 + 7], "%4hx", &blue);
295 sscanf(&buf[i * 16 + 11], "%4hx", &green);
296 tsp = (buf[i * 16 + 2] != ' ');
297 if ((rc = fb_info->fbops->fb_setcolreg(start++,
298 red, green, blue, tsp, fb_info)))
299 return rc;
300
301 fb_info->cmap.red[i] = red;
302 fb_info->cmap.blue[i] = blue;
303 fb_info->cmap.green[i] = green;
304 if (transp)
305 fb_info->cmap.transp[i] = tsp;
306 }
249 return 0; 307 return 0;
250} 308}
251 309
@@ -253,20 +311,24 @@ static ssize_t show_cmap(struct class_device *class_device, char *buf)
253{ 311{
254 struct fb_info *fb_info = 312 struct fb_info *fb_info =
255 (struct fb_info *)class_get_devdata(class_device); 313 (struct fb_info *)class_get_devdata(class_device);
256 unsigned int offset = 0, i; 314 unsigned int i;
257 315
258 if (!fb_info->cmap.red || !fb_info->cmap.blue || 316 if (!fb_info->cmap.red || !fb_info->cmap.blue ||
259 !fb_info->cmap.green || !fb_info->cmap.transp) 317 !fb_info->cmap.green)
318 return -EINVAL;
319
320 if (fb_info->cmap.len > PAGE_SIZE / 16)
260 return -EINVAL; 321 return -EINVAL;
261 322
323 /* don't mess with the format, the buffer is PAGE_SIZE */
324 /* 256 entries at 16 chars per line equals 4096 = PAGE_SIZE */
262 for (i = 0; i < fb_info->cmap.len; i++) { 325 for (i = 0; i < fb_info->cmap.len; i++) {
263 offset += snprintf(buf, PAGE_SIZE - offset, 326 snprintf(&buf[ i * 16], PAGE_SIZE - i * 16, "%02x%c%4x%4x%4x\n", i + fb_info->cmap.start,
264 "%d,%d,%d,%d,%d\n", i + fb_info->cmap.start, 327 ((fb_info->cmap.transp && fb_info->cmap.transp[i]) ? '*' : ' '),
265 fb_info->cmap.red[i], fb_info->cmap.blue[i], 328 fb_info->cmap.red[i], fb_info->cmap.blue[i],
266 fb_info->cmap.green[i], 329 fb_info->cmap.green[i]);
267 fb_info->cmap.transp[i]);
268 } 330 }
269 return offset; 331 return 16 * fb_info->cmap.len;
270} 332}
271 333
272static ssize_t store_blank(struct class_device *class_device, const char * buf, 334static ssize_t store_blank(struct class_device *class_device, const char * buf,
@@ -352,6 +414,13 @@ static ssize_t show_pan(struct class_device *class_device, char *buf)
352 fb_info->var.xoffset); 414 fb_info->var.xoffset);
353} 415}
354 416
417static ssize_t show_name(struct class_device *class_device, char *buf)
418{
419 struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
420
421 return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id);
422}
423
355static struct class_device_attribute class_device_attrs[] = { 424static struct class_device_attribute class_device_attrs[] = {
356 __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), 425 __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
357 __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), 426 __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
@@ -362,6 +431,7 @@ static struct class_device_attribute class_device_attrs[] = {
362 __ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes), 431 __ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes),
363 __ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan), 432 __ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan),
364 __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), 433 __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
434 __ATTR(name, S_IRUGO, show_name, NULL),
365}; 435};
366 436
367int fb_init_class_device(struct fb_info *fb_info) 437int fb_init_class_device(struct fb_info *fb_info)