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

led-class-multicolor.c (5118B)


      1// SPDX-License-Identifier: GPL-2.0
      2// LED Multicolor class interface
      3// Copyright (C) 2019-20 Texas Instruments Incorporated - http://www.ti.com/
      4// Author: Dan Murphy <dmurphy@ti.com>
      5
      6#include <linux/device.h>
      7#include <linux/init.h>
      8#include <linux/led-class-multicolor.h>
      9#include <linux/module.h>
     10#include <linux/slab.h>
     11#include <linux/uaccess.h>
     12
     13#include "leds.h"
     14
     15int led_mc_calc_color_components(struct led_classdev_mc *mcled_cdev,
     16				 enum led_brightness brightness)
     17{
     18	struct led_classdev *led_cdev = &mcled_cdev->led_cdev;
     19	int i;
     20
     21	for (i = 0; i < mcled_cdev->num_colors; i++)
     22		mcled_cdev->subled_info[i].brightness = brightness *
     23					mcled_cdev->subled_info[i].intensity /
     24					led_cdev->max_brightness;
     25
     26	return 0;
     27}
     28EXPORT_SYMBOL_GPL(led_mc_calc_color_components);
     29
     30static ssize_t multi_intensity_store(struct device *dev,
     31				struct device_attribute *intensity_attr,
     32				const char *buf, size_t size)
     33{
     34	struct led_classdev *led_cdev = dev_get_drvdata(dev);
     35	struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev);
     36	int nrchars, offset = 0;
     37	int intensity_value[LED_COLOR_ID_MAX];
     38	int i;
     39	ssize_t ret;
     40
     41	mutex_lock(&led_cdev->led_access);
     42
     43	for (i = 0; i < mcled_cdev->num_colors; i++) {
     44		ret = sscanf(buf + offset, "%i%n",
     45			     &intensity_value[i], &nrchars);
     46		if (ret != 1) {
     47			ret = -EINVAL;
     48			goto err_out;
     49		}
     50		offset += nrchars;
     51	}
     52
     53	offset++;
     54	if (offset < size) {
     55		ret = -EINVAL;
     56		goto err_out;
     57	}
     58
     59	for (i = 0; i < mcled_cdev->num_colors; i++)
     60		mcled_cdev->subled_info[i].intensity = intensity_value[i];
     61
     62	led_set_brightness(led_cdev, led_cdev->brightness);
     63	ret = size;
     64err_out:
     65	mutex_unlock(&led_cdev->led_access);
     66	return ret;
     67}
     68
     69static ssize_t multi_intensity_show(struct device *dev,
     70			      struct device_attribute *intensity_attr,
     71			      char *buf)
     72{
     73	struct led_classdev *led_cdev = dev_get_drvdata(dev);
     74	struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev);
     75	int len = 0;
     76	int i;
     77
     78	for (i = 0; i < mcled_cdev->num_colors; i++) {
     79		len += sprintf(buf + len, "%d",
     80			       mcled_cdev->subled_info[i].intensity);
     81		if (i < mcled_cdev->num_colors - 1)
     82			len += sprintf(buf + len, " ");
     83	}
     84
     85	buf[len++] = '\n';
     86	return len;
     87}
     88static DEVICE_ATTR_RW(multi_intensity);
     89
     90static ssize_t multi_index_show(struct device *dev,
     91			      struct device_attribute *multi_index_attr,
     92			      char *buf)
     93{
     94	struct led_classdev *led_cdev = dev_get_drvdata(dev);
     95	struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev);
     96	int len = 0;
     97	int index;
     98	int i;
     99
    100	for (i = 0; i < mcled_cdev->num_colors; i++) {
    101		index = mcled_cdev->subled_info[i].color_index;
    102		len += sprintf(buf + len, "%s", led_colors[index]);
    103		if (i < mcled_cdev->num_colors - 1)
    104			len += sprintf(buf + len, " ");
    105	}
    106
    107	buf[len++] = '\n';
    108	return len;
    109}
    110static DEVICE_ATTR_RO(multi_index);
    111
    112static struct attribute *led_multicolor_attrs[] = {
    113	&dev_attr_multi_intensity.attr,
    114	&dev_attr_multi_index.attr,
    115	NULL,
    116};
    117ATTRIBUTE_GROUPS(led_multicolor);
    118
    119int led_classdev_multicolor_register_ext(struct device *parent,
    120				     struct led_classdev_mc *mcled_cdev,
    121				     struct led_init_data *init_data)
    122{
    123	struct led_classdev *led_cdev;
    124
    125	if (!mcled_cdev)
    126		return -EINVAL;
    127
    128	if (mcled_cdev->num_colors <= 0)
    129		return -EINVAL;
    130
    131	if (mcled_cdev->num_colors > LED_COLOR_ID_MAX)
    132		return -EINVAL;
    133
    134	led_cdev = &mcled_cdev->led_cdev;
    135	mcled_cdev->led_cdev.groups = led_multicolor_groups;
    136
    137	return led_classdev_register_ext(parent, led_cdev, init_data);
    138}
    139EXPORT_SYMBOL_GPL(led_classdev_multicolor_register_ext);
    140
    141void led_classdev_multicolor_unregister(struct led_classdev_mc *mcled_cdev)
    142{
    143	if (!mcled_cdev)
    144		return;
    145
    146	led_classdev_unregister(&mcled_cdev->led_cdev);
    147}
    148EXPORT_SYMBOL_GPL(led_classdev_multicolor_unregister);
    149
    150static void devm_led_classdev_multicolor_release(struct device *dev, void *res)
    151{
    152	led_classdev_multicolor_unregister(*(struct led_classdev_mc **)res);
    153}
    154
    155int devm_led_classdev_multicolor_register_ext(struct device *parent,
    156					     struct led_classdev_mc *mcled_cdev,
    157					     struct led_init_data *init_data)
    158{
    159	struct led_classdev_mc **dr;
    160	int ret;
    161
    162	dr = devres_alloc(devm_led_classdev_multicolor_release,
    163			  sizeof(*dr), GFP_KERNEL);
    164	if (!dr)
    165		return -ENOMEM;
    166
    167	ret = led_classdev_multicolor_register_ext(parent, mcled_cdev,
    168						   init_data);
    169	if (ret) {
    170		devres_free(dr);
    171		return ret;
    172	}
    173
    174	*dr = mcled_cdev;
    175	devres_add(parent, dr);
    176
    177	return 0;
    178}
    179EXPORT_SYMBOL_GPL(devm_led_classdev_multicolor_register_ext);
    180
    181static int devm_led_classdev_multicolor_match(struct device *dev,
    182					      void *res, void *data)
    183{
    184	struct led_classdev_mc **p = res;
    185
    186	if (WARN_ON(!p || !*p))
    187		return 0;
    188
    189	return *p == data;
    190}
    191
    192void devm_led_classdev_multicolor_unregister(struct device *dev,
    193					     struct led_classdev_mc *mcled_cdev)
    194{
    195	WARN_ON(devres_release(dev,
    196			       devm_led_classdev_multicolor_release,
    197			       devm_led_classdev_multicolor_match, mcled_cdev));
    198}
    199EXPORT_SYMBOL_GPL(devm_led_classdev_multicolor_unregister);
    200
    201MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
    202MODULE_DESCRIPTION("Multicolor LED class interface");
    203MODULE_LICENSE("GPL v2");