13 #include <linux/module.h>
18 #include <linux/i2c.h>
20 #include <linux/slab.h>
33 #define WM_FW_BLOCK_INFO 0xff
34 #define WM_FW_BLOCK_PM 0x00
35 #define WM_FW_BLOCK_X 0x01
36 #define WM_FW_BLOCK_Y 0x02
37 #define WM_FW_BLOCK_Z 0x03
38 #define WM_FW_BLOCK_I 0x06
39 #define WM_FW_BLOCK_A 0x08
40 #define WM_FW_BLOCK_C 0x0c
50 size_t block_len,
len;
58 dev_err(codec->
dev,
"%s: firmware too short (%zd bytes)\n",
66 dev_err(codec->
dev,
"%s: firmware has bad file magic %08x\n",
76 if ((data32 >> 24) & 0xff) {
77 dev_err(codec->
dev,
"%s: unsupported firmware version %d\n",
78 name, (data32 >> 24) & 0xff);
81 if ((data32 & 0xffff) != 8958) {
82 dev_err(codec->
dev,
"%s: unsupported target device %d\n",
83 name, data32 & 0xffff);
86 if (((data32 >> 16) & 0xff) != 0
xc) {
87 dev_err(codec->
dev,
"%s: unsupported target core %d\n",
88 name, (data32 >> 16) & 0xff);
101 data = fw->
data + len;
102 len = fw->
size - len;
105 dev_err(codec->
dev,
"%s short data block of %zd\n",
110 memcpy(&data32, data + 4,
sizeof(data32));
112 if (block_len + 8 > len) {
113 dev_err(codec->
dev,
"%zd byte block longer than file\n",
117 if (block_len == 0) {
122 memcpy(&data32, data,
sizeof(data32));
125 switch ((data32 >> 24) & 0xff) {
133 memcpy(str, data + 8, block_len);
147 dev_dbg(codec->
dev,
"%s: %zd bytes of %x@%x\n", name,
148 block_len, (data32 >> 24) & 0xff,
163 dev_warn(codec->
dev,
"%s: unknown block type %d\n",
164 name, (data32 >> 24) & 0xff);
169 block_len += block_len % 4;
171 data += block_len + 8;
172 len -= block_len + 8;
176 dev_dbg(codec->
dev,
"%s: download done\n", name);
207 wm8958_dsp2_fw(codec,
"MBC", wm8994->
mbc,
false);
210 WM8958_DSP2_ENA, WM8958_DSP2_ENA);
239 static void wm8958_dsp_start_vss(
struct snd_soc_codec *codec,
int path)
241 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
246 wm8958_dsp2_fw(codec,
"MBC+VSS", wm8994->
mbc_vss,
false);
249 WM8958_DSP2_ENA, WM8958_DSP2_ENA);
300 static void wm8958_dsp_start_enh_eq(
struct snd_soc_codec *codec,
int path)
302 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
306 wm8958_dsp2_fw(codec,
"ENH_EQ", wm8994->
enh_eq,
false);
309 WM8958_DSP2_ENA, WM8958_DSP2_ENA);
333 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
364 dev_dbg(codec->
dev,
"DSP path %d %d startup: %d, power: %x, DSP: %x\n",
365 path, wm8994->
dsp_active, start, pwr_reg, reg);
369 if (reg & WM8958_DSP2_ENA)
386 wm8958_dsp_start_enh_eq(codec, path);
389 wm8958_dsp_start_vss(codec, path);
390 else if (wm8994->
mbc_ena[path])
391 wm8958_dsp_start_mbc(codec, path);
395 dev_dbg(codec->
dev,
"DSP running in path %d\n", path);
400 if (!(reg & WM8958_DSP2_ENA))
427 for (i = 0; i < 3; i++)
428 wm8958_dsp_apply(codec, i, 1);
432 for (i = 0; i < 3; i++)
433 wm8958_dsp_apply(codec, i, 0);
441 static int wm8958_dsp2_busy(
struct wm8994_priv *wm8994,
int aif)
456 static int wm8958_put_mbc_enum(
struct snd_kcontrol *kcontrol,
460 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
478 static int wm8958_get_mbc_enum(
struct snd_kcontrol *kcontrol,
482 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
489 static int wm8958_mbc_info(
struct snd_kcontrol *kcontrol,
499 static int wm8958_mbc_get(
struct snd_kcontrol *kcontrol,
504 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
511 static int wm8958_mbc_put(
struct snd_kcontrol *kcontrol,
516 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
518 if (wm8994->
mbc_ena[mbc] == ucontrol->
value.integer.value[0])
521 if (ucontrol->
value.integer.value[0] > 1)
524 if (wm8958_dsp2_busy(wm8994, mbc)) {
525 dev_dbg(codec->
dev,
"DSP2 active on %d already\n", mbc);
534 wm8958_dsp_apply(codec, mbc, wm8994->
mbc_ena[mbc]);
539 #define WM8958_MBC_SWITCH(xname, xval) {\
540 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
541 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
542 .info = wm8958_mbc_info, \
543 .get = wm8958_mbc_get, .put = wm8958_mbc_put, \
544 .private_value = xval }
546 static int wm8958_put_vss_enum(
struct snd_kcontrol *kcontrol,
550 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
552 int value = ucontrol->
value.integer.value[0];
557 if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
568 static int wm8958_get_vss_enum(
struct snd_kcontrol *kcontrol,
572 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
579 static int wm8958_put_vss_hpf_enum(
struct snd_kcontrol *kcontrol,
583 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
585 int value = ucontrol->
value.integer.value[0];
590 if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
601 static int wm8958_get_vss_hpf_enum(
struct snd_kcontrol *kcontrol,
605 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
612 static int wm8958_vss_info(
struct snd_kcontrol *kcontrol,
622 static int wm8958_vss_get(
struct snd_kcontrol *kcontrol,
627 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
629 ucontrol->
value.integer.value[0] = wm8994->
vss_ena[vss];
634 static int wm8958_vss_put(
struct snd_kcontrol *kcontrol,
639 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
641 if (wm8994->
vss_ena[vss] == ucontrol->
value.integer.value[0])
644 if (ucontrol->
value.integer.value[0] > 1)
650 if (wm8958_dsp2_busy(wm8994, vss)) {
651 dev_dbg(codec->
dev,
"DSP2 active on %d already\n", vss);
658 wm8994->
vss_ena[vss] = ucontrol->
value.integer.value[0];
660 wm8958_dsp_apply(codec, vss, wm8994->
vss_ena[vss]);
666 #define WM8958_VSS_SWITCH(xname, xval) {\
667 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
668 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
669 .info = wm8958_vss_info, \
670 .get = wm8958_vss_get, .put = wm8958_vss_put, \
671 .private_value = xval }
673 static int wm8958_hpf_info(
struct snd_kcontrol *kcontrol,
683 static int wm8958_hpf_get(
struct snd_kcontrol *kcontrol,
688 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
691 ucontrol->
value.integer.value[0] = wm8994->
hpf1_ena[hpf % 3];
693 ucontrol->
value.integer.value[0] = wm8994->
hpf2_ena[hpf % 3];
698 static int wm8958_hpf_put(
struct snd_kcontrol *kcontrol,
703 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
707 ucontrol->
value.integer.value[0])
711 ucontrol->
value.integer.value[0])
715 if (ucontrol->
value.integer.value[0] > 1)
721 if (wm8958_dsp2_busy(wm8994, hpf % 3)) {
722 dev_dbg(codec->
dev,
"DSP2 active on %d already\n", hpf);
730 wm8994->
hpf1_ena[hpf % 3] = ucontrol->
value.integer.value[0];
732 wm8994->
hpf2_ena[hpf % 3] = ucontrol->
value.integer.value[0];
734 wm8958_dsp_apply(codec, hpf % 3, ucontrol->
value.integer.value[0]);
739 #define WM8958_HPF_SWITCH(xname, xval) {\
740 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
741 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
742 .info = wm8958_hpf_info, \
743 .get = wm8958_hpf_get, .put = wm8958_hpf_put, \
744 .private_value = xval }
746 static int wm8958_put_enh_eq_enum(
struct snd_kcontrol *kcontrol,
750 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
752 int value = ucontrol->
value.integer.value[0];
757 if (reg < 0 || reg & WM8958_DSP2CLK_ENA)
768 static int wm8958_get_enh_eq_enum(
struct snd_kcontrol *kcontrol,
772 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
779 static int wm8958_enh_eq_info(
struct snd_kcontrol *kcontrol,
789 static int wm8958_enh_eq_get(
struct snd_kcontrol *kcontrol,
794 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
801 static int wm8958_enh_eq_put(
struct snd_kcontrol *kcontrol,
806 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
811 if (ucontrol->
value.integer.value[0] > 1)
817 if (wm8958_dsp2_busy(wm8994, eq)) {
818 dev_dbg(codec->
dev,
"DSP2 active on %d already\n", eq);
828 wm8958_dsp_apply(codec, eq, ucontrol->
value.integer.value[0]);
833 #define WM8958_ENH_EQ_SWITCH(xname, xval) {\
834 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
835 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\
836 .info = wm8958_enh_eq_info, \
837 .get = wm8958_enh_eq_get, .put = wm8958_enh_eq_put, \
838 .private_value = xval }
867 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
869 if (fw && (wm8958_dsp2_fw(codec,
"ENH_EQ", fw,
true) == 0)) {
876 static void wm8958_mbc_vss_loaded(
const struct firmware *fw,
void *context)
879 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
881 if (fw && (wm8958_dsp2_fw(codec,
"MBC+VSS", fw,
true) == 0)) {
892 codec, wm8958_enh_eq_loaded);
895 static void wm8958_mbc_loaded(
const struct firmware *fw,
void *context)
898 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
900 if (wm8958_dsp2_fw(codec,
"MBC", fw,
true) != 0)
912 codec, wm8958_mbc_vss_loaded);
917 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
934 codec, wm8958_mbc_loaded);
942 wm8958_get_mbc_enum, wm8958_put_mbc_enum),
950 "Failed to allocate %d MBC config texts\n",
965 "Failed to add MBC mode controls: %d\n", ret);
971 wm8958_get_vss_enum, wm8958_put_vss_enum),
979 "Failed to allocate %d VSS config texts\n",
994 "Failed to add VSS mode controls: %d\n", ret);
1000 wm8958_get_vss_hpf_enum,
1001 wm8958_put_vss_hpf_enum),
1009 "Failed to allocate %d VSS HPF config texts\n",
1024 "Failed to add VSS HPFmode controls: %d\n",
1031 wm8958_get_enh_eq_enum,
1032 wm8958_put_enh_eq_enum),
1040 "Failed to allocate %d enhanced EQ config texts\n",
1055 "Failed to add enhanced EQ controls: %d\n",