Merge tag 'drm-misc-fixes-2017-11-13' of git://anongit.freedesktop.org/drm/drm-misc...
[sfrench/cifs-2.6.git] / drivers / staging / media / imx / imx-media-dev.c
1 /*
2  * V4L2 Media Controller Driver for Freescale i.MX5/6 SOC
3  *
4  * Copyright (c) 2016 Mentor Graphics Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11 #include <linux/delay.h>
12 #include <linux/fs.h>
13 #include <linux/module.h>
14 #include <linux/of_platform.h>
15 #include <linux/pinctrl/consumer.h>
16 #include <linux/platform_device.h>
17 #include <linux/sched.h>
18 #include <linux/slab.h>
19 #include <linux/spinlock.h>
20 #include <linux/timer.h>
21 #include <media/v4l2-ctrls.h>
22 #include <media/v4l2-event.h>
23 #include <media/v4l2-ioctl.h>
24 #include <media/v4l2-mc.h>
25 #include <video/imx-ipu-v3.h>
26 #include <media/imx.h>
27 #include "imx-media.h"
28
29 static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n)
30 {
31         return container_of(n, struct imx_media_dev, subdev_notifier);
32 }
33
34 /*
35  * Find a subdev by device node or device name. This is called during
36  * driver load to form the async subdev list and bind them.
37  */
38 struct imx_media_subdev *
39 imx_media_find_async_subdev(struct imx_media_dev *imxmd,
40                             struct device_node *np,
41                             const char *devname)
42 {
43         struct fwnode_handle *fwnode = np ? of_fwnode_handle(np) : NULL;
44         struct imx_media_subdev *imxsd;
45         int i;
46
47         for (i = 0; i < imxmd->subdev_notifier.num_subdevs; i++) {
48                 imxsd = &imxmd->subdev[i];
49                 switch (imxsd->asd.match_type) {
50                 case V4L2_ASYNC_MATCH_FWNODE:
51                         if (fwnode && imxsd->asd.match.fwnode.fwnode == fwnode)
52                                 return imxsd;
53                         break;
54                 case V4L2_ASYNC_MATCH_DEVNAME:
55                         if (devname &&
56                             !strcmp(imxsd->asd.match.device_name.name, devname))
57                                 return imxsd;
58                         break;
59                 default:
60                         break;
61                 }
62         }
63
64         return NULL;
65 }
66
67
68 /*
69  * Adds a subdev to the async subdev list. If np is non-NULL, adds
70  * the async as a V4L2_ASYNC_MATCH_FWNODE match type, otherwise as
71  * a V4L2_ASYNC_MATCH_DEVNAME match type using the dev_name of the
72  * given platform_device. This is called during driver load when
73  * forming the async subdev list.
74  */
75 struct imx_media_subdev *
76 imx_media_add_async_subdev(struct imx_media_dev *imxmd,
77                            struct device_node *np,
78                            struct platform_device *pdev)
79 {
80         struct imx_media_subdev *imxsd;
81         struct v4l2_async_subdev *asd;
82         const char *devname = NULL;
83         int sd_idx;
84
85         mutex_lock(&imxmd->mutex);
86
87         if (pdev)
88                 devname = dev_name(&pdev->dev);
89
90         /* return -EEXIST if this subdev already added */
91         if (imx_media_find_async_subdev(imxmd, np, devname)) {
92                 dev_dbg(imxmd->md.dev, "%s: already added %s\n",
93                         __func__, np ? np->name : devname);
94                 imxsd = ERR_PTR(-EEXIST);
95                 goto out;
96         }
97
98         sd_idx = imxmd->subdev_notifier.num_subdevs;
99         if (sd_idx >= IMX_MEDIA_MAX_SUBDEVS) {
100                 dev_err(imxmd->md.dev, "%s: too many subdevs! can't add %s\n",
101                         __func__, np ? np->name : devname);
102                 imxsd = ERR_PTR(-ENOSPC);
103                 goto out;
104         }
105
106         imxsd = &imxmd->subdev[sd_idx];
107
108         asd = &imxsd->asd;
109         if (np) {
110                 asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
111                 asd->match.fwnode.fwnode = of_fwnode_handle(np);
112         } else {
113                 asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
114                 strncpy(imxsd->devname, devname, sizeof(imxsd->devname));
115                 asd->match.device_name.name = imxsd->devname;
116                 imxsd->pdev = pdev;
117         }
118
119         imxmd->async_ptrs[sd_idx] = asd;
120         imxmd->subdev_notifier.num_subdevs++;
121
122         dev_dbg(imxmd->md.dev, "%s: added %s, match type %s\n",
123                 __func__, np ? np->name : devname, np ? "FWNODE" : "DEVNAME");
124
125 out:
126         mutex_unlock(&imxmd->mutex);
127         return imxsd;
128 }
129
130 /*
131  * Adds an imx-media link to a subdev pad's link list. This is called
132  * during driver load when forming the links between subdevs.
133  *
134  * @pad: the local pad
135  * @remote_node: the device node of the remote subdev
136  * @remote_devname: the device name of the remote subdev
137  * @local_pad: local pad index
138  * @remote_pad: remote pad index
139  */
140 int imx_media_add_pad_link(struct imx_media_dev *imxmd,
141                            struct imx_media_pad *pad,
142                            struct device_node *remote_node,
143                            const char *remote_devname,
144                            int local_pad, int remote_pad)
145 {
146         struct imx_media_link *link;
147         int link_idx, ret = 0;
148
149         mutex_lock(&imxmd->mutex);
150
151         link_idx = pad->num_links;
152         if (link_idx >= IMX_MEDIA_MAX_LINKS) {
153                 dev_err(imxmd->md.dev, "%s: too many links!\n", __func__);
154                 ret = -ENOSPC;
155                 goto out;
156         }
157
158         link = &pad->link[link_idx];
159
160         link->remote_sd_node = remote_node;
161         if (remote_devname)
162                 strncpy(link->remote_devname, remote_devname,
163                         sizeof(link->remote_devname));
164
165         link->local_pad = local_pad;
166         link->remote_pad = remote_pad;
167
168         pad->num_links++;
169 out:
170         mutex_unlock(&imxmd->mutex);
171         return ret;
172 }
173
174 /*
175  * get IPU from this CSI and add it to the list of IPUs
176  * the media driver will control.
177  */
178 static int imx_media_get_ipu(struct imx_media_dev *imxmd,
179                              struct v4l2_subdev *csi_sd)
180 {
181         struct ipu_soc *ipu;
182         int ipu_id;
183
184         ipu = dev_get_drvdata(csi_sd->dev->parent);
185         if (!ipu) {
186                 v4l2_err(&imxmd->v4l2_dev,
187                          "CSI %s has no parent IPU!\n", csi_sd->name);
188                 return -ENODEV;
189         }
190
191         ipu_id = ipu_get_num(ipu);
192         if (ipu_id > 1) {
193                 v4l2_err(&imxmd->v4l2_dev, "invalid IPU id %d!\n", ipu_id);
194                 return -ENODEV;
195         }
196
197         if (!imxmd->ipu[ipu_id])
198                 imxmd->ipu[ipu_id] = ipu;
199
200         return 0;
201 }
202
203 /* async subdev bound notifier */
204 static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
205                                   struct v4l2_subdev *sd,
206                                   struct v4l2_async_subdev *asd)
207 {
208         struct imx_media_dev *imxmd = notifier2dev(notifier);
209         struct device_node *np = to_of_node(sd->fwnode);
210         struct imx_media_subdev *imxsd;
211         int ret = 0;
212
213         mutex_lock(&imxmd->mutex);
214
215         imxsd = imx_media_find_async_subdev(imxmd, np, dev_name(sd->dev));
216         if (!imxsd) {
217                 ret = -EINVAL;
218                 goto out;
219         }
220
221         if (sd->grp_id & IMX_MEDIA_GRP_ID_CSI) {
222                 ret = imx_media_get_ipu(imxmd, sd);
223                 if (ret)
224                         goto out_unlock;
225         } else if (sd->entity.function == MEDIA_ENT_F_VID_MUX) {
226                 /* this is a video mux */
227                 sd->grp_id = IMX_MEDIA_GRP_ID_VIDMUX;
228         } else if (imxsd->num_sink_pads == 0) {
229                 /*
230                  * this is an original source of video frames, it
231                  * could be a camera sensor, an analog decoder, or
232                  * a bridge device (HDMI -> MIPI CSI-2 for example).
233                  * This group ID is used to locate the entity that
234                  * is the original source of video in a pipeline.
235                  */
236                 sd->grp_id = IMX_MEDIA_GRP_ID_SENSOR;
237         }
238
239         /* attach the subdev */
240         imxsd->sd = sd;
241 out:
242         if (ret)
243                 v4l2_warn(&imxmd->v4l2_dev,
244                           "Received unknown subdev %s\n", sd->name);
245         else
246                 v4l2_info(&imxmd->v4l2_dev,
247                           "Registered subdev %s\n", sd->name);
248
249 out_unlock:
250         mutex_unlock(&imxmd->mutex);
251         return ret;
252 }
253
254 /*
255  * Create a single source->sink media link given a subdev and a single
256  * link from one of its source pads. Called after all subdevs have
257  * registered.
258  */
259 static int imx_media_create_link(struct imx_media_dev *imxmd,
260                                  struct imx_media_subdev *src,
261                                  struct imx_media_link *link)
262 {
263         struct imx_media_subdev *sink;
264         u16 source_pad, sink_pad;
265         int ret;
266
267         sink = imx_media_find_async_subdev(imxmd, link->remote_sd_node,
268                                            link->remote_devname);
269         if (!sink) {
270                 v4l2_warn(&imxmd->v4l2_dev, "%s: no sink for %s:%d\n",
271                           __func__, src->sd->name, link->local_pad);
272                 return 0;
273         }
274
275         source_pad = link->local_pad;
276         sink_pad = link->remote_pad;
277
278         v4l2_info(&imxmd->v4l2_dev, "%s: %s:%d -> %s:%d\n", __func__,
279                   src->sd->name, source_pad, sink->sd->name, sink_pad);
280
281         ret = media_create_pad_link(&src->sd->entity, source_pad,
282                                     &sink->sd->entity, sink_pad, 0);
283         if (ret)
284                 v4l2_err(&imxmd->v4l2_dev,
285                          "create_pad_link failed: %d\n", ret);
286
287         return ret;
288 }
289
290 /*
291  * create the media links from all imx-media pads and their links.
292  * Called after all subdevs have registered.
293  */
294 static int imx_media_create_links(struct imx_media_dev *imxmd)
295 {
296         struct imx_media_subdev *imxsd;
297         struct imx_media_link *link;
298         struct imx_media_pad *pad;
299         int num_pads, i, j, k;
300         int ret = 0;
301
302         for (i = 0; i < imxmd->num_subdevs; i++) {
303                 imxsd = &imxmd->subdev[i];
304                 num_pads = imxsd->num_sink_pads + imxsd->num_src_pads;
305
306                 for (j = 0; j < num_pads; j++) {
307                         pad = &imxsd->pad[j];
308
309                         /* only create the source->sink links */
310                         if (!(pad->pad.flags & MEDIA_PAD_FL_SOURCE))
311                                 continue;
312
313                         for (k = 0; k < pad->num_links; k++) {
314                                 link = &pad->link[k];
315
316                                 ret = imx_media_create_link(imxmd, imxsd, link);
317                                 if (ret)
318                                         goto out;
319                         }
320                 }
321         }
322
323 out:
324         return ret;
325 }
326
327 /*
328  * adds given video device to given imx-media source pad vdev list.
329  * Continues upstream from the pad entity's sink pads.
330  */
331 static int imx_media_add_vdev_to_pad(struct imx_media_dev *imxmd,
332                                      struct imx_media_video_dev *vdev,
333                                      struct media_pad *srcpad)
334 {
335         struct media_entity *entity = srcpad->entity;
336         struct imx_media_subdev *imxsd;
337         struct imx_media_pad *imxpad;
338         struct media_link *link;
339         struct v4l2_subdev *sd;
340         int i, vdev_idx, ret;
341
342         /* skip this entity if not a v4l2_subdev */
343         if (!is_media_entity_v4l2_subdev(entity))
344                 return 0;
345
346         sd = media_entity_to_v4l2_subdev(entity);
347         imxsd = imx_media_find_subdev_by_sd(imxmd, sd);
348         if (IS_ERR(imxsd))
349                 return PTR_ERR(imxsd);
350
351         imxpad = &imxsd->pad[srcpad->index];
352         vdev_idx = imxpad->num_vdevs;
353
354         /* just return if we've been here before */
355         for (i = 0; i < vdev_idx; i++)
356                 if (vdev == imxpad->vdev[i])
357                         return 0;
358
359         if (vdev_idx >= IMX_MEDIA_MAX_VDEVS) {
360                 dev_err(imxmd->md.dev, "can't add %s to pad %s:%u\n",
361                         vdev->vfd->entity.name, entity->name, srcpad->index);
362                 return -ENOSPC;
363         }
364
365         dev_dbg(imxmd->md.dev, "adding %s to pad %s:%u\n",
366                 vdev->vfd->entity.name, entity->name, srcpad->index);
367         imxpad->vdev[vdev_idx] = vdev;
368         imxpad->num_vdevs++;
369
370         /* move upstream from this entity's sink pads */
371         for (i = 0; i < entity->num_pads; i++) {
372                 struct media_pad *pad = &entity->pads[i];
373
374                 if (!(pad->flags & MEDIA_PAD_FL_SINK))
375                         continue;
376
377                 list_for_each_entry(link, &entity->links, list) {
378                         if (link->sink != pad)
379                                 continue;
380                         ret = imx_media_add_vdev_to_pad(imxmd, vdev,
381                                                         link->source);
382                         if (ret)
383                                 return ret;
384                 }
385         }
386
387         return 0;
388 }
389
390 /* form the vdev lists in all imx-media source pads */
391 static int imx_media_create_pad_vdev_lists(struct imx_media_dev *imxmd)
392 {
393         struct imx_media_video_dev *vdev;
394         struct media_link *link;
395         int i, ret;
396
397         for (i = 0; i < imxmd->num_vdevs; i++) {
398                 vdev = imxmd->vdev[i];
399                 link = list_first_entry(&vdev->vfd->entity.links,
400                                         struct media_link, list);
401                 ret = imx_media_add_vdev_to_pad(imxmd, vdev, link->source);
402                 if (ret)
403                         return ret;
404         }
405
406         return 0;
407 }
408
409 /* async subdev complete notifier */
410 static int imx_media_probe_complete(struct v4l2_async_notifier *notifier)
411 {
412         struct imx_media_dev *imxmd = notifier2dev(notifier);
413         int i, ret;
414
415         mutex_lock(&imxmd->mutex);
416
417         /* make sure all subdevs were bound */
418         for (i = 0; i < imxmd->num_subdevs; i++) {
419                 if (!imxmd->subdev[i].sd) {
420                         v4l2_err(&imxmd->v4l2_dev, "unbound subdev!\n");
421                         ret = -ENODEV;
422                         goto unlock;
423                 }
424         }
425
426         ret = imx_media_create_links(imxmd);
427         if (ret)
428                 goto unlock;
429
430         ret = imx_media_create_pad_vdev_lists(imxmd);
431         if (ret)
432                 goto unlock;
433
434         ret = v4l2_device_register_subdev_nodes(&imxmd->v4l2_dev);
435 unlock:
436         mutex_unlock(&imxmd->mutex);
437         if (ret)
438                 return ret;
439
440         return media_device_register(&imxmd->md);
441 }
442
443 /*
444  * adds controls to a video device from an entity subdevice.
445  * Continues upstream from the entity's sink pads.
446  */
447 static int imx_media_inherit_controls(struct imx_media_dev *imxmd,
448                                       struct video_device *vfd,
449                                       struct media_entity *entity)
450 {
451         int i, ret = 0;
452
453         if (is_media_entity_v4l2_subdev(entity)) {
454                 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
455
456                 dev_dbg(imxmd->md.dev,
457                         "adding controls to %s from %s\n",
458                         vfd->entity.name, sd->entity.name);
459
460                 ret = v4l2_ctrl_add_handler(vfd->ctrl_handler,
461                                             sd->ctrl_handler,
462                                             NULL);
463                 if (ret)
464                         return ret;
465         }
466
467         /* move upstream */
468         for (i = 0; i < entity->num_pads; i++) {
469                 struct media_pad *pad, *spad = &entity->pads[i];
470
471                 if (!(spad->flags & MEDIA_PAD_FL_SINK))
472                         continue;
473
474                 pad = media_entity_remote_pad(spad);
475                 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
476                         continue;
477
478                 ret = imx_media_inherit_controls(imxmd, vfd, pad->entity);
479                 if (ret)
480                         break;
481         }
482
483         return ret;
484 }
485
486 static int imx_media_link_notify(struct media_link *link, u32 flags,
487                                  unsigned int notification)
488 {
489         struct media_entity *source = link->source->entity;
490         struct imx_media_subdev *imxsd;
491         struct imx_media_pad *imxpad;
492         struct imx_media_dev *imxmd;
493         struct video_device *vfd;
494         struct v4l2_subdev *sd;
495         int i, pad_idx, ret;
496
497         ret = v4l2_pipeline_link_notify(link, flags, notification);
498         if (ret)
499                 return ret;
500
501         /* don't bother if source is not a subdev */
502         if (!is_media_entity_v4l2_subdev(source))
503                 return 0;
504
505         sd = media_entity_to_v4l2_subdev(source);
506         pad_idx = link->source->index;
507
508         imxmd = dev_get_drvdata(sd->v4l2_dev->dev);
509
510         imxsd = imx_media_find_subdev_by_sd(imxmd, sd);
511         if (IS_ERR(imxsd))
512                 return PTR_ERR(imxsd);
513         imxpad = &imxsd->pad[pad_idx];
514
515         /*
516          * Before disabling a link, reset controls for all video
517          * devices reachable from this link.
518          *
519          * After enabling a link, refresh controls for all video
520          * devices reachable from this link.
521          */
522         if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH &&
523             !(flags & MEDIA_LNK_FL_ENABLED)) {
524                 for (i = 0; i < imxpad->num_vdevs; i++) {
525                         vfd = imxpad->vdev[i]->vfd;
526                         dev_dbg(imxmd->md.dev,
527                                 "reset controls for %s\n",
528                                 vfd->entity.name);
529                         v4l2_ctrl_handler_free(vfd->ctrl_handler);
530                         v4l2_ctrl_handler_init(vfd->ctrl_handler, 0);
531                 }
532         } else if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
533                    (link->flags & MEDIA_LNK_FL_ENABLED)) {
534                 for (i = 0; i < imxpad->num_vdevs; i++) {
535                         vfd = imxpad->vdev[i]->vfd;
536                         dev_dbg(imxmd->md.dev,
537                                 "refresh controls for %s\n",
538                                 vfd->entity.name);
539                         ret = imx_media_inherit_controls(imxmd, vfd,
540                                                          &vfd->entity);
541                         if (ret)
542                                 break;
543                 }
544         }
545
546         return ret;
547 }
548
549 static const struct media_device_ops imx_media_md_ops = {
550         .link_notify = imx_media_link_notify,
551 };
552
553 static int imx_media_probe(struct platform_device *pdev)
554 {
555         struct device *dev = &pdev->dev;
556         struct device_node *node = dev->of_node;
557         struct imx_media_subdev *csi[4] = {0};
558         struct imx_media_dev *imxmd;
559         int ret;
560
561         imxmd = devm_kzalloc(dev, sizeof(*imxmd), GFP_KERNEL);
562         if (!imxmd)
563                 return -ENOMEM;
564
565         dev_set_drvdata(dev, imxmd);
566
567         strlcpy(imxmd->md.model, "imx-media", sizeof(imxmd->md.model));
568         imxmd->md.ops = &imx_media_md_ops;
569         imxmd->md.dev = dev;
570
571         mutex_init(&imxmd->mutex);
572
573         imxmd->v4l2_dev.mdev = &imxmd->md;
574         strlcpy(imxmd->v4l2_dev.name, "imx-media",
575                 sizeof(imxmd->v4l2_dev.name));
576
577         media_device_init(&imxmd->md);
578
579         ret = v4l2_device_register(dev, &imxmd->v4l2_dev);
580         if (ret < 0) {
581                 v4l2_err(&imxmd->v4l2_dev,
582                          "Failed to register v4l2_device: %d\n", ret);
583                 goto cleanup;
584         }
585
586         dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd);
587
588         ret = imx_media_of_parse(imxmd, &csi, node);
589         if (ret) {
590                 v4l2_err(&imxmd->v4l2_dev,
591                          "imx_media_of_parse failed with %d\n", ret);
592                 goto unreg_dev;
593         }
594
595         ret = imx_media_add_internal_subdevs(imxmd, csi);
596         if (ret) {
597                 v4l2_err(&imxmd->v4l2_dev,
598                          "add_internal_subdevs failed with %d\n", ret);
599                 goto unreg_dev;
600         }
601
602         /* no subdevs? just bail */
603         imxmd->num_subdevs = imxmd->subdev_notifier.num_subdevs;
604         if (imxmd->num_subdevs == 0) {
605                 ret = -ENODEV;
606                 goto unreg_dev;
607         }
608
609         /* prepare the async subdev notifier and register it */
610         imxmd->subdev_notifier.subdevs = imxmd->async_ptrs;
611         imxmd->subdev_notifier.bound = imx_media_subdev_bound;
612         imxmd->subdev_notifier.complete = imx_media_probe_complete;
613         ret = v4l2_async_notifier_register(&imxmd->v4l2_dev,
614                                            &imxmd->subdev_notifier);
615         if (ret) {
616                 v4l2_err(&imxmd->v4l2_dev,
617                          "v4l2_async_notifier_register failed with %d\n", ret);
618                 goto del_int;
619         }
620
621         return 0;
622
623 del_int:
624         imx_media_remove_internal_subdevs(imxmd);
625 unreg_dev:
626         v4l2_device_unregister(&imxmd->v4l2_dev);
627 cleanup:
628         media_device_cleanup(&imxmd->md);
629         return ret;
630 }
631
632 static int imx_media_remove(struct platform_device *pdev)
633 {
634         struct imx_media_dev *imxmd =
635                 (struct imx_media_dev *)platform_get_drvdata(pdev);
636
637         v4l2_info(&imxmd->v4l2_dev, "Removing imx-media\n");
638
639         v4l2_async_notifier_unregister(&imxmd->subdev_notifier);
640         imx_media_remove_internal_subdevs(imxmd);
641         v4l2_device_unregister(&imxmd->v4l2_dev);
642         media_device_unregister(&imxmd->md);
643         media_device_cleanup(&imxmd->md);
644
645         return 0;
646 }
647
648 static const struct of_device_id imx_media_dt_ids[] = {
649         { .compatible = "fsl,imx-capture-subsystem" },
650         { /* sentinel */ }
651 };
652 MODULE_DEVICE_TABLE(of, imx_media_dt_ids);
653
654 static struct platform_driver imx_media_pdrv = {
655         .probe          = imx_media_probe,
656         .remove         = imx_media_remove,
657         .driver         = {
658                 .name   = "imx-media",
659                 .of_match_table = imx_media_dt_ids,
660         },
661 };
662
663 module_platform_driver(imx_media_pdrv);
664
665 MODULE_DESCRIPTION("i.MX5/6 v4l2 media controller driver");
666 MODULE_AUTHOR("Steve Longerbeam <steve_longerbeam@mentor.com>");
667 MODULE_LICENSE("GPL");