summaryrefslogtreecommitdiff
path: root/drivers/leds/leds-lp55xx-common.h
blob: 1bb7c559662c9c4d57b33ee3b0d806009ee26070 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * LP55XX Common Driver Header
 *
 * Copyright (C) 2012 Texas Instruments
 *
 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
 *
 * Derived from leds-lp5521.c, leds-lp5523.c
 */

#ifndef _LEDS_LP55XX_COMMON_H
#define _LEDS_LP55XX_COMMON_H

#include <linux/led-class-multicolor.h>

#define LP55xx_BYTES_PER_PAGE		32      /* bytes */

enum lp55xx_engine_index {
	LP55XX_ENGINE_INVALID,
	LP55XX_ENGINE_1,
	LP55XX_ENGINE_2,
	LP55XX_ENGINE_3,
	LP55XX_ENGINE_MAX = LP55XX_ENGINE_3,
};

enum lp55xx_engine_mode {
	LP55XX_ENGINE_DISABLED,
	LP55XX_ENGINE_LOAD,
	LP55XX_ENGINE_RUN,
};

#define LP55XX_DEV_ATTR_RW(name, show, store)	\
	DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show, store)
#define LP55XX_DEV_ATTR_RO(name, show)		\
	DEVICE_ATTR(name, S_IRUGO, show, NULL)
#define LP55XX_DEV_ATTR_WO(name, store)		\
	DEVICE_ATTR(name, S_IWUSR, NULL, store)

