1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * motor driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun //#define DEBUG
9*4882a593Smuzhiyun #include <linux/io.h>
10*4882a593Smuzhiyun #include <linux/of_gpio.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/device.h>
14*4882a593Smuzhiyun #include <linux/fb.h>
15*4882a593Smuzhiyun #include <linux/interrupt.h>
16*4882a593Smuzhiyun #include <linux/kernel.h>
17*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
18*4882a593Smuzhiyun #include <linux/of_irq.h>
19*4882a593Smuzhiyun #include <linux/platform_device.h>
20*4882a593Smuzhiyun #include <linux/wakelock.h>
21*4882a593Smuzhiyun #include <linux/hrtimer.h>
22*4882a593Smuzhiyun #include <linux/pwm.h>
23*4882a593Smuzhiyun #include <linux/delay.h>
24*4882a593Smuzhiyun #include <media/v4l2-subdev.h>
25*4882a593Smuzhiyun #include <media/v4l2-ctrls.h>
26*4882a593Smuzhiyun #include <media/v4l2-device.h>
27*4882a593Smuzhiyun #include <linux/mutex.h>
28*4882a593Smuzhiyun #include <linux/version.h>
29*4882a593Smuzhiyun #include <linux/rk-camera-module.h>
30*4882a593Smuzhiyun #include <linux/completion.h>
31*4882a593Smuzhiyun #include <linux/rk_vcm_head.h>
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x00)
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #define DRIVER_NAME "hall-dc"
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #define IRIS_MAX_LOG 100
38*4882a593Smuzhiyun #define IRIS_LOG_STEP 1
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #define PWM_PERIOD_DEF 333333
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun struct motor_dev {
43*4882a593Smuzhiyun struct v4l2_subdev sd;
44*4882a593Smuzhiyun struct v4l2_ctrl_handler ctrl_handler;
45*4882a593Smuzhiyun struct pwm_device *pwm;
46*4882a593Smuzhiyun struct device *dev;
47*4882a593Smuzhiyun struct mutex mutex;
48*4882a593Smuzhiyun struct pwm_state pwm_state;
49*4882a593Smuzhiyun u32 module_index;
50*4882a593Smuzhiyun const char *module_facing;
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun
motor_dev_parse_dt(struct motor_dev * motor)53*4882a593Smuzhiyun static int motor_dev_parse_dt(struct motor_dev *motor)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun struct device_node *node = motor->dev->of_node;
56*4882a593Smuzhiyun int ret = 0;
57*4882a593Smuzhiyun int error = 0;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun motor->pwm = devm_pwm_get(motor->dev, NULL);
60*4882a593Smuzhiyun if (IS_ERR(motor->pwm)) {
61*4882a593Smuzhiyun error = PTR_ERR(motor->pwm);
62*4882a593Smuzhiyun if (error != -EPROBE_DEFER)
63*4882a593Smuzhiyun dev_err(motor->dev, "Failed to request PWM device: %d\n", error);
64*4882a593Smuzhiyun return error;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun if (motor->pwm && motor->pwm->args.period != 0) {
67*4882a593Smuzhiyun motor->pwm_state.period = motor->pwm->args.period;
68*4882a593Smuzhiyun motor->pwm_state.polarity = motor->pwm->args.polarity;
69*4882a593Smuzhiyun } else {
70*4882a593Smuzhiyun motor->pwm_state.period = PWM_PERIOD_DEF;
71*4882a593Smuzhiyun motor->pwm_state.polarity = 0;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
74*4882a593Smuzhiyun &motor->module_index);
75*4882a593Smuzhiyun ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
76*4882a593Smuzhiyun &motor->module_facing);
77*4882a593Smuzhiyun if (ret) {
78*4882a593Smuzhiyun dev_err(motor->dev,
79*4882a593Smuzhiyun "could not get module information!\n");
80*4882a593Smuzhiyun return -EINVAL;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun return 0;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
motor_s_ctrl(struct v4l2_ctrl * ctrl)85*4882a593Smuzhiyun static int motor_s_ctrl(struct v4l2_ctrl *ctrl)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun int ret = 0;
88*4882a593Smuzhiyun struct motor_dev *motor = container_of(ctrl->handler,
89*4882a593Smuzhiyun struct motor_dev, ctrl_handler);
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun switch (ctrl->id) {
92*4882a593Smuzhiyun case V4L2_CID_IRIS_ABSOLUTE:
93*4882a593Smuzhiyun motor->pwm_state.enabled = true;
94*4882a593Smuzhiyun motor->pwm_state.duty_cycle =
95*4882a593Smuzhiyun div64_u64((u64)motor->pwm_state.period * ctrl->val, IRIS_MAX_LOG);
96*4882a593Smuzhiyun pwm_apply_state(motor->pwm, &motor->pwm_state);
97*4882a593Smuzhiyun dev_dbg(motor->dev, "iris, ctrl->val %d, pwm duty %lld, period %lld, polarity %d\n",
98*4882a593Smuzhiyun ctrl->val,
99*4882a593Smuzhiyun motor->pwm_state.duty_cycle,
100*4882a593Smuzhiyun motor->pwm_state.period,
101*4882a593Smuzhiyun motor->pwm_state.polarity);
102*4882a593Smuzhiyun break;
103*4882a593Smuzhiyun default:
104*4882a593Smuzhiyun dev_err(motor->dev, "not support cmd %d\n", ctrl->id);
105*4882a593Smuzhiyun break;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun return ret;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
motor_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)110*4882a593Smuzhiyun static long motor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun return 0;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun static const struct v4l2_subdev_core_ops motor_core_ops = {
116*4882a593Smuzhiyun .ioctl = motor_ioctl,
117*4882a593Smuzhiyun };
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun static const struct v4l2_subdev_ops motor_subdev_ops = {
120*4882a593Smuzhiyun .core = &motor_core_ops,
121*4882a593Smuzhiyun };
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun static const struct v4l2_ctrl_ops motor_ctrl_ops = {
124*4882a593Smuzhiyun .s_ctrl = motor_s_ctrl,
125*4882a593Smuzhiyun };
126*4882a593Smuzhiyun
motor_initialize_controls(struct motor_dev * motor)127*4882a593Smuzhiyun static int motor_initialize_controls(struct motor_dev *motor)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun struct v4l2_ctrl_handler *handler;
130*4882a593Smuzhiyun int ret = 0;
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun handler = &motor->ctrl_handler;
133*4882a593Smuzhiyun ret = v4l2_ctrl_handler_init(handler, 1);
134*4882a593Smuzhiyun if (ret)
135*4882a593Smuzhiyun return ret;
136*4882a593Smuzhiyun handler->lock = &motor->mutex;
137*4882a593Smuzhiyun v4l2_ctrl_new_std(handler, &motor_ctrl_ops,
138*4882a593Smuzhiyun V4L2_CID_IRIS_ABSOLUTE, 0, IRIS_MAX_LOG, IRIS_LOG_STEP, 0);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun if (handler->error) {
141*4882a593Smuzhiyun ret = handler->error;
142*4882a593Smuzhiyun dev_err(motor->dev,
143*4882a593Smuzhiyun "Failed to init controls(%d)\n", ret);
144*4882a593Smuzhiyun goto err_free_handler;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun motor->sd.ctrl_handler = handler;
148*4882a593Smuzhiyun return ret;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun err_free_handler:
151*4882a593Smuzhiyun v4l2_ctrl_handler_free(handler);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun return ret;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
motor_dev_probe(struct platform_device * pdev)156*4882a593Smuzhiyun static int motor_dev_probe(struct platform_device *pdev)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun int ret = 0;
159*4882a593Smuzhiyun struct motor_dev *motor;
160*4882a593Smuzhiyun struct v4l2_subdev *sd;
161*4882a593Smuzhiyun char facing[2];
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun dev_info(&pdev->dev, "driver version: %02x.%02x.%02x",
164*4882a593Smuzhiyun DRIVER_VERSION >> 16,
165*4882a593Smuzhiyun (DRIVER_VERSION & 0xff00) >> 8,
166*4882a593Smuzhiyun DRIVER_VERSION & 0x00ff);
167*4882a593Smuzhiyun motor = devm_kzalloc(&pdev->dev, sizeof(*motor), GFP_KERNEL);
168*4882a593Smuzhiyun if (!motor)
169*4882a593Smuzhiyun return -ENOMEM;
170*4882a593Smuzhiyun motor->dev = &pdev->dev;
171*4882a593Smuzhiyun dev_set_name(motor->dev, "motor");
172*4882a593Smuzhiyun dev_set_drvdata(motor->dev, motor);
173*4882a593Smuzhiyun if (motor_dev_parse_dt(motor)) {
174*4882a593Smuzhiyun dev_err(motor->dev, "parse dt error\n");
175*4882a593Smuzhiyun return -EINVAL;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun mutex_init(&motor->mutex);
178*4882a593Smuzhiyun v4l2_subdev_init(&motor->sd, &motor_subdev_ops);
179*4882a593Smuzhiyun motor->sd.owner = pdev->dev.driver->owner;
180*4882a593Smuzhiyun motor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
181*4882a593Smuzhiyun motor->sd.dev = &pdev->dev;
182*4882a593Smuzhiyun v4l2_set_subdevdata(&motor->sd, pdev);
183*4882a593Smuzhiyun platform_set_drvdata(pdev, &motor->sd);
184*4882a593Smuzhiyun motor_initialize_controls(motor);
185*4882a593Smuzhiyun if (ret)
186*4882a593Smuzhiyun goto err_free;
187*4882a593Smuzhiyun ret = media_entity_pads_init(&motor->sd.entity, 0, NULL);
188*4882a593Smuzhiyun if (ret < 0)
189*4882a593Smuzhiyun goto err_free;
190*4882a593Smuzhiyun sd = &motor->sd;
191*4882a593Smuzhiyun sd->entity.function = MEDIA_ENT_F_LENS;
192*4882a593Smuzhiyun sd->entity.flags = 2;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun memset(facing, 0, sizeof(facing));
195*4882a593Smuzhiyun if (strcmp(motor->module_facing, "back") == 0)
196*4882a593Smuzhiyun facing[0] = 'b';
197*4882a593Smuzhiyun else
198*4882a593Smuzhiyun facing[0] = 'f';
199*4882a593Smuzhiyun snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s",
200*4882a593Smuzhiyun motor->module_index, facing,
201*4882a593Smuzhiyun DRIVER_NAME);
202*4882a593Smuzhiyun ret = v4l2_async_register_subdev(sd);
203*4882a593Smuzhiyun if (ret)
204*4882a593Smuzhiyun dev_err(&pdev->dev, "v4l2 async register subdev failed\n");
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun dev_info(motor->dev, "gpio motor driver probe success\n");
207*4882a593Smuzhiyun return 0;
208*4882a593Smuzhiyun err_free:
209*4882a593Smuzhiyun v4l2_ctrl_handler_free(&motor->ctrl_handler);
210*4882a593Smuzhiyun v4l2_device_unregister_subdev(&motor->sd);
211*4882a593Smuzhiyun media_entity_cleanup(&motor->sd.entity);
212*4882a593Smuzhiyun return ret;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun
motor_dev_remove(struct platform_device * pdev)215*4882a593Smuzhiyun static int motor_dev_remove(struct platform_device *pdev)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun struct v4l2_subdev *sd = platform_get_drvdata(pdev);
218*4882a593Smuzhiyun struct motor_dev *motor;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun if (sd)
221*4882a593Smuzhiyun motor = v4l2_get_subdevdata(sd);
222*4882a593Smuzhiyun else
223*4882a593Smuzhiyun return -ENODEV;
224*4882a593Smuzhiyun if (sd)
225*4882a593Smuzhiyun v4l2_device_unregister_subdev(sd);
226*4882a593Smuzhiyun v4l2_ctrl_handler_free(&motor->ctrl_handler);
227*4882a593Smuzhiyun media_entity_cleanup(&motor->sd.entity);
228*4882a593Smuzhiyun return 0;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun #if defined(CONFIG_OF)
232*4882a593Smuzhiyun static const struct of_device_id motor_dev_of_match[] = {
233*4882a593Smuzhiyun { .compatible = "rockchip,hall-dc", },
234*4882a593Smuzhiyun {},
235*4882a593Smuzhiyun };
236*4882a593Smuzhiyun #endif
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun static struct platform_driver motor_dev_driver = {
239*4882a593Smuzhiyun .driver = {
240*4882a593Smuzhiyun .name = DRIVER_NAME,
241*4882a593Smuzhiyun .owner = THIS_MODULE,
242*4882a593Smuzhiyun .of_match_table = of_match_ptr(motor_dev_of_match),
243*4882a593Smuzhiyun },
244*4882a593Smuzhiyun .probe = motor_dev_probe,
245*4882a593Smuzhiyun .remove = motor_dev_remove,
246*4882a593Smuzhiyun };
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun module_platform_driver(motor_dev_driver);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun MODULE_LICENSE("GPL");
251*4882a593Smuzhiyun MODULE_ALIAS("platform:motor");
252*4882a593Smuzhiyun MODULE_AUTHOR("ROCKCHIP");
253