diff options
-rw-r--r-- | sound/soc/codecs/arizona.c | 159 | ||||
-rw-r--r-- | sound/soc/codecs/arizona.h | 15 | ||||
-rw-r--r-- | sound/soc/codecs/wm5110.c | 136 | ||||
-rw-r--r-- | sound/soc/codecs/wm8998.c | 46 | ||||
-rw-r--r-- | sound/soc/codecs/wm_adsp.c | 189 | ||||
-rw-r--r-- | sound/soc/codecs/wm_adsp.h | 7 |
6 files changed, 428 insertions, 124 deletions
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 9929efc..38a73e3 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -310,7 +310,7 @@ int arizona_init_gpio(struct snd_soc_codec *codec) } EXPORT_SYMBOL_GPL(arizona_init_gpio); -const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { +const char * const arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { "None", "Tone Generator 1", "Tone Generator 2", @@ -418,7 +418,7 @@ const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { }; EXPORT_SYMBOL_GPL(arizona_mixer_texts); -int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = { +unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = { 0x00, /* None */ 0x04, /* Tone */ 0x05, @@ -555,12 +555,12 @@ const char *arizona_sample_rate_val_to_name(unsigned int rate_val) } EXPORT_SYMBOL_GPL(arizona_sample_rate_val_to_name); -const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = { +const char * const arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = { "SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate", }; EXPORT_SYMBOL_GPL(arizona_rate_text); -const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = { +const unsigned int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = { 0, 1, 2, 8, }; EXPORT_SYMBOL_GPL(arizona_rate_val); @@ -702,6 +702,100 @@ const struct soc_enum arizona_in_dmic_osr[] = { }; EXPORT_SYMBOL_GPL(arizona_in_dmic_osr); +static const char * const arizona_anc_input_src_text[] = { + "None", "IN1", "IN2", "IN3", "IN4", +}; + +static const char * const arizona_anc_channel_src_text[] = { + "None", "Left", "Right", "Combine", +}; + +const struct soc_enum arizona_anc_input_src[] = { + SOC_ENUM_SINGLE(ARIZONA_ANC_SRC, + ARIZONA_IN_RXANCL_SEL_SHIFT, + ARRAY_SIZE(arizona_anc_input_src_text), + arizona_anc_input_src_text), + SOC_ENUM_SINGLE(ARIZONA_FCL_ADC_REFORMATTER_CONTROL, + ARIZONA_FCL_MIC_MODE_SEL, + ARRAY_SIZE(arizona_anc_channel_src_text), + arizona_anc_channel_src_text), + SOC_ENUM_SINGLE(ARIZONA_ANC_SRC, + ARIZONA_IN_RXANCR_SEL_SHIFT, + ARRAY_SIZE(arizona_anc_input_src_text), + arizona_anc_input_src_text), + SOC_ENUM_SINGLE(ARIZONA_FCR_ADC_REFORMATTER_CONTROL, + ARIZONA_FCR_MIC_MODE_SEL, + ARRAY_SIZE(arizona_anc_channel_src_text), + arizona_anc_channel_src_text), +}; +EXPORT_SYMBOL_GPL(arizona_anc_input_src); + +static const char * const arizona_anc_ng_texts[] = { + "None", + "Internal", + "External", +}; + +SOC_ENUM_SINGLE_DECL(arizona_anc_ng_enum, SND_SOC_NOPM, 0, + arizona_anc_ng_texts); +EXPORT_SYMBOL_GPL(arizona_anc_ng_enum); + +static const char * const arizona_output_anc_src_text[] = { + "None", "RXANCL", "RXANCR", +}; + +const struct soc_enum arizona_output_anc_src[] = { + SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, + ARIZONA_OUT1L_ANC_SRC_SHIFT, + ARRAY_SIZE(arizona_output_anc_src_text), + arizona_output_anc_src_text), + SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1R, + ARIZONA_OUT1R_ANC_SRC_SHIFT, + ARRAY_SIZE(arizona_output_anc_src_text), + arizona_output_anc_src_text), + SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L, + ARIZONA_OUT2L_ANC_SRC_SHIFT, + ARRAY_SIZE(arizona_output_anc_src_text), + arizona_output_anc_src_text), + SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2R, + ARIZONA_OUT2R_ANC_SRC_SHIFT, + ARRAY_SIZE(arizona_output_anc_src_text), + arizona_output_anc_src_text), + SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, + ARIZONA_OUT3L_ANC_SRC_SHIFT, + ARRAY_SIZE(arizona_output_anc_src_text), + arizona_output_anc_src_text), + SOC_ENUM_SINGLE(ARIZONA_DAC_VOLUME_LIMIT_3R, + ARIZONA_OUT3R_ANC_SRC_SHIFT, + ARRAY_SIZE(arizona_output_anc_src_text), + arizona_output_anc_src_text), + SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_4L, + ARIZONA_OUT4L_ANC_SRC_SHIFT, + ARRAY_SIZE(arizona_output_anc_src_text), + arizona_output_anc_src_text), + SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_4R, + ARIZONA_OUT4R_ANC_SRC_SHIFT, + ARRAY_SIZE(arizona_output_anc_src_text), + arizona_output_anc_src_text), + SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_5L, + ARIZONA_OUT5L_ANC_SRC_SHIFT, + ARRAY_SIZE(arizona_output_anc_src_text), + arizona_output_anc_src_text), + SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_5R, + ARIZONA_OUT5R_ANC_SRC_SHIFT, + ARRAY_SIZE(arizona_output_anc_src_text), + arizona_output_anc_src_text), + SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_6L, + ARIZONA_OUT6L_ANC_SRC_SHIFT, + ARRAY_SIZE(arizona_output_anc_src_text), + arizona_output_anc_src_text), + SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_6R, + ARIZONA_OUT6R_ANC_SRC_SHIFT, + ARRAY_SIZE(arizona_output_anc_src_text), + arizona_output_anc_src_text), +}; +EXPORT_SYMBOL_GPL(arizona_output_anc_src); + static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena) { struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); @@ -1023,24 +1117,43 @@ void arizona_init_dvfs(struct arizona_priv *priv) } EXPORT_SYMBOL_GPL(arizona_init_dvfs); -static unsigned int arizona_sysclk_48k_rates[] = { +int arizona_anc_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + unsigned int mask = 0x3 << w->shift; + unsigned int val; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + val = 1 << w->shift; + break; + case SND_SOC_DAPM_PRE_PMD: + val = 1 << (w->shift + 1); + break; + default: + return 0; + } + + snd_soc_update_bits(codec, ARIZONA_CLOCK_CONTROL, mask, val); + + return 0; +} +EXPORT_SYMBOL_GPL(arizona_anc_ev); + +static unsigned int arizona_opclk_ref_48k_rates[] = { 6144000, 12288000, 24576000, 49152000, - 73728000, - 98304000, - 147456000, }; -static unsigned int arizona_sysclk_44k1_rates[] = { +static unsigned int arizona_opclk_ref_44k1_rates[] = { 5644800, 11289600, 22579200, 45158400, - 67737600, - 90316800, - 135475200, }; static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk, @@ -1065,11 +1178,11 @@ static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk, } if (refclk % 8000) - rates = arizona_sysclk_44k1_rates; + rates = arizona_opclk_ref_44k1_rates; else - rates = arizona_sysclk_48k_rates; + rates = arizona_opclk_ref_48k_rates; - for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) && + for (ref = 0; ref < ARRAY_SIZE(arizona_opclk_ref_48k_rates) && rates[ref] <= refclk; ref++) { div = 1; while (rates[ref] / div >= freq && div < 32) { @@ -1101,7 +1214,7 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, unsigned int reg; unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK; unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT; - unsigned int *clk; + int *clk; switch (clk_id) { case ARIZONA_CLK_SYSCLK: @@ -1907,18 +2020,18 @@ static int arizona_calc_fratio(struct arizona_fll *fll, } switch (fll->arizona->type) { + case WM5102: + case WM8997: + return init_ratio; case WM5110: case WM8280: if (fll->arizona->rev < 3 || sync) return init_ratio; break; - case WM8998: - case WM1814: + default: if (sync) return init_ratio; break; - default: - return init_ratio; } cfg->fratio = init_ratio - 1; @@ -2099,9 +2212,9 @@ static int arizona_enable_fll(struct arizona_fll *fll) /* Facilitate smooth refclk across the transition */ regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9, ARIZONA_FLL1_GAIN_MASK, 0); - regmap_update_bits_async(fll->arizona->regmap, fll->base + 1, - ARIZONA_FLL1_FREERUN, - ARIZONA_FLL1_FREERUN); + regmap_update_bits(fll->arizona->regmap, fll->base + 1, + ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN); + udelay(32); } /* diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index fea8b8a..b4f1867 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -96,8 +96,8 @@ struct arizona_priv { #define ARIZONA_NUM_MIXER_INPUTS 104 extern const unsigned int arizona_mixer_tlv[]; -extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; -extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; +extern const char * const arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; +extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; #define ARIZONA_GAINMUX_CONTROLS(name, base) \ SOC_SINGLE_RANGE_TLV(name " Input Volume", base + 1, \ @@ -216,8 +216,8 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; #define ARIZONA_RATE_ENUM_SIZE 4 #define ARIZONA_SAMPLE_RATE_ENUM_SIZE 14 -extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE]; -extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE]; +extern const char * const arizona_rate_text[ARIZONA_RATE_ENUM_SIZE]; +extern const unsigned int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE]; extern const char * const arizona_sample_rate_text[ARIZONA_SAMPLE_RATE_ENUM_SIZE]; extern const unsigned int arizona_sample_rate_val[ARIZONA_SAMPLE_RATE_ENUM_SIZE]; @@ -242,6 +242,10 @@ extern const struct soc_enum arizona_in_dmic_osr[]; extern const struct snd_kcontrol_new arizona_adsp2_rate_controls[]; +extern const struct soc_enum arizona_anc_input_src[]; +extern const struct soc_enum arizona_anc_ng_enum; +extern const struct soc_enum arizona_output_anc_src[]; + extern int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); @@ -251,6 +255,9 @@ extern int arizona_out_ev(struct snd_soc_dapm_widget *w, extern int arizona_hp_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); +extern int arizona_anc_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event); extern int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index c04c0bc..e93e542 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -575,6 +575,33 @@ static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); SOC_SINGLE(name " NG SPKDAT2L Switch", base, 10, 1, 0), \ SOC_SINGLE(name " NG SPKDAT2R Switch", base, 11, 1, 0) +#define WM5110_RXANC_INPUT_ROUTES(widget, name) \ + { widget, NULL, name " NG Mux" }, \ + { name " NG Internal", NULL, "RXANC NG Clock" }, \ + { name " NG Internal", NULL, name " Channel" }, \ + { name " NG External", NULL, "RXANC NG External Clock" }, \ + { name " NG External", NULL, name " Channel" }, \ + { name " NG Mux", "None", name " Channel" }, \ + { name " NG Mux", "Internal", name " NG Internal" }, \ + { name " NG Mux", "External", name " NG External" }, \ + { name " Channel", "Left", name " Left Input" }, \ + { name " Channel", "Combine", name " Left Input" }, \ + { name " Channel", "Right", name " Right Input" }, \ + { name " Channel", "Combine", name " Right Input" }, \ + { name " Left Input", "IN1", "IN1L PGA" }, \ + { name " Right Input", "IN1", "IN1R PGA" }, \ + { name " Left Input", "IN2", "IN2L PGA" }, \ + { name " Right Input", "IN2", "IN2R PGA" }, \ + { name " Left Input", "IN3", "IN3L PGA" }, \ + { name " Right Input", "IN3", "IN3R PGA" }, \ + { name " Left Input", "IN4", "IN4L PGA" }, \ + { name " Right Input", "IN4", "IN4R PGA" } + +#define WM5110_RXANC_OUTPUT_ROUTES(widget, name) \ + { widget, NULL, name " ANC Source" }, \ + { name " ANC Source", "RXANCL", "RXANCL" }, \ + { name " ANC Source", "RXANCR", "RXANCR" } + static const struct snd_kcontrol_new wm5110_snd_controls[] = { SOC_ENUM("IN1 OSR", arizona_in_dmic_osr[0]), SOC_ENUM("IN2 OSR", arizona_in_dmic_osr[1]), @@ -639,6 +666,15 @@ SOC_SINGLE_TLV("IN4R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4R, SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp), SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp), +SND_SOC_BYTES("RXANC Coefficients", ARIZONA_ANC_COEFF_START, + ARIZONA_ANC_COEFF_END - ARIZONA_ANC_COEFF_START + 1), +SND_SOC_BYTES("RXANCL Config", ARIZONA_FCL_FILTER_CONTROL, 1), +SND_SOC_BYTES("RXANCL Coefficients", ARIZONA_FCL_COEFF_START, + ARIZONA_FCL_COEFF_END - ARIZONA_FCL_COEFF_START + 1), +SND_SOC_BYTES("RXANCR Config", ARIZONA_FCR_FILTER_CONTROL, 1), +SND_SOC_BYTES("RXANCR Coefficients", ARIZONA_FCR_COEFF_START, + ARIZONA_FCR_COEFF_END - ARIZONA_FCR_COEFF_START + 1), + ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), @@ -995,6 +1031,31 @@ static const struct soc_enum wm5110_aec_loopback = static const struct snd_kcontrol_new wm5110_aec_loopback_mux = SOC_DAPM_ENUM("AEC Loopback", wm5110_aec_loopback); +static const struct snd_kcontrol_new wm5110_anc_input_mux[] = { + SOC_DAPM_ENUM("RXANCL Input", arizona_anc_input_src[0]), + SOC_DAPM_ENUM("RXANCL Channel", arizona_anc_input_src[1]), + SOC_DAPM_ENUM("RXANCR Input", arizona_anc_input_src[2]), + SOC_DAPM_ENUM("RXANCR Channel", arizona_anc_input_src[3]), +}; + +static const struct snd_kcontrol_new wm5110_anc_ng_mux = + SOC_DAPM_ENUM("RXANC NG Source", arizona_anc_ng_enum); + +static const struct snd_kcontrol_new wm5110_output_anc_src[] = { + SOC_DAPM_ENUM("HPOUT1L ANC Source", arizona_output_anc_src[0]), + SOC_DAPM_ENUM("HPOUT1R ANC Source", arizona_output_anc_src[1]), + SOC_DAPM_ENUM("HPOUT2L ANC Source", arizona_output_anc_src[2]), + SOC_DAPM_ENUM("HPOUT2R ANC Source", arizona_output_anc_src[3]), + SOC_DAPM_ENUM("HPOUT3L ANC Source", arizona_output_anc_src[4]), + SOC_DAPM_ENUM("HPOUT3R ANC Source", arizona_output_anc_src[5]), + SOC_DAPM_ENUM("SPKOUTL ANC Source", arizona_output_anc_src[6]), + SOC_DAPM_ENUM("SPKOUTR ANC Source", arizona_output_anc_src[7]), + SOC_DAPM_ENUM("SPKDAT1L ANC Source", arizona_output_anc_src[8]), + SOC_DAPM_ENUM("SPKDAT1R ANC Source", arizona_output_anc_src[9]), + SOC_DAPM_ENUM("SPKDAT2L ANC Source", arizona_output_anc_src[10]), + SOC_DAPM_ENUM("SPKDAT2R ANC Source", arizona_output_anc_src[11]), +}; + static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, 0, wm5110_sysclk_ev, SND_SOC_DAPM_POST_PMU), @@ -1185,6 +1246,65 @@ SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0, &wm5110_aec_loopback_mux), +SND_SOC_DAPM_SUPPLY("RXANC NG External Clock", SND_SOC_NOPM, + ARIZONA_EXT_NG_SEL_SET_SHIFT, 0, arizona_anc_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_PGA("RXANCL NG External", SND_SOC_NOPM, 0, 0, NULL, 0), +SND_SOC_DAPM_PGA("RXANCR NG External", SND_SOC_NOPM, 0, 0, NULL, 0), + +SND_SOC_DAPM_SUPPLY("RXANC NG Clock", SND_SOC_NOPM, + ARIZONA_CLK_NG_ENA_SET_SHIFT, 0, arizona_anc_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_PGA("RXANCL NG Internal", SND_SOC_NOPM, 0, 0, NULL, 0), +SND_SOC_DAPM_PGA("RXANCR NG Internal", SND_SOC_NOPM, 0, 0, NULL, 0), + +SND_SOC_DAPM_MUX("RXANCL Left Input", SND_SOC_NOPM, 0, 0, + &wm5110_anc_input_mux[0]), +SND_SOC_DAPM_MUX("RXANCL Right Input", SND_SOC_NOPM, 0, 0, + &wm5110_anc_input_mux[0]), +SND_SOC_DAPM_MUX("RXANCL Channel", SND_SOC_NOPM, 0, 0, + &wm5110_anc_input_mux[1]), +SND_SOC_DAPM_MUX("RXANCL NG Mux", SND_SOC_NOPM, 0, 0, &wm5110_anc_ng_mux), +SND_SOC_DAPM_MUX("RXANCR Left Input", SND_SOC_NOPM, 0, 0, + &wm5110_anc_input_mux[2]), +SND_SOC_DAPM_MUX("RXANCR Right Input", SND_SOC_NOPM, 0, 0, + &wm5110_anc_input_mux[2]), +SND_SOC_DAPM_MUX("RXANCR Channel", SND_SOC_NOPM, 0, 0, + &wm5110_anc_input_mux[3]), +SND_SOC_DAPM_MUX("RXANCR NG Mux", SND_SOC_NOPM, 0, 0, &wm5110_anc_ng_mux), + +SND_SOC_DAPM_PGA_E("RXANCL", SND_SOC_NOPM, ARIZONA_CLK_L_ENA_SET_SHIFT, + 0, NULL, 0, arizona_anc_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +SND_SOC_DAPM_PGA_E("RXANCR", SND_SOC_NOPM, ARIZONA_CLK_R_ENA_SET_SHIFT, + 0, NULL, 0, arizona_anc_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + +SND_SOC_DAPM_MUX("HPOUT1L ANC Source", SND_SOC_NOPM, 0, 0, + &wm5110_output_anc_src[0]), +SND_SOC_DAPM_MUX("HPOUT1R ANC Source", SND_SOC_NOPM, 0, 0, + &wm5110_output_anc_src[1]), +SND_SOC_DAPM_MUX("HPOUT2L ANC Source", SND_SOC_NOPM, 0, 0, + &wm5110_output_anc_src[2]), +SND_SOC_DAPM_MUX("HPOUT2R ANC Source", SND_SOC_NOPM, 0, 0, + &wm5110_output_anc_src[3]), +SND_SOC_DAPM_MUX("HPOUT3L ANC Source", SND_SOC_NOPM, 0, 0, + &wm5110_output_anc_src[4]), +SND_SOC_DAPM_MUX("HPOUT3R ANC Source", SND_SOC_NOPM, 0, 0, + &wm5110_output_anc_src[5]), +SND_SOC_DAPM_MUX("SPKOUTL ANC Source", SND_SOC_NOPM, 0, 0, + &wm5110_output_anc_src[6]), +SND_SOC_DAPM_MUX("SPKOUTR ANC Source", SND_SOC_NOPM, 0, 0, + &wm5110_output_anc_src[7]), +SND_SOC_DAPM_MUX("SPKDAT1L ANC Source", SND_SOC_NOPM, 0, 0, + &wm5110_output_anc_src[8]), +SND_SOC_DAPM_MUX("SPKDAT1R ANC Source", SND_SOC_NOPM, 0, 0, + &wm5110_output_anc_src[9]), +SND_SOC_DAPM_MUX("SPKDAT2L ANC Source", SND_SOC_NOPM, 0, 0, + &wm5110_output_anc_src[10]), +SND_SOC_DAPM_MUX("SPKDAT2R ANC Source", SND_SOC_NOPM, 0, 0, + &wm5110_output_anc_src[11]), + SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, @@ -1838,6 +1958,22 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { { "SPKDAT2L", NULL, "OUT6L" }, { "SPKDAT2R", NULL, "OUT6R" }, + WM5110_RXANC_INPUT_ROUTES("RXANCL", "RXANCL"), + WM5110_RXANC_INPUT_ROUTES("RXANCR", "RXANCR"), + + WM5110_RXANC_OUTPUT_ROUTES("OUT1L", "HPOUT1L"), + WM5110_RXANC_OUTPUT_ROUTES("OUT1R", "HPOUT1R"), + WM5110_RXANC_OUTPUT_ROUTES("OUT2L", "HPOUT2L"), + WM5110_RXANC_OUTPUT_ROUTES("OUT2R", "HPOUT2R"), + WM5110_RXANC_OUTPUT_ROUTES("OUT3L", "HPOUT3L"), + WM5110_RXANC_OUTPUT_ROUTES("OUT3R", "HPOUT3R"), + WM5110_RXANC_OUTPUT_ROUTES("OUT4L", "SPKOUTL"), + WM5110_RXANC_OUTPUT_ROUTES("OUT4R", "SPKOUTR"), + WM5110_RXANC_OUTPUT_ROUTES("OUT5L", "SPKDAT1L"), + WM5110_RXANC_OUTPUT_ROUTES("OUT5R", "SPKDAT1R"), + WM5110_RXANC_OUTPUT_ROUTES("OUT6L", "SPKDAT2L"), + WM5110_RXANC_OUTPUT_ROUTES("OUT6R", "SPKDAT2R"), + { "MICSUPP", NULL, "SYSCLK" }, { "DRC1 Signal Activity", NULL, "DRC1L" }, diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 8782dfb..7719bc5 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -199,20 +199,20 @@ static const char * const wm8998_inmux_texts[] = { "B", }; -static const SOC_ENUM_SINGLE_DECL(wm8998_in1muxl_enum, - ARIZONA_ADC_DIGITAL_VOLUME_1L, - ARIZONA_IN1L_SRC_SHIFT, - wm8998_inmux_texts); +static SOC_ENUM_SINGLE_DECL(wm8998_in1muxl_enum, + ARIZONA_ADC_DIGITAL_VOLUME_1L, + ARIZONA_IN1L_SRC_SHIFT, + wm8998_inmux_texts); -static const SOC_ENUM_SINGLE_DECL(wm8998_in1muxr_enum, - ARIZONA_ADC_DIGITAL_VOLUME_1R, - ARIZONA_IN1R_SRC_SHIFT, - wm8998_inmux_texts); +static SOC_ENUM_SINGLE_DECL(wm8998_in1muxr_enum, + ARIZONA_ADC_DIGITAL_VOLUME_1R, + ARIZONA_IN1R_SRC_SHIFT, + wm8998_inmux_texts); -static const SOC_ENUM_SINGLE_DECL(wm8998_in2mux_enum, - ARIZONA_ADC_DIGITAL_VOLUME_2L, - ARIZONA_IN2L_SRC_SHIFT, - wm8998_inmux_texts); +static SOC_ENUM_SINGLE_DECL(wm8998_in2mux_enum, + ARIZONA_ADC_DIGITAL_VOLUME_2L, + ARIZONA_IN2L_SRC_SHIFT, + wm8998_inmux_texts); static const struct snd_kcontrol_new wm8998_in1mux[2] = { SOC_DAPM_ENUM_EXT("IN1L Mux", wm8998_in1muxl_enum, @@ -522,17 +522,17 @@ static const unsigned int wm8998_aec_loopback_values[] = { 0, 1, 2, 3, 4, 6, 7, 8, 9, }; -static const SOC_VALUE_ENUM_SINGLE_DECL(wm8998_aec1_loopback, - ARIZONA_DAC_AEC_CONTROL_1, - ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, - wm8998_aec_loopback_texts, - wm8998_aec_loopback_values); - -static const SOC_VALUE_ENUM_SINGLE_DECL(wm8998_aec2_loopback, - ARIZONA_DAC_AEC_CONTROL_2, - ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, - wm8998_aec_loopback_texts, - wm8998_aec_loopback_values); +static SOC_VALUE_ENUM_SINGLE_DECL(wm8998_aec1_loopback, + ARIZONA_DAC_AEC_CONTROL_1, + ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, + wm8998_aec_loopback_texts, + wm8998_aec_loopback_values); + +static SOC_VALUE_ENUM_SINGLE_DECL(wm8998_aec2_loopback, + ARIZONA_DAC_AEC_CONTROL_2, + ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, + wm8998_aec_loopback_texts, + wm8998_aec_loopback_values); static const struct snd_kcontrol_new wm8998_aec_loopback_mux[] = { SOC_DAPM_ENUM("AEC1 Loopback", wm8998_aec1_loopback), diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 0bb415a..d1e0826 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -201,27 +201,48 @@ static void wm_adsp_buf_free(struct list_head *list) } } -#define WM_ADSP_NUM_FW 4 - -#define WM_ADSP_FW_MBC_VSS 0 -#define WM_ADSP_FW_TX 1 -#define WM_ADSP_FW_TX_SPK 2 -#define WM_ADSP_FW_RX_ANC 3 +#define WM_ADSP_FW_MBC_VSS 0 +#define WM_ADSP_FW_HIFI 1 +#define WM_ADSP_FW_TX 2 +#define WM_ADSP_FW_TX_SPK 3 +#define WM_ADSP_FW_RX 4 +#define WM_ADSP_FW_RX_ANC 5 +#define WM_ADSP_FW_CTRL 6 +#define WM_ADSP_FW_ASR 7 +#define WM_ADSP_FW_TRACE 8 +#define WM_ADSP_FW_SPK_PROT 9 +#define WM_ADSP_FW_MISC 10 + +#define WM_ADSP_NUM_FW 11 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = { - [WM_ADSP_FW_MBC_VSS] = "MBC/VSS", - [WM_ADSP_FW_TX] = "Tx", - [WM_ADSP_FW_TX_SPK] = "Tx Speaker", - [WM_ADSP_FW_RX_ANC] = "Rx ANC", + [WM_ADSP_FW_MBC_VSS] = "MBC/VSS", + [WM_ADSP_FW_HIFI] = "MasterHiFi", + [WM_ADSP_FW_TX] = "Tx", + [WM_ADSP_FW_TX_SPK] = "Tx Speaker", + [WM_ADSP_FW_RX] = "Rx", + [WM_ADSP_FW_RX_ANC] = "Rx ANC", + [WM_ADSP_FW_CTRL] = "Voice Ctrl", + [WM_ADSP_FW_ASR] = "ASR Assist", + [WM_ADSP_FW_TRACE] = "Dbg Trace", + [WM_ADSP_FW_SPK_PROT] = "Protection", + [WM_ADSP_FW_MISC] = "Misc", }; static struct { const char *file; } wm_adsp_fw[WM_ADSP_NUM_FW] = { - [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" }, - [WM_ADSP_FW_TX] = { .file = "tx" }, - [WM_ADSP_FW_TX_SPK] = { .file = "tx-spk" }, - [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" }, + [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" }, + [WM_ADSP_FW_HIFI] = { .file = "hifi" }, + [WM_ADSP_FW_TX] = { .file = "tx" }, + [WM_ADSP_FW_TX_SPK] = { .file = "tx-spk" }, + [WM_ADSP_FW_RX] = { .file = "rx" }, + [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" }, + [WM_ADSP_FW_CTRL] = { .file = "ctrl" }, + [WM_ADSP_FW_ASR] = { .file = "asr" }, + [WM_ADSP_FW_TRACE] = { .file = "trace" }, + [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" }, + [WM_ADSP_FW_MISC] = { .file = "misc" }, }; struct wm_coeff_ctl_ops { @@ -254,30 +275,24 @@ static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s) { char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); - mutex_lock(&dsp->debugfs_lock); kfree(dsp->wmfw_file_name); dsp->wmfw_file_name = tmp; - mutex_unlock(&dsp->debugfs_lock); } static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s) { char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); - mutex_lock(&dsp->debugfs_lock); kfree(dsp->bin_file_name); dsp->bin_file_name = tmp; - mutex_unlock(&dsp->debugfs_lock); } static void wm_adsp_debugfs_clear(struct wm_adsp *dsp) { - mutex_lock(&dsp->debugfs_lock); kfree(dsp->wmfw_file_name); kfree(dsp->bin_file_name); dsp->wmfw_file_name = NULL; dsp->bin_file_name = NULL; - mutex_unlock(&dsp->debugfs_lock); } static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file, @@ -287,7 +302,7 @@ static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file, struct wm_adsp *dsp = file->private_data; ssize_t ret; - mutex_lock(&dsp->debugfs_lock); + mutex_lock(&dsp->pwr_lock); if (!dsp->wmfw_file_name || !dsp->running) ret = 0; @@ -296,7 +311,7 @@ static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file, dsp->wmfw_file_name, strlen(dsp->wmfw_file_name)); - mutex_unlock(&dsp->debugfs_lock); + mutex_unlock(&dsp->pwr_lock); return ret; } @@ -307,7 +322,7 @@ static ssize_t wm_adsp_debugfs_bin_read(struct file *file, struct wm_adsp *dsp = file->private_data; ssize_t ret; - mutex_lock(&dsp->debugfs_lock); + mutex_lock(&dsp->pwr_lock); if (!dsp->bin_file_name || !dsp->running) ret = 0; @@ -316,7 +331,7 @@ static ssize_t wm_adsp_debugfs_bin_read(struct file *file, dsp->bin_file_name, strlen(dsp->bin_file_name)); - mutex_unlock(&dsp->debugfs_lock); + mutex_unlock(&dsp->pwr_lock); return ret; } @@ -436,6 +451,7 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec); + int ret = 0; if (ucontrol->value.integer.value[0] == dsp[e->shift_l].fw) return 0; @@ -443,12 +459,16 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW) return -EINVAL; + mutex_lock(&dsp[e->shift_l].pwr_lock); + if (dsp[e->shift_l].running) - return -EBUSY; + ret = -EBUSY; + else + dsp[e->shift_l].fw = ucontrol->value.integer.value[0]; - dsp[e->shift_l].fw = ucontrol->value.integer.value[0]; + mutex_unlock(&dsp[e->shift_l].pwr_lock); - return 0; + return ret; } static const struct soc_enum wm_adsp_fw_enum[] = { @@ -523,10 +543,10 @@ static void wm_adsp2_show_fw_status(struct wm_adsp *dsp) be16_to_cpu(scratch[3])); } -static int wm_coeff_info(struct snd_kcontrol *kcontrol, +static int wm_coeff_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) { - struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; + struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kctl->private_value; uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; uinfo->count = ctl->len; @@ -572,19 +592,24 @@ static int wm_coeff_write_control(struct wm_coeff_ctl *ctl, return 0; } -static int wm_coeff_put(struct snd_kcontrol *kcontrol, +static int wm_coeff_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { - struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; + struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kctl->private_value; char *p = ucontrol->value.bytes.data; + int ret = 0; + + mutex_lock(&ctl->dsp->pwr_lock); memcpy(ctl->cache, p, ctl->len); ctl->set = 1; - if (!ctl->enabled) - return 0; + if (ctl->enabled) + ret = wm_coeff_write_control(ctl, p, ctl->len); + + mutex_unlock(&ctl->dsp->pwr_lock); - return wm_coeff_write_control(ctl, p, ctl->len); + return ret; } static int wm_coeff_read_control(struct wm_coeff_ctl *ctl, @@ -626,22 +651,30 @@ static int wm_coeff_read_control(struct wm_coeff_ctl *ctl, return 0; } -static int wm_coeff_get(struct snd_kcontrol *kcontrol, +static int wm_coeff_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { - struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; + struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kctl->private_value; char *p = ucontrol->value.bytes.data; + int ret = 0; + + mutex_lock(&ctl->dsp->pwr_lock); if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { if (ctl->enabled) - return wm_coeff_read_control(ctl, p, ctl->len); + ret = wm_coeff_read_control(ctl, p, ctl->len); else - return -EPERM; + ret = -EPERM; + } else { + if (!ctl->flags && ctl->enabled) + ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len); + + memcpy(p, ctl->cache, ctl->len); } - memcpy(p, ctl->cache, ctl->len); + mutex_unlock(&ctl->dsp->pwr_lock); - return 0; + return ret; } struct wmfw_ctl_work { @@ -808,8 +841,7 @@ static int wm_adsp_create_control(struct wm_adsp *dsp, break; } - list_for_each_entry(ctl, &dsp->ctl_list, - list) { + list_for_each_entry(ctl, &dsp->ctl_list, list) { if (!strcmp(ctl->name, name)) { if (!ctl->enabled) ctl->enabled = 1; @@ -1088,7 +1120,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) goto out_fw; } - header = (void*)&firmware->data[0]; + header = (void *)&firmware->data[0]; if (memcmp(&header->magic[0], "WMFW", 4) != 0) { adsp_err(dsp, "%s: invalid magic\n", file); @@ -1168,7 +1200,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) offset = le32_to_cpu(region->offset) & 0xffffff; type = be32_to_cpu(region->type) & 0xff; mem = wm_adsp_find_region(dsp, type); - + switch (type) { case WMFW_NAME_TEXT: region_name = "Firmware name"; @@ -1625,7 +1657,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) goto out_fw; } - hdr = (void*)&firmware->data[0]; + hdr = (void *)&firmware->data[0]; if (memcmp(hdr->magic, "WMDR", 4) != 0) { adsp_err(dsp, "%s: invalid magic\n", file); goto out_fw; @@ -1651,7 +1683,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) blocks = 0; while (pos < firmware->size && pos - firmware->size > sizeof(*blk)) { - blk = (void*)(&firmware->data[pos]); + blk = (void *)(&firmware->data[pos]); type = le16_to_cpu(blk->type); offset = le16_to_cpu(blk->offset); @@ -1778,9 +1810,8 @@ int wm_adsp1_init(struct wm_adsp *dsp) { INIT_LIST_HEAD(&dsp->alg_regions); -#ifdef CONFIG_DEBUG_FS - mutex_init(&dsp->debugfs_lock); -#endif + mutex_init(&dsp->pwr_lock); + return 0; } EXPORT_SYMBOL_GPL(wm_adsp1_init); @@ -1795,10 +1826,12 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, struct wm_adsp_alg_region *alg_region; struct wm_coeff_ctl *ctl; int ret; - int val; + unsigned int val; dsp->card = codec->component.card; + mutex_lock(&dsp->pwr_lock); + switch (event) { case SND_SOC_DAPM_POST_PMU: regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, @@ -1808,12 +1841,12 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, * For simplicity set the DSP clock rate to be the * SYSCLK rate rather than making it configurable. */ - if(dsp->sysclk_reg) { + if (dsp->sysclk_reg) { ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val); if (ret != 0) { adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret); - return ret; + goto err_mutex; } val = (val & dsp->sysclk_mask) @@ -1825,31 +1858,31 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, if (ret != 0) { adsp_err(dsp, "Failed to set clock rate: %d\n", ret); - return ret; + goto err_mutex; } } ret = wm_adsp_load(dsp); if (ret != 0) - goto err; + goto err_ena; ret = wm_adsp1_setup_algs(dsp); if (ret != 0) - goto err; + goto err_ena; ret = wm_adsp_load_coeff(dsp); if (ret != 0) - goto err; + goto err_ena; /* Initialize caches for enabled and unset controls */ ret = wm_coeff_init_control_caches(dsp); if (ret != 0) - goto err; + goto err_ena; /* Sync set controls */ ret = wm_coeff_sync_controls(dsp); if (ret != 0) - goto err; + goto err_ena; /* Start the core running */ regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, @@ -1884,11 +1917,16 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, break; } + mutex_unlock(&dsp->pwr_lock); + return 0; -err: +err_ena: regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, ADSP1_SYS_ENA, 0); +err_mutex: + mutex_unlock(&dsp->pwr_lock); + return ret; } EXPORT_SYMBOL_GPL(wm_adsp1_event); @@ -1934,6 +1972,8 @@ static void wm_adsp2_boot_work(struct work_struct *work) int ret; unsigned int val; + mutex_lock(&dsp->pwr_lock); + /* * For simplicity set the DSP clock rate to be the * SYSCLK rate rather than making it configurable. @@ -1941,7 +1981,7 @@ static void wm_adsp2_boot_work(struct work_struct *work) ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val); if (ret != 0) { adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret); - return; + goto err_mutex; } val = (val & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT; @@ -1951,42 +1991,46 @@ static void wm_adsp2_boot_work(struct work_struct *work) ADSP2_CLK_SEL_MASK, val); if (ret != 0) { adsp_err(dsp, "Failed to set clock rate: %d\n", ret); - return; + goto err_mutex; } ret = wm_adsp2_ena(dsp); if (ret != 0) - return; + goto err_mutex; ret = wm_adsp_load(dsp); if (ret != 0) - goto err; + goto err_ena; ret = wm_adsp2_setup_algs(dsp); if (ret != 0) - goto err; + goto err_ena; ret = wm_adsp_load_coeff(dsp); if (ret != 0) - goto err; + goto err_ena; /* Initialize caches for enabled and unset controls */ ret = wm_coeff_init_control_caches(dsp); if (ret != 0) - goto err; + goto err_ena; /* Sync set controls */ ret = wm_coeff_sync_controls(dsp); if (ret != 0) - goto err; + goto err_ena; dsp->running = true; + mutex_unlock(&dsp->pwr_lock); + return; -err: +err_ena: regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); +err_mutex: + mutex_unlock(&dsp->pwr_lock); } int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, @@ -2039,6 +2083,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, /* Log firmware state, it can be useful for analysis */ wm_adsp2_show_fw_status(dsp); + mutex_lock(&dsp->pwr_lock); + wm_adsp_debugfs_clear(dsp); dsp->fw_id = 0; @@ -2065,6 +2111,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, kfree(alg_region); } + mutex_unlock(&dsp->pwr_lock); + adsp_dbg(dsp, "Shutdown complete\n"); break; @@ -2117,9 +2165,8 @@ int wm_adsp2_init(struct wm_adsp *dsp) INIT_LIST_HEAD(&dsp->ctl_list); INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work); -#ifdef CONFIG_DEBUG_FS - mutex_init(&dsp->debugfs_lock); -#endif + mutex_init(&dsp->pwr_lock); + return 0; } EXPORT_SYMBOL_GPL(wm_adsp2_init); diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 2d117cf..d2a8c78 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -45,8 +45,8 @@ struct wm_adsp { struct list_head alg_regions; - int fw_id; - int fw_id_version; + unsigned int fw_id; + unsigned int fw_id_version; const struct wm_adsp_region *mem; int num_mems; @@ -59,9 +59,10 @@ struct wm_adsp { struct work_struct boot_work; + struct mutex pwr_lock; + #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_root; - struct mutex debugfs_lock; char *wmfw_file_name; char *bin_file_name; #endif |