#define LP55XX_DEV_ATTR_ENGINE_MODE(nr)					\
static ssize_t show_engine##nr##_mode(struct device *dev,		\
				      struct device_attribute *attr,	\
				      char *buf)				\
{									\
	return lp55xx_show_engine_mode(dev, attr, buf, nr);		\
}									\
static ssize_t store_engine##nr##_mode(struct device *dev,		\
				       struct device_attribute *attr,	\
				       const char *buf, size_t len)	\
{									\
	return lp55xx_store_engine_mode(dev, attr, buf, len, nr);	\
}									\
static LP55XX_DEV_ATTR_RW(engine##nr##_mode, show_engine##nr##_mode,	\
			  store_engine##nr##_mode)

#define LP55XX_DEV_ATTR_ENGINE_LEDS(nr)					\
static ssize_t show_engine##nr##_leds(struct device *dev,		\
				      struct device_attribute *attr,	\
				      char *buf)			\
{									\
	return lp55xx_show_engine_leds(dev, attr, buf, nr);		\
}									\
static ssize_t store_engine##nr##_leds(struct device *dev,		\
				       struct device_attribute *attr,	\
				       const char *buf, size_t len)	\
{									\
	return lp55xx_store_engine_leds(dev, attr, buf, len, nr);	\
}									\
static LP55XX_DEV_ATTR_RW(engine##nr##_leds, show_engine##nr##_leds,	\
			  store_engine##nr##_leds)

#define LP55XX_DEV_ATTR_ENGINE_LOAD(nr)					\
static ssize_t store_engine##nr##_load(struct device *dev,		\
				       struct device_attribute *attr,	\
				       const char *buf, size_t len)	\
{									\
	return lp55xx_store_engine_load(dev, attr, buf, len, nr);	\
}									\
static LP55XX_DEV_ATTR_WO(engine##nr##_load, store_engine##nr##_load)

#define LP55XX_DEV_ATTR_MASTER_FADER(nr)				\
static ssize_t show_master_fader##nr(struct device *dev,		\
				     struct device_attribute *attr,	\
				     char *buf)				\
{									\
	return lp55xx_show_master_fader(dev, attr, buf, nr);		\
}									\
static ssize_t store_master_fader##nr(struct device *dev,		\
				      struct device_attribute *attr,	\
				      const char *buf, size_t len)	\
{									\
	return lp55xx_store_master_fader(dev, attr, buf, len, nr);	\
}									\
static LP55XX_DEV_ATTR_RW(master_fader##nr, show_master_fader##nr,	\
			  store_master_fader##nr)

struct lp55xx_led;
struct lp55xx_chip;

/*
 * struct lp55xx_reg
 * @addr : Register address
 * @val  : Register value (can also used as mask or shift)
 */
struct lp55xx_reg {
	u8 addr;
	union {
		u8 val;
		u8 mask;
		u8 shift;
	};
};

/*
 * struct lp55xx_device_config
 * @reg_op_mode        : Chip specific OP MODE reg addr
 * @engine_busy        : Chip specific engine busy
 *			 (if not supported 153 us sleep)
 * @reset              : Chip specific reset command
 * @enable             : Chip specific enable command
 * @prog_mem_base      : Chip specific base reg address for chip SMEM programming
 * @reg_led_pwm_base   : Chip specific base reg address for LED PWM conf
 * @reg_led_current_base : Chip specific base reg address for LED current conf
 * @reg_master_fader_base : Chip specific base reg address for master fader base
 * @reg_led_ctrl_base  : Chip specific base reg address for LED ctrl base
 * @pages_per_engine   : Assigned pages for each engine
 *                       (if not set chip doesn't support pages)
 * @max_channel        : Maximum number of channels
 * @post_init_device   : Chip specific initialization code
 * @brightness_fn      : Brightness function
 * @multicolor_brightness_fn : Multicolor brightness function
 * @set_led_current    : LED current set function
 * @firmware_cb        : Call function when the firmware is loaded
 * @run_engine         : Run internal engine for pattern
 * @dev_attr_group     : Device specific attributes
 */
struct lp55xx_device_config {
	const struct lp55xx_reg reg_op_mode; /* addr, shift */
	const struct lp55xx_reg reg_exec; /* addr, shift */
	const struct lp55xx_reg engine_busy; /* addr, mask */
	const struct lp55xx_reg reset;
	const struct lp55xx_reg enable;
	const struct lp55xx_reg prog_mem_base;
	const struct lp55xx_reg reg_led_pwm_base;
	const struct lp55xx_reg reg_led_current_base;
	const struct lp55xx_reg reg_master_fader_base;
	const struct lp55xx_reg reg_led_ctrl_base;
	const int pages_per_engine;
	const int max_channel;

	/* define if the device has specific initialization process */
	int (*post_init_device) (struct lp55xx_chip *chip);

	/* set LED brightness */
	int (*brightness_fn)(struct lp55xx_led *led);

	/* set multicolor LED brightness */
	int (*multicolor_brightness_fn)(struct lp55xx_led *led);

	/* current setting function */
	void (*set_led_current) (struct lp55xx_led *led, u8 led_current);

	/* access program memory when the firmware is loaded */
	void (*firmware_cb)(struct lp55xx_chip *chip);

	/* used for running firmware LED patterns */
	void (*run_engine) (struct lp55xx_chip *chip, bool start);

	/* additional device specific attributes */
	const struct attribute_group *dev_attr_group;
};

/*
 * struct lp55xx_engine
 * @mode       : Engine mode
 * @led_mux    : Mux bits for LED selection. Only used in LP5523
 */
struct lp55xx_engine {
	enum lp55xx_engine_mode mode;
	u16 led_mux;
};

/*
 * struct lp55xx_chip
 * @cl         : I2C communication for access registers
 * @pdata      : Platform specific data
 * @lock       : Lock for user-space interface
 * @num_leds   : Number of registered LEDs
 * @cfg        : Device specific configuration data
 * @engine_idx : Selected engine number
 * @engines    : Engine structure for the device attribute R/W interface
 * @fw         : Firmware data for running a LED pattern
 */
struct lp55xx_chip {
	struct i2c_client *cl;
	struct clk *clk;
	struct lp55xx_platform_data *pdata;
	struct mutex lock;	/* lock for user-space interface */
	int num_leds;
	const struct lp55xx_device_config *cfg;
	enum lp55xx_engine_index engine_idx;
	struct lp55xx_engine engines[LP55XX_ENGINE_MAX];
	const struct firmware *fw;
};

/*
 * struct lp55xx_led
 * @chan_nr         : Channel number
 * @cdev            : LED class device
 * @mc_cdev         : Multi color class device
 * @color_components: Multi color LED map information
 * @led_current     : Current setting at each led channel
 * @max_current     : Maximun current at each led channel
 * @brightness      : Brightness value
 * @chip            : The lp55xx chip data
 */
struct lp55xx_led {
	int chan_nr;
	struct led_classdev cdev;
	struct led_classdev_mc mc_cdev;
	u8 led_current;
	u8 max_current;
	u8 brightness;
	struct lp55xx_chip *chip;
};

/* register access */
extern int lp55xx_write(struct lp55xx_chip *chip, u8 reg, u8 val);
extern int lp55xx_read(struct lp55xx_chip *chip, u8 reg, u8 *val);
extern int lp55xx_update_bits(struct lp55xx_chip *chip, u8 reg,
			u8 mask, u8 val);

/* external clock detection */
extern bool lp55xx_is_extclk_used(struct lp55xx_chip *chip);

/* common chip functions */
extern void lp55xx_stop_all_engine(struct lp55xx_chip *chip);
extern void lp55xx_load_engine(struct lp55xx_chip *chip);
extern int lp55xx_run_engine_common(struct lp55xx_chip *chip);
extern int lp55xx_update_program_memory(struct lp55xx_chip *chip,
					const u8 *data, size_t size);
extern void lp55xx_firmware_loaded_cb(struct lp55xx_chip *chip);
extern int lp55xx_led_brightness(struct lp55xx_led *led);
extern int lp55xx_multicolor_brightness(struct lp55xx_led *led);
extern void lp55xx_set_led_current(struct lp55xx_led *led, u8 led_current);
extern void lp55xx_turn_off_channels(struct lp55xx_chip *chip);
extern void lp55xx_stop_engine(struct lp55xx_chip *chip);

/* common probe/remove function */
extern int lp55xx_probe(struct i2c_client *client);
extern void lp55xx_remove(struct i2c_client *client);

/* common sysfs function */
extern ssize_t lp55xx_show_engine_mode(struct device *dev,
				       struct device_attribute *attr,
				       char *buf, int nr);
extern ssize_t lp55xx_store_engine_mode(struct device *dev,
					struct device_attribute *attr,
					const char *buf, size_t len, int nr);
extern ssize_t lp55xx_store_engine_load(struct device *dev,
					struct device_attribute *attr,
					const char *buf, size_t len, int nr);
extern ssize_t lp55xx_show_engine_leds(struct device *dev,
				       struct device_attribute *attr,
				       char *buf, int nr);
extern ssize_t lp55xx_store_engine_leds(struct device *dev,
					struct device_attribute *attr,
					const char *buf, size_t len, int nr);
extern ssize_t lp55xx_show_master_fader(struct device *dev,
					struct device_attribute *attr,
					char *buf, int nr);
extern ssize_t lp55xx_store_master_fader(struct device *dev,
					 struct device_attribute *attr,
					 const char *buf, size_t len, int nr);
extern ssize_t lp55xx_show_master_fader_leds(struct device *dev,
					     struct device_attribute *attr,
					     char *buf);
extern ssize_t lp55xx_store_master_fader_leds(struct device *dev,
					      struct device_attribute *attr,
					      const char *buf, size_t len);

#endif /* _LEDS_LP55XX_COMMON_H */