Hi Sylwester
hdmi: hdmi@20034000 { compatible = "rockchip,rk3036-inno-hdmi"; .. ports { #address-cells = <1>; #size-cells = <0>;
/* video */ hdmi_in: port@0 { reg = <0>; hdmi_in_vop: endpoint { remote-endpoint = <&vop_out_hdmi>; }; }; /* audio */ hdmi_audio_out: port@? { reg = <?>; endpoint { remote-endpoint = <&i2s>; }; };
};
i2s: i2s@10220000 { compatible = "rockchip,rk3036-i2s", "rockchip,rk3066-i2s"; reg = <0x10220000 0x4000>; ... };
Now within individual device bindings the type of the port (audio, video) could be determined by reg property, by assigning specific values for video and audio. But if we wanted to make this more generic we would probably need something like a property determining the port's purpose, e.g.
type = "audio";
Regarding compatible string for the card, how about "soc-sound-card-v1" instead of "asoc-simple-graph-card" ? Or "soc-simple-graph-card"? Appending version now could let us avoid inventing funny names when it turns we need some different binding in future.
It seems you are fighting with this issue which I was fighting :) I guess your issue is related to getting dai_name ? Unfortunately, the idea which adding this "type" property on OF-graph was already rejected by Rob before. He said each driver should know each video/sound port somehow.
So, I'm creating new callback .of_xlate_dai_id on component driver. This callback will exchange reg number to sound dai id. In your case, I think your HDMI sound will be located as reg = <1>; ? If so, your driver can have like below. 1) Your HDMI driver can have .of_xlate_dai_id to exchange reg to sound dai id 2) (If you use simple-graph-card) simple card will call asoc_simple_card_parse_graph_dai() 3) It will try to get dai_id by using .of_xlate_dai_id() first. It will get gai_id simply counting DT ports if driver doesn't have callback. 4) you can get correct dai name
Of course this is not yet accepted/reviewed, but I'm ready to post this patch-set now. It includes both OF-graph simple card, and HDMI sound (= of_xlate_dai_id()) solution. But it is a little bit big volume. Thus, before posting it, I wanted to confirm DT bindings. This mail thread is for it. I'm waiting Rob's reply now
-- on your HDMI driver --
static int xxx_get_dai_id(struct snd_soc_component *component, struct device_node *endpoint) { struct of_endpoint of_ep; int ret;
ret = of_graph_parse_endpoint(endpoint, &of_ep); if (ret < 0) return ret;
/* * HDMI sound should be located as reg = <1> * Then, it is sound port 0 */ if (of_ep.port == 1) return 0;
return -EINVAL; }
--- on soc-core ---
int snd_soc_get_dai_id(struct device_node *ep) { struct snd_soc_component *pos; struct device_node *node; struct device_node *endpoint; int i, id; int ret;
node = of_graph_get_port_parent(ep);
/* * For example HDMI case, HDMI has video/sound port, * but ALSA SoC needs sound port number only. * Thus counting HDMI DT port/endpoint doesn't work. * Then, it should have .of_xlate_dai_id */ ret = -ENOTSUPP; mutex_lock(&client_mutex); list_for_each_entry(pos, &component_list, list) { struct device_node *component_of_node = pos->dev->of_node;
if (!component_of_node && pos->dev->parent) component_of_node = pos->dev->parent->of_node;
if (component_of_node != node) continue;
if (pos->driver->of_xlate_dai_id) ret = pos->driver->of_xlate_dai_id(pos, ep);
break; } mutex_unlock(&client_mutex);
if (ret != -ENOTSUPP) return ret;
/* * Non HDMI sound case, counting port/endpoint on its DT * is enough. Let's count it. */ i = 0; id = -1; for_each_endpoint_of_node(node, endpoint) { if (endpoint == ep) id = i; i++; } if (id < 0) return -ENODEV;
return id; } EXPORT_SYMBOL_GPL(snd_soc_get_dai_id);
--- simple-card-utils ----
int asoc_simple_card_parse_graph_dai(struct device_node *ep, struct device_node **dai_of_node, const char **dai_name) { struct device_node *node; struct of_phandle_args args; int ret;
if (!ep) return 0; if (!dai_name) return 0;
node = of_graph_get_port_parent(ep);
/* Get dai->name */ args.np = node; args.args[0] = snd_soc_get_dai_id(ep); args.args_count = (of_graph_get_endpoint_count(node) > 1);
ret = snd_soc_get_dai_name(&args, dai_name); if (ret < 0) return ret;
*dai_of_node = node;
return 0; } EXPORT_SYMBOL_GPL(asoc_simple_card_parse_graph_dai);
Best regards --- Kuninori Morimoto