From 28abd99b6e40741cd0e75be20817f23a3044d338 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 19 Jul 2016 02:53:13 +0000 Subject: ASoC: simple-card: use asoc_simple_card_parse_clk() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 43295f0..b37c81b 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -244,8 +244,6 @@ asoc_simple_card_sub_parse_of(struct device_node *np, int *args_count) { struct of_phandle_args args; - struct clk *clk; - u32 val; int ret; if (!np) @@ -282,29 +280,6 @@ asoc_simple_card_sub_parse_of(struct device_node *np, if (ret) return ret; - /* - * Parse dai->sysclk come from "clocks = <&xxx>" - * (if system has common clock) - * or "system-clock-frequency = " - * or device's module clock. - */ - if (of_property_read_bool(np, "clocks")) { - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - return ret; - } - - dai->sysclk = clk_get_rate(clk); - dai->clk = clk; - } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { - dai->sysclk = val; - } else { - clk = of_clk_get(args.np, 0); - if (!IS_ERR(clk)) - dai->sysclk = clk_get_rate(clk); - } - return 0; } @@ -316,6 +291,8 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, struct device *dev = simple_priv_to_dev(priv); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx); + struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai; + struct asoc_simple_dai *codec_dai = &dai_props->codec_dai; struct device_node *cpu = NULL; struct device_node *plat = NULL; struct device_node *codec = NULL; @@ -370,6 +347,14 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, if (ret < 0) goto dai_link_of_err; + ret = asoc_simple_card_parse_clk_cpu(cpu, dai_link, cpu_dai); + if (ret < 0) + goto dai_link_of_err; + + ret = asoc_simple_card_parse_clk_codec(codec, dai_link, codec_dai); + if (ret < 0) + goto dai_link_of_err; + if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { ret = -EINVAL; goto dai_link_of_err; -- cgit v0.10.2 From c9a235da8a61cf9af7653fca341ded0881a64eca Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 19 Jul 2016 02:53:32 +0000 Subject: ASoC: rsrc-card: use asoc_simple_card_parse_clk() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index fa37f84..ed5391f 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -190,6 +190,10 @@ static int rsrc_card_parse_links(struct device_node *np, if (ret < 0) return ret; + ret = asoc_simple_card_parse_clk_cpu(np, dai_link, dai_props); + if (ret < 0) + return ret; + ret = asoc_simple_card_set_dailink_name(dev, dai_link, "fe.%s", dai_link->cpu_dai_name); @@ -225,6 +229,10 @@ static int rsrc_card_parse_links(struct device_node *np, if (ret < 0) return ret; + ret = asoc_simple_card_parse_clk_codec(np, dai_link, dai_props); + if (ret < 0) + return ret; + ret = asoc_simple_card_set_dailink_name(dev, dai_link, "be.%s", dai_link->codec_dai_name); @@ -250,68 +258,12 @@ static int rsrc_card_parse_links(struct device_node *np, dai_link->ops = &rsrc_card_ops; dai_link->init = rsrc_card_dai_init; - return 0; -} - -static int rsrc_card_parse_clk(struct device_node *np, - struct rsrc_card_priv *priv, - int idx, bool is_fe) -{ - struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); - struct asoc_simple_dai *dai_props = rsrc_priv_to_props(priv, idx); - struct clk *clk; - struct device_node *of_np = is_fe ? dai_link->cpu_of_node : - dai_link->codec_of_node; - u32 val; - - /* - * Parse dai->sysclk come from "clocks = <&xxx>" - * (if system has common clock) - * or "system-clock-frequency = " - * or device's module clock. - */ - if (of_property_read_bool(np, "clocks")) { - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - dai_props->sysclk = clk_get_rate(clk); - dai_props->clk = clk; - } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { - dai_props->sysclk = val; - } else { - clk = of_clk_get(of_np, 0); - if (!IS_ERR(clk)) - dai_props->sysclk = clk_get_rate(clk); - } - - return 0; -} - -static int rsrc_card_dai_sub_link_of(struct device_node *node, - struct device_node *np, - struct rsrc_card_priv *priv, - int idx, bool is_fe) -{ - struct device *dev = rsrc_priv_to_dev(priv); - struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); - struct asoc_simple_dai *dai_props = rsrc_priv_to_props(priv, idx); - int ret; - - ret = rsrc_card_parse_links(np, priv, idx, is_fe); - if (ret < 0) - return ret; - - ret = rsrc_card_parse_clk(np, priv, idx, is_fe); - if (ret < 0) - return ret; - dev_dbg(dev, "\t%s / %04x / %d\n", dai_link->name, dai_link->dai_fmt, dai_props->sysclk); - return ret; + return 0; } static int rsrc_card_dai_link_of(struct device_node *node, @@ -348,7 +300,7 @@ static int rsrc_card_dai_link_of(struct device_node *node, if (strcmp(np->name, "cpu") == 0) is_fe = true; - ret = rsrc_card_dai_sub_link_of(node, np, priv, i, is_fe); + ret = rsrc_card_parse_links(np, priv, i, is_fe); if (ret < 0) return ret; i++; -- cgit v0.10.2 From bb6fc620c2ed972f58a0174f64f8dbd22a5911b1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 05:59:56 +0000 Subject: ASoC: simple-card-utils: add asoc_simple_card_parse_clk() Current simple-card can get clock via DT clocks or "system-clock-frequency" property. This patch makes it simple style standard Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 86088ae..1392eb5 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -33,4 +33,12 @@ int asoc_simple_card_set_dailink_name(struct device *dev, int asoc_simple_card_parse_card_name(struct snd_soc_card *card, char *prefix); +#define asoc_simple_card_parse_clk_cpu(node, dai_link, simple_dai) \ + asoc_simple_card_parse_clk(node, dai_link->cpu_of_node, simple_dai) +#define asoc_simple_card_parse_clk_codec(node, dai_link, simple_dai) \ + asoc_simple_card_parse_clk(node, dai_link->codec_of_node, simple_dai) +int asoc_simple_card_parse_clk(struct device_node *node, + struct device_node *dai_of_node, + struct asoc_simple_dai *simple_dai); + #endif /* __SIMPLE_CARD_CORE_H */ diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 9599de6..16f65f9 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -7,6 +7,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -97,6 +98,35 @@ int asoc_simple_card_parse_card_name(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name); +int asoc_simple_card_parse_clk(struct device_node *node, + struct device_node *dai_of_node, + struct asoc_simple_dai *simple_dai) +{ + struct clk *clk; + u32 val; + + /* + * Parse dai->sysclk come from "clocks = <&xxx>" + * (if system has common clock) + * or "system-clock-frequency = " + * or device's module clock. + */ + clk = of_clk_get(node, 0); + if (!IS_ERR(clk)) { + simple_dai->sysclk = clk_get_rate(clk); + simple_dai->clk = clk; + } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { + simple_dai->sysclk = val; + } else { + clk = of_clk_get(dai_of_node, 0); + if (!IS_ERR(clk)) + simple_dai->sysclk = clk_get_rate(clk); + } + + return 0; +} +EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk); + /* Module information */ MODULE_AUTHOR("Kuninori Morimoto "); MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); -- cgit v0.10.2 From ae30a694da4c37b4d0c8b750c9a4104d8da749b3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 06:01:43 +0000 Subject: ASoC: simple-card-utils: add asoc_simple_card_parse_dai() simple-card needs to get its dai name and endpoint node. This patch makes it simple style standard Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 1392eb5..62b3926 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -41,4 +41,21 @@ int asoc_simple_card_parse_clk(struct device_node *node, struct device_node *dai_of_node, struct asoc_simple_dai *simple_dai); +#define asoc_simple_card_parse_cpu(node, dai_link, \ + list_name, cells_name, is_single_link) \ + asoc_simple_card_parse_dai(node, &dai_link->cpu_of_node, \ + &dai_link->cpu_dai_name, list_name, cells_name, is_single_link) +#define asoc_simple_card_parse_codec(node, dai_link, list_name, cells_name) \ + asoc_simple_card_parse_dai(node, &dai_link->codec_of_node, \ + &dai_link->codec_dai_name, list_name, cells_name, NULL) +#define asoc_simple_card_parse_platform(node, dai_link, list_name, cells_name) \ + asoc_simple_card_parse_dai(node, &dai_link->platform_of_node, \ + NULL, list_name, cells_name, NULL) +int asoc_simple_card_parse_dai(struct device_node *node, + struct device_node **endpoint_np, + const char **dai_name, + const char *list_name, + const char *cells_name, + int *is_single_links); + #endif /* __SIMPLE_CARD_CORE_H */ diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 16f65f9..27e6d03 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -127,6 +127,43 @@ int asoc_simple_card_parse_clk(struct device_node *node, } EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk); +int asoc_simple_card_parse_dai(struct device_node *node, + struct device_node **dai_of_node, + const char **dai_name, + const char *list_name, + const char *cells_name, + int *is_single_link) +{ + struct of_phandle_args args; + int ret; + + if (!node) + return 0; + + /* + * Get node via "sound-dai = <&phandle port>" + * it will be used as xxx_of_node on soc_bind_dai_link() + */ + ret = of_parse_phandle_with_args(node, list_name, cells_name, 0, &args); + if (ret) + return ret; + + /* Get dai->name */ + if (dai_name) { + ret = snd_soc_of_get_dai_name(node, dai_name); + if (ret < 0) + return ret; + } + + *dai_of_node = args.np; + + if (is_single_link) + *is_single_link = !args.args_count; + + return 0; +} +EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai); + /* Module information */ MODULE_AUTHOR("Kuninori Morimoto "); MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); -- cgit v0.10.2 From 44c16af1fa8a5b1464fd76834ee6943f721748fa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 06:02:07 +0000 Subject: ASoC: simple-card: use asoc_simple_card_parse_dai() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index b37c81b..05d6e02 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -44,6 +44,8 @@ struct simple_card_data { #define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i) #define simple_priv_to_props(priv, i) ((priv)->dai_props + i) +#define DAI "sound-dai" +#define CELL "#sound-dai-cells" #define PREFIX "simple-audio-card," #define asoc_simple_card_init_hp(card, sjack, prefix)\ @@ -243,33 +245,11 @@ asoc_simple_card_sub_parse_of(struct device_node *np, const char **name, int *args_count) { - struct of_phandle_args args; int ret; if (!np) return 0; - /* - * Get node via "sound-dai = <&phandle port>" - * it will be used as xxx_of_node on soc_bind_dai_link() - */ - ret = of_parse_phandle_with_args(np, "sound-dai", - "#sound-dai-cells", 0, &args); - if (ret) - return ret; - - *p_node = args.np; - - if (args_count) - *args_count = args.args_count; - - /* Get dai->name */ - if (name) { - ret = snd_soc_of_get_dai_name(np, name); - if (ret < 0) - return ret; - } - if (!dai) return 0; @@ -298,7 +278,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, struct device_node *codec = NULL; char prop[128]; char *prefix = ""; - int ret, cpu_args; + int ret, single_cpu; u32 val; /* For single DAI link & old style of DT node */ @@ -328,10 +308,23 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, if (!of_property_read_u32(node, "mclk-fs", &val)) dai_props->mclk_fs = val; + ret = asoc_simple_card_parse_cpu(cpu, dai_link, + DAI, CELL, &single_cpu); + if (ret < 0) + goto dai_link_of_err; + + ret = asoc_simple_card_parse_codec(codec, dai_link, DAI, CELL); + if (ret < 0) + goto dai_link_of_err; + + ret = asoc_simple_card_parse_platform(plat, dai_link, DAI, CELL); + if (ret < 0) + goto dai_link_of_err; + ret = asoc_simple_card_sub_parse_of(cpu, &dai_props->cpu_dai, &dai_link->cpu_of_node, &dai_link->cpu_dai_name, - &cpu_args); + &single_cpu); if (ret < 0) goto dai_link_of_err; @@ -392,7 +385,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, * fmt_single_name() * fmt_multiple_name() */ - if (!cpu_args) + if (single_cpu) dai_link->cpu_dai_name = NULL; dai_link_of_err: -- cgit v0.10.2 From 5bbf3866cbc1da23c628ad5dd7248cca8b8adc2c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 06:02:31 +0000 Subject: ASoC: rsrc-card: use asoc_simple_card_parse_dai() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index ed5391f..82187e0 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -62,6 +62,9 @@ struct rsrc_card_priv { #define rsrc_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i)) #define rsrc_priv_to_props(priv, i) ((priv)->dai_props + (i)) +#define DAI "sound-dai" +#define CELL "#sound-dai-cells" + static int rsrc_card_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -155,18 +158,9 @@ static int rsrc_card_parse_links(struct device_node *np, struct device *dev = rsrc_priv_to_dev(priv); struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); struct asoc_simple_dai *dai_props = rsrc_priv_to_props(priv, idx); - struct of_phandle_args args; + int is_single_links = 0; int ret; - /* - * Get node via "sound-dai = <&phandle port>" - * it will be used as xxx_of_node on soc_bind_dai_link() - */ - ret = of_parse_phandle_with_args(np, "sound-dai", - "#sound-dai-cells", 0, &args); - if (ret) - return ret; - /* Parse TDM slot */ ret = snd_soc_of_parse_tdm_slot(np, &dai_props->tx_slot_mask, @@ -185,9 +179,10 @@ static int rsrc_card_parse_links(struct device_node *np, /* FE settings */ dai_link->dynamic = 1; dai_link->dpcm_merged_format = 1; - dai_link->cpu_of_node = args.np; - ret = snd_soc_of_get_dai_name(np, &dai_link->cpu_dai_name); - if (ret < 0) + + ret = asoc_simple_card_parse_cpu(np, dai_link, DAI, CELL, + &is_single_links); + if (ret) return ret; ret = asoc_simple_card_parse_clk_cpu(np, dai_link, dai_props); @@ -209,7 +204,7 @@ static int rsrc_card_parse_links(struct device_node *np, * fmt_single_name() * fmt_multiple_name() */ - if (!args.args_count) + if (is_single_links) dai_link->cpu_dai_name = NULL; } else { const struct rsrc_card_of_data *of_data; @@ -224,8 +219,8 @@ static int rsrc_card_parse_links(struct device_node *np, /* BE settings */ dai_link->no_pcm = 1; dai_link->be_hw_params_fixup = rsrc_card_be_hw_params_fixup; - dai_link->codec_of_node = args.np; - ret = snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name); + + ret = asoc_simple_card_parse_codec(np, dai_link, DAI, CELL); if (ret < 0) return ret; -- cgit v0.10.2 From c3b19c8dd069894961d0616aa3706df2920e7be4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 06:03:35 +0000 Subject: ASoC: simple-card: remove asoc_simple_card_sub_parse_of() asoc_simple_card_sub_parse_of() is no longer needed. Let's cleanup Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 05d6e02..99028c1 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -238,31 +238,6 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) return 0; } -static int -asoc_simple_card_sub_parse_of(struct device_node *np, - struct asoc_simple_dai *dai, - struct device_node **p_node, - const char **name, - int *args_count) -{ - int ret; - - if (!np) - return 0; - - if (!dai) - return 0; - - /* Parse TDM slot */ - ret = snd_soc_of_parse_tdm_slot(np, &dai->tx_slot_mask, - &dai->rx_slot_mask, - &dai->slots, &dai->slot_width); - if (ret) - return ret; - - return 0; -} - static int asoc_simple_card_dai_link_of(struct device_node *node, struct simple_card_data *priv, int idx, @@ -321,22 +296,17 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_card_sub_parse_of(cpu, &dai_props->cpu_dai, - &dai_link->cpu_of_node, - &dai_link->cpu_dai_name, - &single_cpu); - if (ret < 0) - goto dai_link_of_err; - - ret = asoc_simple_card_sub_parse_of(codec, &dai_props->codec_dai, - &dai_link->codec_of_node, - &dai_link->codec_dai_name, NULL); + ret = snd_soc_of_parse_tdm_slot(cpu, &cpu_dai->tx_slot_mask, + &cpu_dai->rx_slot_mask, + &cpu_dai->slots, + &cpu_dai->slot_width); if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_card_sub_parse_of(plat, NULL, - &dai_link->platform_of_node, - NULL, NULL); + ret = snd_soc_of_parse_tdm_slot(codec, &codec_dai->tx_slot_mask, + &codec_dai->rx_slot_mask, + &codec_dai->slots, + &codec_dai->slot_width); if (ret < 0) goto dai_link_of_err; -- cgit v0.10.2 From 3597fced666469762c8ea64a68f2ce0716776bd8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 2 Aug 2016 13:48:31 +0800 Subject: ASoC: cs53l30: Constify cs53l30_mclk_coeffs and cs53l30_mclkx_coeffs tables Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index 2c0d9c4..936caf1 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -466,7 +466,7 @@ struct cs53l30_mclk_div { u8 mclk_int_scale; }; -static struct cs53l30_mclk_div cs53l30_mclk_coeffs[] = { +static const struct cs53l30_mclk_div cs53l30_mclk_coeffs[] = { /* NOTE: Enable MCLK_INT_SCALE to save power. */ /* MCLK, Sample Rate, asp_rate, internal_fs_ratio, mclk_int_scale */ @@ -511,7 +511,7 @@ struct cs53l30_mclkx_div { u8 mclkdiv; }; -static struct cs53l30_mclkx_div cs53l30_mclkx_coeffs[] = { +static const struct cs53l30_mclkx_div cs53l30_mclkx_coeffs[] = { {5644800, 1, CS53L30_MCLK_DIV_BY_1}, {6000000, 1, CS53L30_MCLK_DIV_BY_1}, {6144000, 1, CS53L30_MCLK_DIV_BY_1}, -- cgit v0.10.2 From 6e8e9b9a46cf75a0994864a8fcbead4a580af310 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 2 Aug 2016 13:48:31 +0800 Subject: ASoC: cs53l30: Constify cs53l30_mclk_coeffs and cs53l30_mclkx_coeffs tables Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index 2c0d9c4..936caf1 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -466,7 +466,7 @@ struct cs53l30_mclk_div { u8 mclk_int_scale; }; -static struct cs53l30_mclk_div cs53l30_mclk_coeffs[] = { +static const struct cs53l30_mclk_div cs53l30_mclk_coeffs[] = { /* NOTE: Enable MCLK_INT_SCALE to save power. */ /* MCLK, Sample Rate, asp_rate, internal_fs_ratio, mclk_int_scale */ @@ -511,7 +511,7 @@ struct cs53l30_mclkx_div { u8 mclkdiv; }; -static struct cs53l30_mclkx_div cs53l30_mclkx_coeffs[] = { +static const struct cs53l30_mclkx_div cs53l30_mclkx_coeffs[] = { {5644800, 1, CS53L30_MCLK_DIV_BY_1}, {6000000, 1, CS53L30_MCLK_DIV_BY_1}, {6144000, 1, CS53L30_MCLK_DIV_BY_1}, -- cgit v0.10.2 From e094e8f3de9caee07b316324f66696f8a5af4a22 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 2 Aug 2016 13:48:30 +0800 Subject: ASoC: cs42l73: Constify cs42l73_mclk_coeffs and cs42l73_mclkx_coeffs tables Signed-off-by: Axel Lin Acked-by: Brian Austin Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 42a8fd4..8524e22 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -794,7 +794,7 @@ struct cs42l73_mclk_div { u8 mmcc; }; -static struct cs42l73_mclk_div cs42l73_mclk_coeffs[] = { +static const struct cs42l73_mclk_div cs42l73_mclk_coeffs[] = { /* MCLK, Sample Rate, xMMCC[5:0] */ {5644800, 11025, 0x30}, {5644800, 22050, 0x20}, @@ -844,7 +844,7 @@ struct cs42l73_mclkx_div { u8 mclkdiv; }; -static struct cs42l73_mclkx_div cs42l73_mclkx_coeffs[] = { +static const struct cs42l73_mclkx_div cs42l73_mclkx_coeffs[] = { {5644800, 1, 0}, /* 5644800 */ {6000000, 1, 0}, /* 6000000 */ {6144000, 1, 0}, /* 6144000 */ -- cgit v0.10.2 From 4d48298af85aff3dcc9498a564e06efeb9c935be Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 28 Jul 2016 15:43:01 -0700 Subject: ASoC: cs53l30: Do not ignore errors if mclk is specified When the clock is specified, there could be other errors besides the EPROBE_DEFER so don't ignore them. Signed-off-by: Nicolin Chen Acked-by: Paul Handrigan Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index 2c0d9c4..227c556 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -999,8 +999,8 @@ static int cs53l30_i2c_probe(struct i2c_client *client, /* Check if MCLK provided */ cs53l30->mclk = devm_clk_get(dev, "mclk"); if (IS_ERR(cs53l30->mclk)) { - if (PTR_ERR(cs53l30->mclk) == -EPROBE_DEFER) { - ret = -EPROBE_DEFER; + if (PTR_ERR(cs53l30->mclk) != -ENOENT) { + ret = PTR_ERR(cs53l30->mclk); goto error; } /* Otherwise mark the mclk pointer to NULL */ -- cgit v0.10.2 From f612680fb5cd92a213240d82651a1f56bc38129e Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Thu, 4 Aug 2016 15:35:39 +0100 Subject: ASoC: da7213: Improve driver efficiency with regards to MCLK usage Currently MCLK remains enabled during bias STANDBY state, and this is not necessary. This patch updates the code to handle enabling and disabling of MCLK, if provided, when moving between STANDBY and PREPARE states, therefore saving power when no active streams present. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index e5527bc..f1c41fa 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1454,11 +1454,10 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: break; - case SND_SOC_BIAS_STANDBY: - if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { - /* MCLK */ + case SND_SOC_BIAS_PREPARE: + /* Enable MCLK for transition to ON state */ + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { if (da7213->mclk) { ret = clk_prepare_enable(da7213->mclk); if (ret) { @@ -1467,21 +1466,24 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, return ret; } } - + } + break; + case SND_SOC_BIAS_STANDBY: + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { /* Enable VMID reference & master bias */ snd_soc_update_bits(codec, DA7213_REFERENCES, DA7213_VMID_EN | DA7213_BIAS_EN, DA7213_VMID_EN | DA7213_BIAS_EN); + } else { + /* Remove MCLK */ + if (da7213->mclk) + clk_disable_unprepare(da7213->mclk); } break; case SND_SOC_BIAS_OFF: /* Disable VMID reference & master bias */ snd_soc_update_bits(codec, DA7213_REFERENCES, DA7213_VMID_EN | DA7213_BIAS_EN, 0); - - /* MCLK */ - if (da7213->mclk) - clk_disable_unprepare(da7213->mclk); break; } return 0; -- cgit v0.10.2 From 4c75225aa05753217a81ed10f136b86fb94c5922 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Thu, 4 Aug 2016 15:35:40 +0100 Subject: ASoC: da7213: Refactor sysclk(), pll() functions to improve handling Currently the handling of the PLL in the driver is a little clunky, and not ideal for all modes. This patch updates the code to make it cleaner and more sensible for the various PLL states. Key items of note are: - MCLK squaring is now handled directly as part of the sysclk() function, removing the need for a private flag to set this feature. - All PLL modes are defined as an enum, and are handled as a case statement in pll() function to clean up configuration. This also removes any need for a private flag for SRM. - For 32KHz mode, checks are made on codec master mode and correct MCLK rates, to avoid incorrect usage of PLL for this operation. - For 32KHz mode, SRM flag now correctly enabled and fout set to sensible value to achieve appropriate PLL dividers. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index f1c41fa..94550d4 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1297,10 +1297,13 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai, switch (clk_id) { case DA7213_CLKSRC_MCLK: - da7213->mclk_squarer_en = false; + snd_soc_update_bits(codec, DA7213_PLL_CTRL, + DA7213_PLL_MCLK_SQR_EN, 0); break; case DA7213_CLKSRC_MCLK_SQR: - da7213->mclk_squarer_en = true; + snd_soc_update_bits(codec, DA7213_PLL_CTRL, + DA7213_PLL_MCLK_SQR_EN, + DA7213_PLL_MCLK_SQR_EN); break; default: dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id); @@ -1324,7 +1327,7 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai, return 0; } -/* Supported PLL input frequencies are 5MHz - 54MHz. */ +/* Supported PLL input frequencies are 32KHz, 5MHz - 54MHz. */ static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, int source, unsigned int fref, unsigned int fout) { @@ -1336,22 +1339,26 @@ static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, u32 freq_ref; u64 frac_div; - /* Reset PLL configuration */ - snd_soc_write(codec, DA7213_PLL_CTRL, 0); - - pll_ctrl = 0; - /* Workout input divider based on MCLK rate */ if (da7213->mclk_rate == 32768) { + if (!da7213->master) { + dev_err(codec->dev, + "32KHz only valid if codec is clock master\n"); + return -EINVAL; + } + /* 32KHz PLL Mode */ indiv_bits = DA7213_PLL_INDIV_9_TO_18_MHZ; indiv = DA7213_PLL_INDIV_9_TO_18_MHZ_VAL; + source = DA7213_SYSCLK_PLL_32KHZ; freq_ref = 3750000; - pll_ctrl |= DA7213_PLL_32K_MODE; + } else { - /* 5 - 54MHz MCLK */ if (da7213->mclk_rate < 5000000) { - goto pll_err; + dev_err(codec->dev, + "PLL input clock %d below valid range\n", + da7213->mclk_rate); + return -EINVAL; } else if (da7213->mclk_rate <= 9000000) { indiv_bits = DA7213_PLL_INDIV_5_TO_9_MHZ; indiv = DA7213_PLL_INDIV_5_TO_9_MHZ_VAL; @@ -1365,32 +1372,44 @@ static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, indiv_bits = DA7213_PLL_INDIV_36_TO_54_MHZ; indiv = DA7213_PLL_INDIV_36_TO_54_MHZ_VAL; } else { - goto pll_err; + dev_err(codec->dev, + "PLL input clock %d above valid range\n", + da7213->mclk_rate); + return -EINVAL; } freq_ref = (da7213->mclk_rate / indiv); } - pll_ctrl |= indiv_bits; + pll_ctrl = indiv_bits; - /* PLL Bypass mode */ - if (source == DA7213_SYSCLK_MCLK) { - snd_soc_write(codec, DA7213_PLL_CTRL, pll_ctrl); + /* Configure PLL */ + switch (source) { + case DA7213_SYSCLK_MCLK: + snd_soc_update_bits(codec, DA7213_PLL_CTRL, + DA7213_PLL_INDIV_MASK | + DA7213_PLL_MODE_MASK, pll_ctrl); return 0; - } + case DA7213_SYSCLK_PLL: + break; + case DA7213_SYSCLK_PLL_SRM: + pll_ctrl |= DA7213_PLL_SRM_EN; + fout = DA7213_PLL_FREQ_OUT_94310400; + break; + case DA7213_SYSCLK_PLL_32KHZ: + if (da7213->mclk_rate != 32768) { + dev_err(codec->dev, + "32KHz mode only valid with 32KHz MCLK\n"); + return -EINVAL; + } - /* - * If Codec is slave and SRM enabled, - * freq_out is (98304000 + 90316800)/2 = 94310400 - */ - if (!da7213->master && da7213->srm_en) { + pll_ctrl |= DA7213_PLL_32K_MODE | DA7213_PLL_SRM_EN; fout = DA7213_PLL_FREQ_OUT_94310400; - pll_ctrl |= DA7213_PLL_SRM_EN; + break; + default: + dev_err(codec->dev, "Invalid PLL config\n"); + return -EINVAL; } - /* Enable MCLK squarer if required */ - if (da7213->mclk_squarer_en) - pll_ctrl |= DA7213_PLL_MCLK_SQR_EN; - /* Calculate dividers for PLL */ pll_integer = fout / freq_ref; frac_div = (u64)(fout % freq_ref) * 8192ULL; @@ -1405,14 +1424,11 @@ static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, /* Enable PLL */ pll_ctrl |= DA7213_PLL_EN; - snd_soc_write(codec, DA7213_PLL_CTRL, pll_ctrl); + snd_soc_update_bits(codec, DA7213_PLL_CTRL, + DA7213_PLL_INDIV_MASK | DA7213_PLL_MODE_MASK, + pll_ctrl); return 0; - -pll_err: - dev_err(codec_dai->dev, "Unsupported PLL input frequency %d\n", - da7213->mclk_rate); - return -EINVAL; } /* DAI operations */ @@ -1607,9 +1623,6 @@ static int da7213_probe(struct snd_soc_codec *codec) DA7213_ALC_CALIB_MODE_MAN, 0); da7213->alc_calib_auto = true; - /* Default to using SRM for slave mode */ - da7213->srm_en = true; - /* Default PC counter to free-running */ snd_soc_update_bits(codec, DA7213_PC_COUNT, DA7213_PC_FREERUN_MASK, DA7213_PC_FREERUN_MASK); diff --git a/sound/soc/codecs/da7213.h b/sound/soc/codecs/da7213.h index fbb7a35..16ef56f 100644 --- a/sound/soc/codecs/da7213.h +++ b/sound/soc/codecs/da7213.h @@ -172,6 +172,7 @@ #define DA7213_PLL_32K_MODE (0x1 << 5) #define DA7213_PLL_SRM_EN (0x1 << 6) #define DA7213_PLL_EN (0x1 << 7) +#define DA7213_PLL_MODE_MASK (0x7 << 5) /* DA7213_DAI_CLK_MODE = 0x28 */ #define DA7213_DAI_BCLKS_PER_WCLK_32 (0x0 << 0) @@ -499,8 +500,6 @@ #define DA7213_ALC_AVG_ITERATIONS 5 /* PLL related */ -#define DA7213_SYSCLK_MCLK 0 -#define DA7213_SYSCLK_PLL 1 #define DA7213_PLL_FREQ_OUT_90316800 90316800 #define DA7213_PLL_FREQ_OUT_98304000 98304000 #define DA7213_PLL_FREQ_OUT_94310400 94310400 @@ -515,6 +514,13 @@ enum da7213_clk_src { DA7213_CLKSRC_MCLK_SQR, }; +enum da7213_sys_clk { + DA7213_SYSCLK_MCLK = 0, + DA7213_SYSCLK_PLL, + DA7213_SYSCLK_PLL_SRM, + DA7213_SYSCLK_PLL_32KHZ +}; + /* Codec private data */ struct da7213_priv { struct regmap *regmap; @@ -522,8 +528,6 @@ struct da7213_priv { unsigned int mclk_rate; int clk_src; bool master; - bool mclk_squarer_en; - bool srm_en; bool alc_calib_auto; bool alc_en; struct da7213_platform_data *pdata; -- cgit v0.10.2 From d936d527d241b606b0280034b3972b7825d3704c Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Thu, 4 Aug 2016 15:35:41 +0100 Subject: ASoC: da7213: Improve 32KHz mode PLL locking To aid PLL in locking on to a 32KHz MCLK, some register mods are made during PLL configuration, and when enabling the DAI, to achieve the full range of sample rates. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 94550d4..f756220 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -750,11 +750,18 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, DA7213_PC_COUNT, DA7213_PC_FREERUN_MASK, 0); - /* Slave mode, if SRM not enabled no need for status checks */ + /* If SRM not enabled then nothing more to do */ pll_ctrl = snd_soc_read(codec, DA7213_PLL_CTRL); if (!(pll_ctrl & DA7213_PLL_SRM_EN)) return 0; + /* Assist 32KHz mode PLL lock */ + if (pll_ctrl & DA7213_PLL_32K_MODE) { + snd_soc_write(codec, 0xF0, 0x8B); + snd_soc_write(codec, 0xF2, 0x03); + snd_soc_write(codec, 0xF0, 0x00); + } + /* Check SRM has locked */ do { pll_status = snd_soc_read(codec, DA7213_PLL_STATUS); @@ -771,6 +778,14 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w, return 0; case SND_SOC_DAPM_POST_PMD: + /* Revert 32KHz PLL lock udpates if applied previously */ + pll_ctrl = snd_soc_read(codec, DA7213_PLL_CTRL); + if (pll_ctrl & DA7213_PLL_32K_MODE) { + snd_soc_write(codec, 0xF0, 0x8B); + snd_soc_write(codec, 0xF2, 0x01); + snd_soc_write(codec, 0xF0, 0x00); + } + /* PC free-running */ snd_soc_update_bits(codec, DA7213_PC_COUNT, DA7213_PC_FREERUN_MASK, @@ -1428,6 +1443,14 @@ static int da7213_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, DA7213_PLL_INDIV_MASK | DA7213_PLL_MODE_MASK, pll_ctrl); + /* Assist 32KHz mode PLL lock */ + if (source == DA7213_SYSCLK_PLL_32KHZ) { + snd_soc_write(codec, 0xF0, 0x8B); + snd_soc_write(codec, 0xF1, 0x03); + snd_soc_write(codec, 0xF1, 0x01); + snd_soc_write(codec, 0xF0, 0x00); + } + return 0; } -- cgit v0.10.2 From 40585391fc88d6d66dc479efccba973426c004ab Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Fri, 29 Jul 2016 14:46:54 +0100 Subject: ASoC: da7219: Make more efficient use of MCLK within driver Currently, if the driver has control of MCLK then it remains enabled as long as the codec is in STANDBY or above. The MCLK is only really required in STANDBY when a 3-pole jack is inserted and the HP detect procedure is required to run. This patch updates the code to enable/disable the MCLK when moving between the STANDBY and PREPARE bias level, and when a 3-pole jack is inserted and HP detection is required, thus saving power at all other times. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index f0057cd..4e369a1 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -115,12 +116,23 @@ static void da7219_aad_hptest_work(struct work_struct *work) u16 tonegen_freq_hptest; u8 accdet_cfg8; - int report = 0; + int report = 0, ret = 0; /* Lock DAPM and any Kcontrols that are affected by this test */ snd_soc_dapm_mutex_lock(dapm); mutex_lock(&da7219->lock); + /* Ensure MCLK is available for HP test procedure */ + if (da7219->mclk) { + ret = clk_prepare_enable(da7219->mclk); + if (ret) { + dev_err(codec->dev, "Failed to enable mclk - %d\n", ret); + mutex_unlock(&da7219->lock); + snd_soc_dapm_mutex_unlock(dapm); + return; + } + } + /* Bypass cache so it saves current settings */ regcache_cache_bypass(da7219->regmap, true); @@ -250,6 +262,10 @@ static void da7219_aad_hptest_work(struct work_struct *work) snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK, DA7219_HP_R_AMP_OE_MASK); + /* Remove MCLK, if previously enabled */ + if (da7219->mclk) + clk_disable_unprepare(da7219->mclk); + mutex_unlock(&da7219->lock); snd_soc_dapm_mutex_unlock(dapm); diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 50ea943..737e914 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1508,11 +1508,10 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: break; - case SND_SOC_BIAS_STANDBY: - if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { - /* MCLK */ + case SND_SOC_BIAS_PREPARE: + /* Enable MCLK for transition to ON state */ + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { if (da7219->mclk) { ret = clk_prepare_enable(da7219->mclk); if (ret) { @@ -1521,11 +1520,19 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, return ret; } } + } + break; + case SND_SOC_BIAS_STANDBY: + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { /* Master bias */ snd_soc_update_bits(codec, DA7219_REFERENCES, DA7219_BIAS_EN_MASK, DA7219_BIAS_EN_MASK); + } else { + /* Remove MCLK */ + if (da7219->mclk) + clk_disable_unprepare(da7219->mclk); } break; case SND_SOC_BIAS_OFF: @@ -1534,9 +1541,6 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, snd_soc_update_bits(codec, DA7219_REFERENCES, DA7219_BIAS_EN_MASK, 0); - /* MCLK */ - if (da7219->mclk) - clk_disable_unprepare(da7219->mclk); break; } -- cgit v0.10.2 From 35397edeb14f033e51296400ff31d159dbb8444a Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 12:22:32 +0200 Subject: ASoC: dwc: Drop DMA channel names assignment The dw_configure_dai_by_dt() function and further dev->{play,capture} _dma_data.dt data structures seem to be used in this driver only in case of a system using devicetree, thus chan_name assignments have no effect since they will be ignored in dmaengine_pcm_request_chan_of() call and will be substituted with values taken form dmaengine_pcm_dma_channel_names[] table ("tx", "rx"). Also there is no any "TX", "RX" dma-names entries in arch/arm/boot/dts, only lower case "tx", "rx" seem to be used. Lastly, this driver doesn't set SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME flag when registering a dmaengine PCM to indicate the chan_name should be used. My intention is to eventually remove the struct snd_dmaengine_dai_dma_data chan_name field as there is also a chan_names[] field in struct snd_dmaengine_pcm_config which can be used for same purpose. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c index dc97f43..2998954 100644 --- a/sound/soc/dwc/designware_i2s.c +++ b/sound/soc/dwc/designware_i2s.c @@ -577,7 +577,6 @@ static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev, dev->capability |= DWC_I2S_PLAY; dev->play_dma_data.dt.addr = res->start + I2S_TXDMA; dev->play_dma_data.dt.addr_width = bus_widths[idx]; - dev->play_dma_data.dt.chan_name = "TX"; dev->play_dma_data.dt.fifo_size = fifo_depth * (fifo_width[idx2]) >> 8; dev->play_dma_data.dt.maxburst = 16; @@ -588,7 +587,6 @@ static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev, dev->capability |= DWC_I2S_RECORD; dev->capture_dma_data.dt.addr = res->start + I2S_RXDMA; dev->capture_dma_data.dt.addr_width = bus_widths[idx]; - dev->capture_dma_data.dt.chan_name = "RX"; dev->capture_dma_data.dt.fifo_size = fifo_depth * (fifo_width[idx2] >> 8); dev->capture_dma_data.dt.maxburst = 16; -- cgit v0.10.2 From 9731f82d60166a19af6914f998092bbd1560f783 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 3 Aug 2016 02:08:41 +0000 Subject: ASoC: hdmi-codec: enable multi probe for same device hdmi-codec driver is common HDMI sound driver, but it doesn't care about multi sound ports. For example, hdmi-codec driver is supporting 1 I2S and 1 SPDIF ports, so, we can't use this driver if HDMI has 2 or more I2S ports. And we would like to use multi detection. For example, DesignWare HDMI driver is providing dw_hdmi_bind() to DRM/KMS driver, and it will setups HDMI video/sound. Note is that it will be called under for_each loop of ports. int dw_hdmi_bind(xxx) { /* register hdmi-codec driver here */ } static int xxx_probe(struct platform_device *pdev) { for_each_xxx(xx) { ... dw_hdmi_bind(xxx); ... } } This case, dw_hdmi_bind() would like to use hdmi-codec, and it will be called multiple times for each ports. Here, ASoC's CPU/Codec/Card bind will checks each "of_node" on DT, and hdmi-codec driver is assuming its parent device for it. But it doesn't care about case. Thus, ASoC never detect correct sound card in this case. To solve this issue, this patch checks each parent device, and names "hdmi-hifi.x" in order to each ports. And uses struct snd_soc_component_driver :: of_xlate_dai_name for snd_soc_get_dai_name(). Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index f27d115..f64ecaa 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -24,6 +24,15 @@ #include /* This is only to get MAX_ELD_BYTES */ +struct hdmi_device { + struct device *dev; + struct list_head list; + int cnt; +}; +#define pos_to_hdmi_device(pos) container_of((pos), struct hdmi_device, list) +LIST_HEAD(hdmi_device_list); + +#define DAI_NAME_SIZE 16 struct hdmi_codec_priv { struct hdmi_codec_pdata hcd; struct snd_soc_dai_driver *daidrv; @@ -320,7 +329,6 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = { SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) static struct snd_soc_dai_driver hdmi_i2s_dai = { - .name = "i2s-hifi", .id = DAI_ID_I2S, .playback = { .stream_name = "Playback", @@ -334,7 +342,6 @@ static struct snd_soc_dai_driver hdmi_i2s_dai = { }; static const struct snd_soc_dai_driver hdmi_spdif_dai = { - .name = "spdif-hifi", .id = DAI_ID_SPDIF, .playback = { .stream_name = "Playback", @@ -346,6 +353,27 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = { .ops = &hdmi_dai_ops, }; +static char hdmi_dai_name[][DAI_NAME_SIZE] = { + "hdmi-hifi.0", + "hdmi-hifi.1", + "hdmi-hifi.2", + "hdmi-hifi.3", +}; + +static int hdmi_of_xlate_dai_name(struct snd_soc_component *component, + struct of_phandle_args *args, + const char **dai_name) +{ + int id = args->args[0]; + + if (id < ARRAY_SIZE(hdmi_dai_name)) { + *dai_name = hdmi_dai_name[id]; + return 0; + } + + return -EAGAIN; +} + static struct snd_soc_codec_driver hdmi_codec = { .controls = hdmi_controls, .num_controls = ARRAY_SIZE(hdmi_controls), @@ -353,6 +381,9 @@ static struct snd_soc_codec_driver hdmi_codec = { .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), .dapm_routes = hdmi_routes, .num_dapm_routes = ARRAY_SIZE(hdmi_routes), + .component_driver = { + .of_xlate_dai_name = hdmi_of_xlate_dai_name, + }, }; static int hdmi_codec_probe(struct platform_device *pdev) @@ -360,6 +391,8 @@ static int hdmi_codec_probe(struct platform_device *pdev) struct hdmi_codec_pdata *hcd = pdev->dev.platform_data; struct device *dev = &pdev->dev; struct hdmi_codec_priv *hcp; + struct hdmi_device *hd; + struct list_head *pos; int dai_count, i = 0; int ret; @@ -381,6 +414,31 @@ static int hdmi_codec_probe(struct platform_device *pdev) if (!hcp) return -ENOMEM; + hd = NULL; + list_for_each(pos, &hdmi_device_list) { + struct hdmi_device *tmp = pos_to_hdmi_device(pos); + + if (tmp->dev == dev->parent) { + hd = tmp; + break; + } + } + + if (!hd) { + hd = devm_kzalloc(dev, sizeof(*hd), GFP_KERNEL); + if (!hd) + return -ENOMEM; + + hd->dev = dev->parent; + + list_add_tail(&hd->list, &hdmi_device_list); + } + + if (hd->cnt >= ARRAY_SIZE(hdmi_dai_name)) { + dev_err(dev, "too many hdmi codec are deteced\n"); + return -EINVAL; + } + hcp->hcd = *hcd; mutex_init(&hcp->current_stream_lock); @@ -393,11 +451,14 @@ static int hdmi_codec_probe(struct platform_device *pdev) hcp->daidrv[i] = hdmi_i2s_dai; hcp->daidrv[i].playback.channels_max = hcd->max_i2s_channels; + hcp->daidrv[i].name = hdmi_dai_name[hd->cnt++]; i++; } - if (hcd->spdif) + if (hcd->spdif) { hcp->daidrv[i] = hdmi_spdif_dai; + hcp->daidrv[i].name = hdmi_dai_name[hd->cnt++]; + } ret = snd_soc_register_codec(dev, &hdmi_codec, hcp->daidrv, dai_count); -- cgit v0.10.2 From b7c505554c11cc7978ab942b544d86dd92d59dcf Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 26 Jul 2016 18:06:40 +0530 Subject: ASoC: Intel: Skylake: Move modules query to runtime Since we are moving DSP init to later, at the topology load the module info is not available. So set the module id to -1 at init and query at first module initialization. Signed-off-by: Senthilnathan Veppur Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index cc0150f..9041030 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -473,6 +473,28 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) w = w_module->w; mconfig = w->priv; + /* check if module ids are populated */ + if (mconfig->id.module_id < 0) { + struct skl_dfw_module *dfw_config; + + dfw_config = kzalloc(sizeof(dfw_config), GFP_KERNEL); + if (!dfw_config) + return -ENOMEM; + + ret = snd_skl_get_module_info(skl->skl_sst, + mconfig->guid, dfw_config); + if (ret < 0) { + dev_err(skl->skl_sst->dev, + "query module info failed: %d\n", ret); + kfree(dfw_config); + return ret; + } + mconfig->id.module_id = dfw_config->module_id; + mconfig->is_loadable = dfw_config->is_loadable; + + kfree(dfw_config); + } + /* check resource available */ if (!skl_is_pipe_mcps_avail(skl, mconfig)) return -ENOMEM; @@ -1621,11 +1643,11 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, w->priv = mconfig; memcpy(&mconfig->guid, &dfw_config->uuid, 16); - ret = snd_skl_get_module_info(skl->skl_sst, mconfig->guid, dfw_config); - if (ret < 0) - return ret; - - mconfig->id.module_id = dfw_config->module_id; + /* + * module binary can be loaded later, so set it to query when + * module is load for a use case + */ + mconfig->id.module_id = -1; mconfig->id.instance_id = dfw_config->instance_id; mconfig->mcps = dfw_config->max_mcps; mconfig->ibs = dfw_config->ibs; diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 22d3ef8..96fa86d 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -216,7 +216,7 @@ struct skl_module_fmt { struct skl_module_cfg; struct skl_module_inst_id { - u32 module_id; + int module_id; u32 instance_id; }; -- cgit v0.10.2 From 73a675816d704337ef7e8cb441f094a82fcc1018 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 26 Jul 2016 18:06:41 +0530 Subject: ASoC: Intel: Skylake: modify skl_get_dsp_ops() To query the ops used for a platform, we use skl_get_dsp_ops() which return index and then we load the ops. Rather than this return the ops, this way it cna be used later to query the ops in rest of the driver. Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 44ab595..25d0576 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -219,16 +219,16 @@ static const struct skl_dsp_ops dsp_ops[] = { }, }; -static int skl_get_dsp_ops(int pci_id) +const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) { int i; for (i = 0; i < ARRAY_SIZE(dsp_ops); i++) { if (dsp_ops[i].id == pci_id) - return i; + return &dsp_ops[i]; } - return -EINVAL; + return NULL; } int skl_init_dsp(struct skl *skl) @@ -238,7 +238,8 @@ int skl_init_dsp(struct skl *skl) struct hdac_bus *bus = ebus_to_hbus(ebus); struct skl_dsp_loader_ops loader_ops; int irq = bus->irq; - int ret, index; + const struct skl_dsp_ops *ops; + int ret; /* enable ppcap interrupt */ snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); @@ -251,13 +252,14 @@ int skl_init_dsp(struct skl *skl) return -ENXIO; } - index = skl_get_dsp_ops(skl->pci->device); - if (index < 0) - return -EINVAL; + ops = skl_get_dsp_ops(skl->pci->device); + if (!ops) + return -EIO; - loader_ops = dsp_ops[index].loader_ops(); - ret = dsp_ops[index].init(bus->dev, mmio_base, irq, - skl->fw_name, loader_ops, &skl->skl_sst); + loader_ops = ops->loader_ops(); + ret = ops->init(bus->dev, mmio_base, irq, + skl->fw_name, loader_ops, + &skl->skl_sst); if (ret < 0) return ret; @@ -273,16 +275,16 @@ int skl_free_dsp(struct skl *skl) struct hdac_ext_bus *ebus = &skl->ebus; struct hdac_bus *bus = ebus_to_hbus(ebus); struct skl_sst *ctx = skl->skl_sst; - int index; + const struct skl_dsp_ops *ops; /* disable ppcap interrupt */ snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); - index = skl_get_dsp_ops(skl->pci->device); - if (index < 0) + ops = skl_get_dsp_ops(skl->pci->device); + if (!ops) return -EIO; - dsp_ops[index].cleanup(bus->dev, ctx); + ops->cleanup(bus->dev, ctx); if (ctx->dsp->addr.lpe) iounmap(ctx->dsp->addr.lpe); diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 9064e5b..c3538f8 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -123,4 +123,5 @@ int skl_free_dsp(struct skl *skl); int skl_suspend_dsp(struct skl *skl); int skl_resume_dsp(struct skl *skl); void skl_cleanup_resources(struct skl *skl); +const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id); #endif /* __SOUND_SOC_SKL_H */ -- cgit v0.10.2 From 78cdbbdac059fad34740f0bdefe263f8de2a1faf Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 26 Jul 2016 18:06:42 +0530 Subject: ASoC: Intel: Skylake: split fw and dsp initialization The DSP instance creation also loads the firmware on DSPs. For library load the firmware names come from topology so can't be loaded at object creation. So split the firmware load and object creation. FW load is now called after topology init in platform probe. Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 2663781..eb68258 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -397,6 +397,19 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, skl->cores.count = 2; skl->boot_complete = false; init_waitqueue_head(&skl->boot_wait); + skl->is_first_boot = true; + + if (dsp) + *dsp = skl; + + return 0; +} +EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); + +int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx) +{ + int ret; + struct sst_dsp *sst = ctx->dsp; ret = sst->fw_ops.load_fw(sst); if (ret < 0) { @@ -406,13 +419,11 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, skl_dsp_init_core_state(sst); - if (dsp) - *dsp = skl; + ctx->is_first_boot = false; return 0; } -EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); - +EXPORT_SYMBOL_GPL(bxt_sst_init_fw); void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) { diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 25d0576..2199a91 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -203,18 +203,21 @@ static const struct skl_dsp_ops dsp_ops[] = { .id = 0x9d70, .loader_ops = skl_get_loader_ops, .init = skl_sst_dsp_init, + .init_fw = skl_sst_init_fw, .cleanup = skl_sst_dsp_cleanup }, { .id = 0x9d71, .loader_ops = skl_get_loader_ops, .init = skl_sst_dsp_init, + .init_fw = skl_sst_init_fw, .cleanup = skl_sst_dsp_cleanup }, { .id = 0x5a98, .loader_ops = bxt_get_loader_ops, .init = bxt_sst_dsp_init, + .init_fw = bxt_sst_init_fw, .cleanup = bxt_sst_dsp_cleanup }, }; @@ -264,7 +267,6 @@ int skl_init_dsp(struct skl *skl) if (ret < 0) return ret; - skl_dsp_enable_notification(skl->skl_sst, false); dev_dbg(bus->dev, "dsp registration status=%d\n", ret); return ret; @@ -325,6 +327,10 @@ int skl_resume_dsp(struct skl *skl) snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, true); + /* check if DSP 1st boot is done */ + if (skl->skl_sst->is_first_boot == true) + return 0; + ret = skl_dsp_wake(ctx->dsp); if (ret < 0) return ret; diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 6e05bf8..22d4f07 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1142,8 +1142,10 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform) { struct hdac_ext_bus *ebus = dev_get_drvdata(platform->dev); struct skl *skl = ebus_to_skl(ebus); + const struct skl_dsp_ops *ops; int ret; + pm_runtime_get_sync(platform->dev); if (ebus->ppcap) { ret = skl_tplg_init(platform, ebus); if (ret < 0) { @@ -1151,7 +1153,25 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform) return ret; } skl->platform = platform; + + /* load the firmwares, since all is set */ + ops = skl_get_dsp_ops(skl->pci->device); + if (!ops) + return -EIO; + + if (skl->skl_sst->is_first_boot == false) { + dev_err(platform->dev, "DSP reports first boot done!!!\n"); + return -EIO; + } + + ret = ops->init_fw(platform->dev, skl->skl_sst); + if (ret < 0) { + dev_err(platform->dev, "Failed to boot first fw: %d\n", ret); + return ret; + } } + pm_runtime_mark_last_busy(platform->dev); + pm_runtime_put_autosuspend(platform->dev); return 0; } diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index 0f8629e..7e99468 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -203,6 +203,8 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name, struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp); +int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx); +int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx); void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index 2e3d4e8..0a0d09c 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -75,6 +75,9 @@ struct skl_sst { /* Is firmware loaded */ bool fw_loaded; + /* first boot ? */ + bool is_first_boot; + /* multi-core */ struct skl_dsp_cores cores; }; diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 588f899..6de4c02 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -484,25 +484,32 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, return ret; skl->cores.count = 2; + skl->is_first_boot = true; + + if (dsp) + *dsp = skl; + + return ret; +} +EXPORT_SYMBOL_GPL(skl_sst_dsp_init); + +int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx) +{ + int ret; + struct sst_dsp *sst = ctx->dsp; ret = sst->fw_ops.load_fw(sst); if (ret < 0) { dev_err(dev, "Load base fw failed : %d", ret); - goto cleanup; + return ret; } skl_dsp_init_core_state(sst); + ctx->is_first_boot = false; - if (dsp) - *dsp = skl; - - return ret; - -cleanup: - skl_sst_dsp_cleanup(dev, skl); - return ret; + return 0; } -EXPORT_SYMBOL_GPL(skl_sst_dsp_init); +EXPORT_SYMBOL_GPL(skl_sst_init_fw); void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) { diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index c3538f8..5d4fbb0 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -105,6 +105,7 @@ struct skl_dsp_ops { int irq, const char *fw_name, struct skl_dsp_loader_ops loader_ops, struct skl_sst **skl_sst); + int (*init_fw)(struct device *dev, struct skl_sst *ctx); void (*cleanup)(struct device *dev, struct skl_sst *ctx); }; -- cgit v0.10.2 From 15ecaba9148da2d4088c7025d06312d1cbd9d5eb Mon Sep 17 00:00:00 2001 From: Kranthi G Date: Tue, 26 Jul 2016 18:06:43 +0530 Subject: ASoC: Intel: Skylake: add support for tplg manifest load Topology manifest gives information about the libraries to be loaded. Implement the topology manifest load callback to get this. Signed-off-by: Kranthi G Signed-off-by: Senthilnathan Veppur Signed-off-by: Ramesh Babu Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index 0a0d09c..31e5bc3 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -80,6 +80,9 @@ struct skl_sst { /* multi-core */ struct skl_dsp_cores cores; + + /* tplg manifest */ + struct skl_dfw_manifest manifest; }; struct skl_ipc_init_instance_msg { diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 9041030..a1d9f84 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -1789,11 +1789,33 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, return 0; } +static int skl_manifest_load(struct snd_soc_component *cmpnt, + struct snd_soc_tplg_manifest *manifest) +{ + struct skl_dfw_manifest *minfo; + struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); + struct hdac_bus *bus = ebus_to_hbus(ebus); + struct skl *skl = ebus_to_skl(ebus); + int ret = 0; + + minfo = &skl->skl_sst->manifest; + memcpy(minfo, manifest->priv.data, sizeof(struct skl_dfw_manifest)); + + if (minfo->lib_count > HDA_MAX_LIB) { + dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", + minfo->lib_count); + ret = -EINVAL; + } + + return ret; +} + static struct snd_soc_tplg_ops skl_tplg_ops = { .widget_load = skl_tplg_widget_load, .control_load = skl_tplg_control_load, .bytes_ext_ops = skl_tlv_ops, .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), + .manifest = skl_manifest_load, }; /* diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index a32e5e9..1b531c1 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h @@ -228,4 +228,16 @@ struct skl_dfw_algo_data { char params[0]; } __packed; +#define LIB_NAME_LENGTH 128 +#define HDA_MAX_LIB 16 + +struct lib_info { + char name[LIB_NAME_LENGTH]; +} __packed; + +struct skl_dfw_manifest { + u32 lib_count; + struct lib_info lib[HDA_MAX_LIB]; +} __packed; + #endif -- cgit v0.10.2 From a8e2c19efd5d27577661124b1033b344650e4899 Mon Sep 17 00:00:00 2001 From: Senthilnathan Veppur Date: Tue, 26 Jul 2016 18:06:44 +0530 Subject: ASoC: Intel: Skylake: add additional args to module parsing For additional library parsing, we need to pass firmware to be loaded and not use the pointer in context. Also, Library module IDs are combination of library index and module ID in manifest. So add the additional arguments of firmware and library offset to snd_skl_parse_uuids(). Signed-off-by: Senthilnathan Veppur Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index eb68258..d6bf324 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -175,7 +175,7 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx) if (ctx->fw == NULL) goto sst_load_base_firmware_failed; - ret = snd_skl_parse_uuids(ctx, BXT_ADSP_FW_BIN_HDR_OFFSET); + ret = snd_skl_parse_uuids(ctx, ctx->fw, BXT_ADSP_FW_BIN_HDR_OFFSET, 0); if (ret < 0) goto sst_load_base_firmware_failed; diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index 7e99468..5bc77e1 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -210,7 +210,8 @@ void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); int snd_skl_get_module_info(struct skl_sst *ctx, u8 *uuid, struct skl_dfw_module *dfw_config); -int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int offset); +int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, + unsigned int offset, int index); void skl_freeup_uuid_list(struct skl_sst *ctx); int skl_dsp_strip_extended_manifest(struct firmware *fw); diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index 25fcb79..d94ff95 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -140,7 +140,8 @@ EXPORT_SYMBOL_GPL(snd_skl_get_module_info); * Parse the firmware binary to get the UUID, module id * and loadable flags */ -int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int offset) +int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, + unsigned int offset, int index) { struct adsp_fw_hdr *adsp_hdr; struct adsp_module_entry *mod_entry; @@ -153,8 +154,8 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int offset) unsigned int safe_file; /* Get the FW pointer to derive ADSP header */ - stripped_fw.data = ctx->fw->data; - stripped_fw.size = ctx->fw->size; + stripped_fw.data = fw->data; + stripped_fw.size = fw->size; skl_dsp_strip_extended_manifest(&stripped_fw); @@ -205,7 +206,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int offset) uuid_bin = (uuid_le *)mod_entry->uuid.id; memcpy(&module->uuid, uuid_bin, sizeof(module->uuid)); - module->id = i; + module->id = (i | (index << 12)); module->is_loadable = mod_entry->type.load_type; list_add_tail(&module->list, &skl->uuid_list); diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 6de4c02..6e9c634 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -88,7 +88,7 @@ static int skl_load_base_firmware(struct sst_dsp *ctx) } } - ret = snd_skl_parse_uuids(ctx, SKL_ADSP_FW_BIN_HDR_OFFSET); + ret = snd_skl_parse_uuids(ctx, ctx->fw, SKL_ADSP_FW_BIN_HDR_OFFSET, 0); if (ret < 0) { dev_err(ctx->dev, "UUID parsing err: %d\n", ret); -- cgit v0.10.2 From e280823c23f9ccc5f3bbd0fb2fa458cd96c1a881 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 26 Jul 2016 18:06:45 +0530 Subject: ASoC: Intel: Skylake: Parse UUIDs once The firmware manifest contains UUIDs which needs to be passed only once. So use the newly introduced is_first_boot flag to distinguish and parse these only once. Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 6e9c634..064fc7e 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -88,13 +88,15 @@ static int skl_load_base_firmware(struct sst_dsp *ctx) } } - ret = snd_skl_parse_uuids(ctx, ctx->fw, SKL_ADSP_FW_BIN_HDR_OFFSET, 0); - if (ret < 0) { - dev_err(ctx->dev, - "UUID parsing err: %d\n", ret); - release_firmware(ctx->fw); - skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); - return ret; + /* prase uuids on first boot */ + if (skl->is_first_boot) { + ret = snd_skl_parse_uuids(ctx, ctx->fw, SKL_ADSP_FW_BIN_HDR_OFFSET, 0); + if (ret < 0) { + dev_err(ctx->dev, "UUID parsing err: %d\n", ret); + release_firmware(ctx->fw); + skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); + return ret; + } } /* check for extended manifest */ -- cgit v0.10.2 From 0bdd6d8bedffdb33586455302b6543ca3f157cc1 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 26 Jul 2016 18:06:46 +0530 Subject: ASoC: Intel: Bxt: Parse UUIDs once The firmware manifest contains UUIDs which needs to be passed only once. So use the newly introduced is_first_boot flag to distinguish and parse these only once on bxt platform as well. Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index d6bf324..90702ce 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -175,9 +175,12 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx) if (ctx->fw == NULL) goto sst_load_base_firmware_failed; - ret = snd_skl_parse_uuids(ctx, ctx->fw, BXT_ADSP_FW_BIN_HDR_OFFSET, 0); - if (ret < 0) - goto sst_load_base_firmware_failed; + /* prase uuids on first boot */ + if (skl->is_first_boot) { + ret = snd_skl_parse_uuids(ctx, ctx->fw, BXT_ADSP_FW_BIN_HDR_OFFSET, 0); + if (ret < 0) + goto sst_load_base_firmware_failed; + } stripped_fw.data = ctx->fw->data; stripped_fw.size = ctx->fw->size; -- cgit v0.10.2 From 20fb2fbdfc88abb8b6f102c75c27b6068cec2f69 Mon Sep 17 00:00:00 2001 From: Ramesh Babu Date: Tue, 26 Jul 2016 18:06:47 +0530 Subject: ASoC: Intel: Skylake: Add library loading IPCs DSP fw can have additional firmwares as libs. These libs can be loaded using message IPC_GLB_LOAD_LIBRARY. Signed-off-by: Ramesh Babu Signed-off-by: Kranthi G Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 96f2f68..1544564 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -190,6 +190,7 @@ enum skl_ipc_glb_type { IPC_GLB_GET_PPL_CONTEXT_SIZE = 21, IPC_GLB_SAVE_PPL = 22, IPC_GLB_RESTORE_PPL = 23, + IPC_GLB_LOAD_LIBRARY = 24, IPC_GLB_NOTIFY = 26, IPC_GLB_MAX_IPC_MSG_NUMBER = 31 /* Maximum message number */ }; @@ -902,3 +903,25 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, return ret; } EXPORT_SYMBOL_GPL(skl_ipc_get_large_config); + +int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, + u8 dma_id, u8 table_id) +{ + struct skl_ipc_header header = {0}; + u64 *ipc_header = (u64 *)(&header); + int ret = 0; + + header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); + header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); + header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY); + header.primary |= IPC_MOD_INSTANCE_ID(table_id); + header.primary |= IPC_MOD_ID(dma_id); + + ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); + + if (ret < 0) + dev_err(ipc->dev, "ipc: load lib failed\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library); diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index 31e5bc3..fc46779 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -151,6 +151,9 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, struct skl_ipc_large_config_msg *msg, u32 *param); +int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, + u8 dma_id, u8 table_id); + void skl_ipc_int_enable(struct sst_dsp *dsp); void skl_ipc_op_int_enable(struct sst_dsp *ctx); void skl_ipc_op_int_disable(struct sst_dsp *ctx); -- cgit v0.10.2 From 004d94e5ab01a175523c8e7d205f94fb44274986 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Tue, 2 Aug 2016 09:07:13 +0800 Subject: ASoC: Intel: Skylake: fix noderef.cocci warnings sound/soc/intel/skylake/skl-topology.c:480:24-30: ERROR: application of sizeof to pointer sizeof when applied to a pointer typed expression gives the size of the pointer Generated by: scripts/coccinelle/misc/noderef.cocci Signed-off-by: Fengguang Wu Acked-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index a1d9f84..1300e4b 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -477,7 +477,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) if (mconfig->id.module_id < 0) { struct skl_dfw_module *dfw_config; - dfw_config = kzalloc(sizeof(dfw_config), GFP_KERNEL); + dfw_config = kzalloc(sizeof(*dfw_config), GFP_KERNEL); if (!dfw_config) return -ENOMEM; -- cgit v0.10.2 From 1ef015e611570c4cffea480e8d1c64622edef5d9 Mon Sep 17 00:00:00 2001 From: Ramesh Babu Date: Tue, 26 Jul 2016 18:06:48 +0530 Subject: ASoC: Intel: Skylake: Add library loading support The library load is added as one of the ops in skl_dsp_fw_ops(). The manifest load gives the files to be loaded which are loaded during the fw_init() Signed-off-by: Ramesh Babu Signed-off-by: Kranthi G Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 90702ce..48a4ae5 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -23,6 +23,7 @@ #include "../common/sst-dsp.h" #include "../common/sst-dsp-priv.h" #include "skl-sst-ipc.h" +#include "skl-tplg-interface.h" #define BXT_BASEFW_TIMEOUT 3000 #define BXT_INIT_TIMEOUT 500 @@ -40,11 +41,73 @@ #define BXT_INSTANCE_ID 0 #define BXT_BASE_FW_MODULE_ID 0 +#define BXT_ADSP_FW_BIN_HDR_OFFSET 0x2000 + static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) { return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE); } +static int +bxt_load_library(struct sst_dsp *ctx, struct skl_dfw_manifest *minfo) +{ + struct snd_dma_buffer dmab; + struct skl_sst *skl = ctx->thread_context; + const struct firmware *fw = NULL; + struct firmware stripped_fw; + int ret = 0, i, dma_id, stream_tag; + + /* library indices start from 1 to N. 0 represents base FW */ + for (i = 1; i < minfo->lib_count; i++) { + ret = request_firmware(&fw, minfo->lib[i].name, ctx->dev); + if (ret < 0) { + dev_err(ctx->dev, "Request lib %s failed:%d\n", + minfo->lib[i].name, ret); + return ret; + } + + if (skl->is_first_boot) { + ret = snd_skl_parse_uuids(ctx, fw, + BXT_ADSP_FW_BIN_HDR_OFFSET, i); + if (ret < 0) + goto load_library_failed; + } + + stripped_fw.data = fw->data; + stripped_fw.size = fw->size; + skl_dsp_strip_extended_manifest(&stripped_fw); + + stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, + stripped_fw.size, &dmab); + if (stream_tag <= 0) { + dev_err(ctx->dev, "Lib prepare DMA err: %x\n", + stream_tag); + ret = stream_tag; + goto load_library_failed; + } + + dma_id = stream_tag - 1; + memcpy(dmab.area, stripped_fw.data, stripped_fw.size); + + ctx->dsp_ops.trigger(ctx->dev, true, stream_tag); + ret = skl_sst_ipc_load_library(&skl->ipc, dma_id, i); + if (ret < 0) + dev_err(ctx->dev, "IPC Load Lib for %s fail: %d\n", + minfo->lib[i].name, ret); + + ctx->dsp_ops.trigger(ctx->dev, false, stream_tag); + ctx->dsp_ops.cleanup(ctx->dev, &dmab, stream_tag); + release_firmware(fw); + fw = NULL; + } + + return ret; + +load_library_failed: + release_firmware(fw); + return ret; +} + /* * First boot sequence has some extra steps. Core 0 waits for power * status on core 1, so power up core 1 also momentarily, keep it in @@ -157,8 +220,6 @@ static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) return ret; } -#define BXT_ADSP_FW_BIN_HDR_OFFSET 0x2000 - static int bxt_load_base_firmware(struct sst_dsp *ctx) { struct firmware stripped_fw; @@ -233,12 +294,23 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) int ret; struct skl_ipc_dxstate_info dx; unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); + struct skl_dfw_manifest *minfo = &skl->manifest; if (skl->fw_loaded == false) { skl->boot_complete = false; ret = bxt_load_base_firmware(ctx); - if (ret < 0) + if (ret < 0) { dev_err(ctx->dev, "reload fw failed: %d\n", ret); + return ret; + } + + if (minfo->lib_count > 1) { + ret = bxt_load_library(ctx, minfo); + if (ret < 0) { + dev_err(ctx->dev, "reload libs failed: %d\n", ret); + return ret; + } + } return ret; } @@ -344,6 +416,7 @@ static struct skl_dsp_fw_ops bxt_fw_ops = { .set_state_D3 = bxt_set_dsp_D3, .load_fw = bxt_load_base_firmware, .get_fw_errcode = bxt_get_errorcode, + .load_library = bxt_load_library, }; static struct sst_ops skl_ops = { @@ -422,6 +495,13 @@ int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx) skl_dsp_init_core_state(sst); + if (ctx->manifest.lib_count > 1) { + ret = sst->fw_ops.load_library(sst, &ctx->manifest); + if (ret < 0) { + dev_err(dev, "Load Library failed : %x", ret); + return ret; + } + } ctx->is_first_boot = false; return 0; diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index 5bc77e1..fa053c0 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -133,6 +133,8 @@ enum skl_dsp_states { struct skl_dsp_fw_ops { int (*load_fw)(struct sst_dsp *ctx); /* FW module parser/loader */ + int (*load_library)(struct sst_dsp *ctx, + struct skl_dfw_manifest *minfo); int (*parse_fw)(struct sst_dsp *ctx); int (*set_state_D0)(struct sst_dsp *ctx, unsigned int core_id); int (*set_state_D3)(struct sst_dsp *ctx, unsigned int core_id); -- cgit v0.10.2 From 8d983be820fa713785ce54caab08e74b36d9ee39 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 26 Jul 2016 18:06:49 +0530 Subject: ASoC: Intel: Skylake: Fix a comment style While changing code notice bad comment style, so fix it up. Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index fc46779..aad527d 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -66,7 +66,7 @@ struct skl_sst { /* callback for miscbdge */ void (*enable_miscbdcge)(struct device *dev, bool enable); - /*Is CGCTL.MISCBDCGE disabled*/ + /* Is CGCTL.MISCBDCGE disabled */ bool miscbdcg_disabled; /* Populate module information */ -- cgit v0.10.2 From 3d4006cd50289d7626639488c3a6449574cceee7 Mon Sep 17 00:00:00 2001 From: Senthilnathan Veppur Date: Tue, 26 Jul 2016 18:06:50 +0530 Subject: ASoC: Intel: Skylake: Add module processing domain support A module can be scheduled in deferent processing domains in DSP. Topology specifies the module domain. Signed-off-by: Senthilnathan Veppur Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 2199a91..8a750b6 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -870,6 +870,7 @@ int skl_init_module(struct skl_sst *ctx, msg.ppl_instance_id = mconfig->pipe->ppl_id; msg.param_data_size = module_config_size; msg.core_id = mconfig->core_id; + msg.domain = mconfig->domain; ret = skl_ipc_init_instance(&ctx->ipc, &msg, param_data); if (ret < 0) { diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 1544564..74dbecc 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -114,6 +114,11 @@ #define IPC_CORE_ID(x) (((x) & IPC_CORE_ID_MASK) \ << IPC_CORE_ID_SHIFT) +#define IPC_DOMAIN_SHIFT 28 +#define IPC_DOMAIN_MASK 0x1 +#define IPC_DOMAIN(x) (((x) & IPC_DOMAIN_MASK) \ + << IPC_DOMAIN_SHIFT) + /* Bind/Unbind message extension register */ #define IPC_DST_MOD_ID_SHIFT 0 #define IPC_DST_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \ @@ -705,6 +710,7 @@ int skl_ipc_init_instance(struct sst_generic_ipc *ipc, header.extension = IPC_CORE_ID(msg->core_id); header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id); header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size); + header.extension |= IPC_DOMAIN(msg->domain); dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, header.primary, header.extension); diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index aad527d..0334ed4 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -91,6 +91,7 @@ struct skl_ipc_init_instance_msg { u16 param_data_size; u8 ppl_instance_id; u8 core_id; + u8 domain; }; struct skl_ipc_bind_unbind_msg { diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 1300e4b..c13fbef 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -1656,6 +1656,7 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, mconfig->max_in_queue = dfw_config->max_in_queue; mconfig->max_out_queue = dfw_config->max_out_queue; mconfig->is_loadable = dfw_config->is_loadable; + mconfig->domain = dfw_config->proc_domain; skl_tplg_fill_fmt(mconfig->in_fmt, dfw_config->in_fmt, MODULE_MAX_IN_PINS); skl_tplg_fill_fmt(mconfig->out_fmt, dfw_config->out_fmt, diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index 1b531c1..bd8b4ae 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h @@ -210,7 +210,8 @@ struct skl_dfw_module { u32 is_dynamic_in_pin:1; u32 is_dynamic_out_pin:1; u32 is_loadable:1; - u32 rsvd3:11; + u32 proc_domain:1; + u32 rsvd3:10; struct skl_dfw_pipe pipe; struct skl_dfw_module_fmt in_fmt[MAX_IN_QUEUE]; -- cgit v0.10.2 From 519302954b726612eea6362047660cd56aa15c2e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 5 Aug 2016 10:56:51 +0200 Subject: ASoC: use of_property_read_bool Use of_property_read_bool to check for the existence of a property. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression e1,e2; statement S2,S1; @@ - if (of_get_property(e1,e2,NULL)) + if (of_property_read_bool(e1,e2)) S1 else S2 // Signed-off-by: Julia Lawall Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 2fc8915..1d4059c 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2408,28 +2408,28 @@ static void ab8500_codec_of_probe(struct device *dev, struct device_node *np, { u32 value; - if (of_get_property(np, "stericsson,amic1-type-single-ended", NULL)) + if (of_property_read_bool(np, "stericsson,amic1-type-single-ended")) codec->amics.mic1_type = AMIC_TYPE_SINGLE_ENDED; else codec->amics.mic1_type = AMIC_TYPE_DIFFERENTIAL; - if (of_get_property(np, "stericsson,amic2-type-single-ended", NULL)) + if (of_property_read_bool(np, "stericsson,amic2-type-single-ended")) codec->amics.mic2_type = AMIC_TYPE_SINGLE_ENDED; else codec->amics.mic2_type = AMIC_TYPE_DIFFERENTIAL; /* Has a non-standard Vamic been requested? */ - if (of_get_property(np, "stericsson,amic1a-bias-vamic2", NULL)) + if (of_property_read_bool(np, "stericsson,amic1a-bias-vamic2")) codec->amics.mic1a_micbias = AMIC_MICBIAS_VAMIC2; else codec->amics.mic1a_micbias = AMIC_MICBIAS_VAMIC1; - if (of_get_property(np, "stericsson,amic1b-bias-vamic2", NULL)) + if (of_property_read_bool(np, "stericsson,amic1b-bias-vamic2")) codec->amics.mic1b_micbias = AMIC_MICBIAS_VAMIC2; else codec->amics.mic1b_micbias = AMIC_MICBIAS_VAMIC1; - if (of_get_property(np, "stericsson,amic2-bias-vamic1", NULL)) + if (of_property_read_bool(np, "stericsson,amic2-bias-vamic1")) codec->amics.mic2_micbias = AMIC_MICBIAS_VAMIC1; else codec->amics.mic2_micbias = AMIC_MICBIAS_VAMIC2; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 5f848f0..6cb6db0 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -928,7 +928,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv) } ops = &rsnd_ssi_non_ops; - if (of_get_property(np, "pio-transfer", NULL)) + if (of_property_read_bool(np, "pio-transfer")) ops = &rsnd_ssi_pio_ops; else ops = &rsnd_ssi_dma_ops; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 16369ca..ead49d0 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3733,7 +3733,7 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, * SND_SOC_DAIFMT_CLOCK_MASK area */ snprintf(prop, sizeof(prop), "%scontinuous-clock", prefix); - if (of_get_property(np, prop, NULL)) + if (of_property_read_bool(np, prop)) format |= SND_SOC_DAIFMT_CONT; else format |= SND_SOC_DAIFMT_GATED; -- cgit v0.10.2 From c6eac8a36a845e52ba520060a807044964ad9de5 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 3 Aug 2016 16:10:00 +0800 Subject: ASoC: rockchip: Add machine driver for RK3399 GRU Boards Because we need to support the multiple codecs (MAX98357A/RT5514/DA7219) on the RK3399 GRU boards, this patch can help us to support these codecs. Signed-off-by: Xing Zheng Acked-by: Rob Herring Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt new file mode 100644 index 0000000..f19b6c8 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt @@ -0,0 +1,15 @@ +ROCKCHIP with MAX98357A/RT5514/DA7219 codecs on GRU boards + +Required properties: +- compatible: "rockchip,rk3399-gru-sound" +- rockchip,cpu: The phandle of the Rockchip I2S controller that's + connected to the codecs +- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs + +Example: + +sound { + compatible = "rockchip,rk3399-gru-sound"; + rockchip,cpu = <&i2s0>; + rockchip,codec = <&max98357a &rt5514 &da7219>; +}; diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index f1e0c70..6d39032 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig @@ -41,3 +41,14 @@ config SND_SOC_ROCKCHIP_RT5645 help Say Y or M here if you want to add support for SoC audio on Rockchip boards using the RT5645/RT5650 codec, such as Veyron. + +config SND_SOC_RK3399_GRU_SOUND + tristate "ASoC support multiple codecs for Rockchip RK3399 GRU boards" + depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP + select SND_SOC_ROCKCHIP_I2S + select SND_SOC_MAX98357A + select SND_SOC_RT5514 + select SND_SOC_DA7219 + help + Say Y or M here if you want to add support multiple codecs for SoC + audio on Rockchip RK3399 GRU boards. diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile index c0bf560..84e5c7c 100644 --- a/sound/soc/rockchip/Makefile +++ b/sound/soc/rockchip/Makefile @@ -7,6 +7,8 @@ obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o snd-soc-rockchip-max98090-objs := rockchip_max98090.o snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o +snd-soc-rk3399-gru-sound-objs := rk3399_gru_sound.o obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o +obj-$(CONFIG_SND_SOC_RK3399_GRU_SOUND) += snd-soc-rk3399-gru-sound.o diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c new file mode 100644 index 0000000..9933703 --- /dev/null +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -0,0 +1,337 @@ +/* + * Rockchip machine ASoC driver for boards using MAX98357A/RT5514/DA7219 + * + * Copyright (c) 2016, ROCKCHIP CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rockchip_i2s.h" +#include "../codecs/da7219.h" +#include "../codecs/da7219-aad.h" +#include "../codecs/rt5514.h" + +#define DRV_NAME "rk3399-gru-sound" + +#define SOUND_FS 256 + +static struct snd_soc_jack rockchip_sound_jack; + +static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphones", NULL), + SND_SOC_DAPM_SPK("Speakers", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), +}; + +static const struct snd_soc_dapm_route rockchip_dapm_routes[] = { + /* Input Lines */ + {"MIC", NULL, "Headset Mic"}, + {"DMIC1L", NULL, "Int Mic"}, + {"DMIC1R", NULL, "Int Mic"}, + + /* Output Lines */ + {"Headphones", NULL, "HPL"}, + {"Headphones", NULL, "HPR"}, + {"Speakers", NULL, "Speaker"}, +}; + +static const struct snd_kcontrol_new rockchip_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphones"), + SOC_DAPM_PIN_SWITCH("Speakers"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Int Mic"), +}; + +static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + unsigned int mclk; + int ret; + + /* max98357a supports these sample rates */ + switch (params_rate(params)) { + case 8000: + case 16000: + case 48000: + case 96000: + mclk = params_rate(params) * SOUND_FS; + break; + default: + dev_err(rtd->card->dev, "%s() doesn't support this sample rate: %d\n", + __func__, params_rate(params)); + return -EINVAL; + } + + ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0); + if (ret) { + dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n", + __func__, mclk, ret); + return ret; + } + + return 0; +} + +static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + unsigned int mclk; + int ret; + + mclk = params_rate(params) * SOUND_FS; + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, + SND_SOC_CLOCK_OUT); + if (ret < 0) { + dev_err(rtd->card->dev, "Can't set cpu clock out %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK, + mclk, SND_SOC_CLOCK_IN); + if (ret) { + dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n", + __func__, params_rate(params) * 512, ret); + return ret; + } + + return 0; +} + +static int rockchip_sound_da7219_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int mclk, ret; + + /* in bypass mode, the mclk has to be one of the frequencies below */ + switch (params_rate(params)) { + case 8000: + case 16000: + case 24000: + case 32000: + case 48000: + case 64000: + case 96000: + mclk = 12288000; + break; + case 11025: + case 22050: + case 44100: + case 88200: + mclk = 11289600; + break; + default: + return -EINVAL; + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, + SND_SOC_CLOCK_OUT); + if (ret < 0) { + dev_err(codec_dai->dev, "Can't set cpu clock out %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, "Can't set codec clock in %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0); + if (ret < 0) { + dev_err(codec_dai->dev, "Can't set pll sysclk mclk %d\n", ret); + return ret; + } + + return 0; +} + +static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec_dais[0]->codec; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int ret; + + /* We need default MCLK and PLL settings for the accessory detection */ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, 12288000, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, "Init can't set codec clock in %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0); + if (ret < 0) { + dev_err(codec_dai->dev, "Init can't set pll sysclk mclk %d\n", ret); + return ret; + } + + /* Enable Headset and 4 Buttons Jack detection */ + ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_LINEOUT | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &rockchip_sound_jack, NULL, 0); + + if (ret) { + dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret); + return ret; + } + + da7219_aad_jack_det(codec, &rockchip_sound_jack); + + return 0; +} + +static struct snd_soc_ops rockchip_sound_max98357a_ops = { + .hw_params = rockchip_sound_max98357a_hw_params, +}; + +static struct snd_soc_ops rockchip_sound_rt5514_ops = { + .hw_params = rockchip_sound_rt5514_hw_params, +}; + +static struct snd_soc_ops rockchip_sound_da7219_ops = { + .hw_params = rockchip_sound_da7219_hw_params, +}; + +enum { + DAILINK_MAX98357A, + DAILINK_RT5514, + DAILINK_DA7219, +}; + +static struct snd_soc_dai_link rockchip_dailinks[] = { + [DAILINK_MAX98357A] = { + .name = "MAX98357A", + .stream_name = "MAX98357A PCM", + .codec_dai_name = "HiFi", + .ops = &rockchip_sound_max98357a_ops, + /* set max98357a as slave */ + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + }, + [DAILINK_RT5514] = { + .name = "RT5514", + .stream_name = "RT5514 PCM", + .codec_dai_name = "rt5514-aif1", + .ops = &rockchip_sound_rt5514_ops, + /* set rt5514 as slave */ + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + }, + [DAILINK_DA7219] = { + .name = "DA7219", + .stream_name = "DA7219 PCM", + .codec_dai_name = "da7219-hifi", + .init = rockchip_sound_da7219_init, + .ops = &rockchip_sound_da7219_ops, + /* set da7219 as slave */ + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + }, +}; + +static struct snd_soc_card rockchip_sound_card = { + .name = "rk3399-gru-sound", + .owner = THIS_MODULE, + .dai_link = rockchip_dailinks, + .num_links = ARRAY_SIZE(rockchip_dailinks), + .dapm_widgets = rockchip_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets), + .dapm_routes = rockchip_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes), + .controls = rockchip_controls, + .num_controls = ARRAY_SIZE(rockchip_controls), +}; + +static int rockchip_sound_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &rockchip_sound_card; + struct device_node *cpu_node; + int i, ret; + + cpu_node = of_parse_phandle(pdev->dev.of_node, "rockchip,cpu", 0); + if (!cpu_node) { + dev_err(&pdev->dev, "Property 'rockchip,cpu' missing or invalid\n"); + return -EINVAL; + } + + for (i = 0; i < card->num_links; i++) { + rockchip_dailinks[i].platform_of_node = cpu_node; + rockchip_dailinks[i].cpu_of_node = cpu_node; + + rockchip_dailinks[i].codec_of_node = + of_parse_phandle(pdev->dev.of_node, "rockchip,codec", i); + if (!rockchip_dailinks[i].codec_of_node) { + dev_err(&pdev->dev, + "Property[%d] 'rockchip,codec' missing or invalid\n", i); + return -EINVAL; + } + } + + card->dev = &pdev->dev; + platform_set_drvdata(pdev, card); + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) + dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", + __func__, ret); + + return ret; +} + +static const struct of_device_id rockchip_sound_of_match[] = { + { .compatible = "rockchip,rk3399-gru-sound", }, + {}, +}; + +static struct platform_driver rockchip_sound_driver = { + .probe = rockchip_sound_probe, + .driver = { + .name = DRV_NAME, + .of_match_table = rockchip_sound_of_match, +#ifdef CONFIG_PM + .pm = &snd_soc_pm_ops, +#endif + }, +}; + +module_platform_driver(rockchip_sound_driver); + +MODULE_AUTHOR("Xing Zheng "); +MODULE_DESCRIPTION("Rockchip ASoC Machine Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); +MODULE_DEVICE_TABLE(of, rockchip_sound_of_match); -- cgit v0.10.2 From c6f8769b03749b244331699471bef02c9b9d5ebc Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 28 Jul 2016 14:57:16 -0700 Subject: ASoC: rt5659: Add mclk controls The codec driver should control the mclk. So this patch adds this support. Signed-off-by: Nicolin Chen Acked-by: Rob Herring Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/rt5659.txt b/Documentation/devicetree/bindings/sound/rt5659.txt index 5f79e7f..1766e05 100644 --- a/Documentation/devicetree/bindings/sound/rt5659.txt +++ b/Documentation/devicetree/bindings/sound/rt5659.txt @@ -12,6 +12,9 @@ Required properties: Optional properties: +- clocks: The phandle of the master clock to the CODEC +- clock-names: Should be "mclk" + - realtek,in1-differential - realtek,in3-differential - realtek,in4-differential diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 1b30914..42c183f 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include @@ -3565,7 +3566,9 @@ static int rt5659_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) static int rt5659_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec); + int ret; switch (level) { case SND_SOC_BIAS_PREPARE: @@ -3582,6 +3585,17 @@ static int rt5659_set_bias_level(struct snd_soc_codec *codec, RT5659_PWR_FV1 | RT5659_PWR_FV2); break; + case SND_SOC_BIAS_STANDBY: + if (dapm->bias_level == SND_SOC_BIAS_OFF) { + ret = clk_prepare_enable(rt5659->mclk); + if (ret) { + dev_err(codec->dev, + "failed to enable MCLK: %d\n", ret); + return ret; + } + } + break; + case SND_SOC_BIAS_OFF: regmap_update_bits(rt5659->regmap, RT5659_PWR_DIG_1, RT5659_PWR_LDO, 0); @@ -3591,6 +3605,7 @@ static int rt5659_set_bias_level(struct snd_soc_codec *codec, RT5659_PWR_MB | RT5659_PWR_VREF2); regmap_update_bits(rt5659->regmap, RT5659_DIG_MISC, RT5659_DIG_GATE_CTRL, 0); + clk_disable_unprepare(rt5659->mclk); break; default: @@ -4020,6 +4035,15 @@ static int rt5659_i2c_probe(struct i2c_client *i2c, regmap_write(rt5659->regmap, RT5659_RESET, 0); + /* Check if MCLK provided */ + rt5659->mclk = devm_clk_get(&i2c->dev, "mclk"); + if (IS_ERR(rt5659->mclk)) { + if (PTR_ERR(rt5659->mclk) != -ENOENT) + return PTR_ERR(rt5659->mclk); + /* Otherwise mark the mclk pointer to NULL */ + rt5659->mclk = NULL; + } + rt5659_calibrate(rt5659); /* line in diff mode*/ diff --git a/sound/soc/codecs/rt5659.h b/sound/soc/codecs/rt5659.h index d31c9e5..d69b0eb 100644 --- a/sound/soc/codecs/rt5659.h +++ b/sound/soc/codecs/rt5659.h @@ -1796,6 +1796,7 @@ struct rt5659_priv { struct gpio_desc *gpiod_reset; struct snd_soc_jack *hs_jack; struct delayed_work jack_detect_work; + struct clk *mclk; int sysclk; int sysclk_src; -- cgit v0.10.2 From 69e7a69a2225e20503b2623fe2dcf78442ab5593 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 11:30:26 +0200 Subject: ASoC: samsung: Drop usage of struct s3c_dma_params from i2s.c struct s3c_dma_params already includes struct snd_dmaengine_dai_dma_data, there is no need for such an indirection so switch to using struct snd_dmaengine_dai_dma_data instead of struct s3c_dma_params. This also allows us to use snd_soc_dai_init_dma_data() function instead of the platform specific samsung_asoc_init_dma_data helper. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 50635ee..fa3ff03 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -87,9 +87,9 @@ struct i2s_dai { /* Driver for this DAI */ struct snd_soc_dai_driver i2s_dai_drv; /* DMA parameters */ - struct s3c_dma_params dma_playback; - struct s3c_dma_params dma_capture; - struct s3c_dma_params idma_playback; + struct snd_dmaengine_dai_dma_data dma_playback; + struct snd_dmaengine_dai_dma_data dma_capture; + struct snd_dmaengine_dai_dma_data idma_playback; dma_filter_fn filter; u32 quirks; u32 suspend_i2smod; @@ -692,15 +692,15 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, break; case 2: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - i2s->dma_playback.dma_size = 4; + i2s->dma_playback.addr_width = 4; else - i2s->dma_capture.dma_size = 4; + i2s->dma_capture.addr_width = 4; break; case 1: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - i2s->dma_playback.dma_size = 2; + i2s->dma_playback.addr_width = 2; else - i2s->dma_capture.dma_size = 2; + i2s->dma_capture.addr_width = 2; break; default: @@ -754,7 +754,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, writel(mod, i2s->addr + I2SMOD); spin_unlock_irqrestore(i2s->lock, flags); - samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); + snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); i2s->frmclk = params_rate(params); @@ -991,10 +991,10 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) unsigned long flags; if (is_secondary(i2s)) { /* If this is probe on the secondary DAI */ - samsung_asoc_init_dma_data(dai, &other->sec_dai->dma_playback, + snd_soc_dai_init_dma_data(dai, &other->sec_dai->dma_playback, NULL); } else { - samsung_asoc_init_dma_data(dai, &i2s->dma_playback, + snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); if (i2s->quirks & QUIRK_NEED_RSTCLR) @@ -1002,7 +1002,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) if (i2s->quirks & QUIRK_SUPPORTS_IDMA) idma_reg_addr_init(i2s->addr, - i2s->sec_dai->idma_playback.dma_addr); + i2s->sec_dai->idma_playback.addr); } /* Reset any constraint on RFS and BFS */ @@ -1262,8 +1262,8 @@ static int samsung_i2s_probe(struct platform_device *pdev) return -EINVAL; } - pri_dai->dma_playback.slave = i2s_pdata->dma_playback; - pri_dai->dma_capture.slave = i2s_pdata->dma_capture; + pri_dai->dma_playback.filter_data = i2s_pdata->dma_playback; + pri_dai->dma_capture.filter_data = i2s_pdata->dma_capture; pri_dai->filter = i2s_pdata->dma_filter; if (&i2s_pdata->type) @@ -1302,12 +1302,12 @@ static int samsung_i2s_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to enable clock: %d\n", ret); return ret; } - pri_dai->dma_playback.dma_addr = regs_base + I2STXD; - pri_dai->dma_capture.dma_addr = regs_base + I2SRXD; - pri_dai->dma_playback.ch_name = "tx"; - pri_dai->dma_capture.ch_name = "rx"; - pri_dai->dma_playback.dma_size = 4; - pri_dai->dma_capture.dma_size = 4; + pri_dai->dma_playback.addr = regs_base + I2STXD; + pri_dai->dma_capture.addr = regs_base + I2SRXD; + pri_dai->dma_playback.chan_name = "tx"; + pri_dai->dma_capture.chan_name = "rx"; + pri_dai->dma_playback.addr_width = 4; + pri_dai->dma_capture.addr_width = 4; pri_dai->quirks = quirks; pri_dai->variant_regs = i2s_dai_data->i2s_variant_regs; @@ -1323,19 +1323,19 @@ static int samsung_i2s_probe(struct platform_device *pdev) sec_dai->lock = &pri_dai->spinlock; sec_dai->variant_regs = pri_dai->variant_regs; - sec_dai->dma_playback.dma_addr = regs_base + I2STXDS; - sec_dai->dma_playback.ch_name = "tx-sec"; + sec_dai->dma_playback.addr = regs_base + I2STXDS; + sec_dai->dma_playback.chan_name = "tx-sec"; if (!np) { - sec_dai->dma_playback.slave = i2s_pdata->dma_play_sec; + sec_dai->dma_playback.filter_data = i2s_pdata->dma_play_sec; sec_dai->filter = i2s_pdata->dma_filter; } - sec_dai->dma_playback.dma_size = 4; + sec_dai->dma_playback.addr_width = 4; sec_dai->addr = pri_dai->addr; sec_dai->clk = pri_dai->clk; sec_dai->quirks = quirks; - sec_dai->idma_playback.dma_addr = idma_addr; + sec_dai->idma_playback.addr = idma_addr; sec_dai->pri_dai = pri_dai; pri_dai->sec_dai = sec_dai; } -- cgit v0.10.2 From 8999390e40abe8099bd18299eaed96469f8aa5e1 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 11:30:27 +0200 Subject: ASoC: samsung: Drop usage of struct s3c_dma_params from s3c24xx-i2s.c struct s3c_dma_params already includes struct snd_dmaengine_dai_dma_data, there is no need for such an indirection so switch to using struct snd_dmaengine_dai_dma_data instead of struct s3c_dma_params. This also allows us to use snd_soc_dai_init_dma_data() function instead of the platform specific samsung_asoc_init_dma_data helper. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 3e76f2a..c78a936 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -32,14 +32,14 @@ #include -static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = { - .ch_name = "tx", - .dma_size = 2, +static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_out = { + .chan_name = "tx", + .addr_width = 2, }; -static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = { - .ch_name = "rx", - .dma_size = 2, +static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_in = { + .chan_name = "rx", + .addr_width = 2, }; struct s3c24xx_i2s_info { @@ -360,8 +360,8 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) { pr_debug("Entered %s\n", __func__); - samsung_asoc_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out, - &s3c24xx_i2s_pcm_stereo_in); + snd_soc_dai_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out, + &s3c24xx_i2s_pcm_stereo_in); s3c24xx_i2s.iis_clk = devm_clk_get(dai->dev, "iis"); if (IS_ERR(s3c24xx_i2s.iis_clk)) { @@ -469,10 +469,10 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) if (IS_ERR(s3c24xx_i2s.regs)) return PTR_ERR(s3c24xx_i2s.regs); - s3c24xx_i2s_pcm_stereo_out.dma_addr = res->start + S3C2410_IISFIFO; - s3c24xx_i2s_pcm_stereo_out.slave = pdata->dma_playback; - s3c24xx_i2s_pcm_stereo_in.dma_addr = res->start + S3C2410_IISFIFO; - s3c24xx_i2s_pcm_stereo_in.slave = pdata->dma_capture; + s3c24xx_i2s_pcm_stereo_out.addr = res->start + S3C2410_IISFIFO; + s3c24xx_i2s_pcm_stereo_out.filter_data = pdata->dma_playback; + s3c24xx_i2s_pcm_stereo_in.addr = res->start + S3C2410_IISFIFO; + s3c24xx_i2s_pcm_stereo_in.filter_data = pdata->dma_capture; ret = devm_snd_soc_register_component(&pdev->dev, &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); -- cgit v0.10.2 From ea37bd4df55f640b5146ac08cd377242d3042e2e Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 11:30:28 +0200 Subject: ASoC: samsung: Drop usage of struct s3c_dma_params from s3c2412-i2s.c struct s3c_dma_params already includes struct snd_dmaengine_dai_dma_data, there is no need for such an indirection so switch to using struct snd_dmaengine_dai_dma_data instead of struct s3c_dma_params. This also allows us to use snd_soc_dai_init_dma_data() function instead of the platform specific samsung_asoc_init_dma_data helper. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index bf8ae79..74a7f4b 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c @@ -302,7 +302,7 @@ static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct s3c_i2sv2_info *i2s = to_info(dai); - struct s3c_dma_params *dma_data; + struct snd_dmaengine_dai_dma_data *dma_data; u32 iismod; pr_debug("Entered %s\n", __func__); diff --git a/sound/soc/samsung/s3c-i2s-v2.h b/sound/soc/samsung/s3c-i2s-v2.h index d068414..182d805 100644 --- a/sound/soc/samsung/s3c-i2s-v2.h +++ b/sound/soc/samsung/s3c-i2s-v2.h @@ -60,8 +60,8 @@ struct s3c_i2sv2_info { unsigned char master; - struct s3c_dma_params *dma_playback; - struct s3c_dma_params *dma_capture; + struct snd_dmaengine_dai_dma_data *dma_playback; + struct snd_dmaengine_dai_dma_data *dma_capture; u32 suspend_iismod; u32 suspend_iiscon; diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index d45dffb..3e89fbc 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c @@ -34,14 +34,14 @@ #include -static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = { - .ch_name = "tx", - .dma_size = 4, +static struct snd_dmaengine_dai_dma_data s3c2412_i2s_pcm_stereo_out = { + .chan_name = "tx", + .addr_width = 4, }; -static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { - .ch_name = "rx", - .dma_size = 4, +static struct snd_dmaengine_dai_dma_data s3c2412_i2s_pcm_stereo_in = { + .chan_name = "rx", + .addr_width = 4, }; static struct s3c_i2sv2_info s3c2412_i2s; @@ -52,8 +52,8 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) pr_debug("Entered %s\n", __func__); - samsung_asoc_init_dma_data(dai, &s3c2412_i2s_pcm_stereo_out, - &s3c2412_i2s_pcm_stereo_in); + snd_soc_dai_init_dma_data(dai, &s3c2412_i2s_pcm_stereo_out, + &s3c2412_i2s_pcm_stereo_in); ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS); if (ret) @@ -163,10 +163,10 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev) if (IS_ERR(s3c2412_i2s.regs)) return PTR_ERR(s3c2412_i2s.regs); - s3c2412_i2s_pcm_stereo_out.dma_addr = res->start + S3C2412_IISTXD; - s3c2412_i2s_pcm_stereo_out.slave = pdata->dma_playback; - s3c2412_i2s_pcm_stereo_in.dma_addr = res->start + S3C2412_IISRXD; - s3c2412_i2s_pcm_stereo_in.slave = pdata->dma_capture; + s3c2412_i2s_pcm_stereo_out.addr = res->start + S3C2412_IISTXD; + s3c2412_i2s_pcm_stereo_out.filter_data = pdata->dma_playback; + s3c2412_i2s_pcm_stereo_in.addr = res->start + S3C2412_IISRXD; + s3c2412_i2s_pcm_stereo_in.filter_data = pdata->dma_capture; ret = s3c_i2sv2_register_component(&pdev->dev, -1, &s3c2412_i2s_component, -- cgit v0.10.2 From 996d81e167de8a20acabae66c1d0db481b40fbbe Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 11:30:29 +0200 Subject: ASoC: samsung: Drop usage of struct s3c_dma_params from ac97.c struct s3c_dma_params already includes struct snd_dmaengine_dai_dma_data, there is no need for such an indirection so switch to using struct snd_dmaengine_dai_dma_data instead of struct s3c_dma_params. This also allows us to use snd_soc_dai_init_dma_data() function instead of the platform specific samsung_asoc_init_dma_data helper. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index 547d310..5eafb66 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c @@ -38,16 +38,16 @@ struct s3c_ac97_info { }; static struct s3c_ac97_info s3c_ac97; -static struct s3c_dma_params s3c_ac97_pcm_out = { - .dma_size = 4, +static struct snd_dmaengine_dai_dma_data s3c_ac97_pcm_out = { + .addr_width = 4, }; -static struct s3c_dma_params s3c_ac97_pcm_in = { - .dma_size = 4, +static struct snd_dmaengine_dai_dma_data s3c_ac97_pcm_in = { + .addr_width = 4, }; -static struct s3c_dma_params s3c_ac97_mic_in = { - .dma_size = 4, +static struct snd_dmaengine_dai_dma_data s3c_ac97_mic_in = { + .addr_width = 4, }; static void s3c_ac97_activate(struct snd_ac97 *ac97) @@ -273,14 +273,14 @@ static const struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = { static int s3c_ac97_dai_probe(struct snd_soc_dai *dai) { - samsung_asoc_init_dma_data(dai, &s3c_ac97_pcm_out, &s3c_ac97_pcm_in); + snd_soc_dai_init_dma_data(dai, &s3c_ac97_pcm_out, &s3c_ac97_pcm_in); return 0; } static int s3c_ac97_mic_dai_probe(struct snd_soc_dai *dai) { - samsung_asoc_init_dma_data(dai, NULL, &s3c_ac97_mic_in); + snd_soc_dai_init_dma_data(dai, NULL, &s3c_ac97_mic_in); return 0; } @@ -346,12 +346,12 @@ static int s3c_ac97_probe(struct platform_device *pdev) if (IS_ERR(s3c_ac97.regs)) return PTR_ERR(s3c_ac97.regs); - s3c_ac97_pcm_out.slave = ac97_pdata->dma_playback; - s3c_ac97_pcm_out.dma_addr = mem_res->start + S3C_AC97_PCM_DATA; - s3c_ac97_pcm_in.slave = ac97_pdata->dma_capture; - s3c_ac97_pcm_in.dma_addr = mem_res->start + S3C_AC97_PCM_DATA; - s3c_ac97_mic_in.slave = ac97_pdata->dma_capture_mic; - s3c_ac97_mic_in.dma_addr = mem_res->start + S3C_AC97_MIC_DATA; + s3c_ac97_pcm_out.filter_data = ac97_pdata->dma_playback; + s3c_ac97_pcm_out.addr = mem_res->start + S3C_AC97_PCM_DATA; + s3c_ac97_pcm_in.filter_data = ac97_pdata->dma_capture; + s3c_ac97_pcm_in.addr = mem_res->start + S3C_AC97_PCM_DATA; + s3c_ac97_mic_in.filter_data = ac97_pdata->dma_capture_mic; + s3c_ac97_mic_in.addr = mem_res->start + S3C_AC97_MIC_DATA; init_completion(&s3c_ac97.done); mutex_init(&s3c_ac97.lock); -- cgit v0.10.2 From 2b6583457d9f2d5cc5d99243aa115c5fa958a7ad Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 11:30:30 +0200 Subject: ASoC: samsung: Drop usage of struct s3c_dma_params from spdif.c struct s3c_dma_params already includes struct snd_dmaengine_dai_dma_data, there is no need for such an indirection so switch to using struct snd_dmaengine_dai_dma_data instead of struct s3c_dma_params. This also allows us to use snd_soc_dai_init_dma_data() function instead of the platform specific samsung_asoc_init_dma_data helper. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index 0cb9c85..26c1fbe 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c @@ -90,10 +90,10 @@ struct samsung_spdif_info { u32 saved_clkcon; u32 saved_con; u32 saved_cstas; - struct s3c_dma_params *dma_playback; + struct snd_dmaengine_dai_dma_data *dma_playback; }; -static struct s3c_dma_params spdif_stereo_out; +static struct snd_dmaengine_dai_dma_data spdif_stereo_out; static struct samsung_spdif_info spdif_info; static inline struct samsung_spdif_info *to_info(struct snd_soc_dai *cpu_dai) @@ -179,7 +179,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai); void __iomem *regs = spdif->regs; - struct s3c_dma_params *dma_data; + struct snd_dmaengine_dai_dma_data *dma_data; u32 con, clkcon, cstas; unsigned long flags; int i, ratio; @@ -425,11 +425,11 @@ static int spdif_probe(struct platform_device *pdev) goto err4; } - spdif_stereo_out.dma_size = 2; - spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF; + spdif_stereo_out.addr_width = 2; + spdif_stereo_out.addr = mem_res->start + DATA_OUTBUF; filter = NULL; if (spdif_pdata) { - spdif_stereo_out.slave = spdif_pdata->dma_playback; + spdif_stereo_out.filter_data = spdif_pdata->dma_playback; filter = spdif_pdata->dma_filter; } -- cgit v0.10.2 From 2feb6165397155010147ff181b1501424c28ade7 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 11:30:31 +0200 Subject: ASoC: samsung: Drop usage of of struct s3c_dma_params from pcm.c struct s3c_dma_params already includes struct snd_dmaengine_dai_dma_data, there is no need for such an indirection so switch to using struct snd_dmaengine_dai_dma_data instead of struct s3c_dma_params. This also allows us to use snd_soc_dai_init_dma_data() function instead of the platform specific samsung_asoc_init_dma_data helper. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 490c1a8..43e367a 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -127,25 +127,25 @@ struct s3c_pcm_info { struct clk *pclk; struct clk *cclk; - struct s3c_dma_params *dma_playback; - struct s3c_dma_params *dma_capture; + struct snd_dmaengine_dai_dma_data *dma_playback; + struct snd_dmaengine_dai_dma_data *dma_capture; }; -static struct s3c_dma_params s3c_pcm_stereo_out[] = { +static struct snd_dmaengine_dai_dma_data s3c_pcm_stereo_out[] = { [0] = { - .dma_size = 4, + .addr_width = 4, }, [1] = { - .dma_size = 4, + .addr_width = 4, }, }; -static struct s3c_dma_params s3c_pcm_stereo_in[] = { +static struct snd_dmaengine_dai_dma_data s3c_pcm_stereo_in[] = { [0] = { - .dma_size = 4, + .addr_width = 4, }, [1] = { - .dma_size = 4, + .addr_width = 4, }, }; @@ -552,15 +552,13 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) } clk_prepare_enable(pcm->pclk); - s3c_pcm_stereo_in[pdev->id].dma_addr = mem_res->start - + S3C_PCM_RXFIFO; - s3c_pcm_stereo_out[pdev->id].dma_addr = mem_res->start - + S3C_PCM_TXFIFO; + s3c_pcm_stereo_in[pdev->id].addr = mem_res->start + S3C_PCM_RXFIFO; + s3c_pcm_stereo_out[pdev->id].addr = mem_res->start + S3C_PCM_TXFIFO; filter = NULL; if (pcm_pdata) { - s3c_pcm_stereo_in[pdev->id].slave = pcm_pdata->dma_capture; - s3c_pcm_stereo_out[pdev->id].slave = pcm_pdata->dma_playback; + s3c_pcm_stereo_in[pdev->id].filter_data = pcm_pdata->dma_capture; + s3c_pcm_stereo_out[pdev->id].filter_data = pcm_pdata->dma_playback; filter = pcm_pdata->dma_filter; } -- cgit v0.10.2 From 9b08f30c4f91fb9bbafa6a844cd0302e5752b21e Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 11:30:32 +0200 Subject: ASoC: samsung: Remove unused now unused struct s3c_dma_params There is no user of this data structure now, all users have been converted to use struct snd_dmaengine_dai_dma_data instead. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h index 3830f29..7ae580d 100644 --- a/sound/soc/samsung/dma.h +++ b/sound/soc/samsung/dma.h @@ -1,6 +1,4 @@ /* - * dma.h -- - * * 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; either version 2 of the License, or (at your @@ -9,27 +7,15 @@ * ALSA PCM interface for the Samsung SoC */ -#ifndef _S3C_AUDIO_H -#define _S3C_AUDIO_H +#ifndef _SAMSUNG_DMA_H +#define _SAMSUNG_DMA_H #include -#include - -struct s3c_dma_params { - void *slave; /* Channel ID */ - dma_addr_t dma_addr; - int dma_size; /* Size of the DMA transfer */ - char *ch_name; - struct snd_dmaengine_dai_dma_data dma_data; -}; -void samsung_asoc_init_dma_data(struct snd_soc_dai *dai, - struct s3c_dma_params *playback, - struct s3c_dma_params *capture); /* * @tx, @rx arguments can be NULL if the DMA channel names are "tx", "rx", * otherwise actual DMA channel names must be passed to this function. */ int samsung_asoc_dma_platform_register(struct device *dev, dma_filter_fn filter, const char *tx, const char *rx); -#endif +#endif /* _SAMSUNG_DMA_H */ diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c index 2c87f38..9104c98 100644 --- a/sound/soc/samsung/dmaengine.c +++ b/sound/soc/samsung/dmaengine.c @@ -16,49 +16,18 @@ */ #include -#include -#include - #include #include #include #include #include -#include #include "dma.h" -void samsung_asoc_init_dma_data(struct snd_soc_dai *dai, - struct s3c_dma_params *playback, - struct s3c_dma_params *capture) -{ - struct snd_dmaengine_dai_dma_data *playback_data = NULL; - struct snd_dmaengine_dai_dma_data *capture_data = NULL; - - if (playback) { - playback_data = &playback->dma_data; - playback_data->filter_data = playback->slave; - playback_data->chan_name = playback->ch_name; - playback_data->addr = playback->dma_addr; - playback_data->addr_width = playback->dma_size; - } - if (capture) { - capture_data = &capture->dma_data; - capture_data->filter_data = capture->slave; - capture_data->chan_name = capture->ch_name; - capture_data->addr = capture->dma_addr; - capture_data->addr_width = capture->dma_size; - } - - snd_soc_dai_init_dma_data(dai, playback_data, capture_data); -} -EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data); - int samsung_asoc_dma_platform_register(struct device *dev, dma_filter_fn filter, const char *tx, const char *rx) { unsigned int flags = SND_DMAENGINE_PCM_FLAG_COMPAT; - struct snd_dmaengine_pcm_config *pcm_conf; pcm_conf = devm_kzalloc(dev, sizeof(*pcm_conf), GFP_KERNEL); diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c index 4ed29ff..3e40815 100644 --- a/sound/soc/samsung/idma.c +++ b/sound/soc/samsung/idma.c @@ -22,7 +22,6 @@ #include "i2s.h" #include "idma.h" -#include "dma.h" #include "i2s-regs.h" #define ST_RUNNING (1<<0) diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index 74a7f4b..644f186 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c @@ -24,7 +24,6 @@ #include "regs-i2s-v2.h" #include "s3c-i2s-v2.h" -#include "dma.h" #undef S3C_IIS_V2_SUPPORTED diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c index 6deec52..a6d2233 100644 --- a/sound/soc/samsung/smdk_wm8580pcm.c +++ b/sound/soc/samsung/smdk_wm8580pcm.c @@ -16,7 +16,6 @@ #include #include "../codecs/wm8580.h" -#include "dma.h" #include "pcm.h" /* diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c index b1c89ec..2e62149 100644 --- a/sound/soc/samsung/smdk_wm8994pcm.c +++ b/sound/soc/samsung/smdk_wm8994pcm.c @@ -15,7 +15,6 @@ #include #include "../codecs/wm8994.h" -#include "dma.h" #include "pcm.h" /* -- cgit v0.10.2 From 0306741004fdfc2bc515b4b129b1f86881c5fcf5 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 15:38:41 +0200 Subject: ASoC: L3 bus: Add default gpio ops This adds aptional GPIO bit-bang based callback implementations for setting CLK, DATA and MODE L3 bus lines. It is added here to avoid possible duplicate implementations across users of the bus. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/include/sound/l3.h b/include/sound/l3.h index 423a08f..1471da2 100644 --- a/include/sound/l3.h +++ b/include/sound/l3.h @@ -2,9 +2,15 @@ #define _L3_H_ 1 struct l3_pins { - void (*setdat)(int); - void (*setclk)(int); - void (*setmode)(int); + void (*setdat)(struct l3_pins *, int); + void (*setclk)(struct l3_pins *, int); + void (*setmode)(struct l3_pins *, int); + + int gpio_data; + int gpio_clk; + int gpio_mode; + int use_gpios; + int data_hold; int data_setup; int clock_high; @@ -13,6 +19,9 @@ struct l3_pins { int mode_setup; }; +struct device; + int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len); +int l3_set_gpio_ops(struct device *dev, struct l3_pins *adap); #endif diff --git a/sound/soc/codecs/l3.c b/sound/soc/codecs/l3.c index 5353af5..a10ea3c 100644 --- a/sound/soc/codecs/l3.c +++ b/sound/soc/codecs/l3.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include @@ -32,11 +34,11 @@ static void sendbyte(struct l3_pins *adap, unsigned int byte) int i; for (i = 0; i < 8; i++) { - adap->setclk(0); + adap->setclk(adap, 0); udelay(adap->data_hold); - adap->setdat(byte & 1); + adap->setdat(adap, byte & 1); udelay(adap->data_setup); - adap->setclk(1); + adap->setclk(adap, 1); udelay(adap->clock_high); byte >>= 1; } @@ -55,10 +57,10 @@ static void sendbytes(struct l3_pins *adap, const u8 *buf, for (i = 0; i < len; i++) { if (i) { udelay(adap->mode_hold); - adap->setmode(0); + adap->setmode(adap, 0); udelay(adap->mode); } - adap->setmode(1); + adap->setmode(adap, 1); udelay(adap->mode_setup); sendbyte(adap, buf[i]); } @@ -66,26 +68,71 @@ static void sendbytes(struct l3_pins *adap, const u8 *buf, int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len) { - adap->setclk(1); - adap->setdat(1); - adap->setmode(1); + adap->setclk(adap, 1); + adap->setdat(adap, 1); + adap->setmode(adap, 1); udelay(adap->mode); - adap->setmode(0); + adap->setmode(adap, 0); udelay(adap->mode_setup); sendbyte(adap, addr); udelay(adap->mode_hold); sendbytes(adap, data, len); - adap->setclk(1); - adap->setdat(1); - adap->setmode(0); + adap->setclk(adap, 1); + adap->setdat(adap, 1); + adap->setmode(adap, 0); return len; } EXPORT_SYMBOL_GPL(l3_write); + +static void l3_set_clk(struct l3_pins *adap, int val) +{ + gpio_set_value(adap->gpio_clk, val); +} + +static void l3_set_data(struct l3_pins *adap, int val) +{ + gpio_set_value(adap->gpio_data, val); +} + +static void l3_set_mode(struct l3_pins *adap, int val) +{ + gpio_set_value(adap->gpio_mode, val); +} + +int l3_set_gpio_ops(struct device *dev, struct l3_pins *adap) +{ + int ret; + + if (!adap->use_gpios) + return -EINVAL; + + ret = devm_gpio_request_one(dev, adap->gpio_data, + GPIOF_OUT_INIT_LOW, "l3_data"); + if (ret < 0) + return ret; + adap->setdat = l3_set_data; + + ret = devm_gpio_request_one(dev, adap->gpio_clk, + GPIOF_OUT_INIT_LOW, "l3_clk"); + if (ret < 0) + return ret; + adap->setclk = l3_set_clk; + + ret = devm_gpio_request_one(dev, adap->gpio_mode, + GPIOF_OUT_INIT_LOW, "l3_mode"); + if (ret < 0) + return ret; + adap->setmode = l3_set_mode; + + return 0; +} +EXPORT_SYMBOL_GPL(l3_set_gpio_ops); + MODULE_DESCRIPTION("L3 bit-banging driver"); MODULE_AUTHOR("Christian Pellegrin "); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 11496471a1a2e126e7228c88a606544bb57c3e19 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 15:38:42 +0200 Subject: ARM: S3C24XX: Specify audio codec platform_data for mini2440 board The L3 bus GPIOs are specified in the board file rather than through the sound card's device platform_data. This allows to ensure the codec driver doesn't get probed with uninitialized platform_data field of its corresponding platform device. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c index a852168..13999c1 100644 --- a/arch/arm/mach-s3c24xx/mach-mini2440.c +++ b/arch/arm/mach-s3c24xx/mach-mini2440.c @@ -497,9 +497,28 @@ static struct i2c_board_info mini2440_i2c_devs[] __initdata = { }, }; +static struct uda134x_platform_data s3c24xx_uda134x = { + .l3 = { + .gpio_clk = S3C2410_GPB(4), + .gpio_data = S3C2410_GPB(3), + .gpio_mode = S3C2410_GPB(2), + .use_gpios = 1, + .data_hold = 1, + .data_setup = 1, + .clock_high = 1, + .mode_hold = 1, + .mode = 1, + .mode_setup = 1, + }, + .model = UDA134X_UDA1341, +}; + static struct platform_device uda1340_codec = { .name = "uda134x-codec", .id = -1, + .dev = { + .platform_data = &s3c24xx_uda134x, + }, }; static struct platform_device *mini2440_devices[] __initdata = { -- cgit v0.10.2 From 15a1bf0a7d3d7e6b351cac472ca4b6bc3746eb2e Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 15:38:43 +0200 Subject: ASoC: uda134x: Optionally initialize L3 ops to default GPIO ops The GPIO ops can be selected by platform_data which allows the codec platform device to probe without the sound card's driver intervention. The downside is that it will request GPIOs on behalf of the codec device and thus allow only one user on the bus, but it desn't seem to be a limitation with current code and usage of the GPIO ops is optional anyway. The proper approach would presumably be to create a proper Linux bus driver for L3, should this rather ancient bus specification suddenly gain more interest. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index e4c694c..b72c925 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -544,6 +544,7 @@ static int uda134x_codec_probe(struct platform_device *pdev) { struct uda134x_platform_data *pd = pdev->dev.platform_data; struct uda134x_priv *uda134x; + int ret; if (!pd) { dev_err(&pdev->dev, "Missing L3 bitbang function\n"); @@ -557,6 +558,12 @@ static int uda134x_codec_probe(struct platform_device *pdev) uda134x->pd = pd; platform_set_drvdata(pdev, uda134x); + if (pd->l3.use_gpios) { + ret = l3_set_gpio_ops(&pdev->dev, &uda134x->pd->l3); + if (ret < 0) + return ret; + } + uda134x->regmap = devm_regmap_init(&pdev->dev, NULL, pd, &uda134x_regmap_config); if (IS_ERR(uda134x->regmap)) -- cgit v0.10.2 From 84c5c20395a8e4ca2043136e1f0d128cf758244b Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 15:38:44 +0200 Subject: ASoC: s3c24xx_uda134x: Remove unused power() callback The power() callback has always been empty so just remove it. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/include/sound/s3c24xx_uda134x.h b/include/sound/s3c24xx_uda134x.h index 33df4cb..ffaf1f0 100644 --- a/include/sound/s3c24xx_uda134x.h +++ b/include/sound/s3c24xx_uda134x.h @@ -7,7 +7,6 @@ struct s3c24xx_uda134x_platform_data { int l3_clk; int l3_mode; int l3_data; - void (*power) (int); int model; }; diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index 50849e1..33479e7 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c @@ -281,7 +281,6 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev) "unable to find platform data\n"); return -ENODEV; } - s3c24xx_uda134x.power = s3c24xx_uda134x_l3_pins->power; s3c24xx_uda134x.model = s3c24xx_uda134x_l3_pins->model; if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_data, -- cgit v0.10.2 From 2da1e487cab4f3d134cc4b3ce2bd648660683900 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 15:38:45 +0200 Subject: ASoC: s3c24xx_uda134x: Drop initialization of codec's platform data It's already taken care by the codec and its platform_data defined in the arch/arm/mach-s3c24xx/mach-mini2440.c board file. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index 33479e7..7119aab 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c @@ -226,78 +226,12 @@ static struct snd_soc_card snd_soc_s3c24xx_uda134x = { .num_links = 1, }; -static struct s3c24xx_uda134x_platform_data *s3c24xx_uda134x_l3_pins; - -static void setdat(int v) -{ - gpio_set_value(s3c24xx_uda134x_l3_pins->l3_data, v > 0); -} - -static void setclk(int v) -{ - gpio_set_value(s3c24xx_uda134x_l3_pins->l3_clk, v > 0); -} - -static void setmode(int v) -{ - gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0); -} - -/* FIXME - This must be codec platform data but in which board file ?? */ -static struct uda134x_platform_data s3c24xx_uda134x = { - .l3 = { - .setdat = setdat, - .setclk = setclk, - .setmode = setmode, - .data_hold = 1, - .data_setup = 1, - .clock_high = 1, - .mode_hold = 1, - .mode = 1, - .mode_setup = 1, - }, -}; - -static int s3c24xx_uda134x_setup_pin(int pin, char *fun) -{ - if (gpio_request(pin, "s3c24xx_uda134x") < 0) { - printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: " - "l3 %s pin already in use", fun); - return -EBUSY; - } - gpio_direction_output(pin, 0); - return 0; -} - static int s3c24xx_uda134x_probe(struct platform_device *pdev) { int ret; printk(KERN_INFO "S3C24XX_UDA134X SoC Audio driver\n"); - s3c24xx_uda134x_l3_pins = pdev->dev.platform_data; - if (s3c24xx_uda134x_l3_pins == NULL) { - printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: " - "unable to find platform data\n"); - return -ENODEV; - } - s3c24xx_uda134x.model = s3c24xx_uda134x_l3_pins->model; - - if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_data, - "data") < 0) - return -EBUSY; - if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_clk, - "clk") < 0) { - gpio_free(s3c24xx_uda134x_l3_pins->l3_data); - return -EBUSY; - } - if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_mode, - "mode") < 0) { - gpio_free(s3c24xx_uda134x_l3_pins->l3_data); - gpio_free(s3c24xx_uda134x_l3_pins->l3_clk); - return -EBUSY; - } - s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1); if (!s3c24xx_uda134x_snd_device) { printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: " @@ -307,7 +241,7 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev) platform_set_drvdata(s3c24xx_uda134x_snd_device, &snd_soc_s3c24xx_uda134x); - platform_device_add_data(s3c24xx_uda134x_snd_device, &s3c24xx_uda134x, sizeof(s3c24xx_uda134x)); + ret = platform_device_add(s3c24xx_uda134x_snd_device); if (ret) { printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n"); @@ -320,9 +254,6 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev) static int s3c24xx_uda134x_remove(struct platform_device *pdev) { platform_device_unregister(s3c24xx_uda134x_snd_device); - gpio_free(s3c24xx_uda134x_l3_pins->l3_data); - gpio_free(s3c24xx_uda134x_l3_pins->l3_clk); - gpio_free(s3c24xx_uda134x_l3_pins->l3_mode); return 0; } -- cgit v0.10.2 From 28405212b5f972c8a9f666a5bcd1abdcb4a5dd5a Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 4 Aug 2016 15:38:46 +0200 Subject: ASoC: samsung: Convert s3c24xx_uda134x to use devm_snd_soc_register_card() Suppreses a following kernel warning: "soc-audio soc-audio: ASoC: machine S3C24XX_UDA134X should use snd_soc_register_card()". Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index 7119aab..13e52fb 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c @@ -54,8 +54,6 @@ static struct snd_pcm_hw_constraint_list hw_constraints_rates = { }; #endif -static struct platform_device *s3c24xx_uda134x_snd_device; - static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) { int ret = 0; @@ -66,7 +64,7 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) mutex_lock(&clk_lock); pr_debug("%s %d\n", __func__, clk_users); if (clk_users == 0) { - xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal"); + xtal = clk_get(rtd->dev, "xtal"); if (IS_ERR(xtal)) { printk(KERN_ERR "%s cannot get xtal\n", __func__); ret = PTR_ERR(xtal); @@ -228,43 +226,25 @@ static struct snd_soc_card snd_soc_s3c24xx_uda134x = { static int s3c24xx_uda134x_probe(struct platform_device *pdev) { + struct snd_soc_card *card = &snd_soc_s3c24xx_uda134x; int ret; - printk(KERN_INFO "S3C24XX_UDA134X SoC Audio driver\n"); - - s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1); - if (!s3c24xx_uda134x_snd_device) { - printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: " - "Unable to register\n"); - return -ENOMEM; - } + platform_set_drvdata(pdev, card); + card->dev = &pdev->dev; - platform_set_drvdata(s3c24xx_uda134x_snd_device, - &snd_soc_s3c24xx_uda134x); - - ret = platform_device_add(s3c24xx_uda134x_snd_device); - if (ret) { - printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n"); - platform_device_put(s3c24xx_uda134x_snd_device); - } + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) + dev_err(&pdev->dev, "failed to register card: %d\n", ret); return ret; } -static int s3c24xx_uda134x_remove(struct platform_device *pdev) -{ - platform_device_unregister(s3c24xx_uda134x_snd_device); - return 0; -} - static struct platform_driver s3c24xx_uda134x_driver = { .probe = s3c24xx_uda134x_probe, - .remove = s3c24xx_uda134x_remove, .driver = { .name = "s3c24xx_uda134x", }, }; - module_platform_driver(s3c24xx_uda134x_driver); MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin "); -- cgit v0.10.2 From 45ef4969d68f1837649ff3d8cdc5b804fa66df42 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 5 Aug 2016 11:47:09 +0200 Subject: ASoC: samsung: s3c24xx_uda134x: debug/error trace cleanup Switch from pr_* to dev_* macros and drop some debug traces. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index 13e52fb..1619e76 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c @@ -62,18 +62,18 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) #endif mutex_lock(&clk_lock); - pr_debug("%s %d\n", __func__, clk_users); + if (clk_users == 0) { xtal = clk_get(rtd->dev, "xtal"); if (IS_ERR(xtal)) { - printk(KERN_ERR "%s cannot get xtal\n", __func__); + dev_err(rtd->dev, "%s cannot get xtal\n", __func__); ret = PTR_ERR(xtal); } else { pclk = clk_get(&s3c24xx_uda134x_snd_device->dev, "pclk"); if (IS_ERR(pclk)) { - printk(KERN_ERR "%s cannot get pclk\n", - __func__); + dev_err(rtd->dev, "%s cannot get pclk\n", + __func__); clk_put(xtal); ret = PTR_ERR(pclk); } @@ -99,8 +99,8 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); if (ret < 0) - printk(KERN_ERR "%s cannot set constraints\n", - __func__); + dev_err(rtd->dev, "%s cannot set constraints\n", + __func__); #endif } return ret; @@ -109,7 +109,6 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream) { mutex_lock(&clk_lock); - pr_debug("%s %d\n", __func__, clk_users); clk_users -= 1; if (clk_users == 0) { clk_put(xtal); @@ -156,18 +155,19 @@ static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream, clk_source = S3C24XX_CLKSRC_PCLK; div = bi % 33; } - pr_debug("%s desired rate %lu, %d\n", __func__, rate, bi); + + dev_dbg(rtd->dev, "%s desired rate %lu, %d\n", __func__, rate, bi); clk = (fs_mode == S3C2410_IISMOD_384FS ? 384 : 256) * rate; - pr_debug("%s will use: %s %s %d sysclk %d err %ld\n", __func__, - fs_mode == S3C2410_IISMOD_384FS ? "384FS" : "256FS", - clk_source == S3C24XX_CLKSRC_MPLL ? "MPLLin" : "PCLK", - div, clk, err); + + dev_dbg(rtd->dev, "%s will use: %s %s %d sysclk %d err %ld\n", __func__, + fs_mode == S3C2410_IISMOD_384FS ? "384FS" : "256FS", + clk_source == S3C24XX_CLKSRC_MPLL ? "MPLLin" : "PCLK", + div, clk, err); if ((err * 100 / rate) > 5) { - printk(KERN_ERR "S3C24XX_UDA134X: effective frequency " - "too different from desired (%ld%%)\n", - err * 100 / rate); + dev_err(rtd->dev, "effective frequency too different " + "from desired (%ld%%)\n", err * 100 / rate); return -EINVAL; } -- cgit v0.10.2 From dc31e741db49e35e8b99d293dcc7afbbe9418fa7 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Tue, 26 Jul 2016 14:32:18 +0800 Subject: ASoC: topology: ABI - Add the types for BE DAI Define the type and ABI struct for Backend DAIs. Add the number of BE DAIs to manifest, and some reserved fields for future extensions. Pump the version number to 5. Topology core will check size of ABI objects to detect version mismatch between user space and kernel. Signed-off-by: Guneshwor Singh Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h index e4701a3..f734bea 100644 --- a/include/uapi/sound/asoc.h +++ b/include/uapi/sound/asoc.h @@ -83,7 +83,7 @@ #define SND_SOC_TPLG_NUM_TEXTS 16 /* ABI version */ -#define SND_SOC_TPLG_ABI_VERSION 0x4 +#define SND_SOC_TPLG_ABI_VERSION 0x5 /* Max size of TLV data */ #define SND_SOC_TPLG_TLV_SIZE 32 @@ -105,7 +105,8 @@ #define SND_SOC_TPLG_TYPE_CODEC_LINK 9 #define SND_SOC_TPLG_TYPE_BACKEND_LINK 10 #define SND_SOC_TPLG_TYPE_PDATA 11 -#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_PDATA +#define SND_SOC_TPLG_TYPE_BE_DAI 12 +#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_BE_DAI /* vendor block IDs - please add new vendor types to end */ #define SND_SOC_TPLG_TYPE_VENDOR_FW 1000 @@ -124,6 +125,11 @@ #define SND_SOC_TPLG_TUPLE_TYPE_WORD 4 #define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5 +/* BE DAI flags */ +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES (1 << 0) +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS (1 << 1) +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2) + /* * Block Header. * This header precedes all object and object arrays below. @@ -285,6 +291,8 @@ struct snd_soc_tplg_manifest { __le32 graph_elems; /* number of graph elements */ __le32 pcm_elems; /* number of PCM elements */ __le32 dai_link_elems; /* number of DAI link elements */ + __le32 be_dai_elems; /* number of BE DAI elements */ + __le32 reserved[20]; /* reserved for new ABI element types */ struct snd_soc_tplg_private priv; } __attribute__((packed)); @@ -450,4 +458,26 @@ struct snd_soc_tplg_link_config { struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */ __le32 num_streams; /* number of streams */ } __attribute__((packed)); + +/* + * Describes SW/FW specific features of BE DAI. + * + * File block representation for BE DAI :- + * +-----------------------------------+-----+ + * | struct snd_soc_tplg_hdr | 1 | + * +-----------------------------------+-----+ + * | struct snd_soc_tplg_be_dai | N | + * +-----------------------------------+-----+ + */ +struct snd_soc_tplg_be_dai { + __le32 size; /* in bytes of this structure */ + char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* name - used to match */ + __le32 dai_id; /* unique ID - used to match */ + __le32 playback; /* supports playback mode */ + __le32 capture; /* supports capture mode */ + struct snd_soc_tplg_stream_caps caps[2]; /* playback and capture for DAI */ + __le32 flag_mask; /* bitmask of flags to configure */ + __le32 flags; /* SND_SOC_TPLG_DAI_FLGBIT_* */ + struct snd_soc_tplg_private priv; +} __attribute__((packed)); #endif -- cgit v0.10.2 From 0038be9a84dc1a4fbea9ddffe32c1cd141843447 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Tue, 26 Jul 2016 14:32:37 +0800 Subject: ASoC: topology: Add support for configuring existing BE DAIs The platform driver may just specify the BE (Back End) DAI name and ID. And topology will find the existing BE DAI by its name and ID, and then configure its stream caps and flags. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index ee7f15a..05a18f6 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -48,9 +48,10 @@ #define SOC_TPLG_PASS_PCM_DAI 4 #define SOC_TPLG_PASS_GRAPH 5 #define SOC_TPLG_PASS_PINS 6 +#define SOC_TPLG_PASS_BE_DAI 7 #define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST -#define SOC_TPLG_PASS_END SOC_TPLG_PASS_PINS +#define SOC_TPLG_PASS_END SOC_TPLG_PASS_BE_DAI struct soc_tplg { const struct firmware *fw; @@ -1556,6 +1557,24 @@ static void set_stream_info(struct snd_soc_pcm_stream *stream, stream->formats = caps->formats; } +static void set_dai_flags(struct snd_soc_dai_driver *dai_drv, + unsigned int flag_mask, unsigned int flags) +{ + if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES) + dai_drv->symmetric_rates = + flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES ? 1 : 0; + + if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS) + dai_drv->symmetric_channels = + flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS ? + 1 : 0; + + if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS) + dai_drv->symmetric_samplebits = + flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS ? + 1 : 0; +} + static int soc_tplg_dai_create(struct soc_tplg *tplg, struct snd_soc_tplg_pcm *pcm) { @@ -1690,8 +1709,96 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, return 0; } +/* * + * soc_tplg_be_dai_config - Find and configure an existing BE DAI. + * @tplg: topology context + * @be: topology BE DAI configs. + * + * The BE dai should already be registered by the platform driver. The + * platform driver should specify the BE DAI name and ID for matching. + */ +static int soc_tplg_be_dai_config(struct soc_tplg *tplg, + struct snd_soc_tplg_be_dai *be) +{ + struct snd_soc_dai_link_component dai_component = {0}; + struct snd_soc_dai *dai; + struct snd_soc_dai_driver *dai_drv; + struct snd_soc_pcm_stream *stream; + struct snd_soc_tplg_stream_caps *caps; + int ret; + + dai_component.dai_name = be->dai_name; + dai = snd_soc_find_dai(&dai_component); + if (!dai) { + dev_err(tplg->dev, "ASoC: BE DAI %s not registered\n", + be->dai_name); + return -EINVAL; + } + + if (be->dai_id != dai->id) { + dev_err(tplg->dev, "ASoC: BE DAI %s id mismatch\n", + be->dai_name); + return -EINVAL; + } + + dai_drv = dai->driver; + if (!dai_drv) + return -EINVAL; + + if (be->playback) { + stream = &dai_drv->playback; + caps = &be->caps[SND_SOC_TPLG_STREAM_PLAYBACK]; + set_stream_info(stream, caps); + } + + if (be->capture) { + stream = &dai_drv->capture; + caps = &be->caps[SND_SOC_TPLG_STREAM_CAPTURE]; + set_stream_info(stream, caps); + } + + if (be->flag_mask) + set_dai_flags(dai_drv, be->flag_mask, be->flags); + + /* pass control to component driver for optional further init */ + ret = soc_tplg_dai_load(tplg, dai_drv); + if (ret < 0) { + dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n"); + return ret; + } + + return 0; +} + +static int soc_tplg_be_dai_elems_load(struct soc_tplg *tplg, + struct snd_soc_tplg_hdr *hdr) +{ + struct snd_soc_tplg_be_dai *be; + int count = hdr->count; + int i; + + if (tplg->pass != SOC_TPLG_PASS_BE_DAI) + return 0; + + /* config the existing BE DAIs */ + for (i = 0; i < count; i++) { + be = (struct snd_soc_tplg_be_dai *)tplg->pos; + if (be->size != sizeof(*be)) { + dev_err(tplg->dev, "ASoC: invalid BE DAI size\n"); + return -EINVAL; + } + + soc_tplg_be_dai_config(tplg, be); + tplg->pos += (sizeof(*be) + be->priv.size); + } + + dev_dbg(tplg->dev, "ASoC: Configure %d BE DAIs\n", count); + return 0; +} + + static int soc_tplg_manifest_load(struct soc_tplg *tplg, - struct snd_soc_tplg_hdr *hdr) + struct snd_soc_tplg_hdr *hdr) { struct snd_soc_tplg_manifest *manifest; @@ -1793,6 +1900,8 @@ static int soc_tplg_load_header(struct soc_tplg *tplg, return soc_tplg_dapm_widget_elems_load(tplg, hdr); case SND_SOC_TPLG_TYPE_PCM: return soc_tplg_pcm_elems_load(tplg, hdr); + case SND_SOC_TPLG_TYPE_BE_DAI: + return soc_tplg_be_dai_elems_load(tplg, hdr); case SND_SOC_TPLG_TYPE_MANIFEST: return soc_tplg_manifest_load(tplg, hdr); default: -- cgit v0.10.2 From 180f58fece4be11125e663983ee3388e6512f159 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:46:41 +0000 Subject: ASoC: codec duplicated callback function goes to component on sun4i-codec codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 44f170c..0e19c50 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -628,12 +628,14 @@ static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = { }; static struct snd_soc_codec_driver sun4i_codec_codec = { - .controls = sun4i_codec_widgets, - .num_controls = ARRAY_SIZE(sun4i_codec_widgets), - .dapm_widgets = sun4i_codec_codec_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets), - .dapm_routes = sun4i_codec_codec_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes), + .component_driver = { + .controls = sun4i_codec_widgets, + .num_controls = ARRAY_SIZE(sun4i_codec_widgets), + .dapm_widgets = sun4i_codec_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets), + .dapm_routes = sun4i_codec_codec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(sun4i_codec_codec_dapm_routes), + }, }; static const struct snd_soc_component_driver sun4i_codec_component = { -- cgit v0.10.2 From 90eb10fc4fc2d5977879489324e5c4abe099e650 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:46:59 +0000 Subject: ASoC: codec duplicated callback function goes to component on pistachio-internal-dac codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/img/pistachio-internal-dac.c b/sound/soc/img/pistachio-internal-dac.c index 162a0fd..53e11c6 100644 --- a/sound/soc/img/pistachio-internal-dac.c +++ b/sound/soc/img/pistachio-internal-dac.c @@ -134,12 +134,14 @@ static int pistachio_internal_dac_codec_probe(struct snd_soc_codec *codec) static const struct snd_soc_codec_driver pistachio_internal_dac_driver = { .probe = pistachio_internal_dac_codec_probe, .idle_bias_off = true, - .controls = pistachio_internal_dac_snd_controls, - .num_controls = ARRAY_SIZE(pistachio_internal_dac_snd_controls), - .dapm_widgets = pistachio_internal_dac_widgets, - .num_dapm_widgets = ARRAY_SIZE(pistachio_internal_dac_widgets), - .dapm_routes = pistachio_internal_dac_routes, - .num_dapm_routes = ARRAY_SIZE(pistachio_internal_dac_routes), + .component_driver = { + .controls = pistachio_internal_dac_snd_controls, + .num_controls = ARRAY_SIZE(pistachio_internal_dac_snd_controls), + .dapm_widgets = pistachio_internal_dac_widgets, + .num_dapm_widgets = ARRAY_SIZE(pistachio_internal_dac_widgets), + .dapm_routes = pistachio_internal_dac_routes, + .num_dapm_routes = ARRAY_SIZE(pistachio_internal_dac_routes), + }, }; static int pistachio_internal_dac_probe(struct platform_device *pdev) -- cgit v0.10.2 From 8073aefa60823acf205a1e6a5ea118297179d766 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:36:49 +0000 Subject: ASoC: remove codec duplicated callback function codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch removes codec side duplicated callback function. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 6144882..5eb2b38 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -898,14 +898,6 @@ struct snd_soc_codec_driver { int (*resume)(struct snd_soc_codec *); struct snd_soc_component_driver component_driver; - /* Default control and setup, added after probe() is run */ - const struct snd_kcontrol_new *controls; - int num_controls; - const struct snd_soc_dapm_widget *dapm_widgets; - int num_dapm_widgets; - const struct snd_soc_dapm_route *dapm_routes; - int num_dapm_routes; - /* codec wide operations */ int (*set_sysclk)(struct snd_soc_codec *codec, int clk_id, int source, unsigned int freq, int dir); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 16369ca..edba975 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3333,19 +3333,6 @@ int snd_soc_register_codec(struct device *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) -- cgit v0.10.2 From c90e938ebfc3e239818fbb5abe761837f4f80d53 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:47:18 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8985 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 7347abf..bcf3473 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -1110,12 +1110,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8985 = { .set_bias_level = wm8985_set_bias_level, .suspend_bias_off = true, - .controls = wm8985_common_snd_controls, - .num_controls = ARRAY_SIZE(wm8985_common_snd_controls), - .dapm_widgets = wm8985_common_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8985_common_dapm_widgets), - .dapm_routes = wm8985_common_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8985_common_dapm_routes), + .component_driver = { + .controls = wm8985_common_snd_controls, + .num_controls = ARRAY_SIZE(wm8985_common_snd_controls), + .dapm_widgets = wm8985_common_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8985_common_dapm_widgets), + .dapm_routes = wm8985_common_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8985_common_dapm_routes), + }, }; static const struct regmap_config wm8985_regmap = { -- cgit v0.10.2 From 7a3304ea5c783fba6b68c62e17d041dfe9e57d9c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:47:36 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8978 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index d36d600..910b36f 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -999,12 +999,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8978 = { .resume = wm8978_resume, .set_bias_level = wm8978_set_bias_level, - .controls = wm8978_snd_controls, - .num_controls = ARRAY_SIZE(wm8978_snd_controls), - .dapm_widgets = wm8978_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8978_dapm_widgets), - .dapm_routes = wm8978_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8978_dapm_routes), + .component_driver = { + .controls = wm8978_snd_controls, + .num_controls = ARRAY_SIZE(wm8978_snd_controls), + .dapm_widgets = wm8978_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8978_dapm_widgets), + .dapm_routes = wm8978_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8978_dapm_routes), + }, }; static const struct regmap_config wm8978_regmap_config = { -- cgit v0.10.2 From 48b042380e970b70f1c5453d31c6bbff2114974e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:48:05 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8974 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index dc8c3b1..fbda6e3 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -681,12 +681,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { .set_bias_level = wm8974_set_bias_level, .suspend_bias_off = true, - .controls = wm8974_snd_controls, - .num_controls = ARRAY_SIZE(wm8974_snd_controls), - .dapm_widgets = wm8974_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8974_dapm_widgets), - .dapm_routes = wm8974_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes), + .component_driver = { + .controls = wm8974_snd_controls, + .num_controls = ARRAY_SIZE(wm8974_snd_controls), + .dapm_widgets = wm8974_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8974_dapm_widgets), + .dapm_routes = wm8974_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes), + }, }; static int wm8974_i2c_probe(struct i2c_client *i2c, -- cgit v0.10.2 From 2fdff3a06e2fdc7ddfb5636e500fcd491c897c7c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:48:24 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8903 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index a26ca49..c19ba7c 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1880,12 +1880,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { .seq_notifier = wm8903_seq_notifier, .suspend_bias_off = true, - .controls = wm8903_snd_controls, - .num_controls = ARRAY_SIZE(wm8903_snd_controls), - .dapm_widgets = wm8903_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8903_dapm_widgets), - .dapm_routes = wm8903_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8903_intercon), + .component_driver = { + .controls = wm8903_snd_controls, + .num_controls = ARRAY_SIZE(wm8903_snd_controls), + .dapm_widgets = wm8903_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8903_dapm_widgets), + .dapm_routes = wm8903_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8903_intercon), + }, }; static const struct regmap_config wm8903_regmap = { -- cgit v0.10.2 From f1d13276e1856814ac02c077ba0829f6d16b9468 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:48:42 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8804 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 8d91470..af95d648 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -545,10 +545,12 @@ static struct snd_soc_dai_driver wm8804_dai = { static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { .idle_bias_off = true, - .dapm_widgets = wm8804_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), - .dapm_routes = wm8804_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8804_dapm_routes), + .component_driver = { + .dapm_widgets = wm8804_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), + .dapm_routes = wm8804_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8804_dapm_routes), + }, }; const struct regmap_config wm8804_regmap_config = { -- cgit v0.10.2 From 42a60205fff0cacd384ae9497c00de61d5a240bd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:49:02 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8776 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 5af44f9..f17a3a8 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -430,12 +430,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { .set_bias_level = wm8776_set_bias_level, .suspend_bias_off = true, - .controls = wm8776_snd_controls, - .num_controls = ARRAY_SIZE(wm8776_snd_controls), - .dapm_widgets = wm8776_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8776_dapm_widgets), - .dapm_routes = routes, - .num_dapm_routes = ARRAY_SIZE(routes), + .component_driver = { + .controls = wm8776_snd_controls, + .num_controls = ARRAY_SIZE(wm8776_snd_controls), + .dapm_widgets = wm8776_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8776_dapm_widgets), + .dapm_routes = routes, + .num_dapm_routes = ARRAY_SIZE(routes), + }, }; static const struct of_device_id wm8776_of_match[] = { -- cgit v0.10.2 From baa484716a59e86065787ae20008703d178dcec5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:49:19 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8770 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index df61784..8783a5f 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -613,12 +613,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8770 = { .set_bias_level = wm8770_set_bias_level, .idle_bias_off = true, - .controls = wm8770_snd_controls, - .num_controls = ARRAY_SIZE(wm8770_snd_controls), - .dapm_widgets = wm8770_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8770_dapm_widgets), - .dapm_routes = wm8770_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8770_intercon), + .component_driver = { + .controls = wm8770_snd_controls, + .num_controls = ARRAY_SIZE(wm8770_snd_controls), + .dapm_widgets = wm8770_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8770_dapm_widgets), + .dapm_routes = wm8770_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8770_intercon), + }, }; static const struct of_device_id wm8770_of_match[] = { -- cgit v0.10.2 From 73238401ee2a344e921165b3d40bab3a89fe0f40 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:49:44 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8753 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index cdcc912..1bb272c 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1484,12 +1484,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { .set_bias_level = wm8753_set_bias_level, .suspend_bias_off = true, - .controls = wm8753_snd_controls, - .num_controls = ARRAY_SIZE(wm8753_snd_controls), - .dapm_widgets = wm8753_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8753_dapm_widgets), - .dapm_routes = wm8753_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8753_dapm_routes), + .component_driver = { + .controls = wm8753_snd_controls, + .num_controls = ARRAY_SIZE(wm8753_snd_controls), + .dapm_widgets = wm8753_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8753_dapm_widgets), + .dapm_routes = wm8753_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8753_dapm_routes), + }, }; static const struct of_device_id wm8753_of_match[] = { -- cgit v0.10.2 From c107fbaff34eddebeb34714f0334d710ca937091 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:50:02 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8750 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index bd9dcd2..a96a145 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -713,12 +713,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { .set_bias_level = wm8750_set_bias_level, .suspend_bias_off = true, - .controls = wm8750_snd_controls, - .num_controls = ARRAY_SIZE(wm8750_snd_controls), - .dapm_widgets = wm8750_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), - .dapm_routes = wm8750_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8750_dapm_routes), + .component_driver = { + .controls = wm8750_snd_controls, + .num_controls = ARRAY_SIZE(wm8750_snd_controls), + .dapm_widgets = wm8750_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), + .dapm_routes = wm8750_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8750_dapm_routes), + }, }; static const struct of_device_id wm8750_of_match[] = { -- cgit v0.10.2 From 818d2aa162b886e4c1b722ca8661f79384a257e9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:50:19 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8741 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 36ef91f..3e43272 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -502,10 +502,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { .remove = wm8741_remove, .resume = wm8741_resume, - .dapm_widgets = wm8741_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8741_dapm_widgets), - .dapm_routes = wm8741_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8741_dapm_routes), + .component_driver = { + .dapm_widgets = wm8741_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8741_dapm_widgets), + .dapm_routes = wm8741_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8741_dapm_routes), + }, }; static const struct of_device_id wm8741_of_match[] = { -- cgit v0.10.2 From 5cf0b2bd457ceae21b9a85ca7ecf97ccfbca6e25 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:50:38 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8737 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index e780760..728c42c 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -578,12 +578,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { .set_bias_level = wm8737_set_bias_level, .suspend_bias_off = true, - .controls = wm8737_snd_controls, - .num_controls = ARRAY_SIZE(wm8737_snd_controls), - .dapm_widgets = wm8737_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8737_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), + .component_driver = { + .controls = wm8737_snd_controls, + .num_controls = ARRAY_SIZE(wm8737_snd_controls), + .dapm_widgets = wm8737_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8737_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), + }, }; static const struct of_device_id wm8737_of_match[] = { -- cgit v0.10.2 From 2cb7474b0c74a6ba433afaa4d69d7ccec310c70e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:50:58 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8731 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index d18261a..545fc9a 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -632,12 +632,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { .set_bias_level = wm8731_set_bias_level, .suspend_bias_off = true, - .dapm_widgets = wm8731_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), - .dapm_routes = wm8731_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8731_intercon), - .controls = wm8731_snd_controls, - .num_controls = ARRAY_SIZE(wm8731_snd_controls), + .component_driver = { + .controls = wm8731_snd_controls, + .num_controls = ARRAY_SIZE(wm8731_snd_controls), + .dapm_widgets = wm8731_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), + .dapm_routes = wm8731_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8731_intercon), + }, }; static const struct of_device_id wm8731_of_match[] = { -- cgit v0.10.2 From 298e17babf7d3fbc5ab225212cbf3af414d97109 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:51:16 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8728 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 1564e69..dcd64b3 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -215,12 +215,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { .set_bias_level = wm8728_set_bias_level, .suspend_bias_off = true, - .controls = wm8728_snd_controls, - .num_controls = ARRAY_SIZE(wm8728_snd_controls), - .dapm_widgets = wm8728_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8728_dapm_widgets), - .dapm_routes = wm8728_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8728_intercon), + .component_driver = { + .controls = wm8728_snd_controls, + .num_controls = ARRAY_SIZE(wm8728_snd_controls), + .dapm_widgets = wm8728_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8728_dapm_widgets), + .dapm_routes = wm8728_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8728_intercon), + }, }; static const struct of_device_id wm8728_of_match[] = { -- cgit v0.10.2 From e324d8fa47016ca829989b95bc7bb4b550551b47 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:51:40 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8711 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index c759ec0..4e8ebef 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -372,12 +372,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { .set_bias_level = wm8711_set_bias_level, .suspend_bias_off = true, - .controls = wm8711_snd_controls, - .num_controls = ARRAY_SIZE(wm8711_snd_controls), - .dapm_widgets = wm8711_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8711_dapm_widgets), - .dapm_routes = wm8711_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8711_intercon), + .component_driver = { + .controls = wm8711_snd_controls, + .num_controls = ARRAY_SIZE(wm8711_snd_controls), + .dapm_widgets = wm8711_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8711_dapm_widgets), + .dapm_routes = wm8711_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8711_intercon), + }, }; static const struct of_device_id wm8711_of_match[] = { -- cgit v0.10.2 From cc469502fecf023330b21e34aae3268fe763e446 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:52:01 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8580 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 66602bf..2e69270 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -904,12 +904,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { .remove = wm8580_remove, .set_bias_level = wm8580_set_bias_level, - .controls = wm8580_snd_controls, - .num_controls = ARRAY_SIZE(wm8580_snd_controls), - .dapm_widgets = wm8580_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8580_dapm_widgets), - .dapm_routes = wm8580_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8580_dapm_routes), + .component_driver = { + .controls = wm8580_snd_controls, + .num_controls = ARRAY_SIZE(wm8580_snd_controls), + .dapm_widgets = wm8580_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8580_dapm_widgets), + .dapm_routes = wm8580_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8580_dapm_routes), + }, }; static const struct of_device_id wm8580_of_match[] = { -- cgit v0.10.2 From f8a5c975bd5b7fc5e46fd85b5a65c0028d09f979 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:52:19 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8523 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index aa287a3..0bb189a 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -418,12 +418,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { .set_bias_level = wm8523_set_bias_level, .suspend_bias_off = true, - .controls = wm8523_controls, - .num_controls = ARRAY_SIZE(wm8523_controls), - .dapm_widgets = wm8523_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8523_dapm_widgets), - .dapm_routes = wm8523_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8523_dapm_routes), + .component_driver = { + .controls = wm8523_controls, + .num_controls = ARRAY_SIZE(wm8523_controls), + .dapm_widgets = wm8523_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8523_dapm_widgets), + .dapm_routes = wm8523_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8523_dapm_routes), + }, }; static const struct of_device_id wm8523_of_match[] = { -- cgit v0.10.2 From 42c889233d8d5e075fdf8a2643a4ca69a9807075 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:52:40 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8510 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 99e40e6..7f93adf 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -586,12 +586,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { .set_bias_level = wm8510_set_bias_level, .suspend_bias_off = true, - .controls = wm8510_snd_controls, - .num_controls = ARRAY_SIZE(wm8510_snd_controls), - .dapm_widgets = wm8510_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8510_dapm_widgets), - .dapm_routes = wm8510_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8510_dapm_routes), + .component_driver = { + .controls = wm8510_snd_controls, + .num_controls = ARRAY_SIZE(wm8510_snd_controls), + .dapm_widgets = wm8510_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8510_dapm_widgets), + .dapm_routes = wm8510_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8510_dapm_routes), + }, }; static const struct of_device_id wm8510_of_match[] = { -- cgit v0.10.2 From 786e3a480fa9e04b36191a2529cabfec3e30ad9c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:53:08 +0000 Subject: ASoC: codec duplicated callback function goes to component on tlv320aic3x codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index a564759..5a8d96e 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1670,12 +1670,14 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = { .idle_bias_off = true, .probe = aic3x_probe, .remove = aic3x_remove, - .controls = aic3x_snd_controls, - .num_controls = ARRAY_SIZE(aic3x_snd_controls), - .dapm_widgets = aic3x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), + .component_driver = { + .controls = aic3x_snd_controls, + .num_controls = ARRAY_SIZE(aic3x_snd_controls), + .dapm_widgets = aic3x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), + }, }; /* -- cgit v0.10.2 From 1bb99f2a00682162b42998d2bafd7633c6c37541 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:53:34 +0000 Subject: ASoC: codec duplicated callback function goes to component on tlv320aic31xx codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 3c5e1df..e46fb47 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -1114,12 +1114,14 @@ static struct snd_soc_codec_driver soc_codec_driver_aic31xx = { .set_bias_level = aic31xx_set_bias_level, .suspend_bias_off = true, - .controls = aic31xx_snd_controls, - .num_controls = ARRAY_SIZE(aic31xx_snd_controls), - .dapm_widgets = aic31xx_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(aic31xx_dapm_widgets), - .dapm_routes = aic31xx_audio_map, - .num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map), + .component_driver = { + .controls = aic31xx_snd_controls, + .num_controls = ARRAY_SIZE(aic31xx_snd_controls), + .dapm_widgets = aic31xx_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic31xx_dapm_widgets), + .dapm_routes = aic31xx_audio_map, + .num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map), + }, }; static const struct snd_soc_dai_ops aic31xx_dai_ops = { -- cgit v0.10.2 From e88e495064e602772afa7b165643866acc6da6bf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:54:25 +0000 Subject: ASoC: codec duplicated callback function goes to component on tlv320aic23 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index cd8c02b..410cae0 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -583,12 +583,14 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { .set_bias_level = tlv320aic23_set_bias_level, .suspend_bias_off = true, - .controls = tlv320aic23_snd_controls, - .num_controls = ARRAY_SIZE(tlv320aic23_snd_controls), - .dapm_widgets = tlv320aic23_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), - .dapm_routes = tlv320aic23_intercon, - .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), + .component_driver = { + .controls = tlv320aic23_snd_controls, + .num_controls = ARRAY_SIZE(tlv320aic23_snd_controls), + .dapm_widgets = tlv320aic23_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), + .dapm_routes = tlv320aic23_intercon, + .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), + }, }; int tlv320aic23_probe(struct device *dev, struct regmap *regmap) -- cgit v0.10.2 From f2dea01ccbfc34a5e631afeb13c7d010d39c2543 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:54:44 +0000 Subject: ASoC: codec duplicated callback function goes to component on tfa9879 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tfa9879.c b/sound/soc/codecs/tfa9879.c index cb5310d..95e0a7a 100644 --- a/sound/soc/codecs/tfa9879.c +++ b/sound/soc/codecs/tfa9879.c @@ -231,13 +231,14 @@ static const struct snd_soc_dapm_route tfa9879_dapm_routes[] = { }; static const struct snd_soc_codec_driver tfa9879_codec = { - .controls = tfa9879_controls, - .num_controls = ARRAY_SIZE(tfa9879_controls), - - .dapm_widgets = tfa9879_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tfa9879_dapm_widgets), - .dapm_routes = tfa9879_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(tfa9879_dapm_routes), + .component_driver = { + .controls = tfa9879_controls, + .num_controls = ARRAY_SIZE(tfa9879_controls), + .dapm_widgets = tfa9879_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tfa9879_dapm_widgets), + .dapm_routes = tfa9879_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tfa9879_dapm_routes), + }, }; static const struct regmap_config tfa9879_regmap = { -- cgit v0.10.2 From a8f552df807d0c809ec529c8e998a6abbf40f324 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:55:04 +0000 Subject: ASoC: codec duplicated callback function goes to component on tas5720 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c index f54fb46..c65b917 100644 --- a/sound/soc/codecs/tas5720.c +++ b/sound/soc/codecs/tas5720.c @@ -489,12 +489,14 @@ static struct snd_soc_codec_driver soc_codec_dev_tas5720 = { .suspend = tas5720_suspend, .resume = tas5720_resume, - .controls = tas5720_snd_controls, - .num_controls = ARRAY_SIZE(tas5720_snd_controls), - .dapm_widgets = tas5720_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), - .dapm_routes = tas5720_audio_map, - .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map), + .component_driver = { + .controls = tas5720_snd_controls, + .num_controls = ARRAY_SIZE(tas5720_snd_controls), + .dapm_widgets = tas5720_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), + .dapm_routes = tas5720_audio_map, + .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map), + }, }; /* PCM rates supported by the TAS5720 driver */ -- cgit v0.10.2 From d75a9df6927363e5c4a41477db39e5332aa6bf73 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:55:21 +0000 Subject: ASoC: codec duplicated callback function goes to component on tas571x codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index d8baca3..df5e5cb 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -658,10 +658,12 @@ static const struct snd_soc_codec_driver tas571x_codec = { .set_bias_level = tas571x_set_bias_level, .idle_bias_off = true, - .dapm_widgets = tas571x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tas571x_dapm_widgets), - .dapm_routes = tas571x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(tas571x_dapm_routes), + .component_driver = { + .dapm_widgets = tas571x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas571x_dapm_widgets), + .dapm_routes = tas571x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tas571x_dapm_routes), + }, }; static struct snd_soc_dai_driver tas571x_dai = { @@ -754,8 +756,8 @@ static int tas571x_i2c_probe(struct i2c_client *client, memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver)); - priv->codec_driver.controls = priv->chip->controls; - priv->codec_driver.num_controls = priv->chip->num_controls; + priv->codec_driver.component_driver.controls = priv->chip->controls; + priv->codec_driver.component_driver.num_controls = priv->chip->num_controls; if (priv->chip->vol_reg_size == 2) { /* -- cgit v0.10.2 From 9a9a069c4445122b98025e8b1003caf5e0eba037 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:55:41 +0000 Subject: ASoC: codec duplicated callback function goes to component on tas5086 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index d49d25d..c297b9f 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -890,12 +890,14 @@ static struct snd_soc_codec_driver soc_codec_dev_tas5086 = { .remove = tas5086_remove, .suspend = tas5086_soc_suspend, .resume = tas5086_soc_resume, - .controls = tas5086_controls, - .num_controls = ARRAY_SIZE(tas5086_controls), - .dapm_widgets = tas5086_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tas5086_dapm_widgets), - .dapm_routes = tas5086_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(tas5086_dapm_routes), + .component_driver = { + .controls = tas5086_controls, + .num_controls = ARRAY_SIZE(tas5086_controls), + .dapm_widgets = tas5086_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas5086_dapm_widgets), + .dapm_routes = tas5086_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tas5086_dapm_routes), + }, }; static const struct i2c_device_id tas5086_i2c_id[] = { -- cgit v0.10.2 From e5538659c81991b9074ccb842e8af901c908b79b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:55:58 +0000 Subject: ASoC: codec duplicated callback function goes to component on tas2552 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index cc1d398..baf455e 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -667,12 +667,14 @@ static struct snd_soc_codec_driver soc_codec_dev_tas2552 = { .resume = tas2552_resume, .ignore_pmdown_time = true, - .controls = tas2552_snd_controls, - .num_controls = ARRAY_SIZE(tas2552_snd_controls), - .dapm_widgets = tas2552_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tas2552_dapm_widgets), - .dapm_routes = tas2552_audio_map, - .num_dapm_routes = ARRAY_SIZE(tas2552_audio_map), + .component_driver = { + .controls = tas2552_snd_controls, + .num_controls = ARRAY_SIZE(tas2552_snd_controls), + .dapm_widgets = tas2552_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas2552_dapm_widgets), + .dapm_routes = tas2552_audio_map, + .num_dapm_routes = ARRAY_SIZE(tas2552_audio_map), + }, }; static const struct regmap_config tas2552_regmap_config = { -- cgit v0.10.2 From 97bf5f33475c1d2db8a5173883acacb961f45563 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:56:24 +0000 Subject: ASoC: codec duplicated callback function goes to component on sti-sas codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c index 160d61a..7b31ee9 100644 --- a/sound/soc/codecs/sti-sas.c +++ b/sound/soc/codecs/sti-sas.c @@ -591,11 +591,11 @@ static int sti_sas_driver_probe(struct platform_device *pdev) sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].ops = drvdata->dev_data->dac_ops; /* Set dapms*/ - sti_sas_driver.dapm_widgets = drvdata->dev_data->dapm_widgets; - sti_sas_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets; + sti_sas_driver.component_driver.dapm_widgets = drvdata->dev_data->dapm_widgets; + sti_sas_driver.component_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets; - sti_sas_driver.dapm_routes = drvdata->dev_data->dapm_routes; - sti_sas_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes; + sti_sas_driver.component_driver.dapm_routes = drvdata->dev_data->dapm_routes; + sti_sas_driver.component_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes; /* Store context */ dev_set_drvdata(&pdev->dev, drvdata); -- cgit v0.10.2 From ffbb87c94acf917eccd70c635af58dee60548f3d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:56:41 +0000 Subject: ASoC: codec duplicated callback function goes to component on sta350 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index 33a4612..9644c20 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -1057,12 +1057,14 @@ static const struct snd_soc_codec_driver sta350_codec = { .remove = sta350_remove, .set_bias_level = sta350_set_bias_level, .suspend_bias_off = true, - .controls = sta350_snd_controls, - .num_controls = ARRAY_SIZE(sta350_snd_controls), - .dapm_widgets = sta350_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sta350_dapm_widgets), - .dapm_routes = sta350_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(sta350_dapm_routes), + .component_driver = { + .controls = sta350_snd_controls, + .num_controls = ARRAY_SIZE(sta350_snd_controls), + .dapm_widgets = sta350_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sta350_dapm_widgets), + .dapm_routes = sta350_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(sta350_dapm_routes), + }, }; static const struct regmap_config sta350_regmap = { -- cgit v0.10.2 From 37f112b39d8442a17ecdc7e72d42145d8cf18d37 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:57:00 +0000 Subject: ASoC: codec duplicated callback function goes to component on sta32x codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index a9844b2..0790ae8 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -991,12 +991,14 @@ static const struct snd_soc_codec_driver sta32x_codec = { .remove = sta32x_remove, .set_bias_level = sta32x_set_bias_level, .suspend_bias_off = true, - .controls = sta32x_snd_controls, - .num_controls = ARRAY_SIZE(sta32x_snd_controls), - .dapm_widgets = sta32x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sta32x_dapm_widgets), - .dapm_routes = sta32x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), + .component_driver = { + .controls = sta32x_snd_controls, + .num_controls = ARRAY_SIZE(sta32x_snd_controls), + .dapm_widgets = sta32x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sta32x_dapm_widgets), + .dapm_routes = sta32x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), + }, }; static const struct regmap_config sta32x_regmap = { -- cgit v0.10.2 From b5fce187a54808861bb24d84301a8d6d2559bca9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:57:18 +0000 Subject: ASoC: codec duplicated callback function goes to component on ssm4567 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c index 080c78e..2bb5a11 100644 --- a/sound/soc/codecs/ssm4567.c +++ b/sound/soc/codecs/ssm4567.c @@ -421,12 +421,14 @@ static struct snd_soc_codec_driver ssm4567_codec_driver = { .set_bias_level = ssm4567_set_bias_level, .idle_bias_off = true, - .controls = ssm4567_snd_controls, - .num_controls = ARRAY_SIZE(ssm4567_snd_controls), - .dapm_widgets = ssm4567_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ssm4567_dapm_widgets), - .dapm_routes = ssm4567_routes, - .num_dapm_routes = ARRAY_SIZE(ssm4567_routes), + .component_driver = { + .controls = ssm4567_snd_controls, + .num_controls = ARRAY_SIZE(ssm4567_snd_controls), + .dapm_widgets = ssm4567_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ssm4567_dapm_widgets), + .dapm_routes = ssm4567_routes, + .num_dapm_routes = ARRAY_SIZE(ssm4567_routes), + }, }; static const struct regmap_config ssm4567_regmap_config = { -- cgit v0.10.2 From 21c822343fc001b16c6865af8925c83268801644 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:57:35 +0000 Subject: ASoC: codec duplicated callback function goes to component on ssm2602 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 4452fea..993bde2 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -597,12 +597,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { .set_bias_level = ssm2602_set_bias_level, .suspend_bias_off = true, - .controls = ssm260x_snd_controls, - .num_controls = ARRAY_SIZE(ssm260x_snd_controls), - .dapm_widgets = ssm260x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ssm260x_dapm_widgets), - .dapm_routes = ssm260x_routes, - .num_dapm_routes = ARRAY_SIZE(ssm260x_routes), + .component_driver = { + .controls = ssm260x_snd_controls, + .num_controls = ARRAY_SIZE(ssm260x_snd_controls), + .dapm_widgets = ssm260x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ssm260x_dapm_widgets), + .dapm_routes = ssm260x_routes, + .num_dapm_routes = ARRAY_SIZE(ssm260x_routes), + }, }; static bool ssm2602_register_volatile(struct device *dev, unsigned int reg) -- cgit v0.10.2 From b9c990da5f258af36acc508f460356e47cd3cb14 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:57:52 +0000 Subject: ASoC: codec duplicated callback function goes to component on spdif_transmitter codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/spdif_transmitter.c b/sound/soc/codecs/spdif_transmitter.c index ef634a9..ee36753 100644 --- a/sound/soc/codecs/spdif_transmitter.c +++ b/sound/soc/codecs/spdif_transmitter.c @@ -38,10 +38,12 @@ static const struct snd_soc_dapm_route dit_routes[] = { }; static struct snd_soc_codec_driver soc_codec_spdif_dit = { - .dapm_widgets = dit_widgets, - .num_dapm_widgets = ARRAY_SIZE(dit_widgets), - .dapm_routes = dit_routes, - .num_dapm_routes = ARRAY_SIZE(dit_routes), + .component_driver = { + .dapm_widgets = dit_widgets, + .num_dapm_widgets = ARRAY_SIZE(dit_widgets), + .dapm_routes = dit_routes, + .num_dapm_routes = ARRAY_SIZE(dit_routes), + }, }; static struct snd_soc_dai_driver dit_stub_dai = { -- cgit v0.10.2 From 35eeafe3bf90d969756c5ef0f996c052ef35959d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:58:11 +0000 Subject: ASoC: codec duplicated callback function goes to component on spdif_receiver codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c index 3ec41ccb..234f87b 100644 --- a/sound/soc/codecs/spdif_receiver.c +++ b/sound/soc/codecs/spdif_receiver.c @@ -38,10 +38,12 @@ static const struct snd_soc_dapm_route dir_routes[] = { SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) static struct snd_soc_codec_driver soc_codec_spdif_dir = { - .dapm_widgets = dir_widgets, - .num_dapm_widgets = ARRAY_SIZE(dir_widgets), - .dapm_routes = dir_routes, - .num_dapm_routes = ARRAY_SIZE(dir_routes), + .component_driver = { + .dapm_widgets = dir_widgets, + .num_dapm_widgets = ARRAY_SIZE(dir_widgets), + .dapm_routes = dir_routes, + .num_dapm_routes = ARRAY_SIZE(dir_routes), + }, }; static struct snd_soc_dai_driver dir_stub_dai = { -- cgit v0.10.2 From a324dbe5201aadbd96063404162d996ec8a6ad9e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:58:28 +0000 Subject: ASoC: codec duplicated callback function goes to component on sgtl5000 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 527b759..a635bd0 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1151,12 +1151,14 @@ static struct snd_soc_codec_driver sgtl5000_driver = { .remove = sgtl5000_remove, .set_bias_level = sgtl5000_set_bias_level, .suspend_bias_off = true, - .controls = sgtl5000_snd_controls, - .num_controls = ARRAY_SIZE(sgtl5000_snd_controls), - .dapm_widgets = sgtl5000_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sgtl5000_dapm_widgets), - .dapm_routes = sgtl5000_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes), + .component_driver = { + .controls = sgtl5000_snd_controls, + .num_controls = ARRAY_SIZE(sgtl5000_snd_controls), + .dapm_widgets = sgtl5000_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sgtl5000_dapm_widgets), + .dapm_routes = sgtl5000_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes), + }, }; static const struct regmap_config sgtl5000_regmap = { -- cgit v0.10.2 From f78bc2bf1d336246c85fe5a009104fe7c3f586d9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:58:45 +0000 Subject: ASoC: codec duplicated callback function goes to component on rt5631 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 1be2bab..0e41808 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -1657,12 +1657,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5631 = { .probe = rt5631_probe, .set_bias_level = rt5631_set_bias_level, .suspend_bias_off = true, - .controls = rt5631_snd_controls, - .num_controls = ARRAY_SIZE(rt5631_snd_controls), - .dapm_widgets = rt5631_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5631_dapm_widgets), - .dapm_routes = rt5631_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5631_dapm_routes), + .component_driver = { + .controls = rt5631_snd_controls, + .num_controls = ARRAY_SIZE(rt5631_snd_controls), + .dapm_widgets = rt5631_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5631_dapm_widgets), + .dapm_routes = rt5631_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5631_dapm_routes), + }, }; static const struct i2c_device_id rt5631_i2c_id[] = { -- cgit v0.10.2 From 947cd148b43c025bab870f724cba7a17d090f1a5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:59:05 +0000 Subject: ASoC: codec duplicated callback function goes to component on rt5616 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index f527b5b..e92a149 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -1302,12 +1302,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5616 = { .resume = rt5616_resume, .set_bias_level = rt5616_set_bias_level, .idle_bias_off = true, - .controls = rt5616_snd_controls, - .num_controls = ARRAY_SIZE(rt5616_snd_controls), - .dapm_widgets = rt5616_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5616_dapm_widgets), - .dapm_routes = rt5616_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5616_dapm_routes), + .component_driver = { + .controls = rt5616_snd_controls, + .num_controls = ARRAY_SIZE(rt5616_snd_controls), + .dapm_widgets = rt5616_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5616_dapm_widgets), + .dapm_routes = rt5616_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5616_dapm_routes), + }, }; static const struct regmap_config rt5616_regmap = { -- cgit v0.10.2 From d25f113f969eb9a0ae3a61d3937a0fbfe7ecdbdd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:59:23 +0000 Subject: ASoC: codec duplicated callback function goes to component on pcm512x codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 047c489..72b19e6 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -1348,12 +1348,14 @@ static struct snd_soc_codec_driver pcm512x_codec_driver = { .set_bias_level = pcm512x_set_bias_level, .idle_bias_off = true, - .controls = pcm512x_controls, - .num_controls = ARRAY_SIZE(pcm512x_controls), - .dapm_widgets = pcm512x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets), - .dapm_routes = pcm512x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes), + .component_driver = { + .controls = pcm512x_controls, + .num_controls = ARRAY_SIZE(pcm512x_controls), + .dapm_widgets = pcm512x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets), + .dapm_routes = pcm512x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes), + }, }; static const struct regmap_range_cfg pcm512x_range = { -- cgit v0.10.2 From d4fff1ba4768dc7b8dd09db0eee19c1ff098ee60 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:59:41 +0000 Subject: ASoC: codec duplicated callback function goes to component on pcm3168a codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index 992a77e..39bc02d 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -599,12 +599,14 @@ EXPORT_SYMBOL_GPL(pcm3168a_regmap); static const struct snd_soc_codec_driver pcm3168a_driver = { .idle_bias_off = true, - .controls = pcm3168a_snd_controls, - .num_controls = ARRAY_SIZE(pcm3168a_snd_controls), - .dapm_widgets = pcm3168a_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pcm3168a_dapm_widgets), - .dapm_routes = pcm3168a_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pcm3168a_dapm_routes) + .component_driver = { + .controls = pcm3168a_snd_controls, + .num_controls = ARRAY_SIZE(pcm3168a_snd_controls), + .dapm_widgets = pcm3168a_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm3168a_dapm_widgets), + .dapm_routes = pcm3168a_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm3168a_dapm_routes) + }, }; int pcm3168a_probe(struct device *dev, struct regmap *regmap) -- cgit v0.10.2 From 98773a87e83dfd81c77418f2d0f19a63e7476bac Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 08:59:59 +0000 Subject: ASoC: codec duplicated callback function goes to component on pcm179x codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/pcm179x.c b/sound/soc/codecs/pcm179x.c index 88fbdd1..b813a15 100644 --- a/sound/soc/codecs/pcm179x.c +++ b/sound/soc/codecs/pcm179x.c @@ -206,12 +206,14 @@ const struct regmap_config pcm179x_regmap_config = { EXPORT_SYMBOL_GPL(pcm179x_regmap_config); static struct snd_soc_codec_driver soc_codec_dev_pcm179x = { - .controls = pcm179x_controls, - .num_controls = ARRAY_SIZE(pcm179x_controls), - .dapm_widgets = pcm179x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pcm179x_dapm_widgets), - .dapm_routes = pcm179x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pcm179x_dapm_routes), + .component_driver = { + .controls = pcm179x_controls, + .num_controls = ARRAY_SIZE(pcm179x_controls), + .dapm_widgets = pcm179x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm179x_dapm_widgets), + .dapm_routes = pcm179x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm179x_dapm_routes), + }, }; int pcm179x_common_init(struct device *dev, struct regmap *regmap) -- cgit v0.10.2 From a005fd746b4a257ff650c4ac9651111a5d580abe Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:00:18 +0000 Subject: ASoC: codec duplicated callback function goes to component on pcm1681 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index 33e1fc2d..0b14efa 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c @@ -289,12 +289,14 @@ static const struct regmap_config pcm1681_regmap = { }; static struct snd_soc_codec_driver soc_codec_dev_pcm1681 = { - .controls = pcm1681_controls, - .num_controls = ARRAY_SIZE(pcm1681_controls), - .dapm_widgets = pcm1681_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pcm1681_dapm_widgets), - .dapm_routes = pcm1681_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pcm1681_dapm_routes), + .component_driver = { + .controls = pcm1681_controls, + .num_controls = ARRAY_SIZE(pcm1681_controls), + .dapm_widgets = pcm1681_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm1681_dapm_widgets), + .dapm_routes = pcm1681_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm1681_dapm_routes), + }, }; static const struct i2c_device_id pcm1681_i2c_id[] = { -- cgit v0.10.2 From 750a33e6173c5ac5f202f15bb092eb4965f4547d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:00:35 +0000 Subject: ASoC: codec duplicated callback function goes to component on max9860 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c index 68074c9..499bdbf 100644 --- a/sound/soc/codecs/max9860.c +++ b/sound/soc/codecs/max9860.c @@ -538,12 +538,14 @@ static struct snd_soc_codec_driver max9860_codec_driver = { .set_bias_level = max9860_set_bias_level, .idle_bias_off = true, - .controls = max9860_controls, - .num_controls = ARRAY_SIZE(max9860_controls), - .dapm_widgets = max9860_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max9860_dapm_widgets), - .dapm_routes = max9860_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(max9860_dapm_routes), + .component_driver = { + .controls = max9860_controls, + .num_controls = ARRAY_SIZE(max9860_controls), + .dapm_widgets = max9860_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max9860_dapm_widgets), + .dapm_routes = max9860_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(max9860_dapm_routes), + }, }; #ifdef CONFIG_PM -- cgit v0.10.2 From f410a81d4d5fd4d0e9477c5d7ebd4e6712ed4c42 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:00:54 +0000 Subject: ASoC: codec duplicated callback function goes to component on inno_rk3036 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c index 9b6e884..b918ba5 100644 --- a/sound/soc/codecs/inno_rk3036.c +++ b/sound/soc/codecs/inno_rk3036.c @@ -380,12 +380,14 @@ static struct snd_soc_codec_driver rk3036_codec_driver = { .probe = rk3036_codec_probe, .remove = rk3036_codec_remove, .set_bias_level = rk3036_codec_set_bias_level, - .controls = rk3036_codec_dapm_controls, - .num_controls = ARRAY_SIZE(rk3036_codec_dapm_controls), - .dapm_routes = rk3036_codec_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rk3036_codec_dapm_routes), - .dapm_widgets = rk3036_codec_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rk3036_codec_dapm_widgets), + .component_driver = { + .controls = rk3036_codec_dapm_controls, + .num_controls = ARRAY_SIZE(rk3036_codec_dapm_controls), + .dapm_routes = rk3036_codec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rk3036_codec_dapm_routes), + .dapm_widgets = rk3036_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rk3036_codec_dapm_widgets), + }, }; static const struct regmap_config rk3036_codec_regmap_config = { -- cgit v0.10.2 From 054ea6c9e3d240a6679458c6e6e1ecf4031271ea Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:01:11 +0000 Subject: ASoC: codec duplicated callback function goes to component on gtm601 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/gtm601.c b/sound/soc/codecs/gtm601.c index 0b80052..926b1a4 100644 --- a/sound/soc/codecs/gtm601.c +++ b/sound/soc/codecs/gtm601.c @@ -52,10 +52,12 @@ static struct snd_soc_dai_driver gtm601_dai = { }; static const struct snd_soc_codec_driver soc_codec_dev_gtm601 = { - .dapm_widgets = gtm601_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(gtm601_dapm_widgets), - .dapm_routes = gtm601_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(gtm601_dapm_routes), + .component_driver = { + .dapm_widgets = gtm601_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(gtm601_dapm_widgets), + .dapm_routes = gtm601_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(gtm601_dapm_routes), + }, }; static int gtm601_platform_probe(struct platform_device *pdev) -- cgit v0.10.2 From 87869e4fadcaf6f4eac48bfb4a417720af8325a0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:01:30 +0000 Subject: ASoC: codec duplicated callback function goes to component on es8328 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index 2086d71..37722194 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -823,12 +823,14 @@ static struct snd_soc_codec_driver es8328_codec_driver = { .set_bias_level = es8328_set_bias_level, .suspend_bias_off = true, - .controls = es8328_snd_controls, - .num_controls = ARRAY_SIZE(es8328_snd_controls), - .dapm_widgets = es8328_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(es8328_dapm_widgets), - .dapm_routes = es8328_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(es8328_dapm_routes), + .component_driver = { + .controls = es8328_snd_controls, + .num_controls = ARRAY_SIZE(es8328_snd_controls), + .dapm_widgets = es8328_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(es8328_dapm_widgets), + .dapm_routes = es8328_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(es8328_dapm_routes), + }, }; int es8328_probe(struct device *dev, struct regmap *regmap) -- cgit v0.10.2 From cbe5cdbf0e07ea563def6dda7acc6d95817949a5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:01:49 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs53l30 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index 2c0d9c4..e244e08 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -897,13 +897,14 @@ static struct snd_soc_codec_driver cs53l30_driver = { .set_bias_level = cs53l30_set_bias_level, .idle_bias_off = true, - .dapm_widgets = cs53l30_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs53l30_dapm_widgets), - .dapm_routes = cs53l30_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(cs53l30_dapm_routes), - - .controls = cs53l30_snd_controls, - .num_controls = ARRAY_SIZE(cs53l30_snd_controls), + .component_driver = { + .controls = cs53l30_snd_controls, + .num_controls = ARRAY_SIZE(cs53l30_snd_controls), + .dapm_widgets = cs53l30_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs53l30_dapm_widgets), + .dapm_routes = cs53l30_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs53l30_dapm_routes), + }, }; static struct regmap_config cs53l30_regmap = { -- cgit v0.10.2 From b9835ec4a7ebf508cea5e2b5955b830db0fffc5f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:02:09 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs4349 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c index 0ac8fc5..231ca93 100644 --- a/sound/soc/codecs/cs4349.c +++ b/sound/soc/codecs/cs4349.c @@ -256,13 +256,14 @@ static struct snd_soc_dai_driver cs4349_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_cs4349 = { - .controls = cs4349_snd_controls, - .num_controls = ARRAY_SIZE(cs4349_snd_controls), - - .dapm_widgets = cs4349_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs4349_dapm_widgets), - .dapm_routes = cs4349_routes, - .num_dapm_routes = ARRAY_SIZE(cs4349_routes), + .component_driver = { + .controls = cs4349_snd_controls, + .num_controls = ARRAY_SIZE(cs4349_snd_controls), + .dapm_widgets = cs4349_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs4349_dapm_widgets), + .dapm_routes = cs4349_routes, + .num_dapm_routes = ARRAY_SIZE(cs4349_routes), + }, }; static const struct regmap_config cs4349_regmap = { -- cgit v0.10.2 From 4d7ee73707ec0b3759039a1d573f7829f94046e7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:02:28 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs42xx8 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index 1179101..b4d8737 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -411,12 +411,14 @@ static const struct snd_soc_codec_driver cs42xx8_driver = { .probe = cs42xx8_codec_probe, .idle_bias_off = true, - .controls = cs42xx8_snd_controls, - .num_controls = ARRAY_SIZE(cs42xx8_snd_controls), - .dapm_widgets = cs42xx8_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs42xx8_dapm_widgets), - .dapm_routes = cs42xx8_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(cs42xx8_dapm_routes), + .component_driver = { + .controls = cs42xx8_snd_controls, + .num_controls = ARRAY_SIZE(cs42xx8_snd_controls), + .dapm_widgets = cs42xx8_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42xx8_dapm_widgets), + .dapm_routes = cs42xx8_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs42xx8_dapm_routes), + }, }; const struct cs42xx8_driver_data cs42448_data = { -- cgit v0.10.2 From 951cd7e6ffda4dc86ed6fb6ff10e0ca8f3b67c2b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:02:48 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs42l73 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 42a8fd4..01b573a 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -1257,13 +1257,14 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs42l73 = { .set_bias_level = cs42l73_set_bias_level, .suspend_bias_off = true, - .dapm_widgets = cs42l73_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets), - .dapm_routes = cs42l73_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs42l73_audio_map), - - .controls = cs42l73_snd_controls, - .num_controls = ARRAY_SIZE(cs42l73_snd_controls), + .component_driver = { + .controls = cs42l73_snd_controls, + .num_controls = ARRAY_SIZE(cs42l73_snd_controls), + .dapm_widgets = cs42l73_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets), + .dapm_routes = cs42l73_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs42l73_audio_map), + }, }; static const struct regmap_config cs42l73_regmap = { -- cgit v0.10.2 From 561828f821c95c73177e5291e5831b909b400450 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:03:06 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs42l56 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index eec1ff8..54c1768 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -1121,13 +1121,14 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs42l56 = { .set_bias_level = cs42l56_set_bias_level, .suspend_bias_off = true, - .dapm_widgets = cs42l56_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs42l56_dapm_widgets), - .dapm_routes = cs42l56_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs42l56_audio_map), - - .controls = cs42l56_snd_controls, - .num_controls = ARRAY_SIZE(cs42l56_snd_controls), + .component_driver = { + .controls = cs42l56_snd_controls, + .num_controls = ARRAY_SIZE(cs42l56_snd_controls), + .dapm_widgets = cs42l56_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42l56_dapm_widgets), + .dapm_routes = cs42l56_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs42l56_audio_map), + }, }; static const struct regmap_config cs42l56_regmap = { -- cgit v0.10.2 From 59aad18c027669bccfe6b3334c03dbec42c74a7d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:03:26 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs42l52 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 47b97fc..0d9c4a5 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -1056,13 +1056,14 @@ static const struct snd_soc_codec_driver soc_codec_dev_cs42l52 = { .set_bias_level = cs42l52_set_bias_level, .suspend_bias_off = true, - .dapm_widgets = cs42l52_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs42l52_dapm_widgets), - .dapm_routes = cs42l52_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs42l52_audio_map), - - .controls = cs42l52_snd_controls, - .num_controls = ARRAY_SIZE(cs42l52_snd_controls), + .component_driver = { + .controls = cs42l52_snd_controls, + .num_controls = ARRAY_SIZE(cs42l52_snd_controls), + .dapm_widgets = cs42l52_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42l52_dapm_widgets), + .dapm_routes = cs42l52_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs42l52_audio_map), + }, }; /* Current and threshold powerup sequence Pg37 */ -- cgit v0.10.2 From 9353d25dc8442784b1bc626cb2741965a1f53dad Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:03:45 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs42l51 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 35488f1..96cfe38 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -507,12 +507,14 @@ static int cs42l51_codec_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { .probe = cs42l51_codec_probe, - .controls = cs42l51_snd_controls, - .num_controls = ARRAY_SIZE(cs42l51_snd_controls), - .dapm_widgets = cs42l51_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs42l51_dapm_widgets), - .dapm_routes = cs42l51_routes, - .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), + .component_driver = { + .controls = cs42l51_snd_controls, + .num_controls = ARRAY_SIZE(cs42l51_snd_controls), + .dapm_widgets = cs42l51_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42l51_dapm_widgets), + .dapm_routes = cs42l51_routes, + .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), + }, }; const struct regmap_config cs42l51_regmap = { -- cgit v0.10.2 From 228a57aea80b5dfc4624ad29952a8168317a1884 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:04:04 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs4271 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 0c0010b..8c0f3b8 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -645,12 +645,14 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { .suspend = cs4271_soc_suspend, .resume = cs4271_soc_resume, - .controls = cs4271_snd_controls, - .num_controls = ARRAY_SIZE(cs4271_snd_controls), - .dapm_widgets = cs4271_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs4271_dapm_widgets), - .dapm_routes = cs4271_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes), + .component_driver = { + .controls = cs4271_snd_controls, + .num_controls = ARRAY_SIZE(cs4271_snd_controls), + .dapm_widgets = cs4271_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs4271_dapm_widgets), + .dapm_routes = cs4271_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes), + }, }; static int cs4271_common_probe(struct device *dev, -- cgit v0.10.2 From f80894338e8793821f96db179cfc349d8057ffbc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:04:25 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs4270 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index e07807d..18baea2 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -617,12 +617,14 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { .suspend = cs4270_soc_suspend, .resume = cs4270_soc_resume, - .controls = cs4270_snd_controls, - .num_controls = ARRAY_SIZE(cs4270_snd_controls), - .dapm_widgets = cs4270_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs4270_dapm_widgets), - .dapm_routes = cs4270_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(cs4270_dapm_routes), + .component_driver = { + .controls = cs4270_snd_controls, + .num_controls = ARRAY_SIZE(cs4270_snd_controls), + .dapm_widgets = cs4270_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs4270_dapm_widgets), + .dapm_routes = cs4270_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs4270_dapm_routes), + }, }; /* -- cgit v0.10.2 From 9f9dc779bca7eb24f0afc8929bf89a4c5cccccea Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:04:43 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs4265 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 55db19d..fd966bb 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c @@ -547,13 +547,14 @@ static struct snd_soc_dai_driver cs4265_dai[] = { static const struct snd_soc_codec_driver soc_codec_cs4265 = { .set_bias_level = cs4265_set_bias_level, - .dapm_widgets = cs4265_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs4265_dapm_widgets), - .dapm_routes = cs4265_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs4265_audio_map), - - .controls = cs4265_snd_controls, - .num_controls = ARRAY_SIZE(cs4265_snd_controls), + .component_driver = { + .controls = cs4265_snd_controls, + .num_controls = ARRAY_SIZE(cs4265_snd_controls), + .dapm_widgets = cs4265_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs4265_dapm_widgets), + .dapm_routes = cs4265_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs4265_audio_map), + }, }; static const struct regmap_config cs4265_regmap = { -- cgit v0.10.2 From 133987d66418f09c1d9b010a4a6ae67fdd2d6214 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:05:00 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs35l33 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c index 6f9c1ad..6df29fa 100644 --- a/sound/soc/codecs/cs35l33.c +++ b/sound/soc/codecs/cs35l33.c @@ -837,13 +837,14 @@ static struct snd_soc_codec_driver soc_codec_dev_cs35l33 = { .set_bias_level = cs35l33_set_bias_level, .set_sysclk = cs35l33_codec_set_sysclk, - .dapm_widgets = cs35l33_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs35l33_dapm_widgets), - .dapm_routes = cs35l33_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs35l33_audio_map), - .controls = cs35l33_snd_controls, - .num_controls = ARRAY_SIZE(cs35l33_snd_controls), - + .component_driver = { + .controls = cs35l33_snd_controls, + .num_controls = ARRAY_SIZE(cs35l33_snd_controls), + .dapm_widgets = cs35l33_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs35l33_dapm_widgets), + .dapm_routes = cs35l33_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs35l33_audio_map), + }, .idle_bias_off = true, }; -- cgit v0.10.2 From 1728f9d11f234df10c392f41a0ec80be287c4567 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:05:18 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs35l32 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index 287d137..7e98062 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c @@ -231,13 +231,14 @@ static int cs35l32_codec_set_sysclk(struct snd_soc_codec *codec, static const struct snd_soc_codec_driver soc_codec_dev_cs35l32 = { .set_sysclk = cs35l32_codec_set_sysclk, - .dapm_widgets = cs35l32_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs35l32_dapm_widgets), - .dapm_routes = cs35l32_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs35l32_audio_map), - - .controls = cs35l32_snd_controls, - .num_controls = ARRAY_SIZE(cs35l32_snd_controls), + .component_driver = { + .controls = cs35l32_snd_controls, + .num_controls = ARRAY_SIZE(cs35l32_snd_controls), + .dapm_widgets = cs35l32_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs35l32_dapm_widgets), + .dapm_routes = cs35l32_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs35l32_audio_map), + }, }; /* Current and threshold powerup sequence Pg37 in datasheet */ -- cgit v0.10.2 From 24fe48d78be574dcd43bc5156f47d37757cfffbd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:05:36 +0000 Subject: ASoC: codec duplicated callback function goes to component on bt-sco codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c index 2a8d0ee..8014e69 100644 --- a/sound/soc/codecs/bt-sco.c +++ b/sound/soc/codecs/bt-sco.c @@ -63,10 +63,12 @@ static struct snd_soc_dai_driver bt_sco_dai[] = { }; static struct snd_soc_codec_driver soc_codec_dev_bt_sco = { - .dapm_widgets = bt_sco_widgets, - .num_dapm_widgets = ARRAY_SIZE(bt_sco_widgets), - .dapm_routes = bt_sco_routes, - .num_dapm_routes = ARRAY_SIZE(bt_sco_routes), + .component_driver = { + .dapm_widgets = bt_sco_widgets, + .num_dapm_widgets = ARRAY_SIZE(bt_sco_widgets), + .dapm_routes = bt_sco_routes, + .num_dapm_routes = ARRAY_SIZE(bt_sco_routes), + }, }; static int bt_sco_probe(struct platform_device *pdev) -- cgit v0.10.2 From 5bc4f738018ddcb86b7ac5894d4a9e416dbb65b0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:05:56 +0000 Subject: ASoC: codec duplicated callback function goes to component on ak5386 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak5386.c b/sound/soc/codecs/ak5386.c index afa9536..0ef2df2 100644 --- a/sound/soc/codecs/ak5386.c +++ b/sound/soc/codecs/ak5386.c @@ -74,10 +74,12 @@ static struct snd_soc_codec_driver soc_codec_ak5386 = { .remove = ak5386_soc_remove, .suspend = ak5386_soc_suspend, .resume = ak5386_soc_resume, - .dapm_widgets = ak5386_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets), - .dapm_routes = ak5386_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ak5386_dapm_routes), + .component_driver = { + .dapm_widgets = ak5386_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets), + .dapm_routes = ak5386_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ak5386_dapm_routes), + }, }; static int ak5386_set_dai_fmt(struct snd_soc_dai *codec_dai, -- cgit v0.10.2 From 3a6ce00e2a5b85d558f051b709be9d1952bd7461 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:06:14 +0000 Subject: ASoC: codec duplicated callback function goes to component on ak4642 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index cc941d6..2609f95 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -555,12 +555,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { .suspend = ak4642_suspend, .resume = ak4642_resume, .set_bias_level = ak4642_set_bias_level, - .controls = ak4642_snd_controls, - .num_controls = ARRAY_SIZE(ak4642_snd_controls), - .dapm_widgets = ak4642_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets), - .dapm_routes = ak4642_intercon, - .num_dapm_routes = ARRAY_SIZE(ak4642_intercon), + .component_driver = { + .controls = ak4642_snd_controls, + .num_controls = ARRAY_SIZE(ak4642_snd_controls), + .dapm_widgets = ak4642_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets), + .dapm_routes = ak4642_intercon, + .num_dapm_routes = ARRAY_SIZE(ak4642_intercon), + }, }; static const struct regmap_config ak4642_regmap = { -- cgit v0.10.2 From beb84f75c4d9d069172f32543544d757d59e114b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:06:34 +0000 Subject: ASoC: codec duplicated callback function goes to component on ak4613 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index 97798d2..e819dd8 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -458,12 +458,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4613 = { .suspend = ak4613_suspend, .resume = ak4613_resume, .set_bias_level = ak4613_set_bias_level, - .controls = ak4613_snd_controls, - .num_controls = ARRAY_SIZE(ak4613_snd_controls), - .dapm_widgets = ak4613_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4613_dapm_widgets), - .dapm_routes = ak4613_intercon, - .num_dapm_routes = ARRAY_SIZE(ak4613_intercon), + .component_driver = { + .controls = ak4613_snd_controls, + .num_controls = ARRAY_SIZE(ak4613_snd_controls), + .dapm_widgets = ak4613_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4613_dapm_widgets), + .dapm_routes = ak4613_intercon, + .num_dapm_routes = ARRAY_SIZE(ak4613_intercon), + }, }; static void ak4613_parse_of(struct ak4613_priv *priv, -- cgit v0.10.2 From 08c0ca5ebd361420d40a4c6970e3dd1a4c64306a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:06:52 +0000 Subject: ASoC: codec duplicated callback function goes to component on ak4554 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4554.c b/sound/soc/codecs/ak4554.c index 298dedc..b92c548 100644 --- a/sound/soc/codecs/ak4554.c +++ b/sound/soc/codecs/ak4554.c @@ -65,10 +65,12 @@ static struct snd_soc_dai_driver ak4554_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_ak4554 = { - .dapm_widgets = ak4554_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4554_dapm_widgets), - .dapm_routes = ak4554_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ak4554_dapm_routes), + .component_driver = { + .dapm_widgets = ak4554_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4554_dapm_widgets), + .dapm_routes = ak4554_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ak4554_dapm_routes), + }, }; static int ak4554_soc_probe(struct platform_device *pdev) -- cgit v0.10.2 From 1cd5e361736664302285850a327d52ef7f70e74a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:07:11 +0000 Subject: ASoC: codec duplicated callback function goes to component on ak4104 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index 595d02d..bdca879 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c @@ -245,10 +245,12 @@ static struct snd_soc_codec_driver soc_codec_device_ak4104 = { .suspend = ak4104_soc_suspend, .resume = ak4104_soc_resume, - .dapm_widgets = ak4104_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4104_dapm_widgets), - .dapm_routes = ak4104_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ak4104_dapm_routes), + .component_driver = { + .dapm_widgets = ak4104_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4104_dapm_widgets), + .dapm_routes = ak4104_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ak4104_dapm_routes), + } }; static const struct regmap_config ak4104_regmap = { -- cgit v0.10.2 From 7d9477e8e3f2ef6c8ca8103cca6fe9dbef300cd4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:07:29 +0000 Subject: ASoC: codec duplicated callback function goes to component on adau7002 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/adau7002.c b/sound/soc/codecs/adau7002.c index 9df72c6..6384c54 100644 --- a/sound/soc/codecs/adau7002.c +++ b/sound/soc/codecs/adau7002.c @@ -39,10 +39,12 @@ static struct snd_soc_dai_driver adau7002_dai = { }; static const struct snd_soc_codec_driver adau7002_codec_driver = { - .dapm_widgets = adau7002_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau7002_widgets), - .dapm_routes = adau7002_routes, - .num_dapm_routes = ARRAY_SIZE(adau7002_routes), + .component_driver = { + .dapm_widgets = adau7002_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau7002_widgets), + .dapm_routes = adau7002_routes, + .num_dapm_routes = ARRAY_SIZE(adau7002_routes), + }, }; static int adau7002_probe(struct platform_device *pdev) -- cgit v0.10.2 From 637591ecb4468c55489654b698319adb9fbfbe36 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:07:47 +0000 Subject: ASoC: codec duplicated callback function goes to component on adau1701 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index de53c0d..3bad1bc 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c @@ -765,13 +765,14 @@ static struct snd_soc_codec_driver adau1701_codec_drv = { .set_bias_level = adau1701_set_bias_level, .idle_bias_off = true, - .controls = adau1701_controls, - .num_controls = ARRAY_SIZE(adau1701_controls), - .dapm_widgets = adau1701_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau1701_dapm_widgets), - .dapm_routes = adau1701_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), - + .component_driver = { + .controls = adau1701_controls, + .num_controls = ARRAY_SIZE(adau1701_controls), + .dapm_widgets = adau1701_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1701_dapm_widgets), + .dapm_routes = adau1701_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), + }, .set_sysclk = adau1701_set_sysclk, }; -- cgit v0.10.2 From eab73d01f6e3cb484280807be570e75734fca696 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:08:06 +0000 Subject: ASoC: codec duplicated callback function goes to component on ac97 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 5b3224c..f7f04c6 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -117,10 +117,12 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = { .suspend = ac97_soc_suspend, .resume = ac97_soc_resume, - .dapm_widgets = ac97_widgets, - .num_dapm_widgets = ARRAY_SIZE(ac97_widgets), - .dapm_routes = ac97_routes, - .num_dapm_routes = ARRAY_SIZE(ac97_routes), + .component_driver = { + .dapm_widgets = ac97_widgets, + .num_dapm_widgets = ARRAY_SIZE(ac97_widgets), + .dapm_routes = ac97_routes, + .num_dapm_routes = ARRAY_SIZE(ac97_routes), + }, }; static int ac97_probe(struct platform_device *pdev) -- cgit v0.10.2 From 05a0d2d497f91aa9657842484043c08e5aed8eb3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:08:24 +0000 Subject: ASoC: codec duplicated callback function goes to component on ad1980 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 9ef20db..b7c1b9f 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -299,12 +299,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { .probe = ad1980_soc_probe, .remove = ad1980_soc_remove, - .controls = ad1980_snd_ac97_controls, - .num_controls = ARRAY_SIZE(ad1980_snd_ac97_controls), - .dapm_widgets = ad1980_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets), - .dapm_routes = ad1980_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ad1980_dapm_routes), + .component_driver = { + .controls = ad1980_snd_ac97_controls, + .num_controls = ARRAY_SIZE(ad1980_snd_ac97_controls), + .dapm_widgets = ad1980_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets), + .dapm_routes = ad1980_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ad1980_dapm_routes), + }, }; static int ad1980_probe(struct platform_device *pdev) -- cgit v0.10.2 From f95b81387cac798cf790b47cbb676e0fd8f87a6d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:08:46 +0000 Subject: ASoC: codec duplicated callback function goes to component on ad73311 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index a9400ae..3e358a4 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c @@ -55,10 +55,12 @@ static struct snd_soc_dai_driver ad73311_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_ad73311 = { - .dapm_widgets = ad73311_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ad73311_dapm_widgets), - .dapm_routes = ad73311_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ad73311_dapm_routes), + .component_driver = { + .dapm_widgets = ad73311_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ad73311_dapm_widgets), + .dapm_routes = ad73311_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ad73311_dapm_routes), + }, }; static int ad73311_probe(struct platform_device *pdev) -- cgit v0.10.2 From adfe0976aadb618acf130564d39e39ec0b0a5b90 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:09:04 +0000 Subject: ASoC: codec duplicated callback function goes to component on adau1373 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 1556b36..8fa9045 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -1466,12 +1466,14 @@ static struct snd_soc_codec_driver adau1373_codec_driver = { .set_pll = adau1373_set_pll, - .controls = adau1373_controls, - .num_controls = ARRAY_SIZE(adau1373_controls), - .dapm_widgets = adau1373_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau1373_dapm_widgets), - .dapm_routes = adau1373_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes), + .component_driver = { + .controls = adau1373_controls, + .num_controls = ARRAY_SIZE(adau1373_controls), + .dapm_widgets = adau1373_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1373_dapm_widgets), + .dapm_routes = adau1373_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes), + }, }; static int adau1373_i2c_probe(struct i2c_client *client, -- cgit v0.10.2 From 8a04dd67a380384549f6553049fd6c69ae0447ee Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:09:21 +0000 Subject: ASoC: codec duplicated callback function goes to component on ad1836 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index e2ce6c4..a478239 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -327,12 +327,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { .suspend = ad1836_suspend, .resume = ad1836_resume, - .controls = ad183x_controls, - .num_controls = ARRAY_SIZE(ad183x_controls), - .dapm_widgets = ad183x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ad183x_dapm_widgets), - .dapm_routes = ad183x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), + .component_driver = { + .controls = ad183x_controls, + .num_controls = ARRAY_SIZE(ad183x_controls), + .dapm_widgets = ad183x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ad183x_dapm_widgets), + .dapm_routes = ad183x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), + }, }; static const struct reg_default ad1836_reg_defaults[] = { -- cgit v0.10.2 From 1d09e8c35626ea0b899c1cd1922d8802bd169868 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:09:43 +0000 Subject: ASoC: codec duplicated callback function goes to component on ad193x codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 3a3f3f2..d643557 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -410,12 +410,14 @@ static int ad193x_codec_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_ad193x = { .probe = ad193x_codec_probe, - .controls = ad193x_snd_controls, - .num_controls = ARRAY_SIZE(ad193x_snd_controls), - .dapm_widgets = ad193x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ad193x_dapm_widgets), - .dapm_routes = audio_paths, - .num_dapm_routes = ARRAY_SIZE(audio_paths), + .component_driver = { + .controls = ad193x_snd_controls, + .num_controls = ARRAY_SIZE(ad193x_snd_controls), + .dapm_widgets = ad193x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ad193x_dapm_widgets), + .dapm_routes = audio_paths, + .num_dapm_routes = ARRAY_SIZE(audio_paths), + }, }; const struct regmap_config ad193x_regmap_config = { -- cgit v0.10.2 From 33398b509aafe936ec57cb1023f7ff1ba9e48586 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:10:02 +0000 Subject: ASoC: codec duplicated callback function goes to component on 88pm860x-codec codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index e8bed6b..b013a4c 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -1361,12 +1361,14 @@ static struct snd_soc_codec_driver soc_codec_dev_pm860x = { .set_bias_level = pm860x_set_bias_level, .get_regmap = pm860x_get_regmap, - .controls = pm860x_snd_controls, - .num_controls = ARRAY_SIZE(pm860x_snd_controls), - .dapm_widgets = pm860x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pm860x_dapm_widgets), - .dapm_routes = pm860x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pm860x_dapm_routes), + .component_driver = { + .controls = pm860x_snd_controls, + .num_controls = ARRAY_SIZE(pm860x_snd_controls), + .dapm_widgets = pm860x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pm860x_dapm_widgets), + .dapm_routes = pm860x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pm860x_dapm_routes), + }, }; static int pm860x_codec_probe(struct platform_device *pdev) -- cgit v0.10.2 From 69295df090a03e406c54ca0dbd67a76355773138 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:10:21 +0000 Subject: ASoC: codec duplicated callback function goes to component on atmel-classd codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index 6d9b8b4..89ac5f5 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -308,9 +308,11 @@ static struct regmap *atmel_classd_codec_get_remap(struct device *dev) static struct snd_soc_codec_driver soc_codec_dev_classd = { .probe = atmel_classd_codec_probe, - .controls = atmel_classd_snd_controls, - .num_controls = ARRAY_SIZE(atmel_classd_snd_controls), .get_regmap = atmel_classd_codec_get_remap, + .component_driver = { + .controls = atmel_classd_snd_controls, + .num_controls = ARRAY_SIZE(atmel_classd_snd_controls), + }, }; /* codec dai component */ -- cgit v0.10.2 From 72bb3cdf93b1718c9a540fb157890d8639633eca Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:10:41 +0000 Subject: ASoC: codec duplicated callback function goes to component on atmel-pdmic codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index 5f56da6..2a3a41f 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -357,8 +357,10 @@ static int atmel_pdmic_codec_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_pdmic = { .probe = atmel_pdmic_codec_probe, - .controls = atmel_pdmic_snd_controls, - .num_controls = ARRAY_SIZE(atmel_pdmic_snd_controls), + .component_driver = { + .controls = atmel_pdmic_snd_controls, + .num_controls = ARRAY_SIZE(atmel_pdmic_snd_controls), + }, }; /* codec dai component */ -- cgit v0.10.2 From ed135dd69556c70fb780985c536cc650e7f7b450 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:10:59 +0000 Subject: ASoC: codec duplicated callback function goes to component on ab8500-codec codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 2fc8915..3056487 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2525,12 +2525,14 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver ab8500_codec_driver = { .probe = ab8500_codec_probe, - .controls = ab8500_ctrls, - .num_controls = ARRAY_SIZE(ab8500_ctrls), - .dapm_widgets = ab8500_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ab8500_dapm_widgets), - .dapm_routes = ab8500_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ab8500_dapm_routes), + .component_driver = { + .controls = ab8500_ctrls, + .num_controls = ARRAY_SIZE(ab8500_ctrls), + .dapm_widgets = ab8500_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ab8500_dapm_widgets), + .dapm_routes = ab8500_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ab8500_dapm_routes), + }, }; static int ab8500_codec_driver_probe(struct platform_device *pdev) -- cgit v0.10.2 From c30ca68b9a8625e93c218374bad63c6babe85e3a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:11:18 +0000 Subject: ASoC: codec duplicated callback function goes to component on adau1761 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index b95d29d..3bc3cc5 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c @@ -719,12 +719,14 @@ static const struct snd_soc_codec_driver adau1761_codec_driver = { .set_bias_level = adau1761_set_bias_level, .suspend_bias_off = true, - .controls = adau1761_controls, - .num_controls = ARRAY_SIZE(adau1761_controls), - .dapm_widgets = adau1x61_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau1x61_dapm_widgets), - .dapm_routes = adau1x61_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adau1x61_dapm_routes), + .component_driver = { + .controls = adau1761_controls, + .num_controls = ARRAY_SIZE(adau1761_controls), + .dapm_widgets = adau1x61_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1x61_dapm_widgets), + .dapm_routes = adau1x61_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1x61_dapm_routes), + }, }; #define ADAU1761_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ -- cgit v0.10.2 From dbd33b16d68bf3ff93fb7965a2e87878ee091e94 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:11:36 +0000 Subject: ASoC: codec duplicated callback function goes to component on adau1781 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c index bc1bb56..546071c 100644 --- a/sound/soc/codecs/adau1781.c +++ b/sound/soc/codecs/adau1781.c @@ -432,12 +432,14 @@ static const struct snd_soc_codec_driver adau1781_codec_driver = { .set_bias_level = adau1781_set_bias_level, .suspend_bias_off = true, - .controls = adau1781_controls, - .num_controls = ARRAY_SIZE(adau1781_controls), - .dapm_widgets = adau1781_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau1781_dapm_widgets), - .dapm_routes = adau1781_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adau1781_dapm_routes), + .component_driver = { + .controls = adau1781_controls, + .num_controls = ARRAY_SIZE(adau1781_controls), + .dapm_widgets = adau1781_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1781_dapm_widgets), + .dapm_routes = adau1781_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1781_dapm_routes), + }, }; #define ADAU1781_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ -- cgit v0.10.2 From ef611e1f4ad7c0355a2aa97660210bfa4a4472c4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:11:55 +0000 Subject: ASoC: codec duplicated callback function goes to component on adau1977 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c index 9bdd15f..b319db6 100644 --- a/sound/soc/codecs/adau1977.c +++ b/sound/soc/codecs/adau1977.c @@ -873,12 +873,14 @@ static struct snd_soc_codec_driver adau1977_codec_driver = { .set_sysclk = adau1977_set_sysclk, .idle_bias_off = true, - .controls = adau1977_snd_controls, - .num_controls = ARRAY_SIZE(adau1977_snd_controls), - .dapm_widgets = adau1977_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau1977_dapm_widgets), - .dapm_routes = adau1977_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adau1977_dapm_routes), + .component_driver = { + .controls = adau1977_snd_controls, + .num_controls = ARRAY_SIZE(adau1977_snd_controls), + .dapm_widgets = adau1977_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1977_dapm_widgets), + .dapm_routes = adau1977_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1977_dapm_routes), + }, }; static int adau1977_setup_micbias(struct adau1977 *adau1977) -- cgit v0.10.2 From c5946fcf84bf71f4c0bc08a6bce3781e6b281737 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:12:11 +0000 Subject: ASoC: codec duplicated callback function goes to component on adav80x codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index acff8d6..6e793eb 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -834,12 +834,14 @@ static struct snd_soc_codec_driver adav80x_codec_driver = { .set_pll = adav80x_set_pll, .set_sysclk = adav80x_set_sysclk, - .controls = adav80x_controls, - .num_controls = ARRAY_SIZE(adav80x_controls), - .dapm_widgets = adav80x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adav80x_dapm_widgets), - .dapm_routes = adav80x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), + .component_driver = { + .controls = adav80x_controls, + .num_controls = ARRAY_SIZE(adav80x_controls), + .dapm_widgets = adav80x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adav80x_dapm_widgets), + .dapm_routes = adav80x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), + }, }; int adav80x_bus_probe(struct device *dev, struct regmap *regmap) -- cgit v0.10.2 From 940b816f905eddf6c61db150b4833cd0c7eb61d8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:12:30 +0000 Subject: ASoC: codec duplicated callback function goes to component on ads117x codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c index c5be1bd..90c756d 100644 --- a/sound/soc/codecs/ads117x.c +++ b/sound/soc/codecs/ads117x.c @@ -59,10 +59,12 @@ static struct snd_soc_dai_driver ads117x_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_ads117x = { - .dapm_widgets = ads117x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ads117x_dapm_widgets), - .dapm_routes = ads117x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ads117x_dapm_routes), + .component_driver = { + .dapm_widgets = ads117x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ads117x_dapm_widgets), + .dapm_routes = ads117x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(ads117x_dapm_routes), + }, }; static int ads117x_probe(struct platform_device *pdev) -- cgit v0.10.2 From 301810d0dfbcd1f56c552da6c9234db5003ec344 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:12:48 +0000 Subject: ASoC: codec duplicated callback function goes to component on ak4535 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 54428c6..66cfffd 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -395,12 +395,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { .set_bias_level = ak4535_set_bias_level, .suspend_bias_off = true, - .controls = ak4535_snd_controls, - .num_controls = ARRAY_SIZE(ak4535_snd_controls), - .dapm_widgets = ak4535_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets), - .dapm_routes = ak4535_audio_map, - .num_dapm_routes = ARRAY_SIZE(ak4535_audio_map), + .component_driver = { + .controls = ak4535_snd_controls, + .num_controls = ARRAY_SIZE(ak4535_snd_controls), + .dapm_widgets = ak4535_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets), + .dapm_routes = ak4535_audio_map, + .num_dapm_routes = ARRAY_SIZE(ak4535_audio_map), + }, }; static int ak4535_i2c_probe(struct i2c_client *i2c, -- cgit v0.10.2 From f303eb9e1e5d1c9c26cf85274324ce6a863da946 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:13:06 +0000 Subject: ASoC: codec duplicated callback function goes to component on ak4641 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index b14176f..c91717d 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -505,12 +505,14 @@ static struct snd_soc_dai_driver ak4641_dai[] = { }; static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { - .controls = ak4641_snd_controls, - .num_controls = ARRAY_SIZE(ak4641_snd_controls), - .dapm_widgets = ak4641_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4641_dapm_widgets), - .dapm_routes = ak4641_audio_map, - .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), + .component_driver = { + .controls = ak4641_snd_controls, + .num_controls = ARRAY_SIZE(ak4641_snd_controls), + .dapm_widgets = ak4641_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4641_dapm_widgets), + .dapm_routes = ak4641_audio_map, + .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), + }, .set_bias_level = ak4641_set_bias_level, .suspend_bias_off = true, }; -- cgit v0.10.2 From af06ccaded87dc25c41714004a2d73bfeef0c922 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:13:26 +0000 Subject: ASoC: codec duplicated callback function goes to component on ak4671 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index c73a9f6..6088afa 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -612,12 +612,14 @@ static struct snd_soc_dai_driver ak4671_dai = { static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { .set_bias_level = ak4671_set_bias_level, - .controls = ak4671_snd_controls, - .num_controls = ARRAY_SIZE(ak4671_snd_controls), - .dapm_widgets = ak4671_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets), - .dapm_routes = ak4671_intercon, - .num_dapm_routes = ARRAY_SIZE(ak4671_intercon), + .component_driver = { + .controls = ak4671_snd_controls, + .num_controls = ARRAY_SIZE(ak4671_snd_controls), + .dapm_widgets = ak4671_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets), + .dapm_routes = ak4671_intercon, + .num_dapm_routes = ARRAY_SIZE(ak4671_intercon), + }, }; static const struct regmap_config ak4671_regmap = { -- cgit v0.10.2 From e9474dc634c76d047be84c3dd35bf81213d2d550 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:13:44 +0000 Subject: ASoC: codec duplicated callback function goes to component on alc5632 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index 4d3ba33..adb80d8 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c @@ -1072,12 +1072,14 @@ static const struct snd_soc_codec_driver soc_codec_device_alc5632 = { .set_bias_level = alc5632_set_bias_level, .suspend_bias_off = true, - .controls = alc5632_snd_controls, - .num_controls = ARRAY_SIZE(alc5632_snd_controls), - .dapm_widgets = alc5632_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(alc5632_dapm_widgets), - .dapm_routes = alc5632_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes), + .component_driver = { + .controls = alc5632_snd_controls, + .num_controls = ARRAY_SIZE(alc5632_snd_controls), + .dapm_widgets = alc5632_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(alc5632_dapm_widgets), + .dapm_routes = alc5632_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes), + }, }; static const struct regmap_config alc5632_regmap = { -- cgit v0.10.2 From 295f08154cc07db27c75e0c0ac4af9890b87f85b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:14:00 +0000 Subject: ASoC: codec duplicated callback function goes to component on cs47l24 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index 954a4f5..779a7bf 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -1190,12 +1190,14 @@ static struct snd_soc_codec_driver soc_codec_dev_cs47l24 = { .set_sysclk = arizona_set_sysclk, .set_pll = cs47l24_set_fll, - .controls = cs47l24_snd_controls, - .num_controls = ARRAY_SIZE(cs47l24_snd_controls), - .dapm_widgets = cs47l24_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs47l24_dapm_widgets), - .dapm_routes = cs47l24_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(cs47l24_dapm_routes), + .component_driver = { + .controls = cs47l24_snd_controls, + .num_controls = ARRAY_SIZE(cs47l24_snd_controls), + .dapm_widgets = cs47l24_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs47l24_dapm_widgets), + .dapm_routes = cs47l24_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs47l24_dapm_routes), + }, }; static struct snd_compr_ops cs47l24_compr_ops = { -- cgit v0.10.2 From a2c9c0f9729be9b0c5d410fd3f9ba2b335d5e868 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:14:19 +0000 Subject: ASoC: codec duplicated callback function goes to component on cx20442 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index fb3885f..2c12471 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -407,10 +407,12 @@ static struct snd_soc_codec_driver cx20442_codec_dev = { .reg_word_size = sizeof(u8), .read = cx20442_read_reg_cache, .write = cx20442_write, - .dapm_widgets = cx20442_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cx20442_dapm_widgets), - .dapm_routes = cx20442_audio_map, - .num_dapm_routes = ARRAY_SIZE(cx20442_audio_map), + .component_driver = { + .dapm_widgets = cx20442_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cx20442_dapm_widgets), + .dapm_routes = cx20442_audio_map, + .num_dapm_routes = ARRAY_SIZE(cx20442_audio_map), + }, }; static int cx20442_platform_probe(struct platform_device *pdev) -- cgit v0.10.2 From 57329a3a419273e765f5654c3c8cad9266c5b6f2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:14:35 +0000 Subject: ASoC: codec duplicated callback function goes to component on da7210 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index af23a61..17053df 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -1167,13 +1167,14 @@ static int da7210_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_da7210 = { .probe = da7210_probe, - .controls = da7210_snd_controls, - .num_controls = ARRAY_SIZE(da7210_snd_controls), - - .dapm_widgets = da7210_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da7210_dapm_widgets), - .dapm_routes = da7210_audio_map, - .num_dapm_routes = ARRAY_SIZE(da7210_audio_map), + .component_driver = { + .controls = da7210_snd_controls, + .num_controls = ARRAY_SIZE(da7210_snd_controls), + .dapm_widgets = da7210_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da7210_dapm_widgets), + .dapm_routes = da7210_audio_map, + .num_dapm_routes = ARRAY_SIZE(da7210_audio_map), + }, }; #if IS_ENABLED(CONFIG_I2C) -- cgit v0.10.2 From 92d2a233d878c4ddebad805ae4201e8ec335b3af Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:14:53 +0000 Subject: ASoC: codec duplicated callback function goes to component on da7213 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index e5527bc..7cfb5da 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1740,13 +1740,14 @@ static struct snd_soc_codec_driver soc_codec_dev_da7213 = { .probe = da7213_probe, .set_bias_level = da7213_set_bias_level, - .controls = da7213_snd_controls, - .num_controls = ARRAY_SIZE(da7213_snd_controls), - - .dapm_widgets = da7213_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da7213_dapm_widgets), - .dapm_routes = da7213_audio_map, - .num_dapm_routes = ARRAY_SIZE(da7213_audio_map), + .component_driver = { + .controls = da7213_snd_controls, + .num_controls = ARRAY_SIZE(da7213_snd_controls), + .dapm_widgets = da7213_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da7213_dapm_widgets), + .dapm_routes = da7213_audio_map, + .num_dapm_routes = ARRAY_SIZE(da7213_audio_map), + }, }; static const struct regmap_config da7213_regmap_config = { -- cgit v0.10.2 From 91985829cc198dad64b29980aef226e4af2f65c6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:15:10 +0000 Subject: ASoC: codec duplicated callback function goes to component on da7218 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index 99ce23e..dcdda6c 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -3045,13 +3045,14 @@ static struct snd_soc_codec_driver soc_codec_dev_da7218 = { .resume = da7218_resume, .set_bias_level = da7218_set_bias_level, - .controls = da7218_snd_controls, - .num_controls = ARRAY_SIZE(da7218_snd_controls), - - .dapm_widgets = da7218_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da7218_dapm_widgets), - .dapm_routes = da7218_audio_map, - .num_dapm_routes = ARRAY_SIZE(da7218_audio_map), + .component_driver = { + .controls = da7218_snd_controls, + .num_controls = ARRAY_SIZE(da7218_snd_controls), + .dapm_widgets = da7218_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da7218_dapm_widgets), + .dapm_routes = da7218_audio_map, + .num_dapm_routes = ARRAY_SIZE(da7218_audio_map), + }, }; -- cgit v0.10.2 From b0d9df4dc5f3a690c460bb1bb0799ed85255448e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:15:27 +0000 Subject: ASoC: codec duplicated callback function goes to component on da7219 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 50ea943..b6411bd 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1767,13 +1767,14 @@ static struct snd_soc_codec_driver soc_codec_dev_da7219 = { .resume = da7219_resume, .set_bias_level = da7219_set_bias_level, - .controls = da7219_snd_controls, - .num_controls = ARRAY_SIZE(da7219_snd_controls), - - .dapm_widgets = da7219_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da7219_dapm_widgets), - .dapm_routes = da7219_audio_map, - .num_dapm_routes = ARRAY_SIZE(da7219_audio_map), + .component_driver = { + .controls = da7219_snd_controls, + .num_controls = ARRAY_SIZE(da7219_snd_controls), + .dapm_widgets = da7219_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da7219_dapm_widgets), + .dapm_routes = da7219_audio_map, + .num_dapm_routes = ARRAY_SIZE(da7219_audio_map), + }, }; -- cgit v0.10.2 From e7e8dda8b8a3dafd81c64f378c3a2d5cb71860df Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:15:48 +0000 Subject: ASoC: codec duplicated callback function goes to component on da732x codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 461506a..c1cc1c1 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1501,12 +1501,14 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, static struct snd_soc_codec_driver soc_codec_dev_da732x = { .set_bias_level = da732x_set_bias_level, - .controls = da732x_snd_controls, - .num_controls = ARRAY_SIZE(da732x_snd_controls), - .dapm_widgets = da732x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da732x_dapm_widgets), - .dapm_routes = da732x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes), + .component_driver = { + .controls = da732x_snd_controls, + .num_controls = ARRAY_SIZE(da732x_snd_controls), + .dapm_widgets = da732x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da732x_dapm_widgets), + .dapm_routes = da732x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes), + }, .set_pll = da732x_set_dai_pll, }; -- cgit v0.10.2 From b2fb9a6e5cf0ef6771f821507ccb5ca6efd9acad Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:16:04 +0000 Subject: ASoC: codec duplicated callback function goes to component on da9055 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 0b2ede8..4efb5f8 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -1455,13 +1455,14 @@ static struct snd_soc_codec_driver soc_codec_dev_da9055 = { .probe = da9055_probe, .set_bias_level = da9055_set_bias_level, - .controls = da9055_snd_controls, - .num_controls = ARRAY_SIZE(da9055_snd_controls), - - .dapm_widgets = da9055_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da9055_dapm_widgets), - .dapm_routes = da9055_audio_map, - .num_dapm_routes = ARRAY_SIZE(da9055_audio_map), + .component_driver = { + .controls = da9055_snd_controls, + .num_controls = ARRAY_SIZE(da9055_snd_controls), + .dapm_widgets = da9055_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(da9055_dapm_widgets), + .dapm_routes = da9055_audio_map, + .num_dapm_routes = ARRAY_SIZE(da9055_audio_map), + }, }; static const struct regmap_config da9055_regmap_config = { -- cgit v0.10.2 From a73b8e8955fe7660455aaa20e8452f5322793fab Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:16:22 +0000 Subject: ASoC: codec duplicated callback function goes to component on dmic codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c index fde5325..c82b9dc 100644 --- a/sound/soc/codecs/dmic.c +++ b/sound/soc/codecs/dmic.c @@ -51,10 +51,12 @@ static const struct snd_soc_dapm_route intercon[] = { }; static struct snd_soc_codec_driver soc_dmic = { - .dapm_widgets = dmic_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(dmic_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), + .component_driver = { + .dapm_widgets = dmic_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(dmic_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), + }, }; static int dmic_dev_probe(struct platform_device *pdev) -- cgit v0.10.2 From 88b0f761e296682f24639e9d9fc0122e7a7695c1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:16:40 +0000 Subject: ASoC: codec duplicated callback function goes to component on hdmi-codec codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index f64ecaa..b904492 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -375,13 +375,13 @@ static int hdmi_of_xlate_dai_name(struct snd_soc_component *component, } static struct snd_soc_codec_driver hdmi_codec = { - .controls = hdmi_controls, - .num_controls = ARRAY_SIZE(hdmi_controls), - .dapm_widgets = hdmi_widgets, - .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), - .dapm_routes = hdmi_routes, - .num_dapm_routes = ARRAY_SIZE(hdmi_routes), .component_driver = { + .controls = hdmi_controls, + .num_controls = ARRAY_SIZE(hdmi_controls), + .dapm_widgets = hdmi_widgets, + .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), + .dapm_routes = hdmi_routes, + .num_dapm_routes = ARRAY_SIZE(hdmi_routes), .of_xlate_dai_name = hdmi_of_xlate_dai_name, }, }; -- cgit v0.10.2 From 49e774807178c048d34602789f3342e545cc1605 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:16:59 +0000 Subject: ASoC: codec duplicated callback function goes to component on isabelle codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index be44837..a4b0ede 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -1089,12 +1089,14 @@ static struct snd_soc_dai_driver isabelle_dai[] = { static struct snd_soc_codec_driver soc_codec_dev_isabelle = { .set_bias_level = isabelle_set_bias_level, - .controls = isabelle_snd_controls, - .num_controls = ARRAY_SIZE(isabelle_snd_controls), - .dapm_widgets = isabelle_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(isabelle_dapm_widgets), - .dapm_routes = isabelle_intercon, - .num_dapm_routes = ARRAY_SIZE(isabelle_intercon), + .component_driver = { + .controls = isabelle_snd_controls, + .num_controls = ARRAY_SIZE(isabelle_snd_controls), + .dapm_widgets = isabelle_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(isabelle_dapm_widgets), + .dapm_routes = isabelle_intercon, + .num_dapm_routes = ARRAY_SIZE(isabelle_intercon), + }, .idle_bias_off = true, }; -- cgit v0.10.2 From af15dc71b0c343279678af50543f6a64e84fb569 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:17:19 +0000 Subject: ASoC: codec duplicated callback function goes to component on jz4740 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 1f5ab99..0290fab 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c @@ -298,12 +298,14 @@ static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = { .set_bias_level = jz4740_codec_set_bias_level, .suspend_bias_off = true, - .controls = jz4740_codec_controls, - .num_controls = ARRAY_SIZE(jz4740_codec_controls), - .dapm_widgets = jz4740_codec_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(jz4740_codec_dapm_widgets), - .dapm_routes = jz4740_codec_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(jz4740_codec_dapm_routes), + .component_driver = { + .controls = jz4740_codec_controls, + .num_controls = ARRAY_SIZE(jz4740_codec_controls), + .dapm_widgets = jz4740_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(jz4740_codec_dapm_widgets), + .dapm_routes = jz4740_codec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(jz4740_codec_dapm_routes), + }, }; static const struct regmap_config jz4740_codec_regmap_config = { -- cgit v0.10.2 From 2f15de710b44e17fec58880492a2c79b37f09f02 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:17:38 +0000 Subject: ASoC: codec duplicated callback function goes to component on lm49453 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index 9af5640..8d413c2 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -1391,12 +1391,14 @@ static struct snd_soc_dai_driver lm49453_dai[] = { static struct snd_soc_codec_driver soc_codec_dev_lm49453 = { .set_bias_level = lm49453_set_bias_level, - .controls = lm49453_snd_controls, - .num_controls = ARRAY_SIZE(lm49453_snd_controls), - .dapm_widgets = lm49453_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(lm49453_dapm_widgets), - .dapm_routes = lm49453_audio_map, - .num_dapm_routes = ARRAY_SIZE(lm49453_audio_map), + .component_driver = { + .controls = lm49453_snd_controls, + .num_controls = ARRAY_SIZE(lm49453_snd_controls), + .dapm_widgets = lm49453_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(lm49453_dapm_widgets), + .dapm_routes = lm49453_audio_map, + .num_dapm_routes = ARRAY_SIZE(lm49453_audio_map), + }, .idle_bias_off = true, }; -- cgit v0.10.2 From b5cd19e8c3efda9f0b81c7420886b640ef82d223 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:17:54 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm98088 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index fc22804..72f7745 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -1704,12 +1704,14 @@ static struct snd_soc_codec_driver soc_codec_dev_max98088 = { .set_bias_level = max98088_set_bias_level, .suspend_bias_off = true, - .controls = max98088_snd_controls, - .num_controls = ARRAY_SIZE(max98088_snd_controls), - .dapm_widgets = max98088_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets), - .dapm_routes = max98088_audio_map, - .num_dapm_routes = ARRAY_SIZE(max98088_audio_map), + .component_driver = { + .controls = max98088_snd_controls, + .num_controls = ARRAY_SIZE(max98088_snd_controls), + .dapm_widgets = max98088_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets), + .dapm_routes = max98088_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98088_audio_map), + }, }; static int max98088_i2c_probe(struct i2c_client *i2c, -- cgit v0.10.2 From 7fb49ebab0a1e50848466096a217bd8f0aa729eb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:18:12 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm98095 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 3577003..6f8a757 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -2108,12 +2108,14 @@ static struct snd_soc_codec_driver soc_codec_dev_max98095 = { .suspend = max98095_suspend, .resume = max98095_resume, .set_bias_level = max98095_set_bias_level, - .controls = max98095_snd_controls, - .num_controls = ARRAY_SIZE(max98095_snd_controls), - .dapm_widgets = max98095_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max98095_dapm_widgets), - .dapm_routes = max98095_audio_map, - .num_dapm_routes = ARRAY_SIZE(max98095_audio_map), + .component_driver = { + .controls = max98095_snd_controls, + .num_controls = ARRAY_SIZE(max98095_snd_controls), + .dapm_widgets = max98095_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98095_dapm_widgets), + .dapm_routes = max98095_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98095_audio_map), + }, }; static int max98095_i2c_probe(struct i2c_client *i2c, -- cgit v0.10.2 From b071a0bc0fdc03c4a97020ffcb5d529a02b3b564 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:18:31 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm98357a codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index 5b1dfb1..6a6b68a 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c @@ -74,10 +74,12 @@ static int max98357a_codec_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver max98357a_codec_driver = { .probe = max98357a_codec_probe, - .dapm_widgets = max98357a_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max98357a_dapm_widgets), - .dapm_routes = max98357a_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(max98357a_dapm_routes), + .component_driver = { + .dapm_widgets = max98357a_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98357a_dapm_widgets), + .dapm_routes = max98357a_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(max98357a_dapm_routes), + }, }; static const struct snd_soc_dai_ops max98357a_dai_ops = { -- cgit v0.10.2 From 9d32d3dca9f377f8dbfb03413cea5af5482e412c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:18:52 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm9850 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index c14a79d..0610840 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -306,12 +306,14 @@ static struct snd_soc_codec_driver soc_codec_dev_max9850 = { .set_bias_level = max9850_set_bias_level, .suspend_bias_off = true, - .controls = max9850_controls, - .num_controls = ARRAY_SIZE(max9850_controls), - .dapm_widgets = max9850_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max9850_dapm_widgets), - .dapm_routes = max9850_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(max9850_dapm_routes), + .component_driver = { + .controls = max9850_controls, + .num_controls = ARRAY_SIZE(max9850_controls), + .dapm_widgets = max9850_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max9850_dapm_widgets), + .dapm_routes = max9850_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(max9850_dapm_routes), + }, }; static int max9850_i2c_probe(struct i2c_client *i2c, -- cgit v0.10.2 From e92b48aa21d41c64ae1a06d69b94c8dfaec9c672 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:19:11 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm9867 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 2a22fdd..c967323 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -417,12 +417,14 @@ static int max9867_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver max9867_codec = { .probe = max9867_probe, - .controls = max9867_snd_controls, - .num_controls = ARRAY_SIZE(max9867_snd_controls), - .dapm_routes = max9867_audio_map, - .num_dapm_routes = ARRAY_SIZE(max9867_audio_map), - .dapm_widgets = max9867_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max9867_dapm_widgets), + .component_driver = { + .controls = max9867_snd_controls, + .num_controls = ARRAY_SIZE(max9867_snd_controls), + .dapm_routes = max9867_audio_map, + .num_dapm_routes = ARRAY_SIZE(max9867_audio_map), + .dapm_widgets = max9867_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max9867_dapm_widgets), + }, }; static bool max9867_volatile_register(struct device *dev, unsigned int reg) -- cgit v0.10.2 From 4a4339d947e8989aa4f81dbc1cf086a11dbeeb89 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:19:29 +0000 Subject: ASoC: codec duplicated callback function goes to component on max98925 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max98925.c b/sound/soc/codecs/max98925.c index 5990de3..327eaa2 100644 --- a/sound/soc/codecs/max98925.c +++ b/sound/soc/codecs/max98925.c @@ -540,12 +540,14 @@ static int max98925_probe(struct snd_soc_codec *codec) static const struct snd_soc_codec_driver soc_codec_dev_max98925 = { .probe = max98925_probe, - .controls = max98925_snd_controls, - .num_controls = ARRAY_SIZE(max98925_snd_controls), - .dapm_routes = max98925_audio_map, - .num_dapm_routes = ARRAY_SIZE(max98925_audio_map), - .dapm_widgets = max98925_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max98925_dapm_widgets), + .component_driver = { + .controls = max98925_snd_controls, + .num_controls = ARRAY_SIZE(max98925_snd_controls), + .dapm_routes = max98925_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98925_audio_map), + .dapm_widgets = max98925_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98925_dapm_widgets), + }, }; static const struct regmap_config max98925_regmap = { -- cgit v0.10.2 From 3d19c93b7ef6fb76a35a58585df62f9e386a96c2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:19:48 +0000 Subject: ASoC: codec duplicated callback function goes to component on max98926 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c index 8d14ada..5830a81 100644 --- a/sound/soc/codecs/max98926.c +++ b/sound/soc/codecs/max98926.c @@ -498,12 +498,14 @@ static int max98926_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_max98926 = { .probe = max98926_probe, - .controls = max98926_snd_controls, - .num_controls = ARRAY_SIZE(max98926_snd_controls), - .dapm_routes = max98926_audio_map, - .num_dapm_routes = ARRAY_SIZE(max98926_audio_map), - .dapm_widgets = max98926_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max98926_dapm_widgets), + .component_driver = { + .controls = max98926_snd_controls, + .num_controls = ARRAY_SIZE(max98926_snd_controls), + .dapm_routes = max98926_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98926_audio_map), + .dapm_widgets = max98926_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98926_dapm_widgets), + }, }; static const struct regmap_config max98926_regmap = { -- cgit v0.10.2 From f9294a24ae392a59f283b37c821c8f21c2ce1ade Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:20:05 +0000 Subject: ASoC: codec duplicated callback function goes to component on mc13783 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 3e770cb..9056270 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -737,12 +737,14 @@ static struct snd_soc_codec_driver soc_codec_dev_mc13783 = { .probe = mc13783_probe, .remove = mc13783_remove, .get_regmap = mc13783_get_regmap, - .controls = mc13783_control_list, - .num_controls = ARRAY_SIZE(mc13783_control_list), - .dapm_widgets = mc13783_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(mc13783_dapm_widgets), - .dapm_routes = mc13783_routes, - .num_dapm_routes = ARRAY_SIZE(mc13783_routes), + .component_driver = { + .controls = mc13783_control_list, + .num_controls = ARRAY_SIZE(mc13783_control_list), + .dapm_widgets = mc13783_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(mc13783_dapm_widgets), + .dapm_routes = mc13783_routes, + .num_dapm_routes = ARRAY_SIZE(mc13783_routes), + }, }; static int __init mc13783_codec_probe(struct platform_device *pdev) -- cgit v0.10.2 From e21413cab309abdc315ece737f6dff86669884d3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:20:28 +0000 Subject: ASoC: codec duplicated callback function goes to component on ml26124 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index f561c78..69e5e18 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -541,12 +541,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ml26124 = { .probe = ml26124_probe, .set_bias_level = ml26124_set_bias_level, .suspend_bias_off = true, - .dapm_widgets = ml26124_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ml26124_dapm_widgets), - .dapm_routes = ml26124_intercon, - .num_dapm_routes = ARRAY_SIZE(ml26124_intercon), - .controls = ml26124_snd_controls, - .num_controls = ARRAY_SIZE(ml26124_snd_controls), + .component_driver = { + .controls = ml26124_snd_controls, + .num_controls = ARRAY_SIZE(ml26124_snd_controls), + .dapm_widgets = ml26124_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ml26124_dapm_widgets), + .dapm_routes = ml26124_intercon, + .num_dapm_routes = ARRAY_SIZE(ml26124_intercon), + }, }; static const struct regmap_config ml26124_i2c_regmap = { -- cgit v0.10.2 From 889adf638721a9dcd772e20075697338d65fb2bc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:20:46 +0000 Subject: ASoC: codec duplicated callback function goes to component on nau8825 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 5c9707a..822791eb 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -2270,12 +2270,14 @@ static struct snd_soc_codec_driver nau8825_codec_driver = { .suspend = nau8825_suspend, .resume = nau8825_resume, - .controls = nau8825_controls, - .num_controls = ARRAY_SIZE(nau8825_controls), - .dapm_widgets = nau8825_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(nau8825_dapm_widgets), - .dapm_routes = nau8825_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(nau8825_dapm_routes), + .component_driver = { + .controls = nau8825_controls, + .num_controls = ARRAY_SIZE(nau8825_controls), + .dapm_widgets = nau8825_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(nau8825_dapm_widgets), + .dapm_routes = nau8825_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(nau8825_dapm_routes), + }, }; static void nau8825_reset_chip(struct regmap *regmap) -- cgit v0.10.2 From 4cd747df40c6dfdc61daf22b6457904a3d87213a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:21:02 +0000 Subject: ASoC: codec duplicated callback function goes to component on pcm3008 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 8fb445f..708af05 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c @@ -99,10 +99,12 @@ static struct snd_soc_dai_driver pcm3008_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = { - .dapm_widgets = pcm3008_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pcm3008_dapm_widgets), - .dapm_routes = pcm3008_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pcm3008_dapm_routes), + .component_driver = { + .dapm_widgets = pcm3008_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm3008_dapm_widgets), + .dapm_routes = pcm3008_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm3008_dapm_routes), + }, }; static int pcm3008_codec_probe(struct platform_device *pdev) -- cgit v0.10.2 From a6a505dd2fabe43b969147f63d44a3dd1daf6f9d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:21:19 +0000 Subject: ASoC: codec duplicated callback function goes to component on rt286 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 74c0e4e..9c365a7 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1053,12 +1053,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt286 = { .resume = rt286_resume, .set_bias_level = rt286_set_bias_level, .idle_bias_off = true, - .controls = rt286_snd_controls, - .num_controls = ARRAY_SIZE(rt286_snd_controls), - .dapm_widgets = rt286_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt286_dapm_widgets), - .dapm_routes = rt286_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt286_dapm_routes), + .component_driver = { + .controls = rt286_snd_controls, + .num_controls = ARRAY_SIZE(rt286_snd_controls), + .dapm_widgets = rt286_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt286_dapm_widgets), + .dapm_routes = rt286_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt286_dapm_routes), + }, }; static const struct regmap_config rt286_regmap = { -- cgit v0.10.2 From b5c998b472c25d72fedc1b686faf1fab6dfcbf4c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:21:37 +0000 Subject: ASoC: codec duplicated callback function goes to component on rt298 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index f80cfe4..5555864 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -1095,12 +1095,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt298 = { .resume = rt298_resume, .set_bias_level = rt298_set_bias_level, .idle_bias_off = true, - .controls = rt298_snd_controls, - .num_controls = ARRAY_SIZE(rt298_snd_controls), - .dapm_widgets = rt298_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt298_dapm_widgets), - .dapm_routes = rt298_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt298_dapm_routes), + .component_driver = { + .controls = rt298_snd_controls, + .num_controls = ARRAY_SIZE(rt298_snd_controls), + .dapm_widgets = rt298_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt298_dapm_widgets), + .dapm_routes = rt298_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt298_dapm_routes), + }, }; static const struct regmap_config rt298_regmap = { -- cgit v0.10.2 From a3470399bcfcd2ca57b6135f89f48e7e37a499fd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:21:55 +0000 Subject: ASoC: codec duplicated callback function goes to component on rt5514 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index 7162f05..e0606a5 100644 --- a/sound/soc/codecs/rt5514.c +++ b/sound/soc/codecs/rt5514.c @@ -1023,12 +1023,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5514 = { .probe = rt5514_probe, .idle_bias_off = true, .set_bias_level = rt5514_set_bias_level, - .controls = rt5514_snd_controls, - .num_controls = ARRAY_SIZE(rt5514_snd_controls), - .dapm_widgets = rt5514_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5514_dapm_widgets), - .dapm_routes = rt5514_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5514_dapm_routes), + .component_driver = { + .controls = rt5514_snd_controls, + .num_controls = ARRAY_SIZE(rt5514_snd_controls), + .dapm_widgets = rt5514_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5514_dapm_widgets), + .dapm_routes = rt5514_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5514_dapm_routes), + }, }; static const struct regmap_config rt5514_i2c_regmap = { -- cgit v0.10.2 From b72aa483c4d3668b1e95a1d968e64262c7d876f1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:22:11 +0000 Subject: ASoC: codec duplicated callback function goes to component on rt5640 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 09e8988..fbe3af1 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -2261,12 +2261,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5640 = { .resume = rt5640_resume, .set_bias_level = rt5640_set_bias_level, .idle_bias_off = true, - .controls = rt5640_snd_controls, - .num_controls = ARRAY_SIZE(rt5640_snd_controls), - .dapm_widgets = rt5640_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5640_dapm_widgets), - .dapm_routes = rt5640_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5640_dapm_routes), + .component_driver = { + .controls = rt5640_snd_controls, + .num_controls = ARRAY_SIZE(rt5640_snd_controls), + .dapm_widgets = rt5640_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5640_dapm_widgets), + .dapm_routes = rt5640_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5640_dapm_routes), + }, }; static const struct regmap_config rt5640_regmap = { -- cgit v0.10.2 From 51712de1ea87b794e6e47584a87cda7cfd7a2056 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:22:33 +0000 Subject: ASoC: codec duplicated callback function goes to component on rt5645 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 490bfe6..10c2a56 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3484,12 +3484,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5645 = { .resume = rt5645_resume, .set_bias_level = rt5645_set_bias_level, .idle_bias_off = true, - .controls = rt5645_snd_controls, - .num_controls = ARRAY_SIZE(rt5645_snd_controls), - .dapm_widgets = rt5645_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5645_dapm_widgets), - .dapm_routes = rt5645_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5645_dapm_routes), + .component_driver = { + .controls = rt5645_snd_controls, + .num_controls = ARRAY_SIZE(rt5645_snd_controls), + .dapm_widgets = rt5645_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5645_dapm_widgets), + .dapm_routes = rt5645_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5645_dapm_routes), + }, }; static const struct regmap_config rt5645_regmap = { -- cgit v0.10.2 From 1fd899821d59303d7e6ec4be14770213788f1bb8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:22:51 +0000 Subject: ASoC: codec duplicated callback function goes to component on rt5651 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 7a61970..f5d3415 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1712,12 +1712,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5651 = { .resume = rt5651_resume, .set_bias_level = rt5651_set_bias_level, .idle_bias_off = true, - .controls = rt5651_snd_controls, - .num_controls = ARRAY_SIZE(rt5651_snd_controls), - .dapm_widgets = rt5651_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5651_dapm_widgets), - .dapm_routes = rt5651_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5651_dapm_routes), + .component_driver = { + .controls = rt5651_snd_controls, + .num_controls = ARRAY_SIZE(rt5651_snd_controls), + .dapm_widgets = rt5651_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5651_dapm_widgets), + .dapm_routes = rt5651_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5651_dapm_routes), + }, }; static const struct regmap_config rt5651_regmap = { -- cgit v0.10.2 From e0c2b59e83ab98dce500746d482850a2dffdcd22 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:23:07 +0000 Subject: ASoC: codec duplicated callback function goes to component on rt5659 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 1b30914..59ddaf3 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -3722,12 +3722,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5659 = { .resume = rt5659_resume, .set_bias_level = rt5659_set_bias_level, .idle_bias_off = true, - .controls = rt5659_snd_controls, - .num_controls = ARRAY_SIZE(rt5659_snd_controls), - .dapm_widgets = rt5659_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5659_dapm_widgets), - .dapm_routes = rt5659_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5659_dapm_routes), + .component_driver = { + .controls = rt5659_snd_controls, + .num_controls = ARRAY_SIZE(rt5659_snd_controls), + .dapm_widgets = rt5659_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5659_dapm_widgets), + .dapm_routes = rt5659_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5659_dapm_routes), + }, }; -- cgit v0.10.2 From 462fe79468ccc79d9d639f03c666b5c117b4957c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:23:24 +0000 Subject: ASoC: codec duplicated callback function goes to component on rt5670 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 8ef467f..49caf13 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2777,12 +2777,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5670 = { .resume = rt5670_resume, .set_bias_level = rt5670_set_bias_level, .idle_bias_off = true, - .controls = rt5670_snd_controls, - .num_controls = ARRAY_SIZE(rt5670_snd_controls), - .dapm_widgets = rt5670_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5670_dapm_widgets), - .dapm_routes = rt5670_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5670_dapm_routes), + .component_driver = { + .controls = rt5670_snd_controls, + .num_controls = ARRAY_SIZE(rt5670_snd_controls), + .dapm_widgets = rt5670_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5670_dapm_widgets), + .dapm_routes = rt5670_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5670_dapm_routes), + }, }; static const struct regmap_config rt5670_regmap = { -- cgit v0.10.2 From 1ec95a5748de5fd448f0b54a3b3c6fcd3b8374c0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:23:46 +0000 Subject: ASoC: codec duplicated callback function goes to component on rt5677 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index da9483c..68268f2 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -4974,12 +4974,14 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5677 = { .resume = rt5677_resume, .set_bias_level = rt5677_set_bias_level, .idle_bias_off = true, - .controls = rt5677_snd_controls, - .num_controls = ARRAY_SIZE(rt5677_snd_controls), - .dapm_widgets = rt5677_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5677_dapm_widgets), - .dapm_routes = rt5677_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5677_dapm_routes), + .component_driver = { + .controls = rt5677_snd_controls, + .num_controls = ARRAY_SIZE(rt5677_snd_controls), + .dapm_widgets = rt5677_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5677_dapm_widgets), + .dapm_routes = rt5677_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5677_dapm_routes), + }, }; static const struct regmap_config rt5677_regmap_physical = { -- cgit v0.10.2 From 185c7c005ad89e7c21e9922cc5e92af761d87fb4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:24:06 +0000 Subject: ASoC: codec duplicated callback function goes to component on si476x codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index a8402d0..5344f4a 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c @@ -238,10 +238,12 @@ static struct regmap *si476x_get_regmap(struct device *dev) static struct snd_soc_codec_driver soc_codec_dev_si476x = { .get_regmap = si476x_get_regmap, - .dapm_widgets = si476x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets), - .dapm_routes = si476x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(si476x_dapm_routes), + .component_driver = { + .dapm_widgets = si476x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets), + .dapm_routes = si476x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(si476x_dapm_routes), + }, }; static int si476x_platform_probe(struct platform_device *pdev) -- cgit v0.10.2 From 486e0763e23d0fc91aac0b5a156a2646ed7c658f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:24:24 +0000 Subject: ASoC: codec duplicated callback function goes to component on sn95031 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 3a7de01..eae54c3 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c @@ -888,12 +888,14 @@ static struct snd_soc_codec_driver sn95031_codec = { .set_bias_level = sn95031_set_vaud_bias, .idle_bias_off = true, - .controls = sn95031_snd_controls, - .num_controls = ARRAY_SIZE(sn95031_snd_controls), - .dapm_widgets = sn95031_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sn95031_dapm_widgets), - .dapm_routes = sn95031_audio_map, - .num_dapm_routes = ARRAY_SIZE(sn95031_audio_map), + .component_driver = { + .controls = sn95031_snd_controls, + .num_controls = ARRAY_SIZE(sn95031_snd_controls), + .dapm_widgets = sn95031_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sn95031_dapm_widgets), + .dapm_routes = sn95031_audio_map, + .num_dapm_routes = ARRAY_SIZE(sn95031_audio_map), + }, }; static int sn95031_device_probe(struct platform_device *pdev) -- cgit v0.10.2 From 96107bbaf32ab93bd359c7741f3611aff08e144b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:24:44 +0000 Subject: ASoC: codec duplicated callback function goes to component on ssm2518 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index e2e0bfa..38a85f3 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -715,12 +715,14 @@ static struct snd_soc_codec_driver ssm2518_codec_driver = { .set_sysclk = ssm2518_set_sysclk, .idle_bias_off = true, - .controls = ssm2518_snd_controls, - .num_controls = ARRAY_SIZE(ssm2518_snd_controls), - .dapm_widgets = ssm2518_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ssm2518_dapm_widgets), - .dapm_routes = ssm2518_routes, - .num_dapm_routes = ARRAY_SIZE(ssm2518_routes), + .component_driver = { + .controls = ssm2518_snd_controls, + .num_controls = ARRAY_SIZE(ssm2518_snd_controls), + .dapm_widgets = ssm2518_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ssm2518_dapm_widgets), + .dapm_routes = ssm2518_routes, + .num_dapm_routes = ARRAY_SIZE(ssm2518_routes), + }, }; static const struct regmap_config ssm2518_regmap_config = { -- cgit v0.10.2 From 29926fc8e853b6ddfee916d91fe88bec07058107 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:25:03 +0000 Subject: ASoC: codec duplicated callback function goes to component on sta529 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 2cdaca9..d4b384e 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -317,8 +317,10 @@ static const struct snd_soc_codec_driver sta529_codec_driver = { .set_bias_level = sta529_set_bias_level, .suspend_bias_off = true, - .controls = sta529_snd_controls, - .num_controls = ARRAY_SIZE(sta529_snd_controls), + .component_driver = { + .controls = sta529_snd_controls, + .num_controls = ARRAY_SIZE(sta529_snd_controls), + }, }; static const struct regmap_config sta529_regmap = { -- cgit v0.10.2 From 70e710d649ce705910885617fda3e37528057300 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:25:22 +0000 Subject: ASoC: codec duplicated callback function goes to component on stac9766 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 0945c51..2c5941f 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -320,8 +320,10 @@ static int stac9766_codec_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_stac9766 = { - .controls = stac9766_snd_ac97_controls, - .num_controls = ARRAY_SIZE(stac9766_snd_ac97_controls), + .component_driver = { + .controls = stac9766_snd_ac97_controls, + .num_controls = ARRAY_SIZE(stac9766_snd_ac97_controls), + }, .write = stac9766_ac97_write, .read = stac9766_ac97_read, .set_bias_level = stac9766_set_bias_level, -- cgit v0.10.2 From 40be1e609e743733e1e8a18b90e7be22c27d2062 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:25:40 +0000 Subject: ASoC: codec duplicated callback function goes to component on tlv320aic26 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 2c904d7..14aa96d 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -321,12 +321,14 @@ static int aic26_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver aic26_soc_codec_dev = { .probe = aic26_probe, - .controls = aic26_snd_controls, - .num_controls = ARRAY_SIZE(aic26_snd_controls), - .dapm_widgets = tlv320aic26_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tlv320aic26_dapm_widgets), - .dapm_routes = tlv320aic26_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(tlv320aic26_dapm_routes), + .component_driver = { + .controls = aic26_snd_controls, + .num_controls = ARRAY_SIZE(aic26_snd_controls), + .dapm_widgets = tlv320aic26_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tlv320aic26_dapm_widgets), + .dapm_routes = tlv320aic26_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tlv320aic26_dapm_routes), + }, }; static const struct regmap_config aic26_regmap = { -- cgit v0.10.2 From a06809b83f5d8b8a84fc9eb1bd3dae8edf839774 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:25:57 +0000 Subject: ASoC: codec duplicated callback function goes to component on tlv320aic32x4 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 85d4978..28fdfc5 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -797,12 +797,14 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { .set_bias_level = aic32x4_set_bias_level, .suspend_bias_off = true, - .controls = aic32x4_snd_controls, - .num_controls = ARRAY_SIZE(aic32x4_snd_controls), - .dapm_widgets = aic32x4_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets), - .dapm_routes = aic32x4_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), + .component_driver = { + .controls = aic32x4_snd_controls, + .num_controls = ARRAY_SIZE(aic32x4_snd_controls), + .dapm_widgets = aic32x4_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets), + .dapm_routes = aic32x4_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), + }, }; static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4, -- cgit v0.10.2 From b04c71e634e6654cf4e52e7a94e98aba27c0e643 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:26:17 +0000 Subject: ASoC: codec duplicated callback function goes to component on tlv320dac33 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index f7a6ce7..d64eac7 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -1453,12 +1453,14 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = { .probe = dac33_soc_probe, .remove = dac33_soc_remove, - .controls = dac33_snd_controls, - .num_controls = ARRAY_SIZE(dac33_snd_controls), - .dapm_widgets = dac33_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(dac33_dapm_widgets), - .dapm_routes = audio_map, - .num_dapm_routes = ARRAY_SIZE(audio_map), + .component_driver = { + .controls = dac33_snd_controls, + .num_controls = ARRAY_SIZE(dac33_snd_controls), + .dapm_widgets = dac33_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(dac33_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), + }, }; #define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ -- cgit v0.10.2 From e4b918ea24b1e16db7370883a6748efe7a3ac9ff Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:26:35 +0000 Subject: ASoC: codec duplicated callback function goes to component on twl4030 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index a5a4e9f..a2104d6 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -2199,12 +2199,14 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { .set_bias_level = twl4030_set_bias_level, .idle_bias_off = true, - .controls = twl4030_snd_controls, - .num_controls = ARRAY_SIZE(twl4030_snd_controls), - .dapm_widgets = twl4030_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(twl4030_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), + .component_driver = { + .controls = twl4030_snd_controls, + .num_controls = ARRAY_SIZE(twl4030_snd_controls), + .dapm_widgets = twl4030_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(twl4030_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), + }, }; static int twl4030_codec_probe(struct platform_device *pdev) -- cgit v0.10.2 From 2f45b8bd731cbaee5404cfac8bf083e807cffadf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:26:56 +0000 Subject: ASoC: codec duplicated callback function goes to component on twl6040 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 1f70810..748036e 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -1156,12 +1156,14 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { .suspend_bias_off = true, .ignore_pmdown_time = true, - .controls = twl6040_snd_controls, - .num_controls = ARRAY_SIZE(twl6040_snd_controls), - .dapm_widgets = twl6040_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), + .component_driver = { + .controls = twl6040_snd_controls, + .num_controls = ARRAY_SIZE(twl6040_snd_controls), + .dapm_widgets = twl6040_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), + }, }; static int twl6040_codec_probe(struct platform_device *pdev) -- cgit v0.10.2 From e939fc6c2679c474c31c7e07c73703099bd68f70 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:27:14 +0000 Subject: ASoC: codec duplicated callback function goes to component on uda134x codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index e4c694c..a4a3e98 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -523,10 +523,12 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = { .set_bias_level = uda134x_set_bias_level, .suspend_bias_off = true, - .dapm_widgets = uda134x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets), - .dapm_routes = uda134x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes), + .component_driver = { + .dapm_widgets = uda134x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets), + .dapm_routes = uda134x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes), + }, }; static const struct regmap_config uda134x_regmap_config = { -- cgit v0.10.2 From 68509ede7e80e6cd1782485f9a91c9641adadc54 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:27:32 +0000 Subject: ASoC: codec duplicated callback function goes to component on uda1380 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 35f0469..533e3bb 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -765,12 +765,14 @@ static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { .reg_cache_default = uda1380_reg, .reg_cache_step = 1, - .controls = uda1380_snd_controls, - .num_controls = ARRAY_SIZE(uda1380_snd_controls), - .dapm_widgets = uda1380_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), - .dapm_routes = uda1380_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(uda1380_dapm_routes), + .component_driver = { + .controls = uda1380_snd_controls, + .num_controls = ARRAY_SIZE(uda1380_snd_controls), + .dapm_widgets = uda1380_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), + .dapm_routes = uda1380_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(uda1380_dapm_routes), + }, }; #if IS_ENABLED(CONFIG_I2C) -- cgit v0.10.2 From 23ce0ad98946b6d27d43bec2cc1fb34013761690 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:27:49 +0000 Subject: ASoC: codec duplicated callback function goes to component on wl1273 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index 1b79778..fcffb6e 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c @@ -484,12 +484,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wl1273 = { .probe = wl1273_probe, .remove = wl1273_remove, - .controls = wl1273_controls, - .num_controls = ARRAY_SIZE(wl1273_controls), - .dapm_widgets = wl1273_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wl1273_dapm_widgets), - .dapm_routes = wl1273_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wl1273_dapm_routes), + .component_driver = { + .controls = wl1273_controls, + .num_controls = ARRAY_SIZE(wl1273_controls), + .dapm_widgets = wl1273_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wl1273_dapm_widgets), + .dapm_routes = wl1273_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wl1273_dapm_routes), + }, }; static int wl1273_platform_probe(struct platform_device *pdev) -- cgit v0.10.2 From 022f86d6f3b15bcd4865bccf837d309eb336f5a2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:28:08 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm0010 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index e3c34bd..4ef6919 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -795,10 +795,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { .set_sysclk = wm0010_set_sysclk, .idle_bias_off = true, - .dapm_widgets = wm0010_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm0010_dapm_widgets), - .dapm_routes = wm0010_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), + .component_driver = { + .dapm_widgets = wm0010_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm0010_dapm_widgets), + .dapm_routes = wm0010_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), + }, }; #define WM0010_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) -- cgit v0.10.2 From c6c0a214001ecc6c5d42c1226cdd33c07f8a016b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:28:25 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm1250-ev1 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index ec45c5b..caf5012 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c @@ -142,11 +142,12 @@ static struct snd_soc_dai_driver wm1250_ev1_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = { - .dapm_widgets = wm1250_ev1_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets), - .dapm_routes = wm1250_ev1_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes), - + .component_driver = { + .dapm_widgets = wm1250_ev1_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets), + .dapm_routes = wm1250_ev1_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes), + }, .set_bias_level = wm1250_ev1_set_bias_level, .idle_bias_off = true, }; -- cgit v0.10.2 From bd22e11e1b48c088472bc1e91c8ee3a484eaf428 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:28:43 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm2000 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index a67ea10..1ebaf99 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -805,12 +805,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm2000 = { .suspend = wm2000_suspend, .resume = wm2000_resume, - .dapm_widgets = wm2000_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm2000_dapm_widgets), - .dapm_routes = wm2000_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm2000_audio_map), - .controls = wm2000_controls, - .num_controls = ARRAY_SIZE(wm2000_controls), + .component_driver = { + .controls = wm2000_controls, + .num_controls = ARRAY_SIZE(wm2000_controls), + .dapm_widgets = wm2000_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm2000_dapm_widgets), + .dapm_routes = wm2000_audio_map, + .num_dapm_routes = ARRAY_SIZE(wm2000_audio_map), + }, }; static int wm2000_i2c_probe(struct i2c_client *i2c, -- cgit v0.10.2 From b68f37aa2e56c4281d096ca7d165c0bf663ecd2b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:28:59 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm2200 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index fd1439e..d913d0e 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2111,12 +2111,14 @@ static struct snd_soc_codec_driver soc_codec_wm2200 = { .set_sysclk = wm2200_set_sysclk, .set_pll = wm2200_set_fll, - .controls = wm2200_snd_controls, - .num_controls = ARRAY_SIZE(wm2200_snd_controls), - .dapm_widgets = wm2200_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets), - .dapm_routes = wm2200_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes), + .component_driver = { + .controls = wm2200_snd_controls, + .num_controls = ARRAY_SIZE(wm2200_snd_controls), + .dapm_widgets = wm2200_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets), + .dapm_routes = wm2200_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes), + }, }; static irqreturn_t wm2200_irq(int irq, void *data) -- cgit v0.10.2 From 99a95b23a2ad6a5f314e295ded68ea609d288e7c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:29:19 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm5100 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 512a9d2..8cbdf17 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2390,12 +2390,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { .idle_bias_off = 1, .seq_notifier = wm5100_seq_notifier, - .controls = wm5100_snd_controls, - .num_controls = ARRAY_SIZE(wm5100_snd_controls), - .dapm_widgets = wm5100_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm5100_dapm_widgets), - .dapm_routes = wm5100_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm5100_dapm_routes), + .component_driver = { + .controls = wm5100_snd_controls, + .num_controls = ARRAY_SIZE(wm5100_snd_controls), + .dapm_widgets = wm5100_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm5100_dapm_widgets), + .dapm_routes = wm5100_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm5100_dapm_routes), + }, }; static const struct regmap_config wm5100_regmap = { -- cgit v0.10.2 From 4214c3460502e3c57c7cb8269e5c4193d800c929 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:29:37 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm5102 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 846deed..1295978 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -2000,12 +2000,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5102 = { .set_sysclk = arizona_set_sysclk, .set_pll = wm5102_set_fll, - .controls = wm5102_snd_controls, - .num_controls = ARRAY_SIZE(wm5102_snd_controls), - .dapm_widgets = wm5102_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm5102_dapm_widgets), - .dapm_routes = wm5102_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes), + .component_driver = { + .controls = wm5102_snd_controls, + .num_controls = ARRAY_SIZE(wm5102_snd_controls), + .dapm_widgets = wm5102_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm5102_dapm_widgets), + .dapm_routes = wm5102_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes), + }, }; static struct snd_compr_ops wm5102_compr_ops = { -- cgit v0.10.2 From 098c0756931833068318f29d476dffc2aa694582 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:29:55 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm5110 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 1565470..3e7f873 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2357,12 +2357,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { .set_sysclk = arizona_set_sysclk, .set_pll = wm5110_set_fll, - .controls = wm5110_snd_controls, - .num_controls = ARRAY_SIZE(wm5110_snd_controls), - .dapm_widgets = wm5110_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm5110_dapm_widgets), - .dapm_routes = wm5110_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes), + .component_driver = { + .controls = wm5110_snd_controls, + .num_controls = ARRAY_SIZE(wm5110_snd_controls), + .dapm_widgets = wm5110_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm5110_dapm_widgets), + .dapm_routes = wm5110_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes), + }, }; static struct snd_compr_ops wm5110_compr_ops = { -- cgit v0.10.2 From 667a8069066093f618b3930272f52e090ca49d88 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:30:13 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8350 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index ffbf3df..18bc4ca 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -1594,12 +1594,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { .set_bias_level = wm8350_set_bias_level, .suspend_bias_off = true, - .controls = wm8350_snd_controls, - .num_controls = ARRAY_SIZE(wm8350_snd_controls), - .dapm_widgets = wm8350_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8350_dapm_widgets), - .dapm_routes = wm8350_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8350_dapm_routes), + .component_driver = { + .controls = wm8350_snd_controls, + .num_controls = ARRAY_SIZE(wm8350_snd_controls), + .dapm_widgets = wm8350_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8350_dapm_widgets), + .dapm_routes = wm8350_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8350_dapm_routes), + }, }; static int wm8350_probe(struct platform_device *pdev) -- cgit v0.10.2 From 7b5deb2d62b72effc7de9783caeeeed376e3942b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:30:34 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8400 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index b1d346a..4551e54 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -1339,12 +1339,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8400 = { .set_bias_level = wm8400_set_bias_level, .suspend_bias_off = true, - .controls = wm8400_snd_controls, - .num_controls = ARRAY_SIZE(wm8400_snd_controls), - .dapm_widgets = wm8400_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8400_dapm_widgets), - .dapm_routes = wm8400_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8400_dapm_routes), + .component_driver = { + .controls = wm8400_snd_controls, + .num_controls = ARRAY_SIZE(wm8400_snd_controls), + .dapm_widgets = wm8400_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8400_dapm_widgets), + .dapm_routes = wm8400_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8400_dapm_routes), + }, }; static int wm8400_probe(struct platform_device *pdev) -- cgit v0.10.2 From 59b06efb2374f116b4a8007d3b00ab55a5fd3cbc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:30:51 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8727 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c index bb25a75..b01e64e 100644 --- a/sound/soc/codecs/wm8727.c +++ b/sound/soc/codecs/wm8727.c @@ -54,10 +54,12 @@ static struct snd_soc_dai_driver wm8727_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_wm8727 = { - .dapm_widgets = wm8727_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8727_dapm_widgets), - .dapm_routes = wm8727_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8727_dapm_routes), + .component_driver = { + .dapm_widgets = wm8727_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8727_dapm_widgets), + .dapm_routes = wm8727_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8727_dapm_routes), + }, }; static int wm8727_probe(struct platform_device *pdev) -- cgit v0.10.2 From f56531d019f3f13d56c48619d9deeee34efccefb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:31:09 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8782 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c index fb55fd8..1e9c495 100644 --- a/sound/soc/codecs/wm8782.c +++ b/sound/soc/codecs/wm8782.c @@ -51,10 +51,12 @@ static struct snd_soc_dai_driver wm8782_dai = { }; static struct snd_soc_codec_driver soc_codec_dev_wm8782 = { - .dapm_widgets = wm8782_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8782_dapm_widgets), - .dapm_routes = wm8782_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8782_dapm_routes), + .component_driver = { + .dapm_widgets = wm8782_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8782_dapm_widgets), + .dapm_routes = wm8782_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8782_dapm_routes), + }, }; static int wm8782_probe(struct platform_device *pdev) -- cgit v0.10.2 From 496360f5a8a267d72486fb5615f04e063edd6ed0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:31:25 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8900 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5d8dca88..724cec4 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -1214,12 +1214,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { .resume = wm8900_resume, .set_bias_level = wm8900_set_bias_level, - .controls = wm8900_snd_controls, - .num_controls = ARRAY_SIZE(wm8900_snd_controls), - .dapm_widgets = wm8900_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8900_dapm_widgets), - .dapm_routes = wm8900_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes), + .component_driver = { + .controls = wm8900_snd_controls, + .num_controls = ARRAY_SIZE(wm8900_snd_controls), + .dapm_widgets = wm8900_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8900_dapm_widgets), + .dapm_routes = wm8900_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes), + }, }; static const struct regmap_config wm8900_regmap = { -- cgit v0.10.2 From 90a60b06f41880b2415720cec14ea0d830384461 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:31:43 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8940 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 1c60081..3c9febc 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -728,12 +728,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { .set_bias_level = wm8940_set_bias_level, .suspend_bias_off = true, - .controls = wm8940_snd_controls, - .num_controls = ARRAY_SIZE(wm8940_snd_controls), - .dapm_widgets = wm8940_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8940_dapm_widgets), - .dapm_routes = wm8940_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8940_dapm_routes), + .component_driver = { + .controls = wm8940_snd_controls, + .num_controls = ARRAY_SIZE(wm8940_snd_controls), + .dapm_widgets = wm8940_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8940_dapm_widgets), + .dapm_routes = wm8940_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8940_dapm_routes), + }, }; static const struct regmap_config wm8940_regmap = { -- cgit v0.10.2 From 11f473eab148571c9eb2af066b1faaddae8e4fa7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:32:00 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8955 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 9db00d5..575075d 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -945,12 +945,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { .set_bias_level = wm8955_set_bias_level, .suspend_bias_off = true, - .controls = wm8955_snd_controls, - .num_controls = ARRAY_SIZE(wm8955_snd_controls), - .dapm_widgets = wm8955_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8955_dapm_widgets), - .dapm_routes = wm8955_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8955_dapm_routes), + .component_driver = { + .controls = wm8955_snd_controls, + .num_controls = ARRAY_SIZE(wm8955_snd_controls), + .dapm_widgets = wm8955_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8955_dapm_widgets), + .dapm_routes = wm8955_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8955_dapm_routes), + }, }; static const struct regmap_config wm8955_regmap = { -- cgit v0.10.2 From 5e731b7e3bb02c60f42935efee40b9c3118d1a2f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:32:18 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8961 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index e30446a..4b51761 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -888,12 +888,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { .set_bias_level = wm8961_set_bias_level, .suspend_bias_off = true, - .controls = wm8961_snd_controls, - .num_controls = ARRAY_SIZE(wm8961_snd_controls), - .dapm_widgets = wm8961_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8961_dapm_widgets), - .dapm_routes = audio_paths, - .num_dapm_routes = ARRAY_SIZE(audio_paths), + .component_driver = { + .controls = wm8961_snd_controls, + .num_controls = ARRAY_SIZE(wm8961_snd_controls), + .dapm_widgets = wm8961_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8961_dapm_widgets), + .dapm_routes = audio_paths, + .num_dapm_routes = ARRAY_SIZE(audio_paths), + }, }; static const struct regmap_config wm8961_regmap = { -- cgit v0.10.2 From d792e7b678cded4dae6a19e00082bf885833fa19 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:32:37 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8971 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 2cdde32..214fa13 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -654,12 +654,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { .set_bias_level = wm8971_set_bias_level, .suspend_bias_off = true, - .controls = wm8971_snd_controls, - .num_controls = ARRAY_SIZE(wm8971_snd_controls), - .dapm_widgets = wm8971_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8971_dapm_widgets), - .dapm_routes = wm8971_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes), + .component_driver = { + .controls = wm8971_snd_controls, + .num_controls = ARRAY_SIZE(wm8971_snd_controls), + .dapm_widgets = wm8971_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8971_dapm_widgets), + .dapm_routes = wm8971_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes), + }, }; static const struct regmap_config wm8971_regmap = { -- cgit v0.10.2 From c79dc99cdab0f35950460172c809e7900e214fdf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:32:54 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8983 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 0c002a5..9609fc0 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -980,12 +980,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { .probe = wm8983_probe, .set_bias_level = wm8983_set_bias_level, .suspend_bias_off = true, - .controls = wm8983_snd_controls, - .num_controls = ARRAY_SIZE(wm8983_snd_controls), - .dapm_widgets = wm8983_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), - .dapm_routes = wm8983_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), + .component_driver = { + .controls = wm8983_snd_controls, + .num_controls = ARRAY_SIZE(wm8983_snd_controls), + .dapm_widgets = wm8983_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), + .dapm_routes = wm8983_audio_map, + .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), + }, }; static const struct regmap_config wm8983_regmap = { -- cgit v0.10.2 From 11f851f56336f35e2e7575465b53d5d583bbad22 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:33:11 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8988 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 895721a2..b0d0219 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -817,12 +817,14 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8988 = { .set_bias_level = wm8988_set_bias_level, .suspend_bias_off = true, - .controls = wm8988_snd_controls, - .num_controls = ARRAY_SIZE(wm8988_snd_controls), - .dapm_widgets = wm8988_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets), - .dapm_routes = wm8988_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes), + .component_driver = { + .controls = wm8988_snd_controls, + .num_controls = ARRAY_SIZE(wm8988_snd_controls), + .dapm_widgets = wm8988_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets), + .dapm_routes = wm8988_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes), + }, }; static const struct regmap_config wm8988_regmap = { -- cgit v0.10.2 From 0b71b898ff530c0acae9e32df1f884dbdf5d110f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:33:30 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8990 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 23ecd30..a412fd0 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1299,12 +1299,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { .set_bias_level = wm8990_set_bias_level, .suspend_bias_off = true, - .controls = wm8990_snd_controls, - .num_controls = ARRAY_SIZE(wm8990_snd_controls), - .dapm_widgets = wm8990_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8990_dapm_widgets), - .dapm_routes = wm8990_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8990_dapm_routes), + .component_driver = { + .controls = wm8990_snd_controls, + .num_controls = ARRAY_SIZE(wm8990_snd_controls), + .dapm_widgets = wm8990_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8990_dapm_widgets), + .dapm_routes = wm8990_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8990_dapm_routes), + }, }; static const struct regmap_config wm8990_regmap = { -- cgit v0.10.2 From 4664b5e2bf4a44ed625536a79886b4dee17ef9e1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:33:47 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8991 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index c9ee0ac..5822d10 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1236,12 +1236,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8991 = { .set_bias_level = wm8991_set_bias_level, .suspend_bias_off = true, - .controls = wm8991_snd_controls, - .num_controls = ARRAY_SIZE(wm8991_snd_controls), - .dapm_widgets = wm8991_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8991_dapm_widgets), - .dapm_routes = wm8991_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8991_dapm_routes), + .component_driver = { + .controls = wm8991_snd_controls, + .num_controls = ARRAY_SIZE(wm8991_snd_controls), + .dapm_widgets = wm8991_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8991_dapm_widgets), + .dapm_routes = wm8991_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8991_dapm_routes), + }, }; static const struct regmap_config wm8991_regmap = { -- cgit v0.10.2 From af84d1c4dd08b3a185f9ae74165c5cc0ad975559 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:34:07 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8995 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 24500ba..19b08a5 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -2192,12 +2192,14 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8995 = { .set_bias_level = wm8995_set_bias_level, .idle_bias_off = true, - .controls = wm8995_snd_controls, - .num_controls = ARRAY_SIZE(wm8995_snd_controls), - .dapm_widgets = wm8995_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8995_dapm_widgets), - .dapm_routes = wm8995_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8995_intercon), + .component_driver = { + .controls = wm8995_snd_controls, + .num_controls = ARRAY_SIZE(wm8995_snd_controls), + .dapm_widgets = wm8995_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8995_dapm_widgets), + .dapm_routes = wm8995_intercon, + .num_dapm_routes = ARRAY_SIZE(wm8995_intercon), + }, }; static const struct regmap_config wm8995_regmap = { -- cgit v0.10.2 From efee13aa36cb96f78bf2410fa488e60e021a707e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:34:24 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8996 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index a730442..abacf6c 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -2690,12 +2690,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8996 = { .set_bias_level = wm8996_set_bias_level, .idle_bias_off = true, .seq_notifier = wm8996_seq_notifier, - .controls = wm8996_snd_controls, - .num_controls = ARRAY_SIZE(wm8996_snd_controls), - .dapm_widgets = wm8996_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8996_dapm_widgets), - .dapm_routes = wm8996_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8996_dapm_routes), + .component_driver = { + .controls = wm8996_snd_controls, + .num_controls = ARRAY_SIZE(wm8996_snd_controls), + .dapm_widgets = wm8996_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8996_dapm_widgets), + .dapm_routes = wm8996_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8996_dapm_routes), + }, .set_pll = wm8996_set_fll, }; -- cgit v0.10.2 From 4df0f6203e82c38aa7ec59ab706e7aa4d410ad45 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:34:40 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8997 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 6b0785b..cf23a6b 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -1105,12 +1105,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8997 = { .set_sysclk = arizona_set_sysclk, .set_pll = wm8997_set_fll, - .controls = wm8997_snd_controls, - .num_controls = ARRAY_SIZE(wm8997_snd_controls), - .dapm_widgets = wm8997_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8997_dapm_widgets), - .dapm_routes = wm8997_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8997_dapm_routes), + .component_driver = { + .controls = wm8997_snd_controls, + .num_controls = ARRAY_SIZE(wm8997_snd_controls), + .dapm_widgets = wm8997_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8997_dapm_widgets), + .dapm_routes = wm8997_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8997_dapm_routes), + }, }; static int wm8997_probe(struct platform_device *pdev) -- cgit v0.10.2 From 38addd95b81ac84bec4b33fbae739e96fae6e588 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:34:58 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm8998 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 3a5c896..315b23b 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -1361,12 +1361,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8998 = { .set_sysclk = arizona_set_sysclk, .set_pll = wm8998_set_fll, - .controls = wm8998_snd_controls, - .num_controls = ARRAY_SIZE(wm8998_snd_controls), - .dapm_widgets = wm8998_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8998_dapm_widgets), - .dapm_routes = wm8998_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8998_dapm_routes), + .component_driver = { + .controls = wm8998_snd_controls, + .num_controls = ARRAY_SIZE(wm8998_snd_controls), + .dapm_widgets = wm8998_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8998_dapm_widgets), + .dapm_routes = wm8998_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8998_dapm_routes), + }, }; static int wm8998_probe(struct platform_device *pdev) -- cgit v0.10.2 From 216cf784ddea751d930b9e9b77a1b8b5db5cb434 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:35:15 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm9081 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 363b3b6..30eaf4c 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -1282,12 +1282,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { .idle_bias_off = true, - .controls = wm9081_snd_controls, - .num_controls = ARRAY_SIZE(wm9081_snd_controls), - .dapm_widgets = wm9081_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets), - .dapm_routes = wm9081_audio_paths, - .num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths), + .component_driver = { + .controls = wm9081_snd_controls, + .num_controls = ARRAY_SIZE(wm9081_snd_controls), + .dapm_widgets = wm9081_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets), + .dapm_routes = wm9081_audio_paths, + .num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths), + }, }; static const struct regmap_config wm9081_regmap = { -- cgit v0.10.2 From 2fa1f30af91be69158bf86fa9e4d474c0bc955dc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:35:34 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm9705 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 744842c..c88492d 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -364,12 +364,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { .reg_cache_step = 2, .reg_cache_default = wm9705_reg, - .controls = wm9705_snd_ac97_controls, - .num_controls = ARRAY_SIZE(wm9705_snd_ac97_controls), - .dapm_widgets = wm9705_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), - .dapm_routes = wm9705_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm9705_audio_map), + .component_driver = { + .controls = wm9705_snd_ac97_controls, + .num_controls = ARRAY_SIZE(wm9705_snd_ac97_controls), + .dapm_widgets = wm9705_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), + .dapm_routes = wm9705_audio_map, + .num_dapm_routes = ARRAY_SIZE(wm9705_audio_map), + }, }; static int wm9705_probe(struct platform_device *pdev) -- cgit v0.10.2 From 3123e54b341485e022010b263d3c80cafa5ebf1e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:35:53 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm9712 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 488a922..e5aafdd 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -682,12 +682,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { .reg_cache_step = 2, .reg_cache_default = wm9712_reg, - .controls = wm9712_snd_ac97_controls, - .num_controls = ARRAY_SIZE(wm9712_snd_ac97_controls), - .dapm_widgets = wm9712_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets), - .dapm_routes = wm9712_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm9712_audio_map), + .component_driver = { + .controls = wm9712_snd_ac97_controls, + .num_controls = ARRAY_SIZE(wm9712_snd_ac97_controls), + .dapm_widgets = wm9712_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets), + .dapm_routes = wm9712_audio_map, + .num_dapm_routes = ARRAY_SIZE(wm9712_audio_map), + }, }; static int wm9712_probe(struct platform_device *pdev) -- cgit v0.10.2 From 2c452dd8af9da98b4b0ae1f12f8059160c7b11b5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 8 Aug 2016 09:36:29 +0000 Subject: ASoC: codec duplicated callback function goes to component on wm9713 codec driver and component driver has duplicated callback functions, and codec side functions are just copied to component side when register timing. This was quick-hack, but no longer needed. This patch moves these functions from codec driver to component driver. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 9849643..255a7c2 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1242,12 +1242,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { .resume = wm9713_soc_resume, .set_bias_level = wm9713_set_bias_level, - .controls = wm9713_snd_ac97_controls, - .num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls), - .dapm_widgets = wm9713_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), - .dapm_routes = wm9713_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm9713_audio_map), + .component_driver = { + .controls = wm9713_snd_ac97_controls, + .num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls), + .dapm_widgets = wm9713_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), + .dapm_routes = wm9713_audio_map, + .num_dapm_routes = ARRAY_SIZE(wm9713_audio_map), + }, }; static int wm9713_probe(struct platform_device *pdev) -- cgit v0.10.2 From 8799af0d823512c2ce6ba52259dedfebc84793e2 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Mon, 8 Aug 2016 15:35:23 +0100 Subject: ASoC: da7218: Remove 32KHz PLL mode from driver Functionality has been removed in latest silicon variants. This patch removes the feature from the driver to align. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index 99ce23e..f443519 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -1819,7 +1819,7 @@ static int da7218_set_dai_sysclk(struct snd_soc_dai *codec_dai, if (da7218->mclk_rate == freq) return 0; - if (((freq < 2000000) && (freq != 32768)) || (freq > 54000000)) { + if ((freq < 2000000) || (freq > 54000000)) { dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", freq); return -EINVAL; @@ -1866,11 +1866,8 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, u32 freq_ref; u64 frac_div; - /* Verify 32KHz, 2MHz - 54MHz MCLK provided, and set input divider */ - if (da7218->mclk_rate == 32768) { - indiv_bits = DA7218_PLL_INDIV_9_TO_18_MHZ; - indiv = DA7218_PLL_INDIV_9_TO_18_MHZ_VAL; - } else if (da7218->mclk_rate < 2000000) { + /* Verify 2MHz - 54MHz MCLK provided, and set input divider */ + if (da7218->mclk_rate < 2000000) { dev_err(codec->dev, "PLL input clock %d below valid range\n", da7218->mclk_rate); return -EINVAL; @@ -1911,9 +1908,6 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, case DA7218_SYSCLK_PLL_SRM: pll_ctrl |= DA7218_PLL_MODE_SRM; break; - case DA7218_SYSCLK_PLL_32KHZ: - pll_ctrl |= DA7218_PLL_MODE_32KHZ; - break; default: dev_err(codec->dev, "Invalid PLL config\n"); return -EINVAL; diff --git a/sound/soc/codecs/da7218.h b/sound/soc/codecs/da7218.h index 477cd37..4f7ec21 100644 --- a/sound/soc/codecs/da7218.h +++ b/sound/soc/codecs/da7218.h @@ -888,7 +888,6 @@ #define DA7218_PLL_MODE_BYPASS (0x0 << 6) #define DA7218_PLL_MODE_NORMAL (0x1 << 6) #define DA7218_PLL_MODE_SRM (0x2 << 6) -#define DA7218_PLL_MODE_32KHZ (0x3 << 6) /* DA7218_PLL_FRAC_TOP = 0x92 */ #define DA7218_PLL_FBDIV_FRAC_TOP_SHIFT 0 @@ -1371,7 +1370,6 @@ enum da7218_sys_clk { DA7218_SYSCLK_MCLK = 0, DA7218_SYSCLK_PLL, DA7218_SYSCLK_PLL_SRM, - DA7218_SYSCLK_PLL_32KHZ }; enum da7218_dev_id { -- cgit v0.10.2 From 72dce368926167811c10ef094deba524e1ca274f Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Mon, 8 Aug 2016 15:35:24 +0100 Subject: ASoC: da7218: Improve driver efficiency with regards to MCLK usage Currently MCLK remains enabled during bias STANDBY state, and this is not necessary. This patch updates the code to handle enabling and disabling of MCLK, if provided, when moving between STANDBY and PREPARE states, therefore saving power when no active streams present. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index f443519..e7f3e4c 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -2583,20 +2583,22 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: break; - case SND_SOC_BIAS_STANDBY: - if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { - /* MCLK */ + case SND_SOC_BIAS_PREPARE: + /* Enable MCLK for transition to ON state */ + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { if (da7218->mclk) { ret = clk_prepare_enable(da7218->mclk); if (ret) { - dev_err(codec->dev, - "Failed to enable mclk\n"); + dev_err(codec->dev, "Failed to enable mclk\n"); return ret; } } + } + break; + case SND_SOC_BIAS_STANDBY: + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { /* Master bias */ snd_soc_update_bits(codec, DA7218_REFERENCES, DA7218_BIAS_EN_MASK, @@ -2606,6 +2608,10 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec, snd_soc_update_bits(codec, DA7218_LDO_CTRL, DA7218_LDO_EN_MASK, DA7218_LDO_EN_MASK); + } else { + /* Remove MCLK */ + if (da7218->mclk) + clk_disable_unprepare(da7218->mclk); } break; case SND_SOC_BIAS_OFF: @@ -2619,10 +2625,6 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec, snd_soc_update_bits(codec, DA7218_REFERENCES, DA7218_BIAS_EN_MASK, 0); } - - /* MCLK */ - if (da7218->mclk) - clk_disable_unprepare(da7218->mclk); break; } -- cgit v0.10.2 From 6720b38420a01d40dbeb8ee575eb601d612de691 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 4 Aug 2016 15:46:00 +0530 Subject: ALSA: hda - move bus_parse_capabilities to core HDA capability introduced recently are move to hdac core so that it can be used by legacy driver as well. Also move the capability pointers up to hdac_bus object. Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 93e63c5..56004ec 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -245,6 +245,12 @@ struct hdac_rb { /* * HD-audio bus base driver + * + * @ppcap: pp capabilities pointer + * @spbcap: SPIB capabilities pointer + * @mlcap: MultiLink capabilities pointer + * @gtscap: gts capabilities pointer + * @drsmcap: dma resume capabilities pointer */ struct hdac_bus { struct device *dev; @@ -256,6 +262,12 @@ struct hdac_bus { void __iomem *remap_addr; int irq; + void __iomem *ppcap; + void __iomem *spbcap; + void __iomem *mlcap; + void __iomem *gtscap; + void __iomem *drsmcap; + /* codec linked list */ struct list_head codec_list; unsigned int num_codecs; @@ -335,6 +347,7 @@ static inline void snd_hdac_codec_link_down(struct hdac_device *codec) int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val); int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, unsigned int *res); +int snd_hdac_bus_parse_capabilities(struct hdac_bus *bus); int snd_hdac_link_power(struct hdac_device *codec, bool enable); bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset); diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index 9fee464..0430658 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -255,6 +255,81 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, } EXPORT_SYMBOL_GPL(snd_hdac_bus_get_response); +#define HDAC_MAX_CAPS 10 +/** + * snd_hdac_bus_parse_capabilities - parse capability structure + * @bus: the pointer to bus object + * + * Returns 0 if successful, or a negative error code. + */ +int snd_hdac_bus_parse_capabilities(struct hdac_bus *bus) +{ + unsigned int cur_cap; + unsigned int offset; + unsigned int counter = 0; + + offset = snd_hdac_chip_readl(bus, LLCH); + + /* Lets walk the linked capabilities list */ + do { + cur_cap = _snd_hdac_chip_read(l, bus, offset); + + dev_dbg(bus->dev, "Capability version: 0x%x\n", + (cur_cap & AZX_CAP_HDR_VER_MASK) >> AZX_CAP_HDR_VER_OFF); + + dev_dbg(bus->dev, "HDA capability ID: 0x%x\n", + (cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF); + + switch ((cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF) { + case AZX_ML_CAP_ID: + dev_dbg(bus->dev, "Found ML capability\n"); + bus->mlcap = bus->remap_addr + offset; + break; + + case AZX_GTS_CAP_ID: + dev_dbg(bus->dev, "Found GTS capability offset=%x\n", offset); + bus->gtscap = bus->remap_addr + offset; + break; + + case AZX_PP_CAP_ID: + /* PP capability found, the Audio DSP is present */ + dev_dbg(bus->dev, "Found PP capability offset=%x\n", offset); + bus->ppcap = bus->remap_addr + offset; + break; + + case AZX_SPB_CAP_ID: + /* SPIB capability found, handler function */ + dev_dbg(bus->dev, "Found SPB capability\n"); + bus->spbcap = bus->remap_addr + offset; + break; + + case AZX_DRSM_CAP_ID: + /* DMA resume capability found, handler function */ + dev_dbg(bus->dev, "Found DRSM capability\n"); + bus->drsmcap = bus->remap_addr + offset; + break; + + default: + dev_dbg(bus->dev, "Unknown capability %d\n", cur_cap); + break; + } + + counter++; + + if (counter > HDAC_MAX_CAPS) { + dev_err(bus->dev, "We exceeded HDAC capabilities!!!\n"); + break; + } + + /* read the offset of next capability */ + offset = cur_cap & AZX_CAP_HDR_NXT_PTR_MASK; + + } while (offset); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_hdac_bus_parse_capabilities); + /* * Lowlevel interface */ -- cgit v0.10.2 From ec8ae5703da1b8bd057b4e319567ddbcac295b3a Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 4 Aug 2016 15:46:01 +0530 Subject: ALSA: convert users to core bus_parse_capabilities Now that we have the bus parse capabilities moved to core, we need to convert users. The SKL driver and HDA extended lib needs to converted in single patch, otherwise we regress on the functionality. Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index 860f8ca..cd65e00 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -118,15 +118,15 @@ void snd_hdac_ext_bus_ppcap_enable(struct hdac_ext_bus *ebus, bool enable) { struct hdac_bus *bus = &ebus->bus; - if (!ebus->ppcap) { + if (!bus->ppcap) { dev_err(bus->dev, "Address of PP capability is NULL"); return; } if (enable) - snd_hdac_updatel(ebus->ppcap, AZX_REG_PP_PPCTL, 0, AZX_PPCTL_GPROCEN); + snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, 0, AZX_PPCTL_GPROCEN); else - snd_hdac_updatel(ebus->ppcap, AZX_REG_PP_PPCTL, AZX_PPCTL_GPROCEN, 0); + snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, AZX_PPCTL_GPROCEN, 0); } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_enable); @@ -139,15 +139,15 @@ void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_ext_bus *ebus, bool enable) { struct hdac_bus *bus = &ebus->bus; - if (!ebus->ppcap) { + if (!bus->ppcap) { dev_err(bus->dev, "Address of PP capability is NULL\n"); return; } if (enable) - snd_hdac_updatel(ebus->ppcap, AZX_REG_PP_PPCTL, 0, AZX_PPCTL_PIE); + snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, 0, AZX_PPCTL_PIE); else - snd_hdac_updatel(ebus->ppcap, AZX_REG_PP_PPCTL, AZX_PPCTL_PIE, 0); + snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, AZX_PPCTL_PIE, 0); } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_int_enable); @@ -171,7 +171,7 @@ int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *ebus) struct hdac_ext_link *hlink; struct hdac_bus *bus = &ebus->bus; - link_count = readl(ebus->mlcap + AZX_REG_ML_MLCD) + 1; + link_count = readl(bus->mlcap + AZX_REG_ML_MLCD) + 1; dev_dbg(bus->dev, "In %s Link count: %d\n", __func__, link_count); @@ -181,7 +181,7 @@ int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_ext_bus *ebus) return -ENOMEM; hlink->index = idx; hlink->bus = bus; - hlink->ml_addr = ebus->mlcap + AZX_ML_BASE + + hlink->ml_addr = bus->mlcap + AZX_ML_BASE + (AZX_ML_INTERVAL * idx); hlink->lcaps = readl(hlink->ml_addr + AZX_REG_ML_LCAP); hlink->lsdiid = readw(hlink->ml_addr + AZX_REG_ML_LSDIID); diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 626f3bb..2441273 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -40,27 +40,27 @@ void snd_hdac_ext_stream_init(struct hdac_ext_bus *ebus, { struct hdac_bus *bus = &ebus->bus; - if (ebus->ppcap) { - stream->pphc_addr = ebus->ppcap + AZX_PPHC_BASE + + if (bus->ppcap) { + stream->pphc_addr = bus->ppcap + AZX_PPHC_BASE + AZX_PPHC_INTERVAL * idx; - stream->pplc_addr = ebus->ppcap + AZX_PPLC_BASE + + stream->pplc_addr = bus->ppcap + AZX_PPLC_BASE + AZX_PPLC_MULTI * ebus->num_streams + AZX_PPLC_INTERVAL * idx; } - if (ebus->spbcap) { - stream->spib_addr = ebus->spbcap + AZX_SPB_BASE + + if (bus->spbcap) { + stream->spib_addr = bus->spbcap + AZX_SPB_BASE + AZX_SPB_INTERVAL * idx + AZX_SPB_SPIB; - stream->fifo_addr = ebus->spbcap + AZX_SPB_BASE + + stream->fifo_addr = bus->spbcap + AZX_SPB_BASE + AZX_SPB_INTERVAL * idx + AZX_SPB_MAXFIFO; } - if (ebus->drsmcap) - stream->dpibr_addr = ebus->drsmcap + AZX_DRSM_BASE + + if (bus->drsmcap) + stream->dpibr_addr = bus->drsmcap + AZX_DRSM_BASE + AZX_DRSM_INTERVAL * idx; stream->decoupled = false; @@ -131,10 +131,10 @@ void snd_hdac_ext_stream_decouple(struct hdac_ext_bus *ebus, spin_lock_irq(&bus->reg_lock); if (decouple) - snd_hdac_updatel(ebus->ppcap, AZX_REG_PP_PPCTL, 0, + snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, 0, AZX_PPCTL_PROCEN(hstream->index)); else - snd_hdac_updatel(ebus->ppcap, AZX_REG_PP_PPCTL, + snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, AZX_PPCTL_PROCEN(hstream->index), 0); stream->decoupled = decouple; spin_unlock_irq(&bus->reg_lock); @@ -255,7 +255,7 @@ hdac_ext_link_stream_assign(struct hdac_ext_bus *ebus, struct hdac_stream *stream = NULL; struct hdac_bus *hbus = &ebus->bus; - if (!ebus->ppcap) { + if (!hbus->ppcap) { dev_err(hbus->dev, "stream type not supported\n"); return NULL; } @@ -296,7 +296,7 @@ hdac_ext_host_stream_assign(struct hdac_ext_bus *ebus, struct hdac_stream *stream = NULL; struct hdac_bus *hbus = &ebus->bus; - if (!ebus->ppcap) { + if (!hbus->ppcap) { dev_err(hbus->dev, "stream type not supported\n"); return NULL; } @@ -423,21 +423,21 @@ void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *ebus, u32 register_mask = 0; struct hdac_bus *bus = &ebus->bus; - if (!ebus->spbcap) { + if (!bus->spbcap) { dev_err(bus->dev, "Address of SPB capability is NULL"); return; } mask |= (1 << index); - register_mask = readl(ebus->spbcap + AZX_REG_SPB_SPBFCCTL); + register_mask = readl(bus->spbcap + AZX_REG_SPB_SPBFCCTL); mask |= register_mask; if (enable) - snd_hdac_updatel(ebus->spbcap, AZX_REG_SPB_SPBFCCTL, 0, mask); + snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, 0, mask); else - snd_hdac_updatel(ebus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, 0); + snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, 0); } EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_spbcap_enable); @@ -452,7 +452,7 @@ int snd_hdac_ext_stream_set_spib(struct hdac_ext_bus *ebus, { struct hdac_bus *bus = &ebus->bus; - if (!ebus->spbcap) { + if (!bus->spbcap) { dev_err(bus->dev, "Address of SPB capability is NULL"); return -EINVAL; } @@ -475,7 +475,7 @@ int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_ext_bus *ebus, { struct hdac_bus *bus = &ebus->bus; - if (!ebus->spbcap) { + if (!bus->spbcap) { dev_err(bus->dev, "Address of SPB capability is NULL"); return -EINVAL; } @@ -515,21 +515,21 @@ void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus, u32 register_mask = 0; struct hdac_bus *bus = &ebus->bus; - if (!ebus->drsmcap) { + if (!bus->drsmcap) { dev_err(bus->dev, "Address of DRSM capability is NULL"); return; } mask |= (1 << index); - register_mask = readl(ebus->drsmcap + AZX_REG_SPB_SPBFCCTL); + register_mask = readl(bus->drsmcap + AZX_REG_SPB_SPBFCCTL); mask |= register_mask; if (enable) - snd_hdac_updatel(ebus->drsmcap, AZX_REG_DRSM_CTL, 0, mask); + snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, 0, mask); else - snd_hdac_updatel(ebus->drsmcap, AZX_REG_DRSM_CTL, mask, 0); + snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, mask, 0); } EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_drsm_enable); @@ -544,7 +544,7 @@ int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus, { struct hdac_bus *bus = &ebus->bus; - if (!ebus->drsmcap) { + if (!bus->drsmcap) { dev_err(bus->dev, "Address of DRSM capability is NULL"); return -EINVAL; } diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 44ab595..83a731f 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -296,7 +296,7 @@ int skl_suspend_dsp(struct skl *skl) int ret; /* if ppcap is not supported return 0 */ - if (!skl->ebus.ppcap) + if (!skl->ebus.bus.ppcap) return 0; ret = skl_dsp_sleep(ctx->dsp); @@ -316,7 +316,7 @@ int skl_resume_dsp(struct skl *skl) int ret; /* if ppcap is not supported return 0 */ - if (!skl->ebus.ppcap) + if (!skl->ebus.bus.ppcap) return 0; /* enable ppcap interrupt */ diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 6e05bf8..5ae86c2 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -106,7 +106,7 @@ static void skl_set_pcm_constrains(struct hdac_ext_bus *ebus, static enum hdac_ext_stream_type skl_get_host_stream_type(struct hdac_ext_bus *ebus) { - if (ebus->ppcap) + if ((ebus_to_hbus(ebus))->ppcap) return HDAC_EXT_STREAM_TYPE_HOST; else return HDAC_EXT_STREAM_TYPE_COUPLED; @@ -188,7 +188,7 @@ static int skl_get_format(struct snd_pcm_substream *substream, struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); int format_val = 0; - if (ebus->ppcap) { + if ((ebus_to_hbus(ebus))->ppcap) { struct snd_pcm_runtime *runtime = substream->runtime; format_val = snd_hdac_calc_stream_format(runtime->rate, @@ -1020,7 +1020,7 @@ static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream, { struct hdac_ext_bus *ebus = get_bus_ctx(substream); - if (!ebus->ppcap) + if ((ebus_to_hbus(ebus))->ppcap) return skl_coupled_trigger(substream, cmd); return 0; @@ -1144,7 +1144,7 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform) struct skl *skl = ebus_to_skl(ebus); int ret; - if (ebus->ppcap) { + if ((ebus_to_hbus(ebus))->ppcap) { ret = skl_tplg_init(platform, ebus); if (ret < 0) { dev_err(platform->dev, "Failed to init topology!\n"); diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index cd59536..a893ca1 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -587,7 +587,7 @@ static int skl_first_init(struct hdac_ext_bus *ebus) return -ENXIO; } - snd_hdac_ext_bus_parse_capabilities(ebus); + snd_hdac_bus_parse_capabilities(bus); if (skl_acquire_irq(ebus, 0) < 0) return -EBUSY; @@ -682,7 +682,7 @@ static int skl_probe(struct pci_dev *pci, skl_dmic_data.dmic_num = skl_get_dmic_geo(skl); /* check if dsp is there */ - if (ebus->ppcap) { + if (bus->ppcap) { err = skl_machine_device_register(skl, (void *)pci_id->driver_data); if (err < 0) @@ -696,7 +696,7 @@ static int skl_probe(struct pci_dev *pci, skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge; } - if (ebus->mlcap) + if (bus->mlcap) snd_hdac_ext_bus_get_ml_capabilities(ebus); /* create device for soc dmic */ -- cgit v0.10.2 From 404735c9fd8adff8e5ad11e1f9f8db069d865698 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 4 Aug 2016 15:46:02 +0530 Subject: ALSA - Ext hda: remove bus_parse_capabilities Remove the unused one as we have moved it up to hdac core. Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index b9593b2..8660a7f 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -8,11 +8,6 @@ * * @bus: hdac bus * @num_streams: streams supported - * @ppcap: pp capabilities pointer - * @spbcap: SPIB capabilities pointer - * @mlcap: MultiLink capabilities pointer - * @gtscap: gts capabilities pointer - * @drsmcap: dma resume capabilities pointer * @hlink_list: link list of HDA links * @lock: lock for link mgmt * @cmd_dma_state: state of cmd DMAs: CORB and RIRB @@ -22,12 +17,6 @@ struct hdac_ext_bus { int num_streams; int idx; - void __iomem *ppcap; - void __iomem *spbcap; - void __iomem *mlcap; - void __iomem *gtscap; - void __iomem *drsmcap; - struct list_head hlink_list; struct mutex lock; @@ -54,7 +43,6 @@ void snd_hdac_ext_bus_device_remove(struct hdac_ext_bus *ebus); #define HDA_CODEC_EXT_ENTRY(_vid, _revid, _name, _drv_data) \ HDA_CODEC_REV_EXT_ENTRY(_vid, _revid, _name, _drv_data) -int snd_hdac_ext_bus_parse_capabilities(struct hdac_ext_bus *sbus); void snd_hdac_ext_bus_ppcap_enable(struct hdac_ext_bus *chip, bool enable); void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_ext_bus *chip, bool enable); diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index cd65e00..2614691 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -29,81 +29,6 @@ */ #define HDAC_MAX_CAPS 10 -/** - * snd_hdac_ext_bus_parse_capabilities - parse capablity structure - * @ebus: the pointer to extended bus object - * - * Returns 0 if successful, or a negative error code. - */ -int snd_hdac_ext_bus_parse_capabilities(struct hdac_ext_bus *ebus) -{ - unsigned int cur_cap; - unsigned int offset; - struct hdac_bus *bus = &ebus->bus; - unsigned int counter = 0; - - offset = snd_hdac_chip_readl(bus, LLCH); - - /* Lets walk the linked capabilities list */ - do { - cur_cap = _snd_hdac_chip_read(l, bus, offset); - - dev_dbg(bus->dev, "Capability version: 0x%x\n", - ((cur_cap & AZX_CAP_HDR_VER_MASK) >> AZX_CAP_HDR_VER_OFF)); - - dev_dbg(bus->dev, "HDA capability ID: 0x%x\n", - (cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF); - - switch ((cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF) { - case AZX_ML_CAP_ID: - dev_dbg(bus->dev, "Found ML capability\n"); - ebus->mlcap = bus->remap_addr + offset; - break; - - case AZX_GTS_CAP_ID: - dev_dbg(bus->dev, "Found GTS capability offset=%x\n", offset); - ebus->gtscap = bus->remap_addr + offset; - break; - - case AZX_PP_CAP_ID: - /* PP capability found, the Audio DSP is present */ - dev_dbg(bus->dev, "Found PP capability offset=%x\n", offset); - ebus->ppcap = bus->remap_addr + offset; - break; - - case AZX_SPB_CAP_ID: - /* SPIB capability found, handler function */ - dev_dbg(bus->dev, "Found SPB capability\n"); - ebus->spbcap = bus->remap_addr + offset; - break; - - case AZX_DRSM_CAP_ID: - /* DMA resume capability found, handler function */ - dev_dbg(bus->dev, "Found DRSM capability\n"); - ebus->drsmcap = bus->remap_addr + offset; - break; - - default: - dev_dbg(bus->dev, "Unknown capability %d\n", cur_cap); - break; - } - - counter++; - - if (counter > HDAC_MAX_CAPS) { - dev_err(bus->dev, "We exceeded HDAC Ext capablities!!!\n"); - break; - } - - /* read the offset of next capabiity */ - offset = cur_cap & AZX_CAP_HDR_NXT_PTR_MASK; - - } while (offset); - - return 0; -} -EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_parse_capabilities); - /* * processing pipe helpers - these helpers are useful for dealing with HDA * new capability of processing pipelines -- cgit v0.10.2 From 50279d9b5facde811280afe13dd8c79f0e7b21ed Mon Sep 17 00:00:00 2001 From: Guneshwor Singh Date: Thu, 4 Aug 2016 15:46:03 +0530 Subject: ALSA - hda: Add support for parsing new HDA capabilities Skylake onwards HDA controller supports new capabilities like Global Time Stamping (GTS) capability. So add support to parse these new capabilities. Signed-off-by: Guneshwor Singh Signed-off-by: Hardik T Shah Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h index ff1aecf..0013063 100644 --- a/include/sound/hda_register.h +++ b/include/sound/hda_register.h @@ -89,6 +89,19 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define AZX_REG_SD_BDLPL 0x18 #define AZX_REG_SD_BDLPU 0x1c +/* GTS registers */ +#define AZX_REG_LLCH 0x14 + +#define AZX_REG_GTS_BASE 0x520 + +#define AZX_REG_GTSCC (AZX_REG_GTS_BASE + 0x00) +#define AZX_REG_WALFCC (AZX_REG_GTS_BASE + 0x04) +#define AZX_REG_TSCCL (AZX_REG_GTS_BASE + 0x08) +#define AZX_REG_TSCCU (AZX_REG_GTS_BASE + 0x0C) +#define AZX_REG_LLPFOC (AZX_REG_GTS_BASE + 0x14) +#define AZX_REG_LLPCL (AZX_REG_GTS_BASE + 0x18) +#define AZX_REG_LLPCU (AZX_REG_GTS_BASE + 0x1C) + /* Haswell/Broadwell display HD-A controller Extended Mode registers */ #define AZX_REG_HSW_EM4 0x100c #define AZX_REG_HSW_EM5 0x1010 @@ -242,6 +255,29 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; /* Interval used to calculate the iterating register offset */ #define AZX_DRSM_INTERVAL 0x08 +/* Global time synchronization registers */ +#define GTSCC_TSCCD_MASK 0x80000000 +#define GTSCC_TSCCD_SHIFT BIT(31) +#define GTSCC_TSCCI_MASK 0x20 +#define GTSCC_CDMAS_DMA_DIR_SHIFT 4 + +#define WALFCC_CIF_MASK 0x1FF +#define WALFCC_FN_SHIFT 9 +#define HDA_CLK_CYCLES_PER_FRAME 512 + +/* + * An error occurs near frame "rollover". The clocks in frame value indicates + * whether this error may have occurred. Here we use the value of 10. Please + * see the errata for the right number [<10] + */ +#define HDA_MAX_CYCLE_VALUE 499 +#define HDA_MAX_CYCLE_OFFSET 10 +#define HDA_MAX_CYCLE_READ_RETRY 10 + +#define TSCCU_CCU_SHIFT 32 +#define LLPC_CCU_SHIFT 32 + + /* * helpers to read the stream position */ diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 27de801..1567fe2 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -412,6 +412,11 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) goto unlock; } runtime->private_data = azx_dev; + + if (chip->gts_present) + azx_pcm_hw.info = azx_pcm_hw.info | + SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME; + runtime->hw = azx_pcm_hw; runtime->hw.channels_min = hinfo->channels_min; runtime->hw.channels_max = hinfo->channels_max; diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index ec63bbf..a50e053 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -159,6 +159,9 @@ struct azx { unsigned int region_requested:1; unsigned int disabled:1; /* disabled by vga_switcheroo */ + /* GTS present */ + unsigned int gts_present:1; + #ifdef CONFIG_SND_HDA_DSP_LOADER struct azx_dev saved_azx_dev; #endif diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 89dacf9..4786f43 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -54,6 +54,7 @@ /* for snoop control */ #include #include +#include #endif #include #include @@ -1655,6 +1656,22 @@ static int azx_first_init(struct azx *chip) return -ENXIO; } + if (IS_SKL_PLUS(pci)) + snd_hdac_bus_parse_capabilities(bus); + + /* + * Some Intel CPUs has always running timer (ART) feature and + * controller may have Global time sync reporting capability, so + * check both of these before declaring synchronized time reporting + * capability SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME + */ + chip->gts_present = false; + +#ifdef CONFIG_X86 + if (bus->ppcap && boot_cpu_has(X86_FEATURE_ART)) + chip->gts_present = true; +#endif + if (chip->msi) { if (chip->driver_caps & AZX_DCAPS_NO_MSI64) { dev_dbg(card->dev, "Disabling 64bit MSI\n"); -- cgit v0.10.2 From bfcba288b97f10c22fb84f0898ebfb6b468b80ea Mon Sep 17 00:00:00 2001 From: Guneshwor Singh Date: Thu, 4 Aug 2016 15:46:04 +0530 Subject: ALSA - hda: Add support for link audio time reporting The HDA controller from SKL onwards support additional timestamp reporting of the link time. The link time is read from HW registers and converted to audio values. Signed-off-by: Guneshwor Singh Signed-off-by: Hardik T Shah Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 1567fe2..2ad3b44 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -27,6 +27,12 @@ #include #include #include + +#ifdef CONFIG_X86 +/* for art-tsc conversion */ +#include +#endif + #include #include #include "hda_controller.h" @@ -337,12 +343,173 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) azx_get_position(chip, azx_dev)); } +/* + * azx_scale64: Scale base by mult/div while not overflowing sanely + * + * Derived from scale64_check_overflow in kernel/time/timekeeping.c + * + * The tmestamps for a 48Khz stream can overflow after (2^64/10^9)/48K which + * is about 384307 ie ~4.5 days. + * + * This scales the calculation so that overflow will happen but after 2^64 / + * 48000 secs, which is pretty large! + * + * In caln below: + * base may overflow, but since there isn’t any additional division + * performed on base it’s OK + * rem can’t overflow because both are 32-bit values + */ + +#ifdef CONFIG_X86 +static u64 azx_scale64(u64 base, u32 num, u32 den) +{ + u64 rem; + + rem = do_div(base, den); + + base *= num; + rem *= num; + + do_div(rem, den); + + return base + rem; +} + +static int azx_get_sync_time(ktime_t *device, + struct system_counterval_t *system, void *ctx) +{ + struct snd_pcm_substream *substream = ctx; + struct azx_dev *azx_dev = get_azx_dev(substream); + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct azx *chip = apcm->chip; + struct snd_pcm_runtime *runtime; + u64 ll_counter, ll_counter_l, ll_counter_h; + u64 tsc_counter, tsc_counter_l, tsc_counter_h; + u32 wallclk_ctr, wallclk_cycles; + bool direction; + u32 dma_select; + u32 timeout = 200; + u32 retry_count = 0; + + runtime = substream->runtime; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + direction = 1; + else + direction = 0; + + /* 0th stream tag is not used, so DMA ch 0 is for 1st stream tag */ + do { + timeout = 100; + dma_select = (direction << GTSCC_CDMAS_DMA_DIR_SHIFT) | + (azx_dev->core.stream_tag - 1); + snd_hdac_chip_writel(azx_bus(chip), GTSCC, dma_select); + + /* Enable the capture */ + snd_hdac_chip_updatel(azx_bus(chip), GTSCC, 0, GTSCC_TSCCI_MASK); + + while (timeout) { + if (snd_hdac_chip_readl(azx_bus(chip), GTSCC) & + GTSCC_TSCCD_MASK) + break; + + timeout--; + } + + if (!timeout) { + dev_err(chip->card->dev, "GTSCC capture Timedout!\n"); + return -EIO; + } + + /* Read wall clock counter */ + wallclk_ctr = snd_hdac_chip_readl(azx_bus(chip), WALFCC); + + /* Read TSC counter */ + tsc_counter_l = snd_hdac_chip_readl(azx_bus(chip), TSCCL); + tsc_counter_h = snd_hdac_chip_readl(azx_bus(chip), TSCCU); + + /* Read Link counter */ + ll_counter_l = snd_hdac_chip_readl(azx_bus(chip), LLPCL); + ll_counter_h = snd_hdac_chip_readl(azx_bus(chip), LLPCU); + + /* Ack: registers read done */ + snd_hdac_chip_writel(azx_bus(chip), GTSCC, GTSCC_TSCCD_SHIFT); + + tsc_counter = (tsc_counter_h << TSCCU_CCU_SHIFT) | + tsc_counter_l; + + ll_counter = (ll_counter_h << LLPC_CCU_SHIFT) | ll_counter_l; + wallclk_cycles = wallclk_ctr & WALFCC_CIF_MASK; + + /* + * An error occurs near frame "rollover". The clocks in + * frame value indicates whether this error may have + * occurred. Here we use the value of 10 i.e., + * HDA_MAX_CYCLE_OFFSET + */ + if (wallclk_cycles < HDA_MAX_CYCLE_VALUE - HDA_MAX_CYCLE_OFFSET + && wallclk_cycles > HDA_MAX_CYCLE_OFFSET) + break; + + /* + * Sleep before we read again, else we may again get + * value near to MAX_CYCLE. Try to sleep for different + * amount of time so we dont hit the same number again + */ + udelay(retry_count++); + + } while (retry_count != HDA_MAX_CYCLE_READ_RETRY); + + if (retry_count == HDA_MAX_CYCLE_READ_RETRY) { + dev_err_ratelimited(chip->card->dev, + "Error in WALFCC cycle count\n"); + return -EIO; + } + + *device = ns_to_ktime(azx_scale64(ll_counter, + NSEC_PER_SEC, runtime->rate)); + *device = ktime_add_ns(*device, (wallclk_cycles * NSEC_PER_SEC) / + ((HDA_MAX_CYCLE_VALUE + 1) * runtime->rate)); + + *system = convert_art_to_tsc(tsc_counter); + + return 0; +} + +#else +static int azx_get_sync_time(ktime_t *device, + struct system_counterval_t *system, void *ctx) +{ + return -ENXIO; +} +#endif + +static int azx_get_crosststamp(struct snd_pcm_substream *substream, + struct system_device_crosststamp *xtstamp) +{ + return get_device_system_crosststamp(azx_get_sync_time, + substream, NULL, xtstamp); +} + +static inline bool is_link_time_supported(struct snd_pcm_runtime *runtime, + struct snd_pcm_audio_tstamp_config *ts) +{ + if (runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME) + if (ts->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED) + return true; + + return false; +} + static int azx_get_time_info(struct snd_pcm_substream *substream, struct timespec *system_ts, struct timespec *audio_ts, struct snd_pcm_audio_tstamp_config *audio_tstamp_config, struct snd_pcm_audio_tstamp_report *audio_tstamp_report) { struct azx_dev *azx_dev = get_azx_dev(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + struct system_device_crosststamp xtstamp; + int ret; u64 nsec; if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ATIME) && @@ -361,8 +528,37 @@ static int azx_get_time_info(struct snd_pcm_substream *substream, audio_tstamp_report->accuracy_report = 1; /* rest of structure is valid */ audio_tstamp_report->accuracy = 42; /* 24 MHz WallClock == 42ns resolution */ - } else + } else if (is_link_time_supported(runtime, audio_tstamp_config)) { + + ret = azx_get_crosststamp(substream, &xtstamp); + if (ret) + return ret; + + switch (runtime->tstamp_type) { + case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC: + return -EINVAL; + + case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW: + *system_ts = ktime_to_timespec(xtstamp.sys_monoraw); + break; + + default: + *system_ts = ktime_to_timespec(xtstamp.sys_realtime); + break; + + } + + *audio_ts = ktime_to_timespec(xtstamp.device); + + audio_tstamp_report->actual_type = + SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED; + audio_tstamp_report->accuracy_report = 1; + /* 24 MHz WallClock == 42ns resolution */ + audio_tstamp_report->accuracy = 42; + + } else { audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT; + } return 0; } -- cgit v0.10.2 From 6adcbdcd4b6e8301c3a4c61284e701f87de9a409 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 1 Aug 2016 06:10:54 +0000 Subject: ASoC: lpass-platform: don't use snd_soc_pcm_set_drvdata() snd_soc_pcm_set_drvdata() will set driver data to rtd->dev, but driver data of rtd->dev is already used as "rtd" on soc_post_component_init(). static int soc_post_component_init(xxx) { ... dev_set_drvdata(rtd->dev, rtd); ... } To remove confusion, snd_soc_pcm_set/get_drvdata() should be removed soon. This patch is for it. qcom/lpass-platform.c sets struct lpass_pcm_data to rtd->dev today, but we can replace it to struct lpass_data :: private_data. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index db000c6..a144c14 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -84,9 +84,9 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_pcm_data *pcm_data = drvdata->private_data; struct lpass_variant *v = drvdata->variant; snd_pcm_format_t format = params_format(params); unsigned int channels = params_channels(params); @@ -177,9 +177,9 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_pcm_data *pcm_data = drvdata->private_data; struct lpass_variant *v = drvdata->variant; unsigned int reg; int ret; @@ -201,9 +201,9 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_pcm_data *pcm_data = drvdata->private_data; struct lpass_variant *v = drvdata->variant; int ret, ch, dir = substream->stream; @@ -255,9 +255,9 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_pcm_data *pcm_data = drvdata->private_data; struct lpass_variant *v = drvdata->variant; int ret, ch, dir = substream->stream; @@ -331,9 +331,9 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_pcm_data *pcm_data = drvdata->private_data; struct lpass_variant *v = drvdata->variant; unsigned int base_addr, curr_addr; int ret, ch, dir = substream->stream; @@ -483,7 +483,7 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) return -ENOMEM; data->i2s_port = cpu_dai->driver->id; - snd_soc_pcm_set_drvdata(soc_runtime, data); + drvdata->private_data = data; psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; if (psubstream) { @@ -570,8 +570,8 @@ static void lpass_platform_pcm_free(struct snd_pcm *pcm) substream = pcm->streams[i].substream; if (substream) { rt = substream->private_data; - data = snd_soc_pcm_get_drvdata(rt); drvdata = snd_soc_platform_get_drvdata(rt->platform); + data = drvdata->private_data; ch = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? data->rdma_ch diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 30714ad..35b3cea 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -58,6 +58,8 @@ struct lpass_data { /* 8016 specific */ struct clk *pcnoc_mport_clk; struct clk *pcnoc_sway_clk; + + void *private_data; }; /* Vairant data per each SOC */ -- cgit v0.10.2 From 1e814030954015e42621191f3adc52df2241dc08 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 1 Aug 2016 06:11:36 +0000 Subject: ASoC: remove snd_soc_pcm_set/get_drvdata() snd_soc_pcm_set_drvdata() will set driver data to rtd->dev, but driver data of rtd->dev is already used as "rtd" on soc_post_component_init(). static int soc_post_component_init(xxx) { ... dev_set_drvdata(rtd->dev, rtd); ... } To remove confusion, this patch removes snd_soc_pcm_set/get_drvdata(). Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/soc.h b/include/sound/soc.h index 6144882..bc95399 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1547,17 +1547,6 @@ static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platfo return snd_soc_component_get_drvdata(&platform->component); } -static inline void snd_soc_pcm_set_drvdata(struct snd_soc_pcm_runtime *rtd, - void *data) -{ - dev_set_drvdata(rtd->dev, data); -} - -static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd) -{ - return dev_get_drvdata(rtd->dev); -} - static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) { INIT_LIST_HEAD(&card->codec_dev_list); -- cgit v0.10.2 From 21ba62f849a20accf7d41e3056ea8913bc23cfb1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Aug 2016 05:48:30 +0000 Subject: ASoC: simple-card-utils: add asoc_simple_card_init_dai() simple-card is supporting clock/tdm slot initialization. This patch makes this method simple style standard. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 62b3926..13168e0 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -58,4 +58,6 @@ int asoc_simple_card_parse_dai(struct device_node *node, const char *cells_name, int *is_single_links); +int asoc_simple_card_init_dai(struct snd_soc_dai *dai, + struct asoc_simple_dai *simple_dai); #endif /* __SIMPLE_CARD_CORE_H */ diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 27e6d03..33abe1f 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -164,6 +164,35 @@ int asoc_simple_card_parse_dai(struct device_node *node, } EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai); +int asoc_simple_card_init_dai(struct snd_soc_dai *dai, + struct asoc_simple_dai *simple_dai) +{ + int ret; + + if (simple_dai->sysclk) { + ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, 0); + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "simple-card: set_sysclk error\n"); + return ret; + } + } + + if (simple_dai->slots) { + ret = snd_soc_dai_set_tdm_slot(dai, + simple_dai->tx_slot_mask, + simple_dai->rx_slot_mask, + simple_dai->slots, + simple_dai->slot_width); + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai); + /* Module information */ MODULE_AUTHOR("Kuninori Morimoto "); MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); -- cgit v0.10.2 From d8cb9354c86dddb1fb67d3f247c9ebbacd6b4c07 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Aug 2016 05:48:53 +0000 Subject: ASoC: simple-card: use asoc_simple_card_init_dai() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 99028c1..03ecca8 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -179,51 +179,19 @@ static struct snd_soc_ops asoc_simple_card_ops = { .hw_params = asoc_simple_card_hw_params, }; -static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, - struct asoc_simple_dai *set) -{ - int ret; - - if (set->sysclk) { - ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0); - if (ret && ret != -ENOTSUPP) { - dev_err(dai->dev, "simple-card: set_sysclk error\n"); - goto err; - } - } - - if (set->slots) { - ret = snd_soc_dai_set_tdm_slot(dai, - set->tx_slot_mask, - set->rx_slot_mask, - set->slots, - set->slot_width); - if (ret && ret != -ENOTSUPP) { - dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); - goto err; - } - } - - ret = 0; - -err: - return ret; -} - static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) { struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *cpu = rtd->cpu_dai; - struct simple_dai_props *dai_props; + struct simple_dai_props *dai_props = &priv->dai_props[rtd->num]; int ret; - dai_props = &priv->dai_props[rtd->num]; - ret = __asoc_simple_card_dai_init(codec, &dai_props->codec_dai); + ret = asoc_simple_card_init_dai(codec, &dai_props->codec_dai); if (ret < 0) return ret; - ret = __asoc_simple_card_dai_init(cpu, &dai_props->cpu_dai); + ret = asoc_simple_card_init_dai(cpu, &dai_props->cpu_dai); if (ret < 0) return ret; -- cgit v0.10.2 From c262c9ab7a956b15c4c12b81472502a587d0dfcd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Aug 2016 05:49:41 +0000 Subject: ASoC: simple-card-utils: add asoc_simple_card_canonicalize_dailink() simple-card is assuming that sometimes platform and cpu are same. This patch makes this method simple style standard. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 13168e0..a71d46a 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -60,4 +60,7 @@ int asoc_simple_card_parse_dai(struct device_node *node, int asoc_simple_card_init_dai(struct snd_soc_dai *dai, struct asoc_simple_dai *simple_dai); + +int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link); + #endif /* __SIMPLE_CARD_CORE_H */ diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 33abe1f..189eadd 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -193,6 +193,19 @@ int asoc_simple_card_init_dai(struct snd_soc_dai *dai, } EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai); +int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link) +{ + if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) + return -EINVAL; + + /* Assumes platform == cpu */ + if (!dai_link->platform_of_node) + dai_link->platform_of_node = dai_link->cpu_of_node; + + return 0; +} +EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink); + /* Module information */ MODULE_AUTHOR("Kuninori Morimoto "); MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); -- cgit v0.10.2 From c958374f1cd22ec87f210985f9f9e1ba8b3df30b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Aug 2016 05:50:02 +0000 Subject: ASoC: simple-card: use asoc_simple_card_canonicalize_dailink() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 03ecca8..8b1efdd 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -286,14 +286,9 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, if (ret < 0) goto dai_link_of_err; - if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { - ret = -EINVAL; + ret = asoc_simple_card_canonicalize_dailink(dai_link); + if (ret < 0) goto dai_link_of_err; - } - - /* Assumes platform == cpu */ - if (!dai_link->platform_of_node) - dai_link->platform_of_node = dai_link->cpu_of_node; ret = asoc_simple_card_set_dailink_name(dev, dai_link, "%s-%s", -- cgit v0.10.2 From 600ee2085515c03a7a4a6025034fefccf29e5a24 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Aug 2016 05:49:21 +0000 Subject: ASoC: rsrc-card: use asoc_simple_card_init_dai() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index 82187e0..1bf3563 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -97,7 +97,6 @@ static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dai_link *dai_link; struct asoc_simple_dai *dai_props; int num = rtd->num; - int ret; dai_link = rsrc_priv_to_link(priv, num); dai_props = rsrc_priv_to_props(priv, num); @@ -105,30 +104,7 @@ static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd) rtd->cpu_dai : rtd->codec_dai; - if (dai_props->sysclk) { - ret = snd_soc_dai_set_sysclk(dai, 0, dai_props->sysclk, 0); - if (ret && ret != -ENOTSUPP) { - dev_err(dai->dev, "set_sysclk error\n"); - goto err; - } - } - - if (dai_props->slots) { - ret = snd_soc_dai_set_tdm_slot(dai, - dai_props->tx_slot_mask, - dai_props->rx_slot_mask, - dai_props->slots, - dai_props->slot_width); - if (ret && ret != -ENOTSUPP) { - dev_err(dai->dev, "set_tdm_slot error\n"); - goto err; - } - } - - ret = 0; - -err: - return ret; + return asoc_simple_card_init_dai(dai, dai_props); } static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, -- cgit v0.10.2 From a09f383ef72947b7d59fc7fe50fe332ab5c35dca Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Aug 2016 05:50:19 +0000 Subject: ASoC: rsrc-card: use asoc_simple_card_canonicalize_dailink() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index 1bf3563..0bf17dae 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -222,8 +222,10 @@ static int rsrc_card_parse_links(struct device_node *np, } } - /* Simple Card assumes platform == cpu */ - dai_link->platform_of_node = dai_link->cpu_of_node; + ret = asoc_simple_card_canonicalize_dailink(dai_link); + if (ret < 0) + return ret; + dai_link->dpcm_playback = 1; dai_link->dpcm_capture = 1; dai_link->ops = &rsrc_card_ops; -- cgit v0.10.2 From 0556ba463b2419e4f4833563aa3d75aafd9b9c01 Mon Sep 17 00:00:00 2001 From: Dharageswari R Date: Wed, 10 Aug 2016 09:40:48 +0530 Subject: ASoC: Intel: Skylake: modify snd_skl_get_module_info args snd_skl_get_module_info() takes skl_dfw_module as an argument. The users then updates the topology data, so instead pass skl_module_cfg and let snd_skl_get_module_info() fill that up. Signed-off-by: Dharageswari R Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index fa053c0..6ad5cab 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -20,6 +20,7 @@ #include #include "skl-sst-cldma.h" #include "skl-tplg-interface.h" +#include "skl-topology.h" struct sst_dsp; struct skl_sst; @@ -210,10 +211,10 @@ int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx); void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); -int snd_skl_get_module_info(struct skl_sst *ctx, u8 *uuid, - struct skl_dfw_module *dfw_config); +int snd_skl_get_module_info(struct skl_sst *ctx, + struct skl_module_cfg *mconfig); int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, - unsigned int offset, int index); + unsigned int offset, int index); void skl_freeup_uuid_list(struct skl_sst *ctx); int skl_dsp_strip_extended_manifest(struct firmware *fw); diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index d94ff95..e4865ea 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -115,18 +115,18 @@ struct skl_ext_manifest_hdr { u32 entries; }; -int snd_skl_get_module_info(struct skl_sst *ctx, u8 *uuid, - struct skl_dfw_module *dfw_config) +int snd_skl_get_module_info(struct skl_sst *ctx, + struct skl_module_cfg *mconfig) { struct uuid_module *module; uuid_le *uuid_mod; - uuid_mod = (uuid_le *)uuid; + uuid_mod = (uuid_le *)mconfig->guid; list_for_each_entry(module, &ctx->uuid_list, list) { if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) { - dfw_config->module_id = module->id; - dfw_config->is_loadable = module->is_loadable; + mconfig->id.module_id = module->id; + mconfig->is_loadable = module->is_loadable; return 0; } diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index c13fbef..c09e2c7 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -475,24 +475,12 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) /* check if module ids are populated */ if (mconfig->id.module_id < 0) { - struct skl_dfw_module *dfw_config; - - dfw_config = kzalloc(sizeof(*dfw_config), GFP_KERNEL); - if (!dfw_config) - return -ENOMEM; - - ret = snd_skl_get_module_info(skl->skl_sst, - mconfig->guid, dfw_config); + ret = snd_skl_get_module_info(skl->skl_sst, mconfig); if (ret < 0) { dev_err(skl->skl_sst->dev, "query module info failed: %d\n", ret); - kfree(dfw_config); return ret; } - mconfig->id.module_id = dfw_config->module_id; - mconfig->is_loadable = dfw_config->is_loadable; - - kfree(dfw_config); } /* check resource available */ -- cgit v0.10.2 From 64cb1d0ad0eada322c2011e15710d2a1c12ce8b6 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Wed, 10 Aug 2016 09:40:49 +0530 Subject: ASoC: Intel: Skylake: Populate modules after loading Once topology and firmware are loaded, we can parse the manifest. Use driver pipe and widget list to get list of all modules and populate the data. Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 1402492..eb1f00b 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1138,6 +1138,32 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd) return retval; } +static int skl_populate_modules(struct skl *skl) +{ + struct skl_pipeline *p; + struct skl_pipe_module *m; + struct snd_soc_dapm_widget *w; + struct skl_module_cfg *mconfig; + int ret; + + list_for_each_entry(p, &skl->ppl_list, node) { + list_for_each_entry(m, &p->pipe->w_list, node) { + + w = m->w; + mconfig = w->priv; + + ret = snd_skl_get_module_info(skl->skl_sst, mconfig); + if (ret < 0) { + dev_err(skl->skl_sst->dev, + "query module info failed:%d\n", ret); + goto err; + } + } + } +err: + return ret; +} + static int skl_platform_soc_probe(struct snd_soc_platform *platform) { struct hdac_ext_bus *ebus = dev_get_drvdata(platform->dev); @@ -1169,6 +1195,7 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform) dev_err(platform->dev, "Failed to boot first fw: %d\n", ret); return ret; } + skl_populate_modules(skl); } pm_runtime_mark_last_busy(platform->dev); pm_runtime_put_autosuspend(platform->dev); -- cgit v0.10.2 From a657ae7e5c0c9fd8858e5498e6de65c222d206d1 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Wed, 10 Aug 2016 09:40:50 +0530 Subject: ASoC: Intel: Skylake: remove module id query at runtime Now that we have balanced loading of the topology file and split of init and fw_init and fill module data during asoc probe. So remove it from runtime, but keep error check in case things fall apart. Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index c09e2c7..4bc8f9c 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -475,12 +475,10 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) /* check if module ids are populated */ if (mconfig->id.module_id < 0) { - ret = snd_skl_get_module_info(skl->skl_sst, mconfig); - if (ret < 0) { - dev_err(skl->skl_sst->dev, - "query module info failed: %d\n", ret); - return ret; - } + dev_err(skl->skl_sst->dev, + "module %pUL id not populated\n", + (uuid_le *)mconfig->guid); + return -EIO; } /* check resource available */ -- cgit v0.10.2 From 983cebd602af8c2bf9d5830f15fb4e18fb38f994 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 10 Aug 2016 02:20:19 +0000 Subject: ASoC: simple-card-utils: add asoc_simple_card_canonicalize_cpu() simple-card needs remove dai_link->cpu_dai_name if it CPU was single DAI. This patch makes this method simple style standard. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index a71d46a..f760f55 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -62,5 +62,7 @@ int asoc_simple_card_init_dai(struct snd_soc_dai *dai, struct asoc_simple_dai *simple_dai); int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link); +void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link, + int is_single_links); #endif /* __SIMPLE_CARD_CORE_H */ diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 189eadd..c5d32da 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -206,6 +206,23 @@ int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link) } EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink); +void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link, + int is_single_links) +{ + /* + * In soc_bind_dai_link() will check cpu name after + * of_node matching if dai_link has cpu_dai_name. + * but, it will never match if name was created by + * fmt_single_name() remove cpu_dai_name if cpu_args + * was 0. See: + * fmt_single_name() + * fmt_multiple_name() + */ + if (is_single_links) + dai_link->cpu_dai_name = NULL; +} +EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_cpu); + /* Module information */ MODULE_AUTHOR("Kuninori Morimoto "); MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); -- cgit v0.10.2 From 16f1de6f3656519120fd4a88d6b21fc3da8d373a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 10 Aug 2016 02:20:43 +0000 Subject: ASoC: simple-card: use asoc_simple_card_canonicalize_cpu() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 8b1efdd..64896e3 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -309,17 +309,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, dai_link->codec_dai_name, dai_props->codec_dai.sysclk); - /* - * In soc_bind_dai_link() will check cpu name after - * of_node matching if dai_link has cpu_dai_name. - * but, it will never match if name was created by - * fmt_single_name() remove cpu_dai_name if cpu_args - * was 0. See: - * fmt_single_name() - * fmt_multiple_name() - */ - if (single_cpu) - dai_link->cpu_dai_name = NULL; + asoc_simple_card_canonicalize_cpu(dai_link, single_cpu); dai_link_of_err: of_node_put(cpu); -- cgit v0.10.2 From 27b010815bcfbb2cc79de7544547e33e4d169594 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 10 Aug 2016 02:21:03 +0000 Subject: ASoC: rsrc-card: use asoc_simple_card_canonicalize_cpu() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index 0bf17dae..dd5eda1 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -134,7 +134,6 @@ static int rsrc_card_parse_links(struct device_node *np, struct device *dev = rsrc_priv_to_dev(priv); struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); struct asoc_simple_dai *dai_props = rsrc_priv_to_props(priv, idx); - int is_single_links = 0; int ret; /* Parse TDM slot */ @@ -147,6 +146,8 @@ static int rsrc_card_parse_links(struct device_node *np, return ret; if (is_fe) { + int is_single_links = 0; + /* BE is dummy */ dai_link->codec_of_node = NULL; dai_link->codec_dai_name = "snd-soc-dummy-dai"; @@ -171,17 +172,7 @@ static int rsrc_card_parse_links(struct device_node *np, if (ret < 0) return ret; - /* - * In soc_bind_dai_link() will check cpu name after - * of_node matching if dai_link has cpu_dai_name. - * but, it will never match if name was created by - * fmt_single_name() remove cpu_dai_name if cpu_args - * was 0. See: - * fmt_single_name() - * fmt_multiple_name() - */ - if (is_single_links) - dai_link->cpu_dai_name = NULL; + asoc_simple_card_canonicalize_cpu(dai_link, is_single_links); } else { const struct rsrc_card_of_data *of_data; -- cgit v0.10.2 From 0f4e0711b735a148cb6da0e6f91253b62fc2c5b2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 10 Aug 2016 02:21:25 +0000 Subject: ASoC: simple-card-utils: add asoc_simple_card_clean_reference() simple-card needs to decrease the reference count of the device nodes. This patch makes this method simple style standard. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index f760f55..403ec92 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -65,4 +65,6 @@ int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link); void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link, int is_single_links); +int asoc_simple_card_clean_reference(struct snd_soc_card *card); + #endif /* __SIMPLE_CARD_CORE_H */ diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index c5d32da..1cb3930 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -223,6 +223,21 @@ void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link, } EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_cpu); +int asoc_simple_card_clean_reference(struct snd_soc_card *card) +{ + struct snd_soc_dai_link *dai_link; + int num_links; + + for (num_links = 0, dai_link = card->dai_link; + num_links < card->num_links; + num_links++, dai_link++) { + of_node_put(dai_link->cpu_of_node); + of_node_put(dai_link->codec_of_node); + } + return 0; +} +EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference); + /* Module information */ MODULE_AUTHOR("Kuninori Morimoto "); MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); -- cgit v0.10.2 From 885fc0595a3e91ed7b6f78ea419952345be0222b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 10 Aug 2016 02:21:42 +0000 Subject: ASoC: simple-card: use asoc_simple_card_clean_reference() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 64896e3..55638a8 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -378,21 +378,6 @@ static int asoc_simple_card_parse_of(struct device_node *node, return 0; } -/* Decrease the reference count of the device nodes */ -static int asoc_simple_card_unref(struct snd_soc_card *card) -{ - struct snd_soc_dai_link *dai_link; - int num_links; - - for (num_links = 0, dai_link = card->dai_link; - num_links < card->num_links; - num_links++, dai_link++) { - of_node_put(dai_link->cpu_of_node); - of_node_put(dai_link->codec_of_node); - } - return 0; -} - static int asoc_simple_card_probe(struct platform_device *pdev) { struct simple_card_data *priv; @@ -478,7 +463,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) return ret; err: - asoc_simple_card_unref(&priv->snd_card); + asoc_simple_card_clean_reference(&priv->snd_card); return ret; } @@ -490,7 +475,7 @@ static int asoc_simple_card_remove(struct platform_device *pdev) asoc_simple_card_remove_jack(&priv->hp_jack); asoc_simple_card_remove_jack(&priv->mic_jack); - return asoc_simple_card_unref(card); + return asoc_simple_card_clean_reference(card); } static const struct of_device_id asoc_simple_of_match[] = { -- cgit v0.10.2 From 239486baee2bbefd81053cd4a168f90ce5c46fa2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 10 Aug 2016 02:22:01 +0000 Subject: ASoC: rsrc-card: use asoc_simple_card_clean_reference() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index dd5eda1..16dc13e 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -333,21 +333,6 @@ static int rsrc_card_parse_of(struct device_node *node, return 0; } -/* Decrease the reference count of the device nodes */ -static int rsrc_card_unref(struct snd_soc_card *card) -{ - struct snd_soc_dai_link *dai_link; - int num_links; - - for (num_links = 0, dai_link = card->dai_link; - num_links < card->num_links; - num_links++, dai_link++) { - of_node_put(dai_link->cpu_of_node); - of_node_put(dai_link->codec_of_node); - } - return 0; -} - static int rsrc_card_probe(struct platform_device *pdev) { struct rsrc_card_priv *priv; @@ -373,7 +358,7 @@ static int rsrc_card_probe(struct platform_device *pdev) if (ret >= 0) return ret; err: - rsrc_card_unref(&priv->snd_card); + asoc_simple_card_clean_reference(&priv->snd_card); return ret; } @@ -382,7 +367,7 @@ static int rsrc_card_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - return rsrc_card_unref(card); + return asoc_simple_card_clean_reference(card); } static struct platform_driver rsrc_card = { -- cgit v0.10.2 From 19c891924b764fe192d0ad57b7dc676316a85250 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 11 Aug 2016 14:42:55 +0100 Subject: ASoC: arizona: Connect ASRCs to both clock domains The two clock domains are enabled based on each input and output of the chip being connected to its respective clock domain. The ASRC however can bridge the two domains and as such can function as an input/output to either domain. The hardware also requires that both clocks are enabled before the ASRC is. Ensure these constraints by linking the ASRCs to both SYSCLK and ASYNCCLK. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index 954a4f5..f8d8139 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -746,6 +746,16 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = { { "IN2L", NULL, "SYSCLK" }, { "IN2R", NULL, "SYSCLK" }, + { "ASRC1L", NULL, "SYSCLK" }, + { "ASRC1R", NULL, "SYSCLK" }, + { "ASRC2L", NULL, "SYSCLK" }, + { "ASRC2R", NULL, "SYSCLK" }, + + { "ASRC1L", NULL, "ASYNCCLK" }, + { "ASRC1R", NULL, "ASYNCCLK" }, + { "ASRC2L", NULL, "ASYNCCLK" }, + { "ASRC2R", NULL, "ASYNCCLK" }, + { "MICBIAS1", NULL, "MICVDD" }, { "MICBIAS2", NULL, "MICVDD" }, diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 846deed..16a1c5b 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1521,6 +1521,16 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { { "IN3L", NULL, "SYSCLK" }, { "IN3R", NULL, "SYSCLK" }, + { "ASRC1L", NULL, "SYSCLK" }, + { "ASRC1R", NULL, "SYSCLK" }, + { "ASRC2L", NULL, "SYSCLK" }, + { "ASRC2R", NULL, "SYSCLK" }, + + { "ASRC1L", NULL, "ASYNCCLK" }, + { "ASRC1R", NULL, "ASYNCCLK" }, + { "ASRC2L", NULL, "ASYNCCLK" }, + { "ASRC2R", NULL, "ASYNCCLK" }, + { "MICBIAS1", NULL, "MICVDD" }, { "MICBIAS2", NULL, "MICVDD" }, { "MICBIAS3", NULL, "MICVDD" }, diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 1565470..673dc59 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -1745,6 +1745,16 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { { "IN4L", NULL, "SYSCLK" }, { "IN4R", NULL, "SYSCLK" }, + { "ASRC1L", NULL, "SYSCLK" }, + { "ASRC1R", NULL, "SYSCLK" }, + { "ASRC2L", NULL, "SYSCLK" }, + { "ASRC2R", NULL, "SYSCLK" }, + + { "ASRC1L", NULL, "ASYNCCLK" }, + { "ASRC1R", NULL, "ASYNCCLK" }, + { "ASRC2L", NULL, "ASYNCCLK" }, + { "ASRC2R", NULL, "ASYNCCLK" }, + { "MICBIAS1", NULL, "MICVDD" }, { "MICBIAS2", NULL, "MICVDD" }, { "MICBIAS3", NULL, "MICVDD" }, diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 3a5c896..6ba7dbf 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -966,6 +966,16 @@ static const struct snd_soc_dapm_route wm8998_dapm_routes[] = { { "IN2A", NULL, "SYSCLK" }, { "IN2B", NULL, "SYSCLK" }, + { "ASRC1L", NULL, "SYSCLK" }, + { "ASRC1R", NULL, "SYSCLK" }, + { "ASRC2L", NULL, "SYSCLK" }, + { "ASRC2R", NULL, "SYSCLK" }, + + { "ASRC1L", NULL, "ASYNCCLK" }, + { "ASRC1R", NULL, "ASYNCCLK" }, + { "ASRC2L", NULL, "ASYNCCLK" }, + { "ASRC2R", NULL, "ASYNCCLK" }, + { "SPD1", NULL, "SYSCLK" }, { "SPD1", NULL, "SPD1TX1" }, { "SPD1", NULL, "SPD1TX2" }, -- cgit v0.10.2 From 6b0ffacdaf549d66a0c2a838d68f18495980def4 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Thu, 11 Aug 2016 14:38:11 +0800 Subject: ASoC: atmel-pdmic: mark symbols static where possible We get 1 warning about global functions without a declaration in the ASoC atmel-pdmic driver when building with W=1: sound/soc/atmel/atmel-pdmic.c:286:5: warning: no previous prototype for 'pdmic_get_mic_volsw' [-Wmissing-prototypes] In fact, this function is only used in the file in which it is declared and don't need a declaration, but can be made static. so this patch marks it 'static'. Signed-off-by: Baoyou Xie Signed-off-by: Mark Brown diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index 5f56da6..4cce36e 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -283,7 +283,7 @@ static const DECLARE_TLV_DB_RANGE(mic_gain_tlv, 8, ARRAY_SIZE(mic_gain_table)-1, TLV_DB_SCALE_ITEM(-6500, 100, 0), ); -int pdmic_get_mic_volsw(struct snd_kcontrol *kcontrol, +static int pdmic_get_mic_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); -- cgit v0.10.2 From 22e766146a5ae744b0e95d80f663a9aab9c189fb Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Thu, 11 Aug 2016 14:38:12 +0800 Subject: ASoC: mediatek: mark symbols static where possible We get 2 warnings about global functions without a declaration in the ASoC mediatek module when building with W=1: sound/soc/mediatek/common/mtk-afe-fe-dai.c:26:5: warning: no previous prototype for 'mtk_regmap_update_bits' [-Wmissing-prototypes] int mtk_regmap_update_bits(struct regmap *map, int reg, unsigned int mask, ^ sound/soc/mediatek/common/mtk-afe-fe-dai.c:34:5: warning: no previous prototype for 'mtk_regmap_write' [-Wmissing-prototypes] int mtk_regmap_write(struct regmap *map, int reg, unsigned int val) In fact, all of those functions are only used in the file in which they are declared and don't need a declaration, but can be made static. so this patch marks it 'static'. Signed-off-by: Baoyou Xie Signed-off-by: Mark Brown diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c index b788791b..ac231d3 100644 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c @@ -23,7 +23,8 @@ #define AFE_BASE_END_OFFSET 8 -int mtk_regmap_update_bits(struct regmap *map, int reg, unsigned int mask, +static int mtk_regmap_update_bits(struct regmap *map, int reg, + unsigned int mask, unsigned int val) { if (reg < 0) @@ -31,7 +32,7 @@ int mtk_regmap_update_bits(struct regmap *map, int reg, unsigned int mask, return regmap_update_bits(map, reg, mask, val); } -int mtk_regmap_write(struct regmap *map, int reg, unsigned int val) +static int mtk_regmap_write(struct regmap *map, int reg, unsigned int val) { if (reg < 0) return 0; -- cgit v0.10.2 From 1d9d0c65d95ecc446972ace6a7583e5cfdc69e48 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Thu, 11 Aug 2016 14:38:13 +0800 Subject: ASoC: fix W=1 build warnings We get 1 warning about global functions without a declaration in the ASoC sub-system when building with W=1: sound/soc/sh/rcar/core.c:113:6: warning: no previous prototype for 'rsnd_mod_make_sure' [-Wmissing-prototypes] void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type) In this case, the function 'rsnd_mod_make_sure' is declared in rsnd.h file, but it only valid if the macro DEBUG is claimed. so the implementation of function 'rsnd_mod_make_sure' need be held by macro DEBUG. Signed-off-by: Baoyou Xie Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 3351a70..f718a20 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -110,6 +110,7 @@ MODULE_DEVICE_TABLE(of, rsnd_of_match); /* * rsnd_mod functions */ +#ifdef DEBUG void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type) { if (mod->type != type) { @@ -120,6 +121,7 @@ void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type) rsnd_mod_name(mod), rsnd_mod_id(mod)); } } +#endif char *rsnd_mod_name(struct rsnd_mod *mod) { -- cgit v0.10.2 From 61743bfaf061e253a58a3a2f22659405cc95939a Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 10 Aug 2016 13:53:21 +0000 Subject: ASoC: atmel-pdmic: add missing clk_disable_unprepare() on error in atmel_pdmic_cpu_dai_startup() Add the missing clk_disable_unprepare() before return from atmel_pdmic_cpu_dai_startup() in the error handling case. Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index 4cce36e..8b4beb0 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -115,8 +115,10 @@ static int atmel_pdmic_cpu_dai_startup(struct snd_pcm_substream *substream, return ret; ret = clk_prepare_enable(dd->pclk); - if (ret) + if (ret) { + clk_disable_unprepare(dd->gclk); return ret; + } /* Clear all bits in the Control Register(PDMIC_CR) */ regmap_write(dd->regmap, PDMIC_CR, 0); -- cgit v0.10.2 From 8ae3ea48df0d746b663057cf0b972a18d0777b7b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 10 Aug 2016 13:43:12 +0000 Subject: ASoC: topology: Fix error return code in soc_tplg_dapm_widget_create() Fix to return error code -ENOMEM instead of 0 when failed to create widget, as done elsewhere in this function. Fixes: 8a9782346dcc ("ASoC: topology: Add topology core") Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 05a18f6..a9e83a2 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1476,6 +1476,7 @@ widget: if (widget == NULL) { dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n", w->name); + ret = -ENOMEM; goto hdr_err; } -- cgit v0.10.2 From 289ef679086cf0389173a3c08174df2cacc536f3 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 11 Aug 2016 22:40:11 +0200 Subject: ALSA: usb: caiaq: audio: don't print error when allocating urb fails kmalloc will print enough information in case of failure. Signed-off-by: Wolfram Sang Signed-off-by: Takashi Iwai diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index 327f864..8f66ba7 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -739,7 +739,6 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret) for (i = 0; i < N_URBS; i++) { urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL); if (!urbs[i]) { - dev_err(dev, "unable to usb_alloc_urb(), OOM!?\n"); *ret = -ENOMEM; return urbs; } -- cgit v0.10.2 From 4e85e7776eba5f6d5a3b8b43f34001a73c5d08a1 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 12 Aug 2016 13:52:10 +0300 Subject: ASoC: omap-mcbsp: Enable TX/RX under and overflow interrupts FIFO under or overflow can cause channel swaps and data loss. Reporting them can help to identify such events. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index 76ce331..06fec56 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -221,7 +221,8 @@ void omap_mcbsp_config(struct omap_mcbsp *mcbsp, /* Enable TX/RX sync error interrupts by default */ if (mcbsp->irq) - MCBSP_WRITE(mcbsp, IRQEN, RSYNCERREN | XSYNCERREN); + MCBSP_WRITE(mcbsp, IRQEN, RSYNCERREN | XSYNCERREN | + RUNDFLEN | ROVFLEN | XUNDFLEN | XOVFLEN); } /** -- cgit v0.10.2 From fbb016a25dd0f4160df90bb1319e64e8209c7619 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Sat, 30 Jul 2016 17:56:37 +0200 Subject: ASoC: sunxi: Add bindings for sun6i to SPDIF The A31 SoC uses the same SPDIF block as found in earlier SoCs, but its reset is controlled via a separate reset controller. Signed-off-by: Marcus Cooper Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt b/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt index 13503aa..0230c4d 100644 --- a/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt +++ b/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt @@ -9,6 +9,7 @@ Required properties: - compatible : should be one of the following: - "allwinner,sun4i-a10-spdif": for the Allwinner A10 SoC + - "allwinner,sun6i-a31-spdif": for the Allwinner A31 SoC - reg : Offset and length of the register set for the device. @@ -25,6 +26,8 @@ Required properties: "apb" clock for the spdif bus. "spdif" clock for spdif controller. + - resets : reset specifier for the ahb reset (A31 and newer only) + Example: spdif: spdif@01c21000 { -- cgit v0.10.2 From 2f6963cb52bee440105f732b3411f18e38ed6e52 Mon Sep 17 00:00:00 2001 From: Marcus Cooper Date: Sat, 30 Jul 2016 17:56:38 +0200 Subject: ASoC: sunxi: compatibility for sun6i to SPDIF The A31 SoC uses the same SPDIF block as found in earlier SoCs, but its reset is controlled via a separate reset controller. The DMA also complains when the maxburst is set to 4 so it's been adjusted to 8 which suites both the older and newer SoCs. Signed-off-by: Marcus Cooper Signed-off-by: Mark Brown diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index 0b04fb0..88fbb3a 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -162,6 +163,7 @@ struct sun4i_spdif_dev { struct platform_device *pdev; struct clk *spdif_clk; struct clk *apb_clk; + struct reset_control *rst; struct snd_soc_dai_driver cpu_dai_drv; struct regmap *regmap; struct snd_dmaengine_dai_dma_data dma_params_tx; @@ -411,6 +413,7 @@ static const struct snd_soc_dapm_route dit_routes[] = { static const struct of_device_id sun4i_spdif_of_match[] = { { .compatible = "allwinner,sun4i-a10-spdif", }, + { .compatible = "allwinner,sun6i-a31-spdif", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, sun4i_spdif_of_match); @@ -482,11 +485,23 @@ static int sun4i_spdif_probe(struct platform_device *pdev) } host->dma_params_tx.addr = res->start + SUN4I_SPDIF_TXFIFO; - host->dma_params_tx.maxburst = 4; + host->dma_params_tx.maxburst = 8; host->dma_params_tx.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; platform_set_drvdata(pdev, host); + if (of_device_is_compatible(pdev->dev.of_node, + "allwinner,sun6i-a31-spdif")) { + host->rst = devm_reset_control_get_optional(&pdev->dev, NULL); + if (IS_ERR(host->rst) && PTR_ERR(host->rst) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + dev_err(&pdev->dev, "Failed to get reset: %d\n", ret); + goto err_disable_apb_clk; + } + if (!IS_ERR(host->rst)) + reset_control_deassert(host->rst); + } + ret = devm_snd_soc_register_component(&pdev->dev, &sun4i_spdif_component, &sun4i_spdif_dai, 1); if (ret) -- cgit v0.10.2 From 04445681f710eb3a6a263504fa3e6f4199f12d87 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Sun, 19 Jun 2016 03:00:00 +0200 Subject: ASoC: tegra: add tegra sgtl5000 machine driver This binding and driver describe/support playback to headphones, and capture from line-in and microphone. This driver is useful for the Toradex Apalis T30, Apalis TK1 and Colibri T30 modules. Signed-off-by: Marcel Ziswiler Reviewed-by: Stephen Warren Signed-off-by: Marcel Ziswiler Acked-by: Rob Herring Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-sgtl5000.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-sgtl5000.txt new file mode 100644 index 0000000..5da7da4 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-sgtl5000.txt @@ -0,0 +1,42 @@ +NVIDIA Tegra audio complex, with SGTL5000 CODEC + +Required properties: +- compatible : "nvidia,tegra-audio-sgtl5000" +- clocks : Must contain an entry for each entry in clock-names. + See ../clocks/clock-bindings.txt for details. +- clock-names : Must include the following entries: + - pll_a + - pll_a_out0 + - mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk) +- nvidia,model : The user-visible name of this sound complex. +- nvidia,audio-routing : A list of the connections between audio components. + Each entry is a pair of strings, the first being the connection's sink, + the second being the connection's source. Valid names for sources and + sinks are the SGTL5000's pins (as documented in its binding), and the jacks + on the board: + + * Headphone Jack + * Line In Jack + * Mic Jack + +- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's + connected to the CODEC. +- nvidia,audio-codec : The phandle of the SGTL5000 audio codec. + +Example: + +sound { + compatible = "toradex,tegra-audio-sgtl5000-apalis_t30", + "nvidia,tegra-audio-sgtl5000"; + nvidia,model = "Toradex Apalis T30"; + nvidia,audio-routing = + "Headphone Jack", "HP_OUT", + "LINE_IN", "Line In Jack", + "MIC_IN", "Mic Jack"; + nvidia,i2s-controller = <&tegra_i2s2>; + nvidia,audio-codec = <&sgtl5000>; + clocks = <&tegra_car TEGRA30_CLK_PLL_A>, + <&tegra_car TEGRA30_CLK_PLL_A_OUT0>, + <&tegra_car TEGRA30_CLK_EXTERN1>; + clock-names = "pll_a", "pll_a_out0", "mclk"; +}; diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index a6768f8..efbe8d4 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -138,3 +138,14 @@ config SND_SOC_TEGRA_RT5677 help Say Y or M here if you want to add support for SoC audio on Tegra boards using the RT5677 codec, such as Ryu. + +config SND_SOC_TEGRA_SGTL5000 + tristate "SoC Audio support for Tegra boards using a SGTL5000 codec" + depends on SND_SOC_TEGRA && I2C && GPIOLIB + select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC + select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC + select SND_SOC_SGTL5000 + help + Say Y or M here if you want to add support for SoC audio on Tegra + boards using the SGTL5000 codec, such as Apalis T30, Apalis TK1 or + Colibri T30. diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index 9171655..f214a3f 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile @@ -26,6 +26,7 @@ snd-soc-tegra-wm9712-objs := tegra_wm9712.o snd-soc-tegra-trimslice-objs := trimslice.o snd-soc-tegra-alc5632-objs := tegra_alc5632.o snd-soc-tegra-max98090-objs := tegra_max98090.o +snd-soc-tegra-sgtl5000-objs := tegra_sgtl5000.o obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o obj-$(CONFIG_SND_SOC_TEGRA_RT5677) += snd-soc-tegra-rt5677.o @@ -35,3 +36,4 @@ obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o obj-$(CONFIG_SND_SOC_TEGRA_MAX98090) += snd-soc-tegra-max98090.o +obj-$(CONFIG_SND_SOC_TEGRA_SGTL5000) += snd-soc-tegra-sgtl5000.o \ No newline at end of file diff --git a/sound/soc/tegra/tegra_sgtl5000.c b/sound/soc/tegra/tegra_sgtl5000.c new file mode 100644 index 0000000..1e76869 --- /dev/null +++ b/sound/soc/tegra/tegra_sgtl5000.c @@ -0,0 +1,212 @@ +/* + * tegra_sgtl5000.c - Tegra machine ASoC driver for boards using SGTL5000 codec + * + * Author: Marcel Ziswiler + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Based on code copyright/by: + * + * Copyright (C) 2010-2012 - NVIDIA, Inc. + * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd. + * Copyright 2007 Wolfson Microelectronics PLC. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../codecs/sgtl5000.h" + +#include "tegra_asoc_utils.h" + +#define DRV_NAME "tegra-snd-sgtl5000" + +struct tegra_sgtl5000 { + struct tegra_asoc_utils_data util_data; +}; + +static int tegra_sgtl5000_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_card *card = rtd->card; + struct tegra_sgtl5000 *machine = snd_soc_card_get_drvdata(card); + int srate, mclk; + int err; + + srate = params_rate(params); + switch (srate) { + case 11025: + case 22050: + case 44100: + case 88200: + mclk = 11289600; + break; + default: + mclk = 12288000; + break; + } + + err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); + if (err < 0) { + dev_err(card->dev, "Can't configure clocks\n"); + return err; + } + + err = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, + SND_SOC_CLOCK_IN); + if (err < 0) { + dev_err(card->dev, "codec_dai clock not set\n"); + return err; + } + + return 0; +} + +static struct snd_soc_ops tegra_sgtl5000_ops = { + .hw_params = tegra_sgtl5000_hw_params, +}; + +static const struct snd_soc_dapm_widget tegra_sgtl5000_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_LINE("Line In Jack", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), +}; + +static struct snd_soc_dai_link tegra_sgtl5000_dai = { + .name = "sgtl5000", + .stream_name = "HiFi", + .codec_dai_name = "sgtl5000", + .ops = &tegra_sgtl5000_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, +}; + +static struct snd_soc_card snd_soc_tegra_sgtl5000 = { + .name = "tegra-sgtl5000", + .owner = THIS_MODULE, + .dai_link = &tegra_sgtl5000_dai, + .num_links = 1, + .dapm_widgets = tegra_sgtl5000_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tegra_sgtl5000_dapm_widgets), + .fully_routed = true, +}; + +static int tegra_sgtl5000_driver_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct snd_soc_card *card = &snd_soc_tegra_sgtl5000; + struct tegra_sgtl5000 *machine; + int ret; + + machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_sgtl5000), + GFP_KERNEL); + if (!machine) { + dev_err(&pdev->dev, "Can't allocate tegra_sgtl5000 struct\n"); + return -ENOMEM; + } + + card->dev = &pdev->dev; + platform_set_drvdata(pdev, card); + snd_soc_card_set_drvdata(card, machine); + + ret = snd_soc_of_parse_card_name(card, "nvidia,model"); + if (ret) + goto err; + + ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); + if (ret) + goto err; + + tegra_sgtl5000_dai.codec_of_node = of_parse_phandle(np, + "nvidia,audio-codec", 0); + if (!tegra_sgtl5000_dai.codec_of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,audio-codec' missing or invalid\n"); + ret = -EINVAL; + goto err; + } + + tegra_sgtl5000_dai.cpu_of_node = of_parse_phandle(np, + "nvidia,i2s-controller", 0); + if (!tegra_sgtl5000_dai.cpu_of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,i2s-controller' missing/invalid\n"); + ret = -EINVAL; + goto err; + } + + tegra_sgtl5000_dai.platform_of_node = tegra_sgtl5000_dai.cpu_of_node; + + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); + if (ret) + goto err; + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); + goto err_fini_utils; + } + + return 0; + +err_fini_utils: + tegra_asoc_utils_fini(&machine->util_data); +err: + return ret; +} + +static int tegra_sgtl5000_driver_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct tegra_sgtl5000 *machine = snd_soc_card_get_drvdata(card); + int ret; + + ret = snd_soc_unregister_card(card); + + tegra_asoc_utils_fini(&machine->util_data); + + return ret; +} + +static const struct of_device_id tegra_sgtl5000_of_match[] = { + { .compatible = "nvidia,tegra-audio-sgtl5000", }, + { /* sentinel */ }, +}; + +static struct platform_driver tegra_sgtl5000_driver = { + .driver = { + .name = DRV_NAME, + .pm = &snd_soc_pm_ops, + .of_match_table = tegra_sgtl5000_of_match, + }, + .probe = tegra_sgtl5000_driver_probe, + .remove = tegra_sgtl5000_driver_remove, +}; +module_platform_driver(tegra_sgtl5000_driver); + +MODULE_AUTHOR("Marcel Ziswiler "); +MODULE_DESCRIPTION("Tegra SGTL5000 machine ASoC driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); +MODULE_DEVICE_TABLE(of, tegra_sgtl5000_of_match); -- cgit v0.10.2 From c49aed77d55b42a1ec5e1d01c2ab788abc82717c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:55 -0500 Subject: ASoC: rt5640: add internal clock source support Adding missing definitions and flags to select internal clock source as system clock, needed for jack detection. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 09e8988..b0f6f07 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -1870,6 +1870,9 @@ static int rt5640_set_dai_sysclk(struct snd_soc_dai *dai, case RT5640_SCLK_S_PLL1: reg_val |= RT5640_SCLK_SRC_PLL1; break; + case RT5640_SCLK_S_RCCLK: + reg_val |= RT5640_SCLK_SRC_RCCLK; + break; default: dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); return -EINVAL; diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h index 58b664b..90c8871 100644 --- a/sound/soc/codecs/rt5640.h +++ b/sound/soc/codecs/rt5640.h @@ -984,6 +984,7 @@ #define RT5640_SCLK_SRC_SFT 14 #define RT5640_SCLK_SRC_MCLK (0x0 << 14) #define RT5640_SCLK_SRC_PLL1 (0x1 << 14) +#define RT5640_SCLK_SRC_RCCLK (0x2 << 14) #define RT5640_PLL1_SRC_MASK (0x3 << 12) #define RT5640_PLL1_SRC_SFT 12 #define RT5640_PLL1_SRC_MCLK (0x0 << 12) -- cgit v0.10.2 From 73442e3ccbc3136cf92a6785d81d118932292681 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:44 -0500 Subject: ASoC: Intel: bytcr-rt5640: add Asus T100TAF quirks Add quirk based on DMI string matching Also fix matching to use DMI_EXACT_MATCH otherwise T100TA and T100TAF will be using same quirk Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 88efb62..2d3441d 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -127,16 +127,24 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { { .callback = byt_rt5640_quirk_cb, .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"), + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"), }, .driver_data = (unsigned long *)BYT_RT5640_IN1_MAP, }, { .callback = byt_rt5640_quirk_cb, .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "DellInc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"), + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"), + }, + .driver_data = (unsigned long *)BYT_RT5640_IN1_MAP, + }, + { + .callback = byt_rt5640_quirk_cb, + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "DellInc."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"), }, .driver_data = (unsigned long *)(BYT_RT5640_DMIC2_MAP | BYT_RT5640_DMIC_EN), @@ -144,8 +152,8 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { { .callback = byt_rt5640_quirk_cb, .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"), + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"), }, .driver_data = (unsigned long *)BYT_RT5640_IN1_MAP, }, -- cgit v0.10.2 From 68817cdb3b9f1a19ac6741cdb7151f463d86ec7f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:45 -0500 Subject: ASoC: Intel: bytcr_rt5640: quirk for mono speaker Some Baytrail devices only have a mono speaker, add quirk and enable it for T100TAF. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 2d3441d..421a53c 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -40,6 +40,7 @@ enum { #define BYT_RT5640_MAP(quirk) ((quirk) & 0xff) #define BYT_RT5640_DMIC_EN BIT(16) +#define BYT_RT5640_MONO_SPEAKER BIT(17) static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP | BYT_RT5640_DMIC_EN; @@ -63,10 +64,6 @@ static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { {"IN2P", NULL, "Headset Mic"}, {"Headphone", NULL, "HPOL"}, {"Headphone", NULL, "HPOR"}, - {"Speaker", NULL, "SPOLP"}, - {"Speaker", NULL, "SPOLN"}, - {"Speaker", NULL, "SPORP"}, - {"Speaker", NULL, "SPORN"}, }; static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = { @@ -82,6 +79,18 @@ static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = { {"IN1P", NULL, "Internal Mic"}, }; +static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = { + {"Speaker", NULL, "SPOLP"}, + {"Speaker", NULL, "SPOLN"}, + {"Speaker", NULL, "SPORP"}, + {"Speaker", NULL, "SPORN"}, +}; + +static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = { + {"Speaker", NULL, "SPOLP"}, + {"Speaker", NULL, "SPOLN"}, +}; + static const struct snd_kcontrol_new byt_rt5640_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone"), SOC_DAPM_PIN_SWITCH("Headset Mic"), @@ -138,7 +147,9 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"), }, - .driver_data = (unsigned long *)BYT_RT5640_IN1_MAP, + .driver_data = (unsigned long *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_MONO_SPEAKER + ), }, { .callback = byt_rt5640_quirk_cb, @@ -200,6 +211,18 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) if (ret) return ret; + if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { + ret = snd_soc_dapm_add_routes(&card->dapm, + byt_rt5640_mono_spk_map, + ARRAY_SIZE(byt_rt5640_mono_spk_map)); + } else { + ret = snd_soc_dapm_add_routes(&card->dapm, + byt_rt5640_stereo_spk_map, + ARRAY_SIZE(byt_rt5640_stereo_spk_map)); + } + if (ret) + return ret; + if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN) { ret = rt5640_dmic_enable(codec, 0, 0); if (ret) -- cgit v0.10.2 From 5d98f58fd66ea164d7e317d57de77b7d7c1391ff Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:46 -0500 Subject: ASoC: Intel: bytcr_rt5640: enable differential mic quirk Some Baytrail-CR devices rely on analog mics connected with differential pairs and not the single-ended default Add quirk and enable it for T00TAF Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 421a53c..085e57f 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -41,6 +41,7 @@ enum { #define BYT_RT5640_MAP(quirk) ((quirk) & 0xff) #define BYT_RT5640_DMIC_EN BIT(16) #define BYT_RT5640_MONO_SPEAKER BIT(17) +#define BYT_RT5640_DIFF_MIC BIT(18) /* defaut is single-ended */ static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP | BYT_RT5640_DMIC_EN; @@ -148,7 +149,8 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"), }, .driver_data = (unsigned long *)(BYT_RT5640_IN1_MAP | - BYT_RT5640_MONO_SPEAKER + BYT_RT5640_MONO_SPEAKER | + BYT_RT5640_DIFF_MIC ), }, { @@ -223,6 +225,11 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) if (ret) return ret; + if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) { + snd_soc_update_bits(codec, RT5640_IN1_IN2, RT5640_IN_DF1, + RT5640_IN_DF1); + } + if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN) { ret = rt5640_dmic_enable(codec, 0, 0); if (ret) -- cgit v0.10.2 From a68bc0d43e1b96c374c4b03eb9baa662778357b3 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:47 -0500 Subject: ASoC: Intel: Atom: auto-detection of Baytrail-CR BYT-CR needs special handling to deal with BIOS issues. For some reason the IPC interrupt index is also modified from the Baytrail-T reference. Use PUNIT BIOS config bits to infer platform details. Assume regular Baytrail configs if status is incorrect or CONFIG_IOSF_MBI is not enabled. SSP0 routing issues are solved without dedicated firmware in following patches Tested on Asus T100TA and T100TAF. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index 4d31849..0c2cc42 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include "../sst-mfld-platform.h" #include "../../common/sst-dsp.h" #include "../../common/sst-acpi.h" @@ -113,6 +115,28 @@ static const struct sst_res_info byt_rvp_res_info = { .acpi_ipc_irq_index = 5, }; +/* BYTCR has different BIOS from BYT */ +static const struct sst_res_info bytcr_res_info = { + .shim_offset = 0x140000, + .shim_size = 0x000100, + .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR, + .ssp0_offset = 0xa0000, + .ssp0_size = 0x1000, + .dma0_offset = 0x98000, + .dma0_size = 0x4000, + .dma1_offset = 0x9c000, + .dma1_size = 0x4000, + .iram_offset = 0x0c0000, + .iram_size = 0x14000, + .dram_offset = 0x100000, + .dram_size = 0x28000, + .mbox_offset = 0x144000, + .mbox_size = 0x1000, + .acpi_lpe_res_index = 0, + .acpi_ddr_index = 2, + .acpi_ipc_irq_index = 0 +}; + static struct sst_platform_info byt_rvp_platform_data = { .probe_data = &byt_fwparse_info, .ipc_info = &byt_ipc_info, @@ -215,6 +239,47 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) return 0; } + +static int is_byt_cr(struct device *dev, bool *bytcr) +{ + int status = 0; + + if (IS_ENABLED(CONFIG_IOSF_MBI)) { + static const struct x86_cpu_id cpu_ids[] __initconst = { + { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ + {} + }; + int status; + u32 bios_status; + + if (!x86_match_cpu(cpu_ids) || !iosf_mbi_available()) { + /* bail silently */ + return status; + } + + status = iosf_mbi_read(BT_MBI_UNIT_PMC, /* 0x04 PUNIT */ + MBI_REG_READ, /* 0x10 */ + 0x006, /* BIOS_CONFIG */ + &bios_status); + + if (status) { + dev_err(dev, "could not read PUNIT BIOS_CONFIG\n"); + } else { + /* bits 26:27 mirror PMIC options */ + bios_status = (bios_status >> 26) & 3; + + if ((bios_status == 1) || (bios_status == 3)) + *bytcr = true; + else + dev_info(dev, "BYT-CR not detected\n"); + } + } else { + dev_info(dev, "IOSF_MBI not enabled, no BYT-CR detection\n"); + } + return status; +} + + static int sst_acpi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -226,6 +291,7 @@ static int sst_acpi_probe(struct platform_device *pdev) struct platform_device *plat_dev; struct sst_platform_info *pdata; unsigned int dev_id; + bool bytcr = false; id = acpi_match_device(dev->driver->acpi_match_table, dev); if (!id) @@ -251,6 +317,18 @@ static int sst_acpi_probe(struct platform_device *pdev) dev_dbg(dev, "ACPI device id: %x\n", dev_id); + ret = sst_alloc_drv_context(&ctx, dev, dev_id); + if (ret < 0) + return ret; + + ret = is_byt_cr(dev, &bytcr); + if (!((ret < 0) || (bytcr == false))) { + dev_info(dev, "Detected Baytrail-CR platform\n"); + + /* override resource info */ + byt_rvp_platform_data.res_info = &bytcr_res_info; + } + plat_dev = platform_device_register_data(dev, pdata->platform, -1, NULL, 0); if (IS_ERR(plat_dev)) { @@ -271,10 +349,6 @@ static int sst_acpi_probe(struct platform_device *pdev) return PTR_ERR(mdev); } - ret = sst_alloc_drv_context(&ctx, dev, dev_id); - if (ret < 0) - return ret; - /* Fill sst platform data */ ctx->pdata = pdata; strcpy(ctx->firmware_name, mach->fw_filename); -- cgit v0.10.2 From 3d240d73df4e3a21d9c2cdc378c192760adcba13 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:48 -0500 Subject: ASoC: Intel: Atom: add definitions for modem/SSP0 interface The Atom DPCM driver only allowed for the SSP2 interface, add definitions for modem/SSP0. These definitions might be used to route audio to a codec connected to SSP0 (instead of a modem in traditional usages), but there is a restriction to 2ch I2S. SSP2 is capable of handling up to 4 slot TDM. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index 98720a9..28eea12 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c @@ -1,4 +1,4 @@ -/* + /* * sst-atom-controls.c - Intel MID Platform driver DPCM ALSA controls for Mrfld * * Copyright (C) 2013-14 Intel Corp @@ -534,6 +534,7 @@ static const DECLARE_TLV_DB_SCALE(sst_gain_tlv_common, SST_GAIN_MIN_VALUE * 10, /* Look up table to convert MIXER SW bit regs to SWM inputs */ static const uint swm_mixer_input_ids[SST_SWM_INPUT_COUNT] = { + [SST_IP_MODEM] = SST_SWM_IN_MODEM, [SST_IP_CODEC0] = SST_SWM_IN_CODEC0, [SST_IP_CODEC1] = SST_SWM_IN_CODEC1, [SST_IP_LOOP0] = SST_SWM_IN_SPROT_LOOP, @@ -674,6 +675,7 @@ static int sst_swm_mixer_event(struct snd_soc_dapm_widget *w, /* SBA mixers - 16 inputs */ #define SST_SBA_DECLARE_MIX_CONTROLS(kctl_name) \ static const struct snd_kcontrol_new kctl_name[] = { \ + SOC_DAPM_SINGLE("modem_in Switch", SND_SOC_NOPM, SST_IP_MODEM, 1, 0), \ SOC_DAPM_SINGLE("codec_in0 Switch", SND_SOC_NOPM, SST_IP_CODEC0, 1, 0), \ SOC_DAPM_SINGLE("codec_in1 Switch", SND_SOC_NOPM, SST_IP_CODEC1, 1, 0), \ SOC_DAPM_SINGLE("sprot_loop_in Switch", SND_SOC_NOPM, SST_IP_LOOP0, 1, 0), \ @@ -684,6 +686,7 @@ static int sst_swm_mixer_event(struct snd_soc_dapm_widget *w, } #define SST_SBA_MIXER_GRAPH_MAP(mix_name) \ + { mix_name, "modem_in Switch", "modem_in" }, \ { mix_name, "codec_in0 Switch", "codec_in0" }, \ { mix_name, "codec_in1 Switch", "codec_in1" }, \ { mix_name, "sprot_loop_in Switch", "sprot_loop_in" }, \ @@ -713,6 +716,7 @@ SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l2_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_voip_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec0_controls); SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec1_controls); +SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_modem_controls); /* * sst_handle_vb_timer - Start/Stop the DSP scheduler @@ -1047,8 +1051,10 @@ static int sst_set_media_loop(struct snd_soc_dapm_widget *w, } static const struct snd_soc_dapm_widget sst_dapm_widgets[] = { + SST_AIF_IN("modem_in", sst_set_be_modules), SST_AIF_IN("codec_in0", sst_set_be_modules), SST_AIF_IN("codec_in1", sst_set_be_modules), + SST_AIF_OUT("modem_out", sst_set_be_modules), SST_AIF_OUT("codec_out0", sst_set_be_modules), SST_AIF_OUT("codec_out1", sst_set_be_modules), @@ -1103,6 +1109,9 @@ static const struct snd_soc_dapm_widget sst_dapm_widgets[] = { sst_mix_codec0_controls, sst_swm_mixer_event), SST_SWM_MIXER("codec_out1 mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_CODEC1, sst_mix_codec1_controls, sst_swm_mixer_event), + SST_SWM_MIXER("modem_out mix 0", SND_SOC_NOPM, SST_TASK_SBA, SST_SWM_OUT_MODEM, + sst_mix_modem_controls, sst_swm_mixer_event), + }; static const struct snd_soc_dapm_route intercon[] = { @@ -1148,6 +1157,9 @@ static const struct snd_soc_dapm_route intercon[] = { SST_SBA_MIXER_GRAPH_MAP("codec_out0 mix 0"), {"codec_out1", NULL, "codec_out1 mix 0"}, SST_SBA_MIXER_GRAPH_MAP("codec_out1 mix 0"), + {"modem_out", NULL, "modem_out mix 0"}, + SST_SBA_MIXER_GRAPH_MAP("modem_out mix 0"), + }; static const char * const slot_names[] = { @@ -1217,6 +1229,9 @@ static const struct snd_kcontrol_new sst_gain_controls[] = { SST_GAIN("media_loop2_out", SST_PATH_INDEX_MEDIA_LOOP2_OUT, SST_TASK_SBA, 0, &sst_gains[13]), SST_GAIN("sprot_loop_out", SST_PATH_INDEX_SPROT_LOOP_OUT, SST_TASK_SBA, 0, &sst_gains[14]), SST_VOLUME("media0_in", SST_PATH_INDEX_MEDIA0_IN, SST_TASK_MMX, 0, &sst_gains[15]), + SST_GAIN("modem_in", SST_PATH_INDEX_MODEM_IN, SST_TASK_SBA, 0, &sst_gains[16]), + SST_GAIN("modem_out", SST_PATH_INDEX_MODEM_OUT, SST_TASK_SBA, 0, &sst_gains[17]), + }; #define SST_GAIN_NUM_CONTROLS 3 diff --git a/sound/soc/intel/atom/sst-atom-controls.h b/sound/soc/intel/atom/sst-atom-controls.h index e011311..351d814 100644 --- a/sound/soc/intel/atom/sst-atom-controls.h +++ b/sound/soc/intel/atom/sst-atom-controls.h @@ -35,6 +35,8 @@ enum { /* define a bit for each mixer input */ #define SST_MIX_IP(x) (x) +#define SST_IP_MODEM SST_MIX_IP(0) +#define SST_IP_BT SST_MIX_IP(1) #define SST_IP_CODEC0 SST_MIX_IP(2) #define SST_IP_CODEC1 SST_MIX_IP(3) #define SST_IP_LOOP0 SST_MIX_IP(4) @@ -63,6 +65,7 @@ enum { * Audio DSP Path Ids. Specified by the audio DSP FW */ enum sst_path_index { + SST_PATH_INDEX_MODEM_OUT = (0x00 << SST_PATH_ID_SHIFT), SST_PATH_INDEX_CODEC_OUT0 = (0x02 << SST_PATH_ID_SHIFT), SST_PATH_INDEX_CODEC_OUT1 = (0x03 << SST_PATH_ID_SHIFT), @@ -80,6 +83,7 @@ enum sst_path_index { /* Start of input paths */ + SST_PATH_INDEX_MODEM_IN = (0x80 << SST_PATH_ID_SHIFT), SST_PATH_INDEX_CODEC_IN0 = (0x82 << SST_PATH_ID_SHIFT), SST_PATH_INDEX_CODEC_IN1 = (0x83 << SST_PATH_ID_SHIFT), @@ -105,6 +109,7 @@ enum sst_path_index { * path IDs */ enum sst_swm_inputs { + SST_SWM_IN_MODEM = (SST_PATH_INDEX_MODEM_IN | SST_DEFAULT_CELL_NBR), 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), @@ -124,6 +129,7 @@ enum sst_swm_inputs { * path IDs */ enum sst_swm_outputs { + SST_SWM_OUT_MODEM = (SST_PATH_INDEX_MODEM_OUT | SST_DEFAULT_CELL_NBR), 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), -- cgit v0.10.2 From a3f10de1843ab6a37d34d1601cc520498c5d3bc9 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:49 -0500 Subject: ASoC: Intel: atom: enable configuration of SSP0 Existing code used SSP2, make selection of SSP id dependent on port name. This is required when the machine driver uses non-default settings Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index 28eea12..0838478 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c @@ -935,17 +935,26 @@ void sst_fill_ssp_defaults(struct snd_soc_dai *dai) int send_ssp_cmd(struct snd_soc_dai *dai, const char *id, bool enable) { struct sst_data *drv = snd_soc_dai_get_drvdata(dai); - const struct sst_ssp_config *config; + int ssp_id; dev_info(dai->dev, "Enter: enable=%d port_name=%s\n", enable, id); + if (strcmp(id, "ssp0-port") == 0) + ssp_id = SSP_MODEM; + else if (strcmp(id, "ssp2-port") == 0) + ssp_id = SSP_CODEC; + else { + dev_dbg(dai->dev, "port %s is not supported\n", id); + return -1; + } + SST_FILL_DEFAULT_DESTINATION(drv->ssp_cmd.header.dst); drv->ssp_cmd.header.command_id = SBA_HW_SET_SSP; drv->ssp_cmd.header.length = sizeof(struct sst_cmd_sba_hw_set_ssp) - sizeof(struct sst_dsp_header); - config = &sst_ssp_configs; - dev_dbg(dai->dev, "ssp_id: %u\n", config->ssp_id); + drv->ssp_cmd.selection = ssp_id; + dev_dbg(dai->dev, "ssp_id: %u\n", ssp_id); if (enable) drv->ssp_cmd.switch_state = SST_SWITCH_ON; -- cgit v0.10.2 From 89b8907ce28fce3e34240e7668c9704880bf3368 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:50 -0500 Subject: ASoC: Intel: bytcr_rt5640: add SSP2_AIF2 routing Add quirk to model routing on Baytrail-CR devices Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 085e57f..6c6f673 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -42,6 +42,7 @@ enum { #define BYT_RT5640_DMIC_EN BIT(16) #define BYT_RT5640_MONO_SPEAKER BIT(17) #define BYT_RT5640_DIFF_MIC BIT(18) /* defaut is single-ended */ +#define BYT_RT5640_SSP2_AIF2 BIT(19) /* default is using AIF1 */ static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP | BYT_RT5640_DMIC_EN; @@ -54,13 +55,6 @@ static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { }; static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { - {"AIF1 Playback", NULL, "ssp2 Tx"}, - {"ssp2 Tx", NULL, "codec_out0"}, - {"ssp2 Tx", NULL, "codec_out1"}, - {"codec_in0", NULL, "ssp2 Rx"}, - {"codec_in1", NULL, "ssp2 Rx"}, - {"ssp2 Rx", NULL, "AIF1 Capture"}, - {"Headset Mic", NULL, "MICBIAS1"}, {"IN2P", NULL, "Headset Mic"}, {"Headphone", NULL, "HPOL"}, @@ -80,6 +74,26 @@ static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = { {"IN1P", NULL, "Internal Mic"}, }; +static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = { + {"ssp2 Tx", NULL, "codec_out0"}, + {"ssp2 Tx", NULL, "codec_out1"}, + {"codec_in0", NULL, "ssp2 Rx"}, + {"codec_in1", NULL, "ssp2 Rx"}, + + {"AIF1 Playback", NULL, "ssp2 Tx"}, + {"ssp2 Rx", NULL, "AIF1 Capture"}, +}; + +static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif2_map[] = { + {"ssp2 Tx", NULL, "codec_out0"}, + {"ssp2 Tx", NULL, "codec_out1"}, + {"codec_in0", NULL, "ssp2 Rx"}, + {"codec_in1", NULL, "ssp2 Rx"}, + + {"AIF2 Playback", NULL, "ssp2 Tx"}, + {"ssp2 Rx", NULL, "AIF2 Capture"}, +}; + static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = { {"Speaker", NULL, "SPOLP"}, {"Speaker", NULL, "SPOLN"}, @@ -213,6 +227,18 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) if (ret) return ret; + if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) { + ret = snd_soc_dapm_add_routes(&card->dapm, + byt_rt5640_ssp2_aif2_map, + ARRAY_SIZE(byt_rt5640_ssp2_aif2_map)); + } else { + ret = snd_soc_dapm_add_routes(&card->dapm, + byt_rt5640_ssp2_aif1_map, + ARRAY_SIZE(byt_rt5640_ssp2_aif1_map)); + } + if (ret) + return ret; + if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { ret = snd_soc_dapm_add_routes(&card->dapm, byt_rt5640_mono_spk_map, @@ -346,7 +372,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { .cpu_dai_name = "ssp2-port", .platform_name = "sst-mfld-platform", .no_pcm = 1, - .codec_dai_name = "rt5640-aif1", + .codec_dai_name = "rt5640-aif1", /* changed w/ quirk */ .codec_name = "i2c-10EC5640:00", /* overwritten with HID */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -373,6 +399,7 @@ static struct snd_soc_card byt_rt5640_card = { }; static char byt_rt5640_codec_name[16]; /* i2c-:00 with HID being 8 chars */ +static char byt_rt5640_codec_aif_name[12]; /* = "rt5640-aif[1|2]" */ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) { @@ -407,6 +434,17 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) /* check quirks before creating card */ dmi_check_system(byt_rt5640_quirk_table); + if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) { + + /* fixup codec aif name */ + snprintf(byt_rt5640_codec_aif_name, + sizeof(byt_rt5640_codec_aif_name), + "%s", "rt5640-aif2"); + + byt_rt5640_dais[dai_index].codec_dai_name = + byt_rt5640_codec_aif_name; + } + ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card); if (ret_val) { -- cgit v0.10.2 From f47088d5ae6bec6d01bb0fd71c7d113aa8eaaa27 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:51 -0500 Subject: ASoC: Intel: bytcr_rt56040: additional routing quirks Allow for all possible combinations of SSP0,SSP2, AIF1, AIF2 combination (only one at a time) Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 6c6f673..4337b5e 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -43,6 +43,8 @@ enum { #define BYT_RT5640_MONO_SPEAKER BIT(17) #define BYT_RT5640_DIFF_MIC BIT(18) /* defaut is single-ended */ #define BYT_RT5640_SSP2_AIF2 BIT(19) /* default is using AIF1 */ +#define BYT_RT5640_SSP0_AIF1 BIT(20) +#define BYT_RT5640_SSP0_AIF2 BIT(21) static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP | BYT_RT5640_DMIC_EN; @@ -94,6 +96,22 @@ static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif2_map[] = { {"ssp2 Rx", NULL, "AIF2 Capture"}, }; +static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif1_map[] = { + {"ssp0 Tx", NULL, "modem_out"}, + {"modem_in", NULL, "ssp0 Rx"}, + + {"AIF1 Playback", NULL, "ssp0 Tx"}, + {"ssp0 Rx", NULL, "AIF1 Capture"}, +}; + +static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = { + {"ssp0 Tx", NULL, "modem_out"}, + {"modem_in", NULL, "ssp0 Rx"}, + + {"AIF2 Playback", NULL, "ssp0 Tx"}, + {"ssp0 Rx", NULL, "AIF2 Capture"}, +}; + static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = { {"Speaker", NULL, "SPOLP"}, {"Speaker", NULL, "SPOLN"}, @@ -231,6 +249,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) ret = snd_soc_dapm_add_routes(&card->dapm, byt_rt5640_ssp2_aif2_map, ARRAY_SIZE(byt_rt5640_ssp2_aif2_map)); + } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) { + ret = snd_soc_dapm_add_routes(&card->dapm, + byt_rt5640_ssp0_aif1_map, + ARRAY_SIZE(byt_rt5640_ssp0_aif1_map)); + } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) { + ret = snd_soc_dapm_add_routes(&card->dapm, + byt_rt5640_ssp0_aif2_map, + ARRAY_SIZE(byt_rt5640_ssp0_aif2_map)); } else { ret = snd_soc_dapm_add_routes(&card->dapm, byt_rt5640_ssp2_aif1_map, @@ -369,7 +395,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { { .name = "SSP2-Codec", .id = 1, - .cpu_dai_name = "ssp2-port", + .cpu_dai_name = "ssp2-port", /* overwritten for ssp0 routing */ .platform_name = "sst-mfld-platform", .no_pcm = 1, .codec_dai_name = "rt5640-aif1", /* changed w/ quirk */ @@ -400,6 +426,7 @@ static struct snd_soc_card byt_rt5640_card = { static char byt_rt5640_codec_name[16]; /* i2c-:00 with HID being 8 chars */ static char byt_rt5640_codec_aif_name[12]; /* = "rt5640-aif[1|2]" */ +static char byt_rt5640_cpu_dai_name[10]; /* = "ssp[0|2]-port" */ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) { @@ -434,7 +461,8 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) /* check quirks before creating card */ dmi_check_system(byt_rt5640_quirk_table); - if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) { + if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) || + (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { /* fixup codec aif name */ snprintf(byt_rt5640_codec_aif_name, @@ -445,6 +473,18 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) byt_rt5640_codec_aif_name; } + if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || + (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { + + /* fixup cpu dai name name */ + snprintf(byt_rt5640_cpu_dai_name, + sizeof(byt_rt5640_cpu_dai_name), + "%s", "ssp0-port"); + + byt_rt5640_dais[dai_index].cpu_dai_name = + byt_rt5640_cpu_dai_name; + } + ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card); if (ret_val) { -- cgit v0.10.2 From 038a50e735c85a7a9fbcda090785a588443ffa26 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:52 -0500 Subject: ASoC: Intel: bytcr_rt5640: fix dai/clock setup for SSP0 routing SSP0 uses 16 bits 2ch, SSP2 24 bits 2ch Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 4337b5e..42c7bd2 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -138,8 +138,6 @@ static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret; - snd_soc_dai_set_bclk_ratio(codec_dai, 50); - ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, params_rate(params) * 512, SND_SOC_CLOCK_IN); @@ -148,9 +146,18 @@ static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, return ret; } - ret = snd_soc_dai_set_pll(codec_dai, 0, RT5640_PLL1_S_BCLK1, - params_rate(params) * 50, - params_rate(params) * 512); + if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || + (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { + + ret = snd_soc_dai_set_pll(codec_dai, 0, RT5640_PLL1_S_BCLK1, + params_rate(params) * 32, /* FIXME */ + params_rate(params) * 512); + } else { + ret = snd_soc_dai_set_pll(codec_dai, 0, RT5640_PLL1_S_BCLK1, + params_rate(params) * 50, + params_rate(params) * 512); + } + if (ret < 0) { dev_err(rtd->dev, "can't set codec pll: %d\n", ret); return ret; @@ -311,34 +318,63 @@ static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, SNDRV_PCM_HW_PARAM_CHANNELS); int ret; - /* The DSP will covert the FE rate to 48k, stereo, 24bits */ + /* The DSP will covert the FE rate to 48k, stereo */ rate->min = rate->max = 48000; channels->min = channels->max = 2; - /* set SSP2 to 24-bit */ - params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); - - /* - * Default mode for SSP configuration is TDM 4 slot, override config - * with explicit setting to I2S 2ch 24-bit. The word length is set with - * dai_set_tdm_slot() since there is no other API exposed - */ - ret = snd_soc_dai_set_fmt(rtd->cpu_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_IF | - SND_SOC_DAIFMT_CBS_CFS - ); - if (ret < 0) { - dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); - return ret; - } + if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || + (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { + + /* set SSP2 to 16-bit */ + params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); + + /* + * Default mode for SSP configuration is TDM 4 slot, override config + * with explicit setting to I2S 2ch 16-bit. The word length is set with + * dai_set_tdm_slot() since there is no other API exposed + */ + ret = snd_soc_dai_set_fmt(rtd->cpu_dai, + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_CBS_CFS + ); + if (ret < 0) { + dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); + return ret; + } - ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24); - if (ret < 0) { - dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); - return ret; - } + ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16); + if (ret < 0) { + dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); + return ret; + } + + } else { + /* set SSP2 to 24-bit */ + params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); + + /* + * Default mode for SSP configuration is TDM 4 slot, override config + * with explicit setting to I2S 2ch 24-bit. The word length is set with + * dai_set_tdm_slot() since there is no other API exposed + */ + ret = snd_soc_dai_set_fmt(rtd->cpu_dai, + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_CBS_CFS + ); + if (ret < 0) { + dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24); + if (ret < 0) { + dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); + return ret; + } + } return 0; } -- cgit v0.10.2 From e214f5e78aca81080c156a68a263d31d51d0ea17 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:53 -0500 Subject: ASoC: Intel: bytcr_rt5640: default routing and quirks on Baytrail-CR Auto routing based on Baytrail/Baytrail-CR detection Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 42c7bd2..c4a3c57 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -31,6 +33,7 @@ #include "../../codecs/rt5640.h" #include "../atom/sst-atom-controls.h" #include "../common/sst-acpi.h" +#include "../common/sst-dsp.h" enum { BYT_RT5640_DMIC1_MAP, @@ -189,7 +192,8 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { }, .driver_data = (unsigned long *)(BYT_RT5640_IN1_MAP | BYT_RT5640_MONO_SPEAKER | - BYT_RT5640_DIFF_MIC + BYT_RT5640_DIFF_MIC | + BYT_RT5640_SSP0_AIF2 ), }, { @@ -464,6 +468,18 @@ static char byt_rt5640_codec_name[16]; /* i2c-:00 with HID being 8 chars */ static char byt_rt5640_codec_aif_name[12]; /* = "rt5640-aif[1|2]" */ static char byt_rt5640_cpu_dai_name[10]; /* = "ssp[0|2]-port" */ +static bool is_valleyview(void) +{ + static const struct x86_cpu_id cpu_ids[] __initconst = { + { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ + {} + }; + + if (!x86_match_cpu(cpu_ids)) + return false; + return true; +} + static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) { int ret_val = 0; @@ -494,6 +510,20 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) byt_rt5640_dais[dai_index].codec_name = byt_rt5640_codec_name; } + /* + * swap SSP0 if bytcr is detected + * (will be overridden if DMI quirk is detected) + */ + if (is_valleyview()) { + struct sst_platform_info *p_info = mach->pdata; + const struct sst_res_info *res_info = p_info->res_info; + + /* TODO: use CHAN package info from BIOS to detect AIF1/AIF2 */ + if (res_info->acpi_ipc_irq_index == 0) { + byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; + } + } + /* check quirks before creating card */ dmi_check_system(byt_rt5640_quirk_table); -- cgit v0.10.2 From 59e8b6520c6e2e867b35bc402d9a3f28aef3b2bc Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:54 -0500 Subject: ASoC: Intel: bytcr_rt5640: add IN3 map Some platforms have the analog mic connected to IN3, add route accordingly Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index c4a3c57..9b9d380 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -39,6 +39,7 @@ enum { BYT_RT5640_DMIC1_MAP, BYT_RT5640_DMIC2_MAP, BYT_RT5640_IN1_MAP, + BYT_RT5640_IN3_MAP, }; #define BYT_RT5640_MAP(quirk) ((quirk) & 0xff) @@ -79,6 +80,11 @@ static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = { {"IN1P", NULL, "Internal Mic"}, }; +static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = { + {"Internal Mic", NULL, "MICBIAS1"}, + {"IN3P", NULL, "Internal Mic"}, +}; + static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = { {"ssp2 Tx", NULL, "codec_out0"}, {"ssp2 Tx", NULL, "codec_out1"}, @@ -243,6 +249,10 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) custom_map = byt_rt5640_intmic_in1_map; num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map); break; + case BYT_RT5640_IN3_MAP: + custom_map = byt_rt5640_intmic_in3_map; + num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map); + break; case BYT_RT5640_DMIC2_MAP: custom_map = byt_rt5640_intmic_dmic2_map; num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map); -- cgit v0.10.2 From df1a2776a795848f4dbc7c0cb396158b43eb8aa3 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Fri, 12 Aug 2016 16:27:57 -0500 Subject: ASoC: Intel: bytcr_rt5640: add MCLK support Use platform clocks "pmc_plt_clk_3" when MCLK quirk is defined. By default always enable the 19.2 MHz PLL. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Irina Tirdea Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 9b9d380..11e11c6 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -49,18 +50,104 @@ enum { #define BYT_RT5640_SSP2_AIF2 BIT(19) /* default is using AIF1 */ #define BYT_RT5640_SSP0_AIF1 BIT(20) #define BYT_RT5640_SSP0_AIF2 BIT(21) +#define BYT_RT5640_MCLK_EN BIT(22) +#define BYT_RT5640_MCLK_25MHZ BIT(23) + +struct byt_rt5640_private { + struct clk *mclk; +}; static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP | - BYT_RT5640_DMIC_EN; + BYT_RT5640_DMIC_EN | + BYT_RT5640_MCLK_EN; + +#define BYT_CODEC_DAI1 "rt5640-aif1" +#define BYT_CODEC_DAI2 "rt5640-aif2" + +static inline struct snd_soc_dai *byt_get_codec_dai(struct snd_soc_card *card) +{ + struct snd_soc_pcm_runtime *rtd; + + list_for_each_entry(rtd, &card->rtd_list, list) { + if (!strncmp(rtd->codec_dai->name, BYT_CODEC_DAI1, + strlen(BYT_CODEC_DAI1))) + return rtd->codec_dai; + if (!strncmp(rtd->codec_dai->name, BYT_CODEC_DAI2, + strlen(BYT_CODEC_DAI2))) + return rtd->codec_dai; + + } + return NULL; +} + +static int platform_clock_control(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct snd_soc_dai *codec_dai; + struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); + int ret; + + codec_dai = byt_get_codec_dai(card); + if (!codec_dai) { + dev_err(card->dev, + "Codec dai not found; Unable to set platform clock\n"); + return -EIO; + } + + if (SND_SOC_DAPM_EVENT_ON(event)) { + if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && priv->mclk) { + ret = clk_prepare_enable(priv->mclk); + if (ret < 0) { + dev_err(card->dev, + "could not configure MCLK state"); + return ret; + } + } + ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, + 48000 * 512, + SND_SOC_CLOCK_IN); + } else { + /* + * Set codec clock source to internal clock before + * turning off the platform clock. Codec needs clock + * for Jack detection and button press + */ + ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_RCCLK, + 0, + SND_SOC_CLOCK_IN); + if (!ret) { + if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && priv->mclk) + clk_disable_unprepare(priv->mclk); + } + } + + if (ret < 0) { + dev_err(card->dev, "can't set codec sysclk: %d\n", ret); + return ret; + } + + return 0; +} static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_MIC("Internal Mic", NULL), SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, + platform_clock_control, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMD), + }; static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { + {"Headphone", NULL, "Platform Clock"}, + {"Headset Mic", NULL, "Platform Clock"}, + {"Internal Mic", NULL, "Platform Clock"}, + {"Speaker", NULL, "Platform Clock"}, + {"Headset Mic", NULL, "MICBIAS1"}, {"IN2P", NULL, "Headset Mic"}, {"Headphone", NULL, "HPOL"}, @@ -150,21 +237,41 @@ static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, params_rate(params) * 512, SND_SOC_CLOCK_IN); + if (ret < 0) { dev_err(rtd->dev, "can't set codec clock %d\n", ret); return ret; } - if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || - (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { - - ret = snd_soc_dai_set_pll(codec_dai, 0, RT5640_PLL1_S_BCLK1, - params_rate(params) * 32, /* FIXME */ - params_rate(params) * 512); + if (!(byt_rt5640_quirk & BYT_RT5640_MCLK_EN)) { + /* use bitclock as PLL input */ + if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || + (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { + + /* 2x16 bit slots on SSP0 */ + ret = snd_soc_dai_set_pll(codec_dai, 0, + RT5640_PLL1_S_BCLK1, + params_rate(params) * 32, + params_rate(params) * 512); + } else { + /* 2x15 bit slots on SSP2 */ + ret = snd_soc_dai_set_pll(codec_dai, 0, + RT5640_PLL1_S_BCLK1, + params_rate(params) * 50, + params_rate(params) * 512); + } } else { - ret = snd_soc_dai_set_pll(codec_dai, 0, RT5640_PLL1_S_BCLK1, - params_rate(params) * 50, - params_rate(params) * 512); + if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) { + ret = snd_soc_dai_set_pll(codec_dai, 0, + RT5640_PLL1_S_MCLK, + 25000000, + params_rate(params) * 512); + } else { + ret = snd_soc_dai_set_pll(codec_dai, 0, + RT5640_PLL1_S_MCLK, + 19200000, + params_rate(params) * 512); + } } if (ret < 0) { @@ -188,7 +295,8 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"), }, - .driver_data = (unsigned long *)BYT_RT5640_IN1_MAP, + .driver_data = (unsigned long *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_MCLK_EN), }, { .callback = byt_rt5640_quirk_cb, @@ -199,7 +307,8 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { .driver_data = (unsigned long *)(BYT_RT5640_IN1_MAP | BYT_RT5640_MONO_SPEAKER | BYT_RT5640_DIFF_MIC | - BYT_RT5640_SSP0_AIF2 + BYT_RT5640_SSP0_AIF2 | + BYT_RT5640_MCLK_EN ), }, { @@ -209,7 +318,8 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"), }, .driver_data = (unsigned long *)(BYT_RT5640_DMIC2_MAP | - BYT_RT5640_DMIC_EN), + BYT_RT5640_DMIC_EN | + BYT_RT5640_MCLK_EN), }, { .callback = byt_rt5640_quirk_cb, @@ -217,7 +327,8 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"), }, - .driver_data = (unsigned long *)BYT_RT5640_IN1_MAP, + .driver_data = (unsigned long *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_MCLK_EN), }, {} }; @@ -228,13 +339,18 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) struct snd_soc_codec *codec = runtime->codec; struct snd_soc_card *card = runtime->card; const struct snd_soc_dapm_route *custom_map; + struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); int num_routes; card->dapm.idle_bias_off = true; rt5640_sel_asrc_clk_src(codec, RT5640_DA_STEREO_FILTER | - RT5640_AD_STEREO_FILTER, + RT5640_DA_MONO_L_FILTER | + RT5640_DA_MONO_R_FILTER | + RT5640_AD_STEREO_FILTER | + RT5640_AD_MONO_L_FILTER | + RT5640_AD_MONO_R_FILTER, RT5640_CLK_SEL_ASRC); ret = snd_soc_add_card_controls(card, byt_rt5640_controls, @@ -312,6 +428,30 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); + if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && priv->mclk) { + /* + * The firmware might enable the clock at + * boot (this information may or may not + * be reflected in the enable clock register). + * To change the rate we must disable the clock + * first to cover these cases. Due to common + * clock framework restrictions that do not allow + * to disable a clock that has not been enabled, + * we need to enable the clock first. + */ + ret = clk_prepare_enable(priv->mclk); + if (!ret) + clk_disable_unprepare(priv->mclk); + + if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) + ret = clk_set_rate(priv->mclk, 25000000); + else + ret = clk_set_rate(priv->mclk, 19200000); + + if (ret) + dev_err(card->dev, "unable to set MCLK rate\n"); + } + return ret; } @@ -490,6 +630,7 @@ static bool is_valleyview(void) return true; } + static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) { int ret_val = 0; @@ -497,10 +638,16 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) const char *i2c_name = NULL; int i; int dai_index; + struct byt_rt5640_private *priv; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); + if (!priv) + return -ENOMEM; /* register the soc card */ byt_rt5640_card.dev = &pdev->dev; mach = byt_rt5640_card.dev->platform_data; + snd_soc_card_set_drvdata(&byt_rt5640_card, priv); /* fix index of codec dai */ dai_index = MERR_DPCM_COMPR + 1; @@ -561,6 +708,16 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) byt_rt5640_cpu_dai_name; } + if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && (is_valleyview())) { + priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); + if (IS_ERR(priv->mclk)) { + dev_err(&pdev->dev, + "Failed to get MCLK from pmc_plt_clk_3: %ld\n", + PTR_ERR(priv->mclk)); + return PTR_ERR(priv->mclk); + } + } + ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card); if (ret_val) { -- cgit v0.10.2 From 0565e773c272038dc917dde9ed3fb53f72692685 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Fri, 12 Aug 2016 16:27:58 -0500 Subject: AsoC: Intel: Add quirks for MinnowBoard MAX I2S MCLK has been routed to LSE connector on the MinnowBoard starting with HW version 3. Older versions of the board do not have MCLK wired. Add dmi quirk to disable MCLK for MinnowBoard MAX (v2). Signed-off-by: Irina Tirdea Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 11e11c6..230fc23 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -330,6 +330,15 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { .driver_data = (unsigned long *)(BYT_RT5640_IN1_MAP | BYT_RT5640_MCLK_EN), }, + { + .callback = byt_rt5640_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"), + DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"), + }, + .driver_data = (unsigned long *)(BYT_RT5640_DMIC1_MAP | + BYT_RT5640_DMIC_EN), + }, {} }; -- cgit v0.10.2 From ec1c90e777e5a555632747527fae142aa238e583 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:27:59 -0500 Subject: ASoC: Intel: bytcr_rt5640: Add quirk for Teclast X98 Air 3G tablet Add DMI-based quirk, routing from SSP0 to AIF1 is not very usual Suggested-by: Antonio Ospite Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 230fc23..032abfe 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -339,6 +339,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { .driver_data = (unsigned long *)(BYT_RT5640_DMIC1_MAP | BYT_RT5640_DMIC_EN), }, + { + .callback = byt_rt5640_quirk_cb, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), + DMI_MATCH(DMI_BOARD_NAME, "tPAD"), + }, + .driver_data = (unsigned long *)(BYT_RT5640_IN3_MAP | + BYT_RT5640_MCLK_EN | + BYT_RT5640_SSP0_AIF1), + }, {} }; -- cgit v0.10.2 From d7e60d52ac8cbc6eb9baa2c8d1e6d0478b8dadd4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Aug 2016 16:28:00 -0500 Subject: ASoC: Intel: bytcr_rt5640: log quirks use dev_info to provide better support for autodetection and DMI-based quirks, no functional changes Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 032abfe..09ec3d7 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -61,6 +61,35 @@ static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP | BYT_RT5640_DMIC_EN | BYT_RT5640_MCLK_EN; +static void log_quirks(struct device *dev) +{ + if (BYT_RT5640_MAP(byt_rt5640_quirk) == BYT_RT5640_DMIC1_MAP) + dev_info(dev, "quirk DMIC1_MAP enabled"); + if (BYT_RT5640_MAP(byt_rt5640_quirk) == BYT_RT5640_DMIC2_MAP) + dev_info(dev, "quirk DMIC2_MAP enabled"); + if (BYT_RT5640_MAP(byt_rt5640_quirk) == BYT_RT5640_IN1_MAP) + dev_info(dev, "quirk IN1_MAP enabled"); + if (BYT_RT5640_MAP(byt_rt5640_quirk) == BYT_RT5640_IN3_MAP) + dev_info(dev, "quirk IN3_MAP enabled"); + if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN) + dev_info(dev, "quirk DMIC enabled"); + if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) + dev_info(dev, "quirk MONO_SPEAKER enabled"); + if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) + dev_info(dev, "quirk DIFF_MIC enabled"); + if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) + dev_info(dev, "quirk SSP2_AIF2 enabled"); + if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) + dev_info(dev, "quirk SSP0_AIF1 enabled"); + if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) + dev_info(dev, "quirk SSP0_AIF2 enabled"); + if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) + dev_info(dev, "quirk MCLK_EN enabled"); + if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) + dev_info(dev, "quirk MCLK_25MHZ enabled"); +} + + #define BYT_CODEC_DAI1 "rt5640-aif1" #define BYT_CODEC_DAI2 "rt5640-aif2" @@ -702,6 +731,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) /* check quirks before creating card */ dmi_check_system(byt_rt5640_quirk_table); + log_quirks(&pdev->dev); if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) || (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { -- cgit v0.10.2 From 408ef7e18097810f160629447e6ebe979a0b4282 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 15 Aug 2016 16:16:00 +0200 Subject: ASoC: max98371: Delete unnecessary assignment for the field "owner" The field "owner" is set by the core. Thus delete an unneeded initialisation. Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Signed-off-by: Markus Elfring Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max98371.c b/sound/soc/codecs/max98371.c index cf0a39b..3053879 100644 --- a/sound/soc/codecs/max98371.c +++ b/sound/soc/codecs/max98371.c @@ -425,7 +425,6 @@ MODULE_DEVICE_TABLE(of, max98371_of_match); static struct i2c_driver max98371_i2c_driver = { .driver = { .name = "max98371", - .owner = THIS_MODULE, .pm = NULL, .of_match_table = of_match_ptr(max98371_of_match), }, -- cgit v0.10.2 From c80460005743c6f253706a9a5618de81254c81bf Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler Date: Tue, 16 Aug 2016 16:56:17 +0200 Subject: ASoC: dapm: Fix typos in comment Signed-off-by: Peter Meerwald-Stadler Signed-off-by: Mark Brown diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 8698c26..c46b1ff 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1169,7 +1169,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, * @custom_stop_condition: (optional) a function meant to stop the widget graph * walk based on custom logic. * - * Queries DAPM graph as to whether an valid audio stream path exists for + * Queries DAPM graph as to whether a valid audio stream path exists for * the initial stream specified by name. This takes into account * current mixer and mux kcontrol settings. Creates list of valid widgets. * @@ -1294,8 +1294,7 @@ static int dapm_widget_power_check(struct snd_soc_dapm_widget *w) return w->new_power; } -/* Generic check to see if a widget should be powered. - */ +/* Generic check to see if a widget should be powered. */ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w) { int in, out; @@ -1646,7 +1645,7 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie) struct snd_soc_dapm_context *d = data; int ret; - /* If we're off and we're not supposed to be go into STANDBY */ + /* If we're off and we're not supposed to go into STANDBY */ if (d->bias_level == SND_SOC_BIAS_OFF && d->target_bias_level != SND_SOC_BIAS_OFF) { if (d->dev) @@ -1798,7 +1797,7 @@ static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm) * A complete path is a route that has valid endpoints i.e.:- * * o DAC to output pin. - * o Input Pin to ADC. + * o Input pin to ADC. * o Input pin to Output pin (bypass, sidetone) * o DAC to ADC (loopback). */ @@ -2114,7 +2113,7 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) * soc_dapm_connect_path() - Connects or disconnects a path * @path: The path to update * @connect: The new connect state of the path. True if the path is connected, - * false if it is disconneted. + * false if it is disconnected. * @reason: The reason why the path changed (for debugging only) */ static void soc_dapm_connect_path(struct snd_soc_dapm_path *path, @@ -2233,7 +2232,7 @@ static ssize_t dapm_widget_show_component(struct snd_soc_component *cmpnt, if (w->dapm != dapm) continue; - /* only display widgets that burnm power */ + /* only display widgets that burn power */ switch (w->id) { case snd_soc_dapm_hp: case snd_soc_dapm_mic: @@ -2461,7 +2460,7 @@ static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w) switch (w->id) { case snd_soc_dapm_input: - /* On a fully routed card a input is never a source */ + /* On a fully routed card an input is never a source */ if (w->dapm->card->fully_routed) return; ep = SND_SOC_DAPM_EP_SOURCE; @@ -3445,7 +3444,7 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, w->endpoints[dir] = -1; } - /* machine layer set ups unconnected pins and insertions */ + /* machine layer sets up unconnected pins and insertions */ w->connected = 1; return w; } -- cgit v0.10.2 From 032ca4a76fc3cc81801903aa2532f1e6bae94ca2 Mon Sep 17 00:00:00 2001 From: Peter Meerwald-Stadler Date: Tue, 16 Aug 2016 16:56:18 +0200 Subject: ASoC: atmel-pdmic: Fix typos in comments and error messages Signed-off-by: Peter Meerwald-Stadler Cc: Songjun Wu Signed-off-by: Mark Brown diff --git a/sound/soc/atmel/atmel-pdmic.c b/sound/soc/atmel/atmel-pdmic.c index 8b4beb0..bca7751 100644 --- a/sound/soc/atmel/atmel-pdmic.c +++ b/sound/soc/atmel/atmel-pdmic.c @@ -80,7 +80,7 @@ static struct atmel_pdmic_pdata *atmel_pdmic_dt_init(struct device *dev) if (pdata->mic_max_freq < pdata->mic_min_freq) { dev_err(dev, - "mic-max-freq should not less than mic-min-freq\n"); + "mic-max-freq should not be less than mic-min-freq\n"); return ERR_PTR(-EINVAL); } @@ -598,7 +598,7 @@ static int atmel_pdmic_probe(struct platform_device *pdev) dd->irq = platform_get_irq(pdev, 0); if (dd->irq < 0) { ret = dd->irq; - dev_err(dev, "failed to could not get irq: %d\n", ret); + dev_err(dev, "failed to get irq: %d\n", ret); return ret; } @@ -616,7 +616,7 @@ static int atmel_pdmic_probe(struct platform_device *pdev) return ret; } - /* The gclk clock frequency must always be tree times + /* The gclk clock frequency must always be three times * lower than the pclk clock frequency */ ret = clk_set_rate(dd->gclk, clk_get_rate(dd->pclk)/3); @@ -651,7 +651,7 @@ static int atmel_pdmic_probe(struct platform_device *pdev) return ret; } - /* Get the minimal and maximal sample rate that micphone supports */ + /* Get the minimal and maximal sample rate that the microphone supports */ atmel_pdmic_get_sample_rate(dd, &rate_min, &rate_max); /* register cpu dai */ -- cgit v0.10.2 From cac17731df11e076850c46f50a17266181a10b7c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 16 Aug 2016 18:28:21 -0500 Subject: ASoC: Intel: atom: fix 0-day warnings spurious __initconst copy/pasted from other drivers Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index 0c2cc42..773acfb 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c @@ -245,7 +245,7 @@ static int is_byt_cr(struct device *dev, bool *bytcr) int status = 0; if (IS_ENABLED(CONFIG_IOSF_MBI)) { - static const struct x86_cpu_id cpu_ids[] __initconst = { + static const struct x86_cpu_id cpu_ids[] = { { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ {} }; diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 09ec3d7..2548815 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -668,7 +668,7 @@ static char byt_rt5640_cpu_dai_name[10]; /* = "ssp[0|2]-port" */ static bool is_valleyview(void) { - static const struct x86_cpu_id cpu_ids[] __initconst = { + static const struct x86_cpu_id cpu_ids[] = { { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ {} }; -- cgit v0.10.2 From 8f98307d023810669391555e370a8c2a8e2af9b6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 16 Aug 2016 18:28:22 -0500 Subject: ASoC: Intel: bytcr_rt5640: quirk for Acer Aspire SWS-012 Baytrail-CR platform needing SSP0-AIF1 routing Also fix SSP0 while we are at it. Suggested-by: Andrei Lavreniyuk Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 2548815..bff77a1 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -378,6 +378,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_MCLK_EN | BYT_RT5640_SSP0_AIF1), }, + { + .callback = byt_rt5640_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"), + }, + .driver_data = (unsigned long *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_MCLK_EN | + BYT_RT5640_SSP0_AIF1), + + }, {} }; @@ -527,7 +538,7 @@ static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { - /* set SSP2 to 16-bit */ + /* set SSP0 to 16-bit */ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); /* -- cgit v0.10.2 From 6ea9c7ddd96d88e6cc391e63b5ed2fcfe41d5725 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Aug 2016 21:00:54 -0300 Subject: ASoC: fsl_sai: Use 'np' variable The 'np' variable is already assigned to 'pdev->dev.of_node', so use it to improve readability. No functional change. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 2147994..9fadf7e 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -801,8 +801,8 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->pdev = pdev; - if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx6sx-sai") || - of_device_is_compatible(pdev->dev.of_node, "fsl,imx6ul-sai")) + if (of_device_is_compatible(np, "fsl,imx6sx-sai") || + of_device_is_compatible(np, "fsl,imx6ul-sai")) sai->sai_on_imx = true; sai->is_lsb_first = of_property_read_bool(np, "lsb-first"); @@ -883,7 +883,7 @@ static int fsl_sai_probe(struct platform_device *pdev) } if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) && - of_device_is_compatible(pdev->dev.of_node, "fsl,imx6ul-sai")) { + of_device_is_compatible(np, "fsl,imx6ul-sai")) { gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr"); if (IS_ERR(gpr)) { dev_err(&pdev->dev, "cannot find iomuxc registers\n"); -- cgit v0.10.2 From 84ccd63686498e907799fe3789b521a2a18dd6a9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 17 Aug 2016 18:47:59 +0100 Subject: ASoC: Intel: sst: fix ix spelling mistake: "capablities" -> "capabilites" trivial fix to spelling mistake in dev_err message and reformat code to avoid being over 80 chars wide per line Signed-off-by: Colin Ian King Signed-off-by: Mark Brown diff --git a/sound/soc/intel/atom/sst/sst.c b/sound/soc/intel/atom/sst/sst.c index a4b458e..498b5f7 100644 --- a/sound/soc/intel/atom/sst/sst.c +++ b/sound/soc/intel/atom/sst/sst.c @@ -190,7 +190,8 @@ int sst_driver_ops(struct intel_sst_drv *sst) default: dev_err(sst->dev, - "SST Driver capablities missing for dev_id: %x", sst->dev_id); + "SST Driver capabilities missing for dev_id: %x", + sst->dev_id); return -EINVAL; }; } -- cgit v0.10.2 From c029695085145570eba12b6cf236954b42eb4fd5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 19 Aug 2016 10:30:59 -0300 Subject: ASoC: fsl_asrc: Propagate the real error code Instead of returning -EINVAL on error, return the real error code. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index c1a0e01..15f8ba5 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -892,7 +892,7 @@ static int fsl_asrc_probe(struct platform_device *pdev) ret = fsl_asrc_init(asrc_priv); if (ret) { dev_err(&pdev->dev, "failed to init asrc %d\n", ret); - return -EINVAL; + return ret; } asrc_priv->channel_avail = 10; @@ -901,14 +901,14 @@ static int fsl_asrc_probe(struct platform_device *pdev) &asrc_priv->asrc_rate); if (ret) { dev_err(&pdev->dev, "failed to get output rate\n"); - return -EINVAL; + return ret; } ret = of_property_read_u32(np, "fsl,asrc-width", &asrc_priv->asrc_width); if (ret) { dev_err(&pdev->dev, "failed to get output width\n"); - return -EINVAL; + return ret; } if (asrc_priv->asrc_width != 16 && asrc_priv->asrc_width != 24) { -- cgit v0.10.2 From 32101d00ac85a8a85431ce51e58acd6eb4184cf7 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 19 Aug 2016 10:31:01 -0300 Subject: ASoC: fsl_asrc: Remove unneeded driver registration message There is no need to announce that the driver has been successfully probed, so remove the unneeded message. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 15f8ba5..317e93a 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -933,8 +933,6 @@ static int fsl_asrc_probe(struct platform_device *pdev) return ret; } - dev_info(&pdev->dev, "driver registered\n"); - return 0; } -- cgit v0.10.2 From e5abe959549ca267d2f6c7b0df1f74a0d8deab40 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Fri, 19 Aug 2016 21:56:12 +0800 Subject: ASoC: rockchip: Add support rt5514 dsp summy dailink This patch can attach automaticlly rt5514 spi DAI with driver name "rt5514" in the snd_soc_find_dai process. Turn this feature on, we can enable the voice wake up via rt5514 dsp for RK3399 Gru Boards. Signed-off-by: Xing Zheng Signed-off-by: Mark Brown diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index 6d39032..d82d763 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig @@ -49,6 +49,7 @@ config SND_SOC_RK3399_GRU_SOUND select SND_SOC_MAX98357A select SND_SOC_RT5514 select SND_SOC_DA7219 + select SND_SOC_RT5514_SPI help Say Y or M here if you want to add support multiple codecs for SoC audio on Rockchip RK3399 GRU boards. diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 9933703..164b6da 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -230,8 +230,11 @@ enum { DAILINK_MAX98357A, DAILINK_RT5514, DAILINK_DA7219, + DAILINK_RT5514_DSP, }; +#define DAILINK_ENTITIES (DAILINK_DA7219 + 1) + static struct snd_soc_dai_link rockchip_dailinks[] = { [DAILINK_MAX98357A] = { .name = "MAX98357A", @@ -261,6 +264,13 @@ static struct snd_soc_dai_link rockchip_dailinks[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, }, + /* RT5514 DSP for voice wakeup via spi bus */ + [DAILINK_RT5514_DSP] = { + .name = "RT5514 DSP", + .stream_name = "Wake on Voice", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + }, }; static struct snd_soc_card rockchip_sound_card = { @@ -276,10 +286,17 @@ static struct snd_soc_card rockchip_sound_card = { .num_controls = ARRAY_SIZE(rockchip_controls), }; +static int rockchip_sound_match_stub(struct device *dev, void *data) +{ + return 1; +} + static int rockchip_sound_probe(struct platform_device *pdev) { struct snd_soc_card *card = &rockchip_sound_card; struct device_node *cpu_node; + struct device *dev; + struct device_driver *drv; int i, ret; cpu_node = of_parse_phandle(pdev->dev.of_node, "rockchip,cpu", 0); @@ -288,7 +305,7 @@ static int rockchip_sound_probe(struct platform_device *pdev) return -EINVAL; } - for (i = 0; i < card->num_links; i++) { + for (i = 0; i < DAILINK_ENTITIES; i++) { rockchip_dailinks[i].platform_of_node = cpu_node; rockchip_dailinks[i].cpu_of_node = cpu_node; @@ -301,6 +318,26 @@ static int rockchip_sound_probe(struct platform_device *pdev) } } + /** + * To acquire the spi driver of the rt5514 and set the dai-links names + * for soc_bind_dai_link + */ + drv = driver_find("rt5514", &spi_bus_type); + if (!drv) { + dev_err(&pdev->dev, "Can not find the rt5514 driver at the spi bus\n"); + return -EINVAL; + } + + dev = driver_find_device(drv, NULL, NULL, rockchip_sound_match_stub); + if (!dev) { + dev_err(&pdev->dev, "Can not find the rt5514 device\n"); + return -ENODEV; + } + + rockchip_dailinks[DAILINK_RT5514_DSP].cpu_name = kstrdup_const(dev_name(dev), GFP_KERNEL); + rockchip_dailinks[DAILINK_RT5514_DSP].cpu_dai_name = kstrdup_const(dev_name(dev), GFP_KERNEL); + rockchip_dailinks[DAILINK_RT5514_DSP].platform_name = kstrdup_const(dev_name(dev), GFP_KERNEL); + card->dev = &pdev->dev; platform_set_drvdata(pdev, card); -- cgit v0.10.2 From f3d8ac8c4afea2014fbeb5f8e4c03d7fdffd623a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 19 Aug 2016 10:31:00 -0300 Subject: ASoC: fsl_asrc: Use np variable The 'np' variable is already assigned to 'pdev->dev.of_node', so use it to improve readability. No functional change. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 317e93a..b7157ce 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -879,7 +879,7 @@ static int fsl_asrc_probe(struct platform_device *pdev) } } - if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx35-asrc")) { + if (of_device_is_compatible(np, "fsl,imx35-asrc")) { asrc_priv->channel_bits = 3; clk_map[IN] = input_clk_map_imx35; clk_map[OUT] = output_clk_map_imx35; -- cgit v0.10.2 From 77dfa8d3196a0cd219dfd6c65e4ff5a3e696fd8c Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 13 Aug 2016 10:13:33 +0900 Subject: ALSA: seq: add documentation for snd_seq_kernel_client_ctl This kernel API is used by kernel implementation. Currently, it's used for kernel clients of ALSA sequencer, while it can be used for application clients. The difference is just on address spaces of argument. In short, this kernel API can be available for application client with data in kernel space. This commit adds a document about this. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index d6d9419..37590f8 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2423,9 +2423,17 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev, EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); -/* - * exported, called by kernel clients to perform same functions as with - * userland ioctl() +/** + * snd_seq_kernel_client_ctl - operate a command for a client with data in + * kernel space. + * @clientid: A numerical ID for a client. + * @cmd: An ioctl(2) command for ALSA sequencer operation. + * @arg: A pointer to data in kernel space. + * + * Against its name, both kernel/application client can be handled by this + * kernel API. A pointer of 'arg' argument should be in kernel space. + * + * Return: 0 at success. Negative error code at failure. */ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) { -- cgit v0.10.2 From 8ce8eb601c71d4eec4c83ac2398a2cb847f4ef4d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 13 Aug 2016 10:13:34 +0900 Subject: ALSA: seq: add an alternative way to handle ioctl requests ALSA sequencer is designed with two types of clients; application and kernel. Operations for each ioctl command should handle data in both of user space and kernel space, while current implementation just allows them to handle data in user space. Data in kernel space is handled with change of address limit of running tasks. This commit adds a new table to map ioctl commands to corresponding functions. The functions get data in kernel space. Helper functions to operate kernel and application clients seek entries from the table. Especially, the helper function for application is responsible for coping from user space to kernel space or vise versa. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 37590f8..cf37003 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2168,6 +2168,13 @@ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client, /* -------------------------------------------------------- */ +static const struct ioctl_handler { + unsigned int cmd; + int (*func)(struct snd_seq_client *client, void *arg); +} ioctl_handlers[] = { + { 0, NULL }, +}; + static struct seq_ioctl_table { unsigned int cmd; int (*func)(struct snd_seq_client *client, void __user * arg); @@ -2204,6 +2211,63 @@ static struct seq_ioctl_table { { 0, NULL }, }; +static long seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct snd_seq_client *client = file->private_data; + /* To use kernel stack for ioctl data. */ + union ioctl_arg { + int pversion; + int client_id; + struct snd_seq_system_info system_info; + struct snd_seq_running_info running_info; + struct snd_seq_client_info client_info; + struct snd_seq_port_info port_info; + struct snd_seq_port_subscribe port_subscribe; + struct snd_seq_queue_info queue_info; + struct snd_seq_queue_status queue_status; + struct snd_seq_queue_tempo tempo; + struct snd_seq_queue_timer queue_timer; + struct snd_seq_queue_client queue_client; + struct snd_seq_client_pool client_pool; + struct snd_seq_remove_events remove_events; + struct snd_seq_query_subs query_subs; + } buf = {0}; + const struct ioctl_handler *handler; + unsigned long size; + int err; + + if (snd_BUG_ON(!client)) + return -ENXIO; + + for (handler = ioctl_handlers; handler->cmd > 0; ++handler) { + if (handler->cmd == cmd) + break; + } + if (handler->cmd == 0) + return -ENOTTY; + /* + * All of ioctl commands for ALSA sequencer get an argument of size + * within 13 bits. We can safely pick up the size from the command. + */ + size = _IOC_SIZE(handler->cmd); + if (_IOC_DIR(handler->cmd) & IOC_IN) { + if (copy_from_user(&buf, (const void __user *)arg, size)) + return -EFAULT; + } + + err = handler->func(client, &buf); + if (err >= 0) { + /* Some commands includes a bug in 'dir' field. */ + if (handler->cmd == SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT || + handler->cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_POOL || + (_IOC_DIR(handler->cmd) & IOC_OUT)) + if (copy_to_user((void __user *)arg, &buf, size)) + return -EFAULT; + } + + return err; +} + static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd, void __user *arg) { @@ -2234,9 +2298,12 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg { struct snd_seq_client *client = file->private_data; + if (seq_ioctl(file, cmd, arg) >= 0) + return 0; + if (snd_BUG_ON(!client)) return -ENXIO; - + return snd_seq_do_ioctl(client, cmd, (void __user *) arg); } @@ -2437,6 +2504,7 @@ EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); */ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) { + const struct ioctl_handler *handler; struct snd_seq_client *client; mm_segment_t fs; int result; @@ -2444,6 +2512,12 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) client = clientptr(clientid); if (client == NULL) return -ENXIO; + + for (handler = ioctl_handlers; handler->cmd > 0; ++handler) { + if (handler->cmd == cmd) + return handler->func(client, arg); + } + fs = snd_enter_user(); result = snd_seq_do_ioctl(client, cmd, (void __force __user *)arg); snd_leave_user(fs); diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c index 6517590..4cfc505 100644 --- a/sound/core/seq/seq_compat.c +++ b/sound/core/seq/seq_compat.c @@ -59,6 +59,9 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned goto error; data->kernel = NULL; + if (snd_seq_kernel_client_ctl(client->number, cmd, &data) >= 0) + return 0; + fs = snd_enter_user(); err = snd_seq_do_ioctl(client, cmd, data); snd_leave_user(fs); @@ -123,6 +126,8 @@ static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned l case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION: case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT: case SNDRV_SEQ_IOCTL_RUNNING_MODE: + if (seq_ioctl(file, cmd, arg) >= 0) + return 0; return snd_seq_do_ioctl(client, cmd, argp); case SNDRV_SEQ_IOCTL_CREATE_PORT32: return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp); -- cgit v0.10.2 From 04a56dd8ed0de401ccc10e7825d5785844c307fa Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 13 Aug 2016 10:13:35 +0900 Subject: ALSA: seq: change ioctl command operation to get data in kernel space In previous commit, a new table for functions with data in kernel space is added to replace current table. This commit changes existent functions to fit the table. These functions are added to the new table and removed from the old table. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index cf37003..e07a539 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1128,59 +1128,69 @@ static unsigned int snd_seq_poll(struct file *file, poll_table * wait) /*-----------------------------------------------------*/ +static int snd_seq_ioctl_pversion(struct snd_seq_client *client, void *arg) +{ + int *pversion = arg; + + *pversion = SNDRV_SEQ_VERSION; + return 0; +} + +static int snd_seq_ioctl_client_id(struct snd_seq_client *client, void *arg) +{ + int *client_id = arg; + + *client_id = client->number; + return 0; +} /* SYSTEM_INFO ioctl() */ -static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void __user *arg) +static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void *arg) { - struct snd_seq_system_info info; + struct snd_seq_system_info *info = arg; - memset(&info, 0, sizeof(info)); + memset(info, 0, sizeof(*info)); /* fill the info fields */ - info.queues = SNDRV_SEQ_MAX_QUEUES; - info.clients = SNDRV_SEQ_MAX_CLIENTS; - info.ports = SNDRV_SEQ_MAX_PORTS; - info.channels = 256; /* fixed limit */ - info.cur_clients = client_usage.cur; - info.cur_queues = snd_seq_queue_get_cur_queues(); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; + info->queues = SNDRV_SEQ_MAX_QUEUES; + info->clients = SNDRV_SEQ_MAX_CLIENTS; + info->ports = SNDRV_SEQ_MAX_PORTS; + info->channels = 256; /* fixed limit */ + info->cur_clients = client_usage.cur; + info->cur_queues = snd_seq_queue_get_cur_queues(); + return 0; } /* RUNNING_MODE ioctl() */ -static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void __user *arg) +static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg) { - struct snd_seq_running_info info; + struct snd_seq_running_info *info = arg; struct snd_seq_client *cptr; int err = 0; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - /* requested client number */ - cptr = snd_seq_client_use_ptr(info.client); + cptr = snd_seq_client_use_ptr(info->client); if (cptr == NULL) return -ENOENT; /* don't change !!! */ #ifdef SNDRV_BIG_ENDIAN - if (! info.big_endian) { + if (!info->big_endian) { err = -EINVAL; goto __err; } #else - if (info.big_endian) { + if (info->big_endian) { err = -EINVAL; goto __err; } #endif - if (info.cpu_mode > sizeof(long)) { + if (info->cpu_mode > sizeof(long)) { err = -EINVAL; goto __err; } - cptr->convert32 = (info.cpu_mode < sizeof(long)); + cptr->convert32 = (info->cpu_mode < sizeof(long)); __err: snd_seq_client_unlock(cptr); return err; @@ -1214,51 +1224,43 @@ static void get_client_info(struct snd_seq_client *cptr, } static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_client_info *client_info = arg; struct snd_seq_client *cptr; - struct snd_seq_client_info client_info; - - if (copy_from_user(&client_info, arg, sizeof(client_info))) - return -EFAULT; /* requested client number */ - cptr = snd_seq_client_use_ptr(client_info.client); + cptr = snd_seq_client_use_ptr(client_info->client); if (cptr == NULL) return -ENOENT; /* don't change !!! */ - get_client_info(cptr, &client_info); + get_client_info(cptr, client_info); snd_seq_client_unlock(cptr); - if (copy_to_user(arg, &client_info, sizeof(client_info))) - return -EFAULT; return 0; } /* CLIENT_INFO ioctl() */ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_client_info client_info; - - if (copy_from_user(&client_info, arg, sizeof(client_info))) - return -EFAULT; + struct snd_seq_client_info *client_info = arg; /* it is not allowed to set the info fields for an another client */ - if (client->number != client_info.client) + if (client->number != client_info->client) return -EPERM; /* also client type must be set now */ - if (client->type != client_info.type) + if (client->type != client_info->type) return -EINVAL; /* fill the info fields */ - if (client_info.name[0]) - strlcpy(client->name, client_info.name, sizeof(client->name)); + if (client_info->name[0]) + strlcpy(client->name, client_info->name, sizeof(client->name)); - client->filter = client_info.filter; - client->event_lost = client_info.event_lost; - memcpy(client->event_filter, client_info.event_filter, 32); + client->filter = client_info->filter; + client->event_lost = client_info->event_lost; + memcpy(client->event_filter, client_info->event_filter, 32); return 0; } @@ -1267,30 +1269,26 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client, /* * CREATE PORT ioctl() */ -static int snd_seq_ioctl_create_port(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg) { + struct snd_seq_port_info *info = arg; struct snd_seq_client_port *port; - struct snd_seq_port_info info; struct snd_seq_port_callback *callback; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - /* it is not allowed to create the port for an another client */ - if (info.addr.client != client->number) + if (info->addr.client != client->number) return -EPERM; - port = snd_seq_create_port(client, (info.flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info.addr.port : -1); + port = snd_seq_create_port(client, (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info->addr.port : -1); if (port == NULL) return -ENOMEM; - if (client->type == USER_CLIENT && info.kernel) { + if (client->type == USER_CLIENT && info->kernel) { snd_seq_delete_port(client, port->addr.port); return -EINVAL; } if (client->type == KERNEL_CLIENT) { - if ((callback = info.kernel) != NULL) { + if ((callback = info->kernel) != NULL) { if (callback->owner) port->owner = callback->owner; port->private_data = callback->private_data; @@ -1303,37 +1301,29 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, } } - info.addr = port->addr; + info->addr = port->addr; - snd_seq_set_port_info(port, &info); + snd_seq_set_port_info(port, info); snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; } /* * DELETE PORT ioctl() */ -static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, void *arg) { - struct snd_seq_port_info info; + struct snd_seq_port_info *info = arg; int err; - /* set passed parameters */ - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - /* it is not allowed to remove the port for an another client */ - if (info.addr.client != client->number) + if (info->addr.client != client->number) return -EPERM; - err = snd_seq_delete_port(client, info.addr.port); + err = snd_seq_delete_port(client, info->addr.port); if (err >= 0) - snd_seq_system_client_ev_port_exit(client->number, info.addr.port); + snd_seq_system_client_ev_port_exit(client->number, info->addr.port); return err; } @@ -1341,32 +1331,27 @@ static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, /* * GET_PORT_INFO ioctl() (on any client) */ -static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg) { + struct snd_seq_port_info *info = arg; struct snd_seq_client *cptr; struct snd_seq_client_port *port; - struct snd_seq_port_info info; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - cptr = snd_seq_client_use_ptr(info.addr.client); + cptr = snd_seq_client_use_ptr(info->addr.client); if (cptr == NULL) return -ENXIO; - port = snd_seq_port_use_ptr(cptr, info.addr.port); + port = snd_seq_port_use_ptr(cptr, info->addr.port); if (port == NULL) { snd_seq_client_unlock(cptr); return -ENOENT; /* don't change */ } /* get port info */ - snd_seq_get_port_info(port, &info); + snd_seq_get_port_info(port, info); snd_seq_port_unlock(port); snd_seq_client_unlock(cptr); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; } @@ -1374,20 +1359,16 @@ static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, /* * SET_PORT_INFO ioctl() (only ports on this/own client) */ -static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, void *arg) { + struct snd_seq_port_info *info = arg; struct snd_seq_client_port *port; - struct snd_seq_port_info info; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - if (info.addr.client != client->number) /* only set our own ports ! */ + if (info->addr.client != client->number) /* only set our own ports ! */ return -EPERM; - port = snd_seq_port_use_ptr(client, info.addr.port); + port = snd_seq_port_use_ptr(client, info->addr.port); if (port) { - snd_seq_set_port_info(port, &info); + snd_seq_set_port_info(port, info); snd_seq_port_unlock(port); } return 0; @@ -1453,34 +1434,31 @@ int snd_seq_client_notify_subscription(int client, int port, * add to port's subscription list IOCTL interface */ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_port_subscribe *subs = arg; int result = -EINVAL; struct snd_seq_client *receiver = NULL, *sender = NULL; struct snd_seq_client_port *sport = NULL, *dport = NULL; - struct snd_seq_port_subscribe subs; - - if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL) + if ((receiver = snd_seq_client_use_ptr(subs->dest.client)) == NULL) goto __end; - if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) + if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) + if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) goto __end; - if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL) + if ((dport = snd_seq_port_use_ptr(receiver, subs->dest.port)) == NULL) goto __end; - result = check_subscription_permission(client, sport, dport, &subs); + result = check_subscription_permission(client, sport, dport, subs); if (result < 0) goto __end; /* connect them */ - result = snd_seq_port_connect(client, sender, sport, receiver, dport, &subs); + result = snd_seq_port_connect(client, sender, sport, receiver, dport, subs); if (! result) /* broadcast announce */ snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, - &subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED); + subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED); __end: if (sport) snd_seq_port_unlock(sport); @@ -1498,33 +1476,30 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client, * remove from port's subscription list */ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_port_subscribe *subs = arg; int result = -ENXIO; struct snd_seq_client *receiver = NULL, *sender = NULL; struct snd_seq_client_port *sport = NULL, *dport = NULL; - struct snd_seq_port_subscribe subs; - if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - - if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL) + if ((receiver = snd_seq_client_use_ptr(subs->dest.client)) == NULL) goto __end; - if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) + if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) + if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) goto __end; - if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL) + if ((dport = snd_seq_port_use_ptr(receiver, subs->dest.port)) == NULL) goto __end; - result = check_subscription_permission(client, sport, dport, &subs); + result = check_subscription_permission(client, sport, dport, subs); if (result < 0) goto __end; - result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, &subs); + result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, subs); if (! result) /* broadcast announce */ snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, - &subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED); + subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED); __end: if (sport) snd_seq_port_unlock(sport); @@ -1539,17 +1514,13 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client, /* CREATE_QUEUE ioctl() */ -static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; int result; struct snd_seq_queue *q; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - result = snd_seq_queue_alloc(client->number, info.locked, info.flags); + result = snd_seq_queue_alloc(client->number, info->locked, info->flags); if (result < 0) return result; @@ -1557,181 +1528,150 @@ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, if (q == NULL) return -EINVAL; - info.queue = q->queue; - info.locked = q->locked; - info.owner = q->owner; + info->queue = q->queue; + info->locked = q->locked; + info->owner = q->owner; /* set queue name */ - if (! info.name[0]) - snprintf(info.name, sizeof(info.name), "Queue-%d", q->queue); - strlcpy(q->name, info.name, sizeof(q->name)); + if (!info->name[0]) + snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue); + strlcpy(q->name, info->name, sizeof(q->name)); queuefree(q); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; } /* DELETE_QUEUE ioctl() */ -static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client, void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - return snd_seq_queue_delete(client->number, info.queue); + return snd_seq_queue_delete(client->number, info->queue); } /* GET_QUEUE_INFO ioctl() */ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; struct snd_seq_queue *q; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - q = queueptr(info.queue); + q = queueptr(info->queue); if (q == NULL) return -EINVAL; - memset(&info, 0, sizeof(info)); - info.queue = q->queue; - info.owner = q->owner; - info.locked = q->locked; - strlcpy(info.name, q->name, sizeof(info.name)); + memset(info, 0, sizeof(*info)); + info->queue = q->queue; + info->owner = q->owner; + info->locked = q->locked; + strlcpy(info->name, q->name, sizeof(info->name)); queuefree(q); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; } /* SET_QUEUE_INFO ioctl() */ static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; struct snd_seq_queue *q; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - if (info.owner != client->number) + if (info->owner != client->number) return -EINVAL; /* change owner/locked permission */ - if (snd_seq_queue_check_access(info.queue, client->number)) { - if (snd_seq_queue_set_owner(info.queue, client->number, info.locked) < 0) + if (snd_seq_queue_check_access(info->queue, client->number)) { + if (snd_seq_queue_set_owner(info->queue, client->number, info->locked) < 0) return -EPERM; - if (info.locked) - snd_seq_queue_use(info.queue, client->number, 1); + if (info->locked) + snd_seq_queue_use(info->queue, client->number, 1); } else { return -EPERM; } - q = queueptr(info.queue); + q = queueptr(info->queue); if (! q) return -EINVAL; if (q->owner != client->number) { queuefree(q); return -EPERM; } - strlcpy(q->name, info.name, sizeof(q->name)); + strlcpy(q->name, info->name, sizeof(q->name)); queuefree(q); return 0; } /* GET_NAMED_QUEUE ioctl() */ -static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, void __user *arg) +static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, + void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; struct snd_seq_queue *q; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - q = snd_seq_queue_find_name(info.name); + q = snd_seq_queue_find_name(info->name); if (q == NULL) return -EINVAL; - info.queue = q->queue; - info.owner = q->owner; - info.locked = q->locked; + info->queue = q->queue; + info->owner = q->owner; + info->locked = q->locked; queuefree(q); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; } /* GET_QUEUE_STATUS ioctl() */ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_status status; + struct snd_seq_queue_status *status = arg; struct snd_seq_queue *queue; struct snd_seq_timer *tmr; - if (copy_from_user(&status, arg, sizeof(status))) - return -EFAULT; - - queue = queueptr(status.queue); + queue = queueptr(status->queue); if (queue == NULL) return -EINVAL; - memset(&status, 0, sizeof(status)); - status.queue = queue->queue; + memset(status, 0, sizeof(*status)); + status->queue = queue->queue; tmr = queue->timer; - status.events = queue->tickq->cells + queue->timeq->cells; + status->events = queue->tickq->cells + queue->timeq->cells; - status.time = snd_seq_timer_get_cur_time(tmr); - status.tick = snd_seq_timer_get_cur_tick(tmr); + status->time = snd_seq_timer_get_cur_time(tmr); + status->tick = snd_seq_timer_get_cur_tick(tmr); - status.running = tmr->running; + status->running = tmr->running; - status.flags = queue->flags; + status->flags = queue->flags; queuefree(queue); - if (copy_to_user(arg, &status, sizeof(status))) - return -EFAULT; return 0; } /* GET_QUEUE_TEMPO ioctl() */ static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_tempo tempo; + struct snd_seq_queue_tempo *tempo = arg; struct snd_seq_queue *queue; struct snd_seq_timer *tmr; - if (copy_from_user(&tempo, arg, sizeof(tempo))) - return -EFAULT; - - queue = queueptr(tempo.queue); + queue = queueptr(tempo->queue); if (queue == NULL) return -EINVAL; - memset(&tempo, 0, sizeof(tempo)); - tempo.queue = queue->queue; + memset(tempo, 0, sizeof(*tempo)); + tempo->queue = queue->queue; tmr = queue->timer; - tempo.tempo = tmr->tempo; - tempo.ppq = tmr->ppq; - tempo.skew_value = tmr->skew; - tempo.skew_base = tmr->skew_base; + tempo->tempo = tmr->tempo; + tempo->ppq = tmr->ppq; + tempo->skew_value = tmr->skew; + tempo->skew_base = tmr->skew_base; queuefree(queue); - if (copy_to_user(arg, &tempo, sizeof(tempo))) - return -EFAULT; return 0; } @@ -1747,31 +1687,25 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo) EXPORT_SYMBOL(snd_seq_set_queue_tempo); static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_queue_tempo *tempo = arg; int result; - struct snd_seq_queue_tempo tempo; - - if (copy_from_user(&tempo, arg, sizeof(tempo))) - return -EFAULT; - result = snd_seq_set_queue_tempo(client->number, &tempo); + result = snd_seq_set_queue_tempo(client->number, tempo); return result < 0 ? result : 0; } /* GET_QUEUE_TIMER ioctl() */ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_timer timer; + struct snd_seq_queue_timer *timer = arg; struct snd_seq_queue *queue; struct snd_seq_timer *tmr; - if (copy_from_user(&timer, arg, sizeof(timer))) - return -EFAULT; - - queue = queueptr(timer.queue); + queue = queueptr(timer->queue); if (queue == NULL) return -EINVAL; @@ -1780,41 +1714,36 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, return -ERESTARTSYS; } tmr = queue->timer; - memset(&timer, 0, sizeof(timer)); - timer.queue = queue->queue; + memset(timer, 0, sizeof(*timer)); + timer->queue = queue->queue; - timer.type = tmr->type; + timer->type = tmr->type; if (tmr->type == SNDRV_SEQ_TIMER_ALSA) { - timer.u.alsa.id = tmr->alsa_id; - timer.u.alsa.resolution = tmr->preferred_resolution; + timer->u.alsa.id = tmr->alsa_id; + timer->u.alsa.resolution = tmr->preferred_resolution; } mutex_unlock(&queue->timer_mutex); queuefree(queue); - if (copy_to_user(arg, &timer, sizeof(timer))) - return -EFAULT; return 0; } /* SET_QUEUE_TIMER ioctl() */ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_queue_timer *timer = arg; int result = 0; - struct snd_seq_queue_timer timer; - if (copy_from_user(&timer, arg, sizeof(timer))) - return -EFAULT; - - if (timer.type != SNDRV_SEQ_TIMER_ALSA) + if (timer->type != SNDRV_SEQ_TIMER_ALSA) return -EINVAL; - if (snd_seq_queue_check_access(timer.queue, client->number)) { + if (snd_seq_queue_check_access(timer->queue, client->number)) { struct snd_seq_queue *q; struct snd_seq_timer *tmr; - q = queueptr(timer.queue); + q = queueptr(timer->queue); if (q == NULL) return -ENXIO; if (mutex_lock_interruptible(&q->timer_mutex)) { @@ -1822,13 +1751,13 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, return -ERESTARTSYS; } tmr = q->timer; - snd_seq_queue_timer_close(timer.queue); - tmr->type = timer.type; + snd_seq_queue_timer_close(timer->queue); + tmr->type = timer->type; if (tmr->type == SNDRV_SEQ_TIMER_ALSA) { - tmr->alsa_id = timer.u.alsa.id; - tmr->preferred_resolution = timer.u.alsa.resolution; + tmr->alsa_id = timer->u.alsa.id; + tmr->preferred_resolution = timer->u.alsa.resolution; } - result = snd_seq_queue_timer_open(timer.queue); + result = snd_seq_queue_timer_open(timer->queue); mutex_unlock(&q->timer_mutex); queuefree(q); } else { @@ -1841,38 +1770,30 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, /* GET_QUEUE_CLIENT ioctl() */ static int snd_seq_ioctl_get_queue_client(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_client info; + struct snd_seq_queue_client *info = arg; int used; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - used = snd_seq_queue_is_used(info.queue, client->number); + used = snd_seq_queue_is_used(info->queue, client->number); if (used < 0) return -EINVAL; - info.used = used; - info.client = client->number; + info->used = used; + info->client = client->number; - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; } /* SET_QUEUE_CLIENT ioctl() */ static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_queue_client *info = arg; int err; - struct snd_seq_queue_client info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - if (info.used >= 0) { - err = snd_seq_queue_use(info.queue, client->number, info.used); + if (info->used >= 0) { + err = snd_seq_queue_use(info->queue, client->number, info->used); if (err < 0) return err; } @@ -1883,78 +1804,70 @@ static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client, /* GET_CLIENT_POOL ioctl() */ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_client_pool info; + struct snd_seq_client_pool *info = arg; struct snd_seq_client *cptr; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - cptr = snd_seq_client_use_ptr(info.client); + cptr = snd_seq_client_use_ptr(info->client); if (cptr == NULL) return -ENOENT; - memset(&info, 0, sizeof(info)); - info.client = cptr->number; - info.output_pool = cptr->pool->size; - info.output_room = cptr->pool->room; - info.output_free = info.output_pool; - info.output_free = snd_seq_unused_cells(cptr->pool); + memset(info, 0, sizeof(*info)); + info->client = cptr->number; + info->output_pool = cptr->pool->size; + info->output_room = cptr->pool->room; + info->output_free = info->output_pool; + info->output_free = snd_seq_unused_cells(cptr->pool); if (cptr->type == USER_CLIENT) { - info.input_pool = cptr->data.user.fifo_pool_size; - info.input_free = info.input_pool; + info->input_pool = cptr->data.user.fifo_pool_size; + info->input_free = info->input_pool; if (cptr->data.user.fifo) - info.input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool); + info->input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool); } else { - info.input_pool = 0; - info.input_free = 0; + info->input_pool = 0; + info->input_free = 0; } snd_seq_client_unlock(cptr); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; } /* SET_CLIENT_POOL ioctl() */ static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_client_pool info; + struct snd_seq_client_pool *info = arg; int rc; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - if (client->number != info.client) + if (client->number != info->client) return -EINVAL; /* can't change other clients */ - if (info.output_pool >= 1 && info.output_pool <= SNDRV_SEQ_MAX_EVENTS && + if (info->output_pool >= 1 && info->output_pool <= SNDRV_SEQ_MAX_EVENTS && (! snd_seq_write_pool_allocated(client) || - info.output_pool != client->pool->size)) { + info->output_pool != client->pool->size)) { if (snd_seq_write_pool_allocated(client)) { /* remove all existing cells */ snd_seq_queue_client_leave_cells(client->number); snd_seq_pool_done(client->pool); } - client->pool->size = info.output_pool; + client->pool->size = info->output_pool; rc = snd_seq_pool_init(client->pool); if (rc < 0) return rc; } if (client->type == USER_CLIENT && client->data.user.fifo != NULL && - info.input_pool >= 1 && - info.input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS && - info.input_pool != client->data.user.fifo_pool_size) { + info->input_pool >= 1 && + info->input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS && + info->input_pool != client->data.user.fifo_pool_size) { /* change pool size */ - rc = snd_seq_fifo_resize(client->data.user.fifo, info.input_pool); + rc = snd_seq_fifo_resize(client->data.user.fifo, info->input_pool); if (rc < 0) return rc; - client->data.user.fifo_pool_size = info.input_pool; + client->data.user.fifo_pool_size = info->input_pool; } - if (info.output_room >= 1 && - info.output_room <= client->pool->size) { - client->pool->room = info.output_room; + if (info->output_room >= 1 && + info->output_room <= client->pool->size) { + client->pool->room = info->output_room; } return snd_seq_ioctl_get_client_pool(client, arg); @@ -1963,17 +1876,14 @@ static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client, /* REMOVE_EVENTS ioctl() */ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_remove_events info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; + struct snd_seq_remove_events *info = arg; /* * Input mostly not implemented XXX. */ - if (info.remove_mode & SNDRV_SEQ_REMOVE_INPUT) { + if (info->remove_mode & SNDRV_SEQ_REMOVE_INPUT) { /* * No restrictions so for a user client we can clear * the whole fifo @@ -1982,8 +1892,8 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, snd_seq_fifo_clear(client->data.user.fifo); } - if (info.remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) - snd_seq_queue_remove_cells(client->number, &info); + if (info->remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) + snd_seq_queue_remove_cells(client->number, info); return 0; } @@ -1993,26 +1903,23 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, * get subscription info */ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_port_subscribe *subs = arg; int result; struct snd_seq_client *sender = NULL; struct snd_seq_client_port *sport = NULL; - struct snd_seq_port_subscribe subs; struct snd_seq_subscribers *p; - if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - result = -EINVAL; - if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) + if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) + if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) goto __end; - p = snd_seq_port_get_subscription(&sport->c_src, &subs.dest); + p = snd_seq_port_get_subscription(&sport->c_src, &subs->dest); if (p) { result = 0; - subs = p->info; + *subs = p->info; } else result = -ENOENT; @@ -2021,10 +1928,7 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, snd_seq_port_unlock(sport); if (sender) snd_seq_client_unlock(sender); - if (result >= 0) { - if (copy_to_user(arg, &subs, sizeof(subs))) - return -EFAULT; - } + return result; } @@ -2032,26 +1936,22 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, /* * get subscription info - check only its presence */ -static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg) { + struct snd_seq_query_subs *subs = arg; int result = -ENXIO; struct snd_seq_client *cptr = NULL; struct snd_seq_client_port *port = NULL; - struct snd_seq_query_subs subs; struct snd_seq_port_subs_info *group; struct list_head *p; int i; - if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - - if ((cptr = snd_seq_client_use_ptr(subs.root.client)) == NULL) + if ((cptr = snd_seq_client_use_ptr(subs->root.client)) == NULL) goto __end; - if ((port = snd_seq_port_use_ptr(cptr, subs.root.port)) == NULL) + if ((port = snd_seq_port_use_ptr(cptr, subs->root.port)) == NULL) goto __end; - switch (subs.type) { + switch (subs->type) { case SNDRV_SEQ_QUERY_SUBS_READ: group = &port->c_src; break; @@ -2064,22 +1964,22 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, down_read(&group->list_mutex); /* search for the subscriber */ - subs.num_subs = group->count; + subs->num_subs = group->count; i = 0; result = -ENOENT; list_for_each(p, &group->list_head) { - if (i++ == subs.index) { + if (i++ == subs->index) { /* found! */ struct snd_seq_subscribers *s; - if (subs.type == SNDRV_SEQ_QUERY_SUBS_READ) { + if (subs->type == SNDRV_SEQ_QUERY_SUBS_READ) { s = list_entry(p, struct snd_seq_subscribers, src_list); - subs.addr = s->info.dest; + subs->addr = s->info.dest; } else { s = list_entry(p, struct snd_seq_subscribers, dest_list); - subs.addr = s->info.sender; + subs->addr = s->info.sender; } - subs.flags = s->info.flags; - subs.queue = s->info.queue; + subs->flags = s->info.flags; + subs->queue = s->info.queue; result = 0; break; } @@ -2091,10 +1991,7 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, snd_seq_port_unlock(port); if (cptr) snd_seq_client_unlock(cptr); - if (result >= 0) { - if (copy_to_user(arg, &subs, sizeof(subs))) - return -EFAULT; - } + return result; } @@ -2103,31 +2000,26 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, * query next client */ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_client_info *info = arg; struct snd_seq_client *cptr = NULL; - struct snd_seq_client_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; /* search for next client */ - info.client++; - if (info.client < 0) - info.client = 0; - for (; info.client < SNDRV_SEQ_MAX_CLIENTS; info.client++) { - cptr = snd_seq_client_use_ptr(info.client); + info->client++; + if (info->client < 0) + info->client = 0; + for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) { + cptr = snd_seq_client_use_ptr(info->client); if (cptr) break; /* found */ } if (cptr == NULL) return -ENOENT; - get_client_info(cptr, &info); + get_client_info(cptr, info); snd_seq_client_unlock(cptr); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; } @@ -2135,34 +2027,30 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client, * query next port */ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_port_info *info = arg; struct snd_seq_client *cptr; struct snd_seq_client_port *port = NULL; - struct snd_seq_port_info info; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - cptr = snd_seq_client_use_ptr(info.addr.client); + cptr = snd_seq_client_use_ptr(info->addr.client); if (cptr == NULL) return -ENXIO; /* search for next port */ - info.addr.port++; - port = snd_seq_port_query_nearest(cptr, &info); + info->addr.port++; + port = snd_seq_port_query_nearest(cptr, info); if (port == NULL) { snd_seq_client_unlock(cptr); return -ENOENT; } /* get port info */ - info.addr = port->addr; - snd_seq_get_port_info(port, &info); + info->addr = port->addr; + snd_seq_get_port_info(port, info); snd_seq_port_unlock(port); snd_seq_client_unlock(cptr); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; } @@ -2172,13 +2060,8 @@ static const struct ioctl_handler { unsigned int cmd; int (*func)(struct snd_seq_client *client, void *arg); } ioctl_handlers[] = { - { 0, NULL }, -}; - -static struct seq_ioctl_table { - unsigned int cmd; - int (*func)(struct snd_seq_client *client, void __user * arg); -} ioctl_tables[] = { + { SNDRV_SEQ_IOCTL_PVERSION, snd_seq_ioctl_pversion }, + { SNDRV_SEQ_IOCTL_CLIENT_ID, snd_seq_ioctl_client_id }, { SNDRV_SEQ_IOCTL_SYSTEM_INFO, snd_seq_ioctl_system_info }, { SNDRV_SEQ_IOCTL_RUNNING_MODE, snd_seq_ioctl_running_mode }, { SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, snd_seq_ioctl_get_client_info }, @@ -2211,6 +2094,13 @@ static struct seq_ioctl_table { { 0, NULL }, }; +static struct seq_ioctl_table { + unsigned int cmd; + int (*func)(struct snd_seq_client *client, void __user * arg); +} ioctl_tables[] = { + { 0, NULL }, +}; + static long seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct snd_seq_client *client = file->private_data; -- cgit v0.10.2 From e12ec251e4db472e00df2aaefc13430efa25b5ea Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 13 Aug 2016 10:13:36 +0900 Subject: ALSA: seq: obsolete change of address limit Former commits change existent functions so that they don't handle data in kernel space. Copying from/to userspace is done outside of the functions, thus no need to change address limit of running task. This commit obsoletes get_fs()/set_fs() and applies corresponding changes. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index e07a539..286394b 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -87,21 +87,6 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client, /* */ - -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - -/* - */ static inline unsigned short snd_seq_file_flags(struct file *file) { switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) { @@ -2094,14 +2079,8 @@ static const struct ioctl_handler { { 0, NULL }, }; -static struct seq_ioctl_table { - unsigned int cmd; - int (*func)(struct snd_seq_client *client, void __user * arg); -} ioctl_tables[] = { - { 0, NULL }, -}; - -static long seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long snd_seq_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { struct snd_seq_client *client = file->private_data; /* To use kernel stack for ioctl data. */ @@ -2158,45 +2137,6 @@ static long seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return err; } -static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd, - void __user *arg) -{ - struct seq_ioctl_table *p; - - switch (cmd) { - case SNDRV_SEQ_IOCTL_PVERSION: - /* return sequencer version number */ - return put_user(SNDRV_SEQ_VERSION, (int __user *)arg) ? -EFAULT : 0; - case SNDRV_SEQ_IOCTL_CLIENT_ID: - /* return the id of this client */ - return put_user(client->number, (int __user *)arg) ? -EFAULT : 0; - } - - if (! arg) - return -EFAULT; - for (p = ioctl_tables; p->cmd; p++) { - if (p->cmd == cmd) - return p->func(client, arg); - } - pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", - cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); - return -ENOTTY; -} - - -static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_seq_client *client = file->private_data; - - if (seq_ioctl(file, cmd, arg) >= 0) - return 0; - - if (snd_BUG_ON(!client)) - return -ENXIO; - - return snd_seq_do_ioctl(client, cmd, (void __user *) arg); -} - #ifdef CONFIG_COMPAT #include "seq_compat.c" #else @@ -2396,8 +2336,6 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) { const struct ioctl_handler *handler; struct snd_seq_client *client; - mm_segment_t fs; - int result; client = clientptr(clientid); if (client == NULL) @@ -2408,10 +2346,9 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) return handler->func(client, arg); } - fs = snd_enter_user(); - result = snd_seq_do_ioctl(client, cmd, (void __force __user *)arg); - snd_leave_user(fs); - return result; + pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", + cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); + return -ENOTTY; } EXPORT_SYMBOL(snd_seq_kernel_client_ctl); diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c index 4cfc505..fce5697 100644 --- a/sound/core/seq/seq_compat.c +++ b/sound/core/seq/seq_compat.c @@ -47,7 +47,6 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned { int err = -EFAULT; struct snd_seq_port_info *data; - mm_segment_t fs; data = kmalloc(sizeof(*data), GFP_KERNEL); if (!data) @@ -59,12 +58,7 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned goto error; data->kernel = NULL; - if (snd_seq_kernel_client_ctl(client->number, cmd, &data) >= 0) - return 0; - - fs = snd_enter_user(); - err = snd_seq_do_ioctl(client, cmd, data); - snd_leave_user(fs); + err = snd_seq_kernel_client_ctl(client->number, cmd, &data); if (err < 0) goto error; @@ -126,9 +120,7 @@ static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned l case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION: case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT: case SNDRV_SEQ_IOCTL_RUNNING_MODE: - if (seq_ioctl(file, cmd, arg) >= 0) - return 0; - return snd_seq_do_ioctl(client, cmd, argp); + return snd_seq_ioctl(file, cmd, arg); case SNDRV_SEQ_IOCTL_CREATE_PORT32: return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp); case SNDRV_SEQ_IOCTL_DELETE_PORT32: -- cgit v0.10.2 From 9abc134167249ded16a8c776813121609610f119 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 22 Aug 2016 08:53:36 +0200 Subject: ALSA: usb: move udh01_fb_quirk setting to quirks.c That's a quirk, after all, so move it where to all the other quirks live. Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index c07a7ed..4b4ffa0 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -502,10 +502,6 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, ep->syncinterval = 3; ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize); - - if (chip->usb_id == USB_ID(0x0644, 0x8038) /* TEAC UD-H01 */ && - ep->syncmaxsize == 4) - ep->udh01_fb_quirk = 1; } list_add_tail(&ep->list, &chip->ep_list); diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 6cf1f35..299813f 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1216,6 +1216,11 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) ep->chip->usb_id == USB_ID(0x0763, 0x2031)) && ep->type == SND_USB_ENDPOINT_TYPE_DATA) ep->skip_packets = 16; + + /* Work around devices that report unreasonable feedback data */ + if (ep->chip->usb_id == USB_ID(0x0644, 0x8038) /* TEAC UD-H01 */ && + ep->syncmaxsize == 4) + ep->udh01_fb_quirk = 1; } void snd_usb_set_interface_quirk(struct usb_device *dev) -- cgit v0.10.2 From ca0dd2736a05d1df94c8657b4865f9d6c6637085 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 22 Aug 2016 08:53:37 +0200 Subject: ALSA: usb: use TEAC UD-H01 quirk for more devices The quirk seems to be necessary not only for TEAC UD-H01 devices, but to more that are based on the Tenor 8802TL chipset. Devices built by T+A are affected too, and they apparently all use the same USB PID:PID. Extend the quirky handling for that device as well, and rename the quirks flag. Reported-and-tested-by: Thomas Gresens Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai diff --git a/sound/usb/card.h b/sound/usb/card.h index 71778ca..111b0f0 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -92,7 +92,7 @@ struct snd_usb_endpoint { unsigned int curframesize; /* current packet size in frames (for capture) */ unsigned int syncmaxsize; /* sync endpoint packet size */ unsigned int fill_max:1; /* fill max packet size always */ - unsigned int udh01_fb_quirk:1; /* corrupted feedback data */ + unsigned int tenor_fb_quirk:1; /* corrupted feedback data */ unsigned int datainterval; /* log_2 of data packet interval */ unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ unsigned char silence_value; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 4b4ffa0..c317a8d 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -1167,9 +1167,10 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, if (f == 0) return; - if (unlikely(sender->udh01_fb_quirk)) { + if (unlikely(sender->tenor_fb_quirk)) { /* - * The TEAC UD-H01 firmware sometimes changes the feedback value + * Devices based on Tenor 8802 chipsets (TEAC UD-H01 + * and others) sometimes change the feedback value * by +/- 0x1.0000. */ if (f < ep->freqn - 0x8000) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 299813f..d47d927 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1218,9 +1218,10 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) ep->skip_packets = 16; /* Work around devices that report unreasonable feedback data */ - if (ep->chip->usb_id == USB_ID(0x0644, 0x8038) /* TEAC UD-H01 */ && + if ((ep->chip->usb_id == USB_ID(0x0644, 0x8038) || /* TEAC UD-H01 */ + ep->chip->usb_id == USB_ID(0x1852, 0x5034)) && /* T+A Dac8 */ ep->syncmaxsize == 4) - ep->udh01_fb_quirk = 1; + ep->tenor_fb_quirk = 1; } void snd_usb_set_interface_quirk(struct usb_device *dev) -- cgit v0.10.2 From 36e1ac3cf880fb9dbb528c41ebde567ca17d4a84 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 22 Aug 2016 08:53:38 +0200 Subject: ALSA: usb: fine-tune Tenor error compensation value Users of devices affected by the Tenor feedback data error report buffer underruns, even with the +/- 0x1.0000 quirk applied. Compensating the error with 0xf000 instead seems to reliably fix that issue. See https://sourceforge.net/p/alsa/mailman/message/35230259/ Reported-and-tested-by: Norman Nolte Reported-and-tested-by: Thomas Gresens Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index c317a8d..c470251 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -1174,9 +1174,9 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, * by +/- 0x1.0000. */ if (f < ep->freqn - 0x8000) - f += 0x10000; + f += 0xf000; else if (f > ep->freqn + 0x8000) - f -= 0x10000; + f -= 0xf000; } else if (unlikely(ep->freqshift == INT_MIN)) { /* * The first time we see a feedback value, determine its format -- cgit v0.10.2 From 1bc00f32b87c24f1a981e6dcf3f2174babee93ad Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Sun, 21 Aug 2016 10:17:36 +0800 Subject: ALSA: usb-audio: rmove print for failure of kmalloc kmalloc already print similar error once failing to alloc enough memory, so let's remove this dump here. Signed-off-by: Shawn Lin Signed-off-by: Takashi Iwai diff --git a/sound/usb/format.c b/sound/usb/format.c index 789d19e..2c44386 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -176,10 +176,8 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof int r, idx; fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL); - if (fp->rate_table == NULL) { - usb_audio_err(chip, "cannot malloc\n"); + if (fp->rate_table == NULL) return -ENOMEM; - } fp->nr_rates = 0; fp->rate_min = fp->rate_max = 0; -- cgit v0.10.2 From c2f14ba749c1ce94aa97c5a84733a89aaaadada4 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 21 Aug 2016 21:02:06 +0200 Subject: ALSA: compress: Use memdup_user() rather than duplicating its implementation Reuse existing functionality from memdup_user() instead of keeping duplicate source code. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Vinod Koul Signed-off-by: Takashi Iwai diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 2c49848..583d407 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -553,13 +553,9 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) * we should allow parameter change only when stream has been * opened not in other cases */ - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - if (copy_from_user(params, (void __user *)arg, sizeof(*params))) { - retval = -EFAULT; - goto out; - } + params = memdup_user((void __user *)arg, sizeof(*params)); + if (IS_ERR(params)) + return PTR_ERR(params); retval = snd_compress_check_input(params); if (retval) -- cgit v0.10.2 From 07cb3272af7935babe8b421f4070a6e3f26ef59b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 22 Aug 2016 12:50:02 +0100 Subject: ALSA: hdspm: fix spelling mistake "Externel" -> "External" Trivial fix to spelling mistake in dev_warn message. Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index a4a999a..0e51a00 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1666,7 +1666,7 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) HDSPM_AUTOSYNC_FROM_NONE) { dev_warn(hdspm->card->dev, - "Detected no Externel Sync\n"); + "Detected no External Sync\n"); not_set = 1; } else if (rate != external_freq) { -- cgit v0.10.2 From b6970b48e384a602bdb9d6246cded83e150d4660 Mon Sep 17 00:00:00 2001 From: John Hsu Date: Fri, 19 Aug 2016 17:24:52 +0800 Subject: ASoC: nau8810: Add driver for Nuvoton codec chip NAU88C10 The driver is for codec NAU88C10 of Nuvoton Technology Corporation. Signed-off-by: John Hsu Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/nau8810.txt b/Documentation/devicetree/bindings/sound/nau8810.txt new file mode 100644 index 0000000..05830e4 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nau8810.txt @@ -0,0 +1,16 @@ +NAU8810 audio CODEC + +This device supports I2C only. + +Required properties: + + - compatible : "nuvoton,nau8810" + + - reg : the I2C address of the device. + +Example: + +codec: nau8810@1a { + compatible = "nuvoton,nau8810"; + reg = <0x1a>; +}; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1cd6ab3..b3fd110 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -92,6 +92,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_MAX9877 if I2C select SND_SOC_MC13783 if MFD_MC13XXX select SND_SOC_ML26124 if I2C + select SND_SOC_NAU8810 if I2C select SND_SOC_NAU8825 if I2C select SND_SOC_HDMI_CODEC select SND_SOC_PCM1681 if I2C @@ -1064,6 +1065,10 @@ config SND_SOC_MC13783 config SND_SOC_ML26124 tristate +config SND_SOC_NAU8810 + tristate "Nuvoton Technology Corporation NAU88C10 CODEC" + depends on I2C + config SND_SOC_NAU8825 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 58036af..ffaa523 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -86,6 +86,7 @@ snd-soc-max9850-objs := max9850.o snd-soc-max9860-objs := max9860.o snd-soc-mc13783-objs := mc13783.o snd-soc-ml26124-objs := ml26124.o +snd-soc-nau8810-objs := nau8810.o snd-soc-nau8825-objs := nau8825.o snd-soc-hdmi-codec-objs := hdmi-codec.o snd-soc-pcm1681-objs := pcm1681.o @@ -307,6 +308,7 @@ obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o +obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c new file mode 100644 index 0000000..7617dda --- /dev/null +++ b/sound/soc/codecs/nau8810.c @@ -0,0 +1,884 @@ +/* + * nau8810.c -- NAU8810 ALSA Soc Audio driver + * + * Copyright 2016 Nuvoton Technology Corp. + * + * Author: David Lin + * + * Based on WM8974.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nau8810.h" + +#define NAU_PLL_FREQ_MAX 100000000 +#define NAU_PLL_FREQ_MIN 90000000 +#define NAU_PLL_REF_MAX 33000000 +#define NAU_PLL_REF_MIN 8000000 +#define NAU_PLL_OPTOP_MIN 6 + + +static const int nau8810_mclk_scaler[] = { 10, 15, 20, 30, 40, 60, 80, 120 }; + +static const struct reg_default nau8810_reg_defaults[] = { + { NAU8810_REG_POWER1, 0x0000 }, + { NAU8810_REG_POWER2, 0x0000 }, + { NAU8810_REG_POWER3, 0x0000 }, + { NAU8810_REG_IFACE, 0x0050 }, + { NAU8810_REG_COMP, 0x0000 }, + { NAU8810_REG_CLOCK, 0x0140 }, + { NAU8810_REG_SMPLR, 0x0000 }, + { NAU8810_REG_DAC, 0x0000 }, + { NAU8810_REG_DACGAIN, 0x00FF }, + { NAU8810_REG_ADC, 0x0100 }, + { NAU8810_REG_ADCGAIN, 0x00FF }, + { NAU8810_REG_EQ1, 0x012C }, + { NAU8810_REG_EQ2, 0x002C }, + { NAU8810_REG_EQ3, 0x002C }, + { NAU8810_REG_EQ4, 0x002C }, + { NAU8810_REG_EQ5, 0x002C }, + { NAU8810_REG_DACLIM1, 0x0032 }, + { NAU8810_REG_DACLIM2, 0x0000 }, + { NAU8810_REG_NOTCH1, 0x0000 }, + { NAU8810_REG_NOTCH2, 0x0000 }, + { NAU8810_REG_NOTCH3, 0x0000 }, + { NAU8810_REG_NOTCH4, 0x0000 }, + { NAU8810_REG_ALC1, 0x0038 }, + { NAU8810_REG_ALC2, 0x000B }, + { NAU8810_REG_ALC3, 0x0032 }, + { NAU8810_REG_NOISEGATE, 0x0000 }, + { NAU8810_REG_PLLN, 0x0008 }, + { NAU8810_REG_PLLK1, 0x000C }, + { NAU8810_REG_PLLK2, 0x0093 }, + { NAU8810_REG_PLLK3, 0x00E9 }, + { NAU8810_REG_ATTEN, 0x0000 }, + { NAU8810_REG_INPUT_SIGNAL, 0x0003 }, + { NAU8810_REG_PGAGAIN, 0x0010 }, + { NAU8810_REG_ADCBOOST, 0x0100 }, + { NAU8810_REG_OUTPUT, 0x0002 }, + { NAU8810_REG_SPKMIX, 0x0001 }, + { NAU8810_REG_SPKGAIN, 0x0039 }, + { NAU8810_REG_MONOMIX, 0x0001 }, + { NAU8810_REG_POWER4, 0x0000 }, + { NAU8810_REG_TSLOTCTL1, 0x0000 }, + { NAU8810_REG_TSLOTCTL2, 0x0020 }, + { NAU8810_REG_DEVICE_REVID, 0x0000 }, + { NAU8810_REG_I2C_DEVICEID, 0x001A }, + { NAU8810_REG_ADDITIONID, 0x00CA }, + { NAU8810_REG_RESERVE, 0x0124 }, + { NAU8810_REG_OUTCTL, 0x0001 }, + { NAU8810_REG_ALC1ENHAN1, 0x0010 }, + { NAU8810_REG_ALC1ENHAN2, 0x0000 }, + { NAU8810_REG_MISCCTL, 0x0000 }, + { NAU8810_REG_OUTTIEOFF, 0x0000 }, + { NAU8810_REG_AGCP2POUT, 0x0000 }, + { NAU8810_REG_AGCPOUT, 0x0000 }, + { NAU8810_REG_AMTCTL, 0x0000 }, + { NAU8810_REG_OUTTIEOFFMAN, 0x0000 }, +}; + +static bool nau8810_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case NAU8810_REG_RESET ... NAU8810_REG_SMPLR: + case NAU8810_REG_DAC ... NAU8810_REG_DACGAIN: + case NAU8810_REG_ADC ... NAU8810_REG_ADCGAIN: + case NAU8810_REG_EQ1 ... NAU8810_REG_EQ5: + case NAU8810_REG_DACLIM1 ... NAU8810_REG_DACLIM2: + case NAU8810_REG_NOTCH1 ... NAU8810_REG_NOTCH4: + case NAU8810_REG_ALC1 ... NAU8810_REG_ATTEN: + case NAU8810_REG_INPUT_SIGNAL ... NAU8810_REG_PGAGAIN: + case NAU8810_REG_ADCBOOST: + case NAU8810_REG_OUTPUT ... NAU8810_REG_SPKMIX: + case NAU8810_REG_SPKGAIN: + case NAU8810_REG_MONOMIX: + case NAU8810_REG_POWER4 ... NAU8810_REG_TSLOTCTL2: + case NAU8810_REG_DEVICE_REVID ... NAU8810_REG_RESERVE: + case NAU8810_REG_OUTCTL ... NAU8810_REG_ALC1ENHAN2: + case NAU8810_REG_MISCCTL: + case NAU8810_REG_OUTTIEOFF ... NAU8810_REG_OUTTIEOFFMAN: + return true; + default: + return false; + } +} + +static bool nau8810_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case NAU8810_REG_RESET ... NAU8810_REG_SMPLR: + case NAU8810_REG_DAC ... NAU8810_REG_DACGAIN: + case NAU8810_REG_ADC ... NAU8810_REG_ADCGAIN: + case NAU8810_REG_EQ1 ... NAU8810_REG_EQ5: + case NAU8810_REG_DACLIM1 ... NAU8810_REG_DACLIM2: + case NAU8810_REG_NOTCH1 ... NAU8810_REG_NOTCH4: + case NAU8810_REG_ALC1 ... NAU8810_REG_ATTEN: + case NAU8810_REG_INPUT_SIGNAL ... NAU8810_REG_PGAGAIN: + case NAU8810_REG_ADCBOOST: + case NAU8810_REG_OUTPUT ... NAU8810_REG_SPKMIX: + case NAU8810_REG_SPKGAIN: + case NAU8810_REG_MONOMIX: + case NAU8810_REG_POWER4 ... NAU8810_REG_TSLOTCTL2: + case NAU8810_REG_OUTCTL ... NAU8810_REG_ALC1ENHAN2: + case NAU8810_REG_MISCCTL: + case NAU8810_REG_OUTTIEOFF ... NAU8810_REG_OUTTIEOFFMAN: + return true; + default: + return false; + } +} + +static bool nau8810_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case NAU8810_REG_RESET: + case NAU8810_REG_DEVICE_REVID ... NAU8810_REG_RESERVE: + return true; + default: + return false; + } +} + +/* The EQ parameters get function is to get the 5 band equalizer control. + * The regmap raw read can't work here because regmap doesn't provide + * value format for value width of 9 bits. Therefore, the driver reads data + * from cache and makes value format according to the endianness of + * bytes type control element. + */ +static int nau8810_eq_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + struct soc_bytes_ext *params = (void *)kcontrol->private_value; + int i, reg, reg_val; + u16 *val; + + val = (u16 *)ucontrol->value.bytes.data; + reg = NAU8810_REG_EQ1; + for (i = 0; i < params->max / sizeof(u16); i++) { + regmap_read(nau8810->regmap, reg + i, ®_val); + /* conversion of 16-bit integers between native CPU format + * and big endian format + */ + reg_val = cpu_to_be16(reg_val); + memcpy(val + i, ®_val, sizeof(reg_val)); + } + + return 0; +} + +/* The EQ parameters put function is to make configuration of 5 band equalizer + * control. These configuration includes central frequency, equalizer gain, + * cut-off frequency, bandwidth control, and equalizer path. + * The regmap raw write can't work here because regmap doesn't provide + * register and value format for register with address 7 bits and value 9 bits. + * Therefore, the driver makes value format according to the endianness of + * bytes type control element and writes data to codec. + */ +static int nau8810_eq_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + struct soc_bytes_ext *params = (void *)kcontrol->private_value; + void *data; + u16 *val, value; + int i, reg, ret; + + data = kmemdup(ucontrol->value.bytes.data, + params->max, GFP_KERNEL | GFP_DMA); + if (!data) + return -ENOMEM; + + val = (u16 *)data; + reg = NAU8810_REG_EQ1; + for (i = 0; i < params->max / sizeof(u16); i++) { + /* conversion of 16-bit integers between native CPU format + * and big endian format + */ + value = be16_to_cpu(*(val + i)); + ret = regmap_write(nau8810->regmap, reg + i, value); + if (ret) { + dev_err(codec->dev, "EQ configuration fail, register: %x ret: %d\n", + reg + i, ret); + return ret; + } + } + kfree(data); + + return 0; +} + +static const char * const nau8810_companding[] = { + "Off", "NC", "u-law", "A-law" }; + +static const struct soc_enum nau8810_companding_adc_enum = + SOC_ENUM_SINGLE(NAU8810_REG_COMP, NAU8810_ADCCM_SFT, + ARRAY_SIZE(nau8810_companding), nau8810_companding); + +static const struct soc_enum nau8810_companding_dac_enum = + SOC_ENUM_SINGLE(NAU8810_REG_COMP, NAU8810_DACCM_SFT, + ARRAY_SIZE(nau8810_companding), nau8810_companding); + +static const char * const nau8810_deemp[] = { + "None", "32kHz", "44.1kHz", "48kHz" }; + +static const struct soc_enum nau8810_deemp_enum = + SOC_ENUM_SINGLE(NAU8810_REG_DAC, NAU8810_DEEMP_SFT, + ARRAY_SIZE(nau8810_deemp), nau8810_deemp); + +static const char * const nau8810_eqmode[] = {"Capture", "Playback" }; + +static const struct soc_enum nau8810_eqmode_enum = + SOC_ENUM_SINGLE(NAU8810_REG_EQ1, NAU8810_EQM_SFT, + ARRAY_SIZE(nau8810_eqmode), nau8810_eqmode); + +static const char * const nau8810_alc[] = {"Normal", "Limiter" }; + +static const struct soc_enum nau8810_alc_enum = + SOC_ENUM_SINGLE(NAU8810_REG_ALC3, NAU8810_ALCM_SFT, + ARRAY_SIZE(nau8810_alc), nau8810_alc); + +static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); +static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); +static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0); +static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0); + +static const struct snd_kcontrol_new nau8810_snd_controls[] = { + SOC_ENUM("ADC Companding", nau8810_companding_adc_enum), + SOC_ENUM("DAC Companding", nau8810_companding_dac_enum), + SOC_ENUM("DAC De-emphasis", nau8810_deemp_enum), + + SOC_ENUM("EQ Function", nau8810_eqmode_enum), + SND_SOC_BYTES_EXT("EQ Parameters", 10, + nau8810_eq_get, nau8810_eq_put), + + SOC_SINGLE("DAC Inversion Switch", NAU8810_REG_DAC, + NAU8810_DACPL_SFT, 1, 0), + SOC_SINGLE_TLV("Playback Volume", NAU8810_REG_DACGAIN, + NAU8810_DACGAIN_SFT, 0xff, 0, digital_tlv), + + SOC_SINGLE("High Pass Filter Switch", NAU8810_REG_ADC, + NAU8810_HPFEN_SFT, 1, 0), + SOC_SINGLE("High Pass Cut Off", NAU8810_REG_ADC, + NAU8810_HPF_SFT, 0x7, 0), + + SOC_SINGLE("ADC Inversion Switch", NAU8810_REG_ADC, + NAU8810_ADCPL_SFT, 1, 0), + SOC_SINGLE_TLV("Capture Volume", NAU8810_REG_ADCGAIN, + NAU8810_ADCGAIN_SFT, 0xff, 0, digital_tlv), + + SOC_SINGLE_TLV("EQ1 Volume", NAU8810_REG_EQ1, + NAU8810_EQ1GC_SFT, 0x18, 1, eq_tlv), + SOC_SINGLE_TLV("EQ2 Volume", NAU8810_REG_EQ2, + NAU8810_EQ2GC_SFT, 0x18, 1, eq_tlv), + SOC_SINGLE_TLV("EQ3 Volume", NAU8810_REG_EQ3, + NAU8810_EQ3GC_SFT, 0x18, 1, eq_tlv), + SOC_SINGLE_TLV("EQ4 Volume", NAU8810_REG_EQ4, + NAU8810_EQ4GC_SFT, 0x18, 1, eq_tlv), + SOC_SINGLE_TLV("EQ5 Volume", NAU8810_REG_EQ5, + NAU8810_EQ5GC_SFT, 0x18, 1, eq_tlv), + + SOC_SINGLE("DAC Limiter Switch", NAU8810_REG_DACLIM1, + NAU8810_DACLIMEN_SFT, 1, 0), + SOC_SINGLE("DAC Limiter Decay", NAU8810_REG_DACLIM1, + NAU8810_DACLIMDCY_SFT, 0xf, 0), + SOC_SINGLE("DAC Limiter Attack", NAU8810_REG_DACLIM1, + NAU8810_DACLIMATK_SFT, 0xf, 0), + SOC_SINGLE("DAC Limiter Threshold", NAU8810_REG_DACLIM2, + NAU8810_DACLIMTHL_SFT, 0x7, 0), + SOC_SINGLE("DAC Limiter Boost", NAU8810_REG_DACLIM2, + NAU8810_DACLIMBST_SFT, 0xf, 0), + + SOC_ENUM("ALC Mode", nau8810_alc_enum), + SOC_SINGLE("ALC Enable Switch", NAU8810_REG_ALC1, + NAU8810_ALCEN_SFT, 1, 0), + SOC_SINGLE("ALC Max Volume", NAU8810_REG_ALC1, + NAU8810_ALCMXGAIN_SFT, 0x7, 0), + SOC_SINGLE("ALC Min Volume", NAU8810_REG_ALC1, + NAU8810_ALCMINGAIN_SFT, 0x7, 0), + SOC_SINGLE("ALC ZC Switch", NAU8810_REG_ALC2, + NAU8810_ALCZC_SFT, 1, 0), + SOC_SINGLE("ALC Hold", NAU8810_REG_ALC2, + NAU8810_ALCHT_SFT, 0xf, 0), + SOC_SINGLE("ALC Target", NAU8810_REG_ALC2, + NAU8810_ALCSL_SFT, 0xf, 0), + SOC_SINGLE("ALC Decay", NAU8810_REG_ALC3, + NAU8810_ALCDCY_SFT, 0xf, 0), + SOC_SINGLE("ALC Attack", NAU8810_REG_ALC3, + NAU8810_ALCATK_SFT, 0xf, 0), + SOC_SINGLE("ALC Noise Gate Switch", NAU8810_REG_NOISEGATE, + NAU8810_ALCNEN_SFT, 1, 0), + SOC_SINGLE("ALC Noise Gate Threshold", NAU8810_REG_NOISEGATE, + NAU8810_ALCNTH_SFT, 0x7, 0), + + SOC_SINGLE("PGA ZC Switch", NAU8810_REG_PGAGAIN, + NAU8810_PGAZC_SFT, 1, 0), + SOC_SINGLE_TLV("PGA Volume", NAU8810_REG_PGAGAIN, + NAU8810_PGAGAIN_SFT, 0x3f, 0, inpga_tlv), + + SOC_SINGLE("Speaker ZC Switch", NAU8810_REG_SPKGAIN, + NAU8810_SPKZC_SFT, 1, 0), + SOC_SINGLE("Speaker Mute Switch", NAU8810_REG_SPKGAIN, + NAU8810_SPKMT_SFT, 1, 0), + SOC_SINGLE_TLV("Speaker Volume", NAU8810_REG_SPKGAIN, + NAU8810_SPKGAIN_SFT, 0x3f, 0, spk_tlv), + + SOC_SINGLE("Capture Boost(+20dB)", NAU8810_REG_ADCBOOST, + NAU8810_PGABST_SFT, 1, 0), + SOC_SINGLE("Mono Mute Switch", NAU8810_REG_MONOMIX, + NAU8810_MOUTMXMT_SFT, 1, 0), + + SOC_SINGLE("DAC Oversampling Rate(128x) Switch", NAU8810_REG_DAC, + NAU8810_DACOS_SFT, 1, 0), + SOC_SINGLE("ADC Oversampling Rate(128x) Switch", NAU8810_REG_ADC, + NAU8810_ADCOS_SFT, 1, 0), +}; + +/* Speaker Output Mixer */ +static const struct snd_kcontrol_new nau8810_speaker_mixer_controls[] = { + SOC_DAPM_SINGLE("Line Bypass Switch", NAU8810_REG_SPKMIX, + NAU8810_BYPSPK_SFT, 1, 0), + SOC_DAPM_SINGLE("PCM Playback Switch", NAU8810_REG_SPKMIX, + NAU8810_DACSPK_SFT, 1, 0), +}; + +/* Mono Output Mixer */ +static const struct snd_kcontrol_new nau8810_mono_mixer_controls[] = { + SOC_DAPM_SINGLE("Line Bypass Switch", NAU8810_REG_MONOMIX, + NAU8810_BYPMOUT_SFT, 1, 0), + SOC_DAPM_SINGLE("PCM Playback Switch", NAU8810_REG_MONOMIX, + NAU8810_DACMOUT_SFT, 1, 0), +}; + +/* PGA Mute */ +static const struct snd_kcontrol_new nau8810_inpga_mute[] = { + SOC_DAPM_SINGLE("PGA Mute Switch", NAU8810_REG_PGAGAIN, + NAU8810_PGAMT_SFT, 1, 0), +}; + +/* Input PGA */ +static const struct snd_kcontrol_new nau8810_inpga[] = { + SOC_DAPM_SINGLE("MicN Switch", NAU8810_REG_INPUT_SIGNAL, + NAU8810_NMICPGA_SFT, 1, 0), + SOC_DAPM_SINGLE("MicP Switch", NAU8810_REG_INPUT_SIGNAL, + NAU8810_PMICPGA_SFT, 1, 0), +}; + +/* Mic Input boost vol */ +static const struct snd_kcontrol_new nau8810_mic_boost_controls = + SOC_DAPM_SINGLE("Mic Volume", NAU8810_REG_ADCBOOST, + NAU8810_PMICBSTGAIN_SFT, 0x7, 0); + +/* Loopback Switch */ +static const struct snd_kcontrol_new nau8810_loopback[] = { + SOC_DAPM_SINGLE("Switch", NAU8810_REG_COMP, + NAU8810_ADDAP_SFT, 1, 0), +}; + +static int check_mclk_select_pll(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + unsigned int value; + + regmap_read(nau8810->regmap, NAU8810_REG_CLOCK, &value); + return (value & NAU8810_CLKM_MASK); +} + +static const struct snd_soc_dapm_widget nau8810_dapm_widgets[] = { + SND_SOC_DAPM_MIXER("Speaker Mixer", NAU8810_REG_POWER3, + NAU8810_SPKMX_EN_SFT, 0, &nau8810_speaker_mixer_controls[0], + ARRAY_SIZE(nau8810_speaker_mixer_controls)), + SND_SOC_DAPM_MIXER("Mono Mixer", NAU8810_REG_POWER3, + NAU8810_MOUTMX_EN_SFT, 0, &nau8810_mono_mixer_controls[0], + ARRAY_SIZE(nau8810_mono_mixer_controls)), + SND_SOC_DAPM_DAC("DAC", "HiFi Playback", NAU8810_REG_POWER3, + NAU8810_DAC_EN_SFT, 0), + SND_SOC_DAPM_ADC("ADC", "HiFi Capture", NAU8810_REG_POWER2, + NAU8810_ADC_EN_SFT, 0), + SND_SOC_DAPM_PGA("SpkN Out", NAU8810_REG_POWER3, + NAU8810_NSPK_EN_SFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("SpkP Out", NAU8810_REG_POWER3, + NAU8810_PSPK_EN_SFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("Mono Out", NAU8810_REG_POWER3, + NAU8810_MOUT_EN_SFT, 0, NULL, 0), + + SND_SOC_DAPM_MIXER("Input PGA", NAU8810_REG_POWER2, + NAU8810_PGA_EN_SFT, 0, nau8810_inpga, + ARRAY_SIZE(nau8810_inpga)), + SND_SOC_DAPM_MIXER("Input Boost Stage", NAU8810_REG_POWER2, + NAU8810_BST_EN_SFT, 0, nau8810_inpga_mute, + ARRAY_SIZE(nau8810_inpga_mute)), + + SND_SOC_DAPM_SUPPLY("Mic Bias", NAU8810_REG_POWER1, + NAU8810_MICBIAS_EN_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL", NAU8810_REG_POWER1, + NAU8810_PLL_EN_SFT, 0, NULL, 0), + + SND_SOC_DAPM_SWITCH("Digital Loopback", SND_SOC_NOPM, 0, 0, + &nau8810_loopback), + + SND_SOC_DAPM_INPUT("MICN"), + SND_SOC_DAPM_INPUT("MICP"), + SND_SOC_DAPM_OUTPUT("MONOOUT"), + SND_SOC_DAPM_OUTPUT("SPKOUTP"), + SND_SOC_DAPM_OUTPUT("SPKOUTN"), +}; + +static const struct snd_soc_dapm_route nau8810_dapm_routes[] = { + {"DAC", NULL, "PLL", check_mclk_select_pll}, + + /* Mono output mixer */ + {"Mono Mixer", "PCM Playback Switch", "DAC"}, + {"Mono Mixer", "Line Bypass Switch", "Input Boost Stage"}, + + /* Speaker output mixer */ + {"Speaker Mixer", "PCM Playback Switch", "DAC"}, + {"Speaker Mixer", "Line Bypass Switch", "Input Boost Stage"}, + + /* Outputs */ + {"Mono Out", NULL, "Mono Mixer"}, + {"MONOOUT", NULL, "Mono Out"}, + {"SpkN Out", NULL, "Speaker Mixer"}, + {"SpkP Out", NULL, "Speaker Mixer"}, + {"SPKOUTN", NULL, "SpkN Out"}, + {"SPKOUTP", NULL, "SpkP Out"}, + + /* Input Boost Stage */ + {"ADC", NULL, "Input Boost Stage"}, + {"ADC", NULL, "PLL", check_mclk_select_pll}, + {"Input Boost Stage", NULL, "Input PGA"}, + {"Input Boost Stage", NULL, "MICP"}, + + /* Input PGA */ + {"Input PGA", NULL, "Mic Bias"}, + {"Input PGA", "MicN Switch", "MICN"}, + {"Input PGA", "MicP Switch", "MICP"}, + + /* Digital Looptack */ + {"Digital Loopback", "Switch", "ADC"}, + {"DAC", NULL, "Digital Loopback"}, +}; + +static int nau8810_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + + nau8810->clk_id = clk_id; + nau8810->sysclk = freq; + dev_dbg(nau8810->dev, "master sysclk %dHz, source %s\n", + freq, clk_id == NAU8810_SCLK_PLL ? "PLL" : "MCLK"); + + return 0; +} + +static int nau88l0_calc_pll(unsigned int pll_in, + unsigned int fs, struct nau8810_pll *pll_param) +{ + u64 f2, f2_max, pll_ratio; + int i, scal_sel; + + if (pll_in > NAU_PLL_REF_MAX || pll_in < NAU_PLL_REF_MIN) + return -EINVAL; + + f2_max = 0; + scal_sel = ARRAY_SIZE(nau8810_mclk_scaler); + for (i = 0; i < ARRAY_SIZE(nau8810_mclk_scaler); i++) { + f2 = 256 * fs * 4 * nau8810_mclk_scaler[i] / 10; + if (f2 > NAU_PLL_FREQ_MIN && f2 < NAU_PLL_FREQ_MAX && + f2_max < f2) { + f2_max = f2; + scal_sel = i; + } + } + if (ARRAY_SIZE(nau8810_mclk_scaler) == scal_sel) + return -EINVAL; + pll_param->mclk_scaler = scal_sel; + f2 = f2_max; + + /* Calculate the PLL 4-bit integer input and the PLL 24-bit fractional + * input; round up the 24+4bit. + */ + pll_ratio = div_u64(f2 << 28, pll_in); + pll_param->pre_factor = 0; + if (((pll_ratio >> 28) & 0xF) < NAU_PLL_OPTOP_MIN) { + pll_ratio <<= 1; + pll_param->pre_factor = 1; + } + pll_param->pll_int = (pll_ratio >> 28) & 0xF; + pll_param->pll_frac = ((pll_ratio & 0xFFFFFFF) >> 4); + + return 0; +} + +static int nau8810_set_pll(struct snd_soc_dai *codec_dai, int pll_id, + int source, unsigned int freq_in, unsigned int freq_out) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + struct regmap *map = nau8810->regmap; + struct nau8810_pll *pll_param = &nau8810->pll; + int ret, fs; + + fs = freq_out / 256; + ret = nau88l0_calc_pll(freq_in, fs, pll_param); + if (ret < 0) { + dev_err(nau8810->dev, "Unsupported input clock %d\n", freq_in); + return ret; + } + dev_info(nau8810->dev, "pll_int=%x pll_frac=%x mclk_scaler=%x pre_factor=%x\n", + pll_param->pll_int, pll_param->pll_frac, pll_param->mclk_scaler, + pll_param->pre_factor); + + regmap_update_bits(map, NAU8810_REG_PLLN, + NAU8810_PLLMCLK_DIV2 | NAU8810_PLLN_MASK, + (pll_param->pre_factor ? NAU8810_PLLMCLK_DIV2 : 0) | + pll_param->pll_int); + regmap_write(map, NAU8810_REG_PLLK1, + (pll_param->pll_frac >> NAU8810_PLLK1_SFT) & + NAU8810_PLLK1_MASK); + regmap_write(map, NAU8810_REG_PLLK2, + (pll_param->pll_frac >> NAU8810_PLLK2_SFT) & + NAU8810_PLLK2_MASK); + regmap_write(map, NAU8810_REG_PLLK3, + pll_param->pll_frac & NAU8810_PLLK3_MASK); + regmap_update_bits(map, NAU8810_REG_CLOCK, NAU8810_MCLKSEL_MASK, + pll_param->mclk_scaler << NAU8810_MCLKSEL_SFT); + regmap_update_bits(map, NAU8810_REG_CLOCK, + NAU8810_CLKM_MASK, NAU8810_CLKM_PLL); + + return 0; +} + +static int nau8810_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + u16 ctrl1_val = 0, ctrl2_val = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + ctrl2_val |= NAU8810_CLKIO_MASTER; + break; + case SND_SOC_DAIFMT_CBS_CFS: + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + ctrl1_val |= NAU8810_AIFMT_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + break; + case SND_SOC_DAIFMT_LEFT_J: + ctrl1_val |= NAU8810_AIFMT_LEFT; + break; + case SND_SOC_DAIFMT_DSP_A: + ctrl1_val |= NAU8810_AIFMT_PCM_A; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_IF: + ctrl1_val |= NAU8810_BCLKP_IB | NAU8810_FSP_IF; + break; + case SND_SOC_DAIFMT_IB_NF: + ctrl1_val |= NAU8810_BCLKP_IB; + break; + case SND_SOC_DAIFMT_NB_IF: + ctrl1_val |= NAU8810_FSP_IF; + break; + default: + return -EINVAL; + } + + regmap_update_bits(nau8810->regmap, NAU8810_REG_IFACE, + NAU8810_AIFMT_MASK | NAU8810_FSP_IF | + NAU8810_BCLKP_IB, ctrl1_val); + regmap_update_bits(nau8810->regmap, NAU8810_REG_CLOCK, + NAU8810_CLKIO_MASK, ctrl2_val); + + return 0; +} + +static int nau8810_mclk_clkdiv(struct nau8810 *nau8810, int rate) +{ + int i, sclk, imclk = rate * 256, div = 0; + + if (!nau8810->sysclk) { + dev_err(nau8810->dev, "Make mclk div configuration fail because of invalid system clock\n"); + return -EINVAL; + } + + /* Configure the master clock prescaler div to make system + * clock to approximate the internal master clock (IMCLK); + * and large or equal to IMCLK. + */ + for (i = 1; i < ARRAY_SIZE(nau8810_mclk_scaler); i++) { + sclk = (nau8810->sysclk * 10) / + nau8810_mclk_scaler[i]; + if (sclk < imclk) + break; + div = i; + } + dev_dbg(nau8810->dev, + "master clock prescaler %x for fs %d\n", div, rate); + + /* master clock from MCLK and disable PLL */ + regmap_update_bits(nau8810->regmap, NAU8810_REG_CLOCK, + NAU8810_MCLKSEL_MASK, (div << NAU8810_MCLKSEL_SFT)); + regmap_update_bits(nau8810->regmap, NAU8810_REG_CLOCK, + NAU8810_CLKM_MASK, NAU8810_CLKM_MCLK); + + return 0; +} + +static int nau8810_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + int val_len = 0, val_rate = 0, ret = 0; + + switch (params_width(params)) { + case 16: + break; + case 20: + val_len |= NAU8810_WLEN_20; + break; + case 24: + val_len |= NAU8810_WLEN_24; + break; + case 32: + val_len |= NAU8810_WLEN_32; + break; + } + + switch (params_rate(params)) { + case 8000: + val_rate |= NAU8810_SMPLR_8K; + break; + case 11025: + val_rate |= NAU8810_SMPLR_12K; + break; + case 16000: + val_rate |= NAU8810_SMPLR_16K; + break; + case 22050: + val_rate |= NAU8810_SMPLR_24K; + break; + case 32000: + val_rate |= NAU8810_SMPLR_32K; + break; + case 44100: + case 48000: + break; + } + + regmap_update_bits(nau8810->regmap, NAU8810_REG_IFACE, + NAU8810_WLEN_MASK, val_len); + regmap_update_bits(nau8810->regmap, NAU8810_REG_SMPLR, + NAU8810_SMPLR_MASK, val_rate); + + /* If the master clock is from MCLK, provide the runtime FS for driver + * to get the master clock prescaler configuration. + */ + if (nau8810->clk_id == NAU8810_SCLK_MCLK) { + ret = nau8810_mclk_clkdiv(nau8810, params_rate(params)); + if (ret < 0) + dev_err(nau8810->dev, "MCLK div configuration fail\n"); + } + + return ret; +} + +static int nau8810_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct nau8810 *nau8810 = snd_soc_codec_get_drvdata(codec); + struct regmap *map = nau8810->regmap; + + switch (level) { + case SND_SOC_BIAS_ON: + case SND_SOC_BIAS_PREPARE: + regmap_update_bits(map, NAU8810_REG_POWER1, + NAU8810_REFIMP_MASK, NAU8810_REFIMP_80K); + break; + + case SND_SOC_BIAS_STANDBY: + regmap_update_bits(map, NAU8810_REG_POWER1, + NAU8810_IOBUF_EN | NAU8810_ABIAS_EN, + NAU8810_IOBUF_EN | NAU8810_ABIAS_EN); + + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { + regcache_sync(map); + regmap_update_bits(map, NAU8810_REG_POWER1, + NAU8810_REFIMP_MASK, NAU8810_REFIMP_3K); + mdelay(100); + } + regmap_update_bits(map, NAU8810_REG_POWER1, + NAU8810_REFIMP_MASK, NAU8810_REFIMP_300K); + break; + + case SND_SOC_BIAS_OFF: + regmap_write(map, NAU8810_REG_POWER1, 0); + regmap_write(map, NAU8810_REG_POWER2, 0); + regmap_write(map, NAU8810_REG_POWER3, 0); + break; + } + + return 0; +} + + +#define NAU8810_RATES (SNDRV_PCM_RATE_8000_48000) + +#define NAU8810_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static const struct snd_soc_dai_ops nau8810_ops = { + .hw_params = nau8810_pcm_hw_params, + .set_fmt = nau8810_set_dai_fmt, + .set_sysclk = nau8810_set_sysclk, + .set_pll = nau8810_set_pll, +}; + +static struct snd_soc_dai_driver nau8810_dai = { + .name = "nau8810-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, /* Only 1 channel of data */ + .rates = NAU8810_RATES, + .formats = NAU8810_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, /* Only 1 channel of data */ + .rates = NAU8810_RATES, + .formats = NAU8810_FORMATS, + }, + .ops = &nau8810_ops, + .symmetric_rates = 1, +}; + +static const struct regmap_config nau8810_regmap_config = { + .reg_bits = 7, + .val_bits = 9, + + .max_register = NAU8810_REG_MAX, + .readable_reg = nau8810_readable_reg, + .writeable_reg = nau8810_writeable_reg, + .volatile_reg = nau8810_volatile_reg, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = nau8810_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(nau8810_reg_defaults), +}; + +static struct snd_soc_codec_driver nau8810_codec_driver = { + .set_bias_level = nau8810_set_bias_level, + .suspend_bias_off = true, + + .component_driver = { + .controls = nau8810_snd_controls, + .num_controls = ARRAY_SIZE(nau8810_snd_controls), + .dapm_widgets = nau8810_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(nau8810_dapm_widgets), + .dapm_routes = nau8810_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(nau8810_dapm_routes), + }, +}; + +static int nau8810_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct device *dev = &i2c->dev; + struct nau8810 *nau8810 = dev_get_platdata(dev); + + if (!nau8810) { + nau8810 = devm_kzalloc(dev, sizeof(*nau8810), GFP_KERNEL); + if (!nau8810) + return -ENOMEM; + } + i2c_set_clientdata(i2c, nau8810); + + nau8810->regmap = devm_regmap_init_i2c(i2c, &nau8810_regmap_config); + if (IS_ERR(nau8810->regmap)) + return PTR_ERR(nau8810->regmap); + nau8810->dev = dev; + + regmap_write(nau8810->regmap, NAU8810_REG_RESET, 0x00); + + return snd_soc_register_codec(dev, + &nau8810_codec_driver, &nau8810_dai, 1); +} + +static int nau8810_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + + return 0; +} + +static const struct i2c_device_id nau8810_i2c_id[] = { + { "nau8810", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, nau8810_i2c_id); + +#ifdef CONFIG_OF +static const struct of_device_id nau8810_of_match[] = { + { .compatible = "nuvoton,nau8810", }, + { } +}; +MODULE_DEVICE_TABLE(of, nau8810_of_match); +#endif + +static struct i2c_driver nau8810_i2c_driver = { + .driver = { + .name = "nau8810", + .of_match_table = of_match_ptr(nau8810_of_match), + }, + .probe = nau8810_i2c_probe, + .remove = nau8810_i2c_remove, + .id_table = nau8810_i2c_id, +}; + +module_i2c_driver(nau8810_i2c_driver); + +MODULE_DESCRIPTION("ASoC NAU8810 driver"); +MODULE_AUTHOR("David Lin "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/nau8810.h b/sound/soc/codecs/nau8810.h new file mode 100644 index 0000000..df88265 --- /dev/null +++ b/sound/soc/codecs/nau8810.h @@ -0,0 +1,281 @@ +/* + * NAU8810 ALSA SoC audio driver + * + * Copyright 2016 Nuvoton Technology Corp. + * Author: David Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __NAU8810_H__ +#define __NAU8810_H__ + +#define NAU8810_REG_RESET 0x00 +#define NAU8810_REG_POWER1 0x01 +#define NAU8810_REG_POWER2 0x02 +#define NAU8810_REG_POWER3 0x03 +#define NAU8810_REG_IFACE 0x04 +#define NAU8810_REG_COMP 0x05 +#define NAU8810_REG_CLOCK 0x06 +#define NAU8810_REG_SMPLR 0x07 +#define NAU8810_REG_DAC 0x0A +#define NAU8810_REG_DACGAIN 0x0B +#define NAU8810_REG_ADC 0x0E +#define NAU8810_REG_ADCGAIN 0x0F +#define NAU8810_REG_EQ1 0x12 +#define NAU8810_REG_EQ2 0x13 +#define NAU8810_REG_EQ3 0x14 +#define NAU8810_REG_EQ4 0x15 +#define NAU8810_REG_EQ5 0x16 +#define NAU8810_REG_DACLIM1 0x18 +#define NAU8810_REG_DACLIM2 0x19 +#define NAU8810_REG_NOTCH1 0x1B +#define NAU8810_REG_NOTCH2 0x1C +#define NAU8810_REG_NOTCH3 0x1D +#define NAU8810_REG_NOTCH4 0x1E +#define NAU8810_REG_ALC1 0x20 +#define NAU8810_REG_ALC2 0x21 +#define NAU8810_REG_ALC3 0x22 +#define NAU8810_REG_NOISEGATE 0x23 +#define NAU8810_REG_PLLN 0x24 +#define NAU8810_REG_PLLK1 0x25 +#define NAU8810_REG_PLLK2 0x26 +#define NAU8810_REG_PLLK3 0x27 +#define NAU8810_REG_ATTEN 0x28 +#define NAU8810_REG_INPUT_SIGNAL 0x2C +#define NAU8810_REG_PGAGAIN 0x2D +#define NAU8810_REG_ADCBOOST 0x2F +#define NAU8810_REG_OUTPUT 0x31 +#define NAU8810_REG_SPKMIX 0x32 +#define NAU8810_REG_SPKGAIN 0x36 +#define NAU8810_REG_MONOMIX 0x38 +#define NAU8810_REG_POWER4 0x3A +#define NAU8810_REG_TSLOTCTL1 0x3B +#define NAU8810_REG_TSLOTCTL2 0x3C +#define NAU8810_REG_DEVICE_REVID 0x3E +#define NAU8810_REG_I2C_DEVICEID 0x3F +#define NAU8810_REG_ADDITIONID 0x40 +#define NAU8810_REG_RESERVE 0x41 +#define NAU8810_REG_OUTCTL 0x45 +#define NAU8810_REG_ALC1ENHAN1 0x46 +#define NAU8810_REG_ALC1ENHAN2 0x47 +#define NAU8810_REG_MISCCTL 0x49 +#define NAU8810_REG_OUTTIEOFF 0x4B +#define NAU8810_REG_AGCP2POUT 0x4C +#define NAU8810_REG_AGCPOUT 0x4D +#define NAU8810_REG_AMTCTL 0x4E +#define NAU8810_REG_OUTTIEOFFMAN 0x4F +#define NAU8810_REG_MAX NAU8810_REG_OUTTIEOFFMAN + + +/* NAU8810_REG_POWER1 (0x1) */ +#define NAU8810_DCBUF_EN (0x1 << 8) +#define NAU8810_PLL_EN_SFT 5 +#define NAU8810_MICBIAS_EN_SFT 4 +#define NAU8810_ABIAS_EN (0x1 << 3) +#define NAU8810_IOBUF_EN (0x1 << 2) +#define NAU8810_REFIMP_MASK 0x3 +#define NAU8810_REFIMP_DIS 0x0 +#define NAU8810_REFIMP_80K 0x1 +#define NAU8810_REFIMP_300K 0x2 +#define NAU8810_REFIMP_3K 0x3 + +/* NAU8810_REG_POWER2 (0x2) */ +#define NAU8810_BST_EN_SFT 4 +#define NAU8810_PGA_EN_SFT 2 +#define NAU8810_ADC_EN_SFT 0 + +/* NAU8810_REG_POWER3 (0x3) */ +#define NAU8810_DAC_EN_SFT 0 +#define NAU8810_SPKMX_EN_SFT 2 +#define NAU8810_MOUTMX_EN_SFT 3 +#define NAU8810_PSPK_EN_SFT 5 +#define NAU8810_NSPK_EN_SFT 6 +#define NAU8810_MOUT_EN_SFT 7 + +/* NAU8810_REG_IFACE (0x4) */ +#define NAU8810_AIFMT_SFT 3 +#define NAU8810_AIFMT_MASK (0x3 << NAU8810_AIFMT_SFT) +#define NAU8810_AIFMT_RIGHT (0x0 << NAU8810_AIFMT_SFT) +#define NAU8810_AIFMT_LEFT (0x1 << NAU8810_AIFMT_SFT) +#define NAU8810_AIFMT_I2S (0x2 << NAU8810_AIFMT_SFT) +#define NAU8810_AIFMT_PCM_A (0x3 << NAU8810_AIFMT_SFT) +#define NAU8810_WLEN_SFT 5 +#define NAU8810_WLEN_MASK (0x3 << NAU8810_WLEN_SFT) +#define NAU8810_WLEN_16 (0x0 << NAU8810_WLEN_SFT) +#define NAU8810_WLEN_20 (0x1 << NAU8810_WLEN_SFT) +#define NAU8810_WLEN_24 (0x2 << NAU8810_WLEN_SFT) +#define NAU8810_WLEN_32 (0x3 << NAU8810_WLEN_SFT) +#define NAU8810_FSP_IF (0x1 << 7) +#define NAU8810_BCLKP_IB (0x1 << 8) + +/* NAU8810_REG_COMP (0x5) */ +#define NAU8810_ADDAP_SFT 0 +#define NAU8810_ADCCM_SFT 1 +#define NAU8810_DACCM_SFT 3 + +/* NAU8810_REG_CLOCK (0x6) */ +#define NAU8810_CLKIO_MASK 0x1 +#define NAU8810_CLKIO_SLAVE 0x0 +#define NAU8810_CLKIO_MASTER 0x1 +#define NAU8810_BCLKSEL_SFT 2 +#define NAU8810_BCLKSEL_MASK (0x7 << NAU8810_BCLKSEL_SFT) +#define NAU8810_BCLKDIV_1 (0x0 << NAU8810_BCLKSEL_SFT) +#define NAU8810_BCLKDIV_2 (0x1 << NAU8810_BCLKSEL_SFT) +#define NAU8810_BCLKDIV_4 (0x2 << NAU8810_BCLKSEL_SFT) +#define NAU8810_BCLKDIV_8 (0x3 << NAU8810_BCLKSEL_SFT) +#define NAU8810_BCLKDIV_16 (0x4 << NAU8810_BCLKSEL_SFT) +#define NAU8810_BCLKDIV_32 (0x5 << NAU8810_BCLKSEL_SFT) +#define NAU8810_MCLKSEL_SFT 5 +#define NAU8810_MCLKSEL_MASK (0x7 << NAU8810_MCLKSEL_SFT) +#define NAU8810_CLKM_SFT 8 +#define NAU8810_CLKM_MASK (0x1 << NAU8810_CLKM_SFT) +#define NAU8810_CLKM_MCLK (0x0 << NAU8810_CLKM_SFT) +#define NAU8810_CLKM_PLL (0x1 << NAU8810_CLKM_SFT) + +/* NAU8810_REG_SMPLR (0x7) */ +#define NAU8810_SMPLR_SFT 1 +#define NAU8810_SMPLR_MASK (0x7 << NAU8810_SMPLR_SFT) +#define NAU8810_SMPLR_48K (0x0 << NAU8810_SMPLR_SFT) +#define NAU8810_SMPLR_32K (0x1 << NAU8810_SMPLR_SFT) +#define NAU8810_SMPLR_24K (0x2 << NAU8810_SMPLR_SFT) +#define NAU8810_SMPLR_16K (0x3 << NAU8810_SMPLR_SFT) +#define NAU8810_SMPLR_12K (0x4 << NAU8810_SMPLR_SFT) +#define NAU8810_SMPLR_8K (0x5 << NAU8810_SMPLR_SFT) + +/* NAU8810_REG_DAC (0xA) */ +#define NAU8810_DACPL_SFT 0 +#define NAU8810_DACOS_SFT 3 +#define NAU8810_DEEMP_SFT 4 + +/* NAU8810_REG_DACGAIN (0xB) */ +#define NAU8810_DACGAIN_SFT 0 + +/* NAU8810_REG_ADC (0xE) */ +#define NAU8810_ADCPL_SFT 0 +#define NAU8810_ADCOS_SFT 3 +#define NAU8810_HPF_SFT 4 +#define NAU8810_HPFEN_SFT 8 + +/* NAU8810_REG_ADCGAIN (0xF) */ +#define NAU8810_ADCGAIN_SFT 0 + +/* NAU8810_REG_EQ1 (0x12) */ +#define NAU8810_EQ1GC_SFT 0 +#define NAU8810_EQ1CF_SFT 5 +#define NAU8810_EQM_SFT 8 + +/* NAU8810_REG_EQ2 (0x13) */ +#define NAU8810_EQ2GC_SFT 0 +#define NAU8810_EQ2CF_SFT 5 +#define NAU8810_EQ2BW_SFT 8 + +/* NAU8810_REG_EQ3 (0x14) */ +#define NAU8810_EQ3GC_SFT 0 +#define NAU8810_EQ3CF_SFT 5 +#define NAU8810_EQ3BW_SFT 8 + +/* NAU8810_REG_EQ4 (0x15) */ +#define NAU8810_EQ4GC_SFT 0 +#define NAU8810_EQ4CF_SFT 5 +#define NAU8810_EQ4BW_SFT 8 + +/* NAU8810_REG_EQ5 (0x16) */ +#define NAU8810_EQ5GC_SFT 0 +#define NAU8810_EQ5CF_SFT 5 + +/* NAU8810_REG_DACLIM1 (0x18) */ +#define NAU8810_DACLIMATK_SFT 0 +#define NAU8810_DACLIMDCY_SFT 4 +#define NAU8810_DACLIMEN_SFT 8 + +/* NAU8810_REG_DACLIM2 (0x19) */ +#define NAU8810_DACLIMBST_SFT 0 +#define NAU8810_DACLIMTHL_SFT 4 + +/* NAU8810_REG_ALC1 (0x20) */ +#define NAU8810_ALCMINGAIN_SFT 0 +#define NAU8810_ALCMXGAIN_SFT 3 +#define NAU8810_ALCEN_SFT 8 + +/* NAU8810_REG_ALC2 (0x21) */ +#define NAU8810_ALCSL_SFT 0 +#define NAU8810_ALCHT_SFT 4 +#define NAU8810_ALCZC_SFT 8 + +/* NAU8810_REG_ALC3 (0x22) */ +#define NAU8810_ALCATK_SFT 0 +#define NAU8810_ALCDCY_SFT 4 +#define NAU8810_ALCM_SFT 8 + +/* NAU8810_REG_NOISEGATE (0x23) */ +#define NAU8810_ALCNTH_SFT 0 +#define NAU8810_ALCNEN_SFT 3 + +/* NAU8810_REG_PLLN (0x24) */ +#define NAU8810_PLLN_MASK 0xF +#define NAU8810_PLLMCLK_DIV2 (0x1 << 4) + +/* NAU8810_REG_PLLK1 (0x25) */ +#define NAU8810_PLLK1_SFT 18 +#define NAU8810_PLLK1_MASK 0x3F + +/* NAU8810_REG_PLLK2 (0x26) */ +#define NAU8810_PLLK2_SFT 9 +#define NAU8810_PLLK2_MASK 0x1FF + +/* NAU8810_REG_PLLK3 (0x27) */ +#define NAU8810_PLLK3_MASK 0x1FF + +/* NAU8810_REG_INPUT_SIGNAL (0x2C) */ +#define NAU8810_PMICPGA_SFT 0 +#define NAU8810_NMICPGA_SFT 1 + +/* NAU8810_REG_PGAGAIN (0x2D) */ +#define NAU8810_PGAGAIN_SFT 0 +#define NAU8810_PGAMT_SFT 6 +#define NAU8810_PGAZC_SFT 7 + +/* NAU8810_REG_ADCBOOST (0x2F) */ +#define NAU8810_PMICBSTGAIN_SFT 4 +#define NAU8810_PGABST_SFT 8 + +/* NAU8810_REG_SPKMIX (0x32) */ +#define NAU8810_DACSPK_SFT 0 +#define NAU8810_BYPSPK_SFT 1 + +/* NAU8810_REG_SPKGAIN (0x36) */ +#define NAU8810_SPKGAIN_SFT 0 +#define NAU8810_SPKMT_SFT 6 +#define NAU8810_SPKZC_SFT 7 + +/* NAU8810_REG_MONOMIX (0x38) */ +#define NAU8810_DACMOUT_SFT 0 +#define NAU8810_BYPMOUT_SFT 1 +#define NAU8810_MOUTMXMT_SFT 6 + + +/* System Clock Source */ +enum { + NAU8810_SCLK_MCLK, + NAU8810_SCLK_PLL, +}; + +struct nau8810_pll { + int pre_factor; + int mclk_scaler; + int pll_frac; + int pll_int; +}; + +struct nau8810 { + struct device *dev; + struct regmap *regmap; + struct nau8810_pll pll; + int sysclk; + int clk_id; +}; + +#endif -- cgit v0.10.2 From 15f0d4f531d84015511dbdc2512e5a77c0173d49 Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Fri, 12 Aug 2016 12:29:50 +0530 Subject: ASoC: uapi: Intel: Skylake: Define vendor specific tokens With recent topology changes in alsa-lib, driver data for modules can now be passed in topology conf file using tuples. This patch defines vendor specific tokens to describe private data with tuples. The allowed token types are UUID, string, bool, byte, short and word. These tokens will be referenced by the vendor tuples in the conf file. In the topology conf file, multiple data blocks can be defined for a widget which can be either tuple vendor array or blob. So, each data block will be preceded by a descriptor to identify size and type of block. These descriptors will be token value pairs. Tokens for module_id and loadable flag are not defined as these are read from the DSP FW manifest. Signed-off-by: Shreyas NC Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/include/uapi/sound/Kbuild b/include/uapi/sound/Kbuild index 691984c..9578d8b 100644 --- a/include/uapi/sound/Kbuild +++ b/include/uapi/sound/Kbuild @@ -13,3 +13,4 @@ header-y += sb16_csp.h header-y += sfnt_info.h header-y += tlv.h header-y += usb_stream.h +header-y += snd_sst_tokens.h diff --git a/include/uapi/sound/snd_sst_tokens.h b/include/uapi/sound/snd_sst_tokens.h new file mode 100644 index 0000000..f56a932 --- /dev/null +++ b/include/uapi/sound/snd_sst_tokens.h @@ -0,0 +1,208 @@ +/* + * snd_sst_tokens.h - Intel SST tokens definition + * + * Copyright (C) 2016 Intel Corp + * Author: Shreyas NC + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as 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. + */ +#ifndef __SND_SST_TOKENS_H__ +#define __SND_SST_TOKENS_H__ + +/** + * %SKL_TKN_UUID: Module UUID + * + * %SKL_TKN_U8_BLOCK_TYPE: Type of the private data block.Can be: + * tuples, bytes, short and words + * + * %SKL_TKN_U8_IN_PIN_TYPE: Input pin type, + * homogenous=0, heterogenous=1 + * + * %SKL_TKN_U8_OUT_PIN_TYPE: Output pin type, + * homogenous=0, heterogenous=1 + * %SKL_TKN_U8_DYN_IN_PIN: Configure Input pin dynamically + * if true + * + * %SKL_TKN_U8_DYN_OUT_PIN: Configure Output pin dynamically + * if true + * + * %SKL_TKN_U8_IN_QUEUE_COUNT: Store the number of Input pins + * + * %SKL_TKN_U8_OUT_QUEUE_COUNT: Store the number of Output pins + * + * %SKL_TKN_U8_TIME_SLOT: TDM slot number + * + * %SKL_TKN_U8_CORE_ID: Stores module affinity value.Can take + * the values: + * SKL_AFFINITY_CORE_0 = 0, + * SKL_AFFINITY_CORE_1, + * SKL_AFFINITY_CORE_MAX + * + * %SKL_TKN_U8_MOD_TYPE: Module type value. + * + * %SKL_TKN_U8_CONN_TYPE: Module connection type can be a FE, + * BE or NONE as defined : + * SKL_PIPE_CONN_TYPE_NONE = 0, + * SKL_PIPE_CONN_TYPE_FE = 1 (HOST_DMA) + * SKL_PIPE_CONN_TYPE_BE = 2 (LINK_DMA) + * + * %SKL_TKN_U8_DEV_TYPE: Type of device to which the module is + * connected + * Can take the values: + * SKL_DEVICE_BT = 0x0, + * SKL_DEVICE_DMIC = 0x1, + * SKL_DEVICE_I2S = 0x2, + * SKL_DEVICE_SLIMBUS = 0x3, + * SKL_DEVICE_HDALINK = 0x4, + * SKL_DEVICE_HDAHOST = 0x5, + * SKL_DEVICE_NONE + * + * %SKL_TKN_U8_HW_CONN_TYPE: Connection type of the HW to which the + * module is connected + * SKL_CONN_NONE = 0, + * SKL_CONN_SOURCE = 1, + * SKL_CONN_SINK = 2 + * + * %SKL_TKN_U16_PIN_INST_ID: Stores the pin instance id + * + * %SKL_TKN_U16_MOD_INST_ID: Stores the mdule instance id + * + * %SKL_TKN_U32_MAX_MCPS: Module max mcps value + * + * %SKL_TKN_U32_MEM_PAGES: Module resource pages + * + * %SKL_TKN_U32_OBS: Stores Output Buffer size + * + * %SKL_TKN_U32_IBS: Stores input buffer size + * + * %SKL_TKN_U32_VBUS_ID: Module VBUS_ID. PDM=0, SSP0=0, + * SSP1=1,SSP2=2, + * SSP3=3, SSP4=4, + * SSP5=5, SSP6=6,INVALID + * + * %SKL_TKN_U32_PARAMS_FIXUP: Module Params fixup mask + * %SKL_TKN_U32_CONVERTER: Module params converter mask + * %SKL_TKN_U32_PIPE_ID: Stores the pipe id + * + * %SKL_TKN_U32_PIPE_CONN_TYPE: Type of the token to which the pipe is + * connected to. It can be + * SKL_PIPE_CONN_TYPE_NONE = 0, + * SKL_PIPE_CONN_TYPE_FE = 1 (HOST_DMA), + * SKL_PIPE_CONN_TYPE_BE = 2 (LINK_DMA), + * + * %SKL_TKN_U32_PIPE_PRIORITY: Pipe priority value + * %SKL_TKN_U32_PIPE_MEM_PGS: Pipe resource pages + * + * %SKL_TKN_U32_DIR_PIN_COUNT: Value for the direction to set input/output + * formats and the pin count. + * The first 4 bits have the direction + * value and the next 4 have + * the pin count value. + * SKL_DIR_IN = 0, SKL_DIR_OUT = 1. + * The input and output formats + * share the same set of tokens + * with the distinction between input + * and output made by reading direction + * token. + * + * %SKL_TKN_U32_FMT_CH: Supported channel count + * + * %SKL_TKN_U32_FMT_FREQ: Supported frequency/sample rate + * + * %SKL_TKN_U32_FMT_BIT_DEPTH: Supported container size + * + * %SKL_TKN_U32_FMT_SAMPLE_SIZE:Number of samples in the container + * + * %SKL_TKN_U32_FMT_CH_CONFIG: Supported channel configurations for the + * input/output. + * + * %SKL_TKN_U32_FMT_INTERLEAVE: Interleaving style which can be per + * channel or per sample. The values can be : + * SKL_INTERLEAVING_PER_CHANNEL = 0, + * SKL_INTERLEAVING_PER_SAMPLE = 1, + * + * %SKL_TKN_U32_FMT_SAMPLE_TYPE: + * Specifies the sample type. Can take the + * values: SKL_SAMPLE_TYPE_INT_MSB = 0, + * SKL_SAMPLE_TYPE_INT_LSB = 1, + * SKL_SAMPLE_TYPE_INT_SIGNED = 2, + * SKL_SAMPLE_TYPE_INT_UNSIGNED = 3, + * SKL_SAMPLE_TYPE_FLOAT = 4 + * + * %SKL_TKN_U32_CH_MAP: Channel map values + * %SKL_TKN_U32_MOD_SET_PARAMS: It can take these values: + * SKL_PARAM_DEFAULT, SKL_PARAM_INIT, + * SKL_PARAM_SET, SKL_PARAM_BIND + * + * %SKL_TKN_U32_MOD_PARAM_ID: ID of the module params + * + * %SKL_TKN_U32_CAPS_SET_PARAMS: + * Set params value + * + * %SKL_TKN_U32_CAPS_PARAMS_ID: Params ID + * + * %SKL_TKN_U32_CAPS_SIZE: Caps size + * + * %SKL_TKN_U32_PROC_DOMAIN: Specify processing domain + * + * module_id and loadable flags dont have tokens as these values will be + * read from the DSP FW manifest + */ +enum SKL_TKNS { + SKL_TKN_UUID = 1, + SKL_TKN_U8_NUM_BLOCKS, + SKL_TKN_U8_BLOCK_TYPE, + SKL_TKN_U8_IN_PIN_TYPE, + SKL_TKN_U8_OUT_PIN_TYPE, + SKL_TKN_U8_DYN_IN_PIN, + SKL_TKN_U8_DYN_OUT_PIN, + SKL_TKN_U8_IN_QUEUE_COUNT, + SKL_TKN_U8_OUT_QUEUE_COUNT, + SKL_TKN_U8_TIME_SLOT, + SKL_TKN_U8_CORE_ID, + SKL_TKN_U8_MOD_TYPE, + SKL_TKN_U8_CONN_TYPE, + SKL_TKN_U8_DEV_TYPE, + SKL_TKN_U8_HW_CONN_TYPE, + SKL_TKN_U16_MOD_INST_ID, + SKL_TKN_U16_BLOCK_SIZE, + SKL_TKN_U32_MAX_MCPS, + SKL_TKN_U32_MEM_PAGES, + SKL_TKN_U32_OBS, + SKL_TKN_U32_IBS, + SKL_TKN_U32_VBUS_ID, + SKL_TKN_U32_PARAMS_FIXUP, + SKL_TKN_U32_CONVERTER, + SKL_TKN_U32_PIPE_ID, + SKL_TKN_U32_PIPE_CONN_TYPE, + SKL_TKN_U32_PIPE_PRIORITY, + SKL_TKN_U32_PIPE_MEM_PGS, + SKL_TKN_U32_DIR_PIN_COUNT, + SKL_TKN_U32_FMT_CH, + SKL_TKN_U32_FMT_FREQ, + SKL_TKN_U32_FMT_BIT_DEPTH, + SKL_TKN_U32_FMT_SAMPLE_SIZE, + SKL_TKN_U32_FMT_CH_CONFIG, + SKL_TKN_U32_FMT_INTERLEAVE, + SKL_TKN_U32_FMT_SAMPLE_TYPE, + SKL_TKN_U32_FMT_CH_MAP, + SKL_TKN_U32_PIN_MOD_ID, + SKL_TKN_U32_PIN_INST_ID, + SKL_TKN_U32_MOD_SET_PARAMS, + SKL_TKN_U32_MOD_PARAM_ID, + SKL_TKN_U32_CAPS_SET_PARAMS, + SKL_TKN_U32_CAPS_PARAMS_ID, + SKL_TKN_U32_CAPS_SIZE, + SKL_TKN_U32_PROC_DOMAIN, + SKL_TKN_MAX = SKL_TKN_U32_PROC_DOMAIN, +}; + +#endif -- cgit v0.10.2 From 6277e83292a2d4d88d150c0eb3004bd714ad8728 Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Fri, 12 Aug 2016 12:29:51 +0530 Subject: ASoC: Intel: Skylake: Parse vendor tokens to build module data Skl topology data is preceded by a descriptor for number of data blocks, the size of the data block and type of data block. The type of the data block can be either a tuple or a binary blob. Private data is parsed based on data block type and module data is filled accordingly. Signed-off-by: Shreyas NC Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 4bc8f9c..000482e 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "skl-sst-dsp.h" #include "skl-sst-ipc.h" #include "skl-topology.h" @@ -32,6 +33,8 @@ #define SKL_CH_FIXUP_MASK (1 << 0) #define SKL_RATE_FIXUP_MASK (1 << 1) #define SKL_FMT_FIXUP_MASK (1 << 2) +#define SKL_IN_DIR_BIT_MASK BIT(0) +#define SKL_PIN_COUNT_MASK GENMASK(7, 4) /* * SKL DSP driver modelling uses only few DAPM widgets so for rest we will @@ -1468,85 +1471,570 @@ static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = { skl_tplg_tlv_control_set}, }; -/* - * The topology binary passes the pin info for a module so initialize the pin - * info passed into module instance - */ -static void skl_fill_module_pin_info(struct skl_dfw_module_pin *dfw_pin, - struct skl_module_pin *m_pin, - bool is_dynamic, int max_pin) +static int skl_tplg_fill_pipe_tkn(struct device *dev, + struct skl_pipe *pipe, u32 tkn, + u32 tkn_val) { - int i; - for (i = 0; i < max_pin; i++) { - m_pin[i].id.module_id = dfw_pin[i].module_id; - m_pin[i].id.instance_id = dfw_pin[i].instance_id; - m_pin[i].in_use = false; - m_pin[i].is_dynamic = is_dynamic; - m_pin[i].pin_state = SKL_PIN_UNBIND; + switch (tkn) { + case SKL_TKN_U32_PIPE_CONN_TYPE: + pipe->conn_type = tkn_val; + break; + + case SKL_TKN_U32_PIPE_PRIORITY: + pipe->pipe_priority = tkn_val; + break; + + case SKL_TKN_U32_PIPE_MEM_PGS: + pipe->memory_pages = tkn_val; + break; + + default: + dev_err(dev, "Token not handled %d\n", tkn); + return -EINVAL; } + + return 0; } /* - * Add pipeline from topology binary into driver pipeline list - * - * If already added we return that instance - * Otherwise we create a new instance and add into driver list + * Add pipeline by parsing the relevant tokens + * Return an existing pipe if the pipe already exists. */ -static struct skl_pipe *skl_tplg_add_pipe(struct device *dev, - struct skl *skl, struct skl_dfw_pipe *dfw_pipe) +static int skl_tplg_add_pipe(struct device *dev, + struct skl_module_cfg *mconfig, struct skl *skl, + struct snd_soc_tplg_vendor_value_elem *tkn_elem) { struct skl_pipeline *ppl; struct skl_pipe *pipe; struct skl_pipe_params *params; list_for_each_entry(ppl, &skl->ppl_list, node) { - if (ppl->pipe->ppl_id == dfw_pipe->pipe_id) - return ppl->pipe; + if (ppl->pipe->ppl_id == tkn_elem->value) { + mconfig->pipe = ppl->pipe; + return EEXIST; + } } ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL); if (!ppl) - return NULL; + return -ENOMEM; pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL); if (!pipe) - return NULL; + return -ENOMEM; params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL); if (!params) - return NULL; + return -ENOMEM; - pipe->ppl_id = dfw_pipe->pipe_id; - pipe->memory_pages = dfw_pipe->memory_pages; - pipe->pipe_priority = dfw_pipe->pipe_priority; - pipe->conn_type = dfw_pipe->conn_type; - pipe->state = SKL_PIPE_INVALID; pipe->p_params = params; + pipe->ppl_id = tkn_elem->value; INIT_LIST_HEAD(&pipe->w_list); ppl->pipe = pipe; list_add(&ppl->node, &skl->ppl_list); - return ppl->pipe; + mconfig->pipe = pipe; + mconfig->pipe->state = SKL_PIPE_INVALID; + + return 0; +} + +static int skl_tplg_fill_pin(struct device *dev, u32 tkn, + struct skl_module_pin *m_pin, + int pin_index, u32 value) +{ + switch (tkn) { + case SKL_TKN_U32_PIN_MOD_ID: + m_pin[pin_index].id.module_id = value; + break; + + case SKL_TKN_U32_PIN_INST_ID: + m_pin[pin_index].id.instance_id = value; + break; + + default: + dev_err(dev, "%d Not a pin token\n", value); + return -EINVAL; + } + + return 0; +} + +/* + * Parse for pin config specific tokens to fill up the + * module private data + */ +static int skl_tplg_fill_pins_info(struct device *dev, + struct skl_module_cfg *mconfig, + struct snd_soc_tplg_vendor_value_elem *tkn_elem, + int dir, int pin_count) +{ + int ret; + struct skl_module_pin *m_pin; + + switch (dir) { + case SKL_DIR_IN: + m_pin = mconfig->m_in_pin; + break; + + case SKL_DIR_OUT: + m_pin = mconfig->m_out_pin; + break; + + default: + dev_err(dev, "Invalid direction value"); + return -EINVAL; + } + + ret = skl_tplg_fill_pin(dev, tkn_elem->token, + m_pin, pin_count, tkn_elem->value); + + if (ret < 0) + return ret; + + m_pin[pin_count].in_use = false; + m_pin[pin_count].pin_state = SKL_PIN_UNBIND; + + return 0; } -static void skl_tplg_fill_fmt(struct skl_module_fmt *dst_fmt, - struct skl_dfw_module_fmt *src_fmt, - int pins) +/* + * Fill up input/output module config format based + * on the direction + */ +static int skl_tplg_fill_fmt(struct device *dev, + struct skl_module_cfg *mconfig, u32 tkn, + u32 value, u32 dir, u32 pin_count) +{ + struct skl_module_fmt *dst_fmt; + + switch (dir) { + case SKL_DIR_IN: + dst_fmt = mconfig->in_fmt; + dst_fmt += pin_count; + break; + + case SKL_DIR_OUT: + dst_fmt = mconfig->out_fmt; + dst_fmt += pin_count; + break; + + default: + dev_err(dev, "Invalid direction value"); + return -EINVAL; + } + + switch (tkn) { + case SKL_TKN_U32_FMT_CH: + dst_fmt->channels = value; + break; + + case SKL_TKN_U32_FMT_FREQ: + dst_fmt->s_freq = value; + break; + + case SKL_TKN_U32_FMT_BIT_DEPTH: + dst_fmt->bit_depth = value; + break; + + case SKL_TKN_U32_FMT_SAMPLE_SIZE: + dst_fmt->valid_bit_depth = value; + break; + + case SKL_TKN_U32_FMT_CH_CONFIG: + dst_fmt->ch_cfg = value; + break; + + case SKL_TKN_U32_FMT_INTERLEAVE: + dst_fmt->interleaving_style = value; + break; + + case SKL_TKN_U32_FMT_SAMPLE_TYPE: + dst_fmt->sample_type = value; + break; + + case SKL_TKN_U32_FMT_CH_MAP: + dst_fmt->ch_map = value; + break; + + default: + dev_err(dev, "Invalid token %d", tkn); + return -EINVAL; + } + + return 0; +} + +static int skl_tplg_get_uuid(struct device *dev, struct skl_module_cfg *mconfig, + struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) +{ + if (uuid_tkn->token == SKL_TKN_UUID) + memcpy(&mconfig->guid, &uuid_tkn->uuid, 16); + else { + dev_err(dev, "Not an UUID token tkn %d", uuid_tkn->token); + return -EINVAL; + } + + return 0; +} + +static void skl_tplg_fill_pin_dynamic_val( + struct skl_module_pin *mpin, u32 pin_count, u32 value) { int i; - for (i = 0; i < pins; i++) { - dst_fmt[i].channels = src_fmt[i].channels; - dst_fmt[i].s_freq = src_fmt[i].freq; - dst_fmt[i].bit_depth = src_fmt[i].bit_depth; - dst_fmt[i].valid_bit_depth = src_fmt[i].valid_bit_depth; - dst_fmt[i].ch_cfg = src_fmt[i].ch_cfg; - dst_fmt[i].ch_map = src_fmt[i].ch_map; - dst_fmt[i].interleaving_style = src_fmt[i].interleaving_style; - dst_fmt[i].sample_type = src_fmt[i].sample_type; + for (i = 0; i < pin_count; i++) + mpin[i].is_dynamic = value; +} + +/* + * Parse tokens to fill up the module private data + */ +static int skl_tplg_get_token(struct device *dev, + struct snd_soc_tplg_vendor_value_elem *tkn_elem, + struct skl *skl, struct skl_module_cfg *mconfig) +{ + int tkn_count = 0; + int ret; + static int is_pipe_exists; + static int pin_index, dir; + + if (tkn_elem->token > SKL_TKN_MAX) + return -EINVAL; + + switch (tkn_elem->token) { + case SKL_TKN_U8_IN_QUEUE_COUNT: + mconfig->max_in_queue = tkn_elem->value; + mconfig->m_in_pin = devm_kzalloc(dev, mconfig->max_in_queue * + sizeof(*mconfig->m_in_pin), + GFP_KERNEL); + if (!mconfig->m_in_pin) + return -ENOMEM; + + break; + + case SKL_TKN_U8_OUT_QUEUE_COUNT: + mconfig->max_out_queue = tkn_elem->value; + mconfig->m_out_pin = devm_kzalloc(dev, mconfig->max_out_queue * + sizeof(*mconfig->m_out_pin), + GFP_KERNEL); + + if (!mconfig->m_out_pin) + return -ENOMEM; + + break; + + case SKL_TKN_U8_DYN_IN_PIN: + if (!mconfig->m_in_pin) + return -ENOMEM; + + skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, + mconfig->max_in_queue, tkn_elem->value); + + break; + + case SKL_TKN_U8_DYN_OUT_PIN: + if (!mconfig->m_out_pin) + return -ENOMEM; + + skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, + mconfig->max_out_queue, tkn_elem->value); + + break; + + case SKL_TKN_U8_TIME_SLOT: + mconfig->time_slot = tkn_elem->value; + break; + + case SKL_TKN_U8_CORE_ID: + mconfig->core_id = tkn_elem->value; + + case SKL_TKN_U8_MOD_TYPE: + mconfig->m_type = tkn_elem->value; + break; + + case SKL_TKN_U8_DEV_TYPE: + mconfig->dev_type = tkn_elem->value; + break; + + case SKL_TKN_U8_HW_CONN_TYPE: + mconfig->hw_conn_type = tkn_elem->value; + break; + + case SKL_TKN_U16_MOD_INST_ID: + mconfig->id.instance_id = + tkn_elem->value; + break; + + case SKL_TKN_U32_MEM_PAGES: + mconfig->mem_pages = tkn_elem->value; + break; + + case SKL_TKN_U32_MAX_MCPS: + mconfig->mcps = tkn_elem->value; + break; + + case SKL_TKN_U32_OBS: + mconfig->obs = tkn_elem->value; + break; + + case SKL_TKN_U32_IBS: + mconfig->ibs = tkn_elem->value; + break; + + case SKL_TKN_U32_VBUS_ID: + mconfig->vbus_id = tkn_elem->value; + break; + + case SKL_TKN_U32_PARAMS_FIXUP: + mconfig->params_fixup = tkn_elem->value; + break; + + case SKL_TKN_U32_CONVERTER: + mconfig->converter = tkn_elem->value; + break; + + case SKL_TKN_U32_PIPE_ID: + ret = skl_tplg_add_pipe(dev, + mconfig, skl, tkn_elem); + + if (ret < 0) + return is_pipe_exists; + + if (ret == EEXIST) + is_pipe_exists = 1; + + break; + + case SKL_TKN_U32_PIPE_CONN_TYPE: + case SKL_TKN_U32_PIPE_PRIORITY: + case SKL_TKN_U32_PIPE_MEM_PGS: + if (is_pipe_exists) { + ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe, + tkn_elem->token, tkn_elem->value); + if (ret < 0) + return ret; + } + + break; + + /* + * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both + * direction and the pin count. The first four bits represent + * direction and next four the pin count. + */ + case SKL_TKN_U32_DIR_PIN_COUNT: + dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; + pin_index = (tkn_elem->value & + SKL_PIN_COUNT_MASK) >> 4; + + break; + + case SKL_TKN_U32_FMT_CH: + case SKL_TKN_U32_FMT_FREQ: + case SKL_TKN_U32_FMT_BIT_DEPTH: + case SKL_TKN_U32_FMT_SAMPLE_SIZE: + case SKL_TKN_U32_FMT_CH_CONFIG: + case SKL_TKN_U32_FMT_INTERLEAVE: + case SKL_TKN_U32_FMT_SAMPLE_TYPE: + case SKL_TKN_U32_FMT_CH_MAP: + ret = skl_tplg_fill_fmt(dev, mconfig, tkn_elem->token, + tkn_elem->value, dir, pin_index); + + if (ret < 0) + return ret; + + break; + + case SKL_TKN_U32_PIN_MOD_ID: + case SKL_TKN_U32_PIN_INST_ID: + ret = skl_tplg_fill_pins_info(dev, + mconfig, tkn_elem, dir, + pin_index); + if (ret < 0) + return ret; + + break; + + case SKL_TKN_U32_CAPS_SIZE: + mconfig->formats_config.caps_size = + tkn_elem->value; + + break; + + case SKL_TKN_U32_PROC_DOMAIN: + mconfig->domain = + tkn_elem->value; + + break; + + case SKL_TKN_U8_IN_PIN_TYPE: + case SKL_TKN_U8_OUT_PIN_TYPE: + case SKL_TKN_U8_CONN_TYPE: + break; + + default: + dev_err(dev, "Token %d not handled\n", + tkn_elem->token); + return -EINVAL; } + + tkn_count++; + + return tkn_count; +} + +/* + * Parse the vendor array for specific tokens to construct + * module private data + */ +static int skl_tplg_get_tokens(struct device *dev, + char *pvt_data, struct skl *skl, + struct skl_module_cfg *mconfig, int block_size) +{ + struct snd_soc_tplg_vendor_array *array; + struct snd_soc_tplg_vendor_value_elem *tkn_elem; + int tkn_count = 0, ret; + int off = 0, tuple_size = 0; + + if (block_size <= 0) + return -EINVAL; + + while (tuple_size < block_size) { + array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); + + off += array->size; + + switch (array->type) { + case SND_SOC_TPLG_TUPLE_TYPE_STRING: + dev_warn(dev, "no string tokens expected for skl tplg"); + continue; + + case SND_SOC_TPLG_TUPLE_TYPE_UUID: + ret = skl_tplg_get_uuid(dev, mconfig, array->uuid); + if (ret < 0) + return ret; + + tuple_size += sizeof(*array->uuid); + + continue; + + default: + tkn_elem = array->value; + tkn_count = 0; + break; + } + + while (tkn_count <= (array->num_elems - 1)) { + ret = skl_tplg_get_token(dev, tkn_elem, + skl, mconfig); + + if (ret < 0) + return ret; + + tkn_count = tkn_count + ret; + tkn_elem++; + } + + tuple_size += tkn_count * sizeof(*tkn_elem); + } + + return 0; +} + +/* + * Every data block is preceded by a descriptor to read the number + * of data blocks, they type of the block and it's size + */ +static int skl_tplg_get_desc_blocks(struct device *dev, + struct snd_soc_tplg_vendor_array *array) +{ + struct snd_soc_tplg_vendor_value_elem *tkn_elem; + + tkn_elem = array->value; + + switch (tkn_elem->token) { + case SKL_TKN_U8_NUM_BLOCKS: + case SKL_TKN_U8_BLOCK_TYPE: + case SKL_TKN_U16_BLOCK_SIZE: + return tkn_elem->value; + + default: + dev_err(dev, "Invalid descriptor token %d", tkn_elem->token); + break; + } + + return -EINVAL; +} + +/* + * Parse the private data for the token and corresponding value. + * The private data can have multiple data blocks. So, a data block + * is preceded by a descriptor for number of blocks and a descriptor + * for the type and size of the suceeding data block. + */ +static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, + struct skl *skl, struct device *dev, + struct skl_module_cfg *mconfig) +{ + struct snd_soc_tplg_vendor_array *array; + int num_blocks, block_size = 0, block_type, off = 0; + char *data; + int ret; + + /* Read the NUM_DATA_BLOCKS descriptor */ + array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data; + ret = skl_tplg_get_desc_blocks(dev, array); + if (ret < 0) + return ret; + num_blocks = ret; + + off += array->size; + array = (struct snd_soc_tplg_vendor_array *)(tplg_w->priv.data + off); + + /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ + while (num_blocks > 0) { + ret = skl_tplg_get_desc_blocks(dev, array); + + if (ret < 0) + return ret; + block_type = ret; + off += array->size; + + array = (struct snd_soc_tplg_vendor_array *) + (tplg_w->priv.data + off); + + ret = skl_tplg_get_desc_blocks(dev, array); + + if (ret < 0) + return ret; + block_size = ret; + off += array->size; + + array = (struct snd_soc_tplg_vendor_array *) + (tplg_w->priv.data + off); + + data = (tplg_w->priv.data + off); + + if (block_type == SKL_TYPE_TUPLE) { + ret = skl_tplg_get_tokens(dev, data, + skl, mconfig, block_size); + + if (ret < 0) + return ret; + + --num_blocks; + } else { + if (mconfig->formats_config.caps_size > 0) + memcpy(mconfig->formats_config.caps, data, + mconfig->formats_config.caps_size); + --num_blocks; + } + } + + return 0; } static void skl_clear_pin_config(struct snd_soc_platform *platform, @@ -1614,9 +2102,6 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, struct skl *skl = ebus_to_skl(ebus); struct hdac_bus *bus = ebus_to_hbus(ebus); struct skl_module_cfg *mconfig; - struct skl_pipe *pipe; - struct skl_dfw_module *dfw_config = - (struct skl_dfw_module *)tplg_w->priv.data; if (!tplg_w->priv.size) goto bind_event; @@ -1627,77 +2112,17 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, return -ENOMEM; w->priv = mconfig; - memcpy(&mconfig->guid, &dfw_config->uuid, 16); /* * module binary can be loaded later, so set it to query when * module is load for a use case */ mconfig->id.module_id = -1; - mconfig->id.instance_id = dfw_config->instance_id; - mconfig->mcps = dfw_config->max_mcps; - mconfig->ibs = dfw_config->ibs; - mconfig->obs = dfw_config->obs; - mconfig->core_id = dfw_config->core_id; - mconfig->max_in_queue = dfw_config->max_in_queue; - mconfig->max_out_queue = dfw_config->max_out_queue; - mconfig->is_loadable = dfw_config->is_loadable; - mconfig->domain = dfw_config->proc_domain; - skl_tplg_fill_fmt(mconfig->in_fmt, dfw_config->in_fmt, - MODULE_MAX_IN_PINS); - skl_tplg_fill_fmt(mconfig->out_fmt, dfw_config->out_fmt, - MODULE_MAX_OUT_PINS); - - mconfig->params_fixup = dfw_config->params_fixup; - mconfig->converter = dfw_config->converter; - mconfig->m_type = dfw_config->module_type; - mconfig->vbus_id = dfw_config->vbus_id; - mconfig->mem_pages = dfw_config->mem_pages; - - pipe = skl_tplg_add_pipe(bus->dev, skl, &dfw_config->pipe); - if (pipe) - mconfig->pipe = pipe; - - mconfig->dev_type = dfw_config->dev_type; - mconfig->hw_conn_type = dfw_config->hw_conn_type; - mconfig->time_slot = dfw_config->time_slot; - mconfig->formats_config.caps_size = dfw_config->caps.caps_size; - - mconfig->m_in_pin = devm_kzalloc(bus->dev, (mconfig->max_in_queue) * - sizeof(*mconfig->m_in_pin), - GFP_KERNEL); - if (!mconfig->m_in_pin) - return -ENOMEM; - - mconfig->m_out_pin = devm_kzalloc(bus->dev, (mconfig->max_out_queue) * - sizeof(*mconfig->m_out_pin), - GFP_KERNEL); - if (!mconfig->m_out_pin) - return -ENOMEM; - - skl_fill_module_pin_info(dfw_config->in_pin, mconfig->m_in_pin, - dfw_config->is_dynamic_in_pin, - mconfig->max_in_queue); - - skl_fill_module_pin_info(dfw_config->out_pin, mconfig->m_out_pin, - dfw_config->is_dynamic_out_pin, - mconfig->max_out_queue); - - - if (mconfig->formats_config.caps_size == 0) - goto bind_event; - - mconfig->formats_config.caps = (u32 *)devm_kzalloc(bus->dev, - mconfig->formats_config.caps_size, GFP_KERNEL); - - if (mconfig->formats_config.caps == NULL) - return -ENOMEM; - - memcpy(mconfig->formats_config.caps, dfw_config->caps.caps, - dfw_config->caps.caps_size); - mconfig->formats_config.param_id = dfw_config->caps.param_id; - mconfig->formats_config.set_params = dfw_config->caps.set_params; + /* Parse private data for tuples */ + ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); + if (ret < 0) + return ret; bind_event: if (tplg_w->event_type == 0) { dev_dbg(bus->dev, "ASoC: No event handler required\n"); diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index bd8b4ae..281762e 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h @@ -241,4 +241,14 @@ struct skl_dfw_manifest { struct lib_info lib[HDA_MAX_LIB]; } __packed; +enum skl_tkn_dir { + SKL_DIR_IN, + SKL_DIR_OUT +}; + +enum skl_tuple_type { + SKL_TYPE_TUPLE, + SKL_TYPE_DATA +}; + #endif -- cgit v0.10.2 From 33ece7f9c8e8a2abfcca681ec9424b15271f7afb Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Fri, 12 Aug 2016 12:29:52 +0530 Subject: ASoC: Intel: Skylake: Remove dfw config and associated structures The skl_dfw_config structure is no longer required as the module config is populated by parsing and reading the token values. So, remove the structure. Signed-off-by: Shreyas NC Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index e4865ea..9ce93e9 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -28,11 +28,6 @@ /* FW Extended Manifest Header id = $AE1 */ #define SKL_EXT_MANIFEST_HEADER_MAGIC 0x31454124 -struct skl_dfw_module_mod { - char name[100]; - struct skl_dfw_module skl_dfw_mod; -}; - struct UUID { u8 id[16]; }; diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index 281762e..e208724 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h @@ -148,79 +148,6 @@ enum skl_module_param_type { SKL_PARAM_BIND }; -struct skl_dfw_module_pin { - u16 module_id; - u16 instance_id; -} __packed; - -struct skl_dfw_module_fmt { - u32 channels; - u32 freq; - u32 bit_depth; - u32 valid_bit_depth; - u32 ch_cfg; - u32 interleaving_style; - u32 sample_type; - u32 ch_map; -} __packed; - -struct skl_dfw_module_caps { - u32 set_params:2; - u32 rsvd:30; - u32 param_id; - u32 caps_size; - u32 caps[HDA_SST_CFG_MAX]; -}; - -struct skl_dfw_pipe { - u8 pipe_id; - u8 pipe_priority; - u16 conn_type:4; - u16 rsvd:4; - u16 memory_pages:8; -} __packed; - -struct skl_dfw_module { - u8 uuid[16]; - - u16 module_id; - u16 instance_id; - u32 max_mcps; - u32 mem_pages; - u32 obs; - u32 ibs; - u32 vbus_id; - - u32 max_in_queue:8; - u32 max_out_queue:8; - u32 time_slot:8; - u32 core_id:4; - u32 rsvd1:4; - - u32 module_type:8; - u32 conn_type:4; - u32 dev_type:4; - u32 hw_conn_type:4; - u32 rsvd2:12; - - u32 params_fixup:8; - u32 converter:8; - u32 input_pin_type:1; - u32 output_pin_type:1; - u32 is_dynamic_in_pin:1; - u32 is_dynamic_out_pin:1; - u32 is_loadable:1; - u32 proc_domain:1; - u32 rsvd3:10; - - struct skl_dfw_pipe pipe; - struct skl_dfw_module_fmt in_fmt[MAX_IN_QUEUE]; - struct skl_dfw_module_fmt out_fmt[MAX_OUT_QUEUE]; - struct skl_dfw_module_pin in_pin[MAX_IN_QUEUE]; - struct skl_dfw_module_pin out_pin[MAX_OUT_QUEUE]; - struct skl_dfw_module_caps caps; -} __packed; - struct skl_dfw_algo_data { u32 set_params:2; u32 rsvd:30; -- cgit v0.10.2 From f918e1697b1a8f2f26a4813db053cfbcafc48046 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Fri, 19 Aug 2016 18:12:46 +0800 Subject: ASoC: topology: ABI - Add sig_bits to stream caps Kernel struct snd_soc_pcm_stream, SoC PCM stream information, needs this field. Although current topology users don't configure this, we define it for future extension. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h index f734bea..33d00a4 100644 --- a/include/uapi/sound/asoc.h +++ b/include/uapi/sound/asoc.h @@ -257,6 +257,7 @@ struct snd_soc_tplg_stream_caps { __le32 period_size_max; /* max period size bytes */ __le32 buffer_size_min; /* min buffer size bytes */ __le32 buffer_size_max; /* max buffer size bytes */ + __le32 sig_bits; /* number of bits of content */ } __attribute__((packed)); /* diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index a9e83a2..6b05047 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1556,6 +1556,7 @@ static void set_stream_info(struct snd_soc_pcm_stream *stream, stream->rate_min = caps->rate_min; stream->rate_max = caps->rate_max; stream->formats = caps->formats; + stream->sig_bits = caps->sig_bits; } static void set_dai_flags(struct snd_soc_dai_driver *dai_drv, -- cgit v0.10.2 From 78822e36dca8fe8bc83e7847508891b59f3f8603 Mon Sep 17 00:00:00 2001 From: John Hsu Date: Tue, 23 Aug 2016 16:02:49 +0800 Subject: ASoC: nau8810: fix compile warning in loopback switch control Thank Stephen Rothwell for the message. The patch is to fix the following compile error. sound/soc/codecs/nau8810.c:441:3: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] SND_SOC_DAPM_SWITCH("Digital Loopback", SND_SOC_NOPM, 0, 0, &nau8810_loopback), ^ sound/soc/codecs/nau8810.c:441:3: note: (near initialization for 'nau8810_dapm_widgets[11].kcontrol_news') Signed-off-by: John Hsu Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c index 7617dda..f9bcdc3 100644 --- a/sound/soc/codecs/nau8810.c +++ b/sound/soc/codecs/nau8810.c @@ -391,10 +391,9 @@ static const struct snd_kcontrol_new nau8810_mic_boost_controls = NAU8810_PMICBSTGAIN_SFT, 0x7, 0); /* Loopback Switch */ -static const struct snd_kcontrol_new nau8810_loopback[] = { +static const struct snd_kcontrol_new nau8810_loopback = SOC_DAPM_SINGLE("Switch", NAU8810_REG_COMP, - NAU8810_ADDAP_SFT, 1, 0), -}; + NAU8810_ADDAP_SFT, 1, 0); static int check_mclk_select_pll(struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink) -- cgit v0.10.2 From 541070cec4f9be18ce9fcc74ac5e1036965ceb63 Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Tue, 23 Aug 2016 09:31:03 +0530 Subject: ASoC: Intel: Skylake: Parse manifest data Topology manifest has lib names and lib count info. So, define tokens to represent module private data and parse these tokens to fill up the manifest structure in the driver accordingly. Signed-off-by: Shreyas NC Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/include/uapi/sound/snd_sst_tokens.h b/include/uapi/sound/snd_sst_tokens.h index f56a932..1ee2e94 100644 --- a/include/uapi/sound/snd_sst_tokens.h +++ b/include/uapi/sound/snd_sst_tokens.h @@ -153,6 +153,10 @@ * * %SKL_TKN_U32_PROC_DOMAIN: Specify processing domain * + * %SKL_TKN_U32_LIB_COUNT: Specifies the number of libraries + * + * %SKL_TKN_STR_LIB_NAME: Specifies the library name + * * module_id and loadable flags dont have tokens as these values will be * read from the DSP FW manifest */ @@ -202,7 +206,9 @@ enum SKL_TKNS { SKL_TKN_U32_CAPS_PARAMS_ID, SKL_TKN_U32_CAPS_SIZE, SKL_TKN_U32_PROC_DOMAIN, - SKL_TKN_MAX = SKL_TKN_U32_PROC_DOMAIN, + SKL_TKN_U32_LIB_COUNT, + SKL_TKN_STR_LIB_NAME, + SKL_TKN_MAX = SKL_TKN_STR_LIB_NAME, }; #endif diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 000482e..108ebb9 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -2201,6 +2201,197 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, return 0; } +static int skl_tplg_fill_str_mfest_tkn(struct device *dev, + struct snd_soc_tplg_vendor_string_elem *str_elem, + struct skl_dfw_manifest *minfo) +{ + int tkn_count = 0; + static int ref_count; + + switch (str_elem->token) { + case SKL_TKN_STR_LIB_NAME: + if (ref_count > minfo->lib_count - 1) { + ref_count = 0; + return -EINVAL; + } + + strncpy(minfo->lib[ref_count].name, str_elem->string, + ARRAY_SIZE(minfo->lib[ref_count].name)); + ref_count++; + tkn_count++; + break; + + default: + dev_err(dev, "Not a string token %d", str_elem->token); + break; + } + + return tkn_count; +} + +static int skl_tplg_get_str_tkn(struct device *dev, + struct snd_soc_tplg_vendor_array *array, + struct skl_dfw_manifest *minfo) +{ + int tkn_count = 0, ret; + struct snd_soc_tplg_vendor_string_elem *str_elem; + + str_elem = (struct snd_soc_tplg_vendor_string_elem *)array->value; + while (tkn_count < array->num_elems) { + ret = skl_tplg_fill_str_mfest_tkn(dev, str_elem, minfo); + str_elem++; + + if (ret < 0) + return ret; + + tkn_count = tkn_count + ret; + } + + return tkn_count; +} + +static int skl_tplg_get_int_tkn(struct device *dev, + struct snd_soc_tplg_vendor_value_elem *tkn_elem, + struct skl_dfw_manifest *minfo) +{ + int tkn_count = 0; + + switch (tkn_elem->token) { + case SKL_TKN_U32_LIB_COUNT: + minfo->lib_count = tkn_elem->value; + tkn_count++; + break; + + default: + dev_err(dev, "Not a manifest token %d", tkn_elem->token); + return -EINVAL; + } + + return tkn_count; +} + +/* + * Fill the manifest structure by parsing the tokens based on the + * type. + */ +static int skl_tplg_get_manifest_tkn(struct device *dev, + char *pvt_data, struct skl_dfw_manifest *minfo, + int block_size) +{ + int tkn_count = 0, ret; + int off = 0, tuple_size = 0; + struct snd_soc_tplg_vendor_array *array; + struct snd_soc_tplg_vendor_value_elem *tkn_elem; + + if (block_size <= 0) + return -EINVAL; + + while (tuple_size < block_size) { + array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); + off += array->size; + switch (array->type) { + case SND_SOC_TPLG_TUPLE_TYPE_STRING: + ret = skl_tplg_get_str_tkn(dev, array, minfo); + + if (ret < 0) + return ret; + tkn_count += ret; + + tuple_size += tkn_count * + sizeof(struct snd_soc_tplg_vendor_string_elem); + continue; + + case SND_SOC_TPLG_TUPLE_TYPE_UUID: + dev_warn(dev, "no uuid tokens for skl tplf manifest"); + continue; + + default: + tkn_elem = array->value; + tkn_count = 0; + break; + } + + while (tkn_count <= array->num_elems - 1) { + ret = skl_tplg_get_int_tkn(dev, + tkn_elem, minfo); + if (ret < 0) + return ret; + + tkn_count = tkn_count + ret; + tkn_elem++; + tuple_size += tkn_count * + sizeof(struct snd_soc_tplg_vendor_value_elem); + break; + } + tkn_count = 0; + } + + return 0; +} + +/* + * Parse manifest private data for tokens. The private data block is + * preceded by descriptors for type and size of data block. + */ +static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, + struct device *dev, struct skl_dfw_manifest *minfo) +{ + struct snd_soc_tplg_vendor_array *array; + int num_blocks, block_size = 0, block_type, off = 0; + char *data; + int ret; + + /* Read the NUM_DATA_BLOCKS descriptor */ + array = (struct snd_soc_tplg_vendor_array *)manifest->priv.data; + ret = skl_tplg_get_desc_blocks(dev, array); + if (ret < 0) + return ret; + num_blocks = ret; + + off += array->size; + array = (struct snd_soc_tplg_vendor_array *) + (manifest->priv.data + off); + + /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ + while (num_blocks > 0) { + ret = skl_tplg_get_desc_blocks(dev, array); + + if (ret < 0) + return ret; + block_type = ret; + off += array->size; + + array = (struct snd_soc_tplg_vendor_array *) + (manifest->priv.data + off); + + ret = skl_tplg_get_desc_blocks(dev, array); + + if (ret < 0) + return ret; + block_size = ret; + off += array->size; + + array = (struct snd_soc_tplg_vendor_array *) + (manifest->priv.data + off); + + data = (manifest->priv.data + off); + + if (block_type == SKL_TYPE_TUPLE) { + ret = skl_tplg_get_manifest_tkn(dev, data, minfo, + block_size); + + if (ret < 0) + return ret; + + --num_blocks; + } else { + return -EINVAL; + } + } + + return 0; +} + static int skl_manifest_load(struct snd_soc_component *cmpnt, struct snd_soc_tplg_manifest *manifest) { @@ -2211,7 +2402,8 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, int ret = 0; minfo = &skl->skl_sst->manifest; - memcpy(minfo, manifest->priv.data, sizeof(struct skl_dfw_manifest)); + + skl_tplg_get_manifest_data(manifest, bus->dev, minfo); if (minfo->lib_count > HDA_MAX_LIB) { dev_err(bus->dev, "Exceeding max Library count. Got:%d\n", -- cgit v0.10.2 From e56375155e95019cd4abc55d30c2c1a415037e27 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 24 Aug 2016 07:48:06 +0100 Subject: ASoC: tas5086: fix typo: "Inavlid" -> "Invalid" trivial typo fix in dev_err message Signed-off-by: Colin Ian King Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index d49d25d..1666ea6 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -387,7 +387,7 @@ static int tas5086_hw_params(struct snd_pcm_substream *substream, val = index_in_array(tas5086_ratios, ARRAY_SIZE(tas5086_ratios), priv->mclk / priv->rate); if (val < 0) { - dev_err(codec->dev, "Inavlid MCLK / Fs ratio\n"); + dev_err(codec->dev, "Invalid MCLK / Fs ratio\n"); return -EINVAL; } -- cgit v0.10.2 From 687df1ad848102da9ea1ee8b0c64c2576ceb60f6 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 23 Aug 2016 23:10:17 +0000 Subject: ASoC: omap-abe-twl6040: Use devm_snd_soc_register_card() Using devm_snd_soc_register_card() can make the code shorter and cleaner. Signed-off-by: Wei Yongjun Acked-by: Peter Ujfalusi Signed-off-by: Mark Brown diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index f61b3b5..89fe95e 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c @@ -305,23 +305,14 @@ static int omap_abe_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(card, priv); - ret = snd_soc_register_card(card); + ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + dev_err(&pdev->dev, "devm_snd_soc_register_card() failed: %d\n", ret); return ret; } -static int omap_abe_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; -} - static const struct of_device_id omap_abe_of_match[] = { {.compatible = "ti,abe-twl6040", }, { }, @@ -335,7 +326,6 @@ static struct platform_driver omap_abe_driver = { .of_match_table = omap_abe_of_match, }, .probe = omap_abe_probe, - .remove = omap_abe_remove, }; static int __init omap_abe_init(void) -- cgit v0.10.2 From 702650bda073cb9df90e3a091ee515f340133b05 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 23 Aug 2016 18:17:46 +0100 Subject: ASoC: sunxi: depend on ARCH_SUNXI Depend on ARCH_SUNXI or COMPILE_TEST as it doesn't make sense to enable these if the appropriate SoC they're embedded in isn't enabled. Signed-off-by: Peter Robinson Signed-off-by: Mark Brown diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig index 2a954bd..dd23682 100644 --- a/sound/soc/sunxi/Kconfig +++ b/sound/soc/sunxi/Kconfig @@ -1,4 +1,5 @@ menu "Allwinner SoC Audio support" + depends on ARCH_SUNXI || COMPILE_TEST config SND_SUN4I_CODEC tristate "Allwinner A10 Codec Support" -- cgit v0.10.2 From a3235938308150fbd0f8b478e73d1e66e945937a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 23 Aug 2016 01:33:57 +0000 Subject: ASoC: rsrc-card: remove board specific compatible rsrc-card has board specific compatible (= lager/koelsh), but these were created as 1st prototype, and it is used in my test environment only. Now normal user can use generic compatible (= renesas,rsrc-card). Removing these board specific compatible doesn't breake compatibility. This patch remove these. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt index 255ece3..f148bf2 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt @@ -4,11 +4,8 @@ Renesas Sampling Rate Convert Sound Card specifies audio DAI connections of SoC Required properties: -- compatible : "renesas,rsrc-card{,}" - Examples with boards are: - - "renesas,rsrc-card" - - "renesas,rsrc-card,lager" - - "renesas,rsrc-card,koelsch" +- compatible : "renesas,rsrc-card" + Optional properties: - card_name : User specified audio sound card name, one string diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index 16dc13e..ce9f911 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -28,20 +28,7 @@ struct rsrc_card_of_data { int num_routes; }; -static const struct snd_soc_dapm_route routes_ssi0_ak4642[] = { - {"ak4642 Playback", NULL, "DAI0 Playback"}, - {"DAI0 Capture", NULL, "ak4642 Capture"}, -}; - -static const struct rsrc_card_of_data routes_of_ssi0_ak4642 = { - .prefix = "ak4642", - .routes = routes_ssi0_ak4642, - .num_routes = ARRAY_SIZE(routes_ssi0_ak4642), -}; - static const struct of_device_id rsrc_card_of_match[] = { - { .compatible = "renesas,rsrc-card,lager", .data = &routes_of_ssi0_ak4642 }, - { .compatible = "renesas,rsrc-card,koelsch", .data = &routes_of_ssi0_ak4642 }, { .compatible = "renesas,rsrc-card", }, {}, }; -- cgit v0.10.2 From 53e682b60019d501e00cfeb701f99ca027470e36 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 23 Aug 2016 01:34:17 +0000 Subject: ASoC: rsrc-card: rename rsrc-card to simple-scu-card phase1 rsrc-card which is using DPCM feature was created for Renesas sound. But not only Renesas, but many SoC can use this driver, because it is based on simple-card driver. To use it as more open driver, rsrc-card will be renamed to simple-scu-card. In order to easy patch review, as 1st step, this patch renames "rsrc" function prefix to "asoc_simple". Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index ce9f911..a0d0f36 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -1,5 +1,5 @@ /* - * Renesas Sampling Rate Convert Sound Card for DPCM + * ASoC simple SCU sound card support * * Copyright (C) 2015 Renesas Solutions Corp. * Kuninori Morimoto @@ -22,21 +22,21 @@ #include #include -struct rsrc_card_of_data { +struct asoc_simple_card_of_data { const char *prefix; const struct snd_soc_dapm_route *routes; int num_routes; }; -static const struct of_device_id rsrc_card_of_match[] = { +static const struct of_device_id asoc_simple_card_of_match[] = { { .compatible = "renesas,rsrc-card", }, {}, }; -MODULE_DEVICE_TABLE(of, rsrc_card_of_match); +MODULE_DEVICE_TABLE(of, asoc_simple_card_of_match); #define IDX_CPU 0 #define IDX_CODEC 1 -struct rsrc_card_priv { +struct asoc_simple_card_priv { struct snd_soc_card snd_card; struct snd_soc_codec_conf codec_conf; struct asoc_simple_dai *dai_props; @@ -45,48 +45,48 @@ struct rsrc_card_priv { u32 convert_channels; }; -#define rsrc_priv_to_dev(priv) ((priv)->snd_card.dev) -#define rsrc_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i)) -#define rsrc_priv_to_props(priv, i) ((priv)->dai_props + (i)) +#define simple_priv_to_dev(priv) ((priv)->snd_card.dev) +#define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i)) +#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i)) #define DAI "sound-dai" #define CELL "#sound-dai-cells" -static int rsrc_card_startup(struct snd_pcm_substream *substream) +static int asoc_simple_card_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct asoc_simple_dai *dai_props = - rsrc_priv_to_props(priv, rtd->num); + simple_priv_to_props(priv, rtd->num); return clk_prepare_enable(dai_props->clk); } -static void rsrc_card_shutdown(struct snd_pcm_substream *substream) +static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct asoc_simple_dai *dai_props = - rsrc_priv_to_props(priv, rtd->num); + simple_priv_to_props(priv, rtd->num); clk_disable_unprepare(dai_props->clk); } -static struct snd_soc_ops rsrc_card_ops = { - .startup = rsrc_card_startup, - .shutdown = rsrc_card_shutdown, +static struct snd_soc_ops asoc_simple_card_ops = { + .startup = asoc_simple_card_startup, + .shutdown = asoc_simple_card_shutdown, }; -static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd) +static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) { - struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *dai; struct snd_soc_dai_link *dai_link; struct asoc_simple_dai *dai_props; int num = rtd->num; - dai_link = rsrc_priv_to_link(priv, num); - dai_props = rsrc_priv_to_props(priv, num); + dai_link = simple_priv_to_link(priv, num); + dai_props = simple_priv_to_props(priv, num); dai = dai_link->dynamic ? rtd->cpu_dai : rtd->codec_dai; @@ -94,10 +94,10 @@ static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd) return asoc_simple_card_init_dai(dai, dai_props); } -static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, +static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { - struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, @@ -114,13 +114,13 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } -static int rsrc_card_parse_links(struct device_node *np, - struct rsrc_card_priv *priv, - int idx, bool is_fe) +static int asoc_simple_card_parse_links(struct device_node *np, + struct asoc_simple_card_priv *priv, + int idx, bool is_fe) { - struct device *dev = rsrc_priv_to_dev(priv); - struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); - struct asoc_simple_dai *dai_props = rsrc_priv_to_props(priv, idx); + struct device *dev = simple_priv_to_dev(priv); + struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); + struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, idx); int ret; /* Parse TDM slot */ @@ -161,7 +161,7 @@ static int rsrc_card_parse_links(struct device_node *np, asoc_simple_card_canonicalize_cpu(dai_link, is_single_links); } else { - const struct rsrc_card_of_data *of_data; + const struct asoc_simple_card_of_data *of_data; of_data = of_device_get_match_data(dev); @@ -172,7 +172,7 @@ static int rsrc_card_parse_links(struct device_node *np, /* BE settings */ dai_link->no_pcm = 1; - dai_link->be_hw_params_fixup = rsrc_card_be_hw_params_fixup; + dai_link->be_hw_params_fixup = asoc_simple_card_be_hw_params_fixup; ret = asoc_simple_card_parse_codec(np, dai_link, DAI, CELL); if (ret < 0) @@ -206,8 +206,8 @@ static int rsrc_card_parse_links(struct device_node *np, dai_link->dpcm_playback = 1; dai_link->dpcm_capture = 1; - dai_link->ops = &rsrc_card_ops; - dai_link->init = rsrc_card_dai_init; + dai_link->ops = &asoc_simple_card_ops; + dai_link->init = asoc_simple_card_dai_init; dev_dbg(dev, "\t%s / %04x / %d\n", dai_link->name, @@ -217,10 +217,10 @@ static int rsrc_card_parse_links(struct device_node *np, return 0; } -static int rsrc_card_dai_link_of(struct device_node *node, - struct rsrc_card_priv *priv) +static int asoc_simple_card_dai_link_of(struct device_node *node, + struct asoc_simple_card_priv *priv) { - struct device *dev = rsrc_priv_to_dev(priv); + struct device *dev = simple_priv_to_dev(priv); struct snd_soc_dai_link *dai_link; struct device_node *np; unsigned int daifmt = 0; @@ -230,7 +230,7 @@ static int rsrc_card_dai_link_of(struct device_node *node, /* find 1st codec */ i = 0; for_each_child_of_node(node, np) { - dai_link = rsrc_priv_to_link(priv, i); + dai_link = simple_priv_to_link(priv, i); if (strcmp(np->name, "codec") == 0) { ret = asoc_simple_card_parse_daifmt(dev, node, np, @@ -244,14 +244,14 @@ static int rsrc_card_dai_link_of(struct device_node *node, i = 0; for_each_child_of_node(node, np) { - dai_link = rsrc_priv_to_link(priv, i); + dai_link = simple_priv_to_link(priv, i); dai_link->dai_fmt = daifmt; is_fe = false; if (strcmp(np->name, "cpu") == 0) is_fe = true; - ret = rsrc_card_parse_links(np, priv, i, is_fe); + ret = asoc_simple_card_parse_links(np, priv, i, is_fe); if (ret < 0) return ret; i++; @@ -260,11 +260,11 @@ static int rsrc_card_dai_link_of(struct device_node *node, return 0; } -static int rsrc_card_parse_of(struct device_node *node, - struct rsrc_card_priv *priv, +static int asoc_simple_card_parse_of(struct device_node *node, + struct asoc_simple_card_priv *priv, struct device *dev) { - const struct rsrc_card_of_data *of_data = of_device_get_match_data(dev); + const struct asoc_simple_card_of_data *of_data = of_device_get_match_data(dev); struct asoc_simple_dai *props; struct snd_soc_dai_link *links; int ret; @@ -309,7 +309,7 @@ static int rsrc_card_parse_of(struct device_node *node, dev_dbg(dev, "SRC : convert_rate %d\n", priv->convert_rate); dev_dbg(dev, "CTU : convert_channels %d\n", priv->convert_channels); - ret = rsrc_card_dai_link_of(node, priv); + ret = asoc_simple_card_dai_link_of(node, priv); if (ret < 0) return ret; @@ -320,9 +320,9 @@ static int rsrc_card_parse_of(struct device_node *node, return 0; } -static int rsrc_card_probe(struct platform_device *pdev) +static int asoc_simple_card_probe(struct platform_device *pdev) { - struct rsrc_card_priv *priv; + struct asoc_simple_card_priv *priv; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; int ret; @@ -332,7 +332,7 @@ static int rsrc_card_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - ret = rsrc_card_parse_of(np, priv, dev); + ret = asoc_simple_card_parse_of(np, priv, dev); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret); @@ -350,25 +350,25 @@ err: return ret; } -static int rsrc_card_remove(struct platform_device *pdev) +static int asoc_simple_card_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); return asoc_simple_card_clean_reference(card); } -static struct platform_driver rsrc_card = { +static struct platform_driver asoc_simple_card = { .driver = { .name = "renesas-src-audio-card", - .of_match_table = rsrc_card_of_match, + .of_match_table = asoc_simple_card_of_match, }, - .probe = rsrc_card_probe, - .remove = rsrc_card_remove, + .probe = asoc_simple_card_probe, + .remove = asoc_simple_card_remove, }; -module_platform_driver(rsrc_card); +module_platform_driver(asoc_simple_card); -MODULE_ALIAS("platform:renesas-src-audio-card"); +MODULE_ALIAS("platform:asoc-simple-scu-card"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Renesas Sampling Rate Convert Sound Card"); +MODULE_DESCRIPTION("ASoC Simple SCU Sound Card"); MODULE_AUTHOR("Kuninori Morimoto "); -- cgit v0.10.2 From 64df0e6842925311d74f6944710495981d5a0ace Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 23 Aug 2016 01:34:43 +0000 Subject: ASoC: rsrc-card: rename rsrc-card to simple-scu-card phase2 rsrc-card which is using DPCM feature was created for Renesas sound. But not only Renesas, but many SoC can use this driver, because it is based on simple-card driver. To use it as more open driver, rsrc-card will be renamed to simple-scu-card. In order to easy patch review, as 2nd step, this patch adds new compatible "simple-scu-audio-card"; rcar-card used specific property, not "simple-audio-card", but it should be now. Actually, rsrc-card is upstreamed driver, but noone is using it on upstream. The user is only local, and it is only me. Thus, there is no compatible break by this patch. This patch uses "simple-audio-card" prefix. And it removes rcar-card specifix compatible too. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt index f148bf2..ecb4a24 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt @@ -1,35 +1,36 @@ -Renesas Sampling Rate Convert Sound Card: +ASoC simple SCU Sound Card -Renesas Sampling Rate Convert Sound Card specifies audio DAI connections of SoC <-> codec. +Simple-Card specifies audio DAI connections of SoC <-> codec. Required properties: -- compatible : "renesas,rsrc-card" +- compatible : "simple-scu-audio-card" + "renesas,rsrc-card" Optional properties: -- card_name : User specified audio sound card name, one string +- simple-audio-card,name : User specified audio sound card name, one string property. -- cpu : CPU sub-node -- codec : CODEC sub-node +- simple-audio-card,cpu : CPU sub-node +- simple-audio-card,codec : CODEC sub-node Optional subnode properties: -- format : CPU/CODEC common audio format. +- simple-audio-card,format : CPU/CODEC common audio format. "i2s", "right_j", "left_j" , "dsp_a" "dsp_b", "ac97", "pdm", "msb", "lsb" -- frame-master : Indicates dai-link frame master. +- simple-audio-card,frame-master : Indicates dai-link frame master. phandle to a cpu or codec subnode. -- bitclock-master : Indicates dai-link bit clock master. +- simple-audio-card,bitclock-master : Indicates dai-link bit clock master. phandle to a cpu or codec subnode. -- bitclock-inversion : bool property. Add this if the +- simple-audio-card,bitclock-inversion : bool property. Add this if the dai-link uses bit clock inversion. -- frame-inversion : bool property. Add this if the +- simple-audio-card,frame-inversion : bool property. Add this if the dai-link uses frame clock inversion. -- convert-rate : platform specified sampling rate convert -- convert-channels : platform specified converted channel size (2 - 8 ch) -- audio-prefix : see audio-routing -- audio-routing : A list of the connections between audio components. +- simple-audio-card,convert-rate : platform specified sampling rate convert +- simple-audio-card,convert-channels : platform specified converted channel size (2 - 8 ch) +- simple-audio-card,prefix : see audio-routing +- simple-audio-card,routing : A list of the connections between audio components. Each entry is a pair of strings, the first being the connection's sink, the second being the connection's source. Valid names for sources. use audio-prefix if some components is using same sink/sources naming. @@ -54,18 +55,25 @@ Optional CPU/CODEC subnodes properties: Example sound { - compatible = "renesas,rsrc-card,lager"; + compatible = "simple-scu-audio-card"; - card-name = "rsnd-ak4643"; - format = "left_j"; - bitclock-master = <&sndcodec>; - frame-master = <&sndcodec>; + simple-audio-card,name = "rsnd-ak4643"; + simple-audio-card,format = "left_j"; + simple-audio-card,format = "left_j"; + simple-audio-card,bitclock-master = <&sndcodec>; + simple-audio-card,frame-master = <&sndcodec>; - sndcpu: cpu { + simple-audio-card,convert-rate = <48000>; /* see audio_clk_a */ + + simple-audio-card,prefix = "ak4642"; + simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", + "DAI0 Capture", "ak4642 Capture"; + + sndcpu: simple-audio-card,cpu { sound-dai = <&rcar_sound>; }; - sndcodec: codec { + sndcodec: simple-audio-card,codec { sound-dai = <&ak4643>; system-clock-frequency = <11289600>; }; diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index a0d0f36..3fa1908 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -30,6 +30,7 @@ struct asoc_simple_card_of_data { static const struct of_device_id asoc_simple_card_of_match[] = { { .compatible = "renesas,rsrc-card", }, + { .compatible = "simple-scu-audio-card", }, {}, }; MODULE_DEVICE_TABLE(of, asoc_simple_card_of_match); @@ -51,6 +52,7 @@ struct asoc_simple_card_priv { #define DAI "sound-dai" #define CELL "#sound-dai-cells" +#define PREFIX "simple-audio-card," static int asoc_simple_card_startup(struct snd_pcm_substream *substream) { @@ -161,10 +163,6 @@ static int asoc_simple_card_parse_links(struct device_node *np, asoc_simple_card_canonicalize_cpu(dai_link, is_single_links); } else { - const struct asoc_simple_card_of_data *of_data; - - of_data = of_device_get_match_data(dev); - /* FE is dummy */ dai_link->cpu_of_node = NULL; dai_link->cpu_dai_name = "snd-soc-dummy-dai"; @@ -188,16 +186,10 @@ static int asoc_simple_card_parse_links(struct device_node *np, if (ret < 0) return ret; - /* additional name prefix */ - if (of_data) { - priv->codec_conf.of_node = dai_link->codec_of_node; - priv->codec_conf.name_prefix = of_data->prefix; - } else { - snd_soc_of_parse_audio_prefix(&priv->snd_card, - &priv->codec_conf, - dai_link->codec_of_node, - "audio-prefix"); - } + snd_soc_of_parse_audio_prefix(&priv->snd_card, + &priv->codec_conf, + dai_link->codec_of_node, + PREFIX "prefix"); } ret = asoc_simple_card_canonicalize_dailink(dai_link); @@ -232,9 +224,9 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, for_each_child_of_node(node, np) { dai_link = simple_priv_to_link(priv, i); - if (strcmp(np->name, "codec") == 0) { + if (strcmp(np->name, PREFIX "codec") == 0) { ret = asoc_simple_card_parse_daifmt(dev, node, np, - NULL, &daifmt); + PREFIX, &daifmt); if (ret < 0) return ret; break; @@ -248,7 +240,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, dai_link->dai_fmt = daifmt; is_fe = false; - if (strcmp(np->name, "cpu") == 0) + if (strcmp(np->name, PREFIX "cpu") == 0) is_fe = true; ret = asoc_simple_card_parse_links(np, priv, i, is_fe); @@ -264,7 +256,6 @@ static int asoc_simple_card_parse_of(struct device_node *node, struct asoc_simple_card_priv *priv, struct device *dev) { - const struct asoc_simple_card_of_data *of_data = of_device_get_match_data(dev); struct asoc_simple_dai *props; struct snd_soc_dai_link *links; int ret; @@ -290,33 +281,29 @@ static int asoc_simple_card_parse_of(struct device_node *node, priv->snd_card.codec_conf = &priv->codec_conf; priv->snd_card.num_configs = 1; - if (of_data) { - priv->snd_card.of_dapm_routes = of_data->routes; - priv->snd_card.num_of_dapm_routes = of_data->num_routes; - } else { - snd_soc_of_parse_audio_routing(&priv->snd_card, - "audio-routing"); - } + ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing"); + if (ret < 0) + return ret; /* sampling rate convert */ - of_property_read_u32(node, "convert-rate", &priv->convert_rate); + of_property_read_u32(node, PREFIX "convert-rate", &priv->convert_rate); /* channels transfer */ - of_property_read_u32(node, "convert-channels", &priv->convert_channels); - - dev_dbg(dev, "New rsrc-audio-card: %s\n", - priv->snd_card.name ? priv->snd_card.name : ""); - dev_dbg(dev, "SRC : convert_rate %d\n", priv->convert_rate); - dev_dbg(dev, "CTU : convert_channels %d\n", priv->convert_channels); + of_property_read_u32(node, PREFIX "convert-channels", &priv->convert_channels); ret = asoc_simple_card_dai_link_of(node, priv); if (ret < 0) return ret; - ret = asoc_simple_card_parse_card_name(&priv->snd_card, "card-"); + ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX); if (ret < 0) return ret; + dev_dbg(dev, "New card: %s\n", + priv->snd_card.name ? priv->snd_card.name : ""); + dev_dbg(dev, "convert_rate %d\n", priv->convert_rate); + dev_dbg(dev, "convert_channels %d\n", priv->convert_channels); + return 0; } @@ -359,7 +346,7 @@ static int asoc_simple_card_remove(struct platform_device *pdev) static struct platform_driver asoc_simple_card = { .driver = { - .name = "renesas-src-audio-card", + .name = "simple-scu-audio-card", .of_match_table = asoc_simple_card_of_match, }, .probe = asoc_simple_card_probe, -- cgit v0.10.2 From d12c6216c4a58f9fd2a58bc489783a095d84b2fc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 23 Aug 2016 01:35:02 +0000 Subject: ASoC: rsrc-card: rename rsrc-card to simple-scu-card phase3 rsrc-card which is using DPCM feature was created for Renesas sound. But not only Renesas, but many SoC can use this driver, because it is based on simple-card driver. To use it as more open driver, rsrc-card will be renamed to simple-scu-card. In order to easy patch review, as 3rd step, this patch moves rsrc-card driver to generic folder. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt deleted file mode 100644 index ecb4a24..0000000 --- a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt +++ /dev/null @@ -1,80 +0,0 @@ -ASoC simple SCU Sound Card - -Simple-Card specifies audio DAI connections of SoC <-> codec. - -Required properties: - -- compatible : "simple-scu-audio-card" - "renesas,rsrc-card" - -Optional properties: - -- simple-audio-card,name : User specified audio sound card name, one string - property. -- simple-audio-card,cpu : CPU sub-node -- simple-audio-card,codec : CODEC sub-node - -Optional subnode properties: - -- simple-audio-card,format : CPU/CODEC common audio format. - "i2s", "right_j", "left_j" , "dsp_a" - "dsp_b", "ac97", "pdm", "msb", "lsb" -- simple-audio-card,frame-master : Indicates dai-link frame master. - phandle to a cpu or codec subnode. -- simple-audio-card,bitclock-master : Indicates dai-link bit clock master. - phandle to a cpu or codec subnode. -- simple-audio-card,bitclock-inversion : bool property. Add this if the - dai-link uses bit clock inversion. -- simple-audio-card,frame-inversion : bool property. Add this if the - dai-link uses frame clock inversion. -- simple-audio-card,convert-rate : platform specified sampling rate convert -- simple-audio-card,convert-channels : platform specified converted channel size (2 - 8 ch) -- simple-audio-card,prefix : see audio-routing -- simple-audio-card,routing : A list of the connections between audio components. - Each entry is a pair of strings, the first being the connection's sink, - the second being the connection's source. Valid names for sources. - use audio-prefix if some components is using same sink/sources naming. - it can be used if compatible was "renesas,rsrc-card"; - -Required CPU/CODEC subnodes properties: - -- sound-dai : phandle and port of CPU/CODEC - -Optional CPU/CODEC subnodes properties: - -- clocks / system-clock-frequency : specify subnode's clock if needed. - it can be specified via "clocks" if system has - clock node (= common clock), or "system-clock-frequency" - (if system doens't support common clock) - If a clock is specified, it is - enabled with clk_prepare_enable() - in dai startup() and disabled with - clk_disable_unprepare() in dai - shutdown(). - -Example - -sound { - compatible = "simple-scu-audio-card"; - - simple-audio-card,name = "rsnd-ak4643"; - simple-audio-card,format = "left_j"; - simple-audio-card,format = "left_j"; - simple-audio-card,bitclock-master = <&sndcodec>; - simple-audio-card,frame-master = <&sndcodec>; - - simple-audio-card,convert-rate = <48000>; /* see audio_clk_a */ - - simple-audio-card,prefix = "ak4642"; - simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", - "DAI0 Capture", "ak4642 Capture"; - - sndcpu: simple-audio-card,cpu { - sound-dai = <&rcar_sound>; - }; - - sndcodec: simple-audio-card,codec { - sound-dai = <&ak4643>; - system-clock-frequency = <11289600>; - }; -}; diff --git a/Documentation/devicetree/bindings/sound/simple-scu-card.txt b/Documentation/devicetree/bindings/sound/simple-scu-card.txt new file mode 100644 index 0000000..ecb4a24 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/simple-scu-card.txt @@ -0,0 +1,80 @@ +ASoC simple SCU Sound Card + +Simple-Card specifies audio DAI connections of SoC <-> codec. + +Required properties: + +- compatible : "simple-scu-audio-card" + "renesas,rsrc-card" + +Optional properties: + +- simple-audio-card,name : User specified audio sound card name, one string + property. +- simple-audio-card,cpu : CPU sub-node +- simple-audio-card,codec : CODEC sub-node + +Optional subnode properties: + +- simple-audio-card,format : CPU/CODEC common audio format. + "i2s", "right_j", "left_j" , "dsp_a" + "dsp_b", "ac97", "pdm", "msb", "lsb" +- simple-audio-card,frame-master : Indicates dai-link frame master. + phandle to a cpu or codec subnode. +- simple-audio-card,bitclock-master : Indicates dai-link bit clock master. + phandle to a cpu or codec subnode. +- simple-audio-card,bitclock-inversion : bool property. Add this if the + dai-link uses bit clock inversion. +- simple-audio-card,frame-inversion : bool property. Add this if the + dai-link uses frame clock inversion. +- simple-audio-card,convert-rate : platform specified sampling rate convert +- simple-audio-card,convert-channels : platform specified converted channel size (2 - 8 ch) +- simple-audio-card,prefix : see audio-routing +- simple-audio-card,routing : A list of the connections between audio components. + Each entry is a pair of strings, the first being the connection's sink, + the second being the connection's source. Valid names for sources. + use audio-prefix if some components is using same sink/sources naming. + it can be used if compatible was "renesas,rsrc-card"; + +Required CPU/CODEC subnodes properties: + +- sound-dai : phandle and port of CPU/CODEC + +Optional CPU/CODEC subnodes properties: + +- clocks / system-clock-frequency : specify subnode's clock if needed. + it can be specified via "clocks" if system has + clock node (= common clock), or "system-clock-frequency" + (if system doens't support common clock) + If a clock is specified, it is + enabled with clk_prepare_enable() + in dai startup() and disabled with + clk_disable_unprepare() in dai + shutdown(). + +Example + +sound { + compatible = "simple-scu-audio-card"; + + simple-audio-card,name = "rsnd-ak4643"; + simple-audio-card,format = "left_j"; + simple-audio-card,format = "left_j"; + simple-audio-card,bitclock-master = <&sndcodec>; + simple-audio-card,frame-master = <&sndcodec>; + + simple-audio-card,convert-rate = <48000>; /* see audio_clk_a */ + + simple-audio-card,prefix = "ak4642"; + simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", + "DAI0 Capture", "ak4642 Capture"; + + sndcpu: simple-audio-card,cpu { + sound-dai = <&rcar_sound>; + }; + + sndcodec: simple-audio-card,codec { + sound-dai = <&ak4643>; + system-clock-frequency = <11289600>; + }; +}; diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig index c01c5dd..2d0ff03 100644 --- a/sound/soc/generic/Kconfig +++ b/sound/soc/generic/Kconfig @@ -6,3 +6,10 @@ config SND_SIMPLE_CARD select SND_SIMPLE_CARD_UTILS help This option enables generic simple sound card support + +config SND_SIMPLE_SCU_CARD + tristate "ASoC Simple SCU sound card support" + select SND_SIMPLE_CARD_UTILS + help + This option enables generic simple SCU sound card support. + It supports DPCM of multi CPU single Codec ststem. diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile index 2d53c8d..ee750f3 100644 --- a/sound/soc/generic/Makefile +++ b/sound/soc/generic/Makefile @@ -1,5 +1,7 @@ snd-soc-simple-card-utils-objs := simple-card-utils.o snd-soc-simple-card-objs := simple-card.o +snd-soc-simple-scu-card-objs := simple-scu-card.o obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o +obj-$(CONFIG_SND_SIMPLE_SCU_CARD) += snd-soc-simple-scu-card.o diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c new file mode 100644 index 0000000..3fa1908 --- /dev/null +++ b/sound/soc/generic/simple-scu-card.c @@ -0,0 +1,361 @@ +/* + * ASoC simple SCU sound card support + * + * Copyright (C) 2015 Renesas Solutions Corp. + * Kuninori Morimoto + * + * based on ${LINUX}/sound/soc/generic/simple-card.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct asoc_simple_card_of_data { + const char *prefix; + const struct snd_soc_dapm_route *routes; + int num_routes; +}; + +static const struct of_device_id asoc_simple_card_of_match[] = { + { .compatible = "renesas,rsrc-card", }, + { .compatible = "simple-scu-audio-card", }, + {}, +}; +MODULE_DEVICE_TABLE(of, asoc_simple_card_of_match); + +#define IDX_CPU 0 +#define IDX_CODEC 1 +struct asoc_simple_card_priv { + struct snd_soc_card snd_card; + struct snd_soc_codec_conf codec_conf; + struct asoc_simple_dai *dai_props; + struct snd_soc_dai_link *dai_link; + u32 convert_rate; + u32 convert_channels; +}; + +#define simple_priv_to_dev(priv) ((priv)->snd_card.dev) +#define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i)) +#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i)) + +#define DAI "sound-dai" +#define CELL "#sound-dai-cells" +#define PREFIX "simple-audio-card," + +static int asoc_simple_card_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct asoc_simple_dai *dai_props = + simple_priv_to_props(priv, rtd->num); + + return clk_prepare_enable(dai_props->clk); +} + +static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct asoc_simple_dai *dai_props = + simple_priv_to_props(priv, rtd->num); + + clk_disable_unprepare(dai_props->clk); +} + +static struct snd_soc_ops asoc_simple_card_ops = { + .startup = asoc_simple_card_startup, + .shutdown = asoc_simple_card_shutdown, +}; + +static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) +{ + struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_dai *dai; + struct snd_soc_dai_link *dai_link; + struct asoc_simple_dai *dai_props; + int num = rtd->num; + + dai_link = simple_priv_to_link(priv, num); + dai_props = simple_priv_to_props(priv, num); + dai = dai_link->dynamic ? + rtd->cpu_dai : + rtd->codec_dai; + + return asoc_simple_card_init_dai(dai, dai_props); +} + +static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct snd_interval *rate = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + + if (priv->convert_rate) + rate->min = + rate->max = priv->convert_rate; + + if (priv->convert_channels) + channels->min = + channels->max = priv->convert_channels; + + return 0; +} + +static int asoc_simple_card_parse_links(struct device_node *np, + struct asoc_simple_card_priv *priv, + int idx, bool is_fe) +{ + struct device *dev = simple_priv_to_dev(priv); + struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); + struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, idx); + int ret; + + /* Parse TDM slot */ + ret = snd_soc_of_parse_tdm_slot(np, + &dai_props->tx_slot_mask, + &dai_props->rx_slot_mask, + &dai_props->slots, + &dai_props->slot_width); + if (ret) + return ret; + + if (is_fe) { + int is_single_links = 0; + + /* BE is dummy */ + dai_link->codec_of_node = NULL; + dai_link->codec_dai_name = "snd-soc-dummy-dai"; + dai_link->codec_name = "snd-soc-dummy"; + + /* FE settings */ + dai_link->dynamic = 1; + dai_link->dpcm_merged_format = 1; + + ret = asoc_simple_card_parse_cpu(np, dai_link, DAI, CELL, + &is_single_links); + if (ret) + return ret; + + ret = asoc_simple_card_parse_clk_cpu(np, dai_link, dai_props); + if (ret < 0) + return ret; + + ret = asoc_simple_card_set_dailink_name(dev, dai_link, + "fe.%s", + dai_link->cpu_dai_name); + if (ret < 0) + return ret; + + asoc_simple_card_canonicalize_cpu(dai_link, is_single_links); + } else { + /* FE is dummy */ + dai_link->cpu_of_node = NULL; + dai_link->cpu_dai_name = "snd-soc-dummy-dai"; + dai_link->cpu_name = "snd-soc-dummy"; + + /* BE settings */ + dai_link->no_pcm = 1; + dai_link->be_hw_params_fixup = asoc_simple_card_be_hw_params_fixup; + + ret = asoc_simple_card_parse_codec(np, dai_link, DAI, CELL); + if (ret < 0) + return ret; + + ret = asoc_simple_card_parse_clk_codec(np, dai_link, dai_props); + if (ret < 0) + return ret; + + ret = asoc_simple_card_set_dailink_name(dev, dai_link, + "be.%s", + dai_link->codec_dai_name); + if (ret < 0) + return ret; + + snd_soc_of_parse_audio_prefix(&priv->snd_card, + &priv->codec_conf, + dai_link->codec_of_node, + PREFIX "prefix"); + } + + ret = asoc_simple_card_canonicalize_dailink(dai_link); + if (ret < 0) + return ret; + + dai_link->dpcm_playback = 1; + dai_link->dpcm_capture = 1; + dai_link->ops = &asoc_simple_card_ops; + dai_link->init = asoc_simple_card_dai_init; + + dev_dbg(dev, "\t%s / %04x / %d\n", + dai_link->name, + dai_link->dai_fmt, + dai_props->sysclk); + + return 0; +} + +static int asoc_simple_card_dai_link_of(struct device_node *node, + struct asoc_simple_card_priv *priv) +{ + struct device *dev = simple_priv_to_dev(priv); + struct snd_soc_dai_link *dai_link; + struct device_node *np; + unsigned int daifmt = 0; + int ret, i; + bool is_fe; + + /* find 1st codec */ + i = 0; + for_each_child_of_node(node, np) { + dai_link = simple_priv_to_link(priv, i); + + if (strcmp(np->name, PREFIX "codec") == 0) { + ret = asoc_simple_card_parse_daifmt(dev, node, np, + PREFIX, &daifmt); + if (ret < 0) + return ret; + break; + } + i++; + } + + i = 0; + for_each_child_of_node(node, np) { + dai_link = simple_priv_to_link(priv, i); + dai_link->dai_fmt = daifmt; + + is_fe = false; + if (strcmp(np->name, PREFIX "cpu") == 0) + is_fe = true; + + ret = asoc_simple_card_parse_links(np, priv, i, is_fe); + if (ret < 0) + return ret; + i++; + } + + return 0; +} + +static int asoc_simple_card_parse_of(struct device_node *node, + struct asoc_simple_card_priv *priv, + struct device *dev) +{ + struct asoc_simple_dai *props; + struct snd_soc_dai_link *links; + int ret; + int num; + + if (!node) + return -EINVAL; + + num = of_get_child_count(node); + props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL); + links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL); + if (!props || !links) + return -ENOMEM; + + priv->dai_props = props; + priv->dai_link = links; + + /* Init snd_soc_card */ + priv->snd_card.owner = THIS_MODULE; + priv->snd_card.dev = dev; + priv->snd_card.dai_link = priv->dai_link; + priv->snd_card.num_links = num; + priv->snd_card.codec_conf = &priv->codec_conf; + priv->snd_card.num_configs = 1; + + ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing"); + if (ret < 0) + return ret; + + /* sampling rate convert */ + of_property_read_u32(node, PREFIX "convert-rate", &priv->convert_rate); + + /* channels transfer */ + of_property_read_u32(node, PREFIX "convert-channels", &priv->convert_channels); + + ret = asoc_simple_card_dai_link_of(node, priv); + if (ret < 0) + return ret; + + ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX); + if (ret < 0) + return ret; + + dev_dbg(dev, "New card: %s\n", + priv->snd_card.name ? priv->snd_card.name : ""); + dev_dbg(dev, "convert_rate %d\n", priv->convert_rate); + dev_dbg(dev, "convert_channels %d\n", priv->convert_channels); + + return 0; +} + +static int asoc_simple_card_probe(struct platform_device *pdev) +{ + struct asoc_simple_card_priv *priv; + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + int ret; + + /* Allocate the private data */ + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ret = asoc_simple_card_parse_of(np, priv, dev); + if (ret < 0) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "parse error %d\n", ret); + goto err; + } + + snd_soc_card_set_drvdata(&priv->snd_card, priv); + + ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); + if (ret >= 0) + return ret; +err: + asoc_simple_card_clean_reference(&priv->snd_card); + + return ret; +} + +static int asoc_simple_card_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + return asoc_simple_card_clean_reference(card); +} + +static struct platform_driver asoc_simple_card = { + .driver = { + .name = "simple-scu-audio-card", + .of_match_table = asoc_simple_card_of_match, + }, + .probe = asoc_simple_card_probe, + .remove = asoc_simple_card_remove, +}; + +module_platform_driver(asoc_simple_card); + +MODULE_ALIAS("platform:asoc-simple-scu-card"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ASoC Simple SCU Sound Card"); +MODULE_AUTHOR("Kuninori Morimoto "); diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 9311f11..6db6405 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -42,12 +42,6 @@ config SND_SOC_RCAR help This option enables R-Car SRU/SCU/SSIU/SSI sound support -config SND_SOC_RSRC_CARD - tristate "Renesas Sampling Rate Convert Sound Card" - select SND_SIMPLE_CARD_UTILS - help - This option enables simple sound if you need sampling rate convert - ## ## Boards ## diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile index a89ddf7..9c3d5ae 100644 --- a/sound/soc/sh/rcar/Makefile +++ b/sound/soc/sh/rcar/Makefile @@ -1,5 +1,2 @@ snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o ssiu.o src.o ctu.o mix.o dvc.o cmd.o obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o - -snd-soc-rsrc-card-objs := rsrc-card.o -obj-$(CONFIG_SND_SOC_RSRC_CARD) += snd-soc-rsrc-card.o diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c deleted file mode 100644 index 3fa1908..0000000 --- a/sound/soc/sh/rcar/rsrc-card.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * ASoC simple SCU sound card support - * - * Copyright (C) 2015 Renesas Solutions Corp. - * Kuninori Morimoto - * - * based on ${LINUX}/sound/soc/generic/simple-card.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct asoc_simple_card_of_data { - const char *prefix; - const struct snd_soc_dapm_route *routes; - int num_routes; -}; - -static const struct of_device_id asoc_simple_card_of_match[] = { - { .compatible = "renesas,rsrc-card", }, - { .compatible = "simple-scu-audio-card", }, - {}, -}; -MODULE_DEVICE_TABLE(of, asoc_simple_card_of_match); - -#define IDX_CPU 0 -#define IDX_CODEC 1 -struct asoc_simple_card_priv { - struct snd_soc_card snd_card; - struct snd_soc_codec_conf codec_conf; - struct asoc_simple_dai *dai_props; - struct snd_soc_dai_link *dai_link; - u32 convert_rate; - u32 convert_channels; -}; - -#define simple_priv_to_dev(priv) ((priv)->snd_card.dev) -#define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i)) -#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i)) - -#define DAI "sound-dai" -#define CELL "#sound-dai-cells" -#define PREFIX "simple-audio-card," - -static int asoc_simple_card_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct asoc_simple_dai *dai_props = - simple_priv_to_props(priv, rtd->num); - - return clk_prepare_enable(dai_props->clk); -} - -static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct asoc_simple_dai *dai_props = - simple_priv_to_props(priv, rtd->num); - - clk_disable_unprepare(dai_props->clk); -} - -static struct snd_soc_ops asoc_simple_card_ops = { - .startup = asoc_simple_card_startup, - .shutdown = asoc_simple_card_shutdown, -}; - -static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) -{ - struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai; - struct snd_soc_dai_link *dai_link; - struct asoc_simple_dai *dai_props; - int num = rtd->num; - - dai_link = simple_priv_to_link(priv, num); - dai_props = simple_priv_to_props(priv, num); - dai = dai_link->dynamic ? - rtd->cpu_dai : - rtd->codec_dai; - - return asoc_simple_card_init_dai(dai, dai_props); -} - -static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - - if (priv->convert_rate) - rate->min = - rate->max = priv->convert_rate; - - if (priv->convert_channels) - channels->min = - channels->max = priv->convert_channels; - - return 0; -} - -static int asoc_simple_card_parse_links(struct device_node *np, - struct asoc_simple_card_priv *priv, - int idx, bool is_fe) -{ - struct device *dev = simple_priv_to_dev(priv); - struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); - struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, idx); - int ret; - - /* Parse TDM slot */ - ret = snd_soc_of_parse_tdm_slot(np, - &dai_props->tx_slot_mask, - &dai_props->rx_slot_mask, - &dai_props->slots, - &dai_props->slot_width); - if (ret) - return ret; - - if (is_fe) { - int is_single_links = 0; - - /* BE is dummy */ - dai_link->codec_of_node = NULL; - dai_link->codec_dai_name = "snd-soc-dummy-dai"; - dai_link->codec_name = "snd-soc-dummy"; - - /* FE settings */ - dai_link->dynamic = 1; - dai_link->dpcm_merged_format = 1; - - ret = asoc_simple_card_parse_cpu(np, dai_link, DAI, CELL, - &is_single_links); - if (ret) - return ret; - - ret = asoc_simple_card_parse_clk_cpu(np, dai_link, dai_props); - if (ret < 0) - return ret; - - ret = asoc_simple_card_set_dailink_name(dev, dai_link, - "fe.%s", - dai_link->cpu_dai_name); - if (ret < 0) - return ret; - - asoc_simple_card_canonicalize_cpu(dai_link, is_single_links); - } else { - /* FE is dummy */ - dai_link->cpu_of_node = NULL; - dai_link->cpu_dai_name = "snd-soc-dummy-dai"; - dai_link->cpu_name = "snd-soc-dummy"; - - /* BE settings */ - dai_link->no_pcm = 1; - dai_link->be_hw_params_fixup = asoc_simple_card_be_hw_params_fixup; - - ret = asoc_simple_card_parse_codec(np, dai_link, DAI, CELL); - if (ret < 0) - return ret; - - ret = asoc_simple_card_parse_clk_codec(np, dai_link, dai_props); - if (ret < 0) - return ret; - - ret = asoc_simple_card_set_dailink_name(dev, dai_link, - "be.%s", - dai_link->codec_dai_name); - if (ret < 0) - return ret; - - snd_soc_of_parse_audio_prefix(&priv->snd_card, - &priv->codec_conf, - dai_link->codec_of_node, - PREFIX "prefix"); - } - - ret = asoc_simple_card_canonicalize_dailink(dai_link); - if (ret < 0) - return ret; - - dai_link->dpcm_playback = 1; - dai_link->dpcm_capture = 1; - dai_link->ops = &asoc_simple_card_ops; - dai_link->init = asoc_simple_card_dai_init; - - dev_dbg(dev, "\t%s / %04x / %d\n", - dai_link->name, - dai_link->dai_fmt, - dai_props->sysclk); - - return 0; -} - -static int asoc_simple_card_dai_link_of(struct device_node *node, - struct asoc_simple_card_priv *priv) -{ - struct device *dev = simple_priv_to_dev(priv); - struct snd_soc_dai_link *dai_link; - struct device_node *np; - unsigned int daifmt = 0; - int ret, i; - bool is_fe; - - /* find 1st codec */ - i = 0; - for_each_child_of_node(node, np) { - dai_link = simple_priv_to_link(priv, i); - - if (strcmp(np->name, PREFIX "codec") == 0) { - ret = asoc_simple_card_parse_daifmt(dev, node, np, - PREFIX, &daifmt); - if (ret < 0) - return ret; - break; - } - i++; - } - - i = 0; - for_each_child_of_node(node, np) { - dai_link = simple_priv_to_link(priv, i); - dai_link->dai_fmt = daifmt; - - is_fe = false; - if (strcmp(np->name, PREFIX "cpu") == 0) - is_fe = true; - - ret = asoc_simple_card_parse_links(np, priv, i, is_fe); - if (ret < 0) - return ret; - i++; - } - - return 0; -} - -static int asoc_simple_card_parse_of(struct device_node *node, - struct asoc_simple_card_priv *priv, - struct device *dev) -{ - struct asoc_simple_dai *props; - struct snd_soc_dai_link *links; - int ret; - int num; - - if (!node) - return -EINVAL; - - num = of_get_child_count(node); - props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL); - links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL); - if (!props || !links) - return -ENOMEM; - - priv->dai_props = props; - priv->dai_link = links; - - /* Init snd_soc_card */ - priv->snd_card.owner = THIS_MODULE; - priv->snd_card.dev = dev; - priv->snd_card.dai_link = priv->dai_link; - priv->snd_card.num_links = num; - priv->snd_card.codec_conf = &priv->codec_conf; - priv->snd_card.num_configs = 1; - - ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing"); - if (ret < 0) - return ret; - - /* sampling rate convert */ - of_property_read_u32(node, PREFIX "convert-rate", &priv->convert_rate); - - /* channels transfer */ - of_property_read_u32(node, PREFIX "convert-channels", &priv->convert_channels); - - ret = asoc_simple_card_dai_link_of(node, priv); - if (ret < 0) - return ret; - - ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX); - if (ret < 0) - return ret; - - dev_dbg(dev, "New card: %s\n", - priv->snd_card.name ? priv->snd_card.name : ""); - dev_dbg(dev, "convert_rate %d\n", priv->convert_rate); - dev_dbg(dev, "convert_channels %d\n", priv->convert_channels); - - return 0; -} - -static int asoc_simple_card_probe(struct platform_device *pdev) -{ - struct asoc_simple_card_priv *priv; - struct device_node *np = pdev->dev.of_node; - struct device *dev = &pdev->dev; - int ret; - - /* Allocate the private data */ - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - ret = asoc_simple_card_parse_of(np, priv, dev); - if (ret < 0) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "parse error %d\n", ret); - goto err; - } - - snd_soc_card_set_drvdata(&priv->snd_card, priv); - - ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); - if (ret >= 0) - return ret; -err: - asoc_simple_card_clean_reference(&priv->snd_card); - - return ret; -} - -static int asoc_simple_card_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - return asoc_simple_card_clean_reference(card); -} - -static struct platform_driver asoc_simple_card = { - .driver = { - .name = "simple-scu-audio-card", - .of_match_table = asoc_simple_card_of_match, - }, - .probe = asoc_simple_card_probe, - .remove = asoc_simple_card_remove, -}; - -module_platform_driver(asoc_simple_card); - -MODULE_ALIAS("platform:asoc-simple-scu-card"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("ASoC Simple SCU Sound Card"); -MODULE_AUTHOR("Kuninori Morimoto "); -- cgit v0.10.2 From fd61576fdda88c9677f9ea62e6f32997ce39daea Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 23 Aug 2016 15:16:42 +0000 Subject: ASoC: samsung: i2s: Add missing clk_disable_unprepare() on error in samsung_i2s_probe() Add the missing clk_disable_unprepare() before return from samsung_i2s_probe() in the error handling case. Signed-off-by: Wei Yongjun Acked-by: Sylwester Nawrocki Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index fa3ff03..7e32cf4 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1318,7 +1318,8 @@ static int samsung_i2s_probe(struct platform_device *pdev) sec_dai = i2s_alloc_dai(pdev, true); if (!sec_dai) { dev_err(&pdev->dev, "Unable to alloc I2S_sec\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err_disable_clk; } sec_dai->lock = &pri_dai->spinlock; @@ -1342,7 +1343,8 @@ static int samsung_i2s_probe(struct platform_device *pdev) if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { dev_err(&pdev->dev, "Unable to configure gpio\n"); - return -EINVAL; + ret = -EINVAL; + goto err_disable_clk; } ret = devm_snd_soc_register_component(&pri_dai->pdev->dev, @@ -1366,6 +1368,8 @@ static int samsung_i2s_probe(struct platform_device *pdev) err_free_dai: if (sec_dai) i2s_free_sec_dai(sec_dai); +err_disable_clk: + clk_disable_unprepare(pri_dai->clk); return ret; } -- cgit v0.10.2 From df6a886611935f8155e16ded9a7aa63b18b98f7e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 24 Aug 2016 21:42:42 +0900 Subject: ALSA: bebob: rename file with vendor-dependent code so that it's for Yamaha/Terratec Once Yamaha and Terratec cooperated to develop some audio and music units on IEEE 1394 bus. On these models, the same embedded board is used, and similar configurations are also applied. This commit renames file for Yamaha's configuration so that it's for both of Yamaha and Terratec. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/sound/firewire/bebob/Makefile b/sound/firewire/bebob/Makefile index af7ed66..dd45486 100644 --- a/sound/firewire/bebob/Makefile +++ b/sound/firewire/bebob/Makefile @@ -1,4 +1,5 @@ snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o bebob_midi.o \ - bebob_pcm.o bebob_hwdep.o bebob_terratec.o bebob_yamaha.o \ - bebob_focusrite.o bebob_maudio.o bebob.o + bebob_pcm.o bebob_hwdep.o bebob_terratec.o \ + bebob_yamaha_terratec.o bebob_focusrite.o bebob_maudio.o \ + bebob.o obj-$(CONFIG_SND_BEBOB) += snd-bebob.o diff --git a/sound/firewire/bebob/bebob_yamaha.c b/sound/firewire/bebob/bebob_yamaha.c deleted file mode 100644 index 90d4404..0000000 --- a/sound/firewire/bebob/bebob_yamaha.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * bebob_yamaha.c - a part of driver for BeBoB based devices - * - * Copyright (c) 2013-2014 Takashi Sakamoto - * - * Licensed under the terms of the GNU General Public License, version 2. - */ - -#include "./bebob.h" - -/* - * NOTE: - * Yamaha GO44 is not designed to be used as stand-alone mixer. So any streams - * must be accompanied. If changing the state, a LED on the device starts to - * blink and its sync status is false. In this state, the device sounds nothing - * even if streaming. To start streaming at the current sampling rate is only - * way to revocer this state. GO46 is better for stand-alone mixer. - * - * Both of them have a capability to change its sampling rate up to 192.0kHz. - * At 192.0kHz, the device reports 4 PCM-in, 1 MIDI-in, 6 PCM-out, 1 MIDI-out. - * But Yamaha's driver reduce 2 PCM-in, 1 MIDI-in, 2 PCM-out, 1 MIDI-out to use - * 'Extended Stream Format Information Command - Single Request' in 'Additional - * AVC commands' defined by BridgeCo. - * This ALSA driver don't do this because a bit tiresome. Then isochronous - * streaming with many asynchronous transactions brings sounds with noises. - * Unfortunately current 'ffado-mixer' generated many asynchronous transaction - * to observe device's state, mainly check cmp connection and signal format. I - * reccomend users to close ffado-mixer at 192.0kHz if mixer is needless. - */ - -static enum snd_bebob_clock_type clk_src_types[] = { - SND_BEBOB_CLOCK_TYPE_INTERNAL, - SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ -}; -static int -clk_src_get(struct snd_bebob *bebob, unsigned int *id) -{ - int err; - - err = avc_audio_get_selector(bebob->unit, 0, 4, id); - if (err < 0) - return err; - - if (*id >= ARRAY_SIZE(clk_src_types)) - return -EIO; - - return 0; -} -static const struct snd_bebob_clock_spec clock_spec = { - .num = ARRAY_SIZE(clk_src_types), - .types = clk_src_types, - .get = &clk_src_get, -}; -static const struct snd_bebob_rate_spec rate_spec = { - .get = &snd_bebob_stream_get_rate, - .set = &snd_bebob_stream_set_rate, -}; -const struct snd_bebob_spec yamaha_go_spec = { - .clock = &clock_spec, - .rate = &rate_spec, - .meter = NULL -}; diff --git a/sound/firewire/bebob/bebob_yamaha_terratec.c b/sound/firewire/bebob/bebob_yamaha_terratec.c new file mode 100644 index 0000000..5c5d7d3 --- /dev/null +++ b/sound/firewire/bebob/bebob_yamaha_terratec.c @@ -0,0 +1,62 @@ +/* + * bebob_yamaha.c - a part of driver for BeBoB based devices + * + * Copyright (c) 2013-2014 Takashi Sakamoto + * + * Licensed under the terms of the GNU General Public License, version 2. + */ + +#include "./bebob.h" + +/* + * NOTE: + * Yamaha GO44 is not designed to be used as stand-alone mixer. So any streams + * must be accompanied. If changing the state, a LED on the device starts to + * blink and its sync status is false. In this state, the device sounds nothing + * even if streaming. To start streaming at the current sampling rate is only + * way to recover this state. GO46 is better for stand-alone mixer. + * + * Both of them have a capability to change its sampling rate up to 192.0kHz. + * At 192.0kHz, the device reports 4 PCM-in, 1 MIDI-in, 6 PCM-out, 1 MIDI-out. + * But Yamaha's driver reduce 2 PCM-in, 1 MIDI-in, 2 PCM-out, 1 MIDI-out to use + * 'Extended Stream Format Information Command - Single Request' in 'Additional + * AVC commands' defined by BridgeCo. + * This ALSA driver don't do this because a bit tiresome. Then isochronous + * streaming with many asynchronous transactions brings sounds with noises. + * Unfortunately current 'ffado-mixer' generated many asynchronous transaction + * to observe device's state, mainly check cmp connection and signal format. I + * recommend users to close ffado-mixer at 192.0kHz if mixer is needless. + */ + +static enum snd_bebob_clock_type clk_src_types[] = { + SND_BEBOB_CLOCK_TYPE_INTERNAL, + SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ +}; +static int +clk_src_get(struct snd_bebob *bebob, unsigned int *id) +{ + int err; + + err = avc_audio_get_selector(bebob->unit, 0, 4, id); + if (err < 0) + return err; + + if (*id >= ARRAY_SIZE(clk_src_types)) + return -EIO; + + return 0; +} +static const struct snd_bebob_clock_spec clock_spec = { + .num = ARRAY_SIZE(clk_src_types), + .types = clk_src_types, + .get = &clk_src_get, +}; +static const struct snd_bebob_rate_spec rate_spec = { + .get = &snd_bebob_stream_get_rate, + .set = &snd_bebob_stream_set_rate, +}; +const struct snd_bebob_spec yamaha_go_spec = { + .clock = &clock_spec, + .rate = &rate_spec, + .meter = NULL +}; -- cgit v0.10.2 From e15c282eff54aaf4c5ed72d492da7060d14f7be8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 24 Aug 2016 21:42:43 +0900 Subject: ALSA: bebob: unify configurations for some models produced by Yamaha/Terratec The below models were developed with a cooperation by Yamaha and Terratec. - Yamaha GO 44/Terratec PHASE 24 FW - Yamaha GO 46/Terratec PHASE X24 FW They have the same configurations, thus it's better to unify corresponding codes. This commit merges them to reduce the amount of maintained codes. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index f7e2cbd..3469ac14 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -458,17 +458,17 @@ static const struct ieee1394_device_id bebob_id_table[] = { /* TerraTec Electronic GmbH, PHASE 88 Rack FW */ SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000003, &phase88_rack_spec), /* TerraTec Electronic GmbH, PHASE 24 FW */ - SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000004, &phase24_series_spec), + SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000004, &yamaha_terratec_spec), /* TerraTec Electronic GmbH, Phase X24 FW */ - SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000007, &phase24_series_spec), + SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000007, &yamaha_terratec_spec), /* TerraTec Electronic GmbH, EWS MIC2/MIC8 */ SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000005, &spec_normal), /* Terratec Electronic GmbH, Aureon 7.1 Firewire */ SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000002, &spec_normal), /* Yamaha, GO44 */ - SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000b, &yamaha_go_spec), + SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000b, &yamaha_terratec_spec), /* YAMAHA, GO46 */ - SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000c, &yamaha_go_spec), + SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000c, &yamaha_terratec_spec), /* Focusrite, SaffirePro 26 I/O */ SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x00000003, &saffirepro_26_spec), /* Focusrite, SaffirePro 10 I/O */ diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index e7f1bb9..175da87 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -235,8 +235,7 @@ int snd_bebob_create_hwdep_device(struct snd_bebob *bebob); /* model specific operations */ extern const struct snd_bebob_spec phase88_rack_spec; -extern const struct snd_bebob_spec phase24_series_spec; -extern const struct snd_bebob_spec yamaha_go_spec; +extern const struct snd_bebob_spec yamaha_terratec_spec; extern const struct snd_bebob_spec saffirepro_26_spec; extern const struct snd_bebob_spec saffirepro_10_spec; extern const struct snd_bebob_spec saffire_le_spec; diff --git a/sound/firewire/bebob/bebob_terratec.c b/sound/firewire/bebob/bebob_terratec.c index c38358b..2fdaf93 100644 --- a/sound/firewire/bebob/bebob_terratec.c +++ b/sound/firewire/bebob/bebob_terratec.c @@ -36,25 +36,6 @@ end: return err; } -static enum snd_bebob_clock_type phase24_series_clk_src_types[] = { - SND_BEBOB_CLOCK_TYPE_INTERNAL, - SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ -}; -static int -phase24_series_clk_src_get(struct snd_bebob *bebob, unsigned int *id) -{ - int err; - - err = avc_audio_get_selector(bebob->unit, 0, 4, id); - if (err < 0) - return err; - - if (*id >= ARRAY_SIZE(phase24_series_clk_src_types)) - return -EIO; - - return 0; -} - static const struct snd_bebob_rate_spec phase_series_rate_spec = { .get = &snd_bebob_stream_get_rate, .set = &snd_bebob_stream_set_rate, @@ -71,15 +52,3 @@ const struct snd_bebob_spec phase88_rack_spec = { .rate = &phase_series_rate_spec, .meter = NULL }; - -/* 'PHASE 24 FW' and 'PHASE X24 FW' */ -static const struct snd_bebob_clock_spec phase24_series_clk = { - .num = ARRAY_SIZE(phase24_series_clk_src_types), - .types = phase24_series_clk_src_types, - .get = &phase24_series_clk_src_get, -}; -const struct snd_bebob_spec phase24_series_spec = { - .clock = &phase24_series_clk, - .rate = &phase_series_rate_spec, - .meter = NULL -}; diff --git a/sound/firewire/bebob/bebob_yamaha_terratec.c b/sound/firewire/bebob/bebob_yamaha_terratec.c index 5c5d7d3..a6be3e7 100644 --- a/sound/firewire/bebob/bebob_yamaha_terratec.c +++ b/sound/firewire/bebob/bebob_yamaha_terratec.c @@ -26,6 +26,9 @@ * Unfortunately current 'ffado-mixer' generated many asynchronous transaction * to observe device's state, mainly check cmp connection and signal format. I * recommend users to close ffado-mixer at 192.0kHz if mixer is needless. + * + * Terratec PHASE 24 FW and PHASE X24 FW are internally the same as + * Yamaha GO 44 and GO 46. Yamaha and Terratec had cooperated for these models. */ static enum snd_bebob_clock_type clk_src_types[] = { @@ -55,7 +58,7 @@ static const struct snd_bebob_rate_spec rate_spec = { .get = &snd_bebob_stream_get_rate, .set = &snd_bebob_stream_set_rate, }; -const struct snd_bebob_spec yamaha_go_spec = { +const struct snd_bebob_spec yamaha_terratec_spec = { .clock = &clock_spec, .rate = &rate_spec, .meter = NULL -- cgit v0.10.2 From e5668caec5698f14f310fb06bb39595b21d2fe4a Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Tue, 23 Aug 2016 10:51:22 +0200 Subject: ASoC: simple-card-utils: add __printf attribute asoc_simple_card_set_dailink_name() uses devm_kvasprintf() to format some of its arguments. Adding a __printf attribute to this function makes it possible to detect at compile-time errors related to format strings. Signed-off-by: Nicolas Iooss Signed-off-by: Mark Brown diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 403ec92..fd641255 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -27,6 +27,7 @@ int asoc_simple_card_parse_daifmt(struct device *dev, struct device_node *codec, char *prefix, unsigned int *retfmt); +__printf(3, 4) int asoc_simple_card_set_dailink_name(struct device *dev, struct snd_soc_dai_link *dai_link, const char *fmt, ...); -- cgit v0.10.2 From 34b64e5ebffc5e4a9dbf8735561c4159a936248f Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 24 Aug 2016 20:57:47 +0300 Subject: ALSA: snd-aoa: enable sound on PowerBook G4 12" Enable sound on PowerBook G4 12". Signed-off-by: Aaro Koskinen Signed-off-by: Takashi Iwai diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index 8f71f7e..edc8681 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -112,6 +112,7 @@ MODULE_ALIAS("sound-layout-100"); MODULE_ALIAS("aoa-device-id-14"); MODULE_ALIAS("aoa-device-id-22"); +MODULE_ALIAS("aoa-device-id-31"); MODULE_ALIAS("aoa-device-id-35"); MODULE_ALIAS("aoa-device-id-44"); @@ -362,6 +363,13 @@ static struct layout layouts[] = { .connections = tas_connections_nolineout, }, }, + /* PowerBook6,1 */ + { .device_id = 31, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nolineout, + }, + }, /* PowerBook6,5 */ { .device_id = 44, .codecs[0] = { diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index 1cbf210..000b585 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c @@ -197,7 +197,7 @@ static int i2sbus_add_dev(struct macio_dev *macio, * so restrict to those we do handle for now. */ if (id && (*id == 22 || *id == 14 || *id == 35 || - *id == 44)) { + *id == 31 || *id == 44)) { snprintf(dev->sound.modalias, 32, "aoa-device-id-%d", *id); ok = 1; -- cgit v0.10.2 From c9991052aedaa74c69f8198852c65a99caf1adec Mon Sep 17 00:00:00 2001 From: Nariman Poushin Date: Tue, 30 Aug 2016 10:30:40 +0100 Subject: ASoC: arizona: Don't change the FLLn_GAIN before entering FREERUN When reclocking an active FLL, to ensure a clean transition, do not change the gain setting until we have entered free run. Signed-off-by: Nariman Poushin Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index ecfdbfc..0fc3b4b 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -2218,11 +2218,11 @@ static int arizona_enable_fll(struct arizona_fll *fll) if (already_enabled) { /* Facilitate smooth refclk across the transition */ - regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9, - ARIZONA_FLL1_GAIN_MASK, 0); regmap_update_bits(fll->arizona->regmap, fll->base + 1, ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN); udelay(32); + regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9, + ARIZONA_FLL1_GAIN_MASK, 0); } /* -- cgit v0.10.2 From 4127e80a93e8a4ac009a03a8b0897e89042c7ea0 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 31 Aug 2016 21:02:13 +0900 Subject: ALSA: seq: initialize whole fields of automatic variable with union type Currently, automatic variable of 'union ioctl_arg' type is initialized by designated initialization. Although, the actual effect is interpretation of early element of int type and initialization of 'int pversion'. Therefore the first field corresponding to int type is initialized to zero. This is against my expectation to initialize whole fields. This commit uses memset() to initialize the variable, instead of designated initialization. Fixes: 04a56dd8ed0d ('ALSA: seq: change ioctl command operation to get data in kernel space') Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 286394b..811b95b 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2084,7 +2084,7 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd, { struct snd_seq_client *client = file->private_data; /* To use kernel stack for ioctl data. */ - union ioctl_arg { + union { int pversion; int client_id; struct snd_seq_system_info system_info; @@ -2100,7 +2100,7 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd, struct snd_seq_client_pool client_pool; struct snd_seq_remove_events remove_events; struct snd_seq_query_subs query_subs; - } buf = {0}; + } buf; const struct ioctl_handler *handler; unsigned long size; int err; @@ -2114,6 +2114,9 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd, } if (handler->cmd == 0) return -ENOTTY; + + memset(&buf, 0, sizeof(buf)); + /* * All of ioctl commands for ALSA sequencer get an argument of size * within 13 bits. We can safely pick up the size from the command. -- cgit v0.10.2 From 16f0f01d4f7fb9cbc7a383577ef9756d7eb9afd1 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 1 Sep 2016 11:15:44 +0100 Subject: ALSA: cs46xx: fix typo "seconadry" -> "secondary" Trivial fix to typos dev_dbg messages and comment. Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 2706f27..528102c 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -2460,7 +2460,7 @@ static int cs46xx_detect_codec(struct snd_cs46xx *chip, int codec) udelay(10); if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) { dev_dbg(chip->card->dev, - "seconadry codec not present\n"); + "secondary codec not present\n"); return -ENXIO; } } @@ -2503,7 +2503,7 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) chip->nr_ac97_codecs = 1; #ifdef CONFIG_SND_CS46XX_NEW_DSP - dev_dbg(chip->card->dev, "detecting seconadry codec\n"); + dev_dbg(chip->card->dev, "detecting secondary codec\n"); /* try detect a secondary codec */ if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX)) chip->nr_ac97_codecs = 2; diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index d2951ed..4a0cbd2 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -1441,7 +1441,7 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip) if (chip->nr_ac97_codecs == 2) { /* create CODEC tasklet for rear Center/LFE output - slot 6 and 9 on seconadry CODEC */ + slot 6 and 9 on secondary CODEC */ clfe_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_CLFE",0x0030,0x0030, CLFE_MIXER_SCB_ADDR, CLFE_CODEC_SCB_ADDR, -- cgit v0.10.2 From de34dcfe70576792a6312f9af4a1f880182b2d3b Mon Sep 17 00:00:00 2001 From: Harsha Priya Date: Tue, 30 Aug 2016 23:13:05 -0700 Subject: ASoC: Intel: Atom: Fix message handling during drop stream If a stream is being dropped, the period_elapsed received then after need not be processed. Processing of the period_elapsed message causes a time out in drop stream response processing. This patch adds a condition to skip period_elapsed message processing if the stream is in INIT state. Signed-off-by: Harsha Priya Signed-off-by: Naveen M Acked-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/atom/sst/sst_ipc.c b/sound/soc/intel/atom/sst/sst_ipc.c index 8afa6fe..bfc8899 100644 --- a/sound/soc/intel/atom/sst/sst_ipc.c +++ b/sound/soc/intel/atom/sst/sst_ipc.c @@ -267,6 +267,9 @@ static void process_fw_async_msg(struct intel_sst_drv *sst_drv_ctx, "Period elapsed rcvd for pipe id 0x%x\n", pipe_id); stream = &sst_drv_ctx->streams[str_id]; + /* If stream is dropped, skip processing this message*/ + if (stream->status == STREAM_INIT) + break; if (stream->period_elapsed) stream->period_elapsed(stream->pcm_substream); if (stream->compr_cb) -- cgit v0.10.2 From 904a987345258ff95892685bcc4462f18ac259cd Mon Sep 17 00:00:00 2001 From: Richard Leitner Date: Wed, 31 Aug 2016 09:26:31 +0200 Subject: ASoC: sgtl5000: add headphone and LINEOUT mute controls These controls mute/unmute the LINEOUT and headphone outputs of SGTL5000 using its CHIP_ANA_CTRL register. Signed-off-by: Richard Leitner Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 527b759..0187851 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -411,6 +411,8 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { 0, 8, 0x7f, 1, headphone_volume), + SOC_SINGLE("Headphone Playback Switch", SGTL5000_CHIP_ANA_CTRL, + 4, 1, 1), SOC_SINGLE("Headphone Playback ZC Switch", SGTL5000_CHIP_ANA_CTRL, 5, 1, 0), @@ -423,6 +425,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT, 0x1f, 1, lineout_volume), + SOC_SINGLE("Lineout Playback Switch", SGTL5000_CHIP_ANA_CTRL, 8, 1, 1), }; /* mute the codec used by alsa core */ -- cgit v0.10.2 From f802d6c020658b5dce1732da0d5999a1a65afdd6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 31 Aug 2016 23:52:27 +0200 Subject: ASoC: constify snd_soc_codec_driver structures Check for snd_soc_codec_driver structures that are only passed to snd_soc_register_codec or memcpy (2nd arg), for which the corresponding parameters are declared const. Declare as const snd_soc_codec_driver structures that have these properties. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @r disable optional_qualifier@ identifier i; position p; @@ static struct snd_soc_codec_driver i@p = { ... }; @ok@ identifier r.i; expression e1,e2,e3; position p; @@ ( snd_soc_register_codec(e1,&i@p,e2,e3) | memcpy(e1,&i@p,e2) ) @bad@ position p != {r.p,ok.p}; identifier r.i; @@ i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct snd_soc_codec_driver i = { ... }; // Signed-off-by: Julia Lawall Acked-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 4ef6919..0eb5dcf 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -789,7 +789,7 @@ static int wm0010_set_sysclk(struct snd_soc_codec *codec, int source, static int wm0010_probe(struct snd_soc_codec *codec); -static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm0010 = { .probe = wm0010_probe, .set_bias_level = wm0010_set_bias_level, .set_sysclk = wm0010_set_sysclk, diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index caf5012..cf5f058 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c @@ -141,7 +141,7 @@ static struct snd_soc_dai_driver wm1250_ev1_dai = { .ops = &wm1250_ev1_ops, }; -static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = { .component_driver = { .dapm_widgets = wm1250_ev1_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets), diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 1ebaf99..e553f7f 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -799,7 +799,7 @@ static int wm2000_remove(struct snd_soc_codec *codec) return wm2000_anc_transition(wm2000, ANC_OFF); } -static struct snd_soc_codec_driver soc_codec_dev_wm2000 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm2000 = { .probe = wm2000_probe, .remove = wm2000_remove, .suspend = wm2000_suspend, diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index d913d0e..606bf88 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2103,7 +2103,7 @@ static struct snd_soc_dai_driver wm2200_dai = { .ops = &wm2200_dai_ops, }; -static struct snd_soc_codec_driver soc_codec_wm2200 = { +static const struct snd_soc_codec_driver soc_codec_wm2200 = { .probe = wm2200_probe, .idle_bias_off = true, diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 8cbdf17..278467d 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2381,7 +2381,7 @@ static int wm5100_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm5100 = { .probe = wm5100_probe, .remove = wm5100_remove, diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 1295978..05bb3cb 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1990,7 +1990,7 @@ static struct regmap *wm5102_get_regmap(struct device *dev) return priv->core.arizona->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm5102 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm5102 = { .probe = wm5102_codec_probe, .remove = wm5102_codec_remove, .get_regmap = wm5102_get_regmap, diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 3e7f873..e22d3dc 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2347,7 +2347,7 @@ static struct regmap *wm5110_get_regmap(struct device *dev) return priv->core.arizona->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm5110 = { .probe = wm5110_codec_probe, .remove = wm5110_codec_remove, .get_regmap = wm5110_get_regmap, diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 18bc4ca..2efc5b4 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -1587,7 +1587,7 @@ static struct regmap *wm8350_get_regmap(struct device *dev) return wm8350->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8350 = { .probe = wm8350_codec_probe, .remove = wm8350_codec_remove, .get_regmap = wm8350_get_regmap, diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 4551e54..6c59fb9 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -1332,7 +1332,7 @@ static struct regmap *wm8400_get_regmap(struct device *dev) return wm8400->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm8400 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8400 = { .probe = wm8400_codec_probe, .remove = wm8400_codec_remove, .get_regmap = wm8400_get_regmap, diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 7f93adf..119ceac 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -581,7 +581,7 @@ static int wm8510_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8510 = { .probe = wm8510_probe, .set_bias_level = wm8510_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 0bb189a..deb2e07 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -413,7 +413,7 @@ static int wm8523_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8523 = { .probe = wm8523_probe, .set_bias_level = wm8523_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 2e69270..faa7287 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -899,7 +899,7 @@ static int wm8580_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8580 = { .probe = wm8580_probe, .remove = wm8580_remove, .set_bias_level = wm8580_set_bias_level, diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 4e8ebef..2b376c9 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -367,7 +367,7 @@ static int wm8711_probe(struct snd_soc_codec *codec) } -static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8711 = { .probe = wm8711_probe, .set_bias_level = wm8711_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c index b01e64e..7fde077 100644 --- a/sound/soc/codecs/wm8727.c +++ b/sound/soc/codecs/wm8727.c @@ -53,7 +53,7 @@ static struct snd_soc_dai_driver wm8727_dai = { }, }; -static struct snd_soc_codec_driver soc_codec_dev_wm8727 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8727 = { .component_driver = { .dapm_widgets = wm8727_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm8727_dapm_widgets), diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index dcd64b3..797cc6e 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -211,7 +211,7 @@ static struct snd_soc_dai_driver wm8728_dai = { .ops = &wm8728_dai_ops, }; -static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8728 = { .set_bias_level = wm8728_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 545fc9a..4f9a1eb 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -628,7 +628,7 @@ err_regulator_enable: return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8731 = { .set_bias_level = wm8731_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 728c42c..f0cb1c4 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -573,7 +573,7 @@ err_get: return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8737 = { .probe = wm8737_probe, .set_bias_level = wm8737_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 3e43272..565d477 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -497,7 +497,7 @@ static int wm8741_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8741 = { .probe = wm8741_probe, .remove = wm8741_remove, .resume = wm8741_resume, diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index a96a145..0da2bba 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -708,7 +708,7 @@ static int wm8750_probe(struct snd_soc_codec *codec) return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8750 = { .probe = wm8750_probe, .set_bias_level = wm8750_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 1bb272c..9bdf544 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1478,7 +1478,7 @@ static int wm8753_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8753 = { .probe = wm8753_probe, .resume = wm8753_resume, .set_bias_level = wm8753_set_bias_level, diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 8783a5f..d6edcbb 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -608,7 +608,7 @@ err_reg_enable: return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8770 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8770 = { .probe = wm8770_probe, .set_bias_level = wm8770_set_bias_level, .idle_bias_off = true, diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index f17a3a8..ae30480 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -425,7 +425,7 @@ static int wm8776_probe(struct snd_soc_codec *codec) return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8776 = { .probe = wm8776_probe, .set_bias_level = wm8776_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c index 1e9c495..bcda210 100644 --- a/sound/soc/codecs/wm8782.c +++ b/sound/soc/codecs/wm8782.c @@ -50,7 +50,7 @@ static struct snd_soc_dai_driver wm8782_dai = { }, }; -static struct snd_soc_codec_driver soc_codec_dev_wm8782 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8782 = { .component_driver = { .dapm_widgets = wm8782_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm8782_dapm_widgets), diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 724cec4..c77b49a 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -1208,7 +1208,7 @@ static int wm8900_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8900 = { .probe = wm8900_probe, .suspend = wm8900_suspend, .resume = wm8900_resume, diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index c19ba7c..837c8b9 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1874,7 +1874,7 @@ static void wm8903_free_gpio(struct wm8903_priv *wm8903) } #endif -static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8903 = { .resume = wm8903_resume, .set_bias_level = wm8903_set_bias_level, .seq_notifier = wm8903_seq_notifier, diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index edd7a77..4fd350e8 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2086,7 +2086,7 @@ static int wm8904_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8904 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8904 = { .probe = wm8904_probe, .remove = wm8904_remove, .set_bias_level = wm8904_set_bias_level, diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 3c9febc..b593562 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -723,7 +723,7 @@ static int wm8940_probe(struct snd_soc_codec *codec) return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8940 = { .probe = wm8940_probe, .set_bias_level = wm8940_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 575075d..1edc7b1 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -940,7 +940,7 @@ err_enable: return ret; } -static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8955 = { .probe = wm8955_probe, .set_bias_level = wm8955_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index d7f444f..be32443 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -1264,7 +1264,7 @@ static int wm8960_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8960 = { .probe = wm8960_probe, .set_bias_level = wm8960_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 4b51761..e23ceac 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -882,7 +882,7 @@ static int wm8961_resume(struct snd_soc_codec *codec) #define wm8961_resume NULL #endif -static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8961 = { .probe = wm8961_probe, .resume = wm8961_resume, .set_bias_level = wm8961_set_bias_level, diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index f3109da..392b920 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3479,7 +3479,7 @@ static int wm8962_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8962 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8962 = { .probe = wm8962_probe, .remove = wm8962_remove, .set_bias_level = wm8962_set_bias_level, diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 214fa13..887d31c 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -649,7 +649,7 @@ static int wm8971_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8971 = { .probe = wm8971_probe, .set_bias_level = wm8971_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index fbda6e3..d414ddd 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -676,7 +676,7 @@ static int wm8974_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8974 = { .probe = wm8974_probe, .set_bias_level = wm8974_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 910b36f..90b2d41 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -993,7 +993,7 @@ static int wm8978_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8978 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8978 = { .probe = wm8978_probe, .suspend = wm8978_suspend, .resume = wm8978_resume, diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 9609fc0..bfdbe72 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -976,7 +976,7 @@ static struct snd_soc_dai_driver wm8983_dai = { .symmetric_rates = 1 }; -static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8983 = { .probe = wm8983_probe, .set_bias_level = wm8983_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index bcf3473..05344f9 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -1105,7 +1105,7 @@ static struct snd_soc_dai_driver wm8985_dai = { .symmetric_rates = 1 }; -static struct snd_soc_codec_driver soc_codec_dev_wm8985 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8985 = { .probe = wm8985_probe, .set_bias_level = wm8985_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index a412fd0..a894500 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1294,7 +1294,7 @@ static int wm8990_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8990 = { .probe = wm8990_probe, .set_bias_level = wm8990_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 5822d10..9843790 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1232,7 +1232,7 @@ static struct snd_soc_dai_driver wm8991_dai = { .ops = &wm8991_ops }; -static struct snd_soc_codec_driver soc_codec_dev_wm8991 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8991 = { .set_bias_level = wm8991_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 8668c4c..195f7bf 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1613,7 +1613,7 @@ static const struct regmap_config wm8993_regmap = { .num_reg_defaults = ARRAY_SIZE(wm8993_reg_defaults), }; -static struct snd_soc_codec_driver soc_codec_dev_wm8993 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8993 = { .probe = wm8993_probe, .suspend = wm8993_suspend, .resume = wm8993_resume, diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index a18aecb..3896523 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -4439,7 +4439,7 @@ static struct regmap *wm8994_get_regmap(struct device *dev) return control->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8994 = { .probe = wm8994_codec_probe, .remove = wm8994_codec_remove, .suspend = wm8994_codec_suspend, diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index abacf6c..5eba8ff 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -2684,7 +2684,7 @@ static int wm8996_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm8996 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8996 = { .probe = wm8996_probe, .remove = wm8996_remove, .set_bias_level = wm8996_set_bias_level, diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index cf23a6b..2f2821b 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -1095,7 +1095,7 @@ static struct regmap *wm8997_get_regmap(struct device *dev) return priv->core.arizona->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm8997 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8997 = { .probe = wm8997_codec_probe, .remove = wm8997_codec_remove, .get_regmap = wm8997_get_regmap, diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 315b23b..f6d18d7 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -1351,7 +1351,7 @@ static struct regmap *wm8998_get_regmap(struct device *dev) return priv->core.arizona->regmap; } -static struct snd_soc_codec_driver soc_codec_dev_wm8998 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm8998 = { .probe = wm8998_codec_probe, .remove = wm8998_codec_remove, .get_regmap = wm8998_get_regmap, diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 30eaf4c..856867e 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -1274,7 +1274,7 @@ static int wm9081_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm9081 = { .probe = wm9081_probe, .set_sysclk = wm9081_set_sysclk, diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 5d73729..5a13138 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -550,7 +550,7 @@ static int wm9090_probe(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm9090 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm9090 = { .probe = wm9090_probe, .set_bias_level = wm9090_set_bias_level, .suspend_bias_off = true, diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index c88492d..dcdd055 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -352,7 +352,7 @@ static int wm9705_soc_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm9705 = { .probe = wm9705_soc_probe, .remove = wm9705_soc_remove, .suspend = wm9705_soc_suspend, diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index e5aafdd..557709e 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -669,7 +669,7 @@ static int wm9712_soc_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm9712 = { .probe = wm9712_soc_probe, .remove = wm9712_soc_remove, .resume = wm9712_soc_resume, diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 255a7c2..e4301dd 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1235,7 +1235,7 @@ static int wm9713_soc_remove(struct snd_soc_codec *codec) return 0; } -static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { +static const struct snd_soc_codec_driver soc_codec_dev_wm9713 = { .probe = wm9713_soc_probe, .remove = wm9713_soc_remove, .suspend = wm9713_soc_suspend, -- cgit v0.10.2 From 2961d6707ca18830d8d58819ac9409e2e7c6e552 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 1 Sep 2016 08:52:37 +0200 Subject: ASoC: omap-pcm: off-by-one in 'omap_pcm_limit_supported_formats' When calling 'snd_pcm_format_physical_width', SNDRV_PCM_FORMAT_LAST is a valid value, so don't skip it. Signed-off-by: Christophe JAILLET Acked-by: Peter Ujfalusi Signed-off-by: Mark Brown diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index a84f677..94e9ff7 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -58,7 +58,7 @@ static void omap_pcm_limit_supported_formats(void) { int i; - for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) { + for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { switch (snd_pcm_format_physical_width(i)) { case 8: case 16: -- cgit v0.10.2 From 9be072a6f9187f087a8b7682b70b898ac5cb7d64 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 1 Sep 2016 10:05:12 +0300 Subject: ASoC: davinci-mcasp: off-by-one in davinci_mcasp_hw_rule_format() The SNDRV_PCM_FORMAT_LAST is valid, we should not skip it. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 05c2d33..3c5a980 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -1218,7 +1218,7 @@ static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params, snd_mask_none(&nfmt); - for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) { + for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { if (snd_mask_test(fmt, i)) { uint sbits = snd_pcm_format_width(i); int ppm; -- cgit v0.10.2 From 189f06c031d431d4fb7a78952df4c83ac7822b79 Mon Sep 17 00:00:00 2001 From: Jaswinder Jassal Date: Mon, 29 Aug 2016 16:06:58 +0100 Subject: ASoC: core: fix shift used for second item in snd_soc_get_enum_double Incorrect shift value was being used to extract the second item. Signed-off-by: Jaswinder Jassal Reviewed-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index a513a34..9fc1a7b 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -77,7 +77,7 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, item = snd_soc_enum_val_to_item(e, val); ucontrol->value.enumerated.item[0] = item; if (e->shift_l != e->shift_r) { - val = (reg_val >> e->shift_l) & e->mask; + val = (reg_val >> e->shift_r) & e->mask; item = snd_soc_enum_val_to_item(e, val); ucontrol->value.enumerated.item[1] = item; } -- cgit v0.10.2 From 61ab0d403bbd9d5f6e000e3b5734049141b91f6f Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Sun, 28 Aug 2016 21:10:04 +0200 Subject: ASoC: Intel: Atom: add a missing star in a memcpy call In sst_prepare_and_post_msg(), when a response is received in "block", the following code gets executed: *data = kzalloc(block->size, GFP_KERNEL); memcpy(data, (void *) block->data, block->size); The memcpy() call overwrites the content of the *data pointer instead of filling the newly-allocated memory (which pointer is hold by *data). Fix this by merging kzalloc+memcpy into a single kmemdup() call. Thanks Joe Perches for suggesting using kmemdup() Fixes: 60dc8dbacb00 ("ASoC: Intel: sst: Add some helper functions") Signed-off-by: Nicolas Iooss Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/sound/soc/intel/atom/sst/sst_pvt.c b/sound/soc/intel/atom/sst/sst_pvt.c index adb32fe..b1e6b8f 100644 --- a/sound/soc/intel/atom/sst/sst_pvt.c +++ b/sound/soc/intel/atom/sst/sst_pvt.c @@ -279,17 +279,15 @@ int sst_prepare_and_post_msg(struct intel_sst_drv *sst, if (response) { ret = sst_wait_timeout(sst, block); - if (ret < 0) { + if (ret < 0) goto out; - } else if(block->data) { - if (!data) - goto out; - *data = kzalloc(block->size, GFP_KERNEL); - if (!(*data)) { + + if (data && block->data) { + *data = kmemdup(block->data, block->size, GFP_KERNEL); + if (!*data) { ret = -ENOMEM; goto out; - } else - memcpy(data, (void *) block->data, block->size); + } } } out: -- cgit v0.10.2 From f506513ad80dc7ca0b4bfe26a228a801c08d1db7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 26 Aug 2016 17:50:55 +0200 Subject: ASoC: rockchip: use SPI dependency for rt5514 The rk3399 scans the spi_bus_type to find the rt5514 driver, but does not actually have a Kconfig dependency on SPI, so we can end up with a link failure: sound/soc/codecs/snd-soc-rt5514-spi.o: In function `rt5514_spi_driver_init': rt5514-spi.c:(.init.text+0x14): undefined reference to `__spi_register_driver' sound/soc/codecs/snd-soc-rt5514-spi.o: In function `rt5514_spi_burst_read': rt5514-spi.c:(.text.rt5514_spi_burst_read+0x18c): undefined reference to `spi_sync' sound/soc/codecs/snd-soc-rt5514-spi.o: In function `rt5514_spi_burst_write': rt5514-spi.c:(.text.rt5514_spi_burst_write+0x1b4): undefined reference to `spi_sync' sound/soc/rockchip/snd-soc-rk3399-gru-sound.o: In function `rockchip_sound_probe': rk3399_gru_sound.c:(.text.rockchip_sound_probe+0x128): undefined reference to `spi_bus_type' This adds the missing dependency. Fixes: c6eac8a36a84 (ASoC: rockchip: Add machine driver for RK3399 GRU Boards) Signed-off-by: Arnd Bergmann Tested-by: Xing Zheng Signed-off-by: Mark Brown diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index d82d763..c783f9a 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig @@ -44,7 +44,7 @@ config SND_SOC_ROCKCHIP_RT5645 config SND_SOC_RK3399_GRU_SOUND tristate "ASoC support multiple codecs for Rockchip RK3399 GRU boards" - depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP + depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP && SPI select SND_SOC_ROCKCHIP_I2S select SND_SOC_MAX98357A select SND_SOC_RT5514 -- cgit v0.10.2 From ab387b400872791d0e4d8652a08b44848b85e188 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 26 Aug 2016 18:52:33 +0100 Subject: ASoC: wm8962: fix spelling mistake "mesurement" -> "measurement" Trivial fix to spelling mistake in dev_err message. Signed-off-by: Colin Ian King Acked-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index f3109da..97b0228 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3713,7 +3713,7 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, ARRAY_SIZE(wm8962_dc_measure)); if (ret != 0) dev_err(&i2c->dev, - "Failed to configure for DC mesurement: %d\n", + "Failed to configure for DC measurement: %d\n", ret); } -- cgit v0.10.2 From 3fb7b4e488c30f0e2fce3f41bdcd19a18975090f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 26 Aug 2016 19:17:25 +0100 Subject: ASoC: hdac_hdmi: fix spelling mistake "montior" -> "monitor" Trivial fix to spelling mistake in dev_warn message. Signed-off-by: Colin Ian King Acked-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 4e181b2..c602c49 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -614,7 +614,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, (!pin->eld.eld_valid)) { dev_warn(&hdac->hdac.dev, - "Failed: montior present? %d ELD valid?: %d for pin: %d\n", + "Failed: monitor present? %d ELD valid?: %d for pin: %d\n", pin->eld.monitor_present, pin->eld.eld_valid, pin->nid); return 0; -- cgit v0.10.2 From 01ad5e7de67b408d9b48b437b06a9938ddf460b5 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 27 Aug 2016 19:27:58 +0800 Subject: ASoC: dapm: Fix possible uninitialized variable in snd_soc_dapm_get_volsw() If soc_dapm_read() fails, val will be uninitialized, and bogus values will be written later: ret = soc_dapm_read(dapm, reg, &val); val = (val >> shift) & mask; However, the compiler does not give a warning. Return on error before val is really used to avoid this. This is similar to the commit 6912831623c5 ("ASoC: dapm: Fix uninitialized variable in snd_soc_dapm_get_enum_double()") Fixes: ce0fc93ae56e (ASoC: Add DAPM support at the component level) Signed-off-by: Chen-Yu Tsai Signed-off-by: Mark Brown diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d908ff8..edff395 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3049,6 +3049,9 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, } mutex_unlock(&card->dapm_mutex); + if (ret) + return ret; + if (invert) ucontrol->value.integer.value[0] = max - val; else -- cgit v0.10.2 From 071133a209354f39d4e5785d5a6a390e03241841 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 27 Aug 2016 19:27:59 +0800 Subject: ASoC: dapm: Fix value setting for _ENUM_DOUBLE MUX's second channel The value for the second channel in _ENUM_DOUBLE (double channel) MUXs is not correctly updated, due to using the wrong bit shift. Use the correct bit shift, so both channels toggle together. Fixes: 3727b4968453 (ASoC: dapm: Consolidate MUXs and value MUXs) Signed-off-by: Chen-Yu Tsai Reviewed-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index edff395..76d4141 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3203,7 +3203,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, if (e->shift_l != e->shift_r) { if (item[1] > e->items) return -EINVAL; - val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_l; + val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; mask |= e->mask << e->shift_r; } -- cgit v0.10.2 From a3930ed060df4ccf2a06cf0b68738dec3e6ff89a Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 27 Aug 2016 19:28:00 +0800 Subject: ASoC: dapm: Fix kcontrol creation for output driver widget Commit d88429a695a4 ("ASoC: dapm: Add output driver widget") added the snd_soc_dapm_out_drv ID for the output driver widget, which is the same as the PGA widget, with a later power sequence number. Commit 19a2557b76d6 ("ASoC: dapm: Add kcontrol support for PGAs") then added kcontrol support for PGA widgets, but failed to account for output driver widgets. Attempts to use kcontrols with output driver widgets result in silent failures, with the developer having little idea about what went on. Add snd_soc_dapm_out_drv to the switch/case block under snd_soc_dapm_pga in dapm_create_or_share_kcontrol, since they are essentially the same. Fixes: 19a2557b76d6 (ASoC: dapm: Add kcontrol support for PGAs) Signed-off-by: Chen-Yu Tsai Signed-off-by: Mark Brown diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 76d4141..801082f 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -823,6 +823,7 @@ static int dapm_create_or_share_kcontrol(struct snd_soc_dapm_widget *w, case snd_soc_dapm_switch: case snd_soc_dapm_mixer: case snd_soc_dapm_pga: + case snd_soc_dapm_out_drv: wname_in_long_name = true; kcname_in_long_name = true; break; -- cgit v0.10.2 From ec103964776bf8af74e66eb1a810eada757718a5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 25 Aug 2016 08:55:27 +0800 Subject: ASoC: nau8810: Fix memory leak in nau8810_eq_put error path Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c index f9bcdc3..e455186 100644 --- a/sound/soc/codecs/nau8810.c +++ b/sound/soc/codecs/nau8810.c @@ -221,6 +221,7 @@ static int nau8810_eq_put(struct snd_kcontrol *kcontrol, if (ret) { dev_err(codec->dev, "EQ configuration fail, register: %x ret: %d\n", reg + i, ret); + kfree(data); return ret; } } -- cgit v0.10.2 From c614a31287033945478053cd060c3c803d7bc94f Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Wed, 24 Aug 2016 17:26:15 -0700 Subject: ASoC: tegra_rt5640: Correct a copy and paste typo in the comments This patch corrects a copy and paste typo. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c index 773daec..e5ef4e9 100644 --- a/sound/soc/tegra/tegra_rt5640.c +++ b/sound/soc/tegra/tegra_rt5640.c @@ -1,5 +1,5 @@ /* -* tegra_rt5640.c - Tegra machine ASoC driver for boards using WM8903 codec. +* tegra_rt5640.c - Tegra machine ASoC driver for boards using RT5640 codec. * * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. * -- cgit v0.10.2 From 38d16f791634ee95a1a818d2170dc75681ee80af Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Wed, 24 Aug 2016 12:03:39 -0700 Subject: ASoC: rt5659: Enable IRQ output for GPIO1 pin Since it's possible to have an IRQ without enabling JD3, the GPIO1 pin then would remain its default GPIO function which is set as an input direction (seeing from rt5659). Meanwhile, CPU would also listen this connection via its own GPIO input: [input] [input] CPU GPIO <--------> RT5659 GPIO1 The result for the IRQ on the CPU side will be unexpectable. So this patch enables the IRQ output for GPIO1 pin any way as long as there's an IRQ assigned from platform data or DT: [input] [IRQ output] CPU GPIO <--------< RT5659 GPIO1 Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 42c183f..952e802 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -4187,6 +4187,9 @@ static int rt5659_i2c_probe(struct i2c_client *i2c, if (ret) dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); + /* Enable IRQ output for GPIO1 pin any way */ + regmap_update_bits(rt5659->regmap, RT5659_GPIO_CTRL_1, + RT5659_GP1_PIN_MASK, RT5659_GP1_PIN_IRQ); } return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5659, -- cgit v0.10.2 From 5496ca5c657517a20aa0f19f4baea2a119f231aa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Aug 2016 01:56:18 +0000 Subject: ASoC: simple-scu-card: remove unused definitions Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index 3fa1908..fdfaf4f 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -22,12 +22,6 @@ #include #include -struct asoc_simple_card_of_data { - const char *prefix; - const struct snd_soc_dapm_route *routes; - int num_routes; -}; - static const struct of_device_id asoc_simple_card_of_match[] = { { .compatible = "renesas,rsrc-card", }, { .compatible = "simple-scu-audio-card", }, @@ -35,8 +29,6 @@ static const struct of_device_id asoc_simple_card_of_match[] = { }; MODULE_DEVICE_TABLE(of, asoc_simple_card_of_match); -#define IDX_CPU 0 -#define IDX_CODEC 1 struct asoc_simple_card_priv { struct snd_soc_card snd_card; struct snd_soc_codec_conf codec_conf; -- cgit v0.10.2 From 93bc047d768d1049a591cc8b710b6481a7ddab89 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Aug 2016 01:56:38 +0000 Subject: ASoC: simple-scu-card: is GPL v2 It is indicating that this driver is GPL v2 on top of C code. Let's fixup it on MODULE_LICENSE() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index fdfaf4f..ac7ba97 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -348,6 +348,6 @@ static struct platform_driver asoc_simple_card = { module_platform_driver(asoc_simple_card); MODULE_ALIAS("platform:asoc-simple-scu-card"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("ASoC Simple SCU Sound Card"); MODULE_AUTHOR("Kuninori Morimoto "); -- cgit v0.10.2 From 112a2ab5a720279d0805018a9ee162e12b0ce463 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Aug 2016 01:57:04 +0000 Subject: ASoC: simple-scu-card: tidyup codec daifmt handling method Current simple-scu-card is handling codec daifmt by using for_each_child_of_node(), and low-level method. Let's use of_get_child_by_name() instead it Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index ac7ba97..83add14 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -212,19 +212,14 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, bool is_fe; /* find 1st codec */ - i = 0; - for_each_child_of_node(node, np) { - dai_link = simple_priv_to_link(priv, i); + np = of_get_child_by_name(node, PREFIX "codec"); + if (!np) + return -ENODEV; - if (strcmp(np->name, PREFIX "codec") == 0) { - ret = asoc_simple_card_parse_daifmt(dev, node, np, - PREFIX, &daifmt); - if (ret < 0) - return ret; - break; - } - i++; - } + ret = asoc_simple_card_parse_daifmt(dev, node, np, + PREFIX, &daifmt); + if (ret < 0) + return ret; i = 0; for_each_child_of_node(node, np) { -- cgit v0.10.2 From 83216f3acc4ab42ffe7001b54cd62f7ca2bde30f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Aug 2016 01:57:30 +0000 Subject: ASoC: simple-scu-card: tidyup asoc_simple_card_parse_links() method Current asoc_simple_card_parse_links() is setting dai_link daifmt. But, asoc_simple_card_parse_links() is doing it. This patch clean-up this point less method Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index 83add14..2f40f9c 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -110,6 +110,7 @@ static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static int asoc_simple_card_parse_links(struct device_node *np, struct asoc_simple_card_priv *priv, + unsigned int daifmt, int idx, bool is_fe) { struct device *dev = simple_priv_to_dev(priv); @@ -188,6 +189,7 @@ static int asoc_simple_card_parse_links(struct device_node *np, if (ret < 0) return ret; + dai_link->dai_fmt = daifmt; dai_link->dpcm_playback = 1; dai_link->dpcm_capture = 1; dai_link->ops = &asoc_simple_card_ops; @@ -205,7 +207,6 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, struct asoc_simple_card_priv *priv) { struct device *dev = simple_priv_to_dev(priv); - struct snd_soc_dai_link *dai_link; struct device_node *np; unsigned int daifmt = 0; int ret, i; @@ -223,14 +224,11 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, i = 0; for_each_child_of_node(node, np) { - dai_link = simple_priv_to_link(priv, i); - dai_link->dai_fmt = daifmt; - is_fe = false; if (strcmp(np->name, PREFIX "cpu") == 0) is_fe = true; - ret = asoc_simple_card_parse_links(np, priv, i, is_fe); + ret = asoc_simple_card_parse_links(np, priv, daifmt, i, is_fe); if (ret < 0) return ret; i++; -- cgit v0.10.2 From 88da724f77f768877283165f25d8b6d9f30b1ef7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Aug 2016 01:57:50 +0000 Subject: ASoC: simple-scu-card: depends on CONFIG_OF simple-scu-card driver is under CONFIG_OF. This patch adds missing config. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig index 2d0ff03..b95ae49 100644 --- a/sound/soc/generic/Kconfig +++ b/sound/soc/generic/Kconfig @@ -9,6 +9,7 @@ config SND_SIMPLE_CARD config SND_SIMPLE_SCU_CARD tristate "ASoC Simple SCU sound card support" + depends on OF select SND_SIMPLE_CARD_UTILS help This option enables generic simple SCU sound card support. -- cgit v0.10.2 From e5a01eb5fc6f0e77033f005e6b5f7fb8b4ea837f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Aug 2016 01:58:10 +0000 Subject: ASoC: simple-scu-card: add 2 CPU 1 Codec example Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/simple-scu-card.txt b/Documentation/devicetree/bindings/sound/simple-scu-card.txt index ecb4a24..d6fe47e 100644 --- a/Documentation/devicetree/bindings/sound/simple-scu-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-scu-card.txt @@ -52,7 +52,7 @@ Optional CPU/CODEC subnodes properties: clk_disable_unprepare() in dai shutdown(). -Example +Example 1. Sampling Rate Covert sound { compatible = "simple-scu-audio-card"; @@ -78,3 +78,33 @@ sound { system-clock-frequency = <11289600>; }; }; + +Example 2. 2 CPU 1 Codec + +sound { + compatible = "renesas,rsrc-card"; + + card-name = "rsnd-ak4643"; + format = "left_j"; + bitclock-master = <&dpcmcpu>; + frame-master = <&dpcmcpu>; + + convert-rate = <48000>; /* see audio_clk_a */ + + audio-prefix = "ak4642"; + audio-routing = "ak4642 Playback", "DAI0 Playback", + "ak4642 Playback", "DAI1 Playback"; + + dpcmcpu: cpu@0 { + sound-dai = <&rcar_sound 0>; + }; + + cpu@1 { + sound-dai = <&rcar_sound 1>; + }; + + codec { + sound-dai = <&ak4643>; + clocks = <&audio_clock>; + }; +}; -- cgit v0.10.2 From f4d70709c80d907a841e8ffc40995eca661817e6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Aug 2016 01:58:31 +0000 Subject: ASoC: simple-scu-card: code sync: move asoc_simple_card_of_match simple sound card family are using very similar style, but because of its historical reason, there are small differences. For example pointer style, function name, caller postion etc... This patch synchronized simple card style to other simple card family This patch moves asoc_simple_card_of_match to bottom side, and rename it to asoc_simple_of_match same as other simple card family. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index 2f40f9c..abe31dc 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -22,13 +22,6 @@ #include #include -static const struct of_device_id asoc_simple_card_of_match[] = { - { .compatible = "renesas,rsrc-card", }, - { .compatible = "simple-scu-audio-card", }, - {}, -}; -MODULE_DEVICE_TABLE(of, asoc_simple_card_of_match); - struct asoc_simple_card_priv { struct snd_soc_card snd_card; struct snd_soc_codec_conf codec_conf; @@ -329,10 +322,17 @@ static int asoc_simple_card_remove(struct platform_device *pdev) return asoc_simple_card_clean_reference(card); } +static const struct of_device_id asoc_simple_of_match[] = { + { .compatible = "renesas,rsrc-card", }, + { .compatible = "simple-scu-audio-card", }, + {}, +}; +MODULE_DEVICE_TABLE(of, asoc_simple_of_match); + static struct platform_driver asoc_simple_card = { .driver = { .name = "simple-scu-audio-card", - .of_match_table = asoc_simple_card_of_match, + .of_match_table = asoc_simple_of_match, }, .probe = asoc_simple_card_probe, .remove = asoc_simple_card_remove, -- cgit v0.10.2 From 9f645421b8219a466cca512ea5b123a5b170c59b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Aug 2016 01:58:55 +0000 Subject: ASoC: simple-scu-card: code sync: tidyup TDM setting position simple sound card family are using very similar style, but because of its historical reason, there are small differences. For example pointer style, function name, caller postion etc... This patch tidyup TDM setting position Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index abe31dc..b9973a5 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -111,15 +111,6 @@ static int asoc_simple_card_parse_links(struct device_node *np, struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, idx); int ret; - /* Parse TDM slot */ - ret = snd_soc_of_parse_tdm_slot(np, - &dai_props->tx_slot_mask, - &dai_props->rx_slot_mask, - &dai_props->slots, - &dai_props->slot_width); - if (ret) - return ret; - if (is_fe) { int is_single_links = 0; @@ -178,6 +169,14 @@ static int asoc_simple_card_parse_links(struct device_node *np, PREFIX "prefix"); } + ret = snd_soc_of_parse_tdm_slot(np, + &dai_props->tx_slot_mask, + &dai_props->rx_slot_mask, + &dai_props->slots, + &dai_props->slot_width); + if (ret) + return ret; + ret = asoc_simple_card_canonicalize_dailink(dai_link); if (ret < 0) return ret; -- cgit v0.10.2 From a03b0545c26d88ae92cdfc662cad4364e8c627a3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Aug 2016 03:05:16 +0000 Subject: ASoC: simple-card: call of_node_put() for dai_link We need to call of_node_put() if we used of_get_child_by_name(), but missing it for "dai-link" loop. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 55638a8..3ce8bb6 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -322,18 +322,21 @@ static int asoc_simple_card_parse_of(struct device_node *node, struct simple_card_data *priv) { struct device *dev = simple_priv_to_dev(priv); + struct device_node *dai_link; u32 val; int ret; if (!node) return -EINVAL; + dai_link = of_get_child_by_name(node, PREFIX "dai-link"); + /* The off-codec widgets */ if (of_property_read_bool(node, PREFIX "widgets")) { ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, PREFIX "widgets"); if (ret) - return ret; + goto card_parse_end; } /* DAPM routes */ @@ -341,7 +344,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing"); if (ret) - return ret; + goto card_parse_end; } /* Factor to mclk, used in hw_params() */ @@ -350,7 +353,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, priv->mclk_fs = val; /* Single/Muti DAI link(s) & New style of DT node */ - if (of_get_child_by_name(node, PREFIX "dai-link")) { + if (dai_link) { struct device_node *np = NULL; int i = 0; @@ -360,7 +363,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, i, false); if (ret < 0) { of_node_put(np); - return ret; + goto card_parse_end; } i++; } @@ -368,14 +371,15 @@ static int asoc_simple_card_parse_of(struct device_node *node, /* For single DAI link & old style of DT node */ ret = asoc_simple_card_dai_link_of(node, priv, 0, true); if (ret < 0) - return ret; + goto card_parse_end; } ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX); - if (ret) - return ret; - return 0; +card_parse_end: + of_node_put(dai_link); + + return ret; } static int asoc_simple_card_probe(struct platform_device *pdev) -- cgit v0.10.2 From f93b646d5124183ab76cb820d5b21a7741726eba Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Aug 2016 03:05:58 +0000 Subject: ASoC: simple-card: tidyup mclk-fs of_property_read_u32() usage of_property_read_u32() do nothing in error case. Let's tidyup useless usage. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 3ce8bb6..a4a39d4 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -222,7 +222,6 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, char prop[128]; char *prefix = ""; int ret, single_cpu; - u32 val; /* For single DAI link & old style of DT node */ if (is_top_level_node) @@ -248,8 +247,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, if (ret < 0) goto dai_link_of_err; - if (!of_property_read_u32(node, "mclk-fs", &val)) - dai_props->mclk_fs = val; + of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs); ret = asoc_simple_card_parse_cpu(cpu, dai_link, DAI, CELL, &single_cpu); @@ -323,7 +321,6 @@ static int asoc_simple_card_parse_of(struct device_node *node, { struct device *dev = simple_priv_to_dev(priv); struct device_node *dai_link; - u32 val; int ret; if (!node) @@ -348,9 +345,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, } /* Factor to mclk, used in hw_params() */ - ret = of_property_read_u32(node, PREFIX "mclk-fs", &val); - if (ret == 0) - priv->mclk_fs = val; + of_property_read_u32(node, PREFIX "mclk-fs", &priv->mclk_fs); /* Single/Muti DAI link(s) & New style of DT node */ if (dai_link) { -- cgit v0.10.2 From 7e3353ddd232da693ec26ef7982cac50d5386887 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Aug 2016 03:06:23 +0000 Subject: ASoC: simple-card: code sync: tidyup simple_priv_to_xxx() macro Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index a4a39d4..8774d803 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -41,8 +41,8 @@ struct simple_card_data { }; #define simple_priv_to_dev(priv) ((priv)->snd_card.dev) -#define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i) -#define simple_priv_to_props(priv, i) ((priv)->dai_props + i) +#define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i)) +#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i)) #define DAI "sound-dai" #define CELL "#sound-dai-cells" -- cgit v0.10.2 From c9a23ead0261b23a7571d53d90117283b177b360 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Aug 2016 03:06:51 +0000 Subject: ASoC: simple-card: code sync: use simple_priv_to_props() macro Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 8774d803..939c827 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -114,7 +114,7 @@ static int asoc_simple_card_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct simple_dai_props *dai_props = - &priv->dai_props[rtd->num]; + simple_priv_to_props(priv, rtd->num); int ret; ret = clk_prepare_enable(dai_props->cpu_dai.clk); @@ -133,7 +133,7 @@ static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct simple_dai_props *dai_props = - &priv->dai_props[rtd->num]; + simple_priv_to_props(priv, rtd->num); clk_disable_unprepare(dai_props->cpu_dai.clk); @@ -147,7 +147,8 @@ static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *dai_props = &priv->dai_props[rtd->num]; + struct simple_dai_props *dai_props = + simple_priv_to_props(priv, rtd->num); unsigned int mclk, mclk_fs = 0; int ret = 0; @@ -184,7 +185,8 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *cpu = rtd->cpu_dai; - struct simple_dai_props *dai_props = &priv->dai_props[rtd->num]; + struct simple_dai_props *dai_props = + simple_priv_to_props(priv, rtd->num); int ret; ret = asoc_simple_card_init_dai(codec, &dai_props->codec_dai); -- cgit v0.10.2 From a1dbfd001310c429fce9e066730302c82f68bd19 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Aug 2016 03:07:28 +0000 Subject: ASoC: simple-card: is GPL v2 It is indicating that this driver is GPL v2 on top of C code. Let's fixup it on MODULE_LICENSE() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 939c827..7b0a56f 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -498,6 +498,6 @@ static struct platform_driver asoc_simple_card = { module_platform_driver(asoc_simple_card); MODULE_ALIAS("platform:asoc-simple-card"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("ASoC Simple Sound Card"); MODULE_AUTHOR("Kuninori Morimoto "); -- cgit v0.10.2 From 387f5823f400445ed0152bfa06eef50a382b9219 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Aug 2016 03:07:59 +0000 Subject: ASoC: simple-card: code sync: tidyup white line simple sound card family are using very similar style, but because of its historical reason, there are small differences. For example pointer style, function name, caller postion etc... This patch synchronized simple card style to other simple card family. This patch tidyups white line Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 7b0a56f..7d15b50 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -120,7 +120,7 @@ static int asoc_simple_card_startup(struct snd_pcm_substream *substream) ret = clk_prepare_enable(dai_props->cpu_dai.clk); if (ret) return ret; - + ret = clk_prepare_enable(dai_props->codec_dai.clk); if (ret) clk_disable_unprepare(dai_props->cpu_dai.clk); @@ -454,7 +454,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev) sizeof(priv->dai_props->cpu_dai)); memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai, sizeof(priv->dai_props->codec_dai)); - } snd_soc_card_set_drvdata(&priv->snd_card, priv); @@ -462,9 +461,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); if (ret >= 0) return ret; - err: asoc_simple_card_clean_reference(&priv->snd_card); + return ret; } -- cgit v0.10.2 From 0a6c7f2f7890796209896c2239420c8a38dacb60 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Aug 2016 03:08:25 +0000 Subject: ASoC: simple-card: code sync: use tag simple sound card family are using very similar style, but because of its historical reason, there are small differences. For example pointer style, function name, caller postion etc... This patch synchronized simple card style to other simple card family. This patch uses tag on asoc_simple_card_probe Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 7d15b50..c17f851 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -401,11 +401,11 @@ static int asoc_simple_card_probe(struct platform_device *pdev) return -ENOMEM; /* Init snd_soc_card */ - priv->snd_card.owner = THIS_MODULE; - priv->snd_card.dev = dev; dai_link = priv->dai_link; - priv->snd_card.dai_link = dai_link; - priv->snd_card.num_links = num_links; + priv->snd_card.owner = THIS_MODULE; + priv->snd_card.dev = dev; + priv->snd_card.dai_link = priv->dai_link; + priv->snd_card.num_links = num_links; /* Get room for the other properties */ priv->dai_props = devm_kzalloc(dev, -- cgit v0.10.2 From 2c86dda74ceae739eb3c0ada5cd8f2ddf903ce35 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Aug 2016 03:09:38 +0000 Subject: ASoC: simple-card: code sync: rename num_link to num simple sound card family are using very similar style, but because of its historical reason, there are small differences. For example pointer style, function name, caller postion etc... This patch synchronized simple card style to other simple card family. This patch renames num_link to num Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index c17f851..93163c9 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -385,17 +385,17 @@ static int asoc_simple_card_probe(struct platform_device *pdev) struct snd_soc_dai_link *dai_link; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; - int num_links, ret; + int num, ret; /* Get the number of DAI links */ if (np && of_get_child_by_name(np, PREFIX "dai-link")) - num_links = of_get_child_count(np); + num = of_get_child_count(np); else - num_links = 1; + num = 1; /* Allocate the private data and the DAI link array */ priv = devm_kzalloc(dev, - sizeof(*priv) + sizeof(*dai_link) * num_links, + sizeof(*priv) + sizeof(*dai_link) * num, GFP_KERNEL); if (!priv) return -ENOMEM; @@ -405,11 +405,11 @@ static int asoc_simple_card_probe(struct platform_device *pdev) priv->snd_card.owner = THIS_MODULE; priv->snd_card.dev = dev; priv->snd_card.dai_link = priv->dai_link; - priv->snd_card.num_links = num_links; + priv->snd_card.num_links = num; /* Get room for the other properties */ priv->dai_props = devm_kzalloc(dev, - sizeof(*priv->dai_props) * num_links, + sizeof(*priv->dai_props) * num, GFP_KERNEL); if (!priv->dai_props) return -ENOMEM; -- cgit v0.10.2 From b0133d9c4d7600fa43499c12897136fb4f38fd57 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Aug 2016 03:10:25 +0000 Subject: ASoC: simple-card: use kzalloc() for dai_props / dai_link simple sound card family are using very similar style, but because of its historical reason, there are small differences. For example pointer style, function name, caller postion etc... This patch synchronized simple card style to other simple card family. Now, simple card needs to 2 type of buffer for dai_props and dai_link. But, these used different style for buffer allocation. This patch make these same style as other simple card family. (= use kzalloc() for both) Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 93163c9..fe0bc5c 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -37,7 +37,7 @@ struct simple_card_data { unsigned int mclk_fs; struct asoc_simple_jack hp_jack; struct asoc_simple_jack mic_jack; - struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ + struct snd_soc_dai_link *dai_link; }; #define simple_priv_to_dev(priv) ((priv)->snd_card.dev) @@ -383,6 +383,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) { struct simple_card_data *priv; struct snd_soc_dai_link *dai_link; + struct simple_dai_props *dai_props; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; int num, ret; @@ -394,26 +395,24 @@ static int asoc_simple_card_probe(struct platform_device *pdev) num = 1; /* Allocate the private data and the DAI link array */ - priv = devm_kzalloc(dev, - sizeof(*priv) + sizeof(*dai_link) * num, - GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL); + dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL); + if (!dai_props || !dai_link) + return -ENOMEM; + + priv->dai_props = dai_props; + priv->dai_link = dai_link; + /* Init snd_soc_card */ - dai_link = priv->dai_link; priv->snd_card.owner = THIS_MODULE; priv->snd_card.dev = dev; priv->snd_card.dai_link = priv->dai_link; priv->snd_card.num_links = num; - /* Get room for the other properties */ - priv->dai_props = devm_kzalloc(dev, - sizeof(*priv->dai_props) * num, - GFP_KERNEL); - if (!priv->dai_props) - return -ENOMEM; - if (np && of_device_is_available(np)) { ret = asoc_simple_card_parse_of(np, priv); -- cgit v0.10.2 From c15ad605be164dd425c32af730376b6ad71d6cb3 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Wed, 24 Aug 2016 18:03:13 +0530 Subject: ASoC: Intel: Skylake: check manifest size For some platforms manifest data may not be defined, thus the private data would not be defined as well. So check the size of private data and proceed only if it is valid. Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 108ebb9..6bceab8 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -2401,6 +2401,10 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, struct skl *skl = ebus_to_skl(ebus); int ret = 0; + /* proceed only if we have private data defined */ + if (manifest->priv.size == 0) + return 0; + minfo = &skl->skl_sst->manifest; skl_tplg_get_manifest_data(manifest, bus->dev, minfo); -- cgit v0.10.2 From fc94733e56481d1e3d1ed0038f87cf105793effa Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Wed, 24 Aug 2016 18:03:14 +0530 Subject: ASoC: Intel: Skylake: Fix the inverted logic check While converting to new core hda capability parsing, one instance of check had inverted logic which was converted wrongly. Fixes: ec8ae5703da1 (ALSA: convert users to core bus_parse_capabilities) Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index eb1f00b..77bfd40 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1020,7 +1020,7 @@ static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream, { struct hdac_ext_bus *ebus = get_bus_ctx(substream); - if ((ebus_to_hbus(ebus))->ppcap) + if (!(ebus_to_hbus(ebus))->ppcap) return skl_coupled_trigger(substream, cmd); return 0; -- cgit v0.10.2 From 0b6d76bbd5e223d33ccdd73f3a717692d500d221 Mon Sep 17 00:00:00 2001 From: Jeeja KP Date: Wed, 24 Aug 2016 18:03:15 +0530 Subject: ASoC: Intel: Skylake: Fix DMA control config size DMA control IPC structure wrong config array length, So corrected the size Signed-off-by: Jeeja KP Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 96fa86d..37f45cc3 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -133,7 +133,7 @@ struct skl_i2s_config_blob { struct skl_dma_control { u32 node_id; u32 config_length; - u32 config_data[1]; + u32 config_data[0]; } __packed; struct skl_cpr_cfg { -- cgit v0.10.2 From b0fab9c6f636733161b723d1c223f2ce17637ff0 Mon Sep 17 00:00:00 2001 From: Dharageswari R Date: Wed, 24 Aug 2016 18:03:16 +0530 Subject: ASoC: Intel: Skylake: Unload all the loadable modules There could be more than one loadable module in a pipeline. So unload all modules whilst parsing the list. Signed-off-by: Dharageswari R Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 6bceab8..2d475b7 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -523,6 +523,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, struct skl_pipe *pipe) { + int ret; struct skl_pipe_module *w_module = NULL; struct skl_module_cfg *mconfig = NULL; @@ -530,9 +531,12 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, mconfig = w_module->w->priv; if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod && - mconfig->m_state > SKL_MODULE_UNINIT) - return ctx->dsp->fw_ops.unload_mod(ctx->dsp, + mconfig->m_state > SKL_MODULE_UNINIT) { + ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp, mconfig->id.module_id); + if (ret < 0) + return -EIO; + } } /* no modules to unload in this path, so return */ -- cgit v0.10.2 From 63d19e0693668de5ce46b5f0f948645bf43b546b Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Thu, 25 Aug 2016 11:39:32 +0100 Subject: ASoC: arizona: Wait for resume before enabling FLL When enabling an FLL use pm_runtime_get_sync() instead of pm_runtime_get() to ensure that all the register settings have been written out and the codec is powered-up before we write the enable bit. Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 0fc3b4b..ccb3ca2 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -2268,7 +2268,7 @@ static int arizona_enable_fll(struct arizona_fll *fll) ARIZONA_FLL1_SYNC_BW); if (!already_enabled) - pm_runtime_get(arizona->dev); + pm_runtime_get_sync(arizona->dev); regmap_update_bits_async(arizona->regmap, fll->base + 1, ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); -- cgit v0.10.2 From 9d5262ae9b52d5dd96a4c5bd1b683570b84a011e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 2 Sep 2016 00:13:09 +0200 Subject: ALSA: cs5535audio: constify snd_pcm_ops structures Check for snd_pcm_ops structures that are only stored in the ops field of a snd_soc_platform_driver structure or passed as the third argument to snd_pcm_set_ops. The corresponding field or parameter is declared const, so snd_pcm_ops structures that have this property can be declared as const also. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @r disable optional_qualifier@ identifier i; position p; @@ static struct snd_pcm_ops i@p = { ... }; @ok1@ identifier r.i; struct snd_soc_platform_driver e; position p; @@ e.ops = &i@p; @ok2@ identifier r.i; expression e1, e2; position p; @@ snd_pcm_set_ops(e1, e2, &i@p) @bad@ position p != {r.p,ok1.p,ok2.p}; identifier r.i; struct snd_pcm_ops e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct snd_pcm_ops i = { ... }; // Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index 27fa57d..c208c1d 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c @@ -380,7 +380,7 @@ static int snd_cs5535audio_capture_prepare(struct snd_pcm_substream *substream) substream->runtime->rate); } -static struct snd_pcm_ops snd_cs5535audio_playback_ops = { +static const struct snd_pcm_ops snd_cs5535audio_playback_ops = { .open = snd_cs5535audio_playback_open, .close = snd_cs5535audio_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -391,7 +391,7 @@ static struct snd_pcm_ops snd_cs5535audio_playback_ops = { .pointer = snd_cs5535audio_pcm_pointer, }; -static struct snd_pcm_ops snd_cs5535audio_capture_ops = { +static const struct snd_pcm_ops snd_cs5535audio_capture_ops = { .open = snd_cs5535audio_capture_open, .close = snd_cs5535audio_capture_close, .ioctl = snd_pcm_lib_ioctl, -- cgit v0.10.2 From 6769e988b0062bf8d63d35b0fdbb47b385dd3252 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 2 Sep 2016 00:13:10 +0200 Subject: ALSA: constify snd_pcm_ops structures Check for snd_pcm_ops structures that are only stored in the ops field of a snd_soc_platform_driver structure or passed as the third argument to snd_pcm_set_ops. The corresponding field or parameter is declared const, so snd_pcm_ops structures that have this property can be declared as const also. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @r disable optional_qualifier@ identifier i; position p; @@ static struct snd_pcm_ops i@p = { ... }; @ok1@ identifier r.i; struct snd_soc_platform_driver e; position p; @@ e.ops = &i@p; @ok2@ identifier r.i; expression e1, e2; position p; @@ snd_pcm_set_ops(e1, e2, &i@p) @bad@ position p != {r.p,ok1.p,ok2.p}; identifier r.i; struct snd_pcm_ops e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct snd_pcm_ops i = { ... }; // Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai diff --git a/sound/pci/als300.c b/sound/pci/als300.c index add3176..ab75601 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -563,7 +563,7 @@ static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream) return bytes_to_frames(substream->runtime, current_ptr); } -static struct snd_pcm_ops snd_als300_playback_ops = { +static const struct snd_pcm_ops snd_als300_playback_ops = { .open = snd_als300_playback_open, .close = snd_als300_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -574,7 +574,7 @@ static struct snd_pcm_ops snd_als300_playback_ops = { .pointer = snd_als300_pointer, }; -static struct snd_pcm_ops snd_als300_capture_ops = { +static const struct snd_pcm_ops snd_als300_capture_ops = { .open = snd_als300_capture_open, .close = snd_als300_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index ff39a0c..edabe13 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -672,7 +672,7 @@ static int snd_als4000_capture_close(struct snd_pcm_substream *substream) /******************************************************************/ -static struct snd_pcm_ops snd_als4000_playback_ops = { +static const struct snd_pcm_ops snd_als4000_playback_ops = { .open = snd_als4000_playback_open, .close = snd_als4000_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -683,7 +683,7 @@ static struct snd_pcm_ops snd_als4000_playback_ops = { .pointer = snd_als4000_playback_pointer }; -static struct snd_pcm_ops snd_als4000_capture_ops = { +static const struct snd_pcm_ops snd_als4000_capture_ops = { .open = snd_als4000_capture_open, .close = snd_als4000_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 1039ecc..976a3d2 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -1138,7 +1138,7 @@ static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = { +static const struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = { .open = snd_card_asihpi_playback_open, .close = snd_card_asihpi_playback_close, .ioctl = snd_card_asihpi_playback_ioctl, @@ -1305,7 +1305,7 @@ static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = { +static const struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = { .open = snd_card_asihpi_capture_open, .close = snd_card_asihpi_capture_close, .ioctl = snd_card_asihpi_capture_ioctl, diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 2ce0022..a40c918 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1148,7 +1148,7 @@ static int snd_atiixp_spdif_close(struct snd_pcm_substream *substream) } /* AC97 playback */ -static struct snd_pcm_ops snd_atiixp_playback_ops = { +static const struct snd_pcm_ops snd_atiixp_playback_ops = { .open = snd_atiixp_playback_open, .close = snd_atiixp_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1160,7 +1160,7 @@ static struct snd_pcm_ops snd_atiixp_playback_ops = { }; /* AC97 capture */ -static struct snd_pcm_ops snd_atiixp_capture_ops = { +static const struct snd_pcm_ops snd_atiixp_capture_ops = { .open = snd_atiixp_capture_open, .close = snd_atiixp_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1172,7 +1172,7 @@ static struct snd_pcm_ops snd_atiixp_capture_ops = { }; /* SPDIF playback */ -static struct snd_pcm_ops snd_atiixp_spdif_ops = { +static const struct snd_pcm_ops snd_atiixp_spdif_ops = { .open = snd_atiixp_spdif_open, .close = snd_atiixp_spdif_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index c534552..40152fe 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -947,7 +947,7 @@ static int snd_atiixp_capture_close(struct snd_pcm_substream *substream) /* AC97 playback */ -static struct snd_pcm_ops snd_atiixp_playback_ops = { +static const struct snd_pcm_ops snd_atiixp_playback_ops = { .open = snd_atiixp_playback_open, .close = snd_atiixp_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -959,7 +959,7 @@ static struct snd_pcm_ops snd_atiixp_playback_ops = { }; /* AC97 capture */ -static struct snd_pcm_ops snd_atiixp_capture_ops = { +static const struct snd_pcm_ops snd_atiixp_capture_ops = { .open = snd_atiixp_capture_open, .close = snd_atiixp_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index 1677143..57bbb87 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c @@ -179,7 +179,7 @@ static struct pci_driver aw2_driver = { module_pci_driver(aw2_driver); /* operators for playback PCM alsa interface */ -static struct snd_pcm_ops snd_aw2_playback_ops = { +static const struct snd_pcm_ops snd_aw2_playback_ops = { .open = snd_aw2_pcm_playback_open, .close = snd_aw2_pcm_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -191,7 +191,7 @@ static struct snd_pcm_ops snd_aw2_playback_ops = { }; /* operators for capture PCM alsa interface */ -static struct snd_pcm_ops snd_aw2_capture_ops = { +static const struct snd_pcm_ops snd_aw2_capture_ops = { .open = snd_aw2_pcm_capture_open, .close = snd_aw2_pcm_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 5e2ef0b..80c4a44 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -2090,7 +2090,7 @@ snd_azf3328_pcm_close(struct snd_pcm_substream *substream /******************************************************************/ -static struct snd_pcm_ops snd_azf3328_playback_ops = { +static const struct snd_pcm_ops snd_azf3328_playback_ops = { .open = snd_azf3328_pcm_playback_open, .close = snd_azf3328_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -2101,7 +2101,7 @@ static struct snd_pcm_ops snd_azf3328_playback_ops = { .pointer = snd_azf3328_pcm_pointer }; -static struct snd_pcm_ops snd_azf3328_capture_ops = { +static const struct snd_pcm_ops snd_azf3328_capture_ops = { .open = snd_azf3328_pcm_capture_open, .close = snd_azf3328_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -2112,7 +2112,7 @@ static struct snd_pcm_ops snd_azf3328_capture_ops = { .pointer = snd_azf3328_pcm_pointer }; -static struct snd_pcm_ops snd_azf3328_i2s_out_ops = { +static const struct snd_pcm_ops snd_azf3328_i2s_out_ops = { .open = snd_azf3328_pcm_i2s_out_open, .close = snd_azf3328_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index d3cd956..6165a57 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1109,7 +1109,7 @@ snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream) } /* operators */ -static struct snd_pcm_ops snd_ca0106_playback_front_ops = { +static const struct snd_pcm_ops snd_ca0106_playback_front_ops = { .open = snd_ca0106_pcm_open_playback_front, .close = snd_ca0106_pcm_close_playback, .ioctl = snd_pcm_lib_ioctl, @@ -1120,7 +1120,7 @@ static struct snd_pcm_ops snd_ca0106_playback_front_ops = { .pointer = snd_ca0106_pcm_pointer_playback, }; -static struct snd_pcm_ops snd_ca0106_capture_0_ops = { +static const struct snd_pcm_ops snd_ca0106_capture_0_ops = { .open = snd_ca0106_pcm_open_0_capture, .close = snd_ca0106_pcm_close_capture, .ioctl = snd_pcm_lib_ioctl, @@ -1131,7 +1131,7 @@ static struct snd_pcm_ops snd_ca0106_capture_0_ops = { .pointer = snd_ca0106_pcm_pointer_capture, }; -static struct snd_pcm_ops snd_ca0106_capture_1_ops = { +static const struct snd_pcm_ops snd_ca0106_capture_1_ops = { .open = snd_ca0106_pcm_open_1_capture, .close = snd_ca0106_pcm_close_capture, .ioctl = snd_pcm_lib_ioctl, @@ -1142,7 +1142,7 @@ static struct snd_pcm_ops snd_ca0106_capture_1_ops = { .pointer = snd_ca0106_pcm_pointer_capture, }; -static struct snd_pcm_ops snd_ca0106_capture_2_ops = { +static const struct snd_pcm_ops snd_ca0106_capture_2_ops = { .open = snd_ca0106_pcm_open_2_capture, .close = snd_ca0106_pcm_close_capture, .ioctl = snd_pcm_lib_ioctl, @@ -1153,7 +1153,7 @@ static struct snd_pcm_ops snd_ca0106_capture_2_ops = { .pointer = snd_ca0106_pcm_pointer_capture, }; -static struct snd_pcm_ops snd_ca0106_capture_3_ops = { +static const struct snd_pcm_ops snd_ca0106_capture_3_ops = { .open = snd_ca0106_pcm_open_3_capture, .close = snd_ca0106_pcm_close_capture, .ioctl = snd_pcm_lib_ioctl, @@ -1164,7 +1164,7 @@ static struct snd_pcm_ops snd_ca0106_capture_3_ops = { .pointer = snd_ca0106_pcm_pointer_capture, }; -static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = { +static const struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = { .open = snd_ca0106_pcm_open_playback_center_lfe, .close = snd_ca0106_pcm_close_playback, .ioctl = snd_pcm_lib_ioctl, @@ -1175,7 +1175,7 @@ static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = { .pointer = snd_ca0106_pcm_pointer_playback, }; -static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = { +static const struct snd_pcm_ops snd_ca0106_playback_unknown_ops = { .open = snd_ca0106_pcm_open_playback_unknown, .close = snd_ca0106_pcm_close_playback, .ioctl = snd_pcm_lib_ioctl, @@ -1186,7 +1186,7 @@ static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = { .pointer = snd_ca0106_pcm_pointer_playback, }; -static struct snd_pcm_ops snd_ca0106_playback_rear_ops = { +static const struct snd_pcm_ops snd_ca0106_playback_rear_ops = { .open = snd_ca0106_pcm_open_playback_rear, .close = snd_ca0106_pcm_close_playback, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 24cdcba..73f5935 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -1838,7 +1838,7 @@ static int snd_cmipci_capture_spdif_close(struct snd_pcm_substream *substream) /* */ -static struct snd_pcm_ops snd_cmipci_playback_ops = { +static const struct snd_pcm_ops snd_cmipci_playback_ops = { .open = snd_cmipci_playback_open, .close = snd_cmipci_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1849,7 +1849,7 @@ static struct snd_pcm_ops snd_cmipci_playback_ops = { .pointer = snd_cmipci_playback_pointer, }; -static struct snd_pcm_ops snd_cmipci_capture_ops = { +static const struct snd_pcm_ops snd_cmipci_capture_ops = { .open = snd_cmipci_capture_open, .close = snd_cmipci_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1860,7 +1860,7 @@ static struct snd_pcm_ops snd_cmipci_capture_ops = { .pointer = snd_cmipci_capture_pointer, }; -static struct snd_pcm_ops snd_cmipci_playback2_ops = { +static const struct snd_pcm_ops snd_cmipci_playback2_ops = { .open = snd_cmipci_playback2_open, .close = snd_cmipci_playback2_close, .ioctl = snd_pcm_lib_ioctl, @@ -1871,7 +1871,7 @@ static struct snd_pcm_ops snd_cmipci_playback2_ops = { .pointer = snd_cmipci_capture_pointer, /* channel B */ }; -static struct snd_pcm_ops snd_cmipci_playback_spdif_ops = { +static const struct snd_pcm_ops snd_cmipci_playback_spdif_ops = { .open = snd_cmipci_playback_spdif_open, .close = snd_cmipci_playback_spdif_close, .ioctl = snd_pcm_lib_ioctl, @@ -1882,7 +1882,7 @@ static struct snd_pcm_ops snd_cmipci_playback_spdif_ops = { .pointer = snd_cmipci_playback_pointer, }; -static struct snd_pcm_ops snd_cmipci_capture_spdif_ops = { +static const struct snd_pcm_ops snd_cmipci_capture_spdif_ops = { .open = snd_cmipci_capture_spdif_open, .close = snd_cmipci_capture_spdif_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index c296fd0..615d8a9 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -951,7 +951,7 @@ static int snd_cs4281_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_cs4281_playback_ops = { +static const struct snd_pcm_ops snd_cs4281_playback_ops = { .open = snd_cs4281_playback_open, .close = snd_cs4281_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -962,7 +962,7 @@ static struct snd_pcm_ops snd_cs4281_playback_ops = { .pointer = snd_cs4281_pointer, }; -static struct snd_pcm_ops snd_cs4281_capture_ops = { +static const struct snd_pcm_ops snd_cs4281_capture_ops = { .open = snd_cs4281_capture_open, .close = snd_cs4281_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index d86c474..9749780 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c @@ -372,7 +372,7 @@ ct_pcm_capture_pointer(struct snd_pcm_substream *substream) } /* PCM operators for playback */ -static struct snd_pcm_ops ct_pcm_playback_ops = { +static const struct snd_pcm_ops ct_pcm_playback_ops = { .open = ct_pcm_playback_open, .close = ct_pcm_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -385,7 +385,7 @@ static struct snd_pcm_ops ct_pcm_playback_ops = { }; /* PCM operators for capture */ -static struct snd_pcm_ops ct_pcm_capture_ops = { +static const struct snd_pcm_ops ct_pcm_capture_ops = { .open = ct_pcm_capture_open, .close = ct_pcm_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 6d1b98d..921037e 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -548,7 +548,7 @@ snd_emu10k1x_pcm_pointer(struct snd_pcm_substream *substream) } /* operators */ -static struct snd_pcm_ops snd_emu10k1x_playback_ops = { +static const struct snd_pcm_ops snd_emu10k1x_playback_ops = { .open = snd_emu10k1x_playback_open, .close = snd_emu10k1x_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -694,7 +694,7 @@ snd_emu10k1x_pcm_pointer_capture(struct snd_pcm_substream *substream) return ptr; } -static struct snd_pcm_ops snd_emu10k1x_capture_ops = { +static const struct snd_pcm_ops snd_emu10k1x_capture_ops = { .open = snd_emu10k1x_pcm_open_capture, .close = snd_emu10k1x_pcm_close_capture, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 14a305b..37be1e1 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -1364,7 +1364,7 @@ static int snd_emu10k1_capture_efx_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_emu10k1_playback_ops = { +static const struct snd_pcm_ops snd_emu10k1_playback_ops = { .open = snd_emu10k1_playback_open, .close = snd_emu10k1_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1376,7 +1376,7 @@ static struct snd_pcm_ops snd_emu10k1_playback_ops = { .page = snd_pcm_sgbuf_ops_page, }; -static struct snd_pcm_ops snd_emu10k1_capture_ops = { +static const struct snd_pcm_ops snd_emu10k1_capture_ops = { .open = snd_emu10k1_capture_open, .close = snd_emu10k1_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1388,7 +1388,7 @@ static struct snd_pcm_ops snd_emu10k1_capture_ops = { }; /* EFX playback */ -static struct snd_pcm_ops snd_emu10k1_efx_playback_ops = { +static const struct snd_pcm_ops snd_emu10k1_efx_playback_ops = { .open = snd_emu10k1_efx_playback_open, .close = snd_emu10k1_efx_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1455,7 +1455,7 @@ int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device) } -static struct snd_pcm_ops snd_emu10k1_capture_mic_ops = { +static const struct snd_pcm_ops snd_emu10k1_capture_mic_ops = { .open = snd_emu10k1_capture_mic_open, .close = snd_emu10k1_capture_mic_close, .ioctl = snd_pcm_lib_ioctl, @@ -1550,7 +1550,7 @@ static struct snd_kcontrol_new snd_emu10k1_pcm_efx_voices_mask = { .put = snd_emu10k1_pcm_efx_voices_mask_put }; -static struct snd_pcm_ops snd_emu10k1_capture_efx_ops = { +static const struct snd_pcm_ops snd_emu10k1_capture_efx_ops = { .open = snd_emu10k1_capture_efx_open, .close = snd_emu10k1_capture_efx_close, .ioctl = snd_pcm_lib_ioctl, @@ -1791,7 +1791,7 @@ static int snd_emu10k1_fx8010_playback_close(struct snd_pcm_substream *substream return 0; } -static struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = { +static const struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = { .open = snd_emu10k1_fx8010_playback_open, .close = snd_emu10k1_fx8010_playback_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 3c60b43..fd9ab44 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -601,7 +601,7 @@ snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream) } /* operators */ -static struct snd_pcm_ops snd_p16v_playback_front_ops = { +static const struct snd_pcm_ops snd_p16v_playback_front_ops = { .open = snd_p16v_pcm_open_playback_front, .close = snd_p16v_pcm_close_playback, .ioctl = snd_pcm_lib_ioctl, @@ -612,7 +612,7 @@ static struct snd_pcm_ops snd_p16v_playback_front_ops = { .pointer = snd_p16v_pcm_pointer_playback, }; -static struct snd_pcm_ops snd_p16v_capture_ops = { +static const struct snd_pcm_ops snd_p16v_capture_ops = { .open = snd_p16v_pcm_open_capture, .close = snd_p16v_pcm_close_capture, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 626cd21..7e760fe 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -1227,7 +1227,7 @@ static int snd_ensoniq_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_ensoniq_playback1_ops = { +static const struct snd_pcm_ops snd_ensoniq_playback1_ops = { .open = snd_ensoniq_playback1_open, .close = snd_ensoniq_playback1_close, .ioctl = snd_pcm_lib_ioctl, @@ -1238,7 +1238,7 @@ static struct snd_pcm_ops snd_ensoniq_playback1_ops = { .pointer = snd_ensoniq_playback1_pointer, }; -static struct snd_pcm_ops snd_ensoniq_playback2_ops = { +static const struct snd_pcm_ops snd_ensoniq_playback2_ops = { .open = snd_ensoniq_playback2_open, .close = snd_ensoniq_playback2_close, .ioctl = snd_pcm_lib_ioctl, @@ -1249,7 +1249,7 @@ static struct snd_pcm_ops snd_ensoniq_playback2_ops = { .pointer = snd_ensoniq_playback2_pointer, }; -static struct snd_pcm_ops snd_ensoniq_capture_ops = { +static const struct snd_pcm_ops snd_ensoniq_capture_ops = { .open = snd_ensoniq_capture_open, .close = snd_ensoniq_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 8963d76..6813558 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -992,7 +992,7 @@ static int snd_es1938_playback_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_es1938_playback_ops = { +static const struct snd_pcm_ops snd_es1938_playback_ops = { .open = snd_es1938_playback_open, .close = snd_es1938_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1003,7 +1003,7 @@ static struct snd_pcm_ops snd_es1938_playback_ops = { .pointer = snd_es1938_playback_pointer, }; -static struct snd_pcm_ops snd_es1938_capture_ops = { +static const struct snd_pcm_ops snd_es1938_capture_ops = { .open = snd_es1938_capture_open, .close = snd_es1938_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 514f260..8146fb7 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -1677,7 +1677,7 @@ static int snd_es1968_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_es1968_playback_ops = { +static const struct snd_pcm_ops snd_es1968_playback_ops = { .open = snd_es1968_playback_open, .close = snd_es1968_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1688,7 +1688,7 @@ static struct snd_pcm_ops snd_es1968_playback_ops = { .pointer = snd_es1968_pcm_pointer, }; -static struct snd_pcm_ops snd_es1968_capture_ops = { +static const struct snd_pcm_ops snd_es1968_capture_ops = { .open = snd_es1968_capture_open, .close = snd_es1968_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index bade9b9..c47287d 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -691,7 +691,7 @@ static int snd_fm801_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_fm801_playback_ops = { +static const struct snd_pcm_ops snd_fm801_playback_ops = { .open = snd_fm801_playback_open, .close = snd_fm801_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -702,7 +702,7 @@ static struct snd_pcm_ops snd_fm801_playback_ops = { .pointer = snd_fm801_playback_pointer, }; -static struct snd_pcm_ops snd_fm801_capture_ops = { +static const struct snd_pcm_ops snd_fm801_capture_ops = { .open = snd_fm801_capture_open, .close = snd_fm801_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 2ad3b44..5008785 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -696,7 +696,7 @@ static int azx_pcm_mmap(struct snd_pcm_substream *substream, return snd_pcm_lib_default_mmap(substream, area); } -static struct snd_pcm_ops azx_pcm_ops = { +static const struct snd_pcm_ops azx_pcm_ops = { .open = azx_pcm_open, .close = azx_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 8ae3bb7..b4aa4c1 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -847,7 +847,7 @@ static int snd_ice1712_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_ice1712_playback_ops = { +static const struct snd_pcm_ops snd_ice1712_playback_ops = { .open = snd_ice1712_playback_open, .close = snd_ice1712_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -858,7 +858,7 @@ static struct snd_pcm_ops snd_ice1712_playback_ops = { .pointer = snd_ice1712_playback_pointer, }; -static struct snd_pcm_ops snd_ice1712_playback_ds_ops = { +static const struct snd_pcm_ops snd_ice1712_playback_ds_ops = { .open = snd_ice1712_playback_ds_open, .close = snd_ice1712_playback_ds_close, .ioctl = snd_pcm_lib_ioctl, @@ -869,7 +869,7 @@ static struct snd_pcm_ops snd_ice1712_playback_ds_ops = { .pointer = snd_ice1712_playback_ds_pointer, }; -static struct snd_pcm_ops snd_ice1712_capture_ops = { +static const struct snd_pcm_ops snd_ice1712_capture_ops = { .open = snd_ice1712_capture_open, .close = snd_ice1712_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1228,7 +1228,7 @@ static int snd_ice1712_capture_pro_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_ice1712_playback_pro_ops = { +static const struct snd_pcm_ops snd_ice1712_playback_pro_ops = { .open = snd_ice1712_playback_pro_open, .close = snd_ice1712_playback_pro_close, .ioctl = snd_pcm_lib_ioctl, @@ -1239,7 +1239,7 @@ static struct snd_pcm_ops snd_ice1712_playback_pro_ops = { .pointer = snd_ice1712_playback_pro_pointer, }; -static struct snd_pcm_ops snd_ice1712_capture_pro_ops = { +static const struct snd_pcm_ops snd_ice1712_capture_pro_ops = { .open = snd_ice1712_capture_pro_open, .close = snd_ice1712_capture_pro_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 0b22c00..cd68114 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -1113,7 +1113,7 @@ static int snd_vt1724_capture_pro_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_vt1724_playback_pro_ops = { +static const struct snd_pcm_ops snd_vt1724_playback_pro_ops = { .open = snd_vt1724_playback_pro_open, .close = snd_vt1724_playback_pro_close, .ioctl = snd_pcm_lib_ioctl, @@ -1124,7 +1124,7 @@ static struct snd_pcm_ops snd_vt1724_playback_pro_ops = { .pointer = snd_vt1724_playback_pro_pointer, }; -static struct snd_pcm_ops snd_vt1724_capture_pro_ops = { +static const struct snd_pcm_ops snd_vt1724_capture_pro_ops = { .open = snd_vt1724_capture_pro_open, .close = snd_vt1724_capture_pro_close, .ioctl = snd_pcm_lib_ioctl, @@ -1292,7 +1292,7 @@ static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_vt1724_playback_spdif_ops = { +static const struct snd_pcm_ops snd_vt1724_playback_spdif_ops = { .open = snd_vt1724_playback_spdif_open, .close = snd_vt1724_playback_spdif_close, .ioctl = snd_pcm_lib_ioctl, @@ -1303,7 +1303,7 @@ static struct snd_pcm_ops snd_vt1724_playback_spdif_ops = { .pointer = snd_vt1724_pcm_pointer, }; -static struct snd_pcm_ops snd_vt1724_capture_spdif_ops = { +static const struct snd_pcm_ops snd_vt1724_capture_spdif_ops = { .open = snd_vt1724_capture_spdif_open, .close = snd_vt1724_capture_spdif_close, .ioctl = snd_pcm_lib_ioctl, @@ -1437,7 +1437,7 @@ static int snd_vt1724_playback_indep_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_vt1724_playback_indep_ops = { +static const struct snd_pcm_ops snd_vt1724_playback_indep_ops = { .open = snd_vt1724_playback_indep_open, .close = snd_vt1724_playback_indep_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 9e1ad11..565f7f5 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -1681,7 +1681,7 @@ static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream, return snd_korg1212_copy_to(korg1212, dst, pos, count, 0, korg1212->channels * 2); } -static struct snd_pcm_ops snd_korg1212_playback_ops = { +static const struct snd_pcm_ops snd_korg1212_playback_ops = { .open = snd_korg1212_playback_open, .close = snd_korg1212_playback_close, .ioctl = snd_korg1212_ioctl, @@ -1693,7 +1693,7 @@ static struct snd_pcm_ops snd_korg1212_playback_ops = { .silence = snd_korg1212_playback_silence, }; -static struct snd_pcm_ops snd_korg1212_capture_ops = { +static const struct snd_pcm_ops snd_korg1212_capture_ops = { .open = snd_korg1212_capture_open, .close = snd_korg1212_capture_close, .ioctl = snd_korg1212_ioctl, diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c index 3bd6985..1268ba3 100644 --- a/sound/pci/lola/lola_pcm.c +++ b/sound/pci/lola/lola_pcm.c @@ -586,7 +586,7 @@ void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits) } } -static struct snd_pcm_ops lola_pcm_ops = { +static const struct snd_pcm_ops lola_pcm_ops = { .open = lola_pcm_open, .close = lola_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index 8b8e2e5..c0f0c34 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c @@ -804,7 +804,7 @@ mac_ready: return err; } -static struct snd_pcm_ops lx_ops_playback = { +static const struct snd_pcm_ops lx_ops_playback = { .open = lx_pcm_open, .close = lx_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -815,7 +815,7 @@ static struct snd_pcm_ops lx_ops_playback = { .pointer = lx_pcm_stream_pointer, }; -static struct snd_pcm_ops lx_ops_capture = { +static const struct snd_pcm_ops lx_ops_capture = { .open = lx_pcm_open, .close = lx_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 17ae926..cafea6d 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -1834,7 +1834,7 @@ snd_m3_capture_close(struct snd_pcm_substream *subs) * create pcm instance */ -static struct snd_pcm_ops snd_m3_playback_ops = { +static const struct snd_pcm_ops snd_m3_playback_ops = { .open = snd_m3_playback_open, .close = snd_m3_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1845,7 +1845,7 @@ static struct snd_pcm_ops snd_m3_playback_ops = { .pointer = snd_m3_pcm_pointer, }; -static struct snd_pcm_ops snd_m3_capture_ops = { +static const struct snd_pcm_ops snd_m3_capture_ops = { .open = snd_m3_capture_open, .close = snd_m3_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 25c0ddd..80d4399 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -922,7 +922,7 @@ static snd_pcm_uframes_t snd_mixart_stream_pointer(struct snd_pcm_substream *sub -static struct snd_pcm_ops snd_mixart_playback_ops = { +static const struct snd_pcm_ops snd_mixart_playback_ops = { .open = snd_mixart_playback_open, .close = snd_mixart_close, .ioctl = snd_pcm_lib_ioctl, @@ -933,7 +933,7 @@ static struct snd_pcm_ops snd_mixart_playback_ops = { .pointer = snd_mixart_stream_pointer, }; -static struct snd_pcm_ops snd_mixart_capture_ops = { +static const struct snd_pcm_ops snd_mixart_capture_ops = { .open = snd_mixart_capture_open, .close = snd_mixart_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 4735e27..103fe31 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -902,7 +902,7 @@ snd_nm256_capture_close(struct snd_pcm_substream *substream) /* * create a pcm instance */ -static struct snd_pcm_ops snd_nm256_playback_ops = { +static const struct snd_pcm_ops snd_nm256_playback_ops = { .open = snd_nm256_playback_open, .close = snd_nm256_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -917,7 +917,7 @@ static struct snd_pcm_ops snd_nm256_playback_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_nm256_capture_ops = { +static const struct snd_pcm_ops snd_nm256_capture_ops = { .open = snd_nm256_capture_open, .close = snd_nm256_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 9293235..bb7eee9 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -1146,7 +1146,7 @@ static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs) } -static struct snd_pcm_ops pcxhr_ops = { +static const struct snd_pcm_ops pcxhr_ops = { .open = pcxhr_open, .close = pcxhr_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 067a912..ae41fcb 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1669,7 +1669,7 @@ static int snd_riptide_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_riptide_playback_ops = { +static const struct snd_pcm_ops snd_riptide_playback_ops = { .open = snd_riptide_playback_open, .close = snd_riptide_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1680,7 +1680,7 @@ static struct snd_pcm_ops snd_riptide_playback_ops = { .trigger = snd_riptide_trigger, .pointer = snd_riptide_pointer, }; -static struct snd_pcm_ops snd_riptide_capture_ops = { +static const struct snd_pcm_ops snd_riptide_capture_ops = { .open = snd_riptide_capture_open, .close = snd_riptide_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index cd94ac5..96d15db 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1196,7 +1196,7 @@ snd_rme32_capture_fd_pointer(struct snd_pcm_substream *substream) } /* for halfduplex mode */ -static struct snd_pcm_ops snd_rme32_playback_spdif_ops = { +static const struct snd_pcm_ops snd_rme32_playback_spdif_ops = { .open = snd_rme32_playback_spdif_open, .close = snd_rme32_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1210,7 +1210,7 @@ static struct snd_pcm_ops snd_rme32_playback_spdif_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_rme32_capture_spdif_ops = { +static const struct snd_pcm_ops snd_rme32_capture_spdif_ops = { .open = snd_rme32_capture_spdif_open, .close = snd_rme32_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1223,7 +1223,7 @@ static struct snd_pcm_ops snd_rme32_capture_spdif_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_rme32_playback_adat_ops = { +static const struct snd_pcm_ops snd_rme32_playback_adat_ops = { .open = snd_rme32_playback_adat_open, .close = snd_rme32_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1236,7 +1236,7 @@ static struct snd_pcm_ops snd_rme32_playback_adat_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_rme32_capture_adat_ops = { +static const struct snd_pcm_ops snd_rme32_capture_adat_ops = { .open = snd_rme32_capture_adat_open, .close = snd_rme32_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1249,7 +1249,7 @@ static struct snd_pcm_ops snd_rme32_capture_adat_ops = { }; /* for fullduplex mode */ -static struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = { +static const struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = { .open = snd_rme32_playback_spdif_open, .close = snd_rme32_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1261,7 +1261,7 @@ static struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = { .ack = snd_rme32_playback_fd_ack, }; -static struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = { +static const struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = { .open = snd_rme32_capture_spdif_open, .close = snd_rme32_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1273,7 +1273,7 @@ static struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = { .ack = snd_rme32_capture_fd_ack, }; -static struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = { +static const struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = { .open = snd_rme32_playback_adat_open, .close = snd_rme32_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1284,7 +1284,7 @@ static struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = { .ack = snd_rme32_playback_fd_ack, }; -static struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = { +static const struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = { .open = snd_rme32_capture_adat_open, .close = snd_rme32_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 41c31db..05b9da3 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -1505,7 +1505,7 @@ snd_rme96_capture_pointer(struct snd_pcm_substream *substream) return snd_rme96_capture_ptr(rme96); } -static struct snd_pcm_ops snd_rme96_playback_spdif_ops = { +static const struct snd_pcm_ops snd_rme96_playback_spdif_ops = { .open = snd_rme96_playback_spdif_open, .close = snd_rme96_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1518,7 +1518,7 @@ static struct snd_pcm_ops snd_rme96_playback_spdif_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_rme96_capture_spdif_ops = { +static const struct snd_pcm_ops snd_rme96_capture_spdif_ops = { .open = snd_rme96_capture_spdif_open, .close = snd_rme96_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1530,7 +1530,7 @@ static struct snd_pcm_ops snd_rme96_capture_spdif_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_rme96_playback_adat_ops = { +static const struct snd_pcm_ops snd_rme96_playback_adat_ops = { .open = snd_rme96_playback_adat_open, .close = snd_rme96_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1543,7 +1543,7 @@ static struct snd_pcm_ops snd_rme96_playback_adat_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_rme96_capture_adat_ops = { +static const struct snd_pcm_ops snd_rme96_capture_adat_ops = { .open = snd_rme96_capture_adat_open, .close = snd_rme96_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 7c8941b..b94fc63 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -4861,7 +4861,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne return 0; } -static struct snd_pcm_ops snd_hdsp_playback_ops = { +static const struct snd_pcm_ops snd_hdsp_playback_ops = { .open = snd_hdsp_playback_open, .close = snd_hdsp_playback_release, .ioctl = snd_hdsp_ioctl, @@ -4873,7 +4873,7 @@ static struct snd_pcm_ops snd_hdsp_playback_ops = { .silence = snd_hdsp_hw_silence, }; -static struct snd_pcm_ops snd_hdsp_capture_ops = { +static const struct snd_pcm_ops snd_hdsp_capture_ops = { .open = snd_hdsp_capture_open, .close = snd_hdsp_capture_release, .ioctl = snd_hdsp_ioctl, diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 0e51a00..14bbf55 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -6361,7 +6361,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, return 0; } -static struct snd_pcm_ops snd_hdspm_ops = { +static const struct snd_pcm_ops snd_hdspm_ops = { .open = snd_hdspm_open, .close = snd_hdspm_release, .ioctl = snd_hdspm_ioctl, diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index fdbc0aa..55172c6 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -2368,7 +2368,7 @@ static int snd_rme9652_capture_release(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_rme9652_playback_ops = { +static const struct snd_pcm_ops snd_rme9652_playback_ops = { .open = snd_rme9652_playback_open, .close = snd_rme9652_playback_release, .ioctl = snd_rme9652_ioctl, @@ -2380,7 +2380,7 @@ static struct snd_pcm_ops snd_rme9652_playback_ops = { .silence = snd_rme9652_hw_silence, }; -static struct snd_pcm_ops snd_rme9652_capture_ops = { +static const struct snd_pcm_ops snd_rme9652_capture_ops = { .open = snd_rme9652_capture_open, .close = snd_rme9652_capture_release, .ioctl = snd_rme9652_ioctl, diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 1b6fad7..e1a1387 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -857,7 +857,7 @@ static int snd_sonicvibes_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_sonicvibes_playback_ops = { +static const struct snd_pcm_ops snd_sonicvibes_playback_ops = { .open = snd_sonicvibes_playback_open, .close = snd_sonicvibes_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -868,7 +868,7 @@ static struct snd_pcm_ops snd_sonicvibes_playback_ops = { .pointer = snd_sonicvibes_playback_pointer, }; -static struct snd_pcm_ops snd_sonicvibes_capture_ops = { +static const struct snd_pcm_ops snd_sonicvibes_capture_ops = { .open = snd_sonicvibes_capture_open, .close = snd_sonicvibes_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 599d2b7..27f0ed8 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -2070,7 +2070,7 @@ static int snd_trident_foldback_close(struct snd_pcm_substream *substream) PCM operations ---------------------------------------------------------------------------*/ -static struct snd_pcm_ops snd_trident_playback_ops = { +static const struct snd_pcm_ops snd_trident_playback_ops = { .open = snd_trident_playback_open, .close = snd_trident_playback_close, .ioctl = snd_trident_ioctl, @@ -2081,7 +2081,7 @@ static struct snd_pcm_ops snd_trident_playback_ops = { .pointer = snd_trident_playback_pointer, }; -static struct snd_pcm_ops snd_trident_nx_playback_ops = { +static const struct snd_pcm_ops snd_trident_nx_playback_ops = { .open = snd_trident_playback_open, .close = snd_trident_playback_close, .ioctl = snd_trident_ioctl, @@ -2115,7 +2115,7 @@ static struct snd_pcm_ops snd_trident_si7018_capture_ops = { .pointer = snd_trident_playback_pointer, }; -static struct snd_pcm_ops snd_trident_foldback_ops = { +static const struct snd_pcm_ops snd_trident_foldback_ops = { .open = snd_trident_foldback_open, .close = snd_trident_foldback_close, .ioctl = snd_trident_ioctl, @@ -2126,7 +2126,7 @@ static struct snd_pcm_ops snd_trident_foldback_ops = { .pointer = snd_trident_playback_pointer, }; -static struct snd_pcm_ops snd_trident_nx_foldback_ops = { +static const struct snd_pcm_ops snd_trident_nx_foldback_ops = { .open = snd_trident_foldback_open, .close = snd_trident_foldback_close, .ioctl = snd_trident_ioctl, @@ -2138,7 +2138,7 @@ static struct snd_pcm_ops snd_trident_nx_foldback_ops = { .page = snd_pcm_sgbuf_ops_page, }; -static struct snd_pcm_ops snd_trident_spdif_ops = { +static const struct snd_pcm_ops snd_trident_spdif_ops = { .open = snd_trident_spdif_open, .close = snd_trident_spdif_close, .ioctl = snd_trident_ioctl, @@ -2149,7 +2149,7 @@ static struct snd_pcm_ops snd_trident_spdif_ops = { .pointer = snd_trident_spdif_pointer, }; -static struct snd_pcm_ops snd_trident_spdif_7018_ops = { +static const struct snd_pcm_ops snd_trident_spdif_7018_ops = { .open = snd_trident_spdif_open, .close = snd_trident_spdif_close, .ioctl = snd_trident_ioctl, diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 3dd038b..38a17b4 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1366,7 +1366,7 @@ static int snd_via8233_playback_close(struct snd_pcm_substream *substream) /* via686 playback callbacks */ -static struct snd_pcm_ops snd_via686_playback_ops = { +static const struct snd_pcm_ops snd_via686_playback_ops = { .open = snd_via686_playback_open, .close = snd_via82xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -1379,7 +1379,7 @@ static struct snd_pcm_ops snd_via686_playback_ops = { }; /* via686 capture callbacks */ -static struct snd_pcm_ops snd_via686_capture_ops = { +static const struct snd_pcm_ops snd_via686_capture_ops = { .open = snd_via82xx_capture_open, .close = snd_via82xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -1392,7 +1392,7 @@ static struct snd_pcm_ops snd_via686_capture_ops = { }; /* via823x DSX playback callbacks */ -static struct snd_pcm_ops snd_via8233_playback_ops = { +static const struct snd_pcm_ops snd_via8233_playback_ops = { .open = snd_via8233_playback_open, .close = snd_via8233_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1405,7 +1405,7 @@ static struct snd_pcm_ops snd_via8233_playback_ops = { }; /* via823x multi-channel playback callbacks */ -static struct snd_pcm_ops snd_via8233_multi_ops = { +static const struct snd_pcm_ops snd_via8233_multi_ops = { .open = snd_via8233_multi_open, .close = snd_via82xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -1418,7 +1418,7 @@ static struct snd_pcm_ops snd_via8233_multi_ops = { }; /* via823x capture callbacks */ -static struct snd_pcm_ops snd_via8233_capture_ops = { +static const struct snd_pcm_ops snd_via8233_capture_ops = { .open = snd_via82xx_capture_open, .close = snd_via82xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 99b9137..2f6d40f 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -804,7 +804,7 @@ static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream) /* via686 playback callbacks */ -static struct snd_pcm_ops snd_via686_playback_ops = { +static const struct snd_pcm_ops snd_via686_playback_ops = { .open = snd_via82xx_playback_open, .close = snd_via82xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -817,7 +817,7 @@ static struct snd_pcm_ops snd_via686_playback_ops = { }; /* via686 capture callbacks */ -static struct snd_pcm_ops snd_via686_capture_ops = { +static const struct snd_pcm_ops snd_via686_capture_ops = { .open = snd_via82xx_capture_open, .close = snd_via82xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 4c26076..ffee284 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -1123,7 +1123,7 @@ static int snd_ymfpci_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_ymfpci_playback_ops = { +static const struct snd_pcm_ops snd_ymfpci_playback_ops = { .open = snd_ymfpci_playback_open, .close = snd_ymfpci_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1134,7 +1134,7 @@ static struct snd_pcm_ops snd_ymfpci_playback_ops = { .pointer = snd_ymfpci_playback_pointer, }; -static struct snd_pcm_ops snd_ymfpci_capture_rec_ops = { +static const struct snd_pcm_ops snd_ymfpci_capture_rec_ops = { .open = snd_ymfpci_capture_rec_open, .close = snd_ymfpci_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1169,7 +1169,7 @@ int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device) snd_pcm_std_chmaps, 2, 0, NULL); } -static struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = { +static const struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = { .open = snd_ymfpci_capture_ac97_open, .close = snd_ymfpci_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1203,7 +1203,7 @@ int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device) return 0; } -static struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = { +static const struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = { .open = snd_ymfpci_playback_spdif_open, .close = snd_ymfpci_playback_spdif_close, .ioctl = snd_pcm_lib_ioctl, @@ -1236,7 +1236,7 @@ int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device) return 0; } -static struct snd_pcm_ops snd_ymfpci_playback_4ch_ops = { +static const struct snd_pcm_ops snd_ymfpci_playback_4ch_ops = { .open = snd_ymfpci_playback_4ch_open, .close = snd_ymfpci_playback_4ch_close, .ioctl = snd_pcm_lib_ioctl, -- cgit v0.10.2 From 5116ffc32d889d229843cb1d12060491b01eae21 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 2 Sep 2016 00:13:11 +0200 Subject: ALSA: firewire: constify snd_pcm_ops structures Check for snd_pcm_ops structures that are only stored in the ops field of a snd_soc_platform_driver structure or passed as the third argument to snd_pcm_set_ops. The corresponding field or parameter is declared const, so snd_pcm_ops structures that have this property can be declared as const also. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @r disable optional_qualifier@ identifier i; position p; @@ static struct snd_pcm_ops i@p = { ... }; @ok1@ identifier r.i; struct snd_soc_platform_driver e; position p; @@ e.ops = &i@p; @ok2@ identifier r.i; expression e1, e2; position p; @@ snd_pcm_set_ops(e1, e2, &i@p) @bad@ position p != {r.p,ok1.p,ok2.p}; identifier r.i; struct snd_pcm_ops e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct snd_pcm_ops i = { ... }; // Signed-off-by: Julia Lawall Reviewed-by: Takashi Sakamoto Acked-by: Clemens Ladisch Signed-off-by: Takashi Iwai diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index 4aa0249..6074fe1 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -302,7 +302,7 @@ static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream) int snd_dice_create_pcm(struct snd_dice *dice) { - static struct snd_pcm_ops capture_ops = { + static const struct snd_pcm_ops capture_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -314,7 +314,7 @@ int snd_dice_create_pcm(struct snd_dice *dice) .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; - static struct snd_pcm_ops playback_ops = { + static const struct snd_pcm_ops playback_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c index cac28f7..613f058 100644 --- a/sound/firewire/digi00x/digi00x-pcm.c +++ b/sound/firewire/digi00x/digi00x-pcm.c @@ -329,7 +329,7 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) return amdtp_stream_pcm_pointer(&dg00x->rx_stream); } -static struct snd_pcm_ops pcm_capture_ops = { +static const struct snd_pcm_ops pcm_capture_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -341,7 +341,7 @@ static struct snd_pcm_ops pcm_capture_ops = { .page = snd_pcm_lib_get_vmalloc_page, }; -static struct snd_pcm_ops pcm_playback_ops = { +static const struct snd_pcm_ops pcm_playback_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index 8d23341..f3530f8 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c @@ -388,7 +388,7 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstm) int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) { - static struct snd_pcm_ops capture_ops = { + static const struct snd_pcm_ops capture_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -400,7 +400,7 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; - static struct snd_pcm_ops playback_ops = { + static const struct snd_pcm_ops playback_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index 380d3db..79db1b6 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c @@ -268,7 +268,7 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) return amdtp_stream_pcm_pointer(&tscm->rx_stream); } -static struct snd_pcm_ops pcm_capture_ops = { +static const struct snd_pcm_ops pcm_capture_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -280,7 +280,7 @@ static struct snd_pcm_ops pcm_capture_ops = { .page = snd_pcm_lib_get_vmalloc_page, }; -static struct snd_pcm_ops pcm_playback_ops = { +static const struct snd_pcm_ops pcm_playback_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, -- cgit v0.10.2 From d602efcaf5672e4c59450fb9bf2568271fa0266f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 2 Sep 2016 00:13:12 +0200 Subject: ALSA: ad1889: constify snd_pcm_ops structures Check for snd_pcm_ops structures that are only stored in the ops field of a snd_soc_platform_driver structure or passed as the third argument to snd_pcm_set_ops. The corresponding field or parameter is declared const, so snd_pcm_ops structures that have this property can be declared as const also. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @r disable optional_qualifier@ identifier i; position p; @@ static struct snd_pcm_ops i@p = { ... }; @ok1@ identifier r.i; struct snd_soc_platform_driver e; position p; @@ e.ops = &i@p; @ok2@ identifier r.i; expression e1, e2; position p; @@ snd_pcm_set_ops(e1, e2, &i@p) @bad@ position p != {r.p,ok1.p,ok2.p}; identifier r.i; struct snd_pcm_ops e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct snd_pcm_ops i = { ... }; // Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 1fc6d8b..8c36990 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -571,7 +571,7 @@ snd_ad1889_capture_pointer(struct snd_pcm_substream *ss) return bytes_to_frames(ss->runtime, ptr); } -static struct snd_pcm_ops snd_ad1889_playback_ops = { +static const struct snd_pcm_ops snd_ad1889_playback_ops = { .open = snd_ad1889_playback_open, .close = snd_ad1889_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -582,7 +582,7 @@ static struct snd_pcm_ops snd_ad1889_playback_ops = { .pointer = snd_ad1889_playback_pointer, }; -static struct snd_pcm_ops snd_ad1889_capture_ops = { +static const struct snd_pcm_ops snd_ad1889_capture_ops = { .open = snd_ad1889_capture_open, .close = snd_ad1889_capture_close, .ioctl = snd_pcm_lib_ioctl, -- cgit v0.10.2 From bc9a910b15d0cc6f2f540fc0446381d47f215fc7 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 2 Sep 2016 00:13:13 +0200 Subject: ALSA: oxygen: constify snd_pcm_ops structures Check for snd_pcm_ops structures that are only stored in the ops field of a snd_soc_platform_driver structure or passed as the third argument to snd_pcm_set_ops. The corresponding field or parameter is declared const, so snd_pcm_ops structures that have this property can be declared as const also. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @r disable optional_qualifier@ identifier i; position p; @@ static struct snd_pcm_ops i@p = { ... }; @ok1@ identifier r.i; struct snd_soc_platform_driver e; position p; @@ e.ops = &i@p; @ok2@ identifier r.i; expression e1, e2; position p; @@ snd_pcm_set_ops(e1, e2, &i@p) @bad@ position p != {r.p,ok1.p,ok2.p}; identifier r.i; struct snd_pcm_ops e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct snd_pcm_ops i = { ... }; // Signed-off-by: Julia Lawall Acked-by: Clemens Ladisch Signed-off-by: Takashi Iwai diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index aa2ebd1..042a243 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c @@ -631,7 +631,7 @@ static snd_pcm_uframes_t oxygen_pointer(struct snd_pcm_substream *substream) return bytes_to_frames(runtime, curr_addr - (u32)runtime->dma_addr); } -static struct snd_pcm_ops oxygen_rec_a_ops = { +static const struct snd_pcm_ops oxygen_rec_a_ops = { .open = oxygen_rec_a_open, .close = oxygen_close, .ioctl = snd_pcm_lib_ioctl, @@ -642,7 +642,7 @@ static struct snd_pcm_ops oxygen_rec_a_ops = { .pointer = oxygen_pointer, }; -static struct snd_pcm_ops oxygen_rec_b_ops = { +static const struct snd_pcm_ops oxygen_rec_b_ops = { .open = oxygen_rec_b_open, .close = oxygen_close, .ioctl = snd_pcm_lib_ioctl, @@ -653,7 +653,7 @@ static struct snd_pcm_ops oxygen_rec_b_ops = { .pointer = oxygen_pointer, }; -static struct snd_pcm_ops oxygen_rec_c_ops = { +static const struct snd_pcm_ops oxygen_rec_c_ops = { .open = oxygen_rec_c_open, .close = oxygen_close, .ioctl = snd_pcm_lib_ioctl, @@ -664,7 +664,7 @@ static struct snd_pcm_ops oxygen_rec_c_ops = { .pointer = oxygen_pointer, }; -static struct snd_pcm_ops oxygen_spdif_ops = { +static const struct snd_pcm_ops oxygen_spdif_ops = { .open = oxygen_spdif_open, .close = oxygen_close, .ioctl = snd_pcm_lib_ioctl, @@ -675,7 +675,7 @@ static struct snd_pcm_ops oxygen_spdif_ops = { .pointer = oxygen_pointer, }; -static struct snd_pcm_ops oxygen_multich_ops = { +static const struct snd_pcm_ops oxygen_multich_ops = { .open = oxygen_multich_open, .close = oxygen_close, .ioctl = snd_pcm_lib_ioctl, @@ -686,7 +686,7 @@ static struct snd_pcm_ops oxygen_multich_ops = { .pointer = oxygen_pointer, }; -static struct snd_pcm_ops oxygen_ac97_ops = { +static const struct snd_pcm_ops oxygen_ac97_ops = { .open = oxygen_ac97_open, .close = oxygen_close, .ioctl = snd_pcm_lib_ioctl, -- cgit v0.10.2 From 8c91d7d09e3cd52d5d409ba05e8eb9be0f6a2349 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 2 Sep 2016 00:13:14 +0200 Subject: ALSA: bt87x: constify snd_pcm_ops structures Check for snd_pcm_ops structures that are only stored in the ops field of a snd_soc_platform_driver structure or passed as the third argument to snd_pcm_set_ops. The corresponding field or parameter is declared const, so snd_pcm_ops structures that have this property can be declared as const also. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @r disable optional_qualifier@ identifier i; position p; @@ static struct snd_pcm_ops i@p = { ... }; @ok1@ identifier r.i; struct snd_soc_platform_driver e; position p; @@ e.ops = &i@p; @ok2@ identifier r.i; expression e1, e2; position p; @@ snd_pcm_set_ops(e1, e2, &i@p) @bad@ position p != {r.p,ok1.p,ok2.p}; identifier r.i; struct snd_pcm_ops e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct snd_pcm_ops i = { ... }; // Signed-off-by: Julia Lawall Acked-by: Clemens Ladisch Signed-off-by: Takashi Iwai diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 5925b71..f2c0709 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -550,7 +550,7 @@ static snd_pcm_uframes_t snd_bt87x_pointer(struct snd_pcm_substream *substream) return (snd_pcm_uframes_t)bytes_to_frames(runtime, chip->current_line * chip->line_bytes); } -static struct snd_pcm_ops snd_bt87x_pcm_ops = { +static const struct snd_pcm_ops snd_bt87x_pcm_ops = { .open = snd_bt87x_pcm_open, .close = snd_bt87x_close, .ioctl = snd_pcm_lib_ioctl, -- cgit v0.10.2 From 3bcc8656722c84f10355054ed287c15c47e30a74 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 2 Sep 2016 15:07:23 +0100 Subject: ASoC: fsl_esai: fix spelling mistake "Transmition" -> "Transmission" Trivial fix to spelling mistakes in dev_dbg messages Signed-off-by: Colin Ian King Acked-by: Nicolin Chen Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 26a90e1..e927955 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -77,19 +77,19 @@ static irqreturn_t esai_isr(int irq, void *devid) regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr); if (esr & ESAI_ESR_TINIT_MASK) - dev_dbg(&pdev->dev, "isr: Transmition Initialized\n"); + dev_dbg(&pdev->dev, "isr: Transmission Initialized\n"); if (esr & ESAI_ESR_RFF_MASK) dev_warn(&pdev->dev, "isr: Receiving overrun\n"); if (esr & ESAI_ESR_TFE_MASK) - dev_warn(&pdev->dev, "isr: Transmition underrun\n"); + dev_warn(&pdev->dev, "isr: Transmission underrun\n"); if (esr & ESAI_ESR_TLS_MASK) dev_dbg(&pdev->dev, "isr: Just transmitted the last slot\n"); if (esr & ESAI_ESR_TDE_MASK) - dev_dbg(&pdev->dev, "isr: Transmition data exception\n"); + dev_dbg(&pdev->dev, "isr: Transmission data exception\n"); if (esr & ESAI_ESR_TED_MASK) dev_dbg(&pdev->dev, "isr: Transmitting even slots\n"); -- cgit v0.10.2 From c3d7abca999ebf09139f59eeab2f294e76017631 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 2 Sep 2016 16:25:07 +0100 Subject: ASoC: ux500: fix spelling mistake "Unsopported" -> "Unsupported" Trivial fix to spelling mistakes in dev_err messages Signed-off-by: Colin Ian King Signed-off-by: Mark Brown diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 6d5698b..b343efd 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -187,7 +187,7 @@ static int setup_clocking(struct snd_soc_dai *dai, default: dev_err(dai->dev, - "%s: Error: Unsopported inversion (fmt = 0x%x)!\n", + "%s: Error: Unsupported inversion (fmt = 0x%x)!\n", __func__, fmt); return -EINVAL; @@ -218,7 +218,7 @@ static int setup_clocking(struct snd_soc_dai *dai, break; default: - dev_err(dai->dev, "%s: Error: Unsopported master (fmt = 0x%x)!\n", + dev_err(dai->dev, "%s: Error: Unsupported master (fmt = 0x%x)!\n", __func__, fmt); return -EINVAL; @@ -374,7 +374,7 @@ static int setup_msp_config(struct snd_pcm_substream *substream, break; default: - dev_err(dai->dev, "%s: Error: Unsopported format (%d)!\n", + dev_err(dai->dev, "%s: Error: Unsupported format (%d)!\n", __func__, fmt); return -EINVAL; } -- cgit v0.10.2 From 0fd67cee29cef1942865bd4375b8a7e5d98343ad Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 2 Sep 2016 09:45:25 +0100 Subject: ASoC: Intel: sst: fix to spelling mistake: "susupend" -> "suspend" trivial fix to spelling mistake in dev_err message and replace "cant" with "can't" Signed-off-by: Colin Ian King Signed-off-by: Mark Brown diff --git a/sound/soc/intel/atom/sst/sst.c b/sound/soc/intel/atom/sst/sst.c index 498b5f7..9b6e273 100644 --- a/sound/soc/intel/atom/sst/sst.c +++ b/sound/soc/intel/atom/sst/sst.c @@ -442,7 +442,7 @@ static int intel_sst_suspend(struct device *dev) struct stream_info *stream = &ctx->streams[i]; if (stream->status == STREAM_RUNNING) { - dev_err(dev, "stream %d is running, cant susupend, abort\n", i); + dev_err(dev, "stream %d is running, can't suspend, abort\n", i); return -EBUSY; } } -- cgit v0.10.2 From e87d9ae8886783f3a5a8dd6863e8261783214e3b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 2 Sep 2016 16:52:43 +0100 Subject: ASoC: arizona: Correct handling of FLL theta in synchroniser mode Theta/lambda is used to give the fractional portion of the FLL frequency multiplication. When the synchroniser is active the reference path lambda value is hard coded in the hardware to 65536. This patch corrects the handling of theta such that it is scaled to match this denominator, when the synchroniser is active. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index ccb3ca2..ded235f 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1920,8 +1920,8 @@ static struct { struct arizona_fll_cfg { int n; - int theta; - int lambda; + unsigned int theta; + unsigned int lambda; int refdiv; int outdiv; int fratio; @@ -2233,6 +2233,10 @@ static int arizona_enable_fll(struct arizona_fll *fll) fll->ref_src != fll->sync_src) { arizona_calc_fll(fll, &cfg, fll->ref_freq, false); + /* Ref path hardcodes lambda to 65536 when sync is on */ + if (fll->sync_src >= 0 && cfg.lambda) + cfg.theta = (cfg.theta * (1 << 16)) / cfg.lambda; + arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src, false); if (fll->sync_src >= 0) { -- cgit v0.10.2 From 94ae3ce189c75e7d74753b0e1d3e855786514f03 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Sat, 3 Sep 2016 11:23:26 -0500 Subject: ASoC: Intel: Atom: fix IOSF_MBI dependency fix issue reported by 0-Day with randconfig The commit a68bc0d43e1b ("ASoC: Intel: Atom: auto-detection of Baytrail-CR") added a dependency on IOSF_MBI. The code used the IS_ENABLED macro to check for this dependency but this is not enough in case the SST driver is built-in. This could be fixed with IS_REACHABLE but Baytrail-CR would not be detected depending on combinations of options Add dependency in Kconfig to solve this for good Reported-by: 0 day tester Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index a20c3df..fc6e780 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -25,6 +25,7 @@ config SND_SST_IPC_ACPI tristate select SND_SST_IPC select SND_SOC_INTEL_SST + select IOSF_MBI config SND_SOC_INTEL_SST tristate -- cgit v0.10.2 From f3f6c61452e28ffdf93b101555546af8ef63def5 Mon Sep 17 00:00:00 2001 From: Jeeja KP Date: Fri, 2 Sep 2016 21:49:44 +0530 Subject: ALSA: pcm: Fix avail to return error if stream is suspended When the stream is in suspended state some applications wait on "Stream Pipe Error" in response to snd_pcm_avail call to resume the stream. In the current implementation snd_pcm_avail() returns zero when the stream is in suspended state. This causes application to enter in infinite loop for frames to be available. "Stream pipe Error" code is getting returned for read/write call when the stream is in suspended state. Similarly update snd_pcm_avail to return -ESTRPIPE. Signed-off-by: Jeeja KP Signed-off-by: Takashi Iwai diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c61fd50..9d33c1e 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2637,9 +2637,11 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream) break; /* Fall through */ case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_SUSPENDED: err = 0; break; + case SNDRV_PCM_STATE_SUSPENDED: + err = -ESTRPIPE; + break; case SNDRV_PCM_STATE_XRUN: err = -EPIPE; break; -- cgit v0.10.2 From 1190300d03516d00f68abcb01bfab00835bc0ac5 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 6 Sep 2016 10:57:42 +0100 Subject: ASoC: qcom: apq8016-sbc: add board specific dapm mic widgets This patch adds support to board specific dapm mic widgets so that these can be used to specify proper connections of various micbias supported by the board and SOC. Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 1289543..5c3ccf3 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -147,6 +147,15 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) return data; } +static const struct snd_soc_dapm_widget apq8016_sbc_dapm_widgets[] = { + + SND_SOC_DAPM_MIC("Handset Mic", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Secondary Mic", NULL), + SND_SOC_DAPM_MIC("Digital Mic1", NULL), + SND_SOC_DAPM_MIC("Digital Mic2", NULL), +}; + static int apq8016_sbc_platform_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -159,6 +168,8 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev) return -ENOMEM; card->dev = dev; + card->dapm_widgets = apq8016_sbc_dapm_widgets; + card->num_dapm_widgets = ARRAY_SIZE(apq8016_sbc_dapm_widgets); data = apq8016_sbc_parse_of(card); if (IS_ERR(data)) { dev_err(&pdev->dev, "Error resolving dai links: %ld\n", -- cgit v0.10.2 From 05f9033f74798aa27569ad7866b952ff51f83c26 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 6 Sep 2016 10:57:43 +0100 Subject: ASoC: qcom: apq8016-sbc: add support to routing via DT This patch adds support to allow audio routing via Device Tree. This is mostly used to specify MICBIAS and other power supplies relation. Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt index 4812936..d9d8635 100644 --- a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt +++ b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt @@ -16,6 +16,24 @@ Required properties: * "spkr-iomux" - qcom,model : Name of the sound card. +- qcom,audio-routing : A list of the connections between audio components. + Each entry is a pair of strings, the first being the + connection's sink, the second being the connection's + source. Valid names could be power supplies, MicBias + of msm8x16_wcd codec and the jacks on the board: + + Power supplies: + * MIC BIAS External1 + * MIC BIAS External2 + * MIC BIAS Internal1 + * MIC BIAS Internal2 + + Board connectors: + * Headset Mic + * Secondary Mic", + * DMIC + * Ext Spk + Dai-link subnode properties and subnodes: Required dai-link subnodes: @@ -37,6 +55,18 @@ sound: sound { reg-names = "mic-iomux", "spkr-iomux"; qcom,model = "DB410c"; + qcom,audio-routing = + "MIC BIAS External1", "Handset Mic", + "MIC BIAS Internal2", "Headset Mic", + "MIC BIAS External1", "Secondary Mic", + "AMIC1", "MIC BIAS External1", + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS External1", + "DMIC1", "MIC BIAS Internal1", + "MIC BIAS Internal1", "Digital Mic1", + "DMIC2", "MIC BIAS Internal1", + "MIC BIAS Internal1", "Digital Mic2"; + /* I2S - Internal codec */ internal-dai-link@0 { cpu { /* PRIMARY */ diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 5c3ccf3..07f91e9 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -85,6 +85,15 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) return ERR_PTR(ret); } + /* DAPM routes */ + if (of_property_read_bool(node, "qcom,audio-routing")) { + ret = snd_soc_of_parse_audio_routing(card, + "qcom,audio-routing"); + if (ret) + return ERR_PTR(ret); + } + + /* Populate links */ num_links = of_get_child_count(node); -- cgit v0.10.2 From 44cc4a017e2df87f25765ac270f3f64efc6b06ef Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 6 Sep 2016 20:41:19 +0900 Subject: ALSA: squash lines for simple wrapper functions Remove unneeded variables and assignments. Signed-off-by: Masahiro Yamada Signed-off-by: Takashi Iwai diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index edc8681..a0c4a5d 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -1169,12 +1169,7 @@ static struct soundbus_driver aoa_soundbus_driver = { static int __init aoa_fabric_layout_init(void) { - int err; - - err = soundbus_register_driver(&aoa_soundbus_driver); - if (err) - return err; - return 0; + return soundbus_register_driver(&aoa_soundbus_driver); } static void __exit aoa_fabric_layout_exit(void) diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c index 510e56c..f9b5764 100644 --- a/sound/pci/asihpi/hpifunc.c +++ b/sound/pci/asihpi/hpifunc.c @@ -2323,11 +2323,8 @@ u16 hpi_sample_clock_get_source_index(u32 h_control, u16 *pw_source_index) u16 hpi_sample_clock_query_local_rate(const u32 h_clock, const u32 index, u32 *prate) { - u16 err; - err = hpi_control_query(h_clock, HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, - index, 0, prate); - - return err; + return hpi_control_query(h_clock, HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, + index, 0, prate); } u16 hpi_sample_clock_set_local_rate(u32 h_control, u32 sample_rate) diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c index 419306e..520e19b 100644 --- a/sound/pci/ctxfi/ctvmem.c +++ b/sound/pci/ctxfi/ctvmem.c @@ -166,11 +166,7 @@ static void ct_vm_unmap(struct ct_vm *vm, struct ct_vm_block *block) static dma_addr_t ct_get_ptp_phys(struct ct_vm *vm, int index) { - dma_addr_t addr; - - addr = (index >= CT_PTP_NUM) ? ~0UL : vm->ptp[index].addr; - - return addr; + return (index >= CT_PTP_NUM) ? ~0UL : vm->ptp[index].addr; } int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci) diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index fd9ab44..c11f1a2 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -300,37 +300,29 @@ static int snd_p16v_pcm_open_capture(struct snd_pcm_substream *substream) static int snd_p16v_pcm_hw_params_playback(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - int result; - result = snd_pcm_lib_malloc_pages(substream, + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - return result; } /* hw_params callback */ static int snd_p16v_pcm_hw_params_capture(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - int result; - result = snd_pcm_lib_malloc_pages(substream, + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - return result; } /* hw_free callback */ static int snd_p16v_pcm_hw_free_playback(struct snd_pcm_substream *substream) { - int result; - result = snd_pcm_lib_free_pages(substream); - return result; + return snd_pcm_lib_free_pages(substream); } /* hw_free callback */ static int snd_p16v_pcm_hw_free_capture(struct snd_pcm_substream *substream) { - int result; - result = snd_pcm_lib_free_pages(substream); - return result; + return snd_pcm_lib_free_pages(substream); } diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index cd68114..e5c52ed 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -620,9 +620,7 @@ static const unsigned int stdclock_rate_list[16] = { static unsigned int stdclock_get_rate(struct snd_ice1712 *ice) { - unsigned int rate; - rate = stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15]; - return rate; + return stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15]; } static void stdclock_set_rate(struct snd_ice1712 *ice, unsigned int rate) diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 3682425..b84d7d3 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -564,9 +564,7 @@ static int snd_ps3_pcm_hw_params(struct snd_pcm_substream *substream, static int snd_ps3_pcm_hw_free(struct snd_pcm_substream *substream) { - int ret; - ret = snd_pcm_lib_free_pages(substream); - return ret; + return snd_pcm_lib_free_pages(substream); }; static int snd_ps3_delay_to_bytes(struct snd_pcm_substream *substream, diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c index 5bbaa66..c8455b4 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-ipc.c +++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.c @@ -184,15 +184,9 @@ struct sst_byt { static inline u64 sst_byt_header(int msg_id, int data, bool large, int str_id) { - u64 header; - - header = IPC_HEADER_MSG_ID(msg_id) | - IPC_HEADER_STR_ID(str_id) | - IPC_HEADER_LARGE(large) | - IPC_HEADER_DATA(data) | - SST_BYT_IPCX_BUSY; - - return header; + return IPC_HEADER_MSG_ID(msg_id) | IPC_HEADER_STR_ID(str_id) | + IPC_HEADER_LARGE(large) | IPC_HEADER_DATA(data) | + SST_BYT_IPCX_BUSY; } static inline u16 sst_byt_header_msg_id(u64 header) -- cgit v0.10.2 From 09da111aef57c022ac28bb8974f41c1729102d11 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Sep 2016 12:15:02 +0200 Subject: ALSA: hda - Skip Realtek SKU check for Lenovo machines Realtek codec driver expects an implicit rule where either the codec SSID or the pincfg NID 0x1d contains the some information encoded in some bits. One of the expected information is there is the availability of PC beep, and the driver doesn't build up the PC beep control if this is *supposed* to be disabled there. Meanwhile, Lenovo doesn't seem to follow this requirement (yes it's non-standard after all), and the BIOS sets just the normal SSID and the pincfg values. This resulted in the lack of PC beep on a few machines, purely with a lucky or unlucky number. It didn't bother most people, but some people still demand the PC beep, as found in bug reports. This patch just adds the fixup chain to Lenovo machines to skip the SKU checks. Then the beep control will show up in the mixer, and user can still decide to enable / disable it via the standard mixer interface. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=156311 Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 574b1b4..4be2c77 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5263,6 +5263,8 @@ static const struct hda_fixup alc269_fixups[] = { [ALC269_FIXUP_THINKPAD_ACPI] = { .type = HDA_FIXUP_FUNC, .v.func = hda_fixup_thinkpad_acpi, + .chained = true, + .chain_id = ALC269_FIXUP_SKU_IGNORE, }, [ALC269_FIXUP_DMIC_THINKPAD_ACPI] = { .type = HDA_FIXUP_FUNC, -- cgit v0.10.2 From 3f640970a41429f0a076c01270bbd014c9eae61c Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Sun, 11 Sep 2016 11:26:16 +0800 Subject: ALSA: hda - Fix headset mic detection problem for several Dell laptops One of the laptops has the codec ALC256 on it, applying the ALC255_FIXUP_DELL1_MIC_NO_PRESENCE can fix the problem, the rest of laptops have the codec ALC295 on them, they are similar to machines with ALC225, applying the ALC269_FIXUP_DELL1_MIC_NO_PRESENCE can fix the problem. Cc: Signed-off-by: Hui Wang Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 575cefd..32cbcf8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5806,6 +5806,13 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {0x14, 0x90170110}, \ {0x15, 0x0221401f} +#define ALC295_STANDARD_PINS \ + {0x12, 0xb7a60130}, \ + {0x14, 0x90170110}, \ + {0x17, 0x21014020}, \ + {0x18, 0x21a19030}, \ + {0x21, 0x04211020} + #define ALC298_STANDARD_PINS \ {0x12, 0x90a60130}, \ {0x21, 0x03211020} @@ -5911,6 +5918,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x14, 0x90170120}, {0x21, 0x02211030}), SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + {0x12, 0xb7a60130}, + {0x14, 0x90170110}, + {0x21, 0x02211020}), + SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, ALC256_STANDARD_PINS), SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4, {0x12, 0x90a60130}, @@ -6021,6 +6032,8 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, {0x13, 0x90a60140}), + SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC295_STANDARD_PINS), SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, ALC298_STANDARD_PINS, {0x17, 0x90170110}), -- cgit v0.10.2 From 071f1344f47946dfcb511bf0fbc998dd9a83be29 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 11 Sep 2016 15:05:43 +0200 Subject: ALSA: pci: constify local structures For structure types defined in the same file or local header files, find top-level static structure declarations that have the following properties: 1. Never reassigned. 2. Address never taken 3. Not passed to a top-level macro call 4. No pointer or array-typed field passed to a function or stored in a variable. Declare structures having all of these properties as const. Done using Coccinelle. Based on a suggestion by Joe Perches . Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 977a598..908658a 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -1623,7 +1623,7 @@ static int atc_resume(struct ct_atc *atc) } #endif -static struct ct_atc atc_preset = { +static const struct ct_atc atc_preset = { .map_audio_buffer = ct_map_audio_buffer, .unmap_audio_buffer = ct_unmap_audio_buffer, .pcm_playback_prepare = atc_pcm_playback_prepare, diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 9ceb2bc..ad06866 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -4018,7 +4018,7 @@ static int ca0132_build_controls(struct hda_codec *codec) /* * PCM */ -static struct hda_pcm_stream ca0132_pcm_analog_playback = { +static const struct hda_pcm_stream ca0132_pcm_analog_playback = { .substreams = 1, .channels_min = 2, .channels_max = 6, @@ -4029,7 +4029,7 @@ static struct hda_pcm_stream ca0132_pcm_analog_playback = { }, }; -static struct hda_pcm_stream ca0132_pcm_analog_capture = { +static const struct hda_pcm_stream ca0132_pcm_analog_capture = { .substreams = 1, .channels_min = 2, .channels_max = 2, @@ -4040,7 +4040,7 @@ static struct hda_pcm_stream ca0132_pcm_analog_capture = { }, }; -static struct hda_pcm_stream ca0132_pcm_digital_playback = { +static const struct hda_pcm_stream ca0132_pcm_digital_playback = { .substreams = 1, .channels_min = 2, .channels_max = 2, @@ -4052,7 +4052,7 @@ static struct hda_pcm_stream ca0132_pcm_digital_playback = { }, }; -static struct hda_pcm_stream ca0132_pcm_digital_capture = { +static const struct hda_pcm_stream ca0132_pcm_digital_capture = { .substreams = 1, .channels_min = 2, .channels_max = 2, @@ -4614,7 +4614,7 @@ static void ca0132_free(struct hda_codec *codec) kfree(codec->spec); } -static struct hda_codec_ops ca0132_patch_ops = { +static const struct hda_codec_ops ca0132_patch_ops = { .build_controls = ca0132_build_controls, .build_pcms = ca0132_build_pcms, .init = ca0132_init, diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index ae41fcb..ada5f01 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -644,7 +644,7 @@ static struct lbuspath lbus_play_paths[] = { .mono = lbus_play_mono3, }, }; -static struct lbuspath lbus_rec_path = { +static const struct lbuspath lbus_rec_path = { .noconv = lbus_rec_noconv1, .stereo = lbus_rec_stereo1, .mono = lbus_rec_mono1, -- cgit v0.10.2 From a1338a7d4cd401bb71f4562d6896aa2b74eeb1fb Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Wed, 7 Sep 2016 11:07:49 +0800 Subject: ASoC: rt5514: make the volume TLV to match the units 0.01dB The volume have a step of 0.375dB, but TLV uses the units 0.01dB. It should be changed to a step of 0.75dB to match the units of TLV. Signed-off-by: Oder Chiou Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index 7162f05..bad41ae 100644 --- a/sound/soc/codecs/rt5514.c +++ b/sound/soc/codecs/rt5514.c @@ -278,7 +278,7 @@ static const DECLARE_TLV_DB_RANGE(bst_tlv, 8, 8, TLV_DB_SCALE_ITEM(1700, 0, 0) ); -static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); +static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); static int rt5514_dsp_voice_wake_up_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -352,10 +352,10 @@ static const struct snd_kcontrol_new rt5514_snd_controls[] = { SOC_DOUBLE_TLV("MIC Boost Volume", RT5514_ANA_CTRL_MICBST, RT5514_SEL_BSTL_SFT, RT5514_SEL_BSTR_SFT, 8, 0, bst_tlv), SOC_DOUBLE_R_TLV("ADC1 Capture Volume", RT5514_DOWNFILTER0_CTRL1, - RT5514_DOWNFILTER0_CTRL2, RT5514_AD_GAIN_SFT, 127, 0, + RT5514_DOWNFILTER0_CTRL2, RT5514_AD_GAIN_SFT, 63, 0, adc_vol_tlv), SOC_DOUBLE_R_TLV("ADC2 Capture Volume", RT5514_DOWNFILTER1_CTRL1, - RT5514_DOWNFILTER1_CTRL2, RT5514_AD_GAIN_SFT, 127, 0, + RT5514_DOWNFILTER1_CTRL2, RT5514_AD_GAIN_SFT, 63, 0, adc_vol_tlv), SOC_SINGLE_EXT("DSP Voice Wake Up", SND_SOC_NOPM, 0, 1, 0, rt5514_dsp_voice_wake_up_get, rt5514_dsp_voice_wake_up_put), diff --git a/sound/soc/codecs/rt5514.h b/sound/soc/codecs/rt5514.h index 68883c6..229de0e 100644 --- a/sound/soc/codecs/rt5514.h +++ b/sound/soc/codecs/rt5514.h @@ -196,8 +196,8 @@ #define RT5514_AD_AD_MIX_BIT 10 #define RT5514_AD_AD_MUTE (0x1 << 7) #define RT5514_AD_AD_MUTE_BIT 7 -#define RT5514_AD_GAIN_MASK (0x7f << 0) -#define RT5514_AD_GAIN_SFT 0 +#define RT5514_AD_GAIN_MASK (0x3f << 1) +#define RT5514_AD_GAIN_SFT 1 /* RT5514_ANA_CTRL_MICBST (0x2220) */ #define RT5514_SEL_BSTL_MASK (0xf << 4) -- cgit v0.10.2 From f0447f6cbb202e1be8244d15aee390a96d65e490 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Wed, 7 Sep 2016 14:27:33 +0800 Subject: ASoC: rockchip: i2s: restore register during runtime_suspend/resume cycle when step into runtime_suspend, i2s pd will be disabled and loss state. so need to restore register when runtime_resume. Signed-off-by: Sugar Zhang Signed-off-by: Mark Brown diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 652e8c5..974915c 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -57,6 +57,7 @@ static int i2s_runtime_suspend(struct device *dev) { struct rk_i2s_dev *i2s = dev_get_drvdata(dev); + regcache_cache_only(i2s->regmap, true); clk_disable_unprepare(i2s->mclk); return 0; @@ -73,7 +74,14 @@ static int i2s_runtime_resume(struct device *dev) return ret; } - return 0; + regcache_cache_only(i2s->regmap, false); + regcache_mark_dirty(i2s->regmap); + + ret = regcache_sync(i2s->regmap); + if (ret) + clk_disable_unprepare(i2s->mclk); + + return ret; } static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai) -- cgit v0.10.2 From 3628c6987fb45d719cd963805bbba9f15017290e Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Wed, 7 Sep 2016 14:30:21 +0800 Subject: ASoC: rockchip: spdif: restore register during runtime_suspend/resume cycle when step into runtime_suspend, spdif pd will be disabled and loss state. so need to restore register when runtime_resume. Signed-off-by: Sugar Zhang Signed-off-by: Mark Brown diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c index 4ca2657..fa8101d 100644 --- a/sound/soc/rockchip/rockchip_spdif.c +++ b/sound/soc/rockchip/rockchip_spdif.c @@ -65,6 +65,7 @@ static int __maybe_unused rk_spdif_runtime_suspend(struct device *dev) { struct rk_spdif_dev *spdif = dev_get_drvdata(dev); + regcache_cache_only(spdif->regmap, true); clk_disable_unprepare(spdif->mclk); clk_disable_unprepare(spdif->hclk); @@ -88,7 +89,16 @@ static int __maybe_unused rk_spdif_runtime_resume(struct device *dev) return ret; } - return 0; + regcache_cache_only(spdif->regmap, false); + regcache_mark_dirty(spdif->regmap); + + ret = regcache_sync(spdif->regmap); + if (ret) { + clk_disable_unprepare(spdif->mclk); + clk_disable_unprepare(spdif->hclk); + } + + return ret; } static int rk_spdif_hw_params(struct snd_pcm_substream *substream, -- cgit v0.10.2 From 115c7254882ceb965deb05510128464fef06fbfb Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 8 Sep 2016 02:35:23 +0200 Subject: ASoC: constify snd_pcm_ops structures Check for snd_pcm_ops structures that are only stored in the ops field of a snd_soc_platform_driver structure or passed as the third argument to snd_pcm_set_ops. The corresponding field or parameter is declared const, so snd_pcm_ops structures that have this property can be declared as const also. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @r disable optional_qualifier@ identifier i; position p; @@ static struct snd_pcm_ops i@p = { ... }; @ok1@ identifier r.i; struct snd_soc_platform_driver e; position p; @@ e.ops = &i@p; @ok2@ identifier r.i; expression e1, e2; position p; @@ snd_pcm_set_ops(e1, e2, &i@p) @bad@ position p != {r.p,ok1.p,ok2.p}; identifier r.i; struct snd_pcm_ops e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct snd_pcm_ops i = { ... }; // Signed-off-by: Julia Lawall Signed-off-by: Mark Brown diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index d1fb035..504c7cd 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -897,7 +897,7 @@ static int acp_dma_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops acp_dma_ops = { +static const struct snd_pcm_ops acp_dma_ops = { .open = acp_dma_open, .close = acp_dma_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/soc/atmel/atmel-pcm-pdc.c b/sound/soc/atmel/atmel-pcm-pdc.c index da861b4..91b7069 100644 --- a/sound/soc/atmel/atmel-pcm-pdc.c +++ b/sound/soc/atmel/atmel-pcm-pdc.c @@ -381,7 +381,7 @@ static int atmel_pcm_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops atmel_pcm_ops = { +static const struct snd_pcm_ops atmel_pcm_ops = { .open = atmel_pcm_open, .close = atmel_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c index 77ff8eb..09103aa 100644 --- a/sound/soc/codecs/rt5514-spi.c +++ b/sound/soc/codecs/rt5514-spi.c @@ -236,7 +236,7 @@ static snd_pcm_uframes_t rt5514_spi_pcm_pointer( return bytes_to_frames(runtime, rt5514_dsp->dma_offset); } -static struct snd_pcm_ops rt5514_spi_pcm_ops = { +static const struct snd_pcm_ops rt5514_spi_pcm_ops = { .open = rt5514_spi_pcm_open, .hw_params = rt5514_spi_hw_params, .hw_free = rt5514_spi_hw_free, diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index ffc000b..dc30d78 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -322,7 +322,7 @@ static snd_pcm_uframes_t fsl_asrc_dma_pcm_pointer(struct snd_pcm_substream *subs return bytes_to_frames(substream->runtime, pair->pos); } -static struct snd_pcm_ops fsl_asrc_dma_pcm_ops = { +static const struct snd_pcm_ops fsl_asrc_dma_pcm_ops = { .ioctl = snd_pcm_lib_ioctl, .hw_params = fsl_asrc_dma_hw_params, .hw_free = fsl_asrc_dma_hw_free, diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 52ed434..25c6d87 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -670,7 +670,7 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer return str_info->buffer_ptr; } -static struct snd_pcm_ops sst_platform_ops = { +static const struct snd_pcm_ops sst_platform_ops = { .open = sst_platform_open, .ioctl = snd_pcm_lib_ioctl, .trigger = sst_platform_pcm_trigger, diff --git a/sound/soc/intel/haswell/sst-haswell-pcm.c b/sound/soc/intel/haswell/sst-haswell-pcm.c index 3154525..9e4094e 100644 --- a/sound/soc/intel/haswell/sst-haswell-pcm.c +++ b/sound/soc/intel/haswell/sst-haswell-pcm.c @@ -871,7 +871,7 @@ out: return ret; } -static struct snd_pcm_ops hsw_pcm_ops = { +static const struct snd_pcm_ops hsw_pcm_ops = { .open = hsw_pcm_open, .close = hsw_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 6e05bf8..7555b12 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1093,7 +1093,7 @@ static int skl_get_time_info(struct snd_pcm_substream *substream, return 0; } -static struct snd_pcm_ops skl_platform_ops = { +static const struct snd_pcm_ops skl_platform_ops = { .open = skl_platform_open, .ioctl = snd_pcm_lib_ioctl, .trigger = skl_platform_pcm_trigger, diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index dbfdfe9..dafd22e 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c @@ -242,7 +242,7 @@ static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream return count; } -static struct snd_pcm_ops kirkwood_dma_ops = { +static const struct snd_pcm_ops kirkwood_dma_ops = { .open = kirkwood_dma_open, .close = kirkwood_dma_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index db000c6..ccc5770 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -372,7 +372,7 @@ static int lpass_platform_pcmops_mmap(struct snd_pcm_substream *substream, runtime->dma_bytes); } -static struct snd_pcm_ops lpass_platform_pcm_ops = { +static const struct snd_pcm_ops lpass_platform_pcm_ops = { .open = lpass_platform_pcmops_open, .ioctl = snd_pcm_lib_ioctl, .hw_params = lpass_platform_pcmops_hw_params, diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 53dd085..393e8f0 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -80,7 +80,7 @@ static int dummy_dma_open(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops dummy_dma_ops = { +static const struct snd_pcm_ops dummy_dma_ops = { .open = dummy_dma_open, .ioctl = snd_pcm_lib_ioctl, }; -- cgit v0.10.2 From 52abe54138d9b14b4a0a17742a53d2411bc5b167 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 11 Sep 2016 14:14:41 +0200 Subject: ASoC: ac97: constify gpio_chip structures These structures are only used to copy into other structures, so declare them as const. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @r disable optional_qualifier@ identifier i; position p; @@ static struct gpio_chip i@p = { ... }; @ok@ identifier r.i; expression e; position p; @@ e = i@p; @bad@ position p != {r.p,ok.p}; identifier r.i; struct gpio_chip e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct gpio_chip i = { ... }; // Signed-off-by: Julia Lawall Signed-off-by: Mark Brown diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index bc4a55b..6c8b0b0 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c @@ -116,7 +116,7 @@ static int snd_soc_ac97_gpio_direction_out(struct gpio_chip *chip, return snd_soc_update_bits(codec, AC97_GPIO_CFG, 1 << offset, 0); } -static struct gpio_chip snd_soc_ac97_gpio_chip = { +static const struct gpio_chip snd_soc_ac97_gpio_chip = { .label = "snd_soc_ac97", .owner = THIS_MODULE, .request = snd_soc_ac97_gpio_request, -- cgit v0.10.2 From c59b24f87b997f6de6e2511b9ef702685042e089 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 11 Sep 2016 14:14:42 +0200 Subject: ASoC: constify gpio_chip structures These structures are only used to copy into other structures, so declare them as const. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @r disable optional_qualifier@ identifier i; position p; @@ static struct gpio_chip i@p = { ... }; @ok@ identifier r.i; expression e; position p; @@ e = i@p; @bad@ position p != {r.p,ok.p}; identifier r.i; struct gpio_chip e; @@ e@i@p @depends on !bad disable optional_qualifier@ identifier r.i; @@ static +const struct gpio_chip i = { ... }; // Signed-off-by: Julia Lawall Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index da9483c..43ec78e 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -4657,7 +4657,7 @@ static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset) return regmap_irq_get_virq(data, irq); } -static struct gpio_chip rt5677_template_chip = { +static const struct gpio_chip rt5677_template_chip = { .label = "rt5677", .owner = THIS_MODULE, .direction_output = rt5677_gpio_direction_out, diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 512a9d2..28ab01b 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2285,7 +2285,7 @@ static int wm5100_gpio_direction_in(struct gpio_chip *chip, unsigned offset) (1 << WM5100_GP1_DIR_SHIFT)); } -static struct gpio_chip wm5100_template_chip = { +static const struct gpio_chip wm5100_template_chip = { .label = "wm5100", .owner = THIS_MODULE, .direction_output = wm5100_gpio_direction_out, diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index a26ca49..db901f0 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1830,7 +1830,7 @@ static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) !!value << WM8903_GP1_LVL_SHIFT); } -static struct gpio_chip wm8903_template_chip = { +static const struct gpio_chip wm8903_template_chip = { .label = "wm8903", .owner = THIS_MODULE, .request = wm8903_gpio_request, diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index f3109da..11df897 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3357,7 +3357,7 @@ static int wm8962_gpio_direction_out(struct gpio_chip *chip, return 0; } -static struct gpio_chip wm8962_template_chip = { +static const struct gpio_chip wm8962_template_chip = { .label = "wm8962", .owner = THIS_MODULE, .request = wm8962_gpio_request, diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index a730442..11c9bf5 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -2184,7 +2184,7 @@ static int wm8996_gpio_direction_in(struct gpio_chip *chip, unsigned offset) (1 << WM8996_GP1_DIR_SHIFT)); } -static struct gpio_chip wm8996_template_chip = { +static const struct gpio_chip wm8996_template_chip = { .label = "wm8996", .owner = THIS_MODULE, .direction_output = wm8996_gpio_direction_out, -- cgit v0.10.2 From 69b05825e1f883d15d3d051d0eab3171e247ecaa Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 13 Sep 2016 19:37:53 +0900 Subject: ALSA: seq: fix to copy from/to user space When checking value of request for copy operation, current implementation compares shifted value to macros, while these macros are already shifted. As a result, it never performs to copy from/to user space. This commit fixes the bug. Fixes: 8ce8eb601c71('ALSA: seq: add an alternative way to handle ioctl requests' Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 811b95b..4c93520 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -2122,7 +2122,7 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd, * within 13 bits. We can safely pick up the size from the command. */ size = _IOC_SIZE(handler->cmd); - if (_IOC_DIR(handler->cmd) & IOC_IN) { + if (handler->cmd & IOC_IN) { if (copy_from_user(&buf, (const void __user *)arg, size)) return -EFAULT; } @@ -2132,7 +2132,7 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd, /* Some commands includes a bug in 'dir' field. */ if (handler->cmd == SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT || handler->cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_POOL || - (_IOC_DIR(handler->cmd) & IOC_OUT)) + (handler->cmd & IOC_OUT)) if (copy_to_user((void __user *)arg, &buf, size)) return -EFAULT; } -- cgit v0.10.2 From 96fc294cf6cb27f01a865959b9637d0aea3b57c2 Mon Sep 17 00:00:00 2001 From: Hsin-Yu Chao Date: Wed, 14 Sep 2016 22:25:40 +0800 Subject: ASoC: da7219: software reset codec at probe Da7219 does not trigger interrupt to report jack status when system boots from warm reset because its power remains on during warm reset. Doing software reset at probe to handle this. Signed-off-by: Hsin-Yu Chao Signed-off-by: Xing Zheng Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 50ea943..30f35e8 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1937,6 +1937,14 @@ static int da7219_i2c_probe(struct i2c_client *i2c, return ret; } + /* Software reset codec. */ + regmap_write_bits(da7219->regmap, DA7219_ACCDET_CONFIG_1, + DA7219_ACCDET_EN_MASK, 0); + regmap_write_bits(da7219->regmap, DA7219_CIF_CTRL, + DA7219_CIF_REG_SOFT_RESET_MASK, 0); + regmap_write_bits(da7219->regmap, DA7219_SYSTEM_ACTIVE, + DA7219_SYSTEM_ACTIVE_MASK, 0); + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da7219, &da7219_dai, 1); if (ret < 0) { -- cgit v0.10.2 From a8961cae29c38e225120c40c3340dbde2f552e60 Mon Sep 17 00:00:00 2001 From: John Hsu Date: Tue, 13 Sep 2016 11:56:03 +0800 Subject: ASoC: nau8825: fix bug in FLL parameter In the FLL parameter calculation, the FVCO should choose the maximum one. The patch is to fix the bug about the wrong FVCO chosen. Signed-off-by: John Hsu Signed-off-by: Mark Brown Cc: stable@vger.kernel.org diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 5c9707a..cc32699 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -1912,7 +1912,7 @@ static int nau8825_calc_fll_param(unsigned int fll_in, unsigned int fs, /* Calculate the FLL 10-bit integer input and the FLL 16-bit fractional * input based on FDCO, FREF and FLL ratio. */ - fvco = div_u64(fvco << 16, fref * fll_param->ratio); + fvco = div_u64(fvco_max << 16, fref * fll_param->ratio); fll_param->fll_int = (fvco >> 16) & 0x3FF; fll_param->fll_frac = fvco & 0xFFFF; return 0; -- cgit v0.10.2 From df7c52168ee15b3951b50078c0c3960598eb0109 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Fri, 9 Sep 2016 10:33:10 +0800 Subject: ASoC: add rt5663 codec driver This is the initial codec driver for both rt5663 rt5668 codec. Signed-off-by: John Lin Signed-off-by: Jack Yu Signed-off-by: Bard Liao Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/rt5663.txt b/Documentation/devicetree/bindings/sound/rt5663.txt new file mode 100644 index 0000000..7d3c974 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rt5663.txt @@ -0,0 +1,30 @@ +RT5663/RT5668 audio CODEC + +This device supports I2C only. + +Required properties: + +- compatible : One of "realtek,rt5663" or "realtek,rt5668". + +- reg : The I2C address of the device. + +- interrupts : The CODEC's interrupt output. + +Optional properties: + +Pins on the device (for linking into audio routes) for RT5663/RT5668: + + * IN1P + * IN1N + * IN2P + * IN2N + * HPOL + * HPOR + +Example: + +codec: rt5663@12 { + compatible = "realtek,rt5663"; + reg = <0x12>; + interrupts = <7 IRQ_TYPE_EDGE_FALLING>; +}; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1cd6ab3..3028606 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -112,6 +112,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_RT5645 if I2C select SND_SOC_RT5651 if I2C select SND_SOC_RT5659 if I2C + select SND_SOC_RT5663 if I2C select SND_SOC_RT5670 if I2C select SND_SOC_RT5677 if I2C && SPI_MASTER select SND_SOC_SGTL5000 if I2C @@ -645,6 +646,7 @@ config SND_SOC_RL6231 default y if SND_SOC_RT5645=y default y if SND_SOC_RT5651=y default y if SND_SOC_RT5659=y + default y if SND_SOC_RT5663=y default y if SND_SOC_RT5670=y default y if SND_SOC_RT5677=y default m if SND_SOC_RT5514=m @@ -653,6 +655,7 @@ config SND_SOC_RL6231 default m if SND_SOC_RT5645=m default m if SND_SOC_RT5651=m default m if SND_SOC_RT5659=m + default m if SND_SOC_RT5663=m default m if SND_SOC_RT5670=m default m if SND_SOC_RT5677=m @@ -665,6 +668,7 @@ config SND_SOC_RL6347A config SND_SOC_RT286 tristate + select SND_SOC_RT5663 depends on I2C config SND_SOC_RT298 @@ -697,6 +701,9 @@ config SND_SOC_RT5651 config SND_SOC_RT5659 tristate +config SND_SOC_RT5663 + tristate + config SND_SOC_RT5670 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 58036af..dca8d9c 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -112,6 +112,7 @@ snd-soc-rt5640-objs := rt5640.o snd-soc-rt5645-objs := rt5645.o snd-soc-rt5651-objs := rt5651.o snd-soc-rt5659-objs := rt5659.o +snd-soc-rt5663-objs := rt5663.o snd-soc-rt5670-objs := rt5670.o snd-soc-rt5677-objs := rt5677.o snd-soc-rt5677-spi-objs := rt5677-spi.o @@ -333,6 +334,7 @@ obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o obj-$(CONFIG_SND_SOC_RT5659) += snd-soc-rt5659.o +obj-$(CONFIG_SND_SOC_RT5663) += snd-soc-rt5663.o obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c new file mode 100644 index 0000000..7963a27 --- /dev/null +++ b/sound/soc/codecs/rt5663.c @@ -0,0 +1,3216 @@ +/* + * rt5663.c -- RT5668/RT5663 ALSA SoC audio codec driver + * + * Copyright 2016 Realtek Semiconductor Corp. + * Author: Jack Yu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rt5663.h" +#include "rl6231.h" + +#define RT5668_DEVICE_ID 0x6451 +#define RT5663_DEVICE_ID 0x6406 + +enum { + CODEC_TYPE_RT5668, + CODEC_TYPE_RT5663, +}; + +struct rt5663_priv { + struct snd_soc_codec *codec; + struct regmap *regmap; + struct delayed_work jack_detect_work; + struct snd_soc_jack *hs_jack; + struct timer_list btn_check_timer; + + int codec_type; + int sysclk; + int sysclk_src; + int lrck; + + int pll_src; + int pll_in; + int pll_out; + + int jack_type; +}; + +static const struct reg_default rt5668_reg[] = { + { 0x0000, 0x0000 }, + { 0x0001, 0xc8c8 }, + { 0x0002, 0x8080 }, + { 0x0003, 0x8000 }, + { 0x0004, 0xc80a }, + { 0x0005, 0x0000 }, + { 0x0006, 0x0000 }, + { 0x0007, 0x0000 }, + { 0x000a, 0x0000 }, + { 0x000b, 0x0000 }, + { 0x000c, 0x0000 }, + { 0x000d, 0x0000 }, + { 0x000f, 0x0808 }, + { 0x0010, 0x4000 }, + { 0x0011, 0x0000 }, + { 0x0012, 0x1404 }, + { 0x0013, 0x1000 }, + { 0x0014, 0xa00a }, + { 0x0015, 0x0404 }, + { 0x0016, 0x0404 }, + { 0x0017, 0x0011 }, + { 0x0018, 0xafaf }, + { 0x0019, 0xafaf }, + { 0x001a, 0xafaf }, + { 0x001b, 0x0011 }, + { 0x001c, 0x2f2f }, + { 0x001d, 0x2f2f }, + { 0x001e, 0x2f2f }, + { 0x001f, 0x0000 }, + { 0x0020, 0x0000 }, + { 0x0021, 0x0000 }, + { 0x0022, 0x5757 }, + { 0x0023, 0x0039 }, + { 0x0024, 0x000b }, + { 0x0026, 0xc0c0 }, + { 0x0027, 0xc0c0 }, + { 0x0028, 0xc0c0 }, + { 0x0029, 0x8080 }, + { 0x002a, 0xaaaa }, + { 0x002b, 0xaaaa }, + { 0x002c, 0xaba8 }, + { 0x002d, 0x0000 }, + { 0x002e, 0x0000 }, + { 0x002f, 0x0000 }, + { 0x0030, 0x0000 }, + { 0x0031, 0x5000 }, + { 0x0032, 0x0000 }, + { 0x0033, 0x0000 }, + { 0x0034, 0x0000 }, + { 0x0035, 0x0000 }, + { 0x003a, 0x0000 }, + { 0x003b, 0x0000 }, + { 0x003c, 0x00ff }, + { 0x003d, 0x0000 }, + { 0x003e, 0x00ff }, + { 0x003f, 0x0000 }, + { 0x0040, 0x0000 }, + { 0x0041, 0x00ff }, + { 0x0042, 0x0000 }, + { 0x0043, 0x00ff }, + { 0x0044, 0x0c0c }, + { 0x0049, 0xc00b }, + { 0x004a, 0x0000 }, + { 0x004b, 0x031f }, + { 0x004d, 0x0000 }, + { 0x004e, 0x001f }, + { 0x004f, 0x0000 }, + { 0x0050, 0x001f }, + { 0x0052, 0xf000 }, + { 0x0061, 0x0000 }, + { 0x0062, 0x0000 }, + { 0x0063, 0x003e }, + { 0x0064, 0x0000 }, + { 0x0065, 0x0000 }, + { 0x0066, 0x003f }, + { 0x0067, 0x0000 }, + { 0x006b, 0x0000 }, + { 0x006d, 0xff00 }, + { 0x006e, 0x2808 }, + { 0x006f, 0x000a }, + { 0x0070, 0x8000 }, + { 0x0071, 0x8000 }, + { 0x0072, 0x8000 }, + { 0x0073, 0x7000 }, + { 0x0074, 0x7770 }, + { 0x0075, 0x0002 }, + { 0x0076, 0x0001 }, + { 0x0078, 0x00f0 }, + { 0x0079, 0x0000 }, + { 0x007a, 0x0000 }, + { 0x007b, 0x0000 }, + { 0x007c, 0x0000 }, + { 0x007d, 0x0123 }, + { 0x007e, 0x4500 }, + { 0x007f, 0x8003 }, + { 0x0080, 0x0000 }, + { 0x0081, 0x0000 }, + { 0x0082, 0x0000 }, + { 0x0083, 0x0000 }, + { 0x0084, 0x0000 }, + { 0x0085, 0x0000 }, + { 0x0086, 0x0008 }, + { 0x0087, 0x0000 }, + { 0x0088, 0x0000 }, + { 0x0089, 0x0000 }, + { 0x008a, 0x0000 }, + { 0x008b, 0x0000 }, + { 0x008c, 0x0003 }, + { 0x008e, 0x0060 }, + { 0x008f, 0x1000 }, + { 0x0091, 0x0c26 }, + { 0x0092, 0x0073 }, + { 0x0093, 0x0000 }, + { 0x0094, 0x0080 }, + { 0x0098, 0x0000 }, + { 0x0099, 0x0000 }, + { 0x009a, 0x0007 }, + { 0x009f, 0x0000 }, + { 0x00a0, 0x0000 }, + { 0x00a1, 0x0002 }, + { 0x00a2, 0x0001 }, + { 0x00a3, 0x0002 }, + { 0x00a4, 0x0001 }, + { 0x00ae, 0x2040 }, + { 0x00af, 0x0000 }, + { 0x00b6, 0x0000 }, + { 0x00b7, 0x0000 }, + { 0x00b8, 0x0000 }, + { 0x00b9, 0x0000 }, + { 0x00ba, 0x0002 }, + { 0x00bb, 0x0000 }, + { 0x00be, 0x0000 }, + { 0x00c0, 0x0000 }, + { 0x00c1, 0x0aaa }, + { 0x00c2, 0xaa80 }, + { 0x00c3, 0x0003 }, + { 0x00c4, 0x0000 }, + { 0x00d0, 0x0000 }, + { 0x00d1, 0x2244 }, + { 0x00d2, 0x0000 }, + { 0x00d3, 0x3300 }, + { 0x00d4, 0x2200 }, + { 0x00d9, 0x0809 }, + { 0x00da, 0x0000 }, + { 0x00db, 0x0008 }, + { 0x00dc, 0x00c0 }, + { 0x00dd, 0x6724 }, + { 0x00de, 0x3131 }, + { 0x00df, 0x0008 }, + { 0x00e0, 0x4000 }, + { 0x00e1, 0x3131 }, + { 0x00e2, 0x600c }, + { 0x00ea, 0xb320 }, + { 0x00eb, 0x0000 }, + { 0x00ec, 0xb300 }, + { 0x00ed, 0x0000 }, + { 0x00ee, 0xb320 }, + { 0x00ef, 0x0000 }, + { 0x00f0, 0x0201 }, + { 0x00f1, 0x0ddd }, + { 0x00f2, 0x0ddd }, + { 0x00f6, 0x0000 }, + { 0x00f7, 0x0000 }, + { 0x00f8, 0x0000 }, + { 0x00fa, 0x0000 }, + { 0x00fb, 0x0000 }, + { 0x00fc, 0x0000 }, + { 0x00fd, 0x0000 }, + { 0x00fe, 0x10ec }, + { 0x00ff, 0x6451 }, + { 0x0100, 0xaaaa }, + { 0x0101, 0x000a }, + { 0x010a, 0xaaaa }, + { 0x010b, 0xa0a0 }, + { 0x010c, 0xaeae }, + { 0x010d, 0xaaaa }, + { 0x010e, 0xaaaa }, + { 0x010f, 0xaaaa }, + { 0x0110, 0xe002 }, + { 0x0111, 0xa602 }, + { 0x0112, 0xaaaa }, + { 0x0113, 0x2000 }, + { 0x0117, 0x0f00 }, + { 0x0125, 0x0420 }, + { 0x0132, 0x0000 }, + { 0x0133, 0x0000 }, + { 0x0136, 0x5555 }, + { 0x0137, 0x5540 }, + { 0x0138, 0x3700 }, + { 0x0139, 0x79a1 }, + { 0x013a, 0x2020 }, + { 0x013b, 0x2020 }, + { 0x013c, 0x2005 }, + { 0x013f, 0x0000 }, + { 0x0145, 0x0002 }, + { 0x0146, 0x0000 }, + { 0x0147, 0x0000 }, + { 0x0148, 0x0000 }, + { 0x0160, 0x4ec0 }, + { 0x0161, 0x0080 }, + { 0x0162, 0x0200 }, + { 0x0163, 0x0800 }, + { 0x0164, 0x0000 }, + { 0x0165, 0x0000 }, + { 0x0166, 0x0000 }, + { 0x0167, 0x000f }, + { 0x0168, 0x000f }, + { 0x0170, 0x4e80 }, + { 0x0171, 0x0080 }, + { 0x0172, 0x0200 }, + { 0x0173, 0x0800 }, + { 0x0174, 0x00ff }, + { 0x0175, 0x0000 }, + { 0x0190, 0x4131 }, + { 0x0191, 0x4131 }, + { 0x0192, 0x4131 }, + { 0x0193, 0x4131 }, + { 0x0194, 0x0000 }, + { 0x0195, 0x0000 }, + { 0x0196, 0x0000 }, + { 0x0197, 0x0000 }, + { 0x0198, 0x0000 }, + { 0x0199, 0x0000 }, + { 0x01a0, 0x1e64 }, + { 0x01a1, 0x06a3 }, + { 0x01a2, 0x0000 }, + { 0x01a3, 0x0000 }, + { 0x01a4, 0x0000 }, + { 0x01a5, 0x0000 }, + { 0x01a6, 0x0000 }, + { 0x01a7, 0x0000 }, + { 0x01a8, 0x0000 }, + { 0x01a9, 0x0000 }, + { 0x01aa, 0x0000 }, + { 0x01ab, 0x0000 }, + { 0x01b5, 0x0000 }, + { 0x01b6, 0x01c3 }, + { 0x01b7, 0x02a0 }, + { 0x01b8, 0x03e9 }, + { 0x01b9, 0x1389 }, + { 0x01ba, 0xc351 }, + { 0x01bb, 0x0009 }, + { 0x01bc, 0x0018 }, + { 0x01bd, 0x002a }, + { 0x01be, 0x004c }, + { 0x01bf, 0x0097 }, + { 0x01c0, 0x433d }, + { 0x01c1, 0x0000 }, + { 0x01c2, 0x0000 }, + { 0x01c3, 0x0000 }, + { 0x01c4, 0x0000 }, + { 0x01c5, 0x0000 }, + { 0x01c6, 0x0000 }, + { 0x01c7, 0x0000 }, + { 0x01c8, 0x40af }, + { 0x01c9, 0x0702 }, + { 0x01ca, 0x0000 }, + { 0x01cb, 0x0000 }, + { 0x01cc, 0x5757 }, + { 0x01cd, 0x5757 }, + { 0x01ce, 0x5757 }, + { 0x01cf, 0x5757 }, + { 0x01d0, 0x5757 }, + { 0x01d1, 0x5757 }, + { 0x01d2, 0x5757 }, + { 0x01d3, 0x5757 }, + { 0x01d4, 0x5757 }, + { 0x01d5, 0x5757 }, + { 0x01d6, 0x003c }, + { 0x01da, 0x0000 }, + { 0x01db, 0x0000 }, + { 0x01dc, 0x0000 }, + { 0x01de, 0x7c00 }, + { 0x01df, 0x0320 }, + { 0x01e0, 0x06a1 }, + { 0x01e1, 0x0000 }, + { 0x01e2, 0x0000 }, + { 0x01e3, 0x0000 }, + { 0x01e4, 0x0000 }, + { 0x01e5, 0x0000 }, + { 0x01e6, 0x0001 }, + { 0x01e7, 0x0000 }, + { 0x01e8, 0x0000 }, + { 0x01ea, 0x0000 }, + { 0x01eb, 0x0000 }, + { 0x01ec, 0x0000 }, + { 0x01ed, 0x0000 }, + { 0x01ee, 0x0000 }, + { 0x01ef, 0x0000 }, + { 0x01f0, 0x0000 }, + { 0x01f1, 0x0000 }, + { 0x01f2, 0x0000 }, + { 0x01f3, 0x0000 }, + { 0x01f4, 0x0000 }, + { 0x0200, 0x0000 }, + { 0x0201, 0x0000 }, + { 0x0202, 0x0000 }, + { 0x0203, 0x0000 }, + { 0x0204, 0x0000 }, + { 0x0205, 0x0000 }, + { 0x0206, 0x0000 }, + { 0x0207, 0x0000 }, + { 0x0208, 0x0000 }, + { 0x0210, 0x60b1 }, + { 0x0211, 0xa000 }, + { 0x0212, 0x024c }, + { 0x0213, 0xf7ff }, + { 0x0214, 0x024c }, + { 0x0215, 0x0102 }, + { 0x0216, 0x00a3 }, + { 0x0217, 0x0048 }, + { 0x0218, 0x92c0 }, + { 0x0219, 0x0000 }, + { 0x021a, 0x00c8 }, + { 0x021b, 0x0020 }, + { 0x02fa, 0x0000 }, + { 0x02fb, 0x0000 }, + { 0x02fc, 0x0000 }, + { 0x02ff, 0x0110 }, + { 0x0300, 0x001f }, + { 0x0301, 0x032c }, + { 0x0302, 0x5f21 }, + { 0x0303, 0x4000 }, + { 0x0304, 0x4000 }, + { 0x0305, 0x06d5 }, + { 0x0306, 0x8000 }, + { 0x0307, 0x0700 }, + { 0x0310, 0x4560 }, + { 0x0311, 0xa4a8 }, + { 0x0312, 0x7418 }, + { 0x0313, 0x0000 }, + { 0x0314, 0x0006 }, + { 0x0315, 0xffff }, + { 0x0316, 0xc400 }, + { 0x0317, 0x0000 }, + { 0x0330, 0x00a6 }, + { 0x0331, 0x04c3 }, + { 0x0332, 0x27c8 }, + { 0x0333, 0xbf50 }, + { 0x0334, 0x0045 }, + { 0x0335, 0x0007 }, + { 0x0336, 0x7418 }, + { 0x0337, 0x0501 }, + { 0x0338, 0x0000 }, + { 0x0339, 0x0010 }, + { 0x033a, 0x1010 }, + { 0x03c0, 0x7e00 }, + { 0x03c1, 0x8000 }, + { 0x03c2, 0x8000 }, + { 0x03c3, 0x8000 }, + { 0x03c4, 0x8000 }, + { 0x03c5, 0x8000 }, + { 0x03c6, 0x8000 }, + { 0x03c7, 0x8000 }, + { 0x03c8, 0x8000 }, + { 0x03c9, 0x8000 }, + { 0x03ca, 0x8000 }, + { 0x03cb, 0x8000 }, + { 0x03cc, 0x8000 }, + { 0x03d0, 0x0000 }, + { 0x03d1, 0x0000 }, + { 0x03d2, 0x0000 }, + { 0x03d3, 0x0000 }, + { 0x03d4, 0x2000 }, + { 0x03d5, 0x2000 }, + { 0x03d6, 0x0000 }, + { 0x03d7, 0x0000 }, + { 0x03d8, 0x2000 }, + { 0x03d9, 0x2000 }, + { 0x03da, 0x2000 }, + { 0x03db, 0x2000 }, + { 0x03dc, 0x0000 }, + { 0x03dd, 0x0000 }, + { 0x03de, 0x0000 }, + { 0x03df, 0x2000 }, + { 0x03e0, 0x0000 }, + { 0x03e1, 0x0000 }, + { 0x03e2, 0x0000 }, + { 0x03e3, 0x0000 }, + { 0x03e4, 0x0000 }, + { 0x03e5, 0x0000 }, + { 0x03e6, 0x0000 }, + { 0x03e7, 0x0000 }, + { 0x03e8, 0x0000 }, + { 0x03e9, 0x0000 }, + { 0x03ea, 0x0000 }, + { 0x03eb, 0x0000 }, + { 0x03ec, 0x0000 }, + { 0x03ed, 0x0000 }, + { 0x03ee, 0x0000 }, + { 0x03ef, 0x0000 }, + { 0x03f0, 0x0800 }, + { 0x03f1, 0x0800 }, + { 0x03f2, 0x0800 }, + { 0x03f3, 0x0800 }, + { 0x03fe, 0x0000 }, + { 0x03ff, 0x0000 }, + { 0x07f0, 0x0000 }, + { 0x07fa, 0x0000 }, +}; + +static const struct reg_default rt5663_reg[] = { + { 0x0000, 0x0000 }, + { 0x0002, 0x0008 }, + { 0x0005, 0x1000 }, + { 0x0006, 0x1000 }, + { 0x000a, 0x0000 }, + { 0x0010, 0x000f }, + { 0x0015, 0x42c1 }, + { 0x0016, 0x0000 }, + { 0x0018, 0x000b }, + { 0x0019, 0xafaf }, + { 0x001c, 0x2f2f }, + { 0x001f, 0x0000 }, + { 0x0022, 0x5757 }, + { 0x0023, 0x0039 }, + { 0x0026, 0xc0c0 }, + { 0x0029, 0x8080 }, + { 0x002a, 0xa0a0 }, + { 0x002c, 0x000c }, + { 0x002d, 0x0000 }, + { 0x0040, 0x0808 }, + { 0x0061, 0x0000 }, + { 0x0062, 0x0000 }, + { 0x0063, 0x003e }, + { 0x0064, 0x0000 }, + { 0x0065, 0x0000 }, + { 0x0066, 0x0000 }, + { 0x006b, 0x0000 }, + { 0x006e, 0x0000 }, + { 0x006f, 0x0000 }, + { 0x0070, 0x8020 }, + { 0x0073, 0x1000 }, + { 0x0074, 0xe400 }, + { 0x0075, 0x0002 }, + { 0x0076, 0x0001 }, + { 0x0077, 0x00f0 }, + { 0x0078, 0x0000 }, + { 0x0079, 0x0000 }, + { 0x007a, 0x0123 }, + { 0x007b, 0x8003 }, + { 0x0080, 0x0000 }, + { 0x0081, 0x0000 }, + { 0x0082, 0x0000 }, + { 0x0083, 0x0000 }, + { 0x0084, 0x0000 }, + { 0x0086, 0x0008 }, + { 0x0087, 0x0000 }, + { 0x008a, 0x0000 }, + { 0x008b, 0x0000 }, + { 0x008c, 0x0003 }, + { 0x008e, 0x0004 }, + { 0x008f, 0x1000 }, + { 0x0090, 0x0646 }, + { 0x0091, 0x0e3e }, + { 0x0092, 0x1071 }, + { 0x0093, 0x0000 }, + { 0x0094, 0x0080 }, + { 0x0097, 0x0000 }, + { 0x0098, 0x0000 }, + { 0x009a, 0x0000 }, + { 0x009f, 0x0000 }, + { 0x00ae, 0x2000 }, + { 0x00af, 0x0000 }, + { 0x00b6, 0x0000 }, + { 0x00b7, 0x0000 }, + { 0x00b8, 0x0000 }, + { 0x00ba, 0x0000 }, + { 0x00bb, 0x0000 }, + { 0x00be, 0x0000 }, + { 0x00bf, 0x0000 }, + { 0x00c0, 0x0000 }, + { 0x00c1, 0x0000 }, + { 0x00c5, 0x0000 }, + { 0x00cb, 0xa02f }, + { 0x00cc, 0x0000 }, + { 0x00cd, 0x0e02 }, + { 0x00d9, 0x08f9 }, + { 0x00db, 0x0008 }, + { 0x00dc, 0x00c0 }, + { 0x00dd, 0x6724 }, + { 0x00de, 0x3131 }, + { 0x00df, 0x0008 }, + { 0x00e0, 0x4000 }, + { 0x00e1, 0x3131 }, + { 0x00e2, 0x0043 }, + { 0x00e4, 0x400b }, + { 0x00e5, 0x8031 }, + { 0x00e6, 0x3080 }, + { 0x00e7, 0x4100 }, + { 0x00e8, 0x1400 }, + { 0x00e9, 0xe00a }, + { 0x00ea, 0x0404 }, + { 0x00eb, 0x0404 }, + { 0x00ec, 0xb320 }, + { 0x00ed, 0x0000 }, + { 0x00f4, 0x0000 }, + { 0x00f6, 0x0000 }, + { 0x00f8, 0x0000 }, + { 0x00fa, 0x8000 }, + { 0x00fd, 0x0001 }, + { 0x00fe, 0x10ec }, + { 0x00ff, 0x6406 }, + { 0x0100, 0xa0a0 }, + { 0x0108, 0x4444 }, + { 0x0109, 0x4444 }, + { 0x010a, 0xaaaa }, + { 0x010b, 0x00a0 }, + { 0x010c, 0x8aaa }, + { 0x010d, 0xaaaa }, + { 0x010e, 0x2aaa }, + { 0x010f, 0x002a }, + { 0x0110, 0xa0a4 }, + { 0x0111, 0x4602 }, + { 0x0112, 0x0101 }, + { 0x0113, 0x2000 }, + { 0x0114, 0x0000 }, + { 0x0116, 0x0000 }, + { 0x0117, 0x0f00 }, + { 0x0118, 0x0006 }, + { 0x0125, 0x2224 }, + { 0x0126, 0x5550 }, + { 0x0127, 0x0400 }, + { 0x0128, 0x7711 }, + { 0x0132, 0x0004 }, + { 0x0137, 0x5441 }, + { 0x0139, 0x79a1 }, + { 0x013a, 0x30c0 }, + { 0x013b, 0x2000 }, + { 0x013c, 0x2005 }, + { 0x013d, 0x30c0 }, + { 0x013e, 0x0000 }, + { 0x0140, 0x3700 }, + { 0x0141, 0x1f00 }, + { 0x0144, 0x0000 }, + { 0x0145, 0x0002 }, + { 0x0146, 0x0000 }, + { 0x0160, 0x0e80 }, + { 0x0161, 0x0020 }, + { 0x0162, 0x0080 }, + { 0x0163, 0x0800 }, + { 0x0164, 0x0000 }, + { 0x0165, 0x0000 }, + { 0x0166, 0x0000 }, + { 0x0167, 0x1417 }, + { 0x0168, 0x0017 }, + { 0x0169, 0x0017 }, + { 0x0180, 0x2000 }, + { 0x0181, 0x0000 }, + { 0x0182, 0x0000 }, + { 0x0183, 0x2000 }, + { 0x0184, 0x0000 }, + { 0x0185, 0x0000 }, + { 0x01b0, 0x4b30 }, + { 0x01b1, 0x0000 }, + { 0x01b2, 0xd870 }, + { 0x01b3, 0x0000 }, + { 0x01b4, 0x0030 }, + { 0x01b5, 0x5757 }, + { 0x01b6, 0x5757 }, + { 0x01b7, 0x5757 }, + { 0x01b8, 0x5757 }, + { 0x01c0, 0x433d }, + { 0x01c1, 0x0540 }, + { 0x01c2, 0x0000 }, + { 0x01c3, 0x0000 }, + { 0x01c4, 0x0000 }, + { 0x01c5, 0x0009 }, + { 0x01c6, 0x0018 }, + { 0x01c7, 0x002a }, + { 0x01c8, 0x004c }, + { 0x01c9, 0x0097 }, + { 0x01ca, 0x01c3 }, + { 0x01cb, 0x03e9 }, + { 0x01cc, 0x1389 }, + { 0x01cd, 0xc351 }, + { 0x01ce, 0x0000 }, + { 0x01cf, 0x0000 }, + { 0x01d0, 0x0000 }, + { 0x01d1, 0x0000 }, + { 0x01d2, 0x0000 }, + { 0x01d3, 0x003c }, + { 0x01d4, 0x5757 }, + { 0x01d5, 0x5757 }, + { 0x01d6, 0x5757 }, + { 0x01d7, 0x5757 }, + { 0x01d8, 0x5757 }, + { 0x01d9, 0x5757 }, + { 0x01da, 0x0000 }, + { 0x01db, 0x0000 }, + { 0x01dd, 0x0009 }, + { 0x01de, 0x7f00 }, + { 0x01df, 0x00c8 }, + { 0x01e0, 0x0691 }, + { 0x01e1, 0x0000 }, + { 0x01e2, 0x0000 }, + { 0x01e3, 0x0000 }, + { 0x01e4, 0x0000 }, + { 0x01e5, 0x0040 }, + { 0x01e6, 0x0000 }, + { 0x01e7, 0x0000 }, + { 0x01e8, 0x0000 }, + { 0x01ea, 0x0000 }, + { 0x01eb, 0x0000 }, + { 0x01ec, 0x0000 }, + { 0x01ed, 0x0000 }, + { 0x01ee, 0x0000 }, + { 0x01ef, 0x0000 }, + { 0x01f0, 0x0000 }, + { 0x01f1, 0x0000 }, + { 0x01f2, 0x0000 }, + { 0x0200, 0x0000 }, + { 0x0201, 0x2244 }, + { 0x0202, 0xaaaa }, + { 0x0250, 0x8010 }, + { 0x0251, 0x0000 }, + { 0x0252, 0x028a }, + { 0x02fa, 0x0000 }, + { 0x02fb, 0x0000 }, + { 0x02fc, 0x0000 }, + { 0x0300, 0x0000 }, + { 0x03d0, 0x0000 }, + { 0x03d1, 0x0000 }, + { 0x03d2, 0x0000 }, + { 0x03d3, 0x0000 }, + { 0x03d4, 0x2000 }, + { 0x03d5, 0x2000 }, + { 0x03d6, 0x0000 }, + { 0x03d7, 0x0000 }, + { 0x03d8, 0x2000 }, + { 0x03d9, 0x2000 }, + { 0x03da, 0x2000 }, + { 0x03db, 0x2000 }, + { 0x03dc, 0x0000 }, + { 0x03dd, 0x0000 }, + { 0x03de, 0x0000 }, + { 0x03df, 0x2000 }, + { 0x03e0, 0x0000 }, + { 0x03e1, 0x0000 }, + { 0x03e2, 0x0000 }, + { 0x03e3, 0x0000 }, + { 0x03e4, 0x0000 }, + { 0x03e5, 0x0000 }, + { 0x03e6, 0x0000 }, + { 0x03e7, 0x0000 }, + { 0x03e8, 0x0000 }, + { 0x03e9, 0x0000 }, + { 0x03ea, 0x0000 }, + { 0x03eb, 0x0000 }, + { 0x03ec, 0x0000 }, + { 0x03ed, 0x0000 }, + { 0x03ee, 0x0000 }, + { 0x03ef, 0x0000 }, + { 0x03f0, 0x0800 }, + { 0x03f1, 0x0800 }, + { 0x03f2, 0x0800 }, + { 0x03f3, 0x0800 }, +}; + +static bool rt5663_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT5663_RESET: + case RT5663_SIL_DET_CTL: + case RT5663_HP_IMP_GAIN_2: + case RT5663_AD_DA_MIXER: + case RT5663_FRAC_DIV_2: + case RT5663_MICBIAS_1: + case RT5663_ASRC_11_2: + case RT5663_ADC_EQ_1: + case RT5663_INT_ST_1: + case RT5663_INT_ST_2: + case RT5663_GPIO_STA: + case RT5663_SIN_GEN_1: + case RT5663_IL_CMD_1: + case RT5663_IL_CMD_5: + case RT5663_IL_CMD_PWRSAV1: + case RT5663_EM_JACK_TYPE_1: + case RT5663_EM_JACK_TYPE_2: + case RT5663_EM_JACK_TYPE_3: + case RT5663_JD_CTRL2: + case RT5663_VENDOR_ID: + case RT5663_VENDOR_ID_1: + case RT5663_VENDOR_ID_2: + case RT5663_PLL_INT_REG: + case RT5663_SOFT_RAMP: + case RT5663_STO_DRE_1: + case RT5663_STO_DRE_5: + case RT5663_STO_DRE_6: + case RT5663_STO_DRE_7: + case RT5663_MIC_DECRO_1: + case RT5663_MIC_DECRO_4: + case RT5663_HP_IMP_SEN_1: + case RT5663_HP_IMP_SEN_3: + case RT5663_HP_IMP_SEN_4: + case RT5663_HP_IMP_SEN_5: + case RT5663_HP_CALIB_1_1: + case RT5663_HP_CALIB_9: + case RT5663_HP_CALIB_ST1: + case RT5663_HP_CALIB_ST2: + case RT5663_HP_CALIB_ST3: + case RT5663_HP_CALIB_ST4: + case RT5663_HP_CALIB_ST5: + case RT5663_HP_CALIB_ST6: + case RT5663_HP_CALIB_ST7: + case RT5663_HP_CALIB_ST8: + case RT5663_HP_CALIB_ST9: + case RT5663_ANA_JD: + return true; + default: + return false; + } +} + +static bool rt5663_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT5663_RESET: + case RT5663_HP_OUT_EN: + case RT5663_HP_LCH_DRE: + case RT5663_HP_RCH_DRE: + case RT5663_CALIB_BST: + case RT5663_RECMIX: + case RT5663_SIL_DET_CTL: + case RT5663_PWR_SAV_SILDET: + case RT5663_SIDETONE_CTL: + case RT5663_STO1_DAC_DIG_VOL: + case RT5663_STO1_ADC_DIG_VOL: + case RT5663_STO1_BOOST: + case RT5663_HP_IMP_GAIN_1: + case RT5663_HP_IMP_GAIN_2: + case RT5663_STO1_ADC_MIXER: + case RT5663_AD_DA_MIXER: + case RT5663_STO_DAC_MIXER: + case RT5663_DIG_SIDE_MIXER: + case RT5663_BYPASS_STO_DAC: + case RT5663_CALIB_REC_MIX: + case RT5663_PWR_DIG_1: + case RT5663_PWR_DIG_2: + case RT5663_PWR_ANLG_1: + case RT5663_PWR_ANLG_2: + case RT5663_PWR_ANLG_3: + case RT5663_PWR_MIXER: + case RT5663_SIG_CLK_DET: + case RT5663_PRE_DIV_GATING_1: + case RT5663_PRE_DIV_GATING_2: + case RT5663_I2S1_SDP: + case RT5663_ADDA_CLK_1: + case RT5663_ADDA_RST: + case RT5663_FRAC_DIV_1: + case RT5663_FRAC_DIV_2: + case RT5663_TDM_1: + case RT5663_TDM_2: + case RT5663_TDM_3: + case RT5663_TDM_4: + case RT5663_TDM_5: + case RT5663_GLB_CLK: + case RT5663_PLL_1: + case RT5663_PLL_2: + case RT5663_ASRC_1: + case RT5663_ASRC_2: + case RT5663_ASRC_4: + case RT5663_DUMMY_REG: + case RT5663_ASRC_8: + case RT5663_ASRC_9: + case RT5663_ASRC_11: + case RT5663_DEPOP_1: + case RT5663_DEPOP_2: + case RT5663_DEPOP_3: + case RT5663_HP_CHARGE_PUMP_1: + case RT5663_HP_CHARGE_PUMP_2: + case RT5663_MICBIAS_1: + case RT5663_RC_CLK: + case RT5663_ASRC_11_2: + case RT5663_DUMMY_REG_2: + case RT5663_REC_PATH_GAIN: + case RT5663_AUTO_1MRC_CLK: + case RT5663_ADC_EQ_1: + case RT5663_ADC_EQ_2: + case RT5663_IRQ_1: + case RT5663_IRQ_2: + case RT5663_IRQ_3: + case RT5663_IRQ_4: + case RT5663_IRQ_5: + case RT5663_INT_ST_1: + case RT5663_INT_ST_2: + case RT5663_GPIO_1: + case RT5663_GPIO_2: + case RT5663_GPIO_STA: + case RT5663_SIN_GEN_1: + case RT5663_SIN_GEN_2: + case RT5663_SIN_GEN_3: + case RT5663_SOF_VOL_ZC1: + case RT5663_IL_CMD_1: + case RT5663_IL_CMD_2: + case RT5663_IL_CMD_3: + case RT5663_IL_CMD_4: + case RT5663_IL_CMD_5: + case RT5663_IL_CMD_6: + case RT5663_IL_CMD_7: + case RT5663_IL_CMD_8: + case RT5663_IL_CMD_PWRSAV1: + case RT5663_IL_CMD_PWRSAV2: + case RT5663_EM_JACK_TYPE_1: + case RT5663_EM_JACK_TYPE_2: + case RT5663_EM_JACK_TYPE_3: + case RT5663_EM_JACK_TYPE_4: + case RT5663_EM_JACK_TYPE_5: + case RT5663_EM_JACK_TYPE_6: + case RT5663_STO1_HPF_ADJ1: + case RT5663_STO1_HPF_ADJ2: + case RT5663_FAST_OFF_MICBIAS: + case RT5663_JD_CTRL1: + case RT5663_JD_CTRL2: + case RT5663_DIG_MISC: + case RT5663_VENDOR_ID: + case RT5663_VENDOR_ID_1: + case RT5663_VENDOR_ID_2: + case RT5663_DIG_VOL_ZCD: + case RT5663_ANA_BIAS_CUR_1: + case RT5663_ANA_BIAS_CUR_2: + case RT5663_ANA_BIAS_CUR_3: + case RT5663_ANA_BIAS_CUR_4: + case RT5663_ANA_BIAS_CUR_5: + case RT5663_ANA_BIAS_CUR_6: + case RT5663_BIAS_CUR_5: + case RT5663_BIAS_CUR_6: + case RT5663_BIAS_CUR_7: + case RT5663_BIAS_CUR_8: + case RT5663_DACREF_LDO: + case RT5663_DUMMY_REG_3: + case RT5663_BIAS_CUR_9: + case RT5663_DUMMY_REG_4: + case RT5663_VREFADJ_OP: + case RT5663_VREF_RECMIX: + case RT5663_CHARGE_PUMP_1: + case RT5663_CHARGE_PUMP_1_2: + case RT5663_CHARGE_PUMP_1_3: + case RT5663_CHARGE_PUMP_2: + case RT5663_DIG_IN_PIN1: + case RT5663_PAD_DRV_CTL: + case RT5663_PLL_INT_REG: + case RT5663_CHOP_DAC_L: + case RT5663_CHOP_ADC: + case RT5663_CALIB_ADC: + case RT5663_CHOP_DAC_R: + case RT5663_DUMMY_CTL_DACLR: + case RT5663_DUMMY_REG_5: + case RT5663_SOFT_RAMP: + case RT5663_TEST_MODE_1: + case RT5663_TEST_MODE_2: + case RT5663_TEST_MODE_3: + case RT5663_STO_DRE_1: + case RT5663_STO_DRE_2: + case RT5663_STO_DRE_3: + case RT5663_STO_DRE_4: + case RT5663_STO_DRE_5: + case RT5663_STO_DRE_6: + case RT5663_STO_DRE_7: + case RT5663_STO_DRE_8: + case RT5663_STO_DRE_9: + case RT5663_STO_DRE_10: + case RT5663_MIC_DECRO_1: + case RT5663_MIC_DECRO_2: + case RT5663_MIC_DECRO_3: + case RT5663_MIC_DECRO_4: + case RT5663_MIC_DECRO_5: + case RT5663_MIC_DECRO_6: + case RT5663_HP_DECRO_1: + case RT5663_HP_DECRO_2: + case RT5663_HP_DECRO_3: + case RT5663_HP_DECRO_4: + case RT5663_HP_DECOUP: + case RT5663_HP_IMP_SEN_MAP8: + case RT5663_HP_IMP_SEN_MAP9: + case RT5663_HP_IMP_SEN_MAP10: + case RT5663_HP_IMP_SEN_MAP11: + case RT5663_HP_IMP_SEN_1: + case RT5663_HP_IMP_SEN_2: + case RT5663_HP_IMP_SEN_3: + case RT5663_HP_IMP_SEN_4: + case RT5663_HP_IMP_SEN_5: + case RT5663_HP_IMP_SEN_6: + case RT5663_HP_IMP_SEN_7: + case RT5663_HP_IMP_SEN_8: + case RT5663_HP_IMP_SEN_9: + case RT5663_HP_IMP_SEN_10: + case RT5663_HP_IMP_SEN_11: + case RT5663_HP_IMP_SEN_12: + case RT5663_HP_IMP_SEN_13: + case RT5663_HP_IMP_SEN_14: + case RT5663_HP_IMP_SEN_15: + case RT5663_HP_IMP_SEN_16: + case RT5663_HP_IMP_SEN_17: + case RT5663_HP_IMP_SEN_18: + case RT5663_HP_IMP_SEN_19: + case RT5663_HP_IMPSEN_DIG5: + case RT5663_HP_IMPSEN_MAP1: + case RT5663_HP_IMPSEN_MAP2: + case RT5663_HP_IMPSEN_MAP3: + case RT5663_HP_IMPSEN_MAP4: + case RT5663_HP_IMPSEN_MAP5: + case RT5663_HP_IMPSEN_MAP7: + case RT5663_HP_LOGIC_1: + case RT5663_HP_LOGIC_2: + case RT5663_HP_CALIB_1: + case RT5663_HP_CALIB_1_1: + case RT5663_HP_CALIB_2: + case RT5663_HP_CALIB_3: + case RT5663_HP_CALIB_4: + case RT5663_HP_CALIB_5: + case RT5663_HP_CALIB_5_1: + case RT5663_HP_CALIB_6: + case RT5663_HP_CALIB_7: + case RT5663_HP_CALIB_9: + case RT5663_HP_CALIB_10: + case RT5663_HP_CALIB_11: + case RT5663_HP_CALIB_ST1: + case RT5663_HP_CALIB_ST2: + case RT5663_HP_CALIB_ST3: + case RT5663_HP_CALIB_ST4: + case RT5663_HP_CALIB_ST5: + case RT5663_HP_CALIB_ST6: + case RT5663_HP_CALIB_ST7: + case RT5663_HP_CALIB_ST8: + case RT5663_HP_CALIB_ST9: + case RT5663_HP_AMP_DET: + case RT5663_DUMMY_REG_6: + case RT5663_HP_BIAS: + case RT5663_CBJ_1: + case RT5663_CBJ_2: + case RT5663_CBJ_3: + case RT5663_DUMMY_1: + case RT5663_DUMMY_2: + case RT5663_DUMMY_3: + case RT5663_ANA_JD: + case RT5663_ADC_LCH_LPF1_A1: + case RT5663_ADC_RCH_LPF1_A1: + case RT5663_ADC_LCH_LPF1_H0: + case RT5663_ADC_RCH_LPF1_H0: + case RT5663_ADC_LCH_BPF1_A1: + case RT5663_ADC_RCH_BPF1_A1: + case RT5663_ADC_LCH_BPF1_A2: + case RT5663_ADC_RCH_BPF1_A2: + case RT5663_ADC_LCH_BPF1_H0: + case RT5663_ADC_RCH_BPF1_H0: + case RT5663_ADC_LCH_BPF2_A1: + case RT5663_ADC_RCH_BPF2_A1: + case RT5663_ADC_LCH_BPF2_A2: + case RT5663_ADC_RCH_BPF2_A2: + case RT5663_ADC_LCH_BPF2_H0: + case RT5663_ADC_RCH_BPF2_H0: + case RT5663_ADC_LCH_BPF3_A1: + case RT5663_ADC_RCH_BPF3_A1: + case RT5663_ADC_LCH_BPF3_A2: + case RT5663_ADC_RCH_BPF3_A2: + case RT5663_ADC_LCH_BPF3_H0: + case RT5663_ADC_RCH_BPF3_H0: + case RT5663_ADC_LCH_BPF4_A1: + case RT5663_ADC_RCH_BPF4_A1: + case RT5663_ADC_LCH_BPF4_A2: + case RT5663_ADC_RCH_BPF4_A2: + case RT5663_ADC_LCH_BPF4_H0: + case RT5663_ADC_RCH_BPF4_H0: + case RT5663_ADC_LCH_HPF1_A1: + case RT5663_ADC_RCH_HPF1_A1: + case RT5663_ADC_LCH_HPF1_H0: + case RT5663_ADC_RCH_HPF1_H0: + case RT5663_ADC_EQ_PRE_VOL_L: + case RT5663_ADC_EQ_PRE_VOL_R: + case RT5663_ADC_EQ_POST_VOL_L: + case RT5663_ADC_EQ_POST_VOL_R: + return true; + default: + return false; + } +} + +static bool rt5668_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT5663_RESET: + case RT5668_CBJ_TYPE_2: + case RT5668_PDM_OUT_CTL: + case RT5668_PDM_I2C_DATA_CTL1: + case RT5668_PDM_I2C_DATA_CTL4: + case RT5668_ALC_BK_GAIN: + case RT5663_PLL_2: + case RT5663_MICBIAS_1: + case RT5663_ADC_EQ_1: + case RT5663_INT_ST_1: + case RT5668_GPIO_STA: + case RT5663_IL_CMD_1: + case RT5663_IL_CMD_5: + case RT5668_A_JD_CTRL: + case RT5663_JD_CTRL2: + case RT5663_VENDOR_ID: + case RT5663_VENDOR_ID_1: + case RT5663_VENDOR_ID_2: + case RT5663_STO_DRE_1: + case RT5663_STO_DRE_5: + case RT5663_STO_DRE_6: + case RT5663_STO_DRE_7: + case RT5668_MONO_DYNA_6: + case RT5668_STO1_SIL_DET: + case RT5668_MONOL_SIL_DET: + case RT5668_MONOR_SIL_DET: + case RT5668_STO2_DAC_SIL: + case RT5668_MONO_AMP_CAL_ST1: + case RT5668_MONO_AMP_CAL_ST2: + case RT5668_MONO_AMP_CAL_ST3: + case RT5668_MONO_AMP_CAL_ST4: + case RT5663_HP_IMP_SEN_2: + case RT5663_HP_IMP_SEN_3: + case RT5663_HP_IMP_SEN_4: + case RT5663_HP_IMP_SEN_10: + case RT5663_HP_CALIB_1: + case RT5663_HP_CALIB_10: + case RT5663_HP_CALIB_ST1: + case RT5663_HP_CALIB_ST4: + case RT5663_HP_CALIB_ST5: + case RT5663_HP_CALIB_ST6: + case RT5663_HP_CALIB_ST7: + case RT5663_HP_CALIB_ST8: + case RT5663_HP_CALIB_ST9: + case RT5668_HP_CALIB_ST10: + case RT5668_HP_CALIB_ST11: + return true; + default: + return false; + } +} + +static bool rt5668_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT5668_LOUT_CTRL: + case RT5668_HP_AMP_2: + case RT5668_MONO_OUT: + case RT5668_MONO_GAIN: + case RT5668_AEC_BST: + case RT5668_IN1_IN2: + case RT5668_IN3_IN4: + case RT5668_INL1_INR1: + case RT5668_CBJ_TYPE_2: + case RT5668_CBJ_TYPE_3: + case RT5668_CBJ_TYPE_4: + case RT5668_CBJ_TYPE_5: + case RT5668_CBJ_TYPE_8: + case RT5668_DAC3_DIG_VOL: + case RT5668_DAC3_CTRL: + case RT5668_MONO_ADC_DIG_VOL: + case RT5668_STO2_ADC_DIG_VOL: + case RT5668_MONO_ADC_BST_GAIN: + case RT5668_STO2_ADC_BST_GAIN: + case RT5668_SIDETONE_CTRL: + case RT5668_MONO1_ADC_MIXER: + case RT5668_STO2_ADC_MIXER: + case RT5668_MONO_DAC_MIXER: + case RT5668_DAC2_SRC_CTRL: + case RT5668_IF_3_4_DATA_CTL: + case RT5668_IF_5_DATA_CTL: + case RT5668_PDM_OUT_CTL: + case RT5668_PDM_I2C_DATA_CTL1: + case RT5668_PDM_I2C_DATA_CTL2: + case RT5668_PDM_I2C_DATA_CTL3: + case RT5668_PDM_I2C_DATA_CTL4: + case RT5668_RECMIX1_NEW: + case RT5668_RECMIX1L_0: + case RT5668_RECMIX1L: + case RT5668_RECMIX1R_0: + case RT5668_RECMIX1R: + case RT5668_RECMIX2_NEW: + case RT5668_RECMIX2_L_2: + case RT5668_RECMIX2_R: + case RT5668_RECMIX2_R_2: + case RT5668_CALIB_REC_LR: + case RT5668_ALC_BK_GAIN: + case RT5668_MONOMIX_GAIN: + case RT5668_MONOMIX_IN_GAIN: + case RT5668_OUT_MIXL_GAIN: + case RT5668_OUT_LMIX_IN_GAIN: + case RT5668_OUT_RMIX_IN_GAIN: + case RT5668_OUT_RMIX_IN_GAIN1: + case RT5668_LOUT_MIXER_CTRL: + case RT5668_PWR_VOL: + case RT5668_ADCDAC_RST: + case RT5668_I2S34_SDP: + case RT5668_I2S5_SDP: + case RT5668_TDM_5: + case RT5668_TDM_6: + case RT5668_TDM_7: + case RT5668_TDM_8: + case RT5668_ASRC_3: + case RT5668_ASRC_6: + case RT5668_ASRC_7: + case RT5668_PLL_TRK_13: + case RT5668_I2S_M_CLK_CTL: + case RT5668_FDIV_I2S34_M_CLK: + case RT5668_FDIV_I2S34_M_CLK2: + case RT5668_FDIV_I2S5_M_CLK: + case RT5668_FDIV_I2S5_M_CLK2: + case RT5668_IRQ_4: + case RT5668_GPIO_3: + case RT5668_GPIO_4: + case RT5668_GPIO_STA: + case RT5668_HP_AMP_DET1: + case RT5668_HP_AMP_DET2: + case RT5668_HP_AMP_DET3: + case RT5668_MID_BD_HP_AMP: + case RT5668_LOW_BD_HP_AMP: + case RT5668_SOF_VOL_ZC2: + case RT5668_ADC_STO2_ADJ1: + case RT5668_ADC_STO2_ADJ2: + case RT5668_A_JD_CTRL: + case RT5668_JD1_TRES_CTRL: + case RT5668_JD2_TRES_CTRL: + case RT5668_JD_CTRL2: + case RT5668_DUM_REG_2: + case RT5668_DUM_REG_3: + case RT5663_VENDOR_ID: + case RT5663_VENDOR_ID_1: + case RT5663_VENDOR_ID_2: + case RT5668_DACADC_DIG_VOL2: + case RT5668_DIG_IN_PIN2: + case RT5668_PAD_DRV_CTL1: + case RT5668_SOF_RAM_DEPOP: + case RT5668_VOL_TEST: + case RT5668_TEST_MODE_3: + case RT5668_TEST_MODE_4: + case RT5663_STO_DRE_9: + case RT5668_MONO_DYNA_1: + case RT5668_MONO_DYNA_2: + case RT5668_MONO_DYNA_3: + case RT5668_MONO_DYNA_4: + case RT5668_MONO_DYNA_5: + case RT5668_MONO_DYNA_6: + case RT5668_STO1_SIL_DET: + case RT5668_MONOL_SIL_DET: + case RT5668_MONOR_SIL_DET: + case RT5668_STO2_DAC_SIL: + case RT5668_PWR_SAV_CTL1: + case RT5668_PWR_SAV_CTL2: + case RT5668_PWR_SAV_CTL3: + case RT5668_PWR_SAV_CTL4: + case RT5668_PWR_SAV_CTL5: + case RT5668_PWR_SAV_CTL6: + case RT5668_MONO_AMP_CAL1: + case RT5668_MONO_AMP_CAL2: + case RT5668_MONO_AMP_CAL3: + case RT5668_MONO_AMP_CAL4: + case RT5668_MONO_AMP_CAL5: + case RT5668_MONO_AMP_CAL6: + case RT5668_MONO_AMP_CAL7: + case RT5668_MONO_AMP_CAL_ST1: + case RT5668_MONO_AMP_CAL_ST2: + case RT5668_MONO_AMP_CAL_ST3: + case RT5668_MONO_AMP_CAL_ST4: + case RT5668_MONO_AMP_CAL_ST5: + case RT5668_HP_IMP_SEN_13: + case RT5668_HP_IMP_SEN_14: + case RT5668_HP_IMP_SEN_6: + case RT5668_HP_IMP_SEN_7: + case RT5668_HP_IMP_SEN_8: + case RT5668_HP_IMP_SEN_9: + case RT5668_HP_IMP_SEN_10: + case RT5668_HP_LOGIC_3: + case RT5668_HP_CALIB_ST10: + case RT5668_HP_CALIB_ST11: + case RT5668_PRO_REG_TBL_4: + case RT5668_PRO_REG_TBL_5: + case RT5668_PRO_REG_TBL_6: + case RT5668_PRO_REG_TBL_7: + case RT5668_PRO_REG_TBL_8: + case RT5668_PRO_REG_TBL_9: + case RT5668_SAR_ADC_INL_1: + case RT5668_SAR_ADC_INL_2: + case RT5668_SAR_ADC_INL_3: + case RT5668_SAR_ADC_INL_4: + case RT5668_SAR_ADC_INL_5: + case RT5668_SAR_ADC_INL_6: + case RT5668_SAR_ADC_INL_7: + case RT5668_SAR_ADC_INL_8: + case RT5668_SAR_ADC_INL_9: + case RT5668_SAR_ADC_INL_10: + case RT5668_SAR_ADC_INL_11: + case RT5668_SAR_ADC_INL_12: + case RT5668_DRC_CTRL_1: + case RT5668_DRC1_CTRL_2: + case RT5668_DRC1_CTRL_3: + case RT5668_DRC1_CTRL_4: + case RT5668_DRC1_CTRL_5: + case RT5668_DRC1_CTRL_6: + case RT5668_DRC1_HD_CTRL_1: + case RT5668_DRC1_HD_CTRL_2: + case RT5668_DRC1_PRI_REG_1: + case RT5668_DRC1_PRI_REG_2: + case RT5668_DRC1_PRI_REG_3: + case RT5668_DRC1_PRI_REG_4: + case RT5668_DRC1_PRI_REG_5: + case RT5668_DRC1_PRI_REG_6: + case RT5668_DRC1_PRI_REG_7: + case RT5668_DRC1_PRI_REG_8: + case RT5668_ALC_PGA_CTL_1: + case RT5668_ALC_PGA_CTL_2: + case RT5668_ALC_PGA_CTL_3: + case RT5668_ALC_PGA_CTL_4: + case RT5668_ALC_PGA_CTL_5: + case RT5668_ALC_PGA_CTL_6: + case RT5668_ALC_PGA_CTL_7: + case RT5668_ALC_PGA_CTL_8: + case RT5668_ALC_PGA_REG_1: + case RT5668_ALC_PGA_REG_2: + case RT5668_ALC_PGA_REG_3: + case RT5668_ADC_EQ_RECOV_1: + case RT5668_ADC_EQ_RECOV_2: + case RT5668_ADC_EQ_RECOV_3: + case RT5668_ADC_EQ_RECOV_4: + case RT5668_ADC_EQ_RECOV_5: + case RT5668_ADC_EQ_RECOV_6: + case RT5668_ADC_EQ_RECOV_7: + case RT5668_ADC_EQ_RECOV_8: + case RT5668_ADC_EQ_RECOV_9: + case RT5668_ADC_EQ_RECOV_10: + case RT5668_ADC_EQ_RECOV_11: + case RT5668_ADC_EQ_RECOV_12: + case RT5668_ADC_EQ_RECOV_13: + case RT5668_VID_HIDDEN: + case RT5668_VID_CUSTOMER: + case RT5668_SCAN_MODE: + case RT5668_I2C_BYPA: + return true; + case RT5663_TDM_1: + case RT5663_DEPOP_3: + case RT5663_ASRC_11_2: + case RT5663_INT_ST_2: + case RT5663_GPIO_STA: + case RT5663_SIN_GEN_1: + case RT5663_SIN_GEN_2: + case RT5663_SIN_GEN_3: + case RT5663_IL_CMD_PWRSAV1: + case RT5663_IL_CMD_PWRSAV2: + case RT5663_EM_JACK_TYPE_1: + case RT5663_EM_JACK_TYPE_2: + case RT5663_EM_JACK_TYPE_3: + case RT5663_EM_JACK_TYPE_4: + case RT5663_FAST_OFF_MICBIAS: + case RT5663_ANA_BIAS_CUR_1: + case RT5663_ANA_BIAS_CUR_2: + case RT5663_BIAS_CUR_9: + case RT5663_DUMMY_REG_4: + case RT5663_VREF_RECMIX: + case RT5663_CHARGE_PUMP_1_2: + case RT5663_CHARGE_PUMP_1_3: + case RT5663_CHARGE_PUMP_2: + case RT5663_CHOP_DAC_R: + case RT5663_DUMMY_CTL_DACLR: + case RT5663_DUMMY_REG_5: + case RT5663_SOFT_RAMP: + case RT5663_TEST_MODE_1: + case RT5663_STO_DRE_10: + case RT5663_MIC_DECRO_1: + case RT5663_MIC_DECRO_2: + case RT5663_MIC_DECRO_3: + case RT5663_MIC_DECRO_4: + case RT5663_MIC_DECRO_5: + case RT5663_MIC_DECRO_6: + case RT5663_HP_DECRO_1: + case RT5663_HP_DECRO_2: + case RT5663_HP_DECRO_3: + case RT5663_HP_DECRO_4: + case RT5663_HP_DECOUP: + case RT5663_HP_IMPSEN_MAP4: + case RT5663_HP_IMPSEN_MAP5: + case RT5663_HP_IMPSEN_MAP7: + case RT5663_HP_CALIB_1: + case RT5663_CBJ_1: + case RT5663_CBJ_2: + case RT5663_CBJ_3: + return false; + default: + return rt5663_readable_register(dev, reg); + } +} + +static const DECLARE_TLV_DB_SCALE(rt5663_hp_vol_tlv, -2400, 150, 0); +static const DECLARE_TLV_DB_SCALE(rt5668_hp_vol_tlv, -2250, 150, 0); +static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0); +static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); + +/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ +static const DECLARE_TLV_DB_RANGE(in_bst_tlv, + 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), + 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), + 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), + 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), + 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), + 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), + 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0) +); + +/* Interface data select */ +static const char * const rt5663_if1_adc_data_select[] = { + "L/R", "R/L", "L/L", "R/R" +}; + +static const SOC_ENUM_SINGLE_DECL(rt5663_if1_adc_enum, RT5663_TDM_2, + RT5663_DATA_SWAP_ADCDAT1_SHIFT, rt5663_if1_adc_data_select); + +static void rt5663_enable_push_button_irq(struct snd_soc_codec *codec, + bool enable) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + if (enable) { + snd_soc_update_bits(codec, RT5663_IL_CMD_6, + RT5668_EN_4BTN_INL_MASK, RT5668_EN_4BTN_INL_EN); + /* reset in-line command */ + snd_soc_update_bits(codec, RT5663_IL_CMD_6, + RT5668_RESET_4BTN_INL_MASK, + RT5668_RESET_4BTN_INL_RESET); + snd_soc_update_bits(codec, RT5663_IL_CMD_6, + RT5668_RESET_4BTN_INL_MASK, + RT5668_RESET_4BTN_INL_NOR); + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + snd_soc_update_bits(codec, RT5663_IRQ_3, + RT5668_EN_IRQ_INLINE_MASK, + RT5668_EN_IRQ_INLINE_NOR); + break; + case CODEC_TYPE_RT5663: + snd_soc_update_bits(codec, RT5663_IRQ_2, + RT5663_EN_IRQ_INLINE_MASK, + RT5663_EN_IRQ_INLINE_NOR); + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + } else { + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + snd_soc_update_bits(codec, RT5663_IRQ_3, + RT5668_EN_IRQ_INLINE_MASK, + RT5668_EN_IRQ_INLINE_BYP); + break; + case CODEC_TYPE_RT5663: + snd_soc_update_bits(codec, RT5663_IRQ_2, + RT5663_EN_IRQ_INLINE_MASK, + RT5663_EN_IRQ_INLINE_BYP); + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + snd_soc_update_bits(codec, RT5663_IL_CMD_6, + RT5668_EN_4BTN_INL_MASK, RT5668_EN_4BTN_INL_DIS); + /* reset in-line command */ + snd_soc_update_bits(codec, RT5663_IL_CMD_6, + RT5668_RESET_4BTN_INL_MASK, + RT5668_RESET_4BTN_INL_RESET); + snd_soc_update_bits(codec, RT5663_IL_CMD_6, + RT5668_RESET_4BTN_INL_MASK, + RT5668_RESET_4BTN_INL_NOR); + } +} + +/** + * rt5668_jack_detect - Detect headset. + * @codec: SoC audio codec device. + * @jack_insert: Jack insert or not. + * + * Detect whether is headset or not when jack inserted. + * + * Returns detect status. + */ + +static int rt5668_jack_detect(struct snd_soc_codec *codec, int jack_insert) +{ + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + struct rt5663_priv *rt5668 = snd_soc_codec_get_drvdata(codec); + int val, i = 0, sleep_time[5] = {300, 150, 100, 50, 30}; + + dev_dbg(codec->dev, "%s jack_insert:%d\n", __func__, jack_insert); + if (jack_insert) { + snd_soc_write(codec, RT5668_CBJ_TYPE_2, 0x8040); + snd_soc_write(codec, RT5668_CBJ_TYPE_3, 0x1484); + + snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); + snd_soc_dapm_force_enable_pin(dapm, "MICBIAS2"); + snd_soc_dapm_force_enable_pin(dapm, "Mic Det Power"); + snd_soc_dapm_force_enable_pin(dapm, "CBJ Power"); + snd_soc_dapm_sync(dapm); + snd_soc_update_bits(codec, RT5663_RC_CLK, + RT5668_DIG_1M_CLK_MASK, RT5668_DIG_1M_CLK_EN); + snd_soc_update_bits(codec, RT5663_RECMIX, 0x8, 0x8); + + while (i < 5) { + msleep(sleep_time[i]); + val = snd_soc_read(codec, RT5668_CBJ_TYPE_2) & 0x0003; + if (val == 0x1 || val == 0x2 || val == 0x3) + break; + dev_dbg(codec->dev, "%s: MX-0011 val=%x sleep %d\n", + __func__, val, sleep_time[i]); + i++; + } + dev_dbg(codec->dev, "%s val = %d\n", __func__, val); + switch (val) { + case 1: + case 2: + rt5668->jack_type = SND_JACK_HEADSET; + rt5663_enable_push_button_irq(codec, true); + break; + default: + snd_soc_dapm_disable_pin(dapm, "MICBIAS1"); + snd_soc_dapm_disable_pin(dapm, "MICBIAS2"); + snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); + snd_soc_dapm_disable_pin(dapm, "CBJ Power"); + snd_soc_dapm_sync(dapm); + rt5668->jack_type = SND_JACK_HEADPHONE; + break; + } + } else { + snd_soc_update_bits(codec, RT5663_RECMIX, 0x8, 0x0); + + if (rt5668->jack_type == SND_JACK_HEADSET) { + rt5663_enable_push_button_irq(codec, false); + snd_soc_dapm_disable_pin(dapm, "MICBIAS1"); + snd_soc_dapm_disable_pin(dapm, "MICBIAS2"); + snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); + snd_soc_dapm_disable_pin(dapm, "CBJ Power"); + snd_soc_dapm_sync(dapm); + } + rt5668->jack_type = 0; + } + + dev_dbg(codec->dev, "jack_type = %d\n", rt5668->jack_type); + return rt5668->jack_type; +} + +/** + * rt5663_jack_detect - Detect headset. + * @codec: SoC audio codec device. + * @jack_insert: Jack insert or not. + * + * Detect whether is headset or not when jack inserted. + * + * Returns detect status. + */ +static int rt5663_jack_detect(struct snd_soc_codec *codec, int jack_insert) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + int val, i = 0, sleep_time[5] = {300, 150, 100, 50, 30}; + + dev_dbg(codec->dev, "%s jack_insert:%d\n", __func__, jack_insert); + + if (jack_insert) { + snd_soc_update_bits(codec, RT5663_DIG_MISC, + RT5668_DIG_GATE_CTRL_MASK, RT5668_DIG_GATE_CTRL_EN); + snd_soc_update_bits(codec, RT5663_HP_CHARGE_PUMP_1, + RT5663_SI_HP_MASK | RT5668_OSW_HP_L_MASK | + RT5668_OSW_HP_R_MASK, RT5663_SI_HP_EN | + RT5668_OSW_HP_L_DIS | RT5668_OSW_HP_R_DIS); + snd_soc_update_bits(codec, RT5663_DUMMY_1, + RT5663_EMB_CLK_MASK | RT5663_HPA_CPL_BIAS_MASK | + RT5663_HPA_CPR_BIAS_MASK, RT5663_EMB_CLK_EN | + RT5663_HPA_CPL_BIAS_1 | RT5663_HPA_CPR_BIAS_1); + snd_soc_update_bits(codec, RT5663_CBJ_1, + RT5663_INBUF_CBJ_BST1_MASK | RT5663_CBJ_SENSE_BST1_MASK, + RT5663_INBUF_CBJ_BST1_ON | RT5663_CBJ_SENSE_BST1_L); + snd_soc_update_bits(codec, RT5663_IL_CMD_2, + RT5663_PWR_MIC_DET_MASK, RT5663_PWR_MIC_DET_ON); + /* BST1 power on for JD */ + snd_soc_update_bits(codec, RT5663_PWR_ANLG_2, + RT5668_PWR_BST1_MASK, RT5668_PWR_BST1_ON); + snd_soc_update_bits(codec, RT5663_EM_JACK_TYPE_1, + RT5663_CBJ_DET_MASK | RT5663_EXT_JD_MASK | + RT5663_POL_EXT_JD_MASK, RT5663_CBJ_DET_EN | + RT5663_EXT_JD_EN | RT5663_POL_EXT_JD_EN); + snd_soc_update_bits(codec, RT5663_PWR_ANLG_1, + RT5668_PWR_MB_MASK | RT5668_LDO1_DVO_MASK | + RT5668_AMP_HP_MASK, RT5668_PWR_MB | + RT5668_LDO1_DVO_0_9V | RT5668_AMP_HP_3X); + snd_soc_update_bits(codec, RT5663_AUTO_1MRC_CLK, + RT5668_IRQ_POW_SAV_MASK, RT5668_IRQ_POW_SAV_EN); + snd_soc_update_bits(codec, RT5663_IRQ_1, + RT5663_EN_IRQ_JD1_MASK, RT5663_EN_IRQ_JD1_EN); + while (i < 5) { + msleep(sleep_time[i]); + val = snd_soc_read(codec, RT5663_EM_JACK_TYPE_2) & + 0x0003; + i++; + if (val == 0x1 || val == 0x2 || val == 0x3) + break; + dev_dbg(codec->dev, "%s: MX-00e7 val=%x sleep %d\n", + __func__, val, sleep_time[i]); + } + dev_dbg(codec->dev, "%s val = %d\n", __func__, val); + switch (val) { + case 1: + case 2: + rt5663->jack_type = SND_JACK_HEADSET; + rt5663_enable_push_button_irq(codec, true); + break; + default: + rt5663->jack_type = SND_JACK_HEADPHONE; + break; + } + } else { + if (rt5663->jack_type == SND_JACK_HEADSET) + rt5663_enable_push_button_irq(codec, false); + rt5663->jack_type = 0; + } + + dev_dbg(codec->dev, "jack_type = %d\n", rt5663->jack_type); + return rt5663->jack_type; +} + +int rt5663_button_detect(struct snd_soc_codec *codec) +{ + int btn_type, val; + + val = snd_soc_read(codec, RT5663_IL_CMD_5); + dev_dbg(codec->dev, "%s: val=0x%x\n", __func__, val); + btn_type = val & 0xfff0; + snd_soc_write(codec, RT5663_IL_CMD_5, val); + + return btn_type; +} + +static irqreturn_t rt5663_irq(int irq, void *data) +{ + struct rt5663_priv *rt5663 = data; + + dev_dbg(rt5663->codec->dev, "%s IRQ queue work\n", __func__); + + queue_delayed_work(system_wq, &rt5663->jack_detect_work, + msecs_to_jiffies(250)); + + return IRQ_HANDLED; +} + +int rt5663_set_jack_detect(struct snd_soc_codec *codec, + struct snd_soc_jack *hs_jack) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + rt5663->hs_jack = hs_jack; + + rt5663_irq(0, rt5663); + + return 0; +} +EXPORT_SYMBOL_GPL(rt5663_set_jack_detect); + +static bool rt5663_check_jd_status(struct snd_soc_codec *codec) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + int val = snd_soc_read(codec, RT5663_INT_ST_1); + + dev_dbg(codec->dev, "%s val=%x\n", __func__, val); + + /* JD1 */ + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + return !(val & 0x2000); + case CODEC_TYPE_RT5663: + return !(val & 0x1000); + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + + return false; +} + +static void rt5663_jack_detect_work(struct work_struct *work) +{ + struct rt5663_priv *rt5663 = + container_of(work, struct rt5663_priv, jack_detect_work.work); + struct snd_soc_codec *codec = rt5663->codec; + int btn_type, report = 0; + + if (!codec) + return; + + if (rt5663_check_jd_status(codec)) { + /* jack in */ + if (rt5663->jack_type == 0) { + /* jack was out, report jack type */ + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + report = rt5668_jack_detect(rt5663->codec, 1); + break; + case CODEC_TYPE_RT5663: + report = rt5663_jack_detect(rt5663->codec, 1); + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + } else { + /* jack is already in, report button event */ + report = SND_JACK_HEADSET; + btn_type = rt5663_button_detect(rt5663->codec); + /** + * rt5663 can report three kinds of button behavior, + * one click, double click and hold. However, + * currently we will report button pressed/released + * event. So all the three button behaviors are + * treated as button pressed. + */ + switch (btn_type) { + case 0x8000: + case 0x4000: + case 0x2000: + report |= SND_JACK_BTN_0; + break; + case 0x1000: + case 0x0800: + case 0x0400: + report |= SND_JACK_BTN_1; + break; + case 0x0200: + case 0x0100: + case 0x0080: + report |= SND_JACK_BTN_2; + break; + case 0x0040: + case 0x0020: + case 0x0010: + report |= SND_JACK_BTN_3; + break; + case 0x0000: /* unpressed */ + break; + default: + btn_type = 0; + dev_err(rt5663->codec->dev, + "Unexpected button code 0x%04x\n", + btn_type); + break; + } + /* button release or spurious interrput*/ + if (btn_type == 0) + report = rt5663->jack_type; + } + } else { + /* jack out */ + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + report = rt5668_jack_detect(rt5663->codec, 0); + break; + case CODEC_TYPE_RT5663: + report = rt5663_jack_detect(rt5663->codec, 0); + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + } + dev_dbg(codec->dev, "%s jack report: 0x%04x\n", __func__, report); + snd_soc_jack_report(rt5663->hs_jack, report, SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); +} + +static const struct snd_kcontrol_new rt5663_snd_controls[] = { + /* DAC Digital Volume */ + SOC_DOUBLE_TLV("DAC Playback Volume", RT5663_STO1_DAC_DIG_VOL, + RT5668_DAC_L1_VOL_SHIFT + 1, RT5668_DAC_R1_VOL_SHIFT + 1, + 87, 0, dac_vol_tlv), + /* ADC Digital Volume Control */ + SOC_DOUBLE("ADC Capture Switch", RT5663_STO1_ADC_DIG_VOL, + RT5668_ADC_L_MUTE_SHIFT, RT5668_ADC_R_MUTE_SHIFT, 1, 1), + SOC_DOUBLE_TLV("ADC Capture Volume", RT5663_STO1_ADC_DIG_VOL, + RT5668_ADC_L_VOL_SHIFT + 1, RT5668_ADC_R_VOL_SHIFT + 1, + 63, 0, adc_vol_tlv), +}; + +static const struct snd_kcontrol_new rt5668_specific_controls[] = { + /* Headphone Output Volume */ + SOC_DOUBLE_R_TLV("Headphone Playback Volume", RT5663_HP_LCH_DRE, + RT5663_HP_RCH_DRE, RT5668_GAIN_HP_SHIFT, 15, 1, + rt5668_hp_vol_tlv), + /* Mic Boost Volume */ + SOC_SINGLE_TLV("IN1 Capture Volume", RT5668_AEC_BST, + RT5668_GAIN_CBJ_SHIFT, 8, 0, in_bst_tlv), +}; + +static const struct snd_kcontrol_new rt5663_specific_controls[] = { + /* Headphone Output Volume */ + SOC_DOUBLE_R_TLV("Headphone Playback Volume", RT5663_STO_DRE_9, + RT5663_STO_DRE_10, RT5663_DRE_GAIN_HP_SHIFT, 23, 1, + rt5663_hp_vol_tlv), + /* Mic Boost Volume*/ + SOC_SINGLE_TLV("IN1 Capture Volume", RT5663_CBJ_2, + RT5663_GAIN_BST1_SHIFT, 8, 0, in_bst_tlv), + /* Data Swap for Slot0/1 in ADCDAT1 */ + SOC_ENUM("IF1 ADC Data Swap", rt5663_if1_adc_enum), +}; + +static int rt5663_is_sys_clk_from_pll(struct snd_soc_dapm_widget *w, + struct snd_soc_dapm_widget *sink) +{ + unsigned int val; + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + val = snd_soc_read(codec, RT5663_GLB_CLK); + val &= RT5663_SCLK_SRC_MASK; + if (val == RT5663_SCLK_SRC_PLL1) + return 1; + else + return 0; +} + +static int rt5663_is_using_asrc(struct snd_soc_dapm_widget *w, + struct snd_soc_dapm_widget *sink) +{ + unsigned int reg, shift, val; + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + if (rt5663->codec_type == CODEC_TYPE_RT5668) { + switch (w->shift) { + case RT5668_ADC_STO1_ASRC_SHIFT: + reg = RT5668_ASRC_3; + shift = RT5668_AD_STO1_TRACK_SHIFT; + break; + case RT5668_DAC_STO1_ASRC_SHIFT: + reg = RT5663_ASRC_2; + shift = RT5668_DA_STO1_TRACK_SHIFT; + break; + default: + return 0; + } + } else { + switch (w->shift) { + case RT5663_ADC_STO1_ASRC_SHIFT: + reg = RT5663_ASRC_2; + shift = RT5663_AD_STO1_TRACK_SHIFT; + break; + case RT5663_DAC_STO1_ASRC_SHIFT: + reg = RT5663_ASRC_2; + shift = RT5663_DA_STO1_TRACK_SHIFT; + break; + default: + return 0; + } + } + + val = (snd_soc_read(codec, reg) >> shift) & 0x7; + + if (val) + return 1; + + return 0; +} + +static int rt5663_i2s_use_asrc(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + int da_asrc_en, ad_asrc_en; + + da_asrc_en = (snd_soc_read(codec, RT5663_ASRC_2) & + RT5663_DA_STO1_TRACK_MASK) ? 1 : 0; + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + ad_asrc_en = (snd_soc_read(codec, RT5668_ASRC_3) & + RT5668_AD_STO1_TRACK_MASK) ? 1 : 0; + break; + case CODEC_TYPE_RT5663: + ad_asrc_en = (snd_soc_read(codec, RT5663_ASRC_2) & + RT5663_AD_STO1_TRACK_MASK) ? 1 : 0; + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + + if (da_asrc_en || ad_asrc_en) + if (rt5663->sysclk > rt5663->lrck * 384) + return 1; + + dev_err(codec->dev, "sysclk < 384 x fs, disable i2s asrc\n"); + + return 0; +} + +/** + * rt5663_sel_asrc_clk_src - select ASRC clock source for a set of filters + * @codec: SoC audio codec device. + * @filter_mask: mask of filters. + * @clk_src: clock source + * + * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5668 can + * only support standard 32fs or 64fs i2s format, ASRC should be enabled to + * support special i2s clock format such as Intel's 100fs(100 * sampling rate). + * ASRC function will track i2s clock and generate a corresponding system clock + * for codec. This function provides an API to select the clock source for a + * set of filters specified by the mask. And the codec driver will turn on ASRC + * for these filters if ASRC is selected as their clock source. + */ +int rt5663_sel_asrc_clk_src(struct snd_soc_codec *codec, + unsigned int filter_mask, unsigned int clk_src) +{ + struct rt5663_priv *rt5668 = snd_soc_codec_get_drvdata(codec); + unsigned int asrc2_mask = 0; + unsigned int asrc2_value = 0; + unsigned int asrc3_mask = 0; + unsigned int asrc3_value = 0; + + switch (clk_src) { + case RT5663_CLK_SEL_SYS: + case RT5663_CLK_SEL_I2S1_ASRC: + break; + + default: + return -EINVAL; + } + + if (filter_mask & RT5663_DA_STEREO_FILTER) { + asrc2_mask |= RT5668_DA_STO1_TRACK_MASK; + asrc2_value |= clk_src << RT5668_DA_STO1_TRACK_SHIFT; + } + + if (filter_mask & RT5663_AD_STEREO_FILTER) { + switch (rt5668->codec_type) { + case CODEC_TYPE_RT5668: + asrc3_mask |= RT5668_AD_STO1_TRACK_MASK; + asrc3_value |= clk_src << RT5668_AD_STO1_TRACK_SHIFT; + break; + case CODEC_TYPE_RT5663: + asrc2_mask |= RT5663_AD_STO1_TRACK_MASK; + asrc2_value |= clk_src << RT5663_AD_STO1_TRACK_SHIFT; + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + } + + if (asrc2_mask) + snd_soc_update_bits(codec, RT5663_ASRC_2, asrc2_mask, + asrc2_value); + + if (asrc3_mask) + snd_soc_update_bits(codec, RT5668_ASRC_3, asrc3_mask, + asrc3_value); + + return 0; +} +EXPORT_SYMBOL_GPL(rt5663_sel_asrc_clk_src); + +/* Analog Mixer */ +static const struct snd_kcontrol_new rt5668_recmix1l[] = { + SOC_DAPM_SINGLE("BST2 Switch", RT5668_RECMIX1L, + RT5668_RECMIX1L_BST2_SHIFT, 1, 1), + SOC_DAPM_SINGLE("BST1 CBJ Switch", RT5668_RECMIX1L, + RT5668_RECMIX1L_BST1_CBJ_SHIFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5668_recmix1r[] = { + SOC_DAPM_SINGLE("BST2 Switch", RT5668_RECMIX1R, + RT5668_RECMIX1R_BST2_SHIFT, 1, 1), +}; + +/* Digital Mixer */ +static const struct snd_kcontrol_new rt5663_sto1_adc_l_mix[] = { + SOC_DAPM_SINGLE("ADC1 Switch", RT5663_STO1_ADC_MIXER, + RT5668_M_STO1_ADC_L1_SHIFT, 1, 1), + SOC_DAPM_SINGLE("ADC2 Switch", RT5663_STO1_ADC_MIXER, + RT5668_M_STO1_ADC_L2_SHIFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5668_sto1_adc_r_mix[] = { + SOC_DAPM_SINGLE("ADC1 Switch", RT5663_STO1_ADC_MIXER, + RT5668_M_STO1_ADC_R1_SHIFT, 1, 1), + SOC_DAPM_SINGLE("ADC2 Switch", RT5663_STO1_ADC_MIXER, + RT5668_M_STO1_ADC_R2_SHIFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5663_adda_l_mix[] = { + SOC_DAPM_SINGLE("ADC L Switch", RT5663_AD_DA_MIXER, + RT5668_M_ADCMIX_L_SHIFT, 1, 1), + SOC_DAPM_SINGLE("DAC L Switch", RT5663_AD_DA_MIXER, + RT5668_M_DAC1_L_SHIFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5663_adda_r_mix[] = { + SOC_DAPM_SINGLE("ADC R Switch", RT5663_AD_DA_MIXER, + RT5668_M_ADCMIX_R_SHIFT, 1, 1), + SOC_DAPM_SINGLE("DAC R Switch", RT5663_AD_DA_MIXER, + RT5668_M_DAC1_R_SHIFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5663_sto1_dac_l_mix[] = { + SOC_DAPM_SINGLE("DAC L Switch", RT5663_STO_DAC_MIXER, + RT5668_M_DAC_L1_STO_L_SHIFT, 1, 1), + SOC_DAPM_SINGLE("DAC R Switch", RT5663_STO_DAC_MIXER, + RT5668_M_DAC_R1_STO_L_SHIFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5663_sto1_dac_r_mix[] = { + SOC_DAPM_SINGLE("DAC L Switch", RT5663_STO_DAC_MIXER, + RT5668_M_DAC_L1_STO_R_SHIFT, 1, 1), + SOC_DAPM_SINGLE("DAC R Switch", RT5663_STO_DAC_MIXER, + RT5668_M_DAC_R1_STO_R_SHIFT, 1, 1), +}; + +/* Out Switch */ +static const struct snd_kcontrol_new rt5668_hpo_switch = + SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5668_HP_AMP_2, + RT5668_EN_DAC_HPO_SHIFT, 1, 0); + +/* Stereo ADC source */ +static const char * const rt5668_sto1_adc_src[] = { + "ADC L", "ADC R" +}; + +static SOC_ENUM_SINGLE_DECL(rt5668_sto1_adcl_enum, RT5663_STO1_ADC_MIXER, + RT5668_STO1_ADC_L_SRC_SHIFT, rt5668_sto1_adc_src); + +static const struct snd_kcontrol_new rt5668_sto1_adcl_mux = + SOC_DAPM_ENUM("STO1 ADC L Mux", rt5668_sto1_adcl_enum); + +static SOC_ENUM_SINGLE_DECL(rt5668_sto1_adcr_enum, RT5663_STO1_ADC_MIXER, + RT5668_STO1_ADC_R_SRC_SHIFT, rt5668_sto1_adc_src); + +static const struct snd_kcontrol_new rt5668_sto1_adcr_mux = + SOC_DAPM_ENUM("STO1 ADC R Mux", rt5668_sto1_adcr_enum); + +/* RT5663: Analog DACL1 input source */ +static const char * const rt5663_alg_dacl_src[] = { + "DAC L", "STO DAC MIXL" +}; + +static SOC_ENUM_SINGLE_DECL(rt5663_alg_dacl_enum, RT5663_BYPASS_STO_DAC, + RT5663_DACL1_SRC_SHIFT, rt5663_alg_dacl_src); + +static const struct snd_kcontrol_new rt5663_alg_dacl_mux = + SOC_DAPM_ENUM("DAC L Mux", rt5663_alg_dacl_enum); + +/* RT5663: Analog DACR1 input source */ +static const char * const rt5663_alg_dacr_src[] = { + "DAC R", "STO DAC MIXR" +}; + +static SOC_ENUM_SINGLE_DECL(rt5663_alg_dacr_enum, RT5663_BYPASS_STO_DAC, + RT5663_DACR1_SRC_SHIFT, rt5663_alg_dacr_src); + +static const struct snd_kcontrol_new rt5663_alg_dacr_mux = + SOC_DAPM_ENUM("DAC R Mux", rt5663_alg_dacr_enum); + +static int rt5663_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + if (rt5663->codec_type == CODEC_TYPE_RT5668) { + snd_soc_update_bits(codec, RT5663_HP_CHARGE_PUMP_1, + RT5668_SEL_PM_HP_SHIFT, RT5668_SEL_PM_HP_HIGH); + snd_soc_update_bits(codec, RT5663_HP_LOGIC_2, + RT5668_HP_SIG_SRC1_MASK, + RT5668_HP_SIG_SRC1_SILENCE); + } else { + snd_soc_write(codec, RT5663_DEPOP_2, 0x3003); + snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x000b, + 0x000b); + snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x0030, + 0x0030); + snd_soc_update_bits(codec, RT5663_HP_CHARGE_PUMP_1, + RT5668_OVCD_HP_MASK, RT5668_OVCD_HP_DIS); + snd_soc_write(codec, RT5663_HP_CHARGE_PUMP_2, 0x1371); + snd_soc_write(codec, RT5663_HP_BIAS, 0xabba); + snd_soc_write(codec, RT5663_CHARGE_PUMP_1, 0x2224); + snd_soc_write(codec, RT5663_ANA_BIAS_CUR_1, 0x7766); + snd_soc_write(codec, RT5663_HP_BIAS, 0xafaa); + snd_soc_write(codec, RT5663_CHARGE_PUMP_2, 0x7777); + snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x3000, + 0x3000); + } + break; + + case SND_SOC_DAPM_PRE_PMD: + if (rt5663->codec_type == CODEC_TYPE_RT5668) { + snd_soc_update_bits(codec, RT5663_HP_LOGIC_2, + RT5668_HP_SIG_SRC1_MASK, + RT5668_HP_SIG_SRC1_REG); + } else { + snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x3000, 0x0); + snd_soc_update_bits(codec, RT5663_HP_CHARGE_PUMP_1, + RT5668_OVCD_HP_MASK, RT5668_OVCD_HP_EN); + snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x0030, 0x0); + snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x000b, + 0x000b); + } + break; + + default: + return 0; + } + + return 0; +} + +static int rt5668_bst2_power(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, RT5663_PWR_ANLG_2, + RT5668_PWR_BST2_MASK | RT5668_PWR_BST2_OP_MASK, + RT5668_PWR_BST2 | RT5668_PWR_BST2_OP); + break; + + case SND_SOC_DAPM_PRE_PMD: + snd_soc_update_bits(codec, RT5663_PWR_ANLG_2, + RT5668_PWR_BST2_MASK | RT5668_PWR_BST2_OP_MASK, 0); + break; + + default: + return 0; + } + + return 0; +} + +static int rt5663_pre_div_power(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_write(codec, RT5663_PRE_DIV_GATING_1, 0xff00); + snd_soc_write(codec, RT5663_PRE_DIV_GATING_2, 0xfffc); + break; + + case SND_SOC_DAPM_PRE_PMD: + snd_soc_write(codec, RT5663_PRE_DIV_GATING_1, 0x0000); + snd_soc_write(codec, RT5663_PRE_DIV_GATING_2, 0x0000); + break; + + default: + return 0; + } + + return 0; +} + +static const struct snd_soc_dapm_widget rt5663_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("PLL", RT5663_PWR_ANLG_3, RT5668_PWR_PLL_SHIFT, 0, + NULL, 0), + + /* micbias */ + SND_SOC_DAPM_MICBIAS("MICBIAS1", RT5663_PWR_ANLG_2, + RT5668_PWR_MB1_SHIFT, 0), + SND_SOC_DAPM_MICBIAS("MICBIAS2", RT5663_PWR_ANLG_2, + RT5668_PWR_MB2_SHIFT, 0), + + /* Input Lines */ + SND_SOC_DAPM_INPUT("IN1P"), + SND_SOC_DAPM_INPUT("IN1N"), + + /* REC Mixer Power */ + SND_SOC_DAPM_SUPPLY("RECMIX1L Power", RT5663_PWR_ANLG_2, + RT5668_PWR_RECMIX1_SHIFT, 0, NULL, 0), + + /* ADCs */ + SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_SUPPLY("ADC L Power", RT5663_PWR_DIG_1, + RT5668_PWR_ADC_L1_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC Clock", RT5663_CHOP_ADC, + RT5668_CKGEN_ADCC_SHIFT, 0, NULL, 0), + + /* ADC Mixer */ + SND_SOC_DAPM_MIXER("STO1 ADC MIXL", SND_SOC_NOPM, + 0, 0, rt5663_sto1_adc_l_mix, + ARRAY_SIZE(rt5663_sto1_adc_l_mix)), + + /* ADC Filter Power */ + SND_SOC_DAPM_SUPPLY("STO1 ADC Filter", RT5663_PWR_DIG_2, + RT5668_PWR_ADC_S1F_SHIFT, 0, NULL, 0), + + /* Digital Interface */ + SND_SOC_DAPM_SUPPLY("I2S", RT5663_PWR_DIG_1, RT5668_PWR_I2S1_SHIFT, 0, + NULL, 0), + SND_SOC_DAPM_PGA("IF DAC", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF1 ADC1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF ADC", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* Audio Interface */ + SND_SOC_DAPM_AIF_IN("AIFRX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AIFTX", "AIF Capture", 0, SND_SOC_NOPM, 0, 0), + + /* DAC mixer before sound effect */ + SND_SOC_DAPM_MIXER("ADDA MIXL", SND_SOC_NOPM, 0, 0, rt5663_adda_l_mix, + ARRAY_SIZE(rt5663_adda_l_mix)), + SND_SOC_DAPM_MIXER("ADDA MIXR", SND_SOC_NOPM, 0, 0, rt5663_adda_r_mix, + ARRAY_SIZE(rt5663_adda_r_mix)), + SND_SOC_DAPM_PGA("DAC L1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DAC R1", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* DAC Mixer */ + SND_SOC_DAPM_SUPPLY("STO1 DAC Filter", RT5663_PWR_DIG_2, + RT5668_PWR_DAC_S1F_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_MIXER("STO1 DAC MIXL", SND_SOC_NOPM, 0, 0, + rt5663_sto1_dac_l_mix, ARRAY_SIZE(rt5663_sto1_dac_l_mix)), + SND_SOC_DAPM_MIXER("STO1 DAC MIXR", SND_SOC_NOPM, 0, 0, + rt5663_sto1_dac_r_mix, ARRAY_SIZE(rt5663_sto1_dac_r_mix)), + + /* DACs */ + SND_SOC_DAPM_SUPPLY("STO1 DAC L Power", RT5663_PWR_DIG_1, + RT5668_PWR_DAC_L1_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("STO1 DAC R Power", RT5663_PWR_DIG_1, + RT5668_PWR_DAC_R1_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_DAC("DAC L", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC R", NULL, SND_SOC_NOPM, 0, 0), + + /* Headphone*/ + SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, rt5663_hp_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + + /* Output Lines */ + SND_SOC_DAPM_OUTPUT("HPOL"), + SND_SOC_DAPM_OUTPUT("HPOR"), +}; + +static const struct snd_soc_dapm_widget rt5668_specific_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("LDO2", RT5663_PWR_ANLG_3, + RT5668_PWR_LDO2_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5668_PWR_VOL, + RT5668_PWR_MIC_DET_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("LDO DAC", RT5663_PWR_DIG_1, + RT5668_PWR_LDO_DACREF_SHIFT, 0, NULL, 0), + + /* ASRC */ + SND_SOC_DAPM_SUPPLY("I2S ASRC", RT5663_ASRC_1, + RT5668_I2S1_ASRC_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC ASRC", RT5663_ASRC_1, + RT5668_DAC_STO1_ASRC_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC ASRC", RT5663_ASRC_1, + RT5668_ADC_STO1_ASRC_SHIFT, 0, NULL, 0), + + /* Input Lines */ + SND_SOC_DAPM_INPUT("IN2P"), + SND_SOC_DAPM_INPUT("IN2N"), + + /* Boost */ + SND_SOC_DAPM_PGA("BST1 CBJ", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("CBJ Power", RT5663_PWR_ANLG_3, + RT5668_PWR_CBJ_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("BST2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("BST2 Power", SND_SOC_NOPM, 0, 0, + rt5668_bst2_power, SND_SOC_DAPM_PRE_PMD | + SND_SOC_DAPM_POST_PMU), + + /* REC Mixer */ + SND_SOC_DAPM_MIXER("RECMIX1L", SND_SOC_NOPM, 0, 0, rt5668_recmix1l, + ARRAY_SIZE(rt5668_recmix1l)), + SND_SOC_DAPM_MIXER("RECMIX1R", SND_SOC_NOPM, 0, 0, rt5668_recmix1r, + ARRAY_SIZE(rt5668_recmix1r)), + SND_SOC_DAPM_SUPPLY("RECMIX1R Power", RT5663_PWR_ANLG_2, + RT5668_PWR_RECMIX2_SHIFT, 0, NULL, 0), + + /* ADC */ + SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_SUPPLY("ADC R Power", RT5663_PWR_DIG_1, + RT5668_PWR_ADC_R1_SHIFT, 0, NULL, 0), + + /* ADC Mux */ + SND_SOC_DAPM_PGA("STO1 ADC L1", RT5663_STO1_ADC_MIXER, + RT5668_STO1_ADC_L1_SRC_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("STO1 ADC R1", RT5663_STO1_ADC_MIXER, + RT5668_STO1_ADC_R1_SRC_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("STO1 ADC L2", RT5663_STO1_ADC_MIXER, + RT5668_STO1_ADC_L2_SRC_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_PGA("STO1 ADC R2", RT5663_STO1_ADC_MIXER, + RT5668_STO1_ADC_R2_SRC_SHIFT, 1, NULL, 0), + + SND_SOC_DAPM_MUX("STO1 ADC L Mux", SND_SOC_NOPM, 0, 0, + &rt5668_sto1_adcl_mux), + SND_SOC_DAPM_MUX("STO1 ADC R Mux", SND_SOC_NOPM, 0, 0, + &rt5668_sto1_adcr_mux), + + /* ADC Mix */ + SND_SOC_DAPM_MIXER("STO1 ADC MIXR", SND_SOC_NOPM, 0, 0, + rt5668_sto1_adc_r_mix, ARRAY_SIZE(rt5668_sto1_adc_r_mix)), + + /* Analog DAC Clock */ + SND_SOC_DAPM_SUPPLY("DAC Clock", RT5663_CHOP_DAC_L, + RT5668_CKGEN_DAC1_SHIFT, 0, NULL, 0), + + /* Headphone out */ + SND_SOC_DAPM_SWITCH("HPO Playback", SND_SOC_NOPM, 0, 0, + &rt5668_hpo_switch), +}; + +static const struct snd_soc_dapm_widget rt5663_specific_dapm_widgets[] = { + /* System Clock Pre Divider Gating */ + SND_SOC_DAPM_SUPPLY("Pre Div Power", SND_SOC_NOPM, 0, 0, + rt5663_pre_div_power, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), + + /* LDO */ + SND_SOC_DAPM_SUPPLY("LDO ADC", RT5663_PWR_DIG_1, + RT5668_PWR_LDO_DACREF_SHIFT, 0, NULL, 0), + + /* ASRC */ + SND_SOC_DAPM_SUPPLY("I2S ASRC", RT5663_ASRC_1, + RT5663_I2S1_ASRC_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC ASRC", RT5663_ASRC_1, + RT5663_DAC_STO1_ASRC_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC ASRC", RT5663_ASRC_1, + RT5663_ADC_STO1_ASRC_SHIFT, 0, NULL, 0), + + /* Boost */ + SND_SOC_DAPM_PGA("BST1", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* STO ADC */ + SND_SOC_DAPM_PGA("STO1 ADC L1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("STO1 ADC L2", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* Analog DAC source */ + SND_SOC_DAPM_MUX("DAC L Mux", SND_SOC_NOPM, 0, 0, &rt5663_alg_dacl_mux), + SND_SOC_DAPM_MUX("DAC R Mux", SND_SOC_NOPM, 0, 0, &rt5663_alg_dacr_mux), +}; + +static const struct snd_soc_dapm_route rt5663_dapm_routes[] = { + /* PLL */ + { "I2S", NULL, "PLL", rt5663_is_sys_clk_from_pll }, + + /* ASRC */ + { "STO1 ADC Filter", NULL, "ADC ASRC", rt5663_is_using_asrc }, + { "STO1 DAC Filter", NULL, "DAC ASRC", rt5663_is_using_asrc }, + { "I2S", NULL, "I2S ASRC", rt5663_i2s_use_asrc }, + + { "ADC L", NULL, "ADC L Power" }, + { "ADC L", NULL, "ADC Clock" }, + + { "STO1 ADC L2", NULL, "STO1 DAC MIXL" }, + + { "STO1 ADC MIXL", "ADC1 Switch", "STO1 ADC L1" }, + { "STO1 ADC MIXL", "ADC2 Switch", "STO1 ADC L2" }, + { "STO1 ADC MIXL", NULL, "STO1 ADC Filter" }, + + { "IF1 ADC1", NULL, "STO1 ADC MIXL" }, + { "IF ADC", NULL, "IF1 ADC1" }, + { "AIFTX", NULL, "IF ADC" }, + { "AIFTX", NULL, "I2S" }, + + { "AIFRX", NULL, "I2S" }, + { "IF DAC", NULL, "AIFRX" }, + { "IF1 DAC1 L", NULL, "IF DAC" }, + { "IF1 DAC1 R", NULL, "IF DAC" }, + + { "ADDA MIXL", "ADC L Switch", "STO1 ADC MIXL" }, + { "ADDA MIXL", "DAC L Switch", "IF1 DAC1 L" }, + { "ADDA MIXL", NULL, "STO1 DAC Filter" }, + { "ADDA MIXL", NULL, "STO1 DAC L Power" }, + { "ADDA MIXR", "DAC R Switch", "IF1 DAC1 R" }, + { "ADDA MIXR", NULL, "STO1 DAC Filter" }, + { "ADDA MIXR", NULL, "STO1 DAC R Power" }, + + { "DAC L1", NULL, "ADDA MIXL" }, + { "DAC R1", NULL, "ADDA MIXR" }, + + { "STO1 DAC MIXL", "DAC L Switch", "DAC L1" }, + { "STO1 DAC MIXL", "DAC R Switch", "DAC R1" }, + { "STO1 DAC MIXL", NULL, "STO1 DAC L Power" }, + { "STO1 DAC MIXL", NULL, "STO1 DAC Filter" }, + { "STO1 DAC MIXR", "DAC R Switch", "DAC R1" }, + { "STO1 DAC MIXR", "DAC L Switch", "DAC L1" }, + { "STO1 DAC MIXR", NULL, "STO1 DAC R Power" }, + { "STO1 DAC MIXR", NULL, "STO1 DAC Filter" }, + + { "HP Amp", NULL, "DAC L" }, + { "HP Amp", NULL, "DAC R" }, +}; + +static const struct snd_soc_dapm_route rt5668_specific_dapm_routes[] = { + { "MICBIAS1", NULL, "LDO2" }, + { "MICBIAS2", NULL, "LDO2" }, + + { "BST1 CBJ", NULL, "IN1P" }, + { "BST1 CBJ", NULL, "IN1N" }, + { "BST1 CBJ", NULL, "CBJ Power" }, + + { "BST2", NULL, "IN2P" }, + { "BST2", NULL, "IN2N" }, + { "BST2", NULL, "BST2 Power" }, + + { "RECMIX1L", "BST2 Switch", "BST2" }, + { "RECMIX1L", "BST1 CBJ Switch", "BST1 CBJ" }, + { "RECMIX1L", NULL, "RECMIX1L Power" }, + { "RECMIX1R", "BST2 Switch", "BST2" }, + { "RECMIX1R", NULL, "RECMIX1R Power" }, + + { "ADC L", NULL, "RECMIX1L" }, + { "ADC R", NULL, "RECMIX1R" }, + { "ADC R", NULL, "ADC R Power" }, + { "ADC R", NULL, "ADC Clock" }, + + { "STO1 ADC L Mux", "ADC L", "ADC L" }, + { "STO1 ADC L Mux", "ADC R", "ADC R" }, + { "STO1 ADC L1", NULL, "STO1 ADC L Mux" }, + + { "STO1 ADC R Mux", "ADC L", "ADC L" }, + { "STO1 ADC R Mux", "ADC R", "ADC R" }, + { "STO1 ADC R1", NULL, "STO1 ADC R Mux" }, + { "STO1 ADC R2", NULL, "STO1 DAC MIXR" }, + + { "STO1 ADC MIXR", "ADC1 Switch", "STO1 ADC R1" }, + { "STO1 ADC MIXR", "ADC2 Switch", "STO1 ADC R2" }, + { "STO1 ADC MIXR", NULL, "STO1 ADC Filter" }, + + { "IF1 ADC1", NULL, "STO1 ADC MIXR" }, + + { "ADDA MIXR", "ADC R Switch", "STO1 ADC MIXR" }, + + { "DAC L", NULL, "STO1 DAC MIXL" }, + { "DAC L", NULL, "LDO DAC" }, + { "DAC L", NULL, "DAC Clock" }, + { "DAC R", NULL, "STO1 DAC MIXR" }, + { "DAC R", NULL, "LDO DAC" }, + { "DAC R", NULL, "DAC Clock" }, + + { "HPO Playback", "Switch", "HP Amp" }, + { "HPOL", NULL, "HPO Playback" }, + { "HPOR", NULL, "HPO Playback" }, +}; + +static const struct snd_soc_dapm_route rt5663_specific_dapm_routes[] = { + { "I2S", NULL, "Pre Div Power" }, + + { "BST1", NULL, "IN1P" }, + { "BST1", NULL, "IN1N" }, + { "BST1", NULL, "RECMIX1L Power" }, + + { "ADC L", NULL, "BST1" }, + + { "STO1 ADC L1", NULL, "ADC L" }, + + { "DAC L Mux", "DAC L", "DAC L1" }, + { "DAC L Mux", "STO DAC MIXL", "STO1 DAC MIXL" }, + { "DAC R Mux", "DAC R", "DAC R1"}, + { "DAC R Mux", "STO DAC MIXR", "STO1 DAC MIXR" }, + + { "DAC L", NULL, "DAC L Mux" }, + { "DAC R", NULL, "DAC R Mux" }, + + { "HPOL", NULL, "HP Amp" }, + { "HPOR", NULL, "HP Amp" }, +}; + +static int rt5663_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + unsigned int val_len = 0; + int pre_div; + + rt5663->lrck = params_rate(params); + + dev_dbg(dai->dev, "bclk is %dHz and sysclk is %dHz\n", + rt5663->lrck, rt5663->sysclk); + + pre_div = rl6231_get_clk_info(rt5663->sysclk, rt5663->lrck); + if (pre_div < 0) { + dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n", + rt5663->lrck, dai->id); + return -EINVAL; + } + + dev_dbg(dai->dev, "pre_div is %d for iis %d\n", pre_div, dai->id); + + switch (params_width(params)) { + case 8: + val_len = RT5668_I2S_DL_8; + break; + case 16: + val_len = RT5668_I2S_DL_16; + break; + case 20: + val_len = RT5668_I2S_DL_20; + break; + case 24: + val_len = RT5668_I2S_DL_24; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, RT5663_I2S1_SDP, + RT5668_I2S_DL_MASK, val_len); + + snd_soc_update_bits(codec, RT5663_ADDA_CLK_1, + RT5668_I2S_PD1_MASK, pre_div << RT5668_I2S_PD1_SHIFT); + + return 0; +} + +static int rt5663_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = dai->codec; + unsigned int reg_val = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + break; + case SND_SOC_DAIFMT_CBS_CFS: + reg_val |= RT5668_I2S_MS_S; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + reg_val |= RT5668_I2S_BP_INV; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + case SND_SOC_DAIFMT_LEFT_J: + reg_val |= RT5668_I2S_DF_LEFT; + break; + case SND_SOC_DAIFMT_DSP_A: + reg_val |= RT5668_I2S_DF_PCM_A; + break; + case SND_SOC_DAIFMT_DSP_B: + reg_val |= RT5668_I2S_DF_PCM_B; + break; + default: + return -EINVAL; + } + + snd_soc_update_bits(codec, RT5663_I2S1_SDP, RT5668_I2S_MS_MASK | + RT5668_I2S_BP_MASK | RT5668_I2S_DF_MASK, reg_val); + + return 0; +} + +static int rt5663_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + unsigned int reg_val = 0; + + if (freq == rt5663->sysclk && clk_id == rt5663->sysclk_src) + return 0; + + switch (clk_id) { + case RT5663_SCLK_S_MCLK: + reg_val |= RT5663_SCLK_SRC_MCLK; + break; + case RT5663_SCLK_S_PLL1: + reg_val |= RT5663_SCLK_SRC_PLL1; + break; + case RT5663_SCLK_S_RCCLK: + reg_val |= RT5663_SCLK_SRC_RCCLK; + break; + default: + dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); + return -EINVAL; + } + snd_soc_update_bits(codec, RT5663_GLB_CLK, RT5668_SCLK_SRC_MASK, + reg_val); + rt5663->sysclk = freq; + rt5663->sysclk_src = clk_id; + + dev_dbg(codec->dev, "Sysclk is %dHz and clock id is %d\n", + freq, clk_id); + + return 0; +} + +static int rt5663_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, + unsigned int freq_in, unsigned int freq_out) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + struct rl6231_pll_code pll_code; + int ret; + int mask, shift, val; + + if (source == rt5663->pll_src && freq_in == rt5663->pll_in && + freq_out == rt5663->pll_out) + return 0; + + if (!freq_in || !freq_out) { + dev_dbg(codec->dev, "PLL disabled\n"); + + rt5663->pll_in = 0; + rt5663->pll_out = 0; + snd_soc_update_bits(codec, RT5663_GLB_CLK, + RT5663_SCLK_SRC_MASK, RT5663_SCLK_SRC_MCLK); + return 0; + } + + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + mask = RT5668_PLL1_SRC_MASK; + shift = RT5668_PLL1_SRC_SHIFT; + break; + case CODEC_TYPE_RT5663: + mask = RT5663_PLL1_SRC_MASK; + shift = RT5663_PLL1_SRC_SHIFT; + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + + switch (source) { + case RT5663_PLL1_S_MCLK: + val = 0x0; + break; + case RT5663_PLL1_S_BCLK1: + val = 0x1; + break; + default: + dev_err(codec->dev, "Unknown PLL source %d\n", source); + return -EINVAL; + } + snd_soc_update_bits(codec, RT5663_GLB_CLK, mask, (val << shift)); + + ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); + if (ret < 0) { + dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); + return ret; + } + + dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n", pll_code.m_bp, + (pll_code.m_bp ? 0 : pll_code.m_code), pll_code.n_code, + pll_code.k_code); + + snd_soc_write(codec, RT5663_PLL_1, + pll_code.n_code << RT5668_PLL_N_SHIFT | pll_code.k_code); + snd_soc_write(codec, RT5663_PLL_2, + (pll_code.m_bp ? 0 : pll_code.m_code) << RT5668_PLL_M_SHIFT | + pll_code.m_bp << RT5668_PLL_M_BP_SHIFT); + + rt5663->pll_in = freq_in; + rt5663->pll_out = freq_out; + rt5663->pll_src = source; + + return 0; +} + +static int rt5663_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int slot_width) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + unsigned int val = 0, reg; + + if (rx_mask || tx_mask) + val |= RT5668_TDM_MODE_TDM; + + switch (slots) { + case 4: + val |= RT5668_TDM_IN_CH_4; + val |= RT5668_TDM_OUT_CH_4; + break; + case 6: + val |= RT5668_TDM_IN_CH_6; + val |= RT5668_TDM_OUT_CH_6; + break; + case 8: + val |= RT5668_TDM_IN_CH_8; + val |= RT5668_TDM_OUT_CH_8; + break; + case 2: + break; + default: + return -EINVAL; + } + + switch (slot_width) { + case 20: + val |= RT5668_TDM_IN_LEN_20; + val |= RT5668_TDM_OUT_LEN_20; + break; + case 24: + val |= RT5668_TDM_IN_LEN_24; + val |= RT5668_TDM_OUT_LEN_24; + break; + case 32: + val |= RT5668_TDM_IN_LEN_32; + val |= RT5668_TDM_OUT_LEN_32; + break; + case 16: + break; + default: + return -EINVAL; + } + + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + reg = RT5663_TDM_2; + break; + case CODEC_TYPE_RT5663: + reg = RT5663_TDM_1; + break; + default: + dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + } + + snd_soc_update_bits(codec, reg, RT5668_TDM_MODE_MASK | + RT5668_TDM_IN_CH_MASK | RT5668_TDM_OUT_CH_MASK | + RT5668_TDM_IN_LEN_MASK | RT5668_TDM_OUT_LEN_MASK, val); + + return 0; +} + +static int rt5663_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + unsigned int reg; + + dev_dbg(codec->dev, "%s ratio = %d\n", __func__, ratio); + + if (rt5663->codec_type == CODEC_TYPE_RT5668) + reg = RT5668_TDM_8; + else + reg = RT5663_TDM_5; + + switch (ratio) { + case 32: + snd_soc_update_bits(codec, reg, + RT5663_TDM_LENGTN_MASK, + RT5663_TDM_LENGTN_16); + break; + case 40: + snd_soc_update_bits(codec, reg, + RT5663_TDM_LENGTN_MASK, + RT5663_TDM_LENGTN_20); + break; + case 48: + snd_soc_update_bits(codec, reg, + RT5663_TDM_LENGTN_MASK, + RT5663_TDM_LENGTN_24); + break; + case 64: + snd_soc_update_bits(codec, reg, + RT5663_TDM_LENGTN_MASK, + RT5663_TDM_LENGTN_32); + break; + default: + dev_err(codec->dev, "Invalid ratio!\n"); + return -EINVAL; + } + + return 0; +} + +static int rt5663_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + switch (level) { + case SND_SOC_BIAS_ON: + snd_soc_update_bits(codec, RT5663_PWR_ANLG_1, + RT5668_PWR_FV1_MASK | RT5668_PWR_FV2_MASK, + RT5668_PWR_FV1 | RT5668_PWR_FV2); + break; + + case SND_SOC_BIAS_PREPARE: + if (rt5663->codec_type == CODEC_TYPE_RT5668) { + snd_soc_update_bits(codec, RT5663_DIG_MISC, + RT5668_DIG_GATE_CTRL_MASK, + RT5668_DIG_GATE_CTRL_EN); + snd_soc_update_bits(codec, RT5663_SIG_CLK_DET, + RT5668_EN_ANA_CLK_DET_MASK | + RT5668_PWR_CLK_DET_MASK, + RT5668_EN_ANA_CLK_DET_AUTO | + RT5668_PWR_CLK_DET_EN); + } + break; + + case SND_SOC_BIAS_STANDBY: + if (rt5663->codec_type == CODEC_TYPE_RT5668) + snd_soc_update_bits(codec, RT5663_DIG_MISC, + RT5668_DIG_GATE_CTRL_MASK, + RT5668_DIG_GATE_CTRL_DIS); + snd_soc_update_bits(codec, RT5663_PWR_ANLG_1, + RT5668_PWR_VREF1_MASK | RT5668_PWR_VREF2_MASK | + RT5668_PWR_FV1_MASK | RT5668_PWR_FV2_MASK | + RT5668_PWR_MB_MASK, RT5668_PWR_VREF1 | + RT5668_PWR_VREF2 | RT5668_PWR_MB); + usleep_range(10000, 10005); + if (rt5663->codec_type == CODEC_TYPE_RT5668) { + snd_soc_update_bits(codec, RT5663_SIG_CLK_DET, + RT5668_EN_ANA_CLK_DET_MASK | + RT5668_PWR_CLK_DET_MASK, + RT5668_EN_ANA_CLK_DET_DIS | + RT5668_PWR_CLK_DET_DIS); + } + break; + + case SND_SOC_BIAS_OFF: + snd_soc_update_bits(codec, RT5663_PWR_ANLG_1, + RT5668_PWR_VREF1_MASK | RT5668_PWR_VREF2_MASK | + RT5668_PWR_FV1 | RT5668_PWR_FV2, 0x0); + break; + + default: + break; + } + + return 0; +} + +static int rt5663_probe(struct snd_soc_codec *codec) +{ + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + rt5663->codec = codec; + + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + snd_soc_dapm_new_controls(dapm, + rt5668_specific_dapm_widgets, + ARRAY_SIZE(rt5668_specific_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, + rt5668_specific_dapm_routes, + ARRAY_SIZE(rt5668_specific_dapm_routes)); + snd_soc_add_codec_controls(codec, rt5668_specific_controls, + ARRAY_SIZE(rt5668_specific_controls)); + break; + case CODEC_TYPE_RT5663: + snd_soc_dapm_new_controls(dapm, + rt5663_specific_dapm_widgets, + ARRAY_SIZE(rt5663_specific_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, + rt5663_specific_dapm_routes, + ARRAY_SIZE(rt5663_specific_dapm_routes)); + snd_soc_add_codec_controls(codec, rt5663_specific_controls, + ARRAY_SIZE(rt5663_specific_controls)); + break; + } + + return 0; +} + +static int rt5663_remove(struct snd_soc_codec *codec) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + regmap_write(rt5663->regmap, RT5663_RESET, 0); + + return 0; +} + +#ifdef CONFIG_PM +static int rt5663_suspend(struct snd_soc_codec *codec) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + regcache_cache_only(rt5663->regmap, true); + regcache_mark_dirty(rt5663->regmap); + + return 0; +} + +static int rt5663_resume(struct snd_soc_codec *codec) +{ + struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec); + + regcache_cache_only(rt5663->regmap, false); + regcache_sync(rt5663->regmap); + + return 0; +} +#else +#define rt5663_suspend NULL +#define rt5663_resume NULL +#endif + +#define RT5663_STEREO_RATES SNDRV_PCM_RATE_8000_192000 +#define RT5663_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) + +struct snd_soc_dai_ops rt5663_aif_dai_ops = { + .hw_params = rt5663_hw_params, + .set_fmt = rt5663_set_dai_fmt, + .set_sysclk = rt5663_set_dai_sysclk, + .set_pll = rt5663_set_dai_pll, + .set_tdm_slot = rt5663_set_tdm_slot, + .set_bclk_ratio = rt5663_set_bclk_ratio, +}; + +struct snd_soc_dai_driver rt5663_dai[] = { + { + .name = "rt5663-aif", + .id = RT5663_AIF, + .playback = { + .stream_name = "AIF Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT5663_STEREO_RATES, + .formats = RT5663_FORMATS, + }, + .capture = { + .stream_name = "AIF Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5663_STEREO_RATES, + .formats = RT5663_FORMATS, + }, + .ops = &rt5663_aif_dai_ops, + }, +}; + +static struct snd_soc_codec_driver soc_codec_dev_rt5663 = { + .probe = rt5663_probe, + .remove = rt5663_remove, + .suspend = rt5663_suspend, + .resume = rt5663_resume, + .set_bias_level = rt5663_set_bias_level, + .idle_bias_off = true, + .component_driver = { + .controls = rt5663_snd_controls, + .num_controls = ARRAY_SIZE(rt5663_snd_controls), + .dapm_widgets = rt5663_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5663_dapm_widgets), + .dapm_routes = rt5663_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5663_dapm_routes), + } +}; + +static const struct regmap_config rt5668_regmap = { + .reg_bits = 16, + .val_bits = 16, + .use_single_rw = true, + .max_register = 0x07fa, + .volatile_reg = rt5668_volatile_register, + .readable_reg = rt5668_readable_register, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt5668_reg, + .num_reg_defaults = ARRAY_SIZE(rt5668_reg), +}; + +static const struct regmap_config rt5663_regmap = { + .reg_bits = 16, + .val_bits = 16, + .use_single_rw = true, + .max_register = 0x03f3, + .volatile_reg = rt5663_volatile_register, + .readable_reg = rt5663_readable_register, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt5663_reg, + .num_reg_defaults = ARRAY_SIZE(rt5663_reg), +}; + +static const struct regmap_config temp_regmap = { + .name = "nocache", + .reg_bits = 16, + .val_bits = 16, + .use_single_rw = true, + .max_register = 0x03f3, + .cache_type = REGCACHE_NONE, +}; + +static const struct i2c_device_id rt5663_i2c_id[] = { + { "rt5668", 0 }, + { "rt5663", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, rt5663_i2c_id); + +#if defined(CONFIG_OF) +static const struct of_device_id rt5663_of_match[] = { + { .compatible = "realtek,rt5668", }, + { .compatible = "realtek,rt5663", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rt5663_of_match); +#endif + +#ifdef CONFIG_ACPI +static struct acpi_device_id rt5663_acpi_match[] = { + { "10EC5668", 0}, + { "10EC5663", 0}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, rt5663_acpi_match); +#endif + +static void rt5668_calibrate(struct rt5663_priv *rt5668) +{ + regmap_write(rt5668->regmap, RT5663_BIAS_CUR_8, 0xa402); + regmap_write(rt5668->regmap, RT5663_PWR_DIG_1, 0x0100); + regmap_write(rt5668->regmap, RT5663_RECMIX, 0x4040); + regmap_write(rt5668->regmap, RT5663_DIG_MISC, 0x0001); + regmap_write(rt5668->regmap, RT5663_RC_CLK, 0x0380); + regmap_write(rt5668->regmap, RT5663_GLB_CLK, 0x8000); + regmap_write(rt5668->regmap, RT5663_ADDA_CLK_1, 0x1000); + regmap_write(rt5668->regmap, RT5663_CHOP_DAC_L, 0x3030); + regmap_write(rt5668->regmap, RT5663_CALIB_ADC, 0x3c05); + regmap_write(rt5668->regmap, RT5663_PWR_ANLG_1, 0xa23e); + msleep(40); + regmap_write(rt5668->regmap, RT5663_PWR_ANLG_1, 0xf23e); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_2, 0x0321); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_1, 0xfc00); + msleep(500); +} + +static void rt5663_calibrate(struct rt5663_priv *rt5668) +{ + int value, count; + + regmap_write(rt5668->regmap, RT5663_RC_CLK, 0x0280); + regmap_write(rt5668->regmap, RT5663_GLB_CLK, 0x8000); + regmap_write(rt5668->regmap, RT5663_DIG_MISC, 0x8001); + regmap_write(rt5668->regmap, RT5663_VREF_RECMIX, 0x0032); + regmap_write(rt5668->regmap, RT5663_PWR_ANLG_1, 0xa2be); + msleep(20); + regmap_write(rt5668->regmap, RT5663_PWR_ANLG_1, 0xf2be); + regmap_write(rt5668->regmap, RT5663_PWR_DIG_2, 0x8400); + regmap_write(rt5668->regmap, RT5663_CHOP_ADC, 0x3000); + regmap_write(rt5668->regmap, RT5663_DEPOP_1, 0x003b); + regmap_write(rt5668->regmap, RT5663_PWR_DIG_1, 0x8df8); + regmap_write(rt5668->regmap, RT5663_PWR_ANLG_2, 0x0003); + regmap_write(rt5668->regmap, RT5663_PWR_ANLG_3, 0x018c); + regmap_write(rt5668->regmap, RT5663_ADDA_CLK_1, 0x1111); + regmap_write(rt5668->regmap, RT5663_PRE_DIV_GATING_1, 0xffff); + regmap_write(rt5668->regmap, RT5663_PRE_DIV_GATING_2, 0xffff); + regmap_write(rt5668->regmap, RT5663_DEPOP_2, 0x3003); + regmap_write(rt5668->regmap, RT5663_DEPOP_1, 0x003b); + regmap_write(rt5668->regmap, RT5663_HP_CHARGE_PUMP_1, 0x1e32); + regmap_write(rt5668->regmap, RT5663_HP_CHARGE_PUMP_2, 0x1371); + regmap_write(rt5668->regmap, RT5663_DACREF_LDO, 0x3b0b); + regmap_write(rt5668->regmap, RT5663_STO_DAC_MIXER, 0x2080); + regmap_write(rt5668->regmap, RT5663_BYPASS_STO_DAC, 0x000c); + regmap_write(rt5668->regmap, RT5663_HP_BIAS, 0xabba); + regmap_write(rt5668->regmap, RT5663_CHARGE_PUMP_1, 0x2224); + regmap_write(rt5668->regmap, RT5663_HP_OUT_EN, 0x8088); + regmap_write(rt5668->regmap, RT5663_STO_DRE_9, 0x0017); + regmap_write(rt5668->regmap, RT5663_STO_DRE_10, 0x0017); + regmap_write(rt5668->regmap, RT5663_STO1_ADC_MIXER, 0x4040); + regmap_write(rt5668->regmap, RT5663_RECMIX, 0x0005); + regmap_write(rt5668->regmap, RT5663_ADDA_RST, 0xc000); + regmap_write(rt5668->regmap, RT5663_STO1_HPF_ADJ1, 0x3320); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_2, 0x00c9); + regmap_write(rt5668->regmap, RT5663_DUMMY_1, 0x004c); + regmap_write(rt5668->regmap, RT5663_ANA_BIAS_CUR_1, 0x7766); + regmap_write(rt5668->regmap, RT5663_BIAS_CUR_8, 0x4702); + msleep(200); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_1, 0x0069); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_3, 0x06c2); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_1_1, 0x7b00); + regmap_write(rt5668->regmap, RT5663_HP_CALIB_1_1, 0xfb00); + count = 0; + while (true) { + regmap_read(rt5668->regmap, RT5663_HP_CALIB_1_1, &value); + if (value & 0x8000) + usleep_range(10000, 10005); + else + break; + + if (count > 200) + return; + count++; + } +} + +static int rt5663_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rt5663_priv *rt5663; + int ret; + unsigned int val; + struct regmap *regmap; + + rt5663 = devm_kzalloc(&i2c->dev, sizeof(struct rt5663_priv), + GFP_KERNEL); + + if (rt5663 == NULL) + return -ENOMEM; + + i2c_set_clientdata(i2c, rt5663); + + regmap = devm_regmap_init_i2c(i2c, &temp_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&i2c->dev, "Failed to allocate temp register map: %d\n", + ret); + return ret; + } + regmap_read(regmap, RT5663_VENDOR_ID_2, &val); + switch (val) { + case RT5668_DEVICE_ID: + rt5663->regmap = devm_regmap_init_i2c(i2c, &rt5668_regmap); + rt5663->codec_type = CODEC_TYPE_RT5668; + break; + case RT5663_DEVICE_ID: + rt5663->regmap = devm_regmap_init_i2c(i2c, &rt5663_regmap); + rt5663->codec_type = CODEC_TYPE_RT5663; + break; + default: + dev_err(&i2c->dev, + "Device with ID register %#x is not rt5663 or rt5668\n", + val); + return -ENODEV; + } + + if (IS_ERR(rt5663->regmap)) { + ret = PTR_ERR(rt5663->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + /* reset and calibrate */ + regmap_write(rt5663->regmap, RT5663_RESET, 0); + regcache_cache_bypass(rt5663->regmap, true); + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + rt5668_calibrate(rt5663); + break; + case CODEC_TYPE_RT5663: + rt5663_calibrate(rt5663); + break; + default: + dev_err(&i2c->dev, "%s:Unknown codec type\n", __func__); + } + regcache_cache_bypass(rt5663->regmap, false); + regmap_write(rt5663->regmap, RT5663_RESET, 0); + dev_dbg(&i2c->dev, "calibrate done\n"); + + /* GPIO1 as IRQ */ + regmap_update_bits(rt5663->regmap, RT5663_GPIO_1, RT5668_GP1_PIN_MASK, + RT5668_GP1_PIN_IRQ); + /* 4btn inline command debounce */ + regmap_update_bits(rt5663->regmap, RT5663_IL_CMD_5, + RT5668_4BTN_CLK_DEB_MASK, RT5668_4BTN_CLK_DEB_65MS); + + switch (rt5663->codec_type) { + case CODEC_TYPE_RT5668: + regmap_write(rt5663->regmap, RT5663_BIAS_CUR_8, 0xa402); + /* JD1 */ + regmap_update_bits(rt5663->regmap, RT5663_AUTO_1MRC_CLK, + RT5668_IRQ_POW_SAV_MASK | RT5668_IRQ_POW_SAV_JD1_MASK, + RT5668_IRQ_POW_SAV_EN | RT5668_IRQ_POW_SAV_JD1_EN); + regmap_update_bits(rt5663->regmap, RT5663_PWR_ANLG_2, + RT5668_PWR_JD1_MASK, RT5668_PWR_JD1); + regmap_update_bits(rt5663->regmap, RT5663_IRQ_1, + RT5668_EN_CB_JD_MASK, RT5668_EN_CB_JD_EN); + + regmap_update_bits(rt5663->regmap, RT5663_HP_LOGIC_2, + RT5668_HP_SIG_SRC1_MASK, RT5668_HP_SIG_SRC1_REG); + regmap_update_bits(rt5663->regmap, RT5663_RECMIX, + RT5668_VREF_BIAS_MASK | RT5668_CBJ_DET_MASK | + RT5668_DET_TYPE_MASK, RT5668_VREF_BIAS_REG | + RT5668_CBJ_DET_EN | RT5668_DET_TYPE_QFN); + /* Set GPIO4 and GPIO8 as input for combo jack */ + regmap_update_bits(rt5663->regmap, RT5663_GPIO_2, + RT5668_GP4_PIN_CONF_MASK, RT5668_GP4_PIN_CONF_INPUT); + regmap_update_bits(rt5663->regmap, RT5668_GPIO_3, + RT5668_GP8_PIN_CONF_MASK, RT5668_GP8_PIN_CONF_INPUT); + regmap_update_bits(rt5663->regmap, RT5663_PWR_ANLG_1, + RT5668_LDO1_DVO_MASK | RT5668_AMP_HP_MASK, + RT5668_LDO1_DVO_0_9V | RT5668_AMP_HP_3X); + break; + case CODEC_TYPE_RT5663: + regmap_write(rt5663->regmap, RT5663_VREF_RECMIX, 0x0032); + regmap_write(rt5663->regmap, RT5663_PWR_ANLG_1, 0xa2be); + msleep(20); + regmap_write(rt5663->regmap, RT5663_PWR_ANLG_1, 0xf2be); + regmap_update_bits(rt5663->regmap, RT5663_GPIO_2, + RT5663_GP1_PIN_CONF_MASK, RT5663_GP1_PIN_CONF_OUTPUT); + /* DACREF LDO control */ + regmap_update_bits(rt5663->regmap, RT5663_DACREF_LDO, 0x3e0e, + 0x3a0a); + regmap_update_bits(rt5663->regmap, RT5663_RECMIX, + RT5663_RECMIX1_BST1_MASK, RT5663_RECMIX1_BST1_ON); + regmap_update_bits(rt5663->regmap, RT5663_TDM_2, + RT5663_DATA_SWAP_ADCDAT1_MASK, + RT5663_DATA_SWAP_ADCDAT1_LL); + break; + default: + dev_err(&i2c->dev, "%s:Unknown codec type\n", __func__); + } + + INIT_DELAYED_WORK(&rt5663->jack_detect_work, rt5663_jack_detect_work); + + if (i2c->irq) { + ret = request_irq(i2c->irq, rt5663_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING + | IRQF_ONESHOT, "rt5663", rt5663); + if (ret) + dev_err(&i2c->dev, "%s Failed to reguest IRQ: %d\n", + __func__, ret); + } + + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5663, + rt5663_dai, ARRAY_SIZE(rt5663_dai)); + + if (ret) { + if (i2c->irq) + free_irq(i2c->irq, rt5663); + } + + return ret; +} + +static int rt5663_i2c_remove(struct i2c_client *i2c) +{ + struct rt5663_priv *rt5663 = i2c_get_clientdata(i2c); + + if (i2c->irq) + free_irq(i2c->irq, rt5663); + + snd_soc_unregister_codec(&i2c->dev); + + return 0; +} + +void rt5663_i2c_shutdown(struct i2c_client *client) +{ + struct rt5663_priv *rt5663 = i2c_get_clientdata(client); + + regmap_write(rt5663->regmap, RT5663_RESET, 0); +} + +struct i2c_driver rt5663_i2c_driver = { + .driver = { + .name = "rt5663", + .owner = THIS_MODULE, + .acpi_match_table = ACPI_PTR(rt5663_acpi_match), + .of_match_table = of_match_ptr(rt5663_of_match), + }, + .probe = rt5663_i2c_probe, + .remove = rt5663_i2c_remove, + .shutdown = rt5663_i2c_shutdown, + .id_table = rt5663_i2c_id, +}; +module_i2c_driver(rt5663_i2c_driver); + +MODULE_DESCRIPTION("ASoC RT5663 driver"); +MODULE_AUTHOR("Jack Yu "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt5663.h b/sound/soc/codecs/rt5663.h new file mode 100644 index 0000000..2cc8f28 --- /dev/null +++ b/sound/soc/codecs/rt5663.h @@ -0,0 +1,1121 @@ +/* + * rt5663.h -- RT5663 ALSA SoC audio driver + * + * Copyright 2016 Realtek Microelectronics + * Author: Jack Yu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __RT5663_H__ +#define __RT5663_H__ + +/* Info */ +#define RT5663_RESET 0x0000 +#define RT5663_VENDOR_ID 0x00fd +#define RT5663_VENDOR_ID_1 0x00fe +#define RT5663_VENDOR_ID_2 0x00ff + +#define RT5668_LOUT_CTRL 0x0001 +#define RT5668_HP_AMP_2 0x0003 +#define RT5668_MONO_OUT 0x0004 +#define RT5668_MONO_GAIN 0x0007 + +#define RT5668_AEC_BST 0x000b +#define RT5668_IN1_IN2 0x000c +#define RT5668_IN3_IN4 0x000d +#define RT5668_INL1_INR1 0x000f +#define RT5668_CBJ_TYPE_2 0x0011 +#define RT5668_CBJ_TYPE_3 0x0012 +#define RT5668_CBJ_TYPE_4 0x0013 +#define RT5668_CBJ_TYPE_5 0x0014 +#define RT5668_CBJ_TYPE_8 0x0017 + +/* I/O - ADC/DAC/DMIC */ +#define RT5668_DAC3_DIG_VOL 0x001a +#define RT5668_DAC3_CTRL 0x001b +#define RT5668_MONO_ADC_DIG_VOL 0x001d +#define RT5668_STO2_ADC_DIG_VOL 0x001e +#define RT5668_MONO_ADC_BST_GAIN 0x0020 +#define RT5668_STO2_ADC_BST_GAIN 0x0021 +#define RT5668_SIDETONE_CTRL 0x0024 +/* Mixer - D-D */ +#define RT5668_MONO1_ADC_MIXER 0x0027 +#define RT5668_STO2_ADC_MIXER 0x0028 +#define RT5668_MONO_DAC_MIXER 0x002b +#define RT5668_DAC2_SRC_CTRL 0x002e +#define RT5668_IF_3_4_DATA_CTL 0x002f +#define RT5668_IF_5_DATA_CTL 0x0030 +#define RT5668_PDM_OUT_CTL 0x0031 +#define RT5668_PDM_I2C_DATA_CTL1 0x0032 +#define RT5668_PDM_I2C_DATA_CTL2 0x0033 +#define RT5668_PDM_I2C_DATA_CTL3 0x0034 +#define RT5668_PDM_I2C_DATA_CTL4 0x0035 + +/*Mixer - Analog*/ +#define RT5668_RECMIX1_NEW 0x003a +#define RT5668_RECMIX1L_0 0x003b +#define RT5668_RECMIX1L 0x003c +#define RT5668_RECMIX1R_0 0x003d +#define RT5668_RECMIX1R 0x003e +#define RT5668_RECMIX2_NEW 0x003f +#define RT5668_RECMIX2_L_2 0x0041 +#define RT5668_RECMIX2_R 0x0042 +#define RT5668_RECMIX2_R_2 0x0043 +#define RT5668_CALIB_REC_LR 0x0044 +#define RT5668_ALC_BK_GAIN 0x0049 +#define RT5668_MONOMIX_GAIN 0x004a +#define RT5668_MONOMIX_IN_GAIN 0x004b +#define RT5668_OUT_MIXL_GAIN 0x004d +#define RT5668_OUT_LMIX_IN_GAIN 0x004e +#define RT5668_OUT_RMIX_IN_GAIN 0x004f +#define RT5668_OUT_RMIX_IN_GAIN1 0x0050 +#define RT5668_LOUT_MIXER_CTRL 0x0052 +/* Power */ +#define RT5668_PWR_VOL 0x0067 + +#define RT5668_ADCDAC_RST 0x006d +/* Format - ADC/DAC */ +#define RT5668_I2S34_SDP 0x0071 +#define RT5668_I2S5_SDP 0x0072 +/* Format - TDM Control */ +#define RT5668_TDM_5 0x007c +#define RT5668_TDM_6 0x007d +#define RT5668_TDM_7 0x007e +#define RT5668_TDM_8 0x007f + +/* Function - Analog */ +#define RT5668_ASRC_3 0x0085 +#define RT5668_ASRC_6 0x0088 +#define RT5668_ASRC_7 0x0089 +#define RT5668_PLL_TRK_13 0x0099 +#define RT5668_I2S_M_CLK_CTL 0x00a0 +#define RT5668_FDIV_I2S34_M_CLK 0x00a1 +#define RT5668_FDIV_I2S34_M_CLK2 0x00a2 +#define RT5668_FDIV_I2S5_M_CLK 0x00a3 +#define RT5668_FDIV_I2S5_M_CLK2 0x00a4 + +/* Function - Digital */ +#define RT5668_IRQ_4 0x00b9 +#define RT5668_GPIO_3 0x00c2 +#define RT5668_GPIO_4 0x00c3 +#define RT5668_GPIO_STA 0x00c4 +#define RT5668_HP_AMP_DET1 0x00d0 +#define RT5668_HP_AMP_DET2 0x00d1 +#define RT5668_HP_AMP_DET3 0x00d2 +#define RT5668_MID_BD_HP_AMP 0x00d3 +#define RT5668_LOW_BD_HP_AMP 0x00d4 +#define RT5668_SOF_VOL_ZC2 0x00da +#define RT5668_ADC_STO2_ADJ1 0x00ee +#define RT5668_ADC_STO2_ADJ2 0x00ef +/* General Control */ +#define RT5668_A_JD_CTRL 0x00f0 +#define RT5668_JD1_TRES_CTRL 0x00f1 +#define RT5668_JD2_TRES_CTRL 0x00f2 +#define RT5668_JD_CTRL2 0x00f7 +#define RT5668_DUM_REG_2 0x00fb +#define RT5668_DUM_REG_3 0x00fc + + +#define RT5668_DACADC_DIG_VOL2 0x0101 +#define RT5668_DIG_IN_PIN2 0x0133 +#define RT5668_PAD_DRV_CTL1 0x0136 +#define RT5668_SOF_RAM_DEPOP 0x0138 +#define RT5668_VOL_TEST 0x013f +#define RT5668_TEST_MODE_3 0x0147 +#define RT5668_TEST_MODE_4 0x0148 +#define RT5668_MONO_DYNA_1 0x0170 +#define RT5668_MONO_DYNA_2 0x0171 +#define RT5668_MONO_DYNA_3 0x0172 +#define RT5668_MONO_DYNA_4 0x0173 +#define RT5668_MONO_DYNA_5 0x0174 +#define RT5668_MONO_DYNA_6 0x0175 +#define RT5668_STO1_SIL_DET 0x0190 +#define RT5668_MONOL_SIL_DET 0x0191 +#define RT5668_MONOR_SIL_DET 0x0192 +#define RT5668_STO2_DAC_SIL 0x0193 +#define RT5668_PWR_SAV_CTL1 0x0194 +#define RT5668_PWR_SAV_CTL2 0x0195 +#define RT5668_PWR_SAV_CTL3 0x0196 +#define RT5668_PWR_SAV_CTL4 0x0197 +#define RT5668_PWR_SAV_CTL5 0x0198 +#define RT5668_PWR_SAV_CTL6 0x0199 +#define RT5668_MONO_AMP_CAL1 0x01a0 +#define RT5668_MONO_AMP_CAL2 0x01a1 +#define RT5668_MONO_AMP_CAL3 0x01a2 +#define RT5668_MONO_AMP_CAL4 0x01a3 +#define RT5668_MONO_AMP_CAL5 0x01a4 +#define RT5668_MONO_AMP_CAL6 0x01a5 +#define RT5668_MONO_AMP_CAL7 0x01a6 +#define RT5668_MONO_AMP_CAL_ST1 0x01a7 +#define RT5668_MONO_AMP_CAL_ST2 0x01a8 +#define RT5668_MONO_AMP_CAL_ST3 0x01a9 +#define RT5668_MONO_AMP_CAL_ST4 0x01aa +#define RT5668_MONO_AMP_CAL_ST5 0x01ab +#define RT5668_HP_IMP_SEN_13 0x01b9 +#define RT5668_HP_IMP_SEN_14 0x01ba +#define RT5668_HP_IMP_SEN_6 0x01bb +#define RT5668_HP_IMP_SEN_7 0x01bc +#define RT5668_HP_IMP_SEN_8 0x01bd +#define RT5668_HP_IMP_SEN_9 0x01be +#define RT5668_HP_IMP_SEN_10 0x01bf +#define RT5668_HP_LOGIC_3 0x01dc +#define RT5668_HP_CALIB_ST10 0x01f3 +#define RT5668_HP_CALIB_ST11 0x01f4 +#define RT5668_PRO_REG_TBL_4 0x0203 +#define RT5668_PRO_REG_TBL_5 0x0204 +#define RT5668_PRO_REG_TBL_6 0x0205 +#define RT5668_PRO_REG_TBL_7 0x0206 +#define RT5668_PRO_REG_TBL_8 0x0207 +#define RT5668_PRO_REG_TBL_9 0x0208 +#define RT5668_SAR_ADC_INL_1 0x0210 +#define RT5668_SAR_ADC_INL_2 0x0211 +#define RT5668_SAR_ADC_INL_3 0x0212 +#define RT5668_SAR_ADC_INL_4 0x0213 +#define RT5668_SAR_ADC_INL_5 0x0214 +#define RT5668_SAR_ADC_INL_6 0x0215 +#define RT5668_SAR_ADC_INL_7 0x0216 +#define RT5668_SAR_ADC_INL_8 0x0217 +#define RT5668_SAR_ADC_INL_9 0x0218 +#define RT5668_SAR_ADC_INL_10 0x0219 +#define RT5668_SAR_ADC_INL_11 0x021a +#define RT5668_SAR_ADC_INL_12 0x021b +#define RT5668_DRC_CTRL_1 0x02ff +#define RT5668_DRC1_CTRL_2 0x0301 +#define RT5668_DRC1_CTRL_3 0x0302 +#define RT5668_DRC1_CTRL_4 0x0303 +#define RT5668_DRC1_CTRL_5 0x0304 +#define RT5668_DRC1_CTRL_6 0x0305 +#define RT5668_DRC1_HD_CTRL_1 0x0306 +#define RT5668_DRC1_HD_CTRL_2 0x0307 +#define RT5668_DRC1_PRI_REG_1 0x0310 +#define RT5668_DRC1_PRI_REG_2 0x0311 +#define RT5668_DRC1_PRI_REG_3 0x0312 +#define RT5668_DRC1_PRI_REG_4 0x0313 +#define RT5668_DRC1_PRI_REG_5 0x0314 +#define RT5668_DRC1_PRI_REG_6 0x0315 +#define RT5668_DRC1_PRI_REG_7 0x0316 +#define RT5668_DRC1_PRI_REG_8 0x0317 +#define RT5668_ALC_PGA_CTL_1 0x0330 +#define RT5668_ALC_PGA_CTL_2 0x0331 +#define RT5668_ALC_PGA_CTL_3 0x0332 +#define RT5668_ALC_PGA_CTL_4 0x0333 +#define RT5668_ALC_PGA_CTL_5 0x0334 +#define RT5668_ALC_PGA_CTL_6 0x0335 +#define RT5668_ALC_PGA_CTL_7 0x0336 +#define RT5668_ALC_PGA_CTL_8 0x0337 +#define RT5668_ALC_PGA_REG_1 0x0338 +#define RT5668_ALC_PGA_REG_2 0x0339 +#define RT5668_ALC_PGA_REG_3 0x033a +#define RT5668_ADC_EQ_RECOV_1 0x03c0 +#define RT5668_ADC_EQ_RECOV_2 0x03c1 +#define RT5668_ADC_EQ_RECOV_3 0x03c2 +#define RT5668_ADC_EQ_RECOV_4 0x03c3 +#define RT5668_ADC_EQ_RECOV_5 0x03c4 +#define RT5668_ADC_EQ_RECOV_6 0x03c5 +#define RT5668_ADC_EQ_RECOV_7 0x03c6 +#define RT5668_ADC_EQ_RECOV_8 0x03c7 +#define RT5668_ADC_EQ_RECOV_9 0x03c8 +#define RT5668_ADC_EQ_RECOV_10 0x03c9 +#define RT5668_ADC_EQ_RECOV_11 0x03ca +#define RT5668_ADC_EQ_RECOV_12 0x03cb +#define RT5668_ADC_EQ_RECOV_13 0x03cc +#define RT5668_VID_HIDDEN 0x03fe +#define RT5668_VID_CUSTOMER 0x03ff +#define RT5668_SCAN_MODE 0x07f0 +#define RT5668_I2C_BYPA 0x07fa + +/* Headphone Amp Control 2 (0x0003) */ +#define RT5668_EN_DAC_HPO_MASK (0x1 << 14) +#define RT5668_EN_DAC_HPO_SHIFT 14 +#define RT5668_EN_DAC_HPO_DIS (0x0 << 14) +#define RT5668_EN_DAC_HPO_EN (0x1 << 14) + +/*Headphone Amp L/R Analog Gain and Digital NG2 Gain Control (0x0005 0x0006)*/ +#define RT5668_GAIN_HP (0x1f << 8) +#define RT5668_GAIN_HP_SHIFT 8 + +/* AEC BST Control (0x000b) */ +#define RT5668_GAIN_CBJ_MASK (0xf << 8) +#define RT5668_GAIN_CBJ_SHIFT 8 + +/* IN1 Control / MIC GND REF (0x000c) */ +#define RT5668_IN1_DF_MASK (0x1 << 15) +#define RT5668_IN1_DF_SHIFT 15 + +/* Combo Jack and Type Detection Control 1 (0x0010) */ +#define RT5668_CBJ_DET_MASK (0x1 << 15) +#define RT5668_CBJ_DET_SHIFT 15 +#define RT5668_CBJ_DET_DIS (0x0 << 15) +#define RT5668_CBJ_DET_EN (0x1 << 15) +#define RT5668_DET_TYPE_MASK (0x1 << 12) +#define RT5668_DET_TYPE_SHIFT 12 +#define RT5668_DET_TYPE_WLCSP (0x0 << 12) +#define RT5668_DET_TYPE_QFN (0x1 << 12) +#define RT5668_VREF_BIAS_MASK (0x1 << 6) +#define RT5668_VREF_BIAS_SHIFT 6 +#define RT5668_VREF_BIAS_FSM (0x0 << 6) +#define RT5668_VREF_BIAS_REG (0x1 << 6) + +/* REC Left Mixer Control 2 (0x003c) */ +#define RT5668_RECMIX1L_BST1_CBJ (0x1 << 7) +#define RT5668_RECMIX1L_BST1_CBJ_SHIFT 7 +#define RT5668_RECMIX1L_BST2 (0x1 << 4) +#define RT5668_RECMIX1L_BST2_SHIFT 4 + +/* REC Right Mixer Control 2 (0x003e) */ +#define RT5668_RECMIX1R_BST2 (0x1 << 4) +#define RT5668_RECMIX1R_BST2_SHIFT 4 + +/* DAC1 Digital Volume (0x0019) */ +#define RT5668_DAC_L1_VOL_MASK (0xff << 8) +#define RT5668_DAC_L1_VOL_SHIFT 8 +#define RT5668_DAC_R1_VOL_MASK (0xff) +#define RT5668_DAC_R1_VOL_SHIFT 0 + +/* ADC Digital Volume Control (0x001c) */ +#define RT5668_ADC_L_MUTE_MASK (0x1 << 15) +#define RT5668_ADC_L_MUTE_SHIFT 15 +#define RT5668_ADC_L_VOL_MASK (0x7f << 8) +#define RT5668_ADC_L_VOL_SHIFT 8 +#define RT5668_ADC_R_MUTE_MASK (0x1 << 7) +#define RT5668_ADC_R_MUTE_SHIFT 7 +#define RT5668_ADC_R_VOL_MASK (0x7f) +#define RT5668_ADC_R_VOL_SHIFT 0 + +/* Stereo ADC Mixer Control (0x0026) */ +#define RT5668_M_STO1_ADC_L1 (0x1 << 15) +#define RT5668_M_STO1_ADC_L1_SHIFT 15 +#define RT5668_M_STO1_ADC_L2 (0x1 << 14) +#define RT5668_M_STO1_ADC_L2_SHIFT 14 +#define RT5668_STO1_ADC_L1_SRC (0x1 << 13) +#define RT5668_STO1_ADC_L1_SRC_SHIFT 13 +#define RT5668_STO1_ADC_L2_SRC (0x1 << 12) +#define RT5668_STO1_ADC_L2_SRC_SHIFT 12 +#define RT5668_STO1_ADC_L_SRC (0x3 << 10) +#define RT5668_STO1_ADC_L_SRC_SHIFT 10 +#define RT5668_M_STO1_ADC_R1 (0x1 << 7) +#define RT5668_M_STO1_ADC_R1_SHIFT 7 +#define RT5668_M_STO1_ADC_R2 (0x1 << 6) +#define RT5668_M_STO1_ADC_R2_SHIFT 6 +#define RT5668_STO1_ADC_R1_SRC (0x1 << 5) +#define RT5668_STO1_ADC_R1_SRC_SHIFT 5 +#define RT5668_STO1_ADC_R2_SRC (0x1 << 4) +#define RT5668_STO1_ADC_R2_SRC_SHIFT 4 +#define RT5668_STO1_ADC_R_SRC (0x3 << 2) +#define RT5668_STO1_ADC_R_SRC_SHIFT 2 + +/* ADC Mixer to DAC Mixer Control (0x0029) */ +#define RT5668_M_ADCMIX_L (0x1 << 15) +#define RT5668_M_ADCMIX_L_SHIFT 15 +#define RT5668_M_DAC1_L (0x1 << 14) +#define RT5668_M_DAC1_L_SHIFT 14 +#define RT5668_M_ADCMIX_R (0x1 << 7) +#define RT5668_M_ADCMIX_R_SHIFT 7 +#define RT5668_M_DAC1_R (0x1 << 6) +#define RT5668_M_DAC1_R_SHIFT 6 + +/* Stereo DAC Mixer Control (0x002a) */ +#define RT5668_M_DAC_L1_STO_L (0x1 << 15) +#define RT5668_M_DAC_L1_STO_L_SHIFT 15 +#define RT5668_M_DAC_R1_STO_L (0x1 << 13) +#define RT5668_M_DAC_R1_STO_L_SHIFT 13 +#define RT5668_M_DAC_L1_STO_R (0x1 << 7) +#define RT5668_M_DAC_L1_STO_R_SHIFT 7 +#define RT5668_M_DAC_R1_STO_R (0x1 << 5) +#define RT5668_M_DAC_R1_STO_R_SHIFT 5 + +/* Power Management for Digital 1 (0x0061) */ +#define RT5668_PWR_I2S1 (0x1 << 15) +#define RT5668_PWR_I2S1_SHIFT 15 +#define RT5668_PWR_DAC_L1 (0x1 << 11) +#define RT5668_PWR_DAC_L1_SHIFT 11 +#define RT5668_PWR_DAC_R1 (0x1 << 10) +#define RT5668_PWR_DAC_R1_SHIFT 10 +#define RT5668_PWR_LDO_DACREF_MASK (0x1 << 8) +#define RT5668_PWR_LDO_DACREF_SHIFT 8 +#define RT5668_PWR_LDO_DACREF_ON (0x1 << 8) +#define RT5668_PWR_LDO_DACREF_DOWN (0x0 << 8) +#define RT5668_PWR_LDO_SHIFT 8 +#define RT5668_PWR_ADC_L1 (0x1 << 4) +#define RT5668_PWR_ADC_L1_SHIFT 4 +#define RT5668_PWR_ADC_R1 (0x1 << 3) +#define RT5668_PWR_ADC_R1_SHIFT 3 + +/* Power Management for Digital 2 (0x0062) */ +#define RT5668_PWR_ADC_S1F (0x1 << 15) +#define RT5668_PWR_ADC_S1F_SHIFT 15 +#define RT5668_PWR_DAC_S1F (0x1 << 10) +#define RT5668_PWR_DAC_S1F_SHIFT 10 + +/* Power Management for Analog 1 (0x0063) */ +#define RT5668_PWR_VREF1 (0x1 << 15) +#define RT5668_PWR_VREF1_MASK (0x1 << 15) +#define RT5668_PWR_VREF1_SHIFT 15 +#define RT5668_PWR_FV1 (0x1 << 14) +#define RT5668_PWR_FV1_MASK (0x1 << 14) +#define RT5668_PWR_FV1_SHIFT 14 +#define RT5668_PWR_VREF2 (0x1 << 13) +#define RT5668_PWR_VREF2_MASK (0x1 << 13) +#define RT5668_PWR_VREF2_SHIFT 13 +#define RT5668_PWR_FV2 (0x1 << 12) +#define RT5668_PWR_FV2_MASK (0x1 << 12) +#define RT5668_PWR_FV2_SHIFT 12 +#define RT5668_PWR_MB (0x1 << 9) +#define RT5668_PWR_MB_MASK (0x1 << 9) +#define RT5668_PWR_MB_SHIFT 9 +#define RT5668_AMP_HP_MASK (0x3 << 2) +#define RT5668_AMP_HP_SHIFT 2 +#define RT5668_AMP_HP_1X (0x0 << 2) +#define RT5668_AMP_HP_3X (0x1 << 2) +#define RT5668_AMP_HP_5X (0x3 << 2) +#define RT5668_LDO1_DVO_MASK (0x3) +#define RT5668_LDO1_DVO_SHIFT 0 +#define RT5668_LDO1_DVO_0_9V (0x0) +#define RT5668_LDO1_DVO_1_0V (0x1) +#define RT5668_LDO1_DVO_1_2V (0x2) +#define RT5668_LDO1_DVO_1_4V (0x3) + +/* Power Management for Analog 2 (0x0064) */ +#define RT5668_PWR_BST1 (0x1 << 15) +#define RT5668_PWR_BST1_MASK (0x1 << 15) +#define RT5668_PWR_BST1_SHIFT 15 +#define RT5668_PWR_BST1_OFF (0x0 << 15) +#define RT5668_PWR_BST1_ON (0x1 << 15) +#define RT5668_PWR_BST2 (0x1 << 14) +#define RT5668_PWR_BST2_MASK (0x1 << 14) +#define RT5668_PWR_BST2_SHIFT 14 +#define RT5668_PWR_MB1 (0x1 << 11) +#define RT5668_PWR_MB1_SHIFT 11 +#define RT5668_PWR_MB2 (0x1 << 10) +#define RT5668_PWR_MB2_SHIFT 10 +#define RT5668_PWR_BST2_OP (0x1 << 6) +#define RT5668_PWR_BST2_OP_MASK (0x1 << 6) +#define RT5668_PWR_BST2_OP_SHIFT 6 +#define RT5668_PWR_JD1 (0x1 << 3) +#define RT5668_PWR_JD1_MASK (0x1 << 3) +#define RT5668_PWR_JD1_SHIFT 3 +#define RT5668_PWR_JD2 (0x1 << 2) +#define RT5668_PWR_JD2_MASK (0x1 << 2) +#define RT5668_PWR_JD2_SHIFT 2 +#define RT5668_PWR_RECMIX1 (0x1 << 1) +#define RT5668_PWR_RECMIX1_SHIFT 1 +#define RT5668_PWR_RECMIX2 (0x1) +#define RT5668_PWR_RECMIX2_SHIFT 0 + +/* Power Management for Analog 3 (0x0065) */ +#define RT5668_PWR_CBJ_MASK (0x1 << 9) +#define RT5668_PWR_CBJ_SHIFT 9 +#define RT5668_PWR_CBJ_OFF (0x0 << 9) +#define RT5668_PWR_CBJ_ON (0x1 << 9) +#define RT5668_PWR_PLL (0x1 << 6) +#define RT5668_PWR_PLL_SHIFT 6 +#define RT5668_PWR_LDO2 (0x1 << 2) +#define RT5668_PWR_LDO2_SHIFT 2 + +/* Power Management for Volume (0x0067) */ +#define RT5668_PWR_MIC_DET (0x1 << 5) +#define RT5668_PWR_MIC_DET_SHIFT 5 + +/* MCLK and System Clock Detection Control (0x006b) */ +#define RT5668_EN_ANA_CLK_DET_MASK (0x1 << 15) +#define RT5668_EN_ANA_CLK_DET_SHIFT 15 +#define RT5668_EN_ANA_CLK_DET_DIS (0x0 << 15) +#define RT5668_EN_ANA_CLK_DET_AUTO (0x1 << 15) +#define RT5668_PWR_CLK_DET_MASK (0x1) +#define RT5668_PWR_CLK_DET_SHIFT 0 +#define RT5668_PWR_CLK_DET_DIS (0x0) +#define RT5668_PWR_CLK_DET_EN (0x1) + +/* I2S1 Audio Serial Data Port Control (0x0070) */ +#define RT5668_I2S_MS_MASK (0x1 << 15) +#define RT5668_I2S_MS_SHIFT 15 +#define RT5668_I2S_MS_M (0x0 << 15) +#define RT5668_I2S_MS_S (0x1 << 15) +#define RT5668_I2S_BP_MASK (0x1 << 8) +#define RT5668_I2S_BP_SHIFT 8 +#define RT5668_I2S_BP_NOR (0x0 << 8) +#define RT5668_I2S_BP_INV (0x1 << 8) +#define RT5668_I2S_DL_MASK (0x3 << 4) +#define RT5668_I2S_DL_SHIFT 4 +#define RT5668_I2S_DL_16 (0x0 << 4) +#define RT5668_I2S_DL_20 (0x1 << 4) +#define RT5668_I2S_DL_24 (0x2 << 4) +#define RT5668_I2S_DL_8 (0x3 << 4) +#define RT5668_I2S_DF_MASK (0x7) +#define RT5668_I2S_DF_SHIFT 0 +#define RT5668_I2S_DF_I2S (0x0) +#define RT5668_I2S_DF_LEFT (0x1) +#define RT5668_I2S_DF_PCM_A (0x2) +#define RT5668_I2S_DF_PCM_B (0x3) +#define RT5668_I2S_DF_PCM_A_N (0x6) +#define RT5668_I2S_DF_PCM_B_N (0x7) + +/* ADC/DAC Clock Control 1 (0x0073) */ +#define RT5668_I2S_PD1_MASK (0x7 << 12) +#define RT5668_I2S_PD1_SHIFT 12 +#define RT5668_M_I2S_DIV_MASK (0x7 << 8) +#define RT5668_M_I2S_DIV_SHIFT 8 +#define RT5668_CLK_SRC_MASK (0x3 << 4) +#define RT5668_CLK_SRC_MCLK (0x0 << 4) +#define RT5668_CLK_SRC_PLL_OUT (0x1 << 4) +#define RT5668_CLK_SRC_DIV (0x2 << 4) +#define RT5668_CLK_SRC_RC (0x3 << 4) +#define RT5668_DAC_OSR_MASK (0x3 << 2) +#define RT5668_DAC_OSR_SHIFT 2 +#define RT5668_DAC_OSR_128 (0x0 << 2) +#define RT5668_DAC_OSR_64 (0x1 << 2) +#define RT5668_DAC_OSR_32 (0x2 << 2) +#define RT5668_ADC_OSR_MASK (0x3) +#define RT5668_ADC_OSR_SHIFT 0 +#define RT5668_ADC_OSR_128 (0x0) +#define RT5668_ADC_OSR_64 (0x1) +#define RT5668_ADC_OSR_32 (0x2) + +/* TDM1 control 1 (0x0078) */ +#define RT5668_TDM_MODE_MASK (0x1 << 15) +#define RT5668_TDM_MODE_SHIFT 15 +#define RT5668_TDM_MODE_I2S (0x0 << 15) +#define RT5668_TDM_MODE_TDM (0x1 << 15) +#define RT5668_TDM_IN_CH_MASK (0x3 << 10) +#define RT5668_TDM_IN_CH_SHIFT 10 +#define RT5668_TDM_IN_CH_2 (0x0 << 10) +#define RT5668_TDM_IN_CH_4 (0x1 << 10) +#define RT5668_TDM_IN_CH_6 (0x2 << 10) +#define RT5668_TDM_IN_CH_8 (0x3 << 10) +#define RT5668_TDM_OUT_CH_MASK (0x3 << 8) +#define RT5668_TDM_OUT_CH_SHIFT 8 +#define RT5668_TDM_OUT_CH_2 (0x0 << 8) +#define RT5668_TDM_OUT_CH_4 (0x1 << 8) +#define RT5668_TDM_OUT_CH_6 (0x2 << 8) +#define RT5668_TDM_OUT_CH_8 (0x3 << 8) +#define RT5668_TDM_IN_LEN_MASK (0x3 << 6) +#define RT5668_TDM_IN_LEN_SHIFT 6 +#define RT5668_TDM_IN_LEN_16 (0x0 << 6) +#define RT5668_TDM_IN_LEN_20 (0x1 << 6) +#define RT5668_TDM_IN_LEN_24 (0x2 << 6) +#define RT5668_TDM_IN_LEN_32 (0x3 << 6) +#define RT5668_TDM_OUT_LEN_MASK (0x3 << 4) +#define RT5668_TDM_OUT_LEN_SHIFT 4 +#define RT5668_TDM_OUT_LEN_16 (0x0 << 4) +#define RT5668_TDM_OUT_LEN_20 (0x1 << 4) +#define RT5668_TDM_OUT_LEN_24 (0x2 << 4) +#define RT5668_TDM_OUT_LEN_32 (0x3 << 4) + +/* Global Clock Control (0x0080) */ +#define RT5668_SCLK_SRC_MASK (0x3 << 14) +#define RT5668_SCLK_SRC_SHIFT 14 +#define RT5668_SCLK_SRC_MCLK (0x0 << 14) +#define RT5668_SCLK_SRC_PLL1 (0x1 << 14) +#define RT5668_SCLK_SRC_RCCLK (0x2 << 14) +#define RT5668_PLL1_SRC_MASK (0x7 << 8) +#define RT5668_PLL1_SRC_SHIFT 8 +#define RT5668_PLL1_SRC_MCLK (0x0 << 8) +#define RT5668_PLL1_SRC_BCLK1 (0x1 << 8) +#define RT5668_PLL1_PD_MASK (0x1 << 4) +#define RT5668_PLL1_PD_SHIFT 4 + +#define RT5668_PLL_INP_MAX 40000000 +#define RT5668_PLL_INP_MIN 256000 +/* PLL M/N/K Code Control 1 (0x0081) */ +#define RT5668_PLL_N_MAX 0x001ff +#define RT5668_PLL_N_MASK (RT5668_PLL_N_MAX << 7) +#define RT5668_PLL_N_SHIFT 7 +#define RT5668_PLL_K_MAX 0x001f +#define RT5668_PLL_K_MASK (RT5668_PLL_K_MAX) +#define RT5668_PLL_K_SHIFT 0 + +/* PLL M/N/K Code Control 2 (0x0082) */ +#define RT5668_PLL_M_MAX 0x00f +#define RT5668_PLL_M_MASK (RT5668_PLL_M_MAX << 12) +#define RT5668_PLL_M_SHIFT 12 +#define RT5668_PLL_M_BP (0x1 << 11) +#define RT5668_PLL_M_BP_SHIFT 11 + +/* PLL tracking mode 1 (0x0083) */ +#define RT5668_I2S1_ASRC_MASK (0x1 << 13) +#define RT5668_I2S1_ASRC_SHIFT 13 +#define RT5668_DAC_STO1_ASRC_MASK (0x1 << 12) +#define RT5668_DAC_STO1_ASRC_SHIFT 12 +#define RT5668_ADC_STO1_ASRC_MASK (0x1 << 4) +#define RT5668_ADC_STO1_ASRC_SHIFT 4 + +/* PLL tracking mode 2 (0x0084)*/ +#define RT5668_DA_STO1_TRACK_MASK (0x7 << 12) +#define RT5668_DA_STO1_TRACK_SHIFT 12 +#define RT5668_DA_STO1_TRACK_SYSCLK (0x0 << 12) +#define RT5668_DA_STO1_TRACK_I2S1 (0x1 << 12) + +/* PLL tracking mode 3 (0x0085)*/ +#define RT5668_AD_STO1_TRACK_MASK (0x7 << 12) +#define RT5668_AD_STO1_TRACK_SHIFT 12 +#define RT5668_AD_STO1_TRACK_SYSCLK (0x0 << 12) +#define RT5668_AD_STO1_TRACK_I2S1 (0x1 << 12) + +/* HPOUT Charge pump control 1 (0x0091) */ +#define RT5668_OSW_HP_L_MASK (0x1 << 11) +#define RT5668_OSW_HP_L_SHIFT 11 +#define RT5668_OSW_HP_L_EN (0x1 << 11) +#define RT5668_OSW_HP_L_DIS (0x0 << 11) +#define RT5668_OSW_HP_R_MASK (0x1 << 10) +#define RT5668_OSW_HP_R_SHIFT 10 +#define RT5668_OSW_HP_R_EN (0x1 << 10) +#define RT5668_OSW_HP_R_DIS (0x0 << 10) +#define RT5668_SEL_PM_HP_MASK (0x3 << 8) +#define RT5668_SEL_PM_HP_SHIFT 8 +#define RT5668_SEL_PM_HP_0_6 (0x0 << 8) +#define RT5668_SEL_PM_HP_0_9 (0x1 << 8) +#define RT5668_SEL_PM_HP_1_8 (0x2 << 8) +#define RT5668_SEL_PM_HP_HIGH (0x3 << 8) +#define RT5668_OVCD_HP_MASK (0x1 << 2) +#define RT5668_OVCD_HP_SHIFT 2 +#define RT5668_OVCD_HP_EN (0x1 << 2) +#define RT5668_OVCD_HP_DIS (0x0 << 2) + +/* RC Clock Control (0x0094) */ +#define RT5668_DIG_25M_CLK_MASK (0x1 << 9) +#define RT5668_DIG_25M_CLK_SHIFT 9 +#define RT5668_DIG_25M_CLK_DIS (0x0 << 9) +#define RT5668_DIG_25M_CLK_EN (0x1 << 9) +#define RT5668_DIG_1M_CLK_MASK (0x1 << 8) +#define RT5668_DIG_1M_CLK_SHIFT 8 +#define RT5668_DIG_1M_CLK_DIS (0x0 << 8) +#define RT5668_DIG_1M_CLK_EN (0x1 << 8) + +/* Auto Turn On 1M RC CLK (0x009f) */ +#define RT5668_IRQ_POW_SAV_MASK (0x1 << 15) +#define RT5668_IRQ_POW_SAV_SHIFT 15 +#define RT5668_IRQ_POW_SAV_DIS (0x0 << 15) +#define RT5668_IRQ_POW_SAV_EN (0x1 << 15) +#define RT5668_IRQ_POW_SAV_JD1_MASK (0x1 << 14) +#define RT5668_IRQ_POW_SAV_JD1_SHIFT 14 +#define RT5668_IRQ_POW_SAV_JD1_DIS (0x0 << 14) +#define RT5668_IRQ_POW_SAV_JD1_EN (0x1 << 14) + +/* IRQ Control 1 (0x00b6) */ +#define RT5668_EN_CB_JD_MASK (0x1 << 3) +#define RT5668_EN_CB_JD_SHIFT 3 +#define RT5668_EN_CB_JD_EN (0x1 << 3) +#define RT5668_EN_CB_JD_DIS (0x0 << 3) + +/* IRQ Control 3 (0x00b8) */ +#define RT5668_EN_IRQ_INLINE_MASK (0x1 << 6) +#define RT5668_EN_IRQ_INLINE_SHIFT 6 +#define RT5668_EN_IRQ_INLINE_BYP (0x0 << 6) +#define RT5668_EN_IRQ_INLINE_NOR (0x1 << 6) + +/* GPIO Control 1 (0x00c0) */ +#define RT5668_GP1_PIN_MASK (0x1 << 15) +#define RT5668_GP1_PIN_SHIFT 15 +#define RT5668_GP1_PIN_GPIO1 (0x0 << 15) +#define RT5668_GP1_PIN_IRQ (0x1 << 15) + +/* GPIO Control 2 (0x00c1) */ +#define RT5668_GP4_PIN_CONF_MASK (0x1 << 5) +#define RT5668_GP4_PIN_CONF_SHIFT 5 +#define RT5668_GP4_PIN_CONF_INPUT (0x0 << 5) +#define RT5668_GP4_PIN_CONF_OUTPUT (0x1 << 5) + +/* GPIO Control 2 (0x00c2) */ +#define RT5668_GP8_PIN_CONF_MASK (0x1 << 13) +#define RT5668_GP8_PIN_CONF_SHIFT 13 +#define RT5668_GP8_PIN_CONF_INPUT (0x0 << 13) +#define RT5668_GP8_PIN_CONF_OUTPUT (0x1 << 13) + +/* 4 Buttons Inline Command Function 1 (0x00df) */ +#define RT5668_4BTN_CLK_DEB_MASK (0x3 << 2) +#define RT5668_4BTN_CLK_DEB_SHIFT 2 +#define RT5668_4BTN_CLK_DEB_8MS (0x0 << 2) +#define RT5668_4BTN_CLK_DEB_16MS (0x1 << 2) +#define RT5668_4BTN_CLK_DEB_32MS (0x2 << 2) +#define RT5668_4BTN_CLK_DEB_65MS (0x3 << 2) + +/* Inline Command Function 6 (0x00e0) */ +#define RT5668_EN_4BTN_INL_MASK (0x1 << 15) +#define RT5668_EN_4BTN_INL_SHIFT 15 +#define RT5668_EN_4BTN_INL_DIS (0x0 << 15) +#define RT5668_EN_4BTN_INL_EN (0x1 << 15) +#define RT5668_RESET_4BTN_INL_MASK (0x1 << 14) +#define RT5668_RESET_4BTN_INL_SHIFT 14 +#define RT5668_RESET_4BTN_INL_RESET (0x0 << 14) +#define RT5668_RESET_4BTN_INL_NOR (0x1 << 14) + +/* Digital Misc Control (0x00fa) */ +#define RT5668_DIG_GATE_CTRL_MASK 0x1 +#define RT5668_DIG_GATE_CTRL_SHIFT (0) +#define RT5668_DIG_GATE_CTRL_DIS 0x0 +#define RT5668_DIG_GATE_CTRL_EN 0x1 + +/* Chopper and Clock control for DAC L (0x013a)*/ +#define RT5668_CKXEN_DAC1_MASK (0x1 << 13) +#define RT5668_CKXEN_DAC1_SHIFT 13 +#define RT5668_CKGEN_DAC1_MASK (0x1 << 12) +#define RT5668_CKGEN_DAC1_SHIFT 12 + +/* Chopper and Clock control for ADC (0x013b)*/ +#define RT5668_CKXEN_ADCC_MASK (0x1 << 13) +#define RT5668_CKXEN_ADCC_SHIFT 13 +#define RT5668_CKGEN_ADCC_MASK (0x1 << 12) +#define RT5668_CKGEN_ADCC_SHIFT 12 + +/* HP Behavior Logic Control 2 (0x01db) */ +#define RT5668_HP_SIG_SRC1_MASK (0x3) +#define RT5668_HP_SIG_SRC1_SHIFT 0 +#define RT5668_HP_SIG_SRC1_HP_DC (0x0) +#define RT5668_HP_SIG_SRC1_HP_CALIB (0x1) +#define RT5668_HP_SIG_SRC1_REG (0x2) +#define RT5668_HP_SIG_SRC1_SILENCE (0x3) + +/* RT5663 specific register */ +#define RT5663_HP_OUT_EN 0x0002 +#define RT5663_HP_LCH_DRE 0x0005 +#define RT5663_HP_RCH_DRE 0x0006 +#define RT5663_CALIB_BST 0x000a +#define RT5663_RECMIX 0x0010 +#define RT5663_SIL_DET_CTL 0x0015 +#define RT5663_PWR_SAV_SILDET 0x0016 +#define RT5663_SIDETONE_CTL 0x0018 +#define RT5663_STO1_DAC_DIG_VOL 0x0019 +#define RT5663_STO1_ADC_DIG_VOL 0x001c +#define RT5663_STO1_BOOST 0x001f +#define RT5663_HP_IMP_GAIN_1 0x0022 +#define RT5663_HP_IMP_GAIN_2 0x0023 +#define RT5663_STO1_ADC_MIXER 0x0026 +#define RT5663_AD_DA_MIXER 0x0029 +#define RT5663_STO_DAC_MIXER 0x002a +#define RT5663_DIG_SIDE_MIXER 0x002c +#define RT5663_BYPASS_STO_DAC 0x002d +#define RT5663_CALIB_REC_MIX 0x0040 +#define RT5663_PWR_DIG_1 0x0061 +#define RT5663_PWR_DIG_2 0x0062 +#define RT5663_PWR_ANLG_1 0x0063 +#define RT5663_PWR_ANLG_2 0x0064 +#define RT5663_PWR_ANLG_3 0x0065 +#define RT5663_PWR_MIXER 0x0066 +#define RT5663_SIG_CLK_DET 0x006b +#define RT5663_PRE_DIV_GATING_1 0x006e +#define RT5663_PRE_DIV_GATING_2 0x006f +#define RT5663_I2S1_SDP 0x0070 +#define RT5663_ADDA_CLK_1 0x0073 +#define RT5663_ADDA_RST 0x0074 +#define RT5663_FRAC_DIV_1 0x0075 +#define RT5663_FRAC_DIV_2 0x0076 +#define RT5663_TDM_1 0x0077 +#define RT5663_TDM_2 0x0078 +#define RT5663_TDM_3 0x0079 +#define RT5663_TDM_4 0x007a +#define RT5663_TDM_5 0x007b +#define RT5663_GLB_CLK 0x0080 +#define RT5663_PLL_1 0x0081 +#define RT5663_PLL_2 0x0082 +#define RT5663_ASRC_1 0x0083 +#define RT5663_ASRC_2 0x0084 +#define RT5663_ASRC_4 0x0086 +#define RT5663_DUMMY_REG 0x0087 +#define RT5663_ASRC_8 0x008a +#define RT5663_ASRC_9 0x008b +#define RT5663_ASRC_11 0x008c +#define RT5663_DEPOP_1 0x008e +#define RT5663_DEPOP_2 0x008f +#define RT5663_DEPOP_3 0x0090 +#define RT5663_HP_CHARGE_PUMP_1 0x0091 +#define RT5663_HP_CHARGE_PUMP_2 0x0092 +#define RT5663_MICBIAS_1 0x0093 +#define RT5663_RC_CLK 0x0094 +#define RT5663_ASRC_11_2 0x0097 +#define RT5663_DUMMY_REG_2 0x0098 +#define RT5663_REC_PATH_GAIN 0x009a +#define RT5663_AUTO_1MRC_CLK 0x009f +#define RT5663_ADC_EQ_1 0x00ae +#define RT5663_ADC_EQ_2 0x00af +#define RT5663_IRQ_1 0x00b6 +#define RT5663_IRQ_2 0x00b7 +#define RT5663_IRQ_3 0x00b8 +#define RT5663_IRQ_4 0x00ba +#define RT5663_IRQ_5 0x00bb +#define RT5663_INT_ST_1 0x00be +#define RT5663_INT_ST_2 0x00bf +#define RT5663_GPIO_1 0x00c0 +#define RT5663_GPIO_2 0x00c1 +#define RT5663_GPIO_STA 0x00c5 +#define RT5663_SIN_GEN_1 0x00cb +#define RT5663_SIN_GEN_2 0x00cc +#define RT5663_SIN_GEN_3 0x00cd +#define RT5663_SOF_VOL_ZC1 0x00d9 +#define RT5663_IL_CMD_1 0x00db +#define RT5663_IL_CMD_2 0x00dc +#define RT5663_IL_CMD_3 0x00dd +#define RT5663_IL_CMD_4 0x00de +#define RT5663_IL_CMD_5 0x00df +#define RT5663_IL_CMD_6 0x00e0 +#define RT5663_IL_CMD_7 0x00e1 +#define RT5663_IL_CMD_8 0x00e2 +#define RT5663_IL_CMD_PWRSAV1 0x00e4 +#define RT5663_IL_CMD_PWRSAV2 0x00e5 +#define RT5663_EM_JACK_TYPE_1 0x00e6 +#define RT5663_EM_JACK_TYPE_2 0x00e7 +#define RT5663_EM_JACK_TYPE_3 0x00e8 +#define RT5663_EM_JACK_TYPE_4 0x00e9 +#define RT5663_EM_JACK_TYPE_5 0x00ea +#define RT5663_EM_JACK_TYPE_6 0x00eb +#define RT5663_STO1_HPF_ADJ1 0x00ec +#define RT5663_STO1_HPF_ADJ2 0x00ed +#define RT5663_FAST_OFF_MICBIAS 0x00f4 +#define RT5663_JD_CTRL1 0x00f6 +#define RT5663_JD_CTRL2 0x00f8 +#define RT5663_DIG_MISC 0x00fa +#define RT5663_DIG_VOL_ZCD 0x0100 +#define RT5663_ANA_BIAS_CUR_1 0x0108 +#define RT5663_ANA_BIAS_CUR_2 0x0109 +#define RT5663_ANA_BIAS_CUR_3 0x010a +#define RT5663_ANA_BIAS_CUR_4 0x010b +#define RT5663_ANA_BIAS_CUR_5 0x010c +#define RT5663_ANA_BIAS_CUR_6 0x010d +#define RT5663_BIAS_CUR_5 0x010e +#define RT5663_BIAS_CUR_6 0x010f +#define RT5663_BIAS_CUR_7 0x0110 +#define RT5663_BIAS_CUR_8 0x0111 +#define RT5663_DACREF_LDO 0x0112 +#define RT5663_DUMMY_REG_3 0x0113 +#define RT5663_BIAS_CUR_9 0x0114 +#define RT5663_DUMMY_REG_4 0x0116 +#define RT5663_VREFADJ_OP 0x0117 +#define RT5663_VREF_RECMIX 0x0118 +#define RT5663_CHARGE_PUMP_1 0x0125 +#define RT5663_CHARGE_PUMP_1_2 0x0126 +#define RT5663_CHARGE_PUMP_1_3 0x0127 +#define RT5663_CHARGE_PUMP_2 0x0128 +#define RT5663_DIG_IN_PIN1 0x0132 +#define RT5663_PAD_DRV_CTL 0x0137 +#define RT5663_PLL_INT_REG 0x0139 +#define RT5663_CHOP_DAC_L 0x013a +#define RT5663_CHOP_ADC 0x013b +#define RT5663_CALIB_ADC 0x013c +#define RT5663_CHOP_DAC_R 0x013d +#define RT5663_DUMMY_CTL_DACLR 0x013e +#define RT5663_DUMMY_REG_5 0x0140 +#define RT5663_SOFT_RAMP 0x0141 +#define RT5663_TEST_MODE_1 0x0144 +#define RT5663_TEST_MODE_2 0x0145 +#define RT5663_TEST_MODE_3 0x0146 +#define RT5663_STO_DRE_1 0x0160 +#define RT5663_STO_DRE_2 0x0161 +#define RT5663_STO_DRE_3 0x0162 +#define RT5663_STO_DRE_4 0x0163 +#define RT5663_STO_DRE_5 0x0164 +#define RT5663_STO_DRE_6 0x0165 +#define RT5663_STO_DRE_7 0x0166 +#define RT5663_STO_DRE_8 0x0167 +#define RT5663_STO_DRE_9 0x0168 +#define RT5663_STO_DRE_10 0x0169 +#define RT5663_MIC_DECRO_1 0x0180 +#define RT5663_MIC_DECRO_2 0x0181 +#define RT5663_MIC_DECRO_3 0x0182 +#define RT5663_MIC_DECRO_4 0x0183 +#define RT5663_MIC_DECRO_5 0x0184 +#define RT5663_MIC_DECRO_6 0x0185 +#define RT5663_HP_DECRO_1 0x01b0 +#define RT5663_HP_DECRO_2 0x01b1 +#define RT5663_HP_DECRO_3 0x01b2 +#define RT5663_HP_DECRO_4 0x01b3 +#define RT5663_HP_DECOUP 0x01b4 +#define RT5663_HP_IMP_SEN_MAP8 0x01b5 +#define RT5663_HP_IMP_SEN_MAP9 0x01b6 +#define RT5663_HP_IMP_SEN_MAP10 0x01b7 +#define RT5663_HP_IMP_SEN_MAP11 0x01b8 +#define RT5663_HP_IMP_SEN_1 0x01c0 +#define RT5663_HP_IMP_SEN_2 0x01c1 +#define RT5663_HP_IMP_SEN_3 0x01c2 +#define RT5663_HP_IMP_SEN_4 0x01c3 +#define RT5663_HP_IMP_SEN_5 0x01c4 +#define RT5663_HP_IMP_SEN_6 0x01c5 +#define RT5663_HP_IMP_SEN_7 0x01c6 +#define RT5663_HP_IMP_SEN_8 0x01c7 +#define RT5663_HP_IMP_SEN_9 0x01c8 +#define RT5663_HP_IMP_SEN_10 0x01c9 +#define RT5663_HP_IMP_SEN_11 0x01ca +#define RT5663_HP_IMP_SEN_12 0x01cb +#define RT5663_HP_IMP_SEN_13 0x01cc +#define RT5663_HP_IMP_SEN_14 0x01cd +#define RT5663_HP_IMP_SEN_15 0x01ce +#define RT5663_HP_IMP_SEN_16 0x01cf +#define RT5663_HP_IMP_SEN_17 0x01d0 +#define RT5663_HP_IMP_SEN_18 0x01d1 +#define RT5663_HP_IMP_SEN_19 0x01d2 +#define RT5663_HP_IMPSEN_DIG5 0x01d3 +#define RT5663_HP_IMPSEN_MAP1 0x01d4 +#define RT5663_HP_IMPSEN_MAP2 0x01d5 +#define RT5663_HP_IMPSEN_MAP3 0x01d6 +#define RT5663_HP_IMPSEN_MAP4 0x01d7 +#define RT5663_HP_IMPSEN_MAP5 0x01d8 +#define RT5663_HP_IMPSEN_MAP7 0x01d9 +#define RT5663_HP_LOGIC_1 0x01da +#define RT5663_HP_LOGIC_2 0x01db +#define RT5663_HP_CALIB_1 0x01dd +#define RT5663_HP_CALIB_1_1 0x01de +#define RT5663_HP_CALIB_2 0x01df +#define RT5663_HP_CALIB_3 0x01e0 +#define RT5663_HP_CALIB_4 0x01e1 +#define RT5663_HP_CALIB_5 0x01e2 +#define RT5663_HP_CALIB_5_1 0x01e3 +#define RT5663_HP_CALIB_6 0x01e4 +#define RT5663_HP_CALIB_7 0x01e5 +#define RT5663_HP_CALIB_9 0x01e6 +#define RT5663_HP_CALIB_10 0x01e7 +#define RT5663_HP_CALIB_11 0x01e8 +#define RT5663_HP_CALIB_ST1 0x01ea +#define RT5663_HP_CALIB_ST2 0x01eb +#define RT5663_HP_CALIB_ST3 0x01ec +#define RT5663_HP_CALIB_ST4 0x01ed +#define RT5663_HP_CALIB_ST5 0x01ee +#define RT5663_HP_CALIB_ST6 0x01ef +#define RT5663_HP_CALIB_ST7 0x01f0 +#define RT5663_HP_CALIB_ST8 0x01f1 +#define RT5663_HP_CALIB_ST9 0x01f2 +#define RT5663_HP_AMP_DET 0x0200 +#define RT5663_DUMMY_REG_6 0x0201 +#define RT5663_HP_BIAS 0x0202 +#define RT5663_CBJ_1 0x0250 +#define RT5663_CBJ_2 0x0251 +#define RT5663_CBJ_3 0x0252 +#define RT5663_DUMMY_1 0x02fa +#define RT5663_DUMMY_2 0x02fb +#define RT5663_DUMMY_3 0x02fc +#define RT5663_ANA_JD 0x0300 +#define RT5663_ADC_LCH_LPF1_A1 0x03d0 +#define RT5663_ADC_RCH_LPF1_A1 0x03d1 +#define RT5663_ADC_LCH_LPF1_H0 0x03d2 +#define RT5663_ADC_RCH_LPF1_H0 0x03d3 +#define RT5663_ADC_LCH_BPF1_A1 0x03d4 +#define RT5663_ADC_RCH_BPF1_A1 0x03d5 +#define RT5663_ADC_LCH_BPF1_A2 0x03d6 +#define RT5663_ADC_RCH_BPF1_A2 0x03d7 +#define RT5663_ADC_LCH_BPF1_H0 0x03d8 +#define RT5663_ADC_RCH_BPF1_H0 0x03d9 +#define RT5663_ADC_LCH_BPF2_A1 0x03da +#define RT5663_ADC_RCH_BPF2_A1 0x03db +#define RT5663_ADC_LCH_BPF2_A2 0x03dc +#define RT5663_ADC_RCH_BPF2_A2 0x03dd +#define RT5663_ADC_LCH_BPF2_H0 0x03de +#define RT5663_ADC_RCH_BPF2_H0 0x03df +#define RT5663_ADC_LCH_BPF3_A1 0x03e0 +#define RT5663_ADC_RCH_BPF3_A1 0x03e1 +#define RT5663_ADC_LCH_BPF3_A2 0x03e2 +#define RT5663_ADC_RCH_BPF3_A2 0x03e3 +#define RT5663_ADC_LCH_BPF3_H0 0x03e4 +#define RT5663_ADC_RCH_BPF3_H0 0x03e5 +#define RT5663_ADC_LCH_BPF4_A1 0x03e6 +#define RT5663_ADC_RCH_BPF4_A1 0x03e7 +#define RT5663_ADC_LCH_BPF4_A2 0x03e8 +#define RT5663_ADC_RCH_BPF4_A2 0x03e9 +#define RT5663_ADC_LCH_BPF4_H0 0x03ea +#define RT5663_ADC_RCH_BPF4_H0 0x03eb +#define RT5663_ADC_LCH_HPF1_A1 0x03ec +#define RT5663_ADC_RCH_HPF1_A1 0x03ed +#define RT5663_ADC_LCH_HPF1_H0 0x03ee +#define RT5663_ADC_RCH_HPF1_H0 0x03ef +#define RT5663_ADC_EQ_PRE_VOL_L 0x03f0 +#define RT5663_ADC_EQ_PRE_VOL_R 0x03f1 +#define RT5663_ADC_EQ_POST_VOL_L 0x03f2 +#define RT5663_ADC_EQ_POST_VOL_R 0x03f3 + +/* RT5663: RECMIX Control (0x0010) */ +#define RT5663_RECMIX1_BST1_MASK (0x1) +#define RT5663_RECMIX1_BST1_SHIFT 0 +#define RT5663_RECMIX1_BST1_ON (0x0) +#define RT5663_RECMIX1_BST1_OFF (0x1) + +/* RT5663: Bypass Stereo1 DAC Mixer Control (0x002d) */ +#define RT5663_DACL1_SRC_MASK (0x1 << 3) +#define RT5663_DACL1_SRC_SHIFT 3 +#define RT5663_DACR1_SRC_MASK (0x1 << 2) +#define RT5663_DACR1_SRC_SHIFT 2 + +/* RT5663: TDM control 2 (0x0078) */ +#define RT5663_DATA_SWAP_ADCDAT1_MASK (0x3 << 14) +#define RT5663_DATA_SWAP_ADCDAT1_SHIFT 14 +#define RT5663_DATA_SWAP_ADCDAT1_LR (0x0 << 14) +#define RT5663_DATA_SWAP_ADCDAT1_RL (0x1 << 14) +#define RT5663_DATA_SWAP_ADCDAT1_LL (0x2 << 14) +#define RT5663_DATA_SWAP_ADCDAT1_RR (0x3 << 14) + +/* RT5663: TDM control 5 (0x007b) */ +#define RT5663_TDM_LENGTN_MASK (0x3) +#define RT5663_TDM_LENGTN_SHIFT 0 +#define RT5663_TDM_LENGTN_16 (0x0) +#define RT5663_TDM_LENGTN_20 (0x1) +#define RT5663_TDM_LENGTN_24 (0x2) +#define RT5663_TDM_LENGTN_32 (0x3) + +/* RT5663: Global Clock Control (0x0080) */ +#define RT5663_SCLK_SRC_MASK (0x3 << 14) +#define RT5663_SCLK_SRC_SHIFT 14 +#define RT5663_SCLK_SRC_MCLK (0x0 << 14) +#define RT5663_SCLK_SRC_PLL1 (0x1 << 14) +#define RT5663_SCLK_SRC_RCCLK (0x2 << 14) +#define RT5663_PLL1_SRC_MASK (0x7 << 11) +#define RT5663_PLL1_SRC_SHIFT 11 +#define RT5663_PLL1_SRC_MCLK (0x0 << 11) +#define RT5663_PLL1_SRC_BCLK1 (0x1 << 11) + +/* PLL tracking mode 1 (0x0083) */ +#define RT5663_I2S1_ASRC_MASK (0x1 << 11) +#define RT5663_I2S1_ASRC_SHIFT 11 +#define RT5663_DAC_STO1_ASRC_MASK (0x1 << 10) +#define RT5663_DAC_STO1_ASRC_SHIFT 10 +#define RT5663_ADC_STO1_ASRC_MASK (0x1 << 3) +#define RT5663_ADC_STO1_ASRC_SHIFT 3 + +/* PLL tracking mode 2 (0x0084)*/ +#define RT5663_DA_STO1_TRACK_MASK (0x7 << 12) +#define RT5663_DA_STO1_TRACK_SHIFT 12 +#define RT5663_DA_STO1_TRACK_SYSCLK (0x0 << 12) +#define RT5663_DA_STO1_TRACK_I2S1 (0x1 << 12) +#define RT5663_AD_STO1_TRACK_MASK (0x7) +#define RT5663_AD_STO1_TRACK_SHIFT 0 +#define RT5663_AD_STO1_TRACK_SYSCLK (0x0) +#define RT5663_AD_STO1_TRACK_I2S1 (0x1) + +/* RT5663: HPOUT Charge pump control 1 (0x0091) */ +#define RT5663_SI_HP_MASK (0x1 << 12) +#define RT5663_SI_HP_SHIFT 12 +#define RT5663_SI_HP_EN (0x1 << 12) +#define RT5663_SI_HP_DIS (0x0 << 12) + +/* RT5663: GPIO Control 2 (0x00b6) */ +#define RT5663_GP1_PIN_CONF_MASK (0x1 << 2) +#define RT5663_GP1_PIN_CONF_SHIFT 2 +#define RT5663_GP1_PIN_CONF_OUTPUT (0x1 << 2) +#define RT5663_GP1_PIN_CONF_INPUT (0x0 << 2) + +/* RT5663: GPIO Control 2 (0x00b7) */ +#define RT5663_EN_IRQ_INLINE_MASK (0x1 << 3) +#define RT5663_EN_IRQ_INLINE_SHIFT 3 +#define RT5663_EN_IRQ_INLINE_NOR (0x1 << 3) +#define RT5663_EN_IRQ_INLINE_BYP (0x0 << 3) + +/* RT5663: IRQ Control 1 (0x00c1) */ +#define RT5663_EN_IRQ_JD1_MASK (0x1 << 6) +#define RT5663_EN_IRQ_JD1_SHIFT 6 +#define RT5663_EN_IRQ_JD1_EN (0x1 << 6) +#define RT5663_EN_IRQ_JD1_DIS (0x0 << 6) + +/* RT5663: Inline Command Function 2 (0x00dc) */ +#define RT5663_PWR_MIC_DET_MASK (0x1) +#define RT5663_PWR_MIC_DET_SHIFT 0 +#define RT5663_PWR_MIC_DET_ON (0x1) +#define RT5663_PWR_MIC_DET_OFF (0x0) + +/* RT5663: Embeeded Jack and Type Detection Control 1 (0x00e6)*/ +#define RT5663_CBJ_DET_MASK (0x1 << 15) +#define RT5663_CBJ_DET_SHIFT 15 +#define RT5663_CBJ_DET_DIS (0x0 << 15) +#define RT5663_CBJ_DET_EN (0x1 << 15) +#define RT5663_EXT_JD_MASK (0x1 << 11) +#define RT5663_EXT_JD_SHIFT 11 +#define RT5663_EXT_JD_EN (0x1 << 11) +#define RT5663_EXT_JD_DIS (0x0 << 11) +#define RT5663_POL_EXT_JD_MASK (0x1 << 10) +#define RT5663_POL_EXT_JD_SHIFT 10 +#define RT5663_POL_EXT_JD_EN (0x1 << 10) +#define RT5663_POL_EXT_JD_DIS (0x0 << 10) + +/* RT5663: DACREF LDO Control (0x0112)*/ +#define RT5663_PWR_LDO_DACREFL_MASK (0x1 << 9) +#define RT5663_PWR_LDO_DACREFL_SHIFT 9 +#define RT5663_PWR_LDO_DACREFR_MASK (0x1 << 1) +#define RT5663_PWR_LDO_DACREFR_SHIFT 1 + +/* RT5663: Stereo Dynamic Range Enhancement Control 9 (0x0168, 0x0169)*/ +#define RT5663_DRE_GAIN_HP_MASK (0x1f) +#define RT5663_DRE_GAIN_HP_SHIFT 0 + +/* RT5663: Combo Jack Control (0x0250) */ +#define RT5663_INBUF_CBJ_BST1_MASK (0x1 << 11) +#define RT5663_INBUF_CBJ_BST1_SHIFT 11 +#define RT5663_INBUF_CBJ_BST1_ON (0x1 << 11) +#define RT5663_INBUF_CBJ_BST1_OFF (0x0 << 11) +#define RT5663_CBJ_SENSE_BST1_MASK (0x1 << 10) +#define RT5663_CBJ_SENSE_BST1_SHIFT 10 +#define RT5663_CBJ_SENSE_BST1_L (0x1 << 10) +#define RT5663_CBJ_SENSE_BST1_R (0x0 << 10) + +/* RT5663: Combo Jack Control (0x0251) */ +#define RT5663_GAIN_BST1_MASK (0xf) +#define RT5663_GAIN_BST1_SHIFT 0 + +/* RT5663: Dummy register 1 (0x02fa) */ +#define RT5663_EMB_CLK_MASK (0x1 << 9) +#define RT5663_EMB_CLK_SHIFT 9 +#define RT5663_EMB_CLK_EN (0x1 << 9) +#define RT5663_EMB_CLK_DIS (0x0 << 9) +#define RT5663_HPA_CPL_BIAS_MASK (0x7 << 6) +#define RT5663_HPA_CPL_BIAS_SHIFT 6 +#define RT5663_HPA_CPL_BIAS_0_5 (0x0 << 6) +#define RT5663_HPA_CPL_BIAS_1 (0x1 << 6) +#define RT5663_HPA_CPL_BIAS_2 (0x2 << 6) +#define RT5663_HPA_CPL_BIAS_3 (0x3 << 6) +#define RT5663_HPA_CPL_BIAS_4_1 (0x4 << 6) +#define RT5663_HPA_CPL_BIAS_4_2 (0x5 << 6) +#define RT5663_HPA_CPL_BIAS_6 (0x6 << 6) +#define RT5663_HPA_CPL_BIAS_8 (0x7 << 6) +#define RT5663_HPA_CPR_BIAS_MASK (0x7 << 3) +#define RT5663_HPA_CPR_BIAS_SHIFT 3 +#define RT5663_HPA_CPR_BIAS_0_5 (0x0 << 3) +#define RT5663_HPA_CPR_BIAS_1 (0x1 << 3) +#define RT5663_HPA_CPR_BIAS_2 (0x2 << 3) +#define RT5663_HPA_CPR_BIAS_3 (0x3 << 3) +#define RT5663_HPA_CPR_BIAS_4_1 (0x4 << 3) +#define RT5663_HPA_CPR_BIAS_4_2 (0x5 << 3) +#define RT5663_HPA_CPR_BIAS_6 (0x6 << 3) +#define RT5663_HPA_CPR_BIAS_8 (0x7 << 3) +#define RT5663_DUMMY_BIAS_MASK (0x7) +#define RT5663_DUMMY_BIAS_SHIFT 0 +#define RT5663_DUMMY_BIAS_0_5 (0x0) +#define RT5663_DUMMY_BIAS_1 (0x1) +#define RT5663_DUMMY_BIAS_2 (0x2) +#define RT5663_DUMMY_BIAS_3 (0x3) +#define RT5663_DUMMY_BIAS_4_1 (0x4) +#define RT5663_DUMMY_BIAS_4_2 (0x5) +#define RT5663_DUMMY_BIAS_6 (0x6) +#define RT5663_DUMMY_BIAS_8 (0x7) + + +/* System Clock Source */ +enum { + RT5663_SCLK_S_MCLK, + RT5663_SCLK_S_PLL1, + RT5663_SCLK_S_RCCLK, +}; + +/* PLL1 Source */ +enum { + RT5663_PLL1_S_MCLK, + RT5663_PLL1_S_BCLK1, +}; + +enum { + RT5663_AIF, + RT5663_AIFS, +}; + +/* asrc clock source */ +enum { + RT5663_CLK_SEL_SYS = 0x0, + RT5663_CLK_SEL_I2S1_ASRC = 0x1, +}; + +/* filter mask */ +enum { + RT5663_DA_STEREO_FILTER = 0x1, + RT5663_AD_STEREO_FILTER = 0x2, +}; + +int rt5663_set_jack_detect(struct snd_soc_codec *codec, + struct snd_soc_jack *hs_jack); +int rt5663_sel_asrc_clk_src(struct snd_soc_codec *codec, + unsigned int filter_mask, unsigned int clk_src); + +#endif /* __RT5663_H__ */ -- cgit v0.10.2 From 6a0b87c6e7f664aff8957e0889f9f82e5ee27f65 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Mon, 12 Sep 2016 16:46:50 +0100 Subject: ASoC: da7219: Support HP detect procedure when MCLK not present Currently the driver code assumes that MCLK will be present during the procedure, or if it has control of MCLK then it can make sure it's enabled. Some platforms however do not provide MCLK to the driver in this way, and will not leave MCLK enabled when Codec is in STANDBY state. This patch adds support for the HP detect procedure when running from the device's internal oscillator, to ensure all platforms can make use of this feature correctly. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index 4e369a1..fc27dab 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -115,7 +115,7 @@ static void da7219_aad_hptest_work(struct work_struct *work) struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); u16 tonegen_freq_hptest; - u8 accdet_cfg8; + u8 pll_srm_sts, gain_ramp_ctrl, accdet_cfg8; int report = 0, ret = 0; /* Lock DAPM and any Kcontrols that are affected by this test */ @@ -133,6 +133,20 @@ static void da7219_aad_hptest_work(struct work_struct *work) } } + /* + * If MCLK not present, then we're using the internal oscillator and + * require different frequency settings to achieve the same result. + */ + pll_srm_sts = snd_soc_read(codec, DA7219_PLL_SRM_STS); + if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) + tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ); + else + tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC); + + /* Ensure gain ramping at fastest rate */ + gain_ramp_ctrl = snd_soc_read(codec, DA7219_GAIN_RAMP_CTRL); + snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_X8); + /* Bypass cache so it saves current settings */ regcache_cache_bypass(da7219->regmap, true); @@ -195,9 +209,15 @@ static void da7219_aad_hptest_work(struct work_struct *work) snd_soc_write(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK); + /* + * If we're running from the internal oscillator then give audio paths + * time to settle before running test. + */ + if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK)) + msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY); + /* Configure & start Tone Generator */ snd_soc_write(codec, DA7219_TONE_GEN_ON_PER, DA7219_BEEP_ON_PER_MASK); - tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ); regmap_raw_write(da7219->regmap, DA7219_TONE_GEN_FREQ1_L, &tonegen_freq_hptest, sizeof(tonegen_freq_hptest)); snd_soc_update_bits(codec, DA7219_TONE_GEN_CFG2, @@ -256,6 +276,16 @@ static void da7219_aad_hptest_work(struct work_struct *work) snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8, DA7219_HPTEST_EN_MASK, 0); + /* + * If we're running from the internal oscillator then give audio paths + * time to settle before allowing headphones to be driven as required. + */ + if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK)) + msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY); + + /* Restore gain ramping rate */ + snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL, gain_ramp_ctrl); + /* Drive Headphones/lineout */ snd_soc_update_bits(codec, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK, DA7219_HP_L_AMP_OE_MASK); diff --git a/sound/soc/codecs/da7219-aad.h b/sound/soc/codecs/da7219-aad.h index 4fccf67..a34be48 100644 --- a/sound/soc/codecs/da7219-aad.h +++ b/sound/soc/codecs/da7219-aad.h @@ -176,8 +176,10 @@ #define DA7219_AAD_MICBIAS_CHK_DELAY 10 #define DA7219_AAD_MICBIAS_CHK_RETRIES 5 -#define DA7219_AAD_HPTEST_RAMP_FREQ 0x28 -#define DA7219_AAD_HPTEST_PERIOD 65 +#define DA7219_AAD_HPTEST_RAMP_FREQ 0x28 +#define DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC 0x4D +#define DA7219_AAD_HPTEST_PERIOD 65 +#define DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY 20 enum da7219_aad_event_regs { DA7219_AAD_IRQ_REG_A = 0, diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h index ff2a2f0..545576d 100644 --- a/sound/soc/codecs/da7219.h +++ b/sound/soc/codecs/da7219.h @@ -224,6 +224,7 @@ #define DA7219_PLL_SRM_STATE_MASK (0xF << 0) #define DA7219_PLL_SRM_STATUS_SHIFT 4 #define DA7219_PLL_SRM_STATUS_MASK (0xF << 4) +#define DA7219_PLL_SRM_STS_MCLK (0x1 << 4) #define DA7219_PLL_SRM_STS_SRM_LOCK (0x1 << 7) /* DA7219_DIG_ROUTING_DAI = 0x2A */ @@ -576,6 +577,7 @@ /* DA7219_GAIN_RAMP_CTRL = 0x92 */ #define DA7219_GAIN_RAMP_RATE_SHIFT 0 #define DA7219_GAIN_RAMP_RATE_MASK (0x3 << 0) +#define DA7219_GAIN_RAMP_RATE_X8 (0x0 << 0) #define DA7219_GAIN_RAMP_RATE_MAX 4 /* DA7219_PC_COUNT = 0x94 */ -- cgit v0.10.2 From 8891098246d07e6dda964a0cffbd504de566c4c3 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Sun, 4 Sep 2016 21:27:32 +0530 Subject: ASoC: tlv320dac33: Remove deprecated create_singlethread_workqueue The workqueue "dac33_wq" queues a single work item &dac33->work and hence doesn't require ordering. Also, it is not being used on a memory reclaim path. Hence, it has been converted to use system_wq. System workqueues have been able to handle high level of concurrency for a long time now and hence it's not required to have a singlethreaded workqueue just to gain concurrency. Unlike a dedicated per-cpu workqueue created with create_singlethread_workqueue(), system_wq allows multiple work items to overlap executions even on the same CPU; however, a per-cpu workqueue doesn't have any CPU locality or global ordering guarantee unless the target CPU is explicitly specified and thus the increase of local concurrency shouldn't make any difference. The work item has been flushed in dac33_soc_remove to ensure that there are no pending tasks while disconnecting the driver. Signed-off-by: Bhaktipriya Shridhar Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index f7a6ce7..6822ac1 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -90,7 +90,6 @@ static const char *dac33_supply_names[DAC33_NUM_SUPPLIES] = { struct tlv320dac33_priv { struct mutex mutex; - struct workqueue_struct *dac33_wq; struct work_struct work; struct snd_soc_codec *codec; struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; @@ -771,7 +770,7 @@ static irqreturn_t dac33_interrupt_handler(int irq, void *dev) /* Do not schedule the workqueue in Mode7 */ if (dac33->fifo_mode != DAC33_FIFO_MODE7) - queue_work(dac33->dac33_wq, &dac33->work); + schedule_work(&dac33->work); return IRQ_HANDLED; } @@ -1127,7 +1126,7 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (dac33->fifo_mode) { dac33->state = DAC33_PREFILL; - queue_work(dac33->dac33_wq, &dac33->work); + schedule_work(&dac33->work); } break; case SNDRV_PCM_TRIGGER_STOP: @@ -1135,7 +1134,7 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (dac33->fifo_mode) { dac33->state = DAC33_FLUSH; - queue_work(dac33->dac33_wq, &dac33->work); + schedule_work(&dac33->work); } break; default: @@ -1410,14 +1409,6 @@ static int dac33_soc_probe(struct snd_soc_codec *codec) dac33->irq = -1; } if (dac33->irq != -1) { - /* Setup work queue */ - dac33->dac33_wq = - create_singlethread_workqueue("tlv320dac33"); - if (dac33->dac33_wq == NULL) { - free_irq(dac33->irq, codec); - return -ENOMEM; - } - INIT_WORK(&dac33->work, dac33_work); } } @@ -1437,7 +1428,7 @@ static int dac33_soc_remove(struct snd_soc_codec *codec) if (dac33->irq >= 0) { free_irq(dac33->irq, dac33->codec); - destroy_workqueue(dac33->dac33_wq); + flush_work(&dac33->work); } return 0; } -- cgit v0.10.2 From f11766143caa065b3aef4d794c104ea0f37ada76 Mon Sep 17 00:00:00 2001 From: Jeeja KP Date: Tue, 6 Sep 2016 14:17:55 +0530 Subject: ASoC: dpcm: Don't apply symmetry for BE with hw param fixup If be_hw_param_fixup is defined for BE then it will force the BE to a specific configuration supported by HW. In this case don't apply symmetry. Signed-off-by: Jeeja KP Signed-off-by: Mark Brown diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 60d702f..c1bfe9d 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1694,6 +1694,9 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, struct snd_soc_pcm_runtime *rtd = be_substream->private_data; int i; + if (rtd->dai_link->be_hw_params_fixup) + continue; + if (soc_pcm_has_symmetry(be_substream)) be_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; -- cgit v0.10.2 From dde53bcc3ea054a72b6d42a6fe56beb4b1a914f2 Mon Sep 17 00:00:00 2001 From: Samaga Krishna Date: Wed, 24 Aug 2016 18:03:21 +0530 Subject: ASoC: Intel: Skylake: Add 32bit support We also support 32bit playback, so add that in DAI capabilities. Signed-off-by: Samaga Krishna Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 77bfd40..c7cdcba 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -648,7 +648,8 @@ static struct snd_soc_dai_driver skl_platform_dai[] = { .channels_min = HDA_MONO, .channels_max = HDA_STEREO, .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .capture = { .stream_name = "System Capture", -- cgit v0.10.2 From 8cc123671a08f35be6b00f6131d3bf8504372ae0 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Wed, 24 Aug 2016 11:00:27 -0700 Subject: ASoC: rt5659: Fix incorrect register addresses According to the datasheets of Realtek ALC5658 (Rev. 0.9) and ALC5659 (Rev. 0.13), the "IRQ Control 4" register is located at MX-00BAh while the "IRQ control 5" register is at MX-00BBh. There is no "IRQ Control 6" register in the datasheets but it is supposed to be behind the "IRQ Control 5" register. So this patch corrects these addresses. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5659.h b/sound/soc/codecs/rt5659.h index d69b0eb..8f1aeef 100644 --- a/sound/soc/codecs/rt5659.h +++ b/sound/soc/codecs/rt5659.h @@ -180,9 +180,9 @@ #define RT5659_IRQ_CTRL_1 0x00b6 #define RT5659_IRQ_CTRL_2 0x00b7 #define RT5659_IRQ_CTRL_3 0x00b8 -#define RT5659_IRQ_CTRL_4 0x00b9 -#define RT5659_IRQ_CTRL_5 0x00ba -#define RT5659_IRQ_CTRL_6 0x00bb +#define RT5659_IRQ_CTRL_4 0x00ba +#define RT5659_IRQ_CTRL_5 0x00bb +#define RT5659_IRQ_CTRL_6 0x00bc #define RT5659_INT_ST_1 0x00be #define RT5659_INT_ST_2 0x00bf #define RT5659_GPIO_CTRL_1 0x00c0 -- cgit v0.10.2 From 62bb7104687c0ac1e85b1cf45a85a20b492b06a6 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 2 Sep 2016 16:52:44 +0100 Subject: ASoC: arizona: Allow specification of base for arizona_is_enabled_fll In preparation for future improvements allow a base to be passed to arizona_is_enabled_fll, this will allow it to be used to check the state of the synchroniser path as well. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index ecfdbfc..5455d0e 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -2188,13 +2188,13 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base, ARIZONA_FLL1_CTRL_UPD | cfg->n); } -static int arizona_is_enabled_fll(struct arizona_fll *fll) +static int arizona_is_enabled_fll(struct arizona_fll *fll, int base) { struct arizona *arizona = fll->arizona; unsigned int reg; int ret; - ret = regmap_read(arizona->regmap, fll->base + 1, ®); + ret = regmap_read(arizona->regmap, base + 1, ®); if (ret != 0) { arizona_fll_err(fll, "Failed to read current state: %d\n", ret); @@ -2208,7 +2208,7 @@ static int arizona_enable_fll(struct arizona_fll *fll) { struct arizona *arizona = fll->arizona; bool use_sync = false; - int already_enabled = arizona_is_enabled_fll(fll); + int already_enabled = arizona_is_enabled_fll(fll, fll->base); struct arizona_fll_cfg cfg; int i; unsigned int val; -- cgit v0.10.2 From 0f72a8a39cd033a26bddafe2b101d12cac039bdc Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 2 Sep 2016 16:52:45 +0100 Subject: ASoC: arizona: Avoid changing SYNC_ENA whilst the FLL_ENA is set For best performance changing the synchroniser state whilst the FLL is running should be avoided. As this has been done fairly regularly in practice rather than hard preventing this, simply improve the FLL enable sequence and give a warning if the user changes the synchroniser state. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 5455d0e..fae6ccf 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -2209,12 +2209,15 @@ static int arizona_enable_fll(struct arizona_fll *fll) struct arizona *arizona = fll->arizona; bool use_sync = false; int already_enabled = arizona_is_enabled_fll(fll, fll->base); + int sync_enabled = arizona_is_enabled_fll(fll, fll->base + 0x10); struct arizona_fll_cfg cfg; int i; unsigned int val; if (already_enabled < 0) return already_enabled; + if (sync_enabled < 0) + return sync_enabled; if (already_enabled) { /* Facilitate smooth refclk across the transition */ @@ -2255,6 +2258,9 @@ static int arizona_enable_fll(struct arizona_fll *fll) return -EINVAL; } + if (already_enabled && !!sync_enabled != use_sync) + arizona_fll_warn(fll, "Synchroniser changed on active FLL\n"); + /* * Increase the bandwidth if we're not using a low frequency * sync source. @@ -2270,12 +2276,12 @@ static int arizona_enable_fll(struct arizona_fll *fll) if (!already_enabled) pm_runtime_get(arizona->dev); - regmap_update_bits_async(arizona->regmap, fll->base + 1, - ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); if (use_sync) regmap_update_bits_async(arizona->regmap, fll->base + 0x11, ARIZONA_FLL1_SYNC_ENA, ARIZONA_FLL1_SYNC_ENA); + regmap_update_bits_async(arizona->regmap, fll->base + 1, + ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); if (already_enabled) regmap_update_bits_async(arizona->regmap, fll->base + 1, -- cgit v0.10.2 From 5a4326d1c21bc9aa958d5e621e06cd1b13e50711 Mon Sep 17 00:00:00 2001 From: Arnaud Pouliquen Date: Tue, 13 Sep 2016 09:58:23 +0200 Subject: ASoC: sti: suppress inappropriate DT fields Update to suppress some DT nodes that can be handled in driver using compatible string. "dai-name", "st,version"and "st,mode" are suppressed "st,tdm-mode" is added to handle TDM mode. Signed-off-by: Arnaud Pouliquen Signed-off-by: Mark Brown diff --git a/sound/soc/sti/sti_uniperif.c b/sound/soc/sti/sti_uniperif.c index 488ef4e..549fac3 100644 --- a/sound/soc/sti/sti_uniperif.c +++ b/sound/soc/sti/sti_uniperif.c @@ -19,6 +19,84 @@ #define UNIPERIF_MAX_FRAME_SZ 0x20 #define UNIPERIF_ALLOWED_FRAME_SZ (0x08 | 0x10 | 0x18 | UNIPERIF_MAX_FRAME_SZ) +struct sti_uniperiph_dev_data { + unsigned int id; /* Nb available player instances */ + unsigned int version; /* player IP version */ + unsigned int stream; + const char *dai_names; + enum uniperif_type type; +}; + +static const struct sti_uniperiph_dev_data sti_uniplayer_hdmi = { + .id = 0, + .version = SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0, + .stream = SNDRV_PCM_STREAM_PLAYBACK, + .dai_names = "Uni Player #0 (HDMI)", + .type = SND_ST_UNIPERIF_TYPE_HDMI +}; + +static const struct sti_uniperiph_dev_data sti_uniplayer_pcm_out = { + .id = 1, + .version = SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0, + .stream = SNDRV_PCM_STREAM_PLAYBACK, + .dai_names = "Uni Player #1 (PCM OUT)", + .type = SND_ST_UNIPERIF_TYPE_PCM | SND_ST_UNIPERIF_TYPE_TDM, +}; + +static const struct sti_uniperiph_dev_data sti_uniplayer_dac = { + .id = 2, + .version = SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0, + .stream = SNDRV_PCM_STREAM_PLAYBACK, + .dai_names = "Uni Player #2 (DAC)", + .type = SND_ST_UNIPERIF_TYPE_PCM, +}; + +static const struct sti_uniperiph_dev_data sti_uniplayer_spdif = { + .id = 3, + .version = SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0, + .stream = SNDRV_PCM_STREAM_PLAYBACK, + .dai_names = "Uni Player #3 (SPDIF)", + .type = SND_ST_UNIPERIF_TYPE_SPDIF +}; + +static const struct sti_uniperiph_dev_data sti_unireader_pcm_in = { + .id = 0, + .version = SND_ST_UNIPERIF_VERSION_UNI_RDR_1_0, + .stream = SNDRV_PCM_STREAM_CAPTURE, + .dai_names = "Uni Reader #0 (PCM IN)", + .type = SND_ST_UNIPERIF_TYPE_PCM | SND_ST_UNIPERIF_TYPE_TDM, +}; + +static const struct sti_uniperiph_dev_data sti_unireader_hdmi_in = { + .id = 1, + .version = SND_ST_UNIPERIF_VERSION_UNI_RDR_1_0, + .stream = SNDRV_PCM_STREAM_CAPTURE, + .dai_names = "Uni Reader #1 (HDMI IN)", + .type = SND_ST_UNIPERIF_TYPE_PCM, +}; + +static const struct of_device_id snd_soc_sti_match[] = { + { .compatible = "st,stih407-uni-player-hdmi", + .data = &sti_uniplayer_hdmi + }, + { .compatible = "st,stih407-uni-player-pcm-out", + .data = &sti_uniplayer_pcm_out + }, + { .compatible = "st,stih407-uni-player-dac", + .data = &sti_uniplayer_dac + }, + { .compatible = "st,stih407-uni-player-spdif", + .data = &sti_uniplayer_spdif + }, + { .compatible = "st,stih407-uni-reader-pcm_in", + .data = &sti_unireader_pcm_in + }, + { .compatible = "st,stih407-uni-reader-hdmi", + .data = &sti_unireader_hdmi_in + }, + {}, +}; + int sti_uniperiph_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) @@ -167,8 +245,8 @@ static int sti_uniperiph_dai_create_ctrl(struct snd_soc_dai *dai) * Uniperipheral instance ID */ ctrl = &uni->snd_ctrls[i]; - ctrl->index = uni->info->id; - ctrl->device = uni->info->id; + ctrl->index = uni->id; + ctrl->device = uni->id; } return snd_soc_add_dai_controls(dai, uni->snd_ctrls, uni->num_ctrls); @@ -186,7 +264,7 @@ int sti_uniperiph_dai_hw_params(struct snd_pcm_substream *substream, struct snd_dmaengine_dai_dma_data *dma_data; int transfer_size; - if (uni->info->type == SND_ST_UNIPERIF_TYPE_TDM) + if (uni->type == SND_ST_UNIPERIF_TYPE_TDM) /* transfer size = user frame size (in 32-bits FIFO cell) */ transfer_size = snd_soc_params_to_frame_size(params) / 32; else @@ -235,7 +313,7 @@ static int sti_uniperiph_dai_resume(struct snd_soc_dai *dai) struct uniperif *uni = priv->dai_data.uni; int ret; - if (of_device_is_compatible(dai->dev->of_node, "st,sti-uni-player")) { + if (priv->dai_data.stream == SNDRV_PCM_STREAM_PLAYBACK) { ret = uni_player_resume(uni); if (ret) return ret; @@ -256,7 +334,7 @@ static int sti_uniperiph_dai_probe(struct snd_soc_dai *dai) struct sti_uniperiph_dai *dai_data = &priv->dai_data; /* DMA settings*/ - if (of_device_is_compatible(dai->dev->of_node, "st,sti-uni-player")) + if (priv->dai_data.stream == SNDRV_PCM_STREAM_PLAYBACK) snd_soc_dai_init_dma_data(dai, &dai_data->dma_data, NULL); else snd_soc_dai_init_dma_data(dai, NULL, &dai_data->dma_data); @@ -280,25 +358,32 @@ static const struct snd_soc_component_driver sti_uniperiph_dai_component = { static int sti_uniperiph_cpu_dai_of(struct device_node *node, struct sti_uniperiph_data *priv) { - const char *str; - int ret; struct device *dev = &priv->pdev->dev; struct sti_uniperiph_dai *dai_data = &priv->dai_data; struct snd_soc_dai_driver *dai = priv->dai; struct snd_soc_pcm_stream *stream; struct uniperif *uni; + const struct of_device_id *of_id; + const struct sti_uniperiph_dev_data *dev_data; + const char *mode; + + /* Populate data structure depending on compatibility */ + of_id = of_match_node(snd_soc_sti_match, node); + if (!of_id->data) { + dev_err(dev, "data associated to device is missing"); + return -EINVAL; + } + dev_data = (struct sti_uniperiph_dev_data *)of_id->data; uni = devm_kzalloc(dev, sizeof(*uni), GFP_KERNEL); if (!uni) return -ENOMEM; + uni->id = dev_data->id; + uni->ver = dev_data->version; + *dai = sti_uniperiph_dai_template; - ret = of_property_read_string(node, "dai-name", &str); - if (ret < 0) { - dev_err(dev, "%s: dai name missing.\n", __func__); - return -EINVAL; - } - dai->name = str; + dai->name = dev_data->dai_names; /* Get resources */ uni->mem_region = platform_get_resource(priv->pdev, IORESOURCE_MEM, 0); @@ -322,9 +407,20 @@ static int sti_uniperiph_cpu_dai_of(struct device_node *node, return -ENXIO; } + uni->type = dev_data->type; + + /* check if player should be configured for tdm */ + if (dev_data->type & SND_ST_UNIPERIF_TYPE_TDM) { + if (!of_property_read_string(node, "st,tdm-mode", &mode)) + uni->type = SND_ST_UNIPERIF_TYPE_TDM; + else + uni->type = SND_ST_UNIPERIF_TYPE_PCM; + } + dai_data->uni = uni; + dai_data->stream = dev_data->stream; - if (of_device_is_compatible(node, "st,sti-uni-player")) { + if (priv->dai_data.stream == SNDRV_PCM_STREAM_PLAYBACK) { uni_player_init(priv->pdev, uni); stream = &dai->playback; } else { @@ -376,12 +472,6 @@ static int sti_uniperiph_probe(struct platform_device *pdev) &dmaengine_pcm_config, 0); } -static const struct of_device_id snd_soc_sti_match[] = { - { .compatible = "st,sti-uni-player", }, - { .compatible = "st,sti-uni-reader", }, - {}, -}; - static struct platform_driver sti_uniperiph_driver = { .driver = { .name = "sti-uniperiph-dai", diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index eb9933c..1993c65 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -1220,16 +1220,16 @@ #define UNIPERIF_FIFO_FRAMES 4 /* FDMA trigger limit in frames */ #define UNIPERIF_TYPE_IS_HDMI(p) \ - ((p)->info->type == SND_ST_UNIPERIF_TYPE_HDMI) + ((p)->type == SND_ST_UNIPERIF_TYPE_HDMI) #define UNIPERIF_TYPE_IS_PCM(p) \ - ((p)->info->type == SND_ST_UNIPERIF_TYPE_PCM) + ((p)->type == SND_ST_UNIPERIF_TYPE_PCM) #define UNIPERIF_TYPE_IS_SPDIF(p) \ - ((p)->info->type == SND_ST_UNIPERIF_TYPE_SPDIF) + ((p)->type == SND_ST_UNIPERIF_TYPE_SPDIF) #define UNIPERIF_TYPE_IS_IEC958(p) \ (UNIPERIF_TYPE_IS_HDMI(p) || \ UNIPERIF_TYPE_IS_SPDIF(p)) #define UNIPERIF_TYPE_IS_TDM(p) \ - ((p)->info->type == SND_ST_UNIPERIF_TYPE_TDM) + ((p)->type == SND_ST_UNIPERIF_TYPE_TDM) /* * Uniperipheral IP revisions @@ -1249,11 +1249,11 @@ enum uniperif_version { }; enum uniperif_type { - SND_ST_UNIPERIF_TYPE_NONE, - SND_ST_UNIPERIF_TYPE_HDMI, - SND_ST_UNIPERIF_TYPE_PCM, - SND_ST_UNIPERIF_TYPE_SPDIF, - SND_ST_UNIPERIF_TYPE_TDM + SND_ST_UNIPERIF_TYPE_NONE = 0x00, + SND_ST_UNIPERIF_TYPE_HDMI = 0x01, + SND_ST_UNIPERIF_TYPE_PCM = 0x02, + SND_ST_UNIPERIF_TYPE_SPDIF = 0x04, + SND_ST_UNIPERIF_TYPE_TDM = 0x08 }; enum uniperif_state { @@ -1278,12 +1278,6 @@ enum uniperif_word_pos { WORD_MAX }; -struct uniperif_info { - int id; /* instance value of the uniperipheral IP */ - enum uniperif_type type; - int underflow_enabled; /* Underflow recovery mode */ -}; - struct uniperif_iec958_settings { enum uniperif_iec958_encoding_mode encoding_mode; struct snd_aes_iec958 iec958; @@ -1298,8 +1292,10 @@ struct dai_tdm_slot { struct uniperif { /* System information */ - struct uniperif_info *info; + enum uniperif_type type; + int underflow_enabled; /* Underflow recovery mode */ struct device *dev; + int id; /* instance value of the uniperipheral IP */ int ver; /* IP version, used by register access macros */ struct regmap_field *clk_sel; struct regmap_field *valid_sel; diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c index 1ac2db2..645e415 100644 --- a/sound/soc/sti/uniperif_player.c +++ b/sound/soc/sti/uniperif_player.c @@ -100,7 +100,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) dev_err(player->dev, "FIFO underflow error detected"); /* Interrupt is just for information when underflow recovery */ - if (player->info->underflow_enabled) { + if (player->underflow_enabled) { /* Update state to underflow */ player->state = UNIPERIF_STATE_UNDERFLOW; @@ -134,7 +134,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) /* Check for underflow recovery done */ if (unlikely(status & UNIPERIF_ITM_UNDERFLOW_REC_DONE_MASK(player))) { - if (!player->info->underflow_enabled) { + if (!player->underflow_enabled) { dev_err(player->dev, "unexpected Underflow recovering"); return -EPERM; } @@ -764,7 +764,7 @@ static int uni_player_prepare(struct snd_pcm_substream *substream, } /* Calculate transfer size (in fifo cells and bytes) for frame count */ - if (player->info->type == SND_ST_UNIPERIF_TYPE_TDM) { + if (player->type == SND_ST_UNIPERIF_TYPE_TDM) { /* transfer size = user frame size (in 32 bits FIFO cell) */ transfer_size = sti_uniperiph_get_user_frame_size(runtime) / 4; @@ -794,7 +794,7 @@ static int uni_player_prepare(struct snd_pcm_substream *substream, SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(player, trigger_limit); /* Uniperipheral setup depends on player type */ - switch (player->info->type) { + switch (player->type) { case SND_ST_UNIPERIF_TYPE_HDMI: ret = uni_player_prepare_iec958(player, runtime); break; @@ -884,7 +884,7 @@ static int uni_player_start(struct uniperif *player) SET_UNIPERIF_ITM_BSET_FIFO_ERROR(player); /* Enable underflow recovery interrupts */ - if (player->info->underflow_enabled) { + if (player->underflow_enabled) { SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE(player); SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED(player); } @@ -1021,8 +1021,8 @@ static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, struct reg_field regfield[2] = { /* PCM_CLK_SEL */ REG_FIELD(SYS_CFG_AUDIO_GLUE, - 8 + player->info->id, - 8 + player->info->id), + 8 + player->id, + 8 + player->id), /* PCMP_VALID_SEL */ REG_FIELD(SYS_CFG_AUDIO_GLUE, 0, 1) }; @@ -1040,60 +1040,6 @@ static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, return 0; } -static int uni_player_parse_dt(struct platform_device *pdev, - struct uniperif *player) -{ - struct uniperif_info *info; - struct device *dev = &pdev->dev; - struct device_node *pnode = pdev->dev.of_node; - const char *mode; - - /* Allocate memory for the info structure */ - info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - if (of_property_read_u32(pnode, "st,version", &player->ver) || - player->ver == SND_ST_UNIPERIF_VERSION_UNKNOWN) { - dev_err(dev, "Unknown uniperipheral version "); - return -EINVAL; - } - /* Underflow recovery is only supported on later ip revisions */ - if (player->ver >= SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) - info->underflow_enabled = 1; - - if (of_property_read_u32(pnode, "st,uniperiph-id", &info->id)) { - dev_err(dev, "uniperipheral id not defined"); - return -EINVAL; - } - - /* Read the device mode property */ - if (of_property_read_string(pnode, "st,mode", &mode)) { - dev_err(dev, "uniperipheral mode not defined"); - return -EINVAL; - } - - if (strcasecmp(mode, "hdmi") == 0) - info->type = SND_ST_UNIPERIF_TYPE_HDMI; - else if (strcasecmp(mode, "pcm") == 0) - info->type = SND_ST_UNIPERIF_TYPE_PCM; - else if (strcasecmp(mode, "spdif") == 0) - info->type = SND_ST_UNIPERIF_TYPE_SPDIF; - else if (strcasecmp(mode, "tdm") == 0) - info->type = SND_ST_UNIPERIF_TYPE_TDM; - else - info->type = SND_ST_UNIPERIF_TYPE_NONE; - - /* Save the info structure */ - player->info = info; - - /* Get PCM_CLK_SEL & PCMP_VALID_SEL from audio-glue-ctrl SoC reg */ - if (uni_player_parse_dt_audio_glue(pdev, player)) - return -EINVAL; - - return 0; -} - static const struct snd_soc_dai_ops uni_player_dai_ops = { .startup = uni_player_startup, .shutdown = uni_player_shutdown, @@ -1114,13 +1060,18 @@ int uni_player_init(struct platform_device *pdev, player->state = UNIPERIF_STATE_STOPPED; player->dai_ops = &uni_player_dai_ops; - ret = uni_player_parse_dt(pdev, player); + /* Get PCM_CLK_SEL & PCMP_VALID_SEL from audio-glue-ctrl SoC reg */ + ret = uni_player_parse_dt_audio_glue(pdev, player); if (ret < 0) { dev_err(player->dev, "Failed to parse DeviceTree"); return ret; } + /* Underflow recovery is only supported on later ip revisions */ + if (player->ver >= SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0) + player->underflow_enabled = 1; + if (UNIPERIF_TYPE_IS_TDM(player)) player->hw = &uni_tdm_hw; else @@ -1144,8 +1095,8 @@ int uni_player_init(struct platform_device *pdev, /* connect to I2S/TDM TX bus */ if (player->valid_sel && - (player->info->id == UNIPERIF_PLAYER_I2S_OUT)) { - ret = regmap_field_write(player->valid_sel, player->info->id); + (player->id == UNIPERIF_PLAYER_I2S_OUT)) { + ret = regmap_field_write(player->valid_sel, player->id); if (ret) { dev_err(player->dev, "%s: unable to connect to tdm bus", __func__); diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c index eb74a32..0e1c3ee 100644 --- a/sound/soc/sti/uniperif_reader.c +++ b/sound/soc/sti/uniperif_reader.c @@ -13,6 +13,7 @@ #include "uniperif.h" +#define UNIPERIF_READER_I2S_IN 0 /* reader id connected to I2S/TDM TX bus */ /* * Note: snd_pcm_hardware is linked to DMA controller but is declared here to * integrate unireader capability in term of rate and supported channels @@ -195,7 +196,7 @@ static int uni_reader_prepare(struct snd_pcm_substream *substream, } /* Calculate transfer size (in fifo cells and bytes) for frame count */ - if (reader->info->type == SND_ST_UNIPERIF_TYPE_TDM) { + if (reader->type == SND_ST_UNIPERIF_TYPE_TDM) { /* transfer size = unip frame size (in 32 bits FIFO cell) */ transfer_size = sti_uniperiph_get_user_frame_size(runtime) / 4; @@ -280,7 +281,7 @@ static int uni_reader_prepare(struct snd_pcm_substream *substream, SET_UNIPERIF_ITM_BSET_MEM_BLK_READ(reader); /* Enable underflow recovery interrupts */ - if (reader->info->underflow_enabled) { + if (reader->underflow_enabled) { SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_DONE(reader); SET_UNIPERIF_ITM_BSET_UNDERFLOW_REC_FAILED(reader); } @@ -394,41 +395,6 @@ static void uni_reader_shutdown(struct snd_pcm_substream *substream, } } -static int uni_reader_parse_dt(struct platform_device *pdev, - struct uniperif *reader) -{ - struct uniperif_info *info; - struct device_node *node = pdev->dev.of_node; - const char *mode; - - /* Allocate memory for the info structure */ - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - if (of_property_read_u32(node, "st,version", &reader->ver) || - reader->ver == SND_ST_UNIPERIF_VERSION_UNKNOWN) { - dev_err(&pdev->dev, "Unknown uniperipheral version "); - return -EINVAL; - } - - /* Read the device mode property */ - if (of_property_read_string(node, "st,mode", &mode)) { - dev_err(&pdev->dev, "uniperipheral mode not defined"); - return -EINVAL; - } - - if (strcasecmp(mode, "tdm") == 0) - info->type = SND_ST_UNIPERIF_TYPE_TDM; - else - info->type = SND_ST_UNIPERIF_TYPE_PCM; - - /* Save the info structure */ - reader->info = info; - - return 0; -} - static const struct snd_soc_dai_ops uni_reader_dai_ops = { .startup = uni_reader_startup, .shutdown = uni_reader_shutdown, @@ -448,12 +414,6 @@ int uni_reader_init(struct platform_device *pdev, reader->state = UNIPERIF_STATE_STOPPED; reader->dai_ops = &uni_reader_dai_ops; - ret = uni_reader_parse_dt(pdev, reader); - if (ret < 0) { - dev_err(reader->dev, "Failed to parse DeviceTree"); - return ret; - } - if (UNIPERIF_TYPE_IS_TDM(reader)) reader->hw = &uni_tdm_hw; else -- cgit v0.10.2 From 04adc0842f5accf99e9757930fc429bf7788cfb3 Mon Sep 17 00:00:00 2001 From: Arnaud Pouliquen Date: Tue, 13 Sep 2016 09:58:24 +0200 Subject: ASoC: sti: suppress inappropriate fields for sti sound card Suppress fields that can be handled in driver using compatible string. Rename compatibility strings accordingly. Signed-off-by: Arnaud Pouliquen Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt b/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt index 16bcdfb..745dc62 100644 --- a/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt +++ b/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt @@ -11,7 +11,9 @@ Documentation/devicetree/bindings/sound/simple-card.txt. --------------------------------------- Required properties: - - compatible: "st,sti-uni-player" or "st,sti-uni-reader" + - compatible: "st,stih407-uni-player-hdmi", "st,stih407-uni-player-pcm-out", + "st,stih407-uni-player-dac", "st,stih407-uni-player-spdif", + "st,stih407-uni-reader-pcm_in", "st,stih407-uni-reader-hdmi", - st,syscfg: phandle to boot-device system configuration registers @@ -33,32 +35,24 @@ Required properties: "tx" for "st,sti-uni-player" compatibility "rx" for "st,sti-uni-reader" compatibility - - st,version: IP version integrated in SOC. - - - dai-name: DAI name that describes the IP. - - - st,mode: IP working mode depending on associated codec. - "HDMI" connected to HDMI codec and support IEC HDMI formats (player only). - "SPDIF" connected to SPDIF codec and support SPDIF formats (player only). - "PCM" PCM standard mode for I2S or TDM bus. - "TDM" TDM mode for TDM bus. - Required properties ("st,sti-uni-player" compatibility only): - clocks: CPU_DAI IP clock source, listed in the same order than the CPU_DAI properties. - - st,uniperiph-id: internal SOC IP instance ID. - Optional properties: - pinctrl-0: defined for CPU_DAI@1 and CPU_DAI@4 to describe I2S PIOs for external codecs connection. - pinctrl-names: should contain only one value - "default". + - st,tdm-mode: to declare to set TDM mode for unireader and uniplayer IPs. + Only compartible with IPs in charge of the external I2S/TDM bus. + Should be declared depending on associated codec. + Example: - sti_uni_player1: sti-uni-player@1 { - compatible = "st,sti-uni-player"; + sti_uni_player1: sti-uni-player@0x8D81000 { + compatible = "st,stih407-uni-player-hdmi"; status = "okay"; #sound-dai-cells = <0>; st,syscfg = <&syscfg_core>; @@ -66,15 +60,12 @@ Example: reg = <0x8D81000 0x158>; interrupts = ; dmas = <&fdma0 3 0 1>; - st,dai-name = "Uni Player #1 (I2S)"; dma-names = "tx"; - st,uniperiph-id = <1>; - st,version = <5>; - st,mode = "TDM"; + st,tdm-mode = <1>; }; - sti_uni_player2: sti-uni-player@2 { - compatible = "st,sti-uni-player"; + sti_uni_player2: sti-uni-player@0x8D82000 { + compatible = "st,stih407-uni-player-pcm-out"; status = "okay"; #sound-dai-cells = <0>; st,syscfg = <&syscfg_core>; @@ -82,15 +73,11 @@ Example: reg = <0x8D82000 0x158>; interrupts = ; dmas = <&fdma0 4 0 1>; - dai-name = "Uni Player #2 (DAC)"; dma-names = "tx"; - st,uniperiph-id = <2>; - st,version = <5>; - st,mode = "PCM"; }; - sti_uni_player3: sti-uni-player@3 { - compatible = "st,sti-uni-player"; + sti_uni_player3: sti-uni-player@0x8D85000 { + compatible = "st,stih407-uni-player-spdif"; status = "okay"; #sound-dai-cells = <0>; st,syscfg = <&syscfg_core>; @@ -99,14 +86,10 @@ Example: interrupts = ; dmas = <&fdma0 7 0 1>; dma-names = "tx"; - dai-name = "Uni Player #3 (SPDIF)"; - st,uniperiph-id = <3>; - st,version = <5>; - st,mode = "SPDIF"; }; - sti_uni_reader1: sti-uni-reader@1 { - compatible = "st,sti-uni-reader"; + sti_uni_reader1: sti-uni-reader@0x8D84000 { + compatible = "st,stih407-uni-reader-hdmi"; status = "disabled"; #sound-dai-cells = <0>; st,syscfg = <&syscfg_core>; @@ -114,9 +97,6 @@ Example: interrupts = ; dmas = <&fdma0 6 0 1>; dma-names = "rx"; - dai-name = "Uni Reader #1 (HDMI RX)"; - st,version = <3>; - st,mode = "PCM"; }; 2) sti-sas-codec: internal audio codec IPs driver -- cgit v0.10.2 From 398fa4db6c694e1f655cad78478a9e3fb030cc01 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 15 Sep 2016 07:25:19 +0900 Subject: ALSA: control: move layout of TLV payload to UAPI header In ALSA control interface, each element set can have threshold level information. This information is transferred between drivers/applications, in a shape of tlv packet. The layout of this packet is defined in 'uapi/sound/asound.h' (struct snd_ctl_tlv): struct snd_ctl_tlv { unsigned int numid; unsigned int length; unsigned int tlv[0]; }; Data in the payload (struct snd_ctl_tlv.tlv) is expected to be filled according to our own protocol. This protocol is described in 'include/sound/tlv.h'. A layout of the payload is expected as: struct snd_ctl_tlv.tlv[0]: one of SNDRV_CTL_TLVT_XXX struct snd_ctl_tlv.tlv[1]: Length of data struct snd_ctl_tlv.tlv[2...]: data Unfortunately, the macro is not exported to user land yet, thus applications cannot get to know the protocol. Additionally, ALSA control core has a feature called as 'user-defined' element set. This allows applications to add/remove arbitrary element sets with elements to control devices. Elements in the element set can be operated by the same way as the ones added by in-kernel implementation. For threshold level information of 'user-defined' element set, applications need to register the information to an element set. However, as described above, layout of the payload is closed in kernel land. This is quite inconvenient, too. This commit moves the protocol to UAPI header for TLV. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/include/sound/tlv.h b/include/sound/tlv.h index df97d19..1f593b6 100644 --- a/include/sound/tlv.h +++ b/include/sound/tlv.h @@ -22,67 +22,6 @@ * */ -/* - * TLV structure is right behind the struct snd_ctl_tlv: - * unsigned int type - see SNDRV_CTL_TLVT_* - * unsigned int length - * .... data aligned to sizeof(unsigned int), use - * block_length = (length + (sizeof(unsigned int) - 1)) & - * ~(sizeof(unsigned int) - 1)) .... - */ - #include -#define TLV_ITEM(type, ...) \ - (type), TLV_LENGTH(__VA_ARGS__), __VA_ARGS__ -#define TLV_LENGTH(...) \ - ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ })) - -#define TLV_CONTAINER_ITEM(...) \ - TLV_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__) -#define DECLARE_TLV_CONTAINER(name, ...) \ - unsigned int name[] = { TLV_CONTAINER_ITEM(__VA_ARGS__) } - -#define TLV_DB_SCALE_MASK 0xffff -#define TLV_DB_SCALE_MUTE 0x10000 -#define TLV_DB_SCALE_ITEM(min, step, mute) \ - TLV_ITEM(SNDRV_CTL_TLVT_DB_SCALE, \ - (min), \ - ((step) & TLV_DB_SCALE_MASK) | \ - ((mute) ? TLV_DB_SCALE_MUTE : 0)) -#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \ - unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) } - -/* dB scale specified with min/max values instead of step */ -#define TLV_DB_MINMAX_ITEM(min_dB, max_dB) \ - TLV_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB)) -#define TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \ - TLV_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB)) -#define DECLARE_TLV_DB_MINMAX(name, min_dB, max_dB) \ - unsigned int name[] = { TLV_DB_MINMAX_ITEM(min_dB, max_dB) } -#define DECLARE_TLV_DB_MINMAX_MUTE(name, min_dB, max_dB) \ - unsigned int name[] = { TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) } - -/* linear volume between min_dB and max_dB (.01dB unit) */ -#define TLV_DB_LINEAR_ITEM(min_dB, max_dB) \ - TLV_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB)) -#define DECLARE_TLV_DB_LINEAR(name, min_dB, max_dB) \ - unsigned int name[] = { TLV_DB_LINEAR_ITEM(min_dB, max_dB) } - -/* dB range container: - * Items in dB range container must be ordered by their values and by their - * dB values. This implies that larger values must correspond with larger - * dB values (which is also required for all other mixer controls). - */ -/* Each item is: */ -#define TLV_DB_RANGE_ITEM(...) \ - TLV_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__) -#define DECLARE_TLV_DB_RANGE(name, ...) \ - unsigned int name[] = { TLV_DB_RANGE_ITEM(__VA_ARGS__) } -/* The below assumes that each item TLV is 4 words like DB_SCALE or LINEAR */ -#define TLV_DB_RANGE_HEAD(num) \ - SNDRV_CTL_TLVT_DB_RANGE, 6 * (num) * sizeof(unsigned int) - -#define TLV_DB_GAIN_MUTE -9999999 - #endif /* __SOUND_TLV_H */ diff --git a/include/uapi/sound/tlv.h b/include/uapi/sound/tlv.h index ffc4f20..b741e0e 100644 --- a/include/uapi/sound/tlv.h +++ b/include/uapi/sound/tlv.h @@ -28,4 +28,64 @@ #define SNDRV_CTL_TLVT_CHMAP_VAR 0x102 /* channels freely swappable */ #define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103 /* pair-wise swappable */ +/* + * TLV structure is right behind the struct snd_ctl_tlv: + * unsigned int type - see SNDRV_CTL_TLVT_* + * unsigned int length + * .... data aligned to sizeof(unsigned int), use + * block_length = (length + (sizeof(unsigned int) - 1)) & + * ~(sizeof(unsigned int) - 1)) .... + */ +#define TLV_ITEM(type, ...) \ + (type), TLV_LENGTH(__VA_ARGS__), __VA_ARGS__ +#define TLV_LENGTH(...) \ + ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ })) + +#define TLV_CONTAINER_ITEM(...) \ + TLV_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__) +#define DECLARE_TLV_CONTAINER(name, ...) \ + unsigned int name[] = { TLV_CONTAINER_ITEM(__VA_ARGS__) } + +#define TLV_DB_SCALE_MASK 0xffff +#define TLV_DB_SCALE_MUTE 0x10000 +#define TLV_DB_SCALE_ITEM(min, step, mute) \ + TLV_ITEM(SNDRV_CTL_TLVT_DB_SCALE, \ + (min), \ + ((step) & TLV_DB_SCALE_MASK) | \ + ((mute) ? TLV_DB_SCALE_MUTE : 0)) +#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \ + unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) } + +/* dB scale specified with min/max values instead of step */ +#define TLV_DB_MINMAX_ITEM(min_dB, max_dB) \ + TLV_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB)) +#define TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \ + TLV_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB)) +#define DECLARE_TLV_DB_MINMAX(name, min_dB, max_dB) \ + unsigned int name[] = { TLV_DB_MINMAX_ITEM(min_dB, max_dB) } +#define DECLARE_TLV_DB_MINMAX_MUTE(name, min_dB, max_dB) \ + unsigned int name[] = { TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) } + +/* linear volume between min_dB and max_dB (.01dB unit) */ +#define TLV_DB_LINEAR_ITEM(min_dB, max_dB) \ + TLV_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB)) +#define DECLARE_TLV_DB_LINEAR(name, min_dB, max_dB) \ + unsigned int name[] = { TLV_DB_LINEAR_ITEM(min_dB, max_dB) } + +/* dB range container: + * Items in dB range container must be ordered by their values and by their + * dB values. This implies that larger values must correspond with larger + * dB values (which is also required for all other mixer controls). + */ +/* Each item is: */ +#define TLV_DB_RANGE_ITEM(...) \ + TLV_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__) +#define DECLARE_TLV_DB_RANGE(name, ...) \ + unsigned int name[] = { TLV_DB_RANGE_ITEM(__VA_ARGS__) } +/* The below assumes that each item TLV is 4 words like DB_SCALE or LINEAR */ +#define TLV_DB_RANGE_HEAD(num) \ + SNDRV_CTL_TLVT_DB_RANGE, 6 * (num) * sizeof(unsigned int) + +#define TLV_DB_GAIN_MUTE -9999999 + #endif -- cgit v0.10.2 From 46e860f76804f86ac6062e9bb0d6dbea47f23899 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 15 Sep 2016 07:25:20 +0900 Subject: ALSA: rename TLV-related macros so that they're friendly to user applications In a previous commit, some macros newly appeared to UAPI header for TLV packet. These macros have short names and they easily bring name conflist to applications. The conflict can be avoided to rename them with a proper prefix. For this purpose, this commit renames these macros with prefix 'SNDRV_CTL_TLVD_'. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/include/sound/tlv.h b/include/sound/tlv.h index 1f593b6..6e2e773 100644 --- a/include/sound/tlv.h +++ b/include/sound/tlv.h @@ -24,4 +24,30 @@ #include +/* For historical reasons, these macros are aliases to the ones in UAPI. */ +#define TLV_ITEM SNDRV_CTL_TLVD_ITEM +#define TLV_LENGTH SNDRV_CTL_TLVD_LENGTH + +#define TLV_CONTAINER_ITEM SNDRV_CTL_TLVD_CONTAINER_ITEM +#define DECLARE_TLV_CONTAINER SNDRV_CTL_TLVD_DECLARE_CONTAINER + +#define TLV_DB_SCALE_MASK SNDRV_CTL_TLVD_DB_SCALE_MASK +#define TLV_DB_SCALE_MUTE SNDRV_CTL_TLVD_DB_SCALE_MUTE +#define TLV_DB_SCALE_ITEM SNDRV_CTL_TLVD_DB_SCALE_ITEM +#define DECLARE_TLV_DB_SCALE SNDRV_CTL_TLVD_DECLARE_DB_SCALE + +#define TLV_DB_MINMAX_ITEM SNDRV_CTL_TLVD_DB_MINMAX_ITEM +#define TLV_DB_MINMAX_MUTE_ITEM SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM +#define DECLARE_TLV_DB_MINMAX SNDRV_CTL_TLVD_DECLARE_DB_MINMAX +#define DECLARE_TLV_DB_MINMAX_MUTE SNDRV_CTL_TLVD_DECLARE_DB_MINMAX_MUTE + +#define TLV_DB_LINEAR_ITEM SNDRV_CTL_TLVD_DB_LINEAR_ITEM +#define DECLARE_TLV_DB_LINEAR SNDRV_CTL_TLVD_DECLARE_DB_LINEAR + +#define TLV_DB_RANGE_ITEM SNDRV_CTL_TLVD_DB_RANGE_ITEM +#define DECLARE_TLV_DB_RANGE SNDRV_CTL_TLVD_DECLARE_DB_RANGE +#define TLV_DB_RANGE_HEAD SNDRV_CTL_TLVD_DB_RANGE_HEAD + +#define TLV_DB_GAIN_MUTE SNDRV_CTL_TLVD_DB_GAIN_MUTE + #endif /* __SOUND_TLV_H */ diff --git a/include/uapi/sound/tlv.h b/include/uapi/sound/tlv.h index b741e0e..f3c198f 100644 --- a/include/uapi/sound/tlv.h +++ b/include/uapi/sound/tlv.h @@ -36,41 +36,51 @@ * block_length = (length + (sizeof(unsigned int) - 1)) & * ~(sizeof(unsigned int) - 1)) .... */ -#define TLV_ITEM(type, ...) \ - (type), TLV_LENGTH(__VA_ARGS__), __VA_ARGS__ -#define TLV_LENGTH(...) \ +#define SNDRV_CTL_TLVD_ITEM(type, ...) \ + (type), SNDRV_CTL_TLVD_LENGTH(__VA_ARGS__), __VA_ARGS__ +#define SNDRV_CTL_TLVD_LENGTH(...) \ ((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ })) -#define TLV_CONTAINER_ITEM(...) \ - TLV_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__) -#define DECLARE_TLV_CONTAINER(name, ...) \ - unsigned int name[] = { TLV_CONTAINER_ITEM(__VA_ARGS__) } +#define SNDRV_CTL_TLVD_CONTAINER_ITEM(...) \ + SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__) +#define SNDRV_CTL_TLVD_DECLARE_CONTAINER(name, ...) \ + unsigned int name[] = { \ + SNDRV_CTL_TLVD_CONTAINER_ITEM(__VA_ARGS__) \ + } -#define TLV_DB_SCALE_MASK 0xffff -#define TLV_DB_SCALE_MUTE 0x10000 -#define TLV_DB_SCALE_ITEM(min, step, mute) \ - TLV_ITEM(SNDRV_CTL_TLVT_DB_SCALE, \ - (min), \ - ((step) & TLV_DB_SCALE_MASK) | \ - ((mute) ? TLV_DB_SCALE_MUTE : 0)) -#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \ - unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) } +#define SNDRV_CTL_TLVD_DB_SCALE_MASK 0xffff +#define SNDRV_CTL_TLVD_DB_SCALE_MUTE 0x10000 +#define SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \ + SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_SCALE, \ + (min), \ + ((step) & SNDRV_CTL_TLVD_DB_SCALE_MASK) | \ + ((mute) ? SNDRV_CTL_TLVD_DB_SCALE_MUTE : 0)) +#define SNDRV_CTL_TLVD_DECLARE_DB_SCALE(name, min, step, mute) \ + unsigned int name[] = { \ + SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \ + } /* dB scale specified with min/max values instead of step */ -#define TLV_DB_MINMAX_ITEM(min_dB, max_dB) \ - TLV_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB)) -#define TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \ - TLV_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB)) -#define DECLARE_TLV_DB_MINMAX(name, min_dB, max_dB) \ - unsigned int name[] = { TLV_DB_MINMAX_ITEM(min_dB, max_dB) } -#define DECLARE_TLV_DB_MINMAX_MUTE(name, min_dB, max_dB) \ - unsigned int name[] = { TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) } +#define SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \ + SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB)) +#define SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \ + SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB)) +#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(name, min_dB, max_dB) \ + unsigned int name[] = { \ + SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \ + } +#define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX_MUTE(name, min_dB, max_dB) \ + unsigned int name[] = { \ + SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \ + } /* linear volume between min_dB and max_dB (.01dB unit) */ -#define TLV_DB_LINEAR_ITEM(min_dB, max_dB) \ - TLV_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB)) -#define DECLARE_TLV_DB_LINEAR(name, min_dB, max_dB) \ - unsigned int name[] = { TLV_DB_LINEAR_ITEM(min_dB, max_dB) } +#define SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \ + SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB)) +#define SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(name, min_dB, max_dB) \ + unsigned int name[] = { \ + SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \ + } /* dB range container: * Items in dB range container must be ordered by their values and by their @@ -78,14 +88,16 @@ * dB values (which is also required for all other mixer controls). */ /* Each item is: */ -#define TLV_DB_RANGE_ITEM(...) \ - TLV_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__) -#define DECLARE_TLV_DB_RANGE(name, ...) \ - unsigned int name[] = { TLV_DB_RANGE_ITEM(__VA_ARGS__) } +#define SNDRV_CTL_TLVD_DB_RANGE_ITEM(...) \ + SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__) +#define SNDRV_CTL_TLVD_DECLARE_DB_RANGE(name, ...) \ + unsigned int name[] = { \ + SNDRV_CTL_TLVD_DB_RANGE_ITEM(__VA_ARGS__) \ + } /* The below assumes that each item TLV is 4 words like DB_SCALE or LINEAR */ -#define TLV_DB_RANGE_HEAD(num) \ +#define SNDRV_CTL_TLVD_DB_RANGE_HEAD(num) \ SNDRV_CTL_TLVT_DB_RANGE, 6 * (num) * sizeof(unsigned int) -#define TLV_DB_GAIN_MUTE -9999999 +#define SNDRV_CTL_TLVD_DB_GAIN_MUTE -9999999 #endif -- cgit v0.10.2 From 22b93eaf55edfd2f1fe9d1fc0d7338f582f12745 Mon Sep 17 00:00:00 2001 From: Cheng-Yi Chiang Date: Fri, 16 Sep 2016 07:10:06 +0800 Subject: ASoC: rockchip: Support headset button function on rk3399 Set the mapping between button and media key event. Signed-off-by: Cheng-Yi Chiang Signed-off-by: Mark Brown diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 164b6da..ee06489 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -209,6 +210,14 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd) return ret; } + snd_jack_set_key(rockchip_sound_jack.jack, SND_JACK_BTN_0, KEY_MEDIA); + snd_jack_set_key( + rockchip_sound_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); + snd_jack_set_key( + rockchip_sound_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key( + rockchip_sound_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + da7219_aad_jack_det(codec, &rockchip_sound_jack); return 0; -- cgit v0.10.2 From 67956ed1000faf7ce3274e04c582131f1e308d06 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 16 Sep 2016 11:09:25 +0100 Subject: ALSA: au88x0: Add missing \n to end of dev_err message Trival fix, the dev_err message is missing a \n so add it. Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index d3125c1..e1af24f 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c @@ -1043,7 +1043,7 @@ static void vortex_fifo_init(vortex_t * vortex) for (x = NR_ADB - 1; x >= 0; x--) { hwwrite(vortex->mmio, addr, (FIFO_U0 | FIFO_U1)); if (hwread(vortex->mmio, addr) != (FIFO_U0 | FIFO_U1)) - dev_err(vortex->card->dev, "bad adb fifo reset!"); + dev_err(vortex->card->dev, "bad adb fifo reset!\n"); vortex_fifo_clearadbdata(vortex, x, FIFO_SIZE); addr -= 4; } -- cgit v0.10.2 From 56efaed524dc2c3571f66d296cb1efbd59cb2996 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 15 Sep 2016 17:42:21 +0200 Subject: ASoC: rt5663: refine error handling The newly added rt5663 codec driver introduces a couple of warnings when built with -Wmaybe-uninitialized: codecs/rt5663.c: In function 'rt5663_set_tdm_slot': codecs/rt5663.c:2680:2: error: 'reg' may be used uninitialized in this function [-Werror=maybe-uninitialized] codecs/rt5663.c: In function 'rt5663_set_dai_pll': codecs/rt5663.c:2556:12: error: 'shift' may be used uninitialized in this function [-Werror=maybe-uninitialized] codecs/rt5663.c:2596:2: error: 'mask' may be used uninitialized in this function [-Werror=maybe-uninitialized] We can avoid those warnings by always returning an error from the switch() statements instead of falling through with an uninitialized variable when we hit an unexpected case. Signed-off-by: Arnd Bergmann Fixes: df7c52168ee1 ("ASoC: add rt5663 codec driver") Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index 7963a27..8078abc 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -1831,6 +1831,7 @@ static int rt5663_i2s_use_asrc(struct snd_soc_dapm_widget *source, break; default: dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + return 1; } if (da_asrc_en || ad_asrc_en) @@ -2579,6 +2580,7 @@ static int rt5663_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, break; default: dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + return -EINVAL; } switch (source) { @@ -2674,6 +2676,7 @@ static int rt5663_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, break; default: dev_err(codec->dev, "Unknown CODEC_TYPE\n"); + return -EINVAL; } snd_soc_update_bits(codec, reg, RT5668_TDM_MODE_MASK | -- cgit v0.10.2 From 361763127f8734b460e2452cf882272c93c26c56 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 16 Sep 2016 17:36:05 +0100 Subject: ALSA: hdac: add missing \n to end of dev_err messages Trival fix, some dev_err messages are missing a \n, so add it. Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 2441273..3be051a 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -424,7 +424,7 @@ void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *ebus, struct hdac_bus *bus = &ebus->bus; if (!bus->spbcap) { - dev_err(bus->dev, "Address of SPB capability is NULL"); + dev_err(bus->dev, "Address of SPB capability is NULL\n"); return; } @@ -453,7 +453,7 @@ int snd_hdac_ext_stream_set_spib(struct hdac_ext_bus *ebus, struct hdac_bus *bus = &ebus->bus; if (!bus->spbcap) { - dev_err(bus->dev, "Address of SPB capability is NULL"); + dev_err(bus->dev, "Address of SPB capability is NULL\n"); return -EINVAL; } @@ -476,7 +476,7 @@ int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_ext_bus *ebus, struct hdac_bus *bus = &ebus->bus; if (!bus->spbcap) { - dev_err(bus->dev, "Address of SPB capability is NULL"); + dev_err(bus->dev, "Address of SPB capability is NULL\n"); return -EINVAL; } @@ -516,7 +516,7 @@ void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus, struct hdac_bus *bus = &ebus->bus; if (!bus->drsmcap) { - dev_err(bus->dev, "Address of DRSM capability is NULL"); + dev_err(bus->dev, "Address of DRSM capability is NULL\n"); return; } @@ -545,7 +545,7 @@ int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus, struct hdac_bus *bus = &ebus->bus; if (!bus->drsmcap) { - dev_err(bus->dev, "Address of DRSM capability is NULL"); + dev_err(bus->dev, "Address of DRSM capability is NULL\n"); return -EINVAL; } -- cgit v0.10.2 From c5a905d3122a501c014b1ba679d3a6d21f2b5c7b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 16 Sep 2016 17:46:41 +0100 Subject: ALSA: compress: fix some missing and misplaced \n in messages Fix a missing \n in a pr_debug message and move the \n to the end of a pr_err message. Signed-off-by: Colin Ian King Signed-off-by: Takashi Iwai diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 583d407..fec1dfd 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -780,7 +780,7 @@ static int snd_compress_wait_for_drain(struct snd_compr_stream *stream) ret = wait_event_interruptible(stream->runtime->sleep, (stream->runtime->state != SNDRV_PCM_STATE_DRAINING)); if (ret == -ERESTARTSYS) - pr_debug("wait aborted by a signal"); + pr_debug("wait aborted by a signal\n"); else if (ret) pr_debug("wait for drain failed with %d\n", ret); @@ -962,7 +962,7 @@ static int snd_compress_dev_register(struct snd_device *device) compr->card, compr->device, &snd_compr_file_ops, compr, &compr->dev); if (ret < 0) { - pr_err("snd_register_device failed\n %d", ret); + pr_err("snd_register_device failed %d\n", ret); return ret; } return ret; -- cgit v0.10.2 From b7c8c5d6927f9e6f3b4c0f8fcc99daa4568ad185 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 17 Sep 2016 01:34:33 +0000 Subject: ASoC: sti: fix missing clk_disable_unprepare() on error in uni_player_start() Fix the missing clk_disable_unprepare() before return from uni_player_start() in the error handling case. Signed-off-by: Wei Yongjun Acked-by: Arnaud Pouliquen Signed-off-by: Mark Brown diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c index 645e415..1bc8ebc 100644 --- a/sound/soc/sti/uniperif_player.c +++ b/sound/soc/sti/uniperif_player.c @@ -893,8 +893,10 @@ static int uni_player_start(struct uniperif *player) SET_UNIPERIF_SOFT_RST_SOFT_RST(player); ret = reset_player(player); - if (ret < 0) + if (ret < 0) { + clk_disable_unprepare(player->clk); return ret; + } /* * Does not use IEC61937 features of the uniperipheral hardware. -- cgit v0.10.2 From b2233d97a0e64aa1f0557ffb409c957748ae7f3a Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:21 +0200 Subject: ALSA: line6: Enable different number of URBs for frame transfers This basically changes LINE6_ISO_BUFFERS constant to a configurable iso_buffers property. Signed-off-by: Andrej Krutak Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c index f518fbb..c2808a0 100644 --- a/sound/usb/line6/capture.c +++ b/sound/usb/line6/capture.c @@ -29,10 +29,10 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm) int ret; struct urb *urb_in; - index = - find_first_zero_bit(&line6pcm->in.active_urbs, LINE6_ISO_BUFFERS); + index = find_first_zero_bit(&line6pcm->in.active_urbs, + line6pcm->line6->iso_buffers); - if (index < 0 || index >= LINE6_ISO_BUFFERS) { + if (index < 0 || index >= line6pcm->line6->iso_buffers) { dev_err(line6pcm->line6->ifcdev, "no free URB found\n"); return -EINVAL; } @@ -73,7 +73,7 @@ int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm) { int ret = 0, i; - for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + for (i = 0; i < line6pcm->line6->iso_buffers; ++i) { ret = submit_audio_in_urb(line6pcm); if (ret < 0) break; @@ -154,7 +154,7 @@ static void audio_in_callback(struct urb *urb) line6pcm->in.last_frame = urb->start_frame; /* find index of URB */ - for (index = 0; index < LINE6_ISO_BUFFERS; ++index) + for (index = 0; index < line6pcm->line6->iso_buffers; ++index) if (urb == line6pcm->in.urbs[index]) break; @@ -247,8 +247,13 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm) struct usb_line6 *line6 = line6pcm->line6; int i; + line6pcm->in.urbs = kzalloc( + sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL); + if (line6pcm->in.urbs == NULL) + return -ENOMEM; + /* create audio URBs and fill in constant values: */ - for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + for (i = 0; i < line6->iso_buffers; ++i) { struct urb *urb; /* URB for audio in: */ diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 81b7da8..527c408 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -467,6 +467,7 @@ static void line6_get_interval(struct usb_line6 *line6) unsigned epnum = usb_pipeendpoint(pipe); ep = usbdev->ep_in[epnum]; + line6->iso_buffers = LINE6_ISO_BUFFERS; if (ep) { line6->interval = ep->desc.bInterval; line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index 7da643e..43dd1d0 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -111,6 +111,8 @@ struct usb_line6 { /* Interval (ms) */ int interval; + /* Number of isochronous URBs used for frame transfers */ + int iso_buffers; /* Maximum size of USB packet */ int max_packet_size; diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c index 41aa335..317ba6844 100644 --- a/sound/usb/line6/pcm.c +++ b/sound/usb/line6/pcm.c @@ -104,7 +104,7 @@ static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm, { int i; - for (i = 0; i < LINE6_ISO_BUFFERS; i++) { + for (i = 0; i < line6pcm->line6->iso_buffers; i++) { if (test_bit(i, &pcms->active_urbs)) { if (!test_and_set_bit(i, &pcms->unlink_urbs)) usb_unlink_urb(pcms->urbs[i]); @@ -124,7 +124,7 @@ static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm, do { alive = 0; - for (i = 0; i < LINE6_ISO_BUFFERS; i++) { + for (i = 0; i < line6pcm->line6->iso_buffers; i++) { if (test_bit(i, &pcms->active_urbs)) alive++; } @@ -153,7 +153,8 @@ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm, { /* Invoked multiple times in a row so allocate once only */ if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) { - pstr->buffer = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * + pstr->buffer = kmalloc(line6pcm->line6->iso_buffers * + LINE6_ISO_PACKETS * line6pcm->max_packet_size, GFP_KERNEL); if (!pstr->buffer) return -ENOMEM; @@ -434,24 +435,30 @@ static struct snd_kcontrol_new line6_controls[] = { /* Cleanup the PCM device. */ -static void cleanup_urbs(struct line6_pcm_stream *pcms) +static void cleanup_urbs(struct line6_pcm_stream *pcms, int iso_buffers) { int i; - for (i = 0; i < LINE6_ISO_BUFFERS; i++) { + /* Most likely impossible in current code... */ + if (pcms->urbs == NULL) + return; + + for (i = 0; i < iso_buffers; i++) { if (pcms->urbs[i]) { usb_kill_urb(pcms->urbs[i]); usb_free_urb(pcms->urbs[i]); } } + kfree(pcms->urbs); + pcms->urbs = NULL; } static void line6_cleanup_pcm(struct snd_pcm *pcm) { struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm); - cleanup_urbs(&line6pcm->out); - cleanup_urbs(&line6pcm->in); + cleanup_urbs(&line6pcm->out, line6pcm->line6->iso_buffers); + cleanup_urbs(&line6pcm->in, line6pcm->line6->iso_buffers); kfree(line6pcm); } diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h index 508410a..e983880 100644 --- a/sound/usb/line6/pcm.h +++ b/sound/usb/line6/pcm.h @@ -90,7 +90,7 @@ struct line6_pcm_properties { struct line6_pcm_stream { /* allocated URBs */ - struct urb *urbs[LINE6_ISO_BUFFERS]; + struct urb **urbs; /* Temporary buffer; * Since the packet size is not known in advance, this buffer is diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c index 97ed593..1380fac 100644 --- a/sound/usb/line6/playback.c +++ b/sound/usb/line6/playback.c @@ -154,10 +154,10 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL); struct urb *urb_out; - index = - find_first_zero_bit(&line6pcm->out.active_urbs, LINE6_ISO_BUFFERS); + index = find_first_zero_bit(&line6pcm->out.active_urbs, + line6pcm->line6->iso_buffers); - if (index < 0 || index >= LINE6_ISO_BUFFERS) { + if (index < 0 || index >= line6pcm->line6->iso_buffers) { dev_err(line6pcm->line6->ifcdev, "no free URB found\n"); return -EINVAL; } @@ -286,7 +286,7 @@ int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm) { int ret = 0, i; - for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + for (i = 0; i < line6pcm->line6->iso_buffers; ++i) { ret = submit_audio_out_urb(line6pcm); if (ret < 0) break; @@ -313,11 +313,11 @@ static void audio_out_callback(struct urb *urb) line6pcm->out.last_frame = urb->start_frame; /* find index of URB */ - for (index = 0; index < LINE6_ISO_BUFFERS; index++) + for (index = 0; index < line6pcm->line6->iso_buffers; index++) if (urb == line6pcm->out.urbs[index]) break; - if (index >= LINE6_ISO_BUFFERS) + if (index >= line6pcm->line6->iso_buffers) return; /* URB has been unlinked asynchronously */ for (i = 0; i < LINE6_ISO_PACKETS; i++) @@ -401,8 +401,13 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm) struct usb_line6 *line6 = line6pcm->line6; int i; + line6pcm->out.urbs = kzalloc( + sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL); + if (line6pcm->out.urbs == NULL) + return -ENOMEM; + /* create audio URBs and fill in constant values: */ - for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + for (i = 0; i < line6->iso_buffers; ++i) { struct urb *urb; /* URB for audio out: */ -- cgit v0.10.2 From 79faa2b048b23f28a24a7b232d8933cb53df95b7 Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:22 +0200 Subject: ALSA: line6: Add high-speed USB support This has two parts: * intervals_per_second setup (high speed needs 8000, instead of 1000) * iso_buffers setup (count of iso buffers depends on USB speed, 2 is not enough for high speed) Signed-off-by: Andrej Krutak Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c index c2808a0..596bc53 100644 --- a/sound/usb/line6/capture.c +++ b/sound/usb/line6/capture.c @@ -181,7 +181,15 @@ static void audio_in_callback(struct urb *urb) length += fsize; - /* the following assumes LINE6_ISO_PACKETS == 1: */ + BUILD_BUG_ON_MSG(LINE6_ISO_PACKETS != 1, + "The following code assumes LINE6_ISO_PACKETS == 1"); + /* TODO: + * Also, if iso_buffers != 2, the prev frame is almost random at + * playback side. + * This needs to be redesigned. It should be "stable", but we may + * experience sync problems on such high-speed configs. + */ + line6pcm->prev_fbuf = fbuf; line6pcm->prev_fsize = fsize; diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 527c408..14032d9 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -462,14 +462,18 @@ static void line6_destruct(struct snd_card *card) static void line6_get_interval(struct usb_line6 *line6) { struct usb_device *usbdev = line6->usbdev; - struct usb_host_endpoint *ep; - unsigned pipe = usb_rcvintpipe(usbdev, line6->properties->ep_ctrl_r); - unsigned epnum = usb_pipeendpoint(pipe); + struct usb_host_endpoint *ep = usbdev->ep_in[line6->properties->ep_ctrl_r]; - ep = usbdev->ep_in[epnum]; - line6->iso_buffers = LINE6_ISO_BUFFERS; if (ep) { line6->interval = ep->desc.bInterval; + if (usbdev->speed == USB_SPEED_LOW) { + line6->intervals_per_second = USB_LOW_INTERVALS_PER_SECOND; + line6->iso_buffers = USB_LOW_ISO_BUFFERS; + } else { + line6->intervals_per_second = USB_HIGH_INTERVALS_PER_SECOND; + line6->iso_buffers = USB_HIGH_ISO_BUFFERS; + } + line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); } else { dev_err(line6->ifcdev, @@ -559,6 +563,7 @@ int line6_probe(struct usb_interface *interface, /* query interface number */ interface_number = interface->cur_altsetting->desc.bInterfaceNumber; + /* TODO reserves the bus bandwidth even without actual transfer */ ret = usb_set_interface(usbdev, interface_number, properties->altsetting); if (ret < 0) { diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index 43dd1d0..a55eb88 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -18,7 +18,13 @@ #include "midi.h" -#define USB_INTERVALS_PER_SECOND 1000 +/* USB 1.1 speed configuration */ +#define USB_LOW_INTERVALS_PER_SECOND 1000 +#define USB_LOW_ISO_BUFFERS 2 + +/* USB 2.0+ speed configuration */ +#define USB_HIGH_INTERVALS_PER_SECOND 8000 +#define USB_HIGH_ISO_BUFFERS 16 /* Fallback USB interval and max packet size values */ #define LINE6_FALLBACK_INTERVAL 10 @@ -109,12 +115,15 @@ struct usb_line6 { /* Properties */ const struct line6_properties *properties; - /* Interval (ms) */ + /* Interval for data USB packets */ int interval; + /* ...for isochronous transfers framing */ + int intervals_per_second; + /* Number of isochronous URBs used for frame transfers */ int iso_buffers; - /* Maximum size of USB packet */ + /* Maximum size of data USB packet */ int max_packet_size; /* Device representing the USB interface */ diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h index e983880..f41e341 100644 --- a/sound/usb/line6/pcm.h +++ b/sound/usb/line6/pcm.h @@ -20,9 +20,6 @@ #include "driver.h" -/* number of URBs */ -#define LINE6_ISO_BUFFERS 2 - /* number of USB frames per URB The Line 6 Windows driver always transmits two frames per packet, but @@ -31,7 +28,9 @@ */ #define LINE6_ISO_PACKETS 1 -/* in a "full speed" device (such as the PODxt Pro) this means 1ms */ +/* in a "full speed" device (such as the PODxt Pro) this means 1ms, + * for "high speed" it's 1/8ms + */ #define LINE6_ISO_INTERVAL 1 #define LINE6_IMPULSE_DEFAULT_PERIOD 100 diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c index 1380fac..6048d0f 100644 --- a/sound/usb/line6/playback.c +++ b/sound/usb/line6/playback.c @@ -151,7 +151,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) line6pcm->properties->rates.rats[0].num_min; const int frame_factor = line6pcm->properties->rates.rats[0].den * - (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL); + (line6pcm->line6->intervals_per_second / LINE6_ISO_INTERVAL); struct urb *urb_out; index = find_first_zero_bit(&line6pcm->out.active_urbs, -- cgit v0.10.2 From 7a0f55aeeb8f1fa32a119d34ddfefc6100936692 Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:23 +0200 Subject: ALSA: line6: Support assymetrical in/out configurations Splits max_packet_size to max_packet_size_in/out (e.g. for different channel counts). Signed-off-by: Andrej Krutak Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c index 596bc53..8f96478 100644 --- a/sound/usb/line6/capture.c +++ b/sound/usb/line6/capture.c @@ -44,13 +44,13 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm) struct usb_iso_packet_descriptor *fin = &urb_in->iso_frame_desc[i]; fin->offset = urb_size; - fin->length = line6pcm->max_packet_size; - urb_size += line6pcm->max_packet_size; + fin->length = line6pcm->max_packet_size_in; + urb_size += line6pcm->max_packet_size_in; } urb_in->transfer_buffer = line6pcm->in.buffer + - index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; + index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_in; urb_in->transfer_buffer_length = urb_size; urb_in->context = line6pcm; @@ -173,10 +173,10 @@ static void audio_in_callback(struct urb *urb) fbuf = urb->transfer_buffer + fin->offset; fsize = fin->actual_length; - if (fsize > line6pcm->max_packet_size) { + if (fsize > line6pcm->max_packet_size_in) { dev_err(line6pcm->line6->ifcdev, "driver and/or device bug: packet too large (%d > %d)\n", - fsize, line6pcm->max_packet_size); + fsize, line6pcm->max_packet_size_in); } length += fsize; diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c index 317ba6844..a5a4430 100644 --- a/sound/usb/line6/pcm.c +++ b/sound/usb/line6/pcm.c @@ -146,16 +146,20 @@ get_stream(struct snd_line6_pcm *line6pcm, int direction) } /* allocate a buffer if not opened yet; - * call this in line6pcm.state_change mutex + * call this in line6pcm.state_mutex */ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm, - struct line6_pcm_stream *pstr, int type) + struct line6_pcm_stream *pstr, int direction, int type) { + const int pkt_size = + (direction == SNDRV_PCM_STREAM_PLAYBACK) ? + line6pcm->max_packet_size_out : + line6pcm->max_packet_size_in; + /* Invoked multiple times in a row so allocate once only */ if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) { pstr->buffer = kmalloc(line6pcm->line6->iso_buffers * - LINE6_ISO_PACKETS * - line6pcm->max_packet_size, GFP_KERNEL); + LINE6_ISO_PACKETS * pkt_size, GFP_KERNEL); if (!pstr->buffer) return -ENOMEM; } @@ -163,12 +167,11 @@ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm, } /* free a buffer if all streams are closed; - * call this in line6pcm.state_change mutex + * call this in line6pcm.state_mutex */ static void line6_buffer_release(struct snd_line6_pcm *line6pcm, struct line6_pcm_stream *pstr, int type) { - clear_bit(type, &pstr->opened); if (!pstr->opened) { line6_wait_clear_audio_urbs(line6pcm, pstr); @@ -195,6 +198,7 @@ static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction, else ret = line6_submit_audio_in_all_urbs(line6pcm); } + if (ret < 0) clear_bit(type, &pstr->running); spin_unlock_irqrestore(&pstr->lock, flags); @@ -290,7 +294,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type) mutex_lock(&line6pcm->state_mutex); for (dir = 0; dir < 2; dir++) { pstr = get_stream(line6pcm, dir); - ret = line6_buffer_acquire(line6pcm, pstr, type); + ret = line6_buffer_acquire(line6pcm, pstr, dir, type); if (ret < 0) goto error; if (!pstr->running) @@ -335,7 +339,8 @@ int snd_line6_hw_params(struct snd_pcm_substream *substream, struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); mutex_lock(&line6pcm->state_mutex); - ret = line6_buffer_acquire(line6pcm, pstr, LINE6_STREAM_PCM); + ret = line6_buffer_acquire(line6pcm, pstr, substream->stream, + LINE6_STREAM_PCM); if (ret < 0) goto error; @@ -530,12 +535,12 @@ int line6_init_pcm(struct usb_line6 *line6, line6pcm->volume_monitor = 255; line6pcm->line6 = line6; - /* Read and write buffers are sized identically, so choose minimum */ - line6pcm->max_packet_size = min( - usb_maxpacket(line6->usbdev, - usb_rcvisocpipe(line6->usbdev, ep_read), 0), - usb_maxpacket(line6->usbdev, - usb_sndisocpipe(line6->usbdev, ep_write), 1)); + line6pcm->max_packet_size_in = + usb_maxpacket(line6->usbdev, + usb_rcvisocpipe(line6->usbdev, ep_read), 0); + line6pcm->max_packet_size_out = + usb_maxpacket(line6->usbdev, + usb_sndisocpipe(line6->usbdev, ep_write), 1); spin_lock_init(&line6pcm->out.lock); spin_lock_init(&line6pcm->in.lock); diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h index f41e341..f040c81 100644 --- a/sound/usb/line6/pcm.h +++ b/sound/usb/line6/pcm.h @@ -156,11 +156,12 @@ struct snd_line6_pcm { /* Previously captured frame (for software monitoring) */ unsigned char *prev_fbuf; - /* Size of previously captured frame (for software monitoring) */ + /* Size of previously captured frame (for software monitoring/sync) */ int prev_fsize; /* Maximum size of USB packet */ - int max_packet_size; + int max_packet_size_in; + int max_packet_size_out; /* PCM playback volume (left and right) */ int volume_playback[2]; diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c index 6048d0f..08bacf3 100644 --- a/sound/usb/line6/playback.c +++ b/sound/usb/line6/playback.c @@ -195,7 +195,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) urb_frames = urb_size / bytes_per_frame; urb_out->transfer_buffer = line6pcm->out.buffer + - index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; + index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_out; urb_out->transfer_buffer_length = urb_size; urb_out->context = line6pcm; -- cgit v0.10.2 From 97d78acfb870a67339957e9c4d36dc03242df315 Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:24 +0200 Subject: ALSA: line6: Allow different channel numbers for in/out Changes bytes_per_frame to bytes_per_channel. Signed-off-by: Andrej Krutak Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c index 8f96478..0228cb4 100644 --- a/sound/usb/line6/capture.c +++ b/sound/usb/line6/capture.c @@ -90,7 +90,9 @@ void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize) struct snd_pcm_substream *substream = get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE); struct snd_pcm_runtime *runtime = substream->runtime; - const int bytes_per_frame = line6pcm->properties->bytes_per_frame; + const int bytes_per_frame = + line6pcm->properties->bytes_per_channel * + line6pcm->properties->capture_hw.channels_max; int frames = fsize / bytes_per_frame; if (runtime == NULL) @@ -191,7 +193,9 @@ static void audio_in_callback(struct urb *urb) */ line6pcm->prev_fbuf = fbuf; - line6pcm->prev_fsize = fsize; + line6pcm->prev_fsize = fsize / + (line6pcm->properties->bytes_per_channel * + line6pcm->properties->capture_hw.channels_max); if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) && test_bit(LINE6_STREAM_PCM, &line6pcm->in.running) && diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index a55eb88..2d32139 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -31,7 +31,7 @@ #define LINE6_FALLBACK_MAXPACKETSIZE 16 #define LINE6_TIMEOUT 1 -#define LINE6_BUFSIZE_LISTEN 32 +#define LINE6_BUFSIZE_LISTEN 64 #define LINE6_MESSAGE_MAXLEN 256 /* diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h index f040c81..67fda31 100644 --- a/sound/usb/line6/pcm.h +++ b/sound/usb/line6/pcm.h @@ -84,7 +84,7 @@ enum { struct line6_pcm_properties { struct snd_pcm_hardware playback_hw, capture_hw; struct snd_pcm_hw_constraint_ratdens rates; - int bytes_per_frame; + int bytes_per_channel; }; struct line6_pcm_stream { diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c index 08bacf3..812d181 100644 --- a/sound/usb/line6/playback.c +++ b/sound/usb/line6/playback.c @@ -146,7 +146,9 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) int index; int i, urb_size, urb_frames; int ret; - const int bytes_per_frame = line6pcm->properties->bytes_per_frame; + const int bytes_per_frame = + line6pcm->properties->bytes_per_channel * + line6pcm->properties->playback_hw.channels_max; const int frame_increment = line6pcm->properties->rates.rats[0].num_min; const int frame_factor = @@ -165,6 +167,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) urb_out = line6pcm->out.urbs[index]; urb_size = 0; + /* TODO: this may not work for LINE6_ISO_PACKETS != 1 */ for (i = 0; i < LINE6_ISO_PACKETS; ++i) { /* compute frame size for given sampling rate */ int fsize = 0; @@ -178,9 +181,11 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) line6pcm->out.count += frame_increment; n = line6pcm->out.count / frame_factor; line6pcm->out.count -= n * frame_factor; - fsize = n * bytes_per_frame; + fsize = n; } + fsize *= bytes_per_frame; + fout->offset = urb_size; fout->length = fsize; urb_size += fsize; @@ -305,6 +310,9 @@ static void audio_out_callback(struct urb *urb) struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context; struct snd_pcm_substream *substream = get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK); + const int bytes_per_frame = + line6pcm->properties->bytes_per_channel * + line6pcm->properties->playback_hw.channels_max; #if USE_CLEAR_BUFFER_WORKAROUND memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); @@ -329,7 +337,7 @@ static void audio_out_callback(struct urb *urb) struct snd_pcm_runtime *runtime = substream->runtime; line6pcm->out.pos_done += - length / line6pcm->properties->bytes_per_frame; + length / bytes_per_frame; if (line6pcm->out.pos_done >= runtime->buffer_size) line6pcm->out.pos_done -= runtime->buffer_size; diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c index 45dd348..36e7274 100644 --- a/sound/usb/line6/pod.c +++ b/sound/usb/line6/pod.c @@ -83,7 +83,6 @@ struct usb_line6_pod { }; #define POD_SYSEX_CODE 3 -#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ /* *INDENT-OFF* */ @@ -167,7 +166,7 @@ static struct line6_pcm_properties pod_pcm_properties = { .rates = { .nrats = 1, .rats = &pod_ratden}, - .bytes_per_frame = POD_BYTES_PER_FRAME + .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */ }; static const char pod_version_header[] = { diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 63dcaef..4fc4789 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -25,8 +25,6 @@ enum { LINE6_PODHD500_1, }; -#define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ - static struct snd_ratden podhd_ratden = { .num_min = 48000, .num_max = 48000, @@ -73,7 +71,7 @@ static struct line6_pcm_properties podhd_pcm_properties = { .rates = { .nrats = 1, .rats = &podhd_ratden}, - .bytes_per_frame = PODHD_BYTES_PER_FRAME + .bytes_per_channel = 3 /* 24bit audio (stereo) */ }; /* diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c index 6d4c50c..da76e03 100644 --- a/sound/usb/line6/toneport.c +++ b/sound/usb/line6/toneport.c @@ -114,7 +114,7 @@ static struct line6_pcm_properties toneport_pcm_properties = { .rates = { .nrats = 1, .rats = &toneport_ratden}, - .bytes_per_frame = 4 + .bytes_per_channel = 2 }; static const struct { -- cgit v0.10.2 From f56742cc41895b1ed3742406dc3587b0d6424acb Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:25 +0200 Subject: ALSA: line6: Add LINE6_CAP_IN_NEEDS_OUT, a void playback stream during capture E.g. POD X3 seems to require playback data to be sent to it to generate capture data. Otherwise the device stalls and doesn't send any more capture data until it's reset. Signed-off-by: Andrej Krutak Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c index 0228cb4..7c81256 100644 --- a/sound/usb/line6/capture.c +++ b/sound/usb/line6/capture.c @@ -232,6 +232,8 @@ static int snd_line6_capture_open(struct snd_pcm_substream *substream) if (err < 0) return err; + line6_pcm_acquire(line6pcm, LINE6_STREAM_CAPTURE_HELPER, false); + runtime->hw = line6pcm->properties->capture_hw; return 0; } @@ -239,6 +241,9 @@ static int snd_line6_capture_open(struct snd_pcm_substream *substream) /* close capture callback */ static int snd_line6_capture_close(struct snd_pcm_substream *substream) { + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + + line6_pcm_release(line6pcm, LINE6_STREAM_CAPTURE_HELPER); return 0; } diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index 2d32139..0bcab38 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -100,8 +100,10 @@ enum { LINE6_CAP_CONTROL = 1 << 0, /* device supports PCM input/output via USB */ LINE6_CAP_PCM = 1 << 1, - /* device support hardware monitoring */ + /* device supports hardware monitoring */ LINE6_CAP_HWMON = 1 << 2, + /* device requires output data when input is read */ + LINE6_CAP_IN_NEEDS_OUT = 1 << 3, }; /* diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c index a5a4430..fab53f5 100644 --- a/sound/usb/line6/pcm.c +++ b/sound/usb/line6/pcm.c @@ -52,7 +52,7 @@ static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol, line6pcm->impulse_volume = value; if (value > 0) { - err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE); + err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE, true); if (err < 0) { line6pcm->impulse_volume = 0; return err; @@ -242,6 +242,14 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: + if (s->stream == SNDRV_PCM_STREAM_CAPTURE && + (line6pcm->line6->properties->capabilities & + LINE6_CAP_IN_NEEDS_OUT)) { + err = line6_stream_start(line6pcm, SNDRV_PCM_STREAM_PLAYBACK, + LINE6_STREAM_CAPTURE_HELPER); + if (err < 0) + return err; + } err = line6_stream_start(line6pcm, s->stream, LINE6_STREAM_PCM); if (err < 0) @@ -250,6 +258,12 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: + if (s->stream == SNDRV_PCM_STREAM_CAPTURE && + (line6pcm->line6->properties->capabilities & + LINE6_CAP_IN_NEEDS_OUT)) { + line6_stream_stop(line6pcm, SNDRV_PCM_STREAM_PLAYBACK, + LINE6_STREAM_CAPTURE_HELPER); + } line6_stream_stop(line6pcm, s->stream, LINE6_STREAM_PCM); break; @@ -283,14 +297,15 @@ snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream) return pstr->pos_done; } -/* Acquire and start duplex streams: +/* Acquire and optionally start duplex streams: * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR */ -int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type) +int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, bool start) { struct line6_pcm_stream *pstr; int ret = 0, dir; + /* TODO: We should assert SNDRV_PCM_STREAM_PLAYBACK/CAPTURE == 0/1 */ mutex_lock(&line6pcm->state_mutex); for (dir = 0; dir < 2; dir++) { pstr = get_stream(line6pcm, dir); @@ -300,10 +315,12 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type) if (!pstr->running) line6_wait_clear_audio_urbs(line6pcm, pstr); } - for (dir = 0; dir < 2; dir++) { - ret = line6_stream_start(line6pcm, dir, type); - if (ret < 0) - goto error; + if (start) { + for (dir = 0; dir < 2; dir++) { + ret = line6_stream_start(line6pcm, dir, type); + if (ret < 0) + goto error; + } } error: mutex_unlock(&line6pcm->state_mutex); diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h index 67fda31..bb0c9cb 100644 --- a/sound/usb/line6/pcm.h +++ b/sound/usb/line6/pcm.h @@ -73,6 +73,7 @@ enum { LINE6_STREAM_PCM, LINE6_STREAM_MONITOR, LINE6_STREAM_IMPULSE, + LINE6_STREAM_CAPTURE_HELPER, }; /* misc bit flags for PCM operation */ @@ -191,7 +192,8 @@ extern int snd_line6_hw_params(struct snd_pcm_substream *substream, extern int snd_line6_hw_free(struct snd_pcm_substream *substream); extern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream); extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); -extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type); +extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, + bool start); extern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type); #endif diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c index da76e03..8e22f43 100644 --- a/sound/usb/line6/toneport.c +++ b/sound/usb/line6/toneport.c @@ -177,7 +177,7 @@ static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol, line6pcm->volume_monitor = ucontrol->value.integer.value[0]; if (line6pcm->volume_monitor > 0) { - err = line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR); + err = line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR, true); if (err < 0) { line6pcm->volume_monitor = 0; line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR); @@ -246,7 +246,7 @@ static void toneport_start_pcm(unsigned long arg) struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg; struct usb_line6 *line6 = &toneport->line6; - line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR); + line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR, true); } /* control definition */ -- cgit v0.10.2 From 174e1fc0bff5e0bbdf5eb0cbf1b8c0d64a0f38d2 Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:26 +0200 Subject: ALSA: line6: Distinguish device init (ctrl EP) and MIDI data transfer (int EP) POD X3 can initialize similarly to older PODs, but it doesn't have the MIDI interface. Instead, configuration is done via proprietary bulk EP messages. Signed-off-by: Andrej Krutak Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 14032d9..9b16777 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -66,10 +66,17 @@ static int line6_start_listen(struct usb_line6 *line6) { int err; - usb_fill_int_urb(line6->urb_listen, line6->usbdev, - usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r), - line6->buffer_listen, LINE6_BUFSIZE_LISTEN, - line6_data_received, line6, line6->interval); + if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + usb_fill_int_urb(line6->urb_listen, line6->usbdev, + usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r), + line6->buffer_listen, LINE6_BUFSIZE_LISTEN, + line6_data_received, line6, line6->interval); + } else { + usb_fill_bulk_urb(line6->urb_listen, line6->usbdev, + usb_rcvbulkpipe(line6->usbdev, line6->properties->ep_ctrl_r), + line6->buffer_listen, LINE6_BUFSIZE_LISTEN, + line6_data_received, line6); + } line6->urb_listen->actual_length = 0; err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC); return err; @@ -90,6 +97,7 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, int size) { int i, done = 0; + const struct line6_properties *properties = line6->properties; for (i = 0; i < size; i += line6->max_packet_size) { int partial; @@ -97,15 +105,21 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, int frag_size = min(line6->max_packet_size, size - i); int retval; - retval = usb_interrupt_msg(line6->usbdev, - usb_sndintpipe(line6->usbdev, - line6->properties->ep_ctrl_w), - (char *)frag_buf, frag_size, - &partial, LINE6_TIMEOUT * HZ); + if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + retval = usb_interrupt_msg(line6->usbdev, + usb_sndintpipe(line6->usbdev, properties->ep_ctrl_w), + (char *)frag_buf, frag_size, + &partial, LINE6_TIMEOUT * HZ); + } else { + retval = usb_bulk_msg(line6->usbdev, + usb_sndbulkpipe(line6->usbdev, properties->ep_ctrl_w), + (char *)frag_buf, frag_size, + &partial, LINE6_TIMEOUT * HZ); + } if (retval) { dev_err(line6->ifcdev, - "usb_interrupt_msg failed (%d)\n", retval); + "usb_bulk_msg failed (%d)\n", retval); break; } @@ -140,10 +154,17 @@ static int line6_send_raw_message_async_part(struct message *msg, int done = msg->done; int bytes = min(msg->size - done, line6->max_packet_size); - usb_fill_int_urb(urb, line6->usbdev, - usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w), - (char *)msg->buffer + done, bytes, - line6_async_request_sent, msg, line6->interval); + if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + usb_fill_int_urb(urb, line6->usbdev, + usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w), + (char *)msg->buffer + done, bytes, + line6_async_request_sent, msg, line6->interval); + } else { + usb_fill_bulk_urb(urb, line6->usbdev, + usb_sndbulkpipe(line6->usbdev, line6->properties->ep_ctrl_w), + (char *)msg->buffer + done, bytes, + line6_async_request_sent, msg); + } msg->done += bytes; retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -462,7 +483,18 @@ static void line6_destruct(struct snd_card *card) static void line6_get_interval(struct usb_line6 *line6) { struct usb_device *usbdev = line6->usbdev; - struct usb_host_endpoint *ep = usbdev->ep_in[line6->properties->ep_ctrl_r]; + const struct line6_properties *properties = line6->properties; + int pipe; + struct usb_host_endpoint *ep; + + if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + pipe = + usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r); + } else { + pipe = + usb_rcvbulkpipe(line6->usbdev, line6->properties->ep_ctrl_r); + } + ep = usbdev->ep_in[usb_pipeendpoint(pipe)]; if (ep) { line6->interval = ep->desc.bInterval; @@ -483,7 +515,7 @@ static void line6_get_interval(struct usb_line6 *line6) } } -static int line6_init_cap_control(struct usb_line6 *line6) +static int line6_init_cap_control_midi(struct usb_line6 *line6) { int ret; @@ -573,8 +605,8 @@ int line6_probe(struct usb_interface *interface, line6_get_interval(line6); - if (properties->capabilities & LINE6_CAP_CONTROL) { - ret = line6_init_cap_control(line6); + if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + ret = line6_init_cap_control_midi(line6); if (ret < 0) goto error; } @@ -644,7 +676,7 @@ int line6_suspend(struct usb_interface *interface, pm_message_t message) snd_power_change_state(line6->card, SNDRV_CTL_POWER_D3hot); - if (line6->properties->capabilities & LINE6_CAP_CONTROL) + if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) line6_stop_listen(line6); if (line6pcm != NULL) { @@ -663,7 +695,7 @@ int line6_resume(struct usb_interface *interface) { struct usb_line6 *line6 = usb_get_intfdata(interface); - if (line6->properties->capabilities & LINE6_CAP_CONTROL) + if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) line6_start_listen(line6); snd_power_change_state(line6->card, SNDRV_CTL_POWER_D0); diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index 0bcab38..d48c7d2 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -104,6 +104,8 @@ enum { LINE6_CAP_HWMON = 1 << 2, /* device requires output data when input is read */ LINE6_CAP_IN_NEEDS_OUT = 1 << 3, + /* device uses raw MIDI via USB (data endpoints) */ + LINE6_CAP_CONTROL_MIDI = 1 << 4, }; /* @@ -142,10 +144,10 @@ struct usb_line6 { /* Line 6 MIDI device data structure */ struct snd_line6_midi *line6midi; - /* URB for listening to PODxt Pro control endpoint */ + /* URB for listening to POD data endpoint */ struct urb *urb_listen; - /* Buffer for listening to PODxt Pro control endpoint */ + /* Buffer for listening to POD data endpoint */ unsigned char *buffer_listen; /* Buffer for message to be processed */ diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c index 36e7274..17aa616 100644 --- a/sound/usb/line6/pod.c +++ b/sound/usb/line6/pod.c @@ -475,6 +475,7 @@ static const struct line6_properties pod_properties_table[] = { .id = "BassPODxt", .name = "BassPODxt", .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 5, @@ -487,6 +488,7 @@ static const struct line6_properties pod_properties_table[] = { .id = "BassPODxtLive", .name = "BassPODxt Live", .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 1, @@ -499,6 +501,7 @@ static const struct line6_properties pod_properties_table[] = { .id = "BassPODxtPro", .name = "BassPODxt Pro", .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 5, @@ -510,7 +513,8 @@ static const struct line6_properties pod_properties_table[] = { [LINE6_POCKETPOD] = { .id = "PocketPOD", .name = "Pocket POD", - .capabilities = LINE6_CAP_CONTROL, + .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI, .altsetting = 0, .ep_ctrl_r = 0x82, .ep_ctrl_w = 0x02, @@ -520,6 +524,7 @@ static const struct line6_properties pod_properties_table[] = { .id = "PODxt", .name = "PODxt", .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 5, @@ -532,6 +537,7 @@ static const struct line6_properties pod_properties_table[] = { .id = "PODxtLive", .name = "PODxt Live", .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 1, @@ -544,6 +550,7 @@ static const struct line6_properties pod_properties_table[] = { .id = "PODxtPro", .name = "PODxt Pro", .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 5, diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c index ddc23dd..0c4512d 100644 --- a/sound/usb/line6/variax.c +++ b/sound/usb/line6/variax.c @@ -259,7 +259,8 @@ static const struct line6_properties variax_properties_table[] = { [LINE6_PODXTLIVE_VARIAX] = { .id = "PODxtLive", .name = "PODxt Live", - .capabilities = LINE6_CAP_CONTROL, + .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI, .altsetting = 1, .ep_ctrl_r = 0x86, .ep_ctrl_w = 0x05, @@ -269,7 +270,8 @@ static const struct line6_properties variax_properties_table[] = { [LINE6_VARIAX] = { .id = "Variax", .name = "Variax Workbench", - .capabilities = LINE6_CAP_CONTROL, + .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI, .altsetting = 1, .ep_ctrl_r = 0x82, .ep_ctrl_w = 0x01, -- cgit v0.10.2 From 7811a3ad18ac1477976224cc2e8607654870edfc Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:27 +0200 Subject: ALSA: line6: Allow processing of raw incoming messages Not all PODs use MIDI via USB data interface, thus allow avoiding that code and instead using direct processing. Signed-off-by: Andrej Krutak Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 9b16777..853a143 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -290,26 +290,31 @@ static void line6_data_received(struct urb *urb) if (urb->status == -ESHUTDOWN) return; - done = - line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length); + if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + done = + line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length); - if (done < urb->actual_length) { - line6_midibuf_ignore(mb, done); - dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n", - done, urb->actual_length); - } + if (done < urb->actual_length) { + line6_midibuf_ignore(mb, done); + dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n", + done, urb->actual_length); + } - for (;;) { - done = - line6_midibuf_read(mb, line6->buffer_message, - LINE6_MESSAGE_MAXLEN); + for (;;) { + done = + line6_midibuf_read(mb, line6->buffer_message, + LINE6_MESSAGE_MAXLEN); - if (done == 0) - break; + if (done == 0) + break; - line6->message_length = done; - line6_midi_receive(line6, line6->buffer_message, done); + line6->message_length = done; + line6_midi_receive(line6, line6->buffer_message, done); + if (line6->process_message) + line6->process_message(line6); + } + } else { if (line6->process_message) line6->process_message(line6); } @@ -469,7 +474,9 @@ static void line6_destruct(struct snd_card *card) struct usb_device *usbdev = line6->usbdev; /* free buffer memory first: */ - kfree(line6->buffer_message); + if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) + kfree(line6->buffer_message); + kfree(line6->buffer_listen); /* then free URBs: */ @@ -515,7 +522,7 @@ static void line6_get_interval(struct usb_line6 *line6) } } -static int line6_init_cap_control_midi(struct usb_line6 *line6) +static int line6_init_cap_control(struct usb_line6 *line6) { int ret; @@ -524,14 +531,16 @@ static int line6_init_cap_control_midi(struct usb_line6 *line6) if (!line6->buffer_listen) return -ENOMEM; - line6->buffer_message = kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL); - if (!line6->buffer_message) - return -ENOMEM; - line6->urb_listen = usb_alloc_urb(0, GFP_KERNEL); if (!line6->urb_listen) return -ENOMEM; + if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + line6->buffer_message = kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL); + if (!line6->buffer_message) + return -ENOMEM; + } + ret = line6_start_listen(line6); if (ret < 0) { dev_err(line6->ifcdev, "cannot start listening: %d\n", ret); @@ -605,8 +614,8 @@ int line6_probe(struct usb_interface *interface, line6_get_interval(line6); - if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) { - ret = line6_init_cap_control_midi(line6); + if (properties->capabilities & LINE6_CAP_CONTROL) { + ret = line6_init_cap_control(line6); if (ret < 0) goto error; } @@ -676,7 +685,7 @@ int line6_suspend(struct usb_interface *interface, pm_message_t message) snd_power_change_state(line6->card, SNDRV_CTL_POWER_D3hot); - if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) + if (line6->properties->capabilities & LINE6_CAP_CONTROL) line6_stop_listen(line6); if (line6pcm != NULL) { @@ -695,7 +704,7 @@ int line6_resume(struct usb_interface *interface) { struct usb_line6 *line6 = usb_get_intfdata(interface); - if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) + if (line6->properties->capabilities & LINE6_CAP_CONTROL) line6_start_listen(line6); snd_power_change_state(line6->card, SNDRV_CTL_POWER_D0); diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index d48c7d2..88cf1e7 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -147,15 +147,18 @@ struct usb_line6 { /* URB for listening to POD data endpoint */ struct urb *urb_listen; - /* Buffer for listening to POD data endpoint */ + /* Buffer for incoming data from POD data endpoint */ unsigned char *buffer_listen; - /* Buffer for message to be processed */ + /* Buffer for message to be processed, generated from MIDI layer */ unsigned char *buffer_message; - /* Length of message to be processed */ + /* Length of message to be processed, generated from MIDI layer */ int message_length; + /* If MIDI is supported, buffer_message contains the pre-processed data; + * otherwise the data is only in urb_listen (buffer_incoming). + */ void (*process_message)(struct usb_line6 *); void (*disconnect)(struct usb_line6 *line6); }; diff --git a/sound/usb/line6/midi.c b/sound/usb/line6/midi.c index cebea9b..d0fb2f2 100644 --- a/sound/usb/line6/midi.c +++ b/sound/usb/line6/midi.c @@ -258,7 +258,7 @@ int line6_init_midi(struct usb_line6 *line6) struct snd_rawmidi *rmidi; struct snd_line6_midi *line6midi; - if (!(line6->properties->capabilities & LINE6_CAP_CONTROL)) { + if (!(line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI)) { /* skip MIDI initialization and report success */ return 0; } -- cgit v0.10.2 From 790869dacc3d8d4de318905eef32b1f603d02cac Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:28 +0200 Subject: ALSA: line6: Add support for POD X3 This includes audio in/out and basic initialization via control EP (emulates what original driver does). The initialization is done similarly to original POD, firmware and serial IDs are read and exported via sysfs. Signed-off-by: Andrej Krutak Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/Kconfig b/sound/usb/line6/Kconfig index f4585d37..8ffcf48 100644 --- a/sound/usb/line6/Kconfig +++ b/sound/usb/line6/Kconfig @@ -21,10 +21,10 @@ config SND_USB_POD re-amping) config SND_USB_PODHD - tristate "Line 6 POD HD300/400/500 USB support" + tristate "Line 6 POD X3/HD300/400/500 USB support" select SND_USB_LINE6 help - This is a driver for POD HD300, 400 and 500 devices. + This is a driver for POD X3, HD300, 400 and 500 devices. config SND_USB_TONEPORT tristate "TonePort GX, UX1 and UX2 USB support" diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 4fc4789..61c2ff1 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -2,6 +2,7 @@ * Line 6 Pod HD * * Copyright (C) 2011 Stefan Hajnoczi + * Copyright (C) 2015 Andrej Krutak * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,11 +19,44 @@ #include "driver.h" #include "pcm.h" +#define PODHD_STARTUP_DELAY 500 + +/* + * Stages of POD startup procedure + */ +enum { + PODHD_STARTUP_INIT = 1, + PODHD_STARTUP_SCHEDULE_WORKQUEUE, + PODHD_STARTUP_SETUP, + PODHD_STARTUP_LAST = PODHD_STARTUP_SETUP - 1 +}; + enum { LINE6_PODHD300, LINE6_PODHD400, LINE6_PODHD500_0, LINE6_PODHD500_1, + LINE6_PODX3, +}; + +struct usb_line6_podhd { + /* Generic Line 6 USB data */ + struct usb_line6 line6; + + /* Timer for device initialization */ + struct timer_list startup_timer; + + /* Work handler for device initialization */ + struct work_struct startup_work; + + /* Current progress in startup procedure */ + int startup_progress; + + /* Serial number of device */ + u32 serial_number; + + /* Firmware version */ + int firmware_version; }; static struct snd_ratden podhd_ratden = { @@ -71,9 +105,196 @@ static struct line6_pcm_properties podhd_pcm_properties = { .rates = { .nrats = 1, .rats = &podhd_ratden}, - .bytes_per_channel = 3 /* 24bit audio (stereo) */ + .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */ }; +static struct line6_pcm_properties podx3_pcm_properties = { + .playback_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 60000, + .period_bytes_min = 64, + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 1024}, + .capture_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + /* 1+2: Main signal (out), 3+4: Tone 1, + * 5+6: Tone 2, 7+8: raw + */ + .channels_min = 8, + .channels_max = 8, + .buffer_bytes_max = 60000, + .period_bytes_min = 64, + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 1024}, + .rates = { + .nrats = 1, + .rats = &podhd_ratden}, + .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */ +}; + +static void podhd_startup_start_workqueue(unsigned long data); +static void podhd_startup_workqueue(struct work_struct *work); +static int podhd_startup_finalize(struct usb_line6_podhd *pod); + +static ssize_t serial_number_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct snd_card *card = dev_to_snd_card(dev); + struct usb_line6_podhd *pod = card->private_data; + + return sprintf(buf, "%u\n", pod->serial_number); +} + +static ssize_t firmware_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct snd_card *card = dev_to_snd_card(dev); + struct usb_line6_podhd *pod = card->private_data; + + return sprintf(buf, "%06x\n", pod->firmware_version); +} + +static DEVICE_ATTR_RO(firmware_version); +static DEVICE_ATTR_RO(serial_number); + +static struct attribute *podhd_dev_attrs[] = { + &dev_attr_firmware_version.attr, + &dev_attr_serial_number.attr, + NULL +}; + +static const struct attribute_group podhd_dev_attr_group = { + .name = "podhd", + .attrs = podhd_dev_attrs, +}; + +/* + * POD X3 startup procedure. + * + * May be compatible with other POD HD's, since it's also similar to the + * previous POD setup. In any case, it doesn't seem to be required for the + * audio nor bulk interfaces to work. + */ + +static void podhd_startup(struct usb_line6_podhd *pod) +{ + CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_INIT); + + /* delay startup procedure: */ + line6_start_timer(&pod->startup_timer, PODHD_STARTUP_DELAY, + podhd_startup_start_workqueue, (unsigned long)pod); +} + +static void podhd_startup_start_workqueue(unsigned long data) +{ + struct usb_line6_podhd *pod = (struct usb_line6_podhd *)data; + + CHECK_STARTUP_PROGRESS(pod->startup_progress, + PODHD_STARTUP_SCHEDULE_WORKQUEUE); + + /* schedule work for global work queue: */ + schedule_work(&pod->startup_work); +} + +static int podhd_dev_start(struct usb_line6_podhd *pod) +{ + int ret; + u8 init_bytes[8]; + int i; + struct usb_device *usbdev = pod->line6.usbdev; + + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), + 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + 0x11, 0, + NULL, 0, LINE6_TIMEOUT * HZ); + if (ret < 0) { + dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret); + return ret; + } + + /* NOTE: looks like some kind of ping message */ + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x11, 0x0, + &init_bytes, 3, LINE6_TIMEOUT * HZ); + if (ret < 0) { + dev_err(pod->line6.ifcdev, + "receive length failed (error %d)\n", ret); + return ret; + } + + pod->firmware_version = + (init_bytes[0] << 16) | (init_bytes[1] << 8) | (init_bytes[2] << 0); + + for (i = 0; i <= 16; i++) { + ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8); + if (ret < 0) + return ret; + } + + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), + USB_REQ_SET_FEATURE, + USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT, + 1, 0, + NULL, 0, LINE6_TIMEOUT * HZ); + if (ret < 0) + return ret; + + return 0; +} + +static void podhd_startup_workqueue(struct work_struct *work) +{ + struct usb_line6_podhd *pod = + container_of(work, struct usb_line6_podhd, startup_work); + + CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_SETUP); + + podhd_dev_start(pod); + line6_read_serial_number(&pod->line6, &pod->serial_number); + + podhd_startup_finalize(pod); +} + +static int podhd_startup_finalize(struct usb_line6_podhd *pod) +{ + struct usb_line6 *line6 = &pod->line6; + + /* ALSA audio interface: */ + return snd_card_register(line6->card); +} + +static void podhd_disconnect(struct usb_line6 *line6) +{ + struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6; + + if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { + del_timer_sync(&pod->startup_timer); + cancel_work_sync(&pod->startup_work); + } +} + /* Try to init POD HD device. */ @@ -81,6 +302,16 @@ static int podhd_init(struct usb_line6 *line6, const struct usb_device_id *id) { int err; + struct usb_line6_podhd *pod = (struct usb_line6_podhd *) line6; + + line6->disconnect = podhd_disconnect; + + if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { + /* create sysfs entries: */ + err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group); + if (err < 0) + return err; + } /* initialize MIDI subsystem: */ err = line6_init_midi(line6); @@ -88,12 +319,22 @@ static int podhd_init(struct usb_line6 *line6, return err; /* initialize PCM subsystem: */ - err = line6_init_pcm(line6, &podhd_pcm_properties); + err = line6_init_pcm(line6, + (id->driver_info == LINE6_PODX3) ? &podx3_pcm_properties : + &podhd_pcm_properties); if (err < 0) return err; - /* register USB audio system: */ - return snd_card_register(line6->card); + if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL)) { + /* register USB audio system directly */ + return podhd_startup_finalize(pod); + } + + /* init device and delay registering */ + init_timer(&pod->startup_timer); + INIT_WORK(&pod->startup_work, podhd_startup_workqueue); + podhd_startup(pod); + return 0; } #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod) @@ -101,10 +342,12 @@ static int podhd_init(struct usb_line6 *line6, /* table of devices that work with this driver */ static const struct usb_device_id podhd_id_table[] = { + /* TODO: no need to alloc data interfaces when only audio is used */ { LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 }, { LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 }, { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 }, { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 }, + { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 }, {} }; @@ -114,8 +357,7 @@ static const struct line6_properties podhd_properties_table[] = { [LINE6_PODHD300] = { .id = "PODHD300", .name = "POD HD300", - .capabilities = LINE6_CAP_CONTROL - | LINE6_CAP_PCM + .capabilities = LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 5, .ep_ctrl_r = 0x84, @@ -126,8 +368,7 @@ static const struct line6_properties podhd_properties_table[] = { [LINE6_PODHD400] = { .id = "PODHD400", .name = "POD HD400", - .capabilities = LINE6_CAP_CONTROL - | LINE6_CAP_PCM + .capabilities = LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 5, .ep_ctrl_r = 0x84, @@ -138,8 +379,7 @@ static const struct line6_properties podhd_properties_table[] = { [LINE6_PODHD500_0] = { .id = "PODHD500", .name = "POD HD500", - .capabilities = LINE6_CAP_CONTROL - | LINE6_CAP_PCM + .capabilities = LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 1, .ep_ctrl_r = 0x81, @@ -150,8 +390,7 @@ static const struct line6_properties podhd_properties_table[] = { [LINE6_PODHD500_1] = { .id = "PODHD500", .name = "POD HD500", - .capabilities = LINE6_CAP_CONTROL - | LINE6_CAP_PCM + .capabilities = LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 1, .ep_ctrl_r = 0x81, @@ -159,6 +398,17 @@ static const struct line6_properties podhd_properties_table[] = { .ep_audio_r = 0x86, .ep_audio_w = 0x02, }, + [LINE6_PODX3] = { + .id = "PODX3", + .name = "POD X3", + .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, + .altsetting = 1, + .ep_ctrl_r = 0x81, + .ep_ctrl_w = 0x01, + .ep_audio_r = 0x86, + .ep_audio_w = 0x02, + }, }; /* @@ -169,7 +419,7 @@ static int podhd_probe(struct usb_interface *interface, { return line6_probe(interface, id, "Line6-PODHD", &podhd_properties_table[id->driver_info], - podhd_init, sizeof(struct usb_line6)); + podhd_init, sizeof(struct usb_line6_podhd)); } static struct usb_driver podhd_driver = { -- cgit v0.10.2 From c039aaa77a7d1d9375665a8b59ec16dc7d23e259 Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:29 +0200 Subject: ALSA: line6: Add support for POD X3 Live (only USB ID differs from POD X3) Signed-off-by: Andrej Krutak Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 61c2ff1..4bacbf7 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -37,6 +37,7 @@ enum { LINE6_PODHD500_0, LINE6_PODHD500_1, LINE6_PODX3, + LINE6_PODX3LIVE }; struct usb_line6_podhd { @@ -348,6 +349,7 @@ static const struct usb_device_id podhd_id_table[] = { { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 }, { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 }, { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 }, + { LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE }, {} }; @@ -409,6 +411,17 @@ static const struct line6_properties podhd_properties_table[] = { .ep_audio_r = 0x86, .ep_audio_w = 0x02, }, + [LINE6_PODX3LIVE] = { + .id = "PODX3LIVE", + .name = "POD X3 LIVE", + .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, + .altsetting = 1, + .ep_ctrl_r = 0x81, + .ep_ctrl_w = 0x01, + .ep_audio_r = 0x86, + .ep_audio_w = 0x02, + }, }; /* -- cgit v0.10.2 From f6a0dd107ad0c8b59d1c9735eea4b8cb9f460949 Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:30 +0200 Subject: ALSA: line6: Only determine control port properties if needed Not all line6 devices use the control port. Signed-off-by: Andrej Krutak Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 853a143..8a71d45 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -612,9 +612,8 @@ int line6_probe(struct usb_interface *interface, goto error; } - line6_get_interval(line6); - if (properties->capabilities & LINE6_CAP_CONTROL) { + line6_get_interval(line6); ret = line6_init_cap_control(line6); if (ret < 0) goto error; -- cgit v0.10.2 From cfa769695d2bc50b729db6a5973398b24d126c79 Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:31 +0200 Subject: ALSA: line6: Cleanup podhd initialization Only initialize PCM for POD HD devices that support it. No POD HD seems to support MIDI, thus drop the initialization. Signed-off-by: Andrej Krutak Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 4bacbf7..9352a44 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -314,17 +314,14 @@ static int podhd_init(struct usb_line6 *line6, return err; } - /* initialize MIDI subsystem: */ - err = line6_init_midi(line6); - if (err < 0) - return err; - - /* initialize PCM subsystem: */ - err = line6_init_pcm(line6, - (id->driver_info == LINE6_PODX3) ? &podx3_pcm_properties : - &podhd_pcm_properties); - if (err < 0) - return err; + if (pod->line6.properties->capabilities & LINE6_CAP_PCM) { + /* initialize PCM subsystem: */ + err = line6_init_pcm(line6, + (id->driver_info == LINE6_PODX3) ? &podx3_pcm_properties : + &podhd_pcm_properties); + if (err < 0) + return err; + } if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL)) { /* register USB audio system directly */ -- cgit v0.10.2 From a16039cbf1a1ee7e76d7d100f9e613998919ab91 Mon Sep 17 00:00:00 2001 From: Andrej Krutak Date: Sun, 18 Sep 2016 20:59:32 +0200 Subject: ALSA: line6: Add hwdep interface to access the POD control messages We must do it this way, because e.g. POD X3 won't play any sound unless the host listens on the bulk EP, so we cannot export it only via libusb. The driver currently doesn't use the bulk EP messages in other way, in future it could e.g. sense/modify volume(s). Signed-off-by: Andrej Krutak Signed-off-by: Takashi Iwai diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 609cadb..be353a7 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -106,9 +106,10 @@ enum { SNDRV_HWDEP_IFACE_FW_OXFW, /* Oxford OXFW970/971 based device */ SNDRV_HWDEP_IFACE_FW_DIGI00X, /* Digidesign Digi 002/003 family */ SNDRV_HWDEP_IFACE_FW_TASCAM, /* TASCAM FireWire series */ + SNDRV_HWDEP_IFACE_LINE6, /* Line6 USB processors */ /* Don't forget to change the following: */ - SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_TASCAM + SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_LINE6 }; struct snd_hwdep_info { diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 8a71d45..f9224ec 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -17,6 +17,7 @@ #include #include +#include #include "capture.h" #include "driver.h" @@ -303,7 +304,7 @@ static void line6_data_received(struct urb *urb) for (;;) { done = line6_midibuf_read(mb, line6->buffer_message, - LINE6_MESSAGE_MAXLEN); + LINE6_MIDI_MESSAGE_MAXLEN); if (done == 0) break; @@ -315,8 +316,11 @@ static void line6_data_received(struct urb *urb) line6->process_message(line6); } } else { + line6->buffer_message = urb->transfer_buffer; + line6->message_length = urb->actual_length; if (line6->process_message) line6->process_message(line6); + line6->buffer_message = NULL; } line6_start_listen(line6); @@ -473,14 +477,17 @@ static void line6_destruct(struct snd_card *card) struct usb_line6 *line6 = card->private_data; struct usb_device *usbdev = line6->usbdev; - /* free buffer memory first: */ - if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) + /* Free buffer memory first. We cannot depend on the existence of private + * data from the (podhd) module, it may be gone already during this call + */ + if (line6->buffer_message) kfree(line6->buffer_message); kfree(line6->buffer_listen); /* then free URBs: */ usb_free_urb(line6->urb_listen); + line6->urb_listen = NULL; /* decrement reference counters: */ usb_put_dev(usbdev); @@ -522,6 +529,138 @@ static void line6_get_interval(struct usb_line6 *line6) } } + +/* Enable buffering of incoming messages, flush the buffer */ +static int line6_hwdep_open(struct snd_hwdep *hw, struct file *file) +{ + struct usb_line6 *line6 = hw->private_data; + + /* NOTE: hwdep layer provides atomicity here */ + + line6->messages.active = 1; + + return 0; +} + +/* Stop buffering */ +static int line6_hwdep_release(struct snd_hwdep *hw, struct file *file) +{ + struct usb_line6 *line6 = hw->private_data; + + line6->messages.active = 0; + + return 0; +} + +/* Read from circular buffer, return to user */ +static long +line6_hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, + loff_t *offset) +{ + struct usb_line6 *line6 = hwdep->private_data; + long rv = 0; + unsigned int out_count; + + if (mutex_lock_interruptible(&line6->messages.read_lock)) + return -ERESTARTSYS; + + while (kfifo_len(&line6->messages.fifo) == 0) { + mutex_unlock(&line6->messages.read_lock); + + rv = wait_event_interruptible( + line6->messages.wait_queue, + kfifo_len(&line6->messages.fifo) != 0); + if (rv < 0) + return rv; + + if (mutex_lock_interruptible(&line6->messages.read_lock)) + return -ERESTARTSYS; + } + + if (kfifo_peek_len(&line6->messages.fifo) > count) { + /* Buffer too small; allow re-read of the current item... */ + rv = -EINVAL; + } else { + rv = kfifo_to_user(&line6->messages.fifo, buf, count, &out_count); + if (rv == 0) + rv = out_count; + } + + mutex_unlock(&line6->messages.read_lock); + return rv; +} + +/* Write directly (no buffering) to device by user*/ +static long +line6_hwdep_write(struct snd_hwdep *hwdep, const char __user *data, long count, + loff_t *offset) +{ + struct usb_line6 *line6 = hwdep->private_data; + int rv; + char *data_copy; + + if (count > line6->max_packet_size * LINE6_RAW_MESSAGES_MAXCOUNT) { + /* This is an arbitrary limit - still better than nothing... */ + return -EINVAL; + } + + data_copy = memdup_user(data, count); + if (IS_ERR(ERR_PTR)) + return -ENOMEM; + + rv = line6_send_raw_message(line6, data_copy, count); + + kfree(data_copy); + return rv; +} + +static const struct snd_hwdep_ops hwdep_ops = { + .open = line6_hwdep_open, + .release = line6_hwdep_release, + .read = line6_hwdep_read, + .write = line6_hwdep_write, +}; + +/* Insert into circular buffer */ +static void line6_hwdep_push_message(struct usb_line6 *line6) +{ + if (!line6->messages.active) + return; + + if (kfifo_avail(&line6->messages.fifo) >= line6->message_length) { + /* No race condition here, there's only one writer */ + kfifo_in(&line6->messages.fifo, + line6->buffer_message, line6->message_length); + } /* else TODO: signal overflow */ + + wake_up_interruptible(&line6->messages.wait_queue); +} + +static int line6_hwdep_init(struct usb_line6 *line6) +{ + int err; + struct snd_hwdep *hwdep; + + /* TODO: usb_driver_claim_interface(); */ + line6->process_message = line6_hwdep_push_message; + line6->messages.active = 0; + init_waitqueue_head(&line6->messages.wait_queue); + mutex_init(&line6->messages.read_lock); + INIT_KFIFO(line6->messages.fifo); + + err = snd_hwdep_new(line6->card, "config", 0, &hwdep); + if (err < 0) + goto end; + strcpy(hwdep->name, "config"); + hwdep->iface = SNDRV_HWDEP_IFACE_LINE6; + hwdep->ops = hwdep_ops; + hwdep->private_data = line6; + hwdep->exclusive = true; + +end: + return err; +} + static int line6_init_cap_control(struct usb_line6 *line6) { int ret; @@ -536,9 +675,13 @@ static int line6_init_cap_control(struct usb_line6 *line6) return -ENOMEM; if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { - line6->buffer_message = kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL); + line6->buffer_message = kmalloc(LINE6_MIDI_MESSAGE_MAXLEN, GFP_KERNEL); if (!line6->buffer_message) return -ENOMEM; + } else { + ret = line6_hwdep_init(line6); + if (ret < 0) + return ret; } ret = line6_start_listen(line6); @@ -716,3 +859,4 @@ EXPORT_SYMBOL_GPL(line6_resume); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); + diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index 88cf1e7..7e3a3aa 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -12,8 +12,9 @@ #ifndef DRIVER_H #define DRIVER_H -#include #include +#include +#include #include #include "midi.h" @@ -32,7 +33,16 @@ #define LINE6_TIMEOUT 1 #define LINE6_BUFSIZE_LISTEN 64 -#define LINE6_MESSAGE_MAXLEN 256 +#define LINE6_MIDI_MESSAGE_MAXLEN 256 + +#define LINE6_RAW_MESSAGES_MAXCOUNT_ORDER 7 +/* 4k packets are common, BUFSIZE * MAXCOUNT should be bigger... */ +#define LINE6_RAW_MESSAGES_MAXCOUNT (1 << LINE6_RAW_MESSAGES_MAXCOUNT_ORDER) + + +#if LINE6_BUFSIZE_LISTEN > 65535 +#error "Use dynamic fifo instead" +#endif /* Line 6 MIDI control commands @@ -156,6 +166,15 @@ struct usb_line6 { /* Length of message to be processed, generated from MIDI layer */ int message_length; + /* Circular buffer for non-MIDI control messages */ + struct { + struct mutex read_lock; + wait_queue_head_t wait_queue; + unsigned int active:1; + STRUCT_KFIFO_REC_2(LINE6_BUFSIZE_LISTEN * LINE6_RAW_MESSAGES_MAXCOUNT) + fifo; + } messages; + /* If MIDI is supported, buffer_message contains the pre-processed data; * otherwise the data is only in urb_listen (buffer_incoming). */ -- cgit v0.10.2 From a4bc746c41b56ab7588b20d84a58906986edce83 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Tue, 20 Sep 2016 08:10:13 +0800 Subject: ALSA: line6: fix ifnullfree.cocci warnings sound/usb/line6/driver.c:484:2-7: WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values. NULL check before some freeing functions is not needed. Based on checkpatch warning "kfree(NULL) is safe this check is probably not required" and kfreeaddr.cocci by Julia Lawall. Generated by: scripts/coccinelle/free/ifnullfree.cocci CC: Andrej Krutak Signed-off-by: Fengguang Wu Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index f9224ec..c998667 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -480,8 +480,7 @@ static void line6_destruct(struct snd_card *card) /* Free buffer memory first. We cannot depend on the existence of private * data from the (podhd) module, it may be gone already during this call */ - if (line6->buffer_message) - kfree(line6->buffer_message); + kfree(line6->buffer_message); kfree(line6->buffer_listen); -- cgit v0.10.2 From 66d7c2629aa4f2c861b7cca9ff15b6bc38e9c9a8 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 17 Sep 2016 01:34:09 +0000 Subject: ASoC: rt5663: fix sparse warnings Fixes the following sparse warnings: sound/soc/codecs/rt5663.c:1367:14: warning: duplicate const sound/soc/codecs/rt5663.c:1577:5: warning: symbol 'rt5663_button_detect' was not declared. Should it be static? sound/soc/codecs/rt5663.c:2857:24: warning: symbol 'rt5663_aif_dai_ops' was not declared. Should it be static? sound/soc/codecs/rt5663.c:2866:27: warning: symbol 'rt5663_dai' was not declared. Should it be static? sound/soc/codecs/rt5663.c:3193:6: warning: symbol 'rt5663_i2c_shutdown' was not declared. Should it be static? sound/soc/codecs/rt5663.c:3200:19: warning: symbol 'rt5663_i2c_driver' was not declared. Should it be static? Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index 8078abc..90a6ad5 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -1364,7 +1364,7 @@ static const char * const rt5663_if1_adc_data_select[] = { "L/R", "R/L", "L/L", "R/R" }; -static const SOC_ENUM_SINGLE_DECL(rt5663_if1_adc_enum, RT5663_TDM_2, +static SOC_ENUM_SINGLE_DECL(rt5663_if1_adc_enum, RT5663_TDM_2, RT5663_DATA_SWAP_ADCDAT1_SHIFT, rt5663_if1_adc_data_select); static void rt5663_enable_push_button_irq(struct snd_soc_codec *codec, @@ -1574,7 +1574,7 @@ static int rt5663_jack_detect(struct snd_soc_codec *codec, int jack_insert) return rt5663->jack_type; } -int rt5663_button_detect(struct snd_soc_codec *codec) +static int rt5663_button_detect(struct snd_soc_codec *codec) { int btn_type, val; @@ -2857,7 +2857,7 @@ static int rt5663_resume(struct snd_soc_codec *codec) #define RT5663_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) -struct snd_soc_dai_ops rt5663_aif_dai_ops = { +static struct snd_soc_dai_ops rt5663_aif_dai_ops = { .hw_params = rt5663_hw_params, .set_fmt = rt5663_set_dai_fmt, .set_sysclk = rt5663_set_dai_sysclk, @@ -2866,7 +2866,7 @@ struct snd_soc_dai_ops rt5663_aif_dai_ops = { .set_bclk_ratio = rt5663_set_bclk_ratio, }; -struct snd_soc_dai_driver rt5663_dai[] = { +static struct snd_soc_dai_driver rt5663_dai[] = { { .name = "rt5663-aif", .id = RT5663_AIF, @@ -3193,14 +3193,14 @@ static int rt5663_i2c_remove(struct i2c_client *i2c) return 0; } -void rt5663_i2c_shutdown(struct i2c_client *client) +static void rt5663_i2c_shutdown(struct i2c_client *client) { struct rt5663_priv *rt5663 = i2c_get_clientdata(client); regmap_write(rt5663->regmap, RT5663_RESET, 0); } -struct i2c_driver rt5663_i2c_driver = { +static struct i2c_driver rt5663_i2c_driver = { .driver = { .name = "rt5663", .owner = THIS_MODULE, -- cgit v0.10.2 From c5f1edd405eb874cc2c81e8d62c6b3a73c502529 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Sat, 17 Sep 2016 10:45:18 +0800 Subject: ASoC: rt5663: fix platform_no_drv_owner.cocci warnings sound/soc/codecs/rt5663.c:3203:3-8: No need to set .owner here. The core will do it. Remove .owner field if calls are used which set it automatically Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Signed-off-by: Fengguang Wu Acked-by: Bard Liao Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index 90a6ad5..01a18d8 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -3203,7 +3203,6 @@ static void rt5663_i2c_shutdown(struct i2c_client *client) static struct i2c_driver rt5663_i2c_driver = { .driver = { .name = "rt5663", - .owner = THIS_MODULE, .acpi_match_table = ACPI_PTR(rt5663_acpi_match), .of_match_table = of_match_ptr(rt5663_of_match), }, -- cgit v0.10.2 From b413886886b9a8f845f7d1a5adafa0ca573d3828 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 19 Sep 2016 21:30:25 +0200 Subject: ASoC: fsl_asrc: use flat regmap cache Same as commit ce492b3b8f99cf9d2f807ec22d8805c996a09503 Subject: drm/fsl-dcu: use flat regmap cache Using flat regmap cache instead of RB-tree to avoid the following lockdep warning on driver load: WARNING: CPU: 0 PID: 1 at kernel/locking/lockdep.c:2871 lockdep_trace_alloc+0x104/0x128 DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags)) The RB-tree regmap cache needs to allocate new space on first writes. However, allocations in an atomic context (e.g. when a spinlock is held) are not allowed. The function regmap_write calls map->lock, which acquires a spinlock in the fast_io case. Since the driver uses MMIO, the regmap bus of type regmap_mmio is being used which has fast_io set to true. Signed-off-by: Marek Vasut Acked-by: Nicolin Chen Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index b7157ce..1d82f68 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -726,7 +726,7 @@ static const struct regmap_config fsl_asrc_regmap_config = { .readable_reg = fsl_asrc_readable_reg, .volatile_reg = fsl_asrc_volatile_reg, .writeable_reg = fsl_asrc_writeable_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; /** -- cgit v0.10.2 From 0effb8651ee3b00513fbba9ef3912bbcbbd38af6 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 19 Sep 2016 21:30:26 +0200 Subject: ASoC: fsl_esai: use flat regmap cache Same as commit ce492b3b8f99cf9d2f807ec22d8805c996a09503 Subject: drm/fsl-dcu: use flat regmap cache Using flat regmap cache instead of RB-tree to avoid the following lockdep warning on driver load: WARNING: CPU: 0 PID: 1 at kernel/locking/lockdep.c:2871 lockdep_trace_alloc+0x104/0x128 DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags)) The RB-tree regmap cache needs to allocate new space on first writes. However, allocations in an atomic context (e.g. when a spinlock is held) are not allowed. The function regmap_write calls map->lock, which acquires a spinlock in the fast_io case. Since the driver uses MMIO, the regmap bus of type regmap_mmio is being used which has fast_io set to true. Signed-off-by: Marek Vasut Acked-by: Nicolin Chen Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index e927955..38bfd46 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -781,7 +781,7 @@ static const struct regmap_config fsl_esai_regmap_config = { .readable_reg = fsl_esai_readable_reg, .volatile_reg = fsl_esai_volatile_reg, .writeable_reg = fsl_esai_writeable_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int fsl_esai_probe(struct platform_device *pdev) -- cgit v0.10.2 From 35ddb15757cd1c817e424c6252d2f11f268cfebf Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 19 Sep 2016 21:30:27 +0200 Subject: ASoC: fsl_spdif: use flat regmap cache Same as commit ce492b3b8f99cf9d2f807ec22d8805c996a09503 Subject: drm/fsl-dcu: use flat regmap cache Using flat regmap cache instead of RB-tree to avoid the following lockdep warning on driver load: WARNING: CPU: 0 PID: 1 at kernel/locking/lockdep.c:2871 lockdep_trace_alloc+0x104/0x128 DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags)) The RB-tree regmap cache needs to allocate new space on first writes. However, allocations in an atomic context (e.g. when a spinlock is held) are not allowed. The function regmap_write calls map->lock, which acquires a spinlock in the fast_io case. Since the driver uses MMIO, the regmap bus of type regmap_mmio is being used which has fast_io set to true. Signed-off-by: Marek Vasut Acked-by: Nicolin Chen Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index beec793..1ff467c 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1103,7 +1103,7 @@ static const struct regmap_config fsl_spdif_regmap_config = { .readable_reg = fsl_spdif_readable_reg, .volatile_reg = fsl_spdif_volatile_reg, .writeable_reg = fsl_spdif_writeable_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv, -- cgit v0.10.2 From bfcf928d7604692668a7c33b783d05b8e3459d09 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 19 Sep 2016 21:30:28 +0200 Subject: ASoC: fsl_ssi: use flat regmap cache Same as commit ce492b3b8f99cf9d2f807ec22d8805c996a09503 Subject: drm/fsl-dcu: use flat regmap cache Using flat regmap cache instead of RB-tree to avoid the following lockdep warning on driver load: WARNING: CPU: 0 PID: 1 at kernel/locking/lockdep.c:2871 lockdep_trace_alloc+0x104/0x128 DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags)) The RB-tree regmap cache needs to allocate new space on first writes. However, allocations in an atomic context (e.g. when a spinlock is held) are not allowed. The function regmap_write calls map->lock, which acquires a spinlock in the fast_io case. Since the driver uses MMIO, the regmap bus of type regmap_mmio is being used which has fast_io set to true. Signed-off-by: Marek Vasut Acked-by: Nicolin Chen Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index bedec4a..5034943 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -182,7 +182,7 @@ static const struct regmap_config fsl_ssi_regconfig = { .volatile_reg = fsl_ssi_volatile_reg, .precious_reg = fsl_ssi_precious_reg, .writeable_reg = fsl_ssi_writeable_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; struct fsl_ssi_soc_data { -- cgit v0.10.2 From 7de2763d9b325ee5e7e24ac513c93394406cfefa Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 19 Sep 2016 21:30:29 +0200 Subject: ASoC: fsl_ssi: Remove .num_reg_defaults_raw from regmap_config This driver provides no .reg_defaults_raw in regmap_config, so the .num_reg_defaults_raw is useless, and, in fact harmful. It triggers kernel crash in regmap_init which tries to access the register defaults. Signed-off-by: Marek Vasut Acked-by: Nicolin Chen Signed-off-by: Mark Brown diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 5034943..b73c102 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -177,7 +177,6 @@ static const struct regmap_config fsl_ssi_regconfig = { .val_bits = 32, .reg_stride = 4, .val_format_endian = REGMAP_ENDIAN_NATIVE, - .num_reg_defaults_raw = CCSR_SSI_SACCDIS / sizeof(uint32_t) + 1, .readable_reg = fsl_ssi_readable_reg, .volatile_reg = fsl_ssi_volatile_reg, .precious_reg = fsl_ssi_precious_reg, @@ -1501,8 +1500,6 @@ static int fsl_ssi_probe(struct platform_device *pdev) * don't have SACC{ST,EN,DIS} regs. */ regconfig.max_register = CCSR_SSI_SRMSK; - regconfig.num_reg_defaults_raw = - CCSR_SSI_SRMSK / sizeof(uint32_t) + 1; } ret = of_property_match_string(np, "clock-names", "ipg"); -- cgit v0.10.2 From 0da325afbdb80098e014b83937372e3eef6872d5 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 20 Sep 2016 18:14:53 -0400 Subject: ALSA: line6: snd-usb-line6 depends on CONFIG_SND_HWDEP ERROR: "snd_hwdep_new" [sound/usb/line6/snd-usb-line6.ko] undefined! scripts/Makefile.modpost:91: recipe for target '__modpost' failed make[1]: *** [__modpost] Error 1 Fixes: a16039cbf1a1 ('ALSA: line6: Add hwdep interface to access the POD control messages') Signed-off-by: Valdis Kletnieks Reviewed-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/Kconfig b/sound/usb/line6/Kconfig index 8ffcf48..39b4003 100644 --- a/sound/usb/line6/Kconfig +++ b/sound/usb/line6/Kconfig @@ -2,6 +2,7 @@ config SND_USB_LINE6 tristate select SND_RAWMIDI select SND_PCM + select SND_HWDEP config SND_USB_POD tristate "Line 6 POD USB support" -- cgit v0.10.2 From db68577966abc1aeae4ec597b3dcfa0d56e92041 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 21 Sep 2016 14:38:02 +0200 Subject: ALSA: ali5451: Fix out-of-bound position reporting The pointer callbacks of ali5451 driver may return the value at the boundary occasionally, and it results in the kernel warning like snd_ali5451 0000:00:06.0: BUG: , pos = 16384, buffer size = 16384, period size = 1024 It seems that folding the position offset is enough for fixing the warning and no ill-effect has been seen by that. Reported-by: Enrico Mioso Tested-by: Enrico Mioso Cc: Signed-off-by: Takashi Iwai diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 36470af..92b819e 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -1408,6 +1408,7 @@ snd_ali_playback_pointer(struct snd_pcm_substream *substream) spin_unlock(&codec->reg_lock); dev_dbg(codec->card->dev, "playback pointer returned cso=%xh.\n", cso); + cso %= runtime->buffer_size; return cso; } @@ -1428,6 +1429,7 @@ static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream) cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)); spin_unlock(&codec->reg_lock); + cso %= runtime->buffer_size; return cso; } -- cgit v0.10.2 From 8180bd56bdd1dcade8d1b2a0b6f70b2397bec372 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 22 Sep 2016 11:37:32 +0200 Subject: ASoC: cq93vc: duplicated callback function goes to component A cleanup removed a couple of members from struct snd_soc_codec_driver after changing codec drivers to no longer use them, but one codec was missed in the process, giving a build error: sound/soc/codecs/cq93vc.c:134:2: error: unknown field 'controls' specified in initializer .controls = cq93vc_snd_controls, This moves the members from the cq93vc codec driver to its component driver just like the other codecs already had. Fixes: 8073aefa6082 ("ASoC: remove codec duplicated callback function") Signed-off-by: Arnd Bergmann Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index 1c895a5..7a2d9a2 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c @@ -131,8 +131,10 @@ static struct regmap *cq93vc_get_regmap(struct device *dev) static struct snd_soc_codec_driver soc_codec_dev_cq93vc = { .set_bias_level = cq93vc_set_bias_level, .get_regmap = cq93vc_get_regmap, - .controls = cq93vc_snd_controls, - .num_controls = ARRAY_SIZE(cq93vc_snd_controls), + .component_driver = { + .controls = cq93vc_snd_controls, + .num_controls = ARRAY_SIZE(cq93vc_snd_controls), + }, }; static int cq93vc_platform_probe(struct platform_device *pdev) -- cgit v0.10.2 From eb1a74b7bea17eea31915c4f76385cefe69d9795 Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Fri, 23 Sep 2016 06:43:47 +0300 Subject: ALSA: usb-audio: Extend DragonFly dB scale quirk to cover other variants The DragonFly quirk added in 42e3121d90f4 ("ALSA: usb-audio: Add a more accurate volume quirk for AudioQuest DragonFly") applies a custom dB map on the volume control when its range is reported as 0..50 (0 .. 0.2dB). However, there exists at least one other variant (hw v1.0c, as opposed to the tested v1.2) which reports a different non-sensical volume range (0..53) and the custom map is therefore not applied for that device. This results in all of the volume change appearing close to 100% on mixer UIs that utilize the dB TLV information. Add a fallback case where no dB TLV is reported at all if the control range is not 0..50 but still 0..N where N <= 1000 (3.9 dB). Also restrict the quirk to only apply to the volume control as there is also a mute control which would match the check otherwise. Fixes: 42e3121d90f4 ("ALSA: usb-audio: Add a more accurate volume quirk for AudioQuest DragonFly") Signed-off-by: Anssi Hannula Reported-by: David W Tested-by: David W Cc: Signed-off-by: Takashi Iwai diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index f6c3bf7..04991b0 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -1831,6 +1831,7 @@ void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, } static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer, + struct usb_mixer_elem_info *cval, struct snd_kcontrol *kctl) { /* Approximation using 10 ranges based on output measurement on hw v1.2. @@ -1848,10 +1849,19 @@ static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer, 41, 50, TLV_DB_MINMAX_ITEM(-441, 0), ); - usb_audio_info(mixer->chip, "applying DragonFly dB scale quirk\n"); - kctl->tlv.p = scale; - kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; - kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; + if (cval->min == 0 && cval->max == 50) { + usb_audio_info(mixer->chip, "applying DragonFly dB scale quirk (0-50 variant)\n"); + kctl->tlv.p = scale; + kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; + kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; + + } else if (cval->min == 0 && cval->max <= 1000) { + /* Some other clearly broken DragonFly variant. + * At least a 0..53 variant (hw v1.0) exists. + */ + usb_audio_info(mixer->chip, "ignoring too narrow dB range on a DragonFly device"); + kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; + } } void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer, @@ -1860,8 +1870,8 @@ void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer, { switch (mixer->chip->usb_id) { case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */ - if (unitid == 7 && cval->min == 0 && cval->max == 50) - snd_dragonfly_quirk_db_scale(mixer, kctl); + if (unitid == 7 && cval->control == UAC_FU_VOLUME) + snd_dragonfly_quirk_db_scale(mixer, cval, kctl); break; } } -- cgit v0.10.2 From 3a6f9dce6116cc54e31dc10d176ceecb1a7e4e7f Mon Sep 17 00:00:00 2001 From: Wonjoon Lee Date: Thu, 22 Sep 2016 21:50:06 +0800 Subject: ASoC: rk3399_gru_sound: fix recording pop at first attempt Pop happens when mclk applied but dmic's own boot-time Specify dmic delay times in dt to make sure clocks are ready earlier than dmic working Signed-off-by: Wonjoon Lee Signed-off-by: Xing Zheng Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt index f19b6c8..eac91db 100644 --- a/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt +++ b/Documentation/devicetree/bindings/sound/rockchip,rk3399-gru-sound.txt @@ -6,10 +6,17 @@ Required properties: connected to the codecs - rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs +Optional properties: +- dmic-wakeup-delay-ms : specify delay time (ms) for DMIC ready. + If this option is specified, which means it's required dmic need + delay for DMIC to ready so that rt5514 can avoid recording before + DMIC send valid data + Example: sound { compatible = "rockchip,rk3399-gru-sound"; rockchip,cpu = <&i2s0>; rockchip,codec = <&max98357a &rt5514 &da7219>; + dmic-wakeup-delay-ms = <20>; }; diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index ee06489..9ed735a 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -38,6 +38,8 @@ #define SOUND_FS 256 +unsigned int rt5514_dmic_delay; + static struct snd_soc_jack rockchip_sound_jack; static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = { @@ -123,6 +125,9 @@ static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream, return ret; } + /* Wait for DMIC stable */ + msleep(rt5514_dmic_delay); + return 0; } @@ -343,6 +348,15 @@ static int rockchip_sound_probe(struct platform_device *pdev) return -ENODEV; } + /* Set DMIC delay */ + ret = device_property_read_u32(&pdev->dev, "dmic-delay", + &rt5514_dmic_delay); + if (ret) { + rt5514_dmic_delay = 0; + dev_dbg(&pdev->dev, + "no optional property 'dmic-delay' found, default: no delay\n"); + } + rockchip_dailinks[DAILINK_RT5514_DSP].cpu_name = kstrdup_const(dev_name(dev), GFP_KERNEL); rockchip_dailinks[DAILINK_RT5514_DSP].cpu_dai_name = kstrdup_const(dev_name(dev), GFP_KERNEL); rockchip_dailinks[DAILINK_RT5514_DSP].platform_name = kstrdup_const(dev_name(dev), GFP_KERNEL); -- cgit v0.10.2 From 4f0c4e99312d8887483474d60e47ab4e24713114 Mon Sep 17 00:00:00 2001 From: Danny Milosavljevic Date: Thu, 22 Sep 2016 09:13:12 +0200 Subject: ASoC: sun4i-codec: Rename some sun7i-only registers Some of the registers defined in the driver are only usable on the A20. Rename these registers. Signed-off-by: Danny Milosavljevic Acked-by: Maxime Ripard Signed-off-by: Mark Brown diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 44f170c..9d8c027 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -96,8 +96,8 @@ /* Other various ADC registers */ #define SUN4I_CODEC_DAC_TXCNT (0x30) #define SUN4I_CODEC_ADC_RXCNT (0x34) -#define SUN4I_CODEC_AC_SYS_VERI (0x38) -#define SUN4I_CODEC_AC_MIC_PHONE_CAL (0x3c) +#define SUN7I_CODEC_AC_DAC_CAL (0x38) +#define SUN7I_CODEC_AC_MIC_PHONE_CAL (0x3c) struct sun4i_codec { struct device *dev; @@ -680,7 +680,7 @@ static const struct regmap_config sun4i_codec_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = SUN4I_CODEC_AC_MIC_PHONE_CAL, + .max_register = SUN7I_CODEC_AC_MIC_PHONE_CAL, }; static const struct of_device_id sun4i_codec_of_match[] = { -- cgit v0.10.2 From c1d5065a0bd09bac783120b73bfa768ba6a493d9 Mon Sep 17 00:00:00 2001 From: Danny Milosavljevic Date: Thu, 22 Sep 2016 09:13:13 +0200 Subject: ASoC: sun4i-codec: Add custom regmap configs The A20 has a few extra registers that the A10 doesn't have. Therefore, use different regmaps for A10 as compared to A20. Signed-off-by: Danny Milosavljevic Acked-by: Maxime Ripard Signed-off-by: Mark Brown diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 9d8c027..eb68088 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -680,12 +680,37 @@ static const struct regmap_config sun4i_codec_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, + .max_register = SUN4I_CODEC_ADC_RXCNT, +}; + +static const struct regmap_config sun7i_codec_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, .max_register = SUN7I_CODEC_AC_MIC_PHONE_CAL, }; +struct sun4i_codec_quirks { + const struct regmap_config *regmap_config; +}; + +static const struct sun4i_codec_quirks sun4i_codec_quirks = { + .regmap_config = &sun4i_codec_regmap_config, +}; + +static const struct sun4i_codec_quirks sun7i_codec_quirks = { + .regmap_config = &sun7i_codec_regmap_config, +}; + static const struct of_device_id sun4i_codec_of_match[] = { - { .compatible = "allwinner,sun4i-a10-codec" }, - { .compatible = "allwinner,sun7i-a20-codec" }, + { + .compatible = "allwinner,sun4i-a10-codec", + .data = &sun4i_codec_quirks, + }, + { + .compatible = "allwinner,sun7i-a20-codec", + .data = &sun7i_codec_quirks, + }, {} }; MODULE_DEVICE_TABLE(of, sun4i_codec_of_match); @@ -758,6 +783,7 @@ static int sun4i_codec_probe(struct platform_device *pdev) { struct snd_soc_card *card; struct sun4i_codec *scodec; + const struct sun4i_codec_quirks *quirks; struct resource *res; void __iomem *base; int ret; @@ -775,8 +801,14 @@ static int sun4i_codec_probe(struct platform_device *pdev) return PTR_ERR(base); } + quirks = of_device_get_match_data(&pdev->dev); + if (quirks == NULL) { + dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); + return -ENODEV; + } + scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base, - &sun4i_codec_regmap_config); + quirks->regmap_config); if (IS_ERR(scodec->regmap)) { dev_err(&pdev->dev, "Failed to create our regmap\n"); return PTR_ERR(scodec->regmap); -- cgit v0.10.2 From 700a9a63f9c1bc13abaa956eacc0bfcaf3a201c2 Mon Sep 17 00:00:00 2001 From: Dharageswari R Date: Thu, 22 Sep 2016 14:00:37 +0530 Subject: ASoC: Intel: Skylake: Add module instance id generation APIs Driver needs to send unique module instance id to firmware while creating the module and uses this id to communicate with DSP for setting parameters while audio use case is ongoing. But, we have upper bound of instance ID. The current IDs are coming from topology but it doesn't know the upper bound and can't assign unique id's subject to upper bounds as we can create a big graph but not all parts running at same time. This patch adds a 128bit unique id management routines which are built on top of ffz() for faster implementation. Unfortunately ffz() works on 32bits values, so additional code is added on top of ffz() to create a 128bit unique id. Signed-off-by: Dharageswari R Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index 6ad5cab..b61bd03 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -215,6 +215,10 @@ int snd_skl_get_module_info(struct skl_sst *ctx, struct skl_module_cfg *mconfig); int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, unsigned int offset, int index); +int skl_get_pvt_id(struct skl_sst *ctx, + struct skl_module_cfg *mconfig); +int skl_put_pvt_id(struct skl_sst *ctx, + struct skl_module_cfg *mconfig); void skl_freeup_uuid_list(struct skl_sst *ctx); int skl_dsp_strip_extended_manifest(struct firmware *fw); diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index 9ce93e9..5f1c203 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -94,10 +94,14 @@ struct adsp_fw_hdr { u32 load_offset; } __packed; +#define MAX_INSTANCE_BUFF 2 + struct uuid_module { uuid_le uuid; int id; int is_loadable; + int max_instance; + u64 pvt_id[MAX_INSTANCE_BUFF]; struct list_head list; }; @@ -131,6 +135,116 @@ int snd_skl_get_module_info(struct skl_sst *ctx, } EXPORT_SYMBOL_GPL(snd_skl_get_module_info); +static inline int skl_getid_32(struct uuid_module *module, u64 *val, + int word1_mask, int word2_mask) +{ + int index, max_inst, pvt_id; + u32 mask_val; + + max_inst = module->max_instance; + mask_val = (u32)(*val >> word1_mask); + + if (mask_val != 0xffffffff) { + index = ffz(mask_val); + pvt_id = index + word1_mask + word2_mask; + if (pvt_id <= (max_inst - 1)) { + *val |= 1 << (index + word1_mask); + return pvt_id; + } + } + + return -EINVAL; +} + +static inline int skl_pvtid_128(struct uuid_module *module) +{ + int j, i, word1_mask, word2_mask = 0, pvt_id; + + for (j = 0; j < MAX_INSTANCE_BUFF; j++) { + word1_mask = 0; + + for (i = 0; i < 2; i++) { + pvt_id = skl_getid_32(module, &module->pvt_id[j], + word1_mask, word2_mask); + if (pvt_id >= 0) + return pvt_id; + + word1_mask += 32; + if ((word1_mask + word2_mask) >= module->max_instance) + return -EINVAL; + } + + word2_mask += 64; + if (word2_mask >= module->max_instance) + return -EINVAL; + } + + return -EINVAL; +} + +/** + * skl_get_pvt_id: generate a private id for use as module id + * + * @ctx: driver context + * @mconfig: module configuration data + * + * This generates a 128 bit private unique id for a module TYPE so that + * module instance is unique + */ +int skl_get_pvt_id(struct skl_sst *ctx, struct skl_module_cfg *mconfig) +{ + struct uuid_module *module; + uuid_le *uuid_mod; + int pvt_id; + + uuid_mod = (uuid_le *)mconfig->guid; + + list_for_each_entry(module, &ctx->uuid_list, list) { + if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) { + + pvt_id = skl_pvtid_128(module); + if (pvt_id >= 0) + return pvt_id; + } + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(skl_get_pvt_id); + +/** + * skl_put_pvt_id: free up the private id allocated + * + * @ctx: driver context + * @mconfig: module configuration data + * + * This frees a 128 bit private unique id previously generated + */ +int skl_put_pvt_id(struct skl_sst *ctx, struct skl_module_cfg *mconfig) +{ + int i; + uuid_le *uuid_mod; + struct uuid_module *module; + + uuid_mod = (uuid_le *)mconfig->guid; + list_for_each_entry(module, &ctx->uuid_list, list) { + if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) { + + if (mconfig->id.pvt_id != 0) + i = (mconfig->id.pvt_id) / 64; + else + i = 0; + + module->pvt_id[i] &= ~(1 << (mconfig->id.pvt_id)); + mconfig->id.pvt_id = -1; + return 0; + } + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(skl_put_pvt_id); + /* * Parse the firmware binary to get the UUID, module id * and loadable flags @@ -203,6 +317,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, module->id = (i | (index << 12)); module->is_loadable = mod_entry->type.load_type; + module->max_instance = mod_entry->instance_max_count; list_add_tail(&module->list, &skl->uuid_list); diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 37f45cc3..def0391 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -218,6 +218,7 @@ struct skl_module_cfg; struct skl_module_inst_id { int module_id; u32 instance_id; + int pvt_id; }; enum skl_module_pin_state { -- cgit v0.10.2 From ef2a352cfb2a536ae8718065b43702a97f9fba9f Mon Sep 17 00:00:00 2001 From: Dharageswari R Date: Thu, 22 Sep 2016 14:00:38 +0530 Subject: ASoC: Intel: Skylake: Use private instance id of modules in IPC Use private id's of module instances that are generated during init_module for the IPC messages to DSP. These id's are freed up during delete pipeline. Signed-off-by: Dharageswari R Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 8eb5ba2..ac0c58e 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -787,6 +787,7 @@ static int skl_alloc_queue(struct skl_module_pin *mpin, mpin[i].in_use = true; mpin[i].id.module_id = id.module_id; mpin[i].id.instance_id = id.instance_id; + mpin[i].id.pvt_id = id.pvt_id; mpin[i].tgt_mcfg = tgt_cfg; return i; } @@ -810,6 +811,7 @@ static void skl_free_queue(struct skl_module_pin *mpin, int q_index) mpin[q_index].in_use = false; mpin[q_index].id.module_id = 0; mpin[q_index].id.instance_id = 0; + mpin[q_index].id.pvt_id = 0; } mpin[q_index].pin_state = SKL_PIN_UNBIND; mpin[q_index].tgt_mcfg = NULL; @@ -850,7 +852,7 @@ int skl_init_module(struct skl_sst *ctx, struct skl_ipc_init_instance_msg msg; dev_dbg(ctx->dev, "%s: module_id = %d instance=%d\n", __func__, - mconfig->id.module_id, mconfig->id.instance_id); + mconfig->id.module_id, mconfig->id.pvt_id); if (mconfig->pipe->state != SKL_PIPE_CREATED) { dev_err(ctx->dev, "Pipe not created state= %d pipe_id= %d\n", @@ -866,7 +868,7 @@ int skl_init_module(struct skl_sst *ctx, } msg.module_id = mconfig->id.module_id; - msg.instance_id = mconfig->id.instance_id; + msg.instance_id = mconfig->id.pvt_id; msg.ppl_instance_id = mconfig->pipe->ppl_id; msg.param_data_size = module_config_size; msg.core_id = mconfig->core_id; @@ -887,9 +889,9 @@ static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg *src_module, struct skl_module_cfg *dst_module) { dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n", - __func__, src_module->id.module_id, src_module->id.instance_id); + __func__, src_module->id.module_id, src_module->id.pvt_id); dev_dbg(ctx->dev, "%s: dst_module=%d dst_instacne=%d\n", __func__, - dst_module->id.module_id, dst_module->id.instance_id); + dst_module->id.module_id, dst_module->id.pvt_id); dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n", src_module->m_state, dst_module->m_state); @@ -936,9 +938,9 @@ int skl_unbind_modules(struct skl_sst *ctx, return 0; msg.module_id = src_mcfg->id.module_id; - msg.instance_id = src_mcfg->id.instance_id; + msg.instance_id = src_mcfg->id.pvt_id; msg.dst_module_id = dst_mcfg->id.module_id; - msg.dst_instance_id = dst_mcfg->id.instance_id; + msg.dst_instance_id = dst_mcfg->id.pvt_id; msg.bind = false; ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); @@ -997,9 +999,9 @@ int skl_bind_modules(struct skl_sst *ctx, msg.src_queue, msg.dst_queue); msg.module_id = src_mcfg->id.module_id; - msg.instance_id = src_mcfg->id.instance_id; + msg.instance_id = src_mcfg->id.pvt_id; msg.dst_module_id = dst_mcfg->id.module_id; - msg.dst_instance_id = dst_mcfg->id.instance_id; + msg.dst_instance_id = dst_mcfg->id.pvt_id; msg.bind = true; ret = skl_ipc_bind_unbind(&ctx->ipc, &msg); @@ -1177,7 +1179,7 @@ int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, struct skl_ipc_large_config_msg msg; msg.module_id = mcfg->id.module_id; - msg.instance_id = mcfg->id.instance_id; + msg.instance_id = mcfg->id.pvt_id; msg.param_data_size = size; msg.large_param_id = param_id; @@ -1190,7 +1192,7 @@ int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, struct skl_ipc_large_config_msg msg; msg.module_id = mcfg->id.module_id; - msg.instance_id = mcfg->id.instance_id; + msg.instance_id = mcfg->id.pvt_id; msg.param_data_size = size; msg.large_param_id = param_id; diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index 5f1c203..876b9e0 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -136,7 +136,7 @@ int snd_skl_get_module_info(struct skl_sst *ctx, EXPORT_SYMBOL_GPL(snd_skl_get_module_info); static inline int skl_getid_32(struct uuid_module *module, u64 *val, - int word1_mask, int word2_mask) + int word1_mask, int word2_mask) { int index, max_inst, pvt_id; u32 mask_val; diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 2d475b7..b6fc374 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -505,12 +505,15 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) * FE/BE params */ skl_tplg_update_module_params(w, ctx); - + mconfig->id.pvt_id = skl_get_pvt_id(ctx, mconfig); + if (mconfig->id.pvt_id < 0) + return ret; skl_tplg_set_module_init_data(w); ret = skl_init_module(ctx, mconfig); - if (ret < 0) + if (ret < 0) { + skl_put_pvt_id(ctx, mconfig); return ret; - + } skl_tplg_alloc_pipe_mcps(skl, mconfig); ret = skl_tplg_set_module_params(w, ctx); if (ret < 0) @@ -537,6 +540,7 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, if (ret < 0) return -EIO; } + skl_put_pvt_id(ctx, mconfig); } /* no modules to unload in this path, so return */ -- cgit v0.10.2 From 5e8f0ee46de46e709e19675726a46cf5838b9bca Mon Sep 17 00:00:00 2001 From: Dharageswari R Date: Thu, 22 Sep 2016 14:00:40 +0530 Subject: ASoC: Intel: Skylake: Update to use instance ids generated Post bind parameters of KPB module contains the instance id's of neighbouring modules in the sink path Now that module instance ids are generated dynamically we need to update these parameters as well, so use the table created and update the ids Signed-off-by: Dharageswari R Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index ac0c58e..805b7f2 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -680,6 +680,7 @@ static u16 skl_get_module_param_size(struct skl_sst *ctx, return param_size; case SKL_MODULE_TYPE_BASE_OUTFMT: + case SKL_MODULE_TYPE_KPB: return sizeof(struct skl_base_outfmt_cfg); default: @@ -733,6 +734,7 @@ static int skl_set_module_format(struct skl_sst *ctx, break; case SKL_MODULE_TYPE_BASE_OUTFMT: + case SKL_MODULE_TYPE_KPB: skl_set_base_outfmt_format(ctx, module_config, *param_data); break; diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index b6fc374..e48f872 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -607,6 +607,26 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, return 0; } +static int skl_fill_sink_instance_id(struct skl_sst *ctx, + struct skl_algo_data *alg_data) +{ + struct skl_kpb_params *params = (struct skl_kpb_params *)alg_data->params; + struct skl_mod_inst_map *inst; + int i, pvt_id; + + inst = params->map; + + for (i = 0; i < params->num_modules; i++) { + pvt_id = skl_get_pvt_instance_id_map(ctx, + inst->mod_id, inst->inst_id); + if (pvt_id < 0) + return -EINVAL; + inst->inst_id = pvt_id; + inst++; + } + return 0; +} + /* * Some modules require params to be set after the module is bound to * all pins connected. @@ -655,6 +675,8 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, bc = (struct skl_algo_data *)sb->dobj.private; if (bc->set_params == SKL_PARAM_BIND) { + if (mconfig->m_type == SKL_MODULE_TYPE_KPB) + skl_fill_sink_instance_id(ctx, bc); ret = skl_set_module_params(ctx, (u32 *)bc->params, bc->max, bc->param_id, mconfig); diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index def0391..a519360 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -215,6 +215,16 @@ struct skl_module_fmt { struct skl_module_cfg; +struct skl_mod_inst_map { + u16 mod_id; + u16 inst_id; +}; + +struct skl_kpb_params { + u32 num_modules; + struct skl_mod_inst_map map[0]; +}; + struct skl_module_inst_id { int module_id; u32 instance_id; diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index e208724..2f6281e 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h @@ -80,7 +80,8 @@ enum skl_module_type { SKL_MODULE_TYPE_UPDWMIX, SKL_MODULE_TYPE_SRCINT, SKL_MODULE_TYPE_ALGO, - SKL_MODULE_TYPE_BASE_OUTFMT + SKL_MODULE_TYPE_BASE_OUTFMT, + SKL_MODULE_TYPE_KPB, }; enum skl_core_affinity { -- cgit v0.10.2 From 55a92ea9cf6d6cac2f1be1bf53f0a120656b2060 Mon Sep 17 00:00:00 2001 From: Dharageswari R Date: Thu, 22 Sep 2016 14:00:39 +0530 Subject: ASoC: Intel: Skylake: Add table for module id for quick ref Since modules ids are generated dynamically, we do not know the id associate with modules in another pipelines. This limits our ability to tell DSP about neighbouring modules. So add a table for quick referencing of allocated module ids. Signed-off-by: Dharageswari R Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h index b61bd03..b9e71d0 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.h +++ b/sound/soc/intel/skylake/skl-sst-dsp.h @@ -219,6 +219,8 @@ int skl_get_pvt_id(struct skl_sst *ctx, struct skl_module_cfg *mconfig); int skl_put_pvt_id(struct skl_sst *ctx, struct skl_module_cfg *mconfig); +int skl_get_pvt_instance_id_map(struct skl_sst *ctx, + int module_id, int instance_id); void skl_freeup_uuid_list(struct skl_sst *ctx); int skl_dsp_strip_extended_manifest(struct firmware *fw); diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index 876b9e0..1aa0f37 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -102,6 +102,7 @@ struct uuid_module { int is_loadable; int max_instance; u64 pvt_id[MAX_INSTANCE_BUFF]; + int *instance_id; struct list_head list; }; @@ -135,6 +136,31 @@ int snd_skl_get_module_info(struct skl_sst *ctx, } EXPORT_SYMBOL_GPL(snd_skl_get_module_info); +static int skl_get_pvtid_map(struct uuid_module *module, int instance_id) +{ + int pvt_id; + + for (pvt_id = 0; pvt_id < module->max_instance; pvt_id++) { + if (module->instance_id[pvt_id] == instance_id) + return pvt_id; + } + return -EINVAL; +} + +int skl_get_pvt_instance_id_map(struct skl_sst *ctx, + int module_id, int instance_id) +{ + struct uuid_module *module; + + list_for_each_entry(module, &ctx->uuid_list, list) { + if (module->id == module_id) + return skl_get_pvtid_map(module, instance_id); + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(skl_get_pvt_instance_id_map); + static inline int skl_getid_32(struct uuid_module *module, u64 *val, int word1_mask, int word2_mask) { @@ -203,8 +229,11 @@ int skl_get_pvt_id(struct skl_sst *ctx, struct skl_module_cfg *mconfig) if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) { pvt_id = skl_pvtid_128(module); - if (pvt_id >= 0) + if (pvt_id >= 0) { + module->instance_id[pvt_id] = + mconfig->id.instance_id; return pvt_id; + } } } @@ -254,7 +283,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, { struct adsp_fw_hdr *adsp_hdr; struct adsp_module_entry *mod_entry; - int i, num_entry; + int i, num_entry, size; uuid_le *uuid_bin; const char *buf; struct skl_sst *skl = ctx->thread_context; @@ -318,6 +347,10 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, module->id = (i | (index << 12)); module->is_loadable = mod_entry->type.load_type; module->max_instance = mod_entry->instance_max_count; + size = sizeof(int) * mod_entry->instance_max_count; + module->instance_id = devm_kzalloc(ctx->dev, size, GFP_KERNEL); + if (!module->instance_id) + return -ENOMEM; list_add_tail(&module->list, &skl->uuid_list); -- cgit v0.10.2 From a114580f8f3e5bdefc14d75d6c3ba7032210b980 Mon Sep 17 00:00:00 2001 From: Nikita Yushchenko Date: Thu, 22 Sep 2016 13:10:40 +0300 Subject: ASoC: tpa6130a2: fix volume setting when no stream is running After moving tpa6130a2 power management to DAPM, if chip can be physically powered off (either reset_gpio is defined, or regulator indeed removes power), then volume change no longer works unless chip is on due to a running stream. Fix that by entering regcache cache_only mode while chip is off. Move regcache calls to tpa6130a2_power() to get them at driver init time as well. Signed-off-by: Nikita Yushchenko Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index f1ea052..3b6faed 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -52,7 +52,7 @@ struct tpa6130a2_data { static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable) { - int ret; + int ret = 0, ret2; if (enable) { ret = regulator_enable(data->supply); @@ -64,20 +64,34 @@ static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable) /* Power on */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 1); + + /* Sync registers */ + regcache_cache_only(data->regmap, false); + ret = regcache_sync(data->regmap); + if (ret != 0) { + dev_err(data->dev, + "Failed to sync registers: %d\n", ret); + goto regcache_sync_failed; + } } else { + /* Powered off device does not retain registers. While device + * is off, any register updates (i.e. volume changes) should + * happen in cache only. + */ + regcache_mark_dirty(data->regmap); +regcache_sync_failed: + regcache_cache_only(data->regmap, true); + /* Power off */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 0); - ret = regulator_disable(data->supply); - if (ret != 0) { + ret2 = regulator_disable(data->supply); + if (ret2 != 0) { dev_err(data->dev, - "Failed to disable supply: %d\n", ret); - return ret; + "Failed to disable supply: %d\n", ret2); + return ret ? ret : ret2; } - - /* device regs does not match the cache state anymore */ - regcache_mark_dirty(data->regmap); } return ret; @@ -88,25 +102,14 @@ static int tpa6130a2_power_event(struct snd_soc_dapm_widget *w, { struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); struct tpa6130a2_data *data = snd_soc_component_get_drvdata(c); - int ret; - /* before widget power up */ if (SND_SOC_DAPM_EVENT_ON(event)) { - /* Turn on the chip */ - tpa6130a2_power(data, true); - /* Sync the registers */ - ret = regcache_sync(data->regmap); - if (ret < 0) { - dev_err(c->dev, "Failed to initialize chip\n"); - tpa6130a2_power(data, false); - return ret; - } - /* after widget power down */ + /* Before widget power up: turn chip on, sync registers */ + return tpa6130a2_power(data, true); } else { - tpa6130a2_power(data, false); + /* After widget power down: turn chip off */ + return tpa6130a2_power(data, false); } - - return 0; } /* -- cgit v0.10.2 From 28823ebad5e73bd717ca820929de2d18415d9822 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 20 Sep 2016 13:52:32 +0100 Subject: ASoC: wm_adsp: Separate concept of booted and running Currently the wm_adsp driver has a flag that indicates the DSP is "running", this flag is used to gate access to the hardware. However this flag is actually set in the firmware download thread after the firmware has been downloaded, but this is before the core is actually started running, so really it currently indicates that the core has been booted and is perhaps running. This patch clearly separates out the concepts of booted (firmware is downloaded) and running (code is executing on the DSP) within the wm_adsp driver. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 21fbe7d..ae2f2b6 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -480,7 +480,7 @@ static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file, mutex_lock(&dsp->pwr_lock); - if (!dsp->wmfw_file_name || !dsp->running) + if (!dsp->wmfw_file_name || !dsp->booted) ret = 0; else ret = simple_read_from_buffer(user_buf, count, ppos, @@ -500,7 +500,7 @@ static ssize_t wm_adsp_debugfs_bin_read(struct file *file, mutex_lock(&dsp->pwr_lock); - if (!dsp->bin_file_name || !dsp->running) + if (!dsp->bin_file_name || !dsp->booted) ret = 0; else ret = simple_read_from_buffer(user_buf, count, ppos, @@ -554,6 +554,9 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp, if (!root) goto err; + if (!debugfs_create_bool("booted", S_IRUGO, root, &dsp->booted)) + goto err; + if (!debugfs_create_bool("running", S_IRUGO, root, &dsp->running)) goto err; @@ -637,7 +640,7 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, mutex_lock(&dsp[e->shift_l].pwr_lock); - if (dsp[e->shift_l].running || dsp[e->shift_l].compr) + if (dsp[e->shift_l].booted || dsp[e->shift_l].compr) ret = -EBUSY; else dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0]; @@ -789,7 +792,7 @@ static int wm_coeff_put(struct snd_kcontrol *kctl, memcpy(ctl->cache, p, ctl->len); ctl->set = 1; - if (ctl->enabled) + if (ctl->enabled && ctl->dsp->booted) ret = wm_coeff_write_control(ctl, p, ctl->len); mutex_unlock(&ctl->dsp->pwr_lock); @@ -811,7 +814,7 @@ static int wm_coeff_tlv_put(struct snd_kcontrol *kctl, ret = -EFAULT; } else { ctl->set = 1; - if (ctl->enabled) + if (ctl->enabled && ctl->dsp->booted) ret = wm_coeff_write_control(ctl, ctl->cache, size); } @@ -871,12 +874,12 @@ static int wm_coeff_get(struct snd_kcontrol *kctl, mutex_lock(&ctl->dsp->pwr_lock); if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { - if (ctl->enabled) + if (ctl->enabled && ctl->dsp->booted) ret = wm_coeff_read_control(ctl, p, ctl->len); else ret = -EPERM; } else { - if (!ctl->flags && ctl->enabled) + if (!ctl->flags && ctl->enabled && ctl->dsp->booted) ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len); memcpy(p, ctl->cache, ctl->len); @@ -898,12 +901,12 @@ static int wm_coeff_tlv_get(struct snd_kcontrol *kctl, mutex_lock(&ctl->dsp->pwr_lock); if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { - if (ctl->enabled) + if (ctl->enabled && ctl->dsp->booted) ret = wm_coeff_read_control(ctl, ctl->cache, size); else ret = -EPERM; } else { - if (!ctl->flags && ctl->enabled) + if (!ctl->flags && ctl->enabled && ctl->dsp->booted) ret = wm_coeff_read_control(ctl, ctl->cache, size); } @@ -2166,13 +2169,20 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, if (ret != 0) goto err_ena; + dsp->booted = true; + /* Start the core running */ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, ADSP1_CORE_ENA | ADSP1_START, ADSP1_CORE_ENA | ADSP1_START); + + dsp->running = true; break; case SND_SOC_DAPM_PRE_PMD: + dsp->running = false; + dsp->booted = false; + /* Halt the core */ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, ADSP1_CORE_ENA | ADSP1_START, 0); @@ -2275,7 +2285,7 @@ static void wm_adsp2_boot_work(struct work_struct *work) if (ret != 0) goto err_ena; - dsp->running = true; + dsp->booted = true; mutex_unlock(&dsp->pwr_lock); @@ -2336,7 +2346,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: flush_work(&dsp->boot_work); - if (!dsp->running) + if (!dsp->booted) return -EIO; ret = regmap_update_bits(dsp->regmap, @@ -2346,6 +2356,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, if (ret != 0) goto err; + dsp->running = true; + mutex_lock(&dsp->pwr_lock); if (wm_adsp_fw[dsp->fw].num_caps != 0) @@ -2365,7 +2377,9 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, dsp->fw_id = 0; dsp->fw_id_version = 0; + dsp->running = false; + dsp->booted = false; regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, ADSP2_CORE_ENA | ADSP2_START, 0); diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index be3b5bc..6a054e7 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -61,6 +61,8 @@ struct wm_adsp { int fw; int fw_ver; + + bool booted; bool running; struct list_head ctl_list; -- cgit v0.10.2 From cef45771c141fdccebe4cb7e0ce79f4687275494 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 20 Sep 2016 13:52:33 +0100 Subject: ASoC: wm_adsp: Move control cache sync out of preloader As part of the work to download firmware before the audio path is brought up the DSP will be put into a low power state between downloading firmware to the core and starting it running. This will mean that the firmware ALSA controls are not accessible in the hardware during this period of time. To prepare for this change we gate access to the hardware in the ALSA control handlers on the DSP being running rather than simply booted and move the synchronisation of the control caches out of the preloader delayed work and into the main DAPM thread after the DSP will have been brought out of its low power state. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index ae2f2b6..24485ec 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -792,7 +792,7 @@ static int wm_coeff_put(struct snd_kcontrol *kctl, memcpy(ctl->cache, p, ctl->len); ctl->set = 1; - if (ctl->enabled && ctl->dsp->booted) + if (ctl->enabled && ctl->dsp->running) ret = wm_coeff_write_control(ctl, p, ctl->len); mutex_unlock(&ctl->dsp->pwr_lock); @@ -814,7 +814,7 @@ static int wm_coeff_tlv_put(struct snd_kcontrol *kctl, ret = -EFAULT; } else { ctl->set = 1; - if (ctl->enabled && ctl->dsp->booted) + if (ctl->enabled && ctl->dsp->running) ret = wm_coeff_write_control(ctl, ctl->cache, size); } @@ -874,12 +874,12 @@ static int wm_coeff_get(struct snd_kcontrol *kctl, mutex_lock(&ctl->dsp->pwr_lock); if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { - if (ctl->enabled && ctl->dsp->booted) + if (ctl->enabled && ctl->dsp->running) ret = wm_coeff_read_control(ctl, p, ctl->len); else ret = -EPERM; } else { - if (!ctl->flags && ctl->enabled && ctl->dsp->booted) + if (!ctl->flags && ctl->enabled && ctl->dsp->running) ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len); memcpy(p, ctl->cache, ctl->len); @@ -901,12 +901,12 @@ static int wm_coeff_tlv_get(struct snd_kcontrol *kctl, mutex_lock(&ctl->dsp->pwr_lock); if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { - if (ctl->enabled && ctl->dsp->booted) + if (ctl->enabled && ctl->dsp->running) ret = wm_coeff_read_control(ctl, ctl->cache, size); else ret = -EPERM; } else { - if (!ctl->flags && ctl->enabled && ctl->dsp->booted) + if (!ctl->flags && ctl->enabled && ctl->dsp->running) ret = wm_coeff_read_control(ctl, ctl->cache, size); } @@ -2280,11 +2280,6 @@ static void wm_adsp2_boot_work(struct work_struct *work) if (ret != 0) goto err_ena; - /* Sync set controls */ - ret = wm_coeff_sync_controls(dsp); - if (ret != 0) - goto err_ena; - dsp->booted = true; mutex_unlock(&dsp->pwr_lock); @@ -2349,6 +2344,11 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, if (!dsp->booted) return -EIO; + /* Sync set controls */ + ret = wm_coeff_sync_controls(dsp); + if (ret != 0) + goto err; + ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, ADSP2_CORE_ENA | ADSP2_START, -- cgit v0.10.2 From 3577357a1680543b8acb98d69d23e87c1175db2b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 20 Sep 2016 13:52:30 +0100 Subject: ASoC: arizona: Attach SYSCLK to DSP preloaders Currently SYSCLK is attached to every compressed DAI as this follows the pattern of attaching clocks to the chips inputs and outputs, however, it is really the DSP that requires the clock here. As firmware download can be a significant part of the path startup time for these devices occasionally it would be desirable to download the firmware in advance of the path being brought up. To help facilitate this early firmware loading this patch attaches the SYSCLK to the DSP preloader widget. This also saves us adding a new route to SYSCLK every time a new compressed DAI is created. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 69da1ef..e49955d 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -190,6 +190,7 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; #define ARIZONA_DSP_ROUTES(name) \ { name, NULL, name " Preloader"}, \ + { name " Preloader", NULL, "SYSCLK" }, \ { name " Preloader", NULL, name " Aux 1" }, \ { name " Preloader", NULL, name " Aux 2" }, \ { name " Preloader", NULL, name " Aux 3" }, \ diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index f8d8139..9576dbd 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -814,7 +814,6 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = { { "AIF3 Capture", NULL, "SYSCLK" }, { "Voice Control DSP", NULL, "DSP3" }, - { "Voice Control DSP", NULL, "SYSCLK" }, { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" }, @@ -823,7 +822,6 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = { { "IN2R PGA", NULL, "IN2R" }, { "Audio Trace DSP", NULL, "DSP2" }, - { "Audio Trace DSP", NULL, "SYSCLK" }, ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 16a1c5b..8ce7680 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1610,7 +1610,6 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { { "Slim3 Capture", NULL, "SYSCLK" }, { "Audio Trace DSP", NULL, "DSP1" }, - { "Audio Trace DSP", NULL, "SYSCLK" }, { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" }, diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 673dc59..5d8c5b6 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -1842,10 +1842,8 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { { "Slim3 Capture", NULL, "SYSCLK" }, { "Voice Control DSP", NULL, "DSP3" }, - { "Voice Control DSP", NULL, "SYSCLK" }, { "Audio Trace DSP", NULL, "DSP1" }, - { "Audio Trace DSP", NULL, "SYSCLK" }, { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" }, -- cgit v0.10.2 From 5ca7e170e331781fe71acb4919667993bb9fbab6 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 20 Sep 2016 13:52:31 +0100 Subject: ASoC: wm_adsp: Make DSP preloader a supply widget Currently the DSP loading is split into two widgets, the preloader that is a snd_soc_dapm_dai_link widget which starts a thread to download the firmware, and the DSP itself which is a snd_soc_dapm_out_drv and synchronises the thread back in to the DAPM sequence. This allows the firmware download to be overlapped with the rest of the path bring up. The use of a snd_soc_dapm_dai_link widget requires the preloader to be part of the audio path in DAPM, really a supply widget is a better fit for the preloader. The preloader is something that needs to be done for the DSP to function, not a part of the audio path itself. This change makes the DSP preloader widget a supply widget, which as well as probably being a better fit will also make it much simpler to power up the preloader widget to trigger firmware download to the core independently of the audio path coming up. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index e49955d..850aa33 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -191,20 +191,20 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; #define ARIZONA_DSP_ROUTES(name) \ { name, NULL, name " Preloader"}, \ { name " Preloader", NULL, "SYSCLK" }, \ - { name " Preloader", NULL, name " Aux 1" }, \ - { name " Preloader", NULL, name " Aux 2" }, \ - { name " Preloader", NULL, name " Aux 3" }, \ - { name " Preloader", NULL, name " Aux 4" }, \ - { name " Preloader", NULL, name " Aux 5" }, \ - { name " Preloader", NULL, name " Aux 6" }, \ + { name, NULL, name " Aux 1" }, \ + { name, NULL, name " Aux 2" }, \ + { name, NULL, name " Aux 3" }, \ + { name, NULL, name " Aux 4" }, \ + { name, NULL, name " Aux 5" }, \ + { name, NULL, name " Aux 6" }, \ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \ ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \ - ARIZONA_MIXER_ROUTES(name " Preloader", name "L"), \ - ARIZONA_MIXER_ROUTES(name " Preloader", name "R") + ARIZONA_MIXER_ROUTES(name, name "L"), \ + ARIZONA_MIXER_ROUTES(name, name "R") #define ARIZONA_EQ_CONTROL(xname, xbase) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 6a054e7..228b1f9 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -87,9 +87,10 @@ struct wm_adsp { wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) #define WM_ADSP2(wname, num, event_fn) \ -{ .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \ +{ .id = snd_soc_dapm_supply, .name = wname " Preloader", \ .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ - .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \ + .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ + .subseq = 100, /* Ensure we run after SYSCLK supply widget */ }, \ { .id = snd_soc_dapm_out_drv, .name = wname, \ .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } -- cgit v0.10.2 From 090d93488135c8422d7711a8cefa4ed1cff7744a Mon Sep 17 00:00:00 2001 From: Randy Li Date: Tue, 20 Sep 2016 02:57:50 +0800 Subject: ASoC: exynos: organize the asoc audio into a menu It is simple sound card time, we could assign different codec to a interface without making a specific driver for it. The SPDIF and I2S interface for Samsung would be possible used by simple-sound-card, but not sure about the PCM. Those S3C time entries are left alone as I don't think any new board would need them. Signed-off-by: Randy Li Reviewed-by: Krzysztof Kozlowski Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 7b722b0..f6023b4 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -1,12 +1,14 @@ -config SND_SOC_SAMSUNG +menuconfig SND_SOC_SAMSUNG tristate "ASoC support for Samsung" depends on (PLAT_SAMSUNG || ARCH_EXYNOS) select SND_SOC_GENERIC_DMAENGINE_PCM - help + ---help--- Say Y or M if you want to add support for codecs attached to the Samsung SoCs' Audio interfaces. You will also need to select the audio interfaces to support below. +if SND_SOC_SAMSUNG + config SND_S3C24XX_I2S tristate @@ -18,22 +20,22 @@ config SND_S3C2412_SOC_I2S select SND_S3C_I2SV2_SOC config SND_SAMSUNG_PCM - tristate + tristate "Samsung PCM interface support" config SND_SAMSUNG_AC97 tristate select SND_SOC_AC97_BUS config SND_SAMSUNG_SPDIF - tristate + tristate "Samsung SPDIF transmitter support" select SND_SOC_SPDIF config SND_SAMSUNG_I2S - tristate + tristate "Samsung I2S interface support" config SND_SOC_SAMSUNG_NEO1973_WM8753 tristate "Audio support for Openmoko Neo1973 Smartphones (GTA02)" - depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA02 + depends on MACH_NEO1973_GTA02 select SND_S3C24XX_I2S select SND_SOC_WM8753 select SND_SOC_BT_SCO @@ -43,7 +45,7 @@ config SND_SOC_SAMSUNG_NEO1973_WM8753 config SND_SOC_SAMSUNG_JIVE_WM8750 tristate "SoC I2S Audio support for Jive" - depends on SND_SOC_SAMSUNG && MACH_JIVE && I2C + depends on MACH_JIVE && I2C select SND_SOC_WM8750 select SND_S3C2412_SOC_I2S help @@ -51,7 +53,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750 config SND_SOC_SAMSUNG_SMDK_WM8580 tristate "SoC I2S Audio support for WM8580 on SMDK" - depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) + depends on MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110 depends on I2C select SND_SOC_WM8580 select SND_SAMSUNG_I2S @@ -60,7 +62,6 @@ config SND_SOC_SAMSUNG_SMDK_WM8580 config SND_SOC_SAMSUNG_SMDK_WM8994 tristate "SoC I2S Audio support for WM8994 on SMDK" - depends on SND_SOC_SAMSUNG depends on I2C=y select MFD_WM8994 select SND_SOC_WM8994 @@ -70,7 +71,7 @@ config SND_SOC_SAMSUNG_SMDK_WM8994 config SND_SOC_SAMSUNG_SMDK2443_WM9710 tristate "SoC AC97 Audio support for SMDK2443 - WM9710" - depends on SND_SOC_SAMSUNG && MACH_SMDK2443 + depends on MACH_SMDK2443 select AC97_BUS select SND_SOC_AC97_CODEC select SND_SAMSUNG_AC97 @@ -80,7 +81,7 @@ config SND_SOC_SAMSUNG_SMDK2443_WM9710 config SND_SOC_SAMSUNG_LN2440SBC_ALC650 tristate "SoC AC97 Audio support for LN2440SBC - ALC650" - depends on SND_SOC_SAMSUNG && ARCH_S3C24XX + depends on ARCH_S3C24XX select AC97_BUS select SND_SOC_AC97_CODEC select SND_SAMSUNG_AC97 @@ -90,7 +91,7 @@ config SND_SOC_SAMSUNG_LN2440SBC_ALC650 config SND_SOC_SAMSUNG_S3C24XX_UDA134X tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" - depends on SND_SOC_SAMSUNG && ARCH_S3C24XX + depends on ARCH_S3C24XX select SND_S3C24XX_I2S select SND_SOC_L3 select SND_SOC_UDA134X @@ -102,21 +103,21 @@ config SND_SOC_SAMSUNG_SIMTEC config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23 tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" - depends on SND_SOC_SAMSUNG && ARCH_S3C24XX && I2C + depends on ARCH_S3C24XX && I2C select SND_S3C24XX_I2S select SND_SOC_TLV320AIC23_I2C select SND_SOC_SAMSUNG_SIMTEC config SND_SOC_SAMSUNG_SIMTEC_HERMES tristate "SoC I2S Audio support for Simtec Hermes board" - depends on SND_SOC_SAMSUNG && ARCH_S3C24XX && I2C + depends on ARCH_S3C24XX && I2C select SND_S3C24XX_I2S select SND_SOC_TLV320AIC3X select SND_SOC_SAMSUNG_SIMTEC config SND_SOC_SAMSUNG_H1940_UDA1380 tristate "Audio support for the HP iPAQ H1940" - depends on SND_SOC_SAMSUNG && ARCH_H1940 && I2C + depends on ARCH_H1940 && I2C select SND_S3C24XX_I2S select SND_SOC_UDA1380 help @@ -124,7 +125,7 @@ config SND_SOC_SAMSUNG_H1940_UDA1380 config SND_SOC_SAMSUNG_RX1950_UDA1380 tristate "Audio support for the HP iPAQ RX1950" - depends on SND_SOC_SAMSUNG && MACH_RX1950 && I2C + depends on MACH_RX1950 && I2C select SND_S3C24XX_I2S select SND_SOC_UDA1380 help @@ -132,7 +133,7 @@ config SND_SOC_SAMSUNG_RX1950_UDA1380 config SND_SOC_SAMSUNG_SMDK_WM9713 tristate "SoC AC97 Audio support for SMDK with WM9713" - depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) + depends on MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110 select SND_SOC_WM9713 select SND_SAMSUNG_AC97 help @@ -140,20 +141,19 @@ config SND_SOC_SAMSUNG_SMDK_WM9713 config SND_SOC_SMARTQ tristate "SoC I2S Audio support for SmartQ board" - depends on SND_SOC_SAMSUNG && MACH_SMARTQ && I2C + depends on MACH_SMARTQ && I2C select SND_SAMSUNG_I2S select SND_SOC_WM8750 config SND_SOC_SAMSUNG_SMDK_SPDIF tristate "SoC S/PDIF Audio support for SMDK" - depends on SND_SOC_SAMSUNG select SND_SAMSUNG_SPDIF help Say Y if you want to add support for SoC S/PDIF audio on the SMDK. config SND_SOC_SMDK_WM8580_PCM tristate "SoC PCM Audio support for WM8580 on SMDK" - depends on SND_SOC_SAMSUNG && (MACH_SMDKV210 || MACH_SMDKC110) + depends on MACH_SMDKV210 || MACH_SMDKC110 depends on I2C select SND_SOC_WM8580 select SND_SAMSUNG_PCM @@ -162,7 +162,6 @@ config SND_SOC_SMDK_WM8580_PCM config SND_SOC_SMDK_WM8994_PCM tristate "SoC PCM Audio support for WM8994 on SMDK" - depends on SND_SOC_SAMSUNG depends on I2C=y select MFD_WM8994 select SND_SOC_WM8994 @@ -172,7 +171,7 @@ config SND_SOC_SMDK_WM8994_PCM config SND_SOC_SPEYSIDE tristate "Audio support for Wolfson Speyside" - depends on SND_SOC_SAMSUNG && I2C && SPI_MASTER + depends on I2C && SPI_MASTER depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST select SND_SAMSUNG_I2S select SND_SOC_WM8996 @@ -182,14 +181,14 @@ config SND_SOC_SPEYSIDE config SND_SOC_TOBERMORY tristate "Audio support for Wolfson Tobermory" - depends on SND_SOC_SAMSUNG && INPUT && I2C + depends on INPUT && I2C depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST select SND_SAMSUNG_I2S select SND_SOC_WM8962 config SND_SOC_BELLS tristate "Audio support for Wolfson Bells" - depends on SND_SOC_SAMSUNG && MFD_ARIZONA && I2C && SPI_MASTER + depends on MFD_ARIZONA && I2C && SPI_MASTER depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST select SND_SAMSUNG_I2S select SND_SOC_WM5102 @@ -200,7 +199,7 @@ config SND_SOC_BELLS config SND_SOC_LOWLAND tristate "Audio support for Wolfson Lowland" - depends on SND_SOC_SAMSUNG && I2C + depends on I2C depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST select SND_SAMSUNG_I2S select SND_SOC_WM5100 @@ -208,7 +207,7 @@ config SND_SOC_LOWLAND config SND_SOC_LITTLEMILL tristate "Audio support for Wolfson Littlemill" - depends on SND_SOC_SAMSUNG && I2C + depends on I2C depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST select SND_SAMSUNG_I2S select MFD_WM8994 @@ -216,7 +215,7 @@ config SND_SOC_LITTLEMILL config SND_SOC_SNOW tristate "Audio support for Google Snow boards" - depends on SND_SOC_SAMSUNG && I2C + depends on I2C select SND_SOC_MAX98090 select SND_SOC_MAX98095 select SND_SAMSUNG_I2S @@ -226,6 +225,8 @@ config SND_SOC_SNOW config SND_SOC_ARNDALE_RT5631_ALC5631 tristate "Audio support for RT5631(ALC5631) on Arndale Board" - depends on SND_SOC_SAMSUNG && I2C + depends on I2C select SND_SAMSUNG_I2S select SND_SOC_RT5631 + +endif #SND_SOC_SAMSUNG -- cgit v0.10.2 From ecd286a9d8a75771f73110b990512f10dc342356 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 16 Sep 2016 18:51:21 +0100 Subject: ASoC: Intel: Skylake: add missing \n to end of dev_* messages Trival fix, some dev_* messages are missing a \n, so add it. Signed-off-by: Colin Ian King Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 48a4ae5..1d251d5 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -404,7 +404,7 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) ret = skl_dsp_disable_core(ctx, core_mask); if (ret < 0) { - dev_err(ctx->dev, "Failed to disable core %d", ret); + dev_err(ctx->dev, "Failed to disable core %d\n", ret); return ret; } skl->cores.state[core_id] = SKL_DSP_RESET; @@ -489,7 +489,7 @@ int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx) ret = sst->fw_ops.load_fw(sst); if (ret < 0) { - dev_err(dev, "Load base fw failed: %x", ret); + dev_err(dev, "Load base fw failed: %x\n", ret); return ret; } @@ -498,7 +498,7 @@ int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx) if (ctx->manifest.lib_count > 1) { ret = sst->fw_ops.load_library(sst, &ctx->manifest); if (ret < 0) { - dev_err(dev, "Load Library failed : %x", ret); + dev_err(dev, "Load Library failed : %x\n", ret); return ret; } } diff --git a/sound/soc/intel/skylake/skl-sst-cldma.c b/sound/soc/intel/skylake/skl-sst-cldma.c index da2329d..efa2532 100644 --- a/sound/soc/intel/skylake/skl-sst-cldma.c +++ b/sound/soc/intel/skylake/skl-sst-cldma.c @@ -341,14 +341,14 @@ int skl_cldma_prepare(struct sst_dsp *ctx) ret = ctx->dsp_ops.alloc_dma_buf(ctx->dev, &ctx->cl_dev.dmab_data, ctx->cl_dev.bufsize); if (ret < 0) { - dev_err(ctx->dev, "Alloc buffer for base fw failed: %x", ret); + dev_err(ctx->dev, "Alloc buffer for base fw failed: %x\n", ret); return ret; } /* Setup Code loader BDL */ ret = ctx->dsp_ops.alloc_dma_buf(ctx->dev, &ctx->cl_dev.dmab_bdl, PAGE_SIZE); if (ret < 0) { - dev_err(ctx->dev, "Alloc buffer for blde failed: %x", ret); + dev_err(ctx->dev, "Alloc buffer for blde failed: %x\n", ret); ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_data); return ret; } diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 74dbecc..0bd01e6 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -344,7 +344,7 @@ static int skl_ipc_process_notification(struct sst_generic_ipc *ipc, break; default: - dev_err(ipc->dev, "ipc: Unhandled error msg=%x", + dev_err(ipc->dev, "ipc: Unhandled error msg=%x\n", header.primary); break; } @@ -385,13 +385,13 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, break; default: - dev_err(ipc->dev, "Unknown ipc reply: 0x%x", reply); + dev_err(ipc->dev, "Unknown ipc reply: 0x%x\n", reply); msg->errno = -EINVAL; break; } if (reply != IPC_GLB_REPLY_SUCCESS) { - dev_err(ipc->dev, "ipc FW reply: reply=%d", reply); + dev_err(ipc->dev, "ipc FW reply: reply=%d\n", reply); dev_err(ipc->dev, "FW Error Code: %u\n", ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); } @@ -440,9 +440,9 @@ irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE); header.primary = hipct; header.extension = hipcte; - dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x", + dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x\n", header.primary); - dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x", + dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x\n", header.extension); if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) { @@ -749,7 +749,7 @@ int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, header.extension); ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); if (ret < 0) { - dev_err(ipc->dev, "ipc: bind/unbind faileden"); + dev_err(ipc->dev, "ipc: bind/unbind failed\n"); return ret; } diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 064fc7e..8fc3178 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -107,13 +107,13 @@ static int skl_load_base_firmware(struct sst_dsp *ctx) ret = skl_dsp_boot(ctx); if (ret < 0) { - dev_err(ctx->dev, "Boot dsp core failed ret: %d", ret); + dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret); goto skl_load_base_firmware_failed; } ret = skl_cldma_prepare(ctx); if (ret < 0) { - dev_err(ctx->dev, "CL dma prepare failed : %d", ret); + dev_err(ctx->dev, "CL dma prepare failed : %d\n", ret); goto skl_load_base_firmware_failed; } @@ -502,7 +502,7 @@ int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx) ret = sst->fw_ops.load_fw(sst); if (ret < 0) { - dev_err(dev, "Load base fw failed : %d", ret); + dev_err(dev, "Load base fw failed : %d\n", ret); return ret; } diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index e48f872..b5b1934 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -1614,7 +1614,7 @@ static int skl_tplg_fill_pins_info(struct device *dev, break; default: - dev_err(dev, "Invalid direction value"); + dev_err(dev, "Invalid direction value\n"); return -EINVAL; } @@ -1652,7 +1652,7 @@ static int skl_tplg_fill_fmt(struct device *dev, break; default: - dev_err(dev, "Invalid direction value"); + dev_err(dev, "Invalid direction value\n"); return -EINVAL; } @@ -1690,7 +1690,7 @@ static int skl_tplg_fill_fmt(struct device *dev, break; default: - dev_err(dev, "Invalid token %d", tkn); + dev_err(dev, "Invalid token %d\n", tkn); return -EINVAL; } @@ -1703,7 +1703,7 @@ static int skl_tplg_get_uuid(struct device *dev, struct skl_module_cfg *mconfig, if (uuid_tkn->token == SKL_TKN_UUID) memcpy(&mconfig->guid, &uuid_tkn->uuid, 16); else { - dev_err(dev, "Not an UUID token tkn %d", uuid_tkn->token); + dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token); return -EINVAL; } @@ -1939,7 +1939,7 @@ static int skl_tplg_get_tokens(struct device *dev, switch (array->type) { case SND_SOC_TPLG_TUPLE_TYPE_STRING: - dev_warn(dev, "no string tokens expected for skl tplg"); + dev_warn(dev, "no string tokens expected for skl tplg\n"); continue; case SND_SOC_TPLG_TUPLE_TYPE_UUID: @@ -1992,7 +1992,7 @@ static int skl_tplg_get_desc_blocks(struct device *dev, return tkn_elem->value; default: - dev_err(dev, "Invalid descriptor token %d", tkn_elem->token); + dev_err(dev, "Invalid descriptor token %d\n", tkn_elem->token); break; } @@ -2252,7 +2252,7 @@ static int skl_tplg_fill_str_mfest_tkn(struct device *dev, break; default: - dev_err(dev, "Not a string token %d", str_elem->token); + dev_err(dev, "Not a string token %d\n", str_elem->token); break; } @@ -2293,7 +2293,7 @@ static int skl_tplg_get_int_tkn(struct device *dev, break; default: - dev_err(dev, "Not a manifest token %d", tkn_elem->token); + dev_err(dev, "Not a manifest token %d\n", tkn_elem->token); return -EINVAL; } @@ -2332,7 +2332,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, continue; case SND_SOC_TPLG_TUPLE_TYPE_UUID: - dev_warn(dev, "no uuid tokens for skl tplf manifest"); + dev_warn(dev, "no uuid tokens for skl tplf manifest\n"); continue; default: -- cgit v0.10.2 From 478cc9f93c28dccd1db373a4c996fefb5d67b072 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 16 Sep 2016 17:52:16 +0100 Subject: ASoC: max98926: add missing \n to end of dev_err/dev_dbg messages Trival fix, some dev_err and deb_dbg messages are missing a \n, so add it. Signed-off-by: Colin Ian King Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c index 8d14ada..96073d4 100644 --- a/sound/soc/codecs/max98926.c +++ b/sound/soc/codecs/max98926.c @@ -347,7 +347,7 @@ static int max98926_dai_set_fmt(struct snd_soc_dai *codec_dai, max98926_set_sense_data(max98926); break; default: - dev_err(codec->dev, "DAI clock mode unsupported"); + dev_err(codec->dev, "DAI clock mode unsupported\n"); return -EINVAL; } @@ -364,7 +364,7 @@ static int max98926_dai_set_fmt(struct snd_soc_dai *codec_dai, invert = MAX98926_DAI_BCI_MASK | MAX98926_DAI_WCI_MASK; break; default: - dev_err(codec->dev, "DAI invert mode unsupported"); + dev_err(codec->dev, "DAI invert mode unsupported\n"); return -EINVAL; } @@ -408,7 +408,7 @@ static int max98926_dai_hw_params(struct snd_pcm_substream *substream, max98926->ch_size = 32; break; default: - dev_dbg(codec->dev, "format unsupported %d", + dev_dbg(codec->dev, "format unsupported %d\n", params_format(params)); return -EINVAL; } -- cgit v0.10.2 From 5f6af6a75ef3fed8eb220217ecd7d1c7ef8571d9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 16 Sep 2016 18:30:53 +0100 Subject: ASoC: samsung: add missing \n to end of pr_err messages Trival fix, some pr_err messages are missing a \n, so add it. Signed-off-by: Colin Ian King Reviewed-by: Krzysztof Kozlowski Signed-off-by: Mark Brown diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index 5eafb66..97d6700 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c @@ -74,7 +74,7 @@ static void s3c_ac97_activate(struct snd_ac97 *ac97) writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) - pr_err("AC97: Unable to activate!"); + pr_err("AC97: Unable to activate!\n"); } static unsigned short s3c_ac97_read(struct snd_ac97 *ac97, @@ -100,7 +100,7 @@ static unsigned short s3c_ac97_read(struct snd_ac97 *ac97, writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) - pr_err("AC97: Unable to read!"); + pr_err("AC97: Unable to read!\n"); stat = readl(s3c_ac97.regs + S3C_AC97_STAT); addr = (stat >> 16) & 0x7f; @@ -137,7 +137,7 @@ static void s3c_ac97_write(struct snd_ac97 *ac97, unsigned short reg, writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) - pr_err("AC97: Unable to write!"); + pr_err("AC97: Unable to write!\n"); ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD); ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ; -- cgit v0.10.2 From 1635c694124fe66933ae3db0d39dacb44c53f4b9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 16 Sep 2016 18:37:31 +0100 Subject: ASoC: Intel: atom: add missing \n to end of dev_err/dev_dbg messages Trival fix, some dev_err/deb_dbg messages are missing a \n, so add it. Signed-off-by: Colin Ian King Signed-off-by: Mark Brown diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index 773acfb..9718e82 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c @@ -166,7 +166,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) rsrc = platform_get_resource(pdev, IORESOURCE_MEM, ctx->pdata->res_info->acpi_lpe_res_index); if (!rsrc) { - dev_err(ctx->dev, "Invalid SHIM base from IFWI"); + dev_err(ctx->dev, "Invalid SHIM base from IFWI\n"); return -EIO; } dev_info(ctx->dev, "LPE base: %#x size:%#x", (unsigned int) rsrc->start, @@ -178,7 +178,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) ctx->iram = devm_ioremap_nocache(ctx->dev, ctx->iram_base, ctx->pdata->res_info->iram_size); if (!ctx->iram) { - dev_err(ctx->dev, "unable to map IRAM"); + dev_err(ctx->dev, "unable to map IRAM\n"); return -EIO; } @@ -188,7 +188,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) ctx->dram = devm_ioremap_nocache(ctx->dev, ctx->dram_base, ctx->pdata->res_info->dram_size); if (!ctx->dram) { - dev_err(ctx->dev, "unable to map DRAM"); + dev_err(ctx->dev, "unable to map DRAM\n"); return -EIO; } @@ -197,7 +197,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) ctx->shim = devm_ioremap_nocache(ctx->dev, ctx->shim_phy_add, ctx->pdata->res_info->shim_size); if (!ctx->shim) { - dev_err(ctx->dev, "unable to map SHIM"); + dev_err(ctx->dev, "unable to map SHIM\n"); return -EIO; } @@ -210,7 +210,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) ctx->mailbox = devm_ioremap_nocache(ctx->dev, ctx->mailbox_add, ctx->pdata->res_info->mbox_size); if (!ctx->mailbox) { - dev_err(ctx->dev, "unable to map mailbox"); + dev_err(ctx->dev, "unable to map mailbox\n"); return -EIO; } @@ -220,7 +220,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) rsrc = platform_get_resource(pdev, IORESOURCE_MEM, ctx->pdata->res_info->acpi_ddr_index); if (!rsrc) { - dev_err(ctx->dev, "Invalid DDR base from IFWI"); + dev_err(ctx->dev, "Invalid DDR base from IFWI\n"); return -EIO; } ctx->ddr_base = rsrc->start; @@ -229,7 +229,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) ctx->ddr = devm_ioremap_nocache(ctx->dev, ctx->ddr_base, resource_size(rsrc)); if (!ctx->ddr) { - dev_err(ctx->dev, "unable to map DDR"); + dev_err(ctx->dev, "unable to map DDR\n"); return -EIO; } @@ -296,7 +296,7 @@ static int sst_acpi_probe(struct platform_device *pdev) id = acpi_match_device(dev->driver->acpi_match_table, dev); if (!id) return -ENODEV; - dev_dbg(dev, "for %s", id->id); + dev_dbg(dev, "for %s\n", id->id); mach = (struct sst_acpi_mach *)id->driver_data; mach = sst_acpi_find_machine(mach); -- cgit v0.10.2 From 2b26dd4c1fc5f83bc088f4a053120ca03817045e Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Mon, 19 Sep 2016 19:26:08 +0800 Subject: ASoC: rt5660: add rt5660 codec driver This is the initial codec driver for rt5660 Signed-off-by: Oder Chiou Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/rt5660.txt b/Documentation/devicetree/bindings/sound/rt5660.txt new file mode 100644 index 0000000..30be5f9 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rt5660.txt @@ -0,0 +1,47 @@ +RT5660 audio CODEC + +This device supports I2C only. + +Required properties: + +- compatible : "realtek,rt5660". + +- reg : The I2C address of the device. + +Optional properties: + +- clocks: The phandle of the master clock to the CODEC +- clock-names: Should be "mclk" + +- realtek,in1-differential +- realtek,in3-differential + Boolean. Indicate MIC1/3 input are differential, rather than single-ended. + +- realtek,poweroff-in-suspend + Boolean. If the codec will be powered off in suspend, the resume should be + added delay time for waiting codec power ready. + +- realtek,dmic1-data-pin + 0: dmic1 is not used + 1: using GPIO2 pin as dmic1 data pin + 2: using IN1P pin as dmic1 data pin + +Pins on the device (for linking into audio routes) for RT5660: + + * DMIC L1 + * DMIC R1 + * IN1P + * IN1N + * IN2P + * IN3P + * IN3N + * SPO + * LOUTL + * LOUTR + +Example: + +rt5660 { + compatible = "realtek,rt5660"; + reg = <0x1c>; +}; diff --git a/include/sound/rt5660.h b/include/sound/rt5660.h new file mode 100644 index 0000000..065f83a --- /dev/null +++ b/include/sound/rt5660.h @@ -0,0 +1,31 @@ +/* + * linux/sound/rt5660.h -- Platform data for RT5660 + * + * Copyright 2016 Realtek Semiconductor Corp. + * Author: Oder Chiou + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __LINUX_SND_RT5660_H +#define __LINUX_SND_RT5660_H + +enum rt5660_dmic1_data_pin { + RT5660_DMIC1_NULL, + RT5660_DMIC1_DATA_GPIO2, + RT5660_DMIC1_DATA_IN1P, +}; + +struct rt5660_platform_data { + /* IN1 & IN3 can optionally be differential */ + bool in1_diff; + bool in3_diff; + bool use_ldo2; + bool poweroff_codec_in_suspend; + + enum rt5660_dmic1_data_pin dmic1_data_pin; +}; + +#endif diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1cd6ab3..890affe 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -112,6 +112,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_RT5645 if I2C select SND_SOC_RT5651 if I2C select SND_SOC_RT5659 if I2C + select SND_SOC_RT5660 if I2C select SND_SOC_RT5670 if I2C select SND_SOC_RT5677 if I2C && SPI_MASTER select SND_SOC_SGTL5000 if I2C @@ -645,6 +646,7 @@ config SND_SOC_RL6231 default y if SND_SOC_RT5645=y default y if SND_SOC_RT5651=y default y if SND_SOC_RT5659=y + default y if SND_SOC_RT5660=y default y if SND_SOC_RT5670=y default y if SND_SOC_RT5677=y default m if SND_SOC_RT5514=m @@ -653,6 +655,7 @@ config SND_SOC_RL6231 default m if SND_SOC_RT5645=m default m if SND_SOC_RT5651=m default m if SND_SOC_RT5659=m + default m if SND_SOC_RT5660=m default m if SND_SOC_RT5670=m default m if SND_SOC_RT5677=m @@ -697,6 +700,9 @@ config SND_SOC_RT5651 config SND_SOC_RT5659 tristate +config SND_SOC_RT5660 + tristate + config SND_SOC_RT5670 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 58036af..68fed20 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -112,6 +112,7 @@ snd-soc-rt5640-objs := rt5640.o snd-soc-rt5645-objs := rt5645.o snd-soc-rt5651-objs := rt5651.o snd-soc-rt5659-objs := rt5659.o +snd-soc-rt5660-objs := rt5660.o snd-soc-rt5670-objs := rt5670.o snd-soc-rt5677-objs := rt5677.o snd-soc-rt5677-spi-objs := rt5677-spi.o @@ -333,6 +334,7 @@ obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o obj-$(CONFIG_SND_SOC_RT5659) += snd-soc-rt5659.o +obj-$(CONFIG_SND_SOC_RT5660) += snd-soc-rt5660.o obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c new file mode 100644 index 0000000..9f0933c --- /dev/null +++ b/sound/soc/codecs/rt5660.c @@ -0,0 +1,1353 @@ +/* + * rt5660.c -- RT5660 ALSA SoC audio codec driver + * + * Copyright 2016 Realtek Semiconductor Corp. + * Author: Oder Chiou + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rl6231.h" +#include "rt5660.h" + +#define RT5660_DEVICE_ID 0x6338 + +#define RT5660_PR_RANGE_BASE (0xff + 1) +#define RT5660_PR_SPACING 0x100 + +#define RT5660_PR_BASE (RT5660_PR_RANGE_BASE + (0 * RT5660_PR_SPACING)) + +static const struct regmap_range_cfg rt5660_ranges[] = { + { .name = "PR", .range_min = RT5660_PR_BASE, + .range_max = RT5660_PR_BASE + 0xf3, + .selector_reg = RT5660_PRIV_INDEX, + .selector_mask = 0xff, + .selector_shift = 0x0, + .window_start = RT5660_PRIV_DATA, + .window_len = 0x1, }, +}; + +static const struct reg_sequence rt5660_patch[] = { + { RT5660_ALC_PGA_CTRL2, 0x44c3 }, + { RT5660_PR_BASE + 0x3d, 0x2600 }, +}; + +static const struct reg_default rt5660_reg[] = { + { 0x00, 0x0000 }, + { 0x01, 0xc800 }, + { 0x02, 0xc8c8 }, + { 0x0d, 0x1010 }, + { 0x0e, 0x1010 }, + { 0x19, 0xafaf }, + { 0x1c, 0x2f2f }, + { 0x1e, 0x0000 }, + { 0x27, 0x6060 }, + { 0x29, 0x8080 }, + { 0x2a, 0x4242 }, + { 0x2f, 0x0000 }, + { 0x3b, 0x0000 }, + { 0x3c, 0x007f }, + { 0x3d, 0x0000 }, + { 0x3e, 0x007f }, + { 0x45, 0xe000 }, + { 0x46, 0x003e }, + { 0x48, 0xf800 }, + { 0x4a, 0x0004 }, + { 0x4d, 0x0000 }, + { 0x4e, 0x0000 }, + { 0x4f, 0x01ff }, + { 0x50, 0x0000 }, + { 0x51, 0x0000 }, + { 0x52, 0x01ff }, + { 0x61, 0x0000 }, + { 0x62, 0x0000 }, + { 0x63, 0x00c0 }, + { 0x64, 0x0000 }, + { 0x65, 0x0000 }, + { 0x66, 0x0000 }, + { 0x70, 0x8000 }, + { 0x73, 0x7000 }, + { 0x74, 0x3c00 }, + { 0x75, 0x2800 }, + { 0x80, 0x0000 }, + { 0x81, 0x0000 }, + { 0x82, 0x0000 }, + { 0x8c, 0x0228 }, + { 0x8d, 0xa000 }, + { 0x8e, 0x0000 }, + { 0x92, 0x0000 }, + { 0x93, 0x3000 }, + { 0xa1, 0x0059 }, + { 0xa2, 0x0001 }, + { 0xa3, 0x5c80 }, + { 0xa4, 0x0146 }, + { 0xa5, 0x1f1f }, + { 0xa6, 0x78c6 }, + { 0xa7, 0xe5ec }, + { 0xa8, 0xba61 }, + { 0xa9, 0x3c78 }, + { 0xaa, 0x8ae2 }, + { 0xab, 0xe5ec }, + { 0xac, 0xc600 }, + { 0xad, 0xba61 }, + { 0xae, 0x17ed }, + { 0xb0, 0x2080 }, + { 0xb1, 0x0000 }, + { 0xb3, 0x001f }, + { 0xb4, 0x020c }, + { 0xb5, 0x1f00 }, + { 0xb6, 0x0000 }, + { 0xb7, 0x4000 }, + { 0xbb, 0x0000 }, + { 0xbd, 0x0000 }, + { 0xbe, 0x0000 }, + { 0xbf, 0x0100 }, + { 0xc0, 0x0000 }, + { 0xc2, 0x0000 }, + { 0xd3, 0xa220 }, + { 0xd9, 0x0809 }, + { 0xda, 0x0000 }, + { 0xe0, 0x8000 }, + { 0xe1, 0x0200 }, + { 0xe2, 0x8000 }, + { 0xe3, 0x0200 }, + { 0xe4, 0x0f20 }, + { 0xe5, 0x001f }, + { 0xe6, 0x020c }, + { 0xe7, 0x1f00 }, + { 0xe8, 0x0000 }, + { 0xe9, 0x4000 }, + { 0xea, 0x00a6 }, + { 0xeb, 0x04c3 }, + { 0xec, 0x27c8 }, + { 0xed, 0x7418 }, + { 0xee, 0xbf50 }, + { 0xef, 0x0045 }, + { 0xf0, 0x0007 }, + { 0xfa, 0x0000 }, + { 0xfd, 0x0000 }, + { 0xfe, 0x10ec }, + { 0xff, 0x6338 }, +}; + +static bool rt5660_volatile_register(struct device *dev, unsigned int reg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(rt5660_ranges); i++) + if ((reg >= rt5660_ranges[i].window_start && + reg <= rt5660_ranges[i].window_start + + rt5660_ranges[i].window_len) || + (reg >= rt5660_ranges[i].range_min && + reg <= rt5660_ranges[i].range_max)) + return true; + + switch (reg) { + case RT5660_RESET: + case RT5660_PRIV_DATA: + case RT5660_EQ_CTRL1: + case RT5660_IRQ_CTRL2: + case RT5660_INT_IRQ_ST: + case RT5660_VENDOR_ID: + case RT5660_VENDOR_ID1: + case RT5660_VENDOR_ID2: + return true; + default: + return false; + } +} + +static bool rt5660_readable_register(struct device *dev, unsigned int reg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(rt5660_ranges); i++) + if ((reg >= rt5660_ranges[i].window_start && + reg <= rt5660_ranges[i].window_start + + rt5660_ranges[i].window_len) || + (reg >= rt5660_ranges[i].range_min && + reg <= rt5660_ranges[i].range_max)) + return true; + + switch (reg) { + case RT5660_RESET: + case RT5660_SPK_VOL: + case RT5660_LOUT_VOL: + case RT5660_IN1_IN2: + case RT5660_IN3_IN4: + case RT5660_DAC1_DIG_VOL: + case RT5660_STO1_ADC_DIG_VOL: + case RT5660_ADC_BST_VOL1: + case RT5660_STO1_ADC_MIXER: + case RT5660_AD_DA_MIXER: + case RT5660_STO_DAC_MIXER: + case RT5660_DIG_INF1_DATA: + case RT5660_REC_L1_MIXER: + case RT5660_REC_L2_MIXER: + case RT5660_REC_R1_MIXER: + case RT5660_REC_R2_MIXER: + case RT5660_LOUT_MIXER: + case RT5660_SPK_MIXER: + case RT5660_SPO_MIXER: + case RT5660_SPO_CLSD_RATIO: + case RT5660_OUT_L_GAIN1: + case RT5660_OUT_L_GAIN2: + case RT5660_OUT_L1_MIXER: + case RT5660_OUT_R_GAIN1: + case RT5660_OUT_R_GAIN2: + case RT5660_OUT_R1_MIXER: + case RT5660_PWR_DIG1: + case RT5660_PWR_DIG2: + case RT5660_PWR_ANLG1: + case RT5660_PWR_ANLG2: + case RT5660_PWR_MIXER: + case RT5660_PWR_VOL: + case RT5660_PRIV_INDEX: + case RT5660_PRIV_DATA: + case RT5660_I2S1_SDP: + case RT5660_ADDA_CLK1: + case RT5660_ADDA_CLK2: + case RT5660_DMIC_CTRL1: + case RT5660_GLB_CLK: + case RT5660_PLL_CTRL1: + case RT5660_PLL_CTRL2: + case RT5660_CLSD_AMP_OC_CTRL: + case RT5660_CLSD_AMP_CTRL: + case RT5660_LOUT_AMP_CTRL: + case RT5660_SPK_AMP_SPKVDD: + case RT5660_MICBIAS: + case RT5660_CLSD_OUT_CTRL1: + case RT5660_CLSD_OUT_CTRL2: + case RT5660_DIPOLE_MIC_CTRL1: + case RT5660_DIPOLE_MIC_CTRL2: + case RT5660_DIPOLE_MIC_CTRL3: + case RT5660_DIPOLE_MIC_CTRL4: + case RT5660_DIPOLE_MIC_CTRL5: + case RT5660_DIPOLE_MIC_CTRL6: + case RT5660_DIPOLE_MIC_CTRL7: + case RT5660_DIPOLE_MIC_CTRL8: + case RT5660_DIPOLE_MIC_CTRL9: + case RT5660_DIPOLE_MIC_CTRL10: + case RT5660_DIPOLE_MIC_CTRL11: + case RT5660_DIPOLE_MIC_CTRL12: + case RT5660_EQ_CTRL1: + case RT5660_EQ_CTRL2: + case RT5660_DRC_AGC_CTRL1: + case RT5660_DRC_AGC_CTRL2: + case RT5660_DRC_AGC_CTRL3: + case RT5660_DRC_AGC_CTRL4: + case RT5660_DRC_AGC_CTRL5: + case RT5660_JD_CTRL: + case RT5660_IRQ_CTRL1: + case RT5660_IRQ_CTRL2: + case RT5660_INT_IRQ_ST: + case RT5660_GPIO_CTRL1: + case RT5660_GPIO_CTRL2: + case RT5660_WIND_FILTER_CTRL1: + case RT5660_SV_ZCD1: + case RT5660_SV_ZCD2: + case RT5660_DRC1_LM_CTRL1: + case RT5660_DRC1_LM_CTRL2: + case RT5660_DRC2_LM_CTRL1: + case RT5660_DRC2_LM_CTRL2: + case RT5660_MULTI_DRC_CTRL: + case RT5660_DRC2_CTRL1: + case RT5660_DRC2_CTRL2: + case RT5660_DRC2_CTRL3: + case RT5660_DRC2_CTRL4: + case RT5660_DRC2_CTRL5: + case RT5660_ALC_PGA_CTRL1: + case RT5660_ALC_PGA_CTRL2: + case RT5660_ALC_PGA_CTRL3: + case RT5660_ALC_PGA_CTRL4: + case RT5660_ALC_PGA_CTRL5: + case RT5660_ALC_PGA_CTRL6: + case RT5660_ALC_PGA_CTRL7: + case RT5660_GEN_CTRL1: + case RT5660_GEN_CTRL2: + case RT5660_GEN_CTRL3: + case RT5660_VENDOR_ID: + case RT5660_VENDOR_ID1: + case RT5660_VENDOR_ID2: + return true; + default: + return false; + } +} + +static const DECLARE_TLV_DB_SCALE(rt5660_out_vol_tlv, -4650, 150, 0); +static const DECLARE_TLV_DB_SCALE(rt5660_dac_vol_tlv, -6525, 75, 0); +static const DECLARE_TLV_DB_SCALE(rt5660_adc_vol_tlv, -1725, 75, 0); +static const DECLARE_TLV_DB_SCALE(rt5660_adc_bst_tlv, 0, 1200, 0); +static const DECLARE_TLV_DB_SCALE(rt5660_bst_tlv, -1200, 75, 0); + +static const struct snd_kcontrol_new rt5660_snd_controls[] = { + /* Speaker Output Volume */ + SOC_SINGLE("Speaker Playback Switch", RT5660_SPK_VOL, RT5660_L_MUTE_SFT, + 1, 1), + SOC_SINGLE_TLV("Speaker Playback Volume", RT5660_SPK_VOL, + RT5660_L_VOL_SFT, 39, 1, rt5660_out_vol_tlv), + + /* OUTPUT Control */ + SOC_DOUBLE("OUT Playback Switch", RT5660_LOUT_VOL, RT5660_L_MUTE_SFT, + RT5660_R_MUTE_SFT, 1, 1), + SOC_DOUBLE_TLV("OUT Playback Volume", RT5660_LOUT_VOL, RT5660_L_VOL_SFT, + RT5660_R_VOL_SFT, 39, 1, rt5660_out_vol_tlv), + + /* DAC Digital Volume */ + SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5660_DAC1_DIG_VOL, + RT5660_DAC_L1_VOL_SFT, RT5660_DAC_R1_VOL_SFT, 87, 0, + rt5660_dac_vol_tlv), + + /* IN1/IN2/IN3 Control */ + SOC_SINGLE_TLV("IN1 Boost Volume", RT5660_IN1_IN2, RT5660_BST_SFT1, 69, + 0, rt5660_bst_tlv), + SOC_SINGLE_TLV("IN2 Boost Volume", RT5660_IN1_IN2, RT5660_BST_SFT2, 69, + 0, rt5660_bst_tlv), + SOC_SINGLE_TLV("IN3 Boost Volume", RT5660_IN3_IN4, RT5660_BST_SFT3, 69, + 0, rt5660_bst_tlv), + + /* ADC Digital Volume Control */ + SOC_DOUBLE("ADC Capture Switch", RT5660_STO1_ADC_DIG_VOL, + RT5660_L_MUTE_SFT, RT5660_R_MUTE_SFT, 1, 1), + SOC_DOUBLE_TLV("ADC Capture Volume", RT5660_STO1_ADC_DIG_VOL, + RT5660_ADC_L_VOL_SFT, RT5660_ADC_R_VOL_SFT, 63, 0, + rt5660_adc_vol_tlv), + + /* ADC Boost Volume Control */ + SOC_DOUBLE_TLV("STO1 ADC Boost Gain Volume", RT5660_ADC_BST_VOL1, + RT5660_STO1_ADC_L_BST_SFT, RT5660_STO1_ADC_R_BST_SFT, 3, 0, + rt5660_adc_bst_tlv), +}; + +/** + * rt5660_set_dmic_clk - Set parameter of dmic. + * + * @w: DAPM widget. + * @kcontrol: The kcontrol of this widget. + * @event: Event id. + * + */ +static int rt5660_set_dmic_clk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + int idx, rate; + + rate = rt5660->sysclk / rl6231_get_pre_div(rt5660->regmap, + RT5660_ADDA_CLK1, RT5660_I2S_PD1_SFT); + idx = rl6231_calc_dmic_clk(rate); + if (idx < 0) + dev_err(codec->dev, "Failed to set DMIC clock\n"); + else + snd_soc_update_bits(codec, RT5660_DMIC_CTRL1, + RT5660_DMIC_CLK_MASK, idx << RT5660_DMIC_CLK_SFT); + + return idx; +} + +static int rt5660_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); + unsigned int val; + + val = snd_soc_read(codec, RT5660_GLB_CLK); + val &= RT5660_SCLK_SRC_MASK; + if (val == RT5660_SCLK_SRC_PLL1) + return 1; + else + return 0; +} + +/* Digital Mixer */ +static const struct snd_kcontrol_new rt5660_sto1_adc_l_mix[] = { + SOC_DAPM_SINGLE("ADC1 Switch", RT5660_STO1_ADC_MIXER, + RT5660_M_ADC_L1_SFT, 1, 1), + SOC_DAPM_SINGLE("ADC2 Switch", RT5660_STO1_ADC_MIXER, + RT5660_M_ADC_L2_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_sto1_adc_r_mix[] = { + SOC_DAPM_SINGLE("ADC1 Switch", RT5660_STO1_ADC_MIXER, + RT5660_M_ADC_R1_SFT, 1, 1), + SOC_DAPM_SINGLE("ADC2 Switch", RT5660_STO1_ADC_MIXER, + RT5660_M_ADC_R2_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_dac_l_mix[] = { + SOC_DAPM_SINGLE("Stereo ADC Switch", RT5660_AD_DA_MIXER, + RT5660_M_ADCMIX_L_SFT, 1, 1), + SOC_DAPM_SINGLE("DAC1 Switch", RT5660_AD_DA_MIXER, + RT5660_M_DAC1_L_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_dac_r_mix[] = { + SOC_DAPM_SINGLE("Stereo ADC Switch", RT5660_AD_DA_MIXER, + RT5660_M_ADCMIX_R_SFT, 1, 1), + SOC_DAPM_SINGLE("DAC1 Switch", RT5660_AD_DA_MIXER, + RT5660_M_DAC1_R_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_sto_dac_l_mix[] = { + SOC_DAPM_SINGLE("DAC L1 Switch", RT5660_STO_DAC_MIXER, + RT5660_M_DAC_L1_SFT, 1, 1), + SOC_DAPM_SINGLE("DAC R1 Switch", RT5660_STO_DAC_MIXER, + RT5660_M_DAC_R1_STO_L_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_sto_dac_r_mix[] = { + SOC_DAPM_SINGLE("DAC R1 Switch", RT5660_STO_DAC_MIXER, + RT5660_M_DAC_R1_SFT, 1, 1), + SOC_DAPM_SINGLE("DAC L1 Switch", RT5660_STO_DAC_MIXER, + RT5660_M_DAC_L1_STO_R_SFT, 1, 1), +}; + +/* Analog Input Mixer */ +static const struct snd_kcontrol_new rt5660_rec_l_mix[] = { + SOC_DAPM_SINGLE("BST3 Switch", RT5660_REC_L2_MIXER, + RT5660_M_BST3_RM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("BST2 Switch", RT5660_REC_L2_MIXER, + RT5660_M_BST2_RM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("BST1 Switch", RT5660_REC_L2_MIXER, + RT5660_M_BST1_RM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("OUT MIXL Switch", RT5660_REC_L2_MIXER, + RT5660_M_OM_L_RM_L_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_rec_r_mix[] = { + SOC_DAPM_SINGLE("BST3 Switch", RT5660_REC_R2_MIXER, + RT5660_M_BST3_RM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("BST2 Switch", RT5660_REC_R2_MIXER, + RT5660_M_BST2_RM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("BST1 Switch", RT5660_REC_R2_MIXER, + RT5660_M_BST1_RM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("OUT MIXR Switch", RT5660_REC_R2_MIXER, + RT5660_M_OM_R_RM_R_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_spk_mix[] = { + SOC_DAPM_SINGLE("BST3 Switch", RT5660_SPK_MIXER, + RT5660_M_BST3_SM_SFT, 1, 1), + SOC_DAPM_SINGLE("BST1 Switch", RT5660_SPK_MIXER, + RT5660_M_BST1_SM_SFT, 1, 1), + SOC_DAPM_SINGLE("DACL Switch", RT5660_SPK_MIXER, + RT5660_M_DACL_SM_SFT, 1, 1), + SOC_DAPM_SINGLE("DACR Switch", RT5660_SPK_MIXER, + RT5660_M_DACR_SM_SFT, 1, 1), + SOC_DAPM_SINGLE("OUTMIXL Switch", RT5660_SPK_MIXER, + RT5660_M_OM_L_SM_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_out_l_mix[] = { + SOC_DAPM_SINGLE("BST3 Switch", RT5660_OUT_L1_MIXER, + RT5660_M_BST3_OM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("BST2 Switch", RT5660_OUT_L1_MIXER, + RT5660_M_BST2_OM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("BST1 Switch", RT5660_OUT_L1_MIXER, + RT5660_M_BST1_OM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("RECMIXL Switch", RT5660_OUT_L1_MIXER, + RT5660_M_RM_L_OM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("DACR Switch", RT5660_OUT_L1_MIXER, + RT5660_M_DAC_R_OM_L_SFT, 1, 1), + SOC_DAPM_SINGLE("DACL Switch", RT5660_OUT_L1_MIXER, + RT5660_M_DAC_L_OM_L_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_out_r_mix[] = { + SOC_DAPM_SINGLE("BST2 Switch", RT5660_OUT_R1_MIXER, + RT5660_M_BST2_OM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("BST1 Switch", RT5660_OUT_R1_MIXER, + RT5660_M_BST1_OM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("RECMIXR Switch", RT5660_OUT_R1_MIXER, + RT5660_M_RM_R_OM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("DACR Switch", RT5660_OUT_R1_MIXER, + RT5660_M_DAC_R_OM_R_SFT, 1, 1), + SOC_DAPM_SINGLE("DACL Switch", RT5660_OUT_R1_MIXER, + RT5660_M_DAC_L_OM_R_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_spo_mix[] = { + SOC_DAPM_SINGLE("DACR Switch", RT5660_SPO_MIXER, + RT5660_M_DAC_R_SPM_SFT, 1, 1), + SOC_DAPM_SINGLE("DACL Switch", RT5660_SPO_MIXER, + RT5660_M_DAC_L_SPM_SFT, 1, 1), + SOC_DAPM_SINGLE("SPKVOL Switch", RT5660_SPO_MIXER, + RT5660_M_SV_SPM_SFT, 1, 1), + SOC_DAPM_SINGLE("BST1 Switch", RT5660_SPO_MIXER, + RT5660_M_BST1_SPM_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5660_lout_mix[] = { + SOC_DAPM_SINGLE("DAC Switch", RT5660_LOUT_MIXER, + RT5660_M_DAC1_LM_SFT, 1, 1), + SOC_DAPM_SINGLE("OUTMIX Switch", RT5660_LOUT_MIXER, + RT5660_M_LOVOL_LM_SFT, 1, 1), +}; + +static const struct snd_kcontrol_new spk_vol_control = + SOC_DAPM_SINGLE("Switch", RT5660_SPK_VOL, + RT5660_VOL_L_SFT, 1, 1); + +static const struct snd_kcontrol_new lout_l_vol_control = + SOC_DAPM_SINGLE("Switch", RT5660_LOUT_VOL, + RT5660_VOL_L_SFT, 1, 1); + +static const struct snd_kcontrol_new lout_r_vol_control = + SOC_DAPM_SINGLE("Switch", RT5660_LOUT_VOL, + RT5660_VOL_R_SFT, 1, 1); + +/* Interface data select */ +static const char * const rt5660_data_select[] = { + "L/R", "R/L", "L/L", "R/R" +}; + +static const SOC_ENUM_SINGLE_DECL(rt5660_if1_dac_enum, + RT5660_DIG_INF1_DATA, RT5660_IF1_DAC_IN_SFT, rt5660_data_select); + +static const SOC_ENUM_SINGLE_DECL(rt5660_if1_adc_enum, + RT5660_DIG_INF1_DATA, RT5660_IF1_ADC_IN_SFT, rt5660_data_select); + +static const struct snd_kcontrol_new rt5660_if1_dac_swap_mux = + SOC_DAPM_ENUM("IF1 DAC Swap Source", rt5660_if1_dac_enum); + +static const struct snd_kcontrol_new rt5660_if1_adc_swap_mux = + SOC_DAPM_ENUM("IF1 ADC Swap Source", rt5660_if1_adc_enum); + +static int rt5660_lout_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, RT5660_LOUT_AMP_CTRL, + RT5660_LOUT_CO_MASK | RT5660_LOUT_CB_MASK, + RT5660_LOUT_CO_EN | RT5660_LOUT_CB_PU); + break; + + case SND_SOC_DAPM_PRE_PMD: + snd_soc_update_bits(codec, RT5660_LOUT_AMP_CTRL, + RT5660_LOUT_CO_MASK | RT5660_LOUT_CB_MASK, + RT5660_LOUT_CO_DIS | RT5660_LOUT_CB_PD); + break; + + default: + return 0; + } + + return 0; +} + +static const struct snd_soc_dapm_widget rt5660_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("LDO2", RT5660_PWR_ANLG1, + RT5660_PWR_LDO2_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL1", RT5660_PWR_ANLG2, + RT5660_PWR_PLL_BIT, 0, NULL, 0), + + /* MICBIAS */ + SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5660_PWR_ANLG2, + RT5660_PWR_MB1_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MICBIAS2", RT5660_PWR_ANLG2, + RT5660_PWR_MB2_BIT, 0, NULL, 0), + + /* Input Side */ + /* Input Lines */ + SND_SOC_DAPM_INPUT("DMIC L1"), + SND_SOC_DAPM_INPUT("DMIC R1"), + + SND_SOC_DAPM_INPUT("IN1P"), + SND_SOC_DAPM_INPUT("IN1N"), + SND_SOC_DAPM_INPUT("IN2P"), + SND_SOC_DAPM_INPUT("IN3P"), + SND_SOC_DAPM_INPUT("IN3N"), + + SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0, + rt5660_set_dmic_clk, SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_SUPPLY("DMIC Power", RT5660_DMIC_CTRL1, + RT5660_DMIC_1_EN_SFT, 0, NULL, 0), + + /* Boost */ + SND_SOC_DAPM_PGA("BST1", RT5660_PWR_ANLG2, RT5660_PWR_BST1_BIT, 0, + NULL, 0), + SND_SOC_DAPM_PGA("BST2", RT5660_PWR_ANLG2, RT5660_PWR_BST2_BIT, 0, + NULL, 0), + SND_SOC_DAPM_PGA("BST3", RT5660_PWR_ANLG2, RT5660_PWR_BST3_BIT, 0, + NULL, 0), + + /* REC Mixer */ + SND_SOC_DAPM_MIXER("RECMIXL", RT5660_PWR_MIXER, RT5660_PWR_RM_L_BIT, + 0, rt5660_rec_l_mix, ARRAY_SIZE(rt5660_rec_l_mix)), + SND_SOC_DAPM_MIXER("RECMIXR", RT5660_PWR_MIXER, RT5660_PWR_RM_R_BIT, + 0, rt5660_rec_r_mix, ARRAY_SIZE(rt5660_rec_r_mix)), + + /* ADCs */ + SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_SUPPLY("ADC L power", RT5660_PWR_DIG1, + RT5660_PWR_ADC_L_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC R power", RT5660_PWR_DIG1, + RT5660_PWR_ADC_R_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC clock", RT5660_PR_BASE + RT5660_CHOP_DAC_ADC, + 12, 0, NULL, 0), + + /* ADC Mixer */ + SND_SOC_DAPM_SUPPLY("adc stereo1 filter", RT5660_PWR_DIG2, + RT5660_PWR_ADC_S1F_BIT, 0, NULL, 0), + SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0, + rt5660_sto1_adc_l_mix, ARRAY_SIZE(rt5660_sto1_adc_l_mix)), + SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0, + rt5660_sto1_adc_r_mix, ARRAY_SIZE(rt5660_sto1_adc_r_mix)), + + /* ADC */ + SND_SOC_DAPM_ADC("Stereo1 ADC MIXL", NULL, RT5660_STO1_ADC_DIG_VOL, + RT5660_L_MUTE_SFT, 1), + SND_SOC_DAPM_ADC("Stereo1 ADC MIXR", NULL, RT5660_STO1_ADC_DIG_VOL, + RT5660_R_MUTE_SFT, 1), + + /* Digital Interface */ + SND_SOC_DAPM_SUPPLY("I2S1", RT5660_PWR_DIG1, RT5660_PWR_I2S1_BIT, 0, + NULL, 0), + SND_SOC_DAPM_PGA("IF1 DAC", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF1 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF1 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MUX("IF1 DAC Swap Mux", SND_SOC_NOPM, 0, 0, + &rt5660_if1_dac_swap_mux), + SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MUX("IF1 ADC Swap Mux", SND_SOC_NOPM, 0, 0, + &rt5660_if1_adc_swap_mux), + + /* Audio Interface */ + SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), + + /* Output Side */ + /* DAC mixer before sound effect */ + SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0, rt5660_dac_l_mix, + ARRAY_SIZE(rt5660_dac_l_mix)), + SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0, rt5660_dac_r_mix, + ARRAY_SIZE(rt5660_dac_r_mix)), + + /* DAC Mixer */ + SND_SOC_DAPM_SUPPLY("dac stereo1 filter", RT5660_PWR_DIG2, + RT5660_PWR_DAC_S1F_BIT, 0, NULL, 0), + SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0, + rt5660_sto_dac_l_mix, ARRAY_SIZE(rt5660_sto_dac_l_mix)), + SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0, + rt5660_sto_dac_r_mix, ARRAY_SIZE(rt5660_sto_dac_r_mix)), + + /* DACs */ + SND_SOC_DAPM_DAC("DAC L1", NULL, RT5660_PWR_DIG1, + RT5660_PWR_DAC_L1_BIT, 0), + SND_SOC_DAPM_DAC("DAC R1", NULL, RT5660_PWR_DIG1, + RT5660_PWR_DAC_R1_BIT, 0), + + /* OUT Mixer */ + SND_SOC_DAPM_MIXER("SPK MIX", RT5660_PWR_MIXER, RT5660_PWR_SM_BIT, + 0, rt5660_spk_mix, ARRAY_SIZE(rt5660_spk_mix)), + SND_SOC_DAPM_MIXER("OUT MIXL", RT5660_PWR_MIXER, RT5660_PWR_OM_L_BIT, + 0, rt5660_out_l_mix, ARRAY_SIZE(rt5660_out_l_mix)), + SND_SOC_DAPM_MIXER("OUT MIXR", RT5660_PWR_MIXER, RT5660_PWR_OM_R_BIT, + 0, rt5660_out_r_mix, ARRAY_SIZE(rt5660_out_r_mix)), + + /* Output Volume */ + SND_SOC_DAPM_SWITCH("SPKVOL", RT5660_PWR_VOL, + RT5660_PWR_SV_BIT, 0, &spk_vol_control), + SND_SOC_DAPM_PGA("DAC 1", SND_SOC_NOPM, + 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("LOUTVOL", SND_SOC_NOPM, + 0, 0, NULL, 0), + SND_SOC_DAPM_SWITCH("LOUTVOL L", SND_SOC_NOPM, + RT5660_PWR_LV_L_BIT, 0, &lout_l_vol_control), + SND_SOC_DAPM_SWITCH("LOUTVOL R", SND_SOC_NOPM, + RT5660_PWR_LV_R_BIT, 0, &lout_r_vol_control), + + /* HPO/LOUT/Mono Mixer */ + SND_SOC_DAPM_MIXER("SPO MIX", SND_SOC_NOPM, 0, + 0, rt5660_spo_mix, ARRAY_SIZE(rt5660_spo_mix)), + SND_SOC_DAPM_MIXER("LOUT MIX", SND_SOC_NOPM, 0, 0, + rt5660_lout_mix, ARRAY_SIZE(rt5660_lout_mix)), + SND_SOC_DAPM_SUPPLY("VREF HP", RT5660_GEN_CTRL1, + RT5660_PWR_VREF_HP_SFT, 0, NULL, 0), + SND_SOC_DAPM_PGA_S("LOUT amp", 1, RT5660_PWR_ANLG1, + RT5660_PWR_HA_BIT, 0, rt5660_lout_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_PGA_S("SPK amp", 1, RT5660_PWR_DIG1, + RT5660_PWR_CLS_D_BIT, 0, NULL, 0), + + /* Output Lines */ + SND_SOC_DAPM_OUTPUT("LOUTL"), + SND_SOC_DAPM_OUTPUT("LOUTR"), + SND_SOC_DAPM_OUTPUT("SPO"), +}; + +static const struct snd_soc_dapm_route rt5660_dapm_routes[] = { + { "MICBIAS1", NULL, "LDO2" }, + { "MICBIAS2", NULL, "LDO2" }, + + { "BST1", NULL, "IN1P" }, + { "BST1", NULL, "IN1N" }, + { "BST2", NULL, "IN2P" }, + { "BST3", NULL, "IN3P" }, + { "BST3", NULL, "IN3N" }, + + { "RECMIXL", "BST3 Switch", "BST3" }, + { "RECMIXL", "BST2 Switch", "BST2" }, + { "RECMIXL", "BST1 Switch", "BST1" }, + { "RECMIXL", "OUT MIXL Switch", "OUT MIXL" }, + + { "RECMIXR", "BST3 Switch", "BST3" }, + { "RECMIXR", "BST2 Switch", "BST2" }, + { "RECMIXR", "BST1 Switch", "BST1" }, + { "RECMIXR", "OUT MIXR Switch", "OUT MIXR" }, + + { "ADC L", NULL, "RECMIXL" }, + { "ADC L", NULL, "ADC L power" }, + { "ADC L", NULL, "ADC clock" }, + { "ADC R", NULL, "RECMIXR" }, + { "ADC R", NULL, "ADC R power" }, + { "ADC R", NULL, "ADC clock" }, + + {"DMIC L1", NULL, "DMIC CLK"}, + {"DMIC L1", NULL, "DMIC Power"}, + {"DMIC R1", NULL, "DMIC CLK"}, + {"DMIC R1", NULL, "DMIC Power"}, + + { "Sto1 ADC MIXL", "ADC1 Switch", "ADC L" }, + { "Sto1 ADC MIXL", "ADC2 Switch", "DMIC L1" }, + { "Sto1 ADC MIXR", "ADC1 Switch", "ADC R" }, + { "Sto1 ADC MIXR", "ADC2 Switch", "DMIC R1" }, + + { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, + { "Stereo1 ADC MIXL", NULL, "adc stereo1 filter" }, + { "adc stereo1 filter", NULL, "PLL1", rt5660_is_sys_clk_from_pll }, + + { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, + { "Stereo1 ADC MIXR", NULL, "adc stereo1 filter" }, + { "adc stereo1 filter", NULL, "PLL1", rt5660_is_sys_clk_from_pll }, + + { "IF1 ADC", NULL, "Stereo1 ADC MIXL" }, + { "IF1 ADC", NULL, "Stereo1 ADC MIXR" }, + { "IF1 ADC", NULL, "I2S1" }, + + { "IF1 ADC Swap Mux", "L/R", "IF1 ADC" }, + { "IF1 ADC Swap Mux", "R/L", "IF1 ADC" }, + { "IF1 ADC Swap Mux", "L/L", "IF1 ADC" }, + { "IF1 ADC Swap Mux", "R/R", "IF1 ADC" }, + { "AIF1TX", NULL, "IF1 ADC Swap Mux" }, + + { "IF1 DAC", NULL, "AIF1RX" }, + { "IF1 DAC", NULL, "I2S1" }, + + { "IF1 DAC Swap Mux", "L/R", "IF1 DAC" }, + { "IF1 DAC Swap Mux", "R/L", "IF1 DAC" }, + { "IF1 DAC Swap Mux", "L/L", "IF1 DAC" }, + { "IF1 DAC Swap Mux", "R/R", "IF1 DAC" }, + + { "IF1 DAC L", NULL, "IF1 DAC Swap Mux" }, + { "IF1 DAC R", NULL, "IF1 DAC Swap Mux" }, + + { "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL" }, + { "DAC1 MIXL", "DAC1 Switch", "IF1 DAC L" }, + { "DAC1 MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR" }, + { "DAC1 MIXR", "DAC1 Switch", "IF1 DAC R" }, + + { "Stereo DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" }, + { "Stereo DAC MIXL", "DAC R1 Switch", "DAC1 MIXR" }, + { "Stereo DAC MIXL", NULL, "dac stereo1 filter" }, + { "dac stereo1 filter", NULL, "PLL1", rt5660_is_sys_clk_from_pll }, + { "Stereo DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" }, + { "Stereo DAC MIXR", "DAC L1 Switch", "DAC1 MIXL" }, + { "Stereo DAC MIXR", NULL, "dac stereo1 filter" }, + { "dac stereo1 filter", NULL, "PLL1", rt5660_is_sys_clk_from_pll }, + + { "DAC L1", NULL, "Stereo DAC MIXL" }, + { "DAC R1", NULL, "Stereo DAC MIXR" }, + + { "SPK MIX", "BST3 Switch", "BST3" }, + { "SPK MIX", "BST1 Switch", "BST1" }, + { "SPK MIX", "DACL Switch", "DAC L1" }, + { "SPK MIX", "DACR Switch", "DAC R1" }, + { "SPK MIX", "OUTMIXL Switch", "OUT MIXL" }, + + { "OUT MIXL", "BST3 Switch", "BST3" }, + { "OUT MIXL", "BST2 Switch", "BST2" }, + { "OUT MIXL", "BST1 Switch", "BST1" }, + { "OUT MIXL", "RECMIXL Switch", "RECMIXL" }, + { "OUT MIXL", "DACR Switch", "DAC R1" }, + { "OUT MIXL", "DACL Switch", "DAC L1" }, + + { "OUT MIXR", "BST2 Switch", "BST2" }, + { "OUT MIXR", "BST1 Switch", "BST1" }, + { "OUT MIXR", "RECMIXR Switch", "RECMIXR" }, + { "OUT MIXR", "DACR Switch", "DAC R1" }, + { "OUT MIXR", "DACL Switch", "DAC L1" }, + + { "SPO MIX", "DACR Switch", "DAC R1" }, + { "SPO MIX", "DACL Switch", "DAC L1" }, + { "SPO MIX", "SPKVOL Switch", "SPKVOL" }, + { "SPO MIX", "BST1 Switch", "BST1" }, + + { "SPKVOL", "Switch", "SPK MIX" }, + { "LOUTVOL L", "Switch", "OUT MIXL" }, + { "LOUTVOL R", "Switch", "OUT MIXR" }, + + { "LOUTVOL", NULL, "LOUTVOL L" }, + { "LOUTVOL", NULL, "LOUTVOL R" }, + + { "DAC 1", NULL, "DAC L1" }, + { "DAC 1", NULL, "DAC R1" }, + + { "LOUT MIX", "DAC Switch", "DAC 1" }, + { "LOUT MIX", "OUTMIX Switch", "LOUTVOL" }, + + { "LOUT amp", NULL, "LOUT MIX" }, + { "LOUT amp", NULL, "VREF HP" }, + { "LOUTL", NULL, "LOUT amp" }, + { "LOUTR", NULL, "LOUT amp" }, + + { "SPK amp", NULL, "SPO MIX" }, + { "SPO", NULL, "SPK amp" }, +}; + +static int rt5660_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + unsigned int val_len = 0, val_clk, mask_clk; + int pre_div, bclk_ms, frame_size; + + rt5660->lrck[dai->id] = params_rate(params); + pre_div = rl6231_get_clk_info(rt5660->sysclk, rt5660->lrck[dai->id]); + if (pre_div < 0) { + dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n", + rt5660->lrck[dai->id], dai->id); + return -EINVAL; + } + + frame_size = snd_soc_params_to_frame_size(params); + if (frame_size < 0) { + dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size); + return frame_size; + } + + if (frame_size > 32) + bclk_ms = 1; + else + bclk_ms = 0; + + rt5660->bclk[dai->id] = rt5660->lrck[dai->id] * (32 << bclk_ms); + + dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", + rt5660->bclk[dai->id], rt5660->lrck[dai->id]); + dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", + bclk_ms, pre_div, dai->id); + + switch (params_width(params)) { + case 16: + break; + case 20: + val_len |= RT5660_I2S_DL_20; + break; + case 24: + val_len |= RT5660_I2S_DL_24; + break; + case 8: + val_len |= RT5660_I2S_DL_8; + break; + default: + return -EINVAL; + } + + switch (dai->id) { + case RT5660_AIF1: + mask_clk = RT5660_I2S_BCLK_MS1_MASK | RT5660_I2S_PD1_MASK; + val_clk = bclk_ms << RT5660_I2S_BCLK_MS1_SFT | + pre_div << RT5660_I2S_PD1_SFT; + snd_soc_update_bits(codec, RT5660_I2S1_SDP, RT5660_I2S_DL_MASK, + val_len); + snd_soc_update_bits(codec, RT5660_ADDA_CLK1, mask_clk, val_clk); + break; + + default: + dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id); + return -EINVAL; + } + + return 0; +} + +static int rt5660_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + unsigned int reg_val = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + rt5660->master[dai->id] = 1; + break; + + case SND_SOC_DAIFMT_CBS_CFS: + reg_val |= RT5660_I2S_MS_S; + rt5660->master[dai->id] = 0; + break; + + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + + case SND_SOC_DAIFMT_IB_NF: + reg_val |= RT5660_I2S_BP_INV; + break; + + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + + case SND_SOC_DAIFMT_LEFT_J: + reg_val |= RT5660_I2S_DF_LEFT; + break; + + case SND_SOC_DAIFMT_DSP_A: + reg_val |= RT5660_I2S_DF_PCM_A; + break; + + case SND_SOC_DAIFMT_DSP_B: + reg_val |= RT5660_I2S_DF_PCM_B; + break; + + default: + return -EINVAL; + } + + switch (dai->id) { + case RT5660_AIF1: + snd_soc_update_bits(codec, RT5660_I2S1_SDP, + RT5660_I2S_MS_MASK | RT5660_I2S_BP_MASK | + RT5660_I2S_DF_MASK, reg_val); + break; + + default: + dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id); + return -EINVAL; + } + + return 0; +} + +static int rt5660_set_dai_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + unsigned int reg_val = 0; + + if (freq == rt5660->sysclk && clk_id == rt5660->sysclk_src) + return 0; + + switch (clk_id) { + case RT5660_SCLK_S_MCLK: + reg_val |= RT5660_SCLK_SRC_MCLK; + break; + + case RT5660_SCLK_S_PLL1: + reg_val |= RT5660_SCLK_SRC_PLL1; + break; + + case RT5660_SCLK_S_RCCLK: + reg_val |= RT5660_SCLK_SRC_RCCLK; + break; + + default: + dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); + return -EINVAL; + } + + snd_soc_update_bits(codec, RT5660_GLB_CLK, RT5660_SCLK_SRC_MASK, + reg_val); + + rt5660->sysclk = freq; + rt5660->sysclk_src = clk_id; + + dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); + + return 0; +} + +static int rt5660_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, + unsigned int freq_in, unsigned int freq_out) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + struct rl6231_pll_code pll_code; + int ret; + + if (source == rt5660->pll_src && freq_in == rt5660->pll_in && + freq_out == rt5660->pll_out) + return 0; + + if (!freq_in || !freq_out) { + dev_dbg(codec->dev, "PLL disabled\n"); + + rt5660->pll_in = 0; + rt5660->pll_out = 0; + snd_soc_update_bits(codec, RT5660_GLB_CLK, + RT5660_SCLK_SRC_MASK, RT5660_SCLK_SRC_MCLK); + return 0; + } + + switch (source) { + case RT5660_PLL1_S_MCLK: + snd_soc_update_bits(codec, RT5660_GLB_CLK, + RT5660_PLL1_SRC_MASK, RT5660_PLL1_SRC_MCLK); + break; + + case RT5660_PLL1_S_BCLK: + snd_soc_update_bits(codec, RT5660_GLB_CLK, + RT5660_PLL1_SRC_MASK, RT5660_PLL1_SRC_BCLK1); + break; + + default: + dev_err(codec->dev, "Unknown PLL source %d\n", source); + return -EINVAL; + } + + ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); + if (ret < 0) { + dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); + return ret; + } + + dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n", + pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), + pll_code.n_code, pll_code.k_code); + + snd_soc_write(codec, RT5660_PLL_CTRL1, + pll_code.n_code << RT5660_PLL_N_SFT | pll_code.k_code); + snd_soc_write(codec, RT5660_PLL_CTRL2, + (pll_code.m_bp ? 0 : pll_code.m_code) << RT5660_PLL_M_SFT | + pll_code.m_bp << RT5660_PLL_M_BP_SFT); + + rt5660->pll_in = freq_in; + rt5660->pll_out = freq_out; + rt5660->pll_src = source; + + return 0; +} + +static int rt5660_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + int ret; + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + snd_soc_update_bits(codec, RT5660_GEN_CTRL1, + RT5660_DIG_GATE_CTRL, RT5660_DIG_GATE_CTRL); + + if (IS_ERR(rt5660->mclk)) + break; + + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) { + clk_disable_unprepare(rt5660->mclk); + } else { + ret = clk_prepare_enable(rt5660->mclk); + if (ret) + return ret; + } + break; + + case SND_SOC_BIAS_STANDBY: + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { + snd_soc_update_bits(codec, RT5660_PWR_ANLG1, + RT5660_PWR_VREF1 | RT5660_PWR_MB | + RT5660_PWR_BG | RT5660_PWR_VREF2, + RT5660_PWR_VREF1 | RT5660_PWR_MB | + RT5660_PWR_BG | RT5660_PWR_VREF2); + usleep_range(10000, 15000); + snd_soc_update_bits(codec, RT5660_PWR_ANLG1, + RT5660_PWR_FV1 | RT5660_PWR_FV2, + RT5660_PWR_FV1 | RT5660_PWR_FV2); + } + break; + + case SND_SOC_BIAS_OFF: + snd_soc_update_bits(codec, RT5660_GEN_CTRL1, + RT5660_DIG_GATE_CTRL, 0); + break; + + default: + break; + } + + return 0; +} + +static int rt5660_probe(struct snd_soc_codec *codec) +{ + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + + rt5660->codec = codec; + + return 0; +} + +static int rt5660_remove(struct snd_soc_codec *codec) +{ + return snd_soc_write(codec, RT5660_RESET, 0); +} + +#ifdef CONFIG_PM +static int rt5660_suspend(struct snd_soc_codec *codec) +{ + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + + regcache_cache_only(rt5660->regmap, true); + regcache_mark_dirty(rt5660->regmap); + + return 0; +} + +static int rt5660_resume(struct snd_soc_codec *codec) +{ + struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec); + + if (rt5660->pdata.poweroff_codec_in_suspend) + usleep_range(350000, 400000); + + regcache_cache_only(rt5660->regmap, false); + regcache_sync(rt5660->regmap); + + return 0; +} +#else +#define rt5660_suspend NULL +#define rt5660_resume NULL +#endif + +#define RT5660_STEREO_RATES SNDRV_PCM_RATE_8000_192000 +#define RT5660_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) + +static const struct snd_soc_dai_ops rt5660_aif_dai_ops = { + .hw_params = rt5660_hw_params, + .set_fmt = rt5660_set_dai_fmt, + .set_sysclk = rt5660_set_dai_sysclk, + .set_pll = rt5660_set_dai_pll, +}; + +static struct snd_soc_dai_driver rt5660_dai[] = { + { + .name = "rt5660-aif1", + .id = RT5660_AIF1, + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT5660_STEREO_RATES, + .formats = RT5660_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT5660_STEREO_RATES, + .formats = RT5660_FORMATS, + }, + .ops = &rt5660_aif_dai_ops, + }, +}; + +static struct snd_soc_codec_driver soc_codec_dev_rt5660 = { + .probe = rt5660_probe, + .remove = rt5660_remove, + .suspend = rt5660_suspend, + .resume = rt5660_resume, + .set_bias_level = rt5660_set_bias_level, + .idle_bias_off = true, + .component_driver = { + .controls = rt5660_snd_controls, + .num_controls = ARRAY_SIZE(rt5660_snd_controls), + .dapm_widgets = rt5660_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5660_dapm_widgets), + .dapm_routes = rt5660_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5660_dapm_routes), + }, +}; + +static const struct regmap_config rt5660_regmap = { + .reg_bits = 8, + .val_bits = 16, + .use_single_rw = true, + + .max_register = RT5660_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5660_ranges) * + RT5660_PR_SPACING), + .volatile_reg = rt5660_volatile_register, + .readable_reg = rt5660_readable_register, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt5660_reg, + .num_reg_defaults = ARRAY_SIZE(rt5660_reg), + .ranges = rt5660_ranges, + .num_ranges = ARRAY_SIZE(rt5660_ranges), +}; + +static const struct i2c_device_id rt5660_i2c_id[] = { + { "rt5660", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rt5660_i2c_id); + +static const struct of_device_id rt5660_of_match[] = { + { .compatible = "realtek,rt5660", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rt5660_of_match); + +static const struct acpi_device_id rt5660_acpi_match[] = { + { "10EC5660", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, rt5660_acpi_match); + +static int rt5660_parse_dt(struct rt5660_priv *rt5660, struct device *dev) +{ + rt5660->pdata.in1_diff = device_property_read_bool(dev, + "realtek,in1-differential"); + rt5660->pdata.in3_diff = device_property_read_bool(dev, + "realtek,in3-differential"); + rt5660->pdata.poweroff_codec_in_suspend = device_property_read_bool(dev, + "realtek,poweroff-in-suspend"); + device_property_read_u32(dev, "realtek,dmic1-data-pin", + &rt5660->pdata.dmic1_data_pin); + + return 0; +} + +static int rt5660_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rt5660_platform_data *pdata = dev_get_platdata(&i2c->dev); + struct rt5660_priv *rt5660; + int ret; + unsigned int val; + + rt5660 = devm_kzalloc(&i2c->dev, sizeof(struct rt5660_priv), + GFP_KERNEL); + + if (rt5660 == NULL) + return -ENOMEM; + + /* Check if MCLK provided */ + rt5660->mclk = devm_clk_get(&i2c->dev, "mclk"); + if (PTR_ERR(rt5660->mclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + i2c_set_clientdata(i2c, rt5660); + + if (pdata) + rt5660->pdata = *pdata; + else if (i2c->dev.of_node) + rt5660_parse_dt(rt5660, &i2c->dev); + + rt5660->regmap = devm_regmap_init_i2c(i2c, &rt5660_regmap); + if (IS_ERR(rt5660->regmap)) { + ret = PTR_ERR(rt5660->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + regmap_read(rt5660->regmap, RT5660_VENDOR_ID2, &val); + if (val != RT5660_DEVICE_ID) { + dev_err(&i2c->dev, + "Device with ID register %#x is not rt5660\n", val); + return -ENODEV; + } + + regmap_write(rt5660->regmap, RT5660_RESET, 0); + + ret = regmap_register_patch(rt5660->regmap, rt5660_patch, + ARRAY_SIZE(rt5660_patch)); + if (ret != 0) + dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); + + if (rt5660->pdata.dmic1_data_pin) { + regmap_update_bits(rt5660->regmap, RT5660_GPIO_CTRL1, + RT5660_GP1_PIN_MASK, RT5660_GP1_PIN_DMIC1_SCL); + + if (rt5660->pdata.dmic1_data_pin == RT5660_DMIC1_DATA_GPIO2) + regmap_update_bits(rt5660->regmap, RT5660_DMIC_CTRL1, + RT5660_SEL_DMIC_DATA_MASK, + RT5660_SEL_DMIC_DATA_GPIO2); + else if (rt5660->pdata.dmic1_data_pin == RT5660_DMIC1_DATA_IN1P) + regmap_update_bits(rt5660->regmap, RT5660_DMIC_CTRL1, + RT5660_SEL_DMIC_DATA_MASK, + RT5660_SEL_DMIC_DATA_IN1P); + } + + return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5660, + rt5660_dai, ARRAY_SIZE(rt5660_dai)); +} + +static int rt5660_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + + return 0; +} + +static struct i2c_driver rt5660_i2c_driver = { + .driver = { + .name = "rt5660", + .acpi_match_table = ACPI_PTR(rt5660_acpi_match), + .of_match_table = of_match_ptr(rt5660_of_match), + }, + .probe = rt5660_i2c_probe, + .remove = rt5660_i2c_remove, + .id_table = rt5660_i2c_id, +}; +module_i2c_driver(rt5660_i2c_driver); + +MODULE_DESCRIPTION("ASoC RT5660 driver"); +MODULE_AUTHOR("Oder Chiou "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt5660.h b/sound/soc/codecs/rt5660.h new file mode 100644 index 0000000..6cdb926 --- /dev/null +++ b/sound/soc/codecs/rt5660.h @@ -0,0 +1,847 @@ +/* + * rt5660.h -- RT5660 ALSA SoC audio driver + * + * Copyright 2016 Realtek Semiconductor Corp. + * Author: Oder Chiou + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _RT5660_H +#define _RT5660_H + +#include +#include + +/* Info */ +#define RT5660_RESET 0x00 +#define RT5660_VENDOR_ID 0xfd +#define RT5660_VENDOR_ID1 0xfe +#define RT5660_VENDOR_ID2 0xff +/* I/O - Output */ +#define RT5660_SPK_VOL 0x01 +#define RT5660_LOUT_VOL 0x02 +/* I/O - Input */ +#define RT5660_IN1_IN2 0x0d +#define RT5660_IN3_IN4 0x0e +/* I/O - ADC/DAC/DMIC */ +#define RT5660_DAC1_DIG_VOL 0x19 +#define RT5660_STO1_ADC_DIG_VOL 0x1c +#define RT5660_ADC_BST_VOL1 0x1e +/* Mixer - D-D */ +#define RT5660_STO1_ADC_MIXER 0x27 +#define RT5660_AD_DA_MIXER 0x29 +#define RT5660_STO_DAC_MIXER 0x2a +#define RT5660_DIG_INF1_DATA 0x2f +/* Mixer - ADC */ +#define RT5660_REC_L1_MIXER 0x3b +#define RT5660_REC_L2_MIXER 0x3c +#define RT5660_REC_R1_MIXER 0x3d +#define RT5660_REC_R2_MIXER 0x3e +/* Mixer - DAC */ +#define RT5660_LOUT_MIXER 0x45 +#define RT5660_SPK_MIXER 0x46 +#define RT5660_SPO_MIXER 0x48 +#define RT5660_SPO_CLSD_RATIO 0x4a +#define RT5660_OUT_L_GAIN1 0x4d +#define RT5660_OUT_L_GAIN2 0x4e +#define RT5660_OUT_L1_MIXER 0x4f +#define RT5660_OUT_R_GAIN1 0x50 +#define RT5660_OUT_R_GAIN2 0x51 +#define RT5660_OUT_R1_MIXER 0x52 +/* Power */ +#define RT5660_PWR_DIG1 0x61 +#define RT5660_PWR_DIG2 0x62 +#define RT5660_PWR_ANLG1 0x63 +#define RT5660_PWR_ANLG2 0x64 +#define RT5660_PWR_MIXER 0x65 +#define RT5660_PWR_VOL 0x66 +/* Private Register Control */ +#define RT5660_PRIV_INDEX 0x6a +#define RT5660_PRIV_DATA 0x6c +/* Format - ADC/DAC */ +#define RT5660_I2S1_SDP 0x70 +#define RT5660_ADDA_CLK1 0x73 +#define RT5660_ADDA_CLK2 0x74 +#define RT5660_DMIC_CTRL1 0x75 +/* Function - Analog */ +#define RT5660_GLB_CLK 0x80 +#define RT5660_PLL_CTRL1 0x81 +#define RT5660_PLL_CTRL2 0x82 +#define RT5660_CLSD_AMP_OC_CTRL 0x8c +#define RT5660_CLSD_AMP_CTRL 0x8d +#define RT5660_LOUT_AMP_CTRL 0x8e +#define RT5660_SPK_AMP_SPKVDD 0x92 +#define RT5660_MICBIAS 0x93 +#define RT5660_CLSD_OUT_CTRL1 0xa1 +#define RT5660_CLSD_OUT_CTRL2 0xa2 +#define RT5660_DIPOLE_MIC_CTRL1 0xa3 +#define RT5660_DIPOLE_MIC_CTRL2 0xa4 +#define RT5660_DIPOLE_MIC_CTRL3 0xa5 +#define RT5660_DIPOLE_MIC_CTRL4 0xa6 +#define RT5660_DIPOLE_MIC_CTRL5 0xa7 +#define RT5660_DIPOLE_MIC_CTRL6 0xa8 +#define RT5660_DIPOLE_MIC_CTRL7 0xa9 +#define RT5660_DIPOLE_MIC_CTRL8 0xaa +#define RT5660_DIPOLE_MIC_CTRL9 0xab +#define RT5660_DIPOLE_MIC_CTRL10 0xac +#define RT5660_DIPOLE_MIC_CTRL11 0xad +#define RT5660_DIPOLE_MIC_CTRL12 0xae +/* Function - Digital */ +#define RT5660_EQ_CTRL1 0xb0 +#define RT5660_EQ_CTRL2 0xb1 +#define RT5660_DRC_AGC_CTRL1 0xb3 +#define RT5660_DRC_AGC_CTRL2 0xb4 +#define RT5660_DRC_AGC_CTRL3 0xb5 +#define RT5660_DRC_AGC_CTRL4 0xb6 +#define RT5660_DRC_AGC_CTRL5 0xb7 +#define RT5660_JD_CTRL 0xbb +#define RT5660_IRQ_CTRL1 0xbd +#define RT5660_IRQ_CTRL2 0xbe +#define RT5660_INT_IRQ_ST 0xbf +#define RT5660_GPIO_CTRL1 0xc0 +#define RT5660_GPIO_CTRL2 0xc2 +#define RT5660_WIND_FILTER_CTRL1 0xd3 +#define RT5660_SV_ZCD1 0xd9 +#define RT5660_SV_ZCD2 0xda +#define RT5660_DRC1_LM_CTRL1 0xe0 +#define RT5660_DRC1_LM_CTRL2 0xe1 +#define RT5660_DRC2_LM_CTRL1 0xe2 +#define RT5660_DRC2_LM_CTRL2 0xe3 +#define RT5660_MULTI_DRC_CTRL 0xe4 +#define RT5660_DRC2_CTRL1 0xe5 +#define RT5660_DRC2_CTRL2 0xe6 +#define RT5660_DRC2_CTRL3 0xe7 +#define RT5660_DRC2_CTRL4 0xe8 +#define RT5660_DRC2_CTRL5 0xe9 +#define RT5660_ALC_PGA_CTRL1 0xea +#define RT5660_ALC_PGA_CTRL2 0xeb +#define RT5660_ALC_PGA_CTRL3 0xec +#define RT5660_ALC_PGA_CTRL4 0xed +#define RT5660_ALC_PGA_CTRL5 0xee +#define RT5660_ALC_PGA_CTRL6 0xef +#define RT5660_ALC_PGA_CTRL7 0xf0 + +/* General Control */ +#define RT5660_GEN_CTRL1 0xfa +#define RT5660_GEN_CTRL2 0xfb +#define RT5660_GEN_CTRL3 0xfc + +/* Index of Codec Private Register definition */ +#define RT5660_CHOP_DAC_ADC 0x3d + +/* Global Definition */ +#define RT5660_L_MUTE (0x1 << 15) +#define RT5660_L_MUTE_SFT 15 +#define RT5660_VOL_L_MUTE (0x1 << 14) +#define RT5660_VOL_L_SFT 14 +#define RT5660_R_MUTE (0x1 << 7) +#define RT5660_R_MUTE_SFT 7 +#define RT5660_VOL_R_MUTE (0x1 << 6) +#define RT5660_VOL_R_SFT 6 +#define RT5660_L_VOL_MASK (0x3f << 8) +#define RT5660_L_VOL_SFT 8 +#define RT5660_R_VOL_MASK (0x3f) +#define RT5660_R_VOL_SFT 0 + +/* IN1 and IN2 Control (0x0d) */ +#define RT5660_IN_DF1 (0x1 << 15) +#define RT5660_IN_SFT1 15 +#define RT5660_BST_MASK1 (0x7f << 8) +#define RT5660_BST_SFT1 8 +#define RT5660_IN_DF2 (0x1 << 7) +#define RT5660_IN_SFT2 7 +#define RT5660_BST_MASK2 (0x7f << 0) +#define RT5660_BST_SFT2 0 + +/* IN3 and IN4 Control (0x0e) */ +#define RT5660_IN_DF3 (0x1 << 15) +#define RT5660_IN_SFT3 15 +#define RT5660_BST_MASK3 (0x7f << 8) +#define RT5660_BST_SFT3 8 +#define RT5660_IN_DF4 (0x1 << 7) +#define RT5660_IN_SFT4 7 +#define RT5660_BST_MASK4 (0x7f << 0) +#define RT5660_BST_SFT4 0 + +/* DAC1 Digital Volume (0x19) */ +#define RT5660_DAC_L1_VOL_MASK (0x7f << 9) +#define RT5660_DAC_L1_VOL_SFT 9 +#define RT5660_DAC_R1_VOL_MASK (0x7f << 1) +#define RT5660_DAC_R1_VOL_SFT 1 + +/* ADC Digital Volume Control (0x1c) */ +#define RT5660_ADC_L_VOL_MASK (0x3f << 9) +#define RT5660_ADC_L_VOL_SFT 9 +#define RT5660_ADC_R_VOL_MASK (0x3f << 1) +#define RT5660_ADC_R_VOL_SFT 1 + +/* ADC Boost Volume Control (0x1e) */ +#define RT5660_STO1_ADC_L_BST_MASK (0x3 << 14) +#define RT5660_STO1_ADC_L_BST_SFT 14 +#define RT5660_STO1_ADC_R_BST_MASK (0x3 << 12) +#define RT5660_STO1_ADC_R_BST_SFT 12 + +/* Stereo ADC Mixer Control (0x27) */ +#define RT5660_M_ADC_L1 (0x1 << 14) +#define RT5660_M_ADC_L1_SFT 14 +#define RT5660_M_ADC_L2 (0x1 << 13) +#define RT5660_M_ADC_L2_SFT 13 +#define RT5660_M_ADC_R1 (0x1 << 6) +#define RT5660_M_ADC_R1_SFT 6 +#define RT5660_M_ADC_R2 (0x1 << 5) +#define RT5660_M_ADC_R2_SFT 5 + +/* ADC Mixer to DAC Mixer Control (0x29) */ +#define RT5660_M_ADCMIX_L (0x1 << 15) +#define RT5660_M_ADCMIX_L_SFT 15 +#define RT5660_M_DAC1_L (0x1 << 14) +#define RT5660_M_DAC1_L_SFT 14 +#define RT5660_M_ADCMIX_R (0x1 << 7) +#define RT5660_M_ADCMIX_R_SFT 7 +#define RT5660_M_DAC1_R (0x1 << 6) +#define RT5660_M_DAC1_R_SFT 6 + +/* Stereo DAC Mixer Control (0x2a) */ +#define RT5660_M_DAC_L1 (0x1 << 14) +#define RT5660_M_DAC_L1_SFT 14 +#define RT5660_DAC_L1_STO_L_VOL_MASK (0x1 << 13) +#define RT5660_DAC_L1_STO_L_VOL_SFT 13 +#define RT5660_M_DAC_R1_STO_L (0x1 << 9) +#define RT5660_M_DAC_R1_STO_L_SFT 9 +#define RT5660_DAC_R1_STO_L_VOL_MASK (0x1 << 8) +#define RT5660_DAC_R1_STO_L_VOL_SFT 8 +#define RT5660_M_DAC_R1 (0x1 << 6) +#define RT5660_M_DAC_R1_SFT 6 +#define RT5660_DAC_R1_STO_R_VOL_MASK (0x1 << 5) +#define RT5660_DAC_R1_STO_R_VOL_SFT 5 +#define RT5660_M_DAC_L1_STO_R (0x1 << 1) +#define RT5660_M_DAC_L1_STO_R_SFT 1 +#define RT5660_DAC_L1_STO_R_VOL_MASK (0x1) +#define RT5660_DAC_L1_STO_R_VOL_SFT 0 + +/* Digital Interface Data Control (0x2f) */ +#define RT5660_IF1_DAC_IN_SEL (0x3 << 14) +#define RT5660_IF1_DAC_IN_SFT 14 +#define RT5660_IF1_ADC_IN_SEL (0x3 << 12) +#define RT5660_IF1_ADC_IN_SFT 12 + +/* REC Left Mixer Control 1 (0x3b) */ +#define RT5660_G_BST3_RM_L_MASK (0x7 << 4) +#define RT5660_G_BST3_RM_L_SFT 4 +#define RT5660_G_BST2_RM_L_MASK (0x7 << 1) +#define RT5660_G_BST2_RM_L_SFT 1 + +/* REC Left Mixer Control 2 (0x3c) */ +#define RT5660_G_BST1_RM_L_MASK (0x7 << 13) +#define RT5660_G_BST1_RM_L_SFT 13 +#define RT5660_G_OM_L_RM_L_MASK (0x7 << 10) +#define RT5660_G_OM_L_RM_L_SFT 10 +#define RT5660_M_BST3_RM_L (0x1 << 3) +#define RT5660_M_BST3_RM_L_SFT 3 +#define RT5660_M_BST2_RM_L (0x1 << 2) +#define RT5660_M_BST2_RM_L_SFT 2 +#define RT5660_M_BST1_RM_L (0x1 << 1) +#define RT5660_M_BST1_RM_L_SFT 1 +#define RT5660_M_OM_L_RM_L (0x1) +#define RT5660_M_OM_L_RM_L_SFT 0 + +/* REC Right Mixer Control 1 (0x3d) */ +#define RT5660_G_BST3_RM_R_MASK (0x7 << 4) +#define RT5660_G_BST3_RM_R_SFT 4 +#define RT5660_G_BST2_RM_R_MASK (0x7 << 1) +#define RT5660_G_BST2_RM_R_SFT 1 + +/* REC Right Mixer Control 2 (0x3e) */ +#define RT5660_G_BST1_RM_R_MASK (0x7 << 13) +#define RT5660_G_BST1_RM_R_SFT 13 +#define RT5660_G_OM_R_RM_R_MASK (0x7 << 10) +#define RT5660_G_OM_R_RM_R_SFT 10 +#define RT5660_M_BST3_RM_R (0x1 << 3) +#define RT5660_M_BST3_RM_R_SFT 3 +#define RT5660_M_BST2_RM_R (0x1 << 2) +#define RT5660_M_BST2_RM_R_SFT 2 +#define RT5660_M_BST1_RM_R (0x1 << 1) +#define RT5660_M_BST1_RM_R_SFT 1 +#define RT5660_M_OM_R_RM_R (0x1) +#define RT5660_M_OM_R_RM_R_SFT 0 + +/* LOUTMIX Control (0x45) */ +#define RT5660_M_DAC1_LM (0x1 << 14) +#define RT5660_M_DAC1_LM_SFT 14 +#define RT5660_M_LOVOL_M (0x1 << 13) +#define RT5660_M_LOVOL_LM_SFT 13 + +/* SPK Mixer Control (0x46) */ +#define RT5660_G_BST3_SM_MASK (0x3 << 14) +#define RT5660_G_BST3_SM_SFT 14 +#define RT5660_G_BST1_SM_MASK (0x3 << 12) +#define RT5660_G_BST1_SM_SFT 12 +#define RT5660_G_DACl_SM_MASK (0x3 << 10) +#define RT5660_G_DACl_SM_SFT 10 +#define RT5660_G_DACR_SM_MASK (0x3 << 8) +#define RT5660_G_DACR_SM_SFT 8 +#define RT5660_G_OM_L_SM_MASK (0x3 << 6) +#define RT5660_G_OM_L_SM_SFT 6 +#define RT5660_M_DACR_SM (0x1 << 5) +#define RT5660_M_DACR_SM_SFT 5 +#define RT5660_M_BST1_SM (0x1 << 4) +#define RT5660_M_BST1_SM_SFT 4 +#define RT5660_M_BST3_SM (0x1 << 3) +#define RT5660_M_BST3_SM_SFT 3 +#define RT5660_M_DACL_SM (0x1 << 2) +#define RT5660_M_DACL_SM_SFT 2 +#define RT5660_M_OM_L_SM (0x1 << 1) +#define RT5660_M_OM_L_SM_SFT 1 + +/* SPOMIX Control (0x48) */ +#define RT5660_M_DAC_R_SPM (0x1 << 14) +#define RT5660_M_DAC_R_SPM_SFT 14 +#define RT5660_M_DAC_L_SPM (0x1 << 13) +#define RT5660_M_DAC_L_SPM_SFT 13 +#define RT5660_M_SV_SPM (0x1 << 12) +#define RT5660_M_SV_SPM_SFT 12 +#define RT5660_M_BST1_SPM (0x1 << 11) +#define RT5660_M_BST1_SPM_SFT 11 + +/* Output Left Mixer Control 1 (0x4d) */ +#define RT5660_G_BST3_OM_L_MASK (0x7 << 13) +#define RT5660_G_BST3_OM_L_SFT 13 +#define RT5660_G_BST2_OM_L_MASK (0x7 << 10) +#define RT5660_G_BST2_OM_L_SFT 10 +#define RT5660_G_BST1_OM_L_MASK (0x7 << 7) +#define RT5660_G_BST1_OM_L_SFT 7 +#define RT5660_G_RM_L_OM_L_MASK (0x7 << 1) +#define RT5660_G_RM_L_OM_L_SFT 1 + +/* Output Left Mixer Control 2 (0x4e) */ +#define RT5660_G_DAC_R1_OM_L_MASK (0x7 << 10) +#define RT5660_G_DAC_R1_OM_L_SFT 10 +#define RT5660_G_DAC_L1_OM_L_MASK (0x7 << 7) +#define RT5660_G_DAC_L1_OM_L_SFT 7 + +/* Output Left Mixer Control 3 (0x4f) */ +#define RT5660_M_BST3_OM_L (0x1 << 5) +#define RT5660_M_BST3_OM_L_SFT 5 +#define RT5660_M_BST2_OM_L (0x1 << 4) +#define RT5660_M_BST2_OM_L_SFT 4 +#define RT5660_M_BST1_OM_L (0x1 << 3) +#define RT5660_M_BST1_OM_L_SFT 3 +#define RT5660_M_RM_L_OM_L (0x1 << 2) +#define RT5660_M_RM_L_OM_L_SFT 2 +#define RT5660_M_DAC_R_OM_L (0x1 << 1) +#define RT5660_M_DAC_R_OM_L_SFT 1 +#define RT5660_M_DAC_L_OM_L (0x1) +#define RT5660_M_DAC_L_OM_L_SFT 0 + +/* Output Right Mixer Control 1 (0x50) */ +#define RT5660_G_BST2_OM_R_MASK (0x7 << 10) +#define RT5660_G_BST2_OM_R_SFT 10 +#define RT5660_G_BST1_OM_R_MASK (0x7 << 7) +#define RT5660_G_BST1_OM_R_SFT 7 +#define RT5660_G_RM_R_OM_R_MASK (0x7 << 1) +#define RT5660_G_RM_R_OM_R_SFT 1 + +/* Output Right Mixer Control 2 (0x51) */ +#define RT5660_G_DAC_L_OM_R_MASK (0x7 << 10) +#define RT5660_G_DAC_L_OM_R_SFT 10 +#define RT5660_G_DAC_R_OM_R_MASK (0x7 << 7) +#define RT5660_G_DAC_R_OM_R_SFT 7 + +/* Output Right Mixer Control 3 (0x52) */ +#define RT5660_M_BST2_OM_R (0x1 << 4) +#define RT5660_M_BST2_OM_R_SFT 4 +#define RT5660_M_BST1_OM_R (0x1 << 3) +#define RT5660_M_BST1_OM_R_SFT 3 +#define RT5660_M_RM_R_OM_R (0x1 << 2) +#define RT5660_M_RM_R_OM_R_SFT 2 +#define RT5660_M_DAC_L_OM_R (0x1 << 1) +#define RT5660_M_DAC_L_OM_R_SFT 1 +#define RT5660_M_DAC_R_OM_R (0x1) +#define RT5660_M_DAC_R_OM_R_SFT 0 + +/* Power Management for Digital 1 (0x61) */ +#define RT5660_PWR_I2S1 (0x1 << 15) +#define RT5660_PWR_I2S1_BIT 15 +#define RT5660_PWR_DAC_L1 (0x1 << 12) +#define RT5660_PWR_DAC_L1_BIT 12 +#define RT5660_PWR_DAC_R1 (0x1 << 11) +#define RT5660_PWR_DAC_R1_BIT 11 +#define RT5660_PWR_ADC_L (0x1 << 2) +#define RT5660_PWR_ADC_L_BIT 2 +#define RT5660_PWR_ADC_R (0x1 << 1) +#define RT5660_PWR_ADC_R_BIT 1 +#define RT5660_PWR_CLS_D (0x1) +#define RT5660_PWR_CLS_D_BIT 0 + +/* Power Management for Digital 2 (0x62) */ +#define RT5660_PWR_ADC_S1F (0x1 << 15) +#define RT5660_PWR_ADC_S1F_BIT 15 +#define RT5660_PWR_DAC_S1F (0x1 << 11) +#define RT5660_PWR_DAC_S1F_BIT 11 + +/* Power Management for Analog 1 (0x63) */ +#define RT5660_PWR_VREF1 (0x1 << 15) +#define RT5660_PWR_VREF1_BIT 15 +#define RT5660_PWR_FV1 (0x1 << 14) +#define RT5660_PWR_FV1_BIT 14 +#define RT5660_PWR_MB (0x1 << 13) +#define RT5660_PWR_MB_BIT 13 +#define RT5660_PWR_BG (0x1 << 11) +#define RT5660_PWR_BG_BIT 11 +#define RT5660_PWR_HP_L (0x1 << 7) +#define RT5660_PWR_HP_L_BIT 7 +#define RT5660_PWR_HP_R (0x1 << 6) +#define RT5660_PWR_HP_R_BIT 6 +#define RT5660_PWR_HA (0x1 << 5) +#define RT5660_PWR_HA_BIT 5 +#define RT5660_PWR_VREF2 (0x1 << 4) +#define RT5660_PWR_VREF2_BIT 4 +#define RT5660_PWR_FV2 (0x1 << 3) +#define RT5660_PWR_FV2_BIT 3 +#define RT5660_PWR_LDO2 (0x1 << 2) +#define RT5660_PWR_LDO2_BIT 2 + +/* Power Management for Analog 2 (0x64) */ +#define RT5660_PWR_BST1 (0x1 << 15) +#define RT5660_PWR_BST1_BIT 15 +#define RT5660_PWR_BST2 (0x1 << 14) +#define RT5660_PWR_BST2_BIT 14 +#define RT5660_PWR_BST3 (0x1 << 13) +#define RT5660_PWR_BST3_BIT 13 +#define RT5660_PWR_MB1 (0x1 << 11) +#define RT5660_PWR_MB1_BIT 11 +#define RT5660_PWR_MB2 (0x1 << 10) +#define RT5660_PWR_MB2_BIT 10 +#define RT5660_PWR_PLL (0x1 << 9) +#define RT5660_PWR_PLL_BIT 9 + +/* Power Management for Mixer (0x65) */ +#define RT5660_PWR_OM_L (0x1 << 15) +#define RT5660_PWR_OM_L_BIT 15 +#define RT5660_PWR_OM_R (0x1 << 14) +#define RT5660_PWR_OM_R_BIT 14 +#define RT5660_PWR_SM (0x1 << 13) +#define RT5660_PWR_SM_BIT 13 +#define RT5660_PWR_RM_L (0x1 << 11) +#define RT5660_PWR_RM_L_BIT 11 +#define RT5660_PWR_RM_R (0x1 << 10) +#define RT5660_PWR_RM_R_BIT 10 + +/* Power Management for Volume (0x66) */ +#define RT5660_PWR_SV (0x1 << 15) +#define RT5660_PWR_SV_BIT 15 +#define RT5660_PWR_LV_L (0x1 << 11) +#define RT5660_PWR_LV_L_BIT 11 +#define RT5660_PWR_LV_R (0x1 << 10) +#define RT5660_PWR_LV_R_BIT 10 + +/* I2S1 Audio Serial Data Port Control (0x70) */ +#define RT5660_I2S_MS_MASK (0x1 << 15) +#define RT5660_I2S_MS_SFT 15 +#define RT5660_I2S_MS_M (0x0 << 15) +#define RT5660_I2S_MS_S (0x1 << 15) +#define RT5660_I2S_O_CP_MASK (0x3 << 10) +#define RT5660_I2S_O_CP_SFT 10 +#define RT5660_I2S_O_CP_OFF (0x0 << 10) +#define RT5660_I2S_O_CP_U_LAW (0x1 << 10) +#define RT5660_I2S_O_CP_A_LAW (0x2 << 10) +#define RT5660_I2S_I_CP_MASK (0x3 << 8) +#define RT5660_I2S_I_CP_SFT 8 +#define RT5660_I2S_I_CP_OFF (0x0 << 8) +#define RT5660_I2S_I_CP_U_LAW (0x1 << 8) +#define RT5660_I2S_I_CP_A_LAW (0x2 << 8) +#define RT5660_I2S_BP_MASK (0x1 << 7) +#define RT5660_I2S_BP_SFT 7 +#define RT5660_I2S_BP_NOR (0x0 << 7) +#define RT5660_I2S_BP_INV (0x1 << 7) +#define RT5660_I2S_DL_MASK (0x3 << 2) +#define RT5660_I2S_DL_SFT 2 +#define RT5660_I2S_DL_16 (0x0 << 2) +#define RT5660_I2S_DL_20 (0x1 << 2) +#define RT5660_I2S_DL_24 (0x2 << 2) +#define RT5660_I2S_DL_8 (0x3 << 2) +#define RT5660_I2S_DF_MASK (0x3) +#define RT5660_I2S_DF_SFT 0 +#define RT5660_I2S_DF_I2S (0x0) +#define RT5660_I2S_DF_LEFT (0x1) +#define RT5660_I2S_DF_PCM_A (0x2) +#define RT5660_I2S_DF_PCM_B (0x3) + +/* ADC/DAC Clock Control 1 (0x73) */ +#define RT5660_I2S_BCLK_MS1_MASK (0x1 << 15) +#define RT5660_I2S_BCLK_MS1_SFT 15 +#define RT5660_I2S_BCLK_MS1_32 (0x0 << 15) +#define RT5660_I2S_BCLK_MS1_64 (0x1 << 15) +#define RT5660_I2S_PD1_MASK (0x7 << 12) +#define RT5660_I2S_PD1_SFT 12 +#define RT5660_I2S_PD1_1 (0x0 << 12) +#define RT5660_I2S_PD1_2 (0x1 << 12) +#define RT5660_I2S_PD1_3 (0x2 << 12) +#define RT5660_I2S_PD1_4 (0x3 << 12) +#define RT5660_I2S_PD1_6 (0x4 << 12) +#define RT5660_I2S_PD1_8 (0x5 << 12) +#define RT5660_I2S_PD1_12 (0x6 << 12) +#define RT5660_I2S_PD1_16 (0x7 << 12) +#define RT5660_DAC_OSR_MASK (0x3 << 2) +#define RT5660_DAC_OSR_SFT 2 +#define RT5660_DAC_OSR_128 (0x0 << 2) +#define RT5660_DAC_OSR_64 (0x1 << 2) +#define RT5660_DAC_OSR_32 (0x2 << 2) +#define RT5660_DAC_OSR_16 (0x3 << 2) +#define RT5660_ADC_OSR_MASK (0x3) +#define RT5660_ADC_OSR_SFT 0 +#define RT5660_ADC_OSR_128 (0x0) +#define RT5660_ADC_OSR_64 (0x1) +#define RT5660_ADC_OSR_32 (0x2) +#define RT5660_ADC_OSR_16 (0x3) + +/* ADC/DAC Clock Control 2 (0x74) */ +#define RT5660_RESET_ADF (0x1 << 13) +#define RT5660_RESET_ADF_SFT 13 +#define RT5660_RESET_DAF (0x1 << 12) +#define RT5660_RESET_DAF_SFT 12 +#define RT5660_DAHPF_EN (0x1 << 11) +#define RT5660_DAHPF_EN_SFT 11 +#define RT5660_ADHPF_EN (0x1 << 10) +#define RT5660_ADHPF_EN_SFT 10 + +/* Digital Microphone Control (0x75) */ +#define RT5660_DMIC_1_EN_MASK (0x1 << 15) +#define RT5660_DMIC_1_EN_SFT 15 +#define RT5660_DMIC_1_DIS (0x0 << 15) +#define RT5660_DMIC_1_EN (0x1 << 15) +#define RT5660_DMIC_1L_LH_MASK (0x1 << 13) +#define RT5660_DMIC_1L_LH_SFT 13 +#define RT5660_DMIC_1L_LH_RISING (0x0 << 13) +#define RT5660_DMIC_1L_LH_FALLING (0x1 << 13) +#define RT5660_DMIC_1R_LH_MASK (0x1 << 12) +#define RT5660_DMIC_1R_LH_SFT 12 +#define RT5660_DMIC_1R_LH_RISING (0x0 << 12) +#define RT5660_DMIC_1R_LH_FALLING (0x1 << 12) +#define RT5660_SEL_DMIC_DATA_MASK (0x1 << 11) +#define RT5660_SEL_DMIC_DATA_SFT 11 +#define RT5660_SEL_DMIC_DATA_GPIO2 (0x0 << 11) +#define RT5660_SEL_DMIC_DATA_IN1P (0x1 << 11) +#define RT5660_DMIC_CLK_MASK (0x7 << 5) +#define RT5660_DMIC_CLK_SFT 5 + +/* Global Clock Control (0x80) */ +#define RT5660_SCLK_SRC_MASK (0x3 << 14) +#define RT5660_SCLK_SRC_SFT 14 +#define RT5660_SCLK_SRC_MCLK (0x0 << 14) +#define RT5660_SCLK_SRC_PLL1 (0x1 << 14) +#define RT5660_SCLK_SRC_RCCLK (0x2 << 14) +#define RT5660_PLL1_SRC_MASK (0x3 << 12) +#define RT5660_PLL1_SRC_SFT 12 +#define RT5660_PLL1_SRC_MCLK (0x0 << 12) +#define RT5660_PLL1_SRC_BCLK1 (0x1 << 12) +#define RT5660_PLL1_SRC_RCCLK (0x2 << 12) +#define RT5660_PLL1_PD_MASK (0x1 << 3) +#define RT5660_PLL1_PD_SFT 3 +#define RT5660_PLL1_PD_1 (0x0 << 3) +#define RT5660_PLL1_PD_2 (0x1 << 3) + +#define RT5660_PLL_INP_MAX 40000000 +#define RT5660_PLL_INP_MIN 256000 +/* PLL M/N/K Code Control 1 (0x81) */ +#define RT5660_PLL_N_MAX 0x1ff +#define RT5660_PLL_N_MASK (RT5660_PLL_N_MAX << 7) +#define RT5660_PLL_N_SFT 7 +#define RT5660_PLL_K_MAX 0x1f +#define RT5660_PLL_K_MASK (RT5660_PLL_K_MAX) +#define RT5660_PLL_K_SFT 0 + +/* PLL M/N/K Code Control 2 (0x82) */ +#define RT5660_PLL_M_MAX 0xf +#define RT5660_PLL_M_MASK (RT5660_PLL_M_MAX << 12) +#define RT5660_PLL_M_SFT 12 +#define RT5660_PLL_M_BP (0x1 << 11) +#define RT5660_PLL_M_BP_SFT 11 + +/* Class D Over Current Control (0x8c) */ +#define RT5660_CLSD_OC_MASK (0x1 << 9) +#define RT5660_CLSD_OC_SFT 9 +#define RT5660_CLSD_OC_PU (0x0 << 9) +#define RT5660_CLSD_OC_PD (0x1 << 9) +#define RT5660_AUTO_PD_MASK (0x1 << 8) +#define RT5660_AUTO_PD_SFT 8 +#define RT5660_AUTO_PD_DIS (0x0 << 8) +#define RT5660_AUTO_PD_EN (0x1 << 8) +#define RT5660_CLSD_OC_TH_MASK (0x3f) +#define RT5660_CLSD_OC_TH_SFT 0 + +/* Class D Output Control (0x8d) */ +#define RT5660_CLSD_RATIO_MASK (0xf << 12) +#define RT5660_CLSD_RATIO_SFT 12 + +/* Lout Amp Control 1 (0x8e) */ +#define RT5660_LOUT_CO_MASK (0x1 << 4) +#define RT5660_LOUT_CO_SFT 4 +#define RT5660_LOUT_CO_DIS (0x0 << 4) +#define RT5660_LOUT_CO_EN (0x1 << 4) +#define RT5660_LOUT_CB_MASK (0x1) +#define RT5660_LOUT_CB_SFT 0 +#define RT5660_LOUT_CB_PD (0x0) +#define RT5660_LOUT_CB_PU (0x1) + +/* SPKVDD detection control (0x92) */ +#define RT5660_SPKVDD_DET_MASK (0x1 << 15) +#define RT5660_SPKVDD_DET_SFT 15 +#define RT5660_SPKVDD_DET_DIS (0x0 << 15) +#define RT5660_SPKVDD_DET_EN (0x1 << 15) +#define RT5660_SPK_AG_MASK (0x1 << 14) +#define RT5660_SPK_AG_SFT 14 +#define RT5660_SPK_AG_DIS (0x0 << 14) +#define RT5660_SPK_AG_EN (0x1 << 14) + +/* Micbias Control (0x93) */ +#define RT5660_MIC1_BS_MASK (0x1 << 15) +#define RT5660_MIC1_BS_SFT 15 +#define RT5660_MIC1_BS_9AV (0x0 << 15) +#define RT5660_MIC1_BS_75AV (0x1 << 15) +#define RT5660_MIC2_BS_MASK (0x1 << 14) +#define RT5660_MIC2_BS_SFT 14 +#define RT5660_MIC2_BS_9AV (0x0 << 14) +#define RT5660_MIC2_BS_75AV (0x1 << 14) +#define RT5660_MIC1_OVCD_MASK (0x1 << 11) +#define RT5660_MIC1_OVCD_SFT 11 +#define RT5660_MIC1_OVCD_DIS (0x0 << 11) +#define RT5660_MIC1_OVCD_EN (0x1 << 11) +#define RT5660_MIC1_OVTH_MASK (0x3 << 9) +#define RT5660_MIC1_OVTH_SFT 9 +#define RT5660_MIC1_OVTH_600UA (0x0 << 9) +#define RT5660_MIC1_OVTH_1500UA (0x1 << 9) +#define RT5660_MIC1_OVTH_2000UA (0x2 << 9) +#define RT5660_MIC2_OVCD_MASK (0x1 << 8) +#define RT5660_MIC2_OVCD_SFT 8 +#define RT5660_MIC2_OVCD_DIS (0x0 << 8) +#define RT5660_MIC2_OVCD_EN (0x1 << 8) +#define RT5660_MIC2_OVTH_MASK (0x3 << 6) +#define RT5660_MIC2_OVTH_SFT 6 +#define RT5660_MIC2_OVTH_600UA (0x0 << 6) +#define RT5660_MIC2_OVTH_1500UA (0x1 << 6) +#define RT5660_MIC2_OVTH_2000UA (0x2 << 6) +#define RT5660_PWR_CLK25M_MASK (0x1 << 4) +#define RT5660_PWR_CLK25M_SFT 4 +#define RT5660_PWR_CLK25M_PD (0x0 << 4) +#define RT5660_PWR_CLK25M_PU (0x1 << 4) + +/* EQ Control 1 (0xb0) */ +#define RT5660_EQ_SRC_MASK (0x1 << 15) +#define RT5660_EQ_SRC_SFT 15 +#define RT5660_EQ_SRC_DAC (0x0 << 15) +#define RT5660_EQ_SRC_ADC (0x1 << 15) +#define RT5660_EQ_UPD (0x1 << 14) +#define RT5660_EQ_UPD_BIT 14 + +/* Jack Detect Control (0xbb) */ +#define RT5660_JD_MASK (0x3 << 14) +#define RT5660_JD_SFT 14 +#define RT5660_JD_DIS (0x0 << 14) +#define RT5660_JD_GPIO1 (0x1 << 14) +#define RT5660_JD_GPIO2 (0x2 << 14) +#define RT5660_JD_LOUT_MASK (0x1 << 11) +#define RT5660_JD_LOUT_SFT 11 +#define RT5660_JD_LOUT_DIS (0x0 << 11) +#define RT5660_JD_LOUT_EN (0x1 << 11) +#define RT5660_JD_LOUT_TRG_MASK (0x1 << 10) +#define RT5660_JD_LOUT_TRG_SFT 10 +#define RT5660_JD_LOUT_TRG_LO (0x0 << 10) +#define RT5660_JD_LOUT_TRG_HI (0x1 << 10) +#define RT5660_JD_SPO_MASK (0x1 << 9) +#define RT5660_JD_SPO_SFT 9 +#define RT5660_JD_SPO_DIS (0x0 << 9) +#define RT5660_JD_SPO_EN (0x1 << 9) +#define RT5660_JD_SPO_TRG_MASK (0x1 << 8) +#define RT5660_JD_SPO_TRG_SFT 8 +#define RT5660_JD_SPO_TRG_LO (0x0 << 8) +#define RT5660_JD_SPO_TRG_HI (0x1 << 8) + +/* IRQ Control 1 (0xbd) */ +#define RT5660_IRQ_JD_MASK (0x1 << 15) +#define RT5660_IRQ_JD_SFT 15 +#define RT5660_IRQ_JD_BP (0x0 << 15) +#define RT5660_IRQ_JD_NOR (0x1 << 15) +#define RT5660_IRQ_OT_MASK (0x1 << 14) +#define RT5660_IRQ_OT_SFT 14 +#define RT5660_IRQ_OT_BP (0x0 << 14) +#define RT5660_IRQ_OT_NOR (0x1 << 14) +#define RT5660_JD_STKY_MASK (0x1 << 13) +#define RT5660_JD_STKY_SFT 13 +#define RT5660_JD_STKY_DIS (0x0 << 13) +#define RT5660_JD_STKY_EN (0x1 << 13) +#define RT5660_OT_STKY_MASK (0x1 << 12) +#define RT5660_OT_STKY_SFT 12 +#define RT5660_OT_STKY_DIS (0x0 << 12) +#define RT5660_OT_STKY_EN (0x1 << 12) +#define RT5660_JD_P_MASK (0x1 << 11) +#define RT5660_JD_P_SFT 11 +#define RT5660_JD_P_NOR (0x0 << 11) +#define RT5660_JD_P_INV (0x1 << 11) +#define RT5660_OT_P_MASK (0x1 << 10) +#define RT5660_OT_P_SFT 10 +#define RT5660_OT_P_NOR (0x0 << 10) +#define RT5660_OT_P_INV (0x1 << 10) + +/* IRQ Control 2 (0xbe) */ +#define RT5660_IRQ_MB1_OC_MASK (0x1 << 15) +#define RT5660_IRQ_MB1_OC_SFT 15 +#define RT5660_IRQ_MB1_OC_BP (0x0 << 15) +#define RT5660_IRQ_MB1_OC_NOR (0x1 << 15) +#define RT5660_IRQ_MB2_OC_MASK (0x1 << 14) +#define RT5660_IRQ_MB2_OC_SFT 14 +#define RT5660_IRQ_MB2_OC_BP (0x0 << 14) +#define RT5660_IRQ_MB2_OC_NOR (0x1 << 14) +#define RT5660_MB1_OC_STKY_MASK (0x1 << 11) +#define RT5660_MB1_OC_STKY_SFT 11 +#define RT5660_MB1_OC_STKY_DIS (0x0 << 11) +#define RT5660_MB1_OC_STKY_EN (0x1 << 11) +#define RT5660_MB2_OC_STKY_MASK (0x1 << 10) +#define RT5660_MB2_OC_STKY_SFT 10 +#define RT5660_MB2_OC_STKY_DIS (0x0 << 10) +#define RT5660_MB2_OC_STKY_EN (0x1 << 10) +#define RT5660_MB1_OC_P_MASK (0x1 << 7) +#define RT5660_MB1_OC_P_SFT 7 +#define RT5660_MB1_OC_P_NOR (0x0 << 7) +#define RT5660_MB1_OC_P_INV (0x1 << 7) +#define RT5660_MB2_OC_P_MASK (0x1 << 6) +#define RT5660_MB2_OC_P_SFT 6 +#define RT5660_MB2_OC_P_NOR (0x0 << 6) +#define RT5660_MB2_OC_P_INV (0x1 << 6) +#define RT5660_MB1_OC_CLR (0x1 << 3) +#define RT5660_MB1_OC_CLR_SFT 3 +#define RT5660_MB2_OC_CLR (0x1 << 2) +#define RT5660_MB2_OC_CLR_SFT 2 + +/* GPIO Control 1 (0xc0) */ +#define RT5660_GP2_PIN_MASK (0x1 << 14) +#define RT5660_GP2_PIN_SFT 14 +#define RT5660_GP2_PIN_GPIO2 (0x0 << 14) +#define RT5660_GP2_PIN_DMIC1_SDA (0x1 << 14) +#define RT5660_GP1_PIN_MASK (0x3 << 12) +#define RT5660_GP1_PIN_SFT 12 +#define RT5660_GP1_PIN_GPIO1 (0x0 << 12) +#define RT5660_GP1_PIN_DMIC1_SCL (0x1 << 12) +#define RT5660_GP1_PIN_IRQ (0x2 << 12) +#define RT5660_GPIO_M_MASK (0x1 << 9) +#define RT5660_GPIO_M_SFT 9 +#define RT5660_GPIO_M_FLT (0x0 << 9) +#define RT5660_GPIO_M_PH (0x1 << 9) + +/* GPIO Control 3 (0xc2) */ +#define RT5660_GP2_PF_MASK (0x1 << 5) +#define RT5660_GP2_PF_SFT 5 +#define RT5660_GP2_PF_IN (0x0 << 5) +#define RT5660_GP2_PF_OUT (0x1 << 5) +#define RT5660_GP2_OUT_MASK (0x1 << 4) +#define RT5660_GP2_OUT_SFT 4 +#define RT5660_GP2_OUT_LO (0x0 << 4) +#define RT5660_GP2_OUT_HI (0x1 << 4) +#define RT5660_GP2_P_MASK (0x1 << 3) +#define RT5660_GP2_P_SFT 3 +#define RT5660_GP2_P_NOR (0x0 << 3) +#define RT5660_GP2_P_INV (0x1 << 3) +#define RT5660_GP1_PF_MASK (0x1 << 2) +#define RT5660_GP1_PF_SFT 2 +#define RT5660_GP1_PF_IN (0x0 << 2) +#define RT5660_GP1_PF_OUT (0x1 << 2) +#define RT5660_GP1_OUT_MASK (0x1 << 1) +#define RT5660_GP1_OUT_SFT 1 +#define RT5660_GP1_OUT_LO (0x0 << 1) +#define RT5660_GP1_OUT_HI (0x1 << 1) +#define RT5660_GP1_P_MASK (0x1) +#define RT5660_GP1_P_SFT 0 +#define RT5660_GP1_P_NOR (0x0) +#define RT5660_GP1_P_INV (0x1) + +/* Soft volume and zero cross control 1 (0xd9) */ +#define RT5660_SV_MASK (0x1 << 15) +#define RT5660_SV_SFT 15 +#define RT5660_SV_DIS (0x0 << 15) +#define RT5660_SV_EN (0x1 << 15) +#define RT5660_SPO_SV_MASK (0x1 << 14) +#define RT5660_SPO_SV_SFT 14 +#define RT5660_SPO_SV_DIS (0x0 << 14) +#define RT5660_SPO_SV_EN (0x1 << 14) +#define RT5660_OUT_SV_MASK (0x1 << 12) +#define RT5660_OUT_SV_SFT 12 +#define RT5660_OUT_SV_DIS (0x0 << 12) +#define RT5660_OUT_SV_EN (0x1 << 12) +#define RT5660_ZCD_DIG_MASK (0x1 << 11) +#define RT5660_ZCD_DIG_SFT 11 +#define RT5660_ZCD_DIG_DIS (0x0 << 11) +#define RT5660_ZCD_DIG_EN (0x1 << 11) +#define RT5660_ZCD_MASK (0x1 << 10) +#define RT5660_ZCD_SFT 10 +#define RT5660_ZCD_PD (0x0 << 10) +#define RT5660_ZCD_PU (0x1 << 10) +#define RT5660_SV_DLY_MASK (0xf) +#define RT5660_SV_DLY_SFT 0 + +/* Soft volume and zero cross control 2 (0xda) */ +#define RT5660_ZCD_SPO_MASK (0x1 << 15) +#define RT5660_ZCD_SPO_SFT 15 +#define RT5660_ZCD_SPO_DIS (0x0 << 15) +#define RT5660_ZCD_SPO_EN (0x1 << 15) +#define RT5660_ZCD_OMR_MASK (0x1 << 8) +#define RT5660_ZCD_OMR_SFT 8 +#define RT5660_ZCD_OMR_DIS (0x0 << 8) +#define RT5660_ZCD_OMR_EN (0x1 << 8) +#define RT5660_ZCD_OML_MASK (0x1 << 7) +#define RT5660_ZCD_OML_SFT 7 +#define RT5660_ZCD_OML_DIS (0x0 << 7) +#define RT5660_ZCD_OML_EN (0x1 << 7) +#define RT5660_ZCD_SPM_MASK (0x1 << 6) +#define RT5660_ZCD_SPM_SFT 6 +#define RT5660_ZCD_SPM_DIS (0x0 << 6) +#define RT5660_ZCD_SPM_EN (0x1 << 6) +#define RT5660_ZCD_RMR_MASK (0x1 << 5) +#define RT5660_ZCD_RMR_SFT 5 +#define RT5660_ZCD_RMR_DIS (0x0 << 5) +#define RT5660_ZCD_RMR_EN (0x1 << 5) +#define RT5660_ZCD_RML_MASK (0x1 << 4) +#define RT5660_ZCD_RML_SFT 4 +#define RT5660_ZCD_RML_DIS (0x0 << 4) +#define RT5660_ZCD_RML_EN (0x1 << 4) + +/* General Control 1 (0xfa) */ +#define RT5660_PWR_VREF_HP (0x1 << 11) +#define RT5660_PWR_VREF_HP_SFT 11 +#define RT5660_DIG_GATE_CTRL (0x1) +#define RT5660_DIG_GATE_CTRL_SFT 0 + +/* System Clock Source */ +#define RT5660_SCLK_S_MCLK 0 +#define RT5660_SCLK_S_PLL1 1 +#define RT5660_SCLK_S_RCCLK 2 + +/* PLL1 Source */ +#define RT5660_PLL1_S_MCLK 0 +#define RT5660_PLL1_S_BCLK 1 + +enum { + RT5660_AIF1, + RT5660_AIFS, +}; + +struct rt5660_priv { + struct snd_soc_codec *codec; + struct rt5660_platform_data pdata; + struct regmap *regmap; + struct clk *mclk; + + int sysclk; + int sysclk_src; + int lrck[RT5660_AIFS]; + int bclk[RT5660_AIFS]; + int master[RT5660_AIFS]; + + int pll_src; + int pll_in; + int pll_out; +}; + +#endif -- cgit v0.10.2 From fe27f4e0545d3fc1b0518fafb4fe0460d757651d Mon Sep 17 00:00:00 2001 From: Sandeep Tayal Date: Tue, 20 Sep 2016 19:16:05 +0530 Subject: ASoC: hdac_hdmi: use audio component framework to read ELD With codec read sometimes the pin_sense shows invalid monitor present and eld_valid. Currently driver polls for few times to get the valid ELD data. To avoid the latency, Instead of reading ELD from codec, read it directly from the display driver using audio component framework. Removed the direct codec helper functions. Signed-off-by: Sandeep Tayal Signed-off-by: Jeeja KP Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 4e181b2..537f61a 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -46,6 +46,10 @@ #define ELD_MAX_SIZE 256 #define ELD_FIXED_BYTES 20 +#define ELD_VER_CEA_861D 2 +#define ELD_VER_PARTIAL 31 +#define ELD_MAX_MNL 16 + struct hdac_hdmi_cvt_params { unsigned int channels_min; unsigned int channels_max; @@ -81,8 +85,6 @@ struct hdac_hdmi_pin { hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; struct hdac_hdmi_eld eld; struct hdac_ext_device *edev; - int repoll_count; - struct delayed_work work; struct mutex lock; bool chmap_set; unsigned char chmap[8]; /* ALSA API channel-map */ @@ -173,80 +175,6 @@ format_constraint: } - /* HDMI ELD routines */ -static unsigned int hdac_hdmi_get_eld_data(struct hdac_device *codec, - hda_nid_t nid, int byte_index) -{ - unsigned int val; - - val = snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD, - byte_index); - - dev_dbg(&codec->dev, "HDMI: ELD data byte %d: 0x%x\n", - byte_index, val); - - return val; -} - -static int hdac_hdmi_get_eld_size(struct hdac_device *codec, hda_nid_t nid) -{ - return snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, - AC_DIPSIZE_ELD_BUF); -} - -/* - * This function queries the ELD size and ELD data and fills in the buffer - * passed by user - */ -static int hdac_hdmi_get_eld(struct hdac_device *codec, hda_nid_t nid, - unsigned char *buf, int *eld_size) -{ - int i, size, ret = 0; - - /* - * ELD size is initialized to zero in caller function. If no errors and - * ELD is valid, actual eld_size is assigned. - */ - - size = hdac_hdmi_get_eld_size(codec, nid); - if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) { - dev_err(&codec->dev, "HDMI: invalid ELD buf size %d\n", size); - return -ERANGE; - } - - /* set ELD buffer */ - for (i = 0; i < size; i++) { - unsigned int val = hdac_hdmi_get_eld_data(codec, nid, i); - /* - * Graphics driver might be writing to ELD buffer right now. - * Just abort. The caller will repoll after a while. - */ - if (!(val & AC_ELDD_ELD_VALID)) { - dev_err(&codec->dev, - "HDMI: invalid ELD data byte %d\n", i); - ret = -EINVAL; - goto error; - } - val &= AC_ELDD_ELD_DATA; - /* - * The first byte cannot be zero. This can happen on some DVI - * connections. Some Intel chips may also need some 250ms delay - * to return non-zero ELD data, even when the graphics driver - * correctly writes ELD content before setting ELD_valid bit. - */ - if (!val && !i) { - dev_err(&codec->dev, "HDMI: 0 ELD data\n"); - ret = -EINVAL; - goto error; - } - buf[i] = val; - } - - *eld_size = size; -error: - return ret; -} - static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac, hda_nid_t cvt_nid, hda_nid_t pin_nid, u32 stream_tag, int format) @@ -1059,32 +987,59 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid) return hdac_hdmi_query_cvt_params(&edev->hdac, cvt); } -static void hdac_hdmi_parse_eld(struct hdac_ext_device *edev, +static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev, struct hdac_hdmi_pin *pin) { + unsigned int ver, mnl; + + ver = (pin->eld.eld_buffer[DRM_ELD_VER] & DRM_ELD_VER_MASK) + >> DRM_ELD_VER_SHIFT; + + if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) { + dev_dbg(&edev->hdac.dev, "HDMI: Unknown ELD version %d\n", ver); + return -EINVAL; + } + + mnl = (pin->eld.eld_buffer[DRM_ELD_CEA_EDID_VER_MNL] & + DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT; + + if (mnl > ELD_MAX_MNL) { + dev_dbg(&edev->hdac.dev, "HDMI: MNL Invalid %d\n", mnl); + return -EINVAL; + } + pin->eld.info.spk_alloc = pin->eld.eld_buffer[DRM_ELD_SPEAKER]; + + return 0; } -static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll) +static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin) { struct hdac_ext_device *edev = pin->edev; struct hdac_hdmi_priv *hdmi = edev->private_data; struct hdac_hdmi_pcm *pcm; - int val; - - pin->repoll_count = repoll; + int size; - pm_runtime_get_sync(&edev->hdac.dev); - val = snd_hdac_codec_read(&edev->hdac, pin->nid, 0, - AC_VERB_GET_PIN_SENSE, 0); + mutex_lock(&hdmi->pin_mutex); + pin->eld.monitor_present = false; - dev_dbg(&edev->hdac.dev, "Pin sense val %x for pin: %d\n", - val, pin->nid); + size = snd_hdac_acomp_get_eld(&edev->hdac, pin->nid, -1, + &pin->eld.monitor_present, pin->eld.eld_buffer, + ELD_MAX_SIZE); + if (size > 0) { + size = min(size, ELD_MAX_SIZE); + if (hdac_hdmi_parse_eld(edev, pin) < 0) + size = -EINVAL; + } - mutex_lock(&hdmi->pin_mutex); - pin->eld.monitor_present = !!(val & AC_PINSENSE_PRESENCE); - pin->eld.eld_valid = !!(val & AC_PINSENSE_ELDV); + if (size > 0) { + pin->eld.eld_valid = true; + pin->eld.eld_size = size; + } else { + pin->eld.eld_valid = false; + pin->eld.eld_size = 0; + } pcm = hdac_hdmi_get_pcm(edev, pin); @@ -1106,66 +1061,23 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll) } mutex_unlock(&hdmi->pin_mutex); - goto put_hdac_device; + return; } if (pin->eld.monitor_present && pin->eld.eld_valid) { - /* TODO: use i915 component for reading ELD later */ - if (hdac_hdmi_get_eld(&edev->hdac, pin->nid, - pin->eld.eld_buffer, - &pin->eld.eld_size) == 0) { - - if (pcm) { - dev_dbg(&edev->hdac.dev, - "jack report for pcm=%d\n", - pcm->pcm_id); - - snd_jack_report(pcm->jack, SND_JACK_AVOUT); - } - hdac_hdmi_parse_eld(edev, pin); - - print_hex_dump_debug("ELD: ", - DUMP_PREFIX_OFFSET, 16, 1, - pin->eld.eld_buffer, pin->eld.eld_size, - true); - } else { - pin->eld.monitor_present = false; - pin->eld.eld_valid = false; - - if (pcm) { - dev_dbg(&edev->hdac.dev, - "jack report for pcm=%d\n", - pcm->pcm_id); + if (pcm) { + dev_dbg(&edev->hdac.dev, + "jack report for pcm=%d\n", + pcm->pcm_id); - snd_jack_report(pcm->jack, 0); - } + snd_jack_report(pcm->jack, SND_JACK_AVOUT); } + + print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1, + pin->eld.eld_buffer, pin->eld.eld_size, false); } mutex_unlock(&hdmi->pin_mutex); - - /* - * Sometimes the pin_sense may present invalid monitor - * present and eld_valid. If ELD data is not valid, loop few - * more times to get correct pin sense and valid ELD. - */ - if ((!pin->eld.monitor_present || !pin->eld.eld_valid) && repoll) - schedule_delayed_work(&pin->work, msecs_to_jiffies(300)); - -put_hdac_device: - pm_runtime_put_sync(&edev->hdac.dev); -} - -static void hdac_hdmi_repoll_eld(struct work_struct *work) -{ - struct hdac_hdmi_pin *pin = - container_of(to_delayed_work(work), struct hdac_hdmi_pin, work); - - /* picked from legacy HDA driver */ - if (pin->repoll_count++ > 6) - pin->repoll_count = 0; - - hdac_hdmi_present_sense(pin, pin->repoll_count); } static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) @@ -1184,7 +1096,6 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) pin->edev = edev; mutex_init(&pin->lock); - INIT_DELAYED_WORK(&pin->work, hdac_hdmi_repoll_eld); return 0; } @@ -1395,7 +1306,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port) list_for_each_entry(pin, &hdmi->pin_list, head) { if (pin->nid == pin_nid) - hdac_hdmi_present_sense(pin, 1); + hdac_hdmi_present_sense(pin); } } @@ -1496,7 +1407,7 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec) } list_for_each_entry(pin, &hdmi->pin_list, head) - hdac_hdmi_present_sense(pin, 1); + hdac_hdmi_present_sense(pin); /* Imp: Store the card pointer in hda_codec */ edev->card = dapm->card->snd_card; @@ -1561,7 +1472,7 @@ static void hdmi_codec_complete(struct device *dev) * all pins here. */ list_for_each_entry(pin, &hdmi->pin_list, head) - hdac_hdmi_present_sense(pin, 1); + hdac_hdmi_present_sense(pin); pm_runtime_put_sync(&edev->hdac.dev); } -- cgit v0.10.2 From dc995069c675af71a2ecf2ade0995df084da3e2e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 9 Sep 2016 10:09:29 +0100 Subject: ASoC: Intel: remove status, it is shadowing status of a higher scope The second declaration of status is shadowing the status of a higher scope. This uninitialized status results in garbage being returned by the !x86_match_cpu(cpu_ids) || !iosf_mbi_available() return exit path. Fix this by removing the extraneous second declaration of status. Signed-off-by: Colin Ian King Signed-off-by: Mark Brown diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index 9718e82..ba5c0d7 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c @@ -249,7 +249,6 @@ static int is_byt_cr(struct device *dev, bool *bytcr) { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ {} }; - int status; u32 bios_status; if (!x86_match_cpu(cpu_ids) || !iosf_mbi_available()) { -- cgit v0.10.2 From 89128534f925711eea1653c264683b7d14a46530 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Wed, 24 Aug 2016 22:06:35 +0100 Subject: ASoC: rt5677: Add ACPI support The Chromebook Pixel 2015 uses this codec with the ACPI ID RT5677CE, but does not use the standard DT property names so add a new function to parse the codec properties from these ACPI properties. Also, the GPIOs are only available by index, so we need to register a mapping to allow machine drivers to access the GPIOs by name. Signed-off-by: John Keeping Tested-by: Tom Rini Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index da9483c..0e7aba1 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include @@ -40,6 +41,15 @@ #define RT5677_PR_BASE (RT5677_PR_RANGE_BASE + (0 * RT5677_PR_SPACING)) +/* GPIO indexes defined by ACPI */ +enum { + RT5677_GPIO_PLUG_DET = 0, + RT5677_GPIO_MIC_PRESENT_L = 1, + RT5677_GPIO_HOTWORD_DET_L = 2, + RT5677_GPIO_DSP_INT = 3, + RT5677_GPIO_HP_AMP_SHDN_L = 4, +}; + static const struct regmap_range_cfg rt5677_ranges[] = { { .name = "PR", @@ -5018,10 +5028,47 @@ static const struct regmap_config rt5677_regmap = { static const struct i2c_device_id rt5677_i2c_id[] = { { "rt5677", RT5677 }, { "rt5676", RT5676 }, + { "RT5677CE:00", RT5677 }, { } }; MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); +static const struct acpi_gpio_params plug_det_gpio = { RT5677_GPIO_PLUG_DET, 0, false }; +static const struct acpi_gpio_params mic_present_gpio = { RT5677_GPIO_MIC_PRESENT_L, 0, false }; +static const struct acpi_gpio_params headphone_enable_gpio = { RT5677_GPIO_HP_AMP_SHDN_L, 0, false }; + +static const struct acpi_gpio_mapping bdw_rt5677_gpios[] = { + { "plug-det-gpios", &plug_det_gpio, 1 }, + { "mic-present-gpios", &mic_present_gpio, 1 }, + { "headphone-enable-gpios", &headphone_enable_gpio, 1 }, + { NULL }, +}; + +static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677, + struct device *dev) +{ + int ret; + u32 val; + + ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), + bdw_rt5677_gpios); + if (ret) + dev_warn(dev, "Failed to add driver gpios\n"); + + if (!device_property_read_u32(dev, "DCLK", &val)) + rt5677->pdata.dmic2_clk_pin = val; + + rt5677->pdata.in1_diff = device_property_read_bool(dev, "IN1"); + rt5677->pdata.in2_diff = device_property_read_bool(dev, "IN2"); + rt5677->pdata.lout1_diff = device_property_read_bool(dev, "OUT1"); + rt5677->pdata.lout2_diff = device_property_read_bool(dev, "OUT2"); + rt5677->pdata.lout3_diff = device_property_read_bool(dev, "OUT3"); + + device_property_read_u32(dev, "JD1", &rt5677->pdata.jd1_gpio); + device_property_read_u32(dev, "JD2", &rt5677->pdata.jd2_gpio); + device_property_read_u32(dev, "JD3", &rt5677->pdata.jd3_gpio); +} + static void rt5677_read_device_properties(struct rt5677_priv *rt5677, struct device *dev) { @@ -5127,8 +5174,12 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, if (pdata) rt5677->pdata = *pdata; - else + else if (i2c->dev.of_node) rt5677_read_device_properties(rt5677, &i2c->dev); + else if (ACPI_HANDLE(&i2c->dev)) + rt5677_read_acpi_properties(rt5677, &i2c->dev); + else + return -EINVAL; /* pow-ldo2 and reset are optional. The codec pins may be statically * connected on the board without gpios. If the gpio device property -- cgit v0.10.2 From 2d995e5dc283adbfbf9c1eb81bf35ca7af2d22a6 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Wed, 24 Aug 2016 22:06:36 +0100 Subject: ASoC: Intel: boards: Add bdw-rt5677 machine driver This is used by the Chromebook Pixel 2015. Signed-off-by: Ben Zhang Signed-off-by: Dylan Reid [john@metanate.com: - forward-port driver from Chromium OS 3.14 tree to master - remove wake on voice function that isn't supported by upstream rt5677 driver - remote owner assignment in platform_driver (Evan McClain) - convert to devm_snd_soc_register_card (Evan McClain) - add a full copyright header based on module license and Chromium OS Git history ] Signed-off-by: John Keeping Tested-by: Genki Marshall Tested-by: Tom Rini Signed-off-by: Mark Brown diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index fc6e780..26eb5a0 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -121,6 +121,17 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH This adds audio driver for Intel Baytrail platform based boards with the MAX98090 audio codec. +config SND_SOC_INTEL_BDW_RT5677_MACH + tristate "ASoC Audio driver for Intel Broadwell with RT5677 codec" + depends on X86_INTEL_LPSS && GPIOLIB && I2C && DW_DMAC + depends on DW_DMAC_CORE=y + select SND_SOC_INTEL_SST + select SND_SOC_INTEL_HASWELL + select SND_SOC_RT5677 + help + This adds support for Intel Broadwell platform based boards with + the RT5677 audio codec. + config SND_SOC_INTEL_BROADWELL_MACH tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint" depends on X86_INTEL_LPSS && I2C && DW_DMAC && \ diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index dac03a0..5639f10 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -1,6 +1,7 @@ snd-soc-sst-haswell-objs := haswell.o snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o +snd-soc-sst-bdw-rt5677-mach-objs := bdw-rt5677.o snd-soc-sst-broadwell-objs := broadwell.o snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o snd-soc-sst-bxt-rt298-objs := bxt_rt298.o @@ -19,6 +20,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH) += snd-soc-sst-bxt-da7219_max98357a.o obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o +obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH) += snd-soc-sst-bdw-rt5677-mach.o obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH) += snd-soc-sst-bytcr-rt5651.o obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c new file mode 100644 index 0000000..547e670 --- /dev/null +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -0,0 +1,347 @@ +/* + * ASoC machine driver for Intel Broadwell platforms with RT5677 codec + * + * Copyright (c) 2014, The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../common/sst-dsp.h" +#include "../haswell/sst-haswell-ipc.h" + +#include "../../codecs/rt5677.h" + +struct bdw_rt5677_priv { + struct gpio_desc *gpio_hp_en; + struct snd_soc_codec *codec; +}; + +static int bdw_rt5677_event_hp(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct bdw_rt5677_priv *bdw_rt5677 = snd_soc_card_get_drvdata(card); + + if (SND_SOC_DAPM_EVENT_ON(event)) + msleep(70); + + gpiod_set_value_cansleep(bdw_rt5677->gpio_hp_en, + SND_SOC_DAPM_EVENT_ON(event)); + + return 0; +} + +static const struct snd_soc_dapm_widget bdw_rt5677_widgets[] = { + SND_SOC_DAPM_HP("Headphone", bdw_rt5677_event_hp), + SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Local DMICs", NULL), + SND_SOC_DAPM_MIC("Remote DMICs", NULL), +}; + +static const struct snd_soc_dapm_route bdw_rt5677_map[] = { + /* Speakers */ + {"Speaker", NULL, "PDM1L"}, + {"Speaker", NULL, "PDM1R"}, + + /* Headset jack connectors */ + {"Headphone", NULL, "LOUT1"}, + {"Headphone", NULL, "LOUT2"}, + {"IN1P", NULL, "Headset Mic"}, + {"IN1N", NULL, "Headset Mic"}, + + /* Digital MICs + * Local DMICs: the two DMICs on the mainboard + * Remote DMICs: the two DMICs on the camera module + */ + {"DMIC L1", NULL, "Remote DMICs"}, + {"DMIC R1", NULL, "Remote DMICs"}, + {"DMIC L2", NULL, "Local DMICs"}, + {"DMIC R2", NULL, "Local DMICs"}, + + /* CODEC BE connections */ + {"SSP0 CODEC IN", NULL, "AIF1 Capture"}, + {"AIF1 Playback", NULL, "SSP0 CODEC OUT"}, +}; + +static const struct snd_kcontrol_new bdw_rt5677_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Local DMICs"), + SOC_DAPM_PIN_SWITCH("Remote DMICs"), +}; + + +static struct snd_soc_jack headphone_jack; +static struct snd_soc_jack mic_jack; + +static struct snd_soc_jack_pin headphone_jack_pin = { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, +}; + +static struct snd_soc_jack_pin mic_jack_pin = { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, +}; + +static struct snd_soc_jack_gpio headphone_jack_gpio = { + .name = "plug-det", + .report = SND_JACK_HEADPHONE, + .debounce_time = 200, +}; + +static struct snd_soc_jack_gpio mic_jack_gpio = { + .name = "mic-present", + .report = SND_JACK_MICROPHONE, + .debounce_time = 200, + .invert = 1, +}; + +static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + + /* The ADSP will covert the FE rate to 48k, stereo */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSP0 to 16 bit */ + snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - + SNDRV_PCM_HW_PARAM_FIRST_MASK], + SNDRV_PCM_FORMAT_S16_LE); + return 0; +} + +static int bdw_rt5677_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5677_SCLK_S_MCLK, 24576000, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, "can't set codec sysclk configuration\n"); + return ret; + } + + return ret; +} + +static struct snd_soc_ops bdw_rt5677_ops = { + .hw_params = bdw_rt5677_hw_params, +}; + +static int bdw_rt5677_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev); + struct sst_hsw *broadwell = pdata->dsp; + int ret; + + /* Set ADSP SSP port settings */ + ret = sst_hsw_device_set_config(broadwell, SST_HSW_DEVICE_SSP_0, + SST_HSW_DEVICE_MCLK_FREQ_24_MHZ, + SST_HSW_DEVICE_CLOCK_MASTER, 9); + if (ret < 0) { + dev_err(rtd->dev, "error: failed to set device config\n"); + return ret; + } + + return 0; +} + +static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) +{ + struct bdw_rt5677_priv *bdw_rt5677 = + snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + + /* Enable codec ASRC function for Stereo DAC/Stereo1 ADC/DMIC/I2S1. + * The ASRC clock source is clk_i2s1_asrc. + */ + rt5677_sel_asrc_clk_src(codec, RT5677_DA_STEREO_FILTER | + RT5677_AD_STEREO1_FILTER | RT5677_I2S1_SOURCE, + RT5677_CLK_SEL_I2S1_ASRC); + + /* Request rt5677 GPIO for headphone amp control */ + bdw_rt5677->gpio_hp_en = devm_gpiod_get_index(codec->dev, + "headphone-enable", 0, 0); + if (IS_ERR(bdw_rt5677->gpio_hp_en)) { + dev_err(codec->dev, "Can't find HP_AMP_SHDN_L gpio\n"); + return PTR_ERR(bdw_rt5677->gpio_hp_en); + } + gpiod_direction_output(bdw_rt5677->gpio_hp_en, 0); + + /* Create and initialize headphone jack */ + if (!snd_soc_card_jack_new(rtd->card, "Headphone Jack", + SND_JACK_HEADPHONE, &headphone_jack, + &headphone_jack_pin, 1)) { + headphone_jack_gpio.gpiod_dev = codec->dev; + if (snd_soc_jack_add_gpios(&headphone_jack, 1, + &headphone_jack_gpio)) + dev_err(codec->dev, "Can't add headphone jack gpio\n"); + } else { + dev_err(codec->dev, "Can't create headphone jack\n"); + } + + /* Create and initialize mic jack */ + if (!snd_soc_card_jack_new(rtd->card, "Mic Jack", + SND_JACK_MICROPHONE, &mic_jack, + &mic_jack_pin, 1)) { + mic_jack_gpio.gpiod_dev = codec->dev; + if (snd_soc_jack_add_gpios(&mic_jack, 1, &mic_jack_gpio)) + dev_err(codec->dev, "Can't add mic jack gpio\n"); + } else { + dev_err(codec->dev, "Can't create mic jack\n"); + } + bdw_rt5677->codec = codec; + + snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); + return 0; +} + +/* broadwell digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link bdw_rt5677_dais[] = { + /* Front End DAI links */ + { + .name = "System PCM", + .stream_name = "System Playback/Capture", + .cpu_dai_name = "System Pin", + .platform_name = "haswell-pcm-audio", + .dynamic = 1, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .init = bdw_rt5677_rtd_init, + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST + }, + .dpcm_capture = 1, + .dpcm_playback = 1, + }, + + /* Back End DAI links */ + { + /* SSP0 - Codec */ + .name = "Codec", + .id = 0, + .cpu_dai_name = "snd-soc-dummy-dai", + .platform_name = "snd-soc-dummy", + .no_pcm = 1, + .codec_name = "i2c-RT5677CE:00", + .codec_dai_name = "rt5677-aif1", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .be_hw_params_fixup = broadwell_ssp0_fixup, + .ops = &bdw_rt5677_ops, + .dpcm_playback = 1, + .dpcm_capture = 1, + .init = bdw_rt5677_init, + }, +}; + +static int bdw_rt5677_suspend_pre(struct snd_soc_card *card) +{ + struct bdw_rt5677_priv *bdw_rt5677 = snd_soc_card_get_drvdata(card); + struct snd_soc_dapm_context *dapm; + + if (bdw_rt5677->codec) { + dapm = snd_soc_codec_get_dapm(bdw_rt5677->codec); + snd_soc_dapm_disable_pin(dapm, "MICBIAS1"); + } + return 0; +} + +static int bdw_rt5677_resume_post(struct snd_soc_card *card) +{ + struct bdw_rt5677_priv *bdw_rt5677 = snd_soc_card_get_drvdata(card); + struct snd_soc_dapm_context *dapm; + + if (bdw_rt5677->codec) { + dapm = snd_soc_codec_get_dapm(bdw_rt5677->codec); + snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); + } + return 0; +} + +/* ASoC machine driver for Broadwell DSP + RT5677 */ +static struct snd_soc_card bdw_rt5677_card = { + .name = "bdw-rt5677", + .owner = THIS_MODULE, + .dai_link = bdw_rt5677_dais, + .num_links = ARRAY_SIZE(bdw_rt5677_dais), + .dapm_widgets = bdw_rt5677_widgets, + .num_dapm_widgets = ARRAY_SIZE(bdw_rt5677_widgets), + .dapm_routes = bdw_rt5677_map, + .num_dapm_routes = ARRAY_SIZE(bdw_rt5677_map), + .controls = bdw_rt5677_controls, + .num_controls = ARRAY_SIZE(bdw_rt5677_controls), + .fully_routed = true, + .suspend_pre = bdw_rt5677_suspend_pre, + .resume_post = bdw_rt5677_resume_post, +}; + +static int bdw_rt5677_probe(struct platform_device *pdev) +{ + struct bdw_rt5677_priv *bdw_rt5677; + + bdw_rt5677_card.dev = &pdev->dev; + + /* Allocate driver private struct */ + bdw_rt5677 = devm_kzalloc(&pdev->dev, sizeof(struct bdw_rt5677_priv), + GFP_KERNEL); + if (!bdw_rt5677) { + dev_err(&pdev->dev, "Can't allocate bdw_rt5677\n"); + return -ENOMEM; + } + + snd_soc_card_set_drvdata(&bdw_rt5677_card, bdw_rt5677); + + return devm_snd_soc_register_card(&pdev->dev, &bdw_rt5677_card); +} + +static struct platform_driver bdw_rt5677_audio = { + .probe = bdw_rt5677_probe, + .driver = { + .name = "bdw-rt5677", + }, +}; + +module_platform_driver(bdw_rt5677_audio) + +/* Module information */ +MODULE_AUTHOR("Ben Zhang"); +MODULE_DESCRIPTION("Intel Broadwell RT5677 machine driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:bdw-rt5677"); diff --git a/sound/soc/intel/common/sst-acpi.c b/sound/soc/intel/common/sst-acpi.c index 2c5eda1..1285cc5 100644 --- a/sound/soc/intel/common/sst-acpi.c +++ b/sound/soc/intel/common/sst-acpi.c @@ -199,6 +199,7 @@ static struct sst_acpi_desc sst_acpi_haswell_desc = { static struct sst_acpi_mach broadwell_machines[] = { { "INT343A", "broadwell-audio", "intel/IntcSST2.bin", NULL, NULL, NULL }, + { "RT5677CE", "bdw-rt5677", "intel/IntcSST2.bin", NULL, NULL, NULL }, {} }; -- cgit v0.10.2 From 318824d3d0795309b448563faa698d3c02035db4 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 24 Sep 2016 19:28:23 +0900 Subject: ALSA: control: cage TLV_DB_RANGE_HEAD in kernel land because it was obsoleted In commit bf1d1c9b6179 ("ALSA: tlv: add DECLARE_TLV_DB_RANGE()"), the new macro was added so that "dB range information can be specified without having to count the items manually for TLV_DB_RANGE_HEAD()". In short, TLV_DB_RANGE_HEAD macro was obsoleted. In commit 46e860f76804 ("ALSA: rename TLV-related macros so that they're friendly to user applications"), TLV-related macros are exposed for applications in user land to get content of data structured by Type/Length/Value shape. The commit managed to expose TLV-related macros as many as possible, while obsoleted TLV_DB_RANGE_HEAD() was included to the list of exposed macros. This situation brings some confusions to application developers because they might think all exposed macros have their own purpose and useful for applications. For the reason, this commit moves TLV_DB_RANGE_HEAD macro from UAPI header to a header for kernel land, again. The above commit is done within the same development period for kernel 4.9, thus not published yet. This commit might certainly brings no confusions to user land. Reference: commit bf1d1c9b6179 ("ALSA: tlv: add DECLARE_TLV_DB_RANGE()") Reference: commit 46e860f76804 ("ALSA: rename TLV-related macros so that they're friendly to user applications") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/include/sound/tlv.h b/include/sound/tlv.h index 6e2e773..3677ebb 100644 --- a/include/sound/tlv.h +++ b/include/sound/tlv.h @@ -46,8 +46,15 @@ #define TLV_DB_RANGE_ITEM SNDRV_CTL_TLVD_DB_RANGE_ITEM #define DECLARE_TLV_DB_RANGE SNDRV_CTL_TLVD_DECLARE_DB_RANGE -#define TLV_DB_RANGE_HEAD SNDRV_CTL_TLVD_DB_RANGE_HEAD #define TLV_DB_GAIN_MUTE SNDRV_CTL_TLVD_DB_GAIN_MUTE +/* + * The below assumes that each item TLV is 4 words like DB_SCALE or LINEAR. + * This is an old fasion and obsoleted by commit bf1d1c9b6179("ALSA: tlv: add + * DECLARE_TLV_DB_RANGE()"). + */ +#define TLV_DB_RANGE_HEAD(num) \ + SNDRV_CTL_TLVT_DB_RANGE, 6 * (num) * sizeof(unsigned int) + #endif /* __SOUND_TLV_H */ diff --git a/include/uapi/sound/tlv.h b/include/uapi/sound/tlv.h index f3c198f..b4df440 100644 --- a/include/uapi/sound/tlv.h +++ b/include/uapi/sound/tlv.h @@ -94,9 +94,6 @@ unsigned int name[] = { \ SNDRV_CTL_TLVD_DB_RANGE_ITEM(__VA_ARGS__) \ } -/* The below assumes that each item TLV is 4 words like DB_SCALE or LINEAR */ -#define SNDRV_CTL_TLVD_DB_RANGE_HEAD(num) \ - SNDRV_CTL_TLVT_DB_RANGE, 6 * (num) * sizeof(unsigned int) #define SNDRV_CTL_TLVD_DB_GAIN_MUTE -9999999 -- cgit v0.10.2 From 8da08ca03b73593d5299893bf29fc08569c3fb5f Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 25 Sep 2016 22:00:20 +0900 Subject: ALSA: usb-line6: use the same declaration as definition in header for MIDI manufacturer ID Currently, usb-line6 module exports an array of MIDI manufacturer ID and usb-pod module uses it. However, the declaration is not the definition in common header. The difference is explicit length of array. Although compiler calculates it and everything goes well, it's better to use the same representation between definition and declaration. This commit fills the length of array for usb-line6 module. As a small good sub-effect, this commit suppress below warnings from static analysis by sparse v0.5.0. sound/usb/line6/driver.c:274:43: error: cannot size expression sound/usb/line6/driver.c:275:16: error: cannot size expression sound/usb/line6/driver.c:276:16: error: cannot size expression sound/usb/line6/driver.c:277:16: error: cannot size expression Fixes: 705ececd1c60 ("Staging: add line6 usb driver") Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index c998667..14e587e 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -30,7 +30,7 @@ /* This is Line 6's MIDI manufacturer ID. */ -const unsigned char line6_midi_id[] = { +const unsigned char line6_midi_id[3] = { 0x00, 0x01, 0x0c }; EXPORT_SYMBOL_GPL(line6_midi_id); -- cgit v0.10.2 From 392c9da24a994f238c5d7ea611c6245be4617014 Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Mon, 26 Sep 2016 10:59:38 +0800 Subject: ALSA: hda - Adding one more ALC255 pin definition for headset problem We have two new Dell laptop models, they have the same ALC255 pin definition, but not in the pin quirk table yet, as a result, the headset microphone can't work. After adding the definition in the table, the headset microphone works well. Cc: Signed-off-by: Hui Wang Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 32cbcf8..bd481ac 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5853,6 +5853,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x14, 0x90170120}, {0x21, 0x02211030}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + {0x14, 0x90170110}, + {0x1b, 0x02011020}, + {0x21, 0x0221101f}), + SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, {0x14, 0x90170130}, {0x1b, 0x01014020}, {0x21, 0x0221103f}), -- cgit v0.10.2 From 88b456b0f4a2a4c10c141a7d83113a8ce2164463 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 26 Sep 2016 08:59:50 -0700 Subject: ASoC: hdac_hdmi: Drop use of audio component framework to read ELD The audio component framework code has not yet landed in the i915 driver so drop the use of the API for the time being. Signed-off-by: Mark Brown Cc: Jeeja KP diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 537f61a..4e181b2 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -46,10 +46,6 @@ #define ELD_MAX_SIZE 256 #define ELD_FIXED_BYTES 20 -#define ELD_VER_CEA_861D 2 -#define ELD_VER_PARTIAL 31 -#define ELD_MAX_MNL 16 - struct hdac_hdmi_cvt_params { unsigned int channels_min; unsigned int channels_max; @@ -85,6 +81,8 @@ struct hdac_hdmi_pin { hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; struct hdac_hdmi_eld eld; struct hdac_ext_device *edev; + int repoll_count; + struct delayed_work work; struct mutex lock; bool chmap_set; unsigned char chmap[8]; /* ALSA API channel-map */ @@ -175,6 +173,80 @@ format_constraint: } + /* HDMI ELD routines */ +static unsigned int hdac_hdmi_get_eld_data(struct hdac_device *codec, + hda_nid_t nid, int byte_index) +{ + unsigned int val; + + val = snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD, + byte_index); + + dev_dbg(&codec->dev, "HDMI: ELD data byte %d: 0x%x\n", + byte_index, val); + + return val; +} + +static int hdac_hdmi_get_eld_size(struct hdac_device *codec, hda_nid_t nid) +{ + return snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, + AC_DIPSIZE_ELD_BUF); +} + +/* + * This function queries the ELD size and ELD data and fills in the buffer + * passed by user + */ +static int hdac_hdmi_get_eld(struct hdac_device *codec, hda_nid_t nid, + unsigned char *buf, int *eld_size) +{ + int i, size, ret = 0; + + /* + * ELD size is initialized to zero in caller function. If no errors and + * ELD is valid, actual eld_size is assigned. + */ + + size = hdac_hdmi_get_eld_size(codec, nid); + if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) { + dev_err(&codec->dev, "HDMI: invalid ELD buf size %d\n", size); + return -ERANGE; + } + + /* set ELD buffer */ + for (i = 0; i < size; i++) { + unsigned int val = hdac_hdmi_get_eld_data(codec, nid, i); + /* + * Graphics driver might be writing to ELD buffer right now. + * Just abort. The caller will repoll after a while. + */ + if (!(val & AC_ELDD_ELD_VALID)) { + dev_err(&codec->dev, + "HDMI: invalid ELD data byte %d\n", i); + ret = -EINVAL; + goto error; + } + val &= AC_ELDD_ELD_DATA; + /* + * The first byte cannot be zero. This can happen on some DVI + * connections. Some Intel chips may also need some 250ms delay + * to return non-zero ELD data, even when the graphics driver + * correctly writes ELD content before setting ELD_valid bit. + */ + if (!val && !i) { + dev_err(&codec->dev, "HDMI: 0 ELD data\n"); + ret = -EINVAL; + goto error; + } + buf[i] = val; + } + + *eld_size = size; +error: + return ret; +} + static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac, hda_nid_t cvt_nid, hda_nid_t pin_nid, u32 stream_tag, int format) @@ -987,59 +1059,32 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid) return hdac_hdmi_query_cvt_params(&edev->hdac, cvt); } -static int hdac_hdmi_parse_eld(struct hdac_ext_device *edev, +static void hdac_hdmi_parse_eld(struct hdac_ext_device *edev, struct hdac_hdmi_pin *pin) { - unsigned int ver, mnl; - - ver = (pin->eld.eld_buffer[DRM_ELD_VER] & DRM_ELD_VER_MASK) - >> DRM_ELD_VER_SHIFT; - - if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) { - dev_dbg(&edev->hdac.dev, "HDMI: Unknown ELD version %d\n", ver); - return -EINVAL; - } - - mnl = (pin->eld.eld_buffer[DRM_ELD_CEA_EDID_VER_MNL] & - DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT; - - if (mnl > ELD_MAX_MNL) { - dev_dbg(&edev->hdac.dev, "HDMI: MNL Invalid %d\n", mnl); - return -EINVAL; - } - pin->eld.info.spk_alloc = pin->eld.eld_buffer[DRM_ELD_SPEAKER]; - - return 0; } -static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin) +static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll) { struct hdac_ext_device *edev = pin->edev; struct hdac_hdmi_priv *hdmi = edev->private_data; struct hdac_hdmi_pcm *pcm; - int size; + int val; - mutex_lock(&hdmi->pin_mutex); - pin->eld.monitor_present = false; + pin->repoll_count = repoll; - size = snd_hdac_acomp_get_eld(&edev->hdac, pin->nid, -1, - &pin->eld.monitor_present, pin->eld.eld_buffer, - ELD_MAX_SIZE); + pm_runtime_get_sync(&edev->hdac.dev); + val = snd_hdac_codec_read(&edev->hdac, pin->nid, 0, + AC_VERB_GET_PIN_SENSE, 0); - if (size > 0) { - size = min(size, ELD_MAX_SIZE); - if (hdac_hdmi_parse_eld(edev, pin) < 0) - size = -EINVAL; - } + dev_dbg(&edev->hdac.dev, "Pin sense val %x for pin: %d\n", + val, pin->nid); - if (size > 0) { - pin->eld.eld_valid = true; - pin->eld.eld_size = size; - } else { - pin->eld.eld_valid = false; - pin->eld.eld_size = 0; - } + + mutex_lock(&hdmi->pin_mutex); + pin->eld.monitor_present = !!(val & AC_PINSENSE_PRESENCE); + pin->eld.eld_valid = !!(val & AC_PINSENSE_ELDV); pcm = hdac_hdmi_get_pcm(edev, pin); @@ -1061,23 +1106,66 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin) } mutex_unlock(&hdmi->pin_mutex); - return; + goto put_hdac_device; } if (pin->eld.monitor_present && pin->eld.eld_valid) { - if (pcm) { - dev_dbg(&edev->hdac.dev, - "jack report for pcm=%d\n", - pcm->pcm_id); + /* TODO: use i915 component for reading ELD later */ + if (hdac_hdmi_get_eld(&edev->hdac, pin->nid, + pin->eld.eld_buffer, + &pin->eld.eld_size) == 0) { - snd_jack_report(pcm->jack, SND_JACK_AVOUT); - } + if (pcm) { + dev_dbg(&edev->hdac.dev, + "jack report for pcm=%d\n", + pcm->pcm_id); + + snd_jack_report(pcm->jack, SND_JACK_AVOUT); + } + hdac_hdmi_parse_eld(edev, pin); + + print_hex_dump_debug("ELD: ", + DUMP_PREFIX_OFFSET, 16, 1, + pin->eld.eld_buffer, pin->eld.eld_size, + true); + } else { + pin->eld.monitor_present = false; + pin->eld.eld_valid = false; + + if (pcm) { + dev_dbg(&edev->hdac.dev, + "jack report for pcm=%d\n", + pcm->pcm_id); - print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1, - pin->eld.eld_buffer, pin->eld.eld_size, false); + snd_jack_report(pcm->jack, 0); + } + } } mutex_unlock(&hdmi->pin_mutex); + + /* + * Sometimes the pin_sense may present invalid monitor + * present and eld_valid. If ELD data is not valid, loop few + * more times to get correct pin sense and valid ELD. + */ + if ((!pin->eld.monitor_present || !pin->eld.eld_valid) && repoll) + schedule_delayed_work(&pin->work, msecs_to_jiffies(300)); + +put_hdac_device: + pm_runtime_put_sync(&edev->hdac.dev); +} + +static void hdac_hdmi_repoll_eld(struct work_struct *work) +{ + struct hdac_hdmi_pin *pin = + container_of(to_delayed_work(work), struct hdac_hdmi_pin, work); + + /* picked from legacy HDA driver */ + if (pin->repoll_count++ > 6) + pin->repoll_count = 0; + + hdac_hdmi_present_sense(pin, pin->repoll_count); } static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) @@ -1096,6 +1184,7 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) pin->edev = edev; mutex_init(&pin->lock); + INIT_DELAYED_WORK(&pin->work, hdac_hdmi_repoll_eld); return 0; } @@ -1306,7 +1395,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port) list_for_each_entry(pin, &hdmi->pin_list, head) { if (pin->nid == pin_nid) - hdac_hdmi_present_sense(pin); + hdac_hdmi_present_sense(pin, 1); } } @@ -1407,7 +1496,7 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec) } list_for_each_entry(pin, &hdmi->pin_list, head) - hdac_hdmi_present_sense(pin); + hdac_hdmi_present_sense(pin, 1); /* Imp: Store the card pointer in hda_codec */ edev->card = dapm->card->snd_card; @@ -1472,7 +1561,7 @@ static void hdmi_codec_complete(struct device *dev) * all pins here. */ list_for_each_entry(pin, &hdmi->pin_list, head) - hdac_hdmi_present_sense(pin); + hdac_hdmi_present_sense(pin, 1); pm_runtime_put_sync(&edev->hdac.dev); } -- cgit v0.10.2 From 1fa96f3fdad7cef5d043a502682580d2bc3d5ace Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 26 Sep 2016 10:15:22 +0100 Subject: ASoC: wm_adsp: Use usleep_range for short delay Replace the 1ms msleep in wm_adsp2_ena with a usleep_range, as per normal guidance on delay functions. Also tighten up the delay a little as 1ms was quite generous. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 24485ec..4188c37 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2237,7 +2237,7 @@ static int wm_adsp2_ena(struct wm_adsp *dsp) if (val & ADSP2_RAM_RDY) break; - msleep(1); + usleep_range(250, 500); } if (!(val & ADSP2_RAM_RDY)) { -- cgit v0.10.2 From 90d19ba54b428a6bc8cc51ef6c60c6e65e6e2f35 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 26 Sep 2016 10:15:23 +0100 Subject: ASoC: wm_adsp: Put DSP into low power state between loading and running Between when we load the DSP and when it actually starts running put the core into a lower power state where the memory is retained but nothing is clocked. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 4188c37..446f029 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2259,6 +2259,11 @@ static void wm_adsp2_boot_work(struct work_struct *work) mutex_lock(&dsp->pwr_lock); + ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, + ADSP2_MEM_ENA, ADSP2_MEM_ENA); + if (ret != 0) + goto err_mutex; + ret = wm_adsp2_ena(dsp); if (ret != 0) goto err_mutex; @@ -2282,6 +2287,12 @@ static void wm_adsp2_boot_work(struct work_struct *work) dsp->booted = true; + /* Turn DSP back off until we are ready to run */ + ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, + ADSP2_SYS_ENA, 0); + if (ret != 0) + goto err_ena; + mutex_unlock(&dsp->pwr_lock); return; @@ -2344,6 +2355,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, if (!dsp->booted) return -EIO; + ret = wm_adsp2_ena(dsp); + if (ret != 0) + goto err; + /* Sync set controls */ ret = wm_coeff_sync_controls(dsp); if (ret != 0) @@ -2382,7 +2397,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, dsp->booted = false; regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, - ADSP2_CORE_ENA | ADSP2_START, 0); + ADSP2_MEM_ENA | ADSP2_CORE_ENA | ADSP2_START, + 0); /* Make sure DMAs are quiesced */ regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); -- cgit v0.10.2 From 57a60cc3616c8f5447d914b646a1d6df2ba9cc9d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 26 Sep 2016 10:15:24 +0100 Subject: ASoC: wm_adsp: Allow preloader to do the final shutdown of the DSP The booting process for the DSP is clearly separated into two parts, the preloader brings up the core and downloads code, then the main widget starts the code actually executing. However the shutdown sequence is all handled with the main widget. To allow the preloading to be run independently of the main audio bring up it makes sense, and is generally just cleaner, for the preloader widget to shutdown those things it initialised. This patch moves the appropriate parts of the shutdown process into the preloader widget. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 446f029..b943dde 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2323,6 +2323,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); struct wm_adsp *dsp = &dsps[w->shift]; + struct wm_coeff_ctl *ctl; dsp->card = codec->component.card; @@ -2331,6 +2332,24 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, wm_adsp2_set_dspclk(dsp, freq); queue_work(system_unbound_wq, &dsp->boot_work); break; + case SND_SOC_DAPM_PRE_PMD: + wm_adsp_debugfs_clear(dsp); + + dsp->fw_id = 0; + dsp->fw_id_version = 0; + + dsp->booted = false; + + regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, + ADSP2_MEM_ENA, 0); + + list_for_each_entry(ctl, &dsp->ctl_list, list) + ctl->enabled = 0; + + wm_adsp_free_alg_regions(dsp); + + adsp_dbg(dsp, "Shutdown complete\n"); + break; default: break; } @@ -2345,7 +2364,6 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); struct wm_adsp *dsp = &dsps[w->shift]; - struct wm_coeff_ctl *ctl; int ret; switch (event) { @@ -2388,17 +2406,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, mutex_lock(&dsp->pwr_lock); - wm_adsp_debugfs_clear(dsp); - - dsp->fw_id = 0; - dsp->fw_id_version = 0; - dsp->running = false; - dsp->booted = false; regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, - ADSP2_MEM_ENA | ADSP2_CORE_ENA | ADSP2_START, - 0); + ADSP2_CORE_ENA | ADSP2_START, 0); /* Make sure DMAs are quiesced */ regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); @@ -2408,17 +2419,12 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, ADSP2_SYS_ENA, 0); - list_for_each_entry(ctl, &dsp->ctl_list, list) - ctl->enabled = 0; - - wm_adsp_free_alg_regions(dsp); - if (wm_adsp_fw[dsp->fw].num_caps != 0) wm_adsp_buffer_free(dsp); mutex_unlock(&dsp->pwr_lock); - adsp_dbg(dsp, "Shutdown complete\n"); + adsp_dbg(dsp, "Execution stopped\n"); break; default: diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 228b1f9..362dd7c 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -89,7 +89,7 @@ struct wm_adsp { #define WM_ADSP2(wname, num, event_fn) \ { .id = snd_soc_dapm_supply, .name = wname " Preloader", \ .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ - .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ + .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD, \ .subseq = 100, /* Ensure we run after SYSCLK supply widget */ }, \ { .id = snd_soc_dapm_out_drv, .name = wname, \ .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \ -- cgit v0.10.2 From 899a247cf6d5bbb9eb799261791441d7d5ea2099 Mon Sep 17 00:00:00 2001 From: Nikita Yushchenko Date: Mon, 26 Sep 2016 12:56:51 +0300 Subject: ASoC: simple-card: add support for aux devices Add device tree property to define auxiliary devices to be added to simle-audio-card. Together with proper audio routing definition, this allows to use simple-card in setups where separate amplifier chip is connected to codec's output. Signed-off-by: Nikita Yushchenko Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index cf3979e..5ecdde6 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt @@ -22,6 +22,8 @@ Optional properties: headphones are attached. - simple-audio-card,mic-det-gpio : Reference to GPIO that signals when a microphone is attached. +- simple-audio-card,aux-devs : List of phandles pointing to auxiliary devices, such + as amplifiers, to be added to the sound card. Optional subnodes: @@ -162,3 +164,38 @@ sound { }; }; }; + +Example 3 - route audio from IMX6 SSI2 through TLV320DAC3100 codec +through TPA6130A2 amplifier to headphones: + +&i2c0 { + codec: tlv320dac3100@18 { + compatible = "ti,tlv320dac3100"; + ... + } + + amp: tpa6130a2@60 { + compatible = "ti,tpa6130a2"; + ... + } +} + +sound { + compatible = "simple-audio-card"; + ... + simple-audio-card,widgets = + "Headphone", "Headphone Jack"; + simple-audio-card,routing = + "Headphone Jack", "HPLEFT", + "Headphone Jack", "HPRIGHT", + "LEFTIN", "HPL", + "RIGHTIN", "HPR"; + simple-audio-card,aux-devs = <&>; + simple-audio-card,cpu { + sound-dai = <&ssi2>; + }; + simple-audio-card,codec { + sound-dai = <&codec>; + clocks = ... + }; +}; diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index fe0bc5c..f608f8d2 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -318,6 +318,36 @@ dai_link_of_err: return ret; } +static int asoc_simple_card_parse_aux_devs(struct device_node *node, + struct simple_card_data *priv) +{ + struct device *dev = simple_priv_to_dev(priv); + struct device_node *aux_node; + int i, n, len; + + if (!of_find_property(node, PREFIX "aux-devs", &len)) + return 0; /* Ok to have no aux-devs */ + + n = len / sizeof(__be32); + if (n <= 0) + return -EINVAL; + + priv->snd_card.aux_dev = devm_kzalloc(dev, + n * sizeof(*priv->snd_card.aux_dev), GFP_KERNEL); + if (!priv->snd_card.aux_dev) + return -ENOMEM; + + for (i = 0; i < n; i++) { + aux_node = of_parse_phandle(node, PREFIX "aux-devs", i); + if (!aux_node) + return -EINVAL; + priv->snd_card.aux_dev[i].codec_of_node = aux_node; + } + + priv->snd_card.num_aux_devs = n; + return 0; +} + static int asoc_simple_card_parse_of(struct device_node *node, struct simple_card_data *priv) { @@ -372,6 +402,10 @@ static int asoc_simple_card_parse_of(struct device_node *node, } ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX); + if (ret < 0) + goto card_parse_end; + + ret = asoc_simple_card_parse_aux_devs(node, priv); card_parse_end: of_node_put(dai_link); -- cgit v0.10.2 From 020eab35390b976e6b93b61805002d3e2cd195de Mon Sep 17 00:00:00 2001 From: Nikita Yushchenko Date: Mon, 26 Sep 2016 13:35:50 +0300 Subject: ASoC: tpa6130a2: unmerge power enable error path from power disable path Code undo operations in power enable errror path explicitly, instead of reusing power disable path and playing with return values there. Signed-off-by: Nikita Yushchenko Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 3b6faed..3712db0 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -71,7 +71,14 @@ static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable) if (ret != 0) { dev_err(data->dev, "Failed to sync registers: %d\n", ret); - goto regcache_sync_failed; + regcache_cache_only(data->regmap, true); + if (data->power_gpio >= 0) + gpio_set_value(data->power_gpio, 0); + ret2 = regulator_disable(data->supply); + if (ret2 != 0) + dev_err(data->dev, + "Failed to disable supply: %d\n", ret2); + return ret; } } else { /* Powered off device does not retain registers. While device @@ -79,18 +86,17 @@ static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable) * happen in cache only. */ regcache_mark_dirty(data->regmap); -regcache_sync_failed: regcache_cache_only(data->regmap, true); /* Power off */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 0); - ret2 = regulator_disable(data->supply); - if (ret2 != 0) { + ret = regulator_disable(data->supply); + if (ret != 0) { dev_err(data->dev, - "Failed to disable supply: %d\n", ret2); - return ret ? ret : ret2; + "Failed to disable supply: %d\n", ret); + return ret; } } -- cgit v0.10.2 From c9e902f4b37a3c108eb5dc51f1340c09becd7232 Mon Sep 17 00:00:00 2001 From: Danny Milosavljevic Date: Sat, 24 Sep 2016 22:05:01 +0200 Subject: ASoC: sun4i-codec: Rename sun4i_codec_widgets for consistency Rename "sun4i_codec_widgets" to "sun4i_codec_controls" for consistency with the struct field name. Signed-off-by: Danny Milosavljevic Acked-by: Maxime Ripard Signed-off-by: Mark Brown diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index e51f363..e047ec0 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -509,7 +509,7 @@ static const struct snd_kcontrol_new sun4i_codec_pa_mute = static DECLARE_TLV_DB_SCALE(sun4i_codec_pa_volume_scale, -6300, 100, 1); -static const struct snd_kcontrol_new sun4i_codec_widgets[] = { +static const struct snd_kcontrol_new sun4i_codec_controls[] = { SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL, SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0, sun4i_codec_pa_volume_scale), @@ -629,8 +629,8 @@ static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = { static struct snd_soc_codec_driver sun4i_codec_codec = { .component_driver = { - .controls = sun4i_codec_widgets, - .num_controls = ARRAY_SIZE(sun4i_codec_widgets), + .controls = sun4i_codec_controls, + .num_controls = ARRAY_SIZE(sun4i_codec_controls), .dapm_widgets = sun4i_codec_codec_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets), .dapm_routes = sun4i_codec_codec_dapm_routes, -- cgit v0.10.2 From c14c59f2e9ca2dc3ddb3af67b71a11feaaacbbce Mon Sep 17 00:00:00 2001 From: Vishal Thanki Date: Mon, 26 Sep 2016 15:34:19 +0200 Subject: ASoC: ak4104: Limit the supported sample rates Currently the driver exposes range of sample rates between 8KHz to 192KHz as a part of dai_driver. This does not hold true as the limited number sample rates are allowed in hw_params DAI callback. This patch limits the sample rates exposed via dai_driver. Signed-off-by: Vishal Thanki Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index 595d02d..bc5c870 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c @@ -163,7 +163,10 @@ static struct snd_soc_dai_driver ak4104_dai = { .stream_name = "Playback", .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE -- cgit v0.10.2 From a7f16ea90ecffde4d4915eb7c81b11428e636920 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Mon, 26 Sep 2016 14:29:20 +0100 Subject: ASoC: da7219: Reset codec gracefully, if still active Currently the reset code in i2c_probe only resets the AAD part of the device and not the entire codec. This patch updates the driver to resolve this and ensures that if the codec is still active from a previous boot then the audio paths are powered down prior to reset. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 9d08c11..eecb6d6 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1925,7 +1925,8 @@ static int da7219_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct da7219_priv *da7219; - int ret; + unsigned int system_active, system_status; + int i, ret; da7219 = devm_kzalloc(&i2c->dev, sizeof(struct da7219_priv), GFP_KERNEL); @@ -1941,14 +1942,37 @@ static int da7219_i2c_probe(struct i2c_client *i2c, return ret; } - /* Software reset codec. */ + regcache_cache_bypass(da7219->regmap, true); + + /* Disable audio paths if still active from previous start */ + regmap_read(da7219->regmap, DA7219_SYSTEM_ACTIVE, &system_active); + if (system_active) { + regmap_write(da7219->regmap, DA7219_GAIN_RAMP_CTRL, + DA7219_GAIN_RAMP_RATE_NOMINAL); + regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_INPUT, 0x00); + regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_OUTPUT, 0x01); + + for (i = 0; i < DA7219_SYS_STAT_CHECK_RETRIES; ++i) { + regmap_read(da7219->regmap, DA7219_SYSTEM_STATUS, + &system_status); + if (!system_status) + break; + + msleep(DA7219_SYS_STAT_CHECK_DELAY); + } + } + + /* Soft reset codec */ regmap_write_bits(da7219->regmap, DA7219_ACCDET_CONFIG_1, DA7219_ACCDET_EN_MASK, 0); regmap_write_bits(da7219->regmap, DA7219_CIF_CTRL, - DA7219_CIF_REG_SOFT_RESET_MASK, 0); + DA7219_CIF_REG_SOFT_RESET_MASK, + DA7219_CIF_REG_SOFT_RESET_MASK); regmap_write_bits(da7219->regmap, DA7219_SYSTEM_ACTIVE, DA7219_SYSTEM_ACTIVE_MASK, 0); + regcache_cache_bypass(da7219->regmap, false); + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da7219, &da7219_dai, 1); if (ret < 0) { diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h index 545576d..f1b3ad8 100644 --- a/sound/soc/codecs/da7219.h +++ b/sound/soc/codecs/da7219.h @@ -578,6 +578,7 @@ #define DA7219_GAIN_RAMP_RATE_SHIFT 0 #define DA7219_GAIN_RAMP_RATE_MASK (0x3 << 0) #define DA7219_GAIN_RAMP_RATE_X8 (0x0 << 0) +#define DA7219_GAIN_RAMP_RATE_NOMINAL (0x1 << 0) #define DA7219_GAIN_RAMP_RATE_MAX 4 /* DA7219_PC_COUNT = 0x94 */ @@ -772,6 +773,10 @@ /* SRM */ #define DA7219_SRM_CHECK_RETRIES 8 +/* System Controller */ +#define DA7219_SYS_STAT_CHECK_RETRIES 6 +#define DA7219_SYS_STAT_CHECK_DELAY 50 + enum da7219_clk_src { DA7219_CLKSRC_MCLK = 0, DA7219_CLKSRC_MCLK_SQR, -- cgit v0.10.2 From bb0c35fcaf8f2ad3383dd43ca8abf5203cd06cc3 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Mon, 26 Sep 2016 14:29:21 +0100 Subject: ASoC: da7219: Disable AAD if codec is not a wake-up source Currently if AAD is enabled in the device, during system suspend the feature remains, regardless of whether the codec is a wake-up source or not. This means some additional power is being used which is unnecessary, and can causes issues with some platforms' IRQ handlers where state changes during system suspend aren't captured. This patch updates the driver to disable AAD during suspend, if we're not a wake-up source, and then re-enables this on resume. Signed-off-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/include/sound/da7219.h b/include/sound/da7219.h index 02876ac..409ef139 100644 --- a/include/sound/da7219.h +++ b/include/sound/da7219.h @@ -34,6 +34,8 @@ enum da7219_mic_amp_in_sel { struct da7219_aad_pdata; struct da7219_pdata { + bool wakeup_source; + /* Mic */ enum da7219_micbias_voltage micbias_lvl; enum da7219_mic_amp_in_sel mic_amp_in_sel; diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index fc27dab..2b8914d 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -797,6 +797,62 @@ static void da7219_aad_handle_pdata(struct snd_soc_codec *codec) /* + * Suspend/Resume + */ + +void da7219_aad_suspend(struct snd_soc_codec *codec) +{ + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); + struct da7219_aad_priv *da7219_aad = da7219->aad; + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + u8 micbias_ctrl; + + if (da7219_aad->jack) { + /* Disable jack detection during suspend */ + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, + DA7219_ACCDET_EN_MASK, 0); + + /* + * If we have a 4-pole jack inserted, then micbias will be + * enabled. We can disable micbias here, and keep a note to + * re-enable it on resume. If jack removal occurred during + * suspend then this will be dealt with through the IRQ handler. + */ + if (da7219_aad->jack_inserted) { + micbias_ctrl = snd_soc_read(codec, DA7219_MICBIAS_CTRL); + if (micbias_ctrl & DA7219_MICBIAS1_EN_MASK) { + snd_soc_dapm_disable_pin(dapm, "Mic Bias"); + snd_soc_dapm_sync(dapm); + da7219_aad->micbias_resume_enable = true; + } + } + } +} + +void da7219_aad_resume(struct snd_soc_codec *codec) +{ + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); + struct da7219_aad_priv *da7219_aad = da7219->aad; + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + + if (da7219_aad->jack) { + /* Re-enable micbias if previously enabled for 4-pole jack */ + if (da7219_aad->jack_inserted && + da7219_aad->micbias_resume_enable) { + snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); + snd_soc_dapm_sync(dapm); + da7219_aad->micbias_resume_enable = false; + } + + /* Re-enable jack detection */ + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, + DA7219_ACCDET_EN_MASK, + DA7219_ACCDET_EN_MASK); + } +} + + +/* * Init/Exit */ diff --git a/sound/soc/codecs/da7219-aad.h b/sound/soc/codecs/da7219-aad.h index a34be48..117a3d7 100644 --- a/sound/soc/codecs/da7219-aad.h +++ b/sound/soc/codecs/da7219-aad.h @@ -201,12 +201,17 @@ struct da7219_aad_priv { struct work_struct hptest_work; struct snd_soc_jack *jack; + bool micbias_resume_enable; bool jack_inserted; }; /* AAD control */ void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack); +/* Suspend/Resume */ +void da7219_aad_suspend(struct snd_soc_codec *codec); +void da7219_aad_resume(struct snd_soc_codec *codec); + /* Init/Exit */ int da7219_aad_init(struct snd_soc_codec *codec); void da7219_aad_exit(struct snd_soc_codec *codec); diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index eecb6d6..65f7e98 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1482,6 +1482,8 @@ static struct da7219_pdata *da7219_fw_to_pdata(struct snd_soc_codec *codec) if (!pdata) return NULL; + pdata->wakeup_source = device_property_read_bool(dev, "wakeup-source"); + if (device_property_read_u32(dev, "dlg,micbias-lvl", &of_val32) >= 0) pdata->micbias_lvl = da7219_fw_micbias_lvl(dev, of_val32); else @@ -1524,20 +1526,21 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: - if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) /* Master bias */ snd_soc_update_bits(codec, DA7219_REFERENCES, DA7219_BIAS_EN_MASK, DA7219_BIAS_EN_MASK); - } else { + + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE) { /* Remove MCLK */ if (da7219->mclk) clk_disable_unprepare(da7219->mclk); } break; case SND_SOC_BIAS_OFF: - /* Only disable master bias if jack detection not active */ - if (!da7219->aad->jack) + /* Only disable master bias if we're not a wake-up source */ + if (!da7219->wakeup_source) snd_soc_update_bits(codec, DA7219_REFERENCES, DA7219_BIAS_EN_MASK, 0); @@ -1603,6 +1606,8 @@ static void da7219_handle_pdata(struct snd_soc_codec *codec) if (pdata) { u8 micbias_lvl = 0; + da7219->wakeup_source = pdata->wakeup_source; + /* Mic Bias voltages */ switch (pdata->micbias_lvl) { case DA7219_MICBIAS_1_6V: @@ -1737,11 +1742,11 @@ static int da7219_suspend(struct snd_soc_codec *codec) { struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); - snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); + /* Suspend AAD if we're not a wake-up source */ + if (!da7219->wakeup_source) + da7219_aad_suspend(codec); - /* Put device into standby mode if jack detection disabled */ - if (!da7219->aad->jack) - snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, 0); + snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } @@ -1750,13 +1755,12 @@ static int da7219_resume(struct snd_soc_codec *codec) { struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); - /* Put device into active mode if previously pushed to standby */ - if (!da7219->aad->jack) - snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, - DA7219_SYSTEM_ACTIVE_MASK); - snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); + /* Resume AAD if previously suspended */ + if (!da7219->wakeup_source) + da7219_aad_resume(codec); + return 0; } #else diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h index f1b3ad8..66d3bad 100644 --- a/sound/soc/codecs/da7219.h +++ b/sound/soc/codecs/da7219.h @@ -803,6 +803,7 @@ struct da7219_priv { struct da7219_aad_priv *aad; struct da7219_pdata *pdata; + bool wakeup_source; struct regulator_bulk_data supplies[DA7219_NUM_SUPPLIES]; struct regmap *regmap; struct mutex lock; -- cgit v0.10.2 From ef9656b6936fb7f66e7e25d284c955f4893ac421 Mon Sep 17 00:00:00 2001 From: Nikita Yushchenko Date: Fri, 23 Sep 2016 14:52:52 +0300 Subject: ASoC: tlv320aic31xx: add explicit support for tlv320dac31xx tlv320dac31xx is a subset of tlv320aic31xx: - it does not have MIC inputs and ADC, thus capture is not supported, - it has analog inputs AIN1/AIN2 that can be mixed into output. Although tlv320dac31xx does work with tlv320aic31xx driver, this setup does register non-existent widgets and non-existent capture stream. Thus userspace lists non-existent objects in user interfaces, an can access these, causing operations with device registers that are declared as "reserved" in tlv320dac31xx datasheet. This patch fixes this situation by separating controls/widgets/routes into common, aic31xx-specific, and dac31xx-specific parts. Only parts that match actual hardware (as declared in "compatible" device tree property) are registered. Changes from v1: - update device tree binding documentation, - rebased on top of "ASoC: codec duplicated callback function goes to component on tlv320aic31xx" commit. Signed-off-by: Nikita Yushchenko Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt index eff12be..9340d2d 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt @@ -11,6 +11,7 @@ Required properties: "ti,tlv320aic3110" - TLV320AIC3110 (stereo speaker amp, no MiniDSP) "ti,tlv320aic3120" - TLV320AIC3120 (mono speaker amp, MiniDSP) "ti,tlv320aic3111" - TLV320AIC3111 (stereo speaker amp, MiniDSP) + "ti,tlv320dac3100" - TLV320DAC3100 (no ADC, mono speaker amp, no MiniDSP) - reg - - I2C slave address - HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply, @@ -37,9 +38,11 @@ CODEC output pins: * MICBIAS CODEC input pins: - * MIC1LP - * MIC1RP - * MIC1LM + * MIC1LP, devices with ADC + * MIC1RP, devices with ADC + * MIC1LM, devices with ADC + * AIN1, devices without ADC + * AIN2, devices without ADC The pins can be used in referring sound node's audio-routing property. diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index e46fb47..725173b 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -273,10 +273,20 @@ static const DECLARE_TLV_DB_SCALE(sp_vol_tlv, -6350, 50, 0); /* * controls to be exported to the user space */ -static const struct snd_kcontrol_new aic31xx_snd_controls[] = { +static const struct snd_kcontrol_new common31xx_snd_controls[] = { SOC_DOUBLE_R_S_TLV("DAC Playback Volume", AIC31XX_LDACVOL, AIC31XX_RDACVOL, 0, -127, 48, 7, 0, dac_vol_tlv), + SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN, + AIC31XX_HPRGAIN, 2, 1, 0), + SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN, + AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv), + + SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL, + AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv), +}; + +static const struct snd_kcontrol_new aic31xx_snd_controls[] = { SOC_SINGLE_TLV("ADC Fine Capture Volume", AIC31XX_ADCFGA, 4, 4, 1, adc_fgain_tlv), @@ -286,14 +296,6 @@ static const struct snd_kcontrol_new aic31xx_snd_controls[] = { SOC_SINGLE_TLV("Mic PGA Capture Volume", AIC31XX_MICPGA, 0, 119, 0, mic_pga_tlv), - - SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN, - AIC31XX_HPRGAIN, 2, 1, 0), - SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN, - AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv), - - SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL, - AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv), }; static const struct snd_kcontrol_new aic311x_snd_controls[] = { @@ -397,17 +399,28 @@ static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w, return 0; } -static const struct snd_kcontrol_new left_output_switches[] = { +static const struct snd_kcontrol_new aic31xx_left_output_switches[] = { SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0), SOC_DAPM_SINGLE("From MIC1LP", AIC31XX_DACMIXERROUTE, 5, 1, 0), SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 4, 1, 0), }; -static const struct snd_kcontrol_new right_output_switches[] = { +static const struct snd_kcontrol_new aic31xx_right_output_switches[] = { SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0), SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 1, 1, 0), }; +static const struct snd_kcontrol_new dac31xx_left_output_switches[] = { + SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0), + SOC_DAPM_SINGLE("From AIN1", AIC31XX_DACMIXERROUTE, 5, 1, 0), + SOC_DAPM_SINGLE("From AIN2", AIC31XX_DACMIXERROUTE, 4, 1, 0), +}; + +static const struct snd_kcontrol_new dac31xx_right_output_switches[] = { + SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0), + SOC_DAPM_SINGLE("From AIN2", AIC31XX_DACMIXERROUTE, 1, 1, 0), +}; + static const struct snd_kcontrol_new p_term_mic1lp = SOC_DAPM_ENUM("MIC1LP P-Terminal", mic1lp_p_enum); @@ -457,7 +470,7 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, return 0; } -static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { +static const struct snd_soc_dapm_widget common31xx_dapm_widgets[] = { SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_MUX("DAC Left Input", @@ -473,14 +486,7 @@ static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { AIC31XX_DACSETUP, 6, 0, aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - /* Output Mixers */ - SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, - left_output_switches, - ARRAY_SIZE(left_output_switches)), - SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, - right_output_switches, - ARRAY_SIZE(right_output_switches)), - + /* HP */ SND_SOC_DAPM_SWITCH("HP Left", SND_SOC_NOPM, 0, 0, &aic31xx_dapm_hpl_switch), SND_SOC_DAPM_SWITCH("HP Right", SND_SOC_NOPM, 0, 0, @@ -494,10 +500,34 @@ static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { NULL, 0, aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), - /* ADC */ - SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0, - aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_POST_PMD), + /* Mic Bias */ + SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, mic_bias_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + /* Outputs */ + SND_SOC_DAPM_OUTPUT("HPL"), + SND_SOC_DAPM_OUTPUT("HPR"), +}; + +static const struct snd_soc_dapm_widget dac31xx_dapm_widgets[] = { + /* Inputs */ + SND_SOC_DAPM_INPUT("AIN1"), + SND_SOC_DAPM_INPUT("AIN2"), + + /* Output Mixers */ + SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, + dac31xx_left_output_switches, + ARRAY_SIZE(dac31xx_left_output_switches)), + SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, + dac31xx_right_output_switches, + ARRAY_SIZE(dac31xx_right_output_switches)), +}; + +static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { + /* Inputs */ + SND_SOC_DAPM_INPUT("MIC1LP"), + SND_SOC_DAPM_INPUT("MIC1RP"), + SND_SOC_DAPM_INPUT("MIC1LM"), /* Input Selection to MIC_PGA */ SND_SOC_DAPM_MUX("MIC1LP P-Terminal", SND_SOC_NOPM, 0, 0, @@ -507,24 +537,25 @@ static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { SND_SOC_DAPM_MUX("MIC1LM P-Terminal", SND_SOC_NOPM, 0, 0, &p_term_mic1lm), + /* ADC */ + SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX("MIC1LM M-Terminal", SND_SOC_NOPM, 0, 0, &m_term_mic1lm), + /* Enabling & Disabling MIC Gain Ctl */ SND_SOC_DAPM_PGA("MIC_GAIN_CTL", AIC31XX_MICPGA, 7, 1, NULL, 0), - /* Mic Bias */ - SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, mic_bias_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - - /* Outputs */ - SND_SOC_DAPM_OUTPUT("HPL"), - SND_SOC_DAPM_OUTPUT("HPR"), - - /* Inputs */ - SND_SOC_DAPM_INPUT("MIC1LP"), - SND_SOC_DAPM_INPUT("MIC1RP"), - SND_SOC_DAPM_INPUT("MIC1LM"), + /* Output Mixers */ + SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, + aic31xx_left_output_switches, + ARRAY_SIZE(aic31xx_left_output_switches)), + SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, + aic31xx_right_output_switches, + ARRAY_SIZE(aic31xx_right_output_switches)), }; static const struct snd_soc_dapm_widget aic311x_dapm_widgets[] = { @@ -554,7 +585,7 @@ static const struct snd_soc_dapm_widget aic310x_dapm_widgets[] = { }; static const struct snd_soc_dapm_route -aic31xx_audio_map[] = { +common31xx_audio_map[] = { /* DAC Input Routing */ {"DAC Left Input", "Left Data", "DAC IN"}, {"DAC Left Input", "Right Data", "DAC IN"}, @@ -565,6 +596,31 @@ aic31xx_audio_map[] = { {"DAC Left", NULL, "DAC Left Input"}, {"DAC Right", NULL, "DAC Right Input"}, + /* HPL path */ + {"HP Left", "Switch", "Output Left"}, + {"HPL Driver", NULL, "HP Left"}, + {"HPL", NULL, "HPL Driver"}, + + /* HPR path */ + {"HP Right", "Switch", "Output Right"}, + {"HPR Driver", NULL, "HP Right"}, + {"HPR", NULL, "HPR Driver"}, +}; + +static const struct snd_soc_dapm_route +dac31xx_audio_map[] = { + /* Left Output */ + {"Output Left", "From Left DAC", "DAC Left"}, + {"Output Left", "From AIN1", "AIN1"}, + {"Output Left", "From AIN2", "AIN2"}, + + /* Right Output */ + {"Output Right", "From Right DAC", "DAC Right"}, + {"Output Right", "From AIN2", "AIN2"}, +}; + +static const struct snd_soc_dapm_route +aic31xx_audio_map[] = { /* Mic input */ {"MIC1LP P-Terminal", "FFR 10 Ohm", "MIC1LP"}, {"MIC1LP P-Terminal", "FFR 20 Ohm", "MIC1LP"}, @@ -595,16 +651,6 @@ aic31xx_audio_map[] = { /* Right Output */ {"Output Right", "From Right DAC", "DAC Right"}, {"Output Right", "From MIC1RP", "MIC1RP"}, - - /* HPL path */ - {"HP Left", "Switch", "Output Left"}, - {"HPL Driver", NULL, "HP Left"}, - {"HPL", NULL, "HPL Driver"}, - - /* HPR path */ - {"HP Right", "Switch", "Output Right"}, - {"HPR Driver", NULL, "HP Right"}, - {"HPR", NULL, "HPR Driver"}, }; static const struct snd_soc_dapm_route @@ -633,6 +679,13 @@ static int aic31xx_add_controls(struct snd_soc_codec *codec) int ret = 0; struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + if (!(aic31xx->pdata.codec_type & DAC31XX_BIT)) + ret = snd_soc_add_codec_controls( + codec, aic31xx_snd_controls, + ARRAY_SIZE(aic31xx_snd_controls)); + if (ret) + return ret; + if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) ret = snd_soc_add_codec_controls( codec, aic311x_snd_controls, @@ -651,6 +704,30 @@ static int aic31xx_add_widgets(struct snd_soc_codec *codec) struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); int ret = 0; + if (aic31xx->pdata.codec_type & DAC31XX_BIT) { + ret = snd_soc_dapm_new_controls( + dapm, dac31xx_dapm_widgets, + ARRAY_SIZE(dac31xx_dapm_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, dac31xx_audio_map, + ARRAY_SIZE(dac31xx_audio_map)); + if (ret) + return ret; + } else { + ret = snd_soc_dapm_new_controls( + dapm, aic31xx_dapm_widgets, + ARRAY_SIZE(aic31xx_dapm_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, aic31xx_audio_map, + ARRAY_SIZE(aic31xx_audio_map)); + if (ret) + return ret; + } + if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) { ret = snd_soc_dapm_new_controls( dapm, aic311x_dapm_widgets, @@ -1115,12 +1192,12 @@ static struct snd_soc_codec_driver soc_codec_driver_aic31xx = { .suspend_bias_off = true, .component_driver = { - .controls = aic31xx_snd_controls, - .num_controls = ARRAY_SIZE(aic31xx_snd_controls), - .dapm_widgets = aic31xx_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(aic31xx_dapm_widgets), - .dapm_routes = aic31xx_audio_map, - .num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map), + .controls = common31xx_snd_controls, + .num_controls = ARRAY_SIZE(common31xx_snd_controls), + .dapm_widgets = common31xx_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(common31xx_dapm_widgets), + .dapm_routes = common31xx_audio_map, + .num_dapm_routes = ARRAY_SIZE(common31xx_audio_map), }, }; @@ -1131,6 +1208,21 @@ static const struct snd_soc_dai_ops aic31xx_dai_ops = { .digital_mute = aic31xx_dac_mute, }; +static struct snd_soc_dai_driver dac31xx_dai_driver[] = { + { + .name = "tlv32dac31xx-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = AIC31XX_RATES, + .formats = AIC31XX_FORMATS, + }, + .ops = &aic31xx_dai_ops, + .symmetric_rates = 1, + } +}; + static struct snd_soc_dai_driver aic31xx_dai_driver[] = { { .name = "tlv320aic31xx-hifi", @@ -1261,9 +1353,16 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, if (ret) return ret; - return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, - aic31xx_dai_driver, - ARRAY_SIZE(aic31xx_dai_driver)); + if (aic31xx->pdata.codec_type & DAC31XX_BIT) + return snd_soc_register_codec(&i2c->dev, + &soc_codec_driver_aic31xx, + dac31xx_dai_driver, + ARRAY_SIZE(dac31xx_dai_driver)); + else + return snd_soc_register_codec(&i2c->dev, + &soc_codec_driver_aic31xx, + aic31xx_dai_driver, + ARRAY_SIZE(aic31xx_dai_driver)); } static int aic31xx_i2c_remove(struct i2c_client *i2c) @@ -1279,6 +1378,7 @@ static const struct i2c_device_id aic31xx_i2c_id[] = { { "tlv320aic3110", AIC3110 }, { "tlv320aic3120", AIC3120 }, { "tlv320aic3111", AIC3111 }, + { "tlv320dac3100", DAC3100 }, { } }; MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h index ac9b146..5acd5b6 100644 --- a/sound/soc/codecs/tlv320aic31xx.h +++ b/sound/soc/codecs/tlv320aic31xx.h @@ -24,12 +24,14 @@ #define AIC31XX_STEREO_CLASS_D_BIT 0x1 #define AIC31XX_MINIDSP_BIT 0x2 +#define DAC31XX_BIT 0x4 enum aic31xx_type { AIC3100 = 0, AIC3110 = AIC31XX_STEREO_CLASS_D_BIT, AIC3120 = AIC31XX_MINIDSP_BIT, AIC3111 = (AIC31XX_STEREO_CLASS_D_BIT | AIC31XX_MINIDSP_BIT), + DAC3100 = DAC31XX_BIT, }; struct aic31xx_pdata { -- cgit v0.10.2 From 94d215cc6fc5f0a5d202ed2b12fa0b14392cc2e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=B8=9C=E6=9E=97?= Date: Mon, 26 Sep 2016 08:29:31 +0000 Subject: ASoC: dpcm: print dai_link name of BE other than FE. When operating the BE, we should print out the dai_link name of BE other than FE. This is useful when analyzing the kernel log. Signed-off-by: Donglin Peng Signed-off-by: Mark Brown diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index c1bfe9d..d56a16a 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1793,7 +1793,7 @@ int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream) continue; dev_dbg(be->dev, "ASoC: close BE %s\n", - dpcm->fe->dai_link->name); + be->dai_link->name); soc_pcm_close(be_substream); be_substream->runtime = NULL; @@ -1859,7 +1859,7 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) continue; dev_dbg(be->dev, "ASoC: hw_free BE %s\n", - dpcm->fe->dai_link->name); + be->dai_link->name); soc_pcm_hw_free(be_substream); @@ -1937,7 +1937,7 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) continue; dev_dbg(be->dev, "ASoC: hw_params BE %s\n", - dpcm->fe->dai_link->name); + be->dai_link->name); ret = soc_pcm_hw_params(be_substream, &dpcm->hw_params); if (ret < 0) { @@ -2017,7 +2017,7 @@ static int dpcm_do_trigger(struct snd_soc_dpcm *dpcm, int ret; dev_dbg(dpcm->be->dev, "ASoC: trigger BE %s cmd %d\n", - dpcm->fe->dai_link->name, cmd); + dpcm->be->dai_link->name, cmd); ret = soc_pcm_trigger(substream, cmd); if (ret < 0) @@ -2232,7 +2232,7 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) continue; dev_dbg(be->dev, "ASoC: prepare BE %s\n", - dpcm->fe->dai_link->name); + be->dai_link->name); ret = soc_pcm_prepare(be_substream); if (ret < 0) { -- cgit v0.10.2 From 43c02ede76a60de38504f4f4fd6042f677be093a Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Mon, 26 Sep 2016 13:02:29 -0700 Subject: ASoC: Intel: Add DMIC channel constraint for bxt machine Add channel and rate constraints for Refcap and dmiccap devices respectively. Signed-off-by: Yong Zhi Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 3774b11..bb4533c 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -37,6 +37,7 @@ enum { BXT_DPCM_AUDIO_PB = 0, BXT_DPCM_AUDIO_CP, BXT_DPCM_AUDIO_REF_CP, + BXT_DPCM_AUDIO_DMIC_CP, BXT_DPCM_AUDIO_HDMI1_PB, BXT_DPCM_AUDIO_HDMI2_PB, BXT_DPCM_AUDIO_HDMI3_PB, @@ -252,6 +253,52 @@ static struct snd_soc_ops broxton_da7219_ops = { .hw_free = broxton_da7219_hw_free, }; +static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + channels->min = channels->max = DUAL_CHANNEL; + + return 0; +} + +static int broxton_dmic_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + + return snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); +} + +static const struct snd_soc_ops broxton_dmic_ops = { + .startup = broxton_dmic_startup, +}; + +static const unsigned int rates_16000[] = { + 16000, +}; + +static const struct snd_pcm_hw_constraint_list constraints_16000 = { + .count = ARRAY_SIZE(rates_16000), + .list = rates_16000, +}; + +static int broxton_refcap_startup(struct snd_pcm_substream *substream) +{ + return snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &constraints_16000); +}; + +static struct snd_soc_ops broxton_refcap_ops = { + .startup = broxton_refcap_startup, +}; + /* broxton digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link broxton_dais[] = { /* Front End DAI links */ @@ -299,6 +346,21 @@ static struct snd_soc_dai_link broxton_dais[] = { .ignore_suspend = 1, .nonatomic = 1, .dynamic = 1, + .ops = &broxton_refcap_ops, + }, + [BXT_DPCM_AUDIO_DMIC_CP] + { + .name = "Bxt Audio DMIC cap", + .stream_name = "dmiccap", + .cpu_dai_name = "DMIC Pin", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = "0000:00:0e.0", + .init = NULL, + .dpcm_capture = 1, + .nonatomic = 1, + .dynamic = 1, + .ops = &broxton_dmic_ops, }, [BXT_DPCM_AUDIO_HDMI1_PB] { @@ -382,6 +444,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .codec_dai_name = "dmic-hifi", .platform_name = "0000:00:0e.0", .ignore_suspend = 1, + .be_hw_params_fixup = broxton_dmic_fixup, .dpcm_capture = 1, .no_pcm = 1, }, -- cgit v0.10.2 From 0eec880966e77bdbee0112989a2be67d92e39929 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 27 Sep 2016 16:44:49 +0200 Subject: ALSA: hda - Add the top speaker pin config for HP Spectre x360 HP Spectre x360 with CX20724 codec has two speaker outputs while the BIOS sets up only the bottom one (NID 0x17) and disables the top one (NID 0x1d). This patch adds a fixup simply defining the proper pincfg for NID 0x1d so that the top speaker works as is. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=169071 Cc: Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 56fefbd..ed62748 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -261,6 +261,7 @@ enum { CXT_FIXUP_HP_530, CXT_FIXUP_CAP_MIX_AMP_5047, CXT_FIXUP_MUTE_LED_EAPD, + CXT_FIXUP_HP_SPECTRE, }; /* for hda_fixup_thinkpad_acpi() */ @@ -765,6 +766,14 @@ static const struct hda_fixup cxt_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = cxt_fixup_mute_led_eapd, }, + [CXT_FIXUP_HP_SPECTRE] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + /* enable NID 0x1d for the speaker on top */ + { 0x1d, 0x91170111 }, + { } + } + }, }; static const struct snd_pci_quirk cxt5045_fixups[] = { @@ -814,6 +823,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC), SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC), + SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE), SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), -- cgit v0.10.2 From d605bd024e085ba7fe0fbedf1707d339ea9cc0af Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 27 Sep 2016 16:35:44 +0100 Subject: ASoC: arizona: Add debug prints for output power up/down times When debugging it is useful to check the total power up/down delay that is executed as part of the coalesced output delay. This patch adds some debug prints for this. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index fae6ccf..7a99f77 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -891,6 +891,8 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, case ARIZONA_OUT3R_ENA_SHIFT: priv->out_up_pending--; if (!priv->out_up_pending) { + dev_dbg(codec->dev, "Power up delay: %d\n", + priv->out_up_delay); msleep(priv->out_up_delay); priv->out_up_delay = 0; } @@ -925,6 +927,8 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, case ARIZONA_OUT3R_ENA_SHIFT: priv->out_down_pending--; if (!priv->out_down_pending) { + dev_dbg(codec->dev, "Power down delay: %d\n", + priv->out_down_delay); msleep(priv->out_down_delay); priv->out_down_delay = 0; } -- cgit v0.10.2 From 8c7788f34e11f4c52d6a8a1340a8bd61476acabb Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 27 Sep 2016 16:35:45 +0100 Subject: ASoC: arizona: Add output power up/down delays for speaker path The later Arizona parts do run write sequences to power up and down the speaker path as such a delay needs to be inserted into the DAPM sequence to allow this to run. This patch adds appropriate delays into the existing coalesced delay scheme. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 7a99f77..85584ec 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -109,7 +109,7 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w, break; } - return 0; + return arizona_out_ev(w, kcontrol, event); } static irqreturn_t arizona_thermal_warn(int irq, void *data) @@ -159,12 +159,14 @@ static irqreturn_t arizona_thermal_shutdown(int irq, void *data) static const struct snd_soc_dapm_widget arizona_spkl = SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM, ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev, - SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU); + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD); static const struct snd_soc_dapm_widget arizona_spkr = SND_SOC_DAPM_PGA_E("OUT4R", SND_SOC_NOPM, ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev, - SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU); + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD); int arizona_init_spk(struct snd_soc_codec *codec) { @@ -864,6 +866,7 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); + struct arizona *arizona = priv->arizona; switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -877,6 +880,18 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, priv->out_up_pending++; priv->out_up_delay += 17; break; + case ARIZONA_OUT4L_ENA_SHIFT: + case ARIZONA_OUT4R_ENA_SHIFT: + priv->out_up_pending++; + switch (arizona->type) { + case WM5102: + case WM8997: + break; + default: + priv->out_up_delay += 10; + break; + } + break; default: break; } @@ -889,8 +904,10 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, case ARIZONA_OUT2R_ENA_SHIFT: case ARIZONA_OUT3L_ENA_SHIFT: case ARIZONA_OUT3R_ENA_SHIFT: + case ARIZONA_OUT4L_ENA_SHIFT: + case ARIZONA_OUT4R_ENA_SHIFT: priv->out_up_pending--; - if (!priv->out_up_pending) { + if (!priv->out_up_pending && priv->out_up_delay) { dev_dbg(codec->dev, "Power up delay: %d\n", priv->out_up_delay); msleep(priv->out_up_delay); @@ -913,6 +930,21 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, priv->out_down_pending++; priv->out_down_delay++; break; + case ARIZONA_OUT4L_ENA_SHIFT: + case ARIZONA_OUT4R_ENA_SHIFT: + priv->out_down_pending++; + switch (arizona->type) { + case WM5102: + case WM8997: + break; + case WM8998: + case WM1814: + priv->out_down_delay += 5; + break; + default: + priv->out_down_delay++; + break; + } default: break; } @@ -925,8 +957,10 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, case ARIZONA_OUT2R_ENA_SHIFT: case ARIZONA_OUT3L_ENA_SHIFT: case ARIZONA_OUT3R_ENA_SHIFT: + case ARIZONA_OUT4L_ENA_SHIFT: + case ARIZONA_OUT4R_ENA_SHIFT: priv->out_down_pending--; - if (!priv->out_down_pending) { + if (!priv->out_down_pending && priv->out_down_delay) { dev_dbg(codec->dev, "Power down delay: %d\n", priv->out_down_delay); msleep(priv->out_down_delay); -- cgit v0.10.2 From b74e7a26311a14f61fbcd516fb475dd79ea9c4b0 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 27 Sep 2016 07:45:10 +0900 Subject: ASoC: rt5616: add static qualifier for file local symbols Sparse reports below warnings. rt5616.c:1270:24: warning: symbol 'rt5616_aif_dai_ops' was not declared. Should it be static? rt5616.c:1277:27: warning: symbol 'rt5616_dai' was not declared. Should it be static? These two symbols are just used inner the file, thus it's better to add static qualifier. This commit adds it. Signed-off-by: Takashi Sakamoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index f527b5b..98ae326 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -1267,14 +1267,14 @@ static int rt5616_resume(struct snd_soc_codec *codec) #define RT5616_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) -struct snd_soc_dai_ops rt5616_aif_dai_ops = { +static struct snd_soc_dai_ops rt5616_aif_dai_ops = { .hw_params = rt5616_hw_params, .set_fmt = rt5616_set_dai_fmt, .set_sysclk = rt5616_set_dai_sysclk, .set_pll = rt5616_set_dai_pll, }; -struct snd_soc_dai_driver rt5616_dai[] = { +static struct snd_soc_dai_driver rt5616_dai[] = { { .name = "rt5616-aif1", .id = RT5616_AIF1, -- cgit v0.10.2 From 43d443dc257c00ef3a3f940b6abfb7537c4fcbe8 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 27 Sep 2016 07:45:09 +0900 Subject: ASoC: sst-bxt-da7219_max98357a: fix obsoleted initializers for array Sparse reports below warnings. bxt_da7219_max98357a.c:250:9: warning: obsolete array initializer, use C99 syntax bxt_da7219_max98357a.c:275:9: warning: obsolete array initializer, use C99 syntax bxt_da7219_max98357a.c:290:9: warning: obsolete array initializer, use C99 syntax bxt_da7219_max98357a.c:304:9: warning: obsolete array initializer, use C99 syntax bxt_da7219_max98357a.c:317:9: warning: obsolete array initializer, use C99 syntax There's no need to use obsoleted way. This commit fixes it. Fixes: 723bad3fef8b (ASoC: Intel: Add Broxton-P Dialog Maxim machine driver) Signed-off-by: Takashi Sakamoto Acked-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index bb4533c..6532b8f 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -302,7 +302,7 @@ static struct snd_soc_ops broxton_refcap_ops = { /* broxton digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link broxton_dais[] = { /* Front End DAI links */ - [BXT_DPCM_AUDIO_PB] + [BXT_DPCM_AUDIO_PB] = { .name = "Bxt Audio Port", .stream_name = "Audio", @@ -318,7 +318,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .dpcm_playback = 1, .ops = &broxton_da7219_fe_ops, }, - [BXT_DPCM_AUDIO_CP] + [BXT_DPCM_AUDIO_CP] = { .name = "Bxt Audio Capture Port", .stream_name = "Audio Record", @@ -333,7 +333,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .dpcm_capture = 1, .ops = &broxton_da7219_fe_ops, }, - [BXT_DPCM_AUDIO_REF_CP] + [BXT_DPCM_AUDIO_REF_CP] = { .name = "Bxt Audio Reference cap", .stream_name = "Refcap", @@ -362,7 +362,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .dynamic = 1, .ops = &broxton_dmic_ops, }, - [BXT_DPCM_AUDIO_HDMI1_PB] + [BXT_DPCM_AUDIO_HDMI1_PB] = { .name = "Bxt HDMI Port1", .stream_name = "Hdmi1", @@ -375,7 +375,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .nonatomic = 1, .dynamic = 1, }, - [BXT_DPCM_AUDIO_HDMI2_PB] + [BXT_DPCM_AUDIO_HDMI2_PB] = { .name = "Bxt HDMI Port2", .stream_name = "Hdmi2", @@ -388,7 +388,7 @@ static struct snd_soc_dai_link broxton_dais[] = { .nonatomic = 1, .dynamic = 1, }, - [BXT_DPCM_AUDIO_HDMI3_PB] + [BXT_DPCM_AUDIO_HDMI3_PB] = { .name = "Bxt HDMI Port3", .stream_name = "Hdmi3", -- cgit v0.10.2 From 5919a3898136aae4d2cb4b18b44f70f7b185aa47 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 27 Sep 2016 07:45:08 +0900 Subject: ASoC: sst-bxt-rt298: fix obsoleted initializers for array Sparse reports below warnings. bxt_rt298.c:275:9: warning: obsolete array initializer, use C99 syntax bxt_rt298.c:290:9: warning: obsolete array initializer, use C99 syntax bxt_rt298.c:304:9: warning: obsolete array initializer, use C99 syntax bxt_rt298.c:317:9: warning: obsolete array initializer, use C99 syntax bxt_rt298.c:331:9: warning: obsolete array initializer, use C99 syntax bxt_rt298.c:344:9: warning: obsolete array initializer, use C99 syntax bxt_rt298.c:357:9: warning: obsolete array initializer, use C99 syntax There's no need to use obsoleted way. This commit fixes it. Fixes: 76016322ec56 (ASoC: Intel: Add Broxton-P machine driver) Signed-off-by: Takashi Sakamoto Acked-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 253d7bf..d610bdc 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -271,7 +271,7 @@ static const struct snd_soc_ops broxton_rt286_fe_ops = { /* broxton digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link broxton_rt298_dais[] = { /* Front End DAI links */ - [BXT_DPCM_AUDIO_PB] + [BXT_DPCM_AUDIO_PB] = { .name = "Bxt Audio Port", .stream_name = "Audio", @@ -286,7 +286,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .dpcm_playback = 1, .ops = &broxton_rt286_fe_ops, }, - [BXT_DPCM_AUDIO_CP] + [BXT_DPCM_AUDIO_CP] = { .name = "Bxt Audio Capture Port", .stream_name = "Audio Record", @@ -300,7 +300,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .dpcm_capture = 1, .ops = &broxton_rt286_fe_ops, }, - [BXT_DPCM_AUDIO_REF_CP] + [BXT_DPCM_AUDIO_REF_CP] = { .name = "Bxt Audio Reference cap", .stream_name = "refcap", @@ -313,7 +313,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .nonatomic = 1, .dynamic = 1, }, - [BXT_DPCM_AUDIO_DMIC_CP] + [BXT_DPCM_AUDIO_DMIC_CP] = { .name = "Bxt Audio DMIC cap", .stream_name = "dmiccap", @@ -327,7 +327,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .dynamic = 1, .ops = &broxton_dmic_ops, }, - [BXT_DPCM_AUDIO_HDMI1_PB] + [BXT_DPCM_AUDIO_HDMI1_PB] = { .name = "Bxt HDMI Port1", .stream_name = "Hdmi1", @@ -340,7 +340,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .nonatomic = 1, .dynamic = 1, }, - [BXT_DPCM_AUDIO_HDMI2_PB] + [BXT_DPCM_AUDIO_HDMI2_PB] = { .name = "Bxt HDMI Port2", .stream_name = "Hdmi2", @@ -353,7 +353,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { .nonatomic = 1, .dynamic = 1, }, - [BXT_DPCM_AUDIO_HDMI3_PB] + [BXT_DPCM_AUDIO_HDMI3_PB] = { .name = "Bxt HDMI Port3", .stream_name = "Hdmi3", -- cgit v0.10.2 From 3cadd224474d60ee06cebafc63db9cd5f8cc47f7 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 27 Sep 2016 07:45:11 +0900 Subject: ASOC: tpa6130a2: add static qualifier for file local symbols Sparse reports a below warning. tpa6130a2.c:193:33: warning: symbol 'tpa6130a2_component_driver' was not declared. Should it be static? The symbol is just used inner the file. Forthermore, it's constant. Thus, it's better to add static and const qualifier. This commit adds it. Fixes: cb7e62256e99 (ASoC: tpa6130a2: Register component) Signed-off-by: Takashi Sakamoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 3712db0..2e014c8 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -199,7 +199,7 @@ static const struct snd_soc_dapm_route tpa6130a2_dapm_routes[] = { { "Right PGA", NULL, "Power" }, }; -struct snd_soc_component_driver tpa6130a2_component_driver = { +static const struct snd_soc_component_driver tpa6130a2_component_driver = { .name = "tpa6130a2", .probe = tpa6130a2_component_probe, .dapm_widgets = tpa6130a2_dapm_widgets, -- cgit v0.10.2 From 98695eab3c2de34265ac797b1c057215f8e78a1a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 27 Sep 2016 08:25:27 +0900 Subject: ASoC: wm8991: fix wrong usage of DECLARE_TLV_DB_LINEAR() As long as reading datasheet of WM8991, this driver includes wrong usage of DECLARE_TLV_DB_LINEAR(). In "Table 6 Input PGA Volume Range", volume is represented in 5 bits by 1.5 dB/step between -16.5/30.0 dB. Thus, 'in_pga_tlv' should be dB step representation. In "Table 34 LOMIX and ROMIX Volume Range", volume is represented in three bits by -3 dB/step from 0 to -21 dB. Thus, 'out_mix_tlv' should be dB step represenation. In "Table 36 LOPGA, ROPGA, LOUT, ROUT and SPKVOL Volume Range", volume is represented in 7 bits by 1 dB/step from -73 to 6 dB, including mute. Thus, 'out_pga_tlv' should be dB step representation. In "Table 26 Digital Volume Range", volume is represented in 8 bits by 3/8 dB/step from -71.625 to 0 dB. Thus, 'out_dac_tlv' should be dB step representation. In "Table 16 ADC Digital Volume Range", volume is represented in 8 bits by 3/8 dB/step from -71.625 to 17.625 dB. Thus, 'in_adc_tlv' should be dB step representation. In "Table 23 Digital Sidetone Volume", volume is represented in 5 bits by 3 dB/step from -36 to 0 dB. Thus, 'out_sidetone_tlv' should be dB step representation. In "Table 12 Left Input Mixer Volume Control", volume is represented in 3 bits by 3 dB/step from -12 to 6 dB Totally, current implementation includes misuse of TLV-related macro. This commit replaces usage of DECLARE_TLV_DB_LINEAR() with proper macros, to give proper information to applications in user land. Signed-off-by: Takashi Sakamoto Acked-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index c9ee0ac..483b953 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -112,13 +112,25 @@ static bool wm8991_volatile(struct device *dev, unsigned int reg) } static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); -static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000); -static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, 0, -2100); -static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(in_pga_tlv, -1650, 150, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(out_mix_tlv, -2100, 300, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(out_pga_tlv, + 0x00, 0x2f, SNDRV_CTL_TLVD_DB_SCALE_ITEM(SNDRV_CTL_TLVD_DB_GAIN_MUTE, 0, 1), + 0x30, 0x7f, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-7300, 100, 0), +); static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0); -static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0); -static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763); -static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(out_dac_tlv, + 0x00, 0xbf, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-71625, 375, 1), + 0xc0, 0xff, SNDRV_CTL_TLVD_DB_SCALE_ITEM(0, 0, 0), +); +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(in_adc_tlv, + 0x00, 0xef, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-71625, 375, 1), + 0xf0, 0xff, SNDRV_CTL_TLVD_DB_SCALE_ITEM(17625, 0, 0), +); +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(out_sidetone_tlv, + 0x00, 0x0c, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-3600, 300, 0), + 0x0d, 0x0f, SNDRV_CTL_TLVD_DB_SCALE_ITEM(0, 0, 0), +); static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -398,7 +410,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, } /* INMIX dB values */ -static const DECLARE_TLV_DB_LINEAR(in_mix_tlv, -1200, 600); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(in_mix_tlv, -1200, 300, 1); /* Left In PGA Connections */ static const struct snd_kcontrol_new wm8991_dapm_lin12_pga_controls[] = { -- cgit v0.10.2 From c7e9426a02699b9f0873e3c2bb383bcb1dd9ab19 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 27 Sep 2016 08:25:28 +0900 Subject: ASoC: wm8991: remove unused variable This driver has some unused variables. They should be removed. Signed-off-by: Takashi Sakamoto Acked-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 483b953..9d4b607 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -111,14 +111,12 @@ static bool wm8991_volatile(struct device *dev, unsigned int reg) } } -static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(in_pga_tlv, -1650, 150, 0); static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(out_mix_tlv, -2100, 300, 0); static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(out_pga_tlv, 0x00, 0x2f, SNDRV_CTL_TLVD_DB_SCALE_ITEM(SNDRV_CTL_TLVD_DB_GAIN_MUTE, 0, 1), 0x30, 0x7f, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-7300, 100, 0), ); -static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0); static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(out_dac_tlv, 0x00, 0xbf, SNDRV_CTL_TLVD_DB_SCALE_ITEM(-71625, 375, 1), 0xc0, 0xff, SNDRV_CTL_TLVD_DB_SCALE_ITEM(0, 0, 0), -- cgit v0.10.2 From f2b2f6dcd48adf81007b66e39bb7ca21d9bde250 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 27 Sep 2016 08:25:29 +0900 Subject: ASoC: stac9766: fix wrong usage of DECLARE_TLV_DB_LINEAR() As long as reading datasheet of STAC9766/9767, this driver includes wrong usage of DECLARE_TLV_DB_LINEAR(). In "8.1.2. Master Volume Registers", attenuation of lineout volumes is represented in 5 bits by -1.5 dB/step from 0 to -46.5 dB. Thus, 'master_tlv' should be dB step representation. In "8.1.14. Record Gain", gain of volumes is represented in 4 bits by 1.5 dB/step from 0 to 22.5 dB. Thus, 'record_tlv' should be dB step representation. In "8.1.5. PC BEEP Volume", attenuation of volume is represented in 4 bits by -3 dB/step from 0 to 45 dB. Thus, 'beep_tlv' should be dB step representation. In "8.1.7. Stereo or Mic Volume" and so on, gain of volumes is represented in 5 bits by -1.5 dB from 12 to -34.5 dB. Thus, 'mix_tlv' should be dB step representation. Totally, current implementation includes misuse of TLV-related macro. This commit replaces usage of DECLARE_TLV_DB_LINEAR() with SNDRV_CTL_TLVD_DECLARE_DB_SCALE(), to give proper information to applications in user land. Signed-off-by: Takashi Sakamoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 0945c51..a718c653 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -85,10 +85,10 @@ static SOC_ENUM_SINGLE_DECL(stac9766_boost2_enum, static SOC_ENUM_SINGLE_DECL(stac9766_stereo_mic_enum, AC97_STAC_STEREO_MIC, 2, stac9766_stereo_mic); -static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0); -static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250); -static const DECLARE_TLV_DB_LINEAR(beep_tlv, -4500, 0); -static const DECLARE_TLV_DB_LINEAR(mix_tlv, -3450, 1200); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(master_tlv, -4650, 150, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(record_tlv, 0, 150, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(beep_tlv, -4500, 300, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(mix_tlv, -3450, 150, 0); static const struct snd_kcontrol_new stac9766_snd_ac97_controls[] = { SOC_DOUBLE_TLV("Speaker Volume", AC97_MASTER, 8, 0, 31, 1, master_tlv), -- cgit v0.10.2 From 3520646dbb22832fa65dae6899d8cb068257d4aa Mon Sep 17 00:00:00 2001 From: Nikita Yushchenko Date: Tue, 27 Sep 2016 11:30:15 +0300 Subject: ASoC: tlv320aic31xx: do not declare support for mono DAI This hardware supports only 2-channel DAI, even mono ADC digital output has two channels with the same data. Having min_channels=1 results in broken playback of mono files in setups where CPU DAI supports mono. Signed-off-by: Nikita Yushchenko Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 725173b..be1a64b 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -1213,7 +1213,7 @@ static struct snd_soc_dai_driver dac31xx_dai_driver[] = { .name = "tlv32dac31xx-hifi", .playback = { .stream_name = "Playback", - .channels_min = 1, + .channels_min = 2, .channels_max = 2, .rates = AIC31XX_RATES, .formats = AIC31XX_FORMATS, @@ -1228,14 +1228,14 @@ static struct snd_soc_dai_driver aic31xx_dai_driver[] = { .name = "tlv320aic31xx-hifi", .playback = { .stream_name = "Playback", - .channels_min = 1, + .channels_min = 2, .channels_max = 2, .rates = AIC31XX_RATES, .formats = AIC31XX_FORMATS, }, .capture = { .stream_name = "Capture", - .channels_min = 1, + .channels_min = 2, .channels_max = 2, .rates = AIC31XX_RATES, .formats = AIC31XX_FORMATS, -- cgit v0.10.2 From a56a569818ea831ed2325dc5d1122dc0b8a229d0 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 27 Sep 2016 07:45:07 +0900 Subject: ASoC: da7219: fix inappropriate condition statement Sparse reports a below warning. sound/soc/codecs/da7219.c:804:57: warning: dubious: x & !y The line includes a condition statement; '(a < b) & !c'. Practically, the evaluated value of this statement equals to the value of '(a < b) && !c'. Although, it's not an usual way to use bitwise operations as logical operations to several conditions. This commit fixes the bug. Signed-off-by: Takashi Sakamoto Acked-by: Adam Thomson Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 65f7e98..3200762 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -801,7 +801,7 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w, ++i; msleep(50); } - } while ((i < DA7219_SRM_CHECK_RETRIES) & (!srm_lock)); + } while ((i < DA7219_SRM_CHECK_RETRIES) && (!srm_lock)); if (!srm_lock) dev_warn(codec->dev, "SRM failed to lock\n"); -- cgit v0.10.2 From 97b4bc76d9f7ab1fab375bc6d6143804a7bc2256 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 28 Sep 2016 12:24:10 +0200 Subject: ASoC: trivial: system spelling fix Do s/ststem/system/ . Signed-off-by: Marek Vasut Signed-off-by: Mark Brown diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig index b95ae49..d023959 100644 --- a/sound/soc/generic/Kconfig +++ b/sound/soc/generic/Kconfig @@ -13,4 +13,4 @@ config SND_SIMPLE_SCU_CARD select SND_SIMPLE_CARD_UTILS help This option enables generic simple SCU sound card support. - It supports DPCM of multi CPU single Codec ststem. + It supports DPCM of multi CPU single Codec system. -- cgit v0.10.2 From 349fa18c061a485a7928e9d3b998d464deaea8c4 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 28 Sep 2016 09:29:19 +0900 Subject: ASoC: max9867: remove usage of obsoleted TLV-related macro TLV_DB_RANGE_HEAD macro was obsoleted by commit bf1d1c9b6179 ("ALSA: tlv: add DECLARE_TLV_DB_RANGE()"). This commit removes usage of the macro, with the obsoleting macro renamed to SNDRV_CTL_TLVD_DECLARE_DB_RANGE(). Signed-off-by: Takashi Sakamoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 2a22fdd..1aa838f 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -38,11 +38,10 @@ static DECLARE_TLV_DB_SCALE(max9860_capture_tlv, -600, 200, 0); static DECLARE_TLV_DB_SCALE(max9860_mic_tlv, 2000, 100, 1); static DECLARE_TLV_DB_SCALE(max9860_adc_left_tlv, -1200, 100, 1); static DECLARE_TLV_DB_SCALE(max9860_adc_right_tlv, -1200, 100, 1); -static const unsigned int max98088_micboost_tlv[] = { - TLV_DB_RANGE_HEAD(2), +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(max98088_micboost_tlv, 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), -}; +); static const struct snd_kcontrol_new max9867_snd_controls[] = { SOC_DOUBLE_R("Master Playback Volume", MAX9867_LEFTVOL, -- cgit v0.10.2 From 51a576400ea46fec0df1672b373de91b00aa4a30 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 28 Sep 2016 09:29:20 +0900 Subject: ASoC: rt5616: remove usage of obsoleted TLV-related macro TLV_DB_RANGE_HEAD macro was obsoleted by commit bf1d1c9b6179 ("ALSA: tlv: add DECLARE_TLV_DB_RANGE()"). This commit removes usage of the macro, with the obsoleting macro renamed to SNDRV_CTL_TLVD_DECLARE_DB_RANGE(). Signed-off-by: Takashi Sakamoto Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index 98ae326..e643325 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -294,8 +294,7 @@ static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ -static unsigned int bst_tlv[] = { - TLV_DB_RANGE_HEAD(7), +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(bst_tlv, 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), @@ -303,7 +302,7 @@ static unsigned int bst_tlv[] = { 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), -}; +); static const struct snd_kcontrol_new rt5616_snd_controls[] = { /* Headphone Output Volume */ -- cgit v0.10.2 From b269cebf72d3591cd889a25f81ead43166a45fb9 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Wed, 28 Sep 2016 09:29:21 +0900 Subject: ASoC: wm8960: remove usage of obsoleted TLV-related macro TLV_DB_RANGE_HEAD macro was obsoleted by commit bf1d1c9b6179 ("ALSA: tlv: add DECLARE_TLV_DB_RANGE()"). This commit removes usage of the macro, with the obsoleting macro renamed to SNDRV_CTL_TLVD_DECLARE_DB_RANGE(). Signed-off-by: Takashi Sakamoto Acked-by: Charles Keepax Signed-off-by: Mark Brown diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index d7f444f..3d8c756 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -226,11 +226,10 @@ static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0); static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); static const DECLARE_TLV_DB_SCALE(lineinboost_tlv, -1500, 300, 1); -static const unsigned int micboost_tlv[] = { - TLV_DB_RANGE_HEAD(2), +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(micboost_tlv, 0, 1, TLV_DB_SCALE_ITEM(0, 1300, 0), 2, 3, TLV_DB_SCALE_ITEM(2000, 900, 0), -}; +); static const struct snd_kcontrol_new wm8960_snd_controls[] = { SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL, -- cgit v0.10.2 From 4b9c75eaa4f35504c3ee28d3a354f7b6362dfbe8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 29 Sep 2016 03:09:22 +0000 Subject: ASoC: rsnd: add SNDRV_PCM_TRIGGER_SUSPEND/RESUME This patch adds SNDRV_PCM_TRIGGER_SUSPEND/RESUME. Otherwise, it breaks rsnd driver internal start/stop counter when suspend/resume. This issue was reported/tested by Hiep Tested-by: Hiep Cao Minh Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index f718a20..f181410 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -576,6 +576,7 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, switch (cmd) { case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: rsnd_dai_stream_init(io, substream); ret = rsnd_dai_call(init, io, priv); @@ -592,6 +593,7 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, break; case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: ret = rsnd_dai_call(irq, io, priv, 0); ret |= rsnd_dai_call(stop, io, priv); -- cgit v0.10.2 From 0730bd2e2ade00d88647b13a0c17cde254ddf56e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 29 Sep 2016 18:32:12 +0100 Subject: ASoC: Intel: Skylake: fix memory leak of module on error exit path Currently there is a memory leak of module on a ENOMEM return path. Fix this by kfree'ing module before returning. Signed-off-by: Colin Ian King Signed-off-by: Mark Brown diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index 1aa0f37..3fe939c 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -349,8 +349,10 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, module->max_instance = mod_entry->instance_max_count; size = sizeof(int) * mod_entry->instance_max_count; module->instance_id = devm_kzalloc(ctx->dev, size, GFP_KERNEL); - if (!module->instance_id) + if (!module->instance_id) { + kfree(module); return -ENOMEM; + } list_add_tail(&module->list, &skl->uuid_list); -- cgit v0.10.2 From f26b3b2a87680b4be2a6b144929a9dd9c080c81c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 29 Sep 2016 11:22:52 -0700 Subject: ASoC: fsl: Fix lockups with recent cache changes The recent series of changes to the caching in the SSI driver have caused a number of problems to appear in some test systems. These are still not fully understood but we're coming up to the merge window so for now let's revert commit 7de2763d9b3 (ASoC: fsl_ssi: Remove .num_reg_defaults_raw from regmap_config) as backing that out seems to resolve the problem on affected systems. Reported-by: Maciej S. Szmigiero" Signed-off-by: Mark Brown Reviewed-by: Marek Vasut diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index b73c102..5034943 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -177,6 +177,7 @@ static const struct regmap_config fsl_ssi_regconfig = { .val_bits = 32, .reg_stride = 4, .val_format_endian = REGMAP_ENDIAN_NATIVE, + .num_reg_defaults_raw = CCSR_SSI_SACCDIS / sizeof(uint32_t) + 1, .readable_reg = fsl_ssi_readable_reg, .volatile_reg = fsl_ssi_volatile_reg, .precious_reg = fsl_ssi_precious_reg, @@ -1500,6 +1501,8 @@ static int fsl_ssi_probe(struct platform_device *pdev) * don't have SACC{ST,EN,DIS} regs. */ regconfig.max_register = CCSR_SSI_SRMSK; + regconfig.num_reg_defaults_raw = + CCSR_SSI_SRMSK / sizeof(uint32_t) + 1; } ret = of_property_match_string(np, "clock-names", "ipg"); -- cgit v0.10.2