]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/media/platform/sti/delta/delta-ipc.c
Merge branches 'for-4.11/upstream-fixes', 'for-4.12/accutouch', 'for-4.12/cp2112...
[mirror_ubuntu-artful-kernel.git] / drivers / media / platform / sti / delta / delta-ipc.c
1 /*
2 * Copyright (C) STMicroelectronics SA 2015
3 * Author: Hugues Fruchet <hugues.fruchet@st.com> for STMicroelectronics.
4 * License terms: GNU General Public License (GPL), version 2
5 */
6
7 #include <linux/rpmsg.h>
8
9 #include "delta.h"
10 #include "delta-ipc.h"
11 #include "delta-mem.h"
12
13 #define IPC_TIMEOUT 100
14 #define IPC_SANITY_TAG 0xDEADBEEF
15
16 enum delta_ipc_fw_command {
17 DELTA_IPC_OPEN,
18 DELTA_IPC_SET_STREAM,
19 DELTA_IPC_DECODE,
20 DELTA_IPC_CLOSE
21 };
22
23 #define to_rpmsg_driver(__drv) container_of(__drv, struct rpmsg_driver, drv)
24 #define to_delta(__d) container_of(__d, struct delta_dev, rpmsg_driver)
25
26 #define to_ctx(hdl) ((struct delta_ipc_ctx *)hdl)
27 #define to_pctx(ctx) container_of(ctx, struct delta_ctx, ipc_ctx)
28
29 struct delta_ipc_header_msg {
30 u32 tag;
31 void *host_hdl;
32 u32 copro_hdl;
33 u32 command;
34 };
35
36 #define to_host_hdl(ctx) ((void *)ctx)
37
38 #define msg_to_ctx(msg) ((struct delta_ipc_ctx *)(msg)->header.host_hdl)
39 #define msg_to_copro_hdl(msg) ((msg)->header.copro_hdl)
40
41 static inline dma_addr_t to_paddr(struct delta_ipc_ctx *ctx, void *vaddr)
42 {
43 return (ctx->ipc_buf->paddr + (vaddr - ctx->ipc_buf->vaddr));
44 }
45
46 static inline bool is_valid_data(struct delta_ipc_ctx *ctx,
47 void *data, u32 size)
48 {
49 return ((data >= ctx->ipc_buf->vaddr) &&
50 ((data + size) <= (ctx->ipc_buf->vaddr + ctx->ipc_buf->size)));
51 }
52
53 /*
54 * IPC shared memory (@ipc_buf_size, @ipc_buf_paddr) is sent to copro
55 * at each instance opening. This memory is allocated by IPC client
56 * and given through delta_ipc_open(). All messages parameters
57 * (open, set_stream, decode) will have their phy address within
58 * this IPC shared memory, avoiding de-facto recopies inside delta-ipc.
59 * All the below messages structures are used on both host and firmware
60 * side and are packed (use only of 32 bits size fields in messages
61 * structures to ensure packing):
62 * - struct delta_ipc_open_msg
63 * - struct delta_ipc_set_stream_msg
64 * - struct delta_ipc_decode_msg
65 * - struct delta_ipc_close_msg
66 * - struct delta_ipc_cb_msg
67 */
68 struct delta_ipc_open_msg {
69 struct delta_ipc_header_msg header;
70 u32 ipc_buf_size;
71 dma_addr_t ipc_buf_paddr;
72 char name[32];
73 u32 param_size;
74 dma_addr_t param_paddr;
75 };
76
77 struct delta_ipc_set_stream_msg {
78 struct delta_ipc_header_msg header;
79 u32 param_size;
80 dma_addr_t param_paddr;
81 };
82
83 struct delta_ipc_decode_msg {
84 struct delta_ipc_header_msg header;
85 u32 param_size;
86 dma_addr_t param_paddr;
87 u32 status_size;
88 dma_addr_t status_paddr;
89 };
90
91 struct delta_ipc_close_msg {
92 struct delta_ipc_header_msg header;
93 };
94
95 struct delta_ipc_cb_msg {
96 struct delta_ipc_header_msg header;
97 int err;
98 };
99
100 static void build_msg_header(struct delta_ipc_ctx *ctx,
101 enum delta_ipc_fw_command command,
102 struct delta_ipc_header_msg *header)
103 {
104 header->tag = IPC_SANITY_TAG;
105 header->host_hdl = to_host_hdl(ctx);
106 header->copro_hdl = ctx->copro_hdl;
107 header->command = command;
108 }
109
110 int delta_ipc_open(struct delta_ctx *pctx, const char *name,
111 struct delta_ipc_param *param, u32 ipc_buf_size,
112 struct delta_buf **ipc_buf, void **hdl)
113 {
114 struct delta_dev *delta = pctx->dev;
115 struct rpmsg_device *rpmsg_device = delta->rpmsg_device;
116 struct delta_ipc_ctx *ctx = &pctx->ipc_ctx;
117 struct delta_ipc_open_msg msg;
118 struct delta_buf *buf = &ctx->ipc_buf_struct;
119 int ret;
120
121 if (!rpmsg_device) {
122 dev_err(delta->dev,
123 "%s ipc: failed to open, rpmsg is not initialized\n",
124 pctx->name);
125 pctx->sys_errors++;
126 return -EINVAL;
127 }
128
129 if (!name) {
130 dev_err(delta->dev,
131 "%s ipc: failed to open, no name given\n",
132 pctx->name);
133 return -EINVAL;
134 }
135
136 if (!param || !param->data || !param->size) {
137 dev_err(delta->dev,
138 "%s ipc: failed to open, empty parameter\n",
139 pctx->name);
140 return -EINVAL;
141 }
142
143 if (!ipc_buf_size) {
144 dev_err(delta->dev,
145 "%s ipc: failed to open, no size given for ipc buffer\n",
146 pctx->name);
147 return -EINVAL;
148 }
149
150 if (param->size > ipc_buf_size) {
151 dev_err(delta->dev,
152 "%s ipc: failed to open, too large ipc parameter (%d bytes while max %d expected)\n",
153 pctx->name,
154 param->size, ctx->ipc_buf->size);
155 return -EINVAL;
156 }
157
158 /* init */
159 init_completion(&ctx->done);
160
161 /*
162 * allocation of contiguous buffer for
163 * data of commands exchanged between
164 * host and firmware coprocessor
165 */
166 ret = hw_alloc(pctx, ipc_buf_size,
167 "ipc data buffer", buf);
168 if (ret)
169 return ret;
170 ctx->ipc_buf = buf;
171
172 /* build rpmsg message */
173 build_msg_header(ctx, DELTA_IPC_OPEN, &msg.header);
174
175 msg.ipc_buf_size = ipc_buf_size;
176 msg.ipc_buf_paddr = ctx->ipc_buf->paddr;
177
178 memcpy(msg.name, name, sizeof(msg.name));
179 msg.name[sizeof(msg.name) - 1] = 0;
180
181 msg.param_size = param->size;
182 memcpy(ctx->ipc_buf->vaddr, param->data, msg.param_size);
183 msg.param_paddr = ctx->ipc_buf->paddr;
184
185 /* send it */
186 ret = rpmsg_send(rpmsg_device->ept, &msg, sizeof(msg));
187 if (ret) {
188 dev_err(delta->dev,
189 "%s ipc: failed to open, rpmsg_send failed (%d) for DELTA_IPC_OPEN (name=%s, size=%d, data=%p)\n",
190 pctx->name,
191 ret, name, param->size, param->data);
192 goto err;
193 }
194
195 /* wait for acknowledge */
196 if (!wait_for_completion_timeout
197 (&ctx->done, msecs_to_jiffies(IPC_TIMEOUT))) {
198 dev_err(delta->dev,
199 "%s ipc: failed to open, timeout waiting for DELTA_IPC_OPEN callback (name=%s, size=%d, data=%p)\n",
200 pctx->name,
201 name, param->size, param->data);
202 ret = -ETIMEDOUT;
203 goto err;
204 }
205
206 /* command completed, check error */
207 if (ctx->cb_err) {
208 dev_err(delta->dev,
209 "%s ipc: failed to open, DELTA_IPC_OPEN completed but with error (%d) (name=%s, size=%d, data=%p)\n",
210 pctx->name,
211 ctx->cb_err, name, param->size, param->data);
212 ret = -EIO;
213 goto err;
214 }
215
216 *ipc_buf = ctx->ipc_buf;
217 *hdl = (void *)ctx;
218
219 return 0;
220
221 err:
222 pctx->sys_errors++;
223 if (ctx->ipc_buf) {
224 hw_free(pctx, ctx->ipc_buf);
225 ctx->ipc_buf = NULL;
226 }
227
228 return ret;
229 };
230
231 int delta_ipc_set_stream(void *hdl, struct delta_ipc_param *param)
232 {
233 struct delta_ipc_ctx *ctx = to_ctx(hdl);
234 struct delta_ctx *pctx = to_pctx(ctx);
235 struct delta_dev *delta = pctx->dev;
236 struct rpmsg_device *rpmsg_device = delta->rpmsg_device;
237 struct delta_ipc_set_stream_msg msg;
238 int ret;
239
240 if (!hdl) {
241 dev_err(delta->dev,
242 "%s ipc: failed to set stream, invalid ipc handle\n",
243 pctx->name);
244 return -EINVAL;
245 }
246
247 if (!rpmsg_device) {
248 dev_err(delta->dev,
249 "%s ipc: failed to set stream, rpmsg is not initialized\n",
250 pctx->name);
251 return -EINVAL;
252 }
253
254 if (!param || !param->data || !param->size) {
255 dev_err(delta->dev,
256 "%s ipc: failed to set stream, empty parameter\n",
257 pctx->name);
258 return -EINVAL;
259 }
260
261 if (param->size > ctx->ipc_buf->size) {
262 dev_err(delta->dev,
263 "%s ipc: failed to set stream, too large ipc parameter(%d bytes while max %d expected)\n",
264 pctx->name,
265 param->size, ctx->ipc_buf->size);
266 return -EINVAL;
267 }
268
269 if (!is_valid_data(ctx, param->data, param->size)) {
270 dev_err(delta->dev,
271 "%s ipc: failed to set stream, parameter is not in expected address range (size=%d, data=%p not in %p..%p)\n",
272 pctx->name,
273 param->size,
274 param->data,
275 ctx->ipc_buf->vaddr,
276 ctx->ipc_buf->vaddr + ctx->ipc_buf->size - 1);
277 return -EINVAL;
278 }
279
280 /* build rpmsg message */
281 build_msg_header(ctx, DELTA_IPC_SET_STREAM, &msg.header);
282
283 msg.param_size = param->size;
284 msg.param_paddr = to_paddr(ctx, param->data);
285
286 /* send it */
287 ret = rpmsg_send(rpmsg_device->ept, &msg, sizeof(msg));
288 if (ret) {
289 dev_err(delta->dev,
290 "%s ipc: failed to set stream, rpmsg_send failed (%d) for DELTA_IPC_SET_STREAM (size=%d, data=%p)\n",
291 pctx->name,
292 ret, param->size, param->data);
293 pctx->sys_errors++;
294 return ret;
295 }
296
297 /* wait for acknowledge */
298 if (!wait_for_completion_timeout
299 (&ctx->done, msecs_to_jiffies(IPC_TIMEOUT))) {
300 dev_err(delta->dev,
301 "%s ipc: failed to set stream, timeout waiting for DELTA_IPC_SET_STREAM callback (size=%d, data=%p)\n",
302 pctx->name,
303 param->size, param->data);
304 pctx->sys_errors++;
305 return -ETIMEDOUT;
306 }
307
308 /* command completed, check status */
309 if (ctx->cb_err) {
310 dev_err(delta->dev,
311 "%s ipc: failed to set stream, DELTA_IPC_SET_STREAM completed but with error (%d) (size=%d, data=%p)\n",
312 pctx->name,
313 ctx->cb_err, param->size, param->data);
314 pctx->sys_errors++;
315 return -EIO;
316 }
317
318 return 0;
319 }
320
321 int delta_ipc_decode(void *hdl, struct delta_ipc_param *param,
322 struct delta_ipc_param *status)
323 {
324 struct delta_ipc_ctx *ctx = to_ctx(hdl);
325 struct delta_ctx *pctx = to_pctx(ctx);
326 struct delta_dev *delta = pctx->dev;
327 struct rpmsg_device *rpmsg_device = delta->rpmsg_device;
328 struct delta_ipc_decode_msg msg;
329 int ret;
330
331 if (!hdl) {
332 dev_err(delta->dev,
333 "%s ipc: failed to decode, invalid ipc handle\n",
334 pctx->name);
335 return -EINVAL;
336 }
337
338 if (!rpmsg_device) {
339 dev_err(delta->dev,
340 "%s ipc: failed to decode, rpmsg is not initialized\n",
341 pctx->name);
342 return -EINVAL;
343 }
344
345 if (!param || !param->data || !param->size) {
346 dev_err(delta->dev,
347 "%s ipc: failed to decode, empty parameter\n",
348 pctx->name);
349 return -EINVAL;
350 }
351
352 if (!status || !status->data || !status->size) {
353 dev_err(delta->dev,
354 "%s ipc: failed to decode, empty status\n",
355 pctx->name);
356 return -EINVAL;
357 }
358
359 if (param->size + status->size > ctx->ipc_buf->size) {
360 dev_err(delta->dev,
361 "%s ipc: failed to decode, too large ipc parameter (%d bytes (param) + %d bytes (status) while max %d expected)\n",
362 pctx->name,
363 param->size,
364 status->size,
365 ctx->ipc_buf->size);
366 return -EINVAL;
367 }
368
369 if (!is_valid_data(ctx, param->data, param->size)) {
370 dev_err(delta->dev,
371 "%s ipc: failed to decode, parameter is not in expected address range (size=%d, data=%p not in %p..%p)\n",
372 pctx->name,
373 param->size,
374 param->data,
375 ctx->ipc_buf->vaddr,
376 ctx->ipc_buf->vaddr + ctx->ipc_buf->size - 1);
377 return -EINVAL;
378 }
379
380 if (!is_valid_data(ctx, status->data, status->size)) {
381 dev_err(delta->dev,
382 "%s ipc: failed to decode, status is not in expected address range (size=%d, data=%p not in %p..%p)\n",
383 pctx->name,
384 status->size,
385 status->data,
386 ctx->ipc_buf->vaddr,
387 ctx->ipc_buf->vaddr + ctx->ipc_buf->size - 1);
388 return -EINVAL;
389 }
390
391 /* build rpmsg message */
392 build_msg_header(ctx, DELTA_IPC_DECODE, &msg.header);
393
394 msg.param_size = param->size;
395 msg.param_paddr = to_paddr(ctx, param->data);
396
397 msg.status_size = status->size;
398 msg.status_paddr = to_paddr(ctx, status->data);
399
400 /* send it */
401 ret = rpmsg_send(rpmsg_device->ept, &msg, sizeof(msg));
402 if (ret) {
403 dev_err(delta->dev,
404 "%s ipc: failed to decode, rpmsg_send failed (%d) for DELTA_IPC_DECODE (size=%d, data=%p)\n",
405 pctx->name,
406 ret, param->size, param->data);
407 pctx->sys_errors++;
408 return ret;
409 }
410
411 /* wait for acknowledge */
412 if (!wait_for_completion_timeout
413 (&ctx->done, msecs_to_jiffies(IPC_TIMEOUT))) {
414 dev_err(delta->dev,
415 "%s ipc: failed to decode, timeout waiting for DELTA_IPC_DECODE callback (size=%d, data=%p)\n",
416 pctx->name,
417 param->size, param->data);
418 pctx->sys_errors++;
419 return -ETIMEDOUT;
420 }
421
422 /* command completed, check status */
423 if (ctx->cb_err) {
424 dev_err(delta->dev,
425 "%s ipc: failed to decode, DELTA_IPC_DECODE completed but with error (%d) (size=%d, data=%p)\n",
426 pctx->name,
427 ctx->cb_err, param->size, param->data);
428 pctx->sys_errors++;
429 return -EIO;
430 }
431
432 return 0;
433 };
434
435 void delta_ipc_close(void *hdl)
436 {
437 struct delta_ipc_ctx *ctx = to_ctx(hdl);
438 struct delta_ctx *pctx = to_pctx(ctx);
439 struct delta_dev *delta = pctx->dev;
440 struct rpmsg_device *rpmsg_device = delta->rpmsg_device;
441 struct delta_ipc_close_msg msg;
442 int ret;
443
444 if (!hdl) {
445 dev_err(delta->dev,
446 "%s ipc: failed to close, invalid ipc handle\n",
447 pctx->name);
448 return;
449 }
450
451 if (ctx->ipc_buf) {
452 hw_free(pctx, ctx->ipc_buf);
453 ctx->ipc_buf = NULL;
454 }
455
456 if (!rpmsg_device) {
457 dev_err(delta->dev,
458 "%s ipc: failed to close, rpmsg is not initialized\n",
459 pctx->name);
460 return;
461 }
462
463 /* build rpmsg message */
464 build_msg_header(ctx, DELTA_IPC_CLOSE, &msg.header);
465
466 /* send it */
467 ret = rpmsg_send(rpmsg_device->ept, &msg, sizeof(msg));
468 if (ret) {
469 dev_err(delta->dev,
470 "%s ipc: failed to close, rpmsg_send failed (%d) for DELTA_IPC_CLOSE\n",
471 pctx->name, ret);
472 pctx->sys_errors++;
473 return;
474 }
475
476 /* wait for acknowledge */
477 if (!wait_for_completion_timeout
478 (&ctx->done, msecs_to_jiffies(IPC_TIMEOUT))) {
479 dev_err(delta->dev,
480 "%s ipc: failed to close, timeout waiting for DELTA_IPC_CLOSE callback\n",
481 pctx->name);
482 pctx->sys_errors++;
483 return;
484 }
485
486 /* command completed, check status */
487 if (ctx->cb_err) {
488 dev_err(delta->dev,
489 "%s ipc: failed to close, DELTA_IPC_CLOSE completed but with error (%d)\n",
490 pctx->name, ctx->cb_err);
491 pctx->sys_errors++;
492 }
493 };
494
495 static int delta_ipc_cb(struct rpmsg_device *rpdev, void *data,
496 int len, void *priv, u32 src)
497 {
498 struct delta_ipc_ctx *ctx;
499 struct delta_ipc_cb_msg *msg;
500
501 /* sanity check */
502 if (!rpdev) {
503 dev_err(NULL, "rpdev is NULL\n");
504 return -EINVAL;
505 }
506
507 if (!data || !len) {
508 dev_err(&rpdev->dev,
509 "unexpected empty message received from src=%d\n", src);
510 return -EINVAL;
511 }
512
513 if (len != sizeof(*msg)) {
514 dev_err(&rpdev->dev,
515 "unexpected message length received from src=%d (received %d bytes while %zu bytes expected)\n",
516 len, src, sizeof(*msg));
517 return -EINVAL;
518 }
519
520 msg = (struct delta_ipc_cb_msg *)data;
521 if (msg->header.tag != IPC_SANITY_TAG) {
522 dev_err(&rpdev->dev,
523 "unexpected message tag received from src=%d (received %x tag while %x expected)\n",
524 src, msg->header.tag, IPC_SANITY_TAG);
525 return -EINVAL;
526 }
527
528 ctx = msg_to_ctx(msg);
529 if (!ctx) {
530 dev_err(&rpdev->dev,
531 "unexpected message with NULL host_hdl received from src=%d\n",
532 src);
533 return -EINVAL;
534 }
535
536 /*
537 * if not already known, save copro instance context
538 * to ensure re-entrance on copro side
539 */
540 if (!ctx->copro_hdl)
541 ctx->copro_hdl = msg_to_copro_hdl(msg);
542
543 /*
544 * all is fine,
545 * update status & complete command
546 */
547 ctx->cb_err = msg->err;
548 complete(&ctx->done);
549
550 return 0;
551 }
552
553 static int delta_ipc_probe(struct rpmsg_device *rpmsg_device)
554 {
555 struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpmsg_device->dev.driver);
556 struct delta_dev *delta = to_delta(rpdrv);
557
558 delta->rpmsg_device = rpmsg_device;
559
560 return 0;
561 }
562
563 static void delta_ipc_remove(struct rpmsg_device *rpmsg_device)
564 {
565 struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpmsg_device->dev.driver);
566 struct delta_dev *delta = to_delta(rpdrv);
567
568 delta->rpmsg_device = NULL;
569 }
570
571 static struct rpmsg_device_id delta_ipc_device_id_table[] = {
572 {.name = "rpmsg-delta"},
573 {},
574 };
575
576 static struct rpmsg_driver delta_rpmsg_driver = {
577 .drv = {.name = KBUILD_MODNAME},
578 .id_table = delta_ipc_device_id_table,
579 .probe = delta_ipc_probe,
580 .callback = delta_ipc_cb,
581 .remove = delta_ipc_remove,
582 };
583
584 int delta_ipc_init(struct delta_dev *delta)
585 {
586 delta->rpmsg_driver = delta_rpmsg_driver;
587
588 return register_rpmsg_driver(&delta->rpmsg_driver);
589 }
590
591 void delta_ipc_exit(struct delta_dev *delta)
592 {
593 unregister_rpmsg_driver(&delta->rpmsg_driver);
594 }