blob: 9f16e93f5d48365bd507d09c2407b65e7dd7d4ce [file] [log] [blame]
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001/* 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 <linux/kernel.h>
14#include "cam_sensor_util.h"
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -070015
16#define CAM_SENSOR_PINCTRL_STATE_SLEEP "cam_suspend"
17#define CAM_SENSOR_PINCTRL_STATE_DEFAULT "cam_default"
18
19#define VALIDATE_VOLTAGE(min, max, config_val) ((config_val) && \
20 (config_val >= min) && (config_val <= max))
21
22#undef CDBG
23#define CDBG(fmt, args...) pr_debug(fmt, ##args)
24
25static struct i2c_settings_list*
26 cam_sensor_get_i2c_ptr(struct i2c_settings_array *i2c_reg_settings,
27 uint32_t size)
28{
29 struct i2c_settings_list *tmp;
30
31 tmp = (struct i2c_settings_list *)
32 kzalloc(sizeof(struct i2c_settings_list), GFP_KERNEL);
33
34 if (tmp != NULL)
35 list_add_tail(&(tmp->list),
36 &(i2c_reg_settings->list_head));
37 else
38 return NULL;
39
40 tmp->i2c_settings.reg_setting = (struct cam_sensor_i2c_reg_array *)
41 kzalloc(sizeof(struct cam_sensor_i2c_reg_array) *
42 size, GFP_KERNEL);
43 if (tmp->i2c_settings.reg_setting == NULL) {
44 list_del(&(tmp->list));
45 kfree(tmp);
46 return NULL;
47 }
48 tmp->i2c_settings.size = size;
49
50 return tmp;
51}
52
53int32_t delete_request(struct i2c_settings_array *i2c_array)
54{
55 struct i2c_settings_list *i2c_list = NULL, *i2c_next = NULL;
56 int32_t rc = 0;
57
58 if (i2c_array == NULL) {
59 pr_err("%s:%d ::FATAL:: Invalid argument\n",
60 __func__, __LINE__);
61 return -EINVAL;
62 }
63
64 list_for_each_entry_safe(i2c_list, i2c_next,
65 &(i2c_array->list_head), list) {
66 kfree(i2c_list->i2c_settings.reg_setting);
67 list_del(&(i2c_list->list));
68 kfree(i2c_list);
69 }
70 INIT_LIST_HEAD(&(i2c_array->list_head));
71 i2c_array->is_settings_valid = 0;
72
73 return rc;
74}
75
76int32_t cam_sensor_handle_delay(
77 uint32_t **cmd_buf,
78 uint16_t generic_op_code,
79 struct i2c_settings_array *i2c_reg_settings,
80 uint32_t offset, uint32_t *byte_cnt,
81 struct list_head *list_ptr)
82{
83 int32_t rc = 0;
84 struct cam_cmd_unconditional_wait *cmd_uncond_wait =
85 (struct cam_cmd_unconditional_wait *) *cmd_buf;
86 struct i2c_settings_list *i2c_list = NULL;
87
88 if (i2c_list == NULL) {
89 pr_err("%s:%d Invalid list ptr\n",
90 __func__, __LINE__);
91 return -EINVAL;
92 }
93
94 if (offset > 0) {
95 i2c_list =
96 list_entry(list_ptr, struct i2c_settings_list, list);
97 if (generic_op_code ==
98 CAMERA_SENSOR_WAIT_OP_HW_UCND)
99 i2c_list->i2c_settings.
100 reg_setting[offset - 1].delay =
101 cmd_uncond_wait->delay;
102 else
103 i2c_list->i2c_settings.delay =
104 cmd_uncond_wait->delay;
105 (*cmd_buf) +=
106 sizeof(
107 struct cam_cmd_unconditional_wait) / sizeof(uint32_t);
108 (*byte_cnt) +=
109 sizeof(
110 struct cam_cmd_unconditional_wait);
111 } else {
112 pr_err("%s: %d Error: Delay Rxed Before any buffer: %d\n",
113 __func__, __LINE__, offset);
114 return -EINVAL;
115 }
116
117 return rc;
118}
119
120int32_t cam_sensor_handle_poll(
121 uint32_t **cmd_buf,
122 struct i2c_settings_array *i2c_reg_settings,
123 uint32_t *byte_cnt, int32_t *offset,
124 struct list_head **list_ptr)
125{
126 struct i2c_settings_list *i2c_list;
127 int32_t rc = 0;
128 struct cam_cmd_conditional_wait *cond_wait
129 = (struct cam_cmd_conditional_wait *) *cmd_buf;
130
131 i2c_list =
132 cam_sensor_get_i2c_ptr(i2c_reg_settings, 1);
133 if (!i2c_list || !i2c_list->i2c_settings.reg_setting) {
134 pr_err("%s: %d Failed in allocating mem for list\n",
135 __func__, __LINE__);
136 return -ENOMEM;
137 }
138
139 i2c_list->op_code = CAM_SENSOR_I2C_POLL;
140 i2c_list->i2c_settings.data_type =
141 cond_wait->data_type;
142 i2c_list->i2c_settings.addr_type =
143 cond_wait->addr_type;
144 i2c_list->i2c_settings.reg_setting->reg_addr =
145 cond_wait->reg_addr;
146 i2c_list->i2c_settings.reg_setting->reg_data =
147 cond_wait->reg_data;
148 i2c_list->i2c_settings.reg_setting->delay =
149 cond_wait->timeout;
150
151 (*cmd_buf) += sizeof(struct cam_cmd_conditional_wait) /
152 sizeof(uint32_t);
153 (*byte_cnt) += sizeof(struct cam_cmd_conditional_wait);
154
155 (*offset) += 1;
156 *list_ptr = &(i2c_list->list);
157
158 return rc;
159}
160
161int32_t cam_sensor_handle_random_write(
162 struct cam_cmd_i2c_random_wr *cam_cmd_i2c_random_wr,
163 struct i2c_settings_array *i2c_reg_settings,
164 uint16_t *cmd_length_in_bytes, int32_t *offset,
165 struct list_head **list)
166{
167 struct i2c_settings_list *i2c_list;
168 int32_t rc = 0, cnt;
169
170 i2c_list = cam_sensor_get_i2c_ptr(i2c_reg_settings,
171 cam_cmd_i2c_random_wr->header.count);
172 if (i2c_list == NULL ||
173 i2c_list->i2c_settings.reg_setting == NULL) {
174 pr_err("%s: %d Failed in allocating i2c_list\n",
175 __func__, __LINE__);
176 return -ENOMEM;
177 }
178
179 *cmd_length_in_bytes = (sizeof(struct i2c_rdwr_header) +
180 sizeof(struct i2c_random_wr_payload) *
181 (cam_cmd_i2c_random_wr->header.count));
182 i2c_list->op_code = CAM_SENSOR_I2C_WRITE_RANDOM;
183 i2c_list->i2c_settings.addr_type =
184 cam_cmd_i2c_random_wr->header.addr_type;
185 i2c_list->i2c_settings.data_type =
186 cam_cmd_i2c_random_wr->header.data_type;
187
188 for (cnt = 0; cnt < (cam_cmd_i2c_random_wr->header.count);
189 cnt++) {
190 i2c_list->i2c_settings.reg_setting[cnt].reg_addr =
191 cam_cmd_i2c_random_wr->
192 random_wr_payload[cnt].reg_addr;
193 i2c_list->i2c_settings.
194 reg_setting[cnt].reg_data =
195 cam_cmd_i2c_random_wr->
196 random_wr_payload[cnt].reg_data;
197 i2c_list->i2c_settings.
198 reg_setting[cnt].data_mask = 0;
199 }
200 (*offset) += cnt;
201 *list = &(i2c_list->list);
202
203 return rc;
204}
205
206/**
207 * Name : cam_sensor_i2c_pkt_parser
208 * Description : Parse CSL CCI packet and apply register settings
209 * Parameters : s_ctrl input/output sub_device
210 * arg input cam_control
211 * Description :
212 * Handle multiple I2C RD/WR and WAIT cmd formats in one command
213 * buffer, for example, a command buffer of m x RND_WR + 1 x HW_
214 * WAIT + n x RND_WR with num_cmd_buf = 1. Do not exepect RD/WR
215 * with different cmd_type and op_code in one command buffer.
216 */
217int cam_sensor_i2c_pkt_parser(struct i2c_settings_array *i2c_reg_settings,
218 struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers)
219{
220 int16_t rc = 0, i = 0;
221 size_t len_of_buff = 0;
222 uint64_t generic_ptr;
223
224 for (i = 0; i < num_cmd_buffers; i++) {
225 uint32_t *cmd_buf = NULL;
226 struct common_header *cmm_hdr;
227 uint16_t generic_op_code;
228 uint32_t byte_cnt = 0;
229 uint32_t j = 0;
230 struct list_head *list = NULL;
231
232 /*
233 * It is not expected the same settings to
234 * be spread across multiple cmd buffers
235 */
236
237 CDBG("%s:%d Total cmd Buf in Bytes: %d\n", __func__,
238 __LINE__, cmd_desc[i].length);
239
240 if (!cmd_desc[i].length)
241 continue;
242
243 rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
244 (uint64_t *)&generic_ptr, &len_of_buff);
245 cmd_buf = (uint32_t *)generic_ptr;
246 if (rc < 0) {
247 pr_err("%s:%d Failed in getting cmd hdl: %d Err: %d Buffer Len: %ld\n",
248 __func__, __LINE__,
249 cmd_desc[i].mem_handle, rc,
250 len_of_buff);
251 return rc;
252 }
253 cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
254
255 while (byte_cnt < cmd_desc[i].length) {
256 cmm_hdr = (struct common_header *)cmd_buf;
257 generic_op_code = cmm_hdr->third_byte;
258 switch (cmm_hdr->cmd_type) {
259 case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR: {
260 uint16_t cmd_length_in_bytes = 0;
261 struct cam_cmd_i2c_random_wr
262 *cam_cmd_i2c_random_wr =
263 (struct cam_cmd_i2c_random_wr *)cmd_buf;
264
265 rc = cam_sensor_handle_random_write(
266 cam_cmd_i2c_random_wr,
267 i2c_reg_settings,
268 &cmd_length_in_bytes, &j, &list);
269 if (rc < 0) {
270 pr_err("%s:%d :Error: Failed in random read %d\n",
271 __func__, __LINE__, rc);
272 return rc;
273 }
274
275 cmd_buf += cmd_length_in_bytes /
276 sizeof(uint32_t);
277 byte_cnt += cmd_length_in_bytes;
278 break;
279 }
280 case CAMERA_SENSOR_CMD_TYPE_WAIT: {
281 if (generic_op_code ==
282 CAMERA_SENSOR_WAIT_OP_HW_UCND ||
283 generic_op_code ==
284 CAMERA_SENSOR_WAIT_OP_SW_UCND) {
285
286 rc = cam_sensor_handle_delay(
287 &cmd_buf, generic_op_code,
288 i2c_reg_settings, j, &byte_cnt,
289 list);
290 if (rc < 0) {
291 pr_err("%s:%d :Error: Failed in handling delay %d\n",
292 __func__, __LINE__, rc);
293 return rc;
294 }
295
296 } else if (generic_op_code ==
297 CAMERA_SENSOR_WAIT_OP_COND) {
298 rc = cam_sensor_handle_poll(
299 &cmd_buf, i2c_reg_settings,
300 &byte_cnt, &j, &list);
301 if (rc < 0) {
302 pr_err("%s:%d :Error: Failed in random read %d\n",
303 __func__, __LINE__, rc);
304 return rc;
305 }
306 } else {
307 pr_err("%s: %d Wrong Wait Command: %d\n",
308 __func__, __LINE__,
309 generic_op_code);
310 return -EINVAL;
311 }
312 break;
313 }
314 default:
315 pr_err("%s:%d Invalid Command Type:%d\n",
316 __func__, __LINE__, cmm_hdr->cmd_type);
317 return -EINVAL;
318 }
319 }
320 i2c_reg_settings->is_settings_valid = 1;
321 }
322
323 return rc;
324}
325
Alok Pandey01b1b352017-06-25 20:38:54 +0530326int32_t msm_camera_fill_vreg_params(
327 struct cam_hw_soc_info *soc_info,
328 struct cam_sensor_power_setting *power_setting,
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700329 uint16_t power_setting_size)
330{
331 int32_t rc = 0, j = 0, i = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +0530332 uint32_t num_vreg;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700333
334 /* Validate input parameters */
Alok Pandey01b1b352017-06-25 20:38:54 +0530335 if (!soc_info || !power_setting) {
336 pr_err("%s:%d failed: soc_info %pK power_setting %pK", __func__,
337 __LINE__, soc_info, power_setting);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700338 return -EINVAL;
339 }
340
Alok Pandey01b1b352017-06-25 20:38:54 +0530341 num_vreg = soc_info->num_rgltr;
342
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700343 if (num_vreg <= 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530344 pr_err("%s:%d failed: num_vreg %d", __func__, __LINE__,
345 num_vreg);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700346 return -EINVAL;
347 }
348
Alok Pandey01b1b352017-06-25 20:38:54 +0530349
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700350 for (i = 0; i < power_setting_size; i++) {
351 switch (power_setting[i].seq_type) {
352 case SENSOR_VDIG:
353 for (j = 0; j < num_vreg; j++) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530354 if (!strcmp(soc_info->rgltr_name[j],
355 "cam_vdig")) {
356
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700357 CDBG("%s:%d i %d j %d cam_vdig\n",
358 __func__, __LINE__, i, j);
359 power_setting[i].seq_val = j;
Alok Pandey01b1b352017-06-25 20:38:54 +0530360
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700361 if (VALIDATE_VOLTAGE(
Alok Pandey01b1b352017-06-25 20:38:54 +0530362 soc_info->rgltr_min_volt[j],
363 soc_info->rgltr_max_volt[j],
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700364 power_setting[i].config_val)) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530365 soc_info->rgltr_min_volt[j] =
366 soc_info->rgltr_max_volt[j] =
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700367 power_setting[i].config_val;
368 }
369 break;
370 }
371 }
372 if (j == num_vreg)
373 power_setting[i].seq_val = INVALID_VREG;
374 break;
375
376 case SENSOR_VIO:
377 for (j = 0; j < num_vreg; j++) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530378
379 if (!strcmp(soc_info->rgltr_name[j],
380 "cam_vio")) {
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700381 CDBG("%s:%d i %d j %d cam_vio\n",
382 __func__, __LINE__, i, j);
383 power_setting[i].seq_val = j;
Alok Pandey01b1b352017-06-25 20:38:54 +0530384
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700385 if (VALIDATE_VOLTAGE(
Alok Pandey01b1b352017-06-25 20:38:54 +0530386 soc_info->rgltr_min_volt[j],
387 soc_info->rgltr_max_volt[j],
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700388 power_setting[i].config_val)) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530389 soc_info->rgltr_min_volt[j] =
390 soc_info->rgltr_max_volt[j] =
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700391 power_setting[i].config_val;
392 }
393 break;
394 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530395
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700396 }
397 if (j == num_vreg)
398 power_setting[i].seq_val = INVALID_VREG;
399 break;
400
401 case SENSOR_VANA:
402 for (j = 0; j < num_vreg; j++) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530403
404 if (!strcmp(soc_info->rgltr_name[j],
405 "cam_vana")) {
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700406 CDBG("%s:%d i %d j %d cam_vana\n",
407 __func__, __LINE__, i, j);
408 power_setting[i].seq_val = j;
Alok Pandey01b1b352017-06-25 20:38:54 +0530409
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700410 if (VALIDATE_VOLTAGE(
Alok Pandey01b1b352017-06-25 20:38:54 +0530411 soc_info->rgltr_min_volt[j],
412 soc_info->rgltr_max_volt[j],
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700413 power_setting[i].config_val)) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530414 soc_info->rgltr_min_volt[j] =
415 soc_info->rgltr_max_volt[j] =
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700416 power_setting[i].config_val;
417 }
418 break;
419 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530420
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700421 }
422 if (j == num_vreg)
423 power_setting[i].seq_val = INVALID_VREG;
424 break;
425
426 case SENSOR_VAF:
427 for (j = 0; j < num_vreg; j++) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530428
429 if (!strcmp(soc_info->rgltr_name[j],
430 "cam_vaf")) {
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700431 CDBG("%s:%d i %d j %d cam_vaf\n",
432 __func__, __LINE__, i, j);
433 power_setting[i].seq_val = j;
Alok Pandey01b1b352017-06-25 20:38:54 +0530434
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700435 if (VALIDATE_VOLTAGE(
Alok Pandey01b1b352017-06-25 20:38:54 +0530436 soc_info->rgltr_min_volt[j],
437 soc_info->rgltr_max_volt[j],
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700438 power_setting[i].config_val)) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530439 soc_info->rgltr_min_volt[j] =
440 soc_info->rgltr_max_volt[j] =
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700441 power_setting[i].config_val;
442 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530443
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700444 break;
445 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530446
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700447 }
448 if (j == num_vreg)
449 power_setting[i].seq_val = INVALID_VREG;
450 break;
451
452 case SENSOR_CUSTOM_REG1:
453 for (j = 0; j < num_vreg; j++) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530454
455 if (!strcmp(soc_info->rgltr_name[j],
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700456 "cam_v_custom1")) {
457 CDBG("%s:%d i %d j %d cam_vcustom1\n",
458 __func__, __LINE__, i, j);
459 power_setting[i].seq_val = j;
Alok Pandey01b1b352017-06-25 20:38:54 +0530460
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700461 if (VALIDATE_VOLTAGE(
Alok Pandey01b1b352017-06-25 20:38:54 +0530462 soc_info->rgltr_min_volt[j],
463 soc_info->rgltr_max_volt[j],
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700464 power_setting[i].config_val)) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530465 soc_info->rgltr_min_volt[j] =
466 soc_info->rgltr_max_volt[j] =
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700467 power_setting[i].config_val;
468 }
469 break;
470 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530471
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700472 }
473 if (j == num_vreg)
474 power_setting[i].seq_val = INVALID_VREG;
475 break;
476 case SENSOR_CUSTOM_REG2:
477 for (j = 0; j < num_vreg; j++) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530478
479 if (!strcmp(soc_info->rgltr_name[j],
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700480 "cam_v_custom2")) {
481 CDBG("%s:%d i %d j %d cam_vcustom2\n",
482 __func__, __LINE__, i, j);
483 power_setting[i].seq_val = j;
Alok Pandey01b1b352017-06-25 20:38:54 +0530484
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700485 if (VALIDATE_VOLTAGE(
Alok Pandey01b1b352017-06-25 20:38:54 +0530486 soc_info->rgltr_min_volt[j],
487 soc_info->rgltr_max_volt[j],
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700488 power_setting[i].config_val)) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530489 soc_info->rgltr_min_volt[j] =
490 soc_info->rgltr_max_volt[j] =
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700491 power_setting[i].config_val;
492 }
493 break;
494 }
495 }
496 if (j == num_vreg)
497 power_setting[i].seq_val = INVALID_VREG;
498 break;
499
500 default: {
501 pr_err("%s:%d invalid seq_val %d\n", __func__,
502 __LINE__, power_setting[i].seq_val);
503 break;
504 }
505 }
506 }
507
508 return rc;
509}
510
Alok Pandey01b1b352017-06-25 20:38:54 +0530511int cam_sensor_util_request_gpio_table(
512 struct cam_hw_soc_info *soc_info, int gpio_en)
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700513{
Alok Pandey01b1b352017-06-25 20:38:54 +0530514 int rc = 0, i = 0;
515 uint8_t size = 0;
516 struct cam_soc_gpio_data *gpio_conf =
517 soc_info->gpio_data;
518 struct gpio *gpio_tbl = gpio_conf->cam_gpio_req_tbl;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700519
Alok Pandey01b1b352017-06-25 20:38:54 +0530520 size = gpio_conf->cam_gpio_req_tbl_size;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700521
Alok Pandey01b1b352017-06-25 20:38:54 +0530522 if (gpio_conf->cam_gpio_common_tbl_size <= 0) {
523 pr_info("%s:%d No GPIO entry\n", __func__, __LINE__);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700524 return 0;
525 }
526
Alok Pandey01b1b352017-06-25 20:38:54 +0530527 if (!gpio_tbl || !size) {
528 pr_err("%s:%d invalid gpio_tbl %pK / size %d\n", __func__,
529 __LINE__, gpio_tbl, size);
530 return -EINVAL;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700531 }
532
Alok Pandey01b1b352017-06-25 20:38:54 +0530533 for (i = 0; i < size; i++) {
534 CDBG("%s:%d i %d, gpio %d dir %ld\n", __func__, __LINE__, i,
535 gpio_tbl[i].gpio, gpio_tbl[i].flags);
536 }
537
538 if (gpio_en) {
539 for (i = 0; i < size; i++) {
540 rc = gpio_request_one(gpio_tbl[i].gpio,
541 gpio_tbl[i].flags, gpio_tbl[i].label);
542 if (rc) {
543 /*
544 * After GPIO request fails, contine to
545 * apply new gpios, outout a error message
546 * for driver bringup debug
547 */
548 pr_err("%s:%d gpio %d:%s request fails\n",
549 __func__, __LINE__,
550 gpio_tbl[i].gpio, gpio_tbl[i].label);
551 }
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700552 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530553 } else {
554 gpio_free_array(gpio_tbl, size);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700555 }
556
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700557 return rc;
558}
559
Alok Pandey01b1b352017-06-25 20:38:54 +0530560
561int cam_sensor_util_init_gpio_pin_tbl(
562 struct cam_hw_soc_info *soc_info,
563 struct msm_camera_gpio_num_info **pgpio_num_info)
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700564{
565 int rc = 0, val = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +0530566 uint32_t gpio_array_size;
567 struct platform_device *pdev = NULL;
568 struct device_node *of_node = NULL;
569 struct cam_soc_gpio_data *gconf = NULL;
570 struct msm_camera_gpio_num_info *gpio_num_info = NULL;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700571
Alok Pandey01b1b352017-06-25 20:38:54 +0530572 pdev = soc_info->pdev;
573 of_node = pdev->dev.of_node;
574
575 gconf = soc_info->gpio_data;
576 if (!gconf) {
577 pr_err("%s:%d No gpio_common_table is found\n",
578 __func__, __LINE__);
579 return -EINVAL;
580 }
581
582 if (!gconf->cam_gpio_common_tbl) {
583 pr_err("%s:%d gpio_common_table is not initialized\n",
584 __func__, __LINE__);
585 return -EINVAL;
586 }
587
588 gpio_array_size = gconf->cam_gpio_common_tbl_size;
589
590 if (!gpio_array_size) {
591 pr_err("%s:%d invalid size of gpio table\n",
592 __func__, __LINE__);
593 return -EINVAL;
594 }
595
596 *pgpio_num_info = kzalloc(sizeof(struct msm_camera_gpio_num_info),
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700597 GFP_KERNEL);
Alok Pandey01b1b352017-06-25 20:38:54 +0530598 if (!*pgpio_num_info)
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700599 return -ENOMEM;
Alok Pandey01b1b352017-06-25 20:38:54 +0530600 gpio_num_info = *pgpio_num_info;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700601
Alok Pandey01b1b352017-06-25 20:38:54 +0530602 rc = of_property_read_u32(of_node, "gpio-vana", &val);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700603 if (rc != -EINVAL) {
604 if (rc < 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530605 pr_err("%s:%d read gpio-vana failed rc %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700606 __func__, __LINE__, rc);
607 goto free_gpio_info;
608 } else if (val >= gpio_array_size) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530609 pr_err("%s:%d gpio-vana invalid %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700610 __func__, __LINE__, val);
611 rc = -EINVAL;
612 goto free_gpio_info;
613 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530614 gpio_num_info->gpio_num[SENSOR_VANA] =
615 gconf->cam_gpio_common_tbl[val].gpio;
616 gpio_num_info->valid[SENSOR_VANA] = 1;
617
618 CDBG("%s:%d gpio-vana %d\n", __func__, __LINE__,
619 gpio_num_info->gpio_num[SENSOR_VANA]);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700620 }
621
Alok Pandey01b1b352017-06-25 20:38:54 +0530622 rc = of_property_read_u32(of_node, "gpio-vio", &val);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700623 if (rc != -EINVAL) {
624 if (rc < 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530625 pr_err("%s:%d read gpio-vio failed rc %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700626 __func__, __LINE__, rc);
627 goto free_gpio_info;
628 } else if (val >= gpio_array_size) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530629 pr_err("%s:%d gpio-vio invalid %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700630 __func__, __LINE__, val);
631 goto free_gpio_info;
632 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530633 gpio_num_info->gpio_num[SENSOR_VIO] =
634 gconf->cam_gpio_common_tbl[val].gpio;
635 gpio_num_info->valid[SENSOR_VIO] = 1;
636
637 CDBG("%s:%d gpio-vio %d\n", __func__, __LINE__,
638 gpio_num_info->gpio_num[SENSOR_VIO]);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700639 }
640
Alok Pandey01b1b352017-06-25 20:38:54 +0530641 rc = of_property_read_u32(of_node, "gpio-vaf", &val);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700642 if (rc != -EINVAL) {
643 if (rc < 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530644 pr_err("%s:%d read gpio-vaf failed rc %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700645 __func__, __LINE__, rc);
646 goto free_gpio_info;
647 } else if (val >= gpio_array_size) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530648 pr_err("%s:%d gpio-vaf invalid %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700649 __func__, __LINE__, val);
650 rc = -EINVAL;
651 goto free_gpio_info;
652 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530653 gpio_num_info->gpio_num[SENSOR_VAF] =
654 gconf->cam_gpio_common_tbl[val].gpio;
655 gpio_num_info->valid[SENSOR_VAF] = 1;
656
657 CDBG("%s:%d gpio-vaf %d\n", __func__, __LINE__,
658 gpio_num_info->gpio_num[SENSOR_VAF]);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700659 }
660
Alok Pandey01b1b352017-06-25 20:38:54 +0530661 rc = of_property_read_u32(of_node, "gpio-vdig", &val);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700662 if (rc != -EINVAL) {
663 if (rc < 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530664 pr_err("%s:%d read gpio-vdig failed rc %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700665 __func__, __LINE__, rc);
666 goto free_gpio_info;
667 } else if (val >= gpio_array_size) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530668 pr_err("%s:%d gpio-vdig invalid %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700669 __func__, __LINE__, val);
670 rc = -EINVAL;
671 goto free_gpio_info;
672 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530673 gpio_num_info->gpio_num[SENSOR_VDIG] =
674 gconf->cam_gpio_common_tbl[val].gpio;
675 gpio_num_info->valid[SENSOR_VDIG] = 1;
676
677 CDBG("%s:%d gpio-vdig %d\n", __func__, __LINE__,
678 gpio_num_info->gpio_num[SENSOR_VDIG]);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700679 }
680
Alok Pandey01b1b352017-06-25 20:38:54 +0530681 rc = of_property_read_u32(of_node, "gpio-reset", &val);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700682 if (rc != -EINVAL) {
683 if (rc < 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530684 pr_err("%s:%d read gpio-reset failed rc %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700685 __func__, __LINE__, rc);
686 goto free_gpio_info;
687 } else if (val >= gpio_array_size) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530688 pr_err("%s:%d gpio-reset invalid %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700689 __func__, __LINE__, val);
690 rc = -EINVAL;
691 goto free_gpio_info;
692 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530693 gpio_num_info->gpio_num[SENSOR_RESET] =
694 gconf->cam_gpio_common_tbl[val].gpio;
695 gpio_num_info->valid[SENSOR_RESET] = 1;
696
697 CDBG("%s:%d gpio-reset %d\n", __func__, __LINE__,
698 gpio_num_info->gpio_num[SENSOR_RESET]);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700699 }
700
Alok Pandey01b1b352017-06-25 20:38:54 +0530701 rc = of_property_read_u32(of_node, "gpio-standby", &val);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700702 if (rc != -EINVAL) {
703 if (rc < 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530704 pr_err("%s:%d read gpio-standby failed rc %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700705 __func__, __LINE__, rc);
706 goto free_gpio_info;
707 } else if (val >= gpio_array_size) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530708 pr_err("%s:%d gpio-standby invalid %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700709 __func__, __LINE__, val);
710 rc = -EINVAL;
711 goto free_gpio_info;
712 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530713 gpio_num_info->gpio_num[SENSOR_STANDBY] =
714 gconf->cam_gpio_common_tbl[val].gpio;
715 gpio_num_info->valid[SENSOR_STANDBY] = 1;
716
717 CDBG("%s:%d gpio-standby %d\n", __func__, __LINE__,
718 gpio_num_info->gpio_num[SENSOR_STANDBY]);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700719 }
720
Alok Pandey01b1b352017-06-25 20:38:54 +0530721 rc = of_property_read_u32(of_node, "gpio-af-pwdm", &val);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700722 if (rc != -EINVAL) {
723 if (rc < 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530724 pr_err("%s:%d read gpio-af-pwdm failed rc %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700725 __func__, __LINE__, rc);
726 goto free_gpio_info;
727 } else if (val >= gpio_array_size) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530728 pr_err("%s:%d gpio-af-pwdm invalid %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700729 __func__, __LINE__, val);
730 rc = -EINVAL;
731 goto free_gpio_info;
732 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530733 gpio_num_info->gpio_num[SENSOR_VAF_PWDM] =
734 gconf->cam_gpio_common_tbl[val].gpio;
735 gpio_num_info->valid[SENSOR_VAF_PWDM] = 1;
736
737 CDBG("%s:%d gpio-af-pwdm %d\n", __func__, __LINE__,
738 gpio_num_info->gpio_num[SENSOR_VAF_PWDM]);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700739 }
740
Alok Pandey01b1b352017-06-25 20:38:54 +0530741 rc = of_property_read_u32(of_node, "gpio-custom1", &val);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700742 if (rc != -EINVAL) {
743 if (rc < 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530744 pr_err("%s:%d read gpio-custom1 failed rc %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700745 __func__, __LINE__, rc);
746 goto free_gpio_info;
747 } else if (val >= gpio_array_size) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530748 pr_err("%s:%d gpio-custom1 invalid %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700749 __func__, __LINE__, val);
750 rc = -EINVAL;
751 goto free_gpio_info;
752 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530753 gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO1] =
754 gconf->cam_gpio_common_tbl[val].gpio;
755 gpio_num_info->valid[SENSOR_CUSTOM_GPIO1] = 1;
756
757 CDBG("%s:%d gpio-custom1 %d\n", __func__, __LINE__,
758 gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO1]);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700759 }
760
Alok Pandey01b1b352017-06-25 20:38:54 +0530761 rc = of_property_read_u32(of_node, "gpio-custom2", &val);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700762 if (rc != -EINVAL) {
763 if (rc < 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530764 pr_err("%s:%d read gpio-custom2 failed rc %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700765 __func__, __LINE__, rc);
766 goto free_gpio_info;
767 } else if (val >= gpio_array_size) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530768 pr_err("%s:%d gpio-custom2 invalid %d\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700769 __func__, __LINE__, val);
770 rc = -EINVAL;
771 goto free_gpio_info;
772 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530773 gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO2] =
774 gconf->cam_gpio_common_tbl[val].gpio;
775 gpio_num_info->valid[SENSOR_CUSTOM_GPIO2] = 1;
776
777 CDBG("%s:%d gpio-custom2 %d\n", __func__, __LINE__,
778 gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO2]);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700779 } else {
780 rc = 0;
781 }
782
783 return rc;
784
785free_gpio_info:
Alok Pandey01b1b352017-06-25 20:38:54 +0530786 kfree(gpio_num_info);
787 gpio_num_info = NULL;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700788 return rc;
789}
790
791int msm_camera_pinctrl_init(
792 struct msm_pinctrl_info *sensor_pctrl, struct device *dev) {
793
794 sensor_pctrl->pinctrl = devm_pinctrl_get(dev);
795 if (IS_ERR_OR_NULL(sensor_pctrl->pinctrl)) {
796 pr_err("%s:%d Getting pinctrl handle failed\n",
797 __func__, __LINE__);
798 return -EINVAL;
799 }
800 sensor_pctrl->gpio_state_active =
801 pinctrl_lookup_state(sensor_pctrl->pinctrl,
802 CAM_SENSOR_PINCTRL_STATE_DEFAULT);
803 if (IS_ERR_OR_NULL(sensor_pctrl->gpio_state_active)) {
804 pr_err("%s:%d Failed to get the active state pinctrl handle\n",
805 __func__, __LINE__);
806 return -EINVAL;
807 }
808 sensor_pctrl->gpio_state_suspend
809 = pinctrl_lookup_state(sensor_pctrl->pinctrl,
810 CAM_SENSOR_PINCTRL_STATE_SLEEP);
811 if (IS_ERR_OR_NULL(sensor_pctrl->gpio_state_suspend)) {
812 pr_err("%s:%d Failed to get the suspend state pinctrl handle\n",
813 __func__, __LINE__);
814 return -EINVAL;
815 }
816 return 0;
817}
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700818int msm_cam_sensor_handle_reg_gpio(int seq_type,
Alok Pandey01b1b352017-06-25 20:38:54 +0530819 struct msm_camera_gpio_num_info *gpio_num_info, int val)
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700820{
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700821 int gpio_offset = -1;
822
Alok Pandey01b1b352017-06-25 20:38:54 +0530823 if (!gpio_num_info) {
824 pr_err("%s:%d Input Parameters are not proper\n",
825 __func__, __LINE__);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700826 return -EINVAL;
827 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530828
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700829 CDBG("%s: %d Seq type: %d, config: %d", __func__, __LINE__,
830 seq_type, val);
831
832 gpio_offset = seq_type;
833
Alok Pandey01b1b352017-06-25 20:38:54 +0530834 if (gpio_num_info->valid[gpio_offset] == 1) {
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700835 CDBG("%s: %d VALID GPIO offset: %d, seqtype: %d\n",
Alok Pandey01b1b352017-06-25 20:38:54 +0530836 __func__, __LINE__, gpio_offset, seq_type);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700837 gpio_set_value_cansleep(
Alok Pandey01b1b352017-06-25 20:38:54 +0530838 gpio_num_info->gpio_num
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700839 [gpio_offset], val);
840 }
841
842 return 0;
843}
844
Alok Pandey01b1b352017-06-25 20:38:54 +0530845int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl,
846 struct cam_hw_soc_info *soc_info)
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700847{
848 int rc = 0, index = 0, no_gpio = 0, ret = 0, num_vreg, j = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +0530849 int32_t vreg_idx = -1;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700850 struct cam_sensor_power_setting *power_setting = NULL;
Alok Pandey01b1b352017-06-25 20:38:54 +0530851 struct msm_camera_gpio_num_info *gpio_num_info = NULL;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700852
853 CDBG("%s:%d\n", __func__, __LINE__);
854 if (!ctrl) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530855 pr_err("%s:%d Invalid ctrl handle\n", __func__, __LINE__);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700856 return -EINVAL;
857 }
858
Alok Pandey01b1b352017-06-25 20:38:54 +0530859 gpio_num_info = ctrl->gpio_num_info;
860 num_vreg = soc_info->num_rgltr;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700861
Alok Pandey01b1b352017-06-25 20:38:54 +0530862 if ((num_vreg == 0) || (num_vreg > CAM_SOC_MAX_REGULATOR)) {
863 pr_err("%s:%d Regulators are not initialized\n",
864 __func__, __LINE__);
865 return -EINVAL;
866 }
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700867
868 ret = msm_camera_pinctrl_init(&(ctrl->pinctrl_info), ctrl->dev);
869 if (ret < 0) {
870 pr_err("%s:%d Initialization of pinctrl failed\n",
871 __func__, __LINE__);
872 ctrl->cam_pinctrl_status = 0;
873 } else {
874 ctrl->cam_pinctrl_status = 1;
875 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530876
877 rc = cam_sensor_util_request_gpio_table(soc_info, 1);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700878 if (rc < 0)
879 no_gpio = rc;
Alok Pandey01b1b352017-06-25 20:38:54 +0530880
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700881 if (ctrl->cam_pinctrl_status) {
882 ret = pinctrl_select_state(ctrl->pinctrl_info.pinctrl,
883 ctrl->pinctrl_info.gpio_state_active);
884 if (ret)
885 pr_err("%s:%d cannot set pin to active state",
886 __func__, __LINE__);
887 }
888
889 for (index = 0; index < ctrl->power_setting_size; index++) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530890 CDBG("%s:%d index %d\n", __func__, __LINE__, index);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700891 power_setting = &ctrl->power_setting[index];
892
893 switch (power_setting->seq_type) {
894 case SENSOR_MCLK:
Alok Pandey01b1b352017-06-25 20:38:54 +0530895 if (power_setting->seq_val >= soc_info->num_clk) {
896 pr_err("%s:%d :Error: clk index %d >= max %u\n",
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700897 __func__, __LINE__,
898 power_setting->seq_val,
Alok Pandey01b1b352017-06-25 20:38:54 +0530899 soc_info->num_clk);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700900 goto power_up_failed;
901 }
902 for (j = 0; j < num_vreg; j++) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530903 if (!strcmp(soc_info->rgltr_name[j],
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700904 "cam_clk")) {
905 CDBG("%s:%d Enable cam_clk: %d\n",
906 __func__, __LINE__, j);
Alok Pandey01b1b352017-06-25 20:38:54 +0530907
908 soc_info->rgltr[j] =
909 regulator_get(
910 &soc_info->pdev->dev,
911 soc_info->rgltr_name[j]);
912
913 if (IS_ERR_OR_NULL(
914 soc_info->rgltr[j])) {
915 rc = PTR_ERR(
916 soc_info->rgltr[j]);
917 rc = rc ? rc : -EINVAL;
918 pr_err("%s:%d :vreg %s %d\n",
919 __func__, __LINE__,
920 soc_info->rgltr_name[j],
921 rc);
922 soc_info->rgltr[j] = NULL;
923 }
924
925 rc = cam_soc_util_regulator_enable(
926 soc_info->rgltr[j],
927 soc_info->rgltr_name[j],
928 soc_info->rgltr_min_volt[j],
929 soc_info->rgltr_max_volt[j],
930 soc_info->rgltr_op_mode[j],
931 soc_info->rgltr_delay[j]);
932
933 power_setting->data[0] =
934 soc_info->rgltr[j];
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700935 }
936 }
937 if (power_setting->config_val)
Alok Pandey01b1b352017-06-25 20:38:54 +0530938 soc_info->clk_rate[0][power_setting->seq_val] =
939 power_setting->config_val;
940
941 for (j = 0; j < soc_info->num_clk; j++) {
942 rc = cam_soc_util_clk_enable(soc_info->clk[j],
943 soc_info->clk_name[j],
944 soc_info->clk_rate[0][j]);
945 if (rc)
946 break;
947 }
948
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700949 if (rc < 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530950 pr_err("%s:%d clk enable failed\n", __func__,
951 __LINE__);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700952 goto power_up_failed;
953 }
954 break;
955 case SENSOR_RESET:
956 case SENSOR_STANDBY:
957 case SENSOR_CUSTOM_GPIO1:
958 case SENSOR_CUSTOM_GPIO2:
959 if (no_gpio) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530960 pr_err("%s:%d request gpio failed\n", __func__,
961 __LINE__);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700962 return no_gpio;
963 }
964 if (power_setting->seq_val >= CAM_VREG_MAX ||
Alok Pandey01b1b352017-06-25 20:38:54 +0530965 !gpio_num_info) {
966 pr_err("%s:%d gpio index %d >= max %d\n",
967 __func__, __LINE__,
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700968 power_setting->seq_val,
969 CAM_VREG_MAX);
970 goto power_up_failed;
971 }
972 CDBG("%s:%d gpio set val %d\n",
973 __func__, __LINE__,
Alok Pandey01b1b352017-06-25 20:38:54 +0530974 gpio_num_info->gpio_num
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700975 [power_setting->seq_val]);
976
977 rc = msm_cam_sensor_handle_reg_gpio(
978 power_setting->seq_type,
Alok Pandey01b1b352017-06-25 20:38:54 +0530979 gpio_num_info, 1);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700980 if (rc < 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530981 pr_err("%s:%d Error in handling VREG GPIO\n",
982 __func__, __LINE__);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700983 goto power_up_failed;
984 }
985 break;
986 case SENSOR_VANA:
987 case SENSOR_VDIG:
988 case SENSOR_VIO:
989 case SENSOR_VAF:
990 case SENSOR_VAF_PWDM:
991 case SENSOR_CUSTOM_REG1:
992 case SENSOR_CUSTOM_REG2:
993 if (power_setting->seq_val == INVALID_VREG)
994 break;
995
996 if (power_setting->seq_val >= CAM_VREG_MAX) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530997 pr_err("%s:%d vreg index %d >= max %d\n",
998 __func__, __LINE__,
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -0700999 power_setting->seq_val,
1000 CAM_VREG_MAX);
1001 goto power_up_failed;
1002 }
Alok Pandey01b1b352017-06-25 20:38:54 +05301003 if (power_setting->seq_val < num_vreg) {
1004 CDBG("%s:%d Enable Regulator\n",
1005 __func__, __LINE__);
1006 vreg_idx = power_setting->seq_val;
1007
1008 soc_info->rgltr[vreg_idx] =
1009 regulator_get(&soc_info->pdev->dev,
1010 soc_info->rgltr_name[vreg_idx]);
1011 if (IS_ERR_OR_NULL(
1012 soc_info->rgltr[vreg_idx])) {
1013 rc = PTR_ERR(soc_info->rgltr[vreg_idx]);
1014 rc = rc ? rc : -EINVAL;
1015
1016 pr_err("%s:%d, %s get failed %d\n",
1017 __func__, __LINE__,
1018 soc_info->rgltr_name[vreg_idx],
1019 rc);
1020
1021 soc_info->rgltr[vreg_idx] = NULL;
1022 }
1023
1024 rc = cam_soc_util_regulator_enable(
1025 soc_info->rgltr[vreg_idx],
1026 soc_info->rgltr_name[vreg_idx],
1027 soc_info->rgltr_min_volt[vreg_idx],
1028 soc_info->rgltr_max_volt[vreg_idx],
1029 soc_info->rgltr_op_mode[vreg_idx],
1030 soc_info->rgltr_delay[vreg_idx]);
1031
1032 power_setting->data[0] =
1033 soc_info->rgltr[vreg_idx];
1034 }
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001035 else
1036 pr_err("%s: %d usr_idx:%d dts_idx:%d\n",
1037 __func__, __LINE__,
Alok Pandey01b1b352017-06-25 20:38:54 +05301038 power_setting->seq_val, num_vreg);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001039
1040 rc = msm_cam_sensor_handle_reg_gpio(
1041 power_setting->seq_type,
Alok Pandey01b1b352017-06-25 20:38:54 +05301042 gpio_num_info, 1);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001043 if (rc < 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +05301044 pr_err("%s:%d Error in handling VREG GPIO\n",
1045 __func__, __LINE__);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001046 goto power_up_failed;
1047 }
1048 break;
1049 default:
Alok Pandey01b1b352017-06-25 20:38:54 +05301050 pr_err("%s:%d error power seq type %d\n", __func__,
1051 __LINE__, power_setting->seq_type);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001052 break;
1053 }
1054 if (power_setting->delay > 20)
1055 msleep(power_setting->delay);
1056 else if (power_setting->delay)
1057 usleep_range(power_setting->delay * 1000,
1058 (power_setting->delay * 1000) + 1000);
1059 }
1060
1061 return 0;
1062power_up_failed:
1063 pr_err("%s:%d failed\n", __func__, __LINE__);
1064 for (index--; index >= 0; index--) {
Alok Pandey01b1b352017-06-25 20:38:54 +05301065 CDBG("%s:%d index %d\n", __func__, __LINE__, index);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001066 power_setting = &ctrl->power_setting[index];
Alok Pandey01b1b352017-06-25 20:38:54 +05301067 CDBG("%s:%d type %d\n", __func__, __LINE__,
1068 power_setting->seq_type);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001069 switch (power_setting->seq_type) {
1070 case SENSOR_RESET:
1071 case SENSOR_STANDBY:
1072 case SENSOR_CUSTOM_GPIO1:
1073 case SENSOR_CUSTOM_GPIO2:
Alok Pandey01b1b352017-06-25 20:38:54 +05301074 if (!gpio_num_info)
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001075 continue;
Alok Pandey01b1b352017-06-25 20:38:54 +05301076 if (!gpio_num_info->valid
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001077 [power_setting->seq_val])
1078 continue;
1079 gpio_set_value_cansleep(
Alok Pandey01b1b352017-06-25 20:38:54 +05301080 gpio_num_info->gpio_num
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001081 [power_setting->seq_val], GPIOF_OUT_INIT_LOW);
1082 break;
1083 case SENSOR_VANA:
1084 case SENSOR_VDIG:
1085 case SENSOR_VIO:
1086 case SENSOR_VAF:
1087 case SENSOR_VAF_PWDM:
1088 case SENSOR_CUSTOM_REG1:
1089 case SENSOR_CUSTOM_REG2:
Alok Pandey01b1b352017-06-25 20:38:54 +05301090 if (power_setting->seq_val < num_vreg) {
1091 CDBG("%s:%d Disable Regulator\n",
1092 __func__, __LINE__);
1093 vreg_idx = power_setting->seq_val;
1094
1095 rc = cam_soc_util_regulator_disable(
1096 soc_info->rgltr[vreg_idx],
1097 soc_info->rgltr_name[vreg_idx],
1098 soc_info->rgltr_min_volt[vreg_idx],
1099 soc_info->rgltr_max_volt[vreg_idx],
1100 soc_info->rgltr_op_mode[vreg_idx],
1101 soc_info->rgltr_delay[vreg_idx]);
1102
1103 power_setting->data[0] =
1104 soc_info->rgltr[vreg_idx];
1105
1106 }
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001107 else
1108 pr_err("%s:%d:seq_val: %d > num_vreg: %d\n",
1109 __func__, __LINE__,
Alok Pandey01b1b352017-06-25 20:38:54 +05301110 power_setting->seq_val, num_vreg);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001111
1112 msm_cam_sensor_handle_reg_gpio(power_setting->seq_type,
Alok Pandey01b1b352017-06-25 20:38:54 +05301113 gpio_num_info, GPIOF_OUT_INIT_LOW);
1114
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001115 break;
1116 default:
Alok Pandey01b1b352017-06-25 20:38:54 +05301117 pr_err("%s:%d error power seq type %d\n", __func__,
1118 __LINE__, power_setting->seq_type);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001119 break;
1120 }
1121 if (power_setting->delay > 20) {
1122 msleep(power_setting->delay);
1123 } else if (power_setting->delay) {
1124 usleep_range(power_setting->delay * 1000,
1125 (power_setting->delay * 1000) + 1000);
1126 }
1127 }
1128 if (ctrl->cam_pinctrl_status) {
1129 ret = pinctrl_select_state(ctrl->pinctrl_info.pinctrl,
1130 ctrl->pinctrl_info.gpio_state_suspend);
1131 if (ret)
1132 pr_err("%s:%d cannot set pin to suspend state\n",
1133 __func__, __LINE__);
1134 devm_pinctrl_put(ctrl->pinctrl_info.pinctrl);
1135 }
1136 ctrl->cam_pinctrl_status = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +05301137
1138 cam_sensor_util_request_gpio_table(soc_info, 0);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001139
1140 return rc;
1141}
1142
1143static struct cam_sensor_power_setting*
1144msm_camera_get_power_settings(struct cam_sensor_power_ctrl_t *ctrl,
1145 enum msm_camera_power_seq_type seq_type,
1146 uint16_t seq_val)
1147{
1148 struct cam_sensor_power_setting *power_setting, *ps = NULL;
1149 int idx;
1150
1151 for (idx = 0; idx < ctrl->power_setting_size; idx++) {
1152 power_setting = &ctrl->power_setting[idx];
1153 if (power_setting->seq_type == seq_type &&
1154 power_setting->seq_val == seq_val) {
1155 ps = power_setting;
1156 return ps;
1157 }
1158
1159 }
1160
1161 return ps;
1162}
1163
1164static int cam_config_mclk_reg(struct cam_sensor_power_ctrl_t *ctrl,
Alok Pandey01b1b352017-06-25 20:38:54 +05301165 struct cam_hw_soc_info *soc_info, int32_t index)
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001166{
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001167 int32_t num_vreg = 0, j = 0, rc = 0, idx = 0;
1168 struct cam_sensor_power_setting *ps = NULL;
1169 struct cam_sensor_power_setting *pd = NULL;
1170
Alok Pandey01b1b352017-06-25 20:38:54 +05301171 num_vreg = soc_info->num_rgltr;
1172
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001173 pd = &ctrl->power_down_setting[index];
1174
1175 for (j = 0; j < num_vreg; j++) {
Alok Pandey01b1b352017-06-25 20:38:54 +05301176 if (!strcmp(soc_info->rgltr_name[j], "cam_clk")) {
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001177
1178 ps = NULL;
1179 for (idx = 0; idx <
1180 ctrl->power_setting_size; idx++) {
1181 if (ctrl->power_setting[idx].
1182 seq_type == pd->seq_type) {
1183 ps = &ctrl->power_setting[idx];
1184 break;
1185 }
1186 }
1187
Alok Pandey01b1b352017-06-25 20:38:54 +05301188 if (ps != NULL) {
1189 CDBG("%s:%d Disable Regulator\n",
1190 __func__, __LINE__);
1191
1192 rc = cam_soc_util_regulator_disable(
1193 soc_info->rgltr[j],
1194 soc_info->rgltr_name[j],
1195 soc_info->rgltr_min_volt[j],
1196 soc_info->rgltr_max_volt[j],
1197 soc_info->rgltr_op_mode[j],
1198 soc_info->rgltr_delay[j]);
1199
1200 ps->data[0] =
1201 soc_info->rgltr[j];
1202 }
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001203 }
1204 }
1205
1206 return rc;
1207}
1208
Alok Pandey01b1b352017-06-25 20:38:54 +05301209int msm_camera_power_down(struct cam_sensor_power_ctrl_t *ctrl,
1210 struct cam_hw_soc_info *soc_info)
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001211{
Alok Pandey01b1b352017-06-25 20:38:54 +05301212 int index = 0, ret = 0, num_vreg = 0, i;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001213 struct cam_sensor_power_setting *pd = NULL;
1214 struct cam_sensor_power_setting *ps;
Alok Pandey01b1b352017-06-25 20:38:54 +05301215 struct msm_camera_gpio_num_info *gpio_num_info = NULL;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001216
1217 CDBG("%s:%d\n", __func__, __LINE__);
Alok Pandey01b1b352017-06-25 20:38:54 +05301218 if (!ctrl || !soc_info) {
1219 pr_err("%s:%d failed ctrl %pK\n", __func__, __LINE__, ctrl);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001220 return -EINVAL;
1221 }
1222
Alok Pandey01b1b352017-06-25 20:38:54 +05301223 gpio_num_info = ctrl->gpio_num_info;
1224 num_vreg = soc_info->num_rgltr;
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001225
1226 for (index = 0; index < ctrl->power_down_setting_size; index++) {
Alok Pandey01b1b352017-06-25 20:38:54 +05301227 CDBG("%s:%d index %d\n", __func__, __LINE__, index);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001228 pd = &ctrl->power_down_setting[index];
1229 ps = NULL;
Alok Pandey01b1b352017-06-25 20:38:54 +05301230 CDBG("%s:%d type %d\n", __func__, __LINE__, pd->seq_type);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001231 switch (pd->seq_type) {
1232 case SENSOR_MCLK:
Alok Pandey01b1b352017-06-25 20:38:54 +05301233 ret = cam_config_mclk_reg(ctrl, soc_info, index);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001234 if (ret < 0) {
1235 pr_err("%s:%d :Error: in config clk reg\n",
1236 __func__, __LINE__);
1237 return ret;
1238 }
Alok Pandey01b1b352017-06-25 20:38:54 +05301239 //cam_soc_util_clk_disable_default(soc_info);
1240 for (i = soc_info->num_clk - 1; i >= 0; i--) {
1241 cam_soc_util_clk_disable(soc_info->clk[i],
1242 soc_info->clk_name[i]);
1243 }
1244
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001245 break;
1246 case SENSOR_RESET:
1247 case SENSOR_STANDBY:
1248 case SENSOR_CUSTOM_GPIO1:
1249 case SENSOR_CUSTOM_GPIO2:
Alok Pandey01b1b352017-06-25 20:38:54 +05301250
1251 if (!gpio_num_info->valid[pd->seq_val])
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001252 continue;
Alok Pandey01b1b352017-06-25 20:38:54 +05301253
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001254 gpio_set_value_cansleep(
Alok Pandey01b1b352017-06-25 20:38:54 +05301255 gpio_num_info->gpio_num
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001256 [pd->seq_val],
1257 (int) pd->config_val);
Alok Pandey01b1b352017-06-25 20:38:54 +05301258
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001259 break;
1260 case SENSOR_VANA:
1261 case SENSOR_VDIG:
1262 case SENSOR_VIO:
1263 case SENSOR_VAF:
1264 case SENSOR_VAF_PWDM:
1265 case SENSOR_CUSTOM_REG1:
1266 case SENSOR_CUSTOM_REG2:
1267 if (pd->seq_val == INVALID_VREG)
1268 break;
Alok Pandey01b1b352017-06-25 20:38:54 +05301269
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001270 ps = msm_camera_get_power_settings(
1271 ctrl, pd->seq_type,
1272 pd->seq_val);
1273 if (ps) {
Alok Pandey01b1b352017-06-25 20:38:54 +05301274 if (pd->seq_val < num_vreg) {
1275 CDBG("%s:%d Disable Regulator\n",
1276 __func__, __LINE__);
1277 ret = cam_soc_util_regulator_disable(
1278 soc_info->rgltr[ps->seq_val],
1279 soc_info->rgltr_name[ps->seq_val],
1280 soc_info->rgltr_min_volt[ps->seq_val],
1281 soc_info->rgltr_max_volt[ps->seq_val],
1282 soc_info->rgltr_op_mode[ps->seq_val],
1283 soc_info->rgltr_delay[ps->seq_val]);
1284
1285 ps->data[0] =
1286 soc_info->rgltr[ps->seq_val];
1287 }
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001288 else
1289 pr_err("%s:%d:seq_val:%d > num_vreg: %d\n",
1290 __func__, __LINE__, pd->seq_val,
Alok Pandey01b1b352017-06-25 20:38:54 +05301291 num_vreg);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001292 } else
Alok Pandey01b1b352017-06-25 20:38:54 +05301293 pr_err("%s:%d error in power up/down seq\n",
1294 __func__, __LINE__);
1295
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001296 ret = msm_cam_sensor_handle_reg_gpio(pd->seq_type,
Alok Pandey01b1b352017-06-25 20:38:54 +05301297 gpio_num_info, GPIOF_OUT_INIT_LOW);
1298
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001299 if (ret < 0)
Alok Pandey01b1b352017-06-25 20:38:54 +05301300 pr_err("%s:%d Error disabling VREG GPIO\n",
1301 __func__, __LINE__);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001302 break;
1303 default:
Alok Pandey01b1b352017-06-25 20:38:54 +05301304 pr_err("%s:%d error power seq type %d\n", __func__,
1305 __LINE__, pd->seq_type);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001306 break;
1307 }
1308 if (pd->delay > 20)
1309 msleep(pd->delay);
1310 else if (pd->delay)
1311 usleep_range(pd->delay * 1000,
1312 (pd->delay * 1000) + 1000);
1313 }
1314
1315 if (ctrl->cam_pinctrl_status) {
1316 ret = pinctrl_select_state(ctrl->pinctrl_info.pinctrl,
1317 ctrl->pinctrl_info.gpio_state_suspend);
1318 if (ret)
1319 pr_err("%s:%d cannot set pin to suspend state",
1320 __func__, __LINE__);
1321 devm_pinctrl_put(ctrl->pinctrl_info.pinctrl);
1322 }
1323
1324 ctrl->cam_pinctrl_status = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +05301325
1326 cam_sensor_util_request_gpio_table(soc_info, 0);
Viswanadha Raju Thotakura426ec662017-03-15 17:00:29 -07001327
1328 return 0;
1329}
1330