GNU Linux-libre 4.14.254-gnu1
[releases.git] / drivers / media / i2c / dw9714.c
1 /*
2  * Copyright (c) 2015--2017 Intel Corporation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License version
6  * 2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <linux/delay.h>
15 #include <linux/i2c.h>
16 #include <linux/module.h>
17 #include <linux/pm_runtime.h>
18 #include <media/v4l2-ctrls.h>
19 #include <media/v4l2-device.h>
20
21 #define DW9714_NAME             "dw9714"
22 #define DW9714_MAX_FOCUS_POS    1023
23 /*
24  * This acts as the minimum granularity of lens movement.
25  * Keep this value power of 2, so the control steps can be
26  * uniformly adjusted for gradual lens movement, with desired
27  * number of control steps.
28  */
29 #define DW9714_CTRL_STEPS       16
30 #define DW9714_CTRL_DELAY_US    1000
31 /*
32  * S[3:2] = 0x00, codes per step for "Linear Slope Control"
33  * S[1:0] = 0x00, step period
34  */
35 #define DW9714_DEFAULT_S 0x0
36 #define DW9714_VAL(data, s) ((data) << 4 | (s))
37
38 /* dw9714 device structure */
39 struct dw9714_device {
40         struct i2c_client *client;
41         struct v4l2_ctrl_handler ctrls_vcm;
42         struct v4l2_subdev sd;
43         u16 current_val;
44 };
45
46 static inline struct dw9714_device *to_dw9714_vcm(struct v4l2_ctrl *ctrl)
47 {
48         return container_of(ctrl->handler, struct dw9714_device, ctrls_vcm);
49 }
50
51 static inline struct dw9714_device *sd_to_dw9714_vcm(struct v4l2_subdev *subdev)
52 {
53         return container_of(subdev, struct dw9714_device, sd);
54 }
55
56 static int dw9714_i2c_write(struct i2c_client *client, u16 data)
57 {
58         int ret;
59         u16 val = cpu_to_be16(data);
60
61         ret = i2c_master_send(client, (const char *)&val, sizeof(val));
62         if (ret != sizeof(val)) {
63                 dev_err(&client->dev, "I2C write fail\n");
64                 return -EIO;
65         }
66         return 0;
67 }
68
69 static int dw9714_t_focus_vcm(struct dw9714_device *dw9714_dev, u16 val)
70 {
71         struct i2c_client *client = dw9714_dev->client;
72
73         dw9714_dev->current_val = val;
74
75         return dw9714_i2c_write(client, DW9714_VAL(val, DW9714_DEFAULT_S));
76 }
77
78 static int dw9714_set_ctrl(struct v4l2_ctrl *ctrl)
79 {
80         struct dw9714_device *dev_vcm = to_dw9714_vcm(ctrl);
81
82         if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE)
83                 return dw9714_t_focus_vcm(dev_vcm, ctrl->val);
84
85         return -EINVAL;
86 }
87
88 static const struct v4l2_ctrl_ops dw9714_vcm_ctrl_ops = {
89         .s_ctrl = dw9714_set_ctrl,
90 };
91
92 static int dw9714_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
93 {
94         struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd);
95         struct device *dev = &dw9714_dev->client->dev;
96         int rval;
97
98         rval = pm_runtime_get_sync(dev);
99         if (rval < 0) {
100                 pm_runtime_put_noidle(dev);
101                 return rval;
102         }
103
104         return 0;
105 }
106
107 static int dw9714_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
108 {
109         struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd);
110         struct device *dev = &dw9714_dev->client->dev;
111
112         pm_runtime_put(dev);
113
114         return 0;
115 }
116
117 static const struct v4l2_subdev_internal_ops dw9714_int_ops = {
118         .open = dw9714_open,
119         .close = dw9714_close,
120 };
121
122 static const struct v4l2_subdev_ops dw9714_ops = { };
123
124 static void dw9714_subdev_cleanup(struct dw9714_device *dw9714_dev)
125 {
126         v4l2_async_unregister_subdev(&dw9714_dev->sd);
127         v4l2_ctrl_handler_free(&dw9714_dev->ctrls_vcm);
128         media_entity_cleanup(&dw9714_dev->sd.entity);
129 }
130
131 static int dw9714_init_controls(struct dw9714_device *dev_vcm)
132 {
133         struct v4l2_ctrl_handler *hdl = &dev_vcm->ctrls_vcm;
134         const struct v4l2_ctrl_ops *ops = &dw9714_vcm_ctrl_ops;
135         struct i2c_client *client = dev_vcm->client;
136
137         v4l2_ctrl_handler_init(hdl, 1);
138
139         v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE,
140                           0, DW9714_MAX_FOCUS_POS, DW9714_CTRL_STEPS, 0);
141
142         if (hdl->error)
143                 dev_err(&client->dev, "%s fail error: 0x%x\n",
144                         __func__, hdl->error);
145         dev_vcm->sd.ctrl_handler = hdl;
146         return hdl->error;
147 }
148
149 static int dw9714_probe(struct i2c_client *client)
150 {
151         struct dw9714_device *dw9714_dev;
152         int rval;
153
154         dw9714_dev = devm_kzalloc(&client->dev, sizeof(*dw9714_dev),
155                                   GFP_KERNEL);
156         if (dw9714_dev == NULL)
157                 return -ENOMEM;
158
159         dw9714_dev->client = client;
160
161         v4l2_i2c_subdev_init(&dw9714_dev->sd, client, &dw9714_ops);
162         dw9714_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
163         dw9714_dev->sd.internal_ops = &dw9714_int_ops;
164
165         rval = dw9714_init_controls(dw9714_dev);
166         if (rval)
167                 goto err_cleanup;
168
169         rval = media_entity_pads_init(&dw9714_dev->sd.entity, 0, NULL);
170         if (rval < 0)
171                 goto err_cleanup;
172
173         dw9714_dev->sd.entity.function = MEDIA_ENT_F_LENS;
174
175         rval = v4l2_async_register_subdev(&dw9714_dev->sd);
176         if (rval < 0)
177                 goto err_cleanup;
178
179         pm_runtime_set_active(&client->dev);
180         pm_runtime_enable(&client->dev);
181
182         return 0;
183
184 err_cleanup:
185         v4l2_ctrl_handler_free(&dw9714_dev->ctrls_vcm);
186         media_entity_cleanup(&dw9714_dev->sd.entity);
187         dev_err(&client->dev, "Probe failed: %d\n", rval);
188         return rval;
189 }
190
191 static int dw9714_remove(struct i2c_client *client)
192 {
193         struct v4l2_subdev *sd = i2c_get_clientdata(client);
194         struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd);
195
196         pm_runtime_disable(&client->dev);
197         dw9714_subdev_cleanup(dw9714_dev);
198
199         return 0;
200 }
201
202 /*
203  * This function sets the vcm position, so it consumes least current
204  * The lens position is gradually moved in units of DW9714_CTRL_STEPS,
205  * to make the movements smoothly.
206  */
207 static int __maybe_unused dw9714_vcm_suspend(struct device *dev)
208 {
209         struct i2c_client *client = to_i2c_client(dev);
210         struct v4l2_subdev *sd = i2c_get_clientdata(client);
211         struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd);
212         int ret, val;
213
214         for (val = dw9714_dev->current_val & ~(DW9714_CTRL_STEPS - 1);
215              val >= 0; val -= DW9714_CTRL_STEPS) {
216                 ret = dw9714_i2c_write(client,
217                                        DW9714_VAL(val, DW9714_DEFAULT_S));
218                 if (ret)
219                         dev_err_once(dev, "%s I2C failure: %d", __func__, ret);
220                 usleep_range(DW9714_CTRL_DELAY_US, DW9714_CTRL_DELAY_US + 10);
221         }
222         return 0;
223 }
224
225 /*
226  * This function sets the vcm position to the value set by the user
227  * through v4l2_ctrl_ops s_ctrl handler
228  * The lens position is gradually moved in units of DW9714_CTRL_STEPS,
229  * to make the movements smoothly.
230  */
231 static int  __maybe_unused dw9714_vcm_resume(struct device *dev)
232 {
233         struct i2c_client *client = to_i2c_client(dev);
234         struct v4l2_subdev *sd = i2c_get_clientdata(client);
235         struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd);
236         int ret, val;
237
238         for (val = dw9714_dev->current_val % DW9714_CTRL_STEPS;
239              val < dw9714_dev->current_val + DW9714_CTRL_STEPS - 1;
240              val += DW9714_CTRL_STEPS) {
241                 ret = dw9714_i2c_write(client,
242                                        DW9714_VAL(val, DW9714_DEFAULT_S));
243                 if (ret)
244                         dev_err_ratelimited(dev, "%s I2C failure: %d",
245                                                 __func__, ret);
246                 usleep_range(DW9714_CTRL_DELAY_US, DW9714_CTRL_DELAY_US + 10);
247         }
248
249         return 0;
250 }
251
252 static const struct i2c_device_id dw9714_id_table[] = {
253         { DW9714_NAME, 0 },
254         { { 0 } }
255 };
256 MODULE_DEVICE_TABLE(i2c, dw9714_id_table);
257
258 static const struct of_device_id dw9714_of_table[] = {
259         { .compatible = "dongwoon,dw9714" },
260         { { 0 } }
261 };
262 MODULE_DEVICE_TABLE(of, dw9714_of_table);
263
264 static const struct dev_pm_ops dw9714_pm_ops = {
265         SET_SYSTEM_SLEEP_PM_OPS(dw9714_vcm_suspend, dw9714_vcm_resume)
266         SET_RUNTIME_PM_OPS(dw9714_vcm_suspend, dw9714_vcm_resume, NULL)
267 };
268
269 static struct i2c_driver dw9714_i2c_driver = {
270         .driver = {
271                 .name = DW9714_NAME,
272                 .pm = &dw9714_pm_ops,
273                 .of_match_table = dw9714_of_table,
274         },
275         .probe_new = dw9714_probe,
276         .remove = dw9714_remove,
277         .id_table = dw9714_id_table,
278 };
279
280 module_i2c_driver(dw9714_i2c_driver);
281
282 MODULE_AUTHOR("Tianshu Qiu <tian.shu.qiu@intel.com>");
283 MODULE_AUTHOR("Jian Xu Zheng <jian.xu.zheng@intel.com>");
284 MODULE_AUTHOR("Yuning Pu <yuning.pu@intel.com>");
285 MODULE_AUTHOR("Jouni Ukkonen <jouni.ukkonen@intel.com>");
286 MODULE_AUTHOR("Tommi Franttila <tommi.franttila@intel.com>");
287 MODULE_DESCRIPTION("DW9714 VCM driver");
288 MODULE_LICENSE("GPL v2");