Loading Documentation/devicetree/bindings/sound/simple-card.txt +6 −0 Original line number Original line Diff line number Diff line Loading @@ -43,6 +43,12 @@ Optional CPU/CODEC subnodes properties: clock node (= common clock), or "system-clock-frequency" clock node (= common clock), or "system-clock-frequency" (if system doens't support common clock) (if system doens't support common clock) Note: * For 'format', 'frame-master', 'bitclock-master', 'bitclock-inversion' and 'frame-inversion', the simple card will use the settings of CODEC for both CPU and CODEC sides as we need to keep the settings identical for both ends of the link. Example: Example: sound { sound { Loading sound/soc/codecs/sirf-audio-codec.c +0 −9 Original line number Original line Diff line number Diff line Loading @@ -337,18 +337,9 @@ struct snd_soc_dai_driver sirf_audio_codec_dai = { static int sirf_audio_codec_probe(struct snd_soc_codec *codec) static int sirf_audio_codec_probe(struct snd_soc_codec *codec) { { int ret; struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_dapm_context *dapm = &codec->dapm; struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec); pm_runtime_enable(codec->dev); pm_runtime_enable(codec->dev); codec->control_data = sirf_audio_codec->regmap; ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; } if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) { if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) { snd_soc_dapm_new_controls(dapm, snd_soc_dapm_new_controls(dapm, Loading sound/soc/generic/simple-card.c +56 −24 Original line number Original line Diff line number Diff line Loading @@ -20,7 +20,6 @@ struct simple_card_data { struct simple_card_data { struct snd_soc_card snd_card; struct snd_soc_card snd_card; unsigned int daifmt; struct asoc_simple_dai cpu_dai; struct asoc_simple_dai cpu_dai; struct asoc_simple_dai codec_dai; struct asoc_simple_dai codec_dai; struct snd_soc_dai_link snd_link; struct snd_soc_dai_link snd_link; Loading Loading @@ -105,12 +104,12 @@ asoc_simple_card_sub_parse_of(struct device_node *np, /* get dai->name */ /* get dai->name */ ret = snd_soc_of_get_dai_name(np, name); ret = snd_soc_of_get_dai_name(np, name); if (ret < 0) if (ret < 0) goto parse_error; return ret; /* parse TDM slot */ /* parse TDM slot */ ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); if (ret) if (ret) goto parse_error; return ret; /* /* * bitclock-inversion, frame-inversion * bitclock-inversion, frame-inversion Loading @@ -130,7 +129,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, clk = of_clk_get(np, 0); clk = of_clk_get(np, 0); if (IS_ERR(clk)) { if (IS_ERR(clk)) { ret = PTR_ERR(clk); ret = PTR_ERR(clk); goto parse_error; return ret; } } dai->sysclk = clk_get_rate(clk); dai->sysclk = clk_get_rate(clk); Loading @@ -144,12 +143,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, dai->sysclk = clk_get_rate(clk); dai->sysclk = clk_get_rate(clk); } } ret = 0; return 0; parse_error: of_node_put(node); return ret; } } static int asoc_simple_card_parse_of(struct device_node *node, static int asoc_simple_card_parse_of(struct device_node *node, Loading @@ -157,15 +151,18 @@ static int asoc_simple_card_parse_of(struct device_node *node, struct device *dev) struct device *dev) { { struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; struct asoc_simple_dai *codec_dai = &priv->codec_dai; struct asoc_simple_dai *cpu_dai = &priv->cpu_dai; struct device_node *np; struct device_node *np; char *name; char *name; unsigned int daifmt; int ret; int ret; /* parsing the card name from DT */ /* parsing the card name from DT */ snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); /* get CPU/CODEC common format via simple-audio-card,format */ /* get CPU/CODEC common format via simple-audio-card,format */ priv->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); /* off-codec widgets */ /* off-codec widgets */ Loading @@ -187,25 +184,35 @@ static int asoc_simple_card_parse_of(struct device_node *node, /* CPU sub-node */ /* CPU sub-node */ ret = -EINVAL; ret = -EINVAL; np = of_get_child_by_name(node, "simple-audio-card,cpu"); np = of_get_child_by_name(node, "simple-audio-card,cpu"); if (np) if (np) { ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, ret = asoc_simple_card_sub_parse_of(np, daifmt, &priv->cpu_dai, cpu_dai, &dai_link->cpu_of_node, &dai_link->cpu_of_node, &dai_link->cpu_dai_name); &dai_link->cpu_dai_name); of_node_put(np); } if (ret < 0) if (ret < 0) return ret; return ret; /* CODEC sub-node */ /* CODEC sub-node */ ret = -EINVAL; ret = -EINVAL; np = of_get_child_by_name(node, "simple-audio-card,codec"); np = of_get_child_by_name(node, "simple-audio-card,codec"); if (np) if (np) { ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, ret = asoc_simple_card_sub_parse_of(np, daifmt, &priv->codec_dai, codec_dai, &dai_link->codec_of_node, &dai_link->codec_of_node, &dai_link->codec_dai_name); &dai_link->codec_dai_name); of_node_put(np); } if (ret < 0) if (ret < 0) return ret; return ret; /* * overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC * while the other bits should be identical unless buggy SW/HW design. */ cpu_dai->fmt = codec_dai->fmt; if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) return -EINVAL; return -EINVAL; Loading @@ -224,15 +231,15 @@ static int asoc_simple_card_parse_of(struct device_node *node, dai_link->platform_of_node = dai_link->cpu_of_node; dai_link->platform_of_node = dai_link->cpu_of_node; dev_dbg(dev, "card-name : %s\n", name); dev_dbg(dev, "card-name : %s\n", name); dev_dbg(dev, "platform : %04x\n", priv->daifmt); dev_dbg(dev, "platform : %04x\n", daifmt); dev_dbg(dev, "cpu : %s / %04x / %d\n", dev_dbg(dev, "cpu : %s / %04x / %d\n", dai_link->cpu_dai_name, dai_link->cpu_dai_name, priv->cpu_dai.fmt, cpu_dai->fmt, priv->cpu_dai.sysclk); cpu_dai->sysclk); dev_dbg(dev, "codec : %s / %04x / %d\n", dev_dbg(dev, "codec : %s / %04x / %d\n", dai_link->codec_dai_name, dai_link->codec_dai_name, priv->codec_dai.fmt, codec_dai->fmt, priv->codec_dai.sysclk); codec_dai->sysclk); /* /* * soc_bind_dai_link() will check cpu name * soc_bind_dai_link() will check cpu name Loading @@ -248,6 +255,27 @@ static int asoc_simple_card_parse_of(struct device_node *node, return 0; return 0; } } /* update the reference count of the devices nodes at end of probe */ static int asoc_simple_card_unref(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct snd_soc_dai_link *dai_link; struct device_node *np; int num_links; for (num_links = 0, dai_link = card->dai_link; num_links < card->num_links; num_links++, dai_link++) { np = (struct device_node *) dai_link->cpu_of_node; if (np) of_node_put(np); np = (struct device_node *) dai_link->codec_of_node; if (np) of_node_put(np); } return 0; } static int asoc_simple_card_probe(struct platform_device *pdev) static int asoc_simple_card_probe(struct platform_device *pdev) { { struct simple_card_data *priv; struct simple_card_data *priv; Loading Loading @@ -275,7 +303,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) if (ret < 0) { if (ret < 0) { if (ret != -EPROBE_DEFER) if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret); dev_err(dev, "parse error %d\n", ret); return ret; goto err; } } } else { } else { struct asoc_simple_card_info *cinfo; struct asoc_simple_card_info *cinfo; Loading Loading @@ -318,7 +346,11 @@ static int asoc_simple_card_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(&priv->snd_card, priv); snd_soc_card_set_drvdata(&priv->snd_card, priv); return devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); err: asoc_simple_card_unref(pdev); return ret; } } static const struct of_device_id asoc_simple_of_match[] = { static const struct of_device_id asoc_simple_of_match[] = { Loading Loading
Documentation/devicetree/bindings/sound/simple-card.txt +6 −0 Original line number Original line Diff line number Diff line Loading @@ -43,6 +43,12 @@ Optional CPU/CODEC subnodes properties: clock node (= common clock), or "system-clock-frequency" clock node (= common clock), or "system-clock-frequency" (if system doens't support common clock) (if system doens't support common clock) Note: * For 'format', 'frame-master', 'bitclock-master', 'bitclock-inversion' and 'frame-inversion', the simple card will use the settings of CODEC for both CPU and CODEC sides as we need to keep the settings identical for both ends of the link. Example: Example: sound { sound { Loading
sound/soc/codecs/sirf-audio-codec.c +0 −9 Original line number Original line Diff line number Diff line Loading @@ -337,18 +337,9 @@ struct snd_soc_dai_driver sirf_audio_codec_dai = { static int sirf_audio_codec_probe(struct snd_soc_codec *codec) static int sirf_audio_codec_probe(struct snd_soc_codec *codec) { { int ret; struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_dapm_context *dapm = &codec->dapm; struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec); pm_runtime_enable(codec->dev); pm_runtime_enable(codec->dev); codec->control_data = sirf_audio_codec->regmap; ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; } if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) { if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) { snd_soc_dapm_new_controls(dapm, snd_soc_dapm_new_controls(dapm, Loading
sound/soc/generic/simple-card.c +56 −24 Original line number Original line Diff line number Diff line Loading @@ -20,7 +20,6 @@ struct simple_card_data { struct simple_card_data { struct snd_soc_card snd_card; struct snd_soc_card snd_card; unsigned int daifmt; struct asoc_simple_dai cpu_dai; struct asoc_simple_dai cpu_dai; struct asoc_simple_dai codec_dai; struct asoc_simple_dai codec_dai; struct snd_soc_dai_link snd_link; struct snd_soc_dai_link snd_link; Loading Loading @@ -105,12 +104,12 @@ asoc_simple_card_sub_parse_of(struct device_node *np, /* get dai->name */ /* get dai->name */ ret = snd_soc_of_get_dai_name(np, name); ret = snd_soc_of_get_dai_name(np, name); if (ret < 0) if (ret < 0) goto parse_error; return ret; /* parse TDM slot */ /* parse TDM slot */ ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); if (ret) if (ret) goto parse_error; return ret; /* /* * bitclock-inversion, frame-inversion * bitclock-inversion, frame-inversion Loading @@ -130,7 +129,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, clk = of_clk_get(np, 0); clk = of_clk_get(np, 0); if (IS_ERR(clk)) { if (IS_ERR(clk)) { ret = PTR_ERR(clk); ret = PTR_ERR(clk); goto parse_error; return ret; } } dai->sysclk = clk_get_rate(clk); dai->sysclk = clk_get_rate(clk); Loading @@ -144,12 +143,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, dai->sysclk = clk_get_rate(clk); dai->sysclk = clk_get_rate(clk); } } ret = 0; return 0; parse_error: of_node_put(node); return ret; } } static int asoc_simple_card_parse_of(struct device_node *node, static int asoc_simple_card_parse_of(struct device_node *node, Loading @@ -157,15 +151,18 @@ static int asoc_simple_card_parse_of(struct device_node *node, struct device *dev) struct device *dev) { { struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; struct asoc_simple_dai *codec_dai = &priv->codec_dai; struct asoc_simple_dai *cpu_dai = &priv->cpu_dai; struct device_node *np; struct device_node *np; char *name; char *name; unsigned int daifmt; int ret; int ret; /* parsing the card name from DT */ /* parsing the card name from DT */ snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); /* get CPU/CODEC common format via simple-audio-card,format */ /* get CPU/CODEC common format via simple-audio-card,format */ priv->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); /* off-codec widgets */ /* off-codec widgets */ Loading @@ -187,25 +184,35 @@ static int asoc_simple_card_parse_of(struct device_node *node, /* CPU sub-node */ /* CPU sub-node */ ret = -EINVAL; ret = -EINVAL; np = of_get_child_by_name(node, "simple-audio-card,cpu"); np = of_get_child_by_name(node, "simple-audio-card,cpu"); if (np) if (np) { ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, ret = asoc_simple_card_sub_parse_of(np, daifmt, &priv->cpu_dai, cpu_dai, &dai_link->cpu_of_node, &dai_link->cpu_of_node, &dai_link->cpu_dai_name); &dai_link->cpu_dai_name); of_node_put(np); } if (ret < 0) if (ret < 0) return ret; return ret; /* CODEC sub-node */ /* CODEC sub-node */ ret = -EINVAL; ret = -EINVAL; np = of_get_child_by_name(node, "simple-audio-card,codec"); np = of_get_child_by_name(node, "simple-audio-card,codec"); if (np) if (np) { ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, ret = asoc_simple_card_sub_parse_of(np, daifmt, &priv->codec_dai, codec_dai, &dai_link->codec_of_node, &dai_link->codec_of_node, &dai_link->codec_dai_name); &dai_link->codec_dai_name); of_node_put(np); } if (ret < 0) if (ret < 0) return ret; return ret; /* * overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC * while the other bits should be identical unless buggy SW/HW design. */ cpu_dai->fmt = codec_dai->fmt; if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) return -EINVAL; return -EINVAL; Loading @@ -224,15 +231,15 @@ static int asoc_simple_card_parse_of(struct device_node *node, dai_link->platform_of_node = dai_link->cpu_of_node; dai_link->platform_of_node = dai_link->cpu_of_node; dev_dbg(dev, "card-name : %s\n", name); dev_dbg(dev, "card-name : %s\n", name); dev_dbg(dev, "platform : %04x\n", priv->daifmt); dev_dbg(dev, "platform : %04x\n", daifmt); dev_dbg(dev, "cpu : %s / %04x / %d\n", dev_dbg(dev, "cpu : %s / %04x / %d\n", dai_link->cpu_dai_name, dai_link->cpu_dai_name, priv->cpu_dai.fmt, cpu_dai->fmt, priv->cpu_dai.sysclk); cpu_dai->sysclk); dev_dbg(dev, "codec : %s / %04x / %d\n", dev_dbg(dev, "codec : %s / %04x / %d\n", dai_link->codec_dai_name, dai_link->codec_dai_name, priv->codec_dai.fmt, codec_dai->fmt, priv->codec_dai.sysclk); codec_dai->sysclk); /* /* * soc_bind_dai_link() will check cpu name * soc_bind_dai_link() will check cpu name Loading @@ -248,6 +255,27 @@ static int asoc_simple_card_parse_of(struct device_node *node, return 0; return 0; } } /* update the reference count of the devices nodes at end of probe */ static int asoc_simple_card_unref(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct snd_soc_dai_link *dai_link; struct device_node *np; int num_links; for (num_links = 0, dai_link = card->dai_link; num_links < card->num_links; num_links++, dai_link++) { np = (struct device_node *) dai_link->cpu_of_node; if (np) of_node_put(np); np = (struct device_node *) dai_link->codec_of_node; if (np) of_node_put(np); } return 0; } static int asoc_simple_card_probe(struct platform_device *pdev) static int asoc_simple_card_probe(struct platform_device *pdev) { { struct simple_card_data *priv; struct simple_card_data *priv; Loading Loading @@ -275,7 +303,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) if (ret < 0) { if (ret < 0) { if (ret != -EPROBE_DEFER) if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret); dev_err(dev, "parse error %d\n", ret); return ret; goto err; } } } else { } else { struct asoc_simple_card_info *cinfo; struct asoc_simple_card_info *cinfo; Loading Loading @@ -318,7 +346,11 @@ static int asoc_simple_card_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(&priv->snd_card, priv); snd_soc_card_set_drvdata(&priv->snd_card, priv); return devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); err: asoc_simple_card_unref(pdev); return ret; } } static const struct of_device_id asoc_simple_of_match[] = { static const struct of_device_id asoc_simple_of_match[] = { Loading