Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.12 214 lines 4.8 kB view raw
1#include "fbtft.h" 2#include "internal.h" 3 4static int get_next_ulong(char **str_p, unsigned long *val, char *sep, int base) 5{ 6 char *p_val; 7 8 if (!str_p || !(*str_p)) 9 return -EINVAL; 10 11 p_val = strsep(str_p, sep); 12 13 if (!p_val) 14 return -EINVAL; 15 16 return kstrtoul(p_val, base, val); 17} 18 19int fbtft_gamma_parse_str(struct fbtft_par *par, u32 *curves, 20 const char *str, int size) 21{ 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; 27 28 fbtft_par_dbg(DEBUG_SYSFS, par, "%s() str=\n", __func__); 29 30 if (!str || !curves) 31 return -EINVAL; 32 33 fbtft_par_dbg(DEBUG_SYSFS, par, "%s\n", str); 34 35 tmp = kmemdup(str, size + 1, GFP_KERNEL); 36 if (!tmp) 37 return -ENOMEM; 38 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++; 47 } 48 49 str_p = strim(tmp); 50 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; 57 } 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; 66 } 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++; 72 } 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; 77 } 78 curve_counter++; 79 } 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; 84 } 85 86out: 87 kfree(tmp); 88 return ret; 89} 90 91static ssize_t 92sprintf_gamma(struct fbtft_par *par, u32 *curves, char *buf) 93{ 94 ssize_t len = 0; 95 unsigned int i, j; 96 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'; 103 } 104 mutex_unlock(&par->gamma.lock); 105 106 return len; 107} 108 109static ssize_t store_gamma_curve(struct device *device, 110 struct device_attribute *attr, 111 const char *buf, size_t count) 112{ 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; 117 118 ret = fbtft_gamma_parse_str(par, tmp_curves, buf, count); 119 if (ret) 120 return ret; 121 122 ret = par->fbtftops.set_gamma(par, tmp_curves); 123 if (ret) 124 return ret; 125 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); 130 131 return count; 132} 133 134static ssize_t show_gamma_curve(struct device *device, 135 struct device_attribute *attr, char *buf) 136{ 137 struct fb_info *fb_info = dev_get_drvdata(device); 138 struct fbtft_par *par = fb_info->par; 139 140 return sprintf_gamma(par, par->gamma.curves, buf); 141} 142 143static struct device_attribute gamma_device_attrs[] = { 144 __ATTR(gamma, 0660, show_gamma_curve, store_gamma_curve), 145}; 146 147void fbtft_expand_debug_value(unsigned long *debug) 148{ 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; 171 } 172} 173 174static ssize_t store_debug(struct device *device, 175 struct device_attribute *attr, 176 const char *buf, size_t count) 177{ 178 struct fb_info *fb_info = dev_get_drvdata(device); 179 struct fbtft_par *par = fb_info->par; 180 int ret; 181 182 ret = kstrtoul(buf, 10, &par->debug); 183 if (ret) 184 return ret; 185 fbtft_expand_debug_value(&par->debug); 186 187 return count; 188} 189 190static ssize_t show_debug(struct device *device, 191 struct device_attribute *attr, char *buf) 192{ 193 struct fb_info *fb_info = dev_get_drvdata(device); 194 struct fbtft_par *par = fb_info->par; 195 196 return snprintf(buf, PAGE_SIZE, "%lu\n", par->debug); 197} 198 199static struct device_attribute debug_device_attr = 200 __ATTR(debug, 0660, show_debug, store_debug); 201 202void fbtft_sysfs_init(struct fbtft_par *par) 203{ 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]); 207} 208 209void fbtft_sysfs_exit(struct fbtft_par *par) 210{ 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]); 214}