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 */
45static unsigned int tx_slots = DEF_TX_SLOTS;
46static unsigned int rx_slots = DEF_RX_SLOTS;
47
48/* Configuration consistency parameters */
49static DEFINE_MUTEX(mop500_ab8500_params_lock);
50static unsigned long mop500_ab8500_usage;
51static int mop500_ab8500_rate;
52static int mop500_ab8500_channels;
53
54/* Clocks */
55static const char * const enum_mclk[] = {
56	"SYSCLK",
57	"ULPCLK"
58};
59enum mclk {
60	MCLK_SYSCLK,
61	MCLK_ULPCLK,
62};
63
64static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_mclk, enum_mclk);
65
66/* Private data for machine-part MOP500<->AB8500 */
67struct 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
75static 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
87static 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
133static 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
145static 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
167static 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
194static 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
203static 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
217static 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
342static 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
354struct 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
363int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd)
364{
365	struct snd_soc_dapm_context *dapm = &rtd->card->dapm;
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
376	if (!drvdata)
377		return -ENOMEM;
378
379	snd_soc_card_set_drvdata(rtd->card, drvdata);
380
381	/* Setup clocks */
382
383	drvdata->clk_ptr_sysclk = clk_get(dev, "sysclk");
384	if (IS_ERR(drvdata->clk_ptr_sysclk))
385		dev_warn(dev, "%s: WARNING: clk_get failed for 'sysclk'!\n",
386			__func__);
387	drvdata->clk_ptr_ulpclk = clk_get(dev, "ulpclk");
388	if (IS_ERR(drvdata->clk_ptr_ulpclk))
389		dev_warn(dev, "%s: WARNING: clk_get failed for 'ulpclk'!\n",
390			__func__);
391	drvdata->clk_ptr_intclk = clk_get(dev, "intclk");
392	if (IS_ERR(drvdata->clk_ptr_intclk))
393		dev_warn(dev, "%s: WARNING: clk_get failed for 'intclk'!\n",
394			__func__);
395
396	/* Set intclk default parent to ulpclk */
397	drvdata->mclk_sel = MCLK_ULPCLK;
398	ret = mop500_ab8500_set_mclk(dev, drvdata);
399	if (ret < 0)
400		dev_warn(dev, "%s: WARNING: mop500_ab8500_set_mclk!\n",
401			__func__);
402
403	drvdata->mclk_sel = MCLK_ULPCLK;
404
405	/* Add controls */
406	ret = snd_soc_add_card_controls(rtd->card, mop500_ab8500_ctrls,
407			ARRAY_SIZE(mop500_ab8500_ctrls));
408	if (ret < 0) {
409		pr_err("%s: Failed to add machine-controls (%d)!\n",
410				__func__, ret);
411		return ret;
412	}
413
414	ret = snd_soc_dapm_disable_pin(dapm, "Earpiece");
415	ret |= snd_soc_dapm_disable_pin(dapm, "Speaker Left");
416	ret |= snd_soc_dapm_disable_pin(dapm, "Speaker Right");
417	ret |= snd_soc_dapm_disable_pin(dapm, "LineOut Left");
418	ret |= snd_soc_dapm_disable_pin(dapm, "LineOut Right");
419	ret |= snd_soc_dapm_disable_pin(dapm, "Vibra 1");
420	ret |= snd_soc_dapm_disable_pin(dapm, "Vibra 2");
421	ret |= snd_soc_dapm_disable_pin(dapm, "Mic 1");
422	ret |= snd_soc_dapm_disable_pin(dapm, "Mic 2");
423	ret |= snd_soc_dapm_disable_pin(dapm, "LineIn Left");
424	ret |= snd_soc_dapm_disable_pin(dapm, "LineIn Right");
425	ret |= snd_soc_dapm_disable_pin(dapm, "DMic 1");
426	ret |= snd_soc_dapm_disable_pin(dapm, "DMic 2");
427	ret |= snd_soc_dapm_disable_pin(dapm, "DMic 3");
428	ret |= snd_soc_dapm_disable_pin(dapm, "DMic 4");
429	ret |= snd_soc_dapm_disable_pin(dapm, "DMic 5");
430	ret |= snd_soc_dapm_disable_pin(dapm, "DMic 6");
431
432	return ret;
433}
434
435void mop500_ab8500_remove(struct snd_soc_card *card)
436{
437	struct mop500_ab8500_drvdata *drvdata = snd_soc_card_get_drvdata(card);
438
439	if (drvdata->clk_ptr_sysclk != NULL)
440		clk_put(drvdata->clk_ptr_sysclk);
441	if (drvdata->clk_ptr_ulpclk != NULL)
442		clk_put(drvdata->clk_ptr_ulpclk);
443	if (drvdata->clk_ptr_intclk != NULL)
444		clk_put(drvdata->clk_ptr_intclk);
445
446	snd_soc_card_set_drvdata(card, drvdata);
447}
448