Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 8fc9983d authored by Katsuhiro Suzuki's avatar Katsuhiro Suzuki Committed by Mark Brown
Browse files

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: default avatarKatsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent ae1c696a
Loading
Loading
Loading
Loading
+73 −5
Original line number Diff line number Diff line
@@ -264,6 +264,57 @@ void aio_port_reset(struct uniphier_aio_sub *sub)
	}
}

/**
 * aio_port_set_ch - set channels of LPCM
 * @sub: the AIO substream pointer, PCM substream only
 * @ch : count of channels
 *
 * Set suitable slot selecting to input/output port block of AIO.
 *
 * This function may return error if non-PCM substream.
 *
 * Return: Zero if successful, otherwise a negative value on error.
 */
static int aio_port_set_ch(struct uniphier_aio_sub *sub)
{
	struct regmap *r = sub->aio->chip->regmap;
	u32 slotsel_2ch[] = {
		0, 0, 0, 0, 0,
	};
	u32 slotsel_multi[] = {
		OPORTMXTYSLOTCTR_SLOTSEL_SLOT0,
		OPORTMXTYSLOTCTR_SLOTSEL_SLOT1,
		OPORTMXTYSLOTCTR_SLOTSEL_SLOT2,
		OPORTMXTYSLOTCTR_SLOTSEL_SLOT3,
		OPORTMXTYSLOTCTR_SLOTSEL_SLOT4,
	};
	u32 mode, *slotsel;
	int i;

	switch (params_channels(&sub->params)) {
	case 8:
	case 6:
		mode = OPORTMXTYSLOTCTR_MODE;
		slotsel = slotsel_multi;
		break;
	case 2:
		mode = 0;
		slotsel = slotsel_2ch;
		break;
	default:
		return -EINVAL;
	}

	for (i = 0; i < AUD_MAX_SLOTSEL; i++) {
		regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i),
				   OPORTMXTYSLOTCTR_MODE, mode);
		regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i),
				   OPORTMXTYSLOTCTR_SLOTSEL_MASK, slotsel[i]);
	}

	return 0;
}

/**
 * aio_port_set_rate - set sampling rate of LPCM
 * @sub: the AIO substream pointer, PCM substream only
@@ -575,6 +626,10 @@ int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through,
			rate = params_rate(params);
		}

		ret = aio_port_set_ch(sub);
		if (ret)
			return ret;

		ret = aio_port_set_rate(sub, rate);
		if (ret)
			return ret;
@@ -731,15 +786,28 @@ void aio_port_set_volume(struct uniphier_aio_sub *sub, int vol)
int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through)
{
	struct regmap *r = sub->aio->chip->regmap;
	u32 v;
	u32 memfmt, v;

	if (sub->swm->dir == PORT_DIR_OUTPUT) {
		if (pass_through)
		if (pass_through) {
			v = PBOUTMXCTR0_ENDIAN_0123 |
				PBOUTMXCTR0_MEMFMT_STREAM;
		else
			v = PBOUTMXCTR0_ENDIAN_3210 |
				PBOUTMXCTR0_MEMFMT_2CH;
		} else {
			switch (params_channels(&sub->params)) {
			case 2:
				memfmt = PBOUTMXCTR0_MEMFMT_2CH;
				break;
			case 6:
				memfmt = PBOUTMXCTR0_MEMFMT_6CH;
				break;
			case 8:
				memfmt = PBOUTMXCTR0_MEMFMT_8CH;
				break;
			default:
				return -EINVAL;
			}
			v = PBOUTMXCTR0_ENDIAN_3210 | memfmt;
		}

		regmap_write(r, PBOUTMXCTR0(sub->swm->oif.map), v);
		regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0);
+1 −1
Original line number Diff line number Diff line
@@ -286,7 +286,7 @@ static struct snd_soc_dai_driver uniphier_aio_dai_ld11[] = {
			.formats     = SNDRV_PCM_FMTBIT_S32_LE,
			.rates       = SNDRV_PCM_RATE_48000,
			.channels_min = 2,
			.channels_max = 2,
			.channels_max = 8,
		},
		.ops = &uniphier_aio_i2s_ops,
	},
+1 −0
Original line number Diff line number Diff line
@@ -374,6 +374,7 @@
#define OPORTMXTYVOLGAINSTATUS(n, m)     (0x42108 + 0x400 * (n) + 0x20 * (m))
#define   OPORTMXTYVOLGAINSTATUS_CUR_MASK  GENMASK(15, 0)
#define OPORTMXTYSLOTCTR(n, m)           (0x42114 + 0x400 * (n) + 0x20 * (m))
#define   OPORTMXTYSLOTCTR_MODE            BIT(15)
#define   OPORTMXTYSLOTCTR_SLOTSEL_MASK    GENMASK(11, 8)
#define   OPORTMXTYSLOTCTR_SLOTSEL_SLOT0   (0x8 << 8)
#define   OPORTMXTYSLOTCTR_SLOTSEL_SLOT1   (0x9 << 8)
+3 −0
Original line number Diff line number Diff line
@@ -141,6 +141,9 @@ enum IEC61937_PC {
#define AUD_MIN_FRAGMENT_SIZE    (4 * 1024)
#define AUD_MAX_FRAGMENT_SIZE    (16 * 1024)

/* max 5 slots, 10 channels, 2 channel in 1 slot */
#define AUD_MAX_SLOTSEL    5

/*
 * This is a selector for virtual register map of AIO.
 *