fbtft-sysfs.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include "fbtft.h"
  2. #include "internal.h"
  3. static int get_next_ulong(char **str_p, unsigned long *val, char *sep, int base)
  4. {
  5. char *p_val;
  6. int ret;
  7. if (!str_p || !(*str_p))
  8. return -EINVAL;
  9. p_val = strsep(str_p, sep);
  10. if (!p_val)
  11. return -EINVAL;
  12. ret = kstrtoul(p_val, base, val);
  13. if (ret)
  14. return -EINVAL;
  15. return 0;
  16. }
  17. int fbtft_gamma_parse_str(struct fbtft_par *par, unsigned long *curves,
  18. const char *str, int size)
  19. {
  20. char *str_p, *curve_p = NULL;
  21. char *tmp;
  22. unsigned long val = 0;
  23. int ret = 0;
  24. int curve_counter, value_counter;
  25. fbtft_par_dbg(DEBUG_SYSFS, par, "%s() str=\n", __func__);
  26. if (!str || !curves)
  27. return -EINVAL;
  28. fbtft_par_dbg(DEBUG_SYSFS, par, "%s\n", str);
  29. tmp = kmemdup(str, size + 1, GFP_KERNEL);
  30. if (!tmp)
  31. return -ENOMEM;
  32. /* replace optional separators */
  33. str_p = tmp;
  34. while (*str_p) {
  35. if (*str_p == ',')
  36. *str_p = ' ';
  37. if (*str_p == ';')
  38. *str_p = '\n';
  39. str_p++;
  40. }
  41. str_p = strim(tmp);
  42. curve_counter = 0;
  43. while (str_p) {
  44. if (curve_counter == par->gamma.num_curves) {
  45. dev_err(par->info->device, "Gamma: Too many curves\n");
  46. ret = -EINVAL;
  47. goto out;
  48. }
  49. curve_p = strsep(&str_p, "\n");
  50. value_counter = 0;
  51. while (curve_p) {
  52. if (value_counter == par->gamma.num_values) {
  53. dev_err(par->info->device,
  54. "Gamma: Too many values\n");
  55. ret = -EINVAL;
  56. goto out;
  57. }
  58. ret = get_next_ulong(&curve_p, &val, " ", 16);
  59. if (ret)
  60. goto out;
  61. curves[curve_counter * par->gamma.num_values + value_counter] = val;
  62. value_counter++;
  63. }
  64. if (value_counter != par->gamma.num_values) {
  65. dev_err(par->info->device, "Gamma: Too few values\n");
  66. ret = -EINVAL;
  67. goto out;
  68. }
  69. curve_counter++;
  70. }
  71. if (curve_counter != par->gamma.num_curves) {
  72. dev_err(par->info->device, "Gamma: Too few curves\n");
  73. ret = -EINVAL;
  74. goto out;
  75. }
  76. out:
  77. kfree(tmp);
  78. return ret;
  79. }
  80. static ssize_t
  81. sprintf_gamma(struct fbtft_par *par, unsigned long *curves, char *buf)
  82. {
  83. ssize_t len = 0;
  84. unsigned int i, j;
  85. mutex_lock(&par->gamma.lock);
  86. for (i = 0; i < par->gamma.num_curves; i++) {
  87. for (j = 0; j < par->gamma.num_values; j++)
  88. len += scnprintf(&buf[len], PAGE_SIZE,
  89. "%04lx ", curves[i*par->gamma.num_values + j]);
  90. buf[len-1] = '\n';
  91. }
  92. mutex_unlock(&par->gamma.lock);
  93. return len;
  94. }
  95. static ssize_t store_gamma_curve(struct device *device,
  96. struct device_attribute *attr,
  97. const char *buf, size_t count)
  98. {
  99. struct fb_info *fb_info = dev_get_drvdata(device);
  100. struct fbtft_par *par = fb_info->par;
  101. unsigned long tmp_curves[FBTFT_GAMMA_MAX_VALUES_TOTAL];
  102. int ret;
  103. ret = fbtft_gamma_parse_str(par, tmp_curves, buf, count);
  104. if (ret)
  105. return ret;
  106. ret = par->fbtftops.set_gamma(par, tmp_curves);
  107. if (ret)
  108. return ret;
  109. mutex_lock(&par->gamma.lock);
  110. memcpy(par->gamma.curves, tmp_curves,
  111. par->gamma.num_curves * par->gamma.num_values * sizeof(tmp_curves[0]));
  112. mutex_unlock(&par->gamma.lock);
  113. return count;
  114. }
  115. static ssize_t show_gamma_curve(struct device *device,
  116. struct device_attribute *attr, char *buf)
  117. {
  118. struct fb_info *fb_info = dev_get_drvdata(device);
  119. struct fbtft_par *par = fb_info->par;
  120. return sprintf_gamma(par, par->gamma.curves, buf);
  121. }
  122. static struct device_attribute gamma_device_attrs[] = {
  123. __ATTR(gamma, 0660, show_gamma_curve, store_gamma_curve),
  124. };
  125. void fbtft_expand_debug_value(unsigned long *debug)
  126. {
  127. switch (*debug & 0x7) {
  128. case 1:
  129. *debug |= DEBUG_LEVEL_1;
  130. break;
  131. case 2:
  132. *debug |= DEBUG_LEVEL_2;
  133. break;
  134. case 3:
  135. *debug |= DEBUG_LEVEL_3;
  136. break;
  137. case 4:
  138. *debug |= DEBUG_LEVEL_4;
  139. break;
  140. case 5:
  141. *debug |= DEBUG_LEVEL_5;
  142. break;
  143. case 6:
  144. *debug |= DEBUG_LEVEL_6;
  145. break;
  146. case 7:
  147. *debug = 0xFFFFFFFF;
  148. break;
  149. }
  150. }
  151. static ssize_t store_debug(struct device *device,
  152. struct device_attribute *attr,
  153. const char *buf, size_t count)
  154. {
  155. struct fb_info *fb_info = dev_get_drvdata(device);
  156. struct fbtft_par *par = fb_info->par;
  157. int ret;
  158. ret = kstrtoul(buf, 10, &par->debug);
  159. if (ret)
  160. return ret;
  161. fbtft_expand_debug_value(&par->debug);
  162. return count;
  163. }
  164. static ssize_t show_debug(struct device *device,
  165. struct device_attribute *attr, char *buf)
  166. {
  167. struct fb_info *fb_info = dev_get_drvdata(device);
  168. struct fbtft_par *par = fb_info->par;
  169. return snprintf(buf, PAGE_SIZE, "%lu\n", par->debug);
  170. }
  171. static struct device_attribute debug_device_attr = \
  172. __ATTR(debug, 0660, show_debug, store_debug);
  173. void fbtft_sysfs_init(struct fbtft_par *par)
  174. {
  175. device_create_file(par->info->dev, &debug_device_attr);
  176. if (par->gamma.curves && par->fbtftops.set_gamma)
  177. device_create_file(par->info->dev, &gamma_device_attrs[0]);
  178. }
  179. void fbtft_sysfs_exit(struct fbtft_par *par)
  180. {
  181. device_remove_file(par->info->dev, &debug_device_attr);
  182. if (par->gamma.curves && par->fbtftops.set_gamma)
  183. device_remove_file(par->info->dev, &gamma_device_attrs[0]);
  184. }