diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/fbsysfs.c | 82 |
1 files changed, 72 insertions, 10 deletions
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index ddc9443254d9..63b505cce4ec 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 | ||
245 | static 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 | /* 255 rows at 16 chars equals 4096 */ | ||
248 | /* PAGE_SIZE can be 4096 or larger */ | ||
249 | static 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 > 4096) || ((count % 16) != 0) || (PAGE_SIZE < 4096)) | ||
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 (PAGE_SIZE < 4096) | ||
260 | return -EINVAL; | 321 | return -EINVAL; |
261 | 322 | ||
323 | /* don't mess with the format, the buffer is PAGE_SIZE */ | ||
324 | /* 255 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 | sprintf(&buf[ 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 4096; |
270 | } | 332 | } |
271 | 333 | ||
272 | static ssize_t store_blank(struct class_device *class_device, const char * buf, | 334 | static ssize_t store_blank(struct class_device *class_device, const char * buf, |