^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // ASoC simple sound card support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright (C) 2012 Renesas Solutions Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sound/simple_card.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <sound/soc-dai.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define DPCM_SELECTABLE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define DAI "sound-dai"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define CELL "#sound-dai-cells"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PREFIX "simple-audio-card,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static const struct snd_soc_ops simple_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) .startup = asoc_simple_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) .shutdown = asoc_simple_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) .hw_params = asoc_simple_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int asoc_simple_parse_dai(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct snd_soc_dai_link_component *dlc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int *is_single_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct of_phandle_args args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (!node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * Get node via "sound-dai = <&phandle port>"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * it will be used as xxx_of_node on soc_bind_dai_link()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * FIXME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * Here, dlc->dai_name is pointer to CPU/Codec DAI name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * If user unbinded CPU or Codec driver, but not for Sound Card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * dlc->dai_name is keeping unbinded CPU or Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * driver's pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * If user re-bind CPU or Codec driver again, ALSA SoC will try
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * to rebind Card via snd_soc_try_rebind_card(), but because of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * above reason, it might can't bind Sound Card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * Because Sound Card is pointing to released dai_name pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * To avoid this rebind Card issue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * 1) It needs to alloc memory to keep dai_name eventhough
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * CPU or Codec driver was unbinded, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * 2) user need to rebind Sound Card everytime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * if he unbinded CPU or Codec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ret = snd_soc_of_get_dai_name(node, &dlc->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) dlc->of_node = args.np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (is_single_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) *is_single_link = !args.args_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static void simple_parse_convert(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct asoc_simple_data *adata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct device_node *top = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct device_node *node = of_get_parent(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) asoc_simple_parse_convert(dev, top, PREFIX, adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) asoc_simple_parse_convert(dev, node, PREFIX, adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) asoc_simple_parse_convert(dev, node, NULL, adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) asoc_simple_parse_convert(dev, np, NULL, adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static void simple_parse_mclk_fs(struct device_node *top,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct device_node *cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct device_node *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct simple_dai_props *props,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct device_node *node = of_get_parent(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) char prop[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) snprintf(prop, sizeof(prop), "%smclk-fs", PREFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) of_property_read_u32(top, prop, &props->mclk_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) snprintf(prop, sizeof(prop), "%smclk-fs", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) of_property_read_u32(node, prop, &props->mclk_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) of_property_read_u32(cpu, prop, &props->mclk_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) of_property_read_u32(codec, prop, &props->mclk_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct device_node *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct link_info *li,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) bool is_top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct device *dev = simple_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct asoc_simple_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct snd_soc_dai_link_component *cpus = dai_link->cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct snd_soc_dai_link_component *codecs = dai_link->codecs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct device_node *top = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct device_node *node = of_get_parent(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) char *prefix = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * |CPU |Codec : turn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * CPU |Pass |return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * Codec |return|Pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * np
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (li->cpu == (np == codec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) dev_dbg(dev, "link_of DPCM (%pOF)\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) li->link++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* For single DAI link & old style of DT node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (is_top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) prefix = PREFIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (li->cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int is_single_links = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* Codec is dummy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) codecs->of_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) codecs->dai_name = "snd-soc-dummy-dai";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) codecs->name = "snd-soc-dummy";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* FE settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) dai_link->dynamic = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) dai_link->dpcm_merged_format = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) dai =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) dai_props->cpu_dai = &priv->dais[li->dais++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ret = asoc_simple_parse_cpu(np, dai_link, &is_single_links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ret = asoc_simple_parse_clk_cpu(dev, np, dai_link, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ret = asoc_simple_set_dailink_name(dev, dai_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) "fe.%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) cpus->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) asoc_simple_canonicalize_cpu(dai_link, is_single_links);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct snd_soc_codec_conf *cconf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* CPU is dummy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) cpus->of_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) cpus->dai_name = "snd-soc-dummy-dai";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) cpus->name = "snd-soc-dummy";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /* BE settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dai_link->no_pcm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) dai =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) dai_props->codec_dai = &priv->dais[li->dais++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) cconf =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) dai_props->codec_conf = &priv->codec_conf[li->conf++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) ret = asoc_simple_parse_codec(np, dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ret = asoc_simple_parse_clk_codec(dev, np, dai_link, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ret = asoc_simple_set_dailink_name(dev, dai_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) "be.%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) codecs->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* check "prefix" from top node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) PREFIX "prefix");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) snd_soc_of_parse_node_prefix(node, cconf, codecs->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) "prefix");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) snd_soc_of_parse_node_prefix(np, cconf, codecs->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) "prefix");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) simple_parse_convert(dev, np, &dai_props->adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) simple_parse_mclk_fs(top, np, codec, dai_props, prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) asoc_simple_canonicalize_platform(dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ret = asoc_simple_parse_tdm(np, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ret = asoc_simple_parse_daifmt(dev, node, codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) prefix, &dai_link->dai_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) snd_soc_dai_link_set_capabilities(dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) dai_link->ops = &simple_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) dai_link->init = asoc_simple_dai_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) out_put_node:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static int simple_dai_link_of(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct device_node *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct link_info *li,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) bool is_top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct device *dev = simple_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct asoc_simple_dai *cpu_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct asoc_simple_dai *codec_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct device_node *top = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct device_node *cpu = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct device_node *node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct device_node *plat = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) char prop[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) char *prefix = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) int ret, single_cpu = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * |CPU |Codec : turn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * CPU |Pass |return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * Codec |return|return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * np
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (!li->cpu || np == codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) cpu = np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) node = of_get_parent(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) li->link++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dev_dbg(dev, "link_of (%pOF)\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* For single DAI link & old style of DT node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (is_top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) prefix = PREFIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) snprintf(prop, sizeof(prop), "%splat", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) plat = of_get_child_by_name(node, prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) cpu_dai =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) dai_props->cpu_dai = &priv->dais[li->dais++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) codec_dai =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) dai_props->codec_dai = &priv->dais[li->dais++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ret = asoc_simple_parse_daifmt(dev, node, codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) prefix, &dai_link->dai_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) goto dai_link_of_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ret = asoc_simple_parse_cpu(cpu, dai_link, &single_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) goto dai_link_of_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) ret = asoc_simple_parse_codec(codec, dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) goto dai_link_of_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ret = asoc_simple_parse_platform(plat, dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) goto dai_link_of_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) ret = asoc_simple_parse_tdm(cpu, cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) goto dai_link_of_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ret = asoc_simple_parse_tdm(codec, codec_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) goto dai_link_of_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ret = asoc_simple_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) goto dai_link_of_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ret = asoc_simple_parse_clk_codec(dev, codec, dai_link, codec_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) goto dai_link_of_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ret = asoc_simple_set_dailink_name(dev, dai_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) "%s-%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) dai_link->cpus->dai_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) dai_link->codecs->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) goto dai_link_of_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) dai_link->ops = &simple_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) dai_link->init = asoc_simple_dai_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) asoc_simple_canonicalize_cpu(dai_link, single_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) asoc_simple_canonicalize_platform(dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) dai_link_of_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) of_node_put(plat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static int simple_for_each_link(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct link_info *li,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) int (*func_noml)(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct device_node *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct link_info *li, bool is_top),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) int (*func_dpcm)(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct device_node *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct link_info *li, bool is_top))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct device *dev = simple_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct device_node *top = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct device_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) bool is_top = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* Check if it has dai-link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) node = of_get_child_by_name(top, PREFIX "dai-link");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (!node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) node = of_node_get(top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) is_top = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* loop for all dai-link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct asoc_simple_data adata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) struct device_node *codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct device_node *plat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) int num = of_get_child_count(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* get codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) codec = of_get_child_by_name(node, is_top ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) PREFIX "codec" : "codec");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (!codec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /* get platform */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) plat = of_get_child_by_name(node, is_top ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) PREFIX "plat" : "plat");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* get convert-xxx property */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) memset(&adata, 0, sizeof(adata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) for_each_child_of_node(node, np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) simple_parse_convert(dev, np, &adata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* loop for all CPU/Codec node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) for_each_child_of_node(node, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (plat == np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * It is DPCM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * if it has many CPUs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * or has convert-xxx property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (dpcm_selectable &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) (num > 2 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) adata.convert_rate || adata.convert_channels))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) ret = func_dpcm(priv, np, codec, li, is_top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /* else normal sound */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) ret = func_noml(priv, np, codec, li, is_top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) of_node_put(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) of_node_put(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) node = of_get_next_child(top, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) } while (!is_top && node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static int simple_parse_of(struct asoc_simple_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct device *dev = simple_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct device_node *top = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) struct snd_soc_card *card = simple_priv_to_card(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct link_info li;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (!top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ret = asoc_simple_parse_widgets(card, PREFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ret = asoc_simple_parse_routing(card, PREFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ret = asoc_simple_parse_pin_switches(card, PREFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /* Single/Muti DAI link(s) & New style of DT node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) memset(&li, 0, sizeof(li));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) for (li.cpu = 1; li.cpu >= 0; li.cpu--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * Detect all CPU first, and Detect all Codec 2nd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * In Normal sound case, all DAIs are detected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * as "CPU-Codec".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * In DPCM sound case,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * all CPUs are detected as "CPU-dummy", and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * all Codecs are detected as "dummy-Codec".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * To avoid random sub-device numbering,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * detect "dummy-Codec" in last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) ret = simple_for_each_link(priv, &li,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) simple_dai_link_of,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) simple_dai_link_of_dpcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) ret = asoc_simple_parse_card_name(card, PREFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static int simple_count_noml(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct device_node *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct link_info *li, bool is_top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) li->dais++; /* CPU or Codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (np != codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) li->link++; /* CPU-Codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static int simple_count_dpcm(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct device_node *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct link_info *li, bool is_top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) li->dais++; /* CPU or Codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) li->link++; /* CPU-dummy or dummy-Codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (np == codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) li->conf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static void simple_get_dais_count(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) struct link_info *li)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct device *dev = simple_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) struct device_node *top = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * link_num : number of links.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * CPU-Codec / CPU-dummy / dummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * dais_num : number of DAIs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * ccnf_num : number of codec_conf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * same number for "dummy-Codec"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * ex1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * CPU0 --- Codec0 link : 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * CPU1 --- Codec1 dais : 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * CPU2 -/ ccnf : 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * CPU3 --- Codec2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * => 5 links = 2xCPU-Codec + 2xCPU-dummy + 1xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * => 7 DAIs = 4xCPU + 3xCodec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * => 1 ccnf = 1xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * ex2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * CPU0 --- Codec0 link : 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * CPU1 --- Codec1 dais : 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * CPU2 -/ ccnf : 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * CPU3 -/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * => 5 links = 1xCPU-Codec + 3xCPU-dummy + 1xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * => 6 DAIs = 4xCPU + 2xCodec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * => 1 ccnf = 1xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * ex3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * CPU0 --- Codec0 link : 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * CPU1 -/ dais : 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) * CPU2 --- Codec1 ccnf : 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * CPU3 -/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * => 6 links = 0xCPU-Codec + 4xCPU-dummy + 2xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * => 6 DAIs = 4xCPU + 2xCodec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * => 2 ccnf = 2xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * ex4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * CPU0 --- Codec0 (convert-rate) link : 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * CPU1 --- Codec1 dais : 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * ccnf : 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * => 3 links = 1xCPU-Codec + 1xCPU-dummy + 1xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * => 4 DAIs = 2xCPU + 2xCodec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * => 1 ccnf = 1xdummy-Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (!top) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) li->link = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) li->dais = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) li->conf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) simple_for_each_link(priv, li,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) simple_count_noml,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) simple_count_dpcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) dev_dbg(dev, "link %d, dais %d, ccnf %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) li->link, li->dais, li->conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static int simple_soc_probe(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) ret = asoc_simple_init_hp(card, &priv->hp_jack, PREFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) ret = asoc_simple_init_mic(card, &priv->mic_jack, PREFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) static int asoc_simple_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) struct asoc_simple_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct snd_soc_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct link_info li;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /* Allocate the private data and the DAI link array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) card = simple_priv_to_card(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) card->owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) card->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) card->probe = simple_soc_probe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) memset(&li, 0, sizeof(li));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) simple_get_dais_count(priv, &li);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (!li.link || !li.dais)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) ret = asoc_simple_init_priv(priv, &li);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (np && of_device_is_available(np)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) ret = simple_parse_of(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) dev_err(dev, "parse error %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) struct asoc_simple_card_info *cinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) struct snd_soc_dai_link_component *cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct snd_soc_dai_link_component *codecs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) struct snd_soc_dai_link_component *platform;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) struct snd_soc_dai_link *dai_link = priv->dai_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct simple_dai_props *dai_props = priv->dai_props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) int dai_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) cinfo = dev->platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (!cinfo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) dev_err(dev, "no info for asoc-simple-card\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (!cinfo->name ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) !cinfo->codec_dai.name ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) !cinfo->codec ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) !cinfo->platform ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) !cinfo->cpu_dai.name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) dev_err(dev, "insufficient asoc_simple_card_info settings\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) dai_props->cpu_dai = &priv->dais[dai_idx++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) dai_props->codec_dai = &priv->dais[dai_idx++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) cpus = dai_link->cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) cpus->dai_name = cinfo->cpu_dai.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) codecs = dai_link->codecs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) codecs->name = cinfo->codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) codecs->dai_name = cinfo->codec_dai.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) platform = dai_link->platforms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) platform->name = cinfo->platform;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) card->name = (cinfo->card) ? cinfo->card : cinfo->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) dai_link->name = cinfo->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) dai_link->stream_name = cinfo->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) dai_link->dai_fmt = cinfo->daifmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) dai_link->init = asoc_simple_dai_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) memcpy(dai_props->cpu_dai, &cinfo->cpu_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) sizeof(*dai_props->cpu_dai));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) memcpy(dai_props->codec_dai, &cinfo->codec_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) sizeof(*dai_props->codec_dai));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) snd_soc_card_set_drvdata(card, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) asoc_simple_debug_info(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) ret = devm_snd_soc_register_card(dev, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) asoc_simple_clean_reference(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) static int asoc_simple_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) struct snd_soc_card *card = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return asoc_simple_clean_reference(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) static const struct of_device_id simple_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) { .compatible = "simple-audio-card", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) { .compatible = "simple-scu-audio-card",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) .data = (void *)DPCM_SELECTABLE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) MODULE_DEVICE_TABLE(of, simple_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) static struct platform_driver asoc_simple_card = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) .name = "asoc-simple-card",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) .pm = &snd_soc_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) .of_match_table = simple_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) .probe = asoc_simple_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) .remove = asoc_simple_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) module_platform_driver(asoc_simple_card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) MODULE_ALIAS("platform:asoc-simple-card");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) MODULE_DESCRIPTION("ASoC Simple Sound Card");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");