From ea5edfe2f1ce5b2254a5ec4c1bb224fac48c3153 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Mon, 4 Aug 2014 15:04:19 +0530 Subject: ASoC: Intel: Fix to use byte control interface Using a byte control interface instead of generic_params ioctl. Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/sst-mfld-platform.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h index 6c6a42c08e24..cc3a088df7dd 100644 --- a/sound/soc/intel/sst-mfld-platform.h +++ b/sound/soc/intel/sst-mfld-platform.h @@ -63,9 +63,7 @@ enum sst_controls { SST_SND_BUFFER_POINTER = 0x05, SST_SND_STREAM_INIT = 0x06, SST_SND_START = 0x07, - SST_SET_BYTE_STREAM = 0x100A, - SST_GET_BYTE_STREAM = 0x100B, - SST_MAX_CONTROLS = SST_GET_BYTE_STREAM, + SST_MAX_CONTROLS = 0x07, }; enum sst_stream_ops { @@ -129,7 +127,7 @@ struct compress_sst_ops { struct sst_ops { int (*open) (struct snd_sst_params *str_param); int (*device_control) (int cmd, void *arg); - int (*set_generic_params)(enum sst_controls cmd, void *arg); + int (*send_byte_stream)(struct snd_sst_bytes_v2 *bytes); int (*close) (unsigned int str_id); }; -- cgit v1.2.3 From 5981c2d6db2ef16d96ee4d1c4d3ddff4ad9d8ebc Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Mon, 4 Aug 2014 15:04:20 +0530 Subject: ASoC: Intel: mfld-pcm: Use function instead of ioctl Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/sst-mfld-platform-pcm.c | 21 +++++++++------------ sound/soc/intel/sst-mfld-platform.h | 19 ++++++------------- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c index 706212a6a68c..42766a51c17e 100644 --- a/sound/soc/intel/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/sst-mfld-platform-pcm.c @@ -314,8 +314,7 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream) stream->stream_info.arg = substream; stream->stream_info.buffer_ptr = 0; stream->stream_info.sfreq = substream->runtime->rate; - ret_val = stream->ops->device_control( - SST_SND_STREAM_INIT, &stream->stream_info); + ret_val = stream->ops->stream_init(&stream->stream_info); if (ret_val) pr_err("control_set ret error %d\n", ret_val); return ret_val; @@ -403,8 +402,7 @@ static int sst_media_prepare(struct snd_pcm_substream *substream, stream = substream->runtime->private_data; str_id = stream->stream_info.str_id; if (stream->stream_info.str_id) { - ret_val = stream->ops->device_control( - SST_SND_DROP, &str_id); + ret_val = stream->ops->stream_drop(str_id); return ret_val; } @@ -461,7 +459,7 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, { int ret_val = 0, str_id; struct sst_runtime_stream *stream; - int str_cmd, status; + int status; pr_debug("sst_platform_pcm_trigger called\n"); stream = substream->runtime->private_data; @@ -469,29 +467,29 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, switch (cmd) { case SNDRV_PCM_TRIGGER_START: pr_debug("sst: Trigger Start\n"); - str_cmd = SST_SND_START; status = SST_PLATFORM_RUNNING; stream->stream_info.arg = substream; + ret_val = stream->ops->stream_start(str_id); break; case SNDRV_PCM_TRIGGER_STOP: pr_debug("sst: in stop\n"); - str_cmd = SST_SND_DROP; status = SST_PLATFORM_DROPPED; + ret_val = stream->ops->stream_drop(str_id); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: pr_debug("sst: in pause\n"); - str_cmd = SST_SND_PAUSE; status = SST_PLATFORM_PAUSED; + ret_val = stream->ops->stream_pause(str_id); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: pr_debug("sst: in pause release\n"); - str_cmd = SST_SND_RESUME; status = SST_PLATFORM_RUNNING; + ret_val = stream->ops->stream_pause_release(str_id); break; default: return -EINVAL; } - ret_val = stream->ops->device_control(str_cmd, &str_id); + if (!ret_val) sst_set_stream_status(stream, status); @@ -511,8 +509,7 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer if (status == SST_PLATFORM_INIT) return 0; str_info = &stream->stream_info; - ret_val = stream->ops->device_control( - SST_SND_BUFFER_POINTER, str_info); + ret_val = stream->ops->stream_read_tstamp(str_info); if (ret_val) { pr_err("sst: error code = %d\n", ret_val); return ret_val; diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h index cc3a088df7dd..2d6e65bbbc49 100644 --- a/sound/soc/intel/sst-mfld-platform.h +++ b/sound/soc/intel/sst-mfld-platform.h @@ -54,18 +54,6 @@ enum sst_drv_status { SST_PLATFORM_DROPPED, }; -enum sst_controls { - SST_SND_ALLOC = 0x00, - SST_SND_PAUSE = 0x01, - SST_SND_RESUME = 0x02, - SST_SND_DROP = 0x03, - SST_SND_FREE = 0x04, - SST_SND_BUFFER_POINTER = 0x05, - SST_SND_STREAM_INIT = 0x06, - SST_SND_START = 0x07, - SST_MAX_CONTROLS = 0x07, -}; - enum sst_stream_ops { STREAM_OPS_PLAYBACK = 0, STREAM_OPS_CAPTURE, @@ -126,7 +114,12 @@ struct compress_sst_ops { struct sst_ops { int (*open) (struct snd_sst_params *str_param); - int (*device_control) (int cmd, void *arg); + int (*stream_init) (struct pcm_stream_info *str_info); + int (*stream_start) (int str_id); + int (*stream_drop) (int str_id); + int (*stream_pause) (int str_id); + int (*stream_pause_release) (int str_id); + int (*stream_read_tstamp) (struct pcm_stream_info *str_info); int (*send_byte_stream)(struct snd_sst_bytes_v2 *bytes); int (*close) (unsigned int str_id); }; -- cgit v1.2.3 From b12b087c8715286b8759016f1d5c36cac0bb37f6 Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Mon, 4 Aug 2014 15:04:21 +0530 Subject: ASoC: Intel: mfld-pcm: Change sst_ops prototypes to take dev parameter sst_ops need to use the sst driver context. So pass sst device as argument, which can be used to retrieve sst context. Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/sst-mfld-platform-pcm.c | 19 +++++++++---------- sound/soc/intel/sst-mfld-platform.h | 18 +++++++++--------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c index 42766a51c17e..a89ff7e18e1a 100644 --- a/sound/soc/intel/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/sst-mfld-platform-pcm.c @@ -277,7 +277,7 @@ static int sst_platform_alloc_stream(struct snd_pcm_substream *substream, stream->stream_info.str_id = str_params.stream_id; - ret_val = stream->ops->open(&str_params); + ret_val = stream->ops->open(sst->dev, &str_params); if (ret_val <= 0) return ret_val; @@ -314,13 +314,12 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream) stream->stream_info.arg = substream; stream->stream_info.buffer_ptr = 0; stream->stream_info.sfreq = substream->runtime->rate; - ret_val = stream->ops->stream_init(&stream->stream_info); + ret_val = stream->ops->stream_init(sst->dev, &stream->stream_info); if (ret_val) pr_err("control_set ret error %d\n", ret_val); return ret_val; } -/* end -- helper functions */ static int sst_media_open(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) @@ -372,7 +371,7 @@ static void sst_media_close(struct snd_pcm_substream *substream, stream = substream->runtime->private_data; str_id = stream->stream_info.str_id; if (str_id) - ret_val = stream->ops->close(str_id); + ret_val = stream->ops->close(sst->dev, str_id); module_put(sst->dev->driver->owner); kfree(stream); } @@ -402,7 +401,7 @@ static int sst_media_prepare(struct snd_pcm_substream *substream, stream = substream->runtime->private_data; str_id = stream->stream_info.str_id; if (stream->stream_info.str_id) { - ret_val = stream->ops->stream_drop(str_id); + ret_val = stream->ops->stream_drop(sst->dev, str_id); return ret_val; } @@ -469,22 +468,22 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, pr_debug("sst: Trigger Start\n"); status = SST_PLATFORM_RUNNING; stream->stream_info.arg = substream; - ret_val = stream->ops->stream_start(str_id); + ret_val = stream->ops->stream_start(sst->dev, str_id); break; case SNDRV_PCM_TRIGGER_STOP: pr_debug("sst: in stop\n"); status = SST_PLATFORM_DROPPED; - ret_val = stream->ops->stream_drop(str_id); + ret_val = stream->ops->stream_drop(sst->dev, str_id); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: pr_debug("sst: in pause\n"); status = SST_PLATFORM_PAUSED; - ret_val = stream->ops->stream_pause(str_id); + ret_val = stream->ops->stream_pause(sst->dev, str_id); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: pr_debug("sst: in pause release\n"); status = SST_PLATFORM_RUNNING; - ret_val = stream->ops->stream_pause_release(str_id); + ret_val = stream->ops->stream_pause_release(sst->dev, str_id); break; default: return -EINVAL; @@ -509,7 +508,7 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer if (status == SST_PLATFORM_INIT) return 0; str_info = &stream->stream_info; - ret_val = stream->ops->stream_read_tstamp(str_info); + ret_val = stream->ops->stream_read_tstamp(sst->dev, str_info); if (ret_val) { pr_err("sst: error code = %d\n", ret_val); return ret_val; diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h index 2d6e65bbbc49..d4c28b8fb471 100644 --- a/sound/soc/intel/sst-mfld-platform.h +++ b/sound/soc/intel/sst-mfld-platform.h @@ -113,15 +113,15 @@ struct compress_sst_ops { }; struct sst_ops { - int (*open) (struct snd_sst_params *str_param); - int (*stream_init) (struct pcm_stream_info *str_info); - int (*stream_start) (int str_id); - int (*stream_drop) (int str_id); - int (*stream_pause) (int str_id); - int (*stream_pause_release) (int str_id); - int (*stream_read_tstamp) (struct pcm_stream_info *str_info); - int (*send_byte_stream)(struct snd_sst_bytes_v2 *bytes); - int (*close) (unsigned int str_id); + int (*open) (struct device *dev, struct snd_sst_params *str_param); + int (*stream_init) (struct device *dev, struct pcm_stream_info *str_info); + int (*stream_start) (struct device *dev, int str_id); + int (*stream_drop) (struct device *dev, int str_id); + int (*stream_pause) (struct device *dev, int str_id); + int (*stream_pause_release) (struct device *dev, int str_id); + int (*stream_read_tstamp) (struct device *dev, struct pcm_stream_info *str_info); + int (*send_byte_stream)(struct device *dev, struct snd_sst_bytes_v2 *bytes); + int (*close) (struct device *dev, unsigned int str_id); }; struct sst_runtime_stream { -- cgit v1.2.3 From d8499c9b4b03ca88d7c7b4094cb09471658df7c2 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Mon, 4 Aug 2014 15:15:55 +0530 Subject: ASoC: Intel: add mrfld DSP defines We define the DSP commands,structures here which will be used to send the IPCs Signed-off-by: Vinod Koul Signed-off-by: Subhransu S. Prusty Signed-off-by: Mark Brown --- sound/soc/intel/Makefile | 3 +- sound/soc/intel/sst-atom-controls.c | 39 +++++ sound/soc/intel/sst-atom-controls.h | 286 +++++++++++++++++++++++++++++++- sound/soc/intel/sst-mfld-platform-pcm.c | 8 +- sound/soc/intel/sst-mfld-platform.h | 3 + 5 files changed, 335 insertions(+), 4 deletions(-) create mode 100644 sound/soc/intel/sst-atom-controls.c diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 7acbfc43a0c6..f841786dad15 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -2,7 +2,8 @@ snd-soc-sst-dsp-objs := sst-dsp.o sst-firmware.o snd-soc-sst-acpi-objs := sst-acpi.o -snd-soc-sst-mfld-platform-objs := sst-mfld-platform-pcm.o sst-mfld-platform-compress.o +snd-soc-sst-mfld-platform-objs := sst-mfld-platform-pcm.o \ + sst-mfld-platform-compress.o sst-atom-controls.o snd-soc-mfld-machine-objs := mfld_machine.o obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o diff --git a/sound/soc/intel/sst-atom-controls.c b/sound/soc/intel/sst-atom-controls.c new file mode 100644 index 000000000000..ace3c4a59b14 --- /dev/null +++ b/sound/soc/intel/sst-atom-controls.c @@ -0,0 +1,39 @@ +/* + * sst-atom-controls.c - Intel MID Platform driver DPCM ALSA controls for Mrfld + * + * Copyright (C) 2013-14 Intel Corp + * Author: Omair Mohammed Abdullah + * Vinod Koul + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include "sst-mfld-platform.h" +#include "sst-atom-controls.h" + +int sst_dsp_init_v2_dpcm(struct snd_soc_platform *platform) +{ + int ret = 0; + struct sst_data *drv = snd_soc_platform_get_drvdata(platform); + + drv->byte_stream = devm_kzalloc(platform->dev, + SST_MAX_BIN_BYTES, GFP_KERNEL); + if (!drv->byte_stream) + return -ENOMEM; + + return ret; +} diff --git a/sound/soc/intel/sst-atom-controls.h b/sound/soc/intel/sst-atom-controls.h index 14063ab8c7c5..8554889c0694 100644 --- a/sound/soc/intel/sst-atom-controls.h +++ b/sound/soc/intel/sst-atom-controls.h @@ -1,4 +1,6 @@ /* + * sst-atom-controls.h - Intel MID Platform driver header file + * * Copyright (C) 2013-14 Intel Corp * Author: Ramesh Babu * Omair M Abdullah @@ -18,13 +20,293 @@ * */ -#ifndef __SST_CONTROLS_V2_H__ -#define __SST_CONTROLS_V2_H__ +#ifndef __SST_ATOM_CONTROLS_H__ +#define __SST_ATOM_CONTROLS_H__ enum { MERR_DPCM_AUDIO = 0, MERR_DPCM_COMPR, }; +/* define a bit for each mixer input */ +#define SST_MIX_IP(x) (x) + +#define SST_IP_CODEC0 SST_MIX_IP(2) +#define SST_IP_CODEC1 SST_MIX_IP(3) +#define SST_IP_LOOP0 SST_MIX_IP(4) +#define SST_IP_LOOP1 SST_MIX_IP(5) +#define SST_IP_LOOP2 SST_MIX_IP(6) +#define SST_IP_PROBE SST_MIX_IP(7) +#define SST_IP_VOIP SST_MIX_IP(12) +#define SST_IP_PCM0 SST_MIX_IP(13) +#define SST_IP_PCM1 SST_MIX_IP(14) +#define SST_IP_MEDIA0 SST_MIX_IP(17) +#define SST_IP_MEDIA1 SST_MIX_IP(18) +#define SST_IP_MEDIA2 SST_MIX_IP(19) +#define SST_IP_MEDIA3 SST_MIX_IP(20) + +#define SST_IP_LAST SST_IP_MEDIA3 + +#define SST_SWM_INPUT_COUNT (SST_IP_LAST + 1) +#define SST_CMD_SWM_MAX_INPUTS 6 + +#define SST_PATH_ID_SHIFT 8 +#define SST_DEFAULT_LOCATION_ID 0xFFFF +#define SST_DEFAULT_CELL_NBR 0xFF +#define SST_DEFAULT_MODULE_ID 0xFFFF + +/* + * Audio DSP Path Ids. Specified by the audio DSP FW + */ +enum sst_path_index { + SST_PATH_INDEX_CODEC_OUT0 = (0x02 << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_CODEC_OUT1 = (0x03 << SST_PATH_ID_SHIFT), + + SST_PATH_INDEX_SPROT_LOOP_OUT = (0x04 << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_MEDIA_LOOP1_OUT = (0x05 << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_MEDIA_LOOP2_OUT = (0x06 << SST_PATH_ID_SHIFT), + + SST_PATH_INDEX_VOIP_OUT = (0x0C << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_PCM0_OUT = (0x0D << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_PCM1_OUT = (0x0E << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_PCM2_OUT = (0x0F << SST_PATH_ID_SHIFT), + + SST_PATH_INDEX_MEDIA0_OUT = (0x12 << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_MEDIA1_OUT = (0x13 << SST_PATH_ID_SHIFT), + + + /* Start of input paths */ + SST_PATH_INDEX_CODEC_IN0 = (0x82 << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_CODEC_IN1 = (0x83 << SST_PATH_ID_SHIFT), + + SST_PATH_INDEX_SPROT_LOOP_IN = (0x84 << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_MEDIA_LOOP1_IN = (0x85 << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_MEDIA_LOOP2_IN = (0x86 << SST_PATH_ID_SHIFT), + + SST_PATH_INDEX_VOIP_IN = (0x8C << SST_PATH_ID_SHIFT), + + SST_PATH_INDEX_PCM0_IN = (0x8D << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_PCM1_IN = (0x8E << SST_PATH_ID_SHIFT), + + SST_PATH_INDEX_MEDIA0_IN = (0x8F << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_MEDIA1_IN = (0x90 << SST_PATH_ID_SHIFT), + SST_PATH_INDEX_MEDIA2_IN = (0x91 << SST_PATH_ID_SHIFT), + + SST_PATH_INDEX_MEDIA3_IN = (0x9C << SST_PATH_ID_SHIFT), + + SST_PATH_INDEX_RESERVED = (0xFF << SST_PATH_ID_SHIFT), +}; + +/* + * path IDs + */ +enum sst_swm_inputs { + SST_SWM_IN_CODEC0 = (SST_PATH_INDEX_CODEC_IN0 | SST_DEFAULT_CELL_NBR), + SST_SWM_IN_CODEC1 = (SST_PATH_INDEX_CODEC_IN1 | SST_DEFAULT_CELL_NBR), + SST_SWM_IN_SPROT_LOOP = (SST_PATH_INDEX_SPROT_LOOP_IN | SST_DEFAULT_CELL_NBR), + SST_SWM_IN_MEDIA_LOOP1 = (SST_PATH_INDEX_MEDIA_LOOP1_IN | SST_DEFAULT_CELL_NBR), + SST_SWM_IN_MEDIA_LOOP2 = (SST_PATH_INDEX_MEDIA_LOOP2_IN | SST_DEFAULT_CELL_NBR), + SST_SWM_IN_VOIP = (SST_PATH_INDEX_VOIP_IN | SST_DEFAULT_CELL_NBR), + SST_SWM_IN_PCM0 = (SST_PATH_INDEX_PCM0_IN | SST_DEFAULT_CELL_NBR), + SST_SWM_IN_PCM1 = (SST_PATH_INDEX_PCM1_IN | SST_DEFAULT_CELL_NBR), + SST_SWM_IN_MEDIA0 = (SST_PATH_INDEX_MEDIA0_IN | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */ + SST_SWM_IN_MEDIA1 = (SST_PATH_INDEX_MEDIA1_IN | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */ + SST_SWM_IN_MEDIA2 = (SST_PATH_INDEX_MEDIA2_IN | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */ + SST_SWM_IN_MEDIA3 = (SST_PATH_INDEX_MEDIA3_IN | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */ + SST_SWM_IN_END = (SST_PATH_INDEX_RESERVED | SST_DEFAULT_CELL_NBR) +}; + +/* + * path IDs + */ +enum sst_swm_outputs { + SST_SWM_OUT_CODEC0 = (SST_PATH_INDEX_CODEC_OUT0 | SST_DEFAULT_CELL_NBR), + SST_SWM_OUT_CODEC1 = (SST_PATH_INDEX_CODEC_OUT1 | SST_DEFAULT_CELL_NBR), + SST_SWM_OUT_SPROT_LOOP = (SST_PATH_INDEX_SPROT_LOOP_OUT | SST_DEFAULT_CELL_NBR), + SST_SWM_OUT_MEDIA_LOOP1 = (SST_PATH_INDEX_MEDIA_LOOP1_OUT | SST_DEFAULT_CELL_NBR), + SST_SWM_OUT_MEDIA_LOOP2 = (SST_PATH_INDEX_MEDIA_LOOP2_OUT | SST_DEFAULT_CELL_NBR), + SST_SWM_OUT_VOIP = (SST_PATH_INDEX_VOIP_OUT | SST_DEFAULT_CELL_NBR), + SST_SWM_OUT_PCM0 = (SST_PATH_INDEX_PCM0_OUT | SST_DEFAULT_CELL_NBR), + SST_SWM_OUT_PCM1 = (SST_PATH_INDEX_PCM1_OUT | SST_DEFAULT_CELL_NBR), + SST_SWM_OUT_PCM2 = (SST_PATH_INDEX_PCM2_OUT | SST_DEFAULT_CELL_NBR), + SST_SWM_OUT_MEDIA0 = (SST_PATH_INDEX_MEDIA0_OUT | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */ + SST_SWM_OUT_MEDIA1 = (SST_PATH_INDEX_MEDIA1_OUT | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */ + SST_SWM_OUT_END = (SST_PATH_INDEX_RESERVED | SST_DEFAULT_CELL_NBR), +}; + +enum sst_ipc_msg { + SST_IPC_IA_CMD = 1, + SST_IPC_IA_SET_PARAMS, + SST_IPC_IA_GET_PARAMS, +}; + +enum sst_cmd_type { + SST_CMD_BYTES_SET = 1, + SST_CMD_BYTES_GET = 2, +}; + +enum sst_task { + SST_TASK_SBA = 1, + SST_TASK_MMX, +}; + +enum sst_type { + SST_TYPE_CMD = 1, + SST_TYPE_PARAMS, +}; + +enum sst_flag { + SST_FLAG_BLOCKED = 1, + SST_FLAG_NONBLOCK, +}; + +/* + * Enumeration for indexing the gain cells in VB_SET_GAIN DSP command + */ +enum sst_gain_index { + /* GAIN IDs for SB task start here */ + SST_GAIN_INDEX_CODEC_OUT0, + SST_GAIN_INDEX_CODEC_OUT1, + SST_GAIN_INDEX_CODEC_IN0, + SST_GAIN_INDEX_CODEC_IN1, + + SST_GAIN_INDEX_SPROT_LOOP_OUT, + SST_GAIN_INDEX_MEDIA_LOOP1_OUT, + SST_GAIN_INDEX_MEDIA_LOOP2_OUT, + + SST_GAIN_INDEX_PCM0_IN_LEFT, + SST_GAIN_INDEX_PCM0_IN_RIGHT, + + SST_GAIN_INDEX_PCM1_OUT_LEFT, + SST_GAIN_INDEX_PCM1_OUT_RIGHT, + SST_GAIN_INDEX_PCM1_IN_LEFT, + SST_GAIN_INDEX_PCM1_IN_RIGHT, + SST_GAIN_INDEX_PCM2_OUT_LEFT, + + SST_GAIN_INDEX_PCM2_OUT_RIGHT, + SST_GAIN_INDEX_VOIP_OUT, + SST_GAIN_INDEX_VOIP_IN, + + /* Gain IDs for MMX task start here */ + SST_GAIN_INDEX_MEDIA0_IN_LEFT, + SST_GAIN_INDEX_MEDIA0_IN_RIGHT, + SST_GAIN_INDEX_MEDIA1_IN_LEFT, + SST_GAIN_INDEX_MEDIA1_IN_RIGHT, + + SST_GAIN_INDEX_MEDIA2_IN_LEFT, + SST_GAIN_INDEX_MEDIA2_IN_RIGHT, + + SST_GAIN_INDEX_GAIN_END +}; + +/* + * Audio DSP module IDs specified by FW spec + * TODO: Update with all modules + */ +enum sst_module_id { + SST_MODULE_ID_PCM = 0x0001, + SST_MODULE_ID_MP3 = 0x0002, + SST_MODULE_ID_MP24 = 0x0003, + SST_MODULE_ID_AAC = 0x0004, + SST_MODULE_ID_AACP = 0x0005, + SST_MODULE_ID_EAACP = 0x0006, + SST_MODULE_ID_WMA9 = 0x0007, + SST_MODULE_ID_WMA10 = 0x0008, + SST_MODULE_ID_WMA10P = 0x0009, + SST_MODULE_ID_RA = 0x000A, + SST_MODULE_ID_DDAC3 = 0x000B, + SST_MODULE_ID_TRUE_HD = 0x000C, + SST_MODULE_ID_HD_PLUS = 0x000D, + + SST_MODULE_ID_SRC = 0x0064, + SST_MODULE_ID_DOWNMIX = 0x0066, + SST_MODULE_ID_GAIN_CELL = 0x0067, + SST_MODULE_ID_SPROT = 0x006D, + SST_MODULE_ID_BASS_BOOST = 0x006E, + SST_MODULE_ID_STEREO_WDNG = 0x006F, + SST_MODULE_ID_AV_REMOVAL = 0x0070, + SST_MODULE_ID_MIC_EQ = 0x0071, + SST_MODULE_ID_SPL = 0x0072, + SST_MODULE_ID_ALGO_VTSV = 0x0073, + SST_MODULE_ID_NR = 0x0076, + SST_MODULE_ID_BWX = 0x0077, + SST_MODULE_ID_DRP = 0x0078, + SST_MODULE_ID_MDRP = 0x0079, + + SST_MODULE_ID_ANA = 0x007A, + SST_MODULE_ID_AEC = 0x007B, + SST_MODULE_ID_NR_SNS = 0x007C, + SST_MODULE_ID_SER = 0x007D, + SST_MODULE_ID_AGC = 0x007E, + + SST_MODULE_ID_CNI = 0x007F, + SST_MODULE_ID_CONTEXT_ALGO_AWARE = 0x0080, + SST_MODULE_ID_FIR_24 = 0x0081, + SST_MODULE_ID_IIR_24 = 0x0082, + + SST_MODULE_ID_ASRC = 0x0083, + SST_MODULE_ID_TONE_GEN = 0x0084, + SST_MODULE_ID_BMF = 0x0086, + SST_MODULE_ID_EDL = 0x0087, + SST_MODULE_ID_GLC = 0x0088, + + SST_MODULE_ID_FIR_16 = 0x0089, + SST_MODULE_ID_IIR_16 = 0x008A, + SST_MODULE_ID_DNR = 0x008B, + + SST_MODULE_ID_VIRTUALIZER = 0x008C, + SST_MODULE_ID_VISUALIZATION = 0x008D, + SST_MODULE_ID_LOUDNESS_OPTIMIZER = 0x008E, + SST_MODULE_ID_REVERBERATION = 0x008F, + + SST_MODULE_ID_CNI_TX = 0x0090, + SST_MODULE_ID_REF_LINE = 0x0091, + SST_MODULE_ID_VOLUME = 0x0092, + SST_MODULE_ID_FILT_DCR = 0x0094, + SST_MODULE_ID_SLV = 0x009A, + SST_MODULE_ID_NLF = 0x009B, + SST_MODULE_ID_TNR = 0x009C, + SST_MODULE_ID_WNR = 0x009D, + + SST_MODULE_ID_LOG = 0xFF00, + + SST_MODULE_ID_TASK = 0xFFFF, +}; + +enum sst_cmd { + SBA_IDLE = 14, + SBA_VB_SET_SPEECH_PATH = 26, + MMX_SET_GAIN = 33, + SBA_VB_SET_GAIN = 33, + FBA_VB_RX_CNI = 35, + MMX_SET_GAIN_TIMECONST = 36, + SBA_VB_SET_TIMECONST = 36, + SBA_VB_START = 85, + SBA_SET_SWM = 114, + SBA_SET_MDRP = 116, + SBA_HW_SET_SSP = 117, + SBA_SET_MEDIA_LOOP_MAP = 118, + SBA_SET_MEDIA_PATH = 119, + MMX_SET_MEDIA_PATH = 119, + SBA_VB_LPRO = 126, + SBA_VB_SET_FIR = 128, + SBA_VB_SET_IIR = 129, + SBA_SET_SSP_SLOT_MAP = 130, +}; + +enum sst_dsp_switch { + SST_SWITCH_OFF = 0, + SST_SWITCH_ON = 3, +}; + +enum sst_path_switch { + SST_PATH_OFF = 0, + SST_PATH_ON = 1, +}; + +enum sst_swm_state { + SST_SWM_OFF = 0, + SST_SWM_ON = 3, +}; #endif diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c index a89ff7e18e1a..8e1e9bc27642 100644 --- a/sound/soc/intel/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/sst-mfld-platform-pcm.c @@ -550,7 +550,13 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) return retval; } -static struct snd_soc_platform_driver sst_soc_platform_drv = { +static int sst_soc_probe(struct snd_soc_platform *platform) +{ + return sst_dsp_init_v2_dpcm(platform); +} + +static struct snd_soc_platform_driver sst_soc_platform_drv = { + .probe = sst_soc_probe, .ops = &sst_platform_ops, .compr_ops = &sst_platform_compr_ops, .pcm_new = sst_pcm_new, diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h index d4c28b8fb471..faaba10c1dff 100644 --- a/sound/soc/intel/sst-mfld-platform.h +++ b/sound/soc/intel/sst-mfld-platform.h @@ -143,6 +143,8 @@ struct sst_device { }; struct sst_data; + +int sst_dsp_init_v2_dpcm(struct snd_soc_platform *platform); void sst_set_stream_status(struct sst_runtime_stream *stream, int state); int sst_fill_stream_params(void *substream, const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress); @@ -157,6 +159,7 @@ struct sst_algo_int_control_v2 { struct sst_data { struct platform_device *pdev; struct sst_platform_data *pdata; + char *byte_stream; struct mutex lock; }; int sst_register_dsp(struct sst_device *sst); -- cgit v1.2.3 From 81c7cfd1b22a0ee5e40efef72ec2cd17dbf12e6d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 19 Aug 2014 15:51:18 +0200 Subject: ASoC: Move debugfs registration to the component level The debugfs registration is mostly identical between platforms and CODECs. This patches consolidates the two implementations at the component level. Unfortunately there are still a couple of CODEC specific debugfs files that are related to legacy ASoC IO that need to be registered. For this a new callback is added to the component struct that will be initialized when a CODEC is registered and will be used to register the CODEC specific files. Once there are no drivers left using legacy IO this can be removed again. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 20 ++++++--- sound/soc/soc-core.c | 122 ++++++++++++++++++++++----------------------------- 2 files changed, 67 insertions(+), 75 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index be6ecae247b0..0ab8b1e4a5d2 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -728,9 +728,24 @@ struct snd_soc_component { struct mutex io_mutex; +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs_root; +#endif + + /* + * DO NOT use any of the fields below in drivers, they are temporary and + * are going to be removed again soon. If you use them in driver code the + * driver will be marked as BROKEN when these fields are removed. + */ + /* Don't use these, use snd_soc_component_get_dapm() */ struct snd_soc_dapm_context dapm; struct snd_soc_dapm_context *dapm_ptr; + +#ifdef CONFIG_DEBUG_FS + void (*init_debugfs)(struct snd_soc_component *component); + const char *debugfs_prefix; +#endif }; /* SoC Audio Codec device */ @@ -766,7 +781,6 @@ struct snd_soc_codec { struct snd_soc_dapm_context dapm; #ifdef CONFIG_DEBUG_FS - struct dentry *debugfs_codec_root; struct dentry *debugfs_reg; #endif }; @@ -879,10 +893,6 @@ struct snd_soc_platform { struct list_head list; struct snd_soc_component component; - -#ifdef CONFIG_DEBUG_FS - struct dentry *debugfs_platform_root; -#endif }; struct snd_soc_dai_link { diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d4bfd4a9076f..79371a77f324 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -270,79 +270,56 @@ static const struct file_operations codec_reg_fops = { .llseek = default_llseek, }; -static struct dentry *soc_debugfs_create_dir(struct dentry *parent, - const char *fmt, ...) +static void soc_init_component_debugfs(struct snd_soc_component *component) { - struct dentry *de; - va_list ap; - char *s; + if (component->debugfs_prefix) { + char *name; - va_start(ap, fmt); - s = kvasprintf(GFP_KERNEL, fmt, ap); - va_end(ap); + name = kasprintf(GFP_KERNEL, "%s:%s", + component->debugfs_prefix, component->name); + if (name) { + component->debugfs_root = debugfs_create_dir(name, + component->card->debugfs_card_root); + kfree(name); + } + } else { + component->debugfs_root = debugfs_create_dir(component->name, + component->card->debugfs_card_root); + } - if (!s) - return NULL; + if (!component->debugfs_root) { + dev_warn(component->dev, + "ASoC: Failed to create component debugfs directory\n"); + return; + } - de = debugfs_create_dir(s, parent); - kfree(s); + snd_soc_dapm_debugfs_init(snd_soc_component_get_dapm(component), + component->debugfs_root); - return de; + if (component->init_debugfs) + component->init_debugfs(component); } -static void soc_init_codec_debugfs(struct snd_soc_codec *codec) +static void soc_cleanup_component_debugfs(struct snd_soc_component *component) { - struct dentry *debugfs_card_root = codec->component.card->debugfs_card_root; + debugfs_remove_recursive(component->debugfs_root); +} - codec->debugfs_codec_root = soc_debugfs_create_dir(debugfs_card_root, - "codec:%s", - codec->component.name); - if (!codec->debugfs_codec_root) { - dev_warn(codec->dev, - "ASoC: Failed to create codec debugfs directory\n"); - return; - } +static void soc_init_codec_debugfs(struct snd_soc_component *component) +{ + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - debugfs_create_bool("cache_sync", 0444, codec->debugfs_codec_root, + debugfs_create_bool("cache_sync", 0444, codec->component.debugfs_root, &codec->cache_sync); - debugfs_create_bool("cache_only", 0444, codec->debugfs_codec_root, + debugfs_create_bool("cache_only", 0444, codec->component.debugfs_root, &codec->cache_only); codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, - codec->debugfs_codec_root, + codec->component.debugfs_root, codec, &codec_reg_fops); if (!codec->debugfs_reg) dev_warn(codec->dev, "ASoC: Failed to create codec register debugfs file\n"); - - snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root); -} - -static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) -{ - debugfs_remove_recursive(codec->debugfs_codec_root); -} - -static void soc_init_platform_debugfs(struct snd_soc_platform *platform) -{ - struct dentry *debugfs_card_root = platform->component.card->debugfs_card_root; - - platform->debugfs_platform_root = soc_debugfs_create_dir(debugfs_card_root, - "platform:%s", - platform->component.name); - if (!platform->debugfs_platform_root) { - dev_warn(platform->dev, - "ASoC: Failed to create platform debugfs directory\n"); - return; - } - - snd_soc_dapm_debugfs_init(&platform->component.dapm, - platform->debugfs_platform_root); -} - -static void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform) -{ - debugfs_remove_recursive(platform->debugfs_platform_root); } static ssize_t codec_list_read_file(struct file *file, char __user *user_buf, @@ -474,19 +451,15 @@ static void soc_cleanup_card_debugfs(struct snd_soc_card *card) #else -static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) -{ -} +#define soc_init_codec_debugfs NULL -static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) +static inline void soc_init_component_debugfs( + struct snd_soc_component *component) { } -static inline void soc_init_platform_debugfs(struct snd_soc_platform *platform) -{ -} - -static inline void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform) +static inline void soc_cleanup_component_debugfs( + struct snd_soc_component *component) { } @@ -1026,7 +999,7 @@ static int soc_remove_platform(struct snd_soc_platform *platform) /* Make sure all DAPM widgets are freed */ snd_soc_dapm_free(&platform->component.dapm); - soc_cleanup_platform_debugfs(platform); + soc_cleanup_component_debugfs(&platform->component); platform->probed = 0; module_put(platform->dev->driver->owner); @@ -1046,7 +1019,7 @@ static void soc_remove_codec(struct snd_soc_codec *codec) /* Make sure all DAPM widgets are freed */ snd_soc_dapm_free(&codec->dapm); - soc_cleanup_codec_debugfs(codec); + soc_cleanup_component_debugfs(&codec->component); codec->probed = 0; list_del(&codec->card_list); module_put(codec->dev->driver->owner); @@ -1187,7 +1160,7 @@ static int soc_probe_codec(struct snd_soc_card *card, if (!try_module_get(codec->dev->driver->owner)) return -ENODEV; - soc_init_codec_debugfs(codec); + soc_init_component_debugfs(&codec->component); if (driver->dapm_widgets) { ret = snd_soc_dapm_new_controls(&codec->dapm, @@ -1242,7 +1215,7 @@ static int soc_probe_codec(struct snd_soc_card *card, return 0; err_probe: - soc_cleanup_codec_debugfs(codec); + soc_cleanup_component_debugfs(&codec->component); module_put(codec->dev->driver->owner); return ret; @@ -1262,7 +1235,7 @@ static int soc_probe_platform(struct snd_soc_card *card, if (!try_module_get(platform->dev->driver->owner)) return -ENODEV; - soc_init_platform_debugfs(platform); + soc_init_component_debugfs(&platform->component); if (driver->dapm_widgets) snd_soc_dapm_new_controls(&platform->component.dapm, @@ -1302,7 +1275,7 @@ static int soc_probe_platform(struct snd_soc_card *card, return 0; err_probe: - soc_cleanup_platform_debugfs(platform); + soc_cleanup_component_debugfs(&platform->component); module_put(platform->dev->driver->owner); return ret; @@ -4266,6 +4239,10 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, if (platform_drv->read) platform->component.read = snd_soc_platform_drv_read; +#ifdef CONFIG_DEBUG_FS + platform->component.debugfs_prefix = "platform"; +#endif + mutex_lock(&client_mutex); snd_soc_component_add_unlocked(&platform->component); list_add(&platform->list, &platform_list); @@ -4455,6 +4432,11 @@ int snd_soc_register_codec(struct device *dev, codec->component.val_bytes = codec_drv->reg_word_size; mutex_init(&codec->mutex); +#ifdef CONFIG_DEBUG_FS + codec->component.init_debugfs = soc_init_codec_debugfs; + codec->component.debugfs_prefix = "codec"; +#endif + if (!codec->component.write) { if (codec_drv->get_regmap) regmap = codec_drv->get_regmap(dev); -- cgit v1.2.3 From f1d45cc3ae96a6173129b2c164c216272faa5fc0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 19 Aug 2014 15:51:19 +0200 Subject: ASoC: Consolidate platform and CODEC probe/remove The platform and CODEC probe and remove code is now largely identical. This patch consolidates it at the component level. The resulting code is slightly larger due to all the boiler plate code setting up the indirection for the table based control and DAPM registration. Once all drivers have been update to no longer use the snd_soc_codec_driver and snd_soc_platform_driver specific fields for this the indirection can be removed again. This patch contains two noteworthy hacks that are only meant to be temporary to be able to update drivers and the core in separate incremental patches. The first hack is related to that some DPCM platforms expect that the DAPM widgets for the DAIs of a snd_soc_component are created in the DAPM context of the snd_soc_platform that has the same parent device. For handling this the steal_sibling_dai_widgets attribute is introduced. It gets set for snd_soc_platforms that register DAPM elements. When creating the DAI widgets for a component this flag is checked and if it is found on one of the siblings the component will not create any DAI widgets in its own DAPM context. If the attribute is set on a platform it will look for siblings components and create DAI widgets for them in its own context. The fix for this will be to update the offending drivers to only register a single component rather than two. The second hack deals with the fact that the ASoC card suspend and resume code still needs a list of CODECs that have been registered for the card. To handle this the generic probe and remove path have a check to see if the component is CODEC and if yes add/remove it to the card's CODEC list. While it is possible to clean up the suspend/resume code to not need the CODEC list anymore this is a bit of a chicken and egg problem since it will become easier to clean up the suspend/resume code once there is a unified component layer. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 27 ++- sound/soc/soc-core.c | 335 ++++++++++++++++++---------------- sound/soc/soc-generic-dmaengine-pcm.c | 4 +- 3 files changed, 194 insertions(+), 172 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 0ab8b1e4a5d2..22543acfae4b 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -697,6 +697,10 @@ struct snd_soc_component_driver { void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type, int subseq); int (*stream_event)(struct snd_soc_component *, int event); + + /* probe ordering - for components with runtime dependencies */ + int probe_order; + int remove_order; }; struct snd_soc_component { @@ -710,6 +714,7 @@ struct snd_soc_component { unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ unsigned int registered_as_component:1; + unsigned int probed:1; struct list_head list; @@ -742,6 +747,18 @@ struct snd_soc_component { struct snd_soc_dapm_context dapm; struct snd_soc_dapm_context *dapm_ptr; + const struct snd_kcontrol_new *controls; + unsigned int num_controls; + const struct snd_soc_dapm_widget *dapm_widgets; + unsigned int num_dapm_widgets; + const struct snd_soc_dapm_route *dapm_routes; + unsigned int num_dapm_routes; + bool steal_sibling_dai_widgets; + struct snd_soc_codec *codec; + + int (*probe)(struct snd_soc_component *); + void (*remove)(struct snd_soc_component *); + #ifdef CONFIG_DEBUG_FS void (*init_debugfs)(struct snd_soc_component *component); const char *debugfs_prefix; @@ -761,7 +778,6 @@ struct snd_soc_codec { struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ unsigned int cache_bypass:1; /* Suppress access to the cache */ unsigned int suspended:1; /* Codec is in suspend PM state */ - unsigned int probed:1; /* Codec has been probed */ unsigned int ac97_registered:1; /* Codec has been AC97 registered */ unsigned int ac97_created:1; /* Codec has been created by SoC */ unsigned int cache_init:1; /* codec cache has been initialized */ @@ -827,10 +843,6 @@ struct snd_soc_codec_driver { enum snd_soc_dapm_type, int); bool ignore_pmdown_time; /* Doesn't benefit from pmdown delay */ - - /* probe ordering - for components with runtime dependencies */ - int probe_order; - int remove_order; }; /* SoC platform interface */ @@ -867,10 +879,6 @@ struct snd_soc_platform_driver { /* platform stream compress ops */ const struct snd_compr_ops *compr_ops; - /* probe ordering - for components with runtime dependencies */ - int probe_order; - int remove_order; - /* platform IO - used for platform DAPM */ unsigned int (*read)(struct snd_soc_platform *, unsigned int); int (*write)(struct snd_soc_platform *, unsigned int, unsigned int); @@ -888,7 +896,6 @@ struct snd_soc_platform { const struct snd_soc_platform_driver *driver; unsigned int suspended:1; /* platform is suspended */ - unsigned int probed:1; struct list_head list; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 79371a77f324..b833cc6fd86d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -985,44 +985,20 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) return 0; } -static int soc_remove_platform(struct snd_soc_platform *platform) +static void soc_remove_component(struct snd_soc_component *component) { - int ret; - - if (platform->driver->remove) { - ret = platform->driver->remove(platform); - if (ret < 0) - dev_err(platform->dev, "ASoC: failed to remove %d\n", - ret); - } - - /* Make sure all DAPM widgets are freed */ - snd_soc_dapm_free(&platform->component.dapm); - - soc_cleanup_component_debugfs(&platform->component); - platform->probed = 0; - module_put(platform->dev->driver->owner); - - return 0; -} - -static void soc_remove_codec(struct snd_soc_codec *codec) -{ - int err; + /* This is a HACK and will be removed soon */ + if (component->codec) + list_del(&component->codec->card_list); - if (codec->driver->remove) { - err = codec->driver->remove(codec); - if (err < 0) - dev_err(codec->dev, "ASoC: failed to remove %d\n", err); - } + if (component->remove) + component->remove(component); - /* Make sure all DAPM widgets are freed */ - snd_soc_dapm_free(&codec->dapm); + snd_soc_dapm_free(snd_soc_component_get_dapm(component)); - soc_cleanup_component_debugfs(&codec->component); - codec->probed = 0; - list_del(&codec->card_list); - module_put(codec->dev->driver->owner); + soc_cleanup_component_debugfs(component); + component->probed = 0; + module_put(component->dev->driver->owner); } static void soc_remove_codec_dai(struct snd_soc_dai *codec_dai, int order) @@ -1086,25 +1062,24 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num, int i; /* remove the platform */ - if (platform && platform->probed && - platform->driver->remove_order == order) { - soc_remove_platform(platform); - } + if (platform && platform->component.probed && + platform->component.driver->remove_order == order) + soc_remove_component(&platform->component); /* remove the CODEC-side CODEC */ for (i = 0; i < rtd->num_codecs; i++) { codec = rtd->codec_dais[i]->codec; - if (codec && codec->probed && - codec->driver->remove_order == order) - soc_remove_codec(codec); + if (codec && codec->component.probed && + codec->component.driver->remove_order == order) + soc_remove_component(&codec->component); } /* remove any CPU-side CODEC */ if (cpu_dai) { codec = cpu_dai->codec; - if (codec && codec->probed && - codec->driver->remove_order == order) - soc_remove_codec(codec); + if (codec && codec->component.probed && + codec->component.driver->remove_order == order) + soc_remove_component(&codec->component); } } @@ -1146,137 +1121,108 @@ static void soc_set_name_prefix(struct snd_soc_card *card, } } -static int soc_probe_codec(struct snd_soc_card *card, - struct snd_soc_codec *codec) +static int soc_probe_component(struct snd_soc_card *card, + struct snd_soc_component *component) { - int ret = 0; - const struct snd_soc_codec_driver *driver = codec->driver; + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + struct snd_soc_component *dai_component, *component2; struct snd_soc_dai *dai; + int ret; - codec->component.card = card; - codec->dapm.card = card; - soc_set_name_prefix(card, &codec->component); + component->card = card; + dapm->card = card; + soc_set_name_prefix(card, component); - if (!try_module_get(codec->dev->driver->owner)) + if (!try_module_get(component->dev->driver->owner)) return -ENODEV; - soc_init_component_debugfs(&codec->component); + soc_init_component_debugfs(component); - if (driver->dapm_widgets) { - ret = snd_soc_dapm_new_controls(&codec->dapm, - driver->dapm_widgets, - driver->num_dapm_widgets); + if (component->dapm_widgets) { + ret = snd_soc_dapm_new_controls(dapm, component->dapm_widgets, + component->num_dapm_widgets); if (ret != 0) { - dev_err(codec->dev, + dev_err(component->dev, "Failed to create new controls %d\n", ret); goto err_probe; } } - /* Create DAPM widgets for each DAI stream */ - list_for_each_entry(dai, &codec->component.dai_list, list) { - ret = snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); + /* + * This is rather ugly, but certain platforms expect that the DAPM + * widgets for the DAIs for components with the same parent device are + * created in the platforms DAPM context. Until that is fixed we need to + * keep this. + */ + if (component->steal_sibling_dai_widgets) { + dai_component = NULL; + list_for_each_entry(component2, &component_list, list) { + if (component == component2) + continue; - if (ret != 0) { - dev_err(codec->dev, - "Failed to create DAI widgets %d\n", ret); - goto err_probe; + if (component2->dev == component->dev && + !list_empty(&component2->dai_list)) { + dai_component = component2; + break; + } } - } - - codec->dapm.idle_bias_off = driver->idle_bias_off; - - if (driver->probe) { - ret = driver->probe(codec); - if (ret < 0) { - dev_err(codec->dev, - "ASoC: failed to probe CODEC %d\n", ret); - goto err_probe; + } else { + dai_component = component; + list_for_each_entry(component2, &component_list, list) { + if (component2->dev == component->dev && + component2->steal_sibling_dai_widgets) { + dai_component = NULL; + break; + } } - WARN(codec->dapm.idle_bias_off && - codec->dapm.bias_level != SND_SOC_BIAS_OFF, - "codec %s can not start from non-off bias with idle_bias_off==1\n", - codec->component.name); } - if (driver->controls) - snd_soc_add_codec_controls(codec, driver->controls, - driver->num_controls); - if (driver->dapm_routes) - snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes, - driver->num_dapm_routes); - - /* mark codec as probed and add to card codec list */ - codec->probed = 1; - list_add(&codec->card_list, &card->codec_dev_list); - list_add(&codec->dapm.list, &card->dapm_list); - - return 0; - -err_probe: - soc_cleanup_component_debugfs(&codec->component); - module_put(codec->dev->driver->owner); - - return ret; -} - -static int soc_probe_platform(struct snd_soc_card *card, - struct snd_soc_platform *platform) -{ - int ret = 0; - const struct snd_soc_platform_driver *driver = platform->driver; - struct snd_soc_component *component; - struct snd_soc_dai *dai; - - platform->component.card = card; - platform->component.dapm.card = card; - - if (!try_module_get(platform->dev->driver->owner)) - return -ENODEV; - - soc_init_component_debugfs(&platform->component); - - if (driver->dapm_widgets) - snd_soc_dapm_new_controls(&platform->component.dapm, - driver->dapm_widgets, driver->num_dapm_widgets); - - /* Create DAPM widgets for each DAI stream */ - list_for_each_entry(component, &component_list, list) { - if (component->dev != platform->dev) - continue; - list_for_each_entry(dai, &component->dai_list, list) - snd_soc_dapm_new_dai_widgets(&platform->component.dapm, - dai); + if (dai_component) { + list_for_each_entry(dai, &dai_component->dai_list, list) { + snd_soc_dapm_new_dai_widgets(dapm, dai); + if (ret != 0) { + dev_err(component->dev, + "Failed to create DAI widgets %d\n", + ret); + goto err_probe; + } + } } - platform->component.dapm.idle_bias_off = 1; - - if (driver->probe) { - ret = driver->probe(platform); + if (component->probe) { + ret = component->probe(component); if (ret < 0) { - dev_err(platform->dev, - "ASoC: failed to probe platform %d\n", ret); + dev_err(component->dev, + "ASoC: failed to probe component %d\n", ret); goto err_probe; } + + WARN(dapm->idle_bias_off && + dapm->bias_level != SND_SOC_BIAS_OFF, + "codec %s can not start from non-off bias with idle_bias_off==1\n", + component->name); } - if (driver->controls) - snd_soc_add_platform_controls(platform, driver->controls, - driver->num_controls); - if (driver->dapm_routes) - snd_soc_dapm_add_routes(&platform->component.dapm, - driver->dapm_routes, driver->num_dapm_routes); + if (component->controls) + snd_soc_add_component_controls(component, component->controls, + component->num_controls); + if (component->dapm_routes) + snd_soc_dapm_add_routes(dapm, component->dapm_routes, + component->num_dapm_routes); - /* mark platform as probed and add to card platform list */ - platform->probed = 1; - list_add(&platform->component.dapm.list, &card->dapm_list); + component->probed = 1; + list_add(&dapm->list, &card->dapm_list); + + /* This is a HACK and will be removed soon */ + if (component->codec) + list_add(&component->codec->card_list, &card->codec_dev_list); return 0; err_probe: - soc_cleanup_component_debugfs(&platform->component); - module_put(platform->dev->driver->owner); + soc_cleanup_component_debugfs(component); + module_put(component->dev->driver->owner); return ret; } @@ -1334,33 +1280,36 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num, int order) { struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_component *component; int i, ret; /* probe the CPU-side component, if it is a CODEC */ - if (cpu_dai->codec && - !cpu_dai->codec->probed && - cpu_dai->codec->driver->probe_order == order) { - ret = soc_probe_codec(card, cpu_dai->codec); - if (ret < 0) - return ret; + if (rtd->cpu_dai->codec) { + component = &rtd->cpu_dai->codec->component; + if (!component->probed && + component->driver->probe_order == order) { + ret = soc_probe_component(card, component); + if (ret < 0) + return ret; + } } /* probe the CODEC-side components */ for (i = 0; i < rtd->num_codecs; i++) { - if (!rtd->codec_dais[i]->codec->probed && - rtd->codec_dais[i]->codec->driver->probe_order == order) { - ret = soc_probe_codec(card, rtd->codec_dais[i]->codec); + component = &rtd->codec_dais[i]->codec->component; + if (!component->probed && + component->driver->probe_order == order) { + ret = soc_probe_component(card, component); if (ret < 0) return ret; } } /* probe the platform */ - if (!platform->probed && - platform->driver->probe_order == order) { - ret = soc_probe_platform(card, platform); + if (!platform->component.probed && + platform->component.driver->probe_order == order) { + ret = soc_probe_component(card, &platform->component); if (ret < 0) return ret; } @@ -1647,12 +1596,12 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num) struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; int ret; - if (rtd->codec->probed) { + if (rtd->codec->component.probed) { dev_err(rtd->codec->dev, "ASoC: codec already probed\n"); return -EBUSY; } - ret = soc_probe_codec(card, rtd->codec); + ret = soc_probe_component(card, &rtd->codec->component); if (ret < 0) return ret; @@ -1681,8 +1630,8 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num) rtd->dev_registered = 0; } - if (codec && codec->probed) - soc_remove_codec(codec); + if (codec && codec->component.probed) + soc_remove_component(&codec->component); } static int snd_soc_init_codec_cache(struct snd_soc_codec *codec) @@ -4198,6 +4147,20 @@ found: } EXPORT_SYMBOL_GPL(snd_soc_unregister_component); +static int snd_soc_platform_drv_probe(struct snd_soc_component *component) +{ + struct snd_soc_platform *platform = snd_soc_component_to_platform(component); + + return platform->driver->probe(platform); +} + +static void snd_soc_platform_drv_remove(struct snd_soc_component *component) +{ + struct snd_soc_platform *platform = snd_soc_component_to_platform(component); + + platform->driver->remove(platform); +} + static int snd_soc_platform_drv_write(struct snd_soc_component *component, unsigned int reg, unsigned int val) { @@ -4234,6 +4197,24 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, platform->dev = dev; platform->driver = platform_drv; + if (platform_drv->controls) { + platform->component.controls = platform_drv->controls; + platform->component.num_controls = platform_drv->num_controls; + } + if (platform_drv->dapm_widgets) { + platform->component.dapm_widgets = platform_drv->dapm_widgets; + platform->component.num_dapm_widgets = platform_drv->num_dapm_widgets; + platform->component.steal_sibling_dai_widgets = true; + } + if (platform_drv->dapm_routes) { + platform->component.dapm_routes = platform_drv->dapm_routes; + platform->component.num_dapm_routes = platform_drv->num_dapm_routes; + } + + if (platform_drv->probe) + platform->component.probe = snd_soc_platform_drv_probe; + if (platform_drv->remove) + platform->component.remove = snd_soc_platform_drv_remove; if (platform_drv->write) platform->component.write = snd_soc_platform_drv_write; if (platform_drv->read) @@ -4363,6 +4344,20 @@ static void fixup_codec_formats(struct snd_soc_pcm_stream *stream) stream->formats |= codec_format_map[i]; } +static int snd_soc_codec_drv_probe(struct snd_soc_component *component) +{ + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + + return codec->driver->probe(codec); +} + +static void snd_soc_codec_drv_remove(struct snd_soc_component *component) +{ + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + + codec->driver->remove(codec); +} + static int snd_soc_codec_drv_write(struct snd_soc_component *component, unsigned int reg, unsigned int val) { @@ -4411,12 +4406,30 @@ int snd_soc_register_codec(struct device *dev, return -ENOMEM; codec->component.dapm_ptr = &codec->dapm; + codec->component.codec = codec; ret = snd_soc_component_initialize(&codec->component, &codec_drv->component_driver, dev); if (ret) goto err_free; + if (codec_drv->controls) { + codec->component.controls = codec_drv->controls; + codec->component.num_controls = codec_drv->num_controls; + } + if (codec_drv->dapm_widgets) { + codec->component.dapm_widgets = codec_drv->dapm_widgets; + codec->component.num_dapm_widgets = codec_drv->num_dapm_widgets; + } + if (codec_drv->dapm_routes) { + codec->component.dapm_routes = codec_drv->dapm_routes; + codec->component.num_dapm_routes = codec_drv->num_dapm_routes; + } + + if (codec_drv->probe) + codec->component.probe = snd_soc_codec_drv_probe; + if (codec_drv->remove) + codec->component.remove = snd_soc_codec_drv_remove; if (codec_drv->write) codec->component.write = snd_soc_codec_drv_write; if (codec_drv->read) diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 6307f85e871b..b329b84bc5af 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -336,10 +336,12 @@ static const struct snd_pcm_ops dmaengine_pcm_ops = { }; static const struct snd_soc_platform_driver dmaengine_pcm_platform = { + .component_driver = { + .probe_order = SND_SOC_COMP_ORDER_LATE, + }, .ops = &dmaengine_pcm_ops, .pcm_new = dmaengine_pcm_new, .pcm_free = dmaengine_pcm_free, - .probe_order = SND_SOC_COMP_ORDER_LATE, }; static const char * const dmaengine_pcm_dma_channel_names[] = { -- cgit v1.2.3 From 93c3ce76ccced3a8718149e8734ccaa931e9a1f1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 19 Aug 2014 15:51:20 +0200 Subject: ASoC: Make rtd->codec optional There are some place in the ASoC core that expect rtd->codec to be non NULL (mainly CODEC specific sysfs files). With componentization going forward rtd->codec might be NULL in some cases. This patch prepares the core for this by not registering CODEC specific sysfs files if rtd->codec is NULL. sysfs file removal does not need to be conditionalized as it handles the removal of non-existing files just fine. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b833cc6fd86d..1c705c28389c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1261,17 +1261,21 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, } rtd->dev_registered = 1; - /* add DAPM sysfs entries for this codec */ - ret = snd_soc_dapm_sys_add(rtd->dev); - if (ret < 0) - dev_err(rtd->dev, - "ASoC: failed to add codec dapm sysfs entries: %d\n", ret); + if (rtd->codec) { + /* add DAPM sysfs entries for this codec */ + ret = snd_soc_dapm_sys_add(rtd->dev); + if (ret < 0) + dev_err(rtd->dev, + "ASoC: failed to add codec dapm sysfs entries: %d\n", + ret); - /* add codec sysfs entries */ - ret = device_create_file(rtd->dev, &dev_attr_codec_reg); - if (ret < 0) - dev_err(rtd->dev, - "ASoC: failed to add codec sysfs files: %d\n", ret); + /* add codec sysfs entries */ + ret = device_create_file(rtd->dev, &dev_attr_codec_reg); + if (ret < 0) + dev_err(rtd->dev, + "ASoC: failed to add codec sysfs files: %d\n", + ret); + } return 0; } -- cgit v1.2.3 From 61aca5646b736a794d40de29a197144db3f0c5ba Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 19 Aug 2014 15:51:21 +0200 Subject: ASoC: Add component level probe/remove support Now that we have a unified probe and remove path make sure to call them for all components. soc_{probe,remove}_component are responsible for setting up the DAPM context for the component, initialize the component prefix, manage the debugfs entries as well as do the registration of table based controls and DAPM elements. They also call the component drivers probe and remove callbacks. This patch makes these things available for generic snd_soc_component drivers rather than only having them for snd_soc_codec and snd_soc_platform drivers. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 11 +++++++++++ sound/soc/soc-core.c | 42 ++++++++++++++++++++++++------------------ 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 22543acfae4b..4a223a895f00 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -690,6 +690,17 @@ struct snd_soc_compr_ops { struct snd_soc_component_driver { const char *name; + /* Default control and setup, added after probe() is run */ + const struct snd_kcontrol_new *controls; + unsigned int num_controls; + const struct snd_soc_dapm_widget *dapm_widgets; + unsigned int num_dapm_widgets; + const struct snd_soc_dapm_route *dapm_routes; + unsigned int num_dapm_routes; + + int (*probe)(struct snd_soc_component *); + void (*remove)(struct snd_soc_component *); + /* DT */ int (*of_xlate_dai_name)(struct snd_soc_component *component, struct of_phandle_args *args, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 1c705c28389c..08fd85e8c751 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1058,7 +1058,7 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num, struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_platform *platform = rtd->platform; - struct snd_soc_codec *codec; + struct snd_soc_component *component; int i; /* remove the platform */ @@ -1068,18 +1068,17 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num, /* remove the CODEC-side CODEC */ for (i = 0; i < rtd->num_codecs; i++) { - codec = rtd->codec_dais[i]->codec; - if (codec && codec->component.probed && - codec->component.driver->remove_order == order) - soc_remove_component(&codec->component); + component = rtd->codec_dais[i]->component; + if (component->probed && + component->driver->remove_order == order) + soc_remove_component(component); } /* remove any CPU-side CODEC */ if (cpu_dai) { - codec = cpu_dai->codec; - if (codec && codec->component.probed && - codec->component.driver->remove_order == order) - soc_remove_component(&codec->component); + if (cpu_dai->component->probed && + cpu_dai->component->driver->remove_order == order) + soc_remove_component(cpu_dai->component); } } @@ -1289,19 +1288,17 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num, int i, ret; /* probe the CPU-side component, if it is a CODEC */ - if (rtd->cpu_dai->codec) { - component = &rtd->cpu_dai->codec->component; - if (!component->probed && - component->driver->probe_order == order) { - ret = soc_probe_component(card, component); - if (ret < 0) - return ret; - } + component = rtd->cpu_dai->component; + if (!component->probed && + component->driver->probe_order == order) { + ret = soc_probe_component(card, component); + if (ret < 0) + return ret; } /* probe the CODEC-side components */ for (i = 0; i < rtd->num_codecs; i++) { - component = &rtd->codec_dais[i]->codec->component; + component = rtd->codec_dais[i]->component; if (!component->probed && component->driver->probe_order == order) { ret = soc_probe_component(card, component); @@ -4042,6 +4039,8 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, component->dev = dev; component->driver = driver; + component->probe = component->driver->probe; + component->remove = component->driver->remove; if (!component->dapm_ptr) component->dapm_ptr = &component->dapm; @@ -4055,6 +4054,13 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, if (driver->stream_event) dapm->stream_event = snd_soc_component_stream_event; + component->controls = driver->controls; + component->num_controls = driver->num_controls; + component->dapm_widgets = driver->dapm_widgets; + component->num_dapm_widgets = driver->num_dapm_widgets; + component->dapm_routes = driver->dapm_routes; + component->num_dapm_routes = driver->num_dapm_routes; + INIT_LIST_HEAD(&component->dai_list); mutex_init(&component->io_mutex); -- cgit v1.2.3 From 65d9361f0cb50a20641802ee3075145d72e4409c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 19 Aug 2014 15:51:22 +0200 Subject: ASoC: Move AUX dev support to the component level This patch makes it possible to register arbitrary components as a AUX dev for a card. This was previously only possible for CODEC components. With componentization having made it possible for components to have DAPM contexts and controls there is no reason why AUX devs should be artificially limited to snd_soc_codec devices. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 1 + sound/soc/soc-core.c | 48 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 4a223a895f00..fbc2ad840244 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1140,6 +1140,7 @@ struct snd_soc_pcm_runtime { struct snd_soc_platform *platform; struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai; + struct snd_soc_component *component; /* Only valid for AUX dev rtds */ struct snd_soc_dai **codec_dais; unsigned int num_codecs; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 08fd85e8c751..08c04f4c7e62 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -860,6 +860,23 @@ EXPORT_SYMBOL_GPL(snd_soc_resume); static const struct snd_soc_dai_ops null_dai_ops = { }; +static struct snd_soc_component *soc_find_component( + const struct device_node *of_node, const char *name) +{ + struct snd_soc_component *component; + + list_for_each_entry(component, &component_list, list) { + if (of_node) { + if (component->dev->of_node == of_node) + return component; + } else if (strcmp(component->name, name) == 0) { + return component; + } + } + + return NULL; +} + static struct snd_soc_codec *soc_find_codec( const struct device_node *codec_of_node, const char *codec_name) @@ -1577,17 +1594,24 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num) { struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; - const char *codecname = aux_dev->codec_name; + const char *name = aux_dev->codec_name; - rtd->codec = soc_find_codec(aux_dev->codec_of_node, codecname); - if (!rtd->codec) { + rtd->component = soc_find_component(aux_dev->codec_of_node, name); + if (!rtd->component) { if (aux_dev->codec_of_node) - codecname = of_node_full_name(aux_dev->codec_of_node); + name = of_node_full_name(aux_dev->codec_of_node); - dev_err(card->dev, "ASoC: %s not registered\n", codecname); + dev_err(card->dev, "ASoC: %s not registered\n", name); return -EPROBE_DEFER; } + /* + * Some places still reference rtd->codec, so we have to keep that + * initialized if the component is a CODEC. Once all those references + * have been removed, this code can be removed as well. + */ + rtd->codec = rt