xref: /openbmc/linux/sound/soc/ux500/mop500_ab8500.c (revision c853679a)
1 /*
2  * Copyright (C) ST-Ericsson SA 2012
3  *
4  * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
5  *         Kristoffer Karlsson <kristoffer.karlsson@stericsson.com>
6  *         for ST-Ericsson.
7  *
8  * License terms:
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as published
12  * by the Free Software Foundation.
13  */
14 
15 #include <linux/module.h>
16 #include <linux/device.h>
17 #include <linux/io.h>
18 #include <linux/clk.h>
19 #include <linux/mutex.h>
20 
21 #include <sound/soc.h>
22 #include <sound/soc-dapm.h>
23 #include <sound/pcm.h>
24 #include <sound/pcm_params.h>
25 
26 #include "ux500_pcm.h"
27 #include "ux500_msp_dai.h"
28 #include "mop500_ab8500.h"
29 #include "../codecs/ab8500-codec.h"
30 
31 #define TX_SLOT_MONO	0x0008
32 #define TX_SLOT_STEREO	0x000a
33 #define RX_SLOT_MONO	0x0001
34 #define RX_SLOT_STEREO	0x0003
35 #define TX_SLOT_8CH	0x00FF
36 #define RX_SLOT_8CH	0x00FF
37 
38 #define DEF_TX_SLOTS	TX_SLOT_STEREO
39 #define DEF_RX_SLOTS	RX_SLOT_MONO
40 
41 #define DRIVERMODE_NORMAL	0
42 #define DRIVERMODE_CODEC_ONLY	1
43 
44 /* Slot configuration */
45 static unsigned int tx_slots = DEF_TX_SLOTS;
46 static unsigned int rx_slots = DEF_RX_SLOTS;
47 
48 /* Configuration consistency parameters */
49 static DEFINE_MUTEX(mop500_ab8500_params_lock);
50 static unsigned long mop500_ab8500_usage;
51 static int mop500_ab8500_rate;
52 static int mop500_ab8500_channels;
53 
54 /* Clocks */
55 static const char * const enum_mclk[] = {
56 	"SYSCLK",
57 	"ULPCLK"
58 };
59 enum mclk {
60 	MCLK_SYSCLK,
61 	MCLK_ULPCLK,
62 };
63 
64 static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_mclk, enum_mclk);
65 
66 /* Private data for machine-part MOP500<->AB8500 */
67 struct mop500_ab8500_drvdata {
68 	/* Clocks */
69 	enum mclk mclk_sel;
70 	struct clk *clk_ptr_intclk;
71 	struct clk *clk_ptr_sysclk;
72 	struct clk *clk_ptr_ulpclk;
73 };
74 
75 static inline const char *get_mclk_str(enum mclk mclk_sel)
76 {
77 	switch (mclk_sel) {
78 	case MCLK_SYSCLK:
79 		return "SYSCLK";
80 	case MCLK_ULPCLK:
81 		return "ULPCLK";
82 	default:
83 		return "Unknown";
84 	}
85 }
86 
87 static int mop500_ab8500_set_mclk(struct device *dev,
88 				struct mop500_ab8500_drvdata *drvdata)
89 {
90 	int status;
91 	struct clk *clk_ptr;
92 
93 	if (IS_ERR(drvdata->clk_ptr_intclk)) {
94 		dev_err(dev,
95 			"%s: ERROR: intclk not initialized!\n", __func__);
96 		return -EIO;
97 	}
98 
99 	switch (drvdata->mclk_sel) {
100 	case MCLK_SYSCLK:
101 		clk_ptr = drvdata->clk_ptr_sysclk;
102 		break;
103 	case MCLK_ULPCLK:
104 		clk_ptr = drvdata->clk_ptr_ulpclk;
105 		break;
106 	default:
107 		return -EINVAL;
108 	}
109 
110 	if (IS_ERR(clk_ptr)) {
111 		dev_err(dev, "%s: ERROR: %s not initialized!\n", __func__,
112 			get_mclk_str(drvdata->mclk_sel));
113 		return -EIO;
114 	}
115 
116 	status = clk_set_parent(drvdata->clk_ptr_intclk, clk_ptr);
117 	if (status)
118 		dev_err(dev,
119 			"%s: ERROR: Setting intclk parent to %s failed (ret = %d)!",
120 			__func__, get_mclk_str(drvdata->mclk_sel), status);
121 	else
122 		dev_dbg(dev,
123 			"%s: intclk parent changed to %s.\n",
124 			__func__, get_mclk_str(drvdata->mclk_sel));
125 
126 	return status;
127 }
128 
129 /*
130  * Control-events
131  */
132 
133 static int mclk_input_control_get(struct snd_kcontrol *kcontrol,
134 				struct snd_ctl_elem_value *ucontrol)
135 {
136 	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
137 	struct mop500_ab8500_drvdata *drvdata =
138 				snd_soc_card_get_drvdata(card);
139 
140 	ucontrol->value.enumerated.item[0] = drvdata->mclk_sel;
141 
142 	return 0;
143 }
144 
145 static int mclk_input_control_put(struct snd_kcontrol *kcontrol,
146 				struct snd_ctl_elem_value *ucontrol)
147 {
148 	struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
149 	struct mop500_ab8500_drvdata *drvdata =
150 				snd_soc_card_get_drvdata(card);
151 	unsigned int val = ucontrol->value.enumerated.item[0];
152 
153 	if (val > (unsigned int)MCLK_ULPCLK)
154 		return -EINVAL;
155 	if (drvdata->mclk_sel == val)
156 		return 0;
157 
158 	drvdata->mclk_sel = val;
159 
160 	return 1;
161 }
162 
163 /*
164  * Controls
165  */
166 
167 static struct snd_kcontrol_new mop500_ab8500_ctrls[] = {
168 	SOC_ENUM_EXT("Master Clock Select",
169 		soc_enum_mclk,
170 		mclk_input_control_get, mclk_input_control_put),
171 	SOC_DAPM_PIN_SWITCH("Headset Left"),
172 	SOC_DAPM_PIN_SWITCH("Headset Right"),
173 	SOC_DAPM_PIN_SWITCH("Earpiece"),
174 	SOC_DAPM_PIN_SWITCH("Speaker Left"),
175 	SOC_DAPM_PIN_SWITCH("Speaker Right"),
176 	SOC_DAPM_PIN_SWITCH("LineOut Left"),
177 	SOC_DAPM_PIN_SWITCH("LineOut Right"),
178 	SOC_DAPM_PIN_SWITCH("Vibra 1"),
179 	SOC_DAPM_PIN_SWITCH("Vibra 2"),
180 	SOC_DAPM_PIN_SWITCH("Mic 1"),
181 	SOC_DAPM_PIN_SWITCH("Mic 2"),
182 	SOC_DAPM_PIN_SWITCH("LineIn Left"),
183 	SOC_DAPM_PIN_SWITCH("LineIn Right"),
184 	SOC_DAPM_PIN_SWITCH("DMic 1"),
185 	SOC_DAPM_PIN_SWITCH("DMic 2"),
186 	SOC_DAPM_PIN_SWITCH("DMic 3"),
187 	SOC_DAPM_PIN_SWITCH("DMic 4"),
188 	SOC_DAPM_PIN_SWITCH("DMic 5"),
189 	SOC_DAPM_PIN_SWITCH("DMic 6"),
190 };
191 
192 /* ASoC */
193 
194 static int mop500_ab8500_startup(struct snd_pcm_substream *substream)
195 {
196 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
197 
198 	/* Set audio-clock source */
199 	return mop500_ab8500_set_mclk(rtd->card->dev,
200 				snd_soc_card_get_drvdata(rtd->card));
201 }
202 
203 static void mop500_ab8500_shutdown(struct snd_pcm_substream *substream)
204 {
205 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
206 	struct device *dev = rtd->card->dev;
207 
208 	dev_dbg(dev, "%s: Enter\n", __func__);
209 
210 	/* Reset slots configuration to default(s) */
211 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
212 		tx_slots = DEF_TX_SLOTS;
213 	else
214 		rx_slots = DEF_RX_SLOTS;
215 }
216 
217 static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream,
218 			struct snd_pcm_hw_params *params)
219 {
220 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
221 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
222 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
223 	struct device *dev = rtd->card->dev;
224 	unsigned int fmt;
225 	int channels, ret = 0, driver_mode, slots;
226 	unsigned int sw_codec, sw_cpu;
227 	bool is_playback;
228 
229 	dev_dbg(dev, "%s: Enter\n", __func__);
230 
231 	dev_dbg(dev, "%s: substream->pcm->name = %s\n"
232 		"substream->pcm->id = %s.\n"
233 		"substream->name = %s.\n"
234 		"substream->number = %d.\n",
235 		__func__,
236 		substream->pcm->name,
237 		substream->pcm->id,
238 		substream->name,
239 		substream->number);
240 
241 	/* Ensure configuration consistency between DAIs */
242 	mutex_lock(&mop500_ab8500_params_lock);
243 	if (mop500_ab8500_usage) {
244 		if (mop500_ab8500_rate != params_rate(params) ||
245 		    mop500_ab8500_channels != params_channels(params)) {
246 			mutex_unlock(&mop500_ab8500_params_lock);
247 			return -EBUSY;
248 		}
249 	} else {
250 		mop500_ab8500_rate = params_rate(params);
251 		mop500_ab8500_channels = params_channels(params);
252 	}
253 	__set_bit(cpu_dai->id, &mop500_ab8500_usage);
254 	mutex_unlock(&mop500_ab8500_params_lock);
255 
256 	channels = params_channels(params);
257 
258 	switch (params_format(params)) {
259 	case SNDRV_PCM_FORMAT_S32_LE:
260 		sw_cpu = 32;
261 		break;
262 
263 	case SNDRV_PCM_FORMAT_S16_LE:
264 		sw_cpu = 16;
265 		break;
266 
267 	default:
268 		return -EINVAL;
269 	}
270 
271 	/* Setup codec depending on driver-mode */
272 	if (channels == 8)
273 		driver_mode = DRIVERMODE_CODEC_ONLY;
274 	else
275 		driver_mode = DRIVERMODE_NORMAL;
276 	dev_dbg(dev, "%s: Driver-mode: %s.\n", __func__,
277 		(driver_mode == DRIVERMODE_NORMAL) ? "NORMAL" : "CODEC_ONLY");
278 
279 	/* Setup format */
280 
281 	if (driver_mode == DRIVERMODE_NORMAL) {
282 		fmt = SND_SOC_DAIFMT_DSP_A |
283 			SND_SOC_DAIFMT_CBM_CFM |
284 			SND_SOC_DAIFMT_NB_NF |
285 			SND_SOC_DAIFMT_CONT;
286 	} else {
287 		fmt = SND_SOC_DAIFMT_DSP_A |
288 			SND_SOC_DAIFMT_CBM_CFM |
289 			SND_SOC_DAIFMT_NB_NF |
290 			SND_SOC_DAIFMT_GATED;
291 	}
292 
293 	ret = snd_soc_runtime_set_dai_fmt(rtd, fmt);
294 	if (ret)
295 		return ret;
296 
297 	/* Setup TDM-slots */
298 
299 	is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
300 	switch (channels) {
301 	case 1:
302 		slots = 16;
303 		tx_slots = (is_playback) ? TX_SLOT_MONO : 0;
304 		rx_slots = (is_playback) ? 0 : RX_SLOT_MONO;
305 		break;
306 	case 2:
307 		slots = 16;
308 		tx_slots = (is_playback) ? TX_SLOT_STEREO : 0;
309 		rx_slots = (is_playback) ? 0 : RX_SLOT_STEREO;
310 		break;
311 	case 8:
312 		slots = 16;
313 		tx_slots = (is_playback) ? TX_SLOT_8CH : 0;
314 		rx_slots = (is_playback) ? 0 : RX_SLOT_8CH;
315 		break;
316 	default:
317 		return -EINVAL;
318 	}
319 
320 	if (driver_mode == DRIVERMODE_NORMAL)
321 		sw_codec = sw_cpu;
322 	else
323 		sw_codec = 20;
324 
325 	dev_dbg(dev, "%s: CPU-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__,
326 		tx_slots, rx_slots);
327 	ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_slots, rx_slots, slots,
328 				sw_cpu);
329 	if (ret)
330 		return ret;
331 
332 	dev_dbg(dev, "%s: CODEC-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__,
333 		tx_slots, rx_slots);
334 	ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_slots, rx_slots, slots,
335 				sw_codec);
336 	if (ret)
337 		return ret;
338 
339 	return 0;
340 }
341 
342 static int mop500_ab8500_hw_free(struct snd_pcm_substream *substream)
343 {
344 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
345 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
346 
347 	mutex_lock(&mop500_ab8500_params_lock);
348 	__clear_bit(cpu_dai->id, &mop500_ab8500_usage);
349 	mutex_unlock(&mop500_ab8500_params_lock);
350 
351 	return 0;
352 }
353 
354 struct snd_soc_ops mop500_ab8500_ops[] = {
355 	{
356 		.hw_params = mop500_ab8500_hw_params,
357 		.hw_free = mop500_ab8500_hw_free,
358 		.startup = mop500_ab8500_startup,
359 		.shutdown = mop500_ab8500_shutdown,
360 	}
361 };
362 
363 int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd)
364 {
365 	struct snd_soc_codec *codec = rtd->codec;
366 	struct device *dev = rtd->card->dev;
367 	struct mop500_ab8500_drvdata *drvdata;
368 	int ret;
369 
370 	dev_dbg(dev, "%s Enter.\n", __func__);
371 
372 	/* Create driver private-data struct */
373 	drvdata = devm_kzalloc(dev, sizeof(struct mop500_ab8500_drvdata),
374 			GFP_KERNEL);
375 	snd_soc_card_set_drvdata(rtd->card, drvdata);
376 
377 	/* Setup clocks */
378 
379 	drvdata->clk_ptr_sysclk = clk_get(dev, "sysclk");
380 	if (IS_ERR(drvdata->clk_ptr_sysclk))
381 		dev_warn(dev, "%s: WARNING: clk_get failed for 'sysclk'!\n",
382 			__func__);
383 	drvdata->clk_ptr_ulpclk = clk_get(dev, "ulpclk");
384 	if (IS_ERR(drvdata->clk_ptr_ulpclk))
385 		dev_warn(dev, "%s: WARNING: clk_get failed for 'ulpclk'!\n",
386 			__func__);
387 	drvdata->clk_ptr_intclk = clk_get(dev, "intclk");
388 	if (IS_ERR(drvdata->clk_ptr_intclk))
389 		dev_warn(dev, "%s: WARNING: clk_get failed for 'intclk'!\n",
390 			__func__);
391 
392 	/* Set intclk default parent to ulpclk */
393 	drvdata->mclk_sel = MCLK_ULPCLK;
394 	ret = mop500_ab8500_set_mclk(dev, drvdata);
395 	if (ret < 0)
396 		dev_warn(dev, "%s: WARNING: mop500_ab8500_set_mclk!\n",
397 			__func__);
398 
399 	drvdata->mclk_sel = MCLK_ULPCLK;
400 
401 	/* Add controls */
402 	ret = snd_soc_add_card_controls(rtd->card, mop500_ab8500_ctrls,
403 			ARRAY_SIZE(mop500_ab8500_ctrls));
404 	if (ret < 0) {
405 		pr_err("%s: Failed to add machine-controls (%d)!\n",
406 				__func__, ret);
407 		return ret;
408 	}
409 
410 	ret = snd_soc_dapm_disable_pin(&codec->dapm, "Earpiece");
411 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Speaker Left");
412 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Speaker Right");
413 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineOut Left");
414 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineOut Right");
415 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Vibra 1");
416 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Vibra 2");
417 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Mic 1");
418 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Mic 2");
419 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineIn Left");
420 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineIn Right");
421 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 1");
422 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 2");
423 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 3");
424 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 4");
425 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 5");
426 	ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 6");
427 
428 	return ret;
429 }
430 
431 void mop500_ab8500_remove(struct snd_soc_card *card)
432 {
433 	struct mop500_ab8500_drvdata *drvdata = snd_soc_card_get_drvdata(card);
434 
435 	if (drvdata->clk_ptr_sysclk != NULL)
436 		clk_put(drvdata->clk_ptr_sysclk);
437 	if (drvdata->clk_ptr_ulpclk != NULL)
438 		clk_put(drvdata->clk_ptr_ulpclk);
439 	if (drvdata->clk_ptr_intclk != NULL)
440 		clk_put(drvdata->clk_ptr_intclk);
441 
442 	snd_soc_card_set_drvdata(card, drvdata);
443 }
444