Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge remote-tracking branch 'asoc/topic/dt' into asoc-next

+221 -6
+68
Documentation/devicetree/bindings/sound/simple-card.txt
··· 1 + Simple-Card: 2 + 3 + Simple-Card specifies audio DAI connection of SoC <-> codec. 4 + 5 + Required properties: 6 + 7 + - compatible : "simple-audio-card" 8 + 9 + Optional properties: 10 + 11 + - simple-audio-card,format : CPU/CODEC common audio format. 12 + "i2s", "right_j", "left_j" , "dsp_a" 13 + "dsp_b", "ac97", "pdm", "msb", "lsb" 14 + Required subnodes: 15 + 16 + - simple-audio-card,cpu : CPU sub-node 17 + - simple-audio-card,codec : CODEC sub-node 18 + 19 + Required CPU/CODEC subnodes properties: 20 + 21 + - sound-dai : phandle and port of CPU/CODEC 22 + 23 + Optional CPU/CODEC subnodes properties: 24 + 25 + - format : CPU/CODEC specific audio format if needed. 26 + see simple-audio-card,format 27 + - frame-master : bool property. add this if subnode is frame master 28 + - bitclock-master : bool property. add this if subnode is bitclock master 29 + - bitclock-inversion : bool property. add this if subnode has clock inversion 30 + - frame-inversion : bool property. add this if subnode has frame inversion 31 + - clocks / system-clock-frequency : specify subnode's clock if needed. 32 + it can be specified via "clocks" if system has 33 + clock node (= common clock), or "system-clock-frequency" 34 + (if system doens't support common clock) 35 + 36 + Example: 37 + 38 + sound { 39 + compatible = "simple-audio-card"; 40 + simple-audio-card,format = "left_j"; 41 + 42 + simple-audio-card,cpu { 43 + sound-dai = <&sh_fsi2 0>; 44 + }; 45 + 46 + simple-audio-card,codec { 47 + sound-dai = <&ak4648>; 48 + bitclock-master; 49 + frame-master; 50 + clocks = <&osc>; 51 + }; 52 + }; 53 + 54 + &i2c0 { 55 + ak4648: ak4648@12 { 56 + #sound-dai-cells = <0>; 57 + compatible = "asahi-kasei,ak4648"; 58 + reg = <0x12>; 59 + }; 60 + }; 61 + 62 + sh_fsi2: sh_fsi2@ec230000 { 63 + #sound-dai-cells = <1>; 64 + compatible = "renesas,sh_fsi2"; 65 + reg = <0xec230000 0x400>; 66 + interrupt-parent = <&gic>; 67 + interrupts = <0 146 0x4>; 68 + };
+153 -6
sound/soc/generic/simple-card.c
··· 8 8 * it under the terms of the GNU General Public License version 2 as 9 9 * published by the Free Software Foundation. 10 10 */ 11 - 11 + #include <linux/clk.h> 12 + #include <linux/of.h> 12 13 #include <linux/platform_device.h> 13 14 #include <linux/module.h> 14 15 #include <sound/simple_card.h> ··· 58 57 return 0; 59 58 } 60 59 60 + static int 61 + asoc_simple_card_sub_parse_of(struct device_node *np, 62 + struct asoc_simple_dai *dai, 63 + struct device_node **node) 64 + { 65 + struct clk *clk; 66 + int ret; 67 + 68 + /* 69 + * get node via "sound-dai = <&phandle port>" 70 + * it will be used as xxx_of_node on soc_bind_dai_link() 71 + */ 72 + *node = of_parse_phandle(np, "sound-dai", 0); 73 + if (!*node) 74 + return -ENODEV; 75 + 76 + /* get dai->name */ 77 + ret = snd_soc_of_get_dai_name(np, &dai->name); 78 + if (ret < 0) 79 + goto parse_error; 80 + 81 + /* 82 + * bitclock-inversion, frame-inversion 83 + * bitclock-master, frame-master 84 + * and specific "format" if it has 85 + */ 86 + dai->fmt = snd_soc_of_parse_daifmt(np, NULL); 87 + 88 + /* 89 + * dai->sysclk come from 90 + * "clocks = <&xxx>" (if system has common clock) 91 + * or "system-clock-frequency = <xxx>" 92 + */ 93 + clk = of_clk_get(np, 0); 94 + if (IS_ERR(clk)) 95 + of_property_read_u32(np, 96 + "system-clock-frequency", 97 + &dai->sysclk); 98 + else 99 + dai->sysclk = clk_get_rate(clk); 100 + 101 + ret = 0; 102 + 103 + parse_error: 104 + of_node_put(*node); 105 + 106 + return ret; 107 + } 108 + 109 + static int asoc_simple_card_parse_of(struct device_node *node, 110 + struct asoc_simple_card_info *info, 111 + struct device *dev, 112 + struct device_node **of_cpu, 113 + struct device_node **of_codec, 114 + struct device_node **of_platform) 115 + { 116 + struct device_node *np; 117 + char *name; 118 + int ret = 0; 119 + 120 + /* get CPU/CODEC common format via simple-audio-card,format */ 121 + info->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & 122 + (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); 123 + 124 + /* CPU sub-node */ 125 + ret = -EINVAL; 126 + np = of_get_child_by_name(node, "simple-audio-card,cpu"); 127 + if (np) 128 + ret = asoc_simple_card_sub_parse_of(np, 129 + &info->cpu_dai, 130 + of_cpu); 131 + if (ret < 0) 132 + return ret; 133 + 134 + /* CODEC sub-node */ 135 + ret = -EINVAL; 136 + np = of_get_child_by_name(node, "simple-audio-card,codec"); 137 + if (np) 138 + ret = asoc_simple_card_sub_parse_of(np, 139 + &info->codec_dai, 140 + of_codec); 141 + if (ret < 0) 142 + return ret; 143 + 144 + if (!info->cpu_dai.name || !info->codec_dai.name) 145 + return -EINVAL; 146 + 147 + /* card name is created from CPU/CODEC dai name */ 148 + name = devm_kzalloc(dev, 149 + strlen(info->cpu_dai.name) + 150 + strlen(info->codec_dai.name) + 2, 151 + GFP_KERNEL); 152 + sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name); 153 + info->name = info->card = name; 154 + 155 + /* simple-card assumes platform == cpu */ 156 + *of_platform = *of_cpu; 157 + 158 + dev_dbg(dev, "card-name : %s\n", info->card); 159 + dev_dbg(dev, "platform : %04x\n", info->daifmt); 160 + dev_dbg(dev, "cpu : %s / %04x / %d\n", 161 + info->cpu_dai.name, 162 + info->cpu_dai.fmt, 163 + info->cpu_dai.sysclk); 164 + dev_dbg(dev, "codec : %s / %04x / %d\n", 165 + info->codec_dai.name, 166 + info->codec_dai.fmt, 167 + info->codec_dai.sysclk); 168 + 169 + return 0; 170 + } 171 + 61 172 static int asoc_simple_card_probe(struct platform_device *pdev) 62 173 { 63 - struct asoc_simple_card_info *cinfo = pdev->dev.platform_data; 174 + struct asoc_simple_card_info *cinfo; 175 + struct device_node *np = pdev->dev.of_node; 176 + struct device_node *of_cpu, *of_codec, *of_platform; 64 177 struct device *dev = &pdev->dev; 178 + 179 + cinfo = NULL; 180 + of_cpu = NULL; 181 + of_codec = NULL; 182 + of_platform = NULL; 183 + if (np && of_device_is_available(np)) { 184 + cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL); 185 + if (cinfo) { 186 + int ret; 187 + ret = asoc_simple_card_parse_of(np, cinfo, dev, 188 + &of_cpu, 189 + &of_codec, 190 + &of_platform); 191 + if (ret < 0) { 192 + if (ret != -EPROBE_DEFER) 193 + dev_err(dev, "parse error %d\n", ret); 194 + return ret; 195 + } 196 + } 197 + } else { 198 + cinfo = pdev->dev.platform_data; 199 + } 65 200 66 201 if (!cinfo) { 67 202 dev_err(dev, "no info for asoc-simple-card\n"); ··· 206 69 207 70 if (!cinfo->name || 208 71 !cinfo->card || 209 - !cinfo->codec || 210 - !cinfo->platform || 211 - !cinfo->cpu_dai.name || 212 - !cinfo->codec_dai.name) { 72 + !cinfo->codec_dai.name || 73 + !(cinfo->codec || of_codec) || 74 + !(cinfo->platform || of_platform) || 75 + !(cinfo->cpu_dai.name || of_cpu)) { 213 76 dev_err(dev, "insufficient asoc_simple_card_info settings\n"); 214 77 return -EINVAL; 215 78 } ··· 223 86 cinfo->snd_link.platform_name = cinfo->platform; 224 87 cinfo->snd_link.codec_name = cinfo->codec; 225 88 cinfo->snd_link.codec_dai_name = cinfo->codec_dai.name; 89 + cinfo->snd_link.cpu_of_node = of_cpu; 90 + cinfo->snd_link.codec_of_node = of_codec; 91 + cinfo->snd_link.platform_of_node = of_platform; 226 92 cinfo->snd_link.init = asoc_simple_card_dai_init; 227 93 228 94 /* ··· 247 107 return snd_soc_unregister_card(&cinfo->snd_card); 248 108 } 249 109 110 + static const struct of_device_id asoc_simple_of_match[] = { 111 + { .compatible = "simple-audio-card", }, 112 + {}, 113 + }; 114 + MODULE_DEVICE_TABLE(of, asoc_simple_of_match); 115 + 250 116 static struct platform_driver asoc_simple_card = { 251 117 .driver = { 252 118 .name = "asoc-simple-card", 253 119 .owner = THIS_MODULE, 120 + .of_match_table = asoc_simple_of_match, 254 121 }, 255 122 .probe = asoc_simple_card_probe, 256 123 .remove = asoc_simple_card_remove,