blob: c06a1b3b4369e3da80423ca48a4f6266f4eaff14 [file] [log] [blame]
Viswanadha Raju Thotakura7208eb72017-02-26 16:56:34 -08001/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include "cam_sensor_dev.h"
14#include "cam_req_mgr_dev.h"
15#include "cam_sensor_soc.h"
16#include "cam_sensor_core.h"
17
18static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd,
19 unsigned int cmd, void *arg)
20{
21 int rc = 0;
22 struct cam_sensor_ctrl_t *s_ctrl =
23 v4l2_get_subdevdata(sd);
24
25 switch (cmd) {
26 case VIDIOC_CAM_CONTROL:
27 rc = cam_sensor_driver_cmd(s_ctrl, arg);
28 break;
29 default:
30 pr_err("%s:%d Invalid ioctl cmd: %d\n",
31 __func__, __LINE__, cmd);
32 rc = -EINVAL;
33 break;
34 }
35 return rc;
36}
37
38static int32_t cam_sensor_driver_i2c_probe(struct i2c_client *client,
39 const struct i2c_device_id *id)
40{
41 int32_t rc = 0;
42 struct cam_sensor_ctrl_t *s_ctrl;
43
44 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
45 pr_err("%s %s :Error: i2c_check_functionality failed\n",
46 __func__, client->name);
47 return -EFAULT;
48 }
49
50 /* Create sensor control structure */
51 s_ctrl = kzalloc(sizeof(*s_ctrl), GFP_KERNEL);
52 if (!s_ctrl)
53 return -ENOMEM;
54
55 i2c_set_clientdata(client, s_ctrl);
56
57 /* Initialize sensor device type */
58 s_ctrl->of_node = client->dev.of_node;
59 s_ctrl->io_master_info.master_type = I2C_MASTER;
60
61 rc = cam_sensor_parse_dt(s_ctrl);
62 if (rc < 0) {
63 pr_err("%s:%d :Error: cam_sensor_parse_dt rc %d",
64 __func__, __LINE__, rc);
65 goto free_s_ctrl;
66 }
67
68 return rc;
69free_s_ctrl:
70 kfree(s_ctrl);
71 return rc;
72}
73
74static int cam_sensor_platform_remove(struct platform_device *pdev)
75{
76 struct cam_sensor_ctrl_t *s_ctrl;
77
78 s_ctrl = platform_get_drvdata(pdev);
79 if (!s_ctrl) {
80 pr_err("%s: sensor device is NULL\n", __func__);
81 return 0;
82 }
83
84 kfree(s_ctrl->i2c_data.per_frame);
85 devm_kfree(&pdev->dev, s_ctrl);
86
87 return 0;
88}
89
90static int cam_sensor_driver_i2c_remove(struct i2c_client *client)
91{
92 struct cam_sensor_ctrl_t *s_ctrl = i2c_get_clientdata(client);
93
94 if (!s_ctrl) {
95 pr_err("%s: sensor device is NULL\n", __func__);
96 return 0;
97 }
98
99 kfree(s_ctrl->i2c_data.per_frame);
100 kfree(s_ctrl);
101
102 return 0;
103}
104
105#ifdef CONFIG_COMPAT
106static long cam_sensor_init_subdev_do_ioctl(struct v4l2_subdev *sd,
107 unsigned int cmd, unsigned long arg)
108{
109 struct cam_control cmd_data;
110 int32_t rc = 0;
111
112 if (copy_from_user(&cmd_data, (void __user *)arg,
113 sizeof(cmd_data))) {
114 pr_err("Failed to copy from user_ptr=%pK size=%zu\n",
115 (void __user *)arg, sizeof(cmd_data));
116 return -EFAULT;
117 }
118
119 switch (cmd) {
120 case VIDIOC_CAM_CONTROL:
121 rc = cam_sensor_subdev_ioctl(sd, cmd, &cmd_data);
122 if (rc < 0)
123 pr_err("%s:%d cam_sensor_subdev_ioctl failed\n",
124 __func__, __LINE__);
125 break;
126 default:
127 pr_err("%s:%d Invalid compat ioctl cmd_type: %d\n",
128 __func__, __LINE__, cmd);
129 rc = -EINVAL;
130 }
131
132 if (!rc) {
133 if (copy_to_user((void __user *)arg, &cmd_data,
134 sizeof(cmd_data))) {
135 pr_err("Failed to copy to user_ptr=%pK size=%zu\n",
136 (void __user *)arg, sizeof(cmd_data));
137 rc = -EFAULT;
138 }
139 }
140 return rc;
141}
142
143#endif
144
145static struct v4l2_subdev_core_ops cam_sensor_subdev_core_ops = {
146 .ioctl = cam_sensor_subdev_ioctl,
147#ifdef CONFIG_COMPAT
148 .compat_ioctl32 = cam_sensor_init_subdev_do_ioctl,
149#endif
150 .s_power = cam_sensor_power,
151};
152
153static struct v4l2_subdev_ops cam_sensor_subdev_ops = {
154 .core = &cam_sensor_subdev_core_ops,
155};
156
157static const struct v4l2_subdev_internal_ops cam_sensor_internal_ops;
158
159static const struct of_device_id cam_sensor_driver_dt_match[] = {
160 {.compatible = "qcom,cam-sensor"},
161 {}
162};
163
164static int32_t cam_sensor_driver_platform_probe(
165 struct platform_device *pdev)
166{
167 int32_t rc = 0, i = 0;
168 struct cam_sensor_ctrl_t *s_ctrl = NULL;
Alok Pandey01b1b352017-06-25 20:38:54 +0530169 struct cam_hw_soc_info *soc_info = NULL;
Viswanadha Raju Thotakura7208eb72017-02-26 16:56:34 -0800170
171 /* Create sensor control structure */
172 s_ctrl = devm_kzalloc(&pdev->dev,
173 sizeof(struct cam_sensor_ctrl_t), GFP_KERNEL);
174 if (!s_ctrl)
175 return -ENOMEM;
176
Alok Pandey01b1b352017-06-25 20:38:54 +0530177 soc_info = &s_ctrl->soc_info;
178 soc_info->pdev = pdev;
179
Viswanadha Raju Thotakura7208eb72017-02-26 16:56:34 -0800180 /* Initialize sensor device type */
181 s_ctrl->of_node = pdev->dev.of_node;
182 s_ctrl->is_probe_succeed = 0;
183
184 /*fill in platform device*/
185 s_ctrl->pdev = pdev;
186
187 s_ctrl->io_master_info.master_type = CCI_MASTER;
188
189 rc = cam_sensor_parse_dt(s_ctrl);
190 if (rc < 0) {
191 pr_err("failed: cam_sensor_parse_dt rc %d", rc);
192 goto free_s_ctrl;
193 }
194
195 /* Fill platform device id*/
Alok Pandey01b1b352017-06-25 20:38:54 +0530196 pdev->id = soc_info->index;
Viswanadha Raju Thotakura7208eb72017-02-26 16:56:34 -0800197
198 s_ctrl->v4l2_dev_str.internal_ops =
199 &cam_sensor_internal_ops;
200 s_ctrl->v4l2_dev_str.ops =
201 &cam_sensor_subdev_ops;
202 strlcpy(s_ctrl->device_name, CAMX_SENSOR_DEV_NAME,
203 sizeof(s_ctrl->device_name));
204 s_ctrl->v4l2_dev_str.name =
205 s_ctrl->device_name;
206 s_ctrl->v4l2_dev_str.sd_flags =
207 (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS);
208 s_ctrl->v4l2_dev_str.ent_function =
209 CAM_SENSOR_DEVICE_TYPE;
210 s_ctrl->v4l2_dev_str.token = s_ctrl;
211
212 rc = cam_register_subdev(&(s_ctrl->v4l2_dev_str));
213 if (rc < 0) {
214 pr_err("%s:%d :ERROR: Fail with cam_register_subdev\n",
215 __func__, __LINE__);
216 goto free_s_ctrl;
217 }
218
219 s_ctrl->i2c_data.per_frame =
220 (struct i2c_settings_array *)
221 kzalloc(sizeof(struct i2c_settings_array) *
222 MAX_PER_FRAME_ARRAY, GFP_KERNEL);
223 if (s_ctrl->i2c_data.per_frame == NULL) {
224 rc = -ENOMEM;
225 goto free_s_ctrl;
226 }
227
228 INIT_LIST_HEAD(&(s_ctrl->i2c_data.init_settings.list_head));
229
230 for (i = 0; i < MAX_PER_FRAME_ARRAY; i++)
231 INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head));
232
233 s_ctrl->bridge_intf.device_hdl = -1;
234 s_ctrl->bridge_intf.ops.get_dev_info = cam_sensor_publish_dev_info;
235 s_ctrl->bridge_intf.ops.link_setup = cam_sensor_establish_link;
236 s_ctrl->bridge_intf.ops.apply_req = cam_sensor_apply_request;
Vivek Veenamd5e39cd2017-05-23 15:48:03 +0530237 s_ctrl->bridge_intf.ops.flush_req = cam_sensor_flush_request;
Viswanadha Raju Thotakura7208eb72017-02-26 16:56:34 -0800238
239 s_ctrl->sensordata->power_info.dev = &pdev->dev;
240 platform_set_drvdata(pdev, s_ctrl);
241 v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), s_ctrl);
242
243 return rc;
244free_s_ctrl:
245 devm_kfree(&pdev->dev, s_ctrl);
246 return rc;
247}
248
249MODULE_DEVICE_TABLE(of, cam_sensor_driver_dt_match);
250
251static struct platform_driver cam_sensor_platform_driver = {
252 .probe = cam_sensor_driver_platform_probe,
253 .driver = {
254 .name = "qcom,camera",
255 .owner = THIS_MODULE,
256 .of_match_table = cam_sensor_driver_dt_match,
257 },
258 .remove = cam_sensor_platform_remove,
259};
260
261static const struct i2c_device_id i2c_id[] = {
262 {SENSOR_DRIVER_I2C, (kernel_ulong_t)NULL},
263 { }
264};
265
266static struct i2c_driver cam_sensor_driver_i2c = {
267 .id_table = i2c_id,
268 .probe = cam_sensor_driver_i2c_probe,
269 .remove = cam_sensor_driver_i2c_remove,
270 .driver = {
271 .name = SENSOR_DRIVER_I2C,
272 },
273};
274
275static int __init cam_sensor_driver_init(void)
276{
277 int32_t rc = 0;
278
279 rc = platform_driver_register(&cam_sensor_platform_driver);
280 if (rc)
281 pr_err("%s platform_driver_register failed rc = %d",
282 __func__, rc);
283 rc = i2c_add_driver(&cam_sensor_driver_i2c);
284 if (rc)
285 pr_err("%s i2c_add_driver failed rc = %d", __func__, rc);
286
287 return rc;
288}
289
290static void __exit cam_sensor_driver_exit(void)
291{
292 platform_driver_unregister(&cam_sensor_platform_driver);
293 i2c_del_driver(&cam_sensor_driver_i2c);
294}
295
296module_init(cam_sensor_driver_init);
297module_exit(cam_sensor_driver_exit);
298MODULE_DESCRIPTION("cam_sensor_driver");
299MODULE_LICENSE("GPL v2");