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