eeepc-laptop: cpufv updates

Limit cpufv input to acceptables values.
Add an available_cpufv file to show available
presets.
Change cpufv ouput format from %d to %#x, it won't
break compatibility with existing userspace tools, but
it provide a more human readable output.

Signed-off-by: Corentin Chary <corentincj@iksaif.net>
Signed-off-by: Len Brown <len.brown@intel.com>

authored by Corentin Chary and committed by Len Brown b31d0fde b7b700d4

+76 -1
+76 -1
drivers/platform/x86/eeepc-laptop.c
··· 392 392 EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); 393 393 EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); 394 394 EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); 395 - EEEPC_CREATE_DEVICE_ATTR(cpufv, CM_ASL_CPUFV); 395 + 396 + struct eeepc_cpufv { 397 + int num; 398 + int cur; 399 + }; 400 + 401 + static int get_cpufv(struct eeepc_cpufv *c) 402 + { 403 + c->cur = get_acpi(CM_ASL_CPUFV); 404 + c->num = (c->cur >> 8) & 0xff; 405 + c->cur &= 0xff; 406 + if (c->cur < 0 || c->num <= 0 || c->num > 12) 407 + return -ENODEV; 408 + return 0; 409 + } 410 + 411 + static ssize_t show_available_cpufv(struct device *dev, 412 + struct device_attribute *attr, 413 + char *buf) 414 + { 415 + struct eeepc_cpufv c; 416 + int i; 417 + ssize_t len = 0; 418 + 419 + if (get_cpufv(&c)) 420 + return -ENODEV; 421 + for (i = 0; i < c.num; i++) 422 + len += sprintf(buf + len, "%d ", i); 423 + len += sprintf(buf + len, "\n"); 424 + return len; 425 + } 426 + 427 + static ssize_t show_cpufv(struct device *dev, 428 + struct device_attribute *attr, 429 + char *buf) 430 + { 431 + struct eeepc_cpufv c; 432 + 433 + if (get_cpufv(&c)) 434 + return -ENODEV; 435 + return sprintf(buf, "%#x\n", (c.num << 8) | c.cur); 436 + } 437 + 438 + static ssize_t store_cpufv(struct device *dev, 439 + struct device_attribute *attr, 440 + const char *buf, size_t count) 441 + { 442 + struct eeepc_cpufv c; 443 + int rv, value; 444 + 445 + if (get_cpufv(&c)) 446 + return -ENODEV; 447 + rv = parse_arg(buf, count, &value); 448 + if (rv < 0) 449 + return rv; 450 + if (!rv || value < 0 || value >= c.num) 451 + return -EINVAL; 452 + set_acpi(CM_ASL_CPUFV, value); 453 + return rv; 454 + } 455 + 456 + static struct device_attribute dev_attr_cpufv = { 457 + .attr = { 458 + .name = "cpufv", 459 + .mode = 0644 }, 460 + .show = show_cpufv, 461 + .store = store_cpufv 462 + }; 463 + 464 + static struct device_attribute dev_attr_available_cpufv = { 465 + .attr = { 466 + .name = "available_cpufv", 467 + .mode = 0444 }, 468 + .show = show_available_cpufv 469 + }; 396 470 397 471 static struct attribute *platform_attributes[] = { 398 472 &dev_attr_camera.attr, 399 473 &dev_attr_cardr.attr, 400 474 &dev_attr_disp.attr, 401 475 &dev_attr_cpufv.attr, 476 + &dev_attr_available_cpufv.attr, 402 477 NULL 403 478 }; 404 479