[alsa-devel] [PATCH v4 0/3] ASoC: qcom: add support to apq8016 audio
Hi Mark,
Thanks for applying the patches.
Am resending the leftover patches rebased on top of topic/qcom branch. I have funtionally tested these patches on AP8016-SBC board and also compile tested them without CONFIG_OF on x86 to make sure nothing breaks. All these patches are tested and Acked.
I Also included Arnd's Patch to fix Kconfig dependency on STORM board.
APQ8016 has 4 MI2S( Primary, Secondary, Tertiary, Quaternary) which can be routed to internal wcd codec or external codecs. This routing is controlled by 2 mux registers.
Changes since v3 - dropped OF dependency patch - dropped 6 patches which are already applied by Mark. - fixed Kconfig as suggested by Arnd.
Changes since v2(https://lkml.org/lkml/2015/5/16/236) - dropped 3 patches which are already applied by Mark. - rebased on top of topic/qcom branch. - changed dev_err to dev_warn spotted by Kenneth. - fixed typo spotted by kenneth.
Changes since v1(https://lwn.net/Articles/644266/) - Fixed Kconfig dependencies spotted by Kenneth - Fixed compilation error on ipq806x spotted by Kenneth - Fixed clk error messages spotted by Kenneth
Changes since RFC(https://lwn.net/Articles/642661/) - droped cleanup patches, as they are already applied by Mark. - prefixed shared functions with asoc_qcom_* as suggested by Kenneth - made LPASS driver depended on OF. - removed ipq806x specific bits from ipaif_reg.h - removed no_osr clk flag as suggested by Mark and Kenneth - fixed irq return values spotted by Kenneth - renamed the machine file to apq8016-sbc.c as suggested by Kenneth. - use dai->driver->id instead of dai->id as it breaks on Storm board.
--srini Arnd Bergmann (1): ASoC: qcom: fix STORM board Kconfig
Srinivas Kandagatla (2): ASoC: qcom: Add apq8016 lpass driver support ASoC: qcom: add apq8016 sound card support
include/dt-bindings/sound/apq8016-lpass.h | 9 ++ sound/soc/qcom/Kconfig | 17 ++- sound/soc/qcom/Makefile | 4 + sound/soc/qcom/apq8016_sbc.c | 215 ++++++++++++++++++++++++++ sound/soc/qcom/lpass-apq8016.c | 242 ++++++++++++++++++++++++++++++ sound/soc/qcom/lpass.h | 4 + 6 files changed, 490 insertions(+), 1 deletion(-) create mode 100644 include/dt-bindings/sound/apq8016-lpass.h create mode 100644 sound/soc/qcom/apq8016_sbc.c create mode 100644 sound/soc/qcom/lpass-apq8016.c
This patch adds apq8016 lpass driver support. APQ8016 has 4 MI2S which can be routed to one internal codec and 2 external codec interfaces.
Primary, Secondary, Quaternary I2S can do Rx(playback) and Tertiary and Quaternary can do Tx(capture).
Tested-by: Kenneth Westfield kwestfie@codeaurora.org Acked-by: Kenneth Westfield kwestfie@codeaurora.org Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- include/dt-bindings/sound/apq8016-lpass.h | 9 ++ sound/soc/qcom/Kconfig | 6 + sound/soc/qcom/Makefile | 2 + sound/soc/qcom/lpass-apq8016.c | 242 ++++++++++++++++++++++++++++++ sound/soc/qcom/lpass.h | 4 + 5 files changed, 263 insertions(+) create mode 100644 include/dt-bindings/sound/apq8016-lpass.h create mode 100644 sound/soc/qcom/lpass-apq8016.c
diff --git a/include/dt-bindings/sound/apq8016-lpass.h b/include/dt-bindings/sound/apq8016-lpass.h new file mode 100644 index 0000000..499076e --- /dev/null +++ b/include/dt-bindings/sound/apq8016-lpass.h @@ -0,0 +1,9 @@ +#ifndef __DT_APQ8016_LPASS_H +#define __DT_APQ8016_LPASS_H + +#define MI2S_PRIMARY 0 +#define MI2S_SECONDARY 1 +#define MI2S_TERTIARY 2 +#define MI2S_QUATERNARY 3 + +#endif /* __DT_APQ8016_LPASS_H */ diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index b30c2ba..29fff6d 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -18,6 +18,12 @@ config SND_SOC_LPASS_IPQ806X select SND_SOC_LPASS_CPU select SND_SOC_LPASS_PLATFORM
+config SND_SOC_LPASS_APQ8016 + tristate + depends on SND_SOC_QCOM + select SND_SOC_LPASS_CPU + select SND_SOC_LPASS_PLATFORM + config SND_SOC_STORM tristate "ASoC I2S support for Storm boards" depends on (ARCH_QCOM && SND_SOC_QCOM) || COMPILE_TEST diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index f8aab91..ac76308 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -2,10 +2,12 @@ snd-soc-lpass-cpu-objs := lpass-cpu.o snd-soc-lpass-platform-objs := lpass-platform.o snd-soc-lpass-ipq806x-objs := lpass-ipq806x.o +snd-soc-lpass-apq8016-objs := lpass-apq8016.o
obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o obj-$(CONFIG_SND_SOC_LPASS_IPQ806X) += snd-soc-lpass-ipq806x.o +obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += snd-soc-lpass-apq8016.o
# Machine snd-soc-storm-objs := storm.o diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c new file mode 100644 index 0000000..94efc01 --- /dev/null +++ b/sound/soc/qcom/lpass-apq8016.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + * + * lpass-apq8016.c -- ALSA SoC CPU DAI driver for APQ8016 LPASS + * + */ + + +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/soc-dai.h> + +#include <dt-bindings/sound/apq8016-lpass.h> +#include "lpass-lpaif-reg.h" +#include "lpass.h" + +static struct snd_soc_dai_driver apq8016_lpass_cpu_dai_driver[] = { + [MI2S_PRIMARY] = { + .id = MI2S_PRIMARY, + .name = "Primary MI2S", + .playback = { + .stream_name = "Primary Playback", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, + }, + [MI2S_SECONDARY] = { + .id = MI2S_SECONDARY, + .name = "Secondary MI2S", + .playback = { + .stream_name = "Secondary Playback", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, + }, + [MI2S_TERTIARY] = { + .id = MI2S_TERTIARY, + .name = "Tertiary MI2S", + .capture = { + .stream_name = "Tertiary Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, + }, + [MI2S_QUATERNARY] = { + .id = MI2S_QUATERNARY, + .name = "Quatenary MI2S", + .playback = { + .stream_name = "Quatenary Playback", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + }, + .capture = { + .stream_name = "Quatenary Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, + }, +}; + +static int apq8016_lpass_alloc_dma_channel(struct lpass_data *drvdata) +{ + struct lpass_variant *v = drvdata->variant; + int chan = find_first_zero_bit(&drvdata->rdma_ch_bit_map, + v->rdma_channels); + + if (chan >= v->rdma_channels) + return -EBUSY; + + set_bit(chan, &drvdata->rdma_ch_bit_map); + + return chan; +} + +static int apq8016_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) +{ + clear_bit(chan, &drvdata->rdma_ch_bit_map); + + return 0; +} + +static int apq8016_lpass_init(struct platform_device *pdev) +{ + struct lpass_data *drvdata = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + int ret; + + drvdata->pcnoc_mport_clk = devm_clk_get(dev, "pcnoc-mport-clk"); + if (IS_ERR(drvdata->pcnoc_mport_clk)) { + dev_err(&pdev->dev, "%s() error getting pcnoc-mport-clk: %ld\n", + __func__, PTR_ERR(drvdata->pcnoc_mport_clk)); + return PTR_ERR(drvdata->pcnoc_mport_clk); + } + + ret = clk_prepare_enable(drvdata->pcnoc_mport_clk); + if (ret) { + dev_err(&pdev->dev, "%s() Error enabling pcnoc-mport-clk: %d\n", + __func__, ret); + return ret; + } + + drvdata->pcnoc_sway_clk = devm_clk_get(dev, "pcnoc-sway-clk"); + if (IS_ERR(drvdata->pcnoc_sway_clk)) { + dev_err(&pdev->dev, "%s() error getting pcnoc-sway-clk: %ld\n", + __func__, PTR_ERR(drvdata->pcnoc_sway_clk)); + return PTR_ERR(drvdata->pcnoc_sway_clk); + } + + ret = clk_prepare_enable(drvdata->pcnoc_sway_clk); + if (ret) { + dev_err(&pdev->dev, "%s() Error enabling pcnoc_sway_clk: %d\n", + __func__, ret); + return ret; + } + + return 0; +} + +static int apq8016_lpass_exit(struct platform_device *pdev) +{ + struct lpass_data *drvdata = platform_get_drvdata(pdev); + + clk_disable_unprepare(drvdata->pcnoc_mport_clk); + clk_disable_unprepare(drvdata->pcnoc_sway_clk); + + return 0; +} + + +static struct lpass_variant apq8016_data = { + .i2sctrl_reg_base = 0x1000, + .i2sctrl_reg_stride = 0x1000, + .i2s_ports = 4, + .irq_reg_base = 0x6000, + .irq_reg_stride = 0x1000, + .irq_ports = 3, + .rdma_reg_base = 0x8400, + .rdma_reg_stride = 0x1000, + .rdma_channels = 2, + .rdmactl_audif_start = 1, + .dai_driver = apq8016_lpass_cpu_dai_driver, + .num_dai = ARRAY_SIZE(apq8016_lpass_cpu_dai_driver), + .init = apq8016_lpass_init, + .exit = apq8016_lpass_exit, + .alloc_dma_channel = apq8016_lpass_alloc_dma_channel, + .free_dma_channel = apq8016_lpass_free_dma_channel, +}; + +static const struct of_device_id apq8016_lpass_cpu_device_id[] = { + { .compatible = "qcom,lpass-cpu-apq8016", .data = &apq8016_data }, + {} +}; +MODULE_DEVICE_TABLE(of, apq8016_lpass_cpu_device_id); + +static struct platform_driver apq8016_lpass_cpu_platform_driver = { + .driver = { + .name = "apq8016-lpass-cpu", + .of_match_table = of_match_ptr(apq8016_lpass_cpu_device_id), + }, + .probe = asoc_qcom_lpass_cpu_platform_probe, + .remove = asoc_qcom_lpass_cpu_platform_remove, +}; +module_platform_driver(apq8016_lpass_cpu_platform_driver); + +MODULE_DESCRIPTION("APQ8016 LPASS CPU Driver"); +MODULE_LICENSE("GPL v2"); + diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index deecae9..d6e86c1 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -54,6 +54,10 @@ struct lpass_data {
/* used it for handling interrupt per dma channel */ struct snd_pcm_substream *substream[LPASS_MAX_DMA_CHANNELS]; + + /* 8016 specific */ + struct clk *pcnoc_mport_clk; + struct clk *pcnoc_sway_clk; };
/* Vairant data per each SOC */
On Fri, May 22, 2015 at 04:53:52PM +0100, Srinivas Kandagatla wrote:
This patch adds apq8016 lpass driver support. APQ8016 has 4 MI2S which can be routed to one internal codec and 2 external codec interfaces.
Applied, thanks.
This patch adds apq8016 machine driver support. This patch was tested on two apq8016-sbc and msm8916-mtp board for both hdmi and analog audio features.
Tested-by: Kenneth Westfield kwestfie@codeaurora.org Acked-by: Kenneth Westfield kwestfie@codeaurora.org Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/qcom/Kconfig | 9 ++ sound/soc/qcom/Makefile | 2 + sound/soc/qcom/apq8016_sbc.c | 215 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 sound/soc/qcom/apq8016_sbc.c
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 29fff6d..6ecac6c 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -32,3 +32,12 @@ config SND_SOC_STORM help Say Y or M if you want add support for SoC audio on the Qualcomm Technologies IPQ806X-based Storm board. + +config SND_SOC_APQ8016_SBC + tristate "SoC Audio support for APQ8016 SBC platforms" + depends on SND_SOC_QCOM && (ARCH_QCOM || COMPILE_TEST) + select SND_SOC_LPASS_APQ8016 + help + Support for Qualcomm Technologies LPASS audio block in + APQ8016 SOC-based systems. + Say Y if you want to use audio devices on MI2S diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index ac76308..79e5c50 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -11,5 +11,7 @@ obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += snd-soc-lpass-apq8016.o
# Machine snd-soc-storm-objs := storm.o +snd-soc-apq8016-sbc-objs := apq8016_sbc.o
obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o +obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c new file mode 100644 index 0000000..8958633 --- /dev/null +++ b/sound/soc/qcom/apq8016_sbc.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + * + */ + +#include <linux/device.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <dt-bindings/sound/apq8016-lpass.h> + +struct apq8016_sbc_data { + void __iomem *mic_iomux; + void __iomem *spkr_iomux; + struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ +}; + +#define MIC_CTRL_QUA_WS_SLAVE_SEL_10 BIT(17) +#define MIC_CTRL_TLMM_SCLK_EN BIT(1) +#define SPKR_CTL_PRI_WS_SLAVE_SEL_11 (BIT(17) | BIT(16)) + +static int apq8016_sbc_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_card *card = rtd->card; + struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card); + + if (cpu_dai->id == MI2S_QUATERNARY) { + /* Configure the Quat MI2S to TLMM */ + writel(readl(pdata->mic_iomux) | + MIC_CTRL_QUA_WS_SLAVE_SEL_10 | + MIC_CTRL_TLMM_SCLK_EN, + pdata->mic_iomux); + + return 0; + } else if (cpu_dai->id == MI2S_PRIMARY) { + writel(readl(pdata->spkr_iomux) | + SPKR_CTL_PRI_WS_SLAVE_SEL_11, + pdata->spkr_iomux); + + return 0; + } + + dev_err(card->dev, "unsupported cpu dai configuration\n"); + + return -EINVAL; +} + +static struct snd_soc_ops apq8016_sbc_soc_ops = { + .startup = apq8016_sbc_startup, +}; + +static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) +{ + int num_links; + struct device *dev = card->dev; + struct snd_soc_dai_link *dai_link; + struct device_node *np, *codec, *cpu, *node = dev->of_node; + struct apq8016_sbc_data *data; + char *name; + int ret; + + /* Populate links */ + num_links = of_get_child_count(node); + + /* Allocate the private data and the DAI link array */ + data = devm_kzalloc(dev, sizeof(*data) + sizeof(*dai_link) * num_links, + GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); + + card->dai_link = &data->dai_link[0]; + card->num_links = num_links; + + dai_link = data->dai_link; + + for_each_child_of_node(node, np) { + cpu = of_get_child_by_name(np, "cpu"); + codec = of_get_child_by_name(np, "codec"); + + if (!cpu || !codec) { + dev_err(dev, "Can't find cpu/codec DT node\n"); + return ERR_PTR(-EINVAL); + } + + dai_link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0); + if (!dai_link->cpu_of_node) { + dev_err(card->dev, "error getting cpu phandle\n"); + return ERR_PTR(-EINVAL); + } + + dai_link->codec_of_node = of_parse_phandle(codec, + "sound-dai", + 0); + if (!dai_link->codec_of_node) { + dev_err(card->dev, "error getting codec phandle\n"); + return ERR_PTR(-EINVAL); + } + + ret = snd_soc_of_get_dai_name(cpu, &dai_link->cpu_dai_name); + if (ret) { + dev_err(card->dev, "error getting cpu dai name\n"); + return ERR_PTR(ret); + } + + ret = snd_soc_of_get_dai_name(codec, &dai_link->codec_dai_name); + if (ret) { + dev_err(card->dev, "error getting codec dai name\n"); + return ERR_PTR(ret); + } + + dai_link->platform_of_node = dai_link->cpu_of_node; + /* For now we only support playback */ + dai_link->playback_only = true; + + if (of_property_read_bool(np, "external")) + name = "HDMI"; + + else + name = "Headset"; + + dai_link->ops = &apq8016_sbc_soc_ops; + dai_link->name = dai_link->stream_name = name; + + dai_link++; + } + + return data; +} + +static int apq8016_sbc_platform_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct snd_soc_card *card; + struct apq8016_sbc_data *data; + struct resource *res; + int ret; + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + card->dev = dev; + data = apq8016_sbc_parse_of(card); + if (IS_ERR(data)) { + dev_err(&pdev->dev, "Error resolving dai links: %ld\n", + PTR_ERR(data)); + return PTR_ERR(data); + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mic-iomux"); + data->mic_iomux = devm_ioremap_resource(dev, res); + if (IS_ERR(data->mic_iomux)) + return PTR_ERR(data->mic_iomux); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "spkr-iomux"); + data->spkr_iomux = devm_ioremap_resource(dev, res); + if (IS_ERR(data->spkr_iomux)) + return PTR_ERR(data->spkr_iomux); + + platform_set_drvdata(pdev, data); + snd_soc_card_set_drvdata(card, data); + + ret = snd_soc_of_parse_card_name(card, "qcom,model"); + if (ret) { + dev_err(&pdev->dev, "Error parsing card name: %d\n", ret); + return ret; + } + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret == -EPROBE_DEFER) { + card->dev = NULL; + return ret; + } else if (ret) { + dev_err(&pdev->dev, "Error registering soundcard: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct of_device_id apq8016_sbc_device_id[] = { + { .compatible = "qcom,apq8016-sbc-sndcard" }, + {}, +}; +MODULE_DEVICE_TABLE(of, apq8016_sbc_device_id); + +static struct platform_driver apq8016_sbc_platform_driver = { + .driver = { + .name = "qcom-apq8016-sbc", + .of_match_table = of_match_ptr(apq8016_sbc_device_id), + }, + .probe = apq8016_sbc_platform_probe, +}; +module_platform_driver(apq8016_sbc_platform_driver); + +MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org"); +MODULE_DESCRIPTION("APQ8016 ASoC Machine Driver"); +MODULE_LICENSE("GPL v2");
On Fri, May 22, 2015 at 04:54:07PM +0100, Srinivas Kandagatla wrote:
- if (cpu_dai->id == MI2S_QUATERNARY) {
/* Configure the Quat MI2S to TLMM */
writel(readl(pdata->mic_iomux) |
MIC_CTRL_QUA_WS_SLAVE_SEL_10 |
MIC_CTRL_TLMM_SCLK_EN,
pdata->mic_iomux);
return 0;
- } else if (cpu_dai->id == MI2S_PRIMARY) {
This looks like you're trying to write a switch statement. It's also somewhat unclear to me that this should be in a machine driver and not in a CODEC/aux driver that gets pulled in by a machine driver, I can't be entirely sure what this is controlling.
if (of_property_read_bool(np, "external"))
name = "HDMI";
else
name = "Headset";
Coding style. I'm also a bit concerned about the binding here - headsets sound external too?
- card->dev = dev;
- data = apq8016_sbc_parse_of(card);
We parse the DT here and then...
- ret = snd_soc_of_parse_card_name(card, "qcom,model");
- if (ret) {
dev_err(&pdev->dev, "Error parsing card name: %d\n", ret);
return ret;
- }
...this other bit of DT here.
- ret = devm_snd_soc_register_card(&pdev->dev, card);
- if (ret == -EPROBE_DEFER) {
card->dev = NULL;
return ret;
- } else if (ret) {
dev_err(&pdev->dev, "Error registering soundcard: %d\n", ret);
return ret;
- }
If setting card->dev does anything there something is broken, and in general it's just better form to not special case probe deferral.
On 02/06/15 20:55, Mark Brown wrote:
On Fri, May 22, 2015 at 04:54:07PM +0100, Srinivas Kandagatla wrote:
- if (cpu_dai->id == MI2S_QUATERNARY) {
/* Configure the Quat MI2S to TLMM */
writel(readl(pdata->mic_iomux) |
MIC_CTRL_QUA_WS_SLAVE_SEL_10 |
MIC_CTRL_TLMM_SCLK_EN,
pdata->mic_iomux);
return 0;
- } else if (cpu_dai->id == MI2S_PRIMARY) {
This looks like you're trying to write a switch statement. It's also
I started of with switch case but, as this card only uses MI2S_QUATERNARY and MI2S_PRIMARY I converted it to if else statements to save few lines.
somewhat unclear to me that this should be in a machine driver and not in a CODEC/aux driver that gets pulled in by a machine driver, I can't be entirely sure what this is controlling.
This bit of code is writing to a mux control register, which would be very much specific to board wiring. Moving this to machine level could would introduce lot of un-necessary interface.
if (of_property_read_bool(np, "external"))
name = "HDMI";
else
name = "Headset";
Coding style. I'm also a bit concerned about the binding here - headsets sound external too?
I agree, its confusing. The term external in this case describes the placement of codec w.r.t to SOC rather then the audio sink. on APQ8016 we have an internal codec within the SOC which is wiredup to the Headset and on this board we have external ADV7533 codec which is connected to HDMI.
- card->dev = dev;
- data = apq8016_sbc_parse_of(card);
We parse the DT here and then...
- ret = snd_soc_of_parse_card_name(card, "qcom,model");
- if (ret) {
dev_err(&pdev->dev, "Error parsing card name: %d\n", ret);
return ret;
- }
...this other bit of DT here.
I will put this code to the apq8016_sbc_parse_of function.
- ret = devm_snd_soc_register_card(&pdev->dev, card);
- if (ret == -EPROBE_DEFER) {
card->dev = NULL;
return ret;
- } else if (ret) {
dev_err(&pdev->dev, "Error registering soundcard: %d\n", ret);
return ret;
- }
If setting card->dev does anything there something is broken, and in general it's just better form to not special case probe deferral.
Yes, you are right, setting card->dev = NULL is really unnecessary, I will fix it and also remove the special casing the EPROBE_DEFER. There are 2 other drivers which need similar cleanup, I will fix them too.
--srini
From: Arnd Bergmann arnd@arndb.de
This patch is a fixup to correct dependencies in patch 9bae4880acee ("ASoC: qcom: move ipq806x specific bits out of lpass driver.")
Originally this change-set was suggested by Arnd on mailing list.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Signed-off-by: Arnd Bergmann arnd@arndb.de --- sound/soc/qcom/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 6ecac6c..f50197e 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -26,7 +26,7 @@ config SND_SOC_LPASS_APQ8016
config SND_SOC_STORM tristate "ASoC I2S support for Storm boards" - depends on (ARCH_QCOM && SND_SOC_QCOM) || COMPILE_TEST + depends on SND_SOC_QCOM && (ARCH_QCOM || COMPILE_TEST) select SND_SOC_LPASS_IPQ806X select SND_SOC_MAX98357A help
On Friday 22 May 2015 16:54:17 Srinivas Kandagatla wrote:
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 6ecac6c..f50197e 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -26,7 +26,7 @@ config SND_SOC_LPASS_APQ8016
config SND_SOC_STORM tristate "ASoC I2S support for Storm boards"
depends on (ARCH_QCOM && SND_SOC_QCOM) || COMPILE_TEST
depends on SND_SOC_QCOM && (ARCH_QCOM || COMPILE_TEST) select SND_SOC_LPASS_IPQ806X select SND_SOC_MAX98357A help
--
Do you still have the problem that you are selecting another symbol that 'depends on OF', but this one does not have that dependency, or did you drop that patch now before it could get picked up?
Arnd
On 22/05/15 17:33, Arnd Bergmann wrote:
On Friday 22 May 2015 16:54:17 Srinivas Kandagatla wrote:
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 6ecac6c..f50197e 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -26,7 +26,7 @@ config SND_SOC_LPASS_APQ8016
config SND_SOC_STORM tristate "ASoC I2S support for Storm boards"
depends on (ARCH_QCOM && SND_SOC_QCOM) || COMPILE_TEST
depends on SND_SOC_QCOM && (ARCH_QCOM || COMPILE_TEST) select SND_SOC_LPASS_IPQ806X select SND_SOC_MAX98357A help
--
Do you still have the problem that you are selecting another symbol that 'depends on OF', but this one does not have that dependency, or did you drop that patch now before it could get picked up?
Yes, I dropped the OF dependency patch, as these drivers could be compile tested.
--srini
Arnd
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, May 22, 2015 at 04:54:17PM +0100, Srinivas Kandagatla wrote:
From: Arnd Bergmann arnd@arndb.de
This patch is a fixup to correct dependencies in patch 9bae4880acee ("ASoC: qcom: move ipq806x specific bits out of lpass driver.")
Originally this change-set was suggested by Arnd on mailing list.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Signed-off-by: Arnd Bergmann arnd@arndb.de
Did you write this or did Arnd? The authorship suggests that he wrote it but your signoff appears before his. I've assumed Arnd wrote it and reordered but please be more careful and let me know if my assumption is wrong...
participants (3)
-
Arnd Bergmann
-
Mark Brown
-
Srinivas Kandagatla