summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2016-05-27 08:45:55 -0400
committerMark Brown <broonie@kernel.org>2016-05-27 08:45:55 -0400
commit77c92d2b4c6a65ef7e9ca0e7d574d4d48fd5efae (patch)
treea679783f49521f00b026b9475ef222b78519fb8e /sound
parent38e3c63da388f25c0b472a6624eb005076ea0dfb (diff)
parentee4c879b53eb5d757661b9bc8fcdf1a3d2e5fdfb (diff)
Merge remote-tracking branch 'asoc/topic/sti' into asoc-next
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/sti/sti_uniperif.c144
-rw-r--r--sound/soc/sti/uniperif.h220
-rw-r--r--sound/soc/sti/uniperif_player.c182
-rw-r--r--sound/soc/sti/uniperif_reader.c229
4 files changed, 646 insertions, 129 deletions
diff --git a/sound/soc/sti/sti_uniperif.c b/sound/soc/sti/sti_uniperif.c
index 39bcefe5eea0..488ef4ed8fba 100644
--- a/sound/soc/sti/sti_uniperif.c
+++ b/sound/soc/sti/sti_uniperif.c
@@ -11,6 +11,142 @@
11#include "uniperif.h" 11#include "uniperif.h"
12 12
13/* 13/*
14 * User frame size shall be 2, 4, 6 or 8 32-bits words length
15 * (i.e. 8, 16, 24 or 32 bytes)
16 * This constraint comes from allowed values for
17 * UNIPERIF_I2S_FMT_NUM_CH register
18 */
19#define UNIPERIF_MAX_FRAME_SZ 0x20
20#define UNIPERIF_ALLOWED_FRAME_SZ (0x08 | 0x10 | 0x18 | UNIPERIF_MAX_FRAME_SZ)
21
22int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
23 unsigned int rx_mask, int slots,
24 int slot_width)
25{
26 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
27 struct uniperif *uni = priv->dai_data.uni;
28 int i, frame_size, avail_slots;
29
30 if (!UNIPERIF_TYPE_IS_TDM(uni)) {
31 dev_err(uni->dev, "cpu dai not in tdm mode\n");
32 return -EINVAL;
33 }
34
35 /* store info in unip context */
36 uni->tdm_slot.slots = slots;
37 uni->tdm_slot.slot_width = slot_width;
38 /* unip is unidirectionnal */
39 uni->tdm_slot.mask = (tx_mask != 0) ? tx_mask : rx_mask;
40
41 /* number of available timeslots */
42 for (i = 0, avail_slots = 0; i < uni->tdm_slot.slots; i++) {
43 if ((uni->tdm_slot.mask >> i) & 0x01)
44 avail_slots++;
45 }
46 uni->tdm_slot.avail_slots = avail_slots;
47
48 /* frame size in bytes */
49 frame_size = uni->tdm_slot.avail_slots * uni->tdm_slot.slot_width / 8;
50
51 /* check frame size is allowed */
52 if ((frame_size > UNIPERIF_MAX_FRAME_SZ) ||
53 (frame_size & ~(int)UNIPERIF_ALLOWED_FRAME_SZ)) {
54 dev_err(uni->dev, "frame size not allowed: %d bytes\n",
55 frame_size);
56 return -EINVAL;
57 }
58
59 return 0;
60}
61
62int sti_uniperiph_fix_tdm_chan(struct snd_pcm_hw_params *params,
63 struct snd_pcm_hw_rule *rule)
64{
65 struct uniperif *uni = rule->private;
66 struct snd_interval t;
67
68 t.min = uni->tdm_slot.avail_slots;
69 t.max = uni->tdm_slot.avail_slots;
70 t.openmin = 0;
71 t.openmax = 0;
72 t.integer = 0;
73
74 return snd_interval_refine(hw_param_interval(params, rule->var), &t);
75}
76
77int sti_uniperiph_fix_tdm_format(struct snd_pcm_hw_params *params,
78 struct snd_pcm_hw_rule *rule)
79{
80 struct uniperif *uni = rule->private;
81 struct snd_mask *maskp = hw_param_mask(params, rule->var);
82 u64 format;
83
84 switch (uni->tdm_slot.slot_width) {
85 case 16:
86 format = SNDRV_PCM_FMTBIT_S16_LE;
87 break;
88 case 32:
89 format = SNDRV_PCM_FMTBIT_S32_LE;
90 break;
91 default:
92 dev_err(uni->dev, "format not supported: %d bits\n",
93 uni->tdm_slot.slot_width);
94 return -EINVAL;
95 }
96
97 maskp->bits[0] &= (u_int32_t)format;
98 maskp->bits[1] &= (u_int32_t)(format >> 32);
99 /* clear remaining indexes */
100 memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX - 64) / 8);
101
102 if (!maskp->bits[0] && !maskp->bits[1])
103 return -EINVAL;
104
105 return 0;
106}
107
108int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni,
109 unsigned int *word_pos)
110{
111 int slot_width = uni->tdm_slot.slot_width / 8;
112 int slots_num = uni->tdm_slot.slots;
113 unsigned int slots_mask = uni->tdm_slot.mask;
114 int i, j, k;
115 unsigned int word16_pos[4];
116
117 /* word16_pos:
118 * word16_pos[0] = WORDX_LSB
119 * word16_pos[1] = WORDX_MSB,
120 * word16_pos[2] = WORDX+1_LSB
121 * word16_pos[3] = WORDX+1_MSB
122 */
123
124 /* set unip word position */
125 for (i = 0, j = 0, k = 0; (i < slots_num) && (k < WORD_MAX); i++) {
126 if ((slots_mask >> i) & 0x01) {
127 word16_pos[j] = i * slot_width;
128
129 if (slot_width == 4) {
130 word16_pos[j + 1] = word16_pos[j] + 2;
131 j++;
132 }
133 j++;
134
135 if (j > 3) {
136 word_pos[k] = word16_pos[1] |
137 (word16_pos[0] << 8) |
138 (word16_pos[3] << 16) |
139 (word16_pos[2] << 24);
140 j = 0;
141 k++;
142 }
143 }
144 }
145
146 return 0;
147}
148
149/*
14 * sti_uniperiph_dai_create_ctrl 150 * sti_uniperiph_dai_create_ctrl
15 * This function is used to create Ctrl associated to DAI but also pcm device. 151 * This function is used to create Ctrl associated to DAI but also pcm device.
16 * Request is done by front end to associate ctrl with pcm device id 152 * Request is done by front end to associate ctrl with pcm device id
@@ -45,10 +181,16 @@ int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream,
45 struct snd_pcm_hw_params *params, 181 struct snd_pcm_hw_params *params,
46 struct snd_soc_dai *dai) 182 struct snd_soc_dai *dai)
47{ 183{
184 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
185 struct uniperif *uni = priv->dai_data.uni;
48 struct snd_dmaengine_dai_dma_data *dma_data; 186 struct snd_dmaengine_dai_dma_data *dma_data;
49 int transfer_size; 187 int transfer_size;
50 188
51 transfer_size = params_channels(params) * UNIPERIF_FIFO_FRAMES; 189 if (uni->info->type == SND_ST_UNIPERIF_TYPE_TDM)
190 /* transfer size = user frame size (in 32-bits FIFO cell) */
191 transfer_size = snd_soc_params_to_frame_size(params) / 32;
192 else
193 transfer_size = params_channels(params) * UNIPERIF_FIFO_FRAMES;
52 194
53 dma_data = snd_soc_dai_get_dma_data(dai, substream); 195 dma_data = snd_soc_dai_get_dma_data(dai, substream);
54 dma_data->maxburst = transfer_size; 196 dma_data->maxburst = transfer_size;
diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h
index f0fd5a9944e9..eb9933c62ad6 100644
--- a/sound/soc/sti/uniperif.h
+++ b/sound/soc/sti/uniperif.h
@@ -25,7 +25,7 @@
25 writel_relaxed((((value) & mask) << shift), ip->base + offset) 25 writel_relaxed((((value) & mask) << shift), ip->base + offset)
26 26
27/* 27/*
28 * AUD_UNIPERIF_SOFT_RST reg 28 * UNIPERIF_SOFT_RST reg
29 */ 29 */
30 30
31#define UNIPERIF_SOFT_RST_OFFSET(ip) 0x0000 31#define UNIPERIF_SOFT_RST_OFFSET(ip) 0x0000
@@ -50,7 +50,7 @@
50 UNIPERIF_SOFT_RST_SOFT_RST_MASK(ip)) 50 UNIPERIF_SOFT_RST_SOFT_RST_MASK(ip))
51 51
52/* 52/*
53 * AUD_UNIPERIF_FIFO_DATA reg 53 * UNIPERIF_FIFO_DATA reg
54 */ 54 */
55 55
56#define UNIPERIF_FIFO_DATA_OFFSET(ip) 0x0004 56#define UNIPERIF_FIFO_DATA_OFFSET(ip) 0x0004
@@ -58,7 +58,7 @@
58 writel_relaxed(value, ip->base + UNIPERIF_FIFO_DATA_OFFSET(ip)) 58 writel_relaxed(value, ip->base + UNIPERIF_FIFO_DATA_OFFSET(ip))
59 59
60/* 60/*
61 * AUD_UNIPERIF_CHANNEL_STA_REGN reg 61 * UNIPERIF_CHANNEL_STA_REGN reg
62 */ 62 */
63 63
64#define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n)) 64#define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n))
@@ -105,7 +105,7 @@
105 writel_relaxed(value, ip->base + UNIPERIF_CHANNEL_STA_REG5_OFFSET(ip)) 105 writel_relaxed(value, ip->base + UNIPERIF_CHANNEL_STA_REG5_OFFSET(ip))
106 106
107/* 107/*
108 * AUD_UNIPERIF_ITS reg 108 * UNIPERIF_ITS reg
109 */ 109 */
110 110
111#define UNIPERIF_ITS_OFFSET(ip) 0x000C 111#define UNIPERIF_ITS_OFFSET(ip) 0x000C
@@ -143,7 +143,7 @@
143 0 : (BIT(UNIPERIF_ITS_UNDERFLOW_REC_FAILED_SHIFT(ip)))) 143 0 : (BIT(UNIPERIF_ITS_UNDERFLOW_REC_FAILED_SHIFT(ip))))
144 144
145/* 145/*
146 * AUD_UNIPERIF_ITS_BCLR reg 146 * UNIPERIF_ITS_BCLR reg
147 */ 147 */
148 148
149/* FIFO_ERROR */ 149/* FIFO_ERROR */
@@ -160,7 +160,7 @@
160 writel_relaxed(value, ip->base + UNIPERIF_ITS_BCLR_OFFSET(ip)) 160 writel_relaxed(value, ip->base + UNIPERIF_ITS_BCLR_OFFSET(ip))
161 161
162/* 162/*
163 * AUD_UNIPERIF_ITM reg 163 * UNIPERIF_ITM reg
164 */ 164 */
165 165
166#define UNIPERIF_ITM_OFFSET(ip) 0x0018 166#define UNIPERIF_ITM_OFFSET(ip) 0x0018
@@ -188,7 +188,7 @@
188 0 : (BIT(UNIPERIF_ITM_UNDERFLOW_REC_FAILED_SHIFT(ip)))) 188 0 : (BIT(UNIPERIF_ITM_UNDERFLOW_REC_FAILED_SHIFT(ip))))
189 189
190/* 190/*
191 * AUD_UNIPERIF_ITM_BCLR reg 191 * UNIPERIF_ITM_BCLR reg
192 */ 192 */
193 193
194#define UNIPERIF_ITM_BCLR_OFFSET(ip) 0x001c 194#define UNIPERIF_ITM_BCLR_OFFSET(ip) 0x001c
@@ -213,7 +213,7 @@
213 UNIPERIF_ITM_BCLR_DMA_ERROR_MASK(ip)) 213 UNIPERIF_ITM_BCLR_DMA_ERROR_MASK(ip))
214 214
215/* 215/*
216 * AUD_UNIPERIF_ITM_BSET reg 216 * UNIPERIF_ITM_BSET reg
217 */ 217 */
218 218
219#define UNIPERIF_ITM_BSET_OFFSET(ip) 0x0020 219#define UNIPERIF_ITM_BSET_OFFSET(ip) 0x0020
@@ -767,7 +767,7 @@
767 SET_UNIPERIF_REG(ip, \ 767 SET_UNIPERIF_REG(ip, \
768 UNIPERIF_CTRL_OFFSET(ip), \ 768 UNIPERIF_CTRL_OFFSET(ip), \
769 UNIPERIF_CTRL_READER_OUT_SEL_SHIFT(ip), \ 769 UNIPERIF_CTRL_READER_OUT_SEL_SHIFT(ip), \
770 CORAUD_UNIPERIF_CTRL_READER_OUT_SEL_MASK(ip), 1) 770 UNIPERIF_CTRL_READER_OUT_SEL_MASK(ip), 1)
771 771
772/* UNDERFLOW_REC_WINDOW */ 772/* UNDERFLOW_REC_WINDOW */
773#define UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW_SHIFT(ip) 20 773#define UNIPERIF_CTRL_UNDERFLOW_REC_WINDOW_SHIFT(ip) 20
@@ -1046,7 +1046,7 @@
1046 UNIPERIF_STATUS_1_UNDERFLOW_DURATION_MASK(ip), value) 1046 UNIPERIF_STATUS_1_UNDERFLOW_DURATION_MASK(ip), value)
1047 1047
1048/* 1048/*
1049 * AUD_UNIPERIF_CHANNEL_STA_REGN reg 1049 * UNIPERIF_CHANNEL_STA_REGN reg
1050 */ 1050 */
1051 1051
1052#define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n)) 1052#define UNIPERIF_CHANNEL_STA_REGN(ip, n) (0x0060 + (4 * n))
@@ -1057,7 +1057,7 @@
1057 UNIPERIF_CHANNEL_STA_REGN(ip, n)) 1057 UNIPERIF_CHANNEL_STA_REGN(ip, n))
1058 1058
1059/* 1059/*
1060 * AUD_UNIPERIF_USER_VALIDITY reg 1060 * UNIPERIF_USER_VALIDITY reg
1061 */ 1061 */
1062 1062
1063#define UNIPERIF_USER_VALIDITY_OFFSET(ip) 0x0090 1063#define UNIPERIF_USER_VALIDITY_OFFSET(ip) 0x0090
@@ -1101,12 +1101,136 @@
1101 UNIPERIF_DBG_STANDBY_LEFT_SP_MASK(ip), value) 1101 UNIPERIF_DBG_STANDBY_LEFT_SP_MASK(ip), value)
1102 1102
1103/* 1103/*
1104 * UNIPERIF_TDM_ENABLE
1105 */
1106#define UNIPERIF_TDM_ENABLE_OFFSET(ip) 0x0118
1107#define GET_UNIPERIF_TDM_ENABLE(ip) \
1108 readl_relaxed(ip->base + UNIPERIF_TDM_ENABLE_OFFSET(ip))
1109#define SET_UNIPERIF_TDM_ENABLE(ip, value) \
1110 writel_relaxed(value, ip->base + UNIPERIF_TDM_ENABLE_OFFSET(ip))
1111
1112/* TDM_ENABLE */
1113#define UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip) 0x0
1114#define UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip) 0x1
1115#define GET_UNIPERIF_TDM_ENABLE_EN_TDM(ip) \
1116 GET_UNIPERIF_REG(ip, \
1117 UNIPERIF_TDM_ENABLE_OFFSET(ip), \
1118 UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip), \
1119 UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip))
1120#define SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(ip) \
1121 SET_UNIPERIF_REG(ip, \
1122 UNIPERIF_TDM_ENABLE_OFFSET(ip), \
1123 UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip), \
1124 UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip), 1)
1125#define SET_UNIPERIF_TDM_ENABLE_TDM_DISABLE(ip) \
1126 SET_UNIPERIF_REG(ip, \
1127 UNIPERIF_TDM_ENABLE_OFFSET(ip), \
1128 UNIPERIF_TDM_ENABLE_EN_TDM_SHIFT(ip), \
1129 UNIPERIF_TDM_ENABLE_EN_TDM_MASK(ip), 0)
1130
1131/*
1132 * UNIPERIF_TDM_FS_REF_FREQ
1133 */
1134#define UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip) 0x011c
1135#define GET_UNIPERIF_TDM_FS_REF_FREQ(ip) \
1136 readl_relaxed(ip->base + UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip))
1137#define SET_UNIPERIF_TDM_FS_REF_FREQ(ip, value) \
1138 writel_relaxed(value, ip->base + \
1139 UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip))
1140
1141/* REF_FREQ */
1142#define UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip) 0x0
1143#define VALUE_UNIPERIF_TDM_FS_REF_FREQ_8KHZ(ip) 0
1144#define VALUE_UNIPERIF_TDM_FS_REF_FREQ_16KHZ(ip) 1
1145#define VALUE_UNIPERIF_TDM_FS_REF_FREQ_32KHZ(ip) 2
1146#define VALUE_UNIPERIF_TDM_FS_REF_FREQ_48KHZ(ip) 3
1147#define UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip) 0x3
1148#define GET_UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ(ip) \
1149 GET_UNIPERIF_REG(ip, \
1150 UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \
1151 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \
1152 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip))
1153#define SET_UNIPERIF_TDM_FS_REF_FREQ_8KHZ(ip) \
1154 SET_UNIPERIF_REG(ip, \
1155 UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \
1156 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \
1157 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \
1158 VALUE_UNIPERIF_TDM_FS_REF_FREQ_8KHZ(ip))
1159#define SET_UNIPERIF_TDM_FS_REF_FREQ_16KHZ(ip) \
1160 SET_UNIPERIF_REG(ip, \
1161 UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \
1162 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \
1163 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \
1164 VALUE_UNIPERIF_TDM_FS_REF_FREQ_16KHZ(ip))
1165#define SET_UNIPERIF_TDM_FS_REF_FREQ_32KHZ(ip) \
1166 SET_UNIPERIF_REG(ip, \
1167 UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \
1168 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \
1169 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \
1170 VALUE_UNIPERIF_TDM_FS_REF_FREQ_32KHZ(ip))
1171#define SET_UNIPERIF_TDM_FS_REF_FREQ_48KHZ(ip) \
1172 SET_UNIPERIF_REG(ip, \
1173 UNIPERIF_TDM_FS_REF_FREQ_OFFSET(ip), \
1174 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_SHIFT(ip), \
1175 UNIPERIF_TDM_FS_REF_FREQ_REF_FREQ_MASK(ip), \
1176 VALUE_UNIPERIF_TDM_FS_REF_FREQ_48KHZ(ip))
1177
1178/*
1179 * UNIPERIF_TDM_FS_REF_DIV
1180 */
1181#define UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip) 0x0120
1182#define GET_UNIPERIF_TDM_FS_REF_DIV(ip) \
1183 readl_relaxed(ip->base + UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip))
1184#define SET_UNIPERIF_TDM_FS_REF_DIV(ip, value) \
1185 writel_relaxed(value, ip->base + \
1186 UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip))
1187
1188/* NUM_TIMESLOT */
1189#define UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_SHIFT(ip) 0x0
1190#define UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_MASK(ip) 0xff
1191#define GET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(ip) \
1192 GET_UNIPERIF_REG(ip, \
1193 UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip), \
1194 UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_SHIFT(ip), \
1195 UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_MASK(ip))
1196#define SET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(ip, value) \
1197 SET_UNIPERIF_REG(ip, \
1198 UNIPERIF_TDM_FS_REF_DIV_OFFSET(ip), \
1199 UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_SHIFT(ip), \
1200 UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT_MASK(ip), value)
1201
1202/*
1203 * UNIPERIF_TDM_WORD_POS_X_Y
1204 * 32 bits of UNIPERIF_TDM_WORD_POS_X_Y register shall be set in 1 shot
1205 */
1206#define UNIPERIF_TDM_WORD_POS_1_2_OFFSET(ip) 0x013c
1207#define UNIPERIF_TDM_WORD_POS_3_4_OFFSET(ip) 0x0140
1208#define UNIPERIF_TDM_WORD_POS_5_6_OFFSET(ip) 0x0144
1209#define UNIPERIF_TDM_WORD_POS_7_8_OFFSET(ip) 0x0148
1210#define GET_UNIPERIF_TDM_WORD_POS(ip, words) \
1211 readl_relaxed(ip->base + UNIPERIF_TDM_WORD_POS_##words##_OFFSET(ip))
1212#define SET_UNIPERIF_TDM_WORD_POS(ip, words, value) \
1213 writel_relaxed(value, ip->base + \
1214 UNIPERIF_TDM_WORD_POS_##words##_OFFSET(ip))
1215/*
1104 * uniperipheral IP capabilities 1216 * uniperipheral IP capabilities
1105 */ 1217 */
1106 1218
1107#define UNIPERIF_FIFO_SIZE 70 /* FIFO is 70 cells deep */ 1219#define UNIPERIF_FIFO_SIZE 70 /* FIFO is 70 cells deep */
1108#define UNIPERIF_FIFO_FRAMES 4 /* FDMA trigger limit in frames */ 1220#define UNIPERIF_FIFO_FRAMES 4 /* FDMA trigger limit in frames */
1109 1221
1222#define UNIPERIF_TYPE_IS_HDMI(p) \
1223 ((p)->info->type == SND_ST_UNIPERIF_TYPE_HDMI)
1224#define UNIPERIF_TYPE_IS_PCM(p) \
1225 ((p)->info->type == SND_ST_UNIPERIF_TYPE_PCM)
1226#define UNIPERIF_TYPE_IS_SPDIF(p) \
1227 ((p)->info->type == SND_ST_UNIPERIF_TYPE_SPDIF)
1228#define UNIPERIF_TYPE_IS_IEC958(p) \
1229 (UNIPERIF_TYPE_IS_HDMI(p) || \
1230 UNIPERIF_TYPE_IS_SPDIF(p))
1231#define UNIPERIF_TYPE_IS_TDM(p) \
1232 ((p)->info->type == SND_ST_UNIPERIF_TYPE_TDM)
1233
1110/* 1234/*
1111 * Uniperipheral IP revisions 1235 * Uniperipheral IP revisions
1112 */ 1236 */
@@ -1125,10 +1249,11 @@ enum uniperif_version {
1125}; 1249};
1126 1250
1127enum uniperif_type { 1251enum uniperif_type {
1128 SND_ST_UNIPERIF_PLAYER_TYPE_NONE, 1252 SND_ST_UNIPERIF_TYPE_NONE,
1129 SND_ST_UNIPERIF_PLAYER_TYPE_HDMI, 1253 SND_ST_UNIPERIF_TYPE_HDMI,
1130 SND_ST_UNIPERIF_PLAYER_TYPE_PCM, 1254 SND_ST_UNIPERIF_TYPE_PCM,
1131 SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF 1255 SND_ST_UNIPERIF_TYPE_SPDIF,
1256 SND_ST_UNIPERIF_TYPE_TDM
1132}; 1257};
1133 1258
1134enum uniperif_state { 1259enum uniperif_state {
@@ -1145,9 +1270,17 @@ enum uniperif_iec958_encoding_mode {
1145 UNIPERIF_IEC958_ENCODING_MODE_ENCODED 1270 UNIPERIF_IEC958_ENCODING_MODE_ENCODED
1146}; 1271};
1147 1272
1273enum uniperif_word_pos {
1274 WORD_1_2,
1275 WORD_3_4,
1276 WORD_5_6,
1277 WORD_7_8,
1278 WORD_MAX
1279};
1280
1148struct uniperif_info { 1281struct uniperif_info {
1149 int id; /* instance value of the uniperipheral IP */ 1282 int id; /* instance value of the uniperipheral IP */
1150 enum uniperif_type player_type; 1283 enum uniperif_type type;
1151 int underflow_enabled; /* Underflow recovery mode */ 1284 int underflow_enabled; /* Underflow recovery mode */
1152}; 1285};
1153 1286
@@ -1156,12 +1289,20 @@ struct uniperif_iec958_settings {
1156 struct snd_aes_iec958 iec958; 1289 struct snd_aes_iec958 iec958;
1157}; 1290};
1158 1291
1292struct dai_tdm_slot {
1293 unsigned int mask;
1294 int slots;
1295 int slot_width;
1296 unsigned int avail_slots;
1297};
1298
1159struct uniperif { 1299struct uniperif {
1160 /* System information */ 1300 /* System information */
1161 struct uniperif_info *info; 1301 struct uniperif_info *info;
1162 struct device *dev; 1302 struct device *dev;
1163 int ver; /* IP version, used by register access macros */ 1303 int ver; /* IP version, used by register access macros */
1164 struct regmap_field *clk_sel; 1304 struct regmap_field *clk_sel;
1305 struct regmap_field *valid_sel;
1165 1306
1166 /* capabilities */ 1307 /* capabilities */
1167 const struct snd_pcm_hardware *hw; 1308 const struct snd_pcm_hardware *hw;
@@ -1192,6 +1333,7 @@ struct uniperif {
1192 1333
1193 /* dai properties */ 1334 /* dai properties */
1194 unsigned int daifmt; 1335 unsigned int daifmt;
1336 struct dai_tdm_slot tdm_slot;
1195 1337
1196 /* DAI callbacks */ 1338 /* DAI callbacks */
1197 const struct snd_soc_dai_ops *dai_ops; 1339 const struct snd_soc_dai_ops *dai_ops;
@@ -1209,6 +1351,28 @@ struct sti_uniperiph_data {
1209 struct sti_uniperiph_dai dai_data; 1351 struct sti_uniperiph_dai dai_data;
1210}; 1352};
1211 1353
1354static const struct snd_pcm_hardware uni_tdm_hw = {
1355 .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
1356 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP |
1357 SNDRV_PCM_INFO_MMAP_VALID,
1358
1359 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE,
1360
1361 .rates = SNDRV_PCM_RATE_CONTINUOUS,
1362 .rate_min = 8000,
1363 .rate_max = 48000,
1364
1365 .channels_min = 1,
1366 .channels_max = 32,
1367
1368 .periods_min = 2,
1369 .periods_max = 10,
1370
1371 .period_bytes_min = 128,
1372 .period_bytes_max = 64 * PAGE_SIZE,
1373 .buffer_bytes_max = 256 * PAGE_SIZE
1374};
1375
1212/* uniperiph player*/ 1376/* uniperiph player*/
1213int uni_player_init(struct platform_device *pdev, 1377int uni_player_init(struct platform_device *pdev,
1214 struct uniperif *uni_player); 1378 struct uniperif *uni_player);
@@ -1226,4 +1390,28 @@ int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream,
1226 struct snd_pcm_hw_params *params, 1390 struct snd_pcm_hw_params *params,
1227 struct snd_soc_dai *dai); 1391 struct snd_soc_dai *dai);
1228 1392
1393static inline int sti_uniperiph_get_user_frame_size(
1394 struct snd_pcm_runtime *runtime)
1395{
1396 return (runtime->channels * snd_pcm_format_width(runtime->format) / 8);
1397}
1398
1399static inline int sti_uniperiph_get_unip_tdm_frame_size(struct uniperif *uni)
1400{
1401 return (uni->tdm_slot.slots * uni->tdm_slot.slot_width / 8);
1402}
1403
1404int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
1405 unsigned int rx_mask, int slots,
1406 int slot_width);
1407
1408int sti_uniperiph_get_tdm_word_pos(struct uniperif *uni,
1409 unsigned int *word_pos);
1410
1411int sti_uniperiph_fix_tdm_chan(struct snd_pcm_hw_params *params,
1412 struct snd_pcm_hw_rule *rule);
1413
1414int sti_uniperiph_fix_tdm_format(struct snd_pcm_hw_params *params,
1415 struct snd_pcm_hw_rule *rule);
1416
1229#endif 1417#endif
diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c
index 7aca6b92f718..ee1c7c245bc7 100644
--- a/sound/soc/sti/uniperif_player.c
+++ b/sound/soc/sti/uniperif_player.c
@@ -21,23 +21,14 @@
21 21
22/* sys config registers definitions */ 22/* sys config registers definitions */
23#define SYS_CFG_AUDIO_GLUE 0xA4 23#define SYS_CFG_AUDIO_GLUE 0xA4
24#define SYS_CFG_AUDI0_GLUE_PCM_CLKX 8
25 24
26/* 25/*
27 * Driver specific types. 26 * Driver specific types.
28 */ 27 */
29#define UNIPERIF_PLAYER_TYPE_IS_HDMI(p) \
30 ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_HDMI)
31#define UNIPERIF_PLAYER_TYPE_IS_PCM(p) \
32 ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_PCM)
33#define UNIPERIF_PLAYER_TYPE_IS_SPDIF(p) \
34 ((p)->info->player_type == SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF)
35#define UNIPERIF_PLAYER_TYPE_IS_IEC958(p) \
36 (UNIPERIF_PLAYER_TYPE_IS_HDMI(p) || \
37 UNIPERIF_PLAYER_TYPE_IS_SPDIF(p))
38 28
39#define UNIPERIF_PLAYER_CLK_ADJ_MIN -999999 29#define UNIPERIF_PLAYER_CLK_ADJ_MIN -999999
40#define UNIPERIF_PLAYER_CLK_ADJ_MAX 1000000 30#define UNIPERIF_PLAYER_CLK_ADJ_MAX 1000000
31#define UNIPERIF_PLAYER_I2S_OUT 1 /* player id connected to I2S/TDM TX bus */
41 32
42/* 33/*
43 * Note: snd_pcm_hardware is linked to DMA controller but is declared here to 34 * Note: snd_pcm_hardware is linked to DMA controller but is declared here to
@@ -444,18 +435,11 @@ static int uni_player_prepare_pcm(struct uniperif *player,
444 435
445 /* Force slot width to 32 in I2S mode (HW constraint) */ 436 /* Force slot width to 32 in I2S mode (HW constraint) */
446 if ((player->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == 437 if ((player->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
447 SND_SOC_DAIFMT_I2S) { 438 SND_SOC_DAIFMT_I2S)
448 slot_width = 32; 439 slot_width = 32;
449 } else { 440 else
450 switch (runtime->format) { 441 slot_width = snd_pcm_format_width(runtime->format);
451 case SNDRV_PCM_FORMAT_S16_LE: 442
452 slot_width = 16;
453 break;
454 default:
455 slot_width = 32;
456 break;
457 }
458 }
459 output_frame_size = slot_width * runtime->channels; 443 output_frame_size = slot_width * runtime->channels;
460 444
461 clk_div = player->mclk / runtime->rate; 445 clk_div = player->mclk / runtime->rate;
@@ -530,7 +514,6 @@ static int uni_player_prepare_pcm(struct uniperif *player,
530 SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(player); 514 SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(player);
531 515
532 SET_UNIPERIF_I2S_FMT_ORDER_MSB(player); 516 SET_UNIPERIF_I2S_FMT_ORDER_MSB(player);
533 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(player);
534 517
535 /* No iec958 formatting as outputting to DAC */ 518 /* No iec958 formatting as outputting to DAC */
536 SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(player); 519 SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(player);
@@ -538,6 +521,55 @@ static int uni_player_prepare_pcm(struct uniperif *player,
538 return 0; 521 return 0;
539} 522}
540 523
524static int uni_player_prepare_tdm(struct uniperif *player,
525 struct snd_pcm_runtime *runtime)
526{
527 int tdm_frame_size; /* unip tdm frame size in bytes */
528 int user_frame_size; /* user tdm frame size in bytes */
529 /* default unip TDM_WORD_POS_X_Y */
530 unsigned int word_pos[4] = {
531 0x04060002, 0x0C0E080A, 0x14161012, 0x1C1E181A};
532 int freq, ret;
533
534 tdm_frame_size =
535 sti_uniperiph_get_unip_tdm_frame_size(player);
536 user_frame_size =
537 sti_uniperiph_get_user_frame_size(runtime);
538
539 /* fix 16/0 format */
540 SET_UNIPERIF_CONFIG_MEM_FMT_16_0(player);
541 SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(player);
542
543 /* number of words inserted on the TDM line */
544 SET_UNIPERIF_I2S_FMT_NUM_CH(player, user_frame_size / 4 / 2);
545
546 SET_UNIPERIF_I2S_FMT_ORDER_MSB(player);
547 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(player);
548
549 /* Enable the tdm functionality */
550 SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(player);
551
552 /* number of 8 bits timeslots avail in unip tdm frame */
553 SET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESLOT(player, tdm_frame_size);
554
555 /* set the timeslot allocation for words in FIFO */
556 sti_uniperiph_get_tdm_word_pos(player, word_pos);
557 SET_UNIPERIF_TDM_WORD_POS(player, 1_2, word_pos[WORD_1_2]);
558 SET_UNIPERIF_TDM_WORD_POS(player, 3_4, word_pos[WORD_3_4]);
559 SET_UNIPERIF_TDM_WORD_POS(player, 5_6, word_pos[WORD_5_6]);
560 SET_UNIPERIF_TDM_WORD_POS(player, 7_8, word_pos[WORD_7_8]);
561
562 /* set unip clk rate (not done vai set_sysclk ops) */
563 freq = runtime->rate * tdm_frame_size * 8;
564 mutex_lock(&player->ctrl_lock);
565 ret = uni_player_clk_set_rate(player, freq);
566 if (!ret)
567 player->mclk = freq;
568 mutex_unlock(&player->ctrl_lock);
569
570 return 0;
571}
572
541/* 573/*
542 * ALSA uniperipheral iec958 controls 574 * ALSA uniperipheral iec958 controls
543 */ 575 */
@@ -668,11 +700,29 @@ static int uni_player_startup(struct snd_pcm_substream *substream,
668{ 700{
669 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); 701 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
670 struct uniperif *player = priv->dai_data.uni; 702 struct uniperif *player = priv->dai_data.uni;
703 int ret;
704
671 player->substream = substream; 705 player->substream = substream;
672 706
673 player->clk_adj = 0; 707 player->clk_adj = 0;
674 708
675 return 0; 709 if (!UNIPERIF_TYPE_IS_TDM(player))
710 return 0;
711
712 /* refine hw constraint in tdm mode */
713 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
714 SNDRV_PCM_HW_PARAM_CHANNELS,
715 sti_uniperiph_fix_tdm_chan,
716 player, SNDRV_PCM_HW_PARAM_CHANNELS,
717 -1);
718 if (ret < 0)
719 return ret;
720
721 return snd_pcm_hw_rule_add(substream->runtime, 0,
722 SNDRV_PCM_HW_PARAM_FORMAT,
723 sti_uniperiph_fix_tdm_format,
724 player, SNDRV_PCM_HW_PARAM_FORMAT,
725 -1);
676} 726}
677 727
678static int uni_player_set_sysclk(struct snd_soc_dai *dai, int clk_id, 728static int uni_player_set_sysclk(struct snd_soc_dai *dai, int clk_id,
@@ -682,7 +732,7 @@ static int uni_player_set_sysclk(struct snd_soc_dai *dai, int clk_id,
682 struct uniperif *player = priv->dai_data.uni; 732 struct uniperif *player = priv->dai_data.uni;
683 int ret; 733 int ret;
684 734
685 if (dir == SND_SOC_CLOCK_IN) 735 if (UNIPERIF_TYPE_IS_TDM(player) || (dir == SND_SOC_CLOCK_IN))
686 return 0; 736 return 0;
687 737
688 if (clk_id != 0) 738 if (clk_id != 0)
@@ -714,7 +764,13 @@ static int uni_player_prepare(struct snd_pcm_substream *substream,
714 } 764 }
715 765
716 /* Calculate transfer size (in fifo cells and bytes) for frame count */ 766 /* Calculate transfer size (in fifo cells and bytes) for frame count */
717 transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES; 767 if (player->info->type == SND_ST_UNIPERIF_TYPE_TDM) {
768 /* transfer size = user frame size (in 32 bits FIFO cell) */
769 transfer_size =
770 sti_uniperiph_get_user_frame_size(runtime) / 4;
771 } else {
772 transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES;
773 }
718 774
719 /* Calculate number of empty cells available before asserting DREQ */ 775 /* Calculate number of empty cells available before asserting DREQ */
720 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) { 776 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) {
@@ -738,16 +794,19 @@ static int uni_player_prepare(struct snd_pcm_substream *substream,
738 SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(player, trigger_limit); 794 SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(player, trigger_limit);
739 795
740 /* Uniperipheral setup depends on player type */ 796 /* Uniperipheral setup depends on player type */
741 switch (player->info->player_type) { 797 switch (player->info->type) {
742 case SND_ST_UNIPERIF_PLAYER_TYPE_HDMI: 798 case SND_ST_UNIPERIF_TYPE_HDMI:
743 ret = uni_player_prepare_iec958(player, runtime); 799 ret = uni_player_prepare_iec958(player, runtime);
744 break; 800 break;
745 case SND_ST_UNIPERIF_PLAYER_TYPE_PCM: 801 case SND_ST_UNIPERIF_TYPE_PCM:
746 ret = uni_player_prepare_pcm(player, runtime); 802 ret = uni_player_prepare_pcm(player, runtime);
747 break; 803 break;
748 case SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF: 804 case SND_ST_UNIPERIF_TYPE_SPDIF:
749 ret = uni_player_prepare_iec958(player, runtime); 805 ret = uni_player_prepare_iec958(player, runtime);
750 break; 806 break;
807 case SND_ST_UNIPERIF_TYPE_TDM:
808 ret = uni_player_prepare_tdm(player, runtime);
809 break;
751 default: 810 default:
752 dev_err(player->dev, "invalid player type"); 811 dev_err(player->dev, "invalid player type");
753 return -EINVAL; 812 return -EINVAL;
@@ -852,8 +911,8 @@ static int uni_player_start(struct uniperif *player)
852 * will not take affect and hang the player. 911 * will not take affect and hang the player.
853 */ 912 */
854 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) 913 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0)
855 if (UNIPERIF_PLAYER_TYPE_IS_IEC958(player)) 914 if (UNIPERIF_TYPE_IS_IEC958(player))
856 SET_UNIPERIF_CTRL_SPDIF_FMT_ON(player); 915 SET_UNIPERIF_CTRL_SPDIF_FMT_ON(player);
857 916
858 /* Force channel status update (no update if clk disable) */ 917 /* Force channel status update (no update if clk disable) */
859 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) 918 if (player->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0)
@@ -954,27 +1013,30 @@ static void uni_player_shutdown(struct snd_pcm_substream *substream,
954 player->substream = NULL; 1013 player->substream = NULL;
955} 1014}
956 1015
957static int uni_player_parse_dt_clk_glue(struct platform_device *pdev, 1016static int uni_player_parse_dt_audio_glue(struct platform_device *pdev,
958 struct uniperif *player) 1017 struct uniperif *player)
959{ 1018{
960 int bit_offset;
961 struct device_node *node = pdev->dev.of_node; 1019 struct device_node *node = pdev->dev.of_node;
962 struct regmap *regmap; 1020 struct regmap *regmap;
963 1021 struct reg_field regfield[2] = {
964 bit_offset = SYS_CFG_AUDI0_GLUE_PCM_CLKX + player->info->id; 1022 /* PCM_CLK_SEL */
1023 REG_FIELD(SYS_CFG_AUDIO_GLUE,
1024 8 + player->info->id,
1025 8 + player->info->id),
1026 /* PCMP_VALID_SEL */
1027 REG_FIELD(SYS_CFG_AUDIO_GLUE, 0, 1)
1028 };
965 1029
966 regmap = syscon_regmap_lookup_by_phandle(node, "st,syscfg"); 1030 regmap = syscon_regmap_lookup_by_phandle(node, "st,syscfg");
967 1031
968 if (regmap) { 1032 if (!regmap) {
969 struct reg_field regfield =
970 REG_FIELD(SYS_CFG_AUDIO_GLUE, bit_offset, bit_offset);
971
972 player->clk_sel = regmap_field_alloc(regmap, regfield);
973 } else {
974 dev_err(&pdev->dev, "sti-audio-clk-glue syscf not found\n"); 1033 dev_err(&pdev->dev, "sti-audio-clk-glue syscf not found\n");
975 return -EINVAL; 1034 return -EINVAL;
976 } 1035 }
977 1036
1037 player->clk_sel = regmap_field_alloc(regmap, regfield[0]);
1038 player->valid_sel = regmap_field_alloc(regmap, regfield[1]);
1039
978 return 0; 1040 return 0;
979} 1041}
980 1042
@@ -1012,19 +1074,21 @@ static int uni_player_parse_dt(struct platform_device *pdev,
1012 } 1074 }
1013 1075
1014 if (strcasecmp(mode, "hdmi") == 0) 1076 if (strcasecmp(mode, "hdmi") == 0)
1015 info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_HDMI; 1077 info->type = SND_ST_UNIPERIF_TYPE_HDMI;
1016 else if (strcasecmp(mode, "pcm") == 0) 1078 else if (strcasecmp(mode, "pcm") == 0)
1017 info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_PCM; 1079 info->type = SND_ST_UNIPERIF_TYPE_PCM;
1018 else if (strcasecmp(mode, "spdif") == 0) 1080 else if (strcasecmp(mode, "spdif") == 0)
1019 info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_SPDIF; 1081 info->type = SND_ST_UNIPERIF_TYPE_SPDIF;
1082 else if (strcasecmp(mode, "tdm") == 0)
1083 info->type = SND_ST_UNIPERIF_TYPE_TDM;
1020 else 1084 else
1021 info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_NONE; 1085 info->type = SND_ST_UNIPERIF_TYPE_NONE;
1022 1086
1023 /* Save the info structure */ 1087 /* Save the info structure */
1024 player->info = info; 1088 player->info = info;
1025 1089
1026 /* Get the PCM_CLK_SEL bit from audio-glue-ctrl SoC register */ 1090 /* Get PCM_CLK_SEL & PCMP_VALID_SEL from audio-glue-ctrl SoC reg */
1027 if (uni_player_parse_dt_clk_glue(pdev, player)) 1091 if (uni_player_parse_dt_audio_glue(pdev, player))
1028 return -EINVAL; 1092 return -EINVAL;
1029 1093
1030 return 0; 1094 return 0;
@@ -1037,7 +1101,8 @@ static const struct snd_soc_dai_ops uni_player_dai_ops = {
1037 .trigger = uni_player_trigger, 1101 .trigger = uni_player_trigger,
1038 .hw_params = sti_uniperiph_dai_hw_params, 1102 .hw_params = sti_uniperiph_dai_hw_params,
1039 .set_fmt = sti_uniperiph_dai_set_fmt, 1103 .set_fmt = sti_uniperiph_dai_set_fmt,
1040 .set_sysclk = uni_player_set_sysclk 1104 .set_sysclk = uni_player_set_sysclk,
1105 .set_tdm_slot = sti_uniperiph_set_tdm_slot
1041}; 1106};
1042 1107
1043int uni_player_init(struct platform_device *pdev, 1108int uni_player_init(struct platform_device *pdev,
@@ -1047,7 +1112,6 @@ int uni_player_init(struct platform_device *pdev,
1047 1112
1048 player->dev = &pdev->dev; 1113 player->dev = &pdev->dev;
1049 player->state = UNIPERIF_STATE_STOPPED; 1114 player->state = UNIPERIF_STATE_STOPPED;
1050 player->hw = &uni_player_pcm_hw;
1051 player->dai_ops = &uni_player_dai_ops; 1115 player->dai_ops = &uni_player_dai_ops;
1052 1116
1053 ret = uni_player_parse_dt(pdev, player); 1117 ret = uni_player_parse_dt(pdev, player);
@@ -1057,6 +1121,11 @@ int uni_player_init(struct platform_device *pdev,
1057 return ret; 1121 return ret;
1058 } 1122 }
1059 1123
1124 if (UNIPERIF_TYPE_IS_TDM(player))
1125 player->hw = &uni_tdm_hw;
1126 else
1127 player->hw = &uni_player_pcm_hw;
1128
1060 /* Get uniperif resource */ 1129 /* Get uniperif resource */
1061 player->clk = of_clk_get(pdev->dev.of_node, 0); 1130 player->clk = of_clk_get(pdev->dev.of_node, 0);
1062 if (IS_ERR(player->clk)) 1131 if (IS_ERR(player->clk))
@@ -1073,6 +1142,17 @@ int uni_player_init(struct platform_device *pdev,
1073 } 1142 }
1074 } 1143 }
1075 1144
1145 /* connect to I2S/TDM TX bus */
1146 if (player->valid_sel &&
1147 (player->info->id == UNIPERIF_PLAYER_I2S_OUT)) {
1148 ret = regmap_field_write(player->valid_sel, player->info->id);
1149 if (ret) {
1150 dev_err(player->dev,
1151 "%s: unable to connect to tdm bus", __func__);
1152 return ret;
1153 }
1154 }
1155
1076 ret = devm_request_irq(&pdev->dev, player->irq, 1156 ret = devm_request_irq(&pdev->dev, player->irq,
1077 uni_player_irq_handler, IRQF_SHARED, 1157 uni_player_irq_handler, IRQF_SHARED,
1078 dev_name(&pdev->dev), player); 1158 dev_name(&pdev->dev), player);
@@ -1087,7 +1167,7 @@ int uni_player_init(struct platform_device *pdev,
1087 SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player); 1167 SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player);
1088 SET_UNIPERIF_CONFIG_IDLE_MOD_DISABLE(player); 1168 SET_UNIPERIF_CONFIG_IDLE_MOD_DISABLE(player);
1089 1169
1090 if (UNIPERIF_PLAYER_TYPE_IS_IEC958(player)) { 1170 if (UNIPERIF_TYPE_IS_IEC958(player)) {
1091 /* Set default iec958 status bits */ 1171 /* Set default iec958 status bits */
1092 1172
1093 /* Consumer, PCM, copyright, 2ch, mode 0 */ 1173 /* Consumer, PCM, copyright, 2ch, mode 0 */
diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c
index 8a0eb2050169..eb74a328c928 100644
--- a/sound/soc/sti/uniperif_reader.c
+++ b/sound/soc/sti/uniperif_reader.c
@@ -73,55 +73,10 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
73 return ret; 73 return ret;
74} 74}
75 75
76static int uni_reader_prepare(struct snd_pcm_substream *substream, 76static int uni_reader_prepare_pcm(struct snd_pcm_runtime *runtime,
77 struct snd_soc_dai *dai) 77 struct uniperif *reader)
78{ 78{
79 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
80 struct uniperif *reader = priv->dai_data.uni;
81 struct snd_pcm_runtime *runtime = substream->runtime;
82 int transfer_size, trigger_limit;
83 int slot_width; 79 int slot_width;
84 int count = 10;
85
86 /* The reader should be stopped */
87 if (reader->state != UNIPERIF_STATE_STOPPED) {
88 dev_err(reader->dev, "%s: invalid reader state %d", __func__,
89 reader->state);
90 return -EINVAL;
91 }
92
93 /* Calculate transfer size (in fifo cells and bytes) for frame count */
94 transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES;
95
96 /* Calculate number of empty cells available before asserting DREQ */
97 if (reader->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0)
98 trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size;
99 else
100 /*
101 * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0
102 * FDMA_TRIGGER_LIMIT also controls when the state switches
103 * from OFF or STANDBY to AUDIO DATA.
104 */
105 trigger_limit = transfer_size;
106
107 /* Trigger limit must be an even number */
108 if ((!trigger_limit % 2) ||
109 (trigger_limit != 1 && transfer_size % 2) ||
110 (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(reader))) {
111 dev_err(reader->dev, "invalid trigger limit %d", trigger_limit);
112 return -EINVAL;
113 }
114
115 SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader, trigger_limit);
116
117 switch (reader->daifmt & SND_SOC_DAIFMT_INV_MASK) {
118 case SND_SOC_DAIFMT_IB_IF:
119 case SND_SOC_DAIFMT_NB_IF:
120 SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader);
121 break;
122 default:
123 SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader);
124 }
125 80
126 /* Force slot width to 32 in I2S mode */ 81 /* Force slot width to 32 in I2S mode */
127 if ((reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) 82 if ((reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK)
@@ -173,6 +128,109 @@ static int uni_reader_prepare(struct snd_pcm_substream *substream,
173 return -EINVAL; 128 return -EINVAL;
174 } 129 }
175 130
131 /* Number of channels must be even */
132 if ((runtime->channels % 2) || (runtime->channels < 2) ||
133 (runtime->channels > 10)) {
134 dev_err(reader->dev, "%s: invalid nb of channels", __func__);
135 return -EINVAL;
136 }
137
138 SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2);
139 SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader);
140
141 return 0;
142}
143
144static int uni_reader_prepare_tdm(struct snd_pcm_runtime *runtime,
145 struct uniperif *reader)
146{
147 int frame_size; /* user tdm frame size in bytes */
148 /* default unip TDM_WORD_POS_X_Y */
149 unsigned int word_pos[4] = {
150 0x04060002, 0x0C0E080A, 0x14161012, 0x1C1E181A};
151
152 frame_size = sti_uniperiph_get_user_frame_size(runtime);
153
154 /* fix 16/0 format */
155 SET_UNIPERIF_CONFIG_MEM_FMT_16_0(reader);
156 SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(reader);
157
158 /* number of words inserted on the TDM line */
159 SET_UNIPERIF_I2S_FMT_NUM_CH(reader, frame_size / 4 / 2);
160
161 SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader);
162 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader);
163 SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(reader);
164
165 /*
166 * set the timeslots allocation for words in FIFO
167 *
168 * HW bug: (LSB word < MSB word) => this config is not possible
169 * So if we want (LSB word < MSB) word, then it shall be
170 * handled by user
171 */
172 sti_uniperiph_get_tdm_word_pos(reader, word_pos);
173 SET_UNIPERIF_TDM_WORD_POS(reader, 1_2, word_pos[WORD_1_2]);
174 SET_UNIPERIF_TDM_WORD_POS(reader, 3_4, word_pos[WORD_3_4]);
175 SET_UNIPERIF_TDM_WORD_POS(reader, 5_6, word_pos[WORD_5_6]);
176 SET_UNIPERIF_TDM_WORD_POS(reader, 7_8, word_pos[WORD_7_8]);
177
178 return 0;
179}
180
181static int uni_reader_prepare(struct snd_pcm_substream *substream,
182 struct snd_soc_dai *dai)
183{
184 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
185 struct uniperif *reader = priv->dai_data.uni;
186 struct snd_pcm_runtime *runtime = substream->runtime;
187 int transfer_size, trigger_limit, ret;
188 int count = 10;
189
190 /* The reader should be stopped */
191 if (reader->state != UNIPERIF_STATE_STOPPED) {
192 dev_err(reader->dev, "%s: invalid reader state %d", __func__,
193 reader->state);
194 return -EINVAL;
195 }
196
197 /* Calculate transfer size (in fifo cells and bytes) for frame count */
198 if (reader->info->type == SND_ST_UNIPERIF_TYPE_TDM) {
199 /* transfer size = unip frame size (in 32 bits FIFO cell) */
200 transfer_size =
201 sti_uniperiph_get_user_frame_size(runtime) / 4;
202 } else {
203 transfer_size = runtime->channels * UNIPERIF_FIFO_FRAMES;
204 }
205
206 /* Calculate number of empty cells available before asserting DREQ */
207 if (reader->ver < SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0)
208 trigger_limit = UNIPERIF_FIFO_SIZE - transfer_size;
209 else
210 /*
211 * Since SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0
212 * FDMA_TRIGGER_LIMIT also controls when the state switches
213 * from OFF or STANDBY to AUDIO DATA.
214 */
215 trigger_limit = transfer_size;
216
217 /* Trigger limit must be an even number */
218 if ((!trigger_limit % 2) ||
219 (trigger_limit != 1 && transfer_size % 2) ||
220 (trigger_limit > UNIPERIF_CONFIG_DMA_TRIG_LIMIT_MASK(reader))) {
221 dev_err(reader->dev, "invalid trigger limit %d", trigger_limit);
222 return -EINVAL;
223 }
224
225 SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(reader, trigger_limit);
226
227 if (UNIPERIF_TYPE_IS_TDM(reader))
228 ret = uni_reader_prepare_tdm(runtime, reader);
229 else
230 ret = uni_reader_prepare_pcm(runtime, reader);
231 if (ret)
232 return ret;
233
176 switch (reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) { 234 switch (reader->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) {
177 case SND_SOC_DAIFMT_I2S: 235 case SND_SOC_DAIFMT_I2S:
178 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader); 236 SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(reader);
@@ -191,21 +249,26 @@ static int uni_reader_prepare(struct snd_pcm_substream *substream,
191 return -EINVAL; 249 return -EINVAL;
192 } 250 }
193 251
194 SET_UNIPERIF_I2S_FMT_ORDER_MSB(reader); 252 /* Data clocking (changing) on the rising/falling edge */
195 253 switch (reader->daifmt & SND_SOC_DAIFMT_INV_MASK) {
196 /* Data clocking (changing) on the rising edge */ 254 case SND_SOC_DAIFMT_NB_NF:
197 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader); 255 SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader);
198 256 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader);
199 /* Number of channels must be even */ 257 break;
200 258 case SND_SOC_DAIFMT_NB_IF:
201 if ((runtime->channels % 2) || (runtime->channels < 2) || 259 SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader);
202 (runtime->channels > 10)) { 260 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_RISING(reader);
203 dev_err(reader->dev, "%s: invalid nb of channels", __func__); 261 break;
204 return -EINVAL; 262 case SND_SOC_DAIFMT_IB_NF:
263 SET_UNIPERIF_I2S_FMT_LR_POL_LOW(reader);
264 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader);
265 break;
266 case SND_SOC_DAIFMT_IB_IF:
267 SET_UNIPERIF_I2S_FMT_LR_POL_HIG(reader);
268 SET_UNIPERIF_I2S_FMT_SCLK_EDGE_FALLING(reader);
269 break;
205 } 270 }
206 271
207 SET_UNIPERIF_I2S_FMT_NUM_CH(reader, runtime->channels / 2);
208
209 /* Clear any pending interrupts */ 272 /* Clear any pending interrupts */
210 SET_UNIPERIF_ITS_BCLR(reader, GET_UNIPERIF_ITS(reader)); 273 SET_UNIPERIF_ITS_BCLR(reader, GET_UNIPERIF_ITS(reader));
211 274
@@ -293,6 +356,32 @@ static int uni_reader_trigger(struct snd_pcm_substream *substream,
293 } 356 }
294} 357}
295 358
359static int uni_reader_startup(struct snd_pcm_substream *substream,
360 struct snd_soc_dai *dai)
361{
362 struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
363 struct uniperif *reader = priv->dai_data.uni;
364 int ret;
365
366 if (!UNIPERIF_TYPE_IS_TDM(reader))
367 return 0;
368
369 /* refine hw constraint in tdm mode */
370 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
371 SNDRV_PCM_HW_PARAM_CHANNELS,
372 sti_uniperiph_fix_tdm_chan,
373 reader, SNDRV_PCM_HW_PARAM_CHANNELS,
374 -1);
375 if (ret < 0)
376 return ret;
377
378 return snd_pcm_hw_rule_add(substream->runtime, 0,
379 SNDRV_PCM_HW_PARAM_FORMAT,
380 sti_uniperiph_fix_tdm_format,
381 reader, SNDRV_PCM_HW_PARAM_FORMAT,
382 -1);
383}
384
296static void uni_reader_shutdown(struct snd_pcm_substream *substream, 385static void uni_reader_shutdown(struct snd_pcm_substream *substream,
297 struct snd_soc_dai *dai) 386 struct snd_soc_dai *dai)
298{ 387{
@@ -310,6 +399,7 @@ static int uni_reader_parse_dt(struct platform_device *pdev,
310{ 399{
311 struct uniperif_info *info; 400 struct uniperif_info *info;
312 struct device_node *node = pdev->dev.of_node; 401 struct device_node *node = pdev->dev.of_node;
402 const char *mode;
313 403
314 /* Allocate memory for the info structure */ 404 /* Allocate memory for the info structure */
315 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); 405 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
@@ -322,6 +412,17 @@ static int uni_reader_parse_dt(struct platform_device *pdev,
322 return -EINVAL; 412 return -EINVAL;
323 } 413 }
324 414
415 /* Read the device mode property */
416 if (of_property_read_string(node, "st,mode", &mode)) {
417 dev_err(&pdev->dev, "uniperipheral mode not defined");
418 return -EINVAL;
419 }
420
421 if (strcasecmp(mode, "tdm") == 0)
422 info->type = SND_ST_UNIPERIF_TYPE_TDM;
423 else
424 info->type = SND_ST_UNIPERIF_TYPE_PCM;
425
325 /* Save the info structure */ 426 /* Save the info structure */
326 reader->info = info; 427 reader->info = info;
327 428
@@ -329,11 +430,13 @@ static int uni_reader_parse_dt(struct platform_device *pdev,
329} 430}
330 431
331static const struct snd_soc_dai_ops uni_reader_dai_ops = { 432static const struct snd_soc_dai_ops uni_reader_dai_ops = {
433 .startup = uni_reader_startup,
332 .shutdown = uni_reader_shutdown, 434 .shutdown = uni_reader_shutdown,
333 .prepare = uni_reader_prepare, 435 .prepare = uni_reader_prepare,
334 .trigger = uni_reader_trigger, 436 .trigger = uni_reader_trigger,
335 .hw_params = sti_uniperiph_dai_hw_params, 437 .hw_params = sti_uniperiph_dai_hw_params,
336 .set_fmt = sti_uniperiph_dai_set_fmt, 438 .set_fmt = sti_uniperiph_dai_set_fmt,
439 .set_tdm_slot = sti_uniperiph_set_tdm_slot
337}; 440};
338 441
339int uni_reader_init(struct platform_device *pdev, 442int uni_reader_init(struct platform_device *pdev,
@@ -343,7 +446,6 @@ int uni_reader_init(struct platform_device *pdev,
343 446
344 reader->dev = &pdev->dev; 447 reader->dev = &pdev->dev;
345 reader->state = UNIPERIF_STATE_STOPPED; 448 reader->state = UNIPERIF_STATE_STOPPED;
346 reader->hw = &uni_reader_pcm_hw;
347 reader->dai_ops = &uni_reader_dai_ops; 449 reader->dai_ops = &uni_reader_dai_ops;
348 450
349 ret = uni_reader_parse_dt(pdev, reader); 451 ret = uni_reader_parse_dt(pdev, reader);
@@ -352,6 +454,11 @@ int uni_reader_init(struct platform_device *pdev,
352 return ret; 454 return ret;
353 } 455 }
354 456
457 if (UNIPERIF_TYPE_IS_TDM(reader))
458 reader->hw = &uni_tdm_hw;
459 else
460 reader->hw = &uni_reader_pcm_hw;
461
355 ret = devm_request_irq(&pdev->dev, reader->irq, 462 ret = devm_request_irq(&pdev->dev, reader->irq,
356 uni_reader_irq_handler, IRQF_SHARED, 463 uni_reader_irq_handler, IRQF_SHARED,
357 dev_name(&pdev->dev), reader); 464 dev_name(&pdev->dev), reader);