blob: 72b177987e83bf1666bab6357f5927b6ae803d3d [file] [log] [blame]
Vivek Veenam2ad8de12017-04-04 18:56:22 +05301/* 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/module.h>
14#include <linux/crc32.h>
15#include <media/cam_sensor.h>
16
17#include "cam_eeprom_core.h"
18#include "cam_eeprom_soc.h"
19#include "cam_debug_util.h"
20
21/**
22 * cam_eeprom_read_memory() - read map data into buffer
23 * @e_ctrl: eeprom control struct
24 * @block: block to be read
25 *
26 * This function iterates through blocks stored in block->map, reads each
27 * region and concatenate them into the pre-allocated block->mapdata
28 */
29static int cam_eeprom_read_memory(struct cam_eeprom_ctrl_t *e_ctrl,
30 struct cam_eeprom_memory_block_t *block)
31{
32 int rc = 0;
33 int j;
34 struct cam_sensor_i2c_reg_setting i2c_reg_settings;
35 struct cam_sensor_i2c_reg_array i2c_reg_array;
36 struct cam_eeprom_memory_map_t *emap = block->map;
37 struct cam_eeprom_soc_private *eb_info;
38 uint8_t *memptr = block->mapdata;
39
40 if (!e_ctrl) {
41 CAM_ERR(CAM_EEPROM, "e_ctrl is NULL");
42 return -EINVAL;
43 }
44
45 eb_info = (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
46
47 for (j = 0; j < block->num_map; j++) {
48 CAM_DBG(CAM_EEPROM, "slave-addr = 0x%X", emap[j].saddr);
49 if (emap[j].saddr) {
50 eb_info->i2c_info.slave_addr = emap[j].saddr;
51 rc = cam_eeprom_update_i2c_info(e_ctrl,
52 &eb_info->i2c_info);
53 if (rc) {
54 CAM_ERR(CAM_EEPROM,
55 "failed: to update i2c info rc %d",
56 rc);
57 return rc;
58 }
59 }
60
61 if (emap[j].page.valid_size) {
62 i2c_reg_settings.addr_type = emap[j].page.addr_type;
63 i2c_reg_settings.data_type = emap[j].page.data_type;
64 i2c_reg_settings.size = 1;
65 i2c_reg_array.reg_addr = emap[j].page.addr;
66 i2c_reg_array.reg_data = emap[j].page.data;
67 i2c_reg_array.delay = emap[j].page.delay;
68 i2c_reg_settings.reg_setting = &i2c_reg_array;
69 rc = camera_io_dev_write(&e_ctrl->io_master_info,
70 &i2c_reg_settings);
71 if (rc) {
72 CAM_ERR(CAM_EEPROM, "page write failed rc %d",
73 rc);
74 return rc;
75 }
76 }
77
78 if (emap[j].pageen.valid_size) {
79 i2c_reg_settings.addr_type = emap[j].pageen.addr_type;
80 i2c_reg_settings.data_type = emap[j].pageen.data_type;
81 i2c_reg_settings.size = 1;
82 i2c_reg_array.reg_addr = emap[j].pageen.addr;
83 i2c_reg_array.reg_data = emap[j].pageen.data;
84 i2c_reg_array.delay = emap[j].pageen.delay;
85 i2c_reg_settings.reg_setting = &i2c_reg_array;
86 rc = camera_io_dev_write(&e_ctrl->io_master_info,
87 &i2c_reg_settings);
88 if (rc) {
89 CAM_ERR(CAM_EEPROM, "page enable failed rc %d",
90 rc);
91 return rc;
92 }
93 }
94
95 if (emap[j].poll.valid_size) {
96 rc = camera_io_dev_poll(&e_ctrl->io_master_info,
97 emap[j].poll.addr, emap[j].poll.data,
98 0, emap[j].poll.addr_type,
99 emap[j].poll.data_type,
100 emap[j].poll.delay);
101 if (rc) {
102 CAM_ERR(CAM_EEPROM, "poll failed rc %d",
103 rc);
104 return rc;
105 }
106 }
107
108 if (emap[j].mem.valid_size) {
109 rc = camera_io_dev_read_seq(&e_ctrl->io_master_info,
110 emap[j].mem.addr, memptr,
111 emap[j].mem.addr_type,
112 emap[j].mem.valid_size);
113 if (rc) {
114 CAM_ERR(CAM_EEPROM, "read failed rc %d",
115 rc);
116 return rc;
117 }
118 memptr += emap[j].mem.valid_size;
119 }
120
121 if (emap[j].pageen.valid_size) {
122 i2c_reg_settings.addr_type = emap[j].pageen.addr_type;
123 i2c_reg_settings.data_type = emap[j].pageen.data_type;
124 i2c_reg_settings.size = 1;
125 i2c_reg_array.reg_addr = emap[j].pageen.addr;
126 i2c_reg_array.reg_data = 0;
127 i2c_reg_array.delay = emap[j].pageen.delay;
128 i2c_reg_settings.reg_setting = &i2c_reg_array;
129 rc = camera_io_dev_write(&e_ctrl->io_master_info,
130 &i2c_reg_settings);
131
132 if (rc) {
133 CAM_ERR(CAM_EEPROM,
134 "page disable failed rc %d",
135 rc);
136 return rc;
137 }
138 }
139 }
140 return rc;
141}
142
143/**
144 * cam_eeprom_power_up - Power up eeprom hardware
145 * @e_ctrl: ctrl structure
146 * @power_info: power up/down info for eeprom
147 *
148 * Returns success or failure
149 */
150static int cam_eeprom_power_up(struct cam_eeprom_ctrl_t *e_ctrl,
151 struct cam_sensor_power_ctrl_t *power_info)
152{
153 int32_t rc = 0;
154 struct cam_hw_soc_info *soc_info =
155 &e_ctrl->soc_info;
156
157 /* Parse and fill vreg params for power up settings */
158 rc = msm_camera_fill_vreg_params(
159 &e_ctrl->soc_info,
160 power_info->power_setting,
161 power_info->power_setting_size);
162 if (rc) {
163 CAM_ERR(CAM_EEPROM,
164 "failed to fill vreg params for power up rc:%d", rc);
165 return rc;
166 }
167
168 /* Parse and fill vreg params for power down settings*/
169 rc = msm_camera_fill_vreg_params(
170 &e_ctrl->soc_info,
171 power_info->power_down_setting,
172 power_info->power_down_setting_size);
173 if (rc) {
174 CAM_ERR(CAM_EEPROM,
175 "failed to fill vreg params power down rc:%d", rc);
176 return rc;
177 }
178
Viswanadha Raju Thotakuraf721c962017-10-08 20:57:51 -0700179 power_info->dev = soc_info->dev;
180
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530181 rc = cam_sensor_core_power_up(power_info, soc_info);
182 if (rc) {
183 CAM_ERR(CAM_EEPROM, "failed in eeprom power up rc %d", rc);
184 return rc;
185 }
186
187 if (e_ctrl->io_master_info.master_type == CCI_MASTER) {
188 rc = camera_io_init(&(e_ctrl->io_master_info));
189 if (rc) {
190 CAM_ERR(CAM_EEPROM, "cci_init failed");
191 return -EINVAL;
192 }
193 }
194 return rc;
195}
196
197/**
198 * cam_eeprom_power_down - Power down eeprom hardware
199 * @e_ctrl: ctrl structure
200 *
201 * Returns success or failure
202 */
203static int cam_eeprom_power_down(struct cam_eeprom_ctrl_t *e_ctrl)
204{
205 struct cam_sensor_power_ctrl_t *power_info;
206 struct cam_hw_soc_info *soc_info;
207 struct cam_eeprom_soc_private *soc_private;
208 int rc = 0;
209
210 if (!e_ctrl) {
211 CAM_ERR(CAM_EEPROM, "failed: e_ctrl %pK", e_ctrl);
212 return -EINVAL;
213 }
214
215 soc_private =
216 (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
217 power_info = &soc_private->power_info;
218 soc_info = &e_ctrl->soc_info;
219
220 if (!power_info) {
221 CAM_ERR(CAM_EEPROM, "failed: power_info %pK", power_info);
222 return -EINVAL;
223 }
224 rc = msm_camera_power_down(power_info, soc_info);
225 if (rc) {
226 CAM_ERR(CAM_EEPROM, "power down the core is failed:%d", rc);
227 return rc;
228 }
229
230 if (e_ctrl->io_master_info.master_type == CCI_MASTER)
231 camera_io_release(&(e_ctrl->io_master_info));
232
233 return rc;
234}
235
236/**
237 * cam_eeprom_match_id - match eeprom id
238 * @e_ctrl: ctrl structure
239 *
240 * Returns success or failure
241 */
242static int cam_eeprom_match_id(struct cam_eeprom_ctrl_t *e_ctrl)
243{
244 int rc;
245 struct camera_io_master *client = &e_ctrl->io_master_info;
246 uint8_t id[2];
247
Jigarkumar Zala80a11402017-09-05 16:14:59 -0700248 rc = cam_spi_query_id(client, 0, CAMERA_SENSOR_I2C_TYPE_WORD,
249 &id[0], 2);
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530250 if (rc)
251 return rc;
252 CAM_DBG(CAM_EEPROM, "read 0x%x 0x%x, check 0x%x 0x%x",
253 id[0], id[1], client->spi_client->mfr_id0,
254 client->spi_client->device_id0);
255 if (id[0] != client->spi_client->mfr_id0
256 || id[1] != client->spi_client->device_id0)
257 return -ENODEV;
258 return 0;
259}
260
261/**
262 * cam_eeprom_parse_read_memory_map - Parse memory map
263 * @of_node: device node
264 * @e_ctrl: ctrl structure
265 *
266 * Returns success or failure
267 */
268int32_t cam_eeprom_parse_read_memory_map(struct device_node *of_node,
269 struct cam_eeprom_ctrl_t *e_ctrl)
270{
271 int32_t rc = 0;
272 struct cam_eeprom_soc_private *soc_private;
273 struct cam_sensor_power_ctrl_t *power_info;
274
275 if (!e_ctrl) {
276 CAM_ERR(CAM_EEPROM, "failed: e_ctrl is NULL");
277 return -EINVAL;
278 }
279
280 soc_private =
281 (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
282 power_info = &soc_private->power_info;
283
284 rc = cam_eeprom_parse_dt_memory_map(of_node, &e_ctrl->cal_data);
285 if (rc) {
286 CAM_ERR(CAM_EEPROM, "failed: eeprom dt parse rc %d", rc);
287 return rc;
288 }
289 rc = cam_eeprom_power_up(e_ctrl, power_info);
290 if (rc) {
291 CAM_ERR(CAM_EEPROM, "failed: eeprom power up rc %d", rc);
292 goto data_mem_free;
293 }
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700294
295 e_ctrl->cam_eeprom_state = CAM_EEPROM_CONFIG;
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530296 if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE) {
297 rc = cam_eeprom_match_id(e_ctrl);
298 if (rc) {
299 CAM_DBG(CAM_EEPROM, "eeprom not matching %d", rc);
300 goto power_down;
301 }
302 }
303 rc = cam_eeprom_read_memory(e_ctrl, &e_ctrl->cal_data);
304 if (rc) {
305 CAM_ERR(CAM_EEPROM, "read_eeprom_memory failed");
306 goto power_down;
307 }
308
309 rc = cam_eeprom_power_down(e_ctrl);
310 if (rc)
311 CAM_ERR(CAM_EEPROM, "failed: eeprom power down rc %d", rc);
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700312
313 e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE;
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530314 return rc;
315power_down:
Sureshnaidu Laveti3dc87ea2017-10-15 20:53:42 -0700316 cam_eeprom_power_down(e_ctrl);
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530317data_mem_free:
318 kfree(e_ctrl->cal_data.mapdata);
319 kfree(e_ctrl->cal_data.map);
Sureshnaidu Laveti389cf0d2017-09-25 22:35:55 -0700320 e_ctrl->cal_data.num_data = 0;
321 e_ctrl->cal_data.num_map = 0;
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700322 e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE;
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530323 return rc;
324}
325
326/**
327 * cam_eeprom_get_dev_handle - get device handle
328 * @e_ctrl: ctrl structure
329 * @arg: Camera control command argument
330 *
331 * Returns success or failure
332 */
333static int32_t cam_eeprom_get_dev_handle(struct cam_eeprom_ctrl_t *e_ctrl,
334 void *arg)
335{
336 struct cam_sensor_acquire_dev eeprom_acq_dev;
337 struct cam_create_dev_hdl bridge_params;
338 struct cam_control *cmd = (struct cam_control *)arg;
339
340 if (e_ctrl->bridge_intf.device_hdl != -1) {
341 CAM_ERR(CAM_EEPROM, "Device is already acquired");
342 return -EFAULT;
343 }
344 if (copy_from_user(&eeprom_acq_dev, (void __user *) cmd->handle,
345 sizeof(eeprom_acq_dev))) {
346 CAM_ERR(CAM_EEPROM,
347 "EEPROM:ACQUIRE_DEV: copy from user failed");
348 return -EFAULT;
349 }
350
351 bridge_params.session_hdl = eeprom_acq_dev.session_handle;
352 bridge_params.ops = &e_ctrl->bridge_intf.ops;
353 bridge_params.v4l2_sub_dev_flag = 0;
354 bridge_params.media_entity_flag = 0;
355 bridge_params.priv = e_ctrl;
356
357 eeprom_acq_dev.device_handle =
358 cam_create_device_hdl(&bridge_params);
359 e_ctrl->bridge_intf.device_hdl = eeprom_acq_dev.device_handle;
360 e_ctrl->bridge_intf.session_hdl = eeprom_acq_dev.session_handle;
361
362 CAM_DBG(CAM_EEPROM, "Device Handle: %d", eeprom_acq_dev.device_handle);
363 if (copy_to_user((void __user *) cmd->handle, &eeprom_acq_dev,
364 sizeof(struct cam_sensor_acquire_dev))) {
365 CAM_ERR(CAM_EEPROM, "EEPROM:ACQUIRE_DEV: copy to user failed");
366 return -EFAULT;
367 }
368 return 0;
369}
370
371/**
372 * cam_eeprom_update_slaveInfo - Update slave info
373 * @e_ctrl: ctrl structure
374 * @cmd_buf: command buffer
375 *
376 * Returns success or failure
377 */
378static int32_t cam_eeprom_update_slaveInfo(struct cam_eeprom_ctrl_t *e_ctrl,
379 void *cmd_buf)
380{
381 int32_t rc = 0;
382 struct cam_eeprom_soc_private *soc_private;
383 struct cam_cmd_i2c_info *cmd_i2c_info = NULL;
384
385 soc_private =
386 (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
387 cmd_i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
388 soc_private->i2c_info.slave_addr = cmd_i2c_info->slave_addr;
389 soc_private->i2c_info.i2c_freq_mode = cmd_i2c_info->i2c_freq_mode;
390
391 rc = cam_eeprom_update_i2c_info(e_ctrl,
392 &soc_private->i2c_info);
393 CAM_DBG(CAM_EEPROM, "Slave addr: 0x%x Freq Mode: %d",
394 soc_private->i2c_info.slave_addr,
395 soc_private->i2c_info.i2c_freq_mode);
396
397 return rc;
398}
399
400/**
401 * cam_eeprom_parse_memory_map - Parse memory map info
402 * @data: memory block data
403 * @cmd_buf: command buffer
404 * @cmd_length: command buffer length
405 * @num_map: memory map size
406 * @cmd_length_bytes: command length processed in this function
407 *
408 * Returns success or failure
409 */
410static int32_t cam_eeprom_parse_memory_map(
411 struct cam_eeprom_memory_block_t *data,
412 void *cmd_buf, int cmd_length, uint16_t *cmd_length_bytes,
413 int16_t num_map)
414{
415 int32_t rc = 0;
416 int32_t processed_size = 0;
417 struct cam_eeprom_memory_map_t *map = data->map;
418 struct common_header *cmm_hdr =
419 (struct common_header *)cmd_buf;
420 uint16_t cmd_length_in_bytes = 0;
421 struct cam_cmd_i2c_random_wr *i2c_random_wr = NULL;
422 struct cam_cmd_i2c_continuous_rd *i2c_cont_rd = NULL;
423 struct cam_cmd_conditional_wait *i2c_poll = NULL;
424
425 switch (cmm_hdr->cmd_type) {
426 case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
427 i2c_random_wr = (struct cam_cmd_i2c_random_wr *)cmd_buf;
428 cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_random_wr);
429
430 map[num_map].page.addr =
431 i2c_random_wr->random_wr_payload[0].reg_addr;
432 map[num_map].page.addr_type = i2c_random_wr->header.addr_type;
433 map[num_map].page.data =
434 i2c_random_wr->random_wr_payload[0].reg_data;
435 map[num_map].page.data_type = i2c_random_wr->header.data_type;
436 map[num_map].page.valid_size = 1;
437 cmd_buf += cmd_length_in_bytes / sizeof(int32_t);
438 processed_size +=
439 cmd_length_in_bytes;
440 break;
441 case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD:
442 i2c_cont_rd = (struct cam_cmd_i2c_continuous_rd *)cmd_buf;
443 cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_continuous_rd);
444
445 map[num_map].mem.addr = i2c_cont_rd->reg_addr;
446 map[num_map].mem.addr_type = i2c_cont_rd->header.addr_type;
447 map[num_map].mem.data_type = i2c_cont_rd->header.data_type;
448 map[num_map].mem.valid_size =
449 i2c_cont_rd->header.count;
450 cmd_buf += cmd_length_in_bytes / sizeof(int32_t);
451 processed_size +=
452 cmd_length_in_bytes;
453 data->num_data += map[num_map].mem.valid_size;
454 break;
455 case CAMERA_SENSOR_CMD_TYPE_WAIT:
456 i2c_poll = (struct cam_cmd_conditional_wait *)cmd_buf;
457 cmd_length_in_bytes = sizeof(struct cam_cmd_conditional_wait);
458
459 map[num_map].poll.addr = i2c_poll->reg_addr;
460 map[num_map].poll.addr_type = i2c_poll->addr_type;
461 map[num_map].poll.data = i2c_poll->reg_data;
462 map[num_map].poll.data_type = i2c_poll->data_type;
463 map[num_map].poll.delay = i2c_poll->timeout;
464 map[num_map].poll.valid_size = 1;
465 break;
466 default:
467 break;
468 }
469 *cmd_length_bytes = processed_size;
470 return rc;
471}
472
473/**
474 * cam_eeprom_init_pkt_parser - Parse eeprom packet
475 * @e_ctrl: ctrl structure
476 * @csl_packet: csl packet received
477 *
478 * Returns success or failure
479 */
480static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
481 struct cam_packet *csl_packet)
482{
483 int32_t rc = 0;
484 int i = 0;
485 struct cam_cmd_buf_desc *cmd_desc = NULL;
486 uint32_t *offset = NULL;
487 uint32_t *cmd_buf = NULL;
488 uint64_t generic_pkt_addr;
489 size_t pkt_len = 0;
490 uint32_t total_cmd_buf_in_bytes = 0;
491 uint32_t processed_cmd_buf_in_bytes = 0;
492 struct common_header *cmm_hdr = NULL;
493 uint16_t cmd_length_in_bytes = 0;
494 struct cam_cmd_i2c_info *i2c_info = NULL;
495 int num_map = -1;
Sureshnaidu Laveti389cf0d2017-09-25 22:35:55 -0700496 struct cam_eeprom_memory_map_t *map = NULL;
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530497 struct cam_eeprom_soc_private *soc_private =
498 (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
499 struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info;
500
501 e_ctrl->cal_data.map = kcalloc((MSM_EEPROM_MEMORY_MAP_MAX_SIZE *
502 MSM_EEPROM_MAX_MEM_MAP_CNT),
503 (sizeof(struct cam_eeprom_memory_map_t)), GFP_KERNEL);
504 if (!e_ctrl->cal_data.map) {
505 rc = -ENOMEM;
506 CAM_ERR(CAM_EEPROM, "failed");
507 return rc;
508 }
509 map = e_ctrl->cal_data.map;
510
511 offset = (uint32_t *)&csl_packet->payload;
512 offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t));
513 cmd_desc = (struct cam_cmd_buf_desc *)(offset);
514
515 /* Loop through multiple command buffers */
516 for (i = 0; i < csl_packet->num_cmd_buf; i++) {
517 total_cmd_buf_in_bytes = cmd_desc[i].length;
518 processed_cmd_buf_in_bytes = 0;
519 if (!total_cmd_buf_in_bytes)
520 continue;
521 rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
522 (uint64_t *)&generic_pkt_addr, &pkt_len);
523 if (rc) {
524 CAM_ERR(CAM_EEPROM, "Failed to get cpu buf");
525 return rc;
526 }
527 cmd_buf = (uint32_t *)generic_pkt_addr;
528 if (!cmd_buf) {
529 CAM_ERR(CAM_EEPROM, "invalid cmd buf");
530 return -EINVAL;
531 }
532 cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
533 /* Loop through multiple cmd formats in one cmd buffer */
534 while (processed_cmd_buf_in_bytes < total_cmd_buf_in_bytes) {
535 cmm_hdr = (struct common_header *)cmd_buf;
536 switch (cmm_hdr->cmd_type) {
537 case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
538 i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
539 num_map++;
540 map[num_map].saddr = i2c_info->slave_addr;
541 rc = cam_eeprom_update_slaveInfo(e_ctrl,
542 cmd_buf);
543 cmd_length_in_bytes =
544 sizeof(struct cam_cmd_i2c_info);
545 processed_cmd_buf_in_bytes +=
546 cmd_length_in_bytes;
547 cmd_buf += cmd_length_in_bytes/4;
548 e_ctrl->cal_data.num_map = num_map + 1;
549 break;
550 case CAMERA_SENSOR_CMD_TYPE_PWR_UP:
551 case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN:
552 cmd_length_in_bytes =
553 sizeof(struct cam_cmd_power);
554 rc = cam_sensor_update_power_settings(cmd_buf,
555 cmd_length_in_bytes, power_info);
556 processed_cmd_buf_in_bytes +=
557 total_cmd_buf_in_bytes;
558 cmd_buf += total_cmd_buf_in_bytes/4;
559 if (rc) {
560 CAM_ERR(CAM_EEPROM, "Failed");
561 return rc;
562 }
563 break;
564 case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
565 case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD:
566 case CAMERA_SENSOR_CMD_TYPE_WAIT:
567 rc = cam_eeprom_parse_memory_map(
568 &e_ctrl->cal_data, cmd_buf,
569 total_cmd_buf_in_bytes,
570 &cmd_length_in_bytes, num_map);
571 processed_cmd_buf_in_bytes +=
572 cmd_length_in_bytes;
573 cmd_buf += cmd_length_in_bytes/4;
574 break;
575 default:
576 break;
577 }
578 }
579 }
580 return rc;
581}
582
583/**
584 * cam_eeprom_get_cal_data - parse the userspace IO config and
585 * copy read data to share with userspace
586 * @e_ctrl: ctrl structure
587 * @csl_packet: csl packet received
588 *
589 * Returns success or failure
590 */
591static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
592 struct cam_packet *csl_packet)
593{
594 struct cam_buf_io_cfg *io_cfg;
595 uint32_t i = 0;
596 int rc = 0;
597 uint64_t buf_addr;
598 size_t buf_size;
599 uint8_t *read_buffer;
600
601 io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *)
602 &csl_packet->payload +
603 csl_packet->io_configs_offset);
604
605 CAM_DBG(CAM_EEPROM, "number of IO configs: %d:",
606 csl_packet->num_io_configs);
607
608 for (i = 0; i < csl_packet->num_io_configs; i++) {
609 CAM_DBG(CAM_EEPROM, "Direction: %d:", io_cfg->direction);
610 if (io_cfg->direction == CAM_BUF_OUTPUT) {
611 rc = cam_mem_get_cpu_buf(io_cfg->mem_handle[0],
612 (uint64_t *)&buf_addr, &buf_size);
Soundrapandian Jeyaprakashafdca892017-07-27 15:23:13 -0700613 CAM_DBG(CAM_EEPROM, "buf_addr : %pK, buf_size : %zu\n",
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530614 (void *)buf_addr, buf_size);
615
616 read_buffer = (uint8_t *)buf_addr;
617 if (!read_buffer) {
618 CAM_ERR(CAM_EEPROM,
619 "invalid buffer to copy data");
620 return -EINVAL;
621 }
622 read_buffer += io_cfg->offsets[0];
623
624 if (buf_size < e_ctrl->cal_data.num_data) {
625 CAM_ERR(CAM_EEPROM,
626 "failed to copy, Invalid size");
627 return -EINVAL;
628 }
629
Jigarkumar Zalaae152332017-07-18 17:21:48 -0700630 CAM_DBG(CAM_EEPROM, "copy the data, len:%d",
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530631 e_ctrl->cal_data.num_data);
632 memcpy(read_buffer, e_ctrl->cal_data.mapdata,
633 e_ctrl->cal_data.num_data);
634
635 } else {
636 CAM_ERR(CAM_EEPROM, "Invalid direction");
637 rc = -EINVAL;
638 }
639 }
640 return rc;
641}
642
643/**
644 * cam_eeprom_pkt_parse - Parse csl packet
645 * @e_ctrl: ctrl structure
646 * @arg: Camera control command argument
647 *
648 * Returns success or failure
649 */
650static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
651{
652 int32_t rc = 0;
653 struct cam_control *ioctl_ctrl = NULL;
654 struct cam_config_dev_cmd dev_config;
655 uint64_t generic_pkt_addr;
656 size_t pkt_len;
657 struct cam_packet *csl_packet = NULL;
658 struct cam_eeprom_soc_private *soc_private =
659 (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
Depeng Shao6b7576b2017-11-10 16:04:31 +0800660 struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info;
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530661
662 ioctl_ctrl = (struct cam_control *)arg;
Jigarkumar Zalad724ec22017-10-24 16:30:01 -0700663
664 if (ioctl_ctrl->handle_type != CAM_HANDLE_USER_POINTER) {
665 CAM_ERR(CAM_EEPROM, "Invalid Handle Type");
666 return -EINVAL;
667 }
668
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530669 if (copy_from_user(&dev_config, (void __user *) ioctl_ctrl->handle,
670 sizeof(dev_config)))
671 return -EFAULT;
672 rc = cam_mem_get_cpu_buf(dev_config.packet_handle,
673 (uint64_t *)&generic_pkt_addr, &pkt_len);
674 if (rc) {
675 CAM_ERR(CAM_EEPROM,
676 "error in converting command Handle Error: %d", rc);
677 return rc;
678 }
Jigarkumar Zalad724ec22017-10-24 16:30:01 -0700679
680 if (dev_config.offset > pkt_len) {
681 CAM_ERR(CAM_EEPROM,
682 "Offset is out of bound: off: %lld, %zu",
683 dev_config.offset, pkt_len);
684 return -EINVAL;
685 }
686
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530687 csl_packet = (struct cam_packet *)
688 (generic_pkt_addr + dev_config.offset);
689 switch (csl_packet->header.op_code & 0xFFFFFF) {
690 case CAM_EEPROM_PACKET_OPCODE_INIT:
691 if (e_ctrl->userspace_probe == false) {
Sureshnaidu Laveti389cf0d2017-09-25 22:35:55 -0700692 rc = cam_eeprom_parse_read_memory_map(
Sureshnaidu Lavetid02f7ad2017-10-06 10:58:24 -0700693 e_ctrl->soc_info.dev->of_node, e_ctrl);
Sureshnaidu Laveti389cf0d2017-09-25 22:35:55 -0700694 if (rc < 0) {
695 CAM_ERR(CAM_EEPROM, "Failed: rc : %d", rc);
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530696 return rc;
697 }
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530698 rc = cam_eeprom_get_cal_data(e_ctrl, csl_packet);
Sureshnaidu Laveti389cf0d2017-09-25 22:35:55 -0700699 kfree(e_ctrl->cal_data.mapdata);
700 kfree(e_ctrl->cal_data.map);
701 e_ctrl->cal_data.num_data = 0;
702 e_ctrl->cal_data.num_map = 0;
703 CAM_DBG(CAM_EEPROM,
704 "Returning the data using kernel probe");
Depeng Shao6b7576b2017-11-10 16:04:31 +0800705 break;
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530706 }
Sureshnaidu Laveti389cf0d2017-09-25 22:35:55 -0700707 rc = cam_eeprom_init_pkt_parser(e_ctrl, csl_packet);
708 if (rc) {
709 CAM_ERR(CAM_EEPROM,
710 "Failed in parsing the pkt");
711 return rc;
712 }
713
714 e_ctrl->cal_data.mapdata =
715 kzalloc(e_ctrl->cal_data.num_data, GFP_KERNEL);
716 if (!e_ctrl->cal_data.mapdata) {
717 rc = -ENOMEM;
718 CAM_ERR(CAM_EEPROM, "failed");
719 goto error;
720 }
721
722 rc = cam_eeprom_power_up(e_ctrl,
723 &soc_private->power_info);
724 if (rc) {
725 CAM_ERR(CAM_EEPROM, "failed rc %d", rc);
726 goto memdata_free;
727 }
728
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700729 e_ctrl->cam_eeprom_state = CAM_EEPROM_CONFIG;
Sureshnaidu Laveti389cf0d2017-09-25 22:35:55 -0700730 rc = cam_eeprom_read_memory(e_ctrl, &e_ctrl->cal_data);
731 if (rc) {
732 CAM_ERR(CAM_EEPROM,
733 "read_eeprom_memory failed");
734 goto power_down;
735 }
736
737 rc = cam_eeprom_get_cal_data(e_ctrl, csl_packet);
738 rc = cam_eeprom_power_down(e_ctrl);
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700739 e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE;
Sureshnaidu Laveti389cf0d2017-09-25 22:35:55 -0700740 kfree(e_ctrl->cal_data.mapdata);
741 kfree(e_ctrl->cal_data.map);
742 e_ctrl->cal_data.num_data = 0;
743 e_ctrl->cal_data.num_map = 0;
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530744 break;
745 default:
746 break;
747 }
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530748 return rc;
749power_down:
Sureshnaidu Laveti3dc87ea2017-10-15 20:53:42 -0700750 cam_eeprom_power_down(e_ctrl);
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530751memdata_free:
752 kfree(e_ctrl->cal_data.mapdata);
753error:
Depeng Shao6b7576b2017-11-10 16:04:31 +0800754 kfree(power_info->power_setting);
755 kfree(power_info->power_down_setting);
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530756 kfree(e_ctrl->cal_data.map);
Sureshnaidu Laveti389cf0d2017-09-25 22:35:55 -0700757 e_ctrl->cal_data.num_data = 0;
758 e_ctrl->cal_data.num_map = 0;
Depeng Shao6b7576b2017-11-10 16:04:31 +0800759 e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530760 return rc;
761}
762
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -0700763void cam_eeprom_shutdown(struct cam_eeprom_ctrl_t *e_ctrl)
764{
765 int rc;
Depeng Shao6b7576b2017-11-10 16:04:31 +0800766 struct cam_eeprom_soc_private *soc_private =
767 (struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
768 struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info;
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -0700769
770 if (e_ctrl->cam_eeprom_state == CAM_EEPROM_INIT)
771 return;
772
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700773 if (e_ctrl->cam_eeprom_state == CAM_EEPROM_CONFIG) {
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -0700774 rc = cam_eeprom_power_down(e_ctrl);
775 if (rc < 0)
776 CAM_ERR(CAM_EEPROM, "EEPROM Power down failed");
777 e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE;
778 }
779
780 if (e_ctrl->cam_eeprom_state == CAM_EEPROM_ACQUIRE) {
781 rc = cam_destroy_device_hdl(e_ctrl->bridge_intf.device_hdl);
782 if (rc < 0)
783 CAM_ERR(CAM_EEPROM, "destroying the device hdl");
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700784
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -0700785 e_ctrl->bridge_intf.device_hdl = -1;
786 e_ctrl->bridge_intf.link_hdl = -1;
787 e_ctrl->bridge_intf.session_hdl = -1;
Depeng Shao6b7576b2017-11-10 16:04:31 +0800788
789 kfree(power_info->power_setting);
790 kfree(power_info->power_down_setting);
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -0700791 }
792
793 e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
794}
795
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530796/**
797 * cam_eeprom_driver_cmd - Handle eeprom cmds
798 * @e_ctrl: ctrl structure
799 * @arg: Camera control command argument
800 *
801 * Returns success or failure
802 */
803int32_t cam_eeprom_driver_cmd(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
804{
805 int rc = 0;
Soundrapandian Jeyaprakasha37cb232017-08-22 15:27:23 -0700806 struct cam_eeprom_query_cap_t eeprom_cap = {0};
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530807 struct cam_control *cmd = (struct cam_control *)arg;
808
809 if (!e_ctrl) {
810 CAM_ERR(CAM_EEPROM, "e_ctrl is NULL");
811 return -EINVAL;
812 }
813
814 mutex_lock(&(e_ctrl->eeprom_mutex));
815 switch (cmd->op_code) {
816 case CAM_QUERY_CAP:
Depeng Shao0fe56182017-09-25 11:13:48 +0800817 eeprom_cap.slot_info = e_ctrl->soc_info.index;
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530818 if (e_ctrl->userspace_probe == false)
819 eeprom_cap.eeprom_kernel_probe = true;
820 else
821 eeprom_cap.eeprom_kernel_probe = false;
822
823 if (copy_to_user((void __user *) cmd->handle,
824 &eeprom_cap,
825 sizeof(struct cam_eeprom_query_cap_t))) {
826 CAM_ERR(CAM_EEPROM, "Failed Copy to User");
827 return -EFAULT;
828 goto release_mutex;
829 }
830 CAM_DBG(CAM_EEPROM, "eeprom_cap: ID: %d", eeprom_cap.slot_info);
831 break;
832 case CAM_ACQUIRE_DEV:
833 rc = cam_eeprom_get_dev_handle(e_ctrl, arg);
834 if (rc) {
835 CAM_ERR(CAM_EEPROM, "Failed to acquire dev");
836 goto release_mutex;
837 }
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -0700838 e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE;
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530839 break;
Sureshnaidu Laveti389cf0d2017-09-25 22:35:55 -0700840 case CAM_RELEASE_DEV:
Karthik Anantha Ram4f5d66e2017-10-18 13:59:14 -0700841 if (e_ctrl->cam_eeprom_state != CAM_EEPROM_ACQUIRE) {
842 rc = -EINVAL;
843 CAM_WARN(CAM_EEPROM,
844 "Not in right state to release : %d",
845 e_ctrl->cam_eeprom_state);
846 goto release_mutex;
847 }
848
Sureshnaidu Laveti389cf0d2017-09-25 22:35:55 -0700849 if (e_ctrl->bridge_intf.device_hdl == -1) {
850 CAM_ERR(CAM_EEPROM,
851 "Invalid Handles: link hdl: %d device hdl: %d",
852 e_ctrl->bridge_intf.device_hdl,
853 e_ctrl->bridge_intf.link_hdl);
854 rc = -EINVAL;
855 goto release_mutex;
856 }
857 rc = cam_destroy_device_hdl(e_ctrl->bridge_intf.device_hdl);
858 if (rc < 0)
859 CAM_ERR(CAM_EEPROM,
860 "failed in destroying the device hdl");
861 e_ctrl->bridge_intf.device_hdl = -1;
862 e_ctrl->bridge_intf.link_hdl = -1;
863 e_ctrl->bridge_intf.session_hdl = -1;
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -0700864 e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
Sureshnaidu Laveti389cf0d2017-09-25 22:35:55 -0700865 break;
Vivek Veenam2ad8de12017-04-04 18:56:22 +0530866 case CAM_CONFIG_DEV:
867 rc = cam_eeprom_pkt_parse(e_ctrl, arg);
868 if (rc) {
869 CAM_ERR(CAM_EEPROM, "Failed in eeprom pkt Parsing");
870 goto release_mutex;
871 }
872 break;
873 default:
874 CAM_DBG(CAM_EEPROM, "invalid opcode");
875 break;
876 }
877
878release_mutex:
879 mutex_unlock(&(e_ctrl->eeprom_mutex));
880
881 return rc;
882}
883