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

Commit 44f948bd authored by Moise Gergaud's avatar Moise Gergaud Committed by Mark Brown
Browse files

ASoC: sti: helper functions for unip tdm slots configuration



- sti_uniperiph_set_tdm_slot: store tdm slot config in unip context
- sti_uniperiph_get_tdm_word_pos: configure unip tdm slots pos regs

Signed-off-by: default avatarMoise Gergaud <moise.gergaud@st.com>
Acked-by: default avatarArnaud Pouliquen <arnaud.pouliquen@st.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 9a00a3e9
Loading
Loading
Loading
Loading
+90 −0
Original line number Diff line number Diff line
@@ -10,6 +10,96 @@

#include "uniperif.h"

/*
 * User frame size shall be 2, 4, 6 or 8 32-bits words length
 * (i.e. 8, 16, 24 or 32 bytes)
 * This constraint comes from allowed values for
 * UNIPERIF_I2S_FMT_NUM_CH register
 */
#define UNIPERIF_MAX_FRAME_SZ 0x20
#define UNIPERIF_ALLOWED_FRAME_SZ (0x08 | 0x10 | 0x18 | UNIPERIF_MAX_FRAME_SZ)

int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
			       unsigned int rx_mask, int slots,
			       int slot_width)
{
	struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
	struct uniperif *uni = priv->dai_data.uni;
	int i, frame_size, avail_slots;

	if (!UNIPERIF_TYPE_IS_TDM(uni)) {
		dev_err(uni->dev, "cpu dai not in tdm mode\n");
		return -EINVAL;
	}

	/* store info in unip context */
	uni->tdm_slot.slots = slots;
	uni->tdm_slot.slot_width = slot_width;
	/* unip is unidirectionnal */
	uni->tdm_slot.mask = (tx_mask != 0) ? tx_mask : rx_mask;

	/* number of available timeslots */
	for (i = 0, avail_slots = 0; i < uni->tdm_slot.slots; i++) {
		if ((uni->tdm_slot.mask >> i) & 0x01)
			avail_slots++;
	}
	uni->tdm_slot.avail_slots = avail_slots;

	/* frame size in bytes */
	frame_size = uni->tdm_slot.avail_slots * uni->tdm_slot.slot_width / 8;

	/* check frame size is allowed */
	if ((frame_size > UNIPERIF_MAX_FRAME_SZ) ||
	    (frame_size & ~(int)UNIPERIF_ALLOWED_FRAME_SZ)) {
		dev_err(uni->dev, "frame size not allowed: %d bytes\n",
			frame_size);
		return -EINVAL;
	}

	return 0;
}

int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni,
				   unsigned int *word_pos)
{
	int slot_width = uni->tdm_slot.slot_width / 8;
	int slots_num = uni->tdm_slot.slots;
	unsigned int slots_mask = uni->tdm_slot.mask;
	int i, j, k;
	unsigned int word16_pos[4];

	/* word16_pos:
	 * word16_pos[0] = WORDX_LSB
	 * word16_pos[1] = WORDX_MSB,
	 * word16_pos[2] = WORDX+1_LSB
	 * word16_pos[3] = WORDX+1_MSB
	 */

	/* set unip word position */
	for (i = 0, j = 0, k = 0; (i < slots_num) && (k < WORD_MAX); i++) {
		if ((slots_mask >> i) & 0x01) {
			word16_pos[j] = i * slot_width;

			if (slot_width == 4) {
				word16_pos[j + 1] = word16_pos[j] + 2;
				j++;
			}
			j++;

			if (j > 3) {
				word_pos[k] = word16_pos[1] |
					      (word16_pos[0] << 8) |
					      (word16_pos[3] << 16) |
					      (word16_pos[2] << 24);
				j = 0;
				k++;
			}
		}
	}

	return 0;
}

/*
 * sti_uniperiph_dai_create_ctrl
 * This function is used to create Ctrl associated to DAI but also pcm device.
+23 −0
Original line number Diff line number Diff line
@@ -1270,6 +1270,14 @@ enum uniperif_iec958_encoding_mode {
	UNIPERIF_IEC958_ENCODING_MODE_ENCODED
};

enum uniperif_word_pos {
	WORD_1_2,
	WORD_3_4,
	WORD_5_6,
	WORD_7_8,
	WORD_MAX
};

struct uniperif_info {
	int id; /* instance value of the uniperipheral IP */
	enum uniperif_type type;
@@ -1281,6 +1289,13 @@ struct uniperif_iec958_settings {
	struct snd_aes_iec958 iec958;
};

struct dai_tdm_slot {
	unsigned int mask;
	int slots;
	int slot_width;
	unsigned int avail_slots;
};

struct uniperif {
	/* System information */
	struct uniperif_info *info;
@@ -1317,6 +1332,7 @@ struct uniperif {

	/* dai properties */
	unsigned int daifmt;
	struct dai_tdm_slot tdm_slot;

	/* DAI callbacks */
	const struct snd_soc_dai_ops *dai_ops;
@@ -1373,4 +1389,11 @@ int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params,
				struct snd_soc_dai *dai);

int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
			       unsigned int rx_mask, int slots,
			       int slot_width);

int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni,
				   unsigned int *word_pos);

#endif