diff options
Diffstat (limited to 'sound')
251 files changed, 20056 insertions, 5729 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index a2104671f51d..5dcf88bed9b7 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -1242,6 +1242,7 @@ int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_par | |||
1242 | return -EINVAL; | 1242 | return -EINVAL; |
1243 | return 0; | 1243 | return 0; |
1244 | } | 1244 | } |
1245 | EXPORT_SYMBOL(snd_pcm_hw_constraint_mask64); | ||
1245 | 1246 | ||
1246 | /** | 1247 | /** |
1247 | * snd_pcm_hw_constraint_integer - apply an integer constraint to an interval | 1248 | * snd_pcm_hw_constraint_integer - apply an integer constraint to an interval |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ec4536c8d8d4..dafcf82139e2 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -932,7 +932,7 @@ int snd_hda_bus_new(struct snd_card *card, | |||
932 | } | 932 | } |
933 | EXPORT_SYMBOL_GPL(snd_hda_bus_new); | 933 | EXPORT_SYMBOL_GPL(snd_hda_bus_new); |
934 | 934 | ||
935 | #ifdef CONFIG_SND_HDA_GENERIC | 935 | #if IS_ENABLED(CONFIG_SND_HDA_GENERIC) |
936 | #define is_generic_config(codec) \ | 936 | #define is_generic_config(codec) \ |
937 | (codec->modelname && !strcmp(codec->modelname, "generic")) | 937 | (codec->modelname && !strcmp(codec->modelname, "generic")) |
938 | #else | 938 | #else |
@@ -1339,23 +1339,15 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid) | |||
1339 | /* | 1339 | /* |
1340 | * Dynamic symbol binding for the codec parsers | 1340 | * Dynamic symbol binding for the codec parsers |
1341 | */ | 1341 | */ |
1342 | #ifdef MODULE | ||
1343 | #define load_parser_sym(sym) ((int (*)(struct hda_codec *))symbol_request(sym)) | ||
1344 | #define unload_parser_addr(addr) symbol_put_addr(addr) | ||
1345 | #else | ||
1346 | #define load_parser_sym(sym) (sym) | ||
1347 | #define unload_parser_addr(addr) do {} while (0) | ||
1348 | #endif | ||
1349 | 1342 | ||
1350 | #define load_parser(codec, sym) \ | 1343 | #define load_parser(codec, sym) \ |
1351 | ((codec)->parser = load_parser_sym(sym)) | 1344 | ((codec)->parser = (int (*)(struct hda_codec *))symbol_request(sym)) |
1352 | 1345 | ||
1353 | static void unload_parser(struct hda_codec *codec) | 1346 | static void unload_parser(struct hda_codec *codec) |
1354 | { | 1347 | { |
1355 | if (codec->parser) { | 1348 | if (codec->parser) |
1356 | unload_parser_addr(codec->parser); | 1349 | symbol_put_addr(codec->parser); |
1357 | codec->parser = NULL; | 1350 | codec->parser = NULL; |
1358 | } | ||
1359 | } | 1351 | } |
1360 | 1352 | ||
1361 | /* | 1353 | /* |
@@ -1570,7 +1562,7 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec) | |||
1570 | EXPORT_SYMBOL_GPL(snd_hda_codec_update_widgets); | 1562 | EXPORT_SYMBOL_GPL(snd_hda_codec_update_widgets); |
1571 | 1563 | ||
1572 | 1564 | ||
1573 | #ifdef CONFIG_SND_HDA_CODEC_HDMI | 1565 | #if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) |
1574 | /* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */ | 1566 | /* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */ |
1575 | static bool is_likely_hdmi_codec(struct hda_codec *codec) | 1567 | static bool is_likely_hdmi_codec(struct hda_codec *codec) |
1576 | { | 1568 | { |
@@ -1620,12 +1612,20 @@ int snd_hda_codec_configure(struct hda_codec *codec) | |||
1620 | patch = codec->preset->patch; | 1612 | patch = codec->preset->patch; |
1621 | if (!patch) { | 1613 | if (!patch) { |
1622 | unload_parser(codec); /* to be sure */ | 1614 | unload_parser(codec); /* to be sure */ |
1623 | if (is_likely_hdmi_codec(codec)) | 1615 | if (is_likely_hdmi_codec(codec)) { |
1616 | #if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI) | ||
1624 | patch = load_parser(codec, snd_hda_parse_hdmi_codec); | 1617 | patch = load_parser(codec, snd_hda_parse_hdmi_codec); |
1625 | #ifdef CONFIG_SND_HDA_GENERIC | 1618 | #elif IS_BUILTIN(CONFIG_SND_HDA_CODEC_HDMI) |
1626 | if (!patch) | 1619 | patch = snd_hda_parse_hdmi_codec; |
1620 | #endif | ||
1621 | } | ||
1622 | if (!patch) { | ||
1623 | #if IS_MODULE(CONFIG_SND_HDA_GENERIC) | ||
1627 | patch = load_parser(codec, snd_hda_parse_generic_codec); | 1624 | patch = load_parser(codec, snd_hda_parse_generic_codec); |
1625 | #elif IS_BUILTIN(CONFIG_SND_HDA_GENERIC) | ||
1626 | patch = snd_hda_parse_generic_codec; | ||
1628 | #endif | 1627 | #endif |
1628 | } | ||
1629 | if (!patch) { | 1629 | if (!patch) { |
1630 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); | 1630 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); |
1631 | return -ENODEV; | 1631 | return -ENODEV; |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 8321a97d5c05..d9a09bdd09db 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -3269,7 +3269,7 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol, | |||
3269 | mutex_unlock(&codec->control_mutex); | 3269 | mutex_unlock(&codec->control_mutex); |
3270 | snd_hda_codec_flush_cache(codec); /* flush the updates */ | 3270 | snd_hda_codec_flush_cache(codec); /* flush the updates */ |
3271 | if (err >= 0 && spec->cap_sync_hook) | 3271 | if (err >= 0 && spec->cap_sync_hook) |
3272 | spec->cap_sync_hook(codec, ucontrol); | 3272 | spec->cap_sync_hook(codec, kcontrol, ucontrol); |
3273 | return err; | 3273 | return err; |
3274 | } | 3274 | } |
3275 | 3275 | ||
@@ -3390,7 +3390,7 @@ static int cap_single_sw_put(struct snd_kcontrol *kcontrol, | |||
3390 | return ret; | 3390 | return ret; |
3391 | 3391 | ||
3392 | if (spec->cap_sync_hook) | 3392 | if (spec->cap_sync_hook) |
3393 | spec->cap_sync_hook(codec, ucontrol); | 3393 | spec->cap_sync_hook(codec, kcontrol, ucontrol); |
3394 | 3394 | ||
3395 | return ret; | 3395 | return ret; |
3396 | } | 3396 | } |
@@ -3795,7 +3795,7 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx, | |||
3795 | return 0; | 3795 | return 0; |
3796 | snd_hda_activate_path(codec, path, true, false); | 3796 | snd_hda_activate_path(codec, path, true, false); |
3797 | if (spec->cap_sync_hook) | 3797 | if (spec->cap_sync_hook) |
3798 | spec->cap_sync_hook(codec, NULL); | 3798 | spec->cap_sync_hook(codec, NULL, NULL); |
3799 | path_power_down_sync(codec, old_path); | 3799 | path_power_down_sync(codec, old_path); |
3800 | return 1; | 3800 | return 1; |
3801 | } | 3801 | } |
@@ -5270,7 +5270,7 @@ static void init_input_src(struct hda_codec *codec) | |||
5270 | } | 5270 | } |
5271 | 5271 | ||
5272 | if (spec->cap_sync_hook) | 5272 | if (spec->cap_sync_hook) |
5273 | spec->cap_sync_hook(codec, NULL); | 5273 | spec->cap_sync_hook(codec, NULL, NULL); |
5274 | } | 5274 | } |
5275 | 5275 | ||
5276 | /* set right pin controls for digital I/O */ | 5276 | /* set right pin controls for digital I/O */ |
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 07f767231c9f..c908afbe4d94 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h | |||
@@ -274,6 +274,7 @@ struct hda_gen_spec { | |||
274 | void (*init_hook)(struct hda_codec *codec); | 274 | void (*init_hook)(struct hda_codec *codec); |
275 | void (*automute_hook)(struct hda_codec *codec); | 275 | void (*automute_hook)(struct hda_codec *codec); |
276 | void (*cap_sync_hook)(struct hda_codec *codec, | 276 | void (*cap_sync_hook)(struct hda_codec *codec, |
277 | struct snd_kcontrol *kcontrol, | ||
277 | struct snd_ctl_elem_value *ucontrol); | 278 | struct snd_ctl_elem_value *ucontrol); |
278 | 279 | ||
279 | /* PCM hooks */ | 280 | /* PCM hooks */ |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index fa2879a21a50..e354ab1ec20f 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -198,7 +198,7 @@ MODULE_DESCRIPTION("Intel HDA driver"); | |||
198 | #endif | 198 | #endif |
199 | 199 | ||
200 | #if defined(CONFIG_PM) && defined(CONFIG_VGA_SWITCHEROO) | 200 | #if defined(CONFIG_PM) && defined(CONFIG_VGA_SWITCHEROO) |
201 | #ifdef CONFIG_SND_HDA_CODEC_HDMI | 201 | #if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) |
202 | #define SUPPORT_VGA_SWITCHEROO | 202 | #define SUPPORT_VGA_SWITCHEROO |
203 | #endif | 203 | #endif |
204 | #endif | 204 | #endif |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 7a426ed491f2..8ed0bcc01386 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -244,6 +244,19 @@ static void ad_fixup_inv_jack_detect(struct hda_codec *codec, | |||
244 | } | 244 | } |
245 | } | 245 | } |
246 | 246 | ||
247 | /* Toshiba Satellite L40 implements EAPD in a standard way unlike others */ | ||
248 | static void ad1986a_fixup_eapd(struct hda_codec *codec, | ||
249 | const struct hda_fixup *fix, int action) | ||
250 | { | ||
251 | struct ad198x_spec *spec = codec->spec; | ||
252 | |||
253 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
254 | codec->inv_eapd = 0; | ||
255 | spec->gen.keep_eapd_on = 1; | ||
256 | spec->eapd_nid = 0x1b; | ||
257 | } | ||
258 | } | ||
259 | |||
247 | enum { | 260 | enum { |
248 | AD1986A_FIXUP_INV_JACK_DETECT, | 261 | AD1986A_FIXUP_INV_JACK_DETECT, |
249 | AD1986A_FIXUP_ULTRA, | 262 | AD1986A_FIXUP_ULTRA, |
@@ -251,6 +264,7 @@ enum { | |||
251 | AD1986A_FIXUP_3STACK, | 264 | AD1986A_FIXUP_3STACK, |
252 | AD1986A_FIXUP_LAPTOP, | 265 | AD1986A_FIXUP_LAPTOP, |
253 | AD1986A_FIXUP_LAPTOP_IMIC, | 266 | AD1986A_FIXUP_LAPTOP_IMIC, |
267 | AD1986A_FIXUP_EAPD, | ||
254 | }; | 268 | }; |
255 | 269 | ||
256 | static const struct hda_fixup ad1986a_fixups[] = { | 270 | static const struct hda_fixup ad1986a_fixups[] = { |
@@ -311,6 +325,10 @@ static const struct hda_fixup ad1986a_fixups[] = { | |||
311 | .chained_before = 1, | 325 | .chained_before = 1, |
312 | .chain_id = AD1986A_FIXUP_LAPTOP, | 326 | .chain_id = AD1986A_FIXUP_LAPTOP, |
313 | }, | 327 | }, |
328 | [AD1986A_FIXUP_EAPD] = { | ||
329 | .type = HDA_FIXUP_FUNC, | ||
330 | .v.func = ad1986a_fixup_eapd, | ||
331 | }, | ||
314 | }; | 332 | }; |
315 | 333 | ||
316 | static const struct snd_pci_quirk ad1986a_fixup_tbl[] = { | 334 | static const struct snd_pci_quirk ad1986a_fixup_tbl[] = { |
@@ -318,6 +336,7 @@ static const struct snd_pci_quirk ad1986a_fixup_tbl[] = { | |||
318 | SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8100, "ASUS P5", AD1986A_FIXUP_3STACK), | 336 | SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8100, "ASUS P5", AD1986A_FIXUP_3STACK), |
319 | SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8200, "ASUS M2", AD1986A_FIXUP_3STACK), | 337 | SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8200, "ASUS M2", AD1986A_FIXUP_3STACK), |
320 | SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_FIXUP_3STACK), | 338 | SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_FIXUP_3STACK), |
339 | SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40", AD1986A_FIXUP_EAPD), | ||
321 | SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_FIXUP_LAPTOP), | 340 | SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_FIXUP_LAPTOP), |
322 | SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_FIXUP_SAMSUNG), | 341 | SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_FIXUP_SAMSUNG), |
323 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_FIXUP_ULTRA), | 342 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_FIXUP_ULTRA), |
@@ -472,6 +491,8 @@ static int ad1983_add_spdif_mux_ctl(struct hda_codec *codec) | |||
472 | static int patch_ad1983(struct hda_codec *codec) | 491 | static int patch_ad1983(struct hda_codec *codec) |
473 | { | 492 | { |
474 | struct ad198x_spec *spec; | 493 | struct ad198x_spec *spec; |
494 | static hda_nid_t conn_0c[] = { 0x08 }; | ||
495 | static hda_nid_t conn_0d[] = { 0x09 }; | ||
475 | int err; | 496 | int err; |
476 | 497 | ||
477 | err = alloc_ad_spec(codec); | 498 | err = alloc_ad_spec(codec); |
@@ -479,8 +500,14 @@ static int patch_ad1983(struct hda_codec *codec) | |||
479 | return err; | 500 | return err; |
480 | spec = codec->spec; | 501 | spec = codec->spec; |
481 | 502 | ||
503 | spec->gen.mixer_nid = 0x0e; | ||
482 | spec->gen.beep_nid = 0x10; | 504 | spec->gen.beep_nid = 0x10; |
483 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | 505 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); |
506 | |||
507 | /* limit the loopback routes not to confuse the parser */ | ||
508 | snd_hda_override_conn_list(codec, 0x0c, ARRAY_SIZE(conn_0c), conn_0c); | ||
509 | snd_hda_override_conn_list(codec, 0x0d, ARRAY_SIZE(conn_0d), conn_0d); | ||
510 | |||
484 | err = ad198x_parse_auto_config(codec, false); | 511 | err = ad198x_parse_auto_config(codec, false); |
485 | if (err < 0) | 512 | if (err < 0) |
486 | goto error; | 513 | goto error; |
@@ -999,6 +1026,9 @@ static void ad1884_fixup_thinkpad(struct hda_codec *codec, | |||
999 | spec->gen.keep_eapd_on = 1; | 1026 | spec->gen.keep_eapd_on = 1; |
1000 | spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook; | 1027 | spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook; |
1001 | spec->eapd_nid = 0x12; | 1028 | spec->eapd_nid = 0x12; |
1029 | /* Analog PC Beeper - allow firmware/ACPI beeps */ | ||
1030 | spec->beep_amp = HDA_COMPOSE_AMP_VAL(0x20, 3, 3, HDA_INPUT); | ||
1031 | spec->gen.beep_nid = 0; /* no digital beep */ | ||
1002 | } | 1032 | } |
1003 | } | 1033 | } |
1004 | 1034 | ||
@@ -1065,6 +1095,7 @@ static int patch_ad1884(struct hda_codec *codec) | |||
1065 | spec = codec->spec; | 1095 | spec = codec->spec; |
1066 | 1096 | ||
1067 | spec->gen.mixer_nid = 0x20; | 1097 | spec->gen.mixer_nid = 0x20; |
1098 | spec->gen.mixer_merge_nid = 0x21; | ||
1068 | spec->gen.beep_nid = 0x10; | 1099 | spec->gen.beep_nid = 0x10; |
1069 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | 1100 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); |
1070 | 1101 | ||
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 54d14793725a..46ecdbb9053f 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -2662,60 +2662,6 @@ static bool dspload_wait_loaded(struct hda_codec *codec) | |||
2662 | } | 2662 | } |
2663 | 2663 | ||
2664 | /* | 2664 | /* |
2665 | * PCM stuffs | ||
2666 | */ | ||
2667 | static void ca0132_setup_stream(struct hda_codec *codec, hda_nid_t nid, | ||
2668 | u32 stream_tag, | ||
2669 | int channel_id, int format) | ||
2670 | { | ||
2671 | unsigned int oldval, newval; | ||
2672 | |||
2673 | if (!nid) | ||
2674 | return; | ||
2675 | |||
2676 | snd_printdd( | ||
2677 | "ca0132_setup_stream: NID=0x%x, stream=0x%x, " | ||
2678 | "channel=%d, format=0x%x\n", | ||
2679 | nid, stream_tag, channel_id, format); | ||
2680 | |||
2681 | /* update the format-id if changed */ | ||
2682 | oldval = snd_hda_codec_read(codec, nid, 0, | ||
2683 | AC_VERB_GET_STREAM_FORMAT, | ||
2684 | 0); | ||
2685 | if (oldval != format) { | ||
2686 | msleep(20); | ||
2687 | snd_hda_codec_write(codec, nid, 0, | ||
2688 | AC_VERB_SET_STREAM_FORMAT, | ||
2689 | format); | ||
2690 | } | ||
2691 | |||
2692 | oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); | ||
2693 | newval = (stream_tag << 4) | channel_id; | ||
2694 | if (oldval != newval) { | ||
2695 | snd_hda_codec_write(codec, nid, 0, | ||
2696 | AC_VERB_SET_CHANNEL_STREAMID, | ||
2697 | newval); | ||
2698 | } | ||
2699 | } | ||
2700 | |||
2701 | static void ca0132_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) | ||
2702 | { | ||
2703 | unsigned int val; | ||
2704 | |||
2705 | if (!nid) | ||
2706 | return; | ||
2707 | |||
2708 | snd_printdd(KERN_INFO "ca0132_cleanup_stream: NID=0x%x\n", nid); | ||
2709 | |||
2710 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); | ||
2711 | if (!val) | ||
2712 | return; | ||
2713 | |||
2714 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); | ||
2715 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
2716 | } | ||
2717 | |||
2718 | /* | ||
2719 | * PCM callbacks | 2665 | * PCM callbacks |
2720 | */ | 2666 | */ |
2721 | static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 2667 | static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, |
@@ -2726,7 +2672,7 @@ static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
2726 | { | 2672 | { |
2727 | struct ca0132_spec *spec = codec->spec; | 2673 | struct ca0132_spec *spec = codec->spec; |
2728 | 2674 | ||
2729 | ca0132_setup_stream(codec, spec->dacs[0], stream_tag, 0, format); | 2675 | snd_hda_codec_setup_stream(codec, spec->dacs[0], stream_tag, 0, format); |
2730 | 2676 | ||
2731 | return 0; | 2677 | return 0; |
2732 | } | 2678 | } |
@@ -2745,7 +2691,7 @@ static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
2745 | if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) | 2691 | if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) |
2746 | msleep(50); | 2692 | msleep(50); |
2747 | 2693 | ||
2748 | ca0132_cleanup_stream(codec, spec->dacs[0]); | 2694 | snd_hda_codec_cleanup_stream(codec, spec->dacs[0]); |
2749 | 2695 | ||
2750 | return 0; | 2696 | return 0; |
2751 | } | 2697 | } |
@@ -2822,10 +2768,8 @@ static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
2822 | unsigned int format, | 2768 | unsigned int format, |
2823 | struct snd_pcm_substream *substream) | 2769 | struct snd_pcm_substream *substream) |
2824 | { | 2770 | { |
2825 | struct ca0132_spec *spec = codec->spec; | 2771 | snd_hda_codec_setup_stream(codec, hinfo->nid, |
2826 | 2772 | stream_tag, 0, format); | |
2827 | ca0132_setup_stream(codec, spec->adcs[substream->number], | ||
2828 | stream_tag, 0, format); | ||
2829 | 2773 | ||
2830 | return 0; | 2774 | return 0; |
2831 | } | 2775 | } |
@@ -2839,7 +2783,7 @@ static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
2839 | if (spec->dsp_state == DSP_DOWNLOADING) | 2783 | if (spec->dsp_state == DSP_DOWNLOADING) |
2840 | return 0; | 2784 | return 0; |
2841 | 2785 | ||
2842 | ca0132_cleanup_stream(codec, hinfo->nid); | 2786 | snd_hda_codec_cleanup_stream(codec, hinfo->nid); |
2843 | return 0; | 2787 | return 0; |
2844 | } | 2788 | } |
2845 | 2789 | ||
@@ -4742,6 +4686,8 @@ static int patch_ca0132(struct hda_codec *codec) | |||
4742 | return err; | 4686 | return err; |
4743 | 4687 | ||
4744 | codec->patch_ops = ca0132_patch_ops; | 4688 | codec->patch_ops = ca0132_patch_ops; |
4689 | codec->pcm_format_first = 1; | ||
4690 | codec->no_sticky_stream = 1; | ||
4745 | 4691 | ||
4746 | return 0; | 4692 | return 0; |
4747 | } | 4693 | } |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 4e0ec146553d..bcf91bea3317 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -3291,7 +3291,8 @@ static void cxt_update_headset_mode(struct hda_codec *codec) | |||
3291 | } | 3291 | } |
3292 | 3292 | ||
3293 | static void cxt_update_headset_mode_hook(struct hda_codec *codec, | 3293 | static void cxt_update_headset_mode_hook(struct hda_codec *codec, |
3294 | struct snd_ctl_elem_value *ucontrol) | 3294 | struct snd_kcontrol *kcontrol, |
3295 | struct snd_ctl_elem_value *ucontrol) | ||
3295 | { | 3296 | { |
3296 | cxt_update_headset_mode(codec); | 3297 | cxt_update_headset_mode(codec); |
3297 | } | 3298 | } |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 56a8f1876603..8d0a84436674 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -708,7 +708,8 @@ static void alc_inv_dmic_sync(struct hda_codec *codec, bool force) | |||
708 | } | 708 | } |
709 | 709 | ||
710 | static void alc_inv_dmic_hook(struct hda_codec *codec, | 710 | static void alc_inv_dmic_hook(struct hda_codec *codec, |
711 | struct snd_ctl_elem_value *ucontrol) | 711 | struct snd_kcontrol *kcontrol, |
712 | struct snd_ctl_elem_value *ucontrol) | ||
712 | { | 713 | { |
713 | alc_inv_dmic_sync(codec, false); | 714 | alc_inv_dmic_sync(codec, false); |
714 | } | 715 | } |
@@ -1821,6 +1822,7 @@ enum { | |||
1821 | ALC889_FIXUP_IMAC91_VREF, | 1822 | ALC889_FIXUP_IMAC91_VREF, |
1822 | ALC889_FIXUP_MBA11_VREF, | 1823 | ALC889_FIXUP_MBA11_VREF, |
1823 | ALC889_FIXUP_MBA21_VREF, | 1824 | ALC889_FIXUP_MBA21_VREF, |
1825 | ALC889_FIXUP_MP11_VREF, | ||
1824 | ALC882_FIXUP_INV_DMIC, | 1826 | ALC882_FIXUP_INV_DMIC, |
1825 | ALC882_FIXUP_NO_PRIMARY_HP, | 1827 | ALC882_FIXUP_NO_PRIMARY_HP, |
1826 | ALC887_FIXUP_ASUS_BASS, | 1828 | ALC887_FIXUP_ASUS_BASS, |
@@ -2190,6 +2192,12 @@ static const struct hda_fixup alc882_fixups[] = { | |||
2190 | .chained = true, | 2192 | .chained = true, |
2191 | .chain_id = ALC889_FIXUP_MBP_VREF, | 2193 | .chain_id = ALC889_FIXUP_MBP_VREF, |
2192 | }, | 2194 | }, |
2195 | [ALC889_FIXUP_MP11_VREF] = { | ||
2196 | .type = HDA_FIXUP_FUNC, | ||
2197 | .v.func = alc889_fixup_mba11_vref, | ||
2198 | .chained = true, | ||
2199 | .chain_id = ALC885_FIXUP_MACPRO_GPIO, | ||
2200 | }, | ||
2193 | [ALC882_FIXUP_INV_DMIC] = { | 2201 | [ALC882_FIXUP_INV_DMIC] = { |
2194 | .type = HDA_FIXUP_FUNC, | 2202 | .type = HDA_FIXUP_FUNC, |
2195 | .v.func = alc_fixup_inv_dmic_0x12, | 2203 | .v.func = alc_fixup_inv_dmic_0x12, |
@@ -2253,7 +2261,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { | |||
2253 | SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF), | 2261 | SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF), |
2254 | SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF), | 2262 | SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF), |
2255 | SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF), | 2263 | SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF), |
2256 | SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO), | 2264 | SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC889_FIXUP_MP11_VREF), |
2257 | SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO), | 2265 | SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO), |
2258 | SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO), | 2266 | SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO), |
2259 | SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF), | 2267 | SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF), |
@@ -3211,7 +3219,8 @@ static void alc269_fixup_hp_gpio_mute_hook(void *private_data, int enabled) | |||
3211 | 3219 | ||
3212 | /* turn on/off mic-mute LED per capture hook */ | 3220 | /* turn on/off mic-mute LED per capture hook */ |
3213 | static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec, | 3221 | static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec, |
3214 | struct snd_ctl_elem_value *ucontrol) | 3222 | struct snd_kcontrol *kcontrol, |
3223 | struct snd_ctl_elem_value *ucontrol) | ||
3215 | { | 3224 | { |
3216 | struct alc_spec *spec = codec->spec; | 3225 | struct alc_spec *spec = codec->spec; |
3217 | unsigned int oldval = spec->gpio_led; | 3226 | unsigned int oldval = spec->gpio_led; |
@@ -3521,7 +3530,8 @@ static void alc_update_headset_mode(struct hda_codec *codec) | |||
3521 | } | 3530 | } |
3522 | 3531 | ||
3523 | static void alc_update_headset_mode_hook(struct hda_codec *codec, | 3532 | static void alc_update_headset_mode_hook(struct hda_codec *codec, |
3524 | struct snd_ctl_elem_value *ucontrol) | 3533 | struct snd_kcontrol *kcontrol, |
3534 | struct snd_ctl_elem_value *ucontrol) | ||
3525 | { | 3535 | { |
3526 | alc_update_headset_mode(codec); | 3536 | alc_update_headset_mode(codec); |
3527 | } | 3537 | } |
@@ -3606,6 +3616,19 @@ static void alc_fixup_auto_mute_via_amp(struct hda_codec *codec, | |||
3606 | } | 3616 | } |
3607 | } | 3617 | } |
3608 | 3618 | ||
3619 | static void alc_no_shutup(struct hda_codec *codec) | ||
3620 | { | ||
3621 | } | ||
3622 | |||
3623 | static void alc_fixup_no_shutup(struct hda_codec *codec, | ||
3624 | const struct hda_fixup *fix, int action) | ||
3625 | { | ||
3626 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
3627 | struct alc_spec *spec = codec->spec; | ||
3628 | spec->shutup = alc_no_shutup; | ||
3629 | } | ||
3630 | } | ||
3631 | |||
3609 | static void alc_fixup_headset_mode_alc668(struct hda_codec *codec, | 3632 | static void alc_fixup_headset_mode_alc668(struct hda_codec *codec, |
3610 | const struct hda_fixup *fix, int action) | 3633 | const struct hda_fixup *fix, int action) |
3611 | { | 3634 | { |
@@ -3834,6 +3857,7 @@ enum { | |||
3834 | ALC269_FIXUP_HP_GPIO_LED, | 3857 | ALC269_FIXUP_HP_GPIO_LED, |
3835 | ALC269_FIXUP_INV_DMIC, | 3858 | ALC269_FIXUP_INV_DMIC, |
3836 | ALC269_FIXUP_LENOVO_DOCK, | 3859 | ALC269_FIXUP_LENOVO_DOCK, |
3860 | ALC269_FIXUP_NO_SHUTUP, | ||
3837 | ALC286_FIXUP_SONY_MIC_NO_PRESENCE, | 3861 | ALC286_FIXUP_SONY_MIC_NO_PRESENCE, |
3838 | ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT, | 3862 | ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT, |
3839 | ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | 3863 | ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, |
@@ -4010,6 +4034,10 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4010 | .type = HDA_FIXUP_FUNC, | 4034 | .type = HDA_FIXUP_FUNC, |
4011 | .v.func = alc_fixup_inv_dmic_0x12, | 4035 | .v.func = alc_fixup_inv_dmic_0x12, |
4012 | }, | 4036 | }, |
4037 | [ALC269_FIXUP_NO_SHUTUP] = { | ||
4038 | .type = HDA_FIXUP_FUNC, | ||
4039 | .v.func = alc_fixup_no_shutup, | ||
4040 | }, | ||
4013 | [ALC269_FIXUP_LENOVO_DOCK] = { | 4041 | [ALC269_FIXUP_LENOVO_DOCK] = { |
4014 | .type = HDA_FIXUP_PINS, | 4042 | .type = HDA_FIXUP_PINS, |
4015 | .v.pins = (const struct hda_pintbl[]) { | 4043 | .v.pins = (const struct hda_pintbl[]) { |
@@ -4243,6 +4271,7 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4243 | }; | 4271 | }; |
4244 | 4272 | ||
4245 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 4273 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
4274 | SND_PCI_QUIRK(0x1025, 0x0283, "Acer TravelMate 8371", ALC269_FIXUP_INV_DMIC), | ||
4246 | SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), | 4275 | SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), |
4247 | SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), | 4276 | SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), |
4248 | SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700), | 4277 | SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700), |
@@ -4298,7 +4327,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4298 | SND_PCI_QUIRK(0x1028, 0x0651, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | 4327 | SND_PCI_QUIRK(0x1028, 0x0651, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), |
4299 | SND_PCI_QUIRK(0x1028, 0x0652, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | 4328 | SND_PCI_QUIRK(0x1028, 0x0652, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), |
4300 | SND_PCI_QUIRK(0x1028, 0x0653, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | 4329 | SND_PCI_QUIRK(0x1028, 0x0653, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), |
4330 | SND_PCI_QUIRK(0x1028, 0x0657, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4301 | SND_PCI_QUIRK(0x1028, 0x0658, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | 4331 | SND_PCI_QUIRK(0x1028, 0x0658, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), |
4332 | SND_PCI_QUIRK(0x1028, 0x065f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
4302 | SND_PCI_QUIRK(0x1028, 0x0662, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | 4333 | SND_PCI_QUIRK(0x1028, 0x0662, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), |
4303 | SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | 4334 | SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), |
4304 | SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | 4335 | SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), |
@@ -4307,6 +4338,54 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4307 | SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4338 | SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4308 | SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4339 | SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4309 | SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), | 4340 | SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), |
4341 | /* ALC282 */ | ||
4342 | SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4343 | SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4344 | SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4345 | SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4346 | SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4347 | SND_PCI_QUIRK(0x103c, 0x2269, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4348 | SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4349 | SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4350 | SND_PCI_QUIRK(0x103c, 0x227a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4351 | SND_PCI_QUIRK(0x103c, 0x227b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4352 | SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4353 | SND_PCI_QUIRK(0x103c, 0x22a0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4354 | SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4355 | SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4356 | SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4357 | SND_PCI_QUIRK(0x103c, 0x22c0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4358 | SND_PCI_QUIRK(0x103c, 0x22c1, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4359 | SND_PCI_QUIRK(0x103c, 0x22c2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4360 | SND_PCI_QUIRK(0x103c, 0x22cd, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4361 | SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4362 | SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4363 | SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4364 | /* ALC290 */ | ||
4365 | SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4366 | SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4367 | SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4368 | SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4369 | SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4370 | SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4371 | SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4372 | SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4373 | SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4374 | SND_PCI_QUIRK(0x103c, 0x2280, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4375 | SND_PCI_QUIRK(0x103c, 0x2281, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4376 | SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4377 | SND_PCI_QUIRK(0x103c, 0x2289, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4378 | SND_PCI_QUIRK(0x103c, 0x228a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4379 | SND_PCI_QUIRK(0x103c, 0x228b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4380 | SND_PCI_QUIRK(0x103c, 0x228c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4381 | SND_PCI_QUIRK(0x103c, 0x228d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4382 | SND_PCI_QUIRK(0x103c, 0x228e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4383 | SND_PCI_QUIRK(0x103c, 0x22c5, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4384 | SND_PCI_QUIRK(0x103c, 0x22c6, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4385 | SND_PCI_QUIRK(0x103c, 0x22c7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4386 | SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4387 | SND_PCI_QUIRK(0x103c, 0x22c3, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4388 | SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4310 | SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED), | 4389 | SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED), |
4311 | SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), | 4390 | SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), |
4312 | SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4391 | SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
@@ -4322,6 +4401,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4322 | SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), | 4401 | SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), |
4323 | SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), | 4402 | SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), |
4324 | SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101), | 4403 | SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101), |
4404 | SND_PCI_QUIRK(0x104d, 0x90b5, "Sony VAIO Pro 11", ALC286_FIXUP_SONY_MIC_NO_PRESENCE), | ||
4325 | SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE), | 4405 | SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE), |
4326 | SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), | 4406 | SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), |
4327 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), | 4407 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |
@@ -4343,6 +4423,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4343 | SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4423 | SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
4344 | SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4424 | SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
4345 | SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4425 | SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
4426 | SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP), | ||
4346 | SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4427 | SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
4347 | SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC), | 4428 | SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC), |
4348 | SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4429 | SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
@@ -5096,12 +5177,13 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { | |||
5096 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), | 5177 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), |
5097 | SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 5178 | SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5098 | SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 5179 | SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5180 | SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | ||
5099 | SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_AUTO_MUTE), | 5181 | SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_AUTO_MUTE), |
5100 | SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_AUTO_MUTE), | 5182 | SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_AUTO_MUTE), |
5101 | SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 5183 | SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5102 | SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 5184 | SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
5103 | SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_AUTO_MUTE), | 5185 | SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_AUTO_MUTE), |
5104 | SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 5186 | SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_AUTO_MUTE), |
5105 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), | 5187 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), |
5106 | SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A_CHMAP), | 5188 | SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A_CHMAP), |
5107 | SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_CHMAP), | 5189 | SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_CHMAP), |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 6998cf29b9bc..3bc29c9b2529 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -83,6 +83,7 @@ enum { | |||
83 | STAC_DELL_M6_BOTH, | 83 | STAC_DELL_M6_BOTH, |
84 | STAC_DELL_EQ, | 84 | STAC_DELL_EQ, |
85 | STAC_ALIENWARE_M17X, | 85 | STAC_ALIENWARE_M17X, |
86 | STAC_92HD89XX_HP_FRONT_JACK, | ||
86 | STAC_92HD73XX_MODELS | 87 | STAC_92HD73XX_MODELS |
87 | }; | 88 | }; |
88 | 89 | ||
@@ -97,6 +98,7 @@ enum { | |||
97 | STAC_92HD83XXX_HP_LED, | 98 | STAC_92HD83XXX_HP_LED, |
98 | STAC_92HD83XXX_HP_INV_LED, | 99 | STAC_92HD83XXX_HP_INV_LED, |
99 | STAC_92HD83XXX_HP_MIC_LED, | 100 | STAC_92HD83XXX_HP_MIC_LED, |
101 | STAC_HP_LED_GPIO10, | ||
100 | STAC_92HD83XXX_HEADSET_JACK, | 102 | STAC_92HD83XXX_HEADSET_JACK, |
101 | STAC_92HD83XXX_HP, | 103 | STAC_92HD83XXX_HP, |
102 | STAC_HP_ENVY_BASS, | 104 | STAC_HP_ENVY_BASS, |
@@ -194,7 +196,7 @@ struct sigmatel_spec { | |||
194 | int default_polarity; | 196 | int default_polarity; |
195 | 197 | ||
196 | unsigned int mic_mute_led_gpio; /* capture mute LED GPIO */ | 198 | unsigned int mic_mute_led_gpio; /* capture mute LED GPIO */ |
197 | bool mic_mute_led_on; /* current mic mute state */ | 199 | unsigned int mic_enabled; /* current mic mute state (bitmask) */ |
198 | 200 | ||
199 | /* stream */ | 201 | /* stream */ |
200 | unsigned int stream_delay; | 202 | unsigned int stream_delay; |
@@ -324,19 +326,26 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | |||
324 | 326 | ||
325 | /* hook for controlling mic-mute LED GPIO */ | 327 | /* hook for controlling mic-mute LED GPIO */ |
326 | static void stac_capture_led_hook(struct hda_codec *codec, | 328 | static void stac_capture_led_hook(struct hda_codec *codec, |
327 | struct snd_ctl_elem_value *ucontrol) | 329 | struct snd_kcontrol *kcontrol, |
330 | struct snd_ctl_elem_value *ucontrol) | ||
328 | { | 331 | { |
329 | struct sigmatel_spec *spec = codec->spec; | 332 | struct sigmatel_spec *spec = codec->spec; |
330 | bool mute; | 333 | unsigned int mask; |
334 | bool cur_mute, prev_mute; | ||
331 | 335 | ||
332 | if (!ucontrol) | 336 | if (!kcontrol || !ucontrol) |
333 | return; | 337 | return; |
334 | 338 | ||
335 | mute = !(ucontrol->value.integer.value[0] || | 339 | mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
336 | ucontrol->value.integer.value[1]); | 340 | prev_mute = !spec->mic_enabled; |
337 | if (spec->mic_mute_led_on != mute) { | 341 | if (ucontrol->value.integer.value[0] || |
338 | spec->mic_mute_led_on = mute; | 342 | ucontrol->value.integer.value[1]) |
339 | if (mute) | 343 | spec->mic_enabled |= mask; |
344 | else | ||
345 | spec->mic_enabled &= ~mask; | ||
346 | cur_mute = !spec->mic_enabled; | ||
347 | if (cur_mute != prev_mute) { | ||
348 | if (cur_mute) | ||
340 | spec->gpio_data |= spec->mic_mute_led_gpio; | 349 | spec->gpio_data |= spec->mic_mute_led_gpio; |
341 | else | 350 | else |
342 | spec->gpio_data &= ~spec->mic_mute_led_gpio; | 351 | spec->gpio_data &= ~spec->mic_mute_led_gpio; |
@@ -1788,6 +1797,12 @@ static const struct hda_pintbl intel_dg45id_pin_configs[] = { | |||
1788 | {} | 1797 | {} |
1789 | }; | 1798 | }; |
1790 | 1799 | ||
1800 | static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = { | ||
1801 | { 0x0a, 0x02214030 }, | ||
1802 | { 0x0b, 0x02A19010 }, | ||
1803 | {} | ||
1804 | }; | ||
1805 | |||
1791 | static void stac92hd73xx_fixup_ref(struct hda_codec *codec, | 1806 | static void stac92hd73xx_fixup_ref(struct hda_codec *codec, |
1792 | const struct hda_fixup *fix, int action) | 1807 | const struct hda_fixup *fix, int action) |
1793 | { | 1808 | { |
@@ -1906,6 +1921,10 @@ static const struct hda_fixup stac92hd73xx_fixups[] = { | |||
1906 | [STAC_92HD73XX_NO_JD] = { | 1921 | [STAC_92HD73XX_NO_JD] = { |
1907 | .type = HDA_FIXUP_FUNC, | 1922 | .type = HDA_FIXUP_FUNC, |
1908 | .v.func = stac92hd73xx_fixup_no_jd, | 1923 | .v.func = stac92hd73xx_fixup_no_jd, |
1924 | }, | ||
1925 | [STAC_92HD89XX_HP_FRONT_JACK] = { | ||
1926 | .type = HDA_FIXUP_PINS, | ||
1927 | .v.pins = stac92hd89xx_hp_front_jack_pin_configs, | ||
1909 | } | 1928 | } |
1910 | }; | 1929 | }; |
1911 | 1930 | ||
@@ -1966,6 +1985,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = { | |||
1966 | "Alienware M17x", STAC_ALIENWARE_M17X), | 1985 | "Alienware M17x", STAC_ALIENWARE_M17X), |
1967 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, | 1986 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, |
1968 | "Alienware M17x R3", STAC_DELL_EQ), | 1987 | "Alienware M17x R3", STAC_DELL_EQ), |
1988 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, | ||
1989 | "unknown HP", STAC_92HD89XX_HP_FRONT_JACK), | ||
1969 | {} /* terminator */ | 1990 | {} /* terminator */ |
1970 | }; | 1991 | }; |
1971 | 1992 | ||
@@ -2110,6 +2131,17 @@ static void stac92hd83xxx_fixup_hp_mic_led(struct hda_codec *codec, | |||
2110 | } | 2131 | } |
2111 | } | 2132 | } |
2112 | 2133 | ||
2134 | static void stac92hd83xxx_fixup_hp_led_gpio10(struct hda_codec *codec, | ||
2135 | const struct hda_fixup *fix, int action) | ||
2136 | { | ||
2137 | struct sigmatel_spec *spec = codec->spec; | ||
2138 | |||
2139 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
2140 | spec->gpio_led = 0x10; /* GPIO4 */ | ||
2141 | spec->default_polarity = 0; | ||
2142 | } | ||
2143 | } | ||
2144 | |||
2113 | static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec, | 2145 | static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec, |
2114 | const struct hda_fixup *fix, int action) | 2146 | const struct hda_fixup *fix, int action) |
2115 | { | 2147 | { |
@@ -2604,6 +2636,12 @@ static const struct hda_fixup stac92hd83xxx_fixups[] = { | |||
2604 | .chained = true, | 2636 | .chained = true, |
2605 | .chain_id = STAC_92HD83XXX_HP, | 2637 | .chain_id = STAC_92HD83XXX_HP, |
2606 | }, | 2638 | }, |
2639 | [STAC_HP_LED_GPIO10] = { | ||
2640 | .type = HDA_FIXUP_FUNC, | ||
2641 | .v.func = stac92hd83xxx_fixup_hp_led_gpio10, | ||
2642 | .chained = true, | ||
2643 | .chain_id = STAC_92HD83XXX_HP, | ||
2644 | }, | ||
2607 | [STAC_92HD83XXX_HEADSET_JACK] = { | 2645 | [STAC_92HD83XXX_HEADSET_JACK] = { |
2608 | .type = HDA_FIXUP_FUNC, | 2646 | .type = HDA_FIXUP_FUNC, |
2609 | .v.func = stac92hd83xxx_fixup_headset_jack, | 2647 | .v.func = stac92hd83xxx_fixup_headset_jack, |
@@ -2682,6 +2720,8 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = { | |||
2682 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2720 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2683 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1888, | 2721 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1888, |
2684 | "HP Envy Spectre", STAC_HP_ENVY_BASS), | 2722 | "HP Envy Spectre", STAC_HP_ENVY_BASS), |
2723 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1899, | ||
2724 | "HP Folio 13", STAC_HP_LED_GPIO10), | ||
2685 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18df, | 2725 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18df, |
2686 | "HP Folio", STAC_HP_BNB13_EQ), | 2726 | "HP Folio", STAC_HP_BNB13_EQ), |
2687 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18F8, | 2727 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18F8, |
@@ -4462,7 +4502,7 @@ static void stac_setup_gpio(struct hda_codec *codec) | |||
4462 | if (spec->mic_mute_led_gpio) { | 4502 | if (spec->mic_mute_led_gpio) { |
4463 | spec->gpio_mask |= spec->mic_mute_led_gpio; | 4503 | spec->gpio_mask |= spec->mic_mute_led_gpio; |
4464 | spec->gpio_dir |= spec->mic_mute_led_gpio; | 4504 | spec->gpio_dir |= spec->mic_mute_led_gpio; |
4465 | spec->mic_mute_led_on = true; | 4505 | spec->mic_enabled = 0; |
4466 | spec->gpio_data |= spec->mic_mute_led_gpio; | 4506 | spec->gpio_data |= spec->mic_mute_led_gpio; |
4467 | 4507 | ||
4468 | spec->gen.cap_sync_hook = stac_capture_led_hook; | 4508 | spec->gen.cap_sync_hook = stac_capture_led_hook; |
diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c index 5799fbc24c28..8fe3b8c18ed4 100644 --- a/sound/pci/hda/thinkpad_helper.c +++ b/sound/pci/hda/thinkpad_helper.c | |||
@@ -39,6 +39,7 @@ static void update_tpacpi_mute_led(void *private_data, int enabled) | |||
39 | } | 39 | } |
40 | 40 | ||
41 | static void update_tpacpi_micmute_led(struct hda_codec *codec, | 41 | static void update_tpacpi_micmute_led(struct hda_codec *codec, |
42 | struct snd_kcontrol *kcontrol, | ||
42 | struct snd_ctl_elem_value *ucontrol) | 43 | struct snd_ctl_elem_value *ucontrol) |
43 | { | 44 | { |
44 | if (!ucontrol || !led_set_func) | 45 | if (!ucontrol || !led_set_func) |
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index d62ce483a443..0060b31cc3f3 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -50,6 +50,7 @@ source "sound/soc/pxa/Kconfig" | |||
50 | source "sound/soc/samsung/Kconfig" | 50 | source "sound/soc/samsung/Kconfig" |
51 | source "sound/soc/s6000/Kconfig" | 51 | source "sound/soc/s6000/Kconfig" |
52 | source "sound/soc/sh/Kconfig" | 52 | source "sound/soc/sh/Kconfig" |
53 | source "sound/soc/sirf/Kconfig" | ||
53 | source "sound/soc/spear/Kconfig" | 54 | source "sound/soc/spear/Kconfig" |
54 | source "sound/soc/tegra/Kconfig" | 55 | source "sound/soc/tegra/Kconfig" |
55 | source "sound/soc/txx9/Kconfig" | 56 | source "sound/soc/txx9/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 62a1822e77bf..5f1df02984f8 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -27,6 +27,7 @@ obj-$(CONFIG_SND_SOC) += pxa/ | |||
27 | obj-$(CONFIG_SND_SOC) += samsung/ | 27 | obj-$(CONFIG_SND_SOC) += samsung/ |
28 | obj-$(CONFIG_SND_SOC) += s6000/ | 28 | obj-$(CONFIG_SND_SOC) += s6000/ |
29 | obj-$(CONFIG_SND_SOC) += sh/ | 29 | obj-$(CONFIG_SND_SOC) += sh/ |
30 | obj-$(CONFIG_SND_SOC) += sirf/ | ||
30 | obj-$(CONFIG_SND_SOC) += spear/ | 31 | obj-$(CONFIG_SND_SOC) += spear/ |
31 | obj-$(CONFIG_SND_SOC) += tegra/ | 32 | obj-$(CONFIG_SND_SOC) += tegra/ |
32 | obj-$(CONFIG_SND_SOC) += txx9/ | 33 | obj-$(CONFIG_SND_SOC) += txx9/ |
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index e634eb78ed03..4789619a52d8 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig | |||
@@ -58,6 +58,6 @@ config SND_AT91_SOC_AFEB9260 | |||
58 | depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC | 58 | depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC |
59 | select SND_ATMEL_SOC_PDC | 59 | select SND_ATMEL_SOC_PDC |
60 | select SND_ATMEL_SOC_SSC | 60 | select SND_ATMEL_SOC_SSC |
61 | select SND_SOC_TLV320AIC23 | 61 | select SND_SOC_TLV320AIC23_I2C |
62 | help | 62 | help |
63 | Say Y here to support sound on AFEB9260 board. | 63 | Say Y here to support sound on AFEB9260 board. |
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 1ead3c977a51..de433cfd044c 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -341,6 +341,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
341 | { | 341 | { |
342 | int id = dai->id; | 342 | int id = dai->id; |
343 | struct atmel_ssc_info *ssc_p = &ssc_info[id]; | 343 | struct atmel_ssc_info *ssc_p = &ssc_info[id]; |
344 | struct ssc_device *ssc = ssc_p->ssc; | ||
344 | struct atmel_pcm_dma_params *dma_params; | 345 | struct atmel_pcm_dma_params *dma_params; |
345 | int dir, channels, bits; | 346 | int dir, channels, bits; |
346 | u32 tfmr, rfmr, tcmr, rcmr; | 347 | u32 tfmr, rfmr, tcmr, rcmr; |
@@ -466,7 +467,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
466 | | SSC_BF(RCMR_START, start_event) | 467 | | SSC_BF(RCMR_START, start_event) |
467 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | 468 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
468 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | 469 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
469 | | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK); | 470 | | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? |
471 | SSC_CKS_PIN : SSC_CKS_CLOCK); | ||
470 | 472 | ||
471 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | 473 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
472 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) | 474 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) |
@@ -481,7 +483,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
481 | | SSC_BF(TCMR_START, start_event) | 483 | | SSC_BF(TCMR_START, start_event) |
482 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | 484 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
483 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | 485 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE) |
484 | | SSC_BF(TCMR_CKS, SSC_CKS_PIN); | 486 | | SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ? |
487 | SSC_CKS_CLOCK : SSC_CKS_PIN); | ||
485 | 488 | ||
486 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | 489 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
487 | | SSC_BF(TFMR_FSDEN, 0) | 490 | | SSC_BF(TFMR_FSDEN, 0) |
@@ -550,7 +553,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
550 | | SSC_BF(RCMR_START, SSC_START_RISING_RF) | 553 | | SSC_BF(RCMR_START, SSC_START_RISING_RF) |
551 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | 554 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
552 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | 555 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
553 | | SSC_BF(RCMR_CKS, SSC_CKS_PIN); | 556 | | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? |
557 | SSC_CKS_PIN : SSC_CKS_CLOCK); | ||
554 | 558 | ||
555 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | 559 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
556 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) | 560 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) |
@@ -565,7 +569,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
565 | | SSC_BF(TCMR_START, SSC_START_RISING_RF) | 569 | | SSC_BF(TCMR_START, SSC_START_RISING_RF) |
566 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | 570 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
567 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | 571 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE) |
568 | | SSC_BF(TCMR_CKS, SSC_CKS_PIN); | 572 | | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? |
573 | SSC_CKS_CLOCK : SSC_CKS_PIN); | ||
569 | 574 | ||
570 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | 575 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
571 | | SSC_BF(TFMR_FSDEN, 0) | 576 | | SSC_BF(TFMR_FSDEN, 0) |
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index f15bff1548f8..174bd546c08b 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c | |||
@@ -155,25 +155,14 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) | |||
155 | return ret; | 155 | return ret; |
156 | } | 156 | } |
157 | 157 | ||
158 | /* Add specific widgets */ | ||
159 | snd_soc_dapm_new_controls(dapm, at91sam9g20ek_dapm_widgets, | ||
160 | ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); | ||
161 | /* Set up specific audio path interconnects */ | ||
162 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
163 | |||
164 | /* not connected */ | 158 | /* not connected */ |
165 | snd_soc_dapm_nc_pin(dapm, "RLINEIN"); | 159 | snd_soc_dapm_nc_pin(dapm, "RLINEIN"); |
166 | snd_soc_dapm_nc_pin(dapm, "LLINEIN"); | 160 | snd_soc_dapm_nc_pin(dapm, "LLINEIN"); |
167 | 161 | ||
168 | #ifdef ENABLE_MIC_INPUT | 162 | #ifndef ENABLE_MIC_INPUT |
169 | snd_soc_dapm_enable_pin(dapm, "Int Mic"); | 163 | snd_soc_dapm_nc_pin(&rtd->card->dapm, "Int Mic"); |
170 | #else | ||
171 | snd_soc_dapm_nc_pin(dapm, "Int Mic"); | ||
172 | #endif | 164 | #endif |
173 | 165 | ||
174 | /* always connected */ | ||
175 | snd_soc_dapm_enable_pin(dapm, "Ext Spk"); | ||
176 | |||
177 | return 0; | 166 | return 0; |
178 | } | 167 | } |
179 | 168 | ||
@@ -194,6 +183,11 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = { | |||
194 | .dai_link = &at91sam9g20ek_dai, | 183 | .dai_link = &at91sam9g20ek_dai, |
195 | .num_links = 1, | 184 | .num_links = 1, |
196 | .set_bias_level = at91sam9g20ek_set_bias_level, | 185 | .set_bias_level = at91sam9g20ek_set_bias_level, |
186 | |||
187 | .dapm_widgets = at91sam9g20ek_dapm_widgets, | ||
188 | .num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets), | ||
189 | .dapm_routes = intercon, | ||
190 | .num_dapm_routes = ARRAY_SIZE(intercon), | ||
197 | }; | 191 | }; |
198 | 192 | ||
199 | static int at91sam9g20ek_audio_probe(struct platform_device *pdev) | 193 | static int at91sam9g20ek_audio_probe(struct platform_device *pdev) |
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 54f74f8cbb75..6347d5910138 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig | |||
@@ -11,20 +11,20 @@ config SND_BF5XX_I2S | |||
11 | 11 | ||
12 | config SND_BF5XX_SOC_SSM2602 | 12 | config SND_BF5XX_SOC_SSM2602 |
13 | tristate "SoC SSM2602 Audio Codec Add-On Card support" | 13 | tristate "SoC SSM2602 Audio Codec Add-On Card support" |
14 | depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) | 14 | depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI |
15 | select SND_BF5XX_SOC_I2S if !BF60x | 15 | select SND_BF5XX_SOC_I2S if !BF60x |
16 | select SND_BF6XX_SOC_I2S if BF60x | 16 | select SND_BF6XX_SOC_I2S if BF60x |
17 | select SND_SOC_SSM2602 | 17 | select SND_SOC_SSM2602_SPI if SPI_MASTER |
18 | select SND_SOC_SSM2602_I2C if I2C | ||
18 | help | 19 | help |
19 | Say Y if you want to add support for the Analog Devices | 20 | Say Y if you want to add support for the Analog Devices |
20 | SSM2602 Audio Codec Add-On Card. | 21 | SSM2602 Audio Codec Add-On Card. |
21 | 22 | ||
22 | config SND_SOC_BFIN_EVAL_ADAU1701 | 23 | config SND_SOC_BFIN_EVAL_ADAU1701 |
23 | tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards" | 24 | tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards" |
24 | depends on SND_BF5XX_I2S | 25 | depends on SND_BF5XX_I2S && I2C |
25 | select SND_BF5XX_SOC_I2S | 26 | select SND_BF5XX_SOC_I2S |
26 | select SND_SOC_ADAU1701 | 27 | select SND_SOC_ADAU1701 |
27 | select I2C | ||
28 | help | 28 | help |
29 | Say Y if you want to add support for the Analog Devices EVAL-ADAU1701MINIZ | 29 | Say Y if you want to add support for the Analog Devices EVAL-ADAU1701MINIZ |
30 | board connected to one of the Blackfin evaluation boards like the | 30 | board connected to one of the Blackfin evaluation boards like the |
@@ -45,9 +45,10 @@ config SND_SOC_BFIN_EVAL_ADAU1373 | |||
45 | 45 | ||
46 | config SND_SOC_BFIN_EVAL_ADAV80X | 46 | config SND_SOC_BFIN_EVAL_ADAV80X |
47 | tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards" | 47 | tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards" |
48 | depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) | 48 | depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI |
49 | select SND_BF5XX_SOC_I2S | 49 | select SND_BF5XX_SOC_I2S |
50 | select SND_SOC_ADAV80X | 50 | select SND_SOC_ADAV801 if SPI_MASTER |
51 | select SND_SOC_ADAV803 if I2C | ||
51 | help | 52 | help |
52 | Say Y if you want to add support for the Analog Devices EVAL-ADAV801 or | 53 | Say Y if you want to add support for the Analog Devices EVAL-ADAV801 or |
53 | EVAL-ADAV803 board connected to one of the Blackfin evaluation boards | 54 | EVAL-ADAV803 board connected to one of the Blackfin evaluation boards |
@@ -58,7 +59,7 @@ config SND_SOC_BFIN_EVAL_ADAV80X | |||
58 | 59 | ||
59 | config SND_BF5XX_SOC_AD1836 | 60 | config SND_BF5XX_SOC_AD1836 |
60 | tristate "SoC AD1836 Audio support for BF5xx" | 61 | tristate "SoC AD1836 Audio support for BF5xx" |
61 | depends on SND_BF5XX_I2S | 62 | depends on SND_BF5XX_I2S && SPI_MASTER |
62 | select SND_BF5XX_SOC_I2S | 63 | select SND_BF5XX_SOC_I2S |
63 | select SND_SOC_AD1836 | 64 | select SND_SOC_AD1836 |
64 | help | 65 | help |
@@ -66,9 +67,10 @@ config SND_BF5XX_SOC_AD1836 | |||
66 | 67 | ||
67 | config SND_BF5XX_SOC_AD193X | 68 | config SND_BF5XX_SOC_AD193X |
68 | tristate "SoC AD193X Audio support for Blackfin" | 69 | tristate "SoC AD193X Audio support for Blackfin" |
69 | depends on SND_BF5XX_I2S | 70 | depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI |
70 | select SND_BF5XX_SOC_I2S | 71 | select SND_BF5XX_SOC_I2S |
71 | select SND_SOC_AD193X | 72 | select SND_SOC_AD193X_I2C if I2C |
73 | select SND_SOC_AD193X_SPI if SPI_MASTER | ||
72 | help | 74 | help |
73 | Say Y if you want to add support for AD193X codec on Blackfin. | 75 | Say Y if you want to add support for AD193X codec on Blackfin. |
74 | This driver supports AD1936, AD1937, AD1938 and AD1939. | 76 | This driver supports AD1936, AD1937, AD1938 and AD1939. |
diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 06f938deda15..5477c5475923 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config SND_EP93XX_SOC | 1 | config SND_EP93XX_SOC |
2 | tristate "SoC Audio support for the Cirrus Logic EP93xx series" | 2 | tristate "SoC Audio support for the Cirrus Logic EP93xx series" |
3 | depends on (ARCH_EP93XX || COMPILE_TEST) && SND_SOC | 3 | depends on ARCH_EP93XX || COMPILE_TEST |
4 | select SND_SOC_GENERIC_DMAENGINE_PCM | 4 | select SND_SOC_GENERIC_DMAENGINE_PCM |
5 | help | 5 | help |
6 | Say Y or M if you want to add support for codecs attached to | 6 | Say Y or M if you want to add support for codecs attached to |
@@ -18,7 +18,7 @@ config SND_EP93XX_SOC_SNAPPERCL15 | |||
18 | tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" | 18 | tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" |
19 | depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 | 19 | depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 |
20 | select SND_EP93XX_SOC_I2S | 20 | select SND_EP93XX_SOC_I2S |
21 | select SND_SOC_TLV320AIC23 | 21 | select SND_SOC_TLV320AIC23_I2C |
22 | help | 22 | help |
23 | Say Y or M here if you want to add support for I2S audio on the | 23 | Say Y or M here if you want to add support for I2S audio on the |
24 | Bluewater Systems Snapper CL15 module. | 24 | Bluewater Systems Snapper CL15 module. |
diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c index 29238a7476dd..5b68b106cfc2 100644 --- a/sound/soc/cirrus/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c | |||
@@ -65,18 +65,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
65 | {"MICIN", NULL, "Mic Jack"}, | 65 | {"MICIN", NULL, "Mic Jack"}, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) | ||
69 | { | ||
70 | struct snd_soc_codec *codec = rtd->codec; | ||
71 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
72 | |||
73 | snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets, | ||
74 | ARRAY_SIZE(tlv320aic23_dapm_widgets)); | ||
75 | |||
76 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static struct snd_soc_dai_link snappercl15_dai = { | 68 | static struct snd_soc_dai_link snappercl15_dai = { |
81 | .name = "tlv320aic23", | 69 | .name = "tlv320aic23", |
82 | .stream_name = "AIC23", | 70 | .stream_name = "AIC23", |
@@ -84,7 +72,6 @@ static struct snd_soc_dai_link snappercl15_dai = { | |||
84 | .codec_dai_name = "tlv320aic23-hifi", | 72 | .codec_dai_name = "tlv320aic23-hifi", |
85 | .codec_name = "tlv320aic23-codec.0-001a", | 73 | .codec_name = "tlv320aic23-codec.0-001a", |
86 | .platform_name = "ep93xx-i2s", | 74 | .platform_name = "ep93xx-i2s", |
87 | .init = snappercl15_tlv320aic23_init, | ||
88 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | | 75 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | |
89 | SND_SOC_DAIFMT_CBS_CFS, | 76 | SND_SOC_DAIFMT_CBS_CFS, |
90 | .ops = &snappercl15_ops, | 77 | .ops = &snappercl15_ops, |
@@ -95,6 +82,11 @@ static struct snd_soc_card snd_soc_snappercl15 = { | |||
95 | .owner = THIS_MODULE, | 82 | .owner = THIS_MODULE, |
96 | .dai_link = &snappercl15_dai, | 83 | .dai_link = &snappercl15_dai, |
97 | .num_links = 1, | 84 | .num_links = 1, |
85 | |||
86 | .dapm_widgets = tlv320aic23_dapm_widgets, | ||
87 | .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), | ||
88 | .dapm_routes = audio_map, | ||
89 | .num_dapm_routes = ARRAY_SIZE(audio_map), | ||
98 | }; | 90 | }; |
99 | 91 | ||
100 | static int snappercl15_probe(struct platform_device *pdev) | 92 | static int snappercl15_probe(struct platform_device *pdev) |
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 75d0ad5d2dcb..b07e17160f94 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c | |||
@@ -448,38 +448,38 @@ static const char *pm860x_opamp_texts[] = {"-50%", "-25%", "0%", "75%"}; | |||
448 | 448 | ||
449 | static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"}; | 449 | static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"}; |
450 | 450 | ||
451 | static const struct soc_enum pm860x_hs1_opamp_enum = | 451 | static SOC_ENUM_SINGLE_DECL(pm860x_hs1_opamp_enum, |
452 | SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 5, 4, pm860x_opamp_texts); | 452 | PM860X_HS1_CTRL, 5, pm860x_opamp_texts); |
453 | 453 | ||
454 | static const struct soc_enum pm860x_hs2_opamp_enum = | 454 | static SOC_ENUM_SINGLE_DECL(pm860x_hs2_opamp_enum, |
455 | SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 5, 4, pm860x_opamp_texts); | 455 | PM860X_HS2_CTRL, 5, pm860x_opamp_texts); |
456 | 456 | ||
457 | static const struct soc_enum pm860x_hs1_pa_enum = | 457 | static SOC_ENUM_SINGLE_DECL(pm860x_hs1_pa_enum, |
458 | SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 3, 4, pm860x_pa_texts); | 458 | PM860X_HS1_CTRL, 3, pm860x_pa_texts); |
459 | 459 | ||
460 | static const struct soc_enum pm860x_hs2_pa_enum = | 460 | static SOC_ENUM_SINGLE_DECL(pm860x_hs2_pa_enum, |
461 | SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 3, 4, pm860x_pa_texts); | 461 | PM860X_HS2_CTRL, 3, pm860x_pa_texts); |
462 | 462 | ||
463 | static const struct soc_enum pm860x_lo1_opamp_enum = | 463 | static SOC_ENUM_SINGLE_DECL(pm860x_lo1_opamp_enum, |
464 | SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 5, 4, pm860x_opamp_texts); | 464 | PM860X_LO1_CTRL, 5, pm860x_opamp_texts); |
465 | 465 | ||
466 | static const struct soc_enum pm860x_lo2_opamp_enum = | 466 | static SOC_ENUM_SINGLE_DECL(pm860x_lo2_opamp_enum, |
467 | SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 5, 4, pm860x_opamp_texts); | 467 | PM860X_LO2_CTRL, 5, pm860x_opamp_texts); |
468 | 468 | ||
469 | static const struct soc_enum pm860x_lo1_pa_enum = | 469 | static SOC_ENUM_SINGLE_DECL(pm860x_lo1_pa_enum, |
470 | SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 3, 4, pm860x_pa_texts); | 470 | PM860X_LO1_CTRL, 3, pm860x_pa_texts); |
471 | 471 | ||
472 | static const struct soc_enum pm860x_lo2_pa_enum = | 472 | static SOC_ENUM_SINGLE_DECL(pm860x_lo2_pa_enum, |
473 | SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 3, 4, pm860x_pa_texts); | 473 | PM860X_LO2_CTRL, 3, pm860x_pa_texts); |
474 | 474 | ||
475 | static const struct soc_enum pm860x_spk_pa_enum = | 475 | static SOC_ENUM_SINGLE_DECL(pm860x_spk_pa_enum, |
476 | SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 5, 4, pm860x_pa_texts); | 476 | PM860X_EAR_CTRL_1, 5, pm860x_pa_texts); |
477 | 477 | ||
478 | static const struct soc_enum pm860x_ear_pa_enum = | 478 | static SOC_ENUM_SINGLE_DECL(pm860x_ear_pa_enum, |
479 | SOC_ENUM_SINGLE(PM860X_EAR_CTRL_2, 0, 4, pm860x_pa_texts); | 479 | PM860X_EAR_CTRL_2, 0, pm860x_pa_texts); |
480 | 480 | ||
481 | static const struct soc_enum pm860x_spk_ear_opamp_enum = | 481 | static SOC_ENUM_SINGLE_DECL(pm860x_spk_ear_opamp_enum, |
482 | SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 3, 4, pm860x_opamp_texts); | 482 | PM860X_EAR_CTRL_1, 3, pm860x_opamp_texts); |
483 | 483 | ||
484 | static const struct snd_kcontrol_new pm860x_snd_controls[] = { | 484 | static const struct snd_kcontrol_new pm860x_snd_controls[] = { |
485 | SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2, | 485 | SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2, |
@@ -561,8 +561,8 @@ static const char *aif1_text[] = { | |||
561 | "PCM L", "PCM R", | 561 | "PCM L", "PCM R", |
562 | }; | 562 | }; |
563 | 563 | ||
564 | static const struct soc_enum aif1_enum = | 564 | static SOC_ENUM_SINGLE_DECL(aif1_enum, |
565 | SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 6, 2, aif1_text); | 565 | PM860X_PCM_IFACE_3, 6, aif1_text); |
566 | 566 | ||
567 | static const struct snd_kcontrol_new aif1_mux = | 567 | static const struct snd_kcontrol_new aif1_mux = |
568 | SOC_DAPM_ENUM("PCM Mux", aif1_enum); | 568 | SOC_DAPM_ENUM("PCM Mux", aif1_enum); |
@@ -572,8 +572,8 @@ static const char *i2s_din_text[] = { | |||
572 | "DIN", "DIN1", | 572 | "DIN", "DIN1", |
573 | }; | 573 | }; |
574 | 574 | ||
575 | static const struct soc_enum i2s_din_enum = | 575 | static SOC_ENUM_SINGLE_DECL(i2s_din_enum, |
576 | SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 1, 2, i2s_din_text); | 576 | PM860X_I2S_IFACE_3, 1, i2s_din_text); |
577 | 577 | ||
578 | static const struct snd_kcontrol_new i2s_din_mux = | 578 | static const struct snd_kcontrol_new i2s_din_mux = |
579 | SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum); | 579 | SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum); |
@@ -583,8 +583,8 @@ static const char *i2s_mic_text[] = { | |||
583 | "Ex PA", "ADC", | 583 | "Ex PA", "ADC", |
584 | }; | 584 | }; |
585 | 585 | ||
586 | static const struct soc_enum i2s_mic_enum = | 586 | static SOC_ENUM_SINGLE_DECL(i2s_mic_enum, |
587 | SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 4, 2, i2s_mic_text); | 587 | PM860X_I2S_IFACE_3, 4, i2s_mic_text); |
588 | 588 | ||
589 | static const struct snd_kcontrol_new i2s_mic_mux = | 589 | static const struct snd_kcontrol_new i2s_mic_mux = |
590 | SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum); | 590 | SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum); |
@@ -594,8 +594,8 @@ static const char *adcl_text[] = { | |||
594 | "ADCR", "ADCL", | 594 | "ADCR", "ADCL", |
595 | }; | 595 | }; |
596 | 596 | ||
597 | static const struct soc_enum adcl_enum = | 597 | static SOC_ENUM_SINGLE_DECL(adcl_enum, |
598 | SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 4, 2, adcl_text); | 598 | PM860X_PCM_IFACE_3, 4, adcl_text); |
599 | 599 | ||
600 | static const struct snd_kcontrol_new adcl_mux = | 600 | static const struct snd_kcontrol_new adcl_mux = |
601 | SOC_DAPM_ENUM("ADC Left Mux", adcl_enum); | 601 | SOC_DAPM_ENUM("ADC Left Mux", adcl_enum); |
@@ -605,8 +605,8 @@ static const char *adcr_text[] = { | |||
605 | "ADCL", "ADCR", | 605 | "ADCL", "ADCR", |
606 | }; | 606 | }; |
607 | 607 | ||
608 | static const struct soc_enum adcr_enum = | 608 | static SOC_ENUM_SINGLE_DECL(adcr_enum, |
609 | SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 2, 2, adcr_text); | 609 | PM860X_PCM_IFACE_3, 2, adcr_text); |
610 | 610 | ||
611 | static const struct snd_kcontrol_new adcr_mux = | 611 | static const struct snd_kcontrol_new adcr_mux = |
612 | SOC_DAPM_ENUM("ADC Right Mux", adcr_enum); | 612 | SOC_DAPM_ENUM("ADC Right Mux", adcr_enum); |
@@ -616,8 +616,8 @@ static const char *adcr_ec_text[] = { | |||
616 | "ADCR", "EC", | 616 | "ADCR", "EC", |
617 | }; | 617 | }; |
618 | 618 | ||
619 | static const struct soc_enum adcr_ec_enum = | 619 | static SOC_ENUM_SINGLE_DECL(adcr_ec_enum, |
620 | SOC_ENUM_SINGLE(PM860X_ADC_EN_2, 3, 2, adcr_ec_text); | 620 | PM860X_ADC_EN_2, 3, adcr_ec_text); |
621 | 621 | ||
622 | static const struct snd_kcontrol_new adcr_ec_mux = | 622 | static const struct snd_kcontrol_new adcr_ec_mux = |
623 | SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum); | 623 | SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum); |
@@ -627,8 +627,8 @@ static const char *ec_text[] = { | |||
627 | "Left", "Right", "Left + Right", | 627 | "Left", "Right", "Left + Right", |
628 | }; | 628 | }; |
629 | 629 | ||
630 | static const struct soc_enum ec_enum = | 630 | static SOC_ENUM_SINGLE_DECL(ec_enum, |
631 | SOC_ENUM_SINGLE(PM860X_EC_PATH, 1, 3, ec_text); | 631 | PM860X_EC_PATH, 1, ec_text); |
632 | 632 | ||
633 | static const struct snd_kcontrol_new ec_mux = | 633 | static const struct snd_kcontrol_new ec_mux = |
634 | SOC_DAPM_ENUM("EC Mux", ec_enum); | 634 | SOC_DAPM_ENUM("EC Mux", ec_enum); |
@@ -638,36 +638,36 @@ static const char *dac_text[] = { | |||
638 | }; | 638 | }; |
639 | 639 | ||
640 | /* DAC Headset 1 Mux / Mux10 */ | 640 | /* DAC Headset 1 Mux / Mux10 */ |
641 | static const struct soc_enum dac_hs1_enum = | 641 | static SOC_ENUM_SINGLE_DECL(dac_hs1_enum, |
642 | SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 0, 4, dac_text); | 642 | PM860X_ANA_INPUT_SEL_1, 0, dac_text); |
643 | 643 | ||
644 | static const struct snd_kcontrol_new dac_hs1_mux = | 644 | static const struct snd_kcontrol_new dac_hs1_mux = |
645 | SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum); | 645 | SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum); |
646 | 646 | ||
647 | /* DAC Headset 2 Mux / Mux11 */ | 647 | /* DAC Headset 2 Mux / Mux11 */ |
648 | static const struct soc_enum dac_hs2_enum = | 648 | static SOC_ENUM_SINGLE_DECL(dac_hs2_enum, |
649 | SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 2, 4, dac_text); | 649 | PM860X_ANA_INPUT_SEL_1, 2, dac_text); |
650 | 650 | ||
651 | static const struct snd_kcontrol_new dac_hs2_mux = | 651 | static const struct snd_kcontrol_new dac_hs2_mux = |
652 | SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum); | 652 | SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum); |
653 | 653 | ||
654 | /* DAC Lineout 1 Mux / Mux12 */ | 654 | /* DAC Lineout 1 Mux / Mux12 */ |
655 | static const struct soc_enum dac_lo1_enum = | 655 | static SOC_ENUM_SINGLE_DECL(dac_lo1_enum, |
656 | SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 4, 4, dac_text); | 656 | PM860X_ANA_INPUT_SEL_1, 4, dac_text); |
657 | 657 | ||
658 | static const struct snd_kcontrol_new dac_lo1_mux = | 658 | static const struct snd_kcontrol_new dac_lo1_mux = |
659 | SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum); | 659 | SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum); |
660 | 660 | ||
661 | /* DAC Lineout 2 Mux / Mux13 */ | 661 | /* DAC Lineout 2 Mux / Mux13 */ |
662 | static const struct soc_enum dac_lo2_enum = | 662 | static SOC_ENUM_SINGLE_DECL(dac_lo2_enum, |
663 | SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 6, 4, dac_text); | 663 | PM860X_ANA_INPUT_SEL_1, 6, dac_text); |
664 | 664 | ||
665 | static const struct snd_kcontrol_new dac_lo2_mux = | 665 | static const struct snd_kcontrol_new dac_lo2_mux = |
666 | SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum); | 666 | SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum); |
667 | 667 | ||
668 | /* DAC Spearker Earphone Mux / Mux14 */ | 668 | /* DAC Spearker Earphone Mux / Mux14 */ |
669 | static const struct soc_enum dac_spk_ear_enum = | 669 | static SOC_ENUM_SINGLE_DECL(dac_spk_ear_enum, |
670 | SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_2, 0, 4, dac_text); | 670 | PM860X_ANA_INPUT_SEL_2, 0, dac_text); |
671 | 671 | ||
672 | static const struct snd_kcontrol_new dac_spk_ear_mux = | 672 | static const struct snd_kcontrol_new dac_spk_ear_mux = |
673 | SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum); | 673 | SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum); |
@@ -677,29 +677,29 @@ static const char *in_text[] = { | |||
677 | "Digital", "Analog", | 677 | "Digital", "Analog", |
678 | }; | 678 | }; |
679 | 679 | ||
680 | static const struct soc_enum hs1_enum = | 680 | static SOC_ENUM_SINGLE_DECL(hs1_enum, |
681 | SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 0, 2, in_text); | 681 | PM860X_ANA_TO_ANA, 0, in_text); |
682 | 682 | ||
683 | static const struct snd_kcontrol_new hs1_mux = | 683 | static const struct snd_kcontrol_new hs1_mux = |
684 | SOC_DAPM_ENUM("Headset1 Mux", hs1_enum); | 684 | SOC_DAPM_ENUM("Headset1 Mux", hs1_enum); |
685 | 685 | ||
686 | /* Headset 2 Mux / Mux16 */ | 686 | /* Headset 2 Mux / Mux16 */ |
687 | static const struct soc_enum hs2_enum = | 687 | static SOC_ENUM_SINGLE_DECL(hs2_enum, |
688 | SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 1, 2, in_text); | 688 | PM860X_ANA_TO_ANA, 1, in_text); |
689 | 689 | ||
690 | static const struct snd_kcontrol_new hs2_mux = | 690 | static const struct snd_kcontrol_new hs2_mux = |
691 | SOC_DAPM_ENUM("Headset2 Mux", hs2_enum); | 691 | SOC_DAPM_ENUM("Headset2 Mux", hs2_enum); |
692 | 692 | ||
693 | /* Lineout 1 Mux / Mux17 */ | 693 | /* Lineout 1 Mux / Mux17 */ |
694 | static const struct soc_enum lo1_enum = | 694 | static SOC_ENUM_SINGLE_DECL(lo1_enum, |
695 | SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 2, 2, in_text); | 695 | PM860X_ANA_TO_ANA, 2, in_text); |
696 | 696 | ||
697 | static const struct snd_kcontrol_new lo1_mux = | 697 | static const struct snd_kcontrol_new lo1_mux = |
698 | SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum); | 698 | SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum); |
699 | 699 | ||
700 | /* Lineout 2 Mux / Mux18 */ | 700 | /* Lineout 2 Mux / Mux18 */ |
701 | static const struct soc_enum lo2_enum = | 701 | static SOC_ENUM_SINGLE_DECL(lo2_enum, |
702 | SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 3, 2, in_text); | 702 | PM860X_ANA_TO_ANA, 3, in_text); |
703 | 703 | ||
704 | static const struct snd_kcontrol_new lo2_mux = | 704 | static const struct snd_kcontrol_new lo2_mux = |
705 | SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum); | 705 | SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum); |
@@ -709,8 +709,8 @@ static const char *spk_text[] = { | |||
709 | "Earpiece", "Speaker", | 709 | "Earpiece", "Speaker", |
710 | }; | 710 | }; |
711 | 711 | ||
712 | static const struct soc_enum spk_enum = | 712 | static SOC_ENUM_SINGLE_DECL(spk_enum, |
713 | SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 6, 2, spk_text); | 713 | PM860X_ANA_TO_ANA, 6, spk_text); |
714 | 714 | ||
715 | static const struct snd_kcontrol_new spk_demux = | 715 | static const struct snd_kcontrol_new spk_demux = |
716 | SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum); | 716 | SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum); |
@@ -720,8 +720,8 @@ static const char *mic_text[] = { | |||
720 | "Mic 1", "Mic 2", | 720 | "Mic 1", "Mic 2", |
721 | }; | 721 | }; |
722 | 722 | ||
723 | static const struct soc_enum mic_enum = | 723 | static SOC_ENUM_SINGLE_DECL(mic_enum, |
724 | SOC_ENUM_SINGLE(PM860X_ADC_ANA_4, 4, 2, mic_text); | 724 | PM860X_ADC_ANA_4, 4, mic_text); |
725 | 725 | ||
726 | static const struct snd_kcontrol_new mic_mux = | 726 | static const struct snd_kcontrol_new mic_mux = |
727 | SOC_DAPM_ENUM("MIC Mux", mic_enum); | 727 | SOC_DAPM_ENUM("MIC Mux", mic_enum); |
@@ -1327,7 +1327,9 @@ static int pm860x_probe(struct snd_soc_codec *codec) | |||
1327 | 1327 | ||
1328 | pm860x->codec = codec; | 1328 | pm860x->codec = codec; |
1329 | 1329 | ||
1330 | codec->control_data = pm860x->regmap; | 1330 | ret = snd_soc_codec_set_cache_io(codec, pm860x->regmap); |
1331 | if (ret) | ||
1332 | return ret; | ||
1331 | 1333 | ||
1332 | for (i = 0; i < 4; i++) { | 1334 | for (i = 0; i < 4; i++) { |
1333 | ret = request_threaded_irq(pm860x->irq[i], NULL, | 1335 | ret = request_threaded_irq(pm860x->irq[i], NULL, |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..f0e840137887 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -8,6 +8,8 @@ config SND_SOC_I2C_AND_SPI | |||
8 | default y if I2C=y | 8 | default y if I2C=y |
9 | default y if SPI_MASTER=y | 9 | default y if SPI_MASTER=y |
10 | 10 | ||
11 | menu "CODEC drivers" | ||
12 | |||
11 | config SND_SOC_ALL_CODECS | 13 | config SND_SOC_ALL_CODECS |
12 | tristate "Build all ASoC CODEC drivers" | 14 | tristate "Build all ASoC CODEC drivers" |
13 | depends on COMPILE_TEST | 15 | depends on COMPILE_TEST |
@@ -16,15 +18,20 @@ config SND_SOC_ALL_CODECS | |||
16 | select SND_SOC_AB8500_CODEC if ABX500_CORE | 18 | select SND_SOC_AB8500_CODEC if ABX500_CORE |
17 | select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS | 19 | select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS |
18 | select SND_SOC_AD1836 if SPI_MASTER | 20 | select SND_SOC_AD1836 if SPI_MASTER |
19 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI | 21 | select SND_SOC_AD193X_SPI if SPI_MASTER |
22 | select SND_SOC_AD193X_I2C if I2C | ||
20 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS | 23 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS |
21 | select SND_SOC_AD73311 | 24 | select SND_SOC_AD73311 |
22 | select SND_SOC_ADAU1373 if I2C | 25 | select SND_SOC_ADAU1373 if I2C |
23 | select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI | 26 | select SND_SOC_ADAV801 if SPI_MASTER |
27 | select SND_SOC_ADAV803 if I2C | ||
28 | select SND_SOC_ADAU1977_SPI if SPI_MASTER | ||
29 | select SND_SOC_ADAU1977_I2C if I2C | ||
24 | select SND_SOC_ADAU1701 if I2C | 30 | select SND_SOC_ADAU1701 if I2C |
25 | select SND_SOC_ADS117X | 31 | select SND_SOC_ADS117X |
26 | select SND_SOC_AK4104 if SPI_MASTER | 32 | select SND_SOC_AK4104 if SPI_MASTER |
27 | select SND_SOC_AK4535 if I2C | 33 | select SND_SOC_AK4535 if I2C |
34 | select SND_SOC_AK4554 | ||
28 | select SND_SOC_AK4641 if I2C | 35 | select SND_SOC_AK4641 if I2C |
29 | select SND_SOC_AK4642 if I2C | 36 | select SND_SOC_AK4642 if I2C |
30 | select SND_SOC_AK4671 if I2C | 37 | select SND_SOC_AK4671 if I2C |
@@ -37,6 +44,7 @@ config SND_SOC_ALL_CODECS | |||
37 | select SND_SOC_CS42L73 if I2C | 44 | select SND_SOC_CS42L73 if I2C |
38 | select SND_SOC_CS4270 if I2C | 45 | select SND_SOC_CS4270 if I2C |
39 | select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI | 46 | select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI |
47 | select SND_SOC_CS42XX8_I2C if I2C | ||
40 | select SND_SOC_CX20442 if TTY | 48 | select SND_SOC_CX20442 if TTY |
41 | select SND_SOC_DA7210 if I2C | 49 | select SND_SOC_DA7210 if I2C |
42 | select SND_SOC_DA7213 if I2C | 50 | select SND_SOC_DA7213 if I2C |
@@ -59,20 +67,26 @@ config SND_SOC_ALL_CODECS | |||
59 | select SND_SOC_PCM1681 if I2C | 67 | select SND_SOC_PCM1681 if I2C |
60 | select SND_SOC_PCM1792A if SPI_MASTER | 68 | select SND_SOC_PCM1792A if SPI_MASTER |
61 | select SND_SOC_PCM3008 | 69 | select SND_SOC_PCM3008 |
70 | select SND_SOC_PCM512x_I2C if I2C | ||
71 | select SND_SOC_PCM512x_SPI if SPI_MASTER | ||
62 | select SND_SOC_RT5631 if I2C | 72 | select SND_SOC_RT5631 if I2C |
63 | select SND_SOC_RT5640 if I2C | 73 | select SND_SOC_RT5640 if I2C |
64 | select SND_SOC_SGTL5000 if I2C | 74 | select SND_SOC_SGTL5000 if I2C |
65 | select SND_SOC_SI476X if MFD_SI476X_CORE | 75 | select SND_SOC_SI476X if MFD_SI476X_CORE |
76 | select SND_SOC_SIRF_AUDIO_CODEC | ||
66 | select SND_SOC_SN95031 if INTEL_SCU_IPC | 77 | select SND_SOC_SN95031 if INTEL_SCU_IPC |
67 | select SND_SOC_SPDIF | 78 | select SND_SOC_SPDIF |
68 | select SND_SOC_SSM2518 if I2C | 79 | select SND_SOC_SSM2518 if I2C |
69 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI | 80 | select SND_SOC_SSM2602_SPI if SPI_MASTER |
81 | select SND_SOC_SSM2602_I2C if I2C | ||
70 | select SND_SOC_STA32X if I2C | 82 | select SND_SOC_STA32X if I2C |
71 | select SND_SOC_STA529 if I2C | 83 | select SND_SOC_STA529 if I2C |
72 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS | 84 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
73 | select SND_SOC_TAS5086 if I2C | 85 | select SND_SOC_TAS5086 if I2C |
74 | select SND_SOC_TLV320AIC23 if I2C | 86 | select SND_SOC_TLV320AIC23_I2C if I2C |
87 | select SND_SOC_TLV320AIC23_SPI if SPI_MASTER | ||
75 | select SND_SOC_TLV320AIC26 if SPI_MASTER | 88 | select SND_SOC_TLV320AIC26 if SPI_MASTER |
89 | select SND_SOC_TLV320AIC31XX if I2C | ||
76 | select SND_SOC_TLV320AIC32X4 if I2C | 90 | select SND_SOC_TLV320AIC32X4 if I2C |
77 | select SND_SOC_TLV320AIC3X if I2C | 91 | select SND_SOC_TLV320AIC3X if I2C |
78 | select SND_SOC_TPA6130A2 if I2C | 92 | select SND_SOC_TPA6130A2 if I2C |
@@ -182,6 +196,14 @@ config SND_SOC_AD1836 | |||
182 | config SND_SOC_AD193X | 196 | config SND_SOC_AD193X |
183 | tristate | 197 | tristate |
184 | 198 | ||
199 | config SND_SOC_AD193X_SPI | ||
200 | tristate | ||
201 | select SND_SOC_AD193X | ||
202 | |||
203 | config SND_SOC_AD193X_I2C | ||
204 | tristate | ||
205 | select SND_SOC_AD193X | ||
206 | |||
185 | config SND_SOC_AD1980 | 207 | config SND_SOC_AD1980 |
186 | tristate | 208 | tristate |
187 | 209 | ||
@@ -189,41 +211,66 @@ config SND_SOC_AD73311 | |||
189 | tristate | 211 | tristate |
190 | 212 | ||
191 | config SND_SOC_ADAU1701 | 213 | config SND_SOC_ADAU1701 |
214 | tristate "Analog Devices ADAU1701 CODEC" | ||
215 | depends on I2C | ||
192 | select SND_SOC_SIGMADSP | 216 | select SND_SOC_SIGMADSP |
193 | tristate | ||
194 | 217 | ||
195 | config SND_SOC_ADAU1373 | 218 | config SND_SOC_ADAU1373 |
196 | tristate | 219 | tristate |
197 | 220 | ||
221 | config SND_SOC_ADAU1977 | ||
222 | tristate | ||
223 | |||
224 | config SND_SOC_ADAU1977_SPI | ||
225 | tristate | ||
226 | select SND_SOC_ADAU1977 | ||
227 | select REGMAP_SPI | ||
228 | |||
229 | config SND_SOC_ADAU1977_I2C | ||
230 | tristate | ||
231 | select SND_SOC_ADAU1977 | ||
232 | select REGMAP_I2C | ||
233 | |||
198 | config SND_SOC_ADAV80X | 234 | config SND_SOC_ADAV80X |
199 | tristate | 235 | tristate |
200 | 236 | ||
237 | config SND_SOC_ADAV801 | ||
238 | tristate | ||
239 | select SND_SOC_ADAV80X | ||
240 | |||
241 | config SND_SOC_ADAV803 | ||
242 | tristate | ||
243 | select SND_SOC_ADAV80X | ||
244 | |||
201 | config SND_SOC_ADS117X | 245 | config SND_SOC_ADS117X |
202 | tristate | 246 | tristate |
203 | 247 | ||
204 | config SND_SOC_AK4104 | 248 | config SND_SOC_AK4104 |
205 | tristate | 249 | tristate "AKM AK4104 CODEC" |
250 | depends on SPI_MASTER | ||
206 | 251 | ||
207 | config SND_SOC_AK4535 | 252 | config SND_SOC_AK4535 |
208 | tristate | 253 | tristate |
209 | 254 | ||
210 | config SND_SOC_AK4554 | 255 | config SND_SOC_AK4554 |
211 | tristate | 256 | tristate "AKM AK4554 CODEC" |
212 | 257 | ||
213 | config SND_SOC_AK4641 | 258 | config SND_SOC_AK4641 |
214 | tristate | 259 | tristate |
215 | 260 | ||
216 | config SND_SOC_AK4642 | 261 | config SND_SOC_AK4642 |
217 | tristate | 262 | tristate "AKM AK4642 CODEC" |
263 | depends on I2C | ||
218 | 264 | ||
219 | config SND_SOC_AK4671 | 265 | config SND_SOC_AK4671 |
220 | tristate | 266 | tristate |
221 | 267 | ||
222 | config SND_SOC_AK5386 | 268 | config SND_SOC_AK5386 |
223 | tristate | 269 | tristate "AKM AK5638 CODEC" |
224 | 270 | ||
225 | config SND_SOC_ALC5623 | 271 | config SND_SOC_ALC5623 |
226 | tristate | 272 | tristate |
273 | |||
227 | config SND_SOC_ALC5632 | 274 | config SND_SOC_ALC5632 |
228 | tristate | 275 | tristate |
229 | 276 | ||
@@ -234,14 +281,17 @@ config SND_SOC_CS42L51 | |||
234 | tristate | 281 | tristate |
235 | 282 | ||
236 | config SND_SOC_CS42L52 | 283 | config SND_SOC_CS42L52 |
237 | tristate | 284 | tristate "Cirrus Logic CS42L52 CODEC" |
285 | depends on I2C | ||
238 | 286 | ||
239 | config SND_SOC_CS42L73 | 287 | config SND_SOC_CS42L73 |
240 | tristate | 288 | tristate "Cirrus Logic CS42L73 CODEC" |
289 | depends on I2C | ||
241 | 290 | ||
242 | # Cirrus Logic CS4270 Codec | 291 | # Cirrus Logic CS4270 Codec |
243 | config SND_SOC_CS4270 | 292 | config SND_SOC_CS4270 |
244 | tristate | 293 | tristate "Cirrus Logic CS4270 CODEC" |
294 | depends on I2C | ||
245 | 295 | ||
246 | # Cirrus Logic CS4270 Codec VD = 3.3V Errata | 296 | # Cirrus Logic CS4270 Codec VD = 3.3V Errata |
247 | # Select if you are affected by the errata where the part will not function | 297 | # Select if you are affected by the errata where the part will not function |
@@ -252,8 +302,18 @@ config SND_SOC_CS4270_VD33_ERRATA | |||
252 | depends on SND_SOC_CS4270 | 302 | depends on SND_SOC_CS4270 |
253 | 303 | ||
254 | config SND_SOC_CS4271 | 304 | config SND_SOC_CS4271 |
305 | tristate "Cirrus Logic CS4271 CODEC" | ||
306 | depends on SND_SOC_I2C_AND_SPI | ||
307 | |||
308 | config SND_SOC_CS42XX8 | ||
255 | tristate | 309 | tristate |
256 | 310 | ||
311 | config SND_SOC_CS42XX8_I2C | ||
312 | tristate "Cirrus Logic CS42448/CS42888 CODEC (I2C)" | ||
313 | depends on I2C | ||
314 | select SND_SOC_CS42XX8 | ||
315 | select REGMAP_I2C | ||
316 | |||
257 | config SND_SOC_CX20442 | 317 | config SND_SOC_CX20442 |
258 | tristate | 318 | tristate |
259 | depends on TTY | 319 | depends on TTY |
@@ -283,6 +343,9 @@ config SND_SOC_BT_SCO | |||
283 | config SND_SOC_DMIC | 343 | config SND_SOC_DMIC |
284 | tristate | 344 | tristate |
285 | 345 | ||
346 | config SND_SOC_HDMI_CODEC | ||
347 | tristate "HDMI stub CODEC" | ||
348 | |||
286 | config SND_SOC_ISABELLE | 349 | config SND_SOC_ISABELLE |
287 | tristate | 350 | tristate |
288 | 351 | ||
@@ -301,18 +364,32 @@ config SND_SOC_MAX98095 | |||
301 | config SND_SOC_MAX9850 | 364 | config SND_SOC_MAX9850 |
302 | tristate | 365 | tristate |
303 | 366 | ||
304 | config SND_SOC_HDMI_CODEC | ||
305 | tristate | ||
306 | |||
307 | config SND_SOC_PCM1681 | 367 | config SND_SOC_PCM1681 |
308 | tristate | 368 | tristate "Texas Instruments PCM1681 CODEC" |
369 | depends on I2C | ||
309 | 370 | ||
310 | config SND_SOC_PCM1792A | 371 | config SND_SOC_PCM1792A |
311 | tristate | 372 | tristate "Texas Instruments PCM1792A CODEC" |
373 | depends on SPI_MASTER | ||
312 | 374 | ||
313 | config SND_SOC_PCM3008 | 375 | config SND_SOC_PCM3008 |
314 | tristate | 376 | tristate |
315 | 377 | ||
378 | config SND_SOC_PCM512x | ||
379 | tristate | ||
380 | |||
381 | config SND_SOC_PCM512x_I2C | ||
382 | tristate "Texas Instruments PCM512x CODECs - I2C" | ||
383 | depends on I2C | ||
384 | select SND_SOC_PCM512x | ||
385 | select REGMAP_I2C | ||
386 | |||
387 | config SND_SOC_PCM512x_SPI | ||
388 | tristate "Texas Instruments PCM512x CODECs - SPI" | ||
389 | depends on SPI_MASTER | ||
390 | select SND_SOC_PCM512x | ||
391 | select REGMAP_SPI | ||
392 | |||
316 | config SND_SOC_RT5631 | 393 | config SND_SOC_RT5631 |
317 | tristate | 394 | tristate |
318 | 395 | ||
@@ -321,7 +398,8 @@ config SND_SOC_RT5640 | |||
321 | 398 | ||
322 | #Freescale sgtl5000 codec | 399 | #Freescale sgtl5000 codec |
323 | config SND_SOC_SGTL5000 | 400 | config SND_SOC_SGTL5000 |
324 | tristate | 401 | tristate "Freescale SGTL5000 CODEC" |
402 | depends on I2C | ||
325 | 403 | ||
326 | config SND_SOC_SI476X | 404 | config SND_SOC_SI476X |
327 | tristate | 405 | tristate |
@@ -330,11 +408,15 @@ config SND_SOC_SIGMADSP | |||
330 | tristate | 408 | tristate |
331 | select CRC32 | 409 | select CRC32 |
332 | 410 | ||
411 | config SND_SOC_SIRF_AUDIO_CODEC | ||
412 | tristate "SiRF SoC internal audio codec" | ||
413 | select REGMAP_MMIO | ||
414 | |||
333 | config SND_SOC_SN95031 | 415 | config SND_SOC_SN95031 |
334 | tristate | 416 | tristate |
335 | 417 | ||
336 | config SND_SOC_SPDIF | 418 | config SND_SOC_SPDIF |
337 | tristate | 419 | tristate "S/PDIF CODEC" |
338 | 420 | ||
339 | config SND_SOC_SSM2518 | 421 | config SND_SOC_SSM2518 |
340 | tristate | 422 | tristate |
@@ -342,6 +424,14 @@ config SND_SOC_SSM2518 | |||
342 | config SND_SOC_SSM2602 | 424 | config SND_SOC_SSM2602 |
343 | tristate | 425 | tristate |
344 | 426 | ||
427 | config SND_SOC_SSM2602_SPI | ||
428 | select SND_SOC_SSM2602 | ||
429 | tristate | ||
430 | |||
431 | config SND_SOC_SSM2602_I2C | ||
432 | select SND_SOC_SSM2602 | ||
433 | tristate | ||
434 | |||
345 | config SND_SOC_STA32X | 435 | config SND_SOC_STA32X |
346 | tristate | 436 | tristate |
347 | 437 | ||
@@ -352,20 +442,33 @@ config SND_SOC_STAC9766 | |||
352 | tristate | 442 | tristate |
353 | 443 | ||
354 | config SND_SOC_TAS5086 | 444 | config SND_SOC_TAS5086 |
355 | tristate | 445 | tristate "Texas Instruments TAS5086 speaker amplifier" |
446 | depends on I2C | ||
356 | 447 | ||
357 | config SND_SOC_TLV320AIC23 | 448 | config SND_SOC_TLV320AIC23 |
358 | tristate | 449 | tristate |
359 | 450 | ||
451 | config SND_SOC_TLV320AIC23_I2C | ||
452 | tristate | ||
453 | select SND_SOC_TLV320AIC23 | ||
454 | |||
455 | config SND_SOC_TLV320AIC23_SPI | ||
456 | tristate | ||
457 | select SND_SOC_TLV320AIC23 | ||
458 | |||
360 | config SND_SOC_TLV320AIC26 | 459 | config SND_SOC_TLV320AIC26 |
361 | tristate | 460 | tristate |
362 | depends on SPI | 461 | depends on SPI |
363 | 462 | ||
463 | config SND_SOC_TLV320AIC31XX | ||
464 | tristate | ||
465 | |||
364 | config SND_SOC_TLV320AIC32X4 | 466 | config SND_SOC_TLV320AIC32X4 |
365 | tristate | 467 | tristate |
366 | 468 | ||
367 | config SND_SOC_TLV320AIC3X | 469 | config SND_SOC_TLV320AIC3X |
368 | tristate | 470 | tristate "Texas Instruments TLV320AIC3x CODECs" |
471 | depends on I2C | ||
369 | 472 | ||
370 | config SND_SOC_TLV320DAC33 | 473 | config SND_SOC_TLV320DAC33 |
371 | tristate | 474 | tristate |
@@ -414,55 +517,69 @@ config SND_SOC_WM8400 | |||
414 | tristate | 517 | tristate |
415 | 518 | ||
416 | config SND_SOC_WM8510 | 519 | config SND_SOC_WM8510 |
417 | tristate | 520 | tristate "Wolfson Microelectronics WM8510 CODEC" |
521 | depends on SND_SOC_I2C_AND_SPI | ||
418 | 522 | ||
419 | config SND_SOC_WM8523 | 523 | config SND_SOC_WM8523 |
420 | tristate | 524 | tristate "Wolfson Microelectronics WM8523 DAC" |
525 | depends on I2C | ||
421 | 526 | ||
422 | config SND_SOC_WM8580 | 527 | config SND_SOC_WM8580 |
423 | tristate | 528 | tristate "Wolfson Microelectronics WM8523 CODEC" |
529 | depends on I2C | ||
424 | 530 | ||
425 | config SND_SOC_WM8711 | 531 | config SND_SOC_WM8711 |
426 | tristate | 532 | tristate "Wolfson Microelectronics WM8711 CODEC" |
533 | depends on SND_SOC_I2C_AND_SPI | ||
427 | 534 | ||
428 | config SND_SOC_WM8727 | 535 | config SND_SOC_WM8727 |
429 | tristate | 536 | tristate |
430 | 537 | ||
431 | config SND_SOC_WM8728 | 538 | config SND_SOC_WM8728 |
432 | tristate | 539 | tristate "Wolfson Microelectronics WM8728 DAC" |
540 | depends on SND_SOC_I2C_AND_SPI | ||
433 | 541 | ||
434 | config SND_SOC_WM8731 | 542 | config SND_SOC_WM8731 |
435 | tristate | 543 | tristate "Wolfson Microelectronics WM8731 CODEC" |
544 | depends on SND_SOC_I2C_AND_SPI | ||
436 | 545 | ||
437 | config SND_SOC_WM8737 | 546 | config SND_SOC_WM8737 |
438 | tristate | 547 | tristate "Wolfson Microelectronics WM8737 ADC" |
548 | depends on SND_SOC_I2C_AND_SPI | ||
439 | 549 | ||
440 | config SND_SOC_WM8741 | 550 | config SND_SOC_WM8741 |
441 | tristate | 551 | tristate "Wolfson Microelectronics WM8737 DAC" |
552 | depends on SND_SOC_I2C_AND_SPI | ||
442 | 553 | ||
443 | config SND_SOC_WM8750 | 554 | config SND_SOC_WM8750 |
444 | tristate | 555 | tristate "Wolfson Microelectronics WM8750 CODEC" |
556 | depends on SND_SOC_I2C_AND_SPI | ||
445 | 557 | ||
446 | config SND_SOC_WM8753 | 558 | config SND_SOC_WM8753 |
447 | tristate | 559 | tristate "Wolfson Microelectronics WM8753 CODEC" |
560 | depends on SND_SOC_I2C_AND_SPI | ||
448 | 561 | ||
449 | config SND_SOC_WM8770 | 562 | config SND_SOC_WM8770 |
450 | tristate | 563 | tristate "Wolfson Microelectronics WM8770 CODEC" |
564 | depends on SPI_MASTER | ||
451 | 565 | ||
452 | config SND_SOC_WM8776 | 566 | config SND_SOC_WM8776 |
453 | tristate | 567 | tristate "Wolfson Microelectronics WM8776 CODEC" |
568 | depends on SND_SOC_I2C_AND_SPI | ||
454 | 569 | ||
455 | config SND_SOC_WM8782 | 570 | config SND_SOC_WM8782 |
456 | tristate | 571 | tristate |
457 | 572 | ||
458 | config SND_SOC_WM8804 | 573 | config SND_SOC_WM8804 |
459 | tristate | 574 | tristate "Wolfson Microelectronics WM8804 S/PDIF transceiver" |
575 | depends on SND_SOC_I2C_AND_SPI | ||
460 | 576 | ||
461 | config SND_SOC_WM8900 | 577 | config SND_SOC_WM8900 |
462 | tristate | 578 | tristate |
463 | 579 | ||
464 | config SND_SOC_WM8903 | 580 | config SND_SOC_WM8903 |
465 | tristate | 581 | tristate "Wolfson Microelectronics WM8903 CODEC" |
582 | depends on I2C | ||
466 | 583 | ||
467 | config SND_SOC_WM8904 | 584 | config SND_SOC_WM8904 |
468 | tristate | 585 | tristate |
@@ -480,7 +597,8 @@ config SND_SOC_WM8961 | |||
480 | tristate | 597 | tristate |
481 | 598 | ||
482 | config SND_SOC_WM8962 | 599 | config SND_SOC_WM8962 |
483 | tristate | 600 | tristate "Wolfson Microelectronics WM8962 CODEC" |
601 | depends on I2C | ||
484 | 602 | ||
485 | config SND_SOC_WM8971 | 603 | config SND_SOC_WM8971 |
486 | tristate | 604 | tristate |
@@ -553,4 +671,7 @@ config SND_SOC_ML26124 | |||
553 | tristate | 671 | tristate |
554 | 672 | ||
555 | config SND_SOC_TPA6130A2 | 673 | config SND_SOC_TPA6130A2 |
556 | tristate | 674 | tristate "Texas Instruments TPA6130A2 headphone amplifier" |
675 | depends on I2C | ||
676 | |||
677 | endmenu | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..3c4d275d064b 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -3,11 +3,18 @@ snd-soc-ab8500-codec-objs := ab8500-codec.o | |||
3 | snd-soc-ac97-objs := ac97.o | 3 | snd-soc-ac97-objs := ac97.o |
4 | snd-soc-ad1836-objs := ad1836.o | 4 | snd-soc-ad1836-objs := ad1836.o |
5 | snd-soc-ad193x-objs := ad193x.o | 5 | snd-soc-ad193x-objs := ad193x.o |
6 | snd-soc-ad193x-spi-objs := ad193x-spi.o | ||
7 | snd-soc-ad193x-i2c-objs := ad193x-i2c.o | ||
6 | snd-soc-ad1980-objs := ad1980.o | 8 | snd-soc-ad1980-objs := ad1980.o |
7 | snd-soc-ad73311-objs := ad73311.o | 9 | snd-soc-ad73311-objs := ad73311.o |
8 | snd-soc-adau1701-objs := adau1701.o | 10 | snd-soc-adau1701-objs := adau1701.o |
9 | snd-soc-adau1373-objs := adau1373.o | 11 | snd-soc-adau1373-objs := adau1373.o |
12 | snd-soc-adau1977-objs := adau1977.o | ||
13 | snd-soc-adau1977-spi-objs := adau1977-spi.o | ||
14 | snd-soc-adau1977-i2c-objs := adau1977-i2c.o | ||
10 | snd-soc-adav80x-objs := adav80x.o | 15 | snd-soc-adav80x-objs := adav80x.o |
16 | snd-soc-adav801-objs := adav801.o | ||
17 | snd-soc-adav803-objs := adav803.o | ||
11 | snd-soc-ads117x-objs := ads117x.o | 18 | snd-soc-ads117x-objs := ads117x.o |
12 | snd-soc-ak4104-objs := ak4104.o | 19 | snd-soc-ak4104-objs := ak4104.o |
13 | snd-soc-ak4535-objs := ak4535.o | 20 | snd-soc-ak4535-objs := ak4535.o |
@@ -23,6 +30,8 @@ snd-soc-cs42l52-objs := cs42l52.o | |||
23 | snd-soc-cs42l73-objs := cs42l73.o | 30 | snd-soc-cs42l73-objs := cs42l73.o |
24 | snd-soc-cs4270-objs := cs4270.o | 31 | snd-soc-cs4270-objs := cs4270.o |
25 | snd-soc-cs4271-objs := cs4271.o | 32 | snd-soc-cs4271-objs := cs4271.o |
33 | snd-soc-cs42xx8-objs := cs42xx8.o | ||
34 | snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o | ||
26 | snd-soc-cx20442-objs := cx20442.o | 35 | snd-soc-cx20442-objs := cx20442.o |
27 | snd-soc-da7210-objs := da7210.o | 36 | snd-soc-da7210-objs := da7210.o |
28 | snd-soc-da7213-objs := da7213.o | 37 | snd-soc-da7213-objs := da7213.o |
@@ -46,6 +55,9 @@ snd-soc-hdmi-codec-objs := hdmi.o | |||
46 | snd-soc-pcm1681-objs := pcm1681.o | 55 | snd-soc-pcm1681-objs := pcm1681.o |
47 | snd-soc-pcm1792a-codec-objs := pcm1792a.o | 56 | snd-soc-pcm1792a-codec-objs := pcm1792a.o |
48 | snd-soc-pcm3008-objs := pcm3008.o | 57 | snd-soc-pcm3008-objs := pcm3008.o |
58 | snd-soc-pcm512x-objs := pcm512x.o | ||
59 | snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o | ||
60 | snd-soc-pcm512x-spi-objs := pcm512x-spi.o | ||
49 | snd-soc-rt5631-objs := rt5631.o | 61 | snd-soc-rt5631-objs := rt5631.o |
50 | snd-soc-rt5640-objs := rt5640.o | 62 | snd-soc-rt5640-objs := rt5640.o |
51 | snd-soc-sgtl5000-objs := sgtl5000.o | 63 | snd-soc-sgtl5000-objs := sgtl5000.o |
@@ -53,19 +65,25 @@ snd-soc-alc5623-objs := alc5623.o | |||
53 | snd-soc-alc5632-objs := alc5632.o | 65 | snd-soc-alc5632-objs := alc5632.o |
54 | snd-soc-sigmadsp-objs := sigmadsp.o | 66 | snd-soc-sigmadsp-objs := sigmadsp.o |
55 | snd-soc-si476x-objs := si476x.o | 67 | snd-soc-si476x-objs := si476x.o |
68 | snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o | ||
56 | snd-soc-sn95031-objs := sn95031.o | 69 | snd-soc-sn95031-objs := sn95031.o |
57 | snd-soc-spdif-tx-objs := spdif_transmitter.o | 70 | snd-soc-spdif-tx-objs := spdif_transmitter.o |
58 | snd-soc-spdif-rx-objs := spdif_receiver.o | 71 | snd-soc-spdif-rx-objs := spdif_receiver.o |
59 | snd-soc-ssm2518-objs := ssm2518.o | 72 | snd-soc-ssm2518-objs := ssm2518.o |
60 | snd-soc-ssm2602-objs := ssm2602.o | 73 | snd-soc-ssm2602-objs := ssm2602.o |
74 | snd-soc-ssm2602-spi-objs := ssm2602-spi.o | ||
75 | snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o | ||
61 | snd-soc-sta32x-objs := sta32x.o | 76 | snd-soc-sta32x-objs := sta32x.o |
62 | snd-soc-sta529-objs := sta529.o | 77 | snd-soc-sta529-objs := sta529.o |
63 | snd-soc-stac9766-objs := stac9766.o | 78 | snd-soc-stac9766-objs := stac9766.o |
64 | snd-soc-tas5086-objs := tas5086.o | 79 | snd-soc-tas5086-objs := tas5086.o |
65 | snd-soc-tlv320aic23-objs := tlv320aic23.o | 80 | snd-soc-tlv320aic23-objs := tlv320aic23.o |
81 | snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o | ||
82 | snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o | ||
66 | snd-soc-tlv320aic26-objs := tlv320aic26.o | 83 | snd-soc-tlv320aic26-objs := tlv320aic26.o |
67 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o | 84 | snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o |
68 | snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o | 85 | snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o |
86 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o | ||
69 | snd-soc-tlv320dac33-objs := tlv320dac33.o | 87 | snd-soc-tlv320dac33-objs := tlv320dac33.o |
70 | snd-soc-twl4030-objs := twl4030.o | 88 | snd-soc-twl4030-objs := twl4030.o |
71 | snd-soc-twl6040-objs := twl6040.o | 89 | snd-soc-twl6040-objs := twl6040.o |
@@ -134,11 +152,18 @@ obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o | |||
134 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o | 152 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o |
135 | obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o | 153 | obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o |
136 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o | 154 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o |
155 | obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o | ||
156 | obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o | ||
137 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o | 157 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o |
138 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | 158 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o |
139 | obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o | 159 | obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o |
160 | obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o | ||
161 | obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o | ||
162 | obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o | ||
140 | obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o | 163 | obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o |
141 | obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o | 164 | obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o |
165 | obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o | ||
166 | obj-$(CONFIG_SND_SOC_ADAV803) += snd-soc-adav803.o | ||
142 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o | 167 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o |
143 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o | 168 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o |
144 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o | 169 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o |
@@ -156,6 +181,8 @@ obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o | |||
156 | obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o | 181 | obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o |
157 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | 182 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o |
158 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o | 183 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o |
184 | obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o | ||
185 | obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o | ||
159 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 186 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
160 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o | 187 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o |
161 | obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o | 188 | obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o |
@@ -179,6 +206,9 @@ obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o | |||
179 | obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o | 206 | obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o |
180 | obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o | 207 | obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o |
181 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o | 208 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o |
209 | obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o | ||
210 | obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o | ||
211 | obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o | ||
182 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o | 212 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o |
183 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o | 213 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o |
184 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o | 214 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o |
@@ -188,14 +218,19 @@ obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o | |||
188 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o | 218 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o |
189 | obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o | 219 | obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o |
190 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | 220 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
221 | obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o | ||
222 | obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o | ||
191 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o | 223 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o |
192 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | 224 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o |
193 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o | 225 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o |
194 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o | 226 | obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o |
195 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o | 227 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
228 | obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o | ||
229 | obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o | ||
196 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o | 230 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o |
197 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o | 231 | obj-$(CONFIG_SND_SOC_TLV320AIC31XX) += snd-soc-tlv320aic31xx.o |
198 | obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o | 232 | obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o |
233 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o | ||
199 | obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o | 234 | obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o |
200 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o | 235 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o |
201 | obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o | 236 | obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o |
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 77f459868579..685998dd086e 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -40,8 +40,8 @@ struct ad1836_priv { | |||
40 | */ | 40 | */ |
41 | static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"}; | 41 | static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"}; |
42 | 42 | ||
43 | static const struct soc_enum ad1836_deemp_enum = | 43 | static SOC_ENUM_SINGLE_DECL(ad1836_deemp_enum, |
44 | SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp); | 44 | AD1836_DAC_CTRL1, 8, ad1836_deemp); |
45 | 45 | ||
46 | #define AD1836_DAC_VOLUME(x) \ | 46 | #define AD1836_DAC_VOLUME(x) \ |
47 | SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \ | 47 | SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \ |
diff --git a/sound/soc/codecs/ad193x-i2c.c b/sound/soc/codecs/ad193x-i2c.c new file mode 100644 index 000000000000..df3a1a415825 --- /dev/null +++ b/sound/soc/codecs/ad193x-i2c.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * AD1936/AD1937 audio driver | ||
3 | * | ||
4 | * Copyright 2014 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/i2c.h> | ||
11 | #include <linux/regmap.h> | ||
12 | |||
13 | #include <sound/soc.h> | ||
14 | |||
15 | #include "ad193x.h" | ||
16 | |||
17 | static const struct i2c_device_id ad193x_id[] = { | ||
18 | { "ad1936", 0 }, | ||
19 | { "ad1937", 0 }, | ||
20 | { } | ||
21 | }; | ||
22 | MODULE_DEVICE_TABLE(i2c, ad193x_id); | ||
23 | |||
24 | static int ad193x_i2c_probe(struct i2c_client *client, | ||
25 | const struct i2c_device_id *id) | ||
26 | { | ||
27 | struct regmap_config config; | ||
28 | |||
29 | config = ad193x_regmap_config; | ||
30 | config.val_bits = 8; | ||
31 | config.reg_bits = 8; | ||
32 | |||
33 | return ad193x_probe(&client->dev, devm_regmap_init_i2c(client, &config)); | ||
34 | } | ||
35 | |||
36 | static int ad193x_i2c_remove(struct i2c_client *client) | ||
37 | { | ||
38 | snd_soc_unregister_codec(&client->dev); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static struct i2c_driver ad193x_i2c_driver = { | ||
43 | .driver = { | ||
44 | .name = "ad193x", | ||
45 | }, | ||
46 | .probe = ad193x_i2c_probe, | ||
47 | .remove = ad193x_i2c_remove, | ||
48 | .id_table = ad193x_id, | ||
49 | }; | ||
50 | module_i2c_driver(ad193x_i2c_driver); | ||
51 | |||
52 | MODULE_DESCRIPTION("ASoC AD1936/AD1937 audio CODEC driver"); | ||
53 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
54 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ad193x-spi.c b/sound/soc/codecs/ad193x-spi.c new file mode 100644 index 000000000000..390cef9b9dc2 --- /dev/null +++ b/sound/soc/codecs/ad193x-spi.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * AD1938/AD1939 audio driver | ||
3 | * | ||
4 | * Copyright 2014 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/spi/spi.h> | ||
11 | #include <linux/regmap.h> | ||
12 | |||
13 | #include <sound/soc.h> | ||
14 | |||
15 | #include "ad193x.h" | ||
16 | |||
17 | static int ad193x_spi_probe(struct spi_device *spi) | ||
18 | { | ||
19 | struct regmap_config config; | ||
20 | |||
21 | config = ad193x_regmap_config; | ||
22 | config.val_bits = 8; | ||
23 | config.reg_bits = 16; | ||
24 | config.read_flag_mask = 0x09; | ||
25 | config.write_flag_mask = 0x08; | ||
26 | |||
27 | return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); | ||
28 | } | ||
29 | |||
30 | static int ad193x_spi_remove(struct spi_device *spi) | ||
31 | { | ||
32 | snd_soc_unregister_codec(&spi->dev); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static struct spi_driver ad193x_spi_driver = { | ||
37 | .driver = { | ||
38 | .name = "ad193x", | ||
39 | .owner = THIS_MODULE, | ||
40 | }, | ||
41 | .probe = ad193x_spi_probe, | ||
42 | .remove = ad193x_spi_remove, | ||
43 | }; | ||
44 | module_spi_driver(ad193x_spi_driver); | ||
45 | |||
46 | MODULE_DESCRIPTION("ASoC AD1938/AD1939 audio CODEC driver"); | ||
47 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
48 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 5a42dca535b7..6844d0b2af68 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -6,12 +6,10 @@ | |||
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/module.h> | 9 | #include <linux/module.h> |
11 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
12 | #include <linux/device.h> | 11 | #include <linux/device.h> |
13 | #include <linux/i2c.h> | 12 | #include <linux/regmap.h> |
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
16 | #include <sound/core.h> | 14 | #include <sound/core.h> |
17 | #include <sound/pcm.h> | 15 | #include <sound/pcm.h> |
@@ -19,6 +17,7 @@ | |||
19 | #include <sound/initval.h> | 17 | #include <sound/initval.h> |
20 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
21 | #include <sound/tlv.h> | 19 | #include <sound/tlv.h> |
20 | |||
22 | #include "ad193x.h" | 21 | #include "ad193x.h" |
23 | 22 | ||
24 | /* codec private data */ | 23 | /* codec private data */ |
@@ -32,8 +31,8 @@ struct ad193x_priv { | |||
32 | */ | 31 | */ |
33 | static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; | 32 | static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; |
34 | 33 | ||
35 | static const struct soc_enum ad193x_deemp_enum = | 34 | static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1, |
36 | SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp); | 35 | ad193x_deemp); |
37 | 36 | ||
38 | static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0); | 37 | static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0); |
39 | 38 | ||
@@ -320,17 +319,9 @@ static struct snd_soc_dai_driver ad193x_dai = { | |||
320 | .ops = &ad193x_dai_ops, | 319 | .ops = &ad193x_dai_ops, |
321 | }; | 320 | }; |
322 | 321 | ||
323 | static int ad193x_probe(struct snd_soc_codec *codec) | 322 | static int ad193x_codec_probe(struct snd_soc_codec *codec) |
324 | { | 323 | { |
325 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); | 324 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); |
326 | int ret; | ||
327 | |||
328 | codec->control_data = ad193x->regmap; | ||
329 | ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
330 | if (ret < 0) { | ||
331 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); | ||
332 | return ret; | ||
333 | } | ||
334 | 325 | ||
335 | /* default setting for ad193x */ | 326 | /* default setting for ad193x */ |
336 | 327 | ||
@@ -348,11 +339,11 @@ static int ad193x_probe(struct snd_soc_codec *codec) | |||
348 | regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ | 339 | regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ |
349 | regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04); | 340 | regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04); |
350 | 341 | ||
351 | return ret; | 342 | return 0; |
352 | } | 343 | } |
353 | 344 | ||
354 | static struct snd_soc_codec_driver soc_codec_dev_ad193x = { | 345 | static struct snd_soc_codec_driver soc_codec_dev_ad193x = { |
355 | .probe = ad193x_probe, | 346 | .probe = ad193x_codec_probe, |
356 | .controls = ad193x_snd_controls, | 347 | .controls = ad193x_snd_controls, |
357 | .num_controls = ARRAY_SIZE(ad193x_snd_controls), | 348 | .num_controls = ARRAY_SIZE(ad193x_snd_controls), |
358 | .dapm_widgets = ad193x_dapm_widgets, | 349 | .dapm_widgets = ad193x_dapm_widgets, |
@@ -366,140 +357,31 @@ static bool adau193x_reg_volatile(struct device *dev, unsigned int reg) | |||
366 | return false; | 357 | return false; |
367 | } | 358 | } |
368 | 359 | ||
369 | #if defined(CONFIG_SPI_MASTER) | 360 | const struct regmap_config ad193x_regmap_config = { |
370 | |||
371 | static const struct regmap_config ad193x_spi_regmap_config = { | ||
372 | .val_bits = 8, | ||
373 | .reg_bits = 16, | ||
374 | .read_flag_mask = 0x09, | ||
375 | .write_flag_mask = 0x08, | ||
376 | |||
377 | .max_register = AD193X_NUM_REGS - 1, | 361 | .max_register = AD193X_NUM_REGS - 1, |
378 | .volatile_reg = adau193x_reg_volatile, | 362 | .volatile_reg = adau193x_reg_volatile, |
379 | }; | 363 | }; |
364 | EXPORT_SYMBOL_GPL(ad193x_regmap_config); | ||
380 | 365 | ||
381 | static int ad193x_spi_probe(struct spi_device *spi) | 366 | int ad193x_probe(struct device *dev, struct regmap *regmap) |
382 | { | 367 | { |
383 | struct ad193x_priv *ad193x; | 368 | struct ad193x_priv *ad193x; |
384 | 369 | ||
385 | ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), | 370 | if (IS_ERR(regmap)) |
386 | GFP_KERNEL); | 371 | return PTR_ERR(regmap); |
387 | if (ad193x == NULL) | ||
388 | return -ENOMEM; | ||
389 | |||
390 | ad193x->regmap = devm_regmap_init_spi(spi, &ad193x_spi_regmap_config); | ||
391 | if (IS_ERR(ad193x->regmap)) | ||
392 | return PTR_ERR(ad193x->regmap); | ||
393 | |||
394 | spi_set_drvdata(spi, ad193x); | ||
395 | |||
396 | return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x, | ||
397 | &ad193x_dai, 1); | ||
398 | } | ||
399 | |||
400 | static int ad193x_spi_remove(struct spi_device *spi) | ||
401 | { | ||
402 | snd_soc_unregister_codec(&spi->dev); | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static struct spi_driver ad193x_spi_driver = { | ||
407 | .driver = { | ||
408 | .name = "ad193x", | ||
409 | .owner = THIS_MODULE, | ||
410 | }, | ||
411 | .probe = ad193x_spi_probe, | ||
412 | .remove = ad193x_spi_remove, | ||
413 | }; | ||
414 | #endif | ||
415 | |||
416 | #if IS_ENABLED(CONFIG_I2C) | ||
417 | |||
418 | static const struct regmap_config ad193x_i2c_regmap_config = { | ||
419 | .val_bits = 8, | ||
420 | .reg_bits = 8, | ||
421 | |||
422 | .max_register = AD193X_NUM_REGS - 1, | ||
423 | .volatile_reg = adau193x_reg_volatile, | ||
424 | }; | ||
425 | |||
426 | static const struct i2c_device_id ad193x_id[] = { | ||
427 | { "ad1936", 0 }, | ||
428 | { "ad1937", 0 }, | ||
429 | { } | ||
430 | }; | ||
431 | MODULE_DEVICE_TABLE(i2c, ad193x_id); | ||
432 | |||
433 | static int ad193x_i2c_probe(struct i2c_client *client, | ||
434 | const struct i2c_device_id *id) | ||
435 | { | ||
436 | struct ad193x_priv *ad193x; | ||
437 | 372 | ||
438 | ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), | 373 | ad193x = devm_kzalloc(dev, sizeof(*ad193x), GFP_KERNEL); |
439 | GFP_KERNEL); | ||
440 | if (ad193x == NULL) | 374 | if (ad193x == NULL) |
441 | return -ENOMEM; | 375 | return -ENOMEM; |
442 | 376 | ||
443 | ad193x->regmap = devm_regmap_init_i2c(client, &ad193x_i2c_regmap_config); | 377 | ad193x->regmap = regmap; |
444 | if (IS_ERR(ad193x->regmap)) | ||
445 | return PTR_ERR(ad193x->regmap); | ||
446 | |||
447 | i2c_set_clientdata(client, ad193x); | ||
448 | |||
449 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x, | ||
450 | &ad193x_dai, 1); | ||
451 | } | ||
452 | |||
453 | static int ad193x_i2c_remove(struct i2c_client *client) | ||
454 | { | ||
455 | snd_soc_unregister_codec(&client->dev); | ||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | static struct i2c_driver ad193x_i2c_driver = { | ||
460 | .driver = { | ||
461 | .name = "ad193x", | ||
462 | }, | ||
463 | .probe = ad193x_i2c_probe, | ||
464 | .remove = ad193x_i2c_remove, | ||
465 | .id_table = ad193x_id, | ||
466 | }; | ||
467 | #endif | ||
468 | |||
469 | static int __init ad193x_modinit(void) | ||
470 | { | ||
471 | int ret; | ||
472 | |||
473 | #if IS_ENABLED(CONFIG_I2C) | ||
474 | ret = i2c_add_driver(&ad193x_i2c_driver); | ||
475 | if (ret != 0) { | ||
476 | printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n", | ||
477 | ret); | ||
478 | } | ||
479 | #endif | ||
480 | |||
481 | #if defined(CONFIG_SPI_MASTER) | ||
482 | ret = spi_register_driver(&ad193x_spi_driver); | ||
483 | if (ret != 0) { | ||
484 | printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n", | ||
485 | ret); | ||
486 | } | ||
487 | #endif | ||
488 | return ret; | ||
489 | } | ||
490 | module_init(ad193x_modinit); | ||
491 | 378 | ||
492 | static void __exit ad193x_modexit(void) | 379 | dev_set_drvdata(dev, ad193x); |
493 | { | ||
494 | #if defined(CONFIG_SPI_MASTER) | ||
495 | spi_unregister_driver(&ad193x_spi_driver); | ||
496 | #endif | ||
497 | 380 | ||
498 | #if IS_ENABLED(CONFIG_I2C) | 381 | return snd_soc_register_codec(dev, &soc_codec_dev_ad193x, |
499 | i2c_del_driver(&ad193x_i2c_driver); | 382 | &ad193x_dai, 1); |
500 | #endif | ||
501 | } | 383 | } |
502 | module_exit(ad193x_modexit); | 384 | EXPORT_SYMBOL_GPL(ad193x_probe); |
503 | 385 | ||
504 | MODULE_DESCRIPTION("ASoC ad193x driver"); | 386 | MODULE_DESCRIPTION("ASoC ad193x driver"); |
505 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 387 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index 473388049992..ab9a998f15be 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h | |||
@@ -9,6 +9,13 @@ | |||
9 | #ifndef __AD193X_H__ | 9 | #ifndef __AD193X_H__ |
10 | #define __AD193X_H__ | 10 | #define __AD193X_H__ |
11 | 11 | ||
12 | #include <linux/regmap.h> | ||
13 | |||
14 | struct device; | ||
15 | |||
16 | extern const struct regmap_config ad193x_regmap_config; | ||
17 | int ad193x_probe(struct device *dev, struct regmap *regmap); | ||
18 | |||
12 | #define AD193X_PLL_CLK_CTRL0 0x00 | 19 | #define AD193X_PLL_CLK_CTRL0 0x00 |
13 | #define AD193X_PLL_POWERDOWN 0x01 | 20 | #define AD193X_PLL_POWERDOWN 0x01 |
14 | #define AD193X_PLL_INPUT_MASK 0x6 | 21 | #define AD193X_PLL_INPUT_MASK 0x6 |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 7257a8885f42..34d965a4a040 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -57,8 +57,8 @@ static const u16 ad1980_reg[] = { | |||
57 | static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line", | 57 | static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line", |
58 | "Stereo Mix", "Mono Mix", "Phone"}; | 58 | "Stereo Mix", "Mono Mix", "Phone"}; |
59 | 59 | ||
60 | static const struct soc_enum ad1980_cap_src = | 60 | static SOC_ENUM_DOUBLE_DECL(ad1980_cap_src, |
61 | SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 7, ad1980_rec_sel); | 61 | AC97_REC_SEL, 8, 0, ad1980_rec_sel); |
62 | 62 | ||
63 | static const struct snd_kcontrol_new ad1980_snd_ac97_controls[] = { | 63 | static const struct snd_kcontrol_new ad1980_snd_ac97_controls[] = { |
64 | SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1), | 64 | SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1), |
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index eb836ed5271f..877f5737bb6b 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
@@ -345,15 +345,15 @@ static const char *adau1373_fdsp_sel_text[] = { | |||
345 | "Channel 5", | 345 | "Channel 5", |
346 | }; | 346 | }; |
347 | 347 | ||
348 | static const SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum, | 348 | static SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum, |
349 | ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text); | 349 | ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text); |
350 | static const SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum, | 350 | static SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum, |
351 | ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text); | 351 | ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text); |
352 | static const SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum, | 352 | static SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum, |
353 | ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text); | 353 | ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text); |
354 | static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum, | 354 | static SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum, |
355 | ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text); | 355 | ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text); |
356 | static const SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum, | 356 | static SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum, |
357 | ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text); | 357 | ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text); |
358 | 358 | ||
359 | static const char *adau1373_hpf_cutoff_text[] = { | 359 | static const char *adau1373_hpf_cutoff_text[] = { |
@@ -362,7 +362,7 @@ static const char *adau1373_hpf_cutoff_text[] = { | |||
362 | "800Hz", | 362 | "800Hz", |
363 | }; | 363 | }; |
364 | 364 | ||
365 | static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum, | 365 | static SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum, |
366 | ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text); | 366 | ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text); |
367 | 367 | ||
368 | static const char *adau1373_bass_lpf_cutoff_text[] = { | 368 | static const char *adau1373_bass_lpf_cutoff_text[] = { |
@@ -388,14 +388,14 @@ static const unsigned int adau1373_bass_tlv[] = { | |||
388 | 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0), | 388 | 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0), |
389 | }; | 389 | }; |
390 | 390 | ||
391 | static const SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, | 391 | static SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, |
392 | ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text); | 392 | ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text); |
393 | 393 | ||
394 | static const SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum, | 394 | static SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum, |
395 | ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text, | 395 | ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text, |
396 | adau1373_bass_clip_level_values); | 396 | adau1373_bass_clip_level_values); |
397 | 397 | ||
398 | static const SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum, | 398 | static SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum, |
399 | ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text); | 399 | ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text); |
400 | 400 | ||
401 | static const char *adau1373_3d_level_text[] = { | 401 | static const char *adau1373_3d_level_text[] = { |
@@ -409,9 +409,9 @@ static const char *adau1373_3d_cutoff_text[] = { | |||
409 | "0.16875 fs", "0.27083 fs" | 409 | "0.16875 fs", "0.27083 fs" |
410 | }; | 410 | }; |
411 | 411 | ||
412 | static const SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, | 412 | static SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, |
413 | ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text); | 413 | ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text); |
414 | static const SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, | 414 | static SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, |
415 | ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text); | 415 | ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text); |
416 | 416 | ||
417 | static const unsigned int adau1373_3d_tlv[] = { | 417 | static const unsigned int adau1373_3d_tlv[] = { |
@@ -427,11 +427,11 @@ static const char *adau1373_lr_mux_text[] = { | |||
427 | "Stereo", | 427 | "Stereo", |
428 | }; | 428 | }; |
429 | 429 | ||
430 | static const SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum, | 430 | static SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum, |
431 | ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text); | 431 | ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text); |
432 | static const SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum, | 432 | static SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum, |
433 | ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text); | 433 | ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text); |
434 | static const SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum, | 434 | static SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum, |
435 | ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text); | 435 | ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text); |
436 | 436 | ||
437 | static const struct snd_kcontrol_new adau1373_controls[] = { | 437 | static const struct snd_kcontrol_new adau1373_controls[] = { |
@@ -576,8 +576,8 @@ static const char *adau1373_decimator_text[] = { | |||
576 | "DMIC1", | 576 | "DMIC1", |
577 | }; | 577 | }; |
578 | 578 | ||
579 | static const struct soc_enum adau1373_decimator_enum = | 579 | static SOC_ENUM_SINGLE_VIRT_DECL(adau1373_decimator_enum, |
580 | SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text); | 580 | adau1373_decimator_text); |
581 | 581 | ||
582 | static const struct snd_kcontrol_new adau1373_decimator_mux = | 582 | static const struct snd_kcontrol_new adau1373_decimator_mux = |
583 | SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum); | 583 | SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum); |
@@ -1376,15 +1376,8 @@ static int adau1373_probe(struct snd_soc_codec *codec) | |||
1376 | struct adau1373_platform_data *pdata = codec->dev->platform_data; | 1376 | struct adau1373_platform_data *pdata = codec->dev->platform_data; |
1377 | bool lineout_differential = false; | 1377 | bool lineout_differential = false; |
1378 | unsigned int val; | 1378 | unsigned int val; |
1379 | int ret; | ||
1380 | int i; | 1379 | int i; |
1381 | 1380 | ||
1382 | ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
1383 | if (ret) { | ||
1384 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); | ||
1385 | return ret; | ||
1386 | } | ||
1387 | |||
1388 | if (pdata) { | 1381 | if (pdata) { |
1389 | if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting)) | 1382 | if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting)) |
1390 | return -EINVAL; | 1383 | return -EINVAL; |
diff --git a/sound/soc/codecs/adau1977-i2c.c b/sound/soc/codecs/adau1977-i2c.c new file mode 100644 index 000000000000..9700e8c838c9 --- /dev/null +++ b/sound/soc/codecs/adau1977-i2c.c | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * ADAU1977/ADAU1978/ADAU1979 driver | ||
3 | * | ||
4 | * Copyright 2014 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/i2c.h> | ||
11 | #include <linux/mod_devicetable.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/regmap.h> | ||
14 | #include <sound/soc.h> | ||
15 | |||
16 | #include "adau1977.h" | ||
17 | |||
18 | static int adau1977_i2c_probe(struct i2c_client *client, | ||
19 | const struct i2c_device_id *id) | ||
20 | { | ||
21 | struct regmap_config config; | ||
22 | |||
23 | config = adau1977_regmap_config; | ||
24 | config.val_bits = 8; | ||
25 | config.reg_bits = 8; | ||
26 | |||
27 | return adau1977_probe(&client->dev, | ||
28 | devm_regmap_init_i2c(client, &config), | ||
29 | id->driver_data, NULL); | ||
30 | } | ||
31 | |||
32 | static int adau1977_i2c_remove(struct i2c_client *client) | ||
33 | { | ||
34 | snd_soc_unregister_codec(&client->dev); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | static const struct i2c_device_id adau1977_i2c_ids[] = { | ||
39 | { "adau1977", ADAU1977 }, | ||
40 | { "adau1978", ADAU1978 }, | ||
41 | { "adau1979", ADAU1978 }, | ||
42 | { } | ||
43 | }; | ||
44 | MODULE_DEVICE_TABLE(i2c, adau1977_i2c_ids); | ||
45 | |||
46 | static struct i2c_driver adau1977_i2c_driver = { | ||
47 | .driver = { | ||
48 | .name = "adau1977", | ||
49 | .owner = THIS_MODULE, | ||
50 | }, | ||
51 | .probe = adau1977_i2c_probe, | ||
52 | .remove = adau1977_i2c_remove, | ||
53 | .id_table = adau1977_i2c_ids, | ||
54 | }; | ||
55 | module_i2c_driver(adau1977_i2c_driver); | ||
56 | |||
57 | MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver"); | ||
58 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
59 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/adau1977-spi.c b/sound/soc/codecs/adau1977-spi.c new file mode 100644 index 000000000000..b05cf5da3a94 --- /dev/null +++ b/sound/soc/codecs/adau1977-spi.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * ADAU1977/ADAU1978/ADAU1979 driver | ||
3 | * | ||
4 | * Copyright 2014 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/mod_devicetable.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/regmap.h> | ||
13 | #include <linux/spi/spi.h> | ||
14 | #include <sound/soc.h> | ||
15 | |||
16 | #include "adau1977.h" | ||
17 | |||
18 | static void adau1977_spi_switch_mode(struct device *dev) | ||
19 | { | ||
20 | struct spi_device *spi = to_spi_device(dev); | ||
21 | |||
22 | /* | ||
23 | * To get the device into SPI mode CLATCH has to be pulled low three | ||
24 | * times. Do this by issuing three dummy reads. | ||
25 | */ | ||
26 | spi_w8r8(spi, 0x00); | ||
27 | spi_w8r8(spi, 0x00); | ||
28 | spi_w8r8(spi, 0x00); | ||
29 | } | ||
30 | |||
31 | static int adau1977_spi_probe(struct spi_device *spi) | ||
32 | { | ||
33 | const struct spi_device_id *id = spi_get_device_id(spi); | ||
34 | struct regmap_config config; | ||
35 | |||
36 | if (!id) | ||
37 | return -EINVAL; | ||
38 | |||
39 | config = adau1977_regmap_config; | ||
40 | config.val_bits = 8; | ||
41 | config.reg_bits = 16; | ||
42 | config.read_flag_mask = 0x1; | ||
43 | |||
44 | return adau1977_probe(&spi->dev, | ||
45 | devm_regmap_init_spi(spi, &config), | ||
46 | id->driver_data, adau1977_spi_switch_mode); | ||
47 | } | ||
48 | |||
49 | static int adau1977_spi_remove(struct spi_device *spi) | ||
50 | { | ||
51 | snd_soc_unregister_codec(&spi->dev); | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static const struct spi_device_id adau1977_spi_ids[] = { | ||
56 | { "adau1977", ADAU1977 }, | ||
57 | { "adau1978", ADAU1978 }, | ||
58 | { "adau1979", ADAU1978 }, | ||
59 | { } | ||
60 | }; | ||
61 | MODULE_DEVICE_TABLE(spi, adau1977_spi_ids); | ||
62 | |||
63 | static struct spi_driver adau1977_spi_driver = { | ||
64 | .driver = { | ||
65 | .name = "adau1977", | ||
66 | .owner = THIS_MODULE, | ||
67 | }, | ||
68 | .probe = adau1977_spi_probe, | ||
69 | .remove = adau1977_spi_remove, | ||
70 | .id_table = adau1977_spi_ids, | ||
71 | }; | ||
72 | module_spi_driver(adau1977_spi_driver); | ||
73 | |||
74 | MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver"); | ||
75 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
76 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c new file mode 100644 index 000000000000..fd55da7cb9d4 --- /dev/null +++ b/sound/soc/codecs/adau1977.c | |||
@@ -0,0 +1,1018 @@ | |||
1 | /* | ||
2 | * ADAU1977/ADAU1978/ADAU1979 driver | ||
3 | * | ||
4 | * Copyright 2014 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/delay.h> | ||
11 | #include <linux/device.h> | ||
12 | #include <linux/gpio/consumer.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/platform_data/adau1977.h> | ||
17 | #include <linux/regmap.h> | ||
18 | #include <linux/regulator/consumer.h> | ||
19 | #include <linux/slab.h> | ||
20 | |||
21 | #include <sound/core.h> | ||
22 | #include <sound/initval.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/tlv.h> | ||
27 | |||
28 | #include "adau1977.h" | ||
29 | |||
30 | #define ADAU1977_REG_POWER 0x00 | ||
31 | #define ADAU1977_REG_PLL 0x01 | ||
32 | #define ADAU1977_REG_BOOST 0x02 | ||
33 | #define ADAU1977_REG_MICBIAS 0x03 | ||
34 | #define ADAU1977_REG_BLOCK_POWER_SAI 0x04 | ||
35 | #define ADAU1977_REG_SAI_CTRL0 0x05 | ||
36 | #define ADAU1977_REG_SAI_CTRL1 0x06 | ||
37 | #define ADAU1977_REG_CMAP12 0x07 | ||
38 | #define ADAU1977_REG_CMAP34 0x08 | ||
39 | #define ADAU1977_REG_SAI_OVERTEMP 0x09 | ||
40 | #define ADAU1977_REG_POST_ADC_GAIN(x) (0x0a + (x)) | ||
41 | #define ADAU1977_REG_MISC_CONTROL 0x0e | ||
42 | #define ADAU1977_REG_DIAG_CONTROL 0x10 | ||
43 | #define ADAU1977_REG_STATUS(x) (0x11 + (x)) | ||
44 | #define ADAU1977_REG_DIAG_IRQ1 0x15 | ||
45 | #define ADAU1977_REG_DIAG_IRQ2 0x16 | ||
46 | #define ADAU1977_REG_ADJUST1 0x17 | ||
47 | #define ADAU1977_REG_ADJUST2 0x18 | ||
48 | #define ADAU1977_REG_ADC_CLIP 0x19 | ||
49 | #define ADAU1977_REG_DC_HPF_CAL 0x1a | ||
50 | |||
51 | #define ADAU1977_POWER_RESET BIT(7) | ||
52 | #define ADAU1977_POWER_PWUP BIT(0) | ||
53 | |||
54 | #define ADAU1977_PLL_CLK_S BIT(4) | ||
55 | #define ADAU1977_PLL_MCS_MASK 0x7 | ||
56 | |||
57 | #define ADAU1977_MICBIAS_MB_VOLTS_MASK 0xf0 | ||
58 | #define ADAU1977_MICBIAS_MB_VOLTS_OFFSET 4 | ||
59 | |||
60 | #define ADAU1977_BLOCK_POWER_SAI_LR_POL BIT(7) | ||
61 | #define ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE BIT(6) | ||
62 | #define ADAU1977_BLOCK_POWER_SAI_LDO_EN BIT(5) | ||
63 | |||
64 | #define ADAU1977_SAI_CTRL0_FMT_MASK (0x3 << 6) | ||
65 | #define ADAU1977_SAI_CTRL0_FMT_I2S (0x0 << 6) | ||
66 | #define ADAU1977_SAI_CTRL0_FMT_LJ (0x1 << 6) | ||
67 | #define ADAU1977_SAI_CTRL0_FMT_RJ_24BIT (0x2 << 6) | ||
68 | #define ADAU1977_SAI_CTRL0_FMT_RJ_16BIT (0x3 << 6) | ||
69 | |||
70 | #define ADAU1977_SAI_CTRL0_SAI_MASK (0x7 << 3) | ||
71 | #define ADAU1977_SAI_CTRL0_SAI_I2S (0x0 << 3) | ||
72 | #define ADAU1977_SAI_CTRL0_SAI_TDM_2 (0x1 << 3) | ||
73 | #define ADAU1977_SAI_CTRL0_SAI_TDM_4 (0x2 << 3) | ||
74 | #define ADAU1977_SAI_CTRL0_SAI_TDM_8 (0x3 << 3) | ||
75 | #define ADAU1977_SAI_CTRL0_SAI_TDM_16 (0x4 << 3) | ||
76 | |||
77 | #define ADAU1977_SAI_CTRL0_FS_MASK (0x7) | ||
78 | #define ADAU1977_SAI_CTRL0_FS_8000_12000 (0x0) | ||
79 | #define ADAU1977_SAI_CTRL0_FS_16000_24000 (0x1) | ||
80 | #define ADAU1977_SAI_CTRL0_FS_32000_48000 (0x2) | ||
81 | #define ADAU1977_SAI_CTRL0_FS_64000_96000 (0x3) | ||
82 | #define ADAU1977_SAI_CTRL0_FS_128000_192000 (0x4) | ||
83 | |||
84 | #define ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK (0x3 << 5) | ||
85 | #define ADAU1977_SAI_CTRL1_SLOT_WIDTH_32 (0x0 << 5) | ||
86 | #define ADAU1977_SAI_CTRL1_SLOT_WIDTH_24 (0x1 << 5) | ||
87 | #define ADAU1977_SAI_CTRL1_SLOT_WIDTH_16 (0x2 << 5) | ||
88 | #define ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK (0x1 << 4) | ||
89 | #define ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT (0x1 << 4) | ||
90 | #define ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT (0x0 << 4) | ||
91 | #define ADAU1977_SAI_CTRL1_LRCLK_PULSE BIT(3) | ||
92 | #define ADAU1977_SAI_CTRL1_MSB BIT(2) | ||
93 | #define ADAU1977_SAI_CTRL1_BCLKRATE_16 (0x1 << 1) | ||
94 | #define ADAU1977_SAI_CTRL1_BCLKRATE_32 (0x0 << 1) | ||
95 | #define ADAU1977_SAI_CTRL1_BCLKRATE_MASK (0x1 << 1) | ||
96 | #define ADAU1977_SAI_CTRL1_MASTER BIT(0) | ||
97 | |||
98 | #define ADAU1977_SAI_OVERTEMP_DRV_C(x) BIT(4 + (x)) | ||
99 | #define ADAU1977_SAI_OVERTEMP_DRV_HIZ BIT(3) | ||
100 | |||
101 | #define ADAU1977_MISC_CONTROL_SUM_MODE_MASK (0x3 << 6) | ||
102 | #define ADAU1977_MISC_CONTROL_SUM_MODE_1CH (0x2 << 6) | ||
103 | #define ADAU1977_MISC_CONTROL_SUM_MODE_2CH (0x1 << 6) | ||
104 | #define ADAU1977_MISC_CONTROL_SUM_MODE_4CH (0x0 << 6) | ||
105 | #define ADAU1977_MISC_CONTROL_MMUTE BIT(4) | ||
106 | #define ADAU1977_MISC_CONTROL_DC_CAL BIT(0) | ||
107 | |||
108 | #define ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET 4 | ||
109 | #define ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET 0 | ||
110 | |||
111 | struct adau1977 { | ||
112 | struct regmap *regmap; | ||
113 | bool right_j; | ||
114 | unsigned int sysclk; | ||
115 | enum adau1977_sysclk_src sysclk_src; | ||
116 | struct gpio_desc *reset_gpio; | ||
117 | enum adau1977_type type; | ||
118 | |||
119 | struct regulator *avdd_reg; | ||
120 | struct regulator *dvdd_reg; | ||
121 | |||
122 | struct snd_pcm_hw_constraint_list constraints; | ||
123 | |||
124 | struct device *dev; | ||
125 | void (*switch_mode)(struct device *dev); | ||
126 | |||
127 | unsigned int max_master_fs; | ||
128 | unsigned int slot_width; | ||
129 | bool enabled; | ||
130 | bool master; | ||
131 | }; | ||
132 | |||
133 | static const struct reg_default adau1977_reg_defaults[] = { | ||
134 | { 0x00, 0x00 }, | ||
135 | { 0x01, 0x41 }, | ||
136 | { 0x02, 0x4a }, | ||
137 | { 0x03, 0x7d }, | ||
138 | { 0x04, 0x3d }, | ||
139 | { 0x05, 0x02 }, | ||
140 | { 0x06, 0x00 }, | ||
141 | { 0x07, 0x10 }, | ||
142 | { 0x08, 0x32 }, | ||
143 | { 0x09, 0xf0 }, | ||
144 | { 0x0a, 0xa0 }, | ||
145 | { 0x0b, 0xa0 }, | ||
146 | { 0x0c, 0xa0 }, | ||
147 | { 0x0d, 0xa0 }, | ||
148 | { 0x0e, 0x02 }, | ||
149 | { 0x10, 0x0f }, | ||
150 | { 0x15, 0x20 }, | ||
151 | { 0x16, 0x00 }, | ||
152 | { 0x17, 0x00 }, | ||
153 | { 0x18, 0x00 }, | ||
154 | { 0x1a, 0x00 }, | ||
155 | }; | ||
156 | |||
157 | static const DECLARE_TLV_DB_MINMAX_MUTE(adau1977_adc_gain, -3562, 6000); | ||
158 | |||
159 | static const struct snd_soc_dapm_widget adau1977_micbias_dapm_widgets[] = { | ||
160 | SND_SOC_DAPM_SUPPLY("MICBIAS", ADAU1977_REG_MICBIAS, | ||
161 | 3, 0, NULL, 0) | ||
162 | }; | ||
163 | |||
164 | static const struct snd_soc_dapm_widget adau1977_dapm_widgets[] = { | ||
165 | SND_SOC_DAPM_SUPPLY("Vref", ADAU1977_REG_BLOCK_POWER_SAI, | ||
166 | 4, 0, NULL, 0), | ||
167 | |||
168 | SND_SOC_DAPM_ADC("ADC1", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 0, 0), | ||
169 | SND_SOC_DAPM_ADC("ADC2", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 1, 0), | ||
170 | SND_SOC_DAPM_ADC("ADC3", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 2, 0), | ||
171 | SND_SOC_DAPM_ADC("ADC4", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 3, 0), | ||
172 | |||
173 | SND_SOC_DAPM_INPUT("AIN1"), | ||
174 | SND_SOC_DAPM_INPUT("AIN2"), | ||
175 | SND_SOC_DAPM_INPUT("AIN3"), | ||
176 | SND_SOC_DAPM_INPUT("AIN4"), | ||
177 | |||
178 | SND_SOC_DAPM_OUTPUT("VREF"), | ||
179 | }; | ||
180 | |||
181 | static const struct snd_soc_dapm_route adau1977_dapm_routes[] = { | ||
182 | { "ADC1", NULL, "AIN1" }, | ||
183 | { "ADC2", NULL, "AIN2" }, | ||
184 | { "ADC3", NULL, "AIN3" }, | ||
185 | { "ADC4", NULL, "AIN4" }, | ||
186 | |||
187 | { "ADC1", NULL, "Vref" }, | ||
188 | { "ADC2", NULL, "Vref" }, | ||
189 | { "ADC3", NULL, "Vref" }, | ||
190 | { "ADC4", NULL, "Vref" }, | ||
191 | |||
192 | { "VREF", NULL, "Vref" }, | ||
193 | }; | ||
194 | |||
195 | #define ADAU1977_VOLUME(x) \ | ||
196 | SOC_SINGLE_TLV("ADC" #x " Capture Volume", \ | ||
197 | ADAU1977_REG_POST_ADC_GAIN((x) - 1), \ | ||
198 | 0, 255, 1, adau1977_adc_gain) | ||
199 | |||
200 | #define ADAU1977_HPF_SWITCH(x) \ | ||
201 | SOC_SINGLE("ADC" #x " Highpass-Filter Capture Switch", \ | ||
202 | ADAU1977_REG_DC_HPF_CAL, (x) - 1, 1, 0) | ||
203 | |||
204 | #define ADAU1977_DC_SUB_SWITCH(x) \ | ||
205 | SOC_SINGLE("ADC" #x " DC Substraction Capture Switch", \ | ||
206 | ADAU1977_REG_DC_HPF_CAL, (x) + 3, 1, 0) | ||
207 | |||
208 | static const struct snd_kcontrol_new adau1977_snd_controls[] = { | ||
209 | ADAU1977_VOLUME(1), | ||
210 | ADAU1977_VOLUME(2), | ||
211 | ADAU1977_VOLUME(3), | ||
212 | ADAU1977_VOLUME(4), | ||
213 | |||
214 | ADAU1977_HPF_SWITCH(1), | ||
215 | ADAU1977_HPF_SWITCH(2), | ||
216 | ADAU1977_HPF_SWITCH(3), | ||
217 | ADAU1977_HPF_SWITCH(4), | ||
218 | |||
219 | ADAU1977_DC_SUB_SWITCH(1), | ||
220 | ADAU1977_DC_SUB_SWITCH(2), | ||
221 | ADAU1977_DC_SUB_SWITCH(3), | ||
222 | ADAU1977_DC_SUB_SWITCH(4), | ||
223 | }; | ||
224 | |||
225 | static int adau1977_reset(struct adau1977 *adau1977) | ||
226 | { | ||
227 | int ret; | ||
228 | |||
229 | /* | ||
230 | * The reset bit is obviously volatile, but we need to be able to cache | ||
231 | * the other bits in the register, so we can't just mark the whole | ||
232 | * register as volatile. Since this is the only place where we'll ever | ||
233 | * touch the reset bit just bypass the cache for this operation. | ||
234 | */ | ||
235 | regcache_cache_bypass(adau1977->regmap, true); | ||
236 | ret = regmap_write(adau1977->regmap, ADAU1977_REG_POWER, | ||
237 | ADAU1977_POWER_RESET); | ||
238 | regcache_cache_bypass(adau1977->regmap, false); | ||
239 | if (ret) | ||
240 | return ret; | ||
241 | |||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | /* | ||
246 | * Returns the appropriate setting for ths FS field in the CTRL0 register | ||
247 | * depending on the rate. | ||
248 | */ | ||
249 | static int adau1977_lookup_fs(unsigned int rate) | ||
250 | { | ||
251 | if (rate >= 8000 && rate <= 12000) | ||
252 | return ADAU1977_SAI_CTRL0_FS_8000_12000; | ||
253 | else if (rate >= 16000 && rate <= 24000) | ||
254 | return ADAU1977_SAI_CTRL0_FS_16000_24000; | ||
255 | else if (rate >= 32000 && rate <= 48000) | ||
256 | return ADAU1977_SAI_CTRL0_FS_32000_48000; | ||
257 | else if (rate >= 64000 && rate <= 96000) | ||
258 | return ADAU1977_SAI_CTRL0_FS_64000_96000; | ||
259 | else if (rate >= 128000 && rate <= 192000) | ||
260 | return ADAU1977_SAI_CTRL0_FS_128000_192000; | ||
261 | else | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | |||
265 | static int adau1977_lookup_mcs(struct adau1977 *adau1977, unsigned int rate, | ||
266 | unsigned int fs) | ||
267 | { | ||
268 | unsigned int mcs; | ||
269 | |||
270 | /* | ||
271 | * rate = sysclk / (512 * mcs_lut[mcs]) * 2**fs | ||
272 | * => mcs_lut[mcs] = sysclk / (512 * rate) * 2**fs | ||
273 | * => mcs_lut[mcs] = sysclk / ((512 / 2**fs) * rate) | ||
274 | */ | ||
275 | |||
276 | rate *= 512 >> fs; | ||
277 | |||
278 | if (adau1977->sysclk % rate != 0) | ||
279 | return -EINVAL; | ||
280 | |||
281 | mcs = adau1977->sysclk / rate; | ||
282 | |||
283 | /* The factors configured by MCS are 1, 2, 3, 4, 6 */ | ||
284 | if (mcs < 1 || mcs > 6 || mcs == 5) | ||
285 | return -EINVAL; | ||
286 | |||
287 | mcs = mcs - 1; | ||
288 | if (mcs == 5) | ||
289 | mcs = 4; | ||
290 | |||
291 | return mcs; | ||
292 | } | ||
293 | |||
294 | static int adau1977_hw_params(struct snd_pcm_substream *substream, | ||
295 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
296 | { | ||
297 | struct snd_soc_codec *codec = dai->codec; | ||
298 | struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); | ||
299 | unsigned int rate = params_rate(params); | ||
300 | unsigned int slot_width; | ||
301 | unsigned int ctrl0, ctrl0_mask; | ||
302 | unsigned int ctrl1; | ||
303 | int mcs, fs; | ||
304 | int ret; | ||
305 | |||
306 | fs = adau1977_lookup_fs(rate); | ||
307 | if (fs < 0) | ||
308 | return fs; | ||
309 | |||
310 | if (adau1977->sysclk_src == ADAU1977_SYSCLK_SRC_MCLK) { | ||
311 | mcs = adau1977_lookup_mcs(adau1977, rate, fs); | ||
312 | if (mcs < 0) | ||
313 | return mcs; | ||
314 | } else { | ||
315 | mcs = 0; | ||
316 | } | ||
317 | |||
318 | ctrl0_mask = ADAU1977_SAI_CTRL0_FS_MASK; | ||
319 | ctrl0 = fs; | ||
320 | |||
321 | if (adau1977->right_j) { | ||
322 | switch (params_width(params)) { | ||
323 | case 16: | ||
324 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_16BIT; | ||
325 | break; | ||
326 | case 24: | ||
327 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; | ||
328 | break; | ||
329 | default: | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | ctrl0_mask |= ADAU1977_SAI_CTRL0_FMT_MASK; | ||
333 | } | ||
334 | |||
335 | if (adau1977->master) { | ||
336 | switch (params_width(params)) { | ||
337 | case 16: | ||
338 | ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT; | ||
339 | slot_width = 16; | ||
340 | break; | ||
341 | case 24: | ||
342 | case 32: | ||
343 | ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT; | ||
344 | slot_width = 32; | ||
345 | break; | ||
346 | default: | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | |||
350 | /* In TDM mode there is a fixed slot width */ | ||
351 | if (adau1977->slot_width) | ||
352 | slot_width = adau1977->slot_width; | ||
353 | |||
354 | if (slot_width == 16) | ||
355 | ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_16; | ||
356 | else | ||
357 | ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_32; | ||
358 | |||
359 | ret = regmap_update_bits(adau1977->regmap, | ||
360 | ADAU1977_REG_SAI_CTRL1, | ||
361 | ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK | | ||
362 | ADAU1977_SAI_CTRL1_BCLKRATE_MASK, | ||
363 | ctrl1); | ||
364 | if (ret < 0) | ||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, | ||
369 | ctrl0_mask, ctrl0); | ||
370 | if (ret < 0) | ||
371 | return ret; | ||
372 | |||
373 | return regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL, | ||
374 | ADAU1977_PLL_MCS_MASK, mcs); | ||
375 | } | ||
376 | |||
377 | static int adau1977_power_disable(struct adau1977 *adau1977) | ||
378 | { | ||
379 | int ret = 0; | ||
380 | |||
381 | if (!adau1977->enabled) | ||
382 | return 0; | ||
383 | |||
384 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER, | ||
385 | ADAU1977_POWER_PWUP, 0); | ||
386 | if (ret) | ||
387 | return ret; | ||
388 | |||
389 | regcache_mark_dirty(adau1977->regmap); | ||
390 | |||
391 | if (adau1977->reset_gpio) | ||
392 | gpiod_set_value_cansleep(adau1977->reset_gpio, 0); | ||
393 | |||
394 | regcache_cache_only(adau1977->regmap, true); | ||
395 | |||
396 | regulator_disable(adau1977->avdd_reg); | ||
397 | if (adau1977->dvdd_reg) | ||
398 | regulator_disable(adau1977->dvdd_reg); | ||
399 | |||
400 | adau1977->enabled = false; | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static int adau1977_power_enable(struct adau1977 *adau1977) | ||
406 | { | ||
407 | unsigned int val; | ||
408 | int ret = 0; | ||
409 | |||
410 | if (adau1977->enabled) | ||
411 | return 0; | ||
412 | |||
413 | ret = regulator_enable(adau1977->avdd_reg); | ||
414 | if (ret) | ||
415 | return ret; | ||
416 | |||
417 | if (adau1977->dvdd_reg) { | ||
418 | ret = regulator_enable(adau1977->dvdd_reg); | ||
419 | if (ret) | ||
420 | goto err_disable_avdd; | ||
421 | } | ||
422 | |||
423 | if (adau1977->reset_gpio) | ||
424 | gpiod_set_value_cansleep(adau1977->reset_gpio, 1); | ||
425 | |||
426 | regcache_cache_only(adau1977->regmap, false); | ||
427 | |||
428 | if (adau1977->switch_mode) | ||
429 | adau1977->switch_mode(adau1977->dev); | ||
430 | |||
431 | ret = adau1977_reset(adau1977); | ||
432 | if (ret) | ||
433 | goto err_disable_dvdd; | ||
434 | |||
435 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER, | ||
436 | ADAU1977_POWER_PWUP, ADAU1977_POWER_PWUP); | ||
437 | if (ret) | ||
438 | goto err_disable_dvdd; | ||
439 | |||
440 | ret = regcache_sync(adau1977->regmap); | ||
441 | if (ret) | ||
442 | goto err_disable_dvdd; | ||
443 | |||
444 | /* | ||
445 | * The PLL register is not affected by the software reset. It is | ||
446 | * possible that the value of the register was changed to the | ||
447 | * default value while we were in cache only mode. In this case | ||
448 | * regcache_sync will skip over it and we have to manually sync | ||
449 | * it. | ||
450 | */ | ||
451 | ret = regmap_read(adau1977->regmap, ADAU1977_REG_PLL, &val); | ||
452 | if (ret) | ||
453 | goto err_disable_dvdd; | ||
454 | |||
455 | if (val == 0x41) { | ||
456 | regcache_cache_bypass(adau1977->regmap, true); | ||
457 | ret = regmap_write(adau1977->regmap, ADAU1977_REG_PLL, | ||
458 | 0x41); | ||
459 | if (ret) | ||
460 | goto err_disable_dvdd; | ||
461 | regcache_cache_bypass(adau1977->regmap, false); | ||
462 | } | ||
463 | |||
464 | adau1977->enabled = true; | ||
465 | |||
466 | return ret; | ||
467 | |||
468 | err_disable_dvdd: | ||
469 | if (adau1977->dvdd_reg) | ||
470 | regulator_disable(adau1977->dvdd_reg); | ||
471 | err_disable_avdd: | ||
472 | regulator_disable(adau1977->avdd_reg); | ||
473 | return ret; | ||
474 | } | ||
475 | |||
476 | static int adau1977_set_bias_level(struct snd_soc_codec *codec, | ||
477 | enum snd_soc_bias_level level) | ||
478 | { | ||
479 | struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); | ||
480 | int ret = 0; | ||
481 | |||
482 | switch (level) { | ||
483 | case SND_SOC_BIAS_ON: | ||
484 | break; | ||
485 | case SND_SOC_BIAS_PREPARE: | ||
486 | break; | ||
487 | case SND_SOC_BIAS_STANDBY: | ||
488 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | ||
489 | ret = adau1977_power_enable(adau1977); | ||
490 | break; | ||
491 | case SND_SOC_BIAS_OFF: | ||
492 | ret = adau1977_power_disable(adau1977); | ||
493 | break; | ||
494 | } | ||
495 | |||
496 | if (ret) | ||
497 | return ret; | ||
498 | |||
499 | codec->dapm.bias_level = level; | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static int adau1977_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | ||
505 | unsigned int rx_mask, int slots, int width) | ||
506 | { | ||
507 | struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); | ||
508 | unsigned int ctrl0, ctrl1, drv; | ||
509 | unsigned int slot[4]; | ||
510 | unsigned int i; | ||
511 | int ret; | ||
512 | |||
513 | if (slots == 0) { | ||
514 | /* 0 = No fixed slot width */ | ||
515 | adau1977->slot_width = 0; | ||
516 | adau1977->max_master_fs = 192000; | ||
517 | return regmap_update_bits(adau1977->regmap, | ||
518 | ADAU1977_REG_SAI_CTRL0, ADAU1977_SAI_CTRL0_SAI_MASK, | ||
519 | ADAU1977_SAI_CTRL0_SAI_I2S); | ||
520 | } | ||
521 | |||
522 | if (rx_mask == 0 || tx_mask != 0) | ||
523 | return -EINVAL; | ||
524 | |||
525 | drv = 0; | ||
526 | for (i = 0; i < 4; i++) { | ||
527 | slot[i] = __ffs(rx_mask); | ||
528 | drv |= ADAU1977_SAI_OVERTEMP_DRV_C(i); | ||
529 | rx_mask &= ~(1 << slot[i]); | ||
530 | if (slot[i] >= slots) | ||
531 | return -EINVAL; | ||
532 | if (rx_mask == 0) | ||
533 | break; | ||
534 | } | ||
535 | |||
536 | if (rx_mask != 0) | ||
537 | return -EINVAL; | ||
538 | |||
539 | switch (width) { | ||
540 | case 16: | ||
541 | ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_16; | ||
542 | break; | ||
543 | case 24: | ||
544 | /* We can only generate 16 bit or 32 bit wide slots */ | ||
545 | if (adau1977->master) | ||
546 | return -EINVAL; | ||
547 | ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_24; | ||
548 | break; | ||
549 | case 32: | ||
550 | ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_32; | ||
551 | break; | ||
552 | default: | ||
553 | return -EINVAL; | ||
554 | } | ||
555 | |||
556 | switch (slots) { | ||
557 | case 2: | ||
558 | ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_2; | ||
559 | break; | ||
560 | case 4: | ||
561 | ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_4; | ||
562 | break; | ||
563 | case 8: | ||
564 | ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_8; | ||
565 | break; | ||
566 | case 16: | ||
567 | ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_16; | ||
568 | break; | ||
569 | default: | ||
570 | return -EINVAL; | ||
571 | } | ||
572 | |||
573 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP, | ||
574 | ADAU1977_SAI_OVERTEMP_DRV_C(0) | | ||
575 | ADAU1977_SAI_OVERTEMP_DRV_C(1) | | ||
576 | ADAU1977_SAI_OVERTEMP_DRV_C(2) | | ||
577 | ADAU1977_SAI_OVERTEMP_DRV_C(3), drv); | ||
578 | if (ret) | ||
579 | return ret; | ||
580 | |||
581 | ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP12, | ||
582 | (slot[1] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) | | ||
583 | (slot[0] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET)); | ||
584 | if (ret) | ||
585 | return ret; | ||
586 | |||
587 | ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP34, | ||
588 | (slot[3] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) | | ||
589 | (slot[2] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET)); | ||
590 | if (ret) | ||
591 | return ret; | ||
592 | |||
593 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, | ||
594 | ADAU1977_SAI_CTRL0_SAI_MASK, ctrl0); | ||
595 | if (ret) | ||
596 | return ret; | ||
597 | |||
598 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1, | ||
599 | ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK, ctrl1); | ||
600 | if (ret) | ||
601 | return ret; | ||
602 | |||
603 | adau1977->slot_width = width; | ||
604 | |||
605 | /* In master mode the maximum bitclock is 24.576 MHz */ | ||
606 | adau1977->max_master_fs = min(192000, 24576000 / width / slots); | ||
607 | |||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | static int adau1977_mute(struct snd_soc_dai *dai, int mute, int stream) | ||
612 | { | ||
613 | struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); | ||
614 | unsigned int val; | ||
615 | |||
616 | if (mute) | ||
617 | val = ADAU1977_MISC_CONTROL_MMUTE; | ||
618 | else | ||
619 | val = 0; | ||
620 | |||
621 | return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MISC_CONTROL, | ||
622 | ADAU1977_MISC_CONTROL_MMUTE, val); | ||
623 | } | ||
624 | |||
625 | static int adau1977_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
626 | { | ||
627 | struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); | ||
628 | unsigned int ctrl0 = 0, ctrl1 = 0, block_power = 0; | ||
629 | bool invert_lrclk; | ||
630 | int ret; | ||
631 | |||
632 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
633 | case SND_SOC_DAIFMT_CBS_CFS: | ||
634 | adau1977->master = false; | ||
635 | break; | ||
636 | case SND_SOC_DAIFMT_CBM_CFM: | ||
637 | ctrl1 |= ADAU1977_SAI_CTRL1_MASTER; | ||
638 | adau1977->master = true; | ||
639 | break; | ||
640 | default: | ||
641 | return -EINVAL; | ||
642 | } | ||
643 | |||
644 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
645 | case SND_SOC_DAIFMT_NB_NF: | ||
646 | invert_lrclk = false; | ||
647 | break; | ||
648 | case SND_SOC_DAIFMT_IB_NF: | ||
649 | block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE; | ||
650 | invert_lrclk = false; | ||
651 | break; | ||
652 | case SND_SOC_DAIFMT_NB_IF: | ||
653 | invert_lrclk = true; | ||
654 | break; | ||
655 | case SND_SOC_DAIFMT_IB_IF: | ||
656 | block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE; | ||
657 | invert_lrclk = true; | ||
658 | break; | ||
659 | default: | ||
660 | return -EINVAL; | ||
661 | } | ||
662 | |||
663 | adau1977->right_j = false; | ||
664 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
665 | case SND_SOC_DAIFMT_I2S: | ||
666 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S; | ||
667 | break; | ||
668 | case SND_SOC_DAIFMT_LEFT_J: | ||
669 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ; | ||
670 | invert_lrclk = !invert_lrclk; | ||
671 | break; | ||
672 | case SND_SOC_DAIFMT_RIGHT_J: | ||
673 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; | ||
674 | adau1977->right_j = true; | ||
675 | invert_lrclk = !invert_lrclk; | ||
676 | break; | ||
677 | case SND_SOC_DAIFMT_DSP_A: | ||
678 | ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE; | ||
679 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S; | ||
680 | invert_lrclk = false; | ||
681 | break; | ||
682 | case SND_SOC_DAIFMT_DSP_B: | ||
683 | ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE; | ||
684 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ; | ||
685 | invert_lrclk = false; | ||
686 | break; | ||
687 | default: | ||
688 | return -EINVAL; | ||
689 | } | ||
690 | |||
691 | if (invert_lrclk) | ||
692 | block_power |= ADAU1977_BLOCK_POWER_SAI_LR_POL; | ||
693 | |||
694 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, | ||
695 | ADAU1977_BLOCK_POWER_SAI_LR_POL | | ||
696 | ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE, block_power); | ||
697 | if (ret) | ||
698 | return ret; | ||
699 | |||
700 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, | ||
701 | ADAU1977_SAI_CTRL0_FMT_MASK, | ||
702 | ctrl0); | ||
703 | if (ret) | ||
704 | return ret; | ||
705 | |||
706 | return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1, | ||
707 | ADAU1977_SAI_CTRL1_MASTER | ADAU1977_SAI_CTRL1_LRCLK_PULSE, | ||
708 | ctrl1); | ||
709 | } | ||
710 | |||
711 | static int adau1977_startup(struct snd_pcm_substream *substream, | ||
712 | struct snd_soc_dai *dai) | ||
713 | { | ||
714 | struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); | ||
715 | u64 formats = 0; | ||
716 | |||
717 | if (adau1977->slot_width == 16) | ||
718 | formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE; | ||
719 | else if (adau1977->right_j || adau1977->slot_width == 24) | ||
720 | formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | | ||
721 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE; | ||
722 | |||
723 | snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
724 | SNDRV_PCM_HW_PARAM_RATE, &adau1977->constraints); | ||
725 | |||
726 | if (adau1977->master) | ||
727 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
728 | SNDRV_PCM_HW_PARAM_RATE, 8000, adau1977->max_master_fs); | ||
729 | |||
730 | if (formats != 0) | ||
731 | snd_pcm_hw_constraint_mask64(substream->runtime, | ||
732 | SNDRV_PCM_HW_PARAM_FORMAT, formats); | ||
733 | |||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | static int adau1977_set_tristate(struct snd_soc_dai *dai, int tristate) | ||
738 | { | ||
739 | struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); | ||
740 | unsigned int val; | ||
741 | |||
742 | if (tristate) | ||
743 | val = ADAU1977_SAI_OVERTEMP_DRV_HIZ; | ||
744 | else | ||
745 | val = 0; | ||
746 | |||
747 | return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP, | ||
748 | ADAU1977_SAI_OVERTEMP_DRV_HIZ, val); | ||
749 | } | ||
750 | |||
751 | static const struct snd_soc_dai_ops adau1977_dai_ops = { | ||
752 | .startup = adau1977_startup, | ||
753 | .hw_params = adau1977_hw_params, | ||
754 | .mute_stream = adau1977_mute, | ||
755 | .set_fmt = adau1977_set_dai_fmt, | ||
756 | .set_tdm_slot = adau1977_set_tdm_slot, | ||
757 | .set_tristate = adau1977_set_tristate, | ||
758 | }; | ||
759 | |||
760 | static struct snd_soc_dai_driver adau1977_dai = { | ||
761 | .name = "adau1977-hifi", | ||
762 | .capture = { | ||
763 | .stream_name = "Capture", | ||
764 | .channels_min = 1, | ||
765 | .channels_max = 4, | ||
766 | .rates = SNDRV_PCM_RATE_KNOT, | ||
767 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | | ||
768 | SNDRV_PCM_FMTBIT_S32_LE, | ||
769 | .sig_bits = 24, | ||
770 | }, | ||
771 | .ops = &adau1977_dai_ops, | ||
772 | }; | ||
773 | |||
774 | static const unsigned int adau1977_rates[] = { | ||
775 | 8000, 16000, 32000, 64000, 128000, | ||
776 | 11025, 22050, 44100, 88200, 172400, | ||
777 | 12000, 24000, 48000, 96000, 192000, | ||
778 | }; | ||
779 | |||
780 | #define ADAU1977_RATE_CONSTRAINT_MASK_32000 0x001f | ||
781 | #define ADAU1977_RATE_CONSTRAINT_MASK_44100 0x03e0 | ||
782 | #define ADAU1977_RATE_CONSTRAINT_MASK_48000 0x7c00 | ||
783 | /* All rates >= 32000 */ | ||
784 | #define ADAU1977_RATE_CONSTRAINT_MASK_LRCLK 0x739c | ||
785 | |||
786 | static bool adau1977_check_sysclk(unsigned int mclk, unsigned int base_freq) | ||
787 | { | ||
788 | unsigned int mcs; | ||
789 | |||
790 | if (mclk % (base_freq * 128) != 0) | ||
791 | return false; | ||
792 | |||
793 | mcs = mclk / (128 * base_freq); | ||
794 | if (mcs < 1 || mcs > 6 || mcs == 5) | ||
795 | return false; | ||
796 | |||
797 | return true; | ||
798 | } | ||
799 | |||
800 | static int adau1977_set_sysclk(struct snd_soc_codec *codec, | ||
801 | int clk_id, int source, unsigned int freq, int dir) | ||
802 | { | ||
803 | struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); | ||
804 | unsigned int mask = 0; | ||
805 | unsigned int clk_src; | ||
806 | unsigned int ret; | ||
807 | |||
808 | if (dir != SND_SOC_CLOCK_IN) | ||
809 | return -EINVAL; | ||
810 | |||
811 | if (clk_id != ADAU1977_SYSCLK) | ||
812 | return -EINVAL; | ||
813 | |||
814 | switch (source) { | ||
815 | case ADAU1977_SYSCLK_SRC_MCLK: | ||
816 | clk_src = 0; | ||
817 | break; | ||
818 | case ADAU1977_SYSCLK_SRC_LRCLK: | ||
819 | clk_src = ADAU1977_PLL_CLK_S; | ||
820 | break; | ||
821 | default: | ||
822 | return -EINVAL; | ||
823 | } | ||
824 | |||
825 | if (freq != 0 && source == ADAU1977_SYSCLK_SRC_MCLK) { | ||
826 | if (freq < 4000000 || freq > 36864000) | ||
827 | return -EINVAL; | ||
828 | |||
829 | if (adau1977_check_sysclk(freq, 32000)) | ||
830 | mask |= ADAU1977_RATE_CONSTRAINT_MASK_32000; | ||
831 | if (adau1977_check_sysclk(freq, 44100)) | ||
832 | mask |= ADAU1977_RATE_CONSTRAINT_MASK_44100; | ||
833 | if (adau1977_check_sysclk(freq, 48000)) | ||
834 | mask |= ADAU1977_RATE_CONSTRAINT_MASK_48000; | ||
835 | |||
836 | if (mask == 0) | ||
837 | return -EINVAL; | ||
838 | } else if (source == ADAU1977_SYSCLK_SRC_LRCLK) { | ||
839 | mask = ADAU1977_RATE_CONSTRAINT_MASK_LRCLK; | ||
840 | } | ||
841 | |||
842 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL, | ||
843 | ADAU1977_PLL_CLK_S, clk_src); | ||
844 | if (ret) | ||
845 | return ret; | ||
846 | |||
847 | adau1977->constraints.mask = mask; | ||
848 | adau1977->sysclk_src = source; | ||
849 | adau1977->sysclk = freq; | ||
850 | |||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | static int adau1977_codec_probe(struct snd_soc_codec *codec) | ||
855 | { | ||
856 | struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); | ||
857 | int ret; | ||
858 | |||
859 | switch (adau1977->type) { | ||
860 | case ADAU1977: | ||
861 | ret = snd_soc_dapm_new_controls(&codec->dapm, | ||
862 | adau1977_micbias_dapm_widgets, | ||
863 | ARRAY_SIZE(adau1977_micbias_dapm_widgets)); | ||
864 | if (ret < 0) | ||
865 | return ret; | ||
866 | break; | ||
867 | default: | ||
868 | break; | ||
869 | } | ||
870 | |||
871 | return 0; | ||
872 | } | ||
873 | |||
874 | static struct snd_soc_codec_driver adau1977_codec_driver = { | ||
875 | .probe = adau1977_codec_probe, | ||
876 | .set_bias_level = adau1977_set_bias_level, | ||
877 | .set_sysclk = adau1977_set_sysclk, | ||
878 | .idle_bias_off = true, | ||
879 | |||
880 | .controls = adau1977_snd_controls, | ||
881 | .num_controls = ARRAY_SIZE(adau1977_snd_controls), | ||
882 | .dapm_widgets = adau1977_dapm_widgets, | ||
883 | .num_dapm_widgets = ARRAY_SIZE(adau1977_dapm_widgets), | ||
884 | .dapm_routes = adau1977_dapm_routes, | ||
885 | .num_dapm_routes = ARRAY_SIZE(adau1977_dapm_routes), | ||
886 | }; | ||
887 | |||
888 | static int adau1977_setup_micbias(struct adau1977 *adau1977) | ||
889 | { | ||
890 | struct adau1977_platform_data *pdata = adau1977->dev->platform_data; | ||
891 | unsigned int micbias; | ||
892 | |||
893 | if (pdata) { | ||
894 | micbias = pdata->micbias; | ||
895 | if (micbias > ADAU1977_MICBIAS_9V0) | ||
896 | return -EINVAL; | ||
897 | |||
898 | } else { | ||
899 | micbias = ADAU1977_MICBIAS_8V5; | ||
900 | } | ||
901 | |||
902 | return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MICBIAS, | ||
903 | ADAU1977_MICBIAS_MB_VOLTS_MASK, | ||
904 | micbias << ADAU1977_MICBIAS_MB_VOLTS_OFFSET); | ||
905 | } | ||
906 | |||
907 | int adau1977_probe(struct device *dev, struct regmap *regmap, | ||
908 | enum adau1977_type type, void (*switch_mode)(struct device *dev)) | ||
909 | { | ||
910 | unsigned int power_off_mask; | ||
911 | struct adau1977 *adau1977; | ||
912 | int ret; | ||
913 | |||
914 | if (IS_ERR(regmap)) | ||
915 | return PTR_ERR(regmap); | ||
916 | |||
917 | adau1977 = devm_kzalloc(dev, sizeof(*adau1977), GFP_KERNEL); | ||
918 | if (adau1977 == NULL) | ||
919 | return -ENOMEM; | ||
920 | |||
921 | adau1977->dev = dev; | ||
922 | adau1977->type = type; | ||
923 | adau1977->regmap = regmap; | ||
924 | adau1977->switch_mode = switch_mode; | ||
925 | adau1977->max_master_fs = 192000; | ||
926 | |||
927 | adau1977->constraints.list = adau1977_rates; | ||
928 | adau1977->constraints.count = ARRAY_SIZE(adau1977_rates); | ||
929 | |||
930 | adau1977->avdd_reg = devm_regulator_get(dev, "AVDD"); | ||
931 | if (IS_ERR(adau1977->avdd_reg)) | ||
932 | return PTR_ERR(adau1977->avdd_reg); | ||
933 | |||
934 | adau1977->dvdd_reg = devm_regulator_get_optional(dev, "DVDD"); | ||
935 | if (IS_ERR(adau1977->dvdd_reg)) { | ||
936 | if (PTR_ERR(adau1977->dvdd_reg) != -ENODEV) | ||
937 | return PTR_ERR(adau1977->dvdd_reg); | ||
938 | adau1977->dvdd_reg = NULL; | ||
939 | } | ||
940 | |||
941 | adau1977->reset_gpio = devm_gpiod_get(dev, "reset"); | ||
942 | if (IS_ERR(adau1977->reset_gpio)) { | ||
943 | ret = PTR_ERR(adau1977->reset_gpio); | ||
944 | if (ret != -ENOENT && ret != -ENOSYS) | ||
945 | return PTR_ERR(adau1977->reset_gpio); | ||
946 | adau1977->reset_gpio = NULL; | ||
947 | } | ||
948 | |||
949 | dev_set_drvdata(dev, adau1977); | ||
950 | |||
951 | if (adau1977->reset_gpio) { | ||
952 | ret = gpiod_direction_output(adau1977->reset_gpio, 0); | ||
953 | if (ret) | ||
954 | return ret; | ||
955 | ndelay(100); | ||
956 | } | ||
957 | |||
958 | ret = adau1977_power_enable(adau1977); | ||
959 | if (ret) | ||
960 | return ret; | ||
961 | |||
962 | if (type == ADAU1977) { | ||
963 | ret = adau1977_setup_micbias(adau1977); | ||
964 | if (ret) | ||
965 | goto err_poweroff; | ||
966 | } | ||
967 | |||
968 | if (adau1977->dvdd_reg) | ||
969 | power_off_mask = ~0; | ||
970 | else | ||
971 | power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN; | ||
972 | |||
973 | ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, | ||
974 | power_off_mask, 0x00); | ||
975 | if (ret) | ||
976 | goto err_poweroff; | ||
977 | |||
978 | ret = adau1977_power_disable(adau1977); | ||
979 | if (ret) | ||
980 | return ret; | ||
981 | |||
982 | return snd_soc_register_codec(dev, &adau1977_codec_driver, | ||
983 | &adau1977_dai, 1); | ||
984 | |||
985 | err_poweroff: | ||
986 | adau1977_power_disable(adau1977); | ||
987 | return ret; | ||
988 | |||
989 | } | ||
990 | EXPORT_SYMBOL_GPL(adau1977_probe); | ||
991 | |||
992 | static bool adau1977_register_volatile(struct device *dev, unsigned int reg) | ||
993 | { | ||
994 | switch (reg) { | ||
995 | case ADAU1977_REG_STATUS(0): | ||
996 | case ADAU1977_REG_STATUS(1): | ||
997 | case ADAU1977_REG_STATUS(2): | ||
998 | case ADAU1977_REG_STATUS(3): | ||
999 | case ADAU1977_REG_ADC_CLIP: | ||
1000 | return true; | ||
1001 | } | ||
1002 | |||
1003 | return false; | ||
1004 | } | ||
1005 | |||
1006 | const struct regmap_config adau1977_regmap_config = { | ||
1007 | .max_register = ADAU1977_REG_DC_HPF_CAL, | ||
1008 | .volatile_reg = adau1977_register_volatile, | ||
1009 | |||
1010 | .cache_type = REGCACHE_RBTREE, | ||
1011 | .reg_defaults = adau1977_reg_defaults, | ||
1012 | .num_reg_defaults = ARRAY_SIZE(adau1977_reg_defaults), | ||
1013 | }; | ||
1014 | EXPORT_SYMBOL_GPL(adau1977_regmap_config); | ||
1015 | |||
1016 | MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver"); | ||
1017 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
1018 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/adau1977.h b/sound/soc/codecs/adau1977.h new file mode 100644 index 000000000000..95e714345a86 --- /dev/null +++ b/sound/soc/codecs/adau1977.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * ADAU1977/ADAU1978/ADAU1979 driver | ||
3 | * | ||
4 | * Copyright 2014 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #ifndef __SOUND_SOC_CODECS_ADAU1977_H__ | ||
11 | #define __SOUND_SOC_CODECS_ADAU1977_H__ | ||
12 | |||
13 | #include <linux/regmap.h> | ||
14 | |||
15 | struct device; | ||
16 | |||
17 | enum adau1977_type { | ||
18 | ADAU1977, | ||
19 | ADAU1978, | ||
20 | ADAU1979, | ||
21 | }; | ||
22 | |||
23 | int adau1977_probe(struct device *dev, struct regmap *regmap, | ||
24 | enum adau1977_type type, void (*switch_mode)(struct device *dev)); | ||
25 | |||
26 | extern const struct regmap_config adau1977_regmap_config; | ||
27 | |||
28 | enum adau1977_clk_id { | ||
29 | ADAU1977_SYSCLK, | ||
30 | }; | ||
31 | |||
32 | enum adau1977_sysclk_src { | ||
33 | ADAU1977_SYSCLK_SRC_MCLK, | ||
34 | ADAU1977_SYSCLK_SRC_LRCLK, | ||
35 | }; | ||
36 | |||
37 | #endif | ||
diff --git a/sound/soc/codecs/adav801.c b/sound/soc/codecs/adav801.c new file mode 100644 index 000000000000..790fce33ab10 --- /dev/null +++ b/sound/soc/codecs/adav801.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * ADAV801 audio driver | ||
3 | * | ||
4 | * Copyright 2014 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/spi/spi.h> | ||
11 | #include <linux/regmap.h> | ||
12 | |||
13 | #include <sound/soc.h> | ||
14 | |||
15 | #include "adav80x.h" | ||
16 | |||
17 | static const struct spi_device_id adav80x_spi_id[] = { | ||
18 | { "adav801", 0 }, | ||
19 | { } | ||
20 | }; | ||
21 | MODULE_DEVICE_TABLE(spi, adav80x_spi_id); | ||
22 | |||
23 | static int adav80x_spi_probe(struct spi_device *spi) | ||
24 | { | ||
25 | struct regmap_config config; | ||
26 | |||
27 | config = adav80x_regmap_config; | ||
28 | config.read_flag_mask = 0x01; | ||
29 | |||
30 | return adav80x_bus_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); | ||
31 | } | ||
32 | |||
33 | static int adav80x_spi_remove(struct spi_device *spi) | ||
34 | { | ||
35 | snd_soc_unregister_codec(&spi->dev); | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | static struct spi_driver adav80x_spi_driver = { | ||
40 | .driver = { | ||
41 | .name = "adav801", | ||
42 | .owner = THIS_MODULE, | ||
43 | }, | ||
44 | .probe = adav80x_spi_probe, | ||
45 | .remove = adav80x_spi_remove, | ||
46 | .id_table = adav80x_spi_id, | ||
47 | }; | ||
48 | module_spi_driver(adav80x_spi_driver); | ||
49 | |||
50 | MODULE_DESCRIPTION("ASoC ADAV801 driver"); | ||
51 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
52 | MODULE_AUTHOR("Yi Li <yi.li@analog.com>>"); | ||
53 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/adav803.c b/sound/soc/codecs/adav803.c new file mode 100644 index 000000000000..66d9fce34e62 --- /dev/null +++ b/sound/soc/codecs/adav803.c | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * ADAV803 audio driver | ||
3 | * | ||
4 | * Copyright 2014 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/i2c.h> | ||
11 | #include <linux/regmap.h> | ||
12 | |||
13 | #include <sound/soc.h> | ||
14 | |||
15 | #include "adav80x.h" | ||
16 | |||
17 | static const struct i2c_device_id adav803_id[] = { | ||
18 | { "adav803", 0 }, | ||
19 | { } | ||
20 | }; | ||
21 | MODULE_DEVICE_TABLE(i2c, adav803_id); | ||
22 | |||
23 | static int adav803_probe(struct i2c_client *client, | ||
24 | const struct i2c_device_id *id) | ||
25 | { | ||
26 | return adav80x_bus_probe(&client->dev, | ||
27 | devm_regmap_init_i2c(client, &adav80x_regmap_config)); | ||
28 | } | ||
29 | |||
30 | static int adav803_remove(struct i2c_client *client) | ||
31 | { | ||
32 | snd_soc_unregister_codec(&client->dev); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static struct i2c_driver adav803_driver = { | ||
37 | .driver = { | ||
38 | .name = "adav803", | ||
39 | .owner = THIS_MODULE, | ||
40 | }, | ||
41 | .probe = adav803_probe, | ||
42 | .remove = adav803_remove, | ||
43 | .id_table = adav803_id, | ||
44 | }; | ||
45 | module_i2c_driver(adav803_driver); | ||
46 | |||
47 | MODULE_DESCRIPTION("ASoC ADAV803 driver"); | ||
48 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
49 | MODULE_AUTHOR("Yi Li <yi.li@analog.com>>"); | ||
50 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index f78b27a7c461..5062e34ee8dc 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c | |||
@@ -8,17 +8,15 @@ | |||
8 | * Licensed under the GPL-2 or later. | 8 | * Licensed under the GPL-2 or later. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | 11 | #include <linux/module.h> |
13 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
14 | #include <linux/i2c.h> | 13 | #include <linux/regmap.h> |
15 | #include <linux/spi/spi.h> | ||
16 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
17 | #include <sound/core.h> | 15 | |
18 | #include <sound/pcm.h> | 16 | #include <sound/pcm.h> |
19 | #include <sound/pcm_params.h> | 17 | #include <sound/pcm_params.h> |
20 | #include <sound/tlv.h> | ||
21 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
19 | #include <sound/tlv.h> | ||
22 | 20 | ||
23 | #include "adav80x.h" | 21 | #include "adav80x.h" |
24 | 22 | ||
@@ -541,6 +539,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, | |||
541 | unsigned int freq, int dir) | 539 | unsigned int freq, int dir) |
542 | { | 540 | { |
543 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 541 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
542 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
544 | 543 | ||
545 | if (dir == SND_SOC_CLOCK_IN) { | 544 | if (dir == SND_SOC_CLOCK_IN) { |
546 | switch (clk_id) { | 545 | switch (clk_id) { |
@@ -573,7 +572,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, | |||
573 | regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2, | 572 | regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2, |
574 | iclk_ctrl2); | 573 | iclk_ctrl2); |
575 | 574 | ||
576 | snd_soc_dapm_sync(&codec->dapm); | 575 | snd_soc_dapm_sync(dapm); |
577 | } | 576 | } |
578 | } else { | 577 | } else { |
579 | unsigned int mask; | 578 | unsigned int mask; |
@@ -600,17 +599,21 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, | |||
600 | adav80x->sysclk_pd[clk_id] = false; | 599 | adav80x->sysclk_pd[clk_id] = false; |
601 | } | 600 | } |
602 | 601 | ||
602 | snd_soc_dapm_mutex_lock(dapm); | ||
603 | |||
603 | if (adav80x->sysclk_pd[0]) | 604 | if (adav80x->sysclk_pd[0]) |
604 | snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); | 605 | snd_soc_dapm_disable_pin_unlocked(dapm, "PLL1"); |
605 | else | 606 | else |
606 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); | 607 | snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL1"); |
607 | 608 | ||
608 | if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) | 609 | if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) |
609 | snd_soc_dapm_disable_pin(&codec->dapm, "PLL2"); | 610 | snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2"); |
610 | else | 611 | else |
611 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); | 612 | snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2"); |
612 | 613 | ||
613 | snd_soc_dapm_sync(&codec->dapm); | 614 | snd_soc_dapm_sync_unlocked(dapm); |
615 | |||
616 | snd_soc_dapm_mutex_unlock(dapm); | ||
614 | } | 617 | } |
615 | 618 | ||
616 | return 0; | 619 | return 0; |
@@ -722,7 +725,7 @@ static int adav80x_dai_startup(struct snd_pcm_substream *substream, | |||
722 | struct snd_soc_codec *codec = dai->codec; | 725 | struct snd_soc_codec *codec = dai->codec; |
723 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 726 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
724 | 727 | ||
725 | if (!codec->active || !adav80x->rate) | 728 | if (!snd_soc_codec_is_active(codec) || !adav80x->rate) |
726 | return 0; | 729 | return 0; |
727 | 730 | ||
728 | return snd_pcm_hw_constraint_minmax(substream->runtime, | 731 | return snd_pcm_hw_constraint_minmax(substream->runtime, |
@@ -735,7 +738,7 @@ static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, | |||
735 | struct snd_soc_codec *codec = dai->codec; | 738 | struct snd_soc_codec *codec = dai->codec; |
736 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 739 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
737 | 740 | ||
738 | if (!codec->active) | 741 | if (!snd_soc_codec_is_active(codec)) |
739 | adav80x->rate = 0; | 742 | adav80x->rate = 0; |
740 | } | 743 | } |
741 | 744 | ||
@@ -798,15 +801,8 @@ static struct snd_soc_dai_driver adav80x_dais[] = { | |||
798 | 801 | ||
799 | static int adav80x_probe(struct snd_soc_codec *codec) | 802 | static int adav80x_probe(struct snd_soc_codec *codec) |
800 | { | 803 | { |
801 | int ret; | ||
802 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 804 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
803 | 805 | ||
804 | ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
805 | if (ret) { | ||
806 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); | ||
807 | return ret; | ||
808 | } | ||
809 | |||
810 | /* Force PLLs on for SYSCLK output */ | 806 | /* Force PLLs on for SYSCLK output */ |
811 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); | 807 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); |
812 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); | 808 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); |
@@ -864,39 +860,26 @@ static struct snd_soc_codec_driver adav80x_codec_driver = { | |||
864 | .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), | 860 | .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), |
865 | }; | 861 | }; |
866 | 862 | ||
867 | static int adav80x_bus_probe(struct device *dev, struct regmap *regmap) | 863 | int adav80x_bus_probe(struct device *dev, struct regmap *regmap) |
868 | { | 864 | { |
869 | struct adav80x *adav80x; | 865 | struct adav80x *adav80x; |
870 | int ret; | ||
871 | 866 | ||
872 | if (IS_ERR(regmap)) | 867 | if (IS_ERR(regmap)) |
873 | return PTR_ERR(regmap); | 868 | return PTR_ERR(regmap); |
874 | 869 | ||
875 | adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL); | 870 | adav80x = devm_kzalloc(dev, sizeof(*adav80x), GFP_KERNEL); |
876 | if (!adav80x) | 871 | if (!adav80x) |
877 | return -ENOMEM; | 872 | return -ENOMEM; |
878 | 873 | ||
879 | |||
880 | dev_set_drvdata(dev, adav80x); | 874 | dev_set_drvdata(dev, adav80x); |
881 | adav80x->regmap = regmap; | 875 | adav80x->regmap = regmap; |
882 | 876 | ||
883 | ret = snd_soc_register_codec(dev, &adav80x_codec_driver, | 877 | return snd_soc_register_codec(dev, &adav80x_codec_driver, |
884 | adav80x_dais, ARRAY_SIZE(adav80x_dais)); | 878 | adav80x_dais, ARRAY_SIZE(adav80x_dais)); |
885 | if (ret) | ||
886 | kfree(adav80x); | ||
887 | |||
888 | return ret; | ||
889 | } | ||
890 | |||
891 | static int adav80x_bus_remove(struct device *dev) | ||
892 | { | ||
893 | snd_soc_unregister_codec(dev); | ||
894 | kfree(dev_get_drvdata(dev)); | ||
895 | return 0; | ||
896 | } | 879 | } |
880 | EXPORT_SYMBOL_GPL(adav80x_bus_probe); | ||
897 | 881 | ||
898 | #if defined(CONFIG_SPI_MASTER) | 882 | const struct regmap_config adav80x_regmap_config = { |
899 | static const struct regmap_config adav80x_spi_regmap_config = { | ||
900 | .val_bits = 8, | 883 | .val_bits = 8, |
901 | .pad_bits = 1, | 884 | .pad_bits = 1, |
902 | .reg_bits = 7, | 885 | .reg_bits = 7, |
@@ -908,105 +891,7 @@ static const struct regmap_config adav80x_spi_regmap_config = { | |||
908 | .reg_defaults = adav80x_reg_defaults, | 891 | .reg_defaults = adav80x_reg_defaults, |
909 | .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), | 892 | .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), |
910 | }; | 893 | }; |
911 | 894 | EXPORT_SYMBOL_GPL(adav80x_regmap_config); | |
912 | static const struct spi_device_id adav80x_spi_id[] = { | ||
913 | { "adav801", 0 }, | ||
914 | { } | ||
915 | }; | ||
916 | MODULE_DEVICE_TABLE(spi, adav80x_spi_id); | ||
917 | |||
918 | static int adav80x_spi_probe(struct spi_device *spi) | ||
919 | { | ||
920 | return adav80x_bus_probe(&spi->dev, | ||
921 | devm_regmap_init_spi(spi, &adav80x_spi_regmap_config)); | ||
922 | } | ||
923 | |||
924 | static int adav80x_spi_remove(struct spi_device *spi) | ||
925 | { | ||
926 | return adav80x_bus_remove(&spi->dev); | ||
927 | } | ||
928 | |||
929 | static struct spi_driver adav80x_spi_driver = { | ||
930 | .driver = { | ||
931 | .name = "adav801", | ||
932 | .owner = THIS_MODULE, | ||
933 | }, | ||
934 | .probe = adav80x_spi_probe, | ||
935 | .remove = adav80x_spi_remove, | ||
936 | .id_table = adav80x_spi_id, | ||
937 | }; | ||
938 | #endif | ||
939 | |||
940 | #if IS_ENABLED(CONFIG_I2C) | ||
941 | static const struct regmap_config adav80x_i2c_regmap_config = { | ||
942 | .val_bits = 8, | ||
943 | .pad_bits = 1, | ||
944 | .reg_bits = 7, | ||
945 | |||
946 | .max_register = ADAV80X_PLL_OUTE, | ||
947 | |||
948 | .cache_type = REGCACHE_RBTREE, | ||
949 | .reg_defaults = adav80x_reg_defaults, | ||
950 | .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), | ||
951 | }; | ||
952 | |||
953 | static const struct i2c_device_id adav80x_i2c_id[] = { | ||
954 | { "adav803", 0 }, | ||
955 | { } | ||
956 | }; | ||
957 | MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id); | ||
958 | |||
959 | static int adav80x_i2c_probe(struct i2c_client *client, | ||
960 | const struct i2c_device_id *id) | ||
961 | { | ||
962 | return adav80x_bus_probe(&client->dev, | ||
963 | devm_regmap_init_i2c(client, &adav80x_i2c_regmap_config)); | ||
964 | } | ||
965 | |||
966 | static int adav80x_i2c_remove(struct i2c_client *client) | ||
967 | { | ||
968 | return adav80x_bus_remove(&client->dev); | ||
969 | } | ||
970 | |||
971 | static struct i2c_driver adav80x_i2c_driver = { | ||
972 | .driver = { | ||
973 | .name = "adav803", | ||
974 | .owner = THIS_MODULE, | ||
975 | }, | ||
976 | .probe = adav80x_i2c_probe, | ||
977 | .remove = adav80x_i2c_remove, | ||
978 | .id_table = adav80x_i2c_id, | ||
979 | }; | ||
980 | #endif | ||
981 | |||
982 | static int __init adav80x_init(void) | ||
983 | { | ||
984 | int ret = 0; | ||
985 | |||
986 | #if IS_ENABLED(CONFIG_I2C) | ||
987 | ret = i2c_add_driver(&adav80x_i2c_driver); | ||
988 | if (ret) | ||
989 | return ret; | ||
990 | #endif | ||
991 | |||
992 | #if defined(CONFIG_SPI_MASTER) | ||
993 | ret = spi_register_driver(&adav80x_spi_driver); | ||
994 | #endif | ||
995 | |||
996 | return ret; | ||
997 | } | ||
998 | module_init(adav80x_init); | ||
999 | |||
1000 | static void __exit adav80x_exit(void) | ||
1001 | { | ||
1002 | #if IS_ENABLED(CONFIG_I2C) | ||
1003 | i2c_del_driver(&adav80x_i2c_driver); | ||
1004 | #endif | ||
1005 | #if defined(CONFIG_SPI_MASTER) | ||
1006 | spi_unregister_driver(&adav80x_spi_driver); | ||
1007 | #endif | ||
1008 | } | ||
1009 | module_exit(adav80x_exit); | ||
1010 | 895 | ||
1011 | MODULE_DESCRIPTION("ASoC ADAV80x driver"); | 896 | MODULE_DESCRIPTION("ASoC ADAV80x driver"); |
1012 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 897 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
diff --git a/sound/soc/codecs/adav80x.h b/sound/soc/codecs/adav80x.h index adb0fc76d4e3..8a1d7c09dca5 100644 --- a/sound/soc/codecs/adav80x.h +++ b/sound/soc/codecs/adav80x.h | |||
@@ -9,6 +9,13 @@ | |||
9 | #ifndef _ADAV80X_H | 9 | #ifndef _ADAV80X_H |
10 | #define _ADAV80X_H | 10 | #define _ADAV80X_H |
11 | 11 | ||
12 | #include <linux/regmap.h> | ||
13 | |||
14 | struct device; | ||
15 | |||
16 | extern const struct regmap_config adav80x_regmap_config; | ||
17 | int adav80x_bus_probe(struct device *dev, struct regmap *regmap); | ||
18 | |||
12 | enum adav80x_pll_src { | 19 | enum adav80x_pll_src { |
13 | ADAV80X_PLL_SRC_XIN, | 20 | ADAV80X_PLL_SRC_XIN, |
14 | ADAV80X_PLL_SRC_XTAL, | 21 | ADAV80X_PLL_SRC_XTAL, |
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index b4819dcd4f4d..10adf25d4c14 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c | |||
@@ -174,8 +174,6 @@ static int ak4104_probe(struct snd_soc_codec *codec) | |||
174 | struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); | 174 | struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); |
175 | int ret; | 175 | int ret; |
176 | 176 | ||
177 | codec->control_data = ak4104->regmap; | ||
178 | |||
179 | /* set power-up and non-reset bits */ | 177 | /* set power-up and non-reset bits */ |
180 | ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1, | 178 | ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1, |
181 | AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, | 179 | AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, |
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 684fe910669f..30e297890fec 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -388,15 +388,6 @@ static int ak4535_resume(struct snd_soc_codec *codec) | |||
388 | 388 | ||
389 | static int ak4535_probe(struct snd_soc_codec *codec) | 389 | static int ak4535_probe(struct snd_soc_codec *codec) |
390 | { | 390 | { |
391 | struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); | ||
392 | int ret; | ||
393 | |||
394 | codec->control_data = ak4535->regmap; | ||
395 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
396 | if (ret < 0) { | ||
397 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
398 | return ret; | ||
399 | } | ||
400 | /* power on device */ | 391 | /* power on device */ |
401 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 392 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
402 | 393 | ||
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 94cbe508dd37..868c0e2da1ec 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c | |||
@@ -113,14 +113,14 @@ static const DECLARE_TLV_DB_SCALE(alc_tlv, -800, 50, 0); | |||
113 | static const DECLARE_TLV_DB_SCALE(aux_in_tlv, -2100, 300, 0); | 113 | static const DECLARE_TLV_DB_SCALE(aux_in_tlv, -2100, 300, 0); |
114 | 114 | ||
115 | 115 | ||
116 | static const struct soc_enum ak4641_mono_out_enum = | 116 | static SOC_ENUM_SINGLE_DECL(ak4641_mono_out_enum, |
117 | SOC_ENUM_SINGLE(AK4641_SIG1, 6, 2, ak4641_mono_out); | 117 | AK4641_SIG1, 6, ak4641_mono_out); |
118 | static const struct soc_enum ak4641_hp_out_enum = | 118 | static SOC_ENUM_SINGLE_DECL(ak4641_hp_out_enum, |
119 | SOC_ENUM_SINGLE(AK4641_MODE2, 2, 2, ak4641_hp_out); | 119 | AK4641_MODE2, 2, ak4641_hp_out); |
120 | static const struct soc_enum ak4641_mic_select_enum = | 120 | static SOC_ENUM_SINGLE_DECL(ak4641_mic_select_enum, |
121 | SOC_ENUM_SINGLE(AK4641_MIC, 1, 2, ak4641_mic_select); | 121 | AK4641_MIC, 1, ak4641_mic_select); |
122 | static const struct soc_enum ak4641_mic_or_dac_enum = | 122 | static SOC_ENUM_SINGLE_DECL(ak4641_mic_or_dac_enum, |
123 | SOC_ENUM_SINGLE(AK4641_BTIF, 4, 2, ak4641_mic_or_dac); | 123 | AK4641_BTIF, 4, ak4641_mic_or_dac); |
124 | 124 | ||
125 | static const struct snd_kcontrol_new ak4641_snd_controls[] = { | 125 | static const struct snd_kcontrol_new ak4641_snd_controls[] = { |
126 | SOC_ENUM("Mono 1 Output", ak4641_mono_out_enum), | 126 | SOC_ENUM("Mono 1 Output", ak4641_mono_out_enum), |
@@ -519,14 +519,6 @@ static int ak4641_resume(struct snd_soc_codec *codec) | |||
519 | 519 | ||
520 | static int ak4641_probe(struct snd_soc_codec *codec) | 520 | static int ak4641_probe(struct snd_soc_codec *codec) |
521 | { | 521 | { |
522 | int ret; | ||
523 | |||
524 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
525 | if (ret != 0) { | ||
526 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
527 | return ret; | ||
528 | } | ||
529 | |||
530 | /* power on device */ | 522 | /* power on device */ |
531 | ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 523 | ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
532 | 524 | ||
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 1f646c6e90c6..92655cc189ae 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -465,14 +465,6 @@ static int ak4642_resume(struct snd_soc_codec *codec) | |||
465 | 465 | ||
466 | static int ak4642_probe(struct snd_soc_codec *codec) | 466 | static int ak4642_probe(struct snd_soc_codec *codec) |
467 | { | 467 | { |
468 | int ret; | ||
469 | |||
470 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
471 | if (ret < 0) { | ||
472 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
473 | return ret; | ||
474 | } | ||
475 | |||
476 | ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 468 | ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
477 | 469 | ||
478 | return 0; | 470 | return 0; |
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 25bdf6ad4a54..998fa0c5a0b9 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/regmap.h> | ||
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
19 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
20 | #include <sound/initval.h> | 21 | #include <sound/initval.h> |
@@ -23,104 +24,99 @@ | |||
23 | #include "ak4671.h" | 24 | #include "ak4671.h" |
24 | 25 | ||
25 | 26 | ||
26 | /* codec private data */ | ||
27 | struct ak4671_priv { | ||
28 | enum snd_soc_control_type control_type; | ||
29 | }; | ||
30 | |||
31 | /* ak4671 register cache & default register settings */ | 27 | /* ak4671 register cache & default register settings */ |
32 | static const u8 ak4671_reg[AK4671_CACHEREGNUM] = { | 28 | static const struct reg_default ak4671_reg_defaults[] = { |
33 | 0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */ | 29 | { 0x00, 0x00 }, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */ |
34 | 0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */ | 30 | { 0x01, 0xf6 }, /* AK4671_PLL_MODE_SELECT0 (0x01) */ |
35 | 0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */ | 31 | { 0x02, 0x00 }, /* AK4671_PLL_MODE_SELECT1 (0x02) */ |
36 | 0x02, /* AK4671_FORMAT_SELECT (0x03) */ | 32 | { 0x03, 0x02 }, /* AK4671_FORMAT_SELECT (0x03) */ |
37 | 0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */ | 33 | { 0x04, 0x00 }, /* AK4671_MIC_SIGNAL_SELECT (0x04) */ |
38 | 0x55, /* AK4671_MIC_AMP_GAIN (0x05) */ | 34 | { 0x05, 0x55 }, /* AK4671_MIC_AMP_GAIN (0x05) */ |
39 | 0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */ | 35 | { 0x06, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */ |
40 | 0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */ | 36 | { 0x07, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */ |
41 | 0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */ | 37 | { 0x08, 0xb5 }, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */ |
42 | 0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */ | 38 | { 0x09, 0x00 }, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */ |
43 | 0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */ | 39 | { 0x0a, 0x00 }, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */ |
44 | 0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */ | 40 | { 0x0b, 0x00 }, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */ |
45 | 0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */ | 41 | { 0x0c, 0x00 }, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */ |
46 | 0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */ | 42 | { 0x0d, 0x00 }, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */ |
47 | 0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */ | 43 | { 0x0e, 0x00 }, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */ |
48 | 0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */ | 44 | { 0x0f, 0x00 }, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */ |
49 | 0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */ | 45 | { 0x10, 0x00 }, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */ |
50 | 0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */ | 46 | { 0x11, 0x80 }, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */ |
51 | 0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */ | 47 | { 0x12, 0x91 }, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */ |
52 | 0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */ | 48 | { 0x13, 0x91 }, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */ |
53 | 0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */ | 49 | { 0x14, 0xe1 }, /* AK4671_ALC_REFERENCE_SELECT (0x14) */ |
54 | 0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */ | 50 | { 0x15, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */ |
55 | 0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */ | 51 | { 0x16, 0x00 }, /* AK4671_ALC_TIMER_SELECT (0x16) */ |
56 | 0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */ | 52 | { 0x17, 0x00 }, /* AK4671_ALC_MODE_CONTROL (0x17) */ |
57 | 0x02, /* AK4671_MODE_CONTROL1 (0x18) */ | 53 | { 0x18, 0x02 }, /* AK4671_MODE_CONTROL1 (0x18) */ |
58 | 0x01, /* AK4671_MODE_CONTROL2 (0x19) */ | 54 | { 0x19, 0x01 }, /* AK4671_MODE_CONTROL2 (0x19) */ |
59 | 0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */ | 55 | { 0x1a, 0x18 }, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */ |
60 | 0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */ | 56 | { 0x1b, 0x18 }, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */ |
61 | 0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */ | 57 | { 0x1c, 0x00 }, /* AK4671_SIDETONE_A_CONTROL (0x1c) */ |
62 | 0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */ | 58 | { 0x1d, 0x02 }, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */ |
63 | 0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */ | 59 | { 0x1e, 0x00 }, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */ |
64 | 0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */ | 60 | { 0x1f, 0x00 }, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */ |
65 | 0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */ | 61 | { 0x20, 0x00 }, /* AK4671_FIL3_COEFFICIENT2 (0x20) */ |
66 | 0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */ | 62 | { 0x21, 0x00 }, /* AK4671_FIL3_COEFFICIENT3 (0x21) */ |
67 | 0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */ | 63 | { 0x22, 0x00 }, /* AK4671_EQ_COEFFICIENT0 (0x22) */ |
68 | 0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */ | 64 | { 0x23, 0x00 }, /* AK4671_EQ_COEFFICIENT1 (0x23) */ |
69 | 0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */ | 65 | { 0x24, 0x00 }, /* AK4671_EQ_COEFFICIENT2 (0x24) */ |
70 | 0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */ | 66 | { 0x25, 0x00 }, /* AK4671_EQ_COEFFICIENT3 (0x25) */ |
71 | 0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */ | 67 | { 0x26, 0x00 }, /* AK4671_EQ_COEFFICIENT4 (0x26) */ |
72 | 0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */ | 68 | { 0x27, 0x00 }, /* AK4671_EQ_COEFFICIENT5 (0x27) */ |
73 | 0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */ | 69 | { 0x28, 0xa9 }, /* AK4671_FIL1_COEFFICIENT0 (0x28) */ |
74 | 0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */ | 70 | { 0x29, 0x1f }, /* AK4671_FIL1_COEFFICIENT1 (0x29) */ |
75 | 0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */ | 71 | { 0x2a, 0xad }, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */ |
76 | 0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */ | 72 | { 0x2b, 0x20 }, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */ |
77 | 0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */ | 73 | { 0x2c, 0x00 }, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */ |
78 | 0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */ | 74 | { 0x2d, 0x00 }, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */ |
79 | 0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */ | 75 | { 0x2e, 0x00 }, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */ |
80 | 0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */ | 76 | { 0x2f, 0x00 }, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */ |
81 | 0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */ | 77 | { 0x30, 0x00 }, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */ |
82 | 0x00, /* this register not used */ | 78 | |
83 | 0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */ | 79 | { 0x32, 0x00 }, /* AK4671_E1_COEFFICIENT0 (0x32) */ |
84 | 0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */ | 80 | { 0x33, 0x00 }, /* AK4671_E1_COEFFICIENT1 (0x33) */ |
85 | 0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */ | 81 | { 0x34, 0x00 }, /* AK4671_E1_COEFFICIENT2 (0x34) */ |
86 | 0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */ | 82 | { 0x35, 0x00 }, /* AK4671_E1_COEFFICIENT3 (0x35) */ |
87 | 0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */ | 83 | { 0x36, 0x00 }, /* AK4671_E1_COEFFICIENT4 (0x36) */ |
88 | 0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */ | 84 | { 0x37, 0x00 }, /* AK4671_E1_COEFFICIENT5 (0x37) */ |
89 | 0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */ | 85 | { 0x38, 0x00 }, /* AK4671_E2_COEFFICIENT0 (0x38) */ |
90 | 0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */ | 86 | { 0x39, 0x00 }, /* AK4671_E2_COEFFICIENT1 (0x39) */ |
91 | 0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */ | 87 | { 0x3a, 0x00 }, /* AK4671_E2_COEFFICIENT2 (0x3a) */ |
92 | 0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */ | 88 | { 0x3b, 0x00 }, /* AK4671_E2_COEFFICIENT3 (0x3b) */ |
93 | 0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */ | 89 | { 0x3c, 0x00 }, /* AK4671_E2_COEFFICIENT4 (0x3c) */ |
94 | 0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */ | 90 | { 0x3d, 0x00 }, /* AK4671_E2_COEFFICIENT5 (0x3d) */ |
95 | 0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */ | 91 | { 0x3e, 0x00 }, /* AK4671_E3_COEFFICIENT0 (0x3e) */ |
96 | 0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */ | 92 | { 0x3f, 0x00 }, /* AK4671_E3_COEFFICIENT1 (0x3f) */ |
97 | 0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */ | 93 | { 0x40, 0x00 }, /* AK4671_E3_COEFFICIENT2 (0x40) */ |
98 | 0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */ | 94 | { 0x41, 0x00 }, /* AK4671_E3_COEFFICIENT3 (0x41) */ |
99 | 0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */ | 95 | { 0x42, 0x00 }, /* AK4671_E3_COEFFICIENT4 (0x42) */ |
100 | 0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */ | 96 | { 0x43, 0x00 }, /* AK4671_E3_COEFFICIENT5 (0x43) */ |
101 | 0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */ | 97 | { 0x44, 0x00 }, /* AK4671_E4_COEFFICIENT0 (0x44) */ |
102 | 0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */ | 98 | { 0x45, 0x00 }, /* AK4671_E4_COEFFICIENT1 (0x45) */ |
103 | 0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */ | 99 | { 0x46, 0x00 }, /* AK4671_E4_COEFFICIENT2 (0x46) */ |
104 | 0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */ | 100 | { 0x47, 0x00 }, /* AK4671_E4_COEFFICIENT3 (0x47) */ |
105 | 0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */ | 101 | { 0x48, 0x00 }, /* AK4671_E4_COEFFICIENT4 (0x48) */ |
106 | 0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */ | 102 | { 0x49, 0x00 }, /* AK4671_E4_COEFFICIENT5 (0x49) */ |
107 | 0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */ | 103 | { 0x4a, 0x00 }, /* AK4671_E5_COEFFICIENT0 (0x4a) */ |
108 | 0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */ | 104 | { 0x4b, 0x00 }, /* AK4671_E5_COEFFICIENT1 (0x4b) */ |
109 | 0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */ | 105 | { 0x4c, 0x00 }, /* AK4671_E5_COEFFICIENT2 (0x4c) */ |
110 | 0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */ | 106 | { 0x4d, 0x00 }, /* AK4671_E5_COEFFICIENT3 (0x4d) */ |
111 | 0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */ | 107 | { 0x4e, 0x00 }, /* AK4671_E5_COEFFICIENT4 (0x4e) */ |
112 | 0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */ | 108 | { 0x4f, 0x00 }, /* AK4671_E5_COEFFICIENT5 (0x4f) */ |
113 | 0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */ | 109 | { 0x50, 0x88 }, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */ |
114 | 0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */ | 110 | { 0x51, 0x88 }, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */ |
115 | 0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */ | 111 | { 0x52, 0x08 }, /* AK4671_EQ_CONTRO_10KHZ (0x52) */ |
116 | 0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */ | 112 | { 0x53, 0x00 }, /* AK4671_PCM_IF_CONTROL0 (0x53) */ |
117 | 0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */ | 113 | { 0x54, 0x00 }, /* AK4671_PCM_IF_CONTROL1 (0x54) */ |
118 | 0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */ | 114 | { 0x55, 0x00 }, /* AK4671_PCM_IF_CONTROL2 (0x55) */ |
119 | 0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */ | 115 | { 0x56, 0x18 }, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */ |
120 | 0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */ | 116 | { 0x57, 0x18 }, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */ |
121 | 0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */ | 117 | { 0x58, 0x00 }, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */ |
122 | 0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */ | 118 | { 0x59, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */ |
123 | 0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */ | 119 | { 0x5a, 0x00 }, /* AK4671_SAR_ADC_CONTROL (0x5a) */ |
124 | }; | 120 | }; |
125 | 121 | ||
126 | /* | 122 | /* |
@@ -241,19 +237,17 @@ static const struct snd_kcontrol_new ak4671_rout3_mixer_controls[] = { | |||
241 | /* Input MUXs */ | 237 | /* Input MUXs */ |
242 | static const char *ak4671_lin_mux_texts[] = | 238 | static const char *ak4671_lin_mux_texts[] = |
243 | {"LIN1", "LIN2", "LIN3", "LIN4"}; | 239 | {"LIN1", "LIN2", "LIN3", "LIN4"}; |
244 | static const struct soc_enum ak4671_lin_mux_enum = | 240 | static SOC_ENUM_SINGLE_DECL(ak4671_lin_mux_enum, |
245 | SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0, | 241 | AK4671_MIC_SIGNAL_SELECT, 0, |
246 | ARRAY_SIZE(ak4671_lin_mux_texts), | 242 | ak4671_lin_mux_texts); |
247 | ak4671_lin_mux_texts); | ||
248 | static const struct snd_kcontrol_new ak4671_lin_mux_control = | 243 | static const struct snd_kcontrol_new ak4671_lin_mux_control = |
249 | SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum); | 244 | SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum); |
250 | 245 | ||
251 | static const char *ak4671_rin_mux_texts[] = | 246 | static const char *ak4671_rin_mux_texts[] = |
252 | {"RIN1", "RIN2", "RIN3", "RIN4"}; | 247 | {"RIN1", "RIN2", "RIN3", "RIN4"}; |
253 | static const struct soc_enum ak4671_rin_mux_enum = | 248 | static SOC_ENUM_SINGLE_DECL(ak4671_rin_mux_enum, |
254 | SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2, | 249 | AK4671_MIC_SIGNAL_SELECT, 2, |
255 | ARRAY_SIZE(ak4671_rin_mux_texts), | 250 | ak4671_rin_mux_texts); |
256 | ak4671_rin_mux_texts); | ||
257 | static const struct snd_kcontrol_new ak4671_rin_mux_control = | 251 | static const struct snd_kcontrol_new ak4671_rin_mux_control = |
258 | SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum); | 252 | SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum); |
259 | 253 | ||
@@ -619,21 +613,7 @@ static struct snd_soc_dai_driver ak4671_dai = { | |||
619 | 613 | ||
620 | static int ak4671_probe(struct snd_soc_codec *codec) | 614 | static int ak4671_probe(struct snd_soc_codec *codec) |
621 | { | 615 | { |
622 | struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec); | 616 | return ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
623 | int ret; | ||
624 | |||
625 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type); | ||
626 | if (ret < 0) { | ||
627 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
628 | return ret; | ||
629 | } | ||
630 | |||
631 | snd_soc_add_codec_controls(codec, ak4671_snd_controls, | ||
632 | ARRAY_SIZE(ak4671_snd_controls)); | ||
633 | |||
634 | ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
635 | |||
636 | return ret; | ||
637 | } | 617 | } |
638 | 618 | ||
639 | static int ak4671_remove(struct snd_soc_codec *codec) | 619 | static int ak4671_remove(struct snd_soc_codec *codec) |
@@ -646,28 +626,36 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { | |||
646 | .probe = ak4671_probe, | 626 | .probe = ak4671_probe, |
647 | .remove = ak4671_remove, | 627 | .remove = ak4671_remove, |
648 | .set_bias_level = ak4671_set_bias_level, | 628 | .set_bias_level = ak4671_set_bias_level, |
649 | .reg_cache_size = AK4671_CACHEREGNUM, | 629 | .controls = ak4671_snd_controls, |
650 | .reg_word_size = sizeof(u8), | 630 | .num_controls = ARRAY_SIZE(ak4671_snd_controls), |
651 | .reg_cache_default = ak4671_reg, | ||
652 | .dapm_widgets = ak4671_dapm_widgets, | 631 | .dapm_widgets = ak4671_dapm_widgets, |
653 | .num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets), | 632 | .num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets), |
654 | .dapm_routes = ak4671_intercon, | 633 | .dapm_routes = ak4671_intercon, |
655 | .num_dapm_routes = ARRAY_SIZE(ak4671_intercon), | 634 | .num_dapm_routes = ARRAY_SIZE(ak4671_intercon), |
656 | }; | 635 | }; |
657 | 636 | ||
637 | static const struct regmap_config ak4671_regmap = { | ||
638 | .reg_bits = 8, | ||
639 | .val_bits = 8, | ||
640 | |||
641 | .max_register = AK4671_SAR_ADC_CONTROL, | ||
642 | .reg_defaults = ak4671_reg_defaults, | ||
643 | .num_reg_defaults = ARRAY_SIZE(ak4671_reg_defaults), | ||
644 | .cache_type = REGCACHE_RBTREE, | ||
645 | }; | ||
646 | |||
658 | static int ak4671_i2c_probe(struct i2c_client *client, | 647 | static int ak4671_i2c_probe(struct i2c_client *client, |
659 | const struct i2c_device_id *id) | 648 | const struct i2c_device_id *id) |
660 | { | 649 | { |
661 | struct ak4671_priv *ak4671; | 650 | struct regmap *regmap; |
662 | int ret; | 651 | int ret; |
663 | 652 | ||
664 | ak4671 = devm_kzalloc(&client->dev, sizeof(struct ak4671_priv), | 653 | regmap = devm_regmap_init_i2c(client, &ak4671_regmap); |
665 | GFP_KERNEL); | 654 | if (IS_ERR(regmap)) { |
666 | if (ak4671 == NULL) | 655 | ret = PTR_ERR(regmap); |
667 | return -ENOMEM; | 656 | dev_err(&client->dev, "Failed to create regmap: %d\n", ret); |
668 | 657 | return ret; | |
669 | i2c_set_clientdata(client, ak4671); | 658 | } |
670 | ak4671->control_type = SND_SOC_I2C; | ||
671 | 659 | ||
672 | ret = snd_soc_register_codec(&client->dev, | 660 | ret = snd_soc_register_codec(&client->dev, |
673 | &soc_codec_dev_ak4671, &ak4671_dai, 1); | 661 | &soc_codec_dev_ak4671, &ak4671_dai, 1); |
diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h index 61cb7ab7552c..394a34d3f50a 100644 --- a/sound/soc/codecs/ak4671.h +++ b/sound/soc/codecs/ak4671.h | |||
@@ -105,8 +105,6 @@ | |||
105 | #define AK4671_DIGITAL_MIXING_CONTROL2 0x59 | 105 | #define AK4671_DIGITAL_MIXING_CONTROL2 0x59 |
106 | #define AK4671_SAR_ADC_CONTROL 0x5a | 106 | #define AK4671_SAR_ADC_CONTROL 0x5a |
107 | 107 | ||
108 | #define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1) | ||
109 | |||
110 | /* Bitfield Definitions */ | 108 | /* Bitfield Definitions */ |
111 | 109 | ||
112 | /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */ | 110 | /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */ |
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index d3036283482a..09f7e773bafb 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/pm.h> | 22 | #include <linux/pm.h> |
23 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
24 | #include <linux/regmap.h> | ||
24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
25 | #include <sound/core.h> | 26 | #include <sound/core.h> |
26 | #include <sound/pcm.h> | 27 | #include <sound/pcm.h> |
@@ -38,26 +39,13 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)"); | |||
38 | 39 | ||
39 | /* codec private data */ | 40 | /* codec private data */ |
40 | struct alc5623_priv { | 41 | struct alc5623_priv { |
41 | enum snd_soc_control_type control_type; | 42 | struct regmap *regmap; |
42 | u8 id; | 43 | u8 id; |
43 | unsigned int sysclk; | 44 | unsigned int sysclk; |
44 | u16 reg_cache[ALC5623_VENDOR_ID2+2]; | ||
45 | unsigned int add_ctrl; | 45 | unsigned int add_ctrl; |
46 | unsigned int jack_det_ctrl; | 46 | unsigned int jack_det_ctrl; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | static void alc5623_fill_cache(struct snd_soc_codec *codec) | ||
50 | { | ||
51 | int i, step = codec->driver->reg_cache_step; | ||
52 | u16 *cache = codec->reg_cache; | ||
53 | |||
54 | /* not really efficient ... */ | ||
55 | codec->cache_bypass = 1; | ||
56 | for (i = 0 ; i < codec->driver->reg_cache_size ; i += step) | ||
57 | cache[i] = snd_soc_read(codec, i); | ||
58 | codec->cache_bypass = 0; | ||
59 | } | ||
60 | |||
61 | static inline int alc5623_reset(struct snd_soc_codec *codec) | 49 | static inline int alc5623_reset(struct snd_soc_codec *codec) |
62 | { | 50 | { |
63 | return snd_soc_write(codec, ALC5623_RESET, 0); | 51 | return snd_soc_write(codec, ALC5623_RESET, 0); |
@@ -228,32 +216,37 @@ static const char *alc5623_aux_out_input_sel[] = { | |||
228 | "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"}; | 216 | "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"}; |
229 | 217 | ||
230 | /* auxout output mux */ | 218 | /* auxout output mux */ |
231 | static const struct soc_enum alc5623_aux_out_input_enum = | 219 | static SOC_ENUM_SINGLE_DECL(alc5623_aux_out_input_enum, |
232 | SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 6, 4, alc5623_aux_out_input_sel); | 220 | ALC5623_OUTPUT_MIXER_CTRL, 6, |
221 | alc5623_aux_out_input_sel); | ||
233 | static const struct snd_kcontrol_new alc5623_auxout_mux_controls = | 222 | static const struct snd_kcontrol_new alc5623_auxout_mux_controls = |
234 | SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum); | 223 | SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum); |
235 | 224 | ||
236 | /* speaker output mux */ | 225 | /* speaker output mux */ |
237 | static const struct soc_enum alc5623_spkout_input_enum = | 226 | static SOC_ENUM_SINGLE_DECL(alc5623_spkout_input_enum, |
238 | SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 10, 4, alc5623_spkout_input_sel); | 227 | ALC5623_OUTPUT_MIXER_CTRL, 10, |
228 | alc5623_spkout_input_sel); | ||
239 | static const struct snd_kcontrol_new alc5623_spkout_mux_controls = | 229 | static const struct snd_kcontrol_new alc5623_spkout_mux_controls = |
240 | SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum); | 230 | SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum); |
241 | 231 | ||
242 | /* headphone left output mux */ | 232 | /* headphone left output mux */ |
243 | static const struct soc_enum alc5623_hpl_out_input_enum = | 233 | static SOC_ENUM_SINGLE_DECL(alc5623_hpl_out_input_enum, |
244 | SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 9, 2, alc5623_hpl_out_input_sel); | 234 | ALC5623_OUTPUT_MIXER_CTRL, 9, |
235 | alc5623_hpl_out_input_sel); | ||
245 | static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls = | 236 | static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls = |
246 | SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum); | 237 | SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum); |
247 | 238 | ||
248 | /* headphone right output mux */ | 239 | /* headphone right output mux */ |
249 | static const struct soc_enum alc5623_hpr_out_input_enum = | 240 | static SOC_ENUM_SINGLE_DECL(alc5623_hpr_out_input_enum, |
250 | SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 8, 2, alc5623_hpr_out_input_sel); | 241 | ALC5623_OUTPUT_MIXER_CTRL, 8, |
242 | alc5623_hpr_out_input_sel); | ||
251 | static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls = | 243 | static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls = |
252 | SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum); | 244 | SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum); |
253 | 245 | ||
254 | /* speaker output N select */ | 246 | /* speaker output N select */ |
255 | static const struct soc_enum alc5623_spk_n_sour_enum = | 247 | static SOC_ENUM_SINGLE_DECL(alc5623_spk_n_sour_enum, |
256 | SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 14, 4, alc5623_spk_n_sour_sel); | 248 | ALC5623_OUTPUT_MIXER_CTRL, 14, |
249 | alc5623_spk_n_sour_sel); | ||
257 | static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls = | 250 | static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls = |
258 | SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum); | 251 | SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum); |
259 | 252 | ||
@@ -338,8 +331,9 @@ SND_SOC_DAPM_VMID("Vmid"), | |||
338 | }; | 331 | }; |
339 | 332 | ||
340 | static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"}; | 333 | static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"}; |
341 | static const struct soc_enum alc5623_amp_enum = | 334 | static SOC_ENUM_SINGLE_DECL(alc5623_amp_enum, |
342 | SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 13, 2, alc5623_amp_names); | 335 | ALC5623_OUTPUT_MIXER_CTRL, 13, |
336 | alc5623_amp_names); | ||
343 | static const struct snd_kcontrol_new alc5623_amp_mux_controls = | 337 | static const struct snd_kcontrol_new alc5623_amp_mux_controls = |
344 | SOC_DAPM_ENUM("Route", alc5623_amp_enum); | 338 | SOC_DAPM_ENUM("Route", alc5623_amp_enum); |
345 | 339 | ||
@@ -869,18 +863,28 @@ static struct snd_soc_dai_driver alc5623_dai = { | |||
869 | 863 | ||
870 | static int alc5623_suspend(struct snd_soc_codec *codec) | 864 | static int alc5623_suspend(struct snd_soc_codec *codec) |
871 | { | 865 | { |
866 | struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); | ||
867 | |||
872 | alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); | 868 | alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); |
869 | regcache_cache_only(alc5623->regmap, true); | ||
870 | |||
873 | return 0; | 871 | return 0; |
874 | } | 872 | } |
875 | 873 | ||
876 | static int alc5623_resume(struct snd_soc_codec *codec) | 874 | static int alc5623_resume(struct snd_soc_codec *codec) |
877 | { | 875 | { |
878 | int i, step = codec->driver->reg_cache_step; | 876 | struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); |
879 | u16 *cache = codec->reg_cache; | 877 | int ret; |
880 | 878 | ||
881 | /* Sync reg_cache with the hardware */ | 879 | /* Sync reg_cache with the hardware */ |
882 | for (i = 2 ; i < codec->driver->reg_cache_size ; i += step) | 880 | regcache_cache_only(alc5623->regmap, false); |
883 | snd_soc_write(codec, i, cache[i]); | 881 | ret = regcache_sync(alc5623->regmap); |
882 | if (ret != 0) { | ||
883 | dev_err(codec->dev, "Failed to sync register cache: %d\n", | ||
884 | ret); | ||
885 | regcache_cache_only(alc5623->regmap, true); | ||
886 | return ret; | ||
887 | } | ||
884 | 888 | ||
885 | alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 889 | alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
886 | 890 | ||
@@ -900,14 +904,7 @@ static int alc5623_probe(struct snd_soc_codec *codec) | |||
900 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 904 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
901 | int ret; | 905 | int ret; |
902 | 906 | ||
903 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type); | ||
904 | if (ret < 0) { | ||
905 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
906 | return ret; | ||
907 | } | ||
908 | |||
909 | alc5623_reset(codec); | 907 | alc5623_reset(codec); |
910 | alc5623_fill_cache(codec); | ||
911 | 908 | ||
912 | /* power on device */ | 909 | /* power on device */ |
913 | alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 910 | alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -980,9 +977,15 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = { | |||
980 | .suspend = alc5623_suspend, | 977 | .suspend = alc5623_suspend, |
981 | .resume = alc5623_resume, | 978 | .resume = alc5623_resume, |
982 | .set_bias_level = alc5623_set_bias_level, | 979 | .set_bias_level = alc5623_set_bias_level, |
983 | .reg_cache_size = ALC5623_VENDOR_ID2+2, | 980 | }; |
984 | .reg_word_size = sizeof(u16), | 981 | |
985 | .reg_cache_step = 2, | 982 | static const struct regmap_config alc5623_regmap = { |
983 | .reg_bits = 8, | ||
984 | .val_bits = 16, | ||
985 | .reg_stride = 2, | ||
986 | |||
987 | .max_register = ALC5623_VENDOR_ID2, | ||
988 | .cache_type = REGCACHE_RBTREE, | ||
986 | }; | 989 | }; |
987 | 990 | ||
988 | /* | 991 | /* |
@@ -996,19 +999,32 @@ static int alc5623_i2c_probe(struct i2c_client *client, | |||
996 | { | 999 | { |
997 | struct alc5623_platform_data *pdata; | 1000 | struct alc5623_platform_data *pdata; |
998 | struct alc5623_priv *alc5623; | 1001 | struct alc5623_priv *alc5623; |
999 | int ret, vid1, vid2; | 1002 | unsigned int vid1, vid2; |
1003 | int ret; | ||
1000 | 1004 | ||
1001 | vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1); | 1005 | alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv), |
1002 | if (vid1 < 0) { | 1006 | GFP_KERNEL); |
1003 | dev_err(&client->dev, "failed to read I2C\n"); | 1007 | if (alc5623 == NULL) |
1004 | return -EIO; | 1008 | return -ENOMEM; |
1009 | |||
1010 | alc5623->regmap = devm_regmap_init_i2c(client, &alc5623_regmap); | ||
1011 | if (IS_ERR(alc5623->regmap)) { | ||
1012 | ret = PTR_ERR(alc5623->regmap); | ||
1013 | dev_err(&client->dev, "Failed to initialise I/O: %d\n", ret); | ||
1014 | return ret; | ||
1015 | } | ||
1016 | |||
1017 | ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID1, &vid1); | ||
1018 | if (ret < 0) { | ||
1019 | dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret); | ||
1020 | return ret; | ||
1005 | } | 1021 | } |
1006 | vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8); | 1022 | vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8); |
1007 | 1023 | ||
1008 | vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2); | 1024 | ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2); |
1009 | if (vid2 < 0) { | 1025 | if (ret < 0) { |
1010 | dev_err(&client->dev, "failed to read I2C\n"); | 1026 | dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret); |
1011 | return -EIO; | 1027 | return ret; |
1012 | } | 1028 | } |
1013 | 1029 | ||
1014 | if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) { | 1030 | if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) { |
@@ -1021,11 +1037,6 @@ static int alc5623_i2c_probe(struct i2c_client *client, | |||
1021 | 1037 | ||
1022 | dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2); | 1038 | dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2); |
1023 | 1039 | ||
1024 | alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv), | ||
1025 | GFP_KERNEL); | ||
1026 | if (alc5623 == NULL) | ||
1027 | return -ENOMEM; | ||
1028 | |||
1029 | pdata = client->dev.platform_data; | 1040 | pdata = client->dev.platform_data; |
1030 | if (pdata) { | 1041 | if (pdata) { |
1031 | alc5623->add_ctrl = pdata->add_ctrl; | 1042 | alc5623->add_ctrl = pdata->add_ctrl; |
@@ -1048,7 +1059,6 @@ static int alc5623_i2c_probe(struct i2c_client *client, | |||
1048 | } | 1059 | } |
1049 | 1060 | ||
1050 | i2c_set_clientdata(client, alc5623); | 1061 | i2c_set_clientdata(client, alc5623); |
1051 | alc5623->control_type = SND_SOC_I2C; | ||
1052 | 1062 | ||
1053 | ret = snd_soc_register_codec(&client->dev, | 1063 | ret = snd_soc_register_codec(&client->dev, |
1054 | &soc_codec_device_alc5623, &alc5623_dai, 1); | 1064 | &soc_codec_device_alc5623, &alc5623_dai, 1); |
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index fb001c56cf8d..ec071a6306ef 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c | |||
@@ -293,51 +293,59 @@ static const char * const alc5632_i2s_out_sel[] = { | |||
293 | "ADC LR", "Voice Stereo Digital"}; | 293 | "ADC LR", "Voice Stereo Digital"}; |
294 | 294 | ||
295 | /* auxout output mux */ | 295 | /* auxout output mux */ |
296 | static const struct soc_enum alc5632_aux_out_input_enum = | 296 | static SOC_ENUM_SINGLE_DECL(alc5632_aux_out_input_enum, |
297 | SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 6, 4, alc5632_aux_out_input_sel); | 297 | ALC5632_OUTPUT_MIXER_CTRL, 6, |
298 | alc5632_aux_out_input_sel); | ||
298 | static const struct snd_kcontrol_new alc5632_auxout_mux_controls = | 299 | static const struct snd_kcontrol_new alc5632_auxout_mux_controls = |
299 | SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum); | 300 | SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum); |
300 | 301 | ||
301 | /* speaker output mux */ | 302 | /* speaker output mux */ |
302 | static const struct soc_enum alc5632_spkout_input_enum = | 303 | static SOC_ENUM_SINGLE_DECL(alc5632_spkout_input_enum, |
303 | SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 10, 4, alc5632_spkout_input_sel); | 304 | ALC5632_OUTPUT_MIXER_CTRL, 10, |
305 | alc5632_spkout_input_sel); | ||
304 | static const struct snd_kcontrol_new alc5632_spkout_mux_controls = | 306 | static const struct snd_kcontrol_new alc5632_spkout_mux_controls = |
305 | SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum); | 307 | SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum); |
306 | 308 | ||
307 | /* headphone left output mux */ | 309 | /* headphone left output mux */ |
308 | static const struct soc_enum alc5632_hpl_out_input_enum = | 310 | static SOC_ENUM_SINGLE_DECL(alc5632_hpl_out_input_enum, |
309 | SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 9, 2, alc5632_hpl_out_input_sel); | 311 | ALC5632_OUTPUT_MIXER_CTRL, 9, |
312 | alc5632_hpl_out_input_sel); | ||
310 | static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls = | 313 | static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls = |
311 | SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum); | 314 | SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum); |
312 | 315 | ||
313 | /* headphone right output mux */ | 316 | /* headphone right output mux */ |
314 | static const struct soc_enum alc5632_hpr_out_input_enum = | 317 | static SOC_ENUM_SINGLE_DECL(alc5632_hpr_out_input_enum, |
315 | SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 8, 2, alc5632_hpr_out_input_sel); | 318 | ALC5632_OUTPUT_MIXER_CTRL, 8, |
319 | alc5632_hpr_out_input_sel); | ||
316 | static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls = | 320 | static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls = |
317 | SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum); | 321 | SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum); |
318 | 322 | ||
319 | /* speaker output N select */ | 323 | /* speaker output N select */ |
320 | static const struct soc_enum alc5632_spk_n_sour_enum = | 324 | static SOC_ENUM_SINGLE_DECL(alc5632_spk_n_sour_enum, |
321 | SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 14, 4, alc5632_spk_n_sour_sel); | 325 | ALC5632_OUTPUT_MIXER_CTRL, 14, |
326 | alc5632_spk_n_sour_sel); | ||
322 | static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls = | 327 | static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls = |
323 | SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum); | 328 | SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum); |
324 | 329 | ||
325 | /* speaker amplifier */ | 330 | /* speaker amplifier */ |
326 | static const char *alc5632_amp_names[] = {"AB Amp", "D Amp"}; | 331 | static const char *alc5632_amp_names[] = {"AB Amp", "D Amp"}; |
327 | static const struct soc_enum alc5632_amp_enum = | 332 | static SOC_ENUM_SINGLE_DECL(alc5632_amp_enum, |
328 | SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 13, 2, alc5632_amp_names); | 333 | ALC5632_OUTPUT_MIXER_CTRL, 13, |
334 | alc5632_amp_names); | ||
329 | static const struct snd_kcontrol_new alc5632_amp_mux_controls = | 335 | static const struct snd_kcontrol_new alc5632_amp_mux_controls = |
330 | SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum); | 336 | SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum); |
331 | 337 | ||
332 | /* ADC output select */ | 338 | /* ADC output select */ |
333 | static const struct soc_enum alc5632_adcr_func_enum = | 339 | static SOC_ENUM_SINGLE_DECL(alc5632_adcr_func_enum, |
334 | SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel); | 340 | ALC5632_DAC_FUNC_SELECT, 5, |
341 | alc5632_adcr_func_sel); | ||
335 | static const struct snd_kcontrol_new alc5632_adcr_func_controls = | 342 | static const struct snd_kcontrol_new alc5632_adcr_func_controls = |
336 | SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum); | 343 | SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum); |
337 | 344 | ||
338 | /* I2S out select */ | 345 | /* I2S out select */ |
339 | static const struct soc_enum alc5632_i2s_out_enum = | 346 | static SOC_ENUM_SINGLE_DECL(alc5632_i2s_out_enum, |
340 | SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel); | 347 | ALC5632_I2S_OUT_CTL, 5, |
348 | alc5632_i2s_out_sel); | ||
341 | static const struct snd_kcontrol_new alc5632_i2s_out_controls = | 349 | static const struct snd_kcontrol_new alc5632_i2s_out_controls = |
342 | SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum); | 350 | SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum); |
343 | 351 | ||
@@ -1055,14 +1063,6 @@ static int alc5632_probe(struct snd_soc_codec *codec) | |||
1055 | struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); | 1063 | struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); |
1056 | int ret; | 1064 | int ret; |
1057 | 1065 | ||
1058 | codec->control_data = alc5632->regmap; | ||
1059 | |||
1060 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
1061 | if (ret != 0) { | ||
1062 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1063 | return ret; | ||
1064 | } | ||
1065 | |||
1066 | /* power on device */ | 1066 | /* power on device */ |
1067 | alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1067 | alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1068 | 1068 | ||
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index e4295fee8f13..29e198f57d4c 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -53,6 +53,14 @@ | |||
53 | #define ARIZONA_AIF_RX_ENABLES 0x1A | 53 | #define ARIZONA_AIF_RX_ENABLES 0x1A |
54 | #define ARIZONA_AIF_FORCE_WRITE 0x1B | 54 | #define ARIZONA_AIF_FORCE_WRITE 0x1B |
55 | 55 | ||
56 | #define ARIZONA_FLL_VCO_CORNER 141900000 | ||
57 | #define ARIZONA_FLL_MAX_FREF 13500000 | ||
58 | #define ARIZONA_FLL_MIN_FVCO 90000000 | ||
59 | #define ARIZONA_FLL_MAX_FRATIO 16 | ||
60 | #define ARIZONA_FLL_MAX_REFDIV 8 | ||
61 | #define ARIZONA_FLL_MIN_OUTDIV 2 | ||
62 | #define ARIZONA_FLL_MAX_OUTDIV 7 | ||
63 | |||
56 | #define arizona_fll_err(_fll, fmt, ...) \ | 64 | #define arizona_fll_err(_fll, fmt, ...) \ |
57 | dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) | 65 | dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) |
58 | #define arizona_fll_warn(_fll, fmt, ...) \ | 66 | #define arizona_fll_warn(_fll, fmt, ...) \ |
@@ -542,67 +550,76 @@ static const char *arizona_vol_ramp_text[] = { | |||
542 | "15ms/6dB", "30ms/6dB", | 550 | "15ms/6dB", "30ms/6dB", |
543 | }; | 551 | }; |
544 | 552 | ||
545 | const struct soc_enum arizona_in_vd_ramp = | 553 | SOC_ENUM_SINGLE_DECL(arizona_in_vd_ramp, |
546 | SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP, | 554 | ARIZONA_INPUT_VOLUME_RAMP, |
547 | ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text); | 555 | ARIZONA_IN_VD_RAMP_SHIFT, |
556 | arizona_vol_ramp_text); | ||
548 | EXPORT_SYMBOL_GPL(arizona_in_vd_ramp); | 557 | EXPORT_SYMBOL_GPL(arizona_in_vd_ramp); |
549 | 558 | ||
550 | const struct soc_enum arizona_in_vi_ramp = | 559 | SOC_ENUM_SINGLE_DECL(arizona_in_vi_ramp, |
551 | SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP, | 560 | ARIZONA_INPUT_VOLUME_RAMP, |
552 | ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text); | 561 | ARIZONA_IN_VI_RAMP_SHIFT, |
562 | arizona_vol_ramp_text); | ||
553 | EXPORT_SYMBOL_GPL(arizona_in_vi_ramp); | 563 | EXPORT_SYMBOL_GPL(arizona_in_vi_ramp); |
554 | 564 | ||
555 | const struct soc_enum arizona_out_vd_ramp = | 565 | SOC_ENUM_SINGLE_DECL(arizona_out_vd_ramp, |
556 | SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP, | 566 | ARIZONA_OUTPUT_VOLUME_RAMP, |
557 | ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text); | 567 | ARIZONA_OUT_VD_RAMP_SHIFT, |
568 | arizona_vol_ramp_text); | ||
558 | EXPORT_SYMBOL_GPL(arizona_out_vd_ramp); | 569 | EXPORT_SYMBOL_GPL(arizona_out_vd_ramp); |
559 | 570 | ||
560 | const struct soc_enum arizona_out_vi_ramp = | 571 | SOC_ENUM_SINGLE_DECL(arizona_out_vi_ramp, |
561 | SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP, | 572 | ARIZONA_OUTPUT_VOLUME_RAMP, |
562 | ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text); | 573 | ARIZONA_OUT_VI_RAMP_SHIFT, |
574 | arizona_vol_ramp_text); | ||
563 | EXPORT_SYMBOL_GPL(arizona_out_vi_ramp); | 575 | EXPORT_SYMBOL_GPL(arizona_out_vi_ramp); |
564 | 576 | ||
565 | static const char *arizona_lhpf_mode_text[] = { | 577 | static const char *arizona_lhpf_mode_text[] = { |
566 | "Low-pass", "High-pass" | 578 | "Low-pass", "High-pass" |
567 | }; | 579 | }; |
568 | 580 | ||
569 | const struct soc_enum arizona_lhpf1_mode = | 581 | SOC_ENUM_SINGLE_DECL(arizona_lhpf1_mode, |
570 | SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2, | 582 | ARIZONA_HPLPF1_1, |
571 | arizona_lhpf_mode_text); | 583 | ARIZONA_LHPF1_MODE_SHIFT, |
584 | arizona_lhpf_mode_text); | ||
572 | EXPORT_SYMBOL_GPL(arizona_lhpf1_mode); | 585 | EXPORT_SYMBOL_GPL(arizona_lhpf1_mode); |
573 | 586 | ||
574 | const struct soc_enum arizona_lhpf2_mode = | 587 | SOC_ENUM_SINGLE_DECL(arizona_lhpf2_mode, |
575 | SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2, | 588 | ARIZONA_HPLPF2_1, |
576 | arizona_lhpf_mode_text); | 589 | ARIZONA_LHPF2_MODE_SHIFT, |
590 | arizona_lhpf_mode_text); | ||
577 | EXPORT_SYMBOL_GPL(arizona_lhpf2_mode); | 591 | EXPORT_SYMBOL_GPL(arizona_lhpf2_mode); |
578 | 592 | ||
579 | const struct soc_enum arizona_lhpf3_mode = | 593 | SOC_ENUM_SINGLE_DECL(arizona_lhpf3_mode, |
580 | SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2, | 594 | ARIZONA_HPLPF3_1, |
581 | arizona_lhpf_mode_text); | 595 | ARIZONA_LHPF3_MODE_SHIFT, |
596 | arizona_lhpf_mode_text); | ||
582 | EXPORT_SYMBOL_GPL(arizona_lhpf3_mode); | 597 | EXPORT_SYMBOL_GPL(arizona_lhpf3_mode); |
583 | 598 | ||
584 | const struct soc_enum arizona_lhpf4_mode = | 599 | SOC_ENUM_SINGLE_DECL(arizona_lhpf4_mode, |
585 | SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2, | 600 | ARIZONA_HPLPF4_1, |
586 | arizona_lhpf_mode_text); | 601 | ARIZONA_LHPF4_MODE_SHIFT, |
602 | arizona_lhpf_mode_text); | ||
587 | EXPORT_SYMBOL_GPL(arizona_lhpf4_mode); | 603 | EXPORT_SYMBOL_GPL(arizona_lhpf4_mode); |
588 | 604 | ||
589 | static const char *arizona_ng_hold_text[] = { | 605 | static const char *arizona_ng_hold_text[] = { |
590 | "30ms", "120ms", "250ms", "500ms", | 606 | "30ms", "120ms", "250ms", "500ms", |
591 | }; | 607 | }; |
592 | 608 | ||
593 | const struct soc_enum arizona_ng_hold = | 609 | SOC_ENUM_SINGLE_DECL(arizona_ng_hold, |
594 | SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT, | 610 | ARIZONA_NOISE_GATE_CONTROL, |
595 | 4, arizona_ng_hold_text); | 611 | ARIZONA_NGATE_HOLD_SHIFT, |
612 | arizona_ng_hold_text); | ||
596 | EXPORT_SYMBOL_GPL(arizona_ng_hold); | 613 | EXPORT_SYMBOL_GPL(arizona_ng_hold); |
597 | 614 | ||
598 | static const char * const arizona_in_hpf_cut_text[] = { | 615 | static const char * const arizona_in_hpf_cut_text[] = { |
599 | "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz" | 616 | "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz" |
600 | }; | 617 | }; |
601 | 618 | ||
602 | const struct soc_enum arizona_in_hpf_cut_enum = | 619 | SOC_ENUM_SINGLE_DECL(arizona_in_hpf_cut_enum, |
603 | SOC_ENUM_SINGLE(ARIZONA_HPF_CONTROL, ARIZONA_IN_HPF_CUT_SHIFT, | 620 | ARIZONA_HPF_CONTROL, |
604 | ARRAY_SIZE(arizona_in_hpf_cut_text), | 621 | ARIZONA_IN_HPF_CUT_SHIFT, |
605 | arizona_in_hpf_cut_text); | 622 | arizona_in_hpf_cut_text); |
606 | EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); | 623 | EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); |
607 | 624 | ||
608 | static const char * const arizona_in_dmic_osr_text[] = { | 625 | static const char * const arizona_in_dmic_osr_text[] = { |
@@ -1377,74 +1394,147 @@ struct arizona_fll_cfg { | |||
1377 | int gain; | 1394 | int gain; |
1378 | }; | 1395 | }; |
1379 | 1396 | ||
1380 | static int arizona_calc_fll(struct arizona_fll *fll, | 1397 | static int arizona_validate_fll(struct arizona_fll *fll, |
1381 | struct arizona_fll_cfg *cfg, | 1398 | unsigned int Fref, |
1382 | unsigned int Fref, | 1399 | unsigned int Fout) |
1383 | unsigned int Fout) | ||
1384 | { | 1400 | { |
1385 | unsigned int target, div, gcd_fll; | 1401 | unsigned int Fvco_min; |
1386 | int i, ratio; | 1402 | |
1403 | if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) { | ||
1404 | arizona_fll_err(fll, | ||
1405 | "Can't scale %dMHz in to <=13.5MHz\n", | ||
1406 | Fref); | ||
1407 | return -EINVAL; | ||
1408 | } | ||
1387 | 1409 | ||
1388 | arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout); | 1410 | Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult; |
1411 | if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) { | ||
1412 | arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", | ||
1413 | Fout); | ||
1414 | return -EINVAL; | ||
1415 | } | ||
1416 | |||
1417 | return 0; | ||
1418 | } | ||
1419 | |||
1420 | static int arizona_find_fratio(unsigned int Fref, int *fratio) | ||
1421 | { | ||
1422 | int i; | ||
1423 | |||
1424 | /* Find an appropriate FLL_FRATIO */ | ||
1425 | for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { | ||
1426 | if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { | ||
1427 | if (fratio) | ||
1428 | *fratio = fll_fratios[i].fratio; | ||
1429 | return fll_fratios[i].ratio; | ||
1430 | } | ||
1431 | } | ||
1432 | |||
1433 | return -EINVAL; | ||
1434 | } | ||
1435 | |||
1436 | static int arizona_calc_fratio(struct arizona_fll *fll, | ||
1437 | struct arizona_fll_cfg *cfg, | ||
1438 | unsigned int target, | ||
1439 | unsigned int Fref, bool sync) | ||
1440 | { | ||
1441 | int init_ratio, ratio; | ||
1442 | int refdiv, div; | ||
1389 | 1443 | ||
1390 | /* Fref must be <=13.5MHz */ | 1444 | /* Fref must be <=13.5MHz, find initial refdiv */ |
1391 | div = 1; | 1445 | div = 1; |
1392 | cfg->refdiv = 0; | 1446 | cfg->refdiv = 0; |
1393 | while ((Fref / div) > 13500000) { | 1447 | while (Fref > ARIZONA_FLL_MAX_FREF) { |
1394 | div *= 2; | 1448 | div *= 2; |
1449 | Fref /= 2; | ||
1395 | cfg->refdiv++; | 1450 | cfg->refdiv++; |
1396 | 1451 | ||
1397 | if (div > 8) { | 1452 | if (div > ARIZONA_FLL_MAX_REFDIV) |
1398 | arizona_fll_err(fll, | ||
1399 | "Can't scale %dMHz in to <=13.5MHz\n", | ||
1400 | Fref); | ||
1401 | return -EINVAL; | 1453 | return -EINVAL; |
1454 | } | ||
1455 | |||
1456 | /* Find an appropriate FLL_FRATIO */ | ||
1457 | init_ratio = arizona_find_fratio(Fref, &cfg->fratio); | ||
1458 | if (init_ratio < 0) { | ||
1459 | arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n", | ||
1460 | Fref); | ||
1461 | return init_ratio; | ||
1462 | } | ||
1463 | |||
1464 | switch (fll->arizona->type) { | ||
1465 | case WM5110: | ||
1466 | if (fll->arizona->rev < 3 || sync) | ||
1467 | return init_ratio; | ||
1468 | break; | ||
1469 | default: | ||
1470 | return init_ratio; | ||
1471 | } | ||
1472 | |||
1473 | cfg->fratio = init_ratio - 1; | ||
1474 | |||
1475 | /* Adjust FRATIO/refdiv to avoid integer mode if possible */ | ||
1476 | refdiv = cfg->refdiv; | ||
1477 | |||
1478 | while (div <= ARIZONA_FLL_MAX_REFDIV) { | ||
1479 | for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO; | ||
1480 | ratio++) { | ||
1481 | if (target % (ratio * Fref)) { | ||
1482 | cfg->refdiv = refdiv; | ||
1483 | cfg->fratio = ratio - 1; | ||
1484 | return ratio; | ||
1485 | } | ||
1402 | } | 1486 | } |
1487 | |||
1488 | for (ratio = init_ratio - 1; ratio >= 0; ratio--) { | ||
1489 | if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) < | ||
1490 | Fref) | ||
1491 | break; | ||
1492 | |||
1493 | if (target % (ratio * Fref)) { | ||
1494 | cfg->refdiv = refdiv; | ||
1495 | cfg->fratio = ratio - 1; | ||
1496 | return ratio; | ||
1497 | } | ||
1498 | } | ||
1499 | |||
1500 | div *= 2; | ||
1501 | Fref /= 2; | ||
1502 | refdiv++; | ||
1503 | init_ratio = arizona_find_fratio(Fref, NULL); | ||
1403 | } | 1504 | } |
1404 | 1505 | ||
1405 | /* Apply the division for our remaining calculations */ | 1506 | arizona_fll_warn(fll, "Falling back to integer mode operation\n"); |
1406 | Fref /= div; | 1507 | return cfg->fratio + 1; |
1508 | } | ||
1509 | |||
1510 | static int arizona_calc_fll(struct arizona_fll *fll, | ||
1511 | struct arizona_fll_cfg *cfg, | ||
1512 | unsigned int Fref, bool sync) | ||
1513 | { | ||
1514 | unsigned int target, div, gcd_fll; | ||
1515 | int i, ratio; | ||
1516 | |||
1517 | arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout); | ||
1407 | 1518 | ||
1408 | /* Fvco should be over the targt; don't check the upper bound */ | 1519 | /* Fvco should be over the targt; don't check the upper bound */ |
1409 | div = 1; | 1520 | div = ARIZONA_FLL_MIN_OUTDIV; |
1410 | while (Fout * div < 90000000 * fll->vco_mult) { | 1521 | while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { |
1411 | div++; | 1522 | div++; |
1412 | if (div > 7) { | 1523 | if (div > ARIZONA_FLL_MAX_OUTDIV) |
1413 | arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", | ||
1414 | Fout); | ||
1415 | return -EINVAL; | 1524 | return -EINVAL; |
1416 | } | ||
1417 | } | 1525 | } |
1418 | target = Fout * div / fll->vco_mult; | 1526 | target = fll->fout * div / fll->vco_mult; |
1419 | cfg->outdiv = div; | 1527 | cfg->outdiv = div; |
1420 | 1528 | ||
1421 | arizona_fll_dbg(fll, "Fvco=%dHz\n", target); | 1529 | arizona_fll_dbg(fll, "Fvco=%dHz\n", target); |
1422 | 1530 | ||
1423 | /* Find an appropraite FLL_FRATIO and factor it out of the target */ | 1531 | /* Find an appropriate FLL_FRATIO and refdiv */ |
1424 | for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { | 1532 | ratio = arizona_calc_fratio(fll, cfg, target, Fref, sync); |
1425 | if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { | 1533 | if (ratio < 0) |
1426 | cfg->fratio = fll_fratios[i].fratio; | 1534 | return ratio; |
1427 | ratio = fll_fratios[i].ratio; | ||
1428 | break; | ||
1429 | } | ||
1430 | } | ||
1431 | if (i == ARRAY_SIZE(fll_fratios)) { | ||
1432 | arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n", | ||
1433 | Fref); | ||
1434 | return -EINVAL; | ||
1435 | } | ||
1436 | 1535 | ||
1437 | for (i = 0; i < ARRAY_SIZE(fll_gains); i++) { | 1536 | /* Apply the division for our remaining calculations */ |
1438 | if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) { | 1537 | Fref = Fref / (1 << cfg->refdiv); |
1439 | cfg->gain = fll_gains[i].gain; | ||
1440 | break; | ||
1441 | } | ||
1442 | } | ||
1443 | if (i == ARRAY_SIZE(fll_gains)) { | ||
1444 | arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n", | ||
1445 | Fref); | ||
1446 | return -EINVAL; | ||
1447 | } | ||
1448 | 1538 | ||
1449 | cfg->n = target / (ratio * Fref); | 1539 | cfg->n = target / (ratio * Fref); |
1450 | 1540 | ||
@@ -1469,6 +1559,18 @@ static int arizona_calc_fll(struct arizona_fll *fll, | |||
1469 | cfg->lambda >>= 1; | 1559 | cfg->lambda >>= 1; |
1470 | } | 1560 | } |
1471 | 1561 | ||
1562 | for (i = 0; i < ARRAY_SIZE(fll_gains); i++) { | ||
1563 | if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) { | ||
1564 | cfg->gain = fll_gains[i].gain; | ||
1565 | break; | ||
1566 | } | ||
1567 | } | ||
1568 | if (i == ARRAY_SIZE(fll_gains)) { | ||
1569 | arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n", | ||
1570 | Fref); | ||
1571 | return -EINVAL; | ||
1572 | } | ||
1573 | |||
1472 | arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n", | 1574 | arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n", |
1473 | cfg->n, cfg->theta, cfg->lambda); | 1575 | cfg->n, cfg->theta, cfg->lambda); |
1474 | arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", | 1576 | arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", |
@@ -1496,14 +1598,18 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base, | |||
1496 | cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | | 1598 | cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | |
1497 | source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); | 1599 | source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); |
1498 | 1600 | ||
1499 | if (sync) | 1601 | if (sync) { |
1500 | regmap_update_bits_async(arizona->regmap, base + 0x7, | 1602 | regmap_update_bits(arizona->regmap, base + 0x7, |
1501 | ARIZONA_FLL1_GAIN_MASK, | 1603 | ARIZONA_FLL1_GAIN_MASK, |
1502 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); | 1604 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); |
1503 | else | 1605 | } else { |
1504 | regmap_update_bits_async(arizona->regmap, base + 0x9, | 1606 | regmap_update_bits(arizona->regmap, base + 0x5, |
1505 | ARIZONA_FLL1_GAIN_MASK, | 1607 | ARIZONA_FLL1_OUTDIV_MASK, |
1506 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); | 1608 | cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); |
1609 | regmap_update_bits(arizona->regmap, base + 0x9, | ||
1610 | ARIZONA_FLL1_GAIN_MASK, | ||
1611 | cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); | ||
1612 | } | ||
1507 | 1613 | ||
1508 | regmap_update_bits_async(arizona->regmap, base + 2, | 1614 | regmap_update_bits_async(arizona->regmap, base + 2, |
1509 | ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, | 1615 | ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, |
@@ -1526,13 +1632,12 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll) | |||
1526 | return reg & ARIZONA_FLL1_ENA; | 1632 | return reg & ARIZONA_FLL1_ENA; |
1527 | } | 1633 | } |
1528 | 1634 | ||
1529 | static void arizona_enable_fll(struct arizona_fll *fll, | 1635 | static void arizona_enable_fll(struct arizona_fll *fll) |
1530 | struct arizona_fll_cfg *ref, | ||
1531 | struct arizona_fll_cfg *sync) | ||
1532 | { | 1636 | { |
1533 | struct arizona *arizona = fll->arizona; | 1637 | struct arizona *arizona = fll->arizona; |
1534 | int ret; | 1638 | int ret; |
1535 | bool use_sync = false; | 1639 | bool use_sync = false; |
1640 | struct arizona_fll_cfg cfg; | ||
1536 | 1641 | ||
1537 | /* | 1642 | /* |
1538 | * If we have both REFCLK and SYNCCLK then enable both, | 1643 | * If we have both REFCLK and SYNCCLK then enable both, |
@@ -1540,23 +1645,21 @@ static void arizona_enable_fll(struct arizona_fll *fll, | |||
1540 | */ | 1645 | */ |
1541 | if (fll->ref_src >= 0 && fll->ref_freq && | 1646 | if (fll->ref_src >= 0 && fll->ref_freq && |
1542 | fll->ref_src != fll->sync_src) { | 1647 | fll->ref_src != fll->sync_src) { |
1543 | regmap_update_bits_async(arizona->regmap, fll->base + 5, | 1648 | arizona_calc_fll(fll, &cfg, fll->ref_freq, false); |
1544 | ARIZONA_FLL1_OUTDIV_MASK, | ||
1545 | ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); | ||
1546 | 1649 | ||
1547 | arizona_apply_fll(arizona, fll->base, ref, fll->ref_src, | 1650 | arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src, |
1548 | false); | 1651 | false); |
1549 | if (fll->sync_src >= 0) { | 1652 | if (fll->sync_src >= 0) { |
1550 | arizona_apply_fll(arizona, fll->base + 0x10, sync, | 1653 | arizona_calc_fll(fll, &cfg, fll->sync_freq, true); |
1654 | |||
1655 | arizona_apply_fll(arizona, fll->base + 0x10, &cfg, | ||
1551 | fll->sync_src, true); | 1656 | fll->sync_src, true); |
1552 | use_sync = true; | 1657 | use_sync = true; |
1553 | } | 1658 | } |
1554 | } else if (fll->sync_src >= 0) { | 1659 | } else if (fll->sync_src >= 0) { |
1555 | regmap_update_bits_async(arizona->regmap, fll->base + 5, | 1660 | arizona_calc_fll(fll, &cfg, fll->sync_freq, false); |
1556 | ARIZONA_FLL1_OUTDIV_MASK, | ||
1557 | sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); | ||
1558 | 1661 | ||
1559 | arizona_apply_fll(arizona, fll->base, sync, | 1662 | arizona_apply_fll(arizona, fll->base, &cfg, |
1560 | fll->sync_src, false); | 1663 | fll->sync_src, false); |
1561 | 1664 | ||
1562 | regmap_update_bits_async(arizona->regmap, fll->base + 0x11, | 1665 | regmap_update_bits_async(arizona->regmap, fll->base + 0x11, |
@@ -1618,32 +1721,22 @@ static void arizona_disable_fll(struct arizona_fll *fll) | |||
1618 | int arizona_set_fll_refclk(struct arizona_fll *fll, int source, | 1721 | int arizona_set_fll_refclk(struct arizona_fll *fll, int source, |
1619 | unsigned int Fref, unsigned int Fout) | 1722 | unsigned int Fref, unsigned int Fout) |
1620 | { | 1723 | { |
1621 | struct arizona_fll_cfg ref, sync; | ||
1622 | int ret; | 1724 | int ret; |
1623 | 1725 | ||
1624 | if (fll->ref_src == source && fll->ref_freq == Fref) | 1726 | if (fll->ref_src == source && fll->ref_freq == Fref) |
1625 | return 0; | 1727 | return 0; |
1626 | 1728 | ||
1627 | if (fll->fout) { | 1729 | if (fll->fout && Fref > 0) { |
1628 | if (Fref > 0) { | 1730 | ret = arizona_validate_fll(fll, Fref, fll->fout); |
1629 | ret = arizona_calc_fll(fll, &ref, Fref, fll->fout); | 1731 | if (ret != 0) |
1630 | if (ret != 0) | 1732 | return ret; |
1631 | return ret; | ||
1632 | } | ||
1633 | |||
1634 | if (fll->sync_src >= 0) { | ||
1635 | ret = arizona_calc_fll(fll, &sync, fll->sync_freq, | ||
1636 | fll->fout); | ||
1637 | if (ret != 0) | ||
1638 | return ret; | ||
1639 | } | ||
1640 | } | 1733 | } |
1641 | 1734 | ||
1642 | fll->ref_src = source; | 1735 | fll->ref_src = source; |
1643 | fll->ref_freq = Fref; | 1736 | fll->ref_freq = Fref; |
1644 | 1737 | ||
1645 | if (fll->fout && Fref > 0) { | 1738 | if (fll->fout && Fref > 0) { |
1646 | arizona_enable_fll(fll, &ref, &sync); | 1739 | arizona_enable_fll(fll); |
1647 | } | 1740 | } |
1648 | 1741 | ||
1649 | return 0; | 1742 | return 0; |
@@ -1653,7 +1746,6 @@ EXPORT_SYMBOL_GPL(arizona_set_fll_refclk); | |||
1653 | int arizona_set_fll(struct arizona_fll *fll, int source, | 1746 | int arizona_set_fll(struct arizona_fll *fll, int source, |
1654 | unsigned int Fref, unsigned int Fout) | 1747 | unsigned int Fref, unsigned int Fout) |
1655 | { | 1748 | { |
1656 | struct arizona_fll_cfg ref, sync; | ||
1657 | int ret; | 1749 | int ret; |
1658 | 1750 | ||
1659 | if (fll->sync_src == source && | 1751 | if (fll->sync_src == source && |
@@ -1662,13 +1754,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source, | |||
1662 | 1754 | ||
1663 | if (Fout) { | 1755 | if (Fout) { |
1664 | if (fll->ref_src >= 0) { | 1756 | if (fll->ref_src >= 0) { |
1665 | ret = arizona_calc_fll(fll, &ref, fll->ref_freq, | 1757 | ret = arizona_validate_fll(fll, fll->ref_freq, Fout); |
1666 | Fout); | ||
1667 | if (ret != 0) | 1758 | if (ret != 0) |
1668 | return ret; | 1759 | return ret; |
1669 | } | 1760 | } |
1670 | 1761 | ||
1671 | ret = arizona_calc_fll(fll, &sync, Fref, Fout); | 1762 | ret = arizona_validate_fll(fll, Fref, Fout); |
1672 | if (ret != 0) | 1763 | if (ret != 0) |
1673 | return ret; | 1764 | return ret; |
1674 | } | 1765 | } |
@@ -1678,7 +1769,7 @@ int arizona_set_fll(struct arizona_fll *fll, int source, | |||
1678 | fll->fout = Fout; | 1769 | fll->fout = Fout; |
1679 | 1770 | ||
1680 | if (Fout) { | 1771 | if (Fout) { |
1681 | arizona_enable_fll(fll, &ref, &sync); | 1772 | arizona_enable_fll(fll); |
1682 | } else { | 1773 | } else { |
1683 | arizona_disable_fll(fll); | 1774 | arizona_disable_fll(fll); |
1684 | } | 1775 | } |
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index 43737a27d79c..1e25c7af853b 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c | |||
@@ -138,9 +138,8 @@ static int cq93vc_probe(struct snd_soc_codec *codec) | |||
138 | struct davinci_vc *davinci_vc = codec->dev->platform_data; | 138 | struct davinci_vc *davinci_vc = codec->dev->platform_data; |
139 | 139 | ||
140 | davinci_vc->cq93vc.codec = codec; | 140 | davinci_vc->cq93vc.codec = codec; |
141 | codec->control_data = davinci_vc->regmap; | ||
142 | 141 | ||
143 | snd_soc_codec_set_cache_io(codec, 32, 32, SND_SOC_REGMAP); | 142 | snd_soc_codec_set_cache_io(codec, davinci_vc->regmap); |
144 | 143 | ||
145 | /* Off, with power on */ | 144 | /* Off, with power on */ |
146 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 145 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 83c835d9fd88..3920e6264948 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -506,15 +506,6 @@ static int cs4270_probe(struct snd_soc_codec *codec) | |||
506 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 506 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
507 | int ret; | 507 | int ret; |
508 | 508 | ||
509 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will | ||
510 | * then do the I2C transactions itself. | ||
511 | */ | ||
512 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
513 | if (ret < 0) { | ||
514 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); | ||
515 | return ret; | ||
516 | } | ||
517 | |||
518 | /* Disable auto-mute. This feature appears to be buggy. In some | 509 | /* Disable auto-mute. This feature appears to be buggy. In some |
519 | * situations, auto-mute will not deactivate when it should, so we want | 510 | * situations, auto-mute will not deactivate when it should, so we want |
520 | * this feature disabled by default. An application (e.g. alsactl) can | 511 | * this feature disabled by default. An application (e.g. alsactl) can |
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index ce05fd93dc74..aef4965750c7 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c | |||
@@ -159,7 +159,6 @@ static bool cs4271_volatile_reg(struct device *dev, unsigned int reg) | |||
159 | } | 159 | } |
160 | 160 | ||
161 | struct cs4271_private { | 161 | struct cs4271_private { |
162 | /* SND_SOC_I2C or SND_SOC_SPI */ | ||
163 | unsigned int mclk; | 162 | unsigned int mclk; |
164 | bool master; | 163 | bool master; |
165 | bool deemph; | 164 | bool deemph; |
@@ -540,14 +539,10 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
540 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | 539 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); |
541 | struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; | 540 | struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; |
542 | int ret; | 541 | int ret; |
543 | int gpio_nreset = -EINVAL; | ||
544 | bool amutec_eq_bmutec = false; | 542 | bool amutec_eq_bmutec = false; |
545 | 543 | ||
546 | #ifdef CONFIG_OF | 544 | #ifdef CONFIG_OF |
547 | if (of_match_device(cs4271_dt_ids, codec->dev)) { | 545 | if (of_match_device(cs4271_dt_ids, codec->dev)) { |
548 | gpio_nreset = of_get_named_gpio(codec->dev->of_node, | ||
549 | "reset-gpio", 0); | ||
550 | |||
551 | if (of_get_property(codec->dev->of_node, | 546 | if (of_get_property(codec->dev->of_node, |
552 | "cirrus,amutec-eq-bmutec", NULL)) | 547 | "cirrus,amutec-eq-bmutec", NULL)) |
553 | amutec_eq_bmutec = true; | 548 | amutec_eq_bmutec = true; |
@@ -559,27 +554,19 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
559 | #endif | 554 | #endif |
560 | 555 | ||
561 | if (cs4271plat) { | 556 | if (cs4271plat) { |
562 | if (gpio_is_valid(cs4271plat->gpio_nreset)) | ||
563 | gpio_nreset = cs4271plat->gpio_nreset; | ||
564 | |||
565 | amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec; | 557 | amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec; |
566 | cs4271->enable_soft_reset = cs4271plat->enable_soft_reset; | 558 | cs4271->enable_soft_reset = cs4271plat->enable_soft_reset; |
567 | } | 559 | } |
568 | 560 | ||
569 | if (gpio_nreset >= 0) | 561 | if (gpio_is_valid(cs4271->gpio_nreset)) { |
570 | if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset")) | ||
571 | gpio_nreset = -EINVAL; | ||
572 | if (gpio_nreset >= 0) { | ||
573 | /* Reset codec */ | 562 | /* Reset codec */ |
574 | gpio_direction_output(gpio_nreset, 0); | 563 | gpio_direction_output(cs4271->gpio_nreset, 0); |
575 | udelay(1); | 564 | udelay(1); |
576 | gpio_set_value(gpio_nreset, 1); | 565 | gpio_set_value(cs4271->gpio_nreset, 1); |
577 | /* Give the codec time to wake up */ | 566 | /* Give the codec time to wake up */ |
578 | udelay(1); | 567 | udelay(1); |
579 | } | 568 | } |
580 | 569 | ||
581 | cs4271->gpio_nreset = gpio_nreset; | ||
582 | |||
583 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, | 570 | ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, |
584 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN, | 571 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN, |
585 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN); | 572 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN); |
@@ -625,6 +612,36 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { | |||
625 | .num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes), | 612 | .num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes), |
626 | }; | 613 | }; |
627 | 614 | ||
615 | static int cs4271_common_probe(struct device *dev, | ||
616 | struct cs4271_private **c) | ||
617 | { | ||
618 | struct cs4271_platform_data *cs4271plat = dev->platform_data; | ||
619 | struct cs4271_private *cs4271; | ||
620 | |||
621 | cs4271 = devm_kzalloc(dev, sizeof(*cs4271), GFP_KERNEL); | ||
622 | if (!cs4271) | ||
623 | return -ENOMEM; | ||
624 | |||
625 | if (of_match_device(cs4271_dt_ids, dev)) | ||
626 | cs4271->gpio_nreset = | ||
627 | of_get_named_gpio(dev->of_node, "reset-gpio", 0); | ||
628 | |||
629 | if (cs4271plat) | ||
630 | cs4271->gpio_nreset = cs4271plat->gpio_nreset; | ||
631 | |||
632 | if (gpio_is_valid(cs4271->gpio_nreset)) { | ||
633 | int ret; | ||
634 | |||
635 | ret = devm_gpio_request(dev, cs4271->gpio_nreset, | ||
636 | "CS4271 Reset"); | ||
637 | if (ret < 0) | ||
638 | return ret; | ||
639 | } | ||
640 | |||
641 | *c = cs4271; | ||
642 | return 0; | ||
643 | } | ||
644 | |||
628 | #if defined(CONFIG_SPI_MASTER) | 645 | #if defined(CONFIG_SPI_MASTER) |
629 | 646 | ||
630 | static const struct regmap_config cs4271_spi_regmap = { | 647 | static const struct regmap_config cs4271_spi_regmap = { |
@@ -644,10 +661,11 @@ static const struct regmap_config cs4271_spi_regmap = { | |||
644 | static int cs4271_spi_probe(struct spi_device *spi) | 661 | static int cs4271_spi_probe(struct spi_device *spi) |
645 | { | 662 | { |
646 | struct cs4271_private *cs4271; | 663 | struct cs4271_private *cs4271; |
664 | int ret; | ||
647 | 665 | ||
648 | cs4271 = devm_kzalloc(&spi->dev, sizeof(*cs4271), GFP_KERNEL); | 666 | ret = cs4271_common_probe(&spi->dev, &cs4271); |
649 | if (!cs4271) | 667 | if (ret < 0) |
650 | return -ENOMEM; | 668 | return ret; |
651 | 669 | ||
652 | spi_set_drvdata(spi, cs4271); | 670 | spi_set_drvdata(spi, cs4271); |
653 | cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap); | 671 | cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap); |
@@ -698,10 +716,11 @@ static int cs4271_i2c_probe(struct i2c_client *client, | |||
698 | const struct i2c_device_id *id) | 716 | const struct i2c_device_id *id) |
699 | { | 717 | { |
700 | struct cs4271_private *cs4271; | 718 | struct cs4271_private *cs4271; |
719 | int ret; | ||
701 | 720 | ||
702 | cs4271 = devm_kzalloc(&client->dev, sizeof(*cs4271), GFP_KERNEL); | 721 | ret = cs4271_common_probe(&client->dev, &cs4271); |
703 | if (!cs4271) | 722 | if (ret < 0) |
704 | return -ENOMEM; | 723 | return ret; |
705 | 724 | ||
706 | i2c_set_clientdata(client, cs4271); | 725 | i2c_set_clientdata(client, cs4271); |
707 | cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap); | 726 | cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap); |
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 6e9ea8379a91..6c0da2baa154 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <sound/pcm_params.h> | 30 | #include <sound/pcm_params.h> |
31 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
32 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
33 | #include <linux/regmap.h> | ||
33 | 34 | ||
34 | #include "cs42l51.h" | 35 | #include "cs42l51.h" |
35 | 36 | ||
@@ -40,7 +41,6 @@ enum master_slave_mode { | |||
40 | }; | 41 | }; |
41 | 42 | ||
42 | struct cs42l51_private { | 43 | struct cs42l51_private { |
43 | enum snd_soc_control_type control_type; | ||
44 | unsigned int mclk; | 44 | unsigned int mclk; |
45 | unsigned int audio_mode; /* The mode (I2S or left-justified) */ | 45 | unsigned int audio_mode; /* The mode (I2S or left-justified) */ |
46 | enum master_slave_mode func; | 46 | enum master_slave_mode func; |
@@ -52,24 +52,6 @@ struct cs42l51_private { | |||
52 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ | 52 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ |
53 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) | 53 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) |
54 | 54 | ||
55 | static int cs42l51_fill_cache(struct snd_soc_codec *codec) | ||
56 | { | ||
57 | u8 *cache = codec->reg_cache + 1; | ||
58 | struct i2c_client *i2c_client = to_i2c_client(codec->dev); | ||
59 | s32 length; | ||
60 | |||
61 | length = i2c_smbus_read_i2c_block_data(i2c_client, | ||
62 | CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache); | ||
63 | if (length != CS42L51_NUMREGS) { | ||
64 | dev_err(&i2c_client->dev, | ||
65 | "I2C read failure, addr=0x%x (ret=%d vs %d)\n", | ||
66 | i2c_client->addr, length, CS42L51_NUMREGS); | ||
67 | return -EIO; | ||
68 | } | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, | 55 | static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, |
74 | struct snd_ctl_elem_value *ucontrol) | 56 | struct snd_ctl_elem_value *ucontrol) |
75 | { | 57 | { |
@@ -124,9 +106,8 @@ static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol, | |||
124 | 106 | ||
125 | static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0); | 107 | static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0); |
126 | static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0); | 108 | static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0); |
127 | /* This is a lie. after -102 db, it stays at -102 */ | 109 | |
128 | /* maybe a range would be better */ | 110 | static const DECLARE_TLV_DB_SCALE(aout_tlv, -10200, 50, 0); |
129 | static const DECLARE_TLV_DB_SCALE(aout_tlv, -11550, 50, 0); | ||
130 | 111 | ||
131 | static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0); | 112 | static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0); |
132 | static const char *chan_mix[] = { | 113 | static const char *chan_mix[] = { |
@@ -135,13 +116,12 @@ static const char *chan_mix[] = { | |||
135 | "R L", | 116 | "R L", |
136 | }; | 117 | }; |
137 | 118 | ||
138 | static const struct soc_enum cs42l51_chan_mix = | 119 | static SOC_ENUM_SINGLE_EXT_DECL(cs42l51_chan_mix, chan_mix); |
139 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chan_mix), chan_mix); | ||
140 | 120 | ||
141 | static const struct snd_kcontrol_new cs42l51_snd_controls[] = { | 121 | static const struct snd_kcontrol_new cs42l51_snd_controls[] = { |
142 | SOC_DOUBLE_R_SX_TLV("PCM Playback Volume", | 122 | SOC_DOUBLE_R_SX_TLV("PCM Playback Volume", |
143 | CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, | 123 | CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, |
144 | 6, 0x19, 0x7F, adc_pcm_tlv), | 124 | 0, 0x19, 0x7F, adc_pcm_tlv), |
145 | SOC_DOUBLE_R("PCM Playback Switch", | 125 | SOC_DOUBLE_R("PCM Playback Switch", |
146 | CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1), | 126 | CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1), |
147 | SOC_DOUBLE_R_SX_TLV("Analog Playback Volume", | 127 | SOC_DOUBLE_R_SX_TLV("Analog Playback Volume", |
@@ -149,7 +129,7 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = { | |||
149 | 0, 0x34, 0xE4, aout_tlv), | 129 | 0, 0x34, 0xE4, aout_tlv), |
150 | SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", | 130 | SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", |
151 | CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, | 131 | CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, |
152 | 6, 0x19, 0x7F, adc_pcm_tlv), | 132 | 0, 0x19, 0x7F, adc_pcm_tlv), |
153 | SOC_DOUBLE_R("ADC Mixer Switch", | 133 | SOC_DOUBLE_R("ADC Mixer Switch", |
154 | CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1), | 134 | CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1), |
155 | SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0), | 135 | SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0), |
@@ -192,22 +172,22 @@ static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w, | |||
192 | 172 | ||
193 | static const char *cs42l51_dac_names[] = {"Direct PCM", | 173 | static const char *cs42l51_dac_names[] = {"Direct PCM", |
194 | "DSP PCM", "ADC"}; | 174 | "DSP PCM", "ADC"}; |
195 | static const struct soc_enum cs42l51_dac_mux_enum = | 175 | static SOC_ENUM_SINGLE_DECL(cs42l51_dac_mux_enum, |
196 | SOC_ENUM_SINGLE(CS42L51_DAC_CTL, 6, 3, cs42l51_dac_names); | 176 | CS42L51_DAC_CTL, 6, cs42l51_dac_names); |
197 | static const struct snd_kcontrol_new cs42l51_dac_mux_controls = | 177 | static const struct snd_kcontrol_new cs42l51_dac_mux_controls = |
198 | SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum); | 178 | SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum); |
199 | 179 | ||
200 | static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left", | 180 | static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left", |
201 | "MIC Left", "MIC+preamp Left"}; | 181 | "MIC Left", "MIC+preamp Left"}; |
202 | static const struct soc_enum cs42l51_adcl_mux_enum = | 182 | static SOC_ENUM_SINGLE_DECL(cs42l51_adcl_mux_enum, |
203 | SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 4, 4, cs42l51_adcl_names); | 183 | CS42L51_ADC_INPUT, 4, cs42l51_adcl_names); |
204 | static const struct snd_kcontrol_new cs42l51_adcl_mux_controls = | 184 | static const struct snd_kcontrol_new cs42l51_adcl_mux_controls = |
205 | SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum); | 185 | SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum); |
206 | 186 | ||
207 | static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right", | 187 | static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right", |
208 | "MIC Right", "MIC+preamp Right"}; | 188 | "MIC Right", "MIC+preamp Right"}; |
209 | static const struct soc_enum cs42l51_adcr_mux_enum = | 189 | static SOC_ENUM_SINGLE_DECL(cs42l51_adcr_mux_enum, |
210 | SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 6, 4, cs42l51_adcr_names); | 190 | CS42L51_ADC_INPUT, 6, cs42l51_adcr_names); |
211 | static const struct snd_kcontrol_new cs42l51_adcr_mux_controls = | 191 | static const struct snd_kcontrol_new cs42l51_adcr_mux_controls = |
212 | SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum); | 192 | SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum); |
213 | 193 | ||
@@ -505,21 +485,8 @@ static struct snd_soc_dai_driver cs42l51_dai = { | |||
505 | 485 | ||
506 | static int cs42l51_probe(struct snd_soc_codec *codec) | 486 | static int cs42l51_probe(struct snd_soc_codec *codec) |
507 | { | 487 | { |
508 | struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); | ||
509 | int ret, reg; | 488 | int ret, reg; |
510 | 489 | ||
511 | ret = cs42l51_fill_cache(codec); | ||
512 | if (ret < 0) { | ||
513 | dev_err(codec->dev, "failed to fill register cache\n"); | ||
514 | return ret; | ||
515 | } | ||
516 | |||
517 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type); | ||
518 | if (ret < 0) { | ||
519 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
520 | return ret; | ||
521 | } | ||
522 | |||
523 | /* | 490 | /* |
524 | * DAC configuration | 491 | * DAC configuration |
525 | * - Use signal processor | 492 | * - Use signal processor |
@@ -538,8 +505,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec) | |||
538 | 505 | ||
539 | static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { | 506 | static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { |
540 | .probe = cs42l51_probe, | 507 | .probe = cs42l51_probe, |
541 | .reg_cache_size = CS42L51_NUMREGS + 1, | ||
542 | .reg_word_size = sizeof(u8), | ||
543 | 508 | ||
544 | .controls = cs42l51_snd_controls, | 509 | .controls = cs42l51_snd_controls, |
545 | .num_controls = ARRAY_SIZE(cs42l51_snd_controls), | 510 | .num_controls = ARRAY_SIZE(cs42l51_snd_controls), |
@@ -549,38 +514,53 @@ static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { | |||
549 | .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), | 514 | .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), |
550 | }; | 515 | }; |
551 | 516 | ||
517 | static const struct regmap_config cs42l51_regmap = { | ||
518 | .reg_bits = 8, | ||
519 | .val_bits = 8, | ||
520 | |||
521 | .max_register = CS42L51_CHARGE_FREQ, | ||
522 | .cache_type = REGCACHE_RBTREE, | ||
523 | }; | ||
524 | |||
552 | static int cs42l51_i2c_probe(struct i2c_client *i2c_client, | 525 | static int cs42l51_i2c_probe(struct i2c_client *i2c_client, |
553 | const struct i2c_device_id *id) | 526 | const struct i2c_device_id *id) |
554 | { | 527 | { |
555 | struct cs42l51_private *cs42l51; | 528 | struct cs42l51_private *cs42l51; |
529 | struct regmap *regmap; | ||
530 | unsigned int val; | ||
556 | int ret; | 531 | int ret; |
557 | 532 | ||
533 | regmap = devm_regmap_init_i2c(i2c_client, &cs42l51_regmap); | ||
534 | if (IS_ERR(regmap)) { | ||
535 | ret = PTR_ERR(regmap); | ||
536 | dev_err(&i2c_client->dev, "Failed to create regmap: %d\n", | ||
537 | ret); | ||
538 | return ret; | ||
539 | } | ||
540 | |||
558 | /* Verify that we have a CS42L51 */ | 541 | /* Verify that we have a CS42L51 */ |
559 | ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); | 542 | ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val); |
560 | if (ret < 0) { | 543 | if (ret < 0) { |
561 | dev_err(&i2c_client->dev, "failed to read I2C\n"); | 544 | dev_err(&i2c_client->dev, "failed to read I2C\n"); |
562 | goto error; | 545 | goto error; |
563 | } | 546 | } |
564 | 547 | ||
565 | if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && | 548 | if ((val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && |
566 | (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { | 549 | (val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { |
567 | dev_err(&i2c_client->dev, "Invalid chip id\n"); | 550 | dev_err(&i2c_client->dev, "Invalid chip id: %x\n", val); |
568 | ret = -ENODEV; | 551 | ret = -ENODEV; |
569 | goto error; | 552 | goto error; |
570 | } | 553 | } |
571 | 554 | ||
572 | dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", | 555 | dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", |
573 | ret & 7); | 556 | val & 7); |
574 | 557 | ||
575 | cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private), | 558 | cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private), |
576 | GFP_KERNEL); | 559 | GFP_KERNEL); |
577 | if (!cs42l51) { | 560 | if (!cs42l51) |
578 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
579 | return -ENOMEM; | 561 | return -ENOMEM; |
580 | } | ||
581 | 562 | ||
582 | i2c_set_clientdata(i2c_client, cs42l51); | 563 | i2c_set_clientdata(i2c_client, cs42l51); |
583 | cs42l51->control_type = SND_SOC_I2C; | ||
584 | 564 | ||
585 | ret = snd_soc_register_codec(&i2c_client->dev, | 565 | ret = snd_soc_register_codec(&i2c_client->dev, |
586 | &soc_codec_device_cs42l51, &cs42l51_dai, 1); | 566 | &soc_codec_device_cs42l51, &cs42l51_dai, 1); |
@@ -600,10 +580,17 @@ static const struct i2c_device_id cs42l51_id[] = { | |||
600 | }; | 580 | }; |
601 | MODULE_DEVICE_TABLE(i2c, cs42l51_id); | 581 | MODULE_DEVICE_TABLE(i2c, cs42l51_id); |
602 | 582 | ||
583 | static const struct of_device_id cs42l51_of_match[] = { | ||
584 | { .compatible = "cirrus,cs42l51", }, | ||
585 | { } | ||
586 | }; | ||
587 | MODULE_DEVICE_TABLE(of, cs42l51_of_match); | ||
588 | |||
603 | static struct i2c_driver cs42l51_i2c_driver = { | 589 | static struct i2c_driver cs42l51_i2c_driver = { |
604 | .driver = { | 590 | .driver = { |
605 | .name = "cs42l51-codec", | 591 | .name = "cs42l51-codec", |
606 | .owner = THIS_MODULE, | 592 | .owner = THIS_MODULE, |
593 | .of_match_table = cs42l51_of_match, | ||
607 | }, | 594 | }, |
608 | .id_table = cs42l51_id, | 595 | .id_table = cs42l51_id, |
609 | .probe = cs42l51_i2c_probe, | 596 | .probe = cs42l51_i2c_probe, |
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 0bac6d5a4ac8..f0ca6bee6771 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -210,13 +210,11 @@ static const char * const cs42l52_adca_text[] = { | |||
210 | static const char * const cs42l52_adcb_text[] = { | 210 | static const char * const cs42l52_adcb_text[] = { |
211 | "Input1B", "Input2B", "Input3B", "Input4B", "PGA Input Right"}; | 211 | "Input1B", "Input2B", "Input3B", "Input4B", "PGA Input Right"}; |
212 | 212 | ||
213 | static const struct soc_enum adca_enum = | 213 | static SOC_ENUM_SINGLE_DECL(adca_enum, |
214 | SOC_ENUM_SINGLE(CS42L52_ADC_PGA_A, 5, | 214 | CS42L52_ADC_PGA_A, 5, cs42l52_adca_text); |
215 | ARRAY_SIZE(cs42l52_adca_text), cs42l52_adca_text); | ||
216 | 215 | ||
217 | static const struct soc_enum adcb_enum = | 216 | static SOC_ENUM_SINGLE_DECL(adcb_enum, |
218 | SOC_ENUM_SINGLE(CS42L52_ADC_PGA_B, 5, | 217 | CS42L52_ADC_PGA_B, 5, cs42l52_adcb_text); |
219 | ARRAY_SIZE(cs42l52_adcb_text), cs42l52_adcb_text); | ||
220 | 218 | ||
221 | static const struct snd_kcontrol_new adca_mux = | 219 | static const struct snd_kcontrol_new adca_mux = |
222 | SOC_DAPM_ENUM("Left ADC Input Capture Mux", adca_enum); | 220 | SOC_DAPM_ENUM("Left ADC Input Capture Mux", adca_enum); |
@@ -229,26 +227,22 @@ static const char * const mic_bias_level_text[] = { | |||
229 | "0.8 +VA", "0.83 +VA", "0.91 +VA" | 227 | "0.8 +VA", "0.83 +VA", "0.91 +VA" |
230 | }; | 228 | }; |
231 | 229 | ||
232 | static const struct soc_enum mic_bias_level_enum = | 230 | static SOC_ENUM_SINGLE_DECL(mic_bias_level_enum, |
233 | SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0, | 231 | CS42L52_IFACE_CTL2, 0, mic_bias_level_text); |
234 | ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text); | ||
235 | 232 | ||
236 | static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" }; | 233 | static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" }; |
237 | 234 | ||
238 | static const struct soc_enum mica_enum = | 235 | static SOC_ENUM_SINGLE_DECL(mica_enum, |
239 | SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5, | 236 | CS42L52_MICA_CTL, 5, cs42l52_mic_text); |
240 | ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text); | ||
241 | 237 | ||
242 | static const struct soc_enum micb_enum = | 238 | static SOC_ENUM_SINGLE_DECL(micb_enum, |
243 | SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5, | 239 | CS42L52_MICB_CTL, 5, cs42l52_mic_text); |
244 | ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text); | ||
245 | 240 | ||
246 | static const char * const digital_output_mux_text[] = {"ADC", "DSP"}; | 241 | static const char * const digital_output_mux_text[] = {"ADC", "DSP"}; |
247 | 242 | ||
248 | static const struct soc_enum digital_output_mux_enum = | 243 | static SOC_ENUM_SINGLE_DECL(digital_output_mux_enum, |
249 | SOC_ENUM_SINGLE(CS42L52_ADC_MISC_CTL, 6, | 244 | CS42L52_ADC_MISC_CTL, 6, |
250 | ARRAY_SIZE(digital_output_mux_text), | 245 | digital_output_mux_text); |
251 | digital_output_mux_text); | ||
252 | 246 | ||
253 | static const struct snd_kcontrol_new digital_output_mux = | 247 | static const struct snd_kcontrol_new digital_output_mux = |
254 | SOC_DAPM_ENUM("Digital Output Mux", digital_output_mux_enum); | 248 | SOC_DAPM_ENUM("Digital Output Mux", digital_output_mux_enum); |
@@ -258,18 +252,18 @@ static const char * const hp_gain_num_text[] = { | |||
258 | "0.7099", "0.8399", "1.000", "1.1430" | 252 | "0.7099", "0.8399", "1.000", "1.1430" |
259 | }; | 253 | }; |
260 | 254 | ||
261 | static const struct soc_enum hp_gain_enum = | 255 | static SOC_ENUM_SINGLE_DECL(hp_gain_enum, |
262 | SOC_ENUM_SINGLE(CS42L52_PB_CTL1, 5, | 256 | CS42L52_PB_CTL1, 5, |
263 | ARRAY_SIZE(hp_gain_num_text), hp_gain_num_text); | 257 | hp_gain_num_text); |
264 | 258 | ||
265 | static const char * const beep_pitch_text[] = { | 259 | static const char * const beep_pitch_text[] = { |
266 | "C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5", | 260 | "C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5", |
267 | "C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7" | 261 | "C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7" |
268 | }; | 262 | }; |
269 | 263 | ||
270 | static const struct soc_enum beep_pitch_enum = | 264 | static SOC_ENUM_SINGLE_DECL(beep_pitch_enum, |
271 | SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 4, | 265 | CS42L52_BEEP_FREQ, 4, |
272 | ARRAY_SIZE(beep_pitch_text), beep_pitch_text); | 266 | beep_pitch_text); |
273 | 267 | ||
274 | static const char * const beep_ontime_text[] = { | 268 | static const char * const beep_ontime_text[] = { |
275 | "86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s", | 269 | "86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s", |
@@ -277,66 +271,66 @@ static const char * const beep_ontime_text[] = { | |||
277 | "3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s" | 271 | "3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s" |
278 | }; | 272 | }; |
279 | 273 | ||
280 | static const struct soc_enum beep_ontime_enum = | 274 | static SOC_ENUM_SINGLE_DECL(beep_ontime_enum, |
281 | SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 0, | 275 | CS42L52_BEEP_FREQ, 0, |
282 | ARRAY_SIZE(beep_ontime_text), beep_ontime_text); | 276 | beep_ontime_text); |
283 | 277 | ||
284 | static const char * const beep_offtime_text[] = { | 278 | static const char * const beep_offtime_text[] = { |
285 | "1.23 s", "2.58 s", "3.90 s", "5.20 s", | 279 | "1.23 s", "2.58 s", "3.90 s", "5.20 s", |
286 | "6.60 s", "8.05 s", "9.35 s", "10.80 s" | 280 | "6.60 s", "8.05 s", "9.35 s", "10.80 s" |
287 | }; | 281 | }; |
288 | 282 | ||
289 | static const struct soc_enum beep_offtime_enum = | 283 | static SOC_ENUM_SINGLE_DECL(beep_offtime_enum, |
290 | SOC_ENUM_SINGLE(CS42L52_BEEP_VOL, 5, | 284 | CS42L52_BEEP_VOL, 5, |
291 | ARRAY_SIZE(beep_offtime_text), beep_offtime_text); | 285 | beep_offtime_text); |
292 | 286 | ||
293 | static const char * const beep_config_text[] = { | 287 | static const char * const beep_config_text[] = { |
294 | "Off", "Single", "Multiple", "Continuous" | 288 | "Off", "Single", "Multiple", "Continuous" |
295 | }; | 289 | }; |
296 | 290 | ||
297 | static const struct soc_enum beep_config_enum = | 291 | static SOC_ENUM_SINGLE_DECL(beep_config_enum, |
298 | SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 6, | 292 | CS42L52_BEEP_TONE_CTL, 6, |
299 | ARRAY_SIZE(beep_config_text), beep_config_text); | 293 | beep_config_text); |
300 | 294 | ||
301 | static const char * const beep_bass_text[] = { | 295 | static const char * const beep_bass_text[] = { |
302 | "50 Hz", "100 Hz", "200 Hz", "250 Hz" | 296 | "50 Hz", "100 Hz", "200 Hz", "250 Hz" |
303 | }; | 297 | }; |
304 | 298 | ||
305 | static const struct soc_enum beep_bass_enum = | 299 | static SOC_ENUM_SINGLE_DECL(beep_bass_enum, |
306 | SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 1, | 300 | CS42L52_BEEP_TONE_CTL, 1, |
307 | ARRAY_SIZE(beep_bass_text), beep_bass_text); | 301 | beep_bass_text); |
308 | 302 | ||
309 | static const char * const beep_treble_text[] = { | 303 | static const char * const beep_treble_text[] = { |
310 | "5 kHz", "7 kHz", "10 kHz", " 15 kHz" | 304 | "5 kHz", "7 kHz", "10 kHz", " 15 kHz" |
311 | }; | 305 | }; |
312 | 306 | ||
313 | static const struct soc_enum beep_treble_enum = | 307 | static SOC_ENUM_SINGLE_DECL(beep_treble_enum, |
314 | SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 3, | 308 | CS42L52_BEEP_TONE_CTL, 3, |
315 | ARRAY_SIZE(beep_treble_text), beep_treble_text); | 309 | beep_treble_text); |
316 | 310 | ||
317 | static const char * const ng_threshold_text[] = { | 311 | static const char * const ng_threshold_text[] = { |
318 | "-34dB", "-37dB", "-40dB", "-43dB", | 312 | "-34dB", "-37dB", "-40dB", "-43dB", |
319 | "-46dB", "-52dB", "-58dB", "-64dB" | 313 | "-46dB", "-52dB", "-58dB", "-64dB" |
320 | }; | 314 | }; |
321 | 315 | ||
322 | static const struct soc_enum ng_threshold_enum = | 316 | static SOC_ENUM_SINGLE_DECL(ng_threshold_enum, |
323 | SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 2, | 317 | CS42L52_NOISE_GATE_CTL, 2, |
324 | ARRAY_SIZE(ng_threshold_text), ng_threshold_text); | 318 | ng_threshold_text); |
325 | 319 | ||
326 | static const char * const cs42l52_ng_delay_text[] = { | 320 | static const char * const cs42l52_ng_delay_text[] = { |
327 | "50ms", "100ms", "150ms", "200ms"}; | 321 | "50ms", "100ms", "150ms", "200ms"}; |
328 | 322 | ||
329 | static const struct soc_enum ng_delay_enum = | 323 | static SOC_ENUM_SINGLE_DECL(ng_delay_enum, |
330 | SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 0, | 324 | CS42L52_NOISE_GATE_CTL, 0, |
331 | ARRAY_SIZE(cs42l52_ng_delay_text), cs42l52_ng_delay_text); | 325 | cs42l52_ng_delay_text); |
332 | 326 | ||
333 | static const char * const cs42l52_ng_type_text[] = { | 327 | static const char * const cs42l52_ng_type_text[] = { |
334 | "Apply Specific", "Apply All" | 328 | "Apply Specific", "Apply All" |
335 | }; | 329 | }; |
336 | 330 | ||
337 | static const struct soc_enum ng_type_enum = | 331 | static SOC_ENUM_SINGLE_DECL(ng_type_enum, |
338 | SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 6, | 332 | CS42L52_NOISE_GATE_CTL, 6, |
339 | ARRAY_SIZE(cs42l52_ng_type_text), cs42l52_ng_type_text); | 333 | cs42l52_ng_type_text); |
340 | 334 | ||
341 | static const char * const left_swap_text[] = { | 335 | static const char * const left_swap_text[] = { |
342 | "Left", "LR 2", "Right"}; | 336 | "Left", "LR 2", "Right"}; |
@@ -347,7 +341,7 @@ static const char * const right_swap_text[] = { | |||
347 | static const unsigned int swap_values[] = { 0, 1, 3 }; | 341 | static const unsigned int swap_values[] = { 0, 1, 3 }; |
348 | 342 | ||
349 | static const struct soc_enum adca_swap_enum = | 343 | static const struct soc_enum adca_swap_enum = |
350 | SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 1, | 344 | SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 3, |
351 | ARRAY_SIZE(left_swap_text), | 345 | ARRAY_SIZE(left_swap_text), |
352 | left_swap_text, | 346 | left_swap_text, |
353 | swap_values); | 347 | swap_values); |
@@ -356,7 +350,7 @@ static const struct snd_kcontrol_new adca_mixer = | |||
356 | SOC_DAPM_ENUM("Route", adca_swap_enum); | 350 | SOC_DAPM_ENUM("Route", adca_swap_enum); |
357 | 351 | ||
358 | static const struct soc_enum pcma_swap_enum = | 352 | static const struct soc_enum pcma_swap_enum = |
359 | SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 1, | 353 | SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 3, |
360 | ARRAY_SIZE(left_swap_text), | 354 | ARRAY_SIZE(left_swap_text), |
361 | left_swap_text, | 355 | left_swap_text, |
362 | swap_values); | 356 | swap_values); |
@@ -365,7 +359,7 @@ static const struct snd_kcontrol_new pcma_mixer = | |||
365 | SOC_DAPM_ENUM("Route", pcma_swap_enum); | 359 | SOC_DAPM_ENUM("Route", pcma_swap_enum); |
366 | 360 | ||
367 | static const struct soc_enum adcb_swap_enum = | 361 | static const struct soc_enum adcb_swap_enum = |
368 | SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 1, | 362 | SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 3, |
369 | ARRAY_SIZE(right_swap_text), | 363 | ARRAY_SIZE(right_swap_text), |
370 | right_swap_text, | 364 | right_swap_text, |
371 | swap_values); | 365 | swap_values); |
@@ -374,7 +368,7 @@ static const struct snd_kcontrol_new adcb_mixer = | |||
374 | SOC_DAPM_ENUM("Route", adcb_swap_enum); | 368 | SOC_DAPM_ENUM("Route", adcb_swap_enum); |
375 | 369 | ||
376 | static const struct soc_enum pcmb_swap_enum = | 370 | static const struct soc_enum pcmb_swap_enum = |
377 | SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 1, | 371 | SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 3, |
378 | ARRAY_SIZE(right_swap_text), | 372 | ARRAY_SIZE(right_swap_text), |
379 | right_swap_text, | 373 | right_swap_text, |
380 | swap_values); | 374 | swap_values); |
@@ -1115,14 +1109,7 @@ static void cs42l52_free_beep(struct snd_soc_codec *codec) | |||
1115 | static int cs42l52_probe(struct snd_soc_codec *codec) | 1109 | static int cs42l52_probe(struct snd_soc_codec *codec) |
1116 | { | 1110 | { |
1117 | struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec); | 1111 | struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec); |
1118 | int ret; | ||
1119 | 1112 | ||
1120 | codec->control_data = cs42l52->regmap; | ||
1121 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
1122 | if (ret < 0) { | ||
1123 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1124 | return ret; | ||
1125 | } | ||
1126 | regcache_cache_only(cs42l52->regmap, true); | 1113 | regcache_cache_only(cs42l52->regmap, true); |
1127 | 1114 | ||
1128 | cs42l52_add_mic_controls(codec); | 1115 | cs42l52_add_mic_controls(codec); |
@@ -1134,7 +1121,7 @@ static int cs42l52_probe(struct snd_soc_codec *codec) | |||
1134 | cs42l52->sysclk = CS42L52_DEFAULT_CLK; | 1121 | cs42l52->sysclk = CS42L52_DEFAULT_CLK; |
1135 | cs42l52->config.format = CS42L52_DEFAULT_FORMAT; | 1122 | cs42l52->config.format = CS42L52_DEFAULT_FORMAT; |
1136 | 1123 | ||
1137 | return ret; | 1124 | return 0; |
1138 | } | 1125 | } |
1139 | 1126 | ||
1140 | static int cs42l52_remove(struct snd_soc_codec *codec) | 1127 | static int cs42l52_remove(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 549d5d6a3fef..0ee60a19a263 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -278,13 +278,13 @@ static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1); | |||
278 | static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" }; | 278 | static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" }; |
279 | static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" }; | 279 | static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" }; |
280 | 280 | ||
281 | static const struct soc_enum pgaa_enum = | 281 | static SOC_ENUM_SINGLE_DECL(pgaa_enum, |
282 | SOC_ENUM_SINGLE(CS42L73_ADCIPC, 3, | 282 | CS42L73_ADCIPC, 3, |
283 | ARRAY_SIZE(cs42l73_pgaa_text), cs42l73_pgaa_text); | 283 | cs42l73_pgaa_text); |
284 | 284 | ||
285 | static const struct soc_enum pgab_enum = | 285 | static SOC_ENUM_SINGLE_DECL(pgab_enum, |
286 | SOC_ENUM_SINGLE(CS42L73_ADCIPC, 7, | 286 | CS42L73_ADCIPC, 7, |
287 | ARRAY_SIZE(cs42l73_pgab_text), cs42l73_pgab_text); | 287 | cs42l73_pgab_text); |
288 | 288 | ||
289 | static const struct snd_kcontrol_new pgaa_mux = | 289 | static const struct snd_kcontrol_new pgaa_mux = |
290 | SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum); | 290 | SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum); |
@@ -309,9 +309,9 @@ static const struct snd_kcontrol_new input_right_mixer[] = { | |||
309 | static const char * const cs42l73_ng_delay_text[] = { | 309 | static const char * const cs42l73_ng_delay_text[] = { |
310 | "50ms", "100ms", "150ms", "200ms" }; | 310 | "50ms", "100ms", "150ms", "200ms" }; |
311 | 311 | ||
312 | static const struct soc_enum ng_delay_enum = | 312 | static SOC_ENUM_SINGLE_DECL(ng_delay_enum, |
313 | SOC_ENUM_SINGLE(CS42L73_NGCAB, 0, | 313 | CS42L73_NGCAB, 0, |
314 | ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text); | 314 | cs42l73_ng_delay_text); |
315 | 315 | ||
316 | static const char * const cs42l73_mono_mix_texts[] = { | 316 | static const char * const cs42l73_mono_mix_texts[] = { |
317 | "Left", "Right", "Mono Mix"}; | 317 | "Left", "Right", "Mono Mix"}; |
@@ -319,7 +319,7 @@ static const char * const cs42l73_mono_mix_texts[] = { | |||
319 | static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 }; | 319 | static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 }; |
320 | 320 | ||
321 | static const struct soc_enum spk_asp_enum = | 321 | static const struct soc_enum spk_asp_enum = |
322 | SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 1, | 322 | SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 3, |
323 | ARRAY_SIZE(cs42l73_mono_mix_texts), | 323 | ARRAY_SIZE(cs42l73_mono_mix_texts), |
324 | cs42l73_mono_mix_texts, | 324 | cs42l73_mono_mix_texts, |
325 | cs42l73_mono_mix_values); | 325 | cs42l73_mono_mix_values); |
@@ -337,7 +337,7 @@ static const struct snd_kcontrol_new spk_xsp_mixer = | |||
337 | SOC_DAPM_ENUM("Route", spk_xsp_enum); | 337 | SOC_DAPM_ENUM("Route", spk_xsp_enum); |
338 | 338 | ||
339 | static const struct soc_enum esl_asp_enum = | 339 | static const struct soc_enum esl_asp_enum = |
340 | SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 5, | 340 | SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 3, |
341 | ARRAY_SIZE(cs42l73_mono_mix_texts), | 341 | ARRAY_SIZE(cs42l73_mono_mix_texts), |
342 | cs42l73_mono_mix_texts, | 342 | cs42l73_mono_mix_texts, |
343 | cs42l73_mono_mix_values); | 343 | cs42l73_mono_mix_values); |
@@ -346,7 +346,7 @@ static const struct snd_kcontrol_new esl_asp_mixer = | |||
346 | SOC_DAPM_ENUM("Route", esl_asp_enum); | 346 | SOC_DAPM_ENUM("Route", esl_asp_enum); |
347 | 347 | ||
348 | static const struct soc_enum esl_xsp_enum = | 348 | static const struct soc_enum esl_xsp_enum = |
349 | SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 7, | 349 | SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 3, |
350 | ARRAY_SIZE(cs42l73_mono_mix_texts), | 350 | ARRAY_SIZE(cs42l73_mono_mix_texts), |
351 | cs42l73_mono_mix_texts, | 351 | cs42l73_mono_mix_texts, |
352 | cs42l73_mono_mix_values); | 352 | cs42l73_mono_mix_values); |
@@ -357,19 +357,19 @@ static const struct snd_kcontrol_new esl_xsp_mixer = | |||
357 | static const char * const cs42l73_ip_swap_text[] = { | 357 | static const char * const cs42l73_ip_swap_text[] = { |
358 | "Stereo", "Mono A", "Mono B", "Swap A-B"}; | 358 | "Stereo", "Mono A", "Mono B", "Swap A-B"}; |
359 | 359 | ||
360 | static const struct soc_enum ip_swap_enum = | 360 | static SOC_ENUM_SINGLE_DECL(ip_swap_enum, |
361 | SOC_ENUM_SINGLE(CS42L73_MIOPC, 6, | 361 | CS42L73_MIOPC, 6, |
362 | ARRAY_SIZE(cs42l73_ip_swap_text), cs42l73_ip_swap_text); | 362 | cs42l73_ip_swap_text); |
363 | 363 | ||
364 | static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"}; | 364 | static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"}; |
365 | 365 | ||
366 | static const struct soc_enum vsp_output_mux_enum = | 366 | static SOC_ENUM_SINGLE_DECL(vsp_output_mux_enum, |
367 | SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 5, | 367 | CS42L73_MIXERCTL, 5, |
368 | ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text); | 368 | cs42l73_spo_mixer_text); |
369 | 369 | ||
370 | static const struct soc_enum xsp_output_mux_enum = | 370 | static SOC_ENUM_SINGLE_DECL(xsp_output_mux_enum, |
371 | SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 4, | 371 | CS42L73_MIXERCTL, 4, |
372 | ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text); | 372 | cs42l73_spo_mixer_text); |
373 | 373 | ||
374 | static const struct snd_kcontrol_new vsp_output_mux = | 374 | static const struct snd_kcontrol_new vsp_output_mux = |
375 | SOC_DAPM_ENUM("Route", vsp_output_mux_enum); | 375 | SOC_DAPM_ENUM("Route", vsp_output_mux_enum); |
@@ -1108,7 +1108,7 @@ static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | |||
1108 | return 0; | 1108 | return 0; |
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | static u32 cs42l73_asrc_rates[] = { | 1111 | static const unsigned int cs42l73_asrc_rates[] = { |
1112 | 8000, 11025, 12000, 16000, 22050, | 1112 | 8000, 11025, 12000, 16000, 22050, |
1113 | 24000, 32000, 44100, 48000 | 1113 | 24000, 32000, 44100, 48000 |
1114 | }; | 1114 | }; |
@@ -1241,7 +1241,7 @@ static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate) | |||
1241 | 0x7F, tristate << 7); | 1241 | 0x7F, tristate << 7); |
1242 | } | 1242 | } |
1243 | 1243 | ||
1244 | static struct snd_pcm_hw_constraint_list constraints_12_24 = { | 1244 | static const struct snd_pcm_hw_constraint_list constraints_12_24 = { |
1245 | .count = ARRAY_SIZE(cs42l73_asrc_rates), | 1245 | .count = ARRAY_SIZE(cs42l73_asrc_rates), |
1246 | .list = cs42l73_asrc_rates, | 1246 | .list = cs42l73_asrc_rates, |
1247 | }; | 1247 | }; |
@@ -1255,9 +1255,6 @@ static int cs42l73_pcm_startup(struct snd_pcm_substream *substream, | |||
1255 | return 0; | 1255 | return 0; |
1256 | } | 1256 | } |
1257 | 1257 | ||
1258 | /* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */ | ||
1259 | #define CS42L73_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT) | ||
1260 | |||
1261 | 1258 | ||
1262 | #define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 1259 | #define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
1263 | SNDRV_PCM_FMTBIT_S24_LE) | 1260 | SNDRV_PCM_FMTBIT_S24_LE) |
@@ -1278,14 +1275,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { | |||
1278 | .stream_name = "XSP Playback", | 1275 | .stream_name = "XSP Playback", |
1279 | .channels_min = 1, | 1276 | .channels_min = 1, |
1280 | .channels_max = 2, | 1277 | .channels_max = 2, |
1281 | .rates = CS42L73_RATES, | 1278 | .rates = SNDRV_PCM_RATE_KNOT, |
1282 | .formats = CS42L73_FORMATS, | 1279 | .formats = CS42L73_FORMATS, |
1283 | }, | 1280 | }, |
1284 | .capture = { | 1281 | .capture = { |
1285 | .stream_name = "XSP Capture", | 1282 | .stream_name = "XSP Capture", |
1286 | .channels_min = 1, | 1283 | .channels_min = 1, |
1287 | .channels_max = 2, | 1284 | .channels_max = 2, |
1288 | .rates = CS42L73_RATES, | 1285 | .rates = SNDRV_PCM_RATE_KNOT, |
1289 | .formats = CS42L73_FORMATS, | 1286 | .formats = CS42L73_FORMATS, |
1290 | }, | 1287 | }, |
1291 | .ops = &cs42l73_ops, | 1288 | .ops = &cs42l73_ops, |
@@ -1298,14 +1295,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { | |||
1298 | .stream_name = "ASP Playback", | 1295 | .stream_name = "ASP Playback", |
1299 | .channels_min = 2, | 1296 | .channels_min = 2, |
1300 | .channels_max = 2, | 1297 | .channels_max = 2, |
1301 | .rates = CS42L73_RATES, | 1298 | .rates = SNDRV_PCM_RATE_KNOT, |
1302 | .formats = CS42L73_FORMATS, | 1299 | .formats = CS42L73_FORMATS, |
1303 | }, | 1300 | }, |
1304 | .capture = { | 1301 | .capture = { |
1305 | .stream_name = "ASP Capture", | 1302 | .stream_name = "ASP Capture", |
1306 | .channels_min = 2, | 1303 | .channels_min = 2, |
1307 | .channels_max = 2, | 1304 | .channels_max = 2, |
1308 | .rates = CS42L73_RATES, | 1305 | .rates = SNDRV_PCM_RATE_KNOT, |
1309 | .formats = CS42L73_FORMATS, | 1306 | .formats = CS42L73_FORMATS, |
1310 | }, | 1307 | }, |
1311 | .ops = &cs42l73_ops, | 1308 | .ops = &cs42l73_ops, |
@@ -1318,14 +1315,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { | |||
1318 | .stream_name = "VSP Playback", | 1315 | .stream_name = "VSP Playback", |
1319 | .channels_min = 1, | 1316 | .channels_min = 1, |
1320 | .channels_max = 2, | 1317 | .channels_max = 2, |
1321 | .rates = CS42L73_RATES, | 1318 | .rates = SNDRV_PCM_RATE_KNOT, |
1322 | .formats = CS42L73_FORMATS, | 1319 | .formats = CS42L73_FORMATS, |
1323 | }, | 1320 | }, |
1324 | .capture = { | 1321 | .capture = { |
1325 | .stream_name = "VSP Capture", | 1322 | .stream_name = "VSP Capture", |
1326 | .channels_min = 1, | 1323 | .channels_min = 1, |
1327 | .channels_max = 2, | 1324 | .channels_max = 2, |
1328 | .rates = CS42L73_RATES, | 1325 | .rates = SNDRV_PCM_RATE_KNOT, |
1329 | .formats = CS42L73_FORMATS, | 1326 | .formats = CS42L73_FORMATS, |
1330 | }, | 1327 | }, |
1331 | .ops = &cs42l73_ops, | 1328 | .ops = &cs42l73_ops, |
@@ -1348,17 +1345,8 @@ static int cs42l73_resume(struct snd_soc_codec *codec) | |||
1348 | 1345 | ||
1349 | static int cs42l73_probe(struct snd_soc_codec *codec) | 1346 | static int cs42l73_probe(struct snd_soc_codec *codec) |
1350 | { | 1347 | { |
1351 | int ret; | ||
1352 | struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec); | 1348 | struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec); |
1353 | 1349 | ||
1354 | codec->control_data = cs42l73->regmap; | ||
1355 | |||
1356 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
1357 | if (ret < 0) { | ||
1358 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1359 | return ret; | ||
1360 | } | ||
1361 | |||
1362 | cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1350 | cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1363 | 1351 | ||
1364 | /* Set Charge Pump Frequency */ | 1352 | /* Set Charge Pump Frequency */ |
@@ -1371,7 +1359,7 @@ static int cs42l73_probe(struct snd_soc_codec *codec) | |||
1371 | cs42l73->mclksel = CS42L73_CLKID_MCLK1; | 1359 | cs42l73->mclksel = CS42L73_CLKID_MCLK1; |
1372 | cs42l73->mclk = 0; | 1360 | cs42l73->mclk = 0; |
1373 | 1361 | ||
1374 | return ret; | 1362 | return 0; |
1375 | } | 1363 | } |
1376 | 1364 | ||
1377 | static int cs42l73_remove(struct snd_soc_codec *codec) | 1365 | static int cs42l73_remove(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c new file mode 100644 index 000000000000..657dce27eade --- /dev/null +++ b/sound/soc/codecs/cs42xx8-i2c.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Cirrus Logic CS42448/CS42888 Audio CODEC DAI I2C driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Author: Nicolin Chen <Guangyu.Chen@freescale.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of any | ||
10 | * kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/pm_runtime.h> | ||
16 | #include <sound/soc.h> | ||
17 | |||
18 | #include "cs42xx8.h" | ||
19 | |||
20 | static int cs42xx8_i2c_probe(struct i2c_client *i2c, | ||
21 | const struct i2c_device_id *id) | ||
22 | { | ||
23 | u32 ret = cs42xx8_probe(&i2c->dev, | ||
24 | devm_regmap_init_i2c(i2c, &cs42xx8_regmap_config)); | ||
25 | if (ret) | ||
26 | return ret; | ||
27 | |||
28 | pm_runtime_enable(&i2c->dev); | ||
29 | pm_request_idle(&i2c->dev); | ||
30 | |||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | static int cs42xx8_i2c_remove(struct i2c_client *i2c) | ||
35 | { | ||
36 | snd_soc_unregister_codec(&i2c->dev); | ||
37 | pm_runtime_disable(&i2c->dev); | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static struct i2c_device_id cs42xx8_i2c_id[] = { | ||
43 | {"cs42448", (kernel_ulong_t)&cs42448_data}, | ||
44 | {"cs42888", (kernel_ulong_t)&cs42888_data}, | ||
45 | {} | ||
46 | }; | ||
47 | MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id); | ||
48 | |||
49 | static struct i2c_driver cs42xx8_i2c_driver = { | ||
50 | .driver = { | ||
51 | .name = "cs42xx8", | ||
52 | .owner = THIS_MODULE, | ||
53 | .pm = &cs42xx8_pm, | ||
54 | }, | ||
55 | .probe = cs42xx8_i2c_probe, | ||
56 | .remove = cs42xx8_i2c_remove, | ||
57 | .id_table = cs42xx8_i2c_id, | ||
58 | }; | ||
59 | |||
60 | module_i2c_driver(cs42xx8_i2c_driver); | ||
61 | |||
62 | MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec I2C Driver"); | ||
63 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
64 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c new file mode 100644 index 000000000000..082299a4e2fa --- /dev/null +++ b/sound/soc/codecs/cs42xx8.c | |||
@@ -0,0 +1,602 @@ | |||
1 | /* | ||
2 | * Cirrus Logic CS42448/CS42888 Audio CODEC Digital Audio Interface (DAI) driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Author: Nicolin Chen <Guangyu.Chen@freescale.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of any | ||
10 | * kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/of_device.h> | ||
17 | #include <linux/pm_runtime.h> | ||
18 | #include <linux/regulator/consumer.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include <sound/tlv.h> | ||
22 | |||
23 | #include "cs42xx8.h" | ||
24 | |||
25 | #define CS42XX8_NUM_SUPPLIES 4 | ||
26 | static const char *const cs42xx8_supply_names[CS42XX8_NUM_SUPPLIES] = { | ||
27 | "VA", | ||
28 | "VD", | ||
29 | "VLS", | ||
30 | "VLC", | ||
31 | }; | ||
32 | |||
33 | #define CS42XX8_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
34 | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
35 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
36 | SNDRV_PCM_FMTBIT_S32_LE) | ||
37 | |||
38 | /* codec private data */ | ||
39 | struct cs42xx8_priv { | ||
40 | struct regulator_bulk_data supplies[CS42XX8_NUM_SUPPLIES]; | ||
41 | const struct cs42xx8_driver_data *drvdata; | ||
42 | struct regmap *regmap; | ||
43 | struct clk *clk; | ||
44 | |||
45 | bool slave_mode; | ||
46 | unsigned long sysclk; | ||
47 | }; | ||
48 | |||
49 | /* -127.5dB to 0dB with step of 0.5dB */ | ||
50 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); | ||
51 | /* -64dB to 24dB with step of 0.5dB */ | ||
52 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -6400, 50, 0); | ||
53 | |||
54 | static const char *const cs42xx8_adc_single[] = { "Differential", "Single-Ended" }; | ||
55 | static const char *const cs42xx8_szc[] = { "Immediate Change", "Zero Cross", | ||
56 | "Soft Ramp", "Soft Ramp on Zero Cross" }; | ||
57 | |||
58 | static const struct soc_enum adc1_single_enum = | ||
59 | SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 4, 2, cs42xx8_adc_single); | ||
60 | static const struct soc_enum adc2_single_enum = | ||
61 | SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 3, 2, cs42xx8_adc_single); | ||
62 | static const struct soc_enum adc3_single_enum = | ||
63 | SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 2, 2, cs42xx8_adc_single); | ||
64 | static const struct soc_enum dac_szc_enum = | ||
65 | SOC_ENUM_SINGLE(CS42XX8_TXCTL, 5, 4, cs42xx8_szc); | ||
66 | static const struct soc_enum adc_szc_enum = | ||
67 | SOC_ENUM_SINGLE(CS42XX8_TXCTL, 0, 4, cs42xx8_szc); | ||
68 | |||
69 | static const struct snd_kcontrol_new cs42xx8_snd_controls[] = { | ||
70 | SOC_DOUBLE_R_TLV("DAC1 Playback Volume", CS42XX8_VOLAOUT1, | ||
71 | CS42XX8_VOLAOUT2, 0, 0xff, 1, dac_tlv), | ||
72 | SOC_DOUBLE_R_TLV("DAC2 Playback Volume", CS42XX8_VOLAOUT3, | ||
73 | CS42XX8_VOLAOUT4, 0, 0xff, 1, dac_tlv), | ||
74 | SOC_DOUBLE_R_TLV("DAC3 Playback Volume", CS42XX8_VOLAOUT5, | ||
75 | CS42XX8_VOLAOUT6, 0, 0xff, 1, dac_tlv), | ||
76 | SOC_DOUBLE_R_TLV("DAC4 Playback Volume", CS42XX8_VOLAOUT7, | ||
77 | CS42XX8_VOLAOUT8, 0, 0xff, 1, dac_tlv), | ||
78 | SOC_DOUBLE_R_S_TLV("ADC1 Capture Volume", CS42XX8_VOLAIN1, | ||
79 | CS42XX8_VOLAIN2, 0, -0x80, 0x30, 7, 0, adc_tlv), | ||
80 | SOC_DOUBLE_R_S_TLV("ADC2 Capture Volume", CS42XX8_VOLAIN3, | ||
81 | CS42XX8_VOLAIN4, 0, -0x80, 0x30, 7, 0, adc_tlv), | ||
82 | SOC_DOUBLE("DAC1 Invert Switch", CS42XX8_DACINV, 0, 1, 1, 0), | ||
83 | SOC_DOUBLE("DAC2 Invert Switch", CS42XX8_DACINV, 2, 3, 1, 0), | ||
84 | SOC_DOUBLE("DAC3 Invert Switch", CS42XX8_DACINV, 4, 5, 1, 0), | ||
85 | SOC_DOUBLE("DAC4 Invert Switch", CS42XX8_DACINV, 6, 7, 1, 0), | ||
86 | SOC_DOUBLE("ADC1 Invert Switch", CS42XX8_ADCINV, 0, 1, 1, 0), | ||
87 | SOC_DOUBLE("ADC2 Invert Switch", CS42XX8_ADCINV, 2, 3, 1, 0), | ||
88 | SOC_SINGLE("ADC High-Pass Filter Switch", CS42XX8_ADCCTL, 7, 1, 1), | ||
89 | SOC_SINGLE("DAC De-emphasis Switch", CS42XX8_ADCCTL, 5, 1, 0), | ||
90 | SOC_ENUM("ADC1 Single Ended Mode Switch", adc1_single_enum), | ||
91 | SOC_ENUM("ADC2 Single Ended Mode Switch", adc2_single_enum), | ||
92 | SOC_SINGLE("DAC Single Volume Control Switch", CS42XX8_TXCTL, 7, 1, 0), | ||
93 | SOC_ENUM("DAC Soft Ramp & Zero Cross Control Switch", dac_szc_enum), | ||
94 | SOC_SINGLE("DAC Auto Mute Switch", CS42XX8_TXCTL, 4, 1, 0), | ||
95 | SOC_SINGLE("Mute ADC Serial Port Switch", CS42XX8_TXCTL, 3, 1, 0), | ||
96 | SOC_SINGLE("ADC Single Volume Control Switch", CS42XX8_TXCTL, 2, 1, 0), | ||
97 | SOC_ENUM("ADC Soft Ramp & Zero Cross Control Switch", adc_szc_enum), | ||
98 | }; | ||
99 | |||
100 | static const struct snd_kcontrol_new cs42xx8_adc3_snd_controls[] = { | ||
101 | SOC_DOUBLE_R_S_TLV("ADC3 Capture Volume", CS42XX8_VOLAIN5, | ||
102 | CS42XX8_VOLAIN6, 0, -0x80, 0x30, 7, 0, adc_tlv), | ||
103 | SOC_DOUBLE("ADC3 Invert Switch", CS42XX8_ADCINV, 4, 5, 1, 0), | ||
104 | SOC_ENUM("ADC3 Single Ended Mode Switch", adc3_single_enum), | ||
105 | }; | ||
106 | |||
107 | static const struct snd_soc_dapm_widget cs42xx8_dapm_widgets[] = { | ||
108 | SND_SOC_DAPM_DAC("DAC1", "Playback", CS42XX8_PWRCTL, 1, 1), | ||
109 | SND_SOC_DAPM_DAC("DAC2", "Playback", CS42XX8_PWRCTL, 2, 1), | ||
110 | SND_SOC_DAPM_DAC("DAC3", "Playback", CS42XX8_PWRCTL, 3, 1), | ||
111 | SND_SOC_DAPM_DAC("DAC4", "Playback", CS42XX8_PWRCTL, 4, 1), | ||
112 | |||
113 | SND_SOC_DAPM_OUTPUT("AOUT1L"), | ||
114 | SND_SOC_DAPM_OUTPUT("AOUT1R"), | ||
115 | SND_SOC_DAPM_OUTPUT("AOUT2L"), | ||
116 | SND_SOC_DAPM_OUTPUT("AOUT2R"), | ||
117 | SND_SOC_DAPM_OUTPUT("AOUT3L"), | ||
118 | SND_SOC_DAPM_OUTPUT("AOUT3R"), | ||
119 | SND_SOC_DAPM_OUTPUT("AOUT4L"), | ||
120 | SND_SOC_DAPM_OUTPUT("AOUT4R"), | ||
121 | |||
122 | SND_SOC_DAPM_ADC("ADC1", "Capture", CS42XX8_PWRCTL, 5, 1), | ||
123 | SND_SOC_DAPM_ADC("ADC2", "Capture", CS42XX8_PWRCTL, 6, 1), | ||
124 | |||
125 | SND_SOC_DAPM_INPUT("AIN1L"), | ||
126 | SND_SOC_DAPM_INPUT("AIN1R"), | ||
127 | SND_SOC_DAPM_INPUT("AIN2L"), | ||
128 | SND_SOC_DAPM_INPUT("AIN2R"), | ||
129 | |||
130 | SND_SOC_DAPM_SUPPLY("PWR", CS42XX8_PWRCTL, 0, 1, NULL, 0), | ||
131 | }; | ||
132 | |||
133 | static const struct snd_soc_dapm_widget cs42xx8_adc3_dapm_widgets[] = { | ||
134 | SND_SOC_DAPM_ADC("ADC3", "Capture", CS42XX8_PWRCTL, 7, 1), | ||
135 | |||
136 | SND_SOC_DAPM_INPUT("AIN3L"), | ||
137 | SND_SOC_DAPM_INPUT("AIN3R"), | ||
138 | }; | ||
139 | |||
140 | static const struct snd_soc_dapm_route cs42xx8_dapm_routes[] = { | ||
141 | /* Playback */ | ||
142 | { "AOUT1L", NULL, "DAC1" }, | ||
143 | { "AOUT1R", NULL, "DAC1" }, | ||
144 | { "DAC1", NULL, "PWR" }, | ||
145 | |||
146 | { "AOUT2L", NULL, "DAC2" }, | ||
147 | { "AOUT2R", NULL, "DAC2" }, | ||
148 | { "DAC2", NULL, "PWR" }, | ||
149 | |||
150 | { "AOUT3L", NULL, "DAC3" }, | ||
151 | { "AOUT3R", NULL, "DAC3" }, | ||
152 | { "DAC3", NULL, "PWR" }, | ||
153 | |||
154 | { "AOUT4L", NULL, "DAC4" }, | ||
155 | { "AOUT4R", NULL, "DAC4" }, | ||
156 | { "DAC4", NULL, "PWR" }, | ||
157 | |||
158 | /* Capture */ | ||
159 | { "ADC1", NULL, "AIN1L" }, | ||
160 | { "ADC1", NULL, "AIN1R" }, | ||
161 | { "ADC1", NULL, "PWR" }, | ||
162 | |||
163 | { "ADC2", NULL, "AIN2L" }, | ||
164 | { "ADC2", NULL, "AIN2R" }, | ||
165 | { "ADC2", NULL, "PWR" }, | ||
166 | }; | ||
167 | |||
168 | static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = { | ||
169 | /* Capture */ | ||
170 | { "ADC3", NULL, "AIN3L" }, | ||
171 | { "ADC3", NULL, "AIN3R" }, | ||
172 | { "ADC3", NULL, "PWR" }, | ||
173 | }; | ||
174 | |||
175 | struct cs42xx8_ratios { | ||
176 | unsigned int ratio; | ||
177 | unsigned char speed; | ||
178 | unsigned char mclk; | ||
179 | }; | ||
180 | |||
181 | static const struct cs42xx8_ratios cs42xx8_ratios[] = { | ||
182 | { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) }, | ||
183 | { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) }, | ||
184 | { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) }, | ||
185 | { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) }, | ||
186 | { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) }, | ||
187 | { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) }, | ||
188 | { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) }, | ||
189 | { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) }, | ||
190 | { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) } | ||
191 | }; | ||
192 | |||
193 | static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
194 | int clk_id, unsigned int freq, int dir) | ||
195 | { | ||
196 | struct snd_soc_codec *codec = codec_dai->codec; | ||
197 | struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); | ||
198 | |||
199 | cs42xx8->sysclk = freq; | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
205 | unsigned int format) | ||
206 | { | ||
207 | struct snd_soc_codec *codec = codec_dai->codec; | ||
208 | struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); | ||
209 | u32 val; | ||
210 | |||
211 | /* Set DAI format */ | ||
212 | switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
213 | case SND_SOC_DAIFMT_LEFT_J: | ||
214 | val = CS42XX8_INTF_DAC_DIF_LEFTJ | CS42XX8_INTF_ADC_DIF_LEFTJ; | ||
215 | break; | ||
216 | case SND_SOC_DAIFMT_I2S: | ||
217 | val = CS42XX8_INTF_DAC_DIF_I2S | CS42XX8_INTF_ADC_DIF_I2S; | ||
218 | break; | ||
219 | case SND_SOC_DAIFMT_RIGHT_J: | ||
220 | val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ; | ||
221 | break; | ||
222 | default: | ||
223 | dev_err(codec->dev, "unsupported dai format\n"); | ||
224 | return -EINVAL; | ||
225 | } | ||
226 | |||
227 | regmap_update_bits(cs42xx8->regmap, CS42XX8_INTF, | ||
228 | CS42XX8_INTF_DAC_DIF_MASK | | ||
229 | CS42XX8_INTF_ADC_DIF_MASK, val); | ||
230 | |||
231 | /* Set master/slave audio interface */ | ||
232 | switch (format & SND_SOC_DAIFMT_MASTER_MASK) { | ||
233 | case SND_SOC_DAIFMT_CBS_CFS: | ||
234 | cs42xx8->slave_mode = true; | ||
235 | break; | ||
236 | case SND_SOC_DAIFMT_CBM_CFM: | ||
237 | cs42xx8->slave_mode = false; | ||
238 | break; | ||
239 | default: | ||
240 | dev_err(codec->dev, "unsupported master/slave mode\n"); | ||
241 | return -EINVAL; | ||
242 | } | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static int cs42xx8_hw_params(struct snd_pcm_substream *substream, | ||
248 | struct snd_pcm_hw_params *params, | ||
249 | struct snd_soc_dai *dai) | ||
250 | { | ||
251 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
252 | struct snd_soc_codec *codec = rtd->codec; | ||
253 | struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); | ||
254 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
255 | u32 ratio = cs42xx8->sysclk / params_rate(params); | ||
256 | u32 i, fm, val, mask; | ||
257 | |||
258 | for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) { | ||
259 | if (cs42xx8_ratios[i].ratio == ratio) | ||
260 | break; | ||
261 | } | ||
262 | |||
263 | if (i == ARRAY_SIZE(cs42xx8_ratios)) { | ||
264 | dev_err(codec->dev, "unsupported sysclk ratio\n"); | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | |||
268 | mask = CS42XX8_FUNCMOD_MFREQ_MASK; | ||
269 | val = cs42xx8_ratios[i].mclk; | ||
270 | |||
271 | fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed; | ||
272 | |||
273 | regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, | ||
274 | CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask, | ||
275 | CS42XX8_FUNCMOD_xC_FM(tx, fm) | val); | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute) | ||
281 | { | ||
282 | struct snd_soc_codec *codec = dai->codec; | ||
283 | struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); | ||
284 | |||
285 | regmap_update_bits(cs42xx8->regmap, CS42XX8_DACMUTE, | ||
286 | CS42XX8_DACMUTE_ALL, mute ? CS42XX8_DACMUTE_ALL : 0); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static const struct snd_soc_dai_ops cs42xx8_dai_ops = { | ||
292 | .set_fmt = cs42xx8_set_dai_fmt, | ||
293 | .set_sysclk = cs42xx8_set_dai_sysclk, | ||
294 | .hw_params = cs42xx8_hw_params, | ||
295 | .digital_mute = cs42xx8_digital_mute, | ||
296 | }; | ||
297 | |||
298 | static struct snd_soc_dai_driver cs42xx8_dai = { | ||
299 | .playback = { | ||
300 | .stream_name = "Playback", | ||
301 | .channels_min = 1, | ||
302 | .channels_max = 8, | ||
303 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
304 | .formats = CS42XX8_FORMATS, | ||
305 | }, | ||
306 | .capture = { | ||
307 | .stream_name = "Capture", | ||
308 | .channels_min = 1, | ||
309 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
310 | .formats = CS42XX8_FORMATS, | ||
311 | }, | ||
312 | .ops = &cs42xx8_dai_ops, | ||
313 | }; | ||
314 | |||
315 | static const struct reg_default cs42xx8_reg[] = { | ||
316 | { 0x01, 0x01 }, /* Chip I.D. and Revision Register */ | ||
317 | { 0x02, 0x00 }, /* Power Control */ | ||
318 | { 0x03, 0xF0 }, /* Functional Mode */ | ||
319 | { 0x04, 0x46 }, /* Interface Formats */ | ||
320 | { 0x05, 0x00 }, /* ADC Control & DAC De-Emphasis */ | ||
321 | { 0x06, 0x10 }, /* Transition Control */ | ||
322 | { 0x07, 0x00 }, /* DAC Channel Mute */ | ||
323 | { 0x08, 0x00 }, /* Volume Control AOUT1 */ | ||
324 | { 0x09, 0x00 }, /* Volume Control AOUT2 */ | ||
325 | { 0x0a, 0x00 }, /* Volume Control AOUT3 */ | ||
326 | { 0x0b, 0x00 }, /* Volume Control AOUT4 */ | ||
327 | { 0x0c, 0x00 }, /* Volume Control AOUT5 */ | ||
328 | { 0x0d, 0x00 }, /* Volume Control AOUT6 */ | ||
329 | { 0x0e, 0x00 }, /* Volume Control AOUT7 */ | ||
330 | { 0x0f, 0x00 }, /* Volume Control AOUT8 */ | ||
331 | { 0x10, 0x00 }, /* DAC Channel Invert */ | ||
332 | { 0x11, 0x00 }, /* Volume Control AIN1 */ | ||
333 | { 0x12, 0x00 }, /* Volume Control AIN2 */ | ||
334 | { 0x13, 0x00 }, /* Volume Control AIN3 */ | ||
335 | { 0x14, 0x00 }, /* Volume Control AIN4 */ | ||
336 | { 0x15, 0x00 }, /* Volume Control AIN5 */ | ||
337 | { 0x16, 0x00 }, /* Volume Control AIN6 */ | ||
338 | { 0x17, 0x00 }, /* ADC Channel Invert */ | ||
339 | { 0x18, 0x00 }, /* Status Control */ | ||
340 | { 0x1a, 0x00 }, /* Status Mask */ | ||
341 | { 0x1b, 0x00 }, /* MUTEC Pin Control */ | ||
342 | }; | ||
343 | |||
344 | static bool cs42xx8_volatile_register(struct device *dev, unsigned int reg) | ||
345 | { | ||
346 | switch (reg) { | ||
347 | case CS42XX8_STATUS: | ||
348 | return true; | ||
349 | default: | ||
350 | return false; | ||
351 | } | ||
352 | } | ||
353 | |||
354 | static bool cs42xx8_writeable_register(struct device *dev, unsigned int reg) | ||
355 | { | ||
356 | switch (reg) { | ||
357 | case CS42XX8_CHIPID: | ||
358 | case CS42XX8_STATUS: | ||
359 | return false; | ||
360 | default: | ||
361 | return true; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | const struct regmap_config cs42xx8_regmap_config = { | ||
366 | .reg_bits = 8, | ||
367 | .val_bits = 8, | ||
368 | |||
369 | .max_register = CS42XX8_LASTREG, | ||
370 | .reg_defaults = cs42xx8_reg, | ||
371 | .num_reg_defaults = ARRAY_SIZE(cs42xx8_reg), | ||
372 | .volatile_reg = cs42xx8_volatile_register, | ||
373 | .writeable_reg = cs42xx8_writeable_register, | ||
374 | .cache_type = REGCACHE_RBTREE, | ||
375 | }; | ||
376 | EXPORT_SYMBOL_GPL(cs42xx8_regmap_config); | ||
377 | |||
378 | static int cs42xx8_codec_probe(struct snd_soc_codec *codec) | ||
379 | { | ||
380 | struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); | ||
381 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
382 | |||
383 | switch (cs42xx8->drvdata->num_adcs) { | ||
384 | case 3: | ||
385 | snd_soc_add_codec_controls(codec, cs42xx8_adc3_snd_controls, | ||
386 | ARRAY_SIZE(cs42xx8_adc3_snd_controls)); | ||
387 | snd_soc_dapm_new_controls(dapm, cs42xx8_adc3_dapm_widgets, | ||
388 | ARRAY_SIZE(cs42xx8_adc3_dapm_widgets)); | ||
389 | snd_soc_dapm_add_routes(dapm, cs42xx8_adc3_dapm_routes, | ||
390 | ARRAY_SIZE(cs42xx8_adc3_dapm_routes)); | ||
391 | break; | ||
392 | default: | ||
393 | break; | ||
394 | } | ||
395 | |||
396 | /* Mute all DAC channels */ | ||
397 | regmap_write(cs42xx8->regmap, CS42XX8_DACMUTE, CS42XX8_DACMUTE_ALL); | ||
398 | |||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static const struct snd_soc_codec_driver cs42xx8_driver = { | ||
403 | .probe = cs42xx8_codec_probe, | ||
404 | .idle_bias_off = true, | ||
405 | |||
406 | .controls = cs42xx8_snd_controls, | ||
407 | .num_controls = ARRAY_SIZE(cs42xx8_snd_controls), | ||
408 | .dapm_widgets = cs42xx8_dapm_widgets, | ||
409 | .num_dapm_widgets = ARRAY_SIZE(cs42xx8_dapm_widgets), | ||
410 | .dapm_routes = cs42xx8_dapm_routes, | ||
411 | .num_dapm_routes = ARRAY_SIZE(cs42xx8_dapm_routes), | ||
412 | }; | ||
413 | |||
414 | const struct cs42xx8_driver_data cs42448_data = { | ||
415 | .name = "cs42448", | ||
416 | .num_adcs = 3, | ||
417 | }; | ||
418 | EXPORT_SYMBOL_GPL(cs42448_data); | ||
419 | |||
420 | const struct cs42xx8_driver_data cs42888_data = { | ||
421 | .name = "cs42888", | ||
422 | .num_adcs = 2, | ||
423 | }; | ||
424 | EXPORT_SYMBOL_GPL(cs42888_data); | ||
425 | |||
426 | const struct of_device_id cs42xx8_of_match[] = { | ||
427 | { .compatible = "cirrus,cs42448", .data = &cs42448_data, }, | ||
428 | { .compatible = "cirrus,cs42888", .data = &cs42888_data, }, | ||
429 | { /* sentinel */ } | ||
430 | }; | ||
431 | MODULE_DEVICE_TABLE(of, cs42xx8_of_match); | ||
432 | EXPORT_SYMBOL_GPL(cs42xx8_of_match); | ||
433 | |||
434 | int cs42xx8_probe(struct device *dev, struct regmap *regmap) | ||
435 | { | ||
436 | const struct of_device_id *of_id = of_match_device(cs42xx8_of_match, dev); | ||
437 | struct cs42xx8_priv *cs42xx8; | ||
438 | int ret, val, i; | ||
439 | |||
440 | cs42xx8 = devm_kzalloc(dev, sizeof(*cs42xx8), GFP_KERNEL); | ||
441 | if (cs42xx8 == NULL) | ||
442 | return -ENOMEM; | ||
443 | |||
444 | dev_set_drvdata(dev, cs42xx8); | ||
445 | |||
446 | if (of_id) | ||
447 | cs42xx8->drvdata = of_id->data; | ||
448 | |||
449 | if (!cs42xx8->drvdata) { | ||
450 | dev_err(dev, "failed to find driver data\n"); | ||
451 | return -EINVAL; | ||
452 | } | ||
453 | |||
454 | cs42xx8->clk = devm_clk_get(dev, "mclk"); | ||
455 | if (IS_ERR(cs42xx8->clk)) { | ||
456 | dev_err(dev, "failed to get the clock: %ld\n", | ||
457 | PTR_ERR(cs42xx8->clk)); | ||
458 | return -EINVAL; | ||
459 | } | ||
460 | |||
461 | cs42xx8->sysclk = clk_get_rate(cs42xx8->clk); | ||
462 | |||
463 | for (i = 0; i < ARRAY_SIZE(cs42xx8->supplies); i++) | ||
464 | cs42xx8->supplies[i].supply = cs42xx8_supply_names[i]; | ||
465 | |||
466 | ret = devm_regulator_bulk_get(dev, | ||
467 | ARRAY_SIZE(cs42xx8->supplies), cs42xx8->supplies); | ||
468 | if (ret) { | ||
469 | dev_err(dev, "failed to request supplies: %d\n", ret); | ||
470 | return ret; | ||
471 | } | ||
472 | |||
473 | ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies), | ||
474 | cs42xx8->supplies); | ||
475 | if (ret) { | ||
476 | dev_err(dev, "failed to enable supplies: %d\n", ret); | ||
477 | return ret; | ||
478 | } | ||
479 | |||
480 | /* Make sure hardware reset done */ | ||
481 | msleep(5); | ||
482 | |||
483 | cs42xx8->regmap = regmap; | ||
484 | if (IS_ERR(cs42xx8->regmap)) { | ||
485 | ret = PTR_ERR(cs42xx8->regmap); | ||
486 | dev_err(dev, "failed to allocate regmap: %d\n", ret); | ||
487 | goto err_enable; | ||
488 | } | ||
489 | |||
490 | /* | ||
491 | * We haven't marked the chip revision as volatile due to | ||
492 | * sharing a register with the right input volume; explicitly | ||
493 | * bypass the cache to read it. | ||
494 | */ | ||
495 | regcache_cache_bypass(cs42xx8->regmap, true); | ||
496 | |||
497 | /* Validate the chip ID */ | ||
498 | regmap_read(cs42xx8->regmap, CS42XX8_CHIPID, &val); | ||
499 | if (val < 0) { | ||
500 | dev_err(dev, "failed to get device ID: %x", val); | ||
501 | ret = -EINVAL; | ||
502 | goto err_enable; | ||
503 | } | ||
504 | |||
505 | /* The top four bits of the chip ID should be 0000 */ | ||
506 | if ((val & CS42XX8_CHIPID_CHIP_ID_MASK) != 0x00) { | ||
507 | dev_err(dev, "unmatched chip ID: %d\n", | ||
508 | val & CS42XX8_CHIPID_CHIP_ID_MASK); | ||
509 | ret = -EINVAL; | ||
510 | goto err_enable; | ||
511 | } | ||
512 | |||
513 | dev_info(dev, "found device, revision %X\n", | ||
514 | val & CS42XX8_CHIPID_REV_ID_MASK); | ||
515 | |||
516 | regcache_cache_bypass(cs42xx8->regmap, false); | ||
517 | |||
518 | cs42xx8_dai.name = cs42xx8->drvdata->name; | ||
519 | |||
520 | /* Each adc supports stereo input */ | ||
521 | cs42xx8_dai.capture.channels_max = cs42xx8->drvdata->num_adcs * 2; | ||
522 | |||
523 | ret = snd_soc_register_codec(dev, &cs42xx8_driver, &cs42xx8_dai, 1); | ||
524 | if (ret) { | ||
525 | dev_err(dev, "failed to register codec:%d\n", ret); | ||
526 | goto err_enable; | ||
527 | } | ||
528 | |||
529 | regcache_cache_only(cs42xx8->regmap, true); | ||
530 | |||
531 | err_enable: | ||
532 | regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), | ||
533 | cs42xx8->supplies); | ||
534 | |||
535 | return ret; | ||
536 | } | ||
537 | EXPORT_SYMBOL_GPL(cs42xx8_probe); | ||
538 | |||
539 | #ifdef CONFIG_PM_RUNTIME | ||
540 | static int cs42xx8_runtime_resume(struct device *dev) | ||
541 | { | ||
542 | struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev); | ||
543 | int ret; | ||
544 | |||
545 | ret = clk_prepare_enable(cs42xx8->clk); | ||
546 | if (ret) { | ||
547 | dev_err(dev, "failed to enable mclk: %d\n", ret); | ||
548 | return ret; | ||
549 | } | ||
550 | |||
551 | ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies), | ||
552 | cs42xx8->supplies); | ||
553 | if (ret) { | ||
554 | dev_err(dev, "failed to enable supplies: %d\n", ret); | ||
555 | goto err_clk; | ||
556 | } | ||
557 | |||
558 | /* Make sure hardware reset done */ | ||
559 | msleep(5); | ||
560 | |||
561 | regcache_cache_only(cs42xx8->regmap, false); | ||
562 | |||
563 | ret = regcache_sync(cs42xx8->regmap); | ||
564 | if (ret) { | ||
565 | dev_err(dev, "failed to sync regmap: %d\n", ret); | ||
566 | goto err_bulk; | ||
567 | } | ||
568 | |||
569 | return 0; | ||
570 | |||
571 | err_bulk: | ||
572 | regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), | ||
573 | cs42xx8->supplies); | ||
574 | err_clk: | ||
575 | clk_disable_unprepare(cs42xx8->clk); | ||
576 | |||
577 | return ret; | ||
578 | } | ||
579 | |||
580 | static int cs42xx8_runtime_suspend(struct device *dev) | ||
581 | { | ||
582 | struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev); | ||
583 | |||
584 | regcache_cache_only(cs42xx8->regmap, true); | ||
585 | |||
586 | regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), | ||
587 | cs42xx8->supplies); | ||
588 | |||
589 | clk_disable_unprepare(cs42xx8->clk); | ||
590 | |||
591 | return 0; | ||
592 | } | ||
593 | #endif | ||
594 | |||
595 | const struct dev_pm_ops cs42xx8_pm = { | ||
596 | SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL) | ||
597 | }; | ||
598 | EXPORT_SYMBOL_GPL(cs42xx8_pm); | ||
599 | |||
600 | MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec Driver"); | ||
601 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
602 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/cs42xx8.h b/sound/soc/codecs/cs42xx8.h new file mode 100644 index 000000000000..da0b94aee419 --- /dev/null +++ b/sound/soc/codecs/cs42xx8.h | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * cs42xx8.h - Cirrus Logic CS42448/CS42888 Audio CODEC driver header file | ||
3 | * | ||
4 | * Copyright (C) 2014 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Author: Nicolin Chen <Guangyu.Chen@freescale.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of any | ||
10 | * kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #ifndef _CS42XX8_H | ||
14 | #define _CS42XX8_H | ||
15 | |||
16 | struct cs42xx8_driver_data { | ||
17 | char name[32]; | ||
18 | int num_adcs; | ||
19 | }; | ||
20 | |||
21 | extern const struct dev_pm_ops cs42xx8_pm; | ||
22 | extern const struct cs42xx8_driver_data cs42448_data; | ||
23 | extern const struct cs42xx8_driver_data cs42888_data; | ||
24 | extern const struct regmap_config cs42xx8_regmap_config; | ||
25 | int cs42xx8_probe(struct device *dev, struct regmap *regmap); | ||
26 | |||
27 | /* CS42888 register map */ | ||
28 | #define CS42XX8_CHIPID 0x01 /* Chip ID */ | ||
29 | #define CS42XX8_PWRCTL 0x02 /* Power Control */ | ||
30 | #define CS42XX8_FUNCMOD 0x03 /* Functional Mode */ | ||
31 | #define CS42XX8_INTF 0x04 /* Interface Formats */ | ||
32 | #define CS42XX8_ADCCTL 0x05 /* ADC Control */ | ||
33 | #define CS42XX8_TXCTL 0x06 /* Transition Control */ | ||
34 | #define CS42XX8_DACMUTE 0x07 /* DAC Mute Control */ | ||
35 | #define CS42XX8_VOLAOUT1 0x08 /* Volume Control AOUT1 */ | ||
36 | #define CS42XX8_VOLAOUT2 0x09 /* Volume Control AOUT2 */ | ||
37 | #define CS42XX8_VOLAOUT3 0x0A /* Volume Control AOUT3 */ | ||
38 | #define CS42XX8_VOLAOUT4 0x0B /* Volume Control AOUT4 */ | ||
39 | #define CS42XX8_VOLAOUT5 0x0C /* Volume Control AOUT5 */ | ||
40 | #define CS42XX8_VOLAOUT6 0x0D /* Volume Control AOUT6 */ | ||
41 | #define CS42XX8_VOLAOUT7 0x0E /* Volume Control AOUT7 */ | ||
42 | #define CS42XX8_VOLAOUT8 0x0F /* Volume Control AOUT8 */ | ||
43 | #define CS42XX8_DACINV 0x10 /* DAC Channel Invert */ | ||
44 | #define CS42XX8_VOLAIN1 0x11 /* Volume Control AIN1 */ | ||
45 | #define CS42XX8_VOLAIN2 0x12 /* Volume Control AIN2 */ | ||
46 | #define CS42XX8_VOLAIN3 0x13 /* Volume Control AIN3 */ | ||
47 | #define CS42XX8_VOLAIN4 0x14 /* Volume Control AIN4 */ | ||
48 | #define CS42XX8_VOLAIN5 0x15 /* Volume Control AIN5 */ | ||
49 | #define CS42XX8_VOLAIN6 0x16 /* Volume Control AIN6 */ | ||
50 | #define CS42XX8_ADCINV 0x17 /* ADC Channel Invert */ | ||
51 | #define CS42XX8_STATUSCTL 0x18 /* Status Control */ | ||
52 | #define CS42XX8_STATUS 0x19 /* Status */ | ||
53 | #define CS42XX8_STATUSM 0x1A /* Status Mask */ | ||
54 | #define CS42XX8_MUTEC 0x1B /* MUTEC Pin Control */ | ||
55 | |||
56 | #define CS42XX8_FIRSTREG CS42XX8_CHIPID | ||
57 | #define CS42XX8_LASTREG CS42XX8_MUTEC | ||
58 | #define CS42XX8_NUMREGS (CS42XX8_LASTREG - CS42XX8_FIRSTREG + 1) | ||
59 | #define CS42XX8_I2C_INCR 0x80 | ||
60 | |||
61 | /* Chip I.D. and Revision Register (Address 01h) */ | ||
62 | #define CS42XX8_CHIPID_CHIP_ID_MASK 0xF0 | ||
63 | #define CS42XX8_CHIPID_REV_ID_MASK 0x0F | ||
64 | |||
65 | /* Power Control (Address 02h) */ | ||
66 | #define CS42XX8_PWRCTL_PDN_ADC3_SHIFT 7 | ||
67 | #define CS42XX8_PWRCTL_PDN_ADC3_MASK (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT) | ||
68 | #define CS42XX8_PWRCTL_PDN_ADC3 (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT) | ||
69 | #define CS42XX8_PWRCTL_PDN_ADC2_SHIFT 6 | ||
70 | #define CS42XX8_PWRCTL_PDN_ADC2_MASK (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT) | ||
71 | #define CS42XX8_PWRCTL_PDN_ADC2 (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT) | ||
72 | #define CS42XX8_PWRCTL_PDN_ADC1_SHIFT 5 | ||
73 | #define CS42XX8_PWRCTL_PDN_ADC1_MASK (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT) | ||
74 | #define CS42XX8_PWRCTL_PDN_ADC1 (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT) | ||
75 | #define CS42XX8_PWRCTL_PDN_DAC4_SHIFT 4 | ||
76 | #define CS42XX8_PWRCTL_PDN_DAC4_MASK (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT) | ||
77 | #define CS42XX8_PWRCTL_PDN_DAC4 (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT) | ||
78 | #define CS42XX8_PWRCTL_PDN_DAC3_SHIFT 3 | ||
79 | #define CS42XX8_PWRCTL_PDN_DAC3_MASK (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT) | ||
80 | #define CS42XX8_PWRCTL_PDN_DAC3 (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT) | ||
81 | #define CS42XX8_PWRCTL_PDN_DAC2_SHIFT 2 | ||
82 | #define CS42XX8_PWRCTL_PDN_DAC2_MASK (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT) | ||
83 | #define CS42XX8_PWRCTL_PDN_DAC2 (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT) | ||
84 | #define CS42XX8_PWRCTL_PDN_DAC1_SHIFT 1 | ||
85 | #define CS42XX8_PWRCTL_PDN_DAC1_MASK (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT) | ||
86 | #define CS42XX8_PWRCTL_PDN_DAC1 (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT) | ||
87 | #define CS42XX8_PWRCTL_PDN_SHIFT 0 | ||
88 | #define CS42XX8_PWRCTL_PDN_MASK (1 << CS42XX8_PWRCTL_PDN_SHIFT) | ||
89 | #define CS42XX8_PWRCTL_PDN (1 << CS42XX8_PWRCTL_PDN_SHIFT) | ||
90 | |||
91 | /* Functional Mode (Address 03h) */ | ||
92 | #define CS42XX8_FUNCMOD_DAC_FM_SHIFT 6 | ||
93 | #define CS42XX8_FUNCMOD_DAC_FM_WIDTH 2 | ||
94 | #define CS42XX8_FUNCMOD_DAC_FM_MASK (((1 << CS42XX8_FUNCMOD_DAC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_DAC_FM_SHIFT) | ||
95 | #define CS42XX8_FUNCMOD_DAC_FM(v) ((v) << CS42XX8_FUNCMOD_DAC_FM_SHIFT) | ||
96 | #define CS42XX8_FUNCMOD_ADC_FM_SHIFT 4 | ||
97 | #define CS42XX8_FUNCMOD_ADC_FM_WIDTH 2 | ||
98 | #define CS42XX8_FUNCMOD_ADC_FM_MASK (((1 << CS42XX8_FUNCMOD_ADC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_ADC_FM_SHIFT) | ||
99 | #define CS42XX8_FUNCMOD_ADC_FM(v) ((v) << CS42XX8_FUNCMOD_ADC_FM_SHIFT) | ||
100 | #define CS42XX8_FUNCMOD_xC_FM_MASK(x) ((x) ? CS42XX8_FUNCMOD_DAC_FM_MASK : CS42XX8_FUNCMOD_ADC_FM_MASK) | ||
101 | #define CS42XX8_FUNCMOD_xC_FM(x, v) ((x) ? CS42XX8_FUNCMOD_DAC_FM(v) : CS42XX8_FUNCMOD_ADC_FM(v)) | ||
102 | #define CS42XX8_FUNCMOD_MFREQ_SHIFT 1 | ||
103 | #define CS42XX8_FUNCMOD_MFREQ_WIDTH 3 | ||
104 | #define CS42XX8_FUNCMOD_MFREQ_MASK (((1 << CS42XX8_FUNCMOD_MFREQ_WIDTH) - 1) << CS42XX8_FUNCMOD_MFREQ_SHIFT) | ||
105 | #define CS42XX8_FUNCMOD_MFREQ_256(s) ((0 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) | ||
106 | #define CS42XX8_FUNCMOD_MFREQ_384(s) ((1 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) | ||
107 | #define CS42XX8_FUNCMOD_MFREQ_512(s) ((2 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) | ||
108 | #define CS42XX8_FUNCMOD_MFREQ_768(s) ((3 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) | ||
109 | #define CS42XX8_FUNCMOD_MFREQ_1024(s) ((4 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) | ||
110 | |||
111 | #define CS42XX8_FM_SINGLE 0 | ||
112 | #define CS42XX8_FM_DOUBLE 1 | ||
113 | #define CS42XX8_FM_QUAD 2 | ||
114 | #define CS42XX8_FM_AUTO 3 | ||
115 | |||
116 | /* Interface Formats (Address 04h) */ | ||
117 | #define CS42XX8_INTF_FREEZE_SHIFT 7 | ||
118 | #define CS42XX8_INTF_FREEZE_MASK (1 << CS42XX8_INTF_FREEZE_SHIFT) | ||
119 | #define CS42XX8_INTF_FREEZE (1 << CS42XX8_INTF_FREEZE_SHIFT) | ||
120 | #define CS42XX8_INTF_AUX_DIF_SHIFT 6 | ||
121 | #define CS42XX8_INTF_AUX_DIF_MASK (1 << CS42XX8_INTF_AUX_DIF_SHIFT) | ||
122 | #define CS42XX8_INTF_AUX_DIF (1 << CS42XX8_INTF_AUX_DIF_SHIFT) | ||
123 | #define CS42XX8_INTF_DAC_DIF_SHIFT 3 | ||
124 | #define CS42XX8_INTF_DAC_DIF_WIDTH 3 | ||
125 | #define CS42XX8_INTF_DAC_DIF_MASK (((1 << CS42XX8_INTF_DAC_DIF_WIDTH) - 1) << CS42XX8_INTF_DAC_DIF_SHIFT) | ||
126 | #define CS42XX8_INTF_DAC_DIF_LEFTJ (0 << CS42XX8_INTF_DAC_DIF_SHIFT) | ||
127 | #define CS42XX8_INTF_DAC_DIF_I2S (1 << CS42XX8_INTF_DAC_DIF_SHIFT) | ||
128 | #define CS42XX8_INTF_DAC_DIF_RIGHTJ (2 << CS42XX8_INTF_DAC_DIF_SHIFT) | ||
129 | #define CS42XX8_INTF_DAC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_DAC_DIF_SHIFT) | ||
130 | #define CS42XX8_INTF_DAC_DIF_ONELINE_20 (4 << CS42XX8_INTF_DAC_DIF_SHIFT) | ||
131 | #define CS42XX8_INTF_DAC_DIF_ONELINE_24 (6 << CS42XX8_INTF_DAC_DIF_SHIFT) | ||
132 | #define CS42XX8_INTF_DAC_DIF_TDM (7 << CS42XX8_INTF_DAC_DIF_SHIFT) | ||
133 | #define CS42XX8_INTF_ADC_DIF_SHIFT 0 | ||
134 | #define CS42XX8_INTF_ADC_DIF_WIDTH 3 | ||
135 | #define CS42XX8_INTF_ADC_DIF_MASK (((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT) | ||
136 | #define CS42XX8_INTF_ADC_DIF_LEFTJ (0 << CS42XX8_INTF_ADC_DIF_SHIFT) | ||
137 | #define CS42XX8_INTF_ADC_DIF_I2S (1 << CS42XX8_INTF_ADC_DIF_SHIFT) | ||
138 | #define CS42XX8_INTF_ADC_DIF_RIGHTJ (2 << CS42XX8_INTF_ADC_DIF_SHIFT) | ||
139 | #define CS42XX8_INTF_ADC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_ADC_DIF_SHIFT) | ||
140 | #define CS42XX8_INTF_ADC_DIF_ONELINE_20 (4 << CS42XX8_INTF_ADC_DIF_SHIFT) | ||
141 | #define CS42XX8_INTF_ADC_DIF_ONELINE_24 (6 << CS42XX8_INTF_ADC_DIF_SHIFT) | ||
142 | #define CS42XX8_INTF_ADC_DIF_TDM (7 << CS42XX8_INTF_ADC_DIF_SHIFT) | ||
143 | |||
144 | /* ADC Control & DAC De-Emphasis (Address 05h) */ | ||
145 | #define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT 7 | ||
146 | #define CS42XX8_ADCCTL_ADC_HPF_FREEZE_MASK (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT) | ||
147 | #define CS42XX8_ADCCTL_ADC_HPF_FREEZE (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT) | ||
148 | #define CS42XX8_ADCCTL_DAC_DEM_SHIFT 5 | ||
149 | #define CS42XX8_ADCCTL_DAC_DEM_MASK (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT) | ||
150 | #define CS42XX8_ADCCTL_DAC_DEM (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT) | ||
151 | #define CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT 4 | ||
152 | #define CS42XX8_ADCCTL_ADC1_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT) | ||
153 | #define CS42XX8_ADCCTL_ADC1_SINGLE (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT) | ||
154 | #define CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT 3 | ||
155 | #define CS42XX8_ADCCTL_ADC2_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT) | ||
156 | #define CS42XX8_ADCCTL_ADC2_SINGLE (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT) | ||
157 | #define CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT 2 | ||
158 | #define CS42XX8_ADCCTL_ADC3_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT) | ||
159 | #define CS42XX8_ADCCTL_ADC3_SINGLE (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT) | ||
160 | #define CS42XX8_ADCCTL_AIN5_MUX_SHIFT 1 | ||
161 | #define CS42XX8_ADCCTL_AIN5_MUX_MASK (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT) | ||
162 | #define CS42XX8_ADCCTL_AIN5_MUX (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT) | ||
163 | #define CS42XX8_ADCCTL_AIN6_MUX_SHIFT 0 | ||
164 | #define CS42XX8_ADCCTL_AIN6_MUX_MASK (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT) | ||
165 | #define CS42XX8_ADCCTL_AIN6_MUX (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT) | ||
166 | |||
167 | /* Transition Control (Address 06h) */ | ||
168 | #define CS42XX8_TXCTL_DAC_SNGVOL_SHIFT 7 | ||
169 | #define CS42XX8_TXCTL_DAC_SNGVOL_MASK (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT) | ||
170 | #define CS42XX8_TXCTL_DAC_SNGVOL (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT) | ||
171 | #define CS42XX8_TXCTL_DAC_SZC_SHIFT 5 | ||
172 | #define CS42XX8_TXCTL_DAC_SZC_WIDTH 2 | ||
173 | #define CS42XX8_TXCTL_DAC_SZC_MASK (((1 << CS42XX8_TXCTL_DAC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_DAC_SZC_SHIFT) | ||
174 | #define CS42XX8_TXCTL_DAC_SZC_IC (0 << CS42XX8_TXCTL_DAC_SZC_SHIFT) | ||
175 | #define CS42XX8_TXCTL_DAC_SZC_ZC (1 << CS42XX8_TXCTL_DAC_SZC_SHIFT) | ||
176 | #define CS42XX8_TXCTL_DAC_SZC_SR (2 << CS42XX8_TXCTL_DAC_SZC_SHIFT) | ||
177 | #define CS42XX8_TXCTL_DAC_SZC_SRZC (3 << CS42XX8_TXCTL_DAC_SZC_SHIFT) | ||
178 | #define CS42XX8_TXCTL_AMUTE_SHIFT 4 | ||
179 | #define CS42XX8_TXCTL_AMUTE_MASK (1 << CS42XX8_TXCTL_AMUTE_SHIFT) | ||
180 | #define CS42XX8_TXCTL_AMUTE (1 << CS42XX8_TXCTL_AMUTE_SHIFT) | ||
181 | #define CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT 3 | ||
182 | #define CS42XX8_TXCTL_MUTE_ADC_SP_MASK (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT) | ||
183 | #define CS42XX8_TXCTL_MUTE_ADC_SP (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT) | ||
184 | #define CS42XX8_TXCTL_ADC_SNGVOL_SHIFT 2 | ||
185 | #define CS42XX8_TXCTL_ADC_SNGVOL_MASK (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT) | ||
186 | #define CS42XX8_TXCTL_ADC_SNGVOL (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT) | ||
187 | #define CS42XX8_TXCTL_ADC_SZC_SHIFT 0 | ||
188 | #define CS42XX8_TXCTL_ADC_SZC_MASK (((1 << CS42XX8_TXCTL_ADC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_ADC_SZC_SHIFT) | ||
189 | #define CS42XX8_TXCTL_ADC_SZC_IC (0 << CS42XX8_TXCTL_ADC_SZC_SHIFT) | ||
190 | #define CS42XX8_TXCTL_ADC_SZC_ZC (1 << CS42XX8_TXCTL_ADC_SZC_SHIFT) | ||
191 | #define CS42XX8_TXCTL_ADC_SZC_SR (2 << CS42XX8_TXCTL_ADC_SZC_SHIFT) | ||
192 | #define CS42XX8_TXCTL_ADC_SZC_SRZC (3 << CS42XX8_TXCTL_ADC_SZC_SHIFT) | ||
193 | |||
194 | /* DAC Channel Mute (Address 07h) */ | ||
195 | #define CS42XX8_DACMUTE_AOUT(n) (0x1 << n) | ||
196 | #define CS42XX8_DACMUTE_ALL 0xff | ||
197 | |||
198 | /* Status Control (Address 18h)*/ | ||
199 | #define CS42XX8_STATUSCTL_INI_SHIFT 2 | ||
200 | #define CS42XX8_STATUSCTL_INI_WIDTH 2 | ||
201 | #define CS42XX8_STATUSCTL_INI_MASK (((1 << CS42XX8_STATUSCTL_INI_WIDTH) - 1) << CS42XX8_STATUSCTL_INI_SHIFT) | ||
202 | #define CS42XX8_STATUSCTL_INT_ACTIVE_HIGH (0 << CS42XX8_STATUSCTL_INI_SHIFT) | ||
203 | #define CS42XX8_STATUSCTL_INT_ACTIVE_LOW (1 << CS42XX8_STATUSCTL_INI_SHIFT) | ||
204 | #define CS42XX8_STATUSCTL_INT_OPEN_DRAIN (2 << CS42XX8_STATUSCTL_INI_SHIFT) | ||
205 | |||
206 | /* Status (Address 19h)*/ | ||
207 | #define CS42XX8_STATUS_DAC_CLK_ERR_SHIFT 4 | ||
208 | #define CS42XX8_STATUS_DAC_CLK_ERR_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_SHIFT) | ||
209 | #define CS42XX8_STATUS_ADC_CLK_ERR_SHIFT 3 | ||
210 | #define CS42XX8_STATUS_ADC_CLK_ERR_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_SHIFT) | ||
211 | #define CS42XX8_STATUS_ADC3_OVFL_SHIFT 2 | ||
212 | #define CS42XX8_STATUS_ADC3_OVFL_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_SHIFT) | ||
213 | #define CS42XX8_STATUS_ADC2_OVFL_SHIFT 1 | ||
214 | #define CS42XX8_STATUS_ADC2_OVFL_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_SHIFT) | ||
215 | #define CS42XX8_STATUS_ADC1_OVFL_SHIFT 0 | ||
216 | #define CS42XX8_STATUS_ADC1_OVFL_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_SHIFT) | ||
217 | |||
218 | /* Status Mask (Address 1Ah) */ | ||
219 | #define CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT 4 | ||
220 | #define CS42XX8_STATUS_DAC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT) | ||
221 | #define CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT 3 | ||
222 | #define CS42XX8_STATUS_ADC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT) | ||
223 | #define CS42XX8_STATUS_ADC3_OVFL_M_SHIFT 2 | ||
224 | #define CS42XX8_STATUS_ADC3_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_M_SHIFT) | ||
225 | #define CS42XX8_STATUS_ADC2_OVFL_M_SHIFT 1 | ||
226 | #define CS42XX8_STATUS_ADC2_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_M_SHIFT) | ||
227 | #define CS42XX8_STATUS_ADC1_OVFL_M_SHIFT 0 | ||
228 | #define CS42XX8_STATUS_ADC1_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_M_SHIFT) | ||
229 | |||
230 | /* MUTEC Pin Control (Address 1Bh) */ | ||
231 | #define CS42XX8_MUTEC_MCPOLARITY_SHIFT 1 | ||
232 | #define CS42XX8_MUTEC_MCPOLARITY_MASK (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) | ||
233 | #define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_LOW (0 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) | ||
234 | #define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_HIGH (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) | ||
235 | #define CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT 0 | ||
236 | #define CS42XX8_MUTEC_MUTEC_ACTIVE_MASK (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT) | ||
237 | #define CS42XX8_MUTEC_MUTEC_ACTIVE (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT) | ||
238 | #endif /* _CS42XX8_H */ | ||
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index e62e294a8033..137e8ebc092c 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c | |||
@@ -307,29 +307,29 @@ static const char * const da7210_hpf_cutoff_txt[] = { | |||
307 | "Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi" | 307 | "Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi" |
308 | }; | 308 | }; |
309 | 309 | ||
310 | static const struct soc_enum da7210_dac_hpf_cutoff = | 310 | static SOC_ENUM_SINGLE_DECL(da7210_dac_hpf_cutoff, |
311 | SOC_ENUM_SINGLE(DA7210_DAC_HPF, 0, 4, da7210_hpf_cutoff_txt); | 311 | DA7210_DAC_HPF, 0, da7210_hpf_cutoff_txt); |
312 | 312 | ||
313 | static const struct soc_enum da7210_adc_hpf_cutoff = | 313 | static SOC_ENUM_SINGLE_DECL(da7210_adc_hpf_cutoff, |
314 | SOC_ENUM_SINGLE(DA7210_ADC_HPF, 0, 4, da7210_hpf_cutoff_txt); | 314 | DA7210_ADC_HPF, 0, da7210_hpf_cutoff_txt); |
315 | 315 | ||
316 | /* ADC and DAC voice (8kHz) high pass cutoff value */ | 316 | /* ADC and DAC voice (8kHz) high pass cutoff value */ |
317 | static const char * const da7210_vf_cutoff_txt[] = { | 317 | static const char * const da7210_vf_cutoff_txt[] = { |
318 | "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" | 318 | "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" |
319 | }; | 319 | }; |
320 | 320 | ||
321 | static const struct soc_enum da7210_dac_vf_cutoff = | 321 | static SOC_ENUM_SINGLE_DECL(da7210_dac_vf_cutoff, |
322 | SOC_ENUM_SINGLE(DA7210_DAC_HPF, 4, 8, da7210_vf_cutoff_txt); | 322 | DA7210_DAC_HPF, 4, da7210_vf_cutoff_txt); |
323 | 323 | ||
324 | static const struct soc_enum da7210_adc_vf_cutoff = | 324 | static SOC_ENUM_SINGLE_DECL(da7210_adc_vf_cutoff, |
325 | SOC_ENUM_SINGLE(DA7210_ADC_HPF, 4, 8, da7210_vf_cutoff_txt); | 325 | DA7210_ADC_HPF, 4, da7210_vf_cutoff_txt); |
326 | 326 | ||
327 | static const char *da7210_hp_mode_txt[] = { | 327 | static const char *da7210_hp_mode_txt[] = { |
328 | "Class H", "Class G" | 328 | "Class H", "Class G" |
329 | }; | 329 | }; |
330 | 330 | ||
331 | static const struct soc_enum da7210_hp_mode_sel = | 331 | static SOC_ENUM_SINGLE_DECL(da7210_hp_mode_sel, |
332 | SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt); | 332 | DA7210_HP_CFG, 0, da7210_hp_mode_txt); |
333 | 333 | ||
334 | /* ALC can be enabled only if noise suppression is disabled */ | 334 | /* ALC can be enabled only if noise suppression is disabled */ |
335 | static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol, | 335 | static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol, |
@@ -1071,17 +1071,9 @@ static struct snd_soc_dai_driver da7210_dai = { | |||
1071 | static int da7210_probe(struct snd_soc_codec *codec) | 1071 | static int da7210_probe(struct snd_soc_codec *codec) |
1072 | { | 1072 | { |
1073 | struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec); | 1073 | struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec); |
1074 | int ret; | ||
1075 | 1074 | ||
1076 | dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); | 1075 | dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); |
1077 | 1076 | ||
1078 | codec->control_data = da7210->regmap; | ||
1079 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
1080 | if (ret < 0) { | ||
1081 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1082 | return ret; | ||
1083 | } | ||
1084 | |||
1085 | da7210->mclk_rate = 0; /* This will be set from set_sysclk() */ | 1077 | da7210->mclk_rate = 0; /* This will be set from set_sysclk() */ |
1086 | da7210->master = 0; /* This will be set from set_fmt() */ | 1078 | da7210->master = 0; /* This will be set from set_fmt() */ |
1087 | 1079 | ||
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 0c77e7ad7423..738fa18a50d2 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c | |||
@@ -63,30 +63,30 @@ static const char * const da7213_voice_hpf_corner_txt[] = { | |||
63 | "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" | 63 | "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" |
64 | }; | 64 | }; |
65 | 65 | ||
66 | static const struct soc_enum da7213_dac_voice_hpf_corner = | 66 | static SOC_ENUM_SINGLE_DECL(da7213_dac_voice_hpf_corner, |
67 | SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT, | 67 | DA7213_DAC_FILTERS1, |
68 | DA7213_VOICE_HPF_CORNER_MAX, | 68 | DA7213_VOICE_HPF_CORNER_SHIFT, |
69 | da7213_voice_hpf_corner_txt); | 69 | da7213_voice_hpf_corner_txt); |
70 | 70 | ||
71 | static const struct soc_enum da7213_adc_voice_hpf_corner = | 71 | static SOC_ENUM_SINGLE_DECL(da7213_adc_voice_hpf_corner, |
72 | SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT, | 72 | DA7213_ADC_FILTERS1, |
73 | DA7213_VOICE_HPF_CORNER_MAX, | 73 | DA7213_VOICE_HPF_CORNER_SHIFT, |
74 | da7213_voice_hpf_corner_txt); | 74 | da7213_voice_hpf_corner_txt); |
75 | 75 | ||
76 | /* ADC and DAC high pass filter cutoff value */ | 76 | /* ADC and DAC high pass filter cutoff value */ |
77 | static const char * const da7213_audio_hpf_corner_txt[] = { | 77 | static const char * const da7213_audio_hpf_corner_txt[] = { |
78 | "Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000" | 78 | "Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000" |
79 | }; | 79 | }; |
80 | 80 | ||
81 | static const struct soc_enum da7213_dac_audio_hpf_corner = | 81 | static SOC_ENUM_SINGLE_DECL(da7213_dac_audio_hpf_corner, |
82 | SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT, | 82 | DA7213_DAC_FILTERS1 |
83 | DA7213_AUDIO_HPF_CORNER_MAX, | 83 | , DA7213_AUDIO_HPF_CORNER_SHIFT, |
84 | da7213_audio_hpf_corner_txt); | 84 | da7213_audio_hpf_corner_txt); |
85 | 85 | ||
86 | static const struct soc_enum da7213_adc_audio_hpf_corner = | 86 | static SOC_ENUM_SINGLE_DECL(da7213_adc_audio_hpf_corner, |
87 | SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT, | 87 | DA7213_ADC_FILTERS1, |
88 | DA7213_AUDIO_HPF_CORNER_MAX, | 88 | DA7213_AUDIO_HPF_CORNER_SHIFT, |
89 | da7213_audio_hpf_corner_txt); | 89 | da7213_audio_hpf_corner_txt); |
90 | 90 | ||
91 | /* Gain ramping rate value */ | 91 | /* Gain ramping rate value */ |
92 | static const char * const da7213_gain_ramp_rate_txt[] = { | 92 | static const char * const da7213_gain_ramp_rate_txt[] = { |
@@ -94,52 +94,50 @@ static const char * const da7213_gain_ramp_rate_txt[] = { | |||
94 | "nominal rate / 32" | 94 | "nominal rate / 32" |
95 | }; | 95 | }; |
96 | 96 | ||
97 | static const struct soc_enum da7213_gain_ramp_rate = | 97 | static SOC_ENUM_SINGLE_DECL(da7213_gain_ramp_rate, |
98 | SOC_ENUM_SINGLE(DA7213_GAIN_RAMP_CTRL, DA7213_GAIN_RAMP_RATE_SHIFT, | 98 | DA7213_GAIN_RAMP_CTRL, |
99 | DA7213_GAIN_RAMP_RATE_MAX, da7213_gain_ramp_rate_txt); | 99 | DA7213_GAIN_RAMP_RATE_SHIFT, |
100 | da7213_gain_ramp_rate_txt); | ||
100 | 101 | ||
101 | /* DAC noise gate setup time value */ | 102 | /* DAC noise gate setup time value */ |
102 | static const char * const da7213_dac_ng_setup_time_txt[] = { | 103 | static const char * const da7213_dac_ng_setup_time_txt[] = { |
103 | "256 samples", "512 samples", "1024 samples", "2048 samples" | 104 | "256 samples", "512 samples", "1024 samples", "2048 samples" |
104 | }; | 105 | }; |
105 | 106 | ||
106 | static const struct soc_enum da7213_dac_ng_setup_time = | 107 | static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_setup_time, |
107 | SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME, | 108 | DA7213_DAC_NG_SETUP_TIME, |
108 | DA7213_DAC_NG_SETUP_TIME_SHIFT, | 109 | DA7213_DAC_NG_SETUP_TIME_SHIFT, |
109 | DA7213_DAC_NG_SETUP_TIME_MAX, | 110 | da7213_dac_ng_setup_time_txt); |
110 | da7213_dac_ng_setup_time_txt); | ||
111 | 111 | ||
112 | /* DAC noise gate rampup rate value */ | 112 | /* DAC noise gate rampup rate value */ |
113 | static const char * const da7213_dac_ng_rampup_txt[] = { | 113 | static const char * const da7213_dac_ng_rampup_txt[] = { |
114 | "0.02 ms/dB", "0.16 ms/dB" | 114 | "0.02 ms/dB", "0.16 ms/dB" |
115 | }; | 115 | }; |
116 | 116 | ||
117 | static const struct soc_enum da7213_dac_ng_rampup_rate = | 117 | static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampup_rate, |
118 | SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME, | 118 | DA7213_DAC_NG_SETUP_TIME, |
119 | DA7213_DAC_NG_RAMPUP_RATE_SHIFT, | 119 | DA7213_DAC_NG_RAMPUP_RATE_SHIFT, |
120 | DA7213_DAC_NG_RAMP_RATE_MAX, | 120 | da7213_dac_ng_rampup_txt); |
121 | da7213_dac_ng_rampup_txt); | ||
122 | 121 | ||
123 | /* DAC noise gate rampdown rate value */ | 122 | /* DAC noise gate rampdown rate value */ |
124 | static const char * const da7213_dac_ng_rampdown_txt[] = { | 123 | static const char * const da7213_dac_ng_rampdown_txt[] = { |
125 | "0.64 ms/dB", "20.48 ms/dB" | 124 | "0.64 ms/dB", "20.48 ms/dB" |
126 | }; | 125 | }; |
127 | 126 | ||
128 | static const struct soc_enum da7213_dac_ng_rampdown_rate = | 127 | static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampdown_rate, |
129 | SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME, | 128 | DA7213_DAC_NG_SETUP_TIME, |
130 | DA7213_DAC_NG_RAMPDN_RATE_SHIFT, | 129 | DA7213_DAC_NG_RAMPDN_RATE_SHIFT, |
131 | DA7213_DAC_NG_RAMP_RATE_MAX, | 130 | da7213_dac_ng_rampdown_txt); |
132 | da7213_dac_ng_rampdown_txt); | ||
133 | 131 | ||
134 | /* DAC soft mute rate value */ | 132 | /* DAC soft mute rate value */ |
135 | static const char * const da7213_dac_soft_mute_rate_txt[] = { | 133 | static const char * const da7213_dac_soft_mute_rate_txt[] = { |
136 | "1", "2", "4", "8", "16", "32", "64" | 134 | "1", "2", "4", "8", "16", "32", "64" |
137 | }; | 135 | }; |
138 | 136 | ||
139 | static const struct soc_enum da7213_dac_soft_mute_rate = | 137 | static SOC_ENUM_SINGLE_DECL(da7213_dac_soft_mute_rate, |
140 | SOC_ENUM_SINGLE(DA7213_DAC_FILTERS5, DA7213_DAC_SOFTMUTE_RATE_SHIFT, | 138 | DA7213_DAC_FILTERS5, |
141 | DA7213_DAC_SOFTMUTE_RATE_MAX, | 139 | DA7213_DAC_SOFTMUTE_RATE_SHIFT, |
142 | da7213_dac_soft_mute_rate_txt); | 140 | da7213_dac_soft_mute_rate_txt); |
143 | 141 | ||
144 | /* ALC Attack Rate select */ | 142 | /* ALC Attack Rate select */ |
145 | static const char * const da7213_alc_attack_rate_txt[] = { | 143 | static const char * const da7213_alc_attack_rate_txt[] = { |
@@ -147,9 +145,10 @@ static const char * const da7213_alc_attack_rate_txt[] = { | |||
147 | "5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" | 145 | "5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" |
148 | }; | 146 | }; |
149 | 147 | ||
150 | static const struct soc_enum da7213_alc_attack_rate = | 148 | static SOC_ENUM_SINGLE_DECL(da7213_alc_attack_rate, |
151 | SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_ATTACK_SHIFT, | 149 | DA7213_ALC_CTRL2, |
152 | DA7213_ALC_ATTACK_MAX, da7213_alc_attack_rate_txt); | 150 | DA7213_ALC_ATTACK_SHIFT, |
151 | da7213_alc_attack_rate_txt); | ||
153 | 152 | ||
154 | /* ALC Release Rate select */ | 153 | /* ALC Release Rate select */ |
155 | static const char * const da7213_alc_release_rate_txt[] = { | 154 | static const char * const da7213_alc_release_rate_txt[] = { |
@@ -157,9 +156,10 @@ static const char * const da7213_alc_release_rate_txt[] = { | |||
157 | "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" | 156 | "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" |
158 | }; | 157 | }; |
159 | 158 | ||
160 | static const struct soc_enum da7213_alc_release_rate = | 159 | static SOC_ENUM_SINGLE_DECL(da7213_alc_release_rate, |
161 | SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_RELEASE_SHIFT, | 160 | DA7213_ALC_CTRL2, |
162 | DA7213_ALC_RELEASE_MAX, da7213_alc_release_rate_txt); | 161 | DA7213_ALC_RELEASE_SHIFT, |
162 | da7213_alc_release_rate_txt); | ||
163 | 163 | ||
164 | /* ALC Hold Time select */ | 164 | /* ALC Hold Time select */ |
165 | static const char * const da7213_alc_hold_time_txt[] = { | 165 | static const char * const da7213_alc_hold_time_txt[] = { |
@@ -168,22 +168,25 @@ static const char * const da7213_alc_hold_time_txt[] = { | |||
168 | "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" | 168 | "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" |
169 | }; | 169 | }; |
170 | 170 | ||
171 | static const struct soc_enum da7213_alc_hold_time = | 171 | static SOC_ENUM_SINGLE_DECL(da7213_alc_hold_time, |
172 | SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_HOLD_SHIFT, | 172 | DA7213_ALC_CTRL3, |
173 | DA7213_ALC_HOLD_MAX, da7213_alc_hold_time_txt); | 173 | DA7213_ALC_HOLD_SHIFT, |
174 | da7213_alc_hold_time_txt); | ||
174 | 175 | ||
175 | /* ALC Input Signal Tracking rate select */ | 176 | /* ALC Input Signal Tracking rate select */ |
176 | static const char * const da7213_alc_integ_rate_txt[] = { | 177 | static const char * const da7213_alc_integ_rate_txt[] = { |
177 | "1/4", "1/16", "1/256", "1/65536" | 178 | "1/4", "1/16", "1/256", "1/65536" |
178 | }; | 179 | }; |
179 | 180 | ||
180 | static const struct soc_enum da7213_alc_integ_attack_rate = | 181 | static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_attack_rate, |
181 | SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_ATTACK_SHIFT, | 182 | DA7213_ALC_CTRL3, |
182 | DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt); | 183 | DA7213_ALC_INTEG_ATTACK_SHIFT, |
184 | da7213_alc_integ_rate_txt); | ||
183 | 185 | ||
184 | static const struct soc_enum da7213_alc_integ_release_rate = | 186 | static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_release_rate, |
185 | SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_RELEASE_SHIFT, | 187 | DA7213_ALC_CTRL3, |
186 | DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt); | 188 | DA7213_ALC_INTEG_RELEASE_SHIFT, |
189 | da7213_alc_integ_rate_txt); | ||
187 | 190 | ||
188 | 191 | ||
189 | /* | 192 | /* |
@@ -584,15 +587,17 @@ static const char * const da7213_mic_amp_in_sel_txt[] = { | |||
584 | "Differential", "MIC_P", "MIC_N" | 587 | "Differential", "MIC_P", "MIC_N" |
585 | }; | 588 | }; |
586 | 589 | ||
587 | static const struct soc_enum da7213_mic_1_amp_in_sel = | 590 | static SOC_ENUM_SINGLE_DECL(da7213_mic_1_amp_in_sel, |
588 | SOC_ENUM_SINGLE(DA7213_MIC_1_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT, | 591 | DA7213_MIC_1_CTRL, |
589 | DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt); | 592 | DA7213_MIC_AMP_IN_SEL_SHIFT, |
593 | da7213_mic_amp_in_sel_txt); | ||
590 | static const struct snd_kcontrol_new da7213_mic_1_amp_in_sel_mux = | 594 | static const struct snd_kcontrol_new da7213_mic_1_amp_in_sel_mux = |
591 | SOC_DAPM_ENUM("Mic 1 Amp Source MUX", da7213_mic_1_amp_in_sel); | 595 | SOC_DAPM_ENUM("Mic 1 Amp Source MUX", da7213_mic_1_amp_in_sel); |
592 | 596 | ||
593 | static const struct soc_enum da7213_mic_2_amp_in_sel = | 597 | static SOC_ENUM_SINGLE_DECL(da7213_mic_2_amp_in_sel, |
594 | SOC_ENUM_SINGLE(DA7213_MIC_2_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT, | 598 | DA7213_MIC_2_CTRL, |
595 | DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt); | 599 | DA7213_MIC_AMP_IN_SEL_SHIFT, |
600 | da7213_mic_amp_in_sel_txt); | ||
596 | static const struct snd_kcontrol_new da7213_mic_2_amp_in_sel_mux = | 601 | static const struct snd_kcontrol_new da7213_mic_2_amp_in_sel_mux = |
597 | SOC_DAPM_ENUM("Mic 2 Amp Source MUX", da7213_mic_2_amp_in_sel); | 602 | SOC_DAPM_ENUM("Mic 2 Amp Source MUX", da7213_mic_2_amp_in_sel); |
598 | 603 | ||
@@ -601,15 +606,17 @@ static const char * const da7213_dai_src_txt[] = { | |||
601 | "ADC Left", "ADC Right", "DAI Input Left", "DAI Input Right" | 606 | "ADC Left", "ADC Right", "DAI Input Left", "DAI Input Right" |
602 | }; | 607 | }; |
603 | 608 | ||
604 | static const struct soc_enum da7213_dai_l_src = | 609 | static SOC_ENUM_SINGLE_DECL(da7213_dai_l_src, |
605 | SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_L_SRC_SHIFT, | 610 | DA7213_DIG_ROUTING_DAI, |
606 | DA7213_DAI_SRC_MAX, da7213_dai_src_txt); | 611 | DA7213_DAI_L_SRC_SHIFT, |
612 | da7213_dai_src_txt); | ||
607 | static const struct snd_kcontrol_new da7213_dai_l_src_mux = | 613 | static const struct snd_kcontrol_new da7213_dai_l_src_mux = |
608 | SOC_DAPM_ENUM("DAI Left Source MUX", da7213_dai_l_src); | 614 | SOC_DAPM_ENUM("DAI Left Source MUX", da7213_dai_l_src); |
609 | 615 | ||
610 | static const struct soc_enum da7213_dai_r_src = | 616 | static SOC_ENUM_SINGLE_DECL(da7213_dai_r_src, |
611 | SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_R_SRC_SHIFT, | 617 | DA7213_DIG_ROUTING_DAI, |
612 | DA7213_DAI_SRC_MAX, da7213_dai_src_txt); | 618 | DA7213_DAI_R_SRC_SHIFT, |
619 | da7213_dai_src_txt); | ||
613 | static const struct snd_kcontrol_new da7213_dai_r_src_mux = | 620 | static const struct snd_kcontrol_new da7213_dai_r_src_mux = |
614 | SOC_DAPM_ENUM("DAI Right Source MUX", da7213_dai_r_src); | 621 | SOC_DAPM_ENUM("DAI Right Source MUX", da7213_dai_r_src); |
615 | 622 | ||
@@ -619,15 +626,17 @@ static const char * const da7213_dac_src_txt[] = { | |||
619 | "DAI Input Right" | 626 | "DAI Input Right" |
620 | }; | 627 | }; |
621 | 628 | ||
622 | static const struct soc_enum da7213_dac_l_src = | 629 | static SOC_ENUM_SINGLE_DECL(da7213_dac_l_src, |
623 | SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_L_SRC_SHIFT, | 630 | DA7213_DIG_ROUTING_DAC, |
624 | DA7213_DAC_SRC_MAX, da7213_dac_src_txt); | 631 | DA7213_DAC_L_SRC_SHIFT, |
632 | da7213_dac_src_txt); | ||
625 | static const struct snd_kcontrol_new da7213_dac_l_src_mux = | 633 | static const struct snd_kcontrol_new da7213_dac_l_src_mux = |
626 | SOC_DAPM_ENUM("DAC Left Source MUX", da7213_dac_l_src); | 634 | SOC_DAPM_ENUM("DAC Left Source MUX", da7213_dac_l_src); |
627 | 635 | ||
628 | static const struct soc_enum da7213_dac_r_src = | 636 | static SOC_ENUM_SINGLE_DECL(da7213_dac_r_src, |
629 | SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_R_SRC_SHIFT, | 637 | DA7213_DIG_ROUTING_DAC, |
630 | DA7213_DAC_SRC_MAX, da7213_dac_src_txt); | 638 | DA7213_DAC_R_SRC_SHIFT, |
639 | da7213_dac_src_txt); | ||
631 | static const struct snd_kcontrol_new da7213_dac_r_src_mux = | 640 | static const struct snd_kcontrol_new da7213_dac_r_src_mux = |
632 | SOC_DAPM_ENUM("DAC Right Source MUX", da7213_dac_r_src); | 641 | SOC_DAPM_ENUM("DAC Right Source MUX", da7213_dac_r_src); |
633 | 642 | ||
@@ -1384,17 +1393,9 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, | |||
1384 | 1393 | ||
1385 | static int da7213_probe(struct snd_soc_codec *codec) | 1394 | static int da7213_probe(struct snd_soc_codec *codec) |
1386 | { | 1395 | { |
1387 | int ret; | ||
1388 | struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec); | 1396 | struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec); |
1389 | struct da7213_platform_data *pdata = da7213->pdata; | 1397 | struct da7213_platform_data *pdata = da7213->pdata; |
1390 | 1398 | ||
1391 | codec->control_data = da7213->regmap; | ||
1392 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
1393 | if (ret < 0) { | ||
1394 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1395 | return ret; | ||
1396 | } | ||
1397 | |||
1398 | /* Default to using ALC auto offset calibration mode. */ | 1399 | /* Default to using ALC auto offset calibration mode. */ |
1399 | snd_soc_update_bits(codec, DA7213_ALC_CTRL1, | 1400 | snd_soc_update_bits(codec, DA7213_ALC_CTRL1, |
1400 | DA7213_ALC_CALIB_MODE_MAN, 0); | 1401 | DA7213_ALC_CALIB_MODE_MAN, 0); |
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index f295b6569910..7d168ec71cd7 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c | |||
@@ -269,81 +269,65 @@ static const char *da732x_hpf_voice[] = { | |||
269 | "150Hz", "200Hz", "300Hz", "400Hz" | 269 | "150Hz", "200Hz", "300Hz", "400Hz" |
270 | }; | 270 | }; |
271 | 271 | ||
272 | static const struct soc_enum da732x_dac1_hpf_mode_enum[] = { | 272 | static SOC_ENUM_SINGLE_DECL(da732x_dac1_hpf_mode_enum, |
273 | SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT, | 273 | DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT, |
274 | DA732X_HPF_MODE_MAX, da732x_hpf_mode) | 274 | da732x_hpf_mode); |
275 | }; | ||
276 | 275 | ||
277 | static const struct soc_enum da732x_dac2_hpf_mode_enum[] = { | 276 | static SOC_ENUM_SINGLE_DECL(da732x_dac2_hpf_mode_enum, |
278 | SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT, | 277 | DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT, |
279 | DA732X_HPF_MODE_MAX, da732x_hpf_mode) | 278 | da732x_hpf_mode); |
280 | }; | ||
281 | 279 | ||
282 | static const struct soc_enum da732x_dac3_hpf_mode_enum[] = { | 280 | static SOC_ENUM_SINGLE_DECL(da732x_dac3_hpf_mode_enum, |
283 | SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT, | 281 | DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT, |
284 | DA732X_HPF_MODE_MAX, da732x_hpf_mode) | 282 | da732x_hpf_mode); |
285 | }; | ||
286 | 283 | ||
287 | static const struct soc_enum da732x_adc1_hpf_mode_enum[] = { | 284 | static SOC_ENUM_SINGLE_DECL(da732x_adc1_hpf_mode_enum, |
288 | SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT, | 285 | DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT, |
289 | DA732X_HPF_MODE_MAX, da732x_hpf_mode) | 286 | da732x_hpf_mode); |
290 | }; | ||
291 | 287 | ||
292 | static const struct soc_enum da732x_adc2_hpf_mode_enum[] = { | 288 | static SOC_ENUM_SINGLE_DECL(da732x_adc2_hpf_mode_enum, |
293 | SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT, | 289 | DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT, |
294 | DA732X_HPF_MODE_MAX, da732x_hpf_mode) | 290 | da732x_hpf_mode); |
295 | }; | ||
296 | 291 | ||
297 | static const struct soc_enum da732x_dac1_hp_filter_enum[] = { | 292 | static SOC_ENUM_SINGLE_DECL(da732x_dac1_hp_filter_enum, |
298 | SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT, | 293 | DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT, |
299 | DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | 294 | da732x_hpf_music); |
300 | }; | ||
301 | 295 | ||
302 | static const struct soc_enum da732x_dac2_hp_filter_enum[] = { | 296 | static SOC_ENUM_SINGLE_DECL(da732x_dac2_hp_filter_enum, |
303 | SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT, | 297 | DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT, |
304 | DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | 298 | da732x_hpf_music); |
305 | }; | ||
306 | 299 | ||
307 | static const struct soc_enum da732x_dac3_hp_filter_enum[] = { | 300 | static SOC_ENUM_SINGLE_DECL(da732x_dac3_hp_filter_enum, |
308 | SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT, | 301 | DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT, |
309 | DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | 302 | da732x_hpf_music); |
310 | }; | ||
311 | 303 | ||
312 | static const struct soc_enum da732x_adc1_hp_filter_enum[] = { | 304 | static SOC_ENUM_SINGLE_DECL(da732x_adc1_hp_filter_enum, |
313 | SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT, | 305 | DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT, |
314 | DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | 306 | da732x_hpf_music); |
315 | }; | ||
316 | 307 | ||
317 | static const struct soc_enum da732x_adc2_hp_filter_enum[] = { | 308 | static SOC_ENUM_SINGLE_DECL(da732x_adc2_hp_filter_enum, |
318 | SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT, | 309 | DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT, |
319 | DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | 310 | da732x_hpf_music); |
320 | }; | ||
321 | 311 | ||
322 | static const struct soc_enum da732x_dac1_voice_filter_enum[] = { | 312 | static SOC_ENUM_SINGLE_DECL(da732x_dac1_voice_filter_enum, |
323 | SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT, | 313 | DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT, |
324 | DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | 314 | da732x_hpf_voice); |
325 | }; | ||
326 | 315 | ||
327 | static const struct soc_enum da732x_dac2_voice_filter_enum[] = { | 316 | static SOC_ENUM_SINGLE_DECL(da732x_dac2_voice_filter_enum, |
328 | SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT, | 317 | DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT, |
329 | DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | 318 | da732x_hpf_voice); |
330 | }; | ||
331 | 319 | ||
332 | static const struct soc_enum da732x_dac3_voice_filter_enum[] = { | 320 | static SOC_ENUM_SINGLE_DECL(da732x_dac3_voice_filter_enum, |
333 | SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT, | 321 | DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT, |
334 | DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | 322 | da732x_hpf_voice); |
335 | }; | ||
336 | 323 | ||
337 | static const struct soc_enum da732x_adc1_voice_filter_enum[] = { | 324 | static SOC_ENUM_SINGLE_DECL(da732x_adc1_voice_filter_enum, |
338 | SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT, | 325 | DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT, |
339 | DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | 326 | da732x_hpf_voice); |
340 | }; | ||
341 | |||
342 | static const struct soc_enum da732x_adc2_voice_filter_enum[] = { | ||
343 | SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT, | ||
344 | DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | ||
345 | }; | ||
346 | 327 | ||
328 | static SOC_ENUM_SINGLE_DECL(da732x_adc2_voice_filter_enum, | ||
329 | DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT, | ||
330 | da732x_hpf_voice); | ||
347 | 331 | ||
348 | static int da732x_hpf_set(struct snd_kcontrol *kcontrol, | 332 | static int da732x_hpf_set(struct snd_kcontrol *kcontrol, |
349 | struct snd_ctl_elem_value *ucontrol) | 333 | struct snd_ctl_elem_value *ucontrol) |
@@ -714,65 +698,65 @@ static const char *enable_text[] = { | |||
714 | }; | 698 | }; |
715 | 699 | ||
716 | /* ADC1LMUX */ | 700 | /* ADC1LMUX */ |
717 | static const struct soc_enum adc1l_enum = | 701 | static SOC_ENUM_SINGLE_DECL(adc1l_enum, |
718 | SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT, | 702 | DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT, |
719 | DA732X_ADCL_MUX_MAX, adcl_text); | 703 | adcl_text); |
720 | static const struct snd_kcontrol_new adc1l_mux = | 704 | static const struct snd_kcontrol_new adc1l_mux = |
721 | SOC_DAPM_ENUM("ADC Route", adc1l_enum); | 705 | SOC_DAPM_ENUM("ADC Route", adc1l_enum); |
722 | 706 | ||
723 | /* ADC1RMUX */ | 707 | /* ADC1RMUX */ |
724 | static const struct soc_enum adc1r_enum = | 708 | static SOC_ENUM_SINGLE_DECL(adc1r_enum, |
725 | SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT, | 709 | DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT, |
726 | DA732X_ADCR_MUX_MAX, adcr_text); | 710 | adcr_text); |
727 | static const struct snd_kcontrol_new adc1r_mux = | 711 | static const struct snd_kcontrol_new adc1r_mux = |
728 | SOC_DAPM_ENUM("ADC Route", adc1r_enum); | 712 | SOC_DAPM_ENUM("ADC Route", adc1r_enum); |
729 | 713 | ||
730 | /* ADC2LMUX */ | 714 | /* ADC2LMUX */ |
731 | static const struct soc_enum adc2l_enum = | 715 | static SOC_ENUM_SINGLE_DECL(adc2l_enum, |
732 | SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT, | 716 | DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT, |
733 | DA732X_ADCL_MUX_MAX, adcl_text); | 717 | adcl_text); |
734 | static const struct snd_kcontrol_new adc2l_mux = | 718 | static const struct snd_kcontrol_new adc2l_mux = |
735 | SOC_DAPM_ENUM("ADC Route", adc2l_enum); | 719 | SOC_DAPM_ENUM("ADC Route", adc2l_enum); |
736 | 720 | ||
737 | /* ADC2RMUX */ | 721 | /* ADC2RMUX */ |
738 | static const struct soc_enum adc2r_enum = | 722 | static SOC_ENUM_SINGLE_DECL(adc2r_enum, |
739 | SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT, | 723 | DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT, |
740 | DA732X_ADCR_MUX_MAX, adcr_text); | 724 | adcr_text); |
741 | 725 | ||
742 | static const struct snd_kcontrol_new adc2r_mux = | 726 | static const struct snd_kcontrol_new adc2r_mux = |
743 | SOC_DAPM_ENUM("ADC Route", adc2r_enum); | 727 | SOC_DAPM_ENUM("ADC Route", adc2r_enum); |
744 | 728 | ||
745 | static const struct soc_enum da732x_hp_left_output = | 729 | static SOC_ENUM_SINGLE_DECL(da732x_hp_left_output, |
746 | SOC_ENUM_SINGLE(DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT, | 730 | DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT, |
747 | DA732X_DAC_EN_MAX, enable_text); | 731 | enable_text); |
748 | 732 | ||
749 | static const struct snd_kcontrol_new hpl_mux = | 733 | static const struct snd_kcontrol_new hpl_mux = |
750 | SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output); | 734 | SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output); |
751 | 735 | ||
752 | static const struct soc_enum da732x_hp_right_output = | 736 | static SOC_ENUM_SINGLE_DECL(da732x_hp_right_output, |
753 | SOC_ENUM_SINGLE(DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT, | 737 | DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT, |
754 | DA732X_DAC_EN_MAX, enable_text); | 738 | enable_text); |
755 | 739 | ||
756 | static const struct snd_kcontrol_new hpr_mux = | 740 | static const struct snd_kcontrol_new hpr_mux = |
757 | SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output); | 741 | SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output); |
758 | 742 | ||
759 | static const struct soc_enum da732x_speaker_output = | 743 | static SOC_ENUM_SINGLE_DECL(da732x_speaker_output, |
760 | SOC_ENUM_SINGLE(DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT, | 744 | DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT, |
761 | DA732X_DAC_EN_MAX, enable_text); | 745 | enable_text); |
762 | 746 | ||
763 | static const struct snd_kcontrol_new spk_mux = | 747 | static const struct snd_kcontrol_new spk_mux = |
764 | SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output); | 748 | SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output); |
765 | 749 | ||
766 | static const struct soc_enum da732x_lout4_output = | 750 | static SOC_ENUM_SINGLE_DECL(da732x_lout4_output, |
767 | SOC_ENUM_SINGLE(DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT, | 751 | DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT, |
768 | DA732X_DAC_EN_MAX, enable_text); | 752 | enable_text); |
769 | 753 | ||
770 | static const struct snd_kcontrol_new lout4_mux = | 754 | static const struct snd_kcontrol_new lout4_mux = |
771 | SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output); | 755 | SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output); |
772 | 756 | ||
773 | static const struct soc_enum da732x_lout2_output = | 757 | static SOC_ENUM_SINGLE_DECL(da732x_lout2_output, |
774 | SOC_ENUM_SINGLE(DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT, | 758 | DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT, |
775 | DA732X_DAC_EN_MAX, enable_text); | 759 | enable_text); |
776 | 760 | ||
777 | static const struct snd_kcontrol_new lout2_mux = | 761 | static const struct snd_kcontrol_new lout2_mux = |
778 | SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output); | 762 | SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output); |
@@ -1268,11 +1252,23 @@ static struct snd_soc_dai_driver da732x_dai[] = { | |||
1268 | }, | 1252 | }, |
1269 | }; | 1253 | }; |
1270 | 1254 | ||
1255 | static bool da732x_volatile(struct device *dev, unsigned int reg) | ||
1256 | { | ||
1257 | switch (reg) { | ||
1258 | case DA732X_REG_HPL_DAC_OFF_CNTL: | ||
1259 | case DA732X_REG_HPR_DAC_OFF_CNTL: | ||
1260 | return true; | ||
1261 | default: | ||
1262 | return false; | ||
1263 | } | ||
1264 | } | ||
1265 | |||
1271 | static const struct regmap_config da732x_regmap = { | 1266 | static const struct regmap_config da732x_regmap = { |
1272 | .reg_bits = 8, | 1267 | .reg_bits = 8, |
1273 | .val_bits = 8, | 1268 | .val_bits = 8, |
1274 | 1269 | ||
1275 | .max_register = DA732X_MAX_REG, | 1270 | .max_register = DA732X_MAX_REG, |
1271 | .volatile_reg = da732x_volatile, | ||
1276 | .reg_defaults = da732x_reg_cache, | 1272 | .reg_defaults = da732x_reg_cache, |
1277 | .num_reg_defaults = ARRAY_SIZE(da732x_reg_cache), | 1273 | .num_reg_defaults = ARRAY_SIZE(da732x_reg_cache), |
1278 | .cache_type = REGCACHE_RBTREE, | 1274 | .cache_type = REGCACHE_RBTREE, |
@@ -1301,9 +1297,9 @@ static void da732x_dac_offset_adjust(struct snd_soc_codec *codec) | |||
1301 | msleep(DA732X_WAIT_FOR_STABILIZATION); | 1297 | msleep(DA732X_WAIT_FOR_STABILIZATION); |
1302 | 1298 | ||
1303 | /* Check DAC offset sign */ | 1299 | /* Check DAC offset sign */ |
1304 | sign[DA732X_HPL_DAC] = (codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & | 1300 | sign[DA732X_HPL_DAC] = (snd_soc_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & |
1305 | DA732X_HP_DAC_OFF_CNTL_COMPO); | 1301 | DA732X_HP_DAC_OFF_CNTL_COMPO); |
1306 | sign[DA732X_HPR_DAC] = (codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & | 1302 | sign[DA732X_HPR_DAC] = (snd_soc_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & |
1307 | DA732X_HP_DAC_OFF_CNTL_COMPO); | 1303 | DA732X_HP_DAC_OFF_CNTL_COMPO); |
1308 | 1304 | ||
1309 | /* Binary search DAC offset values (both channels at once) */ | 1305 | /* Binary search DAC offset values (both channels at once) */ |
@@ -1320,10 +1316,10 @@ static void da732x_dac_offset_adjust(struct snd_soc_codec *codec) | |||
1320 | 1316 | ||
1321 | msleep(DA732X_WAIT_FOR_STABILIZATION); | 1317 | msleep(DA732X_WAIT_FOR_STABILIZATION); |
1322 | 1318 | ||
1323 | if ((codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & | 1319 | if ((snd_soc_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & |
1324 | DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC]) | 1320 | DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC]) |
1325 | offset[DA732X_HPL_DAC] &= ~step; | 1321 | offset[DA732X_HPL_DAC] &= ~step; |
1326 | if ((codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & | 1322 | if ((snd_soc_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & |
1327 | DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC]) | 1323 | DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC]) |
1328 | offset[DA732X_HPR_DAC] &= ~step; | 1324 | offset[DA732X_HPR_DAC] &= ~step; |
1329 | 1325 | ||
@@ -1364,9 +1360,9 @@ static void da732x_output_offset_adjust(struct snd_soc_codec *codec) | |||
1364 | msleep(DA732X_WAIT_FOR_STABILIZATION); | 1360 | msleep(DA732X_WAIT_FOR_STABILIZATION); |
1365 | 1361 | ||
1366 | /* Check output offset sign */ | 1362 | /* Check output offset sign */ |
1367 | sign[DA732X_HPL_AMP] = codec->hw_read(codec, DA732X_REG_HPL) & | 1363 | sign[DA732X_HPL_AMP] = snd_soc_read(codec, DA732X_REG_HPL) & |
1368 | DA732X_HP_OUT_COMPO; | 1364 | DA732X_HP_OUT_COMPO; |
1369 | sign[DA732X_HPR_AMP] = codec->hw_read(codec, DA732X_REG_HPR) & | 1365 | sign[DA732X_HPR_AMP] = snd_soc_read(codec, DA732X_REG_HPR) & |
1370 | DA732X_HP_OUT_COMPO; | 1366 | DA732X_HP_OUT_COMPO; |
1371 | 1367 | ||
1372 | snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_COMP | | 1368 | snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_COMP | |
@@ -1387,10 +1383,10 @@ static void da732x_output_offset_adjust(struct snd_soc_codec *codec) | |||
1387 | 1383 | ||
1388 | msleep(DA732X_WAIT_FOR_STABILIZATION); | 1384 | msleep(DA732X_WAIT_FOR_STABILIZATION); |
1389 | 1385 | ||
1390 | if ((codec->hw_read(codec, DA732X_REG_HPL) & | 1386 | if ((snd_soc_read(codec, DA732X_REG_HPL) & |
1391 | DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP]) | 1387 | DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP]) |
1392 | offset[DA732X_HPL_AMP] &= ~step; | 1388 | offset[DA732X_HPL_AMP] &= ~step; |
1393 | if ((codec->hw_read(codec, DA732X_REG_HPR) & | 1389 | if ((snd_soc_read(codec, DA732X_REG_HPR) & |
1394 | DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP]) | 1390 | DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP]) |
1395 | offset[DA732X_HPR_AMP] &= ~step; | 1391 | offset[DA732X_HPR_AMP] &= ~step; |
1396 | 1392 | ||
@@ -1487,8 +1483,8 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, | |||
1487 | 1483 | ||
1488 | da732x_hp_dc_offset_cancellation(codec); | 1484 | da732x_hp_dc_offset_cancellation(codec); |
1489 | 1485 | ||
1490 | regcache_cache_only(codec->control_data, false); | 1486 | regcache_cache_only(da732x->regmap, false); |
1491 | regcache_sync(codec->control_data); | 1487 | regcache_sync(da732x->regmap); |
1492 | } else { | 1488 | } else { |
1493 | snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, | 1489 | snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, |
1494 | DA732X_BIAS_BOOST_MASK, | 1490 | DA732X_BIAS_BOOST_MASK, |
@@ -1499,7 +1495,7 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, | |||
1499 | } | 1495 | } |
1500 | break; | 1496 | break; |
1501 | case SND_SOC_BIAS_OFF: | 1497 | case SND_SOC_BIAS_OFF: |
1502 | regcache_cache_only(codec->control_data, true); | 1498 | regcache_cache_only(da732x->regmap, true); |
1503 | da732x_set_charge_pump(codec, DA732X_DISABLE_CP); | 1499 | da732x_set_charge_pump(codec, DA732X_DISABLE_CP); |
1504 | snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN, | 1500 | snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN, |
1505 | DA732X_BIAS_DIS); | 1501 | DA732X_BIAS_DIS); |
@@ -1516,23 +1512,14 @@ static int da732x_probe(struct snd_soc_codec *codec) | |||
1516 | { | 1512 | { |
1517 | struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); | 1513 | struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); |
1518 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 1514 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
1519 | int ret = 0; | ||
1520 | 1515 | ||
1521 | da732x->codec = codec; | 1516 | da732x->codec = codec; |
1522 | 1517 | ||
1523 | dapm->idle_bias_off = false; | 1518 | dapm->idle_bias_off = false; |
1524 | 1519 | ||
1525 | codec->control_data = da732x->regmap; | ||
1526 | |||
1527 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
1528 | if (ret != 0) { | ||
1529 | dev_err(codec->dev, "Failed to register codec.\n"); | ||
1530 | goto err; | ||
1531 | } | ||
1532 | |||
1533 | da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1520 | da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1534 | err: | 1521 | |
1535 | return ret; | 1522 | return 0; |
1536 | } | 1523 | } |
1537 | 1524 | ||
1538 | static int da732x_remove(struct snd_soc_codec *codec) | 1525 | static int da732x_remove(struct snd_soc_codec *codec) |
@@ -1554,7 +1541,6 @@ static struct snd_soc_codec_driver soc_codec_dev_da732x = { | |||
1554 | .dapm_routes = da732x_dapm_routes, | 1541 | .dapm_routes = da732x_dapm_routes, |
1555 | .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes), | 1542 | .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes), |
1556 | .set_pll = da732x_set_dai_pll, | 1543 | .set_pll = da732x_set_dai_pll, |
1557 | .reg_cache_size = ARRAY_SIZE(da732x_reg_cache), | ||
1558 | }; | 1544 | }; |
1559 | 1545 | ||
1560 | static int da732x_i2c_probe(struct i2c_client *i2c, | 1546 | static int da732x_i2c_probe(struct i2c_client *i2c, |
diff --git a/sound/soc/codecs/da732x.h b/sound/soc/codecs/da732x.h index c8ce5475de22..1dceafeec415 100644 --- a/sound/soc/codecs/da732x.h +++ b/sound/soc/codecs/da732x.h | |||
@@ -113,9 +113,6 @@ | |||
113 | #define DA732X_EQ_OVERALL_VOL_DB_MIN -1800 | 113 | #define DA732X_EQ_OVERALL_VOL_DB_MIN -1800 |
114 | #define DA732X_EQ_OVERALL_VOL_DB_INC 600 | 114 | #define DA732X_EQ_OVERALL_VOL_DB_INC 600 |
115 | 115 | ||
116 | #define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \ | ||
117 | {.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext} | ||
118 | |||
119 | enum da732x_sysctl { | 116 | enum da732x_sysctl { |
120 | DA732X_SR_8KHZ = 0x1, | 117 | DA732X_SR_8KHZ = 0x1, |
121 | DA732X_SR_11_025KHZ = 0x2, | 118 | DA732X_SR_11_025KHZ = 0x2, |
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 52b79a487ac7..4ff06b50fbba 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/regmap.h> | 18 | #include <linux/regmap.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/of.h> | ||
22 | #include <linux/of_device.h> | ||
21 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
22 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
23 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
@@ -321,22 +323,22 @@ static const char * const da9055_hpf_cutoff_txt[] = { | |||
321 | "Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000" | 323 | "Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000" |
322 | }; | 324 | }; |
323 | 325 | ||
324 | static const struct soc_enum da9055_dac_hpf_cutoff = | 326 | static SOC_ENUM_SINGLE_DECL(da9055_dac_hpf_cutoff, |
325 | SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt); | 327 | DA9055_DAC_FILTERS1, 4, da9055_hpf_cutoff_txt); |
326 | 328 | ||
327 | static const struct soc_enum da9055_adc_hpf_cutoff = | 329 | static SOC_ENUM_SINGLE_DECL(da9055_adc_hpf_cutoff, |
328 | SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt); | 330 | DA9055_ADC_FILTERS1, 4, da9055_hpf_cutoff_txt); |
329 | 331 | ||
330 | /* ADC and DAC voice mode (8kHz) high pass cutoff value */ | 332 | /* ADC and DAC voice mode (8kHz) high pass cutoff value */ |
331 | static const char * const da9055_vf_cutoff_txt[] = { | 333 | static const char * const da9055_vf_cutoff_txt[] = { |
332 | "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" | 334 | "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" |
333 | }; | 335 | }; |
334 | 336 | ||
335 | static const struct soc_enum da9055_dac_vf_cutoff = | 337 | static SOC_ENUM_SINGLE_DECL(da9055_dac_vf_cutoff, |
336 | SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 0, 8, da9055_vf_cutoff_txt); | 338 | DA9055_DAC_FILTERS1, 0, da9055_vf_cutoff_txt); |
337 | 339 | ||
338 | static const struct soc_enum da9055_adc_vf_cutoff = | 340 | static SOC_ENUM_SINGLE_DECL(da9055_adc_vf_cutoff, |
339 | SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 0, 8, da9055_vf_cutoff_txt); | 341 | DA9055_ADC_FILTERS1, 0, da9055_vf_cutoff_txt); |
340 | 342 | ||
341 | /* Gain ramping rate value */ | 343 | /* Gain ramping rate value */ |
342 | static const char * const da9055_gain_ramping_txt[] = { | 344 | static const char * const da9055_gain_ramping_txt[] = { |
@@ -344,44 +346,44 @@ static const char * const da9055_gain_ramping_txt[] = { | |||
344 | "nominal rate / 8" | 346 | "nominal rate / 8" |
345 | }; | 347 | }; |
346 | 348 | ||
347 | static const struct soc_enum da9055_gain_ramping_rate = | 349 | static SOC_ENUM_SINGLE_DECL(da9055_gain_ramping_rate, |
348 | SOC_ENUM_SINGLE(DA9055_GAIN_RAMP_CTRL, 0, 4, da9055_gain_ramping_txt); | 350 | DA9055_GAIN_RAMP_CTRL, 0, da9055_gain_ramping_txt); |
349 | 351 | ||
350 | /* DAC noise gate setup time value */ | 352 | /* DAC noise gate setup time value */ |
351 | static const char * const da9055_dac_ng_setup_time_txt[] = { | 353 | static const char * const da9055_dac_ng_setup_time_txt[] = { |
352 | "256 samples", "512 samples", "1024 samples", "2048 samples" | 354 | "256 samples", "512 samples", "1024 samples", "2048 samples" |
353 | }; | 355 | }; |
354 | 356 | ||
355 | static const struct soc_enum da9055_dac_ng_setup_time = | 357 | static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_setup_time, |
356 | SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 0, 4, | 358 | DA9055_DAC_NG_SETUP_TIME, 0, |
357 | da9055_dac_ng_setup_time_txt); | 359 | da9055_dac_ng_setup_time_txt); |
358 | 360 | ||
359 | /* DAC noise gate rampup rate value */ | 361 | /* DAC noise gate rampup rate value */ |
360 | static const char * const da9055_dac_ng_rampup_txt[] = { | 362 | static const char * const da9055_dac_ng_rampup_txt[] = { |
361 | "0.02 ms/dB", "0.16 ms/dB" | 363 | "0.02 ms/dB", "0.16 ms/dB" |
362 | }; | 364 | }; |
363 | 365 | ||
364 | static const struct soc_enum da9055_dac_ng_rampup_rate = | 366 | static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampup_rate, |
365 | SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 2, 2, | 367 | DA9055_DAC_NG_SETUP_TIME, 2, |
366 | da9055_dac_ng_rampup_txt); | 368 | da9055_dac_ng_rampup_txt); |
367 | 369 | ||
368 | /* DAC noise gate rampdown rate value */ | 370 | /* DAC noise gate rampdown rate value */ |
369 | static const char * const da9055_dac_ng_rampdown_txt[] = { | 371 | static const char * const da9055_dac_ng_rampdown_txt[] = { |
370 | "0.64 ms/dB", "20.48 ms/dB" | 372 | "0.64 ms/dB", "20.48 ms/dB" |
371 | }; | 373 | }; |
372 | 374 | ||
373 | static const struct soc_enum da9055_dac_ng_rampdown_rate = | 375 | static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampdown_rate, |
374 | SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 3, 2, | 376 | DA9055_DAC_NG_SETUP_TIME, 3, |
375 | da9055_dac_ng_rampdown_txt); | 377 | da9055_dac_ng_rampdown_txt); |
376 | 378 | ||
377 | /* DAC soft mute rate value */ | 379 | /* DAC soft mute rate value */ |
378 | static const char * const da9055_dac_soft_mute_rate_txt[] = { | 380 | static const char * const da9055_dac_soft_mute_rate_txt[] = { |
379 | "1", "2", "4", "8", "16", "32", "64" | 381 | "1", "2", "4", "8", "16", "32", "64" |
380 | }; | 382 | }; |
381 | 383 | ||
382 | static const struct soc_enum da9055_dac_soft_mute_rate = | 384 | static SOC_ENUM_SINGLE_DECL(da9055_dac_soft_mute_rate, |
383 | SOC_ENUM_SINGLE(DA9055_DAC_FILTERS5, 4, 7, | 385 | DA9055_DAC_FILTERS5, 4, |
384 | da9055_dac_soft_mute_rate_txt); | 386 | da9055_dac_soft_mute_rate_txt); |
385 | 387 | ||
386 | /* DAC routing select */ | 388 | /* DAC routing select */ |
387 | static const char * const da9055_dac_src_txt[] = { | 389 | static const char * const da9055_dac_src_txt[] = { |
@@ -389,40 +391,40 @@ static const char * const da9055_dac_src_txt[] = { | |||
389 | "AIF input right" | 391 | "AIF input right" |
390 | }; | 392 | }; |
391 | 393 | ||
392 | static const struct soc_enum da9055_dac_l_src = | 394 | static SOC_ENUM_SINGLE_DECL(da9055_dac_l_src, |
393 | SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 0, 4, da9055_dac_src_txt); | 395 | DA9055_DIG_ROUTING_DAC, 0, da9055_dac_src_txt); |
394 | 396 | ||
395 | static const struct soc_enum da9055_dac_r_src = | 397 | static SOC_ENUM_SINGLE_DECL(da9055_dac_r_src, |
396 | SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 4, 4, da9055_dac_src_txt); | 398 | DA9055_DIG_ROUTING_DAC, 4, da9055_dac_src_txt); |
397 | 399 | ||
398 | /* MIC PGA Left source select */ | 400 | /* MIC PGA Left source select */ |
399 | static const char * const da9055_mic_l_src_txt[] = { | 401 | static const char * const da9055_mic_l_src_txt[] = { |
400 | "MIC1_P_N", "MIC1_P", "MIC1_N", "MIC2_L" | 402 | "MIC1_P_N", "MIC1_P", "MIC1_N", "MIC2_L" |
401 | }; | 403 | }; |
402 | 404 | ||
403 | static const struct soc_enum da9055_mic_l_src = | 405 | static SOC_ENUM_SINGLE_DECL(da9055_mic_l_src, |
404 | SOC_ENUM_SINGLE(DA9055_MIXIN_L_SELECT, 4, 4, da9055_mic_l_src_txt); | 406 | DA9055_MIXIN_L_SELECT, 4, da9055_mic_l_src_txt); |
405 | 407 | ||
406 | /* MIC PGA Right source select */ | 408 | /* MIC PGA Right source select */ |
407 | static const char * const da9055_mic_r_src_txt[] = { | 409 | static const char * const da9055_mic_r_src_txt[] = { |
408 | "MIC2_R_L", "MIC2_R", "MIC2_L" | 410 | "MIC2_R_L", "MIC2_R", "MIC2_L" |
409 | }; | 411 | }; |
410 | 412 | ||
411 | static const struct soc_enum da9055_mic_r_src = | 413 | static SOC_ENUM_SINGLE_DECL(da9055_mic_r_src, |
412 | SOC_ENUM_SINGLE(DA9055_MIXIN_R_SELECT, 4, 3, da9055_mic_r_src_txt); | 414 | DA9055_MIXIN_R_SELECT, 4, da9055_mic_r_src_txt); |
413 | 415 | ||
414 | /* ALC Input Signal Tracking rate select */ | 416 | /* ALC Input Signal Tracking rate select */ |
415 | static const char * const da9055_signal_tracking_rate_txt[] = { | 417 | static const char * const da9055_signal_tracking_rate_txt[] = { |
416 | "1/4", "1/16", "1/256", "1/65536" | 418 | "1/4", "1/16", "1/256", "1/65536" |
417 | }; | 419 | }; |
418 | 420 | ||
419 | static const struct soc_enum da9055_integ_attack_rate = | 421 | static SOC_ENUM_SINGLE_DECL(da9055_integ_attack_rate, |
420 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 4, 4, | 422 | DA9055_ALC_CTRL3, 4, |
421 | da9055_signal_tracking_rate_txt); | 423 | da9055_signal_tracking_rate_txt); |
422 | 424 | ||
423 | static const struct soc_enum da9055_integ_release_rate = | 425 | static SOC_ENUM_SINGLE_DECL(da9055_integ_release_rate, |
424 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 6, 4, | 426 | DA9055_ALC_CTRL3, 6, |
425 | da9055_signal_tracking_rate_txt); | 427 | da9055_signal_tracking_rate_txt); |
426 | 428 | ||
427 | /* ALC Attack Rate select */ | 429 | /* ALC Attack Rate select */ |
428 | static const char * const da9055_attack_rate_txt[] = { | 430 | static const char * const da9055_attack_rate_txt[] = { |
@@ -430,8 +432,8 @@ static const char * const da9055_attack_rate_txt[] = { | |||
430 | "5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" | 432 | "5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" |
431 | }; | 433 | }; |
432 | 434 | ||
433 | static const struct soc_enum da9055_attack_rate = | 435 | static SOC_ENUM_SINGLE_DECL(da9055_attack_rate, |
434 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 0, 13, da9055_attack_rate_txt); | 436 | DA9055_ALC_CTRL2, 0, da9055_attack_rate_txt); |
435 | 437 | ||
436 | /* ALC Release Rate select */ | 438 | /* ALC Release Rate select */ |
437 | static const char * const da9055_release_rate_txt[] = { | 439 | static const char * const da9055_release_rate_txt[] = { |
@@ -439,8 +441,8 @@ static const char * const da9055_release_rate_txt[] = { | |||
439 | "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" | 441 | "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" |
440 | }; | 442 | }; |
441 | 443 | ||
442 | static const struct soc_enum da9055_release_rate = | 444 | static SOC_ENUM_SINGLE_DECL(da9055_release_rate, |
443 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 4, 11, da9055_release_rate_txt); | 445 | DA9055_ALC_CTRL2, 4, da9055_release_rate_txt); |
444 | 446 | ||
445 | /* ALC Hold Time select */ | 447 | /* ALC Hold Time select */ |
446 | static const char * const da9055_hold_time_txt[] = { | 448 | static const char * const da9055_hold_time_txt[] = { |
@@ -449,8 +451,8 @@ static const char * const da9055_hold_time_txt[] = { | |||
449 | "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" | 451 | "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" |
450 | }; | 452 | }; |
451 | 453 | ||
452 | static const struct soc_enum da9055_hold_time = | 454 | static SOC_ENUM_SINGLE_DECL(da9055_hold_time, |
453 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 0, 16, da9055_hold_time_txt); | 455 | DA9055_ALC_CTRL3, 0, da9055_hold_time_txt); |
454 | 456 | ||
455 | static int da9055_get_alc_data(struct snd_soc_codec *codec, u8 reg_val) | 457 | static int da9055_get_alc_data(struct snd_soc_codec *codec, u8 reg_val) |
456 | { | 458 | { |
@@ -1381,16 +1383,8 @@ static int da9055_set_bias_level(struct snd_soc_codec *codec, | |||
1381 | 1383 | ||
1382 | static int da9055_probe(struct snd_soc_codec *codec) | 1384 | static int da9055_probe(struct snd_soc_codec *codec) |
1383 | { | 1385 | { |
1384 | int ret; | ||
1385 | struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); | 1386 | struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); |
1386 | 1387 | ||
1387 | codec->control_data = da9055->regmap; | ||
1388 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
1389 | if (ret < 0) { | ||
1390 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1391 | return ret; | ||
1392 | } | ||
1393 | |||
1394 | /* Enable all Gain Ramps */ | 1388 | /* Enable all Gain Ramps */ |
1395 | snd_soc_update_bits(codec, DA9055_AUX_L_CTRL, | 1389 | snd_soc_update_bits(codec, DA9055_AUX_L_CTRL, |
1396 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | 1390 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); |
@@ -1523,17 +1517,30 @@ static int da9055_remove(struct i2c_client *client) | |||
1523 | return 0; | 1517 | return 0; |
1524 | } | 1518 | } |
1525 | 1519 | ||
1520 | /* | ||
1521 | * DO NOT change the device Ids. The naming is intentionally specific as both | ||
1522 | * the CODEC and PMIC parts of this chip are instantiated separately as I2C | ||
1523 | * devices (both have configurable I2C addresses, and are to all intents and | ||
1524 | * purposes separate). As a result there are specific DA9055 Ids for CODEC | ||
1525 | * and PMIC, which must be different to operate together. | ||
1526 | */ | ||
1526 | static const struct i2c_device_id da9055_i2c_id[] = { | 1527 | static const struct i2c_device_id da9055_i2c_id[] = { |
1527 | { "da9055", 0 }, | 1528 | { "da9055-codec", 0 }, |
1528 | { } | 1529 | { } |
1529 | }; | 1530 | }; |
1530 | MODULE_DEVICE_TABLE(i2c, da9055_i2c_id); | 1531 | MODULE_DEVICE_TABLE(i2c, da9055_i2c_id); |
1531 | 1532 | ||
1533 | static const struct of_device_id da9055_of_match[] = { | ||
1534 | { .compatible = "dlg,da9055-codec", }, | ||
1535 | { } | ||
1536 | }; | ||
1537 | |||
1532 | /* I2C codec control layer */ | 1538 | /* I2C codec control layer */ |
1533 | static struct i2c_driver da9055_i2c_driver = { | 1539 | static struct i2c_driver da9055_i2c_driver = { |
1534 | .driver = { | 1540 | .driver = { |
1535 | .name = "da9055", | 1541 | .name = "da9055-codec", |
1536 | .owner = THIS_MODULE, | 1542 | .owner = THIS_MODULE, |
1543 | .of_match_table = of_match_ptr(da9055_of_match), | ||
1537 | }, | 1544 | }, |
1538 | .probe = da9055_i2c_probe, | 1545 | .probe = da9055_i2c_probe, |
1539 | .remove = da9055_remove, | 1546 | .remove = da9055_remove, |
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 5839048ec467..3a89ce66d51d 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c | |||
@@ -140,13 +140,17 @@ static const char *isabelle_rx1_texts[] = {"VRX1", "ARX1"}; | |||
140 | static const char *isabelle_rx2_texts[] = {"VRX2", "ARX2"}; | 140 | static const char *isabelle_rx2_texts[] = {"VRX2", "ARX2"}; |
141 | 141 | ||
142 | static const struct soc_enum isabelle_rx1_enum[] = { | 142 | static const struct soc_enum isabelle_rx1_enum[] = { |
143 | SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, 1, isabelle_rx1_texts), | 143 | SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, |
144 | SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, 1, isabelle_rx1_texts), | 144 | ARRAY_SIZE(isabelle_rx1_texts), isabelle_rx1_texts), |
145 | SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, | ||
146 | ARRAY_SIZE(isabelle_rx1_texts), isabelle_rx1_texts), | ||
145 | }; | 147 | }; |
146 | 148 | ||
147 | static const struct soc_enum isabelle_rx2_enum[] = { | 149 | static const struct soc_enum isabelle_rx2_enum[] = { |
148 | SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, 1, isabelle_rx2_texts), | 150 | SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, |
149 | SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, 1, isabelle_rx2_texts), | 151 | ARRAY_SIZE(isabelle_rx2_texts), isabelle_rx2_texts), |
152 | SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, | ||
153 | ARRAY_SIZE(isabelle_rx2_texts), isabelle_rx2_texts), | ||
150 | }; | 154 | }; |
151 | 155 | ||
152 | /* Headset DAC playback switches */ | 156 | /* Headset DAC playback switches */ |
@@ -161,13 +165,17 @@ static const char *isabelle_atx_texts[] = {"AMIC1", "DMIC"}; | |||
161 | static const char *isabelle_vtx_texts[] = {"AMIC2", "DMIC"}; | 165 | static const char *isabelle_vtx_texts[] = {"AMIC2", "DMIC"}; |
162 | 166 | ||
163 | static const struct soc_enum isabelle_atx_enum[] = { | 167 | static const struct soc_enum isabelle_atx_enum[] = { |
164 | SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, 1, isabelle_atx_texts), | 168 | SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, |
165 | SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_atx_texts), | 169 | ARRAY_SIZE(isabelle_atx_texts), isabelle_atx_texts), |
170 | SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, | ||
171 | ARRAY_SIZE(isabelle_atx_texts), isabelle_atx_texts), | ||
166 | }; | 172 | }; |
167 | 173 | ||
168 | static const struct soc_enum isabelle_vtx_enum[] = { | 174 | static const struct soc_enum isabelle_vtx_enum[] = { |
169 | SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, 1, isabelle_vtx_texts), | 175 | SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, |
170 | SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_vtx_texts), | 176 | ARRAY_SIZE(isabelle_vtx_texts), isabelle_vtx_texts), |
177 | SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, | ||
178 | ARRAY_SIZE(isabelle_vtx_texts), isabelle_vtx_texts), | ||
171 | }; | 179 | }; |
172 | 180 | ||
173 | static const struct snd_kcontrol_new atx_mux_controls = | 181 | static const struct snd_kcontrol_new atx_mux_controls = |
@@ -183,17 +191,13 @@ static const char *isabelle_amic1_texts[] = { | |||
183 | /* Left analog microphone selection */ | 191 | /* Left analog microphone selection */ |
184 | static const char *isabelle_amic2_texts[] = {"Sub Mic", "Aux/FM Right"}; | 192 | static const char *isabelle_amic2_texts[] = {"Sub Mic", "Aux/FM Right"}; |
185 | 193 | ||
186 | static const struct soc_enum isabelle_amic1_enum[] = { | 194 | static SOC_ENUM_SINGLE_DECL(isabelle_amic1_enum, |
187 | SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 5, | 195 | ISABELLE_AMIC_CFG_REG, 5, |
188 | ARRAY_SIZE(isabelle_amic1_texts), | 196 | isabelle_amic1_texts); |
189 | isabelle_amic1_texts), | ||
190 | }; | ||
191 | 197 | ||
192 | static const struct soc_enum isabelle_amic2_enum[] = { | 198 | static SOC_ENUM_SINGLE_DECL(isabelle_amic2_enum, |
193 | SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 4, | 199 | ISABELLE_AMIC_CFG_REG, 4, |
194 | ARRAY_SIZE(isabelle_amic2_texts), | 200 | isabelle_amic2_texts); |
195 | isabelle_amic2_texts), | ||
196 | }; | ||
197 | 201 | ||
198 | static const struct snd_kcontrol_new amic1_control = | 202 | static const struct snd_kcontrol_new amic1_control = |
199 | SOC_DAPM_ENUM("Route", isabelle_amic1_enum); | 203 | SOC_DAPM_ENUM("Route", isabelle_amic1_enum); |
@@ -206,16 +210,20 @@ static const char *isabelle_st_audio_texts[] = {"ATX1", "ATX2"}; | |||
206 | static const char *isabelle_st_voice_texts[] = {"VTX1", "VTX2"}; | 210 | static const char *isabelle_st_voice_texts[] = {"VTX1", "VTX2"}; |
207 | 211 | ||
208 | static const struct soc_enum isabelle_st_audio_enum[] = { | 212 | static const struct soc_enum isabelle_st_audio_enum[] = { |
209 | SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, 1, | 213 | SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, |
214 | ARRAY_SIZE(isabelle_st_audio_texts), | ||
210 | isabelle_st_audio_texts), | 215 | isabelle_st_audio_texts), |
211 | SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, 1, | 216 | SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, |
217 | ARRAY_SIZE(isabelle_st_audio_texts), | ||
212 | isabelle_st_audio_texts), | 218 | isabelle_st_audio_texts), |
213 | }; | 219 | }; |
214 | 220 | ||
215 | static const struct soc_enum isabelle_st_voice_enum[] = { | 221 | static const struct soc_enum isabelle_st_voice_enum[] = { |
216 | SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, 1, | 222 | SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, |
223 | ARRAY_SIZE(isabelle_st_voice_texts), | ||
217 | isabelle_st_voice_texts), | 224 | isabelle_st_voice_texts), |
218 | SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, 1, | 225 | SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, |
226 | ARRAY_SIZE(isabelle_st_voice_texts), | ||
219 | isabelle_st_voice_texts), | 227 | isabelle_st_voice_texts), |
220 | }; | 228 | }; |
221 | 229 | ||
@@ -910,8 +918,7 @@ static int isabelle_hw_params(struct snd_pcm_substream *substream, | |||
910 | struct snd_pcm_hw_params *params, | 918 | struct snd_pcm_hw_params *params, |
911 | struct snd_soc_dai *dai) | 919 | struct snd_soc_dai *dai) |
912 | { | 920 | { |
913 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 921 | struct snd_soc_codec *codec = dai->codec; |
914 | struct snd_soc_codec *codec = rtd->codec; | ||
915 | u16 aif = 0; | 922 | u16 aif = 0; |
916 | unsigned int fs_val = 0; | 923 | unsigned int fs_val = 0; |
917 | 924 | ||
@@ -1082,23 +1089,7 @@ static struct snd_soc_dai_driver isabelle_dai[] = { | |||
1082 | }, | 1089 | }, |
1083 | }; | 1090 | }; |
1084 | 1091 | ||
1085 | static int isabelle_probe(struct snd_soc_codec *codec) | ||
1086 | { | ||
1087 | int ret = 0; | ||
1088 | |||
1089 | codec->control_data = dev_get_regmap(codec->dev, NULL); | ||
1090 | |||
1091 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
1092 | if (ret < 0) { | ||
1093 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1094 | return ret; | ||
1095 | } | ||
1096 | |||
1097 | return 0; | ||
1098 | } | ||
1099 | |||
1100 | static struct snd_soc_codec_driver soc_codec_dev_isabelle = { | 1092 | static struct snd_soc_codec_driver soc_codec_dev_isabelle = { |
1101 | .probe = isabelle_probe, | ||
1102 | .set_bias_level = isabelle_set_bias_level, | 1093 | .set_bias_level = isabelle_set_bias_level, |
1103 | .controls = isabelle_snd_controls, | 1094 | .controls = isabelle_snd_controls, |
1104 | .num_controls = ARRAY_SIZE(isabelle_snd_controls), | 1095 | .num_controls = ARRAY_SIZE(isabelle_snd_controls), |
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index 0e5743ea79df..4f048db9f55f 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c | |||
@@ -101,8 +101,7 @@ static const char *lm4857_mode[] = { | |||
101 | "Headphone", | 101 | "Headphone", |
102 | }; | 102 | }; |
103 | 103 | ||
104 | static const struct soc_enum lm4857_mode_enum = | 104 | static SOC_ENUM_SINGLE_EXT_DECL(lm4857_mode_enum, lm4857_mode); |
105 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode); | ||
106 | 105 | ||
107 | static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = { | 106 | static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = { |
108 | SND_SOC_DAPM_INPUT("IN"), | 107 | SND_SOC_DAPM_INPUT("IN"), |
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index e19490cfb3a8..275b3f72f3f4 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c | |||
@@ -195,33 +195,31 @@ struct lm49453_priv { | |||
195 | 195 | ||
196 | static const char *lm49453_mic2mode_text[] = {"Single Ended", "Differential"}; | 196 | static const char *lm49453_mic2mode_text[] = {"Single Ended", "Differential"}; |
197 | 197 | ||
198 | static const SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5, | 198 | static SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5, |
199 | lm49453_mic2mode_text); | 199 | lm49453_mic2mode_text); |
200 | 200 | ||
201 | static const char *lm49453_dmic_cfg_text[] = {"DMICDAT1", "DMICDAT2"}; | 201 | static const char *lm49453_dmic_cfg_text[] = {"DMICDAT1", "DMICDAT2"}; |
202 | 202 | ||
203 | static const SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum, | 203 | static SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum, |
204 | LM49453_P0_DIGITAL_MIC1_CONFIG_REG, | 204 | LM49453_P0_DIGITAL_MIC1_CONFIG_REG, 7, |
205 | 7, lm49453_dmic_cfg_text); | 205 | lm49453_dmic_cfg_text); |
206 | 206 | ||
207 | static const SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum, | 207 | static SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum, |
208 | LM49453_P0_DIGITAL_MIC2_CONFIG_REG, | 208 | LM49453_P0_DIGITAL_MIC2_CONFIG_REG, 7, |
209 | 7, lm49453_dmic_cfg_text); | 209 | lm49453_dmic_cfg_text); |
210 | 210 | ||
211 | /* MUX Controls */ | 211 | /* MUX Controls */ |
212 | static const char *lm49453_adcl_mux_text[] = { "MIC1", "Aux_L" }; | 212 | static const char *lm49453_adcl_mux_text[] = { "MIC1", "Aux_L" }; |
213 | 213 | ||
214 | static const char *lm49453_adcr_mux_text[] = { "MIC2", "Aux_R" }; | 214 | static const char *lm49453_adcr_mux_text[] = { "MIC2", "Aux_R" }; |
215 | 215 | ||
216 | static const struct soc_enum lm49453_adcl_enum = | 216 | static SOC_ENUM_SINGLE_DECL(lm49453_adcl_enum, |
217 | SOC_ENUM_SINGLE(LM49453_P0_ANALOG_MIXER_ADC_REG, 0, | 217 | LM49453_P0_ANALOG_MIXER_ADC_REG, 0, |
218 | ARRAY_SIZE(lm49453_adcl_mux_text), | 218 | lm49453_adcl_mux_text); |
219 | lm49453_adcl_mux_text); | ||
220 | 219 | ||
221 | static const struct soc_enum lm49453_adcr_enum = | 220 | static SOC_ENUM_SINGLE_DECL(lm49453_adcr_enum, |
222 | SOC_ENUM_SINGLE(LM49453_P0_ANALOG_MIXER_ADC_REG, 1, | 221 | LM49453_P0_ANALOG_MIXER_ADC_REG, 1, |
223 | ARRAY_SIZE(lm49453_adcr_mux_text), | 222 | lm49453_adcr_mux_text); |
224 | lm49453_adcr_mux_text); | ||
225 | 223 | ||
226 | static const struct snd_kcontrol_new lm49453_adcl_mux_control = | 224 | static const struct snd_kcontrol_new lm49453_adcl_mux_control = |
227 | SOC_DAPM_ENUM("ADC Left Mux", lm49453_adcl_enum); | 225 | SOC_DAPM_ENUM("ADC Left Mux", lm49453_adcl_enum); |
@@ -1409,22 +1407,6 @@ static int lm49453_resume(struct snd_soc_codec *codec) | |||
1409 | return 0; | 1407 | return 0; |
1410 | } | 1408 | } |
1411 | 1409 | ||
1412 | static int lm49453_probe(struct snd_soc_codec *codec) | ||
1413 | { | ||
1414 | struct lm49453_priv *lm49453 = snd_soc_codec_get_drvdata(codec); | ||
1415 | int ret = 0; | ||
1416 | |||
1417 | codec->control_data = lm49453->regmap; | ||
1418 | |||
1419 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
1420 | if (ret < 0) { | ||
1421 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1422 | return ret; | ||
1423 | } | ||
1424 | |||
1425 | return 0; | ||
1426 | } | ||
1427 | |||
1428 | /* power down chip */ | 1410 | /* power down chip */ |
1429 | static int lm49453_remove(struct snd_soc_codec *codec) | 1411 | static int lm49453_remove(struct snd_soc_codec *codec) |
1430 | { | 1412 | { |
@@ -1433,7 +1415,6 @@ static int lm49453_remove(struct snd_soc_codec *codec) | |||
1433 | } | 1415 | } |
1434 | 1416 | ||
1435 | static struct snd_soc_codec_driver soc_codec_dev_lm49453 = { | 1417 | static struct snd_soc_codec_driver soc_codec_dev_lm49453 = { |
1436 | .probe = lm49453_probe, | ||
1437 | .remove = lm49453_remove, | 1418 | .remove = lm49453_remove, |
1438 | .suspend = lm49453_suspend, | 1419 | .suspend = lm49453_suspend, |
1439 | .resume = lm49453_resume, | 1420 | .resume = lm49453_resume, |
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c index 31f91560e9f6..ec481fc428c7 100644 --- a/sound/soc/codecs/max9768.c +++ b/sound/soc/codecs/max9768.c | |||
@@ -135,11 +135,6 @@ static int max9768_probe(struct snd_soc_codec *codec) | |||
135 | struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); | 135 | struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); |
136 | int ret; | 136 | int ret; |
137 | 137 | ||
138 | codec->control_data = max9768->regmap; | ||
139 | ret = snd_soc_codec_set_cache_io(codec, 2, 6, SND_SOC_REGMAP); | ||
140 | if (ret) | ||
141 | return ret; | ||
142 | |||
143 | if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) { | 138 | if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) { |
144 | ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM); | 139 | ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM); |
145 | if (ret) | 140 | if (ret) |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index ee660e2d3df3..ef7cf89f5623 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -597,28 +597,27 @@ static const unsigned int max98088_exmode_values[] = { | |||
597 | 0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32 | 597 | 0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32 |
598 | }; | 598 | }; |
599 | 599 | ||
600 | static const struct soc_enum max98088_exmode_enum = | 600 | static SOC_VALUE_ENUM_SINGLE_DECL(max98088_exmode_enum, |
601 | SOC_VALUE_ENUM_SINGLE(M98088_REG_41_SPKDHP, 0, 127, | 601 | M98088_REG_41_SPKDHP, 0, 127, |
602 | ARRAY_SIZE(max98088_exmode_texts), | 602 | max98088_exmode_texts, |
603 | max98088_exmode_texts, | 603 | max98088_exmode_values); |
604 | max98088_exmode_values); | ||
605 | 604 | ||
606 | static const char *max98088_ex_thresh[] = { /* volts PP */ | 605 | static const char *max98088_ex_thresh[] = { /* volts PP */ |
607 | "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"}; | 606 | "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"}; |
608 | static const struct soc_enum max98088_ex_thresh_enum[] = { | 607 | static SOC_ENUM_SINGLE_DECL(max98088_ex_thresh_enum, |
609 | SOC_ENUM_SINGLE(M98088_REG_42_SPKDHP_THRESH, 0, 8, | 608 | M98088_REG_42_SPKDHP_THRESH, 0, |
610 | max98088_ex_thresh), | 609 | max98088_ex_thresh); |
611 | }; | ||
612 | 610 | ||
613 | static const char *max98088_fltr_mode[] = {"Voice", "Music" }; | 611 | static const char *max98088_fltr_mode[] = {"Voice", "Music" }; |
614 | static const struct soc_enum max98088_filter_mode_enum[] = { | 612 | static SOC_ENUM_SINGLE_DECL(max98088_filter_mode_enum, |
615 | SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 7, 2, max98088_fltr_mode), | 613 | M98088_REG_18_DAI1_FILTERS, 7, |
616 | }; | 614 | max98088_fltr_mode); |
617 | 615 | ||
618 | static const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" }; | 616 | static const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" }; |
619 | 617 | ||
620 | static const struct soc_enum max98088_extmic_enum = | 618 | static SOC_ENUM_SINGLE_DECL(max98088_extmic_enum, |
621 | SOC_ENUM_SINGLE(M98088_REG_48_CFG_MIC, 0, 3, max98088_extmic_text); | 619 | M98088_REG_48_CFG_MIC, 0, |
620 | max98088_extmic_text); | ||
622 | 621 | ||
623 | static const struct snd_kcontrol_new max98088_extmic_mux = | 622 | static const struct snd_kcontrol_new max98088_extmic_mux = |
624 | SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum); | 623 | SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum); |
@@ -626,12 +625,12 @@ static const struct snd_kcontrol_new max98088_extmic_mux = | |||
626 | static const char *max98088_dai1_fltr[] = { | 625 | static const char *max98088_dai1_fltr[] = { |
627 | "Off", "fc=258/fs=16k", "fc=500/fs=16k", | 626 | "Off", "fc=258/fs=16k", "fc=500/fs=16k", |
628 | "fc=258/fs=8k", "fc=500/fs=8k", "fc=200"}; | 627 | "fc=258/fs=8k", "fc=500/fs=8k", "fc=200"}; |
629 | static const struct soc_enum max98088_dai1_dac_filter_enum[] = { | 628 | static SOC_ENUM_SINGLE_DECL(max98088_dai1_dac_filter_enum, |
630 | SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 0, 6, max98088_dai1_fltr), | 629 | M98088_REG_18_DAI1_FILTERS, 0, |
631 | }; | 630 | max98088_dai1_fltr); |
632 | static const struct soc_enum max98088_dai1_adc_filter_enum[] = { | 631 | static SOC_ENUM_SINGLE_DECL(max98088_dai1_adc_filter_enum, |
633 | SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 4, 6, max98088_dai1_fltr), | 632 | M98088_REG_18_DAI1_FILTERS, 4, |
634 | }; | 633 | max98088_dai1_fltr); |
635 | 634 | ||
636 | static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol, | 635 | static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol, |
637 | struct snd_ctl_elem_value *ucontrol) | 636 | struct snd_ctl_elem_value *ucontrol) |
@@ -1849,7 +1848,7 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec) | |||
1849 | 1848 | ||
1850 | /* Now point the soc_enum to .texts array items */ | 1849 | /* Now point the soc_enum to .texts array items */ |
1851 | max98088->eq_enum.texts = max98088->eq_texts; | 1850 | max98088->eq_enum.texts = max98088->eq_texts; |
1852 | max98088->eq_enum.max = max98088->eq_textcnt; | 1851 | max98088->eq_enum.items = max98088->eq_textcnt; |
1853 | 1852 | ||
1854 | ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); | 1853 | ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); |
1855 | if (ret != 0) | 1854 | if (ret != 0) |
@@ -1915,12 +1914,6 @@ static int max98088_probe(struct snd_soc_codec *codec) | |||
1915 | 1914 | ||
1916 | regcache_mark_dirty(max98088->regmap); | 1915 | regcache_mark_dirty(max98088->regmap); |
1917 | 1916 | ||
1918 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
1919 | if (ret != 0) { | ||
1920 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1921 | return ret; | ||
1922 | } | ||
1923 | |||
1924 | /* initialize private data */ | 1917 | /* initialize private data */ |
1925 | 1918 | ||
1926 | max98088->sysclk = (unsigned)-1; | 1919 | max98088->sysclk = (unsigned)-1; |
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 51f9b3d16b41..98c6e104357c 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
@@ -336,6 +336,7 @@ static bool max98090_readable_register(struct device *dev, unsigned int reg) | |||
336 | case M98090_REG_RECORD_TDM_SLOT: | 336 | case M98090_REG_RECORD_TDM_SLOT: |
337 | case M98090_REG_SAMPLE_RATE: | 337 | case M98090_REG_SAMPLE_RATE: |
338 | case M98090_REG_DMIC34_BIQUAD_BASE ... M98090_REG_DMIC34_BIQUAD_BASE + 0x0E: | 338 | case M98090_REG_DMIC34_BIQUAD_BASE ... M98090_REG_DMIC34_BIQUAD_BASE + 0x0E: |
339 | case M98090_REG_REVISION_ID: | ||
339 | return true; | 340 | return true; |
340 | default: | 341 | default: |
341 | return false; | 342 | return false; |
@@ -512,65 +513,75 @@ static const char *max98090_perf_pwr_text[] = | |||
512 | static const char *max98090_pwr_perf_text[] = | 513 | static const char *max98090_pwr_perf_text[] = |
513 | { "Low Power", "High Performance" }; | 514 | { "Low Power", "High Performance" }; |
514 | 515 | ||
515 | static const struct soc_enum max98090_vcmbandgap_enum = | 516 | static SOC_ENUM_SINGLE_DECL(max98090_vcmbandgap_enum, |
516 | SOC_ENUM_SINGLE(M98090_REG_BIAS_CONTROL, M98090_VCM_MODE_SHIFT, | 517 | M98090_REG_BIAS_CONTROL, |
517 | ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); | 518 | M98090_VCM_MODE_SHIFT, |
519 | max98090_pwr_perf_text); | ||
518 | 520 | ||
519 | static const char *max98090_osr128_text[] = { "64*fs", "128*fs" }; | 521 | static const char *max98090_osr128_text[] = { "64*fs", "128*fs" }; |
520 | 522 | ||
521 | static const struct soc_enum max98090_osr128_enum = | 523 | static SOC_ENUM_SINGLE_DECL(max98090_osr128_enum, |
522 | SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_OSR128_SHIFT, | 524 | M98090_REG_ADC_CONTROL, |
523 | ARRAY_SIZE(max98090_osr128_text), max98090_osr128_text); | 525 | M98090_OSR128_SHIFT, |
526 | max98090_osr128_text); | ||
524 | 527 | ||
525 | static const char *max98090_mode_text[] = { "Voice", "Music" }; | 528 | static const char *max98090_mode_text[] = { "Voice", "Music" }; |
526 | 529 | ||
527 | static const struct soc_enum max98090_mode_enum = | 530 | static SOC_ENUM_SINGLE_DECL(max98090_mode_enum, |
528 | SOC_ENUM_SINGLE(M98090_REG_FILTER_CONFIG, M98090_MODE_SHIFT, | 531 | M98090_REG_FILTER_CONFIG, |
529 | ARRAY_SIZE(max98090_mode_text), max98090_mode_text); | 532 | M98090_MODE_SHIFT, |
533 | max98090_mode_text); | ||
530 | 534 | ||
531 | static const struct soc_enum max98090_filter_dmic34mode_enum = | 535 | static SOC_ENUM_SINGLE_DECL(max98090_filter_dmic34mode_enum, |
532 | SOC_ENUM_SINGLE(M98090_REG_FILTER_CONFIG, | 536 | M98090_REG_FILTER_CONFIG, |
533 | M98090_FLT_DMIC34MODE_SHIFT, | 537 | M98090_FLT_DMIC34MODE_SHIFT, |
534 | ARRAY_SIZE(max98090_mode_text), max98090_mode_text); | 538 | max98090_mode_text); |
535 | 539 | ||
536 | static const char *max98090_drcatk_text[] = | 540 | static const char *max98090_drcatk_text[] = |
537 | { "0.5ms", "1ms", "5ms", "10ms", "25ms", "50ms", "100ms", "200ms" }; | 541 | { "0.5ms", "1ms", "5ms", "10ms", "25ms", "50ms", "100ms", "200ms" }; |
538 | 542 | ||
539 | static const struct soc_enum max98090_drcatk_enum = | 543 | static SOC_ENUM_SINGLE_DECL(max98090_drcatk_enum, |
540 | SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCATK_SHIFT, | 544 | M98090_REG_DRC_TIMING, |
541 | ARRAY_SIZE(max98090_drcatk_text), max98090_drcatk_text); | 545 | M98090_DRCATK_SHIFT, |
546 | max98090_drcatk_text); | ||
542 | 547 | ||
543 | static const char *max98090_drcrls_text[] = | 548 | static const char *max98090_drcrls_text[] = |
544 | { "8s", "4s", "2s", "1s", "0.5s", "0.25s", "0.125s", "0.0625s" }; | 549 | { "8s", "4s", "2s", "1s", "0.5s", "0.25s", "0.125s", "0.0625s" }; |
545 | 550 | ||
546 | static const struct soc_enum max98090_drcrls_enum = | 551 | static SOC_ENUM_SINGLE_DECL(max98090_drcrls_enum, |
547 | SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCRLS_SHIFT, | 552 | M98090_REG_DRC_TIMING, |
548 | ARRAY_SIZE(max98090_drcrls_text), max98090_drcrls_text); | 553 | M98090_DRCRLS_SHIFT, |
554 | max98090_drcrls_text); | ||
549 | 555 | ||
550 | static const char *max98090_alccmp_text[] = | 556 | static const char *max98090_alccmp_text[] = |
551 | { "1:1", "1:1.5", "1:2", "1:4", "1:INF" }; | 557 | { "1:1", "1:1.5", "1:2", "1:4", "1:INF" }; |
552 | 558 | ||
553 | static const struct soc_enum max98090_alccmp_enum = | 559 | static SOC_ENUM_SINGLE_DECL(max98090_alccmp_enum, |
554 | SOC_ENUM_SINGLE(M98090_REG_DRC_COMPRESSOR, M98090_DRCCMP_SHIFT, | 560 | M98090_REG_DRC_COMPRESSOR, |
555 | ARRAY_SIZE(max98090_alccmp_text), max98090_alccmp_text); | 561 | M98090_DRCCMP_SHIFT, |
562 | max98090_alccmp_text); | ||
556 | 563 | ||
557 | static const char *max98090_drcexp_text[] = { "1:1", "2:1", "3:1" }; | 564 | static const char *max98090_drcexp_text[] = { "1:1", "2:1", "3:1" }; |
558 | 565 | ||
559 | static const struct soc_enum max98090_drcexp_enum = | 566 | static SOC_ENUM_SINGLE_DECL(max98090_drcexp_enum, |
560 | SOC_ENUM_SINGLE(M98090_REG_DRC_EXPANDER, M98090_DRCEXP_SHIFT, | 567 | M98090_REG_DRC_EXPANDER, |
561 | ARRAY_SIZE(max98090_drcexp_text), max98090_drcexp_text); | 568 | M98090_DRCEXP_SHIFT, |
569 | max98090_drcexp_text); | ||
562 | 570 | ||
563 | static const struct soc_enum max98090_dac_perfmode_enum = | 571 | static SOC_ENUM_SINGLE_DECL(max98090_dac_perfmode_enum, |
564 | SOC_ENUM_SINGLE(M98090_REG_DAC_CONTROL, M98090_PERFMODE_SHIFT, | 572 | M98090_REG_DAC_CONTROL, |
565 | ARRAY_SIZE(max98090_perf_pwr_text), max98090_perf_pwr_text); | 573 | M98090_PERFMODE_SHIFT, |
574 | max98090_perf_pwr_text); | ||
566 | 575 | ||
567 | static const struct soc_enum max98090_dachp_enum = | 576 | static SOC_ENUM_SINGLE_DECL(max98090_dachp_enum, |
568 | SOC_ENUM_SINGLE(M98090_REG_DAC_CONTROL, M98090_DACHP_SHIFT, | 577 | M98090_REG_DAC_CONTROL, |
569 | ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); | 578 | M98090_DACHP_SHIFT, |
579 | max98090_pwr_perf_text); | ||
570 | 580 | ||
571 | static const struct soc_enum max98090_adchp_enum = | 581 | static SOC_ENUM_SINGLE_DECL(max98090_adchp_enum, |
572 | SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_ADCHP_SHIFT, | 582 | M98090_REG_ADC_CONTROL, |
573 | ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); | 583 | M98090_ADCHP_SHIFT, |
584 | max98090_pwr_perf_text); | ||
574 | 585 | ||
575 | static const struct snd_kcontrol_new max98090_snd_controls[] = { | 586 | static const struct snd_kcontrol_new max98090_snd_controls[] = { |
576 | SOC_ENUM("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum), | 587 | SOC_ENUM("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum), |
@@ -841,39 +852,42 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w, | |||
841 | 852 | ||
842 | static const char *mic1_mux_text[] = { "IN12", "IN56" }; | 853 | static const char *mic1_mux_text[] = { "IN12", "IN56" }; |
843 | 854 | ||
844 | static const struct soc_enum mic1_mux_enum = | 855 | static SOC_ENUM_SINGLE_DECL(mic1_mux_enum, |
845 | SOC_ENUM_SINGLE(M98090_REG_INPUT_MODE, M98090_EXTMIC1_SHIFT, | 856 | M98090_REG_INPUT_MODE, |
846 | ARRAY_SIZE(mic1_mux_text), mic1_mux_text); | 857 | M98090_EXTMIC1_SHIFT, |
858 | mic1_mux_text); | ||
847 | 859 | ||
848 | static const struct snd_kcontrol_new max98090_mic1_mux = | 860 | static const struct snd_kcontrol_new max98090_mic1_mux = |
849 | SOC_DAPM_ENUM("MIC1 Mux", mic1_mux_enum); | 861 | SOC_DAPM_ENUM("MIC1 Mux", mic1_mux_enum); |
850 | 862 | ||
851 | static const char *mic2_mux_text[] = { "IN34", "IN56" }; | 863 | static const char *mic2_mux_text[] = { "IN34", "IN56" }; |
852 | 864 | ||
853 | static const struct soc_enum mic2_mux_enum = | 865 | static SOC_ENUM_SINGLE_DECL(mic2_mux_enum, |
854 | SOC_ENUM_SINGLE(M98090_REG_INPUT_MODE, M98090_EXTMIC2_SHIFT, | 866 | M98090_REG_INPUT_MODE, |
855 | ARRAY_SIZE(mic2_mux_text), mic2_mux_text); | 867 | M98090_EXTMIC2_SHIFT, |
868 | mic2_mux_text); | ||
856 | 869 | ||
857 | static const struct snd_kcontrol_new max98090_mic2_mux = | 870 | static const struct snd_kcontrol_new max98090_mic2_mux = |
858 | SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum); | 871 | SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum); |
859 | 872 | ||
860 | static const char *dmic_mux_text[] = { "ADC", "DMIC" }; | 873 | static const char *dmic_mux_text[] = { "ADC", "DMIC" }; |
861 | 874 | ||
862 | static const struct soc_enum dmic_mux_enum = | 875 | static SOC_ENUM_SINGLE_VIRT_DECL(dmic_mux_enum, dmic_mux_text); |
863 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dmic_mux_text), dmic_mux_text); | ||
864 | 876 | ||
865 | static const struct snd_kcontrol_new max98090_dmic_mux = | 877 | static const struct snd_kcontrol_new max98090_dmic_mux = |
866 | SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum); | 878 | SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum); |
867 | 879 | ||
868 | static const char *max98090_micpre_text[] = { "Off", "On" }; | 880 | static const char *max98090_micpre_text[] = { "Off", "On" }; |
869 | 881 | ||
870 | static const struct soc_enum max98090_pa1en_enum = | 882 | static SOC_ENUM_SINGLE_DECL(max98090_pa1en_enum, |
871 | SOC_ENUM_SINGLE(M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT, | 883 | M98090_REG_MIC1_INPUT_LEVEL, |
872 | ARRAY_SIZE(max98090_micpre_text), max98090_micpre_text); | 884 | M98090_MIC_PA1EN_SHIFT, |
885 | max98090_micpre_text); | ||
873 | 886 | ||
874 | static const struct soc_enum max98090_pa2en_enum = | 887 | static SOC_ENUM_SINGLE_DECL(max98090_pa2en_enum, |
875 | SOC_ENUM_SINGLE(M98090_REG_MIC2_INPUT_LEVEL, M98090_MIC_PA2EN_SHIFT, | 888 | M98090_REG_MIC2_INPUT_LEVEL, |
876 | ARRAY_SIZE(max98090_micpre_text), max98090_micpre_text); | 889 | M98090_MIC_PA2EN_SHIFT, |
890 | max98090_micpre_text); | ||
877 | 891 | ||
878 | /* LINEA mixer switch */ | 892 | /* LINEA mixer switch */ |
879 | static const struct snd_kcontrol_new max98090_linea_mixer_controls[] = { | 893 | static const struct snd_kcontrol_new max98090_linea_mixer_controls[] = { |
@@ -937,13 +951,15 @@ static const struct snd_kcontrol_new max98090_right_adc_mixer_controls[] = { | |||
937 | 951 | ||
938 | static const char *lten_mux_text[] = { "Normal", "Loopthrough" }; | 952 | static const char *lten_mux_text[] = { "Normal", "Loopthrough" }; |
939 | 953 | ||
940 | static const struct soc_enum ltenl_mux_enum = | 954 | static SOC_ENUM_SINGLE_DECL(ltenl_mux_enum, |
941 | SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LTEN_SHIFT, | 955 | M98090_REG_IO_CONFIGURATION, |
942 | ARRAY_SIZE(lten_mux_text), lten_mux_text); | 956 | M98090_LTEN_SHIFT, |
957 | lten_mux_text); | ||
943 | 958 | ||
944 | static const struct soc_enum ltenr_mux_enum = | 959 | static SOC_ENUM_SINGLE_DECL(ltenr_mux_enum, |
945 | SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LTEN_SHIFT, | 960 | M98090_REG_IO_CONFIGURATION, |
946 | ARRAY_SIZE(lten_mux_text), lten_mux_text); | 961 | M98090_LTEN_SHIFT, |
962 | lten_mux_text); | ||
947 | 963 | ||
948 | static const struct snd_kcontrol_new max98090_ltenl_mux = | 964 | static const struct snd_kcontrol_new max98090_ltenl_mux = |
949 | SOC_DAPM_ENUM("LTENL Mux", ltenl_mux_enum); | 965 | SOC_DAPM_ENUM("LTENL Mux", ltenl_mux_enum); |
@@ -953,13 +969,15 @@ static const struct snd_kcontrol_new max98090_ltenr_mux = | |||
953 | 969 | ||
954 | static const char *lben_mux_text[] = { "Normal", "Loopback" }; | 970 | static const char *lben_mux_text[] = { "Normal", "Loopback" }; |
955 | 971 | ||
956 | static const struct soc_enum lbenl_mux_enum = | 972 | static SOC_ENUM_SINGLE_DECL(lbenl_mux_enum, |
957 | SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LBEN_SHIFT, | 973 | M98090_REG_IO_CONFIGURATION, |
958 | ARRAY_SIZE(lben_mux_text), lben_mux_text); | 974 | M98090_LBEN_SHIFT, |
975 | lben_mux_text); | ||
959 | 976 | ||
960 | static const struct soc_enum lbenr_mux_enum = | 977 | static SOC_ENUM_SINGLE_DECL(lbenr_mux_enum, |
961 | SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LBEN_SHIFT, | 978 | M98090_REG_IO_CONFIGURATION, |
962 | ARRAY_SIZE(lben_mux_text), lben_mux_text); | 979 | M98090_LBEN_SHIFT, |
980 | lben_mux_text); | ||
963 | 981 | ||
964 | static const struct snd_kcontrol_new max98090_lbenl_mux = | 982 | static const struct snd_kcontrol_new max98090_lbenl_mux = |
965 | SOC_DAPM_ENUM("LBENL Mux", lbenl_mux_enum); | 983 | SOC_DAPM_ENUM("LBENL Mux", lbenl_mux_enum); |
@@ -971,13 +989,15 @@ static const char *stenl_mux_text[] = { "Normal", "Sidetone Left" }; | |||
971 | 989 | ||
972 | static const char *stenr_mux_text[] = { "Normal", "Sidetone Right" }; | 990 | static const char *stenr_mux_text[] = { "Normal", "Sidetone Right" }; |
973 | 991 | ||
974 | static const struct soc_enum stenl_mux_enum = | 992 | static SOC_ENUM_SINGLE_DECL(stenl_mux_enum, |
975 | SOC_ENUM_SINGLE(M98090_REG_ADC_SIDETONE, M98090_DSTSL_SHIFT, | 993 | M98090_REG_ADC_SIDETONE, |
976 | ARRAY_SIZE(stenl_mux_text), stenl_mux_text); | 994 | M98090_DSTSL_SHIFT, |
995 | stenl_mux_text); | ||
977 | 996 | ||
978 | static const struct soc_enum stenr_mux_enum = | 997 | static SOC_ENUM_SINGLE_DECL(stenr_mux_enum, |
979 | SOC_ENUM_SINGLE(M98090_REG_ADC_SIDETONE, M98090_DSTSR_SHIFT, | 998 | M98090_REG_ADC_SIDETONE, |
980 | ARRAY_SIZE(stenr_mux_text), stenr_mux_text); | 999 | M98090_DSTSR_SHIFT, |
1000 | stenr_mux_text); | ||
981 | 1001 | ||
982 | static const struct snd_kcontrol_new max98090_stenl_mux = | 1002 | static const struct snd_kcontrol_new max98090_stenl_mux = |
983 | SOC_DAPM_ENUM("STENL Mux", stenl_mux_enum); | 1003 | SOC_DAPM_ENUM("STENL Mux", stenl_mux_enum); |
@@ -1085,9 +1105,10 @@ static const struct snd_kcontrol_new max98090_right_rcv_mixer_controls[] = { | |||
1085 | 1105 | ||
1086 | static const char *linmod_mux_text[] = { "Left Only", "Left and Right" }; | 1106 | static const char *linmod_mux_text[] = { "Left Only", "Left and Right" }; |
1087 | 1107 | ||
1088 | static const struct soc_enum linmod_mux_enum = | 1108 | static SOC_ENUM_SINGLE_DECL(linmod_mux_enum, |
1089 | SOC_ENUM_SINGLE(M98090_REG_LOUTR_MIXER, M98090_LINMOD_SHIFT, | 1109 | M98090_REG_LOUTR_MIXER, |
1090 | ARRAY_SIZE(linmod_mux_text), linmod_mux_text); | 1110 | M98090_LINMOD_SHIFT, |
1111 | linmod_mux_text); | ||
1091 | 1112 | ||
1092 | static const struct snd_kcontrol_new max98090_linmod_mux = | 1113 | static const struct snd_kcontrol_new max98090_linmod_mux = |
1093 | SOC_DAPM_ENUM("LINMOD Mux", linmod_mux_enum); | 1114 | SOC_DAPM_ENUM("LINMOD Mux", linmod_mux_enum); |
@@ -1097,16 +1118,18 @@ static const char *mixhpsel_mux_text[] = { "DAC Only", "HP Mixer" }; | |||
1097 | /* | 1118 | /* |
1098 | * This is a mux as it selects the HP output, but to DAPM it is a Mixer enable | 1119 | * This is a mux as it selects the HP output, but to DAPM it is a Mixer enable |
1099 | */ | 1120 | */ |
1100 | static const struct soc_enum mixhplsel_mux_enum = | 1121 | static SOC_ENUM_SINGLE_DECL(mixhplsel_mux_enum, |
1101 | SOC_ENUM_SINGLE(M98090_REG_HP_CONTROL, M98090_MIXHPLSEL_SHIFT, | 1122 | M98090_REG_HP_CONTROL, |
1102 | ARRAY_SIZE(mixhpsel_mux_text), mixhpsel_mux_text); | 1123 | M98090_MIXHPLSEL_SHIFT, |
1124 | mixhpsel_mux_text); | ||
1103 | 1125 | ||
1104 | static const struct snd_kcontrol_new max98090_mixhplsel_mux = | 1126 | static const struct snd_kcontrol_new max98090_mixhplsel_mux = |
1105 | SOC_DAPM_ENUM("MIXHPLSEL Mux", mixhplsel_mux_enum); | 1127 | SOC_DAPM_ENUM("MIXHPLSEL Mux", mixhplsel_mux_enum); |
1106 | 1128 | ||
1107 | static const struct soc_enum mixhprsel_mux_enum = | 1129 | static SOC_ENUM_SINGLE_DECL(mixhprsel_mux_enum, |
1108 | SOC_ENUM_SINGLE(M98090_REG_HP_CONTROL, M98090_MIXHPRSEL_SHIFT, | 1130 | M98090_REG_HP_CONTROL, |
1109 | ARRAY_SIZE(mixhpsel_mux_text), mixhpsel_mux_text); | 1131 | M98090_MIXHPRSEL_SHIFT, |
1132 | mixhpsel_mux_text); | ||
1110 | 1133 | ||
1111 | static const struct snd_kcontrol_new max98090_mixhprsel_mux = | 1134 | static const struct snd_kcontrol_new max98090_mixhprsel_mux = |
1112 | SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum); | 1135 | SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum); |
@@ -1769,16 +1792,6 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec, | |||
1769 | 1792 | ||
1770 | switch (level) { | 1793 | switch (level) { |
1771 | case SND_SOC_BIAS_ON: | 1794 | case SND_SOC_BIAS_ON: |
1772 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
1773 | ret = regcache_sync(max98090->regmap); | ||
1774 | |||
1775 | if (ret != 0) { | ||
1776 | dev_err(codec->dev, | ||
1777 | "Failed to sync cache: %d\n", ret); | ||
1778 | return ret; | ||
1779 | } | ||
1780 | } | ||
1781 | |||
1782 | if (max98090->jack_state == M98090_JACK_STATE_HEADSET) { | 1795 | if (max98090->jack_state == M98090_JACK_STATE_HEADSET) { |
1783 | /* | 1796 | /* |
1784 | * Set to normal bias level. | 1797 | * Set to normal bias level. |
@@ -1792,6 +1805,16 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec, | |||
1792 | break; | 1805 | break; |
1793 | 1806 | ||
1794 | case SND_SOC_BIAS_STANDBY: | 1807 | case SND_SOC_BIAS_STANDBY: |
1808 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
1809 | ret = regcache_sync(max98090->regmap); | ||
1810 | if (ret != 0) { | ||
1811 | dev_err(codec->dev, | ||
1812 | "Failed to sync cache: %d\n", ret); | ||
1813 | return ret; | ||
1814 | } | ||
1815 | } | ||
1816 | break; | ||
1817 | |||
1795 | case SND_SOC_BIAS_OFF: | 1818 | case SND_SOC_BIAS_OFF: |
1796 | /* Set internal pull-up to lowest power mode */ | 1819 | /* Set internal pull-up to lowest power mode */ |
1797 | snd_soc_update_bits(codec, M98090_REG_JACK_DETECT, | 1820 | snd_soc_update_bits(codec, M98090_REG_JACK_DETECT, |
@@ -2195,14 +2218,6 @@ static int max98090_probe(struct snd_soc_codec *codec) | |||
2195 | 2218 | ||
2196 | max98090->codec = codec; | 2219 | max98090->codec = codec; |
2197 | 2220 | ||
2198 | codec->control_data = max98090->regmap; | ||
2199 | |||
2200 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
2201 | if (ret != 0) { | ||
2202 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
2203 | return ret; | ||
2204 | } | ||
2205 | |||
2206 | /* Reset the codec, the DSP core, and disable all interrupts */ | 2221 | /* Reset the codec, the DSP core, and disable all interrupts */ |
2207 | max98090_reset(max98090); | 2222 | max98090_reset(max98090); |
2208 | 2223 | ||
@@ -2328,7 +2343,6 @@ static int max98090_i2c_probe(struct i2c_client *i2c, | |||
2328 | 2343 | ||
2329 | max98090->devtype = id->driver_data; | 2344 | max98090->devtype = id->driver_data; |
2330 | i2c_set_clientdata(i2c, max98090); | 2345 | i2c_set_clientdata(i2c, max98090); |
2331 | max98090->control_data = i2c; | ||
2332 | max98090->pdata = i2c->dev.platform_data; | 2346 | max98090->pdata = i2c->dev.platform_data; |
2333 | max98090->irq = i2c->irq; | 2347 | max98090->irq = i2c->irq; |
2334 | 2348 | ||
diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h index 7e103f249053..1a4e2334a7b2 100644 --- a/sound/soc/codecs/max98090.h +++ b/sound/soc/codecs/max98090.h | |||
@@ -1523,7 +1523,6 @@ struct max98090_priv { | |||
1523 | struct regmap *regmap; | 1523 | struct regmap *regmap; |
1524 | struct snd_soc_codec *codec; | 1524 | struct snd_soc_codec *codec; |
1525 | enum max98090_type devtype; | 1525 | enum max98090_type devtype; |
1526 | void *control_data; | ||
1527 | struct max98090_pdata *pdata; | 1526 | struct max98090_pdata *pdata; |
1528 | unsigned int sysclk; | 1527 | unsigned int sysclk; |
1529 | unsigned int bclk; | 1528 | unsigned int bclk; |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 3ba1170ebb53..03f0536e6f61 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c | |||
@@ -560,25 +560,27 @@ static void m98095_biquad_band(struct snd_soc_codec *codec, unsigned int dai, | |||
560 | } | 560 | } |
561 | 561 | ||
562 | static const char * const max98095_fltr_mode[] = { "Voice", "Music" }; | 562 | static const char * const max98095_fltr_mode[] = { "Voice", "Music" }; |
563 | static const struct soc_enum max98095_dai1_filter_mode_enum[] = { | 563 | static SOC_ENUM_SINGLE_DECL(max98095_dai1_filter_mode_enum, |
564 | SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 7, 2, max98095_fltr_mode), | 564 | M98095_02E_DAI1_FILTERS, 7, |
565 | }; | 565 | max98095_fltr_mode); |
566 | static const struct soc_enum max98095_dai2_filter_mode_enum[] = { | 566 | static SOC_ENUM_SINGLE_DECL(max98095_dai2_filter_mode_enum, |
567 | SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 7, 2, max98095_fltr_mode), | 567 | M98095_038_DAI2_FILTERS, 7, |
568 | }; | 568 | max98095_fltr_mode); |
569 | 569 | ||
570 | static const char * const max98095_extmic_text[] = { "None", "MIC1", "MIC2" }; | 570 | static const char * const max98095_extmic_text[] = { "None", "MIC1", "MIC2" }; |
571 | 571 | ||
572 | static const struct soc_enum max98095_extmic_enum = | 572 | static SOC_ENUM_SINGLE_DECL(max98095_extmic_enum, |
573 | SOC_ENUM_SINGLE(M98095_087_CFG_MIC, 0, 3, max98095_extmic_text); | 573 | M98095_087_CFG_MIC, 0, |
574 | max98095_extmic_text); | ||
574 | 575 | ||
575 | static const struct snd_kcontrol_new max98095_extmic_mux = | 576 | static const struct snd_kcontrol_new max98095_extmic_mux = |
576 | SOC_DAPM_ENUM("External MIC Mux", max98095_extmic_enum); | 577 | SOC_DAPM_ENUM("External MIC Mux", max98095_extmic_enum); |
577 | 578 | ||
578 | static const char * const max98095_linein_text[] = { "INA", "INB" }; | 579 | static const char * const max98095_linein_text[] = { "INA", "INB" }; |
579 | 580 | ||
580 | static const struct soc_enum max98095_linein_enum = | 581 | static SOC_ENUM_SINGLE_DECL(max98095_linein_enum, |
581 | SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 6, 2, max98095_linein_text); | 582 | M98095_086_CFG_LINE, 6, |
583 | max98095_linein_text); | ||
582 | 584 | ||
583 | static const struct snd_kcontrol_new max98095_linein_mux = | 585 | static const struct snd_kcontrol_new max98095_linein_mux = |
584 | SOC_DAPM_ENUM("Linein Input Mux", max98095_linein_enum); | 586 | SOC_DAPM_ENUM("Linein Input Mux", max98095_linein_enum); |
@@ -586,24 +588,26 @@ static const struct snd_kcontrol_new max98095_linein_mux = | |||
586 | static const char * const max98095_line_mode_text[] = { | 588 | static const char * const max98095_line_mode_text[] = { |
587 | "Stereo", "Differential"}; | 589 | "Stereo", "Differential"}; |
588 | 590 | ||
589 | static const struct soc_enum max98095_linein_mode_enum = | 591 | static SOC_ENUM_SINGLE_DECL(max98095_linein_mode_enum, |
590 | SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 7, 2, max98095_line_mode_text); | 592 | M98095_086_CFG_LINE, 7, |
593 | max98095_line_mode_text); | ||
591 | 594 | ||
592 | static const struct soc_enum max98095_lineout_mode_enum = | 595 | static SOC_ENUM_SINGLE_DECL(max98095_lineout_mode_enum, |
593 | SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 4, 2, max98095_line_mode_text); | 596 | M98095_086_CFG_LINE, 4, |
597 | max98095_line_mode_text); | ||
594 | 598 | ||
595 | static const char * const max98095_dai_fltr[] = { | 599 | static const char * const max98095_dai_fltr[] = { |
596 | "Off", "Elliptical-HPF-16k", "Butterworth-HPF-16k", | 600 | "Off", "Elliptical-HPF-16k", "Butterworth-HPF-16k", |
597 | "Elliptical-HPF-8k", "Butterworth-HPF-8k", "Butterworth-HPF-Fs/240"}; | 601 | "Elliptical-HPF-8k", "Butterworth-HPF-8k", "Butterworth-HPF-Fs/240"}; |
598 | static const struct soc_enum max98095_dai1_dac_filter_enum[] = { | 602 | static SOC_ENUM_SINGLE_DECL(max98095_dai1_dac_filter_enum, |
599 | SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 0, 6, max98095_dai_fltr), | 603 | M98095_02E_DAI1_FILTERS, 0, |
600 | }; | 604 | max98095_dai_fltr); |
601 | static const struct soc_enum max98095_dai2_dac_filter_enum[] = { | 605 | static SOC_ENUM_SINGLE_DECL(max98095_dai2_dac_filter_enum, |
602 | SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 0, 6, max98095_dai_fltr), | 606 | M98095_038_DAI2_FILTERS, 0, |
603 | }; | 607 | max98095_dai_fltr); |
604 | static const struct soc_enum max98095_dai3_dac_filter_enum[] = { | 608 | static SOC_ENUM_SINGLE_DECL(max98095_dai3_dac_filter_enum, |
605 | SOC_ENUM_SINGLE(M98095_042_DAI3_FILTERS, 0, 6, max98095_dai_fltr), | 609 | M98095_042_DAI3_FILTERS, 0, |
606 | }; | 610 | max98095_dai_fltr); |
607 | 611 | ||
608 | static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol, | 612 | static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol, |
609 | struct snd_ctl_elem_value *ucontrol) | 613 | struct snd_ctl_elem_value *ucontrol) |
@@ -1861,7 +1865,7 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec) | |||
1861 | 1865 | ||
1862 | /* Now point the soc_enum to .texts array items */ | 1866 | /* Now point the soc_enum to .texts array items */ |
1863 | max98095->eq_enum.texts = max98095->eq_texts; | 1867 | max98095->eq_enum.texts = max98095->eq_texts; |
1864 | max98095->eq_enum.max = max98095->eq_textcnt; | 1868 | max98095->eq_enum.items = max98095->eq_textcnt; |
1865 | 1869 | ||
1866 | ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); | 1870 | ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); |
1867 | if (ret != 0) | 1871 | if (ret != 0) |
@@ -2016,7 +2020,7 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec) | |||
2016 | 2020 | ||
2017 | /* Now point the soc_enum to .texts array items */ | 2021 | /* Now point the soc_enum to .texts array items */ |
2018 | max98095->bq_enum.texts = max98095->bq_texts; | 2022 | max98095->bq_enum.texts = max98095->bq_texts; |
2019 | max98095->bq_enum.max = max98095->bq_textcnt; | 2023 | max98095->bq_enum.items = max98095->bq_textcnt; |
2020 | 2024 | ||
2021 | ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); | 2025 | ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); |
2022 | if (ret != 0) | 2026 | if (ret != 0) |
@@ -2234,12 +2238,6 @@ static int max98095_probe(struct snd_soc_codec *codec) | |||
2234 | struct i2c_client *client; | 2238 | struct i2c_client *client; |
2235 | int ret = 0; | 2239 | int ret = 0; |
2236 | 2240 | ||
2237 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
2238 | if (ret != 0) { | ||
2239 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
2240 | return ret; | ||
2241 | } | ||
2242 | |||
2243 | /* reset the codec, the DSP core, and disable all interrupts */ | 2241 | /* reset the codec, the DSP core, and disable all interrupts */ |
2244 | max98095_reset(codec); | 2242 | max98095_reset(codec); |
2245 | 2243 | ||
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 82757ebf0301..4fdf5aaa236f 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c | |||
@@ -312,14 +312,6 @@ static int max9850_resume(struct snd_soc_codec *codec) | |||
312 | 312 | ||
313 | static int max9850_probe(struct snd_soc_codec *codec) | 313 | static int max9850_probe(struct snd_soc_codec *codec) |
314 | { | 314 | { |
315 | int ret; | ||
316 | |||
317 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
318 | if (ret < 0) { | ||
319 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
320 | return ret; | ||
321 | } | ||
322 | |||
323 | /* enable zero-detect */ | 315 | /* enable zero-detect */ |
324 | snd_soc_update_bits(codec, MAX9850_GENERAL_PURPOSE, 1, 1); | 316 | snd_soc_update_bits(codec, MAX9850_GENERAL_PURPOSE, 1, 1); |
325 | /* enable slew-rate control */ | 317 | /* enable slew-rate control */ |
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 582c2bbd42cb..2c59b1fb69dc 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c | |||
@@ -106,8 +106,7 @@ static int mc13783_pcm_hw_params_dac(struct snd_pcm_substream *substream, | |||
106 | struct snd_pcm_hw_params *params, | 106 | struct snd_pcm_hw_params *params, |
107 | struct snd_soc_dai *dai) | 107 | struct snd_soc_dai *dai) |
108 | { | 108 | { |
109 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 109 | struct snd_soc_codec *codec = dai->codec; |
110 | struct snd_soc_codec *codec = rtd->codec; | ||
111 | unsigned int rate = params_rate(params); | 110 | unsigned int rate = params_rate(params); |
112 | int i; | 111 | int i; |
113 | 112 | ||
@@ -126,8 +125,7 @@ static int mc13783_pcm_hw_params_codec(struct snd_pcm_substream *substream, | |||
126 | struct snd_pcm_hw_params *params, | 125 | struct snd_pcm_hw_params *params, |
127 | struct snd_soc_dai *dai) | 126 | struct snd_soc_dai *dai) |
128 | { | 127 | { |
129 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 128 | struct snd_soc_codec *codec = dai->codec; |
130 | struct snd_soc_codec *codec = rtd->codec; | ||
131 | unsigned int rate = params_rate(params); | 129 | unsigned int rate = params_rate(params); |
132 | unsigned int val; | 130 | unsigned int val; |
133 | 131 | ||
@@ -408,8 +406,7 @@ static const char * const adcl_enum_text[] = { | |||
408 | "MC1L", "RXINL", | 406 | "MC1L", "RXINL", |
409 | }; | 407 | }; |
410 | 408 | ||
411 | static const struct soc_enum adcl_enum = | 409 | static SOC_ENUM_SINGLE_VIRT_DECL(adcl_enum, adcl_enum_text); |
412 | SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcl_enum_text), adcl_enum_text); | ||
413 | 410 | ||
414 | static const struct snd_kcontrol_new left_input_mux = | 411 | static const struct snd_kcontrol_new left_input_mux = |
415 | SOC_DAPM_ENUM_VIRT("Route", adcl_enum); | 412 | SOC_DAPM_ENUM_VIRT("Route", adcl_enum); |
@@ -418,8 +415,7 @@ static const char * const adcr_enum_text[] = { | |||
418 | "MC1R", "MC2", "RXINR", "TXIN", | 415 | "MC1R", "MC2", "RXINR", "TXIN", |
419 | }; | 416 | }; |
420 | 417 | ||
421 | static const struct soc_enum adcr_enum = | 418 | static SOC_ENUM_SINGLE_VIRT_DECL(adcr_enum, adcr_enum_text); |
422 | SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcr_enum_text), adcr_enum_text); | ||
423 | 419 | ||
424 | static const struct snd_kcontrol_new right_input_mux = | 420 | static const struct snd_kcontrol_new right_input_mux = |
425 | SOC_DAPM_ENUM_VIRT("Route", adcr_enum); | 421 | SOC_DAPM_ENUM_VIRT("Route", adcr_enum); |
@@ -430,8 +426,8 @@ static const struct snd_kcontrol_new samp_ctl = | |||
430 | static const char * const speaker_amp_source_text[] = { | 426 | static const char * const speaker_amp_source_text[] = { |
431 | "CODEC", "Right" | 427 | "CODEC", "Right" |
432 | }; | 428 | }; |
433 | static const SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4, | 429 | static SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4, |
434 | speaker_amp_source_text); | 430 | speaker_amp_source_text); |
435 | static const struct snd_kcontrol_new speaker_amp_source_mux = | 431 | static const struct snd_kcontrol_new speaker_amp_source_mux = |
436 | SOC_DAPM_ENUM("Speaker Amp Source MUX", speaker_amp_source); | 432 | SOC_DAPM_ENUM("Speaker Amp Source MUX", speaker_amp_source); |
437 | 433 | ||
@@ -439,8 +435,8 @@ static const char * const headset_amp_source_text[] = { | |||
439 | "CODEC", "Mixer" | 435 | "CODEC", "Mixer" |
440 | }; | 436 | }; |
441 | 437 | ||
442 | static const SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11, | 438 | static SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11, |
443 | headset_amp_source_text); | 439 | headset_amp_source_text); |
444 | static const struct snd_kcontrol_new headset_amp_source_mux = | 440 | static const struct snd_kcontrol_new headset_amp_source_mux = |
445 | SOC_DAPM_ENUM("Headset Amp Source MUX", headset_amp_source); | 441 | SOC_DAPM_ENUM("Headset Amp Source MUX", headset_amp_source); |
446 | 442 | ||
@@ -580,9 +576,9 @@ static struct snd_soc_dapm_route mc13783_routes[] = { | |||
580 | static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix", | 576 | static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix", |
581 | "Mono", "Mono Mix"}; | 577 | "Mono", "Mono Mix"}; |
582 | 578 | ||
583 | static const struct soc_enum mc13783_enum_3d_mixer = | 579 | static SOC_ENUM_SINGLE_DECL(mc13783_enum_3d_mixer, |
584 | SOC_ENUM_SINGLE(MC13783_AUDIO_RX1, 16, ARRAY_SIZE(mc13783_3d_mixer), | 580 | MC13783_AUDIO_RX1, 16, |
585 | mc13783_3d_mixer); | 581 | mc13783_3d_mixer); |
586 | 582 | ||
587 | static struct snd_kcontrol_new mc13783_control_list[] = { | 583 | static struct snd_kcontrol_new mc13783_control_list[] = { |
588 | SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0), | 584 | SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0), |
@@ -614,8 +610,8 @@ static int mc13783_probe(struct snd_soc_codec *codec) | |||
614 | struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); | 610 | struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); |
615 | int ret; | 611 | int ret; |
616 | 612 | ||
617 | codec->control_data = dev_get_regmap(codec->dev->parent, NULL); | 613 | ret = snd_soc_codec_set_cache_io(codec, |
618 | ret = snd_soc_codec_set_cache_io(codec, 8, 24, SND_SOC_REGMAP); | 614 | dev_get_regmap(codec->dev->parent, NULL)); |
619 | if (ret != 0) { | 615 | if (ret != 0) { |
620 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 616 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
621 | return ret; | 617 | return ret; |
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 185fa3bc3052..e661e8420e3d 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c | |||
@@ -73,11 +73,11 @@ static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0); | |||
73 | static const char * const ml26124_companding[] = {"16bit PCM", "u-law", | 73 | static const char * const ml26124_companding[] = {"16bit PCM", "u-law", |
74 | "A-law"}; | 74 | "A-law"}; |
75 | 75 | ||
76 | static const struct soc_enum ml26124_adc_companding_enum | 76 | static SOC_ENUM_SINGLE_DECL(ml26124_adc_companding_enum, |
77 | = SOC_ENUM_SINGLE(ML26124_SAI_TRANS_CTL, 6, 3, ml26124_companding); | 77 | ML26124_SAI_TRANS_CTL, 6, ml26124_companding); |
78 | 78 | ||
79 | static const struct soc_enum ml26124_dac_companding_enum | 79 | static SOC_ENUM_SINGLE_DECL(ml26124_dac_companding_enum, |
80 | = SOC_ENUM_SINGLE(ML26124_SAI_RCV_CTL, 6, 3, ml26124_companding); | 80 | ML26124_SAI_RCV_CTL, 6, ml26124_companding); |
81 | 81 | ||
82 | static const struct snd_kcontrol_new ml26124_snd_controls[] = { | 82 | static const struct snd_kcontrol_new ml26124_snd_controls[] = { |
83 | SOC_SINGLE_TLV("Capture Digital Volume", ML26124_RECORD_DIG_VOL, 0, | 83 | SOC_SINGLE_TLV("Capture Digital Volume", ML26124_RECORD_DIG_VOL, 0, |
@@ -136,8 +136,8 @@ static const struct snd_kcontrol_new ml26124_output_mixer_controls[] = { | |||
136 | static const char * const ml26124_input_select[] = {"Analog MIC SingleEnded in", | 136 | static const char * const ml26124_input_select[] = {"Analog MIC SingleEnded in", |
137 | "Digital MIC in", "Analog MIC Differential in"}; | 137 | "Digital MIC in", "Analog MIC Differential in"}; |
138 | 138 | ||
139 | static const struct soc_enum ml26124_insel_enum = | 139 | static SOC_ENUM_SINGLE_DECL(ml26124_insel_enum, |
140 | SOC_ENUM_SINGLE(ML26124_MIC_IF_CTL, 0, 3, ml26124_input_select); | 140 | ML26124_MIC_IF_CTL, 0, ml26124_input_select); |
141 | 141 | ||
142 | static const struct snd_kcontrol_new ml26124_input_mux_controls = | 142 | static const struct snd_kcontrol_new ml26124_input_mux_controls = |
143 | SOC_DAPM_ENUM("Input Select", ml26124_insel_enum); | 143 | SOC_DAPM_ENUM("Input Select", ml26124_insel_enum); |
@@ -586,16 +586,6 @@ static int ml26124_resume(struct snd_soc_codec *codec) | |||
586 | 586 | ||
587 | static int ml26124_probe(struct snd_soc_codec *codec) | 587 | static int ml26124_probe(struct snd_soc_codec *codec) |
588 | { | 588 | { |
589 | int ret; | ||
590 | struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
591 | codec->control_data = priv->regmap; | ||
592 | |||
593 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
594 | if (ret < 0) { | ||
595 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
596 | return ret; | ||
597 | } | ||
598 | |||
599 | /* Software Reset */ | 589 | /* Software Reset */ |
600 | snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 1); | 590 | snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 1); |
601 | snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 0); | 591 | snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 0); |
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index 73f9c3630e2c..e427544183d7 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c | |||
@@ -172,16 +172,21 @@ static int pcm1681_hw_params(struct snd_pcm_substream *substream, | |||
172 | struct snd_soc_codec *codec = dai->codec; | 172 | struct snd_soc_codec *codec = dai->codec; |
173 | struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); | 173 | struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); |
174 | int val = 0, ret; | 174 | int val = 0, ret; |
175 | int pcm_format = params_format(params); | ||
176 | 175 | ||
177 | priv->rate = params_rate(params); | 176 | priv->rate = params_rate(params); |
178 | 177 | ||
179 | switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { | 178 | switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { |
180 | case SND_SOC_DAIFMT_RIGHT_J: | 179 | case SND_SOC_DAIFMT_RIGHT_J: |
181 | if (pcm_format == SNDRV_PCM_FORMAT_S24_LE) | 180 | switch (params_width(params)) { |
182 | val = 0x00; | 181 | case 24: |
183 | else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) | 182 | val = 0; |
184 | val = 0x03; | 183 | break; |
184 | case 16: | ||
185 | val = 3; | ||
186 | break; | ||
187 | default: | ||
188 | return -EINVAL; | ||
189 | } | ||
185 | break; | 190 | break; |
186 | case SND_SOC_DAIFMT_I2S: | 191 | case SND_SOC_DAIFMT_I2S: |
187 | val = 0x04; | 192 | val = 0x04; |
diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c index 7146653a8e16..3a80ba4452df 100644 --- a/sound/soc/codecs/pcm1792a.c +++ b/sound/soc/codecs/pcm1792a.c | |||
@@ -107,24 +107,35 @@ static int pcm1792a_hw_params(struct snd_pcm_substream *substream, | |||
107 | struct snd_soc_codec *codec = dai->codec; | 107 | struct snd_soc_codec *codec = dai->codec; |
108 | struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec); | 108 | struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec); |
109 | int val = 0, ret; | 109 | int val = 0, ret; |
110 | int pcm_format = params_format(params); | ||
111 | 110 | ||
112 | priv->rate = params_rate(params); | 111 | priv->rate = params_rate(params); |
113 | 112 | ||
114 | switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { | 113 | switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { |
115 | case SND_SOC_DAIFMT_RIGHT_J: | 114 | case SND_SOC_DAIFMT_RIGHT_J: |
116 | if (pcm_format == SNDRV_PCM_FORMAT_S24_LE || | 115 | switch (params_width(params)) { |
117 | pcm_format == SNDRV_PCM_FORMAT_S32_LE) | 116 | case 24: |
118 | val = 0x02; | 117 | case 32: |
119 | else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) | 118 | val = 2; |
120 | val = 0x00; | 119 | break; |
120 | case 16: | ||
121 | val = 0; | ||
122 | break; | ||
123 | default: | ||
124 | return -EINVAL; | ||
125 | } | ||
121 | break; | 126 | break; |
122 | case SND_SOC_DAIFMT_I2S: | 127 | case SND_SOC_DAIFMT_I2S: |
123 | if (pcm_format == SNDRV_PCM_FORMAT_S24_LE || | 128 | switch (params_width(params)) { |
124 | pcm_format == SNDRV_PCM_FORMAT_S32_LE) | 129 | case 24: |
125 | val = 0x05; | 130 | case 32: |
126 | else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) | 131 | val = 5; |
127 | val = 0x04; | 132 | break; |
133 | case 16: | ||
134 | val = 4; | ||
135 | break; | ||
136 | default: | ||
137 | return -EINVAL; | ||
138 | } | ||
128 | break; | 139 | break; |
129 | default: | 140 | default: |
130 | dev_err(codec->dev, "Invalid DAI format\n"); | 141 | dev_err(codec->dev, "Invalid DAI format\n"); |
diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c new file mode 100644 index 000000000000..4d62230bd378 --- /dev/null +++ b/sound/soc/codecs/pcm512x-i2c.c | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * Driver for the PCM512x CODECs | ||
3 | * | ||
4 | * Author: Mark Brown <broonie@linaro.org> | ||
5 | * Copyright 2014 Linaro Ltd | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/i2c.h> | ||
20 | |||
21 | #include "pcm512x.h" | ||
22 | |||
23 | static int pcm512x_i2c_probe(struct i2c_client *i2c, | ||
24 | const struct i2c_device_id *id) | ||
25 | { | ||
26 | struct regmap *regmap; | ||
27 | |||
28 | regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap); | ||
29 | if (IS_ERR(regmap)) | ||
30 | return PTR_ERR(regmap); | ||
31 | |||
32 | return pcm512x_probe(&i2c->dev, regmap); | ||
33 | } | ||
34 | |||
35 | static int pcm512x_i2c_remove(struct i2c_client *i2c) | ||
36 | { | ||
37 | pcm512x_remove(&i2c->dev); | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static const struct i2c_device_id pcm512x_i2c_id[] = { | ||
42 | { "pcm5121", }, | ||
43 | { "pcm5122", }, | ||
44 | { } | ||
45 | }; | ||
46 | MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); | ||
47 | |||
48 | static const struct of_device_id pcm512x_of_match[] = { | ||
49 | { .compatible = "ti,pcm5121", }, | ||
50 | { .compatible = "ti,pcm5122", }, | ||
51 | { } | ||
52 | }; | ||
53 | MODULE_DEVICE_TABLE(of, pcm512x_of_match); | ||
54 | |||
55 | static struct i2c_driver pcm512x_i2c_driver = { | ||
56 | .probe = pcm512x_i2c_probe, | ||
57 | .remove = pcm512x_i2c_remove, | ||
58 | .id_table = pcm512x_i2c_id, | ||
59 | .driver = { | ||
60 | .name = "pcm512x", | ||
61 | .owner = THIS_MODULE, | ||
62 | .of_match_table = pcm512x_of_match, | ||
63 | .pm = &pcm512x_pm_ops, | ||
64 | }, | ||
65 | }; | ||
66 | |||
67 | module_i2c_driver(pcm512x_i2c_driver); | ||
68 | |||
69 | MODULE_DESCRIPTION("ASoC PCM512x codec driver - I2C"); | ||
70 | MODULE_AUTHOR("Mark Brown <broonie@linaro.org>"); | ||
71 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/pcm512x-spi.c b/sound/soc/codecs/pcm512x-spi.c new file mode 100644 index 000000000000..f297058c0038 --- /dev/null +++ b/sound/soc/codecs/pcm512x-spi.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * Driver for the PCM512x CODECs | ||
3 | * | ||
4 | * Author: Mark Brown <broonie@linaro.org> | ||
5 | * Copyright 2014 Linaro Ltd | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/spi/spi.h> | ||
20 | |||
21 | #include "pcm512x.h" | ||
22 | |||
23 | static int pcm512x_spi_probe(struct spi_device *spi) | ||
24 | { | ||
25 | struct regmap *regmap; | ||
26 | int ret; | ||
27 | |||
28 | regmap = devm_regmap_init_spi(spi, &pcm512x_regmap); | ||
29 | if (IS_ERR(regmap)) { | ||
30 | ret = PTR_ERR(regmap); | ||
31 | return ret; | ||
32 | } | ||
33 | |||
34 | return pcm512x_probe(&spi->dev, regmap); | ||
35 | } | ||
36 | |||
37 | static int pcm512x_spi_remove(struct spi_device *spi) | ||
38 | { | ||
39 | pcm512x_remove(&spi->dev); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static const struct spi_device_id pcm512x_spi_id[] = { | ||
44 | { "pcm5121", }, | ||
45 | { "pcm5122", }, | ||
46 | { }, | ||
47 | }; | ||
48 | MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); | ||
49 | |||
50 | static const struct of_device_id pcm512x_of_match[] = { | ||
51 | { .compatible = "ti,pcm5121", }, | ||
52 | { .compatible = "ti,pcm5122", }, | ||
53 | { } | ||
54 | }; | ||
55 | MODULE_DEVICE_TABLE(of, pcm512x_of_match); | ||
56 | |||
57 | static struct spi_driver pcm512x_spi_driver = { | ||
58 | .probe = pcm512x_spi_probe, | ||
59 | .remove = pcm512x_spi_remove, | ||
60 | .id_table = pcm512x_spi_id, | ||
61 | .driver = { | ||
62 | .name = "pcm512x", | ||
63 | .owner = THIS_MODULE, | ||
64 | .of_match_table = pcm512x_of_match, | ||
65 | .pm = &pcm512x_pm_ops, | ||
66 | }, | ||
67 | }; | ||
68 | |||
69 | module_spi_driver(pcm512x_spi_driver); | ||
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c new file mode 100644 index 000000000000..4b4c0c7bb918 --- /dev/null +++ b/sound/soc/codecs/pcm512x.c | |||
@@ -0,0 +1,589 @@ | |||
1 | /* | ||
2 | * Driver for the PCM512x CODECs | ||
3 | * | ||
4 | * Author: Mark Brown <broonie@linaro.org> | ||
5 | * Copyright 2014 Linaro Ltd | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | |||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/pm_runtime.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include <linux/regulator/consumer.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/soc-dapm.h> | ||
26 | #include <sound/tlv.h> | ||
27 | |||
28 | #include "pcm512x.h" | ||
29 | |||
30 | #define PCM512x_NUM_SUPPLIES 3 | ||
31 | static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { | ||
32 | "AVDD", | ||
33 | "DVDD", | ||
34 | "CPVDD", | ||
35 | }; | ||
36 | |||
37 | struct pcm512x_priv { | ||
38 | struct regmap *regmap; | ||
39 | struct clk *sclk; | ||
40 | struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES]; | ||
41 | struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES]; | ||
42 | }; | ||
43 | |||
44 | /* | ||
45 | * We can't use the same notifier block for more than one supply and | ||
46 | * there's no way I can see to get from a callback to the caller | ||
47 | * except container_of(). | ||
48 | */ | ||
49 | #define PCM512x_REGULATOR_EVENT(n) \ | ||
50 | static int pcm512x_regulator_event_##n(struct notifier_block *nb, \ | ||
51 | unsigned long event, void *data) \ | ||
52 | { \ | ||
53 | struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \ | ||
54 | supply_nb[n]); \ | ||
55 | if (event & REGULATOR_EVENT_DISABLE) { \ | ||
56 | regcache_mark_dirty(pcm512x->regmap); \ | ||
57 | regcache_cache_only(pcm512x->regmap, true); \ | ||
58 | } \ | ||
59 | return 0; \ | ||
60 | } | ||
61 | |||
62 | PCM512x_REGULATOR_EVENT(0) | ||
63 | PCM512x_REGULATOR_EVENT(1) | ||
64 | PCM512x_REGULATOR_EVENT(2) | ||
65 | |||
66 | static const struct reg_default pcm512x_reg_defaults[] = { | ||
67 | { PCM512x_RESET, 0x00 }, | ||
68 | { PCM512x_POWER, 0x00 }, | ||
69 | { PCM512x_MUTE, 0x00 }, | ||
70 | { PCM512x_DSP, 0x00 }, | ||
71 | { PCM512x_PLL_REF, 0x00 }, | ||
72 | { PCM512x_DAC_ROUTING, 0x11 }, | ||
73 | { PCM512x_DSP_PROGRAM, 0x01 }, | ||
74 | { PCM512x_CLKDET, 0x00 }, | ||
75 | { PCM512x_AUTO_MUTE, 0x00 }, | ||
76 | { PCM512x_ERROR_DETECT, 0x00 }, | ||
77 | { PCM512x_DIGITAL_VOLUME_1, 0x00 }, | ||
78 | { PCM512x_DIGITAL_VOLUME_2, 0x30 }, | ||
79 | { PCM512x_DIGITAL_VOLUME_3, 0x30 }, | ||
80 | { PCM512x_DIGITAL_MUTE_1, 0x22 }, | ||
81 | { PCM512x_DIGITAL_MUTE_2, 0x00 }, | ||
82 | { PCM512x_DIGITAL_MUTE_3, 0x07 }, | ||
83 | { PCM512x_OUTPUT_AMPLITUDE, 0x00 }, | ||
84 | { PCM512x_ANALOG_GAIN_CTRL, 0x00 }, | ||
85 | { PCM512x_UNDERVOLTAGE_PROT, 0x00 }, | ||
86 | { PCM512x_ANALOG_MUTE_CTRL, 0x00 }, | ||
87 | { PCM512x_ANALOG_GAIN_BOOST, 0x00 }, | ||
88 | { PCM512x_VCOM_CTRL_1, 0x00 }, | ||
89 | { PCM512x_VCOM_CTRL_2, 0x01 }, | ||
90 | }; | ||
91 | |||
92 | static bool pcm512x_readable(struct device *dev, unsigned int reg) | ||
93 | { | ||
94 | switch (reg) { | ||
95 | case PCM512x_RESET: | ||
96 | case PCM512x_POWER: | ||
97 | case PCM512x_MUTE: | ||
98 | case PCM512x_PLL_EN: | ||
99 | case PCM512x_SPI_MISO_FUNCTION: | ||
100 | case PCM512x_DSP: | ||
101 | case PCM512x_GPIO_EN: | ||
102 | case PCM512x_BCLK_LRCLK_CFG: | ||
103 | case PCM512x_DSP_GPIO_INPUT: | ||
104 | case PCM512x_MASTER_MODE: | ||
105 | case PCM512x_PLL_REF: | ||
106 | case PCM512x_PLL_COEFF_0: | ||
107 | case PCM512x_PLL_COEFF_1: | ||
108 | case PCM512x_PLL_COEFF_2: | ||
109 | case PCM512x_PLL_COEFF_3: | ||
110 | case PCM512x_PLL_COEFF_4: | ||
111 | case PCM512x_DSP_CLKDIV: | ||
112 | case PCM512x_DAC_CLKDIV: | ||
113 | case PCM512x_NCP_CLKDIV: | ||
114 | case PCM512x_OSR_CLKDIV: | ||
115 | case PCM512x_MASTER_CLKDIV_1: | ||
116 | case PCM512x_MASTER_CLKDIV_2: | ||
117 | case PCM512x_FS_SPEED_MODE: | ||
118 | case PCM512x_IDAC_1: | ||
119 | case PCM512x_IDAC_2: | ||
120 | case PCM512x_ERROR_DETECT: | ||
121 | case PCM512x_I2S_1: | ||
122 | case PCM512x_I2S_2: | ||
123 | case PCM512x_DAC_ROUTING: | ||
124 | case PCM512x_DSP_PROGRAM: | ||
125 | case PCM512x_CLKDET: | ||
126 | case PCM512x_AUTO_MUTE: | ||
127 | case PCM512x_DIGITAL_VOLUME_1: | ||
128 | case PCM512x_DIGITAL_VOLUME_2: | ||
129 | case PCM512x_DIGITAL_VOLUME_3: | ||
130 | case PCM512x_DIGITAL_MUTE_1: | ||
131 | case PCM512x_DIGITAL_MUTE_2: | ||
132 | case PCM512x_DIGITAL_MUTE_3: | ||
133 | case PCM512x_GPIO_OUTPUT_1: | ||
134 | case PCM512x_GPIO_OUTPUT_2: | ||
135 | case PCM512x_GPIO_OUTPUT_3: | ||
136 | case PCM512x_GPIO_OUTPUT_4: | ||
137 | case PCM512x_GPIO_OUTPUT_5: | ||
138 | case PCM512x_GPIO_OUTPUT_6: | ||
139 | case PCM512x_GPIO_CONTROL_1: | ||
140 | case PCM512x_GPIO_CONTROL_2: | ||
141 | case PCM512x_OVERFLOW: | ||
142 | case PCM512x_RATE_DET_1: | ||
143 | case PCM512x_RATE_DET_2: | ||
144 | case PCM512x_RATE_DET_3: | ||
145 | case PCM512x_RATE_DET_4: | ||
146 | case PCM512x_ANALOG_MUTE_DET: | ||
147 | case PCM512x_GPIN: | ||
148 | case PCM512x_DIGITAL_MUTE_DET: | ||
149 | case PCM512x_OUTPUT_AMPLITUDE: | ||
150 | case PCM512x_ANALOG_GAIN_CTRL: | ||
151 | case PCM512x_UNDERVOLTAGE_PROT: | ||
152 | case PCM512x_ANALOG_MUTE_CTRL: | ||
153 | case PCM512x_ANALOG_GAIN_BOOST: | ||
154 | case PCM512x_VCOM_CTRL_1: | ||
155 | case PCM512x_VCOM_CTRL_2: | ||
156 | case PCM512x_CRAM_CTRL: | ||
157 | return true; | ||
158 | default: | ||
159 | /* There are 256 raw register addresses */ | ||
160 | return reg < 0xff; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | static bool pcm512x_volatile(struct device *dev, unsigned int reg) | ||
165 | { | ||
166 | switch (reg) { | ||
167 | case PCM512x_PLL_EN: | ||
168 | case PCM512x_OVERFLOW: | ||
169 | case PCM512x_RATE_DET_1: | ||
170 | case PCM512x_RATE_DET_2: | ||
171 | case PCM512x_RATE_DET_3: | ||
172 | case PCM512x_RATE_DET_4: | ||
173 | case PCM512x_ANALOG_MUTE_DET: | ||
174 | case PCM512x_GPIN: | ||
175 | case PCM512x_DIGITAL_MUTE_DET: | ||
176 | case PCM512x_CRAM_CTRL: | ||
177 | return true; | ||
178 | default: | ||
179 | /* There are 256 raw register addresses */ | ||
180 | return reg < 0xff; | ||
181 | } | ||
182 | } | ||
183 | |||
184 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1); | ||
185 | static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0); | ||
186 | static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0); | ||
187 | |||
188 | static const char * const pcm512x_dsp_program_texts[] = { | ||
189 | "FIR interpolation with de-emphasis", | ||
190 | "Low latency IIR with de-emphasis", | ||
191 | "Fixed process flow", | ||
192 | "High attenuation with de-emphasis", | ||
193 | "Ringing-less low latency FIR", | ||
194 | }; | ||
195 | |||
196 | static const unsigned int pcm512x_dsp_program_values[] = { | ||
197 | 1, | ||
198 | 2, | ||
199 | 3, | ||
200 | 5, | ||
201 | 7, | ||
202 | }; | ||
203 | |||
204 | static SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program, | ||
205 | PCM512x_DSP_PROGRAM, 0, 0x1f, | ||
206 | pcm512x_dsp_program_texts, | ||
207 | pcm512x_dsp_program_values); | ||
208 | |||
209 | static const char * const pcm512x_clk_missing_text[] = { | ||
210 | "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s" | ||
211 | }; | ||
212 | |||
213 | static const struct soc_enum pcm512x_clk_missing = | ||
214 | SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 8, pcm512x_clk_missing_text); | ||
215 | |||
216 | static const char * const pcm512x_autom_text[] = { | ||
217 | "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s" | ||
218 | }; | ||
219 | |||
220 | static const struct soc_enum pcm512x_autom_l = | ||
221 | SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 8, | ||
222 | pcm512x_autom_text); | ||
223 | |||
224 | static const struct soc_enum pcm512x_autom_r = | ||
225 | SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8, | ||
226 | pcm512x_autom_text); | ||
227 | |||
228 | static const char * const pcm512x_ramp_rate_text[] = { | ||
229 | "1 sample/update", "2 samples/update", "4 samples/update", | ||
230 | "Immediate" | ||
231 | }; | ||
232 | |||
233 | static const struct soc_enum pcm512x_vndf = | ||
234 | SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4, | ||
235 | pcm512x_ramp_rate_text); | ||
236 | |||
237 | static const struct soc_enum pcm512x_vnuf = | ||
238 | SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4, | ||
239 | pcm512x_ramp_rate_text); | ||
240 | |||
241 | static const struct soc_enum pcm512x_vedf = | ||
242 | SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4, | ||
243 | pcm512x_ramp_rate_text); | ||
244 | |||
245 | static const char * const pcm512x_ramp_step_text[] = { | ||
246 | "4dB/step", "2dB/step", "1dB/step", "0.5dB/step" | ||
247 | }; | ||
248 | |||
249 | static const struct soc_enum pcm512x_vnds = | ||
250 | SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4, | ||
251 | pcm512x_ramp_step_text); | ||
252 | |||
253 | static const struct soc_enum pcm512x_vnus = | ||
254 | SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4, | ||
255 | pcm512x_ramp_step_text); | ||
256 | |||
257 | static const struct soc_enum pcm512x_veds = | ||
258 | SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4, | ||
259 | pcm512x_ramp_step_text); | ||
260 | |||
261 | static const struct snd_kcontrol_new pcm512x_controls[] = { | ||
262 | SOC_DOUBLE_R_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2, | ||
263 | PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv), | ||
264 | SOC_DOUBLE_TLV("Playback Volume", PCM512x_ANALOG_GAIN_CTRL, | ||
265 | PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv), | ||
266 | SOC_DOUBLE_TLV("Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST, | ||
267 | PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv), | ||
268 | SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT, | ||
269 | PCM512x_RQMR_SHIFT, 1, 1), | ||
270 | |||
271 | SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1), | ||
272 | SOC_VALUE_ENUM("DSP Program", pcm512x_dsp_program), | ||
273 | |||
274 | SOC_ENUM("Clock Missing Period", pcm512x_clk_missing), | ||
275 | SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l), | ||
276 | SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r), | ||
277 | SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3, | ||
278 | PCM512x_ACTL_SHIFT, 1, 0), | ||
279 | SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT, | ||
280 | PCM512x_AMLR_SHIFT, 1, 0), | ||
281 | |||
282 | SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf), | ||
283 | SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds), | ||
284 | SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf), | ||
285 | SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus), | ||
286 | SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf), | ||
287 | SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds), | ||
288 | }; | ||
289 | |||
290 | static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = { | ||
291 | SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), | ||
292 | SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), | ||
293 | |||
294 | SND_SOC_DAPM_OUTPUT("OUTL"), | ||
295 | SND_SOC_DAPM_OUTPUT("OUTR"), | ||
296 | }; | ||
297 | |||
298 | static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = { | ||
299 | { "DACL", NULL, "Playback" }, | ||
300 | { "DACR", NULL, "Playback" }, | ||
301 | |||
302 | { "OUTL", NULL, "DACL" }, | ||
303 | { "OUTR", NULL, "DACR" }, | ||
304 | }; | ||
305 | |||
306 | static int pcm512x_set_bias_level(struct snd_soc_codec *codec, | ||
307 | enum snd_soc_bias_level level) | ||
308 | { | ||
309 | struct pcm512x_priv *pcm512x = dev_get_drvdata(codec->dev); | ||
310 | int ret; | ||
311 | |||
312 | switch (level) { | ||
313 | case SND_SOC_BIAS_ON: | ||
314 | case SND_SOC_BIAS_PREPARE: | ||
315 | break; | ||
316 | |||
317 | case SND_SOC_BIAS_STANDBY: | ||
318 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, | ||
319 | PCM512x_RQST, 0); | ||
320 | if (ret != 0) { | ||
321 | dev_err(codec->dev, "Failed to remove standby: %d\n", | ||
322 | ret); | ||
323 | return ret; | ||
324 | } | ||
325 | break; | ||
326 | |||
327 | case SND_SOC_BIAS_OFF: | ||
328 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, | ||
329 | PCM512x_RQST, PCM512x_RQST); | ||
330 | if (ret != 0) { | ||
331 | dev_err(codec->dev, "Failed to request standby: %d\n", | ||
332 | ret); | ||
333 | return ret; | ||
334 | } | ||
335 | break; | ||
336 | } | ||
337 | |||
338 | codec->dapm.bias_level = level; | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static struct snd_soc_dai_driver pcm512x_dai = { | ||
344 | .name = "pcm512x-hifi", | ||
345 | .playback = { | ||
346 | .stream_name = "Playback", | ||
347 | .channels_min = 2, | ||
348 | .channels_max = 2, | ||
349 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
350 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
351 | SNDRV_PCM_FMTBIT_S24_LE | | ||
352 | SNDRV_PCM_FMTBIT_S32_LE | ||
353 | }, | ||
354 | }; | ||
355 | |||
356 | static struct snd_soc_codec_driver pcm512x_codec_driver = { | ||
357 | .set_bias_level = pcm512x_set_bias_level, | ||
358 | .idle_bias_off = true, | ||
359 | |||
360 | .controls = pcm512x_controls, | ||
361 | .num_controls = ARRAY_SIZE(pcm512x_controls), | ||
362 | .dapm_widgets = pcm512x_dapm_widgets, | ||
363 | .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets), | ||
364 | .dapm_routes = pcm512x_dapm_routes, | ||
365 | .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes), | ||
366 | }; | ||
367 | |||
368 | static const struct regmap_range_cfg pcm512x_range = { | ||
369 | .name = "Pages", .range_min = PCM512x_VIRT_BASE, | ||
370 | .range_max = PCM512x_MAX_REGISTER, | ||
371 | .selector_reg = PCM512x_PAGE, | ||
372 | .selector_mask = 0xff, | ||
373 | .window_start = 0, .window_len = 0x100, | ||
374 | }; | ||
375 | |||
376 | const struct regmap_config pcm512x_regmap = { | ||
377 | .reg_bits = 8, | ||
378 | .val_bits = 8, | ||
379 | |||
380 | .readable_reg = pcm512x_readable, | ||
381 | .volatile_reg = pcm512x_volatile, | ||
382 | |||
383 | .ranges = &pcm512x_range, | ||
384 | .num_ranges = 1, | ||
385 | |||
386 | .max_register = PCM512x_MAX_REGISTER, | ||
387 | .reg_defaults = pcm512x_reg_defaults, | ||
388 | .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults), | ||
389 | .cache_type = REGCACHE_RBTREE, | ||
390 | }; | ||
391 | EXPORT_SYMBOL_GPL(pcm512x_regmap); | ||
392 | |||
393 | int pcm512x_probe(struct device *dev, struct regmap *regmap) | ||
394 | { | ||
395 | struct pcm512x_priv *pcm512x; | ||
396 | int i, ret; | ||
397 | |||
398 | pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL); | ||
399 | if (!pcm512x) | ||
400 | return -ENOMEM; | ||
401 | |||
402 | dev_set_drvdata(dev, pcm512x); | ||
403 | pcm512x->regmap = regmap; | ||
404 | |||
405 | for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) | ||
406 | pcm512x->supplies[i].supply = pcm512x_supply_names[i]; | ||
407 | |||
408 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies), | ||
409 | pcm512x->supplies); | ||
410 | if (ret != 0) { | ||
411 | dev_err(dev, "Failed to get supplies: %d\n", ret); | ||
412 | return ret; | ||
413 | } | ||
414 | |||
415 | pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0; | ||
416 | pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1; | ||
417 | pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2; | ||
418 | |||
419 | for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) { | ||
420 | ret = regulator_register_notifier(pcm512x->supplies[i].consumer, | ||
421 | &pcm512x->supply_nb[i]); | ||
422 | if (ret != 0) { | ||
423 | dev_err(dev, | ||
424 | "Failed to register regulator notifier: %d\n", | ||
425 | ret); | ||
426 | } | ||
427 | } | ||
428 | |||
429 | ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies), | ||
430 | pcm512x->supplies); | ||
431 | if (ret != 0) { | ||
432 | dev_err(dev, "Failed to enable supplies: %d\n", ret); | ||
433 | return ret; | ||
434 | } | ||
435 | |||
436 | /* Reset the device, verifying I/O in the process for I2C */ | ||
437 | ret = regmap_write(regmap, PCM512x_RESET, | ||
438 | PCM512x_RSTM | PCM512x_RSTR); | ||
439 | if (ret != 0) { | ||
440 | dev_err(dev, "Failed to reset device: %d\n", ret); | ||
441 | goto err; | ||
442 | } | ||
443 | |||
444 | ret = regmap_write(regmap, PCM512x_RESET, 0); | ||
445 | if (ret != 0) { | ||
446 | dev_err(dev, "Failed to reset device: %d\n", ret); | ||
447 | goto err; | ||
448 | } | ||
449 | |||
450 | pcm512x->sclk = devm_clk_get(dev, NULL); | ||
451 | if (IS_ERR(pcm512x->sclk)) { | ||
452 | if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) | ||
453 | return -EPROBE_DEFER; | ||
454 | |||
455 | dev_info(dev, "No SCLK, using BCLK: %ld\n", | ||
456 | PTR_ERR(pcm512x->sclk)); | ||
457 | |||
458 | /* Disable reporting of missing SCLK as an error */ | ||
459 | regmap_update_bits(regmap, PCM512x_ERROR_DETECT, | ||
460 | PCM512x_IDCH, PCM512x_IDCH); | ||
461 | |||
462 | /* Switch PLL input to BCLK */ | ||
463 | regmap_update_bits(regmap, PCM512x_PLL_REF, | ||
464 | PCM512x_SREF, PCM512x_SREF); | ||
465 | } else { | ||
466 | ret = clk_prepare_enable(pcm512x->sclk); | ||
467 | if (ret != 0) { | ||
468 | dev_err(dev, "Failed to enable SCLK: %d\n", ret); | ||
469 | return ret; | ||
470 | } | ||
471 | } | ||
472 | |||
473 | /* Default to standby mode */ | ||
474 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, | ||
475 | PCM512x_RQST, PCM512x_RQST); | ||
476 | if (ret != 0) { | ||
477 | dev_err(dev, "Failed to request standby: %d\n", | ||
478 | ret); | ||
479 | goto err_clk; | ||
480 | } | ||
481 | |||
482 | pm_runtime_set_active(dev); | ||
483 | pm_runtime_enable(dev); | ||
484 | pm_runtime_idle(dev); | ||
485 | |||
486 | ret = snd_soc_register_codec(dev, &pcm512x_codec_driver, | ||
487 | &pcm512x_dai, 1); | ||
488 | if (ret != 0) { | ||
489 | dev_err(dev, "Failed to register CODEC: %d\n", ret); | ||
490 | goto err_pm; | ||
491 | } | ||
492 | |||
493 | return 0; | ||
494 | |||
495 | err_pm: | ||
496 | pm_runtime_disable(dev); | ||
497 | err_clk: | ||
498 | if (!IS_ERR(pcm512x->sclk)) | ||
499 | clk_disable_unprepare(pcm512x->sclk); | ||
500 | err: | ||
501 | regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), | ||
502 | pcm512x->supplies); | ||
503 | return ret; | ||
504 | } | ||
505 | EXPORT_SYMBOL_GPL(pcm512x_probe); | ||
506 | |||
507 | void pcm512x_remove(struct device *dev) | ||
508 | { | ||
509 | struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); | ||
510 | |||
511 | snd_soc_unregister_codec(dev); | ||
512 | pm_runtime_disable(dev); | ||
513 | if (!IS_ERR(pcm512x->sclk)) | ||
514 | clk_disable_unprepare(pcm512x->sclk); | ||
515 | regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), | ||
516 | pcm512x->supplies); | ||
517 | } | ||
518 | EXPORT_SYMBOL_GPL(pcm512x_remove); | ||
519 | |||
520 | static int pcm512x_suspend(struct device *dev) | ||
521 | { | ||
522 | struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); | ||
523 | int ret; | ||
524 | |||
525 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, | ||
526 | PCM512x_RQPD, PCM512x_RQPD); | ||
527 | if (ret != 0) { | ||
528 | dev_err(dev, "Failed to request power down: %d\n", ret); | ||
529 | return ret; | ||
530 | } | ||
531 | |||
532 | ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), | ||
533 | pcm512x->supplies); | ||
534 | if (ret != 0) { | ||
535 | dev_err(dev, "Failed to disable supplies: %d\n", ret); | ||
536 | return ret; | ||
537 | } | ||
538 | |||
539 | if (!IS_ERR(pcm512x->sclk)) | ||
540 | clk_disable_unprepare(pcm512x->sclk); | ||
541 | |||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | static int pcm512x_resume(struct device *dev) | ||
546 | { | ||
547 | struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); | ||
548 | int ret; | ||
549 | |||
550 | if (!IS_ERR(pcm512x->sclk)) { | ||
551 | ret = clk_prepare_enable(pcm512x->sclk); | ||
552 | if (ret != 0) { | ||
553 | dev_err(dev, "Failed to enable SCLK: %d\n", ret); | ||
554 | return ret; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies), | ||
559 | pcm512x->supplies); | ||
560 | if (ret != 0) { | ||
561 | dev_err(dev, "Failed to enable supplies: %d\n", ret); | ||
562 | return ret; | ||
563 | } | ||
564 | |||
565 | regcache_cache_only(pcm512x->regmap, false); | ||
566 | ret = regcache_sync(pcm512x->regmap); | ||
567 | if (ret != 0) { | ||
568 | dev_err(dev, "Failed to sync cache: %d\n", ret); | ||
569 | return ret; | ||
570 | } | ||
571 | |||
572 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, | ||
573 | PCM512x_RQPD, 0); | ||
574 | if (ret != 0) { | ||
575 | dev_err(dev, "Failed to remove power down: %d\n", ret); | ||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | const struct dev_pm_ops pcm512x_pm_ops = { | ||
583 | SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL) | ||
584 | }; | ||
585 | EXPORT_SYMBOL_GPL(pcm512x_pm_ops); | ||
586 | |||
587 | MODULE_DESCRIPTION("ASoC PCM512x codec driver"); | ||
588 | MODULE_AUTHOR("Mark Brown <broonie@linaro.org>"); | ||
589 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h new file mode 100644 index 000000000000..6ee76aaca09a --- /dev/null +++ b/sound/soc/codecs/pcm512x.h | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * Driver for the PCM512x CODECs | ||
3 | * | ||
4 | * Author: Mark Brown <broonie@linaro.org> | ||
5 | * Copyright 2014 Linaro Ltd | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #ifndef _SND_SOC_PCM512X | ||
18 | #define _SND_SOC_PCM512X | ||
19 | |||
20 | #include <linux/pm.h> | ||
21 | #include <linux/regmap.h> | ||
22 | |||
23 | #define PCM512x_VIRT_BASE 0x100 | ||
24 | #define PCM512x_PAGE_LEN 0x100 | ||
25 | #define PCM512x_PAGE_BASE(n) (PCM512x_VIRT_BASE + (PCM512x_PAGE_LEN * n)) | ||
26 | |||
27 | #define PCM512x_PAGE 0 | ||
28 | |||
29 | #define PCM512x_RESET (PCM512x_PAGE_BASE(0) + 1) | ||
30 | #define PCM512x_POWER (PCM512x_PAGE_BASE(0) + 2) | ||
31 | #define PCM512x_MUTE (PCM512x_PAGE_BASE(0) + 3) | ||
32 | #define PCM512x_PLL_EN (PCM512x_PAGE_BASE(0) + 4) | ||
33 | #define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_BASE(0) + 6) | ||
34 | #define PCM512x_DSP (PCM512x_PAGE_BASE(0) + 7) | ||
35 | #define PCM512x_GPIO_EN (PCM512x_PAGE_BASE(0) + 8) | ||
36 | #define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_BASE(0) + 9) | ||
37 | #define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_BASE(0) + 10) | ||
38 | #define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12) | ||
39 | #define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13) | ||
40 | #define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20) | ||
41 | #define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_BASE(0) + 21) | ||
42 | #define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_BASE(0) + 22) | ||
43 | #define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_BASE(0) + 23) | ||
44 | #define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_BASE(0) + 24) | ||
45 | #define PCM512x_DSP_CLKDIV (PCM512x_PAGE_BASE(0) + 27) | ||
46 | #define PCM512x_DAC_CLKDIV (PCM512x_PAGE_BASE(0) + 28) | ||
47 | #define PCM512x_NCP_CLKDIV (PCM512x_PAGE_BASE(0) + 29) | ||
48 | #define PCM512x_OSR_CLKDIV (PCM512x_PAGE_BASE(0) + 30) | ||
49 | #define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_BASE(0) + 32) | ||
50 | #define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_BASE(0) + 33) | ||
51 | #define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_BASE(0) + 34) | ||
52 | #define PCM512x_IDAC_1 (PCM512x_PAGE_BASE(0) + 35) | ||
53 | #define PCM512x_IDAC_2 (PCM512x_PAGE_BASE(0) + 36) | ||
54 | #define PCM512x_ERROR_DETECT (PCM512x_PAGE_BASE(0) + 37) | ||
55 | #define PCM512x_I2S_1 (PCM512x_PAGE_BASE(0) + 40) | ||
56 | #define PCM512x_I2S_2 (PCM512x_PAGE_BASE(0) + 41) | ||
57 | #define PCM512x_DAC_ROUTING (PCM512x_PAGE_BASE(0) + 42) | ||
58 | #define PCM512x_DSP_PROGRAM (PCM512x_PAGE_BASE(0) + 43) | ||
59 | #define PCM512x_CLKDET (PCM512x_PAGE_BASE(0) + 44) | ||
60 | #define PCM512x_AUTO_MUTE (PCM512x_PAGE_BASE(0) + 59) | ||
61 | #define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_BASE(0) + 60) | ||
62 | #define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_BASE(0) + 61) | ||
63 | #define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_BASE(0) + 62) | ||
64 | #define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_BASE(0) + 63) | ||
65 | #define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_BASE(0) + 64) | ||
66 | #define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_BASE(0) + 65) | ||
67 | #define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_BASE(0) + 80) | ||
68 | #define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_BASE(0) + 81) | ||
69 | #define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_BASE(0) + 82) | ||
70 | #define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_BASE(0) + 83) | ||
71 | #define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_BASE(0) + 84) | ||
72 | #define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_BASE(0) + 85) | ||
73 | #define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_BASE(0) + 86) | ||
74 | #define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_BASE(0) + 87) | ||
75 | #define PCM512x_OVERFLOW (PCM512x_PAGE_BASE(0) + 90) | ||
76 | #define PCM512x_RATE_DET_1 (PCM512x_PAGE_BASE(0) + 91) | ||
77 | #define PCM512x_RATE_DET_2 (PCM512x_PAGE_BASE(0) + 92) | ||
78 | #define PCM512x_RATE_DET_3 (PCM512x_PAGE_BASE(0) + 93) | ||
79 | #define PCM512x_RATE_DET_4 (PCM512x_PAGE_BASE(0) + 94) | ||
80 | #define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_BASE(0) + 108) | ||
81 | #define PCM512x_GPIN (PCM512x_PAGE_BASE(0) + 119) | ||
82 | #define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_BASE(0) + 120) | ||
83 | |||
84 | #define PCM512x_OUTPUT_AMPLITUDE (PCM512x_PAGE_BASE(1) + 1) | ||
85 | #define PCM512x_ANALOG_GAIN_CTRL (PCM512x_PAGE_BASE(1) + 2) | ||
86 | #define PCM512x_UNDERVOLTAGE_PROT (PCM512x_PAGE_BASE(1) + 5) | ||
87 | #define PCM512x_ANALOG_MUTE_CTRL (PCM512x_PAGE_BASE(1) + 6) | ||
88 | #define PCM512x_ANALOG_GAIN_BOOST (PCM512x_PAGE_BASE(1) + 7) | ||
89 | #define PCM512x_VCOM_CTRL_1 (PCM512x_PAGE_BASE(1) + 8) | ||
90 | #define PCM512x_VCOM_CTRL_2 (PCM512x_PAGE_BASE(1) + 9) | ||
91 | |||
92 | #define PCM512x_CRAM_CTRL (PCM512x_PAGE_BASE(44) + 1) | ||
93 | |||
94 | #define PCM512x_MAX_REGISTER (PCM512x_PAGE_BASE(44) + 1) | ||
95 | |||
96 | /* Page 0, Register 1 - reset */ | ||
97 | #define PCM512x_RSTR (1 << 0) | ||
98 | #define PCM512x_RSTM (1 << 4) | ||
99 | |||
100 | /* Page 0, Register 2 - power */ | ||
101 | #define PCM512x_RQPD (1 << 0) | ||
102 | #define PCM512x_RQPD_SHIFT 0 | ||
103 | #define PCM512x_RQST (1 << 4) | ||
104 | #define PCM512x_RQST_SHIFT 4 | ||
105 | |||
106 | /* Page 0, Register 3 - mute */ | ||
107 | #define PCM512x_RQMR_SHIFT 0 | ||
108 | #define PCM512x_RQML_SHIFT 4 | ||
109 | |||
110 | /* Page 0, Register 4 - PLL */ | ||
111 | #define PCM512x_PLCE (1 << 0) | ||
112 | #define PCM512x_RLCE_SHIFT 0 | ||
113 | #define PCM512x_PLCK (1 << 4) | ||
114 | #define PCM512x_PLCK_SHIFT 4 | ||
115 | |||
116 | /* Page 0, Register 7 - DSP */ | ||
117 | #define PCM512x_SDSL (1 << 0) | ||
118 | #define PCM512x_SDSL_SHIFT 0 | ||
119 | #define PCM512x_DEMP (1 << 4) | ||
120 | #define PCM512x_DEMP_SHIFT 4 | ||
121 | |||
122 | /* Page 0, Register 13 - PLL reference */ | ||
123 | #define PCM512x_SREF (1 << 4) | ||
124 | |||
125 | /* Page 0, Register 37 - Error detection */ | ||
126 | #define PCM512x_IPLK (1 << 0) | ||
127 | #define PCM512x_DCAS (1 << 1) | ||
128 | #define PCM512x_IDCM (1 << 2) | ||
129 | #define PCM512x_IDCH (1 << 3) | ||
130 | #define PCM512x_IDSK (1 << 4) | ||
131 | #define PCM512x_IDBK (1 << 5) | ||
132 | #define PCM512x_IDFS (1 << 6) | ||
133 | |||
134 | /* Page 0, Register 42 - DAC routing */ | ||
135 | #define PCM512x_AUPR_SHIFT 0 | ||
136 | #define PCM512x_AUPL_SHIFT 4 | ||
137 | |||
138 | /* Page 0, Register 59 - auto mute */ | ||
139 | #define PCM512x_ATMR_SHIFT 0 | ||
140 | #define PCM512x_ATML_SHIFT 4 | ||
141 | |||
142 | /* Page 0, Register 63 - ramp rates */ | ||
143 | #define PCM512x_VNDF_SHIFT 6 | ||
144 | #define PCM512x_VNDS_SHIFT 4 | ||
145 | #define PCM512x_VNUF_SHIFT 2 | ||
146 | #define PCM512x_VNUS_SHIFT 0 | ||
147 | |||
148 | /* Page 0, Register 64 - emergency ramp rates */ | ||
149 | #define PCM512x_VEDF_SHIFT 6 | ||
150 | #define PCM512x_VEDS_SHIFT 4 | ||
151 | |||
152 | /* Page 0, Register 65 - Digital mute enables */ | ||
153 | #define PCM512x_ACTL_SHIFT 2 | ||
154 | #define PCM512x_AMLE_SHIFT 1 | ||
155 | #define PCM512x_AMLR_SHIFT 0 | ||
156 | |||
157 | /* Page 1, Register 2 - analog volume control */ | ||
158 | #define PCM512x_RAGN_SHIFT 0 | ||
159 | #define PCM512x_LAGN_SHIFT 4 | ||
160 | |||
161 | /* Page 1, Register 7 - analog boost control */ | ||
162 | #define PCM512x_AGBR_SHIFT 0 | ||
163 | #define PCM512x_AGBL_SHIFT 4 | ||
164 | |||
165 | extern const struct dev_pm_ops pcm512x_pm_ops; | ||
166 | extern const struct regmap_config pcm512x_regmap; | ||
167 | |||
168 | int pcm512x_probe(struct device *dev, struct regmap *regmap); | ||
169 | void pcm512x_remove(struct device *dev); | ||
170 | |||
171 | #endif | ||
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 912c9cbc2724..d4c229f0233f 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c | |||
@@ -210,26 +210,22 @@ static int rt5631_dmic_put(struct snd_kcontrol *kcontrol, | |||
210 | static const char *rt5631_input_mode[] = { | 210 | static const char *rt5631_input_mode[] = { |
211 | "Single ended", "Differential"}; | 211 | "Single ended", "Differential"}; |
212 | 212 | ||
213 | static const SOC_ENUM_SINGLE_DECL( | 213 | static SOC_ENUM_SINGLE_DECL(rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1, |
214 | rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1, | 214 | RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode); |
215 | RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode); | ||
216 | 215 | ||
217 | static const SOC_ENUM_SINGLE_DECL( | 216 | static SOC_ENUM_SINGLE_DECL(rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1, |
218 | rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1, | 217 | RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode); |
219 | RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode); | ||
220 | 218 | ||
221 | /* MONO Input Type */ | 219 | /* MONO Input Type */ |
222 | static const SOC_ENUM_SINGLE_DECL( | 220 | static SOC_ENUM_SINGLE_DECL(rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL, |
223 | rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL, | 221 | RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode); |
224 | RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode); | ||
225 | 222 | ||
226 | /* SPK Ratio Gain Control */ | 223 | /* SPK Ratio Gain Control */ |
227 | static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x", | 224 | static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x", |
228 | "1.56x", "1.68x", "1.99x", "2.34x"}; | 225 | "1.56x", "1.68x", "1.99x", "2.34x"}; |
229 | 226 | ||
230 | static const SOC_ENUM_SINGLE_DECL( | 227 | static SOC_ENUM_SINGLE_DECL(rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG, |
231 | rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG, | 228 | RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio); |
232 | RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio); | ||
233 | 229 | ||
234 | static const struct snd_kcontrol_new rt5631_snd_controls[] = { | 230 | static const struct snd_kcontrol_new rt5631_snd_controls[] = { |
235 | /* MIC */ | 231 | /* MIC */ |
@@ -759,9 +755,8 @@ static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = { | |||
759 | /* Left SPK Volume Input */ | 755 | /* Left SPK Volume Input */ |
760 | static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"}; | 756 | static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"}; |
761 | 757 | ||
762 | static const SOC_ENUM_SINGLE_DECL( | 758 | static SOC_ENUM_SINGLE_DECL(rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL, |
763 | rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL, | 759 | RT5631_L_EN_SHIFT, rt5631_spkvoll_sel); |
764 | RT5631_L_EN_SHIFT, rt5631_spkvoll_sel); | ||
765 | 760 | ||
766 | static const struct snd_kcontrol_new rt5631_spkvoll_mux_control = | 761 | static const struct snd_kcontrol_new rt5631_spkvoll_mux_control = |
767 | SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum); | 762 | SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum); |
@@ -769,9 +764,8 @@ static const struct snd_kcontrol_new rt5631_spkvoll_mux_control = | |||
769 | /* Left HP Volume Input */ | 764 | /* Left HP Volume Input */ |
770 | static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"}; | 765 | static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"}; |
771 | 766 | ||
772 | static const SOC_ENUM_SINGLE_DECL( | 767 | static SOC_ENUM_SINGLE_DECL(rt5631_hpvoll_enum, RT5631_HP_OUT_VOL, |
773 | rt5631_hpvoll_enum, RT5631_HP_OUT_VOL, | 768 | RT5631_L_EN_SHIFT, rt5631_hpvoll_sel); |
774 | RT5631_L_EN_SHIFT, rt5631_hpvoll_sel); | ||
775 | 769 | ||
776 | static const struct snd_kcontrol_new rt5631_hpvoll_mux_control = | 770 | static const struct snd_kcontrol_new rt5631_hpvoll_mux_control = |
777 | SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum); | 771 | SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum); |
@@ -779,9 +773,8 @@ static const struct snd_kcontrol_new rt5631_hpvoll_mux_control = | |||
779 | /* Left Out Volume Input */ | 773 | /* Left Out Volume Input */ |
780 | static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"}; | 774 | static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"}; |
781 | 775 | ||
782 | static const SOC_ENUM_SINGLE_DECL( | 776 | static SOC_ENUM_SINGLE_DECL(rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL, |
783 | rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL, | 777 | RT5631_L_EN_SHIFT, rt5631_outvoll_sel); |
784 | RT5631_L_EN_SHIFT, rt5631_outvoll_sel); | ||
785 | 778 | ||
786 | static const struct snd_kcontrol_new rt5631_outvoll_mux_control = | 779 | static const struct snd_kcontrol_new rt5631_outvoll_mux_control = |
787 | SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum); | 780 | SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum); |
@@ -789,9 +782,8 @@ static const struct snd_kcontrol_new rt5631_outvoll_mux_control = | |||
789 | /* Right Out Volume Input */ | 782 | /* Right Out Volume Input */ |
790 | static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"}; | 783 | static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"}; |
791 | 784 | ||
792 | static const SOC_ENUM_SINGLE_DECL( | 785 | static SOC_ENUM_SINGLE_DECL(rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL, |
793 | rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL, | 786 | RT5631_R_EN_SHIFT, rt5631_outvolr_sel); |
794 | RT5631_R_EN_SHIFT, rt5631_outvolr_sel); | ||
795 | 787 | ||
796 | static const struct snd_kcontrol_new rt5631_outvolr_mux_control = | 788 | static const struct snd_kcontrol_new rt5631_outvolr_mux_control = |
797 | SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum); | 789 | SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum); |
@@ -799,9 +791,8 @@ static const struct snd_kcontrol_new rt5631_outvolr_mux_control = | |||
799 | /* Right HP Volume Input */ | 791 | /* Right HP Volume Input */ |
800 | static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"}; | 792 | static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"}; |
801 | 793 | ||
802 | static const SOC_ENUM_SINGLE_DECL( | 794 | static SOC_ENUM_SINGLE_DECL(rt5631_hpvolr_enum, RT5631_HP_OUT_VOL, |
803 | rt5631_hpvolr_enum, RT5631_HP_OUT_VOL, | 795 | RT5631_R_EN_SHIFT, rt5631_hpvolr_sel); |
804 | RT5631_R_EN_SHIFT, rt5631_hpvolr_sel); | ||
805 | 796 | ||
806 | static const struct snd_kcontrol_new rt5631_hpvolr_mux_control = | 797 | static const struct snd_kcontrol_new rt5631_hpvolr_mux_control = |
807 | SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum); | 798 | SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum); |
@@ -809,9 +800,8 @@ static const struct snd_kcontrol_new rt5631_hpvolr_mux_control = | |||
809 | /* Right SPK Volume Input */ | 800 | /* Right SPK Volume Input */ |
810 | static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"}; | 801 | static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"}; |
811 | 802 | ||
812 | static const SOC_ENUM_SINGLE_DECL( | 803 | static SOC_ENUM_SINGLE_DECL(rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL, |
813 | rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL, | 804 | RT5631_R_EN_SHIFT, rt5631_spkvolr_sel); |
814 | RT5631_R_EN_SHIFT, rt5631_spkvolr_sel); | ||
815 | 805 | ||
816 | static const struct snd_kcontrol_new rt5631_spkvolr_mux_control = | 806 | static const struct snd_kcontrol_new rt5631_spkvolr_mux_control = |
817 | SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum); | 807 | SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum); |
@@ -820,9 +810,8 @@ static const struct snd_kcontrol_new rt5631_spkvolr_mux_control = | |||
820 | static const char *rt5631_spol_src_sel[] = { | 810 | static const char *rt5631_spol_src_sel[] = { |
821 | "SPOLMIX", "MONOIN_RX", "VDAC", "DACL"}; | 811 | "SPOLMIX", "MONOIN_RX", "VDAC", "DACL"}; |
822 | 812 | ||
823 | static const SOC_ENUM_SINGLE_DECL( | 813 | static SOC_ENUM_SINGLE_DECL(rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, |
824 | rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, | 814 | RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel); |
825 | RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel); | ||
826 | 815 | ||
827 | static const struct snd_kcontrol_new rt5631_spol_mux_control = | 816 | static const struct snd_kcontrol_new rt5631_spol_mux_control = |
828 | SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum); | 817 | SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum); |
@@ -831,9 +820,8 @@ static const struct snd_kcontrol_new rt5631_spol_mux_control = | |||
831 | static const char *rt5631_spor_src_sel[] = { | 820 | static const char *rt5631_spor_src_sel[] = { |
832 | "SPORMIX", "MONOIN_RX", "VDAC", "DACR"}; | 821 | "SPORMIX", "MONOIN_RX", "VDAC", "DACR"}; |
833 | 822 | ||
834 | static const SOC_ENUM_SINGLE_DECL( | 823 | static SOC_ENUM_SINGLE_DECL(rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, |
835 | rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, | 824 | RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel); |
836 | RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel); | ||
837 | 825 | ||
838 | static const struct snd_kcontrol_new rt5631_spor_mux_control = | 826 | static const struct snd_kcontrol_new rt5631_spor_mux_control = |
839 | SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum); | 827 | SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum); |
@@ -841,9 +829,8 @@ static const struct snd_kcontrol_new rt5631_spor_mux_control = | |||
841 | /* MONO Input */ | 829 | /* MONO Input */ |
842 | static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"}; | 830 | static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"}; |
843 | 831 | ||
844 | static const SOC_ENUM_SINGLE_DECL( | 832 | static SOC_ENUM_SINGLE_DECL(rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, |
845 | rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, | 833 | RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel); |
846 | RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel); | ||
847 | 834 | ||
848 | static const struct snd_kcontrol_new rt5631_mono_mux_control = | 835 | static const struct snd_kcontrol_new rt5631_mono_mux_control = |
849 | SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum); | 836 | SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum); |
@@ -851,9 +838,8 @@ static const struct snd_kcontrol_new rt5631_mono_mux_control = | |||
851 | /* Left HPO Input */ | 838 | /* Left HPO Input */ |
852 | static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"}; | 839 | static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"}; |
853 | 840 | ||
854 | static const SOC_ENUM_SINGLE_DECL( | 841 | static SOC_ENUM_SINGLE_DECL(rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, |
855 | rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, | 842 | RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel); |
856 | RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel); | ||
857 | 843 | ||
858 | static const struct snd_kcontrol_new rt5631_hpl_mux_control = | 844 | static const struct snd_kcontrol_new rt5631_hpl_mux_control = |
859 | SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum); | 845 | SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum); |
@@ -861,9 +847,8 @@ static const struct snd_kcontrol_new rt5631_hpl_mux_control = | |||
861 | /* Right HPO Input */ | 847 | /* Right HPO Input */ |
862 | static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"}; | 848 | static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"}; |
863 | 849 | ||
864 | static const SOC_ENUM_SINGLE_DECL( | 850 | static SOC_ENUM_SINGLE_DECL(rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, |
865 | rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, | 851 | RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel); |
866 | RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel); | ||
867 | 852 | ||
868 | static const struct snd_kcontrol_new rt5631_hpr_mux_control = | 853 | static const struct snd_kcontrol_new rt5631_hpr_mux_control = |
869 | SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum); | 854 | SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum); |
@@ -1585,15 +1570,6 @@ static int rt5631_probe(struct snd_soc_codec *codec) | |||
1585 | { | 1570 | { |
1586 | struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); | 1571 | struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); |
1587 | unsigned int val; | 1572 | unsigned int val; |
1588 | int ret; | ||
1589 | |||
1590 | codec->control_data = rt5631->regmap; | ||
1591 | |||
1592 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
1593 | if (ret != 0) { | ||
1594 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1595 | return ret; | ||
1596 | } | ||
1597 | 1573 | ||
1598 | val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3); | 1574 | val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3); |
1599 | if (val & 0x0002) | 1575 | if (val & 0x0002) |
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index a3fb41179636..0061ae6b6716 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c | |||
@@ -361,25 +361,24 @@ static unsigned int bst_tlv[] = { | |||
361 | static const char * const rt5640_data_select[] = { | 361 | static const char * const rt5640_data_select[] = { |
362 | "Normal", "left copy to right", "right copy to left", "Swap"}; | 362 | "Normal", "left copy to right", "right copy to left", "Swap"}; |
363 | 363 | ||
364 | static const SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA, | 364 | static SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA, |
365 | RT5640_IF1_DAC_SEL_SFT, rt5640_data_select); | 365 | RT5640_IF1_DAC_SEL_SFT, rt5640_data_select); |
366 | 366 | ||
367 | static const SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA, | 367 | static SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA, |
368 | RT5640_IF1_ADC_SEL_SFT, rt5640_data_select); | 368 | RT5640_IF1_ADC_SEL_SFT, rt5640_data_select); |
369 | 369 | ||
370 | static const SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA, | 370 | static SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA, |
371 | RT5640_IF2_DAC_SEL_SFT, rt5640_data_select); | 371 | RT5640_IF2_DAC_SEL_SFT, rt5640_data_select); |
372 | 372 | ||
373 | static const SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA, | 373 | static SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA, |
374 | RT5640_IF2_ADC_SEL_SFT, rt5640_data_select); | 374 | RT5640_IF2_ADC_SEL_SFT, rt5640_data_select); |
375 | 375 | ||
376 | /* Class D speaker gain ratio */ | 376 | /* Class D speaker gain ratio */ |
377 | static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x", | 377 | static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x", |
378 | "2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"}; | 378 | "2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"}; |
379 | 379 | ||
380 | static const SOC_ENUM_SINGLE_DECL( | 380 | static SOC_ENUM_SINGLE_DECL(rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT, |
381 | rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT, | 381 | RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio); |
382 | RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio); | ||
383 | 382 | ||
384 | static const struct snd_kcontrol_new rt5640_snd_controls[] = { | 383 | static const struct snd_kcontrol_new rt5640_snd_controls[] = { |
385 | /* Speaker Output Volume */ | 384 | /* Speaker Output Volume */ |
@@ -753,9 +752,8 @@ static const char * const rt5640_stereo_adc1_src[] = { | |||
753 | "DIG MIX", "ADC" | 752 | "DIG MIX", "ADC" |
754 | }; | 753 | }; |
755 | 754 | ||
756 | static const SOC_ENUM_SINGLE_DECL( | 755 | static SOC_ENUM_SINGLE_DECL(rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER, |
757 | rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER, | 756 | RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src); |
758 | RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src); | ||
759 | 757 | ||
760 | static const struct snd_kcontrol_new rt5640_sto_adc_1_mux = | 758 | static const struct snd_kcontrol_new rt5640_sto_adc_1_mux = |
761 | SOC_DAPM_ENUM("Stereo ADC1 Mux", rt5640_stereo_adc1_enum); | 759 | SOC_DAPM_ENUM("Stereo ADC1 Mux", rt5640_stereo_adc1_enum); |
@@ -764,9 +762,8 @@ static const char * const rt5640_stereo_adc2_src[] = { | |||
764 | "DMIC1", "DMIC2", "DIG MIX" | 762 | "DMIC1", "DMIC2", "DIG MIX" |
765 | }; | 763 | }; |
766 | 764 | ||
767 | static const SOC_ENUM_SINGLE_DECL( | 765 | static SOC_ENUM_SINGLE_DECL(rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER, |
768 | rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER, | 766 | RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src); |
769 | RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src); | ||
770 | 767 | ||
771 | static const struct snd_kcontrol_new rt5640_sto_adc_2_mux = | 768 | static const struct snd_kcontrol_new rt5640_sto_adc_2_mux = |
772 | SOC_DAPM_ENUM("Stereo ADC2 Mux", rt5640_stereo_adc2_enum); | 769 | SOC_DAPM_ENUM("Stereo ADC2 Mux", rt5640_stereo_adc2_enum); |
@@ -776,9 +773,8 @@ static const char * const rt5640_mono_adc_l1_src[] = { | |||
776 | "Mono DAC MIXL", "ADCL" | 773 | "Mono DAC MIXL", "ADCL" |
777 | }; | 774 | }; |
778 | 775 | ||
779 | static const SOC_ENUM_SINGLE_DECL( | 776 | static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER, |
780 | rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER, | 777 | RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src); |
781 | RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src); | ||
782 | 778 | ||
783 | static const struct snd_kcontrol_new rt5640_mono_adc_l1_mux = | 779 | static const struct snd_kcontrol_new rt5640_mono_adc_l1_mux = |
784 | SOC_DAPM_ENUM("Mono ADC1 left source", rt5640_mono_adc_l1_enum); | 780 | SOC_DAPM_ENUM("Mono ADC1 left source", rt5640_mono_adc_l1_enum); |
@@ -787,9 +783,8 @@ static const char * const rt5640_mono_adc_l2_src[] = { | |||
787 | "DMIC L1", "DMIC L2", "Mono DAC MIXL" | 783 | "DMIC L1", "DMIC L2", "Mono DAC MIXL" |
788 | }; | 784 | }; |
789 | 785 | ||
790 | static const SOC_ENUM_SINGLE_DECL( | 786 | static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER, |
791 | rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER, | 787 | RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src); |
792 | RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src); | ||
793 | 788 | ||
794 | static const struct snd_kcontrol_new rt5640_mono_adc_l2_mux = | 789 | static const struct snd_kcontrol_new rt5640_mono_adc_l2_mux = |
795 | SOC_DAPM_ENUM("Mono ADC2 left source", rt5640_mono_adc_l2_enum); | 790 | SOC_DAPM_ENUM("Mono ADC2 left source", rt5640_mono_adc_l2_enum); |
@@ -798,9 +793,8 @@ static const char * const rt5640_mono_adc_r1_src[] = { | |||
798 | "Mono DAC MIXR", "ADCR" | 793 | "Mono DAC MIXR", "ADCR" |
799 | }; | 794 | }; |
800 | 795 | ||
801 | static const SOC_ENUM_SINGLE_DECL( | 796 | static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER, |
802 | rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER, | 797 | RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src); |
803 | RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src); | ||
804 | 798 | ||
805 | static const struct snd_kcontrol_new rt5640_mono_adc_r1_mux = | 799 | static const struct snd_kcontrol_new rt5640_mono_adc_r1_mux = |
806 | SOC_DAPM_ENUM("Mono ADC1 right source", rt5640_mono_adc_r1_enum); | 800 | SOC_DAPM_ENUM("Mono ADC1 right source", rt5640_mono_adc_r1_enum); |
@@ -809,9 +803,8 @@ static const char * const rt5640_mono_adc_r2_src[] = { | |||
809 | "DMIC R1", "DMIC R2", "Mono DAC MIXR" | 803 | "DMIC R1", "DMIC R2", "Mono DAC MIXR" |
810 | }; | 804 | }; |
811 | 805 | ||
812 | static const SOC_ENUM_SINGLE_DECL( | 806 | static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER, |
813 | rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER, | 807 | RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src); |
814 | RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src); | ||
815 | 808 | ||
816 | static const struct snd_kcontrol_new rt5640_mono_adc_r2_mux = | 809 | static const struct snd_kcontrol_new rt5640_mono_adc_r2_mux = |
817 | SOC_DAPM_ENUM("Mono ADC2 right source", rt5640_mono_adc_r2_enum); | 810 | SOC_DAPM_ENUM("Mono ADC2 right source", rt5640_mono_adc_r2_enum); |
@@ -826,9 +819,9 @@ static int rt5640_dac_l2_values[] = { | |||
826 | 3, | 819 | 3, |
827 | }; | 820 | }; |
828 | 821 | ||
829 | static const SOC_VALUE_ENUM_SINGLE_DECL( | 822 | static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_l2_enum, |
830 | rt5640_dac_l2_enum, RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT, | 823 | RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT, |
831 | 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values); | 824 | 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values); |
832 | 825 | ||
833 | static const struct snd_kcontrol_new rt5640_dac_l2_mux = | 826 | static const struct snd_kcontrol_new rt5640_dac_l2_mux = |
834 | SOC_DAPM_VALUE_ENUM("DAC2 left channel source", rt5640_dac_l2_enum); | 827 | SOC_DAPM_VALUE_ENUM("DAC2 left channel source", rt5640_dac_l2_enum); |
@@ -841,9 +834,9 @@ static int rt5640_dac_r2_values[] = { | |||
841 | 0, | 834 | 0, |
842 | }; | 835 | }; |
843 | 836 | ||
844 | static const SOC_VALUE_ENUM_SINGLE_DECL( | 837 | static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_r2_enum, |
845 | rt5640_dac_r2_enum, RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT, | 838 | RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT, |
846 | 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values); | 839 | 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values); |
847 | 840 | ||
848 | static const struct snd_kcontrol_new rt5640_dac_r2_mux = | 841 | static const struct snd_kcontrol_new rt5640_dac_r2_mux = |
849 | SOC_DAPM_ENUM("DAC2 right channel source", rt5640_dac_r2_enum); | 842 | SOC_DAPM_ENUM("DAC2 right channel source", rt5640_dac_r2_enum); |
@@ -860,9 +853,10 @@ static int rt5640_dai_iis_map_values[] = { | |||
860 | 7, | 853 | 7, |
861 | }; | 854 | }; |
862 | 855 | ||
863 | static const SOC_VALUE_ENUM_SINGLE_DECL( | 856 | static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dai_iis_map_enum, |
864 | rt5640_dai_iis_map_enum, RT5640_I2S1_SDP, RT5640_I2S_IF_SFT, | 857 | RT5640_I2S1_SDP, RT5640_I2S_IF_SFT, |
865 | 0x7, rt5640_dai_iis_map, rt5640_dai_iis_map_values); | 858 | 0x7, rt5640_dai_iis_map, |
859 | rt5640_dai_iis_map_values); | ||
866 | 860 | ||
867 | static const struct snd_kcontrol_new rt5640_dai_mux = | 861 | static const struct snd_kcontrol_new rt5640_dai_mux = |
868 | SOC_DAPM_VALUE_ENUM("DAI select", rt5640_dai_iis_map_enum); | 862 | SOC_DAPM_VALUE_ENUM("DAI select", rt5640_dai_iis_map_enum); |
@@ -872,9 +866,8 @@ static const char * const rt5640_sdi_sel[] = { | |||
872 | "IF1", "IF2" | 866 | "IF1", "IF2" |
873 | }; | 867 | }; |
874 | 868 | ||
875 | static const SOC_ENUM_SINGLE_DECL( | 869 | static SOC_ENUM_SINGLE_DECL(rt5640_sdi_sel_enum, RT5640_I2S2_SDP, |
876 | rt5640_sdi_sel_enum, RT5640_I2S2_SDP, | 870 | RT5640_I2S2_SDI_SFT, rt5640_sdi_sel); |
877 | RT5640_I2S2_SDI_SFT, rt5640_sdi_sel); | ||
878 | 871 | ||
879 | static const struct snd_kcontrol_new rt5640_sdi_mux = | 872 | static const struct snd_kcontrol_new rt5640_sdi_mux = |
880 | SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum); | 873 | SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum); |
@@ -1601,8 +1594,7 @@ static int get_clk_info(int sclk, int rate) | |||
1601 | static int rt5640_hw_params(struct snd_pcm_substream *substream, | 1594 | static int rt5640_hw_params(struct snd_pcm_substream *substream, |
1602 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 1595 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
1603 | { | 1596 | { |
1604 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1597 | struct snd_soc_codec *codec = dai->codec; |
1605 | struct snd_soc_codec *codec = rtd->codec; | ||
1606 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | 1598 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); |
1607 | unsigned int val_len = 0, val_clk, mask_clk; | 1599 | unsigned int val_len = 0, val_clk, mask_clk; |
1608 | int dai_sel, pre_div, bclk_ms, frame_size; | 1600 | int dai_sel, pre_div, bclk_ms, frame_size; |
@@ -1943,16 +1935,8 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec, | |||
1943 | static int rt5640_probe(struct snd_soc_codec *codec) | 1935 | static int rt5640_probe(struct snd_soc_codec *codec) |
1944 | { | 1936 | { |
1945 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | 1937 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); |
1946 | int ret; | ||
1947 | 1938 | ||
1948 | rt5640->codec = codec; | 1939 | rt5640->codec = codec; |
1949 | codec->control_data = rt5640->regmap; | ||
1950 | |||
1951 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
1952 | if (ret != 0) { | ||
1953 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1954 | return ret; | ||
1955 | } | ||
1956 | 1940 | ||
1957 | codec->dapm.idle_bias_off = 1; | 1941 | codec->dapm.idle_bias_off = 1; |
1958 | rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1942 | rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF); |
@@ -2093,6 +2077,7 @@ MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id); | |||
2093 | #ifdef CONFIG_ACPI | 2077 | #ifdef CONFIG_ACPI |
2094 | static struct acpi_device_id rt5640_acpi_match[] = { | 2078 | static struct acpi_device_id rt5640_acpi_match[] = { |
2095 | { "INT33CA", 0 }, | 2079 | { "INT33CA", 0 }, |
2080 | { "10EC5640", 0 }, | ||
2096 | { }, | 2081 | { }, |
2097 | }; | 2082 | }; |
2098 | MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match); | 2083 | MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match); |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 0fcbe90f3ef2..d3ed1be5a186 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -187,8 +187,9 @@ static const char *adc_mux_text[] = { | |||
187 | "MIC_IN", "LINE_IN" | 187 | "MIC_IN", "LINE_IN" |
188 | }; | 188 | }; |
189 | 189 | ||
190 | static const struct soc_enum adc_enum = | 190 | static SOC_ENUM_SINGLE_DECL(adc_enum, |
191 | SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 2, 2, adc_mux_text); | 191 | SGTL5000_CHIP_ANA_CTRL, 2, |
192 | adc_mux_text); | ||
192 | 193 | ||
193 | static const struct snd_kcontrol_new adc_mux = | 194 | static const struct snd_kcontrol_new adc_mux = |
194 | SOC_DAPM_ENUM("Capture Mux", adc_enum); | 195 | SOC_DAPM_ENUM("Capture Mux", adc_enum); |
@@ -198,8 +199,9 @@ static const char *dac_mux_text[] = { | |||
198 | "DAC", "LINE_IN" | 199 | "DAC", "LINE_IN" |
199 | }; | 200 | }; |
200 | 201 | ||
201 | static const struct soc_enum dac_enum = | 202 | static SOC_ENUM_SINGLE_DECL(dac_enum, |
202 | SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 6, 2, dac_mux_text); | 203 | SGTL5000_CHIP_ANA_CTRL, 6, |
204 | dac_mux_text); | ||
203 | 205 | ||
204 | static const struct snd_kcontrol_new dac_mux = | 206 | static const struct snd_kcontrol_new dac_mux = |
205 | SOC_DAPM_ENUM("Headphone Mux", dac_enum); | 207 | SOC_DAPM_ENUM("Headphone Mux", dac_enum); |
@@ -1350,14 +1352,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) | |||
1350 | int ret; | 1352 | int ret; |
1351 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | 1353 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); |
1352 | 1354 | ||
1353 | /* setup i2c data ops */ | ||
1354 | codec->control_data = sgtl5000->regmap; | ||
1355 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | ||
1356 | if (ret < 0) { | ||
1357 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1358 | return ret; | ||
1359 | } | ||
1360 | |||
1361 | ret = sgtl5000_enable_regulators(codec); | 1355 | ret = sgtl5000_enable_regulators(codec); |
1362 | if (ret) | 1356 | if (ret) |
1363 | return ret; | 1357 | return ret; |
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index 52e7cb08434b..244c097cd905 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 23 | #include <sound/pcm_params.h> |
24 | #include <linux/regmap.h> | ||
24 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
25 | #include <sound/initval.h> | 26 | #include <sound/initval.h> |
26 | 27 | ||
@@ -209,8 +210,9 @@ out: | |||
209 | 210 | ||
210 | static int si476x_codec_probe(struct snd_soc_codec *codec) | 211 | static int si476x_codec_probe(struct snd_soc_codec *codec) |
211 | { | 212 | { |
212 | codec->control_data = dev_get_regmap(codec->dev->parent, NULL); | 213 | struct regmap *regmap = dev_get_regmap(codec->dev->parent, NULL); |
213 | return 0; | 214 | |
215 | return snd_soc_codec_set_cache_io(codec, regmap); | ||
214 | } | 216 | } |
215 | 217 | ||
216 | static struct snd_soc_dai_ops si476x_dai_ops = { | 218 | static struct snd_soc_dai_ops si476x_dai_ops = { |
diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c new file mode 100644 index 000000000000..90e3a228bae4 --- /dev/null +++ b/sound/soc/codecs/sirf-audio-codec.c | |||
@@ -0,0 +1,533 @@ | |||
1 | /* | ||
2 | * SiRF audio codec driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/pm_runtime.h> | ||
12 | #include <linux/of.h> | ||
13 | #include <linux/of_device.h> | ||
14 | #include <linux/clk.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/regmap.h> | ||
18 | #include <sound/core.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/pcm_params.h> | ||
21 | #include <sound/initval.h> | ||
22 | #include <sound/tlv.h> | ||
23 | #include <sound/soc.h> | ||
24 | #include <sound/dmaengine_pcm.h> | ||
25 | |||
26 | #include "sirf-audio-codec.h" | ||
27 | |||
28 | struct sirf_audio_codec { | ||
29 | struct clk *clk; | ||
30 | struct regmap *regmap; | ||
31 | u32 reg_ctrl0, reg_ctrl1; | ||
32 | }; | ||
33 | |||
34 | static const char * const input_mode_mux[] = {"Single-ended", | ||
35 | "Differential"}; | ||
36 | |||
37 | static const struct soc_enum input_mode_mux_enum = | ||
38 | SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux); | ||
39 | |||
40 | static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control = | ||
41 | SOC_DAPM_ENUM("Route", input_mode_mux_enum); | ||
42 | |||
43 | static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0); | ||
44 | static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0); | ||
45 | static const DECLARE_TLV_DB_RANGE(capture_vol_tlv_atlas6, | ||
46 | 0, 7, TLV_DB_SCALE_ITEM(-100, 100, 0), | ||
47 | 0x22, 0x3F, TLV_DB_SCALE_ITEM(700, 100, 0), | ||
48 | ); | ||
49 | |||
50 | static struct snd_kcontrol_new volume_controls_atlas6[] = { | ||
51 | SOC_DOUBLE_TLV("Playback Volume", AUDIO_IC_CODEC_CTRL0, 21, 14, | ||
52 | 0x7F, 0, playback_vol_tlv), | ||
53 | SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 16, 10, | ||
54 | 0x3F, 0, capture_vol_tlv_atlas6), | ||
55 | }; | ||
56 | |||
57 | static struct snd_kcontrol_new volume_controls_prima2[] = { | ||
58 | SOC_DOUBLE_TLV("Speaker Volume", AUDIO_IC_CODEC_CTRL0, 21, 14, | ||
59 | 0x7F, 0, playback_vol_tlv), | ||
60 | SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 15, 10, | ||
61 | 0x1F, 0, capture_vol_tlv_prima2), | ||
62 | }; | ||
63 | |||
64 | static struct snd_kcontrol_new left_input_path_controls[] = { | ||
65 | SOC_DAPM_SINGLE("Line Left Switch", AUDIO_IC_CODEC_CTRL1, 6, 1, 0), | ||
66 | SOC_DAPM_SINGLE("Mic Left Switch", AUDIO_IC_CODEC_CTRL1, 3, 1, 0), | ||
67 | }; | ||
68 | |||
69 | static struct snd_kcontrol_new right_input_path_controls[] = { | ||
70 | SOC_DAPM_SINGLE("Line Right Switch", AUDIO_IC_CODEC_CTRL1, 5, 1, 0), | ||
71 | SOC_DAPM_SINGLE("Mic Right Switch", AUDIO_IC_CODEC_CTRL1, 2, 1, 0), | ||
72 | }; | ||
73 | |||
74 | static struct snd_kcontrol_new left_dac_to_hp_left_amp_switch_control = | ||
75 | SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 9, 1, 0); | ||
76 | |||
77 | static struct snd_kcontrol_new left_dac_to_hp_right_amp_switch_control = | ||
78 | SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 8, 1, 0); | ||
79 | |||
80 | static struct snd_kcontrol_new right_dac_to_hp_left_amp_switch_control = | ||
81 | SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 7, 1, 0); | ||
82 | |||
83 | static struct snd_kcontrol_new right_dac_to_hp_right_amp_switch_control = | ||
84 | SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 6, 1, 0); | ||
85 | |||
86 | static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control = | ||
87 | SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0); | ||
88 | |||
89 | static struct snd_kcontrol_new right_dac_to_speaker_lineout_switch_control = | ||
90 | SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 10, 1, 0); | ||
91 | |||
92 | /* After enable adc, Delay 200ms to avoid pop noise */ | ||
93 | static int adc_enable_delay_event(struct snd_soc_dapm_widget *w, | ||
94 | struct snd_kcontrol *kcontrol, int event) | ||
95 | { | ||
96 | switch (event) { | ||
97 | case SND_SOC_DAPM_POST_PMU: | ||
98 | msleep(200); | ||
99 | break; | ||
100 | default: | ||
101 | break; | ||
102 | } | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static void enable_and_reset_codec(struct regmap *regmap, | ||
108 | u32 codec_enable_bits, u32 codec_reset_bits) | ||
109 | { | ||
110 | regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, | ||
111 | codec_enable_bits | codec_reset_bits, | ||
112 | codec_enable_bits | ~codec_reset_bits); | ||
113 | msleep(20); | ||
114 | regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, | ||
115 | codec_reset_bits, codec_reset_bits); | ||
116 | } | ||
117 | |||
118 | static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, | ||
119 | struct snd_kcontrol *kcontrol, int event) | ||
120 | { | ||
121 | #define ATLAS6_CODEC_ENABLE_BITS (1 << 29) | ||
122 | #define ATLAS6_CODEC_RESET_BITS (1 << 28) | ||
123 | struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev); | ||
124 | switch (event) { | ||
125 | case SND_SOC_DAPM_PRE_PMU: | ||
126 | enable_and_reset_codec(sirf_audio_codec->regmap, | ||
127 | ATLAS6_CODEC_ENABLE_BITS, ATLAS6_CODEC_RESET_BITS); | ||
128 | break; | ||
129 | case SND_SOC_DAPM_POST_PMD: | ||
130 | regmap_update_bits(sirf_audio_codec->regmap, | ||
131 | AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, | ||
132 | ~ATLAS6_CODEC_ENABLE_BITS); | ||
133 | break; | ||
134 | default: | ||
135 | break; | ||
136 | } | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, | ||
142 | struct snd_kcontrol *kcontrol, int event) | ||
143 | { | ||
144 | #define PRIMA2_CODEC_ENABLE_BITS (1 << 27) | ||
145 | #define PRIMA2_CODEC_RESET_BITS (1 << 26) | ||
146 | struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev); | ||
147 | switch (event) { | ||
148 | case SND_SOC_DAPM_POST_PMU: | ||
149 | enable_and_reset_codec(sirf_audio_codec->regmap, | ||
150 | PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS); | ||
151 | break; | ||
152 | case SND_SOC_DAPM_POST_PMD: | ||
153 | regmap_update_bits(sirf_audio_codec->regmap, | ||
154 | AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, | ||
155 | ~PRIMA2_CODEC_ENABLE_BITS); | ||
156 | break; | ||
157 | default: | ||
158 | break; | ||
159 | } | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = { | ||
165 | SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1, | ||
166 | 25, 0, NULL, 0), | ||
167 | SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1, | ||
168 | 26, 0, NULL, 0), | ||
169 | SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1, | ||
170 | 27, 0, NULL, 0), | ||
171 | }; | ||
172 | |||
173 | static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = { | ||
174 | SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1, | ||
175 | 23, 0, NULL, 0), | ||
176 | SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1, | ||
177 | 24, 0, NULL, 0), | ||
178 | SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1, | ||
179 | 25, 0, NULL, 0), | ||
180 | }; | ||
181 | |||
182 | static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget = | ||
183 | SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0, | ||
184 | atlas6_codec_enable_and_reset_event, | ||
185 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD); | ||
186 | |||
187 | static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget = | ||
188 | SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0, | ||
189 | prima2_codec_enable_and_reset_event, | ||
190 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD); | ||
191 | |||
192 | static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = { | ||
193 | SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0), | ||
194 | SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0), | ||
195 | SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0, | ||
196 | &left_dac_to_hp_left_amp_switch_control), | ||
197 | SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0, | ||
198 | &left_dac_to_hp_right_amp_switch_control), | ||
199 | SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0, | ||
200 | &right_dac_to_hp_left_amp_switch_control), | ||
201 | SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0, | ||
202 | &right_dac_to_hp_right_amp_switch_control), | ||
203 | SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0, | ||
204 | NULL, 0), | ||
205 | SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0, | ||
206 | NULL, 0), | ||
207 | |||
208 | SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0, | ||
209 | &left_dac_to_speaker_lineout_switch_control), | ||
210 | SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0, | ||
211 | &right_dac_to_speaker_lineout_switch_control), | ||
212 | SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0, | ||
213 | NULL, 0), | ||
214 | |||
215 | SND_SOC_DAPM_OUTPUT("HPOUTL"), | ||
216 | SND_SOC_DAPM_OUTPUT("HPOUTR"), | ||
217 | SND_SOC_DAPM_OUTPUT("SPKOUT"), | ||
218 | |||
219 | SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0, | ||
220 | adc_enable_delay_event, SND_SOC_DAPM_POST_PMU), | ||
221 | SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0, | ||
222 | adc_enable_delay_event, SND_SOC_DAPM_POST_PMU), | ||
223 | SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0, | ||
224 | &left_input_path_controls[0], | ||
225 | ARRAY_SIZE(left_input_path_controls)), | ||
226 | SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0, | ||
227 | &right_input_path_controls[0], | ||
228 | ARRAY_SIZE(right_input_path_controls)), | ||
229 | |||
230 | SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0, | ||
231 | &sirf_audio_codec_input_mode_control), | ||
232 | SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0), | ||
233 | SND_SOC_DAPM_INPUT("MICIN1"), | ||
234 | SND_SOC_DAPM_INPUT("MICIN2"), | ||
235 | SND_SOC_DAPM_INPUT("LINEIN1"), | ||
236 | SND_SOC_DAPM_INPUT("LINEIN2"), | ||
237 | |||
238 | SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0, | ||
239 | 30, 0, NULL, 0), | ||
240 | }; | ||
241 | |||
242 | static const struct snd_soc_dapm_route sirf_audio_codec_map[] = { | ||
243 | {"SPKOUT", NULL, "Speaker Driver"}, | ||
244 | {"Speaker Driver", NULL, "Speaker amp driver"}, | ||
245 | {"Speaker amp driver", NULL, "Left dac to speaker lineout"}, | ||
246 | {"Speaker amp driver", NULL, "Right dac to speaker lineout"}, | ||
247 | {"Left dac to speaker lineout", "Switch", "DAC left"}, | ||
248 | {"Right dac to speaker lineout", "Switch", "DAC right"}, | ||
249 | {"HPOUTL", NULL, "HP Left Driver"}, | ||
250 | {"HPOUTR", NULL, "HP Right Driver"}, | ||
251 | {"HP Left Driver", NULL, "HP amp left driver"}, | ||
252 | {"HP Right Driver", NULL, "HP amp right driver"}, | ||
253 | {"HP amp left driver", NULL, "Right dac to hp left amp"}, | ||
254 | {"HP amp right driver", NULL , "Right dac to hp right amp"}, | ||
255 | {"HP amp left driver", NULL, "Left dac to hp left amp"}, | ||
256 | {"HP amp right driver", NULL , "Right dac to hp right amp"}, | ||
257 | {"Right dac to hp left amp", "Switch", "DAC left"}, | ||
258 | {"Right dac to hp right amp", "Switch", "DAC right"}, | ||
259 | {"Left dac to hp left amp", "Switch", "DAC left"}, | ||
260 | {"Left dac to hp right amp", "Switch", "DAC right"}, | ||
261 | {"DAC left", NULL, "codecclk"}, | ||
262 | {"DAC right", NULL, "codecclk"}, | ||
263 | {"DAC left", NULL, "Playback"}, | ||
264 | {"DAC right", NULL, "Playback"}, | ||
265 | {"DAC left", NULL, "HSL Phase Opposite"}, | ||
266 | {"DAC right", NULL, "HSL Phase Opposite"}, | ||
267 | |||
268 | {"Capture", NULL, "ADC left"}, | ||
269 | {"Capture", NULL, "ADC right"}, | ||
270 | {"ADC left", NULL, "codecclk"}, | ||
271 | {"ADC right", NULL, "codecclk"}, | ||
272 | {"ADC left", NULL, "Left PGA mixer"}, | ||
273 | {"ADC right", NULL, "Right PGA mixer"}, | ||
274 | {"Left PGA mixer", "Line Left Switch", "LINEIN2"}, | ||
275 | {"Right PGA mixer", "Line Right Switch", "LINEIN1"}, | ||
276 | {"Left PGA mixer", "Mic Left Switch", "MICIN2"}, | ||
277 | {"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"}, | ||
278 | {"Mic input mode mux", "Single-ended", "MICIN1"}, | ||
279 | {"Mic input mode mux", "Differential", "MICIN1"}, | ||
280 | }; | ||
281 | |||
282 | static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream, | ||
283 | int cmd, | ||
284 | struct snd_soc_dai *dai) | ||
285 | { | ||
286 | int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
287 | struct snd_soc_codec *codec = dai->codec; | ||
288 | u32 val = 0; | ||
289 | |||
290 | /* | ||
291 | * This is a workaround, When stop playback, | ||
292 | * need disable HP amp, avoid the current noise. | ||
293 | */ | ||
294 | switch (cmd) { | ||
295 | case SNDRV_PCM_TRIGGER_STOP: | ||
296 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
297 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
298 | break; | ||
299 | case SNDRV_PCM_TRIGGER_START: | ||
300 | case SNDRV_PCM_TRIGGER_RESUME: | ||
301 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
302 | if (playback) | ||
303 | val = IC_HSLEN | IC_HSREN; | ||
304 | break; | ||
305 | default: | ||
306 | return -EINVAL; | ||
307 | } | ||
308 | |||
309 | if (playback) | ||
310 | snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, | ||
311 | IC_HSLEN | IC_HSREN, val); | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | struct snd_soc_dai_ops sirf_audio_codec_dai_ops = { | ||
316 | .trigger = sirf_audio_codec_trigger, | ||
317 | }; | ||
318 | |||
319 | struct snd_soc_dai_driver sirf_audio_codec_dai = { | ||
320 | .name = "sirf-audio-codec", | ||
321 | .playback = { | ||
322 | .stream_name = "Playback", | ||
323 | .channels_min = 2, | ||
324 | .channels_max = 2, | ||
325 | .rates = SNDRV_PCM_RATE_48000, | ||
326 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
327 | }, | ||
328 | .capture = { | ||
329 | .stream_name = "Capture", | ||
330 | .channels_min = 1, | ||
331 | .channels_max = 2, | ||
332 | .rates = SNDRV_PCM_RATE_48000, | ||
333 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
334 | }, | ||
335 | .ops = &sirf_audio_codec_dai_ops, | ||
336 | }; | ||
337 | |||
338 | static int sirf_audio_codec_probe(struct snd_soc_codec *codec) | ||
339 | { | ||
340 | int ret; | ||
341 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
342 | struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec); | ||
343 | |||
344 | pm_runtime_enable(codec->dev); | ||
345 | codec->control_data = sirf_audio_codec->regmap; | ||
346 | |||
347 | ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
348 | if (ret != 0) { | ||
349 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
350 | return ret; | ||
351 | } | ||
352 | |||
353 | if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) { | ||
354 | snd_soc_dapm_new_controls(dapm, | ||
355 | prima2_output_driver_dapm_widgets, | ||
356 | ARRAY_SIZE(prima2_output_driver_dapm_widgets)); | ||
357 | snd_soc_dapm_new_controls(dapm, | ||
358 | &prima2_codec_clock_dapm_widget, 1); | ||
359 | return snd_soc_add_codec_controls(codec, | ||
360 | volume_controls_prima2, | ||
361 | ARRAY_SIZE(volume_controls_prima2)); | ||
362 | } | ||
363 | if (of_device_is_compatible(codec->dev->of_node, "sirf,atlas6-audio-codec")) { | ||
364 | snd_soc_dapm_new_controls(dapm, | ||
365 | atlas6_output_driver_dapm_widgets, | ||
366 | ARRAY_SIZE(atlas6_output_driver_dapm_widgets)); | ||
367 | snd_soc_dapm_new_controls(dapm, | ||
368 | &atlas6_codec_clock_dapm_widget, 1); | ||
369 | return snd_soc_add_codec_controls(codec, | ||
370 | volume_controls_atlas6, | ||
371 | ARRAY_SIZE(volume_controls_atlas6)); | ||
372 | } | ||
373 | |||
374 | return -EINVAL; | ||
375 | } | ||
376 | |||
377 | static int sirf_audio_codec_remove(struct snd_soc_codec *codec) | ||
378 | { | ||
379 | pm_runtime_disable(codec->dev); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static struct snd_soc_codec_driver soc_codec_device_sirf_audio_codec = { | ||
384 | .probe = sirf_audio_codec_probe, | ||
385 | .remove = sirf_audio_codec_remove, | ||
386 | .dapm_widgets = sirf_audio_codec_dapm_widgets, | ||
387 | .num_dapm_widgets = ARRAY_SIZE(sirf_audio_codec_dapm_widgets), | ||
388 | .dapm_routes = sirf_audio_codec_map, | ||
389 | .num_dapm_routes = ARRAY_SIZE(sirf_audio_codec_map), | ||
390 | .idle_bias_off = true, | ||
391 | }; | ||
392 | |||
393 | static const struct of_device_id sirf_audio_codec_of_match[] = { | ||
394 | { .compatible = "sirf,prima2-audio-codec" }, | ||
395 | { .compatible = "sirf,atlas6-audio-codec" }, | ||
396 | {} | ||
397 | }; | ||
398 | MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match); | ||
399 | |||
400 | static const struct regmap_config sirf_audio_codec_regmap_config = { | ||
401 | .reg_bits = 32, | ||
402 | .reg_stride = 4, | ||
403 | .val_bits = 32, | ||
404 | .max_register = AUDIO_IC_CODEC_CTRL3, | ||
405 | .cache_type = REGCACHE_NONE, | ||
406 | }; | ||
407 | |||
408 | static int sirf_audio_codec_driver_probe(struct platform_device *pdev) | ||
409 | { | ||
410 | int ret; | ||
411 | struct sirf_audio_codec *sirf_audio_codec; | ||
412 | void __iomem *base; | ||
413 | struct resource *mem_res; | ||
414 | const struct of_device_id *match; | ||
415 | |||
416 | match = of_match_node(sirf_audio_codec_of_match, pdev->dev.of_node); | ||
417 | |||
418 | sirf_audio_codec = devm_kzalloc(&pdev->dev, | ||
419 | sizeof(struct sirf_audio_codec), GFP_KERNEL); | ||
420 | if (!sirf_audio_codec) | ||
421 | return -ENOMEM; | ||
422 | |||
423 | platform_set_drvdata(pdev, sirf_audio_codec); | ||
424 | |||
425 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
426 | base = devm_ioremap_resource(&pdev->dev, mem_res); | ||
427 | if (base == NULL) | ||
428 | return -ENOMEM; | ||
429 | |||
430 | sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base, | ||
431 | &sirf_audio_codec_regmap_config); | ||
432 | if (IS_ERR(sirf_audio_codec->regmap)) | ||
433 | return PTR_ERR(sirf_audio_codec->regmap); | ||
434 | |||
435 | sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL); | ||
436 | if (IS_ERR(sirf_audio_codec->clk)) { | ||
437 | dev_err(&pdev->dev, "Get clock failed.\n"); | ||
438 | return PTR_ERR(sirf_audio_codec->clk); | ||
439 | } | ||
440 | |||
441 | ret = clk_prepare_enable(sirf_audio_codec->clk); | ||
442 | if (ret) { | ||
443 | dev_err(&pdev->dev, "Enable clock failed.\n"); | ||
444 | return ret; | ||
445 | } | ||
446 | |||
447 | ret = snd_soc_register_codec(&(pdev->dev), | ||
448 | &soc_codec_device_sirf_audio_codec, | ||
449 | &sirf_audio_codec_dai, 1); | ||
450 | if (ret) { | ||
451 | dev_err(&pdev->dev, "Register Audio Codec dai failed.\n"); | ||
452 | goto err_clk_put; | ||
453 | } | ||
454 | |||
455 | /* | ||
456 | * Always open charge pump, if not, when the charge pump closed the | ||
457 | * adc will not stable | ||
458 | */ | ||
459 | regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, | ||
460 | IC_CPFREQ, IC_CPFREQ); | ||
461 | |||
462 | if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec")) | ||
463 | regmap_update_bits(sirf_audio_codec->regmap, | ||
464 | AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN); | ||
465 | return 0; | ||
466 | |||
467 | err_clk_put: | ||
468 | clk_disable_unprepare(sirf_audio_codec->clk); | ||
469 | return ret; | ||
470 | } | ||
471 | |||
472 | static int sirf_audio_codec_driver_remove(struct platform_device *pdev) | ||
473 | { | ||
474 | struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev); | ||
475 | |||
476 | clk_disable_unprepare(sirf_audio_codec->clk); | ||
477 | snd_soc_unregister_codec(&(pdev->dev)); | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | #ifdef CONFIG_PM_SLEEP | ||
483 | static int sirf_audio_codec_suspend(struct device *dev) | ||
484 | { | ||
485 | struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev); | ||
486 | |||
487 | regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, | ||
488 | &sirf_audio_codec->reg_ctrl0); | ||
489 | regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1, | ||
490 | &sirf_audio_codec->reg_ctrl1); | ||
491 | clk_disable_unprepare(sirf_audio_codec->clk); | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static int sirf_audio_codec_resume(struct device *dev) | ||
497 | { | ||
498 | struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev); | ||
499 | int ret; | ||
500 | |||
501 | ret = clk_prepare_enable(sirf_audio_codec->clk); | ||
502 | if (ret) | ||
503 | return ret; | ||
504 | |||
505 | regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, | ||
506 | sirf_audio_codec->reg_ctrl0); | ||
507 | regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1, | ||
508 | sirf_audio_codec->reg_ctrl1); | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | #endif | ||
513 | |||
514 | static const struct dev_pm_ops sirf_audio_codec_pm_ops = { | ||
515 | SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume) | ||
516 | }; | ||
517 | |||
518 | static struct platform_driver sirf_audio_codec_driver = { | ||
519 | .driver = { | ||
520 | .name = "sirf-audio-codec", | ||
521 | .owner = THIS_MODULE, | ||
522 | .of_match_table = sirf_audio_codec_of_match, | ||
523 | .pm = &sirf_audio_codec_pm_ops, | ||
524 | }, | ||
525 | .probe = sirf_audio_codec_driver_probe, | ||
526 | .remove = sirf_audio_codec_driver_remove, | ||
527 | }; | ||
528 | |||
529 | module_platform_driver(sirf_audio_codec_driver); | ||
530 | |||
531 | MODULE_DESCRIPTION("SiRF audio codec driver"); | ||
532 | MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>"); | ||
533 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/sirf-audio-codec.h b/sound/soc/codecs/sirf-audio-codec.h new file mode 100644 index 000000000000..d4c187b8e54a --- /dev/null +++ b/sound/soc/codecs/sirf-audio-codec.h | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * SiRF inner codec controllers define | ||
3 | * | ||
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #ifndef _SIRF_AUDIO_CODEC_H | ||
10 | #define _SIRF_AUDIO_CODEC_H | ||
11 | |||
12 | |||
13 | #define AUDIO_IC_CODEC_PWR (0x00E0) | ||
14 | #define AUDIO_IC_CODEC_CTRL0 (0x00E4) | ||
15 | #define AUDIO_IC_CODEC_CTRL1 (0x00E8) | ||
16 | #define AUDIO_IC_CODEC_CTRL2 (0x00EC) | ||
17 | #define AUDIO_IC_CODEC_CTRL3 (0x00F0) | ||
18 | |||
19 | #define MICBIASEN (1 << 3) | ||
20 | |||
21 | #define IC_RDACEN (1 << 0) | ||
22 | #define IC_LDACEN (1 << 1) | ||
23 | #define IC_HSREN (1 << 2) | ||
24 | #define IC_HSLEN (1 << 3) | ||
25 | #define IC_SPEN (1 << 4) | ||
26 | #define IC_CPEN (1 << 5) | ||
27 | |||
28 | #define IC_HPRSELR (1 << 6) | ||
29 | #define IC_HPLSELR (1 << 7) | ||
30 | #define IC_HPRSELL (1 << 8) | ||
31 | #define IC_HPLSELL (1 << 9) | ||
32 | #define IC_SPSELR (1 << 10) | ||
33 | #define IC_SPSELL (1 << 11) | ||
34 | |||
35 | #define IC_MONOR (1 << 12) | ||
36 | #define IC_MONOL (1 << 13) | ||
37 | |||
38 | #define IC_RXOSRSEL (1 << 28) | ||
39 | #define IC_CPFREQ (1 << 29) | ||
40 | #define IC_HSINVEN (1 << 30) | ||
41 | |||
42 | #define IC_MICINREN (1 << 0) | ||
43 | #define IC_MICINLEN (1 << 1) | ||
44 | #define IC_MICIN1SEL (1 << 2) | ||
45 | #define IC_MICIN2SEL (1 << 3) | ||
46 | #define IC_MICDIFSEL (1 << 4) | ||
47 | #define IC_LINEIN1SEL (1 << 5) | ||
48 | #define IC_LINEIN2SEL (1 << 6) | ||
49 | #define IC_RADCEN (1 << 7) | ||
50 | #define IC_LADCEN (1 << 8) | ||
51 | #define IC_ALM (1 << 9) | ||
52 | |||
53 | #define IC_DIGMICEN (1 << 22) | ||
54 | #define IC_DIGMICFREQ (1 << 23) | ||
55 | #define IC_ADC14B_12 (1 << 24) | ||
56 | #define IC_FIRDAC_HSL_EN (1 << 25) | ||
57 | #define IC_FIRDAC_HSR_EN (1 << 26) | ||
58 | #define IC_FIRDAC_LOUT_EN (1 << 27) | ||
59 | #define IC_POR (1 << 28) | ||
60 | #define IC_CODEC_CLK_EN (1 << 29) | ||
61 | #define IC_HP_3DB_BOOST (1 << 30) | ||
62 | |||
63 | #define IC_ADC_LEFT_GAIN_SHIFT 16 | ||
64 | #define IC_ADC_RIGHT_GAIN_SHIFT 10 | ||
65 | #define IC_ADC_GAIN_MASK 0x3F | ||
66 | #define IC_MIC_MAX_GAIN 0x39 | ||
67 | |||
68 | #define IC_RXPGAR_MASK 0x3F | ||
69 | #define IC_RXPGAR_SHIFT 14 | ||
70 | #define IC_RXPGAL_MASK 0x3F | ||
71 | #define IC_RXPGAL_SHIFT 21 | ||
72 | #define IC_RXPGAR 0x7B | ||
73 | #define IC_RXPGAL 0x7B | ||
74 | |||
75 | #endif /*__SIRF_AUDIO_CODEC_H*/ | ||
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 13045f2af4d3..42dff26b3a2a 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c | |||
@@ -312,14 +312,14 @@ static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w, | |||
312 | /* mux controls */ | 312 | /* mux controls */ |
313 | static const char *sn95031_mic_texts[] = { "AMIC", "LineIn" }; | 313 | static const char *sn95031_mic_texts[] = { "AMIC", "LineIn" }; |
314 | 314 | ||
315 | static const struct soc_enum sn95031_micl_enum = | 315 | static SOC_ENUM_SINGLE_DECL(sn95031_micl_enum, |
316 | SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 1, 2, sn95031_mic_texts); | 316 | SN95031_ADCCONFIG, 1, sn95031_mic_texts); |
317 | 317 | ||
318 | static const struct snd_kcontrol_new sn95031_micl_mux_control = | 318 | static const struct snd_kcontrol_new sn95031_micl_mux_control = |
319 | SOC_DAPM_ENUM("Route", sn95031_micl_enum); | 319 | SOC_DAPM_ENUM("Route", sn95031_micl_enum); |
320 | 320 | ||
321 | static const struct soc_enum sn95031_micr_enum = | 321 | static SOC_ENUM_SINGLE_DECL(sn95031_micr_enum, |
322 | SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 3, 2, sn95031_mic_texts); | 322 | SN95031_ADCCONFIG, 3, sn95031_mic_texts); |
323 | 323 | ||
324 | static const struct snd_kcontrol_new sn95031_micr_mux_control = | 324 | static const struct snd_kcontrol_new sn95031_micr_mux_control = |
325 | SOC_DAPM_ENUM("Route", sn95031_micr_enum); | 325 | SOC_DAPM_ENUM("Route", sn95031_micr_enum); |
@@ -328,26 +328,26 @@ static const char *sn95031_input_texts[] = { "DMIC1", "DMIC2", "DMIC3", | |||
328 | "DMIC4", "DMIC5", "DMIC6", | 328 | "DMIC4", "DMIC5", "DMIC6", |
329 | "ADC Left", "ADC Right" }; | 329 | "ADC Left", "ADC Right" }; |
330 | 330 | ||
331 | static const struct soc_enum sn95031_input1_enum = | 331 | static SOC_ENUM_SINGLE_DECL(sn95031_input1_enum, |
332 | SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 0, 8, sn95031_input_texts); | 332 | SN95031_AUDIOMUX12, 0, sn95031_input_texts); |
333 | 333 | ||
334 | static const struct snd_kcontrol_new sn95031_input1_mux_control = | 334 | static const struct snd_kcontrol_new sn95031_input1_mux_control = |
335 | SOC_DAPM_ENUM("Route", sn95031_input1_enum); | 335 | SOC_DAPM_ENUM("Route", sn95031_input1_enum); |
336 | 336 | ||
337 | static const struct soc_enum sn95031_input2_enum = | 337 | static SOC_ENUM_SINGLE_DECL(sn95031_input2_enum, |
338 | SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 4, 8, sn95031_input_texts); | 338 | SN95031_AUDIOMUX12, 4, sn95031_input_texts); |
339 | 339 | ||
340 | static const struct snd_kcontrol_new sn95031_input2_mux_control = | 340 | static const struct snd_kcontrol_new sn95031_input2_mux_control = |
341 | SOC_DAPM_ENUM("Route", sn95031_input2_enum); | 341 | SOC_DAPM_ENUM("Route", sn95031_input2_enum); |
342 | 342 | ||
343 | static const struct soc_enum sn95031_input3_enum = | 343 | static SOC_ENUM_SINGLE_DECL(sn95031_input3_enum, |
344 | SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 0, 8, sn95031_input_texts); | 344 | SN95031_AUDIOMUX34, 0, sn95031_input_texts); |
345 | 345 | ||
346 | static const struct snd_kcontrol_new sn95031_input3_mux_control = | 346 | static const struct snd_kcontrol_new sn95031_input3_mux_control = |
347 | SOC_DAPM_ENUM("Route", sn95031_input3_enum); | 347 | SOC_DAPM_ENUM("Route", sn95031_input3_enum); |
348 | 348 | ||
349 | static const struct soc_enum sn95031_input4_enum = | 349 | static SOC_ENUM_SINGLE_DECL(sn95031_input4_enum, |
350 | SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 4, 8, sn95031_input_texts); | 350 | SN95031_AUDIOMUX34, 4, sn95031_input_texts); |
351 | 351 | ||
352 | static const struct snd_kcontrol_new sn95031_input4_mux_control = | 352 | static const struct snd_kcontrol_new sn95031_input4_mux_control = |
353 | SOC_DAPM_ENUM("Route", sn95031_input4_enum); | 353 | SOC_DAPM_ENUM("Route", sn95031_input4_enum); |
@@ -359,19 +359,19 @@ static const char *sn95031_micmode_text[] = {"Single Ended", "Differential"}; | |||
359 | /* 0dB to 30dB in 10dB steps */ | 359 | /* 0dB to 30dB in 10dB steps */ |
360 | static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 10, 0); | 360 | static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 10, 0); |
361 | 361 | ||
362 | static const struct soc_enum sn95031_micmode1_enum = | 362 | static SOC_ENUM_SINGLE_DECL(sn95031_micmode1_enum, |
363 | SOC_ENUM_SINGLE(SN95031_MICAMP1, 1, 2, sn95031_micmode_text); | 363 | SN95031_MICAMP1, 1, sn95031_micmode_text); |
364 | static const struct soc_enum sn95031_micmode2_enum = | 364 | static SOC_ENUM_SINGLE_DECL(sn95031_micmode2_enum, |
365 | SOC_ENUM_SINGLE(SN95031_MICAMP2, 1, 2, sn95031_micmode_text); | 365 | SN95031_MICAMP2, 1, sn95031_micmode_text); |
366 | 366 | ||
367 | static const char *sn95031_dmic_cfg_text[] = {"GPO", "DMIC"}; | 367 | static const char *sn95031_dmic_cfg_text[] = {"GPO", "DMIC"}; |
368 | 368 | ||
369 | static const struct soc_enum sn95031_dmic12_cfg_enum = | 369 | static SOC_ENUM_SINGLE_DECL(sn95031_dmic12_cfg_enum, |
370 | SOC_ENUM_SINGLE(SN95031_DMICMUX, 0, 2, sn95031_dmic_cfg_text); | 370 | SN95031_DMICMUX, 0, sn95031_dmic_cfg_text); |
371 | static const struct soc_enum sn95031_dmic34_cfg_enum = | 371 | static SOC_ENUM_SINGLE_DECL(sn95031_dmic34_cfg_enum, |
372 | SOC_ENUM_SINGLE(SN95031_DMICMUX, 1, 2, sn95031_dmic_cfg_text); | 372 | SN95031_DMICMUX, 1, sn95031_dmic_cfg_text); |
373 | static const struct soc_enum sn95031_dmic56_cfg_enum = | 373 | static SOC_ENUM_SINGLE_DECL(sn95031_dmic56_cfg_enum, |
374 | SOC_ENUM_SINGLE(SN95031_DMICMUX, 2, 2, sn95031_dmic_cfg_text); | 374 | SN95031_DMICMUX, 2, sn95031_dmic_cfg_text); |
375 | 375 | ||
376 | static const struct snd_kcontrol_new sn95031_snd_controls[] = { | 376 | static const struct snd_kcontrol_new sn95031_snd_controls[] = { |
377 | SOC_ENUM("Mic1Mode Capture Route", sn95031_micmode1_enum), | 377 | SOC_ENUM("Mic1Mode Capture Route", sn95031_micmode1_enum), |
@@ -825,8 +825,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec) | |||
825 | { | 825 | { |
826 | pr_debug("codec_probe called\n"); | 826 | pr_debug("codec_probe called\n"); |
827 | 827 | ||
828 | snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
829 | |||
830 | /* PCM interface config | 828 | /* PCM interface config |
831 | * This sets the pcm rx slot conguration to max 6 slots | 829 | * This sets the pcm rx slot conguration to max 6 slots |
832 | * for max 4 dais (2 stereo and 2 mono) | 830 | * for max 4 dais (2 stereo and 2 mono) |
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index cc8debce752f..56adb3e2def9 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c | |||
@@ -169,19 +169,19 @@ static const char * const ssm2518_drc_hold_time_text[] = { | |||
169 | "682.24 ms", "1364 ms", | 169 | "682.24 ms", "1364 ms", |
170 | }; | 170 | }; |
171 | 171 | ||
172 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum, | 172 | static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum, |
173 | SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text); | 173 | SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text); |
174 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum, | 174 | static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum, |
175 | SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text); | 175 | SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text); |
176 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum, | 176 | static SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum, |
177 | SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text); | 177 | SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text); |
178 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum, | 178 | static SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum, |
179 | SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text); | 179 | SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text); |
180 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum, | 180 | static SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum, |
181 | SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text); | 181 | SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text); |
182 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum, | 182 | static SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum, |
183 | SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text); | 183 | SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text); |
184 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum, | 184 | static SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum, |
185 | SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text); | 185 | SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text); |
186 | 186 | ||
187 | static const struct snd_kcontrol_new ssm2518_snd_controls[] = { | 187 | static const struct snd_kcontrol_new ssm2518_snd_controls[] = { |
@@ -648,16 +648,6 @@ static struct snd_soc_dai_driver ssm2518_dai = { | |||
648 | 648 | ||
649 | static int ssm2518_probe(struct snd_soc_codec *codec) | 649 | static int ssm2518_probe(struct snd_soc_codec *codec) |
650 | { | 650 | { |
651 | struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec); | ||
652 | int ret; | ||
653 | |||
654 | codec->control_data = ssm2518->regmap; | ||
655 | ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
656 | if (ret < 0) { | ||
657 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
658 | return ret; | ||
659 | } | ||
660 | |||
661 | return ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF); | 651 | return ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF); |
662 | } | 652 | } |
663 | 653 | ||
diff --git a/sound/soc/codecs/ssm2602-i2c.c b/sound/soc/codecs/ssm2602-i2c.c new file mode 100644 index 000000000000..abd63d537173 --- /dev/null +++ b/sound/soc/codecs/ssm2602-i2c.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * SSM2602/SSM2603/SSM2604 I2C audio driver | ||
3 | * | ||
4 | * Copyright 2014 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/i2c.h> | ||
11 | #include <linux/regmap.h> | ||
12 | |||
13 | #include <sound/soc.h> | ||
14 | |||
15 | #include "ssm2602.h" | ||
16 | |||
17 | /* | ||
18 | * ssm2602 2 wire address is determined by GPIO5 | ||
19 | * state during powerup. | ||
20 | * low = 0x1a | ||
21 | * high = 0x1b | ||
22 | */ | ||
23 | static int ssm2602_i2c_probe(struct i2c_client *client, | ||
24 | const struct i2c_device_id *id) | ||
25 | { | ||
26 | return ssm2602_probe(&client->dev, id->driver_data, | ||
27 | devm_regmap_init_i2c(client, &ssm2602_regmap_config)); | ||
28 | } | ||
29 | |||
30 | static int ssm2602_i2c_remove(struct i2c_client *client) | ||
31 | { | ||
32 | snd_soc_unregister_codec(&client->dev); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static const struct i2c_device_id ssm2602_i2c_id[] = { | ||
37 | { "ssm2602", SSM2602 }, | ||
38 | { "ssm2603", SSM2602 }, | ||
39 | { "ssm2604", SSM2604 }, | ||
40 | { } | ||
41 | }; | ||
42 | MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); | ||
43 | |||
44 | static struct i2c_driver ssm2602_i2c_driver = { | ||
45 | .driver = { | ||
46 | .name = "ssm2602", | ||
47 | .owner = THIS_MODULE, | ||
48 | }, | ||
49 | .probe = ssm2602_i2c_probe, | ||
50 | .remove = ssm2602_i2c_remove, | ||
51 | .id_table = ssm2602_i2c_id, | ||
52 | }; | ||
53 | module_i2c_driver(ssm2602_i2c_driver); | ||
54 | |||
55 | MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 I2C driver"); | ||
56 | MODULE_AUTHOR("Cliff Cai"); | ||
57 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ssm2602-spi.c b/sound/soc/codecs/ssm2602-spi.c new file mode 100644 index 000000000000..2bf55e24a7bb --- /dev/null +++ b/sound/soc/codecs/ssm2602-spi.c | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * SSM2602 SPI audio driver | ||
3 | * | ||
4 | * Copyright 2014 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/spi/spi.h> | ||
11 | #include <linux/regmap.h> | ||
12 | |||
13 | #include <sound/soc.h> | ||
14 | |||
15 | #include "ssm2602.h" | ||
16 | |||
17 | static int ssm2602_spi_probe(struct spi_device *spi) | ||
18 | { | ||
19 | return ssm2602_probe(&spi->dev, SSM2602, | ||
20 | devm_regmap_init_spi(spi, &ssm2602_regmap_config)); | ||
21 | } | ||
22 | |||
23 | static int ssm2602_spi_remove(struct spi_device *spi) | ||
24 | { | ||
25 | snd_soc_unregister_codec(&spi->dev); | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | static struct spi_driver ssm2602_spi_driver = { | ||
30 | .driver = { | ||
31 | .name = "ssm2602", | ||
32 | .owner = THIS_MODULE, | ||
33 | }, | ||
34 | .probe = ssm2602_spi_probe, | ||
35 | .remove = ssm2602_spi_remove, | ||
36 | }; | ||
37 | module_spi_driver(ssm2602_spi_driver); | ||
38 | |||
39 | MODULE_DESCRIPTION("ASoC SSM2602 SPI driver"); | ||
40 | MODULE_AUTHOR("Cliff Cai"); | ||
41 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index af76bbd1b24f..97b0454eb346 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -27,32 +27,20 @@ | |||
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/moduleparam.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/pm.h> | ||
34 | #include <linux/i2c.h> | ||
35 | #include <linux/spi/spi.h> | ||
36 | #include <linux/regmap.h> | 30 | #include <linux/regmap.h> |
37 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
38 | #include <sound/core.h> | 32 | |
39 | #include <sound/pcm.h> | 33 | #include <sound/pcm.h> |
40 | #include <sound/pcm_params.h> | 34 | #include <sound/pcm_params.h> |
41 | #include <sound/soc.h> | 35 | #include <sound/soc.h> |
42 | #include <sound/initval.h> | ||
43 | #include <sound/tlv.h> | 36 | #include <sound/tlv.h> |
44 | 37 | ||
45 | #include "ssm2602.h" | 38 | #include "ssm2602.h" |
46 | 39 | ||
47 | enum ssm2602_type { | ||
48 | SSM2602, | ||
49 | SSM2604, | ||
50 | }; | ||
51 | |||
52 | /* codec private data */ | 40 | /* codec private data */ |
53 | struct ssm2602_priv { | 41 | struct ssm2602_priv { |
54 | unsigned int sysclk; | 42 | unsigned int sysclk; |
55 | struct snd_pcm_hw_constraint_list *sysclk_constraints; | 43 | const struct snd_pcm_hw_constraint_list *sysclk_constraints; |
56 | 44 | ||
57 | struct regmap *regmap; | 45 | struct regmap *regmap; |
58 | 46 | ||
@@ -75,15 +63,16 @@ static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = { | |||
75 | 63 | ||
76 | /*Appending several "None"s just for OSS mixer use*/ | 64 | /*Appending several "None"s just for OSS mixer use*/ |
77 | static const char *ssm2602_input_select[] = { | 65 | static const char *ssm2602_input_select[] = { |
78 | "Line", "Mic", "None", "None", "None", | 66 | "Line", "Mic", |
79 | "None", "None", "None", | ||
80 | }; | 67 | }; |
81 | 68 | ||
82 | static const char *ssm2602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; | 69 | static const char *ssm2602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; |
83 | 70 | ||
84 | static const struct soc_enum ssm2602_enum[] = { | 71 | static const struct soc_enum ssm2602_enum[] = { |
85 | SOC_ENUM_SINGLE(SSM2602_APANA, 2, 2, ssm2602_input_select), | 72 | SOC_ENUM_SINGLE(SSM2602_APANA, 2, ARRAY_SIZE(ssm2602_input_select), |
86 | SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, 4, ssm2602_deemph), | 73 | ssm2602_input_select), |
74 | SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, ARRAY_SIZE(ssm2602_deemph), | ||
75 | ssm2602_deemph), | ||
87 | }; | 76 | }; |
88 | 77 | ||
89 | static const unsigned int ssm260x_outmix_tlv[] = { | 78 | static const unsigned int ssm260x_outmix_tlv[] = { |
@@ -197,7 +186,7 @@ static const unsigned int ssm2602_rates_12288000[] = { | |||
197 | 8000, 16000, 32000, 48000, 96000, | 186 | 8000, 16000, 32000, 48000, 96000, |
198 | }; | 187 | }; |
199 | 188 | ||
200 | static struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { | 189 | static const struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { |
201 | .list = ssm2602_rates_12288000, | 190 | .list = ssm2602_rates_12288000, |
202 | .count = ARRAY_SIZE(ssm2602_rates_12288000), | 191 | .count = ARRAY_SIZE(ssm2602_rates_12288000), |
203 | }; | 192 | }; |
@@ -206,7 +195,7 @@ static const unsigned int ssm2602_rates_11289600[] = { | |||
206 | 8000, 44100, 88200, | 195 | 8000, 44100, 88200, |
207 | }; | 196 | }; |
208 | 197 | ||
209 | static struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { | 198 | static const struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { |
210 | .list = ssm2602_rates_11289600, | 199 | .list = ssm2602_rates_11289600, |
211 | .count = ARRAY_SIZE(ssm2602_rates_11289600), | 200 | .count = ARRAY_SIZE(ssm2602_rates_11289600), |
212 | }; | 201 | }; |
@@ -529,7 +518,7 @@ static int ssm2602_resume(struct snd_soc_codec *codec) | |||
529 | return 0; | 518 | return 0; |
530 | } | 519 | } |
531 | 520 | ||
532 | static int ssm2602_probe(struct snd_soc_codec *codec) | 521 | static int ssm2602_codec_probe(struct snd_soc_codec *codec) |
533 | { | 522 | { |
534 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 523 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
535 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 524 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
@@ -554,7 +543,7 @@ static int ssm2602_probe(struct snd_soc_codec *codec) | |||
554 | ARRAY_SIZE(ssm2602_routes)); | 543 | ARRAY_SIZE(ssm2602_routes)); |
555 | } | 544 | } |
556 | 545 | ||
557 | static int ssm2604_probe(struct snd_soc_codec *codec) | 546 | static int ssm2604_codec_probe(struct snd_soc_codec *codec) |
558 | { | 547 | { |
559 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 548 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
560 | int ret; | 549 | int ret; |
@@ -568,18 +557,11 @@ static int ssm2604_probe(struct snd_soc_codec *codec) | |||
568 | ARRAY_SIZE(ssm2604_routes)); | 557 | ARRAY_SIZE(ssm2604_routes)); |
569 | } | 558 | } |
570 | 559 | ||
571 | static int ssm260x_probe(struct snd_soc_codec *codec) | 560 | static int ssm260x_codec_probe(struct snd_soc_codec *codec) |
572 | { | 561 | { |
573 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 562 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
574 | int ret; | 563 | int ret; |
575 | 564 | ||
576 | codec->control_data = ssm2602->regmap; | ||
577 | ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
578 | if (ret < 0) { | ||
579 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
580 | return ret; | ||
581 | } | ||
582 | |||
583 | ret = regmap_write(ssm2602->regmap, SSM2602_RESET, 0); | 565 | ret = regmap_write(ssm2602->regmap, SSM2602_RESET, 0); |
584 | if (ret < 0) { | 566 | if (ret < 0) { |
585 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | 567 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
@@ -597,10 +579,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec) | |||
597 | 579 | ||
598 | switch (ssm2602->type) { | 580 | switch (ssm2602->type) { |
599 | case SSM2602: | 581 | case SSM2602: |
600 | ret = ssm2602_probe(codec); | 582 | ret = ssm2602_codec_probe(codec); |
601 | break; | 583 | break; |
602 | case SSM2604: | 584 | case SSM2604: |
603 | ret = ssm2604_probe(codec); | 585 | ret = ssm2604_codec_probe(codec); |
604 | break; | 586 | break; |
605 | } | 587 | } |
606 | 588 | ||
@@ -620,7 +602,7 @@ static int ssm2602_remove(struct snd_soc_codec *codec) | |||
620 | } | 602 | } |
621 | 603 | ||
622 | static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { | 604 | static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { |
623 | .probe = ssm260x_probe, | 605 | .probe = ssm260x_codec_probe, |
624 | .remove = ssm2602_remove, | 606 | .remove = ssm2602_remove, |
625 | .suspend = ssm2602_suspend, | 607 | .suspend = ssm2602_suspend, |
626 | .resume = ssm2602_resume, | 608 | .resume = ssm2602_resume, |
@@ -639,7 +621,7 @@ static bool ssm2602_register_volatile(struct device *dev, unsigned int reg) | |||
639 | return reg == SSM2602_RESET; | 621 | return reg == SSM2602_RESET; |
640 | } | 622 | } |
641 | 623 | ||
642 | static const struct regmap_config ssm2602_regmap_config = { | 624 | const struct regmap_config ssm2602_regmap_config = { |
643 | .val_bits = 9, | 625 | .val_bits = 9, |
644 | .reg_bits = 7, | 626 | .reg_bits = 7, |
645 | 627 | ||
@@ -650,134 +632,28 @@ static const struct regmap_config ssm2602_regmap_config = { | |||
650 | .reg_defaults_raw = ssm2602_reg, | 632 | .reg_defaults_raw = ssm2602_reg, |
651 | .num_reg_defaults_raw = ARRAY_SIZE(ssm2602_reg), | 633 | .num_reg_defaults_raw = ARRAY_SIZE(ssm2602_reg), |
652 | }; | 634 | }; |
635 | EXPORT_SYMBOL_GPL(ssm2602_regmap_config); | ||
653 | 636 | ||
654 | #if defined(CONFIG_SPI_MASTER) | 637 | int ssm2602_probe(struct device *dev, enum ssm2602_type type, |
655 | static int ssm2602_spi_probe(struct spi_device *spi) | 638 | struct regmap *regmap) |
656 | { | 639 | { |
657 | struct ssm2602_priv *ssm2602; | 640 | struct ssm2602_priv *ssm2602; |
658 | int ret; | ||
659 | |||
660 | ssm2602 = devm_kzalloc(&spi->dev, sizeof(struct ssm2602_priv), | ||
661 | GFP_KERNEL); | ||
662 | if (ssm2602 == NULL) | ||
663 | return -ENOMEM; | ||
664 | |||
665 | spi_set_drvdata(spi, ssm2602); | ||
666 | ssm2602->type = SSM2602; | ||
667 | 641 | ||
668 | ssm2602->regmap = devm_regmap_init_spi(spi, &ssm2602_regmap_config); | 642 | if (IS_ERR(regmap)) |
669 | if (IS_ERR(ssm2602->regmap)) | 643 | return PTR_ERR(regmap); |
670 | return PTR_ERR(ssm2602->regmap); | ||
671 | 644 | ||
672 | ret = snd_soc_register_codec(&spi->dev, | 645 | ssm2602 = devm_kzalloc(dev, sizeof(*ssm2602), GFP_KERNEL); |
673 | &soc_codec_dev_ssm2602, &ssm2602_dai, 1); | ||
674 | return ret; | ||
675 | } | ||
676 | |||
677 | static int ssm2602_spi_remove(struct spi_device *spi) | ||
678 | { | ||
679 | snd_soc_unregister_codec(&spi->dev); | ||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | static struct spi_driver ssm2602_spi_driver = { | ||
684 | .driver = { | ||
685 | .name = "ssm2602", | ||
686 | .owner = THIS_MODULE, | ||
687 | }, | ||
688 | .probe = ssm2602_spi_probe, | ||
689 | .remove = ssm2602_spi_remove, | ||
690 | }; | ||
691 | #endif | ||
692 | |||
693 | #if IS_ENABLED(CONFIG_I2C) | ||
694 | /* | ||
695 | * ssm2602 2 wire address is determined by GPIO5 | ||
696 | * state during powerup. | ||
697 | * low = 0x1a | ||
698 | * high = 0x1b | ||
699 | */ | ||
700 | static int ssm2602_i2c_probe(struct i2c_client *i2c, | ||
701 | const struct i2c_device_id *id) | ||
702 | { | ||
703 | struct ssm2602_priv *ssm2602; | ||
704 | int ret; | ||
705 | |||
706 | ssm2602 = devm_kzalloc(&i2c->dev, sizeof(struct ssm2602_priv), | ||
707 | GFP_KERNEL); | ||
708 | if (ssm2602 == NULL) | 646 | if (ssm2602 == NULL) |
709 | return -ENOMEM; | 647 | return -ENOMEM; |
710 | 648 | ||
711 | i2c_set_clientdata(i2c, ssm2602); | 649 | dev_set_drvdata(dev, ssm2602); |
712 | ssm2602->type = id->driver_data; | 650 | ssm2602->type = SSM2602; |
713 | 651 | ssm2602->regmap = regmap; | |
714 | ssm2602->regmap = devm_regmap_init_i2c(i2c, &ssm2602_regmap_config); | ||
715 | if (IS_ERR(ssm2602->regmap)) | ||
716 | return PTR_ERR(ssm2602->regmap); | ||
717 | |||
718 | ret = snd_soc_register_codec(&i2c->dev, | ||
719 | &soc_codec_dev_ssm2602, &ssm2602_dai, 1); | ||
720 | return ret; | ||
721 | } | ||
722 | |||
723 | static int ssm2602_i2c_remove(struct i2c_client *client) | ||
724 | { | ||
725 | snd_soc_unregister_codec(&client->dev); | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | static const struct i2c_device_id ssm2602_i2c_id[] = { | ||
730 | { "ssm2602", SSM2602 }, | ||
731 | { "ssm2603", SSM2602 }, | ||
732 | { "ssm2604", SSM2604 }, | ||
733 | { } | ||
734 | }; | ||
735 | MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); | ||
736 | |||
737 | /* corgi i2c codec control layer */ | ||
738 | static struct i2c_driver ssm2602_i2c_driver = { | ||
739 | .driver = { | ||
740 | .name = "ssm2602", | ||
741 | .owner = THIS_MODULE, | ||
742 | }, | ||
743 | .probe = ssm2602_i2c_probe, | ||
744 | .remove = ssm2602_i2c_remove, | ||
745 | .id_table = ssm2602_i2c_id, | ||
746 | }; | ||
747 | #endif | ||
748 | |||
749 | |||
750 | static int __init ssm2602_modinit(void) | ||
751 | { | ||
752 | int ret = 0; | ||
753 | |||
754 | #if defined(CONFIG_SPI_MASTER) | ||
755 | ret = spi_register_driver(&ssm2602_spi_driver); | ||
756 | if (ret) | ||
757 | return ret; | ||
758 | #endif | ||
759 | |||
760 | #if IS_ENABLED(CONFIG_I2C) | ||
761 | ret = i2c_add_driver(&ssm2602_i2c_driver); | ||
762 | if (ret) | ||
763 | return ret; | ||
764 | #endif | ||
765 | |||
766 | return ret; | ||
767 | } | ||
768 | module_init(ssm2602_modinit); | ||
769 | |||
770 | static void __exit ssm2602_exit(void) | ||
771 | { | ||
772 | #if defined(CONFIG_SPI_MASTER) | ||
773 | spi_unregister_driver(&ssm2602_spi_driver); | ||
774 | #endif | ||
775 | 652 | ||
776 | #if IS_ENABLED(CONFIG_I2C) | 653 | return snd_soc_register_codec(dev, &soc_codec_dev_ssm2602, |
777 | i2c_del_driver(&ssm2602_i2c_driver); | 654 | &ssm2602_dai, 1); |
778 | #endif | ||
779 | } | 655 | } |
780 | module_exit(ssm2602_exit); | 656 | EXPORT_SYMBOL_GPL(ssm2602_probe); |
781 | 657 | ||
782 | MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver"); | 658 | MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver"); |
783 | MODULE_AUTHOR("Cliff Cai"); | 659 | MODULE_AUTHOR("Cliff Cai"); |
diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h index fbd07d7b73ca..747538847689 100644 --- a/sound/soc/codecs/ssm2602.h +++ b/sound/soc/codecs/ssm2602.h | |||
@@ -28,6 +28,20 @@ | |||
28 | #ifndef _SSM2602_H | 28 | #ifndef _SSM2602_H |
29 | #define _SSM2602_H | 29 | #define _SSM2602_H |
30 | 30 | ||
31 | #include <linux/regmap.h> | ||
32 | |||
33 | struct device; | ||
34 | |||
35 | enum ssm2602_type { | ||
36 | SSM2602, | ||
37 | SSM2604, | ||
38 | }; | ||
39 | |||
40 | extern const struct regmap_config ssm2602_regmap_config; | ||
41 | |||
42 | int ssm2602_probe(struct device *dev, enum ssm2602_type type, | ||
43 | struct regmap *regmap); | ||
44 | |||
31 | /* SSM2602 Codec Register definitions */ | 45 | /* SSM2602 Codec Register definitions */ |
32 | 46 | ||
33 | #define SSM2602_LINVOL 0x00 | 47 | #define SSM2602_LINVOL 0x00 |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 06edb396e733..12577749b17b 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -187,42 +187,42 @@ static const unsigned int sta32x_limiter_drc_release_tlv[] = { | |||
187 | 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0), | 187 | 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0), |
188 | }; | 188 | }; |
189 | 189 | ||
190 | static const struct soc_enum sta32x_drc_ac_enum = | 190 | static SOC_ENUM_SINGLE_DECL(sta32x_drc_ac_enum, |
191 | SOC_ENUM_SINGLE(STA32X_CONFD, STA32X_CONFD_DRC_SHIFT, | 191 | STA32X_CONFD, STA32X_CONFD_DRC_SHIFT, |
192 | 2, sta32x_drc_ac); | 192 | sta32x_drc_ac); |
193 | static const struct soc_enum sta32x_auto_eq_enum = | 193 | static SOC_ENUM_SINGLE_DECL(sta32x_auto_eq_enum, |
194 | SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT, | 194 | STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT, |
195 | 3, sta32x_auto_eq_mode); | 195 | sta32x_auto_eq_mode); |
196 | static const struct soc_enum sta32x_auto_gc_enum = | 196 | static SOC_ENUM_SINGLE_DECL(sta32x_auto_gc_enum, |
197 | SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT, | 197 | STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT, |
198 | 4, sta32x_auto_gc_mode); | 198 | sta32x_auto_gc_mode); |
199 | static const struct soc_enum sta32x_auto_xo_enum = | 199 | static SOC_ENUM_SINGLE_DECL(sta32x_auto_xo_enum, |
200 | SOC_ENUM_SINGLE(STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT, | 200 | STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT, |
201 | 16, sta32x_auto_xo_mode); | 201 | sta32x_auto_xo_mode); |
202 | static const struct soc_enum sta32x_preset_eq_enum = | 202 | static SOC_ENUM_SINGLE_DECL(sta32x_preset_eq_enum, |
203 | SOC_ENUM_SINGLE(STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT, | 203 | STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT, |
204 | 32, sta32x_preset_eq_mode); | 204 | sta32x_preset_eq_mode); |
205 | static const struct soc_enum sta32x_limiter_ch1_enum = | 205 | static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch1_enum, |
206 | SOC_ENUM_SINGLE(STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT, | 206 | STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT, |
207 | 3, sta32x_limiter_select); | 207 | sta32x_limiter_select); |
208 | static const struct soc_enum sta32x_limiter_ch2_enum = | 208 | static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch2_enum, |
209 | SOC_ENUM_SINGLE(STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT, | 209 | STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT, |
210 | 3, sta32x_limiter_select); | 210 | sta32x_limiter_select); |
211 | static const struct soc_enum sta32x_limiter_ch3_enum = | 211 | static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch3_enum, |
212 | SOC_ENUM_SINGLE(STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT, | 212 | STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT, |
213 | 3, sta32x_limiter_select); | 213 | sta32x_limiter_select); |
214 | static const struct soc_enum sta32x_limiter1_attack_rate_enum = | 214 | static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_attack_rate_enum, |
215 | SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxA_SHIFT, | 215 | STA32X_L1AR, STA32X_LxA_SHIFT, |
216 | 16, sta32x_limiter_attack_rate); | 216 | sta32x_limiter_attack_rate); |
217 | static const struct soc_enum sta32x_limiter2_attack_rate_enum = | 217 | static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_attack_rate_enum, |
218 | SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxA_SHIFT, | 218 | STA32X_L2AR, STA32X_LxA_SHIFT, |
219 | 16, sta32x_limiter_attack_rate); | 219 | sta32x_limiter_attack_rate); |
220 | static const struct soc_enum sta32x_limiter1_release_rate_enum = | 220 | static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_release_rate_enum, |
221 | SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxR_SHIFT, | 221 | STA32X_L1AR, STA32X_LxR_SHIFT, |
222 | 16, sta32x_limiter_release_rate); | 222 | sta32x_limiter_release_rate); |
223 | static const struct soc_enum sta32x_limiter2_release_rate_enum = | 223 | static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_release_rate_enum, |
224 | SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxR_SHIFT, | 224 | STA32X_L2AR, STA32X_LxR_SHIFT, |
225 | 16, sta32x_limiter_release_rate); | 225 | sta32x_limiter_release_rate); |
226 | 226 | ||
227 | /* byte array controls for setting biquad, mixer, scaling coefficients; | 227 | /* byte array controls for setting biquad, mixer, scaling coefficients; |
228 | * for biquads all five coefficients need to be set in one go, | 228 | * for biquads all five coefficients need to be set in one go, |
@@ -331,7 +331,7 @@ static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec) | |||
331 | 331 | ||
332 | static int sta32x_cache_sync(struct snd_soc_codec *codec) | 332 | static int sta32x_cache_sync(struct snd_soc_codec *codec) |
333 | { | 333 | { |
334 | struct sta32x_priv *sta32x = codec->control_data; | 334 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); |
335 | unsigned int mute; | 335 | unsigned int mute; |
336 | int rc; | 336 | int rc; |
337 | 337 | ||
@@ -434,7 +434,7 @@ SOC_SINGLE_TLV("Treble Tone Control", STA32X_TONE, STA32X_TONE_TTC_SHIFT, 15, 0, | |||
434 | SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum), | 434 | SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum), |
435 | SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum), | 435 | SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum), |
436 | SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum), | 436 | SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum), |
437 | SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum), | 437 | SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter2_release_rate_enum), |
438 | 438 | ||
439 | /* depending on mode, the attack/release thresholds have | 439 | /* depending on mode, the attack/release thresholds have |
440 | * two different enum definitions; provide both | 440 | * two different enum definitions; provide both |
@@ -872,16 +872,6 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
872 | return ret; | 872 | return ret; |
873 | } | 873 | } |
874 | 874 | ||
875 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will | ||
876 | * then do the I2C transactions itself. | ||
877 | */ | ||
878 | codec->control_data = sta32x->regmap; | ||
879 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
880 | if (ret < 0) { | ||
881 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); | ||
882 | goto err; | ||
883 | } | ||
884 | |||
885 | /* Chip documentation explicitly requires that the reset values | 875 | /* Chip documentation explicitly requires that the reset values |
886 | * of reserved register bits are left untouched. | 876 | * of reserved register bits are left untouched. |
887 | * Write the register default value to cache for reserved registers, | 877 | * Write the register default value to cache for reserved registers, |
@@ -946,10 +936,6 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
946 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | 936 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); |
947 | 937 | ||
948 | return 0; | 938 | return 0; |
949 | |||
950 | err: | ||
951 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
952 | return ret; | ||
953 | } | 939 | } |
954 | 940 | ||
955 | static int sta32x_remove(struct snd_soc_codec *codec) | 941 | static int sta32x_remove(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 40c07be9b581..a40c4b0196a3 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c | |||
@@ -141,7 +141,7 @@ static const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary", | |||
141 | 141 | ||
142 | static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0); | 142 | static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0); |
143 | static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0); | 143 | static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0); |
144 | static const SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text); | 144 | static SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text); |
145 | 145 | ||
146 | static const struct snd_kcontrol_new sta529_snd_controls[] = { | 146 | static const struct snd_kcontrol_new sta529_snd_controls[] = { |
147 | SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0, | 147 | SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0, |
@@ -193,8 +193,7 @@ static int sta529_hw_params(struct snd_pcm_substream *substream, | |||
193 | struct snd_pcm_hw_params *params, | 193 | struct snd_pcm_hw_params *params, |
194 | struct snd_soc_dai *dai) | 194 | struct snd_soc_dai *dai) |
195 | { | 195 | { |
196 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 196 | struct snd_soc_codec *codec = dai->codec; |
197 | struct snd_soc_codec *codec = rtd->codec; | ||
198 | int pdata, play_freq_val, record_freq_val; | 197 | int pdata, play_freq_val, record_freq_val; |
199 | int bclk_to_fs_ratio; | 198 | int bclk_to_fs_ratio; |
200 | 199 | ||
@@ -322,16 +321,6 @@ static struct snd_soc_dai_driver sta529_dai = { | |||
322 | 321 | ||
323 | static int sta529_probe(struct snd_soc_codec *codec) | 322 | static int sta529_probe(struct snd_soc_codec *codec) |
324 | { | 323 | { |
325 | struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec); | ||
326 | int ret; | ||
327 | |||
328 | codec->control_data = sta529->regmap; | ||
329 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
330 | |||
331 | if (ret < 0) { | ||
332 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
333 | return ret; | ||
334 | } | ||
335 | sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 324 | sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
336 | 325 | ||
337 | return 0; | 326 | return 0; |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index a5455c1aea42..53b810d23fea 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
@@ -62,25 +62,25 @@ static const char *stac9766_boost1[] = {"0dB", "10dB"}; | |||
62 | static const char *stac9766_boost2[] = {"0dB", "20dB"}; | 62 | static const char *stac9766_boost2[] = {"0dB", "20dB"}; |
63 | static const char *stac9766_stereo_mic[] = {"Off", "On"}; | 63 | static const char *stac9766_stereo_mic[] = {"Off", "On"}; |
64 | 64 | ||
65 | static const struct soc_enum stac9766_record_enum = | 65 | static SOC_ENUM_DOUBLE_DECL(stac9766_record_enum, |
66 | SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, stac9766_record_mux); | 66 | AC97_REC_SEL, 8, 0, stac9766_record_mux); |
67 | static const struct soc_enum stac9766_mono_enum = | 67 | static SOC_ENUM_SINGLE_DECL(stac9766_mono_enum, |
68 | SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, stac9766_mono_mux); | 68 | AC97_GENERAL_PURPOSE, 9, stac9766_mono_mux); |
69 | static const struct soc_enum stac9766_mic_enum = | 69 | static SOC_ENUM_SINGLE_DECL(stac9766_mic_enum, |
70 | SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, stac9766_mic_mux); | 70 | AC97_GENERAL_PURPOSE, 8, stac9766_mic_mux); |
71 | static const struct soc_enum stac9766_SPDIF_enum = | 71 | static SOC_ENUM_SINGLE_DECL(stac9766_SPDIF_enum, |
72 | SOC_ENUM_SINGLE(AC97_STAC_DA_CONTROL, 1, 2, stac9766_SPDIF_mux); | 72 | AC97_STAC_DA_CONTROL, 1, stac9766_SPDIF_mux); |
73 | static const struct soc_enum stac9766_popbypass_enum = | 73 | static SOC_ENUM_SINGLE_DECL(stac9766_popbypass_enum, |
74 | SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, stac9766_popbypass_mux); | 74 | AC97_GENERAL_PURPOSE, 15, stac9766_popbypass_mux); |
75 | static const struct soc_enum stac9766_record_all_enum = | 75 | static SOC_ENUM_SINGLE_DECL(stac9766_record_all_enum, |
76 | SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 12, 2, | 76 | AC97_STAC_ANALOG_SPECIAL, 12, |
77 | stac9766_record_all_mux); | 77 | stac9766_record_all_mux); |
78 | static const struct soc_enum stac9766_boost1_enum = | 78 | static SOC_ENUM_SINGLE_DECL(stac9766_boost1_enum, |
79 | SOC_ENUM_SINGLE(AC97_MIC, 6, 2, stac9766_boost1); /* 0/10dB */ | 79 | AC97_MIC, 6, stac9766_boost1); /* 0/10dB */ |
80 | static const struct soc_enum stac9766_boost2_enum = | 80 | static SOC_ENUM_SINGLE_DECL(stac9766_boost2_enum, |
81 | SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 2, 2, stac9766_boost2); /* 0/20dB */ | 81 | AC97_STAC_ANALOG_SPECIAL, 2, stac9766_boost2); /* 0/20dB */ |
82 | static const struct soc_enum stac9766_stereo_mic_enum = | 82 | static SOC_ENUM_SINGLE_DECL(stac9766_stereo_mic_enum, |
83 | SOC_ENUM_SINGLE(AC97_STAC_STEREO_MIC, 2, 1, stac9766_stereo_mic); | 83 | AC97_STAC_STEREO_MIC, 2, stac9766_stereo_mic); |
84 | 84 | ||
85 | static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0); | 85 | static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0); |
86 | static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250); | 86 | static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250); |
diff --git a/sound/soc/codecs/tlv320aic23-i2c.c b/sound/soc/codecs/tlv320aic23-i2c.c new file mode 100644 index 000000000000..20fc46092c2c --- /dev/null +++ b/sound/soc/codecs/tlv320aic23-i2c.c | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * ALSA SoC TLV320AIC23 codec driver I2C interface | ||
3 | * | ||
4 | * Author: Arun KS, <arunks@mistralsolutions.com> | ||
5 | * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., | ||
6 | * | ||
7 | * Based on sound/soc/codecs/wm8731.c by Richard Purdie | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/regmap.h> | ||
17 | #include <sound/soc.h> | ||
18 | |||
19 | #include "tlv320aic23.h" | ||
20 | |||
21 | static int tlv320aic23_i2c_probe(struct i2c_client *i2c, | ||
22 | const struct i2c_device_id *i2c_id) | ||
23 | { | ||
24 | struct regmap *regmap; | ||
25 | |||
26 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
27 | return -EINVAL; | ||
28 | |||
29 | regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); | ||
30 | return tlv320aic23_probe(&i2c->dev, regmap); | ||
31 | } | ||
32 | |||
33 | static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) | ||
34 | { | ||
35 | snd_soc_unregister_codec(&i2c->dev); | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | static const struct i2c_device_id tlv320aic23_id[] = { | ||
40 | {"tlv320aic23", 0}, | ||
41 | {} | ||
42 | }; | ||
43 | |||
44 | MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); | ||
45 | |||
46 | static struct i2c_driver tlv320aic23_i2c_driver = { | ||
47 | .driver = { | ||
48 | .name = "tlv320aic23-codec", | ||
49 | }, | ||
50 | .probe = tlv320aic23_i2c_probe, | ||
51 | .remove = __exit_p(tlv320aic23_i2c_remove), | ||
52 | .id_table = tlv320aic23_id, | ||
53 | }; | ||
54 | |||
55 | module_i2c_driver(tlv320aic23_i2c_driver); | ||
56 | |||
57 | MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver I2C"); | ||
58 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); | ||
59 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tlv320aic23-spi.c b/sound/soc/codecs/tlv320aic23-spi.c new file mode 100644 index 000000000000..3b387e41d75d --- /dev/null +++ b/sound/soc/codecs/tlv320aic23-spi.c | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * ALSA SoC TLV320AIC23 codec driver SPI interface | ||
3 | * | ||
4 | * Author: Arun KS, <arunks@mistralsolutions.com> | ||
5 | * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., | ||
6 | * | ||
7 | * Based on sound/soc/codecs/wm8731.c by Richard Purdie | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/regmap.h> | ||
16 | #include <linux/spi/spi.h> | ||
17 | #include <sound/soc.h> | ||
18 | |||
19 | #include "tlv320aic23.h" | ||
20 | |||
21 | static int aic23_spi_probe(struct spi_device *spi) | ||
22 | { | ||
23 | int ret; | ||
24 | struct regmap *regmap; | ||
25 | |||
26 | dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n"); | ||
27 | |||
28 | spi->mode = SPI_MODE_0; | ||
29 | ret = spi_setup(spi); | ||
30 | if (ret < 0) | ||
31 | return ret; | ||
32 | |||
33 | regmap = devm_regmap_init_spi(spi, &tlv320aic23_regmap); | ||
34 | return tlv320aic23_probe(&spi->dev, regmap); | ||
35 | } | ||
36 | |||
37 | static int aic23_spi_remove(struct spi_device *spi) | ||
38 | { | ||
39 | snd_soc_unregister_codec(&spi->dev); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static struct spi_driver aic23_spi = { | ||
44 | .driver = { | ||
45 | .name = "tlv320aic23", | ||
46 | .owner = THIS_MODULE, | ||
47 | }, | ||
48 | .probe = aic23_spi_probe, | ||
49 | .remove = aic23_spi_remove, | ||
50 | }; | ||
51 | |||
52 | module_spi_driver(aic23_spi); | ||
53 | |||
54 | MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver SPI"); | ||
55 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); | ||
56 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 5d430cc56f51..20864ee8793b 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/i2c.h> | ||
27 | #include <linux/regmap.h> | 26 | #include <linux/regmap.h> |
28 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
29 | #include <sound/core.h> | 28 | #include <sound/core.h> |
@@ -51,7 +50,7 @@ static const struct reg_default tlv320aic23_reg[] = { | |||
51 | { 9, 0x0000 }, | 50 | { 9, 0x0000 }, |
52 | }; | 51 | }; |
53 | 52 | ||
54 | static const struct regmap_config tlv320aic23_regmap = { | 53 | const struct regmap_config tlv320aic23_regmap = { |
55 | .reg_bits = 7, | 54 | .reg_bits = 7, |
56 | .val_bits = 9, | 55 | .val_bits = 9, |
57 | 56 | ||
@@ -60,20 +59,21 @@ static const struct regmap_config tlv320aic23_regmap = { | |||
60 | .num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg), | 59 | .num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg), |
61 | .cache_type = REGCACHE_RBTREE, | 60 | .cache_type = REGCACHE_RBTREE, |
62 | }; | 61 | }; |
62 | EXPORT_SYMBOL(tlv320aic23_regmap); | ||
63 | 63 | ||
64 | static const char *rec_src_text[] = { "Line", "Mic" }; | 64 | static const char *rec_src_text[] = { "Line", "Mic" }; |
65 | static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; | 65 | static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; |
66 | 66 | ||
67 | static const struct soc_enum rec_src_enum = | 67 | static SOC_ENUM_SINGLE_DECL(rec_src_enum, |
68 | SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); | 68 | TLV320AIC23_ANLG, 2, rec_src_text); |
69 | 69 | ||
70 | static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls = | 70 | static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls = |
71 | SOC_DAPM_ENUM("Input Select", rec_src_enum); | 71 | SOC_DAPM_ENUM("Input Select", rec_src_enum); |
72 | 72 | ||
73 | static const struct soc_enum tlv320aic23_rec_src = | 73 | static SOC_ENUM_SINGLE_DECL(tlv320aic23_rec_src, |
74 | SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); | 74 | TLV320AIC23_ANLG, 2, rec_src_text); |
75 | static const struct soc_enum tlv320aic23_deemph = | 75 | static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph, |
76 | SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text); | 76 | TLV320AIC23_DIGT, 1, deemph_text); |
77 | 77 | ||
78 | static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0); | 78 | static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0); |
79 | static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0); | 79 | static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0); |
@@ -400,7 +400,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, | |||
400 | struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); | 400 | struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); |
401 | 401 | ||
402 | /* deactivate */ | 402 | /* deactivate */ |
403 | if (!codec->active) { | 403 | if (!snd_soc_codec_is_active(codec)) { |
404 | udelay(50); | 404 | udelay(50); |
405 | snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0); | 405 | snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0); |
406 | } | 406 | } |
@@ -557,16 +557,8 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec) | |||
557 | return 0; | 557 | return 0; |
558 | } | 558 | } |
559 | 559 | ||
560 | static int tlv320aic23_probe(struct snd_soc_codec *codec) | 560 | static int tlv320aic23_codec_probe(struct snd_soc_codec *codec) |
561 | { | 561 | { |
562 | int ret; | ||
563 | |||
564 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
565 | if (ret < 0) { | ||
566 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
567 | return ret; | ||
568 | } | ||
569 | |||
570 | /* Reset codec */ | 562 | /* Reset codec */ |
571 | snd_soc_write(codec, TLV320AIC23_RESET, 0); | 563 | snd_soc_write(codec, TLV320AIC23_RESET, 0); |
572 | 564 | ||
@@ -604,7 +596,7 @@ static int tlv320aic23_remove(struct snd_soc_codec *codec) | |||
604 | } | 596 | } |
605 | 597 | ||
606 | static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { | 598 | static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { |
607 | .probe = tlv320aic23_probe, | 599 | .probe = tlv320aic23_codec_probe, |
608 | .remove = tlv320aic23_remove, | 600 | .remove = tlv320aic23_remove, |
609 | .suspend = tlv320aic23_suspend, | 601 | .suspend = tlv320aic23_suspend, |
610 | .resume = tlv320aic23_resume, | 602 | .resume = tlv320aic23_resume, |
@@ -617,56 +609,25 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { | |||
617 | .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), | 609 | .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), |
618 | }; | 610 | }; |
619 | 611 | ||
620 | /* | 612 | int tlv320aic23_probe(struct device *dev, struct regmap *regmap) |
621 | * If the i2c layer weren't so broken, we could pass this kind of data | ||
622 | * around | ||
623 | */ | ||
624 | static int tlv320aic23_codec_probe(struct i2c_client *i2c, | ||
625 | const struct i2c_device_id *i2c_id) | ||
626 | { | 613 | { |
627 | struct aic23 *aic23; | 614 | struct aic23 *aic23; |
628 | int ret; | ||
629 | 615 | ||
630 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 616 | if (IS_ERR(regmap)) |
631 | return -EINVAL; | 617 | return PTR_ERR(regmap); |
632 | 618 | ||
633 | aic23 = devm_kzalloc(&i2c->dev, sizeof(struct aic23), GFP_KERNEL); | 619 | aic23 = devm_kzalloc(dev, sizeof(struct aic23), GFP_KERNEL); |
634 | if (aic23 == NULL) | 620 | if (aic23 == NULL) |
635 | return -ENOMEM; | 621 | return -ENOMEM; |
636 | 622 | ||
637 | aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); | 623 | aic23->regmap = regmap; |
638 | if (IS_ERR(aic23->regmap)) | ||
639 | return PTR_ERR(aic23->regmap); | ||
640 | 624 | ||
641 | i2c_set_clientdata(i2c, aic23); | 625 | dev_set_drvdata(dev, aic23); |
642 | 626 | ||
643 | ret = snd_soc_register_codec(&i2c->dev, | 627 | return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23, |
644 | &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); | 628 | &tlv320aic23_dai, 1); |
645 | return ret; | ||
646 | } | 629 | } |
647 | static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) | 630 | EXPORT_SYMBOL(tlv320aic23_probe); |
648 | { | ||
649 | snd_soc_unregister_codec(&i2c->dev); | ||
650 | return 0; | ||
651 | } | ||
652 | |||
653 | static const struct i2c_device_id tlv320aic23_id[] = { | ||
654 | {"tlv320aic23", 0}, | ||
655 | {} | ||
656 | }; | ||
657 | |||
658 | MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); | ||
659 | |||
660 | static struct i2c_driver tlv320aic23_i2c_driver = { | ||
661 | .driver = { | ||
662 | .name = "tlv320aic23-codec", | ||
663 | }, | ||
664 | .probe = tlv320aic23_codec_probe, | ||
665 | .remove = __exit_p(tlv320aic23_i2c_remove), | ||
666 | .id_table = tlv320aic23_id, | ||
667 | }; | ||
668 | |||
669 | module_i2c_driver(tlv320aic23_i2c_driver); | ||
670 | 631 | ||
671 | MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); | 632 | MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); |
672 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); | 633 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); |
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h index e804120bd3da..3a7235a04a89 100644 --- a/sound/soc/codecs/tlv320aic23.h +++ b/sound/soc/codecs/tlv320aic23.h | |||
@@ -12,6 +12,12 @@ | |||
12 | #ifndef _TLV320AIC23_H | 12 | #ifndef _TLV320AIC23_H |
13 | #define _TLV320AIC23_H | 13 | #define _TLV320AIC23_H |
14 | 14 | ||
15 | struct device; | ||
16 | struct regmap_config; | ||
17 | |||
18 | extern const struct regmap_config tlv320aic23_regmap; | ||
19 | int tlv320aic23_probe(struct device *dev, struct regmap *regmap); | ||
20 | |||
15 | /* Codec TLV320AIC23 */ | 21 | /* Codec TLV320AIC23 */ |
16 | #define TLV320AIC23_LINVOL 0x00 | 22 | #define TLV320AIC23_LINVOL 0x00 |
17 | #define TLV320AIC23_RINVOL 0x01 | 23 | #define TLV320AIC23_RINVOL 0x01 |
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 94a658fa6d97..43069de3d56a 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
@@ -238,8 +238,9 @@ static struct snd_soc_dai_driver aic26_dai = { | |||
238 | * ALSA controls | 238 | * ALSA controls |
239 | */ | 239 | */ |
240 | static const char *aic26_capture_src_text[] = {"Mic", "Aux"}; | 240 | static const char *aic26_capture_src_text[] = {"Mic", "Aux"}; |
241 | static const struct soc_enum aic26_capture_src_enum = | 241 | static SOC_ENUM_SINGLE_DECL(aic26_capture_src_enum, |
242 | SOC_ENUM_SINGLE(AIC26_REG_AUDIO_CTRL1, 12, 2, aic26_capture_src_text); | 242 | AIC26_REG_AUDIO_CTRL1, 12, |
243 | aic26_capture_src_text); | ||
243 | 244 | ||
244 | static const struct snd_kcontrol_new aic26_snd_controls[] = { | 245 | static const struct snd_kcontrol_new aic26_snd_controls[] = { |
245 | /* Output */ | 246 | /* Output */ |
@@ -295,8 +296,6 @@ static int aic26_probe(struct snd_soc_codec *codec) | |||
295 | struct aic26 *aic26 = dev_get_drvdata(codec->dev); | 296 | struct aic26 *aic26 = dev_get_drvdata(codec->dev); |
296 | int ret, reg; | 297 | int ret, reg; |
297 | 298 | ||
298 | snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | ||
299 | |||
300 | aic26->codec = codec; | 299 | aic26->codec = codec; |
301 | 300 | ||
302 | /* Reset the codec to power on defaults */ | 301 | /* Reset the codec to power on defaults */ |
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c new file mode 100644 index 000000000000..fa158cfe9b32 --- /dev/null +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -0,0 +1,1280 @@ | |||
1 | /* | ||
2 | * ALSA SoC TLV320AIC31XX codec driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Texas Instruments, Inc. | ||
5 | * | ||
6 | * Author: Jyri Sarha <jsarha@ti.com> | ||
7 | * | ||
8 | * Based on ground work by: Ajit Kulkarni <x0175765@ti.com> | ||
9 | * | ||
10 | * This package is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * THIS PACKAGE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR | ||
15 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | ||
16 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
17 | * | ||
18 | * The TLV320AIC31xx series of audio codec is a low-power, highly integrated | ||
19 | * high performance codec which provides a stereo DAC, a mono ADC, | ||
20 | * and mono/stereo Class-D speaker driver. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/pm.h> | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/gpio.h> | ||
30 | #include <linux/regulator/consumer.h> | ||
31 | #include <linux/of_gpio.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <sound/core.h> | ||
34 | #include <sound/pcm.h> | ||
35 | #include <sound/pcm_params.h> | ||
36 | #include <sound/soc.h> | ||
37 | #include <sound/initval.h> | ||
38 | #include <sound/tlv.h> | ||
39 | #include <dt-bindings/sound/tlv320aic31xx-micbias.h> | ||
40 | |||
41 | #include "tlv320aic31xx.h" | ||
42 | |||
43 | static const struct reg_default aic31xx_reg_defaults[] = { | ||
44 | { AIC31XX_CLKMUX, 0x00 }, | ||
45 | { AIC31XX_PLLPR, 0x11 }, | ||
46 | { AIC31XX_PLLJ, 0x04 }, | ||
47 | { AIC31XX_PLLDMSB, 0x00 }, | ||
48 | { AIC31XX_PLLDLSB, 0x00 }, | ||
49 | { AIC31XX_NDAC, 0x01 }, | ||
50 | { AIC31XX_MDAC, 0x01 }, | ||
51 | { AIC31XX_DOSRMSB, 0x00 }, | ||
52 | { AIC31XX_DOSRLSB, 0x80 }, | ||
53 | { AIC31XX_NADC, 0x01 }, | ||
54 | { AIC31XX_MADC, 0x01 }, | ||
55 | { AIC31XX_AOSR, 0x80 }, | ||
56 | { AIC31XX_IFACE1, 0x00 }, | ||
57 | { AIC31XX_DATA_OFFSET, 0x00 }, | ||
58 | { AIC31XX_IFACE2, 0x00 }, | ||
59 | { AIC31XX_BCLKN, 0x01 }, | ||
60 | { AIC31XX_DACSETUP, 0x14 }, | ||
61 | { AIC31XX_DACMUTE, 0x0c }, | ||
62 | { AIC31XX_LDACVOL, 0x00 }, | ||
63 | { AIC31XX_RDACVOL, 0x00 }, | ||
64 | { AIC31XX_ADCSETUP, 0x00 }, | ||
65 | { AIC31XX_ADCFGA, 0x80 }, | ||
66 | { AIC31XX_ADCVOL, 0x00 }, | ||
67 | { AIC31XX_HPDRIVER, 0x04 }, | ||
68 | { AIC31XX_SPKAMP, 0x06 }, | ||
69 | { AIC31XX_DACMIXERROUTE, 0x00 }, | ||
70 | { AIC31XX_LANALOGHPL, 0x7f }, | ||
71 | { AIC31XX_RANALOGHPR, 0x7f }, | ||
72 | { AIC31XX_LANALOGSPL, 0x7f }, | ||
73 | { AIC31XX_RANALOGSPR, 0x7f }, | ||
74 | { AIC31XX_HPLGAIN, 0x02 }, | ||
75 | { AIC31XX_HPRGAIN, 0x02 }, | ||
76 | { AIC31XX_SPLGAIN, 0x00 }, | ||
77 | { AIC31XX_SPRGAIN, 0x00 }, | ||
78 | { AIC31XX_MICBIAS, 0x00 }, | ||
79 | { AIC31XX_MICPGA, 0x80 }, | ||
80 | { AIC31XX_MICPGAPI, 0x00 }, | ||
81 | { AIC31XX_MICPGAMI, 0x00 }, | ||
82 | }; | ||
83 | |||
84 | static bool aic31xx_volatile(struct device *dev, unsigned int reg) | ||
85 | { | ||
86 | switch (reg) { | ||
87 | case AIC31XX_PAGECTL: /* regmap implementation requires this */ | ||
88 | case AIC31XX_RESET: /* always clears after write */ | ||
89 | case AIC31XX_OT_FLAG: | ||
90 | case AIC31XX_ADCFLAG: | ||
91 | case AIC31XX_DACFLAG1: | ||
92 | case AIC31XX_DACFLAG2: | ||
93 | case AIC31XX_OFFLAG: /* Sticky interrupt flags */ | ||
94 | case AIC31XX_INTRDACFLAG: /* Sticky interrupt flags */ | ||
95 | case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */ | ||
96 | case AIC31XX_INTRDACFLAG2: | ||
97 | case AIC31XX_INTRADCFLAG2: | ||
98 | return true; | ||
99 | } | ||
100 | return false; | ||
101 | } | ||
102 | |||
103 | static bool aic31xx_writeable(struct device *dev, unsigned int reg) | ||
104 | { | ||
105 | switch (reg) { | ||
106 | case AIC31XX_OT_FLAG: | ||
107 | case AIC31XX_ADCFLAG: | ||
108 | case AIC31XX_DACFLAG1: | ||
109 | case AIC31XX_DACFLAG2: | ||
110 | case AIC31XX_OFFLAG: /* Sticky interrupt flags */ | ||
111 | case AIC31XX_INTRDACFLAG: /* Sticky interrupt flags */ | ||
112 | case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */ | ||
113 | case AIC31XX_INTRDACFLAG2: | ||
114 | case AIC31XX_INTRADCFLAG2: | ||
115 | return false; | ||
116 | } | ||
117 | return true; | ||
118 | } | ||
119 | |||
120 | static const struct regmap_range_cfg aic31xx_ranges[] = { | ||
121 | { | ||
122 | .range_min = 0, | ||
123 | .range_max = 12 * 128, | ||
124 | .selector_reg = AIC31XX_PAGECTL, | ||
125 | .selector_mask = 0xff, | ||
126 | .selector_shift = 0, | ||
127 | .window_start = 0, | ||
128 | .window_len = 128, | ||
129 | }, | ||
130 | }; | ||
131 | |||
132 | static const struct regmap_config aic31xx_i2c_regmap = { | ||
133 | .reg_bits = 8, | ||
134 | .val_bits = 8, | ||
135 | .writeable_reg = aic31xx_writeable, | ||
136 | .volatile_reg = aic31xx_volatile, | ||
137 | .reg_defaults = aic31xx_reg_defaults, | ||
138 | .num_reg_defaults = ARRAY_SIZE(aic31xx_reg_defaults), | ||
139 | .cache_type = REGCACHE_RBTREE, | ||
140 | .ranges = aic31xx_ranges, | ||
141 | .num_ranges = ARRAY_SIZE(aic31xx_ranges), | ||
142 | .max_register = 12 * 128, | ||
143 | }; | ||
144 | |||
145 | #define AIC31XX_NUM_SUPPLIES 6 | ||
146 | static const char * const aic31xx_supply_names[AIC31XX_NUM_SUPPLIES] = { | ||
147 | "HPVDD", | ||
148 | "SPRVDD", | ||
149 | "SPLVDD", | ||
150 | "AVDD", | ||
151 | "IOVDD", | ||
152 | "DVDD", | ||
153 | }; | ||
154 | |||
155 | struct aic31xx_disable_nb { | ||
156 | struct notifier_block nb; | ||
157 | struct aic31xx_priv *aic31xx; | ||
158 | }; | ||
159 | |||
160 | struct aic31xx_priv { | ||
161 | struct snd_soc_codec *codec; | ||
162 | u8 i2c_regs_status; | ||
163 | struct device *dev; | ||
164 | struct regmap *regmap; | ||
165 | struct aic31xx_pdata pdata; | ||
166 | struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES]; | ||
167 | struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES]; | ||
168 | unsigned int sysclk; | ||
169 | int rate_div_line; | ||
170 | }; | ||
171 | |||
172 | struct aic31xx_rate_divs { | ||
173 | u32 mclk; | ||
174 | u32 rate; | ||
175 | u8 p_val; | ||
176 | u8 pll_j; | ||
177 | u16 pll_d; | ||
178 | u16 dosr; | ||
179 | u8 ndac; | ||
180 | u8 mdac; | ||
181 | u8 aosr; | ||
182 | u8 nadc; | ||
183 | u8 madc; | ||
184 | }; | ||
185 | |||
186 | /* ADC dividers can be disabled by cofiguring them to 0 */ | ||
187 | static const struct aic31xx_rate_divs aic31xx_divs[] = { | ||
188 | /* mclk rate pll: p j d dosr ndac mdac aors nadc madc */ | ||
189 | /* 8k rate */ | ||
190 | {12000000, 8000, 1, 8, 1920, 128, 48, 2, 128, 48, 2}, | ||
191 | {24000000, 8000, 2, 8, 1920, 128, 48, 2, 128, 48, 2}, | ||
192 | {25000000, 8000, 2, 7, 8643, 128, 48, 2, 128, 48, 2}, | ||
193 | /* 11.025k rate */ | ||
194 | {12000000, 11025, 1, 7, 5264, 128, 32, 2, 128, 32, 2}, | ||
195 | {24000000, 11025, 2, 7, 5264, 128, 32, 2, 128, 32, 2}, | ||
196 | {25000000, 11025, 2, 7, 2253, 128, 32, 2, 128, 32, 2}, | ||
197 | /* 16k rate */ | ||
198 | {12000000, 16000, 1, 8, 1920, 128, 24, 2, 128, 24, 2}, | ||
199 | {24000000, 16000, 2, 8, 1920, 128, 24, 2, 128, 24, 2}, | ||
200 | {25000000, 16000, 2, 7, 8643, 128, 24, 2, 128, 24, 2}, | ||
201 | /* 22.05k rate */ | ||
202 | {12000000, 22050, 1, 7, 5264, 128, 16, 2, 128, 16, 2}, | ||
203 | {24000000, 22050, 2, 7, 5264, 128, 16, 2, 128, 16, 2}, | ||
204 | {25000000, 22050, 2, 7, 2253, 128, 16, 2, 128, 16, 2}, | ||
205 | /* 32k rate */ | ||
206 | {12000000, 32000, 1, 8, 1920, 128, 12, 2, 128, 12, 2}, | ||
207 | {24000000, 32000, 2, 8, 1920, 128, 12, 2, 128, 12, 2}, | ||
208 | {25000000, 32000, 2, 7, 8643, 128, 12, 2, 128, 12, 2}, | ||
209 | /* 44.1k rate */ | ||
210 | {12000000, 44100, 1, 7, 5264, 128, 8, 2, 128, 8, 2}, | ||
211 | {24000000, 44100, 2, 7, 5264, 128, 8, 2, 128, 8, 2}, | ||
212 | {25000000, 44100, 2, 7, 2253, 128, 8, 2, 128, 8, 2}, | ||
213 | /* 48k rate */ | ||
214 | {12000000, 48000, 1, 8, 1920, 128, 8, 2, 128, 8, 2}, | ||
215 | {24000000, 48000, 2, 8, 1920, 128, 8, 2, 128, 8, 2}, | ||
216 | {25000000, 48000, 2, 7, 8643, 128, 8, 2, 128, 8, 2}, | ||
217 | /* 88.2k rate */ | ||
218 | {12000000, 88200, 1, 7, 5264, 64, 8, 2, 64, 8, 2}, | ||
219 | {24000000, 88200, 2, 7, 5264, 64, 8, 2, 64, 8, 2}, | ||
220 | {25000000, 88200, 2, 7, 2253, 64, 8, 2, 64, 8, 2}, | ||
221 | /* 96k rate */ | ||
222 | {12000000, 96000, 1, 8, 1920, 64, 8, 2, 64, 8, 2}, | ||
223 | {24000000, 96000, 2, 8, 1920, 64, 8, 2, 64, 8, 2}, | ||
224 | {25000000, 96000, 2, 7, 8643, 64, 8, 2, 64, 8, 2}, | ||
225 | /* 176.4k rate */ | ||
226 | {12000000, 176400, 1, 7, 5264, 32, 8, 2, 32, 8, 2}, | ||
227 | {24000000, 176400, 2, 7, 5264, 32, 8, 2, 32, 8, 2}, | ||
228 | {25000000, 176400, 2, 7, 2253, 32, 8, 2, 32, 8, 2}, | ||
229 | /* 192k rate */ | ||
230 | {12000000, 192000, 1, 8, 1920, 32, 8, 2, 32, 8, 2}, | ||
231 | {24000000, 192000, 2, 8, 1920, 32, 8, 2, 32, 8, 2}, | ||
232 | {25000000, 192000, 2, 7, 8643, 32, 8, 2, 32, 8, 2}, | ||
233 | }; | ||
234 | |||
235 | static const char * const ldac_in_text[] = { | ||
236 | "Off", "Left Data", "Right Data", "Mono" | ||
237 | }; | ||
238 | |||
239 | static const char * const rdac_in_text[] = { | ||
240 | "Off", "Right Data", "Left Data", "Mono" | ||
241 | }; | ||
242 | |||
243 | static SOC_ENUM_SINGLE_DECL(ldac_in_enum, AIC31XX_DACSETUP, 4, ldac_in_text); | ||
244 | |||
245 | static SOC_ENUM_SINGLE_DECL(rdac_in_enum, AIC31XX_DACSETUP, 2, rdac_in_text); | ||
246 | |||
247 | static const char * const mic_select_text[] = { | ||
248 | "Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm" | ||
249 | }; | ||
250 | |||
251 | static const | ||
252 | SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, mic_select_text); | ||
253 | static const | ||
254 | SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, mic_select_text); | ||
255 | static const | ||
256 | SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, mic_select_text); | ||
257 | |||
258 | static const | ||
259 | SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text); | ||
260 | static const | ||
261 | SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, mic_select_text); | ||
262 | |||
263 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0); | ||
264 | static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0); | ||
265 | static const DECLARE_TLV_DB_SCALE(adc_cgain_tlv, -2000, 50, 0); | ||
266 | static const DECLARE_TLV_DB_SCALE(mic_pga_tlv, 0, 50, 0); | ||
267 | static const DECLARE_TLV_DB_SCALE(hp_drv_tlv, 0, 100, 0); | ||
268 | static const DECLARE_TLV_DB_SCALE(class_D_drv_tlv, 600, 600, 0); | ||
269 | static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -6350, 50, 0); | ||
270 | static const DECLARE_TLV_DB_SCALE(sp_vol_tlv, -6350, 50, 0); | ||
271 | |||
272 | /* | ||
273 | * controls to be exported to the user space | ||
274 | */ | ||
275 | static const struct snd_kcontrol_new aic31xx_snd_controls[] = { | ||
276 | SOC_DOUBLE_R_S_TLV("DAC Playback Volume", AIC31XX_LDACVOL, | ||
277 | AIC31XX_RDACVOL, 0, -127, 48, 7, 0, dac_vol_tlv), | ||
278 | |||
279 | SOC_SINGLE_TLV("ADC Fine Capture Volume", AIC31XX_ADCFGA, 4, 4, 1, | ||
280 | adc_fgain_tlv), | ||
281 | |||
282 | SOC_SINGLE("ADC Capture Switch", AIC31XX_ADCFGA, 7, 1, 1), | ||
283 | SOC_DOUBLE_R_S_TLV("ADC Capture Volume", AIC31XX_ADCVOL, AIC31XX_ADCVOL, | ||
284 | 0, -24, 40, 6, 0, adc_cgain_tlv), | ||
285 | |||
286 | SOC_SINGLE_TLV("Mic PGA Capture Volume", AIC31XX_MICPGA, 0, | ||
287 | 119, 0, mic_pga_tlv), | ||
288 | |||
289 | SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN, | ||
290 | AIC31XX_HPRGAIN, 2, 1, 0), | ||
291 | SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN, | ||
292 | AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv), | ||
293 | |||
294 | SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL, | ||
295 | AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv), | ||
296 | }; | ||
297 | |||
298 | static const struct snd_kcontrol_new aic311x_snd_controls[] = { | ||
299 | SOC_DOUBLE_R("Speaker Driver Playback Switch", AIC31XX_SPLGAIN, | ||
300 | AIC31XX_SPRGAIN, 2, 1, 0), | ||
301 | SOC_DOUBLE_R_TLV("Speaker Driver Playback Volume", AIC31XX_SPLGAIN, | ||
302 | AIC31XX_SPRGAIN, 3, 3, 0, class_D_drv_tlv), | ||
303 | |||
304 | SOC_DOUBLE_R_TLV("Speaker Analog Playback Volume", AIC31XX_LANALOGSPL, | ||
305 | AIC31XX_RANALOGSPR, 0, 0x7F, 1, sp_vol_tlv), | ||
306 | }; | ||
307 | |||
308 | static const struct snd_kcontrol_new aic310x_snd_controls[] = { | ||
309 | SOC_SINGLE("Speaker Driver Playback Switch", AIC31XX_SPLGAIN, | ||
310 | 2, 1, 0), | ||
311 | SOC_SINGLE_TLV("Speaker Driver Playback Volume", AIC31XX_SPLGAIN, | ||
312 | 3, 3, 0, class_D_drv_tlv), | ||
313 | |||
314 | SOC_SINGLE_TLV("Speaker Analog Playback Volume", AIC31XX_LANALOGSPL, | ||
315 | 0, 0x7F, 1, sp_vol_tlv), | ||
316 | }; | ||
317 | |||
318 | static const struct snd_kcontrol_new ldac_in_control = | ||
319 | SOC_DAPM_ENUM("DAC Left Input", ldac_in_enum); | ||
320 | |||
321 | static const struct snd_kcontrol_new rdac_in_control = | ||
322 | SOC_DAPM_ENUM("DAC Right Input", rdac_in_enum); | ||
323 | |||
324 | static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg, | ||
325 | unsigned int mask, unsigned int wbits, int sleep, | ||
326 | int count) | ||
327 | { | ||
328 | unsigned int bits; | ||
329 | int counter = count; | ||
330 | int ret = regmap_read(aic31xx->regmap, reg, &bits); | ||
331 | while ((bits & mask) != wbits && counter && !ret) { | ||
332 | usleep_range(sleep, sleep * 2); | ||
333 | ret = regmap_read(aic31xx->regmap, reg, &bits); | ||
334 | counter--; | ||
335 | } | ||
336 | if ((bits & mask) != wbits) { | ||
337 | dev_err(aic31xx->dev, | ||
338 | "%s: Failed! 0x%x was 0x%x expected 0x%x (%d, 0x%x, %d us)\n", | ||
339 | __func__, reg, bits, wbits, ret, mask, | ||
340 | (count - counter) * sleep); | ||
341 | ret = -1; | ||
342 | } | ||
343 | return ret; | ||
344 | } | ||
345 | |||
346 | #define WIDGET_BIT(reg, shift) (((shift) << 8) | (reg)) | ||
347 | |||
348 | static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w, | ||
349 | struct snd_kcontrol *kcontrol, int event) | ||
350 | { | ||
351 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(w->codec); | ||
352 | unsigned int reg = AIC31XX_DACFLAG1; | ||
353 | unsigned int mask; | ||
354 | |||
355 | switch (WIDGET_BIT(w->reg, w->shift)) { | ||
356 | case WIDGET_BIT(AIC31XX_DACSETUP, 7): | ||
357 | mask = AIC31XX_LDACPWRSTATUS_MASK; | ||
358 | break; | ||
359 | case WIDGET_BIT(AIC31XX_DACSETUP, 6): | ||
360 | mask = AIC31XX_RDACPWRSTATUS_MASK; | ||
361 | break; | ||
362 | case WIDGET_BIT(AIC31XX_HPDRIVER, 7): | ||
363 | mask = AIC31XX_HPLDRVPWRSTATUS_MASK; | ||
364 | break; | ||
365 | case WIDGET_BIT(AIC31XX_HPDRIVER, 6): | ||
366 | mask = AIC31XX_HPRDRVPWRSTATUS_MASK; | ||
367 | break; | ||
368 | case WIDGET_BIT(AIC31XX_SPKAMP, 7): | ||
369 | mask = AIC31XX_SPLDRVPWRSTATUS_MASK; | ||
370 | break; | ||
371 | case WIDGET_BIT(AIC31XX_SPKAMP, 6): | ||
372 | mask = AIC31XX_SPRDRVPWRSTATUS_MASK; | ||
373 | break; | ||
374 | case WIDGET_BIT(AIC31XX_ADCSETUP, 7): | ||
375 | mask = AIC31XX_ADCPWRSTATUS_MASK; | ||
376 | reg = AIC31XX_ADCFLAG; | ||
377 | break; | ||
378 | default: | ||
379 | dev_err(w->codec->dev, "Unknown widget '%s' calling %s/n", | ||
380 | w->name, __func__); | ||
381 | return -EINVAL; | ||
382 | } | ||
383 | |||
384 | switch (event) { | ||
385 | case SND_SOC_DAPM_POST_PMU: | ||
386 | return aic31xx_wait_bits(aic31xx, reg, mask, mask, 5000, 100); | ||
387 | case SND_SOC_DAPM_POST_PMD: | ||
388 | return aic31xx_wait_bits(aic31xx, reg, mask, 0, 5000, 100); | ||
389 | default: | ||
390 | dev_dbg(w->codec->dev, | ||
391 | "Unhandled dapm widget event %d from %s\n", | ||
392 | event, w->name); | ||
393 | } | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | static const struct snd_kcontrol_new left_output_switches[] = { | ||
398 | SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0), | ||
399 | SOC_DAPM_SINGLE("From MIC1LP", AIC31XX_DACMIXERROUTE, 5, 1, 0), | ||
400 | SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 4, 1, 0), | ||
401 | }; | ||
402 | |||
403 | static const struct snd_kcontrol_new right_output_switches[] = { | ||
404 | SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0), | ||
405 | SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 1, 1, 0), | ||
406 | }; | ||
407 | |||
408 | static const struct snd_kcontrol_new p_term_mic1lp = | ||
409 | SOC_DAPM_ENUM("MIC1LP P-Terminal", mic1lp_p_enum); | ||
410 | |||
411 | static const struct snd_kcontrol_new p_term_mic1rp = | ||
412 | SOC_DAPM_ENUM("MIC1RP P-Terminal", mic1rp_p_enum); | ||
413 | |||
414 | static const struct snd_kcontrol_new p_term_mic1lm = | ||
415 | SOC_DAPM_ENUM("MIC1LM P-Terminal", mic1lm_p_enum); | ||
416 | |||
417 | static const struct snd_kcontrol_new m_term_mic1lm = | ||
418 | SOC_DAPM_ENUM("MIC1LM M-Terminal", mic1lm_m_enum); | ||
419 | |||
420 | static const struct snd_kcontrol_new aic31xx_dapm_hpl_switch = | ||
421 | SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGHPL, 7, 1, 0); | ||
422 | |||
423 | static const struct snd_kcontrol_new aic31xx_dapm_hpr_switch = | ||
424 | SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGHPR, 7, 1, 0); | ||
425 | |||
426 | static const struct snd_kcontrol_new aic31xx_dapm_spl_switch = | ||
427 | SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGSPL, 7, 1, 0); | ||
428 | |||
429 | static const struct snd_kcontrol_new aic31xx_dapm_spr_switch = | ||
430 | SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGSPR, 7, 1, 0); | ||
431 | |||
432 | static int mic_bias_event(struct snd_soc_dapm_widget *w, | ||
433 | struct snd_kcontrol *kcontrol, int event) | ||
434 | { | ||
435 | struct snd_soc_codec *codec = w->codec; | ||
436 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | ||
437 | switch (event) { | ||
438 | case SND_SOC_DAPM_POST_PMU: | ||
439 | /* change mic bias voltage to user defined */ | ||
440 | snd_soc_update_bits(codec, AIC31XX_MICBIAS, | ||
441 | AIC31XX_MICBIAS_MASK, | ||
442 | aic31xx->pdata.micbias_vg << | ||
443 | AIC31XX_MICBIAS_SHIFT); | ||
444 | dev_dbg(codec->dev, "%s: turned on\n", __func__); | ||
445 | break; | ||
446 | case SND_SOC_DAPM_PRE_PMD: | ||
447 | /* turn mic bias off */ | ||
448 | snd_soc_update_bits(codec, AIC31XX_MICBIAS, | ||
449 | AIC31XX_MICBIAS_MASK, 0); | ||
450 | dev_dbg(codec->dev, "%s: turned off\n", __func__); | ||
451 | break; | ||
452 | } | ||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { | ||
457 | SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), | ||
458 | |||
459 | SND_SOC_DAPM_MUX("DAC Left Input", | ||
460 | SND_SOC_NOPM, 0, 0, &ldac_in_control), | ||
461 | SND_SOC_DAPM_MUX("DAC Right Input", | ||
462 | SND_SOC_NOPM, 0, 0, &rdac_in_control), | ||
463 | /* DACs */ | ||
464 | SND_SOC_DAPM_DAC_E("DAC Left", "Left Playback", | ||
465 | AIC31XX_DACSETUP, 7, 0, aic31xx_dapm_power_event, | ||
466 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
467 | |||
468 | SND_SOC_DAPM_DAC_E("DAC Right", "Right Playback", | ||
469 | AIC31XX_DACSETUP, 6, 0, aic31xx_dapm_power_event, | ||
470 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
471 | |||
472 | /* Output Mixers */ | ||
473 | SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, | ||
474 | left_output_switches, | ||
475 | ARRAY_SIZE(left_output_switches)), | ||
476 | SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, | ||
477 | right_output_switches, | ||
478 | ARRAY_SIZE(right_output_switches)), | ||
479 | |||
480 | SND_SOC_DAPM_SWITCH("HP Left", SND_SOC_NOPM, 0, 0, | ||
481 | &aic31xx_dapm_hpl_switch), | ||
482 | SND_SOC_DAPM_SWITCH("HP Right", SND_SOC_NOPM, 0, 0, | ||
483 | &aic31xx_dapm_hpr_switch), | ||
484 | |||
485 | /* Output drivers */ | ||
486 | SND_SOC_DAPM_OUT_DRV_E("HPL Driver", AIC31XX_HPDRIVER, 7, 0, | ||
487 | NULL, 0, aic31xx_dapm_power_event, | ||
488 | SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), | ||
489 | SND_SOC_DAPM_OUT_DRV_E("HPR Driver", AIC31XX_HPDRIVER, 6, 0, | ||
490 | NULL, 0, aic31xx_dapm_power_event, | ||
491 | SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), | ||
492 | |||
493 | /* ADC */ | ||
494 | SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0, | ||
495 | aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | | ||
496 | SND_SOC_DAPM_POST_PMD), | ||
497 | |||
498 | /* Input Selection to MIC_PGA */ | ||
499 | SND_SOC_DAPM_MUX("MIC1LP P-Terminal", SND_SOC_NOPM, 0, 0, | ||
500 | &p_term_mic1lp), | ||
501 | SND_SOC_DAPM_MUX("MIC1RP P-Terminal", SND_SOC_NOPM, 0, 0, | ||
502 | &p_term_mic1rp), | ||
503 | SND_SOC_DAPM_MUX("MIC1LM P-Terminal", SND_SOC_NOPM, 0, 0, | ||
504 | &p_term_mic1lm), | ||
505 | |||
506 | SND_SOC_DAPM_MUX("MIC1LM M-Terminal", SND_SOC_NOPM, 0, 0, | ||
507 | &m_term_mic1lm), | ||
508 | /* Enabling & Disabling MIC Gain Ctl */ | ||
509 | SND_SOC_DAPM_PGA("MIC_GAIN_CTL", AIC31XX_MICPGA, | ||
510 | 7, 1, NULL, 0), | ||
511 | |||
512 | /* Mic Bias */ | ||
513 | SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, mic_bias_event, | ||
514 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
515 | |||
516 | /* Outputs */ | ||
517 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
518 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
519 | |||
520 | /* Inputs */ | ||
521 | SND_SOC_DAPM_INPUT("MIC1LP"), | ||
522 | SND_SOC_DAPM_INPUT("MIC1RP"), | ||
523 | SND_SOC_DAPM_INPUT("MIC1LM"), | ||
524 | }; | ||
525 | |||
526 | static const struct snd_soc_dapm_widget aic311x_dapm_widgets[] = { | ||
527 | /* AIC3111 and AIC3110 have stereo class-D amplifier */ | ||
528 | SND_SOC_DAPM_OUT_DRV_E("SPL ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0, | ||
529 | aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | | ||
530 | SND_SOC_DAPM_POST_PMD), | ||
531 | SND_SOC_DAPM_OUT_DRV_E("SPR ClassD", AIC31XX_SPKAMP, 6, 0, NULL, 0, | ||
532 | aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | | ||
533 | SND_SOC_DAPM_POST_PMD), | ||
534 | SND_SOC_DAPM_SWITCH("Speaker Left", SND_SOC_NOPM, 0, 0, | ||
535 | &aic31xx_dapm_spl_switch), | ||
536 | SND_SOC_DAPM_SWITCH("Speaker Right", SND_SOC_NOPM, 0, 0, | ||
537 | &aic31xx_dapm_spr_switch), | ||
538 | SND_SOC_DAPM_OUTPUT("SPL"), | ||
539 | SND_SOC_DAPM_OUTPUT("SPR"), | ||
540 | }; | ||
541 | |||
542 | /* AIC3100 and AIC3120 have only mono class-D amplifier */ | ||
543 | static const struct snd_soc_dapm_widget aic310x_dapm_widgets[] = { | ||
544 | SND_SOC_DAPM_OUT_DRV_E("SPK ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0, | ||
545 | aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | | ||
546 | SND_SOC_DAPM_POST_PMD), | ||
547 | SND_SOC_DAPM_SWITCH("Speaker", SND_SOC_NOPM, 0, 0, | ||
548 | &aic31xx_dapm_spl_switch), | ||
549 | SND_SOC_DAPM_OUTPUT("SPK"), | ||
550 | }; | ||
551 | |||
552 | static const struct snd_soc_dapm_route | ||
553 | aic31xx_audio_map[] = { | ||
554 | /* DAC Input Routing */ | ||
555 | {"DAC Left Input", "Left Data", "DAC IN"}, | ||
556 | {"DAC Left Input", "Right Data", "DAC IN"}, | ||
557 | {"DAC Left Input", "Mono", "DAC IN"}, | ||
558 | {"DAC Right Input", "Left Data", "DAC IN"}, | ||
559 | {"DAC Right Input", "Right Data", "DAC IN"}, | ||
560 | {"DAC Right Input", "Mono", "DAC IN"}, | ||
561 | {"DAC Left", NULL, "DAC Left Input"}, | ||
562 | {"DAC Right", NULL, "DAC Right Input"}, | ||
563 | |||
564 | /* Mic input */ | ||
565 | {"MIC1LP P-Terminal", "FFR 10 Ohm", "MIC1LP"}, | ||
566 | {"MIC1LP P-Terminal", "FFR 20 Ohm", "MIC1LP"}, | ||
567 | {"MIC1LP P-Terminal", "FFR 40 Ohm", "MIC1LP"}, | ||
568 | {"MIC1RP P-Terminal", "FFR 10 Ohm", "MIC1RP"}, | ||
569 | {"MIC1RP P-Terminal", "FFR 20 Ohm", "MIC1RP"}, | ||
570 | {"MIC1RP P-Terminal", "FFR 40 Ohm", "MIC1RP"}, | ||
571 | {"MIC1LM P-Terminal", "FFR 10 Ohm", "MIC1LM"}, | ||
572 | {"MIC1LM P-Terminal", "FFR 20 Ohm", "MIC1LM"}, | ||
573 | {"MIC1LM P-Terminal", "FFR 40 Ohm", "MIC1LM"}, | ||
574 | |||
575 | {"MIC1LM M-Terminal", "FFR 10 Ohm", "MIC1LM"}, | ||
576 | {"MIC1LM M-Terminal", "FFR 20 Ohm", "MIC1LM"}, | ||
577 | {"MIC1LM M-Terminal", "FFR 40 Ohm", "MIC1LM"}, | ||
578 | |||
579 | {"MIC_GAIN_CTL", NULL, "MIC1LP P-Terminal"}, | ||
580 | {"MIC_GAIN_CTL", NULL, "MIC1RP P-Terminal"}, | ||
581 | {"MIC_GAIN_CTL", NULL, "MIC1LM P-Terminal"}, | ||
582 | {"MIC_GAIN_CTL", NULL, "MIC1LM M-Terminal"}, | ||
583 | |||
584 | {"ADC", NULL, "MIC_GAIN_CTL"}, | ||
585 | |||
586 | /* Left Output */ | ||
587 | {"Output Left", "From Left DAC", "DAC Left"}, | ||
588 | {"Output Left", "From MIC1LP", "MIC1LP"}, | ||
589 | {"Output Left", "From MIC1RP", "MIC1RP"}, | ||
590 | |||
591 | /* Right Output */ | ||
592 | {"Output Right", "From Right DAC", "DAC Right"}, | ||
593 | {"Output Right", "From MIC1RP", "MIC1RP"}, | ||
594 | |||
595 | /* HPL path */ | ||
596 | {"HP Left", "Switch", "Output Left"}, | ||
597 | {"HPL Driver", NULL, "HP Left"}, | ||
598 | {"HPL", NULL, "HPL Driver"}, | ||
599 | |||
600 | /* HPR path */ | ||
601 | {"HP Right", "Switch", "Output Right"}, | ||
602 | {"HPR Driver", NULL, "HP Right"}, | ||
603 | {"HPR", NULL, "HPR Driver"}, | ||
604 | }; | ||
605 | |||
606 | static const struct snd_soc_dapm_route | ||
607 | aic311x_audio_map[] = { | ||
608 | /* SP L path */ | ||
609 | {"Speaker Left", "Switch", "Output Left"}, | ||
610 | {"SPL ClassD", NULL, "Speaker Left"}, | ||
611 | {"SPL", NULL, "SPL ClassD"}, | ||
612 | |||
613 | /* SP R path */ | ||
614 | {"Speaker Right", "Switch", "Output Right"}, | ||
615 | {"SPR ClassD", NULL, "Speaker Right"}, | ||
616 | {"SPR", NULL, "SPR ClassD"}, | ||
617 | }; | ||
618 | |||
619 | static const struct snd_soc_dapm_route | ||
620 | aic310x_audio_map[] = { | ||
621 | /* SP L path */ | ||
622 | {"Speaker", "Switch", "Output Left"}, | ||
623 | {"SPK ClassD", NULL, "Speaker"}, | ||
624 | {"SPK", NULL, "SPK ClassD"}, | ||
625 | }; | ||
626 | |||
627 | static int aic31xx_add_controls(struct snd_soc_codec *codec) | ||
628 | { | ||
629 | int ret = 0; | ||
630 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | ||
631 | |||
632 | if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) | ||
633 | ret = snd_soc_add_codec_controls( | ||
634 | codec, aic311x_snd_controls, | ||
635 | ARRAY_SIZE(aic311x_snd_controls)); | ||
636 | else | ||
637 | ret = snd_soc_add_codec_controls( | ||
638 | codec, aic310x_snd_controls, | ||
639 | ARRAY_SIZE(aic310x_snd_controls)); | ||
640 | |||
641 | return ret; | ||
642 | } | ||
643 | |||
644 | static int aic31xx_add_widgets(struct snd_soc_codec *codec) | ||
645 | { | ||
646 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
647 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | ||
648 | int ret = 0; | ||
649 | |||
650 | if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) { | ||
651 | ret = snd_soc_dapm_new_controls( | ||
652 | dapm, aic311x_dapm_widgets, | ||
653 | ARRAY_SIZE(aic311x_dapm_widgets)); | ||
654 | if (ret) | ||
655 | return ret; | ||
656 | |||
657 | ret = snd_soc_dapm_add_routes(dapm, aic311x_audio_map, | ||
658 | ARRAY_SIZE(aic311x_audio_map)); | ||
659 | if (ret) | ||
660 | return ret; | ||
661 | } else { | ||
662 | ret = snd_soc_dapm_new_controls( | ||
663 | dapm, aic310x_dapm_widgets, | ||
664 | ARRAY_SIZE(aic310x_dapm_widgets)); | ||
665 | if (ret) | ||
666 | return ret; | ||
667 | |||
668 | ret = snd_soc_dapm_add_routes(dapm, aic310x_audio_map, | ||
669 | ARRAY_SIZE(aic310x_audio_map)); | ||
670 | if (ret) | ||
671 | return ret; | ||
672 | } | ||
673 | |||
674 | return 0; | ||
675 | } | ||
676 | |||
677 | static int aic31xx_setup_pll(struct snd_soc_codec *codec, | ||
678 | struct snd_pcm_hw_params *params) | ||
679 | { | ||
680 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | ||
681 | int bclk_n = 0; | ||
682 | int i; | ||
683 | |||
684 | /* Use PLL as CODEC_CLKIN and DAC_CLK as BDIV_CLKIN */ | ||
685 | snd_soc_update_bits(codec, AIC31XX_CLKMUX, | ||
686 | AIC31XX_CODEC_CLKIN_MASK, AIC31XX_CODEC_CLKIN_PLL); | ||
687 | snd_soc_update_bits(codec, AIC31XX_IFACE2, | ||
688 | AIC31XX_BDIVCLK_MASK, AIC31XX_DAC2BCLK); | ||
689 | |||
690 | for (i = 0; i < ARRAY_SIZE(aic31xx_divs); i++) { | ||
691 | if (aic31xx_divs[i].rate == params_rate(params) && | ||
692 | aic31xx_divs[i].mclk == aic31xx->sysclk) | ||
693 | break; | ||
694 | } | ||
695 | |||
696 | if (i == ARRAY_SIZE(aic31xx_divs)) { | ||
697 | dev_err(codec->dev, "%s: Sampling rate %u not supported\n", | ||
698 | __func__, params_rate(params)); | ||
699 | return -EINVAL; | ||
700 | } | ||
701 | |||
702 | /* PLL configuration */ | ||
703 | snd_soc_update_bits(codec, AIC31XX_PLLPR, AIC31XX_PLL_MASK, | ||
704 | (aic31xx_divs[i].p_val << 4) | 0x01); | ||
705 | snd_soc_write(codec, AIC31XX_PLLJ, aic31xx_divs[i].pll_j); | ||
706 | |||
707 | snd_soc_write(codec, AIC31XX_PLLDMSB, | ||
708 | aic31xx_divs[i].pll_d >> 8); | ||
709 | snd_soc_write(codec, AIC31XX_PLLDLSB, | ||
710 | aic31xx_divs[i].pll_d & 0xff); | ||
711 | |||
712 | /* DAC dividers configuration */ | ||
713 | snd_soc_update_bits(codec, AIC31XX_NDAC, AIC31XX_PLL_MASK, | ||
714 | aic31xx_divs[i].ndac); | ||
715 | snd_soc_update_bits(codec, AIC31XX_MDAC, AIC31XX_PLL_MASK, | ||
716 | aic31xx_divs[i].mdac); | ||
717 | |||
718 | snd_soc_write(codec, AIC31XX_DOSRMSB, aic31xx_divs[i].dosr >> 8); | ||
719 | snd_soc_write(codec, AIC31XX_DOSRLSB, aic31xx_divs[i].dosr & 0xff); | ||
720 | |||
721 | /* ADC dividers configuration. Write reset value 1 if not used. */ | ||
722 | snd_soc_update_bits(codec, AIC31XX_NADC, AIC31XX_PLL_MASK, | ||
723 | aic31xx_divs[i].nadc ? aic31xx_divs[i].nadc : 1); | ||
724 | snd_soc_update_bits(codec, AIC31XX_MADC, AIC31XX_PLL_MASK, | ||
725 | aic31xx_divs[i].madc ? aic31xx_divs[i].madc : 1); | ||
726 | |||
727 | snd_soc_write(codec, AIC31XX_AOSR, aic31xx_divs[i].aosr); | ||
728 | |||
729 | /* Bit clock divider configuration. */ | ||
730 | bclk_n = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) | ||
731 | / snd_soc_params_to_frame_size(params); | ||
732 | if (bclk_n == 0) { | ||
733 | dev_err(codec->dev, "%s: Not enough BLCK bandwidth\n", | ||
734 | __func__); | ||
735 | return -EINVAL; | ||
736 | } | ||
737 | |||
738 | snd_soc_update_bits(codec, AIC31XX_BCLKN, | ||
739 | AIC31XX_PLL_MASK, bclk_n); | ||
740 | |||
741 | aic31xx->rate_div_line = i; | ||
742 | |||
743 | dev_dbg(codec->dev, | ||
744 | "pll %d.%04d/%d dosr %d n %d m %d aosr %d n %d m %d bclk_n %d\n", | ||
745 | aic31xx_divs[i].pll_j, aic31xx_divs[i].pll_d, | ||
746 | aic31xx_divs[i].p_val, aic31xx_divs[i].dosr, | ||
747 | aic31xx_divs[i].ndac, aic31xx_divs[i].mdac, | ||
748 | aic31xx_divs[i].aosr, aic31xx_divs[i].nadc, | ||
749 | aic31xx_divs[i].madc, bclk_n); | ||
750 | |||
751 | return 0; | ||
752 | } | ||
753 | |||
754 | static int aic31xx_hw_params(struct snd_pcm_substream *substream, | ||
755 | struct snd_pcm_hw_params *params, | ||
756 | struct snd_soc_dai *dai) | ||
757 | { | ||
758 | struct snd_soc_codec *codec = dai->codec; | ||
759 | u8 data = 0; | ||
760 | |||
761 | dev_dbg(codec->dev, "## %s: format %d width %d rate %d\n", | ||
762 | __func__, params_format(params), params_width(params), | ||
763 | params_rate(params)); | ||
764 | |||
765 | switch (params_width(params)) { | ||
766 | case 16: | ||
767 | break; | ||
768 | case 20: | ||
769 | data = (AIC31XX_WORD_LEN_20BITS << | ||
770 | AIC31XX_IFACE1_DATALEN_SHIFT); | ||
771 | break; | ||
772 | case 24: | ||
773 | data = (AIC31XX_WORD_LEN_24BITS << | ||
774 | AIC31XX_IFACE1_DATALEN_SHIFT); | ||
775 | break; | ||
776 | case 32: | ||
777 | data = (AIC31XX_WORD_LEN_32BITS << | ||
778 | AIC31XX_IFACE1_DATALEN_SHIFT); | ||
779 | break; | ||
780 | default: | ||
781 | dev_err(codec->dev, "%s: Unsupported format %d\n", | ||
782 | __func__, params_format(params)); | ||
783 | return -EINVAL; | ||
784 | } | ||
785 | |||
786 | snd_soc_update_bits(codec, AIC31XX_IFACE1, | ||
787 | AIC31XX_IFACE1_DATALEN_MASK, | ||
788 | data); | ||
789 | |||
790 | return aic31xx_setup_pll(codec, params); | ||
791 | } | ||
792 | |||
793 | static int aic31xx_dac_mute(struct snd_soc_dai *codec_dai, int mute) | ||
794 | { | ||
795 | struct snd_soc_codec *codec = codec_dai->codec; | ||
796 | |||
797 | if (mute) { | ||
798 | snd_soc_update_bits(codec, AIC31XX_DACMUTE, | ||
799 | AIC31XX_DACMUTE_MASK, | ||
800 | AIC31XX_DACMUTE_MASK); | ||
801 | } else { | ||
802 | snd_soc_update_bits(codec, AIC31XX_DACMUTE, | ||
803 | AIC31XX_DACMUTE_MASK, 0x0); | ||
804 | } | ||
805 | |||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
810 | unsigned int fmt) | ||
811 | { | ||
812 | struct snd_soc_codec *codec = codec_dai->codec; | ||
813 | u8 iface_reg1 = 0; | ||
814 | u8 iface_reg3 = 0; | ||
815 | u8 dsp_a_val = 0; | ||
816 | |||
817 | dev_dbg(codec->dev, "## %s: fmt = 0x%x\n", __func__, fmt); | ||
818 | |||
819 | /* set master/slave audio interface */ | ||
820 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
821 | case SND_SOC_DAIFMT_CBM_CFM: | ||
822 | iface_reg1 |= AIC31XX_BCLK_MASTER | AIC31XX_WCLK_MASTER; | ||
823 | break; | ||
824 | default: | ||
825 | dev_alert(codec->dev, "Invalid DAI master/slave interface\n"); | ||
826 | return -EINVAL; | ||
827 | } | ||
828 | |||
829 | /* interface format */ | ||
830 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
831 | case SND_SOC_DAIFMT_I2S: | ||
832 | break; | ||
833 | case SND_SOC_DAIFMT_DSP_A: | ||
834 | dsp_a_val = 0x1; | ||
835 | case SND_SOC_DAIFMT_DSP_B: | ||
836 | /* NOTE: BCLKINV bit value 1 equas NB and 0 equals IB */ | ||
837 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
838 | case SND_SOC_DAIFMT_NB_NF: | ||
839 | iface_reg3 |= AIC31XX_BCLKINV_MASK; | ||
840 | break; | ||
841 | case SND_SOC_DAIFMT_IB_NF: | ||
842 | break; | ||
843 | default: | ||
844 | return -EINVAL; | ||
845 | } | ||
846 | iface_reg1 |= (AIC31XX_DSP_MODE << | ||
847 | AIC31XX_IFACE1_DATATYPE_SHIFT); | ||
848 | break; | ||
849 | case SND_SOC_DAIFMT_RIGHT_J: | ||
850 | iface_reg1 |= (AIC31XX_RIGHT_JUSTIFIED_MODE << | ||
851 | AIC31XX_IFACE1_DATATYPE_SHIFT); | ||
852 | break; | ||
853 | case SND_SOC_DAIFMT_LEFT_J: | ||
854 | iface_reg1 |= (AIC31XX_LEFT_JUSTIFIED_MODE << | ||
855 | AIC31XX_IFACE1_DATATYPE_SHIFT); | ||
856 | break; | ||
857 | default: | ||
858 | dev_err(codec->dev, "Invalid DAI interface format\n"); | ||
859 | return -EINVAL; | ||
860 | } | ||
861 | |||
862 | snd_soc_update_bits(codec, AIC31XX_IFACE1, | ||
863 | AIC31XX_IFACE1_DATATYPE_MASK | | ||
864 | AIC31XX_IFACE1_MASTER_MASK, | ||
865 | iface_reg1); | ||
866 | snd_soc_update_bits(codec, AIC31XX_DATA_OFFSET, | ||
867 | AIC31XX_DATA_OFFSET_MASK, | ||
868 | dsp_a_val); | ||
869 | snd_soc_update_bits(codec, AIC31XX_IFACE2, | ||
870 | AIC31XX_BCLKINV_MASK, | ||
871 | iface_reg3); | ||
872 | |||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
877 | int clk_id, unsigned int freq, int dir) | ||
878 | { | ||
879 | struct snd_soc_codec *codec = codec_dai->codec; | ||
880 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | ||
881 | int i; | ||
882 | |||
883 | dev_dbg(codec->dev, "## %s: clk_id = %d, freq = %d, dir = %d\n", | ||
884 | __func__, clk_id, freq, dir); | ||
885 | |||
886 | for (i = 0; aic31xx_divs[i].mclk != freq; i++) { | ||
887 | if (i == ARRAY_SIZE(aic31xx_divs)) { | ||
888 | dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n", | ||
889 | __func__, freq); | ||
890 | return -EINVAL; | ||
891 | } | ||
892 | } | ||
893 | |||
894 | /* set clock on MCLK, BCLK, or GPIO1 as PLL input */ | ||
895 | snd_soc_update_bits(codec, AIC31XX_CLKMUX, AIC31XX_PLL_CLKIN_MASK, | ||
896 | clk_id << AIC31XX_PLL_CLKIN_SHIFT); | ||
897 | |||
898 | aic31xx->sysclk = freq; | ||
899 | return 0; | ||
900 | } | ||
901 | |||
902 | static int aic31xx_regulator_event(struct notifier_block *nb, | ||
903 | unsigned long event, void *data) | ||
904 | { | ||
905 | struct aic31xx_disable_nb *disable_nb = | ||
906 | container_of(nb, struct aic31xx_disable_nb, nb); | ||
907 | struct aic31xx_priv *aic31xx = disable_nb->aic31xx; | ||
908 | |||
909 | if (event & REGULATOR_EVENT_DISABLE) { | ||
910 | /* | ||
911 | * Put codec to reset and as at least one of the | ||
912 | * supplies was disabled. | ||
913 | */ | ||
914 | if (gpio_is_valid(aic31xx->pdata.gpio_reset)) | ||
915 | gpio_set_value(aic31xx->pdata.gpio_reset, 0); | ||
916 | |||
917 | regcache_mark_dirty(aic31xx->regmap); | ||
918 | dev_dbg(aic31xx->dev, "## %s: DISABLE received\n", __func__); | ||
919 | } | ||
920 | |||
921 | return 0; | ||
922 | } | ||
923 | |||
924 | static void aic31xx_clk_on(struct snd_soc_codec *codec) | ||
925 | { | ||
926 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | ||
927 | u8 mask = AIC31XX_PM_MASK; | ||
928 | u8 on = AIC31XX_PM_MASK; | ||
929 | |||
930 | dev_dbg(codec->dev, "codec clock -> on (rate %d)\n", | ||
931 | aic31xx_divs[aic31xx->rate_div_line].rate); | ||
932 | snd_soc_update_bits(codec, AIC31XX_PLLPR, mask, on); | ||
933 | mdelay(10); | ||
934 | snd_soc_update_bits(codec, AIC31XX_NDAC, mask, on); | ||
935 | snd_soc_update_bits(codec, AIC31XX_MDAC, mask, on); | ||
936 | if (aic31xx_divs[aic31xx->rate_div_line].nadc) | ||
937 | snd_soc_update_bits(codec, AIC31XX_NADC, mask, on); | ||
938 | if (aic31xx_divs[aic31xx->rate_div_line].madc) | ||
939 | snd_soc_update_bits(codec, AIC31XX_MADC, mask, on); | ||
940 | snd_soc_update_bits(codec, AIC31XX_BCLKN, mask, on); | ||
941 | } | ||
942 | |||
943 | static void aic31xx_clk_off(struct snd_soc_codec *codec) | ||
944 | { | ||
945 | u8 mask = AIC31XX_PM_MASK; | ||
946 | u8 off = 0; | ||
947 | |||
948 | dev_dbg(codec->dev, "codec clock -> off\n"); | ||
949 | snd_soc_update_bits(codec, AIC31XX_BCLKN, mask, off); | ||
950 | snd_soc_update_bits(codec, AIC31XX_MADC, mask, off); | ||
951 | snd_soc_update_bits(codec, AIC31XX_NADC, mask, off); | ||
952 | snd_soc_update_bits(codec, AIC31XX_MDAC, mask, off); | ||
953 | snd_soc_update_bits(codec, AIC31XX_NDAC, mask, off); | ||
954 | snd_soc_update_bits(codec, AIC31XX_PLLPR, mask, off); | ||
955 | } | ||
956 | |||
957 | static int aic31xx_power_on(struct snd_soc_codec *codec) | ||
958 | { | ||
959 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | ||
960 | int ret = 0; | ||
961 | |||
962 | ret = regulator_bulk_enable(ARRAY_SIZE(aic31xx->supplies), | ||
963 | aic31xx->supplies); | ||
964 | if (ret) | ||
965 | return ret; | ||
966 | |||
967 | if (gpio_is_valid(aic31xx->pdata.gpio_reset)) { | ||
968 | gpio_set_value(aic31xx->pdata.gpio_reset, 1); | ||
969 | udelay(100); | ||
970 | } | ||
971 | regcache_cache_only(aic31xx->regmap, false); | ||
972 | ret = regcache_sync(aic31xx->regmap); | ||
973 | if (ret != 0) { | ||
974 | dev_err(codec->dev, | ||
975 | "Failed to restore cache: %d\n", ret); | ||
976 | regcache_cache_only(aic31xx->regmap, true); | ||
977 | regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies), | ||
978 | aic31xx->supplies); | ||
979 | return ret; | ||
980 | } | ||
981 | return 0; | ||
982 | } | ||
983 | |||
984 | static int aic31xx_power_off(struct snd_soc_codec *codec) | ||
985 | { | ||
986 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | ||
987 | int ret = 0; | ||
988 | |||
989 | regcache_cache_only(aic31xx->regmap, true); | ||
990 | ret = regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies), | ||
991 | aic31xx->supplies); | ||
992 | |||
993 | return ret; | ||
994 | } | ||
995 | |||
996 | static int aic31xx_set_bias_level(struct snd_soc_codec *codec, | ||
997 | enum snd_soc_bias_level level) | ||
998 | { | ||
999 | dev_dbg(codec->dev, "## %s: %d -> %d\n", __func__, | ||
1000 | codec->dapm.bias_level, level); | ||
1001 | |||
1002 | switch (level) { | ||
1003 | case SND_SOC_BIAS_ON: | ||
1004 | break; | ||
1005 | case SND_SOC_BIAS_PREPARE: | ||
1006 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) | ||
1007 | aic31xx_clk_on(codec); | ||
1008 | break; | ||
1009 | case SND_SOC_BIAS_STANDBY: | ||
1010 | switch (codec->dapm.bias_level) { | ||
1011 | case SND_SOC_BIAS_OFF: | ||
1012 | aic31xx_power_on(codec); | ||
1013 | break; | ||
1014 | case SND_SOC_BIAS_PREPARE: | ||
1015 | aic31xx_clk_off(codec); | ||
1016 | break; | ||
1017 | default: | ||
1018 | BUG(); | ||
1019 | } | ||
1020 | break; | ||
1021 | case SND_SOC_BIAS_OFF: | ||
1022 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) | ||
1023 | aic31xx_power_off(codec); | ||
1024 | break; | ||
1025 | } | ||
1026 | codec->dapm.bias_level = level; | ||
1027 | |||
1028 | return 0; | ||
1029 | } | ||
1030 | |||
1031 | static int aic31xx_suspend(struct snd_soc_codec *codec) | ||
1032 | { | ||
1033 | aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | static int aic31xx_resume(struct snd_soc_codec *codec) | ||
1038 | { | ||
1039 | aic31xx_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1040 | return 0; | ||
1041 | } | ||
1042 | |||
1043 | static int aic31xx_codec_probe(struct snd_soc_codec *codec) | ||
1044 | { | ||
1045 | int ret = 0; | ||
1046 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | ||
1047 | int i; | ||
1048 | |||
1049 | dev_dbg(aic31xx->dev, "## %s\n", __func__); | ||
1050 | |||
1051 | aic31xx = snd_soc_codec_get_drvdata(codec); | ||
1052 | |||
1053 | aic31xx->codec = codec; | ||
1054 | |||
1055 | for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) { | ||
1056 | aic31xx->disable_nb[i].nb.notifier_call = | ||
1057 | aic31xx_regulator_event; | ||
1058 | aic31xx->disable_nb[i].aic31xx = aic31xx; | ||
1059 | ret = regulator_register_notifier(aic31xx->supplies[i].consumer, | ||
1060 | &aic31xx->disable_nb[i].nb); | ||
1061 | if (ret) { | ||
1062 | dev_err(codec->dev, | ||
1063 | "Failed to request regulator notifier: %d\n", | ||
1064 | ret); | ||
1065 | return ret; | ||
1066 | } | ||
1067 | } | ||
1068 | |||
1069 | regcache_cache_only(aic31xx->regmap, true); | ||
1070 | regcache_mark_dirty(aic31xx->regmap); | ||
1071 | |||
1072 | ret = aic31xx_add_controls(codec); | ||
1073 | if (ret) | ||
1074 | return ret; | ||
1075 | |||
1076 | ret = aic31xx_add_widgets(codec); | ||
1077 | |||
1078 | return ret; | ||
1079 | } | ||
1080 | |||
1081 | static int aic31xx_codec_remove(struct snd_soc_codec *codec) | ||
1082 | { | ||
1083 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | ||
1084 | int i; | ||
1085 | /* power down chip */ | ||
1086 | aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1087 | |||
1088 | for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) | ||
1089 | regulator_unregister_notifier(aic31xx->supplies[i].consumer, | ||
1090 | &aic31xx->disable_nb[i].nb); | ||
1091 | |||
1092 | return 0; | ||
1093 | } | ||
1094 | |||
1095 | static struct snd_soc_codec_driver soc_codec_driver_aic31xx = { | ||
1096 | .probe = aic31xx_codec_probe, | ||
1097 | .remove = aic31xx_codec_remove, | ||
1098 | .suspend = aic31xx_suspend, | ||
1099 | .resume = aic31xx_resume, | ||
1100 | .set_bias_level = aic31xx_set_bias_level, | ||
1101 | .controls = aic31xx_snd_controls, | ||
1102 | .num_controls = ARRAY_SIZE(aic31xx_snd_controls), | ||
1103 | .dapm_widgets = aic31xx_dapm_widgets, | ||
1104 | .num_dapm_widgets = ARRAY_SIZE(aic31xx_dapm_widgets), | ||
1105 | .dapm_routes = aic31xx_audio_map, | ||
1106 | .num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map), | ||
1107 | }; | ||
1108 | |||
1109 | static struct snd_soc_dai_ops aic31xx_dai_ops = { | ||
1110 | .hw_params = aic31xx_hw_params, | ||
1111 | .set_sysclk = aic31xx_set_dai_sysclk, | ||
1112 | .set_fmt = aic31xx_set_dai_fmt, | ||
1113 | .digital_mute = aic31xx_dac_mute, | ||
1114 | }; | ||
1115 | |||
1116 | static struct snd_soc_dai_driver aic31xx_dai_driver[] = { | ||
1117 | { | ||
1118 | .name = "tlv320aic31xx-hifi", | ||
1119 | .playback = { | ||
1120 | .stream_name = "Playback", | ||
1121 | .channels_min = 1, | ||
1122 | .channels_max = 2, | ||
1123 | .rates = AIC31XX_RATES, | ||
1124 | .formats = AIC31XX_FORMATS, | ||
1125 | }, | ||
1126 | .capture = { | ||
1127 | .stream_name = "Capture", | ||
1128 | .channels_min = 1, | ||
1129 | .channels_max = 2, | ||
1130 | .rates = AIC31XX_RATES, | ||
1131 | .formats = AIC31XX_FORMATS, | ||
1132 | }, | ||
1133 | .ops = &aic31xx_dai_ops, | ||
1134 | .symmetric_rates = 1, | ||
1135 | } | ||
1136 | }; | ||
1137 | |||
1138 | #if defined(CONFIG_OF) | ||
1139 | static const struct of_device_id tlv320aic31xx_of_match[] = { | ||
1140 | { .compatible = "ti,tlv320aic310x" }, | ||
1141 | { .compatible = "ti,tlv320aic311x" }, | ||
1142 | { .compatible = "ti,tlv320aic3100" }, | ||
1143 | { .compatible = "ti,tlv320aic3110" }, | ||
1144 | { .compatible = "ti,tlv320aic3120" }, | ||
1145 | { .compatible = "ti,tlv320aic3111" }, | ||
1146 | {}, | ||
1147 | }; | ||
1148 | MODULE_DEVICE_TABLE(of, tlv320aic31xx_of_match); | ||
1149 | |||
1150 | static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx) | ||
1151 | { | ||
1152 | struct device_node *np = aic31xx->dev->of_node; | ||
1153 | unsigned int value = MICBIAS_2_0V; | ||
1154 | int ret; | ||
1155 | |||
1156 | of_property_read_u32(np, "ai31xx-micbias-vg", &value); | ||
1157 | switch (value) { | ||
1158 | case MICBIAS_2_0V: | ||
1159 | case MICBIAS_2_5V: | ||
1160 | case MICBIAS_AVDDV: | ||
1161 | aic31xx->pdata.micbias_vg = value; | ||
1162 | break; | ||
1163 | default: | ||
1164 | dev_err(aic31xx->dev, | ||
1165 | "Bad ai31xx-micbias-vg value %d DT\n", | ||
1166 | value); | ||
1167 | aic31xx->pdata.micbias_vg = MICBIAS_2_0V; | ||
1168 | } | ||
1169 | |||
1170 | ret = of_get_named_gpio(np, "gpio-reset", 0); | ||
1171 | if (ret > 0) | ||
1172 | aic31xx->pdata.gpio_reset = ret; | ||
1173 | } | ||
1174 | #else /* CONFIG_OF */ | ||
1175 | static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx) | ||
1176 | { | ||
1177 | } | ||
1178 | #endif /* CONFIG_OF */ | ||
1179 | |||
1180 | static void aic31xx_device_init(struct aic31xx_priv *aic31xx) | ||
1181 | { | ||
1182 | int ret, i; | ||
1183 | |||
1184 | dev_set_drvdata(aic31xx->dev, aic31xx); | ||
1185 | |||
1186 | if (dev_get_platdata(aic31xx->dev)) | ||
1187 | memcpy(&aic31xx->pdata, dev_get_platdata(aic31xx->dev), | ||
1188 | sizeof(aic31xx->pdata)); | ||
1189 | else if (aic31xx->dev->of_node) | ||
1190 | aic31xx_pdata_from_of(aic31xx); | ||
1191 | |||
1192 | if (aic31xx->pdata.gpio_reset) { | ||
1193 | ret = devm_gpio_request_one(aic31xx->dev, | ||
1194 | aic31xx->pdata.gpio_reset, | ||
1195 | GPIOF_OUT_INIT_HIGH, | ||
1196 | "aic31xx-reset-pin"); | ||
1197 | if (ret < 0) { | ||
1198 | dev_err(aic31xx->dev, "not able to acquire gpio\n"); | ||
1199 | return; | ||
1200 | } | ||
1201 | } | ||
1202 | |||
1203 | for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) | ||
1204 | aic31xx->supplies[i].supply = aic31xx_supply_names[i]; | ||
1205 | |||
1206 | ret = devm_regulator_bulk_get(aic31xx->dev, | ||
1207 | ARRAY_SIZE(aic31xx->supplies), | ||
1208 | aic31xx->supplies); | ||
1209 | if (ret != 0) | ||
1210 | dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret); | ||
1211 | |||
1212 | } | ||
1213 | |||
1214 | static int aic31xx_i2c_probe(struct i2c_client *i2c, | ||
1215 | const struct i2c_device_id *id) | ||
1216 | { | ||
1217 | struct aic31xx_priv *aic31xx; | ||
1218 | int ret; | ||
1219 | const struct regmap_config *regmap_config; | ||
1220 | |||
1221 | dev_dbg(&i2c->dev, "## %s: %s codec_type = %d\n", __func__, | ||
1222 | id->name, (int) id->driver_data); | ||
1223 | |||
1224 | regmap_config = &aic31xx_i2c_regmap; | ||
1225 | |||
1226 | aic31xx = devm_kzalloc(&i2c->dev, sizeof(*aic31xx), GFP_KERNEL); | ||
1227 | if (aic31xx == NULL) | ||
1228 | return -ENOMEM; | ||
1229 | |||
1230 | aic31xx->regmap = devm_regmap_init_i2c(i2c, regmap_config); | ||
1231 | if (IS_ERR(aic31xx->regmap)) { | ||
1232 | ret = PTR_ERR(aic31xx->regmap); | ||
1233 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
1234 | ret); | ||
1235 | return ret; | ||
1236 | } | ||
1237 | aic31xx->dev = &i2c->dev; | ||
1238 | |||
1239 | aic31xx->pdata.codec_type = id->driver_data; | ||
1240 | |||
1241 | aic31xx_device_init(aic31xx); | ||
1242 | |||
1243 | return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, | ||
1244 | aic31xx_dai_driver, | ||
1245 | ARRAY_SIZE(aic31xx_dai_driver)); | ||
1246 | } | ||
1247 | |||
1248 | static int aic31xx_i2c_remove(struct i2c_client *i2c) | ||
1249 | { | ||
1250 | snd_soc_unregister_codec(&i2c->dev); | ||
1251 | return 0; | ||
1252 | } | ||
1253 | |||
1254 | static const struct i2c_device_id aic31xx_i2c_id[] = { | ||
1255 | { "tlv320aic310x", AIC3100 }, | ||
1256 | { "tlv320aic311x", AIC3110 }, | ||
1257 | { "tlv320aic3100", AIC3100 }, | ||
1258 | { "tlv320aic3110", AIC3110 }, | ||
1259 | { "tlv320aic3120", AIC3120 }, | ||
1260 | { "tlv320aic3111", AIC3111 }, | ||
1261 | { } | ||
1262 | }; | ||
1263 | MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); | ||
1264 | |||
1265 | static struct i2c_driver aic31xx_i2c_driver = { | ||
1266 | .driver = { | ||
1267 | .name = "tlv320aic31xx-codec", | ||
1268 | .owner = THIS_MODULE, | ||
1269 | .of_match_table = of_match_ptr(tlv320aic31xx_of_match), | ||
1270 | }, | ||
1271 | .probe = aic31xx_i2c_probe, | ||
1272 | .remove = aic31xx_i2c_remove, | ||
1273 | .id_table = aic31xx_i2c_id, | ||
1274 | }; | ||
1275 | |||
1276 | module_i2c_driver(aic31xx_i2c_driver); | ||
1277 | |||
1278 | MODULE_DESCRIPTION("ASoC TLV320AIC3111 codec driver"); | ||
1279 | MODULE_AUTHOR("Jyri Sarha"); | ||
1280 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h new file mode 100644 index 000000000000..52ed57c69dfa --- /dev/null +++ b/sound/soc/codecs/tlv320aic31xx.h | |||
@@ -0,0 +1,258 @@ | |||
1 | /* | ||
2 | * ALSA SoC TLV320AIC31XX codec driver | ||
3 | * | ||
4 | * Copyright (C) 2013 Texas Instruments, Inc. | ||
5 | * | ||
6 | * This package is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | ||
11 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | ||
12 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
13 | * | ||
14 | */ | ||
15 | #ifndef _TLV320AIC31XX_H | ||
16 | #define _TLV320AIC31XX_H | ||
17 | |||
18 | #define AIC31XX_RATES SNDRV_PCM_RATE_8000_192000 | ||
19 | |||
20 | #define AIC31XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ | ||
21 | | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
22 | |||
23 | |||
24 | #define AIC31XX_STEREO_CLASS_D_BIT 0x1 | ||
25 | #define AIC31XX_MINIDSP_BIT 0x2 | ||
26 | |||
27 | enum aic31xx_type { | ||
28 | AIC3100 = 0, | ||
29 | AIC3110 = AIC31XX_STEREO_CLASS_D_BIT, | ||
30 | AIC3120 = AIC31XX_MINIDSP_BIT, | ||
31 | AIC3111 = (AIC31XX_STEREO_CLASS_D_BIT | AIC31XX_MINIDSP_BIT), | ||
32 | }; | ||
33 | |||
34 | struct aic31xx_pdata { | ||
35 | enum aic31xx_type codec_type; | ||
36 | unsigned int gpio_reset; | ||
37 | int micbias_vg; | ||
38 | }; | ||
39 | |||
40 | /* Page Control Register */ | ||
41 | #define AIC31XX_PAGECTL 0x00 | ||
42 | |||
43 | /* Page 0 Registers */ | ||
44 | /* Software reset register */ | ||
45 | #define AIC31XX_RESET 0x01 | ||
46 | /* OT FLAG register */ | ||
47 | #define AIC31XX_OT_FLAG 0x03 | ||
48 | /* Clock clock Gen muxing, Multiplexers*/ | ||
49 | #define AIC31XX_CLKMUX 0x04 | ||
50 | /* PLL P and R-VAL register */ | ||
51 | #define AIC31XX_PLLPR 0x05 | ||
52 | /* PLL J-VAL register */ | ||
53 | #define AIC31XX_PLLJ 0x06 | ||
54 | /* PLL D-VAL MSB register */ | ||
55 | #define AIC31XX_PLLDMSB 0x07 | ||
56 | /* PLL D-VAL LSB register */ | ||
57 | #define AIC31XX_PLLDLSB 0x08 | ||
58 | /* DAC NDAC_VAL register*/ | ||
59 | #define AIC31XX_NDAC 0x0B | ||
60 | /* DAC MDAC_VAL register */ | ||
61 | #define AIC31XX_MDAC 0x0C | ||
62 | /* DAC OSR setting register 1, MSB value */ | ||
63 | #define AIC31XX_DOSRMSB 0x0D | ||
64 | /* DAC OSR setting register 2, LSB value */ | ||
65 | #define AIC31XX_DOSRLSB 0x0E | ||
66 | #define AIC31XX_MINI_DSP_INPOL 0x10 | ||
67 | /* Clock setting register 8, PLL */ | ||
68 | #define AIC31XX_NADC 0x12 | ||
69 | /* Clock setting register 9, PLL */ | ||
70 | #define AIC31XX_MADC 0x13 | ||
71 | /* ADC Oversampling (AOSR) Register */ | ||
72 | #define AIC31XX_AOSR 0x14 | ||
73 | /* Clock setting register 9, Multiplexers */ | ||
74 | #define AIC31XX_CLKOUTMUX 0x19 | ||
75 | /* Clock setting register 10, CLOCKOUT M divider value */ | ||
76 | #define AIC31XX_CLKOUTMVAL 0x1A | ||
77 | /* Audio Interface Setting Register 1 */ | ||
78 | #define AIC31XX_IFACE1 0x1B | ||
79 | /* Audio Data Slot Offset Programming */ | ||
80 | #define AIC31XX_DATA_OFFSET 0x1C | ||
81 | /* Audio Interface Setting Register 2 */ | ||
82 | #define AIC31XX_IFACE2 0x1D | ||
83 | /* Clock setting register 11, BCLK N Divider */ | ||
84 | #define AIC31XX_BCLKN 0x1E | ||
85 | /* Audio Interface Setting Register 3, Secondary Audio Interface */ | ||
86 | #define AIC31XX_IFACESEC1 0x1F | ||
87 | /* Audio Interface Setting Register 4 */ | ||
88 | #define AIC31XX_IFACESEC2 0x20 | ||
89 | /* Audio Interface Setting Register 5 */ | ||
90 | #define AIC31XX_IFACESEC3 0x21 | ||
91 | /* I2C Bus Condition */ | ||
92 | #define AIC31XX_I2C 0x22 | ||
93 | /* ADC FLAG */ | ||
94 | #define AIC31XX_ADCFLAG 0x24 | ||
95 | /* DAC Flag Registers */ | ||
96 | #define AIC31XX_DACFLAG1 0x25 | ||
97 | #define AIC31XX_DACFLAG2 0x26 | ||
98 | /* Sticky Interrupt flag (overflow) */ | ||
99 | #define AIC31XX_OFFLAG 0x27 | ||
100 | /* Sticy DAC Interrupt flags */ | ||
101 | #define AIC31XX_INTRDACFLAG 0x2C | ||
102 | /* Sticy ADC Interrupt flags */ | ||
103 | #define AIC31XX_INTRADCFLAG 0x2D | ||
104 | /* DAC Interrupt flags 2 */ | ||
105 | #define AIC31XX_INTRDACFLAG2 0x2E | ||
106 | /* ADC Interrupt flags 2 */ | ||
107 | #define AIC31XX_INTRADCFLAG2 0x2F | ||
108 | /* INT1 interrupt control */ | ||
109 | #define AIC31XX_INT1CTRL 0x30 | ||
110 | /* INT2 interrupt control */ | ||
111 | #define AIC31XX_INT2CTRL 0x31 | ||
112 | /* GPIO1 control */ | ||
113 | #define AIC31XX_GPIO1 0x33 | ||
114 | |||
115 | #define AIC31XX_DACPRB 0x3C | ||
116 | /* ADC Instruction Set Register */ | ||
117 | #define AIC31XX_ADCPRB 0x3D | ||
118 | /* DAC channel setup register */ | ||
119 | #define AIC31XX_DACSETUP 0x3F | ||
120 | /* DAC Mute and volume control register */ | ||
121 | #define AIC31XX_DACMUTE 0x40 | ||
122 | /* Left DAC channel digital volume control */ | ||
123 | #define AIC31XX_LDACVOL 0x41 | ||
124 | /* Right DAC channel digital volume control */ | ||
125 | #define AIC31XX_RDACVOL 0x42 | ||
126 | /* Headset detection */ | ||
127 | #define AIC31XX_HSDETECT 0x43 | ||
128 | /* ADC Digital Mic */ | ||
129 | #define AIC31XX_ADCSETUP 0x51 | ||
130 | /* ADC Digital Volume Control Fine Adjust */ | ||
131 | #define AIC31XX_ADCFGA 0x52 | ||
132 | /* ADC Digital Volume Control Coarse Adjust */ | ||
133 | #define AIC31XX_ADCVOL 0x53 | ||
134 | |||
135 | |||
136 | /* Page 1 Registers */ | ||
137 | /* Headphone drivers */ | ||
138 | #define AIC31XX_HPDRIVER 0x9F | ||
139 | /* Class-D Speakear Amplifier */ | ||
140 | #define AIC31XX_SPKAMP 0xA0 | ||
141 | /* HP Output Drivers POP Removal Settings */ | ||
142 | #define AIC31XX_HPPOP 0xA1 | ||
143 | /* Output Driver PGA Ramp-Down Period Control */ | ||
144 | #define AIC31XX_SPPGARAMP 0xA2 | ||
145 | /* DAC_L and DAC_R Output Mixer Routing */ | ||
146 | #define AIC31XX_DACMIXERROUTE 0xA3 | ||
147 | /* Left Analog Vol to HPL */ | ||
148 | #define AIC31XX_LANALOGHPL 0xA4 | ||
149 | /* Right Analog Vol to HPR */ | ||
150 | #define AIC31XX_RANALOGHPR 0xA5 | ||
151 | /* Left Analog Vol to SPL */ | ||
152 | #define AIC31XX_LANALOGSPL 0xA6 | ||
153 | /* Right Analog Vol to SPR */ | ||
154 | #define AIC31XX_RANALOGSPR 0xA7 | ||
155 | /* HPL Driver */ | ||
156 | #define AIC31XX_HPLGAIN 0xA8 | ||
157 | /* HPR Driver */ | ||
158 | #define AIC31XX_HPRGAIN 0xA9 | ||
159 | /* SPL Driver */ | ||
160 | #define AIC31XX_SPLGAIN 0xAA | ||
161 | /* SPR Driver */ | ||
162 | #define AIC31XX_SPRGAIN 0xAB | ||
163 | /* HP Driver Control */ | ||
164 | #define AIC31XX_HPCONTROL 0xAC | ||
165 | /* MIC Bias Control */ | ||
166 | #define AIC31XX_MICBIAS 0xAE | ||
167 | /* MIC PGA*/ | ||
168 | #define AIC31XX_MICPGA 0xAF | ||
169 | /* Delta-Sigma Mono ADC Channel Fine-Gain Input Selection for P-Terminal */ | ||
170 | #define AIC31XX_MICPGAPI 0xB0 | ||
171 | /* ADC Input Selection for M-Terminal */ | ||
172 | #define AIC31XX_MICPGAMI 0xB1 | ||
173 | /* Input CM Settings */ | ||
174 | #define AIC31XX_MICPGACM 0xB2 | ||
175 | |||
176 | /* Bits, masks and shifts */ | ||
177 | |||
178 | /* AIC31XX_CLKMUX */ | ||
179 | #define AIC31XX_PLL_CLKIN_MASK 0x0c | ||
180 | #define AIC31XX_PLL_CLKIN_SHIFT 2 | ||
181 | #define AIC31XX_PLL_CLKIN_MCLK 0 | ||
182 | #define AIC31XX_CODEC_CLKIN_MASK 0x03 | ||
183 | #define AIC31XX_CODEC_CLKIN_SHIFT 0 | ||
184 | #define AIC31XX_CODEC_CLKIN_PLL 3 | ||
185 | #define AIC31XX_CODEC_CLKIN_BCLK 1 | ||
186 | |||
187 | /* AIC31XX_PLLPR, AIC31XX_NDAC, AIC31XX_MDAC, AIC31XX_NADC, AIC31XX_MADC, | ||
188 | AIC31XX_BCLKN */ | ||
189 | #define AIC31XX_PLL_MASK 0x7f | ||
190 | #define AIC31XX_PM_MASK 0x80 | ||
191 | |||
192 | /* AIC31XX_IFACE1 */ | ||
193 | #define AIC31XX_WORD_LEN_16BITS 0x00 | ||
194 | #define AIC31XX_WORD_LEN_20BITS 0x01 | ||
195 | #define AIC31XX_WORD_LEN_24BITS 0x02 | ||
196 | #define AIC31XX_WORD_LEN_32BITS 0x03 | ||
197 | #define AIC31XX_IFACE1_DATALEN_MASK 0x30 | ||
198 | #define AIC31XX_IFACE1_DATALEN_SHIFT (4) | ||
199 | #define AIC31XX_IFACE1_DATATYPE_MASK 0xC0 | ||
200 | #define AIC31XX_IFACE1_DATATYPE_SHIFT (6) | ||
201 | #define AIC31XX_I2S_MODE 0x00 | ||
202 | #define AIC31XX_DSP_MODE 0x01 | ||
203 | #define AIC31XX_RIGHT_JUSTIFIED_MODE 0x02 | ||
204 | #define AIC31XX_LEFT_JUSTIFIED_MODE 0x03 | ||
205 | #define AIC31XX_IFACE1_MASTER_MASK 0x0C | ||
206 | #define AIC31XX_BCLK_MASTER 0x08 | ||
207 | #define AIC31XX_WCLK_MASTER 0x04 | ||
208 | |||
209 | /* AIC31XX_DATA_OFFSET */ | ||
210 | #define AIC31XX_DATA_OFFSET_MASK 0xFF | ||
211 | |||
212 | /* AIC31XX_IFACE2 */ | ||
213 | #define AIC31XX_BCLKINV_MASK 0x08 | ||
214 | #define AIC31XX_BDIVCLK_MASK 0x03 | ||
215 | #define AIC31XX_DAC2BCLK 0x00 | ||
216 | #define AIC31XX_DACMOD2BCLK 0x01 | ||
217 | #define AIC31XX_ADC2BCLK 0x02 | ||
218 | #define AIC31XX_ADCMOD2BCLK 0x03 | ||
219 | |||
220 | /* AIC31XX_ADCFLAG */ | ||
221 | #define AIC31XX_ADCPWRSTATUS_MASK 0x40 | ||
222 | |||
223 | /* AIC31XX_DACFLAG1 */ | ||
224 | #define AIC31XX_LDACPWRSTATUS_MASK 0x80 | ||
225 | #define AIC31XX_RDACPWRSTATUS_MASK 0x08 | ||
226 | #define AIC31XX_HPLDRVPWRSTATUS_MASK 0x20 | ||
227 | #define AIC31XX_HPRDRVPWRSTATUS_MASK 0x02 | ||
228 | #define AIC31XX_SPLDRVPWRSTATUS_MASK 0x10 | ||
229 | #define AIC31XX_SPRDRVPWRSTATUS_MASK 0x01 | ||
230 | |||
231 | /* AIC31XX_INTRDACFLAG */ | ||
232 | #define AIC31XX_HPSCDETECT_MASK 0x80 | ||
233 | #define AIC31XX_BUTTONPRESS_MASK 0x20 | ||
234 | #define AIC31XX_HSPLUG_MASK 0x10 | ||
235 | #define AIC31XX_LDRCTHRES_MASK 0x08 | ||
236 | #define AIC31XX_RDRCTHRES_MASK 0x04 | ||
237 | #define AIC31XX_DACSINT_MASK 0x02 | ||
238 | #define AIC31XX_DACAINT_MASK 0x01 | ||
239 | |||
240 | /* AIC31XX_INT1CTRL */ | ||
241 | #define AIC31XX_HSPLUGDET_MASK 0x80 | ||
242 | #define AIC31XX_BUTTONPRESSDET_MASK 0x40 | ||
243 | #define AIC31XX_DRCTHRES_MASK 0x20 | ||
244 | #define AIC31XX_AGCNOISE_MASK 0x10 | ||
245 | #define AIC31XX_OC_MASK 0x08 | ||
246 | #define AIC31XX_ENGINE_MASK 0x04 | ||
247 | |||
248 | /* AIC31XX_DACSETUP */ | ||
249 | #define AIC31XX_SOFTSTEP_MASK 0x03 | ||
250 | |||
251 | /* AIC31XX_DACMUTE */ | ||
252 | #define AIC31XX_DACMUTE_MASK 0x0C | ||
253 | |||
254 | /* AIC31XX_MICBIAS */ | ||
255 | #define AIC31XX_MICBIAS_MASK 0x03 | ||
256 | #define AIC31XX_MICBIAS_SHIFT 0 | ||
257 | |||
258 | #endif /* _TLV320AIC31XX_H */ | ||
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 688151ba309a..1d9b117345a3 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c | |||
@@ -29,9 +29,12 @@ | |||
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/pm.h> | 30 | #include <linux/pm.h> |
31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
32 | #include <linux/of_gpio.h> | ||
32 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
33 | #include <linux/cdev.h> | 34 | #include <linux/cdev.h> |
34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/clk.h> | ||
37 | #include <linux/regulator/consumer.h> | ||
35 | 38 | ||
36 | #include <sound/tlv320aic32x4.h> | 39 | #include <sound/tlv320aic32x4.h> |
37 | #include <sound/core.h> | 40 | #include <sound/core.h> |
@@ -66,20 +69,32 @@ struct aic32x4_priv { | |||
66 | u32 micpga_routing; | 69 | u32 micpga_routing; |
67 | bool swapdacs; | 70 | bool swapdacs; |
68 | int rstn_gpio; | 71 | int rstn_gpio; |
72 | struct clk *mclk; | ||
73 | |||
74 | struct regulator *supply_ldo; | ||
75 | struct regulator *supply_iov; | ||
76 | struct regulator *supply_dv; | ||
77 | struct regulator *supply_av; | ||
69 | }; | 78 | }; |
70 | 79 | ||
71 | /* 0dB min, 1dB steps */ | ||
72 | static DECLARE_TLV_DB_SCALE(tlv_step_1, 0, 100, 0); | ||
73 | /* 0dB min, 0.5dB steps */ | 80 | /* 0dB min, 0.5dB steps */ |
74 | static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0); | 81 | static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0); |
82 | /* -63.5dB min, 0.5dB steps */ | ||
83 | static DECLARE_TLV_DB_SCALE(tlv_pcm, -6350, 50, 0); | ||
84 | /* -6dB min, 1dB steps */ | ||
85 | static DECLARE_TLV_DB_SCALE(tlv_driver_gain, -600, 100, 0); | ||
86 | /* -12dB min, 0.5dB steps */ | ||
87 | static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0); | ||
75 | 88 | ||
76 | static const struct snd_kcontrol_new aic32x4_snd_controls[] = { | 89 | static const struct snd_kcontrol_new aic32x4_snd_controls[] = { |
77 | SOC_DOUBLE_R_TLV("PCM Playback Volume", AIC32X4_LDACVOL, | 90 | SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL, |
78 | AIC32X4_RDACVOL, 0, 0x30, 0, tlv_step_0_5), | 91 | AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm), |
79 | SOC_DOUBLE_R_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, | 92 | SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, |
80 | AIC32X4_HPRGAIN, 0, 0x1D, 0, tlv_step_1), | 93 | AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0, |
81 | SOC_DOUBLE_R_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, | 94 | tlv_driver_gain), |
82 | AIC32X4_LORGAIN, 0, 0x1D, 0, tlv_step_1), | 95 | SOC_DOUBLE_R_S_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, |
96 | AIC32X4_LORGAIN, 0, -0x6, 0x1d, 5, 0, | ||
97 | tlv_driver_gain), | ||
83 | SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN, | 98 | SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN, |
84 | AIC32X4_HPRGAIN, 6, 0x01, 1), | 99 | AIC32X4_HPRGAIN, 6, 0x01, 1), |
85 | SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN, | 100 | SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN, |
@@ -90,8 +105,8 @@ static const struct snd_kcontrol_new aic32x4_snd_controls[] = { | |||
90 | SOC_SINGLE("ADCFGA Left Mute Switch", AIC32X4_ADCFGA, 7, 1, 0), | 105 | SOC_SINGLE("ADCFGA Left Mute Switch", AIC32X4_ADCFGA, 7, 1, 0), |
91 | SOC_SINGLE("ADCFGA Right Mute Switch", AIC32X4_ADCFGA, 3, 1, 0), | 106 | SOC_SINGLE("ADCFGA Right Mute Switch", AIC32X4_ADCFGA, 3, 1, 0), |
92 | 107 | ||
93 | SOC_DOUBLE_R_TLV("ADC Level Volume", AIC32X4_LADCVOL, | 108 | SOC_DOUBLE_R_S_TLV("ADC Level Volume", AIC32X4_LADCVOL, |
94 | AIC32X4_RADCVOL, 0, 0x28, 0, tlv_step_0_5), | 109 | AIC32X4_RADCVOL, 0, -0x18, 0x28, 6, 0, tlv_adc_vol), |
95 | SOC_DOUBLE_R_TLV("PGA Level Volume", AIC32X4_LMICPGAVOL, | 110 | SOC_DOUBLE_R_TLV("PGA Level Volume", AIC32X4_LMICPGAVOL, |
96 | AIC32X4_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5), | 111 | AIC32X4_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5), |
97 | 112 | ||
@@ -480,8 +495,18 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute) | |||
480 | static int aic32x4_set_bias_level(struct snd_soc_codec *codec, | 495 | static int aic32x4_set_bias_level(struct snd_soc_codec *codec, |
481 | enum snd_soc_bias_level level) | 496 | enum snd_soc_bias_level level) |
482 | { | 497 | { |
498 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | ||
499 | int ret; | ||
500 | |||
483 | switch (level) { | 501 | switch (level) { |
484 | case SND_SOC_BIAS_ON: | 502 | case SND_SOC_BIAS_ON: |
503 | /* Switch on master clock */ | ||
504 | ret = clk_prepare_enable(aic32x4->mclk); | ||
505 | if (ret) { | ||
506 | dev_err(codec->dev, "Failed to enable master clock\n"); | ||
507 | return ret; | ||
508 | } | ||
509 | |||
485 | /* Switch on PLL */ | 510 | /* Switch on PLL */ |
486 | snd_soc_update_bits(codec, AIC32X4_PLLPR, | 511 | snd_soc_update_bits(codec, AIC32X4_PLLPR, |
487 | AIC32X4_PLLEN, AIC32X4_PLLEN); | 512 | AIC32X4_PLLEN, AIC32X4_PLLEN); |
@@ -509,29 +534,32 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, | |||
509 | case SND_SOC_BIAS_PREPARE: | 534 | case SND_SOC_BIAS_PREPARE: |
510 | break; | 535 | break; |
511 | case SND_SOC_BIAS_STANDBY: | 536 | case SND_SOC_BIAS_STANDBY: |
512 | /* Switch off PLL */ | 537 | /* Switch off BCLK_N Divider */ |
513 | snd_soc_update_bits(codec, AIC32X4_PLLPR, | 538 | snd_soc_update_bits(codec, AIC32X4_BCLKN, |
514 | AIC32X4_PLLEN, 0); | 539 | AIC32X4_BCLKEN, 0); |
515 | 540 | ||
516 | /* Switch off NDAC Divider */ | 541 | /* Switch off MADC Divider */ |
517 | snd_soc_update_bits(codec, AIC32X4_NDAC, | 542 | snd_soc_update_bits(codec, AIC32X4_MADC, |
518 | AIC32X4_NDACEN, 0); | 543 | AIC32X4_MADCEN, 0); |
544 | |||
545 | /* Switch off NADC Divider */ | ||
546 | snd_soc_update_bits(codec, AIC32X4_NADC, | ||
547 | AIC32X4_NADCEN, 0); | ||
519 | 548 | ||
520 | /* Switch off MDAC Divider */ | 549 | /* Switch off MDAC Divider */ |
521 | snd_soc_update_bits(codec, AIC32X4_MDAC, | 550 | snd_soc_update_bits(codec, AIC32X4_MDAC, |
522 | AIC32X4_MDACEN, 0); | 551 | AIC32X4_MDACEN, 0); |
523 | 552 | ||
524 | /* Switch off NADC Divider */ | 553 | /* Switch off NDAC Divider */ |
525 | snd_soc_update_bits(codec, AIC32X4_NADC, | 554 | snd_soc_update_bits(codec, AIC32X4_NDAC, |
526 | AIC32X4_NADCEN, 0); | 555 | AIC32X4_NDACEN, 0); |
527 | 556 | ||
528 | /* Switch off MADC Divider */ | 557 | /* Switch off PLL */ |
529 | snd_soc_update_bits(codec, AIC32X4_MADC, | 558 | snd_soc_update_bits(codec, AIC32X4_PLLPR, |
530 | AIC32X4_MADCEN, 0); | 559 | AIC32X4_PLLEN, 0); |
531 | 560 | ||
532 | /* Switch off BCLK_N Divider */ | 561 | /* Switch off master clock */ |
533 | snd_soc_update_bits(codec, AIC32X4_BCLKN, | 562 | clk_disable_unprepare(aic32x4->mclk); |
534 | AIC32X4_BCLKEN, 0); | ||
535 | break; | 563 | break; |
536 | case SND_SOC_BIAS_OFF: | 564 | case SND_SOC_BIAS_OFF: |
537 | break; | 565 | break; |
@@ -586,9 +614,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec) | |||
586 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | 614 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); |
587 | u32 tmp_reg; | 615 | u32 tmp_reg; |
588 | 616 | ||
589 | snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | 617 | if (gpio_is_valid(aic32x4->rstn_gpio)) { |
590 | |||
591 | if (aic32x4->rstn_gpio >= 0) { | ||
592 | ndelay(10); | 618 | ndelay(10); |
593 | gpio_set_value(aic32x4->rstn_gpio, 1); | 619 | gpio_set_value(aic32x4->rstn_gpio, 1); |
594 | } | 620 | } |
@@ -663,11 +689,122 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { | |||
663 | .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), | 689 | .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), |
664 | }; | 690 | }; |
665 | 691 | ||
692 | static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4, | ||
693 | struct device_node *np) | ||
694 | { | ||
695 | aic32x4->swapdacs = false; | ||
696 | aic32x4->micpga_routing = 0; | ||
697 | aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0); | ||
698 | |||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | static void aic32x4_disable_regulators(struct aic32x4_priv *aic32x4) | ||
703 | { | ||
704 | regulator_disable(aic32x4->supply_iov); | ||
705 | |||
706 | if (!IS_ERR(aic32x4->supply_ldo)) | ||
707 | regulator_disable(aic32x4->supply_ldo); | ||
708 | |||
709 | if (!IS_ERR(aic32x4->supply_dv)) | ||
710 | regulator_disable(aic32x4->supply_dv); | ||
711 | |||
712 | if (!IS_ERR(aic32x4->supply_av)) | ||
713 | regulator_disable(aic32x4->supply_av); | ||
714 | } | ||
715 | |||
716 | static int aic32x4_setup_regulators(struct device *dev, | ||
717 | struct aic32x4_priv *aic32x4) | ||
718 | { | ||
719 | int ret = 0; | ||
720 | |||
721 | aic32x4->supply_ldo = devm_regulator_get_optional(dev, "ldoin"); | ||
722 | aic32x4->supply_iov = devm_regulator_get(dev, "iov"); | ||
723 | aic32x4->supply_dv = devm_regulator_get_optional(dev, "dv"); | ||
724 | aic32x4->supply_av = devm_regulator_get_optional(dev, "av"); | ||
725 | |||
726 | /* Check if the regulator requirements are fulfilled */ | ||
727 | |||
728 | if (IS_ERR(aic32x4->supply_iov)) { | ||
729 | dev_err(dev, "Missing supply 'iov'\n"); | ||
730 | return PTR_ERR(aic32x4->supply_iov); | ||
731 | } | ||
732 | |||
733 | if (IS_ERR(aic32x4->supply_ldo)) { | ||
734 | if (PTR_ERR(aic32x4->supply_ldo) == -EPROBE_DEFER) | ||
735 | return -EPROBE_DEFER; | ||
736 | |||
737 | if (IS_ERR(aic32x4->supply_dv)) { | ||
738 | dev_err(dev, "Missing supply 'dv' or 'ldoin'\n"); | ||
739 | return PTR_ERR(aic32x4->supply_dv); | ||
740 | } | ||
741 | if (IS_ERR(aic32x4->supply_av)) { | ||
742 | dev_err(dev, "Missing supply 'av' or 'ldoin'\n"); | ||
743 | return PTR_ERR(aic32x4->supply_av); | ||
744 | } | ||
745 | } else { | ||
746 | if (IS_ERR(aic32x4->supply_dv) && | ||
747 | PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER) | ||
748 | return -EPROBE_DEFER; | ||
749 | if (IS_ERR(aic32x4->supply_av) && | ||
750 | PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER) | ||
751 | return -EPROBE_DEFER; | ||
752 | } | ||
753 | |||
754 | ret = regulator_enable(aic32x4->supply_iov); | ||
755 | if (ret) { | ||
756 | dev_err(dev, "Failed to enable regulator iov\n"); | ||
757 | return ret; | ||
758 | } | ||
759 | |||
760 | if (!IS_ERR(aic32x4->supply_ldo)) { | ||
761 | ret = regulator_enable(aic32x4->supply_ldo); | ||
762 | if (ret) { | ||
763 | dev_err(dev, "Failed to enable regulator ldo\n"); | ||
764 | goto error_ldo; | ||
765 | } | ||
766 | } | ||
767 | |||
768 | if (!IS_ERR(aic32x4->supply_dv)) { | ||
769 | ret = regulator_enable(aic32x4->supply_dv); | ||
770 | if (ret) { | ||
771 | dev_err(dev, "Failed to enable regulator dv\n"); | ||
772 | goto error_dv; | ||
773 | } | ||
774 | } | ||
775 | |||
776 | if (!IS_ERR(aic32x4->supply_av)) { | ||
777 | ret = regulator_enable(aic32x4->supply_av); | ||
778 | if (ret) { | ||
779 | dev_err(dev, "Failed to enable regulator av\n"); | ||
780 | goto error_av; | ||
781 | } | ||
782 | } | ||
783 | |||
784 | if (!IS_ERR(aic32x4->supply_ldo) && IS_ERR(aic32x4->supply_av)) | ||
785 | aic32x4->power_cfg |= AIC32X4_PWR_AIC32X4_LDO_ENABLE; | ||
786 | |||
787 | return 0; | ||
788 | |||
789 | error_av: | ||
790 | if (!IS_ERR(aic32x4->supply_dv)) | ||
791 | regulator_disable(aic32x4->supply_dv); | ||
792 | |||
793 | error_dv: | ||
794 | if (!IS_ERR(aic32x4->supply_ldo)) | ||
795 | regulator_disable(aic32x4->supply_ldo); | ||
796 | |||
797 | error_ldo: | ||
798 | regulator_disable(aic32x4->supply_iov); | ||
799 | return ret; | ||
800 | } | ||
801 | |||
666 | static int aic32x4_i2c_probe(struct i2c_client *i2c, | 802 | static int aic32x4_i2c_probe(struct i2c_client *i2c, |
667 | const struct i2c_device_id *id) | 803 | const struct i2c_device_id *id) |
668 | { | 804 | { |
669 | struct aic32x4_pdata *pdata = i2c->dev.platform_data; | 805 | struct aic32x4_pdata *pdata = i2c->dev.platform_data; |
670 | struct aic32x4_priv *aic32x4; | 806 | struct aic32x4_priv *aic32x4; |
807 | struct device_node *np = i2c->dev.of_node; | ||
671 | int ret; | 808 | int ret; |
672 | 809 | ||
673 | aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv), | 810 | aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv), |
@@ -686,6 +823,12 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, | |||
686 | aic32x4->swapdacs = pdata->swapdacs; | 823 | aic32x4->swapdacs = pdata->swapdacs; |
687 | aic32x4->micpga_routing = pdata->micpga_routing; | 824 | aic32x4->micpga_routing = pdata->micpga_routing; |
688 | aic32x4->rstn_gpio = pdata->rstn_gpio; | 825 | aic32x4->rstn_gpio = pdata->rstn_gpio; |
826 | } else if (np) { | ||
827 | ret = aic32x4_parse_dt(aic32x4, np); | ||
828 | if (ret) { | ||
829 | dev_err(&i2c->dev, "Failed to parse DT node\n"); | ||
830 | return ret; | ||
831 | } | ||
689 | } else { | 832 | } else { |
690 | aic32x4->power_cfg = 0; | 833 | aic32x4->power_cfg = 0; |
691 | aic32x4->swapdacs = false; | 834 | aic32x4->swapdacs = false; |
@@ -693,20 +836,44 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, | |||
693 | aic32x4->rstn_gpio = -1; | 836 | aic32x4->rstn_gpio = -1; |
694 | } | 837 | } |
695 | 838 | ||
696 | if (aic32x4->rstn_gpio >= 0) { | 839 | aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk"); |
840 | if (IS_ERR(aic32x4->mclk)) { | ||
841 | dev_err(&i2c->dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n"); | ||
842 | return PTR_ERR(aic32x4->mclk); | ||
843 | } | ||
844 | |||
845 | if (gpio_is_valid(aic32x4->rstn_gpio)) { | ||
697 | ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, | 846 | ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, |
698 | GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); | 847 | GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); |
699 | if (ret != 0) | 848 | if (ret != 0) |
700 | return ret; | 849 | return ret; |
701 | } | 850 | } |
702 | 851 | ||
852 | ret = aic32x4_setup_regulators(&i2c->dev, aic32x4); | ||
853 | if (ret) { | ||
854 | dev_err(&i2c->dev, "Failed to setup regulators\n"); | ||
855 | return ret; | ||
856 | } | ||
857 | |||
703 | ret = snd_soc_register_codec(&i2c->dev, | 858 | ret = snd_soc_register_codec(&i2c->dev, |
704 | &soc_codec_dev_aic32x4, &aic32x4_dai, 1); | 859 | &soc_codec_dev_aic32x4, &aic32x4_dai, 1); |
705 | return ret; | 860 | if (ret) { |
861 | dev_err(&i2c->dev, "Failed to register codec\n"); | ||
862 | aic32x4_disable_regulators(aic32x4); | ||
863 | return ret; | ||
864 | } | ||
865 | |||
866 | i2c_set_clientdata(i2c, aic32x4); | ||
867 | |||
868 | return 0; | ||
706 | } | 869 | } |
707 | 870 | ||
708 | static int aic32x4_i2c_remove(struct i2c_client *client) | 871 | static int aic32x4_i2c_remove(struct i2c_client *client) |
709 | { | 872 | { |
873 | struct aic32x4_priv *aic32x4 = i2c_get_clientdata(client); | ||
874 | |||
875 | aic32x4_disable_regulators(aic32x4); | ||
876 | |||
710 | snd_soc_unregister_codec(&client->dev); | 877 | snd_soc_unregister_codec(&client->dev); |
711 | return 0; | 878 | return 0; |
712 | } | 879 | } |
@@ -717,10 +884,17 @@ static const struct i2c_device_id aic32x4_i2c_id[] = { | |||
717 | }; | 884 | }; |
718 | MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); | 885 | MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); |
719 | 886 | ||
887 | static const struct of_device_id aic32x4_of_id[] = { | ||
888 | { .compatible = "ti,tlv320aic32x4", }, | ||
889 | { /* senitel */ } | ||
890 | }; | ||
891 | MODULE_DEVICE_TABLE(of, aic32x4_of_id); | ||
892 | |||
720 | static struct i2c_driver aic32x4_i2c_driver = { | 893 | static struct i2c_driver aic32x4_i2c_driver = { |
721 | .driver = { | 894 | .driver = { |
722 | .name = "tlv320aic32x4", | 895 | .name = "tlv320aic32x4", |
723 | .owner = THIS_MODULE, | 896 | .owner = THIS_MODULE, |
897 | .of_match_table = aic32x4_of_id, | ||
724 | }, | 898 | }, |
725 | .probe = aic32x4_i2c_probe, | 899 | .probe = aic32x4_i2c_probe, |
726 | .remove = aic32x4_i2c_remove, | 900 | .remove = aic32x4_i2c_remove, |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 470fbfb4b386..b1835103e9b4 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -1344,12 +1344,6 @@ static int aic3x_probe(struct snd_soc_codec *codec) | |||
1344 | INIT_LIST_HEAD(&aic3x->list); | 1344 | INIT_LIST_HEAD(&aic3x->list); |
1345 | aic3x->codec = codec; | 1345 | aic3x->codec = codec; |
1346 | 1346 | ||
1347 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
1348 | if (ret != 0) { | ||
1349 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1350 | return ret; | ||
1351 | } | ||
1352 | |||
1353 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) { | 1347 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) { |
1354 | aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event; | 1348 | aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event; |
1355 | aic3x->disable_nb[i].aic3x = aic3x; | 1349 | aic3x->disable_nb[i].aic3x = aic3x; |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 4f358393d6d6..6bfc8a17331b 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -122,7 +122,6 @@ struct tlv320dac33_priv { | |||
122 | unsigned int uthr; | 122 | unsigned int uthr; |
123 | 123 | ||
124 | enum dac33_state state; | 124 | enum dac33_state state; |
125 | enum snd_soc_control_type control_type; | ||
126 | void *control_data; | 125 | void *control_data; |
127 | }; | 126 | }; |
128 | 127 | ||
@@ -461,7 +460,7 @@ static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol, | |||
461 | if (dac33->fifo_mode == ucontrol->value.integer.value[0]) | 460 | if (dac33->fifo_mode == ucontrol->value.integer.value[0]) |
462 | return 0; | 461 | return 0; |
463 | /* Do not allow changes while stream is running*/ | 462 | /* Do not allow changes while stream is running*/ |
464 | if (codec->active) | 463 | if (snd_soc_codec_is_active(codec)) |
465 | return -EPERM; | 464 | return -EPERM; |
466 | 465 | ||
467 | if (ucontrol->value.integer.value[0] < 0 || | 466 | if (ucontrol->value.integer.value[0] < 0 || |
@@ -478,9 +477,7 @@ static const char *dac33_fifo_mode_texts[] = { | |||
478 | "Bypass", "Mode 1", "Mode 7" | 477 | "Bypass", "Mode 1", "Mode 7" |
479 | }; | 478 | }; |
480 | 479 | ||
481 | static const struct soc_enum dac33_fifo_mode_enum = | 480 | static SOC_ENUM_SINGLE_EXT_DECL(dac33_fifo_mode_enum, dac33_fifo_mode_texts); |
482 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dac33_fifo_mode_texts), | ||
483 | dac33_fifo_mode_texts); | ||
484 | 481 | ||
485 | /* L/R Line Output Gain */ | 482 | /* L/R Line Output Gain */ |
486 | static const char *lr_lineout_gain_texts[] = { | 483 | static const char *lr_lineout_gain_texts[] = { |
@@ -488,15 +485,13 @@ static const char *lr_lineout_gain_texts[] = { | |||
488 | "Line 0dB DAC 12dB", "Line 6dB DAC 18dB", | 485 | "Line 0dB DAC 12dB", "Line 6dB DAC 18dB", |
489 | }; | 486 | }; |
490 | 487 | ||
491 | static const struct soc_enum l_lineout_gain_enum = | 488 | static SOC_ENUM_SINGLE_DECL(l_lineout_gain_enum, |
492 | SOC_ENUM_SINGLE(DAC33_LDAC_PWR_CTRL, 0, | 489 | DAC33_LDAC_PWR_CTRL, 0, |
493 | ARRAY_SIZE(lr_lineout_gain_texts), | 490 | lr_lineout_gain_texts); |
494 | lr_lineout_gain_texts); | ||
495 | 491 | ||
496 | static const struct soc_enum r_lineout_gain_enum = | 492 | static SOC_ENUM_SINGLE_DECL(r_lineout_gain_enum, |
497 | SOC_ENUM_SINGLE(DAC33_RDAC_PWR_CTRL, 0, | 493 | DAC33_RDAC_PWR_CTRL, 0, |
498 | ARRAY_SIZE(lr_lineout_gain_texts), | 494 | lr_lineout_gain_texts); |
499 | lr_lineout_gain_texts); | ||
500 | 495 | ||
501 | /* | 496 | /* |
502 | * DACL/R digital volume control: | 497 | * DACL/R digital volume control: |
@@ -534,18 +529,16 @@ static const struct snd_kcontrol_new dac33_dapm_abypassr_control = | |||
534 | /* LOP L/R invert selection */ | 529 | /* LOP L/R invert selection */ |
535 | static const char *dac33_lr_lom_texts[] = {"DAC", "LOP"}; | 530 | static const char *dac33_lr_lom_texts[] = {"DAC", "LOP"}; |
536 | 531 | ||
537 | static const struct soc_enum dac33_left_lom_enum = | 532 | static SOC_ENUM_SINGLE_DECL(dac33_left_lom_enum, |
538 | SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 3, | 533 | DAC33_OUT_AMP_CTRL, 3, |
539 | ARRAY_SIZE(dac33_lr_lom_texts), | 534 | dac33_lr_lom_texts); |
540 | dac33_lr_lom_texts); | ||
541 | 535 | ||
542 | static const struct snd_kcontrol_new dac33_dapm_left_lom_control = | 536 | static const struct snd_kcontrol_new dac33_dapm_left_lom_control = |
543 | SOC_DAPM_ENUM("Route", dac33_left_lom_enum); | 537 | SOC_DAPM_ENUM("Route", dac33_left_lom_enum); |
544 | 538 | ||
545 | static const struct soc_enum dac33_right_lom_enum = | 539 | static SOC_ENUM_SINGLE_DECL(dac33_right_lom_enum, |
546 | SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 2, | 540 | DAC33_OUT_AMP_CTRL, 2, |
547 | ARRAY_SIZE(dac33_lr_lom_texts), | 541 | dac33_lr_lom_texts); |
548 | dac33_lr_lom_texts); | ||
549 | 542 | ||
550 | static const struct snd_kcontrol_new dac33_dapm_right_lom_control = | 543 | static const struct snd_kcontrol_new dac33_dapm_right_lom_control = |
551 | SOC_DAPM_ENUM("Route", dac33_right_lom_enum); | 544 | SOC_DAPM_ENUM("Route", dac33_right_lom_enum); |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 00665ada23e2..975e0f760ac1 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -415,10 +415,9 @@ static const struct snd_kcontrol_new twl4030_dapm_carkitr_controls[] = { | |||
415 | static const char *twl4030_handsfreel_texts[] = | 415 | static const char *twl4030_handsfreel_texts[] = |
416 | {"Voice", "AudioL1", "AudioL2", "AudioR2"}; | 416 | {"Voice", "AudioL1", "AudioL2", "AudioR2"}; |
417 | 417 | ||
418 | static const struct soc_enum twl4030_handsfreel_enum = | 418 | static SOC_ENUM_SINGLE_DECL(twl4030_handsfreel_enum, |
419 | SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0, | 419 | TWL4030_REG_HFL_CTL, 0, |
420 | ARRAY_SIZE(twl4030_handsfreel_texts), | 420 | twl4030_handsfreel_texts); |
421 | twl4030_handsfreel_texts); | ||
422 | 421 | ||
423 | static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control = | 422 | static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control = |
424 | SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum); | 423 | SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum); |
@@ -431,10 +430,9 @@ static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control = | |||
431 | static const char *twl4030_handsfreer_texts[] = | 430 | static const char *twl4030_handsfreer_texts[] = |
432 | {"Voice", "AudioR1", "AudioR2", "AudioL2"}; | 431 | {"Voice", "AudioR1", "AudioR2", "AudioL2"}; |
433 | 432 | ||
434 | static const struct soc_enum twl4030_handsfreer_enum = | 433 | static SOC_ENUM_SINGLE_DECL(twl4030_handsfreer_enum, |
435 | SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0, | 434 | TWL4030_REG_HFR_CTL, 0, |
436 | ARRAY_SIZE(twl4030_handsfreer_texts), | 435 | twl4030_handsfreer_texts); |
437 | twl4030_handsfreer_texts); | ||
438 | 436 | ||
439 | static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control = | 437 | static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control = |
440 | SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum); | 438 | SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum); |
@@ -448,10 +446,9 @@ static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control = | |||
448 | static const char *twl4030_vibra_texts[] = | 446 | static const char *twl4030_vibra_texts[] = |
449 | {"AudioL1", "AudioR1", "AudioL2", "AudioR2"}; | 447 | {"AudioL1", "AudioR1", "AudioL2", "AudioR2"}; |
450 | 448 | ||
451 | static const struct soc_enum twl4030_vibra_enum = | 449 | static SOC_ENUM_SINGLE_DECL(twl4030_vibra_enum, |
452 | SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 2, | 450 | TWL4030_REG_VIBRA_CTL, 2, |
453 | ARRAY_SIZE(twl4030_vibra_texts), | 451 | twl4030_vibra_texts); |
454 | twl4030_vibra_texts); | ||
455 | 452 | ||
456 | static const struct snd_kcontrol_new twl4030_dapm_vibra_control = | 453 | static const struct snd_kcontrol_new twl4030_dapm_vibra_control = |
457 | SOC_DAPM_ENUM("Route", twl4030_vibra_enum); | 454 | SOC_DAPM_ENUM("Route", twl4030_vibra_enum); |
@@ -460,10 +457,9 @@ SOC_DAPM_ENUM("Route", twl4030_vibra_enum); | |||
460 | static const char *twl4030_vibrapath_texts[] = | 457 | static const char *twl4030_vibrapath_texts[] = |
461 | {"Local vibrator", "Audio"}; | 458 | {"Local vibrator", "Audio"}; |
462 | 459 | ||
463 | static const struct soc_enum twl4030_vibrapath_enum = | 460 | static SOC_ENUM_SINGLE_DECL(twl4030_vibrapath_enum, |
464 | SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 4, | 461 | TWL4030_REG_VIBRA_CTL, 4, |
465 | ARRAY_SIZE(twl4030_vibrapath_texts), | 462 | twl4030_vibrapath_texts); |
466 | twl4030_vibrapath_texts); | ||
467 | 463 | ||
468 | static const struct snd_kcontrol_new twl4030_dapm_vibrapath_control = | 464 | static const struct snd_kcontrol_new twl4030_dapm_vibrapath_control = |
469 | SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum); | 465 | SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum); |
@@ -490,10 +486,9 @@ static const struct snd_kcontrol_new twl4030_dapm_analogrmic_controls[] = { | |||
490 | static const char *twl4030_micpathtx1_texts[] = | 486 | static const char *twl4030_micpathtx1_texts[] = |
491 | {"Analog", "Digimic0"}; | 487 | {"Analog", "Digimic0"}; |
492 | 488 | ||
493 | static const struct soc_enum twl4030_micpathtx1_enum = | 489 | static SOC_ENUM_SINGLE_DECL(twl4030_micpathtx1_enum, |
494 | SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 0, | 490 | TWL4030_REG_ADCMICSEL, 0, |
495 | ARRAY_SIZE(twl4030_micpathtx1_texts), | 491 | twl4030_micpathtx1_texts); |
496 | twl4030_micpathtx1_texts); | ||
497 | 492 | ||
498 | static const struct snd_kcontrol_new twl4030_dapm_micpathtx1_control = | 493 | static const struct snd_kcontrol_new twl4030_dapm_micpathtx1_control = |
499 | SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum); | 494 | SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum); |
@@ -502,10 +497,9 @@ SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum); | |||
502 | static const char *twl4030_micpathtx2_texts[] = | 497 | static const char *twl4030_micpathtx2_texts[] = |
503 | {"Analog", "Digimic1"}; | 498 | {"Analog", "Digimic1"}; |
504 | 499 | ||
505 | static const struct soc_enum twl4030_micpathtx2_enum = | 500 | static SOC_ENUM_SINGLE_DECL(twl4030_micpathtx2_enum, |
506 | SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 2, | 501 | TWL4030_REG_ADCMICSEL, 2, |
507 | ARRAY_SIZE(twl4030_micpathtx2_texts), | 502 | twl4030_micpathtx2_texts); |
508 | twl4030_micpathtx2_texts); | ||
509 | 503 | ||
510 | static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control = | 504 | static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control = |
511 | SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum); | 505 | SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum); |
@@ -955,19 +949,15 @@ static const char *twl4030_op_modes_texts[] = { | |||
955 | "Option 2 (voice/audio)", "Option 1 (audio)" | 949 | "Option 2 (voice/audio)", "Option 1 (audio)" |
956 | }; | 950 | }; |
957 | 951 | ||
958 | static const struct soc_enum twl4030_op_modes_enum = | 952 | static SOC_ENUM_SINGLE_DECL(twl4030_op_modes_enum, |
959 | SOC_ENUM_SINGLE(TWL4030_REG_CODEC_MODE, 0, | 953 | TWL4030_REG_CODEC_MODE, 0, |
960 | ARRAY_SIZE(twl4030_op_modes_texts), | 954 | twl4030_op_modes_texts); |
961 | twl4030_op_modes_texts); | ||
962 | 955 | ||
963 | static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, | 956 | static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, |
964 | struct snd_ctl_elem_value *ucontrol) | 957 | struct snd_ctl_elem_value *ucontrol) |
965 | { | 958 | { |
966 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 959 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
967 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 960 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
968 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
969 | unsigned short val; | ||
970 | unsigned short mask; | ||
971 | 961 | ||
972 | if (twl4030->configured) { | 962 | if (twl4030->configured) { |
973 | dev_err(codec->dev, | 963 | dev_err(codec->dev, |
@@ -975,19 +965,7 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, | |||
975 | return -EBUSY; | 965 | return -EBUSY; |
976 | } | 966 | } |
977 | 967 | ||
978 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 968 | return snd_soc_put_enum_double(kcontrol, ucontrol); |
979 | return -EINVAL; | ||
980 | |||
981 | val = ucontrol->value.enumerated.item[0] << e->shift_l; | ||
982 | mask = e->mask << e->shift_l; | ||
983 | if (e->shift_l != e->shift_r) { | ||
984 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | ||
985 | return -EINVAL; | ||
986 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | ||
987 | mask |= e->mask << e->shift_r; | ||
988 | } | ||
989 | |||
990 | return snd_soc_update_bits(codec, e->reg, mask, val); | ||
991 | } | 969 | } |
992 | 970 | ||
993 | /* | 971 | /* |
@@ -1044,10 +1022,9 @@ static const char *twl4030_avadc_clk_priority_texts[] = { | |||
1044 | "Voice high priority", "HiFi high priority" | 1022 | "Voice high priority", "HiFi high priority" |
1045 | }; | 1023 | }; |
1046 | 1024 | ||
1047 | static const struct soc_enum twl4030_avadc_clk_priority_enum = | 1025 | static SOC_ENUM_SINGLE_DECL(twl4030_avadc_clk_priority_enum, |
1048 | SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2, | 1026 | TWL4030_REG_AVADC_CTL, 2, |
1049 | ARRAY_SIZE(twl4030_avadc_clk_priority_texts), | 1027 | twl4030_avadc_clk_priority_texts); |
1050 | twl4030_avadc_clk_priority_texts); | ||
1051 | 1028 | ||
1052 | static const char *twl4030_rampdelay_texts[] = { | 1029 | static const char *twl4030_rampdelay_texts[] = { |
1053 | "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", | 1030 | "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", |
@@ -1055,40 +1032,36 @@ static const char *twl4030_rampdelay_texts[] = { | |||
1055 | "3495/2581/1748 ms" | 1032 | "3495/2581/1748 ms" |
1056 | }; | 1033 | }; |
1057 | 1034 | ||
1058 | static const struct soc_enum twl4030_rampdelay_enum = | 1035 | static SOC_ENUM_SINGLE_DECL(twl4030_rampdelay_enum, |
1059 | SOC_ENUM_SINGLE(TWL4030_REG_HS_POPN_SET, 2, | 1036 | TWL4030_REG_HS_POPN_SET, 2, |
1060 | ARRAY_SIZE(twl4030_rampdelay_texts), | 1037 | twl4030_rampdelay_texts); |
1061 | twl4030_rampdelay_texts); | ||
1062 | 1038 | ||
1063 | /* Vibra H-bridge direction mode */ | 1039 | /* Vibra H-bridge direction mode */ |
1064 | static const char *twl4030_vibradirmode_texts[] = { | 1040 | static const char *twl4030_vibradirmode_texts[] = { |
1065 | "Vibra H-bridge direction", "Audio data MSB", | 1041 | "Vibra H-bridge direction", "Audio data MSB", |
1066 | }; | 1042 | }; |
1067 | 1043 | ||
1068 | static const struct soc_enum twl4030_vibradirmode_enum = | 1044 | static SOC_ENUM_SINGLE_DECL(twl4030_vibradirmode_enum, |
1069 | SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 5, | 1045 | TWL4030_REG_VIBRA_CTL, 5, |
1070 | ARRAY_SIZE(twl4030_vibradirmode_texts), | 1046 | twl4030_vibradirmode_texts); |
1071 | twl4030_vibradirmode_texts); | ||
1072 | 1047 | ||
1073 | /* Vibra H-bridge direction */ | 1048 | /* Vibra H-bridge direction */ |
1074 | static const char *twl4030_vibradir_texts[] = { | 1049 | static const char *twl4030_vibradir_texts[] = { |
1075 | "Positive polarity", "Negative polarity", | 1050 | "Positive polarity", "Negative polarity", |
1076 | }; | 1051 | }; |
1077 | 1052 | ||
1078 | static const struct soc_enum twl4030_vibradir_enum = | 1053 | static SOC_ENUM_SINGLE_DECL(twl4030_vibradir_enum, |
1079 | SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 1, | 1054 | TWL4030_REG_VIBRA_CTL, 1, |
1080 | ARRAY_SIZE(twl4030_vibradir_texts), | 1055 | twl4030_vibradir_texts); |
1081 | twl4030_vibradir_texts); | ||
1082 | 1056 | ||
1083 | /* Digimic Left and right swapping */ | 1057 | /* Digimic Left and right swapping */ |
1084 | static const char *twl4030_digimicswap_texts[] = { | 1058 | static const char *twl4030_digimicswap_texts[] = { |
1085 | "Not swapped", "Swapped", | 1059 | "Not swapped", "Swapped", |
1086 | }; | 1060 | }; |
1087 | 1061 | ||
1088 | static const struct soc_enum twl4030_digimicswap_enum = | 1062 | static SOC_ENUM_SINGLE_DECL(twl4030_digimicswap_enum, |
1089 | SOC_ENUM_SINGLE(TWL4030_REG_MISC_SET_1, 0, | 1063 | TWL4030_REG_MISC_SET_1, 0, |
1090 | ARRAY_SIZE(twl4030_digimicswap_texts), | 1064 | twl4030_digimicswap_texts); |
1091 | twl4030_digimicswap_texts); | ||
1092 | 1065 | ||
1093 | static const struct snd_kcontrol_new twl4030_snd_controls[] = { | 1066 | static const struct snd_kcontrol_new twl4030_snd_controls[] = { |
1094 | /* Codec operation mode control */ | 1067 | /* Codec operation mode control */ |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 0afe8bef6765..bd3a20647fdf 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -81,7 +81,7 @@ struct twl6040_data { | |||
81 | }; | 81 | }; |
82 | 82 | ||
83 | /* set of rates for each pll: low-power and high-performance */ | 83 | /* set of rates for each pll: low-power and high-performance */ |
84 | static unsigned int lp_rates[] = { | 84 | static const unsigned int lp_rates[] = { |
85 | 8000, | 85 | 8000, |
86 | 11250, | 86 | 11250, |
87 | 16000, | 87 | 16000, |
@@ -93,7 +93,7 @@ static unsigned int lp_rates[] = { | |||
93 | 96000, | 93 | 96000, |
94 | }; | 94 | }; |
95 | 95 | ||
96 | static unsigned int hp_rates[] = { | 96 | static const unsigned int hp_rates[] = { |
97 | 8000, | 97 | 8000, |
98 | 16000, | 98 | 16000, |
99 | 32000, | 99 | 32000, |
@@ -101,7 +101,7 @@ static unsigned int hp_rates[] = { | |||
101 | 96000, | 101 | 96000, |
102 | }; | 102 | }; |
103 | 103 | ||
104 | static struct snd_pcm_hw_constraint_list sysclk_constraints[] = { | 104 | static const struct snd_pcm_hw_constraint_list sysclk_constraints[] = { |
105 | { .count = ARRAY_SIZE(lp_rates), .list = lp_rates, }, | 105 | { .count = ARRAY_SIZE(lp_rates), .list = lp_rates, }, |
106 | { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, }, | 106 | { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, }, |
107 | }; | 107 | }; |
@@ -392,8 +392,10 @@ static const char *twl6040_amicr_texts[] = | |||
392 | {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"}; | 392 | {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"}; |
393 | 393 | ||
394 | static const struct soc_enum twl6040_enum[] = { | 394 | static const struct soc_enum twl6040_enum[] = { |
395 | SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 4, twl6040_amicl_texts), | 395 | SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, |
396 | SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 4, twl6040_amicr_texts), | 396 | ARRAY_SIZE(twl6040_amicl_texts), twl6040_amicl_texts), |
397 | SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, | ||
398 | ARRAY_SIZE(twl6040_amicr_texts), twl6040_amicr_texts), | ||
397 | }; | 399 | }; |
398 | 400 | ||
399 | static const char *twl6040_hs_texts[] = { | 401 | static const char *twl6040_hs_texts[] = { |
@@ -476,9 +478,8 @@ static const char *twl6040_power_mode_texts[] = { | |||
476 | "Low-Power", "High-Performance", | 478 | "Low-Power", "High-Performance", |
477 | }; | 479 | }; |
478 | 480 | ||
479 | static const struct soc_enum twl6040_power_mode_enum = | 481 | static SOC_ENUM_SINGLE_EXT_DECL(twl6040_power_mode_enum, |
480 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl6040_power_mode_texts), | 482 | twl6040_power_mode_texts); |
481 | twl6040_power_mode_texts); | ||
482 | 483 | ||
483 | static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol, | 484 | static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol, |
484 | struct snd_ctl_elem_value *ucontrol) | 485 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index c94d4c1e3dac..edf27acc1d77 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c | |||
@@ -203,8 +203,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, | |||
203 | struct snd_pcm_hw_params *params, | 203 | struct snd_pcm_hw_params *params, |
204 | struct snd_soc_dai *dai) | 204 | struct snd_soc_dai *dai) |
205 | { | 205 | { |
206 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 206 | struct snd_soc_codec *codec = dai->codec; |
207 | struct snd_soc_codec *codec = rtd->codec; | ||
208 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); | 207 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
209 | u8 hw_params; | 208 | u8 hw_params; |
210 | 209 | ||
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 726df6d43c2b..e62e70781ec2 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c | |||
@@ -108,7 +108,7 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, | |||
108 | /* the interpolator & decimator regs must only be written when the | 108 | /* the interpolator & decimator regs must only be written when the |
109 | * codec DAI is active. | 109 | * codec DAI is active. |
110 | */ | 110 | */ |
111 | if (!codec->active && (reg >= UDA1380_MVOL)) | 111 | if (!snd_soc_codec_is_active(codec) && (reg >= UDA1380_MVOL)) |
112 | return 0; | 112 | return 0; |
113 | pr_debug("uda1380: hw write %x val %x\n", reg, value); | 113 | pr_debug("uda1380: hw write %x val %x\n", reg, value); |
114 | if (codec->hw_write(codec->control_data, data, 3) == 3) { | 114 | if (codec->hw_write(codec->control_data, data, 3) == 3) { |
@@ -237,25 +237,27 @@ static const char *uda1380_os_setting[] = { | |||
237 | }; | 237 | }; |
238 | 238 | ||
239 | static const struct soc_enum uda1380_deemp_enum[] = { | 239 | static const struct soc_enum uda1380_deemp_enum[] = { |
240 | SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, 5, uda1380_deemp), | 240 | SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, ARRAY_SIZE(uda1380_deemp), |
241 | SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, 5, uda1380_deemp), | 241 | uda1380_deemp), |
242 | SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, ARRAY_SIZE(uda1380_deemp), | ||
243 | uda1380_deemp), | ||
242 | }; | 244 | }; |
243 | static const struct soc_enum uda1380_input_sel_enum = | 245 | static SOC_ENUM_SINGLE_DECL(uda1380_input_sel_enum, |
244 | SOC_ENUM_SINGLE(UDA1380_ADC, 2, 4, uda1380_input_sel); /* SEL_MIC, SEL_LNA */ | 246 | UDA1380_ADC, 2, uda1380_input_sel); /* SEL_MIC, SEL_LNA */ |
245 | static const struct soc_enum uda1380_output_sel_enum = | 247 | static SOC_ENUM_SINGLE_DECL(uda1380_output_sel_enum, |
246 | SOC_ENUM_SINGLE(UDA1380_PM, 7, 2, uda1380_output_sel); /* R02_EN_AVC */ | 248 | UDA1380_PM, 7, uda1380_output_sel); /* R02_EN_AVC */ |
247 | static const struct soc_enum uda1380_spf_enum = | 249 | static SOC_ENUM_SINGLE_DECL(uda1380_spf_enum, |
248 | SOC_ENUM_SINGLE(UDA1380_MODE, 14, 4, uda1380_spf_mode); /* M */ | 250 | UDA1380_MODE, 14, uda1380_spf_mode); /* M */ |
249 | static const struct soc_enum uda1380_capture_sel_enum = | 251 | static SOC_ENUM_SINGLE_DECL(uda1380_capture_sel_enum, |
250 | SOC_ENUM_SINGLE(UDA1380_IFACE, 6, 2, uda1380_capture_sel); /* SEL_SOURCE */ | 252 | UDA1380_IFACE, 6, uda1380_capture_sel); /* SEL_SOURCE */ |
251 | static const struct soc_enum uda1380_sel_ns_enum = | 253 | static SOC_ENUM_SINGLE_DECL(uda1380_sel_ns_enum, |
252 | SOC_ENUM_SINGLE(UDA1380_MIXER, 14, 2, uda1380_sel_ns); /* SEL_NS */ | 254 | UDA1380_MIXER, 14, uda1380_sel_ns); /* SEL_NS */ |
253 | static const struct soc_enum uda1380_mix_enum = | 255 | static SOC_ENUM_SINGLE_DECL(uda1380_mix_enum, |
254 | SOC_ENUM_SINGLE(UDA1380_MIXER, 12, 4, uda1380_mix_control); /* MIX, MIX_POS */ | 256 | UDA1380_MIXER, 12, uda1380_mix_control); /* MIX, MIX_POS */ |
255 | static const struct soc_enum uda1380_sdet_enum = | 257 | static SOC_ENUM_SINGLE_DECL(uda1380_sdet_enum, |
256 | SOC_ENUM_SINGLE(UDA1380_MIXER, 4, 4, uda1380_sdet_setting); /* SD_VALUE */ | 258 | UDA1380_MIXER, 4, uda1380_sdet_setting); /* SD_VALUE */ |
257 | static const struct soc_enum uda1380_os_enum = | 259 | static SOC_ENUM_SINGLE_DECL(uda1380_os_enum, |
258 | SOC_ENUM_SINGLE(UDA1380_MIXER, 0, 3, uda1380_os_setting); /* OS */ | 260 | UDA1380_MIXER, 0, uda1380_os_setting); /* OS */ |
259 | 261 | ||
260 | /* | 262 | /* |
261 | * from -48 dB in 1.5 dB steps (mute instead of -49.5 dB) | 263 | * from -48 dB in 1.5 dB steps (mute instead of -49.5 dB) |
@@ -564,8 +566,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, | |||
564 | static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, | 566 | static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, |
565 | struct snd_soc_dai *dai) | 567 | struct snd_soc_dai *dai) |
566 | { | 568 | { |
567 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 569 | struct snd_soc_codec *codec = dai->codec; |
568 | struct snd_soc_codec *codec = rtd->codec; | ||
569 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); | 570 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); |
570 | 571 | ||
571 | /* shut down WSPLL power if running from this clock */ | 572 | /* shut down WSPLL power if running from this clock */ |
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index b7ab2ef567c8..6be5f80b65f1 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c | |||
@@ -197,7 +197,7 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol, | |||
197 | return 0; | 197 | return 0; |
198 | 198 | ||
199 | /* Do not allow changes while stream is running */ | 199 | /* Do not allow changes while stream is running */ |
200 | if (codec->active) | 200 | if (snd_soc_codec_is_active(codec)) |
201 | return -EPERM; | 201 | return -EPERM; |
202 | 202 | ||
203 | if (ucontrol->value.integer.value[0] < 0 || | 203 | if (ucontrol->value.integer.value[0] < 0 || |
@@ -209,8 +209,7 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol, | |||
209 | return 1; | 209 | return 1; |
210 | } | 210 | } |
211 | 211 | ||
212 | static const struct soc_enum wl1273_enum = | 212 | static SOC_ENUM_SINGLE_EXT_DECL(wl1273_enum, wl1273_audio_route); |
213 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_route), wl1273_audio_route); | ||
214 | 213 | ||
215 | static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol, | 214 | static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol, |
216 | struct snd_ctl_elem_value *ucontrol) | 215 | struct snd_ctl_elem_value *ucontrol) |
@@ -247,9 +246,7 @@ static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol, | |||
247 | 246 | ||
248 | static const char * const wl1273_audio_strings[] = { "Digital", "Analog" }; | 247 | static const char * const wl1273_audio_strings[] = { "Digital", "Analog" }; |
249 | 248 | ||
250 | static const struct soc_enum wl1273_audio_enum = | 249 | static SOC_ENUM_SINGLE_EXT_DECL(wl1273_audio_enum, wl1273_audio_strings); |
251 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_strings), | ||
252 | wl1273_audio_strings); | ||
253 | 250 | ||
254 | static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol, | 251 | static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol, |
255 | struct snd_ctl_elem_value *ucontrol) | 252 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 8ae50274ea8f..83a2c872925c 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -786,8 +786,6 @@ static int wm2000_probe(struct snd_soc_codec *codec) | |||
786 | { | 786 | { |
787 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); | 787 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); |
788 | 788 | ||
789 | snd_soc_codec_set_cache_io(codec, 16, 8, SND_SOC_REGMAP); | ||
790 | |||
791 | /* This will trigger a transition to standby mode by default */ | 789 | /* This will trigger a transition to standby mode by default */ |
792 | wm2000_anc_set_mode(wm2000); | 790 | wm2000_anc_set_mode(wm2000); |
793 | 791 | ||
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 57ba315d0c84..2e721e06671b 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c | |||
@@ -1113,11 +1113,10 @@ static const char *wm2200_rxanc_input_sel_texts[] = { | |||
1113 | "None", "IN1", "IN2", "IN3", | 1113 | "None", "IN1", "IN2", "IN3", |
1114 | }; | 1114 | }; |
1115 | 1115 | ||
1116 | static const struct soc_enum wm2200_rxanc_input_sel = | 1116 | static SOC_ENUM_SINGLE_DECL(wm2200_rxanc_input_sel, |
1117 | SOC_ENUM_SINGLE(WM2200_RXANC_SRC, | 1117 | WM2200_RXANC_SRC, |
1118 | WM2200_IN_RXANC_SEL_SHIFT, | 1118 | WM2200_IN_RXANC_SEL_SHIFT, |
1119 | ARRAY_SIZE(wm2200_rxanc_input_sel_texts), | 1119 | wm2200_rxanc_input_sel_texts); |
1120 | wm2200_rxanc_input_sel_texts); | ||
1121 | 1120 | ||
1122 | static const struct snd_kcontrol_new wm2200_snd_controls[] = { | 1121 | static const struct snd_kcontrol_new wm2200_snd_controls[] = { |
1123 | SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL, | 1122 | SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL, |
@@ -1288,11 +1287,10 @@ static const char *wm2200_aec_loopback_texts[] = { | |||
1288 | "OUT1L", "OUT1R", "OUT2L", "OUT2R", | 1287 | "OUT1L", "OUT1R", "OUT2L", "OUT2R", |
1289 | }; | 1288 | }; |
1290 | 1289 | ||
1291 | static const struct soc_enum wm2200_aec_loopback = | 1290 | static SOC_ENUM_SINGLE_DECL(wm2200_aec_loopback, |
1292 | SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1, | 1291 | WM2200_DAC_AEC_CONTROL_1, |
1293 | WM2200_AEC_LOOPBACK_SRC_SHIFT, | 1292 | WM2200_AEC_LOOPBACK_SRC_SHIFT, |
1294 | ARRAY_SIZE(wm2200_aec_loopback_texts), | 1293 | wm2200_aec_loopback_texts); |
1295 | wm2200_aec_loopback_texts); | ||
1296 | 1294 | ||
1297 | static const struct snd_kcontrol_new wm2200_aec_loopback_mux = | 1295 | static const struct snd_kcontrol_new wm2200_aec_loopback_mux = |
1298 | SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback); | 1296 | SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback); |
@@ -1556,15 +1554,8 @@ static int wm2200_probe(struct snd_soc_codec *codec) | |||
1556 | int ret; | 1554 | int ret; |
1557 | 1555 | ||
1558 | wm2200->codec = codec; | 1556 | wm2200->codec = codec; |
1559 | codec->control_data = wm2200->regmap; | ||
1560 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | 1557 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; |
1561 | 1558 | ||
1562 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | ||
1563 | if (ret != 0) { | ||
1564 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1565 | return ret; | ||
1566 | } | ||
1567 | |||
1568 | ret = snd_soc_add_codec_controls(codec, wm_adsp1_fw_controls, 2); | 1559 | ret = snd_soc_add_codec_controls(codec, wm_adsp1_fw_controls, 2); |
1569 | if (ret != 0) | 1560 | if (ret != 0) |
1570 | return ret; | 1561 | return ret; |
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 4e3e31aaf509..eca983fad891 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c | |||
@@ -506,21 +506,21 @@ static const char *wm5100_lhpf_mode_text[] = { | |||
506 | "Low-pass", "High-pass" | 506 | "Low-pass", "High-pass" |
507 | }; | 507 | }; |
508 | 508 | ||
509 | static const struct soc_enum wm5100_lhpf1_mode = | 509 | static SOC_ENUM_SINGLE_DECL(wm5100_lhpf1_mode, |
510 | SOC_ENUM_SINGLE(WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, 2, | 510 | WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, |
511 | wm5100_lhpf_mode_text); | 511 | wm5100_lhpf_mode_text); |
512 | 512 | ||
513 | static const struct soc_enum wm5100_lhpf2_mode = | 513 | static SOC_ENUM_SINGLE_DECL(wm5100_lhpf2_mode, |
514 | SOC_ENUM_SINGLE(WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, 2, | 514 | WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, |
515 | wm5100_lhpf_mode_text); | 515 | wm5100_lhpf_mode_text); |
516 | 516 | ||
517 | static const struct soc_enum wm5100_lhpf3_mode = | 517 | static SOC_ENUM_SINGLE_DECL(wm5100_lhpf3_mode, |
518 | SOC_ENUM_SINGLE(WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, 2, | 518 | WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, |
519 | wm5100_lhpf_mode_text); | 519 | wm5100_lhpf_mode_text); |
520 | 520 | ||
521 | static const struct soc_enum wm5100_lhpf4_mode = | 521 | static SOC_ENUM_SINGLE_DECL(wm5100_lhpf4_mode, |
522 | SOC_ENUM_SINGLE(WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, 2, | 522 | WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, |
523 | wm5100_lhpf_mode_text); | 523 | wm5100_lhpf_mode_text); |
524 | 524 | ||
525 | static const struct snd_kcontrol_new wm5100_snd_controls[] = { | 525 | static const struct snd_kcontrol_new wm5100_snd_controls[] = { |
526 | SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL, | 526 | SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL, |
@@ -2100,6 +2100,7 @@ static void wm5100_micd_irq(struct wm5100_priv *wm5100) | |||
2100 | int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | 2100 | int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) |
2101 | { | 2101 | { |
2102 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | 2102 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); |
2103 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
2103 | 2104 | ||
2104 | if (jack) { | 2105 | if (jack) { |
2105 | wm5100->jack = jack; | 2106 | wm5100->jack = jack; |
@@ -2117,9 +2118,14 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | |||
2117 | WM5100_ACCDET_RATE_MASK); | 2118 | WM5100_ACCDET_RATE_MASK); |
2118 | 2119 | ||
2119 | /* We need the charge pump to power MICBIAS */ | 2120 | /* We need the charge pump to power MICBIAS */ |
2120 | snd_soc_dapm_force_enable_pin(&codec->dapm, "CP2"); | 2121 | snd_soc_dapm_mutex_lock(dapm); |
2121 | snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); | 2122 | |
2122 | snd_soc_dapm_sync(&codec->dapm); | 2123 | snd_soc_dapm_force_enable_pin_unlocked(dapm, "CP2"); |
2124 | snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK"); | ||
2125 | |||
2126 | snd_soc_dapm_sync_unlocked(dapm); | ||
2127 | |||
2128 | snd_soc_dapm_mutex_unlock(dapm); | ||
2123 | 2129 | ||
2124 | /* We start off just enabling microphone detection - even a | 2130 | /* We start off just enabling microphone detection - even a |
2125 | * plain headphone will trigger detection. | 2131 | * plain headphone will trigger detection. |
@@ -2337,13 +2343,6 @@ static int wm5100_probe(struct snd_soc_codec *codec) | |||
2337 | int ret, i; | 2343 | int ret, i; |
2338 | 2344 | ||
2339 | wm5100->codec = codec; | 2345 | wm5100->codec = codec; |
2340 | codec->control_data = wm5100->regmap; | ||
2341 | |||
2342 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | ||
2343 | if (ret != 0) { | ||
2344 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
2345 | return ret; | ||
2346 | } | ||
2347 | 2346 | ||
2348 | for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++) | 2347 | for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++) |
2349 | snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU, | 2348 | snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU, |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index ce9c8e14d4bd..dcf1d12cfef8 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -582,7 +582,7 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
582 | { | 582 | { |
583 | struct snd_soc_codec *codec = w->codec; | 583 | struct snd_soc_codec *codec = w->codec; |
584 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 584 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
585 | struct regmap *regmap = codec->control_data; | 585 | struct regmap *regmap = arizona->regmap; |
586 | const struct reg_default *patch = NULL; | 586 | const struct reg_default *patch = NULL; |
587 | int i, patch_size; | 587 | int i, patch_size; |
588 | 588 | ||
@@ -622,13 +622,16 @@ static const unsigned int wm5102_osr_val[] = { | |||
622 | 622 | ||
623 | static const struct soc_enum wm5102_hpout_osr[] = { | 623 | static const struct soc_enum wm5102_hpout_osr[] = { |
624 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, | 624 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, |
625 | ARIZONA_OUT1_OSR_SHIFT, 0x7, 3, | 625 | ARIZONA_OUT1_OSR_SHIFT, 0x7, |
626 | ARRAY_SIZE(wm5102_osr_text), | ||
626 | wm5102_osr_text, wm5102_osr_val), | 627 | wm5102_osr_text, wm5102_osr_val), |
627 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L, | 628 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L, |
628 | ARIZONA_OUT2_OSR_SHIFT, 0x7, 3, | 629 | ARIZONA_OUT2_OSR_SHIFT, 0x7, |
630 | ARRAY_SIZE(wm5102_osr_text), | ||
629 | wm5102_osr_text, wm5102_osr_val), | 631 | wm5102_osr_text, wm5102_osr_val), |
630 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, | 632 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, |
631 | ARIZONA_OUT3_OSR_SHIFT, 0x7, 3, | 633 | ARIZONA_OUT3_OSR_SHIFT, 0x7, |
634 | ARRAY_SIZE(wm5102_osr_text), | ||
632 | wm5102_osr_text, wm5102_osr_val), | 635 | wm5102_osr_text, wm5102_osr_val), |
633 | }; | 636 | }; |
634 | 637 | ||
@@ -685,15 +688,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | |||
685 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | 688 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), |
686 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | 689 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), |
687 | 690 | ||
688 | SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21, | 691 | SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), |
689 | ARIZONA_EQ1_ENA_MASK), | 692 | SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), |
690 | SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21, | ||
691 | ARIZONA_EQ2_ENA_MASK), | ||
692 | SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21, | ||
693 | ARIZONA_EQ3_ENA_MASK), | ||
694 | SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21, | ||
695 | ARIZONA_EQ4_ENA_MASK), | ||
696 | |||
697 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | 693 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, |
698 | 24, 0, eq_tlv), | 694 | 24, 0, eq_tlv), |
699 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | 695 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, |
@@ -705,6 +701,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, | |||
705 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, | 701 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, |
706 | 24, 0, eq_tlv), | 702 | 24, 0, eq_tlv), |
707 | 703 | ||
704 | SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), | ||
705 | SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), | ||
708 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, | 706 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, |
709 | 24, 0, eq_tlv), | 707 | 24, 0, eq_tlv), |
710 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, | 708 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, |
@@ -716,6 +714,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, | |||
716 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, | 714 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, |
717 | 24, 0, eq_tlv), | 715 | 24, 0, eq_tlv), |
718 | 716 | ||
717 | SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), | ||
718 | SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), | ||
719 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, | 719 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, |
720 | 24, 0, eq_tlv), | 720 | 24, 0, eq_tlv), |
721 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, | 721 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, |
@@ -727,6 +727,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, | |||
727 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, | 727 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, |
728 | 24, 0, eq_tlv), | 728 | 24, 0, eq_tlv), |
729 | 729 | ||
730 | SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), | ||
731 | SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), | ||
730 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, | 732 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, |
731 | 24, 0, eq_tlv), | 733 | 24, 0, eq_tlv), |
732 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, | 734 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, |
@@ -1758,9 +1760,7 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) | |||
1758 | struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); | 1760 | struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); |
1759 | int ret; | 1761 | int ret; |
1760 | 1762 | ||
1761 | codec->control_data = priv->core.arizona->regmap; | 1763 | ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap); |
1762 | |||
1763 | ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); | ||
1764 | if (ret != 0) | 1764 | if (ret != 0) |
1765 | return ret; | 1765 | return ret; |
1766 | 1766 | ||
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 2c3c962d9a85..df5a38dd8328 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -136,7 +136,7 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
136 | { | 136 | { |
137 | struct snd_soc_codec *codec = w->codec; | 137 | struct snd_soc_codec *codec = w->codec; |
138 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 138 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
139 | struct regmap *regmap = codec->control_data; | 139 | struct regmap *regmap = arizona->regmap; |
140 | const struct reg_default *patch = NULL; | 140 | const struct reg_default *patch = NULL; |
141 | int i, patch_size; | 141 | int i, patch_size; |
142 | 142 | ||
@@ -247,15 +247,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | |||
247 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | 247 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), |
248 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | 248 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), |
249 | 249 | ||
250 | SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21, | 250 | SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), |
251 | ARIZONA_EQ1_ENA_MASK), | 251 | SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), |
252 | SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21, | ||
253 | ARIZONA_EQ2_ENA_MASK), | ||
254 | SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21, | ||
255 | ARIZONA_EQ3_ENA_MASK), | ||
256 | SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21, | ||
257 | ARIZONA_EQ4_ENA_MASK), | ||
258 | |||
259 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | 252 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, |
260 | 24, 0, eq_tlv), | 253 | 24, 0, eq_tlv), |
261 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | 254 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, |
@@ -267,6 +260,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, | |||
267 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, | 260 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, |
268 | 24, 0, eq_tlv), | 261 | 24, 0, eq_tlv), |
269 | 262 | ||
263 | SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), | ||
264 | SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), | ||
270 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, | 265 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, |
271 | 24, 0, eq_tlv), | 266 | 24, 0, eq_tlv), |
272 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, | 267 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, |
@@ -278,6 +273,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, | |||
278 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, | 273 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, |
279 | 24, 0, eq_tlv), | 274 | 24, 0, eq_tlv), |
280 | 275 | ||
276 | SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), | ||
277 | SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), | ||
281 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, | 278 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, |
282 | 24, 0, eq_tlv), | 279 | 24, 0, eq_tlv), |
283 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, | 280 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, |
@@ -289,6 +286,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, | |||
289 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, | 286 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, |
290 | 24, 0, eq_tlv), | 287 | 24, 0, eq_tlv), |
291 | 288 | ||
289 | SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), | ||
290 | SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), | ||
292 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, | 291 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, |
293 | 24, 0, eq_tlv), | 292 | 24, 0, eq_tlv), |
294 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, | 293 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, |
@@ -1588,10 +1587,9 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) | |||
1588 | struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); | 1587 | struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); |
1589 | int ret; | 1588 | int ret; |
1590 | 1589 | ||
1591 | codec->control_data = priv->core.arizona->regmap; | ||
1592 | priv->core.arizona->dapm = &codec->dapm; | 1590 | priv->core.arizona->dapm = &codec->dapm; |
1593 | 1591 | ||
1594 | ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); | 1592 | ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap); |
1595 | if (ret != 0) | 1593 | if (ret != 0) |
1596 | return ret; | 1594 | return ret; |
1597 | 1595 | ||
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index a183dcf3d5c1..757256bf7672 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -1505,9 +1505,7 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) | |||
1505 | if (ret != 0) | 1505 | if (ret != 0) |
1506 | return ret; | 1506 | return ret; |
1507 | 1507 | ||
1508 | codec->control_data = wm8350->regmap; | 1508 | snd_soc_codec_set_cache_io(codec, wm8350->regmap); |
1509 | |||
1510 | snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
1511 | 1509 | ||
1512 | /* Put the codec into reset if it wasn't already */ | 1510 | /* Put the codec into reset if it wasn't already */ |
1513 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1511 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 48dc7d2fee36..146564feaea0 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -117,19 +117,23 @@ static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, | |||
117 | static const char *wm8400_digital_sidetone[] = | 117 | static const char *wm8400_digital_sidetone[] = |
118 | {"None", "Left ADC", "Right ADC", "Reserved"}; | 118 | {"None", "Left ADC", "Right ADC", "Reserved"}; |
119 | 119 | ||
120 | static const struct soc_enum wm8400_left_digital_sidetone_enum = | 120 | static SOC_ENUM_SINGLE_DECL(wm8400_left_digital_sidetone_enum, |
121 | SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE, | 121 | WM8400_DIGITAL_SIDE_TONE, |
122 | WM8400_ADC_TO_DACL_SHIFT, 2, wm8400_digital_sidetone); | 122 | WM8400_ADC_TO_DACL_SHIFT, |
123 | wm8400_digital_sidetone); | ||
123 | 124 | ||
124 | static const struct soc_enum wm8400_right_digital_sidetone_enum = | 125 | static SOC_ENUM_SINGLE_DECL(wm8400_right_digital_sidetone_enum, |
125 | SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE, | 126 | WM8400_DIGITAL_SIDE_TONE, |
126 | WM8400_ADC_TO_DACR_SHIFT, 2, wm8400_digital_sidetone); | 127 | WM8400_ADC_TO_DACR_SHIFT, |
128 | wm8400_digital_sidetone); | ||
127 | 129 | ||
128 | static const char *wm8400_adcmode[] = | 130 | static const char *wm8400_adcmode[] = |
129 | {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; | 131 | {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; |
130 | 132 | ||
131 | static const struct soc_enum wm8400_right_adcmode_enum = | 133 | static SOC_ENUM_SINGLE_DECL(wm8400_right_adcmode_enum, |
132 | SOC_ENUM_SINGLE(WM8400_ADC_CTRL, WM8400_ADC_HPF_CUT_SHIFT, 3, wm8400_adcmode); | 134 | WM8400_ADC_CTRL, |
135 | WM8400_ADC_HPF_CUT_SHIFT, | ||
136 | wm8400_adcmode); | ||
133 | 137 | ||
134 | static const struct snd_kcontrol_new wm8400_snd_controls[] = { | 138 | static const struct snd_kcontrol_new wm8400_snd_controls[] = { |
135 | /* INMIXL */ | 139 | /* INMIXL */ |
@@ -422,9 +426,10 @@ SOC_DAPM_SINGLE("RINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT, | |||
422 | static const char *wm8400_ainlmux[] = | 426 | static const char *wm8400_ainlmux[] = |
423 | {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; | 427 | {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; |
424 | 428 | ||
425 | static const struct soc_enum wm8400_ainlmux_enum = | 429 | static SOC_ENUM_SINGLE_DECL(wm8400_ainlmux_enum, |
426 | SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINLMODE_SHIFT, | 430 | WM8400_INPUT_MIXER1, |
427 | ARRAY_SIZE(wm8400_ainlmux), wm8400_ainlmux); | 431 | WM8400_AINLMODE_SHIFT, |
432 | wm8400_ainlmux); | ||
428 | 433 | ||
429 | static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls = | 434 | static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls = |
430 | SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum); | 435 | SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum); |
@@ -435,9 +440,10 @@ SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum); | |||
435 | static const char *wm8400_ainrmux[] = | 440 | static const char *wm8400_ainrmux[] = |
436 | {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; | 441 | {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; |
437 | 442 | ||
438 | static const struct soc_enum wm8400_ainrmux_enum = | 443 | static SOC_ENUM_SINGLE_DECL(wm8400_ainrmux_enum, |
439 | SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINRMODE_SHIFT, | 444 | WM8400_INPUT_MIXER1, |
440 | ARRAY_SIZE(wm8400_ainrmux), wm8400_ainrmux); | 445 | WM8400_AINRMODE_SHIFT, |
446 | wm8400_ainrmux); | ||
441 | 447 | ||
442 | static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls = | 448 | static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls = |
443 | SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum); | 449 | SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum); |
@@ -1310,10 +1316,9 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec) | |||
1310 | 1316 | ||
1311 | snd_soc_codec_set_drvdata(codec, priv); | 1317 | snd_soc_codec_set_drvdata(codec, priv); |
1312 | priv->wm8400 = wm8400; | 1318 | priv->wm8400 = wm8400; |
1313 | codec->control_data = wm8400->regmap; | ||
1314 | priv->codec = codec; | 1319 | priv->codec = codec; |
1315 | 1320 | ||
1316 | snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | 1321 | snd_soc_codec_set_cache_io(codec, wm8400->regmap); |
1317 | 1322 | ||
1318 | ret = devm_regulator_bulk_get(wm8400->dev, | 1323 | ret = devm_regulator_bulk_get(wm8400->dev, |
1319 | ARRAY_SIZE(power), &power[0]); | 1324 | ARRAY_SIZE(power), &power[0]); |
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 7df7d4572755..1c1e328feeb8 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -589,20 +589,12 @@ static int wm8510_resume(struct snd_soc_codec *codec) | |||
589 | 589 | ||
590 | static int wm8510_probe(struct snd_soc_codec *codec) | 590 | static int wm8510_probe(struct snd_soc_codec *codec) |
591 | { | 591 | { |
592 | int ret; | ||
593 | |||
594 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
595 | if (ret < 0) { | ||
596 | printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); | ||
597 | return ret; | ||
598 | } | ||
599 | |||
600 | wm8510_reset(codec); | 592 | wm8510_reset(codec); |
601 | 593 | ||
602 | /* power on device */ | 594 | /* power on device */ |
603 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 595 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
604 | 596 | ||
605 | return ret; | 597 | return 0; |
606 | } | 598 | } |
607 | 599 | ||
608 | /* power down chip */ | 600 | /* power down chip */ |
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 74d106dc7667..601ee8178af1 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -75,8 +75,8 @@ static const char *wm8523_zd_count_text[] = { | |||
75 | "2048", | 75 | "2048", |
76 | }; | 76 | }; |
77 | 77 | ||
78 | static const struct soc_enum wm8523_zc_count = | 78 | static SOC_ENUM_SINGLE_DECL(wm8523_zc_count, WM8523_ZERO_DETECT, 0, |
79 | SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text); | 79 | wm8523_zd_count_text); |
80 | 80 | ||
81 | static const struct snd_kcontrol_new wm8523_controls[] = { | 81 | static const struct snd_kcontrol_new wm8523_controls[] = { |
82 | SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, | 82 | SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, |
@@ -392,18 +392,11 @@ static int wm8523_resume(struct snd_soc_codec *codec) | |||
392 | static int wm8523_probe(struct snd_soc_codec *codec) | 392 | static int wm8523_probe(struct snd_soc_codec *codec) |
393 | { | 393 | { |
394 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); | 394 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
395 | int ret; | ||
396 | 395 | ||
397 | wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; | 396 | wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; |
398 | wm8523->rate_constraint.count = | 397 | wm8523->rate_constraint.count = |
399 | ARRAY_SIZE(wm8523->rate_constraint_list); | 398 | ARRAY_SIZE(wm8523->rate_constraint_list); |
400 | 399 | ||
401 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
402 | if (ret != 0) { | ||
403 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
404 | return ret; | ||
405 | } | ||
406 | |||
407 | /* Change some default settings - latch VU and enable ZC */ | 400 | /* Change some default settings - latch VU and enable ZC */ |
408 | snd_soc_update_bits(codec, WM8523_DAC_GAINR, | 401 | snd_soc_update_bits(codec, WM8523_DAC_GAINR, |
409 | WM8523_DACR_VU, WM8523_DACR_VU); | 402 | WM8523_DACR_VU, WM8523_DACR_VU); |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 318989acbbe5..af7ed8b5d4e1 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -504,8 +504,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | |||
504 | struct snd_pcm_hw_params *params, | 504 | struct snd_pcm_hw_params *params, |
505 | struct snd_soc_dai *dai) | 505 | struct snd_soc_dai *dai) |
506 | { | 506 | { |
507 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 507 | struct snd_soc_codec *codec = dai->codec; |
508 | struct snd_soc_codec *codec = rtd->codec; | ||
509 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); | 508 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
510 | u16 paifa = 0; | 509 | u16 paifa = 0; |
511 | u16 paifb = 0; | 510 | u16 paifb = 0; |
@@ -869,12 +868,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) | |||
869 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); | 868 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
870 | int ret = 0; | 869 | int ret = 0; |
871 | 870 | ||
872 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
873 | if (ret < 0) { | ||
874 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
875 | return ret; | ||
876 | } | ||
877 | |||
878 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), | 871 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), |
879 | wm8580->supplies); | 872 | wm8580->supplies); |
880 | if (ret != 0) { | 873 | if (ret != 0) { |
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index d99f948c513c..b0fbcb377baf 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -201,7 +201,7 @@ static void wm8711_shutdown(struct snd_pcm_substream *substream, | |||
201 | struct snd_soc_codec *codec = dai->codec; | 201 | struct snd_soc_codec *codec = dai->codec; |
202 | 202 | ||
203 | /* deactivate */ | 203 | /* deactivate */ |
204 | if (!codec->active) { | 204 | if (!snd_soc_codec_is_active(codec)) { |
205 | udelay(50); | 205 | udelay(50); |
206 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); | 206 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); |
207 | } | 207 | } |
@@ -367,12 +367,6 @@ static int wm8711_probe(struct snd_soc_codec *codec) | |||
367 | { | 367 | { |
368 | int ret; | 368 | int ret; |
369 | 369 | ||
370 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
371 | if (ret < 0) { | ||
372 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
373 | return ret; | ||
374 | } | ||
375 | |||
376 | ret = wm8711_reset(codec); | 370 | ret = wm8711_reset(codec); |
377 | if (ret < 0) { | 371 | if (ret < 0) { |
378 | dev_err(codec->dev, "Failed to issue reset\n"); | 372 | dev_err(codec->dev, "Failed to issue reset\n"); |
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index cd89033e84c0..bac7fc28fe71 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -228,19 +228,10 @@ static int wm8728_resume(struct snd_soc_codec *codec) | |||
228 | 228 | ||
229 | static int wm8728_probe(struct snd_soc_codec *codec) | 229 | static int wm8728_probe(struct snd_soc_codec *codec) |
230 | { | 230 | { |
231 | int ret; | ||
232 | |||
233 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
234 | if (ret < 0) { | ||
235 | printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", | ||
236 | ret); | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | /* power on device */ | 231 | /* power on device */ |
241 | wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 232 | wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
242 | 233 | ||
243 | return ret; | 234 | return 0; |
244 | } | 235 | } |
245 | 236 | ||
246 | static int wm8728_remove(struct snd_soc_codec *codec) | 237 | static int wm8728_remove(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 029720366ff8..d74f43975b90 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -83,8 +83,8 @@ static bool wm8731_writeable(struct device *dev, unsigned int reg) | |||
83 | 83 | ||
84 | static const char *wm8731_input_select[] = {"Line In", "Mic"}; | 84 | static const char *wm8731_input_select[] = {"Line In", "Mic"}; |
85 | 85 | ||
86 | static const struct soc_enum wm8731_insel_enum = | 86 | static SOC_ENUM_SINGLE_DECL(wm8731_insel_enum, |
87 | SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select); | 87 | WM8731_APANA, 2, wm8731_input_select); |
88 | 88 | ||
89 | static int wm8731_deemph[] = { 0, 32000, 44100, 48000 }; | 89 | static int wm8731_deemph[] = { 0, 32000, 44100, 48000 }; |
90 | 90 | ||
@@ -583,13 +583,6 @@ static int wm8731_probe(struct snd_soc_codec *codec) | |||
583 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | 583 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); |
584 | int ret = 0, i; | 584 | int ret = 0, i; |
585 | 585 | ||
586 | codec->control_data = wm8731->regmap; | ||
587 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
588 | if (ret < 0) { | ||
589 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
590 | return ret; | ||
591 | } | ||
592 | |||
593 | for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) | 586 | for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) |
594 | wm8731->supplies[i].supply = wm8731_supply_names[i]; | 587 | wm8731->supplies[i].supply = wm8731_supply_names[i]; |
595 | 588 | ||
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 2f167a8ca01b..b27f26cdc049 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c | |||
@@ -99,29 +99,29 @@ static const char *micbias_enum_text[] = { | |||
99 | "100%", | 99 | "100%", |
100 | }; | 100 | }; |
101 | 101 | ||
102 | static const struct soc_enum micbias_enum = | 102 | static SOC_ENUM_SINGLE_DECL(micbias_enum, |
103 | SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 0, 4, micbias_enum_text); | 103 | WM8737_MIC_PREAMP_CONTROL, 0, micbias_enum_text); |
104 | 104 | ||
105 | static const char *low_cutoff_text[] = { | 105 | static const char *low_cutoff_text[] = { |
106 | "Low", "High" | 106 | "Low", "High" |
107 | }; | 107 | }; |
108 | 108 | ||
109 | static const struct soc_enum low_3d = | 109 | static SOC_ENUM_SINGLE_DECL(low_3d, |
110 | SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 6, 2, low_cutoff_text); | 110 | WM8737_3D_ENHANCE, 6, low_cutoff_text); |
111 | 111 | ||
112 | static const char *high_cutoff_text[] = { | 112 | static const char *high_cutoff_text[] = { |
113 | "High", "Low" | 113 | "High", "Low" |
114 | }; | 114 | }; |
115 | 115 | ||
116 | static const struct soc_enum high_3d = | 116 | static SOC_ENUM_SINGLE_DECL(high_3d, |
117 | SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 5, 2, high_cutoff_text); | 117 | WM8737_3D_ENHANCE, 5, high_cutoff_text); |
118 | 118 | ||
119 | static const char *alc_fn_text[] = { | 119 | static const char *alc_fn_text[] = { |
120 | "Disabled", "Right", "Left", "Stereo" | 120 | "Disabled", "Right", "Left", "Stereo" |
121 | }; | 121 | }; |
122 | 122 | ||
123 | static const struct soc_enum alc_fn = | 123 | static SOC_ENUM_SINGLE_DECL(alc_fn, |
124 | SOC_ENUM_SINGLE(WM8737_ALC1, 7, 4, alc_fn_text); | 124 | WM8737_ALC1, 7, alc_fn_text); |
125 | 125 | ||
126 | static const char *alc_hold_text[] = { | 126 | static const char *alc_hold_text[] = { |
127 | "0", "2.67ms", "5.33ms", "10.66ms", "21.32ms", "42.64ms", "85.28ms", | 127 | "0", "2.67ms", "5.33ms", "10.66ms", "21.32ms", "42.64ms", "85.28ms", |
@@ -129,24 +129,24 @@ static const char *alc_hold_text[] = { | |||
129 | "10.916s", "21.832s", "43.691s" | 129 | "10.916s", "21.832s", "43.691s" |
130 | }; | 130 | }; |
131 | 131 | ||
132 | static const struct soc_enum alc_hold = | 132 | static SOC_ENUM_SINGLE_DECL(alc_hold, |
133 | SOC_ENUM_SINGLE(WM8737_ALC2, 0, 16, alc_hold_text); | 133 | WM8737_ALC2, 0, alc_hold_text); |
134 | 134 | ||
135 | static const char *alc_atk_text[] = { | 135 | static const char *alc_atk_text[] = { |
136 | "8.4ms", "16.8ms", "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", | 136 | "8.4ms", "16.8ms", "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", |
137 | "1.075s", "2.15s", "4.3s", "8.6s" | 137 | "1.075s", "2.15s", "4.3s", "8.6s" |
138 | }; | 138 | }; |
139 | 139 | ||
140 | static const struct soc_enum alc_atk = | 140 | static SOC_ENUM_SINGLE_DECL(alc_atk, |
141 | SOC_ENUM_SINGLE(WM8737_ALC3, 0, 11, alc_atk_text); | 141 | WM8737_ALC3, 0, alc_atk_text); |
142 | 142 | ||
143 | static const char *alc_dcy_text[] = { | 143 | static const char *alc_dcy_text[] = { |
144 | "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s", | 144 | "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s", |
145 | "4.3s", "8.6s", "17.2s", "34.41s" | 145 | "4.3s", "8.6s", "17.2s", "34.41s" |
146 | }; | 146 | }; |
147 | 147 | ||
148 | static const struct soc_enum alc_dcy = | 148 | static SOC_ENUM_SINGLE_DECL(alc_dcy, |
149 | SOC_ENUM_SINGLE(WM8737_ALC3, 4, 11, alc_dcy_text); | 149 | WM8737_ALC3, 4, alc_dcy_text); |
150 | 150 | ||
151 | static const struct snd_kcontrol_new wm8737_snd_controls[] = { | 151 | static const struct snd_kcontrol_new wm8737_snd_controls[] = { |
152 | SOC_DOUBLE_R_TLV("Mic Boost Volume", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R, | 152 | SOC_DOUBLE_R_TLV("Mic Boost Volume", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R, |
@@ -191,8 +191,8 @@ static const char *linsel_text[] = { | |||
191 | "LINPUT1", "LINPUT2", "LINPUT3", "LINPUT1 DC", | 191 | "LINPUT1", "LINPUT2", "LINPUT3", "LINPUT1 DC", |
192 | }; | 192 | }; |
193 | 193 | ||
194 | static const struct soc_enum linsel_enum = | 194 | static SOC_ENUM_SINGLE_DECL(linsel_enum, |
195 | SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_L, 7, 4, linsel_text); | 195 | WM8737_AUDIO_PATH_L, 7, linsel_text); |
196 | 196 | ||
197 | static const struct snd_kcontrol_new linsel_mux = | 197 | static const struct snd_kcontrol_new linsel_mux = |
198 | SOC_DAPM_ENUM("LINSEL", linsel_enum); | 198 | SOC_DAPM_ENUM("LINSEL", linsel_enum); |
@@ -202,8 +202,8 @@ static const char *rinsel_text[] = { | |||
202 | "RINPUT1", "RINPUT2", "RINPUT3", "RINPUT1 DC", | 202 | "RINPUT1", "RINPUT2", "RINPUT3", "RINPUT1 DC", |
203 | }; | 203 | }; |
204 | 204 | ||
205 | static const struct soc_enum rinsel_enum = | 205 | static SOC_ENUM_SINGLE_DECL(rinsel_enum, |
206 | SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_R, 7, 4, rinsel_text); | 206 | WM8737_AUDIO_PATH_R, 7, rinsel_text); |
207 | 207 | ||
208 | static const struct snd_kcontrol_new rinsel_mux = | 208 | static const struct snd_kcontrol_new rinsel_mux = |
209 | SOC_DAPM_ENUM("RINSEL", rinsel_enum); | 209 | SOC_DAPM_ENUM("RINSEL", rinsel_enum); |
@@ -212,15 +212,15 @@ static const char *bypass_text[] = { | |||
212 | "Direct", "Preamp" | 212 | "Direct", "Preamp" |
213 | }; | 213 | }; |
214 | 214 | ||
215 | static const struct soc_enum lbypass_enum = | 215 | static SOC_ENUM_SINGLE_DECL(lbypass_enum, |
216 | SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 2, 2, bypass_text); | 216 | WM8737_MIC_PREAMP_CONTROL, 2, bypass_text); |
217 | 217 | ||
218 | static const struct snd_kcontrol_new lbypass_mux = | 218 | static const struct snd_kcontrol_new lbypass_mux = |
219 | SOC_DAPM_ENUM("Left Bypass", lbypass_enum); | 219 | SOC_DAPM_ENUM("Left Bypass", lbypass_enum); |
220 | 220 | ||
221 | 221 | ||
222 | static const struct soc_enum rbypass_enum = | 222 | static SOC_ENUM_SINGLE_DECL(rbypass_enum, |
223 | SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 3, 2, bypass_text); | 223 | WM8737_MIC_PREAMP_CONTROL, 3, bypass_text); |
224 | 224 | ||
225 | static const struct snd_kcontrol_new rbypass_mux = | 225 | static const struct snd_kcontrol_new rbypass_mux = |
226 | SOC_DAPM_ENUM("Left Bypass", rbypass_enum); | 226 | SOC_DAPM_ENUM("Left Bypass", rbypass_enum); |
@@ -570,12 +570,6 @@ static int wm8737_probe(struct snd_soc_codec *codec) | |||
570 | struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); | 570 | struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); |
571 | int ret; | 571 | int ret; |
572 | 572 | ||
573 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
574 | if (ret != 0) { | ||
575 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), | 573 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), |
580 | wm8737->supplies); | 574 | wm8737->supplies); |
581 | if (ret != 0) { | 575 | if (ret != 0) { |
@@ -644,7 +638,7 @@ static const struct regmap_config wm8737_regmap = { | |||
644 | .volatile_reg = wm8737_volatile, | 638 | .volatile_reg = wm8737_volatile, |
645 | }; | 639 | }; |
646 | 640 | ||
647 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 641 | #if IS_ENABLED(CONFIG_I2C) |
648 | static int wm8737_i2c_probe(struct i2c_client *i2c, | 642 | static int wm8737_i2c_probe(struct i2c_client *i2c, |
649 | const struct i2c_device_id *id) | 643 | const struct i2c_device_id *id) |
650 | { | 644 | { |
@@ -758,7 +752,7 @@ static struct spi_driver wm8737_spi_driver = { | |||
758 | static int __init wm8737_modinit(void) | 752 | static int __init wm8737_modinit(void) |
759 | { | 753 | { |
760 | int ret; | 754 | int ret; |
761 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 755 | #if IS_ENABLED(CONFIG_I2C) |
762 | ret = i2c_add_driver(&wm8737_i2c_driver); | 756 | ret = i2c_add_driver(&wm8737_i2c_driver); |
763 | if (ret != 0) { | 757 | if (ret != 0) { |
764 | printk(KERN_ERR "Failed to register WM8737 I2C driver: %d\n", | 758 | printk(KERN_ERR "Failed to register WM8737 I2C driver: %d\n", |
@@ -781,7 +775,7 @@ static void __exit wm8737_exit(void) | |||
781 | #if defined(CONFIG_SPI_MASTER) | 775 | #if defined(CONFIG_SPI_MASTER) |
782 | spi_unregister_driver(&wm8737_spi_driver); | 776 | spi_unregister_driver(&wm8737_spi_driver); |
783 | #endif | 777 | #endif |
784 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 778 | #if IS_ENABLED(CONFIG_I2C) |
785 | i2c_del_driver(&wm8737_i2c_driver); | 779 | i2c_del_driver(&wm8737_i2c_driver); |
786 | #endif | 780 | #endif |
787 | } | 781 | } |
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 2895c8d3b5e4..b33542a04607 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -44,7 +44,7 @@ struct wm8741_priv { | |||
44 | struct regmap *regmap; | 44 | struct regmap *regmap; |
45 | struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; | 45 | struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; |
46 | unsigned int sysclk; | 46 | unsigned int sysclk; |
47 | struct snd_pcm_hw_constraint_list *sysclk_constraints; | 47 | const struct snd_pcm_hw_constraint_list *sysclk_constraints; |
48 | }; | 48 | }; |
49 | 49 | ||
50 | static const struct reg_default wm8741_reg_defaults[] = { | 50 | static const struct reg_default wm8741_reg_defaults[] = { |
@@ -122,74 +122,74 @@ static struct { | |||
122 | { 6, 768 }, | 122 | { 6, 768 }, |
123 | }; | 123 | }; |
124 | 124 | ||
125 | static unsigned int rates_11289[] = { | 125 | static const unsigned int rates_11289[] = { |
126 | 44100, 88235, | 126 | 44100, 88235, |
127 | }; | 127 | }; |
128 | 128 | ||
129 | static struct snd_pcm_hw_constraint_list constraints_11289 = { | 129 | static const struct snd_pcm_hw_constraint_list constraints_11289 = { |
130 | .count = ARRAY_SIZE(rates_11289), | 130 | .count = ARRAY_SIZE(rates_11289), |
131 | .list = rates_11289, | 131 | .list = rates_11289, |
132 | }; | 132 | }; |
133 | 133 | ||
134 | static unsigned int rates_12288[] = { | 134 | static const unsigned int rates_12288[] = { |
135 | 32000, 48000, 96000, | 135 | 32000, 48000, 96000, |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static struct snd_pcm_hw_constraint_list constraints_12288 = { | 138 | static const struct snd_pcm_hw_constraint_list constraints_12288 = { |
139 | .count = ARRAY_SIZE(rates_12288), | 139 | .count = ARRAY_SIZE(rates_12288), |
140 | .list = rates_12288, | 140 | .list = rates_12288, |
141 | }; | 141 | }; |
142 | 142 | ||
143 | static unsigned int rates_16384[] = { | 143 | static const unsigned int rates_16384[] = { |
144 | 32000, | 144 | 32000, |
145 | }; | 145 | }; |
146 | 146 | ||
147 | static struct snd_pcm_hw_constraint_list constraints_16384 = { | 147 | static const struct snd_pcm_hw_constraint_list constraints_16384 = { |
148 | .count = ARRAY_SIZE(rates_16384), | 148 | .count = ARRAY_SIZE(rates_16384), |
149 | .list = rates_16384, | 149 | .list = rates_16384, |
150 | }; | 150 | }; |
151 | 151 | ||
152 | static unsigned int rates_16934[] = { | 152 | static const unsigned int rates_16934[] = { |
153 | 44100, 88235, | 153 | 44100, 88235, |
154 | }; | 154 | }; |
155 | 155 | ||
156 | static struct snd_pcm_hw_constraint_list constraints_16934 = { | 156 | static const struct snd_pcm_hw_constraint_list constraints_16934 = { |
157 | .count = ARRAY_SIZE(rates_16934), | 157 | .count = ARRAY_SIZE(rates_16934), |
158 | .list = rates_16934, | 158 | .list = rates_16934, |
159 | }; | 159 | }; |
160 | 160 | ||
161 | static unsigned int rates_18432[] = { | 161 | static const unsigned int rates_18432[] = { |
162 | 48000, 96000, | 162 | 48000, 96000, |
163 | }; | 163 | }; |
164 | 164 | ||
165 | static struct snd_pcm_hw_constraint_list constraints_18432 = { | 165 | static const struct snd_pcm_hw_constraint_list constraints_18432 = { |
166 | .count = ARRAY_SIZE(rates_18432), | 166 | .count = ARRAY_SIZE(rates_18432), |
167 | .list = rates_18432, | 167 | .list = rates_18432, |
168 | }; | 168 | }; |
169 | 169 | ||
170 | static unsigned int rates_22579[] = { | 170 | static const unsigned int rates_22579[] = { |
171 | 44100, 88235, 1764000 | 171 | 44100, 88235, 1764000 |
172 | }; | 172 | }; |
173 | 173 | ||
174 | static struct snd_pcm_hw_constraint_list constraints_22579 = { | 174 | static const struct snd_pcm_hw_constraint_list constraints_22579 = { |
175 | .count = ARRAY_SIZE(rates_22579), | 175 | .count = ARRAY_SIZE(rates_22579), |
176 | .list = rates_22579, | 176 | .list = rates_22579, |
177 | }; | 177 | }; |
178 | 178 | ||
179 | static unsigned int rates_24576[] = { | 179 | static const unsigned int rates_24576[] = { |
180 | 32000, 48000, 96000, 192000 | 180 | 32000, 48000, 96000, 192000 |
181 | }; | 181 | }; |
182 | 182 | ||
183 | static struct snd_pcm_hw_constraint_list constraints_24576 = { | 183 | static const struct snd_pcm_hw_constraint_list constraints_24576 = { |
184 | .count = ARRAY_SIZE(rates_24576), | 184 | .count = ARRAY_SIZE(rates_24576), |
185 | .list = rates_24576, | 185 | .list = rates_24576, |
186 | }; | 186 | }; |
187 | 187 | ||
188 | static unsigned int rates_36864[] = { | 188 | static const unsigned int rates_36864[] = { |
189 | 48000, 96000, 19200 | 189 | 48000, 96000, 19200 |
190 | }; | 190 | }; |
191 | 191 | ||
192 | static struct snd_pcm_hw_constraint_list constraints_36864 = { | 192 | static const struct snd_pcm_hw_constraint_list constraints_36864 = { |
193 | .count = ARRAY_SIZE(rates_36864), | 193 | .count = ARRAY_SIZE(rates_36864), |
194 | .list = rates_36864, | 194 | .list = rates_36864, |
195 | }; | 195 | }; |
@@ -429,12 +429,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
429 | goto err_get; | 429 | goto err_get; |
430 | } | 430 | } |
431 | 431 | ||
432 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
433 | if (ret != 0) { | ||
434 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
435 | goto err_enable; | ||
436 | } | ||
437 | |||
438 | ret = wm8741_reset(codec); | 432 | ret = wm8741_reset(codec); |
439 | if (ret < 0) { | 433 | if (ret < 0) { |
440 | dev_err(codec->dev, "Failed to issue reset\n"); | 434 | dev_err(codec->dev, "Failed to issue reset\n"); |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 78616a638a55..33990b63d214 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -702,12 +702,6 @@ static int wm8750_probe(struct snd_soc_codec *codec) | |||
702 | { | 702 | { |
703 | int ret; | 703 | int ret; |
704 | 704 | ||
705 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
706 | if (ret < 0) { | ||
707 | printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); | ||
708 | return ret; | ||
709 | } | ||
710 | |||
711 | ret = wm8750_reset(codec); | 705 | ret = wm8750_reset(codec); |
712 | if (ret < 0) { | 706 | if (ret < 0) { |
713 | printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); | 707 | printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index be85da93a268..cbb8d55052a4 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -251,7 +251,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, | |||
251 | if (wm8753->dai_func == ucontrol->value.integer.value[0]) | 251 | if (wm8753->dai_func == ucontrol->value.integer.value[0]) |
252 | return 0; | 252 | return 0; |
253 | 253 | ||
254 | if (codec->active) | 254 | if (snd_soc_codec_is_active(codec)) |
255 | return -EBUSY; | 255 | return -EBUSY; |
256 | 256 | ||
257 | ioctl = snd_soc_read(codec, WM8753_IOCTL); | 257 | ioctl = snd_soc_read(codec, WM8753_IOCTL); |
@@ -1314,7 +1314,7 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) | |||
1314 | /* the digital mute covers the HiFi and Voice DAC's on the WM8753. | 1314 | /* the digital mute covers the HiFi and Voice DAC's on the WM8753. |
1315 | * make sure we check if they are not both active when we mute */ | 1315 | * make sure we check if they are not both active when we mute */ |
1316 | if (mute && wm8753->dai_func == 1) { | 1316 | if (mute && wm8753->dai_func == 1) { |
1317 | if (!codec->active) | 1317 | if (!snd_soc_codec_is_active(codec)) |
1318 | snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8); | 1318 | snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8); |
1319 | } else { | 1319 | } else { |
1320 | if (mute) | 1320 | if (mute) |
@@ -1440,7 +1440,6 @@ static void wm8753_work(struct work_struct *work) | |||
1440 | static int wm8753_suspend(struct snd_soc_codec *codec) | 1440 | static int wm8753_suspend(struct snd_soc_codec *codec) |
1441 | { | 1441 | { |
1442 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1442 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1443 | codec->cache_sync = 1; | ||
1444 | return 0; | 1443 | return 0; |
1445 | } | 1444 | } |
1446 | 1445 | ||
@@ -1471,13 +1470,6 @@ static int wm8753_probe(struct snd_soc_codec *codec) | |||
1471 | 1470 | ||
1472 | INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work); | 1471 | INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work); |
1473 | 1472 | ||
1474 | codec->control_data = wm8753->regmap; | ||
1475 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
1476 | if (ret < 0) { | ||
1477 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1478 | return ret; | ||
1479 | } | ||
1480 | |||
1481 | ret = wm8753_reset(codec); | 1473 | ret = wm8753_reset(codec); |
1482 | if (ret < 0) { | 1474 | if (ret < 0) { |
1483 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | 1475 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 89a18d82f303..c61aeb38efb8 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c | |||
@@ -196,8 +196,8 @@ static const char *ain_text[] = { | |||
196 | "AIN5", "AIN6", "AIN7", "AIN8" | 196 | "AIN5", "AIN6", "AIN7", "AIN8" |
197 | }; | 197 | }; |
198 | 198 | ||
199 | static const struct soc_enum ain_enum = | 199 | static SOC_ENUM_DOUBLE_DECL(ain_enum, |
200 | SOC_ENUM_DOUBLE(WM8770_ADCMUX, 0, 4, 8, ain_text); | 200 | WM8770_ADCMUX, 0, 4, ain_text); |
201 | 201 | ||
202 | static const struct snd_kcontrol_new ain_mux = | 202 | static const struct snd_kcontrol_new ain_mux = |
203 | SOC_DAPM_ENUM("Capture Mux", ain_enum); | 203 | SOC_DAPM_ENUM("Capture Mux", ain_enum); |
@@ -580,12 +580,6 @@ static int wm8770_probe(struct snd_soc_codec *codec) | |||
580 | wm8770 = snd_soc_codec_get_drvdata(codec); | 580 | wm8770 = snd_soc_codec_get_drvdata(codec); |
581 | wm8770->codec = codec; | 581 | wm8770->codec = codec; |
582 | 582 | ||
583 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
584 | if (ret < 0) { | ||
585 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
586 | return ret; | ||
587 | } | ||
588 | |||
589 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), | 583 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), |
590 | wm8770->supplies); | 584 | wm8770->supplies); |
591 | if (ret) { | 585 | if (ret) { |
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index ef8246725232..70952ceb278b 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
@@ -430,12 +430,6 @@ static int wm8776_probe(struct snd_soc_codec *codec) | |||
430 | { | 430 | { |
431 | int ret = 0; | 431 | int ret = 0; |
432 | 432 | ||
433 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
434 | if (ret < 0) { | ||
435 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
436 | return ret; | ||
437 | } | ||
438 | |||
439 | ret = wm8776_reset(codec); | 433 | ret = wm8776_reset(codec); |
440 | if (ret < 0) { | 434 | if (ret < 0) { |
441 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | 435 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 9bc8206a6807..ee76f0fb4299 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -92,7 +92,7 @@ WM8804_REGULATOR_EVENT(0) | |||
92 | WM8804_REGULATOR_EVENT(1) | 92 | WM8804_REGULATOR_EVENT(1) |
93 | 93 | ||
94 | static const char *txsrc_text[] = { "S/PDIF RX", "AIF" }; | 94 | static const char *txsrc_text[] = { "S/PDIF RX", "AIF" }; |
95 | static const SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text); | 95 | static SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text); |
96 | 96 | ||
97 | static const struct snd_kcontrol_new wm8804_snd_controls[] = { | 97 | static const struct snd_kcontrol_new wm8804_snd_controls[] = { |
98 | SOC_ENUM_EXT("Input Source", txsrc, txsrc_get, txsrc_put), | 98 | SOC_ENUM_EXT("Input Source", txsrc, txsrc_get, txsrc_put), |
@@ -546,14 +546,6 @@ static int wm8804_probe(struct snd_soc_codec *codec) | |||
546 | 546 | ||
547 | wm8804 = snd_soc_codec_get_drvdata(codec); | 547 | wm8804 = snd_soc_codec_get_drvdata(codec); |
548 | 548 | ||
549 | codec->control_data = wm8804->regmap; | ||
550 | |||
551 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
552 | if (ret < 0) { | ||
553 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | ||
554 | return ret; | ||
555 | } | ||
556 | |||
557 | for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) | 549 | for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) |
558 | wm8804->supplies[i].supply = wm8804_supply_names[i]; | 550 | wm8804->supplies[i].supply = wm8804_supply_names[i]; |
559 | 551 | ||
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index e98bc7038a08..d09fdce57f5a 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -304,53 +304,53 @@ static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1); | |||
304 | 304 | ||
305 | static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" }; | 305 | static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" }; |
306 | 306 | ||
307 | static const struct soc_enum mic_bias_level = | 307 | static SOC_ENUM_SINGLE_DECL(mic_bias_level, |
308 | SOC_ENUM_SINGLE(WM8900_REG_INCTL, 8, 2, mic_bias_level_txt); | 308 | WM8900_REG_INCTL, 8, mic_bias_level_txt); |
309 | 309 | ||
310 | static const char *dac_mute_rate_txt[] = { "Fast", "Slow" }; | 310 | static const char *dac_mute_rate_txt[] = { "Fast", "Slow" }; |
311 | 311 | ||
312 | static const struct soc_enum dac_mute_rate = | 312 | static SOC_ENUM_SINGLE_DECL(dac_mute_rate, |
313 | SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 7, 2, dac_mute_rate_txt); | 313 | WM8900_REG_DACCTRL, 7, dac_mute_rate_txt); |
314 | 314 | ||
315 | static const char *dac_deemphasis_txt[] = { | 315 | static const char *dac_deemphasis_txt[] = { |
316 | "Disabled", "32kHz", "44.1kHz", "48kHz" | 316 | "Disabled", "32kHz", "44.1kHz", "48kHz" |
317 | }; | 317 | }; |
318 | 318 | ||
319 | static const struct soc_enum dac_deemphasis = | 319 | static SOC_ENUM_SINGLE_DECL(dac_deemphasis, |
320 | SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 4, 4, dac_deemphasis_txt); | 320 | WM8900_REG_DACCTRL, 4, dac_deemphasis_txt); |
321 | 321 | ||
322 | static const char *adc_hpf_cut_txt[] = { | 322 | static const char *adc_hpf_cut_txt[] = { |
323 | "Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3" | 323 | "Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3" |
324 | }; | 324 | }; |
325 | 325 | ||
326 | static const struct soc_enum adc_hpf_cut = | 326 | static SOC_ENUM_SINGLE_DECL(adc_hpf_cut, |
327 | SOC_ENUM_SINGLE(WM8900_REG_ADCCTRL, 5, 4, adc_hpf_cut_txt); | 327 | WM8900_REG_ADCCTRL, 5, adc_hpf_cut_txt); |
328 | 328 | ||
329 | static const char *lr_txt[] = { | 329 | static const char *lr_txt[] = { |
330 | "Left", "Right" | 330 | "Left", "Right" |
331 | }; | 331 | }; |
332 | 332 | ||
333 | static const struct soc_enum aifl_src = | 333 | static SOC_ENUM_SINGLE_DECL(aifl_src, |
334 | SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 15, 2, lr_txt); | 334 | WM8900_REG_AUDIO1, 15, lr_txt); |
335 | 335 | ||
336 | static const struct soc_enum aifr_src = | 336 | static SOC_ENUM_SINGLE_DECL(aifr_src, |
337 | SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 14, 2, lr_txt); | 337 | WM8900_REG_AUDIO1, 14, lr_txt); |
338 | 338 | ||
339 | static const struct soc_enum dacl_src = | 339 | static SOC_ENUM_SINGLE_DECL(dacl_src, |
340 | SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 15, 2, lr_txt); | 340 | WM8900_REG_AUDIO2, 15, lr_txt); |
341 | 341 | ||
342 | static const struct soc_enum dacr_src = | 342 | static SOC_ENUM_SINGLE_DECL(dacr_src, |
343 | SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 14, 2, lr_txt); | 343 | WM8900_REG_AUDIO2, 14, lr_txt); |
344 | 344 | ||
345 | static const char *sidetone_txt[] = { | 345 | static const char *sidetone_txt[] = { |
346 | "Disabled", "Left ADC", "Right ADC" | 346 | "Disabled", "Left ADC", "Right ADC" |
347 | }; | 347 | }; |
348 | 348 | ||
349 | static const struct soc_enum dacl_sidetone = | 349 | static SOC_ENUM_SINGLE_DECL(dacl_sidetone, |
350 | SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 2, 3, sidetone_txt); | 350 | WM8900_REG_SIDETONE, 2, sidetone_txt); |
351 | 351 | ||
352 | static const struct soc_enum dacr_sidetone = | 352 | static SOC_ENUM_SINGLE_DECL(dacr_sidetone, |
353 | SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 0, 3, sidetone_txt); | 353 | WM8900_REG_SIDETONE, 0, sidetone_txt); |
354 | 354 | ||
355 | static const struct snd_kcontrol_new wm8900_snd_controls[] = { | 355 | static const struct snd_kcontrol_new wm8900_snd_controls[] = { |
356 | SOC_ENUM("Mic Bias Level", mic_bias_level), | 356 | SOC_ENUM("Mic Bias Level", mic_bias_level), |
@@ -496,8 +496,8 @@ SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0), | |||
496 | 496 | ||
497 | static const char *wm8900_lp_mux[] = { "Disabled", "Enabled" }; | 497 | static const char *wm8900_lp_mux[] = { "Disabled", "Enabled" }; |
498 | 498 | ||
499 | static const struct soc_enum wm8900_lineout2_lp_mux = | 499 | static SOC_ENUM_SINGLE_DECL(wm8900_lineout2_lp_mux, |
500 | SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm8900_lp_mux); | 500 | WM8900_REG_LOUTMIXCTL1, 1, wm8900_lp_mux); |
501 | 501 | ||
502 | static const struct snd_kcontrol_new wm8900_lineout2_lp = | 502 | static const struct snd_kcontrol_new wm8900_lineout2_lp = |
503 | SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux); | 503 | SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux); |
@@ -1178,13 +1178,7 @@ static int wm8900_resume(struct snd_soc_codec *codec) | |||
1178 | 1178 | ||
1179 | static int wm8900_probe(struct snd_soc_codec *codec) | 1179 | static int wm8900_probe(struct snd_soc_codec *codec) |
1180 | { | 1180 | { |
1181 | int ret = 0, reg; | 1181 | int reg; |
1182 | |||
1183 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
1184 | if (ret != 0) { | ||
1185 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1186 | return ret; | ||
1187 | } | ||
1188 | 1182 | ||
1189 | reg = snd_soc_read(codec, WM8900_REG_ID); | 1183 | reg = snd_soc_read(codec, WM8900_REG_ID); |
1190 | if (reg != 0x8900) { | 1184 | if (reg != 0x8900) { |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index eebcb1da3b7b..b0084a127d18 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -489,28 +489,28 @@ static const char *hpf_mode_text[] = { | |||
489 | "Hi-fi", "Voice 1", "Voice 2", "Voice 3" | 489 | "Hi-fi", "Voice 1", "Voice 2", "Voice 3" |
490 | }; | 490 | }; |
491 | 491 | ||
492 | static const struct soc_enum hpf_mode = | 492 | static SOC_ENUM_SINGLE_DECL(hpf_mode, |
493 | SOC_ENUM_SINGLE(WM8903_ADC_DIGITAL_0, 5, 4, hpf_mode_text); | 493 | WM8903_ADC_DIGITAL_0, 5, hpf_mode_text); |
494 | 494 | ||
495 | static const char *osr_text[] = { | 495 | static const char *osr_text[] = { |
496 | "Low power", "High performance" | 496 | "Low power", "High performance" |
497 | }; | 497 | }; |
498 | 498 | ||
499 | static const struct soc_enum adc_osr = | 499 | static SOC_ENUM_SINGLE_DECL(adc_osr, |
500 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_ADC_0, 0, 2, osr_text); | 500 | WM8903_ANALOGUE_ADC_0, 0, osr_text); |
501 | 501 | ||
502 | static const struct soc_enum dac_osr = | 502 | static SOC_ENUM_SINGLE_DECL(dac_osr, |
503 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 0, 2, osr_text); | 503 | WM8903_DAC_DIGITAL_1, 0, osr_text); |
504 | 504 | ||
505 | static const char *drc_slope_text[] = { | 505 | static const char *drc_slope_text[] = { |
506 | "1", "1/2", "1/4", "1/8", "1/16", "0" | 506 | "1", "1/2", "1/4", "1/8", "1/16", "0" |
507 | }; | 507 | }; |
508 | 508 | ||
509 | static const struct soc_enum drc_slope_r0 = | 509 | static SOC_ENUM_SINGLE_DECL(drc_slope_r0, |
510 | SOC_ENUM_SINGLE(WM8903_DRC_2, 3, 6, drc_slope_text); | 510 | WM8903_DRC_2, 3, drc_slope_text); |
511 | 511 | ||
512 | static const struct soc_enum drc_slope_r1 = | 512 | static SOC_ENUM_SINGLE_DECL(drc_slope_r1, |
513 | SOC_ENUM_SINGLE(WM8903_DRC_2, 0, 6, drc_slope_text); | 513 | WM8903_DRC_2, 0, drc_slope_text); |
514 | 514 | ||
515 | static const char *drc_attack_text[] = { | 515 | static const char *drc_attack_text[] = { |
516 | "instantaneous", | 516 | "instantaneous", |
@@ -518,125 +518,125 @@ static const char *drc_attack_text[] = { | |||
518 | "46.4ms", "92.8ms", "185.6ms" | 518 | "46.4ms", "92.8ms", "185.6ms" |
519 | }; | 519 | }; |
520 | 520 | ||
521 | static const struct soc_enum drc_attack = | 521 | static SOC_ENUM_SINGLE_DECL(drc_attack, |
522 | SOC_ENUM_SINGLE(WM8903_DRC_1, 12, 11, drc_attack_text); | 522 | WM8903_DRC_1, 12, drc_attack_text); |
523 | 523 | ||
524 | static const char *drc_decay_text[] = { | 524 | static const char *drc_decay_text[] = { |
525 | "186ms", "372ms", "743ms", "1.49s", "2.97s", "5.94s", "11.89s", | 525 | "186ms", "372ms", "743ms", "1.49s", "2.97s", "5.94s", "11.89s", |
526 | "23.87s", "47.56s" | 526 | "23.87s", "47.56s" |
527 | }; | 527 | }; |
528 | 528 | ||
529 | static const struct soc_enum drc_decay = | 529 | static SOC_ENUM_SINGLE_DECL(drc_decay, |
530 | SOC_ENUM_SINGLE(WM8903_DRC_1, 8, 9, drc_decay_text); | 530 | WM8903_DRC_1, 8, drc_decay_text); |
531 | 531 | ||
532 | static const char *drc_ff_delay_text[] = { | 532 | static const char *drc_ff_delay_text[] = { |
533 | "5 samples", "9 samples" | 533 | "5 samples", "9 samples" |
534 | }; | 534 | }; |
535 | 535 | ||
536 | static const struct soc_enum drc_ff_delay = | 536 | static SOC_ENUM_SINGLE_DECL(drc_ff_delay, |
537 | SOC_ENUM_SINGLE(WM8903_DRC_0, 5, 2, drc_ff_delay_text); | 537 | WM8903_DRC_0, 5, drc_ff_delay_text); |
538 | 538 | ||
539 | static const char *drc_qr_decay_text[] = { | 539 | static const char *drc_qr_decay_text[] = { |
540 | "0.725ms", "1.45ms", "5.8ms" | 540 | "0.725ms", "1.45ms", "5.8ms" |
541 | }; | 541 | }; |
542 | 542 | ||
543 | static const struct soc_enum drc_qr_decay = | 543 | static SOC_ENUM_SINGLE_DECL(drc_qr_decay, |
544 | SOC_ENUM_SINGLE(WM8903_DRC_1, 4, 3, drc_qr_decay_text); | 544 | WM8903_DRC_1, 4, drc_qr_decay_text); |
545 | 545 | ||
546 | static const char *drc_smoothing_text[] = { | 546 | static const char *drc_smoothing_text[] = { |
547 | "Low", "Medium", "High" | 547 | "Low", "Medium", "High" |
548 | }; | 548 | }; |
549 | 549 | ||
550 | static const struct soc_enum drc_smoothing = | 550 | static SOC_ENUM_SINGLE_DECL(drc_smoothing, |
551 | SOC_ENUM_SINGLE(WM8903_DRC_0, 11, 3, drc_smoothing_text); | 551 | WM8903_DRC_0, 11, drc_smoothing_text); |
552 | 552 | ||
553 | static const char *soft_mute_text[] = { | 553 | static const char *soft_mute_text[] = { |
554 | "Fast (fs/2)", "Slow (fs/32)" | 554 | "Fast (fs/2)", "Slow (fs/32)" |
555 | }; | 555 | }; |
556 | 556 | ||
557 | static const struct soc_enum soft_mute = | 557 | static SOC_ENUM_SINGLE_DECL(soft_mute, |
558 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 10, 2, soft_mute_text); | 558 | WM8903_DAC_DIGITAL_1, 10, soft_mute_text); |
559 | 559 | ||
560 | static const char *mute_mode_text[] = { | 560 | static const char *mute_mode_text[] = { |
561 | "Hard", "Soft" | 561 | "Hard", "Soft" |
562 | }; | 562 | }; |
563 | 563 | ||
564 | static const struct soc_enum mute_mode = | 564 | static SOC_ENUM_SINGLE_DECL(mute_mode, |
565 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 9, 2, mute_mode_text); | 565 | WM8903_DAC_DIGITAL_1, 9, mute_mode_text); |
566 | 566 | ||
567 | static const char *companding_text[] = { | 567 | static const char *companding_text[] = { |
568 | "ulaw", "alaw" | 568 | "ulaw", "alaw" |
569 | }; | 569 | }; |
570 | 570 | ||
571 | static const struct soc_enum dac_companding = | 571 | static SOC_ENUM_SINGLE_DECL(dac_companding, |
572 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 0, 2, companding_text); | 572 | WM8903_AUDIO_INTERFACE_0, 0, companding_text); |
573 | 573 | ||
574 | static const struct soc_enum adc_companding = | 574 | static SOC_ENUM_SINGLE_DECL(adc_companding, |
575 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 2, 2, companding_text); | 575 | WM8903_AUDIO_INTERFACE_0, 2, companding_text); |
576 | 576 | ||
577 | static const char *input_mode_text[] = { | 577 | static const char *input_mode_text[] = { |
578 | "Single-Ended", "Differential Line", "Differential Mic" | 578 | "Single-Ended", "Differential Line", "Differential Mic" |
579 | }; | 579 | }; |
580 | 580 | ||
581 | static const struct soc_enum linput_mode_enum = | 581 | static SOC_ENUM_SINGLE_DECL(linput_mode_enum, |
582 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); | 582 | WM8903_ANALOGUE_LEFT_INPUT_1, 0, input_mode_text); |
583 | 583 | ||
584 | static const struct soc_enum rinput_mode_enum = | 584 | static SOC_ENUM_SINGLE_DECL(rinput_mode_enum, |
585 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); | 585 | WM8903_ANALOGUE_RIGHT_INPUT_1, 0, input_mode_text); |
586 | 586 | ||
587 | static const char *linput_mux_text[] = { | 587 | static const char *linput_mux_text[] = { |
588 | "IN1L", "IN2L", "IN3L" | 588 | "IN1L", "IN2L", "IN3L" |
589 | }; | 589 | }; |
590 | 590 | ||
591 | static const struct soc_enum linput_enum = | 591 | static SOC_ENUM_SINGLE_DECL(linput_enum, |
592 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 2, 3, linput_mux_text); | 592 | WM8903_ANALOGUE_LEFT_INPUT_1, 2, linput_mux_text); |
593 | 593 | ||
594 | static const struct soc_enum linput_inv_enum = | 594 | static SOC_ENUM_SINGLE_DECL(linput_inv_enum, |
595 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 4, 3, linput_mux_text); | 595 | WM8903_ANALOGUE_LEFT_INPUT_1, 4, linput_mux_text); |
596 | 596 | ||
597 | static const char *rinput_mux_text[] = { | 597 | static const char *rinput_mux_text[] = { |
598 | "IN1R", "IN2R", "IN3R" | 598 | "IN1R", "IN2R", "IN3R" |
599 | }; | 599 | }; |
600 | 600 | ||
601 | static const struct soc_enum rinput_enum = | 601 | static SOC_ENUM_SINGLE_DECL(rinput_enum, |
602 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 2, 3, rinput_mux_text); | 602 | WM8903_ANALOGUE_RIGHT_INPUT_1, 2, rinput_mux_text); |
603 | 603 | ||
604 | static const struct soc_enum rinput_inv_enum = | 604 | static SOC_ENUM_SINGLE_DECL(rinput_inv_enum, |
605 | SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text); | 605 | WM8903_ANALOGUE_RIGHT_INPUT_1, 4, rinput_mux_text); |
606 | 606 | ||
607 | 607 | ||
608 | static const char *sidetone_text[] = { | 608 | static const char *sidetone_text[] = { |
609 | "None", "Left", "Right" | 609 | "None", "Left", "Right" |
610 | }; | 610 | }; |
611 | 611 | ||
612 | static const struct soc_enum lsidetone_enum = | 612 | static SOC_ENUM_SINGLE_DECL(lsidetone_enum, |
613 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 2, 3, sidetone_text); | 613 | WM8903_DAC_DIGITAL_0, 2, sidetone_text); |
614 | 614 | ||
615 | static const struct soc_enum rsidetone_enum = | 615 | static SOC_ENUM_SINGLE_DECL(rsidetone_enum, |
616 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text); | 616 | WM8903_DAC_DIGITAL_0, 0, sidetone_text); |
617 | 617 | ||
618 | static const char *adcinput_text[] = { | 618 | static const char *adcinput_text[] = { |
619 | "ADC", "DMIC" | 619 | "ADC", "DMIC" |
620 | }; | 620 | }; |
621 | 621 | ||
622 | static const struct soc_enum adcinput_enum = | 622 | static SOC_ENUM_SINGLE_DECL(adcinput_enum, |
623 | SOC_ENUM_SINGLE(WM8903_CLOCK_RATE_TEST_4, 9, 2, adcinput_text); | 623 | WM8903_CLOCK_RATE_TEST_4, 9, adcinput_text); |
624 | 624 | ||
625 | static const char *aif_text[] = { | 625 | static const char *aif_text[] = { |
626 | "Left", "Right" | 626 | "Left", "Right" |
627 | }; | 627 | }; |
628 | 628 | ||
629 | static const struct soc_enum lcapture_enum = | 629 | static SOC_ENUM_SINGLE_DECL(lcapture_enum, |
630 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 7, 2, aif_text); | 630 | WM8903_AUDIO_INTERFACE_0, 7, aif_text); |
631 | 631 | ||
632 | static const struct soc_enum rcapture_enum = | 632 | static SOC_ENUM_SINGLE_DECL(rcapture_enum, |
633 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 6, 2, aif_text); | 633 | WM8903_AUDIO_INTERFACE_0, 6, aif_text); |
634 | 634 | ||
635 | static const struct soc_enum lplay_enum = | 635 | static SOC_ENUM_SINGLE_DECL(lplay_enum, |
636 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 5, 2, aif_text); | 636 | WM8903_AUDIO_INTERFACE_0, 5, aif_text); |
637 | 637 | ||
638 | static const struct soc_enum rplay_enum = | 638 | static SOC_ENUM_SINGLE_DECL(rplay_enum, |
639 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 4, 2, aif_text); | 639 | WM8903_AUDIO_INTERFACE_0, 4, aif_text); |
640 | 640 | ||
641 | static const struct snd_kcontrol_new wm8903_snd_controls[] = { | 641 | static const struct snd_kcontrol_new wm8903_snd_controls[] = { |
642 | 642 | ||
@@ -1897,21 +1897,13 @@ static void wm8903_free_gpio(struct wm8903_priv *wm8903) | |||
1897 | static int wm8903_probe(struct snd_soc_codec *codec) | 1897 | static int wm8903_probe(struct snd_soc_codec *codec) |
1898 | { | 1898 | { |
1899 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 1899 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1900 | int ret; | ||
1901 | 1900 | ||
1902 | wm8903->codec = codec; | 1901 | wm8903->codec = codec; |
1903 | codec->control_data = wm8903->regmap; | ||
1904 | |||
1905 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
1906 | if (ret != 0) { | ||
1907 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1908 | return ret; | ||
1909 | } | ||
1910 | 1902 | ||
1911 | /* power on device */ | 1903 | /* power on device */ |
1912 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1904 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1913 | 1905 | ||
1914 | return ret; | 1906 | return 0; |
1915 | } | 1907 | } |
1916 | 1908 | ||
1917 | /* power down chip */ | 1909 | /* power down chip */ |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 53bbfac6a83a..49c35c36935e 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -552,18 +552,20 @@ static const char *input_mode_text[] = { | |||
552 | "Single-Ended", "Differential Line", "Differential Mic" | 552 | "Single-Ended", "Differential Line", "Differential Mic" |
553 | }; | 553 | }; |
554 | 554 | ||
555 | static const struct soc_enum lin_mode = | 555 | static SOC_ENUM_SINGLE_DECL(lin_mode, |
556 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); | 556 | WM8904_ANALOGUE_LEFT_INPUT_1, 0, |
557 | input_mode_text); | ||
557 | 558 | ||
558 | static const struct soc_enum rin_mode = | 559 | static SOC_ENUM_SINGLE_DECL(rin_mode, |
559 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); | 560 | WM8904_ANALOGUE_RIGHT_INPUT_1, 0, |
561 | input_mode_text); | ||
560 | 562 | ||
561 | static const char *hpf_mode_text[] = { | 563 | static const char *hpf_mode_text[] = { |
562 | "Hi-fi", "Voice 1", "Voice 2", "Voice 3" | 564 | "Hi-fi", "Voice 1", "Voice 2", "Voice 3" |
563 | }; | 565 | }; |
564 | 566 | ||
565 | static const struct soc_enum hpf_mode = | 567 | static SOC_ENUM_SINGLE_DECL(hpf_mode, WM8904_ADC_DIGITAL_0, 5, |
566 | SOC_ENUM_SINGLE(WM8904_ADC_DIGITAL_0, 5, 4, hpf_mode_text); | 568 | hpf_mode_text); |
567 | 569 | ||
568 | static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol, | 570 | static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol, |
569 | struct snd_ctl_elem_value *ucontrol) | 571 | struct snd_ctl_elem_value *ucontrol) |
@@ -611,8 +613,7 @@ static const char *drc_path_text[] = { | |||
611 | "ADC", "DAC" | 613 | "ADC", "DAC" |
612 | }; | 614 | }; |
613 | 615 | ||
614 | static const struct soc_enum drc_path = | 616 | static SOC_ENUM_SINGLE_DECL(drc_path, WM8904_DRC_0, 14, drc_path_text); |
615 | SOC_ENUM_SINGLE(WM8904_DRC_0, 14, 2, drc_path_text); | ||
616 | 617 | ||
617 | static const struct snd_kcontrol_new wm8904_dac_snd_controls[] = { | 618 | static const struct snd_kcontrol_new wm8904_dac_snd_controls[] = { |
618 | SOC_SINGLE_TLV("Digital Playback Boost Volume", | 619 | SOC_SINGLE_TLV("Digital Playback Boost Volume", |
@@ -858,14 +859,14 @@ static const char *lin_text[] = { | |||
858 | "IN1L", "IN2L", "IN3L" | 859 | "IN1L", "IN2L", "IN3L" |
859 | }; | 860 | }; |
860 | 861 | ||
861 | static const struct soc_enum lin_enum = | 862 | static SOC_ENUM_SINGLE_DECL(lin_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 2, |
862 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 2, 3, lin_text); | 863 | lin_text); |
863 | 864 | ||
864 | static const struct snd_kcontrol_new lin_mux = | 865 | static const struct snd_kcontrol_new lin_mux = |
865 | SOC_DAPM_ENUM("Left Capture Mux", lin_enum); | 866 | SOC_DAPM_ENUM("Left Capture Mux", lin_enum); |
866 | 867 | ||
867 | static const struct soc_enum lin_inv_enum = | 868 | static SOC_ENUM_SINGLE_DECL(lin_inv_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 4, |
868 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 4, 3, lin_text); | 869 | lin_text); |
869 | 870 | ||
870 | static const struct snd_kcontrol_new lin_inv_mux = | 871 | static const struct snd_kcontrol_new lin_inv_mux = |
871 | SOC_DAPM_ENUM("Left Capture Inveting Mux", lin_inv_enum); | 872 | SOC_DAPM_ENUM("Left Capture Inveting Mux", lin_inv_enum); |
@@ -874,14 +875,14 @@ static const char *rin_text[] = { | |||
874 | "IN1R", "IN2R", "IN3R" | 875 | "IN1R", "IN2R", "IN3R" |
875 | }; | 876 | }; |
876 | 877 | ||
877 | static const struct soc_enum rin_enum = | 878 | static SOC_ENUM_SINGLE_DECL(rin_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 2, |
878 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 2, 3, rin_text); | 879 | rin_text); |
879 | 880 | ||
880 | static const struct snd_kcontrol_new rin_mux = | 881 | static const struct snd_kcontrol_new rin_mux = |
881 | SOC_DAPM_ENUM("Right Capture Mux", rin_enum); | 882 | SOC_DAPM_ENUM("Right Capture Mux", rin_enum); |
882 | 883 | ||
883 | static const struct soc_enum rin_inv_enum = | 884 | static SOC_ENUM_SINGLE_DECL(rin_inv_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 4, |
884 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 4, 3, rin_text); | 885 | rin_text); |
885 | 886 | ||
886 | static const struct snd_kcontrol_new rin_inv_mux = | 887 | static const struct snd_kcontrol_new rin_inv_mux = |
887 | SOC_DAPM_ENUM("Right Capture Inveting Mux", rin_inv_enum); | 888 | SOC_DAPM_ENUM("Right Capture Inveting Mux", rin_inv_enum); |
@@ -890,26 +891,26 @@ static const char *aif_text[] = { | |||
890 | "Left", "Right" | 891 | "Left", "Right" |
891 | }; | 892 | }; |
892 | 893 | ||
893 | static const struct soc_enum aifoutl_enum = | 894 | static SOC_ENUM_SINGLE_DECL(aifoutl_enum, WM8904_AUDIO_INTERFACE_0, 7, |
894 | SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 7, 2, aif_text); | 895 | aif_text); |
895 | 896 | ||
896 | static const struct snd_kcontrol_new aifoutl_mux = | 897 | static const struct snd_kcontrol_new aifoutl_mux = |
897 | SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); | 898 | SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); |
898 | 899 | ||
899 | static const struct soc_enum aifoutr_enum = | 900 | static SOC_ENUM_SINGLE_DECL(aifoutr_enum, WM8904_AUDIO_INTERFACE_0, 6, |
900 | SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 6, 2, aif_text); | 901 | aif_text); |
901 | 902 | ||
902 | static const struct snd_kcontrol_new aifoutr_mux = | 903 | static const struct snd_kcontrol_new aifoutr_mux = |
903 | SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); | 904 | SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); |
904 | 905 | ||
905 | static const struct soc_enum aifinl_enum = | 906 | static SOC_ENUM_SINGLE_DECL(aifinl_enum, WM8904_AUDIO_INTERFACE_0, 5, |
906 | SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 5, 2, aif_text); | 907 | aif_text); |
907 | 908 | ||
908 | static const struct snd_kcontrol_new aifinl_mux = | 909 | static const struct snd_kcontrol_new aifinl_mux = |
909 | SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); | 910 | SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); |
910 | 911 | ||
911 | static const struct soc_enum aifinr_enum = | 912 | static SOC_ENUM_SINGLE_DECL(aifinr_enum, WM8904_AUDIO_INTERFACE_0, 4, |
912 | SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 4, 2, aif_text); | 913 | aif_text); |
913 | 914 | ||
914 | static const struct snd_kcontrol_new aifinr_mux = | 915 | static const struct snd_kcontrol_new aifinr_mux = |
915 | SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); | 916 | SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); |
@@ -991,26 +992,26 @@ static const char *out_mux_text[] = { | |||
991 | "DAC", "Bypass" | 992 | "DAC", "Bypass" |
992 | }; | 993 | }; |
993 | 994 | ||
994 | static const struct soc_enum hpl_enum = | 995 | static SOC_ENUM_SINGLE_DECL(hpl_enum, WM8904_ANALOGUE_OUT12_ZC, 3, |
995 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 3, 2, out_mux_text); | 996 | out_mux_text); |
996 | 997 | ||
997 | static const struct snd_kcontrol_new hpl_mux = | 998 | static const struct snd_kcontrol_new hpl_mux = |
998 | SOC_DAPM_ENUM("HPL Mux", hpl_enum); | 999 | SOC_DAPM_ENUM("HPL Mux", hpl_enum); |
999 | 1000 | ||
1000 | static const struct soc_enum hpr_enum = | 1001 | static SOC_ENUM_SINGLE_DECL(hpr_enum, WM8904_ANALOGUE_OUT12_ZC, 2, |
1001 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 2, 2, out_mux_text); | 1002 | out_mux_text); |
1002 | 1003 | ||
1003 | static const struct snd_kcontrol_new hpr_mux = | 1004 | static const struct snd_kcontrol_new hpr_mux = |
1004 | SOC_DAPM_ENUM("HPR Mux", hpr_enum); | 1005 | SOC_DAPM_ENUM("HPR Mux", hpr_enum); |
1005 | 1006 | ||
1006 | static const struct soc_enum linel_enum = | 1007 | static SOC_ENUM_SINGLE_DECL(linel_enum, WM8904_ANALOGUE_OUT12_ZC, 1, |
1007 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 1, 2, out_mux_text); | 1008 | out_mux_text); |
1008 | 1009 | ||
1009 | static const struct snd_kcontrol_new linel_mux = | 1010 | static const struct snd_kcontrol_new linel_mux = |
1010 | SOC_DAPM_ENUM("LINEL Mux", linel_enum); | 1011 | SOC_DAPM_ENUM("LINEL Mux", linel_enum); |
1011 | 1012 | ||
1012 | static const struct soc_enum liner_enum = | 1013 | static SOC_ENUM_SINGLE_DECL(liner_enum, WM8904_ANALOGUE_OUT12_ZC, 0, |
1013 | SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 0, 2, out_mux_text); | 1014 | out_mux_text); |
1014 | 1015 | ||
1015 | static const struct snd_kcontrol_new liner_mux = | 1016 | static const struct snd_kcontrol_new liner_mux = |
1016 | SOC_DAPM_ENUM("LINER Mux", liner_enum); | 1017 | SOC_DAPM_ENUM("LINER Mux", liner_enum); |
@@ -1019,14 +1020,14 @@ static const char *sidetone_text[] = { | |||
1019 | "None", "Left", "Right" | 1020 | "None", "Left", "Right" |
1020 | }; | 1021 | }; |
1021 | 1022 | ||
1022 | static const struct soc_enum dacl_sidetone_enum = | 1023 | static SOC_ENUM_SINGLE_DECL(dacl_sidetone_enum, WM8904_DAC_DIGITAL_0, 2, |
1023 | SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 2, 3, sidetone_text); | 1024 | sidetone_text); |
1024 | 1025 | ||
1025 | static const struct snd_kcontrol_new dacl_sidetone_mux = | 1026 | static const struct snd_kcontrol_new dacl_sidetone_mux = |
1026 | SOC_DAPM_ENUM("Left Sidetone Mux", dacl_sidetone_enum); | 1027 | SOC_DAPM_ENUM("Left Sidetone Mux", dacl_sidetone_enum); |
1027 | 1028 | ||
1028 | static const struct soc_enum dacr_sidetone_enum = | 1029 | static SOC_ENUM_SINGLE_DECL(dacr_sidetone_enum, WM8904_DAC_DIGITAL_0, 0, |
1029 | SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 0, 3, sidetone_text); | 1030 | sidetone_text); |
1030 | 1031 | ||
1031 | static const struct snd_kcontrol_new dacr_sidetone_mux = | 1032 | static const struct snd_kcontrol_new dacr_sidetone_mux = |
1032 | SOC_DAPM_ENUM("Right Sidetone Mux", dacr_sidetone_enum); | 1033 | SOC_DAPM_ENUM("Right Sidetone Mux", dacr_sidetone_enum); |
@@ -1981,7 +1982,7 @@ static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec) | |||
1981 | dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", | 1982 | dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", |
1982 | wm8904->num_retune_mobile_texts); | 1983 | wm8904->num_retune_mobile_texts); |
1983 | 1984 | ||
1984 | wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; | 1985 | wm8904->retune_mobile_enum.items = wm8904->num_retune_mobile_texts; |
1985 | wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; | 1986 | wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; |
1986 | 1987 | ||
1987 | ret = snd_soc_add_codec_controls(codec, &control, 1); | 1988 | ret = snd_soc_add_codec_controls(codec, &control, 1); |
@@ -2022,7 +2023,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) | |||
2022 | for (i = 0; i < pdata->num_drc_cfgs; i++) | 2023 | for (i = 0; i < pdata->num_drc_cfgs; i++) |
2023 | wm8904->drc_texts[i] = pdata->drc_cfgs[i].name; | 2024 | wm8904->drc_texts[i] = pdata->drc_cfgs[i].name; |
2024 | 2025 | ||
2025 | wm8904->drc_enum.max = pdata->num_drc_cfgs; | 2026 | wm8904->drc_enum.items = pdata->num_drc_cfgs; |
2026 | wm8904->drc_enum.texts = wm8904->drc_texts; | 2027 | wm8904->drc_enum.texts = wm8904->drc_texts; |
2027 | 2028 | ||
2028 | ret = snd_soc_add_codec_controls(codec, &control, 1); | 2029 | ret = snd_soc_add_codec_controls(codec, &control, 1); |
@@ -2047,9 +2048,6 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) | |||
2047 | static int wm8904_probe(struct snd_soc_codec *codec) | 2048 | static int wm8904_probe(struct snd_soc_codec *codec) |
2048 | { | 2049 | { |
2049 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | 2050 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
2050 | int ret; | ||
2051 | |||
2052 | codec->control_data = wm8904->regmap; | ||
2053 | 2051 | ||
2054 | switch (wm8904->devtype) { | 2052 | switch (wm8904->devtype) { |
2055 | case WM8904: | 2053 | case WM8904: |
@@ -2063,12 +2061,6 @@ static int wm8904_probe(struct snd_soc_codec *codec) | |||
2063 | return -EINVAL; | 2061 | return -EINVAL; |
2064 | } | 2062 | } |
2065 | 2063 | ||
2066 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
2067 | if (ret != 0) { | ||
2068 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
2069 | return ret; | ||
2070 | } | ||
2071 | |||
2072 | wm8904_handle_pdata(codec); | 2064 | wm8904_handle_pdata(codec); |
2073 | 2065 | ||
2074 | wm8904_add_widgets(codec); | 2066 | wm8904_add_widgets(codec); |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index b404c26c1753..fc6eec9ad66b 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -154,22 +154,22 @@ static const struct reg_default wm8940_reg_defaults[] = { | |||
154 | }; | 154 | }; |
155 | 155 | ||
156 | static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" }; | 156 | static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" }; |
157 | static const struct soc_enum wm8940_adc_companding_enum | 157 | static SOC_ENUM_SINGLE_DECL(wm8940_adc_companding_enum, |
158 | = SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 1, 4, wm8940_companding); | 158 | WM8940_COMPANDINGCTL, 1, wm8940_companding); |
159 | static const struct soc_enum wm8940_dac_companding_enum | 159 | static SOC_ENUM_SINGLE_DECL(wm8940_dac_companding_enum, |
160 | = SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 3, 4, wm8940_companding); | 160 | WM8940_COMPANDINGCTL, 3, wm8940_companding); |
161 | 161 | ||
162 | static const char *wm8940_alc_mode_text[] = {"ALC", "Limiter"}; | 162 | static const char *wm8940_alc_mode_text[] = {"ALC", "Limiter"}; |
163 | static const struct soc_enum wm8940_alc_mode_enum | 163 | static SOC_ENUM_SINGLE_DECL(wm8940_alc_mode_enum, |
164 | = SOC_ENUM_SINGLE(WM8940_ALC3, 8, 2, wm8940_alc_mode_text); | 164 | WM8940_ALC3, 8, wm8940_alc_mode_text); |
165 | 165 | ||
166 | static const char *wm8940_mic_bias_level_text[] = {"0.9", "0.65"}; | 166 | static const char *wm8940_mic_bias_level_text[] = {"0.9", "0.65"}; |
167 | static const struct soc_enum wm8940_mic_bias_level_enum | 167 | static SOC_ENUM_SINGLE_DECL(wm8940_mic_bias_level_enum, |
168 | = SOC_ENUM_SINGLE(WM8940_INPUTCTL, 8, 2, wm8940_mic_bias_level_text); | 168 | WM8940_INPUTCTL, 8, wm8940_mic_bias_level_text); |
169 | 169 | ||
170 | static const char *wm8940_filter_mode_text[] = {"Audio", "Application"}; | 170 | static const char *wm8940_filter_mode_text[] = {"Audio", "Application"}; |
171 | static const struct soc_enum wm8940_filter_mode_enum | 171 | static SOC_ENUM_SINGLE_DECL(wm8940_filter_mode_enum, |
172 | = SOC_ENUM_SINGLE(WM8940_ADC, 7, 2, wm8940_filter_mode_text); | 172 | WM8940_ADC, 7, wm8940_filter_mode_text); |
173 | 173 | ||
174 | static DECLARE_TLV_DB_SCALE(wm8940_spk_vol_tlv, -5700, 100, 1); | 174 | static DECLARE_TLV_DB_SCALE(wm8940_spk_vol_tlv, -5700, 100, 1); |
175 | static DECLARE_TLV_DB_SCALE(wm8940_att_tlv, -1000, 1000, 0); | 175 | static DECLARE_TLV_DB_SCALE(wm8940_att_tlv, -1000, 1000, 0); |
@@ -712,12 +712,6 @@ static int wm8940_probe(struct snd_soc_codec *codec) | |||
712 | int ret; | 712 | int ret; |
713 | u16 reg; | 713 | u16 reg; |
714 | 714 | ||
715 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
716 | if (ret < 0) { | ||
717 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | ret = wm8940_reset(codec); | 715 | ret = wm8940_reset(codec); |
722 | if (ret < 0) { | 716 | if (ret < 0) { |
723 | dev_err(codec->dev, "Failed to issue reset\n"); | 717 | dev_err(codec->dev, "Failed to issue reset\n"); |
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 82c8ba975720..fecd4e4f4c57 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -416,22 +416,21 @@ static const char *bass_mode_text[] = { | |||
416 | "Linear", "Adaptive", | 416 | "Linear", "Adaptive", |
417 | }; | 417 | }; |
418 | 418 | ||
419 | static const struct soc_enum bass_mode = | 419 | static SOC_ENUM_SINGLE_DECL(bass_mode, WM8955_BASS_CONTROL, 7, bass_mode_text); |
420 | SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 7, 2, bass_mode_text); | ||
421 | 420 | ||
422 | static const char *bass_cutoff_text[] = { | 421 | static const char *bass_cutoff_text[] = { |
423 | "Low", "High" | 422 | "Low", "High" |
424 | }; | 423 | }; |
425 | 424 | ||
426 | static const struct soc_enum bass_cutoff = | 425 | static SOC_ENUM_SINGLE_DECL(bass_cutoff, WM8955_BASS_CONTROL, 6, |
427 | SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 6, 2, bass_cutoff_text); | 426 | bass_cutoff_text); |
428 | 427 | ||
429 | static const char *treble_cutoff_text[] = { | 428 | static const char *treble_cutoff_text[] = { |
430 | "High", "Low" | 429 | "High", "Low" |
431 | }; | 430 | }; |
432 | 431 | ||
433 | static const struct soc_enum treble_cutoff = | 432 | static SOC_ENUM_SINGLE_DECL(treble_cutoff, WM8955_TREBLE_CONTROL, 2, |
434 | SOC_ENUM_SINGLE(WM8955_TREBLE_CONTROL, 6, 2, treble_cutoff_text); | 433 | treble_cutoff_text); |
435 | 434 | ||
436 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); | 435 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); |
437 | static const DECLARE_TLV_DB_SCALE(atten_tlv, -600, 600, 0); | 436 | static const DECLARE_TLV_DB_SCALE(atten_tlv, -600, 600, 0); |
@@ -896,14 +895,6 @@ static int wm8955_probe(struct snd_soc_codec *codec) | |||
896 | struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); | 895 | struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); |
897 | int ret, i; | 896 | int ret, i; |
898 | 897 | ||
899 | codec->control_data = wm8955->regmap; | ||
900 | |||
901 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
902 | if (ret != 0) { | ||
903 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
904 | return ret; | ||
905 | } | ||
906 | |||
907 | for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) | 898 | for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) |
908 | wm8955->supplies[i].supply = wm8955_supply_names[i]; | 899 | wm8955->supplies[i].supply = wm8955_supply_names[i]; |
909 | 900 | ||
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index b7488f190d2b..7ac2e511403c 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c | |||
@@ -153,7 +153,7 @@ static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name, | |||
153 | 153 | ||
154 | data32 &= 0xffffff; | 154 | data32 &= 0xffffff; |
155 | 155 | ||
156 | wm8994_bulk_write(codec->control_data, | 156 | wm8994_bulk_write(wm8994->wm8994, |
157 | data32 & 0xffffff, | 157 | data32 & 0xffffff, |
158 | block_len / 2, | 158 | block_len / 2, |
159 | (void *)(data + 8)); | 159 | (void *)(data + 8)); |
@@ -944,7 +944,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
944 | for (i = 0; i < pdata->num_mbc_cfgs; i++) | 944 | for (i = 0; i < pdata->num_mbc_cfgs; i++) |
945 | wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; | 945 | wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; |
946 | 946 | ||
947 | wm8994->mbc_enum.max = pdata->num_mbc_cfgs; | 947 | wm8994->mbc_enum.items = pdata->num_mbc_cfgs; |
948 | wm8994->mbc_enum.texts = wm8994->mbc_texts; | 948 | wm8994->mbc_enum.texts = wm8994->mbc_texts; |
949 | 949 | ||
950 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, | 950 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
@@ -973,7 +973,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
973 | for (i = 0; i < pdata->num_vss_cfgs; i++) | 973 | for (i = 0; i < pdata->num_vss_cfgs; i++) |
974 | wm8994->vss_texts[i] = pdata->vss_cfgs[i].name; | 974 | wm8994->vss_texts[i] = pdata->vss_cfgs[i].name; |
975 | 975 | ||
976 | wm8994->vss_enum.max = pdata->num_vss_cfgs; | 976 | wm8994->vss_enum.items = pdata->num_vss_cfgs; |
977 | wm8994->vss_enum.texts = wm8994->vss_texts; | 977 | wm8994->vss_enum.texts = wm8994->vss_texts; |
978 | 978 | ||
979 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, | 979 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
@@ -1003,7 +1003,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
1003 | for (i = 0; i < pdata->num_vss_hpf_cfgs; i++) | 1003 | for (i = 0; i < pdata->num_vss_hpf_cfgs; i++) |
1004 | wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name; | 1004 | wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name; |
1005 | 1005 | ||
1006 | wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; | 1006 | wm8994->vss_hpf_enum.items = pdata->num_vss_hpf_cfgs; |
1007 | wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; | 1007 | wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; |
1008 | 1008 | ||
1009 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, | 1009 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
@@ -1034,7 +1034,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
1034 | for (i = 0; i < pdata->num_enh_eq_cfgs; i++) | 1034 | for (i = 0; i < pdata->num_enh_eq_cfgs; i++) |
1035 | wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name; | 1035 | wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name; |
1036 | 1036 | ||
1037 | wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; | 1037 | wm8994->enh_eq_enum.items = pdata->num_enh_eq_cfgs; |
1038 | wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; | 1038 | wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; |
1039 | 1039 | ||
1040 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, | 1040 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index f156010e52bc..d04e9cad445c 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -976,12 +976,6 @@ static int wm8960_probe(struct snd_soc_codec *codec) | |||
976 | wm8960->set_bias_level = wm8960_set_bias_level_capless; | 976 | wm8960->set_bias_level = wm8960_set_bias_level_capless; |
977 | } | 977 | } |
978 | 978 | ||
979 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
980 | if (ret < 0) { | ||
981 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
982 | return ret; | ||
983 | } | ||
984 | |||
985 | ret = wm8960_reset(codec); | 979 | ret = wm8960_reset(codec); |
986 | if (ret < 0) { | 980 | if (ret < 0) { |
987 | dev_err(codec->dev, "Failed to issue reset\n"); | 981 | dev_err(codec->dev, "Failed to issue reset\n"); |
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 900328e28a15..9c88f04442b3 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -317,15 +317,15 @@ static const char *adc_hpf_text[] = { | |||
317 | "Hi-fi", "Voice 1", "Voice 2", "Voice 3", | 317 | "Hi-fi", "Voice 1", "Voice 2", "Voice 3", |
318 | }; | 318 | }; |
319 | 319 | ||
320 | static const struct soc_enum adc_hpf = | 320 | static SOC_ENUM_SINGLE_DECL(adc_hpf, |
321 | SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_2, 7, 4, adc_hpf_text); | 321 | WM8961_ADC_DAC_CONTROL_2, 7, adc_hpf_text); |
322 | 322 | ||
323 | static const char *dac_deemph_text[] = { | 323 | static const char *dac_deemph_text[] = { |
324 | "None", "32kHz", "44.1kHz", "48kHz", | 324 | "None", "32kHz", "44.1kHz", "48kHz", |
325 | }; | 325 | }; |
326 | 326 | ||
327 | static const struct soc_enum dac_deemph = | 327 | static SOC_ENUM_SINGLE_DECL(dac_deemph, |
328 | SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_1, 1, 4, dac_deemph_text); | 328 | WM8961_ADC_DAC_CONTROL_1, 1, dac_deemph_text); |
329 | 329 | ||
330 | static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); | 330 | static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); |
331 | static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0); | 331 | static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0); |
@@ -385,11 +385,11 @@ static const char *sidetone_text[] = { | |||
385 | "None", "Left", "Right" | 385 | "None", "Left", "Right" |
386 | }; | 386 | }; |
387 | 387 | ||
388 | static const struct soc_enum dacl_sidetone = | 388 | static SOC_ENUM_SINGLE_DECL(dacl_sidetone, |
389 | SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_0, 2, 3, sidetone_text); | 389 | WM8961_DSP_SIDETONE_0, 2, sidetone_text); |
390 | 390 | ||
391 | static const struct soc_enum dacr_sidetone = | 391 | static SOC_ENUM_SINGLE_DECL(dacr_sidetone, |
392 | SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_1, 2, 3, sidetone_text); | 392 | WM8961_DSP_SIDETONE_1, 2, sidetone_text); |
393 | 393 | ||
394 | static const struct snd_kcontrol_new dacl_mux = | 394 | static const struct snd_kcontrol_new dacl_mux = |
395 | SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone); | 395 | SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone); |
@@ -836,15 +836,8 @@ static struct snd_soc_dai_driver wm8961_dai = { | |||
836 | static int wm8961_probe(struct snd_soc_codec *codec) | 836 | static int wm8961_probe(struct snd_soc_codec *codec) |
837 | { | 837 | { |
838 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 838 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
839 | int ret = 0; | ||
840 | u16 reg; | 839 | u16 reg; |
841 | 840 | ||
842 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
843 | if (ret != 0) { | ||
844 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
845 | return ret; | ||
846 | } | ||
847 | |||
848 | /* Enable class W */ | 841 | /* Enable class W */ |
849 | reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); | 842 | reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); |
850 | reg |= WM8961_CP_DYN_PWR_MASK; | 843 | reg |= WM8961_CP_DYN_PWR_MASK; |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 97db3b45b411..5522d2566c67 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -1479,7 +1479,9 @@ static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | |||
1479 | 1479 | ||
1480 | static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) | 1480 | static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) |
1481 | { | 1481 | { |
1482 | return regcache_sync_region(codec->control_data, | 1482 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
1483 | |||
1484 | return regcache_sync_region(wm8962->regmap, | ||
1483 | WM8962_HDBASS_AI_1, WM8962_MAX_REGISTER); | 1485 | WM8962_HDBASS_AI_1, WM8962_MAX_REGISTER); |
1484 | } | 1486 | } |
1485 | 1487 | ||
@@ -1658,16 +1660,16 @@ static const char *cap_hpf_mode_text[] = { | |||
1658 | "Hi-fi", "Application" | 1660 | "Hi-fi", "Application" |
1659 | }; | 1661 | }; |
1660 | 1662 | ||
1661 | static const struct soc_enum cap_hpf_mode = | 1663 | static SOC_ENUM_SINGLE_DECL(cap_hpf_mode, |
1662 | SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); | 1664 | WM8962_ADC_DAC_CONTROL_2, 10, cap_hpf_mode_text); |
1663 | 1665 | ||
1664 | 1666 | ||
1665 | static const char *cap_lhpf_mode_text[] = { | 1667 | static const char *cap_lhpf_mode_text[] = { |
1666 | "LPF", "HPF" | 1668 | "LPF", "HPF" |
1667 | }; | 1669 | }; |
1668 | 1670 | ||
1669 | static const struct soc_enum cap_lhpf_mode = | 1671 | static SOC_ENUM_SINGLE_DECL(cap_lhpf_mode, |
1670 | SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text); | 1672 | WM8962_LHPF1, 1, cap_lhpf_mode_text); |
1671 | 1673 | ||
1672 | static const struct snd_kcontrol_new wm8962_snd_controls[] = { | 1674 | static const struct snd_kcontrol_new wm8962_snd_controls[] = { |
1673 | SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), | 1675 | SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), |
@@ -2014,40 +2016,40 @@ static int dsp2_event(struct snd_soc_dapm_widget *w, | |||
2014 | 2016 | ||
2015 | static const char *st_text[] = { "None", "Left", "Right" }; | 2017 | static const char *st_text[] = { "None", "Left", "Right" }; |
2016 | 2018 | ||
2017 | static const struct soc_enum str_enum = | 2019 | static SOC_ENUM_SINGLE_DECL(str_enum, |
2018 | SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text); | 2020 | WM8962_DAC_DSP_MIXING_1, 2, st_text); |
2019 | 2021 | ||
2020 | static const struct snd_kcontrol_new str_mux = | 2022 | static const struct snd_kcontrol_new str_mux = |
2021 | SOC_DAPM_ENUM("Right Sidetone", str_enum); | 2023 | SOC_DAPM_ENUM("Right Sidetone", str_enum); |
2022 | 2024 | ||
2023 | static const struct soc_enum stl_enum = | 2025 | static SOC_ENUM_SINGLE_DECL(stl_enum, |
2024 | SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_2, 2, 3, st_text); | 2026 | WM8962_DAC_DSP_MIXING_2, 2, st_text); |
2025 | 2027 | ||
2026 | static const struct snd_kcontrol_new stl_mux = | 2028 | static const struct snd_kcontrol_new stl_mux = |
2027 | SOC_DAPM_ENUM("Left Sidetone", stl_enum); | 2029 | SOC_DAPM_ENUM("Left Sidetone", stl_enum); |
2028 | 2030 | ||
2029 | static const char *outmux_text[] = { "DAC", "Mixer" }; | 2031 | static const char *outmux_text[] = { "DAC", "Mixer" }; |
2030 | 2032 | ||
2031 | static const struct soc_enum spkoutr_enum = | 2033 | static SOC_ENUM_SINGLE_DECL(spkoutr_enum, |
2032 | SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_2, 7, 2, outmux_text); | 2034 | WM8962_SPEAKER_MIXER_2, 7, outmux_text); |
2033 | 2035 | ||
2034 | static const struct snd_kcontrol_new spkoutr_mux = | 2036 | static const struct snd_kcontrol_new spkoutr_mux = |
2035 | SOC_DAPM_ENUM("SPKOUTR Mux", spkoutr_enum); | 2037 | SOC_DAPM_ENUM("SPKOUTR Mux", spkoutr_enum); |
2036 | 2038 | ||
2037 | static const struct soc_enum spkoutl_enum = | 2039 | static SOC_ENUM_SINGLE_DECL(spkoutl_enum, |
2038 | SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_1, 7, 2, outmux_text); | 2040 | WM8962_SPEAKER_MIXER_1, 7, outmux_text); |
2039 | 2041 | ||
2040 | static const struct snd_kcontrol_new spkoutl_mux = | 2042 | static const struct snd_kcontrol_new spkoutl_mux = |
2041 | SOC_DAPM_ENUM("SPKOUTL Mux", spkoutl_enum); | 2043 | SOC_DAPM_ENUM("SPKOUTL Mux", spkoutl_enum); |
2042 | 2044 | ||
2043 | static const struct soc_enum hpoutr_enum = | 2045 | static SOC_ENUM_SINGLE_DECL(hpoutr_enum, |
2044 | SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_2, 7, 2, outmux_text); | 2046 | WM8962_HEADPHONE_MIXER_2, 7, outmux_text); |
2045 | 2047 | ||
2046 | static const struct snd_kcontrol_new hpoutr_mux = | 2048 | static const struct snd_kcontrol_new hpoutr_mux = |
2047 | SOC_DAPM_ENUM("HPOUTR Mux", hpoutr_enum); | 2049 | SOC_DAPM_ENUM("HPOUTR Mux", hpoutr_enum); |
2048 | 2050 | ||
2049 | static const struct soc_enum hpoutl_enum = | 2051 | static SOC_ENUM_SINGLE_DECL(hpoutl_enum, |
2050 | SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_1, 7, 2, outmux_text); | 2052 | WM8962_HEADPHONE_MIXER_1, 7, outmux_text); |
2051 | 2053 | ||
2052 | static const struct snd_kcontrol_new hpoutl_mux = | 2054 | static const struct snd_kcontrol_new hpoutl_mux = |
2053 | SOC_DAPM_ENUM("HPOUTL Mux", hpoutl_enum); | 2055 | SOC_DAPM_ENUM("HPOUTL Mux", hpoutl_enum); |
@@ -2884,9 +2886,13 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2884 | snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda); | 2886 | snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda); |
2885 | snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n); | 2887 | snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n); |
2886 | 2888 | ||
2887 | try_wait_for_completion(&wm8962->fll_lock); | 2889 | reinit_completion(&wm8962->fll_lock); |
2888 | 2890 | ||
2889 | pm_runtime_get_sync(codec->dev); | 2891 | ret = pm_runtime_get_sync(codec->dev); |
2892 | if (ret < 0) { | ||
2893 | dev_err(codec->dev, "Failed to resume device: %d\n", ret); | ||
2894 | return ret; | ||
2895 | } | ||
2890 | 2896 | ||
2891 | snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, | 2897 | snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, |
2892 | WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK | | 2898 | WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK | |
@@ -2894,8 +2900,6 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2894 | 2900 | ||
2895 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); | 2901 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); |
2896 | 2902 | ||
2897 | ret = 0; | ||
2898 | |||
2899 | /* This should be a massive overestimate but go even | 2903 | /* This should be a massive overestimate but go even |
2900 | * higher if we'll error out | 2904 | * higher if we'll error out |
2901 | */ | 2905 | */ |
@@ -2909,14 +2913,17 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2909 | 2913 | ||
2910 | if (timeout == 0 && wm8962->irq) { | 2914 | if (timeout == 0 && wm8962->irq) { |
2911 | dev_err(codec->dev, "FLL lock timed out"); | 2915 | dev_err(codec->dev, "FLL lock timed out"); |
2912 | ret = -ETIMEDOUT; | 2916 | snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, |
2917 | WM8962_FLL_ENA, 0); | ||
2918 | pm_runtime_put(codec->dev); | ||
2919 | return -ETIMEDOUT; | ||
2913 | } | 2920 | } |
2914 | 2921 | ||
2915 | wm8962->fll_fref = Fref; | 2922 | wm8962->fll_fref = Fref; |
2916 | wm8962->fll_fout = Fout; | 2923 | wm8962->fll_fout = Fout; |
2917 | wm8962->fll_src = source; | 2924 | wm8962->fll_src = source; |
2918 | 2925 | ||
2919 | return ret; | 2926 | return 0; |
2920 | } | 2927 | } |
2921 | 2928 | ||
2922 | static int wm8962_mute(struct snd_soc_dai *dai, int mute) | 2929 | static int wm8962_mute(struct snd_soc_dai *dai, int mute) |
@@ -3003,9 +3010,16 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3003 | unsigned int active; | 3010 | unsigned int active; |
3004 | int reg, ret; | 3011 | int reg, ret; |
3005 | 3012 | ||
3013 | ret = pm_runtime_get_sync(dev); | ||
3014 | if (ret < 0) { | ||
3015 | dev_err(dev, "Failed to resume: %d\n", ret); | ||
3016 | return IRQ_NONE; | ||
3017 | } | ||
3018 | |||
3006 | ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK, | 3019 | ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK, |
3007 | &mask); | 3020 | &mask); |
3008 | if (ret != 0) { | 3021 | if (ret != 0) { |
3022 | pm_runtime_put(dev); | ||
3009 | dev_err(dev, "Failed to read interrupt mask: %d\n", | 3023 | dev_err(dev, "Failed to read interrupt mask: %d\n", |
3010 | ret); | 3024 | ret); |
3011 | return IRQ_NONE; | 3025 | return IRQ_NONE; |
@@ -3013,14 +3027,17 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3013 | 3027 | ||
3014 | ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active); | 3028 | ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active); |
3015 | if (ret != 0) { | 3029 | if (ret != 0) { |
3030 | pm_runtime_put(dev); | ||
3016 | dev_err(dev, "Failed to read interrupt: %d\n", ret); | 3031 | dev_err(dev, "Failed to read interrupt: %d\n", ret); |
3017 | return IRQ_NONE; | 3032 | return IRQ_NONE; |
3018 | } | 3033 | } |
3019 | 3034 | ||
3020 | active &= ~mask; | 3035 | active &= ~mask; |
3021 | 3036 | ||
3022 | if (!active) | 3037 | if (!active) { |
3038 | pm_runtime_put(dev); | ||
3023 | return IRQ_NONE; | 3039 | return IRQ_NONE; |
3040 | } | ||
3024 | 3041 | ||
3025 | /* Acknowledge the interrupts */ | 3042 | /* Acknowledge the interrupts */ |
3026 | ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active); | 3043 | ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active); |
@@ -3070,6 +3087,8 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3070 | msecs_to_jiffies(250)); | 3087 | msecs_to_jiffies(250)); |
3071 | } | 3088 | } |
3072 | 3089 | ||
3090 | pm_runtime_put(dev); | ||
3091 | |||
3073 | return IRQ_HANDLED; | 3092 | return IRQ_HANDLED; |
3074 | } | 3093 | } |
3075 | 3094 | ||
@@ -3089,6 +3108,7 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3089 | int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | 3108 | int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) |
3090 | { | 3109 | { |
3091 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3110 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3111 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
3092 | int irq_mask, enable; | 3112 | int irq_mask, enable; |
3093 | 3113 | ||
3094 | wm8962->jack = jack; | 3114 | wm8962->jack = jack; |
@@ -3109,14 +3129,18 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | |||
3109 | snd_soc_jack_report(wm8962->jack, 0, | 3129 | snd_soc_jack_report(wm8962->jack, 0, |
3110 | SND_JACK_MICROPHONE | SND_JACK_BTN_0); | 3130 | SND_JACK_MICROPHONE | SND_JACK_BTN_0); |
3111 | 3131 | ||
3132 | snd_soc_dapm_mutex_lock(dapm); | ||
3133 | |||
3112 | if (jack) { | 3134 | if (jack) { |
3113 | snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); | 3135 | snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK"); |
3114 | snd_soc_dapm_force_enable_pin(&codec->dapm, "MICBIAS"); | 3136 | snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS"); |
3115 | } else { | 3137 | } else { |
3116 | snd_soc_dapm_disable_pin(&codec->dapm, "SYSCLK"); | 3138 | snd_soc_dapm_disable_pin_unlocked(dapm, "SYSCLK"); |
3117 | snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS"); | 3139 | snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS"); |
3118 | } | 3140 | } |
3119 | 3141 | ||
3142 | snd_soc_dapm_mutex_unlock(dapm); | ||
3143 | |||
3120 | return 0; | 3144 | return 0; |
3121 | } | 3145 | } |
3122 | EXPORT_SYMBOL_GPL(wm8962_mic_detect); | 3146 | EXPORT_SYMBOL_GPL(wm8962_mic_detect); |
@@ -3400,13 +3424,6 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3400 | bool dmicclk, dmicdat; | 3424 | bool dmicclk, dmicdat; |
3401 | 3425 | ||
3402 | wm8962->codec = codec; | 3426 | wm8962->codec = codec; |
3403 | codec->control_data = wm8962->regmap; | ||
3404 | |||
3405 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | ||
3406 | if (ret != 0) { | ||
3407 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
3408 | return ret; | ||
3409 | } | ||
3410 | 3427 | ||
3411 | wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0; | 3428 | wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0; |
3412 | wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1; | 3429 | wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1; |
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 67aba78a7ca5..09b7b4200221 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -648,12 +648,6 @@ static int wm8971_probe(struct snd_soc_codec *codec) | |||
648 | int ret = 0; | 648 | int ret = 0; |
649 | u16 reg; | 649 | u16 reg; |
650 | 650 | ||
651 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
652 | if (ret < 0) { | ||
653 | printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); | ||
654 | return ret; | ||
655 | } | ||
656 | |||
657 | INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8971_work); | 651 | INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8971_work); |
658 | wm8971_workq = create_workqueue("wm8971"); | 652 | wm8971_workq = create_workqueue("wm8971"); |
659 | if (wm8971_workq == NULL) | 653 | if (wm8971_workq == NULL) |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 15f45c7bd833..0627c56fa44e 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -84,8 +84,8 @@ static const struct soc_enum wm8974_enum[] = { | |||
84 | 84 | ||
85 | static const char *wm8974_auxmode_text[] = { "Buffer", "Mixer" }; | 85 | static const char *wm8974_auxmode_text[] = { "Buffer", "Mixer" }; |
86 | 86 | ||
87 | static const struct soc_enum wm8974_auxmode = | 87 | static SOC_ENUM_SINGLE_DECL(wm8974_auxmode, |
88 | SOC_ENUM_SINGLE(WM8974_INPUT, 3, 2, wm8974_auxmode_text); | 88 | WM8974_INPUT, 3, wm8974_auxmode_text); |
89 | 89 | ||
90 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); | 90 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); |
91 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 91 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
@@ -593,12 +593,6 @@ static int wm8974_probe(struct snd_soc_codec *codec) | |||
593 | { | 593 | { |
594 | int ret = 0; | 594 | int ret = 0; |
595 | 595 | ||
596 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
597 | if (ret < 0) { | ||
598 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
599 | return ret; | ||
600 | } | ||
601 | |||
602 | ret = wm8974_reset(codec); | 596 | ret = wm8974_reset(codec); |
603 | if (ret < 0) { | 597 | if (ret < 0) { |
604 | dev_err(codec->dev, "Failed to issue reset\n"); | 598 | dev_err(codec->dev, "Failed to issue reset\n"); |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index d8fc531c0e59..28ef46c91f62 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -117,21 +117,21 @@ static const char *wm8978_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz"}; | |||
117 | static const char *wm8978_alc3[] = {"ALC", "Limiter"}; | 117 | static const char *wm8978_alc3[] = {"ALC", "Limiter"}; |
118 | static const char *wm8978_alc1[] = {"Off", "Right", "Left", "Both"}; | 118 | static const char *wm8978_alc1[] = {"Off", "Right", "Left", "Both"}; |
119 | 119 | ||
120 | static const SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1, | 120 | static SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1, |
121 | wm8978_companding); | 121 | wm8978_companding); |
122 | static const SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3, | 122 | static SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3, |
123 | wm8978_companding); | 123 | wm8978_companding); |
124 | static const SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode); | 124 | static SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode); |
125 | static const SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1); | 125 | static SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1); |
126 | static const SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw); | 126 | static SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw); |
127 | static const SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2); | 127 | static SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2); |
128 | static const SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw); | 128 | static SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw); |
129 | static const SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3); | 129 | static SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3); |
130 | static const SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw); | 130 | static SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw); |
131 | static const SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4); | 131 | static SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4); |
132 | static const SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5); | 132 | static SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5); |
133 | static const SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3); | 133 | static SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3); |
134 | static const SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1); | 134 | static SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1); |
135 | 135 | ||
136 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); | 136 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); |
137 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 137 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
@@ -975,19 +975,13 @@ static const int update_reg[] = { | |||
975 | static int wm8978_probe(struct snd_soc_codec *codec) | 975 | static int wm8978_probe(struct snd_soc_codec *codec) |
976 | { | 976 | { |
977 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); | 977 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); |
978 | int ret = 0, i; | 978 | int i; |
979 | 979 | ||
980 | /* | 980 | /* |
981 | * Set default system clock to PLL, it is more precise, this is also the | 981 | * Set default system clock to PLL, it is more precise, this is also the |
982 | * default hardware setting | 982 | * default hardware setting |
983 | */ | 983 | */ |
984 | wm8978->sysclk = WM8978_PLL; | 984 | wm8978->sysclk = WM8978_PLL; |
985 | codec->control_data = wm8978->regmap; | ||
986 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
987 | if (ret < 0) { | ||
988 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
989 | return ret; | ||
990 | } | ||
991 | 985 | ||
992 | /* | 986 | /* |
993 | * Set the update bit in all registers, that have one. This way all | 987 | * Set the update bit in all registers, that have one. This way all |
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index aa41ba0dfff4..2b9bfa53efbf 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c | |||
@@ -205,49 +205,44 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); | |||
205 | static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); | 205 | static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); |
206 | 206 | ||
207 | static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; | 207 | static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; |
208 | static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7, | 208 | static SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7, alc_sel_text); |
209 | alc_sel_text); | ||
210 | 209 | ||
211 | static const char *alc_mode_text[] = { "ALC", "Limiter" }; | 210 | static const char *alc_mode_text[] = { "ALC", "Limiter" }; |
212 | static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, | 211 | static SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, alc_mode_text); |
213 | alc_mode_text); | ||
214 | 212 | ||
215 | static const char *filter_mode_text[] = { "Audio", "Application" }; | 213 | static const char *filter_mode_text[] = { "Audio", "Application" }; |
216 | static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7, | 214 | static SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7, |
217 | filter_mode_text); | 215 | filter_mode_text); |
218 | 216 | ||
219 | static const char *eq_bw_text[] = { "Narrow", "Wide" }; | 217 | static const char *eq_bw_text[] = { "Narrow", "Wide" }; |
220 | static const char *eqmode_text[] = { "Capture", "Playback" }; | 218 | static const char *eqmode_text[] = { "Capture", "Playback" }; |
221 | static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); | 219 | static SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); |
222 | 220 | ||
223 | static const char *eq1_cutoff_text[] = { | 221 | static const char *eq1_cutoff_text[] = { |
224 | "80Hz", "105Hz", "135Hz", "175Hz" | 222 | "80Hz", "105Hz", "135Hz", "175Hz" |
225 | }; | 223 | }; |
226 | static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5, | 224 | static SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5, |
227 | eq1_cutoff_text); | 225 | eq1_cutoff_text); |
228 | static const char *eq2_cutoff_text[] = { | 226 | static const char *eq2_cutoff_text[] = { |
229 | "230Hz", "300Hz", "385Hz", "500Hz" | 227 | "230Hz", "300Hz", "385Hz", "500Hz" |
230 | }; | 228 | }; |
231 | static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text); | 229 | static SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text); |
232 | static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5, | 230 | static SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5, eq2_cutoff_text); |
233 | eq2_cutoff_text); | ||
234 | static const char *eq3_cutoff_text[] = { | 231 | static const char *eq3_cutoff_text[] = { |
235 | "650Hz", "850Hz", "1.1kHz", "1.4kHz" | 232 | "650Hz", "850Hz", "1.1kHz", "1.4kHz" |
236 | }; | 233 | }; |
237 | static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text); | 234 | static SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text); |
238 | static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5, | 235 | static SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5, eq3_cutoff_text); |
239 | eq3_cutoff_text); | ||
240 | static const char *eq4_cutoff_text[] = { | 236 | static const char *eq4_cutoff_text[] = { |
241 | "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" | 237 | "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" |
242 | }; | 238 | }; |
243 | static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text); | 239 | static SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text); |
244 | static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5, | 240 | static SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5, eq4_cutoff_text); |
245 | eq4_cutoff_text); | ||
246 | static const char *eq5_cutoff_text[] = { | 241 | static const char *eq5_cutoff_text[] = { |
247 | "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" | 242 | "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" |
248 | }; | 243 | }; |
249 | static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5, | 244 | static SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5, |
250 | eq5_cutoff_text); | 245 | eq5_cutoff_text); |
251 | 246 | ||
252 | static const char *depth_3d_text[] = { | 247 | static const char *depth_3d_text[] = { |
253 | "Off", | 248 | "Off", |
@@ -267,8 +262,8 @@ static const char *depth_3d_text[] = { | |||
267 | "93.3%", | 262 | "93.3%", |
268 | "100%" | 263 | "100%" |
269 | }; | 264 | }; |
270 | static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0, | 265 | static SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0, |
271 | depth_3d_text); | 266 | depth_3d_text); |
272 | 267 | ||
273 | static const struct snd_kcontrol_new wm8983_snd_controls[] = { | 268 | static const struct snd_kcontrol_new wm8983_snd_controls[] = { |
274 | SOC_SINGLE("Digital Loopback Switch", WM8983_COMPANDING_CONTROL, | 269 | SOC_SINGLE("Digital Loopback Switch", WM8983_COMPANDING_CONTROL, |
@@ -1000,12 +995,6 @@ static int wm8983_probe(struct snd_soc_codec *codec) | |||
1000 | int ret; | 995 | int ret; |
1001 | int i; | 996 | int i; |
1002 | 997 | ||
1003 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
1004 | if (ret < 0) { | ||
1005 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | ||
1006 | return ret; | ||
1007 | } | ||
1008 | |||
1009 | ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0); | 998 | ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0); |
1010 | if (ret < 0) { | 999 | if (ret < 0) { |
1011 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | 1000 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
@@ -1129,7 +1118,7 @@ static struct spi_driver wm8983_spi_driver = { | |||
1129 | }; | 1118 | }; |
1130 | #endif | 1119 | #endif |
1131 | 1120 | ||
1132 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1121 | #if IS_ENABLED(CONFIG_I2C) |
1133 | static int wm8983_i2c_probe(struct i2c_client *i2c, | 1122 | static int wm8983_i2c_probe(struct i2c_client *i2c, |
1134 | const struct i2c_device_id *id) | 1123 | const struct i2c_device_id *id) |
1135 | { | 1124 | { |
@@ -1182,7 +1171,7 @@ static int __init wm8983_modinit(void) | |||
1182 | { | 1171 | { |
1183 | int ret = 0; | 1172 | int ret = 0; |
1184 | 1173 | ||
1185 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1174 | #if IS_ENABLED(CONFIG_I2C) |
1186 | ret = i2c_add_driver(&wm8983_i2c_driver); | 1175 | ret = i2c_add_driver(&wm8983_i2c_driver); |
1187 | if (ret) { | 1176 | if (ret) { |
1188 | printk(KERN_ERR "Failed to register wm8983 I2C driver: %d\n", | 1177 | printk(KERN_ERR "Failed to register wm8983 I2C driver: %d\n", |
@@ -1202,7 +1191,7 @@ module_init(wm8983_modinit); | |||
1202 | 1191 | ||
1203 | static void __exit wm8983_exit(void) | 1192 | static void __exit wm8983_exit(void) |
1204 | { | 1193 | { |
1205 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1194 | #if IS_ENABLED(CONFIG_I2C) |
1206 | i2c_del_driver(&wm8983_i2c_driver); | 1195 | i2c_del_driver(&wm8983_i2c_driver); |
1207 | #endif | 1196 | #endif |
1208 | #if defined(CONFIG_SPI_MASTER) | 1197 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 271b517911a4..5473dc969585 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c | |||
@@ -226,52 +226,48 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); | |||
226 | static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); | 226 | static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); |
227 | 227 | ||
228 | static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; | 228 | static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; |
229 | static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7, | 229 | static SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7, alc_sel_text); |
230 | alc_sel_text); | ||
231 | 230 | ||
232 | static const char *alc_mode_text[] = { "ALC", "Limiter" }; | 231 | static const char *alc_mode_text[] = { "ALC", "Limiter" }; |
233 | static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8, | 232 | static SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8, alc_mode_text); |
234 | alc_mode_text); | ||
235 | 233 | ||
236 | static const char *filter_mode_text[] = { "Audio", "Application" }; | 234 | static const char *filter_mode_text[] = { "Audio", "Application" }; |
237 | static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7, | 235 | static SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7, |
238 | filter_mode_text); | 236 | filter_mode_text); |
239 | 237 | ||
240 | static const char *eq_bw_text[] = { "Narrow", "Wide" }; | 238 | static const char *eq_bw_text[] = { "Narrow", "Wide" }; |
241 | static const char *eqmode_text[] = { "Capture", "Playback" }; | 239 | static const char *eqmode_text[] = { "Capture", "Playback" }; |
242 | static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); | 240 | static SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); |
243 | 241 | ||
244 | static const char *eq1_cutoff_text[] = { | 242 | static const char *eq1_cutoff_text[] = { |
245 | "80Hz", "105Hz", "135Hz", "175Hz" | 243 | "80Hz", "105Hz", "135Hz", "175Hz" |
246 | }; | 244 | }; |
247 | static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5, | 245 | static SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5, |
248 | eq1_cutoff_text); | 246 | eq1_cutoff_text); |
249 | static const char *eq2_cutoff_text[] = { | 247 | static const char *eq2_cutoff_text[] = { |
250 | "230Hz", "300Hz", "385Hz", "500Hz" | 248 | "230Hz", "300Hz", "385Hz", "500Hz" |
251 | }; | 249 | }; |
252 | static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text); | 250 | static SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text); |
253 | static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5, | 251 | static SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5, eq2_cutoff_text); |
254 | eq2_cutoff_text); | ||
255 | static const char *eq3_cutoff_text[] = { | 252 | static const char *eq3_cutoff_text[] = { |
256 | "650Hz", "850Hz", "1.1kHz", "1.4kHz" | 253 | "650Hz", "850Hz", "1.1kHz", "1.4kHz" |
257 | }; | 254 | }; |
258 | static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text); | 255 | static SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text); |
259 | static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5, | 256 | static SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5, |
260 | eq3_cutoff_text); | 257 | eq3_cutoff_text); |
261 | static const char *eq4_cutoff_text[] = { | 258 | static const char *eq4_cutoff_text[] = { |
262 | "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" | 259 | "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" |
263 | }; | 260 | }; |
264 | static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text); | 261 | static SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text); |
265 | static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5, | 262 | static SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5, eq4_cutoff_text); |
266 | eq4_cutoff_text); | ||
267 | static const char *eq5_cutoff_text[] = { | 263 | static const char *eq5_cutoff_text[] = { |
268 | "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" | 264 | "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" |
269 | }; | 265 | }; |
270 | static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5, | 266 | static SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5, |
271 | eq5_cutoff_text); | 267 | eq5_cutoff_text); |
272 | 268 | ||
273 | static const char *speaker_mode_text[] = { "Class A/B", "Class D" }; | 269 | static const char *speaker_mode_text[] = { "Class A/B", "Class D" }; |
274 | static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text); | 270 | static SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text); |
275 | 271 | ||
276 | static const char *depth_3d_text[] = { | 272 | static const char *depth_3d_text[] = { |
277 | "Off", | 273 | "Off", |
@@ -291,8 +287,7 @@ static const char *depth_3d_text[] = { | |||
291 | "93.3%", | 287 | "93.3%", |
292 | "100%" | 288 | "100%" |
293 | }; | 289 | }; |
294 | static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0, | 290 | static SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0, depth_3d_text); |
295 | depth_3d_text); | ||
296 | 291 | ||
297 | static const struct snd_kcontrol_new wm8985_snd_controls[] = { | 292 | static const struct snd_kcontrol_new wm8985_snd_controls[] = { |
298 | SOC_SINGLE("Digital Loopback Switch", WM8985_COMPANDING_CONTROL, | 293 | SOC_SINGLE("Digital Loopback Switch", WM8985_COMPANDING_CONTROL, |
@@ -1000,13 +995,6 @@ static int wm8985_probe(struct snd_soc_codec *codec) | |||
1000 | int ret; | 995 | int ret; |
1001 | 996 | ||
1002 | wm8985 = snd_soc_codec_get_drvdata(codec); | 997 | wm8985 = snd_soc_codec_get_drvdata(codec); |
1003 | codec->control_data = wm8985->regmap; | ||
1004 | |||
1005 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
1006 | if (ret < 0) { | ||
1007 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | ||
1008 | return ret; | ||
1009 | } | ||
1010 | 998 | ||
1011 | for (i = 0; i < ARRAY_SIZE(wm8985->supplies); i++) | 999 | for (i = 0; i < ARRAY_SIZE(wm8985->supplies); i++) |
1012 | wm8985->supplies[i].supply = wm8985_supply_names[i]; | 1000 | wm8985->supplies[i].supply = wm8985_supply_names[i]; |
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index a55e1c2c382e..3a1ae4f5164d 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c | |||
@@ -116,7 +116,7 @@ static bool wm8988_writeable(struct device *dev, unsigned int reg) | |||
116 | struct wm8988_priv { | 116 | struct wm8988_priv { |
117 | struct regmap *regmap; | 117 | struct regmap *regmap; |
118 | unsigned int sysclk; | 118 | unsigned int sysclk; |
119 | struct snd_pcm_hw_constraint_list *sysclk_constraints; | 119 | const struct snd_pcm_hw_constraint_list *sysclk_constraints; |
120 | }; | 120 | }; |
121 | 121 | ||
122 | #define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0) | 122 | #define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0) |
@@ -126,46 +126,46 @@ struct wm8988_priv { | |||
126 | */ | 126 | */ |
127 | 127 | ||
128 | static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"}; | 128 | static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"}; |
129 | static const struct soc_enum bass_boost = | 129 | static SOC_ENUM_SINGLE_DECL(bass_boost, |
130 | SOC_ENUM_SINGLE(WM8988_BASS, 7, 2, bass_boost_txt); | 130 | WM8988_BASS, 7, bass_boost_txt); |
131 | 131 | ||
132 | static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" }; | 132 | static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" }; |
133 | static const struct soc_enum bass_filter = | 133 | static SOC_ENUM_SINGLE_DECL(bass_filter, |
134 | SOC_ENUM_SINGLE(WM8988_BASS, 6, 2, bass_filter_txt); | 134 | WM8988_BASS, 6, bass_filter_txt); |
135 | 135 | ||
136 | static const char *treble_txt[] = {"8kHz", "4kHz"}; | 136 | static const char *treble_txt[] = {"8kHz", "4kHz"}; |
137 | static const struct soc_enum treble = | 137 | static SOC_ENUM_SINGLE_DECL(treble, |
138 | SOC_ENUM_SINGLE(WM8988_TREBLE, 6, 2, treble_txt); | 138 | WM8988_TREBLE, 6, treble_txt); |
139 | 139 | ||
140 | static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"}; | 140 | static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"}; |
141 | static const struct soc_enum stereo_3d_lc = | 141 | static SOC_ENUM_SINGLE_DECL(stereo_3d_lc, |
142 | SOC_ENUM_SINGLE(WM8988_3D, 5, 2, stereo_3d_lc_txt); | 142 | WM8988_3D, 5, stereo_3d_lc_txt); |
143 | 143 | ||
144 | static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"}; | 144 | static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"}; |
145 | static const struct soc_enum stereo_3d_uc = | 145 | static SOC_ENUM_SINGLE_DECL(stereo_3d_uc, |
146 | SOC_ENUM_SINGLE(WM8988_3D, 6, 2, stereo_3d_uc_txt); | 146 | WM8988_3D, 6, stereo_3d_uc_txt); |
147 | 147 | ||
148 | static const char *stereo_3d_func_txt[] = {"Capture", "Playback"}; | 148 | static const char *stereo_3d_func_txt[] = {"Capture", "Playback"}; |
149 | static const struct soc_enum stereo_3d_func = | 149 | static SOC_ENUM_SINGLE_DECL(stereo_3d_func, |
150 | SOC_ENUM_SINGLE(WM8988_3D, 7, 2, stereo_3d_func_txt); | 150 | WM8988_3D, 7, stereo_3d_func_txt); |
151 | 151 | ||
152 | static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"}; | 152 | static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"}; |
153 | static const struct soc_enum alc_func = | 153 | static SOC_ENUM_SINGLE_DECL(alc_func, |
154 | SOC_ENUM_SINGLE(WM8988_ALC1, 7, 4, alc_func_txt); | 154 | WM8988_ALC1, 7, alc_func_txt); |
155 | 155 | ||
156 | static const char *ng_type_txt[] = {"Constant PGA Gain", | 156 | static const char *ng_type_txt[] = {"Constant PGA Gain", |
157 | "Mute ADC Output"}; | 157 | "Mute ADC Output"}; |
158 | static const struct soc_enum ng_type = | 158 | static SOC_ENUM_SINGLE_DECL(ng_type, |
159 | SOC_ENUM_SINGLE(WM8988_NGATE, 1, 2, ng_type_txt); | 159 | WM8988_NGATE, 1, ng_type_txt); |
160 | 160 | ||
161 | static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"}; | 161 | static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"}; |
162 | static const struct soc_enum deemph = | 162 | static SOC_ENUM_SINGLE_DECL(deemph, |
163 | SOC_ENUM_SINGLE(WM8988_ADCDAC, 1, 4, deemph_txt); | 163 | WM8988_ADCDAC, 1, deemph_txt); |
164 | 164 | ||
165 | static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert", | 165 | static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert", |
166 | "L + R Invert"}; | 166 | "L + R Invert"}; |
167 | static const struct soc_enum adcpol = | 167 | static SOC_ENUM_SINGLE_DECL(adcpol, |
168 | SOC_ENUM_SINGLE(WM8988_ADCDAC, 5, 4, adcpol_txt); | 168 | WM8988_ADCDAC, 5, adcpol_txt); |
169 | 169 | ||
170 | static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0); | 170 | static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0); |
171 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1); | 171 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1); |
@@ -317,16 +317,16 @@ static const struct snd_kcontrol_new wm8988_right_pga_controls = | |||
317 | 317 | ||
318 | /* Differential Mux */ | 318 | /* Differential Mux */ |
319 | static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"}; | 319 | static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"}; |
320 | static const struct soc_enum diffmux = | 320 | static SOC_ENUM_SINGLE_DECL(diffmux, |
321 | SOC_ENUM_SINGLE(WM8988_ADCIN, 8, 2, wm8988_diff_sel); | 321 | WM8988_ADCIN, 8, wm8988_diff_sel); |
322 | static const struct snd_kcontrol_new wm8988_diffmux_controls = | 322 | static const struct snd_kcontrol_new wm8988_diffmux_controls = |
323 | SOC_DAPM_ENUM("Route", diffmux); | 323 | SOC_DAPM_ENUM("Route", diffmux); |
324 | 324 | ||
325 | /* Mono ADC Mux */ | 325 | /* Mono ADC Mux */ |
326 | static const char *wm8988_mono_mux[] = {"Stereo", "Mono (Left)", | 326 | static const char *wm8988_mono_mux[] = {"Stereo", "Mono (Left)", |
327 | "Mono (Right)", "Digital Mono"}; | 327 | "Mono (Right)", "Digital Mono"}; |
328 | static const struct soc_enum monomux = | 328 | static SOC_ENUM_SINGLE_DECL(monomux, |
329 | SOC_ENUM_SINGLE(WM8988_ADCIN, 6, 4, wm8988_mono_mux); | 329 | WM8988_ADCIN, 6, wm8988_mono_mux); |
330 | static const struct snd_kcontrol_new wm8988_monomux_controls = | 330 | static const struct snd_kcontrol_new wm8988_monomux_controls = |
331 | SOC_DAPM_ENUM("Route", monomux); | 331 | SOC_DAPM_ENUM("Route", monomux); |
332 | 332 | ||
@@ -521,30 +521,30 @@ static inline int get_coeff(int mclk, int rate) | |||
521 | 521 | ||
522 | /* The set of rates we can generate from the above for each SYSCLK */ | 522 | /* The set of rates we can generate from the above for each SYSCLK */ |
523 | 523 | ||
524 | static unsigned int rates_12288[] = { | 524 | static const unsigned int rates_12288[] = { |
525 | 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000, | 525 | 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000, |
526 | }; | 526 | }; |
527 | 527 | ||
528 | static struct snd_pcm_hw_constraint_list constraints_12288 = { | 528 | static const struct snd_pcm_hw_constraint_list constraints_12288 = { |
529 | .count = ARRAY_SIZE(rates_12288), | 529 | .count = ARRAY_SIZE(rates_12288), |
530 | .list = rates_12288, | 530 | .list = rates_12288, |
531 | }; | 531 | }; |
532 | 532 | ||
533 | static unsigned int rates_112896[] = { | 533 | static const unsigned int rates_112896[] = { |
534 | 8000, 11025, 22050, 44100, | 534 | 8000, 11025, 22050, 44100, |
535 | }; | 535 | }; |
536 | 536 | ||
537 | static struct snd_pcm_hw_constraint_list constraints_112896 = { | 537 | static const struct snd_pcm_hw_constraint_list constraints_112896 = { |
538 | .count = ARRAY_SIZE(rates_112896), | 538 | .count = ARRAY_SIZE(rates_112896), |
539 | .list = rates_112896, | 539 | .list = rates_112896, |
540 | }; | 540 | }; |
541 | 541 | ||
542 | static unsigned int rates_12[] = { | 542 | static const unsigned int rates_12[] = { |
543 | 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000, | 543 | 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000, |
544 | 48000, 88235, 96000, | 544 | 48000, 88235, 96000, |
545 | }; | 545 | }; |
546 | 546 | ||
547 | static struct snd_pcm_hw_constraint_list constraints_12 = { | 547 | static const struct snd_pcm_hw_constraint_list constraints_12 = { |
548 | .count = ARRAY_SIZE(rates_12), | 548 | .count = ARRAY_SIZE(rates_12), |
549 | .list = rates_12, | 549 | .list = rates_12, |
550 | }; | 550 | }; |
@@ -810,16 +810,8 @@ static int wm8988_resume(struct snd_soc_codec *codec) | |||
810 | 810 | ||
811 | static int wm8988_probe(struct snd_soc_codec *codec) | 811 | static int wm8988_probe(struct snd_soc_codec *codec) |
812 | { | 812 | { |
813 | struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); | ||
814 | int ret = 0; | 813 | int ret = 0; |
815 | 814 | ||
816 | codec->control_data = wm8988->regmap; | ||
817 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
818 | if (ret < 0) { | ||
819 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
820 | return ret; | ||
821 | } | ||
822 | |||
823 | ret = wm8988_reset(codec); | 815 | ret = wm8988_reset(codec); |
824 | if (ret < 0) { | 816 | if (ret < 0) { |
825 | dev_err(codec->dev, "Failed to issue reset\n"); | 817 | dev_err(codec->dev, "Failed to issue reset\n"); |
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 0ccd4d8d043b..c413c1991453 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -157,26 +157,23 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, | |||
157 | static const char *wm8990_digital_sidetone[] = | 157 | static const char *wm8990_digital_sidetone[] = |
158 | {"None", "Left ADC", "Right ADC", "Reserved"}; | 158 | {"None", "Left ADC", "Right ADC", "Reserved"}; |
159 | 159 | ||
160 | static const struct soc_enum wm8990_left_digital_sidetone_enum = | 160 | static SOC_ENUM_SINGLE_DECL(wm8990_left_digital_sidetone_enum, |
161 | SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE, | 161 | WM8990_DIGITAL_SIDE_TONE, |
162 | WM8990_ADC_TO_DACL_SHIFT, | 162 | WM8990_ADC_TO_DACL_SHIFT, |
163 | WM8990_ADC_TO_DACL_MASK, | 163 | wm8990_digital_sidetone); |
164 | wm8990_digital_sidetone); | 164 | |
165 | 165 | static SOC_ENUM_SINGLE_DECL(wm8990_right_digital_sidetone_enum, | |
166 | static const struct soc_enum wm8990_right_digital_sidetone_enum = | 166 | WM8990_DIGITAL_SIDE_TONE, |
167 | SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE, | 167 | WM8990_ADC_TO_DACR_SHIFT, |
168 | WM8990_ADC_TO_DACR_SHIFT, | 168 | wm8990_digital_sidetone); |
169 | WM8990_ADC_TO_DACR_MASK, | ||
170 | wm8990_digital_sidetone); | ||
171 | 169 | ||
172 | static const char *wm8990_adcmode[] = | 170 | static const char *wm8990_adcmode[] = |
173 | {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; | 171 | {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; |
174 | 172 | ||
175 | static const struct soc_enum wm8990_right_adcmode_enum = | 173 | static SOC_ENUM_SINGLE_DECL(wm8990_right_adcmode_enum, |
176 | SOC_ENUM_SINGLE(WM8990_ADC_CTRL, | 174 | WM8990_ADC_CTRL, |
177 | WM8990_ADC_HPF_CUT_SHIFT, | 175 | WM8990_ADC_HPF_CUT_SHIFT, |
178 | WM8990_ADC_HPF_CUT_MASK, | 176 | wm8990_adcmode); |
179 | wm8990_adcmode); | ||
180 | 177 | ||
181 | static const struct snd_kcontrol_new wm8990_snd_controls[] = { | 178 | static const struct snd_kcontrol_new wm8990_snd_controls[] = { |
182 | /* INMIXL */ | 179 | /* INMIXL */ |
@@ -475,9 +472,9 @@ SOC_DAPM_SINGLE("RINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT, | |||
475 | static const char *wm8990_ainlmux[] = | 472 | static const char *wm8990_ainlmux[] = |
476 | {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; | 473 | {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; |
477 | 474 | ||
478 | static const struct soc_enum wm8990_ainlmux_enum = | 475 | static SOC_ENUM_SINGLE_DECL(wm8990_ainlmux_enum, |
479 | SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT, | 476 | WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT, |
480 | ARRAY_SIZE(wm8990_ainlmux), wm8990_ainlmux); | 477 | wm8990_ainlmux); |
481 | 478 | ||
482 | static const struct snd_kcontrol_new wm8990_dapm_ainlmux_controls = | 479 | static const struct snd_kcontrol_new wm8990_dapm_ainlmux_controls = |
483 | SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum); | 480 | SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum); |
@@ -488,9 +485,9 @@ SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum); | |||
488 | static const char *wm8990_ainrmux[] = | 485 | static const char *wm8990_ainrmux[] = |
489 | {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; | 486 | {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; |
490 | 487 | ||
491 | static const struct soc_enum wm8990_ainrmux_enum = | 488 | static SOC_ENUM_SINGLE_DECL(wm8990_ainrmux_enum, |
492 | SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT, | 489 | WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT, |
493 | ARRAY_SIZE(wm8990_ainrmux), wm8990_ainrmux); | 490 | wm8990_ainrmux); |
494 | 491 | ||
495 | static const struct snd_kcontrol_new wm8990_dapm_ainrmux_controls = | 492 | static const struct snd_kcontrol_new wm8990_dapm_ainrmux_controls = |
496 | SOC_DAPM_ENUM("Route", wm8990_ainrmux_enum); | 493 | SOC_DAPM_ENUM("Route", wm8990_ainrmux_enum); |
@@ -1292,14 +1289,6 @@ static int wm8990_resume(struct snd_soc_codec *codec) | |||
1292 | */ | 1289 | */ |
1293 | static int wm8990_probe(struct snd_soc_codec *codec) | 1290 | static int wm8990_probe(struct snd_soc_codec *codec) |
1294 | { | 1291 | { |
1295 | int ret; | ||
1296 | |||
1297 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
1298 | if (ret < 0) { | ||
1299 | printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); | ||
1300 | return ret; | ||
1301 | } | ||
1302 | |||
1303 | wm8990_reset(codec); | 1292 | wm8990_reset(codec); |
1304 | 1293 | ||
1305 | /* charge output caps */ | 1294 | /* charge output caps */ |
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index dba0306c42a5..844cc4a60d66 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c | |||
@@ -171,26 +171,23 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, | |||
171 | static const char *wm8991_digital_sidetone[] = | 171 | static const char *wm8991_digital_sidetone[] = |
172 | {"None", "Left ADC", "Right ADC", "Reserved"}; | 172 | {"None", "Left ADC", "Right ADC", "Reserved"}; |
173 | 173 | ||
174 | static const struct soc_enum wm8991_left_digital_sidetone_enum = | 174 | static SOC_ENUM_SINGLE_DECL(wm8991_left_digital_sidetone_enum, |
175 | SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, | 175 | WM8991_DIGITAL_SIDE_TONE, |
176 | WM8991_ADC_TO_DACL_SHIFT, | 176 | WM8991_ADC_TO_DACL_SHIFT, |
177 | WM8991_ADC_TO_DACL_MASK, | 177 | wm8991_digital_sidetone); |
178 | wm8991_digital_sidetone); | 178 | |
179 | 179 | static SOC_ENUM_SINGLE_DECL(wm8991_right_digital_sidetone_enum, | |
180 | static const struct soc_enum wm8991_right_digital_sidetone_enum = | 180 | WM8991_DIGITAL_SIDE_TONE, |
181 | SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, | 181 | WM8991_ADC_TO_DACR_SHIFT, |
182 | WM8991_ADC_TO_DACR_SHIFT, | 182 | wm8991_digital_sidetone); |
183 | WM8991_ADC_TO_DACR_MASK, | ||
184 | wm8991_digital_sidetone); | ||
185 | 183 | ||
186 | static const char *wm8991_adcmode[] = | 184 | static const char *wm8991_adcmode[] = |
187 | {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; | 185 | {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; |
188 | 186 | ||
189 | static const struct soc_enum wm8991_right_adcmode_enum = | 187 | static SOC_ENUM_SINGLE_DECL(wm8991_right_adcmode_enum, |
190 | SOC_ENUM_SINGLE(WM8991_ADC_CTRL, | 188 | WM8991_ADC_CTRL, |
191 | WM8991_ADC_HPF_CUT_SHIFT, | 189 | WM8991_ADC_HPF_CUT_SHIFT, |
192 | WM8991_ADC_HPF_CUT_MASK, | 190 | wm8991_adcmode); |
193 | wm8991_adcmode); | ||
194 | 191 | ||
195 | static const struct snd_kcontrol_new wm8991_snd_controls[] = { | 192 | static const struct snd_kcontrol_new wm8991_snd_controls[] = { |
196 | /* INMIXL */ | 193 | /* INMIXL */ |
@@ -486,9 +483,9 @@ static const struct snd_kcontrol_new wm8991_dapm_inmixr_controls[] = { | |||
486 | static const char *wm8991_ainlmux[] = | 483 | static const char *wm8991_ainlmux[] = |
487 | {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; | 484 | {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; |
488 | 485 | ||
489 | static const struct soc_enum wm8991_ainlmux_enum = | 486 | static SOC_ENUM_SINGLE_DECL(wm8991_ainlmux_enum, |
490 | SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, | 487 | WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, |
491 | ARRAY_SIZE(wm8991_ainlmux), wm8991_ainlmux); | 488 | wm8991_ainlmux); |
492 | 489 | ||
493 | static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = | 490 | static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = |
494 | SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum); | 491 | SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum); |
@@ -499,9 +496,9 @@ static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = | |||
499 | static const char *wm8991_ainrmux[] = | 496 | static const char *wm8991_ainrmux[] = |
500 | {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; | 497 | {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; |
501 | 498 | ||
502 | static const struct soc_enum wm8991_ainrmux_enum = | 499 | static SOC_ENUM_SINGLE_DECL(wm8991_ainrmux_enum, |
503 | SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, | 500 | WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, |
504 | ARRAY_SIZE(wm8991_ainrmux), wm8991_ainrmux); | 501 | wm8991_ainrmux); |
505 | 502 | ||
506 | static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls = | 503 | static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls = |
507 | SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum); | 504 | SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum); |
@@ -1251,17 +1248,6 @@ static int wm8991_remove(struct snd_soc_codec *codec) | |||
1251 | 1248 | ||
1252 | static int wm8991_probe(struct snd_soc_codec *codec) | 1249 | static int wm8991_probe(struct snd_soc_codec *codec) |
1253 | { | 1250 | { |
1254 | struct wm8991_priv *wm8991; | ||
1255 | int ret; | ||
1256 | |||
1257 | wm8991 = snd_soc_codec_get_drvdata(codec); | ||
1258 | |||
1259 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
1260 | if (ret < 0) { | ||
1261 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | ||
1262 | return ret; | ||
1263 | } | ||
1264 | |||
1265 | wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1251 | wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1266 | 1252 | ||
1267 | return 0; | 1253 | return 0; |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 433d59a0f3ef..f825dc04ebe1 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -646,8 +646,8 @@ static const char *dac_deemph_text[] = { | |||
646 | "48kHz", | 646 | "48kHz", |
647 | }; | 647 | }; |
648 | 648 | ||
649 | static const struct soc_enum dac_deemph = | 649 | static SOC_ENUM_SINGLE_DECL(dac_deemph, |
650 | SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text); | 650 | WM8993_DAC_CTRL, 4, dac_deemph_text); |
651 | 651 | ||
652 | static const char *adc_hpf_text[] = { | 652 | static const char *adc_hpf_text[] = { |
653 | "Hi-Fi", | 653 | "Hi-Fi", |
@@ -656,16 +656,16 @@ static const char *adc_hpf_text[] = { | |||
656 | "Voice 3", | 656 | "Voice 3", |
657 | }; | 657 | }; |
658 | 658 | ||
659 | static const struct soc_enum adc_hpf = | 659 | static SOC_ENUM_SINGLE_DECL(adc_hpf, |
660 | SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text); | 660 | WM8993_ADC_CTRL, 5, adc_hpf_text); |
661 | 661 | ||
662 | static const char *drc_path_text[] = { | 662 | static const char *drc_path_text[] = { |
663 | "ADC", | 663 | "ADC", |
664 | "DAC" | 664 | "DAC" |
665 | }; | 665 | }; |
666 | 666 | ||
667 | static const struct soc_enum drc_path = | 667 | static SOC_ENUM_SINGLE_DECL(drc_path, |
668 | SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text); | 668 | WM8993_DRC_CONTROL_1, 14, drc_path_text); |
669 | 669 | ||
670 | static const char *drc_r0_text[] = { | 670 | static const char *drc_r0_text[] = { |
671 | "1", | 671 | "1", |
@@ -676,8 +676,8 @@ static const char *drc_r0_text[] = { | |||
676 | "0", | 676 | "0", |
677 | }; | 677 | }; |
678 | 678 | ||
679 | static const struct soc_enum drc_r0 = | 679 | static SOC_ENUM_SINGLE_DECL(drc_r0, |
680 | SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text); | 680 | WM8993_DRC_CONTROL_3, 8, drc_r0_text); |
681 | 681 | ||
682 | static const char *drc_r1_text[] = { | 682 | static const char *drc_r1_text[] = { |
683 | "1", | 683 | "1", |
@@ -687,8 +687,8 @@ static const char *drc_r1_text[] = { | |||
687 | "0", | 687 | "0", |
688 | }; | 688 | }; |
689 | 689 | ||
690 | static const struct soc_enum drc_r1 = | 690 | static SOC_ENUM_SINGLE_DECL(drc_r1, |
691 | SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text); | 691 | WM8993_DRC_CONTROL_4, 13, drc_r1_text); |
692 | 692 | ||
693 | static const char *drc_attack_text[] = { | 693 | static const char *drc_attack_text[] = { |
694 | "Reserved", | 694 | "Reserved", |
@@ -705,8 +705,8 @@ static const char *drc_attack_text[] = { | |||
705 | "185.6ms", | 705 | "185.6ms", |
706 | }; | 706 | }; |
707 | 707 | ||
708 | static const struct soc_enum drc_attack = | 708 | static SOC_ENUM_SINGLE_DECL(drc_attack, |
709 | SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text); | 709 | WM8993_DRC_CONTROL_2, 12, drc_attack_text); |
710 | 710 | ||
711 | static const char *drc_decay_text[] = { | 711 | static const char *drc_decay_text[] = { |
712 | "186ms", | 712 | "186ms", |
@@ -720,16 +720,16 @@ static const char *drc_decay_text[] = { | |||
720 | "47.56ms", | 720 | "47.56ms", |
721 | }; | 721 | }; |
722 | 722 | ||
723 | static const struct soc_enum drc_decay = | 723 | static SOC_ENUM_SINGLE_DECL(drc_decay, |
724 | SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text); | 724 | WM8993_DRC_CONTROL_2, 8, drc_decay_text); |
725 | 725 | ||
726 | static const char *drc_ff_text[] = { | 726 | static const char *drc_ff_text[] = { |
727 | "5 samples", | 727 | "5 samples", |
728 | "9 samples", | 728 | "9 samples", |
729 | }; | 729 | }; |
730 | 730 | ||
731 | static const struct soc_enum drc_ff = | 731 | static SOC_ENUM_SINGLE_DECL(drc_ff, |
732 | SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text); | 732 | WM8993_DRC_CONTROL_3, 7, drc_ff_text); |
733 | 733 | ||
734 | static const char *drc_qr_rate_text[] = { | 734 | static const char *drc_qr_rate_text[] = { |
735 | "0.725ms", | 735 | "0.725ms", |
@@ -737,8 +737,8 @@ static const char *drc_qr_rate_text[] = { | |||
737 | "5.8ms", | 737 | "5.8ms", |
738 | }; | 738 | }; |
739 | 739 | ||
740 | static const struct soc_enum drc_qr_rate = | 740 | static SOC_ENUM_SINGLE_DECL(drc_qr_rate, |
741 | SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text); | 741 | WM8993_DRC_CONTROL_3, 0, drc_qr_rate_text); |
742 | 742 | ||
743 | static const char *drc_smooth_text[] = { | 743 | static const char *drc_smooth_text[] = { |
744 | "Low", | 744 | "Low", |
@@ -746,8 +746,8 @@ static const char *drc_smooth_text[] = { | |||
746 | "High", | 746 | "High", |
747 | }; | 747 | }; |
748 | 748 | ||
749 | static const struct soc_enum drc_smooth = | 749 | static SOC_ENUM_SINGLE_DECL(drc_smooth, |
750 | SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text); | 750 | WM8993_DRC_CONTROL_1, 4, drc_smooth_text); |
751 | 751 | ||
752 | static const struct snd_kcontrol_new wm8993_snd_controls[] = { | 752 | static const struct snd_kcontrol_new wm8993_snd_controls[] = { |
753 | SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE, | 753 | SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE, |
@@ -841,26 +841,26 @@ static const char *aif_text[] = { | |||
841 | "Left", "Right" | 841 | "Left", "Right" |
842 | }; | 842 | }; |
843 | 843 | ||
844 | static const struct soc_enum aifoutl_enum = | 844 | static SOC_ENUM_SINGLE_DECL(aifoutl_enum, |
845 | SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 15, 2, aif_text); | 845 | WM8993_AUDIO_INTERFACE_1, 15, aif_text); |
846 | 846 | ||
847 | static const struct snd_kcontrol_new aifoutl_mux = | 847 | static const struct snd_kcontrol_new aifoutl_mux = |
848 | SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); | 848 | SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); |
849 | 849 | ||
850 | static const struct soc_enum aifoutr_enum = | 850 | static SOC_ENUM_SINGLE_DECL(aifoutr_enum, |
851 | SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 14, 2, aif_text); | 851 | WM8993_AUDIO_INTERFACE_1, 14, aif_text); |
852 | 852 | ||
853 | static const struct snd_kcontrol_new aifoutr_mux = | 853 | static const struct snd_kcontrol_new aifoutr_mux = |
854 | SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); | 854 | SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); |
855 | 855 | ||
856 | static const struct soc_enum aifinl_enum = | 856 | static SOC_ENUM_SINGLE_DECL(aifinl_enum, |
857 | SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text); | 857 | WM8993_AUDIO_INTERFACE_2, 15, aif_text); |
858 | 858 | ||
859 | static const struct snd_kcontrol_new aifinl_mux = | 859 | static const struct snd_kcontrol_new aifinl_mux = |
860 | SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); | 860 | SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); |
861 | 861 | ||
862 | static const struct soc_enum aifinr_enum = | 862 | static SOC_ENUM_SINGLE_DECL(aifinr_enum, |
863 | SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text); | 863 | WM8993_AUDIO_INTERFACE_2, 14, aif_text); |
864 | 864 | ||
865 | static const struct snd_kcontrol_new aifinr_mux = | 865 | static const struct snd_kcontrol_new aifinr_mux = |
866 | SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); | 866 | SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); |
@@ -869,14 +869,14 @@ static const char *sidetone_text[] = { | |||
869 | "None", "Left", "Right" | 869 | "None", "Left", "Right" |
870 | }; | 870 | }; |
871 | 871 | ||
872 | static const struct soc_enum sidetonel_enum = | 872 | static SOC_ENUM_SINGLE_DECL(sidetonel_enum, |
873 | SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 2, 3, sidetone_text); | 873 | WM8993_DIGITAL_SIDE_TONE, 2, sidetone_text); |
874 | 874 | ||
875 | static const struct snd_kcontrol_new sidetonel_mux = | 875 | static const struct snd_kcontrol_new sidetonel_mux = |
876 | SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum); | 876 | SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum); |
877 | 877 | ||
878 | static const struct soc_enum sidetoner_enum = | 878 | static SOC_ENUM_SINGLE_DECL(sidetoner_enum, |
879 | SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 0, 3, sidetone_text); | 879 | WM8993_DIGITAL_SIDE_TONE, 0, sidetone_text); |
880 | 880 | ||
881 | static const struct snd_kcontrol_new sidetoner_mux = | 881 | static const struct snd_kcontrol_new sidetoner_mux = |
882 | SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum); | 882 | SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum); |
@@ -1493,13 +1493,6 @@ static int wm8993_probe(struct snd_soc_codec *codec) | |||
1493 | wm8993->hubs_data.dcs_codes_r = -2; | 1493 | wm8993->hubs_data.dcs_codes_r = -2; |
1494 | wm8993->hubs_data.series_startup = 1; | 1494 | wm8993->hubs_data.series_startup = 1; |
1495 | 1495 | ||
1496 | codec->control_data = wm8993->regmap; | ||
1497 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
1498 | if (ret != 0) { | ||
1499 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1500 | return ret; | ||
1501 | } | ||
1502 | |||
1503 | /* Latch volume update bits and default ZC on */ | 1496 | /* Latch volume update bits and default ZC on */ |
1504 | snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, | 1497 | snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, |
1505 | WM8993_DAC_VU, WM8993_DAC_VU); | 1498 | WM8993_DAC_VU, WM8993_DAC_VU); |
@@ -1559,10 +1552,7 @@ static int wm8993_probe(struct snd_soc_codec *codec) | |||
1559 | 1552 | ||
1560 | static int wm8993_remove(struct snd_soc_codec *codec) | 1553 | static int wm8993_remove(struct snd_soc_codec *codec) |
1561 | { | 1554 | { |
1562 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | ||
1563 | |||
1564 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1555 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1565 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1566 | return 0; | 1556 | return 0; |
1567 | } | 1557 | } |
1568 | 1558 | ||
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b9be9cbc4603..6303537f54c6 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -265,21 +265,21 @@ static const char *sidetone_hpf_text[] = { | |||
265 | "2.7kHz", "1.35kHz", "675Hz", "370Hz", "180Hz", "90Hz", "45Hz" | 265 | "2.7kHz", "1.35kHz", "675Hz", "370Hz", "180Hz", "90Hz", "45Hz" |
266 | }; | 266 | }; |
267 | 267 | ||
268 | static const struct soc_enum sidetone_hpf = | 268 | static SOC_ENUM_SINGLE_DECL(sidetone_hpf, |
269 | SOC_ENUM_SINGLE(WM8994_SIDETONE, 7, 7, sidetone_hpf_text); | 269 | WM8994_SIDETONE, 7, sidetone_hpf_text); |
270 | 270 | ||
271 | static const char *adc_hpf_text[] = { | 271 | static const char *adc_hpf_text[] = { |
272 | "HiFi", "Voice 1", "Voice 2", "Voice 3" | 272 | "HiFi", "Voice 1", "Voice 2", "Voice 3" |
273 | }; | 273 | }; |
274 | 274 | ||
275 | static const struct soc_enum aif1adc1_hpf = | 275 | static SOC_ENUM_SINGLE_DECL(aif1adc1_hpf, |
276 | SOC_ENUM_SINGLE(WM8994_AIF1_ADC1_FILTERS, 13, 4, adc_hpf_text); | 276 | WM8994_AIF1_ADC1_FILTERS, 13, adc_hpf_text); |
277 | 277 | ||
278 | static const struct soc_enum aif1adc2_hpf = | 278 | static SOC_ENUM_SINGLE_DECL(aif1adc2_hpf, |
279 | SOC_ENUM_SINGLE(WM8994_AIF1_ADC2_FILTERS, 13, 4, adc_hpf_text); | 279 | WM8994_AIF1_ADC2_FILTERS, 13, adc_hpf_text); |
280 | 280 | ||
281 | static const struct soc_enum aif2adc_hpf = | 281 | static SOC_ENUM_SINGLE_DECL(aif2adc_hpf, |
282 | SOC_ENUM_SINGLE(WM8994_AIF2_ADC_FILTERS, 13, 4, adc_hpf_text); | 282 | WM8994_AIF2_ADC_FILTERS, 13, adc_hpf_text); |
283 | 283 | ||
284 | static const DECLARE_TLV_DB_SCALE(aif_tlv, 0, 600, 0); | 284 | static const DECLARE_TLV_DB_SCALE(aif_tlv, 0, 600, 0); |
285 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); | 285 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); |
@@ -501,39 +501,39 @@ static const char *aif_chan_src_text[] = { | |||
501 | "Left", "Right" | 501 | "Left", "Right" |
502 | }; | 502 | }; |
503 | 503 | ||
504 | static const struct soc_enum aif1adcl_src = | 504 | static SOC_ENUM_SINGLE_DECL(aif1adcl_src, |
505 | SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 15, 2, aif_chan_src_text); | 505 | WM8994_AIF1_CONTROL_1, 15, aif_chan_src_text); |
506 | 506 | ||
507 | static const struct soc_enum aif1adcr_src = | 507 | static SOC_ENUM_SINGLE_DECL(aif1adcr_src, |
508 | SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 14, 2, aif_chan_src_text); | 508 | WM8994_AIF1_CONTROL_1, 14, aif_chan_src_text); |
509 | 509 | ||
510 | static const struct soc_enum aif2adcl_src = | 510 | static SOC_ENUM_SINGLE_DECL(aif2adcl_src, |
511 | SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 15, 2, aif_chan_src_text); | 511 | WM8994_AIF2_CONTROL_1, 15, aif_chan_src_text); |
512 | 512 | ||
513 | static const struct soc_enum aif2adcr_src = | 513 | static SOC_ENUM_SINGLE_DECL(aif2adcr_src, |
514 | SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 14, 2, aif_chan_src_text); | 514 | WM8994_AIF2_CONTROL_1, 14, aif_chan_src_text); |
515 | 515 | ||
516 | static const struct soc_enum aif1dacl_src = | 516 | static SOC_ENUM_SINGLE_DECL(aif1dacl_src, |
517 | SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 15, 2, aif_chan_src_text); | 517 | WM8994_AIF1_CONTROL_2, 15, aif_chan_src_text); |
518 | 518 | ||
519 | static const struct soc_enum aif1dacr_src = | 519 | static SOC_ENUM_SINGLE_DECL(aif1dacr_src, |
520 | SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 14, 2, aif_chan_src_text); | 520 | WM8994_AIF1_CONTROL_2, 14, aif_chan_src_text); |
521 | 521 | ||
522 | static const struct soc_enum aif2dacl_src = | 522 | static SOC_ENUM_SINGLE_DECL(aif2dacl_src, |
523 | SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 15, 2, aif_chan_src_text); | 523 | WM8994_AIF2_CONTROL_2, 15, aif_chan_src_text); |
524 | 524 | ||
525 | static const struct soc_enum aif2dacr_src = | 525 | static SOC_ENUM_SINGLE_DECL(aif2dacr_src, |
526 | SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 14, 2, aif_chan_src_text); | 526 | WM8994_AIF2_CONTROL_2, 14, aif_chan_src_text); |
527 | 527 | ||
528 | static const char *osr_text[] = { | 528 | static const char *osr_text[] = { |
529 | "Low Power", "High Performance", | 529 | "Low Power", "High Performance", |
530 | }; | 530 | }; |
531 | 531 | ||
532 | static const struct soc_enum dac_osr = | 532 | static SOC_ENUM_SINGLE_DECL(dac_osr, |
533 | SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 0, 2, osr_text); | 533 | WM8994_OVERSAMPLING, 0, osr_text); |
534 | 534 | ||
535 | static const struct soc_enum adc_osr = | 535 | static SOC_ENUM_SINGLE_DECL(adc_osr, |
536 | SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 1, 2, osr_text); | 536 | WM8994_OVERSAMPLING, 1, osr_text); |
537 | 537 | ||
538 | static const struct snd_kcontrol_new wm8994_snd_controls[] = { | 538 | static const struct snd_kcontrol_new wm8994_snd_controls[] = { |
539 | SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME, | 539 | SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME, |
@@ -690,17 +690,20 @@ static const char *wm8958_ng_text[] = { | |||
690 | "30ms", "125ms", "250ms", "500ms", | 690 | "30ms", "125ms", "250ms", "500ms", |
691 | }; | 691 | }; |
692 | 692 | ||
693 | static const struct soc_enum wm8958_aif1dac1_ng_hold = | 693 | static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac1_ng_hold, |
694 | SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE, | 694 | WM8958_AIF1_DAC1_NOISE_GATE, |
695 | WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text); | 695 | WM8958_AIF1DAC1_NG_THR_SHIFT, |
696 | wm8958_ng_text); | ||
696 | 697 | ||
697 | static const struct soc_enum wm8958_aif1dac2_ng_hold = | 698 | static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac2_ng_hold, |
698 | SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE, | 699 | WM8958_AIF1_DAC2_NOISE_GATE, |
699 | WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text); | 700 | WM8958_AIF1DAC2_NG_THR_SHIFT, |
701 | wm8958_ng_text); | ||
700 | 702 | ||
701 | static const struct soc_enum wm8958_aif2dac_ng_hold = | 703 | static SOC_ENUM_SINGLE_DECL(wm8958_aif2dac_ng_hold, |
702 | SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE, | 704 | WM8958_AIF2_DAC_NOISE_GATE, |
703 | WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text); | 705 | WM8958_AIF2DAC_NG_THR_SHIFT, |
706 | wm8958_ng_text); | ||
704 | 707 | ||
705 | static const struct snd_kcontrol_new wm8958_snd_controls[] = { | 708 | static const struct snd_kcontrol_new wm8958_snd_controls[] = { |
706 | SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv), | 709 | SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv), |
@@ -1341,8 +1344,7 @@ static const char *adc_mux_text[] = { | |||
1341 | "DMIC", | 1344 | "DMIC", |
1342 | }; | 1345 | }; |
1343 | 1346 | ||
1344 | static const struct soc_enum adc_enum = | 1347 | static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text); |
1345 | SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text); | ||
1346 | 1348 | ||
1347 | static const struct snd_kcontrol_new adcl_mux = | 1349 | static const struct snd_kcontrol_new adcl_mux = |
1348 | SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); | 1350 | SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); |
@@ -1478,14 +1480,14 @@ static const char *sidetone_text[] = { | |||
1478 | "ADC/DMIC1", "DMIC2", | 1480 | "ADC/DMIC1", "DMIC2", |
1479 | }; | 1481 | }; |
1480 | 1482 | ||
1481 | static const struct soc_enum sidetone1_enum = | 1483 | static SOC_ENUM_SINGLE_DECL(sidetone1_enum, |
1482 | SOC_ENUM_SINGLE(WM8994_SIDETONE, 0, 2, sidetone_text); | 1484 | WM8994_SIDETONE, 0, sidetone_text); |
1483 | 1485 | ||
1484 | static const struct snd_kcontrol_new sidetone1_mux = | 1486 | static const struct snd_kcontrol_new sidetone1_mux = |
1485 | SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum); | 1487 | SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum); |
1486 | 1488 | ||
1487 | static const struct soc_enum sidetone2_enum = | 1489 | static SOC_ENUM_SINGLE_DECL(sidetone2_enum, |
1488 | SOC_ENUM_SINGLE(WM8994_SIDETONE, 1, 2, sidetone_text); | 1490 | WM8994_SIDETONE, 1, sidetone_text); |
1489 | 1491 | ||
1490 | static const struct snd_kcontrol_new sidetone2_mux = | 1492 | static const struct snd_kcontrol_new sidetone2_mux = |
1491 | SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum); | 1493 | SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum); |
@@ -1498,22 +1500,24 @@ static const char *loopback_text[] = { | |||
1498 | "None", "ADCDAT", | 1500 | "None", "ADCDAT", |
1499 | }; | 1501 | }; |
1500 | 1502 | ||
1501 | static const struct soc_enum aif1_loopback_enum = | 1503 | static SOC_ENUM_SINGLE_DECL(aif1_loopback_enum, |
1502 | SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, WM8994_AIF1_LOOPBACK_SHIFT, 2, | 1504 | WM8994_AIF1_CONTROL_2, |
1503 | loopback_text); | 1505 | WM8994_AIF1_LOOPBACK_SHIFT, |
1506 | loopback_text); | ||
1504 | 1507 | ||
1505 | static const struct snd_kcontrol_new aif1_loopback = | 1508 | static const struct snd_kcontrol_new aif1_loopback = |
1506 | SOC_DAPM_ENUM("AIF1 Loopback", aif1_loopback_enum); | 1509 | SOC_DAPM_ENUM("AIF1 Loopback", aif1_loopback_enum); |
1507 | 1510 | ||
1508 | static const struct soc_enum aif2_loopback_enum = | 1511 | static SOC_ENUM_SINGLE_DECL(aif2_loopback_enum, |
1509 | SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, WM8994_AIF2_LOOPBACK_SHIFT, 2, | 1512 | WM8994_AIF2_CONTROL_2, |
1510 | loopback_text); | 1513 | WM8994_AIF2_LOOPBACK_SHIFT, |
1514 | loopback_text); | ||
1511 | 1515 | ||
1512 | static const struct snd_kcontrol_new aif2_loopback = | 1516 | static const struct snd_kcontrol_new aif2_loopback = |
1513 | SOC_DAPM_ENUM("AIF2 Loopback", aif2_loopback_enum); | 1517 | SOC_DAPM_ENUM("AIF2 Loopback", aif2_loopback_enum); |
1514 | 1518 | ||
1515 | static const struct soc_enum aif1dac_enum = | 1519 | static SOC_ENUM_SINGLE_DECL(aif1dac_enum, |
1516 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text); | 1520 | WM8994_POWER_MANAGEMENT_6, 0, aif1dac_text); |
1517 | 1521 | ||
1518 | static const struct snd_kcontrol_new aif1dac_mux = | 1522 | static const struct snd_kcontrol_new aif1dac_mux = |
1519 | SOC_DAPM_ENUM("AIF1DAC Mux", aif1dac_enum); | 1523 | SOC_DAPM_ENUM("AIF1DAC Mux", aif1dac_enum); |
@@ -1522,8 +1526,8 @@ static const char *aif2dac_text[] = { | |||
1522 | "AIF2DACDAT", "AIF3DACDAT", | 1526 | "AIF2DACDAT", "AIF3DACDAT", |
1523 | }; | 1527 | }; |
1524 | 1528 | ||
1525 | static const struct soc_enum aif2dac_enum = | 1529 | static SOC_ENUM_SINGLE_DECL(aif2dac_enum, |
1526 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 1, 2, aif2dac_text); | 1530 | WM8994_POWER_MANAGEMENT_6, 1, aif2dac_text); |
1527 | 1531 | ||
1528 | static const struct snd_kcontrol_new aif2dac_mux = | 1532 | static const struct snd_kcontrol_new aif2dac_mux = |
1529 | SOC_DAPM_ENUM("AIF2DAC Mux", aif2dac_enum); | 1533 | SOC_DAPM_ENUM("AIF2DAC Mux", aif2dac_enum); |
@@ -1532,8 +1536,8 @@ static const char *aif2adc_text[] = { | |||
1532 | "AIF2ADCDAT", "AIF3DACDAT", | 1536 | "AIF2ADCDAT", "AIF3DACDAT", |
1533 | }; | 1537 | }; |
1534 | 1538 | ||
1535 | static const struct soc_enum aif2adc_enum = | 1539 | static SOC_ENUM_SINGLE_DECL(aif2adc_enum, |
1536 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 2, 2, aif2adc_text); | 1540 | WM8994_POWER_MANAGEMENT_6, 2, aif2adc_text); |
1537 | 1541 | ||
1538 | static const struct snd_kcontrol_new aif2adc_mux = | 1542 | static const struct snd_kcontrol_new aif2adc_mux = |
1539 | SOC_DAPM_ENUM("AIF2ADC Mux", aif2adc_enum); | 1543 | SOC_DAPM_ENUM("AIF2ADC Mux", aif2adc_enum); |
@@ -1542,14 +1546,14 @@ static const char *aif3adc_text[] = { | |||
1542 | "AIF1ADCDAT", "AIF2ADCDAT", "AIF2DACDAT", "Mono PCM", | 1546 | "AIF1ADCDAT", "AIF2ADCDAT", "AIF2DACDAT", "Mono PCM", |
1543 | }; | 1547 | }; |
1544 | 1548 | ||
1545 | static const struct soc_enum wm8994_aif3adc_enum = | 1549 | static SOC_ENUM_SINGLE_DECL(wm8994_aif3adc_enum, |
1546 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 3, aif3adc_text); | 1550 | WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text); |
1547 | 1551 | ||
1548 | static const struct snd_kcontrol_new wm8994_aif3adc_mux = | 1552 | static const struct snd_kcontrol_new wm8994_aif3adc_mux = |
1549 | SOC_DAPM_ENUM("AIF3ADC Mux", wm8994_aif3adc_enum); | 1553 | SOC_DAPM_ENUM("AIF3ADC Mux", wm8994_aif3adc_enum); |
1550 | 1554 | ||
1551 | static const struct soc_enum wm8958_aif3adc_enum = | 1555 | static SOC_ENUM_SINGLE_DECL(wm8958_aif3adc_enum, |
1552 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 4, aif3adc_text); | 1556 | WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text); |
1553 | 1557 | ||
1554 | static const struct snd_kcontrol_new wm8958_aif3adc_mux = | 1558 | static const struct snd_kcontrol_new wm8958_aif3adc_mux = |
1555 | SOC_DAPM_ENUM("AIF3ADC Mux", wm8958_aif3adc_enum); | 1559 | SOC_DAPM_ENUM("AIF3ADC Mux", wm8958_aif3adc_enum); |
@@ -1558,8 +1562,8 @@ static const char *mono_pcm_out_text[] = { | |||
1558 | "None", "AIF2ADCL", "AIF2ADCR", | 1562 | "None", "AIF2ADCL", "AIF2ADCR", |
1559 | }; | 1563 | }; |
1560 | 1564 | ||
1561 | static const struct soc_enum mono_pcm_out_enum = | 1565 | static SOC_ENUM_SINGLE_DECL(mono_pcm_out_enum, |
1562 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 9, 3, mono_pcm_out_text); | 1566 | WM8994_POWER_MANAGEMENT_6, 9, mono_pcm_out_text); |
1563 | 1567 | ||
1564 | static const struct snd_kcontrol_new mono_pcm_out_mux = | 1568 | static const struct snd_kcontrol_new mono_pcm_out_mux = |
1565 | SOC_DAPM_ENUM("Mono PCM Out Mux", mono_pcm_out_enum); | 1569 | SOC_DAPM_ENUM("Mono PCM Out Mux", mono_pcm_out_enum); |
@@ -1569,14 +1573,14 @@ static const char *aif2dac_src_text[] = { | |||
1569 | }; | 1573 | }; |
1570 | 1574 | ||
1571 | /* Note that these two control shouldn't be simultaneously switched to AIF3 */ | 1575 | /* Note that these two control shouldn't be simultaneously switched to AIF3 */ |
1572 | static const struct soc_enum aif2dacl_src_enum = | 1576 | static SOC_ENUM_SINGLE_DECL(aif2dacl_src_enum, |
1573 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 7, 2, aif2dac_src_text); | 1577 | WM8994_POWER_MANAGEMENT_6, 7, aif2dac_src_text); |
1574 | 1578 | ||
1575 | static const struct snd_kcontrol_new aif2dacl_src_mux = | 1579 | static const struct snd_kcontrol_new aif2dacl_src_mux = |
1576 | SOC_DAPM_ENUM("AIF2DACL Mux", aif2dacl_src_enum); | 1580 | SOC_DAPM_ENUM("AIF2DACL Mux", aif2dacl_src_enum); |
1577 | 1581 | ||
1578 | static const struct soc_enum aif2dacr_src_enum = | 1582 | static SOC_ENUM_SINGLE_DECL(aif2dacr_src_enum, |
1579 | SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 8, 2, aif2dac_src_text); | 1583 | WM8994_POWER_MANAGEMENT_6, 8, aif2dac_src_text); |
1580 | 1584 | ||
1581 | static const struct snd_kcontrol_new aif2dacr_src_mux = | 1585 | static const struct snd_kcontrol_new aif2dacr_src_mux = |
1582 | SOC_DAPM_ENUM("AIF2DACR Mux", aif2dacr_src_enum); | 1586 | SOC_DAPM_ENUM("AIF2DACR Mux", aif2dacr_src_enum); |
@@ -2549,43 +2553,52 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
2549 | int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode) | 2553 | int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode) |
2550 | { | 2554 | { |
2551 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2555 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2556 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
2552 | 2557 | ||
2553 | switch (mode) { | 2558 | switch (mode) { |
2554 | case WM8994_VMID_NORMAL: | 2559 | case WM8994_VMID_NORMAL: |
2560 | snd_soc_dapm_mutex_lock(dapm); | ||
2561 | |||
2555 | if (wm8994->hubs.lineout1_se) { | 2562 | if (wm8994->hubs.lineout1_se) { |
2556 | snd_soc_dapm_disable_pin(&codec->dapm, | 2563 | snd_soc_dapm_disable_pin_unlocked(dapm, |
2557 | "LINEOUT1N Driver"); | 2564 | "LINEOUT1N Driver"); |
2558 | snd_soc_dapm_disable_pin(&codec->dapm, | 2565 | snd_soc_dapm_disable_pin_unlocked(dapm, |
2559 | "LINEOUT1P Driver"); | 2566 | "LINEOUT1P Driver"); |
2560 | } | 2567 | } |
2561 | if (wm8994->hubs.lineout2_se) { | 2568 | if (wm8994->hubs.lineout2_se) { |
2562 | snd_soc_dapm_disable_pin(&codec->dapm, | 2569 | snd_soc_dapm_disable_pin_unlocked(dapm, |
2563 | "LINEOUT2N Driver"); | 2570 | "LINEOUT2N Driver"); |
2564 | snd_soc_dapm_disable_pin(&codec->dapm, | 2571 | snd_soc_dapm_disable_pin_unlocked(dapm, |
2565 | "LINEOUT2P Driver"); | 2572 | "LINEOUT2P Driver"); |
2566 | } | 2573 | } |
2567 | 2574 | ||
2568 | /* Do the sync with the old mode to allow it to clean up */ | 2575 | /* Do the sync with the old mode to allow it to clean up */ |
2569 | snd_soc_dapm_sync(&codec->dapm); | 2576 | snd_soc_dapm_sync_unlocked(dapm); |
2570 | wm8994->vmid_mode = mode; | 2577 | wm8994->vmid_mode = mode; |
2578 | |||
2579 | snd_soc_dapm_mutex_unlock(dapm); | ||
2571 | break; | 2580 | break; |
2572 | 2581 | ||
2573 | case WM8994_VMID_FORCE: | 2582 | case WM8994_VMID_FORCE: |
2583 | snd_soc_dapm_mutex_lock(dapm); | ||
2584 | |||
2574 | if (wm8994->hubs.lineout1_se) { | 2585 | if (wm8994->hubs.lineout1_se) { |
2575 | snd_soc_dapm_force_enable_pin(&codec->dapm, | 2586 | snd_soc_dapm_force_enable_pin_unlocked(dapm, |
2576 | "LINEOUT1N Driver"); | 2587 | "LINEOUT1N Driver"); |
2577 | snd_soc_dapm_force_enable_pin(&codec->dapm, | 2588 | snd_soc_dapm_force_enable_pin_unlocked(dapm, |
2578 | "LINEOUT1P Driver"); | 2589 | "LINEOUT1P Driver"); |
2579 | } | 2590 | } |
2580 | if (wm8994->hubs.lineout2_se) { | 2591 | if (wm8994->hubs.lineout2_se) { |
2581 | snd_soc_dapm_force_enable_pin(&codec->dapm, | 2592 | snd_soc_dapm_force_enable_pin_unlocked(dapm, |
2582 | "LINEOUT2N Driver"); | 2593 | "LINEOUT2N Driver"); |
2583 | snd_soc_dapm_force_enable_pin(&codec->dapm, | 2594 | snd_soc_dapm_force_enable_pin_unlocked(dapm, |
2584 | "LINEOUT2P Driver"); | 2595 | "LINEOUT2P Driver"); |
2585 | } | 2596 | } |
2586 | 2597 | ||
2587 | wm8994->vmid_mode = mode; | 2598 | wm8994->vmid_mode = mode; |
2588 | snd_soc_dapm_sync(&codec->dapm); | 2599 | snd_soc_dapm_sync_unlocked(dapm); |
2600 | |||
2601 | snd_soc_dapm_mutex_unlock(dapm); | ||
2589 | break; | 2602 | break; |
2590 | 2603 | ||
2591 | default: | 2604 | default: |
@@ -3237,7 +3250,7 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | |||
3237 | dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", | 3250 | dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", |
3238 | wm8994->num_retune_mobile_texts); | 3251 | wm8994->num_retune_mobile_texts); |
3239 | 3252 | ||
3240 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; | 3253 | wm8994->retune_mobile_enum.items = wm8994->num_retune_mobile_texts; |
3241 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; | 3254 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; |
3242 | 3255 | ||
3243 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, | 3256 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, |
@@ -3293,7 +3306,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3293 | for (i = 0; i < pdata->num_drc_cfgs; i++) | 3306 | for (i = 0; i < pdata->num_drc_cfgs; i++) |
3294 | wm8994->drc_texts[i] = pdata->drc_cfgs[i].name; | 3307 | wm8994->drc_texts[i] = pdata->drc_cfgs[i].name; |
3295 | 3308 | ||
3296 | wm8994->drc_enum.max = pdata->num_drc_cfgs; | 3309 | wm8994->drc_enum.items = pdata->num_drc_cfgs; |
3297 | wm8994->drc_enum.texts = wm8994->drc_texts; | 3310 | wm8994->drc_enum.texts = wm8994->drc_texts; |
3298 | 3311 | ||
3299 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, | 3312 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, |
@@ -3985,9 +3998,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3985 | int ret, i; | 3998 | int ret, i; |
3986 | 3999 | ||
3987 | wm8994->hubs.codec = codec; | 4000 | wm8994->hubs.codec = codec; |
3988 | codec->control_data = control->regmap; | ||
3989 | 4001 | ||
3990 | snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | 4002 | snd_soc_codec_set_cache_io(codec, control->regmap); |
3991 | 4003 | ||
3992 | mutex_init(&wm8994->accdet_lock); | 4004 | mutex_init(&wm8994->accdet_lock); |
3993 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, | 4005 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 4300caff1783..d3152cf5bd56 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -423,24 +423,24 @@ static const char *in1l_text[] = { | |||
423 | "Differential", "Single-ended IN1LN", "Single-ended IN1LP" | 423 | "Differential", "Single-ended IN1LN", "Single-ended IN1LP" |
424 | }; | 424 | }; |
425 | 425 | ||
426 | static const SOC_ENUM_SINGLE_DECL(in1l_enum, WM8995_LEFT_LINE_INPUT_CONTROL, | 426 | static SOC_ENUM_SINGLE_DECL(in1l_enum, WM8995_LEFT_LINE_INPUT_CONTROL, |
427 | 2, in1l_text); | 427 | 2, in1l_text); |
428 | 428 | ||
429 | static const char *in1r_text[] = { | 429 | static const char *in1r_text[] = { |
430 | "Differential", "Single-ended IN1RN", "Single-ended IN1RP" | 430 | "Differential", "Single-ended IN1RN", "Single-ended IN1RP" |
431 | }; | 431 | }; |
432 | 432 | ||
433 | static const SOC_ENUM_SINGLE_DECL(in1r_enum, WM8995_LEFT_LINE_INPUT_CONTROL, | 433 | static SOC_ENUM_SINGLE_DECL(in1r_enum, WM8995_LEFT_LINE_INPUT_CONTROL, |
434 | 0, in1r_text); | 434 | 0, in1r_text); |
435 | 435 | ||
436 | static const char *dmic_src_text[] = { | 436 | static const char *dmic_src_text[] = { |
437 | "DMICDAT1", "DMICDAT2", "DMICDAT3" | 437 | "DMICDAT1", "DMICDAT2", "DMICDAT3" |
438 | }; | 438 | }; |
439 | 439 | ||
440 | static const SOC_ENUM_SINGLE_DECL(dmic_src1_enum, WM8995_POWER_MANAGEMENT_5, | 440 | static SOC_ENUM_SINGLE_DECL(dmic_src1_enum, WM8995_POWER_MANAGEMENT_5, |
441 | 8, dmic_src_text); | 441 | 8, dmic_src_text); |
442 | static const SOC_ENUM_SINGLE_DECL(dmic_src2_enum, WM8995_POWER_MANAGEMENT_5, | 442 | static SOC_ENUM_SINGLE_DECL(dmic_src2_enum, WM8995_POWER_MANAGEMENT_5, |
443 | 6, dmic_src_text); | 443 | 6, dmic_src_text); |
444 | 444 | ||
445 | static const struct snd_kcontrol_new wm8995_snd_controls[] = { | 445 | static const struct snd_kcontrol_new wm8995_snd_controls[] = { |
446 | SOC_DOUBLE_R_TLV("DAC1 Volume", WM8995_DAC1_LEFT_VOLUME, | 446 | SOC_DOUBLE_R_TLV("DAC1 Volume", WM8995_DAC1_LEFT_VOLUME, |
@@ -561,10 +561,8 @@ static int hp_supply_event(struct snd_soc_dapm_widget *w, | |||
561 | struct snd_kcontrol *kcontrol, int event) | 561 | struct snd_kcontrol *kcontrol, int event) |
562 | { | 562 | { |
563 | struct snd_soc_codec *codec; | 563 | struct snd_soc_codec *codec; |
564 | struct wm8995_priv *wm8995; | ||
565 | 564 | ||
566 | codec = w->codec; | 565 | codec = w->codec; |
567 | wm8995 = snd_soc_codec_get_drvdata(codec); | ||
568 | 566 | ||
569 | switch (event) { | 567 | switch (event) { |
570 | case SND_SOC_DAPM_PRE_PMU: | 568 | case SND_SOC_DAPM_PRE_PMU: |
@@ -783,14 +781,12 @@ static const char *sidetone_text[] = { | |||
783 | "ADC/DMIC1", "DMIC2", | 781 | "ADC/DMIC1", "DMIC2", |
784 | }; | 782 | }; |
785 | 783 | ||
786 | static const struct soc_enum sidetone1_enum = | 784 | static SOC_ENUM_SINGLE_DECL(sidetone1_enum, WM8995_SIDETONE, 0, sidetone_text); |
787 | SOC_ENUM_SINGLE(WM8995_SIDETONE, 0, 2, sidetone_text); | ||
788 | 785 | ||
789 | static const struct snd_kcontrol_new sidetone1_mux = | 786 | static const struct snd_kcontrol_new sidetone1_mux = |
790 | SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum); | 787 | SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum); |
791 | 788 | ||
792 | static const struct soc_enum sidetone2_enum = | 789 | static SOC_ENUM_SINGLE_DECL(sidetone2_enum, WM8995_SIDETONE, 1, sidetone_text); |
793 | SOC_ENUM_SINGLE(WM8995_SIDETONE, 1, 2, sidetone_text); | ||
794 | 790 | ||
795 | static const struct snd_kcontrol_new sidetone2_mux = | 791 | static const struct snd_kcontrol_new sidetone2_mux = |
796 | SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum); | 792 | SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum); |
@@ -886,8 +882,7 @@ static const char *adc_mux_text[] = { | |||
886 | "DMIC", | 882 | "DMIC", |
887 | }; | 883 | }; |
888 | 884 | ||
889 | static const struct soc_enum adc_enum = | 885 | static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text); |
890 | SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text); | ||
891 | 886 | ||
892 | static const struct snd_kcontrol_new adcl_mux = | 887 | static const struct snd_kcontrol_new adcl_mux = |
893 | SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); | 888 | SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); |
@@ -899,14 +894,14 @@ static const char *spk_src_text[] = { | |||
899 | "DAC1L", "DAC1R", "DAC2L", "DAC2R" | 894 | "DAC1L", "DAC1R", "DAC2L", "DAC2R" |
900 | }; | 895 | }; |
901 | 896 | ||
902 | static const SOC_ENUM_SINGLE_DECL(spk1l_src_enum, WM8995_LEFT_PDM_SPEAKER_1, | 897 | static SOC_ENUM_SINGLE_DECL(spk1l_src_enum, WM8995_LEFT_PDM_SPEAKER_1, |
903 | 0, spk_src_text); | 898 | 0, spk_src_text); |
904 | static const SOC_ENUM_SINGLE_DECL(spk1r_src_enum, WM8995_RIGHT_PDM_SPEAKER_1, | 899 | static SOC_ENUM_SINGLE_DECL(spk1r_src_enum, WM8995_RIGHT_PDM_SPEAKER_1, |
905 | 0, spk_src_text); | 900 | 0, spk_src_text); |
906 | static const SOC_ENUM_SINGLE_DECL(spk2l_src_enum, WM8995_LEFT_PDM_SPEAKER_2, | 901 | static SOC_ENUM_SINGLE_DECL(spk2l_src_enum, WM8995_LEFT_PDM_SPEAKER_2, |
907 | 0, spk_src_text); | 902 | 0, spk_src_text); |
908 | static const SOC_ENUM_SINGLE_DECL(spk2r_src_enum, WM8995_RIGHT_PDM_SPEAKER_2, | 903 | static SOC_ENUM_SINGLE_DECL(spk2r_src_enum, WM8995_RIGHT_PDM_SPEAKER_2, |
909 | 0, spk_src_text); | 904 | 0, spk_src_text); |
910 | 905 | ||
911 | static const struct snd_kcontrol_new spk1l_mux = | 906 | static const struct snd_kcontrol_new spk1l_mux = |
912 | SOC_DAPM_ENUM("SPK1L SRC", spk1l_src_enum); | 907 | SOC_DAPM_ENUM("SPK1L SRC", spk1l_src_enum); |
@@ -2047,13 +2042,6 @@ static int wm8995_probe(struct snd_soc_codec *codec) | |||
2047 | wm8995 = snd_soc_codec_get_drvdata(codec); | 2042 | wm8995 = snd_soc_codec_get_drvdata(codec); |
2048 | wm8995->codec = codec; | 2043 | wm8995->codec = codec; |
2049 | 2044 | ||
2050 | codec->control_data = wm8995->regmap; | ||
2051 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | ||
2052 | if (ret < 0) { | ||
2053 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | ||
2054 | return ret; | ||
2055 | } | ||
2056 | |||
2057 | for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++) | 2045 | for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++) |
2058 | wm8995->supplies[i].supply = wm8995_supply_names[i]; | 2046 | wm8995->supplies[i].supply = wm8995_supply_names[i]; |
2059 | 2047 | ||
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 1a7655b0aa22..c6cbb3b8ace9 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -311,28 +311,28 @@ static const char *sidetone_hpf_text[] = { | |||
311 | "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz" | 311 | "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz" |
312 | }; | 312 | }; |
313 | 313 | ||
314 | static const struct soc_enum sidetone_hpf = | 314 | static SOC_ENUM_SINGLE_DECL(sidetone_hpf, |
315 | SOC_ENUM_SINGLE(WM8996_SIDETONE, 7, 7, sidetone_hpf_text); | 315 | WM8996_SIDETONE, 7, sidetone_hpf_text); |
316 | 316 | ||
317 | static const char *hpf_mode_text[] = { | 317 | static const char *hpf_mode_text[] = { |
318 | "HiFi", "Custom", "Voice" | 318 | "HiFi", "Custom", "Voice" |
319 | }; | 319 | }; |
320 | 320 | ||
321 | static const struct soc_enum dsp1tx_hpf_mode = | 321 | static SOC_ENUM_SINGLE_DECL(dsp1tx_hpf_mode, |
322 | SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 3, 3, hpf_mode_text); | 322 | WM8996_DSP1_TX_FILTERS, 3, hpf_mode_text); |
323 | 323 | ||
324 | static const struct soc_enum dsp2tx_hpf_mode = | 324 | static SOC_ENUM_SINGLE_DECL(dsp2tx_hpf_mode, |
325 | SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 3, 3, hpf_mode_text); | 325 | WM8996_DSP2_TX_FILTERS, 3, hpf_mode_text); |
326 | 326 | ||
327 | static const char *hpf_cutoff_text[] = { | 327 | static const char *hpf_cutoff_text[] = { |
328 | "50Hz", "75Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" | 328 | "50Hz", "75Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" |
329 | }; | 329 | }; |
330 | 330 | ||
331 | static const struct soc_enum dsp1tx_hpf_cutoff = | 331 | static SOC_ENUM_SINGLE_DECL(dsp1tx_hpf_cutoff, |
332 | SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 0, 7, hpf_cutoff_text); | 332 | WM8996_DSP1_TX_FILTERS, 0, hpf_cutoff_text); |
333 | 333 | ||
334 | static const struct soc_enum dsp2tx_hpf_cutoff = | 334 | static SOC_ENUM_SINGLE_DECL(dsp2tx_hpf_cutoff, |
335 | SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 0, 7, hpf_cutoff_text); | 335 | WM8996_DSP2_TX_FILTERS, 0, hpf_cutoff_text); |
336 | 336 | ||
337 | static void wm8996_set_retune_mobile(struct snd_soc_codec *codec, int block) | 337 | static void wm8996_set_retune_mobile(struct snd_soc_codec *codec, int block) |
338 | { | 338 | { |
@@ -780,14 +780,14 @@ static const char *sidetone_text[] = { | |||
780 | "IN1", "IN2", | 780 | "IN1", "IN2", |
781 | }; | 781 | }; |
782 | 782 | ||
783 | static const struct soc_enum left_sidetone_enum = | 783 | static SOC_ENUM_SINGLE_DECL(left_sidetone_enum, |
784 | SOC_ENUM_SINGLE(WM8996_SIDETONE, 0, 2, sidetone_text); | 784 | WM8996_SIDETONE, 0, sidetone_text); |
785 | 785 | ||
786 | static const struct snd_kcontrol_new left_sidetone = | 786 | static const struct snd_kcontrol_new left_sidetone = |
787 | SOC_DAPM_ENUM("Left Sidetone", left_sidetone_enum); | 787 | SOC_DAPM_ENUM("Left Sidetone", left_sidetone_enum); |
788 | 788 | ||
789 | static const struct soc_enum right_sidetone_enum = | 789 | static SOC_ENUM_SINGLE_DECL(right_sidetone_enum, |
790 | SOC_ENUM_SINGLE(WM8996_SIDETONE, 1, 2, sidetone_text); | 790 | WM8996_SIDETONE, 1, sidetone_text); |
791 | 791 | ||
792 | static const struct snd_kcontrol_new right_sidetone = | 792 | static const struct snd_kcontrol_new right_sidetone = |
793 | SOC_DAPM_ENUM("Right Sidetone", right_sidetone_enum); | 793 | SOC_DAPM_ENUM("Right Sidetone", right_sidetone_enum); |
@@ -796,14 +796,14 @@ static const char *spk_text[] = { | |||
796 | "DAC1L", "DAC1R", "DAC2L", "DAC2R" | 796 | "DAC1L", "DAC1R", "DAC2L", "DAC2R" |
797 | }; | 797 | }; |
798 | 798 | ||
799 | static const struct soc_enum spkl_enum = | 799 | static SOC_ENUM_SINGLE_DECL(spkl_enum, |
800 | SOC_ENUM_SINGLE(WM8996_LEFT_PDM_SPEAKER, 0, 4, spk_text); | 800 | WM8996_LEFT_PDM_SPEAKER, 0, spk_text); |
801 | 801 | ||
802 | static const struct snd_kcontrol_new spkl_mux = | 802 | static const struct snd_kcontrol_new spkl_mux = |
803 | SOC_DAPM_ENUM("SPKL", spkl_enum); | 803 | SOC_DAPM_ENUM("SPKL", spkl_enum); |
804 | 804 | ||
805 | static const struct soc_enum spkr_enum = | 805 | static SOC_ENUM_SINGLE_DECL(spkr_enum, |
806 | SOC_ENUM_SINGLE(WM8996_RIGHT_PDM_SPEAKER, 0, 4, spk_text); | 806 | WM8996_RIGHT_PDM_SPEAKER, 0, spk_text); |
807 | 807 | ||
808 | static const struct snd_kcontrol_new spkr_mux = | 808 | static const struct snd_kcontrol_new spkr_mux = |
809 | SOC_DAPM_ENUM("SPKR", spkr_enum); | 809 | SOC_DAPM_ENUM("SPKR", spkr_enum); |
@@ -812,8 +812,8 @@ static const char *dsp1rx_text[] = { | |||
812 | "AIF1", "AIF2" | 812 | "AIF1", "AIF2" |
813 | }; | 813 | }; |
814 | 814 | ||
815 | static const struct soc_enum dsp1rx_enum = | 815 | static SOC_ENUM_SINGLE_DECL(dsp1rx_enum, |
816 | SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 0, 2, dsp1rx_text); | 816 | WM8996_POWER_MANAGEMENT_8, 0, dsp1rx_text); |
817 | 817 | ||
818 | static const struct snd_kcontrol_new dsp1rx = | 818 | static const struct snd_kcontrol_new dsp1rx = |
819 | SOC_DAPM_ENUM("DSP1RX", dsp1rx_enum); | 819 | SOC_DAPM_ENUM("DSP1RX", dsp1rx_enum); |
@@ -822,8 +822,8 @@ static const char *dsp2rx_text[] = { | |||
822 | "AIF2", "AIF1" | 822 | "AIF2", "AIF1" |
823 | }; | 823 | }; |
824 | 824 | ||
825 | static const struct soc_enum dsp2rx_enum = | 825 | static SOC_ENUM_SINGLE_DECL(dsp2rx_enum, |
826 | SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 4, 2, dsp2rx_text); | 826 | WM8996_POWER_MANAGEMENT_8, 4, dsp2rx_text); |
827 | 827 | ||
828 | static const struct snd_kcontrol_new dsp2rx = | 828 | static const struct snd_kcontrol_new dsp2rx = |
829 | SOC_DAPM_ENUM("DSP2RX", dsp2rx_enum); | 829 | SOC_DAPM_ENUM("DSP2RX", dsp2rx_enum); |
@@ -832,8 +832,8 @@ static const char *aif2tx_text[] = { | |||
832 | "DSP2", "DSP1", "AIF1" | 832 | "DSP2", "DSP1", "AIF1" |
833 | }; | 833 | }; |
834 | 834 | ||
835 | static const struct soc_enum aif2tx_enum = | 835 | static SOC_ENUM_SINGLE_DECL(aif2tx_enum, |
836 | SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 6, 3, aif2tx_text); | 836 | WM8996_POWER_MANAGEMENT_8, 6, aif2tx_text); |
837 | 837 | ||
838 | static const struct snd_kcontrol_new aif2tx = | 838 | static const struct snd_kcontrol_new aif2tx = |
839 | SOC_DAPM_ENUM("AIF2TX", aif2tx_enum); | 839 | SOC_DAPM_ENUM("AIF2TX", aif2tx_enum); |
@@ -842,14 +842,14 @@ static const char *inmux_text[] = { | |||
842 | "ADC", "DMIC1", "DMIC2" | 842 | "ADC", "DMIC1", "DMIC2" |
843 | }; | 843 | }; |
844 | 844 | ||
845 | static const struct soc_enum in1_enum = | 845 | static SOC_ENUM_SINGLE_DECL(in1_enum, |
846 | SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 0, 3, inmux_text); | 846 | WM8996_POWER_MANAGEMENT_7, 0, inmux_text); |
847 | 847 | ||
848 | static const struct snd_kcontrol_new in1_mux = | 848 | static const struct snd_kcontrol_new in1_mux = |
849 | SOC_DAPM_ENUM("IN1 Mux", in1_enum); | 849 | SOC_DAPM_ENUM("IN1 Mux", in1_enum); |
850 | 850 | ||
851 | static const struct soc_enum in2_enum = | 851 | static SOC_ENUM_SINGLE_DECL(in2_enum, |
852 | SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 4, 3, inmux_text); | 852 | WM8996_POWER_MANAGEMENT_7, 4, inmux_text); |
853 | 853 | ||
854 | static const struct snd_kcontrol_new in2_mux = | 854 | static const struct snd_kcontrol_new in2_mux = |
855 | SOC_DAPM_ENUM("IN2 Mux", in2_enum); | 855 | SOC_DAPM_ENUM("IN2 Mux", in2_enum); |
@@ -1608,8 +1608,8 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, | |||
1608 | msleep(5); | 1608 | msleep(5); |
1609 | } | 1609 | } |
1610 | 1610 | ||
1611 | regcache_cache_only(codec->control_data, false); | 1611 | regcache_cache_only(wm8996->regmap, false); |
1612 | regcache_sync(codec->control_data); | 1612 | regcache_sync(wm8996->regmap); |
1613 | } | 1613 | } |
1614 | 1614 | ||
1615 | /* Bypass the MICBIASes for lowest power */ | 1615 | /* Bypass the MICBIASes for lowest power */ |
@@ -1620,10 +1620,10 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, | |||
1620 | break; | 1620 | break; |
1621 | 1621 | ||
1622 | case SND_SOC_BIAS_OFF: | 1622 | case SND_SOC_BIAS_OFF: |
1623 | regcache_cache_only(codec->control_data, true); | 1623 | regcache_cache_only(wm8996->regmap, true); |
1624 | if (wm8996->pdata.ldo_ena >= 0) { | 1624 | if (wm8996->pdata.ldo_ena >= 0) { |
1625 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | 1625 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
1626 | regcache_cache_only(codec->control_data, true); | 1626 | regcache_cache_only(wm8996->regmap, true); |
1627 | } | 1627 | } |
1628 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), | 1628 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), |
1629 | wm8996->supplies); | 1629 | wm8996->supplies); |
@@ -2251,6 +2251,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
2251 | wm8996_polarity_fn polarity_cb) | 2251 | wm8996_polarity_fn polarity_cb) |
2252 | { | 2252 | { |
2253 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 2253 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
2254 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
2254 | 2255 | ||
2255 | wm8996->jack = jack; | 2256 | wm8996->jack = jack; |
2256 | wm8996->detecting = true; | 2257 | wm8996->detecting = true; |
@@ -2267,8 +2268,12 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
2267 | WM8996_MICB2_DISCH, 0); | 2268 | WM8996_MICB2_DISCH, 0); |
2268 | 2269 | ||
2269 | /* LDO2 powers the microphones, SYSCLK clocks detection */ | 2270 | /* LDO2 powers the microphones, SYSCLK clocks detection */ |
2270 | snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); | 2271 | snd_soc_dapm_mutex_lock(dapm); |
2271 | snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); | 2272 | |
2273 | snd_soc_dapm_force_enable_pin_unlocked(dapm, "LDO2"); | ||
2274 | snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK"); | ||
2275 | |||
2276 | snd_soc_dapm_mutex_unlock(dapm); | ||
2272 | 2277 | ||
2273 | /* We start off just enabling microphone detection - even a | 2278 | /* We start off just enabling microphone detection - even a |
2274 | * plain headphone will trigger detection. | 2279 | * plain headphone will trigger detection. |
@@ -2595,7 +2600,7 @@ static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec) | |||
2595 | dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", | 2600 | dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", |
2596 | wm8996->num_retune_mobile_texts); | 2601 | wm8996->num_retune_mobile_texts); |
2597 | 2602 | ||
2598 | wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts; | 2603 | wm8996->retune_mobile_enum.items = wm8996->num_retune_mobile_texts; |
2599 | wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts; | 2604 | wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts; |
2600 | 2605 | ||
2601 | ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); | 2606 | ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); |
@@ -2628,14 +2633,6 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2628 | init_completion(&wm8996->dcs_done); | 2633 | init_completion(&wm8996->dcs_done); |
2629 | init_completion(&wm8996->fll_lock); | 2634 | init_completion(&wm8996->fll_lock); |
2630 | 2635 | ||
2631 | codec->control_data = wm8996->regmap; | ||
2632 | |||
2633 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | ||
2634 | if (ret != 0) { | ||
2635 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
2636 | goto err; | ||
2637 | } | ||
2638 | |||
2639 | if (wm8996->pdata.num_retune_mobile_cfgs) | 2636 | if (wm8996->pdata.num_retune_mobile_cfgs) |
2640 | wm8996_retune_mobile_pdata(codec); | 2637 | wm8996_retune_mobile_pdata(codec); |
2641 | else | 2638 | else |
@@ -2674,13 +2671,11 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2674 | } else { | 2671 | } else { |
2675 | dev_err(codec->dev, "Failed to request IRQ: %d\n", | 2672 | dev_err(codec->dev, "Failed to request IRQ: %d\n", |
2676 | ret); | 2673 | ret); |
2674 | return ret; | ||
2677 | } | 2675 | } |
2678 | } | 2676 | } |
2679 | 2677 | ||
2680 | return 0; | 2678 | return 0; |
2681 | |||
2682 | err: | ||
2683 | return ret; | ||
2684 | } | 2679 | } |
2685 | 2680 | ||
2686 | static int wm8996_remove(struct snd_soc_codec *codec) | 2681 | static int wm8996_remove(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 555115ee2159..004186b6bd48 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c | |||
@@ -86,7 +86,7 @@ static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w, | |||
86 | { | 86 | { |
87 | struct snd_soc_codec *codec = w->codec; | 87 | struct snd_soc_codec *codec = w->codec; |
88 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 88 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
89 | struct regmap *regmap = codec->control_data; | 89 | struct regmap *regmap = arizona->regmap; |
90 | const struct reg_default *patch = NULL; | 90 | const struct reg_default *patch = NULL; |
91 | int i, patch_size; | 91 | int i, patch_size; |
92 | 92 | ||
@@ -123,10 +123,12 @@ static const unsigned int wm8997_osr_val[] = { | |||
123 | 123 | ||
124 | static const struct soc_enum wm8997_hpout_osr[] = { | 124 | static const struct soc_enum wm8997_hpout_osr[] = { |
125 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, | 125 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, |
126 | ARIZONA_OUT1_OSR_SHIFT, 0x7, 3, | 126 | ARIZONA_OUT1_OSR_SHIFT, 0x7, |
127 | ARRAY_SIZE(wm8997_osr_text), | ||
127 | wm8997_osr_text, wm8997_osr_val), | 128 | wm8997_osr_text, wm8997_osr_val), |
128 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, | 129 | SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, |
129 | ARIZONA_OUT3_OSR_SHIFT, 0x7, 3, | 130 | ARIZONA_OUT3_OSR_SHIFT, 0x7, |
131 | ARRAY_SIZE(wm8997_osr_text), | ||
130 | wm8997_osr_text, wm8997_osr_val), | 132 | wm8997_osr_text, wm8997_osr_val), |
131 | }; | 133 | }; |
132 | 134 | ||
@@ -170,15 +172,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | |||
170 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | 172 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), |
171 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | 173 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), |
172 | 174 | ||
173 | SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21, | 175 | SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), |
174 | ARIZONA_EQ1_ENA_MASK), | 176 | SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), |
175 | SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21, | ||
176 | ARIZONA_EQ2_ENA_MASK), | ||
177 | SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21, | ||
178 | ARIZONA_EQ3_ENA_MASK), | ||
179 | SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21, | ||
180 | ARIZONA_EQ4_ENA_MASK), | ||
181 | |||
182 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | 177 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, |
183 | 24, 0, eq_tlv), | 178 | 24, 0, eq_tlv), |
184 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | 179 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, |
@@ -190,6 +185,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, | |||
190 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, | 185 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, |
191 | 24, 0, eq_tlv), | 186 | 24, 0, eq_tlv), |
192 | 187 | ||
188 | SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), | ||
189 | SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), | ||
193 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, | 190 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, |
194 | 24, 0, eq_tlv), | 191 | 24, 0, eq_tlv), |
195 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, | 192 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, |
@@ -201,6 +198,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, | |||
201 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, | 198 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, |
202 | 24, 0, eq_tlv), | 199 | 24, 0, eq_tlv), |
203 | 200 | ||
201 | SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), | ||
202 | SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), | ||
204 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, | 203 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, |
205 | 24, 0, eq_tlv), | 204 | 24, 0, eq_tlv), |
206 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, | 205 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, |
@@ -212,6 +211,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, | |||
212 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, | 211 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, |
213 | 24, 0, eq_tlv), | 212 | 24, 0, eq_tlv), |
214 | 213 | ||
214 | SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), | ||
215 | SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), | ||
215 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, | 216 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, |
216 | 24, 0, eq_tlv), | 217 | 24, 0, eq_tlv), |
217 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, | 218 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, |
@@ -1052,9 +1053,7 @@ static int wm8997_codec_probe(struct snd_soc_codec *codec) | |||
1052 | struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec); | 1053 | struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec); |
1053 | int ret; | 1054 | int ret; |
1054 | 1055 | ||
1055 | codec->control_data = priv->core.arizona->regmap; | 1056 | ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap); |
1056 | |||
1057 | ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); | ||
1058 | if (ret != 0) | 1057 | if (ret != 0) |
1059 | return ret; | 1058 | return ret; |
1060 | 1059 | ||
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 0982c1d38ec4..d18eff31fbbc 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -268,8 +268,7 @@ static const char *drc_high_text[] = { | |||
268 | "0", | 268 | "0", |
269 | }; | 269 | }; |
270 | 270 | ||
271 | static const struct soc_enum drc_high = | 271 | static SOC_ENUM_SINGLE_DECL(drc_high, WM9081_DRC_3, 3, drc_high_text); |
272 | SOC_ENUM_SINGLE(WM9081_DRC_3, 3, 6, drc_high_text); | ||
273 | 272 | ||
274 | static const char *drc_low_text[] = { | 273 | static const char *drc_low_text[] = { |
275 | "1", | 274 | "1", |
@@ -279,8 +278,7 @@ static const char *drc_low_text[] = { | |||
279 | "0", | 278 | "0", |
280 | }; | 279 | }; |
281 | 280 | ||
282 | static const struct soc_enum drc_low = | 281 | static SOC_ENUM_SINGLE_DECL(drc_low, WM9081_DRC_3, 0, drc_low_text); |
283 | SOC_ENUM_SINGLE(WM9081_DRC_3, 0, 5, drc_low_text); | ||
284 | 282 | ||
285 | static const char *drc_atk_text[] = { | 283 | static const char *drc_atk_text[] = { |
286 | "181us", | 284 | "181us", |
@@ -297,8 +295,7 @@ static const char *drc_atk_text[] = { | |||
297 | "185.6ms", | 295 | "185.6ms", |
298 | }; | 296 | }; |
299 | 297 | ||
300 | static const struct soc_enum drc_atk = | 298 | static SOC_ENUM_SINGLE_DECL(drc_atk, WM9081_DRC_2, 12, drc_atk_text); |
301 | SOC_ENUM_SINGLE(WM9081_DRC_2, 12, 12, drc_atk_text); | ||
302 | 299 | ||
303 | static const char *drc_dcy_text[] = { | 300 | static const char *drc_dcy_text[] = { |
304 | "186ms", | 301 | "186ms", |
@@ -312,8 +309,7 @@ static const char *drc_dcy_text[] = { | |||
312 | "47.56s", | 309 | "47.56s", |
313 | }; | 310 | }; |
314 | 311 | ||
315 | static const struct soc_enum drc_dcy = | 312 | static SOC_ENUM_SINGLE_DECL(drc_dcy, WM9081_DRC_2, 8, drc_dcy_text); |
316 | SOC_ENUM_SINGLE(WM9081_DRC_2, 8, 9, drc_dcy_text); | ||
317 | 313 | ||
318 | static const char *drc_qr_dcy_text[] = { | 314 | static const char *drc_qr_dcy_text[] = { |
319 | "0.725ms", | 315 | "0.725ms", |
@@ -321,8 +317,7 @@ static const char *drc_qr_dcy_text[] = { | |||
321 | "5.8ms", | 317 | "5.8ms", |
322 | }; | 318 | }; |
323 | 319 | ||
324 | static const struct soc_enum drc_qr_dcy = | 320 | static SOC_ENUM_SINGLE_DECL(drc_qr_dcy, WM9081_DRC_2, 4, drc_qr_dcy_text); |
325 | SOC_ENUM_SINGLE(WM9081_DRC_2, 4, 3, drc_qr_dcy_text); | ||
326 | 321 | ||
327 | static const char *dac_deemph_text[] = { | 322 | static const char *dac_deemph_text[] = { |
328 | "None", | 323 | "None", |
@@ -331,16 +326,16 @@ static const char *dac_deemph_text[] = { | |||
331 | "48kHz", | 326 | "48kHz", |
332 | }; | 327 | }; |
333 | 328 | ||
334 | static const struct soc_enum dac_deemph = | 329 | static SOC_ENUM_SINGLE_DECL(dac_deemph, WM9081_DAC_DIGITAL_2, 1, |
335 | SOC_ENUM_SINGLE(WM9081_DAC_DIGITAL_2, 1, 4, dac_deemph_text); | 330 | dac_deemph_text); |
336 | 331 | ||
337 | static const char *speaker_mode_text[] = { | 332 | static const char *speaker_mode_text[] = { |
338 | "Class D", | 333 | "Class D", |
339 | "Class AB", | 334 | "Class AB", |
340 | }; | 335 | }; |
341 | 336 | ||
342 | static const struct soc_enum speaker_mode = | 337 | static SOC_ENUM_SINGLE_DECL(speaker_mode, WM9081_ANALOGUE_SPEAKER_2, 6, |
343 | SOC_ENUM_SINGLE(WM9081_ANALOGUE_SPEAKER_2, 6, 2, speaker_mode_text); | 338 | speaker_mode_text); |
344 | 339 | ||
345 | static int speaker_mode_get(struct snd_kcontrol *kcontrol, | 340 | static int speaker_mode_get(struct snd_kcontrol *kcontrol, |
346 | struct snd_ctl_elem_value *ucontrol) | 341 | struct snd_ctl_elem_value *ucontrol) |
@@ -1265,15 +1260,6 @@ static struct snd_soc_dai_driver wm9081_dai = { | |||
1265 | static int wm9081_probe(struct snd_soc_codec *codec) | 1260 | static int wm9081_probe(struct snd_soc_codec *codec) |
1266 | { | 1261 | { |
1267 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); | 1262 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); |
1268 | int ret; | ||
1269 | |||
1270 | codec->control_data = wm9081->regmap; | ||
1271 | |||
1272 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
1273 | if (ret != 0) { | ||
1274 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1275 | return ret; | ||
1276 | } | ||
1277 | 1263 | ||
1278 | /* Enable zero cross by default */ | 1264 | /* Enable zero cross by default */ |
1279 | snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT, | 1265 | snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT, |
@@ -1288,7 +1274,7 @@ static int wm9081_probe(struct snd_soc_codec *codec) | |||
1288 | ARRAY_SIZE(wm9081_eq_controls)); | 1274 | ARRAY_SIZE(wm9081_eq_controls)); |
1289 | } | 1275 | } |
1290 | 1276 | ||
1291 | return ret; | 1277 | return 0; |
1292 | } | 1278 | } |
1293 | 1279 | ||
1294 | static int wm9081_remove(struct snd_soc_codec *codec) | 1280 | static int wm9081_remove(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index a07fe1618eec..87934171f063 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -522,16 +522,6 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, | |||
522 | 522 | ||
523 | static int wm9090_probe(struct snd_soc_codec *codec) | 523 | static int wm9090_probe(struct snd_soc_codec *codec) |
524 | { | 524 | { |
525 | struct wm9090_priv *wm9090 = dev_get_drvdata(codec->dev); | ||
526 | int ret; | ||
527 | |||
528 | codec->control_data = wm9090->regmap; | ||
529 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
530 | if (ret != 0) { | ||
531 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
532 | return ret; | ||
533 | } | ||
534 | |||
535 | /* Configure some defaults; they will be written out when we | 525 | /* Configure some defaults; they will be written out when we |
536 | * bring the bias up. | 526 | * bring the bias up. |
537 | */ | 527 | */ |
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 70ce6793c5bd..c0b7f45dfa37 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
@@ -67,12 +67,12 @@ static const char *wm9705_mic[] = {"Mic 1", "Mic 2"}; | |||
67 | static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC", | 67 | static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC", |
68 | "Line", "Stereo Mix", "Mono Mix", "Phone"}; | 68 | "Line", "Stereo Mix", "Mono Mix", "Phone"}; |
69 | 69 | ||
70 | static const struct soc_enum wm9705_enum_mic = | 70 | static SOC_ENUM_SINGLE_DECL(wm9705_enum_mic, |
71 | SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, wm9705_mic); | 71 | AC97_GENERAL_PURPOSE, 8, wm9705_mic); |
72 | static const struct soc_enum wm9705_enum_rec_l = | 72 | static SOC_ENUM_SINGLE_DECL(wm9705_enum_rec_l, |
73 | SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9705_rec_sel); | 73 | AC97_REC_SEL, 8, wm9705_rec_sel); |
74 | static const struct soc_enum wm9705_enum_rec_r = | 74 | static SOC_ENUM_SINGLE_DECL(wm9705_enum_rec_r, |
75 | SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9705_rec_sel); | 75 | AC97_REC_SEL, 0, wm9705_rec_sel); |
76 | 76 | ||
77 | /* Headphone Mixer */ | 77 | /* Headphone Mixer */ |
78 | static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = { | 78 | static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = { |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 444626fcab40..bb5f7b4e3ebb 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -684,24 +684,38 @@ static int wm_adsp_load(struct wm_adsp *dsp) | |||
684 | } | 684 | } |
685 | 685 | ||
686 | if (reg) { | 686 | if (reg) { |
687 | buf = wm_adsp_buf_alloc(region->data, | 687 | size_t to_write = PAGE_SIZE; |
688 | le32_to_cpu(region->len), | 688 | size_t remain = le32_to_cpu(region->len); |
689 | &buf_list); | 689 | const u8 *data = region->data; |
690 | if (!buf) { | 690 | |
691 | adsp_err(dsp, "Out of memory\n"); | 691 | while (remain > 0) { |
692 | ret = -ENOMEM; | 692 | if (remain < PAGE_SIZE) |
693 | goto out_fw; | 693 | to_write = remain; |
694 | } | 694 | |
695 | buf = wm_adsp_buf_alloc(data, | ||
696 | to_write, | ||
697 | &buf_list); | ||
698 | if (!buf) { | ||
699 | adsp_err(dsp, "Out of memory\n"); | ||
700 | ret = -ENOMEM; | ||
701 | goto out_fw; | ||
702 | } | ||
695 | 703 | ||
696 | ret = regmap_raw_write_async(regmap, reg, buf->buf, | 704 | ret = regmap_raw_write_async(regmap, reg, |
697 | le32_to_cpu(region->len)); | 705 | buf->buf, |
698 | if (ret != 0) { | 706 | to_write); |
699 | adsp_err(dsp, | 707 | if (ret != 0) { |
700 | "%s.%d: Failed to write %d bytes at %d in %s: %d\n", | 708 | adsp_err(dsp, |
701 | file, regions, | 709 | "%s.%d: Failed to write %zd bytes at %d in %s: %d\n", |
702 | le32_to_cpu(region->len), offset, | 710 | file, regions, |
703 | region_name, ret); | 711 | to_write, offset, |
704 | goto out_fw; | 712 | region_name, ret); |
713 | goto out_fw; | ||
714 | } | ||
715 | |||
716 | data += to_write; | ||
717 | reg += to_write / 2; | ||
718 | remain -= to_write; | ||
705 | } | 719 | } |
706 | } | 720 | } |
707 | 721 | ||
@@ -1679,6 +1693,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
1679 | list_del(&alg_region->list); | 1693 | list_del(&alg_region->list); |
1680 | kfree(alg_region); | 1694 | kfree(alg_region); |
1681 | } | 1695 | } |
1696 | |||
1697 | adsp_dbg(dsp, "Shutdown complete\n"); | ||
1682 | break; | 1698 | break; |
1683 | 1699 | ||
1684 | default: | 1700 | default: |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index b371066dd5bc..b6209662ab13 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -50,16 +50,16 @@ static const char *speaker_ref_text[] = { | |||
50 | "VMID", | 50 | "VMID", |
51 | }; | 51 | }; |
52 | 52 | ||
53 | static const struct soc_enum speaker_ref = | 53 | static SOC_ENUM_SINGLE_DECL(speaker_ref, |
54 | SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text); | 54 | WM8993_SPEAKER_MIXER, 8, speaker_ref_text); |
55 | 55 | ||
56 | static const char *speaker_mode_text[] = { | 56 | static const char *speaker_mode_text[] = { |
57 | "Class D", | 57 | "Class D", |
58 | "Class AB", | 58 | "Class AB", |
59 | }; | 59 | }; |
60 | 60 | ||
61 | static const struct soc_enum speaker_mode = | 61 | static SOC_ENUM_SINGLE_DECL(speaker_mode, |
62 | SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); | 62 | WM8993_SPKMIXR_ATTENUATION, 8, speaker_mode_text); |
63 | 63 | ||
64 | static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) | 64 | static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) |
65 | { | 65 | { |
@@ -735,15 +735,15 @@ static const char *hp_mux_text[] = { | |||
735 | "DAC", | 735 | "DAC", |
736 | }; | 736 | }; |
737 | 737 | ||
738 | static const struct soc_enum hpl_enum = | 738 | static SOC_ENUM_SINGLE_DECL(hpl_enum, |
739 | SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text); | 739 | WM8993_OUTPUT_MIXER1, 8, hp_mux_text); |
740 | 740 | ||
741 | const struct snd_kcontrol_new wm_hubs_hpl_mux = | 741 | const struct snd_kcontrol_new wm_hubs_hpl_mux = |
742 | WM_HUBS_ENUM_W("Left Headphone Mux", hpl_enum); | 742 | WM_HUBS_ENUM_W("Left Headphone Mux", hpl_enum); |
743 | EXPORT_SYMBOL_GPL(wm_hubs_hpl_mux); | 743 | EXPORT_SYMBOL_GPL(wm_hubs_hpl_mux); |
744 | 744 | ||
745 | static const struct soc_enum hpr_enum = | 745 | static SOC_ENUM_SINGLE_DECL(hpr_enum, |
746 | SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text); | 746 | WM8993_OUTPUT_MIXER2, 8, hp_mux_text); |
747 | 747 | ||
748 | const struct snd_kcontrol_new wm_hubs_hpr_mux = | 748 | const struct snd_kcontrol_new wm_hubs_hpr_mux = |
749 | WM_HUBS_ENUM_W("Right Headphone Mux", hpr_enum); | 749 | WM_HUBS_ENUM_W("Right Headphone Mux", hpr_enum); |
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 70ff3772079f..cab98a580053 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/platform_data/edma.h> | 17 | #include <linux/platform_data/edma.h> |
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/of_platform.h> | 19 | #include <linux/of_platform.h> |
20 | #include <linux/clk.h> | ||
20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
21 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
22 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
@@ -30,9 +31,34 @@ | |||
30 | #include "davinci-i2s.h" | 31 | #include "davinci-i2s.h" |
31 | 32 | ||
32 | struct snd_soc_card_drvdata_davinci { | 33 | struct snd_soc_card_drvdata_davinci { |
34 | struct clk *mclk; | ||
33 | unsigned sysclk; | 35 | unsigned sysclk; |
34 | }; | 36 | }; |
35 | 37 | ||
38 | static int evm_startup(struct snd_pcm_substream *substream) | ||
39 | { | ||
40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
41 | struct snd_soc_card *soc_card = rtd->codec->card; | ||
42 | struct snd_soc_card_drvdata_davinci *drvdata = | ||
43 | snd_soc_card_get_drvdata(soc_card); | ||
44 | |||
45 | if (drvdata->mclk) | ||
46 | return clk_prepare_enable(drvdata->mclk); | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static void evm_shutdown(struct snd_pcm_substream *substream) | ||
52 | { | ||
53 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
54 | struct snd_soc_card *soc_card = rtd->codec->card; | ||
55 | struct snd_soc_card_drvdata_davinci *drvdata = | ||
56 | snd_soc_card_get_drvdata(soc_card); | ||
57 | |||
58 | if (drvdata->mclk) | ||
59 | clk_disable_unprepare(drvdata->mclk); | ||
60 | } | ||
61 | |||
36 | static int evm_hw_params(struct snd_pcm_substream *substream, | 62 | static int evm_hw_params(struct snd_pcm_substream *substream, |
37 | struct snd_pcm_hw_params *params) | 63 | struct snd_pcm_hw_params *params) |
38 | { | 64 | { |
@@ -59,6 +85,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream, | |||
59 | } | 85 | } |
60 | 86 | ||
61 | static struct snd_soc_ops evm_ops = { | 87 | static struct snd_soc_ops evm_ops = { |
88 | .startup = evm_startup, | ||
89 | .shutdown = evm_shutdown, | ||
62 | .hw_params = evm_hw_params, | 90 | .hw_params = evm_hw_params, |
63 | }; | 91 | }; |
64 | 92 | ||
@@ -95,35 +123,29 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
95 | /* Logic for a aic3x as connected on a davinci-evm */ | 123 | /* Logic for a aic3x as connected on a davinci-evm */ |
96 | static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) | 124 | static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) |
97 | { | 125 | { |
126 | struct snd_soc_card *card = rtd->card; | ||
98 | struct snd_soc_codec *codec = rtd->codec; | 127 | struct snd_soc_codec *codec = rtd->codec; |
99 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
100 | struct device_node *np = codec->card->dev->of_node; | 128 | struct device_node *np = codec->card->dev->of_node; |
101 | int ret; | 129 | int ret; |
102 | 130 | ||
103 | /* Add davinci-evm specific widgets */ | 131 | /* Add davinci-evm specific widgets */ |
104 | snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, | 132 | snd_soc_dapm_new_controls(&card->dapm, aic3x_dapm_widgets, |
105 | ARRAY_SIZE(aic3x_dapm_widgets)); | 133 | ARRAY_SIZE(aic3x_dapm_widgets)); |
106 | 134 | ||
107 | if (np) { | 135 | if (np) { |
108 | ret = snd_soc_of_parse_audio_routing(codec->card, | 136 | ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing"); |
109 | "ti,audio-routing"); | ||
110 | if (ret) | 137 | if (ret) |
111 | return ret; | 138 | return ret; |
112 | } else { | 139 | } else { |
113 | /* Set up davinci-evm specific audio path audio_map */ | 140 | /* Set up davinci-evm specific audio path audio_map */ |
114 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | 141 | snd_soc_dapm_add_routes(&card->dapm, audio_map, |
142 | ARRAY_SIZE(audio_map)); | ||
115 | } | 143 | } |
116 | 144 | ||
117 | /* not connected */ | 145 | /* not connected */ |
118 | snd_soc_dapm_disable_pin(dapm, "MONO_LOUT"); | 146 | snd_soc_dapm_nc_pin(&codec->dapm, "MONO_LOUT"); |
119 | snd_soc_dapm_disable_pin(dapm, "HPLCOM"); | 147 | snd_soc_dapm_nc_pin(&codec->dapm, "HPLCOM"); |
120 | snd_soc_dapm_disable_pin(dapm, "HPRCOM"); | 148 | snd_soc_dapm_nc_pin(&codec->dapm, "HPRCOM"); |
121 | |||
122 | /* always connected */ | ||
123 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | ||
124 | snd_soc_dapm_enable_pin(dapm, "Line Out"); | ||
125 | snd_soc_dapm_enable_pin(dapm, "Mic Jack"); | ||
126 | snd_soc_dapm_enable_pin(dapm, "Line In"); | ||
127 | 149 | ||
128 | return 0; | 150 | return 0; |
129 | } | 151 | } |
@@ -348,6 +370,7 @@ static int davinci_evm_probe(struct platform_device *pdev) | |||
348 | of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev); | 370 | of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev); |
349 | struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data; | 371 | struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data; |
350 | struct snd_soc_card_drvdata_davinci *drvdata = NULL; | 372 | struct snd_soc_card_drvdata_davinci *drvdata = NULL; |
373 | struct clk *mclk; | ||
351 | int ret = 0; | 374 | int ret = 0; |
352 | 375 | ||
353 | evm_soc_card.dai_link = dai; | 376 | evm_soc_card.dai_link = dai; |
@@ -367,13 +390,38 @@ static int davinci_evm_probe(struct platform_device *pdev) | |||
367 | if (ret) | 390 | if (ret) |
368 | return ret; | 391 | return ret; |
369 | 392 | ||
393 | mclk = devm_clk_get(&pdev->dev, "mclk"); | ||
394 | if (PTR_ERR(mclk) == -EPROBE_DEFER) { | ||
395 | return -EPROBE_DEFER; | ||
396 | } else if (IS_ERR(mclk)) { | ||
397 | dev_dbg(&pdev->dev, "mclk not found.\n"); | ||
398 | mclk = NULL; | ||
399 | } | ||
400 | |||
370 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); | 401 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); |
371 | if (!drvdata) | 402 | if (!drvdata) |
372 | return -ENOMEM; | 403 | return -ENOMEM; |
373 | 404 | ||
405 | drvdata->mclk = mclk; | ||
406 | |||
374 | ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk); | 407 | ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk); |
375 | if (ret < 0) | 408 | |
376 | return -EINVAL; | 409 | if (ret < 0) { |
410 | if (!drvdata->mclk) { | ||
411 | dev_err(&pdev->dev, | ||
412 | "No clock or clock rate defined.\n"); | ||
413 | return -EINVAL; | ||
414 | } | ||
415 | drvdata->sysclk = clk_get_rate(drvdata->mclk); | ||
416 | } else if (drvdata->mclk) { | ||
417 | unsigned int requestd_rate = drvdata->sysclk; | ||
418 | clk_set_rate(drvdata->mclk, drvdata->sysclk); | ||
419 | drvdata->sysclk = clk_get_rate(drvdata->mclk); | ||
420 | if (drvdata->sysclk != requestd_rate) | ||
421 | dev_warn(&pdev->dev, | ||
422 | "Could not get requested rate %u using %u.\n", | ||
423 | requestd_rate, drvdata->sysclk); | ||
424 | } | ||
377 | 425 | ||
378 | snd_soc_card_set_drvdata(&evm_soc_card, drvdata); | 426 | snd_soc_card_set_drvdata(&evm_soc_card, drvdata); |
379 | ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card); | 427 | ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card); |
@@ -399,6 +447,7 @@ static struct platform_driver davinci_evm_driver = { | |||
399 | .driver = { | 447 | .driver = { |
400 | .name = "davinci_evm", | 448 | .name = "davinci_evm", |
401 | .owner = THIS_MODULE, | 449 | .owner = THIS_MODULE, |
450 | .pm = &snd_soc_pm_ops, | ||
402 | .of_match_table = of_match_ptr(davinci_evm_dt_ids), | 451 | .of_match_table = of_match_ptr(davinci_evm_dt_ids), |
403 | }, | 452 | }, |
404 | }; | 453 | }; |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index b7858bfa0295..a01ae97c90aa 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -37,6 +37,16 @@ | |||
37 | #include "davinci-pcm.h" | 37 | #include "davinci-pcm.h" |
38 | #include "davinci-mcasp.h" | 38 | #include "davinci-mcasp.h" |
39 | 39 | ||
40 | struct davinci_mcasp_context { | ||
41 | u32 txfmtctl; | ||
42 | u32 rxfmtctl; | ||
43 | u32 txfmt; | ||
44 | u32 rxfmt; | ||
45 | u32 aclkxctl; | ||
46 | u32 aclkrctl; | ||
47 | u32 pdir; | ||
48 | }; | ||
49 | |||
40 | struct davinci_mcasp { | 50 | struct davinci_mcasp { |
41 | struct davinci_pcm_dma_params dma_params[2]; | 51 | struct davinci_pcm_dma_params dma_params[2]; |
42 | struct snd_dmaengine_dai_dma_data dma_data[2]; | 52 | struct snd_dmaengine_dai_dma_data dma_data[2]; |
@@ -53,6 +63,9 @@ struct davinci_mcasp { | |||
53 | u16 bclk_lrclk_ratio; | 63 | u16 bclk_lrclk_ratio; |
54 | int streams; | 64 | int streams; |
55 | 65 | ||
66 | int sysclk_freq; | ||
67 | bool bclk_master; | ||
68 | |||
56 | /* McASP FIFO related */ | 69 | /* McASP FIFO related */ |
57 | u8 txnumevt; | 70 | u8 txnumevt; |
58 | u8 rxnumevt; | 71 | u8 rxnumevt; |
@@ -60,15 +73,7 @@ struct davinci_mcasp { | |||
60 | bool dat_port; | 73 | bool dat_port; |
61 | 74 | ||
62 | #ifdef CONFIG_PM_SLEEP | 75 | #ifdef CONFIG_PM_SLEEP |
63 | struct { | 76 | struct davinci_mcasp_context context; |
64 | u32 txfmtctl; | ||
65 | u32 rxfmtctl; | ||
66 | u32 txfmt; | ||
67 | u32 rxfmt; | ||
68 | u32 aclkxctl; | ||
69 | u32 aclkrctl; | ||
70 | u32 pdir; | ||
71 | } context; | ||
72 | #endif | 77 | #endif |
73 | }; | 78 | }; |
74 | 79 | ||
@@ -263,7 +268,9 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
263 | unsigned int fmt) | 268 | unsigned int fmt) |
264 | { | 269 | { |
265 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); | 270 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); |
271 | int ret = 0; | ||
266 | 272 | ||
273 | pm_runtime_get_sync(mcasp->dev); | ||
267 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 274 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
268 | case SND_SOC_DAIFMT_DSP_B: | 275 | case SND_SOC_DAIFMT_DSP_B: |
269 | case SND_SOC_DAIFMT_AC97: | 276 | case SND_SOC_DAIFMT_AC97: |
@@ -292,6 +299,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
292 | 299 | ||
293 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); | 300 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); |
294 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); | 301 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); |
302 | mcasp->bclk_master = 1; | ||
295 | break; | 303 | break; |
296 | case SND_SOC_DAIFMT_CBM_CFS: | 304 | case SND_SOC_DAIFMT_CBM_CFS: |
297 | /* codec is clock master and frame slave */ | 305 | /* codec is clock master and frame slave */ |
@@ -303,6 +311,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
303 | 311 | ||
304 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); | 312 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); |
305 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); | 313 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); |
314 | mcasp->bclk_master = 0; | ||
306 | break; | 315 | break; |
307 | case SND_SOC_DAIFMT_CBM_CFM: | 316 | case SND_SOC_DAIFMT_CBM_CFM: |
308 | /* codec is clock and frame master */ | 317 | /* codec is clock and frame master */ |
@@ -314,10 +323,12 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
314 | 323 | ||
315 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, | 324 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, |
316 | ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); | 325 | ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); |
326 | mcasp->bclk_master = 0; | ||
317 | break; | 327 | break; |
318 | 328 | ||
319 | default: | 329 | default: |
320 | return -EINVAL; | 330 | ret = -EINVAL; |
331 | goto out; | ||
321 | } | 332 | } |
322 | 333 | ||
323 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 334 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
@@ -354,10 +365,12 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
354 | break; | 365 | break; |
355 | 366 | ||
356 | default: | 367 | default: |
357 | return -EINVAL; | 368 | ret = -EINVAL; |
369 | break; | ||
358 | } | 370 | } |
359 | 371 | out: | |
360 | return 0; | 372 | pm_runtime_put_sync(mcasp->dev); |
373 | return ret; | ||
361 | } | 374 | } |
362 | 375 | ||
363 | static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) | 376 | static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) |
@@ -405,6 +418,8 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
405 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX); | 418 | mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX); |
406 | } | 419 | } |
407 | 420 | ||
421 | mcasp->sysclk_freq = freq; | ||
422 | |||
408 | return 0; | 423 | return 0; |
409 | } | 424 | } |
410 | 425 | ||
@@ -448,7 +463,7 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, | |||
448 | return 0; | 463 | return 0; |
449 | } | 464 | } |
450 | 465 | ||
451 | static int davinci_hw_common_param(struct davinci_mcasp *mcasp, int stream, | 466 | static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, |
452 | int channels) | 467 | int channels) |
453 | { | 468 | { |
454 | int i; | 469 | int i; |
@@ -524,12 +539,18 @@ static int davinci_hw_common_param(struct davinci_mcasp *mcasp, int stream, | |||
524 | return 0; | 539 | return 0; |
525 | } | 540 | } |
526 | 541 | ||
527 | static void davinci_hw_param(struct davinci_mcasp *mcasp, int stream) | 542 | static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream) |
528 | { | 543 | { |
529 | int i, active_slots; | 544 | int i, active_slots; |
530 | u32 mask = 0; | 545 | u32 mask = 0; |
531 | u32 busel = 0; | 546 | u32 busel = 0; |
532 | 547 | ||
548 | if ((mcasp->tdm_slots < 2) || (mcasp->tdm_slots > 32)) { | ||
549 | dev_err(mcasp->dev, "tdm slot %d not supported\n", | ||
550 | mcasp->tdm_slots); | ||
551 | return -EINVAL; | ||
552 | } | ||
553 | |||
533 | active_slots = (mcasp->tdm_slots > 31) ? 32 : mcasp->tdm_slots; | 554 | active_slots = (mcasp->tdm_slots > 31) ? 32 : mcasp->tdm_slots; |
534 | for (i = 0; i < active_slots; i++) | 555 | for (i = 0; i < active_slots; i++) |
535 | mask |= (1 << i); | 556 | mask |= (1 << i); |
@@ -539,35 +560,21 @@ static void davinci_hw_param(struct davinci_mcasp *mcasp, int stream) | |||
539 | if (!mcasp->dat_port) | 560 | if (!mcasp->dat_port) |
540 | busel = TXSEL; | 561 | busel = TXSEL; |
541 | 562 | ||
542 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 563 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask); |
543 | /* bit stream is MSB first with no delay */ | 564 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD); |
544 | /* DSP_B mode */ | 565 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, |
545 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask); | 566 | FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF)); |
546 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD); | 567 | |
547 | 568 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask); | |
548 | if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32)) | 569 | mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD); |
549 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, | 570 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, |
550 | FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF)); | 571 | FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF)); |
551 | else | 572 | |
552 | printk(KERN_ERR "playback tdm slot %d not supported\n", | 573 | return 0; |
553 | mcasp->tdm_slots); | ||
554 | } else { | ||
555 | /* bit stream is MSB first with no delay */ | ||
556 | /* DSP_B mode */ | ||
557 | mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD); | ||
558 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask); | ||
559 | |||
560 | if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32)) | ||
561 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, | ||
562 | FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF)); | ||
563 | else | ||
564 | printk(KERN_ERR "capture tdm slot %d not supported\n", | ||
565 | mcasp->tdm_slots); | ||
566 | } | ||
567 | } | 574 | } |
568 | 575 | ||
569 | /* S/PDIF */ | 576 | /* S/PDIF */ |
570 | static void davinci_hw_dit_param(struct davinci_mcasp *mcasp) | 577 | static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp) |
571 | { | 578 | { |
572 | /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 | 579 | /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 |
573 | and LSB first */ | 580 | and LSB first */ |
@@ -589,6 +596,8 @@ static void davinci_hw_dit_param(struct davinci_mcasp *mcasp) | |||
589 | 596 | ||
590 | /* Enable the DIT */ | 597 | /* Enable the DIT */ |
591 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); | 598 | mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); |
599 | |||
600 | return 0; | ||
592 | } | 601 | } |
593 | 602 | ||
594 | static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | 603 | static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, |
@@ -604,24 +613,31 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
604 | u8 fifo_level; | 613 | u8 fifo_level; |
605 | u8 slots = mcasp->tdm_slots; | 614 | u8 slots = mcasp->tdm_slots; |
606 | u8 active_serializers; | 615 | u8 active_serializers; |
607 | int channels; | 616 | int channels = params_channels(params); |
608 | struct snd_interval *pcm_channels = hw_param_interval(params, | 617 | int ret; |
609 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
610 | channels = pcm_channels->min; | ||
611 | 618 | ||
612 | active_serializers = (channels + slots - 1) / slots; | 619 | /* If mcasp is BCLK master we need to set BCLK divider */ |
620 | if (mcasp->bclk_master) { | ||
621 | unsigned int bclk_freq = snd_soc_params_to_bclk(params); | ||
622 | if (mcasp->sysclk_freq % bclk_freq != 0) { | ||
623 | dev_err(mcasp->dev, "Can't produce requred BCLK\n"); | ||
624 | return -EINVAL; | ||
625 | } | ||
626 | davinci_mcasp_set_clkdiv( | ||
627 | cpu_dai, 1, mcasp->sysclk_freq / bclk_freq); | ||
628 | } | ||
613 | 629 | ||
614 | if (davinci_hw_common_param(mcasp, substream->stream, channels) == -EINVAL) | 630 | ret = mcasp_common_hw_param(mcasp, substream->stream, channels); |
615 | return -EINVAL; | 631 | if (ret) |
616 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 632 | return ret; |
617 | fifo_level = mcasp->txnumevt * active_serializers; | ||
618 | else | ||
619 | fifo_level = mcasp->rxnumevt * active_serializers; | ||
620 | 633 | ||
621 | if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) | 634 | if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) |
622 | davinci_hw_dit_param(mcasp); | 635 | ret = mcasp_dit_hw_param(mcasp); |
623 | else | 636 | else |
624 | davinci_hw_param(mcasp, substream->stream); | 637 | ret = mcasp_i2s_hw_param(mcasp, substream->stream); |
638 | |||
639 | if (ret) | ||
640 | return ret; | ||
625 | 641 | ||
626 | switch (params_format(params)) { | 642 | switch (params_format(params)) { |
627 | case SNDRV_PCM_FORMAT_U8: | 643 | case SNDRV_PCM_FORMAT_U8: |
@@ -655,6 +671,13 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
655 | return -EINVAL; | 671 | return -EINVAL; |
656 | } | 672 | } |
657 | 673 | ||
674 | /* Calculate FIFO level */ | ||
675 | active_serializers = (channels + slots - 1) / slots; | ||
676 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
677 | fifo_level = mcasp->txnumevt * active_serializers; | ||
678 | else | ||
679 | fifo_level = mcasp->rxnumevt * active_serializers; | ||
680 | |||
658 | if (mcasp->version == MCASP_VERSION_2 && !fifo_level) | 681 | if (mcasp->version == MCASP_VERSION_2 && !fifo_level) |
659 | dma_params->acnt = 4; | 682 | dma_params->acnt = 4; |
660 | else | 683 | else |
@@ -678,19 +701,9 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, | |||
678 | case SNDRV_PCM_TRIGGER_RESUME: | 701 | case SNDRV_PCM_TRIGGER_RESUME: |
679 | case SNDRV_PCM_TRIGGER_START: | 702 | case SNDRV_PCM_TRIGGER_START: |
680 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 703 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
681 | ret = pm_runtime_get_sync(mcasp->dev); | ||
682 | if (IS_ERR_VALUE(ret)) | ||
683 | dev_err(mcasp->dev, "pm_runtime_get_sync() failed\n"); | ||
684 | davinci_mcasp_start(mcasp, substream->stream); | 704 | davinci_mcasp_start(mcasp, substream->stream); |
685 | break; | 705 | break; |
686 | |||
687 | case SNDRV_PCM_TRIGGER_SUSPEND: | 706 | case SNDRV_PCM_TRIGGER_SUSPEND: |
688 | davinci_mcasp_stop(mcasp, substream->stream); | ||
689 | ret = pm_runtime_put_sync(mcasp->dev); | ||
690 | if (IS_ERR_VALUE(ret)) | ||
691 | dev_err(mcasp->dev, "pm_runtime_put_sync() failed\n"); | ||
692 | break; | ||
693 | |||
694 | case SNDRV_PCM_TRIGGER_STOP: | 707 | case SNDRV_PCM_TRIGGER_STOP: |
695 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 708 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
696 | davinci_mcasp_stop(mcasp, substream->stream); | 709 | davinci_mcasp_stop(mcasp, substream->stream); |
@@ -726,6 +739,43 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { | |||
726 | .set_sysclk = davinci_mcasp_set_sysclk, | 739 | .set_sysclk = davinci_mcasp_set_sysclk, |
727 | }; | 740 | }; |
728 | 741 | ||
742 | #ifdef CONFIG_PM_SLEEP | ||
743 | static int davinci_mcasp_suspend(struct snd_soc_dai *dai) | ||
744 | { | ||
745 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); | ||
746 | struct davinci_mcasp_context *context = &mcasp->context; | ||
747 | |||
748 | context->txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); | ||
749 | context->rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); | ||
750 | context->txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); | ||
751 | context->rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); | ||
752 | context->aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); | ||
753 | context->aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); | ||
754 | context->pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | static int davinci_mcasp_resume(struct snd_soc_dai *dai) | ||
760 | { | ||
761 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); | ||
762 | struct davinci_mcasp_context *context = &mcasp->context; | ||
763 | |||
764 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, context->txfmtctl); | ||
765 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, context->rxfmtctl); | ||
766 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, context->txfmt); | ||
767 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, context->rxfmt); | ||
768 | mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, context->aclkxctl); | ||
769 | mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, context->aclkrctl); | ||
770 | mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, context->pdir); | ||
771 | |||
772 | return 0; | ||
773 | } | ||
774 | #else | ||
775 | #define davinci_mcasp_suspend NULL | ||
776 | #define davinci_mcasp_resume NULL | ||
777 | #endif | ||
778 | |||
729 | #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000 | 779 | #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000 |
730 | 780 | ||
731 | #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ | 781 | #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ |
@@ -742,6 +792,8 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { | |||
742 | static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | 792 | static struct snd_soc_dai_driver davinci_mcasp_dai[] = { |
743 | { | 793 | { |
744 | .name = "davinci-mcasp.0", | 794 | .name = "davinci-mcasp.0", |
795 | .suspend = davinci_mcasp_suspend, | ||
796 | .resume = davinci_mcasp_resume, | ||
745 | .playback = { | 797 | .playback = { |
746 | .channels_min = 2, | 798 | .channels_min = 2, |
747 | .channels_max = 32 * 16, | 799 | .channels_max = 32 * 16, |
@@ -775,28 +827,28 @@ static const struct snd_soc_component_driver davinci_mcasp_component = { | |||
775 | }; | 827 | }; |
776 | 828 | ||
777 | /* Some HW specific values and defaults. The rest is filled in from DT. */ | 829 | /* Some HW specific values and defaults. The rest is filled in from DT. */ |
778 | static struct snd_platform_data dm646x_mcasp_pdata = { | 830 | static struct davinci_mcasp_pdata dm646x_mcasp_pdata = { |
779 | .tx_dma_offset = 0x400, | 831 | .tx_dma_offset = 0x400, |
780 | .rx_dma_offset = 0x400, | 832 | .rx_dma_offset = 0x400, |
781 | .asp_chan_q = EVENTQ_0, | 833 | .asp_chan_q = EVENTQ_0, |
782 | .version = MCASP_VERSION_1, | 834 | .version = MCASP_VERSION_1, |
783 | }; | 835 | }; |
784 | 836 | ||
785 | static struct snd_platform_data da830_mcasp_pdata = { | 837 | static struct davinci_mcasp_pdata da830_mcasp_pdata = { |
786 | .tx_dma_offset = 0x2000, | 838 | .tx_dma_offset = 0x2000, |
787 | .rx_dma_offset = 0x2000, | 839 | .rx_dma_offset = 0x2000, |
788 | .asp_chan_q = EVENTQ_0, | 840 | .asp_chan_q = EVENTQ_0, |
789 | .version = MCASP_VERSION_2, | 841 | .version = MCASP_VERSION_2, |
790 | }; | 842 | }; |
791 | 843 | ||
792 | static struct snd_platform_data am33xx_mcasp_pdata = { | 844 | static struct davinci_mcasp_pdata am33xx_mcasp_pdata = { |
793 | .tx_dma_offset = 0, | 845 | .tx_dma_offset = 0, |
794 | .rx_dma_offset = 0, | 846 | .rx_dma_offset = 0, |
795 | .asp_chan_q = EVENTQ_0, | 847 | .asp_chan_q = EVENTQ_0, |
796 | .version = MCASP_VERSION_3, | 848 | .version = MCASP_VERSION_3, |
797 | }; | 849 | }; |
798 | 850 | ||
799 | static struct snd_platform_data dra7_mcasp_pdata = { | 851 | static struct davinci_mcasp_pdata dra7_mcasp_pdata = { |
800 | .tx_dma_offset = 0x200, | 852 | .tx_dma_offset = 0x200, |
801 | .rx_dma_offset = 0x284, | 853 | .rx_dma_offset = 0x284, |
802 | .asp_chan_q = EVENTQ_0, | 854 | .asp_chan_q = EVENTQ_0, |
@@ -864,11 +916,11 @@ err1: | |||
864 | return ret; | 916 | return ret; |
865 | } | 917 | } |
866 | 918 | ||
867 | static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | 919 | static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of( |
868 | struct platform_device *pdev) | 920 | struct platform_device *pdev) |
869 | { | 921 | { |
870 | struct device_node *np = pdev->dev.of_node; | 922 | struct device_node *np = pdev->dev.of_node; |
871 | struct snd_platform_data *pdata = NULL; | 923 | struct davinci_mcasp_pdata *pdata = NULL; |
872 | const struct of_device_id *match = | 924 | const struct of_device_id *match = |
873 | of_match_device(mcasp_dt_ids, &pdev->dev); | 925 | of_match_device(mcasp_dt_ids, &pdev->dev); |
874 | struct of_phandle_args dma_spec; | 926 | struct of_phandle_args dma_spec; |
@@ -881,7 +933,7 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | |||
881 | pdata = pdev->dev.platform_data; | 933 | pdata = pdev->dev.platform_data; |
882 | return pdata; | 934 | return pdata; |
883 | } else if (match) { | 935 | } else if (match) { |
884 | pdata = (struct snd_platform_data *) match->data; | 936 | pdata = (struct davinci_mcasp_pdata*) match->data; |
885 | } else { | 937 | } else { |
886 | /* control shouldn't reach here. something is wrong */ | 938 | /* control shouldn't reach here. something is wrong */ |
887 | ret = -EINVAL; | 939 | ret = -EINVAL; |
@@ -973,9 +1025,10 @@ nodata: | |||
973 | 1025 | ||
974 | static int davinci_mcasp_probe(struct platform_device *pdev) | 1026 | static int davinci_mcasp_probe(struct platform_device *pdev) |
975 | { | 1027 | { |
976 | struct davinci_pcm_dma_params *dma_data; | 1028 | struct davinci_pcm_dma_params *dma_params; |
1029 | struct snd_dmaengine_dai_dma_data *dma_data; | ||
977 | struct resource *mem, *ioarea, *res, *dat; | 1030 | struct resource *mem, *ioarea, *res, *dat; |
978 | struct snd_platform_data *pdata; | 1031 | struct davinci_mcasp_pdata *pdata; |
979 | struct davinci_mcasp *mcasp; | 1032 | struct davinci_mcasp *mcasp; |
980 | int ret; | 1033 | int ret; |
981 | 1034 | ||
@@ -1042,41 +1095,49 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1042 | if (dat) | 1095 | if (dat) |
1043 | mcasp->dat_port = true; | 1096 | mcasp->dat_port = true; |
1044 | 1097 | ||
1045 | dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; | 1098 | dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; |
1046 | dma_data->asp_chan_q = pdata->asp_chan_q; | 1099 | dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; |
1047 | dma_data->ram_chan_q = pdata->ram_chan_q; | 1100 | dma_params->asp_chan_q = pdata->asp_chan_q; |
1048 | dma_data->sram_pool = pdata->sram_pool; | 1101 | dma_params->ram_chan_q = pdata->ram_chan_q; |
1049 | dma_data->sram_size = pdata->sram_size_playback; | 1102 | dma_params->sram_pool = pdata->sram_pool; |
1103 | dma_params->sram_size = pdata->sram_size_playback; | ||
1050 | if (dat) | 1104 | if (dat) |
1051 | dma_data->dma_addr = dat->start; | 1105 | dma_params->dma_addr = dat->start; |
1052 | else | 1106 | else |
1053 | dma_data->dma_addr = mem->start + pdata->tx_dma_offset; | 1107 | dma_params->dma_addr = mem->start + pdata->tx_dma_offset; |
1054 | 1108 | ||
1055 | /* Unconditional dmaengine stuff */ | 1109 | /* Unconditional dmaengine stuff */ |
1056 | mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_data->dma_addr; | 1110 | dma_data->addr = dma_params->dma_addr; |
1057 | 1111 | ||
1058 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 1112 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
1059 | if (res) | 1113 | if (res) |
1060 | dma_data->channel = res->start; | 1114 | dma_params->channel = res->start; |
1061 | else | 1115 | else |
1062 | dma_data->channel = pdata->tx_dma_channel; | 1116 | dma_params->channel = pdata->tx_dma_channel; |
1063 | 1117 | ||
1064 | dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; | 1118 | /* dmaengine filter data for DT and non-DT boot */ |
1065 | dma_data->asp_chan_q = pdata->asp_chan_q; | 1119 | if (pdev->dev.of_node) |
1066 | dma_data->ram_chan_q = pdata->ram_chan_q; | 1120 | dma_data->filter_data = "tx"; |
1067 | dma_data->sram_pool = pdata->sram_pool; | 1121 | else |
1068 | dma_data->sram_size = pdata->sram_size_capture; | 1122 | dma_data->filter_data = &dma_params->channel; |
1123 | |||
1124 | dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; | ||
1125 | dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; | ||
1126 | dma_params->asp_chan_q = pdata->asp_chan_q; | ||
1127 | dma_params->ram_chan_q = pdata->ram_chan_q; | ||
1128 | dma_params->sram_pool = pdata->sram_pool; | ||
1129 | dma_params->sram_size = pdata->sram_size_capture; | ||
1069 | if (dat) | 1130 | if (dat) |
1070 | dma_data->dma_addr = dat->start; | 1131 | dma_params->dma_addr = dat->start; |
1071 | else | 1132 | else |
1072 | dma_data->dma_addr = mem->start + pdata->rx_dma_offset; | 1133 | dma_params->dma_addr = mem->start + pdata->rx_dma_offset; |
1073 | 1134 | ||
1074 | /* Unconditional dmaengine stuff */ | 1135 | /* Unconditional dmaengine stuff */ |
1075 | mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_data->dma_addr; | 1136 | dma_data->addr = dma_params->dma_addr; |
1076 | 1137 | ||
1077 | if (mcasp->version < MCASP_VERSION_3) { | 1138 | if (mcasp->version < MCASP_VERSION_3) { |
1078 | mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE; | 1139 | mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE; |
1079 | /* dma_data->dma_addr is pointing to the data port address */ | 1140 | /* dma_params->dma_addr is pointing to the data port address */ |
1080 | mcasp->dat_port = true; | 1141 | mcasp->dat_port = true; |
1081 | } else { | 1142 | } else { |
1082 | mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE; | 1143 | mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE; |
@@ -1084,13 +1145,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1084 | 1145 | ||
1085 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 1146 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
1086 | if (res) | 1147 | if (res) |
1087 | dma_data->channel = res->start; | 1148 | dma_params->channel = res->start; |
1088 | else | 1149 | else |
1089 | dma_data->channel = pdata->rx_dma_channel; | 1150 | dma_params->channel = pdata->rx_dma_channel; |
1090 | 1151 | ||
1091 | /* Unconditional dmaengine stuff */ | 1152 | /* dmaengine filter data for DT and non-DT boot */ |
1092 | mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = "tx"; | 1153 | if (pdev->dev.of_node) |
1093 | mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data = "rx"; | 1154 | dma_data->filter_data = "rx"; |
1155 | else | ||
1156 | dma_data->filter_data = &dma_params->channel; | ||
1094 | 1157 | ||
1095 | dev_set_drvdata(&pdev->dev, mcasp); | 1158 | dev_set_drvdata(&pdev->dev, mcasp); |
1096 | 1159 | ||
@@ -1134,49 +1197,12 @@ static int davinci_mcasp_remove(struct platform_device *pdev) | |||
1134 | return 0; | 1197 | return 0; |
1135 | } | 1198 | } |
1136 | 1199 | ||
1137 | #ifdef CONFIG_PM_SLEEP | ||
1138 | static int davinci_mcasp_suspend(struct device *dev) | ||
1139 | { | ||
1140 | struct davinci_mcasp *mcasp = dev_get_drvdata(dev); | ||
1141 | |||
1142 | mcasp->context.txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); | ||
1143 | mcasp->context.rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); | ||
1144 | mcasp->context.txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); | ||
1145 | mcasp->context.rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); | ||
1146 | mcasp->context.aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); | ||
1147 | mcasp->context.aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); | ||
1148 | mcasp->context.pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); | ||
1149 | |||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1153 | static int davinci_mcasp_resume(struct device *dev) | ||
1154 | { | ||
1155 | struct davinci_mcasp *mcasp = dev_get_drvdata(dev); | ||
1156 | |||
1157 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, mcasp->context.txfmtctl); | ||
1158 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, mcasp->context.rxfmtctl); | ||
1159 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, mcasp->context.txfmt); | ||
1160 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, mcasp->context.rxfmt); | ||
1161 | mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, mcasp->context.aclkxctl); | ||
1162 | mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, mcasp->context.aclkrctl); | ||
1163 | mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, mcasp->context.pdir); | ||
1164 | |||
1165 | return 0; | ||
1166 | } | ||
1167 | #endif | ||
1168 | |||
1169 | SIMPLE_DEV_PM_OPS(davinci_mcasp_pm_ops, | ||
1170 | davinci_mcasp_suspend, | ||
1171 | davinci_mcasp_resume); | ||
1172 | |||
1173 | static struct platform_driver davinci_mcasp_driver = { | 1200 | static struct platform_driver davinci_mcasp_driver = { |
1174 | .probe = davinci_mcasp_probe, | 1201 | .probe = davinci_mcasp_probe, |
1175 | .remove = davinci_mcasp_remove, | 1202 | .remove = davinci_mcasp_remove, |
1176 | .driver = { | 1203 | .driver = { |
1177 | .name = "davinci-mcasp", | 1204 | .name = "davinci-mcasp", |
1178 | .owner = THIS_MODULE, | 1205 | .owner = THIS_MODULE, |
1179 | .pm = &davinci_mcasp_pm_ops, | ||
1180 | .of_match_table = mcasp_dt_ids, | 1206 | .of_match_table = mcasp_dt_ids, |
1181 | }, | 1207 | }, |
1182 | }; | 1208 | }; |
diff --git a/sound/soc/davinci/edma-pcm.c b/sound/soc/davinci/edma-pcm.c new file mode 100644 index 000000000000..d38afb1c61ae --- /dev/null +++ b/sound/soc/davinci/edma-pcm.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * edma-pcm.c - eDMA PCM driver using dmaengine for AM3xxx, AM4xxx | ||
3 | * | ||
4 | * Copyright (C) 2014 Texas Instruments, Inc. | ||
5 | * | ||
6 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
7 | * | ||
8 | * Based on: sound/soc/tegra/tegra_pcm.c | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/dmaengine_pcm.h> | ||
26 | #include <linux/edma.h> | ||
27 | |||
28 | static const struct snd_pcm_hardware edma_pcm_hardware = { | ||
29 | .info = SNDRV_PCM_INFO_MMAP | | ||
30 | SNDRV_PCM_INFO_MMAP_VALID | | ||
31 | SNDRV_PCM_INFO_BATCH | | ||
32 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | | ||
33 | SNDRV_PCM_INFO_INTERLEAVED, | ||
34 | .buffer_bytes_max = 128 * 1024, | ||
35 | .period_bytes_min = 32, | ||
36 | .period_bytes_max = 64 * 1024, | ||
37 | .periods_min = 2, | ||
38 | .periods_max = 19, /* Limit by edma dmaengine driver */ | ||
39 | }; | ||
40 | |||
41 | static const struct snd_dmaengine_pcm_config edma_dmaengine_pcm_config = { | ||
42 | .pcm_hardware = &edma_pcm_hardware, | ||
43 | .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, | ||
44 | .compat_filter_fn = edma_filter_fn, | ||
45 | .prealloc_buffer_size = 128 * 1024, | ||
46 | }; | ||
47 | |||
48 | int edma_pcm_platform_register(struct device *dev) | ||
49 | { | ||
50 | return devm_snd_dmaengine_pcm_register(dev, &edma_dmaengine_pcm_config, | ||
51 | SND_DMAENGINE_PCM_FLAG_COMPAT); | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(edma_pcm_platform_register); | ||
54 | |||
55 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | ||
56 | MODULE_DESCRIPTION("eDMA PCM ASoC platform driver"); | ||
57 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/davinci/edma-pcm.h b/sound/soc/davinci/edma-pcm.h new file mode 100644 index 000000000000..894c378c0f74 --- /dev/null +++ b/sound/soc/davinci/edma-pcm.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * edma-pcm.h - eDMA PCM driver using dmaengine for AM3xxx, AM4xxx | ||
3 | * | ||
4 | * Copyright (C) 2014 Texas Instruments, Inc. | ||
5 | * | ||
6 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
7 | * | ||
8 | * Based on: sound/soc/tegra/tegra_pcm.h | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | */ | ||
19 | |||
20 | #ifndef __EDMA_PCM_H__ | ||
21 | #define __EDMA_PCM_H__ | ||
22 | |||
23 | int edma_pcm_platform_register(struct device *dev); | ||
24 | |||
25 | #endif /* __EDMA_PCM_H__ */ | ||
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 07f8f141727d..597962ec28fa 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | config SND_SOC_FSL_SAI | 1 | config SND_SOC_FSL_SAI |
2 | tristate | 2 | tristate |
3 | select REGMAP_MMIO | ||
3 | select SND_SOC_GENERIC_DMAENGINE_PCM | 4 | select SND_SOC_GENERIC_DMAENGINE_PCM |
4 | 5 | ||
5 | config SND_SOC_FSL_SSI | 6 | config SND_SOC_FSL_SSI |
@@ -7,9 +8,11 @@ config SND_SOC_FSL_SSI | |||
7 | 8 | ||
8 | config SND_SOC_FSL_SPDIF | 9 | config SND_SOC_FSL_SPDIF |
9 | tristate | 10 | tristate |
11 | select REGMAP_MMIO | ||
10 | 12 | ||
11 | config SND_SOC_FSL_ESAI | 13 | config SND_SOC_FSL_ESAI |
12 | tristate | 14 | tristate |
15 | select REGMAP_MMIO | ||
13 | 16 | ||
14 | config SND_SOC_FSL_UTILS | 17 | config SND_SOC_FSL_UTILS |
15 | tristate | 18 | tristate |
@@ -168,12 +171,14 @@ config SND_SOC_EUKREA_TLV320 | |||
168 | depends on MACH_EUKREA_MBIMX27_BASEBOARD \ | 171 | depends on MACH_EUKREA_MBIMX27_BASEBOARD \ |
169 | || MACH_EUKREA_MBIMXSD25_BASEBOARD \ | 172 | || MACH_EUKREA_MBIMXSD25_BASEBOARD \ |
170 | || MACH_EUKREA_MBIMXSD35_BASEBOARD \ | 173 | || MACH_EUKREA_MBIMXSD35_BASEBOARD \ |
171 | || MACH_EUKREA_MBIMXSD51_BASEBOARD | 174 | || MACH_EUKREA_MBIMXSD51_BASEBOARD \ |
175 | || (OF && ARM) | ||
172 | depends on I2C | 176 | depends on I2C |
173 | select SND_SOC_TLV320AIC23 | 177 | select SND_SOC_TLV320AIC23_I2C |
174 | select SND_SOC_IMX_PCM_FIQ | ||
175 | select SND_SOC_IMX_AUDMUX | 178 | select SND_SOC_IMX_AUDMUX |
176 | select SND_SOC_IMX_SSI | 179 | select SND_SOC_IMX_SSI |
180 | select SND_SOC_FSL_SSI | ||
181 | select SND_SOC_IMX_PCM_DMA | ||
177 | help | 182 | help |
178 | Enable I2S based access to the TLV320AIC23B codec attached | 183 | Enable I2S based access to the TLV320AIC23B codec attached |
179 | to the SSI interface | 184 | to the SSI interface |
@@ -204,7 +209,6 @@ config SND_SOC_IMX_SPDIF | |||
204 | tristate "SoC Audio support for i.MX boards with S/PDIF" | 209 | tristate "SoC Audio support for i.MX boards with S/PDIF" |
205 | select SND_SOC_IMX_PCM_DMA | 210 | select SND_SOC_IMX_PCM_DMA |
206 | select SND_SOC_FSL_SPDIF | 211 | select SND_SOC_FSL_SPDIF |
207 | select REGMAP_MMIO | ||
208 | help | 212 | help |
209 | SoC Audio support for i.MX boards with S/PDIF | 213 | SoC Audio support for i.MX boards with S/PDIF |
210 | Say Y if you want to add support for SoC audio on an i.MX board with | 214 | Say Y if you want to add support for SoC audio on an i.MX board with |
diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 5983740be123..eb093d5b85c4 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c | |||
@@ -15,8 +15,11 @@ | |||
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/errno.h> | ||
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | #include <linux/moduleparam.h> | 20 | #include <linux/moduleparam.h> |
21 | #include <linux/of.h> | ||
22 | #include <linux/of_platform.h> | ||
20 | #include <linux/device.h> | 23 | #include <linux/device.h> |
21 | #include <linux/i2c.h> | 24 | #include <linux/i2c.h> |
22 | #include <sound/core.h> | 25 | #include <sound/core.h> |
@@ -26,6 +29,7 @@ | |||
26 | 29 | ||
27 | #include "../codecs/tlv320aic23.h" | 30 | #include "../codecs/tlv320aic23.h" |
28 | #include "imx-ssi.h" | 31 | #include "imx-ssi.h" |
32 | #include "fsl_ssi.h" | ||
29 | #include "imx-audmux.h" | 33 | #include "imx-audmux.h" |
30 | 34 | ||
31 | #define CODEC_CLOCK 12000000 | 35 | #define CODEC_CLOCK 12000000 |
@@ -41,7 +45,8 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, | |||
41 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | 45 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | |
42 | SND_SOC_DAIFMT_NB_NF | | 46 | SND_SOC_DAIFMT_NB_NF | |
43 | SND_SOC_DAIFMT_CBM_CFM); | 47 | SND_SOC_DAIFMT_CBM_CFM); |
44 | if (ret) { | 48 | /* fsl_ssi lacks the set_fmt ops. */ |
49 | if (ret && ret != -ENOTSUPP) { | ||
45 | dev_err(cpu_dai->dev, | 50 | dev_err(cpu_dai->dev, |
46 | "Failed to set the cpu dai format.\n"); | 51 | "Failed to set the cpu dai format.\n"); |
47 | return ret; | 52 | return ret; |
@@ -63,11 +68,13 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, | |||
63 | "Failed to set the codec sysclk.\n"); | 68 | "Failed to set the codec sysclk.\n"); |
64 | return ret; | 69 | return ret; |
65 | } | 70 | } |
71 | |||
66 | snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0); | 72 | snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0); |
67 | 73 | ||
68 | ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, | 74 | ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, |
69 | SND_SOC_CLOCK_IN); | 75 | SND_SOC_CLOCK_IN); |
70 | if (ret) { | 76 | /* fsl_ssi lacks the set_sysclk ops */ |
77 | if (ret && ret != -EINVAL) { | ||
71 | dev_err(cpu_dai->dev, | 78 | dev_err(cpu_dai->dev, |
72 | "Can't set the IMX_SSP_SYS_CLK CPU system clock.\n"); | 79 | "Can't set the IMX_SSP_SYS_CLK CPU system clock.\n"); |
73 | return ret; | 80 | return ret; |
@@ -84,14 +91,10 @@ static struct snd_soc_dai_link eukrea_tlv320_dai = { | |||
84 | .name = "tlv320aic23", | 91 | .name = "tlv320aic23", |
85 | .stream_name = "TLV320AIC23", | 92 | .stream_name = "TLV320AIC23", |
86 | .codec_dai_name = "tlv320aic23-hifi", | 93 | .codec_dai_name = "tlv320aic23-hifi", |
87 | .platform_name = "imx-ssi.0", | ||
88 | .codec_name = "tlv320aic23-codec.0-001a", | ||
89 | .cpu_dai_name = "imx-ssi.0", | ||
90 | .ops = &eukrea_tlv320_snd_ops, | 94 | .ops = &eukrea_tlv320_snd_ops, |
91 | }; | 95 | }; |
92 | 96 | ||
93 | static struct snd_soc_card eukrea_tlv320 = { | 97 | static struct snd_soc_card eukrea_tlv320 = { |
94 | .name = "cpuimx-audio", | ||
95 | .owner = THIS_MODULE, | 98 | .owner = THIS_MODULE, |
96 | .dai_link = &eukrea_tlv320_dai, | 99 | .dai_link = &eukrea_tlv320_dai, |
97 | .num_links = 1, | 100 | .num_links = 1, |
@@ -101,8 +104,65 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) | |||
101 | { | 104 | { |
102 | int ret; | 105 | int ret; |
103 | int int_port = 0, ext_port; | 106 | int int_port = 0, ext_port; |
107 | struct device_node *np = pdev->dev.of_node; | ||
108 | struct device_node *ssi_np, *codec_np; | ||
104 | 109 | ||
105 | if (machine_is_eukrea_cpuimx27()) { | 110 | eukrea_tlv320.dev = &pdev->dev; |
111 | if (np) { | ||
112 | ret = snd_soc_of_parse_card_name(&eukrea_tlv320, | ||
113 | "eukrea,model"); | ||
114 | if (ret) { | ||
115 | dev_err(&pdev->dev, | ||
116 | "eukrea,model node missing or invalid.\n"); | ||
117 | goto err; | ||
118 | } | ||
119 | |||
120 | ssi_np = of_parse_phandle(pdev->dev.of_node, | ||
121 | "ssi-controller", 0); | ||
122 | if (!ssi_np) { | ||
123 | dev_err(&pdev->dev, | ||
124 | "ssi-controller missing or invalid.\n"); | ||
125 | ret = -ENODEV; | ||
126 | goto err; | ||
127 | } | ||
128 | |||
129 | codec_np = of_parse_phandle(ssi_np, "codec-handle", 0); | ||
130 | if (codec_np) | ||
131 | eukrea_tlv320_dai.codec_of_node = codec_np; | ||
132 | else | ||
133 | dev_err(&pdev->dev, "codec-handle node missing or invalid.\n"); | ||
134 | |||
135 | ret = of_property_read_u32(np, "fsl,mux-int-port", &int_port); | ||
136 | if (ret) { | ||
137 | dev_err(&pdev->dev, | ||
138 | "fsl,mux-int-port node missing or invalid.\n"); | ||
139 | return ret; | ||
140 | } | ||
141 | ret = of_property_read_u32(np, "fsl,mux-ext-port", &ext_port); | ||
142 | if (ret) { | ||
143 | dev_err(&pdev->dev, | ||
144 | "fsl,mux-ext-port node missing or invalid.\n"); | ||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * The port numbering in the hardware manual starts at 1, while | ||
150 | * the audmux API expects it starts at 0. | ||
151 | */ | ||
152 | int_port--; | ||
153 | ext_port--; | ||
154 | |||
155 | eukrea_tlv320_dai.cpu_of_node = ssi_np; | ||
156 | eukrea_tlv320_dai.platform_of_node = ssi_np; | ||
157 | } else { | ||
158 | eukrea_tlv320_dai.cpu_dai_name = "imx-ssi.0"; | ||
159 | eukrea_tlv320_dai.platform_name = "imx-ssi.0"; | ||
160 | eukrea_tlv320_dai.codec_name = "tlv320aic23-codec.0-001a"; | ||
161 | eukrea_tlv320.name = "cpuimx-audio"; | ||
162 | } | ||
163 | |||
164 | if (machine_is_eukrea_cpuimx27() || | ||
165 | of_find_compatible_node(NULL, NULL, "fsl,imx21-audmux")) { | ||
106 | imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, | 166 | imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, |
107 | IMX_AUDMUX_V1_PCR_SYN | | 167 | IMX_AUDMUX_V1_PCR_SYN | |
108 | IMX_AUDMUX_V1_PCR_TFSDIR | | 168 | IMX_AUDMUX_V1_PCR_TFSDIR | |
@@ -119,8 +179,12 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) | |||
119 | ); | 179 | ); |
120 | } else if (machine_is_eukrea_cpuimx25sd() || | 180 | } else if (machine_is_eukrea_cpuimx25sd() || |
121 | machine_is_eukrea_cpuimx35sd() || | 181 | machine_is_eukrea_cpuimx35sd() || |
122 | machine_is_eukrea_cpuimx51sd()) { | 182 | machine_is_eukrea_cpuimx51sd() || |
123 | ext_port = machine_is_eukrea_cpuimx25sd() ? 4 : 3; | 183 | of_find_compatible_node(NULL, NULL, "fsl,imx31-audmux")) { |
184 | if (!np) | ||
185 | ext_port = machine_is_eukrea_cpuimx25sd() ? | ||
186 | 4 : 3; | ||
187 | |||
124 | imx_audmux_v2_configure_port(int_port, | 188 | imx_audmux_v2_configure_port(int_port, |
125 | IMX_AUDMUX_V2_PTCR_SYN | | 189 | IMX_AUDMUX_V2_PTCR_SYN | |
126 | IMX_AUDMUX_V2_PTCR_TFSDIR | | 190 | IMX_AUDMUX_V2_PTCR_TFSDIR | |
@@ -134,14 +198,27 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) | |||
134 | IMX_AUDMUX_V2_PDCR_RXDSEL(int_port) | 198 | IMX_AUDMUX_V2_PDCR_RXDSEL(int_port) |
135 | ); | 199 | ); |
136 | } else { | 200 | } else { |
137 | /* return happy. We might run on a totally different machine */ | 201 | if (np) { |
138 | return 0; | 202 | /* The eukrea,asoc-tlv320 driver was explicitely |
203 | * requested (through the device tree). | ||
204 | */ | ||
205 | dev_err(&pdev->dev, | ||
206 | "Missing or invalid audmux DT node.\n"); | ||
207 | return -ENODEV; | ||
208 | } else { | ||
209 | /* Return happy. | ||
210 | * We might run on a totally different machine. | ||
211 | */ | ||
212 | return 0; | ||
213 | } | ||
139 | } | 214 | } |
140 | 215 | ||
141 | eukrea_tlv320.dev = &pdev->dev; | ||
142 | ret = snd_soc_register_card(&eukrea_tlv320); | 216 | ret = snd_soc_register_card(&eukrea_tlv320); |
217 | err: | ||
143 | if (ret) | 218 | if (ret) |
144 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | 219 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); |
220 | if (np) | ||
221 | of_node_put(ssi_np); | ||
145 | 222 | ||
146 | return ret; | 223 | return ret; |
147 | } | 224 | } |
@@ -153,10 +230,17 @@ static int eukrea_tlv320_remove(struct platform_device *pdev) | |||
153 | return 0; | 230 | return 0; |
154 | } | 231 | } |
155 | 232 | ||
233 | static const struct of_device_id imx_tlv320_dt_ids[] = { | ||
234 | { .compatible = "eukrea,asoc-tlv320"}, | ||
235 | { /* sentinel */ } | ||
236 | }; | ||
237 | MODULE_DEVICE_TABLE(of, imx_tlv320_dt_ids); | ||
238 | |||
156 | static struct platform_driver eukrea_tlv320_driver = { | 239 | static struct platform_driver eukrea_tlv320_driver = { |
157 | .driver = { | 240 | .driver = { |
158 | .name = "eukrea_tlv320", | 241 | .name = "eukrea_tlv320", |
159 | .owner = THIS_MODULE, | 242 | .owner = THIS_MODULE, |
243 | .of_match_table = imx_tlv320_dt_ids, | ||
160 | }, | 244 | }, |
161 | .probe = eukrea_tlv320_probe, | 245 | .probe = eukrea_tlv320_probe, |
162 | .remove = eukrea_tlv320_remove, | 246 | .remove = eukrea_tlv320_remove, |
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index d0c72ed261e7..0ba37005ab04 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c | |||
@@ -326,7 +326,7 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, | |||
326 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA, | 326 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA, |
327 | ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask)); | 327 | ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask)); |
328 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB, | 328 | regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB, |
329 | ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(tx_mask)); | 329 | ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(tx_mask)); |
330 | 330 | ||
331 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, | 331 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, |
332 | ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots)); | 332 | ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots)); |
@@ -334,7 +334,7 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, | |||
334 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA, | 334 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA, |
335 | ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask)); | 335 | ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask)); |
336 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB, | 336 | regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB, |
337 | ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(rx_mask)); | 337 | ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask)); |
338 | 338 | ||
339 | esai_priv->slot_width = slot_width; | 339 | esai_priv->slot_width = slot_width; |
340 | 340 | ||
@@ -431,17 +431,26 @@ static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
431 | static int fsl_esai_startup(struct snd_pcm_substream *substream, | 431 | static int fsl_esai_startup(struct snd_pcm_substream *substream, |
432 | struct snd_soc_dai *dai) | 432 | struct snd_soc_dai *dai) |
433 | { | 433 | { |
434 | int ret; | ||
434 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); | 435 | struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); |
435 | 436 | ||
436 | /* | 437 | /* |
437 | * Some platforms might use the same bit to gate all three or two of | 438 | * Some platforms might use the same bit to gate all three or two of |
438 | * clocks, so keep all clocks open/close at the same time for safety | 439 | * clocks, so keep all clocks open/close at the same time for safety |
439 | */ | 440 | */ |
440 | clk_prepare_enable(esai_priv->coreclk); | 441 | ret = clk_prepare_enable(esai_priv->coreclk); |
441 | if (!IS_ERR(esai_priv->extalclk)) | 442 | if (ret) |
442 | clk_prepare_enable(esai_priv->extalclk); | 443 | return ret; |
443 | if (!IS_ERR(esai_priv->fsysclk)) | 444 | if (!IS_ERR(esai_priv->extalclk)) { |
444 | clk_prepare_enable(esai_priv->fsysclk); | 445 | ret = clk_prepare_enable(esai_priv->extalclk); |
446 | if (ret) | ||
447 | goto err_extalck; | ||
448 | } | ||
449 | if (!IS_ERR(esai_priv->fsysclk)) { | ||
450 | ret = clk_prepare_enable(esai_priv->fsysclk); | ||
451 | if (ret) | ||
452 | goto err_fsysclk; | ||
453 | } | ||
445 | 454 | ||
446 | if (!dai->active) { | 455 | if (!dai->active) { |
447 | /* Reset Port C */ | 456 | /* Reset Port C */ |
@@ -463,6 +472,14 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream, | |||
463 | } | 472 | } |
464 | 473 | ||
465 | return 0; | 474 | return 0; |
475 | |||
476 | err_fsysclk: | ||
477 | if (!IS_ERR(esai_priv->extalclk)) | ||
478 | clk_disable_unprepare(esai_priv->extalclk); | ||
479 | err_extalck: | ||
480 | clk_disable_unprepare(esai_priv->coreclk); | ||
481 | |||
482 | return ret; | ||
466 | } | 483 | } |
467 | 484 | ||
468 | static int fsl_esai_hw_params(struct snd_pcm_substream *substream, | 485 | static int fsl_esai_hw_params(struct snd_pcm_substream *substream, |
@@ -661,7 +678,7 @@ static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg) | |||
661 | } | 678 | } |
662 | } | 679 | } |
663 | 680 | ||
664 | static const struct regmap_config fsl_esai_regmap_config = { | 681 | static struct regmap_config fsl_esai_regmap_config = { |
665 | .reg_bits = 32, | 682 | .reg_bits = 32, |
666 | .reg_stride = 4, | 683 | .reg_stride = 4, |
667 | .val_bits = 32, | 684 | .val_bits = 32, |
@@ -687,6 +704,9 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
687 | esai_priv->pdev = pdev; | 704 | esai_priv->pdev = pdev; |
688 | strcpy(esai_priv->name, np->name); | 705 | strcpy(esai_priv->name, np->name); |
689 | 706 | ||
707 | if (of_property_read_bool(np, "big-endian")) | ||
708 | fsl_esai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; | ||
709 | |||
690 | /* Get the addresses and IRQ */ | 710 | /* Get the addresses and IRQ */ |
691 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 711 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
692 | regs = devm_ioremap_resource(&pdev->dev, res); | 712 | regs = devm_ioremap_resource(&pdev->dev, res); |
diff --git a/sound/soc/fsl/fsl_esai.h b/sound/soc/fsl/fsl_esai.h index 9c9f957fcae1..75e14033e8d8 100644 --- a/sound/soc/fsl/fsl_esai.h +++ b/sound/soc/fsl/fsl_esai.h | |||
@@ -322,7 +322,7 @@ | |||
322 | #define ESAI_xSMB_xS_SHIFT 0 | 322 | #define ESAI_xSMB_xS_SHIFT 0 |
323 | #define ESAI_xSMB_xS_WIDTH 16 | 323 | #define ESAI_xSMB_xS_WIDTH 16 |
324 | #define ESAI_xSMB_xS_MASK (((1 << ESAI_xSMB_xS_WIDTH) - 1) << ESAI_xSMB_xS_SHIFT) | 324 | #define ESAI_xSMB_xS_MASK (((1 << ESAI_xSMB_xS_WIDTH) - 1) << ESAI_xSMB_xS_SHIFT) |
325 | #define ESAI_xSMB_xS(v) (((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMA_xS_MASK) | 325 | #define ESAI_xSMB_xS(v) (((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMB_xS_MASK) |
326 | 326 | ||
327 | /* Port C Direction Register -- REG_ESAI_PRRC 0xF8 */ | 327 | /* Port C Direction Register -- REG_ESAI_PRRC 0xF8 */ |
328 | #define ESAI_PRRC_PDC_SHIFT 0 | 328 | #define ESAI_PRRC_PDC_SHIFT 0 |
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index cdd3fa830704..c4a423111673 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/dmaengine.h> | 15 | #include <linux/dmaengine.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/of_address.h> | 17 | #include <linux/of_address.h> |
18 | #include <linux/regmap.h> | ||
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
19 | #include <sound/core.h> | 20 | #include <sound/core.h> |
20 | #include <sound/dmaengine_pcm.h> | 21 | #include <sound/dmaengine_pcm.h> |
@@ -22,34 +23,6 @@ | |||
22 | 23 | ||
23 | #include "fsl_sai.h" | 24 | #include "fsl_sai.h" |
24 | 25 | ||
25 | static inline u32 sai_readl(struct fsl_sai *sai, | ||
26 | const void __iomem *addr) | ||
27 | { | ||
28 | u32 val; | ||
29 | |||
30 | val = __raw_readl(addr); | ||
31 | |||
32 | if (likely(sai->big_endian_regs)) | ||
33 | val = be32_to_cpu(val); | ||
34 | else | ||
35 | val = le32_to_cpu(val); | ||
36 | rmb(); | ||
37 | |||
38 | return val; | ||
39 | } | ||
40 | |||
41 | static inline void sai_writel(struct fsl_sai *sai, | ||
42 | u32 val, void __iomem *addr) | ||
43 | { | ||
44 | wmb(); | ||
45 | if (likely(sai->big_endian_regs)) | ||
46 | val = cpu_to_be32(val); | ||
47 | else | ||
48 | val = cpu_to_le32(val); | ||
49 | |||
50 | __raw_writel(val, addr); | ||
51 | } | ||
52 | |||
53 | static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, | 26 | static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, |
54 | int clk_id, unsigned int freq, int fsl_dir) | 27 | int clk_id, unsigned int freq, int fsl_dir) |
55 | { | 28 | { |
@@ -61,7 +34,8 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, | |||
61 | else | 34 | else |
62 | reg_cr2 = FSL_SAI_RCR2; | 35 | reg_cr2 = FSL_SAI_RCR2; |
63 | 36 | ||
64 | val_cr2 = sai_readl(sai, sai->base + reg_cr2); | 37 | regmap_read(sai->regmap, reg_cr2, &val_cr2); |
38 | |||
65 | val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK; | 39 | val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK; |
66 | 40 | ||
67 | switch (clk_id) { | 41 | switch (clk_id) { |
@@ -81,7 +55,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, | |||
81 | return -EINVAL; | 55 | return -EINVAL; |
82 | } | 56 | } |
83 | 57 | ||
84 | sai_writel(sai, val_cr2, sai->base + reg_cr2); | 58 | regmap_write(sai->regmap, reg_cr2, val_cr2); |
85 | 59 | ||
86 | return 0; | 60 | return 0; |
87 | } | 61 | } |
@@ -89,32 +63,22 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, | |||
89 | static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | 63 | static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, |
90 | int clk_id, unsigned int freq, int dir) | 64 | int clk_id, unsigned int freq, int dir) |
91 | { | 65 | { |
92 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
93 | int ret; | 66 | int ret; |
94 | 67 | ||
95 | if (dir == SND_SOC_CLOCK_IN) | 68 | if (dir == SND_SOC_CLOCK_IN) |
96 | return 0; | 69 | return 0; |
97 | 70 | ||
98 | ret = clk_prepare_enable(sai->clk); | ||
99 | if (ret) | ||
100 | return ret; | ||
101 | |||
102 | ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, | 71 | ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, |
103 | FSL_FMT_TRANSMITTER); | 72 | FSL_FMT_TRANSMITTER); |
104 | if (ret) { | 73 | if (ret) { |
105 | dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret); | 74 | dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret); |
106 | goto err_clk; | 75 | return ret; |
107 | } | 76 | } |
108 | 77 | ||
109 | ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, | 78 | ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, |
110 | FSL_FMT_RECEIVER); | 79 | FSL_FMT_RECEIVER); |
111 | if (ret) { | 80 | if (ret) |
112 | dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret); | 81 | dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret); |
113 | goto err_clk; | ||
114 | } | ||
115 | |||
116 | err_clk: | ||
117 | clk_disable_unprepare(sai->clk); | ||
118 | 82 | ||
119 | return ret; | 83 | return ret; |
120 | } | 84 | } |
@@ -133,43 +97,84 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, | |||
133 | reg_cr4 = FSL_SAI_RCR4; | 97 | reg_cr4 = FSL_SAI_RCR4; |
134 | } | 98 | } |
135 | 99 | ||
136 | val_cr2 = sai_readl(sai, sai->base + reg_cr2); | 100 | regmap_read(sai->regmap, reg_cr2, &val_cr2); |
137 | val_cr4 = sai_readl(sai, sai->base + reg_cr4); | 101 | regmap_read(sai->regmap, reg_cr4, &val_cr4); |
138 | 102 | ||
139 | if (sai->big_endian_data) | 103 | if (sai->big_endian_data) |
140 | val_cr4 &= ~FSL_SAI_CR4_MF; | 104 | val_cr4 &= ~FSL_SAI_CR4_MF; |
141 | else | 105 | else |
142 | val_cr4 |= FSL_SAI_CR4_MF; | 106 | val_cr4 |= FSL_SAI_CR4_MF; |
143 | 107 | ||
108 | /* DAI mode */ | ||
144 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 109 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
145 | case SND_SOC_DAIFMT_I2S: | 110 | case SND_SOC_DAIFMT_I2S: |
111 | /* | ||
112 | * Frame low, 1clk before data, one word length for frame sync, | ||
113 | * frame sync starts one serial clock cycle earlier, | ||
114 | * that is, together with the last bit of the previous | ||
115 | * data word. | ||
116 | */ | ||
117 | val_cr2 &= ~FSL_SAI_CR2_BCP; | ||
118 | val_cr4 |= FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP; | ||
119 | break; | ||
120 | case SND_SOC_DAIFMT_LEFT_J: | ||
121 | /* | ||
122 | * Frame high, one word length for frame sync, | ||
123 | * frame sync asserts with the first bit of the frame. | ||
124 | */ | ||
125 | val_cr2 &= ~FSL_SAI_CR2_BCP; | ||
126 | val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP); | ||
127 | break; | ||
128 | case SND_SOC_DAIFMT_DSP_A: | ||
129 | /* | ||
130 | * Frame high, 1clk before data, one bit for frame sync, | ||
131 | * frame sync starts one serial clock cycle earlier, | ||
132 | * that is, together with the last bit of the previous | ||
133 | * data word. | ||
134 | */ | ||
135 | val_cr2 &= ~FSL_SAI_CR2_BCP; | ||
136 | val_cr4 &= ~FSL_SAI_CR4_FSP; | ||
146 | val_cr4 |= FSL_SAI_CR4_FSE; | 137 | val_cr4 |= FSL_SAI_CR4_FSE; |
138 | sai->is_dsp_mode = true; | ||
139 | break; | ||
140 | case SND_SOC_DAIFMT_DSP_B: | ||
141 | /* | ||
142 | * Frame high, one bit for frame sync, | ||
143 | * frame sync asserts with the first bit of the frame. | ||
144 | */ | ||
145 | val_cr2 &= ~FSL_SAI_CR2_BCP; | ||
146 | val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP); | ||
147 | sai->is_dsp_mode = true; | ||
147 | break; | 148 | break; |
149 | case SND_SOC_DAIFMT_RIGHT_J: | ||
150 | /* To be done */ | ||
148 | default: | 151 | default: |
149 | return -EINVAL; | 152 | return -EINVAL; |
150 | } | 153 | } |
151 | 154 | ||
155 | /* DAI clock inversion */ | ||
152 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 156 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
153 | case SND_SOC_DAIFMT_IB_IF: | 157 | case SND_SOC_DAIFMT_IB_IF: |
154 | val_cr4 |= FSL_SAI_CR4_FSP; | 158 | /* Invert both clocks */ |
155 | val_cr2 &= ~FSL_SAI_CR2_BCP; | 159 | val_cr2 ^= FSL_SAI_CR2_BCP; |
160 | val_cr4 ^= FSL_SAI_CR4_FSP; | ||
156 | break; | 161 | break; |
157 | case SND_SOC_DAIFMT_IB_NF: | 162 | case SND_SOC_DAIFMT_IB_NF: |
158 | val_cr4 &= ~FSL_SAI_CR4_FSP; | 163 | /* Invert bit clock */ |
159 | val_cr2 &= ~FSL_SAI_CR2_BCP; | 164 | val_cr2 ^= FSL_SAI_CR2_BCP; |
160 | break; | 165 | break; |
161 | case SND_SOC_DAIFMT_NB_IF: | 166 | case SND_SOC_DAIFMT_NB_IF: |
162 | val_cr4 |= FSL_SAI_CR4_FSP; | 167 | /* Invert frame clock */ |
163 | val_cr2 |= FSL_SAI_CR2_BCP; | 168 | val_cr4 ^= FSL_SAI_CR4_FSP; |
164 | break; | 169 | break; |
165 | case SND_SOC_DAIFMT_NB_NF: | 170 | case SND_SOC_DAIFMT_NB_NF: |
166 | val_cr4 &= ~FSL_SAI_CR4_FSP; | 171 | /* Nothing to do for both normal cases */ |
167 | val_cr2 |= FSL_SAI_CR2_BCP; | ||
168 | break; | 172 | break; |
169 | default: | 173 | default: |
170 | return -EINVAL; | 174 | return -EINVAL; |
171 | } | 175 | } |
172 | 176 | ||
177 | /* DAI clock master masks */ | ||
173 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 178 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
174 | case SND_SOC_DAIFMT_CBS_CFS: | 179 | case SND_SOC_DAIFMT_CBS_CFS: |
175 | val_cr2 |= FSL_SAI_CR2_BCD_MSTR; | 180 | val_cr2 |= FSL_SAI_CR2_BCD_MSTR; |
@@ -179,39 +184,37 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, | |||
179 | val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR; | 184 | val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR; |
180 | val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR; | 185 | val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR; |
181 | break; | 186 | break; |
187 | case SND_SOC_DAIFMT_CBS_CFM: | ||
188 | val_cr2 |= FSL_SAI_CR2_BCD_MSTR; | ||
189 | val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR; | ||
190 | break; | ||
191 | case SND_SOC_DAIFMT_CBM_CFS: | ||
192 | val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR; | ||
193 | val_cr4 |= FSL_SAI_CR4_FSD_MSTR; | ||
194 | break; | ||
182 | default: | 195 | default: |
183 | return -EINVAL; | 196 | return -EINVAL; |
184 | } | 197 | } |
185 | 198 | ||
186 | sai_writel(sai, val_cr2, sai->base + reg_cr2); | 199 | regmap_write(sai->regmap, reg_cr2, val_cr2); |
187 | sai_writel(sai, val_cr4, sai->base + reg_cr4); | 200 | regmap_write(sai->regmap, reg_cr4, val_cr4); |
188 | 201 | ||
189 | return 0; | 202 | return 0; |
190 | } | 203 | } |
191 | 204 | ||
192 | static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | 205 | static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) |
193 | { | 206 | { |
194 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | ||
195 | int ret; | 207 | int ret; |
196 | 208 | ||
197 | ret = clk_prepare_enable(sai->clk); | ||
198 | if (ret) | ||
199 | return ret; | ||
200 | |||
201 | ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER); | 209 | ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER); |
202 | if (ret) { | 210 | if (ret) { |
203 | dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret); | 211 | dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret); |
204 | goto err_clk; | 212 | return ret; |
205 | } | 213 | } |
206 | 214 | ||
207 | ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER); | 215 | ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER); |
208 | if (ret) { | 216 | if (ret) |
209 | dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret); | 217 | dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret); |
210 | goto err_clk; | ||
211 | } | ||
212 | |||
213 | err_clk: | ||
214 | clk_disable_unprepare(sai->clk); | ||
215 | 218 | ||
216 | return ret; | 219 | return ret; |
217 | } | 220 | } |
@@ -235,16 +238,19 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, | |||
235 | reg_mr = FSL_SAI_RMR; | 238 | reg_mr = FSL_SAI_RMR; |
236 | } | 239 | } |
237 | 240 | ||
238 | val_cr4 = sai_readl(sai, sai->base + reg_cr4); | 241 | regmap_read(sai->regmap, reg_cr4, &val_cr4); |
242 | regmap_read(sai->regmap, reg_cr4, &val_cr5); | ||
243 | |||
239 | val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK; | 244 | val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK; |
240 | val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK; | 245 | val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK; |
241 | 246 | ||
242 | val_cr5 = sai_readl(sai, sai->base + reg_cr5); | ||
243 | val_cr5 &= ~FSL_SAI_CR5_WNW_MASK; | 247 | val_cr5 &= ~FSL_SAI_CR5_WNW_MASK; |
244 | val_cr5 &= ~FSL_SAI_CR5_W0W_MASK; | 248 | val_cr5 &= ~FSL_SAI_CR5_W0W_MASK; |
245 | val_cr5 &= ~FSL_SAI_CR5_FBT_MASK; | 249 | val_cr5 &= ~FSL_SAI_CR5_FBT_MASK; |
246 | 250 | ||
247 | val_cr4 |= FSL_SAI_CR4_SYWD(word_width); | 251 | if (!sai->is_dsp_mode) |
252 | val_cr4 |= FSL_SAI_CR4_SYWD(word_width); | ||
253 | |||
248 | val_cr5 |= FSL_SAI_CR5_WNW(word_width); | 254 | val_cr5 |= FSL_SAI_CR5_WNW(word_width); |
249 | val_cr5 |= FSL_SAI_CR5_W0W(word_width); | 255 | val_cr5 |= FSL_SAI_CR5_W0W(word_width); |
250 | 256 | ||
@@ -257,9 +263,9 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, | |||
257 | val_cr4 |= FSL_SAI_CR4_FRSZ(channels); | 263 | val_cr4 |= FSL_SAI_CR4_FRSZ(channels); |
258 | val_mr = ~0UL - ((1 << channels) - 1); | 264 | val_mr = ~0UL - ((1 << channels) - 1); |
259 | 265 | ||
260 | sai_writel(sai, val_cr4, sai->base + reg_cr4); | 266 | regmap_write(sai->regmap, reg_cr4, val_cr4); |
261 | sai_writel(sai, val_cr5, sai->base + reg_cr5); | 267 | regmap_write(sai->regmap, reg_cr5, val_cr5); |
262 | sai_writel(sai, val_mr, sai->base + reg_mr); | 268 | regmap_write(sai->regmap, reg_mr, val_mr); |
263 | 269 | ||
264 | return 0; | 270 | return 0; |
265 | } | 271 | } |
@@ -268,44 +274,42 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
268 | struct snd_soc_dai *cpu_dai) | 274 | struct snd_soc_dai *cpu_dai) |
269 | { | 275 | { |
270 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | 276 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); |
271 | u32 tcsr, rcsr, val_cr2, val_cr3, reg_cr3; | 277 | u32 tcsr, rcsr; |
272 | |||
273 | val_cr2 = sai_readl(sai, sai->base + FSL_SAI_TCR2); | ||
274 | val_cr2 &= ~FSL_SAI_CR2_SYNC; | ||
275 | sai_writel(sai, val_cr2, sai->base + FSL_SAI_TCR2); | ||
276 | 278 | ||
277 | val_cr2 = sai_readl(sai, sai->base + FSL_SAI_RCR2); | 279 | /* |
278 | val_cr2 |= FSL_SAI_CR2_SYNC; | 280 | * The transmitter bit clock and frame sync are to be |
279 | sai_writel(sai, val_cr2, sai->base + FSL_SAI_RCR2); | 281 | * used by both the transmitter and receiver. |
282 | */ | ||
283 | regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC, | ||
284 | ~FSL_SAI_CR2_SYNC); | ||
285 | regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, | ||
286 | FSL_SAI_CR2_SYNC); | ||
280 | 287 | ||
281 | tcsr = sai_readl(sai, sai->base + FSL_SAI_TCSR); | 288 | regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr); |
282 | rcsr = sai_readl(sai, sai->base + FSL_SAI_RCSR); | 289 | regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr); |
283 | 290 | ||
284 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 291 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
285 | tcsr |= FSL_SAI_CSR_FRDE; | 292 | tcsr |= FSL_SAI_CSR_FRDE; |
286 | rcsr &= ~FSL_SAI_CSR_FRDE; | 293 | rcsr &= ~FSL_SAI_CSR_FRDE; |
287 | reg_cr3 = FSL_SAI_TCR3; | ||
288 | } else { | 294 | } else { |
289 | rcsr |= FSL_SAI_CSR_FRDE; | 295 | rcsr |= FSL_SAI_CSR_FRDE; |
290 | tcsr &= ~FSL_SAI_CSR_FRDE; | 296 | tcsr &= ~FSL_SAI_CSR_FRDE; |
291 | reg_cr3 = FSL_SAI_RCR3; | ||
292 | } | 297 | } |
293 | 298 | ||
294 | val_cr3 = sai_readl(sai, sai->base + reg_cr3); | 299 | /* |
295 | 300 | * It is recommended that the transmitter is the last enabled | |
301 | * and the first disabled. | ||
302 | */ | ||
296 | switch (cmd) { | 303 | switch (cmd) { |
297 | case SNDRV_PCM_TRIGGER_START: | 304 | case SNDRV_PCM_TRIGGER_START: |
298 | case SNDRV_PCM_TRIGGER_RESUME: | 305 | case SNDRV_PCM_TRIGGER_RESUME: |
299 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 306 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
300 | tcsr |= FSL_SAI_CSR_TERE; | 307 | tcsr |= FSL_SAI_CSR_TERE; |
301 | rcsr |= FSL_SAI_CSR_TERE; | 308 | rcsr |= FSL_SAI_CSR_TERE; |
302 | val_cr3 |= FSL_SAI_CR3_TRCE; | ||
303 | 309 | ||
304 | sai_writel(sai, val_cr3, sai->base + reg_cr3); | 310 | regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr); |
305 | sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR); | 311 | regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr); |
306 | sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR); | ||
307 | break; | 312 | break; |
308 | |||
309 | case SNDRV_PCM_TRIGGER_STOP: | 313 | case SNDRV_PCM_TRIGGER_STOP: |
310 | case SNDRV_PCM_TRIGGER_SUSPEND: | 314 | case SNDRV_PCM_TRIGGER_SUSPEND: |
311 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 315 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
@@ -314,11 +318,8 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
314 | rcsr &= ~FSL_SAI_CSR_TERE; | 318 | rcsr &= ~FSL_SAI_CSR_TERE; |
315 | } | 319 | } |
316 | 320 | ||
317 | val_cr3 &= ~FSL_SAI_CR3_TRCE; | 321 | regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr); |
318 | 322 | regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr); | |
319 | sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR); | ||
320 | sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR); | ||
321 | sai_writel(sai, val_cr3, sai->base + reg_cr3); | ||
322 | break; | 323 | break; |
323 | default: | 324 | default: |
324 | return -EINVAL; | 325 | return -EINVAL; |
@@ -331,16 +332,32 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, | |||
331 | struct snd_soc_dai *cpu_dai) | 332 | struct snd_soc_dai *cpu_dai) |
332 | { | 333 | { |
333 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | 334 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); |
335 | u32 reg; | ||
336 | |||
337 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
338 | reg = FSL_SAI_TCR3; | ||
339 | else | ||
340 | reg = FSL_SAI_RCR3; | ||
341 | |||
342 | regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE, | ||
343 | FSL_SAI_CR3_TRCE); | ||
334 | 344 | ||
335 | return clk_prepare_enable(sai->clk); | 345 | return 0; |
336 | } | 346 | } |
337 | 347 | ||
338 | static void fsl_sai_shutdown(struct snd_pcm_substream *substream, | 348 | static void fsl_sai_shutdown(struct snd_pcm_substream *substream, |
339 | struct snd_soc_dai *cpu_dai) | 349 | struct snd_soc_dai *cpu_dai) |
340 | { | 350 | { |
341 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); | 351 | struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); |
352 | u32 reg; | ||
353 | |||
354 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
355 | reg = FSL_SAI_TCR3; | ||
356 | else | ||
357 | reg = FSL_SAI_RCR3; | ||
342 | 358 | ||
343 | clk_disable_unprepare(sai->clk); | 359 | regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE, |
360 | ~FSL_SAI_CR3_TRCE); | ||
344 | } | 361 | } |
345 | 362 | ||
346 | static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { | 363 | static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { |
@@ -355,18 +372,13 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { | |||
355 | static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) | 372 | static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) |
356 | { | 373 | { |
357 | struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); | 374 | struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); |
358 | int ret; | ||
359 | 375 | ||
360 | ret = clk_prepare_enable(sai->clk); | 376 | regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, 0x0); |
361 | if (ret) | 377 | regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, 0x0); |
362 | return ret; | 378 | regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK, |
363 | 379 | FSL_SAI_MAXBURST_TX * 2); | |
364 | sai_writel(sai, 0x0, sai->base + FSL_SAI_RCSR); | 380 | regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK, |
365 | sai_writel(sai, 0x0, sai->base + FSL_SAI_TCSR); | 381 | FSL_SAI_MAXBURST_RX - 1); |
366 | sai_writel(sai, FSL_SAI_MAXBURST_TX * 2, sai->base + FSL_SAI_TCR1); | ||
367 | sai_writel(sai, FSL_SAI_MAXBURST_RX - 1, sai->base + FSL_SAI_RCR1); | ||
368 | |||
369 | clk_disable_unprepare(sai->clk); | ||
370 | 382 | ||
371 | snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, | 383 | snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, |
372 | &sai->dma_params_rx); | 384 | &sai->dma_params_rx); |
@@ -397,26 +409,109 @@ static const struct snd_soc_component_driver fsl_component = { | |||
397 | .name = "fsl-sai", | 409 | .name = "fsl-sai", |
398 | }; | 410 | }; |
399 | 411 | ||
412 | static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg) | ||
413 | { | ||
414 | switch (reg) { | ||
415 | case FSL_SAI_TCSR: | ||
416 | case FSL_SAI_TCR1: | ||
417 | case FSL_SAI_TCR2: | ||
418 | case FSL_SAI_TCR3: | ||
419 | case FSL_SAI_TCR4: | ||
420 | case FSL_SAI_TCR5: | ||
421 | case FSL_SAI_TFR: | ||
422 | case FSL_SAI_TMR: | ||
423 | case FSL_SAI_RCSR: | ||
424 | case FSL_SAI_RCR1: | ||
425 | case FSL_SAI_RCR2: | ||
426 | case FSL_SAI_RCR3: | ||
427 | case FSL_SAI_RCR4: | ||
428 | case FSL_SAI_RCR5: | ||
429 | case FSL_SAI_RDR: | ||
430 | case FSL_SAI_RFR: | ||
431 | case FSL_SAI_RMR: | ||
432 | return true; | ||
433 | default: | ||
434 | return false; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg) | ||
439 | { | ||
440 | switch (reg) { | ||
441 | case FSL_SAI_TFR: | ||
442 | case FSL_SAI_RFR: | ||
443 | case FSL_SAI_TDR: | ||
444 | case FSL_SAI_RDR: | ||
445 | return true; | ||
446 | default: | ||
447 | return false; | ||
448 | } | ||
449 | |||
450 | } | ||
451 | |||
452 | static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg) | ||
453 | { | ||
454 | switch (reg) { | ||
455 | case FSL_SAI_TCSR: | ||
456 | case FSL_SAI_TCR1: | ||
457 | case FSL_SAI_TCR2: | ||
458 | case FSL_SAI_TCR3: | ||
459 | case FSL_SAI_TCR4: | ||
460 | case FSL_SAI_TCR5: | ||
461 | case FSL_SAI_TDR: | ||
462 | case FSL_SAI_TMR: | ||
463 | case FSL_SAI_RCSR: | ||
464 | case FSL_SAI_RCR1: | ||
465 | case FSL_SAI_RCR2: | ||
466 | case FSL_SAI_RCR3: | ||
467 | case FSL_SAI_RCR4: | ||
468 | case FSL_SAI_RCR5: | ||
469 | case FSL_SAI_RMR: | ||
470 | return true; | ||
471 | default: | ||
472 | return false; | ||
473 | } | ||
474 | } | ||
475 | |||
476 | static struct regmap_config fsl_sai_regmap_config = { | ||
477 | .reg_bits = 32, | ||
478 | .reg_stride = 4, | ||
479 | .val_bits = 32, | ||
480 | |||
481 | .max_register = FSL_SAI_RMR, | ||
482 | .readable_reg = fsl_sai_readable_reg, | ||
483 | .volatile_reg = fsl_sai_volatile_reg, | ||
484 | .writeable_reg = fsl_sai_writeable_reg, | ||
485 | }; | ||
486 | |||
400 | static int fsl_sai_probe(struct platform_device *pdev) | 487 | static int fsl_sai_probe(struct platform_device *pdev) |
401 | { | 488 | { |
402 | struct device_node *np = pdev->dev.of_node; | 489 | struct device_node *np = pdev->dev.of_node; |
403 | struct fsl_sai *sai; | 490 | struct fsl_sai *sai; |
404 | struct resource *res; | 491 | struct resource *res; |
492 | void __iomem *base; | ||
405 | int ret; | 493 | int ret; |
406 | 494 | ||
407 | sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); | 495 | sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); |
408 | if (!sai) | 496 | if (!sai) |
409 | return -ENOMEM; | 497 | return -ENOMEM; |
410 | 498 | ||
499 | sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs"); | ||
500 | if (sai->big_endian_regs) | ||
501 | fsl_sai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; | ||
502 | |||
503 | sai->big_endian_data = of_property_read_bool(np, "big-endian-data"); | ||
504 | |||
411 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 505 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
412 | sai->base = devm_ioremap_resource(&pdev->dev, res); | 506 | base = devm_ioremap_resource(&pdev->dev, res); |
413 | if (IS_ERR(sai->base)) | 507 | if (IS_ERR(base)) |
414 | return PTR_ERR(sai->base); | 508 | return PTR_ERR(base); |
415 | 509 | ||
416 | sai->clk = devm_clk_get(&pdev->dev, "sai"); | 510 | sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, |
417 | if (IS_ERR(sai->clk)) { | 511 | "sai", base, &fsl_sai_regmap_config); |
418 | dev_err(&pdev->dev, "Cannot get SAI's clock\n"); | 512 | if (IS_ERR(sai->regmap)) { |
419 | return PTR_ERR(sai->clk); | 513 | dev_err(&pdev->dev, "regmap init failed\n"); |
514 | return PTR_ERR(sai->regmap); | ||
420 | } | 515 | } |
421 | 516 | ||
422 | sai->dma_params_rx.addr = res->start + FSL_SAI_RDR; | 517 | sai->dma_params_rx.addr = res->start + FSL_SAI_RDR; |
@@ -424,9 +519,6 @@ static int fsl_sai_probe(struct platform_device *pdev) | |||
424 | sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; | 519 | sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; |
425 | sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; | 520 | sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; |
426 | 521 | ||
427 | sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs"); | ||
428 | sai->big_endian_data = of_property_read_bool(np, "big-endian-data"); | ||
429 | |||
430 | platform_set_drvdata(pdev, sai); | 522 | platform_set_drvdata(pdev, sai); |
431 | 523 | ||
432 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, | 524 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, |
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 41bb62e69361..e432260be598 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h | |||
@@ -15,31 +15,36 @@ | |||
15 | SNDRV_PCM_FMTBIT_S20_3LE |\ | 15 | SNDRV_PCM_FMTBIT_S20_3LE |\ |
16 | SNDRV_PCM_FMTBIT_S24_LE) | 16 | SNDRV_PCM_FMTBIT_S24_LE) |
17 | 17 | ||
18 | /* SAI Register Map Register */ | ||
19 | #define FSL_SAI_TCSR 0x00 /* SAI Transmit Control */ | ||
20 | #define FSL_SAI_TCR1 0x04 /* SAI Transmit Configuration 1 */ | ||
21 | #define FSL_SAI_TCR2 0x08 /* SAI Transmit Configuration 2 */ | ||
22 | #define FSL_SAI_TCR3 0x0c /* SAI Transmit Configuration 3 */ | ||
23 | #define FSL_SAI_TCR4 0x10 /* SAI Transmit Configuration 4 */ | ||
24 | #define FSL_SAI_TCR5 0x14 /* SAI Transmit Configuration 5 */ | ||
25 | #define FSL_SAI_TDR 0x20 /* SAI Transmit Data */ | ||
26 | #define FSL_SAI_TFR 0x40 /* SAI Transmit FIFO */ | ||
27 | #define FSL_SAI_TMR 0x60 /* SAI Transmit Mask */ | ||
28 | #define FSL_SAI_RCSR 0x80 /* SAI Receive Control */ | ||
29 | #define FSL_SAI_RCR1 0x84 /* SAI Receive Configuration 1 */ | ||
30 | #define FSL_SAI_RCR2 0x88 /* SAI Receive Configuration 2 */ | ||
31 | #define FSL_SAI_RCR3 0x8c /* SAI Receive Configuration 3 */ | ||
32 | #define FSL_SAI_RCR4 0x90 /* SAI Receive Configuration 4 */ | ||
33 | #define FSL_SAI_RCR5 0x94 /* SAI Receive Configuration 5 */ | ||
34 | #define FSL_SAI_RDR 0xa0 /* SAI Receive Data */ | ||
35 | #define FSL_SAI_RFR 0xc0 /* SAI Receive FIFO */ | ||
36 | #define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */ | ||
37 | |||
18 | /* SAI Transmit/Recieve Control Register */ | 38 | /* SAI Transmit/Recieve Control Register */ |
19 | #define FSL_SAI_TCSR 0x00 | ||
20 | #define FSL_SAI_RCSR 0x80 | ||
21 | #define FSL_SAI_CSR_TERE BIT(31) | 39 | #define FSL_SAI_CSR_TERE BIT(31) |
22 | #define FSL_SAI_CSR_FWF BIT(17) | 40 | #define FSL_SAI_CSR_FWF BIT(17) |
23 | #define FSL_SAI_CSR_FRIE BIT(8) | 41 | #define FSL_SAI_CSR_FRIE BIT(8) |
24 | #define FSL_SAI_CSR_FRDE BIT(0) | 42 | #define FSL_SAI_CSR_FRDE BIT(0) |
25 | 43 | ||
26 | /* SAI Transmit Data/FIFO/MASK Register */ | ||
27 | #define FSL_SAI_TDR 0x20 | ||
28 | #define FSL_SAI_TFR 0x40 | ||
29 | #define FSL_SAI_TMR 0x60 | ||
30 | |||
31 | /* SAI Recieve Data/FIFO/MASK Register */ | ||
32 | #define FSL_SAI_RDR 0xa0 | ||
33 | #define FSL_SAI_RFR 0xc0 | ||
34 | #define FSL_SAI_RMR 0xe0 | ||
35 | |||
36 | /* SAI Transmit and Recieve Configuration 1 Register */ | 44 | /* SAI Transmit and Recieve Configuration 1 Register */ |
37 | #define FSL_SAI_TCR1 0x04 | 45 | #define FSL_SAI_CR1_RFW_MASK 0x1f |
38 | #define FSL_SAI_RCR1 0x84 | ||
39 | 46 | ||
40 | /* SAI Transmit and Recieve Configuration 2 Register */ | 47 | /* SAI Transmit and Recieve Configuration 2 Register */ |
41 | #define FSL_SAI_TCR2 0x08 | ||
42 | #define FSL_SAI_RCR2 0x88 | ||
43 | #define FSL_SAI_CR2_SYNC BIT(30) | 48 | #define FSL_SAI_CR2_SYNC BIT(30) |
44 | #define FSL_SAI_CR2_MSEL_MASK (0xff << 26) | 49 | #define FSL_SAI_CR2_MSEL_MASK (0xff << 26) |
45 | #define FSL_SAI_CR2_MSEL_BUS 0 | 50 | #define FSL_SAI_CR2_MSEL_BUS 0 |
@@ -50,15 +55,11 @@ | |||
50 | #define FSL_SAI_CR2_BCD_MSTR BIT(24) | 55 | #define FSL_SAI_CR2_BCD_MSTR BIT(24) |
51 | 56 | ||
52 | /* SAI Transmit and Recieve Configuration 3 Register */ | 57 | /* SAI Transmit and Recieve Configuration 3 Register */ |
53 | #define FSL_SAI_TCR3 0x0c | ||
54 | #define FSL_SAI_RCR3 0x8c | ||
55 | #define FSL_SAI_CR3_TRCE BIT(16) | 58 | #define FSL_SAI_CR3_TRCE BIT(16) |
56 | #define FSL_SAI_CR3_WDFL(x) (x) | 59 | #define FSL_SAI_CR3_WDFL(x) (x) |
57 | #define FSL_SAI_CR3_WDFL_MASK 0x1f | 60 | #define FSL_SAI_CR3_WDFL_MASK 0x1f |
58 | 61 | ||
59 | /* SAI Transmit and Recieve Configuration 4 Register */ | 62 | /* SAI Transmit and Recieve Configuration 4 Register */ |
60 | #define FSL_SAI_TCR4 0x10 | ||
61 | #define FSL_SAI_RCR4 0x90 | ||
62 | #define FSL_SAI_CR4_FRSZ(x) (((x) - 1) << 16) | 63 | #define FSL_SAI_CR4_FRSZ(x) (((x) - 1) << 16) |
63 | #define FSL_SAI_CR4_FRSZ_MASK (0x1f << 16) | 64 | #define FSL_SAI_CR4_FRSZ_MASK (0x1f << 16) |
64 | #define FSL_SAI_CR4_SYWD(x) (((x) - 1) << 8) | 65 | #define FSL_SAI_CR4_SYWD(x) (((x) - 1) << 8) |
@@ -69,8 +70,6 @@ | |||
69 | #define FSL_SAI_CR4_FSD_MSTR BIT(0) | 70 | #define FSL_SAI_CR4_FSD_MSTR BIT(0) |
70 | 71 | ||
71 | /* SAI Transmit and Recieve Configuration 5 Register */ | 72 | /* SAI Transmit and Recieve Configuration 5 Register */ |
72 | #define FSL_SAI_TCR5 0x14 | ||
73 | #define FSL_SAI_RCR5 0x94 | ||
74 | #define FSL_SAI_CR5_WNW(x) (((x) - 1) << 24) | 73 | #define FSL_SAI_CR5_WNW(x) (((x) - 1) << 24) |
75 | #define FSL_SAI_CR5_WNW_MASK (0x1f << 24) | 74 | #define FSL_SAI_CR5_WNW_MASK (0x1f << 24) |
76 | #define FSL_SAI_CR5_W0W(x) (((x) - 1) << 16) | 75 | #define FSL_SAI_CR5_W0W(x) (((x) - 1) << 16) |
@@ -100,12 +99,11 @@ | |||
100 | #define FSL_SAI_MAXBURST_RX 6 | 99 | #define FSL_SAI_MAXBURST_RX 6 |
101 | 100 | ||
102 | struct fsl_sai { | 101 | struct fsl_sai { |
103 | struct clk *clk; | 102 | struct regmap *regmap; |
104 | |||
105 | void __iomem *base; | ||
106 | 103 | ||
107 | bool big_endian_regs; | 104 | bool big_endian_regs; |
108 | bool big_endian_data; | 105 | bool big_endian_data; |
106 | bool is_dsp_mode; | ||
109 | 107 | ||
110 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 108 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
111 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 109 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 4d075f1abe78..6452ca83d889 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
@@ -911,8 +911,8 @@ static int fsl_spdif_dai_probe(struct snd_soc_dai *dai) | |||
911 | { | 911 | { |
912 | struct fsl_spdif_priv *spdif_private = snd_soc_dai_get_drvdata(dai); | 912 | struct fsl_spdif_priv *spdif_private = snd_soc_dai_get_drvdata(dai); |
913 | 913 | ||
914 | dai->playback_dma_data = &spdif_private->dma_params_tx; | 914 | snd_soc_dai_init_dma_data(dai, &spdif_private->dma_params_tx, |
915 | dai->capture_dma_data = &spdif_private->dma_params_rx; | 915 | &spdif_private->dma_params_rx); |
916 | 916 | ||
917 | snd_soc_add_dai_controls(dai, fsl_spdif_ctrls, ARRAY_SIZE(fsl_spdif_ctrls)); | 917 | snd_soc_add_dai_controls(dai, fsl_spdif_ctrls, ARRAY_SIZE(fsl_spdif_ctrls)); |
918 | 918 | ||
@@ -985,7 +985,7 @@ static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg) | |||
985 | } | 985 | } |
986 | } | 986 | } |
987 | 987 | ||
988 | static const struct regmap_config fsl_spdif_regmap_config = { | 988 | static struct regmap_config fsl_spdif_regmap_config = { |
989 | .reg_bits = 32, | 989 | .reg_bits = 32, |
990 | .reg_stride = 4, | 990 | .reg_stride = 4, |
991 | .val_bits = 32, | 991 | .val_bits = 32, |
@@ -1105,6 +1105,9 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
1105 | memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); | 1105 | memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); |
1106 | spdif_priv->cpu_dai_drv.name = spdif_priv->name; | 1106 | spdif_priv->cpu_dai_drv.name = spdif_priv->name; |
1107 | 1107 | ||
1108 | if (of_property_read_bool(np, "big-endian")) | ||
1109 | fsl_spdif_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; | ||
1110 | |||
1108 | /* Get the addresses and IRQ */ | 1111 | /* Get the addresses and IRQ */ |
1109 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1112 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1110 | regs = devm_ioremap_resource(&pdev->dev, res); | 1113 | regs = devm_ioremap_resource(&pdev->dev, res); |
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c index 79cee782dbbf..a2fd7321b5a9 100644 --- a/sound/soc/fsl/imx-mc13783.c +++ b/sound/soc/fsl/imx-mc13783.c | |||
@@ -160,7 +160,6 @@ static struct platform_driver imx_mc13783_audio_driver = { | |||
160 | .driver = { | 160 | .driver = { |
161 | .name = "imx_mc13783", | 161 | .name = "imx_mc13783", |
162 | .owner = THIS_MODULE, | 162 | .owner = THIS_MODULE, |
163 | .pm = &snd_soc_pm_ops, | ||
164 | }, | 163 | }, |
165 | .probe = imx_mc13783_probe, | 164 | .probe = imx_mc13783_probe, |
166 | .remove = imx_mc13783_remove | 165 | .remove = imx_mc13783_remove |
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index 6553202dd48c..7abf6a079574 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c | |||
@@ -270,18 +270,17 @@ static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
270 | ret = imx_pcm_preallocate_dma_buffer(pcm, | 270 | ret = imx_pcm_preallocate_dma_buffer(pcm, |
271 | SNDRV_PCM_STREAM_PLAYBACK); | 271 | SNDRV_PCM_STREAM_PLAYBACK); |
272 | if (ret) | 272 | if (ret) |
273 | goto out; | 273 | return ret; |
274 | } | 274 | } |
275 | 275 | ||
276 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | 276 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { |
277 | ret = imx_pcm_preallocate_dma_buffer(pcm, | 277 | ret = imx_pcm_preallocate_dma_buffer(pcm, |
278 | SNDRV_PCM_STREAM_CAPTURE); | 278 | SNDRV_PCM_STREAM_CAPTURE); |
279 | if (ret) | 279 | if (ret) |
280 | goto out; | 280 | return ret; |
281 | } | 281 | } |
282 | 282 | ||
283 | out: | 283 | return 0; |
284 | return ret; | ||
285 | } | 284 | } |
286 | 285 | ||
287 | static int ssi_irq = 0; | 286 | static int ssi_irq = 0; |
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index f2beae78969f..1cb22dd034eb 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c | |||
@@ -33,8 +33,7 @@ struct imx_sgtl5000_data { | |||
33 | 33 | ||
34 | static int imx_sgtl5000_dai_init(struct snd_soc_pcm_runtime *rtd) | 34 | static int imx_sgtl5000_dai_init(struct snd_soc_pcm_runtime *rtd) |
35 | { | 35 | { |
36 | struct imx_sgtl5000_data *data = container_of(rtd->card, | 36 | struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(rtd->card); |
37 | struct imx_sgtl5000_data, card); | ||
38 | struct device *dev = rtd->card->dev; | 37 | struct device *dev = rtd->card->dev; |
39 | int ret; | 38 | int ret; |
40 | 39 | ||
@@ -159,13 +158,15 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) | |||
159 | data->card.dapm_widgets = imx_sgtl5000_dapm_widgets; | 158 | data->card.dapm_widgets = imx_sgtl5000_dapm_widgets; |
160 | data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets); | 159 | data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets); |
161 | 160 | ||
161 | platform_set_drvdata(pdev, &data->card); | ||
162 | snd_soc_card_set_drvdata(&data->card, data); | ||
163 | |||
162 | ret = devm_snd_soc_register_card(&pdev->dev, &data->card); | 164 | ret = devm_snd_soc_register_card(&pdev->dev, &data->card); |
163 | if (ret) { | 165 | if (ret) { |
164 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | 166 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); |
165 | goto fail; | 167 | goto fail; |
166 | } | 168 | } |
167 | 169 | ||
168 | platform_set_drvdata(pdev, data); | ||
169 | of_node_put(ssi_np); | 170 | of_node_put(ssi_np); |
170 | of_node_put(codec_np); | 171 | of_node_put(codec_np); |
171 | 172 | ||
@@ -184,7 +185,8 @@ fail: | |||
184 | 185 | ||
185 | static int imx_sgtl5000_remove(struct platform_device *pdev) | 186 | static int imx_sgtl5000_remove(struct platform_device *pdev) |
186 | { | 187 | { |
187 | struct imx_sgtl5000_data *data = platform_get_drvdata(pdev); | 188 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
189 | struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(card); | ||
188 | 190 | ||
189 | clk_put(data->codec_clk); | 191 | clk_put(data->codec_clk); |
190 | 192 | ||
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c index 3fd76bc391de..3a3d17ce6ba4 100644 --- a/sound/soc/fsl/imx-wm8962.c +++ b/sound/soc/fsl/imx-wm8962.c | |||
@@ -71,7 +71,7 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card, | |||
71 | { | 71 | { |
72 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | 72 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; |
73 | struct imx_priv *priv = &card_priv; | 73 | struct imx_priv *priv = &card_priv; |
74 | struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev); | 74 | struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card); |
75 | struct device *dev = &priv->pdev->dev; | 75 | struct device *dev = &priv->pdev->dev; |
76 | unsigned int pll_out; | 76 | unsigned int pll_out; |
77 | int ret; | 77 | int ret; |
@@ -137,7 +137,7 @@ static int imx_wm8962_late_probe(struct snd_soc_card *card) | |||
137 | { | 137 | { |
138 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | 138 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; |
139 | struct imx_priv *priv = &card_priv; | 139 | struct imx_priv *priv = &card_priv; |
140 | struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev); | 140 | struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card); |
141 | struct device *dev = &priv->pdev->dev; | 141 | struct device *dev = &priv->pdev->dev; |
142 | int ret; | 142 | int ret; |
143 | 143 | ||
@@ -264,13 +264,15 @@ static int imx_wm8962_probe(struct platform_device *pdev) | |||
264 | data->card.late_probe = imx_wm8962_late_probe; | 264 | data->card.late_probe = imx_wm8962_late_probe; |
265 | data->card.set_bias_level = imx_wm8962_set_bias_level; | 265 | data->card.set_bias_level = imx_wm8962_set_bias_level; |
266 | 266 | ||
267 | platform_set_drvdata(pdev, &data->card); | ||
268 | snd_soc_card_set_drvdata(&data->card, data); | ||
269 | |||
267 | ret = devm_snd_soc_register_card(&pdev->dev, &data->card); | 270 | ret = devm_snd_soc_register_card(&pdev->dev, &data->card); |
268 | if (ret) { | 271 | if (ret) { |
269 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | 272 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); |
270 | goto clk_fail; | 273 | goto clk_fail; |
271 | } | 274 | } |
272 | 275 | ||
273 | platform_set_drvdata(pdev, data); | ||
274 | of_node_put(ssi_np); | 276 | of_node_put(ssi_np); |
275 | of_node_put(codec_np); | 277 | of_node_put(codec_np); |
276 | 278 | ||
@@ -289,7 +291,8 @@ fail: | |||
289 | 291 | ||
290 | static int imx_wm8962_remove(struct platform_device *pdev) | 292 | static int imx_wm8962_remove(struct platform_device *pdev) |
291 | { | 293 | { |
292 | struct imx_wm8962_data *data = platform_get_drvdata(pdev); | 294 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
295 | struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card); | ||
293 | 296 | ||
294 | if (!IS_ERR(data->codec_clk)) | 297 | if (!IS_ERR(data->codec_clk)) |
295 | clk_disable_unprepare(data->codec_clk); | 298 | clk_disable_unprepare(data->codec_clk); |
diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c index fce63252bdbb..804749a6c61e 100644 --- a/sound/soc/fsl/wm1133-ev1.c +++ b/sound/soc/fsl/wm1133-ev1.c | |||
@@ -214,12 +214,6 @@ static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd) | |||
214 | struct snd_soc_codec *codec = rtd->codec; | 214 | struct snd_soc_codec *codec = rtd->codec; |
215 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 215 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
216 | 216 | ||
217 | snd_soc_dapm_new_controls(dapm, wm1133_ev1_widgets, | ||
218 | ARRAY_SIZE(wm1133_ev1_widgets)); | ||
219 | |||
220 | snd_soc_dapm_add_routes(dapm, wm1133_ev1_map, | ||
221 | ARRAY_SIZE(wm1133_ev1_map)); | ||
222 | |||
223 | /* Headphone jack detection */ | 217 | /* Headphone jack detection */ |
224 | snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack); | 218 | snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack); |
225 | snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), | 219 | snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), |
@@ -257,6 +251,11 @@ static struct snd_soc_card wm1133_ev1 = { | |||
257 | .owner = THIS_MODULE, | 251 | .owner = THIS_MODULE, |
258 | .dai_link = &wm1133_ev1_dai, | 252 | .dai_link = &wm1133_ev1_dai, |
259 | .num_links = 1, | 253 | .num_links = 1, |
254 | |||
255 | .dapm_widgets = wm1133_ev1_widgets, | ||
256 | .num_dapm_widgets = ARRAY_SIZE(wm1133_ev1_widgets), | ||
257 | .dapm_routes = wm1133_ev1_map, | ||
258 | .num_dapm_routes = ARRAY_SIZE(wm1133_ev1_map), | ||
260 | }; | 259 | }; |
261 | 260 | ||
262 | static struct platform_device *wm1133_ev1_snd_device; | 261 | static struct platform_device *wm1133_ev1_snd_device; |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 2a1b1b5b5221..5dd47691ba41 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -9,48 +9,73 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
12 | #include <linux/device.h> | ||
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/of.h> | 14 | #include <linux/of.h> |
14 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
15 | #include <linux/string.h> | 16 | #include <linux/string.h> |
16 | #include <sound/simple_card.h> | 17 | #include <sound/simple_card.h> |
18 | #include <sound/soc-dai.h> | ||
19 | #include <sound/soc.h> | ||
20 | |||
21 | struct simple_card_data { | ||
22 | struct snd_soc_card snd_card; | ||
23 | unsigned int daifmt; | ||
24 | struct asoc_simple_dai cpu_dai; | ||
25 | struct asoc_simple_dai codec_dai; | ||
26 | struct snd_soc_dai_link snd_link; | ||
27 | }; | ||
17 | 28 | ||
18 | static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, | 29 | static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, |
19 | struct asoc_simple_dai *set, | 30 | struct asoc_simple_dai *set) |
20 | unsigned int daifmt) | ||
21 | { | 31 | { |
22 | int ret = 0; | 32 | int ret; |
23 | 33 | ||
24 | daifmt |= set->fmt; | 34 | if (set->fmt) { |
35 | ret = snd_soc_dai_set_fmt(dai, set->fmt); | ||
36 | if (ret && ret != -ENOTSUPP) { | ||
37 | dev_err(dai->dev, "simple-card: set_fmt error\n"); | ||
38 | goto err; | ||
39 | } | ||
40 | } | ||
25 | 41 | ||
26 | if (daifmt) | 42 | if (set->sysclk) { |
27 | ret = snd_soc_dai_set_fmt(dai, daifmt); | 43 | ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0); |
44 | if (ret && ret != -ENOTSUPP) { | ||
45 | dev_err(dai->dev, "simple-card: set_sysclk error\n"); | ||
46 | goto err; | ||
47 | } | ||
48 | } | ||
28 | 49 | ||
29 | if (ret == -ENOTSUPP) { | 50 | if (set->slots) { |
30 | dev_dbg(dai->dev, "ASoC: set_fmt is not supported\n"); | 51 | ret = snd_soc_dai_set_tdm_slot(dai, 0, 0, |
31 | ret = 0; | 52 | set->slots, |
53 | set->slot_width); | ||
54 | if (ret && ret != -ENOTSUPP) { | ||
55 | dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); | ||
56 | goto err; | ||
57 | } | ||
32 | } | 58 | } |
33 | 59 | ||
34 | if (!ret && set->sysclk) | 60 | ret = 0; |
35 | ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0); | ||
36 | 61 | ||
62 | err: | ||
37 | return ret; | 63 | return ret; |
38 | } | 64 | } |
39 | 65 | ||
40 | static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) | 66 | static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) |
41 | { | 67 | { |
42 | struct asoc_simple_card_info *info = | 68 | struct simple_card_data *priv = |
43 | snd_soc_card_get_drvdata(rtd->card); | 69 | snd_soc_card_get_drvdata(rtd->card); |
44 | struct snd_soc_dai *codec = rtd->codec_dai; | 70 | struct snd_soc_dai *codec = rtd->codec_dai; |
45 | struct snd_soc_dai *cpu = rtd->cpu_dai; | 71 | struct snd_soc_dai *cpu = rtd->cpu_dai; |
46 | unsigned int daifmt = info->daifmt; | ||
47 | int ret; | 72 | int ret; |
48 | 73 | ||
49 | ret = __asoc_simple_card_dai_init(codec, &info->codec_dai, daifmt); | 74 | ret = __asoc_simple_card_dai_init(codec, &priv->codec_dai); |
50 | if (ret < 0) | 75 | if (ret < 0) |
51 | return ret; | 76 | return ret; |
52 | 77 | ||
53 | ret = __asoc_simple_card_dai_init(cpu, &info->cpu_dai, daifmt); | 78 | ret = __asoc_simple_card_dai_init(cpu, &priv->cpu_dai); |
54 | if (ret < 0) | 79 | if (ret < 0) |
55 | return ret; | 80 | return ret; |
56 | 81 | ||
@@ -59,9 +84,12 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) | |||
59 | 84 | ||
60 | static int | 85 | static int |
61 | asoc_simple_card_sub_parse_of(struct device_node *np, | 86 | asoc_simple_card_sub_parse_of(struct device_node *np, |
87 | unsigned int daifmt, | ||
62 | struct asoc_simple_dai *dai, | 88 | struct asoc_simple_dai *dai, |
63 | struct device_node **node) | 89 | const struct device_node **p_node, |
90 | const char **name) | ||
64 | { | 91 | { |
92 | struct device_node *node; | ||
65 | struct clk *clk; | 93 | struct clk *clk; |
66 | int ret; | 94 | int ret; |
67 | 95 | ||
@@ -69,21 +97,28 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
69 | * get node via "sound-dai = <&phandle port>" | 97 | * get node via "sound-dai = <&phandle port>" |
70 | * it will be used as xxx_of_node on soc_bind_dai_link() | 98 | * it will be used as xxx_of_node on soc_bind_dai_link() |
71 | */ | 99 | */ |
72 | *node = of_parse_phandle(np, "sound-dai", 0); | 100 | node = of_parse_phandle(np, "sound-dai", 0); |
73 | if (!*node) | 101 | if (!node) |
74 | return -ENODEV; | 102 | return -ENODEV; |
103 | *p_node = node; | ||
75 | 104 | ||
76 | /* get dai->name */ | 105 | /* get dai->name */ |
77 | ret = snd_soc_of_get_dai_name(np, &dai->name); | 106 | ret = snd_soc_of_get_dai_name(np, name); |
78 | if (ret < 0) | 107 | if (ret < 0) |
79 | goto parse_error; | 108 | goto parse_error; |
80 | 109 | ||
110 | /* parse TDM slot */ | ||
111 | ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); | ||
112 | if (ret) | ||
113 | goto parse_error; | ||
114 | |||
81 | /* | 115 | /* |
82 | * bitclock-inversion, frame-inversion | 116 | * bitclock-inversion, frame-inversion |
83 | * bitclock-master, frame-master | 117 | * bitclock-master, frame-master |
84 | * and specific "format" if it has | 118 | * and specific "format" if it has |
85 | */ | 119 | */ |
86 | dai->fmt = snd_soc_of_parse_daifmt(np, NULL); | 120 | dai->fmt = snd_soc_of_parse_daifmt(np, NULL); |
121 | dai->fmt |= daifmt; | ||
87 | 122 | ||
88 | /* | 123 | /* |
89 | * dai->sysclk come from | 124 | * dai->sysclk come from |
@@ -104,7 +139,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
104 | "system-clock-frequency", | 139 | "system-clock-frequency", |
105 | &dai->sysclk); | 140 | &dai->sysclk); |
106 | } else { | 141 | } else { |
107 | clk = of_clk_get(*node, 0); | 142 | clk = of_clk_get(node, 0); |
108 | if (!IS_ERR(clk)) | 143 | if (!IS_ERR(clk)) |
109 | dai->sysclk = clk_get_rate(clk); | 144 | dai->sysclk = clk_get_rate(clk); |
110 | } | 145 | } |
@@ -112,29 +147,38 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
112 | ret = 0; | 147 | ret = 0; |
113 | 148 | ||
114 | parse_error: | 149 | parse_error: |
115 | of_node_put(*node); | 150 | of_node_put(node); |
116 | 151 | ||
117 | return ret; | 152 | return ret; |
118 | } | 153 | } |
119 | 154 | ||
120 | static int asoc_simple_card_parse_of(struct device_node *node, | 155 | static int asoc_simple_card_parse_of(struct device_node *node, |
121 | struct asoc_simple_card_info *info, | 156 | struct simple_card_data *priv, |
122 | struct device *dev, | 157 | struct device *dev) |
123 | struct device_node **of_cpu, | ||
124 | struct device_node **of_codec, | ||
125 | struct device_node **of_platform) | ||
126 | { | 158 | { |
159 | struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; | ||
127 | struct device_node *np; | 160 | struct device_node *np; |
128 | char *name; | 161 | char *name; |
129 | int ret; | 162 | int ret; |
130 | 163 | ||
164 | /* parsing the card name from DT */ | ||
165 | snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); | ||
166 | |||
131 | /* get CPU/CODEC common format via simple-audio-card,format */ | 167 | /* get CPU/CODEC common format via simple-audio-card,format */ |
132 | info->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & | 168 | priv->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & |
133 | (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); | 169 | (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); |
134 | 170 | ||
171 | /* off-codec widgets */ | ||
172 | if (of_property_read_bool(node, "simple-audio-card,widgets")) { | ||
173 | ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, | ||
174 | "simple-audio-card,widgets"); | ||
175 | if (ret) | ||
176 | return ret; | ||
177 | } | ||
178 | |||
135 | /* DAPM routes */ | 179 | /* DAPM routes */ |
136 | if (of_property_read_bool(node, "simple-audio-card,routing")) { | 180 | if (of_property_read_bool(node, "simple-audio-card,routing")) { |
137 | ret = snd_soc_of_parse_audio_routing(&info->snd_card, | 181 | ret = snd_soc_of_parse_audio_routing(&priv->snd_card, |
138 | "simple-audio-card,routing"); | 182 | "simple-audio-card,routing"); |
139 | if (ret) | 183 | if (ret) |
140 | return ret; | 184 | return ret; |
@@ -144,9 +188,10 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
144 | ret = -EINVAL; | 188 | ret = -EINVAL; |
145 | np = of_get_child_by_name(node, "simple-audio-card,cpu"); | 189 | np = of_get_child_by_name(node, "simple-audio-card,cpu"); |
146 | if (np) | 190 | if (np) |
147 | ret = asoc_simple_card_sub_parse_of(np, | 191 | ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, |
148 | &info->cpu_dai, | 192 | &priv->cpu_dai, |
149 | of_cpu); | 193 | &dai_link->cpu_of_node, |
194 | &dai_link->cpu_dai_name); | ||
150 | if (ret < 0) | 195 | if (ret < 0) |
151 | return ret; | 196 | return ret; |
152 | 197 | ||
@@ -154,114 +199,126 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
154 | ret = -EINVAL; | 199 | ret = -EINVAL; |
155 | np = of_get_child_by_name(node, "simple-audio-card,codec"); | 200 | np = of_get_child_by_name(node, "simple-audio-card,codec"); |
156 | if (np) | 201 | if (np) |
157 | ret = asoc_simple_card_sub_parse_of(np, | 202 | ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, |
158 | &info->codec_dai, | 203 | &priv->codec_dai, |
159 | of_codec); | 204 | &dai_link->codec_of_node, |
205 | &dai_link->codec_dai_name); | ||
160 | if (ret < 0) | 206 | if (ret < 0) |
161 | return ret; | 207 | return ret; |
162 | 208 | ||
163 | if (!info->cpu_dai.name || !info->codec_dai.name) | 209 | if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) |
164 | return -EINVAL; | 210 | return -EINVAL; |
165 | 211 | ||
166 | /* card name is created from CPU/CODEC dai name */ | 212 | /* card name is created from CPU/CODEC dai name */ |
167 | name = devm_kzalloc(dev, | 213 | name = devm_kzalloc(dev, |
168 | strlen(info->cpu_dai.name) + | 214 | strlen(dai_link->cpu_dai_name) + |
169 | strlen(info->codec_dai.name) + 2, | 215 | strlen(dai_link->codec_dai_name) + 2, |
170 | GFP_KERNEL); | 216 | GFP_KERNEL); |
171 | sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name); | 217 | sprintf(name, "%s-%s", dai_link->cpu_dai_name, |
172 | info->name = info->card = name; | 218 | dai_link->codec_dai_name); |
219 | if (!priv->snd_card.name) | ||
220 | priv->snd_card.name = name; | ||
221 | dai_link->name = dai_link->stream_name = name; | ||
173 | 222 | ||
174 | /* simple-card assumes platform == cpu */ | 223 | /* simple-card assumes platform == cpu */ |
175 | *of_platform = *of_cpu; | 224 | dai_link->platform_of_node = dai_link->cpu_of_node; |
176 | 225 | ||
177 | dev_dbg(dev, "card-name : %s\n", info->card); | 226 | dev_dbg(dev, "card-name : %s\n", name); |
178 | dev_dbg(dev, "platform : %04x\n", info->daifmt); | 227 | dev_dbg(dev, "platform : %04x\n", priv->daifmt); |
179 | dev_dbg(dev, "cpu : %s / %04x / %d\n", | 228 | dev_dbg(dev, "cpu : %s / %04x / %d\n", |
180 | info->cpu_dai.name, | 229 | dai_link->cpu_dai_name, |
181 | info->cpu_dai.fmt, | 230 | priv->cpu_dai.fmt, |
182 | info->cpu_dai.sysclk); | 231 | priv->cpu_dai.sysclk); |
183 | dev_dbg(dev, "codec : %s / %04x / %d\n", | 232 | dev_dbg(dev, "codec : %s / %04x / %d\n", |
184 | info->codec_dai.name, | 233 | dai_link->codec_dai_name, |
185 | info->codec_dai.fmt, | 234 | priv->codec_dai.fmt, |
186 | info->codec_dai.sysclk); | 235 | priv->codec_dai.sysclk); |
236 | |||
237 | /* | ||
238 | * soc_bind_dai_link() will check cpu name | ||
239 | * after of_node matching if dai_link has cpu_dai_name. | ||
240 | * but, it will never match if name was created by fmt_single_name() | ||
241 | * remove cpu_dai_name to escape name matching. | ||
242 | * see | ||
243 | * fmt_single_name() | ||
244 | * fmt_multiple_name() | ||
245 | */ | ||
246 | dai_link->cpu_dai_name = NULL; | ||
187 | 247 | ||
188 | return 0; | 248 | return 0; |
189 | } | 249 | } |
190 | 250 | ||
191 | static int asoc_simple_card_probe(struct platform_device *pdev) | 251 | static int asoc_simple_card_probe(struct platform_device *pdev) |
192 | { | 252 | { |
193 | struct asoc_simple_card_info *cinfo; | 253 | struct simple_card_data *priv; |
254 | struct snd_soc_dai_link *dai_link; | ||
194 | struct device_node *np = pdev->dev.of_node; | 255 | struct device_node *np = pdev->dev.of_node; |
195 | struct device_node *of_cpu, *of_codec, *of_platform; | ||
196 | struct device *dev = &pdev->dev; | 256 | struct device *dev = &pdev->dev; |
197 | int ret; | 257 | int ret; |
198 | 258 | ||
199 | cinfo = NULL; | 259 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
200 | of_cpu = NULL; | 260 | if (!priv) |
201 | of_codec = NULL; | ||
202 | of_platform = NULL; | ||
203 | |||
204 | cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL); | ||
205 | if (!cinfo) | ||
206 | return -ENOMEM; | 261 | return -ENOMEM; |
207 | 262 | ||
263 | /* | ||
264 | * init snd_soc_card | ||
265 | */ | ||
266 | priv->snd_card.owner = THIS_MODULE; | ||
267 | priv->snd_card.dev = dev; | ||
268 | dai_link = &priv->snd_link; | ||
269 | priv->snd_card.dai_link = dai_link; | ||
270 | priv->snd_card.num_links = 1; | ||
271 | |||
208 | if (np && of_device_is_available(np)) { | 272 | if (np && of_device_is_available(np)) { |
209 | cinfo->snd_card.dev = dev; | ||
210 | 273 | ||
211 | ret = asoc_simple_card_parse_of(np, cinfo, dev, | 274 | ret = asoc_simple_card_parse_of(np, priv, dev); |
212 | &of_cpu, | ||
213 | &of_codec, | ||
214 | &of_platform); | ||
215 | if (ret < 0) { | 275 | if (ret < 0) { |
216 | if (ret != -EPROBE_DEFER) | 276 | if (ret != -EPROBE_DEFER) |
217 | dev_err(dev, "parse error %d\n", ret); | 277 | dev_err(dev, "parse error %d\n", ret); |
218 | return ret; | 278 | return ret; |
219 | } | 279 | } |
220 | } else { | 280 | } else { |
221 | if (!dev->platform_data) { | 281 | struct asoc_simple_card_info *cinfo; |
282 | |||
283 | cinfo = dev->platform_data; | ||
284 | if (!cinfo) { | ||
222 | dev_err(dev, "no info for asoc-simple-card\n"); | 285 | dev_err(dev, "no info for asoc-simple-card\n"); |
223 | return -EINVAL; | 286 | return -EINVAL; |
224 | } | 287 | } |
225 | 288 | ||
226 | memcpy(cinfo, dev->platform_data, sizeof(*cinfo)); | 289 | if (!cinfo->name || |
227 | cinfo->snd_card.dev = dev; | 290 | !cinfo->codec_dai.name || |
228 | } | 291 | !cinfo->codec || |
292 | !cinfo->platform || | ||
293 | !cinfo->cpu_dai.name) { | ||
294 | dev_err(dev, "insufficient asoc_simple_card_info settings\n"); | ||
295 | return -EINVAL; | ||
296 | } | ||
229 | 297 | ||
230 | if (!cinfo->name || | 298 | priv->snd_card.name = (cinfo->card) ? cinfo->card : cinfo->name; |
231 | !cinfo->card || | 299 | dai_link->name = cinfo->name; |
232 | !cinfo->codec_dai.name || | 300 | dai_link->stream_name = cinfo->name; |
233 | !(cinfo->codec || of_codec) || | 301 | dai_link->platform_name = cinfo->platform; |
234 | !(cinfo->platform || of_platform) || | 302 | dai_link->codec_name = cinfo->codec; |
235 | !(cinfo->cpu_dai.name || of_cpu)) { | 303 | dai_link->cpu_dai_name = cinfo->cpu_dai.name; |
236 | dev_err(dev, "insufficient asoc_simple_card_info settings\n"); | 304 | dai_link->codec_dai_name = cinfo->codec_dai.name; |
237 | return -EINVAL; | 305 | memcpy(&priv->cpu_dai, &cinfo->cpu_dai, |
306 | sizeof(priv->cpu_dai)); | ||
307 | memcpy(&priv->codec_dai, &cinfo->codec_dai, | ||
308 | sizeof(priv->codec_dai)); | ||
309 | |||
310 | priv->cpu_dai.fmt |= cinfo->daifmt; | ||
311 | priv->codec_dai.fmt |= cinfo->daifmt; | ||
238 | } | 312 | } |
239 | 313 | ||
240 | /* | 314 | /* |
241 | * init snd_soc_dai_link | 315 | * init snd_soc_dai_link |
242 | */ | 316 | */ |
243 | cinfo->snd_link.name = cinfo->name; | 317 | dai_link->init = asoc_simple_card_dai_init; |
244 | cinfo->snd_link.stream_name = cinfo->name; | ||
245 | cinfo->snd_link.cpu_dai_name = cinfo->cpu_dai.name; | ||
246 | cinfo->snd_link.platform_name = cinfo->platform; | ||
247 | cinfo->snd_link.codec_name = cinfo->codec; | ||
248 | cinfo->snd_link.codec_dai_name = cinfo->codec_dai.name; | ||
249 | cinfo->snd_link.cpu_of_node = of_cpu; | ||
250 | cinfo->snd_link.codec_of_node = of_codec; | ||
251 | cinfo->snd_link.platform_of_node = of_platform; | ||
252 | cinfo->snd_link.init = asoc_simple_card_dai_init; | ||
253 | |||
254 | /* | ||
255 | * init snd_soc_card | ||
256 | */ | ||
257 | cinfo->snd_card.name = cinfo->card; | ||
258 | cinfo->snd_card.owner = THIS_MODULE; | ||
259 | cinfo->snd_card.dai_link = &cinfo->snd_link; | ||
260 | cinfo->snd_card.num_links = 1; | ||
261 | 318 | ||
262 | snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo); | 319 | snd_soc_card_set_drvdata(&priv->snd_card, priv); |
263 | 320 | ||
264 | return devm_snd_soc_register_card(&pdev->dev, &cinfo->snd_card); | 321 | return devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); |
265 | } | 322 | } |
266 | 323 | ||
267 | static const struct of_device_id asoc_simple_of_match[] = { | 324 | static const struct of_device_id asoc_simple_of_match[] = { |
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 61c10bf503d2..3c81b3891209 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -2,12 +2,50 @@ config SND_MFLD_MACHINE | |||
2 | tristate "SOC Machine Audio driver for Intel Medfield MID platform" | 2 | tristate "SOC Machine Audio driver for Intel Medfield MID platform" |
3 | depends on INTEL_SCU_IPC | 3 | depends on INTEL_SCU_IPC |
4 | select SND_SOC_SN95031 | 4 | select SND_SOC_SN95031 |
5 | select SND_SST_PLATFORM | 5 | select SND_SST_MFLD_PLATFORM |
6 | help | 6 | help |
7 | This adds support for ASoC machine driver for Intel(R) MID Medfield platform | 7 | This adds support for ASoC machine driver for Intel(R) MID Medfield platform |
8 | used as alsa device in audio substem in Intel(R) MID devices | 8 | used as alsa device in audio substem in Intel(R) MID devices |
9 | Say Y if you have such a device | 9 | Say Y if you have such a device |
10 | If unsure select "N". | 10 | If unsure select "N". |
11 | 11 | ||
12 | config SND_SST_PLATFORM | 12 | config SND_SST_MFLD_PLATFORM |
13 | tristate | 13 | tristate |
14 | |||
15 | config SND_SOC_INTEL_SST | ||
16 | tristate "ASoC support for Intel(R) Smart Sound Technology" | ||
17 | select SND_SOC_INTEL_SST_ACPI if ACPI | ||
18 | depends on (X86 || COMPILE_TEST) | ||
19 | help | ||
20 | This adds support for Intel(R) Smart Sound Technology (SST). | ||
21 | Say Y if you have such a device | ||
22 | If unsure select "N". | ||
23 | |||
24 | config SND_SOC_INTEL_SST_ACPI | ||
25 | tristate | ||
26 | |||
27 | config SND_SOC_INTEL_HASWELL | ||
28 | tristate | ||
29 | |||
30 | config SND_SOC_INTEL_BAYTRAIL | ||
31 | tristate | ||
32 | |||
33 | config SND_SOC_INTEL_HASWELL_MACH | ||
34 | tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" | ||
35 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C | ||
36 | select SND_SOC_INTEL_HASWELL | ||
37 | select SND_SOC_RT5640 | ||
38 | help | ||
39 | This adds support for the Lynxpoint Audio DSP on Intel(R) Haswell | ||
40 | Ultrabook platforms. | ||
41 | Say Y if you have such a device | ||
42 | If unsure select "N". | ||
43 | |||
44 | config SND_SOC_INTEL_BYT_RT5640_MACH | ||
45 | tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec" | ||
46 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C | ||
47 | select SND_SOC_INTEL_BAYTRAIL | ||
48 | select SND_SOC_RT5640 | ||
49 | help | ||
50 | This adds audio driver for Intel Baytrail platform based boards | ||
51 | with the RT5640 audio codec. | ||
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 639883339465..edeb79ae3dff 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile | |||
@@ -1,5 +1,28 @@ | |||
1 | snd-soc-sst-platform-objs := sst_platform.o | 1 | # Core support |
2 | snd-soc-sst-dsp-objs := sst-dsp.o sst-firmware.o | ||
3 | snd-soc-sst-acpi-objs := sst-acpi.o | ||
4 | |||
5 | snd-soc-sst-mfld-platform-objs := sst-mfld-platform.o | ||
2 | snd-soc-mfld-machine-objs := mfld_machine.o | 6 | snd-soc-mfld-machine-objs := mfld_machine.o |
3 | 7 | ||
4 | obj-$(CONFIG_SND_SST_PLATFORM) += snd-soc-sst-platform.o | 8 | obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o |
5 | obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o | 9 | obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o |
10 | |||
11 | obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o | ||
12 | obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o | ||
13 | |||
14 | # Platform Support | ||
15 | snd-soc-sst-haswell-pcm-objs := \ | ||
16 | sst-haswell-ipc.o sst-haswell-pcm.o sst-haswell-dsp.o | ||
17 | snd-soc-sst-baytrail-pcm-objs := \ | ||
18 | sst-baytrail-ipc.o sst-baytrail-pcm.o sst-baytrail-dsp.o | ||
19 | |||
20 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += snd-soc-sst-haswell-pcm.o | ||
21 | obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o | ||
22 | |||
23 | # Machine support | ||
24 | snd-soc-sst-haswell-objs := haswell.o | ||
25 | snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o | ||
26 | |||
27 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o | ||
28 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o | ||
diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c new file mode 100644 index 000000000000..eff97c8e5218 --- /dev/null +++ b/sound/soc/intel/byt-rt5640.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * Intel Baytrail SST RT5640 machine driver | ||
3 | * Copyright (c) 2014, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/acpi.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <sound/pcm.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | #include <sound/soc.h> | ||
24 | #include <sound/jack.h> | ||
25 | #include "../codecs/rt5640.h" | ||
26 | |||
27 | #include "sst-dsp.h" | ||
28 | |||
29 | static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { | ||
30 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
31 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
32 | SND_SOC_DAPM_MIC("Internal Mic", NULL), | ||
33 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
34 | }; | ||
35 | |||
36 | static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { | ||
37 | {"IN2P", NULL, "Headset Mic"}, | ||
38 | {"IN2N", NULL, "Headset Mic"}, | ||
39 | {"DMIC1", NULL, "Internal Mic"}, | ||
40 | {"Headphone", NULL, "HPOL"}, | ||
41 | {"Headphone", NULL, "HPOR"}, | ||
42 | {"Speaker", NULL, "SPOLP"}, | ||
43 | {"Speaker", NULL, "SPOLN"}, | ||
44 | {"Speaker", NULL, "SPORP"}, | ||
45 | {"Speaker", NULL, "SPORN"}, | ||
46 | }; | ||
47 | |||
48 | static const struct snd_kcontrol_new byt_rt5640_controls[] = { | ||
49 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
50 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
51 | SOC_DAPM_PIN_SWITCH("Internal Mic"), | ||
52 | SOC_DAPM_PIN_SWITCH("Speaker"), | ||
53 | }; | ||
54 | |||
55 | static int byt_rt5640_hw_params(struct snd_pcm_substream *substream, | ||
56 | struct snd_pcm_hw_params *params) | ||
57 | { | ||
58 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
59 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
60 | int ret; | ||
61 | |||
62 | ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, | ||
63 | params_rate(params) * 256, | ||
64 | SND_SOC_CLOCK_IN); | ||
65 | if (ret < 0) { | ||
66 | dev_err(codec_dai->dev, "can't set codec clock %d\n", ret); | ||
67 | return ret; | ||
68 | } | ||
69 | ret = snd_soc_dai_set_pll(codec_dai, 0, RT5640_PLL1_S_BCLK1, | ||
70 | params_rate(params) * 64, | ||
71 | params_rate(params) * 256); | ||
72 | if (ret < 0) { | ||
73 | dev_err(codec_dai->dev, "can't set codec pll: %d\n", ret); | ||
74 | return ret; | ||
75 | } | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) | ||
80 | { | ||
81 | int ret; | ||
82 | struct snd_soc_codec *codec = runtime->codec; | ||
83 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
84 | struct snd_soc_card *card = runtime->card; | ||
85 | |||
86 | card->dapm.idle_bias_off = true; | ||
87 | |||
88 | ret = snd_soc_add_card_controls(card, byt_rt5640_controls, | ||
89 | ARRAY_SIZE(byt_rt5640_controls)); | ||
90 | if (ret) { | ||
91 | dev_err(card->dev, "unable to add card controls\n"); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | snd_soc_dapm_ignore_suspend(dapm, "HPOL"); | ||
96 | snd_soc_dapm_ignore_suspend(dapm, "HPOR"); | ||
97 | |||
98 | snd_soc_dapm_ignore_suspend(dapm, "SPOLP"); | ||
99 | snd_soc_dapm_ignore_suspend(dapm, "SPOLN"); | ||
100 | snd_soc_dapm_ignore_suspend(dapm, "SPORP"); | ||
101 | snd_soc_dapm_ignore_suspend(dapm, "SPORN"); | ||
102 | |||
103 | snd_soc_dapm_enable_pin(dapm, "Headset Mic"); | ||
104 | snd_soc_dapm_enable_pin(dapm, "Headphone"); | ||
105 | snd_soc_dapm_enable_pin(dapm, "Speaker"); | ||
106 | snd_soc_dapm_enable_pin(dapm, "Internal Mic"); | ||
107 | |||
108 | snd_soc_dapm_sync(dapm); | ||
109 | return ret; | ||
110 | } | ||
111 | |||
112 | static struct snd_soc_ops byt_rt5640_ops = { | ||
113 | .hw_params = byt_rt5640_hw_params, | ||
114 | }; | ||
115 | |||
116 | static struct snd_soc_dai_link byt_rt5640_dais[] = { | ||
117 | { | ||
118 | .name = "Baytrail Audio", | ||
119 | .stream_name = "Audio", | ||
120 | .cpu_dai_name = "Front-cpu-dai", | ||
121 | .codec_dai_name = "rt5640-aif1", | ||
122 | .codec_name = "i2c-10EC5640:00", | ||
123 | .platform_name = "baytrail-pcm-audio", | ||
124 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
125 | SND_SOC_DAIFMT_CBS_CFS, | ||
126 | .init = byt_rt5640_init, | ||
127 | .ignore_suspend = 1, | ||
128 | .ops = &byt_rt5640_ops, | ||
129 | }, | ||
130 | { | ||
131 | .name = "Baytrail Voice", | ||
132 | .stream_name = "Voice", | ||
133 | .cpu_dai_name = "Mic1-cpu-dai", | ||
134 | .codec_dai_name = "rt5640-aif1", | ||
135 | .codec_name = "i2c-10EC5640:00", | ||
136 | .platform_name = "baytrail-pcm-audio", | ||
137 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
138 | SND_SOC_DAIFMT_CBS_CFS, | ||
139 | .init = NULL, | ||
140 | .ignore_suspend = 1, | ||
141 | .ops = &byt_rt5640_ops, | ||
142 | }, | ||
143 | }; | ||
144 | |||
145 | static struct snd_soc_card byt_rt5640_card = { | ||
146 | .name = "byt-rt5640", | ||
147 | .dai_link = byt_rt5640_dais, | ||
148 | .num_links = ARRAY_SIZE(byt_rt5640_dais), | ||
149 | .dapm_widgets = byt_rt5640_widgets, | ||
150 | .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets), | ||
151 | .dapm_routes = byt_rt5640_audio_map, | ||
152 | .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map), | ||
153 | }; | ||
154 | |||
155 | static int byt_rt5640_probe(struct platform_device *pdev) | ||
156 | { | ||
157 | struct snd_soc_card *card = &byt_rt5640_card; | ||
158 | struct device *dev = &pdev->dev; | ||
159 | |||
160 | card->dev = &pdev->dev; | ||
161 | dev_set_drvdata(dev, card); | ||
162 | return snd_soc_register_card(card); | ||
163 | } | ||
164 | |||
165 | static int byt_rt5640_remove(struct platform_device *pdev) | ||
166 | { | ||
167 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
168 | |||
169 | snd_soc_unregister_card(card); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static struct platform_driver byt_rt5640_audio = { | ||
175 | .probe = byt_rt5640_probe, | ||
176 | .remove = byt_rt5640_remove, | ||
177 | .driver = { | ||
178 | .name = "byt-rt5640", | ||
179 | .owner = THIS_MODULE, | ||
180 | }, | ||
181 | }; | ||
182 | module_platform_driver(byt_rt5640_audio) | ||
183 | |||
184 | MODULE_DESCRIPTION("ASoC Intel(R) Baytrail Machine driver"); | ||
185 | MODULE_AUTHOR("Omair Md Abdullah, Jarkko Nikula"); | ||
186 | MODULE_LICENSE("GPL v2"); | ||
187 | MODULE_ALIAS("platform:byt-rt5640"); | ||
diff --git a/sound/soc/intel/haswell.c b/sound/soc/intel/haswell.c new file mode 100644 index 000000000000..54345a2a7386 --- /dev/null +++ b/sound/soc/intel/haswell.c | |||
@@ -0,0 +1,235 @@ | |||
1 | /* | ||
2 | * Intel Haswell Lynxpoint SST Audio | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <sound/core.h> | ||
20 | #include <sound/pcm.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | |||
24 | #include "sst-dsp.h" | ||
25 | #include "sst-haswell-ipc.h" | ||
26 | |||
27 | #include "../codecs/rt5640.h" | ||
28 | |||
29 | /* Haswell ULT platforms have a Headphone and Mic jack */ | ||
30 | static const struct snd_soc_dapm_widget haswell_widgets[] = { | ||
31 | SND_SOC_DAPM_HP("Headphones", NULL), | ||
32 | SND_SOC_DAPM_MIC("Mic", NULL), | ||
33 | }; | ||
34 | |||
35 | static const struct snd_soc_dapm_route haswell_rt5640_map[] = { | ||
36 | |||
37 | {"Headphones", NULL, "HPOR"}, | ||
38 | {"Headphones", NULL, "HPOL"}, | ||
39 | {"IN2P", NULL, "Mic"}, | ||
40 | |||
41 | /* CODEC BE connections */ | ||
42 | {"SSP0 CODEC IN", NULL, "AIF1 Capture"}, | ||
43 | {"AIF1 Playback", NULL, "SSP0 CODEC OUT"}, | ||
44 | }; | ||
45 | |||
46 | static int haswell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, | ||
47 | struct snd_pcm_hw_params *params) | ||
48 | { | ||
49 | struct snd_interval *rate = hw_param_interval(params, | ||
50 | SNDRV_PCM_HW_PARAM_RATE); | ||
51 | struct snd_interval *channels = hw_param_interval(params, | ||
52 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
53 | |||
54 | /* The ADSP will covert the FE rate to 48k, stereo */ | ||
55 | rate->min = rate->max = 48000; | ||
56 | channels->min = channels->max = 2; | ||
57 | |||
58 | /* set SSP0 to 16 bit */ | ||
59 | snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - | ||
60 | SNDRV_PCM_HW_PARAM_FIRST_MASK], | ||
61 | SNDRV_PCM_FORMAT_S16_LE); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int haswell_rt5640_hw_params(struct snd_pcm_substream *substream, | ||
66 | struct snd_pcm_hw_params *params) | ||
67 | { | ||
68 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
69 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
70 | int ret; | ||
71 | |||
72 | ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_MCLK, 12288000, | ||
73 | SND_SOC_CLOCK_IN); | ||
74 | |||
75 | if (ret < 0) { | ||
76 | dev_err(rtd->dev, "can't set codec sysclk configuration\n"); | ||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | /* set correct codec filter for DAI format and clock config */ | ||
81 | snd_soc_update_bits(rtd->codec, 0x83, 0xffff, 0x8000); | ||
82 | |||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static struct snd_soc_ops haswell_rt5640_ops = { | ||
87 | .hw_params = haswell_rt5640_hw_params, | ||
88 | }; | ||
89 | |||
90 | static int haswell_rtd_init(struct snd_soc_pcm_runtime *rtd) | ||
91 | { | ||
92 | struct snd_soc_codec *codec = rtd->codec; | ||
93 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
94 | struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev); | ||
95 | struct sst_hsw *haswell = pdata->dsp; | ||
96 | int ret; | ||
97 | |||
98 | /* Set ADSP SSP port settings */ | ||
99 | ret = sst_hsw_device_set_config(haswell, SST_HSW_DEVICE_SSP_0, | ||
100 | SST_HSW_DEVICE_MCLK_FREQ_24_MHZ, | ||
101 | SST_HSW_DEVICE_CLOCK_MASTER, 9); | ||
102 | if (ret < 0) { | ||
103 | dev_err(rtd->dev, "failed to set device config\n"); | ||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | /* always connected */ | ||
108 | snd_soc_dapm_enable_pin(dapm, "Headphones"); | ||
109 | snd_soc_dapm_enable_pin(dapm, "Mic"); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static struct snd_soc_dai_link haswell_rt5640_dais[] = { | ||
115 | /* Front End DAI links */ | ||
116 | { | ||
117 | .name = "System", | ||
118 | .stream_name = "System Playback", | ||
119 | .cpu_dai_name = "System Pin", | ||
120 | .platform_name = "haswell-pcm-audio", | ||
121 | .dynamic = 1, | ||
122 | .codec_name = "snd-soc-dummy", | ||
123 | .codec_dai_name = "snd-soc-dummy-dai", | ||
124 | .init = haswell_rtd_init, | ||
125 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
126 | .dpcm_playback = 1, | ||
127 | }, | ||
128 | { | ||
129 | .name = "Offload0", | ||
130 | .stream_name = "Offload0 Playback", | ||
131 | .cpu_dai_name = "Offload0 Pin", | ||
132 | .platform_name = "haswell-pcm-audio", | ||
133 | .dynamic = 1, | ||
134 | .codec_name = "snd-soc-dummy", | ||
135 | .codec_dai_name = "snd-soc-dummy-dai", | ||
136 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
137 | .dpcm_playback = 1, | ||
138 | }, | ||
139 | { | ||
140 | .name = "Offload1", | ||
141 | .stream_name = "Offload1 Playback", | ||
142 | .cpu_dai_name = "Offload1 Pin", | ||
143 | .platform_name = "haswell-pcm-audio", | ||
144 | .dynamic = 1, | ||
145 | .codec_name = "snd-soc-dummy", | ||
146 | .codec_dai_name = "snd-soc-dummy-dai", | ||
147 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
148 | .dpcm_playback = 1, | ||
149 | }, | ||
150 | { | ||
151 | .name = "Loopback", | ||
152 | .stream_name = "Loopback", | ||
153 | .cpu_dai_name = "Loopback Pin", | ||
154 | .platform_name = "haswell-pcm-audio", | ||
155 | .dynamic = 0, | ||
156 | .codec_name = "snd-soc-dummy", | ||
157 | .codec_dai_name = "snd-soc-dummy-dai", | ||
158 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
159 | .dpcm_capture = 1, | ||
160 | }, | ||
161 | { | ||
162 | .name = "Capture", | ||
163 | .stream_name = "Capture", | ||
164 | .cpu_dai_name = "Capture Pin", | ||
165 | .platform_name = "haswell-pcm-audio", | ||
166 | .dynamic = 1, | ||
167 | .codec_name = "snd-soc-dummy", | ||
168 | .codec_dai_name = "snd-soc-dummy-dai", | ||
169 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
170 | .dpcm_capture = 1, | ||
171 | }, | ||
172 | |||
173 | /* Back End DAI links */ | ||
174 | { | ||
175 | /* SSP0 - Codec */ | ||
176 | .name = "Codec", | ||
177 | .be_id = 0, | ||
178 | .cpu_dai_name = "snd-soc-dummy-dai", | ||
179 | .platform_name = "snd-soc-dummy", | ||
180 | .no_pcm = 1, | ||
181 | .codec_name = "i2c-INT33CA:00", | ||
182 | .codec_dai_name = "rt5640-aif1", | ||
183 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
184 | SND_SOC_DAIFMT_CBS_CFS, | ||
185 | .ignore_suspend = 1, | ||
186 | .ignore_pmdown_time = 1, | ||
187 | .be_hw_params_fixup = haswell_ssp0_fixup, | ||
188 | .ops = &haswell_rt5640_ops, | ||
189 | .dpcm_playback = 1, | ||
190 | .dpcm_capture = 1, | ||
191 | }, | ||
192 | }; | ||
193 | |||
194 | /* audio machine driver for Haswell Lynxpoint DSP + RT5640 */ | ||
195 | static struct snd_soc_card haswell_rt5640 = { | ||
196 | .name = "haswell-rt5640", | ||
197 | .owner = THIS_MODULE, | ||
198 | .dai_link = haswell_rt5640_dais, | ||
199 | .num_links = ARRAY_SIZE(haswell_rt5640_dais), | ||
200 | .dapm_widgets = haswell_widgets, | ||
201 | .num_dapm_widgets = ARRAY_SIZE(haswell_widgets), | ||
202 | .dapm_routes = haswell_rt5640_map, | ||
203 | .num_dapm_routes = ARRAY_SIZE(haswell_rt5640_map), | ||
204 | .fully_routed = true, | ||
205 | }; | ||
206 | |||
207 | static int haswell_audio_probe(struct platform_device *pdev) | ||
208 | { | ||
209 | haswell_rt5640.dev = &pdev->dev; | ||
210 | |||
211 | return snd_soc_register_card(&haswell_rt5640); | ||
212 | } | ||
213 | |||
214 | static int haswell_audio_remove(struct platform_device *pdev) | ||
215 | { | ||
216 | snd_soc_unregister_card(&haswell_rt5640); | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static struct platform_driver haswell_audio = { | ||
221 | .probe = haswell_audio_probe, | ||
222 | .remove = haswell_audio_remove, | ||
223 | .driver = { | ||
224 | .name = "haswell-audio", | ||
225 | .owner = THIS_MODULE, | ||
226 | }, | ||
227 | }; | ||
228 | |||
229 | module_platform_driver(haswell_audio) | ||
230 | |||
231 | /* Module information */ | ||
232 | MODULE_AUTHOR("Liam Girdwood, Xingchao Wang"); | ||
233 | MODULE_DESCRIPTION("Intel SST Audio for Haswell Lynxpoint"); | ||
234 | MODULE_LICENSE("GPL v2"); | ||
235 | MODULE_ALIAS("platform:haswell-audio"); | ||
diff --git a/sound/soc/intel/mfld_machine.c b/sound/soc/intel/mfld_machine.c index d3d4c32434f7..031d78783fc8 100644 --- a/sound/soc/intel/mfld_machine.c +++ b/sound/soc/intel/mfld_machine.c | |||
@@ -53,6 +53,7 @@ enum soc_mic_bias_zones { | |||
53 | 53 | ||
54 | static unsigned int hs_switch; | 54 | static unsigned int hs_switch; |
55 | static unsigned int lo_dac; | 55 | static unsigned int lo_dac; |
56 | static struct snd_soc_codec *mfld_codec; | ||
56 | 57 | ||
57 | struct mfld_mc_private { | 58 | struct mfld_mc_private { |
58 | void __iomem *int_base; | 59 | void __iomem *int_base; |
@@ -100,40 +101,47 @@ static int headset_get_switch(struct snd_kcontrol *kcontrol, | |||
100 | static int headset_set_switch(struct snd_kcontrol *kcontrol, | 101 | static int headset_set_switch(struct snd_kcontrol *kcontrol, |
101 | struct snd_ctl_elem_value *ucontrol) | 102 | struct snd_ctl_elem_value *ucontrol) |
102 | { | 103 | { |
103 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 104 | struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); |
105 | struct snd_soc_dapm_context *dapm = &card->dapm; | ||
104 | 106 | ||
105 | if (ucontrol->value.integer.value[0] == hs_switch) | 107 | if (ucontrol->value.integer.value[0] == hs_switch) |
106 | return 0; | 108 | return 0; |
107 | 109 | ||
110 | snd_soc_dapm_mutex_lock(dapm); | ||
111 | |||
108 | if (ucontrol->value.integer.value[0]) { | 112 | if (ucontrol->value.integer.value[0]) { |
109 | pr_debug("hs_set HS path\n"); | 113 | pr_debug("hs_set HS path\n"); |
110 | snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); | 114 | snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones"); |
111 | snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); | 115 | snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); |
112 | } else { | 116 | } else { |
113 | pr_debug("hs_set EP path\n"); | 117 | pr_debug("hs_set EP path\n"); |
114 | snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); | 118 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); |
115 | snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); | 119 | snd_soc_dapm_enable_pin_unlocked(dapm, "EPOUT"); |
116 | } | 120 | } |
117 | snd_soc_dapm_sync(&codec->dapm); | 121 | |
122 | snd_soc_dapm_sync_unlocked(dapm); | ||
123 | |||
124 | snd_soc_dapm_mutex_unlock(dapm); | ||
125 | |||
118 | hs_switch = ucontrol->value.integer.value[0]; | 126 | hs_switch = ucontrol->value.integer.value[0]; |
119 | 127 | ||
120 | return 0; | 128 | return 0; |
121 | } | 129 | } |
122 | 130 | ||
123 | static void lo_enable_out_pins(struct snd_soc_codec *codec) | 131 | static void lo_enable_out_pins(struct snd_soc_dapm_context *dapm) |
124 | { | 132 | { |
125 | snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTL"); | 133 | snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTL"); |
126 | snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTR"); | 134 | snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTR"); |
127 | snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTL"); | 135 | snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTL"); |
128 | snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTR"); | 136 | snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTR"); |
129 | snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT"); | 137 | snd_soc_dapm_enable_pin_unlocked(dapm, "VIB1OUT"); |
130 | snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT"); | 138 | snd_soc_dapm_enable_pin_unlocked(dapm, "VIB2OUT"); |
131 | if (hs_switch) { | 139 | if (hs_switch) { |
132 | snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); | 140 | snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones"); |
133 | snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); | 141 | snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); |
134 | } else { | 142 | } else { |
135 | snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); | 143 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); |
136 | snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); | 144 | snd_soc_dapm_enable_pin_unlocked(dapm, "EPOUT"); |
137 | } | 145 | } |
138 | } | 146 | } |
139 | 147 | ||
@@ -147,45 +155,53 @@ static int lo_get_switch(struct snd_kcontrol *kcontrol, | |||
147 | static int lo_set_switch(struct snd_kcontrol *kcontrol, | 155 | static int lo_set_switch(struct snd_kcontrol *kcontrol, |
148 | struct snd_ctl_elem_value *ucontrol) | 156 | struct snd_ctl_elem_value *ucontrol) |
149 | { | 157 | { |
150 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 158 | struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); |
159 | struct snd_soc_dapm_context *dapm = &card->dapm; | ||
151 | 160 | ||
152 | if (ucontrol->value.integer.value[0] == lo_dac) | 161 | if (ucontrol->value.integer.value[0] == lo_dac) |
153 | return 0; | 162 | return 0; |
154 | 163 | ||
164 | snd_soc_dapm_mutex_lock(dapm); | ||
165 | |||
155 | /* we dont want to work with last state of lineout so just enable all | 166 | /* we dont want to work with last state of lineout so just enable all |
156 | * pins and then disable pins not required | 167 | * pins and then disable pins not required |
157 | */ | 168 | */ |
158 | lo_enable_out_pins(codec); | 169 | lo_enable_out_pins(dapm); |
170 | |||
159 | switch (ucontrol->value.integer.value[0]) { | 171 | switch (ucontrol->value.integer.value[0]) { |
160 | case 0: | 172 | case 0: |
161 | pr_debug("set vibra path\n"); | 173 | pr_debug("set vibra path\n"); |
162 | snd_soc_dapm_disable_pin(&codec->dapm, "VIB1OUT"); | 174 | snd_soc_dapm_disable_pin_unlocked(dapm, "VIB1OUT"); |
163 | snd_soc_dapm_disable_pin(&codec->dapm, "VIB2OUT"); | 175 | snd_soc_dapm_disable_pin_unlocked(dapm, "VIB2OUT"); |
164 | snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0); | 176 | snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0); |
165 | break; | 177 | break; |
166 | 178 | ||
167 | case 1: | 179 | case 1: |
168 | pr_debug("set hs path\n"); | 180 | pr_debug("set hs path\n"); |
169 | snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); | 181 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); |
170 | snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); | 182 | snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); |
171 | snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22); | 183 | snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0x22); |
172 | break; | 184 | break; |
173 | 185 | ||
174 | case 2: | 186 | case 2: |
175 | pr_debug("set spkr path\n"); | 187 | pr_debug("set spkr path\n"); |
176 | snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTL"); | 188 | snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTL"); |
177 | snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTR"); | 189 | snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTR"); |
178 | snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44); | 190 | snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0x44); |
179 | break; | 191 | break; |
180 | 192 | ||
181 | case 3: | 193 | case 3: |
182 | pr_debug("set null path\n"); | 194 | pr_debug("set null path\n"); |
183 | snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTL"); | 195 | snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTL"); |
184 | snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTR"); | 196 | snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTR"); |
185 | snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66); | 197 | snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0x66); |
186 | break; | 198 | break; |
187 | } | 199 | } |
188 | snd_soc_dapm_sync(&codec->dapm); | 200 | |
201 | snd_soc_dapm_sync_unlocked(dapm); | ||
202 | |||
203 | snd_soc_dapm_mutex_unlock(dapm); | ||
204 | |||
189 | lo_dac = ucontrol->value.integer.value[0]; | 205 | lo_dac = ucontrol->value.integer.value[0]; |
190 | return 0; | 206 | return 0; |
191 | } | 207 | } |
@@ -221,26 +237,11 @@ static void mfld_jack_check(unsigned int intr_status) | |||
221 | 237 | ||
222 | static int mfld_init(struct snd_soc_pcm_runtime *runtime) | 238 | static int mfld_init(struct snd_soc_pcm_runtime *runtime) |
223 | { | 239 | { |
224 | struct snd_soc_codec *codec = runtime->codec; | 240 | struct snd_soc_dapm_context *dapm = &runtime->card->dapm; |
225 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
226 | int ret_val; | 241 | int ret_val; |
227 | 242 | ||
228 | /* Add jack sense widgets */ | 243 | mfld_codec = runtime->codec; |
229 | snd_soc_dapm_new_controls(dapm, mfld_widgets, ARRAY_SIZE(mfld_widgets)); | ||
230 | |||
231 | /* Set up the map */ | ||
232 | snd_soc_dapm_add_routes(dapm, mfld_map, ARRAY_SIZE(mfld_map)); | ||
233 | 244 | ||
234 | /* always connected */ | ||
235 | snd_soc_dapm_enable_pin(dapm, "Headphones"); | ||
236 | snd_soc_dapm_enable_pin(dapm, "Mic"); | ||
237 | |||
238 | ret_val = snd_soc_add_codec_controls(codec, mfld_snd_controls, | ||
239 | ARRAY_SIZE(mfld_snd_controls)); | ||
240 | if (ret_val) { | ||
241 | pr_err("soc_add_controls failed %d", ret_val); | ||
242 | return ret_val; | ||
243 | } | ||
244 | /* default is earpiece pin, userspace sets it explcitly */ | 245 | /* default is earpiece pin, userspace sets it explcitly */ |
245 | snd_soc_dapm_disable_pin(dapm, "Headphones"); | 246 | snd_soc_dapm_disable_pin(dapm, "Headphones"); |
246 | /* default is lineout NC, userspace sets it explcitly */ | 247 | /* default is lineout NC, userspace sets it explcitly */ |
@@ -253,7 +254,7 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime) | |||
253 | snd_soc_dapm_disable_pin(dapm, "LINEINR"); | 254 | snd_soc_dapm_disable_pin(dapm, "LINEINR"); |
254 | 255 | ||
255 | /* Headset and button jack detection */ | 256 | /* Headset and button jack detection */ |
256 | ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack", | 257 | ret_val = snd_soc_jack_new(mfld_codec, "Intel(R) MID Audio Jack", |
257 | SND_JACK_HEADSET | SND_JACK_BTN_0 | | 258 | SND_JACK_HEADSET | SND_JACK_BTN_0 | |
258 | SND_JACK_BTN_1, &mfld_jack); | 259 | SND_JACK_BTN_1, &mfld_jack); |
259 | if (ret_val) { | 260 | if (ret_val) { |
@@ -335,6 +336,13 @@ static struct snd_soc_card snd_soc_card_mfld = { | |||
335 | .owner = THIS_MODULE, | 336 | .owner = THIS_MODULE, |
336 | .dai_link = mfld_msic_dailink, | 337 | .dai_link = mfld_msic_dailink, |
337 | .num_links = ARRAY_SIZE(mfld_msic_dailink), | 338 | .num_links = ARRAY_SIZE(mfld_msic_dailink), |
339 | |||
340 | .controls = mfld_snd_controls, | ||
341 | .num_controls = ARRAY_SIZE(mfld_snd_controls), | ||
342 | .dapm_widgets = mfld_widgets, | ||
343 | .num_dapm_widgets = ARRAY_SIZE(mfld_widgets), | ||
344 | .dapm_routes = mfld_map, | ||
345 | .num_dapm_routes = ARRAY_SIZE(mfld_map), | ||
338 | }; | 346 | }; |
339 | 347 | ||
340 | static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev) | 348 | static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev) |
diff --git a/sound/soc/intel/sst-acpi.c b/sound/soc/intel/sst-acpi.c new file mode 100644 index 000000000000..5d06eecb6198 --- /dev/null +++ b/sound/soc/intel/sst-acpi.c | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * Intel SST loader on ACPI systems | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/acpi.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/firmware.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | #include "sst-dsp.h" | ||
24 | |||
25 | #define SST_LPT_DSP_DMA_ADDR_OFFSET 0x0F0000 | ||
26 | #define SST_WPT_DSP_DMA_ADDR_OFFSET 0x0FE000 | ||
27 | #define SST_LPT_DSP_DMA_SIZE (1024 - 1) | ||
28 | |||
29 | /* Descriptor for SST ASoC machine driver */ | ||
30 | struct sst_acpi_mach { | ||
31 | /* ACPI ID for the matching machine driver. Audio codec for instance */ | ||
32 | const u8 id[ACPI_ID_LEN]; | ||
33 | /* machine driver name */ | ||
34 | const char *drv_name; | ||
35 | /* firmware file name */ | ||
36 | const char *fw_filename; | ||
37 | }; | ||
38 | |||
39 | /* Descriptor for setting up SST platform data */ | ||
40 | struct sst_acpi_desc { | ||
41 | const char *drv_name; | ||
42 | struct sst_acpi_mach *machines; | ||
43 | /* Platform resource indexes. Must set to -1 if not used */ | ||
44 | int resindex_lpe_base; | ||
45 | int resindex_pcicfg_base; | ||
46 | int resindex_fw_base; | ||
47 | int irqindex_host_ipc; | ||
48 | int resindex_dma_base; | ||
49 | /* Unique number identifying the SST core on platform */ | ||
50 | int sst_id; | ||
51 | /* DMA only valid when resindex_dma_base != -1*/ | ||
52 | int dma_engine; | ||
53 | int dma_size; | ||
54 | }; | ||
55 | |||
56 | struct sst_acpi_priv { | ||
57 | struct platform_device *pdev_mach; | ||
58 | struct platform_device *pdev_pcm; | ||
59 | struct sst_pdata sst_pdata; | ||
60 | struct sst_acpi_desc *desc; | ||
61 | struct sst_acpi_mach *mach; | ||
62 | }; | ||
63 | |||
64 | static void sst_acpi_fw_cb(const struct firmware *fw, void *context) | ||
65 | { | ||
66 | struct platform_device *pdev = context; | ||
67 | struct device *dev = &pdev->dev; | ||
68 | struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev); | ||
69 | struct sst_pdata *sst_pdata = &sst_acpi->sst_pdata; | ||
70 | struct sst_acpi_desc *desc = sst_acpi->desc; | ||
71 | struct sst_acpi_mach *mach = sst_acpi->mach; | ||
72 | |||
73 | sst_pdata->fw = fw; | ||
74 | if (!fw) { | ||
75 | dev_err(dev, "Cannot load firmware %s\n", mach->fw_filename); | ||
76 | return; | ||
77 | } | ||
78 | |||
79 | /* register PCM and DAI driver */ | ||
80 | sst_acpi->pdev_pcm = | ||
81 | platform_device_register_data(dev, desc->drv_name, -1, | ||
82 | sst_pdata, sizeof(*sst_pdata)); | ||
83 | if (IS_ERR(sst_acpi->pdev_pcm)) { | ||
84 | dev_err(dev, "Cannot register device %s. Error %d\n", | ||
85 | desc->drv_name, (int)PTR_ERR(sst_acpi->pdev_pcm)); | ||
86 | } | ||
87 | |||
88 | return; | ||
89 | } | ||
90 | |||
91 | static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level, | ||
92 | void *context, void **ret) | ||
93 | { | ||
94 | *(bool *)context = true; | ||
95 | return AE_OK; | ||
96 | } | ||
97 | |||
98 | static struct sst_acpi_mach *sst_acpi_find_machine( | ||
99 | struct sst_acpi_mach *machines) | ||
100 | { | ||
101 | struct sst_acpi_mach *mach; | ||
102 | bool found = false; | ||
103 | |||
104 | for (mach = machines; mach->id[0]; mach++) | ||
105 | if (ACPI_SUCCESS(acpi_get_devices(mach->id, | ||
106 | sst_acpi_mach_match, | ||
107 | &found, NULL)) && found) | ||
108 | return mach; | ||
109 | |||
110 | return NULL; | ||
111 | } | ||
112 | |||
113 | static int sst_acpi_probe(struct platform_device *pdev) | ||
114 | { | ||
115 | const struct acpi_device_id *id; | ||
116 | struct device *dev = &pdev->dev; | ||
117 | struct sst_acpi_priv *sst_acpi; | ||
118 | struct sst_pdata *sst_pdata; | ||
119 | struct sst_acpi_mach *mach; | ||
120 | struct sst_acpi_desc *desc; | ||
121 | struct resource *mmio; | ||
122 | int ret = 0; | ||
123 | |||
124 | sst_acpi = devm_kzalloc(dev, sizeof(*sst_acpi), GFP_KERNEL); | ||
125 | if (sst_acpi == NULL) | ||
126 | return -ENOMEM; | ||
127 | |||
128 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
129 | if (!id) | ||
130 | return -ENODEV; | ||
131 | |||
132 | desc = (struct sst_acpi_desc *)id->driver_data; | ||
133 | mach = sst_acpi_find_machine(desc->machines); | ||
134 | if (mach == NULL) { | ||
135 | dev_err(dev, "No matching ASoC machine driver found\n"); | ||
136 | return -ENODEV; | ||
137 | } | ||
138 | |||
139 | sst_pdata = &sst_acpi->sst_pdata; | ||
140 | sst_pdata->id = desc->sst_id; | ||
141 | sst_acpi->desc = desc; | ||
142 | sst_acpi->mach = mach; | ||
143 | |||
144 | if (desc->resindex_dma_base >= 0) { | ||
145 | sst_pdata->dma_engine = desc->dma_engine; | ||
146 | sst_pdata->dma_base = desc->resindex_dma_base; | ||
147 | sst_pdata->dma_size = desc->dma_size; | ||
148 | } | ||
149 | |||
150 | if (desc->irqindex_host_ipc >= 0) | ||
151 | sst_pdata->irq = platform_get_irq(pdev, desc->irqindex_host_ipc); | ||
152 | |||
153 | if (desc->resindex_lpe_base >= 0) { | ||
154 | mmio = platform_get_resource(pdev, IORESOURCE_MEM, | ||
155 | desc->resindex_lpe_base); | ||
156 | if (mmio) { | ||
157 | sst_pdata->lpe_base = mmio->start; | ||
158 | sst_pdata->lpe_size = resource_size(mmio); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | if (desc->resindex_pcicfg_base >= 0) { | ||
163 | mmio = platform_get_resource(pdev, IORESOURCE_MEM, | ||
164 | desc->resindex_pcicfg_base); | ||
165 | if (mmio) { | ||
166 | sst_pdata->pcicfg_base = mmio->start; | ||
167 | sst_pdata->pcicfg_size = resource_size(mmio); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | if (desc->resindex_fw_base >= 0) { | ||
172 | mmio = platform_get_resource(pdev, IORESOURCE_MEM, | ||
173 | desc->resindex_fw_base); | ||
174 | if (mmio) { | ||
175 | sst_pdata->fw_base = mmio->start; | ||
176 | sst_pdata->fw_size = resource_size(mmio); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | platform_set_drvdata(pdev, sst_acpi); | ||
181 | |||
182 | /* register machine driver */ | ||
183 | sst_acpi->pdev_mach = | ||
184 | platform_device_register_data(dev, mach->drv_name, -1, | ||
185 | sst_pdata, sizeof(*sst_pdata)); | ||
186 | if (IS_ERR(sst_acpi->pdev_mach)) | ||
187 | return PTR_ERR(sst_acpi->pdev_mach); | ||
188 | |||
189 | /* continue SST probing after firmware is loaded */ | ||
190 | ret = request_firmware_nowait(THIS_MODULE, true, mach->fw_filename, | ||
191 | dev, GFP_KERNEL, pdev, sst_acpi_fw_cb); | ||
192 | if (ret) | ||
193 | platform_device_unregister(sst_acpi->pdev_mach); | ||
194 | |||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | static int sst_acpi_remove(struct platform_device *pdev) | ||
199 | { | ||
200 | struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev); | ||
201 | struct sst_pdata *sst_pdata = &sst_acpi->sst_pdata; | ||
202 | |||
203 | platform_device_unregister(sst_acpi->pdev_mach); | ||
204 | if (!IS_ERR_OR_NULL(sst_acpi->pdev_pcm)) | ||
205 | platform_device_unregister(sst_acpi->pdev_pcm); | ||
206 | release_firmware(sst_pdata->fw); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static struct sst_acpi_mach haswell_machines[] = { | ||
212 | { "INT33CA", "haswell-audio", "intel/IntcSST1.bin" }, | ||
213 | {} | ||
214 | }; | ||
215 | |||
216 | static struct sst_acpi_desc sst_acpi_haswell_desc = { | ||
217 | .drv_name = "haswell-pcm-audio", | ||
218 | .machines = haswell_machines, | ||
219 | .resindex_lpe_base = 0, | ||
220 | .resindex_pcicfg_base = 1, | ||
221 | .resindex_fw_base = -1, | ||
222 | .irqindex_host_ipc = 0, | ||
223 | .sst_id = SST_DEV_ID_LYNX_POINT, | ||
224 | .dma_engine = SST_DMA_TYPE_DW, | ||
225 | .resindex_dma_base = SST_LPT_DSP_DMA_ADDR_OFFSET, | ||
226 | .dma_size = SST_LPT_DSP_DMA_SIZE, | ||
227 | }; | ||
228 | |||
229 | static struct sst_acpi_mach broadwell_machines[] = { | ||
230 | { "INT343A", "broadwell-audio", "intel/IntcSST2.bin" }, | ||
231 | {} | ||
232 | }; | ||
233 | |||
234 | static struct sst_acpi_desc sst_acpi_broadwell_desc = { | ||
235 | .drv_name = "haswell-pcm-audio", | ||
236 | .machines = broadwell_machines, | ||
237 | .resindex_lpe_base = 0, | ||
238 | .resindex_pcicfg_base = 1, | ||
239 | .resindex_fw_base = -1, | ||
240 | .irqindex_host_ipc = 0, | ||
241 | .sst_id = SST_DEV_ID_WILDCAT_POINT, | ||
242 | .dma_engine = SST_DMA_TYPE_DW, | ||
243 | .resindex_dma_base = SST_WPT_DSP_DMA_ADDR_OFFSET, | ||
244 | .dma_size = SST_LPT_DSP_DMA_SIZE, | ||
245 | }; | ||
246 | |||
247 | static struct sst_acpi_mach baytrail_machines[] = { | ||
248 | { "10EC5640", "byt-rt5640", "intel/fw_sst_0f28.bin-i2s_master" }, | ||
249 | {} | ||
250 | }; | ||
251 | |||
252 | static struct sst_acpi_desc sst_acpi_baytrail_desc = { | ||
253 | .drv_name = "baytrail-pcm-audio", | ||
254 | .machines = baytrail_machines, | ||
255 | .resindex_lpe_base = 0, | ||
256 | .resindex_pcicfg_base = 1, | ||
257 | .resindex_fw_base = 2, | ||
258 | .irqindex_host_ipc = 5, | ||
259 | .sst_id = SST_DEV_ID_BYT, | ||
260 | .resindex_dma_base = -1, | ||
261 | }; | ||
262 | |||
263 | static struct acpi_device_id sst_acpi_match[] = { | ||
264 | { "INT33C8", (unsigned long)&sst_acpi_haswell_desc }, | ||
265 | { "INT3438", (unsigned long)&sst_acpi_broadwell_desc }, | ||
266 | { "80860F28", (unsigned long)&sst_acpi_baytrail_desc }, | ||
267 | { } | ||
268 | }; | ||
269 | MODULE_DEVICE_TABLE(acpi, sst_acpi_match); | ||
270 | |||
271 | static struct platform_driver sst_acpi_driver = { | ||
272 | .probe = sst_acpi_probe, | ||
273 | .remove = sst_acpi_remove, | ||
274 | .driver = { | ||
275 | .name = "sst-acpi", | ||
276 | .owner = THIS_MODULE, | ||
277 | .acpi_match_table = ACPI_PTR(sst_acpi_match), | ||
278 | }, | ||
279 | }; | ||
280 | module_platform_driver(sst_acpi_driver); | ||
281 | |||
282 | MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@linux.intel.com>"); | ||
283 | MODULE_DESCRIPTION("Intel SST loader on ACPI systems"); | ||
284 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/intel/sst-baytrail-dsp.c b/sound/soc/intel/sst-baytrail-dsp.c new file mode 100644 index 000000000000..a50bf7fc0e3a --- /dev/null +++ b/sound/soc/intel/sst-baytrail-dsp.c | |||
@@ -0,0 +1,372 @@ | |||
1 | /* | ||
2 | * Intel Baytrail SST DSP driver | ||
3 | * Copyright (c) 2014, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/delay.h> | ||
16 | #include <linux/fs.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/dma-mapping.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/firmware.h> | ||
24 | |||
25 | #include "sst-dsp.h" | ||
26 | #include "sst-dsp-priv.h" | ||
27 | #include "sst-baytrail-ipc.h" | ||
28 | |||
29 | #define SST_BYT_FW_SIGNATURE_SIZE 4 | ||
30 | #define SST_BYT_FW_SIGN "$SST" | ||
31 | |||
32 | #define SST_BYT_IRAM_OFFSET 0xC0000 | ||
33 | #define SST_BYT_DRAM_OFFSET 0x100000 | ||
34 | #define SST_BYT_SHIM_OFFSET 0x140000 | ||
35 | |||
36 | enum sst_ram_type { | ||
37 | SST_BYT_IRAM = 1, | ||
38 | SST_BYT_DRAM = 2, | ||
39 | SST_BYT_CACHE = 3, | ||
40 | }; | ||
41 | |||
42 | struct dma_block_info { | ||
43 | enum sst_ram_type type; /* IRAM/DRAM */ | ||
44 | u32 size; /* Bytes */ | ||
45 | u32 ram_offset; /* Offset in I/DRAM */ | ||
46 | u32 rsvd; /* Reserved field */ | ||
47 | }; | ||
48 | |||
49 | struct fw_header { | ||
50 | unsigned char signature[SST_BYT_FW_SIGNATURE_SIZE]; | ||
51 | u32 file_size; /* size of fw minus this header */ | ||
52 | u32 modules; /* # of modules */ | ||
53 | u32 file_format; /* version of header format */ | ||
54 | u32 reserved[4]; | ||
55 | }; | ||
56 | |||
57 | struct sst_byt_fw_module_header { | ||
58 | unsigned char signature[SST_BYT_FW_SIGNATURE_SIZE]; | ||
59 | u32 mod_size; /* size of module */ | ||
60 | u32 blocks; /* # of blocks */ | ||
61 | u32 type; /* codec type, pp lib */ | ||
62 | u32 entry_point; | ||
63 | }; | ||
64 | |||
65 | static int sst_byt_parse_module(struct sst_dsp *dsp, struct sst_fw *fw, | ||
66 | struct sst_byt_fw_module_header *module) | ||
67 | { | ||
68 | struct dma_block_info *block; | ||
69 | struct sst_module *mod; | ||
70 | struct sst_module_data block_data; | ||
71 | struct sst_module_template template; | ||
72 | int count; | ||
73 | |||
74 | memset(&template, 0, sizeof(template)); | ||
75 | template.id = module->type; | ||
76 | template.entry = module->entry_point; | ||
77 | template.p.type = SST_MEM_DRAM; | ||
78 | template.p.data_type = SST_DATA_P; | ||
79 | template.s.type = SST_MEM_DRAM; | ||
80 | template.s.data_type = SST_DATA_S; | ||
81 | |||
82 | mod = sst_module_new(fw, &template, NULL); | ||
83 | if (mod == NULL) | ||
84 | return -ENOMEM; | ||
85 | |||
86 | block = (void *)module + sizeof(*module); | ||
87 | |||
88 | for (count = 0; count < module->blocks; count++) { | ||
89 | |||
90 | if (block->size <= 0) { | ||
91 | dev_err(dsp->dev, "block %d size invalid\n", count); | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | |||
95 | switch (block->type) { | ||
96 | case SST_BYT_IRAM: | ||
97 | block_data.offset = block->ram_offset + | ||
98 | dsp->addr.iram_offset; | ||
99 | block_data.type = SST_MEM_IRAM; | ||
100 | break; | ||
101 | case SST_BYT_DRAM: | ||
102 | block_data.offset = block->ram_offset + | ||
103 | dsp->addr.dram_offset; | ||
104 | block_data.type = SST_MEM_DRAM; | ||
105 | break; | ||
106 | case SST_BYT_CACHE: | ||
107 | block_data.offset = block->ram_offset + | ||
108 | (dsp->addr.fw_ext - dsp->addr.lpe); | ||
109 | block_data.type = SST_MEM_CACHE; | ||
110 | break; | ||
111 | default: | ||
112 | dev_err(dsp->dev, "wrong ram type 0x%x in block0x%x\n", | ||
113 | block->type, count); | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | |||
117 | block_data.size = block->size; | ||
118 | block_data.data_type = SST_DATA_M; | ||
119 | block_data.data = (void *)block + sizeof(*block); | ||
120 | |||
121 | sst_module_insert_fixed_block(mod, &block_data); | ||
122 | |||
123 | block = (void *)block + sizeof(*block) + block->size; | ||
124 | } | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static int sst_byt_parse_fw_image(struct sst_fw *sst_fw) | ||
129 | { | ||
130 | struct fw_header *header; | ||
131 | struct sst_byt_fw_module_header *module; | ||
132 | struct sst_dsp *dsp = sst_fw->dsp; | ||
133 | int ret, count; | ||
134 | |||
135 | /* Read the header information from the data pointer */ | ||
136 | header = (struct fw_header *)sst_fw->dma_buf; | ||
137 | |||
138 | /* verify FW */ | ||
139 | if ((strncmp(header->signature, SST_BYT_FW_SIGN, 4) != 0) || | ||
140 | (sst_fw->size != header->file_size + sizeof(*header))) { | ||
141 | /* Invalid FW signature */ | ||
142 | dev_err(dsp->dev, "Invalid FW sign/filesize mismatch\n"); | ||
143 | return -EINVAL; | ||
144 | } | ||
145 | |||
146 | dev_dbg(dsp->dev, | ||
147 | "header sign=%4s size=0x%x modules=0x%x fmt=0x%x size=%zu\n", | ||
148 | header->signature, header->file_size, header->modules, | ||
149 | header->file_format, sizeof(*header)); | ||
150 | |||
151 | module = (void *)sst_fw->dma_buf + sizeof(*header); | ||
152 | for (count = 0; count < header->modules; count++) { | ||
153 | /* module */ | ||
154 | ret = sst_byt_parse_module(dsp, sst_fw, module); | ||
155 | if (ret < 0) { | ||
156 | dev_err(dsp->dev, "invalid module %d\n", count); | ||
157 | return ret; | ||
158 | } | ||
159 | module = (void *)module + sizeof(*module) + module->mod_size; | ||
160 | } | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static void sst_byt_dump_shim(struct sst_dsp *sst) | ||
166 | { | ||
167 | int i; | ||
168 | u64 reg; | ||
169 | |||
170 | for (i = 0; i <= 0xF0; i += 8) { | ||
171 | reg = sst_dsp_shim_read64_unlocked(sst, i); | ||
172 | if (reg) | ||
173 | dev_dbg(sst->dev, "shim 0x%2.2x value 0x%16.16llx\n", | ||
174 | i, reg); | ||
175 | } | ||
176 | |||
177 | for (i = 0x00; i <= 0xff; i += 4) { | ||
178 | reg = readl(sst->addr.pci_cfg + i); | ||
179 | if (reg) | ||
180 | dev_dbg(sst->dev, "pci 0x%2.2x value 0x%8.8x\n", | ||
181 | i, (u32)reg); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | static irqreturn_t sst_byt_irq(int irq, void *context) | ||
186 | { | ||
187 | struct sst_dsp *sst = (struct sst_dsp *) context; | ||
188 | u64 isrx; | ||
189 | irqreturn_t ret = IRQ_NONE; | ||
190 | |||
191 | spin_lock(&sst->spinlock); | ||
192 | |||
193 | isrx = sst_dsp_shim_read64_unlocked(sst, SST_ISRX); | ||
194 | if (isrx & SST_ISRX_DONE) { | ||
195 | /* ADSP has processed the message request from IA */ | ||
196 | sst_dsp_shim_update_bits64_unlocked(sst, SST_IPCX, | ||
197 | SST_BYT_IPCX_DONE, 0); | ||
198 | ret = IRQ_WAKE_THREAD; | ||
199 | } | ||
200 | if (isrx & SST_BYT_ISRX_REQUEST) { | ||
201 | /* mask message request from ADSP and do processing later */ | ||
202 | sst_dsp_shim_update_bits64_unlocked(sst, SST_IMRX, | ||
203 | SST_BYT_IMRX_REQUEST, | ||
204 | SST_BYT_IMRX_REQUEST); | ||
205 | ret = IRQ_WAKE_THREAD; | ||
206 | } | ||
207 | |||
208 | spin_unlock(&sst->spinlock); | ||
209 | |||
210 | return ret; | ||
211 | } | ||
212 | |||
213 | static void sst_byt_boot(struct sst_dsp *sst) | ||
214 | { | ||
215 | int tries = 10; | ||
216 | |||
217 | /* release stall and wait to unstall */ | ||
218 | sst_dsp_shim_update_bits64(sst, SST_CSR, SST_BYT_CSR_STALL, 0x0); | ||
219 | while (tries--) { | ||
220 | if (!(sst_dsp_shim_read64(sst, SST_CSR) & | ||
221 | SST_BYT_CSR_PWAITMODE)) | ||
222 | break; | ||
223 | msleep(100); | ||
224 | } | ||
225 | if (tries < 0) { | ||
226 | dev_err(sst->dev, "unable to start DSP\n"); | ||
227 | sst_byt_dump_shim(sst); | ||
228 | } | ||
229 | } | ||
230 | |||
231 | static void sst_byt_reset(struct sst_dsp *sst) | ||
232 | { | ||
233 | /* put DSP into reset, set reset vector and stall */ | ||
234 | sst_dsp_shim_update_bits64(sst, SST_CSR, | ||
235 | SST_BYT_CSR_RST | SST_BYT_CSR_VECTOR_SEL | SST_BYT_CSR_STALL, | ||
236 | SST_BYT_CSR_RST | SST_BYT_CSR_VECTOR_SEL | SST_BYT_CSR_STALL); | ||
237 | |||
238 | udelay(10); | ||
239 | |||
240 | /* take DSP out of reset and keep stalled for FW loading */ | ||
241 | sst_dsp_shim_update_bits64(sst, SST_CSR, SST_BYT_CSR_RST, 0); | ||
242 | } | ||
243 | |||
244 | struct sst_adsp_memregion { | ||
245 | u32 start; | ||
246 | u32 end; | ||
247 | int blocks; | ||
248 | enum sst_mem_type type; | ||
249 | }; | ||
250 | |||
251 | /* BYT test stuff */ | ||
252 | static const struct sst_adsp_memregion byt_region[] = { | ||
253 | {0xC0000, 0x100000, 8, SST_MEM_IRAM}, /* I-SRAM - 8 * 32kB */ | ||
254 | {0x100000, 0x140000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ | ||
255 | }; | ||
256 | |||
257 | static int sst_byt_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata) | ||
258 | { | ||
259 | sst->addr.lpe_base = pdata->lpe_base; | ||
260 | sst->addr.lpe = ioremap(pdata->lpe_base, pdata->lpe_size); | ||
261 | if (!sst->addr.lpe) | ||
262 | return -ENODEV; | ||
263 | |||
264 | /* ADSP PCI MMIO config space */ | ||
265 | sst->addr.pci_cfg = ioremap(pdata->pcicfg_base, pdata->pcicfg_size); | ||
266 | if (!sst->addr.pci_cfg) { | ||
267 | iounmap(sst->addr.lpe); | ||
268 | return -ENODEV; | ||
269 | } | ||
270 | |||
271 | /* SST Extended FW allocation */ | ||
272 | sst->addr.fw_ext = ioremap(pdata->fw_base, pdata->fw_size); | ||
273 | if (!sst->addr.fw_ext) { | ||
274 | iounmap(sst->addr.pci_cfg); | ||
275 | iounmap(sst->addr.lpe); | ||
276 | return -ENODEV; | ||
277 | } | ||
278 | |||
279 | /* SST Shim */ | ||
280 | sst->addr.shim = sst->addr.lpe + sst->addr.shim_offset; | ||
281 | |||
282 | sst_dsp_mailbox_init(sst, SST_BYT_MAILBOX_OFFSET + 0x204, | ||
283 | SST_BYT_IPC_MAX_PAYLOAD_SIZE, | ||
284 | SST_BYT_MAILBOX_OFFSET, | ||
285 | SST_BYT_IPC_MAX_PAYLOAD_SIZE); | ||
286 | |||
287 | sst->irq = pdata->irq; | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int sst_byt_init(struct sst_dsp *sst, struct sst_pdata *pdata) | ||
293 | { | ||
294 | const struct sst_adsp_memregion *region; | ||
295 | struct device *dev; | ||
296 | int ret = -ENODEV, i, j, region_count; | ||
297 | u32 offset, size; | ||
298 | |||
299 | dev = sst->dev; | ||
300 | |||
301 | switch (sst->id) { | ||
302 | case SST_DEV_ID_BYT: | ||
303 | region = byt_region; | ||
304 | region_count = ARRAY_SIZE(byt_region); | ||
305 | sst->addr.iram_offset = SST_BYT_IRAM_OFFSET; | ||
306 | sst->addr.dram_offset = SST_BYT_DRAM_OFFSET; | ||
307 | sst->addr.shim_offset = SST_BYT_SHIM_OFFSET; | ||
308 | break; | ||
309 | default: | ||
310 | dev_err(dev, "failed to get mem resources\n"); | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | ret = sst_byt_resource_map(sst, pdata); | ||
315 | if (ret < 0) { | ||
316 | dev_err(dev, "failed to map resources\n"); | ||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | /* | ||
321 | * save the physical address of extended firmware block in the first | ||
322 | * 4 bytes of the mailbox | ||
323 | */ | ||
324 | memcpy_toio(sst->addr.lpe + SST_BYT_MAILBOX_OFFSET, | ||
325 | &pdata->fw_base, sizeof(u32)); | ||
326 | |||
327 | ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); | ||
328 | if (ret) | ||
329 | return ret; | ||
330 | |||
331 | /* enable Interrupt from both sides */ | ||
332 | sst_dsp_shim_update_bits64(sst, SST_IMRX, 0x3, 0x0); | ||
333 | sst_dsp_shim_update_bits64(sst, SST_IMRD, 0x3, 0x0); | ||
334 | |||
335 | /* register DSP memory blocks - ideally we should get this from ACPI */ | ||
336 | for (i = 0; i < region_count; i++) { | ||
337 | offset = region[i].start; | ||
338 | size = (region[i].end - region[i].start) / region[i].blocks; | ||
339 | |||
340 | /* register individual memory blocks */ | ||
341 | for (j = 0; j < region[i].blocks; j++) { | ||
342 | sst_mem_block_register(sst, offset, size, | ||
343 | region[i].type, NULL, j, sst); | ||
344 | offset += size; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static void sst_byt_free(struct sst_dsp *sst) | ||
352 | { | ||
353 | sst_mem_block_unregister_all(sst); | ||
354 | iounmap(sst->addr.lpe); | ||
355 | iounmap(sst->addr.pci_cfg); | ||
356 | iounmap(sst->addr.fw_ext); | ||
357 | } | ||
358 | |||
359 | struct sst_ops sst_byt_ops = { | ||
360 | .reset = sst_byt_reset, | ||
361 | .boot = sst_byt_boot, | ||
362 | .write = sst_shim32_write, | ||
363 | .read = sst_shim32_read, | ||
364 | .write64 = sst_shim32_write64, | ||
365 | .read64 = sst_shim32_read64, | ||
366 | .ram_read = sst_memcpy_fromio_32, | ||
367 | .ram_write = sst_memcpy_toio_32, | ||
368 | .irq_handler = sst_byt_irq, | ||
369 | .init = sst_byt_init, | ||
370 | .free = sst_byt_free, | ||
371 | .parse_fw = sst_byt_parse_fw_image, | ||
372 | }; | ||
diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c new file mode 100644 index 000000000000..d0eaeee21be4 --- /dev/null +++ b/sound/soc/intel/sst-baytrail-ipc.c | |||
@@ -0,0 +1,867 @@ | |||
1 | /* | ||
2 | * Intel Baytrail SST IPC Support | ||
3 | * Copyright (c) 2014, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/types.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/list.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/wait.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | #include <linux/export.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/list.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/kthread.h> | ||
28 | #include <linux/firmware.h> | ||
29 | #include <linux/io.h> | ||
30 | #include <asm/div64.h> | ||
31 | |||
32 | #include "sst-baytrail-ipc.h" | ||
33 | #include "sst-dsp.h" | ||
34 | #include "sst-dsp-priv.h" | ||
35 | |||
36 | /* IPC message timeout */ | ||
37 | #define IPC_TIMEOUT_MSECS 300 | ||
38 | #define IPC_BOOT_MSECS 200 | ||
39 | |||
40 | #define IPC_EMPTY_LIST_SIZE 8 | ||
41 | |||
42 | /* IPC header bits */ | ||
43 | #define IPC_HEADER_MSG_ID_MASK 0xff | ||
44 | #define IPC_HEADER_MSG_ID(x) ((x) & IPC_HEADER_MSG_ID_MASK) | ||
45 | #define IPC_HEADER_STR_ID_SHIFT 8 | ||
46 | #define IPC_HEADER_STR_ID_MASK 0x1f | ||
47 | #define IPC_HEADER_STR_ID(x) (((x) & 0x1f) << IPC_HEADER_STR_ID_SHIFT) | ||
48 | #define IPC_HEADER_LARGE_SHIFT 13 | ||
49 | #define IPC_HEADER_LARGE(x) (((x) & 0x1) << IPC_HEADER_LARGE_SHIFT) | ||
50 | #define IPC_HEADER_DATA_SHIFT 16 | ||
51 | #define IPC_HEADER_DATA_MASK 0x3fff | ||
52 | #define IPC_HEADER_DATA(x) (((x) & 0x3fff) << IPC_HEADER_DATA_SHIFT) | ||
53 | |||
54 | /* mask for differentiating between notification and reply message */ | ||
55 | #define IPC_NOTIFICATION (0x1 << 7) | ||
56 | |||
57 | /* I2L Stream config/control msgs */ | ||
58 | #define IPC_IA_ALLOC_STREAM 0x20 | ||
59 | #define IPC_IA_FREE_STREAM 0x21 | ||
60 | #define IPC_IA_PAUSE_STREAM 0x24 | ||
61 | #define IPC_IA_RESUME_STREAM 0x25 | ||
62 | #define IPC_IA_DROP_STREAM 0x26 | ||
63 | #define IPC_IA_START_STREAM 0x30 | ||
64 | |||
65 | /* notification messages */ | ||
66 | #define IPC_IA_FW_INIT_CMPLT 0x81 | ||
67 | #define IPC_SST_PERIOD_ELAPSED 0x97 | ||
68 | |||
69 | /* IPC messages between host and ADSP */ | ||
70 | struct sst_byt_address_info { | ||
71 | u32 addr; | ||
72 | u32 size; | ||
73 | } __packed; | ||
74 | |||
75 | struct sst_byt_str_type { | ||
76 | u8 codec_type; | ||
77 | u8 str_type; | ||
78 | u8 operation; | ||
79 | u8 protected_str; | ||
80 | u8 time_slots; | ||
81 | u8 reserved; | ||
82 | u16 result; | ||
83 | } __packed; | ||
84 | |||
85 | struct sst_byt_pcm_params { | ||
86 | u8 num_chan; | ||
87 | u8 pcm_wd_sz; | ||
88 | u8 use_offload_path; | ||
89 | u8 reserved; | ||
90 | u32 sfreq; | ||
91 | u8 channel_map[8]; | ||
92 | } __packed; | ||
93 | |||
94 | struct sst_byt_frames_info { | ||
95 | u16 num_entries; | ||
96 | u16 rsrvd; | ||
97 | u32 frag_size; | ||
98 | struct sst_byt_address_info ring_buf_info[8]; | ||
99 | } __packed; | ||
100 | |||
101 | struct sst_byt_alloc_params { | ||
102 | struct sst_byt_str_type str_type; | ||
103 | struct sst_byt_pcm_params pcm_params; | ||
104 | struct sst_byt_frames_info frame_info; | ||
105 | } __packed; | ||
106 | |||
107 | struct sst_byt_alloc_response { | ||
108 | struct sst_byt_str_type str_type; | ||
109 | u8 reserved[88]; | ||
110 | } __packed; | ||
111 | |||
112 | struct sst_byt_start_stream_params { | ||
113 | u32 byte_offset; | ||
114 | } __packed; | ||
115 | |||
116 | struct sst_byt_tstamp { | ||
117 | u64 ring_buffer_counter; | ||
118 | u64 hardware_counter; | ||
119 | u64 frames_decoded; | ||
120 | u64 bytes_decoded; | ||
121 | u64 bytes_copied; | ||
122 | u32 sampling_frequency; | ||
123 | u32 channel_peak[8]; | ||
124 | } __packed; | ||
125 | |||
126 | /* driver internal IPC message structure */ | ||
127 | struct ipc_message { | ||
128 | struct list_head list; | ||
129 | u64 header; | ||
130 | |||
131 | /* direction wrt host CPU */ | ||
132 | char tx_data[SST_BYT_IPC_MAX_PAYLOAD_SIZE]; | ||
133 | size_t tx_size; | ||
134 | char rx_data[SST_BYT_IPC_MAX_PAYLOAD_SIZE]; | ||
135 | size_t rx_size; | ||
136 | |||
137 | wait_queue_head_t waitq; | ||
138 | bool complete; | ||
139 | bool wait; | ||
140 | int errno; | ||
141 | }; | ||
142 | |||
143 | struct sst_byt_stream; | ||
144 | struct sst_byt; | ||
145 | |||
146 | /* stream infomation */ | ||
147 | struct sst_byt_stream { | ||
148 | struct list_head node; | ||
149 | |||
150 | /* configuration */ | ||
151 | struct sst_byt_alloc_params request; | ||
152 | struct sst_byt_alloc_response reply; | ||
153 | |||
154 | /* runtime info */ | ||
155 | struct sst_byt *byt; | ||
156 | int str_id; | ||
157 | bool commited; | ||
158 | bool running; | ||
159 | |||
160 | /* driver callback */ | ||
161 | u32 (*notify_position)(struct sst_byt_stream *stream, void *data); | ||
162 | void *pdata; | ||
163 | }; | ||
164 | |||
165 | /* SST Baytrail IPC data */ | ||
166 | struct sst_byt { | ||
167 | struct device *dev; | ||
168 | struct sst_dsp *dsp; | ||
169 | |||
170 | /* stream */ | ||
171 | struct list_head stream_list; | ||
172 | |||
173 | /* boot */ | ||
174 | wait_queue_head_t boot_wait; | ||
175 | bool boot_complete; | ||
176 | |||
177 | /* IPC messaging */ | ||
178 | struct list_head tx_list; | ||
179 | struct list_head rx_list; | ||
180 | struct list_head empty_list; | ||
181 | wait_queue_head_t wait_txq; | ||
182 | struct task_struct *tx_thread; | ||
183 | struct kthread_worker kworker; | ||
184 | struct kthread_work kwork; | ||
185 | struct ipc_message *msg; | ||
186 | }; | ||
187 | |||
188 | static inline u64 sst_byt_header(int msg_id, int data, bool large, int str_id) | ||
189 | { | ||
190 | u64 header; | ||
191 | |||
192 | header = IPC_HEADER_MSG_ID(msg_id) | | ||
193 | IPC_HEADER_STR_ID(str_id) | | ||
194 | IPC_HEADER_LARGE(large) | | ||
195 | IPC_HEADER_DATA(data) | | ||
196 | SST_BYT_IPCX_BUSY; | ||
197 | |||
198 | return header; | ||
199 | } | ||
200 | |||
201 | static inline u16 sst_byt_header_msg_id(u64 header) | ||
202 | { | ||
203 | return header & IPC_HEADER_MSG_ID_MASK; | ||
204 | } | ||
205 | |||
206 | static inline u8 sst_byt_header_str_id(u64 header) | ||
207 | { | ||
208 | return (header >> IPC_HEADER_STR_ID_SHIFT) & IPC_HEADER_STR_ID_MASK; | ||
209 | } | ||
210 | |||
211 | static inline u16 sst_byt_header_data(u64 header) | ||
212 | { | ||
213 | return (header >> IPC_HEADER_DATA_SHIFT) & IPC_HEADER_DATA_MASK; | ||
214 | } | ||
215 | |||
216 | static struct sst_byt_stream *sst_byt_get_stream(struct sst_byt *byt, | ||
217 | int stream_id) | ||
218 | { | ||
219 | struct sst_byt_stream *stream; | ||
220 | |||
221 | list_for_each_entry(stream, &byt->stream_list, node) { | ||
222 | if (stream->str_id == stream_id) | ||
223 | return stream; | ||
224 | } | ||
225 | |||
226 | return NULL; | ||
227 | } | ||
228 | |||
229 | static void sst_byt_ipc_shim_dbg(struct sst_byt *byt, const char *text) | ||
230 | { | ||
231 | struct sst_dsp *sst = byt->dsp; | ||
232 | u64 isr, ipcd, imrx, ipcx; | ||
233 | |||
234 | ipcx = sst_dsp_shim_read64_unlocked(sst, SST_IPCX); | ||
235 | isr = sst_dsp_shim_read64_unlocked(sst, SST_ISRX); | ||
236 | ipcd = sst_dsp_shim_read64_unlocked(sst, SST_IPCD); | ||
237 | imrx = sst_dsp_shim_read64_unlocked(sst, SST_IMRX); | ||
238 | |||
239 | dev_err(byt->dev, | ||
240 | "ipc: --%s-- ipcx 0x%llx isr 0x%llx ipcd 0x%llx imrx 0x%llx\n", | ||
241 | text, ipcx, isr, ipcd, imrx); | ||
242 | } | ||
243 | |||
244 | /* locks held by caller */ | ||
245 | static struct ipc_message *sst_byt_msg_get_empty(struct sst_byt *byt) | ||
246 | { | ||
247 | struct ipc_message *msg = NULL; | ||
248 | |||
249 | if (!list_empty(&byt->empty_list)) { | ||
250 | msg = list_first_entry(&byt->empty_list, | ||
251 | struct ipc_message, list); | ||
252 | list_del(&msg->list); | ||
253 | } | ||
254 | |||
255 | return msg; | ||
256 | } | ||
257 | |||
258 | static void sst_byt_ipc_tx_msgs(struct kthread_work *work) | ||
259 | { | ||
260 | struct sst_byt *byt = | ||
261 | container_of(work, struct sst_byt, kwork); | ||
262 | struct ipc_message *msg; | ||
263 | u64 ipcx; | ||
264 | unsigned long flags; | ||
265 | |||
266 | spin_lock_irqsave(&byt->dsp->spinlock, flags); | ||
267 | if (list_empty(&byt->tx_list)) { | ||
268 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
269 | return; | ||
270 | } | ||
271 | |||
272 | /* if the DSP is busy we will TX messages after IRQ */ | ||
273 | ipcx = sst_dsp_shim_read64_unlocked(byt->dsp, SST_IPCX); | ||
274 | if (ipcx & SST_BYT_IPCX_BUSY) { | ||
275 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
276 | return; | ||
277 | } | ||
278 | |||
279 | msg = list_first_entry(&byt->tx_list, struct ipc_message, list); | ||
280 | |||
281 | list_move(&msg->list, &byt->rx_list); | ||
282 | |||
283 | /* send the message */ | ||
284 | if (msg->header & IPC_HEADER_LARGE(true)) | ||
285 | sst_dsp_outbox_write(byt->dsp, msg->tx_data, msg->tx_size); | ||
286 | sst_dsp_shim_write64_unlocked(byt->dsp, SST_IPCX, msg->header); | ||
287 | |||
288 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
289 | } | ||
290 | |||
291 | static inline void sst_byt_tx_msg_reply_complete(struct sst_byt *byt, | ||
292 | struct ipc_message *msg) | ||
293 | { | ||
294 | msg->complete = true; | ||
295 | |||
296 | if (!msg->wait) | ||
297 | list_add_tail(&msg->list, &byt->empty_list); | ||
298 | else | ||
299 | wake_up(&msg->waitq); | ||
300 | } | ||
301 | |||
302 | static int sst_byt_tx_wait_done(struct sst_byt *byt, struct ipc_message *msg, | ||
303 | void *rx_data) | ||
304 | { | ||
305 | unsigned long flags; | ||
306 | int ret; | ||
307 | |||
308 | /* wait for DSP completion */ | ||
309 | ret = wait_event_timeout(msg->waitq, msg->complete, | ||
310 | msecs_to_jiffies(IPC_TIMEOUT_MSECS)); | ||
311 | |||
312 | spin_lock_irqsave(&byt->dsp->spinlock, flags); | ||
313 | if (ret == 0) { | ||
314 | list_del(&msg->list); | ||
315 | sst_byt_ipc_shim_dbg(byt, "message timeout"); | ||
316 | |||
317 | ret = -ETIMEDOUT; | ||
318 | } else { | ||
319 | |||
320 | /* copy the data returned from DSP */ | ||
321 | if (msg->rx_size) | ||
322 | memcpy(rx_data, msg->rx_data, msg->rx_size); | ||
323 | ret = msg->errno; | ||
324 | } | ||
325 | |||
326 | list_add_tail(&msg->list, &byt->empty_list); | ||
327 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
328 | return ret; | ||
329 | } | ||
330 | |||
331 | static int sst_byt_ipc_tx_message(struct sst_byt *byt, u64 header, | ||
332 | void *tx_data, size_t tx_bytes, | ||
333 | void *rx_data, size_t rx_bytes, int wait) | ||
334 | { | ||
335 | unsigned long flags; | ||
336 | struct ipc_message *msg; | ||
337 | |||
338 | spin_lock_irqsave(&byt->dsp->spinlock, flags); | ||
339 | |||
340 | msg = sst_byt_msg_get_empty(byt); | ||
341 | if (msg == NULL) { | ||
342 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
343 | return -EBUSY; | ||
344 | } | ||
345 | |||
346 | msg->header = header; | ||
347 | msg->tx_size = tx_bytes; | ||
348 | msg->rx_size = rx_bytes; | ||
349 | msg->wait = wait; | ||
350 | msg->errno = 0; | ||
351 | msg->complete = false; | ||
352 | |||
353 | if (tx_bytes) { | ||
354 | /* msg content = lower 32-bit of the header + data */ | ||
355 | *(u32 *)msg->tx_data = (u32)(header & (u32)-1); | ||
356 | memcpy(msg->tx_data + sizeof(u32), tx_data, tx_bytes); | ||
357 | msg->tx_size += sizeof(u32); | ||
358 | } | ||
359 | |||
360 | list_add_tail(&msg->list, &byt->tx_list); | ||
361 | spin_unlock_irqrestore(&byt->dsp->spinlock, flags); | ||
362 | |||
363 | queue_kthread_work(&byt->kworker, &byt->kwork); | ||
364 | |||
365 | if (wait) | ||
366 | return sst_byt_tx_wait_done(byt, msg, rx_data); | ||
367 | else | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static inline int sst_byt_ipc_tx_msg_wait(struct sst_byt *byt, u64 header, | ||
372 | void *tx_data, size_t tx_bytes, | ||
373 | void *rx_data, size_t rx_bytes) | ||
374 | { | ||
375 | return sst_byt_ipc_tx_message(byt, header, tx_data, tx_bytes, | ||
376 | rx_data, rx_bytes, 1); | ||
377 | } | ||
378 | |||
379 | static inline int sst_byt_ipc_tx_msg_nowait(struct sst_byt *byt, u64 header, | ||
380 | void *tx_data, size_t tx_bytes) | ||
381 | { | ||
382 | return sst_byt_ipc_tx_message(byt, header, tx_data, tx_bytes, | ||
383 | NULL, 0, 0); | ||
384 | } | ||
385 | |||
386 | static struct ipc_message *sst_byt_reply_find_msg(struct sst_byt *byt, | ||
387 | u64 header) | ||
388 | { | ||
389 | struct ipc_message *msg = NULL, *_msg; | ||
390 | u64 mask; | ||
391 | |||
392 | /* match reply to message sent based on msg and stream IDs */ | ||
393 | mask = IPC_HEADER_MSG_ID_MASK | | ||
394 | IPC_HEADER_STR_ID_MASK << IPC_HEADER_STR_ID_SHIFT; | ||
395 | header &= mask; | ||
396 | |||
397 | if (list_empty(&byt->rx_list)) { | ||
398 | dev_err(byt->dev, | ||
399 | "ipc: rx list is empty but received 0x%llx\n", header); | ||
400 | goto out; | ||
401 | } | ||
402 | |||
403 | list_for_each_entry(_msg, &byt->rx_list, list) { | ||
404 | if ((_msg->header & mask) == header) { | ||
405 | msg = _msg; | ||
406 | break; | ||
407 | } | ||
408 | } | ||
409 | |||
410 | out: | ||
411 | return msg; | ||
412 | } | ||
413 | |||
414 | static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg) | ||
415 | { | ||
416 | struct sst_byt_stream *stream; | ||
417 | u64 header = msg->header; | ||
418 | u8 stream_id = sst_byt_header_str_id(header); | ||
419 | u8 stream_msg = sst_byt_header_msg_id(header); | ||
420 | |||
421 | stream = sst_byt_get_stream(byt, stream_id); | ||
422 | if (stream == NULL) | ||
423 | return; | ||
424 | |||
425 | switch (stream_msg) { | ||
426 | case IPC_IA_DROP_STREAM: | ||
427 | case IPC_IA_PAUSE_STREAM: | ||
428 | case IPC_IA_FREE_STREAM: | ||
429 | stream->running = false; | ||
430 | break; | ||
431 | case IPC_IA_START_STREAM: | ||
432 | case IPC_IA_RESUME_STREAM: | ||
433 | stream->running = true; | ||
434 | break; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | static int sst_byt_process_reply(struct sst_byt *byt, u64 header) | ||
439 | { | ||
440 | struct ipc_message *msg; | ||
441 | |||
442 | msg = sst_byt_reply_find_msg(byt, header); | ||
443 | if (msg == NULL) | ||
444 | return 1; | ||
445 | |||
446 | if (header & IPC_HEADER_LARGE(true)) { | ||
447 | msg->rx_size = sst_byt_header_data(header); | ||
448 | sst_dsp_inbox_read(byt->dsp, msg->rx_data, msg->rx_size); | ||
449 | } | ||
450 | |||
451 | /* update any stream states */ | ||
452 | sst_byt_stream_update(byt, msg); | ||
453 | |||
454 | list_del(&msg->list); | ||
455 | /* wake up */ | ||
456 | sst_byt_tx_msg_reply_complete(byt, msg); | ||
457 | |||
458 | return 1; | ||
459 | } | ||
460 | |||
461 | static void sst_byt_fw_ready(struct sst_byt *byt, u64 header) | ||
462 | { | ||
463 | dev_dbg(byt->dev, "ipc: DSP is ready 0x%llX\n", header); | ||
464 | |||
465 | byt->boot_complete = true; | ||
466 | wake_up(&byt->boot_wait); | ||
467 | } | ||
468 | |||
469 | static int sst_byt_process_notification(struct sst_byt *byt, | ||
470 | unsigned long *flags) | ||
471 | { | ||
472 | struct sst_dsp *sst = byt->dsp; | ||
473 | struct sst_byt_stream *stream; | ||
474 | u64 header; | ||
475 | u8 msg_id, stream_id; | ||
476 | int handled = 1; | ||
477 | |||
478 | header = sst_dsp_shim_read64_unlocked(sst, SST_IPCD); | ||
479 | msg_id = sst_byt_header_msg_id(header); | ||
480 | |||
481 | switch (msg_id) { | ||
482 | case IPC_SST_PERIOD_ELAPSED: | ||
483 | stream_id = sst_byt_header_str_id(header); | ||
484 | stream = sst_byt_get_stream(byt, stream_id); | ||
485 | if (stream && stream->running && stream->notify_position) { | ||
486 | spin_unlock_irqrestore(&sst->spinlock, *flags); | ||
487 | stream->notify_position(stream, stream->pdata); | ||
488 | spin_lock_irqsave(&sst->spinlock, *flags); | ||
489 | } | ||
490 | break; | ||
491 | case IPC_IA_FW_INIT_CMPLT: | ||
492 | sst_byt_fw_ready(byt, header); | ||
493 | break; | ||
494 | } | ||
495 | |||
496 | return handled; | ||
497 | } | ||
498 | |||
499 | static irqreturn_t sst_byt_irq_thread(int irq, void *context) | ||
500 | { | ||
501 | struct sst_dsp *sst = (struct sst_dsp *) context; | ||
502 | struct sst_byt *byt = sst_dsp_get_thread_context(sst); | ||
503 | u64 header; | ||
504 | unsigned long flags; | ||
505 | |||
506 | spin_lock_irqsave(&sst->spinlock, flags); | ||
507 | |||
508 | header = sst_dsp_shim_read64_unlocked(sst, SST_IPCD); | ||
509 | if (header & SST_BYT_IPCD_BUSY) { | ||
510 | if (header & IPC_NOTIFICATION) { | ||
511 | /* message from ADSP */ | ||
512 | sst_byt_process_notification(byt, &flags); | ||
513 | } else { | ||
514 | /* reply from ADSP */ | ||
515 | sst_byt_process_reply(byt, header); | ||
516 | } | ||
517 | /* | ||
518 | * clear IPCD BUSY bit and set DONE bit. Tell DSP we have | ||
519 | * processed the message and can accept new. Clear data part | ||
520 | * of the header | ||
521 | */ | ||
522 | sst_dsp_shim_update_bits64_unlocked(sst, SST_IPCD, | ||
523 | SST_BYT_IPCD_DONE | SST_BYT_IPCD_BUSY | | ||
524 | IPC_HEADER_DATA(IPC_HEADER_DATA_MASK), | ||
525 | SST_BYT_IPCD_DONE); | ||
526 | /* unmask message request interrupts */ | ||
527 | sst_dsp_shim_update_bits64_unlocked(sst, SST_IMRX, | ||
528 | SST_BYT_IMRX_REQUEST, 0); | ||
529 | } | ||
530 | |||
531 | spin_unlock_irqrestore(&sst->spinlock, flags); | ||
532 | |||
533 | /* continue to send any remaining messages... */ | ||
534 | queue_kthread_work(&byt->kworker, &byt->kwork); | ||
535 | |||
536 | return IRQ_HANDLED; | ||
537 | } | ||
538 | |||
539 | /* stream API */ | ||
540 | struct sst_byt_stream *sst_byt_stream_new(struct sst_byt *byt, int id, | ||
541 | u32 (*notify_position)(struct sst_byt_stream *stream, void *data), | ||
542 | void *data) | ||
543 | { | ||
544 | struct sst_byt_stream *stream; | ||
545 | |||
546 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); | ||
547 | if (stream == NULL) | ||
548 | return NULL; | ||
549 | |||
550 | list_add(&stream->node, &byt->stream_list); | ||
551 | stream->notify_position = notify_position; | ||
552 | stream->pdata = data; | ||
553 | stream->byt = byt; | ||
554 | stream->str_id = id; | ||
555 | |||
556 | return stream; | ||
557 | } | ||
558 | |||
559 | int sst_byt_stream_set_bits(struct sst_byt *byt, struct sst_byt_stream *stream, | ||
560 | int bits) | ||
561 | { | ||
562 | stream->request.pcm_params.pcm_wd_sz = bits; | ||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | int sst_byt_stream_set_channels(struct sst_byt *byt, | ||
567 | struct sst_byt_stream *stream, u8 channels) | ||
568 | { | ||
569 | stream->request.pcm_params.num_chan = channels; | ||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | int sst_byt_stream_set_rate(struct sst_byt *byt, struct sst_byt_stream *stream, | ||
574 | unsigned int rate) | ||
575 | { | ||
576 | stream->request.pcm_params.sfreq = rate; | ||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | /* stream sonfiguration */ | ||
581 | int sst_byt_stream_type(struct sst_byt *byt, struct sst_byt_stream *stream, | ||
582 | int codec_type, int stream_type, int operation) | ||
583 | { | ||
584 | stream->request.str_type.codec_type = codec_type; | ||
585 | stream->request.str_type.str_type = stream_type; | ||
586 | stream->request.str_type.operation = operation; | ||
587 | stream->request.str_type.time_slots = 0xc; | ||
588 | |||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | int sst_byt_stream_buffer(struct sst_byt *byt, struct sst_byt_stream *stream, | ||
593 | uint32_t buffer_addr, uint32_t buffer_size) | ||
594 | { | ||
595 | stream->request.frame_info.num_entries = 1; | ||
596 | stream->request.frame_info.ring_buf_info[0].addr = buffer_addr; | ||
597 | stream->request.frame_info.ring_buf_info[0].size = buffer_size; | ||
598 | /* calculate bytes per 4 ms fragment */ | ||
599 | stream->request.frame_info.frag_size = | ||
600 | stream->request.pcm_params.sfreq * | ||
601 | stream->request.pcm_params.num_chan * | ||
602 | stream->request.pcm_params.pcm_wd_sz / 8 * | ||
603 | 4 / 1000; | ||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream) | ||
608 | { | ||
609 | struct sst_byt_alloc_params *str_req = &stream->request; | ||
610 | struct sst_byt_alloc_response *reply = &stream->reply; | ||
611 | u64 header; | ||
612 | int ret; | ||
613 | |||
614 | header = sst_byt_header(IPC_IA_ALLOC_STREAM, | ||
615 | sizeof(*str_req) + sizeof(u32), | ||
616 | true, stream->str_id); | ||
617 | ret = sst_byt_ipc_tx_msg_wait(byt, header, str_req, sizeof(*str_req), | ||
618 | reply, sizeof(*reply)); | ||
619 | if (ret < 0) { | ||
620 | dev_err(byt->dev, "ipc: error stream commit failed\n"); | ||
621 | return ret; | ||
622 | } | ||
623 | |||
624 | stream->commited = true; | ||
625 | |||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream) | ||
630 | { | ||
631 | u64 header; | ||
632 | int ret = 0; | ||
633 | |||
634 | if (!stream->commited) | ||
635 | goto out; | ||
636 | |||
637 | header = sst_byt_header(IPC_IA_FREE_STREAM, 0, false, stream->str_id); | ||
638 | ret = sst_byt_ipc_tx_msg_wait(byt, header, NULL, 0, NULL, 0); | ||
639 | if (ret < 0) { | ||
640 | dev_err(byt->dev, "ipc: free stream %d failed\n", | ||
641 | stream->str_id); | ||
642 | return -EAGAIN; | ||
643 | } | ||
644 | |||
645 | stream->commited = false; | ||
646 | out: | ||
647 | list_del(&stream->node); | ||
648 | kfree(stream); | ||
649 | |||
650 | return ret; | ||
651 | } | ||
652 | |||
653 | static int sst_byt_stream_operations(struct sst_byt *byt, int type, | ||
654 | int stream_id, int wait) | ||
655 | { | ||
656 | struct sst_byt_start_stream_params start_stream; | ||
657 | u64 header; | ||
658 | void *tx_msg = NULL; | ||
659 | size_t size = 0; | ||
660 | |||
661 | if (type != IPC_IA_START_STREAM) { | ||
662 | header = sst_byt_header(type, 0, false, stream_id); | ||
663 | } else { | ||
664 | start_stream.byte_offset = 0; | ||
665 | header = sst_byt_header(IPC_IA_START_STREAM, | ||
666 | sizeof(start_stream) + sizeof(u32), | ||
667 | true, stream_id); | ||
668 | tx_msg = &start_stream; | ||
669 | size = sizeof(start_stream); | ||
670 | } | ||
671 | |||
672 | if (wait) | ||
673 | return sst_byt_ipc_tx_msg_wait(byt, header, | ||
674 | tx_msg, size, NULL, 0); | ||
675 | else | ||
676 | return sst_byt_ipc_tx_msg_nowait(byt, header, tx_msg, size); | ||
677 | } | ||
678 | |||
679 | /* stream ALSA trigger operations */ | ||
680 | int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream) | ||
681 | { | ||
682 | int ret; | ||
683 | |||
684 | ret = sst_byt_stream_operations(byt, IPC_IA_START_STREAM, | ||
685 | stream->str_id, 0); | ||
686 | if (ret < 0) | ||
687 | dev_err(byt->dev, "ipc: error failed to start stream %d\n", | ||
688 | stream->str_id); | ||
689 | |||
690 | return ret; | ||
691 | } | ||
692 | |||
693 | int sst_byt_stream_stop(struct sst_byt *byt, struct sst_byt_stream *stream) | ||
694 | { | ||
695 | int ret; | ||
696 | |||
697 | /* don't stop streams that are not commited */ | ||
698 | if (!stream->commited) | ||
699 | return 0; | ||
700 | |||
701 | ret = sst_byt_stream_operations(byt, IPC_IA_DROP_STREAM, | ||
702 | stream->str_id, 0); | ||
703 | if (ret < 0) | ||
704 | dev_err(byt->dev, "ipc: error failed to stop stream %d\n", | ||
705 | stream->str_id); | ||
706 | return ret; | ||
707 | } | ||
708 | |||
709 | int sst_byt_stream_pause(struct sst_byt *byt, struct sst_byt_stream *stream) | ||
710 | { | ||
711 | int ret; | ||
712 | |||
713 | ret = sst_byt_stream_operations(byt, IPC_IA_PAUSE_STREAM, | ||
714 | stream->str_id, 0); | ||
715 | if (ret < 0) | ||
716 | dev_err(byt->dev, "ipc: error failed to pause stream %d\n", | ||
717 | stream->str_id); | ||
718 | |||
719 | return ret; | ||
720 | } | ||
721 | |||
722 | int sst_byt_stream_resume(struct sst_byt *byt, struct sst_byt_stream *stream) | ||
723 | { | ||
724 | int ret; | ||
725 | |||
726 | ret = sst_byt_stream_operations(byt, IPC_IA_RESUME_STREAM, | ||
727 | stream->str_id, 0); | ||
728 | if (ret < 0) | ||
729 | dev_err(byt->dev, "ipc: error failed to resume stream %d\n", | ||
730 | stream->str_id); | ||
731 | |||
732 | return ret; | ||
733 | } | ||
734 | |||
735 | int sst_byt_get_dsp_position(struct sst_byt *byt, | ||
736 | struct sst_byt_stream *stream, int buffer_size) | ||
737 | { | ||
738 | struct sst_dsp *sst = byt->dsp; | ||
739 | struct sst_byt_tstamp fw_tstamp; | ||
740 | u8 str_id = stream->str_id; | ||
741 | u32 tstamp_offset; | ||
742 | |||
743 | tstamp_offset = SST_BYT_TIMESTAMP_OFFSET + str_id * sizeof(fw_tstamp); | ||
744 | memcpy_fromio(&fw_tstamp, | ||
745 | sst->addr.lpe + tstamp_offset, sizeof(fw_tstamp)); | ||
746 | |||
747 | return do_div(fw_tstamp.ring_buffer_counter, buffer_size); | ||
748 | } | ||
749 | |||
750 | static int msg_empty_list_init(struct sst_byt *byt) | ||
751 | { | ||
752 | struct ipc_message *msg; | ||
753 | int i; | ||
754 | |||
755 | byt->msg = kzalloc(sizeof(*msg) * IPC_EMPTY_LIST_SIZE, GFP_KERNEL); | ||
756 | if (byt->msg == NULL) | ||
757 | return -ENOMEM; | ||
758 | |||
759 | for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { | ||
760 | init_waitqueue_head(&byt->msg[i].waitq); | ||
761 | list_add(&byt->msg[i].list, &byt->empty_list); | ||
762 | } | ||
763 | |||
764 | return 0; | ||
765 | } | ||
766 | |||
767 | struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt) | ||
768 | { | ||
769 | return byt->dsp; | ||
770 | } | ||
771 | |||
772 | static struct sst_dsp_device byt_dev = { | ||
773 | .thread = sst_byt_irq_thread, | ||
774 | .ops = &sst_byt_ops, | ||
775 | }; | ||
776 | |||
777 | int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) | ||
778 | { | ||
779 | struct sst_byt *byt; | ||
780 | struct sst_fw *byt_sst_fw; | ||
781 | int err; | ||
782 | |||
783 | dev_dbg(dev, "initialising Byt DSP IPC\n"); | ||
784 | |||
785 | byt = devm_kzalloc(dev, sizeof(*byt), GFP_KERNEL); | ||
786 | if (byt == NULL) | ||
787 | return -ENOMEM; | ||
788 | |||
789 | byt->dev = dev; | ||
790 | INIT_LIST_HEAD(&byt->stream_list); | ||
791 | INIT_LIST_HEAD(&byt->tx_list); | ||
792 | INIT_LIST_HEAD(&byt->rx_list); | ||
793 | INIT_LIST_HEAD(&byt->empty_list); | ||
794 | init_waitqueue_head(&byt->boot_wait); | ||
795 | init_waitqueue_head(&byt->wait_txq); | ||
796 | |||
797 | err = msg_empty_list_init(byt); | ||
798 | if (err < 0) | ||
799 | return -ENOMEM; | ||
800 | |||
801 | /* start the IPC message thread */ | ||
802 | init_kthread_worker(&byt->kworker); | ||
803 | byt->tx_thread = kthread_run(kthread_worker_fn, | ||
804 | &byt->kworker, | ||
805 | dev_name(byt->dev)); | ||
806 | if (IS_ERR(byt->tx_thread)) { | ||
807 | err = PTR_ERR(byt->tx_thread); | ||
808 | dev_err(byt->dev, "error failed to create message TX task\n"); | ||
809 | goto err_free_msg; | ||
810 | } | ||
811 | init_kthread_work(&byt->kwork, sst_byt_ipc_tx_msgs); | ||
812 | |||
813 | byt_dev.thread_context = byt; | ||
814 | |||
815 | /* init SST shim */ | ||
816 | byt->dsp = sst_dsp_new(dev, &byt_dev, pdata); | ||
817 | if (byt->dsp == NULL) { | ||
818 | err = -ENODEV; | ||
819 | goto err_free_msg; | ||
820 | } | ||
821 | |||
822 | /* keep the DSP in reset state for base FW loading */ | ||
823 | sst_dsp_reset(byt->dsp); | ||
824 | |||
825 | byt_sst_fw = sst_fw_new(byt->dsp, pdata->fw, byt); | ||
826 | if (byt_sst_fw == NULL) { | ||
827 | err = -ENODEV; | ||
828 | dev_err(dev, "error: failed to load firmware\n"); | ||
829 | goto fw_err; | ||
830 | } | ||
831 | |||
832 | /* wait for DSP boot completion */ | ||
833 | sst_dsp_boot(byt->dsp); | ||
834 | err = wait_event_timeout(byt->boot_wait, byt->boot_complete, | ||
835 | msecs_to_jiffies(IPC_BOOT_MSECS)); | ||
836 | if (err == 0) { | ||
837 | err = -EIO; | ||
838 | dev_err(byt->dev, "ipc: error DSP boot timeout\n"); | ||
839 | goto boot_err; | ||
840 | } | ||
841 | |||
842 | pdata->dsp = byt; | ||
843 | |||
844 | return 0; | ||
845 | |||
846 | boot_err: | ||
847 | sst_dsp_reset(byt->dsp); | ||
848 | sst_fw_free(byt_sst_fw); | ||
849 | fw_err: | ||
850 | sst_dsp_free(byt->dsp); | ||
851 | err_free_msg: | ||
852 | kfree(byt->msg); | ||
853 | |||
854 | return err; | ||
855 | } | ||
856 | EXPORT_SYMBOL_GPL(sst_byt_dsp_init); | ||
857 | |||
858 | void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata) | ||
859 | { | ||
860 | struct sst_byt *byt = pdata->dsp; | ||
861 | |||
862 | sst_dsp_reset(byt->dsp); | ||
863 | sst_fw_free_all(byt->dsp); | ||
864 | sst_dsp_free(byt->dsp); | ||
865 | kfree(byt->msg); | ||
866 | } | ||
867 | EXPORT_SYMBOL_GPL(sst_byt_dsp_free); | ||
diff --git a/sound/soc/intel/sst-baytrail-ipc.h b/sound/soc/intel/sst-baytrail-ipc.h new file mode 100644 index 000000000000..f172b6440fa9 --- /dev/null +++ b/sound/soc/intel/sst-baytrail-ipc.h | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * Intel Baytrail SST IPC Support | ||
3 | * Copyright (c) 2014, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #ifndef __SST_BYT_IPC_H | ||
16 | #define __SST_BYT_IPC_H | ||
17 | |||
18 | #include <linux/types.h> | ||
19 | |||
20 | struct sst_byt; | ||
21 | struct sst_byt_stream; | ||
22 | struct sst_pdata; | ||
23 | extern struct sst_ops sst_byt_ops; | ||
24 | |||
25 | |||
26 | #define SST_BYT_MAILBOX_OFFSET 0x144000 | ||
27 | #define SST_BYT_TIMESTAMP_OFFSET (SST_BYT_MAILBOX_OFFSET + 0x800) | ||
28 | |||
29 | /** | ||
30 | * Upfront defined maximum message size that is | ||
31 | * expected by the in/out communication pipes in FW. | ||
32 | */ | ||
33 | #define SST_BYT_IPC_MAX_PAYLOAD_SIZE 200 | ||
34 | |||
35 | /* stream API */ | ||
36 | struct sst_byt_stream *sst_byt_stream_new(struct sst_byt *byt, int id, | ||
37 | uint32_t (*get_write_position)(struct sst_byt_stream *stream, | ||
38 | void *data), | ||
39 | void *data); | ||
40 | |||
41 | /* stream configuration */ | ||
42 | int sst_byt_stream_set_bits(struct sst_byt *byt, struct sst_byt_stream *stream, | ||
43 | int bits); | ||
44 | int sst_byt_stream_set_channels(struct sst_byt *byt, | ||
45 | struct sst_byt_stream *stream, u8 channels); | ||
46 | int sst_byt_stream_set_rate(struct sst_byt *byt, struct sst_byt_stream *stream, | ||
47 | unsigned int rate); | ||
48 | int sst_byt_stream_type(struct sst_byt *byt, struct sst_byt_stream *stream, | ||
49 | int codec_type, int stream_type, int operation); | ||
50 | int sst_byt_stream_buffer(struct sst_byt *byt, struct sst_byt_stream *stream, | ||
51 | uint32_t buffer_addr, uint32_t buffer_size); | ||
52 | int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream); | ||
53 | int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream); | ||
54 | |||
55 | /* stream ALSA trigger operations */ | ||
56 | int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream); | ||
57 | int sst_byt_stream_stop(struct sst_byt *byt, struct sst_byt_stream *stream); | ||
58 | int sst_byt_stream_pause(struct sst_byt *byt, struct sst_byt_stream *stream); | ||
59 | int sst_byt_stream_resume(struct sst_byt *byt, struct sst_byt_stream *stream); | ||
60 | |||
61 | int sst_byt_get_dsp_position(struct sst_byt *byt, | ||
62 | struct sst_byt_stream *stream, int buffer_size); | ||
63 | |||
64 | /* init */ | ||
65 | int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata); | ||
66 | void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata); | ||
67 | struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt); | ||
68 | |||
69 | #endif | ||
diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/sst-baytrail-pcm.c new file mode 100644 index 000000000000..6d101f3813b4 --- /dev/null +++ b/sound/soc/intel/sst-baytrail-pcm.c | |||
@@ -0,0 +1,422 @@ | |||
1 | /* | ||
2 | * Intel Baytrail SST PCM Support | ||
3 | * Copyright (c) 2014, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <sound/core.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/pcm_params.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include "sst-baytrail-ipc.h" | ||
23 | #include "sst-dsp-priv.h" | ||
24 | #include "sst-dsp.h" | ||
25 | |||
26 | #define BYT_PCM_COUNT 2 | ||
27 | |||
28 | static const struct snd_pcm_hardware sst_byt_pcm_hardware = { | ||
29 | .info = SNDRV_PCM_INFO_MMAP | | ||
30 | SNDRV_PCM_INFO_MMAP_VALID | | ||
31 | SNDRV_PCM_INFO_INTERLEAVED | | ||
32 | SNDRV_PCM_INFO_PAUSE | | ||
33 | SNDRV_PCM_INFO_RESUME, | ||
34 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
35 | SNDRV_PCM_FORMAT_S24_LE, | ||
36 | .period_bytes_min = 384, | ||
37 | .period_bytes_max = 48000, | ||
38 | .periods_min = 2, | ||
39 | .periods_max = 250, | ||
40 | .buffer_bytes_max = 96000, | ||
41 | }; | ||
42 | |||
43 | /* private data for each PCM DSP stream */ | ||
44 | struct sst_byt_pcm_data { | ||
45 | struct sst_byt_stream *stream; | ||
46 | struct snd_pcm_substream *substream; | ||
47 | struct mutex mutex; | ||
48 | }; | ||
49 | |||
50 | /* private data for the driver */ | ||
51 | struct sst_byt_priv_data { | ||
52 | /* runtime DSP */ | ||
53 | struct sst_byt *byt; | ||
54 | |||
55 | /* DAI data */ | ||
56 | struct sst_byt_pcm_data pcm[BYT_PCM_COUNT]; | ||
57 | }; | ||
58 | |||
59 | /* this may get called several times by oss emulation */ | ||
60 | static int sst_byt_pcm_hw_params(struct snd_pcm_substream *substream, | ||
61 | struct snd_pcm_hw_params *params) | ||
62 | { | ||
63 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
64 | struct sst_byt_priv_data *pdata = | ||
65 | snd_soc_platform_get_drvdata(rtd->platform); | ||
66 | struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | ||
67 | struct sst_byt *byt = pdata->byt; | ||
68 | u32 rate, bits; | ||
69 | u8 channels; | ||
70 | int ret, playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | ||
71 | |||
72 | dev_dbg(rtd->dev, "PCM: hw_params, pcm_data %p\n", pcm_data); | ||
73 | |||
74 | ret = sst_byt_stream_type(byt, pcm_data->stream, | ||
75 | 1, 1, !playback); | ||
76 | if (ret < 0) { | ||
77 | dev_err(rtd->dev, "failed to set stream format %d\n", ret); | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | rate = params_rate(params); | ||
82 | ret = sst_byt_stream_set_rate(byt, pcm_data->stream, rate); | ||
83 | if (ret < 0) { | ||
84 | dev_err(rtd->dev, "could not set rate %d\n", rate); | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | bits = snd_pcm_format_width(params_format(params)); | ||
89 | ret = sst_byt_stream_set_bits(byt, pcm_data->stream, bits); | ||
90 | if (ret < 0) { | ||
91 | dev_err(rtd->dev, "could not set formats %d\n", | ||
92 | params_rate(params)); | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | channels = (u8)(params_channels(params) & 0xF); | ||
97 | ret = sst_byt_stream_set_channels(byt, pcm_data->stream, channels); | ||
98 | if (ret < 0) { | ||
99 | dev_err(rtd->dev, "could not set channels %d\n", | ||
100 | params_rate(params)); | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
105 | |||
106 | ret = sst_byt_stream_buffer(byt, pcm_data->stream, | ||
107 | substream->dma_buffer.addr, | ||
108 | params_buffer_bytes(params)); | ||
109 | if (ret < 0) { | ||
110 | dev_err(rtd->dev, "PCM: failed to set DMA buffer %d\n", ret); | ||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | ret = sst_byt_stream_commit(byt, pcm_data->stream); | ||
115 | if (ret < 0) { | ||
116 | dev_err(rtd->dev, "PCM: failed stream commit %d\n", ret); | ||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static int sst_byt_pcm_hw_free(struct snd_pcm_substream *substream) | ||
124 | { | ||
125 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
126 | |||
127 | dev_dbg(rtd->dev, "PCM: hw_free\n"); | ||
128 | snd_pcm_lib_free_pages(substream); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
134 | { | ||
135 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
136 | struct sst_byt_priv_data *pdata = | ||
137 | snd_soc_platform_get_drvdata(rtd->platform); | ||
138 | struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | ||
139 | struct sst_byt *byt = pdata->byt; | ||
140 | |||
141 | dev_dbg(rtd->dev, "PCM: trigger %d\n", cmd); | ||
142 | |||
143 | switch (cmd) { | ||
144 | case SNDRV_PCM_TRIGGER_START: | ||
145 | sst_byt_stream_start(byt, pcm_data->stream); | ||
146 | break; | ||
147 | case SNDRV_PCM_TRIGGER_RESUME: | ||
148 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
149 | sst_byt_stream_resume(byt, pcm_data->stream); | ||
150 | break; | ||
151 | case SNDRV_PCM_TRIGGER_STOP: | ||
152 | sst_byt_stream_stop(byt, pcm_data->stream); | ||
153 | break; | ||
154 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
155 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
156 | sst_byt_stream_pause(byt, pcm_data->stream); | ||
157 | break; | ||
158 | default: | ||
159 | break; | ||
160 | } | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static u32 byt_notify_pointer(struct sst_byt_stream *stream, void *data) | ||
166 | { | ||
167 | struct sst_byt_pcm_data *pcm_data = data; | ||
168 | struct snd_pcm_substream *substream = pcm_data->substream; | ||
169 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
170 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
171 | u32 pos; | ||
172 | |||
173 | pos = frames_to_bytes(runtime, | ||
174 | (runtime->control->appl_ptr % | ||
175 | runtime->buffer_size)); | ||
176 | |||
177 | dev_dbg(rtd->dev, "PCM: App pointer %d bytes\n", pos); | ||
178 | |||
179 | snd_pcm_period_elapsed(substream); | ||
180 | return pos; | ||
181 | } | ||
182 | |||
183 | static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_pcm_substream *substream) | ||
184 | { | ||
185 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
186 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
187 | struct sst_byt_priv_data *pdata = | ||
188 | snd_soc_platform_get_drvdata(rtd->platform); | ||
189 | struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | ||
190 | struct sst_byt *byt = pdata->byt; | ||
191 | snd_pcm_uframes_t offset; | ||
192 | int pos; | ||
193 | |||
194 | pos = sst_byt_get_dsp_position(byt, pcm_data->stream, | ||
195 | snd_pcm_lib_buffer_bytes(substream)); | ||
196 | offset = bytes_to_frames(runtime, pos); | ||
197 | |||
198 | dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n", | ||
199 | frames_to_bytes(runtime, (u32)offset)); | ||
200 | return offset; | ||
201 | } | ||
202 | |||
203 | static int sst_byt_pcm_open(struct snd_pcm_substream *substream) | ||
204 | { | ||
205 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
206 | struct sst_byt_priv_data *pdata = | ||
207 | snd_soc_platform_get_drvdata(rtd->platform); | ||
208 | struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | ||
209 | struct sst_byt *byt = pdata->byt; | ||
210 | |||
211 | dev_dbg(rtd->dev, "PCM: open\n"); | ||
212 | |||
213 | pcm_data = &pdata->pcm[rtd->cpu_dai->id]; | ||
214 | mutex_lock(&pcm_data->mutex); | ||
215 | |||
216 | snd_soc_pcm_set_drvdata(rtd, pcm_data); | ||
217 | pcm_data->substream = substream; | ||
218 | |||
219 | snd_soc_set_runtime_hwparams(substream, &sst_byt_pcm_hardware); | ||
220 | |||
221 | pcm_data->stream = sst_byt_stream_new(byt, rtd->cpu_dai->id + 1, | ||
222 | byt_notify_pointer, pcm_data); | ||
223 | if (pcm_data->stream == NULL) { | ||
224 | dev_err(rtd->dev, "failed to create stream\n"); | ||
225 | mutex_unlock(&pcm_data->mutex); | ||
226 | return -EINVAL; | ||
227 | } | ||
228 | |||
229 | mutex_unlock(&pcm_data->mutex); | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static int sst_byt_pcm_close(struct snd_pcm_substream *substream) | ||
234 | { | ||
235 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
236 | struct sst_byt_priv_data *pdata = | ||
237 | snd_soc_platform_get_drvdata(rtd->platform); | ||
238 | struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | ||
239 | struct sst_byt *byt = pdata->byt; | ||
240 | int ret; | ||
241 | |||
242 | dev_dbg(rtd->dev, "PCM: close\n"); | ||
243 | |||
244 | mutex_lock(&pcm_data->mutex); | ||
245 | ret = sst_byt_stream_free(byt, pcm_data->stream); | ||
246 | if (ret < 0) { | ||
247 | dev_dbg(rtd->dev, "Free stream fail\n"); | ||
248 | goto out; | ||
249 | } | ||
250 | pcm_data->stream = NULL; | ||
251 | |||
252 | out: | ||
253 | mutex_unlock(&pcm_data->mutex); | ||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static int sst_byt_pcm_mmap(struct snd_pcm_substream *substream, | ||
258 | struct vm_area_struct *vma) | ||
259 | { | ||
260 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
261 | |||
262 | dev_dbg(rtd->dev, "PCM: mmap\n"); | ||
263 | return snd_pcm_lib_default_mmap(substream, vma); | ||
264 | } | ||
265 | |||
266 | static struct snd_pcm_ops sst_byt_pcm_ops = { | ||
267 | .open = sst_byt_pcm_open, | ||
268 | .close = sst_byt_pcm_close, | ||
269 | .ioctl = snd_pcm_lib_ioctl, | ||
270 | .hw_params = sst_byt_pcm_hw_params, | ||
271 | .hw_free = sst_byt_pcm_hw_free, | ||
272 | .trigger = sst_byt_pcm_trigger, | ||
273 | .pointer = sst_byt_pcm_pointer, | ||
274 | .mmap = sst_byt_pcm_mmap, | ||
275 | }; | ||
276 | |||
277 | static void sst_byt_pcm_free(struct snd_pcm *pcm) | ||
278 | { | ||
279 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
280 | } | ||
281 | |||
282 | static int sst_byt_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
283 | { | ||
284 | struct snd_pcm *pcm = rtd->pcm; | ||
285 | size_t size; | ||
286 | int ret = 0; | ||
287 | |||
288 | ret = dma_coerce_mask_and_coherent(rtd->card->dev, DMA_BIT_MASK(32)); | ||
289 | if (ret) | ||
290 | return ret; | ||
291 | |||
292 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || | ||
293 | pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
294 | size = sst_byt_pcm_hardware.buffer_bytes_max; | ||
295 | ret = snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
296 | SNDRV_DMA_TYPE_DEV, | ||
297 | rtd->card->dev, | ||
298 | size, size); | ||
299 | if (ret) { | ||
300 | dev_err(rtd->dev, "dma buffer allocation failed %d\n", | ||
301 | ret); | ||
302 | return ret; | ||
303 | } | ||
304 | } | ||
305 | |||
306 | return ret; | ||
307 | } | ||
308 | |||
309 | static struct snd_soc_dai_driver byt_dais[] = { | ||
310 | { | ||
311 | .name = "Front-cpu-dai", | ||
312 | .playback = { | ||
313 | .stream_name = "System Playback", | ||
314 | .channels_min = 2, | ||
315 | .channels_max = 2, | ||
316 | .rates = SNDRV_PCM_RATE_48000, | ||
317 | .formats = SNDRV_PCM_FMTBIT_S24_3LE | | ||
318 | SNDRV_PCM_FMTBIT_S16_LE, | ||
319 | }, | ||
320 | }, | ||
321 | { | ||
322 | .name = "Mic1-cpu-dai", | ||
323 | .capture = { | ||
324 | .stream_name = "Analog Capture", | ||
325 | .channels_min = 2, | ||
326 | .channels_max = 2, | ||
327 | .rates = SNDRV_PCM_RATE_48000, | ||
328 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
329 | }, | ||
330 | }, | ||
331 | }; | ||
332 | |||
333 | static int sst_byt_pcm_probe(struct snd_soc_platform *platform) | ||
334 | { | ||
335 | struct sst_pdata *plat_data = dev_get_platdata(platform->dev); | ||
336 | struct sst_byt_priv_data *priv_data; | ||
337 | int i; | ||
338 | |||
339 | if (!plat_data) | ||
340 | return -ENODEV; | ||
341 | |||
342 | priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data), | ||
343 | GFP_KERNEL); | ||
344 | priv_data->byt = plat_data->dsp; | ||
345 | snd_soc_platform_set_drvdata(platform, priv_data); | ||
346 | |||
347 | for (i = 0; i < ARRAY_SIZE(byt_dais); i++) | ||
348 | mutex_init(&priv_data->pcm[i].mutex); | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static int sst_byt_pcm_remove(struct snd_soc_platform *platform) | ||
354 | { | ||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static struct snd_soc_platform_driver byt_soc_platform = { | ||
359 | .probe = sst_byt_pcm_probe, | ||
360 | .remove = sst_byt_pcm_remove, | ||
361 | .ops = &sst_byt_pcm_ops, | ||
362 | .pcm_new = sst_byt_pcm_new, | ||
363 | .pcm_free = sst_byt_pcm_free, | ||
364 | }; | ||
365 | |||
366 | static const struct snd_soc_component_driver byt_dai_component = { | ||
367 | .name = "byt-dai", | ||
368 | }; | ||
369 | |||
370 | static int sst_byt_pcm_dev_probe(struct platform_device *pdev) | ||
371 | { | ||
372 | struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); | ||
373 | int ret; | ||
374 | |||
375 | ret = sst_byt_dsp_init(&pdev->dev, sst_pdata); | ||
376 | if (ret < 0) | ||
377 | return -ENODEV; | ||
378 | |||
379 | ret = snd_soc_register_platform(&pdev->dev, &byt_soc_platform); | ||
380 | if (ret < 0) | ||
381 | goto err_plat; | ||
382 | |||
383 | ret = snd_soc_register_component(&pdev->dev, &byt_dai_component, | ||
384 | byt_dais, ARRAY_SIZE(byt_dais)); | ||
385 | if (ret < 0) | ||
386 | goto err_comp; | ||
387 | |||
388 | return 0; | ||
389 | |||
390 | err_comp: | ||
391 | snd_soc_unregister_platform(&pdev->dev); | ||
392 | err_plat: | ||
393 | sst_byt_dsp_free(&pdev->dev, sst_pdata); | ||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | static int sst_byt_pcm_dev_remove(struct platform_device *pdev) | ||
398 | { | ||
399 | struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); | ||
400 | |||
401 | snd_soc_unregister_platform(&pdev->dev); | ||
402 | snd_soc_unregister_component(&pdev->dev); | ||
403 | sst_byt_dsp_free(&pdev->dev, sst_pdata); | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static struct platform_driver sst_byt_pcm_driver = { | ||
409 | .driver = { | ||
410 | .name = "baytrail-pcm-audio", | ||
411 | .owner = THIS_MODULE, | ||
412 | }, | ||
413 | |||
414 | .probe = sst_byt_pcm_dev_probe, | ||
415 | .remove = sst_byt_pcm_dev_remove, | ||
416 | }; | ||
417 | module_platform_driver(sst_byt_pcm_driver); | ||
418 | |||
419 | MODULE_AUTHOR("Jarkko Nikula"); | ||
420 | MODULE_DESCRIPTION("Baytrail PCM"); | ||
421 | MODULE_LICENSE("GPL v2"); | ||
422 | MODULE_ALIAS("platform:baytrail-pcm-audio"); | ||
diff --git a/sound/soc/intel/sst-dsp-priv.h b/sound/soc/intel/sst-dsp-priv.h new file mode 100644 index 000000000000..fe8e81aad646 --- /dev/null +++ b/sound/soc/intel/sst-dsp-priv.h | |||
@@ -0,0 +1,309 @@ | |||
1 | /* | ||
2 | * Intel Smart Sound Technology | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __SOUND_SOC_SST_DSP_PRIV_H | ||
18 | #define __SOUND_SOC_SST_DSP_PRIV_H | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/firmware.h> | ||
24 | |||
25 | struct sst_mem_block; | ||
26 | struct sst_module; | ||
27 | struct sst_fw; | ||
28 | |||
29 | /* | ||
30 | * DSP Operations exported by platform Audio DSP driver. | ||
31 | */ | ||
32 | struct sst_ops { | ||
33 | /* DSP core boot / reset */ | ||
34 | void (*boot)(struct sst_dsp *); | ||
35 | void (*reset)(struct sst_dsp *); | ||
36 | |||
37 | /* Shim IO */ | ||
38 | void (*write)(void __iomem *addr, u32 offset, u32 value); | ||
39 | u32 (*read)(void __iomem *addr, u32 offset); | ||
40 | void (*write64)(void __iomem *addr, u32 offset, u64 value); | ||
41 | u64 (*read64)(void __iomem *addr, u32 offset); | ||
42 | |||
43 | /* DSP I/DRAM IO */ | ||
44 | void (*ram_read)(struct sst_dsp *sst, void *dest, void __iomem *src, | ||
45 | size_t bytes); | ||
46 | void (*ram_write)(struct sst_dsp *sst, void __iomem *dest, void *src, | ||
47 | size_t bytes); | ||
48 | |||
49 | void (*dump)(struct sst_dsp *); | ||
50 | |||
51 | /* IRQ handlers */ | ||
52 | irqreturn_t (*irq_handler)(int irq, void *context); | ||
53 | |||
54 | /* SST init and free */ | ||
55 | int (*init)(struct sst_dsp *sst, struct sst_pdata *pdata); | ||
56 | void (*free)(struct sst_dsp *sst); | ||
57 | |||
58 | /* FW module parser/loader */ | ||
59 | int (*parse_fw)(struct sst_fw *sst_fw); | ||
60 | }; | ||
61 | |||
62 | /* | ||
63 | * Audio DSP memory offsets and addresses. | ||
64 | */ | ||
65 | struct sst_addr { | ||
66 | u32 lpe_base; | ||
67 | u32 shim_offset; | ||
68 | u32 iram_offset; | ||
69 | u32 dram_offset; | ||
70 | void __iomem *lpe; | ||
71 | void __iomem *shim; | ||
72 | void __iomem *pci_cfg; | ||
73 | void __iomem *fw_ext; | ||
74 | }; | ||
75 | |||
76 | /* | ||
77 | * Audio DSP Mailbox configuration. | ||
78 | */ | ||
79 | struct sst_mailbox { | ||
80 | void __iomem *in_base; | ||
81 | void __iomem *out_base; | ||
82 | size_t in_size; | ||
83 | size_t out_size; | ||
84 | }; | ||
85 | |||
86 | /* | ||
87 | * Audio DSP Firmware data types. | ||
88 | */ | ||
89 | enum sst_data_type { | ||
90 | SST_DATA_M = 0, /* module block data */ | ||
91 | SST_DATA_P = 1, /* peristant data (text, data) */ | ||
92 | SST_DATA_S = 2, /* scratch data (usually buffers) */ | ||
93 | }; | ||
94 | |||
95 | /* | ||
96 | * Audio DSP memory block types. | ||
97 | */ | ||
98 | enum sst_mem_type { | ||
99 | SST_MEM_IRAM = 0, | ||
100 | SST_MEM_DRAM = 1, | ||
101 | SST_MEM_ANY = 2, | ||
102 | SST_MEM_CACHE= 3, | ||
103 | }; | ||
104 | |||
105 | /* | ||
106 | * Audio DSP Generic Firmware File. | ||
107 | * | ||
108 | * SST Firmware files can consist of 1..N modules. This generic structure is | ||
109 | * used to manage each firmware file and it's modules regardless of SST firmware | ||
110 | * type. A SST driver may load multiple FW files. | ||
111 | */ | ||
112 | struct sst_fw { | ||
113 | struct sst_dsp *dsp; | ||
114 | |||
115 | /* base addresses of FW file data */ | ||
116 | dma_addr_t dmable_fw_paddr; /* physical address of fw data */ | ||
117 | void *dma_buf; /* virtual address of fw data */ | ||
118 | u32 size; /* size of fw data */ | ||
119 | |||
120 | /* lists */ | ||
121 | struct list_head list; /* DSP list of FW */ | ||
122 | struct list_head module_list; /* FW list of modules */ | ||
123 | |||
124 | void *private; /* core doesn't touch this */ | ||
125 | }; | ||
126 | |||
127 | /* | ||
128 | * Audio DSP Generic Module data. | ||
129 | * | ||
130 | * This is used to dsecribe any sections of persistent (text and data) and | ||
131 | * scratch (buffers) of module data in ADSP memory space. | ||
132 | */ | ||
133 | struct sst_module_data { | ||
134 | |||
135 | enum sst_mem_type type; /* destination memory type */ | ||
136 | enum sst_data_type data_type; /* type of module data */ | ||
137 | |||
138 | u32 size; /* size in bytes */ | ||
139 | u32 offset; /* offset in FW file */ | ||
140 | u32 data_offset; /* offset in ADSP memory space */ | ||
141 | void *data; /* module data */ | ||
142 | }; | ||
143 | |||
144 | /* | ||
145 | * Audio DSP Generic Module Template. | ||
146 | * | ||
147 | * Used to define and register a new FW module. This data is extracted from | ||
148 | * FW module header information. | ||
149 | */ | ||
150 | struct sst_module_template { | ||
151 | u32 id; | ||
152 | u32 entry; /* entry point */ | ||
153 | struct sst_module_data s; /* scratch data */ | ||
154 | struct sst_module_data p; /* peristant data */ | ||
155 | }; | ||
156 | |||
157 | /* | ||
158 | * Audio DSP Generic Module. | ||
159 | * | ||
160 | * Each Firmware file can consist of 1..N modules. A module can span multiple | ||
161 | * ADSP memory blocks. The simplest FW will be a file with 1 module. | ||
162 | */ | ||
163 | struct sst_module { | ||
164 | struct sst_dsp *dsp; | ||
165 | struct sst_fw *sst_fw; /* parent FW we belong too */ | ||
166 | |||
167 | /* module configuration */ | ||
168 | u32 id; | ||
169 | u32 entry; /* module entry point */ | ||
170 | u32 offset; /* module offset in firmware file */ | ||
171 | u32 size; /* module size */ | ||
172 | struct sst_module_data s; /* scratch data */ | ||
173 | struct sst_module_data p; /* peristant data */ | ||
174 | |||
175 | /* runtime */ | ||
176 | u32 usage_count; /* can be unloaded if count == 0 */ | ||
177 | void *private; /* core doesn't touch this */ | ||
178 | |||
179 | /* lists */ | ||
180 | struct list_head block_list; /* Module list of blocks in use */ | ||
181 | struct list_head list; /* DSP list of modules */ | ||
182 | struct list_head list_fw; /* FW list of modules */ | ||
183 | }; | ||
184 | |||
185 | /* | ||
186 | * SST Memory Block operations. | ||
187 | */ | ||
188 | struct sst_block_ops { | ||
189 | int (*enable)(struct sst_mem_block *block); | ||
190 | int (*disable)(struct sst_mem_block *block); | ||
191 | }; | ||
192 | |||
193 | /* | ||
194 | * SST Generic Memory Block. | ||
195 | * | ||
196 | * SST ADP memory has multiple IRAM and DRAM blocks. Some ADSP blocks can be | ||
197 | * power gated. | ||
198 | */ | ||
199 | struct sst_mem_block { | ||
200 | struct sst_dsp *dsp; | ||
201 | struct sst_module *module; /* module that uses this block */ | ||
202 | |||
203 | /* block config */ | ||
204 | u32 offset; /* offset from base */ | ||
205 | u32 size; /* block size */ | ||
206 | u32 index; /* block index 0..N */ | ||
207 | enum sst_mem_type type; /* block memory type IRAM/DRAM */ | ||
208 | struct sst_block_ops *ops; /* block operations, if any */ | ||
209 | |||
210 | /* block status */ | ||
211 | enum sst_data_type data_type; /* data type held in this block */ | ||
212 | u32 bytes_used; /* bytes in use by modules */ | ||
213 | void *private; /* generic core does not touch this */ | ||
214 | int users; /* number of modules using this block */ | ||
215 | |||
216 | /* block lists */ | ||
217 | struct list_head module_list; /* Module list of blocks */ | ||
218 | struct list_head list; /* Map list of free/used blocks */ | ||
219 | }; | ||
220 | |||
221 | /* | ||
222 | * Generic SST Shim Interface. | ||
223 | */ | ||
224 | struct sst_dsp { | ||
225 | |||
226 | /* runtime */ | ||
227 | struct sst_dsp_device *sst_dev; | ||
228 | spinlock_t spinlock; /* IPC locking */ | ||
229 | struct mutex mutex; /* DSP FW lock */ | ||
230 | struct device *dev; | ||
231 | void *thread_context; | ||
232 | int irq; | ||
233 | u32 id; | ||
234 | |||
235 | /* list of free and used ADSP memory blocks */ | ||
236 | struct list_head used_block_list; | ||
237 | struct list_head free_block_list; | ||
238 | |||
239 | /* operations */ | ||
240 | struct sst_ops *ops; | ||
241 | |||
242 | /* debug FS */ | ||
243 | struct dentry *debugfs_root; | ||
244 | |||
245 | /* base addresses */ | ||
246 | struct sst_addr addr; | ||
247 | |||
248 | /* mailbox */ | ||
249 | struct sst_mailbox mailbox; | ||
250 | |||
251 | /* SST FW files loaded and their modules */ | ||
252 | struct list_head module_list; | ||
253 | struct list_head fw_list; | ||
254 | |||
255 | /* platform data */ | ||
256 | struct sst_pdata *pdata; | ||
257 | |||
258 | /* DMA FW loading */ | ||
259 | struct sst_dma *dma; | ||
260 | bool fw_use_dma; | ||
261 | }; | ||
262 | |||
263 | /* Size optimised DRAM/IRAM memcpy */ | ||
264 | static inline void sst_dsp_write(struct sst_dsp *sst, void *src, | ||
265 | u32 dest_offset, size_t bytes) | ||
266 | { | ||
267 | sst->ops->ram_write(sst, sst->addr.lpe + dest_offset, src, bytes); | ||
268 | } | ||
269 | |||
270 | static inline void sst_dsp_read(struct sst_dsp *sst, void *dest, | ||
271 | u32 src_offset, size_t bytes) | ||
272 | { | ||
273 | sst->ops->ram_read(sst, dest, sst->addr.lpe + src_offset, bytes); | ||
274 | } | ||
275 | |||
276 | static inline void *sst_dsp_get_thread_context(struct sst_dsp *sst) | ||
277 | { | ||
278 | return sst->thread_context; | ||
279 | } | ||
280 | |||
281 | /* Create/Free FW files - can contain multiple modules */ | ||
282 | struct sst_fw *sst_fw_new(struct sst_dsp *dsp, | ||
283 | const struct firmware *fw, void *private); | ||
284 | void sst_fw_free(struct sst_fw *sst_fw); | ||
285 | void sst_fw_free_all(struct sst_dsp *dsp); | ||
286 | |||
287 | /* Create/Free firmware modules */ | ||
288 | struct sst_module *sst_module_new(struct sst_fw *sst_fw, | ||
289 | struct sst_module_template *template, void *private); | ||
290 | void sst_module_free(struct sst_module *sst_module); | ||
291 | int sst_module_insert(struct sst_module *sst_module); | ||
292 | int sst_module_remove(struct sst_module *sst_module); | ||
293 | int sst_module_insert_fixed_block(struct sst_module *module, | ||
294 | struct sst_module_data *data); | ||
295 | struct sst_module *sst_module_get_from_id(struct sst_dsp *dsp, u32 id); | ||
296 | |||
297 | /* allocate/free pesistent/scratch memory regions managed by drv */ | ||
298 | struct sst_module *sst_mem_block_alloc_scratch(struct sst_dsp *dsp); | ||
299 | void sst_mem_block_free_scratch(struct sst_dsp *dsp, | ||
300 | struct sst_module *scratch); | ||
301 | int sst_block_module_remove(struct sst_module *module); | ||
302 | |||
303 | /* Register the DSPs memory blocks - would be nice to read from ACPI */ | ||
304 | struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset, | ||
305 | u32 size, enum sst_mem_type type, struct sst_block_ops *ops, u32 index, | ||
306 | void *private); | ||
307 | void sst_mem_block_unregister_all(struct sst_dsp *dsp); | ||
308 | |||
309 | #endif | ||
diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c new file mode 100644 index 000000000000..0c129fd85ecf --- /dev/null +++ b/sound/soc/intel/sst-dsp.c | |||
@@ -0,0 +1,385 @@ | |||
1 | /* | ||
2 | * Intel Smart Sound Technology (SST) DSP Core Driver | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/slab.h> | ||
18 | #include <linux/export.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/io.h> | ||
23 | |||
24 | #include "sst-dsp.h" | ||
25 | #include "sst-dsp-priv.h" | ||
26 | |||
27 | #define CREATE_TRACE_POINTS | ||
28 | #include <trace/events/intel-sst.h> | ||
29 | |||
30 | /* Internal generic low-level SST IO functions - can be overidden */ | ||
31 | void sst_shim32_write(void __iomem *addr, u32 offset, u32 value) | ||
32 | { | ||
33 | writel(value, addr + offset); | ||
34 | } | ||
35 | EXPORT_SYMBOL_GPL(sst_shim32_write); | ||
36 | |||
37 | u32 sst_shim32_read(void __iomem *addr, u32 offset) | ||
38 | { | ||
39 | return readl(addr + offset); | ||
40 | } | ||
41 | EXPORT_SYMBOL_GPL(sst_shim32_read); | ||
42 | |||
43 | void sst_shim32_write64(void __iomem *addr, u32 offset, u64 value) | ||
44 | { | ||
45 | memcpy_toio(addr + offset, &value, sizeof(value)); | ||
46 | } | ||
47 | EXPORT_SYMBOL_GPL(sst_shim32_write64); | ||
48 | |||
49 | u64 sst_shim32_read64(void __iomem *addr, u32 offset) | ||
50 | { | ||
51 | u64 val; | ||
52 | |||
53 | memcpy_fromio(&val, addr + offset, sizeof(val)); | ||
54 | return val; | ||
55 | } | ||
56 | EXPORT_SYMBOL_GPL(sst_shim32_read64); | ||
57 | |||
58 | static inline void _sst_memcpy_toio_32(volatile u32 __iomem *dest, | ||
59 | u32 *src, size_t bytes) | ||
60 | { | ||
61 | int i, words = bytes >> 2; | ||
62 | |||
63 | for (i = 0; i < words; i++) | ||
64 | writel(src[i], dest + i); | ||
65 | } | ||
66 | |||
67 | static inline void _sst_memcpy_fromio_32(u32 *dest, | ||
68 | const volatile __iomem u32 *src, size_t bytes) | ||
69 | { | ||
70 | int i, words = bytes >> 2; | ||
71 | |||
72 | for (i = 0; i < words; i++) | ||
73 | dest[i] = readl(src + i); | ||
74 | } | ||
75 | |||
76 | void sst_memcpy_toio_32(struct sst_dsp *sst, | ||
77 | void __iomem *dest, void *src, size_t bytes) | ||
78 | { | ||
79 | _sst_memcpy_toio_32(dest, src, bytes); | ||
80 | } | ||
81 | EXPORT_SYMBOL_GPL(sst_memcpy_toio_32); | ||
82 | |||
83 | void sst_memcpy_fromio_32(struct sst_dsp *sst, void *dest, | ||
84 | void __iomem *src, size_t bytes) | ||
85 | { | ||
86 | _sst_memcpy_fromio_32(dest, src, bytes); | ||
87 | } | ||
88 | EXPORT_SYMBOL_GPL(sst_memcpy_fromio_32); | ||
89 | |||
90 | /* Public API */ | ||
91 | void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value) | ||
92 | { | ||
93 | unsigned long flags; | ||
94 | |||
95 | spin_lock_irqsave(&sst->spinlock, flags); | ||
96 | sst->ops->write(sst->addr.shim, offset, value); | ||
97 | spin_unlock_irqrestore(&sst->spinlock, flags); | ||
98 | } | ||
99 | EXPORT_SYMBOL_GPL(sst_dsp_shim_write); | ||
100 | |||
101 | u32 sst_dsp_shim_read(struct sst_dsp *sst, u32 offset) | ||
102 | { | ||
103 | unsigned long flags; | ||
104 | u32 val; | ||
105 | |||
106 | spin_lock_irqsave(&sst->spinlock, flags); | ||
107 | val = sst->ops->read(sst->addr.shim, offset); | ||
108 | spin_unlock_irqrestore(&sst->spinlock, flags); | ||
109 | |||
110 | return val; | ||
111 | } | ||
112 | EXPORT_SYMBOL_GPL(sst_dsp_shim_read); | ||
113 | |||
114 | void sst_dsp_shim_write64(struct sst_dsp *sst, u32 offset, u64 value) | ||
115 | { | ||
116 | unsigned long flags; | ||
117 | |||
118 | spin_lock_irqsave(&sst->spinlock, flags); | ||
119 | sst->ops->write64(sst->addr.shim, offset, value); | ||
120 | spin_unlock_irqrestore(&sst->spinlock, flags); | ||
121 | } | ||
122 | EXPORT_SYMBOL_GPL(sst_dsp_shim_write64); | ||
123 | |||
124 | u64 sst_dsp_shim_read64(struct sst_dsp *sst, u32 offset) | ||
125 | { | ||
126 | unsigned long flags; | ||
127 | u64 val; | ||
128 | |||
129 | spin_lock_irqsave(&sst->spinlock, flags); | ||
130 | val = sst->ops->read64(sst->addr.shim, offset); | ||
131 | spin_unlock_irqrestore(&sst->spinlock, flags); | ||
132 | |||
133 | return val; | ||
134 | } | ||
135 | EXPORT_SYMBOL_GPL(sst_dsp_shim_read64); | ||
136 | |||
137 | void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value) | ||
138 | { | ||
139 | sst->ops->write(sst->addr.shim, offset, value); | ||
140 | } | ||
141 | EXPORT_SYMBOL_GPL(sst_dsp_shim_write_unlocked); | ||
142 | |||
143 | u32 sst_dsp_shim_read_unlocked(struct sst_dsp *sst, u32 offset) | ||
144 | { | ||
145 | return sst->ops->read(sst->addr.shim, offset); | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(sst_dsp_shim_read_unlocked); | ||
148 | |||
149 | void sst_dsp_shim_write64_unlocked(struct sst_dsp *sst, u32 offset, u64 value) | ||
150 | { | ||
151 | sst->ops->write64(sst->addr.shim, offset, value); | ||
152 | } | ||
153 | EXPORT_SYMBOL_GPL(sst_dsp_shim_write64_unlocked); | ||
154 | |||
155 | u64 sst_dsp_shim_read64_unlocked(struct sst_dsp *sst, u32 offset) | ||
156 | { | ||
157 | return sst->ops->read64(sst->addr.shim, offset); | ||
158 | } | ||
159 | EXPORT_SYMBOL_GPL(sst_dsp_shim_read64_unlocked); | ||
160 | |||
161 | int sst_dsp_shim_update_bits_unlocked(struct sst_dsp *sst, u32 offset, | ||
162 | u32 mask, u32 value) | ||
163 | { | ||
164 | bool change; | ||
165 | unsigned int old, new; | ||
166 | u32 ret; | ||
167 | |||
168 | ret = sst_dsp_shim_read_unlocked(sst, offset); | ||
169 | |||
170 | old = ret; | ||
171 | new = (old & (~mask)) | (value & mask); | ||
172 | |||
173 | change = (old != new); | ||
174 | if (change) | ||
175 | sst_dsp_shim_write_unlocked(sst, offset, new); | ||
176 | |||
177 | return change; | ||
178 | } | ||
179 | EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_unlocked); | ||
180 | |||
181 | int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset, | ||
182 | u64 mask, u64 value) | ||
183 | { | ||
184 | bool change; | ||
185 | u64 old, new; | ||
186 | |||
187 | old = sst_dsp_shim_read64_unlocked(sst, offset); | ||
188 | |||
189 | new = (old & (~mask)) | (value & mask); | ||
190 | |||
191 | change = (old != new); | ||
192 | if (change) | ||
193 | sst_dsp_shim_write64_unlocked(sst, offset, new); | ||
194 | |||
195 | return change; | ||
196 | } | ||
197 | EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64_unlocked); | ||
198 | |||
199 | int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset, | ||
200 | u32 mask, u32 value) | ||
201 | { | ||
202 | unsigned long flags; | ||
203 | bool change; | ||
204 | |||
205 | spin_lock_irqsave(&sst->spinlock, flags); | ||
206 | change = sst_dsp_shim_update_bits_unlocked(sst, offset, mask, value); | ||
207 | spin_unlock_irqrestore(&sst->spinlock, flags); | ||
208 | return change; | ||
209 | } | ||
210 | EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits); | ||
211 | |||
212 | int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset, | ||
213 | u64 mask, u64 value) | ||
214 | { | ||
215 | unsigned long flags; | ||
216 | bool change; | ||
217 | |||
218 | spin_lock_irqsave(&sst->spinlock, flags); | ||
219 | change = sst_dsp_shim_update_bits64_unlocked(sst, offset, mask, value); | ||
220 | spin_unlock_irqrestore(&sst->spinlock, flags); | ||
221 | return change; | ||
222 | } | ||
223 | EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64); | ||
224 | |||
225 | void sst_dsp_dump(struct sst_dsp *sst) | ||
226 | { | ||
227 | sst->ops->dump(sst); | ||
228 | } | ||
229 | EXPORT_SYMBOL_GPL(sst_dsp_dump); | ||
230 | |||
231 | void sst_dsp_reset(struct sst_dsp *sst) | ||
232 | { | ||
233 | sst->ops->reset(sst); | ||
234 | } | ||
235 | EXPORT_SYMBOL_GPL(sst_dsp_reset); | ||
236 | |||
237 | int sst_dsp_boot(struct sst_dsp *sst) | ||
238 | { | ||
239 | sst->ops->boot(sst); | ||
240 | return 0; | ||
241 | } | ||
242 | EXPORT_SYMBOL_GPL(sst_dsp_boot); | ||
243 | |||
244 | void sst_dsp_ipc_msg_tx(struct sst_dsp *dsp, u32 msg) | ||
245 | { | ||
246 | sst_dsp_shim_write_unlocked(dsp, SST_IPCX, msg | SST_IPCX_BUSY); | ||
247 | trace_sst_ipc_msg_tx(msg); | ||
248 | } | ||
249 | EXPORT_SYMBOL_GPL(sst_dsp_ipc_msg_tx); | ||
250 | |||
251 | u32 sst_dsp_ipc_msg_rx(struct sst_dsp *dsp) | ||
252 | { | ||
253 | u32 msg; | ||
254 | |||
255 | msg = sst_dsp_shim_read_unlocked(dsp, SST_IPCX); | ||
256 | trace_sst_ipc_msg_rx(msg); | ||
257 | |||
258 | return msg; | ||
259 | } | ||
260 | EXPORT_SYMBOL_GPL(sst_dsp_ipc_msg_rx); | ||
261 | |||
262 | int sst_dsp_mailbox_init(struct sst_dsp *sst, u32 inbox_offset, size_t inbox_size, | ||
263 | u32 outbox_offset, size_t outbox_size) | ||
264 | { | ||
265 | sst->mailbox.in_base = sst->addr.lpe + inbox_offset; | ||
266 | sst->mailbox.out_base = sst->addr.lpe + outbox_offset; | ||
267 | sst->mailbox.in_size = inbox_size; | ||
268 | sst->mailbox.out_size = outbox_size; | ||
269 | return 0; | ||
270 | } | ||
271 | EXPORT_SYMBOL_GPL(sst_dsp_mailbox_init); | ||
272 | |||
273 | void sst_dsp_outbox_write(struct sst_dsp *sst, void *message, size_t bytes) | ||
274 | { | ||
275 | u32 i; | ||
276 | |||
277 | trace_sst_ipc_outbox_write(bytes); | ||
278 | |||
279 | memcpy_toio(sst->mailbox.out_base, message, bytes); | ||
280 | |||
281 | for (i = 0; i < bytes; i += 4) | ||
282 | trace_sst_ipc_outbox_wdata(i, *(u32 *)(message + i)); | ||
283 | } | ||
284 | EXPORT_SYMBOL_GPL(sst_dsp_outbox_write); | ||
285 | |||
286 | void sst_dsp_outbox_read(struct sst_dsp *sst, void *message, size_t bytes) | ||
287 | { | ||
288 | u32 i; | ||
289 | |||
290 | trace_sst_ipc_outbox_read(bytes); | ||
291 | |||
292 | memcpy_fromio(message, sst->mailbox.out_base, bytes); | ||
293 | |||
294 | for (i = 0; i < bytes; i += 4) | ||
295 | trace_sst_ipc_outbox_rdata(i, *(u32 *)(message + i)); | ||
296 | } | ||
297 | EXPORT_SYMBOL_GPL(sst_dsp_outbox_read); | ||
298 | |||
299 | void sst_dsp_inbox_write(struct sst_dsp *sst, void *message, size_t bytes) | ||
300 | { | ||
301 | u32 i; | ||
302 | |||
303 | trace_sst_ipc_inbox_write(bytes); | ||
304 | |||
305 | memcpy_toio(sst->mailbox.in_base, message, bytes); | ||
306 | |||
307 | for (i = 0; i < bytes; i += 4) | ||
308 | trace_sst_ipc_inbox_wdata(i, *(u32 *)(message + i)); | ||
309 | } | ||
310 | EXPORT_SYMBOL_GPL(sst_dsp_inbox_write); | ||
311 | |||
312 | void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes) | ||
313 | { | ||
314 | u32 i; | ||
315 | |||
316 | trace_sst_ipc_inbox_read(bytes); | ||
317 | |||
318 | memcpy_fromio(message, sst->mailbox.in_base, bytes); | ||
319 | |||
320 | for (i = 0; i < bytes; i += 4) | ||
321 | trace_sst_ipc_inbox_rdata(i, *(u32 *)(message + i)); | ||
322 | } | ||
323 | EXPORT_SYMBOL_GPL(sst_dsp_inbox_read); | ||
324 | |||
325 | struct sst_dsp *sst_dsp_new(struct device *dev, | ||
326 | struct sst_dsp_device *sst_dev, struct sst_pdata *pdata) | ||
327 | { | ||
328 | struct sst_dsp *sst; | ||
329 | int err; | ||
330 | |||
331 | dev_dbg(dev, "initialising audio DSP id 0x%x\n", pdata->id); | ||
332 | |||
333 | sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL); | ||
334 | if (sst == NULL) | ||
335 | return NULL; | ||
336 | |||
337 | spin_lock_init(&sst->spinlock); | ||
338 | mutex_init(&sst->mutex); | ||
339 | sst->dev = dev; | ||
340 | sst->thread_context = sst_dev->thread_context; | ||
341 | sst->sst_dev = sst_dev; | ||
342 | sst->id = pdata->id; | ||
343 | sst->irq = pdata->irq; | ||
344 | sst->ops = sst_dev->ops; | ||
345 | sst->pdata = pdata; | ||
346 | INIT_LIST_HEAD(&sst->used_block_list); | ||
347 | INIT_LIST_HEAD(&sst->free_block_list); | ||
348 | INIT_LIST_HEAD(&sst->module_list); | ||
349 | INIT_LIST_HEAD(&sst->fw_list); | ||
350 | |||
351 | /* Initialise SST Audio DSP */ | ||
352 | if (sst->ops->init) { | ||
353 | err = sst->ops->init(sst, pdata); | ||
354 | if (err < 0) | ||
355 | return NULL; | ||
356 | } | ||
357 | |||
358 | /* Register the ISR */ | ||
359 | err = request_threaded_irq(sst->irq, sst->ops->irq_handler, | ||
360 | sst_dev->thread, IRQF_SHARED, "AudioDSP", sst); | ||
361 | if (err) | ||
362 | goto irq_err; | ||
363 | |||
364 | return sst; | ||
365 | |||
366 | irq_err: | ||
367 | if (sst->ops->free) | ||
368 | sst->ops->free(sst); | ||
369 | |||
370 | return NULL; | ||
371 | } | ||
372 | EXPORT_SYMBOL_GPL(sst_dsp_new); | ||
373 | |||
374 | void sst_dsp_free(struct sst_dsp *sst) | ||
375 | { | ||
376 | free_irq(sst->irq, sst); | ||
377 | if (sst->ops->free) | ||
378 | sst->ops->free(sst); | ||
379 | } | ||
380 | EXPORT_SYMBOL_GPL(sst_dsp_free); | ||
381 | |||
382 | /* Module information */ | ||
383 | MODULE_AUTHOR("Liam Girdwood"); | ||
384 | MODULE_DESCRIPTION("Intel SST Core"); | ||
385 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h new file mode 100644 index 000000000000..74052b59485c --- /dev/null +++ b/sound/soc/intel/sst-dsp.h | |||
@@ -0,0 +1,233 @@ | |||
1 | /* | ||
2 | * Intel Smart Sound Technology (SST) Core | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __SOUND_SOC_SST_DSP_H | ||
18 | #define __SOUND_SOC_SST_DSP_H | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | |||
24 | /* SST Device IDs */ | ||
25 | #define SST_DEV_ID_LYNX_POINT 0x33C8 | ||
26 | #define SST_DEV_ID_WILDCAT_POINT 0x3438 | ||
27 | #define SST_DEV_ID_BYT 0x0F28 | ||
28 | |||
29 | /* Supported SST DMA Devices */ | ||
30 | #define SST_DMA_TYPE_DW 1 | ||
31 | #define SST_DMA_TYPE_MID 2 | ||
32 | |||
33 | /* SST Shim register map | ||
34 | * The register naming can differ between products. Some products also | ||
35 | * contain extra functionality. | ||
36 | */ | ||
37 | #define SST_CSR 0x00 | ||
38 | #define SST_PISR 0x08 | ||
39 | #define SST_PIMR 0x10 | ||
40 | #define SST_ISRX 0x18 | ||
41 | #define SST_ISRD 0x20 | ||
42 | #define SST_IMRX 0x28 | ||
43 | #define SST_IMRD 0x30 | ||
44 | #define SST_IPCX 0x38 /* IPC IA -> SST */ | ||
45 | #define SST_IPCD 0x40 /* IPC SST -> IA */ | ||
46 | #define SST_ISRSC 0x48 | ||
47 | #define SST_ISRLPESC 0x50 | ||
48 | #define SST_IMRSC 0x58 | ||
49 | #define SST_IMRLPESC 0x60 | ||
50 | #define SST_IPCSC 0x68 | ||
51 | #define SST_IPCLPESC 0x70 | ||
52 | #define SST_CLKCTL 0x78 | ||
53 | #define SST_CSR2 0x80 | ||
54 | #define SST_LTRC 0xE0 | ||
55 | #define SST_HDMC 0xE8 | ||
56 | #define SST_DBGO 0xF0 | ||
57 | |||
58 | #define SST_SHIM_SIZE 0x100 | ||
59 | #define SST_PWMCTRL 0x1000 | ||
60 | |||
61 | /* SST Shim Register bits | ||
62 | * The register bit naming can differ between products. Some products also | ||
63 | * contain extra functionality. | ||
64 | */ | ||
65 | |||
66 | /* CSR / CS */ | ||
67 | #define SST_CSR_RST (0x1 << 1) | ||
68 | #define SST_CSR_SBCS0 (0x1 << 2) | ||
69 | #define SST_CSR_SBCS1 (0x1 << 3) | ||
70 | #define SST_CSR_DCS(x) (x << 4) | ||
71 | #define SST_CSR_DCS_MASK (0x7 << 4) | ||
72 | #define SST_CSR_STALL (0x1 << 10) | ||
73 | #define SST_CSR_S0IOCS (0x1 << 21) | ||
74 | #define SST_CSR_S1IOCS (0x1 << 23) | ||
75 | #define SST_CSR_LPCS (0x1 << 31) | ||
76 | #define SST_BYT_CSR_RST (0x1 << 0) | ||
77 | #define SST_BYT_CSR_VECTOR_SEL (0x1 << 1) | ||
78 | #define SST_BYT_CSR_STALL (0x1 << 2) | ||
79 | #define SST_BYT_CSR_PWAITMODE (0x1 << 3) | ||
80 | |||
81 | /* ISRX / ISC */ | ||
82 | #define SST_ISRX_BUSY (0x1 << 1) | ||
83 | #define SST_ISRX_DONE (0x1 << 0) | ||
84 | #define SST_BYT_ISRX_REQUEST (0x1 << 1) | ||
85 | |||
86 | /* ISRD / ISD */ | ||
87 | #define SST_ISRD_BUSY (0x1 << 1) | ||
88 | #define SST_ISRD_DONE (0x1 << 0) | ||
89 | |||
90 | /* IMRX / IMC */ | ||
91 | #define SST_IMRX_BUSY (0x1 << 1) | ||
92 | #define SST_IMRX_DONE (0x1 << 0) | ||
93 | #define SST_BYT_IMRX_REQUEST (0x1 << 1) | ||
94 | |||
95 | /* IPCX / IPCC */ | ||
96 | #define SST_IPCX_DONE (0x1 << 30) | ||
97 | #define SST_IPCX_BUSY (0x1 << 31) | ||
98 | #define SST_BYT_IPCX_DONE ((u64)0x1 << 62) | ||
99 | #define SST_BYT_IPCX_BUSY ((u64)0x1 << 63) | ||
100 | |||
101 | /* IPCD */ | ||
102 | #define SST_IPCD_DONE (0x1 << 30) | ||
103 | #define SST_IPCD_BUSY (0x1 << 31) | ||
104 | #define SST_BYT_IPCD_DONE ((u64)0x1 << 62) | ||
105 | #define SST_BYT_IPCD_BUSY ((u64)0x1 << 63) | ||
106 | |||
107 | /* CLKCTL */ | ||
108 | #define SST_CLKCTL_SMOS(x) (x << 24) | ||
109 | #define SST_CLKCTL_MASK (3 << 24) | ||
110 | #define SST_CLKCTL_DCPLCG (1 << 18) | ||
111 | #define SST_CLKCTL_SCOE1 (1 << 17) | ||
112 | #define SST_CLKCTL_SCOE0 (1 << 16) | ||
113 | |||
114 | /* CSR2 / CS2 */ | ||
115 | #define SST_CSR2_SDFD_SSP0 (1 << 1) | ||
116 | #define SST_CSR2_SDFD_SSP1 (1 << 2) | ||
117 | |||
118 | /* LTRC */ | ||
119 | #define SST_LTRC_VAL(x) (x << 0) | ||
120 | |||
121 | /* HDMC */ | ||
122 | #define SST_HDMC_HDDA0(x) (x << 0) | ||
123 | #define SST_HDMC_HDDA1(x) (x << 7) | ||
124 | |||
125 | |||
126 | /* SST Vendor Defined Registers and bits */ | ||
127 | #define SST_VDRTCTL0 0xa0 | ||
128 | #define SST_VDRTCTL1 0xa4 | ||
129 | #define SST_VDRTCTL2 0xa8 | ||
130 | #define SST_VDRTCTL3 0xaC | ||
131 | |||
132 | /* VDRTCTL0 */ | ||
133 | #define SST_VDRTCL0_DSRAMPGE_SHIFT 16 | ||
134 | #define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT) | ||
135 | #define SST_VDRTCL0_ISRAMPGE_SHIFT 6 | ||
136 | #define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT) | ||
137 | |||
138 | struct sst_dsp; | ||
139 | |||
140 | /* | ||
141 | * SST Device. | ||
142 | * | ||
143 | * This structure is populated by the SST core driver. | ||
144 | */ | ||
145 | struct sst_dsp_device { | ||
146 | /* Mandatory fields */ | ||
147 | struct sst_ops *ops; | ||
148 | irqreturn_t (*thread)(int irq, void *context); | ||
149 | void *thread_context; | ||
150 | }; | ||
151 | |||
152 | /* | ||
153 | * SST Platform Data. | ||
154 | */ | ||
155 | struct sst_pdata { | ||
156 | /* ACPI data */ | ||
157 | u32 lpe_base; | ||
158 | u32 lpe_size; | ||
159 | u32 pcicfg_base; | ||
160 | u32 pcicfg_size; | ||
161 | u32 fw_base; | ||
162 | u32 fw_size; | ||
163 | int irq; | ||
164 | |||
165 | /* Firmware */ | ||
166 | const struct firmware *fw; | ||
167 | |||
168 | /* DMA */ | ||
169 | u32 dma_base; | ||
170 | u32 dma_size; | ||
171 | int dma_engine; | ||
172 | |||
173 | /* DSP */ | ||
174 | u32 id; | ||
175 | void *dsp; | ||
176 | }; | ||
177 | |||
178 | /* Initialization */ | ||
179 | struct sst_dsp *sst_dsp_new(struct device *dev, | ||
180 | struct sst_dsp_device *sst_dev, struct sst_pdata *pdata); | ||
181 | void sst_dsp_free(struct sst_dsp *sst); | ||
182 | |||
183 | /* SHIM Read / Write */ | ||
184 | void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value); | ||
185 | u32 sst_dsp_shim_read(struct sst_dsp *sst, u32 offset); | ||
186 | int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset, | ||
187 | u32 mask, u32 value); | ||
188 | void sst_dsp_shim_write64(struct sst_dsp *sst, u32 offset, u64 value); | ||
189 | u64 sst_dsp_shim_read64(struct sst_dsp *sst, u32 offset); | ||
190 | int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset, | ||
191 | u64 mask, u64 value); | ||
192 | |||
193 | /* SHIM Read / Write Unlocked for callers already holding sst lock */ | ||
194 | void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value); | ||
195 | u32 sst_dsp_shim_read_unlocked(struct sst_dsp *sst, u32 offset); | ||
196 | int sst_dsp_shim_update_bits_unlocked(struct sst_dsp *sst, u32 offset, | ||
197 | u32 mask, u32 value); | ||
198 | void sst_dsp_shim_write64_unlocked(struct sst_dsp *sst, u32 offset, u64 value); | ||
199 | u64 sst_dsp_shim_read64_unlocked(struct sst_dsp *sst, u32 offset); | ||
200 | int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset, | ||
201 | u64 mask, u64 value); | ||
202 | |||
203 | /* Internal generic low-level SST IO functions - can be overidden */ | ||
204 | void sst_shim32_write(void __iomem *addr, u32 offset, u32 value); | ||
205 | u32 sst_shim32_read(void __iomem *addr, u32 offset); | ||
206 | void sst_shim32_write64(void __iomem *addr, u32 offset, u64 value); | ||
207 | u64 sst_shim32_read64(void __iomem *addr, u32 offset); | ||
208 | void sst_memcpy_toio_32(struct sst_dsp *sst, | ||
209 | void __iomem *dest, void *src, size_t bytes); | ||
210 | void sst_memcpy_fromio_32(struct sst_dsp *sst, | ||
211 | void *dest, void __iomem *src, size_t bytes); | ||
212 | |||
213 | /* DSP reset & boot */ | ||
214 | void sst_dsp_reset(struct sst_dsp *sst); | ||
215 | int sst_dsp_boot(struct sst_dsp *sst); | ||
216 | |||
217 | /* Msg IO */ | ||
218 | void sst_dsp_ipc_msg_tx(struct sst_dsp *dsp, u32 msg); | ||
219 | u32 sst_dsp_ipc_msg_rx(struct sst_dsp *dsp); | ||
220 | |||
221 | /* Mailbox management */ | ||
222 | int sst_dsp_mailbox_init(struct sst_dsp *dsp, u32 inbox_offset, | ||
223 | size_t inbox_size, u32 outbox_offset, size_t outbox_size); | ||
224 | void sst_dsp_inbox_write(struct sst_dsp *dsp, void *message, size_t bytes); | ||
225 | void sst_dsp_inbox_read(struct sst_dsp *dsp, void *message, size_t bytes); | ||
226 | void sst_dsp_outbox_write(struct sst_dsp *dsp, void *message, size_t bytes); | ||
227 | void sst_dsp_outbox_read(struct sst_dsp *dsp, void *message, size_t bytes); | ||
228 | void sst_dsp_mailbox_dump(struct sst_dsp *dsp, size_t bytes); | ||
229 | |||
230 | /* Debug */ | ||
231 | void sst_dsp_dump(struct sst_dsp *sst); | ||
232 | |||
233 | #endif | ||
diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c new file mode 100644 index 000000000000..f7687107cf7f --- /dev/null +++ b/sound/soc/intel/sst-firmware.c | |||
@@ -0,0 +1,587 @@ | |||
1 | /* | ||
2 | * Intel SST Firmware Loader | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/firmware.h> | ||
21 | #include <linux/export.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/dma-mapping.h> | ||
24 | #include <linux/dmaengine.h> | ||
25 | #include <linux/pci.h> | ||
26 | |||
27 | #include <asm/page.h> | ||
28 | #include <asm/pgtable.h> | ||
29 | |||
30 | #include "sst-dsp.h" | ||
31 | #include "sst-dsp-priv.h" | ||
32 | |||
33 | static void sst_memcpy32(volatile void __iomem *dest, void *src, u32 bytes) | ||
34 | { | ||
35 | u32 i; | ||
36 | |||
37 | /* copy one 32 bit word at a time as 64 bit access is not supported */ | ||
38 | for (i = 0; i < bytes; i += 4) | ||
39 | memcpy_toio(dest + i, src + i, 4); | ||
40 | } | ||
41 | |||
42 | /* create new generic firmware object */ | ||
43 | struct sst_fw *sst_fw_new(struct sst_dsp *dsp, | ||
44 | const struct firmware *fw, void *private) | ||
45 | { | ||
46 | struct sst_fw *sst_fw; | ||
47 | int err; | ||
48 | |||
49 | if (!dsp->ops->parse_fw) | ||
50 | return NULL; | ||
51 | |||
52 | sst_fw = kzalloc(sizeof(*sst_fw), GFP_KERNEL); | ||
53 | if (sst_fw == NULL) | ||
54 | return NULL; | ||
55 | |||
56 | sst_fw->dsp = dsp; | ||
57 | sst_fw->private = private; | ||
58 | sst_fw->size = fw->size; | ||
59 | |||
60 | err = dma_coerce_mask_and_coherent(dsp->dev, DMA_BIT_MASK(32)); | ||
61 | if (err < 0) { | ||
62 | kfree(sst_fw); | ||
63 | return NULL; | ||
64 | } | ||
65 | |||
66 | /* allocate DMA buffer to store FW data */ | ||
67 | sst_fw->dma_buf = dma_alloc_coherent(dsp->dev, sst_fw->size, | ||
68 | &sst_fw->dmable_fw_paddr, GFP_DMA | GFP_KERNEL); | ||
69 | if (!sst_fw->dma_buf) { | ||
70 | dev_err(dsp->dev, "error: DMA alloc failed\n"); | ||
71 | kfree(sst_fw); | ||
72 | return NULL; | ||
73 | } | ||
74 | |||
75 | /* copy FW data to DMA-able memory */ | ||
76 | memcpy((void *)sst_fw->dma_buf, (void *)fw->data, fw->size); | ||
77 | |||
78 | /* call core specific FW paser to load FW data into DSP */ | ||
79 | err = dsp->ops->parse_fw(sst_fw); | ||
80 | if (err < 0) { | ||
81 | dev_err(dsp->dev, "error: parse fw failed %d\n", err); | ||
82 | goto parse_err; | ||
83 | } | ||
84 | |||
85 | mutex_lock(&dsp->mutex); | ||
86 | list_add(&sst_fw->list, &dsp->fw_list); | ||
87 | mutex_unlock(&dsp->mutex); | ||
88 | |||
89 | return sst_fw; | ||
90 | |||
91 | parse_err: | ||
92 | dma_free_coherent(dsp->dev, sst_fw->size, | ||
93 | sst_fw->dma_buf, | ||
94 | sst_fw->dmable_fw_paddr); | ||
95 | kfree(sst_fw); | ||
96 | return NULL; | ||
97 | } | ||
98 | EXPORT_SYMBOL_GPL(sst_fw_new); | ||
99 | |||
100 | /* free single firmware object */ | ||
101 | void sst_fw_free(struct sst_fw *sst_fw) | ||
102 | { | ||
103 | struct sst_dsp *dsp = sst_fw->dsp; | ||
104 | |||
105 | mutex_lock(&dsp->mutex); | ||
106 | list_del(&sst_fw->list); | ||
107 | mutex_unlock(&dsp->mutex); | ||
108 | |||
109 | dma_free_coherent(dsp->dev, sst_fw->size, sst_fw->dma_buf, | ||
110 | sst_fw->dmable_fw_paddr); | ||
111 | kfree(sst_fw); | ||
112 | } | ||
113 | EXPORT_SYMBOL_GPL(sst_fw_free); | ||
114 | |||
115 | /* free all firmware objects */ | ||
116 | void sst_fw_free_all(struct sst_dsp *dsp) | ||
117 | { | ||
118 | struct sst_fw *sst_fw, *t; | ||
119 | |||
120 | mutex_lock(&dsp->mutex); | ||
121 | list_for_each_entry_safe(sst_fw, t, &dsp->fw_list, list) { | ||
122 | |||
123 | list_del(&sst_fw->list); | ||
124 | dma_free_coherent(dsp->dev, sst_fw->size, sst_fw->dma_buf, | ||
125 | sst_fw->dmable_fw_paddr); | ||
126 | kfree(sst_fw); | ||
127 | } | ||
128 | mutex_unlock(&dsp->mutex); | ||
129 | } | ||
130 | EXPORT_SYMBOL_GPL(sst_fw_free_all); | ||
131 | |||
132 | /* create a new SST generic module from FW template */ | ||
133 | struct sst_module *sst_module_new(struct sst_fw *sst_fw, | ||
134 | struct sst_module_template *template, void *private) | ||
135 | { | ||
136 | struct sst_dsp *dsp = sst_fw->dsp; | ||
137 | struct sst_module *sst_module; | ||
138 | |||
139 | sst_module = kzalloc(sizeof(*sst_module), GFP_KERNEL); | ||
140 | if (sst_module == NULL) | ||
141 | return NULL; | ||
142 | |||
143 | sst_module->id = template->id; | ||
144 | sst_module->dsp = dsp; | ||
145 | sst_module->sst_fw = sst_fw; | ||
146 | |||
147 | memcpy(&sst_module->s, &template->s, sizeof(struct sst_module_data)); | ||
148 | memcpy(&sst_module->p, &template->p, sizeof(struct sst_module_data)); | ||
149 | |||
150 | INIT_LIST_HEAD(&sst_module->block_list); | ||
151 | |||
152 | mutex_lock(&dsp->mutex); | ||
153 | list_add(&sst_module->list, &dsp->module_list); | ||
154 | mutex_unlock(&dsp->mutex); | ||
155 | |||
156 | return sst_module; | ||
157 | } | ||
158 | EXPORT_SYMBOL_GPL(sst_module_new); | ||
159 | |||
160 | /* free firmware module and remove from available list */ | ||
161 | void sst_module_free(struct sst_module *sst_module) | ||
162 | { | ||
163 | struct sst_dsp *dsp = sst_module->dsp; | ||
164 | |||
165 | mutex_lock(&dsp->mutex); | ||
166 | list_del(&sst_module->list); | ||
167 | mutex_unlock(&dsp->mutex); | ||
168 | |||
169 | kfree(sst_module); | ||
170 | } | ||
171 | EXPORT_SYMBOL_GPL(sst_module_free); | ||
172 | |||
173 | static struct sst_mem_block *find_block(struct sst_dsp *dsp, int type, | ||
174 | u32 offset) | ||
175 | { | ||
176 | struct sst_mem_block *block; | ||
177 | |||
178 | list_for_each_entry(block, &dsp->free_block_list, list) { | ||
179 | if (block->type == type && block->offset == offset) | ||
180 | return block; | ||
181 | } | ||
182 | |||
183 | return NULL; | ||
184 | } | ||
185 | |||
186 | static int block_alloc_contiguous(struct sst_module *module, | ||
187 | struct sst_module_data *data, u32 offset, int size) | ||
188 | { | ||
189 | struct list_head tmp = LIST_HEAD_INIT(tmp); | ||
190 | struct sst_dsp *dsp = module->dsp; | ||
191 | struct sst_mem_block *block; | ||
192 | |||
193 | while (size > 0) { | ||
194 | block = find_block(dsp, data->type, offset); | ||
195 | if (!block) { | ||
196 | list_splice(&tmp, &dsp->free_block_list); | ||
197 | return -ENOMEM; | ||
198 | } | ||
199 | |||
200 | list_move_tail(&block->list, &tmp); | ||
201 | offset += block->size; | ||
202 | size -= block->size; | ||
203 | } | ||
204 | |||
205 | list_splice(&tmp, &dsp->used_block_list); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | /* allocate free DSP blocks for module data - callers hold locks */ | ||
210 | static int block_alloc(struct sst_module *module, | ||
211 | struct sst_module_data *data) | ||
212 | { | ||
213 | struct sst_dsp *dsp = module->dsp; | ||
214 | struct sst_mem_block *block, *tmp; | ||
215 | int ret = 0; | ||
216 | |||
217 | if (data->size == 0) | ||
218 | return 0; | ||
219 | |||
220 | /* find first free whole blocks that can hold module */ | ||
221 | list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) { | ||
222 | |||
223 | /* ignore blocks with wrong type */ | ||
224 | if (block->type != data->type) | ||
225 | continue; | ||
226 | |||
227 | if (data->size > block->size) | ||
228 | continue; | ||
229 | |||
230 | data->offset = block->offset; | ||
231 | block->data_type = data->data_type; | ||
232 | block->bytes_used = data->size % block->size; | ||
233 | list_add(&block->module_list, &module->block_list); | ||
234 | list_move(&block->list, &dsp->used_block_list); | ||
235 | dev_dbg(dsp->dev, " *module %d added block %d:%d\n", | ||
236 | module->id, block->type, block->index); | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | /* then find free multiple blocks that can hold module */ | ||
241 | list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) { | ||
242 | |||
243 | /* ignore blocks with wrong type */ | ||
244 | if (block->type != data->type) | ||
245 | continue; | ||
246 | |||
247 | /* do we span > 1 blocks */ | ||
248 | if (data->size > block->size) { | ||
249 | ret = block_alloc_contiguous(module, data, | ||
250 | block->offset + block->size, | ||
251 | data->size - block->size); | ||
252 | if (ret == 0) | ||
253 | return ret; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | /* not enough free block space */ | ||
258 | return -ENOMEM; | ||
259 | } | ||
260 | |||
261 | /* remove module from memory - callers hold locks */ | ||
262 | static void block_module_remove(struct sst_module *module) | ||
263 | { | ||
264 | struct sst_mem_block *block, *tmp; | ||
265 | struct sst_dsp *dsp = module->dsp; | ||
266 | int err; | ||
267 | |||
268 | /* disable each block */ | ||
269 | list_for_each_entry(block, &module->block_list, module_list) { | ||
270 | |||
271 | if (block->ops && block->ops->disable) { | ||
272 | err = block->ops->disable(block); | ||
273 | if (err < 0) | ||
274 | dev_err(dsp->dev, | ||
275 | "error: cant disable block %d:%d\n", | ||
276 | block->type, block->index); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | /* mark each block as free */ | ||
281 | list_for_each_entry_safe(block, tmp, &module->block_list, module_list) { | ||
282 | list_del(&block->module_list); | ||
283 | list_move(&block->list, &dsp->free_block_list); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | /* prepare the memory block to receive data from host - callers hold locks */ | ||
288 | static int block_module_prepare(struct sst_module *module) | ||
289 | { | ||
290 | struct sst_mem_block *block; | ||
291 | int ret = 0; | ||
292 | |||
293 | /* enable each block so that's it'e ready for module P/S data */ | ||
294 | list_for_each_entry(block, &module->block_list, module_list) { | ||
295 | |||
296 | if (block->ops && block->ops->enable) { | ||
297 | ret = block->ops->enable(block); | ||
298 | if (ret < 0) { | ||
299 | dev_err(module->dsp->dev, | ||
300 | "error: cant disable block %d:%d\n", | ||
301 | block->type, block->index); | ||
302 | goto err; | ||
303 | } | ||
304 | } | ||
305 | } | ||
306 | return ret; | ||
307 | |||
308 | err: | ||
309 | list_for_each_entry(block, &module->block_list, module_list) { | ||
310 | if (block->ops && block->ops->disable) | ||
311 | block->ops->disable(block); | ||
312 | } | ||
313 | return ret; | ||
314 | } | ||
315 | |||
316 | /* allocate memory blocks for static module addresses - callers hold locks */ | ||
317 | static int block_alloc_fixed(struct sst_module *module, | ||
318 | struct sst_module_data *data) | ||
319 | { | ||
320 | struct sst_dsp *dsp = module->dsp; | ||
321 | struct sst_mem_block *block, *tmp; | ||
322 | u32 end = data->offset + data->size, block_end; | ||
323 | int err; | ||
324 | |||
325 | /* only IRAM/DRAM blocks are managed */ | ||
326 | if (data->type != SST_MEM_IRAM && data->type != SST_MEM_DRAM) | ||
327 | return 0; | ||
328 | |||
329 | /* are blocks already attached to this module */ | ||
330 | list_for_each_entry_safe(block, tmp, &module->block_list, module_list) { | ||
331 | |||
332 | /* force compacting mem blocks of the same data_type */ | ||
333 | if (block->data_type != data->data_type) | ||
334 | continue; | ||
335 | |||
336 | block_end = block->offset + block->size; | ||
337 | |||
338 | /* find block that holds section */ | ||
339 | if (data->offset >= block->offset && end < block_end) | ||
340 | return 0; | ||
341 | |||
342 | /* does block span more than 1 section */ | ||
343 | if (data->offset >= block->offset && data->offset < block_end) { | ||
344 | |||
345 | err = block_alloc_contiguous(module, data, | ||
346 | block->offset + block->size, | ||
347 | data->size - block->size + data->offset - block->offset); | ||
348 | if (err < 0) | ||
349 | return -ENOMEM; | ||
350 | |||
351 | /* module already owns blocks */ | ||
352 | return 0; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | /* find first free blocks that can hold section in free list */ | ||
357 | list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) { | ||
358 | block_end = block->offset + block->size; | ||
359 | |||
360 | /* find block that holds section */ | ||
361 | if (data->offset >= block->offset && end < block_end) { | ||
362 | |||
363 | /* add block */ | ||
364 | block->data_type = data->data_type; | ||
365 | list_move(&block->list, &dsp->used_block_list); | ||
366 | list_add(&block->module_list, &module->block_list); | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | /* does block span more than 1 section */ | ||
371 | if (data->offset >= block->offset && data->offset < block_end) { | ||
372 | |||
373 | err = block_alloc_contiguous(module, data, | ||
374 | block->offset + block->size, | ||
375 | data->size - block->size); | ||
376 | if (err < 0) | ||
377 | return -ENOMEM; | ||
378 | |||
379 | /* add block */ | ||
380 | block->data_type = data->data_type; | ||
381 | list_move(&block->list, &dsp->used_block_list); | ||
382 | list_add(&block->module_list, &module->block_list); | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | } | ||
387 | |||
388 | return -ENOMEM; | ||
389 | } | ||
390 | |||
391 | /* Load fixed module data into DSP memory blocks */ | ||
392 | int sst_module_insert_fixed_block(struct sst_module *module, | ||
393 | struct sst_module_data *data) | ||
394 | { | ||
395 | struct sst_dsp *dsp = module->dsp; | ||
396 | int ret; | ||
397 | |||
398 | mutex_lock(&dsp->mutex); | ||
399 | |||
400 | /* alloc blocks that includes this section */ | ||
401 | ret = block_alloc_fixed(module, data); | ||
402 | if (ret < 0) { | ||
403 | dev_err(dsp->dev, | ||
404 | "error: no free blocks for section at offset 0x%x size 0x%x\n", | ||
405 | data->offset, data->size); | ||
406 | mutex_unlock(&dsp->mutex); | ||
407 | return -ENOMEM; | ||
408 | } | ||
409 | |||
410 | /* prepare DSP blocks for module copy */ | ||
411 | ret = block_module_prepare(module); | ||
412 | if (ret < 0) { | ||
413 | dev_err(dsp->dev, "error: fw module prepare failed\n"); | ||
414 | goto err; | ||
415 | } | ||
416 | |||
417 | /* copy partial module data to blocks */ | ||
418 | sst_memcpy32(dsp->addr.lpe + data->offset, data->data, data->size); | ||
419 | |||
420 | mutex_unlock(&dsp->mutex); | ||
421 | return ret; | ||
422 | |||
423 | err: | ||
424 | block_module_remove(module); | ||
425 | mutex_unlock(&dsp->mutex); | ||
426 | return ret; | ||
427 | } | ||
428 | EXPORT_SYMBOL_GPL(sst_module_insert_fixed_block); | ||
429 | |||
430 | /* Unload entire module from DSP memory */ | ||
431 | int sst_block_module_remove(struct sst_module *module) | ||
432 | { | ||
433 | struct sst_dsp *dsp = module->dsp; | ||
434 | |||
435 | mutex_lock(&dsp->mutex); | ||
436 | block_module_remove(module); | ||
437 | mutex_unlock(&dsp->mutex); | ||
438 | return 0; | ||
439 | } | ||
440 | EXPORT_SYMBOL_GPL(sst_block_module_remove); | ||
441 | |||
442 | /* register a DSP memory block for use with FW based modules */ | ||
443 | struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset, | ||
444 | u32 size, enum sst_mem_type type, struct sst_block_ops *ops, u32 index, | ||
445 | void *private) | ||
446 | { | ||
447 | struct sst_mem_block *block; | ||
448 | |||
449 | block = kzalloc(sizeof(*block), GFP_KERNEL); | ||
450 | if (block == NULL) | ||
451 | return NULL; | ||
452 | |||
453 | block->offset = offset; | ||
454 | block->size = size; | ||
455 | block->index = index; | ||
456 | block->type = type; | ||
457 | block->dsp = dsp; | ||
458 | block->private = private; | ||
459 | block->ops = ops; | ||
460 | |||
461 | mutex_lock(&dsp->mutex); | ||
462 | list_add(&block->list, &dsp->free_block_list); | ||
463 | mutex_unlock(&dsp->mutex); | ||
464 | |||
465 | return block; | ||
466 | } | ||
467 | EXPORT_SYMBOL_GPL(sst_mem_block_register); | ||
468 | |||
469 | /* unregister all DSP memory blocks */ | ||
470 | void sst_mem_block_unregister_all(struct sst_dsp *dsp) | ||
471 | { | ||
472 | struct sst_mem_block *block, *tmp; | ||
473 | |||
474 | mutex_lock(&dsp->mutex); | ||
475 | |||
476 | /* unregister used blocks */ | ||
477 | list_for_each_entry_safe(block, tmp, &dsp->used_block_list, list) { | ||
478 | list_del(&block->list); | ||
479 | kfree(block); | ||
480 | } | ||
481 | |||
482 | /* unregister free blocks */ | ||
483 | list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) { | ||
484 | list_del(&block->list); | ||
485 | kfree(block); | ||
486 | } | ||
487 | |||
488 | mutex_unlock(&dsp->mutex); | ||
489 | } | ||
490 | EXPORT_SYMBOL_GPL(sst_mem_block_unregister_all); | ||
491 | |||
492 | /* allocate scratch buffer blocks */ | ||
493 | struct sst_module *sst_mem_block_alloc_scratch(struct sst_dsp *dsp) | ||
494 | { | ||
495 | struct sst_module *sst_module, *scratch; | ||
496 | struct sst_mem_block *block, *tmp; | ||
497 | u32 block_size; | ||
498 | int ret = 0; | ||
499 | |||
500 | scratch = kzalloc(sizeof(struct sst_module), GFP_KERNEL); | ||
501 | if (scratch == NULL) | ||
502 | return NULL; | ||
503 | |||
504 | mutex_lock(&dsp->mutex); | ||
505 | |||
506 | /* calculate required scratch size */ | ||
507 | list_for_each_entry(sst_module, &dsp->module_list, list) { | ||
508 | if (scratch->s.size > sst_module->s.size) | ||
509 | scratch->s.size = scratch->s.size; | ||
510 | else | ||
511 | scratch->s.size = sst_module->s.size; | ||
512 | } | ||
513 | |||
514 | dev_dbg(dsp->dev, "scratch buffer required is %d bytes\n", | ||
515 | scratch->s.size); | ||
516 | |||
517 | /* init scratch module */ | ||
518 | scratch->dsp = dsp; | ||
519 | scratch->s.type = SST_MEM_DRAM; | ||
520 | scratch->s.data_type = SST_DATA_S; | ||
521 | INIT_LIST_HEAD(&scratch->block_list); | ||
522 | |||
523 | /* check free blocks before looking at used blocks for space */ | ||
524 | if (!list_empty(&dsp->free_block_list)) | ||
525 | block = list_first_entry(&dsp->free_block_list, | ||
526 | struct sst_mem_block, list); | ||
527 | else | ||
528 | block = list_first_entry(&dsp->used_block_list, | ||
529 | struct sst_mem_block, list); | ||
530 | block_size = block->size; | ||
531 | |||
532 | /* allocate blocks for module scratch buffers */ | ||
533 | dev_dbg(dsp->dev, "allocating scratch blocks\n"); | ||
534 | ret = block_alloc(scratch, &scratch->s); | ||
535 | if (ret < 0) { | ||
536 | dev_err(dsp->dev, "error: can't alloc scratch blocks\n"); | ||
537 | goto err; | ||
538 | } | ||
539 | |||
540 | /* assign the same offset of scratch to each module */ | ||
541 | list_for_each_entry(sst_module, &dsp->module_list, list) | ||
542 | sst_module->s.offset = scratch->s.offset; | ||
543 | |||
544 | mutex_unlock(&dsp->mutex); | ||
545 | return scratch; | ||
546 | |||
547 | err: | ||
548 | list_for_each_entry_safe(block, tmp, &scratch->block_list, module_list) | ||
549 | list_del(&block->module_list); | ||
550 | mutex_unlock(&dsp->mutex); | ||
551 | return NULL; | ||
552 | } | ||
553 | EXPORT_SYMBOL_GPL(sst_mem_block_alloc_scratch); | ||
554 | |||
555 | /* free all scratch blocks */ | ||
556 | void sst_mem_block_free_scratch(struct sst_dsp *dsp, | ||
557 | struct sst_module *scratch) | ||
558 | { | ||
559 | struct sst_mem_block *block, *tmp; | ||
560 | |||
561 | mutex_lock(&dsp->mutex); | ||
562 | |||
563 | list_for_each_entry_safe(block, tmp, &scratch->block_list, module_list) | ||
564 | list_del(&block->module_list); | ||
565 | |||
566 | mutex_unlock(&dsp->mutex); | ||
567 | } | ||
568 | EXPORT_SYMBOL_GPL(sst_mem_block_free_scratch); | ||
569 | |||
570 | /* get a module from it's unique ID */ | ||
571 | struct sst_module *sst_module_get_from_id(struct sst_dsp *dsp, u32 id) | ||
572 | { | ||
573 | struct sst_module *module; | ||
574 | |||
575 | mutex_lock(&dsp->mutex); | ||
576 | |||
577 | list_for_each_entry(module, &dsp->module_list, list) { | ||
578 | if (module->id == id) { | ||
579 | mutex_unlock(&dsp->mutex); | ||
580 | return module; | ||
581 | } | ||
582 | } | ||
583 | |||
584 | mutex_unlock(&dsp->mutex); | ||
585 | return NULL; | ||
586 | } | ||
587 | EXPORT_SYMBOL_GPL(sst_module_get_from_id); | ||
diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c new file mode 100644 index 000000000000..f5ebf36af889 --- /dev/null +++ b/sound/soc/intel/sst-haswell-dsp.c | |||
@@ -0,0 +1,517 @@ | |||
1 | /* | ||
2 | * Intel Haswell SST DSP driver | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/delay.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/export.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/dma-mapping.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/firmware.h> | ||
29 | #include <linux/pm_runtime.h> | ||
30 | |||
31 | #include <linux/acpi.h> | ||
32 | #include <acpi/acpi_bus.h> | ||
33 | |||
34 | #include "sst-dsp.h" | ||
35 | #include "sst-dsp-priv.h" | ||
36 | #include "sst-haswell-ipc.h" | ||
37 | |||
38 | #include <trace/events/hswadsp.h> | ||
39 | |||
40 | #define SST_HSW_FW_SIGNATURE_SIZE 4 | ||
41 | #define SST_HSW_FW_SIGN "$SST" | ||
42 | #define SST_HSW_FW_LIB_SIGN "$LIB" | ||
43 | |||
44 | #define SST_WPT_SHIM_OFFSET 0xFB000 | ||
45 | #define SST_LP_SHIM_OFFSET 0xE7000 | ||
46 | #define SST_WPT_IRAM_OFFSET 0xA0000 | ||
47 | #define SST_LP_IRAM_OFFSET 0x80000 | ||
48 | |||
49 | #define SST_SHIM_PM_REG 0x84 | ||
50 | |||
51 | #define SST_HSW_IRAM 1 | ||
52 | #define SST_HSW_DRAM 2 | ||
53 | #define SST_HSW_REGS 3 | ||
54 | |||
55 | struct dma_block_info { | ||
56 | __le32 type; /* IRAM/DRAM */ | ||
57 | __le32 size; /* Bytes */ | ||
58 | __le32 ram_offset; /* Offset in I/DRAM */ | ||
59 | __le32 rsvd; /* Reserved field */ | ||
60 | } __attribute__((packed)); | ||
61 | |||
62 | struct fw_module_info { | ||
63 | __le32 persistent_size; | ||
64 | __le32 scratch_size; | ||
65 | } __attribute__((packed)); | ||
66 | |||
67 | struct fw_header { | ||
68 | unsigned char signature[SST_HSW_FW_SIGNATURE_SIZE]; /* FW signature */ | ||
69 | __le32 file_size; /* size of fw minus this header */ | ||
70 | __le32 modules; /* # of modules */ | ||
71 | __le32 file_format; /* version of header format */ | ||
72 | __le32 reserved[4]; | ||
73 | } __attribute__((packed)); | ||
74 | |||
75 | struct fw_module_header { | ||
76 | unsigned char signature[SST_HSW_FW_SIGNATURE_SIZE]; /* module signature */ | ||
77 | __le32 mod_size; /* size of module */ | ||
78 | __le32 blocks; /* # of blocks */ | ||
79 | __le16 padding; | ||
80 | __le16 type; /* codec type, pp lib */ | ||
81 | __le32 entry_point; | ||
82 | struct fw_module_info info; | ||
83 | } __attribute__((packed)); | ||
84 | |||
85 | static void hsw_free(struct sst_dsp *sst); | ||
86 | |||
87 | static int hsw_parse_module(struct sst_dsp *dsp, struct sst_fw *fw, | ||
88 | struct fw_module_header *module) | ||
89 | { | ||
90 | struct dma_block_info *block; | ||
91 | struct sst_module *mod; | ||
92 | struct sst_module_data block_data; | ||
93 | struct sst_module_template template; | ||
94 | int count; | ||
95 | void __iomem *ram; | ||
96 | |||
97 | /* TODO: allowed module types need to be configurable */ | ||
98 | if (module->type != SST_HSW_MODULE_BASE_FW | ||
99 | && module->type != SST_HSW_MODULE_PCM_SYSTEM | ||
100 | && module->type != SST_HSW_MODULE_PCM | ||
101 | && module->type != SST_HSW_MODULE_PCM_REFERENCE | ||
102 | && module->type != SST_HSW_MODULE_PCM_CAPTURE | ||
103 | && module->type != SST_HSW_MODULE_LPAL) | ||
104 | return 0; | ||
105 | |||
106 | dev_dbg(dsp->dev, "new module sign 0x%s size 0x%x blocks 0x%x type 0x%x\n", | ||
107 | module->signature, module->mod_size, | ||
108 | module->blocks, module->type); | ||
109 | dev_dbg(dsp->dev, " entrypoint 0x%x\n", module->entry_point); | ||
110 | dev_dbg(dsp->dev, " persistent 0x%x scratch 0x%x\n", | ||
111 | module->info.persistent_size, module->info.scratch_size); | ||
112 | |||
113 | memset(&template, 0, sizeof(template)); | ||
114 | template.id = module->type; | ||
115 | template.entry = module->entry_point; | ||
116 | template.p.size = module->info.persistent_size; | ||
117 | template.p.type = SST_MEM_DRAM; | ||
118 | template.p.data_type = SST_DATA_P; | ||
119 | template.s.size = module->info.scratch_size; | ||
120 | template.s.type = SST_MEM_DRAM; | ||
121 | template.s.data_type = SST_DATA_S; | ||
122 | |||
123 | mod = sst_module_new(fw, &template, NULL); | ||
124 | if (mod == NULL) | ||
125 | return -ENOMEM; | ||
126 | |||
127 | block = (void *)module + sizeof(*module); | ||
128 | |||
129 | for (count = 0; count < module->blocks; count++) { | ||
130 | |||
131 | if (block->size <= 0) { | ||
132 | dev_err(dsp->dev, | ||
133 | "error: block %d size invalid\n", count); | ||
134 | sst_module_free(mod); | ||
135 | return -EINVAL; | ||
136 | } | ||
137 | |||
138 | switch (block->type) { | ||
139 | case SST_HSW_IRAM: | ||
140 | ram = dsp->addr.lpe; | ||
141 | block_data.offset = | ||
142 | block->ram_offset + dsp->addr.iram_offset; | ||
143 | block_data.type = SST_MEM_IRAM; | ||
144 | break; | ||
145 | case SST_HSW_DRAM: | ||
146 | ram = dsp->addr.lpe; | ||
147 | block_data.offset = block->ram_offset; | ||
148 | block_data.type = SST_MEM_DRAM; | ||
149 | break; | ||
150 | default: | ||
151 | dev_err(dsp->dev, "error: bad type 0x%x for block 0x%x\n", | ||
152 | block->type, count); | ||
153 | sst_module_free(mod); | ||
154 | return -EINVAL; | ||
155 | } | ||
156 | |||
157 | block_data.size = block->size; | ||
158 | block_data.data_type = SST_DATA_M; | ||
159 | block_data.data = (void *)block + sizeof(*block); | ||
160 | block_data.data_offset = block_data.data - fw->dma_buf; | ||
161 | |||
162 | dev_dbg(dsp->dev, "copy firmware block %d type 0x%x " | ||
163 | "size 0x%x ==> ram %p offset 0x%x\n", | ||
164 | count, block->type, block->size, ram, | ||
165 | block->ram_offset); | ||
166 | |||
167 | sst_module_insert_fixed_block(mod, &block_data); | ||
168 | |||
169 | block = (void *)block + sizeof(*block) + block->size; | ||
170 | } | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int hsw_parse_fw_image(struct sst_fw *sst_fw) | ||
175 | { | ||
176 | struct fw_header *header; | ||
177 | struct sst_module *scratch; | ||
178 | struct fw_module_header *module; | ||
179 | struct sst_dsp *dsp = sst_fw->dsp; | ||
180 | struct sst_hsw *hsw = sst_fw->private; | ||
181 | int ret, count; | ||
182 | |||
183 | /* Read the header information from the data pointer */ | ||
184 | header = (struct fw_header *)sst_fw->dma_buf; | ||
185 | |||
186 | /* verify FW */ | ||
187 | if ((strncmp(header->signature, SST_HSW_FW_SIGN, 4) != 0) || | ||
188 | (sst_fw->size != header->file_size + sizeof(*header))) { | ||
189 | dev_err(dsp->dev, "error: invalid fw sign/filesize mismatch\n"); | ||
190 | return -EINVAL; | ||
191 | } | ||
192 | |||
193 | dev_dbg(dsp->dev, "header size=0x%x modules=0x%x fmt=0x%x size=%zu\n", | ||
194 | header->file_size, header->modules, | ||
195 | header->file_format, sizeof(*header)); | ||
196 | |||
197 | /* parse each module */ | ||
198 | module = (void *)sst_fw->dma_buf + sizeof(*header); | ||
199 | for (count = 0; count < header->modules; count++) { | ||
200 | |||
201 | /* module */ | ||
202 | ret = hsw_parse_module(dsp, sst_fw, module); | ||
203 | if (ret < 0) { | ||
204 | dev_err(dsp->dev, "error: invalid module %d\n", count); | ||
205 | return ret; | ||
206 | } | ||
207 | module = (void *)module + sizeof(*module) + module->mod_size; | ||
208 | } | ||
209 | |||
210 | /* allocate persistent/scratch mem regions */ | ||
211 | scratch = sst_mem_block_alloc_scratch(dsp); | ||
212 | if (scratch == NULL) | ||
213 | return -ENOMEM; | ||
214 | |||
215 | sst_hsw_set_scratch_module(hsw, scratch); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static irqreturn_t hsw_irq(int irq, void *context) | ||
221 | { | ||
222 | struct sst_dsp *sst = (struct sst_dsp *) context; | ||
223 | u32 isr; | ||
224 | int ret = IRQ_NONE; | ||
225 | |||
226 | spin_lock(&sst->spinlock); | ||
227 | |||
228 | /* Interrupt arrived, check src */ | ||
229 | isr = sst_dsp_shim_read_unlocked(sst, SST_ISRX); | ||
230 | if (isr & SST_ISRX_DONE) { | ||
231 | trace_sst_irq_done(isr, | ||
232 | sst_dsp_shim_read_unlocked(sst, SST_IMRX)); | ||
233 | |||
234 | /* Mask Done interrupt before return */ | ||
235 | sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, | ||
236 | SST_IMRX_DONE, SST_IMRX_DONE); | ||
237 | ret = IRQ_WAKE_THREAD; | ||
238 | } | ||
239 | |||
240 | if (isr & SST_ISRX_BUSY) { | ||
241 | trace_sst_irq_busy(isr, | ||
242 | sst_dsp_shim_read_unlocked(sst, SST_IMRX)); | ||
243 | |||
244 | /* Mask Busy interrupt before return */ | ||
245 | sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, | ||
246 | SST_IMRX_BUSY, SST_IMRX_BUSY); | ||
247 | ret = IRQ_WAKE_THREAD; | ||
248 | } | ||
249 | |||
250 | spin_unlock(&sst->spinlock); | ||
251 | return ret; | ||
252 | } | ||
253 | |||
254 | static void hsw_boot(struct sst_dsp *sst) | ||
255 | { | ||
256 | /* select SSP1 19.2MHz base clock, SSP clock 0, turn off Low Power Clock */ | ||
257 | sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, | ||
258 | SST_CSR_S1IOCS | SST_CSR_SBCS1 | SST_CSR_LPCS, 0x0); | ||
259 | |||
260 | /* stall DSP core, set clk to 192/96Mhz */ | ||
261 | sst_dsp_shim_update_bits_unlocked(sst, | ||
262 | SST_CSR, SST_CSR_STALL | SST_CSR_DCS_MASK, | ||
263 | SST_CSR_STALL | SST_CSR_DCS(4)); | ||
264 | |||
265 | /* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */ | ||
266 | sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL, | ||
267 | SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0, | ||
268 | SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0); | ||
269 | |||
270 | /* disable DMA finish function for SSP0 & SSP1 */ | ||
271 | sst_dsp_shim_update_bits_unlocked(sst, SST_CSR2, SST_CSR2_SDFD_SSP1, | ||
272 | SST_CSR2_SDFD_SSP1); | ||
273 | |||
274 | /* enable DMA engine 0,1 all channels to access host memory */ | ||
275 | sst_dsp_shim_update_bits_unlocked(sst, SST_HDMC, | ||
276 | SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff), | ||
277 | SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff)); | ||
278 | |||
279 | /* disable all clock gating */ | ||
280 | writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2); | ||
281 | |||
282 | /* set DSP to RUN */ | ||
283 | sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, SST_CSR_STALL, 0x0); | ||
284 | } | ||
285 | |||
286 | static void hsw_reset(struct sst_dsp *sst) | ||
287 | { | ||
288 | /* put DSP into reset and stall */ | ||
289 | sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, | ||
290 | SST_CSR_RST | SST_CSR_STALL, SST_CSR_RST | SST_CSR_STALL); | ||
291 | |||
292 | /* keep in reset for 10ms */ | ||
293 | mdelay(10); | ||
294 | |||
295 | /* take DSP out of reset and keep stalled for FW loading */ | ||
296 | sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, | ||
297 | SST_CSR_RST | SST_CSR_STALL, SST_CSR_STALL); | ||
298 | } | ||
299 | |||
300 | struct sst_adsp_memregion { | ||
301 | u32 start; | ||
302 | u32 end; | ||
303 | int blocks; | ||
304 | enum sst_mem_type type; | ||
305 | }; | ||
306 | |||
307 | /* lynx point ADSP mem regions */ | ||
308 | static const struct sst_adsp_memregion lp_region[] = { | ||
309 | {0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ | ||
310 | {0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */ | ||
311 | {0x80000, 0xE0000, 12, SST_MEM_IRAM}, /* I-SRAM - 12 * 32kB */ | ||
312 | }; | ||
313 | |||
314 | /* wild cat point ADSP mem regions */ | ||
315 | static const struct sst_adsp_memregion wpt_region[] = { | ||
316 | {0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ | ||
317 | {0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */ | ||
318 | {0x80000, 0xA0000, 4, SST_MEM_DRAM}, /* D-SRAM2 - 4 * 32kB */ | ||
319 | {0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */ | ||
320 | }; | ||
321 | |||
322 | static int hsw_acpi_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata) | ||
323 | { | ||
324 | /* ADSP DRAM & IRAM */ | ||
325 | sst->addr.lpe_base = pdata->lpe_base; | ||
326 | sst->addr.lpe = ioremap(pdata->lpe_base, pdata->lpe_size); | ||
327 | if (!sst->addr.lpe) | ||
328 | return -ENODEV; | ||
329 | |||
330 | /* ADSP PCI MMIO config space */ | ||
331 | sst->addr.pci_cfg = ioremap(pdata->pcicfg_base, pdata->pcicfg_size); | ||
332 | if (!sst->addr.pci_cfg) { | ||
333 | iounmap(sst->addr.lpe); | ||
334 | return -ENODEV; | ||
335 | } | ||
336 | |||
337 | /* SST Shim */ | ||
338 | sst->addr.shim = sst->addr.lpe + sst->addr.shim_offset; | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static u32 hsw_block_get_bit(struct sst_mem_block *block) | ||
343 | { | ||
344 | u32 bit = 0, shift = 0; | ||
345 | |||
346 | switch (block->type) { | ||
347 | case SST_MEM_DRAM: | ||
348 | shift = 16; | ||
349 | break; | ||
350 | case SST_MEM_IRAM: | ||
351 | shift = 6; | ||
352 | break; | ||
353 | default: | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | bit = 1 << (block->index + shift); | ||
358 | |||
359 | return bit; | ||
360 | } | ||
361 | |||
362 | /* enable 32kB memory block - locks held by caller */ | ||
363 | static int hsw_block_enable(struct sst_mem_block *block) | ||
364 | { | ||
365 | struct sst_dsp *sst = block->dsp; | ||
366 | u32 bit, val; | ||
367 | |||
368 | if (block->users++ > 0) | ||
369 | return 0; | ||
370 | |||
371 | dev_dbg(block->dsp->dev, " enabled block %d:%d at offset 0x%x\n", | ||
372 | block->type, block->index, block->offset); | ||
373 | |||
374 | val = readl(sst->addr.pci_cfg + SST_VDRTCTL0); | ||
375 | bit = hsw_block_get_bit(block); | ||
376 | writel(val & ~bit, sst->addr.pci_cfg + SST_VDRTCTL0); | ||
377 | |||
378 | /* wait 18 DSP clock ticks */ | ||
379 | udelay(10); | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | /* disable 32kB memory block - locks held by caller */ | ||
385 | static int hsw_block_disable(struct sst_mem_block *block) | ||
386 | { | ||
387 | struct sst_dsp *sst = block->dsp; | ||
388 | u32 bit, val; | ||
389 | |||
390 | if (--block->users > 0) | ||
391 | return 0; | ||
392 | |||
393 | dev_dbg(block->dsp->dev, " disabled block %d:%d at offset 0x%x\n", | ||
394 | block->type, block->index, block->offset); | ||
395 | |||
396 | val = readl(sst->addr.pci_cfg + SST_VDRTCTL0); | ||
397 | bit = hsw_block_get_bit(block); | ||
398 | writel(val | bit, sst->addr.pci_cfg + SST_VDRTCTL0); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static struct sst_block_ops sst_hsw_ops = { | ||
404 | .enable = hsw_block_enable, | ||
405 | .disable = hsw_block_disable, | ||
406 | }; | ||
407 | |||
408 | static int hsw_enable_shim(struct sst_dsp *sst) | ||
409 | { | ||
410 | int tries = 10; | ||
411 | u32 reg; | ||
412 | |||
413 | /* enable shim */ | ||
414 | reg = readl(sst->addr.pci_cfg + SST_SHIM_PM_REG); | ||
415 | writel(reg & ~0x3, sst->addr.pci_cfg + SST_SHIM_PM_REG); | ||
416 | |||
417 | /* check that ADSP shim is enabled */ | ||
418 | while (tries--) { | ||
419 | reg = sst_dsp_shim_read_unlocked(sst, SST_CSR); | ||
420 | if (reg != 0xffffffff) | ||
421 | return 0; | ||
422 | |||
423 | msleep(1); | ||
424 | } | ||
425 | |||
426 | return -ENODEV; | ||
427 | } | ||
428 | |||
429 | static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) | ||
430 | { | ||
431 | const struct sst_adsp_memregion *region; | ||
432 | struct device *dev; | ||
433 | int ret = -ENODEV, i, j, region_count; | ||
434 | u32 offset, size; | ||
435 | |||
436 | dev = sst->dev; | ||
437 | |||
438 | switch (sst->id) { | ||
439 | case SST_DEV_ID_LYNX_POINT: | ||
440 | region = lp_region; | ||
441 | region_count = ARRAY_SIZE(lp_region); | ||
442 | sst->addr.iram_offset = SST_LP_IRAM_OFFSET; | ||
443 | sst->addr.shim_offset = SST_LP_SHIM_OFFSET; | ||
444 | break; | ||
445 | case SST_DEV_ID_WILDCAT_POINT: | ||
446 | region = wpt_region; | ||
447 | region_count = ARRAY_SIZE(wpt_region); | ||
448 | sst->addr.iram_offset = SST_WPT_IRAM_OFFSET; | ||
449 | sst->addr.shim_offset = SST_WPT_SHIM_OFFSET; | ||
450 | break; | ||
451 | default: | ||
452 | dev_err(dev, "error: failed to get mem resources\n"); | ||
453 | return ret; | ||
454 | } | ||
455 | |||
456 | ret = hsw_acpi_resource_map(sst, pdata); | ||
457 | if (ret < 0) { | ||
458 | dev_err(dev, "error: failed to map resources\n"); | ||
459 | return ret; | ||
460 | } | ||
461 | |||
462 | /* enable the DSP SHIM */ | ||
463 | ret = hsw_enable_shim(sst); | ||
464 | if (ret < 0) { | ||
465 | dev_err(dev, "error: failed to set DSP D0 and reset SHIM\n"); | ||
466 | return ret; | ||
467 | } | ||
468 | |||
469 | ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); | ||
470 | if (ret) | ||
471 | return ret; | ||
472 | |||
473 | /* Enable Interrupt from both sides */ | ||
474 | sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, 0x3, 0x0); | ||
475 | sst_dsp_shim_update_bits_unlocked(sst, SST_IMRD, | ||
476 | (0x3 | 0x1 << 16 | 0x3 << 21), 0x0); | ||
477 | |||
478 | /* register DSP memory blocks - ideally we should get this from ACPI */ | ||
479 | for (i = 0; i < region_count; i++) { | ||
480 | offset = region[i].start; | ||
481 | size = (region[i].end - region[i].start) / region[i].blocks; | ||
482 | |||
483 | /* register individual memory blocks */ | ||
484 | for (j = 0; j < region[i].blocks; j++) { | ||
485 | sst_mem_block_register(sst, offset, size, | ||
486 | region[i].type, &sst_hsw_ops, j, sst); | ||
487 | offset += size; | ||
488 | } | ||
489 | } | ||
490 | |||
491 | /* set default power gating mask */ | ||
492 | writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL0); | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static void hsw_free(struct sst_dsp *sst) | ||
498 | { | ||
499 | sst_mem_block_unregister_all(sst); | ||
500 | iounmap(sst->addr.lpe); | ||
501 | iounmap(sst->addr.pci_cfg); | ||
502 | } | ||
503 | |||
504 | struct sst_ops haswell_ops = { | ||
505 | .reset = hsw_reset, | ||
506 | .boot = hsw_boot, | ||
507 | .write = sst_shim32_write, | ||
508 | .read = sst_shim32_read, | ||
509 | .write64 = sst_shim32_write64, | ||
510 | .read64 = sst_shim32_read64, | ||
511 | .ram_read = sst_memcpy_fromio_32, | ||
512 | .ram_write = sst_memcpy_toio_32, | ||
513 | .irq_handler = hsw_irq, | ||
514 | .init = hsw_init, | ||
515 | .free = hsw_free, | ||
516 | .parse_fw = hsw_parse_fw_image, | ||
517 | }; | ||
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c new file mode 100644 index 000000000000..f46bb4ddde6f --- /dev/null +++ b/sound/soc/intel/sst-haswell-ipc.c | |||
@@ -0,0 +1,1785 @@ | |||
1 | /* | ||
2 | * Intel SST Haswell/Broadwell IPC Support | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/types.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/list.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/wait.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | #include <linux/export.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <linux/list.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/kthread.h> | ||
31 | #include <linux/firmware.h> | ||
32 | #include <linux/dma-mapping.h> | ||
33 | #include <linux/debugfs.h> | ||
34 | |||
35 | #include "sst-haswell-ipc.h" | ||
36 | #include "sst-dsp.h" | ||
37 | #include "sst-dsp-priv.h" | ||
38 | |||
39 | /* Global Message - Generic */ | ||
40 | #define IPC_GLB_TYPE_SHIFT 24 | ||
41 | #define IPC_GLB_TYPE_MASK (0x1f << IPC_GLB_TYPE_SHIFT) | ||
42 | #define IPC_GLB_TYPE(x) (x << IPC_GLB_TYPE_SHIFT) | ||
43 | |||
44 | /* Global Message - Reply */ | ||
45 | #define IPC_GLB_REPLY_SHIFT 0 | ||
46 | #define IPC_GLB_REPLY_MASK (0x1f << IPC_GLB_REPLY_SHIFT) | ||
47 | #define IPC_GLB_REPLY_TYPE(x) (x << IPC_GLB_REPLY_TYPE_SHIFT) | ||
48 | |||
49 | /* Stream Message - Generic */ | ||
50 | #define IPC_STR_TYPE_SHIFT 20 | ||
51 | #define IPC_STR_TYPE_MASK (0xf << IPC_STR_TYPE_SHIFT) | ||
52 | #define IPC_STR_TYPE(x) (x << IPC_STR_TYPE_SHIFT) | ||
53 | #define IPC_STR_ID_SHIFT 16 | ||
54 | #define IPC_STR_ID_MASK (0xf << IPC_STR_ID_SHIFT) | ||
55 | #define IPC_STR_ID(x) (x << IPC_STR_ID_SHIFT) | ||
56 | |||
57 | /* Stream Message - Reply */ | ||
58 | #define IPC_STR_REPLY_SHIFT 0 | ||
59 | #define IPC_STR_REPLY_MASK (0x1f << IPC_STR_REPLY_SHIFT) | ||
60 | |||
61 | /* Stream Stage Message - Generic */ | ||
62 | #define IPC_STG_TYPE_SHIFT 12 | ||
63 | #define IPC_STG_TYPE_MASK (0xf << IPC_STG_TYPE_SHIFT) | ||
64 | #define IPC_STG_TYPE(x) (x << IPC_STG_TYPE_SHIFT) | ||
65 | #define IPC_STG_ID_SHIFT 10 | ||
66 | #define IPC_STG_ID_MASK (0x3 << IPC_STG_ID_SHIFT) | ||
67 | #define IPC_STG_ID(x) (x << IPC_STG_ID_SHIFT) | ||
68 | |||
69 | /* Stream Stage Message - Reply */ | ||
70 | #define IPC_STG_REPLY_SHIFT 0 | ||
71 | #define IPC_STG_REPLY_MASK (0x1f << IPC_STG_REPLY_SHIFT) | ||
72 | |||
73 | /* Debug Log Message - Generic */ | ||
74 | #define IPC_LOG_OP_SHIFT 20 | ||
75 | #define IPC_LOG_OP_MASK (0xf << IPC_LOG_OP_SHIFT) | ||
76 | #define IPC_LOG_OP_TYPE(x) (x << IPC_LOG_OP_SHIFT) | ||
77 | #define IPC_LOG_ID_SHIFT 16 | ||
78 | #define IPC_LOG_ID_MASK (0xf << IPC_LOG_ID_SHIFT) | ||
79 | #define IPC_LOG_ID(x) (x << IPC_LOG_ID_SHIFT) | ||
80 | |||
81 | /* IPC message timeout (msecs) */ | ||
82 | #define IPC_TIMEOUT_MSECS 300 | ||
83 | #define IPC_BOOT_MSECS 200 | ||
84 | #define IPC_MSG_WAIT 0 | ||
85 | #define IPC_MSG_NOWAIT 1 | ||
86 | |||
87 | /* Firmware Ready Message */ | ||
88 | #define IPC_FW_READY (0x1 << 29) | ||
89 | #define IPC_STATUS_MASK (0x3 << 30) | ||
90 | |||
91 | #define IPC_EMPTY_LIST_SIZE 8 | ||
92 | #define IPC_MAX_STREAMS 4 | ||
93 | |||
94 | /* Mailbox */ | ||
95 | #define IPC_MAX_MAILBOX_BYTES 256 | ||
96 | |||
97 | /* Global Message - Types and Replies */ | ||
98 | enum ipc_glb_type { | ||
99 | IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */ | ||
100 | IPC_GLB_PERFORMANCE_MONITOR = 1, /* Performance monitoring actions */ | ||
101 | IPC_GLB_ALLOCATE_STREAM = 3, /* Request to allocate new stream */ | ||
102 | IPC_GLB_FREE_STREAM = 4, /* Request to free stream */ | ||
103 | IPC_GLB_GET_FW_CAPABILITIES = 5, /* Retrieves firmware capabilities */ | ||
104 | IPC_GLB_STREAM_MESSAGE = 6, /* Message directed to stream or its stages */ | ||
105 | /* Request to store firmware context during D0->D3 transition */ | ||
106 | IPC_GLB_REQUEST_DUMP = 7, | ||
107 | /* Request to restore firmware context during D3->D0 transition */ | ||
108 | IPC_GLB_RESTORE_CONTEXT = 8, | ||
109 | IPC_GLB_GET_DEVICE_FORMATS = 9, /* Set device format */ | ||
110 | IPC_GLB_SET_DEVICE_FORMATS = 10, /* Get device format */ | ||
111 | IPC_GLB_SHORT_REPLY = 11, | ||
112 | IPC_GLB_ENTER_DX_STATE = 12, | ||
113 | IPC_GLB_GET_MIXER_STREAM_INFO = 13, /* Request mixer stream params */ | ||
114 | IPC_GLB_DEBUG_LOG_MESSAGE = 14, /* Message to or from the debug logger. */ | ||
115 | IPC_GLB_REQUEST_TRANSFER = 16, /* < Request Transfer for host */ | ||
116 | IPC_GLB_MAX_IPC_MESSAGE_TYPE = 17, /* Maximum message number */ | ||
117 | }; | ||
118 | |||
119 | enum ipc_glb_reply { | ||
120 | IPC_GLB_REPLY_SUCCESS = 0, /* The operation was successful. */ | ||
121 | IPC_GLB_REPLY_ERROR_INVALID_PARAM = 1, /* Invalid parameter was passed. */ | ||
122 | IPC_GLB_REPLY_UNKNOWN_MESSAGE_TYPE = 2, /* Uknown message type was resceived. */ | ||
123 | IPC_GLB_REPLY_OUT_OF_RESOURCES = 3, /* No resources to satisfy the request. */ | ||
124 | IPC_GLB_REPLY_BUSY = 4, /* The system or resource is busy. */ | ||
125 | IPC_GLB_REPLY_PENDING = 5, /* The action was scheduled for processing. */ | ||
126 | IPC_GLB_REPLY_FAILURE = 6, /* Critical error happened. */ | ||
127 | IPC_GLB_REPLY_INVALID_REQUEST = 7, /* Request can not be completed. */ | ||
128 | IPC_GLB_REPLY_STAGE_UNINITIALIZED = 8, /* Processing stage was uninitialized. */ | ||
129 | IPC_GLB_REPLY_NOT_FOUND = 9, /* Required resource can not be found. */ | ||
130 | IPC_GLB_REPLY_SOURCE_NOT_STARTED = 10, /* Source was not started. */ | ||
131 | }; | ||
132 | |||
133 | /* Stream Message - Types */ | ||
134 | enum ipc_str_operation { | ||
135 | IPC_STR_RESET = 0, | ||
136 | IPC_STR_PAUSE = 1, | ||
137 | IPC_STR_RESUME = 2, | ||
138 | IPC_STR_STAGE_MESSAGE = 3, | ||
139 | IPC_STR_NOTIFICATION = 4, | ||
140 | IPC_STR_MAX_MESSAGE | ||
141 | }; | ||
142 | |||
143 | /* Stream Stage Message Types */ | ||
144 | enum ipc_stg_operation { | ||
145 | IPC_STG_GET_VOLUME = 0, | ||
146 | IPC_STG_SET_VOLUME, | ||
147 | IPC_STG_SET_WRITE_POSITION, | ||
148 | IPC_STG_SET_FX_ENABLE, | ||
149 | IPC_STG_SET_FX_DISABLE, | ||
150 | IPC_STG_SET_FX_GET_PARAM, | ||
151 | IPC_STG_SET_FX_SET_PARAM, | ||
152 | IPC_STG_SET_FX_GET_INFO, | ||
153 | IPC_STG_MUTE_LOOPBACK, | ||
154 | IPC_STG_MAX_MESSAGE | ||
155 | }; | ||
156 | |||
157 | /* Stream Stage Message Types For Notification*/ | ||
158 | enum ipc_stg_operation_notify { | ||
159 | IPC_POSITION_CHANGED = 0, | ||
160 | IPC_STG_GLITCH, | ||
161 | IPC_STG_MAX_NOTIFY | ||
162 | }; | ||
163 | |||
164 | enum ipc_glitch_type { | ||
165 | IPC_GLITCH_UNDERRUN = 1, | ||
166 | IPC_GLITCH_DECODER_ERROR, | ||
167 | IPC_GLITCH_DOUBLED_WRITE_POS, | ||
168 | IPC_GLITCH_MAX | ||
169 | }; | ||
170 | |||
171 | /* Debug Control */ | ||
172 | enum ipc_debug_operation { | ||
173 | IPC_DEBUG_ENABLE_LOG = 0, | ||
174 | IPC_DEBUG_DISABLE_LOG = 1, | ||
175 | IPC_DEBUG_REQUEST_LOG_DUMP = 2, | ||
176 | IPC_DEBUG_NOTIFY_LOG_DUMP = 3, | ||
177 | IPC_DEBUG_MAX_DEBUG_LOG | ||
178 | }; | ||
179 | |||
180 | /* Firmware Ready */ | ||
181 | struct sst_hsw_ipc_fw_ready { | ||
182 | u32 inbox_offset; | ||
183 | u32 outbox_offset; | ||
184 | u32 inbox_size; | ||
185 | u32 outbox_size; | ||
186 | u32 fw_info_size; | ||
187 | u8 fw_info[1]; | ||
188 | } __attribute__((packed)); | ||
189 | |||
190 | struct ipc_message { | ||
191 | struct list_head list; | ||
192 | u32 header; | ||
193 | |||
194 | /* direction wrt host CPU */ | ||
195 | char tx_data[IPC_MAX_MAILBOX_BYTES]; | ||
196 | size_t tx_size; | ||
197 | char rx_data[IPC_MAX_MAILBOX_BYTES]; | ||
198 | size_t rx_size; | ||
199 | |||
200 | wait_queue_head_t waitq; | ||
201 | bool pending; | ||
202 | bool complete; | ||
203 | bool wait; | ||
204 | int errno; | ||
205 | }; | ||
206 | |||
207 | struct sst_hsw_stream; | ||
208 | struct sst_hsw; | ||
209 | |||
210 | /* Stream infomation */ | ||
211 | struct sst_hsw_stream { | ||
212 | /* configuration */ | ||
213 | struct sst_hsw_ipc_stream_alloc_req request; | ||
214 | struct sst_hsw_ipc_stream_alloc_reply reply; | ||
215 | struct sst_hsw_ipc_stream_free_req free_req; | ||
216 | |||
217 | /* Mixer info */ | ||
218 | u32 mute_volume[SST_HSW_NO_CHANNELS]; | ||
219 | u32 mute[SST_HSW_NO_CHANNELS]; | ||
220 | |||
221 | /* runtime info */ | ||
222 | struct sst_hsw *hsw; | ||
223 | int host_id; | ||
224 | bool commited; | ||
225 | bool running; | ||
226 | |||
227 | /* Notification work */ | ||
228 | struct work_struct notify_work; | ||
229 | u32 header; | ||
230 | |||
231 | /* Position info from DSP */ | ||
232 | struct sst_hsw_ipc_stream_set_position wpos; | ||
233 | struct sst_hsw_ipc_stream_get_position rpos; | ||
234 | struct sst_hsw_ipc_stream_glitch_position glitch; | ||
235 | |||
236 | /* Volume info */ | ||
237 | struct sst_hsw_ipc_volume_req vol_req; | ||
238 | |||
239 | /* driver callback */ | ||
240 | u32 (*notify_position)(struct sst_hsw_stream *stream, void *data); | ||
241 | void *pdata; | ||
242 | |||
243 | struct list_head node; | ||
244 | }; | ||
245 | |||
246 | /* FW log ring information */ | ||
247 | struct sst_hsw_log_stream { | ||
248 | dma_addr_t dma_addr; | ||
249 | unsigned char *dma_area; | ||
250 | unsigned char *ring_descr; | ||
251 | int pages; | ||
252 | int size; | ||
253 | |||
254 | /* Notification work */ | ||
255 | struct work_struct notify_work; | ||
256 | wait_queue_head_t readers_wait_q; | ||
257 | struct mutex rw_mutex; | ||
258 | |||
259 | u32 last_pos; | ||
260 | u32 curr_pos; | ||
261 | u32 reader_pos; | ||
262 | |||
263 | /* fw log config */ | ||
264 | u32 config[SST_HSW_FW_LOG_CONFIG_DWORDS]; | ||
265 | |||
266 | struct sst_hsw *hsw; | ||
267 | }; | ||
268 | |||
269 | /* SST Haswell IPC data */ | ||
270 | struct sst_hsw { | ||
271 | struct device *dev; | ||
272 | struct sst_dsp *dsp; | ||
273 | struct platform_device *pdev_pcm; | ||
274 | |||
275 | /* FW config */ | ||
276 | struct sst_hsw_ipc_fw_ready fw_ready; | ||
277 | struct sst_hsw_ipc_fw_version version; | ||
278 | struct sst_module *scratch; | ||
279 | bool fw_done; | ||
280 | |||
281 | /* stream */ | ||
282 | struct list_head stream_list; | ||
283 | |||
284 | /* global mixer */ | ||
285 | struct sst_hsw_ipc_stream_info_reply mixer_info; | ||
286 | enum sst_hsw_volume_curve curve_type; | ||
287 | u32 curve_duration; | ||
288 | u32 mute[SST_HSW_NO_CHANNELS]; | ||
289 | u32 mute_volume[SST_HSW_NO_CHANNELS]; | ||
290 | |||
291 | /* DX */ | ||
292 | struct sst_hsw_ipc_dx_reply dx; | ||
293 | |||
294 | /* boot */ | ||
295 | wait_queue_head_t boot_wait; | ||
296 | bool boot_complete; | ||
297 | bool shutdown; | ||
298 | |||
299 | /* IPC messaging */ | ||
300 | struct list_head tx_list; | ||
301 | struct list_head rx_list; | ||
302 | struct list_head empty_list; | ||
303 | wait_queue_head_t wait_txq; | ||
304 | struct task_struct *tx_thread; | ||
305 | struct kthread_worker kworker; | ||
306 | struct kthread_work kwork; | ||
307 | bool pending; | ||
308 | struct ipc_message *msg; | ||
309 | |||
310 | /* FW log stream */ | ||
311 | struct sst_hsw_log_stream log_stream; | ||
312 | }; | ||
313 | |||
314 | #define CREATE_TRACE_POINTS | ||
315 | #include <trace/events/hswadsp.h> | ||
316 | |||
317 | static inline u32 msg_get_global_type(u32 msg) | ||
318 | { | ||
319 | return (msg & IPC_GLB_TYPE_MASK) >> IPC_GLB_TYPE_SHIFT; | ||
320 | } | ||
321 | |||
322 | static inline u32 msg_get_global_reply(u32 msg) | ||
323 | { | ||
324 | return (msg & IPC_GLB_REPLY_MASK) >> IPC_GLB_REPLY_SHIFT; | ||
325 | } | ||
326 | |||
327 | static inline u32 msg_get_stream_type(u32 msg) | ||
328 | { | ||
329 | return (msg & IPC_STR_TYPE_MASK) >> IPC_STR_TYPE_SHIFT; | ||
330 | } | ||
331 | |||
332 | static inline u32 msg_get_stage_type(u32 msg) | ||
333 | { | ||
334 | return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; | ||
335 | } | ||
336 | |||
337 | static inline u32 msg_set_stage_type(u32 msg, u32 type) | ||
338 | { | ||
339 | return (msg & ~IPC_STG_TYPE_MASK) + | ||
340 | (type << IPC_STG_TYPE_SHIFT); | ||
341 | } | ||
342 | |||
343 | static inline u32 msg_get_stream_id(u32 msg) | ||
344 | { | ||
345 | return (msg & IPC_STR_ID_MASK) >> IPC_STR_ID_SHIFT; | ||
346 | } | ||
347 | |||
348 | static inline u32 msg_get_notify_reason(u32 msg) | ||
349 | { | ||
350 | return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; | ||
351 | } | ||
352 | |||
353 | u32 create_channel_map(enum sst_hsw_channel_config config) | ||
354 | { | ||
355 | switch (config) { | ||
356 | case SST_HSW_CHANNEL_CONFIG_MONO: | ||
357 | return (0xFFFFFFF0 | SST_HSW_CHANNEL_CENTER); | ||
358 | case SST_HSW_CHANNEL_CONFIG_STEREO: | ||
359 | return (0xFFFFFF00 | SST_HSW_CHANNEL_LEFT | ||
360 | | (SST_HSW_CHANNEL_RIGHT << 4)); | ||
361 | case SST_HSW_CHANNEL_CONFIG_2_POINT_1: | ||
362 | return (0xFFFFF000 | SST_HSW_CHANNEL_LEFT | ||
363 | | (SST_HSW_CHANNEL_RIGHT << 4) | ||
364 | | (SST_HSW_CHANNEL_LFE << 8 )); | ||
365 | case SST_HSW_CHANNEL_CONFIG_3_POINT_0: | ||
366 | return (0xFFFFF000 | SST_HSW_CHANNEL_LEFT | ||
367 | | (SST_HSW_CHANNEL_CENTER << 4) | ||
368 | | (SST_HSW_CHANNEL_RIGHT << 8)); | ||
369 | case SST_HSW_CHANNEL_CONFIG_3_POINT_1: | ||
370 | return (0xFFFF0000 | SST_HSW_CHANNEL_LEFT | ||
371 | | (SST_HSW_CHANNEL_CENTER << 4) | ||
372 | | (SST_HSW_CHANNEL_RIGHT << 8) | ||
373 | | (SST_HSW_CHANNEL_LFE << 12)); | ||
374 | case SST_HSW_CHANNEL_CONFIG_QUATRO: | ||
375 | return (0xFFFF0000 | SST_HSW_CHANNEL_LEFT | ||
376 | | (SST_HSW_CHANNEL_RIGHT << 4) | ||
377 | | (SST_HSW_CHANNEL_LEFT_SURROUND << 8) | ||
378 | | (SST_HSW_CHANNEL_RIGHT_SURROUND << 12)); | ||
379 | case SST_HSW_CHANNEL_CONFIG_4_POINT_0: | ||
380 | return (0xFFFF0000 | SST_HSW_CHANNEL_LEFT | ||
381 | | (SST_HSW_CHANNEL_CENTER << 4) | ||
382 | | (SST_HSW_CHANNEL_RIGHT << 8) | ||
383 | | (SST_HSW_CHANNEL_CENTER_SURROUND << 12)); | ||
384 | case SST_HSW_CHANNEL_CONFIG_5_POINT_0: | ||
385 | return (0xFFF00000 | SST_HSW_CHANNEL_LEFT | ||
386 | | (SST_HSW_CHANNEL_CENTER << 4) | ||
387 | | (SST_HSW_CHANNEL_RIGHT << 8) | ||
388 | | (SST_HSW_CHANNEL_LEFT_SURROUND << 12) | ||
389 | | (SST_HSW_CHANNEL_RIGHT_SURROUND << 16)); | ||
390 | case SST_HSW_CHANNEL_CONFIG_5_POINT_1: | ||
391 | return (0xFF000000 | SST_HSW_CHANNEL_CENTER | ||
392 | | (SST_HSW_CHANNEL_LEFT << 4) | ||
393 | | (SST_HSW_CHANNEL_RIGHT << 8) | ||
394 | | (SST_HSW_CHANNEL_LEFT_SURROUND << 12) | ||
395 | | (SST_HSW_CHANNEL_RIGHT_SURROUND << 16) | ||
396 | | (SST_HSW_CHANNEL_LFE << 20)); | ||
397 | case SST_HSW_CHANNEL_CONFIG_DUAL_MONO: | ||
398 | return (0xFFFFFF00 | SST_HSW_CHANNEL_LEFT | ||
399 | | (SST_HSW_CHANNEL_LEFT << 4)); | ||
400 | default: | ||
401 | return 0xFFFFFFFF; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | static struct sst_hsw_stream *get_stream_by_id(struct sst_hsw *hsw, | ||
406 | int stream_id) | ||
407 | { | ||
408 | struct sst_hsw_stream *stream; | ||
409 | |||
410 | list_for_each_entry(stream, &hsw->stream_list, node) { | ||
411 | if (stream->reply.stream_hw_id == stream_id) | ||
412 | return stream; | ||
413 | } | ||
414 | |||
415 | return NULL; | ||
416 | } | ||
417 | |||
418 | static void ipc_shim_dbg(struct sst_hsw *hsw, const char *text) | ||
419 | { | ||
420 | struct sst_dsp *sst = hsw->dsp; | ||
421 | u32 isr, ipcd, imrx, ipcx; | ||
422 | |||
423 | ipcx = sst_dsp_shim_read_unlocked(sst, SST_IPCX); | ||
424 | isr = sst_dsp_shim_read_unlocked(sst, SST_ISRX); | ||
425 | ipcd = sst_dsp_shim_read_unlocked(sst, SST_IPCD); | ||
426 | imrx = sst_dsp_shim_read_unlocked(sst, SST_IMRX); | ||
427 | |||
428 | dev_err(hsw->dev, "ipc: --%s-- ipcx 0x%8.8x isr 0x%8.8x ipcd 0x%8.8x imrx 0x%8.8x\n", | ||
429 | text, ipcx, isr, ipcd, imrx); | ||
430 | } | ||
431 | |||
432 | /* locks held by caller */ | ||
433 | static struct ipc_message *msg_get_empty(struct sst_hsw *hsw) | ||
434 | { | ||
435 | struct ipc_message *msg = NULL; | ||
436 | |||
437 | if (!list_empty(&hsw->empty_list)) { | ||
438 | msg = list_first_entry(&hsw->empty_list, struct ipc_message, | ||
439 | list); | ||
440 | list_del(&msg->list); | ||
441 | } | ||
442 | |||
443 | return msg; | ||
444 | } | ||
445 | |||
446 | static void ipc_tx_msgs(struct kthread_work *work) | ||
447 | { | ||
448 | struct sst_hsw *hsw = | ||
449 | container_of(work, struct sst_hsw, kwork); | ||
450 | struct ipc_message *msg; | ||
451 | unsigned long flags; | ||
452 | u32 ipcx; | ||
453 | |||
454 | spin_lock_irqsave(&hsw->dsp->spinlock, flags); | ||
455 | |||
456 | if (list_empty(&hsw->tx_list) || hsw->pending) { | ||
457 | spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); | ||
458 | return; | ||
459 | } | ||
460 | |||
461 | /* if the DSP is busy we will TX messages after IRQ */ | ||
462 | ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX); | ||
463 | if (ipcx & SST_IPCX_BUSY) { | ||
464 | spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); | ||
465 | return; | ||
466 | } | ||
467 | |||
468 | msg = list_first_entry(&hsw->tx_list, struct ipc_message, list); | ||
469 | |||
470 | list_move(&msg->list, &hsw->rx_list); | ||
471 | |||
472 | /* send the message */ | ||
473 | sst_dsp_outbox_write(hsw->dsp, msg->tx_data, msg->tx_size); | ||
474 | sst_dsp_ipc_msg_tx(hsw->dsp, msg->header | SST_IPCX_BUSY); | ||
475 | |||
476 | spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); | ||
477 | } | ||
478 | |||
479 | /* locks held by caller */ | ||
480 | static void tx_msg_reply_complete(struct sst_hsw *hsw, struct ipc_message *msg) | ||
481 | { | ||
482 | msg->complete = true; | ||
483 | trace_ipc_reply("completed", msg->header); | ||
484 | |||
485 | if (!msg->wait) | ||
486 | list_add_tail(&msg->list, &hsw->empty_list); | ||
487 | else | ||
488 | wake_up(&msg->waitq); | ||
489 | } | ||
490 | |||
491 | static int tx_wait_done(struct sst_hsw *hsw, struct ipc_message *msg, | ||
492 | void *rx_data) | ||
493 | { | ||
494 | unsigned long flags; | ||
495 | int ret; | ||
496 | |||
497 | /* wait for DSP completion (in all cases atm inc pending) */ | ||
498 | ret = wait_event_timeout(msg->waitq, msg->complete, | ||
499 | msecs_to_jiffies(IPC_TIMEOUT_MSECS)); | ||
500 | |||
501 | spin_lock_irqsave(&hsw->dsp->spinlock, flags); | ||
502 | if (ret == 0) { | ||
503 | ipc_shim_dbg(hsw, "message timeout"); | ||
504 | |||
505 | trace_ipc_error("error message timeout for", msg->header); | ||
506 | ret = -ETIMEDOUT; | ||
507 | } else { | ||
508 | |||
509 | /* copy the data returned from DSP */ | ||
510 | if (msg->rx_size) | ||
511 | memcpy(rx_data, msg->rx_data, msg->rx_size); | ||
512 | ret = msg->errno; | ||
513 | } | ||
514 | |||
515 | list_add_tail(&msg->list, &hsw->empty_list); | ||
516 | spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); | ||
517 | return ret; | ||
518 | } | ||
519 | |||
520 | static int ipc_tx_message(struct sst_hsw *hsw, u32 header, void *tx_data, | ||
521 | size_t tx_bytes, void *rx_data, size_t rx_bytes, int wait) | ||
522 | { | ||
523 | struct ipc_message *msg; | ||
524 | unsigned long flags; | ||
525 | |||
526 | spin_lock_irqsave(&hsw->dsp->spinlock, flags); | ||
527 | |||
528 | msg = msg_get_empty(hsw); | ||
529 | if (msg == NULL) { | ||
530 | spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); | ||
531 | return -EBUSY; | ||
532 | } | ||
533 | |||
534 | if (tx_bytes) | ||
535 | memcpy(msg->tx_data, tx_data, tx_bytes); | ||
536 | |||
537 | msg->header = header; | ||
538 | msg->tx_size = tx_bytes; | ||
539 | msg->rx_size = rx_bytes; | ||
540 | msg->wait = wait; | ||
541 | msg->errno = 0; | ||
542 | msg->pending = false; | ||
543 | msg->complete = false; | ||
544 | |||
545 | list_add_tail(&msg->list, &hsw->tx_list); | ||
546 | spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); | ||
547 | |||
548 | queue_kthread_work(&hsw->kworker, &hsw->kwork); | ||
549 | |||
550 | if (wait) | ||
551 | return tx_wait_done(hsw, msg, rx_data); | ||
552 | else | ||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | static inline int ipc_tx_message_wait(struct sst_hsw *hsw, u32 header, | ||
557 | void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes) | ||
558 | { | ||
559 | return ipc_tx_message(hsw, header, tx_data, tx_bytes, rx_data, | ||
560 | rx_bytes, 1); | ||
561 | } | ||
562 | |||
563 | static inline int ipc_tx_message_nowait(struct sst_hsw *hsw, u32 header, | ||
564 | void *tx_data, size_t tx_bytes) | ||
565 | { | ||
566 | return ipc_tx_message(hsw, header, tx_data, tx_bytes, NULL, 0, 0); | ||
567 | } | ||
568 | |||
569 | static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) | ||
570 | { | ||
571 | struct sst_hsw_ipc_fw_ready fw_ready; | ||
572 | u32 offset; | ||
573 | |||
574 | offset = (header & 0x1FFFFFFF) << 3; | ||
575 | |||
576 | dev_dbg(hsw->dev, "ipc: DSP is ready 0x%8.8x offset %d\n", | ||
577 | header, offset); | ||
578 | |||
579 | /* copy data from the DSP FW ready offset */ | ||
580 | sst_dsp_read(hsw->dsp, &fw_ready, offset, sizeof(fw_ready)); | ||
581 | |||
582 | sst_dsp_mailbox_init(hsw->dsp, fw_ready.inbox_offset, | ||
583 | fw_ready.inbox_size, fw_ready.outbox_offset, | ||
584 | fw_ready.outbox_size); | ||
585 | |||
586 | hsw->boot_complete = true; | ||
587 | wake_up(&hsw->boot_wait); | ||
588 | |||
589 | dev_dbg(hsw->dev, " mailbox upstream 0x%x - size 0x%x\n", | ||
590 | fw_ready.inbox_offset, fw_ready.inbox_size); | ||
591 | dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n", | ||
592 | fw_ready.outbox_offset, fw_ready.outbox_size); | ||
593 | } | ||
594 | |||
595 | static void hsw_notification_work(struct work_struct *work) | ||
596 | { | ||
597 | struct sst_hsw_stream *stream = container_of(work, | ||
598 | struct sst_hsw_stream, notify_work); | ||
599 | struct sst_hsw_ipc_stream_glitch_position *glitch = &stream->glitch; | ||
600 | struct sst_hsw_ipc_stream_get_position *pos = &stream->rpos; | ||
601 | struct sst_hsw *hsw = stream->hsw; | ||
602 | u32 reason; | ||
603 | |||
604 | reason = msg_get_notify_reason(stream->header); | ||
605 | |||
606 | switch (reason) { | ||
607 | case IPC_STG_GLITCH: | ||
608 | trace_ipc_notification("DSP stream under/overrun", | ||
609 | stream->reply.stream_hw_id); | ||
610 | sst_dsp_inbox_read(hsw->dsp, glitch, sizeof(*glitch)); | ||
611 | |||
612 | dev_err(hsw->dev, "glitch %d pos 0x%x write pos 0x%x\n", | ||
613 | glitch->glitch_type, glitch->present_pos, | ||
614 | glitch->write_pos); | ||
615 | break; | ||
616 | |||
617 | case IPC_POSITION_CHANGED: | ||
618 | trace_ipc_notification("DSP stream position changed for", | ||
619 | stream->reply.stream_hw_id); | ||
620 | sst_dsp_inbox_read(hsw->dsp, pos, sizeof(pos)); | ||
621 | |||
622 | if (stream->notify_position) | ||
623 | stream->notify_position(stream, stream->pdata); | ||
624 | |||
625 | break; | ||
626 | default: | ||
627 | dev_err(hsw->dev, "error: unknown notification 0x%x\n", | ||
628 | stream->header); | ||
629 | break; | ||
630 | } | ||
631 | |||
632 | /* tell DSP that notification has been handled */ | ||
633 | sst_dsp_shim_update_bits_unlocked(hsw->dsp, SST_IPCD, | ||
634 | SST_IPCD_BUSY | SST_IPCD_DONE, SST_IPCD_DONE); | ||
635 | |||
636 | /* unmask busy interrupt */ | ||
637 | sst_dsp_shim_update_bits_unlocked(hsw->dsp, SST_IMRX, SST_IMRX_BUSY, 0); | ||
638 | } | ||
639 | |||
640 | static struct ipc_message *reply_find_msg(struct sst_hsw *hsw, u32 header) | ||
641 | { | ||
642 | struct ipc_message *msg; | ||
643 | |||
644 | /* clear reply bits & status bits */ | ||
645 | header &= ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK); | ||
646 | |||
647 | if (list_empty(&hsw->rx_list)) { | ||
648 | dev_err(hsw->dev, "error: rx list empty but received 0x%x\n", | ||
649 | header); | ||
650 | return NULL; | ||
651 | } | ||
652 | |||
653 | list_for_each_entry(msg, &hsw->rx_list, list) { | ||
654 | if (msg->header == header) | ||
655 | return msg; | ||
656 | } | ||
657 | |||
658 | return NULL; | ||
659 | } | ||
660 | |||
661 | static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg) | ||
662 | { | ||
663 | struct sst_hsw_stream *stream; | ||
664 | u32 header = msg->header & ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK); | ||
665 | u32 stream_id = msg_get_stream_id(header); | ||
666 | u32 stream_msg = msg_get_stream_type(header); | ||
667 | |||
668 | stream = get_stream_by_id(hsw, stream_id); | ||
669 | if (stream == NULL) | ||
670 | return; | ||
671 | |||
672 | switch (stream_msg) { | ||
673 | case IPC_STR_STAGE_MESSAGE: | ||
674 | case IPC_STR_NOTIFICATION: | ||
675 | case IPC_STR_RESET: | ||
676 | break; | ||
677 | case IPC_STR_PAUSE: | ||
678 | stream->running = false; | ||
679 | trace_ipc_notification("stream paused", | ||
680 | stream->reply.stream_hw_id); | ||
681 | break; | ||
682 | case IPC_STR_RESUME: | ||
683 | stream->running = true; | ||
684 | trace_ipc_notification("stream running", | ||
685 | stream->reply.stream_hw_id); | ||
686 | break; | ||
687 | } | ||
688 | } | ||
689 | |||
690 | static int hsw_process_reply(struct sst_hsw *hsw, u32 header) | ||
691 | { | ||
692 | struct ipc_message *msg; | ||
693 | u32 reply = msg_get_global_reply(header); | ||
694 | |||
695 | trace_ipc_reply("processing -->", header); | ||
696 | |||
697 | msg = reply_find_msg(hsw, header); | ||
698 | if (msg == NULL) { | ||
699 | trace_ipc_error("error: can't find message header", header); | ||
700 | return -EIO; | ||
701 | } | ||
702 | |||
703 | /* first process the header */ | ||
704 | switch (reply) { | ||
705 | case IPC_GLB_REPLY_PENDING: | ||
706 | trace_ipc_pending_reply("received", header); | ||
707 | msg->pending = true; | ||
708 | hsw->pending = true; | ||
709 | return 1; | ||
710 | case IPC_GLB_REPLY_SUCCESS: | ||
711 | if (msg->pending) { | ||
712 | trace_ipc_pending_reply("completed", header); | ||
713 | sst_dsp_inbox_read(hsw->dsp, msg->rx_data, | ||
714 | msg->rx_size); | ||
715 | hsw->pending = false; | ||
716 | } else { | ||
717 | /* copy data from the DSP */ | ||
718 | sst_dsp_outbox_read(hsw->dsp, msg->rx_data, | ||
719 | msg->rx_size); | ||
720 | } | ||
721 | break; | ||
722 | /* these will be rare - but useful for debug */ | ||
723 | case IPC_GLB_REPLY_UNKNOWN_MESSAGE_TYPE: | ||
724 | trace_ipc_error("error: unknown message type", header); | ||
725 | msg->errno = -EBADMSG; | ||
726 | break; | ||
727 | case IPC_GLB_REPLY_OUT_OF_RESOURCES: | ||
728 | trace_ipc_error("error: out of resources", header); | ||
729 | msg->errno = -ENOMEM; | ||
730 | break; | ||
731 | case IPC_GLB_REPLY_BUSY: | ||
732 | trace_ipc_error("error: reply busy", header); | ||
733 | msg->errno = -EBUSY; | ||
734 | break; | ||
735 | case IPC_GLB_REPLY_FAILURE: | ||
736 | trace_ipc_error("error: reply failure", header); | ||
737 | msg->errno = -EINVAL; | ||
738 | break; | ||
739 | case IPC_GLB_REPLY_STAGE_UNINITIALIZED: | ||
740 | trace_ipc_error("error: stage uninitialized", header); | ||
741 | msg->errno = -EINVAL; | ||
742 | break; | ||
743 | case IPC_GLB_REPLY_NOT_FOUND: | ||
744 | trace_ipc_error("error: reply not found", header); | ||
745 | msg->errno = -EINVAL; | ||
746 | break; | ||
747 | case IPC_GLB_REPLY_SOURCE_NOT_STARTED: | ||
748 | trace_ipc_error("error: source not started", header); | ||
749 | msg->errno = -EINVAL; | ||
750 | break; | ||
751 | case IPC_GLB_REPLY_INVALID_REQUEST: | ||
752 | trace_ipc_error("error: invalid request", header); | ||
753 | msg->errno = -EINVAL; | ||
754 | break; | ||
755 | case IPC_GLB_REPLY_ERROR_INVALID_PARAM: | ||
756 | trace_ipc_error("error: invalid parameter", header); | ||
757 | msg->errno = -EINVAL; | ||
758 | break; | ||
759 | default: | ||
760 | trace_ipc_error("error: unknown reply", header); | ||
761 | msg->errno = -EINVAL; | ||
762 | break; | ||
763 | } | ||
764 | |||
765 | /* update any stream states */ | ||
766 | hsw_stream_update(hsw, msg); | ||
767 | |||
768 | /* wake up and return the error if we have waiters on this message ? */ | ||
769 | list_del(&msg->list); | ||
770 | tx_msg_reply_complete(hsw, msg); | ||
771 | |||
772 | return 1; | ||
773 | } | ||
774 | |||
775 | static int hsw_stream_message(struct sst_hsw *hsw, u32 header) | ||
776 | { | ||
777 | u32 stream_msg, stream_id, stage_type; | ||
778 | struct sst_hsw_stream *stream; | ||
779 | int handled = 0; | ||
780 | |||
781 | stream_msg = msg_get_stream_type(header); | ||
782 | stream_id = msg_get_stream_id(header); | ||
783 | stage_type = msg_get_stage_type(header); | ||
784 | |||
785 | stream = get_stream_by_id(hsw, stream_id); | ||
786 | if (stream == NULL) | ||
787 | return handled; | ||
788 | |||
789 | stream->header = header; | ||
790 | |||
791 | switch (stream_msg) { | ||
792 | case IPC_STR_STAGE_MESSAGE: | ||
793 | dev_err(hsw->dev, "error: stage msg not implemented 0x%8.8x\n", | ||
794 | header); | ||
795 | break; | ||
796 | case IPC_STR_NOTIFICATION: | ||
797 | schedule_work(&stream->notify_work); | ||
798 | break; | ||
799 | default: | ||
800 | /* handle pending message complete request */ | ||
801 | handled = hsw_process_reply(hsw, header); | ||
802 | break; | ||
803 | } | ||
804 | |||
805 | return handled; | ||
806 | } | ||
807 | |||
808 | static int hsw_log_message(struct sst_hsw *hsw, u32 header) | ||
809 | { | ||
810 | u32 operation = (header & IPC_LOG_OP_MASK) >> IPC_LOG_OP_SHIFT; | ||
811 | struct sst_hsw_log_stream *stream = &hsw->log_stream; | ||
812 | int ret = 1; | ||
813 | |||
814 | if (operation != IPC_DEBUG_REQUEST_LOG_DUMP) { | ||
815 | dev_err(hsw->dev, | ||
816 | "error: log msg not implemented 0x%8.8x\n", header); | ||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | mutex_lock(&stream->rw_mutex); | ||
821 | stream->last_pos = stream->curr_pos; | ||
822 | sst_dsp_inbox_read( | ||
823 | hsw->dsp, &stream->curr_pos, sizeof(stream->curr_pos)); | ||
824 | mutex_unlock(&stream->rw_mutex); | ||
825 | |||
826 | schedule_work(&stream->notify_work); | ||
827 | |||
828 | return ret; | ||
829 | } | ||
830 | |||
831 | static int hsw_process_notification(struct sst_hsw *hsw) | ||
832 | { | ||
833 | struct sst_dsp *sst = hsw->dsp; | ||
834 | u32 type, header; | ||
835 | int handled = 1; | ||
836 | |||
837 | header = sst_dsp_shim_read_unlocked(sst, SST_IPCD); | ||
838 | type = msg_get_global_type(header); | ||
839 | |||
840 | trace_ipc_request("processing -->", header); | ||
841 | |||
842 | /* FW Ready is a special case */ | ||
843 | if (!hsw->boot_complete && header & IPC_FW_READY) { | ||
844 | hsw_fw_ready(hsw, header); | ||
845 | return handled; | ||
846 | } | ||
847 | |||
848 | switch (type) { | ||
849 | case IPC_GLB_GET_FW_VERSION: | ||
850 | case IPC_GLB_ALLOCATE_STREAM: | ||
851 | case IPC_GLB_FREE_STREAM: | ||
852 | case IPC_GLB_GET_FW_CAPABILITIES: | ||
853 | case IPC_GLB_REQUEST_DUMP: | ||
854 | case IPC_GLB_GET_DEVICE_FORMATS: | ||
855 | case IPC_GLB_SET_DEVICE_FORMATS: | ||
856 | case IPC_GLB_ENTER_DX_STATE: | ||
857 | case IPC_GLB_GET_MIXER_STREAM_INFO: | ||
858 | case IPC_GLB_MAX_IPC_MESSAGE_TYPE: | ||
859 | case IPC_GLB_RESTORE_CONTEXT: | ||
860 | case IPC_GLB_SHORT_REPLY: | ||
861 | dev_err(hsw->dev, "error: message type %d header 0x%x\n", | ||
862 | type, header); | ||
863 | break; | ||
864 | case IPC_GLB_STREAM_MESSAGE: | ||
865 | handled = hsw_stream_message(hsw, header); | ||
866 | break; | ||
867 | case IPC_GLB_DEBUG_LOG_MESSAGE: | ||
868 | handled = hsw_log_message(hsw, header); | ||
869 | break; | ||
870 | default: | ||
871 | dev_err(hsw->dev, "error: unexpected type %d hdr 0x%8.8x\n", | ||
872 | type, header); | ||
873 | break; | ||
874 | } | ||
875 | |||
876 | return handled; | ||
877 | } | ||
878 | |||
879 | static irqreturn_t hsw_irq_thread(int irq, void *context) | ||
880 | { | ||
881 | struct sst_dsp *sst = (struct sst_dsp *) context; | ||
882 | struct sst_hsw *hsw = sst_dsp_get_thread_context(sst); | ||
883 | u32 ipcx, ipcd; | ||
884 | int handled; | ||
885 | unsigned long flags; | ||
886 | |||
887 | spin_lock_irqsave(&sst->spinlock, flags); | ||
888 | |||
889 | ipcx = sst_dsp_ipc_msg_rx(hsw->dsp); | ||
890 | ipcd = sst_dsp_shim_read_unlocked(sst, SST_IPCD); | ||
891 | |||
892 | /* reply message from DSP */ | ||
893 | if (ipcx & SST_IPCX_DONE) { | ||
894 | |||
895 | /* Handle Immediate reply from DSP Core */ | ||
896 | handled = hsw_process_reply(hsw, ipcx); | ||
897 | |||
898 | if (handled > 0) { | ||
899 | /* clear DONE bit - tell DSP we have completed */ | ||
900 | sst_dsp_shim_update_bits_unlocked(sst, SST_IPCX, | ||
901 | SST_IPCX_DONE, 0); | ||
902 | |||
903 | /* unmask Done interrupt */ | ||
904 | sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, | ||
905 | SST_IMRX_DONE, 0); | ||
906 | } | ||
907 | } | ||
908 | |||
909 | /* new message from DSP */ | ||
910 | if (ipcd & SST_IPCD_BUSY) { | ||
911 | |||
912 | /* Handle Notification and Delayed reply from DSP Core */ | ||
913 | handled = hsw_process_notification(hsw); | ||
914 | |||
915 | /* clear BUSY bit and set DONE bit - accept new messages */ | ||
916 | if (handled > 0) { | ||
917 | sst_dsp_shim_update_bits_unlocked(sst, SST_IPCD, | ||
918 | SST_IPCD_BUSY | SST_IPCD_DONE, SST_IPCD_DONE); | ||
919 | |||
920 | /* unmask busy interrupt */ | ||
921 | sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, | ||
922 | SST_IMRX_BUSY, 0); | ||
923 | } | ||
924 | } | ||
925 | |||
926 | spin_unlock_irqrestore(&sst->spinlock, flags); | ||
927 | |||
928 | /* continue to send any remaining messages... */ | ||
929 | queue_kthread_work(&hsw->kworker, &hsw->kwork); | ||
930 | |||
931 | return IRQ_HANDLED; | ||
932 | } | ||
933 | |||
934 | int sst_hsw_fw_get_version(struct sst_hsw *hsw, | ||
935 | struct sst_hsw_ipc_fw_version *version) | ||
936 | { | ||
937 | int ret; | ||
938 | |||
939 | ret = ipc_tx_message_wait(hsw, IPC_GLB_TYPE(IPC_GLB_GET_FW_VERSION), | ||
940 | NULL, 0, version, sizeof(*version)); | ||
941 | if (ret < 0) | ||
942 | dev_err(hsw->dev, "error: get version failed\n"); | ||
943 | |||
944 | return ret; | ||
945 | } | ||
946 | |||
947 | /* Mixer Controls */ | ||
948 | int sst_hsw_stream_mute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
949 | u32 stage_id, u32 channel) | ||
950 | { | ||
951 | int ret; | ||
952 | |||
953 | ret = sst_hsw_stream_get_volume(hsw, stream, stage_id, channel, | ||
954 | &stream->mute_volume[channel]); | ||
955 | if (ret < 0) | ||
956 | return ret; | ||
957 | |||
958 | ret = sst_hsw_stream_set_volume(hsw, stream, stage_id, channel, 0); | ||
959 | if (ret < 0) { | ||
960 | dev_err(hsw->dev, "error: can't unmute stream %d channel %d\n", | ||
961 | stream->reply.stream_hw_id, channel); | ||
962 | return ret; | ||
963 | } | ||
964 | |||
965 | stream->mute[channel] = 1; | ||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | int sst_hsw_stream_unmute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
970 | u32 stage_id, u32 channel) | ||
971 | |||
972 | { | ||
973 | int ret; | ||
974 | |||
975 | stream->mute[channel] = 0; | ||
976 | ret = sst_hsw_stream_set_volume(hsw, stream, stage_id, channel, | ||
977 | stream->mute_volume[channel]); | ||
978 | if (ret < 0) { | ||
979 | dev_err(hsw->dev, "error: can't unmute stream %d channel %d\n", | ||
980 | stream->reply.stream_hw_id, channel); | ||
981 | return ret; | ||
982 | } | ||
983 | |||
984 | return 0; | ||
985 | } | ||
986 | |||
987 | int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
988 | u32 stage_id, u32 channel, u32 *volume) | ||
989 | { | ||
990 | if (channel > 1) | ||
991 | return -EINVAL; | ||
992 | |||
993 | sst_dsp_read(hsw->dsp, volume, | ||
994 | stream->reply.volume_register_address[channel], sizeof(volume)); | ||
995 | |||
996 | return 0; | ||
997 | } | ||
998 | |||
999 | int sst_hsw_stream_set_volume_curve(struct sst_hsw *hsw, | ||
1000 | struct sst_hsw_stream *stream, u64 curve_duration, | ||
1001 | enum sst_hsw_volume_curve curve) | ||
1002 | { | ||
1003 | /* curve duration in steps of 100ns */ | ||
1004 | stream->vol_req.curve_duration = curve_duration; | ||
1005 | stream->vol_req.curve_type = curve; | ||
1006 | |||
1007 | return 0; | ||
1008 | } | ||
1009 | |||
1010 | /* stream volume */ | ||
1011 | int sst_hsw_stream_set_volume(struct sst_hsw *hsw, | ||
1012 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume) | ||
1013 | { | ||
1014 | struct sst_hsw_ipc_volume_req *req; | ||
1015 | u32 header; | ||
1016 | int ret; | ||
1017 | |||
1018 | trace_ipc_request("set stream volume", stream->reply.stream_hw_id); | ||
1019 | |||
1020 | if (channel > 1) | ||
1021 | return -EINVAL; | ||
1022 | |||
1023 | if (stream->mute[channel]) { | ||
1024 | stream->mute_volume[channel] = volume; | ||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | | ||
1029 | IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); | ||
1030 | header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); | ||
1031 | header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); | ||
1032 | header |= (stage_id << IPC_STG_ID_SHIFT); | ||
1033 | |||
1034 | req = &stream->vol_req; | ||
1035 | req->channel = channel; | ||
1036 | req->target_volume = volume; | ||
1037 | |||
1038 | ret = ipc_tx_message_wait(hsw, header, req, sizeof(*req), NULL, 0); | ||
1039 | if (ret < 0) { | ||
1040 | dev_err(hsw->dev, "error: set stream volume failed\n"); | ||
1041 | return ret; | ||
1042 | } | ||
1043 | |||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | int sst_hsw_mixer_mute(struct sst_hsw *hsw, u32 stage_id, u32 channel) | ||
1048 | { | ||
1049 | int ret; | ||
1050 | |||
1051 | ret = sst_hsw_mixer_get_volume(hsw, stage_id, channel, | ||
1052 | &hsw->mute_volume[channel]); | ||
1053 | if (ret < 0) | ||
1054 | return ret; | ||
1055 | |||
1056 | ret = sst_hsw_mixer_set_volume(hsw, stage_id, channel, 0); | ||
1057 | if (ret < 0) { | ||
1058 | dev_err(hsw->dev, "error: failed to unmute mixer channel %d\n", | ||
1059 | channel); | ||
1060 | return ret; | ||
1061 | } | ||
1062 | |||
1063 | hsw->mute[channel] = 1; | ||
1064 | return 0; | ||
1065 | } | ||
1066 | |||
1067 | int sst_hsw_mixer_unmute(struct sst_hsw *hsw, u32 stage_id, u32 channel) | ||
1068 | { | ||
1069 | int ret; | ||
1070 | |||
1071 | ret = sst_hsw_mixer_set_volume(hsw, stage_id, channel, | ||
1072 | hsw->mixer_info.volume_register_address[channel]); | ||
1073 | if (ret < 0) { | ||
1074 | dev_err(hsw->dev, "error: failed to unmute mixer channel %d\n", | ||
1075 | channel); | ||
1076 | return ret; | ||
1077 | } | ||
1078 | |||
1079 | hsw->mute[channel] = 0; | ||
1080 | return 0; | ||
1081 | } | ||
1082 | |||
1083 | int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | ||
1084 | u32 *volume) | ||
1085 | { | ||
1086 | if (channel > 1) | ||
1087 | return -EINVAL; | ||
1088 | |||
1089 | sst_dsp_read(hsw->dsp, volume, | ||
1090 | hsw->mixer_info.volume_register_address[channel], | ||
1091 | sizeof(*volume)); | ||
1092 | |||
1093 | return 0; | ||
1094 | } | ||
1095 | |||
1096 | int sst_hsw_mixer_set_volume_curve(struct sst_hsw *hsw, | ||
1097 | u64 curve_duration, enum sst_hsw_volume_curve curve) | ||
1098 | { | ||
1099 | /* curve duration in steps of 100ns */ | ||
1100 | hsw->curve_duration = curve_duration; | ||
1101 | hsw->curve_type = curve; | ||
1102 | |||
1103 | return 0; | ||
1104 | } | ||
1105 | |||
1106 | /* global mixer volume */ | ||
1107 | int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | ||
1108 | u32 volume) | ||
1109 | { | ||
1110 | struct sst_hsw_ipc_volume_req req; | ||
1111 | u32 header; | ||
1112 | int ret; | ||
1113 | |||
1114 | trace_ipc_request("set mixer volume", volume); | ||
1115 | |||
1116 | /* set both at same time ? */ | ||
1117 | if (channel == 2) { | ||
1118 | if (hsw->mute[0] && hsw->mute[1]) { | ||
1119 | hsw->mute_volume[0] = hsw->mute_volume[1] = volume; | ||
1120 | return 0; | ||
1121 | } else if (hsw->mute[0]) | ||
1122 | req.channel = 1; | ||
1123 | else if (hsw->mute[1]) | ||
1124 | req.channel = 0; | ||
1125 | else | ||
1126 | req.channel = 0xffffffff; | ||
1127 | } else { | ||
1128 | /* set only 1 channel */ | ||
1129 | if (hsw->mute[channel]) { | ||
1130 | hsw->mute_volume[channel] = volume; | ||
1131 | return 0; | ||
1132 | } | ||
1133 | req.channel = channel; | ||
1134 | } | ||
1135 | |||
1136 | header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | | ||
1137 | IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); | ||
1138 | header |= (hsw->mixer_info.mixer_hw_id << IPC_STR_ID_SHIFT); | ||
1139 | header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); | ||
1140 | header |= (stage_id << IPC_STG_ID_SHIFT); | ||
1141 | |||
1142 | req.curve_duration = hsw->curve_duration; | ||
1143 | req.curve_type = hsw->curve_type; | ||
1144 | req.target_volume = volume; | ||
1145 | |||
1146 | ret = ipc_tx_message_wait(hsw, header, &req, sizeof(req), NULL, 0); | ||
1147 | if (ret < 0) { | ||
1148 | dev_err(hsw->dev, "error: set mixer volume failed\n"); | ||
1149 | return ret; | ||
1150 | } | ||
1151 | |||
1152 | return 0; | ||
1153 | } | ||
1154 | |||
1155 | /* Stream API */ | ||
1156 | struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, | ||
1157 | u32 (*notify_position)(struct sst_hsw_stream *stream, void *data), | ||
1158 | void *data) | ||
1159 | { | ||
1160 | struct sst_hsw_stream *stream; | ||
1161 | |||
1162 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); | ||
1163 | if (stream == NULL) | ||
1164 | return NULL; | ||
1165 | |||
1166 | list_add(&stream->node, &hsw->stream_list); | ||
1167 | stream->notify_position = notify_position; | ||
1168 | stream->pdata = data; | ||
1169 | stream->hsw = hsw; | ||
1170 | stream->host_id = id; | ||
1171 | |||
1172 | /* work to process notification messages */ | ||
1173 | INIT_WORK(&stream->notify_work, hsw_notification_work); | ||
1174 | |||
1175 | return stream; | ||
1176 | } | ||
1177 | |||
1178 | int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) | ||
1179 | { | ||
1180 | u32 header; | ||
1181 | int ret = 0; | ||
1182 | |||
1183 | /* dont free DSP streams that are not commited */ | ||
1184 | if (!stream->commited) | ||
1185 | goto out; | ||
1186 | |||
1187 | trace_ipc_request("stream free", stream->host_id); | ||
1188 | |||
1189 | stream->free_req.stream_id = stream->reply.stream_hw_id; | ||
1190 | header = IPC_GLB_TYPE(IPC_GLB_FREE_STREAM); | ||
1191 | |||
1192 | ret = ipc_tx_message_wait(hsw, header, &stream->free_req, | ||
1193 | sizeof(stream->free_req), NULL, 0); | ||
1194 | if (ret < 0) { | ||
1195 | dev_err(hsw->dev, "error: free stream %d failed\n", | ||
1196 | stream->free_req.stream_id); | ||
1197 | return -EAGAIN; | ||
1198 | } | ||
1199 | |||
1200 | trace_hsw_stream_free_req(stream, &stream->free_req); | ||
1201 | |||
1202 | out: | ||
1203 | list_del(&stream->node); | ||
1204 | kfree(stream); | ||
1205 | |||
1206 | return ret; | ||
1207 | } | ||
1208 | |||
1209 | int sst_hsw_stream_set_bits(struct sst_hsw *hsw, | ||
1210 | struct sst_hsw_stream *stream, enum sst_hsw_bitdepth bits) | ||
1211 | { | ||
1212 | if (stream->commited) { | ||
1213 | dev_err(hsw->dev, "error: stream committed for set bits\n"); | ||
1214 | return -EINVAL; | ||
1215 | } | ||
1216 | |||
1217 | stream->request.format.bitdepth = bits; | ||
1218 | return 0; | ||
1219 | } | ||
1220 | |||
1221 | int sst_hsw_stream_set_channels(struct sst_hsw *hsw, | ||
1222 | struct sst_hsw_stream *stream, int channels) | ||
1223 | { | ||
1224 | if (stream->commited) { | ||
1225 | dev_err(hsw->dev, "error: stream committed for set channels\n"); | ||
1226 | return -EINVAL; | ||
1227 | } | ||
1228 | |||
1229 | /* stereo is only supported atm */ | ||
1230 | if (channels != 2) | ||
1231 | return -EINVAL; | ||
1232 | |||
1233 | stream->request.format.ch_num = channels; | ||
1234 | return 0; | ||
1235 | } | ||
1236 | |||
1237 | int sst_hsw_stream_set_rate(struct sst_hsw *hsw, | ||
1238 | struct sst_hsw_stream *stream, int rate) | ||
1239 | { | ||
1240 | if (stream->commited) { | ||
1241 | dev_err(hsw->dev, "error: stream committed for set rate\n"); | ||
1242 | return -EINVAL; | ||
1243 | } | ||
1244 | |||
1245 | stream->request.format.frequency = rate; | ||
1246 | return 0; | ||
1247 | } | ||
1248 | |||
1249 | int sst_hsw_stream_set_map_config(struct sst_hsw *hsw, | ||
1250 | struct sst_hsw_stream *stream, u32 map, | ||
1251 | enum sst_hsw_channel_config config) | ||
1252 | { | ||
1253 | if (stream->commited) { | ||
1254 | dev_err(hsw->dev, "error: stream committed for set map\n"); | ||
1255 | return -EINVAL; | ||
1256 | } | ||
1257 | |||
1258 | stream->request.format.map = map; | ||
1259 | stream->request.format.config = config; | ||
1260 | return 0; | ||
1261 | } | ||
1262 | |||
1263 | int sst_hsw_stream_set_style(struct sst_hsw *hsw, | ||
1264 | struct sst_hsw_stream *stream, enum sst_hsw_interleaving style) | ||
1265 | { | ||
1266 | if (stream->commited) { | ||
1267 | dev_err(hsw->dev, "error: stream committed for set style\n"); | ||
1268 | return -EINVAL; | ||
1269 | } | ||
1270 | |||
1271 | stream->request.format.style = style; | ||
1272 | return 0; | ||
1273 | } | ||
1274 | |||
1275 | int sst_hsw_stream_set_valid(struct sst_hsw *hsw, | ||
1276 | struct sst_hsw_stream *stream, u32 bits) | ||
1277 | { | ||
1278 | if (stream->commited) { | ||
1279 | dev_err(hsw->dev, "error: stream committed for set valid bits\n"); | ||
1280 | return -EINVAL; | ||
1281 | } | ||
1282 | |||
1283 | stream->request.format.valid_bit = bits; | ||
1284 | return 0; | ||
1285 | } | ||
1286 | |||
1287 | /* Stream Configuration */ | ||
1288 | int sst_hsw_stream_format(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
1289 | enum sst_hsw_stream_path_id path_id, | ||
1290 | enum sst_hsw_stream_type stream_type, | ||
1291 | enum sst_hsw_stream_format format_id) | ||
1292 | { | ||
1293 | if (stream->commited) { | ||
1294 | dev_err(hsw->dev, "error: stream committed for set format\n"); | ||
1295 | return -EINVAL; | ||
1296 | } | ||
1297 | |||
1298 | stream->request.path_id = path_id; | ||
1299 | stream->request.stream_type = stream_type; | ||
1300 | stream->request.format_id = format_id; | ||
1301 | |||
1302 | trace_hsw_stream_alloc_request(stream, &stream->request); | ||
1303 | |||
1304 | return 0; | ||
1305 | } | ||
1306 | |||
1307 | int sst_hsw_stream_buffer(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
1308 | u32 ring_pt_address, u32 num_pages, | ||
1309 | u32 ring_size, u32 ring_offset, u32 ring_first_pfn) | ||
1310 | { | ||
1311 | if (stream->commited) { | ||
1312 | dev_err(hsw->dev, "error: stream committed for buffer\n"); | ||
1313 | return -EINVAL; | ||
1314 | } | ||
1315 | |||
1316 | stream->request.ringinfo.ring_pt_address = ring_pt_address; | ||
1317 | stream->request.ringinfo.num_pages = num_pages; | ||
1318 | stream->request.ringinfo.ring_size = ring_size; | ||
1319 | stream->request.ringinfo.ring_offset = ring_offset; | ||
1320 | stream->request.ringinfo.ring_first_pfn = ring_first_pfn; | ||
1321 | |||
1322 | trace_hsw_stream_buffer(stream); | ||
1323 | |||
1324 | return 0; | ||
1325 | } | ||
1326 | |||
1327 | int sst_hsw_stream_set_module_info(struct sst_hsw *hsw, | ||
1328 | struct sst_hsw_stream *stream, enum sst_hsw_module_id module_id, | ||
1329 | u32 entry_point) | ||
1330 | { | ||
1331 | struct sst_hsw_module_map *map = &stream->request.map; | ||
1332 | |||
1333 | if (stream->commited) { | ||
1334 | dev_err(hsw->dev, "error: stream committed for set module\n"); | ||
1335 | return -EINVAL; | ||
1336 | } | ||
1337 | |||
1338 | /* only support initial module atm */ | ||
1339 | map->module_entries_count = 1; | ||
1340 | map->module_entries[0].module_id = module_id; | ||
1341 | map->module_entries[0].entry_point = entry_point; | ||
1342 | |||
1343 | return 0; | ||
1344 | } | ||
1345 | |||
1346 | int sst_hsw_stream_set_pmemory_info(struct sst_hsw *hsw, | ||
1347 | struct sst_hsw_stream *stream, u32 offset, u32 size) | ||
1348 | { | ||
1349 | if (stream->commited) { | ||
1350 | dev_err(hsw->dev, "error: stream committed for set pmem\n"); | ||
1351 | return -EINVAL; | ||
1352 | } | ||
1353 | |||
1354 | stream->request.persistent_mem.offset = offset; | ||
1355 | stream->request.persistent_mem.size = size; | ||
1356 | |||
1357 | return 0; | ||
1358 | } | ||
1359 | |||
1360 | int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw, | ||
1361 | struct sst_hsw_stream *stream, u32 offset, u32 size) | ||
1362 | { | ||
1363 | if (stream->commited) { | ||
1364 | dev_err(hsw->dev, "error: stream committed for set smem\n"); | ||
1365 | return -EINVAL; | ||
1366 | } | ||
1367 | |||
1368 | stream->request.scratch_mem.offset = offset; | ||
1369 | stream->request.scratch_mem.size = size; | ||
1370 | |||
1371 | return 0; | ||
1372 | } | ||
1373 | |||
1374 | int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream) | ||
1375 | { | ||
1376 | struct sst_hsw_ipc_stream_alloc_req *str_req = &stream->request; | ||
1377 | struct sst_hsw_ipc_stream_alloc_reply *reply = &stream->reply; | ||
1378 | u32 header; | ||
1379 | int ret; | ||
1380 | |||
1381 | trace_ipc_request("stream alloc", stream->host_id); | ||
1382 | |||
1383 | header = IPC_GLB_TYPE(IPC_GLB_ALLOCATE_STREAM); | ||
1384 | |||
1385 | ret = ipc_tx_message_wait(hsw, header, str_req, sizeof(*str_req), | ||
1386 | reply, sizeof(*reply)); | ||
1387 | if (ret < 0) { | ||
1388 | dev_err(hsw->dev, "error: stream commit failed\n"); | ||
1389 | return ret; | ||
1390 | } | ||
1391 | |||
1392 | stream->commited = 1; | ||
1393 | trace_hsw_stream_alloc_reply(stream); | ||
1394 | |||
1395 | return 0; | ||
1396 | } | ||
1397 | |||
1398 | /* Stream Information - these calls could be inline but we want the IPC | ||
1399 | ABI to be opaque to client PCM drivers to cope with any future ABI changes */ | ||
1400 | int sst_hsw_stream_get_hw_id(struct sst_hsw *hsw, | ||
1401 | struct sst_hsw_stream *stream) | ||
1402 | { | ||
1403 | return stream->reply.stream_hw_id; | ||
1404 | } | ||
1405 | |||
1406 | int sst_hsw_stream_get_mixer_id(struct sst_hsw *hsw, | ||
1407 | struct sst_hsw_stream *stream) | ||
1408 | { | ||
1409 | return stream->reply.mixer_hw_id; | ||
1410 | } | ||
1411 | |||
1412 | u32 sst_hsw_stream_get_read_reg(struct sst_hsw *hsw, | ||
1413 | struct sst_hsw_stream *stream) | ||
1414 | { | ||
1415 | return stream->reply.read_position_register_address; | ||
1416 | } | ||
1417 | |||
1418 | u32 sst_hsw_stream_get_pointer_reg(struct sst_hsw *hsw, | ||
1419 | struct sst_hsw_stream *stream) | ||
1420 | { | ||
1421 | return stream->reply.presentation_position_register_address; | ||
1422 | } | ||
1423 | |||
1424 | u32 sst_hsw_stream_get_peak_reg(struct sst_hsw *hsw, | ||
1425 | struct sst_hsw_stream *stream, u32 channel) | ||
1426 | { | ||
1427 | if (channel >= 2) | ||
1428 | return 0; | ||
1429 | |||
1430 | return stream->reply.peak_meter_register_address[channel]; | ||
1431 | } | ||
1432 | |||
1433 | u32 sst_hsw_stream_get_vol_reg(struct sst_hsw *hsw, | ||
1434 | struct sst_hsw_stream *stream, u32 channel) | ||
1435 | { | ||
1436 | if (channel >= 2) | ||
1437 | return 0; | ||
1438 | |||
1439 | return stream->reply.volume_register_address[channel]; | ||
1440 | } | ||
1441 | |||
1442 | int sst_hsw_mixer_get_info(struct sst_hsw *hsw) | ||
1443 | { | ||
1444 | struct sst_hsw_ipc_stream_info_reply *reply; | ||
1445 | u32 header; | ||
1446 | int ret; | ||
1447 | |||
1448 | reply = &hsw->mixer_info; | ||
1449 | header = IPC_GLB_TYPE(IPC_GLB_GET_MIXER_STREAM_INFO); | ||
1450 | |||
1451 | trace_ipc_request("get global mixer info", 0); | ||
1452 | |||
1453 | ret = ipc_tx_message_wait(hsw, header, NULL, 0, reply, sizeof(*reply)); | ||
1454 | if (ret < 0) { | ||
1455 | dev_err(hsw->dev, "error: get stream info failed\n"); | ||
1456 | return ret; | ||
1457 | } | ||
1458 | |||
1459 | trace_hsw_mixer_info_reply(reply); | ||
1460 | |||
1461 | return 0; | ||
1462 | } | ||
1463 | |||
1464 | /* Send stream command */ | ||
1465 | static int sst_hsw_stream_operations(struct sst_hsw *hsw, int type, | ||
1466 | int stream_id, int wait) | ||
1467 | { | ||
1468 | u32 header; | ||
1469 | |||
1470 | header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | IPC_STR_TYPE(type); | ||
1471 | header |= (stream_id << IPC_STR_ID_SHIFT); | ||
1472 | |||
1473 | if (wait) | ||
1474 | return ipc_tx_message_wait(hsw, header, NULL, 0, NULL, 0); | ||
1475 | else | ||
1476 | return ipc_tx_message_nowait(hsw, header, NULL, 0); | ||
1477 | } | ||
1478 | |||
1479 | /* Stream ALSA trigger operations */ | ||
1480 | int sst_hsw_stream_pause(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
1481 | int wait) | ||
1482 | { | ||
1483 | int ret; | ||
1484 | |||
1485 | trace_ipc_request("stream pause", stream->reply.stream_hw_id); | ||
1486 | |||
1487 | ret = sst_hsw_stream_operations(hsw, IPC_STR_PAUSE, | ||
1488 | stream->reply.stream_hw_id, wait); | ||
1489 | if (ret < 0) | ||
1490 | dev_err(hsw->dev, "error: failed to pause stream %d\n", | ||
1491 | stream->reply.stream_hw_id); | ||
1492 | |||
1493 | return ret; | ||
1494 | } | ||
1495 | |||
1496 | int sst_hsw_stream_resume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
1497 | int wait) | ||
1498 | { | ||
1499 | int ret; | ||
1500 | |||
1501 | trace_ipc_request("stream resume", stream->reply.stream_hw_id); | ||
1502 | |||
1503 | ret = sst_hsw_stream_operations(hsw, IPC_STR_RESUME, | ||
1504 | stream->reply.stream_hw_id, wait); | ||
1505 | if (ret < 0) | ||
1506 | dev_err(hsw->dev, "error: failed to resume stream %d\n", | ||
1507 | stream->reply.stream_hw_id); | ||
1508 | |||
1509 | return ret; | ||
1510 | } | ||
1511 | |||
1512 | int sst_hsw_stream_reset(struct sst_hsw *hsw, struct sst_hsw_stream *stream) | ||
1513 | { | ||
1514 | int ret, tries = 10; | ||
1515 | |||
1516 | /* dont reset streams that are not commited */ | ||
1517 | if (!stream->commited) | ||
1518 | return 0; | ||
1519 | |||
1520 | /* wait for pause to complete before we reset the stream */ | ||
1521 | while (stream->running && tries--) | ||
1522 | msleep(1); | ||
1523 | if (!tries) { | ||
1524 | dev_err(hsw->dev, "error: reset stream %d still running\n", | ||
1525 | stream->reply.stream_hw_id); | ||
1526 | return -EINVAL; | ||
1527 | } | ||
1528 | |||
1529 | trace_ipc_request("stream reset", stream->reply.stream_hw_id); | ||
1530 | |||
1531 | ret = sst_hsw_stream_operations(hsw, IPC_STR_RESET, | ||
1532 | stream->reply.stream_hw_id, 1); | ||
1533 | if (ret < 0) | ||
1534 | dev_err(hsw->dev, "error: failed to reset stream %d\n", | ||
1535 | stream->reply.stream_hw_id); | ||
1536 | return ret; | ||
1537 | } | ||
1538 | |||
1539 | /* Stream pointer positions */ | ||
1540 | int sst_hsw_get_dsp_position(struct sst_hsw *hsw, | ||
1541 | struct sst_hsw_stream *stream) | ||
1542 | { | ||
1543 | return stream->rpos.position; | ||
1544 | } | ||
1545 | |||
1546 | int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, | ||
1547 | struct sst_hsw_stream *stream, u32 stage_id, u32 position) | ||
1548 | { | ||
1549 | u32 header; | ||
1550 | int ret; | ||
1551 | |||
1552 | trace_stream_write_position(stream->reply.stream_hw_id, position); | ||
1553 | |||
1554 | header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | | ||
1555 | IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); | ||
1556 | header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); | ||
1557 | header |= (IPC_STG_SET_WRITE_POSITION << IPC_STG_TYPE_SHIFT); | ||
1558 | header |= (stage_id << IPC_STG_ID_SHIFT); | ||
1559 | stream->wpos.position = position; | ||
1560 | |||
1561 | ret = ipc_tx_message_nowait(hsw, header, &stream->wpos, | ||
1562 | sizeof(stream->wpos)); | ||
1563 | if (ret < 0) | ||
1564 | dev_err(hsw->dev, "error: stream %d set position %d failed\n", | ||
1565 | stream->reply.stream_hw_id, position); | ||
1566 | |||
1567 | return ret; | ||
1568 | } | ||
1569 | |||
1570 | /* physical BE config */ | ||
1571 | int sst_hsw_device_set_config(struct sst_hsw *hsw, | ||
1572 | enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, | ||
1573 | enum sst_hsw_device_mode mode, u32 clock_divider) | ||
1574 | { | ||
1575 | struct sst_hsw_ipc_device_config_req config; | ||
1576 | u32 header; | ||
1577 | int ret; | ||
1578 | |||
1579 | trace_ipc_request("set device config", dev); | ||
1580 | |||
1581 | config.ssp_interface = dev; | ||
1582 | config.clock_frequency = mclk; | ||
1583 | config.mode = mode; | ||
1584 | config.clock_divider = clock_divider; | ||
1585 | |||
1586 | trace_hsw_device_config_req(&config); | ||
1587 | |||
1588 | header = IPC_GLB_TYPE(IPC_GLB_SET_DEVICE_FORMATS); | ||
1589 | |||
1590 | ret = ipc_tx_message_wait(hsw, header, &config, sizeof(config), | ||
1591 | NULL, 0); | ||
1592 | if (ret < 0) | ||
1593 | dev_err(hsw->dev, "error: set device formats failed\n"); | ||
1594 | |||
1595 | return ret; | ||
1596 | } | ||
1597 | EXPORT_SYMBOL_GPL(sst_hsw_device_set_config); | ||
1598 | |||
1599 | /* DX Config */ | ||
1600 | int sst_hsw_dx_set_state(struct sst_hsw *hsw, | ||
1601 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) | ||
1602 | { | ||
1603 | u32 header, state_; | ||
1604 | int ret; | ||
1605 | |||
1606 | header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); | ||
1607 | state_ = state; | ||
1608 | |||
1609 | trace_ipc_request("PM enter Dx state", state); | ||
1610 | |||
1611 | ret = ipc_tx_message_wait(hsw, header, &state_, sizeof(state_), | ||
1612 | dx, sizeof(dx)); | ||
1613 | if (ret < 0) { | ||
1614 | dev_err(hsw->dev, "ipc: error set dx state %d failed\n", state); | ||
1615 | return ret; | ||
1616 | } | ||
1617 | |||
1618 | dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n", | ||
1619 | dx->entries_no, state); | ||
1620 | |||
1621 | memcpy(&hsw->dx, dx, sizeof(*dx)); | ||
1622 | return 0; | ||
1623 | } | ||
1624 | |||
1625 | /* Used to save state into hsw->dx_reply */ | ||
1626 | int sst_hsw_dx_get_state(struct sst_hsw *hsw, u32 item, | ||
1627 | u32 *offset, u32 *size, u32 *source) | ||
1628 | { | ||
1629 | struct sst_hsw_ipc_dx_memory_item *dx_mem; | ||
1630 | struct sst_hsw_ipc_dx_reply *dx_reply; | ||
1631 | int entry_no; | ||
1632 | |||
1633 | dx_reply = &hsw->dx; | ||
1634 | entry_no = dx_reply->entries_no; | ||
1635 | |||
1636 | trace_ipc_request("PM get Dx state", entry_no); | ||
1637 | |||
1638 | if (item >= entry_no) | ||
1639 | return -EINVAL; | ||
1640 | |||
1641 | dx_mem = &dx_reply->mem_info[item]; | ||
1642 | *offset = dx_mem->offset; | ||
1643 | *size = dx_mem->size; | ||
1644 | *source = dx_mem->source; | ||
1645 | |||
1646 | return 0; | ||
1647 | } | ||
1648 | |||
1649 | static int msg_empty_list_init(struct sst_hsw *hsw) | ||
1650 | { | ||
1651 | int i; | ||
1652 | |||
1653 | hsw->msg = kzalloc(sizeof(struct ipc_message) * | ||
1654 | IPC_EMPTY_LIST_SIZE, GFP_KERNEL); | ||
1655 | if (hsw->msg == NULL) | ||
1656 | return -ENOMEM; | ||
1657 | |||
1658 | for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { | ||
1659 | init_waitqueue_head(&hsw->msg[i].waitq); | ||
1660 | list_add(&hsw->msg[i].list, &hsw->empty_list); | ||
1661 | } | ||
1662 | |||
1663 | return 0; | ||
1664 | } | ||
1665 | |||
1666 | void sst_hsw_set_scratch_module(struct sst_hsw *hsw, | ||
1667 | struct sst_module *scratch) | ||
1668 | { | ||
1669 | hsw->scratch = scratch; | ||
1670 | } | ||
1671 | |||
1672 | struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw) | ||
1673 | { | ||
1674 | return hsw->dsp; | ||
1675 | } | ||
1676 | |||
1677 | static struct sst_dsp_device hsw_dev = { | ||
1678 | .thread = hsw_irq_thread, | ||
1679 | .ops = &haswell_ops, | ||
1680 | }; | ||
1681 | |||
1682 | int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) | ||
1683 | { | ||
1684 | struct sst_hsw_ipc_fw_version version; | ||
1685 | struct sst_hsw *hsw; | ||
1686 | struct sst_fw *hsw_sst_fw; | ||
1687 | int ret; | ||
1688 | |||
1689 | dev_dbg(dev, "initialising Audio DSP IPC\n"); | ||
1690 | |||
1691 | hsw = devm_kzalloc(dev, sizeof(*hsw), GFP_KERNEL); | ||
1692 | if (hsw == NULL) | ||
1693 | return -ENOMEM; | ||
1694 | |||
1695 | hsw->dev = dev; | ||
1696 | INIT_LIST_HEAD(&hsw->stream_list); | ||
1697 | INIT_LIST_HEAD(&hsw->tx_list); | ||
1698 | INIT_LIST_HEAD(&hsw->rx_list); | ||
1699 | INIT_LIST_HEAD(&hsw->empty_list); | ||
1700 | init_waitqueue_head(&hsw->boot_wait); | ||
1701 | init_waitqueue_head(&hsw->wait_txq); | ||
1702 | |||
1703 | ret = msg_empty_list_init(hsw); | ||
1704 | if (ret < 0) | ||
1705 | goto list_err; | ||
1706 | |||
1707 | /* start the IPC message thread */ | ||
1708 | init_kthread_worker(&hsw->kworker); | ||
1709 | hsw->tx_thread = kthread_run(kthread_worker_fn, | ||
1710 | &hsw->kworker, | ||
1711 | dev_name(hsw->dev)); | ||
1712 | if (IS_ERR(hsw->tx_thread)) { | ||
1713 | ret = PTR_ERR(hsw->tx_thread); | ||
1714 | dev_err(hsw->dev, "error: failed to create message TX task\n"); | ||
1715 | goto list_err; | ||
1716 | } | ||
1717 | init_kthread_work(&hsw->kwork, ipc_tx_msgs); | ||
1718 | |||
1719 | hsw_dev.thread_context = hsw; | ||
1720 | |||
1721 | /* init SST shim */ | ||
1722 | hsw->dsp = sst_dsp_new(dev, &hsw_dev, pdata); | ||
1723 | if (hsw->dsp == NULL) { | ||
1724 | ret = -ENODEV; | ||
1725 | goto list_err; | ||
1726 | } | ||
1727 | |||
1728 | /* keep the DSP in reset state for base FW loading */ | ||
1729 | sst_dsp_reset(hsw->dsp); | ||
1730 | |||
1731 | hsw_sst_fw = sst_fw_new(hsw->dsp, pdata->fw, hsw); | ||
1732 | |||
1733 | if (hsw_sst_fw == NULL) { | ||
1734 | ret = -ENODEV; | ||
1735 | dev_err(dev, "error: failed to load firmware\n"); | ||
1736 | goto fw_err; | ||
1737 | } | ||
1738 | |||
1739 | /* wait for DSP boot completion */ | ||
1740 | sst_dsp_boot(hsw->dsp); | ||
1741 | ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete, | ||
1742 | msecs_to_jiffies(IPC_BOOT_MSECS)); | ||
1743 | if (ret == 0) { | ||
1744 | ret = -EIO; | ||
1745 | dev_err(hsw->dev, "error: ADSP boot timeout\n"); | ||
1746 | goto boot_err; | ||
1747 | } | ||
1748 | |||
1749 | /* get the FW version */ | ||
1750 | sst_hsw_fw_get_version(hsw, &version); | ||
1751 | dev_info(hsw->dev, "FW loaded: type %d - version: %d.%d build %d\n", | ||
1752 | version.type, version.major, version.minor, version.build); | ||
1753 | |||
1754 | /* get the globalmixer */ | ||
1755 | ret = sst_hsw_mixer_get_info(hsw); | ||
1756 | if (ret < 0) { | ||
1757 | dev_err(hsw->dev, "error: failed to get stream info\n"); | ||
1758 | goto boot_err; | ||
1759 | } | ||
1760 | |||
1761 | pdata->dsp = hsw; | ||
1762 | return 0; | ||
1763 | |||
1764 | boot_err: | ||
1765 | sst_dsp_reset(hsw->dsp); | ||
1766 | sst_fw_free(hsw_sst_fw); | ||
1767 | fw_err: | ||
1768 | sst_dsp_free(hsw->dsp); | ||
1769 | kfree(hsw->msg); | ||
1770 | list_err: | ||
1771 | return ret; | ||
1772 | } | ||
1773 | EXPORT_SYMBOL_GPL(sst_hsw_dsp_init); | ||
1774 | |||
1775 | void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata) | ||
1776 | { | ||
1777 | struct sst_hsw *hsw = pdata->dsp; | ||
1778 | |||
1779 | sst_dsp_reset(hsw->dsp); | ||
1780 | sst_fw_free_all(hsw->dsp); | ||
1781 | sst_dsp_free(hsw->dsp); | ||
1782 | kfree(hsw->scratch); | ||
1783 | kfree(hsw->msg); | ||
1784 | } | ||
1785 | EXPORT_SYMBOL_GPL(sst_hsw_dsp_free); | ||
diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/sst-haswell-ipc.h new file mode 100644 index 000000000000..d517929ccc38 --- /dev/null +++ b/sound/soc/intel/sst-haswell-ipc.h | |||
@@ -0,0 +1,488 @@ | |||
1 | /* | ||
2 | * Intel SST Haswell/Broadwell IPC Support | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __SST_HASWELL_IPC_H | ||
18 | #define __SST_HASWELL_IPC_H | ||
19 | |||
20 | #include <linux/types.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | |||
24 | #define SST_HSW_NO_CHANNELS 2 | ||
25 | #define SST_HSW_MAX_DX_REGIONS 14 | ||
26 | |||
27 | #define SST_HSW_FW_LOG_CONFIG_DWORDS 12 | ||
28 | #define SST_HSW_GLOBAL_LOG 15 | ||
29 | |||
30 | /** | ||
31 | * Upfront defined maximum message size that is | ||
32 | * expected by the in/out communication pipes in FW. | ||
33 | */ | ||
34 | #define SST_HSW_IPC_MAX_PAYLOAD_SIZE 400 | ||
35 | #define SST_HSW_MAX_INFO_SIZE 64 | ||
36 | #define SST_HSW_BUILD_HASH_LENGTH 40 | ||
37 | |||
38 | struct sst_hsw; | ||
39 | struct sst_hsw_stream; | ||
40 | struct sst_hsw_log_stream; | ||
41 | struct sst_pdata; | ||
42 | struct sst_module; | ||
43 | extern struct sst_ops haswell_ops; | ||
44 | |||
45 | /* Stream Allocate Path ID */ | ||
46 | enum sst_hsw_stream_path_id { | ||
47 | SST_HSW_STREAM_PATH_SSP0_OUT = 0, | ||
48 | SST_HSW_STREAM_PATH_SSP0_IN = 1, | ||
49 | SST_HSW_STREAM_PATH_MAX_PATH_ID = 2, | ||
50 | }; | ||
51 | |||
52 | /* Stream Allocate Stream Type */ | ||
53 | enum sst_hsw_stream_type { | ||
54 | SST_HSW_STREAM_TYPE_RENDER = 0, | ||
55 | SST_HSW_STREAM_TYPE_SYSTEM = 1, | ||
56 | SST_HSW_STREAM_TYPE_CAPTURE = 2, | ||
57 | SST_HSW_STREAM_TYPE_LOOPBACK = 3, | ||
58 | SST_HSW_STREAM_TYPE_MAX_STREAM_TYPE = 4, | ||
59 | }; | ||
60 | |||
61 | /* Stream Allocate Stream Format */ | ||
62 | enum sst_hsw_stream_format { | ||
63 | SST_HSW_STREAM_FORMAT_PCM_FORMAT = 0, | ||
64 | SST_HSW_STREAM_FORMAT_MP3_FORMAT = 1, | ||
65 | SST_HSW_STREAM_FORMAT_AAC_FORMAT = 2, | ||
66 | SST_HSW_STREAM_FORMAT_MAX_FORMAT_ID = 3, | ||
67 | }; | ||
68 | |||
69 | /* Device ID */ | ||
70 | enum sst_hsw_device_id { | ||
71 | SST_HSW_DEVICE_SSP_0 = 0, | ||
72 | SST_HSW_DEVICE_SSP_1 = 1, | ||
73 | }; | ||
74 | |||
75 | /* Device Master Clock Frequency */ | ||
76 | enum sst_hsw_device_mclk { | ||
77 | SST_HSW_DEVICE_MCLK_OFF = 0, | ||
78 | SST_HSW_DEVICE_MCLK_FREQ_6_MHZ = 1, | ||
79 | SST_HSW_DEVICE_MCLK_FREQ_12_MHZ = 2, | ||
80 | SST_HSW_DEVICE_MCLK_FREQ_24_MHZ = 3, | ||
81 | }; | ||
82 | |||
83 | /* Device Clock Master */ | ||
84 | enum sst_hsw_device_mode { | ||
85 | SST_HSW_DEVICE_CLOCK_SLAVE = 0, | ||
86 | SST_HSW_DEVICE_CLOCK_MASTER = 1, | ||
87 | }; | ||
88 | |||
89 | /* DX Power State */ | ||
90 | enum sst_hsw_dx_state { | ||
91 | SST_HSW_DX_STATE_D0 = 0, | ||
92 | SST_HSW_DX_STATE_D1 = 1, | ||
93 | SST_HSW_DX_STATE_D3 = 3, | ||
94 | SST_HSW_DX_STATE_MAX = 3, | ||
95 | }; | ||
96 | |||
97 | /* Audio stream stage IDs */ | ||
98 | enum sst_hsw_fx_stage_id { | ||
99 | SST_HSW_STAGE_ID_WAVES = 0, | ||
100 | SST_HSW_STAGE_ID_DTS = 1, | ||
101 | SST_HSW_STAGE_ID_DOLBY = 2, | ||
102 | SST_HSW_STAGE_ID_BOOST = 3, | ||
103 | SST_HSW_STAGE_ID_MAX_FX_ID | ||
104 | }; | ||
105 | |||
106 | /* DX State Type */ | ||
107 | enum sst_hsw_dx_type { | ||
108 | SST_HSW_DX_TYPE_FW_IMAGE = 0, | ||
109 | SST_HSW_DX_TYPE_MEMORY_DUMP = 1 | ||
110 | }; | ||
111 | |||
112 | /* Volume Curve Type*/ | ||
113 | enum sst_hsw_volume_curve { | ||
114 | SST_HSW_VOLUME_CURVE_NONE = 0, | ||
115 | SST_HSW_VOLUME_CURVE_FADE = 1 | ||
116 | }; | ||
117 | |||
118 | /* Sample ordering */ | ||
119 | enum sst_hsw_interleaving { | ||
120 | SST_HSW_INTERLEAVING_PER_CHANNEL = 0, | ||
121 | SST_HSW_INTERLEAVING_PER_SAMPLE = 1, | ||
122 | }; | ||
123 | |||
124 | /* Channel indices */ | ||
125 | enum sst_hsw_channel_index { | ||
126 | SST_HSW_CHANNEL_LEFT = 0, | ||
127 | SST_HSW_CHANNEL_CENTER = 1, | ||
128 | SST_HSW_CHANNEL_RIGHT = 2, | ||
129 | SST_HSW_CHANNEL_LEFT_SURROUND = 3, | ||
130 | SST_HSW_CHANNEL_CENTER_SURROUND = 3, | ||
131 | SST_HSW_CHANNEL_RIGHT_SURROUND = 4, | ||
132 | SST_HSW_CHANNEL_LFE = 7, | ||
133 | SST_HSW_CHANNEL_INVALID = 0xF, | ||
134 | }; | ||
135 | |||
136 | /* List of supported channel maps. */ | ||
137 | enum sst_hsw_channel_config { | ||
138 | SST_HSW_CHANNEL_CONFIG_MONO = 0, /* mono only. */ | ||
139 | SST_HSW_CHANNEL_CONFIG_STEREO = 1, /* L & R. */ | ||
140 | SST_HSW_CHANNEL_CONFIG_2_POINT_1 = 2, /* L, R & LFE; PCM only. */ | ||
141 | SST_HSW_CHANNEL_CONFIG_3_POINT_0 = 3, /* L, C & R; MP3 & AAC only. */ | ||
142 | SST_HSW_CHANNEL_CONFIG_3_POINT_1 = 4, /* L, C, R & LFE; PCM only. */ | ||
143 | SST_HSW_CHANNEL_CONFIG_QUATRO = 5, /* L, R, Ls & Rs; PCM only. */ | ||
144 | SST_HSW_CHANNEL_CONFIG_4_POINT_0 = 6, /* L, C, R & Cs; MP3 & AAC only. */ | ||
145 | SST_HSW_CHANNEL_CONFIG_5_POINT_0 = 7, /* L, C, R, Ls & Rs. */ | ||
146 | SST_HSW_CHANNEL_CONFIG_5_POINT_1 = 8, /* L, C, R, Ls, Rs & LFE. */ | ||
147 | SST_HSW_CHANNEL_CONFIG_DUAL_MONO = 9, /* One channel replicated in two. */ | ||
148 | SST_HSW_CHANNEL_CONFIG_INVALID, | ||
149 | }; | ||
150 | |||
151 | /* List of supported bit depths. */ | ||
152 | enum sst_hsw_bitdepth { | ||
153 | SST_HSW_DEPTH_8BIT = 8, | ||
154 | SST_HSW_DEPTH_16BIT = 16, | ||
155 | SST_HSW_DEPTH_24BIT = 24, /* Default. */ | ||
156 | SST_HSW_DEPTH_32BIT = 32, | ||
157 | SST_HSW_DEPTH_INVALID = 33, | ||
158 | }; | ||
159 | |||
160 | enum sst_hsw_module_id { | ||
161 | SST_HSW_MODULE_BASE_FW = 0x0, | ||
162 | SST_HSW_MODULE_MP3 = 0x1, | ||
163 | SST_HSW_MODULE_AAC_5_1 = 0x2, | ||
164 | SST_HSW_MODULE_AAC_2_0 = 0x3, | ||
165 | SST_HSW_MODULE_SRC = 0x4, | ||
166 | SST_HSW_MODULE_WAVES = 0x5, | ||
167 | SST_HSW_MODULE_DOLBY = 0x6, | ||
168 | SST_HSW_MODULE_BOOST = 0x7, | ||
169 | SST_HSW_MODULE_LPAL = 0x8, | ||
170 | SST_HSW_MODULE_DTS = 0x9, | ||
171 | SST_HSW_MODULE_PCM_CAPTURE = 0xA, | ||
172 | SST_HSW_MODULE_PCM_SYSTEM = 0xB, | ||
173 | SST_HSW_MODULE_PCM_REFERENCE = 0xC, | ||
174 | SST_HSW_MODULE_PCM = 0xD, | ||
175 | SST_HSW_MODULE_BLUETOOTH_RENDER_MODULE = 0xE, | ||
176 | SST_HSW_MODULE_BLUETOOTH_CAPTURE_MODULE = 0xF, | ||
177 | SST_HSW_MAX_MODULE_ID, | ||
178 | }; | ||
179 | |||
180 | enum sst_hsw_performance_action { | ||
181 | SST_HSW_PERF_START = 0, | ||
182 | SST_HSW_PERF_STOP = 1, | ||
183 | }; | ||
184 | |||
185 | /* SST firmware module info */ | ||
186 | struct sst_hsw_module_info { | ||
187 | u8 name[SST_HSW_MAX_INFO_SIZE]; | ||
188 | u8 version[SST_HSW_MAX_INFO_SIZE]; | ||
189 | } __attribute__((packed)); | ||
190 | |||
191 | /* Module entry point */ | ||
192 | struct sst_hsw_module_entry { | ||
193 | enum sst_hsw_module_id module_id; | ||
194 | u32 entry_point; | ||
195 | } __attribute__((packed)); | ||
196 | |||
197 | /* Module map - alignement matches DSP */ | ||
198 | struct sst_hsw_module_map { | ||
199 | u8 module_entries_count; | ||
200 | struct sst_hsw_module_entry module_entries[1]; | ||
201 | } __attribute__((packed)); | ||
202 | |||
203 | struct sst_hsw_memory_info { | ||
204 | u32 offset; | ||
205 | u32 size; | ||
206 | } __attribute__((packed)); | ||
207 | |||
208 | struct sst_hsw_fx_enable { | ||
209 | struct sst_hsw_module_map module_map; | ||
210 | struct sst_hsw_memory_info persistent_mem; | ||
211 | } __attribute__((packed)); | ||
212 | |||
213 | struct sst_hsw_get_fx_param { | ||
214 | u32 parameter_id; | ||
215 | u32 param_size; | ||
216 | } __attribute__((packed)); | ||
217 | |||
218 | struct sst_hsw_perf_action { | ||
219 | u32 action; | ||
220 | } __attribute__((packed)); | ||
221 | |||
222 | struct sst_hsw_perf_data { | ||
223 | u64 timestamp; | ||
224 | u64 cycles; | ||
225 | u64 datatime; | ||
226 | } __attribute__((packed)); | ||
227 | |||
228 | /* FW version */ | ||
229 | struct sst_hsw_ipc_fw_version { | ||
230 | u8 build; | ||
231 | u8 minor; | ||
232 | u8 major; | ||
233 | u8 type; | ||
234 | u8 fw_build_hash[SST_HSW_BUILD_HASH_LENGTH]; | ||
235 | u32 fw_log_providers_hash; | ||
236 | } __attribute__((packed)); | ||
237 | |||
238 | /* Stream ring info */ | ||
239 | struct sst_hsw_ipc_stream_ring { | ||
240 | u32 ring_pt_address; | ||
241 | u32 num_pages; | ||
242 | u32 ring_size; | ||
243 | u32 ring_offset; | ||
244 | u32 ring_first_pfn; | ||
245 | } __attribute__((packed)); | ||
246 | |||
247 | /* Debug Dump Log Enable Request */ | ||
248 | struct sst_hsw_ipc_debug_log_enable_req { | ||
249 | struct sst_hsw_ipc_stream_ring ringinfo; | ||
250 | u32 config[SST_HSW_FW_LOG_CONFIG_DWORDS]; | ||
251 | } __attribute__((packed)); | ||
252 | |||
253 | /* Debug Dump Log Reply */ | ||
254 | struct sst_hsw_ipc_debug_log_reply { | ||
255 | u32 log_buffer_begining; | ||
256 | u32 log_buffer_size; | ||
257 | } __attribute__((packed)); | ||
258 | |||
259 | /* Stream glitch position */ | ||
260 | struct sst_hsw_ipc_stream_glitch_position { | ||
261 | u32 glitch_type; | ||
262 | u32 present_pos; | ||
263 | u32 write_pos; | ||
264 | } __attribute__((packed)); | ||
265 | |||
266 | /* Stream get position */ | ||
267 | struct sst_hsw_ipc_stream_get_position { | ||
268 | u32 position; | ||
269 | u32 fw_cycle_count; | ||
270 | } __attribute__((packed)); | ||
271 | |||
272 | /* Stream set position */ | ||
273 | struct sst_hsw_ipc_stream_set_position { | ||
274 | u32 position; | ||
275 | u32 end_of_buffer; | ||
276 | } __attribute__((packed)); | ||
277 | |||
278 | /* Stream Free Request */ | ||
279 | struct sst_hsw_ipc_stream_free_req { | ||
280 | u8 stream_id; | ||
281 | u8 reserved[3]; | ||
282 | } __attribute__((packed)); | ||
283 | |||
284 | /* Set Volume Request */ | ||
285 | struct sst_hsw_ipc_volume_req { | ||
286 | u32 channel; | ||
287 | u32 target_volume; | ||
288 | u64 curve_duration; | ||
289 | u32 curve_type; | ||
290 | } __attribute__((packed)); | ||
291 | |||
292 | /* Device Configuration Request */ | ||
293 | struct sst_hsw_ipc_device_config_req { | ||
294 | u32 ssp_interface; | ||
295 | u32 clock_frequency; | ||
296 | u32 mode; | ||
297 | u16 clock_divider; | ||
298 | u16 reserved; | ||
299 | } __attribute__((packed)); | ||
300 | |||
301 | /* Audio Data formats */ | ||
302 | struct sst_hsw_audio_data_format_ipc { | ||
303 | u32 frequency; | ||
304 | u32 bitdepth; | ||
305 | u32 map; | ||
306 | u32 config; | ||
307 | u32 style; | ||
308 | u8 ch_num; | ||
309 | u8 valid_bit; | ||
310 | u8 reserved[2]; | ||
311 | } __attribute__((packed)); | ||
312 | |||
313 | /* Stream Allocate Request */ | ||
314 | struct sst_hsw_ipc_stream_alloc_req { | ||
315 | u8 path_id; | ||
316 | u8 stream_type; | ||
317 | u8 format_id; | ||
318 | u8 reserved; | ||
319 | struct sst_hsw_audio_data_format_ipc format; | ||
320 | struct sst_hsw_ipc_stream_ring ringinfo; | ||
321 | struct sst_hsw_module_map map; | ||
322 | struct sst_hsw_memory_info persistent_mem; | ||
323 | struct sst_hsw_memory_info scratch_mem; | ||
324 | u32 number_of_notifications; | ||
325 | } __attribute__((packed)); | ||
326 | |||
327 | /* Stream Allocate Reply */ | ||
328 | struct sst_hsw_ipc_stream_alloc_reply { | ||
329 | u32 stream_hw_id; | ||
330 | u32 mixer_hw_id; // returns rate ???? | ||
331 | u32 read_position_register_address; | ||
332 | u32 presentation_position_register_address; | ||
333 | u32 peak_meter_register_address[SST_HSW_NO_CHANNELS]; | ||
334 | u32 volume_register_address[SST_HSW_NO_CHANNELS]; | ||
335 | } __attribute__((packed)); | ||
336 | |||
337 | /* Get Mixer Stream Info */ | ||
338 | struct sst_hsw_ipc_stream_info_reply { | ||
339 | u32 mixer_hw_id; | ||
340 | u32 peak_meter_register_address[SST_HSW_NO_CHANNELS]; | ||
341 | u32 volume_register_address[SST_HSW_NO_CHANNELS]; | ||
342 | } __attribute__((packed)); | ||
343 | |||
344 | /* DX State Request */ | ||
345 | struct sst_hsw_ipc_dx_req { | ||
346 | u8 state; | ||
347 | u8 reserved[3]; | ||
348 | } __attribute__((packed)); | ||
349 | |||
350 | /* DX State Reply Memory Info Item */ | ||
351 | struct sst_hsw_ipc_dx_memory_item { | ||
352 | u32 offset; | ||
353 | u32 size; | ||
354 | u32 source; | ||
355 | } __attribute__((packed)); | ||
356 | |||
357 | /* DX State Reply */ | ||
358 | struct sst_hsw_ipc_dx_reply { | ||
359 | u32 entries_no; | ||
360 | struct sst_hsw_ipc_dx_memory_item mem_info[SST_HSW_MAX_DX_REGIONS]; | ||
361 | } __attribute__((packed)); | ||
362 | |||
363 | struct sst_hsw_ipc_fw_version; | ||
364 | |||
365 | /* SST Init & Free */ | ||
366 | struct sst_hsw *sst_hsw_new(struct device *dev, const u8 *fw, size_t fw_length, | ||
367 | u32 fw_offset); | ||
368 | void sst_hsw_free(struct sst_hsw *hsw); | ||
369 | int sst_hsw_fw_get_version(struct sst_hsw *hsw, | ||
370 | struct sst_hsw_ipc_fw_version *version); | ||
371 | u32 create_channel_map(enum sst_hsw_channel_config config); | ||
372 | |||
373 | /* Stream Mixer Controls - */ | ||
374 | int sst_hsw_stream_mute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
375 | u32 stage_id, u32 channel); | ||
376 | int sst_hsw_stream_unmute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
377 | u32 stage_id, u32 channel); | ||
378 | |||
379 | int sst_hsw_stream_set_volume(struct sst_hsw *hsw, | ||
380 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume); | ||
381 | int sst_hsw_stream_get_volume(struct sst_hsw *hsw, | ||
382 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 *volume); | ||
383 | |||
384 | int sst_hsw_stream_set_volume_curve(struct sst_hsw *hsw, | ||
385 | struct sst_hsw_stream *stream, u64 curve_duration, | ||
386 | enum sst_hsw_volume_curve curve); | ||
387 | |||
388 | /* Global Mixer Controls - */ | ||
389 | int sst_hsw_mixer_mute(struct sst_hsw *hsw, u32 stage_id, u32 channel); | ||
390 | int sst_hsw_mixer_unmute(struct sst_hsw *hsw, u32 stage_id, u32 channel); | ||
391 | |||
392 | int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | ||
393 | u32 volume); | ||
394 | int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | ||
395 | u32 *volume); | ||
396 | |||
397 | int sst_hsw_mixer_set_volume_curve(struct sst_hsw *hsw, | ||
398 | u64 curve_duration, enum sst_hsw_volume_curve curve); | ||
399 | |||
400 | /* Stream API */ | ||
401 | struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, | ||
402 | u32 (*get_write_position)(struct sst_hsw_stream *stream, void *data), | ||
403 | void *data); | ||
404 | |||
405 | int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream); | ||
406 | |||
407 | /* Stream Configuration */ | ||
408 | int sst_hsw_stream_format(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
409 | enum sst_hsw_stream_path_id path_id, | ||
410 | enum sst_hsw_stream_type stream_type, | ||
411 | enum sst_hsw_stream_format format_id); | ||
412 | |||
413 | int sst_hsw_stream_buffer(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
414 | u32 ring_pt_address, u32 num_pages, | ||
415 | u32 ring_size, u32 ring_offset, u32 ring_first_pfn); | ||
416 | |||
417 | int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream); | ||
418 | |||
419 | int sst_hsw_stream_set_valid(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
420 | u32 bits); | ||
421 | int sst_hsw_stream_set_rate(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
422 | int rate); | ||
423 | int sst_hsw_stream_set_bits(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
424 | enum sst_hsw_bitdepth bits); | ||
425 | int sst_hsw_stream_set_channels(struct sst_hsw *hsw, | ||
426 | struct sst_hsw_stream *stream, int channels); | ||
427 | int sst_hsw_stream_set_map_config(struct sst_hsw *hsw, | ||
428 | struct sst_hsw_stream *stream, u32 map, | ||
429 | enum sst_hsw_channel_config config); | ||
430 | int sst_hsw_stream_set_style(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
431 | enum sst_hsw_interleaving style); | ||
432 | int sst_hsw_stream_set_module_info(struct sst_hsw *hsw, | ||
433 | struct sst_hsw_stream *stream, enum sst_hsw_module_id module_id, | ||
434 | u32 entry_point); | ||
435 | int sst_hsw_stream_set_pmemory_info(struct sst_hsw *hsw, | ||
436 | struct sst_hsw_stream *stream, u32 offset, u32 size); | ||
437 | int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw, | ||
438 | struct sst_hsw_stream *stream, u32 offset, u32 size); | ||
439 | int sst_hsw_stream_get_hw_id(struct sst_hsw *hsw, | ||
440 | struct sst_hsw_stream *stream); | ||
441 | int sst_hsw_stream_get_mixer_id(struct sst_hsw *hsw, | ||
442 | struct sst_hsw_stream *stream); | ||
443 | u32 sst_hsw_stream_get_read_reg(struct sst_hsw *hsw, | ||
444 | struct sst_hsw_stream *stream); | ||
445 | u32 sst_hsw_stream_get_pointer_reg(struct sst_hsw *hsw, | ||
446 | struct sst_hsw_stream *stream); | ||
447 | u32 sst_hsw_stream_get_peak_reg(struct sst_hsw *hsw, | ||
448 | struct sst_hsw_stream *stream, u32 channel); | ||
449 | u32 sst_hsw_stream_get_vol_reg(struct sst_hsw *hsw, | ||
450 | struct sst_hsw_stream *stream, u32 channel); | ||
451 | int sst_hsw_mixer_get_info(struct sst_hsw *hsw); | ||
452 | |||
453 | /* Stream ALSA trigger operations */ | ||
454 | int sst_hsw_stream_pause(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
455 | int wait); | ||
456 | int sst_hsw_stream_resume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
457 | int wait); | ||
458 | int sst_hsw_stream_reset(struct sst_hsw *hsw, struct sst_hsw_stream *stream); | ||
459 | |||
460 | /* Stream pointer positions */ | ||
461 | int sst_hsw_stream_get_read_pos(struct sst_hsw *hsw, | ||
462 | struct sst_hsw_stream *stream, u32 *position); | ||
463 | int sst_hsw_stream_get_write_pos(struct sst_hsw *hsw, | ||
464 | struct sst_hsw_stream *stream, u32 *position); | ||
465 | int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, | ||
466 | struct sst_hsw_stream *stream, u32 stage_id, u32 position); | ||
467 | int sst_hsw_get_dsp_position(struct sst_hsw *hsw, | ||
468 | struct sst_hsw_stream *stream); | ||
469 | |||
470 | /* HW port config */ | ||
471 | int sst_hsw_device_set_config(struct sst_hsw *hsw, | ||
472 | enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, | ||
473 | enum sst_hsw_device_mode mode, u32 clock_divider); | ||
474 | |||
475 | /* DX Config */ | ||
476 | int sst_hsw_dx_set_state(struct sst_hsw *hsw, | ||
477 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx); | ||
478 | int sst_hsw_dx_get_state(struct sst_hsw *hsw, u32 item, | ||
479 | u32 *offset, u32 *size, u32 *source); | ||
480 | |||
481 | /* init */ | ||
482 | int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata); | ||
483 | void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata); | ||
484 | struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw); | ||
485 | void sst_hsw_set_scratch_module(struct sst_hsw *hsw, | ||
486 | struct sst_module *scratch); | ||
487 | |||
488 | #endif | ||
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c new file mode 100644 index 000000000000..0a32dd13a23d --- /dev/null +++ b/sound/soc/intel/sst-haswell-pcm.c | |||
@@ -0,0 +1,872 @@ | |||
1 | /* | ||
2 | * Intel SST Haswell/Broadwell PCM Support | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <asm/page.h> | ||
23 | #include <asm/pgtable.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/dmaengine_pcm.h> | ||
28 | #include <sound/soc.h> | ||
29 | #include <sound/tlv.h> | ||
30 | #include <sound/compress_driver.h> | ||
31 | |||
32 | #include "sst-haswell-ipc.h" | ||
33 | #include "sst-dsp-priv.h" | ||
34 | #include "sst-dsp.h" | ||
35 | |||
36 | #define HSW_PCM_COUNT 6 | ||
37 | #define HSW_VOLUME_MAX 0x7FFFFFFF /* 0dB */ | ||
38 | |||
39 | /* simple volume table */ | ||
40 | static const u32 volume_map[] = { | ||
41 | HSW_VOLUME_MAX >> 30, | ||
42 | HSW_VOLUME_MAX >> 29, | ||
43 | HSW_VOLUME_MAX >> 28, | ||
44 | HSW_VOLUME_MAX >> 27, | ||
45 | HSW_VOLUME_MAX >> 26, | ||
46 | HSW_VOLUME_MAX >> 25, | ||
47 | HSW_VOLUME_MAX >> 24, | ||
48 | HSW_VOLUME_MAX >> 23, | ||
49 | HSW_VOLUME_MAX >> 22, | ||
50 | HSW_VOLUME_MAX >> 21, | ||
51 | HSW_VOLUME_MAX >> 20, | ||
52 | HSW_VOLUME_MAX >> 19, | ||
53 | HSW_VOLUME_MAX >> 18, | ||
54 | HSW_VOLUME_MAX >> 17, | ||
55 | HSW_VOLUME_MAX >> 16, | ||
56 | HSW_VOLUME_MAX >> 15, | ||
57 | HSW_VOLUME_MAX >> 14, | ||
58 | HSW_VOLUME_MAX >> 13, | ||
59 | HSW_VOLUME_MAX >> 12, | ||
60 | HSW_VOLUME_MAX >> 11, | ||
61 | HSW_VOLUME_MAX >> 10, | ||
62 | HSW_VOLUME_MAX >> 9, | ||
63 | HSW_VOLUME_MAX >> 8, | ||
64 | HSW_VOLUME_MAX >> 7, | ||
65 | HSW_VOLUME_MAX >> 6, | ||
66 | HSW_VOLUME_MAX >> 5, | ||
67 | HSW_VOLUME_MAX >> 4, | ||
68 | HSW_VOLUME_MAX >> 3, | ||
69 | HSW_VOLUME_MAX >> 2, | ||
70 | HSW_VOLUME_MAX >> 1, | ||
71 | HSW_VOLUME_MAX >> 0, | ||
72 | }; | ||
73 | |||
74 | #define HSW_PCM_PERIODS_MAX 64 | ||
75 | #define HSW_PCM_PERIODS_MIN 2 | ||
76 | |||
77 | static const struct snd_pcm_hardware hsw_pcm_hardware = { | ||
78 | .info = SNDRV_PCM_INFO_MMAP | | ||
79 | SNDRV_PCM_INFO_MMAP_VALID | | ||
80 | SNDRV_PCM_INFO_INTERLEAVED | | ||
81 | SNDRV_PCM_INFO_PAUSE | | ||
82 | SNDRV_PCM_INFO_RESUME | | ||
83 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, | ||
84 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE | | ||
85 | SNDRV_PCM_FMTBIT_S32_LE, | ||
86 | .period_bytes_min = PAGE_SIZE, | ||
87 | .period_bytes_max = (HSW_PCM_PERIODS_MAX / HSW_PCM_PERIODS_MIN) * PAGE_SIZE, | ||
88 | .periods_min = HSW_PCM_PERIODS_MIN, | ||
89 | .periods_max = HSW_PCM_PERIODS_MAX, | ||
90 | .buffer_bytes_max = HSW_PCM_PERIODS_MAX * PAGE_SIZE, | ||
91 | }; | ||
92 | |||
93 | /* private data for each PCM DSP stream */ | ||
94 | struct hsw_pcm_data { | ||
95 | int dai_id; | ||
96 | struct sst_hsw_stream *stream; | ||
97 | u32 volume[2]; | ||
98 | struct snd_pcm_substream *substream; | ||
99 | struct snd_compr_stream *cstream; | ||
100 | unsigned int wpos; | ||
101 | struct mutex mutex; | ||
102 | }; | ||
103 | |||
104 | /* private data for the driver */ | ||
105 | struct hsw_priv_data { | ||
106 | /* runtime DSP */ | ||
107 | struct sst_hsw *hsw; | ||
108 | |||
109 | /* page tables */ | ||
110 | unsigned char *pcm_pg[HSW_PCM_COUNT][2]; | ||
111 | |||
112 | /* DAI data */ | ||
113 | struct hsw_pcm_data pcm[HSW_PCM_COUNT]; | ||
114 | }; | ||
115 | |||
116 | static inline u32 hsw_mixer_to_ipc(unsigned int value) | ||
117 | { | ||
118 | if (value >= ARRAY_SIZE(volume_map)) | ||
119 | return volume_map[0]; | ||
120 | else | ||
121 | return volume_map[value]; | ||
122 | } | ||
123 | |||
124 | static inline unsigned int hsw_ipc_to_mixer(u32 value) | ||
125 | { | ||
126 | int i; | ||
127 | |||
128 | for (i = 0; i < ARRAY_SIZE(volume_map); i++) { | ||
129 | if (volume_map[i] >= value) | ||
130 | return i; | ||
131 | } | ||
132 | |||
133 | return i - 1; | ||
134 | } | ||
135 | |||
136 | static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol, | ||
137 | struct snd_ctl_elem_value *ucontrol) | ||
138 | { | ||
139 | struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); | ||
140 | struct soc_mixer_control *mc = | ||
141 | (struct soc_mixer_control *)kcontrol->private_value; | ||
142 | struct hsw_priv_data *pdata = | ||
143 | snd_soc_platform_get_drvdata(platform); | ||
144 | struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; | ||
145 | struct sst_hsw *hsw = pdata->hsw; | ||
146 | u32 volume; | ||
147 | |||
148 | mutex_lock(&pcm_data->mutex); | ||
149 | |||
150 | if (!pcm_data->stream) { | ||
151 | pcm_data->volume[0] = | ||
152 | hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); | ||
153 | pcm_data->volume[1] = | ||
154 | hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); | ||
155 | mutex_unlock(&pcm_data->mutex); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | if (ucontrol->value.integer.value[0] == | ||
160 | ucontrol->value.integer.value[1]) { | ||
161 | volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); | ||
162 | sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 2, volume); | ||
163 | } else { | ||
164 | volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); | ||
165 | sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 0, volume); | ||
166 | volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); | ||
167 | sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 1, volume); | ||
168 | } | ||
169 | |||
170 | mutex_unlock(&pcm_data->mutex); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int hsw_stream_volume_get(struct snd_kcontrol *kcontrol, | ||
175 | struct snd_ctl_elem_value *ucontrol) | ||
176 | { | ||
177 | struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); | ||
178 | struct soc_mixer_control *mc = | ||
179 | (struct soc_mixer_control *)kcontrol->private_value; | ||
180 | struct hsw_priv_data *pdata = | ||
181 | snd_soc_platform_get_drvdata(platform); | ||
182 | struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; | ||
183 | struct sst_hsw *hsw = pdata->hsw; | ||
184 | u32 volume; | ||
185 | |||
186 | mutex_lock(&pcm_data->mutex); | ||
187 | |||
188 | if (!pcm_data->stream) { | ||
189 | ucontrol->value.integer.value[0] = | ||
190 | hsw_ipc_to_mixer(pcm_data->volume[0]); | ||
191 | ucontrol->value.integer.value[1] = | ||
192 | hsw_ipc_to_mixer(pcm_data->volume[1]); | ||
193 | mutex_unlock(&pcm_data->mutex); | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | sst_hsw_stream_get_volume(hsw, pcm_data->stream, 0, 0, &volume); | ||
198 | ucontrol->value.integer.value[0] = hsw_ipc_to_mixer(volume); | ||
199 | sst_hsw_stream_get_volume(hsw, pcm_data->stream, 0, 1, &volume); | ||
200 | ucontrol->value.integer.value[1] = hsw_ipc_to_mixer(volume); | ||
201 | mutex_unlock(&pcm_data->mutex); | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int hsw_volume_put(struct snd_kcontrol *kcontrol, | ||
207 | struct snd_ctl_elem_value *ucontrol) | ||
208 | { | ||
209 | struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); | ||
210 | struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform); | ||
211 | struct sst_hsw *hsw = pdata->hsw; | ||
212 | u32 volume; | ||
213 | |||
214 | if (ucontrol->value.integer.value[0] == | ||
215 | ucontrol->value.integer.value[1]) { | ||
216 | |||
217 | volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); | ||
218 | sst_hsw_mixer_set_volume(hsw, 0, 2, volume); | ||
219 | |||
220 | } else { | ||
221 | volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); | ||
222 | sst_hsw_mixer_set_volume(hsw, 0, 0, volume); | ||
223 | |||
224 | volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); | ||
225 | sst_hsw_mixer_set_volume(hsw, 0, 1, volume); | ||
226 | } | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int hsw_volume_get(struct snd_kcontrol *kcontrol, | ||
232 | struct snd_ctl_elem_value *ucontrol) | ||
233 | { | ||
234 | struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); | ||
235 | struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform); | ||
236 | struct sst_hsw *hsw = pdata->hsw; | ||
237 | unsigned int volume = 0; | ||
238 | |||
239 | sst_hsw_mixer_get_volume(hsw, 0, 0, &volume); | ||
240 | ucontrol->value.integer.value[0] = hsw_ipc_to_mixer(volume); | ||
241 | |||
242 | sst_hsw_mixer_get_volume(hsw, 0, 1, &volume); | ||
243 | ucontrol->value.integer.value[1] = hsw_ipc_to_mixer(volume); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | /* TLV used by both global and stream volumes */ | ||
249 | static const DECLARE_TLV_DB_SCALE(hsw_vol_tlv, -9000, 300, 1); | ||
250 | |||
251 | /* System Pin has no volume control */ | ||
252 | static const struct snd_kcontrol_new hsw_volume_controls[] = { | ||
253 | /* Global DSP volume */ | ||
254 | SOC_DOUBLE_EXT_TLV("Master Playback Volume", 0, 0, 8, | ||
255 | ARRAY_SIZE(volume_map) -1, 0, | ||
256 | hsw_volume_get, hsw_volume_put, hsw_vol_tlv), | ||
257 | /* Offload 0 volume */ | ||
258 | SOC_DOUBLE_EXT_TLV("Media0 Playback Volume", 1, 0, 8, | ||
259 | ARRAY_SIZE(volume_map), 0, | ||
260 | hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), | ||
261 | /* Offload 1 volume */ | ||
262 | SOC_DOUBLE_EXT_TLV("Media1 Playback Volume", 2, 0, 8, | ||
263 | ARRAY_SIZE(volume_map), 0, | ||
264 | hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), | ||
265 | /* Loopback volume */ | ||
266 | SOC_DOUBLE_EXT_TLV("Loopback Capture Volume", 3, 0, 8, | ||
267 | ARRAY_SIZE(volume_map), 0, | ||
268 | hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), | ||
269 | /* Mic Capture volume */ | ||
270 | SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 4, 0, 8, | ||
271 | ARRAY_SIZE(volume_map), 0, | ||
272 | hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), | ||
273 | }; | ||
274 | |||
275 | /* Create DMA buffer page table for DSP */ | ||
276 | static int create_adsp_page_table(struct hsw_priv_data *pdata, | ||
277 | struct snd_soc_pcm_runtime *rtd, | ||
278 | unsigned char *dma_area, size_t size, int pcm, int stream) | ||
279 | { | ||
280 | int i, pages; | ||
281 | |||
282 | if (size % PAGE_SIZE) | ||
283 | pages = (size / PAGE_SIZE) + 1; | ||
284 | else | ||
285 | pages = size / PAGE_SIZE; | ||
286 | |||
287 | dev_dbg(rtd->dev, "generating page table for %p size 0x%zu pages %d\n", | ||
288 | dma_area, size, pages); | ||
289 | |||
290 | for (i = 0; i < pages; i++) { | ||
291 | u32 idx = (((i << 2) + i)) >> 1; | ||
292 | u32 pfn = (virt_to_phys(dma_area + i * PAGE_SIZE)) >> PAGE_SHIFT; | ||
293 | u32 *pg_table; | ||
294 | |||
295 | dev_dbg(rtd->dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn); | ||
296 | |||
297 | pg_table = (u32*)(pdata->pcm_pg[pcm][stream] + idx); | ||
298 | |||
299 | if (i & 1) | ||
300 | *pg_table |= (pfn << 4); | ||
301 | else | ||
302 | *pg_table |= pfn; | ||
303 | } | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | /* this may get called several times by oss emulation */ | ||
309 | static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, | ||
310 | struct snd_pcm_hw_params *params) | ||
311 | { | ||
312 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
313 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
314 | struct hsw_priv_data *pdata = | ||
315 | snd_soc_platform_get_drvdata(rtd->platform); | ||
316 | struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | ||
317 | struct sst_hsw *hsw = pdata->hsw; | ||
318 | struct sst_module *module_data; | ||
319 | struct sst_dsp *dsp; | ||
320 | enum sst_hsw_stream_type stream_type; | ||
321 | enum sst_hsw_stream_path_id path_id; | ||
322 | u32 rate, bits, map, pages, module_id; | ||
323 | u8 channels; | ||
324 | int ret; | ||
325 | |||
326 | /* stream direction */ | ||
327 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
328 | path_id = SST_HSW_STREAM_PATH_SSP0_OUT; | ||
329 | else | ||
330 | path_id = SST_HSW_STREAM_PATH_SSP0_IN; | ||
331 | |||
332 | /* DSP stream type depends on DAI ID */ | ||
333 | switch (rtd->cpu_dai->id) { | ||
334 | case 0: | ||
335 | stream_type = SST_HSW_STREAM_TYPE_SYSTEM; | ||
336 | module_id = SST_HSW_MODULE_PCM_SYSTEM; | ||
337 | break; | ||
338 | case 1: | ||
339 | case 2: | ||
340 | stream_type = SST_HSW_STREAM_TYPE_RENDER; | ||
341 | module_id = SST_HSW_MODULE_PCM; | ||
342 | break; | ||
343 | case 3: | ||
344 | /* path ID needs to be OUT for loopback */ | ||
345 | stream_type = SST_HSW_STREAM_TYPE_LOOPBACK; | ||
346 | path_id = SST_HSW_STREAM_PATH_SSP0_OUT; | ||
347 | module_id = SST_HSW_MODULE_PCM_REFERENCE; | ||
348 | break; | ||
349 | case 4: | ||
350 | stream_type = SST_HSW_STREAM_TYPE_CAPTURE; | ||
351 | module_id = SST_HSW_MODULE_PCM_CAPTURE; | ||
352 | break; | ||
353 | default: | ||
354 | dev_err(rtd->dev, "error: invalid DAI ID %d\n", | ||
355 | rtd->cpu_dai->id); | ||
356 | return -EINVAL; | ||
357 | }; | ||
358 | |||
359 | ret = sst_hsw_stream_format(hsw, pcm_data->stream, | ||
360 | path_id, stream_type, SST_HSW_STREAM_FORMAT_PCM_FORMAT); | ||
361 | if (ret < 0) { | ||
362 | dev_err(rtd->dev, "error: failed to set format %d\n", ret); | ||
363 | return ret; | ||
364 | } | ||
365 | |||
366 | rate = params_rate(params); | ||
367 | ret = sst_hsw_stream_set_rate(hsw, pcm_data->stream, rate); | ||
368 | if (ret < 0) { | ||
369 | dev_err(rtd->dev, "error: could not set rate %d\n", rate); | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | switch (params_format(params)) { | ||
374 | case SNDRV_PCM_FORMAT_S16_LE: | ||
375 | bits = SST_HSW_DEPTH_16BIT; | ||
376 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 16); | ||
377 | break; | ||
378 | case SNDRV_PCM_FORMAT_S24_LE: | ||
379 | bits = SST_HSW_DEPTH_24BIT; | ||
380 | sst_hsw_stream_set_valid(hsw, pcm_data->stream, 32); | ||
381 | break; | ||
382 | default: | ||
383 | dev_err(rtd->dev, "error: invalid format %d\n", | ||
384 | params_format(params)); | ||
385 | return -EINVAL; | ||
386 | } | ||
387 | |||
388 | ret = sst_hsw_stream_set_bits(hsw, pcm_data->stream, bits); | ||
389 | if (ret < 0) { | ||
390 | dev_err(rtd->dev, "error: could not set bits %d\n", bits); | ||
391 | return ret; | ||
392 | } | ||
393 | |||
394 | /* we only support stereo atm */ | ||
395 | channels = params_channels(params); | ||
396 | if (channels != 2) { | ||
397 | dev_err(rtd->dev, "error: invalid channels %d\n", channels); | ||
398 | return -EINVAL; | ||
399 | } | ||
400 | |||
401 | map = create_channel_map(SST_HSW_CHANNEL_CONFIG_STEREO); | ||
402 | sst_hsw_stream_set_map_config(hsw, pcm_data->stream, | ||
403 | map, SST_HSW_CHANNEL_CONFIG_STEREO); | ||
404 | |||
405 | ret = sst_hsw_stream_set_channels(hsw, pcm_data->stream, channels); | ||
406 | if (ret < 0) { | ||
407 | dev_err(rtd->dev, "error: could not set channels %d\n", | ||
408 | channels); | ||
409 | return ret; | ||
410 | } | ||
411 | |||
412 | ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
413 | if (ret < 0) { | ||
414 | dev_err(rtd->dev, "error: could not allocate %d bytes for PCM %d\n", | ||
415 | params_buffer_bytes(params), ret); | ||
416 | return ret; | ||
417 | } | ||
418 | |||
419 | ret = create_adsp_page_table(pdata, rtd, runtime->dma_area, | ||
420 | runtime->dma_bytes, rtd->cpu_dai->id, substream->stream); | ||
421 | if (ret < 0) | ||
422 | return ret; | ||
423 | |||
424 | sst_hsw_stream_set_style(hsw, pcm_data->stream, | ||
425 | SST_HSW_INTERLEAVING_PER_CHANNEL); | ||
426 | |||
427 | if (runtime->dma_bytes % PAGE_SIZE) | ||
428 | pages = (runtime->dma_bytes / PAGE_SIZE) + 1; | ||
429 | else | ||
430 | pages = runtime->dma_bytes / PAGE_SIZE; | ||
431 | |||
432 | ret = sst_hsw_stream_buffer(hsw, pcm_data->stream, | ||
433 | virt_to_phys(pdata->pcm_pg[rtd->cpu_dai->id][substream->stream]), | ||
434 | pages, runtime->dma_bytes, 0, | ||
435 | (u32)(virt_to_phys(runtime->dma_area) >> PAGE_SHIFT)); | ||
436 | if (ret < 0) { | ||
437 | dev_err(rtd->dev, "error: failed to set DMA buffer %d\n", ret); | ||
438 | return ret; | ||
439 | } | ||
440 | |||
441 | dsp = sst_hsw_get_dsp(hsw); | ||
442 | |||
443 | module_data = sst_module_get_from_id(dsp, module_id); | ||
444 | if (module_data == NULL) { | ||
445 | dev_err(rtd->dev, "error: failed to get module config\n"); | ||
446 | return -EINVAL; | ||
447 | } | ||
448 | |||
449 | /* we use hardcoded memory offsets atm, will be updated for new FW */ | ||
450 | if (stream_type == SST_HSW_STREAM_TYPE_CAPTURE) { | ||
451 | sst_hsw_stream_set_module_info(hsw, pcm_data->stream, | ||
452 | SST_HSW_MODULE_PCM_CAPTURE, module_data->entry); | ||
453 | sst_hsw_stream_set_pmemory_info(hsw, pcm_data->stream, | ||
454 | 0x449400, 0x4000); | ||
455 | sst_hsw_stream_set_smemory_info(hsw, pcm_data->stream, | ||
456 | 0x400000, 0); | ||
457 | } else { /* stream_type == SST_HSW_STREAM_TYPE_SYSTEM */ | ||
458 | sst_hsw_stream_set_module_info(hsw, pcm_data->stream, | ||
459 | SST_HSW_MODULE_PCM_SYSTEM, module_data->entry); | ||
460 | |||
461 | sst_hsw_stream_set_pmemory_info(hsw, pcm_data->stream, | ||
462 | module_data->offset, module_data->size); | ||
463 | sst_hsw_stream_set_pmemory_info(hsw, pcm_data->stream, | ||
464 | 0x44d400, 0x3800); | ||
465 | |||
466 | sst_hsw_stream_set_smemory_info(hsw, pcm_data->stream, | ||
467 | module_data->offset, module_data->size); | ||
468 | sst_hsw_stream_set_smemory_info(hsw, pcm_data->stream, | ||
469 | 0x400000, 0); | ||
470 | } | ||
471 | |||
472 | ret = sst_hsw_stream_commit(hsw, pcm_data->stream); | ||
473 | if (ret < 0) { | ||
474 | dev_err(rtd->dev, "error: failed to commit stream %d\n", ret); | ||
475 | return ret; | ||
476 | } | ||
477 | |||
478 | ret = sst_hsw_stream_pause(hsw, pcm_data->stream, 1); | ||
479 | if (ret < 0) | ||
480 | dev_err(rtd->dev, "error: failed to pause %d\n", ret); | ||
481 | |||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | static int hsw_pcm_hw_free(struct snd_pcm_substream *substream) | ||
486 | { | ||
487 | snd_pcm_lib_free_pages(substream); | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | static int hsw_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
492 | { | ||
493 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
494 | struct hsw_priv_data *pdata = | ||
495 | snd_soc_platform_get_drvdata(rtd->platform); | ||
496 | struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | ||
497 | struct sst_hsw *hsw = pdata->hsw; | ||
498 | |||
499 | switch (cmd) { | ||
500 | case SNDRV_PCM_TRIGGER_START: | ||
501 | case SNDRV_PCM_TRIGGER_RESUME: | ||
502 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
503 | sst_hsw_stream_resume(hsw, pcm_data->stream, 0); | ||
504 | break; | ||
505 | case SNDRV_PCM_TRIGGER_STOP: | ||
506 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
507 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
508 | sst_hsw_stream_pause(hsw, pcm_data->stream, 0); | ||
509 | break; | ||
510 | default: | ||
511 | break; | ||
512 | } | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data) | ||
518 | { | ||
519 | struct hsw_pcm_data *pcm_data = data; | ||
520 | struct snd_pcm_substream *substream = pcm_data->substream; | ||
521 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
522 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
523 | u32 pos; | ||
524 | |||
525 | pos = frames_to_bytes(runtime, | ||
526 | (runtime->control->appl_ptr % runtime->buffer_size)); | ||
527 | |||
528 | dev_dbg(rtd->dev, "PCM: App pointer %d bytes\n", pos); | ||
529 | |||
530 | /* let alsa know we have play a period */ | ||
531 | snd_pcm_period_elapsed(substream); | ||
532 | return pos; | ||
533 | } | ||
534 | |||
535 | static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_pcm_substream *substream) | ||
536 | { | ||
537 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
538 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
539 | struct hsw_priv_data *pdata = | ||
540 | snd_soc_platform_get_drvdata(rtd->platform); | ||
541 | struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | ||
542 | struct sst_hsw *hsw = pdata->hsw; | ||
543 | snd_pcm_uframes_t offset; | ||
544 | |||
545 | offset = bytes_to_frames(runtime, | ||
546 | sst_hsw_get_dsp_position(hsw, pcm_data->stream)); | ||
547 | |||
548 | dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n", | ||
549 | frames_to_bytes(runtime, (u32)offset)); | ||
550 | return offset; | ||
551 | } | ||
552 | |||
553 | static int hsw_pcm_open(struct snd_pcm_substream *substream) | ||
554 | { | ||
555 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
556 | struct hsw_priv_data *pdata = | ||
557 | snd_soc_platform_get_drvdata(rtd->platform); | ||
558 | struct hsw_pcm_data *pcm_data; | ||
559 | struct sst_hsw *hsw = pdata->hsw; | ||
560 | |||
561 | pcm_data = &pdata->pcm[rtd->cpu_dai->id]; | ||
562 | |||
563 | mutex_lock(&pcm_data->mutex); | ||
564 | |||
565 | snd_soc_pcm_set_drvdata(rtd, pcm_data); | ||
566 | pcm_data->substream = substream; | ||
567 | |||
568 | snd_soc_set_runtime_hwparams(substream, &hsw_pcm_hardware); | ||
569 | |||
570 | pcm_data->stream = sst_hsw_stream_new(hsw, rtd->cpu_dai->id, | ||
571 | hsw_notify_pointer, pcm_data); | ||
572 | if (pcm_data->stream == NULL) { | ||
573 | dev_err(rtd->dev, "error: failed to create stream\n"); | ||
574 | mutex_unlock(&pcm_data->mutex); | ||
575 | return -EINVAL; | ||
576 | } | ||
577 | |||
578 | /* Set previous saved volume */ | ||
579 | sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, | ||
580 | 0, pcm_data->volume[0]); | ||
581 | sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, | ||
582 | 1, pcm_data->volume[1]); | ||
583 | |||
584 | mutex_unlock(&pcm_data->mutex); | ||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | static int hsw_pcm_close(struct snd_pcm_substream *substream) | ||
589 | { | ||
590 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
591 | struct hsw_priv_data *pdata = | ||
592 | snd_soc_platform_get_drvdata(rtd->platform); | ||
593 | struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | ||
594 | struct sst_hsw *hsw = pdata->hsw; | ||
595 | int ret; | ||
596 | |||
597 | mutex_lock(&pcm_data->mutex); | ||
598 | ret = sst_hsw_stream_reset(hsw, pcm_data->stream); | ||
599 | if (ret < 0) { | ||
600 | dev_dbg(rtd->dev, "error: reset stream failed %d\n", ret); | ||
601 | goto out; | ||
602 | } | ||
603 | |||
604 | ret = sst_hsw_stream_free(hsw, pcm_data->stream); | ||
605 | if (ret < 0) { | ||
606 | dev_dbg(rtd->dev, "error: free stream failed %d\n", ret); | ||
607 | goto out; | ||
608 | } | ||
609 | pcm_data->stream = NULL; | ||
610 | |||
611 | out: | ||
612 | mutex_unlock(&pcm_data->mutex); | ||
613 | return ret; | ||
614 | } | ||
615 | |||
616 | static struct snd_pcm_ops hsw_pcm_ops = { | ||
617 | .open = hsw_pcm_open, | ||
618 | .close = hsw_pcm_close, | ||
619 | .ioctl = snd_pcm_lib_ioctl, | ||
620 | .hw_params = hsw_pcm_hw_params, | ||
621 | .hw_free = hsw_pcm_hw_free, | ||
622 | .trigger = hsw_pcm_trigger, | ||
623 | .pointer = hsw_pcm_pointer, | ||
624 | .mmap = snd_pcm_lib_default_mmap, | ||
625 | }; | ||
626 | |||
627 | static void hsw_pcm_free(struct snd_pcm *pcm) | ||
628 | { | ||
629 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
630 | } | ||
631 | |||
632 | static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
633 | { | ||
634 | struct snd_pcm *pcm = rtd->pcm; | ||
635 | int ret = 0; | ||
636 | |||
637 | ret = dma_coerce_mask_and_coherent(rtd->card->dev, DMA_BIT_MASK(32)); | ||
638 | if (ret) | ||
639 | return ret; | ||
640 | |||
641 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || | ||
642 | pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
643 | ret = snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
644 | SNDRV_DMA_TYPE_DEV, | ||
645 | rtd->card->dev, | ||
646 | hsw_pcm_hardware.buffer_bytes_max, | ||
647 | hsw_pcm_hardware.buffer_bytes_max); | ||
648 | if (ret) { | ||
649 | dev_err(rtd->dev, "dma buffer allocation failed %d\n", | ||
650 | ret); | ||
651 | return ret; | ||
652 | } | ||
653 | } | ||
654 | |||
655 | return ret; | ||
656 | } | ||
657 | |||
658 | #define HSW_FORMATS \ | ||
659 | (SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
660 | SNDRV_PCM_FMTBIT_S32_LE) | ||
661 | |||
662 | static struct snd_soc_dai_driver hsw_dais[] = { | ||
663 | { | ||
664 | .name = "System Pin", | ||
665 | .playback = { | ||
666 | .stream_name = "System Playback", | ||
667 | .channels_min = 2, | ||
668 | .channels_max = 2, | ||
669 | .rates = SNDRV_PCM_RATE_48000, | ||
670 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
671 | }, | ||
672 | }, | ||
673 | { | ||
674 | /* PCM */ | ||
675 | .name = "Offload0 Pin", | ||
676 | .playback = { | ||
677 | .stream_name = "Offload0 Playback", | ||
678 | .channels_min = 2, | ||
679 | .channels_max = 2, | ||
680 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
681 | .formats = HSW_FORMATS, | ||
682 | }, | ||
683 | }, | ||
684 | { | ||
685 | /* PCM */ | ||
686 | .name = "Offload1 Pin", | ||
687 | .playback = { | ||
688 | .stream_name = "Offload1 Playback", | ||
689 | .channels_min = 2, | ||
690 | .channels_max = 2, | ||
691 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
692 | .formats = HSW_FORMATS, | ||
693 | }, | ||
694 | }, | ||
695 | { | ||
696 | .name = "Loopback Pin", | ||
697 | .capture = { | ||
698 | .stream_name = "Loopback Capture", | ||
699 | .channels_min = 2, | ||
700 | .channels_max = 2, | ||
701 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
702 | .formats = HSW_FORMATS, | ||
703 | }, | ||
704 | }, | ||
705 | { | ||
706 | .name = "Capture Pin", | ||
707 | .capture = { | ||
708 | .stream_name = "Analog Capture", | ||
709 | .channels_min = 2, | ||
710 | .channels_max = 2, | ||
711 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
712 | .formats = HSW_FORMATS, | ||
713 | }, | ||
714 | }, | ||
715 | }; | ||
716 | |||
717 | static const struct snd_soc_dapm_widget widgets[] = { | ||
718 | |||
719 | /* Backend DAIs */ | ||
720 | SND_SOC_DAPM_AIF_IN("SSP0 CODEC IN", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
721 | SND_SOC_DAPM_AIF_OUT("SSP0 CODEC OUT", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
722 | SND_SOC_DAPM_AIF_IN("SSP1 BT IN", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
723 | SND_SOC_DAPM_AIF_OUT("SSP1 BT OUT", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
724 | |||
725 | /* Global Playback Mixer */ | ||
726 | SND_SOC_DAPM_MIXER("Playback VMixer", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
727 | }; | ||
728 | |||
729 | static const struct snd_soc_dapm_route graph[] = { | ||
730 | |||
731 | /* Playback Mixer */ | ||
732 | {"Playback VMixer", NULL, "System Playback"}, | ||
733 | {"Playback VMixer", NULL, "Offload0 Playback"}, | ||
734 | {"Playback VMixer", NULL, "Offload1 Playback"}, | ||
735 | |||
736 | {"SSP0 CODEC OUT", NULL, "Playback VMixer"}, | ||
737 | |||
738 | {"Analog Capture", NULL, "SSP0 CODEC IN"}, | ||
739 | }; | ||
740 | |||
741 | static int hsw_pcm_probe(struct snd_soc_platform *platform) | ||
742 | { | ||
743 | struct sst_pdata *pdata = dev_get_platdata(platform->dev); | ||
744 | struct hsw_priv_data *priv_data; | ||
745 | int i; | ||
746 | |||
747 | if (!pdata) | ||
748 | return -ENODEV; | ||
749 | |||
750 | priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data), GFP_KERNEL); | ||
751 | priv_data->hsw = pdata->dsp; | ||
752 | snd_soc_platform_set_drvdata(platform, priv_data); | ||
753 | |||
754 | /* allocate DSP buffer page tables */ | ||
755 | for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { | ||
756 | |||
757 | mutex_init(&priv_data->pcm[i].mutex); | ||
758 | |||
759 | /* playback */ | ||
760 | if (hsw_dais[i].playback.channels_min) { | ||
761 | priv_data->pcm_pg[i][0] = kzalloc(PAGE_SIZE, GFP_DMA); | ||
762 | if (priv_data->pcm_pg[i][0] == NULL) | ||
763 | goto err; | ||
764 | } | ||
765 | |||
766 | /* capture */ | ||
767 | if (hsw_dais[i].capture.channels_min) { | ||
768 | priv_data->pcm_pg[i][1] = kzalloc(PAGE_SIZE, GFP_DMA); | ||
769 | if (priv_data->pcm_pg[i][1] == NULL) | ||
770 | goto err; | ||
771 | } | ||
772 | } | ||
773 | |||
774 | return 0; | ||
775 | |||
776 | err: | ||
777 | for (;i >= 0; i--) { | ||
778 | if (hsw_dais[i].playback.channels_min) | ||
779 | kfree(priv_data->pcm_pg[i][0]); | ||
780 | if (hsw_dais[i].capture.channels_min) | ||
781 | kfree(priv_data->pcm_pg[i][1]); | ||
782 | } | ||
783 | return -ENOMEM; | ||
784 | } | ||
785 | |||
786 | static int hsw_pcm_remove(struct snd_soc_platform *platform) | ||
787 | { | ||
788 | struct hsw_priv_data *priv_data = | ||
789 | snd_soc_platform_get_drvdata(platform); | ||
790 | int i; | ||
791 | |||
792 | for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { | ||
793 | if (hsw_dais[i].playback.channels_min) | ||
794 | kfree(priv_data->pcm_pg[i][0]); | ||
795 | if (hsw_dais[i].capture.channels_min) | ||
796 | kfree(priv_data->pcm_pg[i][1]); | ||
797 | } | ||
798 | |||
799 | return 0; | ||
800 | } | ||
801 | |||
802 | static struct snd_soc_platform_driver hsw_soc_platform = { | ||
803 | .probe = hsw_pcm_probe, | ||
804 | .remove = hsw_pcm_remove, | ||
805 | .ops = &hsw_pcm_ops, | ||
806 | .pcm_new = hsw_pcm_new, | ||
807 | .pcm_free = hsw_pcm_free, | ||
808 | .controls = hsw_volume_controls, | ||
809 | .num_controls = ARRAY_SIZE(hsw_volume_controls), | ||
810 | .dapm_widgets = widgets, | ||
811 | .num_dapm_widgets = ARRAY_SIZE(widgets), | ||
812 | .dapm_routes = graph, | ||
813 | .num_dapm_routes = ARRAY_SIZE(graph), | ||
814 | }; | ||
815 | |||
816 | static const struct snd_soc_component_driver hsw_dai_component = { | ||
817 | .name = "haswell-dai", | ||
818 | }; | ||
819 | |||
820 | static int hsw_pcm_dev_probe(struct platform_device *pdev) | ||
821 | { | ||
822 | struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); | ||
823 | int ret; | ||
824 | |||
825 | ret = sst_hsw_dsp_init(&pdev->dev, sst_pdata); | ||
826 | if (ret < 0) | ||
827 | return -ENODEV; | ||
828 | |||
829 | ret = snd_soc_register_platform(&pdev->dev, &hsw_soc_platform); | ||
830 | if (ret < 0) | ||
831 | goto err_plat; | ||
832 | |||
833 | ret = snd_soc_register_component(&pdev->dev, &hsw_dai_component, | ||
834 | hsw_dais, ARRAY_SIZE(hsw_dais)); | ||
835 | if (ret < 0) | ||
836 | goto err_comp; | ||
837 | |||
838 | return 0; | ||
839 | |||
840 | err_comp: | ||
841 | snd_soc_unregister_platform(&pdev->dev); | ||
842 | err_plat: | ||
843 | sst_hsw_dsp_free(&pdev->dev, sst_pdata); | ||
844 | return 0; | ||
845 | } | ||
846 | |||
847 | static int hsw_pcm_dev_remove(struct platform_device *pdev) | ||
848 | { | ||
849 | struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); | ||
850 | |||
851 | snd_soc_unregister_platform(&pdev->dev); | ||
852 | snd_soc_unregister_component(&pdev->dev); | ||
853 | sst_hsw_dsp_free(&pdev->dev, sst_pdata); | ||
854 | |||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | static struct platform_driver hsw_pcm_driver = { | ||
859 | .driver = { | ||
860 | .name = "haswell-pcm-audio", | ||
861 | .owner = THIS_MODULE, | ||
862 | }, | ||
863 | |||
864 | .probe = hsw_pcm_dev_probe, | ||
865 | .remove = hsw_pcm_dev_remove, | ||
866 | }; | ||
867 | module_platform_driver(hsw_pcm_driver); | ||
868 | |||
869 | MODULE_AUTHOR("Liam Girdwood, Xingchao Wang"); | ||
870 | MODULE_DESCRIPTION("Haswell/Lynxpoint + Broadwell/Wildcatpoint PCM"); | ||
871 | MODULE_LICENSE("GPL v2"); | ||
872 | MODULE_ALIAS("platform:haswell-pcm-audio"); | ||
diff --git a/sound/soc/intel/sst_dsp.h b/sound/soc/intel/sst-mfld-dsp.h index 0fce1de284ff..3b63edc04b7f 100644 --- a/sound/soc/intel/sst_dsp.h +++ b/sound/soc/intel/sst-mfld-dsp.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef __SST_DSP_H__ | 1 | #ifndef __SST_MFLD_DSP_H__ |
2 | #define __SST_DSP_H__ | 2 | #define __SST_MFLD_DSP_H__ |
3 | /* | 3 | /* |
4 | * sst_dsp.h - Intel SST Driver for audio engine | 4 | * sst_mfld_dsp.h - Intel SST Driver for audio engine |
5 | * | 5 | * |
6 | * Copyright (C) 2008-12 Intel Corporation | 6 | * Copyright (C) 2008-12 Intel Corporation |
7 | * Authors: Vinod Koul <vinod.koul@linux.intel.com> | 7 | * Authors: Vinod Koul <vinod.koul@linux.intel.com> |
@@ -131,4 +131,4 @@ struct snd_sst_params { | |||
131 | struct snd_sst_alloc_params_ext aparams; | 131 | struct snd_sst_alloc_params_ext aparams; |
132 | }; | 132 | }; |
133 | 133 | ||
134 | #endif /* __SST_DSP_H__ */ | 134 | #endif /* __SST_MFLD_DSP_H__ */ |
diff --git a/sound/soc/intel/sst_platform.c b/sound/soc/intel/sst-mfld-platform.c index f465a8180863..840306c2ef14 100644 --- a/sound/soc/intel/sst_platform.c +++ b/sound/soc/intel/sst-mfld-platform.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * sst_platform.c - Intel MID Platform driver | 2 | * sst_mfld_platform.c - Intel MID Platform driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010-2013 Intel Corp | 4 | * Copyright (C) 2010-2013 Intel Corp |
5 | * Author: Vinod Koul <vinod.koul@intel.com> | 5 | * Author: Vinod Koul <vinod.koul@intel.com> |
@@ -33,7 +33,7 @@ | |||
33 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
34 | #include <sound/soc.h> | 34 | #include <sound/soc.h> |
35 | #include <sound/compress_driver.h> | 35 | #include <sound/compress_driver.h> |
36 | #include "sst_platform.h" | 36 | #include "sst-mfld-platform.h" |
37 | 37 | ||
38 | static struct sst_device *sst; | 38 | static struct sst_device *sst; |
39 | static DEFINE_MUTEX(sst_lock); | 39 | static DEFINE_MUTEX(sst_lock); |
@@ -709,7 +709,7 @@ static int sst_platform_remove(struct platform_device *pdev) | |||
709 | 709 | ||
710 | static struct platform_driver sst_platform_driver = { | 710 | static struct platform_driver sst_platform_driver = { |
711 | .driver = { | 711 | .driver = { |
712 | .name = "sst-platform", | 712 | .name = "sst-mfld-platform", |
713 | .owner = THIS_MODULE, | 713 | .owner = THIS_MODULE, |
714 | }, | 714 | }, |
715 | .probe = sst_platform_probe, | 715 | .probe = sst_platform_probe, |
@@ -722,4 +722,4 @@ MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver"); | |||
722 | MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); | 722 | MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); |
723 | MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); | 723 | MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); |
724 | MODULE_LICENSE("GPL v2"); | 724 | MODULE_LICENSE("GPL v2"); |
725 | MODULE_ALIAS("platform:sst-platform"); | 725 | MODULE_ALIAS("platform:sst-mfld-platform"); |
diff --git a/sound/soc/intel/sst_platform.h b/sound/soc/intel/sst-mfld-platform.h index bee64fb7d2ef..0c4e2ddcecb1 100644 --- a/sound/soc/intel/sst_platform.h +++ b/sound/soc/intel/sst-mfld-platform.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * sst_platform.h - Intel MID Platform driver header file | 2 | * sst_mfld_platform.h - Intel MID Platform driver header file |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Intel Corp | 4 | * Copyright (C) 2010 Intel Corp |
5 | * Author: Vinod Koul <vinod.koul@intel.com> | 5 | * Author: Vinod Koul <vinod.koul@intel.com> |
@@ -27,7 +27,7 @@ | |||
27 | #ifndef __SST_PLATFORMDRV_H__ | 27 | #ifndef __SST_PLATFORMDRV_H__ |
28 | #define __SST_PLATFORMDRV_H__ | 28 | #define __SST_PLATFORMDRV_H__ |
29 | 29 | ||
30 | #include "sst_dsp.h" | 30 | #include "sst-mfld-dsp.h" |
31 | 31 | ||
32 | #define SST_MONO 1 | 32 | #define SST_MONO 1 |
33 | #define SST_STEREO 2 | 33 | #define SST_STEREO 2 |
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig index 78ed4a42ad21..49f8437665de 100644 --- a/sound/soc/kirkwood/Kconfig +++ b/sound/soc/kirkwood/Kconfig | |||
@@ -1,11 +1,20 @@ | |||
1 | config SND_KIRKWOOD_SOC | 1 | config SND_KIRKWOOD_SOC |
2 | tristate "SoC Audio for the Marvell Kirkwood and Dove chips" | 2 | tristate "SoC Audio for the Marvell Kirkwood and Dove chips" |
3 | depends on ARCH_KIRKWOOD || ARCH_DOVE || COMPILE_TEST | 3 | depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST |
4 | help | 4 | help |
5 | Say Y or M if you want to add support for codecs attached to | 5 | Say Y or M if you want to add support for codecs attached to |
6 | the Kirkwood I2S interface. You will also need to select the | 6 | the Kirkwood I2S interface. You will also need to select the |
7 | audio interfaces to support below. | 7 | audio interfaces to support below. |
8 | 8 | ||
9 | config SND_KIRKWOOD_SOC_ARMADA370_DB | ||
10 | tristate "SoC Audio support for Armada 370 DB" | ||
11 | depends on SND_KIRKWOOD_SOC && (ARCH_MVEBU || COMPILE_TEST) && I2C | ||
12 | select SND_SOC_CS42L51 | ||
13 | select SND_SOC_SPDIF | ||
14 | help | ||
15 | Say Y if you want to add support for SoC audio on | ||
16 | the Armada 370 Development Board. | ||
17 | |||
9 | config SND_KIRKWOOD_SOC_OPENRD | 18 | config SND_KIRKWOOD_SOC_OPENRD |
10 | tristate "SoC Audio support for Kirkwood Openrd Client" | 19 | tristate "SoC Audio support for Kirkwood Openrd Client" |
11 | depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST) | 20 | depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST) |
diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile index 9e781385cb88..7c1d8fe09e6b 100644 --- a/sound/soc/kirkwood/Makefile +++ b/sound/soc/kirkwood/Makefile | |||
@@ -4,6 +4,8 @@ obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o | |||
4 | 4 | ||
5 | snd-soc-openrd-objs := kirkwood-openrd.o | 5 | snd-soc-openrd-objs := kirkwood-openrd.o |
6 | snd-soc-t5325-objs := kirkwood-t5325.o | 6 | snd-soc-t5325-objs := kirkwood-t5325.o |
7 | snd-soc-armada-370-db-objs := armada-370-db.o | ||
7 | 8 | ||
9 | obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o | ||
8 | obj-$(CONFIG_SND_KIRKWOOD_SOC_OPENRD) += snd-soc-openrd.o | 10 | obj-$(CONFIG_SND_KIRKWOOD_SOC_OPENRD) += snd-soc-openrd.o |
9 | obj-$(CONFIG_SND_KIRKWOOD_SOC_T5325) += snd-soc-t5325.o | 11 | obj-$(CONFIG_SND_KIRKWOOD_SOC_T5325) += snd-soc-t5325.o |
diff --git a/sound/soc/kirkwood/armada-370-db.c b/sound/soc/kirkwood/armada-370-db.c new file mode 100644 index 000000000000..c44333849259 --- /dev/null +++ b/sound/soc/kirkwood/armada-370-db.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Marvell | ||
3 | * | ||
4 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <sound/soc.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/platform_data/asoc-kirkwood.h> | ||
20 | #include "../codecs/cs42l51.h" | ||
21 | |||
22 | static int a370db_hw_params(struct snd_pcm_substream *substream, | ||
23 | struct snd_pcm_hw_params *params) | ||
24 | { | ||
25 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
26 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
27 | unsigned int freq; | ||
28 | |||
29 | switch (params_rate(params)) { | ||
30 | default: | ||
31 | case 44100: | ||
32 | freq = 11289600; | ||
33 | break; | ||
34 | case 48000: | ||
35 | freq = 12288000; | ||
36 | break; | ||
37 | case 96000: | ||
38 | freq = 24576000; | ||
39 | break; | ||
40 | } | ||
41 | |||
42 | return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN); | ||
43 | } | ||
44 | |||
45 | static struct snd_soc_ops a370db_ops = { | ||
46 | .hw_params = a370db_hw_params, | ||
47 | }; | ||
48 | |||
49 | static const struct snd_soc_dapm_widget a370db_dapm_widgets[] = { | ||
50 | SND_SOC_DAPM_HP("Out Jack", NULL), | ||
51 | SND_SOC_DAPM_LINE("In Jack", NULL), | ||
52 | }; | ||
53 | |||
54 | static const struct snd_soc_dapm_route a370db_route[] = { | ||
55 | { "Out Jack", NULL, "HPL" }, | ||
56 | { "Out Jack", NULL, "HPR" }, | ||
57 | { "AIN1L", NULL, "In Jack" }, | ||
58 | { "AIN1L", NULL, "In Jack" }, | ||
59 | }; | ||
60 | |||
61 | static struct snd_soc_dai_link a370db_dai[] = { | ||
62 | { | ||
63 | .name = "CS42L51", | ||
64 | .stream_name = "analog", | ||
65 | .cpu_dai_name = "i2s", | ||
66 | .codec_dai_name = "cs42l51-hifi", | ||
67 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, | ||
68 | .ops = &a370db_ops, | ||
69 | }, | ||
70 | { | ||
71 | .name = "S/PDIF out", | ||
72 | .stream_name = "spdif-out", | ||
73 | .cpu_dai_name = "spdif", | ||
74 | .codec_dai_name = "dit-hifi", | ||
75 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, | ||
76 | }, | ||
77 | { | ||
78 | .name = "S/PDIF in", | ||
79 | .stream_name = "spdif-in", | ||
80 | .cpu_dai_name = "spdif", | ||
81 | .codec_dai_name = "dir-hifi", | ||
82 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, | ||
83 | }, | ||
84 | }; | ||
85 | |||
86 | static struct snd_soc_card a370db = { | ||
87 | .name = "a370db", | ||
88 | .owner = THIS_MODULE, | ||
89 | .dai_link = a370db_dai, | ||
90 | .num_links = ARRAY_SIZE(a370db_dai), | ||
91 | .dapm_widgets = a370db_dapm_widgets, | ||
92 | .num_dapm_widgets = ARRAY_SIZE(a370db_dapm_widgets), | ||
93 | .dapm_routes = a370db_route, | ||
94 | .num_dapm_routes = ARRAY_SIZE(a370db_route), | ||
95 | }; | ||
96 | |||
97 | static int a370db_probe(struct platform_device *pdev) | ||
98 | { | ||
99 | struct snd_soc_card *card = &a370db; | ||
100 | |||
101 | card->dev = &pdev->dev; | ||
102 | |||
103 | a370db_dai[0].cpu_of_node = | ||
104 | of_parse_phandle(pdev->dev.of_node, | ||
105 | "marvell,audio-controller", 0); | ||
106 | a370db_dai[0].platform_of_node = a370db_dai[0].cpu_of_node; | ||
107 | |||
108 | a370db_dai[0].codec_of_node = | ||
109 | of_parse_phandle(pdev->dev.of_node, | ||
110 | "marvell,audio-codec", 0); | ||
111 | |||
112 | a370db_dai[1].cpu_of_node = a370db_dai[0].cpu_of_node; | ||
113 | a370db_dai[1].platform_of_node = a370db_dai[0].cpu_of_node; | ||
114 | |||
115 | a370db_dai[1].codec_of_node = | ||
116 | of_parse_phandle(pdev->dev.of_node, | ||
117 | "marvell,audio-codec", 1); | ||
118 | |||
119 | a370db_dai[2].cpu_of_node = a370db_dai[0].cpu_of_node; | ||
120 | a370db_dai[2].platform_of_node = a370db_dai[0].cpu_of_node; | ||
121 | |||
122 | a370db_dai[2].codec_of_node = | ||
123 | of_parse_phandle(pdev->dev.of_node, | ||
124 | "marvell,audio-codec", 2); | ||
125 | |||
126 | return devm_snd_soc_register_card(card->dev, card); | ||
127 | } | ||
128 | |||
129 | static const struct of_device_id a370db_dt_ids[] = { | ||
130 | { .compatible = "marvell,a370db-audio" }, | ||
131 | { }, | ||
132 | }; | ||
133 | |||
134 | static struct platform_driver a370db_driver = { | ||
135 | .driver = { | ||
136 | .name = "a370db-audio", | ||
137 | .owner = THIS_MODULE, | ||
138 | .of_match_table = of_match_ptr(a370db_dt_ids), | ||
139 | }, | ||
140 | .probe = a370db_probe, | ||
141 | }; | ||
142 | |||
143 | module_platform_driver(a370db_driver); | ||
144 | |||
145 | MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); | ||
146 | MODULE_DESCRIPTION("ALSA SoC a370db audio client"); | ||
147 | MODULE_LICENSE("GPL"); | ||
148 | MODULE_ALIAS("platform:a370db-audio"); | ||
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 3920a5e8125f..9f842222e798 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c | |||
@@ -633,6 +633,7 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev) | |||
633 | static struct of_device_id mvebu_audio_of_match[] = { | 633 | static struct of_device_id mvebu_audio_of_match[] = { |
634 | { .compatible = "marvell,kirkwood-audio" }, | 634 | { .compatible = "marvell,kirkwood-audio" }, |
635 | { .compatible = "marvell,dove-audio" }, | 635 | { .compatible = "marvell,dove-audio" }, |
636 | { .compatible = "marvell,armada370-audio" }, | ||
636 | { } | 637 | { } |
637 | }; | 638 | }; |
638 | MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); | 639 | MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); |
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 22ad9c5654b5..e00659351a4e 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
@@ -58,7 +58,7 @@ config SND_OMAP_SOC_OSK5912 | |||
58 | tristate "SoC Audio support for omap osk5912" | 58 | tristate "SoC Audio support for omap osk5912" |
59 | depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C | 59 | depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C |
60 | select SND_OMAP_SOC_MCBSP | 60 | select SND_OMAP_SOC_MCBSP |
61 | select SND_SOC_TLV320AIC23 | 61 | select SND_SOC_TLV320AIC23_I2C |
62 | help | 62 | help |
63 | Say Y if you want to add support for SoC audio on osk5912. | 63 | Say Y if you want to add support for SoC audio on osk5912. |
64 | 64 | ||
@@ -66,7 +66,7 @@ config SND_OMAP_SOC_AM3517EVM | |||
66 | tristate "SoC Audio support for OMAP3517 / AM3517 EVM" | 66 | tristate "SoC Audio support for OMAP3517 / AM3517 EVM" |
67 | depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C | 67 | depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C |
68 | select SND_OMAP_SOC_MCBSP | 68 | select SND_OMAP_SOC_MCBSP |
69 | select SND_SOC_TLV320AIC23 | 69 | select SND_SOC_TLV320AIC23_I2C |
70 | help | 70 | help |
71 | Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517 | 71 | Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517 |
72 | EVM. | 72 | EVM. |
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 99b314d53790..56a5219c0a00 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c | |||
@@ -103,60 +103,62 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, | |||
103 | if (!codec->hw_write) | 103 | if (!codec->hw_write) |
104 | return -EUNATCH; | 104 | return -EUNATCH; |
105 | 105 | ||
106 | if (ucontrol->value.enumerated.item[0] >= control->max) | 106 | if (ucontrol->value.enumerated.item[0] >= control->items) |
107 | return -EINVAL; | 107 | return -EINVAL; |
108 | 108 | ||
109 | mutex_lock(&codec->mutex); | 109 | snd_soc_dapm_mutex_lock(dapm); |
110 | 110 | ||
111 | /* Translate selection to bitmap */ | 111 | /* Translate selection to bitmap */ |
112 | pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]]; | 112 | pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]]; |
113 | 113 | ||
114 | /* Setup pins after corresponding bits if changed */ | 114 | /* Setup pins after corresponding bits if changed */ |
115 | pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE)); | 115 | pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE)); |
116 | |||
116 | if (pin != snd_soc_dapm_get_pin_status(dapm, "Mouthpiece")) { | 117 | if (pin != snd_soc_dapm_get_pin_status(dapm, "Mouthpiece")) { |
117 | changed = 1; | 118 | changed = 1; |
118 | if (pin) | 119 | if (pin) |
119 | snd_soc_dapm_enable_pin(dapm, "Mouthpiece"); | 120 | snd_soc_dapm_enable_pin_unlocked(dapm, "Mouthpiece"); |
120 | else | 121 | else |
121 | snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); | 122 | snd_soc_dapm_disable_pin_unlocked(dapm, "Mouthpiece"); |
122 | } | 123 | } |
123 | pin = !!(pins & (1 << AMS_DELTA_EARPIECE)); | 124 | pin = !!(pins & (1 << AMS_DELTA_EARPIECE)); |
124 | if (pin != snd_soc_dapm_get_pin_status(dapm, "Earpiece")) { | 125 | if (pin != snd_soc_dapm_get_pin_status(dapm, "Earpiece")) { |
125 | changed = 1; | 126 | changed = 1; |
126 | if (pin) | 127 | if (pin) |
127 | snd_soc_dapm_enable_pin(dapm, "Earpiece"); | 128 | snd_soc_dapm_enable_pin_unlocked(dapm, "Earpiece"); |
128 | else | 129 | else |
129 | snd_soc_dapm_disable_pin(dapm, "Earpiece"); | 130 | snd_soc_dapm_disable_pin_unlocked(dapm, "Earpiece"); |
130 | } | 131 | } |
131 | pin = !!(pins & (1 << AMS_DELTA_MICROPHONE)); | 132 | pin = !!(pins & (1 << AMS_DELTA_MICROPHONE)); |
132 | if (pin != snd_soc_dapm_get_pin_status(dapm, "Microphone")) { | 133 | if (pin != snd_soc_dapm_get_pin_status(dapm, "Microphone")) { |
133 | changed = 1; | 134 | changed = 1; |
134 | if (pin) | 135 | if (pin) |
135 | snd_soc_dapm_enable_pin(dapm, "Microphone"); | 136 | snd_soc_dapm_enable_pin_unlocked(dapm, "Microphone"); |
136 | else | 137 | else |
137 | snd_soc_dapm_disable_pin(dapm, "Microphone"); | 138 | snd_soc_dapm_disable_pin_unlocked(dapm, "Microphone"); |
138 | } | 139 | } |
139 | pin = !!(pins & (1 << AMS_DELTA_SPEAKER)); | 140 | pin = !!(pins & (1 << AMS_DELTA_SPEAKER)); |
140 | if (pin != snd_soc_dapm_get_pin_status(dapm, "Speaker")) { | 141 | if (pin != snd_soc_dapm_get_pin_status(dapm, "Speaker")) { |
141 | changed = 1; | 142 | changed = 1; |
142 | if (pin) | 143 | if (pin) |
143 | snd_soc_dapm_enable_pin(dapm, "Speaker"); | 144 | snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); |
144 | else | 145 | else |
145 | snd_soc_dapm_disable_pin(dapm, "Speaker"); | 146 | snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); |
146 | } | 147 | } |
147 | pin = !!(pins & (1 << AMS_DELTA_AGC)); | 148 | pin = !!(pins & (1 << AMS_DELTA_AGC)); |
148 | if (pin != ams_delta_audio_agc) { | 149 | if (pin != ams_delta_audio_agc) { |
149 | ams_delta_audio_agc = pin; | 150 | ams_delta_audio_agc = pin; |
150 | changed = 1; | 151 | changed = 1; |
151 | if (pin) | 152 | if (pin) |
152 | snd_soc_dapm_enable_pin(dapm, "AGCIN"); | 153 | snd_soc_dapm_enable_pin_unlocked(dapm, "AGCIN"); |
153 | else | 154 | else |
154 | snd_soc_dapm_disable_pin(dapm, "AGCIN"); | 155 | snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN"); |
155 | } | 156 | } |
157 | |||
156 | if (changed) | 158 | if (changed) |
157 | snd_soc_dapm_sync(dapm); | 159 | snd_soc_dapm_sync_unlocked(dapm); |
158 | 160 | ||
159 | mutex_unlock(&codec->mutex); | 161 | snd_soc_dapm_mutex_unlock(dapm); |
160 | 162 | ||
161 | return changed; | 163 | return changed; |
162 | } | 164 | } |
@@ -313,12 +315,17 @@ static void cx81801_close(struct tty_struct *tty) | |||
313 | v253_ops.close(tty); | 315 | v253_ops.close(tty); |
314 | 316 | ||
315 | /* Revert back to default audio input/output constellation */ | 317 | /* Revert back to default audio input/output constellation */ |
316 | snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); | 318 | snd_soc_dapm_mutex_lock(dapm); |
317 | snd_soc_dapm_enable_pin(dapm, "Earpiece"); | 319 | |
318 | snd_soc_dapm_enable_pin(dapm, "Microphone"); | 320 | snd_soc_dapm_disable_pin_unlocked(dapm, "Mouthpiece"); |
319 | snd_soc_dapm_disable_pin(dapm, "Speaker"); | 321 | snd_soc_dapm_enable_pin_unlocked(dapm, "Earpiece"); |
320 | snd_soc_dapm_disable_pin(dapm, "AGCIN"); | 322 | snd_soc_dapm_enable_pin_unlocked(dapm, "Microphone"); |
321 | snd_soc_dapm_sync(dapm); | 323 | snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); |
324 | snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN"); | ||
325 | |||
326 | snd_soc_dapm_sync_unlocked(dapm); | ||
327 | |||
328 | snd_soc_dapm_mutex_unlock(dapm); | ||
322 | } | 329 | } |
323 | 330 | ||
324 | /* Line discipline .hangup() */ | 331 | /* Line discipline .hangup() */ |
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 3fde9e402710..fd4d9c809e50 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c | |||
@@ -68,26 +68,30 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm) | |||
68 | break; | 68 | break; |
69 | } | 69 | } |
70 | 70 | ||
71 | snd_soc_dapm_mutex_lock(dapm); | ||
72 | |||
71 | if (n810_spk_func) | 73 | if (n810_spk_func) |
72 | snd_soc_dapm_enable_pin(dapm, "Ext Spk"); | 74 | snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); |
73 | else | 75 | else |
74 | snd_soc_dapm_disable_pin(dapm, "Ext Spk"); | 76 | snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); |
75 | 77 | ||
76 | if (hp) | 78 | if (hp) |
77 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | 79 | snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); |
78 | else | 80 | else |
79 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | 81 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); |
80 | if (line1l) | 82 | if (line1l) |
81 | snd_soc_dapm_enable_pin(dapm, "LINE1L"); | 83 | snd_soc_dapm_enable_pin_unlocked(dapm, "LINE1L"); |
82 | else | 84 | else |
83 | snd_soc_dapm_disable_pin(dapm, "LINE1L"); | 85 | snd_soc_dapm_disable_pin_unlocked(dapm, "LINE1L"); |
84 | 86 | ||
85 | if (n810_dmic_func) | 87 | if (n810_dmic_func) |
86 | snd_soc_dapm_enable_pin(dapm, "DMic"); | 88 | snd_soc_dapm_enable_pin_unlocked(dapm, "DMic"); |
87 | else | 89 | else |
88 | snd_soc_dapm_disable_pin(dapm, "DMic"); | 90 | snd_soc_dapm_disable_pin_unlocked(dapm, "DMic"); |
91 | |||
92 | snd_soc_dapm_sync_unlocked(dapm); | ||
89 | 93 | ||
90 | snd_soc_dapm_sync(dapm); | 94 | snd_soc_dapm_mutex_unlock(dapm); |
91 | } | 95 | } |
92 | 96 | ||
93 | static int n810_startup(struct snd_pcm_substream *substream) | 97 | static int n810_startup(struct snd_pcm_substream *substream) |
@@ -305,7 +309,9 @@ static int __init n810_soc_init(void) | |||
305 | int err; | 309 | int err; |
306 | struct device *dev; | 310 | struct device *dev; |
307 | 311 | ||
308 | if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax())) | 312 | if (!of_have_populated_dt() || |
313 | (!of_machine_is_compatible("nokia,n810") && | ||
314 | !of_machine_is_compatible("nokia,n810-wimax"))) | ||
309 | return -ENODEV; | 315 | return -ENODEV; |
310 | 316 | ||
311 | n810_snd_device = platform_device_alloc("soc-audio", -1); | 317 | n810_snd_device = platform_device_alloc("soc-audio", -1); |
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 611179c3bca4..7fb3d4b10370 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c | |||
@@ -74,26 +74,30 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm) | |||
74 | break; | 74 | break; |
75 | } | 75 | } |
76 | 76 | ||
77 | snd_soc_dapm_mutex_lock(dapm); | ||
78 | |||
77 | if (rx51_spk_func) | 79 | if (rx51_spk_func) |
78 | snd_soc_dapm_enable_pin(dapm, "Ext Spk"); | 80 | snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); |
79 | else | 81 | else |
80 | snd_soc_dapm_disable_pin(dapm, "Ext Spk"); | 82 | snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); |
81 | if (rx51_dmic_func) | 83 | if (rx51_dmic_func) |
82 | snd_soc_dapm_enable_pin(dapm, "DMic"); | 84 | snd_soc_dapm_enable_pin_unlocked(dapm, "DMic"); |
83 | else | 85 | else |
84 | snd_soc_dapm_disable_pin(dapm, "DMic"); | 86 | snd_soc_dapm_disable_pin_unlocked(dapm, "DMic"); |
85 | if (hp) | 87 | if (hp) |
86 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | 88 | snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); |
87 | else | 89 | else |
88 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | 90 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); |
89 | if (hs) | 91 | if (hs) |
90 | snd_soc_dapm_enable_pin(dapm, "HS Mic"); | 92 | snd_soc_dapm_enable_pin_unlocked(dapm, "HS Mic"); |
91 | else | 93 | else |
92 | snd_soc_dapm_disable_pin(dapm, "HS Mic"); | 94 | snd_soc_dapm_disable_pin_unlocked(dapm, "HS Mic"); |
93 | 95 | ||
94 | gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout); | 96 | gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout); |
95 | 97 | ||
96 | snd_soc_dapm_sync(dapm); | 98 | snd_soc_dapm_sync_unlocked(dapm); |
99 | |||
100 | snd_soc_dapm_mutex_unlock(dapm); | ||
97 | } | 101 | } |
98 | 102 | ||
99 | static int rx51_startup(struct snd_pcm_substream *substream) | 103 | static int rx51_startup(struct snd_pcm_substream *substream) |
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 1853d41034bf..5a88136aa800 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c | |||
@@ -47,64 +47,63 @@ static int corgi_spk_func; | |||
47 | 47 | ||
48 | static void corgi_ext_control(struct snd_soc_dapm_context *dapm) | 48 | static void corgi_ext_control(struct snd_soc_dapm_context *dapm) |
49 | { | 49 | { |
50 | snd_soc_dapm_mutex_lock(dapm); | ||
51 | |||
50 | /* set up jack connection */ | 52 | /* set up jack connection */ |
51 | switch (corgi_jack_func) { | 53 | switch (corgi_jack_func) { |
52 | case CORGI_HP: | 54 | case CORGI_HP: |
53 | /* set = unmute headphone */ | 55 | /* set = unmute headphone */ |
54 | gpio_set_value(CORGI_GPIO_MUTE_L, 1); | 56 | gpio_set_value(CORGI_GPIO_MUTE_L, 1); |
55 | gpio_set_value(CORGI_GPIO_MUTE_R, 1); | 57 | gpio_set_value(CORGI_GPIO_MUTE_R, 1); |
56 | snd_soc_dapm_disable_pin(dapm, "Mic Jack"); | 58 | snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); |
57 | snd_soc_dapm_disable_pin(dapm, "Line Jack"); | 59 | snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); |
58 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | 60 | snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); |
59 | snd_soc_dapm_disable_pin(dapm, "Headset Jack"); | 61 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); |
60 | break; | 62 | break; |
61 | case CORGI_MIC: | 63 | case CORGI_MIC: |
62 | /* reset = mute headphone */ | 64 | /* reset = mute headphone */ |
63 | gpio_set_value(CORGI_GPIO_MUTE_L, 0); | 65 | gpio_set_value(CORGI_GPIO_MUTE_L, 0); |
64 | gpio_set_value(CORGI_GPIO_MUTE_R, 0); | 66 | gpio_set_value(CORGI_GPIO_MUTE_R, 0); |
65 | snd_soc_dapm_enable_pin(dapm, "Mic Jack"); | 67 | snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); |
66 | snd_soc_dapm_disable_pin(dapm, "Line Jack"); | 68 | snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); |
67 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | 69 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); |
68 | snd_soc_dapm_disable_pin(dapm, "Headset Jack"); | 70 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); |
69 | break; | 71 | break; |
70 | case CORGI_LINE: | 72 | case CORGI_LINE: |
71 | gpio_set_value(CORGI_GPIO_MUTE_L, 0); | 73 | gpio_set_value(CORGI_GPIO_MUTE_L, 0); |
72 | gpio_set_value(CORGI_GPIO_MUTE_R, 0); | 74 | gpio_set_value(CORGI_GPIO_MUTE_R, 0); |
73 | snd_soc_dapm_disable_pin(dapm, "Mic Jack"); | 75 | snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); |
74 | snd_soc_dapm_enable_pin(dapm, "Line Jack"); | 76 | snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack"); |
75 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | 77 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); |
76 | snd_soc_dapm_disable_pin(dapm, "Headset Jack"); | 78 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); |
77 | break; | 79 | break; |
78 | case CORGI_HEADSET: | 80 | case CORGI_HEADSET: |
79 | gpio_set_value(CORGI_GPIO_MUTE_L, 0); | 81 | gpio_set_value(CORGI_GPIO_MUTE_L, 0); |
80 | gpio_set_value(CORGI_GPIO_MUTE_R, 1); | 82 | gpio_set_value(CORGI_GPIO_MUTE_R, 1); |
81 | snd_soc_dapm_enable_pin(dapm, "Mic Jack"); | 83 | snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); |
82 | snd_soc_dapm_disable_pin(dapm, "Line Jack"); | 84 | snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); |
83 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | 85 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); |
84 | snd_soc_dapm_enable_pin(dapm, "Headset Jack"); | 86 | snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); |
85 | break; | 87 | break; |
86 | } | 88 | } |
87 | 89 | ||
88 | if (corgi_spk_func == CORGI_SPK_ON) | 90 | if (corgi_spk_func == CORGI_SPK_ON) |
89 | snd_soc_dapm_enable_pin(dapm, "Ext Spk"); | 91 | snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); |
90 | else | 92 | else |
91 | snd_soc_dapm_disable_pin(dapm, "Ext Spk"); | 93 | snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); |
92 | 94 | ||
93 | /* signal a DAPM event */ | 95 | /* signal a DAPM event */ |
94 | snd_soc_dapm_sync(dapm); | 96 | snd_soc_dapm_sync_unlocked(dapm); |
97 | |||
98 | snd_soc_dapm_mutex_unlock(dapm); | ||
95 | } | 99 | } |
96 | 100 | ||
97 | static int corgi_startup(struct snd_pcm_substream *substream) | 101 | static int corgi_startup(struct snd_pcm_substream *substream) |
98 | { | 102 | { |
99 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 103 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
100 | struct snd_soc_codec *codec = rtd->codec; | ||
101 | |||
102 | mutex_lock(&codec->mutex); | ||
103 | 104 | ||
104 | /* check the jack status at stream startup */ | 105 | /* check the jack status at stream startup */ |
105 | corgi_ext_control(&codec->dapm); | 106 | corgi_ext_control(&rtd->card->dapm); |
106 | |||
107 | mutex_unlock(&codec->mutex); | ||
108 | 107 | ||
109 | return 0; | 108 | return 0; |
110 | } | 109 | } |
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index 44b5c09d296b..c29fedab2f49 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c | |||
@@ -103,11 +103,6 @@ static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd) | |||
103 | snd_soc_dapm_nc_pin(dapm, "PCBEEP"); | 103 | snd_soc_dapm_nc_pin(dapm, "PCBEEP"); |
104 | snd_soc_dapm_nc_pin(dapm, "MIC2"); | 104 | snd_soc_dapm_nc_pin(dapm, "MIC2"); |
105 | 105 | ||
106 | snd_soc_dapm_new_controls(dapm, e740_dapm_widgets, | ||
107 | ARRAY_SIZE(e740_dapm_widgets)); | ||
108 | |||
109 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
110 | |||
111 | return 0; | 106 | return 0; |
112 | } | 107 | } |
113 | 108 | ||
@@ -136,6 +131,11 @@ static struct snd_soc_card e740 = { | |||
136 | .owner = THIS_MODULE, | 131 | .owner = THIS_MODULE, |
137 | .dai_link = e740_dai, | 132 | .dai_link = e740_dai, |
138 | .num_links = ARRAY_SIZE(e740_dai), | 133 | .num_links = ARRAY_SIZE(e740_dai), |
134 | |||
135 | .dapm_widgets = e740_dapm_widgets, | ||
136 | .num_dapm_widgets = ARRAY_SIZE(e740_dapm_widgets), | ||
137 | .dapm_routes = audio_map, | ||
138 | .num_dapm_routes = ARRAY_SIZE(audio_map), | ||
139 | }; | 139 | }; |
140 | 140 | ||
141 | static struct gpio e740_audio_gpios[] = { | 141 | static struct gpio e740_audio_gpios[] = { |
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index c34e447eb991..ee36aba88063 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c | |||
@@ -85,11 +85,6 @@ static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd) | |||
85 | snd_soc_dapm_nc_pin(dapm, "PCBEEP"); | 85 | snd_soc_dapm_nc_pin(dapm, "PCBEEP"); |
86 | snd_soc_dapm_nc_pin(dapm, "MIC2"); | 86 | snd_soc_dapm_nc_pin(dapm, "MIC2"); |
87 | 87 | ||
88 | snd_soc_dapm_new_controls(dapm, e750_dapm_widgets, | ||
89 | ARRAY_SIZE(e750_dapm_widgets)); | ||
90 | |||
91 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
92 | |||
93 | return 0; | 88 | return 0; |
94 | } | 89 | } |
95 | 90 | ||
@@ -119,6 +114,11 @@ static struct snd_soc_card e750 = { | |||
119 | .owner = THIS_MODULE, | 114 | .owner = THIS_MODULE, |
120 | .dai_link = e750_dai, | 115 | .dai_link = e750_dai, |
121 | .num_links = ARRAY_SIZE(e750_dai), | 116 | .num_links = ARRAY_SIZE(e750_dai), |
117 | |||
118 | .dapm_widgets = e750_dapm_widgets, | ||
119 | .num_dapm_widgets = ARRAY_SIZE(e750_dapm_widgets), | ||
120 | .dapm_routes = audio_map, | ||
121 | .num_dapm_routes = ARRAY_SIZE(audio_map), | ||
122 | }; | 122 | }; |
123 | 123 | ||
124 | static struct gpio e750_audio_gpios[] = { | 124 | static struct gpio e750_audio_gpios[] = { |
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 3137f800b43f..24c2078ce70b 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c | |||
@@ -71,19 +71,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
71 | {"MIC2", NULL, "Mic (Internal2)"}, | 71 | {"MIC2", NULL, "Mic (Internal2)"}, |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd) | ||
75 | { | ||
76 | struct snd_soc_codec *codec = rtd->codec; | ||
77 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
78 | |||
79 | snd_soc_dapm_new_controls(dapm, e800_dapm_widgets, | ||
80 | ARRAY_SIZE(e800_dapm_widgets)); | ||
81 | |||
82 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static struct snd_soc_dai_link e800_dai[] = { | 74 | static struct snd_soc_dai_link e800_dai[] = { |
88 | { | 75 | { |
89 | .name = "AC97", | 76 | .name = "AC97", |
@@ -92,7 +79,6 @@ static struct snd_soc_dai_link e800_dai[] = { | |||
92 | .codec_dai_name = "wm9712-hifi", | 79 | .codec_dai_name = "wm9712-hifi", |
93 | .platform_name = "pxa-pcm-audio", | 80 | .platform_name = "pxa-pcm-audio", |
94 | .codec_name = "wm9712-codec", | 81 | .codec_name = "wm9712-codec", |
95 | .init = e800_ac97_init, | ||
96 | }, | 82 | }, |
97 | { | 83 | { |
98 | .name = "AC97 Aux", | 84 | .name = "AC97 Aux", |
@@ -109,6 +95,11 @@ static struct snd_soc_card e800 = { | |||
109 | .owner = THIS_MODULE, | 95 | .owner = THIS_MODULE, |
110 | .dai_link = e800_dai, | 96 | .dai_link = e800_dai, |
111 | .num_links = ARRAY_SIZE(e800_dai), | 97 | .num_links = ARRAY_SIZE(e800_dai), |
98 | |||
99 | .dapm_widgets = e800_dapm_widgets, | ||
100 | .num_dapm_widgets = ARRAY_SIZE(e800_dapm_widgets), | ||
101 | .dapm_routes = audio_map, | ||
102 | .num_dapm_routes = ARRAY_SIZE(audio_map), | ||
112 | }; | 103 | }; |
113 | 104 | ||
114 | static struct gpio e800_audio_gpios[] = { | 105 | static struct gpio e800_audio_gpios[] = { |
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index aace19e0fe2c..259e048681c0 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c | |||
@@ -41,44 +41,42 @@ static int magician_hp_switch; | |||
41 | static int magician_spk_switch = 1; | 41 | static int magician_spk_switch = 1; |
42 | static int magician_in_sel = MAGICIAN_MIC; | 42 | static int magician_in_sel = MAGICIAN_MIC; |
43 | 43 | ||
44 | static void magician_ext_control(struct snd_soc_codec *codec) | 44 | static void magician_ext_control(struct snd_soc_dapm_context *dapm) |
45 | { | 45 | { |
46 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 46 | |
47 | snd_soc_dapm_mutex_lock(dapm); | ||
47 | 48 | ||
48 | if (magician_spk_switch) | 49 | if (magician_spk_switch) |
49 | snd_soc_dapm_enable_pin(dapm, "Speaker"); | 50 | snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); |
50 | else | 51 | else |
51 | snd_soc_dapm_disable_pin(dapm, "Speaker"); | 52 | snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); |
52 | if (magician_hp_switch) | 53 | if (magician_hp_switch) |
53 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | 54 | snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); |
54 | else | 55 | else |
55 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | 56 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); |
56 | 57 | ||
57 | switch (magician_in_sel) { | 58 | switch (magician_in_sel) { |
58 | case MAGICIAN_MIC: | 59 | case MAGICIAN_MIC: |
59 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | 60 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Mic"); |
60 | snd_soc_dapm_enable_pin(dapm, "Call Mic"); | 61 | snd_soc_dapm_enable_pin_unlocked(dapm, "Call Mic"); |
61 | break; | 62 | break; |
62 | case MAGICIAN_MIC_EXT: | 63 | case MAGICIAN_MIC_EXT: |
63 | snd_soc_dapm_disable_pin(dapm, "Call Mic"); | 64 | snd_soc_dapm_disable_pin_unlocked(dapm, "Call Mic"); |
64 | snd_soc_dapm_enable_pin(dapm, "Headset Mic"); | 65 | snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Mic"); |
65 | break; | 66 | break; |
66 | } | 67 | } |
67 | 68 | ||
68 | snd_soc_dapm_sync(dapm); | 69 | snd_soc_dapm_sync_unlocked(dapm); |
70 | |||
71 | snd_soc_dapm_mutex_unlock(dapm); | ||
69 | } | 72 | } |
70 | 73 | ||
71 | static int magician_startup(struct snd_pcm_substream *substream) | 74 | static int magician_startup(struct snd_pcm_substream *substream) |
72 | { | 75 | { |
73 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 76 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
74 | struct snd_soc_codec *codec = rtd->codec; | ||
75 | |||
76 | mutex_lock(&codec->mutex); | ||
77 | 77 | ||
78 | /* check the jack status at stream startup */ | 78 | /* check the jack status at stream startup */ |
79 | magician_ext_control(codec); | 79 | magician_ext_control(&rtd->card->dapm); |
80 | |||
81 | mutex_unlock(&codec->mutex); | ||
82 | 80 | ||
83 | return 0; | 81 | return 0; |
84 | } | 82 | } |
@@ -277,13 +275,13 @@ static int magician_get_hp(struct snd_kcontrol *kcontrol, | |||
277 | static int magician_set_hp(struct snd_kcontrol *kcontrol, | 275 | static int magician_set_hp(struct snd_kcontrol *kcontrol, |
278 | struct snd_ctl_elem_value *ucontrol) | 276 | struct snd_ctl_elem_value *ucontrol) |
279 | { | 277 | { |
280 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 278 | struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); |
281 | 279 | ||
282 | if (magician_hp_switch == ucontrol->value.integer.value[0]) | 280 | if (magician_hp_switch == ucontrol->value.integer.value[0]) |
283 | return 0; | 281 | return 0; |
284 | 282 | ||
285 | magician_hp_switch = ucontrol->value.integer.value[0]; | 283 | magician_hp_switch = ucontrol->value.integer.value[0]; |
286 | magician_ext_control(codec); | 284 | magician_ext_control(&card->dapm); |
287 | return 1; | 285 | return 1; |
288 | } | 286 | } |
289 | 287 | ||
@@ -297,13 +295,13 @@ static int magician_get_spk(struct snd_kcontrol *kcontrol, | |||
297 | static int magician_set_spk(struct snd_kcontrol *kcontrol, | 295 | static int magician_set_spk(struct snd_kcontrol *kcontrol, |
298 | struct snd_ctl_elem_value *ucontrol) | 296 | struct snd_ctl_elem_value *ucontrol) |
299 | { | 297 | { |
300 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 298 | struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); |
301 | 299 | ||
302 | if (magician_spk_switch == ucontrol->value.integer.value[0]) | 300 | if (magician_spk_switch == ucontrol->value.integer.value[0]) |
303 | return 0; | 301 | return 0; |
304 | 302 | ||
305 | magician_spk_switch = ucontrol->value.integer.value[0]; | 303 | magician_spk_switch = ucontrol->value.integer.value[0]; |
306 | magician_ext_control(codec); | 304 | magician_ext_control(&card->dapm); |
307 | return 1; | 305 | return 1; |
308 | } | 306 | } |
309 | 307 | ||
@@ -400,7 +398,6 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd) | |||
400 | { | 398 | { |
401 | struct snd_soc_codec *codec = rtd->codec; | 399 | struct snd_soc_codec *codec = rtd->codec; |
402 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 400 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
403 | int err; | ||
404 | 401 | ||
405 | /* NC codec pins */ | 402 | /* NC codec pins */ |
406 | snd_soc_dapm_nc_pin(dapm, "VOUTLHP"); | 403 | snd_soc_dapm_nc_pin(dapm, "VOUTLHP"); |
@@ -410,19 +407,6 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd) | |||
410 | snd_soc_dapm_nc_pin(dapm, "VINL"); | 407 | snd_soc_dapm_nc_pin(dapm, "VINL"); |
411 | snd_soc_dapm_nc_pin(dapm, "VINR"); | 408 | snd_soc_dapm_nc_pin(dapm, "VINR"); |
412 | 409 | ||
413 | /* Add magician specific controls */ | ||
414 | err = snd_soc_add_codec_controls(codec, uda1380_magician_controls, | ||
415 | ARRAY_SIZE(uda1380_magician_controls)); | ||
416 | if (err < 0) | ||
417 | return err; | ||
418 | |||
419 | /* Add magician specific widgets */ | ||
420 | snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets, | ||
421 | ARRAY_SIZE(uda1380_dapm_widgets)); | ||
422 | |||
423 | /* Set up magician specific audio path interconnects */ | ||
424 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
425 | |||
426 | return 0; | 410 | return 0; |
427 | } | 411 | } |
428 | 412 | ||
@@ -456,6 +440,12 @@ static struct snd_soc_card snd_soc_card_magician = { | |||
456 | .dai_link = magician_dai, | 440 | .dai_link = magician_dai, |
457 | .num_links = ARRAY_SIZE(magician_dai), | 441 | .num_links = ARRAY_SIZE(magician_dai), |
458 | 442 | ||
443 | .controls = uda1380_magician_controls, | ||
444 | .num_controls = ARRAY_SIZE(uda1380_magician_controls), | ||
445 | .dapm_widgets = uda1380_dapm_widgets, | ||
446 | .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), | ||
447 | .dapm_routes = audio_map, | ||
448 | .num_dapm_routes = ARRAY_SIZE(audio_map), | ||
459 | }; | 449 | }; |
460 | 450 | ||
461 | static struct platform_device *magician_snd_device; | 451 | static struct platform_device *magician_snd_device; |
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 160c5245448f..595eee341e90 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c | |||
@@ -127,16 +127,8 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
127 | static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) | 127 | static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) |
128 | { | 128 | { |
129 | struct snd_soc_codec *codec = rtd->codec; | 129 | struct snd_soc_codec *codec = rtd->codec; |
130 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
131 | unsigned short reg; | 130 | unsigned short reg; |
132 | 131 | ||
133 | /* Add mioa701 specific widgets */ | ||
134 | snd_soc_dapm_new_controls(dapm, mioa701_dapm_widgets, | ||
135 | ARRAY_SIZE(mioa701_dapm_widgets)); | ||
136 | |||
137 | /* Set up mioa701 specific audio path audio_mapnects */ | ||
138 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
139 | |||
140 | /* Prepare GPIO8 for rear speaker amplifier */ | 132 | /* Prepare GPIO8 for rear speaker amplifier */ |
141 | reg = codec->driver->read(codec, AC97_GPIO_CFG); | 133 | reg = codec->driver->read(codec, AC97_GPIO_CFG); |
142 | codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100); | 134 | codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100); |
@@ -145,12 +137,6 @@ static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) | |||
145 | reg = codec->driver->read(codec, AC97_3D_CONTROL); | 137 | reg = codec->driver->read(codec, AC97_3D_CONTROL); |
146 | codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000); | 138 | codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000); |
147 | 139 | ||
148 | snd_soc_dapm_enable_pin(dapm, "Front Speaker"); | ||
149 | snd_soc_dapm_enable_pin(dapm, "Rear Speaker"); | ||
150 | snd_soc_dapm_enable_pin(dapm, "Front Mic"); | ||
151 | snd_soc_dapm_enable_pin(dapm, "GSM Line In"); | ||
152 | snd_soc_dapm_enable_pin(dapm, "GSM Line Out"); | ||
153 | |||
154 | return 0; | 140 | return 0; |
155 | } | 141 | } |
156 | 142 | ||
@@ -183,6 +169,11 @@ static struct snd_soc_card mioa701 = { | |||
183 | .owner = THIS_MODULE, | 169 | .owner = THIS_MODULE, |
184 | .dai_link = mioa701_dai, | 170 | .dai_link = mioa701_dai, |
185 | .num_links = ARRAY_SIZE(mioa701_dai), | 171 | .num_links = ARRAY_SIZE(mioa701_dai), |
172 | |||
173 | .dapm_widgets = mioa701_dapm_widgets, | ||
174 | .num_dapm_widgets = ARRAY_SIZE(mioa701_dapm_widgets), | ||
175 | .dapm_routes = audio_map, | ||
176 | .num_dapm_routes = ARRAY_SIZE(audio_map), | ||
186 | }; | 177 | }; |
187 | 178 | ||
188 | static int mioa701_wm9713_probe(struct platform_device *pdev) | 179 | static int mioa701_wm9713_probe(struct platform_device *pdev) |
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index c93e138d8dc3..c6bdc6c0eff6 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c | |||
@@ -74,14 +74,9 @@ static void poodle_ext_control(struct snd_soc_dapm_context *dapm) | |||
74 | static int poodle_startup(struct snd_pcm_substream *substream) | 74 | static int poodle_startup(struct snd_pcm_substream *substream) |
75 | { | 75 | { |
76 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 76 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
77 | struct snd_soc_codec *codec = rtd->codec; | ||
78 | |||
79 | mutex_lock(&codec->mutex); | ||
80 | 77 | ||
81 | /* check the jack status at stream startup */ | 78 | /* check the jack status at stream startup */ |
82 | poodle_ext_control(&codec->dapm); | 79 | poodle_ext_control(&rtd->card->dapm); |
83 | |||
84 | mutex_unlock(&codec->mutex); | ||
85 | 80 | ||
86 | return 0; | 81 | return 0; |
87 | } | 82 | } |
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index fc052d8247ff..1373b017a951 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c | |||
@@ -46,74 +46,74 @@ static int spitz_mic_gpio; | |||
46 | 46 | ||
47 | static void spitz_ext_control(struct snd_soc_dapm_context *dapm) | 47 | static void spitz_ext_control(struct snd_soc_dapm_context *dapm) |
48 | { | 48 | { |
49 | snd_soc_dapm_mutex_lock(dapm); | ||
50 | |||
49 | if (spitz_spk_func == SPITZ_SPK_ON) | 51 | if (spitz_spk_func == SPITZ_SPK_ON) |
50 | snd_soc_dapm_enable_pin(dapm, "Ext Spk"); | 52 | snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); |
51 | else | 53 | else |
52 | snd_soc_dapm_disable_pin(dapm, "Ext Spk"); | 54 | snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); |
53 | 55 | ||
54 | /* set up jack connection */ | 56 | /* set up jack connection */ |
55 | switch (spitz_jack_func) { | 57 | switch (spitz_jack_func) { |
56 | case SPITZ_HP: | 58 | case SPITZ_HP: |
57 | /* enable and unmute hp jack, disable mic bias */ | 59 | /* enable and unmute hp jack, disable mic bias */ |
58 | snd_soc_dapm_disable_pin(dapm, "Headset Jack"); | 60 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); |
59 | snd_soc_dapm_disable_pin(dapm, "Mic Jack"); | 61 | snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); |
60 | snd_soc_dapm_disable_pin(dapm, "Line Jack"); | 62 | snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); |
61 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | 63 | snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); |
62 | gpio_set_value(SPITZ_GPIO_MUTE_L, 1); | 64 | gpio_set_value(SPITZ_GPIO_MUTE_L, 1); |
63 | gpio_set_value(SPITZ_GPIO_MUTE_R, 1); | 65 | gpio_set_value(SPITZ_GPIO_MUTE_R, 1); |
64 | break; | 66 | break; |
65 | case SPITZ_MIC: | 67 | case SPITZ_MIC: |
66 | /* enable mic jack and bias, mute hp */ | 68 | /* enable mic jack and bias, mute hp */ |
67 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | 69 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); |
68 | snd_soc_dapm_disable_pin(dapm, "Headset Jack"); | 70 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); |
69 | snd_soc_dapm_disable_pin(dapm, "Line Jack"); | 71 | snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); |
70 | snd_soc_dapm_enable_pin(dapm, "Mic Jack"); | 72 | snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); |
71 | gpio_set_value(SPITZ_GPIO_MUTE_L, 0); | 73 | gpio_set_value(SPITZ_GPIO_MUTE_L, 0); |
72 | gpio_set_value(SPITZ_GPIO_MUTE_R, 0); | 74 | gpio_set_value(SPITZ_GPIO_MUTE_R, 0); |
73 | break; | 75 | break; |
74 | case SPITZ_LINE: | 76 | case SPITZ_LINE: |
75 | /* enable line jack, disable mic bias and mute hp */ | 77 | /* enable line jack, disable mic bias and mute hp */ |
76 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | 78 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); |
77 | snd_soc_dapm_disable_pin(dapm, "Headset Jack"); | 79 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); |
78 | snd_soc_dapm_disable_pin(dapm, "Mic Jack"); | 80 | snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); |
79 | snd_soc_dapm_enable_pin(dapm, "Line Jack"); | 81 | snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack"); |
80 | gpio_set_value(SPITZ_GPIO_MUTE_L, 0); | 82 | gpio_set_value(SPITZ_GPIO_MUTE_L, 0); |
81 | gpio_set_value(SPITZ_GPIO_MUTE_R, 0); | 83 | gpio_set_value(SPITZ_GPIO_MUTE_R, 0); |
82 | break; | 84 | break; |
83 | case SPITZ_HEADSET: | 85 | case SPITZ_HEADSET: |
84 | /* enable and unmute headset jack enable mic bias, mute L hp */ | 86 | /* enable and unmute headset jack enable mic bias, mute L hp */ |
85 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | 87 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); |
86 | snd_soc_dapm_enable_pin(dapm, "Mic Jack"); | 88 | snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); |
87 | snd_soc_dapm_disable_pin(dapm, "Line Jack"); | 89 | snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); |
88 | snd_soc_dapm_enable_pin(dapm, "Headset Jack"); | 90 | snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); |
89 | gpio_set_value(SPITZ_GPIO_MUTE_L, 0); | 91 | gpio_set_value(SPITZ_GPIO_MUTE_L, 0); |
90 | gpio_set_value(SPITZ_GPIO_MUTE_R, 1); | 92 | gpio_set_value(SPITZ_GPIO_MUTE_R, 1); |
91 | break; | 93 | break; |
92 | case SPITZ_HP_OFF: | 94 | case SPITZ_HP_OFF: |
93 | 95 | ||
94 | /* jack removed, everything off */ | 96 | /* jack removed, everything off */ |
95 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | 97 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); |
96 | snd_soc_dapm_disable_pin(dapm, "Headset Jack"); | 98 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); |
97 | snd_soc_dapm_disable_pin(dapm, "Mic Jack"); | 99 | snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); |
98 | snd_soc_dapm_disable_pin(dapm, "Line Jack"); | 100 | snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); |
99 | gpio_set_value(SPITZ_GPIO_MUTE_L, 0); | 101 | gpio_set_value(SPITZ_GPIO_MUTE_L, 0); |
100 | gpio_set_value(SPITZ_GPIO_MUTE_R, 0); | 102 | gpio_set_value(SPITZ_GPIO_MUTE_R, 0); |
101 | break; | 103 | break; |
102 | } | 104 | } |
103 | snd_soc_dapm_sync(dapm); | 105 | |
106 | snd_soc_dapm_sync_unlocked(dapm); | ||
107 | |||
108 | snd_soc_dapm_mutex_unlock(dapm); | ||
104 | } | 109 | } |
105 | 110 | ||
106 | static int spitz_startup(struct snd_pcm_substream *substream) | 111 | static int spitz_startup(struct snd_pcm_substream *substream) |
107 | { | 112 | { |
108 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 113 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
109 | struct snd_soc_codec *codec = rtd->codec; | ||
110 | |||
111 | mutex_lock(&codec->mutex); | ||
112 | 114 | ||
113 | /* check the jack status at stream startup */ | 115 | /* check the jack status at stream startup */ |
114 | spitz_ext_control(&codec->dapm); | 116 | spitz_ext_control(&rtd->card->dapm); |
115 | |||
116 | mutex_unlock(&codec->mutex); | ||
117 | 117 | ||
118 | return 0; | 118 | return 0; |
119 | } | 119 | } |
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 1d9c2ed223bc..4a956d1cb269 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c | |||
@@ -44,48 +44,46 @@ | |||
44 | static int tosa_jack_func; | 44 | static int tosa_jack_func; |
45 | static int tosa_spk_func; | 45 | static int tosa_spk_func; |
46 | 46 | ||
47 | static void tosa_ext_control(struct snd_soc_codec *codec) | 47 | static void tosa_ext_control(struct snd_soc_dapm_context *dapm) |
48 | { | 48 | { |
49 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 49 | |
50 | snd_soc_dapm_mutex_lock(dapm); | ||
50 | 51 | ||
51 | /* set up jack connection */ | 52 | /* set up jack connection */ |
52 | switch (tosa_jack_func) { | 53 | switch (tosa_jack_func) { |
53 | case TOSA_HP: | 54 | case TOSA_HP: |
54 | snd_soc_dapm_disable_pin(dapm, "Mic (Internal)"); | 55 | snd_soc_dapm_disable_pin_unlocked(dapm, "Mic (Internal)"); |
55 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | 56 | snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); |
56 | snd_soc_dapm_disable_pin(dapm, "Headset Jack"); | 57 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); |
57 | break; | 58 | break; |
58 | case TOSA_MIC_INT: | 59 | case TOSA_MIC_INT: |
59 | snd_soc_dapm_enable_pin(dapm, "Mic (Internal)"); | 60 | snd_soc_dapm_enable_pin_unlocked(dapm, "Mic (Internal)"); |
60 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | 61 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); |
61 | snd_soc_dapm_disable_pin(dapm, "Headset Jack"); | 62 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); |
62 | break; | 63 | break; |
63 | case TOSA_HEADSET: | 64 | case TOSA_HEADSET: |
64 | snd_soc_dapm_disable_pin(dapm, "Mic (Internal)"); | 65 | snd_soc_dapm_disable_pin_unlocked(dapm, "Mic (Internal)"); |
65 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | 66 | snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); |
66 | snd_soc_dapm_enable_pin(dapm, "Headset Jack"); | 67 | snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); |
67 | break; | 68 | break; |
68 | } | 69 | } |
69 | 70 | ||
70 | if (tosa_spk_func == TOSA_SPK_ON) | 71 | if (tosa_spk_func == TOSA_SPK_ON) |
71 | snd_soc_dapm_enable_pin(dapm, "Speaker"); | 72 | snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); |
72 | else | 73 | else |
73 | snd_soc_dapm_disable_pin(dapm, "Speaker"); | 74 | snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); |
75 | |||
76 | snd_soc_dapm_sync_unlocked(dapm); | ||
74 | 77 | ||
75 | snd_soc_dapm_sync(dapm); | 78 | snd_soc_dapm_mutex_unlock(dapm); |
76 | } | 79 | } |
77 | 80 | ||
78 | static int tosa_startup(struct snd_pcm_substream *substream) | 81 | static int tosa_startup(struct snd_pcm_substream *substream) |
79 | { | 82 | { |
80 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 83 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
81 | struct snd_soc_codec *codec = rtd->codec; | ||
82 | |||
83 | mutex_lock(&codec->mutex); | ||
84 | 84 | ||
85 | /* check the jack status at stream startup */ | 85 | /* check the jack status at stream startup */ |
86 | tosa_ext_control(codec); | 86 | tosa_ext_control(&rtd->card->dapm); |
87 | |||
88 | mutex_unlock(&codec->mutex); | ||
89 | 87 | ||
90 | return 0; | 88 | return 0; |
91 | } | 89 | } |
@@ -104,13 +102,13 @@ static int tosa_get_jack(struct snd_kcontrol *kcontrol, | |||
104 | static int tosa_set_jack(struct snd_kcontrol *kcontrol, | 102 | static int tosa_set_jack(struct snd_kcontrol *kcontrol, |
105 | struct snd_ctl_elem_value *ucontrol) | 103 | struct snd_ctl_elem_value *ucontrol) |
106 | { | 104 | { |
107 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 105 | struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); |
108 | 106 | ||
109 | if (tosa_jack_func == ucontrol->value.integer.value[0]) | 107 | if (tosa_jack_func == ucontrol->value.integer.value[0]) |
110 | return 0; | 108 | return 0; |
111 | 109 | ||
112 | tosa_jack_func = ucontrol->value.integer.value[0]; | 110 | tosa_jack_func = ucontrol->value.integer.value[0]; |
113 | tosa_ext_control(codec); | 111 | tosa_ext_control(&card->dapm); |
114 | return 1; | 112 | return 1; |
115 | } | 113 | } |
116 | 114 | ||
@@ -124,13 +122,13 @@ static int tosa_get_spk(struct snd_kcontrol *kcontrol, | |||
124 | static int tosa_set_spk(struct snd_kcontrol *kcontrol, | 122 | static int tosa_set_spk(struct snd_kcontrol *kcontrol, |
125 | struct snd_ctl_elem_value *ucontrol) | 123 | struct snd_ctl_elem_value *ucontrol) |
126 | { | 124 | { |
127 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 125 | struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); |
128 | 126 | ||
129 | if (tosa_spk_func == ucontrol->value.integer.value[0]) | 127 | if (tosa_spk_func == ucontrol->value.integer.value[0]) |
130 | return 0; | 128 | return 0; |
131 | 129 | ||
132 | tosa_spk_func = ucontrol->value.integer.value[0]; | 130 | tosa_spk_func = ucontrol->value.integer.value[0]; |
133 | tosa_ext_control(codec); | 131 | tosa_ext_control(&card->dapm); |
134 | return 1; | 132 | return 1; |
135 | } | 133 | } |
136 | 134 | ||
@@ -191,24 +189,10 @@ static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd) | |||
191 | { | 189 | { |
192 | struct snd_soc_codec *codec = rtd->codec; | 190 | struct snd_soc_codec *codec = rtd->codec; |
193 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 191 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
194 | int err; | ||
195 | 192 | ||
196 | snd_soc_dapm_nc_pin(dapm, "OUT3"); | 193 | snd_soc_dapm_nc_pin(dapm, "OUT3"); |
197 | snd_soc_dapm_nc_pin(dapm, "MONOOUT"); | 194 | snd_soc_dapm_nc_pin(dapm, "MONOOUT"); |
198 | 195 | ||
199 | /* add tosa specific controls */ | ||
200 | err = snd_soc_add_codec_controls(codec, tosa_controls, | ||
201 | ARRAY_SIZE(tosa_controls)); | ||
202 | if (err < 0) | ||
203 | return err; | ||
204 | |||
205 | /* add tosa specific widgets */ | ||
206 | snd_soc_dapm_new_controls(dapm, tosa_dapm_widgets, | ||
207 | ARRAY_SIZE(tosa_dapm_widgets)); | ||
208 | |||
209 | /* set up tosa specific audio path audio_map */ | ||
210 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
211 | |||
212 | return 0; | 196 | return 0; |
213 | } | 197 | } |
214 | 198 | ||
@@ -239,6 +223,13 @@ static struct snd_soc_card tosa = { | |||
239 | .owner = THIS_MODULE, | 223 | .owner = THIS_MODULE, |
240 | .dai_link = tosa_dai, | 224 | .dai_link = tosa_dai, |
241 | .num_links = ARRAY_SIZE(tosa_dai), | 225 | .num_links = ARRAY_SIZE(tosa_dai), |
226 | |||
227 | .controls = tosa_controls, | ||
228 | .num_controls = ARRAY_SIZE(tosa_controls), | ||
229 | .dapm_widgets = tosa_dapm_widgets, | ||
230 | .num_dapm_widgets = ARRAY_SIZE(tosa_dapm_widgets), | ||
231 | .dapm_routes = audio_map, | ||
232 | .num_dapm_routes = ARRAY_SIZE(audio_map), | ||
242 | }; | 233 | }; |
243 | 234 | ||
244 | static int tosa_probe(struct platform_device *pdev) | 235 | static int tosa_probe(struct platform_device *pdev) |
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index db8aadf8932d..23bf991e95d5 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c | |||
@@ -71,22 +71,10 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
71 | 71 | ||
72 | static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd) | 72 | static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd) |
73 | { | 73 | { |
74 | struct snd_soc_codec *codec = rtd->codec; | ||
75 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
76 | |||
77 | if (clk_pout) | 74 | if (clk_pout) |
78 | snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, | 75 | snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, |
79 | clk_get_rate(pout), 0); | 76 | clk_get_rate(pout), 0); |
80 | 77 | ||
81 | snd_soc_dapm_new_controls(dapm, zylonite_dapm_widgets, | ||
82 | ARRAY_SIZE(zylonite_dapm_widgets)); | ||
83 | |||
84 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
85 | |||
86 | /* Static setup for now */ | ||
87 | snd_soc_dapm_enable_pin(dapm, "Headphone"); | ||
88 | snd_soc_dapm_enable_pin(dapm, "Headset Earpiece"); | ||
89 | |||
90 | return 0; | 78 | return 0; |
91 | } | 79 | } |
92 | 80 | ||
@@ -256,6 +244,11 @@ static struct snd_soc_card zylonite = { | |||
256 | .resume_pre = &zylonite_resume_pre, | 244 | .resume_pre = &zylonite_resume_pre, |
257 | .dai_link = zylonite_dai, | 245 | .dai_link = zylonite_dai, |
258 | .num_links = ARRAY_SIZE(zylonite_dai), | 246 | .num_links = ARRAY_SIZE(zylonite_dai), |
247 | |||
248 | .dapm_widgets = zylonite_dapm_widgets, | ||
249 | .num_dapm_widgets = ARRAY_SIZE(zylonite_dapm_widgets), | ||
250 | .dapm_routes = audio_map, | ||
251 | .num_dapm_routes = ARRAY_SIZE(audio_map), | ||
259 | }; | 252 | }; |
260 | 253 | ||
261 | static struct platform_device *zylonite_snd_ac97_device; | 254 | static struct platform_device *zylonite_snd_ac97_device; |
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c index 945e8abdc10f..0b21d1dc80c1 100644 --- a/sound/soc/s6000/s6105-ipcam.c +++ b/sound/soc/s6000/s6105-ipcam.c | |||
@@ -104,8 +104,8 @@ static int output_type_get(struct snd_kcontrol *kcontrol, | |||
104 | static int output_type_put(struct snd_kcontrol *kcontrol, | 104 | static int output_type_put(struct snd_kcontrol *kcontrol, |
105 | struct snd_ctl_elem_value *ucontrol) | 105 | struct snd_ctl_elem_value *ucontrol) |
106 | { | 106 | { |
107 | struct snd_soc_codec *codec = kcontrol->private_data; | 107 | struct snd_soc_card *card = kcontrol->private_data; |
108 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 108 | struct snd_soc_dapm_context *dapm = &card->dapm; |
109 | unsigned int val = (ucontrol->value.enumerated.item[0] != 0); | 109 | unsigned int val = (ucontrol->value.enumerated.item[0] != 0); |
110 | char *differential = "Audio Out Differential"; | 110 | char *differential = "Audio Out Differential"; |
111 | char *stereo = "Audio Out Stereo"; | 111 | char *stereo = "Audio Out Stereo"; |
@@ -137,13 +137,7 @@ static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) | |||
137 | { | 137 | { |
138 | struct snd_soc_codec *codec = rtd->codec; | 138 | struct snd_soc_codec *codec = rtd->codec; |
139 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 139 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
140 | 140 | struct snd_soc_card *card = rtd->card; | |
141 | /* Add s6105 specific widgets */ | ||
142 | snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, | ||
143 | ARRAY_SIZE(aic3x_dapm_widgets)); | ||
144 | |||
145 | /* Set up s6105 specific audio path audio_map */ | ||
146 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
147 | 141 | ||
148 | /* not present */ | 142 | /* not present */ |
149 | snd_soc_dapm_nc_pin(dapm, "MONO_LOUT"); | 143 | snd_soc_dapm_nc_pin(dapm, "MONO_LOUT"); |
@@ -157,17 +151,10 @@ static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) | |||
157 | snd_soc_dapm_nc_pin(dapm, "RLOUT"); | 151 | snd_soc_dapm_nc_pin(dapm, "RLOUT"); |
158 | snd_soc_dapm_nc_pin(dapm, "HPRCOM"); | 152 | snd_soc_dapm_nc_pin(dapm, "HPRCOM"); |
159 | 153 | ||
160 | /* always connected */ | ||
161 | snd_soc_dapm_enable_pin(dapm, "Audio In"); | ||
162 | |||
163 | /* must correspond to audio_out_mux.private_value initializer */ | 154 | /* must correspond to audio_out_mux.private_value initializer */ |
164 | snd_soc_dapm_disable_pin(dapm, "Audio Out Differential"); | 155 | snd_soc_dapm_disable_pin(&card->dapm, "Audio Out Differential"); |
165 | snd_soc_dapm_sync(dapm); | ||
166 | snd_soc_dapm_enable_pin(dapm, "Audio Out Stereo"); | ||
167 | |||
168 | snd_soc_dapm_sync(dapm); | ||
169 | 156 | ||
170 | snd_ctl_add(codec->card->snd_card, snd_ctl_new1(&audio_out_mux, codec)); | 157 | snd_ctl_add(card->snd_card, snd_ctl_new1(&audio_out_mux, card)); |
171 | 158 | ||
172 | return 0; | 159 | return 0; |
173 | } | 160 | } |
@@ -190,6 +177,11 @@ static struct snd_soc_card snd_soc_card_s6105 = { | |||
190 | .owner = THIS_MODULE, | 177 | .owner = THIS_MODULE, |
191 | .dai_link = &s6105_dai, | 178 | .dai_link = &s6105_dai, |
192 | .num_links = 1, | 179 | .num_links = 1, |
180 | |||
181 | .dapm_widgets = aic3x_dapm_widgets, | ||
182 | .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), | ||
183 | .dapm_routes = audio_map, | ||
184 | .num_dapm_routes = ARRAY_SIZE(audio_map), | ||
193 | }; | 185 | }; |
194 | 186 | ||
195 | static struct s6000_snd_platform_data s6105_snd_data __initdata = { | 187 | static struct s6000_snd_platform_data s6105_snd_data __initdata = { |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 454f41cfc828..f2e289180e46 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -59,7 +59,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750 | |||
59 | select SND_SOC_WM8750 | 59 | select SND_SOC_WM8750 |
60 | select SND_S3C2412_SOC_I2S | 60 | select SND_S3C2412_SOC_I2S |
61 | help | 61 | help |
62 | Sat Y if you want to add support for SoC audio on the Jive. | 62 | Say Y if you want to add support for SoC audio on the Jive. |
63 | 63 | ||
64 | config SND_SOC_SAMSUNG_SMDK_WM8580 | 64 | config SND_SOC_SAMSUNG_SMDK_WM8580 |
65 | tristate "SoC I2S Audio support for WM8580 on SMDK" | 65 | tristate "SoC I2S Audio support for WM8580 on SMDK" |
@@ -117,7 +117,7 @@ config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23 | |||
117 | tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" | 117 | tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" |
118 | depends on SND_SOC_SAMSUNG && ARCH_S3C24XX | 118 | depends on SND_SOC_SAMSUNG && ARCH_S3C24XX |
119 | select SND_S3C24XX_I2S | 119 | select SND_S3C24XX_I2S |
120 | select SND_SOC_TLV320AIC23 | 120 | select SND_SOC_TLV320AIC23_I2C |
121 | select SND_SOC_SAMSUNG_SIMTEC | 121 | select SND_SOC_SAMSUNG_SIMTEC |
122 | 122 | ||
123 | config SND_SOC_SAMSUNG_SIMTEC_HERMES | 123 | config SND_SOC_SAMSUNG_SIMTEC_HERMES |
@@ -145,11 +145,11 @@ config SND_SOC_SAMSUNG_RX1950_UDA1380 | |||
145 | 145 | ||
146 | config SND_SOC_SAMSUNG_SMDK_WM9713 | 146 | config SND_SOC_SAMSUNG_SMDK_WM9713 |
147 | tristate "SoC AC97 Audio support for SMDK with WM9713" | 147 | tristate "SoC AC97 Audio support for SMDK with WM9713" |
148 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110 || MACH_SMDKV310 || MACH_SMDKC210) | 148 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) |
149 | select SND_SOC_WM9713 | 149 | select SND_SOC_WM9713 |
150 | select SND_SAMSUNG_AC97 | 150 | select SND_SAMSUNG_AC97 |
151 | help | 151 | help |
152 | Sat Y if you want to add support for SoC audio on the SMDK. | 152 | Say Y if you want to add support for SoC audio on the SMDK. |
153 | 153 | ||
154 | config SND_SOC_SMARTQ | 154 | config SND_SOC_SMARTQ |
155 | tristate "SoC I2S Audio support for SmartQ board" | 155 | tristate "SoC I2S Audio support for SmartQ board" |
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index fbced589d077..88b09e022503 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c | |||
@@ -66,10 +66,6 @@ static int h1940_startup(struct snd_pcm_substream *substream) | |||
66 | { | 66 | { |
67 | struct snd_pcm_runtime *runtime = substream->runtime; | 67 | struct snd_pcm_runtime *runtime = substream->runtime; |
68 | 68 | ||
69 | runtime->hw.rate_min = hw_rates.list[0]; | ||
70 | runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; | ||
71 | runtime->hw.rates = SNDRV_PCM_RATE_KNOT; | ||
72 | |||
73 | return snd_pcm_hw_constraint_list(runtime, 0, | 69 | return snd_pcm_hw_constraint_list(runtime, 0, |
74 | SNDRV_PCM_HW_PARAM_RATE, | 70 | SNDRV_PCM_HW_PARAM_RATE, |
75 | &hw_rates); | 71 | &hw_rates); |
@@ -94,7 +90,7 @@ static int h1940_hw_params(struct snd_pcm_substream *substream, | |||
94 | div++; | 90 | div++; |
95 | break; | 91 | break; |
96 | default: | 92 | default: |
97 | dev_err(&rtd->dev, "%s: rate %d is not supported\n", | 93 | dev_err(rtd->dev, "%s: rate %d is not supported\n", |
98 | __func__, rate); | 94 | __func__, rate); |
99 | return -EINVAL; | 95 | return -EINVAL; |
100 | } | 96 | } |
@@ -181,7 +177,6 @@ static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd) | |||
181 | { | 177 | { |
182 | struct snd_soc_codec *codec = rtd->codec; | 178 | struct snd_soc_codec *codec = rtd->codec; |
183 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 179 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
184 | int err; | ||
185 | 180 | ||
186 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | 181 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); |
187 | snd_soc_dapm_enable_pin(dapm, "Speaker"); | 182 | snd_soc_dapm_enable_pin(dapm, "Speaker"); |
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 98a04c11202d..b0800337b79e 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c | |||
@@ -192,44 +192,6 @@ static struct snd_soc_ops neo1973_voice_ops = { | |||
192 | .hw_free = neo1973_voice_hw_free, | 192 | .hw_free = neo1973_voice_hw_free, |
193 | }; | 193 | }; |
194 | 194 | ||
195 | /* Shared routes and controls */ | ||
196 | |||
197 | static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = { | ||
198 | SND_SOC_DAPM_LINE("GSM Line Out", NULL), | ||
199 | SND_SOC_DAPM_LINE("GSM Line In", NULL), | ||
200 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
201 | SND_SOC_DAPM_MIC("Handset Mic", NULL), | ||
202 | }; | ||
203 | |||
204 | static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { | ||
205 | /* Connections to the GSM Module */ | ||
206 | {"GSM Line Out", NULL, "MONO1"}, | ||
207 | {"GSM Line Out", NULL, "MONO2"}, | ||
208 | {"RXP", NULL, "GSM Line In"}, | ||
209 | {"RXN", NULL, "GSM Line In"}, | ||
210 | |||
211 | /* Connections to Headset */ | ||
212 | {"MIC1", NULL, "Mic Bias"}, | ||
213 | {"Mic Bias", NULL, "Headset Mic"}, | ||
214 | |||
215 | /* Call Mic */ | ||
216 | {"MIC2", NULL, "Mic Bias"}, | ||
217 | {"MIC2N", NULL, "Mic Bias"}, | ||
218 | {"Mic Bias", NULL, "Handset Mic"}, | ||
219 | |||
220 | /* Connect the ALC pins */ | ||
221 | {"ACIN", NULL, "ACOP"}, | ||
222 | }; | ||
223 | |||
224 | static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { | ||
225 | SOC_DAPM_PIN_SWITCH("GSM Line Out"), | ||
226 | SOC_DAPM_PIN_SWITCH("GSM Line In"), | ||
227 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
228 | SOC_DAPM_PIN_SWITCH("Handset Mic"), | ||
229 | }; | ||
230 | |||
231 | /* GTA02 specific routes and controls */ | ||
232 | |||
233 | static int gta02_speaker_enabled; | 195 | static int gta02_speaker_enabled; |
234 | 196 | ||
235 | static int lm4853_set_spk(struct snd_kcontrol *kcontrol, | 197 | static int lm4853_set_spk(struct snd_kcontrol *kcontrol, |
@@ -257,7 +219,34 @@ static int lm4853_event(struct snd_soc_dapm_widget *w, | |||
257 | return 0; | 219 | return 0; |
258 | } | 220 | } |
259 | 221 | ||
260 | static const struct snd_soc_dapm_route neo1973_gta02_routes[] = { | 222 | static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = { |
223 | SND_SOC_DAPM_LINE("GSM Line Out", NULL), | ||
224 | SND_SOC_DAPM_LINE("GSM Line In", NULL), | ||
225 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
226 | SND_SOC_DAPM_MIC("Handset Mic", NULL), | ||
227 | SND_SOC_DAPM_SPK("Handset Spk", NULL), | ||
228 | SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), | ||
229 | }; | ||
230 | |||
231 | static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { | ||
232 | /* Connections to the GSM Module */ | ||
233 | {"GSM Line Out", NULL, "MONO1"}, | ||
234 | {"GSM Line Out", NULL, "MONO2"}, | ||
235 | {"RXP", NULL, "GSM Line In"}, | ||
236 | {"RXN", NULL, "GSM Line In"}, | ||
237 | |||
238 | /* Connections to Headset */ | ||
239 | {"MIC1", NULL, "Mic Bias"}, | ||
240 | {"Mic Bias", NULL, "Headset Mic"}, | ||
241 | |||
242 | /* Call Mic */ | ||
243 | {"MIC2", NULL, "Mic Bias"}, | ||
244 | {"MIC2N", NULL, "Mic Bias"}, | ||
245 | {"Mic Bias", NULL, "Handset Mic"}, | ||
246 | |||
247 | /* Connect the ALC pins */ | ||
248 | {"ACIN", NULL, "ACOP"}, | ||
249 | |||
261 | /* Connections to the amp */ | 250 | /* Connections to the amp */ |
262 | {"Stereo Out", NULL, "LOUT1"}, | 251 | {"Stereo Out", NULL, "LOUT1"}, |
263 | {"Stereo Out", NULL, "ROUT1"}, | 252 | {"Stereo Out", NULL, "ROUT1"}, |
@@ -267,7 +256,11 @@ static const struct snd_soc_dapm_route neo1973_gta02_routes[] = { | |||
267 | {"Handset Spk", NULL, "ROUT2"}, | 256 | {"Handset Spk", NULL, "ROUT2"}, |
268 | }; | 257 | }; |
269 | 258 | ||
270 | static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = { | 259 | static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { |
260 | SOC_DAPM_PIN_SWITCH("GSM Line Out"), | ||
261 | SOC_DAPM_PIN_SWITCH("GSM Line In"), | ||
262 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
263 | SOC_DAPM_PIN_SWITCH("Handset Mic"), | ||
271 | SOC_DAPM_PIN_SWITCH("Handset Spk"), | 264 | SOC_DAPM_PIN_SWITCH("Handset Spk"), |
272 | SOC_DAPM_PIN_SWITCH("Stereo Out"), | 265 | SOC_DAPM_PIN_SWITCH("Stereo Out"), |
273 | 266 | ||
@@ -276,86 +269,32 @@ static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = { | |||
276 | lm4853_set_spk), | 269 | lm4853_set_spk), |
277 | }; | 270 | }; |
278 | 271 | ||
279 | static const struct snd_soc_dapm_widget neo1973_gta02_wm8753_dapm_widgets[] = { | ||
280 | SND_SOC_DAPM_SPK("Handset Spk", NULL), | ||
281 | SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), | ||
282 | }; | ||
283 | |||
284 | static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) | ||
285 | { | ||
286 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
287 | int ret; | ||
288 | |||
289 | ret = snd_soc_dapm_new_controls(dapm, neo1973_gta02_wm8753_dapm_widgets, | ||
290 | ARRAY_SIZE(neo1973_gta02_wm8753_dapm_widgets)); | ||
291 | if (ret) | ||
292 | return ret; | ||
293 | |||
294 | ret = snd_soc_dapm_add_routes(dapm, neo1973_gta02_routes, | ||
295 | ARRAY_SIZE(neo1973_gta02_routes)); | ||
296 | if (ret) | ||
297 | return ret; | ||
298 | |||
299 | ret = snd_soc_add_card_controls(codec->card, neo1973_gta02_wm8753_controls, | ||
300 | ARRAY_SIZE(neo1973_gta02_wm8753_controls)); | ||
301 | if (ret) | ||
302 | return ret; | ||
303 | |||
304 | snd_soc_dapm_disable_pin(dapm, "Stereo Out"); | ||
305 | snd_soc_dapm_disable_pin(dapm, "Handset Spk"); | ||
306 | snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); | ||
307 | snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) | 272 | static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) |
313 | { | 273 | { |
314 | struct snd_soc_codec *codec = rtd->codec; | 274 | struct snd_soc_codec *codec = rtd->codec; |
315 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 275 | struct snd_soc_card *card = rtd->card; |
316 | int ret; | ||
317 | 276 | ||
318 | /* set up NC codec pins */ | 277 | /* set up NC codec pins */ |
319 | snd_soc_dapm_nc_pin(dapm, "OUT3"); | 278 | snd_soc_dapm_nc_pin(&codec->dapm, "OUT3"); |
320 | snd_soc_dapm_nc_pin(dapm, "OUT4"); | 279 | snd_soc_dapm_nc_pin(&codec->dapm, "OUT4"); |
321 | snd_soc_dapm_nc_pin(dapm, "LINE1"); | 280 | snd_soc_dapm_nc_pin(&codec->dapm, "LINE1"); |
322 | snd_soc_dapm_nc_pin(dapm, "LINE2"); | 281 | snd_soc_dapm_nc_pin(&codec->dapm, "LINE2"); |
323 | |||
324 | /* Add neo1973 specific widgets */ | ||
325 | ret = snd_soc_dapm_new_controls(dapm, neo1973_wm8753_dapm_widgets, | ||
326 | ARRAY_SIZE(neo1973_wm8753_dapm_widgets)); | ||
327 | if (ret) | ||
328 | return ret; | ||
329 | |||
330 | /* add neo1973 specific controls */ | ||
331 | ret = snd_soc_add_card_controls(rtd->card, neo1973_wm8753_controls, | ||
332 | ARRAY_SIZE(neo1973_wm8753_controls)); | ||
333 | if (ret) | ||
334 | return ret; | ||
335 | |||
336 | /* set up neo1973 specific audio routes */ | ||
337 | ret = snd_soc_dapm_add_routes(dapm, neo1973_wm8753_routes, | ||
338 | ARRAY_SIZE(neo1973_wm8753_routes)); | ||
339 | if (ret) | ||
340 | return ret; | ||
341 | 282 | ||
342 | /* set endpoints to default off mode */ | 283 | /* set endpoints to default off mode */ |
343 | snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); | 284 | snd_soc_dapm_disable_pin(&card->dapm, "GSM Line Out"); |
344 | snd_soc_dapm_disable_pin(dapm, "GSM Line In"); | 285 | snd_soc_dapm_disable_pin(&card->dapm, "GSM Line In"); |
345 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | 286 | snd_soc_dapm_disable_pin(&card->dapm, "Headset Mic"); |
346 | snd_soc_dapm_disable_pin(dapm, "Handset Mic"); | 287 | snd_soc_dapm_disable_pin(&card->dapm, "Handset Mic"); |
288 | snd_soc_dapm_disable_pin(&card->dapm, "Stereo Out"); | ||
289 | snd_soc_dapm_disable_pin(&card->dapm, "Handset Spk"); | ||
347 | 290 | ||
348 | /* allow audio paths from the GSM modem to run during suspend */ | 291 | /* allow audio paths from the GSM modem to run during suspend */ |
349 | snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out"); | 292 | snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line Out"); |
350 | snd_soc_dapm_ignore_suspend(dapm, "GSM Line In"); | 293 | snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line In"); |
351 | snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); | 294 | snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic"); |
352 | snd_soc_dapm_ignore_suspend(dapm, "Handset Mic"); | 295 | snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Mic"); |
353 | 296 | snd_soc_dapm_ignore_suspend(&card->dapm, "Stereo Out"); | |
354 | if (machine_is_neo1973_gta02()) { | 297 | snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Spk"); |
355 | ret = neo1973_gta02_wm8753_init(codec); | ||
356 | if (ret) | ||
357 | return ret; | ||
358 | } | ||
359 | 298 | ||
360 | return 0; | 299 | return 0; |
361 | } | 300 | } |
@@ -409,6 +348,13 @@ static struct snd_soc_card neo1973 = { | |||
409 | .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs), | 348 | .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs), |
410 | .codec_conf = neo1973_codec_conf, | 349 | .codec_conf = neo1973_codec_conf, |
411 | .num_configs = ARRAY_SIZE(neo1973_codec_conf), | 350 | .num_configs = ARRAY_SIZE(neo1973_codec_conf), |
351 | |||
352 | .controls = neo1973_wm8753_controls, | ||
353 | .num_controls = ARRAY_SIZE(neo1973_wm8753_controls), | ||
354 | .dapm_widgets = neo1973_wm8753_dapm_widgets, | ||
355 | .num_dapm_widgets = ARRAY_SIZE(neo1973_wm8753_dapm_widgets), | ||
356 | .dapm_routes = neo1973_wm8753_routes, | ||
357 | .num_dapm_routes = ARRAY_SIZE(neo1973_wm8753_routes), | ||
412 | }; | 358 | }; |
413 | 359 | ||
414 | static struct platform_device *neo1973_snd_device; | 360 | static struct platform_device *neo1973_snd_device; |
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index 06ebdc061770..2982d9e7f268 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c | |||
@@ -131,10 +131,6 @@ static int rx1950_startup(struct snd_pcm_substream *substream) | |||
131 | { | 131 | { |
132 | struct snd_pcm_runtime *runtime = substream->runtime; | 132 | struct snd_pcm_runtime *runtime = substream->runtime; |
133 | 133 | ||
134 | runtime->hw.rate_min = hw_rates.list[0]; | ||
135 | runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; | ||
136 | runtime->hw.rates = SNDRV_PCM_RATE_KNOT; | ||
137 | |||
138 | return snd_pcm_hw_constraint_list(runtime, 0, | 134 | return snd_pcm_hw_constraint_list(runtime, 0, |
139 | SNDRV_PCM_HW_PARAM_RATE, | 135 | SNDRV_PCM_HW_PARAM_RATE, |
140 | &hw_rates); | 136 | &hw_rates); |
@@ -226,7 +222,6 @@ static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd) | |||
226 | { | 222 | { |
227 | struct snd_soc_codec *codec = rtd->codec; | 223 | struct snd_soc_codec *codec = rtd->codec; |
228 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 224 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
229 | int err; | ||
230 | 225 | ||
231 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | 226 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); |
232 | snd_soc_dapm_enable_pin(dapm, "Speaker"); | 227 | snd_soc_dapm_enable_pin(dapm, "Speaker"); |
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index d38ae98e2f32..682eb4f7ba0c 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c | |||
@@ -202,7 +202,7 @@ static int smdk_audio_probe(struct platform_device *pdev) | |||
202 | 202 | ||
203 | static struct platform_driver smdk_audio_driver = { | 203 | static struct platform_driver smdk_audio_driver = { |
204 | .driver = { | 204 | .driver = { |
205 | .name = "smdk-audio-wm8894", | 205 | .name = "smdk-audio-wm8994", |
206 | .owner = THIS_MODULE, | 206 | .owner = THIS_MODULE, |
207 | .of_match_table = of_match_ptr(samsung_wm8994_of_match), | 207 | .of_match_table = of_match_ptr(samsung_wm8994_of_match), |
208 | .pm = &snd_soc_pm_ops, | 208 | .pm = &snd_soc_pm_ops, |
diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c index f21ff608a819..1807b75ccc12 100644 --- a/sound/soc/samsung/tobermory.c +++ b/sound/soc/samsung/tobermory.c | |||
@@ -44,6 +44,8 @@ static int tobermory_set_bias_level(struct snd_soc_card *card, | |||
44 | SND_SOC_CLOCK_IN); | 44 | SND_SOC_CLOCK_IN); |
45 | if (ret < 0) { | 45 | if (ret < 0) { |
46 | pr_err("Failed to set SYSCLK: %d\n", ret); | 46 | pr_err("Failed to set SYSCLK: %d\n", ret); |
47 | snd_soc_dai_set_pll(codec_dai, WM8962_FLL, | ||
48 | 0, 0, 0); | ||
47 | return ret; | 49 | return ret; |
48 | } | 50 | } |
49 | } | 51 | } |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 1967f44e7cd4..710a079a7377 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -1711,9 +1711,9 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
1711 | /* set master/slave audio interface */ | 1711 | /* set master/slave audio interface */ |
1712 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 1712 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
1713 | case SND_SOC_DAIFMT_CBM_CFM: | 1713 | case SND_SOC_DAIFMT_CBM_CFM: |
1714 | fsi->clk_master = 1; | ||
1715 | break; | 1714 | break; |
1716 | case SND_SOC_DAIFMT_CBS_CFS: | 1715 | case SND_SOC_DAIFMT_CBS_CFS: |
1716 | fsi->clk_master = 1; /* codec is slave, cpu is master */ | ||
1717 | break; | 1717 | break; |
1718 | default: | 1718 | default: |
1719 | return -EINVAL; | 1719 | return -EINVAL; |
diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index 5014a884afee..c58c2529f103 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c | |||
@@ -136,19 +136,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
136 | { "Mic Bias", NULL, "External Microphone" }, | 136 | { "Mic Bias", NULL, "External Microphone" }, |
137 | }; | 137 | }; |
138 | 138 | ||
139 | static int migor_dai_init(struct snd_soc_pcm_runtime *rtd) | ||
140 | { | ||
141 | struct snd_soc_codec *codec = rtd->codec; | ||
142 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
143 | |||
144 | snd_soc_dapm_new_controls(dapm, migor_dapm_widgets, | ||
145 | ARRAY_SIZE(migor_dapm_widgets)); | ||
146 | |||
147 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | /* migor digital audio interface glue - connects codec <--> CPU */ | 139 | /* migor digital audio interface glue - connects codec <--> CPU */ |
153 | static struct snd_soc_dai_link migor_dai = { | 140 | static struct snd_soc_dai_link migor_dai = { |
154 | .name = "wm8978", | 141 | .name = "wm8978", |
@@ -158,7 +145,6 @@ static struct snd_soc_dai_link migor_dai = { | |||
158 | .platform_name = "siu-pcm-audio", | 145 | .platform_name = "siu-pcm-audio", |
159 | .codec_name = "wm8978.0-001a", | 146 | .codec_name = "wm8978.0-001a", |
160 | .ops = &migor_dai_ops, | 147 | .ops = &migor_dai_ops, |
161 | .init = migor_dai_init, | ||
162 | }; | 148 | }; |
163 | 149 | ||
164 | /* migor audio machine driver */ | 150 | /* migor audio machine driver */ |
@@ -167,6 +153,11 @@ static struct snd_soc_card snd_soc_migor = { | |||
167 | .owner = THIS_MODULE, | 153 | .owner = THIS_MODULE, |
168 | .dai_link = &migor_dai, | 154 | .dai_link = &migor_dai, |
169 | .num_links = 1, | 155 | .num_links = 1, |
156 | |||
157 | .dapm_widgets = migor_dapm_widgets, | ||
158 | .num_dapm_widgets = ARRAY_SIZE(migor_dapm_widgets), | ||
159 | .dapm_routes = audio_map, | ||
160 | .num_dapm_routes = ARRAY_SIZE(audio_map), | ||
170 | }; | 161 | }; |
171 | 162 | ||
172 | static struct platform_device *migor_snd_device; | 163 | static struct platform_device *migor_snd_device; |
diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile index 0ff492df7929..7d0051ced838 100644 --- a/sound/soc/sh/rcar/Makefile +++ b/sound/soc/sh/rcar/Makefile | |||
@@ -1,2 +1,2 @@ | |||
1 | snd-soc-rcar-objs := core.o gen.o scu.o adg.o ssi.o | 1 | snd-soc-rcar-objs := core.o gen.o src.o adg.o ssi.o |
2 | obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o \ No newline at end of file | 2 | obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o \ No newline at end of file |
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index a53235c4d1b0..953f1cce982d 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c | |||
@@ -25,15 +25,165 @@ struct rsnd_adg { | |||
25 | }; | 25 | }; |
26 | 26 | ||
27 | #define for_each_rsnd_clk(pos, adg, i) \ | 27 | #define for_each_rsnd_clk(pos, adg, i) \ |
28 | for (i = 0, (pos) = adg->clk[i]; \ | 28 | for (i = 0; \ |
29 | i < CLKMAX; \ | 29 | (i < CLKMAX) && \ |
30 | i++, (pos) = adg->clk[i]) | 30 | ((pos) = adg->clk[i]); \ |
31 | i++) | ||
31 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) | 32 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) |
32 | 33 | ||
33 | static int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, | 34 | |
34 | struct rsnd_mod *mod, | 35 | static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io) |
35 | unsigned int src_rate, | 36 | { |
36 | unsigned int dst_rate) | 37 | struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io); |
38 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
39 | int id = rsnd_mod_id(mod); | ||
40 | int ws = id; | ||
41 | |||
42 | if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) { | ||
43 | switch (id) { | ||
44 | case 1: | ||
45 | case 2: | ||
46 | ws = 0; | ||
47 | break; | ||
48 | case 4: | ||
49 | ws = 3; | ||
50 | break; | ||
51 | case 8: | ||
52 | ws = 7; | ||
53 | break; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | return (0x6 + ws) << 8; | ||
58 | } | ||
59 | |||
60 | static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, | ||
61 | struct rsnd_mod *mod, | ||
62 | struct rsnd_dai_stream *io, | ||
63 | u32 timsel) | ||
64 | { | ||
65 | int is_play = rsnd_dai_is_play(rdai, io); | ||
66 | int id = rsnd_mod_id(mod); | ||
67 | int shift = (id % 2) ? 16 : 0; | ||
68 | u32 mask, ws; | ||
69 | u32 in, out; | ||
70 | |||
71 | ws = rsnd_adg_ssi_ws_timing_gen2(io); | ||
72 | |||
73 | in = (is_play) ? timsel : ws; | ||
74 | out = (is_play) ? ws : timsel; | ||
75 | |||
76 | in = in << shift; | ||
77 | out = out << shift; | ||
78 | mask = 0xffff << shift; | ||
79 | |||
80 | switch (id / 2) { | ||
81 | case 0: | ||
82 | rsnd_mod_bset(mod, SRCIN_TIMSEL0, mask, in); | ||
83 | rsnd_mod_bset(mod, SRCOUT_TIMSEL0, mask, out); | ||
84 | break; | ||
85 | case 1: | ||
86 | rsnd_mod_bset(mod, SRCIN_TIMSEL1, mask, in); | ||
87 | rsnd_mod_bset(mod, SRCOUT_TIMSEL1, mask, out); | ||
88 | break; | ||
89 | case 2: | ||
90 | rsnd_mod_bset(mod, SRCIN_TIMSEL2, mask, in); | ||
91 | rsnd_mod_bset(mod, SRCOUT_TIMSEL2, mask, out); | ||
92 | break; | ||
93 | case 3: | ||
94 | rsnd_mod_bset(mod, SRCIN_TIMSEL3, mask, in); | ||
95 | rsnd_mod_bset(mod, SRCOUT_TIMSEL3, mask, out); | ||
96 | break; | ||
97 | case 4: | ||
98 | rsnd_mod_bset(mod, SRCIN_TIMSEL4, mask, in); | ||
99 | rsnd_mod_bset(mod, SRCOUT_TIMSEL4, mask, out); | ||
100 | break; | ||
101 | } | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, | ||
107 | struct rsnd_dai *rdai, | ||
108 | struct rsnd_dai_stream *io, | ||
109 | unsigned int src_rate, | ||
110 | unsigned int dst_rate) | ||
111 | { | ||
112 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
113 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); | ||
114 | struct device *dev = rsnd_priv_to_dev(priv); | ||
115 | int idx, sel, div, step, ret; | ||
116 | u32 val, en; | ||
117 | unsigned int min, diff; | ||
118 | unsigned int sel_rate [] = { | ||
119 | clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ | ||
120 | clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */ | ||
121 | clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */ | ||
122 | adg->rbga_rate_for_441khz_div_6,/* 0011: RBGA */ | ||
123 | adg->rbgb_rate_for_48khz_div_6, /* 0100: RBGB */ | ||
124 | }; | ||
125 | |||
126 | min = ~0; | ||
127 | val = 0; | ||
128 | en = 0; | ||
129 | for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { | ||
130 | idx = 0; | ||
131 | step = 2; | ||
132 | |||
133 | if (!sel_rate[sel]) | ||
134 | continue; | ||
135 | |||
136 | for (div = 2; div <= 98304; div += step) { | ||
137 | diff = abs(src_rate - sel_rate[sel] / div); | ||
138 | if (min > diff) { | ||
139 | val = (sel << 8) | idx; | ||
140 | min = diff; | ||
141 | en = 1 << (sel + 1); /* fixme */ | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * step of 0_0000 / 0_0001 / 0_1101 | ||
146 | * are out of order | ||
147 | */ | ||
148 | if ((idx > 2) && (idx % 2)) | ||
149 | step *= 2; | ||
150 | if (idx == 0x1c) { | ||
151 | div += step; | ||
152 | step *= 2; | ||
153 | } | ||
154 | idx++; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | if (min == ~0) { | ||
159 | dev_err(dev, "no Input clock\n"); | ||
160 | return -EIO; | ||
161 | } | ||
162 | |||
163 | ret = rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); | ||
164 | if (ret < 0) { | ||
165 | dev_err(dev, "timsel error\n"); | ||
166 | return ret; | ||
167 | } | ||
168 | |||
169 | rsnd_mod_bset(mod, DIV_EN, en, en); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, | ||
175 | struct rsnd_dai *rdai, | ||
176 | struct rsnd_dai_stream *io) | ||
177 | { | ||
178 | u32 val = rsnd_adg_ssi_ws_timing_gen2(io); | ||
179 | |||
180 | return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); | ||
181 | } | ||
182 | |||
183 | int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, | ||
184 | struct rsnd_mod *mod, | ||
185 | unsigned int src_rate, | ||
186 | unsigned int dst_rate) | ||
37 | { | 187 | { |
38 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); | 188 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); |
39 | struct device *dev = rsnd_priv_to_dev(priv); | 189 | struct device *dev = rsnd_priv_to_dev(priv); |
@@ -91,18 +241,6 @@ find_rate: | |||
91 | return 0; | 241 | return 0; |
92 | } | 242 | } |
93 | 243 | ||
94 | int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, | ||
95 | struct rsnd_mod *mod, | ||
96 | unsigned int src_rate, | ||
97 | unsigned int dst_rate) | ||
98 | { | ||
99 | if (rsnd_is_gen1(priv)) | ||
100 | return rsnd_adg_set_convert_clk_gen1(priv, mod, | ||
101 | src_rate, dst_rate); | ||
102 | |||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val) | 244 | static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val) |
107 | { | 245 | { |
108 | int id = rsnd_mod_id(mod); | 246 | int id = rsnd_mod_id(mod); |
@@ -254,13 +392,13 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) | |||
254 | } | 392 | } |
255 | 393 | ||
256 | int rsnd_adg_probe(struct platform_device *pdev, | 394 | int rsnd_adg_probe(struct platform_device *pdev, |
257 | struct rcar_snd_info *info, | ||
258 | struct rsnd_priv *priv) | 395 | struct rsnd_priv *priv) |
259 | { | 396 | { |
260 | struct rsnd_adg *adg; | 397 | struct rsnd_adg *adg; |
261 | struct device *dev = rsnd_priv_to_dev(priv); | 398 | struct device *dev = rsnd_priv_to_dev(priv); |
262 | struct clk *clk; | 399 | struct clk *clk, *clk_orig; |
263 | int i; | 400 | int i; |
401 | bool use_old_style = false; | ||
264 | 402 | ||
265 | adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); | 403 | adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); |
266 | if (!adg) { | 404 | if (!adg) { |
@@ -268,10 +406,39 @@ int rsnd_adg_probe(struct platform_device *pdev, | |||
268 | return -ENOMEM; | 406 | return -ENOMEM; |
269 | } | 407 | } |
270 | 408 | ||
271 | adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); | 409 | clk_orig = devm_clk_get(dev, NULL); |
272 | adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); | 410 | adg->clk[CLKA] = devm_clk_get(dev, "clk_a"); |
273 | adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); | 411 | adg->clk[CLKB] = devm_clk_get(dev, "clk_b"); |
274 | adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); | 412 | adg->clk[CLKC] = devm_clk_get(dev, "clk_c"); |
413 | adg->clk[CLKI] = devm_clk_get(dev, "clk_i"); | ||
414 | |||
415 | /* | ||
416 | * It request device dependent audio clock. | ||
417 | * But above all clks will indicate rsnd module clock | ||
418 | * if platform doesn't it | ||
419 | */ | ||
420 | for_each_rsnd_clk(clk, adg, i) { | ||
421 | if (clk_orig == clk) { | ||
422 | dev_warn(dev, | ||
423 | "doesn't have device dependent clock, use independent clock\n"); | ||
424 | use_old_style = true; | ||
425 | break; | ||
426 | } | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | * note: | ||
431 | * these exist in order to keep compatible with | ||
432 | * platform which has device independent audio clock, | ||
433 | * but will be removed soon | ||
434 | */ | ||
435 | if (use_old_style) { | ||
436 | adg->clk[CLKA] = devm_clk_get(NULL, "audio_clk_a"); | ||
437 | adg->clk[CLKB] = devm_clk_get(NULL, "audio_clk_b"); | ||
438 | adg->clk[CLKC] = devm_clk_get(NULL, "audio_clk_c"); | ||
439 | adg->clk[CLKI] = devm_clk_get(NULL, "audio_clk_internal"); | ||
440 | } | ||
441 | |||
275 | for_each_rsnd_clk(clk, adg, i) { | 442 | for_each_rsnd_clk(clk, adg, i) { |
276 | if (IS_ERR(clk)) { | 443 | if (IS_ERR(clk)) { |
277 | dev_err(dev, "Audio clock failed\n"); | 444 | dev_err(dev, "Audio clock failed\n"); |
@@ -287,14 +454,3 @@ int rsnd_adg_probe(struct platform_device *pdev, | |||
287 | 454 | ||
288 | return 0; | 455 | return 0; |
289 | } | 456 | } |
290 | |||
291 | void rsnd_adg_remove(struct platform_device *pdev, | ||
292 | struct rsnd_priv *priv) | ||
293 | { | ||
294 | struct rsnd_adg *adg = priv->adg; | ||
295 | struct clk *clk; | ||
296 | int i; | ||
297 | |||
298 | for_each_rsnd_clk(clk, adg, i) | ||
299 | clk_put(clk); | ||
300 | } | ||
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 743de5e3b1e1..d836e8a9fdce 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -73,13 +73,13 @@ | |||
73 | * | +- ssi[2] | 73 | * | +- ssi[2] |
74 | * | ... | 74 | * | ... |
75 | * | | 75 | * | |
76 | * | ** these control scu | 76 | * | ** these control src |
77 | * | | 77 | * | |
78 | * +- scu | 78 | * +- src |
79 | * | | 79 | * | |
80 | * +- scu[0] | 80 | * +- src[0] |
81 | * +- scu[1] | 81 | * +- src[1] |
82 | * +- scu[2] | 82 | * +- src[2] |
83 | * ... | 83 | * ... |
84 | * | 84 | * |
85 | * | 85 | * |
@@ -107,6 +107,11 @@ | |||
107 | (!(priv->info->func) ? 0 : \ | 107 | (!(priv->info->func) ? 0 : \ |
108 | priv->info->func(param)) | 108 | priv->info->func(param)) |
109 | 109 | ||
110 | #define rsnd_is_enable_path(io, name) \ | ||
111 | ((io)->info ? (io)->info->name : NULL) | ||
112 | #define rsnd_info_id(priv, io, name) \ | ||
113 | ((io)->info->name - priv->info->name##_info) | ||
114 | |||
110 | /* | 115 | /* |
111 | * rsnd_mod functions | 116 | * rsnd_mod functions |
112 | */ | 117 | */ |
@@ -121,17 +126,19 @@ char *rsnd_mod_name(struct rsnd_mod *mod) | |||
121 | void rsnd_mod_init(struct rsnd_priv *priv, | 126 | void rsnd_mod_init(struct rsnd_priv *priv, |
122 | struct rsnd_mod *mod, | 127 | struct rsnd_mod *mod, |
123 | struct rsnd_mod_ops *ops, | 128 | struct rsnd_mod_ops *ops, |
129 | enum rsnd_mod_type type, | ||
124 | int id) | 130 | int id) |
125 | { | 131 | { |
126 | mod->priv = priv; | 132 | mod->priv = priv; |
127 | mod->id = id; | 133 | mod->id = id; |
128 | mod->ops = ops; | 134 | mod->ops = ops; |
129 | INIT_LIST_HEAD(&mod->list); | 135 | mod->type = type; |
130 | } | 136 | } |
131 | 137 | ||
132 | /* | 138 | /* |
133 | * rsnd_dma functions | 139 | * rsnd_dma functions |
134 | */ | 140 | */ |
141 | static void __rsnd_dma_start(struct rsnd_dma *dma); | ||
135 | static void rsnd_dma_continue(struct rsnd_dma *dma) | 142 | static void rsnd_dma_continue(struct rsnd_dma *dma) |
136 | { | 143 | { |
137 | /* push next A or B plane */ | 144 | /* push next A or B plane */ |
@@ -142,8 +149,9 @@ static void rsnd_dma_continue(struct rsnd_dma *dma) | |||
142 | void rsnd_dma_start(struct rsnd_dma *dma) | 149 | void rsnd_dma_start(struct rsnd_dma *dma) |
143 | { | 150 | { |
144 | /* push both A and B plane*/ | 151 | /* push both A and B plane*/ |
152 | dma->offset = 0; | ||
145 | dma->submit_loop = 2; | 153 | dma->submit_loop = 2; |
146 | schedule_work(&dma->work); | 154 | __rsnd_dma_start(dma); |
147 | } | 155 | } |
148 | 156 | ||
149 | void rsnd_dma_stop(struct rsnd_dma *dma) | 157 | void rsnd_dma_stop(struct rsnd_dma *dma) |
@@ -156,12 +164,26 @@ void rsnd_dma_stop(struct rsnd_dma *dma) | |||
156 | static void rsnd_dma_complete(void *data) | 164 | static void rsnd_dma_complete(void *data) |
157 | { | 165 | { |
158 | struct rsnd_dma *dma = (struct rsnd_dma *)data; | 166 | struct rsnd_dma *dma = (struct rsnd_dma *)data; |
159 | struct rsnd_priv *priv = dma->priv; | 167 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
168 | struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); | ||
169 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
160 | unsigned long flags; | 170 | unsigned long flags; |
161 | 171 | ||
162 | rsnd_lock(priv, flags); | 172 | rsnd_lock(priv, flags); |
163 | 173 | ||
164 | dma->complete(dma); | 174 | /* |
175 | * Renesas sound Gen1 needs 1 DMAC, | ||
176 | * Gen2 needs 2 DMAC. | ||
177 | * In Gen2 case, it are Audio-DMAC, and Audio-DMAC-peri-peri. | ||
178 | * But, Audio-DMAC-peri-peri doesn't have interrupt, | ||
179 | * and this driver is assuming that here. | ||
180 | * | ||
181 | * If Audio-DMAC-peri-peri has interrpt, | ||
182 | * rsnd_dai_pointer_update() will be called twice, | ||
183 | * ant it will breaks io->byte_pos | ||
184 | */ | ||
185 | |||
186 | rsnd_dai_pointer_update(io, io->byte_per_period); | ||
165 | 187 | ||
166 | if (dma->submit_loop) | 188 | if (dma->submit_loop) |
167 | rsnd_dma_continue(dma); | 189 | rsnd_dma_continue(dma); |
@@ -169,20 +191,23 @@ static void rsnd_dma_complete(void *data) | |||
169 | rsnd_unlock(priv, flags); | 191 | rsnd_unlock(priv, flags); |
170 | } | 192 | } |
171 | 193 | ||
172 | static void rsnd_dma_do_work(struct work_struct *work) | 194 | static void __rsnd_dma_start(struct rsnd_dma *dma) |
173 | { | 195 | { |
174 | struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); | 196 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
175 | struct rsnd_priv *priv = dma->priv; | 197 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
198 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
199 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
176 | struct device *dev = rsnd_priv_to_dev(priv); | 200 | struct device *dev = rsnd_priv_to_dev(priv); |
177 | struct dma_async_tx_descriptor *desc; | 201 | struct dma_async_tx_descriptor *desc; |
178 | dma_addr_t buf; | 202 | dma_addr_t buf; |
179 | size_t len; | 203 | size_t len = io->byte_per_period; |
180 | int i; | 204 | int i; |
181 | 205 | ||
182 | for (i = 0; i < dma->submit_loop; i++) { | 206 | for (i = 0; i < dma->submit_loop; i++) { |
183 | 207 | ||
184 | if (dma->inquiry(dma, &buf, &len) < 0) | 208 | buf = runtime->dma_addr + |
185 | return; | 209 | rsnd_dai_pointer_offset(io, dma->offset + len); |
210 | dma->offset = len; | ||
186 | 211 | ||
187 | desc = dmaengine_prep_slave_single( | 212 | desc = dmaengine_prep_slave_single( |
188 | dma->chan, buf, len, dma->dir, | 213 | dma->chan, buf, len, dma->dir, |
@@ -204,16 +229,20 @@ static void rsnd_dma_do_work(struct work_struct *work) | |||
204 | } | 229 | } |
205 | } | 230 | } |
206 | 231 | ||
232 | static void rsnd_dma_do_work(struct work_struct *work) | ||
233 | { | ||
234 | struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); | ||
235 | |||
236 | __rsnd_dma_start(dma); | ||
237 | } | ||
238 | |||
207 | int rsnd_dma_available(struct rsnd_dma *dma) | 239 | int rsnd_dma_available(struct rsnd_dma *dma) |
208 | { | 240 | { |
209 | return !!dma->chan; | 241 | return !!dma->chan; |
210 | } | 242 | } |
211 | 243 | ||
212 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | 244 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, |
213 | int is_play, int id, | 245 | int is_play, int id) |
214 | int (*inquiry)(struct rsnd_dma *dma, | ||
215 | dma_addr_t *buf, int *len), | ||
216 | int (*complete)(struct rsnd_dma *dma)) | ||
217 | { | 246 | { |
218 | struct device *dev = rsnd_priv_to_dev(priv); | 247 | struct device *dev = rsnd_priv_to_dev(priv); |
219 | struct dma_slave_config cfg; | 248 | struct dma_slave_config cfg; |
@@ -246,9 +275,6 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
246 | goto rsnd_dma_init_err; | 275 | goto rsnd_dma_init_err; |
247 | 276 | ||
248 | dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 277 | dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; |
249 | dma->priv = priv; | ||
250 | dma->inquiry = inquiry; | ||
251 | dma->complete = complete; | ||
252 | INIT_WORK(&dma->work, rsnd_dma_do_work); | 278 | INIT_WORK(&dma->work, rsnd_dma_do_work); |
253 | 279 | ||
254 | return 0; | 280 | return 0; |
@@ -271,26 +297,42 @@ void rsnd_dma_quit(struct rsnd_priv *priv, | |||
271 | /* | 297 | /* |
272 | * rsnd_dai functions | 298 | * rsnd_dai functions |
273 | */ | 299 | */ |
274 | #define rsnd_dai_call(rdai, io, fn) \ | 300 | #define __rsnd_mod_call(mod, func, rdai, io) \ |
275 | ({ \ | 301 | ({ \ |
276 | struct rsnd_mod *mod, *n; \ | 302 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ |
277 | int ret = 0; \ | 303 | struct device *dev = rsnd_priv_to_dev(priv); \ |
278 | for_each_rsnd_mod(mod, n, io) { \ | 304 | dev_dbg(dev, "%s [%d] %s\n", \ |
279 | ret = rsnd_mod_call(mod, fn, rdai, io); \ | 305 | rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ |
280 | if (ret < 0) \ | 306 | (mod)->ops->func(mod, rdai, io); \ |
281 | break; \ | ||
282 | } \ | ||
283 | ret; \ | ||
284 | }) | 307 | }) |
285 | 308 | ||
286 | int rsnd_dai_connect(struct rsnd_dai *rdai, | 309 | #define rsnd_mod_call(mod, func, rdai, io) \ |
287 | struct rsnd_mod *mod, | 310 | (!(mod) ? -ENODEV : \ |
288 | struct rsnd_dai_stream *io) | 311 | !((mod)->ops->func) ? 0 : \ |
312 | __rsnd_mod_call(mod, func, (rdai), (io))) | ||
313 | |||
314 | #define rsnd_dai_call(rdai, io, fn) \ | ||
315 | ({ \ | ||
316 | struct rsnd_mod *mod; \ | ||
317 | int ret = 0, i; \ | ||
318 | for (i = 0; i < RSND_MOD_MAX; i++) { \ | ||
319 | mod = (io)->mod[i]; \ | ||
320 | if (!mod) \ | ||
321 | continue; \ | ||
322 | ret = rsnd_mod_call(mod, fn, (rdai), (io)); \ | ||
323 | if (ret < 0) \ | ||
324 | break; \ | ||
325 | } \ | ||
326 | ret; \ | ||
327 | }) | ||
328 | |||
329 | static int rsnd_dai_connect(struct rsnd_mod *mod, | ||
330 | struct rsnd_dai_stream *io) | ||
289 | { | 331 | { |
290 | if (!mod) | 332 | if (!mod) |
291 | return -EIO; | 333 | return -EIO; |
292 | 334 | ||
293 | if (!list_empty(&mod->list)) { | 335 | if (io->mod[mod->type]) { |
294 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 336 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
295 | struct device *dev = rsnd_priv_to_dev(priv); | 337 | struct device *dev = rsnd_priv_to_dev(priv); |
296 | 338 | ||
@@ -300,14 +342,8 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, | |||
300 | return -EIO; | 342 | return -EIO; |
301 | } | 343 | } |
302 | 344 | ||
303 | list_add_tail(&mod->list, &io->head); | 345 | io->mod[mod->type] = mod; |
304 | 346 | mod->io = io; | |
305 | return 0; | ||
306 | } | ||
307 | |||
308 | int rsnd_dai_disconnect(struct rsnd_mod *mod) | ||
309 | { | ||
310 | list_del_init(&mod->list); | ||
311 | 347 | ||
312 | return 0; | 348 | return 0; |
313 | } | 349 | } |
@@ -316,7 +352,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) | |||
316 | { | 352 | { |
317 | int id = rdai - priv->rdai; | 353 | int id = rdai - priv->rdai; |
318 | 354 | ||
319 | if ((id < 0) || (id >= rsnd_dai_nr(priv))) | 355 | if ((id < 0) || (id >= rsnd_rdai_nr(priv))) |
320 | return -EINVAL; | 356 | return -EINVAL; |
321 | 357 | ||
322 | return id; | 358 | return id; |
@@ -324,7 +360,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) | |||
324 | 360 | ||
325 | struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id) | 361 | struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id) |
326 | { | 362 | { |
327 | if ((id < 0) || (id >= rsnd_dai_nr(priv))) | 363 | if ((id < 0) || (id >= rsnd_rdai_nr(priv))) |
328 | return NULL; | 364 | return NULL; |
329 | 365 | ||
330 | return priv->rdai + id; | 366 | return priv->rdai + id; |
@@ -382,10 +418,6 @@ static int rsnd_dai_stream_init(struct rsnd_dai_stream *io, | |||
382 | { | 418 | { |
383 | struct snd_pcm_runtime *runtime = substream->runtime; | 419 | struct snd_pcm_runtime *runtime = substream->runtime; |
384 | 420 | ||
385 | if (!list_empty(&io->head)) | ||
386 | return -EIO; | ||
387 | |||
388 | INIT_LIST_HEAD(&io->head); | ||
389 | io->substream = substream; | 421 | io->substream = substream; |
390 | io->byte_pos = 0; | 422 | io->byte_pos = 0; |
391 | io->period_pos = 0; | 423 | io->period_pos = 0; |
@@ -440,10 +472,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
440 | if (ret < 0) | 472 | if (ret < 0) |
441 | goto dai_trigger_end; | 473 | goto dai_trigger_end; |
442 | 474 | ||
443 | ret = rsnd_gen_path_init(priv, rdai, io); | ||
444 | if (ret < 0) | ||
445 | goto dai_trigger_end; | ||
446 | |||
447 | ret = rsnd_dai_call(rdai, io, init); | 475 | ret = rsnd_dai_call(rdai, io, init); |
448 | if (ret < 0) | 476 | if (ret < 0) |
449 | goto dai_trigger_end; | 477 | goto dai_trigger_end; |
@@ -461,10 +489,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
461 | if (ret < 0) | 489 | if (ret < 0) |
462 | goto dai_trigger_end; | 490 | goto dai_trigger_end; |
463 | 491 | ||
464 | ret = rsnd_gen_path_exit(priv, rdai, io); | ||
465 | if (ret < 0) | ||
466 | goto dai_trigger_end; | ||
467 | |||
468 | ret = rsnd_platform_call(priv, dai, stop, ssi_id); | 492 | ret = rsnd_platform_call(priv, dai, stop, ssi_id); |
469 | if (ret < 0) | 493 | if (ret < 0) |
470 | goto dai_trigger_end; | 494 | goto dai_trigger_end; |
@@ -486,10 +510,10 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
486 | /* set master/slave audio interface */ | 510 | /* set master/slave audio interface */ |
487 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 511 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
488 | case SND_SOC_DAIFMT_CBM_CFM: | 512 | case SND_SOC_DAIFMT_CBM_CFM: |
489 | rdai->clk_master = 1; | 513 | rdai->clk_master = 0; |
490 | break; | 514 | break; |
491 | case SND_SOC_DAIFMT_CBS_CFS: | 515 | case SND_SOC_DAIFMT_CBS_CFS: |
492 | rdai->clk_master = 0; | 516 | rdai->clk_master = 1; /* codec is slave, cpu is master */ |
493 | break; | 517 | break; |
494 | default: | 518 | default: |
495 | return -EINVAL; | 519 | return -EINVAL; |
@@ -540,24 +564,86 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { | |||
540 | .set_fmt = rsnd_soc_dai_set_fmt, | 564 | .set_fmt = rsnd_soc_dai_set_fmt, |
541 | }; | 565 | }; |
542 | 566 | ||
567 | static int rsnd_path_init(struct rsnd_priv *priv, | ||
568 | struct rsnd_dai *rdai, | ||
569 | struct rsnd_dai_stream *io) | ||
570 | { | ||
571 | struct rsnd_mod *mod; | ||
572 | struct rsnd_dai_platform_info *dai_info = rdai->info; | ||
573 | int ret; | ||
574 | int ssi_id = -1; | ||
575 | int src_id = -1; | ||
576 | |||
577 | /* | ||
578 | * Gen1 is created by SRU/SSI, and this SRU is base module of | ||
579 | * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU) | ||
580 | * | ||
581 | * Easy image is.. | ||
582 | * Gen1 SRU = Gen2 SCU + SSIU + etc | ||
583 | * | ||
584 | * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is | ||
585 | * using fixed path. | ||
586 | */ | ||
587 | if (dai_info) { | ||
588 | if (rsnd_is_enable_path(io, ssi)) | ||
589 | ssi_id = rsnd_info_id(priv, io, ssi); | ||
590 | if (rsnd_is_enable_path(io, src)) | ||
591 | src_id = rsnd_info_id(priv, io, src); | ||
592 | } else { | ||
593 | /* get SSI's ID */ | ||
594 | mod = rsnd_ssi_mod_get_frm_dai(priv, | ||
595 | rsnd_dai_id(priv, rdai), | ||
596 | rsnd_dai_is_play(rdai, io)); | ||
597 | if (!mod) | ||
598 | return 0; | ||
599 | ssi_id = src_id = rsnd_mod_id(mod); | ||
600 | } | ||
601 | |||
602 | ret = 0; | ||
603 | |||
604 | /* SRC */ | ||
605 | if (src_id >= 0) { | ||
606 | mod = rsnd_src_mod_get(priv, src_id); | ||
607 | ret = rsnd_dai_connect(mod, io); | ||
608 | if (ret < 0) | ||
609 | return ret; | ||
610 | } | ||
611 | |||
612 | /* SSI */ | ||
613 | if (ssi_id >= 0) { | ||
614 | mod = rsnd_ssi_mod_get(priv, ssi_id); | ||
615 | ret = rsnd_dai_connect(mod, io); | ||
616 | if (ret < 0) | ||
617 | return ret; | ||
618 | } | ||
619 | |||
620 | return ret; | ||
621 | } | ||
622 | |||
543 | static int rsnd_dai_probe(struct platform_device *pdev, | 623 | static int rsnd_dai_probe(struct platform_device *pdev, |
544 | struct rcar_snd_info *info, | ||
545 | struct rsnd_priv *priv) | 624 | struct rsnd_priv *priv) |
546 | { | 625 | { |
547 | struct snd_soc_dai_driver *drv; | 626 | struct snd_soc_dai_driver *drv; |
627 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
548 | struct rsnd_dai *rdai; | 628 | struct rsnd_dai *rdai; |
549 | struct rsnd_mod *pmod, *cmod; | 629 | struct rsnd_mod *pmod, *cmod; |
550 | struct device *dev = rsnd_priv_to_dev(priv); | 630 | struct device *dev = rsnd_priv_to_dev(priv); |
551 | int dai_nr; | 631 | int dai_nr = info->dai_info_nr; |
552 | int i; | 632 | int i; |
553 | 633 | ||
554 | /* get max dai nr */ | 634 | /* |
555 | for (dai_nr = 0; dai_nr < 32; dai_nr++) { | 635 | * dai_nr should be set via dai_info_nr, |
556 | pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1); | 636 | * but allow it to keeping compatible |
557 | cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0); | 637 | */ |
638 | if (!dai_nr) { | ||
639 | /* get max dai nr */ | ||
640 | for (dai_nr = 0; dai_nr < 32; dai_nr++) { | ||
641 | pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1); | ||
642 | cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0); | ||
558 | 643 | ||
559 | if (!pmod && !cmod) | 644 | if (!pmod && !cmod) |
560 | break; | 645 | break; |
646 | } | ||
561 | } | 647 | } |
562 | 648 | ||
563 | if (!dai_nr) { | 649 | if (!dai_nr) { |
@@ -572,7 +658,13 @@ static int rsnd_dai_probe(struct platform_device *pdev, | |||
572 | return -ENOMEM; | 658 | return -ENOMEM; |
573 | } | 659 | } |
574 | 660 | ||
661 | priv->rdai_nr = dai_nr; | ||
662 | priv->daidrv = drv; | ||
663 | priv->rdai = rdai; | ||
664 | |||
575 | for (i = 0; i < dai_nr; i++) { | 665 | for (i = 0; i < dai_nr; i++) { |
666 | if (info->dai_info) | ||
667 | rdai[i].info = &info->dai_info[i]; | ||
576 | 668 | ||
577 | pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1); | 669 | pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1); |
578 | cmod = rsnd_ssi_mod_get_frm_dai(priv, i, 0); | 670 | cmod = rsnd_ssi_mod_get_frm_dai(priv, i, 0); |
@@ -580,9 +672,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, | |||
580 | /* | 672 | /* |
581 | * init rsnd_dai | 673 | * init rsnd_dai |
582 | */ | 674 | */ |
583 | INIT_LIST_HEAD(&rdai[i].playback.head); | ||
584 | INIT_LIST_HEAD(&rdai[i].capture.head); | ||
585 | |||
586 | snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i); | 675 | snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i); |
587 | 676 | ||
588 | /* | 677 | /* |
@@ -595,12 +684,20 @@ static int rsnd_dai_probe(struct platform_device *pdev, | |||
595 | drv[i].playback.formats = RSND_FMTS; | 684 | drv[i].playback.formats = RSND_FMTS; |
596 | drv[i].playback.channels_min = 2; | 685 | drv[i].playback.channels_min = 2; |
597 | drv[i].playback.channels_max = 2; | 686 | drv[i].playback.channels_max = 2; |
687 | |||
688 | if (info->dai_info) | ||
689 | rdai[i].playback.info = &info->dai_info[i].playback; | ||
690 | rsnd_path_init(priv, &rdai[i], &rdai[i].playback); | ||
598 | } | 691 | } |
599 | if (cmod) { | 692 | if (cmod) { |
600 | drv[i].capture.rates = RSND_RATES; | 693 | drv[i].capture.rates = RSND_RATES; |
601 | drv[i].capture.formats = RSND_FMTS; | 694 | drv[i].capture.formats = RSND_FMTS; |
602 | drv[i].capture.channels_min = 2; | 695 | drv[i].capture.channels_min = 2; |
603 | drv[i].capture.channels_max = 2; | 696 | drv[i].capture.channels_max = 2; |
697 | |||
698 | if (info->dai_info) | ||
699 | rdai[i].capture.info = &info->dai_info[i].capture; | ||
700 | rsnd_path_init(priv, &rdai[i], &rdai[i].capture); | ||
604 | } | 701 | } |
605 | 702 | ||
606 | dev_dbg(dev, "%s (%s/%s)\n", rdai[i].name, | 703 | dev_dbg(dev, "%s (%s/%s)\n", rdai[i].name, |
@@ -608,18 +705,9 @@ static int rsnd_dai_probe(struct platform_device *pdev, | |||
608 | cmod ? "capture" : " -- "); | 705 | cmod ? "capture" : " -- "); |
609 | } | 706 | } |
610 | 707 | ||
611 | priv->dai_nr = dai_nr; | ||
612 | priv->daidrv = drv; | ||
613 | priv->rdai = rdai; | ||
614 | |||
615 | return 0; | 708 | return 0; |
616 | } | 709 | } |
617 | 710 | ||
618 | static void rsnd_dai_remove(struct platform_device *pdev, | ||
619 | struct rsnd_priv *priv) | ||
620 | { | ||
621 | } | ||
622 | |||
623 | /* | 711 | /* |
624 | * pcm ops | 712 | * pcm ops |
625 | */ | 713 | */ |
@@ -713,7 +801,16 @@ static int rsnd_probe(struct platform_device *pdev) | |||
713 | struct rcar_snd_info *info; | 801 | struct rcar_snd_info *info; |
714 | struct rsnd_priv *priv; | 802 | struct rsnd_priv *priv; |
715 | struct device *dev = &pdev->dev; | 803 | struct device *dev = &pdev->dev; |
716 | int ret; | 804 | struct rsnd_dai *rdai; |
805 | int (*probe_func[])(struct platform_device *pdev, | ||
806 | struct rsnd_priv *priv) = { | ||
807 | rsnd_gen_probe, | ||
808 | rsnd_ssi_probe, | ||
809 | rsnd_src_probe, | ||
810 | rsnd_adg_probe, | ||
811 | rsnd_dai_probe, | ||
812 | }; | ||
813 | int ret, i; | ||
717 | 814 | ||
718 | info = pdev->dev.platform_data; | 815 | info = pdev->dev.platform_data; |
719 | if (!info) { | 816 | if (!info) { |
@@ -737,25 +834,21 @@ static int rsnd_probe(struct platform_device *pdev) | |||
737 | /* | 834 | /* |
738 | * init each module | 835 | * init each module |
739 | */ | 836 | */ |
740 | ret = rsnd_gen_probe(pdev, info, priv); | 837 | for (i = 0; i < ARRAY_SIZE(probe_func); i++) { |
741 | if (ret < 0) | 838 | ret = probe_func[i](pdev, priv); |
742 | return ret; | 839 | if (ret) |
743 | 840 | return ret; | |
744 | ret = rsnd_scu_probe(pdev, info, priv); | 841 | } |
745 | if (ret < 0) | ||
746 | return ret; | ||
747 | 842 | ||
748 | ret = rsnd_adg_probe(pdev, info, priv); | 843 | for_each_rsnd_dai(rdai, priv, i) { |
749 | if (ret < 0) | 844 | ret = rsnd_dai_call(rdai, &rdai->playback, probe); |
750 | return ret; | 845 | if (ret) |
846 | return ret; | ||
751 | 847 | ||
752 | ret = rsnd_ssi_probe(pdev, info, priv); | 848 | ret = rsnd_dai_call(rdai, &rdai->capture, probe); |
753 | if (ret < 0) | 849 | if (ret) |
754 | return ret; | 850 | return ret; |
755 | 851 | } | |
756 | ret = rsnd_dai_probe(pdev, info, priv); | ||
757 | if (ret < 0) | ||
758 | return ret; | ||
759 | 852 | ||
760 | /* | 853 | /* |
761 | * asoc register | 854 | * asoc register |
@@ -767,7 +860,7 @@ static int rsnd_probe(struct platform_device *pdev) | |||
767 | } | 860 | } |
768 | 861 | ||
769 | ret = snd_soc_register_component(dev, &rsnd_soc_component, | 862 | ret = snd_soc_register_component(dev, &rsnd_soc_component, |
770 | priv->daidrv, rsnd_dai_nr(priv)); | 863 | priv->daidrv, rsnd_rdai_nr(priv)); |
771 | if (ret < 0) { | 864 | if (ret < 0) { |
772 | dev_err(dev, "cannot snd dai register\n"); | 865 | dev_err(dev, "cannot snd dai register\n"); |
773 | goto exit_snd_soc; | 866 | goto exit_snd_soc; |
@@ -789,17 +882,20 @@ exit_snd_soc: | |||
789 | static int rsnd_remove(struct platform_device *pdev) | 882 | static int rsnd_remove(struct platform_device *pdev) |
790 | { | 883 | { |
791 | struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); | 884 | struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); |
885 | struct rsnd_dai *rdai; | ||
886 | int ret, i; | ||
792 | 887 | ||
793 | pm_runtime_disable(&pdev->dev); | 888 | pm_runtime_disable(&pdev->dev); |
794 | 889 | ||
795 | /* | 890 | for_each_rsnd_dai(rdai, priv, i) { |
796 | * remove each module | 891 | ret = rsnd_dai_call(rdai, &rdai->playback, remove); |
797 | */ | 892 | if (ret) |
798 | rsnd_ssi_remove(pdev, priv); | 893 | return ret; |
799 | rsnd_adg_remove(pdev, priv); | 894 | |
800 | rsnd_scu_remove(pdev, priv); | 895 | ret = rsnd_dai_call(rdai, &rdai->capture, remove); |
801 | rsnd_dai_remove(pdev, priv); | 896 | if (ret) |
802 | rsnd_gen_remove(pdev, priv); | 897 | return ret; |
898 | } | ||
803 | 899 | ||
804 | return 0; | 900 | return 0; |
805 | } | 901 | } |
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index add088bd4b2a..9094970dbdfb 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c | |||
@@ -155,62 +155,6 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, | |||
155 | return 0; | 155 | return 0; |
156 | } | 156 | } |
157 | 157 | ||
158 | int rsnd_gen_path_init(struct rsnd_priv *priv, | ||
159 | struct rsnd_dai *rdai, | ||
160 | struct rsnd_dai_stream *io) | ||
161 | { | ||
162 | struct rsnd_mod *mod; | ||
163 | int ret; | ||
164 | int id; | ||
165 | |||
166 | /* | ||
167 | * Gen1 is created by SRU/SSI, and this SRU is base module of | ||
168 | * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU) | ||
169 | * | ||
170 | * Easy image is.. | ||
171 | * Gen1 SRU = Gen2 SCU + SSIU + etc | ||
172 | * | ||
173 | * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is | ||
174 | * using fixed path. | ||
175 | * | ||
176 | * Then, SSI id = SCU id here | ||
177 | */ | ||
178 | |||
179 | /* get SSI's ID */ | ||
180 | mod = rsnd_ssi_mod_get_frm_dai(priv, | ||
181 | rsnd_dai_id(priv, rdai), | ||
182 | rsnd_dai_is_play(rdai, io)); | ||
183 | id = rsnd_mod_id(mod); | ||
184 | |||
185 | /* SSI */ | ||
186 | mod = rsnd_ssi_mod_get(priv, id); | ||
187 | ret = rsnd_dai_connect(rdai, mod, io); | ||
188 | if (ret < 0) | ||
189 | return ret; | ||
190 | |||
191 | /* SCU */ | ||
192 | mod = rsnd_scu_mod_get(priv, id); | ||
193 | ret = rsnd_dai_connect(rdai, mod, io); | ||
194 | |||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | int rsnd_gen_path_exit(struct rsnd_priv *priv, | ||
199 | struct rsnd_dai *rdai, | ||
200 | struct rsnd_dai_stream *io) | ||
201 | { | ||
202 | struct rsnd_mod *mod, *n; | ||
203 | int ret = 0; | ||
204 | |||
205 | /* | ||
206 | * remove all mod from rdai | ||
207 | */ | ||
208 | for_each_rsnd_mod(mod, n, io) | ||
209 | ret |= rsnd_dai_disconnect(mod); | ||
210 | |||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | /* | 158 | /* |
215 | * Gen2 | 159 | * Gen2 |
216 | */ | 160 | */ |
@@ -229,14 +173,40 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | |||
229 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), | 173 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), |
230 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), | 174 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), |
231 | /* FIXME: it needs SSI_MODE2/3 in the future */ | 175 | /* FIXME: it needs SSI_MODE2/3 in the future */ |
176 | RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_MODE, 0x0, 0x80), | ||
177 | RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_ADINR,0x4, 0x80), | ||
178 | RSND_GEN2_M_REG(gen, SSIU, SSI_CTRL, 0x10, 0x80), | ||
232 | RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), | 179 | RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), |
233 | 180 | ||
181 | RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), | ||
182 | RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), | ||
183 | RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), | ||
184 | RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), | ||
185 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), | ||
186 | RSND_GEN2_M_REG(gen, SCU, SRC_ADINR, 0x214, 0x40), | ||
187 | RSND_GEN2_M_REG(gen, SCU, SRC_IFSCR, 0x21c, 0x40), | ||
188 | RSND_GEN2_M_REG(gen, SCU, SRC_IFSVR, 0x220, 0x40), | ||
189 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), | ||
190 | RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), | ||
191 | RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), | ||
192 | |||
234 | RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), | 193 | RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), |
235 | RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), | 194 | RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), |
236 | RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), | 195 | RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), |
237 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), | 196 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), |
238 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), | 197 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), |
239 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), | 198 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), |
199 | RSND_GEN2_S_REG(gen, ADG, DIV_EN, 0x30), | ||
200 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL0, 0x34), | ||
201 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL1, 0x38), | ||
202 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL2, 0x3c), | ||
203 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL3, 0x40), | ||
204 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL4, 0x44), | ||
205 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL0, 0x48), | ||
206 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL1, 0x4c), | ||
207 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), | ||
208 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), | ||
209 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), | ||
240 | 210 | ||
241 | RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), | 211 | RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), |
242 | RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), | 212 | RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), |
@@ -249,7 +219,6 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | |||
249 | } | 219 | } |
250 | 220 | ||
251 | static int rsnd_gen2_probe(struct platform_device *pdev, | 221 | static int rsnd_gen2_probe(struct platform_device *pdev, |
252 | struct rcar_snd_info *info, | ||
253 | struct rsnd_priv *priv) | 222 | struct rsnd_priv *priv) |
254 | { | 223 | { |
255 | struct device *dev = rsnd_priv_to_dev(priv); | 224 | struct device *dev = rsnd_priv_to_dev(priv); |
@@ -283,7 +252,7 @@ static int rsnd_gen2_probe(struct platform_device *pdev, | |||
283 | return ret; | 252 | return ret; |
284 | 253 | ||
285 | dev_dbg(dev, "Gen2 device probed\n"); | 254 | dev_dbg(dev, "Gen2 device probed\n"); |
286 | dev_dbg(dev, "SRU : %08x => %p\n", scu_res->start, | 255 | dev_dbg(dev, "SCU : %08x => %p\n", scu_res->start, |
287 | gen->base[RSND_GEN2_SCU]); | 256 | gen->base[RSND_GEN2_SCU]); |
288 | dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start, | 257 | dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start, |
289 | gen->base[RSND_GEN2_ADG]); | 258 | gen->base[RSND_GEN2_ADG]); |
@@ -317,7 +286,7 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | |||
317 | RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_CTRL, 0xc0), | 286 | RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_CTRL, 0xc0), |
318 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), | 287 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), |
319 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), | 288 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), |
320 | RSND_GEN1_M_REG(gen, SRU, BUSIF_MODE, 0x20, 0x4), | 289 | RSND_GEN1_M_REG(gen, SRU, SRC_BUSIF_MODE, 0x20, 0x4), |
321 | RSND_GEN1_M_REG(gen, SRU, SRC_ROUTE_MODE0,0x50, 0x8), | 290 | RSND_GEN1_M_REG(gen, SRU, SRC_ROUTE_MODE0,0x50, 0x8), |
322 | RSND_GEN1_M_REG(gen, SRU, SRC_SWRSR, 0x200, 0x40), | 291 | RSND_GEN1_M_REG(gen, SRU, SRC_SWRSR, 0x200, 0x40), |
323 | RSND_GEN1_M_REG(gen, SRU, SRC_SRCIR, 0x204, 0x40), | 292 | RSND_GEN1_M_REG(gen, SRU, SRC_SRCIR, 0x204, 0x40), |
@@ -347,7 +316,6 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | |||
347 | } | 316 | } |
348 | 317 | ||
349 | static int rsnd_gen1_probe(struct platform_device *pdev, | 318 | static int rsnd_gen1_probe(struct platform_device *pdev, |
350 | struct rcar_snd_info *info, | ||
351 | struct rsnd_priv *priv) | 319 | struct rsnd_priv *priv) |
352 | { | 320 | { |
353 | struct device *dev = rsnd_priv_to_dev(priv); | 321 | struct device *dev = rsnd_priv_to_dev(priv); |
@@ -392,7 +360,6 @@ static int rsnd_gen1_probe(struct platform_device *pdev, | |||
392 | * Gen | 360 | * Gen |
393 | */ | 361 | */ |
394 | int rsnd_gen_probe(struct platform_device *pdev, | 362 | int rsnd_gen_probe(struct platform_device *pdev, |
395 | struct rcar_snd_info *info, | ||
396 | struct rsnd_priv *priv) | 363 | struct rsnd_priv *priv) |
397 | { | 364 | { |
398 | struct device *dev = rsnd_priv_to_dev(priv); | 365 | struct device *dev = rsnd_priv_to_dev(priv); |
@@ -409,17 +376,12 @@ int rsnd_gen_probe(struct platform_device *pdev, | |||
409 | 376 | ||
410 | ret = -ENODEV; | 377 | ret = -ENODEV; |
411 | if (rsnd_is_gen1(priv)) | 378 | if (rsnd_is_gen1(priv)) |
412 | ret = rsnd_gen1_probe(pdev, info, priv); | 379 | ret = rsnd_gen1_probe(pdev, priv); |
413 | else if (rsnd_is_gen2(priv)) | 380 | else if (rsnd_is_gen2(priv)) |
414 | ret = rsnd_gen2_probe(pdev, info, priv); | 381 | ret = rsnd_gen2_probe(pdev, priv); |
415 | 382 | ||
416 | if (ret < 0) | 383 | if (ret < 0) |
417 | dev_err(dev, "unknown generation R-Car sound device\n"); | 384 | dev_err(dev, "unknown generation R-Car sound device\n"); |
418 | 385 | ||
419 | return ret; | 386 | return ret; |
420 | } | 387 | } |
421 | |||
422 | void rsnd_gen_remove(struct platform_device *pdev, | ||
423 | struct rsnd_priv *priv) | ||
424 | { | ||
425 | } | ||
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 4ca66cd899c8..c46e0afa54ae 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -32,15 +32,9 @@ | |||
32 | */ | 32 | */ |
33 | enum rsnd_reg { | 33 | enum rsnd_reg { |
34 | /* SRU/SCU/SSIU */ | 34 | /* SRU/SCU/SSIU */ |
35 | RSND_REG_SRC_ROUTE_SEL, /* for Gen1 */ | ||
36 | RSND_REG_SRC_TMG_SEL0, /* for Gen1 */ | ||
37 | RSND_REG_SRC_TMG_SEL1, /* for Gen1 */ | ||
38 | RSND_REG_SRC_TMG_SEL2, /* for Gen1 */ | ||
39 | RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ | ||
40 | RSND_REG_SSI_MODE0, | 35 | RSND_REG_SSI_MODE0, |
41 | RSND_REG_SSI_MODE1, | 36 | RSND_REG_SSI_MODE1, |
42 | RSND_REG_BUSIF_MODE, | 37 | RSND_REG_SRC_BUSIF_MODE, |
43 | RSND_REG_INT_ENABLE, /* for Gen2 */ | ||
44 | RSND_REG_SRC_ROUTE_MODE0, | 38 | RSND_REG_SRC_ROUTE_MODE0, |
45 | RSND_REG_SRC_SWRSR, | 39 | RSND_REG_SRC_SWRSR, |
46 | RSND_REG_SRC_SRCIR, | 40 | RSND_REG_SRC_SRCIR, |
@@ -48,7 +42,6 @@ enum rsnd_reg { | |||
48 | RSND_REG_SRC_IFSCR, | 42 | RSND_REG_SRC_IFSCR, |
49 | RSND_REG_SRC_IFSVR, | 43 | RSND_REG_SRC_IFSVR, |
50 | RSND_REG_SRC_SRCCR, | 44 | RSND_REG_SRC_SRCCR, |
51 | RSND_REG_SRC_MNFSR, | ||
52 | 45 | ||
53 | /* ADG */ | 46 | /* ADG */ |
54 | RSND_REG_BRRA, | 47 | RSND_REG_BRRA, |
@@ -56,10 +49,6 @@ enum rsnd_reg { | |||
56 | RSND_REG_SSICKR, | 49 | RSND_REG_SSICKR, |
57 | RSND_REG_AUDIO_CLK_SEL0, | 50 | RSND_REG_AUDIO_CLK_SEL0, |
58 | RSND_REG_AUDIO_CLK_SEL1, | 51 | RSND_REG_AUDIO_CLK_SEL1, |
59 | RSND_REG_AUDIO_CLK_SEL2, | ||
60 | RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ | ||
61 | RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ | ||
62 | RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ | ||
63 | 52 | ||
64 | /* SSI */ | 53 | /* SSI */ |
65 | RSND_REG_SSICR, | 54 | RSND_REG_SSICR, |
@@ -68,9 +57,62 @@ enum rsnd_reg { | |||
68 | RSND_REG_SSIRDR, | 57 | RSND_REG_SSIRDR, |
69 | RSND_REG_SSIWSR, | 58 | RSND_REG_SSIWSR, |
70 | 59 | ||
60 | /* SHARE see below */ | ||
61 | RSND_REG_SHARE01, | ||
62 | RSND_REG_SHARE02, | ||
63 | RSND_REG_SHARE03, | ||
64 | RSND_REG_SHARE04, | ||
65 | RSND_REG_SHARE05, | ||
66 | RSND_REG_SHARE06, | ||
67 | RSND_REG_SHARE07, | ||
68 | RSND_REG_SHARE08, | ||
69 | RSND_REG_SHARE09, | ||
70 | RSND_REG_SHARE10, | ||
71 | RSND_REG_SHARE11, | ||
72 | RSND_REG_SHARE12, | ||
73 | RSND_REG_SHARE13, | ||
74 | RSND_REG_SHARE14, | ||
75 | RSND_REG_SHARE15, | ||
76 | RSND_REG_SHARE16, | ||
77 | RSND_REG_SHARE17, | ||
78 | RSND_REG_SHARE18, | ||
79 | RSND_REG_SHARE19, | ||
80 | |||
71 | RSND_REG_MAX, | 81 | RSND_REG_MAX, |
72 | }; | 82 | }; |
73 | 83 | ||
84 | /* Gen1 only */ | ||
85 | #define RSND_REG_SRC_ROUTE_SEL RSND_REG_SHARE01 | ||
86 | #define RSND_REG_SRC_TMG_SEL0 RSND_REG_SHARE02 | ||
87 | #define RSND_REG_SRC_TMG_SEL1 RSND_REG_SHARE03 | ||
88 | #define RSND_REG_SRC_TMG_SEL2 RSND_REG_SHARE04 | ||
89 | #define RSND_REG_SRC_ROUTE_CTRL RSND_REG_SHARE05 | ||
90 | #define RSND_REG_SRC_MNFSR RSND_REG_SHARE06 | ||
91 | #define RSND_REG_AUDIO_CLK_SEL3 RSND_REG_SHARE07 | ||
92 | #define RSND_REG_AUDIO_CLK_SEL4 RSND_REG_SHARE08 | ||
93 | #define RSND_REG_AUDIO_CLK_SEL5 RSND_REG_SHARE09 | ||
94 | |||
95 | /* Gen2 only */ | ||
96 | #define RSND_REG_SRC_CTRL RSND_REG_SHARE01 | ||
97 | #define RSND_REG_SSI_CTRL RSND_REG_SHARE02 | ||
98 | #define RSND_REG_SSI_BUSIF_MODE RSND_REG_SHARE03 | ||
99 | #define RSND_REG_SSI_BUSIF_ADINR RSND_REG_SHARE04 | ||
100 | #define RSND_REG_INT_ENABLE RSND_REG_SHARE05 | ||
101 | #define RSND_REG_SRC_BSDSR RSND_REG_SHARE06 | ||
102 | #define RSND_REG_SRC_BSISR RSND_REG_SHARE07 | ||
103 | #define RSND_REG_DIV_EN RSND_REG_SHARE08 | ||
104 | #define RSND_REG_SRCIN_TIMSEL0 RSND_REG_SHARE09 | ||
105 | #define RSND_REG_SRCIN_TIMSEL1 RSND_REG_SHARE10 | ||
106 | #define RSND_REG_SRCIN_TIMSEL2 RSND_REG_SHARE11 | ||
107 | #define RSND_REG_SRCIN_TIMSEL3 RSND_REG_SHARE12 | ||
108 | #define RSND_REG_SRCIN_TIMSEL4 RSND_REG_SHARE13 | ||
109 | #define RSND_REG_SRCOUT_TIMSEL0 RSND_REG_SHARE14 | ||
110 | #define RSND_REG_SRCOUT_TIMSEL1 RSND_REG_SHARE15 | ||
111 | #define RSND_REG_SRCOUT_TIMSEL2 RSND_REG_SHARE16 | ||
112 | #define RSND_REG_SRCOUT_TIMSEL3 RSND_REG_SHARE17 | ||
113 | #define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18 | ||
114 | #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 | ||
115 | |||
74 | struct rsnd_priv; | 116 | struct rsnd_priv; |
75 | struct rsnd_mod; | 117 | struct rsnd_mod; |
76 | struct rsnd_dai; | 118 | struct rsnd_dai; |
@@ -96,24 +138,20 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, | |||
96 | * R-Car DMA | 138 | * R-Car DMA |
97 | */ | 139 | */ |
98 | struct rsnd_dma { | 140 | struct rsnd_dma { |
99 | struct rsnd_priv *priv; | ||
100 | struct sh_dmae_slave slave; | 141 | struct sh_dmae_slave slave; |
101 | struct work_struct work; | 142 | struct work_struct work; |
102 | struct dma_chan *chan; | 143 | struct dma_chan *chan; |
103 | enum dma_data_direction dir; | 144 | enum dma_data_direction dir; |
104 | int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len); | ||
105 | int (*complete)(struct rsnd_dma *dma); | ||
106 | 145 | ||
107 | int submit_loop; | 146 | int submit_loop; |
147 | int offset; /* it cares A/B plane */ | ||
108 | }; | 148 | }; |
109 | 149 | ||
110 | void rsnd_dma_start(struct rsnd_dma *dma); | 150 | void rsnd_dma_start(struct rsnd_dma *dma); |
111 | void rsnd_dma_stop(struct rsnd_dma *dma); | 151 | void rsnd_dma_stop(struct rsnd_dma *dma); |
112 | int rsnd_dma_available(struct rsnd_dma *dma); | 152 | int rsnd_dma_available(struct rsnd_dma *dma); |
113 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | 153 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, |
114 | int is_play, int id, | 154 | int is_play, int id); |
115 | int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len), | ||
116 | int (*complete)(struct rsnd_dma *dma)); | ||
117 | void rsnd_dma_quit(struct rsnd_priv *priv, | 155 | void rsnd_dma_quit(struct rsnd_priv *priv, |
118 | struct rsnd_dma *dma); | 156 | struct rsnd_dma *dma); |
119 | 157 | ||
@@ -121,9 +159,20 @@ void rsnd_dma_quit(struct rsnd_priv *priv, | |||
121 | /* | 159 | /* |
122 | * R-Car sound mod | 160 | * R-Car sound mod |
123 | */ | 161 | */ |
162 | enum rsnd_mod_type { | ||
163 | RSND_MOD_SRC = 0, | ||
164 | RSND_MOD_SSI, | ||
165 | RSND_MOD_MAX, | ||
166 | }; | ||
124 | 167 | ||
125 | struct rsnd_mod_ops { | 168 | struct rsnd_mod_ops { |
126 | char *name; | 169 | char *name; |
170 | int (*probe)(struct rsnd_mod *mod, | ||
171 | struct rsnd_dai *rdai, | ||
172 | struct rsnd_dai_stream *io); | ||
173 | int (*remove)(struct rsnd_mod *mod, | ||
174 | struct rsnd_dai *rdai, | ||
175 | struct rsnd_dai_stream *io); | ||
127 | int (*init)(struct rsnd_mod *mod, | 176 | int (*init)(struct rsnd_mod *mod, |
128 | struct rsnd_dai *rdai, | 177 | struct rsnd_dai *rdai, |
129 | struct rsnd_dai_stream *io); | 178 | struct rsnd_dai_stream *io); |
@@ -138,28 +187,26 @@ struct rsnd_mod_ops { | |||
138 | struct rsnd_dai_stream *io); | 187 | struct rsnd_dai_stream *io); |
139 | }; | 188 | }; |
140 | 189 | ||
190 | struct rsnd_dai_stream; | ||
141 | struct rsnd_mod { | 191 | struct rsnd_mod { |
142 | int id; | 192 | int id; |
193 | enum rsnd_mod_type type; | ||
143 | struct rsnd_priv *priv; | 194 | struct rsnd_priv *priv; |
144 | struct rsnd_mod_ops *ops; | 195 | struct rsnd_mod_ops *ops; |
145 | struct list_head list; /* connect to rsnd_dai playback/capture */ | ||
146 | struct rsnd_dma dma; | 196 | struct rsnd_dma dma; |
197 | struct rsnd_dai_stream *io; | ||
147 | }; | 198 | }; |
148 | 199 | ||
149 | #define rsnd_mod_to_priv(mod) ((mod)->priv) | 200 | #define rsnd_mod_to_priv(mod) ((mod)->priv) |
150 | #define rsnd_mod_to_dma(mod) (&(mod)->dma) | 201 | #define rsnd_mod_to_dma(mod) (&(mod)->dma) |
151 | #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) | 202 | #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) |
203 | #define rsnd_mod_to_io(mod) ((mod)->io) | ||
152 | #define rsnd_mod_id(mod) ((mod)->id) | 204 | #define rsnd_mod_id(mod) ((mod)->id) |
153 | #define for_each_rsnd_mod(pos, n, io) \ | ||
154 | list_for_each_entry_safe(pos, n, &(io)->head, list) | ||
155 | #define rsnd_mod_call(mod, func, rdai, io) \ | ||
156 | (!(mod) ? -ENODEV : \ | ||
157 | !((mod)->ops->func) ? 0 : \ | ||
158 | (mod)->ops->func(mod, rdai, io)) | ||
159 | 205 | ||
160 | void rsnd_mod_init(struct rsnd_priv *priv, | 206 | void rsnd_mod_init(struct rsnd_priv *priv, |
161 | struct rsnd_mod *mod, | 207 | struct rsnd_mod *mod, |
162 | struct rsnd_mod_ops *ops, | 208 | struct rsnd_mod_ops *ops, |
209 | enum rsnd_mod_type type, | ||
163 | int id); | 210 | int id); |
164 | char *rsnd_mod_name(struct rsnd_mod *mod); | 211 | char *rsnd_mod_name(struct rsnd_mod *mod); |
165 | 212 | ||
@@ -168,13 +215,16 @@ char *rsnd_mod_name(struct rsnd_mod *mod); | |||
168 | */ | 215 | */ |
169 | #define RSND_DAI_NAME_SIZE 16 | 216 | #define RSND_DAI_NAME_SIZE 16 |
170 | struct rsnd_dai_stream { | 217 | struct rsnd_dai_stream { |
171 | struct list_head head; /* head of rsnd_mod list */ | ||
172 | struct snd_pcm_substream *substream; | 218 | struct snd_pcm_substream *substream; |
219 | struct rsnd_mod *mod[RSND_MOD_MAX]; | ||
220 | struct rsnd_dai_path_info *info; /* rcar_snd.h */ | ||
173 | int byte_pos; | 221 | int byte_pos; |
174 | int period_pos; | 222 | int period_pos; |
175 | int byte_per_period; | 223 | int byte_per_period; |
176 | int next_period_byte; | 224 | int next_period_byte; |
177 | }; | 225 | }; |
226 | #define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) | ||
227 | #define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC]) | ||
178 | 228 | ||
179 | struct rsnd_dai { | 229 | struct rsnd_dai { |
180 | char name[RSND_DAI_NAME_SIZE]; | 230 | char name[RSND_DAI_NAME_SIZE]; |
@@ -189,16 +239,14 @@ struct rsnd_dai { | |||
189 | unsigned int data_alignment:1; | 239 | unsigned int data_alignment:1; |
190 | }; | 240 | }; |
191 | 241 | ||
192 | #define rsnd_dai_nr(priv) ((priv)->dai_nr) | 242 | #define rsnd_rdai_nr(priv) ((priv)->rdai_nr) |
193 | #define for_each_rsnd_dai(rdai, priv, i) \ | 243 | #define for_each_rsnd_dai(rdai, priv, i) \ |
194 | for (i = 0, (rdai) = rsnd_dai_get(priv, i); \ | 244 | for (i = 0; \ |
195 | i < rsnd_dai_nr(priv); \ | 245 | (i < rsnd_rdai_nr(priv)) && \ |
196 | i++, (rdai) = rsnd_dai_get(priv, i)) | 246 | ((rdai) = rsnd_dai_get(priv, i)); \ |
247 | i++) | ||
197 | 248 | ||
198 | struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); | 249 | struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); |
199 | int rsnd_dai_disconnect(struct rsnd_mod *mod); | ||
200 | int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod, | ||
201 | struct rsnd_dai_stream *io); | ||
202 | int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io); | 250 | int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io); |
203 | int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); | 251 | int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); |
204 | #define rsnd_dai_get_platform_info(rdai) ((rdai)->info) | 252 | #define rsnd_dai_get_platform_info(rdai) ((rdai)->info) |
@@ -206,21 +254,13 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); | |||
206 | 254 | ||
207 | void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); | 255 | void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); |
208 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); | 256 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); |
257 | #define rsnd_dai_is_clk_master(rdai) ((rdai)->clk_master) | ||
209 | 258 | ||
210 | /* | 259 | /* |
211 | * R-Car Gen1/Gen2 | 260 | * R-Car Gen1/Gen2 |
212 | */ | 261 | */ |
213 | int rsnd_gen_probe(struct platform_device *pdev, | 262 | int rsnd_gen_probe(struct platform_device *pdev, |
214 | struct rcar_snd_info *info, | ||
215 | struct rsnd_priv *priv); | 263 | struct rsnd_priv *priv); |
216 | void rsnd_gen_remove(struct platform_device *pdev, | ||
217 | struct rsnd_priv *priv); | ||
218 | int rsnd_gen_path_init(struct rsnd_priv *priv, | ||
219 | struct rsnd_dai *rdai, | ||
220 | struct rsnd_dai_stream *io); | ||
221 | int rsnd_gen_path_exit(struct rsnd_priv *priv, | ||
222 | struct rsnd_dai *rdai, | ||
223 | struct rsnd_dai_stream *io); | ||
224 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, | 264 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, |
225 | struct rsnd_mod *mod, | 265 | struct rsnd_mod *mod, |
226 | enum rsnd_reg reg); | 266 | enum rsnd_reg reg); |
@@ -233,14 +273,19 @@ void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, | |||
233 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); | 273 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); |
234 | int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); | 274 | int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); |
235 | int rsnd_adg_probe(struct platform_device *pdev, | 275 | int rsnd_adg_probe(struct platform_device *pdev, |
236 | struct rcar_snd_info *info, | ||
237 | struct rsnd_priv *priv); | ||
238 | void rsnd_adg_remove(struct platform_device *pdev, | ||
239 | struct rsnd_priv *priv); | 276 | struct rsnd_priv *priv); |
240 | int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, | 277 | int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, |
241 | struct rsnd_mod *mod, | 278 | struct rsnd_mod *mod, |
242 | unsigned int src_rate, | 279 | unsigned int src_rate, |
243 | unsigned int dst_rate); | 280 | unsigned int dst_rate); |
281 | int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, | ||
282 | struct rsnd_dai *rdai, | ||
283 | struct rsnd_dai_stream *io, | ||
284 | unsigned int src_rate, | ||
285 | unsigned int dst_rate); | ||
286 | int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, | ||
287 | struct rsnd_dai *rdai, | ||
288 | struct rsnd_dai_stream *io); | ||
244 | 289 | ||
245 | /* | 290 | /* |
246 | * R-Car sound priv | 291 | * R-Car sound priv |
@@ -257,10 +302,10 @@ struct rsnd_priv { | |||
257 | void *gen; | 302 | void *gen; |
258 | 303 | ||
259 | /* | 304 | /* |
260 | * below value will be filled on rsnd_scu_probe() | 305 | * below value will be filled on rsnd_src_probe() |
261 | */ | 306 | */ |
262 | void *scu; | 307 | void *src; |
263 | int scu_nr; | 308 | int src_nr; |
264 | 309 | ||
265 | /* | 310 | /* |
266 | * below value will be filled on rsnd_adg_probe() | 311 | * below value will be filled on rsnd_adg_probe() |
@@ -270,46 +315,62 @@ struct rsnd_priv { | |||
270 | /* | 315 | /* |
271 | * below value will be filled on rsnd_ssi_probe() | 316 | * below value will be filled on rsnd_ssi_probe() |
272 | */ | 317 | */ |
273 | void *ssiu; | 318 | void *ssi; |
319 | int ssi_nr; | ||
274 | 320 | ||
275 | /* | 321 | /* |
276 | * below value will be filled on rsnd_dai_probe() | 322 | * below value will be filled on rsnd_dai_probe() |
277 | */ | 323 | */ |
278 | struct snd_soc_dai_driver *daidrv; | 324 | struct snd_soc_dai_driver *daidrv; |
279 | struct rsnd_dai *rdai; | 325 | struct rsnd_dai *rdai; |
280 | int dai_nr; | 326 | int rdai_nr; |
281 | }; | 327 | }; |
282 | 328 | ||
283 | #define rsnd_priv_to_dev(priv) ((priv)->dev) | 329 | #define rsnd_priv_to_dev(priv) ((priv)->dev) |
330 | #define rsnd_priv_to_info(priv) ((priv)->info) | ||
284 | #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) | 331 | #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) |
285 | #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) | 332 | #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) |
286 | 333 | ||
334 | #define rsnd_info_is_playback(priv, type) \ | ||
335 | ({ \ | ||
336 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); \ | ||
337 | int i, is_play = 0; \ | ||
338 | for (i = 0; i < info->dai_info_nr; i++) { \ | ||
339 | if (info->dai_info[i].playback.type == (type)->info) { \ | ||
340 | is_play = 1; \ | ||
341 | break; \ | ||
342 | } \ | ||
343 | } \ | ||
344 | is_play; \ | ||
345 | }) | ||
346 | |||
287 | /* | 347 | /* |
288 | * R-Car SCU | 348 | * R-Car SRC |
289 | */ | 349 | */ |
290 | int rsnd_scu_probe(struct platform_device *pdev, | 350 | int rsnd_src_probe(struct platform_device *pdev, |
291 | struct rcar_snd_info *info, | ||
292 | struct rsnd_priv *priv); | 351 | struct rsnd_priv *priv); |
293 | void rsnd_scu_remove(struct platform_device *pdev, | 352 | struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); |
294 | struct rsnd_priv *priv); | 353 | unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, |
295 | struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); | 354 | struct rsnd_dai_stream *io, |
296 | bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod); | ||
297 | unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, | ||
298 | struct rsnd_mod *ssi_mod, | ||
299 | struct snd_pcm_runtime *runtime); | 355 | struct snd_pcm_runtime *runtime); |
356 | int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, | ||
357 | struct rsnd_dai *rdai, | ||
358 | struct rsnd_dai_stream *io); | ||
359 | int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, | ||
360 | struct rsnd_dai *rdai, | ||
361 | struct rsnd_dai_stream *io); | ||
300 | 362 | ||
301 | #define rsnd_scu_nr(priv) ((priv)->scu_nr) | 363 | #define rsnd_src_nr(priv) ((priv)->src_nr) |
302 | 364 | ||
303 | /* | 365 | /* |
304 | * R-Car SSI | 366 | * R-Car SSI |
305 | */ | 367 | */ |
306 | int rsnd_ssi_probe(struct platform_device *pdev, | 368 | int rsnd_ssi_probe(struct platform_device *pdev, |
307 | struct rcar_snd_info *info, | ||
308 | struct rsnd_priv *priv); | ||
309 | void rsnd_ssi_remove(struct platform_device *pdev, | ||
310 | struct rsnd_priv *priv); | 369 | struct rsnd_priv *priv); |
311 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); | 370 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); |
312 | struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, | 371 | struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, |
313 | int dai_id, int is_play); | 372 | int dai_id, int is_play); |
373 | int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); | ||
374 | int rsnd_ssi_is_play(struct rsnd_mod *mod); | ||
314 | 375 | ||
315 | #endif | 376 | #endif |
diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c deleted file mode 100644 index 9bb08bb1d455..000000000000 --- a/sound/soc/sh/rcar/scu.c +++ /dev/null | |||
@@ -1,384 +0,0 @@ | |||
1 | /* | ||
2 | * Renesas R-Car SCU support | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include "rsnd.h" | ||
12 | |||
13 | struct rsnd_scu { | ||
14 | struct rsnd_scu_platform_info *info; /* rcar_snd.h */ | ||
15 | struct rsnd_mod mod; | ||
16 | struct clk *clk; | ||
17 | }; | ||
18 | |||
19 | #define rsnd_scu_mode_flags(p) ((p)->info->flags) | ||
20 | #define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) | ||
21 | |||
22 | #define RSND_SCU_NAME_SIZE 16 | ||
23 | |||
24 | /* | ||
25 | * ADINR | ||
26 | */ | ||
27 | #define OTBL_24 (0 << 16) | ||
28 | #define OTBL_22 (2 << 16) | ||
29 | #define OTBL_20 (4 << 16) | ||
30 | #define OTBL_18 (6 << 16) | ||
31 | #define OTBL_16 (8 << 16) | ||
32 | |||
33 | /* | ||
34 | * image of SRC (Sampling Rate Converter) | ||
35 | * | ||
36 | * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ | ||
37 | * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | | ||
38 | * 44.1kHz <-> +-----+ +-----+ +-------+ | ||
39 | * ... | ||
40 | * | ||
41 | */ | ||
42 | |||
43 | #define rsnd_mod_to_scu(_mod) \ | ||
44 | container_of((_mod), struct rsnd_scu, mod) | ||
45 | |||
46 | #define for_each_rsnd_scu(pos, priv, i) \ | ||
47 | for ((i) = 0; \ | ||
48 | ((i) < rsnd_scu_nr(priv)) && \ | ||
49 | ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ | ||
50 | i++) | ||
51 | |||
52 | /* Gen1 only */ | ||
53 | static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, | ||
54 | struct rsnd_mod *mod, | ||
55 | struct rsnd_dai *rdai, | ||
56 | struct rsnd_dai_stream *io) | ||
57 | { | ||
58 | struct scu_route_config { | ||
59 | u32 mask; | ||
60 | int shift; | ||
61 | } routes[] = { | ||
62 | { 0xF, 0, }, /* 0 */ | ||
63 | { 0xF, 4, }, /* 1 */ | ||
64 | { 0xF, 8, }, /* 2 */ | ||
65 | { 0x7, 12, }, /* 3 */ | ||
66 | { 0x7, 16, }, /* 4 */ | ||
67 | { 0x7, 20, }, /* 5 */ | ||
68 | { 0x7, 24, }, /* 6 */ | ||
69 | { 0x3, 28, }, /* 7 */ | ||
70 | { 0x3, 30, }, /* 8 */ | ||
71 | }; | ||
72 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
73 | u32 mask; | ||
74 | u32 val; | ||
75 | int shift; | ||
76 | int id; | ||
77 | |||
78 | /* | ||
79 | * Gen1 only | ||
80 | */ | ||
81 | if (!rsnd_is_gen1(priv)) | ||
82 | return 0; | ||
83 | |||
84 | id = rsnd_mod_id(mod); | ||
85 | if (id < 0 || id >= ARRAY_SIZE(routes)) | ||
86 | return -EIO; | ||
87 | |||
88 | /* | ||
89 | * SRC_ROUTE_SELECT | ||
90 | */ | ||
91 | val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; | ||
92 | val = val << routes[id].shift; | ||
93 | mask = routes[id].mask << routes[id].shift; | ||
94 | |||
95 | rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); | ||
96 | |||
97 | /* | ||
98 | * SRC_TIMING_SELECT | ||
99 | */ | ||
100 | shift = (id % 4) * 8; | ||
101 | mask = 0x1F << shift; | ||
102 | |||
103 | /* | ||
104 | * ADG is used as source clock if SRC was used, | ||
105 | * then, SSI WS is used as destination clock. | ||
106 | * SSI WS is used as source clock if SRC is not used | ||
107 | * (when playback, source/destination become reverse when capture) | ||
108 | */ | ||
109 | if (rsnd_scu_convert_rate(scu)) /* use ADG */ | ||
110 | val = 0; | ||
111 | else if (8 == id) /* use SSI WS, but SRU8 is special */ | ||
112 | val = id << shift; | ||
113 | else /* use SSI WS */ | ||
114 | val = (id + 1) << shift; | ||
115 | |||
116 | switch (id / 4) { | ||
117 | case 0: | ||
118 | rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); | ||
119 | break; | ||
120 | case 1: | ||
121 | rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); | ||
122 | break; | ||
123 | case 2: | ||
124 | rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); | ||
125 | break; | ||
126 | } | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, | ||
132 | struct rsnd_mod *ssi_mod, | ||
133 | struct snd_pcm_runtime *runtime) | ||
134 | { | ||
135 | struct rsnd_scu *scu; | ||
136 | unsigned int rate; | ||
137 | |||
138 | /* this function is assuming SSI id = SCU id here */ | ||
139 | scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod))); | ||
140 | |||
141 | /* | ||
142 | * return convert rate if SRC is used, | ||
143 | * otherwise, return runtime->rate as usual | ||
144 | */ | ||
145 | rate = rsnd_scu_convert_rate(scu); | ||
146 | if (!rate) | ||
147 | rate = runtime->rate; | ||
148 | |||
149 | return rate; | ||
150 | } | ||
151 | |||
152 | static int rsnd_scu_convert_rate_ctrl(struct rsnd_priv *priv, | ||
153 | struct rsnd_mod *mod, | ||
154 | struct rsnd_dai *rdai, | ||
155 | struct rsnd_dai_stream *io) | ||
156 | { | ||
157 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
158 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
159 | u32 convert_rate = rsnd_scu_convert_rate(scu); | ||
160 | u32 adinr = runtime->channels; | ||
161 | |||
162 | /* set/clear soft reset */ | ||
163 | rsnd_mod_write(mod, SRC_SWRSR, 0); | ||
164 | rsnd_mod_write(mod, SRC_SWRSR, 1); | ||
165 | |||
166 | /* Initialize the operation of the SRC internal circuits */ | ||
167 | rsnd_mod_write(mod, SRC_SRCIR, 1); | ||
168 | |||
169 | /* Set channel number and output bit length */ | ||
170 | switch (runtime->sample_bits) { | ||
171 | case 16: | ||
172 | adinr |= OTBL_16; | ||
173 | break; | ||
174 | case 32: | ||
175 | adinr |= OTBL_24; | ||
176 | break; | ||
177 | default: | ||
178 | return -EIO; | ||
179 | } | ||
180 | rsnd_mod_write(mod, SRC_ADINR, adinr); | ||
181 | |||
182 | if (convert_rate) { | ||
183 | u32 fsrate = 0x0400000 / convert_rate * runtime->rate; | ||
184 | int ret; | ||
185 | |||
186 | /* Enable the initial value of IFS */ | ||
187 | rsnd_mod_write(mod, SRC_IFSCR, 1); | ||
188 | |||
189 | /* Set initial value of IFS */ | ||
190 | rsnd_mod_write(mod, SRC_IFSVR, fsrate); | ||
191 | |||
192 | /* Select SRC mode (fixed value) */ | ||
193 | rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); | ||
194 | |||
195 | /* Set the restriction value of the FS ratio (98%) */ | ||
196 | rsnd_mod_write(mod, SRC_MNFSR, fsrate / 100 * 98); | ||
197 | |||
198 | if (rsnd_is_gen1(priv)) { | ||
199 | /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ | ||
200 | } | ||
201 | |||
202 | /* set convert clock */ | ||
203 | ret = rsnd_adg_set_convert_clk(priv, mod, | ||
204 | runtime->rate, | ||
205 | convert_rate); | ||
206 | if (ret < 0) | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | /* Cancel the initialization and operate the SRC function */ | ||
211 | rsnd_mod_write(mod, SRC_SRCIR, 0); | ||
212 | |||
213 | /* use DMA transfer */ | ||
214 | rsnd_mod_write(mod, BUSIF_MODE, 1); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static int rsnd_scu_transfer_start(struct rsnd_priv *priv, | ||
220 | struct rsnd_mod *mod, | ||
221 | struct rsnd_dai *rdai, | ||
222 | struct rsnd_dai_stream *io) | ||
223 | { | ||
224 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
225 | int id = rsnd_mod_id(mod); | ||
226 | u32 val; | ||
227 | |||
228 | if (rsnd_is_gen1(priv)) { | ||
229 | val = (1 << id); | ||
230 | rsnd_mod_bset(mod, SRC_ROUTE_CTRL, val, val); | ||
231 | } | ||
232 | |||
233 | if (rsnd_scu_convert_rate(scu)) | ||
234 | rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int rsnd_scu_transfer_stop(struct rsnd_priv *priv, | ||
240 | struct rsnd_mod *mod, | ||
241 | struct rsnd_dai *rdai, | ||
242 | struct rsnd_dai_stream *io) | ||
243 | { | ||
244 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
245 | int id = rsnd_mod_id(mod); | ||
246 | u32 mask; | ||
247 | |||
248 | if (rsnd_is_gen1(priv)) { | ||
249 | mask = (1 << id); | ||
250 | rsnd_mod_bset(mod, SRC_ROUTE_CTRL, mask, 0); | ||
251 | } | ||
252 | |||
253 | if (rsnd_scu_convert_rate(scu)) | ||
254 | rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod) | ||
260 | { | ||
261 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
262 | u32 flags = rsnd_scu_mode_flags(scu); | ||
263 | |||
264 | return !!(flags & RSND_SCU_USE_HPBIF); | ||
265 | } | ||
266 | |||
267 | static int rsnd_scu_start(struct rsnd_mod *mod, | ||
268 | struct rsnd_dai *rdai, | ||
269 | struct rsnd_dai_stream *io) | ||
270 | { | ||
271 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
272 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
273 | struct device *dev = rsnd_priv_to_dev(priv); | ||
274 | int ret; | ||
275 | |||
276 | /* | ||
277 | * SCU will be used if it has RSND_SCU_USE_HPBIF flags | ||
278 | */ | ||
279 | if (!rsnd_scu_hpbif_is_enable(mod)) { | ||
280 | /* it use PIO transter */ | ||
281 | dev_dbg(dev, "%s%d is not used\n", | ||
282 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | clk_enable(scu->clk); | ||
288 | |||
289 | /* it use DMA transter */ | ||
290 | |||
291 | ret = rsnd_src_set_route_if_gen1(priv, mod, rdai, io); | ||
292 | if (ret < 0) | ||
293 | return ret; | ||
294 | |||
295 | ret = rsnd_scu_convert_rate_ctrl(priv, mod, rdai, io); | ||
296 | if (ret < 0) | ||
297 | return ret; | ||
298 | |||
299 | ret = rsnd_scu_transfer_start(priv, mod, rdai, io); | ||
300 | if (ret < 0) | ||
301 | return ret; | ||
302 | |||
303 | dev_dbg(dev, "%s%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int rsnd_scu_stop(struct rsnd_mod *mod, | ||
309 | struct rsnd_dai *rdai, | ||
310 | struct rsnd_dai_stream *io) | ||
311 | { | ||
312 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
313 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
314 | |||
315 | if (!rsnd_scu_hpbif_is_enable(mod)) | ||
316 | return 0; | ||
317 | |||
318 | rsnd_scu_transfer_stop(priv, mod, rdai, io); | ||
319 | |||
320 | clk_disable(scu->clk); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static struct rsnd_mod_ops rsnd_scu_ops = { | ||
326 | .name = "scu", | ||
327 | .start = rsnd_scu_start, | ||
328 | .stop = rsnd_scu_stop, | ||
329 | }; | ||
330 | |||
331 | struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) | ||
332 | { | ||
333 | if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv))) | ||
334 | id = 0; | ||
335 | |||
336 | return &((struct rsnd_scu *)(priv->scu) + id)->mod; | ||
337 | } | ||
338 | |||
339 | int rsnd_scu_probe(struct platform_device *pdev, | ||
340 | struct rcar_snd_info *info, | ||
341 | struct rsnd_priv *priv) | ||
342 | { | ||
343 | struct device *dev = rsnd_priv_to_dev(priv); | ||
344 | struct rsnd_scu *scu; | ||
345 | struct clk *clk; | ||
346 | char name[RSND_SCU_NAME_SIZE]; | ||
347 | int i, nr; | ||
348 | |||
349 | /* | ||
350 | * init SCU | ||
351 | */ | ||
352 | nr = info->scu_info_nr; | ||
353 | scu = devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL); | ||
354 | if (!scu) { | ||
355 | dev_err(dev, "SCU allocate failed\n"); | ||
356 | return -ENOMEM; | ||
357 | } | ||
358 | |||
359 | priv->scu_nr = nr; | ||
360 | priv->scu = scu; | ||
361 | |||
362 | for_each_rsnd_scu(scu, priv, i) { | ||
363 | snprintf(name, RSND_SCU_NAME_SIZE, "scu.%d", i); | ||
364 | |||
365 | clk = devm_clk_get(dev, name); | ||
366 | if (IS_ERR(clk)) | ||
367 | return PTR_ERR(clk); | ||
368 | |||
369 | rsnd_mod_init(priv, &scu->mod, | ||
370 | &rsnd_scu_ops, i); | ||
371 | scu->info = &info->scu_info[i]; | ||
372 | scu->clk = clk; | ||
373 | |||
374 | dev_dbg(dev, "SCU%d probed\n", i); | ||
375 | } | ||
376 | dev_dbg(dev, "scu probed\n"); | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | void rsnd_scu_remove(struct platform_device *pdev, | ||
382 | struct rsnd_priv *priv) | ||
383 | { | ||
384 | } | ||
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c new file mode 100644 index 000000000000..ea6a214985d0 --- /dev/null +++ b/sound/soc/sh/rcar/src.c | |||
@@ -0,0 +1,687 @@ | |||
1 | /* | ||
2 | * Renesas R-Car SRC support | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include "rsnd.h" | ||
12 | |||
13 | struct rsnd_src { | ||
14 | struct rsnd_src_platform_info *info; /* rcar_snd.h */ | ||
15 | struct rsnd_mod mod; | ||
16 | struct clk *clk; | ||
17 | }; | ||
18 | |||
19 | #define RSND_SRC_NAME_SIZE 16 | ||
20 | |||
21 | /* | ||
22 | * ADINR | ||
23 | */ | ||
24 | #define OTBL_24 (0 << 16) | ||
25 | #define OTBL_22 (2 << 16) | ||
26 | #define OTBL_20 (4 << 16) | ||
27 | #define OTBL_18 (6 << 16) | ||
28 | #define OTBL_16 (8 << 16) | ||
29 | |||
30 | #define rsnd_src_mode_flags(p) ((p)->info->flags) | ||
31 | #define rsnd_src_convert_rate(p) ((p)->info->convert_rate) | ||
32 | #define rsnd_mod_to_src(_mod) \ | ||
33 | container_of((_mod), struct rsnd_src, mod) | ||
34 | #define rsnd_src_hpbif_is_enable(src) \ | ||
35 | (rsnd_src_mode_flags(src) & RSND_SCU_USE_HPBIF) | ||
36 | #define rsnd_src_dma_available(src) \ | ||
37 | rsnd_dma_available(rsnd_mod_to_dma(&(src)->mod)) | ||
38 | |||
39 | #define for_each_rsnd_src(pos, priv, i) \ | ||
40 | for ((i) = 0; \ | ||
41 | ((i) < rsnd_src_nr(priv)) && \ | ||
42 | ((pos) = (struct rsnd_src *)(priv)->src + i); \ | ||
43 | i++) | ||
44 | |||
45 | |||
46 | /* | ||
47 | * image of SRC (Sampling Rate Converter) | ||
48 | * | ||
49 | * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ | ||
50 | * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | | ||
51 | * 44.1kHz <-> +-----+ +-----+ +-------+ | ||
52 | * ... | ||
53 | * | ||
54 | */ | ||
55 | |||
56 | /* | ||
57 | * src.c is caring... | ||
58 | * | ||
59 | * Gen1 | ||
60 | * | ||
61 | * [mem] -> [SRU] -> [SSI] | ||
62 | * |--------| | ||
63 | * | ||
64 | * Gen2 | ||
65 | * | ||
66 | * [mem] -> [SRC] -> [SSIU] -> [SSI] | ||
67 | * |-----------------| | ||
68 | */ | ||
69 | |||
70 | /* | ||
71 | * How to use SRC bypass mode for debugging | ||
72 | * | ||
73 | * SRC has bypass mode, and it is useful for debugging. | ||
74 | * In Gen2 case, | ||
75 | * SRCm_MODE controls whether SRC is used or not | ||
76 | * SSI_MODE0 controls whether SSIU which receives SRC data | ||
77 | * is used or not. | ||
78 | * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, | ||
79 | * but SRC bypass mode needs SSI_MODE0 only. | ||
80 | * | ||
81 | * This driver request | ||
82 | * struct rsnd_src_platform_info { | ||
83 | * u32 flags; | ||
84 | * u32 convert_rate; | ||
85 | * } | ||
86 | * | ||
87 | * rsnd_src_hpbif_is_enable() will be true | ||
88 | * if flags had RSND_SRC_USE_HPBIF, | ||
89 | * and it controls whether SSIU is used or not. | ||
90 | * | ||
91 | * rsnd_src_convert_rate() indicates | ||
92 | * above convert_rate, and it controls | ||
93 | * whether SRC is used or not. | ||
94 | * | ||
95 | * ex) doesn't use SRC | ||
96 | * struct rsnd_src_platform_info info = { | ||
97 | * .flags = 0, | ||
98 | * .convert_rate = 0, | ||
99 | * }; | ||
100 | * | ||
101 | * ex) uses SRC | ||
102 | * struct rsnd_src_platform_info info = { | ||
103 | * .flags = RSND_SRC_USE_HPBIF, | ||
104 | * .convert_rate = 48000, | ||
105 | * }; | ||
106 | * | ||
107 | * ex) uses SRC bypass mode | ||
108 | * struct rsnd_src_platform_info info = { | ||
109 | * .flags = RSND_SRC_USE_HPBIF, | ||
110 | * .convert_rate = 0, | ||
111 | * }; | ||
112 | * | ||
113 | */ | ||
114 | |||
115 | /* | ||
116 | * Gen1/Gen2 common functions | ||
117 | */ | ||
118 | int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, | ||
119 | struct rsnd_dai *rdai, | ||
120 | struct rsnd_dai_stream *io) | ||
121 | { | ||
122 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); | ||
123 | struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); | ||
124 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
125 | int ssi_id = rsnd_mod_id(ssi_mod); | ||
126 | int has_src = 0; | ||
127 | |||
128 | /* | ||
129 | * SSI_MODE0 | ||
130 | */ | ||
131 | if (info->dai_info) { | ||
132 | has_src = !!src_mod; | ||
133 | } else { | ||
134 | struct rsnd_src *src = rsnd_mod_to_src(src_mod); | ||
135 | has_src = rsnd_src_hpbif_is_enable(src); | ||
136 | } | ||
137 | |||
138 | rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), | ||
139 | has_src ? 0 : (1 << ssi_id)); | ||
140 | |||
141 | /* | ||
142 | * SSI_MODE1 | ||
143 | */ | ||
144 | if (rsnd_ssi_is_pin_sharing(ssi_mod)) { | ||
145 | int shift = -1; | ||
146 | switch (ssi_id) { | ||
147 | case 1: | ||
148 | shift = 0; | ||
149 | break; | ||
150 | case 2: | ||
151 | shift = 2; | ||
152 | break; | ||
153 | case 4: | ||
154 | shift = 16; | ||
155 | break; | ||
156 | } | ||
157 | |||
158 | if (shift >= 0) | ||
159 | rsnd_mod_bset(ssi_mod, SSI_MODE1, | ||
160 | 0x3 << shift, | ||
161 | rsnd_dai_is_clk_master(rdai) ? | ||
162 | 0x2 << shift : 0x1 << shift); | ||
163 | } | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, | ||
169 | struct rsnd_dai *rdai, | ||
170 | struct rsnd_dai_stream *io) | ||
171 | { | ||
172 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); | ||
173 | |||
174 | /* enable PIO interrupt if Gen2 */ | ||
175 | if (rsnd_is_gen2(priv)) | ||
176 | rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, | ||
182 | struct rsnd_dai_stream *io, | ||
183 | struct snd_pcm_runtime *runtime) | ||
184 | { | ||
185 | struct rsnd_src *src; | ||
186 | unsigned int rate; | ||
187 | |||
188 | src = rsnd_mod_to_src(rsnd_io_to_mod_src(io)); | ||
189 | |||
190 | /* | ||
191 | * return convert rate if SRC is used, | ||
192 | * otherwise, return runtime->rate as usual | ||
193 | */ | ||
194 | rate = rsnd_src_convert_rate(src); | ||
195 | if (!rate) | ||
196 | rate = runtime->rate; | ||
197 | |||
198 | return rate; | ||
199 | } | ||
200 | |||
201 | static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, | ||
202 | struct rsnd_dai *rdai, | ||
203 | struct rsnd_dai_stream *io) | ||
204 | { | ||
205 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
206 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
207 | u32 convert_rate = rsnd_src_convert_rate(src); | ||
208 | u32 adinr = runtime->channels; | ||
209 | u32 fsrate = 0; | ||
210 | |||
211 | if (convert_rate) | ||
212 | fsrate = 0x0400000 / convert_rate * runtime->rate; | ||
213 | |||
214 | /* set/clear soft reset */ | ||
215 | rsnd_mod_write(mod, SRC_SWRSR, 0); | ||
216 | rsnd_mod_write(mod, SRC_SWRSR, 1); | ||
217 | |||
218 | /* | ||
219 | * Initialize the operation of the SRC internal circuits | ||
220 | * see rsnd_src_start() | ||
221 | */ | ||
222 | rsnd_mod_write(mod, SRC_SRCIR, 1); | ||
223 | |||
224 | /* Set channel number and output bit length */ | ||
225 | switch (runtime->sample_bits) { | ||
226 | case 16: | ||
227 | adinr |= OTBL_16; | ||
228 | break; | ||
229 | case 32: | ||
230 | adinr |= OTBL_24; | ||
231 | break; | ||
232 | default: | ||
233 | return -EIO; | ||
234 | } | ||
235 | rsnd_mod_write(mod, SRC_ADINR, adinr); | ||
236 | |||
237 | /* Enable the initial value of IFS */ | ||
238 | if (fsrate) { | ||
239 | rsnd_mod_write(mod, SRC_IFSCR, 1); | ||
240 | |||
241 | /* Set initial value of IFS */ | ||
242 | rsnd_mod_write(mod, SRC_IFSVR, fsrate); | ||
243 | } | ||
244 | |||
245 | /* use DMA transfer */ | ||
246 | rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static int rsnd_src_init(struct rsnd_mod *mod, | ||
252 | struct rsnd_dai *rdai, | ||
253 | struct rsnd_dai_stream *io) | ||
254 | { | ||
255 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
256 | |||
257 | clk_enable(src->clk); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static int rsnd_src_quit(struct rsnd_mod *mod, | ||
263 | struct rsnd_dai *rdai, | ||
264 | struct rsnd_dai_stream *io) | ||
265 | { | ||
266 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
267 | |||
268 | clk_disable(src->clk); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int rsnd_src_start(struct rsnd_mod *mod, | ||
274 | struct rsnd_dai *rdai, | ||
275 | struct rsnd_dai_stream *io) | ||
276 | { | ||
277 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
278 | |||
279 | /* | ||
280 | * Cancel the initialization and operate the SRC function | ||
281 | * see rsnd_src_set_convert_rate() | ||
282 | */ | ||
283 | rsnd_mod_write(mod, SRC_SRCIR, 0); | ||
284 | |||
285 | if (rsnd_src_convert_rate(src)) | ||
286 | rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | |||
292 | static int rsnd_src_stop(struct rsnd_mod *mod, | ||
293 | struct rsnd_dai *rdai, | ||
294 | struct rsnd_dai_stream *io) | ||
295 | { | ||
296 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
297 | |||
298 | if (rsnd_src_convert_rate(src)) | ||
299 | rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static struct rsnd_mod_ops rsnd_src_non_ops = { | ||
305 | .name = "src (non)", | ||
306 | }; | ||
307 | |||
308 | /* | ||
309 | * Gen1 functions | ||
310 | */ | ||
311 | static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, | ||
312 | struct rsnd_dai *rdai, | ||
313 | struct rsnd_dai_stream *io) | ||
314 | { | ||
315 | struct src_route_config { | ||
316 | u32 mask; | ||
317 | int shift; | ||
318 | } routes[] = { | ||
319 | { 0xF, 0, }, /* 0 */ | ||
320 | { 0xF, 4, }, /* 1 */ | ||
321 | { 0xF, 8, }, /* 2 */ | ||
322 | { 0x7, 12, }, /* 3 */ | ||
323 | { 0x7, 16, }, /* 4 */ | ||
324 | { 0x7, 20, }, /* 5 */ | ||
325 | { 0x7, 24, }, /* 6 */ | ||
326 | { 0x3, 28, }, /* 7 */ | ||
327 | { 0x3, 30, }, /* 8 */ | ||
328 | }; | ||
329 | u32 mask; | ||
330 | u32 val; | ||
331 | int id; | ||
332 | |||
333 | id = rsnd_mod_id(mod); | ||
334 | if (id < 0 || id >= ARRAY_SIZE(routes)) | ||
335 | return -EIO; | ||
336 | |||
337 | /* | ||
338 | * SRC_ROUTE_SELECT | ||
339 | */ | ||
340 | val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; | ||
341 | val = val << routes[id].shift; | ||
342 | mask = routes[id].mask << routes[id].shift; | ||
343 | |||
344 | rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); | ||
345 | |||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod, | ||
350 | struct rsnd_dai *rdai, | ||
351 | struct rsnd_dai_stream *io) | ||
352 | { | ||
353 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
354 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
355 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
356 | u32 convert_rate = rsnd_src_convert_rate(src); | ||
357 | u32 mask; | ||
358 | u32 val; | ||
359 | int shift; | ||
360 | int id = rsnd_mod_id(mod); | ||
361 | int ret; | ||
362 | |||
363 | /* | ||
364 | * SRC_TIMING_SELECT | ||
365 | */ | ||
366 | shift = (id % 4) * 8; | ||
367 | mask = 0x1F << shift; | ||
368 | |||
369 | /* | ||
370 | * ADG is used as source clock if SRC was used, | ||
371 | * then, SSI WS is used as destination clock. | ||
372 | * SSI WS is used as source clock if SRC is not used | ||
373 | * (when playback, source/destination become reverse when capture) | ||
374 | */ | ||
375 | ret = 0; | ||
376 | if (convert_rate) { | ||
377 | /* use ADG */ | ||
378 | val = 0; | ||
379 | ret = rsnd_adg_set_convert_clk_gen1(priv, mod, | ||
380 | runtime->rate, | ||
381 | convert_rate); | ||
382 | } else if (8 == id) { | ||
383 | /* use SSI WS, but SRU8 is special */ | ||
384 | val = id << shift; | ||
385 | } else { | ||
386 | /* use SSI WS */ | ||
387 | val = (id + 1) << shift; | ||
388 | } | ||
389 | |||
390 | if (ret < 0) | ||
391 | return ret; | ||
392 | |||
393 | switch (id / 4) { | ||
394 | case 0: | ||
395 | rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); | ||
396 | break; | ||
397 | case 1: | ||
398 | rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); | ||
399 | break; | ||
400 | case 2: | ||
401 | rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); | ||
402 | break; | ||
403 | } | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, | ||
409 | struct rsnd_dai *rdai, | ||
410 | struct rsnd_dai_stream *io) | ||
411 | { | ||
412 | int ret; | ||
413 | |||
414 | ret = rsnd_src_set_convert_rate(mod, rdai, io); | ||
415 | if (ret < 0) | ||
416 | return ret; | ||
417 | |||
418 | /* Select SRC mode (fixed value) */ | ||
419 | rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); | ||
420 | |||
421 | /* Set the restriction value of the FS ratio (98%) */ | ||
422 | rsnd_mod_write(mod, SRC_MNFSR, | ||
423 | rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); | ||
424 | |||
425 | /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static int rsnd_src_init_gen1(struct rsnd_mod *mod, | ||
431 | struct rsnd_dai *rdai, | ||
432 | struct rsnd_dai_stream *io) | ||
433 | { | ||
434 | int ret; | ||
435 | |||
436 | ret = rsnd_src_init(mod, rdai, io); | ||
437 | if (ret < 0) | ||
438 | return ret; | ||
439 | |||
440 | ret = rsnd_src_set_route_gen1(mod, rdai, io); | ||
441 | if (ret < 0) | ||
442 | return ret; | ||
443 | |||
444 | ret = rsnd_src_set_convert_rate_gen1(mod, rdai, io); | ||
445 | if (ret < 0) | ||
446 | return ret; | ||
447 | |||
448 | ret = rsnd_src_set_convert_timing_gen1(mod, rdai, io); | ||
449 | if (ret < 0) | ||
450 | return ret; | ||
451 | |||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static int rsnd_src_start_gen1(struct rsnd_mod *mod, | ||
456 | struct rsnd_dai *rdai, | ||
457 | struct rsnd_dai_stream *io) | ||
458 | { | ||
459 | int id = rsnd_mod_id(mod); | ||
460 | |||
461 | rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); | ||
462 | |||
463 | return rsnd_src_start(mod, rdai, io); | ||
464 | } | ||
465 | |||
466 | static int rsnd_src_stop_gen1(struct rsnd_mod *mod, | ||
467 | struct rsnd_dai *rdai, | ||
468 | struct rsnd_dai_stream *io) | ||
469 | { | ||
470 | int id = rsnd_mod_id(mod); | ||
471 | |||
472 | rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); | ||
473 | |||
474 | return rsnd_src_stop(mod, rdai, io); | ||
475 | } | ||
476 | |||
477 | static struct rsnd_mod_ops rsnd_src_gen1_ops = { | ||
478 | .name = "sru (gen1)", | ||
479 | .init = rsnd_src_init_gen1, | ||
480 | .quit = rsnd_src_quit, | ||
481 | .start = rsnd_src_start_gen1, | ||
482 | .stop = rsnd_src_stop_gen1, | ||
483 | }; | ||
484 | |||
485 | /* | ||
486 | * Gen2 functions | ||
487 | */ | ||
488 | static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, | ||
489 | struct rsnd_dai *rdai, | ||
490 | struct rsnd_dai_stream *io) | ||
491 | { | ||
492 | int ret; | ||
493 | |||
494 | ret = rsnd_src_set_convert_rate(mod, rdai, io); | ||
495 | if (ret < 0) | ||
496 | return ret; | ||
497 | |||
498 | rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); | ||
499 | rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); | ||
500 | |||
501 | rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); | ||
502 | |||
503 | rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); | ||
504 | rsnd_mod_write(mod, SRC_BSISR, 0x00100060); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod, | ||
510 | struct rsnd_dai *rdai, | ||
511 | struct rsnd_dai_stream *io) | ||
512 | { | ||
513 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
514 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
515 | u32 convert_rate = rsnd_src_convert_rate(src); | ||
516 | int ret; | ||
517 | |||
518 | if (convert_rate) | ||
519 | ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, | ||
520 | runtime->rate, | ||
521 | convert_rate); | ||
522 | else | ||
523 | ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); | ||
524 | |||
525 | return ret; | ||
526 | } | ||
527 | |||
528 | static int rsnd_src_probe_gen2(struct rsnd_mod *mod, | ||
529 | struct rsnd_dai *rdai, | ||
530 | struct rsnd_dai_stream *io) | ||
531 | { | ||
532 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
533 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
534 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
535 | struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); | ||
536 | struct device *dev = rsnd_priv_to_dev(priv); | ||
537 | int ret; | ||
538 | int is_play; | ||
539 | |||
540 | if (info->dai_info) | ||
541 | is_play = rsnd_info_is_playback(priv, src); | ||
542 | else | ||
543 | is_play = rsnd_ssi_is_play(ssi); | ||
544 | |||
545 | ret = rsnd_dma_init(priv, | ||
546 | rsnd_mod_to_dma(mod), | ||
547 | is_play, | ||
548 | src->info->dma_id); | ||
549 | if (ret < 0) | ||
550 | dev_err(dev, "SRC DMA failed\n"); | ||
551 | |||
552 | return ret; | ||
553 | } | ||
554 | |||
555 | static int rsnd_src_remove_gen2(struct rsnd_mod *mod, | ||
556 | struct rsnd_dai *rdai, | ||
557 | struct rsnd_dai_stream *io) | ||
558 | { | ||
559 | rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); | ||
560 | |||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | static int rsnd_src_init_gen2(struct rsnd_mod *mod, | ||
565 | struct rsnd_dai *rdai, | ||
566 | struct rsnd_dai_stream *io) | ||
567 | { | ||
568 | int ret; | ||
569 | |||
570 | ret = rsnd_src_init(mod, rdai, io); | ||
571 | if (ret < 0) | ||
572 | return ret; | ||
573 | |||
574 | ret = rsnd_src_set_convert_rate_gen2(mod, rdai, io); | ||
575 | if (ret < 0) | ||
576 | return ret; | ||
577 | |||
578 | ret = rsnd_src_set_convert_timing_gen2(mod, rdai, io); | ||
579 | if (ret < 0) | ||
580 | return ret; | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | static int rsnd_src_start_gen2(struct rsnd_mod *mod, | ||
586 | struct rsnd_dai *rdai, | ||
587 | struct rsnd_dai_stream *io) | ||
588 | { | ||
589 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
590 | |||
591 | rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); | ||
592 | |||
593 | rsnd_mod_write(mod, SSI_CTRL, 0x1); | ||
594 | rsnd_mod_write(mod, SRC_CTRL, 0x11); | ||
595 | |||
596 | return rsnd_src_start(mod, rdai, io); | ||
597 | } | ||
598 | |||
599 | static int rsnd_src_stop_gen2(struct rsnd_mod *mod, | ||
600 | struct rsnd_dai *rdai, | ||
601 | struct rsnd_dai_stream *io) | ||
602 | { | ||
603 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
604 | |||
605 | rsnd_mod_write(mod, SSI_CTRL, 0); | ||
606 | rsnd_mod_write(mod, SRC_CTRL, 0); | ||
607 | |||
608 | rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); | ||
609 | |||
610 | return rsnd_src_stop(mod, rdai, io); | ||
611 | } | ||
612 | |||
613 | static struct rsnd_mod_ops rsnd_src_gen2_ops = { | ||
614 | .name = "src (gen2)", | ||
615 | .probe = rsnd_src_probe_gen2, | ||
616 | .remove = rsnd_src_remove_gen2, | ||
617 | .init = rsnd_src_init_gen2, | ||
618 | .quit = rsnd_src_quit, | ||
619 | .start = rsnd_src_start_gen2, | ||
620 | .stop = rsnd_src_stop_gen2, | ||
621 | }; | ||
622 | |||
623 | struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) | ||
624 | { | ||
625 | if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv))) | ||
626 | id = 0; | ||
627 | |||
628 | return &((struct rsnd_src *)(priv->src) + id)->mod; | ||
629 | } | ||
630 | |||
631 | int rsnd_src_probe(struct platform_device *pdev, | ||
632 | struct rsnd_priv *priv) | ||
633 | { | ||
634 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
635 | struct device *dev = rsnd_priv_to_dev(priv); | ||
636 | struct rsnd_src *src; | ||
637 | struct rsnd_mod_ops *ops; | ||
638 | struct clk *clk; | ||
639 | char name[RSND_SRC_NAME_SIZE]; | ||
640 | int i, nr; | ||
641 | |||
642 | /* | ||
643 | * init SRC | ||
644 | */ | ||
645 | nr = info->src_info_nr; | ||
646 | if (!nr) | ||
647 | return 0; | ||
648 | |||
649 | src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); | ||
650 | if (!src) { | ||
651 | dev_err(dev, "SRC allocate failed\n"); | ||
652 | return -ENOMEM; | ||
653 | } | ||
654 | |||
655 | priv->src_nr = nr; | ||
656 | priv->src = src; | ||
657 | |||
658 | for_each_rsnd_src(src, priv, i) { | ||
659 | snprintf(name, RSND_SRC_NAME_SIZE, "src.%d", i); | ||
660 | |||
661 | clk = devm_clk_get(dev, name); | ||
662 | if (IS_ERR(clk)) { | ||
663 | snprintf(name, RSND_SRC_NAME_SIZE, "scu.%d", i); | ||
664 | clk = devm_clk_get(dev, name); | ||
665 | } | ||
666 | |||
667 | if (IS_ERR(clk)) | ||
668 | return PTR_ERR(clk); | ||
669 | |||
670 | src->info = &info->src_info[i]; | ||
671 | src->clk = clk; | ||
672 | |||
673 | ops = &rsnd_src_non_ops; | ||
674 | if (rsnd_src_hpbif_is_enable(src)) { | ||
675 | if (rsnd_is_gen1(priv)) | ||
676 | ops = &rsnd_src_gen1_ops; | ||
677 | if (rsnd_is_gen2(priv)) | ||
678 | ops = &rsnd_src_gen2_ops; | ||
679 | } | ||
680 | |||
681 | rsnd_mod_init(priv, &src->mod, ops, RSND_MOD_SRC, i); | ||
682 | |||
683 | dev_dbg(dev, "SRC%d probed\n", i); | ||
684 | } | ||
685 | |||
686 | return 0; | ||
687 | } | ||
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 4b8cf7ca9d19..633b23d209b9 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -64,108 +64,29 @@ struct rsnd_ssi { | |||
64 | struct rsnd_mod mod; | 64 | struct rsnd_mod mod; |
65 | 65 | ||
66 | struct rsnd_dai *rdai; | 66 | struct rsnd_dai *rdai; |
67 | struct rsnd_dai_stream *io; | ||
68 | u32 cr_own; | 67 | u32 cr_own; |
69 | u32 cr_clk; | 68 | u32 cr_clk; |
70 | u32 cr_etc; | 69 | u32 cr_etc; |
71 | int err; | 70 | int err; |
72 | int dma_offset; | ||
73 | unsigned int usrcnt; | 71 | unsigned int usrcnt; |
74 | unsigned int rate; | 72 | unsigned int rate; |
75 | }; | 73 | }; |
76 | 74 | ||
77 | struct rsnd_ssiu { | ||
78 | u32 ssi_mode0; | ||
79 | u32 ssi_mode1; | ||
80 | |||
81 | int ssi_nr; | ||
82 | struct rsnd_ssi *ssi; | ||
83 | }; | ||
84 | |||
85 | #define for_each_rsnd_ssi(pos, priv, i) \ | 75 | #define for_each_rsnd_ssi(pos, priv, i) \ |
86 | for (i = 0; \ | 76 | for (i = 0; \ |
87 | (i < rsnd_ssi_nr(priv)) && \ | 77 | (i < rsnd_ssi_nr(priv)) && \ |
88 | ((pos) = ((struct rsnd_ssiu *)((priv)->ssiu))->ssi + i); \ | 78 | ((pos) = ((struct rsnd_ssi *)(priv)->ssi + i)); \ |
89 | i++) | 79 | i++) |
90 | 80 | ||
91 | #define rsnd_ssi_nr(priv) (((struct rsnd_ssiu *)((priv)->ssiu))->ssi_nr) | 81 | #define rsnd_ssi_nr(priv) ((priv)->ssi_nr) |
92 | #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) | 82 | #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) |
93 | #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) | 83 | #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) |
94 | #define rsnd_ssi_pio_available(ssi) ((ssi)->info->pio_irq > 0) | 84 | #define rsnd_ssi_pio_available(ssi) ((ssi)->info->pio_irq > 0) |
95 | #define rsnd_ssi_dma_available(ssi) \ | 85 | #define rsnd_ssi_dma_available(ssi) \ |
96 | rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod)) | 86 | rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod)) |
97 | #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) | 87 | #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) |
98 | #define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master) | ||
99 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) | 88 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) |
100 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) | 89 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) |
101 | #define rsnd_ssi_to_ssiu(ssi)\ | ||
102 | (((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1) | ||
103 | |||
104 | static void rsnd_ssi_mode_set(struct rsnd_priv *priv, | ||
105 | struct rsnd_dai *rdai, | ||
106 | struct rsnd_ssi *ssi) | ||
107 | { | ||
108 | struct device *dev = rsnd_priv_to_dev(priv); | ||
109 | struct rsnd_mod *scu; | ||
110 | struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi); | ||
111 | int id = rsnd_mod_id(&ssi->mod); | ||
112 | u32 flags; | ||
113 | u32 val; | ||
114 | |||
115 | scu = rsnd_scu_mod_get(priv, rsnd_mod_id(&ssi->mod)); | ||
116 | |||
117 | /* | ||
118 | * SSI_MODE0 | ||
119 | */ | ||
120 | |||
121 | /* see also BUSIF_MODE */ | ||
122 | if (rsnd_scu_hpbif_is_enable(scu)) { | ||
123 | ssiu->ssi_mode0 &= ~(1 << id); | ||
124 | dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", id); | ||
125 | } else { | ||
126 | ssiu->ssi_mode0 |= (1 << id); | ||
127 | dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", id); | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * SSI_MODE1 | ||
132 | */ | ||
133 | #define ssi_parent_set(p, sync, adg, ext) \ | ||
134 | do { \ | ||
135 | ssi->parent = ssiu->ssi + p; \ | ||
136 | if (rsnd_rdai_is_clk_master(rdai)) \ | ||
137 | val = adg; \ | ||
138 | else \ | ||
139 | val = ext; \ | ||
140 | if (flags & RSND_SSI_SYNC) \ | ||
141 | val |= sync; \ | ||
142 | } while (0) | ||
143 | |||
144 | flags = rsnd_ssi_mode_flags(ssi); | ||
145 | if (flags & RSND_SSI_CLK_PIN_SHARE) { | ||
146 | |||
147 | val = 0; | ||
148 | switch (id) { | ||
149 | case 1: | ||
150 | ssi_parent_set(0, (1 << 4), (0x2 << 0), (0x1 << 0)); | ||
151 | break; | ||
152 | case 2: | ||
153 | ssi_parent_set(0, (1 << 4), (0x2 << 2), (0x1 << 2)); | ||
154 | break; | ||
155 | case 4: | ||
156 | ssi_parent_set(3, (1 << 20), (0x2 << 16), (0x1 << 16)); | ||
157 | break; | ||
158 | case 8: | ||
159 | ssi_parent_set(7, 0, 0, 0); | ||
160 | break; | ||
161 | } | ||
162 | |||
163 | ssiu->ssi_mode1 |= val; | ||
164 | } | ||
165 | |||
166 | rsnd_mod_write(&ssi->mod, SSI_MODE0, ssiu->ssi_mode0); | ||
167 | rsnd_mod_write(&ssi->mod, SSI_MODE1, ssiu->ssi_mode1); | ||
168 | } | ||
169 | 90 | ||
170 | static void rsnd_ssi_status_check(struct rsnd_mod *mod, | 91 | static void rsnd_ssi_status_check(struct rsnd_mod *mod, |
171 | u32 bit) | 92 | u32 bit) |
@@ -200,7 +121,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, | |||
200 | 1, 2, 4, 8, 16, 6, 12, | 121 | 1, 2, 4, 8, 16, 6, 12, |
201 | }; | 122 | }; |
202 | unsigned int main_rate; | 123 | unsigned int main_rate; |
203 | unsigned int rate = rsnd_scu_get_ssi_rate(priv, &ssi->mod, runtime); | 124 | unsigned int rate = rsnd_src_get_ssi_rate(priv, io, runtime); |
204 | 125 | ||
205 | /* | 126 | /* |
206 | * Find best clock, and try to start ADG | 127 | * Find best clock, and try to start ADG |
@@ -252,7 +173,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, | |||
252 | if (0 == ssi->usrcnt) { | 173 | if (0 == ssi->usrcnt) { |
253 | clk_enable(ssi->clk); | 174 | clk_enable(ssi->clk); |
254 | 175 | ||
255 | if (rsnd_rdai_is_clk_master(rdai)) { | 176 | if (rsnd_dai_is_clk_master(rdai)) { |
256 | if (rsnd_ssi_clk_from_parent(ssi)) | 177 | if (rsnd_ssi_clk_from_parent(ssi)) |
257 | rsnd_ssi_hw_start(ssi->parent, rdai, io); | 178 | rsnd_ssi_hw_start(ssi->parent, rdai, io); |
258 | else | 179 | else |
@@ -302,7 +223,7 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, | |||
302 | rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */ | 223 | rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */ |
303 | rsnd_ssi_status_check(&ssi->mod, IIRQ); | 224 | rsnd_ssi_status_check(&ssi->mod, IIRQ); |
304 | 225 | ||
305 | if (rsnd_rdai_is_clk_master(rdai)) { | 226 | if (rsnd_dai_is_clk_master(rdai)) { |
306 | if (rsnd_ssi_clk_from_parent(ssi)) | 227 | if (rsnd_ssi_clk_from_parent(ssi)) |
307 | rsnd_ssi_hw_stop(ssi->parent, rdai); | 228 | rsnd_ssi_hw_stop(ssi->parent, rdai); |
308 | else | 229 | else |
@@ -323,8 +244,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, | |||
323 | struct rsnd_dai_stream *io) | 244 | struct rsnd_dai_stream *io) |
324 | { | 245 | { |
325 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 246 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
326 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
327 | struct device *dev = rsnd_priv_to_dev(priv); | ||
328 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 247 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
329 | u32 cr; | 248 | u32 cr; |
330 | 249 | ||
@@ -365,13 +284,10 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, | |||
365 | * set ssi parameter | 284 | * set ssi parameter |
366 | */ | 285 | */ |
367 | ssi->rdai = rdai; | 286 | ssi->rdai = rdai; |
368 | ssi->io = io; | ||
369 | ssi->cr_own = cr; | 287 | ssi->cr_own = cr; |
370 | ssi->err = -1; /* ignore 1st error */ | 288 | ssi->err = -1; /* ignore 1st error */ |
371 | 289 | ||
372 | rsnd_ssi_mode_set(priv, rdai, ssi); | 290 | rsnd_src_ssi_mode_init(mod, rdai, io); |
373 | |||
374 | dev_dbg(dev, "%s.%d init\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
375 | 291 | ||
376 | return 0; | 292 | return 0; |
377 | } | 293 | } |
@@ -384,13 +300,10 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, | |||
384 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 300 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
385 | struct device *dev = rsnd_priv_to_dev(priv); | 301 | struct device *dev = rsnd_priv_to_dev(priv); |
386 | 302 | ||
387 | dev_dbg(dev, "%s.%d quit\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
388 | |||
389 | if (ssi->err > 0) | 303 | if (ssi->err > 0) |
390 | dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err); | 304 | dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err); |
391 | 305 | ||
392 | ssi->rdai = NULL; | 306 | ssi->rdai = NULL; |
393 | ssi->io = NULL; | ||
394 | ssi->cr_own = 0; | 307 | ssi->cr_own = 0; |
395 | ssi->err = 0; | 308 | ssi->err = 0; |
396 | 309 | ||
@@ -414,8 +327,9 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) | |||
414 | static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) | 327 | static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) |
415 | { | 328 | { |
416 | struct rsnd_ssi *ssi = data; | 329 | struct rsnd_ssi *ssi = data; |
417 | struct rsnd_dai_stream *io = ssi->io; | 330 | struct rsnd_mod *mod = &ssi->mod; |
418 | u32 status = rsnd_mod_read(&ssi->mod, SSISR); | 331 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
332 | u32 status = rsnd_mod_read(mod, SSISR); | ||
419 | irqreturn_t ret = IRQ_NONE; | 333 | irqreturn_t ret = IRQ_NONE; |
420 | 334 | ||
421 | if (io && (status & DIRQ)) { | 335 | if (io && (status & DIRQ)) { |
@@ -432,9 +346,9 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) | |||
432 | * see rsnd_ssi_init() | 346 | * see rsnd_ssi_init() |
433 | */ | 347 | */ |
434 | if (rsnd_dai_is_play(rdai, io)) | 348 | if (rsnd_dai_is_play(rdai, io)) |
435 | rsnd_mod_write(&ssi->mod, SSITDR, *buf); | 349 | rsnd_mod_write(mod, SSITDR, *buf); |
436 | else | 350 | else |
437 | *buf = rsnd_mod_read(&ssi->mod, SSIRDR); | 351 | *buf = rsnd_mod_read(mod, SSIRDR); |
438 | 352 | ||
439 | rsnd_dai_pointer_update(io, sizeof(*buf)); | 353 | rsnd_dai_pointer_update(io, sizeof(*buf)); |
440 | 354 | ||
@@ -444,25 +358,39 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) | |||
444 | return ret; | 358 | return ret; |
445 | } | 359 | } |
446 | 360 | ||
447 | static int rsnd_ssi_pio_start(struct rsnd_mod *mod, | 361 | static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, |
448 | struct rsnd_dai *rdai, | 362 | struct rsnd_dai *rdai, |
449 | struct rsnd_dai_stream *io) | 363 | struct rsnd_dai_stream *io) |
450 | { | 364 | { |
451 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 365 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
452 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
453 | struct device *dev = rsnd_priv_to_dev(priv); | 366 | struct device *dev = rsnd_priv_to_dev(priv); |
367 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
368 | int irq = ssi->info->pio_irq; | ||
369 | int ret; | ||
370 | |||
371 | ret = devm_request_irq(dev, irq, | ||
372 | rsnd_ssi_pio_interrupt, | ||
373 | IRQF_SHARED, | ||
374 | dev_name(dev), ssi); | ||
375 | if (ret) | ||
376 | dev_err(dev, "SSI request interrupt failed\n"); | ||
377 | |||
378 | return ret; | ||
379 | } | ||
380 | |||
381 | static int rsnd_ssi_pio_start(struct rsnd_mod *mod, | ||
382 | struct rsnd_dai *rdai, | ||
383 | struct rsnd_dai_stream *io) | ||
384 | { | ||
385 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
454 | 386 | ||
455 | /* enable PIO IRQ */ | 387 | /* enable PIO IRQ */ |
456 | ssi->cr_etc = UIEN | OIEN | DIEN; | 388 | ssi->cr_etc = UIEN | OIEN | DIEN; |
457 | 389 | ||
458 | /* enable PIO interrupt if gen2 */ | 390 | rsnd_src_enable_ssi_irq(mod, rdai, io); |
459 | if (rsnd_is_gen2(priv)) | ||
460 | rsnd_mod_write(&ssi->mod, INT_ENABLE, 0x0f000000); | ||
461 | 391 | ||
462 | rsnd_ssi_hw_start(ssi, rdai, io); | 392 | rsnd_ssi_hw_start(ssi, rdai, io); |
463 | 393 | ||
464 | dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
465 | |||
466 | return 0; | 394 | return 0; |
467 | } | 395 | } |
468 | 396 | ||
@@ -470,12 +398,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, | |||
470 | struct rsnd_dai *rdai, | 398 | struct rsnd_dai *rdai, |
471 | struct rsnd_dai_stream *io) | 399 | struct rsnd_dai_stream *io) |
472 | { | 400 | { |
473 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
474 | struct device *dev = rsnd_priv_to_dev(priv); | ||
475 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 401 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
476 | 402 | ||
477 | dev_dbg(dev, "%s.%d stop\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
478 | |||
479 | ssi->cr_etc = 0; | 403 | ssi->cr_etc = 0; |
480 | 404 | ||
481 | rsnd_ssi_hw_stop(ssi, rdai); | 405 | rsnd_ssi_hw_stop(ssi, rdai); |
@@ -485,35 +409,46 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, | |||
485 | 409 | ||
486 | static struct rsnd_mod_ops rsnd_ssi_pio_ops = { | 410 | static struct rsnd_mod_ops rsnd_ssi_pio_ops = { |
487 | .name = "ssi (pio)", | 411 | .name = "ssi (pio)", |
412 | .probe = rsnd_ssi_pio_probe, | ||
488 | .init = rsnd_ssi_init, | 413 | .init = rsnd_ssi_init, |
489 | .quit = rsnd_ssi_quit, | 414 | .quit = rsnd_ssi_quit, |
490 | .start = rsnd_ssi_pio_start, | 415 | .start = rsnd_ssi_pio_start, |
491 | .stop = rsnd_ssi_pio_stop, | 416 | .stop = rsnd_ssi_pio_stop, |
492 | }; | 417 | }; |
493 | 418 | ||
494 | static int rsnd_ssi_dma_inquiry(struct rsnd_dma *dma, dma_addr_t *buf, int *len) | 419 | static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, |
420 | struct rsnd_dai *rdai, | ||
421 | struct rsnd_dai_stream *io) | ||
495 | { | 422 | { |
496 | struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma); | 423 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
497 | struct rsnd_dai_stream *io = ssi->io; | 424 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
498 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 425 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); |
426 | struct device *dev = rsnd_priv_to_dev(priv); | ||
427 | int dma_id = ssi->info->dma_id; | ||
428 | int is_play; | ||
429 | int ret; | ||
499 | 430 | ||
500 | *len = io->byte_per_period; | 431 | if (info->dai_info) |
501 | *buf = runtime->dma_addr + | 432 | is_play = rsnd_info_is_playback(priv, ssi); |
502 | rsnd_dai_pointer_offset(io, ssi->dma_offset + *len); | 433 | else |
503 | ssi->dma_offset = *len; /* it cares A/B plane */ | 434 | is_play = rsnd_ssi_is_play(&ssi->mod); |
504 | 435 | ||
505 | return 0; | 436 | ret = rsnd_dma_init( |
506 | } | 437 | priv, rsnd_mod_to_dma(mod), |
438 | is_play, | ||
439 | dma_id); | ||
507 | 440 | ||
508 | static int rsnd_ssi_dma_complete(struct rsnd_dma *dma) | 441 | if (ret < 0) |
509 | { | 442 | dev_err(dev, "SSI DMA failed\n"); |
510 | struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma); | ||
511 | struct rsnd_dai_stream *io = ssi->io; | ||
512 | u32 status = rsnd_mod_read(&ssi->mod, SSISR); | ||
513 | 443 | ||
514 | rsnd_ssi_record_error(ssi, status); | 444 | return ret; |
445 | } | ||
515 | 446 | ||
516 | rsnd_dai_pointer_update(ssi->io, io->byte_per_period); | 447 | static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, |
448 | struct rsnd_dai *rdai, | ||
449 | struct rsnd_dai_stream *io) | ||
450 | { | ||
451 | rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); | ||
517 | 452 | ||
518 | return 0; | 453 | return 0; |
519 | } | 454 | } |
@@ -527,14 +462,13 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, | |||
527 | 462 | ||
528 | /* enable DMA transfer */ | 463 | /* enable DMA transfer */ |
529 | ssi->cr_etc = DMEN; | 464 | ssi->cr_etc = DMEN; |
530 | ssi->dma_offset = 0; | ||
531 | 465 | ||
532 | rsnd_dma_start(dma); | 466 | rsnd_dma_start(dma); |
533 | 467 | ||
534 | rsnd_ssi_hw_start(ssi, ssi->rdai, io); | 468 | rsnd_ssi_hw_start(ssi, ssi->rdai, io); |
535 | 469 | ||
536 | /* enable WS continue */ | 470 | /* enable WS continue */ |
537 | if (rsnd_rdai_is_clk_master(rdai)) | 471 | if (rsnd_dai_is_clk_master(rdai)) |
538 | rsnd_mod_write(&ssi->mod, SSIWSR, CONT); | 472 | rsnd_mod_write(&ssi->mod, SSIWSR, CONT); |
539 | 473 | ||
540 | return 0; | 474 | return 0; |
@@ -549,6 +483,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, | |||
549 | 483 | ||
550 | ssi->cr_etc = 0; | 484 | ssi->cr_etc = 0; |
551 | 485 | ||
486 | rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); | ||
487 | |||
552 | rsnd_ssi_hw_stop(ssi, rdai); | 488 | rsnd_ssi_hw_stop(ssi, rdai); |
553 | 489 | ||
554 | rsnd_dma_stop(dma); | 490 | rsnd_dma_stop(dma); |
@@ -558,6 +494,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, | |||
558 | 494 | ||
559 | static struct rsnd_mod_ops rsnd_ssi_dma_ops = { | 495 | static struct rsnd_mod_ops rsnd_ssi_dma_ops = { |
560 | .name = "ssi (dma)", | 496 | .name = "ssi (dma)", |
497 | .probe = rsnd_ssi_dma_probe, | ||
498 | .remove = rsnd_ssi_dma_remove, | ||
561 | .init = rsnd_ssi_init, | 499 | .init = rsnd_ssi_init, |
562 | .quit = rsnd_ssi_quit, | 500 | .quit = rsnd_ssi_quit, |
563 | .start = rsnd_ssi_dma_start, | 501 | .start = rsnd_ssi_dma_start, |
@@ -567,24 +505,8 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { | |||
567 | /* | 505 | /* |
568 | * Non SSI | 506 | * Non SSI |
569 | */ | 507 | */ |
570 | static int rsnd_ssi_non(struct rsnd_mod *mod, | ||
571 | struct rsnd_dai *rdai, | ||
572 | struct rsnd_dai_stream *io) | ||
573 | { | ||
574 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
575 | struct device *dev = rsnd_priv_to_dev(priv); | ||
576 | |||
577 | dev_dbg(dev, "%s\n", __func__); | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | static struct rsnd_mod_ops rsnd_ssi_non_ops = { | 508 | static struct rsnd_mod_ops rsnd_ssi_non_ops = { |
583 | .name = "ssi (non)", | 509 | .name = "ssi (non)", |
584 | .init = rsnd_ssi_non, | ||
585 | .quit = rsnd_ssi_non, | ||
586 | .start = rsnd_ssi_non, | ||
587 | .stop = rsnd_ssi_non, | ||
588 | }; | 510 | }; |
589 | 511 | ||
590 | /* | 512 | /* |
@@ -593,16 +515,30 @@ static struct rsnd_mod_ops rsnd_ssi_non_ops = { | |||
593 | struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, | 515 | struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, |
594 | int dai_id, int is_play) | 516 | int dai_id, int is_play) |
595 | { | 517 | { |
518 | struct rsnd_dai_platform_info *dai_info = NULL; | ||
519 | struct rsnd_dai_path_info *path_info = NULL; | ||
520 | struct rsnd_ssi_platform_info *target_info = NULL; | ||
596 | struct rsnd_ssi *ssi; | 521 | struct rsnd_ssi *ssi; |
597 | int i, has_play; | 522 | int i, has_play; |
598 | 523 | ||
524 | if (priv->rdai) | ||
525 | dai_info = priv->rdai[dai_id].info; | ||
526 | if (dai_info) | ||
527 | path_info = (is_play) ? &dai_info->playback : &dai_info->capture; | ||
528 | if (path_info) | ||
529 | target_info = path_info->ssi; | ||
530 | |||
599 | is_play = !!is_play; | 531 | is_play = !!is_play; |
600 | 532 | ||
601 | for_each_rsnd_ssi(ssi, priv, i) { | 533 | for_each_rsnd_ssi(ssi, priv, i) { |
534 | if (target_info == ssi->info) | ||
535 | return &ssi->mod; | ||
536 | |||
537 | /* for compatible */ | ||
602 | if (rsnd_ssi_dai_id(ssi) != dai_id) | 538 | if (rsnd_ssi_dai_id(ssi) != dai_id) |
603 | continue; | 539 | continue; |
604 | 540 | ||
605 | has_play = !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); | 541 | has_play = rsnd_ssi_is_play(&ssi->mod); |
606 | 542 | ||
607 | if (is_play == has_play) | 543 | if (is_play == has_play) |
608 | return &ssi->mod; | 544 | return &ssi->mod; |
@@ -616,36 +552,66 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id) | |||
616 | if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv))) | 552 | if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv))) |
617 | id = 0; | 553 | id = 0; |
618 | 554 | ||
619 | return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod; | 555 | return &((struct rsnd_ssi *)(priv->ssi) + id)->mod; |
556 | } | ||
557 | |||
558 | int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) | ||
559 | { | ||
560 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
561 | |||
562 | return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); | ||
563 | } | ||
564 | |||
565 | int rsnd_ssi_is_play(struct rsnd_mod *mod) | ||
566 | { | ||
567 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
568 | |||
569 | return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); | ||
570 | } | ||
571 | |||
572 | static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) | ||
573 | { | ||
574 | if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) | ||
575 | return; | ||
576 | |||
577 | switch (rsnd_mod_id(&ssi->mod)) { | ||
578 | case 1: | ||
579 | case 2: | ||
580 | ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 0)); | ||
581 | break; | ||
582 | case 4: | ||
583 | ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 3)); | ||
584 | break; | ||
585 | case 8: | ||
586 | ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 7)); | ||
587 | break; | ||
588 | } | ||
620 | } | 589 | } |
621 | 590 | ||
622 | int rsnd_ssi_probe(struct platform_device *pdev, | 591 | int rsnd_ssi_probe(struct platform_device *pdev, |
623 | struct rcar_snd_info *info, | ||
624 | struct rsnd_priv *priv) | 592 | struct rsnd_priv *priv) |
625 | { | 593 | { |
594 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
626 | struct rsnd_ssi_platform_info *pinfo; | 595 | struct rsnd_ssi_platform_info *pinfo; |
627 | struct device *dev = rsnd_priv_to_dev(priv); | 596 | struct device *dev = rsnd_priv_to_dev(priv); |
628 | struct rsnd_mod_ops *ops; | 597 | struct rsnd_mod_ops *ops; |
629 | struct clk *clk; | 598 | struct clk *clk; |
630 | struct rsnd_ssiu *ssiu; | ||
631 | struct rsnd_ssi *ssi; | 599 | struct rsnd_ssi *ssi; |
632 | char name[RSND_SSI_NAME_SIZE]; | 600 | char name[RSND_SSI_NAME_SIZE]; |
633 | int i, nr, ret; | 601 | int i, nr; |
634 | 602 | ||
635 | /* | 603 | /* |
636 | * init SSI | 604 | * init SSI |
637 | */ | 605 | */ |
638 | nr = info->ssi_info_nr; | 606 | nr = info->ssi_info_nr; |
639 | ssiu = devm_kzalloc(dev, sizeof(*ssiu) + (sizeof(*ssi) * nr), | 607 | ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL); |
640 | GFP_KERNEL); | 608 | if (!ssi) { |
641 | if (!ssiu) { | ||
642 | dev_err(dev, "SSI allocate failed\n"); | 609 | dev_err(dev, "SSI allocate failed\n"); |
643 | return -ENOMEM; | 610 | return -ENOMEM; |
644 | } | 611 | } |
645 | 612 | ||
646 | priv->ssiu = ssiu; | 613 | priv->ssi = ssi; |
647 | ssiu->ssi = (struct rsnd_ssi *)(ssiu + 1); | 614 | priv->ssi_nr = nr; |
648 | ssiu->ssi_nr = nr; | ||
649 | 615 | ||
650 | for_each_rsnd_ssi(ssi, priv, i) { | 616 | for_each_rsnd_ssi(ssi, priv, i) { |
651 | pinfo = &info->ssi_info[i]; | 617 | pinfo = &info->ssi_info[i]; |
@@ -660,61 +626,15 @@ int rsnd_ssi_probe(struct platform_device *pdev, | |||
660 | ssi->clk = clk; | 626 | ssi->clk = clk; |
661 | 627 | ||
662 | ops = &rsnd_ssi_non_ops; | 628 | ops = &rsnd_ssi_non_ops; |
629 | if (pinfo->dma_id > 0) | ||
630 | ops = &rsnd_ssi_dma_ops; | ||
631 | else if (rsnd_ssi_pio_available(ssi)) | ||
632 | ops = &rsnd_ssi_pio_ops; | ||
663 | 633 | ||
664 | /* | 634 | rsnd_mod_init(priv, &ssi->mod, ops, RSND_MOD_SSI, i); |
665 | * SSI DMA case | ||
666 | */ | ||
667 | if (pinfo->dma_id > 0) { | ||
668 | ret = rsnd_dma_init( | ||
669 | priv, rsnd_mod_to_dma(&ssi->mod), | ||
670 | (rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY), | ||
671 | pinfo->dma_id, | ||
672 | rsnd_ssi_dma_inquiry, | ||
673 | rsnd_ssi_dma_complete); | ||
674 | if (ret < 0) | ||
675 | dev_info(dev, "SSI DMA failed. try PIO transter\n"); | ||
676 | else | ||
677 | ops = &rsnd_ssi_dma_ops; | ||
678 | |||
679 | dev_dbg(dev, "SSI%d use DMA transfer\n", i); | ||
680 | } | ||
681 | |||
682 | /* | ||
683 | * SSI PIO case | ||
684 | */ | ||
685 | if (!rsnd_ssi_dma_available(ssi) && | ||
686 | rsnd_ssi_pio_available(ssi)) { | ||
687 | ret = devm_request_irq(dev, pinfo->pio_irq, | ||
688 | &rsnd_ssi_pio_interrupt, | ||
689 | IRQF_SHARED, | ||
690 | dev_name(dev), ssi); | ||
691 | if (ret) { | ||
692 | dev_err(dev, "SSI request interrupt failed\n"); | ||
693 | return ret; | ||
694 | } | ||
695 | |||
696 | ops = &rsnd_ssi_pio_ops; | ||
697 | 635 | ||
698 | dev_dbg(dev, "SSI%d use PIO transfer\n", i); | 636 | rsnd_ssi_parent_clk_setup(priv, ssi); |
699 | } | ||
700 | |||
701 | rsnd_mod_init(priv, &ssi->mod, ops, i); | ||
702 | } | 637 | } |
703 | 638 | ||
704 | dev_dbg(dev, "ssi probed\n"); | ||
705 | |||
706 | return 0; | 639 | return 0; |
707 | } | 640 | } |
708 | |||
709 | void rsnd_ssi_remove(struct platform_device *pdev, | ||
710 | struct rsnd_priv *priv) | ||
711 | { | ||
712 | struct rsnd_ssi *ssi; | ||
713 | int i; | ||
714 | |||
715 | for_each_rsnd_ssi(ssi, priv, i) { | ||
716 | if (rsnd_ssi_dma_available(ssi)) | ||
717 | rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod)); | ||
718 | } | ||
719 | |||
720 | } | ||
diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig new file mode 100644 index 000000000000..89e89429b04a --- /dev/null +++ b/sound/soc/sirf/Kconfig | |||
@@ -0,0 +1,14 @@ | |||
1 | config SND_SOC_SIRF | ||
2 | tristate "SoC Audio for the SiRF SoC chips" | ||
3 | depends on ARCH_SIRF || COMPILE_TEST | ||
4 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
5 | |||
6 | config SND_SOC_SIRF_AUDIO | ||
7 | tristate "SoC Audio support for SiRF internal audio codec" | ||
8 | depends on SND_SOC_SIRF | ||
9 | select SND_SOC_SIRF_AUDIO_CODEC | ||
10 | select SND_SOC_SIRF_AUDIO_PORT | ||
11 | |||
12 | config SND_SOC_SIRF_AUDIO_PORT | ||
13 | select REGMAP_MMIO | ||
14 | tristate | ||
diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile new file mode 100644 index 000000000000..913b93231d4e --- /dev/null +++ b/sound/soc/sirf/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | snd-soc-sirf-audio-objs := sirf-audio.o | ||
2 | snd-soc-sirf-audio-port-objs := sirf-audio-port.o | ||
3 | |||
4 | obj-$(CONFIG_SND_SOC_SIRF_AUDIO) += snd-soc-sirf-audio.o | ||
5 | obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o | ||
diff --git a/sound/soc/sirf/sirf-audio-port.c b/sound/soc/sirf/sirf-audio-port.c new file mode 100644 index 000000000000..b04a53f2b4f6 --- /dev/null +++ b/sound/soc/sirf/sirf-audio-port.c | |||
@@ -0,0 +1,194 @@ | |||
1 | /* | ||
2 | * SiRF Audio port driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | #include <linux/module.h> | ||
9 | #include <linux/io.h> | ||
10 | #include <linux/regmap.h> | ||
11 | #include <sound/soc.h> | ||
12 | #include <sound/dmaengine_pcm.h> | ||
13 | |||
14 | #include "sirf-audio-port.h" | ||
15 | |||
16 | struct sirf_audio_port { | ||
17 | struct regmap *regmap; | ||
18 | struct snd_dmaengine_dai_dma_data playback_dma_data; | ||
19 | struct snd_dmaengine_dai_dma_data capture_dma_data; | ||
20 | }; | ||
21 | |||
22 | static void sirf_audio_port_tx_enable(struct sirf_audio_port *port) | ||
23 | { | ||
24 | regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, | ||
25 | AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); | ||
26 | regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0); | ||
27 | regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); | ||
28 | regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, | ||
29 | AUDIO_FIFO_START, AUDIO_FIFO_START); | ||
30 | regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL, | ||
31 | IC_TX_ENABLE, IC_TX_ENABLE); | ||
32 | } | ||
33 | |||
34 | static void sirf_audio_port_tx_disable(struct sirf_audio_port *port) | ||
35 | { | ||
36 | regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); | ||
37 | regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL, | ||
38 | IC_TX_ENABLE, ~IC_TX_ENABLE); | ||
39 | } | ||
40 | |||
41 | static void sirf_audio_port_rx_enable(struct sirf_audio_port *port, | ||
42 | int channels) | ||
43 | { | ||
44 | regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, | ||
45 | AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); | ||
46 | regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_INT_MSK, 0); | ||
47 | regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0); | ||
48 | regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, | ||
49 | AUDIO_FIFO_START, AUDIO_FIFO_START); | ||
50 | if (channels == 1) | ||
51 | regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, | ||
52 | IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO); | ||
53 | else | ||
54 | regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, | ||
55 | IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO); | ||
56 | } | ||
57 | |||
58 | static void sirf_audio_port_rx_disable(struct sirf_audio_port *port) | ||
59 | { | ||
60 | regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, | ||
61 | IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO); | ||
62 | } | ||
63 | |||
64 | static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai) | ||
65 | { | ||
66 | struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); | ||
67 | snd_soc_dai_init_dma_data(dai, &port->playback_dma_data, | ||
68 | &port->capture_dma_data); | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int sirf_audio_port_trigger(struct snd_pcm_substream *substream, int cmd, | ||
73 | struct snd_soc_dai *dai) | ||
74 | { | ||
75 | struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); | ||
76 | int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
77 | |||
78 | switch (cmd) { | ||
79 | case SNDRV_PCM_TRIGGER_STOP: | ||
80 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
81 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
82 | if (playback) | ||
83 | sirf_audio_port_tx_disable(port); | ||
84 | else | ||
85 | sirf_audio_port_rx_disable(port); | ||
86 | break; | ||
87 | case SNDRV_PCM_TRIGGER_START: | ||
88 | case SNDRV_PCM_TRIGGER_RESUME: | ||
89 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
90 | if (playback) | ||
91 | sirf_audio_port_tx_enable(port); | ||
92 | else | ||
93 | sirf_audio_port_rx_enable(port, | ||
94 | substream->runtime->channels); | ||
95 | break; | ||
96 | default: | ||
97 | return -EINVAL; | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static const struct snd_soc_dai_ops sirf_audio_port_dai_ops = { | ||
104 | .trigger = sirf_audio_port_trigger, | ||
105 | }; | ||
106 | |||
107 | static struct snd_soc_dai_driver sirf_audio_port_dai = { | ||
108 | .probe = sirf_audio_port_dai_probe, | ||
109 | .name = "sirf-audio-port", | ||
110 | .id = 0, | ||
111 | .playback = { | ||
112 | .channels_min = 2, | ||
113 | .channels_max = 2, | ||
114 | .rates = SNDRV_PCM_RATE_48000, | ||
115 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
116 | }, | ||
117 | .capture = { | ||
118 | .channels_min = 1, | ||
119 | .channels_max = 2, | ||
120 | .rates = SNDRV_PCM_RATE_48000, | ||
121 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
122 | }, | ||
123 | .ops = &sirf_audio_port_dai_ops, | ||
124 | }; | ||
125 | |||
126 | static const struct snd_soc_component_driver sirf_audio_port_component = { | ||
127 | .name = "sirf-audio-port", | ||
128 | }; | ||
129 | |||
130 | static const struct regmap_config sirf_audio_port_regmap_config = { | ||
131 | .reg_bits = 32, | ||
132 | .reg_stride = 4, | ||
133 | .val_bits = 32, | ||
134 | .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK, | ||
135 | .cache_type = REGCACHE_NONE, | ||
136 | }; | ||
137 | |||
138 | static int sirf_audio_port_probe(struct platform_device *pdev) | ||
139 | { | ||
140 | int ret; | ||
141 | struct sirf_audio_port *port; | ||
142 | void __iomem *base; | ||
143 | struct resource *mem_res; | ||
144 | |||
145 | port = devm_kzalloc(&pdev->dev, | ||
146 | sizeof(struct sirf_audio_port), GFP_KERNEL); | ||
147 | if (!port) | ||
148 | return -ENOMEM; | ||
149 | |||
150 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
151 | if (!mem_res) { | ||
152 | dev_err(&pdev->dev, "no mem resource?\n"); | ||
153 | return -ENODEV; | ||
154 | } | ||
155 | |||
156 | base = devm_ioremap(&pdev->dev, mem_res->start, | ||
157 | resource_size(mem_res)); | ||
158 | if (base == NULL) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | port->regmap = devm_regmap_init_mmio(&pdev->dev, base, | ||
162 | &sirf_audio_port_regmap_config); | ||
163 | if (IS_ERR(port->regmap)) | ||
164 | return PTR_ERR(port->regmap); | ||
165 | |||
166 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
167 | &sirf_audio_port_component, &sirf_audio_port_dai, 1); | ||
168 | if (ret) | ||
169 | return ret; | ||
170 | |||
171 | platform_set_drvdata(pdev, port); | ||
172 | return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | ||
173 | } | ||
174 | |||
175 | static const struct of_device_id sirf_audio_port_of_match[] = { | ||
176 | { .compatible = "sirf,audio-port", }, | ||
177 | {} | ||
178 | }; | ||
179 | MODULE_DEVICE_TABLE(of, sirf_audio_port_of_match); | ||
180 | |||
181 | static struct platform_driver sirf_audio_port_driver = { | ||
182 | .driver = { | ||
183 | .name = "sirf-audio-port", | ||
184 | .owner = THIS_MODULE, | ||
185 | .of_match_table = sirf_audio_port_of_match, | ||
186 | }, | ||
187 | .probe = sirf_audio_port_probe, | ||
188 | }; | ||
189 | |||
190 | module_platform_driver(sirf_audio_port_driver); | ||
191 | |||
192 | MODULE_DESCRIPTION("SiRF Audio Port driver"); | ||
193 | MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>"); | ||
194 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/sirf/sirf-audio-port.h b/sound/soc/sirf/sirf-audio-port.h new file mode 100644 index 000000000000..f32dc54f4499 --- /dev/null +++ b/sound/soc/sirf/sirf-audio-port.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * SiRF Audio port controllers define | ||
3 | * | ||
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #ifndef _SIRF_AUDIO_PORT_H | ||
10 | #define _SIRF_AUDIO_PORT_H | ||
11 | |||
12 | #define AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK 0x3F | ||
13 | #define AUDIO_PORT_TX_FIFO_SC_OFFSET 0 | ||
14 | #define AUDIO_PORT_TX_FIFO_LC_OFFSET 10 | ||
15 | #define AUDIO_PORT_TX_FIFO_HC_OFFSET 20 | ||
16 | |||
17 | #define TX_FIFO_SC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ | ||
18 | << AUDIO_PORT_TX_FIFO_SC_OFFSET) | ||
19 | #define TX_FIFO_LC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ | ||
20 | << AUDIO_PORT_TX_FIFO_LC_OFFSET) | ||
21 | #define TX_FIFO_HC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ | ||
22 | << AUDIO_PORT_TX_FIFO_HC_OFFSET) | ||
23 | |||
24 | #define AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK 0x0F | ||
25 | #define AUDIO_PORT_RX_FIFO_SC_OFFSET 0 | ||
26 | #define AUDIO_PORT_RX_FIFO_LC_OFFSET 10 | ||
27 | #define AUDIO_PORT_RX_FIFO_HC_OFFSET 20 | ||
28 | |||
29 | #define RX_FIFO_SC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ | ||
30 | << AUDIO_PORT_RX_FIFO_SC_OFFSET) | ||
31 | #define RX_FIFO_LC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ | ||
32 | << AUDIO_PORT_RX_FIFO_LC_OFFSET) | ||
33 | #define RX_FIFO_HC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ | ||
34 | << AUDIO_PORT_RX_FIFO_HC_OFFSET) | ||
35 | #define AUDIO_PORT_IC_CODEC_TX_CTRL (0x00F4) | ||
36 | #define AUDIO_PORT_IC_CODEC_RX_CTRL (0x00F8) | ||
37 | |||
38 | #define AUDIO_PORT_IC_TXFIFO_OP (0x00FC) | ||
39 | #define AUDIO_PORT_IC_TXFIFO_LEV_CHK (0x0100) | ||
40 | #define AUDIO_PORT_IC_TXFIFO_STS (0x0104) | ||
41 | #define AUDIO_PORT_IC_TXFIFO_INT (0x0108) | ||
42 | #define AUDIO_PORT_IC_TXFIFO_INT_MSK (0x010C) | ||
43 | |||
44 | #define AUDIO_PORT_IC_RXFIFO_OP (0x0110) | ||
45 | #define AUDIO_PORT_IC_RXFIFO_LEV_CHK (0x0114) | ||
46 | #define AUDIO_PORT_IC_RXFIFO_STS (0x0118) | ||
47 | #define AUDIO_PORT_IC_RXFIFO_INT (0x011C) | ||
48 | #define AUDIO_PORT_IC_RXFIFO_INT_MSK (0x0120) | ||
49 | |||
50 | #define AUDIO_FIFO_START (1 << 0) | ||
51 | #define AUDIO_FIFO_RESET (1 << 1) | ||
52 | |||
53 | #define AUDIO_FIFO_FULL (1 << 0) | ||
54 | #define AUDIO_FIFO_EMPTY (1 << 1) | ||
55 | #define AUDIO_FIFO_OFLOW (1 << 2) | ||
56 | #define AUDIO_FIFO_UFLOW (1 << 3) | ||
57 | |||
58 | #define IC_TX_ENABLE (0x03) | ||
59 | #define IC_RX_ENABLE_MONO (0x01) | ||
60 | #define IC_RX_ENABLE_STEREO (0x03) | ||
61 | |||
62 | #endif /*__SIRF_AUDIO_PORT_H*/ | ||
diff --git a/sound/soc/sirf/sirf-audio.c b/sound/soc/sirf/sirf-audio.c new file mode 100644 index 000000000000..ecef51021653 --- /dev/null +++ b/sound/soc/sirf/sirf-audio.c | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | * SiRF audio card driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/platform_device.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/of.h> | ||
12 | #include <linux/gpio.h> | ||
13 | #include <linux/of_gpio.h> | ||
14 | #include <sound/core.h> | ||
15 | #include <sound/pcm.h> | ||
16 | #include <sound/soc.h> | ||
17 | |||
18 | struct sirf_audio_card { | ||
19 | unsigned int gpio_hp_pa; | ||
20 | unsigned int gpio_spk_pa; | ||
21 | }; | ||
22 | |||
23 | static int sirf_audio_hp_event(struct snd_soc_dapm_widget *w, | ||
24 | struct snd_kcontrol *ctrl, int event) | ||
25 | { | ||
26 | struct snd_soc_dapm_context *dapm = w->dapm; | ||
27 | struct snd_soc_card *card = dapm->card; | ||
28 | struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card); | ||
29 | int on = !SND_SOC_DAPM_EVENT_OFF(event); | ||
30 | if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) | ||
31 | gpio_set_value(sirf_audio_card->gpio_hp_pa, on); | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static int sirf_audio_spk_event(struct snd_soc_dapm_widget *w, | ||
36 | struct snd_kcontrol *ctrl, int event) | ||
37 | { | ||
38 | struct snd_soc_dapm_context *dapm = w->dapm; | ||
39 | struct snd_soc_card *card = dapm->card; | ||
40 | struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card); | ||
41 | int on = !SND_SOC_DAPM_EVENT_OFF(event); | ||
42 | |||
43 | if (gpio_is_valid(sirf_audio_card->gpio_spk_pa)) | ||
44 | gpio_set_value(sirf_audio_card->gpio_spk_pa, on); | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | static const struct snd_soc_dapm_widget sirf_audio_dapm_widgets[] = { | ||
49 | SND_SOC_DAPM_HP("Hp", sirf_audio_hp_event), | ||
50 | SND_SOC_DAPM_SPK("Ext Spk", sirf_audio_spk_event), | ||
51 | SND_SOC_DAPM_MIC("Ext Mic", NULL), | ||
52 | }; | ||
53 | |||
54 | static const struct snd_soc_dapm_route intercon[] = { | ||
55 | {"Hp", NULL, "HPOUTL"}, | ||
56 | {"Hp", NULL, "HPOUTR"}, | ||
57 | {"Ext Spk", NULL, "SPKOUT"}, | ||
58 | {"MICIN1", NULL, "Mic Bias"}, | ||
59 | {"Mic Bias", NULL, "Ext Mic"}, | ||
60 | }; | ||
61 | |||
62 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
63 | static struct snd_soc_dai_link sirf_audio_dai_link[] = { | ||
64 | { | ||
65 | .name = "SiRF audio card", | ||
66 | .stream_name = "SiRF audio HiFi", | ||
67 | .codec_dai_name = "sirf-audio-codec", | ||
68 | }, | ||
69 | }; | ||
70 | |||
71 | /* Audio machine driver */ | ||
72 | static struct snd_soc_card snd_soc_sirf_audio_card = { | ||
73 | .name = "SiRF audio card", | ||
74 | .owner = THIS_MODULE, | ||
75 | .dai_link = sirf_audio_dai_link, | ||
76 | .num_links = ARRAY_SIZE(sirf_audio_dai_link), | ||
77 | .dapm_widgets = sirf_audio_dapm_widgets, | ||
78 | .num_dapm_widgets = ARRAY_SIZE(sirf_audio_dapm_widgets), | ||
79 | .dapm_routes = intercon, | ||
80 | .num_dapm_routes = ARRAY_SIZE(intercon), | ||
81 | }; | ||
82 | |||
83 | static int sirf_audio_probe(struct platform_device *pdev) | ||
84 | { | ||
85 | struct snd_soc_card *card = &snd_soc_sirf_audio_card; | ||
86 | struct sirf_audio_card *sirf_audio_card; | ||
87 | int ret; | ||
88 | |||
89 | sirf_audio_card = devm_kzalloc(&pdev->dev, sizeof(struct sirf_audio_card), | ||
90 | GFP_KERNEL); | ||
91 | if (sirf_audio_card == NULL) | ||
92 | return -ENOMEM; | ||
93 | |||
94 | sirf_audio_dai_link[0].cpu_of_node = | ||
95 | of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); | ||
96 | sirf_audio_dai_link[0].platform_of_node = | ||
97 | of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); | ||
98 | sirf_audio_dai_link[0].codec_of_node = | ||
99 | of_parse_phandle(pdev->dev.of_node, "sirf,audio-codec", 0); | ||
100 | sirf_audio_card->gpio_spk_pa = of_get_named_gpio(pdev->dev.of_node, | ||
101 | "spk-pa-gpios", 0); | ||
102 | sirf_audio_card->gpio_hp_pa = of_get_named_gpio(pdev->dev.of_node, | ||
103 | "hp-pa-gpios", 0); | ||
104 | if (gpio_is_valid(sirf_audio_card->gpio_spk_pa)) { | ||
105 | ret = devm_gpio_request_one(&pdev->dev, | ||
106 | sirf_audio_card->gpio_spk_pa, | ||
107 | GPIOF_OUT_INIT_LOW, "SPA_PA_SD"); | ||
108 | if (ret) { | ||
109 | dev_err(&pdev->dev, | ||
110 | "Failed to request GPIO_%d for reset: %d\n", | ||
111 | sirf_audio_card->gpio_spk_pa, ret); | ||
112 | return ret; | ||
113 | } | ||
114 | } | ||
115 | if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) { | ||
116 | ret = devm_gpio_request_one(&pdev->dev, | ||
117 | sirf_audio_card->gpio_hp_pa, | ||
118 | GPIOF_OUT_INIT_LOW, "HP_PA_SD"); | ||
119 | if (ret) { | ||
120 | dev_err(&pdev->dev, | ||
121 | "Failed to request GPIO_%d for reset: %d\n", | ||
122 | sirf_audio_card->gpio_hp_pa, ret); | ||
123 | return ret; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | card->dev = &pdev->dev; | ||
128 | snd_soc_card_set_drvdata(card, sirf_audio_card); | ||
129 | |||
130 | ret = devm_snd_soc_register_card(&pdev->dev, card); | ||
131 | if (ret) | ||
132 | dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret); | ||
133 | |||
134 | return ret; | ||
135 | } | ||
136 | |||
137 | static const struct of_device_id sirf_audio_of_match[] = { | ||
138 | {.compatible = "sirf,sirf-audio-card", }, | ||
139 | { }, | ||
140 | }; | ||
141 | MODULE_DEVICE_TABLE(of, sirf_audio_of_match); | ||
142 | |||
143 | static struct platform_driver sirf_audio_driver = { | ||
144 | .driver = { | ||
145 | .name = "sirf-audio-card", | ||
146 | .owner = THIS_MODULE, | ||
147 | .pm = &snd_soc_pm_ops, | ||
148 | .of_match_table = sirf_audio_of_match, | ||
149 | }, | ||
150 | .probe = sirf_audio_probe, | ||
151 | }; | ||
152 | module_platform_driver(sirf_audio_driver); | ||
153 | |||
154 | MODULE_AUTHOR("RongJun Ying <RongJun.Ying@csr.com>"); | ||
155 | MODULE_DESCRIPTION("ALSA SoC SIRF audio card driver"); | ||
156 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 375dc6dfba4e..bfed3e4c45ff 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -96,8 +96,7 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec) | |||
96 | { | 96 | { |
97 | dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n", | 97 | dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n", |
98 | codec->name); | 98 | codec->name); |
99 | if (!codec->reg_cache) | 99 | |
100 | return 0; | ||
101 | kfree(codec->reg_cache); | 100 | kfree(codec->reg_cache); |
102 | codec->reg_cache = NULL; | 101 | codec->reg_cache = NULL; |
103 | return 0; | 102 | return 0; |
@@ -117,8 +116,9 @@ int snd_soc_cache_read(struct snd_soc_codec *codec, | |||
117 | return -EINVAL; | 116 | return -EINVAL; |
118 | 117 | ||
119 | mutex_lock(&codec->cache_rw_mutex); | 118 | mutex_lock(&codec->cache_rw_mutex); |
120 | *value = snd_soc_get_cache_val(codec->reg_cache, reg, | 119 | if (!ZERO_OR_NULL_PTR(codec->reg_cache)) |
121 | codec->driver->reg_word_size); | 120 | *value = snd_soc_get_cache_val(codec->reg_cache, reg, |
121 | codec->driver->reg_word_size); | ||
122 | mutex_unlock(&codec->cache_rw_mutex); | 122 | mutex_unlock(&codec->cache_rw_mutex); |
123 | 123 | ||
124 | return 0; | 124 | return 0; |
@@ -136,8 +136,9 @@ int snd_soc_cache_write(struct snd_soc_codec *codec, | |||
136 | unsigned int reg, unsigned int value) | 136 | unsigned int reg, unsigned int value) |
137 | { | 137 | { |
138 | mutex_lock(&codec->cache_rw_mutex); | 138 | mutex_lock(&codec->cache_rw_mutex); |
139 | snd_soc_set_cache_val(codec->reg_cache, reg, value, | 139 | if (!ZERO_OR_NULL_PTR(codec->reg_cache)) |
140 | codec->driver->reg_word_size); | 140 | snd_soc_set_cache_val(codec->reg_cache, reg, value, |
141 | codec->driver->reg_word_size); | ||
141 | mutex_unlock(&codec->cache_rw_mutex); | 142 | mutex_unlock(&codec->cache_rw_mutex); |
142 | 143 | ||
143 | return 0; | 144 | return 0; |
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 5e9690c85d8f..91083e6a6b38 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c | |||
@@ -30,8 +30,6 @@ static int soc_compr_open(struct snd_compr_stream *cstream) | |||
30 | { | 30 | { |
31 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | 31 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; |
32 | struct snd_soc_platform *platform = rtd->platform; | 32 | struct snd_soc_platform *platform = rtd->platform; |
33 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
34 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
35 | int ret = 0; | 33 | int ret = 0; |
36 | 34 | ||
37 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 35 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
@@ -52,17 +50,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) | |||
52 | } | 50 | } |
53 | } | 51 | } |
54 | 52 | ||
55 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | 53 | snd_soc_runtime_activate(rtd, cstream->direction); |
56 | cpu_dai->playback_active++; | ||
57 | codec_dai->playback_active++; | ||
58 | } else { | ||
59 | cpu_dai->capture_active++; | ||
60 | codec_dai->capture_active++; | ||
61 | } | ||
62 | |||
63 | cpu_dai->active++; | ||
64 | codec_dai->active++; | ||
65 | rtd->codec->active++; | ||
66 | 54 | ||
67 | mutex_unlock(&rtd->pcm_mutex); | 55 | mutex_unlock(&rtd->pcm_mutex); |
68 | 56 | ||
@@ -81,8 +69,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) | |||
81 | struct snd_soc_pcm_runtime *fe = cstream->private_data; | 69 | struct snd_soc_pcm_runtime *fe = cstream->private_data; |
82 | struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; | 70 | struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; |
83 | struct snd_soc_platform *platform = fe->platform; | 71 | struct snd_soc_platform *platform = fe->platform; |
84 | struct snd_soc_dai *cpu_dai = fe->cpu_dai; | ||
85 | struct snd_soc_dai *codec_dai = fe->codec_dai; | ||
86 | struct snd_soc_dpcm *dpcm; | 72 | struct snd_soc_dpcm *dpcm; |
87 | struct snd_soc_dapm_widget_list *list; | 73 | struct snd_soc_dapm_widget_list *list; |
88 | int stream; | 74 | int stream; |
@@ -140,17 +126,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) | |||
140 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; | 126 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; |
141 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | 127 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; |
142 | 128 | ||
143 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | 129 | snd_soc_runtime_activate(fe, stream); |
144 | cpu_dai->playback_active++; | ||
145 | codec_dai->playback_active++; | ||
146 | } else { | ||
147 | cpu_dai->capture_active++; | ||
148 | codec_dai->capture_active++; | ||
149 | } | ||
150 | |||
151 | cpu_dai->active++; | ||
152 | codec_dai->active++; | ||
153 | fe->codec->active++; | ||
154 | 130 | ||
155 | mutex_unlock(&fe->card->mutex); | 131 | mutex_unlock(&fe->card->mutex); |
156 | 132 | ||
@@ -202,23 +178,18 @@ static int soc_compr_free(struct snd_compr_stream *cstream) | |||
202 | struct snd_soc_platform *platform = rtd->platform; | 178 | struct snd_soc_platform *platform = rtd->platform; |
203 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 179 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
204 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 180 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
205 | struct snd_soc_codec *codec = rtd->codec; | 181 | int stream; |
206 | 182 | ||
207 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 183 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
208 | 184 | ||
209 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | 185 | if (cstream->direction == SND_COMPRESS_PLAYBACK) |
210 | cpu_dai->playback_active--; | 186 | stream = SNDRV_PCM_STREAM_PLAYBACK; |
211 | codec_dai->playback_active--; | 187 | else |
212 | } else { | 188 | stream = SNDRV_PCM_STREAM_CAPTURE; |
213 | cpu_dai->capture_active--; | ||
214 | codec_dai->capture_active--; | ||
215 | } | ||
216 | 189 | ||
217 | snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); | 190 | snd_soc_runtime_deactivate(rtd, stream); |
218 | 191 | ||
219 | cpu_dai->active--; | 192 | snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); |
220 | codec_dai->active--; | ||
221 | codec->active--; | ||
222 | 193 | ||
223 | if (!cpu_dai->active) | 194 | if (!cpu_dai->active) |
224 | cpu_dai->rate = 0; | 195 | cpu_dai->rate = 0; |
@@ -235,8 +206,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) | |||
235 | cpu_dai->runtime = NULL; | 206 | cpu_dai->runtime = NULL; |
236 | 207 | ||
237 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | 208 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { |
238 | if (!rtd->pmdown_time || codec->ignore_pmdown_time || | 209 | if (snd_soc_runtime_ignore_pmdown_time(rtd)) { |
239 | rtd->dai_link->ignore_pmdown_time) { | ||
240 | snd_soc_dapm_stream_event(rtd, | 210 | snd_soc_dapm_stream_event(rtd, |
241 | SNDRV_PCM_STREAM_PLAYBACK, | 211 | SNDRV_PCM_STREAM_PLAYBACK, |
242 | SND_SOC_DAPM_STREAM_STOP); | 212 | SND_SOC_DAPM_STREAM_STOP); |
@@ -261,26 +231,17 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) | |||
261 | { | 231 | { |
262 | struct snd_soc_pcm_runtime *fe = cstream->private_data; | 232 | struct snd_soc_pcm_runtime *fe = cstream->private_data; |
263 | struct snd_soc_platform *platform = fe->platform; | 233 | struct snd_soc_platform *platform = fe->platform; |
264 | struct snd_soc_dai *cpu_dai = fe->cpu_dai; | ||
265 | struct snd_soc_dai *codec_dai = fe->codec_dai; | ||
266 | struct snd_soc_dpcm *dpcm; | 234 | struct snd_soc_dpcm *dpcm; |
267 | int stream, ret; | 235 | int stream, ret; |
268 | 236 | ||
269 | mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); | 237 | mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); |
270 | 238 | ||
271 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | 239 | if (cstream->direction == SND_COMPRESS_PLAYBACK) |
272 | stream = SNDRV_PCM_STREAM_PLAYBACK; | 240 | stream = SNDRV_PCM_STREAM_PLAYBACK; |
273 | cpu_dai->playback_active--; | 241 | else |
274 | codec_dai->playback_active--; | ||
275 | } else { | ||
276 | stream = SNDRV_PCM_STREAM_CAPTURE; | 242 | stream = SNDRV_PCM_STREAM_CAPTURE; |
277 | cpu_dai->capture_active--; | ||
278 | codec_dai->capture_active--; | ||
279 | } | ||
280 | 243 | ||
281 | cpu_dai->active--; | 244 | snd_soc_runtime_deactivate(fe, stream); |
282 | codec_dai->active--; | ||
283 | fe->codec->active--; | ||
284 | 245 | ||
285 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; | 246 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; |
286 | 247 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a3..b322cf294d06 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -56,7 +56,6 @@ EXPORT_SYMBOL_GPL(snd_soc_debugfs_root); | |||
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | static DEFINE_MUTEX(client_mutex); | 58 | static DEFINE_MUTEX(client_mutex); |
59 | static LIST_HEAD(dai_list); | ||
60 | static LIST_HEAD(platform_list); | 59 | static LIST_HEAD(platform_list); |
61 | static LIST_HEAD(codec_list); | 60 | static LIST_HEAD(codec_list); |
62 | static LIST_HEAD(component_list); | 61 | static LIST_HEAD(component_list); |
@@ -370,18 +369,22 @@ static ssize_t dai_list_read_file(struct file *file, char __user *user_buf, | |||
370 | { | 369 | { |
371 | char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 370 | char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
372 | ssize_t len, ret = 0; | 371 | ssize_t len, ret = 0; |
372 | struct snd_soc_component *component; | ||
373 | struct snd_soc_dai *dai; | 373 | struct snd_soc_dai *dai; |
374 | 374 | ||
375 | if (!buf) | 375 | if (!buf) |
376 | return -ENOMEM; | 376 | return -ENOMEM; |
377 | 377 | ||
378 | list_for_each_entry(dai, &dai_list, list) { | 378 | list_for_each_entry(component, &component_list, list) { |
379 | len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", dai->name); | 379 | list_for_each_entry(dai, &component->dai_list, list) { |
380 | if (len >= 0) | 380 | len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", |
381 | ret += len; | 381 | dai->name); |
382 | if (ret > PAGE_SIZE) { | 382 | if (len >= 0) |
383 | ret = PAGE_SIZE; | 383 | ret += len; |
384 | break; | 384 | if (ret > PAGE_SIZE) { |
385 | ret = PAGE_SIZE; | ||
386 | break; | ||
387 | } | ||
385 | } | 388 | } |
386 | } | 389 | } |
387 | 390 | ||
@@ -855,6 +858,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
855 | { | 858 | { |
856 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 859 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
857 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 860 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
861 | struct snd_soc_component *component; | ||
858 | struct snd_soc_codec *codec; | 862 | struct snd_soc_codec *codec; |
859 | struct snd_soc_platform *platform; | 863 | struct snd_soc_platform *platform; |
860 | struct snd_soc_dai *codec_dai, *cpu_dai; | 864 | struct snd_soc_dai *codec_dai, *cpu_dai; |
@@ -863,18 +867,20 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
863 | dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); | 867 | dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); |
864 | 868 | ||
865 | /* Find CPU DAI from registered DAIs*/ | 869 | /* Find CPU DAI from registered DAIs*/ |
866 | list_for_each_entry(cpu_dai, &dai_list, list) { | 870 | list_for_each_entry(component, &component_list, list) { |
867 | if (dai_link->cpu_of_node && | 871 | if (dai_link->cpu_of_node && |
868 | (cpu_dai->dev->of_node != dai_link->cpu_of_node)) | 872 | component->dev->of_node != dai_link->cpu_of_node) |
869 | continue; | 873 | continue; |
870 | if (dai_link->cpu_name && | 874 | if (dai_link->cpu_name && |
871 | strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name)) | 875 | strcmp(dev_name(component->dev), dai_link->cpu_name)) |
872 | continue; | ||
873 | if (dai_link->cpu_dai_name && | ||
874 | strcmp(cpu_dai->name, dai_link->cpu_dai_name)) | ||
875 | continue; | 876 | continue; |
877 | list_for_each_entry(cpu_dai, &component->dai_list, list) { | ||
878 | if (dai_link->cpu_dai_name && | ||
879 | strcmp(cpu_dai->name, dai_link->cpu_dai_name)) | ||
880 | continue; | ||
876 | 881 | ||
877 | rtd->cpu_dai = cpu_dai; | 882 | rtd->cpu_dai = cpu_dai; |
883 | } | ||
878 | } | 884 | } |
879 | 885 | ||
880 | if (!rtd->cpu_dai) { | 886 | if (!rtd->cpu_dai) { |
@@ -899,12 +905,10 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
899 | * CODEC found, so find CODEC DAI from registered DAIs from | 905 | * CODEC found, so find CODEC DAI from registered DAIs from |
900 | * this CODEC | 906 | * this CODEC |
901 | */ | 907 | */ |
902 | list_for_each_entry(codec_dai, &dai_list, list) { | 908 | list_for_each_entry(codec_dai, &codec->component.dai_list, list) { |
903 | if (codec->dev == codec_dai->dev && | 909 | if (!strcmp(codec_dai->name, dai_link->codec_dai_name)) { |
904 | !strcmp(codec_dai->name, | ||
905 | dai_link->codec_dai_name)) { | ||
906 | |||
907 | rtd->codec_dai = codec_dai; | 910 | rtd->codec_dai = codec_dai; |
911 | break; | ||
908 | } | 912 | } |
909 | } | 913 | } |
910 | 914 | ||
@@ -1128,15 +1132,21 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1128 | driver->num_dapm_widgets); | 1132 | driver->num_dapm_widgets); |
1129 | 1133 | ||
1130 | /* Create DAPM widgets for each DAI stream */ | 1134 | /* Create DAPM widgets for each DAI stream */ |
1131 | list_for_each_entry(dai, &dai_list, list) { | 1135 | list_for_each_entry(dai, &codec->component.dai_list, list) |
1132 | if (dai->dev != codec->dev) | ||
1133 | continue; | ||
1134 | |||
1135 | snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); | 1136 | snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); |
1136 | } | ||
1137 | 1137 | ||
1138 | codec->dapm.idle_bias_off = driver->idle_bias_off; | 1138 | codec->dapm.idle_bias_off = driver->idle_bias_off; |
1139 | 1139 | ||
1140 | if (!codec->write && dev_get_regmap(codec->dev, NULL)) { | ||
1141 | /* Set the default I/O up try regmap */ | ||
1142 | ret = snd_soc_codec_set_cache_io(codec, NULL); | ||
1143 | if (ret < 0) { | ||
1144 | dev_err(codec->dev, | ||
1145 | "Failed to set cache I/O: %d\n", ret); | ||
1146 | goto err_probe; | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1140 | if (driver->probe) { | 1150 | if (driver->probe) { |
1141 | ret = driver->probe(codec); | 1151 | ret = driver->probe(codec); |
1142 | if (ret < 0) { | 1152 | if (ret < 0) { |
@@ -1150,10 +1160,6 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1150 | codec->name); | 1160 | codec->name); |
1151 | } | 1161 | } |
1152 | 1162 | ||
1153 | /* If the driver didn't set I/O up try regmap */ | ||
1154 | if (!codec->write && dev_get_regmap(codec->dev, NULL)) | ||
1155 | snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
1156 | |||
1157 | if (driver->controls) | 1163 | if (driver->controls) |
1158 | snd_soc_add_codec_controls(codec, driver->controls, | 1164 | snd_soc_add_codec_controls(codec, driver->controls, |
1159 | driver->num_controls); | 1165 | driver->num_controls); |
@@ -1180,6 +1186,7 @@ static int soc_probe_platform(struct snd_soc_card *card, | |||
1180 | { | 1186 | { |
1181 | int ret = 0; | 1187 | int ret = 0; |
1182 | const struct snd_soc_platform_driver *driver = platform->driver; | 1188 | const struct snd_soc_platform_driver *driver = platform->driver; |
1189 | struct snd_soc_component *component; | ||
1183 | struct snd_soc_dai *dai; | 1190 | struct snd_soc_dai *dai; |
1184 | 1191 | ||
1185 | platform->card = card; | 1192 | platform->card = card; |
@@ -1195,11 +1202,11 @@ static int soc_probe_platform(struct snd_soc_card *card, | |||
1195 | driver->dapm_widgets, driver->num_dapm_widgets); | 1202 | driver->dapm_widgets, driver->num_dapm_widgets); |
1196 | 1203 | ||
1197 | /* Create DAPM widgets for each DAI stream */ | 1204 | /* Create DAPM widgets for each DAI stream */ |
1198 | list_for_each_entry(dai, &dai_list, list) { | 1205 | list_for_each_entry(component, &component_list, list) { |
1199 | if (dai->dev != platform->dev) | 1206 | if (component->dev != platform->dev) |
1200 | continue; | 1207 | continue; |
1201 | 1208 | list_for_each_entry(dai, &component->dai_list, list) | |
1202 | snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); | 1209 | snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); |
1203 | } | 1210 | } |
1204 | 1211 | ||
1205 | platform->dapm.idle_bias_off = 1; | 1212 | platform->dapm.idle_bias_off = 1; |
@@ -2571,10 +2578,10 @@ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, | |||
2571 | 2578 | ||
2572 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2579 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2573 | uinfo->count = e->shift_l == e->shift_r ? 1 : 2; | 2580 | uinfo->count = e->shift_l == e->shift_r ? 1 : 2; |
2574 | uinfo->value.enumerated.items = e->max; | 2581 | uinfo->value.enumerated.items = e->items; |
2575 | 2582 | ||
2576 | if (uinfo->value.enumerated.item > e->max - 1) | 2583 | if (uinfo->value.enumerated.item >= e->items) |
2577 | uinfo->value.enumerated.item = e->max - 1; | 2584 | uinfo->value.enumerated.item = e->items - 1; |
2578 | strlcpy(uinfo->value.enumerated.name, | 2585 | strlcpy(uinfo->value.enumerated.name, |
2579 | e->texts[uinfo->value.enumerated.item], | 2586 | e->texts[uinfo->value.enumerated.item], |
2580 | sizeof(uinfo->value.enumerated.name)); | 2587 | sizeof(uinfo->value.enumerated.name)); |
@@ -2596,14 +2603,18 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, | |||
2596 | { | 2603 | { |
2597 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2604 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2598 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2605 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2599 | unsigned int val; | 2606 | unsigned int val, item; |
2607 | unsigned int reg_val; | ||
2600 | 2608 | ||
2601 | val = snd_soc_read(codec, e->reg); | 2609 | reg_val = snd_soc_read(codec, e->reg); |
2602 | ucontrol->value.enumerated.item[0] | 2610 | val = (reg_val >> e->shift_l) & e->mask; |
2603 | = (val >> e->shift_l) & e->mask; | 2611 | item = snd_soc_enum_val_to_item(e, val); |
2604 | if (e->shift_l != e->shift_r) | 2612 | ucontrol->value.enumerated.item[0] = item; |
2605 | ucontrol->value.enumerated.item[1] = | 2613 | if (e->shift_l != e->shift_r) { |
2606 | (val >> e->shift_r) & e->mask; | 2614 | val = (reg_val >> e->shift_l) & e->mask; |
2615 | item = snd_soc_enum_val_to_item(e, val); | ||
2616 | ucontrol->value.enumerated.item[1] = item; | ||
2617 | } | ||
2607 | 2618 | ||
2608 | return 0; | 2619 | return 0; |
2609 | } | 2620 | } |
@@ -2623,17 +2634,18 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2623 | { | 2634 | { |
2624 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2635 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2625 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2636 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2637 | unsigned int *item = ucontrol->value.enumerated.item; | ||
2626 | unsigned int val; | 2638 | unsigned int val; |
2627 | unsigned int mask; | 2639 | unsigned int mask; |
2628 | 2640 | ||
2629 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2641 | if (item[0] >= e->items) |
2630 | return -EINVAL; | 2642 | return -EINVAL; |
2631 | val = ucontrol->value.enumerated.item[0] << e->shift_l; | 2643 | val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; |
2632 | mask = e->mask << e->shift_l; | 2644 | mask = e->mask << e->shift_l; |
2633 | if (e->shift_l != e->shift_r) { | 2645 | if (e->shift_l != e->shift_r) { |
2634 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | 2646 | if (item[1] >= e->items) |
2635 | return -EINVAL; | 2647 | return -EINVAL; |
2636 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 2648 | val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; |
2637 | mask |= e->mask << e->shift_r; | 2649 | mask |= e->mask << e->shift_r; |
2638 | } | 2650 | } |
2639 | 2651 | ||
@@ -2642,78 +2654,46 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2642 | EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); | 2654 | EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); |
2643 | 2655 | ||
2644 | /** | 2656 | /** |
2645 | * snd_soc_get_value_enum_double - semi enumerated double mixer get callback | 2657 | * snd_soc_read_signed - Read a codec register and interprete as signed value |
2646 | * @kcontrol: mixer control | 2658 | * @codec: codec |
2647 | * @ucontrol: control element information | 2659 | * @reg: Register to read |
2660 | * @mask: Mask to use after shifting the register value | ||
2661 | * @shift: Right shift of register value | ||
2662 | * @sign_bit: Bit that describes if a number is negative or not. | ||
2648 | * | 2663 | * |
2649 | * Callback to get the value of a double semi enumerated mixer. | 2664 | * This functions reads a codec register. The register value is shifted right |
2665 | * by 'shift' bits and masked with the given 'mask'. Afterwards it translates | ||
2666 | * the given registervalue into a signed integer if sign_bit is non-zero. | ||
2650 | * | 2667 | * |
2651 | * Semi enumerated mixer: the enumerated items are referred as values. Can be | 2668 | * Returns the register value as signed int. |
2652 | * used for handling bitfield coded enumeration for example. | ||
2653 | * | ||
2654 | * Returns 0 for success. | ||
2655 | */ | 2669 | */ |
2656 | int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, | 2670 | static int snd_soc_read_signed(struct snd_soc_codec *codec, unsigned int reg, |
2657 | struct snd_ctl_elem_value *ucontrol) | 2671 | unsigned int mask, unsigned int shift, unsigned int sign_bit) |
2658 | { | 2672 | { |
2659 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2673 | int ret; |
2660 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2674 | unsigned int val; |
2661 | unsigned int reg_val, val, mux; | ||
2662 | 2675 | ||
2663 | reg_val = snd_soc_read(codec, e->reg); | 2676 | val = (snd_soc_read(codec, reg) >> shift) & mask; |
2664 | val = (reg_val >> e->shift_l) & e->mask; | ||
2665 | for (mux = 0; mux < e->max; mux++) { | ||
2666 | if (val == e->values[mux]) | ||
2667 | break; | ||
2668 | } | ||
2669 | ucontrol->value.enumerated.item[0] = mux; | ||
2670 | if (e->shift_l != e->shift_r) { | ||
2671 | val = (reg_val >> e->shift_r) & e->mask; | ||
2672 | for (mux = 0; mux < e->max; mux++) { | ||
2673 | if (val == e->values[mux]) | ||
2674 | break; | ||
2675 | } | ||
2676 | ucontrol->value.enumerated.item[1] = mux; | ||
2677 | } | ||
2678 | 2677 | ||
2679 | return 0; | 2678 | if (!sign_bit) |
2680 | } | 2679 | return val; |
2681 | EXPORT_SYMBOL_GPL(snd_soc_get_value_enum_double); | ||
2682 | 2680 | ||
2683 | /** | 2681 | /* non-negative number */ |
2684 | * snd_soc_put_value_enum_double - semi enumerated double mixer put callback | 2682 | if (!(val & BIT(sign_bit))) |
2685 | * @kcontrol: mixer control | 2683 | return val; |
2686 | * @ucontrol: control element information | ||
2687 | * | ||
2688 | * Callback to set the value of a double semi enumerated mixer. | ||
2689 | * | ||
2690 | * Semi enumerated mixer: the enumerated items are referred as values. Can be | ||
2691 | * used for handling bitfield coded enumeration for example. | ||
2692 | * | ||
2693 | * Returns 0 for success. | ||
2694 | */ | ||
2695 | int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, | ||
2696 | struct snd_ctl_elem_value *ucontrol) | ||
2697 | { | ||
2698 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2699 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
2700 | unsigned int val; | ||
2701 | unsigned int mask; | ||
2702 | 2684 | ||
2703 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2685 | ret = val; |
2704 | return -EINVAL; | ||
2705 | val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; | ||
2706 | mask = e->mask << e->shift_l; | ||
2707 | if (e->shift_l != e->shift_r) { | ||
2708 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | ||
2709 | return -EINVAL; | ||
2710 | val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; | ||
2711 | mask |= e->mask << e->shift_r; | ||
2712 | } | ||
2713 | 2686 | ||
2714 | return snd_soc_update_bits_locked(codec, e->reg, mask, val); | 2687 | /* |
2688 | * The register most probably does not contain a full-sized int. | ||
2689 | * Instead we have an arbitrary number of bits in a signed | ||
2690 | * representation which has to be translated into a full-sized int. | ||
2691 | * This is done by filling up all bits above the sign-bit. | ||
2692 | */ | ||
2693 | ret |= ~((int)(BIT(sign_bit) - 1)); | ||
2694 | |||
2695 | return ret; | ||
2715 | } | 2696 | } |
2716 | EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); | ||
2717 | 2697 | ||
2718 | /** | 2698 | /** |
2719 | * snd_soc_info_volsw - single mixer info callback | 2699 | * snd_soc_info_volsw - single mixer info callback |
@@ -2743,7 +2723,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, | |||
2743 | 2723 | ||
2744 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; | 2724 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; |
2745 | uinfo->value.integer.min = 0; | 2725 | uinfo->value.integer.min = 0; |
2746 | uinfo->value.integer.max = platform_max; | 2726 | uinfo->value.integer.max = platform_max - mc->min; |
2747 | return 0; | 2727 | return 0; |
2748 | } | 2728 | } |
2749 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); | 2729 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); |
@@ -2769,11 +2749,16 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | |||
2769 | unsigned int shift = mc->shift; | 2749 | unsigned int shift = mc->shift; |
2770 | unsigned int rshift = mc->rshift; | 2750 | unsigned int rshift = mc->rshift; |
2771 | int max = mc->max; | 2751 | int max = mc->max; |
2752 | int min = mc->min; | ||
2753 | int sign_bit = mc->sign_bit; | ||
2772 | unsigned int mask = (1 << fls(max)) - 1; | 2754 | unsigned int mask = (1 << fls(max)) - 1; |
2773 | unsigned int invert = mc->invert; | 2755 | unsigned int invert = mc->invert; |
2774 | 2756 | ||
2775 | ucontrol->value.integer.value[0] = | 2757 | if (sign_bit) |
2776 | (snd_soc_read(codec, reg) >> shift) & mask; | 2758 | mask = BIT(sign_bit + 1) - 1; |
2759 | |||
2760 | ucontrol->value.integer.value[0] = snd_soc_read_signed(codec, reg, mask, | ||
2761 | shift, sign_bit) - min; | ||
2777 | if (invert) | 2762 | if (invert) |
2778 | ucontrol->value.integer.value[0] = | 2763 | ucontrol->value.integer.value[0] = |
2779 | max - ucontrol->value.integer.value[0]; | 2764 | max - ucontrol->value.integer.value[0]; |
@@ -2781,10 +2766,12 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | |||
2781 | if (snd_soc_volsw_is_stereo(mc)) { | 2766 | if (snd_soc_volsw_is_stereo(mc)) { |
2782 | if (reg == reg2) | 2767 | if (reg == reg2) |
2783 | ucontrol->value.integer.value[1] = | 2768 | ucontrol->value.integer.value[1] = |
2784 | (snd_soc_read(codec, reg) >> rshift) & mask; | 2769 | snd_soc_read_signed(codec, reg, mask, rshift, |
2770 | sign_bit) - min; | ||
2785 | else | 2771 | else |
2786 | ucontrol->value.integer.value[1] = | 2772 | ucontrol->value.integer.value[1] = |
2787 | (snd_soc_read(codec, reg2) >> shift) & mask; | 2773 | snd_soc_read_signed(codec, reg2, mask, shift, |
2774 | sign_bit) - min; | ||
2788 | if (invert) | 2775 | if (invert) |
2789 | ucontrol->value.integer.value[1] = | 2776 | ucontrol->value.integer.value[1] = |
2790 | max - ucontrol->value.integer.value[1]; | 2777 | max - ucontrol->value.integer.value[1]; |
@@ -2815,20 +2802,25 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | |||
2815 | unsigned int shift = mc->shift; | 2802 | unsigned int shift = mc->shift; |
2816 | unsigned int rshift = mc->rshift; | 2803 | unsigned int rshift = mc->rshift; |
2817 | int max = mc->max; | 2804 | int max = mc->max; |
2805 | int min = mc->min; | ||
2806 | unsigned int sign_bit = mc->sign_bit; | ||
2818 | unsigned int mask = (1 << fls(max)) - 1; | 2807 | unsigned int mask = (1 << fls(max)) - 1; |
2819 | unsigned int invert = mc->invert; | 2808 | unsigned int invert = mc->invert; |
2820 | int err; | 2809 | int err; |
2821 | bool type_2r = 0; | 2810 | bool type_2r = false; |
2822 | unsigned int val2 = 0; | 2811 | unsigned int val2 = 0; |
2823 | unsigned int val, val_mask; | 2812 | unsigned int val, val_mask; |
2824 | 2813 | ||
2825 | val = (ucontrol->value.integer.value[0] & mask); | 2814 | if (sign_bit) |
2815 | mask = BIT(sign_bit + 1) - 1; | ||
2816 | |||
2817 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
2826 | if (invert) | 2818 | if (invert) |
2827 | val = max - val; | 2819 | val = max - val; |
2828 | val_mask = mask << shift; | 2820 | val_mask = mask << shift; |
2829 | val = val << shift; | 2821 | val = val << shift; |
2830 | if (snd_soc_volsw_is_stereo(mc)) { | 2822 | if (snd_soc_volsw_is_stereo(mc)) { |
2831 | val2 = (ucontrol->value.integer.value[1] & mask); | 2823 | val2 = ((ucontrol->value.integer.value[1] + min) & mask); |
2832 | if (invert) | 2824 | if (invert) |
2833 | val2 = max - val2; | 2825 | val2 = max - val2; |
2834 | if (reg == reg2) { | 2826 | if (reg == reg2) { |
@@ -2836,7 +2828,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | |||
2836 | val |= val2 << rshift; | 2828 | val |= val2 << rshift; |
2837 | } else { | 2829 | } else { |
2838 | val2 = val2 << shift; | 2830 | val2 = val2 << shift; |
2839 | type_2r = 1; | 2831 | type_2r = true; |
2840 | } | 2832 | } |
2841 | } | 2833 | } |
2842 | err = snd_soc_update_bits_locked(codec, reg, val_mask, val); | 2834 | err = snd_soc_update_bits_locked(codec, reg, val_mask, val); |
@@ -3234,7 +3226,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, | |||
3234 | struct soc_bytes *params = (void *)kcontrol->private_value; | 3226 | struct soc_bytes *params = (void *)kcontrol->private_value; |
3235 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 3227 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
3236 | int ret, len; | 3228 | int ret, len; |
3237 | unsigned int val; | 3229 | unsigned int val, mask; |
3238 | void *data; | 3230 | void *data; |
3239 | 3231 | ||
3240 | if (!codec->using_regmap) | 3232 | if (!codec->using_regmap) |
@@ -3264,12 +3256,36 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, | |||
3264 | ((u8 *)data)[0] |= val; | 3256 | ((u8 *)data)[0] |= val; |
3265 | break; | 3257 | break; |
3266 | case 2: | 3258 | case 2: |
3267 | ((u16 *)data)[0] &= cpu_to_be16(~params->mask); | 3259 | mask = ~params->mask; |
3268 | ((u16 *)data)[0] |= cpu_to_be16(val); | 3260 | ret = regmap_parse_val(codec->control_data, |
3261 | &mask, &mask); | ||
3262 | if (ret != 0) | ||
3263 | goto out; | ||
3264 | |||
3265 | ((u16 *)data)[0] &= mask; | ||
3266 | |||
3267 | ret = regmap_parse_val(codec->control_data, | ||
3268 | &val, &val); | ||
3269 | if (ret != 0) | ||
3270 | goto out; | ||
3271 | |||
3272 | ((u16 *)data)[0] |= val; | ||
3269 | break; | 3273 | break; |
3270 | case 4: | 3274 | case 4: |
3271 | ((u32 *)data)[0] &= cpu_to_be32(~params->mask); | 3275 | mask = ~params->mask; |
3272 | ((u32 *)data)[0] |= cpu_to_be32(val); | 3276 | ret = regmap_parse_val(codec->control_data, |
3277 | &mask, &mask); | ||
3278 | if (ret != 0) | ||
3279 | goto out; | ||
3280 | |||
3281 | ((u32 *)data)[0] &= mask; | ||
3282 | |||
3283 | ret = regmap_parse_val(codec->control_data, | ||
3284 | &val, &val); | ||
3285 | if (ret != 0) | ||
3286 | goto out; | ||
3287 | |||
3288 | ((u32 *)data)[0] |= val; | ||
3273 | break; | 3289 | break; |
3274 | default: | 3290 | default: |
3275 | ret = -EINVAL; | 3291 | ret = -EINVAL; |
@@ -3609,6 +3625,30 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
3609 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); | 3625 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); |
3610 | 3626 | ||
3611 | /** | 3627 | /** |
3628 | * snd_soc_of_xlate_tdm_slot - generate tx/rx slot mask. | ||
3629 | * @slots: Number of slots in use. | ||
3630 | * @tx_mask: bitmask representing active TX slots. | ||
3631 | * @rx_mask: bitmask representing active RX slots. | ||
3632 | * | ||
3633 | * Generates the TDM tx and rx slot default masks for DAI. | ||
3634 | */ | ||
3635 | static int snd_soc_of_xlate_tdm_slot_mask(unsigned int slots, | ||
3636 | unsigned int *tx_mask, | ||
3637 | unsigned int *rx_mask) | ||
3638 | { | ||
3639 | if (*tx_mask || *rx_mask) | ||
3640 | return 0; | ||
3641 | |||
3642 | if (!slots) | ||
3643 | return -EINVAL; | ||
3644 | |||
3645 | *tx_mask = (1 << slots) - 1; | ||
3646 | *rx_mask = (1 << slots) - 1; | ||
3647 | |||
3648 | return 0; | ||
3649 | } | ||
3650 | |||
3651 | /** | ||
3612 | * snd_soc_dai_set_tdm_slot - configure DAI TDM. | 3652 | * snd_soc_dai_set_tdm_slot - configure DAI TDM. |
3613 | * @dai: DAI | 3653 | * @dai: DAI |
3614 | * @tx_mask: bitmask representing active TX slots. | 3654 | * @tx_mask: bitmask representing active TX slots. |
@@ -3622,11 +3662,17 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); | |||
3622 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | 3662 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, |
3623 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) | 3663 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) |
3624 | { | 3664 | { |
3665 | if (dai->driver && dai->driver->ops->of_xlate_tdm_slot_mask) | ||
3666 | dai->driver->ops->of_xlate_tdm_slot_mask(slots, | ||
3667 | &tx_mask, &rx_mask); | ||
3668 | else | ||
3669 | snd_soc_of_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); | ||
3670 | |||
3625 | if (dai->driver && dai->driver->ops->set_tdm_slot) | 3671 | if (dai->driver && dai->driver->ops->set_tdm_slot) |
3626 | return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, | 3672 | return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, |
3627 | slots, slot_width); | 3673 | slots, slot_width); |
3628 | else | 3674 | else |
3629 | return -EINVAL; | 3675 | return -ENOTSUPP; |
3630 | } | 3676 | } |
3631 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); | 3677 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); |
3632 | 3678 | ||
@@ -3882,95 +3928,42 @@ static inline char *fmt_multiple_name(struct device *dev, | |||
3882 | } | 3928 | } |
3883 | 3929 | ||
3884 | /** | 3930 | /** |
3885 | * snd_soc_register_dai - Register a DAI with the ASoC core | 3931 | * snd_soc_unregister_dai - Unregister DAIs from the ASoC core |
3886 | * | 3932 | * |
3887 | * @dai: DAI to register | 3933 | * @component: The component for which the DAIs should be unregistered |
3888 | */ | 3934 | */ |
3889 | static int snd_soc_register_dai(struct device *dev, | 3935 | static void snd_soc_unregister_dais(struct snd_soc_component *component) |
3890 | struct snd_soc_dai_driver *dai_drv) | ||
3891 | { | 3936 | { |
3892 | struct snd_soc_codec *codec; | 3937 | struct snd_soc_dai *dai, *_dai; |
3893 | struct snd_soc_dai *dai; | ||
3894 | |||
3895 | dev_dbg(dev, "ASoC: dai register %s\n", dev_name(dev)); | ||
3896 | 3938 | ||
3897 | dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); | 3939 | list_for_each_entry_safe(dai, _dai, &component->dai_list, list) { |
3898 | if (dai == NULL) | 3940 | dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n", |
3899 | return -ENOMEM; | 3941 | dai->name); |
3900 | 3942 | list_del(&dai->list); | |
3901 | /* create DAI component name */ | 3943 | kfree(dai->name); |
3902 | dai->name = fmt_single_name(dev, &dai->id); | ||
3903 | if (dai->name == NULL) { | ||
3904 | kfree(dai); | 3944 | kfree(dai); |
3905 | return -ENOMEM; | ||
3906 | } | 3945 | } |
3907 | |||
3908 | dai->dev = dev; | ||
3909 | dai->driver = dai_drv; | ||
3910 | dai->dapm.dev = dev; | ||
3911 | if (!dai->driver->ops) | ||
3912 | dai->driver->ops = &null_dai_ops; | ||
3913 | |||
3914 | mutex_lock(&client_mutex); | ||
3915 | |||
3916 | list_for_each_entry(codec, &codec_list, list) { | ||
3917 | if (codec->dev == dev) { | ||
3918 | dev_dbg(dev, "ASoC: Mapped DAI %s to CODEC %s\n", | ||
3919 | dai->name, codec->name); | ||
3920 | dai->codec = codec; | ||
3921 | break; | ||
3922 | } | ||
3923 | } | ||
3924 | |||
3925 | if (!dai->codec) | ||
3926 | dai->dapm.idle_bias_off = 1; | ||
3927 | |||
3928 | list_add(&dai->list, &dai_list); | ||
3929 | |||
3930 | mutex_unlock(&client_mutex); | ||
3931 | |||
3932 | dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); | ||
3933 | |||
3934 | return 0; | ||
3935 | } | ||
3936 | |||
3937 | /** | ||
3938 | * snd_soc_unregister_dai - Unregister a DAI from the ASoC core | ||
3939 | * | ||
3940 | * @dai: DAI to unregister | ||
3941 | */ | ||
3942 | static void snd_soc_unregister_dai(struct device *dev) | ||
3943 | { | ||
3944 | struct snd_soc_dai *dai; | ||
3945 | |||
3946 | list_for_each_entry(dai, &dai_list, list) { | ||
3947 | if (dev == dai->dev) | ||
3948 | goto found; | ||
3949 | } | ||
3950 | return; | ||
3951 | |||
3952 | found: | ||
3953 | mutex_lock(&client_mutex); | ||
3954 | list_del(&dai->list); | ||
3955 | mutex_unlock(&client_mutex); | ||
3956 | |||
3957 | dev_dbg(dev, "ASoC: Unregistered DAI '%s'\n", dai->name); | ||
3958 | kfree(dai->name); | ||
3959 | kfree(dai); | ||
3960 | } | 3946 | } |
3961 | 3947 | ||
3962 | /** | 3948 | /** |
3963 | * snd_soc_register_dais - Register multiple DAIs with the ASoC core | 3949 | * snd_soc_register_dais - Register a DAI with the ASoC core |
3964 | * | 3950 | * |
3965 | * @dai: Array of DAIs to register | 3951 | * @component: The component the DAIs are registered for |
3952 | * @codec: The CODEC that the DAIs are registered for, NULL if the component is | ||
3953 | * not a CODEC. | ||
3954 | * @dai_drv: DAI driver to use for the DAIs | ||
3966 | * @count: Number of DAIs | 3955 | * @count: Number of DAIs |
3956 | * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the | ||
3957 | * parent's name. | ||
3967 | */ | 3958 | */ |
3968 | static int snd_soc_register_dais(struct device *dev, | 3959 | static int snd_soc_register_dais(struct snd_soc_component *component, |
3969 | struct snd_soc_dai_driver *dai_drv, size_t count) | 3960 | struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv, |
3961 | size_t count, bool legacy_dai_naming) | ||
3970 | { | 3962 | { |
3971 | struct snd_soc_codec *codec; | 3963 | struct device *dev = component->dev; |
3972 | struct snd_soc_dai *dai; | 3964 | struct snd_soc_dai *dai; |
3973 | int i, ret = 0; | 3965 | unsigned int i; |
3966 | int ret; | ||
3974 | 3967 | ||
3975 | dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); | 3968 | dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); |
3976 | 3969 | ||
@@ -3982,70 +3975,54 @@ static int snd_soc_register_dais(struct device *dev, | |||
3982 | goto err; | 3975 | goto err; |
3983 | } | 3976 | } |
3984 | 3977 | ||
3985 | /* create DAI component name */ | 3978 | /* |
3986 | dai->name = fmt_multiple_name(dev, &dai_drv[i]); | 3979 | * Back in the old days when we still had component-less DAIs, |
3980 | * instead of having a static name, component-less DAIs would | ||
3981 | * inherit the name of the parent device so it is possible to | ||
3982 | * register multiple instances of the DAI. We still need to keep | ||
3983 | * the same naming style even though those DAIs are not | ||
3984 | * component-less anymore. | ||
3985 | */ | ||
3986 | if (count == 1 && legacy_dai_naming) { | ||
3987 | dai->name = fmt_single_name(dev, &dai->id); | ||
3988 | } else { | ||
3989 | dai->name = fmt_multiple_name(dev, &dai_drv[i]); | ||
3990 | if (dai_drv[i].id) | ||
3991 | dai->id = dai_drv[i].id; | ||
3992 | else | ||
3993 | dai->id = i; | ||
3994 | } | ||
3987 | if (dai->name == NULL) { | 3995 | if (dai->name == NULL) { |
3988 | kfree(dai); | 3996 | kfree(dai); |
3989 | ret = -EINVAL; | 3997 | ret = -ENOMEM; |
3990 | goto err; | 3998 | goto err; |
3991 | } | 3999 | } |
3992 | 4000 | ||
4001 | dai->component = component; | ||
4002 | dai->codec = codec; | ||
3993 | dai->dev = dev; | 4003 | dai->dev = dev; |
3994 | dai->driver = &dai_drv[i]; | 4004 | dai->driver = &dai_drv[i]; |
3995 | if (dai->driver->id) | ||
3996 | dai->id = dai->driver->id; | ||
3997 | else | ||
3998 | dai->id = i; | ||
3999 | dai->dapm.dev = dev; | 4005 | dai->dapm.dev = dev; |
4000 | if (!dai->driver->ops) | 4006 | if (!dai->driver->ops) |
4001 | dai->driver->ops = &null_dai_ops; | 4007 | dai->driver->ops = &null_dai_ops; |
4002 | 4008 | ||
4003 | mutex_lock(&client_mutex); | ||
4004 | |||
4005 | list_for_each_entry(codec, &codec_list, list) { | ||
4006 | if (codec->dev == dev) { | ||
4007 | dev_dbg(dev, | ||
4008 | "ASoC: Mapped DAI %s to CODEC %s\n", | ||
4009 | dai->name, codec->name); | ||
4010 | dai->codec = codec; | ||
4011 | break; | ||
4012 | } | ||
4013 | } | ||
4014 | |||
4015 | if (!dai->codec) | 4009 | if (!dai->codec) |
4016 | dai->dapm.idle_bias_off = 1; | 4010 | dai->dapm.idle_bias_off = 1; |
4017 | 4011 | ||
4018 | list_add(&dai->list, &dai_list); | 4012 | list_add(&dai->list, &component->dai_list); |
4019 | 4013 | ||
4020 | mutex_unlock(&client_mutex); | 4014 | dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); |
4021 | |||
4022 | dev_dbg(dai->dev, "ASoC: Registered DAI '%s'\n", dai->name); | ||
4023 | } | 4015 | } |
4024 | 4016 | ||
4025 | return 0; | 4017 | return 0; |
4026 | 4018 | ||
4027 | err: | 4019 | err: |
4028 | for (i--; i >= 0; i--) | 4020 | snd_soc_unregister_dais(component); |
4029 | snd_soc_unregister_dai(dev); | ||
4030 | 4021 | ||
4031 | return ret; | 4022 | return ret; |
4032 | } | 4023 | } |
4033 | 4024 | ||
4034 | /** | 4025 | /** |
4035 | * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core | ||
4036 | * | ||
4037 | * @dai: Array of DAIs to unregister | ||
4038 | * @count: Number of DAIs | ||
4039 | */ | ||
4040 | static void snd_soc_unregister_dais(struct device *dev, size_t count) | ||
4041 | { | ||
4042 | int i; | ||
4043 | |||
4044 | for (i = 0; i < count; i++) | ||
4045 | snd_soc_unregister_dai(dev); | ||
4046 | } | ||
4047 | |||
4048 | /** | ||
4049 | * snd_soc_register_component - Register a component with the ASoC core | 4026 | * snd_soc_register_component - Register a component with the ASoC core |
4050 | * | 4027 | * |
4051 | */ | 4028 | */ |
@@ -4053,6 +4030,7 @@ static int | |||
4053 | __snd_soc_register_component(struct device *dev, | 4030 | __snd_soc_register_component(struct device *dev, |
4054 | struct snd_soc_component *cmpnt, | 4031 | struct snd_soc_component *cmpnt, |
4055 | const struct snd_soc_component_driver *cmpnt_drv, | 4032 | const struct snd_soc_component_driver *cmpnt_drv, |
4033 | struct snd_soc_codec *codec, | ||
4056 | struct snd_soc_dai_driver *dai_drv, | 4034 | struct snd_soc_dai_driver *dai_drv, |
4057 | int num_dai, bool allow_single_dai) | 4035 | int num_dai, bool allow_single_dai) |
4058 | { | 4036 | { |
@@ -4075,20 +4053,10 @@ __snd_soc_register_component(struct device *dev, | |||
4075 | cmpnt->driver = cmpnt_drv; | 4053 | cmpnt->driver = cmpnt_drv; |
4076 | cmpnt->dai_drv = dai_drv; | 4054 | cmpnt->dai_drv = dai_drv; |
4077 | cmpnt->num_dai = num_dai; | 4055 | cmpnt->num_dai = num_dai; |
4056 | INIT_LIST_HEAD(&cmpnt->dai_list); | ||
4078 | 4057 | ||
4079 | /* | 4058 | ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai, |
4080 | * snd_soc_register_dai() uses fmt_single_name(), and | 4059 | allow_single_dai); |
4081 | * snd_soc_register_dais() uses fmt_multiple_name() | ||
4082 | * for dai->name which is used for name based matching | ||
4083 | * | ||
4084 | * this function is used from cpu/codec. | ||
4085 | * allow_single_dai flag can ignore "codec" driver reworking | ||
4086 | * since it had been used snd_soc_register_dais(), | ||
4087 | */ | ||
4088 | if ((1 == num_dai) && allow_single_dai) | ||
4089 | ret = snd_soc_register_dai(dev, dai_drv); | ||
4090 | else | ||
4091 | ret = snd_soc_register_dais(dev, dai_drv, num_dai); | ||
4092 | if (ret < 0) { | 4060 | if (ret < 0) { |
4093 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); | 4061 | dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); |
4094 | goto error_component_name; | 4062 | goto error_component_name; |
@@ -4121,7 +4089,9 @@ int snd_soc_register_component(struct device *dev, | |||
4121 | return -ENOMEM; | 4089 | return -ENOMEM; |
4122 | } | 4090 | } |
4123 | 4091 | ||
4124 | return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, | 4092 | cmpnt->ignore_pmdown_time = true; |
4093 | |||
4094 | return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, NULL, | ||
4125 | dai_drv, num_dai, true); | 4095 | dai_drv, num_dai, true); |
4126 | } | 4096 | } |
4127 | EXPORT_SYMBOL_GPL(snd_soc_register_component); | 4097 | EXPORT_SYMBOL_GPL(snd_soc_register_component); |
@@ -4141,7 +4111,7 @@ void snd_soc_unregister_component(struct device *dev) | |||
4141 | return; | 4111 | return; |
4142 | 4112 | ||
4143 | found: | 4113 | found: |
4144 | snd_soc_unregister_dais(dev, cmpnt->num_dai); | 4114 | snd_soc_unregister_dais(cmpnt); |
4145 | 4115 | ||
4146 | mutex_lock(&client_mutex); | 4116 | mutex_lock(&client_mutex); |
4147 | list_del(&cmpnt->list); | 4117 | list_del(&cmpnt->list); |
@@ -4319,7 +4289,7 @@ int snd_soc_register_codec(struct device *dev, | |||
4319 | codec->volatile_register = codec_drv->volatile_register; | 4289 | codec->volatile_register = codec_drv->volatile_register; |
4320 | codec->readable_register = codec_drv->readable_register; | 4290 | codec->readable_register = codec_drv->readable_register; |
4321 | codec->writable_register = codec_drv->writable_register; | 4291 | codec->writable_register = codec_drv->writable_register; |
4322 | codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time; | 4292 | codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; |
4323 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | 4293 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; |
4324 | codec->dapm.dev = dev; | 4294 | codec->dapm.dev = dev; |
4325 | codec->dapm.codec = codec; | 4295 | codec->dapm.codec = codec; |
@@ -4342,7 +4312,7 @@ int snd_soc_register_codec(struct device *dev, | |||
4342 | /* register component */ | 4312 | /* register component */ |
4343 | ret = __snd_soc_register_component(dev, &codec->component, | 4313 | ret = __snd_soc_register_component(dev, &codec->component, |
4344 | &codec_drv->component_driver, | 4314 | &codec_drv->component_driver, |
4345 | dai_drv, num_dai, false); | 4315 | codec, dai_drv, num_dai, false); |
4346 | if (ret < 0) { | 4316 | if (ret < 0) { |
4347 | dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); | 4317 | dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); |
4348 | goto fail_codec_name; | 4318 | goto fail_codec_name; |
@@ -4417,6 +4387,122 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, | |||
4417 | } | 4387 | } |
4418 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name); | 4388 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name); |
4419 | 4389 | ||
4390 | static const struct snd_soc_dapm_widget simple_widgets[] = { | ||
4391 | SND_SOC_DAPM_MIC("Microphone", NULL), | ||
4392 | SND_SOC_DAPM_LINE("Line", NULL), | ||
4393 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
4394 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
4395 | }; | ||
4396 | |||
4397 | int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, | ||
4398 | const char *propname) | ||
4399 | { | ||
4400 | struct device_node *np = card->dev->of_node; | ||
4401 | struct snd_soc_dapm_widget *widgets; | ||
4402 | const char *template, *wname; | ||
4403 | int i, j, num_widgets, ret; | ||
4404 | |||
4405 | num_widgets = of_property_count_strings(np, propname); | ||
4406 | if (num_widgets < 0) { | ||
4407 | dev_err(card->dev, | ||
4408 | "ASoC: Property '%s' does not exist\n", propname); | ||
4409 | return -EINVAL; | ||
4410 | } | ||
4411 | if (num_widgets & 1) { | ||
4412 | dev_err(card->dev, | ||
4413 | "ASoC: Property '%s' length is not even\n", propname); | ||
4414 | return -EINVAL; | ||
4415 | } | ||
4416 | |||
4417 | num_widgets /= 2; | ||
4418 | if (!num_widgets) { | ||
4419 | dev_err(card->dev, "ASoC: Property '%s's length is zero\n", | ||
4420 | propname); | ||
4421 | return -EINVAL; | ||
4422 | } | ||
4423 | |||
4424 | widgets = devm_kcalloc(card->dev, num_widgets, sizeof(*widgets), | ||
4425 | GFP_KERNEL); | ||
4426 | if (!widgets) { | ||
4427 | dev_err(card->dev, | ||
4428 | "ASoC: Could not allocate memory for widgets\n"); | ||
4429 | return -ENOMEM; | ||
4430 | } | ||
4431 | |||
4432 | for (i = 0; i < num_widgets; i++) { | ||
4433 | ret = of_property_read_string_index(np, propname, | ||
4434 | 2 * i, &template); | ||
4435 | if (ret) { | ||
4436 | dev_err(card->dev, | ||
4437 | "ASoC: Property '%s' index %d read error:%d\n", | ||
4438 | propname, 2 * i, ret); | ||
4439 | return -EINVAL; | ||
4440 | } | ||
4441 | |||
4442 | for (j = 0; j < ARRAY_SIZE(simple_widgets); j++) { | ||
4443 | if (!strncmp(template, simple_widgets[j].name, | ||
4444 | strlen(simple_widgets[j].name))) { | ||
4445 | widgets[i] = simple_widgets[j]; | ||
4446 | break; | ||
4447 | } | ||
4448 | } | ||
4449 | |||
4450 | if (j >= ARRAY_SIZE(simple_widgets)) { | ||
4451 | dev_err(card->dev, | ||
4452 | "ASoC: DAPM widget '%s' is not supported\n", | ||
4453 | template); | ||
4454 | return -EINVAL; | ||
4455 | } | ||
4456 | |||
4457 | ret = of_property_read_string_index(np, propname, | ||
4458 | (2 * i) + 1, | ||
4459 | &wname); | ||
4460 | if (ret) { | ||
4461 | dev_err(card->dev, | ||
4462 | "ASoC: Property '%s' index %d read error:%d\n", | ||
4463 | propname, (2 * i) + 1, ret); | ||
4464 | return -EINVAL; | ||
4465 | } | ||
4466 | |||
4467 | widgets[i].name = wname; | ||
4468 | } | ||
4469 | |||
4470 | card->dapm_widgets = widgets; | ||
4471 | card->num_dapm_widgets = num_widgets; | ||
4472 | |||
4473 | return 0; | ||
4474 | } | ||
4475 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); | ||
4476 | |||
4477 | int snd_soc_of_parse_tdm_slot(struct device_node *np, | ||
4478 | unsigned int *slots, | ||
4479 | unsigned int *slot_width) | ||
4480 | { | ||
4481 | u32 val; | ||
4482 | int ret; | ||
4483 | |||
4484 | if (of_property_read_bool(np, "dai-tdm-slot-num")) { | ||
4485 | ret = of_property_read_u32(np, "dai-tdm-slot-num", &val); | ||
4486 | if (ret) | ||
4487 | return ret; | ||
4488 | |||
4489 | if (slots) | ||
4490 | *slots = val; | ||
4491 | } | ||
4492 | |||
4493 | if (of_property_read_bool(np, "dai-tdm-slot-width")) { | ||
4494 | ret = of_property_read_u32(np, "dai-tdm-slot-width", &val); | ||
4495 | if (ret) | ||
4496 | return ret; | ||
4497 | |||
4498 | if (slot_width) | ||
4499 | *slot_width = val; | ||
4500 | } | ||
4501 | |||
4502 | return 0; | ||
4503 | } | ||
4504 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); | ||
4505 | |||
4420 | int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | 4506 | int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, |
4421 | const char *propname) | 4507 | const char *propname) |
4422 | { | 4508 | { |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dc8ff13187f7..c8a780d0d057 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -70,8 +70,6 @@ static int dapm_up_seq[] = { | |||
70 | [snd_soc_dapm_aif_out] = 4, | 70 | [snd_soc_dapm_aif_out] = 4, |
71 | [snd_soc_dapm_mic] = 5, | 71 | [snd_soc_dapm_mic] = 5, |
72 | [snd_soc_dapm_mux] = 6, | 72 | [snd_soc_dapm_mux] = 6, |
73 | [snd_soc_dapm_virt_mux] = 6, | ||
74 | [snd_soc_dapm_value_mux] = 6, | ||
75 | [snd_soc_dapm_dac] = 7, | 73 | [snd_soc_dapm_dac] = 7, |
76 | [snd_soc_dapm_switch] = 8, | 74 | [snd_soc_dapm_switch] = 8, |
77 | [snd_soc_dapm_mixer] = 8, | 75 | [snd_soc_dapm_mixer] = 8, |
@@ -102,8 +100,6 @@ static int dapm_down_seq[] = { | |||
102 | [snd_soc_dapm_mic] = 7, | 100 | [snd_soc_dapm_mic] = 7, |
103 | [snd_soc_dapm_micbias] = 8, | 101 | [snd_soc_dapm_micbias] = 8, |
104 | [snd_soc_dapm_mux] = 9, | 102 | [snd_soc_dapm_mux] = 9, |
105 | [snd_soc_dapm_virt_mux] = 9, | ||
106 | [snd_soc_dapm_value_mux] = 9, | ||
107 | [snd_soc_dapm_aif_in] = 10, | 103 | [snd_soc_dapm_aif_in] = 10, |
108 | [snd_soc_dapm_aif_out] = 10, | 104 | [snd_soc_dapm_aif_out] = 10, |
109 | [snd_soc_dapm_dai_in] = 10, | 105 | [snd_soc_dapm_dai_in] = 10, |
@@ -115,6 +111,12 @@ static int dapm_down_seq[] = { | |||
115 | [snd_soc_dapm_post] = 14, | 111 | [snd_soc_dapm_post] = 14, |
116 | }; | 112 | }; |
117 | 113 | ||
114 | static void dapm_assert_locked(struct snd_soc_dapm_context *dapm) | ||
115 | { | ||
116 | if (dapm->card && dapm->card->instantiated) | ||
117 | lockdep_assert_held(&dapm->card->dapm_mutex); | ||
118 | } | ||
119 | |||
118 | static void pop_wait(u32 pop_time) | 120 | static void pop_wait(u32 pop_time) |
119 | { | 121 | { |
120 | if (pop_time) | 122 | if (pop_time) |
@@ -146,15 +148,16 @@ static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w) | |||
146 | return !list_empty(&w->dirty); | 148 | return !list_empty(&w->dirty); |
147 | } | 149 | } |
148 | 150 | ||
149 | void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) | 151 | static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) |
150 | { | 152 | { |
153 | dapm_assert_locked(w->dapm); | ||
154 | |||
151 | if (!dapm_dirty_widget(w)) { | 155 | if (!dapm_dirty_widget(w)) { |
152 | dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n", | 156 | dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n", |
153 | w->name, reason); | 157 | w->name, reason); |
154 | list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty); | 158 | list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty); |
155 | } | 159 | } |
156 | } | 160 | } |
157 | EXPORT_SYMBOL_GPL(dapm_mark_dirty); | ||
158 | 161 | ||
159 | void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm) | 162 | void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm) |
160 | { | 163 | { |
@@ -361,6 +364,8 @@ static void dapm_reset(struct snd_soc_card *card) | |||
361 | { | 364 | { |
362 | struct snd_soc_dapm_widget *w; | 365 | struct snd_soc_dapm_widget *w; |
363 | 366 | ||
367 | lockdep_assert_held(&card->dapm_mutex); | ||
368 | |||
364 | memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); | 369 | memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); |
365 | 370 | ||
366 | list_for_each_entry(w, &card->widgets, list) { | 371 | list_for_each_entry(w, &card->widgets, list) { |
@@ -386,7 +391,8 @@ static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg, | |||
386 | return -1; | 391 | return -1; |
387 | } | 392 | } |
388 | 393 | ||
389 | static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val) | 394 | static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, |
395 | unsigned int val) | ||
390 | { | 396 | { |
391 | if (w->codec) | 397 | if (w->codec) |
392 | return snd_soc_write(w->codec, reg, val); | 398 | return snd_soc_write(w->codec, reg, val); |
@@ -498,131 +504,40 @@ out: | |||
498 | return ret; | 504 | return ret; |
499 | } | 505 | } |
500 | 506 | ||
501 | /* set up initial codec paths */ | 507 | /* connect mux widget to its interconnecting audio paths */ |
502 | static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | 508 | static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, |
503 | struct snd_soc_dapm_path *p, int i) | 509 | struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, |
510 | struct snd_soc_dapm_path *path, const char *control_name, | ||
511 | const struct snd_kcontrol_new *kcontrol) | ||
504 | { | 512 | { |
505 | switch (w->id) { | 513 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
506 | case snd_soc_dapm_switch: | 514 | unsigned int val, item; |
507 | case snd_soc_dapm_mixer: | 515 | int i; |
508 | case snd_soc_dapm_mixer_named_ctl: { | ||
509 | int val; | ||
510 | struct soc_mixer_control *mc = (struct soc_mixer_control *) | ||
511 | w->kcontrol_news[i].private_value; | ||
512 | int reg = mc->reg; | ||
513 | unsigned int shift = mc->shift; | ||
514 | int max = mc->max; | ||
515 | unsigned int mask = (1 << fls(max)) - 1; | ||
516 | unsigned int invert = mc->invert; | ||
517 | |||
518 | if (reg != SND_SOC_NOPM) { | ||
519 | soc_widget_read(w, reg, &val); | ||
520 | val = (val >> shift) & mask; | ||
521 | if (invert) | ||
522 | val = max - val; | ||
523 | p->connect = !!val; | ||
524 | } else { | ||
525 | p->connect = 0; | ||
526 | } | ||
527 | |||
528 | } | ||
529 | break; | ||
530 | case snd_soc_dapm_mux: { | ||
531 | struct soc_enum *e = (struct soc_enum *) | ||
532 | w->kcontrol_news[i].private_value; | ||
533 | int val, item; | ||
534 | |||
535 | soc_widget_read(w, e->reg, &val); | ||
536 | item = (val >> e->shift_l) & e->mask; | ||
537 | |||
538 | if (item < e->max && !strcmp(p->name, e->texts[item])) | ||
539 | p->connect = 1; | ||
540 | else | ||
541 | p->connect = 0; | ||
542 | } | ||
543 | break; | ||
544 | case snd_soc_dapm_virt_mux: { | ||
545 | struct soc_enum *e = (struct soc_enum *) | ||
546 | w->kcontrol_news[i].private_value; | ||
547 | 516 | ||
548 | p->connect = 0; | 517 | if (e->reg != SND_SOC_NOPM) { |
518 | soc_widget_read(dest, e->reg, &val); | ||
519 | val = (val >> e->shift_l) & e->mask; | ||
520 | item = snd_soc_enum_val_to_item(e, val); | ||
521 | } else { | ||
549 | /* since a virtual mux has no backing registers to | 522 | /* since a virtual mux has no backing registers to |
550 | * decide which path to connect, it will try to match | 523 | * decide which path to connect, it will try to match |
551 | * with the first enumeration. This is to ensure | 524 | * with the first enumeration. This is to ensure |
552 | * that the default mux choice (the first) will be | 525 | * that the default mux choice (the first) will be |
553 | * correctly powered up during initialization. | 526 | * correctly powered up during initialization. |
554 | */ | 527 | */ |
555 | if (!strcmp(p->name, e->texts[0])) | 528 | item = 0; |
556 | p->connect = 1; | ||
557 | } | ||
558 | break; | ||
559 | case snd_soc_dapm_value_mux: { | ||
560 | struct soc_enum *e = (struct soc_enum *) | ||
561 | w->kcontrol_news[i].private_value; | ||
562 | int val, item; | ||
563 | |||
564 | soc_widget_read(w, e->reg, &val); | ||
565 | val = (val >> e->shift_l) & e->mask; | ||
566 | for (item = 0; item < e->max; item++) { | ||
567 | if (val == e->values[item]) | ||
568 | break; | ||
569 | } | ||
570 | |||
571 | if (item < e->max && !strcmp(p->name, e->texts[item])) | ||
572 | p->connect = 1; | ||
573 | else | ||
574 | p->connect = 0; | ||
575 | } | ||
576 | break; | ||
577 | /* does not affect routing - always connected */ | ||
578 | case snd_soc_dapm_pga: | ||
579 | case snd_soc_dapm_out_drv: | ||
580 | case snd_soc_dapm_output: | ||
581 | case snd_soc_dapm_adc: | ||
582 | case snd_soc_dapm_input: | ||
583 | case snd_soc_dapm_siggen: | ||
584 | case snd_soc_dapm_dac: | ||
585 | case snd_soc_dapm_micbias: | ||
586 | case snd_soc_dapm_vmid: | ||
587 | case snd_soc_dapm_supply: | ||
588 | case snd_soc_dapm_regulator_supply: | ||
589 | case snd_soc_dapm_clock_supply: | ||
590 | case snd_soc_dapm_aif_in: | ||
591 | case snd_soc_dapm_aif_out: | ||
592 | case snd_soc_dapm_dai_in: | ||
593 | case snd_soc_dapm_dai_out: | ||
594 | case snd_soc_dapm_hp: | ||
595 | case snd_soc_dapm_mic: | ||
596 | case snd_soc_dapm_spk: | ||
597 | case snd_soc_dapm_line: | ||
598 | case snd_soc_dapm_dai_link: | ||
599 | case snd_soc_dapm_kcontrol: | ||
600 | p->connect = 1; | ||
601 | break; | ||
602 | /* does affect routing - dynamically connected */ | ||
603 | case snd_soc_dapm_pre: | ||
604 | case snd_soc_dapm_post: | ||
605 | p->connect = 0; | ||
606 | break; | ||
607 | } | 529 | } |
608 | } | ||
609 | |||
610 | /* connect mux widget to its interconnecting audio paths */ | ||
611 | static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, | ||
612 | struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, | ||
613 | struct snd_soc_dapm_path *path, const char *control_name, | ||
614 | const struct snd_kcontrol_new *kcontrol) | ||
615 | { | ||
616 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
617 | int i; | ||
618 | 530 | ||
619 | for (i = 0; i < e->max; i++) { | 531 | for (i = 0; i < e->items; i++) { |
620 | if (!(strcmp(control_name, e->texts[i]))) { | 532 | if (!(strcmp(control_name, e->texts[i]))) { |
621 | list_add(&path->list, &dapm->card->paths); | 533 | list_add(&path->list, &dapm->card->paths); |
622 | list_add(&path->list_sink, &dest->sources); | 534 | list_add(&path->list_sink, &dest->sources); |
623 | list_add(&path->list_source, &src->sinks); | 535 | list_add(&path->list_source, &src->sinks); |
624 | path->name = (char*)e->texts[i]; | 536 | path->name = (char*)e->texts[i]; |
625 | dapm_set_path_status(dest, path, 0); | 537 | if (i == item) |
538 | path->connect = 1; | ||
539 | else | ||
540 | path->connect = 0; | ||
626 | return 0; | 541 | return 0; |
627 | } | 542 | } |
628 | } | 543 | } |
@@ -630,6 +545,30 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, | |||
630 | return -ENODEV; | 545 | return -ENODEV; |
631 | } | 546 | } |
632 | 547 | ||
548 | /* set up initial codec paths */ | ||
549 | static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, | ||
550 | struct snd_soc_dapm_path *p, int i) | ||
551 | { | ||
552 | struct soc_mixer_control *mc = (struct soc_mixer_control *) | ||
553 | w->kcontrol_news[i].private_value; | ||
554 | unsigned int reg = mc->reg; | ||
555 | unsigned int shift = mc->shift; | ||
556 | unsigned int max = mc->max; | ||
557 | unsigned int mask = (1 << fls(max)) - 1; | ||
558 | unsigned int invert = mc->invert; | ||
559 | unsigned int val; | ||
560 | |||
561 | if (reg != SND_SOC_NOPM) { | ||
562 | soc_widget_read(w, reg, &val); | ||
563 | val = (val >> shift) & mask; | ||
564 | if (invert) | ||
565 | val = max - val; | ||
566 | p->connect = !!val; | ||
567 | } else { | ||
568 | p->connect = 0; | ||
569 | } | ||
570 | } | ||
571 | |||
633 | /* connect mixer widget to its interconnecting audio paths */ | 572 | /* connect mixer widget to its interconnecting audio paths */ |
634 | static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, | 573 | static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, |
635 | struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, | 574 | struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, |
@@ -644,7 +583,7 @@ static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, | |||
644 | list_add(&path->list_sink, &dest->sources); | 583 | list_add(&path->list_sink, &dest->sources); |
645 | list_add(&path->list_source, &src->sinks); | 584 | list_add(&path->list_source, &src->sinks); |
646 | path->name = dest->kcontrol_news[i].name; | 585 | path->name = dest->kcontrol_news[i].name; |
647 | dapm_set_path_status(dest, path, i); | 586 | dapm_set_mixer_path_status(dest, path, i); |
648 | return 0; | 587 | return 0; |
649 | } | 588 | } |
650 | } | 589 | } |
@@ -723,8 +662,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, | |||
723 | kcname_in_long_name = true; | 662 | kcname_in_long_name = true; |
724 | break; | 663 | break; |
725 | case snd_soc_dapm_mux: | 664 | case snd_soc_dapm_mux: |
726 | case snd_soc_dapm_virt_mux: | ||
727 | case snd_soc_dapm_value_mux: | ||
728 | wname_in_long_name = true; | 665 | wname_in_long_name = true; |
729 | kcname_in_long_name = false; | 666 | kcname_in_long_name = false; |
730 | break; | 667 | break; |
@@ -1218,7 +1155,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, | |||
1218 | ret = regulator_allow_bypass(w->regulator, false); | 1155 | ret = regulator_allow_bypass(w->regulator, false); |
1219 | if (ret != 0) | 1156 | if (ret != 0) |
1220 | dev_warn(w->dapm->dev, | 1157 | dev_warn(w->dapm->dev, |
1221 | "ASoC: Failed to bypass %s: %d\n", | 1158 | "ASoC: Failed to unbypass %s: %d\n", |
1222 | w->name, ret); | 1159 | w->name, ret); |
1223 | } | 1160 | } |
1224 | 1161 | ||
@@ -1228,7 +1165,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, | |||
1228 | ret = regulator_allow_bypass(w->regulator, true); | 1165 | ret = regulator_allow_bypass(w->regulator, true); |
1229 | if (ret != 0) | 1166 | if (ret != 0) |
1230 | dev_warn(w->dapm->dev, | 1167 | dev_warn(w->dapm->dev, |
1231 | "ASoC: Failed to unbypass %s: %d\n", | 1168 | "ASoC: Failed to bypass %s: %d\n", |
1232 | w->name, ret); | 1169 | w->name, ret); |
1233 | } | 1170 | } |
1234 | 1171 | ||
@@ -1823,6 +1760,8 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) | |||
1823 | ASYNC_DOMAIN_EXCLUSIVE(async_domain); | 1760 | ASYNC_DOMAIN_EXCLUSIVE(async_domain); |
1824 | enum snd_soc_bias_level bias; | 1761 | enum snd_soc_bias_level bias; |
1825 | 1762 | ||
1763 | lockdep_assert_held(&card->dapm_mutex); | ||
1764 | |||
1826 | trace_snd_soc_dapm_start(card); | 1765 | trace_snd_soc_dapm_start(card); |
1827 | 1766 | ||
1828 | list_for_each_entry(d, &card->dapm_list, list) { | 1767 | list_for_each_entry(d, &card->dapm_list, list) { |
@@ -1897,10 +1836,14 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) | |||
1897 | 1836 | ||
1898 | trace_snd_soc_dapm_walk_done(card); | 1837 | trace_snd_soc_dapm_walk_done(card); |
1899 | 1838 | ||
1900 | /* Run all the bias changes in parallel */ | 1839 | /* Run card bias changes at first */ |
1901 | list_for_each_entry(d, &card->dapm_list, list) | 1840 | dapm_pre_sequence_async(&card->dapm, 0); |
1902 | async_schedule_domain(dapm_pre_sequence_async, d, | 1841 | /* Run other bias changes in parallel */ |
1903 | &async_domain); | 1842 | list_for_each_entry(d, &card->dapm_list, list) { |
1843 | if (d != &card->dapm) | ||
1844 | async_schedule_domain(dapm_pre_sequence_async, d, | ||
1845 | &async_domain); | ||
1846 | } | ||
1904 | async_synchronize_full_domain(&async_domain); | 1847 | async_synchronize_full_domain(&async_domain); |
1905 | 1848 | ||
1906 | list_for_each_entry(w, &down_list, power_list) { | 1849 | list_for_each_entry(w, &down_list, power_list) { |
@@ -1920,10 +1863,14 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) | |||
1920 | dapm_seq_run(card, &up_list, event, true); | 1863 | dapm_seq_run(card, &up_list, event, true); |
1921 | 1864 | ||
1922 | /* Run all the bias changes in parallel */ | 1865 | /* Run all the bias changes in parallel */ |
1923 | list_for_each_entry(d, &card->dapm_list, list) | 1866 | list_for_each_entry(d, &card->dapm_list, list) { |
1924 | async_schedule_domain(dapm_post_sequence_async, d, | 1867 | if (d != &card->dapm) |
1925 | &async_domain); | 1868 | async_schedule_domain(dapm_post_sequence_async, d, |
1869 | &async_domain); | ||
1870 | } | ||
1926 | async_synchronize_full_domain(&async_domain); | 1871 | async_synchronize_full_domain(&async_domain); |
1872 | /* Run card bias changes at last */ | ||
1873 | dapm_post_sequence_async(&card->dapm, 0); | ||
1927 | 1874 | ||
1928 | /* do we need to notify any clients that DAPM event is complete */ | 1875 | /* do we need to notify any clients that DAPM event is complete */ |
1929 | list_for_each_entry(d, &card->dapm_list, list) { | 1876 | list_for_each_entry(d, &card->dapm_list, list) { |
@@ -2110,6 +2057,8 @@ static int soc_dapm_mux_update_power(struct snd_soc_card *card, | |||
2110 | struct snd_soc_dapm_path *path; | 2057 | struct snd_soc_dapm_path *path; |
2111 | int found = 0; | 2058 | int found = 0; |
2112 | 2059 | ||
2060 | lockdep_assert_held(&card->dapm_mutex); | ||
2061 | |||
2113 | /* find dapm widget path assoc with kcontrol */ | 2062 | /* find dapm widget path assoc with kcontrol */ |
2114 | dapm_kcontrol_for_each_path(path, kcontrol) { | 2063 | dapm_kcontrol_for_each_path(path, kcontrol) { |
2115 | if (!path->name || !e->texts[mux]) | 2064 | if (!path->name || !e->texts[mux]) |
@@ -2160,6 +2109,8 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card, | |||
2160 | struct snd_soc_dapm_path *path; | 2109 | struct snd_soc_dapm_path *path; |
2161 | int found = 0; | 2110 | int found = 0; |
2162 | 2111 | ||
2112 | lockdep_assert_held(&card->dapm_mutex); | ||
2113 | |||
2163 | /* find dapm widget path assoc with kcontrol */ | 2114 | /* find dapm widget path assoc with kcontrol */ |
2164 | dapm_kcontrol_for_each_path(path, kcontrol) { | 2115 | dapm_kcontrol_for_each_path(path, kcontrol) { |
2165 | found = 1; | 2116 | found = 1; |
@@ -2325,6 +2276,8 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, | |||
2325 | { | 2276 | { |
2326 | struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); | 2277 | struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); |
2327 | 2278 | ||
2279 | dapm_assert_locked(dapm); | ||
2280 | |||
2328 | if (!w) { | 2281 | if (!w) { |
2329 | dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin); | 2282 | dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin); |
2330 | return -EINVAL; | 2283 | return -EINVAL; |
@@ -2341,18 +2294,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, | |||
2341 | } | 2294 | } |
2342 | 2295 | ||
2343 | /** | 2296 | /** |
2344 | * snd_soc_dapm_sync - scan and power dapm paths | 2297 | * snd_soc_dapm_sync_unlocked - scan and power dapm paths |
2345 | * @dapm: DAPM context | 2298 | * @dapm: DAPM context |
2346 | * | 2299 | * |
2347 | * Walks all dapm audio paths and powers widgets according to their | 2300 | * Walks all dapm audio paths and powers widgets according to their |
2348 | * stream or path usage. | 2301 | * stream or path usage. |
2349 | * | 2302 | * |
2303 | * Requires external locking. | ||
2304 | * | ||
2350 | * Returns 0 for success. | 2305 | * Returns 0 for success. |
2351 | */ | 2306 | */ |
2352 | int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) | 2307 | int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm) |
2353 | { | 2308 | { |
2354 | int ret; | ||
2355 | |||
2356 | /* | 2309 | /* |
2357 | * Suppress early reports (eg, jacks syncing their state) to avoid | 2310 | * Suppress early reports (eg, jacks syncing their state) to avoid |
2358 | * silly DAPM runs during card startup. | 2311 | * silly DAPM runs during card startup. |
@@ -2360,8 +2313,25 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) | |||
2360 | if (!dapm->card || !dapm->card->instantiated) | 2313 | if (!dapm->card || !dapm->card->instantiated) |
2361 | return 0; | 2314 | return 0; |
2362 | 2315 | ||
2316 | return dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); | ||
2317 | } | ||
2318 | EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_unlocked); | ||
2319 | |||
2320 | /** | ||
2321 | * snd_soc_dapm_sync - scan and power dapm paths | ||
2322 | * @dapm: DAPM context | ||
2323 | * | ||
2324 | * Walks all dapm audio paths and powers widgets according to their | ||
2325 | * stream or path usage. | ||
2326 | * | ||
2327 | * Returns 0 for success. | ||
2328 | */ | ||
2329 | int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) | ||
2330 | { | ||
2331 | int ret; | ||
2332 | |||
2363 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2333 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
2364 | ret = dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); | 2334 | ret = snd_soc_dapm_sync_unlocked(dapm); |
2365 | mutex_unlock(&dapm->card->dapm_mutex); | 2335 | mutex_unlock(&dapm->card->dapm_mutex); |
2366 | return ret; | 2336 | return ret; |
2367 | } | 2337 | } |
@@ -2444,8 +2414,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | |||
2444 | path->connect = 1; | 2414 | path->connect = 1; |
2445 | return 0; | 2415 | return 0; |
2446 | case snd_soc_dapm_mux: | 2416 | case snd_soc_dapm_mux: |
2447 | case snd_soc_dapm_virt_mux: | ||
2448 | case snd_soc_dapm_value_mux: | ||
2449 | ret = dapm_connect_mux(dapm, wsource, wsink, path, control, | 2417 | ret = dapm_connect_mux(dapm, wsource, wsink, path, control, |
2450 | &wsink->kcontrol_news[0]); | 2418 | &wsink->kcontrol_news[0]); |
2451 | if (ret != 0) | 2419 | if (ret != 0) |
@@ -2772,8 +2740,6 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) | |||
2772 | dapm_new_mixer(w); | 2740 | dapm_new_mixer(w); |
2773 | break; | 2741 | break; |
2774 | case snd_soc_dapm_mux: | 2742 | case snd_soc_dapm_mux: |
2775 | case snd_soc_dapm_virt_mux: | ||
2776 | case snd_soc_dapm_value_mux: | ||
2777 | dapm_new_mux(w); | 2743 | dapm_new_mux(w); |
2778 | break; | 2744 | break; |
2779 | case snd_soc_dapm_pga: | 2745 | case snd_soc_dapm_pga: |
@@ -2935,213 +2901,75 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | |||
2935 | { | 2901 | { |
2936 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 2902 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
2937 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2903 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2938 | unsigned int val; | 2904 | unsigned int reg_val, val; |
2939 | |||
2940 | val = snd_soc_read(codec, e->reg); | ||
2941 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; | ||
2942 | if (e->shift_l != e->shift_r) | ||
2943 | ucontrol->value.enumerated.item[1] = | ||
2944 | (val >> e->shift_r) & e->mask; | ||
2945 | |||
2946 | return 0; | ||
2947 | } | ||
2948 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); | ||
2949 | |||
2950 | /** | ||
2951 | * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback | ||
2952 | * @kcontrol: mixer control | ||
2953 | * @ucontrol: control element information | ||
2954 | * | ||
2955 | * Callback to set the value of a dapm enumerated double mixer control. | ||
2956 | * | ||
2957 | * Returns 0 for success. | ||
2958 | */ | ||
2959 | int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | ||
2960 | struct snd_ctl_elem_value *ucontrol) | ||
2961 | { | ||
2962 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | ||
2963 | struct snd_soc_card *card = codec->card; | ||
2964 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
2965 | unsigned int val, mux, change; | ||
2966 | unsigned int mask; | ||
2967 | struct snd_soc_dapm_update update; | ||
2968 | int ret = 0; | ||
2969 | |||
2970 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | ||
2971 | return -EINVAL; | ||
2972 | mux = ucontrol->value.enumerated.item[0]; | ||
2973 | val = mux << e->shift_l; | ||
2974 | mask = e->mask << e->shift_l; | ||
2975 | if (e->shift_l != e->shift_r) { | ||
2976 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | ||
2977 | return -EINVAL; | ||
2978 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | ||
2979 | mask |= e->mask << e->shift_r; | ||
2980 | } | ||
2981 | |||
2982 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
2983 | |||
2984 | change = snd_soc_test_bits(codec, e->reg, mask, val); | ||
2985 | if (change) { | ||
2986 | update.kcontrol = kcontrol; | ||
2987 | update.reg = e->reg; | ||
2988 | update.mask = mask; | ||
2989 | update.val = val; | ||
2990 | card->update = &update; | ||
2991 | |||
2992 | ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); | ||
2993 | |||
2994 | card->update = NULL; | ||
2995 | } | ||
2996 | |||
2997 | mutex_unlock(&card->dapm_mutex); | ||
2998 | 2905 | ||
2999 | if (ret > 0) | 2906 | if (e->reg != SND_SOC_NOPM) |
3000 | soc_dpcm_runtime_update(card); | 2907 | reg_val = snd_soc_read(codec, e->reg); |
3001 | 2908 | else | |
3002 | return change; | 2909 | reg_val = dapm_kcontrol_get_value(kcontrol); |
3003 | } | ||
3004 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); | ||
3005 | |||
3006 | /** | ||
3007 | * snd_soc_dapm_get_enum_virt - Get virtual DAPM mux | ||
3008 | * @kcontrol: mixer control | ||
3009 | * @ucontrol: control element information | ||
3010 | * | ||
3011 | * Returns 0 for success. | ||
3012 | */ | ||
3013 | int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, | ||
3014 | struct snd_ctl_elem_value *ucontrol) | ||
3015 | { | ||
3016 | ucontrol->value.enumerated.item[0] = dapm_kcontrol_get_value(kcontrol); | ||
3017 | return 0; | ||
3018 | } | ||
3019 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); | ||
3020 | |||
3021 | /** | ||
3022 | * snd_soc_dapm_put_enum_virt - Set virtual DAPM mux | ||
3023 | * @kcontrol: mixer control | ||
3024 | * @ucontrol: control element information | ||
3025 | * | ||
3026 | * Returns 0 for success. | ||
3027 | */ | ||
3028 | int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, | ||
3029 | struct snd_ctl_elem_value *ucontrol) | ||
3030 | { | ||
3031 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | ||
3032 | struct snd_soc_card *card = codec->card; | ||
3033 | unsigned int value; | ||
3034 | struct soc_enum *e = | ||
3035 | (struct soc_enum *)kcontrol->private_value; | ||
3036 | int change; | ||
3037 | int ret = 0; | ||
3038 | |||
3039 | if (ucontrol->value.enumerated.item[0] >= e->max) | ||
3040 | return -EINVAL; | ||
3041 | |||
3042 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
3043 | |||
3044 | value = ucontrol->value.enumerated.item[0]; | ||
3045 | change = dapm_kcontrol_set_value(kcontrol, value); | ||
3046 | if (change) | ||
3047 | ret = soc_dapm_mux_update_power(card, kcontrol, value, e); | ||
3048 | |||
3049 | mutex_unlock(&card->dapm_mutex); | ||
3050 | |||
3051 | if (ret > 0) | ||
3052 | soc_dpcm_runtime_update(card); | ||
3053 | |||
3054 | return change; | ||
3055 | } | ||
3056 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); | ||
3057 | |||
3058 | /** | ||
3059 | * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get | ||
3060 | * callback | ||
3061 | * @kcontrol: mixer control | ||
3062 | * @ucontrol: control element information | ||
3063 | * | ||
3064 | * Callback to get the value of a dapm semi enumerated double mixer control. | ||
3065 | * | ||
3066 | * Semi enumerated mixer: the enumerated items are referred as values. Can be | ||
3067 | * used for handling bitfield coded enumeration for example. | ||
3068 | * | ||
3069 | * Returns 0 for success. | ||
3070 | */ | ||
3071 | int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, | ||
3072 | struct snd_ctl_elem_value *ucontrol) | ||
3073 | { | ||
3074 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | ||
3075 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
3076 | unsigned int reg_val, val, mux; | ||
3077 | 2910 | ||
3078 | reg_val = snd_soc_read(codec, e->reg); | ||
3079 | val = (reg_val >> e->shift_l) & e->mask; | 2911 | val = (reg_val >> e->shift_l) & e->mask; |
3080 | for (mux = 0; mux < e->max; mux++) { | 2912 | ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); |
3081 | if (val == e->values[mux]) | ||
3082 | break; | ||
3083 | } | ||
3084 | ucontrol->value.enumerated.item[0] = mux; | ||
3085 | if (e->shift_l != e->shift_r) { | 2913 | if (e->shift_l != e->shift_r) { |
3086 | val = (reg_val >> e->shift_r) & e->mask; | 2914 | val = (reg_val >> e->shift_r) & e->mask; |
3087 | for (mux = 0; mux < e->max; mux++) { | 2915 | val = snd_soc_enum_val_to_item(e, val); |
3088 | if (val == e->values[mux]) | 2916 | ucontrol->value.enumerated.item[1] = val; |
3089 | break; | ||
3090 | } | ||
3091 | ucontrol->value.enumerated.item[1] = mux; | ||
3092 | } | 2917 | } |
3093 | 2918 | ||
3094 | return 0; | 2919 | return 0; |
3095 | } | 2920 | } |
3096 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double); | 2921 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); |
3097 | 2922 | ||
3098 | /** | 2923 | /** |
3099 | * snd_soc_dapm_put_value_enum_double - dapm semi enumerated double mixer set | 2924 | * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback |
3100 | * callback | ||
3101 | * @kcontrol: mixer control | 2925 | * @kcontrol: mixer control |
3102 | * @ucontrol: control element information | 2926 | * @ucontrol: control element information |
3103 | * | 2927 | * |
3104 | * Callback to set the value of a dapm semi enumerated double mixer control. | 2928 | * Callback to set the value of a dapm enumerated double mixer control. |
3105 | * | ||
3106 | * Semi enumerated mixer: the enumerated items are referred as values. Can be | ||
3107 | * used for handling bitfield coded enumeration for example. | ||
3108 | * | 2929 | * |
3109 | * Returns 0 for success. | 2930 | * Returns 0 for success. |
3110 | */ | 2931 | */ |
3111 | int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | 2932 | int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, |
3112 | struct snd_ctl_elem_value *ucontrol) | 2933 | struct snd_ctl_elem_value *ucontrol) |
3113 | { | 2934 | { |
3114 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); | 2935 | struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); |
3115 | struct snd_soc_card *card = codec->card; | 2936 | struct snd_soc_card *card = codec->card; |
3116 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2937 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
3117 | unsigned int val, mux, change; | 2938 | unsigned int *item = ucontrol->value.enumerated.item; |
2939 | unsigned int val, change; | ||
3118 | unsigned int mask; | 2940 | unsigned int mask; |
3119 | struct snd_soc_dapm_update update; | 2941 | struct snd_soc_dapm_update update; |
3120 | int ret = 0; | 2942 | int ret = 0; |
3121 | 2943 | ||
3122 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2944 | if (item[0] >= e->items) |
3123 | return -EINVAL; | 2945 | return -EINVAL; |
3124 | mux = ucontrol->value.enumerated.item[0]; | 2946 | |
3125 | val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; | 2947 | val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; |
3126 | mask = e->mask << e->shift_l; | 2948 | mask = e->mask << e->shift_l; |
3127 | if (e->shift_l != e->shift_r) { | 2949 | if (e->shift_l != e->shift_r) { |
3128 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | 2950 | if (item[1] > e->items) |
3129 | return -EINVAL; | 2951 | return -EINVAL; |
3130 | val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; | 2952 | val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_l; |
3131 | mask |= e->mask << e->shift_r; | 2953 | mask |= e->mask << e->shift_r; |
3132 | } | 2954 | } |
3133 | 2955 | ||
3134 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2956 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
3135 | 2957 | ||
3136 | change = snd_soc_test_bits(codec, e->reg, mask, val); | 2958 | if (e->reg != SND_SOC_NOPM) |
2959 | change = snd_soc_test_bits(codec, e->reg, mask, val); | ||
2960 | else | ||
2961 | change = dapm_kcontrol_set_value(kcontrol, val); | ||
2962 | |||
3137 | if (change) { | 2963 | if (change) { |
3138 | update.kcontrol = kcontrol; | 2964 | if (e->reg != SND_SOC_NOPM) { |
3139 | update.reg = e->reg; | 2965 | update.kcontrol = kcontrol; |
3140 | update.mask = mask; | 2966 | update.reg = e->reg; |
3141 | update.val = val; | 2967 | update.mask = mask; |
3142 | card->update = &update; | 2968 | update.val = val; |
2969 | card->update = &update; | ||
2970 | } | ||
3143 | 2971 | ||
3144 | ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); | 2972 | ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e); |
3145 | 2973 | ||
3146 | card->update = NULL; | 2974 | card->update = NULL; |
3147 | } | 2975 | } |
@@ -3153,7 +2981,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
3153 | 2981 | ||
3154 | return change; | 2982 | return change; |
3155 | } | 2983 | } |
3156 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); | 2984 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); |
3157 | 2985 | ||
3158 | /** | 2986 | /** |
3159 | * snd_soc_dapm_info_pin_switch - Info for a pin switch | 2987 | * snd_soc_dapm_info_pin_switch - Info for a pin switch |
@@ -3210,15 +3038,11 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, | |||
3210 | struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); | 3038 | struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); |
3211 | const char *pin = (const char *)kcontrol->private_value; | 3039 | const char *pin = (const char *)kcontrol->private_value; |
3212 | 3040 | ||
3213 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
3214 | |||
3215 | if (ucontrol->value.integer.value[0]) | 3041 | if (ucontrol->value.integer.value[0]) |
3216 | snd_soc_dapm_enable_pin(&card->dapm, pin); | 3042 | snd_soc_dapm_enable_pin(&card->dapm, pin); |
3217 | else | 3043 | else |
3218 | snd_soc_dapm_disable_pin(&card->dapm, pin); | 3044 | snd_soc_dapm_disable_pin(&card->dapm, pin); |
3219 | 3045 | ||
3220 | mutex_unlock(&card->dapm_mutex); | ||
3221 | |||
3222 | snd_soc_dapm_sync(&card->dapm); | 3046 | snd_soc_dapm_sync(&card->dapm); |
3223 | return 0; | 3047 | return 0; |
3224 | } | 3048 | } |
@@ -3248,7 +3072,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3248 | ret = regulator_allow_bypass(w->regulator, true); | 3072 | ret = regulator_allow_bypass(w->regulator, true); |
3249 | if (ret != 0) | 3073 | if (ret != 0) |
3250 | dev_warn(w->dapm->dev, | 3074 | dev_warn(w->dapm->dev, |
3251 | "ASoC: Failed to unbypass %s: %d\n", | 3075 | "ASoC: Failed to bypass %s: %d\n", |
3252 | w->name, ret); | 3076 | w->name, ret); |
3253 | } | 3077 | } |
3254 | break; | 3078 | break; |
@@ -3287,8 +3111,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3287 | w->power_check = dapm_generic_check_power; | 3111 | w->power_check = dapm_generic_check_power; |
3288 | break; | 3112 | break; |
3289 | case snd_soc_dapm_mux: | 3113 | case snd_soc_dapm_mux: |
3290 | case snd_soc_dapm_virt_mux: | ||
3291 | case snd_soc_dapm_value_mux: | ||
3292 | w->power_check = dapm_generic_check_power; | 3114 | w->power_check = dapm_generic_check_power; |
3293 | break; | 3115 | break; |
3294 | case snd_soc_dapm_dai_out: | 3116 | case snd_soc_dapm_dai_out: |
@@ -3767,23 +3589,52 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, | |||
3767 | } | 3589 | } |
3768 | 3590 | ||
3769 | /** | 3591 | /** |
3592 | * snd_soc_dapm_enable_pin_unlocked - enable pin. | ||
3593 | * @dapm: DAPM context | ||
3594 | * @pin: pin name | ||
3595 | * | ||
3596 | * Enables input/output pin and its parents or children widgets iff there is | ||
3597 | * a valid audio route and active audio stream. | ||
3598 | * | ||
3599 | * Requires external locking. | ||
3600 | * | ||
3601 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | ||
3602 | * do any widget power switching. | ||
3603 | */ | ||
3604 | int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, | ||
3605 | const char *pin) | ||
3606 | { | ||
3607 | return snd_soc_dapm_set_pin(dapm, pin, 1); | ||
3608 | } | ||
3609 | EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin_unlocked); | ||
3610 | |||
3611 | /** | ||
3770 | * snd_soc_dapm_enable_pin - enable pin. | 3612 | * snd_soc_dapm_enable_pin - enable pin. |
3771 | * @dapm: DAPM context | 3613 | * @dapm: DAPM context |
3772 | * @pin: pin name | 3614 | * @pin: pin name |
3773 | * | 3615 | * |
3774 | * Enables input/output pin and its parents or children widgets iff there is | 3616 | * Enables input/output pin and its parents or children widgets iff there is |
3775 | * a valid audio route and active audio stream. | 3617 | * a valid audio route and active audio stream. |
3618 | * | ||
3776 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 3619 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
3777 | * do any widget power switching. | 3620 | * do any widget power switching. |
3778 | */ | 3621 | */ |
3779 | int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin) | 3622 | int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin) |
3780 | { | 3623 | { |
3781 | return snd_soc_dapm_set_pin(dapm, pin, 1); | 3624 | int ret; |
3625 | |||
3626 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
3627 | |||
3628 | ret = snd_soc_dapm_set_pin(dapm, pin, 1); | ||
3629 | |||
3630 | mutex_unlock(&dapm->card->dapm_mutex); | ||
3631 | |||
3632 | return ret; | ||
3782 | } | 3633 | } |
3783 | EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); | 3634 | EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); |
3784 | 3635 | ||
3785 | /** | 3636 | /** |
3786 | * snd_soc_dapm_force_enable_pin - force a pin to be enabled | 3637 | * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled |
3787 | * @dapm: DAPM context | 3638 | * @dapm: DAPM context |
3788 | * @pin: pin name | 3639 | * @pin: pin name |
3789 | * | 3640 | * |
@@ -3791,11 +3642,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); | |||
3791 | * intended for use with microphone bias supplies used in microphone | 3642 | * intended for use with microphone bias supplies used in microphone |
3792 | * jack detection. | 3643 | * jack detection. |
3793 | * | 3644 | * |
3645 | * Requires external locking. | ||
3646 | * | ||
3794 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 3647 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
3795 | * do any widget power switching. | 3648 | * do any widget power switching. |
3796 | */ | 3649 | */ |
3797 | int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, | 3650 | int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, |
3798 | const char *pin) | 3651 | const char *pin) |
3799 | { | 3652 | { |
3800 | struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); | 3653 | struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); |
3801 | 3654 | ||
@@ -3811,25 +3664,103 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, | |||
3811 | 3664 | ||
3812 | return 0; | 3665 | return 0; |
3813 | } | 3666 | } |
3667 | EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin_unlocked); | ||
3668 | |||
3669 | /** | ||
3670 | * snd_soc_dapm_force_enable_pin - force a pin to be enabled | ||
3671 | * @dapm: DAPM context | ||
3672 | * @pin: pin name | ||
3673 | * | ||
3674 | * Enables input/output pin regardless of any other state. This is | ||
3675 | * intended for use with microphone bias supplies used in microphone | ||
3676 | * jack detection. | ||
3677 | * | ||
3678 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | ||
3679 | * do any widget power switching. | ||
3680 | */ | ||
3681 | int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, | ||
3682 | const char *pin) | ||
3683 | { | ||
3684 | int ret; | ||
3685 | |||
3686 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
3687 | |||
3688 | ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin); | ||
3689 | |||
3690 | mutex_unlock(&dapm->card->dapm_mutex); | ||
3691 | |||
3692 | return ret; | ||
3693 | } | ||
3814 | EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin); | 3694 | EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin); |
3815 | 3695 | ||
3816 | /** | 3696 | /** |
3697 | * snd_soc_dapm_disable_pin_unlocked - disable pin. | ||
3698 | * @dapm: DAPM context | ||
3699 | * @pin: pin name | ||
3700 | * | ||
3701 | * Disables input/output pin and its parents or children widgets. | ||
3702 | * | ||
3703 | * Requires external locking. | ||
3704 | * | ||
3705 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | ||
3706 | * do any widget power switching. | ||
3707 | */ | ||
3708 | int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm, | ||
3709 | const char *pin) | ||
3710 | { | ||
3711 | return snd_soc_dapm_set_pin(dapm, pin, 0); | ||
3712 | } | ||
3713 | EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin_unlocked); | ||
3714 | |||
3715 | /** | ||
3817 | * snd_soc_dapm_disable_pin - disable pin. | 3716 | * snd_soc_dapm_disable_pin - disable pin. |
3818 | * @dapm: DAPM context | 3717 | * @dapm: DAPM context |
3819 | * @pin: pin name | 3718 | * @pin: pin name |
3820 | * | 3719 | * |
3821 | * Disables input/output pin and its parents or children widgets. | 3720 | * Disables input/output pin and its parents or children widgets. |
3721 | * | ||
3822 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 3722 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
3823 | * do any widget power switching. | 3723 | * do any widget power switching. |
3824 | */ | 3724 | */ |
3825 | int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, | 3725 | int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, |
3826 | const char *pin) | 3726 | const char *pin) |
3827 | { | 3727 | { |
3828 | return snd_soc_dapm_set_pin(dapm, pin, 0); | 3728 | int ret; |
3729 | |||
3730 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
3731 | |||
3732 | ret = snd_soc_dapm_set_pin(dapm, pin, 0); | ||
3733 | |||
3734 | mutex_unlock(&dapm->card->dapm_mutex); | ||
3735 | |||
3736 | return ret; | ||
3829 | } | 3737 | } |
3830 | EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); | 3738 | EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); |
3831 | 3739 | ||
3832 | /** | 3740 | /** |
3741 | * snd_soc_dapm_nc_pin_unlocked - permanently disable pin. | ||
3742 | * @dapm: DAPM context | ||
3743 | * @pin: pin name | ||
3744 | * | ||
3745 | * Marks the specified pin as being not connected, disabling it along | ||
3746 | * any parent or child widgets. At present this is identical to | ||
3747 | * snd_soc_dapm_disable_pin() but in future it will be extended to do | ||
3748 | * additional things such as disabling controls which only affect | ||
3749 | * paths through the pin. | ||
3750 | * | ||
3751 | * Requires external locking. | ||
3752 | * | ||
3753 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | ||
3754 | * do any widget power switching. | ||
3755 | */ | ||
3756 | int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm, | ||
3757 | const char *pin) | ||
3758 | { | ||
3759 | return snd_soc_dapm_set_pin(dapm, pin, 0); | ||
3760 | } | ||
3761 | EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin_unlocked); | ||
3762 | |||
3763 | /** | ||
3833 | * snd_soc_dapm_nc_pin - permanently disable pin. | 3764 | * snd_soc_dapm_nc_pin - permanently disable pin. |
3834 | * @dapm: DAPM context | 3765 | * @dapm: DAPM context |
3835 | * @pin: pin name | 3766 | * @pin: pin name |
@@ -3845,7 +3776,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); | |||
3845 | */ | 3776 | */ |
3846 | int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin) | 3777 | int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin) |
3847 | { | 3778 | { |
3848 | return snd_soc_dapm_set_pin(dapm, pin, 0); | 3779 | int ret; |
3780 | |||
3781 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
3782 | |||
3783 | ret = snd_soc_dapm_set_pin(dapm, pin, 0); | ||
3784 | |||
3785 | mutex_unlock(&dapm->card->dapm_mutex); | ||
3786 | |||
3787 | return ret; | ||
3849 | } | 3788 | } |
3850 | EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); | 3789 | EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); |
3851 | 3790 | ||
@@ -3985,7 +3924,7 @@ void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm) | |||
3985 | } | 3924 | } |
3986 | EXPORT_SYMBOL_GPL(snd_soc_dapm_free); | 3925 | EXPORT_SYMBOL_GPL(snd_soc_dapm_free); |
3987 | 3926 | ||
3988 | static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) | 3927 | static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) |
3989 | { | 3928 | { |
3990 | struct snd_soc_card *card = dapm->card; | 3929 | struct snd_soc_card *card = dapm->card; |
3991 | struct snd_soc_dapm_widget *w; | 3930 | struct snd_soc_dapm_widget *w; |
@@ -4025,14 +3964,21 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) | |||
4025 | */ | 3964 | */ |
4026 | void snd_soc_dapm_shutdown(struct snd_soc_card *card) | 3965 | void snd_soc_dapm_shutdown(struct snd_soc_card *card) |
4027 | { | 3966 | { |
4028 | struct snd_soc_codec *codec; | 3967 | struct snd_soc_dapm_context *dapm; |
4029 | 3968 | ||
4030 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { | 3969 | list_for_each_entry(dapm, &card->dapm_list, list) { |
4031 | soc_dapm_shutdown_codec(&codec->dapm); | 3970 | if (dapm != &card->dapm) { |
4032 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) | 3971 | soc_dapm_shutdown_dapm(dapm); |
4033 | snd_soc_dapm_set_bias_level(&codec->dapm, | 3972 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) |
4034 | SND_SOC_BIAS_OFF); | 3973 | snd_soc_dapm_set_bias_level(dapm, |
3974 | SND_SOC_BIAS_OFF); | ||
3975 | } | ||
4035 | } | 3976 | } |
3977 | |||
3978 | soc_dapm_shutdown_dapm(&card->dapm); | ||
3979 | if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY) | ||
3980 | snd_soc_dapm_set_bias_level(&card->dapm, | ||
3981 | SND_SOC_BIAS_OFF); | ||
4036 | } | 3982 | } |
4037 | 3983 | ||
4038 | /* Module information */ | 3984 | /* Module information */ |
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index aa886cca3ecf..260efc8466fc 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c | |||
@@ -23,21 +23,6 @@ | |||
23 | static int hw_write(struct snd_soc_codec *codec, unsigned int reg, | 23 | static int hw_write(struct snd_soc_codec *codec, unsigned int reg, |
24 | unsigned int value) | 24 | unsigned int value) |
25 | { | 25 | { |
26 | int ret; | ||
27 | |||
28 | if (!snd_soc_codec_volatile_register(codec, reg) && | ||
29 | reg < codec->driver->reg_cache_size && | ||
30 | !codec->cache_bypass) { | ||
31 | ret = snd_soc_cache_write(codec, reg, value); | ||
32 | if (ret < 0) | ||
33 | return -1; | ||
34 | } | ||
35 | |||
36 | if (codec->cache_only) { | ||
37 | codec->cache_sync = 1; | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | return regmap_write(codec->control_data, reg, value); | 26 | return regmap_write(codec->control_data, reg, value); |
42 | } | 27 | } |
43 | 28 | ||
@@ -46,32 +31,18 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) | |||
46 | int ret; | 31 | int ret; |
47 | unsigned int val; | 32 | unsigned int val; |
48 | 33 | ||
49 | if (reg >= codec->driver->reg_cache_size || | 34 | ret = regmap_read(codec->control_data, reg, &val); |
50 | snd_soc_codec_volatile_register(codec, reg) || | 35 | if (ret == 0) |
51 | codec->cache_bypass) { | 36 | return val; |
52 | if (codec->cache_only) | 37 | else |
53 | return -1; | ||
54 | |||
55 | ret = regmap_read(codec->control_data, reg, &val); | ||
56 | if (ret == 0) | ||
57 | return val; | ||
58 | else | ||
59 | return -1; | ||
60 | } | ||
61 | |||
62 | ret = snd_soc_cache_read(codec, reg, &val); | ||
63 | if (ret < 0) | ||
64 | return -1; | 38 | return -1; |
65 | return val; | ||
66 | } | 39 | } |
67 | 40 | ||
68 | /** | 41 | /** |
69 | * snd_soc_codec_set_cache_io: Set up standard I/O functions. | 42 | * snd_soc_codec_set_cache_io: Set up standard I/O functions. |
70 | * | 43 | * |
71 | * @codec: CODEC to configure. | 44 | * @codec: CODEC to configure. |
72 | * @addr_bits: Number of bits of register address data. | 45 | * @map: Register map to write to |
73 | * @data_bits: Number of bits of data per register. | ||
74 | * @control: Control bus used. | ||
75 | * | 46 | * |
76 | * Register formats are frequently shared between many I2C and SPI | 47 | * Register formats are frequently shared between many I2C and SPI |
77 | * devices. In order to promote code reuse the ASoC core provides | 48 | * devices. In order to promote code reuse the ASoC core provides |
@@ -85,60 +56,36 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) | |||
85 | * volatile registers. | 56 | * volatile registers. |
86 | */ | 57 | */ |
87 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | 58 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, |
88 | int addr_bits, int data_bits, | 59 | struct regmap *regmap) |
89 | enum snd_soc_control_type control) | ||
90 | { | 60 | { |
91 | struct regmap_config config; | ||
92 | int ret; | 61 | int ret; |
93 | 62 | ||
94 | memset(&config, 0, sizeof(config)); | 63 | /* Device has made its own regmap arrangements */ |
95 | codec->write = hw_write; | 64 | if (!regmap) |
96 | codec->read = hw_read; | 65 | codec->control_data = dev_get_regmap(codec->dev, NULL); |
97 | 66 | else | |
98 | config.reg_bits = addr_bits; | 67 | codec->control_data = regmap; |
99 | config.val_bits = data_bits; | ||
100 | 68 | ||
101 | switch (control) { | 69 | if (IS_ERR(codec->control_data)) |
102 | #if IS_ENABLED(CONFIG_REGMAP_I2C) | 70 | return PTR_ERR(codec->control_data); |
103 | case SND_SOC_I2C: | ||
104 | codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev), | ||
105 | &config); | ||
106 | break; | ||
107 | #endif | ||
108 | 71 | ||
109 | #if IS_ENABLED(CONFIG_REGMAP_SPI) | 72 | codec->write = hw_write; |
110 | case SND_SOC_SPI: | 73 | codec->read = hw_read; |
111 | codec->control_data = regmap_init_spi(to_spi_device(codec->dev), | ||
112 | &config); | ||
113 | break; | ||
114 | #endif | ||
115 | |||
116 | case SND_SOC_REGMAP: | ||
117 | /* Device has made its own regmap arrangements */ | ||
118 | codec->using_regmap = true; | ||
119 | if (!codec->control_data) | ||
120 | codec->control_data = dev_get_regmap(codec->dev, NULL); | ||
121 | 74 | ||
122 | if (codec->control_data) { | 75 | ret = regmap_get_val_bytes(codec->control_data); |
123 | ret = regmap_get_val_bytes(codec->control_data); | 76 | /* Errors are legitimate for non-integer byte |
124 | /* Errors are legitimate for non-integer byte | 77 | * multiples */ |
125 | * multiples */ | 78 | if (ret > 0) |
126 | if (ret > 0) | 79 | codec->val_bytes = ret; |
127 | codec->val_bytes = ret; | ||
128 | } | ||
129 | break; | ||
130 | 80 | ||
131 | default: | 81 | codec->using_regmap = true; |
132 | return -EINVAL; | ||
133 | } | ||
134 | 82 | ||
135 | return PTR_ERR_OR_ZERO(codec->control_data); | 83 | return 0; |
136 | } | 84 | } |
137 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); | 85 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); |
138 | #else | 86 | #else |
139 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | 87 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, |
140 | int addr_bits, int data_bits, | 88 | struct regmap *regmap) |
141 | enum snd_soc_control_type control) | ||
142 | { | 89 | { |
143 | return -ENOTSUPP; | 90 | return -ENOTSUPP; |
144 | } | 91 | } |
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 23d43dac91da..b903f822d1b2 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
@@ -250,7 +250,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) | |||
250 | report = 0; | 250 | report = 0; |
251 | 251 | ||
252 | if (gpio->jack_status_check) | 252 | if (gpio->jack_status_check) |
253 | report = gpio->jack_status_check(); | 253 | report = gpio->jack_status_check(gpio->data); |
254 | 254 | ||
255 | snd_soc_jack_report(jack, report, gpio->report); | 255 | snd_soc_jack_report(jack, report, gpio->report); |
256 | } | 256 | } |
@@ -342,7 +342,8 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, | |||
342 | gpio_export(gpios[i].gpio, false); | 342 | gpio_export(gpios[i].gpio, false); |
343 | 343 | ||
344 | /* Update initial jack status */ | 344 | /* Update initial jack status */ |
345 | snd_soc_jack_gpio_detect(&gpios[i]); | 345 | schedule_delayed_work(&gpios[i].work, |
346 | msecs_to_jiffies(gpios[i].debounce_time)); | ||
346 | } | 347 | } |
347 | 348 | ||
348 | return 0; | 349 | return 0; |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 47e1ce771e65..2cedf09f6d96 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -35,6 +35,86 @@ | |||
35 | #define DPCM_MAX_BE_USERS 8 | 35 | #define DPCM_MAX_BE_USERS 8 |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * snd_soc_runtime_activate() - Increment active count for PCM runtime components | ||
39 | * @rtd: ASoC PCM runtime that is activated | ||
40 | * @stream: Direction of the PCM stream | ||
41 | * | ||
42 | * Increments the active count for all the DAIs and components attached to a PCM | ||
43 | * runtime. Should typically be called when a stream is opened. | ||
44 | * | ||
45 | * Must be called with the rtd->pcm_mutex being held | ||
46 | */ | ||
47 | void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) | ||
48 | { | ||
49 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
50 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
51 | |||
52 | lockdep_assert_held(&rtd->pcm_mutex); | ||
53 | |||
54 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
55 | cpu_dai->playback_active++; | ||
56 | codec_dai->playback_active++; | ||
57 | } else { | ||
58 | cpu_dai->capture_active++; | ||
59 | codec_dai->capture_active++; | ||
60 | } | ||
61 | |||
62 | cpu_dai->active++; | ||
63 | codec_dai->active++; | ||
64 | cpu_dai->component->active++; | ||
65 | codec_dai->component->active++; | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * snd_soc_runtime_deactivate() - Decrement active count for PCM runtime components | ||
70 | * @rtd: ASoC PCM runtime that is deactivated | ||
71 | * @stream: Direction of the PCM stream | ||
72 | * | ||
73 | * Decrements the active count for all the DAIs and components attached to a PCM | ||
74 | * runtime. Should typically be called when a stream is closed. | ||
75 | * | ||
76 | * Must be called with the rtd->pcm_mutex being held | ||
77 | */ | ||
78 | void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) | ||
79 | { | ||
80 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
81 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
82 | |||
83 | lockdep_assert_held(&rtd->pcm_mutex); | ||
84 | |||
85 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
86 | cpu_dai->playback_active--; | ||
87 | codec_dai->playback_active--; | ||
88 | } else { | ||
89 | cpu_dai->capture_active--; | ||
90 | codec_dai->capture_active--; | ||
91 | } | ||
92 | |||
93 | cpu_dai->active--; | ||
94 | codec_dai->active--; | ||
95 | cpu_dai->component->active--; | ||
96 | codec_dai->component->active--; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay | ||
101 | * @rtd: The ASoC PCM runtime that should be checked. | ||
102 | * | ||
103 | * This function checks whether the power down delay should be ignored for a | ||
104 | * specific PCM runtime. Returns true if the delay is 0, if it the DAI link has | ||
105 | * been configured to ignore the delay, or if none of the components benefits | ||
106 | * from having the delay. | ||
107 | */ | ||
108 | bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) | ||
109 | { | ||
110 | if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time) | ||
111 | return true; | ||
112 | |||
113 | return rtd->cpu_dai->component->ignore_pmdown_time && | ||
114 | rtd->codec_dai->component->ignore_pmdown_time; | ||
115 | } | ||
116 | |||
117 | /** | ||
38 | * snd_soc_set_runtime_hwparams - set the runtime hardware parameters | 118 | * snd_soc_set_runtime_hwparams - set the runtime hardware parameters |
39 | * @substream: the pcm substream | 119 | * @substream: the pcm substream |
40 | * @hw: the hardware parameters | 120 | * @hw: the hardware parameters |
@@ -378,16 +458,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
378 | runtime->hw.rate_max); | 458 | runtime->hw.rate_max); |
379 | 459 | ||
380 | dynamic: | 460 | dynamic: |
381 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 461 | |
382 | cpu_dai->playback_active++; | 462 | snd_soc_runtime_activate(rtd, substream->stream); |
383 | codec_dai->playback_active++; | 463 | |
384 | } else { | ||
385 | cpu_dai->capture_active++; | ||
386 | codec_dai->capture_active++; | ||
387 | } | ||
388 | cpu_dai->active++; | ||
389 | codec_dai->active++; | ||
390 | rtd->codec->active++; | ||
391 | mutex_unlock(&rtd->pcm_mutex); | 464 | mutex_unlock(&rtd->pcm_mutex); |
392 | return 0; | 465 | return 0; |
393 | 466 | ||
@@ -459,21 +532,10 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
459 | struct snd_soc_platform *platform = rtd->platform; | 532 | struct snd_soc_platform *platform = rtd->platform; |
460 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 533 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
461 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 534 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
462 | struct snd_soc_codec *codec = rtd->codec; | ||
463 | 535 | ||
464 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 536 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
465 | 537 | ||
466 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 538 | snd_soc_runtime_deactivate(rtd, substream->stream); |
467 | cpu_dai->playback_active--; | ||
468 | codec_dai->playback_active--; | ||
469 | } else { | ||
470 | cpu_dai->capture_active--; | ||
471 | codec_dai->capture_active--; | ||
472 | } | ||
473 | |||
474 | cpu_dai->active--; | ||
475 | codec_dai->active--; | ||
476 | codec->active--; | ||
477 | 539 | ||
478 | /* clear the corresponding DAIs rate when inactive */ | 540 | /* clear the corresponding DAIs rate when inactive */ |
479 | if (!cpu_dai->active) | 541 | if (!cpu_dai->active) |
@@ -496,8 +558,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
496 | cpu_dai->runtime = NULL; | 558 | cpu_dai->runtime = NULL; |
497 | 559 | ||
498 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 560 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
499 | if (!rtd->pmdown_time || codec->ignore_pmdown_time || | 561 | if (snd_soc_runtime_ignore_pmdown_time(rtd)) { |
500 | rtd->dai_link->ignore_pmdown_time) { | ||
501 | /* powered down playback stream now */ | 562 | /* powered down playback stream now */ |
502 | snd_soc_dapm_stream_event(rtd, | 563 | snd_soc_dapm_stream_event(rtd, |
503 | SNDRV_PCM_STREAM_PLAYBACK, | 564 | SNDRV_PCM_STREAM_PLAYBACK, |
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c index fe99f461aff0..19cca043e6e4 100644 --- a/sound/soc/spear/spdif_out.c +++ b/sound/soc/spear/spdif_out.c | |||
@@ -213,10 +213,7 @@ static int spdif_digital_mute(struct snd_soc_dai *dai, int mute) | |||
213 | static int spdif_mute_get(struct snd_kcontrol *kcontrol, | 213 | static int spdif_mute_get(struct snd_kcontrol *kcontrol, |
214 | struct snd_ctl_elem_value *ucontrol) | 214 | struct snd_ctl_elem_value *ucontrol) |
215 | { | 215 | { |
216 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 216 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); |
217 | struct snd_soc_card *card = codec->card; | ||
218 | struct snd_soc_pcm_runtime *rtd = card->rtd; | ||
219 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
220 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); | 217 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); |
221 | 218 | ||
222 | ucontrol->value.integer.value[0] = host->saved_params.mute; | 219 | ucontrol->value.integer.value[0] = host->saved_params.mute; |
@@ -226,10 +223,7 @@ static int spdif_mute_get(struct snd_kcontrol *kcontrol, | |||
226 | static int spdif_mute_put(struct snd_kcontrol *kcontrol, | 223 | static int spdif_mute_put(struct snd_kcontrol *kcontrol, |
227 | struct snd_ctl_elem_value *ucontrol) | 224 | struct snd_ctl_elem_value *ucontrol) |
228 | { | 225 | { |
229 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 226 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); |
230 | struct snd_soc_card *card = codec->card; | ||
231 | struct snd_soc_pcm_runtime *rtd = card->rtd; | ||
232 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
233 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); | 227 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); |
234 | 228 | ||
235 | if (host->saved_params.mute == ucontrol->value.integer.value[0]) | 229 | if (host->saved_params.mute == ucontrol->value.integer.value[0]) |
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 9f9c1856f822..31198cf7f88d 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig | |||
@@ -105,7 +105,7 @@ config SND_SOC_TEGRA_TRIMSLICE | |||
105 | tristate "SoC Audio support for TrimSlice board" | 105 | tristate "SoC Audio support for TrimSlice board" |
106 | depends on SND_SOC_TEGRA && I2C | 106 | depends on SND_SOC_TEGRA && I2C |
107 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC | 107 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC |
108 | select SND_SOC_TLV320AIC23 | 108 | select SND_SOC_TLV320AIC23_I2C |
109 | help | 109 | help |
110 | Say Y or M here if you want to add support for SoC audio on the | 110 | Say Y or M here if you want to add support for SoC audio on the |
111 | TrimSlice platform. | 111 | TrimSlice platform. |
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index cf5e1cfe818d..0a59e2383ef3 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c | |||
@@ -306,7 +306,7 @@ static const struct regmap_config tegra20_ac97_regmap_config = { | |||
306 | .readable_reg = tegra20_ac97_wr_rd_reg, | 306 | .readable_reg = tegra20_ac97_wr_rd_reg, |
307 | .volatile_reg = tegra20_ac97_volatile_reg, | 307 | .volatile_reg = tegra20_ac97_volatile_reg, |
308 | .precious_reg = tegra20_ac97_precious_reg, | 308 | .precious_reg = tegra20_ac97_precious_reg, |
309 | .cache_type = REGCACHE_RBTREE, | 309 | .cache_type = REGCACHE_FLAT, |
310 | }; | 310 | }; |
311 | 311 | ||
312 | static int tegra20_ac97_platform_probe(struct platform_device *pdev) | 312 | static int tegra20_ac97_platform_probe(struct platform_device *pdev) |
diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c index e72392927bd2..a634f13b3ffc 100644 --- a/sound/soc/tegra/tegra20_das.c +++ b/sound/soc/tegra/tegra20_das.c | |||
@@ -128,7 +128,7 @@ static const struct regmap_config tegra20_das_regmap_config = { | |||
128 | .max_register = LAST_REG(DAC_INPUT_DATA_CLK_SEL), | 128 | .max_register = LAST_REG(DAC_INPUT_DATA_CLK_SEL), |
129 | .writeable_reg = tegra20_das_wr_rd_reg, | 129 | .writeable_reg = tegra20_das_wr_rd_reg, |
130 | .readable_reg = tegra20_das_wr_rd_reg, | 130 | .readable_reg = tegra20_das_wr_rd_reg, |
131 | .cache_type = REGCACHE_RBTREE, | 131 | .cache_type = REGCACHE_FLAT, |
132 | }; | 132 | }; |
133 | 133 | ||
134 | static int tegra20_das_probe(struct platform_device *pdev) | 134 | static int tegra20_das_probe(struct platform_device *pdev) |
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 42c1f6bfaf2e..79a9932ffe6e 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c | |||
@@ -333,7 +333,7 @@ static const struct regmap_config tegra20_i2s_regmap_config = { | |||
333 | .readable_reg = tegra20_i2s_wr_rd_reg, | 333 | .readable_reg = tegra20_i2s_wr_rd_reg, |
334 | .volatile_reg = tegra20_i2s_volatile_reg, | 334 | .volatile_reg = tegra20_i2s_volatile_reg, |
335 | .precious_reg = tegra20_i2s_precious_reg, | 335 | .precious_reg = tegra20_i2s_precious_reg, |
336 | .cache_type = REGCACHE_RBTREE, | 336 | .cache_type = REGCACHE_FLAT, |
337 | }; | 337 | }; |
338 | 338 | ||
339 | static int tegra20_i2s_platform_probe(struct platform_device *pdev) | 339 | static int tegra20_i2s_platform_probe(struct platform_device *pdev) |
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 8c7c1028e579..a0ce92400faf 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c | |||
@@ -259,7 +259,7 @@ static const struct regmap_config tegra20_spdif_regmap_config = { | |||
259 | .readable_reg = tegra20_spdif_wr_rd_reg, | 259 | .readable_reg = tegra20_spdif_wr_rd_reg, |
260 | .volatile_reg = tegra20_spdif_volatile_reg, | 260 | .volatile_reg = tegra20_spdif_volatile_reg, |
261 | .precious_reg = tegra20_spdif_precious_reg, | 261 | .precious_reg = tegra20_spdif_precious_reg, |
262 | .cache_type = REGCACHE_RBTREE, | 262 | .cache_type = REGCACHE_FLAT, |
263 | }; | 263 | }; |
264 | 264 | ||
265 | static int tegra20_spdif_platform_probe(struct platform_device *pdev) | 265 | static int tegra20_spdif_platform_probe(struct platform_device *pdev) |
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index d6f4c9940e0c..0db68f49f4d9 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c | |||
@@ -471,7 +471,7 @@ static const struct regmap_config tegra30_ahub_apbif_regmap_config = { | |||
471 | .readable_reg = tegra30_ahub_apbif_wr_rd_reg, | 471 | .readable_reg = tegra30_ahub_apbif_wr_rd_reg, |
472 | .volatile_reg = tegra30_ahub_apbif_volatile_reg, | 472 | .volatile_reg = tegra30_ahub_apbif_volatile_reg, |
473 | .precious_reg = tegra30_ahub_apbif_precious_reg, | 473 | .precious_reg = tegra30_ahub_apbif_precious_reg, |
474 | .cache_type = REGCACHE_RBTREE, | 474 | .cache_type = REGCACHE_FLAT, |
475 | }; | 475 | }; |
476 | 476 | ||
477 | static bool tegra30_ahub_ahub_wr_rd_reg(struct device *dev, unsigned int reg) | 477 | static bool tegra30_ahub_ahub_wr_rd_reg(struct device *dev, unsigned int reg) |
@@ -490,7 +490,7 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = { | |||
490 | .max_register = LAST_REG(AUDIO_RX), | 490 | .max_register = LAST_REG(AUDIO_RX), |
491 | .writeable_reg = tegra30_ahub_ahub_wr_rd_reg, | 491 | .writeable_reg = tegra30_ahub_ahub_wr_rd_reg, |
492 | .readable_reg = tegra30_ahub_ahub_wr_rd_reg, | 492 | .readable_reg = tegra30_ahub_ahub_wr_rd_reg, |
493 | .cache_type = REGCACHE_RBTREE, | 493 | .cache_type = REGCACHE_FLAT, |
494 | }; | 494 | }; |
495 | 495 | ||
496 | static struct tegra30_ahub_soc_data soc_data_tegra30 = { | 496 | static struct tegra30_ahub_soc_data soc_data_tegra30 = { |
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 49ad9366add8..f146c41dd3ec 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c | |||
@@ -357,7 +357,7 @@ static const struct regmap_config tegra30_i2s_regmap_config = { | |||
357 | .writeable_reg = tegra30_i2s_wr_rd_reg, | 357 | .writeable_reg = tegra30_i2s_wr_rd_reg, |
358 | .readable_reg = tegra30_i2s_wr_rd_reg, | 358 | .readable_reg = tegra30_i2s_wr_rd_reg, |
359 | .volatile_reg = tegra30_i2s_volatile_reg, | 359 | .volatile_reg = tegra30_i2s_volatile_reg, |
360 | .cache_type = REGCACHE_RBTREE, | 360 | .cache_type = REGCACHE_FLAT, |
361 | }; | 361 | }; |
362 | 362 | ||
363 | static const struct tegra30_i2s_soc_data tegra30_i2s_config = { | 363 | static const struct tegra30_i2s_soc_data tegra30_i2s_config = { |
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index e0305a148568..9edd68db9f48 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c | |||
@@ -183,14 +183,16 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
183 | irq = platform_get_irq(pdev, 0); | 183 | irq = platform_get_irq(pdev, 0); |
184 | if (irq < 0) | 184 | if (irq < 0) |
185 | return irq; | 185 | return irq; |
186 | |||
187 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); | ||
188 | if (!drvdata) | ||
189 | return -ENOMEM; | ||
190 | |||
186 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 191 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
187 | drvdata->base = devm_ioremap_resource(&pdev->dev, r); | 192 | drvdata->base = devm_ioremap_resource(&pdev->dev, r); |
188 | if (IS_ERR(drvdata->base)) | 193 | if (IS_ERR(drvdata->base)) |
189 | return PTR_ERR(drvdata->base); | 194 | return PTR_ERR(drvdata->base); |
190 | 195 | ||
191 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); | ||
192 | if (!drvdata) | ||
193 | return -ENOMEM; | ||
194 | platform_set_drvdata(pdev, drvdata); | 196 | platform_set_drvdata(pdev, drvdata); |
195 | drvdata->physbase = r->start; | 197 | drvdata->physbase = r->start; |
196 | if (sizeof(drvdata->physbase) > sizeof(r->start) && | 198 | if (sizeof(drvdata->physbase) > sizeof(r->start) && |
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index de9408b83f75..e05a86b7c0da 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -14,6 +14,7 @@ config SND_USB_AUDIO | |||
14 | select SND_HWDEP | 14 | select SND_HWDEP |
15 | select SND_RAWMIDI | 15 | select SND_RAWMIDI |
16 | select SND_PCM | 16 | select SND_PCM |
17 | select BITREVERSE | ||
17 | help | 18 | help |
18 | Say Y here to include support for USB audio and USB MIDI | 19 | Say Y here to include support for USB audio and USB MIDI |
19 | devices. | 20 | devices. |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 44b0ba4feab3..1bed780e21d9 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -883,6 +883,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, | |||
883 | } | 883 | } |
884 | break; | 884 | break; |
885 | 885 | ||
886 | case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */ | ||
886 | case USB_ID(0x046d, 0x0808): | 887 | case USB_ID(0x046d, 0x0808): |
887 | case USB_ID(0x046d, 0x0809): | 888 | case USB_ID(0x046d, 0x0809): |
888 | case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */ | 889 | case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */ |
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c index 32af6b741ef5..d1d72ff50347 100644 --- a/sound/usb/mixer_maps.c +++ b/sound/usb/mixer_maps.c | |||
@@ -328,6 +328,11 @@ static struct usbmix_name_map gamecom780_map[] = { | |||
328 | {} | 328 | {} |
329 | }; | 329 | }; |
330 | 330 | ||
331 | static const struct usbmix_name_map kef_x300a_map[] = { | ||
332 | { 10, NULL }, /* firmware locks up (?) when we try to access this FU */ | ||
333 | { 0 } | ||
334 | }; | ||
335 | |||
331 | /* | 336 | /* |
332 | * Control map entries | 337 | * Control map entries |
333 | */ | 338 | */ |
@@ -419,6 +424,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { | |||
419 | .id = USB_ID(0x200c, 0x1018), | 424 | .id = USB_ID(0x200c, 0x1018), |
420 | .map = ebox44_map, | 425 | .map = ebox44_map, |
421 | }, | 426 | }, |
427 | { | ||
428 | .id = USB_ID(0x27ac, 0x1000), | ||
429 | .map = kef_x300a_map, | ||
430 | }, | ||
422 | { 0 } /* terminator */ | 431 | { 0 } /* terminator */ |
423 | }; | 432 | }; |
424 | 433 | ||