diff options
| -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, | 
