1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Media driver for Freescale i.MX5/6 SOC 4 * 5 * Open Firmware parsing. 6 * 7 * Copyright (c) 2016 Mentor Graphics Inc. 8 */ 9 #include <linux/of_platform.h> 10 #include <media/v4l2-ctrls.h> 11 #include <media/v4l2-device.h> 12 #include <media/v4l2-fwnode.h> 13 #include <media/v4l2-subdev.h> 14 #include <media/videobuf2-dma-contig.h> 15 #include <linux/of_graph.h> 16 #include <video/imx-ipu-v3.h> 17 #include "imx-media.h" 18 19 int imx_media_of_add_csi(struct imx_media_dev *imxmd, 20 struct device_node *csi_np) 21 { 22 struct v4l2_async_subdev *asd; 23 int ret = 0; 24 25 if (!of_device_is_available(csi_np)) { 26 dev_dbg(imxmd->md.dev, "%s: %pOFn not enabled\n", __func__, 27 csi_np); 28 return -ENODEV; 29 } 30 31 /* add CSI fwnode to async notifier */ 32 asd = v4l2_async_notifier_add_fwnode_subdev(&imxmd->notifier, 33 of_fwnode_handle(csi_np), 34 sizeof(*asd)); 35 if (IS_ERR(asd)) { 36 ret = PTR_ERR(asd); 37 if (ret == -EEXIST) 38 dev_dbg(imxmd->md.dev, "%s: already added %pOFn\n", 39 __func__, csi_np); 40 } 41 42 return ret; 43 } 44 EXPORT_SYMBOL_GPL(imx_media_of_add_csi); 45 46 int imx_media_add_of_subdevs(struct imx_media_dev *imxmd, 47 struct device_node *np) 48 { 49 struct device_node *csi_np; 50 int i, ret; 51 52 for (i = 0; ; i++) { 53 csi_np = of_parse_phandle(np, "ports", i); 54 if (!csi_np) 55 break; 56 57 ret = imx_media_of_add_csi(imxmd, csi_np); 58 if (ret) { 59 /* unavailable or already added is not an error */ 60 if (ret == -ENODEV || ret == -EEXIST) { 61 of_node_put(csi_np); 62 continue; 63 } 64 65 /* other error, can't continue */ 66 goto err_out; 67 } 68 } 69 70 return 0; 71 72 err_out: 73 of_node_put(csi_np); 74 return ret; 75 } 76 EXPORT_SYMBOL_GPL(imx_media_add_of_subdevs); 77