Example #1
0
static void sun4i_drv_traverse_endpoints(struct endpoint_list *list,
					 struct device_node *node,
					 int port_id)
{
	struct device_node *ep, *remote, *port;

	port = of_graph_get_port_by_id(node, port_id);
	if (!port) {
		DRM_DEBUG_DRIVER("No output to bind on port %d\n", port_id);
		return;
	}

	for_each_available_child_of_node(port, ep) {
		remote = of_graph_get_remote_port_parent(ep);
		if (!remote) {
			DRM_DEBUG_DRIVER("Error retrieving the output node\n");
			continue;
		}

		if (sun4i_drv_node_is_tcon(node)) {
			/*
			 * TCON TOP is always probed before TCON. However, TCON
			 * points back to TCON TOP when it is source for HDMI.
			 * We have to skip it here to prevent infinite looping
			 * between TCON TOP and TCON.
			 */
			if (sun4i_drv_node_is_tcon_top(remote)) {
				DRM_DEBUG_DRIVER("TCON output endpoint is TCON TOP... skipping\n");
				of_node_put(remote);
				continue;
			}

			/*
			 * If the node is our TCON with channel 0, the first
			 * port is used for panel or bridges, and will not be
			 * part of the component framework.
			 */
			if (sun4i_drv_node_is_tcon_with_ch0(node)) {
				struct of_endpoint endpoint;

				if (of_graph_parse_endpoint(ep, &endpoint)) {
					DRM_DEBUG_DRIVER("Couldn't parse endpoint\n");
					of_node_put(remote);
					continue;
				}

				if (!endpoint.id) {
					DRM_DEBUG_DRIVER("Endpoint is our panel... skipping\n");
					of_node_put(remote);
					continue;
				}
			}
		}

		kfifo_put(&list->fifo, remote);
	}
Example #2
0
static int sun4i_drv_add_endpoints(struct device *dev,
				   struct component_match **match,
				   struct device_node *node)
{
	struct device_node *port, *ep, *remote;
	int count = 0;

	/*
	 * We don't support the frontend for now, so we will never
	 * have a device bound. Just skip over it, but we still want
	 * the rest our pipeline to be added.
	 */
	if (!sun4i_drv_node_is_frontend(node) &&
	    !of_device_is_available(node))
		return 0;

	if (!sun4i_drv_node_is_frontend(node)) {
		/* Add current component */
		DRM_DEBUG_DRIVER("Adding component %s\n",
				 of_node_full_name(node));
		drm_of_component_match_add(dev, match, compare_of, node);
		count++;
	}

	/* Inputs are listed first, then outputs */
	port = of_graph_get_port_by_id(node, 1);
	if (!port) {
		DRM_DEBUG_DRIVER("No output to bind\n");
		return count;
	}

	for_each_available_child_of_node(port, ep) {
		remote = of_graph_get_remote_port_parent(ep);
		if (!remote) {
			DRM_DEBUG_DRIVER("Error retrieving the output node\n");
			of_node_put(remote);
			continue;
		}

		/*
		 * If the node is our TCON, the first port is used for
		 * panel or bridges, and will not be part of the
		 * component framework.
		 */
		if (sun4i_drv_node_is_tcon(node)) {
			struct of_endpoint endpoint;

			if (of_graph_parse_endpoint(ep, &endpoint)) {
				DRM_DEBUG_DRIVER("Couldn't parse endpoint\n");
				continue;
			}

			if (!endpoint.id) {
				DRM_DEBUG_DRIVER("Endpoint is our panel... skipping\n");
				continue;
			}
		}

		/* Walk down our tree */
		count += sun4i_drv_add_endpoints(dev, match, remote);

		of_node_put(remote);
	}