1 // SPDX-License-Identifier: GPL-2.0
2 /**
3 * Rockchip rk1608 device driver
4 *
5 * Copyright (C) Rockchip Electronics Co., Ltd.
6 *
7 */
8 #include <linux/of_platform.h>
9 #include <linux/ctype.h>
10 #include <media/v4l2-ctrls.h>
11 #include <media/v4l2-fwnode.h>
12 #include <media/v4l2-subdev.h>
13 #include <linux/compat.h>
14 #include <linux/rk-preisp.h>
15 #include "rk1608_dev.h"
16
17 #define DEBUG_DUMP_ALL_SEND_RECV_MSG 0
18
19 #define MSG_QUEUE_DEFAULT_SIZE (8 * 1024)
20
21 struct msg_queue {
22 u32 *buf_head; /* msg buffer head */
23 u32 *buf_tail; /* msg buffer tail */
24 u32 *cur_send; /* current msg send position */
25 u32 *cur_recv; /* current msg receive position */
26 };
27
28 struct rk1608_client {
29 s8 id;
30 struct msg_queue q;
31 struct list_head list;
32 wait_queue_head_t wait;
33 void *private_data;
34 };
35
36 enum {
37 AUTO_ARG_TYPE_STR,
38 AUTO_ARG_TYPE_INT32,
39 };
40
41 struct auto_arg {
42 int type;
43 union {
44 s32 m_int32;
45 const char *m_str;
46 };
47 };
48
49 struct auto_args {
50 int argc;
51 struct auto_arg *argv;
52 };
53
54 /**
55 * msq_init - Initialize msg queue
56 *
57 * @q: the msg queue to initialize
58 * @size: size of msg queue buf
59 *
60 * It returns zero on success, else a negative error code.
61 */
msq_init(struct msg_queue * q,int size)62 static int msq_init(struct msg_queue *q, int size)
63 {
64 u32 *buf = kmalloc(size, GFP_KERNEL);
65
66 q->buf_head = buf;
67 q->buf_tail = buf + size / sizeof(u32);
68 q->cur_send = buf;
69 q->cur_recv = buf;
70
71 return 0;
72 }
73
74 /**
75 * msq_release - release msg queue buf
76 *
77 * @q: the msg queue to release
78 */
msq_release(struct msg_queue * q)79 static void msq_release(struct msg_queue *q)
80 {
81 kfree(q->buf_head);
82 q->buf_head = NULL;
83 q->buf_tail = NULL;
84 q->cur_send = NULL;
85 q->cur_recv = NULL;
86 }
87
88 /**
89 * msq_is_empty - tests whether a msg queue is empty
90 *
91 * @q: the msg queue to test
92 *
93 * It returns true on msg queue is empty, else false.
94 */
msq_is_empty(const struct msg_queue * q)95 static int msq_is_empty(const struct msg_queue *q)
96 {
97 return q->cur_send == q->cur_recv;
98 }
99
100 /**
101 * msq_tail_free_size - get msg queue tail unused buf size
102 *
103 * @q: msg queue
104 *
105 * It returns size of msg queue tail unused buf size, unit 4 bytes
106 */
msq_tail_free_size(const struct msg_queue * q)107 static u32 msq_tail_free_size(const struct msg_queue *q)
108 {
109 if (q->cur_send >= q->cur_recv)
110 return (q->buf_tail - q->cur_send);
111
112 return q->cur_recv - q->cur_send;
113 }
114
115 /**
116 * msq_head_free_size - get msg queue head unused buf size
117 *
118 * @q: msg queue
119 *
120 * It returns size of msg queue head unused buf size, unit 4 bytes
121 */
msq_head_free_size(const struct msg_queue * q)122 static u32 msq_head_free_size(const struct msg_queue *q)
123 {
124 if (q->cur_send >= q->cur_recv)
125 return (q->cur_recv - q->buf_head);
126
127 return 0;
128 }
129
130 /**
131 * msq_send_msg - send a msg to msg queue
132 *
133 * @q: msg queue
134 * @m: a msg to queue
135 *
136 * It returns zero on success, else a negative error code.
137 */
msq_send_msg(struct msg_queue * q,const struct msg * m)138 static int msq_send_msg(struct msg_queue *q, const struct msg *m)
139 {
140 int ret = 0;
141
142 if (msq_tail_free_size(q) > m->size) {
143 u32 *next_send;
144
145 memcpy(q->cur_send, m, m->size * sizeof(u32));
146 next_send = q->cur_send + m->size;
147 if (next_send == q->buf_tail)
148 next_send = q->buf_head;
149
150 q->cur_send = next_send;
151 } else if (msq_head_free_size(q) > m->size) {
152 *q->cur_send = 0; /* set size to 0 for skip to head mark */
153 memcpy(q->buf_head, m, m->size * sizeof(u32));
154 q->cur_send = q->buf_head + m->size;
155 } else {
156 ret = -1;
157 }
158
159 return ret;
160 }
161
162 /**
163 * msq_recv_msg - receive a msg from msg queue
164 *
165 * @q: msg queue
166 * @m: a msg pointer buf [out]
167 *
168 * need call msq_recv_msg_free to free msg after msg use done
169 *
170 * It returns zero on success, else a negative error code.
171 */
msq_recv_msg(struct msg_queue * q,struct msg ** m)172 static int msq_recv_msg(struct msg_queue *q, struct msg **m)
173 {
174 *m = NULL;
175 if (msq_is_empty(q))
176 return -1;
177
178 /* skip to head when size is 0 */
179 if (*q->cur_recv == 0)
180 *m = (struct msg *)q->buf_head;
181 else
182 *m = (struct msg *)q->cur_recv;
183
184 return 0;
185 }
186
187 /**
188 * msq_free_received_msg - free a received msg to msg queue
189 *
190 * @q: msg queue
191 * @m: a msg
192 *
193 * It returns zero on success, else a negative error code.
194 */
msq_free_received_msg(struct msg_queue * q,const struct msg * m)195 static int msq_free_received_msg(struct msg_queue *q, const struct msg *m)
196 {
197 /* skip to head when size is 0 */
198 if (*q->cur_recv == 0) {
199 q->cur_recv = q->buf_head + m->size;
200 } else {
201 u32 *next_recv;
202
203 next_recv = q->cur_recv + m->size;
204 if (next_recv == q->buf_tail)
205 next_recv = q->buf_head;
206
207 q->cur_recv = next_recv;
208 }
209
210 return 0;
211 }
212
rk1608_client_list_init(struct rk1608_client_list * s)213 static void rk1608_client_list_init(struct rk1608_client_list *s)
214 {
215 mutex_init(&s->mutex);
216 INIT_LIST_HEAD(&s->list);
217 }
218
rk1608_client_new(void)219 static struct rk1608_client *rk1608_client_new(void)
220 {
221 struct rk1608_client *c = kzalloc(sizeof(*c), GFP_KERNEL);
222
223 if (!c)
224 return NULL;
225
226 c->id = INVALID_ID;
227 INIT_LIST_HEAD(&c->list);
228 msq_init(&c->q, MSG_QUEUE_DEFAULT_SIZE);
229 init_waitqueue_head(&c->wait);
230
231 return c;
232 }
233
rk1608_client_release(struct rk1608_client * c)234 static void rk1608_client_release(struct rk1608_client *c)
235 {
236 msq_release(&c->q);
237 kfree(c);
238 }
239
240 static struct rk1608_client *
rk1608_client_find(struct rk1608_client_list * s,struct rk1608_client * c)241 rk1608_client_find(struct rk1608_client_list *s,
242 struct rk1608_client *c)
243 {
244 struct rk1608_client *client = NULL;
245
246 list_for_each_entry(client, &s->list, list) {
247 if (c == client)
248 return c;
249 }
250
251 return NULL;
252 }
253
rk1608_client_connect(struct rk1608_state * pdata,struct rk1608_client * c)254 static int rk1608_client_connect(struct rk1608_state *pdata,
255 struct rk1608_client *c)
256 {
257 struct rk1608_client_list *s = &pdata->clients;
258
259 mutex_lock(&s->mutex);
260 if (rk1608_client_find(s, c)) {
261 mutex_unlock(&s->mutex);
262 return -1;
263 }
264
265 list_add_tail(&c->list, &s->list);
266 mutex_unlock(&s->mutex);
267
268 return 0;
269 }
270
rk1608_client_disconnect(struct rk1608_state * pdata,struct rk1608_client * c)271 static void rk1608_client_disconnect(struct rk1608_state *pdata,
272 struct rk1608_client *c)
273 {
274 struct rk1608_client_list *s = &pdata->clients;
275
276 mutex_lock(&s->mutex);
277 if (rk1608_client_find(s, c))
278 list_del_init(&c->list);
279 mutex_unlock(&s->mutex);
280 }
281
parse_arg(const char * s,struct auto_arg * arg)282 static int parse_arg(const char *s, struct auto_arg *arg)
283 {
284 if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
285 long v;
286
287 v = simple_strtol(s, NULL, 16);
288 arg->type = AUTO_ARG_TYPE_INT32;
289 arg->m_int32 = v;
290 } else if (isdigit(s[0])) {
291 long v;
292
293 v = simple_strtol(s, NULL, 10);
294 arg->type = AUTO_ARG_TYPE_INT32;
295 arg->m_int32 = v;
296 } else {
297 arg->type = AUTO_ARG_TYPE_STR;
298 arg->m_str = s;
299 }
300
301 return 0;
302 }
303
parse_auto_args(char * s,struct auto_args * args)304 static int parse_auto_args(char *s, struct auto_args *args)
305 {
306 int i = 0;
307 char c = 0;
308 int last_is_arg_flag = 0;
309 const char *last_arg;
310
311 args->argc = 0;
312
313 i = -1;
314 do {
315 c = s[++i];
316 if (c == ' ' || c == ',' || c == '\n' || c == '\r' || c == 0) {
317 if (last_is_arg_flag)
318 args->argc++;
319
320 last_is_arg_flag = 0;
321 } else {
322 last_is_arg_flag = 1;
323 }
324 } while (c != 0 && c != '\n' && c != '\r');
325
326 args->argv =
327 kmalloc_array(args->argc, sizeof(struct auto_arg), GFP_KERNEL);
328 if (!args->argv)
329 return -ENOMEM;
330
331 i = -1;
332 last_is_arg_flag = 0;
333 last_arg = s;
334 args->argc = 0;
335 do {
336 c = s[++i];
337 if (c == ' ' || c == ',' || c == '\n' || c == '\r' || c == 0) {
338 if (last_is_arg_flag) {
339 parse_arg(last_arg, args->argv + args->argc++);
340 s[i] = 0;
341 }
342 last_is_arg_flag = 0;
343 } else {
344 if (last_is_arg_flag == 0)
345 last_arg = s + i;
346
347 last_is_arg_flag = 1;
348 }
349 } while (c != 0 && c != '\n' && c != '\r');
350
351 return c == 0 ? i : i + 1;
352 }
353
free_auto_args(struct auto_args * args)354 static void free_auto_args(struct auto_args *args)
355 {
356 kfree(args->argv);
357 args->argv = NULL;
358 args->argc = 0;
359 }
360
int32_hexdump(const char * prefix,s32 * data,int len)361 static void int32_hexdump(const char *prefix, s32 *data, int len)
362 {
363 pr_err("%s\n", prefix);
364 print_hex_dump(KERN_ERR, "offset ", DUMP_PREFIX_OFFSET,
365 16, 4, data, len, false);
366 pr_err("\n");
367 }
368
do_cmd_write(struct rk1608_state * pdata,const struct auto_args * args)369 static int do_cmd_write(struct rk1608_state *pdata,
370 const struct auto_args *args)
371 {
372 s32 addr;
373 s32 len = (args->argc - 2) * sizeof(s32);
374 s32 *data;
375 int i;
376
377 if (args->argc < 3 || args->argv[1].type != AUTO_ARG_TYPE_INT32) {
378 dev_err(pdata->dev, "Mis or unknown args!\n");
379 return -1;
380 }
381
382 len = MIN(len, RK1608_MAX_OP_BYTES);
383
384 addr = args->argv[1].m_int32;
385 data = kmalloc(len, GFP_KERNEL);
386 if (!data)
387 return -ENOMEM;
388
389 for (i = 0; i < len / 4; i++) {
390 if (args->argv[i + 2].type != AUTO_ARG_TYPE_INT32) {
391 dev_err(pdata->dev, "Unknown args!\n");
392 kfree(data);
393 return -1;
394 }
395
396 data[i] = args->argv[i + 2].m_int32;
397 }
398
399 rk1608_write(pdata->spi, addr, data, len);
400
401 kfree(data);
402
403 dev_info(pdata->dev, "write addr: 0x%x, len: %d bytes\n", addr, len);
404 return 0;
405 }
406
do_cmd_read(struct rk1608_state * pdata,const struct auto_args * args)407 static int do_cmd_read(struct rk1608_state *pdata,
408 const struct auto_args *args)
409 {
410 s32 addr;
411 s32 len;
412 s32 *data;
413
414 if (args->argc < 3 || args->argv[1].type != AUTO_ARG_TYPE_INT32) {
415 dev_err(pdata->dev, "Mis or unknown args!\n");
416 return -1;
417 }
418
419 addr = args->argv[1].m_int32;
420 if (args->argc == 2) {
421 len = 32;
422 } else {
423 if (args->argv[2].type != AUTO_ARG_TYPE_INT32) {
424 dev_err(pdata->dev, "Unknown args!\n");
425 return -1;
426 }
427 len = args->argv[2].m_int32 * sizeof(s32);
428 len = MIN(len, RK1608_MAX_OP_BYTES);
429 }
430
431 data = kmalloc(len, GFP_KERNEL);
432 if (!data)
433 return -ENOMEM;
434
435 dev_info(pdata->dev, "\nread addr: %x, len: %d bytes\n", addr, len);
436 rk1608_read(pdata->spi, addr, data, len);
437 int32_hexdump("read data:", data, len);
438 kfree(data);
439
440 return 0;
441 }
442
do_cmd_set_spi_rate(struct rk1608_state * pdata,const struct auto_args * args)443 static int do_cmd_set_spi_rate(struct rk1608_state *pdata,
444 const struct auto_args *args)
445 {
446 if (args->argc < 2 || args->argv[1].type != AUTO_ARG_TYPE_INT32) {
447 dev_err(pdata->dev, "Mis or unknown args!\n");
448 return -1;
449 }
450
451 pdata->max_speed_hz = args->argv[1].m_int32;
452 dev_info(pdata->dev, "set spi max speed to %d!\n", pdata->max_speed_hz);
453
454 if (args->argc == 3 && args->argv[2].type == AUTO_ARG_TYPE_INT32) {
455 pdata->min_speed_hz = args->argv[2].m_int32;
456 dev_info(pdata->dev, "set spi min speed to %d!\n",
457 pdata->min_speed_hz);
458 }
459
460 return 0;
461 }
462
do_cmd_query(struct rk1608_state * pdata,const struct auto_args * args)463 static int do_cmd_query(struct rk1608_state *pdata,
464 const struct auto_args *args)
465 {
466 s32 state;
467
468 rk1608_operation_query(pdata->spi, &state);
469 dev_info(pdata->dev, "state %x\n", state);
470 return 0;
471 }
472
do_cmd_download_fw(struct rk1608_state * pdata,const struct auto_args * args)473 static int do_cmd_download_fw(struct rk1608_state *pdata,
474 const struct auto_args *args)
475 {
476 int ret = 0;
477 const char *fw_name = NULL;
478
479 if (args->argc == 2 && args->argv[1].type == AUTO_ARG_TYPE_STR)
480 fw_name = args->argv[1].m_str;
481
482 ret = rk1608_download_fw(pdata, pdata->spi, fw_name);
483 if (ret)
484 dev_err(pdata->dev, "download firmware failed!\n");
485 else
486 dev_info(pdata->dev, "download firmware success!\n");
487
488 return 0;
489 }
490
do_cmd_fast_write(struct rk1608_state * pdata,const struct auto_args * args)491 static int do_cmd_fast_write(struct rk1608_state *pdata,
492 const struct auto_args *args)
493 {
494 int ret = 0;
495 s32 reg;
496
497 if (args->argc != 2 || args->argv[1].type != AUTO_ARG_TYPE_INT32) {
498 dev_err(pdata->dev, "Mis or unknown args!\n");
499 return -1;
500 }
501
502 reg = args->argv[1].m_int32;
503
504 ret = rk1608_interrupt_request(pdata->spi, reg);
505 dev_info(pdata->dev, "interrupt request reg1:%x ret:%x\n", reg, ret);
506
507 return 0;
508 }
509
do_cmd_fast_read(struct rk1608_state * pdata,const struct auto_args * args)510 static int do_cmd_fast_read(struct rk1608_state *pdata,
511 const struct auto_args *args)
512 {
513 s32 state;
514
515 rk1608_state_query(pdata->spi, &state);
516 dev_info(pdata->dev, "dsp state %x\n", state);
517
518 return 0;
519 }
520
do_cmd_send_msg(struct rk1608_state * pdata,const struct auto_args * args)521 static int do_cmd_send_msg(struct rk1608_state *pdata,
522 const struct auto_args *args)
523 {
524 struct msg *m;
525 int ret = 0;
526 int msg_len;
527 u32 i = 0;
528
529 if (args->argc < 2) {
530 dev_err(pdata->dev, "need more args\n");
531 return -1;
532 }
533
534 msg_len = args->argc * sizeof(u32);
535
536 m = kmalloc(msg_len, GFP_KERNEL);
537 if (!m)
538 return -ENOMEM;
539
540 m->size = msg_len / 4;
541 for (i = 1; i < m->size; i++) {
542 if (args->argv[i].type != AUTO_ARG_TYPE_INT32) {
543 dev_err(pdata->dev, "Unknown args!\n");
544 kfree(m);
545 return -1;
546 }
547
548 *((s32 *)m + i) = args->argv[i].m_int32;
549 }
550
551 ret = rk1608_send_msg_to_dsp(pdata, m);
552
553 dev_info(pdata->dev, "send msg len: %d, ret: %x\n", m->size, ret);
554
555 kfree(m);
556
557 return 0;
558 }
559
do_cmd_recv_msg(struct rk1608_state * pdata,const struct auto_args * args)560 static int do_cmd_recv_msg(struct rk1608_state *pdata,
561 const struct auto_args *args)
562 {
563 struct msg *m;
564 char buf[256] = "";
565 int ret = 0;
566
567 ret = rk1608_msq_recv_msg(pdata, pdata->spi, &m);
568 if (ret || !m)
569 return 0;
570
571 dev_info(pdata->dev, "\nrecv msg len: %d, ret: %x\n", m->size, ret);
572 int32_hexdump("recv msg:", (s32 *)m, m->size * 4);
573
574 dev_info(pdata->dev, buf);
575
576 kfree(m);
577
578 return 0;
579 }
580
do_cmd_power_on(struct rk1608_state * pdata,const struct auto_args * args)581 static int do_cmd_power_on(struct rk1608_state *pdata,
582 const struct auto_args *args)
583 {
584 int ret;
585
586 ret = rk1608_set_power(pdata, 1);
587 dev_info(pdata->dev, "do cmd power on, count++\n");
588
589 return ret;
590 }
591
do_cmd_power_off(struct rk1608_state * pdata,const struct auto_args * args)592 static int do_cmd_power_off(struct rk1608_state *pdata,
593 const struct auto_args *args)
594 {
595 int ret;
596
597 ret = rk1608_set_power(pdata, 0);
598 dev_info(pdata->dev, "do cmd power off, count--\n");
599
600 return ret;
601 }
602
do_cmd_set_dsp_log_level(struct rk1608_state * pdata,const struct auto_args * args)603 static int do_cmd_set_dsp_log_level(struct rk1608_state *pdata,
604 const struct auto_args *args)
605 {
606 int ret;
607
608 if (args->argc != 2 || args->argv[1].type != AUTO_ARG_TYPE_INT32) {
609 dev_err(pdata->dev, "Mis or unknown args!\n");
610 return -1;
611 }
612
613 pdata->log_level = args->argv[1].m_int32;
614 ret = rk1608_set_log_level(pdata, pdata->log_level);
615
616 dev_info(pdata->dev, "set dsp log level %d, ret: %d\n",
617 pdata->log_level, ret);
618
619 return ret;
620 }
621
do_cmd_version(struct rk1608_state * pdata,const struct auto_args * args)622 static int do_cmd_version(struct rk1608_state *pdata,
623 const struct auto_args *args)
624 {
625 dev_info(pdata->dev, "driver version: v%02x.%02x.%02x\n",
626 RK1608_VERSION >> 16,
627 (RK1608_VERSION & 0xff00) >> 8,
628 RK1608_VERSION & 0x00ff);
629 return 0;
630 }
631
do_cmd_help(struct rk1608_state * pdata)632 static int do_cmd_help(struct rk1608_state *pdata)
633 {
634 dev_info(pdata->dev, "\n"
635 "support debug commands:\n"
636 "v -- rk1608 driver version.\n"
637 "log level -- set rk1608 log level.\n"
638 "on -- power count + 1.\n"
639 "off -- power count - 1.\n"
640 "f [fw_name] -- download fw.\n"
641 "q -- query operation status.\n"
642 "r addr [length=32] -- read addr.\n"
643 "w addr value,... -- write addr.\n"
644 "s type,... -- send msg.\n"
645 "rate max [min] -- set spi speed.\n\n");
646 return 0;
647 }
648
do_cmd(struct rk1608_state * pdata,const struct auto_args * args)649 static int do_cmd(struct rk1608_state *pdata, const struct auto_args *args)
650 {
651 const char *s;
652
653 if (args->argv->type != AUTO_ARG_TYPE_STR)
654 return 0;
655
656 s = args->argv->m_str;
657 /* echo c > /dev/rk_preisp */
658 if (!strcmp(s, "c"))
659 return do_cmd_recv_msg(pdata, args);
660 /* echo f [fw_name] > /dev/rk_preisp */
661 if (!strcmp(s, "f"))
662 return do_cmd_download_fw(pdata, args);
663 /* echo fw reg1 > /dev/rk_preisp */
664 if (!strcmp(s, "fw"))
665 return do_cmd_fast_write(pdata, args);
666 /* echo fr > /dev/rk_preisp */
667 if (!strcmp(s, "fr"))
668 return do_cmd_fast_read(pdata, args);
669 /* echo log level > /dev/rk_preisp */
670 if (!strcmp(s, "log"))
671 return do_cmd_set_dsp_log_level(pdata, args);
672 /* echo on > /dev/rk_preisp */
673 if (!strcmp(s, "on"))
674 return do_cmd_power_on(pdata, args);
675 /* echo off > /dev/rk_preisp */
676 if (!strcmp(s, "off"))
677 return do_cmd_power_off(pdata, args);
678 /* echo q > /dev/rk_preisp */
679 if (!strcmp(s, "q"))
680 return do_cmd_query(pdata, args);
681 /* echo r addr [length] > /dev/rk_preisp */
682 if (!strcmp(s, "r"))
683 return do_cmd_read(pdata, args);
684 /* echo rate > /dev/rk_preisp */
685 if (!strcmp(s, "rate"))
686 return do_cmd_set_spi_rate(pdata, args);
687 /* echo s type,... > /dev/rk_preisp */
688 if (!strcmp(s, "s"))
689 return do_cmd_send_msg(pdata, args);
690 /* echo v > /dev/rk_preisp */
691 if (!strcmp(s, "v"))
692 return do_cmd_version(pdata, args);
693 /* echo w addr value,... > /dev/rk_preisp */
694 if (!strcmp(s, "w"))
695 return do_cmd_write(pdata, args);
696
697 dev_err(pdata->dev, "unknown commands:%s\n", s);
698 do_cmd_help(pdata);
699
700 return 0;
701 }
702
rk1608_dev_open(struct inode * inode,struct file * file)703 static int rk1608_dev_open(struct inode *inode, struct file *file)
704 {
705 struct rk1608_state *pdata =
706 container_of(file->private_data, struct rk1608_state, misc);
707 struct rk1608_client *client = rk1608_client_new();
708
709 client->private_data = pdata;
710 file->private_data = client;
711
712 rk1608_set_power(pdata, 1);
713
714 return 0;
715 }
716
rk1608_dev_release(struct inode * inode,struct file * file)717 static int rk1608_dev_release(struct inode *inode, struct file *file)
718 {
719 struct rk1608_client *client = file->private_data;
720 struct rk1608_state *pdata = client->private_data;
721
722 rk1608_client_disconnect(pdata, client);
723 rk1608_client_release(client);
724 rk1608_set_power(pdata, 0);
725
726 return 0;
727 }
728
rk1608_dev_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)729 static ssize_t rk1608_dev_write(struct file *file, const char __user *user_buf,
730 size_t count, loff_t *ppos)
731 {
732 char *buf;
733 struct auto_args args;
734 int i;
735 struct rk1608_client *client = file->private_data;
736 struct rk1608_state *pdata = client->private_data;
737
738 buf = kmalloc(count + 1, GFP_KERNEL);
739 if (!buf)
740 return -ENOMEM;
741
742 if (copy_from_user(buf, user_buf, count))
743 return -EFAULT;
744
745 buf[count] = 0;
746
747 i = 0;
748 while (buf[i] != 0) {
749 int ret = parse_auto_args(buf + i, &args);
750
751 if (ret < 0)
752 break;
753
754 i += ret;
755 if (args.argc == 0)
756 continue;
757
758 do_cmd(pdata, &args);
759 free_auto_args(&args);
760 }
761
762 kfree(buf);
763
764 return count;
765 }
766
rk1608_dev_ioctl(struct file * file,unsigned int cmd,unsigned long arg)767 static long rk1608_dev_ioctl(struct file *file, unsigned int cmd,
768 unsigned long arg)
769 {
770 int ret = 0;
771 void __user *ubuf = (void __user *)arg;
772 struct rk1608_client *client = file->private_data;
773 struct rk1608_state *pdata = client->private_data;
774
775 switch (cmd) {
776 case PREISP_POWER_ON:
777 ret = rk1608_set_power(pdata, 1);
778 break;
779 case PREISP_POWER_OFF:
780 ret = rk1608_set_power(pdata, 0);
781 break;
782 case PREISP_DOWNLOAD_FW: {
783 char fw_name[PREISP_FW_NAME_LEN];
784
785 if (strncpy_from_user(fw_name, ubuf, PREISP_FW_NAME_LEN) <= 0) {
786 ret = -EFAULT;
787 break;
788 }
789 dev_info(pdata->dev, "download fw:%s\n", fw_name);
790 ret = rk1608_download_fw(pdata, pdata->spi, fw_name);
791 break;
792 }
793 case PREISP_WRITE: {
794 struct preisp_apb_pkt pkt;
795 s32 *data;
796
797 if (copy_from_user(&pkt, ubuf, sizeof(pkt))) {
798 ret = -EFAULT;
799 break;
800 }
801 pkt.data_len = MIN(pkt.data_len, RK1608_MAX_OP_BYTES);
802 data = memdup_user((void __user *)pkt.data, pkt.data_len);
803 if (IS_ERR(data)) {
804 ret = (long)ERR_PTR((long)data);
805 break;
806 }
807
808 ret = rk1608_safe_write(pdata, pdata->spi, pkt.addr, data, pkt.data_len);
809 kfree(data);
810 break;
811 }
812 case PREISP_READ: {
813 struct preisp_apb_pkt pkt;
814 s32 *data;
815
816 if (copy_from_user(&pkt, ubuf, sizeof(pkt))) {
817 ret = -EFAULT;
818 break;
819 }
820 pkt.data_len = MIN(pkt.data_len, RK1608_MAX_OP_BYTES);
821 data = kmalloc(pkt.data_len, GFP_KERNEL);
822 if (!data) {
823 ret = -ENOMEM;
824 break;
825 }
826
827 ret = rk1608_safe_read(pdata, pdata->spi, pkt.addr, data, pkt.data_len);
828 if (ret) {
829 kfree(data);
830 break;
831 }
832 ret = copy_to_user((void __user *)pkt.data, data, pkt.data_len);
833
834 kfree(data);
835 break;
836 }
837 case PREISP_ST_QUERY: {
838 s32 state;
839
840 ret = rk1608_state_query(pdata->spi, &state);
841 if (ret)
842 break;
843
844 ret = put_user(state, (s32 __user *)ubuf);
845 break;
846 }
847 case PREISP_IRQ_REQUEST: {
848 int int_num = arg;
849
850 ret = rk1608_interrupt_request(pdata->spi, int_num);
851 break;
852 }
853 case PREISP_SEND_MSG: {
854 struct msg *msg;
855 u32 len;
856
857 if (get_user(len, (u32 __user *)ubuf)) {
858 ret = -EFAULT;
859 break;
860 }
861 len = len * sizeof(s32);
862 msg = memdup_user(ubuf, len);
863 if (IS_ERR(msg)) {
864 ret = (long)ERR_PTR((long)msg);
865 break;
866 }
867
868 #if DEBUG_DUMP_ALL_SEND_RECV_MSG == 1
869 int32_hexdump("send msg:", (s32 *)msg, len);
870 #endif
871
872 ret = rk1608_send_msg_to_dsp(pdata, msg);
873 kfree(msg);
874 break;
875 }
876 case PREISP_QUERY_MSG: {
877 struct msg *msg;
878
879 ret = msq_recv_msg(&client->q, &msg);
880 if (ret)
881 break;
882
883 ret = put_user(msg->size, (u32 __user *)ubuf);
884 break;
885 }
886 case PREISP_RECV_MSG: {
887 struct msg *msg;
888
889 ret = msq_recv_msg(&client->q, &msg);
890 if (ret)
891 break;
892
893 ret = copy_to_user(ubuf, msg, msg->size * sizeof(u32));
894 msq_free_received_msg(&client->q, msg);
895 break;
896 }
897 case PREISP_CLIENT_CONNECT: {
898 client->id = (int)arg;
899 ret = rk1608_client_connect(pdata, client);
900 break;
901 }
902 case PREISP_CLIENT_DISCONNECT: {
903 rk1608_client_disconnect(pdata, client);
904 client->id = INVALID_ID;
905 break;
906 }
907 default:
908 ret = -EFAULT;
909 break;
910 }
911
912 return ret;
913 }
914
915 #ifdef CONFIG_COMPAT
916 #define PREISP_WRITE32 _IOW('p', 6, struct preisp_apb_pkt32)
917 #define PREISP_READ32 _IOR('p', 7, struct preisp_apb_pkt32)
918
919 struct preisp_apb_pkt32 {
920 s32 data_len;
921 s32 addr;
922 compat_uptr_t data;
923 };
924
rk1608_compat_ioctl(struct file * file,unsigned int cmd,unsigned long arg)925 static long rk1608_compat_ioctl(struct file *file, unsigned int cmd,
926 unsigned long arg)
927 {
928 int ret = 0;
929 struct preisp_apb_pkt32 pkt32;
930 struct preisp_apb_pkt *pkt;
931
932 switch (cmd) {
933 case PREISP_WRITE32:
934 cmd = PREISP_WRITE;
935 break;
936 case PREISP_READ32:
937 cmd = PREISP_READ;
938 break;
939 default:
940 break;
941 }
942
943 switch (cmd) {
944 case PREISP_WRITE:
945 case PREISP_READ:
946 if (copy_from_user(&pkt32, (void __user *)arg, sizeof(pkt32)))
947 return -EFAULT;
948
949 pkt = compat_alloc_user_space(sizeof(*pkt));
950 if (!pkt ||
951 put_user(pkt32.data_len, &pkt->data_len) ||
952 put_user(pkt32.addr, &pkt->addr) ||
953 put_user(compat_ptr(pkt32.data), &pkt->data))
954 return -EFAULT;
955
956 ret = rk1608_dev_ioctl(file, cmd, (unsigned long)pkt);
957 break;
958 default:
959 ret = rk1608_dev_ioctl(file, cmd, arg);
960 break;
961 }
962
963 return ret;
964 }
965 #endif
966
rk1608_dev_poll(struct file * file,poll_table * wait)967 static unsigned int rk1608_dev_poll(struct file *file, poll_table *wait)
968 {
969 struct rk1608_client *client = file->private_data;
970 unsigned int mask = 0;
971
972 poll_wait(file, &client->wait, wait);
973
974 if (!msq_is_empty(&client->q))
975 mask |= POLLIN;
976
977 return mask;
978 }
979
980 static const struct file_operations rk1608_fops = {
981 .owner = THIS_MODULE,
982 .open = rk1608_dev_open,
983 .release = rk1608_dev_release,
984 .write = rk1608_dev_write,
985 .poll = rk1608_dev_poll,
986 .unlocked_ioctl = rk1608_dev_ioctl,
987 #ifdef CONFIG_COMPAT
988 .compat_ioctl = rk1608_compat_ioctl,
989 #endif
990 };
991
rk1608_dev_receive_msg(struct rk1608_state * pdata,struct msg * msg)992 void rk1608_dev_receive_msg(struct rk1608_state *pdata, struct msg *msg)
993 {
994 struct rk1608_client_list *s = &pdata->clients;
995 struct rk1608_client *client;
996
997 #if DEBUG_DUMP_ALL_SEND_RECV_MSG == 1
998 int32_hexdump("recv msg:", (s32 *)msg, msg->size * 4);
999 #endif
1000
1001 mutex_lock(&s->mutex);
1002 list_for_each_entry(client, &s->list, list) {
1003 if (client->id == msg->id.camera_id) {
1004 msq_send_msg(&client->q, msg);
1005 wake_up_interruptible(&client->wait);
1006 }
1007 }
1008 mutex_unlock(&s->mutex);
1009 }
1010
rk1608_dev_register(struct rk1608_state * pdata)1011 int rk1608_dev_register(struct rk1608_state *pdata)
1012 {
1013 int ret;
1014
1015 rk1608_client_list_init(&pdata->clients);
1016
1017 pdata->misc.minor = MISC_DYNAMIC_MINOR;
1018 pdata->misc.name = "rk_preisp";
1019 pdata->misc.fops = &rk1608_fops;
1020
1021 ret = misc_register(&pdata->misc);
1022 if (ret < 0)
1023 dev_err(pdata->dev, "Error: misc_register returned %d\n", ret);
1024
1025 return 0;
1026 }
1027
rk1608_dev_unregister(struct rk1608_state * pdata)1028 void rk1608_dev_unregister(struct rk1608_state *pdata)
1029 {
1030 misc_deregister(&pdata->misc);
1031 }
1032