|
@@ -22,6 +22,7 @@
|
|
|
#include <linux/component.h>
|
|
|
#include <linux/dma-mapping.h>
|
|
|
#include <linux/of_device.h>
|
|
|
+#include <linux/of_graph.h>
|
|
|
#include <linux/reset.h>
|
|
|
|
|
|
#include "sun4i_drv.h"
|
|
@@ -322,6 +323,42 @@ static struct regmap_config sun8i_mixer_regmap_config = {
|
|
|
.max_register = 0xbfffc, /* guessed */
|
|
|
};
|
|
|
|
|
|
+static int sun8i_mixer_of_get_id(struct device_node *node)
|
|
|
+{
|
|
|
+ struct device_node *port, *ep;
|
|
|
+ int ret = -EINVAL;
|
|
|
+
|
|
|
+ /* output is port 1 */
|
|
|
+ port = of_graph_get_port_by_id(node, 1);
|
|
|
+ if (!port)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ /* try to find downstream endpoint */
|
|
|
+ for_each_available_child_of_node(port, ep) {
|
|
|
+ struct device_node *remote;
|
|
|
+ u32 reg;
|
|
|
+
|
|
|
+ remote = of_graph_get_remote_endpoint(ep);
|
|
|
+ if (!remote)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ ret = of_property_read_u32(remote, "reg", ®);
|
|
|
+ if (!ret) {
|
|
|
+ of_node_put(remote);
|
|
|
+ of_node_put(ep);
|
|
|
+ of_node_put(port);
|
|
|
+
|
|
|
+ return reg;
|
|
|
+ }
|
|
|
+
|
|
|
+ of_node_put(remote);
|
|
|
+ }
|
|
|
+
|
|
|
+ of_node_put(port);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static int sun8i_mixer_bind(struct device *dev, struct device *master,
|
|
|
void *data)
|
|
|
{
|
|
@@ -353,8 +390,16 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
|
|
|
dev_set_drvdata(dev, mixer);
|
|
|
mixer->engine.ops = &sun8i_engine_ops;
|
|
|
mixer->engine.node = dev->of_node;
|
|
|
- /* The ID of the mixer currently doesn't matter */
|
|
|
- mixer->engine.id = -1;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * While this function can fail, we shouldn't do anything
|
|
|
+ * if this happens. Some early DE2 DT entries don't provide
|
|
|
+ * mixer id but work nevertheless because matching between
|
|
|
+ * TCON and mixer is done by comparing node pointers (old
|
|
|
+ * way) instead comparing ids. If this function fails and
|
|
|
+ * id is needed, it will fail during id matching anyway.
|
|
|
+ */
|
|
|
+ mixer->engine.id = sun8i_mixer_of_get_id(dev->of_node);
|
|
|
|
|
|
mixer->cfg = of_device_get_match_data(dev);
|
|
|
if (!mixer->cfg)
|