cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fbtft-sysfs.c (4844B)


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