IB/uverbs: Fix device cleanup
[linux/fpc-iii.git] / drivers / staging / fbtft / fbtft-sysfs.c
blob5bfd67b526b57d6188fe41b86d352e3544deee6d
1 #include "fbtft.h"
2 #include "internal.h"
4 static int get_next_ulong(char **str_p, unsigned long *val, char *sep, int base)
6 char *p_val;
8 if (!str_p || !(*str_p))
9 return -EINVAL;
11 p_val = strsep(str_p, sep);
13 if (!p_val)
14 return -EINVAL;
16 return kstrtoul(p_val, base, val);
19 int fbtft_gamma_parse_str(struct fbtft_par *par, u32 *curves,
20 const char *str, int size)
22 char *str_p, *curve_p = NULL;
23 char *tmp;
24 unsigned long val = 0;
25 int ret = 0;
26 int curve_counter, value_counter;
28 fbtft_par_dbg(DEBUG_SYSFS, par, "%s() str=\n", __func__);
30 if (!str || !curves)
31 return -EINVAL;
33 fbtft_par_dbg(DEBUG_SYSFS, par, "%s\n", str);
35 tmp = kmemdup(str, size + 1, GFP_KERNEL);
36 if (!tmp)
37 return -ENOMEM;
39 /* replace optional separators */
40 str_p = tmp;
41 while (*str_p) {
42 if (*str_p == ',')
43 *str_p = ' ';
44 if (*str_p == ';')
45 *str_p = '\n';
46 str_p++;
49 str_p = strim(tmp);
51 curve_counter = 0;
52 while (str_p) {
53 if (curve_counter == par->gamma.num_curves) {
54 dev_err(par->info->device, "Gamma: Too many curves\n");
55 ret = -EINVAL;
56 goto out;
58 curve_p = strsep(&str_p, "\n");
59 value_counter = 0;
60 while (curve_p) {
61 if (value_counter == par->gamma.num_values) {
62 dev_err(par->info->device,
63 "Gamma: Too many values\n");
64 ret = -EINVAL;
65 goto out;
67 ret = get_next_ulong(&curve_p, &val, " ", 16);
68 if (ret)
69 goto out;
70 curves[curve_counter * par->gamma.num_values + value_counter] = val;
71 value_counter++;
73 if (value_counter != par->gamma.num_values) {
74 dev_err(par->info->device, "Gamma: Too few values\n");
75 ret = -EINVAL;
76 goto out;
78 curve_counter++;
80 if (curve_counter != par->gamma.num_curves) {
81 dev_err(par->info->device, "Gamma: Too few curves\n");
82 ret = -EINVAL;
83 goto out;
86 out:
87 kfree(tmp);
88 return ret;
91 static ssize_t
92 sprintf_gamma(struct fbtft_par *par, u32 *curves, char *buf)
94 ssize_t len = 0;
95 unsigned int i, j;
97 mutex_lock(&par->gamma.lock);
98 for (i = 0; i < par->gamma.num_curves; i++) {
99 for (j = 0; j < par->gamma.num_values; j++)
100 len += scnprintf(&buf[len], PAGE_SIZE,
101 "%04x ", curves[i * par->gamma.num_values + j]);
102 buf[len - 1] = '\n';
104 mutex_unlock(&par->gamma.lock);
106 return len;
109 static ssize_t store_gamma_curve(struct device *device,
110 struct device_attribute *attr,
111 const char *buf, size_t count)
113 struct fb_info *fb_info = dev_get_drvdata(device);
114 struct fbtft_par *par = fb_info->par;
115 u32 tmp_curves[FBTFT_GAMMA_MAX_VALUES_TOTAL];
116 int ret;
118 ret = fbtft_gamma_parse_str(par, tmp_curves, buf, count);
119 if (ret)
120 return ret;
122 ret = par->fbtftops.set_gamma(par, tmp_curves);
123 if (ret)
124 return ret;
126 mutex_lock(&par->gamma.lock);
127 memcpy(par->gamma.curves, tmp_curves,
128 par->gamma.num_curves * par->gamma.num_values * sizeof(tmp_curves[0]));
129 mutex_unlock(&par->gamma.lock);
131 return count;
134 static ssize_t show_gamma_curve(struct device *device,
135 struct device_attribute *attr, char *buf)
137 struct fb_info *fb_info = dev_get_drvdata(device);
138 struct fbtft_par *par = fb_info->par;
140 return sprintf_gamma(par, par->gamma.curves, buf);
143 static struct device_attribute gamma_device_attrs[] = {
144 __ATTR(gamma, 0660, show_gamma_curve, store_gamma_curve),
147 void fbtft_expand_debug_value(unsigned long *debug)
149 switch (*debug & 0x7) {
150 case 1:
151 *debug |= DEBUG_LEVEL_1;
152 break;
153 case 2:
154 *debug |= DEBUG_LEVEL_2;
155 break;
156 case 3:
157 *debug |= DEBUG_LEVEL_3;
158 break;
159 case 4:
160 *debug |= DEBUG_LEVEL_4;
161 break;
162 case 5:
163 *debug |= DEBUG_LEVEL_5;
164 break;
165 case 6:
166 *debug |= DEBUG_LEVEL_6;
167 break;
168 case 7:
169 *debug = 0xFFFFFFFF;
170 break;
174 static ssize_t store_debug(struct device *device,
175 struct device_attribute *attr,
176 const char *buf, size_t count)
178 struct fb_info *fb_info = dev_get_drvdata(device);
179 struct fbtft_par *par = fb_info->par;
180 int ret;
182 ret = kstrtoul(buf, 10, &par->debug);
183 if (ret)
184 return ret;
185 fbtft_expand_debug_value(&par->debug);
187 return count;
190 static ssize_t show_debug(struct device *device,
191 struct device_attribute *attr, char *buf)
193 struct fb_info *fb_info = dev_get_drvdata(device);
194 struct fbtft_par *par = fb_info->par;
196 return snprintf(buf, PAGE_SIZE, "%lu\n", par->debug);
199 static struct device_attribute debug_device_attr =
200 __ATTR(debug, 0660, show_debug, store_debug);
202 void fbtft_sysfs_init(struct fbtft_par *par)
204 device_create_file(par->info->dev, &debug_device_attr);
205 if (par->gamma.curves && par->fbtftops.set_gamma)
206 device_create_file(par->info->dev, &gamma_device_attrs[0]);
209 void fbtft_sysfs_exit(struct fbtft_par *par)
211 device_remove_file(par->info->dev, &debug_device_attr);
212 if (par->gamma.curves && par->fbtftops.set_gamma)
213 device_remove_file(par->info->dev, &gamma_device_attrs[0]);