Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <linux/bitops.h>
  4#include <linux/regmap.h>
  5#include <net/dsa.h>
  6#include "rtl83xx.h"
  7#include "rtl8366rb.h"
  8
  9static inline u32 rtl8366rb_led_group_port_mask(u8 led_group, u8 port)
 10{
 11	switch (led_group) {
 12	case 0:
 13		return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
 14	case 1:
 15		return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
 16	case 2:
 17		return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
 18	case 3:
 19		return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
 20	default:
 21		return 0;
 22	}
 23}
 24
 25static int rb8366rb_get_port_led(struct rtl8366rb_led *led)
 26{
 27	struct realtek_priv *priv = led->priv;
 28	u8 led_group = led->led_group;
 29	u8 port_num = led->port_num;
 30	int ret;
 31	u32 val;
 32
 33	ret = regmap_read(priv->map, RTL8366RB_LED_X_X_CTRL_REG(led_group),
 34			  &val);
 35	if (ret) {
 36		dev_err(priv->dev, "error reading LED on port %d group %d\n",
 37			led_group, port_num);
 38		return ret;
 39	}
 40
 41	return !!(val & rtl8366rb_led_group_port_mask(led_group, port_num));
 42}
 43
 44static int rb8366rb_set_port_led(struct rtl8366rb_led *led, bool enable)
 45{
 46	struct realtek_priv *priv = led->priv;
 47	u8 led_group = led->led_group;
 48	u8 port_num = led->port_num;
 49	int ret;
 50
 51	ret = regmap_update_bits(priv->map,
 52				 RTL8366RB_LED_X_X_CTRL_REG(led_group),
 53				 rtl8366rb_led_group_port_mask(led_group,
 54							       port_num),
 55				 enable ? 0xffff : 0);
 56	if (ret) {
 57		dev_err(priv->dev, "error updating LED on port %d group %d\n",
 58			led_group, port_num);
 59		return ret;
 60	}
 61
 62	/* Change the LED group to manual controlled LEDs if required */
 63	ret = rb8366rb_set_ledgroup_mode(priv, led_group,
 64					 RTL8366RB_LEDGROUP_FORCE);
 65
 66	if (ret) {
 67		dev_err(priv->dev, "error updating LED GROUP group %d\n",
 68			led_group);
 69		return ret;
 70	}
 71
 72	return 0;
 73}
 74
 75static int
 76rtl8366rb_cled_brightness_set_blocking(struct led_classdev *ldev,
 77				       enum led_brightness brightness)
 78{
 79	struct rtl8366rb_led *led = container_of(ldev, struct rtl8366rb_led,
 80						 cdev);
 81
 82	return rb8366rb_set_port_led(led, brightness == LED_ON);
 83}
 84
 85static int rtl8366rb_setup_led(struct realtek_priv *priv, struct dsa_port *dp,
 86			       struct fwnode_handle *led_fwnode)
 87{
 88	struct rtl8366rb *rb = priv->chip_data;
 89	struct led_init_data init_data = { };
 90	enum led_default_state state;
 91	struct rtl8366rb_led *led;
 92	u32 led_group;
 93	int ret;
 94
 95	ret = fwnode_property_read_u32(led_fwnode, "reg", &led_group);
 96	if (ret)
 97		return ret;
 98
 99	if (led_group >= RTL8366RB_NUM_LEDGROUPS) {
100		dev_warn(priv->dev, "Invalid LED reg %d defined for port %d",
101			 led_group, dp->index);
102		return -EINVAL;
103	}
104
105	led = &rb->leds[dp->index][led_group];
106	led->port_num = dp->index;
107	led->led_group = led_group;
108	led->priv = priv;
109
110	state = led_init_default_state_get(led_fwnode);
111	switch (state) {
112	case LEDS_DEFSTATE_ON:
113		led->cdev.brightness = 1;
114		rb8366rb_set_port_led(led, 1);
115		break;
116	case LEDS_DEFSTATE_KEEP:
117		led->cdev.brightness =
118			rb8366rb_get_port_led(led);
119		break;
120	case LEDS_DEFSTATE_OFF:
121	default:
122		led->cdev.brightness = 0;
123		rb8366rb_set_port_led(led, 0);
124	}
125
126	led->cdev.max_brightness = 1;
127	led->cdev.brightness_set_blocking =
128		rtl8366rb_cled_brightness_set_blocking;
129	init_data.fwnode = led_fwnode;
130	init_data.devname_mandatory = true;
131
132	init_data.devicename = kasprintf(GFP_KERNEL, "Realtek-%d:0%d:%d",
133					 dp->ds->index, dp->index, led_group);
134	if (!init_data.devicename)
135		return -ENOMEM;
136
137	ret = devm_led_classdev_register_ext(priv->dev, &led->cdev, &init_data);
138	if (ret) {
139		dev_warn(priv->dev, "Failed to init LED %d for port %d",
140			 led_group, dp->index);
141		return ret;
142	}
143
144	return 0;
145}
146
147int rtl8366rb_setup_leds(struct realtek_priv *priv)
148{
149	struct dsa_switch *ds = &priv->ds;
150	struct device_node *leds_np;
151	struct dsa_port *dp;
152	int ret = 0;
153
154	dsa_switch_for_each_port(dp, ds) {
155		if (!dp->dn)
156			continue;
157
158		leds_np = of_get_child_by_name(dp->dn, "leds");
159		if (!leds_np) {
160			dev_dbg(priv->dev, "No leds defined for port %d",
161				dp->index);
162			continue;
163		}
164
165		for_each_child_of_node_scoped(leds_np, led_np) {
166			ret = rtl8366rb_setup_led(priv, dp,
167						  of_fwnode_handle(led_np));
168			if (ret)
169				break;
170		}
171
172		of_node_put(leds_np);
173		if (ret)
174			return ret;
175	}
176	return 0;
177}