xref: /OK3568_Linux_fs/kernel/drivers/input/misc/sc27xx-vibra.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2018 Spreadtrum Communications Inc.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <linux/module.h>
7*4882a593Smuzhiyun #include <linux/of_address.h>
8*4882a593Smuzhiyun #include <linux/platform_device.h>
9*4882a593Smuzhiyun #include <linux/regmap.h>
10*4882a593Smuzhiyun #include <linux/input.h>
11*4882a593Smuzhiyun #include <linux/workqueue.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #define CUR_DRV_CAL_SEL		GENMASK(13, 12)
14*4882a593Smuzhiyun #define SLP_LDOVIBR_PD_EN	BIT(9)
15*4882a593Smuzhiyun #define LDO_VIBR_PD		BIT(8)
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun struct vibra_info {
18*4882a593Smuzhiyun 	struct input_dev	*input_dev;
19*4882a593Smuzhiyun 	struct work_struct	play_work;
20*4882a593Smuzhiyun 	struct regmap		*regmap;
21*4882a593Smuzhiyun 	u32			base;
22*4882a593Smuzhiyun 	u32			strength;
23*4882a593Smuzhiyun 	bool			enabled;
24*4882a593Smuzhiyun };
25*4882a593Smuzhiyun 
sc27xx_vibra_set(struct vibra_info * info,bool on)26*4882a593Smuzhiyun static void sc27xx_vibra_set(struct vibra_info *info, bool on)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun 	if (on) {
29*4882a593Smuzhiyun 		regmap_update_bits(info->regmap, info->base, LDO_VIBR_PD, 0);
30*4882a593Smuzhiyun 		regmap_update_bits(info->regmap, info->base,
31*4882a593Smuzhiyun 				   SLP_LDOVIBR_PD_EN, 0);
32*4882a593Smuzhiyun 		info->enabled = true;
33*4882a593Smuzhiyun 	} else {
34*4882a593Smuzhiyun 		regmap_update_bits(info->regmap, info->base, LDO_VIBR_PD,
35*4882a593Smuzhiyun 				   LDO_VIBR_PD);
36*4882a593Smuzhiyun 		regmap_update_bits(info->regmap, info->base,
37*4882a593Smuzhiyun 				   SLP_LDOVIBR_PD_EN, SLP_LDOVIBR_PD_EN);
38*4882a593Smuzhiyun 		info->enabled = false;
39*4882a593Smuzhiyun 	}
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
sc27xx_vibra_hw_init(struct vibra_info * info)42*4882a593Smuzhiyun static int sc27xx_vibra_hw_init(struct vibra_info *info)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun 	return regmap_update_bits(info->regmap, info->base, CUR_DRV_CAL_SEL, 0);
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun 
sc27xx_vibra_play_work(struct work_struct * work)47*4882a593Smuzhiyun static void sc27xx_vibra_play_work(struct work_struct *work)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 	struct vibra_info *info = container_of(work, struct vibra_info,
50*4882a593Smuzhiyun 					       play_work);
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	if (info->strength && !info->enabled)
53*4882a593Smuzhiyun 		sc27xx_vibra_set(info, true);
54*4882a593Smuzhiyun 	else if (info->strength == 0 && info->enabled)
55*4882a593Smuzhiyun 		sc27xx_vibra_set(info, false);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun 
sc27xx_vibra_play(struct input_dev * input,void * data,struct ff_effect * effect)58*4882a593Smuzhiyun static int sc27xx_vibra_play(struct input_dev *input, void *data,
59*4882a593Smuzhiyun 			     struct ff_effect *effect)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	struct vibra_info *info = input_get_drvdata(input);
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	info->strength = effect->u.rumble.weak_magnitude;
64*4882a593Smuzhiyun 	schedule_work(&info->play_work);
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	return 0;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun 
sc27xx_vibra_close(struct input_dev * input)69*4882a593Smuzhiyun static void sc27xx_vibra_close(struct input_dev *input)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	struct vibra_info *info = input_get_drvdata(input);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	cancel_work_sync(&info->play_work);
74*4882a593Smuzhiyun 	if (info->enabled)
75*4882a593Smuzhiyun 		sc27xx_vibra_set(info, false);
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
sc27xx_vibra_probe(struct platform_device * pdev)78*4882a593Smuzhiyun static int sc27xx_vibra_probe(struct platform_device *pdev)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	struct vibra_info *info;
81*4882a593Smuzhiyun 	int error;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
84*4882a593Smuzhiyun 	if (!info)
85*4882a593Smuzhiyun 		return -ENOMEM;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	info->regmap = dev_get_regmap(pdev->dev.parent, NULL);
88*4882a593Smuzhiyun 	if (!info->regmap) {
89*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to get vibrator regmap.\n");
90*4882a593Smuzhiyun 		return -ENODEV;
91*4882a593Smuzhiyun 	}
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	error = device_property_read_u32(&pdev->dev, "reg", &info->base);
94*4882a593Smuzhiyun 	if (error) {
95*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to get vibrator base address.\n");
96*4882a593Smuzhiyun 		return error;
97*4882a593Smuzhiyun 	}
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	info->input_dev = devm_input_allocate_device(&pdev->dev);
100*4882a593Smuzhiyun 	if (!info->input_dev) {
101*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to allocate input device.\n");
102*4882a593Smuzhiyun 		return -ENOMEM;
103*4882a593Smuzhiyun 	}
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	info->input_dev->name = "sc27xx:vibrator";
106*4882a593Smuzhiyun 	info->input_dev->id.version = 0;
107*4882a593Smuzhiyun 	info->input_dev->close = sc27xx_vibra_close;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	input_set_drvdata(info->input_dev, info);
110*4882a593Smuzhiyun 	input_set_capability(info->input_dev, EV_FF, FF_RUMBLE);
111*4882a593Smuzhiyun 	INIT_WORK(&info->play_work, sc27xx_vibra_play_work);
112*4882a593Smuzhiyun 	info->enabled = false;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	error = sc27xx_vibra_hw_init(info);
115*4882a593Smuzhiyun 	if (error) {
116*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to initialize the vibrator.\n");
117*4882a593Smuzhiyun 		return error;
118*4882a593Smuzhiyun 	}
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	error = input_ff_create_memless(info->input_dev, NULL,
121*4882a593Smuzhiyun 					sc27xx_vibra_play);
122*4882a593Smuzhiyun 	if (error) {
123*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to register vibrator to FF.\n");
124*4882a593Smuzhiyun 		return error;
125*4882a593Smuzhiyun 	}
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	error = input_register_device(info->input_dev);
128*4882a593Smuzhiyun 	if (error) {
129*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to register input device.\n");
130*4882a593Smuzhiyun 		return error;
131*4882a593Smuzhiyun 	}
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	return 0;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun static const struct of_device_id sc27xx_vibra_of_match[] = {
137*4882a593Smuzhiyun 	{ .compatible = "sprd,sc2731-vibrator", },
138*4882a593Smuzhiyun 	{}
139*4882a593Smuzhiyun };
140*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, sc27xx_vibra_of_match);
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun static struct platform_driver sc27xx_vibra_driver = {
143*4882a593Smuzhiyun 	.driver = {
144*4882a593Smuzhiyun 		.name = "sc27xx-vibrator",
145*4882a593Smuzhiyun 		.of_match_table = sc27xx_vibra_of_match,
146*4882a593Smuzhiyun 	},
147*4882a593Smuzhiyun 	.probe = sc27xx_vibra_probe,
148*4882a593Smuzhiyun };
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun module_platform_driver(sc27xx_vibra_driver);
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun MODULE_DESCRIPTION("Spreadtrum SC27xx Vibrator Driver");
153*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
154*4882a593Smuzhiyun MODULE_AUTHOR("Xiaotong Lu <xiaotong.lu@spreadtrum.com>");
155