Commit | Line | Data |
---|---|---|
1cac41cb MB |
1 | /* |
2 | * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | */ | |
15 | #include "ssp.h" | |
16 | ||
17 | #define LIMIT_DELAY_CNT 200 | |
18 | #define RECEIVEBUFFERSIZE 12 | |
19 | #define DEBUG_SHOW_DATA 0 | |
20 | ||
21 | void clean_msg(struct ssp_msg *msg) | |
22 | { | |
23 | if (msg->free_buffer) | |
24 | kfree(msg->buffer); | |
25 | kfree(msg); | |
26 | } | |
27 | ||
28 | static int do_transfer(struct ssp_data *data, struct ssp_msg *msg, | |
29 | struct completion *done, int timeout) | |
30 | { | |
31 | return bbd_do_transfer(data, msg, done, timeout); | |
32 | } | |
33 | ||
34 | int ssp_spi_async(struct ssp_data *data, struct ssp_msg *msg) | |
35 | { | |
36 | int status = 0; | |
37 | u64 diff = get_current_timestamp() - data->resumeTimestamp; | |
38 | int timeout = diff < 5000000000ULL ? 400 : 1000; // unit: ms | |
39 | ||
40 | if (msg->length) | |
41 | return ssp_spi_sync(data, msg, timeout); | |
42 | ||
43 | status = do_transfer(data, msg, NULL, 0); | |
44 | ||
45 | return status; | |
46 | } | |
47 | ||
48 | int ssp_spi_sync(struct ssp_data *data, struct ssp_msg *msg, int timeout) | |
49 | { | |
50 | DECLARE_COMPLETION_ONSTACK(done); | |
51 | int status = 0; | |
52 | ||
53 | if (msg->length == 0) { | |
54 | pr_err("[SSP]: %s length must not be 0\n", __func__); | |
55 | clean_msg(msg); | |
56 | return status; | |
57 | } | |
58 | ||
59 | status = do_transfer(data, msg, &done, timeout); | |
60 | ||
61 | return status; | |
62 | } | |
63 | ||
64 | int select_irq_msg(struct ssp_data *data) | |
65 | { | |
66 | struct ssp_msg *msg, *n; | |
67 | bool found = false; | |
68 | u16 chLength = 0, msg_options = 0; | |
69 | u8 msg_type = 0; | |
70 | int iRet = 0; | |
71 | char *buffer; | |
72 | char chTempBuf[4] = { -1 }; | |
73 | ||
74 | data->bHandlingIrq = true; | |
75 | iRet = spi_read(data->spi, chTempBuf, sizeof(chTempBuf)); | |
76 | if (iRet < 0) { | |
77 | pr_err("[SSP] %s spi_read fail, ret = %d\n", __func__, iRet); | |
78 | data->bHandlingIrq = false; | |
79 | return iRet; | |
80 | } | |
81 | ||
82 | memcpy(&msg_options, &chTempBuf[0], 2); | |
83 | msg_type = msg_options & SSP_SPI_MASK; | |
84 | memcpy(&chLength, &chTempBuf[2], 2); | |
85 | ||
86 | switch (msg_type) { | |
87 | case AP2HUB_READ: | |
88 | case AP2HUB_WRITE: | |
89 | mutex_lock(&data->pending_mutex); | |
90 | if (!list_empty(&data->pending_list)) { | |
91 | list_for_each_entry_safe(msg, n, | |
92 | &data->pending_list, list) { | |
93 | ||
94 | if (msg->options == msg_options) { | |
95 | list_del(&msg->list); | |
96 | found = true; | |
97 | break; | |
98 | } | |
99 | } | |
100 | ||
101 | if (!found) { | |
102 | pr_err("[SSP]: %s %d - Not match error\n", | |
103 | __func__, msg_options); | |
104 | goto exit; | |
105 | } | |
106 | ||
107 | if (msg->dead && !msg->free_buffer) { | |
108 | msg->buffer = (char *) kzalloc(msg->length, GFP_KERNEL); | |
109 | msg->free_buffer = 1; | |
110 | } /* For dead msg, make a temporary buffer to read. */ | |
111 | ||
112 | if (msg_type == AP2HUB_READ) { | |
113 | iRet = spi_read(data->spi, | |
114 | msg->buffer, msg->length); | |
115 | } | |
116 | if (msg_type == AP2HUB_WRITE) { | |
117 | iRet = spi_write(data->spi, | |
118 | msg->buffer, msg->length); | |
119 | ||
120 | if (msg_options & AP2HUB_RETURN) { | |
121 | msg->options = AP2HUB_READ | |
122 | | AP2HUB_RETURN; | |
123 | msg->length = 1; | |
124 | list_add_tail(&msg->list, | |
125 | &data->pending_list); | |
126 | goto exit; | |
127 | } | |
128 | } | |
129 | ||
130 | if (msg->done != NULL && !completion_done(msg->done)) | |
131 | complete(msg->done); | |
132 | if (msg->dead_hook != NULL) | |
133 | *(msg->dead_hook) = true; | |
134 | ||
135 | clean_msg(msg); | |
136 | } else | |
137 | pr_err("[SSP]List empty error(%d)\n", msg_type); | |
138 | exit: | |
139 | mutex_unlock(&data->pending_mutex); | |
140 | break; | |
141 | case HUB2AP_WRITE: | |
142 | buffer = (char *) kzalloc(chLength, GFP_KERNEL); | |
143 | if (buffer == NULL) { | |
144 | pr_err("[SSP] %s, failed to alloc memory for buffer\n", | |
145 | __func__); | |
146 | iRet = -ENOMEM; | |
147 | break; | |
148 | } | |
149 | iRet = spi_read(data->spi, buffer, chLength); | |
150 | if (iRet < 0) | |
151 | pr_err("[SSP] %s spi_read fail\n", __func__); | |
152 | else | |
153 | parse_dataframe(data, buffer, chLength); | |
154 | kfree(buffer); | |
155 | break; | |
156 | default: | |
157 | pr_err("[SSP]No type error(%d)\n", msg_type); | |
158 | break; | |
159 | } | |
160 | ||
161 | if (iRet < 0) { | |
162 | pr_err("[SSP]: %s - MSG2SSP_SSD error %d\n", __func__, iRet); | |
163 | data->bHandlingIrq = false; | |
164 | return ERROR; | |
165 | } | |
166 | ||
167 | data->bHandlingIrq = false; | |
168 | return SUCCESS; | |
169 | } | |
170 | ||
171 | void clean_pending_list(struct ssp_data *data) | |
172 | { | |
173 | struct ssp_msg *msg, *n; | |
174 | ||
175 | mutex_lock(&data->pending_mutex); | |
176 | list_for_each_entry_safe(msg, n, &data->pending_list, list) { | |
177 | list_del(&msg->list); | |
178 | if (msg->done != NULL && !completion_done(msg->done)) | |
179 | complete(msg->done); | |
180 | if (msg->dead_hook != NULL) | |
181 | *(msg->dead_hook) = true; | |
182 | ||
183 | clean_msg(msg); | |
184 | } | |
185 | mutex_unlock(&data->pending_mutex); | |
186 | } | |
187 | ||
188 | int ssp_send_cmd(struct ssp_data *data, char command, int arg) | |
189 | { | |
190 | int iRet = 0; | |
191 | struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
192 | ||
193 | if (msg == NULL) { | |
194 | iRet = -ENOMEM; | |
195 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
196 | __func__); | |
197 | return iRet; | |
198 | } | |
199 | msg->cmd = command; | |
200 | msg->length = 0; | |
201 | msg->options = AP2HUB_WRITE; | |
202 | msg->data = arg; | |
203 | msg->free_buffer = 0; | |
204 | ||
205 | iRet = ssp_spi_async(data, msg); | |
206 | if (iRet != SUCCESS) { | |
207 | pr_err("[SSP]: %s - command 0x%x failed %d\n", | |
208 | __func__, command, iRet); | |
209 | return ERROR; | |
210 | } | |
211 | ||
212 | ssp_dbg("[SSP]: %s - command 0x%x %d\n", __func__, command, arg); | |
213 | ||
214 | return SUCCESS; | |
215 | } | |
216 | ||
217 | int send_instruction(struct ssp_data *data, u8 uInst, | |
218 | u8 uSensorType, u8 *uSendBuf, u16 uLength) | |
219 | { | |
220 | char command; | |
221 | int iRet = 0; | |
222 | struct ssp_msg *msg; | |
223 | ||
224 | //u64 current_Ts = 0; | |
225 | #ifdef CONFIG_SENSORS_SSP_HIFI_BATCHING | |
226 | u64 timestamp; | |
227 | #endif | |
228 | ||
229 | if ((!(data->uSensorState & (1ULL << uSensorType))) | |
230 | && (uInst <= CHANGE_DELAY)) { | |
231 | pr_err("[SSP]: %s - Bypass Inst Skip! - %u\n", | |
232 | __func__, uSensorType); | |
233 | return FAIL; | |
234 | } | |
235 | ||
236 | switch (uInst) { | |
237 | case REMOVE_SENSOR: | |
238 | command = MSG2SSP_INST_BYPASS_SENSOR_REMOVE; | |
239 | break; | |
240 | case ADD_SENSOR: | |
241 | command = MSG2SSP_INST_BYPASS_SENSOR_ADD; | |
242 | #ifdef CONFIG_SENSORS_SSP_HIFI_BATCHING | |
243 | timestamp = get_current_timestamp(); | |
244 | data->lastTimestamp[uSensorType] = data->LastSensorTimeforReset[uSensorType] = timestamp; | |
245 | data->ts_avg_buffer_idx[uSensorType] = 0; | |
246 | data->ts_avg_buffer_cnt[uSensorType] = 0; | |
247 | data->ts_avg_buffer_sum[uSensorType] = 0; | |
248 | data->ts_prev_index[uSensorType] = 0; | |
249 | data->ts_avg_skip_cnt[uSensorType] = SKIP_CNT_MOVING_AVG_ADD; | |
250 | data->ts_last_enable_cmd_time = timestamp; | |
251 | memset(data->ts_avg_buffer[uSensorType], 0, | |
252 | sizeof(u64)*SIZE_MOVING_AVG_BUFFER); | |
253 | #endif | |
254 | data->first_sensor_data[uSensorType] = true; | |
255 | break; | |
256 | case CHANGE_DELAY: | |
257 | command = MSG2SSP_INST_CHANGE_DELAY; | |
258 | #ifdef CONFIG_SENSORS_SSP_HIFI_BATCHING | |
259 | timestamp = get_current_timestamp(); | |
260 | data->LastSensorTimeforReset[uSensorType] = timestamp; | |
261 | data->ts_avg_buffer_idx[uSensorType] = 0; | |
262 | data->ts_avg_buffer_cnt[uSensorType] = 0; | |
263 | data->ts_avg_buffer_sum[uSensorType] = 0; | |
264 | data->ts_prev_index[uSensorType] = 0; | |
265 | data->ts_avg_skip_cnt[uSensorType] = SKIP_CNT_MOVING_AVG_CHANGE; | |
266 | memset(data->ts_avg_buffer[uSensorType], 0, | |
267 | sizeof(u64)*SIZE_MOVING_AVG_BUFFER); | |
268 | #endif | |
269 | data->first_sensor_data[uSensorType] = true; | |
270 | break; | |
271 | case GO_SLEEP: | |
272 | command = MSG2SSP_AP_STATUS_SLEEP; | |
273 | data->uLastAPState = MSG2SSP_AP_STATUS_SLEEP; | |
274 | break; | |
275 | case REMOVE_LIBRARY: | |
276 | command = MSG2SSP_INST_LIBRARY_REMOVE; | |
277 | break; | |
278 | case ADD_LIBRARY: | |
279 | command = MSG2SSP_INST_LIBRARY_ADD; | |
280 | break; | |
281 | default: | |
282 | command = uInst; | |
283 | break; | |
284 | } | |
285 | ||
286 | msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
287 | if (msg == NULL) { | |
288 | iRet = -ENOMEM; | |
289 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
290 | __func__); | |
291 | return iRet; | |
292 | } | |
293 | msg->cmd = command; | |
294 | msg->length = uLength + 1; | |
295 | msg->options = AP2HUB_WRITE; | |
296 | msg->buffer = (char *) kzalloc(uLength + 1, GFP_KERNEL); | |
297 | msg->free_buffer = 1; | |
298 | ||
299 | msg->buffer[0] = uSensorType; | |
300 | memcpy(&msg->buffer[1], uSendBuf, uLength); | |
301 | ||
302 | ssp_dbg("[SSP]: %s - Inst = 0x%x, Sensor Type = 0x%x, data = %u\n", | |
303 | __func__, command, uSensorType, msg->buffer[1]); | |
304 | ||
305 | iRet = ssp_spi_async(data, msg); | |
306 | ||
307 | if (iRet != SUCCESS) { | |
308 | pr_err("[SSP]: %s - Instruction CMD Fail %d\n", __func__, iRet); | |
309 | return ERROR; | |
310 | } | |
311 | ||
312 | if (uInst == ADD_SENSOR || uInst == CHANGE_DELAY) { | |
313 | unsigned int BatchTimeforReset = 0; | |
314 | //current_Ts = get_current_timestamp(); | |
28765241 | 315 | if (uLength >= 9) { |
1cac41cb MB |
316 | BatchTimeforReset = *(unsigned int *)(&uSendBuf[4]);// Add / change normal case, not factory. |
317 | //pr_info("[SSP] %s timeForRest %d", __func__, BatchTimeforReset); | |
318 | data->IsBypassMode[uSensorType] = (BatchTimeforReset == 0); | |
319 | //pr_info("[SSP] sensor%d mode%d Time %lld\n", uSensorType, data->IsBypassMode[uSensorType], current_Ts); | |
28765241 | 320 | } |
1cac41cb MB |
321 | } |
322 | return iRet; | |
323 | } | |
324 | ||
325 | int send_instruction_sync(struct ssp_data *data, u8 uInst, | |
326 | u8 uSensorType, u8 *uSendBuf, u16 uLength) | |
327 | { | |
328 | char command; | |
329 | int iRet = 0; | |
330 | char buffer[10] = { 0, }; | |
331 | struct ssp_msg *msg; | |
332 | ||
333 | //u64 current_Ts = 0; | |
334 | #ifdef CONFIG_SENSORS_SSP_HIFI_BATCHING | |
335 | u64 timestamp; | |
336 | #endif | |
337 | ||
338 | if ((!(data->uSensorState & (1ULL << uSensorType))) | |
339 | && (uInst <= CHANGE_DELAY)) { | |
340 | pr_err("[SSP]: %s - Bypass Inst Skip! - %u\n", | |
341 | __func__, uSensorType); | |
342 | return FAIL; | |
343 | } | |
344 | ||
345 | switch (uInst) { | |
346 | case REMOVE_SENSOR: | |
347 | command = MSG2SSP_INST_BYPASS_SENSOR_REMOVE; | |
348 | break; | |
349 | case ADD_SENSOR: | |
350 | command = MSG2SSP_INST_BYPASS_SENSOR_ADD; | |
351 | #ifdef CONFIG_SENSORS_SSP_HIFI_BATCHING | |
352 | timestamp = get_current_timestamp(); | |
353 | data->lastTimestamp[uSensorType] = data->LastSensorTimeforReset[uSensorType] = timestamp; | |
354 | data->ts_avg_buffer_idx[uSensorType] = 0; | |
355 | data->ts_avg_buffer_cnt[uSensorType] = 0; | |
356 | data->ts_avg_buffer_sum[uSensorType] = 0; | |
357 | data->ts_prev_index[uSensorType] = 0; | |
358 | data->ts_avg_skip_cnt[uSensorType] = SKIP_CNT_MOVING_AVG_ADD; | |
359 | data->ts_last_enable_cmd_time = timestamp; | |
360 | memset(data->ts_avg_buffer[uSensorType], 0, | |
361 | sizeof(u64)*SIZE_MOVING_AVG_BUFFER); | |
362 | #endif | |
363 | data->first_sensor_data[uSensorType] = true; | |
364 | break; | |
365 | case CHANGE_DELAY: | |
366 | command = MSG2SSP_INST_CHANGE_DELAY; | |
367 | #ifdef CONFIG_SENSORS_SSP_HIFI_BATCHING | |
368 | timestamp = get_current_timestamp(); | |
369 | data->LastSensorTimeforReset[uSensorType] = timestamp; | |
370 | data->ts_avg_buffer_idx[uSensorType] = 0; | |
371 | data->ts_avg_buffer_cnt[uSensorType] = 0; | |
372 | data->ts_avg_buffer_sum[uSensorType] = 0; | |
373 | data->ts_prev_index[uSensorType] = 0; | |
374 | data->ts_avg_skip_cnt[uSensorType] = SKIP_CNT_MOVING_AVG_CHANGE; | |
375 | memset(data->ts_avg_buffer[uSensorType], 0, | |
376 | sizeof(u64)*SIZE_MOVING_AVG_BUFFER); | |
377 | #endif | |
378 | data->first_sensor_data[uSensorType] = true; | |
379 | break; | |
380 | case GO_SLEEP: | |
381 | command = MSG2SSP_AP_STATUS_SLEEP; | |
382 | data->uLastAPState = MSG2SSP_AP_STATUS_SLEEP; | |
383 | break; | |
384 | case REMOVE_LIBRARY: | |
385 | command = MSG2SSP_INST_LIBRARY_REMOVE; | |
386 | break; | |
387 | case ADD_LIBRARY: | |
388 | command = MSG2SSP_INST_LIBRARY_ADD; | |
389 | break; | |
390 | default: | |
391 | command = uInst; | |
392 | break; | |
393 | } | |
394 | ||
395 | msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
396 | if (msg == NULL) { | |
397 | iRet = -ENOMEM; | |
398 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
399 | __func__); | |
400 | return iRet; | |
401 | } | |
402 | msg->cmd = command; | |
403 | msg->length = uLength + 1; | |
404 | msg->options = AP2HUB_WRITE | AP2HUB_RETURN; | |
405 | msg->buffer = buffer; | |
406 | msg->free_buffer = 0; | |
407 | ||
408 | msg->buffer[0] = uSensorType; | |
409 | memcpy(&msg->buffer[1], uSendBuf, uLength); | |
410 | ||
411 | ssp_dbg("[SSP]: %s - Inst Sync = 0x%x, Sensor Type = %u, data = %u\n", | |
412 | __func__, command, uSensorType, msg->buffer[0]); | |
413 | ||
414 | iRet = ssp_spi_sync(data, msg, 1000); | |
415 | ||
416 | if (iRet != SUCCESS) { | |
417 | pr_err("[SSP]: %s - Instruction CMD Fail %d\n", __func__, iRet); | |
418 | return ERROR; | |
419 | } | |
420 | ||
421 | if (uInst == ADD_SENSOR || uInst == CHANGE_DELAY) { | |
422 | unsigned int BatchTimeforReset = 0; | |
423 | //current_Ts = get_current_timestamp(); | |
424 | if (uLength >= 9) | |
425 | BatchTimeforReset = *(unsigned int *)(&uSendBuf[4]);// Add / change normal case, not factory. | |
426 | //pr_info("[SSP] %s timeForRest %d", __func__, BatchTimeforReset); | |
427 | data->IsBypassMode[uSensorType] = (BatchTimeforReset == 0); | |
428 | //pr_info("[SSP] sensor%d mode%d Time %lld\n", uSensorType, data->IsBypassMode[uSensorType], current_Ts); | |
429 | } | |
430 | return buffer[0]; | |
431 | } | |
432 | ||
433 | int flush(struct ssp_data *data, u8 uSensorType) | |
434 | { | |
435 | int iRet = 0; | |
436 | char buffer = 0; | |
437 | struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
438 | ||
439 | if (msg == NULL) { | |
440 | iRet = -ENOMEM; | |
441 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
442 | __func__); | |
443 | return iRet; | |
444 | } | |
445 | msg->cmd = MSG2SSP_AP_MCU_BATCH_FLUSH; | |
446 | msg->length = 1; | |
447 | msg->options = AP2HUB_READ; | |
448 | msg->data = uSensorType; | |
449 | msg->buffer = &buffer; | |
450 | msg->free_buffer = 0; | |
451 | ||
452 | iRet = ssp_spi_sync(data, msg, 1000); | |
453 | ||
454 | if (iRet != SUCCESS) { | |
455 | pr_err("[SSP]: %s - fail %d\n", __func__, iRet); | |
456 | return ERROR; | |
457 | } | |
458 | ||
459 | ssp_dbg("[SSP]: %s Sensor Type = 0x%x, data = %u\n", | |
460 | __func__, uSensorType, buffer); | |
461 | ||
462 | return buffer ? 0 : -1; | |
463 | } | |
464 | ||
465 | int get_batch_count(struct ssp_data *data, u8 uSensorType) | |
466 | { | |
467 | int iRet = 0; | |
468 | s32 result = 0; | |
469 | char buffer[4] = {0, }; | |
470 | struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
471 | ||
472 | if (msg == NULL) { | |
473 | iRet = -ENOMEM; | |
474 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
475 | __func__); | |
476 | return iRet; | |
477 | } | |
478 | msg->cmd = MSG2SSP_AP_MCU_BATCH_COUNT; | |
479 | msg->length = 4; | |
480 | msg->options = AP2HUB_READ; | |
481 | msg->data = uSensorType; | |
482 | msg->buffer = buffer; | |
483 | msg->free_buffer = 0; | |
484 | ||
485 | iRet = ssp_spi_sync(data, msg, 1000); | |
486 | ||
487 | if (iRet != SUCCESS) { | |
488 | pr_err("[SSP]: %s - fail %d\n", __func__, iRet); | |
489 | return ERROR; | |
490 | } | |
491 | ||
492 | memcpy(&result, buffer, 4); | |
493 | ||
494 | ssp_dbg("[SSP]: %s Sensor Type = 0x%x, data = %u\n", | |
495 | __func__, uSensorType, result); | |
496 | ||
497 | return result; | |
498 | } | |
499 | ||
500 | int get_chipid(struct ssp_data *data) | |
501 | { | |
502 | int iRet, iReties = 0; | |
503 | char buffer = 0; | |
504 | struct ssp_msg *msg; | |
505 | ||
506 | retries: | |
507 | msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
508 | if (msg == NULL) { | |
509 | iRet = -ENOMEM; | |
510 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
511 | __func__); | |
512 | return iRet; | |
513 | } | |
514 | msg->cmd = MSG2SSP_AP_WHOAMI; | |
515 | msg->length = 1; | |
516 | msg->options = AP2HUB_READ; | |
517 | msg->buffer = &buffer; | |
518 | msg->free_buffer = 0; | |
519 | ||
520 | iRet = ssp_spi_sync(data, msg, 1000); | |
521 | ||
522 | if (buffer != DEVICE_ID && iReties++ < 2) { | |
523 | mdelay(5); | |
524 | pr_err("[SSP] %s - get chip ID retry\n", __func__); | |
525 | goto retries; | |
526 | } | |
527 | ||
528 | if (iRet == SUCCESS) | |
529 | return buffer; | |
530 | ||
531 | pr_err("[SSP] %s - get chip ID failed %d\n", __func__, iRet); | |
532 | return ERROR; | |
533 | } | |
534 | ||
535 | int set_sensor_position(struct ssp_data *data) | |
536 | { | |
537 | int iRet = 0; | |
538 | struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
539 | ||
540 | if (msg == NULL) { | |
541 | iRet = -ENOMEM; | |
542 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
543 | __func__); | |
544 | return iRet; | |
545 | } | |
546 | msg->cmd = MSG2SSP_AP_SENSOR_FORMATION; | |
547 | msg->length = 3; | |
548 | msg->options = AP2HUB_WRITE; | |
549 | msg->buffer = (char *) kzalloc(3, GFP_KERNEL); | |
550 | msg->free_buffer = 1; | |
551 | ||
552 | msg->buffer[0] = data->accel_position; | |
553 | msg->buffer[1] = data->accel_position; | |
554 | msg->buffer[2] = data->mag_position; | |
555 | ||
556 | iRet = ssp_spi_async(data, msg); | |
557 | ||
558 | pr_info("[SSP] Sensor Posision A : %u, G : %u, M: %u, P: %u\n", | |
559 | data->accel_position, | |
560 | data->accel_position, | |
561 | data->mag_position, 0); | |
562 | ||
563 | if (iRet != SUCCESS) { | |
564 | pr_err("[SSP] %s -fail to %s %d\n", | |
565 | __func__, __func__, iRet); | |
566 | iRet = ERROR; | |
567 | } | |
568 | ||
569 | return iRet; | |
570 | } | |
571 | ||
572 | #ifdef CONFIG_SENSORS_MULTIPLE_GLASS_TYPE | |
573 | int set_glass_type(struct ssp_data *data) | |
574 | { | |
575 | int iRet = 0; | |
576 | struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
577 | ||
578 | if (msg == NULL) { | |
579 | iRet = -ENOMEM; | |
580 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
581 | __func__); | |
582 | return iRet; | |
583 | } | |
584 | msg->cmd = MSG2SSP_AP_GLASS_TYPE; | |
585 | msg->length = 1; | |
586 | msg->options = AP2HUB_WRITE; | |
587 | msg->buffer = (char *) kzalloc(1, GFP_KERNEL); | |
588 | msg->free_buffer = 1; | |
589 | ||
590 | msg->buffer[0] = data->glass_type; | |
591 | ||
592 | iRet = ssp_spi_async(data, msg); | |
593 | ||
594 | pr_info("[SSP] glass_type : %u\n", data->glass_type); | |
595 | ||
596 | if (iRet != SUCCESS) { | |
597 | pr_err("[SSP] %s -fail to %s %d\n", | |
598 | __func__, __func__, iRet); | |
599 | iRet = ERROR; | |
600 | } | |
601 | ||
602 | return iRet; | |
603 | } | |
604 | #endif | |
605 | ||
606 | int set_magnetic_static_matrix(struct ssp_data *data) | |
607 | { | |
608 | int iRet = 0; | |
609 | struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
610 | ||
611 | if (msg == NULL) { | |
612 | iRet = -ENOMEM; | |
613 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
614 | __func__); | |
615 | return iRet; | |
616 | } | |
617 | msg->cmd = MSG2SSP_AP_SET_MAGNETIC_STATIC_MATRIX; | |
618 | msg->length = data->mag_matrix_size; | |
619 | msg->options = AP2HUB_WRITE; | |
620 | msg->buffer = (char *) kzalloc(data->mag_matrix_size, GFP_KERNEL); | |
621 | msg->free_buffer = 1; | |
622 | ||
623 | memcpy(msg->buffer, data->mag_matrix, data->mag_matrix_size); | |
624 | ||
625 | iRet = ssp_spi_async(data, msg); | |
626 | if (iRet != SUCCESS) { | |
627 | pr_err("[SSP] %s -fail to %s %d\n", | |
628 | __func__, __func__, iRet); | |
629 | iRet = ERROR; | |
630 | } | |
631 | ||
632 | return iRet; | |
633 | } | |
634 | ||
635 | void set_proximity_threshold(struct ssp_data *data) | |
636 | { | |
637 | int iRet = 0; | |
638 | ||
639 | struct ssp_msg *msg; | |
640 | ||
641 | if (!(data->uSensorState & (1 << PROXIMITY_SENSOR))) { | |
642 | pr_info("[SSP]: %s - Skip this function!!!,proximity sensor is not connected(0x%llx)\n", | |
643 | __func__, data->uSensorState); | |
644 | return; | |
645 | } | |
646 | ||
647 | msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
648 | #if defined(CONFIG_SENSORS_SSP_TMG399x) | |
649 | msg->cmd = MSG2SSP_AP_SENSOR_PROXTHRESHOLD; | |
650 | msg->length = 2; | |
651 | msg->options = AP2HUB_WRITE; | |
652 | msg->buffer = (char *) kzalloc(2, GFP_KERNEL); | |
653 | msg->free_buffer = 1; | |
654 | ||
655 | msg->buffer[0] = (char)data->uProxHiThresh; | |
656 | msg->buffer[1] = (char)data->uProxLoThresh; | |
657 | #elif defined(CONFIG_SENSORS_SSP_PROX_AUTOCAL_AMS) | |
658 | msg->cmd = MSG2SSP_AP_SENSOR_PROXTHRESHOLD; | |
659 | msg->length = 8; | |
660 | msg->options = AP2HUB_WRITE; | |
661 | msg->buffer = (char *) kzalloc(8, GFP_KERNEL); | |
662 | msg->free_buffer = 1; | |
663 | ||
664 | msg->buffer[0] = ((char) (data->uProxHiThresh >> 8) & 0xff); | |
665 | msg->buffer[1] = (char) data->uProxHiThresh; | |
666 | msg->buffer[2] = ((char) (data->uProxLoThresh >> 8) & 0xff); | |
667 | msg->buffer[3] = (char) data->uProxLoThresh; | |
668 | msg->buffer[4] = ((char) (data->uProxHiThresh_detect >> 8) & 0xff); | |
669 | msg->buffer[5] = (char) data->uProxHiThresh_detect; | |
670 | msg->buffer[6] = ((char) (data->uProxLoThresh_detect >> 8) & 0xff); | |
671 | msg->buffer[7] = (char) data->uProxLoThresh_detect; | |
672 | #else /* CONFIG_SENSORS_SSP_PROX_FACTORYCAL */ | |
673 | msg->cmd = MSG2SSP_AP_SENSOR_PROXTHRESHOLD; | |
674 | msg->length = 4; | |
675 | msg->options = AP2HUB_WRITE; | |
676 | msg->buffer = (char *) kzalloc(4, GFP_KERNEL); | |
677 | msg->free_buffer = 1; | |
678 | ||
679 | msg->buffer[0] = ((char) (data->uProxHiThresh >> 8) & 0xff); | |
680 | msg->buffer[1] = (char) data->uProxHiThresh; | |
681 | msg->buffer[2] = ((char) (data->uProxLoThresh >> 8) & 0xff); | |
682 | msg->buffer[3] = (char) data->uProxLoThresh; | |
683 | #endif | |
684 | ||
685 | iRet = ssp_spi_async(data, msg); | |
686 | ||
687 | if (iRet != SUCCESS) { | |
688 | pr_err("[SSP]: %s - SENSOR_PROXTHRESHOLD CMD fail %d\n", | |
689 | __func__, iRet); | |
690 | return; | |
691 | } | |
692 | ||
693 | #if defined(CONFIG_SENSORS_SSP_PROX_AUTOCAL_AMS) | |
694 | pr_info("[SSP]: Proximity Threshold - %u, %u, %u, %u\n", | |
695 | data->uProxHiThresh, data->uProxLoThresh, | |
696 | data->uProxHiThresh_detect, data->uProxLoThresh_detect); | |
697 | #else | |
698 | pr_info("[SSP]: Proximity Threshold - %u, %u\n", | |
699 | data->uProxHiThresh, data->uProxLoThresh); | |
700 | #endif | |
701 | } | |
702 | ||
703 | void set_proximity_alert_threshold(struct ssp_data *data) | |
704 | { | |
705 | int iRet = 0; | |
706 | ||
707 | struct ssp_msg *msg; | |
708 | ||
709 | if (!(data->uSensorState & (1 << PROXIMITY_ALERT_SENSOR))) { | |
710 | pr_info("[SSP]: %s - Skip this function!!!,proximity alert sensor is not connected(0x%llx)\n", | |
711 | __func__, data->uSensorState); | |
712 | return; | |
713 | } | |
714 | ||
715 | msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
716 | ||
717 | msg->cmd = MSG2SSP_AP_SENSOR_PROX_ALERT_THRESHOLD; | |
718 | msg->length = 2; | |
719 | msg->options = AP2HUB_WRITE; | |
720 | msg->buffer = (char *) kzalloc(2, GFP_KERNEL); | |
721 | msg->free_buffer = 1; | |
722 | ||
723 | msg->buffer[0] = ((char) (data->uProxAlertHiThresh >> 8) & 0xff); | |
724 | msg->buffer[1] = (char) data->uProxAlertHiThresh; | |
725 | ||
726 | iRet = ssp_spi_async(data, msg); | |
727 | ||
728 | if (iRet != SUCCESS) { | |
729 | pr_err("[SSP]: %s - SENSOR_PROX_ALERT_THRESHOLD CMD fail %d\n", | |
730 | __func__, iRet); | |
731 | return; | |
732 | } | |
733 | ||
734 | pr_info("[SSP]: %s Proximity alert Threshold - %u\n", | |
735 | __func__, data->uProxAlertHiThresh); | |
736 | } | |
737 | ||
738 | void set_light_coef(struct ssp_data *data) | |
739 | { | |
740 | int iRet = 0; | |
741 | struct ssp_msg *msg; | |
742 | ||
743 | if (!(data->uSensorState & (1 << LIGHT_SENSOR))) { | |
744 | pr_info("[SSP]: %s - Skip this function!!!,light sensor is not connected(0x%llx)\n", | |
745 | __func__, data->uSensorState); | |
746 | return; | |
747 | } | |
748 | ||
749 | msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
750 | ||
751 | msg->cmd = MSG2SSP_AP_SET_LIGHT_COEF; | |
752 | msg->length = sizeof(data->light_coef); | |
753 | msg->options = AP2HUB_WRITE; | |
754 | msg->buffer = (char *) kzalloc(sizeof(data->light_coef), GFP_KERNEL); | |
755 | msg->free_buffer = 1; | |
756 | ||
757 | memcpy(msg->buffer, data->light_coef, sizeof(data->light_coef)); | |
758 | ||
759 | iRet = ssp_spi_async(data, msg); | |
760 | ||
761 | if (iRet != SUCCESS) { | |
762 | pr_err("[SSP]: %s - MSG2SSP_AP_SET_LIGHT_COEF CMD fail %d\n", | |
763 | __func__, iRet); | |
764 | return; | |
765 | } | |
766 | ||
767 | pr_info("[SSP]: %s - %d %d %d %d %d %d %d\n", __func__, | |
768 | data->light_coef[0], data->light_coef[1], data->light_coef[2], | |
769 | data->light_coef[3], data->light_coef[4], data->light_coef[5], data->light_coef[6]); | |
770 | } | |
771 | ||
772 | void set_proximity_barcode_enable(struct ssp_data *data, bool bEnable) | |
773 | { | |
774 | int iRet = 0; | |
775 | struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
776 | ||
777 | msg->cmd = MSG2SSP_AP_SENSOR_BARCODE_EMUL; | |
778 | msg->length = 1; | |
779 | msg->options = AP2HUB_WRITE; | |
780 | msg->buffer = (char *) kzalloc(1, GFP_KERNEL); | |
781 | msg->free_buffer = 1; | |
782 | ||
783 | data->bBarcodeEnabled = bEnable; | |
784 | msg->buffer[0] = bEnable; | |
785 | ||
786 | iRet = ssp_spi_async(data, msg); | |
787 | if (iRet != SUCCESS) { | |
788 | pr_err("[SSP]: %s - SENSOR_BARCODE_EMUL CMD fail %d\n", | |
789 | __func__, iRet); | |
790 | return; | |
791 | } | |
792 | ||
793 | pr_info("[SSP] Proximity Barcode En : %u\n", bEnable); | |
794 | } | |
795 | ||
796 | void set_gesture_current(struct ssp_data *data, unsigned char uData1) | |
797 | { | |
798 | int iRet = 0; | |
799 | struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
800 | ||
801 | msg->cmd = MSG2SSP_AP_SENSOR_GESTURE_CURRENT; | |
802 | msg->length = 1; | |
803 | msg->options = AP2HUB_WRITE; | |
804 | msg->buffer = (char *) kzalloc(1, GFP_KERNEL); | |
805 | msg->free_buffer = 1; | |
806 | ||
807 | msg->buffer[0] = uData1; | |
808 | iRet = ssp_spi_async(data, msg); | |
809 | if (iRet != SUCCESS) { | |
810 | pr_err("[SSP]: %s - SENSOR_GESTURE_CURRENT CMD fail %d\n", | |
811 | __func__, iRet); | |
812 | return; | |
813 | } | |
814 | ||
815 | pr_info("[SSP]: Gesture Current Setting - %u\n", uData1); | |
816 | } | |
817 | ||
818 | int set_hall_threshold(struct ssp_data *data) | |
819 | { | |
820 | int iRet = 0; | |
821 | struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
822 | ||
823 | if (msg == NULL) { | |
824 | iRet = -ENOMEM; | |
825 | pr_err("[SSP]: %s - failed to alloc memory for ssp_msg\n", | |
826 | __func__); | |
827 | return iRet; | |
828 | } | |
829 | ||
830 | msg->cmd = MSG2SSP_AP_SET_HALL_THRESHOLD; | |
831 | msg->length = sizeof(data->hall_threshold); | |
832 | msg->options = AP2HUB_WRITE; | |
833 | msg->buffer = kzalloc(sizeof(data->hall_threshold), GFP_KERNEL); | |
834 | msg->free_buffer = 1; | |
835 | ||
836 | memcpy(msg->buffer, data->hall_threshold, | |
837 | sizeof(data->hall_threshold)); | |
838 | ||
839 | iRet = ssp_spi_async(data, msg); | |
840 | if (iRet != SUCCESS) { | |
841 | pr_err("[SSP]: %s - fail to %s %d\n", | |
842 | __func__, __func__, iRet); | |
843 | iRet = ERROR; | |
844 | } | |
845 | ||
846 | return iRet; | |
847 | } | |
848 | ||
849 | u64 get_sensor_scanning_info(struct ssp_data *data) | |
850 | { | |
851 | int iRet = 0, z = 0; | |
852 | u64 result = 0; | |
853 | struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
854 | ||
855 | if (msg == NULL) { | |
856 | iRet = -ENOMEM; | |
857 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
858 | __func__); | |
859 | return iRet; | |
860 | } | |
861 | msg->cmd = MSG2SSP_AP_SENSOR_SCANNING; | |
862 | msg->length = 8; | |
863 | msg->options = AP2HUB_READ; | |
864 | msg->buffer = (char *) &result; | |
865 | msg->free_buffer = 0; | |
866 | ||
867 | iRet = ssp_spi_sync(data, msg, 1000); | |
868 | ||
869 | if (iRet != SUCCESS) | |
870 | pr_err("[SSP]: %s - i2c fail %d\n", __func__, iRet); | |
871 | ||
872 | data->sensor_state[SENSOR_MAX] = '\0'; | |
873 | for (z = 0; z < SENSOR_MAX; z++) | |
874 | data->sensor_state[SENSOR_MAX - 1 - z] = (result & (1ULL << z)) ? '1' : '0'; | |
875 | pr_err("[SSP]: state: %s\n", data->sensor_state); | |
876 | ||
877 | return result; | |
878 | } | |
879 | ||
880 | unsigned int get_firmware_rev(struct ssp_data *data) | |
881 | { | |
882 | int iRet; | |
883 | u32 result = SSP_INVALID_REVISION; | |
884 | struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
885 | ||
886 | if (msg == NULL) { | |
887 | iRet = -ENOMEM; | |
888 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
889 | __func__); | |
890 | return iRet; | |
891 | } | |
892 | msg->cmd = MSG2SSP_AP_FIRMWARE_REV; | |
893 | msg->length = 4; | |
894 | msg->options = AP2HUB_READ; | |
895 | msg->buffer = (char *) &result; | |
896 | msg->free_buffer = 0; | |
897 | ||
898 | iRet = ssp_spi_sync(data, msg, 1000); | |
899 | if (iRet != SUCCESS) | |
900 | pr_err("[SSP]: %s - transfer fail %d\n", __func__, iRet); | |
901 | ||
902 | return result; | |
903 | } | |
904 | ||
905 | int set_big_data_start(struct ssp_data *data, u8 type, u32 length) | |
906 | { | |
907 | int iRet = 0; | |
908 | struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
909 | ||
910 | if (msg == NULL) { | |
911 | iRet = -ENOMEM; | |
912 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
913 | __func__); | |
914 | return iRet; | |
915 | } | |
916 | msg->cmd = MSG2SSP_AP_START_BIG_DATA; | |
917 | msg->length = 5; | |
918 | msg->options = AP2HUB_WRITE; | |
919 | msg->buffer = (char *) kzalloc(5, GFP_KERNEL); | |
920 | msg->free_buffer = 1; | |
921 | ||
922 | msg->buffer[0] = type; | |
923 | memcpy(&msg->buffer[1], &length, 4); | |
924 | ||
925 | iRet = ssp_spi_async(data, msg); | |
926 | ||
927 | if (iRet != SUCCESS) { | |
928 | pr_err("[SSP]: %s - i2c fail %d\n", __func__, iRet); | |
929 | iRet = ERROR; | |
930 | } | |
931 | ||
932 | return iRet; | |
933 | } | |
934 | ||
935 | int set_time(struct ssp_data *data) | |
936 | { | |
937 | int iRet; | |
938 | struct ssp_msg *msg; | |
939 | struct timespec ts; | |
940 | struct rtc_time tm; | |
941 | ||
942 | getnstimeofday(&ts); | |
943 | rtc_time_to_tm(ts.tv_sec, &tm); | |
944 | pr_info("[SSP]: %s %d-%02d-%02d %02d:%02d:%02d.%09lu UTC\n", | |
945 | __func__, | |
946 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | |
947 | tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); | |
948 | ||
949 | msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
950 | if (msg == NULL) { | |
951 | iRet = -ENOMEM; | |
952 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
953 | __func__); | |
954 | return iRet; | |
955 | } | |
956 | msg->cmd = MSG2SSP_AP_MCU_SET_TIME; | |
957 | msg->length = 12; | |
958 | msg->options = AP2HUB_WRITE; | |
959 | msg->buffer = (char *) kzalloc(12, GFP_KERNEL); | |
960 | msg->free_buffer = 1; | |
961 | ||
962 | msg->buffer[0] = tm.tm_hour; | |
963 | msg->buffer[1] = tm.tm_min; | |
964 | msg->buffer[2] = tm.tm_sec; | |
965 | msg->buffer[3] = tm.tm_hour > 11 ? 64 : 0; | |
966 | msg->buffer[4] = tm.tm_wday; | |
967 | msg->buffer[5] = tm.tm_mon + 1; | |
968 | msg->buffer[6] = tm.tm_mday; | |
969 | msg->buffer[7] = tm.tm_year % 100; | |
970 | memcpy(&msg->buffer[8], &ts.tv_nsec, 4); | |
971 | ||
972 | iRet = ssp_spi_async(data, msg); | |
973 | ||
974 | if (iRet != SUCCESS) { | |
975 | pr_err("[SSP]: %s - i2c fail %d\n", __func__, iRet); | |
976 | iRet = ERROR; | |
977 | } | |
978 | ||
979 | return iRet; | |
980 | } | |
981 | ||
982 | int get_time(struct ssp_data *data) | |
983 | { | |
984 | int iRet; | |
985 | char buffer[12] = { 0, }; | |
986 | struct ssp_msg *msg; | |
987 | struct timespec ts; | |
988 | struct rtc_time tm; | |
989 | ||
990 | getnstimeofday(&ts); | |
991 | rtc_time_to_tm(ts.tv_sec, &tm); | |
992 | pr_info("[SSP]: %s ap %d-%02d-%02d %02d:%02d:%02d.%09lu UTC\n", | |
993 | __func__, | |
994 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | |
995 | tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); | |
996 | ||
997 | msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
998 | if (msg == NULL) { | |
999 | iRet = -ENOMEM; | |
1000 | pr_err("[SSP] %s, failed to alloc memory for ssp_msg\n", | |
1001 | __func__); | |
1002 | return iRet; | |
1003 | } | |
1004 | msg->cmd = MSG2SSP_AP_MCU_GET_TIME; | |
1005 | msg->length = 12; | |
1006 | msg->options = AP2HUB_READ; | |
1007 | msg->buffer = buffer; | |
1008 | msg->free_buffer = 0; | |
1009 | ||
1010 | iRet = ssp_spi_sync(data, msg, 1000); | |
1011 | ||
1012 | if (iRet != SUCCESS) { | |
1013 | pr_err("[SSP]: %s - i2c failed %d\n", __func__, iRet); | |
1014 | return 0; | |
1015 | } | |
1016 | ||
1017 | tm.tm_hour = buffer[0]; | |
1018 | tm.tm_min = buffer[1]; | |
1019 | tm.tm_sec = buffer[2]; | |
1020 | tm.tm_mon = msg->buffer[5] - 1; | |
1021 | tm.tm_mday = buffer[6]; | |
1022 | tm.tm_year = buffer[7] + 100; | |
1023 | rtc_tm_to_time(&tm, &ts.tv_sec); | |
1024 | memcpy(&ts.tv_nsec, &msg->buffer[8], 4); | |
1025 | ||
1026 | rtc_time_to_tm(ts.tv_sec, &tm); | |
1027 | pr_info("[SSP]: %s mcu %d-%02d-%02d %02d:%02d:%02d.%09lu UTC\n", | |
1028 | __func__, | |
1029 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | |
1030 | tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); | |
1031 | ||
1032 | return iRet; | |
1033 | } | |
1034 | ||
1035 | void set_gyro_cal_lib_enable(struct ssp_data *data, bool bEnable) | |
1036 | { | |
1037 | int iRet = 0; | |
1038 | u8 cmd; | |
1039 | struct ssp_msg *msg; | |
1040 | ||
1041 | pr_info("[SSP] %s - enable %d(cur %d)\n", __func__, bEnable, data->gyro_lib_state); | |
1042 | ||
1043 | if (bEnable) | |
1044 | cmd = SH_MSG2AP_GYRO_CALIBRATION_START; | |
1045 | else | |
1046 | cmd = SH_MSG2AP_GYRO_CALIBRATION_STOP; | |
1047 | ||
1048 | msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
1049 | ||
1050 | msg->cmd = cmd; | |
1051 | msg->length = 1; | |
1052 | msg->options = AP2HUB_WRITE; | |
1053 | msg->buffer = (char *) kzalloc(1, GFP_KERNEL); | |
1054 | msg->free_buffer = 1; | |
1055 | ||
1056 | msg->buffer[0] = bEnable; | |
1057 | ||
1058 | iRet = ssp_spi_async(data, msg); | |
1059 | ||
1060 | if (iRet == SUCCESS) { | |
1061 | if (bEnable) | |
1062 | data->gyro_lib_state = GYRO_CALIBRATION_STATE_REGISTERED; | |
1063 | else | |
1064 | data->gyro_lib_state = GYRO_CALIBRATION_STATE_DONE; | |
1065 | } else | |
1066 | pr_err("[SSP] %s - gyro lib enable cmd fail\n", __func__); | |
1067 | ||
1068 | } | |
1069 | ||
1070 | #if defined(CONFIG_SSP_MOTOR_CALLBACK) | |
1071 | int send_motor_state(struct ssp_data *data) | |
1072 | { | |
1073 | int iRet = 0; | |
1074 | struct ssp_msg *msg; | |
1075 | ||
1076 | msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
1077 | ||
1078 | msg->cmd = MSG2SSP_AP_MCU_SET_MOTOR_STATUS; | |
1079 | msg->length = 1; | |
1080 | msg->options = AP2HUB_WRITE; | |
1081 | msg->buffer = (char *) kzalloc(1, GFP_KERNEL); | |
1082 | msg->free_buffer = 1; | |
1083 | ||
1084 | /*if 1: start, 0: stop*/ | |
1085 | msg->buffer[0] = data->motor_state; | |
1086 | ||
1087 | iRet = ssp_spi_async(data, msg); | |
1088 | if (iRet != SUCCESS) { | |
1089 | pr_err("[SSP]: %s - fail %d\n", | |
1090 | __func__, iRet); | |
1091 | return iRet; | |
1092 | } | |
1093 | pr_info("[SSP] %s - En : %u\n", __func__, data->motor_state); | |
1094 | return data->motor_state; | |
1095 | } | |
1096 | #endif | |
1097 | u8 get_accel_range(struct ssp_data *data) | |
1098 | { | |
1099 | int iRet = 0; | |
1100 | struct ssp_msg *msg; | |
1101 | u8 rxbuffer[1] = {0x00}; | |
1102 | ||
1103 | msg = kzalloc(sizeof(*msg), GFP_KERNEL); | |
1104 | ||
1105 | msg->cmd = MSG2SSP_AP_MCU_GET_ACCEL_RANGE; | |
1106 | msg->length = 1; | |
1107 | msg->options = AP2HUB_READ; | |
1108 | msg->buffer = rxbuffer; | |
1109 | msg->free_buffer = 0; | |
1110 | ||
1111 | iRet = ssp_spi_sync(data, msg, 1000); | |
1112 | if (iRet != SUCCESS) { | |
1113 | pr_err("[SSP]: %s - fail %d\n", | |
1114 | __func__, iRet); | |
1115 | return iRet; | |
1116 | } | |
1117 | ||
1118 | pr_info("[SSP] %s - Range : %u\n", __func__, rxbuffer[0]); | |
1119 | return rxbuffer[0]; | |
1120 | } | |
1121 | ||
1122 |