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