|
@@ -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.
|