.. | .. |
---|
102 | 102 | #include "rsnd.h" |
---|
103 | 103 | |
---|
104 | 104 | #define RSND_RATES SNDRV_PCM_RATE_8000_192000 |
---|
105 | | -#define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) |
---|
| 105 | +#define RSND_FMTS (SNDRV_PCM_FMTBIT_S8 |\ |
---|
| 106 | + SNDRV_PCM_FMTBIT_S16_LE |\ |
---|
| 107 | + SNDRV_PCM_FMTBIT_S24_LE) |
---|
106 | 108 | |
---|
107 | 109 | static const struct of_device_id rsnd_of_match[] = { |
---|
108 | 110 | { .compatible = "renesas,rcar_sound-gen1", .data = (void *)RSND_GEN1 }, |
---|
109 | 111 | { .compatible = "renesas,rcar_sound-gen2", .data = (void *)RSND_GEN2 }, |
---|
110 | 112 | { .compatible = "renesas,rcar_sound-gen3", .data = (void *)RSND_GEN3 }, |
---|
| 113 | + /* Special Handling */ |
---|
| 114 | + { .compatible = "renesas,rcar_sound-r8a77990", .data = (void *)(RSND_GEN3 | RSND_SOC_E) }, |
---|
111 | 115 | {}, |
---|
112 | 116 | }; |
---|
113 | 117 | MODULE_DEVICE_TABLE(of, rsnd_of_match); |
---|
.. | .. |
---|
121 | 125 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
---|
122 | 126 | struct device *dev = rsnd_priv_to_dev(priv); |
---|
123 | 127 | |
---|
124 | | - dev_warn(dev, "%s[%d] is not your expected module\n", |
---|
125 | | - rsnd_mod_name(mod), rsnd_mod_id(mod)); |
---|
| 128 | + dev_warn(dev, "%s is not your expected module\n", |
---|
| 129 | + rsnd_mod_name(mod)); |
---|
126 | 130 | } |
---|
127 | 131 | } |
---|
128 | 132 | |
---|
.. | .. |
---|
135 | 139 | return mod->ops->dma_req(io, mod); |
---|
136 | 140 | } |
---|
137 | 141 | |
---|
138 | | -u32 *rsnd_mod_get_status(struct rsnd_dai_stream *io, |
---|
139 | | - struct rsnd_mod *mod, |
---|
| 142 | +#define MOD_NAME_NUM 5 |
---|
| 143 | +#define MOD_NAME_SIZE 16 |
---|
| 144 | +char *rsnd_mod_name(struct rsnd_mod *mod) |
---|
| 145 | +{ |
---|
| 146 | + static char names[MOD_NAME_NUM][MOD_NAME_SIZE]; |
---|
| 147 | + static int num; |
---|
| 148 | + char *name = names[num]; |
---|
| 149 | + |
---|
| 150 | + num++; |
---|
| 151 | + if (num >= MOD_NAME_NUM) |
---|
| 152 | + num = 0; |
---|
| 153 | + |
---|
| 154 | + /* |
---|
| 155 | + * Let's use same char to avoid pointlessness memory |
---|
| 156 | + * Thus, rsnd_mod_name() should be used immediately |
---|
| 157 | + * Don't keep pointer |
---|
| 158 | + */ |
---|
| 159 | + if ((mod)->ops->id_sub) { |
---|
| 160 | + snprintf(name, MOD_NAME_SIZE, "%s[%d%d]", |
---|
| 161 | + mod->ops->name, |
---|
| 162 | + rsnd_mod_id(mod), |
---|
| 163 | + rsnd_mod_id_sub(mod)); |
---|
| 164 | + } else { |
---|
| 165 | + snprintf(name, MOD_NAME_SIZE, "%s[%d]", |
---|
| 166 | + mod->ops->name, |
---|
| 167 | + rsnd_mod_id(mod)); |
---|
| 168 | + } |
---|
| 169 | + |
---|
| 170 | + return name; |
---|
| 171 | +} |
---|
| 172 | + |
---|
| 173 | +u32 *rsnd_mod_get_status(struct rsnd_mod *mod, |
---|
| 174 | + struct rsnd_dai_stream *io, |
---|
140 | 175 | enum rsnd_mod_type type) |
---|
141 | 176 | { |
---|
142 | 177 | return &mod->status; |
---|
| 178 | +} |
---|
| 179 | + |
---|
| 180 | +int rsnd_mod_id_raw(struct rsnd_mod *mod) |
---|
| 181 | +{ |
---|
| 182 | + return mod->id; |
---|
| 183 | +} |
---|
| 184 | + |
---|
| 185 | +int rsnd_mod_id(struct rsnd_mod *mod) |
---|
| 186 | +{ |
---|
| 187 | + if ((mod)->ops->id) |
---|
| 188 | + return (mod)->ops->id(mod); |
---|
| 189 | + |
---|
| 190 | + return rsnd_mod_id_raw(mod); |
---|
| 191 | +} |
---|
| 192 | + |
---|
| 193 | +int rsnd_mod_id_sub(struct rsnd_mod *mod) |
---|
| 194 | +{ |
---|
| 195 | + if ((mod)->ops->id_sub) |
---|
| 196 | + return (mod)->ops->id_sub(mod); |
---|
| 197 | + |
---|
| 198 | + return 0; |
---|
143 | 199 | } |
---|
144 | 200 | |
---|
145 | 201 | int rsnd_mod_init(struct rsnd_priv *priv, |
---|
146 | 202 | struct rsnd_mod *mod, |
---|
147 | 203 | struct rsnd_mod_ops *ops, |
---|
148 | 204 | struct clk *clk, |
---|
149 | | - u32* (*get_status)(struct rsnd_dai_stream *io, |
---|
150 | | - struct rsnd_mod *mod, |
---|
151 | | - enum rsnd_mod_type type), |
---|
152 | 205 | enum rsnd_mod_type type, |
---|
153 | 206 | int id) |
---|
154 | 207 | { |
---|
.. | .. |
---|
162 | 215 | mod->type = type; |
---|
163 | 216 | mod->clk = clk; |
---|
164 | 217 | mod->priv = priv; |
---|
165 | | - mod->get_status = get_status; |
---|
166 | 218 | |
---|
167 | 219 | return ret; |
---|
168 | 220 | } |
---|
.. | .. |
---|
226 | 278 | struct rsnd_mod *ctu_mod = rsnd_io_to_mod_ctu(io); |
---|
227 | 279 | |
---|
228 | 280 | if (ctu_mod) { |
---|
229 | | - u32 converted_chan = rsnd_ctu_converted_channel(ctu_mod); |
---|
| 281 | + u32 converted_chan = rsnd_io_converted_chan(io); |
---|
| 282 | + |
---|
| 283 | + /* |
---|
| 284 | + * !! Note !! |
---|
| 285 | + * |
---|
| 286 | + * converted_chan will be used for CTU, |
---|
| 287 | + * or TDM Split mode. |
---|
| 288 | + * User shouldn't use CTU with TDM Split mode. |
---|
| 289 | + */ |
---|
| 290 | + if (rsnd_runtime_is_tdm_split(io)) { |
---|
| 291 | + struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io)); |
---|
| 292 | + |
---|
| 293 | + dev_err(dev, "CTU and TDM Split should be used\n"); |
---|
| 294 | + } |
---|
230 | 295 | |
---|
231 | 296 | if (converted_chan) |
---|
232 | 297 | return converted_chan; |
---|
233 | 298 | } |
---|
| 299 | + |
---|
| 300 | + return chan; |
---|
| 301 | +} |
---|
| 302 | + |
---|
| 303 | +int rsnd_channel_normalization(int chan) |
---|
| 304 | +{ |
---|
| 305 | + if (WARN_ON((chan > 8) || (chan < 0))) |
---|
| 306 | + return 0; |
---|
| 307 | + |
---|
| 308 | + /* TDM Extend Mode needs 8ch */ |
---|
| 309 | + if (chan == 6) |
---|
| 310 | + chan = 8; |
---|
234 | 311 | |
---|
235 | 312 | return chan; |
---|
236 | 313 | } |
---|
.. | .. |
---|
244 | 321 | rsnd_runtime_channel_original_with_params(io, params); |
---|
245 | 322 | |
---|
246 | 323 | /* Use Multi SSI */ |
---|
247 | | - if (rsnd_runtime_is_ssi_multi(io)) |
---|
| 324 | + if (rsnd_runtime_is_multi_ssi(io)) |
---|
248 | 325 | chan /= rsnd_rdai_ssi_lane_get(rdai); |
---|
249 | 326 | |
---|
250 | | - /* TDM Extend Mode needs 8ch */ |
---|
251 | | - if (chan == 6) |
---|
252 | | - chan = 8; |
---|
253 | | - |
---|
254 | | - return chan; |
---|
| 327 | + return rsnd_channel_normalization(chan); |
---|
255 | 328 | } |
---|
256 | 329 | |
---|
257 | | -int rsnd_runtime_is_ssi_multi(struct rsnd_dai_stream *io) |
---|
| 330 | +int rsnd_runtime_is_multi_ssi(struct rsnd_dai_stream *io) |
---|
258 | 331 | { |
---|
259 | 332 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
---|
260 | 333 | int lane = rsnd_rdai_ssi_lane_get(rdai); |
---|
.. | .. |
---|
265 | 338 | return (chan > 2) && (lane > 1); |
---|
266 | 339 | } |
---|
267 | 340 | |
---|
268 | | -int rsnd_runtime_is_ssi_tdm(struct rsnd_dai_stream *io) |
---|
| 341 | +int rsnd_runtime_is_tdm(struct rsnd_dai_stream *io) |
---|
269 | 342 | { |
---|
270 | 343 | return rsnd_runtime_channel_for_ssi(io) >= 6; |
---|
| 344 | +} |
---|
| 345 | + |
---|
| 346 | +int rsnd_runtime_is_tdm_split(struct rsnd_dai_stream *io) |
---|
| 347 | +{ |
---|
| 348 | + return !!rsnd_flags_has(io, RSND_STREAM_TDM_SPLIT); |
---|
271 | 349 | } |
---|
272 | 350 | |
---|
273 | 351 | /* |
---|
.. | .. |
---|
280 | 358 | struct device *dev = rsnd_priv_to_dev(priv); |
---|
281 | 359 | |
---|
282 | 360 | switch (snd_pcm_format_width(runtime->format)) { |
---|
| 361 | + case 8: |
---|
| 362 | + return 16 << 16; |
---|
283 | 363 | case 16: |
---|
284 | 364 | return 8 << 16; |
---|
285 | 365 | case 24: |
---|
.. | .. |
---|
296 | 376 | */ |
---|
297 | 377 | u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) |
---|
298 | 378 | { |
---|
| 379 | + static const u32 dalign_values[8] = { |
---|
| 380 | + 0x76543210, 0x00000032, 0x00007654, 0x00000076, |
---|
| 381 | + 0xfedcba98, 0x000000ba, 0x0000fedc, 0x000000fe, |
---|
| 382 | + }; |
---|
| 383 | + int id = 0; |
---|
299 | 384 | struct rsnd_mod *ssiu = rsnd_io_to_mod_ssiu(io); |
---|
300 | 385 | struct rsnd_mod *target; |
---|
301 | 386 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
---|
| 387 | + u32 dalign; |
---|
302 | 388 | |
---|
303 | 389 | /* |
---|
304 | 390 | * *Hardware* L/R and *Software* L/R are inverted for 16bit data. |
---|
.. | .. |
---|
331 | 417 | target = cmd ? cmd : ssiu; |
---|
332 | 418 | } |
---|
333 | 419 | |
---|
334 | | - /* Non target mod or 24bit data needs normal DALIGN */ |
---|
335 | | - if ((snd_pcm_format_width(runtime->format) != 16) || |
---|
336 | | - (mod != target)) |
---|
337 | | - return 0x76543210; |
---|
338 | | - /* Target mod needs inverted DALIGN when 16bit */ |
---|
339 | | - else |
---|
340 | | - return 0x67452301; |
---|
| 420 | + if (mod == ssiu) |
---|
| 421 | + id = rsnd_mod_id_sub(mod); |
---|
| 422 | + |
---|
| 423 | + dalign = dalign_values[id]; |
---|
| 424 | + |
---|
| 425 | + if (mod == target && snd_pcm_format_width(runtime->format) == 16) { |
---|
| 426 | + /* Target mod needs inverted DALIGN when 16bit */ |
---|
| 427 | + dalign = (dalign & 0xf0f0f0f0) >> 4 | |
---|
| 428 | + (dalign & 0x0f0f0f0f) << 4; |
---|
| 429 | + } |
---|
| 430 | + |
---|
| 431 | + return dalign; |
---|
341 | 432 | } |
---|
342 | 433 | |
---|
343 | 434 | u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod) |
---|
.. | .. |
---|
367 | 458 | * HW 24bit data is located as 0x******00 |
---|
368 | 459 | * |
---|
369 | 460 | */ |
---|
370 | | - if (snd_pcm_format_width(runtime->format) == 16) |
---|
| 461 | + if (snd_pcm_format_width(runtime->format) != 24) |
---|
371 | 462 | return 0; |
---|
372 | 463 | |
---|
373 | 464 | for (i = 0; i < ARRAY_SIZE(playback_mods); i++) { |
---|
.. | .. |
---|
468 | 559 | enum rsnd_mod_type *types = rsnd_mod_sequence[is_play]; \ |
---|
469 | 560 | for_each_rsnd_mod_arrays(i, mod, io, types, RSND_MOD_MAX) { \ |
---|
470 | 561 | int tmp = 0; \ |
---|
471 | | - u32 *status = mod->get_status(io, mod, types[i]); \ |
---|
| 562 | + u32 *status = mod->ops->get_status(mod, io, types[i]); \ |
---|
472 | 563 | int func_call = rsnd_status_update(status, \ |
---|
473 | 564 | __rsnd_mod_shift_##fn, \ |
---|
474 | 565 | __rsnd_mod_add_##fn, \ |
---|
475 | 566 | __rsnd_mod_call_##fn); \ |
---|
476 | | - rsnd_dbg_dai_call(dev, "%s[%d]\t0x%08x %s\n", \ |
---|
477 | | - rsnd_mod_name(mod), rsnd_mod_id(mod), *status, \ |
---|
| 567 | + rsnd_dbg_dai_call(dev, "%s\t0x%08x %s\n", \ |
---|
| 568 | + rsnd_mod_name(mod), *status, \ |
---|
478 | 569 | (func_call && (mod)->ops->fn) ? #fn : ""); \ |
---|
479 | 570 | if (func_call && (mod)->ops->fn) \ |
---|
480 | 571 | tmp = (mod)->ops->fn(mod, io, param); \ |
---|
481 | 572 | if (tmp && (tmp != -EPROBE_DEFER)) \ |
---|
482 | | - dev_err(dev, "%s[%d] : %s error %d\n", \ |
---|
483 | | - rsnd_mod_name(mod), rsnd_mod_id(mod), \ |
---|
484 | | - #fn, tmp); \ |
---|
| 573 | + dev_err(dev, "%s : %s error %d\n", \ |
---|
| 574 | + rsnd_mod_name(mod), #fn, tmp); \ |
---|
485 | 575 | ret |= tmp; \ |
---|
486 | 576 | } \ |
---|
487 | 577 | ret; \ |
---|
.. | .. |
---|
508 | 598 | |
---|
509 | 599 | io->mod[type] = mod; |
---|
510 | 600 | |
---|
511 | | - dev_dbg(dev, "%s[%d] is connected to io (%s)\n", |
---|
512 | | - rsnd_mod_name(mod), rsnd_mod_id(mod), |
---|
| 601 | + dev_dbg(dev, "%s is connected to io (%s)\n", |
---|
| 602 | + rsnd_mod_name(mod), |
---|
513 | 603 | rsnd_io_is_play(io) ? "Playback" : "Capture"); |
---|
514 | 604 | |
---|
515 | 605 | return 0; |
---|
.. | .. |
---|
538 | 628 | rdai->ssi_lane = ssi_lane; |
---|
539 | 629 | |
---|
540 | 630 | return rdai->ssi_lane; |
---|
| 631 | +} |
---|
| 632 | + |
---|
| 633 | +int rsnd_rdai_width_ctrl(struct rsnd_dai *rdai, int width) |
---|
| 634 | +{ |
---|
| 635 | + if (width > 0) |
---|
| 636 | + rdai->chan_width = width; |
---|
| 637 | + |
---|
| 638 | + return rdai->chan_width; |
---|
541 | 639 | } |
---|
542 | 640 | |
---|
543 | 641 | struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id) |
---|
.. | .. |
---|
596 | 694 | static |
---|
597 | 695 | struct snd_soc_dai *rsnd_substream_to_dai(struct snd_pcm_substream *substream) |
---|
598 | 696 | { |
---|
599 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
---|
| 697 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
---|
600 | 698 | |
---|
601 | | - return rtd->cpu_dai; |
---|
| 699 | + return asoc_rtd_to_cpu(rtd, 0); |
---|
602 | 700 | } |
---|
603 | 701 | |
---|
604 | 702 | static |
---|
.. | .. |
---|
661 | 759 | { |
---|
662 | 760 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
---|
663 | 761 | |
---|
664 | | - /* set master/slave audio interface */ |
---|
| 762 | + /* set clock master for audio interface */ |
---|
665 | 763 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
---|
666 | 764 | case SND_SOC_DAIFMT_CBM_CFM: |
---|
667 | 765 | rdai->clk_master = 0; |
---|
668 | 766 | break; |
---|
669 | 767 | case SND_SOC_DAIFMT_CBS_CFS: |
---|
670 | | - rdai->clk_master = 1; /* codec is slave, cpu is master */ |
---|
| 768 | + rdai->clk_master = 1; /* cpu is master */ |
---|
671 | 769 | break; |
---|
672 | 770 | default: |
---|
673 | 771 | return -EINVAL; |
---|
.. | .. |
---|
682 | 780 | rdai->frm_clk_inv = 0; |
---|
683 | 781 | break; |
---|
684 | 782 | case SND_SOC_DAIFMT_LEFT_J: |
---|
| 783 | + case SND_SOC_DAIFMT_DSP_B: |
---|
685 | 784 | rdai->sys_delay = 1; |
---|
686 | 785 | rdai->data_alignment = 0; |
---|
687 | 786 | rdai->frm_clk_inv = 1; |
---|
.. | .. |
---|
689 | 788 | case SND_SOC_DAIFMT_RIGHT_J: |
---|
690 | 789 | rdai->sys_delay = 1; |
---|
691 | 790 | rdai->data_alignment = 1; |
---|
| 791 | + rdai->frm_clk_inv = 1; |
---|
| 792 | + break; |
---|
| 793 | + case SND_SOC_DAIFMT_DSP_A: |
---|
| 794 | + rdai->sys_delay = 0; |
---|
| 795 | + rdai->data_alignment = 0; |
---|
692 | 796 | rdai->frm_clk_inv = 1; |
---|
693 | 797 | break; |
---|
694 | 798 | } |
---|
.. | .. |
---|
721 | 825 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
---|
722 | 826 | struct device *dev = rsnd_priv_to_dev(priv); |
---|
723 | 827 | |
---|
| 828 | + switch (slot_width) { |
---|
| 829 | + case 16: |
---|
| 830 | + case 24: |
---|
| 831 | + case 32: |
---|
| 832 | + break; |
---|
| 833 | + default: |
---|
| 834 | + /* use default */ |
---|
| 835 | + slot_width = 32; |
---|
| 836 | + } |
---|
| 837 | + |
---|
724 | 838 | switch (slots) { |
---|
725 | 839 | case 2: |
---|
| 840 | + /* TDM Split Mode */ |
---|
726 | 841 | case 6: |
---|
727 | 842 | case 8: |
---|
728 | 843 | /* TDM Extend Mode */ |
---|
729 | 844 | rsnd_rdai_channels_set(rdai, slots); |
---|
730 | 845 | rsnd_rdai_ssi_lane_set(rdai, 1); |
---|
| 846 | + rsnd_rdai_width_set(rdai, slot_width); |
---|
731 | 847 | break; |
---|
732 | 848 | default: |
---|
733 | 849 | dev_err(dev, "unsupported TDM slots (%d)\n", slots); |
---|
.. | .. |
---|
756 | 872 | 192000, |
---|
757 | 873 | }; |
---|
758 | 874 | |
---|
759 | | -static int rsnd_soc_hw_rule(struct rsnd_priv *priv, |
---|
| 875 | +static int rsnd_soc_hw_rule(struct rsnd_dai *rdai, |
---|
760 | 876 | unsigned int *list, int list_num, |
---|
761 | 877 | struct snd_interval *baseline, struct snd_interval *iv) |
---|
762 | 878 | { |
---|
.. | .. |
---|
773 | 889 | if (!snd_interval_test(iv, list[i])) |
---|
774 | 890 | continue; |
---|
775 | 891 | |
---|
776 | | - rate = rsnd_ssi_clk_query(priv, |
---|
| 892 | + rate = rsnd_ssi_clk_query(rdai, |
---|
777 | 893 | baseline->min, list[i], NULL); |
---|
778 | 894 | if (rate > 0) { |
---|
779 | 895 | p.min = min(p.min, list[i]); |
---|
780 | 896 | p.max = max(p.max, list[i]); |
---|
781 | 897 | } |
---|
782 | 898 | |
---|
783 | | - rate = rsnd_ssi_clk_query(priv, |
---|
| 899 | + rate = rsnd_ssi_clk_query(rdai, |
---|
784 | 900 | baseline->max, list[i], NULL); |
---|
785 | 901 | if (rate > 0) { |
---|
786 | 902 | p.min = min(p.min, list[i]); |
---|
.. | .. |
---|
791 | 907 | return snd_interval_refine(iv, &p); |
---|
792 | 908 | } |
---|
793 | 909 | |
---|
794 | | -static int __rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params, |
---|
795 | | - struct snd_pcm_hw_rule *rule, |
---|
796 | | - int is_play) |
---|
| 910 | +static int rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params, |
---|
| 911 | + struct snd_pcm_hw_rule *rule) |
---|
797 | 912 | { |
---|
798 | 913 | struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); |
---|
799 | 914 | struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
---|
800 | 915 | struct snd_interval ic; |
---|
801 | | - struct snd_soc_dai *dai = rule->private; |
---|
802 | | - struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
---|
803 | | - struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); |
---|
804 | | - struct rsnd_dai_stream *io = is_play ? &rdai->playback : &rdai->capture; |
---|
| 916 | + struct rsnd_dai_stream *io = rule->private; |
---|
| 917 | + struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
---|
805 | 918 | |
---|
806 | 919 | /* |
---|
807 | 920 | * possible sampling rate limitation is same as |
---|
.. | .. |
---|
812 | 925 | ic.min = |
---|
813 | 926 | ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params); |
---|
814 | 927 | |
---|
815 | | - return rsnd_soc_hw_rule(priv, rsnd_soc_hw_rate_list, |
---|
| 928 | + return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_rate_list, |
---|
816 | 929 | ARRAY_SIZE(rsnd_soc_hw_rate_list), |
---|
817 | 930 | &ic, ir); |
---|
818 | 931 | } |
---|
819 | 932 | |
---|
820 | | -static int rsnd_soc_hw_rule_rate_playback(struct snd_pcm_hw_params *params, |
---|
821 | | - struct snd_pcm_hw_rule *rule) |
---|
822 | | -{ |
---|
823 | | - return __rsnd_soc_hw_rule_rate(params, rule, 1); |
---|
824 | | -} |
---|
825 | | - |
---|
826 | | -static int rsnd_soc_hw_rule_rate_capture(struct snd_pcm_hw_params *params, |
---|
827 | | - struct snd_pcm_hw_rule *rule) |
---|
828 | | -{ |
---|
829 | | - return __rsnd_soc_hw_rule_rate(params, rule, 0); |
---|
830 | | -} |
---|
831 | | - |
---|
832 | | -static int __rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params, |
---|
833 | | - struct snd_pcm_hw_rule *rule, |
---|
834 | | - int is_play) |
---|
| 933 | +static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params, |
---|
| 934 | + struct snd_pcm_hw_rule *rule) |
---|
835 | 935 | { |
---|
836 | 936 | struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); |
---|
837 | 937 | struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
---|
838 | 938 | struct snd_interval ic; |
---|
839 | | - struct snd_soc_dai *dai = rule->private; |
---|
840 | | - struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
---|
841 | | - struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); |
---|
842 | | - struct rsnd_dai_stream *io = is_play ? &rdai->playback : &rdai->capture; |
---|
| 939 | + struct rsnd_dai_stream *io = rule->private; |
---|
| 940 | + struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
---|
843 | 941 | |
---|
844 | 942 | /* |
---|
845 | 943 | * possible sampling rate limitation is same as |
---|
.. | .. |
---|
850 | 948 | ic.min = |
---|
851 | 949 | ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params); |
---|
852 | 950 | |
---|
853 | | - return rsnd_soc_hw_rule(priv, rsnd_soc_hw_channels_list, |
---|
| 951 | + return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_channels_list, |
---|
854 | 952 | ARRAY_SIZE(rsnd_soc_hw_channels_list), |
---|
855 | 953 | ir, &ic); |
---|
856 | | -} |
---|
857 | | - |
---|
858 | | -static int rsnd_soc_hw_rule_channels_playback(struct snd_pcm_hw_params *params, |
---|
859 | | - struct snd_pcm_hw_rule *rule) |
---|
860 | | -{ |
---|
861 | | - return __rsnd_soc_hw_rule_channels(params, rule, 1); |
---|
862 | | -} |
---|
863 | | - |
---|
864 | | -static int rsnd_soc_hw_rule_channels_capture(struct snd_pcm_hw_params *params, |
---|
865 | | - struct snd_pcm_hw_rule *rule) |
---|
866 | | -{ |
---|
867 | | - return __rsnd_soc_hw_rule_channels(params, rule, 0); |
---|
868 | 954 | } |
---|
869 | 955 | |
---|
870 | 956 | static const struct snd_pcm_hardware rsnd_pcm_hardware = { |
---|
.. | .. |
---|
883 | 969 | struct snd_soc_dai *dai) |
---|
884 | 970 | { |
---|
885 | 971 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
---|
886 | | - struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); |
---|
887 | 972 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); |
---|
888 | 973 | struct snd_pcm_hw_constraint_list *constraint = &rdai->constraint; |
---|
889 | 974 | struct snd_pcm_runtime *runtime = substream->runtime; |
---|
890 | 975 | unsigned int max_channels = rsnd_rdai_channels_get(rdai); |
---|
891 | | - int ret; |
---|
892 | 976 | int i; |
---|
893 | 977 | |
---|
894 | 978 | rsnd_dai_stream_init(io, substream); |
---|
.. | .. |
---|
923 | 1007 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
---|
924 | 1008 | |
---|
925 | 1009 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
---|
926 | | - is_play ? rsnd_soc_hw_rule_rate_playback : |
---|
927 | | - rsnd_soc_hw_rule_rate_capture, |
---|
928 | | - dai, |
---|
| 1010 | + rsnd_soc_hw_rule_rate, |
---|
| 1011 | + is_play ? &rdai->playback : &rdai->capture, |
---|
929 | 1012 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
---|
930 | 1013 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
---|
931 | | - is_play ? rsnd_soc_hw_rule_channels_playback : |
---|
932 | | - rsnd_soc_hw_rule_channels_capture, |
---|
933 | | - dai, |
---|
| 1014 | + rsnd_soc_hw_rule_channels, |
---|
| 1015 | + is_play ? &rdai->playback : &rdai->capture, |
---|
934 | 1016 | SNDRV_PCM_HW_PARAM_RATE, -1); |
---|
935 | 1017 | } |
---|
936 | 1018 | |
---|
937 | | - /* |
---|
938 | | - * call rsnd_dai_call without spinlock |
---|
939 | | - */ |
---|
940 | | - ret = rsnd_dai_call(nolock_start, io, priv); |
---|
941 | | - if (ret < 0) |
---|
942 | | - rsnd_dai_call(nolock_stop, io, priv); |
---|
943 | | - |
---|
944 | | - return ret; |
---|
| 1019 | + return 0; |
---|
945 | 1020 | } |
---|
946 | 1021 | |
---|
947 | 1022 | static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream, |
---|
.. | .. |
---|
954 | 1029 | /* |
---|
955 | 1030 | * call rsnd_dai_call without spinlock |
---|
956 | 1031 | */ |
---|
957 | | - rsnd_dai_call(nolock_stop, io, priv); |
---|
| 1032 | + rsnd_dai_call(cleanup, io, priv); |
---|
958 | 1033 | |
---|
959 | 1034 | rsnd_dai_stream_quit(io); |
---|
960 | 1035 | } |
---|
.. | .. |
---|
977 | 1052 | .set_tdm_slot = rsnd_soc_set_dai_tdm_slot, |
---|
978 | 1053 | .prepare = rsnd_soc_dai_prepare, |
---|
979 | 1054 | }; |
---|
| 1055 | + |
---|
| 1056 | +static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv, |
---|
| 1057 | + struct rsnd_dai_stream *io, |
---|
| 1058 | + struct device_node *dai_np) |
---|
| 1059 | +{ |
---|
| 1060 | + struct device *dev = rsnd_priv_to_dev(priv); |
---|
| 1061 | + struct device_node *ssiu_np = rsnd_ssiu_of_node(priv); |
---|
| 1062 | + struct device_node *np; |
---|
| 1063 | + int is_play = rsnd_io_is_play(io); |
---|
| 1064 | + int i, j; |
---|
| 1065 | + |
---|
| 1066 | + if (!ssiu_np) |
---|
| 1067 | + return; |
---|
| 1068 | + |
---|
| 1069 | + /* |
---|
| 1070 | + * This driver assumes that it is TDM Split mode |
---|
| 1071 | + * if it includes ssiu node |
---|
| 1072 | + */ |
---|
| 1073 | + for (i = 0;; i++) { |
---|
| 1074 | + struct device_node *node = is_play ? |
---|
| 1075 | + of_parse_phandle(dai_np, "playback", i) : |
---|
| 1076 | + of_parse_phandle(dai_np, "capture", i); |
---|
| 1077 | + |
---|
| 1078 | + if (!node) |
---|
| 1079 | + break; |
---|
| 1080 | + |
---|
| 1081 | + j = 0; |
---|
| 1082 | + for_each_child_of_node(ssiu_np, np) { |
---|
| 1083 | + if (np == node) { |
---|
| 1084 | + rsnd_flags_set(io, RSND_STREAM_TDM_SPLIT); |
---|
| 1085 | + dev_dbg(dev, "%s is part of TDM Split\n", io->name); |
---|
| 1086 | + } |
---|
| 1087 | + j++; |
---|
| 1088 | + } |
---|
| 1089 | + |
---|
| 1090 | + of_node_put(node); |
---|
| 1091 | + } |
---|
| 1092 | + |
---|
| 1093 | + of_node_put(ssiu_np); |
---|
| 1094 | +} |
---|
| 1095 | + |
---|
| 1096 | +static void rsnd_parse_connect_simple(struct rsnd_priv *priv, |
---|
| 1097 | + struct rsnd_dai_stream *io, |
---|
| 1098 | + struct device_node *dai_np) |
---|
| 1099 | +{ |
---|
| 1100 | + if (!rsnd_io_to_mod_ssi(io)) |
---|
| 1101 | + return; |
---|
| 1102 | + |
---|
| 1103 | + rsnd_parse_tdm_split_mode(priv, io, dai_np); |
---|
| 1104 | +} |
---|
| 1105 | + |
---|
| 1106 | +static void rsnd_parse_connect_graph(struct rsnd_priv *priv, |
---|
| 1107 | + struct rsnd_dai_stream *io, |
---|
| 1108 | + struct device_node *endpoint) |
---|
| 1109 | +{ |
---|
| 1110 | + struct device *dev = rsnd_priv_to_dev(priv); |
---|
| 1111 | + struct device_node *remote_node; |
---|
| 1112 | + |
---|
| 1113 | + if (!rsnd_io_to_mod_ssi(io)) |
---|
| 1114 | + return; |
---|
| 1115 | + |
---|
| 1116 | + remote_node = of_graph_get_remote_port_parent(endpoint); |
---|
| 1117 | + |
---|
| 1118 | + /* HDMI0 */ |
---|
| 1119 | + if (strstr(remote_node->full_name, "hdmi@fead0000")) { |
---|
| 1120 | + rsnd_flags_set(io, RSND_STREAM_HDMI0); |
---|
| 1121 | + dev_dbg(dev, "%s connected to HDMI0\n", io->name); |
---|
| 1122 | + } |
---|
| 1123 | + |
---|
| 1124 | + /* HDMI1 */ |
---|
| 1125 | + if (strstr(remote_node->full_name, "hdmi@feae0000")) { |
---|
| 1126 | + rsnd_flags_set(io, RSND_STREAM_HDMI1); |
---|
| 1127 | + dev_dbg(dev, "%s connected to HDMI1\n", io->name); |
---|
| 1128 | + } |
---|
| 1129 | + |
---|
| 1130 | + rsnd_parse_tdm_split_mode(priv, io, endpoint); |
---|
| 1131 | + |
---|
| 1132 | + of_node_put(remote_node); |
---|
| 1133 | +} |
---|
980 | 1134 | |
---|
981 | 1135 | void rsnd_parse_connect_common(struct rsnd_dai *rdai, |
---|
982 | 1136 | struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id), |
---|
.. | .. |
---|
1041 | 1195 | return ret; |
---|
1042 | 1196 | } |
---|
1043 | 1197 | |
---|
| 1198 | + |
---|
| 1199 | +#define PREALLOC_BUFFER (32 * 1024) |
---|
| 1200 | +#define PREALLOC_BUFFER_MAX (32 * 1024) |
---|
| 1201 | + |
---|
| 1202 | +static int rsnd_preallocate_pages(struct snd_soc_pcm_runtime *rtd, |
---|
| 1203 | + struct rsnd_dai_stream *io, |
---|
| 1204 | + int stream) |
---|
| 1205 | +{ |
---|
| 1206 | + struct rsnd_priv *priv = rsnd_io_to_priv(io); |
---|
| 1207 | + struct device *dev = rsnd_priv_to_dev(priv); |
---|
| 1208 | + struct snd_pcm_substream *substream; |
---|
| 1209 | + |
---|
| 1210 | + /* |
---|
| 1211 | + * use Audio-DMAC dev if we can use IPMMU |
---|
| 1212 | + * see |
---|
| 1213 | + * rsnd_dmaen_attach() |
---|
| 1214 | + */ |
---|
| 1215 | + if (io->dmac_dev) |
---|
| 1216 | + dev = io->dmac_dev; |
---|
| 1217 | + |
---|
| 1218 | + for (substream = rtd->pcm->streams[stream].substream; |
---|
| 1219 | + substream; |
---|
| 1220 | + substream = substream->next) { |
---|
| 1221 | + snd_pcm_set_managed_buffer(substream, |
---|
| 1222 | + SNDRV_DMA_TYPE_DEV, |
---|
| 1223 | + dev, |
---|
| 1224 | + PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); |
---|
| 1225 | + } |
---|
| 1226 | + |
---|
| 1227 | + return 0; |
---|
| 1228 | +} |
---|
| 1229 | + |
---|
| 1230 | +static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd, |
---|
| 1231 | + struct snd_soc_dai *dai) |
---|
| 1232 | +{ |
---|
| 1233 | + struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
---|
| 1234 | + int ret; |
---|
| 1235 | + |
---|
| 1236 | + ret = rsnd_dai_call(pcm_new, &rdai->playback, rtd); |
---|
| 1237 | + if (ret) |
---|
| 1238 | + return ret; |
---|
| 1239 | + |
---|
| 1240 | + ret = rsnd_dai_call(pcm_new, &rdai->capture, rtd); |
---|
| 1241 | + if (ret) |
---|
| 1242 | + return ret; |
---|
| 1243 | + |
---|
| 1244 | + ret = rsnd_preallocate_pages(rtd, &rdai->playback, |
---|
| 1245 | + SNDRV_PCM_STREAM_PLAYBACK); |
---|
| 1246 | + if (ret) |
---|
| 1247 | + return ret; |
---|
| 1248 | + |
---|
| 1249 | + ret = rsnd_preallocate_pages(rtd, &rdai->capture, |
---|
| 1250 | + SNDRV_PCM_STREAM_CAPTURE); |
---|
| 1251 | + if (ret) |
---|
| 1252 | + return ret; |
---|
| 1253 | + |
---|
| 1254 | + return 0; |
---|
| 1255 | +} |
---|
| 1256 | + |
---|
1044 | 1257 | static void __rsnd_dai_probe(struct rsnd_priv *priv, |
---|
1045 | 1258 | struct device_node *dai_np, |
---|
1046 | 1259 | int dai_i) |
---|
.. | .. |
---|
1063 | 1276 | rdai->priv = priv; |
---|
1064 | 1277 | drv->name = rdai->name; |
---|
1065 | 1278 | drv->ops = &rsnd_soc_dai_ops; |
---|
| 1279 | + drv->pcm_new = rsnd_pcm_new; |
---|
1066 | 1280 | |
---|
1067 | | - snprintf(rdai->playback.name, RSND_DAI_NAME_SIZE, |
---|
| 1281 | + snprintf(io_playback->name, RSND_DAI_NAME_SIZE, |
---|
1068 | 1282 | "DAI%d Playback", dai_i); |
---|
1069 | 1283 | drv->playback.rates = RSND_RATES; |
---|
1070 | 1284 | drv->playback.formats = RSND_FMTS; |
---|
1071 | 1285 | drv->playback.channels_min = 2; |
---|
1072 | 1286 | drv->playback.channels_max = 8; |
---|
1073 | | - drv->playback.stream_name = rdai->playback.name; |
---|
| 1287 | + drv->playback.stream_name = io_playback->name; |
---|
1074 | 1288 | |
---|
1075 | | - snprintf(rdai->capture.name, RSND_DAI_NAME_SIZE, |
---|
| 1289 | + snprintf(io_capture->name, RSND_DAI_NAME_SIZE, |
---|
1076 | 1290 | "DAI%d Capture", dai_i); |
---|
1077 | 1291 | drv->capture.rates = RSND_RATES; |
---|
1078 | 1292 | drv->capture.formats = RSND_FMTS; |
---|
1079 | 1293 | drv->capture.channels_min = 2; |
---|
1080 | 1294 | drv->capture.channels_max = 8; |
---|
1081 | | - drv->capture.stream_name = rdai->capture.name; |
---|
| 1295 | + drv->capture.stream_name = io_capture->name; |
---|
1082 | 1296 | |
---|
1083 | | - rdai->playback.rdai = rdai; |
---|
1084 | | - rdai->capture.rdai = rdai; |
---|
| 1297 | + io_playback->rdai = rdai; |
---|
| 1298 | + io_capture->rdai = rdai; |
---|
1085 | 1299 | rsnd_rdai_channels_set(rdai, 2); /* default 2ch */ |
---|
1086 | 1300 | rsnd_rdai_ssi_lane_set(rdai, 1); /* default 1lane */ |
---|
| 1301 | + rsnd_rdai_width_set(rdai, 32); /* default 32bit width */ |
---|
1087 | 1302 | |
---|
1088 | 1303 | for (io_i = 0;; io_i++) { |
---|
1089 | 1304 | playback = of_parse_phandle(dai_np, "playback", io_i); |
---|
.. | .. |
---|
1093 | 1308 | break; |
---|
1094 | 1309 | |
---|
1095 | 1310 | rsnd_parse_connect_ssi(rdai, playback, capture); |
---|
| 1311 | + rsnd_parse_connect_ssiu(rdai, playback, capture); |
---|
1096 | 1312 | rsnd_parse_connect_src(rdai, playback, capture); |
---|
1097 | 1313 | rsnd_parse_connect_ctu(rdai, playback, capture); |
---|
1098 | 1314 | rsnd_parse_connect_mix(rdai, playback, capture); |
---|
.. | .. |
---|
1149 | 1365 | if (is_graph) { |
---|
1150 | 1366 | for_each_endpoint_of_node(dai_node, dai_np) { |
---|
1151 | 1367 | __rsnd_dai_probe(priv, dai_np, dai_i); |
---|
1152 | | - rsnd_ssi_parse_hdmi_connection(priv, dai_np, dai_i); |
---|
| 1368 | + if (rsnd_is_gen3(priv)) { |
---|
| 1369 | + struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i); |
---|
| 1370 | + |
---|
| 1371 | + rsnd_parse_connect_graph(priv, &rdai->playback, dai_np); |
---|
| 1372 | + rsnd_parse_connect_graph(priv, &rdai->capture, dai_np); |
---|
| 1373 | + } |
---|
1153 | 1374 | dai_i++; |
---|
1154 | 1375 | } |
---|
1155 | 1376 | } else { |
---|
1156 | | - for_each_child_of_node(dai_node, dai_np) |
---|
1157 | | - __rsnd_dai_probe(priv, dai_np, dai_i++); |
---|
| 1377 | + for_each_child_of_node(dai_node, dai_np) { |
---|
| 1378 | + __rsnd_dai_probe(priv, dai_np, dai_i); |
---|
| 1379 | + if (rsnd_is_gen3(priv)) { |
---|
| 1380 | + struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i); |
---|
| 1381 | + |
---|
| 1382 | + rsnd_parse_connect_simple(priv, &rdai->playback, dai_np); |
---|
| 1383 | + rsnd_parse_connect_simple(priv, &rdai->capture, dai_np); |
---|
| 1384 | + } |
---|
| 1385 | + dai_i++; |
---|
| 1386 | + } |
---|
1158 | 1387 | } |
---|
1159 | 1388 | |
---|
1160 | 1389 | return 0; |
---|
.. | .. |
---|
1163 | 1392 | /* |
---|
1164 | 1393 | * pcm ops |
---|
1165 | 1394 | */ |
---|
1166 | | -static int rsnd_hw_params(struct snd_pcm_substream *substream, |
---|
1167 | | - struct snd_pcm_hw_params *hw_params) |
---|
| 1395 | +static int rsnd_hw_params(struct snd_soc_component *component, |
---|
| 1396 | + struct snd_pcm_substream *substream, |
---|
| 1397 | + struct snd_pcm_hw_params *hw_params) |
---|
1168 | 1398 | { |
---|
1169 | 1399 | struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); |
---|
1170 | 1400 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
---|
1171 | 1401 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); |
---|
1172 | | - int ret; |
---|
| 1402 | + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); |
---|
1173 | 1403 | |
---|
1174 | | - ret = rsnd_dai_call(hw_params, io, substream, hw_params); |
---|
1175 | | - if (ret) |
---|
1176 | | - return ret; |
---|
| 1404 | + /* |
---|
| 1405 | + * rsnd assumes that it might be used under DPCM if user want to use |
---|
| 1406 | + * channel / rate convert. Then, rsnd should be FE. |
---|
| 1407 | + * And then, this function will be called *after* BE settings. |
---|
| 1408 | + * this means, each BE already has fixuped hw_params. |
---|
| 1409 | + * see |
---|
| 1410 | + * dpcm_fe_dai_hw_params() |
---|
| 1411 | + * dpcm_be_dai_hw_params() |
---|
| 1412 | + */ |
---|
| 1413 | + io->converted_rate = 0; |
---|
| 1414 | + io->converted_chan = 0; |
---|
| 1415 | + if (fe->dai_link->dynamic) { |
---|
| 1416 | + struct rsnd_priv *priv = rsnd_io_to_priv(io); |
---|
| 1417 | + struct device *dev = rsnd_priv_to_dev(priv); |
---|
| 1418 | + struct snd_soc_dpcm *dpcm; |
---|
| 1419 | + struct snd_pcm_hw_params *be_params; |
---|
| 1420 | + int stream = substream->stream; |
---|
1177 | 1421 | |
---|
1178 | | - return snd_pcm_lib_malloc_pages(substream, |
---|
1179 | | - params_buffer_bytes(hw_params)); |
---|
| 1422 | + for_each_dpcm_be(fe, stream, dpcm) { |
---|
| 1423 | + be_params = &dpcm->hw_params; |
---|
| 1424 | + if (params_channels(hw_params) != params_channels(be_params)) |
---|
| 1425 | + io->converted_chan = params_channels(be_params); |
---|
| 1426 | + if (params_rate(hw_params) != params_rate(be_params)) |
---|
| 1427 | + io->converted_rate = params_rate(be_params); |
---|
| 1428 | + } |
---|
| 1429 | + if (io->converted_chan) |
---|
| 1430 | + dev_dbg(dev, "convert channels = %d\n", io->converted_chan); |
---|
| 1431 | + if (io->converted_rate) { |
---|
| 1432 | + /* |
---|
| 1433 | + * SRC supports convert rates from params_rate(hw_params)/k_down |
---|
| 1434 | + * to params_rate(hw_params)*k_up, where k_up is always 6, and |
---|
| 1435 | + * k_down depends on number of channels and SRC unit. |
---|
| 1436 | + * So all SRC units can upsample audio up to 6 times regardless |
---|
| 1437 | + * its number of channels. And all SRC units can downsample |
---|
| 1438 | + * 2 channel audio up to 6 times too. |
---|
| 1439 | + */ |
---|
| 1440 | + int k_up = 6; |
---|
| 1441 | + int k_down = 6; |
---|
| 1442 | + int channel; |
---|
| 1443 | + struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); |
---|
| 1444 | + |
---|
| 1445 | + dev_dbg(dev, "convert rate = %d\n", io->converted_rate); |
---|
| 1446 | + |
---|
| 1447 | + channel = io->converted_chan ? io->converted_chan : |
---|
| 1448 | + params_channels(hw_params); |
---|
| 1449 | + |
---|
| 1450 | + switch (rsnd_mod_id(src_mod)) { |
---|
| 1451 | + /* |
---|
| 1452 | + * SRC0 can downsample 4, 6 and 8 channel audio up to 4 times. |
---|
| 1453 | + * SRC1, SRC3 and SRC4 can downsample 4 channel audio |
---|
| 1454 | + * up to 4 times. |
---|
| 1455 | + * SRC1, SRC3 and SRC4 can downsample 6 and 8 channel audio |
---|
| 1456 | + * no more than twice. |
---|
| 1457 | + */ |
---|
| 1458 | + case 1: |
---|
| 1459 | + case 3: |
---|
| 1460 | + case 4: |
---|
| 1461 | + if (channel > 4) { |
---|
| 1462 | + k_down = 2; |
---|
| 1463 | + break; |
---|
| 1464 | + } |
---|
| 1465 | + fallthrough; |
---|
| 1466 | + case 0: |
---|
| 1467 | + if (channel > 2) |
---|
| 1468 | + k_down = 4; |
---|
| 1469 | + break; |
---|
| 1470 | + |
---|
| 1471 | + /* Other SRC units do not support more than 2 channels */ |
---|
| 1472 | + default: |
---|
| 1473 | + if (channel > 2) |
---|
| 1474 | + return -EINVAL; |
---|
| 1475 | + } |
---|
| 1476 | + |
---|
| 1477 | + if (params_rate(hw_params) > io->converted_rate * k_down) { |
---|
| 1478 | + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min = |
---|
| 1479 | + io->converted_rate * k_down; |
---|
| 1480 | + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max = |
---|
| 1481 | + io->converted_rate * k_down; |
---|
| 1482 | + hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE; |
---|
| 1483 | + } else if (params_rate(hw_params) * k_up < io->converted_rate) { |
---|
| 1484 | + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min = |
---|
| 1485 | + (io->converted_rate + k_up - 1) / k_up; |
---|
| 1486 | + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max = |
---|
| 1487 | + (io->converted_rate + k_up - 1) / k_up; |
---|
| 1488 | + hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE; |
---|
| 1489 | + } |
---|
| 1490 | + |
---|
| 1491 | + /* |
---|
| 1492 | + * TBD: Max SRC input and output rates also depend on number |
---|
| 1493 | + * of channels and SRC unit: |
---|
| 1494 | + * SRC1, SRC3 and SRC4 do not support more than 128kHz |
---|
| 1495 | + * for 6 channel and 96kHz for 8 channel audio. |
---|
| 1496 | + * Perhaps this function should return EINVAL if the input or |
---|
| 1497 | + * the output rate exceeds the limitation. |
---|
| 1498 | + */ |
---|
| 1499 | + } |
---|
| 1500 | + } |
---|
| 1501 | + |
---|
| 1502 | + return rsnd_dai_call(hw_params, io, substream, hw_params); |
---|
1180 | 1503 | } |
---|
1181 | 1504 | |
---|
1182 | | -static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream) |
---|
| 1505 | +static int rsnd_hw_free(struct snd_soc_component *component, |
---|
| 1506 | + struct snd_pcm_substream *substream) |
---|
| 1507 | +{ |
---|
| 1508 | + struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); |
---|
| 1509 | + struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
---|
| 1510 | + struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); |
---|
| 1511 | + |
---|
| 1512 | + return rsnd_dai_call(hw_free, io, substream); |
---|
| 1513 | +} |
---|
| 1514 | + |
---|
| 1515 | +static snd_pcm_uframes_t rsnd_pointer(struct snd_soc_component *component, |
---|
| 1516 | + struct snd_pcm_substream *substream) |
---|
1183 | 1517 | { |
---|
1184 | 1518 | struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); |
---|
1185 | 1519 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
---|
.. | .. |
---|
1190 | 1524 | |
---|
1191 | 1525 | return pointer; |
---|
1192 | 1526 | } |
---|
1193 | | - |
---|
1194 | | -static const struct snd_pcm_ops rsnd_pcm_ops = { |
---|
1195 | | - .ioctl = snd_pcm_lib_ioctl, |
---|
1196 | | - .hw_params = rsnd_hw_params, |
---|
1197 | | - .hw_free = snd_pcm_lib_free_pages, |
---|
1198 | | - .pointer = rsnd_pointer, |
---|
1199 | | -}; |
---|
1200 | 1527 | |
---|
1201 | 1528 | /* |
---|
1202 | 1529 | * snd_kcontrol |
---|
.. | .. |
---|
1275 | 1602 | int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io) |
---|
1276 | 1603 | { |
---|
1277 | 1604 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
---|
| 1605 | + struct rsnd_priv *priv = rsnd_io_to_priv(io); |
---|
| 1606 | + struct device *dev = rsnd_priv_to_dev(priv); |
---|
1278 | 1607 | |
---|
1279 | | - return !!runtime; |
---|
| 1608 | + if (!runtime) { |
---|
| 1609 | + dev_warn(dev, "Can't update kctrl when idle\n"); |
---|
| 1610 | + return 0; |
---|
| 1611 | + } |
---|
| 1612 | + |
---|
| 1613 | + return 1; |
---|
1280 | 1614 | } |
---|
1281 | 1615 | |
---|
1282 | 1616 | struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg) |
---|
.. | .. |
---|
1383 | 1717 | /* |
---|
1384 | 1718 | * snd_soc_component |
---|
1385 | 1719 | */ |
---|
1386 | | - |
---|
1387 | | -#define PREALLOC_BUFFER (32 * 1024) |
---|
1388 | | -#define PREALLOC_BUFFER_MAX (32 * 1024) |
---|
1389 | | - |
---|
1390 | | -static int rsnd_preallocate_pages(struct snd_soc_pcm_runtime *rtd, |
---|
1391 | | - struct rsnd_dai_stream *io, |
---|
1392 | | - int stream) |
---|
1393 | | -{ |
---|
1394 | | - struct rsnd_priv *priv = rsnd_io_to_priv(io); |
---|
1395 | | - struct device *dev = rsnd_priv_to_dev(priv); |
---|
1396 | | - struct snd_pcm_substream *substream; |
---|
1397 | | - int err; |
---|
1398 | | - |
---|
1399 | | - /* |
---|
1400 | | - * use Audio-DMAC dev if we can use IPMMU |
---|
1401 | | - * see |
---|
1402 | | - * rsnd_dmaen_attach() |
---|
1403 | | - */ |
---|
1404 | | - if (io->dmac_dev) |
---|
1405 | | - dev = io->dmac_dev; |
---|
1406 | | - |
---|
1407 | | - for (substream = rtd->pcm->streams[stream].substream; |
---|
1408 | | - substream; |
---|
1409 | | - substream = substream->next) { |
---|
1410 | | - err = snd_pcm_lib_preallocate_pages(substream, |
---|
1411 | | - SNDRV_DMA_TYPE_DEV, |
---|
1412 | | - dev, |
---|
1413 | | - PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); |
---|
1414 | | - if (err < 0) |
---|
1415 | | - return err; |
---|
1416 | | - } |
---|
1417 | | - |
---|
1418 | | - return 0; |
---|
1419 | | -} |
---|
1420 | | - |
---|
1421 | | -static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) |
---|
1422 | | -{ |
---|
1423 | | - struct snd_soc_dai *dai = rtd->cpu_dai; |
---|
1424 | | - struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
---|
1425 | | - int ret; |
---|
1426 | | - |
---|
1427 | | - ret = rsnd_dai_call(pcm_new, &rdai->playback, rtd); |
---|
1428 | | - if (ret) |
---|
1429 | | - return ret; |
---|
1430 | | - |
---|
1431 | | - ret = rsnd_dai_call(pcm_new, &rdai->capture, rtd); |
---|
1432 | | - if (ret) |
---|
1433 | | - return ret; |
---|
1434 | | - |
---|
1435 | | - ret = rsnd_preallocate_pages(rtd, &rdai->playback, |
---|
1436 | | - SNDRV_PCM_STREAM_PLAYBACK); |
---|
1437 | | - if (ret) |
---|
1438 | | - return ret; |
---|
1439 | | - |
---|
1440 | | - ret = rsnd_preallocate_pages(rtd, &rdai->capture, |
---|
1441 | | - SNDRV_PCM_STREAM_CAPTURE); |
---|
1442 | | - if (ret) |
---|
1443 | | - return ret; |
---|
1444 | | - |
---|
1445 | | - return 0; |
---|
1446 | | -} |
---|
1447 | | - |
---|
1448 | 1720 | static const struct snd_soc_component_driver rsnd_soc_component = { |
---|
1449 | | - .ops = &rsnd_pcm_ops, |
---|
1450 | | - .pcm_new = rsnd_pcm_new, |
---|
1451 | 1721 | .name = "rsnd", |
---|
| 1722 | + .hw_params = rsnd_hw_params, |
---|
| 1723 | + .hw_free = rsnd_hw_free, |
---|
| 1724 | + .pointer = rsnd_pointer, |
---|
1452 | 1725 | }; |
---|
1453 | 1726 | |
---|
1454 | 1727 | static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv, |
---|
.. | .. |
---|
1600 | 1873 | rsnd_adg_remove, |
---|
1601 | 1874 | }; |
---|
1602 | 1875 | int ret = 0, i; |
---|
1603 | | - |
---|
1604 | | - snd_soc_disconnect_sync(&pdev->dev); |
---|
1605 | 1876 | |
---|
1606 | 1877 | pm_runtime_disable(&pdev->dev); |
---|
1607 | 1878 | |
---|