// SPDX-License-Identifier: GPL-2.0
/*
* APBridge ALSA SoC dummy codec driver
* Copyright 2016 Google Inc.
* Copyright 2016 Linaro Ltd.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include <uapi/linux/input.h>
#include "audio_codec.h"
#include "audio_apbridgea.h"
#include "audio_manager.h"
static struct gbaudio_codec_info *gbcodec;
static struct gbaudio_data_connection *
find_data(struct gbaudio_module_info *module, int id)
{
struct gbaudio_data_connection *data;
list_for_each_entry(data, &module->data_list, list) {
if (id == data->id)
return data;
}
return NULL;
}
static struct gbaudio_stream_params *
find_dai_stream_params(struct gbaudio_codec_info *codec, int id, int stream)
{
struct gbaudio_codec_dai *dai;
list_for_each_entry(dai, &codec->dai_list, list) {
if (dai->id == id)
return &dai->params[stream];
}
return NULL;
}
static int gbaudio_module_enable_tx(struct gbaudio_codec_info *codec,
struct gbaudio_module_info *module, int id)
{
int module_state, ret = 0;
u16 data_cport, i2s_port, cportid;
u8 sig_bits, channels;
u32 format, rate;
struct gbaudio_data_connection *data;
struct gbaudio_stream_params *params;
/* find the dai */
data = find_data(module, id);
if (!data) {
dev_err(module->dev, "%d:DATA connection missing\n", id);
return -ENODEV;
}
module_state = data->state[SNDRV_PCM_STREAM_PLAYBACK];
params = find_dai_stream_params(codec, id, SNDRV_PCM_STREAM_PLAYBACK);
if (!params) {
dev_err(codec->dev, "Failed to fetch dai_stream pointer\n");
return -EINVAL;
}
/* register cport */
if (module_state < GBAUDIO_CODEC_STARTUP) {
i2s_port = 0; /* fixed for now */
cportid = data->connection->hd_cport_id;
ret = gb_audio_apbridgea_register_cport(data->connection,
i2s_port, cportid,
AUDIO_APBRIDGEA_DIRECTION_TX);
if (ret) {
dev_err_ratelimited(module->dev,
"reg_cport failed:%d\n", ret);
return ret;
}
data->state[SNDRV_PCM_STREAM_PLAYBACK] =
GBAUDIO_CODEC_STARTUP;
dev_dbg(module->dev, "Dynamic Register %d DAI\n", cportid);
}
/* hw_params */
if (module_state < GBAUDIO_CODEC_HWPARAMS) {
format = params->format;
channels = params->channels;
rate = params->rate;
sig_bits = params->sig_bits;
data_cport = data->connection->intf_cport_id;
ret = gb_audio_gb_set_pcm(module->mgmt_connection, data_cport,
format, rate, channels, sig_bits);
if (ret) {
dev_err_ratelimited(module->dev, "set_pcm failed:%d\n",
ret);
return ret;
}
data->state[SNDRV_PCM_STREAM_PLAYBACK] =
GBAUDIO_CODEC_HWPARAMS;
dev_dbg(module->dev, "Dynamic hw_params %d DAI\n", data_cport);
}
/* prepare */
if (module_state < GBAUDIO_CODEC_PREPARE) {
data_cport = data->connection->intf_cport_id;
ret = gb_audio_gb_set_tx_data_size(module->mgmt_connection,
data_cport, 192);
if (ret)