Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: staging/imx: of: allow for recursing downstream

Calling of_parse_subdev() recursively to a downstream path that has
already been followed is ok, it just means that call will return
immediately since the subdevice was already added to the async list.

With that there is no need to determine whether a subdevice's port
is a sink or source, so 'num_{sink|src}_pads' is no longer used and
is removed.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Steve Longerbeam and committed by
Mauro Carvalho Chehab
f5abe1c5 621b08ea

+21 -88
-17
drivers/staging/media/imx/imx-media-internal-sd.c
··· 78 78 static const struct internal_subdev { 79 79 const struct internal_subdev_id *id; 80 80 struct internal_pad pad[IMX_MEDIA_MAX_PADS]; 81 - int num_sink_pads; 82 - int num_src_pads; 83 81 } int_subdev[num_isd] = { 84 82 [isd_csi0] = { 85 83 .id = &isd_id[isd_csi0], 86 - .num_sink_pads = CSI_NUM_SINK_PADS, 87 - .num_src_pads = CSI_NUM_SRC_PADS, 88 84 .pad[CSI_SRC_PAD_DIRECT] = { 89 85 .link = { 90 86 { ··· 98 102 99 103 [isd_csi1] = { 100 104 .id = &isd_id[isd_csi1], 101 - .num_sink_pads = CSI_NUM_SINK_PADS, 102 - .num_src_pads = CSI_NUM_SRC_PADS, 103 105 .pad[CSI_SRC_PAD_DIRECT] = { 104 106 .link = { 105 107 { ··· 115 121 116 122 [isd_vdic] = { 117 123 .id = &isd_id[isd_vdic], 118 - .num_sink_pads = VDIC_NUM_SINK_PADS, 119 - .num_src_pads = VDIC_NUM_SRC_PADS, 120 124 .pad[VDIC_SRC_PAD_DIRECT] = { 121 125 .link = { 122 126 { ··· 128 136 129 137 [isd_ic_prp] = { 130 138 .id = &isd_id[isd_ic_prp], 131 - .num_sink_pads = PRP_NUM_SINK_PADS, 132 - .num_src_pads = PRP_NUM_SRC_PADS, 133 139 .pad[PRP_SRC_PAD_PRPENC] = { 134 140 .link = { 135 141 { ··· 150 160 151 161 [isd_ic_prpenc] = { 152 162 .id = &isd_id[isd_ic_prpenc], 153 - .num_sink_pads = PRPENCVF_NUM_SINK_PADS, 154 - .num_src_pads = PRPENCVF_NUM_SRC_PADS, 155 163 }, 156 164 157 165 [isd_ic_prpvf] = { 158 166 .id = &isd_id[isd_ic_prpvf], 159 - .num_sink_pads = PRPENCVF_NUM_SINK_PADS, 160 - .num_src_pads = PRPENCVF_NUM_SRC_PADS, 161 167 }, 162 168 }; 163 169 ··· 297 311 imxsd = imx_media_add_async_subdev(imxmd, NULL, pdev); 298 312 if (IS_ERR(imxsd)) 299 313 return PTR_ERR(imxsd); 300 - 301 - imxsd->num_sink_pads = isd->num_sink_pads; 302 - imxsd->num_src_pads = isd->num_src_pads; 303 314 304 315 return 0; 305 316 }
+21 -57
drivers/staging/media/imx/imx-media-of.c
··· 41 41 /* 42 42 * find the remote device node given local endpoint node 43 43 */ 44 - static void of_get_remote(struct device_node *epnode, 44 + static bool of_get_remote(struct device_node *epnode, 45 45 struct device_node **remote_node) 46 46 { 47 47 struct device_node *rp, *rpp; 48 48 struct device_node *remote; 49 + bool is_csi_port; 49 50 50 51 rp = of_graph_get_remote_port(epnode); 51 52 rpp = of_graph_get_remote_port_parent(epnode); ··· 55 54 /* the remote is one of the CSI ports */ 56 55 remote = rp; 57 56 of_node_put(rpp); 57 + is_csi_port = true; 58 58 } else { 59 59 remote = rpp; 60 60 of_node_put(rp); 61 + is_csi_port = false; 61 62 } 62 63 63 64 if (!of_device_is_available(remote)) { ··· 68 65 } else { 69 66 *remote_node = remote; 70 67 } 68 + 69 + return is_csi_port; 71 70 } 72 71 73 72 static int ··· 77 72 bool is_csi_port) 78 73 { 79 74 struct imx_media_subdev *imxsd; 80 - int i, num_pads, ret; 75 + int i, num_ports, ret; 81 76 82 77 if (!of_device_is_available(sd_np)) { 83 78 dev_dbg(imxmd->md.dev, "%s: %s not enabled\n", __func__, ··· 99 94 return ret; 100 95 } 101 96 102 - if (is_csi_port) { 103 - /* 104 - * the ipu-csi has one sink port and two source ports. 105 - * The source ports are not represented in the device tree, 106 - * but are described by the internal pads and links later. 107 - */ 108 - num_pads = CSI_NUM_PADS; 109 - imxsd->num_sink_pads = CSI_NUM_SINK_PADS; 110 - } else if (of_device_is_compatible(sd_np, "fsl,imx6-mipi-csi2")) { 111 - num_pads = of_get_port_count(sd_np); 112 - /* the mipi csi2 receiver has only one sink port */ 113 - imxsd->num_sink_pads = 1; 114 - } else if (of_device_is_compatible(sd_np, "video-mux")) { 115 - num_pads = of_get_port_count(sd_np); 116 - /* for the video mux, all but the last port are sinks */ 117 - imxsd->num_sink_pads = num_pads - 1; 118 - } else { 119 - num_pads = of_get_port_count(sd_np); 120 - if (num_pads != 1) { 121 - /* confused, but no reason to give up here */ 122 - dev_warn(imxmd->md.dev, 123 - "%s: unknown device %s with %d ports\n", 124 - __func__, sd_np->name, num_pads); 125 - return 0; 126 - } 97 + /* 98 + * the ipu-csi has one sink port. The source pads are not 99 + * represented in the device tree by port nodes, but are 100 + * described by the internal pads and links later. 101 + */ 102 + num_ports = is_csi_port ? 1 : of_get_port_count(sd_np); 127 103 128 - /* 129 - * we got to this node from this single source port, 130 - * there are no sink pads. 131 - */ 132 - imxsd->num_sink_pads = 0; 133 - } 134 - 135 - if (imxsd->num_sink_pads >= num_pads) 136 - return -EINVAL; 137 - 138 - imxsd->num_src_pads = num_pads - imxsd->num_sink_pads; 139 - 140 - dev_dbg(imxmd->md.dev, "%s: %s has %d pads (%d sink, %d src)\n", 141 - __func__, sd_np->name, num_pads, 142 - imxsd->num_sink_pads, imxsd->num_src_pads); 143 - 144 - for (i = 0; i < num_pads; i++) { 104 + for (i = 0; i < num_ports; i++) { 145 105 struct device_node *epnode = NULL, *port, *remote_np; 146 106 147 - if (is_csi_port) 148 - port = (i < imxsd->num_sink_pads) ? sd_np : NULL; 149 - else 150 - port = of_graph_get_port_by_id(sd_np, i); 107 + port = is_csi_port ? sd_np : of_graph_get_port_by_id(sd_np, i); 151 108 if (!port) 152 109 continue; 153 110 154 111 for_each_child_of_node(port, epnode) { 155 - of_get_remote(epnode, &remote_np); 112 + bool remote_is_csi; 113 + 114 + remote_is_csi = of_get_remote(epnode, &remote_np); 156 115 if (!remote_np) 157 116 continue; 158 117 159 - if (i < imxsd->num_sink_pads) { 160 - /* follow sink endpoints upstream */ 161 - ret = of_parse_subdev(imxmd, remote_np, false); 162 - if (ret) 163 - break; 164 - } 165 - 118 + ret = of_parse_subdev(imxmd, remote_np, remote_is_csi); 166 119 of_node_put(remote_np); 120 + if (ret) 121 + break; 167 122 } 168 123 169 124 if (port != sd_np) 170 125 of_node_put(port); 171 126 if (ret) { 172 - of_node_put(remote_np); 173 127 of_node_put(epnode); 174 128 break; 175 129 }
-14
drivers/staging/media/imx/imx-media.h
··· 49 49 CSI_NUM_PADS, 50 50 }; 51 51 52 - #define CSI_NUM_SINK_PADS 1 53 - #define CSI_NUM_SRC_PADS 2 54 - 55 52 /* ipu_vdic */ 56 53 enum { 57 54 VDIC_SINK_PAD_DIRECT = 0, ··· 56 59 VDIC_SRC_PAD_DIRECT, 57 60 VDIC_NUM_PADS, 58 61 }; 59 - 60 - #define VDIC_NUM_SINK_PADS 2 61 - #define VDIC_NUM_SRC_PADS 1 62 62 63 63 /* ipu_ic_prp */ 64 64 enum { ··· 65 71 PRP_NUM_PADS, 66 72 }; 67 73 68 - #define PRP_NUM_SINK_PADS 1 69 - #define PRP_NUM_SRC_PADS 2 70 - 71 74 /* ipu_ic_prpencvf */ 72 75 enum { 73 76 PRPENCVF_SINK_PAD = 0, 74 77 PRPENCVF_SRC_PAD, 75 78 PRPENCVF_NUM_PADS, 76 79 }; 77 - 78 - #define PRPENCVF_NUM_SINK_PADS 1 79 - #define PRPENCVF_NUM_SRC_PADS 1 80 80 81 81 /* How long to wait for EOF interrupts in the buffer-capture subdevs */ 82 82 #define IMX_MEDIA_EOF_TIMEOUT 1000 ··· 125 137 struct v4l2_subdev *sd; /* set when bound */ 126 138 127 139 struct imx_media_pad pad[IMX_MEDIA_MAX_PADS]; 128 - int num_sink_pads; 129 - int num_src_pads; 130 140 131 141 /* the platform device if this is an IPU-internal subdev */ 132 142 struct platform_device *pdev;