cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ux500_msp_dai.c (22535B)


      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 *         Roger Nilsson <roger.xr.nilsson@stericsson.com>
      7 *         for ST-Ericsson.
      8 *
      9 * License terms:
     10 */
     11
     12#include <linux/module.h>
     13#include <linux/slab.h>
     14#include <linux/bitops.h>
     15#include <linux/platform_device.h>
     16#include <linux/clk.h>
     17#include <linux/of.h>
     18#include <linux/regulator/consumer.h>
     19#include <linux/mfd/dbx500-prcmu.h>
     20#include <linux/platform_data/asoc-ux500-msp.h>
     21
     22#include <sound/soc.h>
     23#include <sound/soc-dai.h>
     24#include <sound/dmaengine_pcm.h>
     25
     26#include "ux500_msp_i2s.h"
     27#include "ux500_msp_dai.h"
     28#include "ux500_pcm.h"
     29
     30static int setup_pcm_multichan(struct snd_soc_dai *dai,
     31			struct ux500_msp_config *msp_config)
     32{
     33	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
     34	struct msp_multichannel_config *multi =
     35					&msp_config->multichannel_config;
     36
     37	if (drvdata->slots > 1) {
     38		msp_config->multichannel_configured = 1;
     39
     40		multi->tx_multichannel_enable = true;
     41		multi->rx_multichannel_enable = true;
     42		multi->rx_comparison_enable_mode = MSP_COMPARISON_DISABLED;
     43
     44		multi->tx_channel_0_enable = drvdata->tx_mask;
     45		multi->tx_channel_1_enable = 0;
     46		multi->tx_channel_2_enable = 0;
     47		multi->tx_channel_3_enable = 0;
     48
     49		multi->rx_channel_0_enable = drvdata->rx_mask;
     50		multi->rx_channel_1_enable = 0;
     51		multi->rx_channel_2_enable = 0;
     52		multi->rx_channel_3_enable = 0;
     53
     54		dev_dbg(dai->dev,
     55			"%s: Multichannel enabled. Slots: %d, TX: %u, RX: %u\n",
     56			__func__, drvdata->slots, multi->tx_channel_0_enable,
     57			multi->rx_channel_0_enable);
     58	}
     59
     60	return 0;
     61}
     62
     63static int setup_frameper(struct snd_soc_dai *dai, unsigned int rate,
     64			struct msp_protdesc *prot_desc)
     65{
     66	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
     67
     68	switch (drvdata->slots) {
     69	case 1:
     70		switch (rate) {
     71		case 8000:
     72			prot_desc->frame_period =
     73				FRAME_PER_SINGLE_SLOT_8_KHZ;
     74			break;
     75
     76		case 16000:
     77			prot_desc->frame_period =
     78				FRAME_PER_SINGLE_SLOT_16_KHZ;
     79			break;
     80
     81		case 44100:
     82			prot_desc->frame_period =
     83				FRAME_PER_SINGLE_SLOT_44_1_KHZ;
     84			break;
     85
     86		case 48000:
     87			prot_desc->frame_period =
     88				FRAME_PER_SINGLE_SLOT_48_KHZ;
     89			break;
     90
     91		default:
     92			dev_err(dai->dev,
     93				"%s: Error: Unsupported sample-rate (freq = %d)!\n",
     94				__func__, rate);
     95			return -EINVAL;
     96		}
     97		break;
     98
     99	case 2:
    100		prot_desc->frame_period = FRAME_PER_2_SLOTS;
    101		break;
    102
    103	case 8:
    104		prot_desc->frame_period = FRAME_PER_8_SLOTS;
    105		break;
    106
    107	case 16:
    108		prot_desc->frame_period = FRAME_PER_16_SLOTS;
    109		break;
    110	default:
    111		dev_err(dai->dev,
    112			"%s: Error: Unsupported slot-count (slots = %d)!\n",
    113			__func__, drvdata->slots);
    114		return -EINVAL;
    115	}
    116
    117	prot_desc->clocks_per_frame =
    118			prot_desc->frame_period+1;
    119
    120	dev_dbg(dai->dev, "%s: Clocks per frame: %u\n",
    121		__func__,
    122		prot_desc->clocks_per_frame);
    123
    124	return 0;
    125}
    126
    127static int setup_pcm_framing(struct snd_soc_dai *dai, unsigned int rate,
    128			struct msp_protdesc *prot_desc)
    129{
    130	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
    131
    132	u32 frame_length = MSP_FRAME_LEN_1;
    133
    134	prot_desc->frame_width = 0;
    135
    136	switch (drvdata->slots) {
    137	case 1:
    138		frame_length = MSP_FRAME_LEN_1;
    139		break;
    140
    141	case 2:
    142		frame_length = MSP_FRAME_LEN_2;
    143		break;
    144
    145	case 8:
    146		frame_length = MSP_FRAME_LEN_8;
    147		break;
    148
    149	case 16:
    150		frame_length = MSP_FRAME_LEN_16;
    151		break;
    152	default:
    153		dev_err(dai->dev,
    154			"%s: Error: Unsupported slot-count (slots = %d)!\n",
    155			__func__, drvdata->slots);
    156		return -EINVAL;
    157	}
    158
    159	prot_desc->tx_frame_len_1 = frame_length;
    160	prot_desc->rx_frame_len_1 = frame_length;
    161	prot_desc->tx_frame_len_2 = frame_length;
    162	prot_desc->rx_frame_len_2 = frame_length;
    163
    164	prot_desc->tx_elem_len_1 = MSP_ELEM_LEN_16;
    165	prot_desc->rx_elem_len_1 = MSP_ELEM_LEN_16;
    166	prot_desc->tx_elem_len_2 = MSP_ELEM_LEN_16;
    167	prot_desc->rx_elem_len_2 = MSP_ELEM_LEN_16;
    168
    169	return setup_frameper(dai, rate, prot_desc);
    170}
    171
    172static int setup_clocking(struct snd_soc_dai *dai,
    173			unsigned int fmt,
    174			struct ux500_msp_config *msp_config)
    175{
    176	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
    177	case SND_SOC_DAIFMT_NB_NF:
    178		break;
    179
    180	case SND_SOC_DAIFMT_NB_IF:
    181		msp_config->tx_fsync_pol ^= 1 << TFSPOL_SHIFT;
    182		msp_config->rx_fsync_pol ^= 1 << RFSPOL_SHIFT;
    183
    184		break;
    185
    186	default:
    187		dev_err(dai->dev,
    188			"%s: Error: Unsupported inversion (fmt = 0x%x)!\n",
    189			__func__, fmt);
    190
    191		return -EINVAL;
    192	}
    193
    194	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
    195	case SND_SOC_DAIFMT_CBM_CFM:
    196		dev_dbg(dai->dev, "%s: Codec is master.\n", __func__);
    197
    198		msp_config->iodelay = 0x20;
    199		msp_config->rx_fsync_sel = 0;
    200		msp_config->tx_fsync_sel = 1 << TFSSEL_SHIFT;
    201		msp_config->tx_clk_sel = 0;
    202		msp_config->rx_clk_sel = 0;
    203		msp_config->srg_clk_sel = 0x2 << SCKSEL_SHIFT;
    204
    205		break;
    206
    207	case SND_SOC_DAIFMT_CBS_CFS:
    208		dev_dbg(dai->dev, "%s: Codec is slave.\n", __func__);
    209
    210		msp_config->tx_clk_sel = TX_CLK_SEL_SRG;
    211		msp_config->tx_fsync_sel = TX_SYNC_SRG_PROG;
    212		msp_config->rx_clk_sel = RX_CLK_SEL_SRG;
    213		msp_config->rx_fsync_sel = RX_SYNC_SRG;
    214		msp_config->srg_clk_sel = 1 << SCKSEL_SHIFT;
    215
    216		break;
    217
    218	default:
    219		dev_err(dai->dev, "%s: Error: Unsupported master (fmt = 0x%x)!\n",
    220			__func__, fmt);
    221
    222		return -EINVAL;
    223	}
    224
    225	return 0;
    226}
    227
    228static int setup_pcm_protdesc(struct snd_soc_dai *dai,
    229				unsigned int fmt,
    230				struct msp_protdesc *prot_desc)
    231{
    232	prot_desc->rx_phase_mode = MSP_SINGLE_PHASE;
    233	prot_desc->tx_phase_mode = MSP_SINGLE_PHASE;
    234	prot_desc->rx_phase2_start_mode = MSP_PHASE2_START_MODE_IMEDIATE;
    235	prot_desc->tx_phase2_start_mode = MSP_PHASE2_START_MODE_IMEDIATE;
    236	prot_desc->rx_byte_order = MSP_BTF_MS_BIT_FIRST;
    237	prot_desc->tx_byte_order = MSP_BTF_MS_BIT_FIRST;
    238	prot_desc->tx_fsync_pol = MSP_FSYNC_POL(MSP_FSYNC_POL_ACT_HI);
    239	prot_desc->rx_fsync_pol = MSP_FSYNC_POL_ACT_HI << RFSPOL_SHIFT;
    240
    241	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A) {
    242		dev_dbg(dai->dev, "%s: DSP_A.\n", __func__);
    243		prot_desc->rx_clk_pol = MSP_RISING_EDGE;
    244		prot_desc->tx_clk_pol = MSP_FALLING_EDGE;
    245
    246		prot_desc->rx_data_delay = MSP_DELAY_1;
    247		prot_desc->tx_data_delay = MSP_DELAY_1;
    248	} else {
    249		dev_dbg(dai->dev, "%s: DSP_B.\n", __func__);
    250		prot_desc->rx_clk_pol = MSP_FALLING_EDGE;
    251		prot_desc->tx_clk_pol = MSP_RISING_EDGE;
    252
    253		prot_desc->rx_data_delay = MSP_DELAY_0;
    254		prot_desc->tx_data_delay = MSP_DELAY_0;
    255	}
    256
    257	prot_desc->rx_half_word_swap = MSP_SWAP_NONE;
    258	prot_desc->tx_half_word_swap = MSP_SWAP_NONE;
    259	prot_desc->compression_mode = MSP_COMPRESS_MODE_LINEAR;
    260	prot_desc->expansion_mode = MSP_EXPAND_MODE_LINEAR;
    261	prot_desc->frame_sync_ignore = MSP_FSYNC_IGNORE;
    262
    263	return 0;
    264}
    265
    266static int setup_i2s_protdesc(struct msp_protdesc *prot_desc)
    267{
    268	prot_desc->rx_phase_mode = MSP_DUAL_PHASE;
    269	prot_desc->tx_phase_mode = MSP_DUAL_PHASE;
    270	prot_desc->rx_phase2_start_mode = MSP_PHASE2_START_MODE_FSYNC;
    271	prot_desc->tx_phase2_start_mode = MSP_PHASE2_START_MODE_FSYNC;
    272	prot_desc->rx_byte_order = MSP_BTF_MS_BIT_FIRST;
    273	prot_desc->tx_byte_order = MSP_BTF_MS_BIT_FIRST;
    274	prot_desc->tx_fsync_pol = MSP_FSYNC_POL(MSP_FSYNC_POL_ACT_LO);
    275	prot_desc->rx_fsync_pol = MSP_FSYNC_POL_ACT_LO << RFSPOL_SHIFT;
    276
    277	prot_desc->rx_frame_len_1 = MSP_FRAME_LEN_1;
    278	prot_desc->rx_frame_len_2 = MSP_FRAME_LEN_1;
    279	prot_desc->tx_frame_len_1 = MSP_FRAME_LEN_1;
    280	prot_desc->tx_frame_len_2 = MSP_FRAME_LEN_1;
    281	prot_desc->rx_elem_len_1 = MSP_ELEM_LEN_16;
    282	prot_desc->rx_elem_len_2 = MSP_ELEM_LEN_16;
    283	prot_desc->tx_elem_len_1 = MSP_ELEM_LEN_16;
    284	prot_desc->tx_elem_len_2 = MSP_ELEM_LEN_16;
    285
    286	prot_desc->rx_clk_pol = MSP_RISING_EDGE;
    287	prot_desc->tx_clk_pol = MSP_FALLING_EDGE;
    288
    289	prot_desc->rx_data_delay = MSP_DELAY_0;
    290	prot_desc->tx_data_delay = MSP_DELAY_0;
    291
    292	prot_desc->tx_half_word_swap = MSP_SWAP_NONE;
    293	prot_desc->rx_half_word_swap = MSP_SWAP_NONE;
    294	prot_desc->compression_mode = MSP_COMPRESS_MODE_LINEAR;
    295	prot_desc->expansion_mode = MSP_EXPAND_MODE_LINEAR;
    296	prot_desc->frame_sync_ignore = MSP_FSYNC_IGNORE;
    297
    298	return 0;
    299}
    300
    301static int setup_msp_config(struct snd_pcm_substream *substream,
    302			struct snd_soc_dai *dai,
    303			struct ux500_msp_config *msp_config)
    304{
    305	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
    306	struct msp_protdesc *prot_desc = &msp_config->protdesc;
    307	struct snd_pcm_runtime *runtime = substream->runtime;
    308	unsigned int fmt = drvdata->fmt;
    309	int ret;
    310
    311	memset(msp_config, 0, sizeof(*msp_config));
    312
    313	msp_config->f_inputclk = drvdata->master_clk;
    314
    315	msp_config->tx_fifo_config = TX_FIFO_ENABLE;
    316	msp_config->rx_fifo_config = RX_FIFO_ENABLE;
    317	msp_config->def_elem_len = 1;
    318	msp_config->direction = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
    319				MSP_DIR_TX : MSP_DIR_RX;
    320	msp_config->data_size = MSP_DATA_BITS_32;
    321	msp_config->frame_freq = runtime->rate;
    322
    323	dev_dbg(dai->dev, "%s: f_inputclk = %u, frame_freq = %u.\n",
    324	       __func__, msp_config->f_inputclk, msp_config->frame_freq);
    325	/* To avoid division by zero */
    326	prot_desc->clocks_per_frame = 1;
    327
    328	dev_dbg(dai->dev, "%s: rate: %u, channels: %d.\n", __func__,
    329		runtime->rate, runtime->channels);
    330	switch (fmt &
    331		(SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
    332	case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
    333		dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__);
    334
    335		msp_config->default_protdesc = 1;
    336		msp_config->protocol = MSP_I2S_PROTOCOL;
    337		break;
    338
    339	case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
    340		dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__);
    341
    342		msp_config->data_size = MSP_DATA_BITS_16;
    343		msp_config->protocol = MSP_I2S_PROTOCOL;
    344
    345		ret = setup_i2s_protdesc(prot_desc);
    346		if (ret < 0)
    347			return ret;
    348
    349		break;
    350
    351	case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
    352	case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
    353	case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS:
    354	case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM:
    355		dev_dbg(dai->dev, "%s: PCM format.\n", __func__);
    356
    357		msp_config->data_size = MSP_DATA_BITS_16;
    358		msp_config->protocol = MSP_PCM_PROTOCOL;
    359
    360		ret = setup_pcm_protdesc(dai, fmt, prot_desc);
    361		if (ret < 0)
    362			return ret;
    363
    364		ret = setup_pcm_multichan(dai, msp_config);
    365		if (ret < 0)
    366			return ret;
    367
    368		ret = setup_pcm_framing(dai, runtime->rate, prot_desc);
    369		if (ret < 0)
    370			return ret;
    371
    372		break;
    373
    374	default:
    375		dev_err(dai->dev, "%s: Error: Unsupported format (%d)!\n",
    376			__func__, fmt);
    377		return -EINVAL;
    378	}
    379
    380	return setup_clocking(dai, fmt, msp_config);
    381}
    382
    383static int ux500_msp_dai_startup(struct snd_pcm_substream *substream,
    384				struct snd_soc_dai *dai)
    385{
    386	int ret = 0;
    387	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
    388
    389	dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
    390		snd_pcm_stream_str(substream));
    391
    392	/* Enable regulator */
    393	ret = regulator_enable(drvdata->reg_vape);
    394	if (ret != 0) {
    395		dev_err(drvdata->msp->dev,
    396			"%s: Failed to enable regulator!\n", __func__);
    397		return ret;
    398	}
    399
    400	/* Prepare and enable clocks */
    401	dev_dbg(dai->dev, "%s: Enabling MSP-clocks.\n", __func__);
    402	ret = clk_prepare_enable(drvdata->pclk);
    403	if (ret) {
    404		dev_err(drvdata->msp->dev,
    405			"%s: Failed to prepare/enable pclk!\n", __func__);
    406		goto err_pclk;
    407	}
    408
    409	ret = clk_prepare_enable(drvdata->clk);
    410	if (ret) {
    411		dev_err(drvdata->msp->dev,
    412			"%s: Failed to prepare/enable clk!\n", __func__);
    413		goto err_clk;
    414	}
    415
    416	return ret;
    417err_clk:
    418	clk_disable_unprepare(drvdata->pclk);
    419err_pclk:
    420	regulator_disable(drvdata->reg_vape);
    421	return ret;
    422}
    423
    424static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
    425				struct snd_soc_dai *dai)
    426{
    427	int ret;
    428	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
    429	bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
    430
    431	dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
    432		snd_pcm_stream_str(substream));
    433
    434	if (drvdata->vape_opp_constraint == 1) {
    435		prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
    436					"ux500_msp_i2s", 50);
    437		drvdata->vape_opp_constraint = 0;
    438	}
    439
    440	if (ux500_msp_i2s_close(drvdata->msp,
    441				is_playback ? MSP_DIR_TX : MSP_DIR_RX)) {
    442		dev_err(dai->dev,
    443			"%s: Error: MSP %d (%s): Unable to close i2s.\n",
    444			__func__, dai->id, snd_pcm_stream_str(substream));
    445	}
    446
    447	/* Disable and unprepare clocks */
    448	clk_disable_unprepare(drvdata->clk);
    449	clk_disable_unprepare(drvdata->pclk);
    450
    451	/* Disable regulator */
    452	ret = regulator_disable(drvdata->reg_vape);
    453	if (ret < 0)
    454		dev_err(dai->dev,
    455			"%s: ERROR: Failed to disable regulator (%d)!\n",
    456			__func__, ret);
    457}
    458
    459static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream,
    460				struct snd_soc_dai *dai)
    461{
    462	int ret = 0;
    463	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
    464	struct snd_pcm_runtime *runtime = substream->runtime;
    465	struct ux500_msp_config msp_config;
    466
    467	dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (rate = %d).\n", __func__,
    468		dai->id, snd_pcm_stream_str(substream), runtime->rate);
    469
    470	setup_msp_config(substream, dai, &msp_config);
    471
    472	ret = ux500_msp_i2s_open(drvdata->msp, &msp_config);
    473	if (ret < 0) {
    474		dev_err(dai->dev, "%s: Error: msp_setup failed (ret = %d)!\n",
    475			__func__, ret);
    476		return ret;
    477	}
    478
    479	/* Set OPP-level */
    480	if ((drvdata->fmt & SND_SOC_DAIFMT_MASTER_MASK) &&
    481		(drvdata->msp->f_bitclk > 19200000)) {
    482		/* If the bit-clock is higher than 19.2MHz, Vape should be
    483		 * run in 100% OPP. Only when bit-clock is used (MSP master)
    484		 */
    485		prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
    486					"ux500-msp-i2s", 100);
    487		drvdata->vape_opp_constraint = 1;
    488	} else {
    489		prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
    490					"ux500-msp-i2s", 50);
    491		drvdata->vape_opp_constraint = 0;
    492	}
    493
    494	return ret;
    495}
    496
    497static int ux500_msp_dai_hw_params(struct snd_pcm_substream *substream,
    498				struct snd_pcm_hw_params *params,
    499				struct snd_soc_dai *dai)
    500{
    501	unsigned int mask, slots_active;
    502	struct snd_pcm_runtime *runtime = substream->runtime;
    503	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
    504
    505	dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n",
    506			__func__, dai->id, snd_pcm_stream_str(substream));
    507
    508	switch (drvdata->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
    509	case SND_SOC_DAIFMT_I2S:
    510		snd_pcm_hw_constraint_minmax(runtime,
    511				SNDRV_PCM_HW_PARAM_CHANNELS,
    512				1, 2);
    513		break;
    514
    515	case SND_SOC_DAIFMT_DSP_B:
    516	case SND_SOC_DAIFMT_DSP_A:
    517		mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
    518			drvdata->tx_mask :
    519			drvdata->rx_mask;
    520
    521		slots_active = hweight32(mask);
    522		dev_dbg(dai->dev, "TDM-slots active: %d", slots_active);
    523
    524		snd_pcm_hw_constraint_single(runtime,
    525				SNDRV_PCM_HW_PARAM_CHANNELS,
    526				slots_active);
    527		break;
    528
    529	default:
    530		dev_err(dai->dev,
    531			"%s: Error: Unsupported protocol (fmt = 0x%x)!\n",
    532			__func__, drvdata->fmt);
    533		return -EINVAL;
    534	}
    535
    536	return 0;
    537}
    538
    539static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *dai,
    540				unsigned int fmt)
    541{
    542	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
    543
    544	dev_dbg(dai->dev, "%s: MSP %d: Enter.\n", __func__, dai->id);
    545
    546	switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK |
    547		SND_SOC_DAIFMT_MASTER_MASK)) {
    548	case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
    549	case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
    550	case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS:
    551	case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM:
    552	case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
    553	case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
    554		break;
    555
    556	default:
    557		dev_err(dai->dev,
    558			"%s: Error: Unsupported protocol/master (fmt = 0x%x)!\n",
    559			__func__, drvdata->fmt);
    560		return -EINVAL;
    561	}
    562
    563	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
    564	case SND_SOC_DAIFMT_NB_NF:
    565	case SND_SOC_DAIFMT_NB_IF:
    566	case SND_SOC_DAIFMT_IB_IF:
    567		break;
    568
    569	default:
    570		dev_err(dai->dev,
    571			"%s: Error: Unsupported inversion (fmt = 0x%x)!\n",
    572			__func__, drvdata->fmt);
    573		return -EINVAL;
    574	}
    575
    576	drvdata->fmt = fmt;
    577	return 0;
    578}
    579
    580static int ux500_msp_dai_set_tdm_slot(struct snd_soc_dai *dai,
    581				unsigned int tx_mask,
    582				unsigned int rx_mask,
    583				int slots, int slot_width)
    584{
    585	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
    586	unsigned int cap;
    587
    588	switch (slots) {
    589	case 1:
    590		cap = 0x01;
    591		break;
    592	case 2:
    593		cap = 0x03;
    594		break;
    595	case 8:
    596		cap = 0xFF;
    597		break;
    598	case 16:
    599		cap = 0xFFFF;
    600		break;
    601	default:
    602		dev_err(dai->dev, "%s: Error: Unsupported slot-count (%d)!\n",
    603			__func__, slots);
    604		return -EINVAL;
    605	}
    606	drvdata->slots = slots;
    607
    608	if (!(slot_width == 16)) {
    609		dev_err(dai->dev, "%s: Error: Unsupported slot-width (%d)!\n",
    610			__func__, slot_width);
    611		return -EINVAL;
    612	}
    613	drvdata->slot_width = slot_width;
    614
    615	drvdata->tx_mask = tx_mask & cap;
    616	drvdata->rx_mask = rx_mask & cap;
    617
    618	return 0;
    619}
    620
    621static int ux500_msp_dai_set_dai_sysclk(struct snd_soc_dai *dai,
    622					int clk_id, unsigned int freq, int dir)
    623{
    624	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
    625
    626	dev_dbg(dai->dev, "%s: MSP %d: Enter. clk-id: %d, freq: %u.\n",
    627		__func__, dai->id, clk_id, freq);
    628
    629	switch (clk_id) {
    630	case UX500_MSP_MASTER_CLOCK:
    631		drvdata->master_clk = freq;
    632		break;
    633
    634	default:
    635		dev_err(dai->dev, "%s: MSP %d: Invalid clk-id (%d)!\n",
    636			__func__, dai->id, clk_id);
    637		return -EINVAL;
    638	}
    639
    640	return 0;
    641}
    642
    643static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream,
    644				int cmd, struct snd_soc_dai *dai)
    645{
    646	int ret = 0;
    647	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
    648
    649	dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (msp->id = %d, cmd = %d).\n",
    650		__func__, dai->id, snd_pcm_stream_str(substream),
    651		(int)drvdata->msp->id, cmd);
    652
    653	ret = ux500_msp_i2s_trigger(drvdata->msp, cmd, substream->stream);
    654
    655	return ret;
    656}
    657
    658static int ux500_msp_dai_of_probe(struct snd_soc_dai *dai)
    659{
    660	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
    661	struct snd_dmaengine_dai_dma_data *playback_dma_data;
    662	struct snd_dmaengine_dai_dma_data *capture_dma_data;
    663
    664	playback_dma_data = devm_kzalloc(dai->dev,
    665					 sizeof(*playback_dma_data),
    666					 GFP_KERNEL);
    667	if (!playback_dma_data)
    668		return -ENOMEM;
    669
    670	capture_dma_data = devm_kzalloc(dai->dev,
    671					sizeof(*capture_dma_data),
    672					GFP_KERNEL);
    673	if (!capture_dma_data)
    674		return -ENOMEM;
    675
    676	playback_dma_data->addr = drvdata->msp->playback_dma_data.tx_rx_addr;
    677	capture_dma_data->addr = drvdata->msp->capture_dma_data.tx_rx_addr;
    678
    679	playback_dma_data->maxburst = 4;
    680	capture_dma_data->maxburst = 4;
    681
    682	snd_soc_dai_init_dma_data(dai, playback_dma_data, capture_dma_data);
    683
    684	return 0;
    685}
    686
    687static int ux500_msp_dai_probe(struct snd_soc_dai *dai)
    688{
    689	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
    690	struct msp_i2s_platform_data *pdata = dai->dev->platform_data;
    691	int ret;
    692
    693	if (!pdata) {
    694		ret = ux500_msp_dai_of_probe(dai);
    695		return ret;
    696	}
    697
    698	drvdata->msp->playback_dma_data.data_size = drvdata->slot_width;
    699	drvdata->msp->capture_dma_data.data_size = drvdata->slot_width;
    700
    701	snd_soc_dai_init_dma_data(dai,
    702				  &drvdata->msp->playback_dma_data,
    703				  &drvdata->msp->capture_dma_data);
    704	return 0;
    705}
    706
    707static const struct snd_soc_dai_ops ux500_msp_dai_ops[] = {
    708	{
    709		.set_sysclk = ux500_msp_dai_set_dai_sysclk,
    710		.set_fmt = ux500_msp_dai_set_dai_fmt,
    711		.set_tdm_slot = ux500_msp_dai_set_tdm_slot,
    712		.startup = ux500_msp_dai_startup,
    713		.shutdown = ux500_msp_dai_shutdown,
    714		.prepare = ux500_msp_dai_prepare,
    715		.trigger = ux500_msp_dai_trigger,
    716		.hw_params = ux500_msp_dai_hw_params,
    717	}
    718};
    719
    720static struct snd_soc_dai_driver ux500_msp_dai_drv = {
    721	.probe                 = ux500_msp_dai_probe,
    722	.playback.channels_min = UX500_MSP_MIN_CHANNELS,
    723	.playback.channels_max = UX500_MSP_MAX_CHANNELS,
    724	.playback.rates        = UX500_I2S_RATES,
    725	.playback.formats      = UX500_I2S_FORMATS,
    726	.capture.channels_min  = UX500_MSP_MIN_CHANNELS,
    727	.capture.channels_max  = UX500_MSP_MAX_CHANNELS,
    728	.capture.rates         = UX500_I2S_RATES,
    729	.capture.formats       = UX500_I2S_FORMATS,
    730	.ops                   = ux500_msp_dai_ops,
    731};
    732
    733static const struct snd_soc_component_driver ux500_msp_component = {
    734	.name		= "ux500-msp",
    735};
    736
    737
    738static int ux500_msp_drv_probe(struct platform_device *pdev)
    739{
    740	struct ux500_msp_i2s_drvdata *drvdata;
    741	struct msp_i2s_platform_data *pdata = pdev->dev.platform_data;
    742	struct device_node *np = pdev->dev.of_node;
    743	int ret = 0;
    744
    745	if (!pdata && !np) {
    746		dev_err(&pdev->dev, "No platform data or Device Tree found\n");
    747		return -ENODEV;
    748	}
    749
    750	drvdata = devm_kzalloc(&pdev->dev,
    751				sizeof(struct ux500_msp_i2s_drvdata),
    752				GFP_KERNEL);
    753	if (!drvdata)
    754		return -ENOMEM;
    755
    756	drvdata->fmt = 0;
    757	drvdata->slots = 1;
    758	drvdata->tx_mask = 0x01;
    759	drvdata->rx_mask = 0x01;
    760	drvdata->slot_width = 16;
    761	drvdata->master_clk = MSP_INPUT_FREQ_APB;
    762
    763	drvdata->reg_vape = devm_regulator_get(&pdev->dev, "v-ape");
    764	if (IS_ERR(drvdata->reg_vape)) {
    765		ret = (int)PTR_ERR(drvdata->reg_vape);
    766		dev_err(&pdev->dev,
    767			"%s: ERROR: Failed to get Vape supply (%d)!\n",
    768			__func__, ret);
    769		return ret;
    770	}
    771	prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)pdev->name, 50);
    772
    773	drvdata->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
    774	if (IS_ERR(drvdata->pclk)) {
    775		ret = (int)PTR_ERR(drvdata->pclk);
    776		dev_err(&pdev->dev,
    777			"%s: ERROR: devm_clk_get of pclk failed (%d)!\n",
    778			__func__, ret);
    779		return ret;
    780	}
    781
    782	drvdata->clk = devm_clk_get(&pdev->dev, NULL);
    783	if (IS_ERR(drvdata->clk)) {
    784		ret = (int)PTR_ERR(drvdata->clk);
    785		dev_err(&pdev->dev,
    786			"%s: ERROR: devm_clk_get failed (%d)!\n",
    787			__func__, ret);
    788		return ret;
    789	}
    790
    791	ret = ux500_msp_i2s_init_msp(pdev, &drvdata->msp,
    792				pdev->dev.platform_data);
    793	if (!drvdata->msp) {
    794		dev_err(&pdev->dev,
    795			"%s: ERROR: Failed to init MSP-struct (%d)!",
    796			__func__, ret);
    797		return ret;
    798	}
    799	dev_set_drvdata(&pdev->dev, drvdata);
    800
    801	ret = snd_soc_register_component(&pdev->dev, &ux500_msp_component,
    802					 &ux500_msp_dai_drv, 1);
    803	if (ret < 0) {
    804		dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n",
    805			__func__, drvdata->msp->id);
    806		return ret;
    807	}
    808
    809	ret = ux500_pcm_register_platform(pdev);
    810	if (ret < 0) {
    811		dev_err(&pdev->dev,
    812			"Error: %s: Failed to register PCM platform device!\n",
    813			__func__);
    814		goto err_reg_plat;
    815	}
    816
    817	return 0;
    818
    819err_reg_plat:
    820	snd_soc_unregister_component(&pdev->dev);
    821	return ret;
    822}
    823
    824static int ux500_msp_drv_remove(struct platform_device *pdev)
    825{
    826	struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
    827
    828	ux500_pcm_unregister_platform(pdev);
    829
    830	snd_soc_unregister_component(&pdev->dev);
    831
    832	prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s");
    833
    834	ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp);
    835
    836	return 0;
    837}
    838
    839static const struct of_device_id ux500_msp_i2s_match[] = {
    840	{ .compatible = "stericsson,ux500-msp-i2s", },
    841	{},
    842};
    843MODULE_DEVICE_TABLE(of, ux500_msp_i2s_match);
    844
    845static struct platform_driver msp_i2s_driver = {
    846	.driver = {
    847		.name = "ux500-msp-i2s",
    848		.of_match_table = ux500_msp_i2s_match,
    849	},
    850	.probe = ux500_msp_drv_probe,
    851	.remove = ux500_msp_drv_remove,
    852};
    853module_platform_driver(msp_i2s_driver);
    854
    855MODULE_LICENSE("GPL v2");