forked from luck/tmp_suning_uos_patched
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>
This commit is contained in:
parent
ae1c696a48
commit
8fc9983db1
|
@ -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
|
* aio_port_set_rate - set sampling rate of LPCM
|
||||||
* @sub: the AIO substream pointer, PCM substream only
|
* @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);
|
rate = params_rate(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = aio_port_set_ch(sub);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = aio_port_set_rate(sub, rate);
|
ret = aio_port_set_rate(sub, rate);
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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)
|
int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through)
|
||||||
{
|
{
|
||||||
struct regmap *r = sub->aio->chip->regmap;
|
struct regmap *r = sub->aio->chip->regmap;
|
||||||
u32 v;
|
u32 memfmt, v;
|
||||||
|
|
||||||
if (sub->swm->dir == PORT_DIR_OUTPUT) {
|
if (sub->swm->dir == PORT_DIR_OUTPUT) {
|
||||||
if (pass_through)
|
if (pass_through) {
|
||||||
v = PBOUTMXCTR0_ENDIAN_0123 |
|
v = PBOUTMXCTR0_ENDIAN_0123 |
|
||||||
PBOUTMXCTR0_MEMFMT_STREAM;
|
PBOUTMXCTR0_MEMFMT_STREAM;
|
||||||
else
|
} else {
|
||||||
v = PBOUTMXCTR0_ENDIAN_3210 |
|
switch (params_channels(&sub->params)) {
|
||||||
PBOUTMXCTR0_MEMFMT_2CH;
|
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, PBOUTMXCTR0(sub->swm->oif.map), v);
|
||||||
regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0);
|
regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0);
|
||||||
|
|
|
@ -286,7 +286,7 @@ static struct snd_soc_dai_driver uniphier_aio_dai_ld11[] = {
|
||||||
.formats = SNDRV_PCM_FMTBIT_S32_LE,
|
.formats = SNDRV_PCM_FMTBIT_S32_LE,
|
||||||
.rates = SNDRV_PCM_RATE_48000,
|
.rates = SNDRV_PCM_RATE_48000,
|
||||||
.channels_min = 2,
|
.channels_min = 2,
|
||||||
.channels_max = 2,
|
.channels_max = 8,
|
||||||
},
|
},
|
||||||
.ops = &uniphier_aio_i2s_ops,
|
.ops = &uniphier_aio_i2s_ops,
|
||||||
},
|
},
|
||||||
|
|
|
@ -374,6 +374,7 @@
|
||||||
#define OPORTMXTYVOLGAINSTATUS(n, m) (0x42108 + 0x400 * (n) + 0x20 * (m))
|
#define OPORTMXTYVOLGAINSTATUS(n, m) (0x42108 + 0x400 * (n) + 0x20 * (m))
|
||||||
#define OPORTMXTYVOLGAINSTATUS_CUR_MASK GENMASK(15, 0)
|
#define OPORTMXTYVOLGAINSTATUS_CUR_MASK GENMASK(15, 0)
|
||||||
#define OPORTMXTYSLOTCTR(n, m) (0x42114 + 0x400 * (n) + 0x20 * (m))
|
#define OPORTMXTYSLOTCTR(n, m) (0x42114 + 0x400 * (n) + 0x20 * (m))
|
||||||
|
#define OPORTMXTYSLOTCTR_MODE BIT(15)
|
||||||
#define OPORTMXTYSLOTCTR_SLOTSEL_MASK GENMASK(11, 8)
|
#define OPORTMXTYSLOTCTR_SLOTSEL_MASK GENMASK(11, 8)
|
||||||
#define OPORTMXTYSLOTCTR_SLOTSEL_SLOT0 (0x8 << 8)
|
#define OPORTMXTYSLOTCTR_SLOTSEL_SLOT0 (0x8 << 8)
|
||||||
#define OPORTMXTYSLOTCTR_SLOTSEL_SLOT1 (0x9 << 8)
|
#define OPORTMXTYSLOTCTR_SLOTSEL_SLOT1 (0x9 << 8)
|
||||||
|
|
|
@ -141,6 +141,9 @@ enum IEC61937_PC {
|
||||||
#define AUD_MIN_FRAGMENT_SIZE (4 * 1024)
|
#define AUD_MIN_FRAGMENT_SIZE (4 * 1024)
|
||||||
#define AUD_MAX_FRAGMENT_SIZE (16 * 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.
|
* This is a selector for virtual register map of AIO.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue
Block a user