root/drivers/staging/fbtft/fbtft-sysfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_next_ulong
  2. fbtft_gamma_parse_str
  3. sprintf_gamma
  4. store_gamma_curve
  5. show_gamma_curve
  6. fbtft_expand_debug_value
  7. store_debug
  8. show_debug
  9. fbtft_sysfs_init
  10. fbtft_sysfs_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include "fbtft.h"
   3 #include "internal.h"
   4 
   5 static int get_next_ulong(char **str_p, unsigned long *val, char *sep, int base)
   6 {
   7         char *p_val;
   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         return kstrtoul(p_val, base, val);
  18 }
  19 
  20 int fbtft_gamma_parse_str(struct fbtft_par *par, u32 *curves,
  21                           const char *str, int size)
  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 
  36         tmp = kmemdup(str, size + 1, GFP_KERNEL);
  37         if (!tmp)
  38                 return -ENOMEM;
  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 
  87 out:
  88         kfree(tmp);
  89         return ret;
  90 }
  91 
  92 static ssize_t
  93 sprintf_gamma(struct fbtft_par *par, u32 *curves, char *buf)
  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,
 102                              "%04x ", curves[i * par->gamma.num_values + j]);
 103                 buf[len - 1] = '\n';
 104         }
 105         mutex_unlock(&par->gamma.lock);
 106 
 107         return len;
 108 }
 109 
 110 static ssize_t store_gamma_curve(struct device *device,
 111                                  struct device_attribute *attr,
 112                                  const char *buf, size_t count)
 113 {
 114         struct fb_info *fb_info = dev_get_drvdata(device);
 115         struct fbtft_par *par = fb_info->par;
 116         u32 tmp_curves[FBTFT_GAMMA_MAX_VALUES_TOTAL];
 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,
 129                par->gamma.num_curves * par->gamma.num_values *
 130                sizeof(tmp_curves[0]));
 131         mutex_unlock(&par->gamma.lock);
 132 
 133         return count;
 134 }
 135 
 136 static ssize_t show_gamma_curve(struct device *device,
 137                                 struct device_attribute *attr, char *buf)
 138 {
 139         struct fb_info *fb_info = dev_get_drvdata(device);
 140         struct fbtft_par *par = fb_info->par;
 141 
 142         return sprintf_gamma(par, par->gamma.curves, buf);
 143 }
 144 
 145 static struct device_attribute gamma_device_attrs[] = {
 146         __ATTR(gamma, 0660, show_gamma_curve, store_gamma_curve),
 147 };
 148 
 149 void fbtft_expand_debug_value(unsigned long *debug)
 150 {
 151         switch (*debug & 0x7) {
 152         case 1:
 153                 *debug |= DEBUG_LEVEL_1;
 154                 break;
 155         case 2:
 156                 *debug |= DEBUG_LEVEL_2;
 157                 break;
 158         case 3:
 159                 *debug |= DEBUG_LEVEL_3;
 160                 break;
 161         case 4:
 162                 *debug |= DEBUG_LEVEL_4;
 163                 break;
 164         case 5:
 165                 *debug |= DEBUG_LEVEL_5;
 166                 break;
 167         case 6:
 168                 *debug |= DEBUG_LEVEL_6;
 169                 break;
 170         case 7:
 171                 *debug = 0xFFFFFFFF;
 172                 break;
 173         }
 174 }
 175 
 176 static ssize_t store_debug(struct device *device,
 177                            struct device_attribute *attr,
 178                            const char *buf, size_t count)
 179 {
 180         struct fb_info *fb_info = dev_get_drvdata(device);
 181         struct fbtft_par *par = fb_info->par;
 182         int ret;
 183 
 184         ret = kstrtoul(buf, 10, &par->debug);
 185         if (ret)
 186                 return ret;
 187         fbtft_expand_debug_value(&par->debug);
 188 
 189         return count;
 190 }
 191 
 192 static ssize_t show_debug(struct device *device,
 193                           struct device_attribute *attr, char *buf)
 194 {
 195         struct fb_info *fb_info = dev_get_drvdata(device);
 196         struct fbtft_par *par = fb_info->par;
 197 
 198         return snprintf(buf, PAGE_SIZE, "%lu\n", par->debug);
 199 }
 200 
 201 static struct device_attribute debug_device_attr =
 202         __ATTR(debug, 0660, show_debug, store_debug);
 203 
 204 void fbtft_sysfs_init(struct fbtft_par *par)
 205 {
 206         device_create_file(par->info->dev, &debug_device_attr);
 207         if (par->gamma.curves && par->fbtftops.set_gamma)
 208                 device_create_file(par->info->dev, &gamma_device_attrs[0]);
 209 }
 210 
 211 void fbtft_sysfs_exit(struct fbtft_par *par)
 212 {
 213         device_remove_file(par->info->dev, &debug_device_attr);
 214         if (par->gamma.curves && par->fbtftops.set_gamma)
 215                 device_remove_file(par->info->dev, &gamma_device_attrs[0]);
 216 }

/* [<][>][^][v][top][bottom][index][help] */