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

audio_codec.c (29083B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * APBridge ALSA SoC dummy codec driver
      4 * Copyright 2016 Google Inc.
      5 * Copyright 2016 Linaro Ltd.
      6 */
      7#include <linux/kernel.h>
      8#include <linux/module.h>
      9#include <linux/pm_runtime.h>
     10#include <sound/soc.h>
     11#include <sound/pcm_params.h>
     12#include <uapi/linux/input.h>
     13
     14#include "audio_codec.h"
     15#include "audio_apbridgea.h"
     16#include "audio_manager.h"
     17#include "audio_helper.h"
     18
     19static struct gbaudio_codec_info *gbcodec;
     20
     21static struct gbaudio_data_connection *
     22find_data(struct gbaudio_module_info *module, int id)
     23{
     24	struct gbaudio_data_connection *data;
     25
     26	list_for_each_entry(data, &module->data_list, list) {
     27		if (id == data->id)
     28			return data;
     29	}
     30	return NULL;
     31}
     32
     33static struct gbaudio_stream_params *
     34find_dai_stream_params(struct gbaudio_codec_info *codec, int id, int stream)
     35{
     36	struct gbaudio_codec_dai *dai;
     37
     38	list_for_each_entry(dai, &codec->dai_list, list) {
     39		if (dai->id == id)
     40			return &dai->params[stream];
     41	}
     42	return NULL;
     43}
     44
     45static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec,
     46				    struct gbaudio_module_info *module, int id)
     47{
     48	int module_state, ret = 0;
     49	u16 data_cport, i2s_port, cportid;
     50	u8 sig_bits, channels;
     51	u32 format, rate;
     52	struct gbaudio_data_connection *data;
     53	struct gbaudio_stream_params *params;
     54
     55	/* find the dai */
     56	data = find_data(module, id);
     57	if (!data) {
     58		dev_err(module->dev, "%d:DATA connection missing\n", id);
     59		return -ENODEV;
     60	}
     61	module_state = data->state[SNDRV_PCM_STREAM_PLAYBACK];
     62
     63	params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_PLAYBACK);
     64	if (!params) {
     65		dev_err(codec->dev, "Failed to fetch dai_stream pointer\n");
     66		return -EINVAL;
     67	}
     68
     69	/* register cport */
     70	if (module_state < GBAUDIO_CODEC_STARTUP) {
     71		i2s_port = 0;	/* fixed for now */
     72		cportid = data->connection->hd_cport_id;
     73		ret = gb_audio_apbridgea_register_cport(data->connection,
     74							i2s_port, cportid,
     75							AUDIO_APBRIDGEA_DIRECTION_TX);
     76		if (ret) {
     77			dev_err_ratelimited(module->dev, "reg_cport failed:%d\n", ret);
     78			return ret;
     79		}
     80		data->state[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_STARTUP;
     81		dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid);
     82	}
     83
     84	/* hw_params */
     85	if (module_state < GBAUDIO_CODEC_HWPARAMS) {
     86		format = params->format;
     87		channels = params->channels;
     88		rate = params->rate;
     89		sig_bits = params->sig_bits;
     90		data_cport = data->connection->intf_cport_id;
     91		ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport,
     92					  format, rate, channels, sig_bits);
     93		if (ret) {
     94			dev_err_ratelimited(module->dev, "set_pcm failed:%d\n", ret);
     95			return ret;
     96		}
     97		data->state[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_HWPARAMS;
     98		dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport);
     99	}
    100
    101	/* prepare */
    102	if (module_state < GBAUDIO_CODEC_PREPARE) {
    103		data_cport = data->connection->intf_cport_id;
    104		ret = gb_audio_gb_set_tx_data_size(module->mgmt_connection,
    105						   data_cport, 192);
    106		if (ret) {
    107			dev_err_ratelimited(module->dev,
    108					    "set_tx_data_size failed:%d\n",
    109					    ret);
    110			return ret;
    111		}
    112		ret = gb_audio_gb_activate_tx(module->mgmt_connection, data_cport);
    113		if (ret) {
    114			dev_err_ratelimited(module->dev,
    115					    "activate_tx failed:%d\n", ret);
    116			return ret;
    117		}
    118		data->state[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_PREPARE;
    119		dev_dbg(module->dev, "Dynamic prepare %d DAI\n", data_cport);
    120	}
    121
    122	return 0;
    123}
    124
    125static int gbaudio_module_disable_tx(struct gbaudio_module_info *module, int id)
    126{
    127	int ret;
    128	u16 data_cport, cportid, i2s_port;
    129	int module_state;
    130	struct gbaudio_data_connection *data;
    131
    132	/* find the dai */
    133	data = find_data(module, id);
    134	if (!data) {
    135		dev_err(module->dev, "%d:DATA connection missing\n", id);
    136		return -ENODEV;
    137	}
    138	module_state = data->state[SNDRV_PCM_STREAM_PLAYBACK];
    139
    140	if (module_state > GBAUDIO_CODEC_HWPARAMS) {
    141		data_cport = data->connection->intf_cport_id;
    142		ret = gb_audio_gb_deactivate_tx(module->mgmt_connection,
    143						data_cport);
    144		if (ret) {
    145			dev_err_ratelimited(module->dev,
    146					    "deactivate_tx failed:%d\n", ret);
    147			return ret;
    148		}
    149		dev_dbg(module->dev, "Dynamic deactivate %d DAI\n", data_cport);
    150		data->state[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_HWPARAMS;
    151	}
    152
    153	if (module_state > GBAUDIO_CODEC_SHUTDOWN) {
    154		i2s_port = 0;	/* fixed for now */
    155		cportid = data->connection->hd_cport_id;
    156		ret = gb_audio_apbridgea_unregister_cport(data->connection,
    157							  i2s_port, cportid,
    158							  AUDIO_APBRIDGEA_DIRECTION_TX);
    159		if (ret) {
    160			dev_err_ratelimited(module->dev,
    161					    "unregister_cport failed:%d\n", ret);
    162			return ret;
    163		}
    164		dev_dbg(module->dev, "Dynamic Unregister %d DAI\n", cportid);
    165		data->state[SNDRV_PCM_STREAM_PLAYBACK] = GBAUDIO_CODEC_SHUTDOWN;
    166	}
    167
    168	return 0;
    169}
    170
    171static int gbaudio_module_enable_rx(struct gbaudio_codec_info *codec,
    172				    struct gbaudio_module_info *module, int id)
    173{
    174	int module_state, ret = 0;
    175	u16 data_cport, i2s_port, cportid;
    176	u8 sig_bits, channels;
    177	u32 format, rate;
    178	struct gbaudio_data_connection *data;
    179	struct gbaudio_stream_params *params;
    180
    181	/* find the dai */
    182	data = find_data(module, id);
    183	if (!data) {
    184		dev_err(module->dev, "%d:DATA connection missing\n", id);
    185		return -ENODEV;
    186	}
    187	module_state = data->state[SNDRV_PCM_STREAM_CAPTURE];
    188
    189	params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_CAPTURE);
    190	if (!params) {
    191		dev_err(codec->dev, "Failed to fetch dai_stream pointer\n");
    192		return -EINVAL;
    193	}
    194
    195	/* register cport */
    196	if (module_state < GBAUDIO_CODEC_STARTUP) {
    197		i2s_port = 0;	/* fixed for now */
    198		cportid = data->connection->hd_cport_id;
    199		ret = gb_audio_apbridgea_register_cport(data->connection,
    200							i2s_port, cportid,
    201							AUDIO_APBRIDGEA_DIRECTION_RX);
    202		if (ret) {
    203			dev_err_ratelimited(module->dev, "reg_cport failed:%d\n", ret);
    204			return ret;
    205		}
    206		data->state[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_STARTUP;
    207		dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid);
    208	}
    209
    210	/* hw_params */
    211	if (module_state < GBAUDIO_CODEC_HWPARAMS) {
    212		format = params->format;
    213		channels = params->channels;
    214		rate = params->rate;
    215		sig_bits = params->sig_bits;
    216		data_cport = data->connection->intf_cport_id;
    217		ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport,
    218					  format, rate, channels, sig_bits);
    219		if (ret) {
    220			dev_err_ratelimited(module->dev, "set_pcm failed:%d\n", ret);
    221			return ret;
    222		}
    223		data->state[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_HWPARAMS;
    224		dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport);
    225	}
    226
    227	/* prepare */
    228	if (module_state < GBAUDIO_CODEC_PREPARE) {
    229		data_cport = data->connection->intf_cport_id;
    230		ret = gb_audio_gb_set_rx_data_size(module->mgmt_connection,
    231						   data_cport, 192);
    232		if (ret) {
    233			dev_err_ratelimited(module->dev,
    234					    "set_rx_data_size failed:%d\n",
    235					    ret);
    236			return ret;
    237		}
    238		ret = gb_audio_gb_activate_rx(module->mgmt_connection,
    239					      data_cport);
    240		if (ret) {
    241			dev_err_ratelimited(module->dev,
    242					    "activate_rx failed:%d\n", ret);
    243			return ret;
    244		}
    245		data->state[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_PREPARE;
    246		dev_dbg(module->dev, "Dynamic prepare %d DAI\n", data_cport);
    247	}
    248
    249	return 0;
    250}
    251
    252static int gbaudio_module_disable_rx(struct gbaudio_module_info *module, int id)
    253{
    254	int ret;
    255	u16 data_cport, cportid, i2s_port;
    256	int module_state;
    257	struct gbaudio_data_connection *data;
    258
    259	/* find the dai */
    260	data = find_data(module, id);
    261	if (!data) {
    262		dev_err(module->dev, "%d:DATA connection missing\n", id);
    263		return -ENODEV;
    264	}
    265	module_state = data->state[SNDRV_PCM_STREAM_CAPTURE];
    266
    267	if (module_state > GBAUDIO_CODEC_HWPARAMS) {
    268		data_cport = data->connection->intf_cport_id;
    269		ret = gb_audio_gb_deactivate_rx(module->mgmt_connection,
    270						data_cport);
    271		if (ret) {
    272			dev_err_ratelimited(module->dev,
    273					    "deactivate_rx failed:%d\n", ret);
    274			return ret;
    275		}
    276		dev_dbg(module->dev, "Dynamic deactivate %d DAI\n", data_cport);
    277		data->state[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_HWPARAMS;
    278	}
    279
    280	if (module_state > GBAUDIO_CODEC_SHUTDOWN) {
    281		i2s_port = 0;	/* fixed for now */
    282		cportid = data->connection->hd_cport_id;
    283		ret = gb_audio_apbridgea_unregister_cport(data->connection,
    284							  i2s_port, cportid,
    285							  AUDIO_APBRIDGEA_DIRECTION_RX);
    286		if (ret) {
    287			dev_err_ratelimited(module->dev,
    288					    "unregister_cport failed:%d\n", ret);
    289			return ret;
    290		}
    291		dev_dbg(module->dev, "Dynamic Unregister %d DAI\n", cportid);
    292		data->state[SNDRV_PCM_STREAM_CAPTURE] = GBAUDIO_CODEC_SHUTDOWN;
    293	}
    294
    295	return 0;
    296}
    297
    298int gbaudio_module_update(struct gbaudio_codec_info *codec,
    299			  struct snd_soc_dapm_widget *w,
    300			  struct gbaudio_module_info *module, int enable)
    301{
    302	int dai_id, ret;
    303	char intf_name[NAME_SIZE], dir[NAME_SIZE];
    304
    305	dev_dbg(module->dev, "%s:Module update %s sequence\n", w->name,
    306		enable ? "Enable" : "Disable");
    307
    308	if ((w->id != snd_soc_dapm_aif_in) && (w->id != snd_soc_dapm_aif_out)) {
    309		dev_dbg(codec->dev, "No action required for %s\n", w->name);
    310		return 0;
    311	}
    312
    313	/* parse dai_id from AIF widget's stream_name */
    314	ret = sscanf(w->sname, "%s %d %s", intf_name, &dai_id, dir);
    315	if (ret < 3) {
    316		dev_err(codec->dev, "Error while parsing dai_id for %s\n", w->name);
    317		return -EINVAL;
    318	}
    319
    320	mutex_lock(&codec->lock);
    321	if (w->id == snd_soc_dapm_aif_in) {
    322		if (enable)
    323			ret = gbaudio_module_enable_tx(codec, module, dai_id);
    324		else
    325			ret = gbaudio_module_disable_tx(module, dai_id);
    326	} else if (w->id == snd_soc_dapm_aif_out) {
    327		if (enable)
    328			ret = gbaudio_module_enable_rx(codec, module, dai_id);
    329		else
    330			ret = gbaudio_module_disable_rx(module, dai_id);
    331	}
    332
    333	mutex_unlock(&codec->lock);
    334
    335	return ret;
    336}
    337EXPORT_SYMBOL(gbaudio_module_update);
    338
    339/*
    340 * codec DAI ops
    341 */
    342static int gbcodec_startup(struct snd_pcm_substream *substream,
    343			   struct snd_soc_dai *dai)
    344{
    345	struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev);
    346	struct gbaudio_stream_params *params;
    347
    348	mutex_lock(&codec->lock);
    349
    350	if (list_empty(&codec->module_list)) {
    351		dev_err(codec->dev, "No codec module available\n");
    352		mutex_unlock(&codec->lock);
    353		return -ENODEV;
    354	}
    355
    356	params = find_dai_stream_params(codec, dai->id, substream->stream);
    357	if (!params) {
    358		dev_err(codec->dev, "Failed to fetch dai_stream pointer\n");
    359		mutex_unlock(&codec->lock);
    360		return -EINVAL;
    361	}
    362	params->state = GBAUDIO_CODEC_STARTUP;
    363	mutex_unlock(&codec->lock);
    364	/* to prevent suspend in case of active audio */
    365	pm_stay_awake(dai->dev);
    366
    367	return 0;
    368}
    369
    370static void gbcodec_shutdown(struct snd_pcm_substream *substream,
    371			     struct snd_soc_dai *dai)
    372{
    373	struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev);
    374	struct gbaudio_stream_params *params;
    375
    376	mutex_lock(&codec->lock);
    377
    378	if (list_empty(&codec->module_list))
    379		dev_info(codec->dev, "No codec module available during shutdown\n");
    380
    381	params = find_dai_stream_params(codec, dai->id, substream->stream);
    382	if (!params) {
    383		dev_err(codec->dev, "Failed to fetch dai_stream pointer\n");
    384		mutex_unlock(&codec->lock);
    385		return;
    386	}
    387	params->state = GBAUDIO_CODEC_SHUTDOWN;
    388	mutex_unlock(&codec->lock);
    389	pm_relax(dai->dev);
    390}
    391
    392static int gbcodec_hw_params(struct snd_pcm_substream *substream,
    393			     struct snd_pcm_hw_params *hwparams,
    394			     struct snd_soc_dai *dai)
    395{
    396	int ret;
    397	u8 sig_bits, channels;
    398	u32 format, rate;
    399	struct gbaudio_module_info *module;
    400	struct gbaudio_data_connection *data;
    401	struct gb_bundle *bundle;
    402	struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev);
    403	struct gbaudio_stream_params *params;
    404
    405	mutex_lock(&codec->lock);
    406
    407	if (list_empty(&codec->module_list)) {
    408		dev_err(codec->dev, "No codec module available\n");
    409		mutex_unlock(&codec->lock);
    410		return -ENODEV;
    411	}
    412
    413	/*
    414	 * assuming, currently only 48000 Hz, 16BIT_LE, stereo
    415	 * is supported, validate params before configuring codec
    416	 */
    417	if (params_channels(hwparams) != 2) {
    418		dev_err(dai->dev, "Invalid channel count:%d\n",
    419			params_channels(hwparams));
    420		mutex_unlock(&codec->lock);
    421		return -EINVAL;
    422	}
    423	channels = params_channels(hwparams);
    424
    425	if (params_rate(hwparams) != 48000) {
    426		dev_err(dai->dev, "Invalid sampling rate:%d\n",
    427			params_rate(hwparams));
    428		mutex_unlock(&codec->lock);
    429		return -EINVAL;
    430	}
    431	rate = GB_AUDIO_PCM_RATE_48000;
    432
    433	if (params_format(hwparams) != SNDRV_PCM_FORMAT_S16_LE) {
    434		dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams));
    435		mutex_unlock(&codec->lock);
    436		return -EINVAL;
    437	}
    438	format = GB_AUDIO_PCM_FMT_S16_LE;
    439
    440	/* find the data connection */
    441	list_for_each_entry(module, &codec->module_list, list) {
    442		data = find_data(module, dai->id);
    443		if (data)
    444			break;
    445	}
    446
    447	if (!data) {
    448		dev_err(dai->dev, "DATA connection missing\n");
    449		mutex_unlock(&codec->lock);
    450		return -EINVAL;
    451	}
    452
    453	params = find_dai_stream_params(codec, dai->id, substream->stream);
    454	if (!params) {
    455		dev_err(codec->dev, "Failed to fetch dai_stream pointer\n");
    456		mutex_unlock(&codec->lock);
    457		return -EINVAL;
    458	}
    459
    460	bundle = to_gb_bundle(module->dev);
    461	ret = gb_pm_runtime_get_sync(bundle);
    462	if (ret) {
    463		mutex_unlock(&codec->lock);
    464		return ret;
    465	}
    466
    467	ret = gb_audio_apbridgea_set_config(data->connection, 0,
    468					    AUDIO_APBRIDGEA_PCM_FMT_16,
    469					    AUDIO_APBRIDGEA_PCM_RATE_48000,
    470					    6144000);
    471	if (ret) {
    472		dev_err_ratelimited(dai->dev, "%d: Error during set_config\n",
    473				    ret);
    474		gb_pm_runtime_put_noidle(bundle);
    475		mutex_unlock(&codec->lock);
    476		return ret;
    477	}
    478
    479	gb_pm_runtime_put_noidle(bundle);
    480
    481	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    482		sig_bits = dai->driver->playback.sig_bits;
    483	else
    484		sig_bits = dai->driver->capture.sig_bits;
    485
    486	params->state = GBAUDIO_CODEC_HWPARAMS;
    487	params->format = format;
    488	params->rate = rate;
    489	params->channels = channels;
    490	params->sig_bits = sig_bits;
    491
    492	mutex_unlock(&codec->lock);
    493	return 0;
    494}
    495
    496static int gbcodec_prepare(struct snd_pcm_substream *substream,
    497			   struct snd_soc_dai *dai)
    498{
    499	int ret;
    500	struct gbaudio_module_info *module = NULL, *iter;
    501	struct gbaudio_data_connection *data;
    502	struct gb_bundle *bundle;
    503	struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev);
    504	struct gbaudio_stream_params *params;
    505
    506	mutex_lock(&codec->lock);
    507
    508	if (list_empty(&codec->module_list)) {
    509		dev_err(codec->dev, "No codec module available\n");
    510		mutex_unlock(&codec->lock);
    511		return -ENODEV;
    512	}
    513
    514	list_for_each_entry(iter, &codec->module_list, list) {
    515		/* find the dai */
    516		data = find_data(iter, dai->id);
    517		if (data) {
    518			module = iter;
    519			break;
    520		}
    521	}
    522	if (!data) {
    523		dev_err(dai->dev, "DATA connection missing\n");
    524		mutex_unlock(&codec->lock);
    525		return -ENODEV;
    526	}
    527
    528	params = find_dai_stream_params(codec, dai->id, substream->stream);
    529	if (!params) {
    530		dev_err(codec->dev, "Failed to fetch dai_stream pointer\n");
    531		mutex_unlock(&codec->lock);
    532		return -EINVAL;
    533	}
    534
    535	bundle = to_gb_bundle(module->dev);
    536	ret = gb_pm_runtime_get_sync(bundle);
    537	if (ret) {
    538		mutex_unlock(&codec->lock);
    539		return ret;
    540	}
    541
    542	switch (substream->stream) {
    543	case SNDRV_PCM_STREAM_PLAYBACK:
    544		ret = gb_audio_apbridgea_set_tx_data_size(data->connection, 0, 192);
    545		break;
    546	case SNDRV_PCM_STREAM_CAPTURE:
    547		ret = gb_audio_apbridgea_set_rx_data_size(data->connection, 0, 192);
    548		break;
    549	}
    550	if (ret) {
    551		gb_pm_runtime_put_noidle(bundle);
    552		mutex_unlock(&codec->lock);
    553		dev_err_ratelimited(dai->dev, "set_data_size failed:%d\n", ret);
    554		return ret;
    555	}
    556
    557	gb_pm_runtime_put_noidle(bundle);
    558
    559	params->state = GBAUDIO_CODEC_PREPARE;
    560	mutex_unlock(&codec->lock);
    561	return 0;
    562}
    563
    564static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
    565{
    566	int ret;
    567	struct gbaudio_data_connection *data;
    568	struct gbaudio_module_info *module = NULL, *iter;
    569	struct gb_bundle *bundle;
    570	struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev);
    571	struct gbaudio_stream_params *params;
    572
    573	dev_dbg(dai->dev, "Mute:%d, Direction:%s\n", mute,
    574		stream ? "CAPTURE" : "PLAYBACK");
    575
    576	mutex_lock(&codec->lock);
    577
    578	params = find_dai_stream_params(codec, dai->id, stream);
    579	if (!params) {
    580		dev_err(codec->dev, "Failed to fetch dai_stream pointer\n");
    581		mutex_unlock(&codec->lock);
    582		return -EINVAL;
    583	}
    584
    585	if (list_empty(&codec->module_list)) {
    586		dev_err(codec->dev, "No codec module available\n");
    587		if (mute) {
    588			params->state = GBAUDIO_CODEC_STOP;
    589			ret = 0;
    590		} else {
    591			ret = -ENODEV;
    592		}
    593		mutex_unlock(&codec->lock);
    594		return ret;
    595	}
    596
    597	list_for_each_entry(iter, &codec->module_list, list) {
    598		/* find the dai */
    599		data = find_data(iter, dai->id);
    600		if (data) {
    601			module = iter;
    602			break;
    603		}
    604	}
    605	if (!data) {
    606		dev_err(dai->dev, "%s DATA connection missing\n",
    607			dai->name);
    608		mutex_unlock(&codec->lock);
    609		return -ENODEV;
    610	}
    611
    612	bundle = to_gb_bundle(module->dev);
    613	ret = gb_pm_runtime_get_sync(bundle);
    614	if (ret) {
    615		mutex_unlock(&codec->lock);
    616		return ret;
    617	}
    618
    619	if (!mute && !stream) {/* start playback */
    620		ret = gb_audio_apbridgea_prepare_tx(data->connection, 0);
    621		if (!ret)
    622			ret = gb_audio_apbridgea_start_tx(data->connection, 0, 0);
    623		params->state = GBAUDIO_CODEC_START;
    624	} else if (!mute && stream) {/* start capture */
    625		ret = gb_audio_apbridgea_prepare_rx(data->connection, 0);
    626		if (!ret)
    627			ret = gb_audio_apbridgea_start_rx(data->connection, 0);
    628		params->state = GBAUDIO_CODEC_START;
    629	} else if (mute && !stream) {/* stop playback */
    630		ret = gb_audio_apbridgea_stop_tx(data->connection, 0);
    631		if (!ret)
    632			ret = gb_audio_apbridgea_shutdown_tx(data->connection, 0);
    633		params->state = GBAUDIO_CODEC_STOP;
    634	} else if (mute && stream) {/* stop capture */
    635		ret = gb_audio_apbridgea_stop_rx(data->connection, 0);
    636		if (!ret)
    637			ret = gb_audio_apbridgea_shutdown_rx(data->connection, 0);
    638		params->state = GBAUDIO_CODEC_STOP;
    639	} else {
    640		ret = -EINVAL;
    641	}
    642
    643	if (ret)
    644		dev_err_ratelimited(dai->dev,
    645				    "%s:Error during %s %s stream:%d\n",
    646				    module->name, mute ? "Mute" : "Unmute",
    647				    stream ? "Capture" : "Playback", ret);
    648
    649	gb_pm_runtime_put_noidle(bundle);
    650	mutex_unlock(&codec->lock);
    651	return ret;
    652}
    653
    654static const struct snd_soc_dai_ops gbcodec_dai_ops = {
    655	.startup = gbcodec_startup,
    656	.shutdown = gbcodec_shutdown,
    657	.hw_params = gbcodec_hw_params,
    658	.prepare = gbcodec_prepare,
    659	.mute_stream = gbcodec_mute_stream,
    660};
    661
    662static struct snd_soc_dai_driver gbaudio_dai[] = {
    663	{
    664		.name = "apb-i2s0",
    665		.id = 0,
    666		.playback = {
    667			.stream_name = "I2S 0 Playback",
    668			.rates = SNDRV_PCM_RATE_48000,
    669			.formats = SNDRV_PCM_FMTBIT_S16_LE,
    670			.rate_max = 48000,
    671			.rate_min = 48000,
    672			.channels_min = 1,
    673			.channels_max = 2,
    674			.sig_bits = 16,
    675		},
    676		.capture = {
    677			.stream_name = "I2S 0 Capture",
    678			.rates = SNDRV_PCM_RATE_48000,
    679			.formats = SNDRV_PCM_FMTBIT_S16_LE,
    680			.rate_max = 48000,
    681			.rate_min = 48000,
    682			.channels_min = 1,
    683			.channels_max = 2,
    684			.sig_bits = 16,
    685		},
    686		.ops = &gbcodec_dai_ops,
    687	},
    688};
    689
    690static int gbaudio_init_jack(struct gbaudio_module_info *module,
    691			     struct snd_soc_card *card)
    692{
    693	int ret;
    694	struct gbaudio_jack *jack, *n;
    695	struct snd_soc_jack_pin *headset, *button;
    696
    697	if (!module->jack_mask)
    698		return 0;
    699
    700	snprintf(module->jack_name, NAME_SIZE, "GB %d Headset Jack",
    701		 module->dev_id);
    702
    703	headset = devm_kzalloc(module->dev, sizeof(*headset), GFP_KERNEL);
    704	if (!headset)
    705		return -ENOMEM;
    706
    707	headset->pin = module->jack_name;
    708	headset->mask = module->jack_mask;
    709	ret = snd_soc_card_jack_new_pins(card, module->jack_name,
    710					 module->jack_mask,
    711					 &module->headset.jack, headset, 1);
    712	if (ret) {
    713		dev_err(module->dev, "Failed to create new jack\n");
    714		return ret;
    715	}
    716
    717	/* Add to module's jack list */
    718	list_add(&module->headset.list, &module->jack_list);
    719
    720	if (!module->button_mask)
    721		return 0;
    722
    723	snprintf(module->button_name, NAME_SIZE, "GB %d Button Jack",
    724		 module->dev_id);
    725	button = devm_kzalloc(module->dev, sizeof(*button), GFP_KERNEL);
    726	if (!button) {
    727		ret = -ENOMEM;
    728		goto free_jacks;
    729	}
    730
    731	button->pin = module->button_name;
    732	button->mask = module->button_mask;
    733	ret = snd_soc_card_jack_new_pins(card, module->button_name,
    734					 module->button_mask,
    735					 &module->button.jack,
    736					 button, 1);
    737	if (ret) {
    738		dev_err(module->dev, "Failed to create button jack\n");
    739		goto free_jacks;
    740	}
    741
    742	/* Add to module's jack list */
    743	list_add(&module->button.list, &module->jack_list);
    744
    745	/*
    746	 * Currently, max 4 buttons are supported with following key mapping
    747	 * BTN_0 = KEY_MEDIA
    748	 * BTN_1 = KEY_VOICECOMMAND
    749	 * BTN_2 = KEY_VOLUMEUP
    750	 * BTN_3 = KEY_VOLUMEDOWN
    751	 */
    752
    753	if (module->button_mask & SND_JACK_BTN_0) {
    754		ret = snd_jack_set_key(module->button.jack.jack, SND_JACK_BTN_0,
    755				       KEY_MEDIA);
    756		if (ret) {
    757			dev_err(module->dev, "Failed to set BTN_0\n");
    758			goto free_jacks;
    759		}
    760	}
    761
    762	if (module->button_mask & SND_JACK_BTN_1) {
    763		ret = snd_jack_set_key(module->button.jack.jack, SND_JACK_BTN_1,
    764				       KEY_VOICECOMMAND);
    765		if (ret) {
    766			dev_err(module->dev, "Failed to set BTN_1\n");
    767			goto free_jacks;
    768		}
    769	}
    770
    771	if (module->button_mask & SND_JACK_BTN_2) {
    772		ret = snd_jack_set_key(module->button.jack.jack, SND_JACK_BTN_2,
    773				       KEY_VOLUMEUP);
    774		if (ret) {
    775			dev_err(module->dev, "Failed to set BTN_2\n");
    776			goto free_jacks;
    777		}
    778	}
    779
    780	if (module->button_mask & SND_JACK_BTN_3) {
    781		ret = snd_jack_set_key(module->button.jack.jack, SND_JACK_BTN_3,
    782				       KEY_VOLUMEDOWN);
    783		if (ret) {
    784			dev_err(module->dev, "Failed to set BTN_0\n");
    785			goto free_jacks;
    786		}
    787	}
    788
    789	/* FIXME
    790	 * verify if this is really required
    791	set_bit(INPUT_PROP_NO_DUMMY_RELEASE,
    792		module->button.jack.jack->input_dev->propbit);
    793	*/
    794
    795	return 0;
    796
    797free_jacks:
    798	list_for_each_entry_safe(jack, n, &module->jack_list, list) {
    799		snd_device_free(card->snd_card, jack->jack.jack);
    800		list_del(&jack->list);
    801	}
    802
    803	return ret;
    804}
    805
    806int gbaudio_register_module(struct gbaudio_module_info *module)
    807{
    808	int ret;
    809	struct snd_soc_component *comp;
    810	struct snd_card *card;
    811	struct gbaudio_jack *jack = NULL;
    812
    813	if (!gbcodec) {
    814		dev_err(module->dev, "GB Codec not yet probed\n");
    815		return -EAGAIN;
    816	}
    817
    818	comp = gbcodec->component;
    819	card = comp->card->snd_card;
    820
    821	down_write(&card->controls_rwsem);
    822
    823	if (module->num_dais) {
    824		dev_err(gbcodec->dev,
    825			"%d:DAIs not supported via gbcodec driver\n",
    826			module->num_dais);
    827		up_write(&card->controls_rwsem);
    828		return -EINVAL;
    829	}
    830
    831	ret = gbaudio_init_jack(module, comp->card);
    832	if (ret) {
    833		up_write(&card->controls_rwsem);
    834		return ret;
    835	}
    836
    837	if (module->dapm_widgets)
    838		snd_soc_dapm_new_controls(&comp->dapm, module->dapm_widgets,
    839					  module->num_dapm_widgets);
    840	if (module->controls)
    841		snd_soc_add_component_controls(comp, module->controls,
    842					       module->num_controls);
    843	if (module->dapm_routes)
    844		snd_soc_dapm_add_routes(&comp->dapm, module->dapm_routes,
    845					module->num_dapm_routes);
    846
    847	/* card already instantiated, create widgets here only */
    848	if (comp->card->instantiated) {
    849		gbaudio_dapm_link_component_dai_widgets(comp->card, &comp->dapm);
    850#ifdef CONFIG_SND_JACK
    851		/*
    852		 * register jack devices for this module
    853		 * from codec->jack_list
    854		 */
    855		list_for_each_entry(jack, &module->jack_list, list) {
    856			snd_device_register(comp->card->snd_card,
    857					    jack->jack.jack);
    858		}
    859#endif
    860	}
    861
    862	mutex_lock(&gbcodec->lock);
    863	list_add(&module->list, &gbcodec->module_list);
    864	mutex_unlock(&gbcodec->lock);
    865
    866	if (comp->card->instantiated)
    867		ret = snd_soc_dapm_new_widgets(comp->card);
    868	dev_dbg(comp->dev, "Registered %s module\n", module->name);
    869
    870	up_write(&card->controls_rwsem);
    871	return ret;
    872}
    873EXPORT_SYMBOL(gbaudio_register_module);
    874
    875static void gbaudio_codec_clean_data_tx(struct gbaudio_data_connection *data)
    876{
    877	u16 i2s_port, cportid;
    878	int ret;
    879
    880	if (list_is_singular(&gbcodec->module_list)) {
    881		ret = gb_audio_apbridgea_stop_tx(data->connection, 0);
    882		if (ret)
    883			return;
    884		ret = gb_audio_apbridgea_shutdown_tx(data->connection, 0);
    885		if (ret)
    886			return;
    887	}
    888	i2s_port = 0;	/* fixed for now */
    889	cportid = data->connection->hd_cport_id;
    890	ret = gb_audio_apbridgea_unregister_cport(data->connection,
    891						  i2s_port, cportid,
    892						  AUDIO_APBRIDGEA_DIRECTION_TX);
    893	data->state[0] = GBAUDIO_CODEC_SHUTDOWN;
    894}
    895
    896static void gbaudio_codec_clean_data_rx(struct gbaudio_data_connection *data)
    897{
    898	u16 i2s_port, cportid;
    899	int ret;
    900
    901	if (list_is_singular(&gbcodec->module_list)) {
    902		ret = gb_audio_apbridgea_stop_rx(data->connection, 0);
    903		if (ret)
    904			return;
    905		ret = gb_audio_apbridgea_shutdown_rx(data->connection, 0);
    906		if (ret)
    907			return;
    908	}
    909	i2s_port = 0;	/* fixed for now */
    910	cportid = data->connection->hd_cport_id;
    911	ret = gb_audio_apbridgea_unregister_cport(data->connection,
    912						  i2s_port, cportid,
    913						  AUDIO_APBRIDGEA_DIRECTION_RX);
    914	data->state[1] = GBAUDIO_CODEC_SHUTDOWN;
    915}
    916
    917static void gbaudio_codec_cleanup(struct gbaudio_module_info *module)
    918{
    919	struct gbaudio_data_connection *data;
    920	int pb_state, cap_state;
    921
    922	dev_dbg(gbcodec->dev, "%s: removed, cleanup APBridge\n", module->name);
    923	list_for_each_entry(data, &module->data_list, list) {
    924		pb_state = data->state[0];
    925		cap_state = data->state[1];
    926
    927		if (pb_state > GBAUDIO_CODEC_SHUTDOWN)
    928			gbaudio_codec_clean_data_tx(data);
    929
    930		if (cap_state > GBAUDIO_CODEC_SHUTDOWN)
    931			gbaudio_codec_clean_data_rx(data);
    932	}
    933}
    934
    935void gbaudio_unregister_module(struct gbaudio_module_info *module)
    936{
    937	struct snd_soc_component *comp = gbcodec->component;
    938	struct snd_card *card = comp->card->snd_card;
    939	struct gbaudio_jack *jack, *n;
    940	int mask;
    941
    942	dev_dbg(comp->dev, "Unregister %s module\n", module->name);
    943
    944	down_write(&card->controls_rwsem);
    945	mutex_lock(&gbcodec->lock);
    946	gbaudio_codec_cleanup(module);
    947	list_del(&module->list);
    948	dev_dbg(comp->dev, "Process Unregister %s module\n", module->name);
    949	mutex_unlock(&gbcodec->lock);
    950
    951#ifdef CONFIG_SND_JACK
    952	/* free jack devices for this module jack_list */
    953	list_for_each_entry_safe(jack, n, &module->jack_list, list) {
    954		if (jack == &module->headset)
    955			mask = GBCODEC_JACK_MASK;
    956		else if (jack == &module->button)
    957			mask = GBCODEC_JACK_BUTTON_MASK;
    958		else
    959			mask = 0;
    960		if (mask) {
    961			dev_dbg(module->dev, "Report %s removal\n",
    962				jack->jack.jack->id);
    963			snd_soc_jack_report(&jack->jack, 0, mask);
    964			snd_device_free(comp->card->snd_card,
    965					jack->jack.jack);
    966			list_del(&jack->list);
    967		}
    968	}
    969#endif
    970
    971	if (module->dapm_routes) {
    972		dev_dbg(comp->dev, "Removing %d routes\n",
    973			module->num_dapm_routes);
    974		snd_soc_dapm_del_routes(&comp->dapm, module->dapm_routes,
    975					module->num_dapm_routes);
    976	}
    977	if (module->controls) {
    978		dev_dbg(comp->dev, "Removing %d controls\n",
    979			module->num_controls);
    980		/* release control semaphore */
    981		up_write(&card->controls_rwsem);
    982		gbaudio_remove_component_controls(comp, module->controls,
    983						  module->num_controls);
    984		down_write(&card->controls_rwsem);
    985	}
    986	if (module->dapm_widgets) {
    987		dev_dbg(comp->dev, "Removing %d widgets\n",
    988			module->num_dapm_widgets);
    989		gbaudio_dapm_free_controls(&comp->dapm, module->dapm_widgets,
    990					   module->num_dapm_widgets);
    991	}
    992
    993	dev_dbg(comp->dev, "Unregistered %s module\n", module->name);
    994
    995	up_write(&card->controls_rwsem);
    996}
    997EXPORT_SYMBOL(gbaudio_unregister_module);
    998
    999/*
   1000 * component driver ops
   1001 */
   1002static int gbcodec_probe(struct snd_soc_component *comp)
   1003{
   1004	int i;
   1005	struct gbaudio_codec_info *info;
   1006	struct gbaudio_codec_dai *dai;
   1007
   1008	info = devm_kzalloc(comp->dev, sizeof(*info), GFP_KERNEL);
   1009	if (!info)
   1010		return -ENOMEM;
   1011
   1012	info->dev = comp->dev;
   1013	INIT_LIST_HEAD(&info->module_list);
   1014	mutex_init(&info->lock);
   1015	INIT_LIST_HEAD(&info->dai_list);
   1016
   1017	/* init dai_list used to maintain runtime stream info */
   1018	for (i = 0; i < ARRAY_SIZE(gbaudio_dai); i++) {
   1019		dai = devm_kzalloc(comp->dev, sizeof(*dai), GFP_KERNEL);
   1020		if (!dai)
   1021			return -ENOMEM;
   1022		dai->id = gbaudio_dai[i].id;
   1023		list_add(&dai->list, &info->dai_list);
   1024	}
   1025
   1026	info->component = comp;
   1027	snd_soc_component_set_drvdata(comp, info);
   1028	gbcodec = info;
   1029
   1030	device_init_wakeup(comp->dev, 1);
   1031	return 0;
   1032}
   1033
   1034static int gbcodec_write(struct snd_soc_component *comp, unsigned int reg,
   1035			 unsigned int value)
   1036{
   1037	return 0;
   1038}
   1039
   1040static unsigned int gbcodec_read(struct snd_soc_component *comp,
   1041				 unsigned int reg)
   1042{
   1043	return 0;
   1044}
   1045
   1046static const struct snd_soc_component_driver soc_codec_dev_gbaudio = {
   1047	.probe	= gbcodec_probe,
   1048	.read = gbcodec_read,
   1049	.write = gbcodec_write,
   1050};
   1051
   1052#ifdef CONFIG_PM
   1053static int gbaudio_codec_suspend(struct device *dev)
   1054{
   1055	dev_dbg(dev, "%s: suspend\n", __func__);
   1056	return 0;
   1057}
   1058
   1059static int gbaudio_codec_resume(struct device *dev)
   1060{
   1061	dev_dbg(dev, "%s: resume\n", __func__);
   1062	return 0;
   1063}
   1064
   1065static const struct dev_pm_ops gbaudio_codec_pm_ops = {
   1066	.suspend	= gbaudio_codec_suspend,
   1067	.resume		= gbaudio_codec_resume,
   1068};
   1069#endif
   1070
   1071static int gbaudio_codec_probe(struct platform_device *pdev)
   1072{
   1073	return devm_snd_soc_register_component(&pdev->dev,
   1074			&soc_codec_dev_gbaudio,
   1075			gbaudio_dai, ARRAY_SIZE(gbaudio_dai));
   1076}
   1077
   1078static int gbaudio_codec_remove(struct platform_device *pdev)
   1079{
   1080	return 0;
   1081}
   1082
   1083static const struct of_device_id greybus_asoc_machine_of_match[]  = {
   1084	{ .compatible = "toshiba,apb-dummy-codec", },
   1085	{},
   1086};
   1087
   1088static struct platform_driver gbaudio_codec_driver = {
   1089	.driver = {
   1090		.name = "apb-dummy-codec",
   1091#ifdef CONFIG_PM
   1092		.pm = &gbaudio_codec_pm_ops,
   1093#endif
   1094		.of_match_table = greybus_asoc_machine_of_match,
   1095	},
   1096	.probe = gbaudio_codec_probe,
   1097	.remove = gbaudio_codec_remove,
   1098};
   1099module_platform_driver(gbaudio_codec_driver);
   1100
   1101MODULE_DESCRIPTION("APBridge ALSA SoC dummy codec driver");
   1102MODULE_AUTHOR("Vaibhav Agarwal <vaibhav.agarwal@linaro.org>");
   1103MODULE_LICENSE("GPL v2");
   1104MODULE_ALIAS("platform:apb-dummy-codec");