xref: /linux/drivers/input/misc/rave-sp-pwrbutton.c (revision c1144d29f405ce1f4e6ede6482beb3d0d09750c6)
1*62f0f079SAndrey Smirnov // SPDX-License-Identifier: GPL-2.0+
2*62f0f079SAndrey Smirnov //
3*62f0f079SAndrey Smirnov // Power Button driver for RAVE SP
4*62f0f079SAndrey Smirnov //
5*62f0f079SAndrey Smirnov // Copyright (C) 2017 Zodiac Inflight Innovations
6*62f0f079SAndrey Smirnov //
7*62f0f079SAndrey Smirnov //
8*62f0f079SAndrey Smirnov 
9*62f0f079SAndrey Smirnov #include <linux/input.h>
10*62f0f079SAndrey Smirnov #include <linux/kernel.h>
11*62f0f079SAndrey Smirnov #include <linux/module.h>
12*62f0f079SAndrey Smirnov #include <linux/mfd/rave-sp.h>
13*62f0f079SAndrey Smirnov #include <linux/platform_device.h>
14*62f0f079SAndrey Smirnov 
15*62f0f079SAndrey Smirnov #define RAVE_SP_EVNT_BUTTON_PRESS	(RAVE_SP_EVNT_BASE + 0x00)
16*62f0f079SAndrey Smirnov 
17*62f0f079SAndrey Smirnov struct rave_sp_power_button {
18*62f0f079SAndrey Smirnov 	struct input_dev *idev;
19*62f0f079SAndrey Smirnov 	struct notifier_block nb;
20*62f0f079SAndrey Smirnov };
21*62f0f079SAndrey Smirnov 
rave_sp_power_button_event(struct notifier_block * nb,unsigned long action,void * data)22*62f0f079SAndrey Smirnov static int rave_sp_power_button_event(struct notifier_block *nb,
23*62f0f079SAndrey Smirnov 				      unsigned long action, void *data)
24*62f0f079SAndrey Smirnov {
25*62f0f079SAndrey Smirnov 	struct rave_sp_power_button *pb =
26*62f0f079SAndrey Smirnov 		container_of(nb, struct rave_sp_power_button, nb);
27*62f0f079SAndrey Smirnov 	const u8 event = rave_sp_action_unpack_event(action);
28*62f0f079SAndrey Smirnov 	const u8 value = rave_sp_action_unpack_value(action);
29*62f0f079SAndrey Smirnov 	struct input_dev *idev = pb->idev;
30*62f0f079SAndrey Smirnov 
31*62f0f079SAndrey Smirnov 	if (event == RAVE_SP_EVNT_BUTTON_PRESS) {
32*62f0f079SAndrey Smirnov 		input_report_key(idev, KEY_POWER, value);
33*62f0f079SAndrey Smirnov 		input_sync(idev);
34*62f0f079SAndrey Smirnov 
35*62f0f079SAndrey Smirnov 		return NOTIFY_STOP;
36*62f0f079SAndrey Smirnov 	}
37*62f0f079SAndrey Smirnov 
38*62f0f079SAndrey Smirnov 	return NOTIFY_DONE;
39*62f0f079SAndrey Smirnov }
40*62f0f079SAndrey Smirnov 
rave_sp_pwrbutton_probe(struct platform_device * pdev)41*62f0f079SAndrey Smirnov static int rave_sp_pwrbutton_probe(struct platform_device *pdev)
42*62f0f079SAndrey Smirnov {
43*62f0f079SAndrey Smirnov 	struct device *dev = &pdev->dev;
44*62f0f079SAndrey Smirnov 	struct rave_sp_power_button *pb;
45*62f0f079SAndrey Smirnov 	struct input_dev *idev;
46*62f0f079SAndrey Smirnov 	int error;
47*62f0f079SAndrey Smirnov 
48*62f0f079SAndrey Smirnov 	pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL);
49*62f0f079SAndrey Smirnov 	if (!pb)
50*62f0f079SAndrey Smirnov 		return -ENOMEM;
51*62f0f079SAndrey Smirnov 
52*62f0f079SAndrey Smirnov 	idev = devm_input_allocate_device(dev);
53*62f0f079SAndrey Smirnov 	if (!idev)
54*62f0f079SAndrey Smirnov 		return -ENOMEM;
55*62f0f079SAndrey Smirnov 
56*62f0f079SAndrey Smirnov 	idev->name = pdev->name;
57*62f0f079SAndrey Smirnov 
58*62f0f079SAndrey Smirnov 	input_set_capability(idev, EV_KEY, KEY_POWER);
59*62f0f079SAndrey Smirnov 
60*62f0f079SAndrey Smirnov 	error = input_register_device(idev);
61*62f0f079SAndrey Smirnov 	if (error)
62*62f0f079SAndrey Smirnov 		return error;
63*62f0f079SAndrey Smirnov 
64*62f0f079SAndrey Smirnov 	pb->idev = idev;
65*62f0f079SAndrey Smirnov 	pb->nb.notifier_call = rave_sp_power_button_event;
66*62f0f079SAndrey Smirnov 	pb->nb.priority = 128;
67*62f0f079SAndrey Smirnov 
68*62f0f079SAndrey Smirnov 	error = devm_rave_sp_register_event_notifier(dev, &pb->nb);
69*62f0f079SAndrey Smirnov 	if (error)
70*62f0f079SAndrey Smirnov 		return error;
71*62f0f079SAndrey Smirnov 
72*62f0f079SAndrey Smirnov 	return 0;
73*62f0f079SAndrey Smirnov }
74*62f0f079SAndrey Smirnov 
75*62f0f079SAndrey Smirnov static const struct of_device_id rave_sp_pwrbutton_of_match[] = {
76*62f0f079SAndrey Smirnov 	{ .compatible = "zii,rave-sp-pwrbutton" },
77*62f0f079SAndrey Smirnov 	{}
78*62f0f079SAndrey Smirnov };
79*62f0f079SAndrey Smirnov 
80*62f0f079SAndrey Smirnov static struct platform_driver rave_sp_pwrbutton_driver = {
81*62f0f079SAndrey Smirnov 	.probe = rave_sp_pwrbutton_probe,
82*62f0f079SAndrey Smirnov 	.driver	= {
83*62f0f079SAndrey Smirnov 		.name = KBUILD_MODNAME,
84*62f0f079SAndrey Smirnov 		.of_match_table = rave_sp_pwrbutton_of_match,
85*62f0f079SAndrey Smirnov 	},
86*62f0f079SAndrey Smirnov };
87*62f0f079SAndrey Smirnov module_platform_driver(rave_sp_pwrbutton_driver);
88*62f0f079SAndrey Smirnov 
89*62f0f079SAndrey Smirnov MODULE_DEVICE_TABLE(of, rave_sp_pwrbutton_of_match);
90*62f0f079SAndrey Smirnov MODULE_LICENSE("GPL");
91*62f0f079SAndrey Smirnov MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>");
92*62f0f079SAndrey Smirnov MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>");
93*62f0f079SAndrey Smirnov MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
94*62f0f079SAndrey Smirnov MODULE_DESCRIPTION("RAVE SP Power Button driver");
95