The patch adds the initial connector parsing code, so we can move from a
driver specific parsing code to a generic one. Currently only the
generic fields and the analog-connector specific fields are parsed. Parsing
the other connector specific fields can be added by a simple callbacks.

Signed-off-by: Marco Felsch <m.fel...@pengutronix.de>
---
 drivers/media/v4l2-core/v4l2-fwnode.c | 113 ++++++++++++++++++++++++++
 include/media/v4l2-fwnode.h           |  16 ++++
 2 files changed, 129 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c 
b/drivers/media/v4l2-core/v4l2-fwnode.c
index 9bfedd7596a1..56f581e00197 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -592,6 +592,119 @@ void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link)
 }
 EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link);
 
+static const struct v4l2_fwnode_connector_conv {
+       enum v4l2_connector_type type;
+       const char *name;
+} connectors[] = {
+       {
+               .type = V4L2_CON_COMPOSITE,
+               .name = "composite-video-connector",
+       }, {
+               .type = V4L2_CON_SVIDEO,
+               .name = "svideo-connector",
+       }, {
+               .type = V4L2_CON_VGA,
+               .name = "vga-connector",
+       }, {
+               .type = V4L2_CON_DVI,
+               .name = "dvi-connector",
+       }, {
+               .type = V4L2_CON_HDMI,
+               .name = "hdmi-connector"
+       }
+};
+
+static enum v4l2_connector_type
+v4l2_fwnode_string_to_connector_type(const char *con_str)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(connectors); i++)
+               if (!strcmp(con_str, connectors[i].name))
+                       return connectors[i].type;
+
+       /* no valid connector found */
+       return V4L2_CON_UNKNOWN;
+}
+
+static int
+v4l2_fwnode_connector_parse_analog(struct fwnode_handle *fwnode,
+                                  struct v4l2_fwnode_connector *vc)
+{
+       u32 tvnorms;
+       int ret;
+
+       ret = fwnode_property_read_u32(fwnode, "tvnorms", &tvnorms);
+
+       /* set it to V4L2_STD_ALL in case of not specified tvnorms */
+       vc->connector.analog.supported_tvnorms = ret ? V4L2_STD_ALL : tvnorms;
+       return 0;
+}
+
+int v4l2_fwnode_parse_connector(struct fwnode_handle *__fwnode,
+                               struct v4l2_fwnode_connector *connector)
+{
+       struct fwnode_handle *fwnode;
+       struct fwnode_endpoint __ep;
+       const char *c_type_str, *label;
+       int ret;
+
+       memset(connector, 0, sizeof(*connector));
+
+       fwnode = fwnode_graph_get_remote_port_parent(__fwnode);
+
+       /* 1st parse all common properties */
+       /* connector-type is stored within the compatible string */
+       ret = fwnode_property_read_string(fwnode, "compatible", &c_type_str);
+       if (ret)
+               return -EINVAL;
+
+       connector->type = v4l2_fwnode_string_to_connector_type(c_type_str);
+
+       fwnode_graph_parse_endpoint(__fwnode, &__ep);
+       connector->remote_port = __ep.port;
+       connector->remote_id = __ep.id;
+
+       ret = fwnode_property_read_string(fwnode, "label", &label);
+       if (!ret) {
+               /* ensure label doesn't exceed V4L2_CONNECTOR_MAX_LABEL size */
+               strlcpy(connector->label, label, V4L2_CONNECTOR_MAX_LABEL);
+       } else {
+               /*
+                * labels are optional, if no one is given create one:
+                * <connector-type-string>@port<endpoint_port>/ep<endpoint_id>
+                */
+               snprintf(connector->label, V4L2_CONNECTOR_MAX_LABEL,
+                        "%s@port%u/ep%u", c_type_str, connector->remote_port,
+                        connector->remote_id);
+       }
+
+       /* now parse the connector specific properties */
+       switch (connector->type) {
+               /* fall through */
+       case V4L2_CON_COMPOSITE:
+       case V4L2_CON_SVIDEO:
+               ret = v4l2_fwnode_connector_parse_analog(fwnode, connector);
+               break;
+               /* fall through */
+       case V4L2_CON_VGA:
+       case V4L2_CON_DVI:
+       case V4L2_CON_HDMI:
+               pr_warn("Connector specific parsing is currently not supported 
for %s\n",
+                       c_type_str);
+               ret = 0;
+               break;
+               /* fall through */
+       case V4L2_CON_UNKNOWN:
+       default:
+               pr_err("Unknown connector type\n");
+               ret = -EINVAL;
+       };
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_fwnode_parse_connector);
+
 static int
 v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev,
                                          struct v4l2_async_notifier *notifier,
diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
index cf87e819800f..c00cb346b5eb 100644
--- a/include/media/v4l2-fwnode.h
+++ b/include/media/v4l2-fwnode.h
@@ -269,6 +269,22 @@ int v4l2_fwnode_parse_link(struct fwnode_handle *fwnode,
  */
 void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link);
 
+/**
+ * v4l2_fwnode_parse_connector() - parse the connector on endpoint
+ * @fwnode: pointer to the endpoint's fwnode handle where the connector is
+ *          connected to.
+ * @connector: pointer to the V4L2 fwnode connector data structure
+ *
+ * Fill the connector data structure with the connector type, label and the
+ * endpoint id and port where the connector belongs to. If no label is present
+ * a unique one will be created. Labels with more than 40 characters are cut.
+ *
+ * Return: %0 on success or a negative error code on failure:
+ *        %-EINVAL on parsing failure
+ */
+int v4l2_fwnode_parse_connector(struct fwnode_handle *fwnode,
+                               struct v4l2_fwnode_connector *connector);
+
 /**
  * typedef parse_endpoint_func - Driver's callback function to be called on
  *     each V4L2 fwnode endpoint.
-- 
2.20.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to