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

ASoC: uniphier: add support for multichannel output

This patch adds multichannel PCM output support for LD11/LD20.
Currently driver tested and supported only 2ch, 6ch, and 8ch.

Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Katsuhiro Suzuki and committed by
Mark Brown
8fc9983d ae1c696a

+78 -6
+73 -5
sound/soc/uniphier/aio-core.c
··· 265 265 } 266 266 267 267 /** 268 + * aio_port_set_ch - set channels of LPCM 269 + * @sub: the AIO substream pointer, PCM substream only 270 + * @ch : count of channels 271 + * 272 + * Set suitable slot selecting to input/output port block of AIO. 273 + * 274 + * This function may return error if non-PCM substream. 275 + * 276 + * Return: Zero if successful, otherwise a negative value on error. 277 + */ 278 + static int aio_port_set_ch(struct uniphier_aio_sub *sub) 279 + { 280 + struct regmap *r = sub->aio->chip->regmap; 281 + u32 slotsel_2ch[] = { 282 + 0, 0, 0, 0, 0, 283 + }; 284 + u32 slotsel_multi[] = { 285 + OPORTMXTYSLOTCTR_SLOTSEL_SLOT0, 286 + OPORTMXTYSLOTCTR_SLOTSEL_SLOT1, 287 + OPORTMXTYSLOTCTR_SLOTSEL_SLOT2, 288 + OPORTMXTYSLOTCTR_SLOTSEL_SLOT3, 289 + OPORTMXTYSLOTCTR_SLOTSEL_SLOT4, 290 + }; 291 + u32 mode, *slotsel; 292 + int i; 293 + 294 + switch (params_channels(&sub->params)) { 295 + case 8: 296 + case 6: 297 + mode = OPORTMXTYSLOTCTR_MODE; 298 + slotsel = slotsel_multi; 299 + break; 300 + case 2: 301 + mode = 0; 302 + slotsel = slotsel_2ch; 303 + break; 304 + default: 305 + return -EINVAL; 306 + } 307 + 308 + for (i = 0; i < AUD_MAX_SLOTSEL; i++) { 309 + regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i), 310 + OPORTMXTYSLOTCTR_MODE, mode); 311 + regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i), 312 + OPORTMXTYSLOTCTR_SLOTSEL_MASK, slotsel[i]); 313 + } 314 + 315 + return 0; 316 + } 317 + 318 + /** 268 319 * aio_port_set_rate - set sampling rate of LPCM 269 320 * @sub: the AIO substream pointer, PCM substream only 270 321 * @rate: Sampling rate in Hz. ··· 626 575 rate = params_rate(params); 627 576 } 628 577 578 + ret = aio_port_set_ch(sub); 579 + if (ret) 580 + return ret; 581 + 629 582 ret = aio_port_set_rate(sub, rate); 630 583 if (ret) 631 584 return ret; ··· 786 731 int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through) 787 732 { 788 733 struct regmap *r = sub->aio->chip->regmap; 789 - u32 v; 734 + u32 memfmt, v; 790 735 791 736 if (sub->swm->dir == PORT_DIR_OUTPUT) { 792 - if (pass_through) 737 + if (pass_through) { 793 738 v = PBOUTMXCTR0_ENDIAN_0123 | 794 739 PBOUTMXCTR0_MEMFMT_STREAM; 795 - else 796 - v = PBOUTMXCTR0_ENDIAN_3210 | 797 - PBOUTMXCTR0_MEMFMT_2CH; 740 + } else { 741 + switch (params_channels(&sub->params)) { 742 + case 2: 743 + memfmt = PBOUTMXCTR0_MEMFMT_2CH; 744 + break; 745 + case 6: 746 + memfmt = PBOUTMXCTR0_MEMFMT_6CH; 747 + break; 748 + case 8: 749 + memfmt = PBOUTMXCTR0_MEMFMT_8CH; 750 + break; 751 + default: 752 + return -EINVAL; 753 + } 754 + v = PBOUTMXCTR0_ENDIAN_3210 | memfmt; 755 + } 798 756 799 757 regmap_write(r, PBOUTMXCTR0(sub->swm->oif.map), v); 800 758 regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0);
+1 -1
sound/soc/uniphier/aio-ld11.c
··· 286 286 .formats = SNDRV_PCM_FMTBIT_S32_LE, 287 287 .rates = SNDRV_PCM_RATE_48000, 288 288 .channels_min = 2, 289 - .channels_max = 2, 289 + .channels_max = 8, 290 290 }, 291 291 .ops = &uniphier_aio_i2s_ops, 292 292 },
+1
sound/soc/uniphier/aio-reg.h
··· 374 374 #define OPORTMXTYVOLGAINSTATUS(n, m) (0x42108 + 0x400 * (n) + 0x20 * (m)) 375 375 #define OPORTMXTYVOLGAINSTATUS_CUR_MASK GENMASK(15, 0) 376 376 #define OPORTMXTYSLOTCTR(n, m) (0x42114 + 0x400 * (n) + 0x20 * (m)) 377 + #define OPORTMXTYSLOTCTR_MODE BIT(15) 377 378 #define OPORTMXTYSLOTCTR_SLOTSEL_MASK GENMASK(11, 8) 378 379 #define OPORTMXTYSLOTCTR_SLOTSEL_SLOT0 (0x8 << 8) 379 380 #define OPORTMXTYSLOTCTR_SLOTSEL_SLOT1 (0x9 << 8)
+3
sound/soc/uniphier/aio.h
··· 141 141 #define AUD_MIN_FRAGMENT_SIZE (4 * 1024) 142 142 #define AUD_MAX_FRAGMENT_SIZE (16 * 1024) 143 143 144 + /* max 5 slots, 10 channels, 2 channel in 1 slot */ 145 + #define AUD_MAX_SLOTSEL 5 146 + 144 147 /* 145 148 * This is a selector for virtual register map of AIO. 146 149 *