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 * Azoteq IQS620A/621/622/624/625 Keys and Switches
  4 *
  5 * Copyright (C) 2019 Jeff LaBundy <jeff@labundy.com>
  6 */
  7
  8#include <linux/device.h>
  9#include <linux/input.h>
 10#include <linux/kernel.h>
 11#include <linux/mfd/iqs62x.h>
 12#include <linux/module.h>
 13#include <linux/notifier.h>
 14#include <linux/platform_device.h>
 15#include <linux/property.h>
 16#include <linux/regmap.h>
 17#include <linux/slab.h>
 18
 19enum {
 20	IQS62X_SW_HALL_N,
 21	IQS62X_SW_HALL_S,
 22};
 23
 24static const char * const iqs62x_switch_names[] = {
 25	[IQS62X_SW_HALL_N] = "hall-switch-north",
 26	[IQS62X_SW_HALL_S] = "hall-switch-south",
 27};
 28
 29struct iqs62x_switch_desc {
 30	enum iqs62x_event_flag flag;
 31	unsigned int code;
 32	bool enabled;
 33};
 34
 35struct iqs62x_keys_private {
 36	struct iqs62x_core *iqs62x;
 37	struct input_dev *input;
 38	struct notifier_block notifier;
 39	struct iqs62x_switch_desc switches[ARRAY_SIZE(iqs62x_switch_names)];
 40	unsigned int keycode[IQS62X_NUM_KEYS];
 41	unsigned int keycodemax;
 42	u8 interval;
 43};
 44
 45static int iqs62x_keys_parse_prop(struct platform_device *pdev,
 46				  struct iqs62x_keys_private *iqs62x_keys)
 47{
 48	unsigned int val;
 49	int ret, i;
 50
 51	ret = device_property_count_u32(&pdev->dev, "linux,keycodes");
 52	if (ret > IQS62X_NUM_KEYS) {
 53		dev_err(&pdev->dev, "Too many keycodes present\n");
 54		return -EINVAL;
 55	} else if (ret < 0) {
 56		dev_err(&pdev->dev, "Failed to count keycodes: %d\n", ret);
 57		return ret;
 58	}
 59	iqs62x_keys->keycodemax = ret;
 60
 61	ret = device_property_read_u32_array(&pdev->dev, "linux,keycodes",
 62					     iqs62x_keys->keycode,
 63					     iqs62x_keys->keycodemax);
 64	if (ret) {
 65		dev_err(&pdev->dev, "Failed to read keycodes: %d\n", ret);
 66		return ret;
 67	}
 68
 69	for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) {
 70		struct fwnode_handle *child __free(fwnode_handle) =
 71			device_get_named_child_node(&pdev->dev,
 72						    iqs62x_switch_names[i]);
 73		if (!child)
 74			continue;
 75
 76		ret = fwnode_property_read_u32(child, "linux,code", &val);
 77		if (ret) {
 78			dev_err(&pdev->dev, "Failed to read switch code: %d\n",
 79				ret);
 80			return ret;
 81		}
 82		iqs62x_keys->switches[i].code = val;
 83		iqs62x_keys->switches[i].enabled = true;
 84
 85		if (fwnode_property_present(child, "azoteq,use-prox"))
 86			iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ?
 87							 IQS62X_EVENT_HALL_N_P :
 88							 IQS62X_EVENT_HALL_S_P);
 89		else
 90			iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ?
 91							 IQS62X_EVENT_HALL_N_T :
 92							 IQS62X_EVENT_HALL_S_T);
 93	}
 94
 95	return 0;
 96}
 97
 98static int iqs62x_keys_init(struct iqs62x_keys_private *iqs62x_keys)
 99{
100	struct iqs62x_core *iqs62x = iqs62x_keys->iqs62x;
101	enum iqs62x_event_flag flag;
102	unsigned int event_reg, val;
103	unsigned int event_mask = 0;
104	int ret, i;
105
106	switch (iqs62x->dev_desc->prod_num) {
107	case IQS620_PROD_NUM:
108	case IQS621_PROD_NUM:
109	case IQS622_PROD_NUM:
110		event_reg = IQS620_GLBL_EVENT_MASK;
111
112		/*
113		 * Discreet button, hysteresis and SAR UI flags represent keys
114		 * and are unmasked if mapped to a valid keycode.
115		 */
116		for (i = 0; i < iqs62x_keys->keycodemax; i++) {
117			if (iqs62x_keys->keycode[i] == KEY_RESERVED)
118				continue;
119
120			if (iqs62x_events[i].reg == IQS62X_EVENT_PROX)
121				event_mask |= iqs62x->dev_desc->prox_mask;
122			else if (iqs62x_events[i].reg == IQS62X_EVENT_HYST)
123				event_mask |= (iqs62x->dev_desc->hyst_mask |
124					       iqs62x->dev_desc->sar_mask);
125		}
126
127		ret = regmap_read(iqs62x->regmap, iqs62x->dev_desc->hall_flags,
128				  &val);
129		if (ret)
130			return ret;
131
132		/*
133		 * Hall UI flags represent switches and are unmasked if their
134		 * corresponding child nodes are present.
135		 */
136		for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) {
137			if (!(iqs62x_keys->switches[i].enabled))
138				continue;
139
140			flag = iqs62x_keys->switches[i].flag;
141
142			if (iqs62x_events[flag].reg != IQS62X_EVENT_HALL)
143				continue;
144
145			event_mask |= iqs62x->dev_desc->hall_mask;
146
147			input_report_switch(iqs62x_keys->input,
148					    iqs62x_keys->switches[i].code,
149					    (val & iqs62x_events[flag].mask) ==
150					    iqs62x_events[flag].val);
151		}
152
153		input_sync(iqs62x_keys->input);
154		break;
155
156	case IQS624_PROD_NUM:
157		event_reg = IQS624_HALL_UI;
158
159		/*
160		 * Interval change events represent keys and are unmasked if
161		 * either wheel movement flag is mapped to a valid keycode.
162		 */
163		if (iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_UP] != KEY_RESERVED)
164			event_mask |= IQS624_HALL_UI_INT_EVENT;
165
166		if (iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_DN] != KEY_RESERVED)
167			event_mask |= IQS624_HALL_UI_INT_EVENT;
168
169		ret = regmap_read(iqs62x->regmap, iqs62x->dev_desc->interval,
170				  &val);
171		if (ret)
172			return ret;
173
174		iqs62x_keys->interval = val;
175		break;
176
177	default:
178		return 0;
179	}
180
181	return regmap_update_bits(iqs62x->regmap, event_reg, event_mask, 0);
182}
183
184static int iqs62x_keys_notifier(struct notifier_block *notifier,
185				unsigned long event_flags, void *context)
186{
187	struct iqs62x_event_data *event_data = context;
188	struct iqs62x_keys_private *iqs62x_keys;
189	int ret, i;
190
191	iqs62x_keys = container_of(notifier, struct iqs62x_keys_private,
192				   notifier);
193
194	if (event_flags & BIT(IQS62X_EVENT_SYS_RESET)) {
195		ret = iqs62x_keys_init(iqs62x_keys);
196		if (ret) {
197			dev_err(iqs62x_keys->input->dev.parent,
198				"Failed to re-initialize device: %d\n", ret);
199			return NOTIFY_BAD;
200		}
201
202		return NOTIFY_OK;
203	}
204
205	for (i = 0; i < iqs62x_keys->keycodemax; i++) {
206		if (iqs62x_events[i].reg == IQS62X_EVENT_WHEEL &&
207		    event_data->interval == iqs62x_keys->interval)
208			continue;
209
210		input_report_key(iqs62x_keys->input, iqs62x_keys->keycode[i],
211				 event_flags & BIT(i));
212	}
213
214	for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++)
215		if (iqs62x_keys->switches[i].enabled)
216			input_report_switch(iqs62x_keys->input,
217					    iqs62x_keys->switches[i].code,
218					    event_flags &
219					    BIT(iqs62x_keys->switches[i].flag));
220
221	input_sync(iqs62x_keys->input);
222
223	if (event_data->interval == iqs62x_keys->interval)
224		return NOTIFY_OK;
225
226	/*
227	 * Each frame contains at most one wheel event (up or down), in which
228	 * case a complementary release cycle is emulated.
229	 */
230	if (event_flags & BIT(IQS62X_EVENT_WHEEL_UP)) {
231		input_report_key(iqs62x_keys->input,
232				 iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_UP],
233				 0);
234		input_sync(iqs62x_keys->input);
235	} else if (event_flags & BIT(IQS62X_EVENT_WHEEL_DN)) {
236		input_report_key(iqs62x_keys->input,
237				 iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_DN],
238				 0);
239		input_sync(iqs62x_keys->input);
240	}
241
242	iqs62x_keys->interval = event_data->interval;
243
244	return NOTIFY_OK;
245}
246
247static int iqs62x_keys_probe(struct platform_device *pdev)
248{
249	struct iqs62x_core *iqs62x = dev_get_drvdata(pdev->dev.parent);
250	struct iqs62x_keys_private *iqs62x_keys;
251	struct input_dev *input;
252	int ret, i;
253
254	iqs62x_keys = devm_kzalloc(&pdev->dev, sizeof(*iqs62x_keys),
255				   GFP_KERNEL);
256	if (!iqs62x_keys)
257		return -ENOMEM;
258
259	platform_set_drvdata(pdev, iqs62x_keys);
260
261	ret = iqs62x_keys_parse_prop(pdev, iqs62x_keys);
262	if (ret)
263		return ret;
264
265	input = devm_input_allocate_device(&pdev->dev);
266	if (!input)
267		return -ENOMEM;
268
269	input->keycodemax = iqs62x_keys->keycodemax;
270	input->keycode = iqs62x_keys->keycode;
271	input->keycodesize = sizeof(*iqs62x_keys->keycode);
272
273	input->name = iqs62x->dev_desc->dev_name;
274	input->id.bustype = BUS_I2C;
275
276	for (i = 0; i < iqs62x_keys->keycodemax; i++)
277		if (iqs62x_keys->keycode[i] != KEY_RESERVED)
278			input_set_capability(input, EV_KEY,
279					     iqs62x_keys->keycode[i]);
280
281	for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++)
282		if (iqs62x_keys->switches[i].enabled)
283			input_set_capability(input, EV_SW,
284					     iqs62x_keys->switches[i].code);
285
286	iqs62x_keys->iqs62x = iqs62x;
287	iqs62x_keys->input = input;
288
289	ret = iqs62x_keys_init(iqs62x_keys);
290	if (ret) {
291		dev_err(&pdev->dev, "Failed to initialize device: %d\n", ret);
292		return ret;
293	}
294
295	ret = input_register_device(iqs62x_keys->input);
296	if (ret) {
297		dev_err(&pdev->dev, "Failed to register device: %d\n", ret);
298		return ret;
299	}
300
301	iqs62x_keys->notifier.notifier_call = iqs62x_keys_notifier;
302	ret = blocking_notifier_chain_register(&iqs62x_keys->iqs62x->nh,
303					       &iqs62x_keys->notifier);
304	if (ret)
305		dev_err(&pdev->dev, "Failed to register notifier: %d\n", ret);
306
307	return ret;
308}
309
310static void iqs62x_keys_remove(struct platform_device *pdev)
311{
312	struct iqs62x_keys_private *iqs62x_keys = platform_get_drvdata(pdev);
313	int ret;
314
315	ret = blocking_notifier_chain_unregister(&iqs62x_keys->iqs62x->nh,
316						 &iqs62x_keys->notifier);
317	if (ret)
318		dev_err(&pdev->dev, "Failed to unregister notifier: %d\n", ret);
319}
320
321static struct platform_driver iqs62x_keys_platform_driver = {
322	.driver = {
323		.name = "iqs62x-keys",
324	},
325	.probe = iqs62x_keys_probe,
326	.remove = iqs62x_keys_remove,
327};
328module_platform_driver(iqs62x_keys_platform_driver);
329
330MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>");
331MODULE_DESCRIPTION("Azoteq IQS620A/621/622/624/625 Keys and Switches");
332MODULE_LICENSE("GPL");
333MODULE_ALIAS("platform:iqs62x-keys");