diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2014-11-06 09:59:23 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-11-06 11:05:10 -0500 |
commit | ead99f89b7cd2b5cfe99601380a6f6f0a1ce7e53 (patch) | |
tree | 5f99babab7131b74b409de71ec3c762e6015f62d | |
parent | feec843d6c4528263724ff3f4c463ea82bf63b4a (diff) |
ASoC: ssm4567: Add support for setting the DAI format and TDM configuration
The SSM4567 has support for a couple of different DAI formats. In TDM mode
it is also possible to select the TDM slot. This patch adds support for this
by implementing the set_fmt and set_tdm_slot callbacks.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/codecs/ssm4567.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c index e1e33d8cb55a..217667926a77 100644 --- a/sound/soc/codecs/ssm4567.c +++ b/sound/soc/codecs/ssm4567.c | |||
@@ -69,6 +69,22 @@ | |||
69 | #define SSM4567_DAC_FS_64000_96000 0x3 | 69 | #define SSM4567_DAC_FS_64000_96000 0x3 |
70 | #define SSM4567_DAC_FS_128000_192000 0x4 | 70 | #define SSM4567_DAC_FS_128000_192000 0x4 |
71 | 71 | ||
72 | /* SAI_CTRL_1 */ | ||
73 | #define SSM4567_SAI_CTRL_1_BCLK BIT(6) | ||
74 | #define SSM4567_SAI_CTRL_1_TDM_BLCKS_MASK (0x3 << 4) | ||
75 | #define SSM4567_SAI_CTRL_1_TDM_BLCKS_32 (0x0 << 4) | ||
76 | #define SSM4567_SAI_CTRL_1_TDM_BLCKS_48 (0x1 << 4) | ||
77 | #define SSM4567_SAI_CTRL_1_TDM_BLCKS_64 (0x2 << 4) | ||
78 | #define SSM4567_SAI_CTRL_1_FSYNC BIT(3) | ||
79 | #define SSM4567_SAI_CTRL_1_LJ BIT(2) | ||
80 | #define SSM4567_SAI_CTRL_1_TDM BIT(1) | ||
81 | #define SSM4567_SAI_CTRL_1_PDM BIT(0) | ||
82 | |||
83 | /* SAI_CTRL_2 */ | ||
84 | #define SSM4567_SAI_CTRL_2_AUTO_SLOT BIT(3) | ||
85 | #define SSM4567_SAI_CTRL_2_TDM_SLOT_MASK 0x7 | ||
86 | #define SSM4567_SAI_CTRL_2_TDM_SLOT(x) (x) | ||
87 | |||
72 | struct ssm4567 { | 88 | struct ssm4567 { |
73 | struct regmap *regmap; | 89 | struct regmap *regmap; |
74 | }; | 90 | }; |
@@ -194,6 +210,107 @@ static int ssm4567_mute(struct snd_soc_dai *dai, int mute) | |||
194 | SSM4567_DAC_MUTE, val); | 210 | SSM4567_DAC_MUTE, val); |
195 | } | 211 | } |
196 | 212 | ||
213 | static int ssm4567_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
214 | unsigned int rx_mask, int slots, int width) | ||
215 | { | ||
216 | struct ssm4567 *ssm4567 = snd_soc_dai_get_drvdata(dai); | ||
217 | unsigned int blcks; | ||
218 | int slot; | ||
219 | int ret; | ||
220 | |||
221 | if (tx_mask == 0) | ||
222 | return -EINVAL; | ||
223 | |||
224 | if (rx_mask && rx_mask != tx_mask) | ||
225 | return -EINVAL; | ||
226 | |||
227 | slot = __ffs(tx_mask); | ||
228 | if (tx_mask != BIT(slot)) | ||
229 | return -EINVAL; | ||
230 | |||
231 | switch (width) { | ||
232 | case 32: | ||
233 | blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_32; | ||
234 | break; | ||
235 | case 48: | ||
236 | blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_48; | ||
237 | break; | ||
238 | case 64: | ||
239 | blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_64; | ||
240 | break; | ||
241 | default: | ||
242 | return -EINVAL; | ||
243 | } | ||
244 | |||
245 | ret = regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_2, | ||
246 | SSM4567_SAI_CTRL_2_AUTO_SLOT | SSM4567_SAI_CTRL_2_TDM_SLOT_MASK, | ||
247 | SSM4567_SAI_CTRL_2_TDM_SLOT(slot)); | ||
248 | if (ret) | ||
249 | return ret; | ||
250 | |||
251 | return regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1, | ||
252 | SSM4567_SAI_CTRL_1_TDM_BLCKS_MASK, blcks); | ||
253 | } | ||
254 | |||
255 | static int ssm4567_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
256 | { | ||
257 | struct ssm4567 *ssm4567 = snd_soc_dai_get_drvdata(dai); | ||
258 | unsigned int ctrl1 = 0; | ||
259 | bool invert_fclk; | ||
260 | |||
261 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
262 | case SND_SOC_DAIFMT_CBS_CFS: | ||
263 | break; | ||
264 | default: | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | |||
268 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
269 | case SND_SOC_DAIFMT_NB_NF: | ||
270 | invert_fclk = false; | ||
271 | break; | ||
272 | case SND_SOC_DAIFMT_IB_NF: | ||
273 | ctrl1 |= SSM4567_SAI_CTRL_1_BCLK; | ||
274 | invert_fclk = false; | ||
275 | break; | ||
276 | case SND_SOC_DAIFMT_NB_IF: | ||
277 | ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC; | ||
278 | invert_fclk = true; | ||
279 | break; | ||
280 | case SND_SOC_DAIFMT_IB_IF: | ||
281 | ctrl1 |= SSM4567_SAI_CTRL_1_BCLK; | ||
282 | invert_fclk = true; | ||
283 | break; | ||
284 | default: | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
289 | case SND_SOC_DAIFMT_I2S: | ||
290 | break; | ||
291 | case SND_SOC_DAIFMT_LEFT_J: | ||
292 | ctrl1 |= SSM4567_SAI_CTRL_1_LJ; | ||
293 | invert_fclk = !invert_fclk; | ||
294 | break; | ||
295 | case SND_SOC_DAIFMT_DSP_A: | ||
296 | ctrl1 |= SSM4567_SAI_CTRL_1_TDM; | ||
297 | break; | ||
298 | case SND_SOC_DAIFMT_DSP_B: | ||
299 | ctrl1 |= SSM4567_SAI_CTRL_1_TDM | SSM4567_SAI_CTRL_1_LJ; | ||
300 | break; | ||
301 | case SND_SOC_DAIFMT_PDM: | ||
302 | ctrl1 |= SSM4567_SAI_CTRL_1_PDM; | ||
303 | break; | ||
304 | default: | ||
305 | return -EINVAL; | ||
306 | } | ||
307 | |||
308 | if (invert_fclk) | ||
309 | ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC; | ||
310 | |||
311 | return regmap_write(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1, ctrl1); | ||
312 | } | ||
313 | |||
197 | static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable) | 314 | static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable) |
198 | { | 315 | { |
199 | int ret = 0; | 316 | int ret = 0; |
@@ -248,6 +365,8 @@ static int ssm4567_set_bias_level(struct snd_soc_codec *codec, | |||
248 | static const struct snd_soc_dai_ops ssm4567_dai_ops = { | 365 | static const struct snd_soc_dai_ops ssm4567_dai_ops = { |
249 | .hw_params = ssm4567_hw_params, | 366 | .hw_params = ssm4567_hw_params, |
250 | .digital_mute = ssm4567_mute, | 367 | .digital_mute = ssm4567_mute, |
368 | .set_fmt = ssm4567_set_dai_fmt, | ||
369 | .set_tdm_slot = ssm4567_set_tdm_slot, | ||
251 | }; | 370 | }; |
252 | 371 | ||
253 | static struct snd_soc_dai_driver ssm4567_dai = { | 372 | static struct snd_soc_dai_driver ssm4567_dai = { |