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