diff options
203 files changed, 11371 insertions, 3034 deletions
diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl index 58ced2346e67..598c22f3b3ac 100644 --- a/Documentation/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl | |||
@@ -1164,7 +1164,7 @@ | |||
1164 | } | 1164 | } |
1165 | chip->port = pci_resource_start(pci, 0); | 1165 | chip->port = pci_resource_start(pci, 0); |
1166 | if (request_irq(pci->irq, snd_mychip_interrupt, | 1166 | if (request_irq(pci->irq, snd_mychip_interrupt, |
1167 | IRQF_SHARED, "My Chip", chip)) { | 1167 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
1168 | printk(KERN_ERR "cannot grab irq %d\n", pci->irq); | 1168 | printk(KERN_ERR "cannot grab irq %d\n", pci->irq); |
1169 | snd_mychip_free(chip); | 1169 | snd_mychip_free(chip); |
1170 | return -EBUSY; | 1170 | return -EBUSY; |
@@ -1197,7 +1197,7 @@ | |||
1197 | 1197 | ||
1198 | /* pci_driver definition */ | 1198 | /* pci_driver definition */ |
1199 | static struct pci_driver driver = { | 1199 | static struct pci_driver driver = { |
1200 | .name = "My Own Chip", | 1200 | .name = KBUILD_MODNAME, |
1201 | .id_table = snd_mychip_ids, | 1201 | .id_table = snd_mychip_ids, |
1202 | .probe = snd_mychip_probe, | 1202 | .probe = snd_mychip_probe, |
1203 | .remove = __devexit_p(snd_mychip_remove), | 1203 | .remove = __devexit_p(snd_mychip_remove), |
@@ -1340,7 +1340,7 @@ | |||
1340 | <programlisting> | 1340 | <programlisting> |
1341 | <![CDATA[ | 1341 | <![CDATA[ |
1342 | if (request_irq(pci->irq, snd_mychip_interrupt, | 1342 | if (request_irq(pci->irq, snd_mychip_interrupt, |
1343 | IRQF_SHARED, "My Chip", chip)) { | 1343 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
1344 | printk(KERN_ERR "cannot grab irq %d\n", pci->irq); | 1344 | printk(KERN_ERR "cannot grab irq %d\n", pci->irq); |
1345 | snd_mychip_free(chip); | 1345 | snd_mychip_free(chip); |
1346 | return -EBUSY; | 1346 | return -EBUSY; |
@@ -1616,7 +1616,7 @@ | |||
1616 | <programlisting> | 1616 | <programlisting> |
1617 | <![CDATA[ | 1617 | <![CDATA[ |
1618 | static struct pci_driver driver = { | 1618 | static struct pci_driver driver = { |
1619 | .name = "My Own Chip", | 1619 | .name = KBUILD_MODNAME, |
1620 | .id_table = snd_mychip_ids, | 1620 | .id_table = snd_mychip_ids, |
1621 | .probe = snd_mychip_probe, | 1621 | .probe = snd_mychip_probe, |
1622 | .remove = __devexit_p(snd_mychip_remove), | 1622 | .remove = __devexit_p(snd_mychip_remove), |
@@ -5816,7 +5816,7 @@ struct _snd_pcm_runtime { | |||
5816 | <programlisting> | 5816 | <programlisting> |
5817 | <![CDATA[ | 5817 | <![CDATA[ |
5818 | static struct pci_driver driver = { | 5818 | static struct pci_driver driver = { |
5819 | .name = "My Chip", | 5819 | .name = KBUILD_MODNAME, |
5820 | .id_table = snd_my_ids, | 5820 | .id_table = snd_my_ids, |
5821 | .probe = snd_my_probe, | 5821 | .probe = snd_my_probe, |
5822 | .remove = __devexit_p(snd_my_remove), | 5822 | .remove = __devexit_p(snd_my_remove), |
diff --git a/MAINTAINERS b/MAINTAINERS index 29801f760b6f..7bcc3951189f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -533,6 +533,8 @@ L: device-drivers-devel@blackfin.uclinux.org | |||
533 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 533 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
534 | W: http://wiki.analog.com/ | 534 | W: http://wiki.analog.com/ |
535 | S: Supported | 535 | S: Supported |
536 | F: sound/soc/codecs/adau* | ||
537 | F: sound/soc/codecs/adav* | ||
536 | F: sound/soc/codecs/ad1* | 538 | F: sound/soc/codecs/ad1* |
537 | F: sound/soc/codecs/ssm* | 539 | F: sound/soc/codecs/ssm* |
538 | 540 | ||
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index a311008af5e1..f23f8bf02b04 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -1308,6 +1308,7 @@ | |||
1308 | #define PCI_SUBDEVICE_ID_CREATIVE_SB08801 0x0041 | 1308 | #define PCI_SUBDEVICE_ID_CREATIVE_SB08801 0x0041 |
1309 | #define PCI_SUBDEVICE_ID_CREATIVE_SB08802 0x0042 | 1309 | #define PCI_SUBDEVICE_ID_CREATIVE_SB08802 0x0042 |
1310 | #define PCI_SUBDEVICE_ID_CREATIVE_SB08803 0x0043 | 1310 | #define PCI_SUBDEVICE_ID_CREATIVE_SB08803 0x0043 |
1311 | #define PCI_SUBDEVICE_ID_CREATIVE_SB1270 0x0062 | ||
1311 | #define PCI_SUBDEVICE_ID_CREATIVE_HENDRIX 0x6000 | 1312 | #define PCI_SUBDEVICE_ID_CREATIVE_HENDRIX 0x6000 |
1312 | 1313 | ||
1313 | #define PCI_VENDOR_ID_ECTIVA 0x1102 /* duplicate: CREATIVE */ | 1314 | #define PCI_VENDOR_ID_ECTIVA 0x1102 /* duplicate: CREATIVE */ |
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index 2480e7d10dcf..6b14359d9fed 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
28 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
30 | #include <linux/workqueue.h> | ||
30 | 31 | ||
31 | #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) | 32 | #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) |
32 | #include "seq_device.h" | 33 | #include "seq_device.h" |
@@ -63,6 +64,7 @@ struct snd_rawmidi_global_ops { | |||
63 | }; | 64 | }; |
64 | 65 | ||
65 | struct snd_rawmidi_runtime { | 66 | struct snd_rawmidi_runtime { |
67 | struct snd_rawmidi_substream *substream; | ||
66 | unsigned int drain: 1, /* drain stage */ | 68 | unsigned int drain: 1, /* drain stage */ |
67 | oss: 1; /* OSS compatible mode */ | 69 | oss: 1; /* OSS compatible mode */ |
68 | /* midi stream buffer */ | 70 | /* midi stream buffer */ |
@@ -79,7 +81,7 @@ struct snd_rawmidi_runtime { | |||
79 | /* event handler (new bytes, input only) */ | 81 | /* event handler (new bytes, input only) */ |
80 | void (*event)(struct snd_rawmidi_substream *substream); | 82 | void (*event)(struct snd_rawmidi_substream *substream); |
81 | /* defers calls to event [input] or ops->trigger [output] */ | 83 | /* defers calls to event [input] or ops->trigger [output] */ |
82 | struct tasklet_struct tasklet; | 84 | struct work_struct event_work; |
83 | /* private data */ | 85 | /* private data */ |
84 | void *private_data; | 86 | void *private_data; |
85 | void (*private_free)(struct snd_rawmidi_substream *substream); | 87 | void (*private_free)(struct snd_rawmidi_substream *substream); |
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 1bafe95dcf41..5ad5f3a50c68 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h | |||
@@ -209,6 +209,10 @@ struct snd_soc_dai_driver { | |||
209 | struct snd_soc_pcm_stream capture; | 209 | struct snd_soc_pcm_stream capture; |
210 | struct snd_soc_pcm_stream playback; | 210 | struct snd_soc_pcm_stream playback; |
211 | unsigned int symmetric_rates:1; | 211 | unsigned int symmetric_rates:1; |
212 | |||
213 | /* probe ordering - for components with runtime dependencies */ | ||
214 | int probe_order; | ||
215 | int remove_order; | ||
212 | }; | 216 | }; |
213 | 217 | ||
214 | /* | 218 | /* |
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c46e7d89561d..e09505c5a490 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -348,6 +348,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm); | |||
348 | void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm); | 348 | void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm); |
349 | int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, | 349 | int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, |
350 | const struct snd_soc_dapm_route *route, int num); | 350 | const struct snd_soc_dapm_route *route, int num); |
351 | int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm, | ||
352 | const struct snd_soc_dapm_route *route, int num); | ||
351 | 353 | ||
352 | /* dapm events */ | 354 | /* dapm events */ |
353 | int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, | 355 | int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, |
@@ -429,6 +431,7 @@ struct snd_soc_dapm_path { | |||
429 | /* status */ | 431 | /* status */ |
430 | u32 connect:1; /* source and sink widgets are connected */ | 432 | u32 connect:1; /* source and sink widgets are connected */ |
431 | u32 walked:1; /* path has been walked */ | 433 | u32 walked:1; /* path has been walked */ |
434 | u32 weak:1; /* path ignored for power management */ | ||
432 | 435 | ||
433 | int (*connected)(struct snd_soc_dapm_widget *source, | 436 | int (*connected)(struct snd_soc_dapm_widget *source, |
434 | struct snd_soc_dapm_widget *sink); | 437 | struct snd_soc_dapm_widget *sink); |
@@ -444,6 +447,7 @@ struct snd_soc_dapm_widget { | |||
444 | char *name; /* widget name */ | 447 | char *name; /* widget name */ |
445 | char *sname; /* stream name */ | 448 | char *sname; /* stream name */ |
446 | struct snd_soc_codec *codec; | 449 | struct snd_soc_codec *codec; |
450 | struct snd_soc_platform *platform; | ||
447 | struct list_head list; | 451 | struct list_head list; |
448 | struct snd_soc_dapm_context *dapm; | 452 | struct snd_soc_dapm_context *dapm; |
449 | 453 | ||
@@ -507,10 +511,11 @@ struct snd_soc_dapm_context { | |||
507 | 511 | ||
508 | struct device *dev; /* from parent - for debug */ | 512 | struct device *dev; /* from parent - for debug */ |
509 | struct snd_soc_codec *codec; /* parent codec */ | 513 | struct snd_soc_codec *codec; /* parent codec */ |
514 | struct snd_soc_platform *platform; /* parent platform */ | ||
510 | struct snd_soc_card *card; /* parent card */ | 515 | struct snd_soc_card *card; /* parent card */ |
511 | 516 | ||
512 | /* used during DAPM updates */ | 517 | /* used during DAPM updates */ |
513 | int dev_power; | 518 | enum snd_soc_bias_level target_bias_level; |
514 | struct list_head list; | 519 | struct list_head list; |
515 | 520 | ||
516 | #ifdef CONFIG_DEBUG_FS | 521 | #ifdef CONFIG_DEBUG_FS |
diff --git a/include/sound/soc.h b/include/sound/soc.h index 3a4bd3a3c68d..aa19f5a32ba8 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -203,6 +203,16 @@ | |||
203 | SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues) | 203 | SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues) |
204 | 204 | ||
205 | /* | 205 | /* |
206 | * Component probe and remove ordering levels for components with runtime | ||
207 | * dependencies. | ||
208 | */ | ||
209 | #define SND_SOC_COMP_ORDER_FIRST -2 | ||
210 | #define SND_SOC_COMP_ORDER_EARLY -1 | ||
211 | #define SND_SOC_COMP_ORDER_NORMAL 0 | ||
212 | #define SND_SOC_COMP_ORDER_LATE 1 | ||
213 | #define SND_SOC_COMP_ORDER_LAST 2 | ||
214 | |||
215 | /* | ||
206 | * Bias levels | 216 | * Bias levels |
207 | * | 217 | * |
208 | * @ON: Bias is fully on for audio playback and capture operations. | 218 | * @ON: Bias is fully on for audio playback and capture operations. |
@@ -214,10 +224,10 @@ | |||
214 | * @OFF: Power Off. No restrictions on transition times. | 224 | * @OFF: Power Off. No restrictions on transition times. |
215 | */ | 225 | */ |
216 | enum snd_soc_bias_level { | 226 | enum snd_soc_bias_level { |
217 | SND_SOC_BIAS_OFF, | 227 | SND_SOC_BIAS_OFF = 0, |
218 | SND_SOC_BIAS_STANDBY, | 228 | SND_SOC_BIAS_STANDBY = 1, |
219 | SND_SOC_BIAS_PREPARE, | 229 | SND_SOC_BIAS_PREPARE = 2, |
220 | SND_SOC_BIAS_ON, | 230 | SND_SOC_BIAS_ON = 3, |
221 | }; | 231 | }; |
222 | 232 | ||
223 | struct snd_jack; | 233 | struct snd_jack; |
@@ -258,6 +268,11 @@ enum snd_soc_compress_type { | |||
258 | SND_SOC_RBTREE_COMPRESSION | 268 | SND_SOC_RBTREE_COMPRESSION |
259 | }; | 269 | }; |
260 | 270 | ||
271 | enum snd_soc_pcm_subclass { | ||
272 | SND_SOC_PCM_CLASS_PCM = 0, | ||
273 | SND_SOC_PCM_CLASS_BE = 1, | ||
274 | }; | ||
275 | |||
261 | int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, | 276 | int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, |
262 | unsigned int freq, int dir); | 277 | unsigned int freq, int dir); |
263 | int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, | 278 | int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, |
@@ -297,6 +312,10 @@ int snd_soc_default_readable_register(struct snd_soc_codec *codec, | |||
297 | unsigned int reg); | 312 | unsigned int reg); |
298 | int snd_soc_default_writable_register(struct snd_soc_codec *codec, | 313 | int snd_soc_default_writable_register(struct snd_soc_codec *codec, |
299 | unsigned int reg); | 314 | unsigned int reg); |
315 | int snd_soc_platform_read(struct snd_soc_platform *platform, | ||
316 | unsigned int reg); | ||
317 | int snd_soc_platform_write(struct snd_soc_platform *platform, | ||
318 | unsigned int reg, unsigned int val); | ||
300 | 319 | ||
301 | /* Utility functions to get clock rates from various things */ | 320 | /* Utility functions to get clock rates from various things */ |
302 | int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); | 321 | int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); |
@@ -349,6 +368,8 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, | |||
349 | const char *prefix); | 368 | const char *prefix); |
350 | int snd_soc_add_controls(struct snd_soc_codec *codec, | 369 | int snd_soc_add_controls(struct snd_soc_codec *codec, |
351 | const struct snd_kcontrol_new *controls, int num_controls); | 370 | const struct snd_kcontrol_new *controls, int num_controls); |
371 | int snd_soc_add_platform_controls(struct snd_soc_platform *platform, | ||
372 | const struct snd_kcontrol_new *controls, int num_controls); | ||
352 | int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, | 373 | int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, |
353 | struct snd_ctl_elem_info *uinfo); | 374 | struct snd_ctl_elem_info *uinfo); |
354 | int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol, | 375 | int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol, |
@@ -612,6 +633,10 @@ struct snd_soc_codec_driver { | |||
612 | 633 | ||
613 | void (*seq_notifier)(struct snd_soc_dapm_context *, | 634 | void (*seq_notifier)(struct snd_soc_dapm_context *, |
614 | enum snd_soc_dapm_type, int); | 635 | enum snd_soc_dapm_type, int); |
636 | |||
637 | /* probe ordering - for components with runtime dependencies */ | ||
638 | int probe_order; | ||
639 | int remove_order; | ||
615 | }; | 640 | }; |
616 | 641 | ||
617 | /* SoC platform interface */ | 642 | /* SoC platform interface */ |
@@ -623,10 +648,17 @@ struct snd_soc_platform_driver { | |||
623 | int (*resume)(struct snd_soc_dai *dai); | 648 | int (*resume)(struct snd_soc_dai *dai); |
624 | 649 | ||
625 | /* pcm creation and destruction */ | 650 | /* pcm creation and destruction */ |
626 | int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, | 651 | int (*pcm_new)(struct snd_soc_pcm_runtime *); |
627 | struct snd_pcm *); | ||
628 | void (*pcm_free)(struct snd_pcm *); | 652 | void (*pcm_free)(struct snd_pcm *); |
629 | 653 | ||
654 | /* Default control and setup, added after probe() is run */ | ||
655 | const struct snd_kcontrol_new *controls; | ||
656 | int num_controls; | ||
657 | const struct snd_soc_dapm_widget *dapm_widgets; | ||
658 | int num_dapm_widgets; | ||
659 | const struct snd_soc_dapm_route *dapm_routes; | ||
660 | int num_dapm_routes; | ||
661 | |||
630 | /* | 662 | /* |
631 | * For platform caused delay reporting. | 663 | * For platform caused delay reporting. |
632 | * Optional. | 664 | * Optional. |
@@ -636,6 +668,14 @@ struct snd_soc_platform_driver { | |||
636 | 668 | ||
637 | /* platform stream ops */ | 669 | /* platform stream ops */ |
638 | struct snd_pcm_ops *ops; | 670 | struct snd_pcm_ops *ops; |
671 | |||
672 | /* probe ordering - for components with runtime dependencies */ | ||
673 | int probe_order; | ||
674 | int remove_order; | ||
675 | |||
676 | /* platform IO - used for platform DAPM */ | ||
677 | unsigned int (*read)(struct snd_soc_platform *, unsigned int); | ||
678 | int (*write)(struct snd_soc_platform *, unsigned int, unsigned int); | ||
639 | }; | 679 | }; |
640 | 680 | ||
641 | struct snd_soc_platform { | 681 | struct snd_soc_platform { |
@@ -650,6 +690,8 @@ struct snd_soc_platform { | |||
650 | struct snd_soc_card *card; | 690 | struct snd_soc_card *card; |
651 | struct list_head list; | 691 | struct list_head list; |
652 | struct list_head card_list; | 692 | struct list_head card_list; |
693 | |||
694 | struct snd_soc_dapm_context dapm; | ||
653 | }; | 695 | }; |
654 | 696 | ||
655 | struct snd_soc_dai_link { | 697 | struct snd_soc_dai_link { |
@@ -725,8 +767,10 @@ struct snd_soc_card { | |||
725 | 767 | ||
726 | /* callbacks */ | 768 | /* callbacks */ |
727 | int (*set_bias_level)(struct snd_soc_card *, | 769 | int (*set_bias_level)(struct snd_soc_card *, |
770 | struct snd_soc_dapm_context *dapm, | ||
728 | enum snd_soc_bias_level level); | 771 | enum snd_soc_bias_level level); |
729 | int (*set_bias_level_post)(struct snd_soc_card *, | 772 | int (*set_bias_level_post)(struct snd_soc_card *, |
773 | struct snd_soc_dapm_context *dapm, | ||
730 | enum snd_soc_bias_level level); | 774 | enum snd_soc_bias_level level); |
731 | 775 | ||
732 | long pmdown_time; | 776 | long pmdown_time; |
@@ -789,6 +833,9 @@ struct snd_soc_pcm_runtime { | |||
789 | struct device dev; | 833 | struct device dev; |
790 | struct snd_soc_card *card; | 834 | struct snd_soc_card *card; |
791 | struct snd_soc_dai_link *dai_link; | 835 | struct snd_soc_dai_link *dai_link; |
836 | struct mutex pcm_mutex; | ||
837 | enum snd_soc_pcm_subclass pcm_subclass; | ||
838 | struct snd_pcm_ops ops; | ||
792 | 839 | ||
793 | unsigned int complete:1; | 840 | unsigned int complete:1; |
794 | unsigned int dev_registered:1; | 841 | unsigned int dev_registered:1; |
diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h index ae973d2e27a1..603f5a0f0365 100644 --- a/include/trace/events/asoc.h +++ b/include/trace/events/asoc.h | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | struct snd_soc_jack; | 10 | struct snd_soc_jack; |
11 | struct snd_soc_codec; | 11 | struct snd_soc_codec; |
12 | struct snd_soc_platform; | ||
12 | struct snd_soc_card; | 13 | struct snd_soc_card; |
13 | struct snd_soc_dapm_widget; | 14 | struct snd_soc_dapm_widget; |
14 | 15 | ||
@@ -59,6 +60,50 @@ DEFINE_EVENT(snd_soc_reg, snd_soc_reg_read, | |||
59 | 60 | ||
60 | ); | 61 | ); |
61 | 62 | ||
63 | DECLARE_EVENT_CLASS(snd_soc_preg, | ||
64 | |||
65 | TP_PROTO(struct snd_soc_platform *platform, unsigned int reg, | ||
66 | unsigned int val), | ||
67 | |||
68 | TP_ARGS(platform, reg, val), | ||
69 | |||
70 | TP_STRUCT__entry( | ||
71 | __string( name, platform->name ) | ||
72 | __field( int, id ) | ||
73 | __field( unsigned int, reg ) | ||
74 | __field( unsigned int, val ) | ||
75 | ), | ||
76 | |||
77 | TP_fast_assign( | ||
78 | __assign_str(name, platform->name); | ||
79 | __entry->id = platform->id; | ||
80 | __entry->reg = reg; | ||
81 | __entry->val = val; | ||
82 | ), | ||
83 | |||
84 | TP_printk("platform=%s.%d reg=%x val=%x", __get_str(name), | ||
85 | (int)__entry->id, (unsigned int)__entry->reg, | ||
86 | (unsigned int)__entry->val) | ||
87 | ); | ||
88 | |||
89 | DEFINE_EVENT(snd_soc_preg, snd_soc_preg_write, | ||
90 | |||
91 | TP_PROTO(struct snd_soc_platform *platform, unsigned int reg, | ||
92 | unsigned int val), | ||
93 | |||
94 | TP_ARGS(platform, reg, val) | ||
95 | |||
96 | ); | ||
97 | |||
98 | DEFINE_EVENT(snd_soc_preg, snd_soc_preg_read, | ||
99 | |||
100 | TP_PROTO(struct snd_soc_platform *platform, unsigned int reg, | ||
101 | unsigned int val), | ||
102 | |||
103 | TP_ARGS(platform, reg, val) | ||
104 | |||
105 | ); | ||
106 | |||
62 | DECLARE_EVENT_CLASS(snd_soc_card, | 107 | DECLARE_EVENT_CLASS(snd_soc_card, |
63 | 108 | ||
64 | TP_PROTO(struct snd_soc_card *card, int val), | 109 | TP_PROTO(struct snd_soc_card *card, int val), |
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index cbbed0db9e56..849a0ed95054 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
@@ -92,16 +92,12 @@ static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substre | |||
92 | (!substream->append || runtime->avail >= count); | 92 | (!substream->append || runtime->avail >= count); |
93 | } | 93 | } |
94 | 94 | ||
95 | static void snd_rawmidi_input_event_tasklet(unsigned long data) | 95 | static void snd_rawmidi_input_event_work(struct work_struct *work) |
96 | { | 96 | { |
97 | struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *)data; | 97 | struct snd_rawmidi_runtime *runtime = |
98 | substream->runtime->event(substream); | 98 | container_of(work, struct snd_rawmidi_runtime, event_work); |
99 | } | 99 | if (runtime->event) |
100 | 100 | runtime->event(runtime->substream); | |
101 | static void snd_rawmidi_output_trigger_tasklet(unsigned long data) | ||
102 | { | ||
103 | struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *)data; | ||
104 | substream->ops->trigger(substream, 1); | ||
105 | } | 101 | } |
106 | 102 | ||
107 | static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) | 103 | static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) |
@@ -110,16 +106,10 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) | |||
110 | 106 | ||
111 | if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL) | 107 | if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL) |
112 | return -ENOMEM; | 108 | return -ENOMEM; |
109 | runtime->substream = substream; | ||
113 | spin_lock_init(&runtime->lock); | 110 | spin_lock_init(&runtime->lock); |
114 | init_waitqueue_head(&runtime->sleep); | 111 | init_waitqueue_head(&runtime->sleep); |
115 | if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT) | 112 | INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work); |
116 | tasklet_init(&runtime->tasklet, | ||
117 | snd_rawmidi_input_event_tasklet, | ||
118 | (unsigned long)substream); | ||
119 | else | ||
120 | tasklet_init(&runtime->tasklet, | ||
121 | snd_rawmidi_output_trigger_tasklet, | ||
122 | (unsigned long)substream); | ||
123 | runtime->event = NULL; | 113 | runtime->event = NULL; |
124 | runtime->buffer_size = PAGE_SIZE; | 114 | runtime->buffer_size = PAGE_SIZE; |
125 | runtime->avail_min = 1; | 115 | runtime->avail_min = 1; |
@@ -150,12 +140,7 @@ static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *subs | |||
150 | { | 140 | { |
151 | if (!substream->opened) | 141 | if (!substream->opened) |
152 | return; | 142 | return; |
153 | if (up) { | 143 | substream->ops->trigger(substream, up); |
154 | tasklet_schedule(&substream->runtime->tasklet); | ||
155 | } else { | ||
156 | tasklet_kill(&substream->runtime->tasklet); | ||
157 | substream->ops->trigger(substream, 0); | ||
158 | } | ||
159 | } | 144 | } |
160 | 145 | ||
161 | static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) | 146 | static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) |
@@ -163,8 +148,8 @@ static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, i | |||
163 | if (!substream->opened) | 148 | if (!substream->opened) |
164 | return; | 149 | return; |
165 | substream->ops->trigger(substream, up); | 150 | substream->ops->trigger(substream, up); |
166 | if (!up && substream->runtime->event) | 151 | if (!up) |
167 | tasklet_kill(&substream->runtime->tasklet); | 152 | cancel_work_sync(&substream->runtime->event_work); |
168 | } | 153 | } |
169 | 154 | ||
170 | int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream) | 155 | int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream) |
@@ -641,10 +626,10 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, | |||
641 | return -EINVAL; | 626 | return -EINVAL; |
642 | } | 627 | } |
643 | if (params->buffer_size != runtime->buffer_size) { | 628 | if (params->buffer_size != runtime->buffer_size) { |
644 | newbuf = kmalloc(params->buffer_size, GFP_KERNEL); | 629 | newbuf = krealloc(runtime->buffer, params->buffer_size, |
630 | GFP_KERNEL); | ||
645 | if (!newbuf) | 631 | if (!newbuf) |
646 | return -ENOMEM; | 632 | return -ENOMEM; |
647 | kfree(runtime->buffer); | ||
648 | runtime->buffer = newbuf; | 633 | runtime->buffer = newbuf; |
649 | runtime->buffer_size = params->buffer_size; | 634 | runtime->buffer_size = params->buffer_size; |
650 | runtime->avail = runtime->buffer_size; | 635 | runtime->avail = runtime->buffer_size; |
@@ -668,10 +653,10 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, | |||
668 | return -EINVAL; | 653 | return -EINVAL; |
669 | } | 654 | } |
670 | if (params->buffer_size != runtime->buffer_size) { | 655 | if (params->buffer_size != runtime->buffer_size) { |
671 | newbuf = kmalloc(params->buffer_size, GFP_KERNEL); | 656 | newbuf = krealloc(runtime->buffer, params->buffer_size, |
657 | GFP_KERNEL); | ||
672 | if (!newbuf) | 658 | if (!newbuf) |
673 | return -ENOMEM; | 659 | return -ENOMEM; |
674 | kfree(runtime->buffer); | ||
675 | runtime->buffer = newbuf; | 660 | runtime->buffer = newbuf; |
676 | runtime->buffer_size = params->buffer_size; | 661 | runtime->buffer_size = params->buffer_size; |
677 | } | 662 | } |
@@ -926,7 +911,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, | |||
926 | } | 911 | } |
927 | if (result > 0) { | 912 | if (result > 0) { |
928 | if (runtime->event) | 913 | if (runtime->event) |
929 | tasklet_schedule(&runtime->tasklet); | 914 | schedule_work(&runtime->event_work); |
930 | else if (snd_rawmidi_ready(substream)) | 915 | else if (snd_rawmidi_ready(substream)) |
931 | wake_up(&runtime->sleep); | 916 | wake_up(&runtime->sleep); |
932 | } | 917 | } |
diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c index 5466de8527bd..3fc257da180c 100644 --- a/sound/firewire/speakers.c +++ b/sound/firewire/speakers.c | |||
@@ -171,7 +171,7 @@ static int fwspk_open(struct snd_pcm_substream *substream) | |||
171 | 171 | ||
172 | err = snd_pcm_hw_constraint_minmax(runtime, | 172 | err = snd_pcm_hw_constraint_minmax(runtime, |
173 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | 173 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, |
174 | 5000, 8192000); | 174 | 5000, UINT_MAX); |
175 | if (err < 0) | 175 | if (err < 0) |
176 | return err; | 176 | return err; |
177 | 177 | ||
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index d8f6fd65ebbb..201503673f25 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c | |||
@@ -944,7 +944,7 @@ snd_ad1889_create(struct snd_card *card, | |||
944 | spin_lock_init(&chip->lock); /* only now can we call ad1889_free */ | 944 | spin_lock_init(&chip->lock); /* only now can we call ad1889_free */ |
945 | 945 | ||
946 | if (request_irq(pci->irq, snd_ad1889_interrupt, | 946 | if (request_irq(pci->irq, snd_ad1889_interrupt, |
947 | IRQF_SHARED, card->driver, chip)) { | 947 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
948 | printk(KERN_ERR PFX "cannot obtain IRQ %d\n", pci->irq); | 948 | printk(KERN_ERR PFX "cannot obtain IRQ %d\n", pci->irq); |
949 | snd_ad1889_free(chip); | 949 | snd_ad1889_free(chip); |
950 | return -EBUSY; | 950 | return -EBUSY; |
@@ -1055,7 +1055,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_ad1889_ids) = { | |||
1055 | MODULE_DEVICE_TABLE(pci, snd_ad1889_ids); | 1055 | MODULE_DEVICE_TABLE(pci, snd_ad1889_ids); |
1056 | 1056 | ||
1057 | static struct pci_driver ad1889_pci_driver = { | 1057 | static struct pci_driver ad1889_pci_driver = { |
1058 | .name = "AD1889 Audio", | 1058 | .name = KBUILD_MODNAME, |
1059 | .id_table = snd_ad1889_ids, | 1059 | .id_table = snd_ad1889_ids, |
1060 | .probe = snd_ad1889_probe, | 1060 | .probe = snd_ad1889_probe, |
1061 | .remove = __devexit_p(snd_ad1889_remove), | 1061 | .remove = __devexit_p(snd_ad1889_remove), |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 5c6e322a48f0..b444b74d9dcf 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -2090,7 +2090,7 @@ static int __devinit snd_ali_resources(struct snd_ali *codec) | |||
2090 | codec->port = pci_resource_start(codec->pci, 0); | 2090 | codec->port = pci_resource_start(codec->pci, 0); |
2091 | 2091 | ||
2092 | if (request_irq(codec->pci->irq, snd_ali_card_interrupt, | 2092 | if (request_irq(codec->pci->irq, snd_ali_card_interrupt, |
2093 | IRQF_SHARED, "ALI 5451", codec)) { | 2093 | IRQF_SHARED, KBUILD_MODNAME, codec)) { |
2094 | snd_printk(KERN_ERR "Unable to request irq.\n"); | 2094 | snd_printk(KERN_ERR "Unable to request irq.\n"); |
2095 | return -EBUSY; | 2095 | return -EBUSY; |
2096 | } | 2096 | } |
@@ -2295,7 +2295,7 @@ static void __devexit snd_ali_remove(struct pci_dev *pci) | |||
2295 | } | 2295 | } |
2296 | 2296 | ||
2297 | static struct pci_driver driver = { | 2297 | static struct pci_driver driver = { |
2298 | .name = "ALI 5451", | 2298 | .name = KBUILD_MODNAME, |
2299 | .id_table = snd_ali_ids, | 2299 | .id_table = snd_ali_ids, |
2300 | .probe = snd_ali_probe, | 2300 | .probe = snd_ali_probe, |
2301 | .remove = __devexit_p(snd_ali_remove), | 2301 | .remove = __devexit_p(snd_ali_remove), |
diff --git a/sound/pci/als300.c b/sound/pci/als300.c index d7653cb7ac60..736c8e93db1f 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c | |||
@@ -722,7 +722,7 @@ static int __devinit snd_als300_create(struct snd_card *card, | |||
722 | irq_handler = snd_als300_interrupt; | 722 | irq_handler = snd_als300_interrupt; |
723 | 723 | ||
724 | if (request_irq(pci->irq, irq_handler, IRQF_SHARED, | 724 | if (request_irq(pci->irq, irq_handler, IRQF_SHARED, |
725 | card->shortname, chip)) { | 725 | KBUILD_MODNAME, chip)) { |
726 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 726 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
727 | snd_als300_free(chip); | 727 | snd_als300_free(chip); |
728 | return -EBUSY; | 728 | return -EBUSY; |
@@ -846,7 +846,7 @@ static int __devinit snd_als300_probe(struct pci_dev *pci, | |||
846 | } | 846 | } |
847 | 847 | ||
848 | static struct pci_driver driver = { | 848 | static struct pci_driver driver = { |
849 | .name = "ALS300", | 849 | .name = KBUILD_MODNAME, |
850 | .id_table = snd_als300_ids, | 850 | .id_table = snd_als300_ids, |
851 | .probe = snd_als300_probe, | 851 | .probe = snd_als300_probe, |
852 | .remove = __devexit_p(snd_als300_remove), | 852 | .remove = __devexit_p(snd_als300_remove), |
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 0e247cb90ecc..a9c1af33f276 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
@@ -1036,7 +1036,7 @@ static int snd_als4000_resume(struct pci_dev *pci) | |||
1036 | 1036 | ||
1037 | 1037 | ||
1038 | static struct pci_driver driver = { | 1038 | static struct pci_driver driver = { |
1039 | .name = "ALS4000", | 1039 | .name = KBUILD_MODNAME, |
1040 | .id_table = snd_als4000_ids, | 1040 | .id_table = snd_als4000_ids, |
1041 | .probe = snd_card_als4000_probe, | 1041 | .probe = snd_card_als4000_probe, |
1042 | .remove = __devexit_p(snd_card_als4000_remove), | 1042 | .remove = __devexit_p(snd_card_als4000_remove), |
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index e3569bdd3b64..b941d2541dda 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c | |||
@@ -49,19 +49,21 @@ MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx"); | |||
49 | #if defined CONFIG_SND_DEBUG | 49 | #if defined CONFIG_SND_DEBUG |
50 | /* copied from pcm_lib.c, hope later patch will make that version public | 50 | /* copied from pcm_lib.c, hope later patch will make that version public |
51 | and this copy can be removed */ | 51 | and this copy can be removed */ |
52 | static void pcm_debug_name(struct snd_pcm_substream *substream, | 52 | static inline void |
53 | char *name, size_t len) | 53 | snd_pcm_debug_name(struct snd_pcm_substream *substream, char *buf, size_t size) |
54 | { | 54 | { |
55 | snprintf(name, len, "pcmC%dD%d%c:%d", | 55 | snprintf(buf, size, "pcmC%dD%d%c:%d", |
56 | substream->pcm->card->number, | 56 | substream->pcm->card->number, |
57 | substream->pcm->device, | 57 | substream->pcm->device, |
58 | substream->stream ? 'c' : 'p', | 58 | substream->stream ? 'c' : 'p', |
59 | substream->number); | 59 | substream->number); |
60 | } | 60 | } |
61 | #define DEBUG_NAME(substream, name) char name[16]; pcm_debug_name(substream, name, sizeof(name)) | ||
62 | #else | 61 | #else |
63 | #define pcm_debug_name(s, n, l) do { } while (0) | 62 | static inline void |
64 | #define DEBUG_NAME(name, substream) do { } while (0) | 63 | snd_pcm_debug_name(struct snd_pcm_substream *substream, char *buf, size_t size) |
64 | { | ||
65 | *buf = 0; | ||
66 | } | ||
65 | #endif | 67 | #endif |
66 | 68 | ||
67 | #if defined CONFIG_SND_DEBUG_VERBOSE | 69 | #if defined CONFIG_SND_DEBUG_VERBOSE |
@@ -304,7 +306,8 @@ static u16 handle_error(u16 err, int line, char *filename) | |||
304 | static void print_hwparams(struct snd_pcm_substream *substream, | 306 | static void print_hwparams(struct snd_pcm_substream *substream, |
305 | struct snd_pcm_hw_params *p) | 307 | struct snd_pcm_hw_params *p) |
306 | { | 308 | { |
307 | DEBUG_NAME(substream, name); | 309 | char name[16]; |
310 | snd_pcm_debug_name(substream, name, sizeof(name)); | ||
308 | snd_printd("%s HWPARAMS\n", name); | 311 | snd_printd("%s HWPARAMS\n", name); |
309 | snd_printd(" samplerate %d Hz\n", params_rate(p)); | 312 | snd_printd(" samplerate %d Hz\n", params_rate(p)); |
310 | snd_printd(" channels %d\n", params_channels(p)); | 313 | snd_printd(" channels %d\n", params_channels(p)); |
@@ -576,8 +579,9 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, | |||
576 | struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); | 579 | struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); |
577 | struct snd_pcm_substream *s; | 580 | struct snd_pcm_substream *s; |
578 | u16 e; | 581 | u16 e; |
579 | DEBUG_NAME(substream, name); | 582 | char name[16]; |
580 | 583 | ||
584 | snd_pcm_debug_name(substream, name, sizeof(name)); | ||
581 | snd_printdd("%s trigger\n", name); | 585 | snd_printdd("%s trigger\n", name); |
582 | 586 | ||
583 | switch (cmd) { | 587 | switch (cmd) { |
@@ -741,7 +745,9 @@ static void snd_card_asihpi_timer_function(unsigned long data) | |||
741 | int loops = 0; | 745 | int loops = 0; |
742 | u16 state; | 746 | u16 state; |
743 | u32 buffer_size, bytes_avail, samples_played, on_card_bytes; | 747 | u32 buffer_size, bytes_avail, samples_played, on_card_bytes; |
744 | DEBUG_NAME(substream, name); | 748 | char name[16]; |
749 | |||
750 | snd_pcm_debug_name(substream, name, sizeof(name)); | ||
745 | 751 | ||
746 | snd_printdd("%s snd_card_asihpi_timer_function\n", name); | 752 | snd_printdd("%s snd_card_asihpi_timer_function\n", name); |
747 | 753 | ||
@@ -1323,10 +1329,12 @@ static const char * const asihpi_src_names[] = { | |||
1323 | "RF", | 1329 | "RF", |
1324 | "Clock", | 1330 | "Clock", |
1325 | "Bitstream", | 1331 | "Bitstream", |
1326 | "Microphone", | 1332 | "Mic", |
1327 | "Cobranet", | 1333 | "Net", |
1328 | "Analog", | 1334 | "Analog", |
1329 | "Adapter", | 1335 | "Adapter", |
1336 | "RTP", | ||
1337 | "GPI", | ||
1330 | }; | 1338 | }; |
1331 | 1339 | ||
1332 | compile_time_assert( | 1340 | compile_time_assert( |
@@ -1341,8 +1349,10 @@ static const char * const asihpi_dst_names[] = { | |||
1341 | "Digital", | 1349 | "Digital", |
1342 | "RF", | 1350 | "RF", |
1343 | "Speaker", | 1351 | "Speaker", |
1344 | "Cobranet Out", | 1352 | "Net", |
1345 | "Analog" | 1353 | "Analog", |
1354 | "RTP", | ||
1355 | "GPO", | ||
1346 | }; | 1356 | }; |
1347 | 1357 | ||
1348 | compile_time_assert( | 1358 | compile_time_assert( |
@@ -1476,11 +1486,40 @@ static int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol, | |||
1476 | 1486 | ||
1477 | static const DECLARE_TLV_DB_SCALE(db_scale_100, -10000, VOL_STEP_mB, 0); | 1487 | static const DECLARE_TLV_DB_SCALE(db_scale_100, -10000, VOL_STEP_mB, 0); |
1478 | 1488 | ||
1489 | #define snd_asihpi_volume_mute_info snd_ctl_boolean_mono_info | ||
1490 | |||
1491 | static int snd_asihpi_volume_mute_get(struct snd_kcontrol *kcontrol, | ||
1492 | struct snd_ctl_elem_value *ucontrol) | ||
1493 | { | ||
1494 | u32 h_control = kcontrol->private_value; | ||
1495 | u32 mute; | ||
1496 | |||
1497 | hpi_handle_error(hpi_volume_get_mute(h_control, &mute)); | ||
1498 | ucontrol->value.integer.value[0] = mute ? 0 : 1; | ||
1499 | |||
1500 | return 0; | ||
1501 | } | ||
1502 | |||
1503 | static int snd_asihpi_volume_mute_put(struct snd_kcontrol *kcontrol, | ||
1504 | struct snd_ctl_elem_value *ucontrol) | ||
1505 | { | ||
1506 | u32 h_control = kcontrol->private_value; | ||
1507 | int change = 1; | ||
1508 | /* HPI currently only supports all or none muting of multichannel volume | ||
1509 | ALSA Switch element has opposite sense to HPI mute: on==unmuted, off=muted | ||
1510 | */ | ||
1511 | int mute = ucontrol->value.integer.value[0] ? 0 : HPI_BITMASK_ALL_CHANNELS; | ||
1512 | hpi_handle_error(hpi_volume_set_mute(h_control, mute)); | ||
1513 | return change; | ||
1514 | } | ||
1515 | |||
1479 | static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi, | 1516 | static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi, |
1480 | struct hpi_control *hpi_ctl) | 1517 | struct hpi_control *hpi_ctl) |
1481 | { | 1518 | { |
1482 | struct snd_card *card = asihpi->card; | 1519 | struct snd_card *card = asihpi->card; |
1483 | struct snd_kcontrol_new snd_control; | 1520 | struct snd_kcontrol_new snd_control; |
1521 | int err; | ||
1522 | u32 mute; | ||
1484 | 1523 | ||
1485 | asihpi_ctl_init(&snd_control, hpi_ctl, "Volume"); | 1524 | asihpi_ctl_init(&snd_control, hpi_ctl, "Volume"); |
1486 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | 1525 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | |
@@ -1490,7 +1529,19 @@ static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi, | |||
1490 | snd_control.put = snd_asihpi_volume_put; | 1529 | snd_control.put = snd_asihpi_volume_put; |
1491 | snd_control.tlv.p = db_scale_100; | 1530 | snd_control.tlv.p = db_scale_100; |
1492 | 1531 | ||
1493 | return ctl_add(card, &snd_control, asihpi); | 1532 | err = ctl_add(card, &snd_control, asihpi); |
1533 | if (err) | ||
1534 | return err; | ||
1535 | |||
1536 | if (hpi_volume_get_mute(hpi_ctl->h_control, &mute) == 0) { | ||
1537 | asihpi_ctl_init(&snd_control, hpi_ctl, "Switch"); | ||
1538 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | ||
1539 | snd_control.info = snd_asihpi_volume_mute_info; | ||
1540 | snd_control.get = snd_asihpi_volume_mute_get; | ||
1541 | snd_control.put = snd_asihpi_volume_mute_put; | ||
1542 | err = ctl_add(card, &snd_control, asihpi); | ||
1543 | } | ||
1544 | return err; | ||
1494 | } | 1545 | } |
1495 | 1546 | ||
1496 | /*------------------------------------------------------------ | 1547 | /*------------------------------------------------------------ |
@@ -2923,7 +2974,7 @@ static DEFINE_PCI_DEVICE_TABLE(asihpi_pci_tbl) = { | |||
2923 | MODULE_DEVICE_TABLE(pci, asihpi_pci_tbl); | 2974 | MODULE_DEVICE_TABLE(pci, asihpi_pci_tbl); |
2924 | 2975 | ||
2925 | static struct pci_driver driver = { | 2976 | static struct pci_driver driver = { |
2926 | .name = "asihpi", | 2977 | .name = KBUILD_MODNAME, |
2927 | .id_table = asihpi_pci_tbl, | 2978 | .id_table = asihpi_pci_tbl, |
2928 | .probe = snd_asihpi_probe, | 2979 | .probe = snd_asihpi_probe, |
2929 | .remove = __devexit_p(snd_asihpi_remove), | 2980 | .remove = __devexit_p(snd_asihpi_remove), |
diff --git a/sound/pci/asihpi/hpi.h b/sound/pci/asihpi/hpi.h index 255429c32c1c..f20727288994 100644 --- a/sound/pci/asihpi/hpi.h +++ b/sound/pci/asihpi/hpi.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | 2 | ||
3 | AudioScience HPI driver | 3 | AudioScience HPI driver |
4 | Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com> | 4 | Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> |
5 | 5 | ||
6 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of version 2 of the GNU General Public License as | 7 | it under the terms of version 2 of the GNU General Public License as |
@@ -42,12 +42,11 @@ i.e 3.05.02 is a development version | |||
42 | #define HPI_VER_MINOR(v) ((int)((v >> 8) & 0xFF)) | 42 | #define HPI_VER_MINOR(v) ((int)((v >> 8) & 0xFF)) |
43 | #define HPI_VER_RELEASE(v) ((int)(v & 0xFF)) | 43 | #define HPI_VER_RELEASE(v) ((int)(v & 0xFF)) |
44 | 44 | ||
45 | /* Use single digits for versions less that 10 to avoid octal. */ | 45 | #define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 8, 0) |
46 | #define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 6, 0) | 46 | #define HPI_VER_STRING "4.08.00" |
47 | #define HPI_VER_STRING "4.06.00" | ||
48 | 47 | ||
49 | /* Library version as documented in hpi-api-versions.txt */ | 48 | /* Library version as documented in hpi-api-versions.txt */ |
50 | #define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(9, 0, 0) | 49 | #define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(10, 0, 0) |
51 | 50 | ||
52 | #include <linux/types.h> | 51 | #include <linux/types.h> |
53 | #define HPI_BUILD_EXCLUDE_DEPRECATED | 52 | #define HPI_BUILD_EXCLUDE_DEPRECATED |
@@ -211,8 +210,12 @@ enum HPI_SOURCENODES { | |||
211 | HPI_SOURCENODE_COBRANET = 109, | 210 | HPI_SOURCENODE_COBRANET = 109, |
212 | HPI_SOURCENODE_ANALOG = 110, /**< analog input node. */ | 211 | HPI_SOURCENODE_ANALOG = 110, /**< analog input node. */ |
213 | HPI_SOURCENODE_ADAPTER = 111, /**< adapter node. */ | 212 | HPI_SOURCENODE_ADAPTER = 111, /**< adapter node. */ |
213 | /** RTP stream input node - This node is a destination for | ||
214 | packets of RTP audio samples from other devices. */ | ||
215 | HPI_SOURCENODE_RTP_DESTINATION = 112, | ||
216 | HPI_SOURCENODE_GP_IN = 113, /**< general purpose input. */ | ||
214 | /* !!!Update this AND hpidebug.h if you add a new sourcenode type!!! */ | 217 | /* !!!Update this AND hpidebug.h if you add a new sourcenode type!!! */ |
215 | HPI_SOURCENODE_LAST_INDEX = 111 /**< largest ID */ | 218 | HPI_SOURCENODE_LAST_INDEX = 113 /**< largest ID */ |
216 | /* AX6 max sourcenode types = 15 */ | 219 | /* AX6 max sourcenode types = 15 */ |
217 | }; | 220 | }; |
218 | 221 | ||
@@ -228,7 +231,7 @@ enum HPI_DESTNODES { | |||
228 | HPI_DESTNODE_NONE = 200, | 231 | HPI_DESTNODE_NONE = 200, |
229 | /** In Stream (Record) node. */ | 232 | /** In Stream (Record) node. */ |
230 | HPI_DESTNODE_ISTREAM = 201, | 233 | HPI_DESTNODE_ISTREAM = 201, |
231 | HPI_DESTNODE_LINEOUT = 202, /**< line out node. */ | 234 | HPI_DESTNODE_LINEOUT = 202, /**< line out node. */ |
232 | HPI_DESTNODE_AESEBU_OUT = 203, /**< AES/EBU output node. */ | 235 | HPI_DESTNODE_AESEBU_OUT = 203, /**< AES/EBU output node. */ |
233 | HPI_DESTNODE_RF = 204, /**< RF output node. */ | 236 | HPI_DESTNODE_RF = 204, /**< RF output node. */ |
234 | HPI_DESTNODE_SPEAKER = 205, /**< speaker output node. */ | 237 | HPI_DESTNODE_SPEAKER = 205, /**< speaker output node. */ |
@@ -236,9 +239,12 @@ enum HPI_DESTNODES { | |||
236 | Audio samples from the device are sent out on the Cobranet network.*/ | 239 | Audio samples from the device are sent out on the Cobranet network.*/ |
237 | HPI_DESTNODE_COBRANET = 206, | 240 | HPI_DESTNODE_COBRANET = 206, |
238 | HPI_DESTNODE_ANALOG = 207, /**< analog output node. */ | 241 | HPI_DESTNODE_ANALOG = 207, /**< analog output node. */ |
239 | 242 | /** RTP stream output node - This node is a source for | |
243 | packets of RTP audio samples that are sent to other devices. */ | ||
244 | HPI_DESTNODE_RTP_SOURCE = 208, | ||
245 | HPI_DESTNODE_GP_OUT = 209, /**< general purpose output node. */ | ||
240 | /* !!!Update this AND hpidebug.h if you add a new destnode type!!! */ | 246 | /* !!!Update this AND hpidebug.h if you add a new destnode type!!! */ |
241 | HPI_DESTNODE_LAST_INDEX = 207 /**< largest ID */ | 247 | HPI_DESTNODE_LAST_INDEX = 209 /**< largest ID */ |
242 | /* AX6 max destnode types = 15 */ | 248 | /* AX6 max destnode types = 15 */ |
243 | }; | 249 | }; |
244 | 250 | ||
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c index df4aed5295dd..3cc6f11c20aa 100644 --- a/sound/pci/asihpi/hpi6000.c +++ b/sound/pci/asihpi/hpi6000.c | |||
@@ -359,7 +359,7 @@ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr) | |||
359 | HPI_ERROR_PROCESSING_MESSAGE); | 359 | HPI_ERROR_PROCESSING_MESSAGE); |
360 | 360 | ||
361 | switch (phm->type) { | 361 | switch (phm->type) { |
362 | case HPI_TYPE_MESSAGE: | 362 | case HPI_TYPE_REQUEST: |
363 | switch (phm->object) { | 363 | switch (phm->object) { |
364 | case HPI_OBJ_SUBSYSTEM: | 364 | case HPI_OBJ_SUBSYSTEM: |
365 | subsys_message(phm, phr); | 365 | subsys_message(phm, phr); |
@@ -538,7 +538,7 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao, | |||
538 | 538 | ||
539 | HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n"); | 539 | HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n"); |
540 | memset(&hm, 0, sizeof(hm)); | 540 | memset(&hm, 0, sizeof(hm)); |
541 | hm.type = HPI_TYPE_MESSAGE; | 541 | hm.type = HPI_TYPE_REQUEST; |
542 | hm.size = sizeof(struct hpi_message); | 542 | hm.size = sizeof(struct hpi_message); |
543 | hm.object = HPI_OBJ_ADAPTER; | 543 | hm.object = HPI_OBJ_ADAPTER; |
544 | hm.function = HPI_ADAPTER_GET_INFO; | 544 | hm.function = HPI_ADAPTER_GET_INFO; |
@@ -946,11 +946,8 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
946 | } | 946 | } |
947 | 947 | ||
948 | /* write the DSP code down into the DSPs memory */ | 948 | /* write the DSP code down into the DSPs memory */ |
949 | /*HpiDspCode_Open(nBootLoadFamily,&DspCode,pdwOsErrorCode); */ | 949 | error = hpi_dsp_code_open(boot_load_family, pao->pci.pci_dev, |
950 | dsp_code.ps_dev = pao->pci.pci_dev; | 950 | &dsp_code, pos_error_code); |
951 | |||
952 | error = hpi_dsp_code_open(boot_load_family, &dsp_code, | ||
953 | pos_error_code); | ||
954 | 951 | ||
955 | if (error) | 952 | if (error) |
956 | return error; | 953 | return error; |
diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c index 9d5df54a6b46..e041a6ae1c5a 100644 --- a/sound/pci/asihpi/hpi6205.c +++ b/sound/pci/asihpi/hpi6205.c | |||
@@ -373,6 +373,7 @@ static void instream_message(struct hpi_adapter_obj *pao, | |||
373 | /** Entry point to this HPI backend | 373 | /** Entry point to this HPI backend |
374 | * All calls to the HPI start here | 374 | * All calls to the HPI start here |
375 | */ | 375 | */ |
376 | static | ||
376 | void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm, | 377 | void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm, |
377 | struct hpi_response *phr) | 378 | struct hpi_response *phr) |
378 | { | 379 | { |
@@ -392,7 +393,7 @@ void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm, | |||
392 | 393 | ||
393 | HPI_DEBUG_LOG(VERBOSE, "start of switch\n"); | 394 | HPI_DEBUG_LOG(VERBOSE, "start of switch\n"); |
394 | switch (phm->type) { | 395 | switch (phm->type) { |
395 | case HPI_TYPE_MESSAGE: | 396 | case HPI_TYPE_REQUEST: |
396 | switch (phm->object) { | 397 | switch (phm->object) { |
397 | case HPI_OBJ_SUBSYSTEM: | 398 | case HPI_OBJ_SUBSYSTEM: |
398 | subsys_message(pao, phm, phr); | 399 | subsys_message(pao, phm, phr); |
@@ -402,7 +403,6 @@ void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm, | |||
402 | adapter_message(pao, phm, phr); | 403 | adapter_message(pao, phm, phr); |
403 | break; | 404 | break; |
404 | 405 | ||
405 | case HPI_OBJ_CONTROLEX: | ||
406 | case HPI_OBJ_CONTROL: | 406 | case HPI_OBJ_CONTROL: |
407 | control_message(pao, phm, phr); | 407 | control_message(pao, phm, phr); |
408 | break; | 408 | break; |
@@ -634,11 +634,12 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, | |||
634 | 634 | ||
635 | HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n"); | 635 | HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n"); |
636 | memset(&hm, 0, sizeof(hm)); | 636 | memset(&hm, 0, sizeof(hm)); |
637 | hm.type = HPI_TYPE_MESSAGE; | 637 | /* wAdapterIndex == version == 0 */ |
638 | hm.type = HPI_TYPE_REQUEST; | ||
638 | hm.size = sizeof(hm); | 639 | hm.size = sizeof(hm); |
639 | hm.object = HPI_OBJ_ADAPTER; | 640 | hm.object = HPI_OBJ_ADAPTER; |
640 | hm.function = HPI_ADAPTER_GET_INFO; | 641 | hm.function = HPI_ADAPTER_GET_INFO; |
641 | hm.adapter_index = 0; | 642 | |
642 | memset(&hr, 0, sizeof(hr)); | 643 | memset(&hr, 0, sizeof(hr)); |
643 | hr.size = sizeof(hr); | 644 | hr.size = sizeof(hr); |
644 | 645 | ||
@@ -658,9 +659,6 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, | |||
658 | hr.u.ax.info.num_outstreams + | 659 | hr.u.ax.info.num_outstreams + |
659 | hr.u.ax.info.num_instreams; | 660 | hr.u.ax.info.num_instreams; |
660 | 661 | ||
661 | hpios_locked_mem_prepare((max_streams * 6) / 10, max_streams, | ||
662 | 65536, pao->pci.pci_dev); | ||
663 | |||
664 | HPI_DEBUG_LOG(VERBOSE, | 662 | HPI_DEBUG_LOG(VERBOSE, |
665 | "got adapter info type %x index %d serial %d\n", | 663 | "got adapter info type %x index %d serial %d\n", |
666 | hr.u.ax.info.adapter_type, hr.u.ax.info.adapter_index, | 664 | hr.u.ax.info.adapter_type, hr.u.ax.info.adapter_index, |
@@ -709,9 +707,6 @@ static void delete_adapter_obj(struct hpi_adapter_obj *pao) | |||
709 | [i]); | 707 | [i]); |
710 | phw->outstream_host_buffer_size[i] = 0; | 708 | phw->outstream_host_buffer_size[i] = 0; |
711 | } | 709 | } |
712 | |||
713 | hpios_locked_mem_unprepare(pao->pci.pci_dev); | ||
714 | |||
715 | kfree(phw); | 710 | kfree(phw); |
716 | } | 711 | } |
717 | 712 | ||
@@ -1371,9 +1366,8 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1371 | return err; | 1366 | return err; |
1372 | 1367 | ||
1373 | /* write the DSP code down into the DSPs memory */ | 1368 | /* write the DSP code down into the DSPs memory */ |
1374 | dsp_code.ps_dev = pao->pci.pci_dev; | 1369 | err = hpi_dsp_code_open(boot_code_id[dsp], pao->pci.pci_dev, |
1375 | err = hpi_dsp_code_open(boot_code_id[dsp], &dsp_code, | 1370 | &dsp_code, pos_error_code); |
1376 | pos_error_code); | ||
1377 | if (err) | 1371 | if (err) |
1378 | return err; | 1372 | return err; |
1379 | 1373 | ||
@@ -2084,13 +2078,13 @@ static u16 message_response_sequence(struct hpi_adapter_obj *pao, | |||
2084 | u16 err = 0; | 2078 | u16 err = 0; |
2085 | 2079 | ||
2086 | message_count++; | 2080 | message_count++; |
2087 | if (phm->size > sizeof(interface->u)) { | 2081 | if (phm->size > sizeof(interface->u.message_buffer)) { |
2088 | phr->error = HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL; | 2082 | phr->error = HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL; |
2089 | phr->specific_error = sizeof(interface->u); | 2083 | phr->specific_error = sizeof(interface->u.message_buffer); |
2090 | phr->size = sizeof(struct hpi_response_header); | 2084 | phr->size = sizeof(struct hpi_response_header); |
2091 | HPI_DEBUG_LOG(ERROR, | 2085 | HPI_DEBUG_LOG(ERROR, |
2092 | "message len %d too big for buffer %zd \n", phm->size, | 2086 | "message len %d too big for buffer %zd \n", phm->size, |
2093 | sizeof(interface->u)); | 2087 | sizeof(interface->u.message_buffer)); |
2094 | return 0; | 2088 | return 0; |
2095 | } | 2089 | } |
2096 | 2090 | ||
@@ -2122,18 +2116,19 @@ static u16 message_response_sequence(struct hpi_adapter_obj *pao, | |||
2122 | 2116 | ||
2123 | /* read the result */ | 2117 | /* read the result */ |
2124 | if (time_out) { | 2118 | if (time_out) { |
2125 | if (interface->u.response_buffer.size <= phr->size) | 2119 | if (interface->u.response_buffer.response.size <= phr->size) |
2126 | memcpy(phr, &interface->u.response_buffer, | 2120 | memcpy(phr, &interface->u.response_buffer, |
2127 | interface->u.response_buffer.size); | 2121 | interface->u.response_buffer.response.size); |
2128 | else { | 2122 | else { |
2129 | HPI_DEBUG_LOG(ERROR, | 2123 | HPI_DEBUG_LOG(ERROR, |
2130 | "response len %d too big for buffer %d\n", | 2124 | "response len %d too big for buffer %d\n", |
2131 | interface->u.response_buffer.size, phr->size); | 2125 | interface->u.response_buffer.response.size, |
2126 | phr->size); | ||
2132 | memcpy(phr, &interface->u.response_buffer, | 2127 | memcpy(phr, &interface->u.response_buffer, |
2133 | sizeof(struct hpi_response_header)); | 2128 | sizeof(struct hpi_response_header)); |
2134 | phr->error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; | 2129 | phr->error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; |
2135 | phr->specific_error = | 2130 | phr->specific_error = |
2136 | interface->u.response_buffer.size; | 2131 | interface->u.response_buffer.response.size; |
2137 | phr->size = sizeof(struct hpi_response_header); | 2132 | phr->size = sizeof(struct hpi_response_header); |
2138 | } | 2133 | } |
2139 | } | 2134 | } |
@@ -2202,23 +2197,6 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, | |||
2202 | phm->u.d.u.data.data_size, H620_HIF_GET_DATA); | 2197 | phm->u.d.u.data.data_size, H620_HIF_GET_DATA); |
2203 | break; | 2198 | break; |
2204 | 2199 | ||
2205 | case HPI_CONTROL_SET_STATE: | ||
2206 | if (phm->object == HPI_OBJ_CONTROLEX | ||
2207 | && phm->u.cx.attribute == HPI_COBRANET_SET_DATA) | ||
2208 | err = hpi6205_transfer_data(pao, | ||
2209 | phm->u.cx.u.cobranet_bigdata.pb_data, | ||
2210 | phm->u.cx.u.cobranet_bigdata.byte_count, | ||
2211 | H620_HIF_SEND_DATA); | ||
2212 | break; | ||
2213 | |||
2214 | case HPI_CONTROL_GET_STATE: | ||
2215 | if (phm->object == HPI_OBJ_CONTROLEX | ||
2216 | && phm->u.cx.attribute == HPI_COBRANET_GET_DATA) | ||
2217 | err = hpi6205_transfer_data(pao, | ||
2218 | phm->u.cx.u.cobranet_bigdata.pb_data, | ||
2219 | phr->u.cx.u.cobranet_data.byte_count, | ||
2220 | H620_HIF_GET_DATA); | ||
2221 | break; | ||
2222 | } | 2200 | } |
2223 | phr->error = err; | 2201 | phr->error = err; |
2224 | 2202 | ||
diff --git a/sound/pci/asihpi/hpi6205.h b/sound/pci/asihpi/hpi6205.h index df2f02c0c7b4..ec0827b633a6 100644 --- a/sound/pci/asihpi/hpi6205.h +++ b/sound/pci/asihpi/hpi6205.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /***************************************************************************** | 1 | /***************************************************************************** |
2 | 2 | ||
3 | AudioScience HPI driver | 3 | AudioScience HPI driver |
4 | Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com> | 4 | Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> |
5 | 5 | ||
6 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of version 2 of the GNU General Public License as | 7 | it under the terms of version 2 of the GNU General Public License as |
@@ -70,15 +70,28 @@ The Host located memory buffer that the 6205 will bus master | |||
70 | in and out of. | 70 | in and out of. |
71 | ************************************************************/ | 71 | ************************************************************/ |
72 | #define HPI6205_SIZEOF_DATA (16*1024) | 72 | #define HPI6205_SIZEOF_DATA (16*1024) |
73 | |||
74 | struct message_buffer_6205 { | ||
75 | struct hpi_message message; | ||
76 | char data[256]; | ||
77 | }; | ||
78 | |||
79 | struct response_buffer_6205 { | ||
80 | struct hpi_response response; | ||
81 | char data[256]; | ||
82 | }; | ||
83 | |||
84 | union buffer_6205 { | ||
85 | struct message_buffer_6205 message_buffer; | ||
86 | struct response_buffer_6205 response_buffer; | ||
87 | u8 b_data[HPI6205_SIZEOF_DATA]; | ||
88 | }; | ||
89 | |||
73 | struct bus_master_interface { | 90 | struct bus_master_interface { |
74 | u32 host_cmd; | 91 | u32 host_cmd; |
75 | u32 dsp_ack; | 92 | u32 dsp_ack; |
76 | u32 transfer_size_in_bytes; | 93 | u32 transfer_size_in_bytes; |
77 | union { | 94 | union buffer_6205 u; |
78 | struct hpi_message_header message_buffer; | ||
79 | struct hpi_response_header response_buffer; | ||
80 | u8 b_data[HPI6205_SIZEOF_DATA]; | ||
81 | } u; | ||
82 | struct controlcache_6205 control_cache; | 95 | struct controlcache_6205 control_cache; |
83 | struct async_event_buffer_6205 async_buffer; | 96 | struct async_event_buffer_6205 async_buffer; |
84 | struct hpi_hostbuffer_status | 97 | struct hpi_hostbuffer_status |
diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h index bf5eced76bac..d497030c160f 100644 --- a/sound/pci/asihpi/hpi_internal.h +++ b/sound/pci/asihpi/hpi_internal.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | 2 | ||
3 | AudioScience HPI driver | 3 | AudioScience HPI driver |
4 | Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com> | 4 | Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> |
5 | 5 | ||
6 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of version 2 of the GNU General Public License as | 7 | it under the terms of version 2 of the GNU General Public License as |
@@ -32,12 +32,6 @@ HPI internal definitions | |||
32 | #include "hpios.h" | 32 | #include "hpios.h" |
33 | 33 | ||
34 | /* physical memory allocation */ | 34 | /* physical memory allocation */ |
35 | void hpios_locked_mem_init(void | ||
36 | ); | ||
37 | void hpios_locked_mem_free_all(void | ||
38 | ); | ||
39 | #define hpios_locked_mem_prepare(a, b, c, d); | ||
40 | #define hpios_locked_mem_unprepare(a) | ||
41 | 35 | ||
42 | /** Allocate and map an area of locked memory for bus master DMA operations. | 36 | /** Allocate and map an area of locked memory for bus master DMA operations. |
43 | 37 | ||
@@ -226,8 +220,8 @@ enum HPI_CONTROL_ATTRIBUTES { | |||
226 | 220 | ||
227 | HPI_COBRANET_SET = HPI_CTL_ATTR(COBRANET, 1), | 221 | HPI_COBRANET_SET = HPI_CTL_ATTR(COBRANET, 1), |
228 | HPI_COBRANET_GET = HPI_CTL_ATTR(COBRANET, 2), | 222 | HPI_COBRANET_GET = HPI_CTL_ATTR(COBRANET, 2), |
229 | HPI_COBRANET_SET_DATA = HPI_CTL_ATTR(COBRANET, 3), | 223 | /*HPI_COBRANET_SET_DATA = HPI_CTL_ATTR(COBRANET, 3), */ |
230 | HPI_COBRANET_GET_DATA = HPI_CTL_ATTR(COBRANET, 4), | 224 | /*HPI_COBRANET_GET_DATA = HPI_CTL_ATTR(COBRANET, 4), */ |
231 | HPI_COBRANET_GET_STATUS = HPI_CTL_ATTR(COBRANET, 5), | 225 | HPI_COBRANET_GET_STATUS = HPI_CTL_ATTR(COBRANET, 5), |
232 | HPI_COBRANET_SEND_PACKET = HPI_CTL_ATTR(COBRANET, 6), | 226 | HPI_COBRANET_SEND_PACKET = HPI_CTL_ATTR(COBRANET, 6), |
233 | HPI_COBRANET_GET_PACKET = HPI_CTL_ATTR(COBRANET, 7), | 227 | HPI_COBRANET_GET_PACKET = HPI_CTL_ATTR(COBRANET, 7), |
@@ -364,10 +358,12 @@ Used in DLL to indicate device not present | |||
364 | #define HPI_ADAPTER_ASI(f) (f) | 358 | #define HPI_ADAPTER_ASI(f) (f) |
365 | 359 | ||
366 | enum HPI_MESSAGE_TYPES { | 360 | enum HPI_MESSAGE_TYPES { |
367 | HPI_TYPE_MESSAGE = 1, | 361 | HPI_TYPE_REQUEST = 1, |
368 | HPI_TYPE_RESPONSE = 2, | 362 | HPI_TYPE_RESPONSE = 2, |
369 | HPI_TYPE_DATA = 3, | 363 | HPI_TYPE_DATA = 3, |
370 | HPI_TYPE_SSX2BYPASS_MESSAGE = 4 | 364 | HPI_TYPE_SSX2BYPASS_MESSAGE = 4, |
365 | HPI_TYPE_COMMAND = 5, | ||
366 | HPI_TYPE_NOTIFICATION = 6 | ||
371 | }; | 367 | }; |
372 | 368 | ||
373 | enum HPI_OBJECT_TYPES { | 369 | enum HPI_OBJECT_TYPES { |
@@ -383,7 +379,7 @@ enum HPI_OBJECT_TYPES { | |||
383 | HPI_OBJ_WATCHDOG = 10, | 379 | HPI_OBJ_WATCHDOG = 10, |
384 | HPI_OBJ_CLOCK = 11, | 380 | HPI_OBJ_CLOCK = 11, |
385 | HPI_OBJ_PROFILE = 12, | 381 | HPI_OBJ_PROFILE = 12, |
386 | HPI_OBJ_CONTROLEX = 13, | 382 | /* HPI_ OBJ_ CONTROLEX = 13, */ |
387 | HPI_OBJ_ASYNCEVENT = 14 | 383 | HPI_OBJ_ASYNCEVENT = 14 |
388 | #define HPI_OBJ_MAXINDEX 14 | 384 | #define HPI_OBJ_MAXINDEX 14 |
389 | }; | 385 | }; |
@@ -608,7 +604,7 @@ struct hpi_data_compat32 { | |||
608 | #endif | 604 | #endif |
609 | 605 | ||
610 | struct hpi_buffer { | 606 | struct hpi_buffer { |
611 | /** placehoder for backward compatibility (see dwBufferSize) */ | 607 | /** placeholder for backward compatibility (see dwBufferSize) */ |
612 | struct hpi_msg_format reserved; | 608 | struct hpi_msg_format reserved; |
613 | u32 command; /**< HPI_BUFFER_CMD_xxx*/ | 609 | u32 command; /**< HPI_BUFFER_CMD_xxx*/ |
614 | u32 pci_address; /**< PCI physical address of buffer for DSP DMA */ | 610 | u32 pci_address; /**< PCI physical address of buffer for DSP DMA */ |
@@ -912,95 +908,13 @@ union hpi_control_union_res { | |||
912 | u32 remaining_chars; | 908 | u32 remaining_chars; |
913 | } chars8; | 909 | } chars8; |
914 | char c_data12[12]; | 910 | char c_data12[12]; |
915 | }; | ||
916 | |||
917 | /* HPI_CONTROLX_STRUCTURES */ | ||
918 | |||
919 | /* Message */ | ||
920 | |||
921 | /** Used for all HMI variables where max length <= 8 bytes | ||
922 | */ | ||
923 | struct hpi_controlx_msg_cobranet_data { | ||
924 | u32 hmi_address; | ||
925 | u32 byte_count; | ||
926 | u32 data[2]; | ||
927 | }; | ||
928 | |||
929 | /** Used for string data, and for packet bridge | ||
930 | */ | ||
931 | struct hpi_controlx_msg_cobranet_bigdata { | ||
932 | u32 hmi_address; | ||
933 | u32 byte_count; | ||
934 | u8 *pb_data; | ||
935 | #ifndef HPI64BIT | ||
936 | u32 padding; | ||
937 | #endif | ||
938 | }; | ||
939 | |||
940 | /** Used for PADS control reading of string fields. | ||
941 | */ | ||
942 | struct hpi_controlx_msg_pad_data { | ||
943 | u32 field; | ||
944 | u32 byte_count; | ||
945 | u8 *pb_data; | ||
946 | #ifndef HPI64BIT | ||
947 | u32 padding; | ||
948 | #endif | ||
949 | }; | ||
950 | |||
951 | /** Used for generic data | ||
952 | */ | ||
953 | |||
954 | struct hpi_controlx_msg_generic { | ||
955 | u32 param1; | ||
956 | u32 param2; | ||
957 | }; | ||
958 | |||
959 | struct hpi_controlx_msg { | ||
960 | u16 attribute; /* control attribute or property */ | ||
961 | u16 saved_index; | ||
962 | union { | ||
963 | struct hpi_controlx_msg_cobranet_data cobranet_data; | ||
964 | struct hpi_controlx_msg_cobranet_bigdata cobranet_bigdata; | ||
965 | struct hpi_controlx_msg_generic generic; | ||
966 | struct hpi_controlx_msg_pad_data pad_data; | ||
967 | /*struct param_value universal_value; */ | ||
968 | /* nothing extra to send for status read */ | ||
969 | } u; | ||
970 | }; | ||
971 | |||
972 | /* Response */ | ||
973 | /** | ||
974 | */ | ||
975 | struct hpi_controlx_res_cobranet_data { | ||
976 | u32 byte_count; | ||
977 | u32 data[2]; | ||
978 | }; | ||
979 | |||
980 | struct hpi_controlx_res_cobranet_bigdata { | ||
981 | u32 byte_count; | ||
982 | }; | ||
983 | |||
984 | struct hpi_controlx_res_cobranet_status { | ||
985 | u32 status; | ||
986 | u32 readable_size; | ||
987 | u32 writeable_size; | ||
988 | }; | ||
989 | |||
990 | struct hpi_controlx_res_generic { | ||
991 | u32 param1; | ||
992 | u32 param2; | ||
993 | }; | ||
994 | |||
995 | struct hpi_controlx_res { | ||
996 | union { | 911 | union { |
997 | struct hpi_controlx_res_cobranet_bigdata cobranet_bigdata; | 912 | struct { |
998 | struct hpi_controlx_res_cobranet_data cobranet_data; | 913 | u32 status; |
999 | struct hpi_controlx_res_cobranet_status cobranet_status; | 914 | u32 readable_size; |
1000 | struct hpi_controlx_res_generic generic; | 915 | u32 writeable_size; |
1001 | /*struct param_info universal_info; */ | 916 | } status; |
1002 | /*struct param_value universal_value; */ | 917 | } cobranet; |
1003 | } u; | ||
1004 | }; | 918 | }; |
1005 | 919 | ||
1006 | struct hpi_nvmemory_msg { | 920 | struct hpi_nvmemory_msg { |
@@ -1126,7 +1040,6 @@ struct hpi_message { | |||
1126 | /* identical to struct hpi_control_msg, | 1040 | /* identical to struct hpi_control_msg, |
1127 | but field naming is improved */ | 1041 | but field naming is improved */ |
1128 | struct hpi_control_union_msg cu; | 1042 | struct hpi_control_union_msg cu; |
1129 | struct hpi_controlx_msg cx; /* extended mixer control; */ | ||
1130 | struct hpi_nvmemory_msg n; | 1043 | struct hpi_nvmemory_msg n; |
1131 | struct hpi_gpio_msg l; /* digital i/o */ | 1044 | struct hpi_gpio_msg l; /* digital i/o */ |
1132 | struct hpi_watchdog_msg w; | 1045 | struct hpi_watchdog_msg w; |
@@ -1151,7 +1064,7 @@ struct hpi_message { | |||
1151 | sizeof(struct hpi_message_header) + sizeof(struct hpi_watchdog_msg),\ | 1064 | sizeof(struct hpi_message_header) + sizeof(struct hpi_watchdog_msg),\ |
1152 | sizeof(struct hpi_message_header) + sizeof(struct hpi_clock_msg),\ | 1065 | sizeof(struct hpi_message_header) + sizeof(struct hpi_clock_msg),\ |
1153 | sizeof(struct hpi_message_header) + sizeof(struct hpi_profile_msg),\ | 1066 | sizeof(struct hpi_message_header) + sizeof(struct hpi_profile_msg),\ |
1154 | sizeof(struct hpi_message_header) + sizeof(struct hpi_controlx_msg),\ | 1067 | sizeof(struct hpi_message_header), /* controlx obj removed */ \ |
1155 | sizeof(struct hpi_message_header) + sizeof(struct hpi_async_msg) \ | 1068 | sizeof(struct hpi_message_header) + sizeof(struct hpi_async_msg) \ |
1156 | } | 1069 | } |
1157 | 1070 | ||
@@ -1188,7 +1101,6 @@ struct hpi_response { | |||
1188 | struct hpi_control_res c; /* mixer control; */ | 1101 | struct hpi_control_res c; /* mixer control; */ |
1189 | /* identical to hpi_control_res, but field naming is improved */ | 1102 | /* identical to hpi_control_res, but field naming is improved */ |
1190 | union hpi_control_union_res cu; | 1103 | union hpi_control_union_res cu; |
1191 | struct hpi_controlx_res cx; /* extended mixer control; */ | ||
1192 | struct hpi_nvmemory_res n; | 1104 | struct hpi_nvmemory_res n; |
1193 | struct hpi_gpio_res l; /* digital i/o */ | 1105 | struct hpi_gpio_res l; /* digital i/o */ |
1194 | struct hpi_watchdog_res w; | 1106 | struct hpi_watchdog_res w; |
@@ -1213,7 +1125,7 @@ struct hpi_response { | |||
1213 | sizeof(struct hpi_response_header) + sizeof(struct hpi_watchdog_res),\ | 1125 | sizeof(struct hpi_response_header) + sizeof(struct hpi_watchdog_res),\ |
1214 | sizeof(struct hpi_response_header) + sizeof(struct hpi_clock_res),\ | 1126 | sizeof(struct hpi_response_header) + sizeof(struct hpi_clock_res),\ |
1215 | sizeof(struct hpi_response_header) + sizeof(struct hpi_profile_res),\ | 1127 | sizeof(struct hpi_response_header) + sizeof(struct hpi_profile_res),\ |
1216 | sizeof(struct hpi_response_header) + sizeof(struct hpi_controlx_res),\ | 1128 | sizeof(struct hpi_response_header), /* controlx obj removed */ \ |
1217 | sizeof(struct hpi_response_header) + sizeof(struct hpi_async_res) \ | 1129 | sizeof(struct hpi_response_header) + sizeof(struct hpi_async_res) \ |
1218 | } | 1130 | } |
1219 | 1131 | ||
@@ -1308,6 +1220,30 @@ struct hpi_res_adapter_debug_read { | |||
1308 | u8 bytes[256]; | 1220 | u8 bytes[256]; |
1309 | }; | 1221 | }; |
1310 | 1222 | ||
1223 | struct hpi_msg_cobranet_hmi { | ||
1224 | u16 attribute; | ||
1225 | u16 padding; | ||
1226 | u32 hmi_address; | ||
1227 | u32 byte_count; | ||
1228 | }; | ||
1229 | |||
1230 | struct hpi_msg_cobranet_hmiwrite { | ||
1231 | struct hpi_message_header h; | ||
1232 | struct hpi_msg_cobranet_hmi p; | ||
1233 | u8 bytes[256]; | ||
1234 | }; | ||
1235 | |||
1236 | struct hpi_msg_cobranet_hmiread { | ||
1237 | struct hpi_message_header h; | ||
1238 | struct hpi_msg_cobranet_hmi p; | ||
1239 | }; | ||
1240 | |||
1241 | struct hpi_res_cobranet_hmiread { | ||
1242 | struct hpi_response_header h; | ||
1243 | u32 byte_count; | ||
1244 | u8 bytes[256]; | ||
1245 | }; | ||
1246 | |||
1311 | #if 1 | 1247 | #if 1 |
1312 | #define hpi_message_header_v1 hpi_message_header | 1248 | #define hpi_message_header_v1 hpi_message_header |
1313 | #define hpi_response_header_v1 hpi_response_header | 1249 | #define hpi_response_header_v1 hpi_response_header |
@@ -1338,7 +1274,6 @@ struct hpi_msg_payload_v0 { | |||
1338 | union hpi_mixerx_msg mx; | 1274 | union hpi_mixerx_msg mx; |
1339 | struct hpi_control_msg c; | 1275 | struct hpi_control_msg c; |
1340 | struct hpi_control_union_msg cu; | 1276 | struct hpi_control_union_msg cu; |
1341 | struct hpi_controlx_msg cx; | ||
1342 | struct hpi_nvmemory_msg n; | 1277 | struct hpi_nvmemory_msg n; |
1343 | struct hpi_gpio_msg l; | 1278 | struct hpi_gpio_msg l; |
1344 | struct hpi_watchdog_msg w; | 1279 | struct hpi_watchdog_msg w; |
@@ -1358,7 +1293,6 @@ struct hpi_res_payload_v0 { | |||
1358 | union hpi_mixerx_res mx; | 1293 | union hpi_mixerx_res mx; |
1359 | struct hpi_control_res c; | 1294 | struct hpi_control_res c; |
1360 | union hpi_control_union_res cu; | 1295 | union hpi_control_union_res cu; |
1361 | struct hpi_controlx_res cx; | ||
1362 | struct hpi_nvmemory_res n; | 1296 | struct hpi_nvmemory_res n; |
1363 | struct hpi_gpio_res l; | 1297 | struct hpi_gpio_res l; |
1364 | struct hpi_watchdog_res w; | 1298 | struct hpi_watchdog_res w; |
@@ -1493,12 +1427,6 @@ struct hpi_control_cache_microphone { | |||
1493 | char temp_padding[6]; | 1427 | char temp_padding[6]; |
1494 | }; | 1428 | }; |
1495 | 1429 | ||
1496 | struct hpi_control_cache_generic { | ||
1497 | struct hpi_control_cache_info i; | ||
1498 | u32 dw1; | ||
1499 | u32 dw2; | ||
1500 | }; | ||
1501 | |||
1502 | struct hpi_control_cache_single { | 1430 | struct hpi_control_cache_single { |
1503 | union { | 1431 | union { |
1504 | struct hpi_control_cache_info i; | 1432 | struct hpi_control_cache_info i; |
@@ -1514,7 +1442,6 @@ struct hpi_control_cache_single { | |||
1514 | struct hpi_control_cache_silencedetector silence; | 1442 | struct hpi_control_cache_silencedetector silence; |
1515 | struct hpi_control_cache_sampleclock clk; | 1443 | struct hpi_control_cache_sampleclock clk; |
1516 | struct hpi_control_cache_microphone microphone; | 1444 | struct hpi_control_cache_microphone microphone; |
1517 | struct hpi_control_cache_generic generic; | ||
1518 | } u; | 1445 | } u; |
1519 | }; | 1446 | }; |
1520 | 1447 | ||
diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c index b15a02e91f82..65b7ca13115b 100644 --- a/sound/pci/asihpi/hpicmn.c +++ b/sound/pci/asihpi/hpicmn.c | |||
@@ -57,7 +57,7 @@ u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr) | |||
57 | } | 57 | } |
58 | 58 | ||
59 | if (phr->function != phm->function) { | 59 | if (phr->function != phm->function) { |
60 | HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", | 60 | HPI_DEBUG_LOG(ERROR, "header function %d invalid\n", |
61 | phr->function); | 61 | phr->function); |
62 | return HPI_ERROR_INVALID_RESPONSE; | 62 | return HPI_ERROR_INVALID_RESPONSE; |
63 | } | 63 | } |
@@ -315,8 +315,7 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
315 | short found = 1; | 315 | short found = 1; |
316 | struct hpi_control_cache_info *pI; | 316 | struct hpi_control_cache_info *pI; |
317 | struct hpi_control_cache_single *pC; | 317 | struct hpi_control_cache_single *pC; |
318 | struct hpi_control_cache_pad *p_pad; | 318 | size_t response_size; |
319 | |||
320 | if (!find_control(phm->obj_index, p_cache, &pI)) { | 319 | if (!find_control(phm->obj_index, p_cache, &pI)) { |
321 | HPI_DEBUG_LOG(VERBOSE, | 320 | HPI_DEBUG_LOG(VERBOSE, |
322 | "HPICMN find_control() failed for adap %d\n", | 321 | "HPICMN find_control() failed for adap %d\n", |
@@ -326,11 +325,15 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
326 | 325 | ||
327 | phr->error = 0; | 326 | phr->error = 0; |
328 | 327 | ||
328 | /* set the default response size */ | ||
329 | response_size = | ||
330 | sizeof(struct hpi_response_header) + | ||
331 | sizeof(struct hpi_control_res); | ||
332 | |||
329 | /* pC is the default cached control strucure. May be cast to | 333 | /* pC is the default cached control strucure. May be cast to |
330 | something else in the following switch statement. | 334 | something else in the following switch statement. |
331 | */ | 335 | */ |
332 | pC = (struct hpi_control_cache_single *)pI; | 336 | pC = (struct hpi_control_cache_single *)pI; |
333 | p_pad = (struct hpi_control_cache_pad *)pI; | ||
334 | 337 | ||
335 | switch (pI->control_type) { | 338 | switch (pI->control_type) { |
336 | 339 | ||
@@ -529,9 +532,7 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
529 | pI->control_index, pI->control_type, phm->u.c.attribute); | 532 | pI->control_index, pI->control_type, phm->u.c.attribute); |
530 | 533 | ||
531 | if (found) | 534 | if (found) |
532 | phr->size = | 535 | phr->size = (u16)response_size; |
533 | sizeof(struct hpi_response_header) + | ||
534 | sizeof(struct hpi_control_res); | ||
535 | 536 | ||
536 | return found; | 537 | return found; |
537 | } | 538 | } |
@@ -682,7 +683,7 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) | |||
682 | void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr) | 683 | void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr) |
683 | { | 684 | { |
684 | switch (phm->type) { | 685 | switch (phm->type) { |
685 | case HPI_TYPE_MESSAGE: | 686 | case HPI_TYPE_REQUEST: |
686 | switch (phm->object) { | 687 | switch (phm->object) { |
687 | case HPI_OBJ_SUBSYSTEM: | 688 | case HPI_OBJ_SUBSYSTEM: |
688 | subsys_message(phm, phr); | 689 | subsys_message(phm, phr); |
diff --git a/sound/pci/asihpi/hpidspcd.c b/sound/pci/asihpi/hpidspcd.c index 5c6ea113d219..3a7afa31c1d8 100644 --- a/sound/pci/asihpi/hpidspcd.c +++ b/sound/pci/asihpi/hpidspcd.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /***********************************************************************/ | 1 | /***********************************************************************/ |
2 | /*! | 2 | /** |
3 | 3 | ||
4 | AudioScience HPI driver | 4 | AudioScience HPI driver |
5 | Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com> | 5 | Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> |
6 | 6 | ||
7 | This program is free software; you can redistribute it and/or modify | 7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of version 2 of the GNU General Public License as | 8 | it under the terms of version 2 of the GNU General Public License as |
@@ -18,90 +18,59 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | 19 | ||
20 | \file | 20 | \file |
21 | Functions for reading DSP code to load into DSP | 21 | Functions for reading DSP code using |
22 | |||
23 | (Linux only:) If DSPCODE_FIRMWARE_LOADER is defined, code is read using | ||
24 | hotplug firmware loader from individual dsp code files | 22 | hotplug firmware loader from individual dsp code files |
25 | 23 | */ | |
26 | If neither of the above is defined, code is read from linked arrays. | ||
27 | DSPCODE_ARRAY is defined. | ||
28 | |||
29 | HPI_INCLUDE_**** must be defined | ||
30 | and the appropriate hzz?????.c or hex?????.c linked in | ||
31 | |||
32 | */ | ||
33 | /***********************************************************************/ | 24 | /***********************************************************************/ |
34 | #define SOURCEFILE_NAME "hpidspcd.c" | 25 | #define SOURCEFILE_NAME "hpidspcd.c" |
35 | #include "hpidspcd.h" | 26 | #include "hpidspcd.h" |
36 | #include "hpidebug.h" | 27 | #include "hpidebug.h" |
37 | 28 | ||
38 | /** | 29 | struct dsp_code_private { |
39 | Header structure for binary dsp code file (see asidsp.doc) | 30 | /** Firmware descriptor */ |
40 | This structure must match that used in s2bin.c for generation of asidsp.bin | 31 | const struct firmware *firmware; |
41 | */ | 32 | struct pci_dev *dev; |
42 | |||
43 | #ifndef DISABLE_PRAGMA_PACK1 | ||
44 | #pragma pack(push, 1) | ||
45 | #endif | ||
46 | |||
47 | struct code_header { | ||
48 | u32 size; | ||
49 | char type[4]; | ||
50 | u32 adapter; | ||
51 | u32 version; | ||
52 | u32 crc; | ||
53 | }; | 33 | }; |
54 | 34 | ||
55 | #ifndef DISABLE_PRAGMA_PACK1 | ||
56 | #pragma pack(pop) | ||
57 | #endif | ||
58 | |||
59 | #define HPI_VER_DECIMAL ((int)(HPI_VER_MAJOR(HPI_VER) * 10000 + \ | 35 | #define HPI_VER_DECIMAL ((int)(HPI_VER_MAJOR(HPI_VER) * 10000 + \ |
60 | HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER))) | 36 | HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER))) |
61 | 37 | ||
62 | /***********************************************************************/ | ||
63 | #include <linux/pci.h> | ||
64 | /*-------------------------------------------------------------------*/ | 38 | /*-------------------------------------------------------------------*/ |
65 | short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code, | 39 | short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code, |
66 | u32 *pos_error_code) | 40 | u32 *os_error_code) |
67 | { | 41 | { |
68 | const struct firmware *ps_firmware = ps_dsp_code->ps_firmware; | 42 | const struct firmware *firmware; |
43 | struct pci_dev *dev = os_data; | ||
69 | struct code_header header; | 44 | struct code_header header; |
70 | char fw_name[20]; | 45 | char fw_name[20]; |
71 | int err; | 46 | int err; |
72 | 47 | ||
73 | sprintf(fw_name, "asihpi/dsp%04x.bin", adapter); | 48 | sprintf(fw_name, "asihpi/dsp%04x.bin", adapter); |
74 | 49 | ||
75 | err = request_firmware(&ps_firmware, fw_name, | 50 | err = request_firmware(&firmware, fw_name, &dev->dev); |
76 | &ps_dsp_code->ps_dev->dev); | ||
77 | 51 | ||
78 | if (err != 0) { | 52 | if (err || !firmware) { |
79 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, | 53 | dev_printk(KERN_ERR, &dev->dev, |
80 | "%d, request_firmware failed for %s\n", err, | 54 | "%d, request_firmware failed for %s\n", err, |
81 | fw_name); | 55 | fw_name); |
82 | goto error1; | 56 | goto error1; |
83 | } | 57 | } |
84 | if (ps_firmware->size < sizeof(header)) { | 58 | if (firmware->size < sizeof(header)) { |
85 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, | 59 | dev_printk(KERN_ERR, &dev->dev, "Header size too small %s\n", |
86 | "Header size too small %s\n", fw_name); | 60 | fw_name); |
87 | goto error2; | ||
88 | } | ||
89 | memcpy(&header, ps_firmware->data, sizeof(header)); | ||
90 | if (header.adapter != adapter) { | ||
91 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, | ||
92 | "Adapter type incorrect %4x != %4x\n", header.adapter, | ||
93 | adapter); | ||
94 | goto error2; | 61 | goto error2; |
95 | } | 62 | } |
96 | if (header.size != ps_firmware->size) { | 63 | memcpy(&header, firmware->data, sizeof(header)); |
97 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, | 64 | |
98 | "Code size wrong %d != %ld\n", header.size, | 65 | if ((header.type != 0x45444F43) || /* "CODE" */ |
99 | (unsigned long)ps_firmware->size); | 66 | (header.adapter != adapter) |
67 | || (header.size != firmware->size)) { | ||
68 | dev_printk(KERN_ERR, &dev->dev, "Invalid firmware file\n"); | ||
100 | goto error2; | 69 | goto error2; |
101 | } | 70 | } |
102 | 71 | ||
103 | if (header.version / 100 != HPI_VER_DECIMAL / 100) { | 72 | if ((header.version / 100 & ~1) != (HPI_VER_DECIMAL / 100 & ~1)) { |
104 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, | 73 | dev_printk(KERN_ERR, &dev->dev, |
105 | "Incompatible firmware version " | 74 | "Incompatible firmware version " |
106 | "DSP image %d != Driver %d\n", header.version, | 75 | "DSP image %d != Driver %d\n", header.version, |
107 | HPI_VER_DECIMAL); | 76 | HPI_VER_DECIMAL); |
@@ -109,67 +78,70 @@ short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code, | |||
109 | } | 78 | } |
110 | 79 | ||
111 | if (header.version != HPI_VER_DECIMAL) { | 80 | if (header.version != HPI_VER_DECIMAL) { |
112 | dev_printk(KERN_WARNING, &ps_dsp_code->ps_dev->dev, | 81 | dev_printk(KERN_WARNING, &dev->dev, |
113 | "Firmware: release version mismatch DSP image %d != Driver %d\n", | 82 | "Firmware: release version mismatch DSP image %d != Driver %d\n", |
114 | header.version, HPI_VER_DECIMAL); | 83 | header.version, HPI_VER_DECIMAL); |
115 | } | 84 | } |
116 | 85 | ||
117 | HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name); | 86 | HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name); |
118 | ps_dsp_code->ps_firmware = ps_firmware; | 87 | dsp_code->pvt = kmalloc(sizeof(*dsp_code->pvt), GFP_KERNEL); |
119 | ps_dsp_code->block_length = header.size / sizeof(u32); | 88 | if (!dsp_code->pvt) |
120 | ps_dsp_code->word_count = sizeof(header) / sizeof(u32); | 89 | return HPI_ERROR_MEMORY_ALLOC; |
121 | ps_dsp_code->version = header.version; | 90 | |
122 | ps_dsp_code->crc = header.crc; | 91 | dsp_code->pvt->dev = dev; |
92 | dsp_code->pvt->firmware = firmware; | ||
93 | dsp_code->header = header; | ||
94 | dsp_code->block_length = header.size / sizeof(u32); | ||
95 | dsp_code->word_count = sizeof(header) / sizeof(u32); | ||
123 | return 0; | 96 | return 0; |
124 | 97 | ||
125 | error2: | 98 | error2: |
126 | release_firmware(ps_firmware); | 99 | release_firmware(firmware); |
127 | error1: | 100 | error1: |
128 | ps_dsp_code->ps_firmware = NULL; | 101 | dsp_code->block_length = 0; |
129 | ps_dsp_code->block_length = 0; | ||
130 | return HPI_ERROR_DSP_FILE_NOT_FOUND; | 102 | return HPI_ERROR_DSP_FILE_NOT_FOUND; |
131 | } | 103 | } |
132 | 104 | ||
133 | /*-------------------------------------------------------------------*/ | 105 | /*-------------------------------------------------------------------*/ |
134 | void hpi_dsp_code_close(struct dsp_code *ps_dsp_code) | 106 | void hpi_dsp_code_close(struct dsp_code *dsp_code) |
135 | { | 107 | { |
136 | if (ps_dsp_code->ps_firmware != NULL) { | 108 | if (dsp_code->pvt->firmware) { |
137 | HPI_DEBUG_LOG(DEBUG, "dsp code closed\n"); | 109 | HPI_DEBUG_LOG(DEBUG, "dsp code closed\n"); |
138 | release_firmware(ps_dsp_code->ps_firmware); | 110 | release_firmware(dsp_code->pvt->firmware); |
139 | ps_dsp_code->ps_firmware = NULL; | 111 | dsp_code->pvt->firmware = NULL; |
140 | } | 112 | } |
113 | kfree(dsp_code->pvt); | ||
141 | } | 114 | } |
142 | 115 | ||
143 | /*-------------------------------------------------------------------*/ | 116 | /*-------------------------------------------------------------------*/ |
144 | void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code) | 117 | void hpi_dsp_code_rewind(struct dsp_code *dsp_code) |
145 | { | 118 | { |
146 | /* Go back to start of data, after header */ | 119 | /* Go back to start of data, after header */ |
147 | ps_dsp_code->word_count = sizeof(struct code_header) / sizeof(u32); | 120 | dsp_code->word_count = sizeof(struct code_header) / sizeof(u32); |
148 | } | 121 | } |
149 | 122 | ||
150 | /*-------------------------------------------------------------------*/ | 123 | /*-------------------------------------------------------------------*/ |
151 | short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, u32 *pword) | 124 | short hpi_dsp_code_read_word(struct dsp_code *dsp_code, u32 *pword) |
152 | { | 125 | { |
153 | if (ps_dsp_code->word_count + 1 > ps_dsp_code->block_length) | 126 | if (dsp_code->word_count + 1 > dsp_code->block_length) |
154 | return HPI_ERROR_DSP_FILE_FORMAT; | 127 | return HPI_ERROR_DSP_FILE_FORMAT; |
155 | 128 | ||
156 | *pword = ((u32 *)(ps_dsp_code->ps_firmware->data))[ps_dsp_code-> | 129 | *pword = ((u32 *)(dsp_code->pvt->firmware->data))[dsp_code-> |
157 | word_count]; | 130 | word_count]; |
158 | ps_dsp_code->word_count++; | 131 | dsp_code->word_count++; |
159 | return 0; | 132 | return 0; |
160 | } | 133 | } |
161 | 134 | ||
162 | /*-------------------------------------------------------------------*/ | 135 | /*-------------------------------------------------------------------*/ |
163 | short hpi_dsp_code_read_block(size_t words_requested, | 136 | short hpi_dsp_code_read_block(size_t words_requested, |
164 | struct dsp_code *ps_dsp_code, u32 **ppblock) | 137 | struct dsp_code *dsp_code, u32 **ppblock) |
165 | { | 138 | { |
166 | if (ps_dsp_code->word_count + words_requested > | 139 | if (dsp_code->word_count + words_requested > dsp_code->block_length) |
167 | ps_dsp_code->block_length) | ||
168 | return HPI_ERROR_DSP_FILE_FORMAT; | 140 | return HPI_ERROR_DSP_FILE_FORMAT; |
169 | 141 | ||
170 | *ppblock = | 142 | *ppblock = |
171 | ((u32 *)(ps_dsp_code->ps_firmware->data)) + | 143 | ((u32 *)(dsp_code->pvt->firmware->data)) + |
172 | ps_dsp_code->word_count; | 144 | dsp_code->word_count; |
173 | ps_dsp_code->word_count += words_requested; | 145 | dsp_code->word_count += words_requested; |
174 | return 0; | 146 | return 0; |
175 | } | 147 | } |
diff --git a/sound/pci/asihpi/hpidspcd.h b/sound/pci/asihpi/hpidspcd.h index 65f0ca732704..b22881122f19 100644 --- a/sound/pci/asihpi/hpidspcd.h +++ b/sound/pci/asihpi/hpidspcd.h | |||
@@ -2,7 +2,7 @@ | |||
2 | /** | 2 | /** |
3 | 3 | ||
4 | AudioScience HPI driver | 4 | AudioScience HPI driver |
5 | Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com> | 5 | Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> |
6 | 6 | ||
7 | This program is free software; you can redistribute it and/or modify | 7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of version 2 of the GNU General Public License as | 8 | it under the terms of version 2 of the GNU General Public License as |
@@ -20,19 +20,6 @@ | |||
20 | \file | 20 | \file |
21 | Functions for reading DSP code to load into DSP | 21 | Functions for reading DSP code to load into DSP |
22 | 22 | ||
23 | hpi_dspcode_defines HPI DSP code loading method | ||
24 | Define exactly one of these to select how the DSP code is supplied to | ||
25 | the adapter. | ||
26 | |||
27 | End users writing applications that use the HPI interface do not have to | ||
28 | use any of the below defines; they are only necessary for building drivers | ||
29 | |||
30 | HPI_DSPCODE_FILE: | ||
31 | DSP code is supplied as a file that is opened and read from by the driver. | ||
32 | |||
33 | HPI_DSPCODE_FIRMWARE: | ||
34 | DSP code is read using the hotplug firmware loader module. | ||
35 | Only valid when compiling the HPI kernel driver under Linux. | ||
36 | */ | 23 | */ |
37 | /***********************************************************************/ | 24 | /***********************************************************************/ |
38 | #ifndef _HPIDSPCD_H_ | 25 | #ifndef _HPIDSPCD_H_ |
@@ -40,37 +27,56 @@ DSP code is read using the hotplug firmware loader module. | |||
40 | 27 | ||
41 | #include "hpi_internal.h" | 28 | #include "hpi_internal.h" |
42 | 29 | ||
43 | #ifndef DISABLE_PRAGMA_PACK1 | 30 | /** Code header version is decimal encoded e.g. 4.06.10 is 40601 */ |
44 | #pragma pack(push, 1) | 31 | #define HPI_VER_DECIMAL ((int)(HPI_VER_MAJOR(HPI_VER) * 10000 + \ |
45 | #endif | 32 | HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER))) |
33 | |||
34 | /** Header structure for dsp firmware file | ||
35 | This structure must match that used in s2bin.c for generation of asidsp.bin | ||
36 | */ | ||
37 | /*#ifndef DISABLE_PRAGMA_PACK1 */ | ||
38 | /*#pragma pack(push, 1) */ | ||
39 | /*#endif */ | ||
40 | struct code_header { | ||
41 | /** Size in bytes including header */ | ||
42 | u32 size; | ||
43 | /** File type tag "CODE" == 0x45444F43 */ | ||
44 | u32 type; | ||
45 | /** Adapter model number */ | ||
46 | u32 adapter; | ||
47 | /** Firmware version*/ | ||
48 | u32 version; | ||
49 | /** Data checksum */ | ||
50 | u32 checksum; | ||
51 | }; | ||
52 | /*#ifndef DISABLE_PRAGMA_PACK1 */ | ||
53 | /*#pragma pack(pop) */ | ||
54 | /*#endif */ | ||
55 | |||
56 | /*? Don't need the pragmas? */ | ||
57 | compile_time_assert((sizeof(struct code_header) == 20), code_header_size); | ||
46 | 58 | ||
47 | /** Descriptor for dspcode from firmware loader */ | 59 | /** Descriptor for dspcode from firmware loader */ |
48 | struct dsp_code { | 60 | struct dsp_code { |
49 | /** Firmware descriptor */ | 61 | /** copy of file header */ |
50 | const struct firmware *ps_firmware; | 62 | struct code_header header; |
51 | struct pci_dev *ps_dev; | ||
52 | /** Expected number of words in the whole dsp code,INCL header */ | 63 | /** Expected number of words in the whole dsp code,INCL header */ |
53 | long int block_length; | 64 | u32 block_length; |
54 | /** Number of words read so far */ | 65 | /** Number of words read so far */ |
55 | long int word_count; | 66 | u32 word_count; |
56 | /** Version read from dsp code file */ | ||
57 | u32 version; | ||
58 | /** CRC read from dsp code file */ | ||
59 | u32 crc; | ||
60 | }; | ||
61 | 67 | ||
62 | #ifndef DISABLE_PRAGMA_PACK1 | 68 | /** internal state of DSP code reader */ |
63 | #pragma pack(pop) | 69 | struct dsp_code_private *pvt; |
64 | #endif | 70 | }; |
65 | 71 | ||
66 | /** Prepare *psDspCode to refer to the requuested adapter. | 72 | /** Prepare *psDspCode to refer to the requested adapter's firmware. |
67 | Searches the file, or selects the appropriate linked array | 73 | Code file name is obtained from HpiOs_GetDspCodePath |
68 | 74 | ||
69 | \return 0 for success, or error code if requested code is not available | 75 | \return 0 for success, or error code if requested code is not available |
70 | */ | 76 | */ |
71 | short hpi_dsp_code_open( | 77 | short hpi_dsp_code_open( |
72 | /** Code identifier, usually adapter family */ | 78 | /** Code identifier, usually adapter family */ |
73 | u32 adapter, | 79 | u32 adapter, void *pci_dev, |
74 | /** Pointer to DSP code control structure */ | 80 | /** Pointer to DSP code control structure */ |
75 | struct dsp_code *ps_dsp_code, | 81 | struct dsp_code *ps_dsp_code, |
76 | /** Pointer to dword to receive OS specific error code */ | 82 | /** Pointer to dword to receive OS specific error code */ |
diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c index 7397b169b89f..ebb568d695f1 100644 --- a/sound/pci/asihpi/hpifunc.c +++ b/sound/pci/asihpi/hpifunc.c | |||
@@ -1663,68 +1663,64 @@ u16 hpi_channel_mode_get(u32 h_control, u16 *mode) | |||
1663 | u16 hpi_cobranet_hmi_write(u32 h_control, u32 hmi_address, u32 byte_count, | 1663 | u16 hpi_cobranet_hmi_write(u32 h_control, u32 hmi_address, u32 byte_count, |
1664 | u8 *pb_data) | 1664 | u8 *pb_data) |
1665 | { | 1665 | { |
1666 | struct hpi_message hm; | 1666 | struct hpi_msg_cobranet_hmiwrite hm; |
1667 | struct hpi_response hr; | 1667 | struct hpi_response_header hr; |
1668 | 1668 | ||
1669 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX, | 1669 | hpi_init_message_responseV1(&hm.h, sizeof(hm), &hr, sizeof(hr), |
1670 | HPI_CONTROL_SET_STATE); | 1670 | HPI_OBJ_CONTROL, HPI_CONTROL_SET_STATE); |
1671 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) | ||
1672 | return HPI_ERROR_INVALID_HANDLE; | ||
1673 | 1671 | ||
1674 | hm.u.cx.u.cobranet_data.byte_count = byte_count; | 1672 | if (hpi_handle_indexes(h_control, &hm.h.adapter_index, |
1675 | hm.u.cx.u.cobranet_data.hmi_address = hmi_address; | 1673 | &hm.h.obj_index)) |
1674 | return HPI_ERROR_INVALID_HANDLE; | ||
1676 | 1675 | ||
1677 | if (byte_count <= 8) { | 1676 | if (byte_count > sizeof(hm.bytes)) |
1678 | memcpy(hm.u.cx.u.cobranet_data.data, pb_data, byte_count); | 1677 | return HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL; |
1679 | hm.u.cx.attribute = HPI_COBRANET_SET; | ||
1680 | } else { | ||
1681 | hm.u.cx.u.cobranet_bigdata.pb_data = pb_data; | ||
1682 | hm.u.cx.attribute = HPI_COBRANET_SET_DATA; | ||
1683 | } | ||
1684 | 1678 | ||
1685 | hpi_send_recv(&hm, &hr); | 1679 | hm.p.attribute = HPI_COBRANET_SET; |
1680 | hm.p.byte_count = byte_count; | ||
1681 | hm.p.hmi_address = hmi_address; | ||
1682 | memcpy(hm.bytes, pb_data, byte_count); | ||
1683 | hm.h.size = (u16)(sizeof(hm.h) + sizeof(hm.p) + byte_count); | ||
1686 | 1684 | ||
1685 | hpi_send_recvV1(&hm.h, &hr); | ||
1687 | return hr.error; | 1686 | return hr.error; |
1688 | } | 1687 | } |
1689 | 1688 | ||
1690 | u16 hpi_cobranet_hmi_read(u32 h_control, u32 hmi_address, u32 max_byte_count, | 1689 | u16 hpi_cobranet_hmi_read(u32 h_control, u32 hmi_address, u32 max_byte_count, |
1691 | u32 *pbyte_count, u8 *pb_data) | 1690 | u32 *pbyte_count, u8 *pb_data) |
1692 | { | 1691 | { |
1693 | struct hpi_message hm; | 1692 | struct hpi_msg_cobranet_hmiread hm; |
1694 | struct hpi_response hr; | 1693 | struct hpi_res_cobranet_hmiread hr; |
1695 | 1694 | ||
1696 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX, | 1695 | hpi_init_message_responseV1(&hm.h, sizeof(hm), &hr.h, sizeof(hr), |
1697 | HPI_CONTROL_GET_STATE); | 1696 | HPI_OBJ_CONTROL, HPI_CONTROL_GET_STATE); |
1698 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) | 1697 | |
1698 | if (hpi_handle_indexes(h_control, &hm.h.adapter_index, | ||
1699 | &hm.h.obj_index)) | ||
1699 | return HPI_ERROR_INVALID_HANDLE; | 1700 | return HPI_ERROR_INVALID_HANDLE; |
1700 | 1701 | ||
1701 | hm.u.cx.u.cobranet_data.byte_count = max_byte_count; | 1702 | if (max_byte_count > sizeof(hr.bytes)) |
1702 | hm.u.cx.u.cobranet_data.hmi_address = hmi_address; | 1703 | return HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; |
1703 | 1704 | ||
1704 | if (max_byte_count <= 8) { | 1705 | hm.p.attribute = HPI_COBRANET_GET; |
1705 | hm.u.cx.attribute = HPI_COBRANET_GET; | 1706 | hm.p.byte_count = max_byte_count; |
1706 | } else { | 1707 | hm.p.hmi_address = hmi_address; |
1707 | hm.u.cx.u.cobranet_bigdata.pb_data = pb_data; | ||
1708 | hm.u.cx.attribute = HPI_COBRANET_GET_DATA; | ||
1709 | } | ||
1710 | 1708 | ||
1711 | hpi_send_recv(&hm, &hr); | 1709 | hpi_send_recvV1(&hm.h, &hr.h); |
1712 | if (!hr.error && pb_data) { | ||
1713 | 1710 | ||
1714 | *pbyte_count = hr.u.cx.u.cobranet_data.byte_count; | 1711 | if (!hr.h.error && pb_data) { |
1712 | if (hr.byte_count > sizeof(hr.bytes)) | ||
1715 | 1713 | ||
1716 | if (*pbyte_count < max_byte_count) | 1714 | return HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; |
1717 | max_byte_count = *pbyte_count; | ||
1718 | 1715 | ||
1719 | if (hm.u.cx.attribute == HPI_COBRANET_GET) { | 1716 | *pbyte_count = hr.byte_count; |
1720 | memcpy(pb_data, hr.u.cx.u.cobranet_data.data, | ||
1721 | max_byte_count); | ||
1722 | } else { | ||
1723 | 1717 | ||
1724 | } | 1718 | if (hr.byte_count < max_byte_count) |
1719 | max_byte_count = *pbyte_count; | ||
1725 | 1720 | ||
1721 | memcpy(pb_data, hr.bytes, max_byte_count); | ||
1726 | } | 1722 | } |
1727 | return hr.error; | 1723 | return hr.h.error; |
1728 | } | 1724 | } |
1729 | 1725 | ||
1730 | u16 hpi_cobranet_hmi_get_status(u32 h_control, u32 *pstatus, | 1726 | u16 hpi_cobranet_hmi_get_status(u32 h_control, u32 *pstatus, |
@@ -1733,23 +1729,23 @@ u16 hpi_cobranet_hmi_get_status(u32 h_control, u32 *pstatus, | |||
1733 | struct hpi_message hm; | 1729 | struct hpi_message hm; |
1734 | struct hpi_response hr; | 1730 | struct hpi_response hr; |
1735 | 1731 | ||
1736 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX, | 1732 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
1737 | HPI_CONTROL_GET_STATE); | 1733 | HPI_CONTROL_GET_STATE); |
1738 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) | 1734 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1739 | return HPI_ERROR_INVALID_HANDLE; | 1735 | return HPI_ERROR_INVALID_HANDLE; |
1740 | 1736 | ||
1741 | hm.u.cx.attribute = HPI_COBRANET_GET_STATUS; | 1737 | hm.u.c.attribute = HPI_COBRANET_GET_STATUS; |
1742 | 1738 | ||
1743 | hpi_send_recv(&hm, &hr); | 1739 | hpi_send_recv(&hm, &hr); |
1744 | if (!hr.error) { | 1740 | if (!hr.error) { |
1745 | if (pstatus) | 1741 | if (pstatus) |
1746 | *pstatus = hr.u.cx.u.cobranet_status.status; | 1742 | *pstatus = hr.u.cu.cobranet.status.status; |
1747 | if (preadable_size) | 1743 | if (preadable_size) |
1748 | *preadable_size = | 1744 | *preadable_size = |
1749 | hr.u.cx.u.cobranet_status.readable_size; | 1745 | hr.u.cu.cobranet.status.readable_size; |
1750 | if (pwriteable_size) | 1746 | if (pwriteable_size) |
1751 | *pwriteable_size = | 1747 | *pwriteable_size = |
1752 | hr.u.cx.u.cobranet_status.writeable_size; | 1748 | hr.u.cu.cobranet.status.writeable_size; |
1753 | } | 1749 | } |
1754 | return hr.error; | 1750 | return hr.error; |
1755 | } | 1751 | } |
diff --git a/sound/pci/asihpi/hpimsginit.c b/sound/pci/asihpi/hpimsginit.c index 628376ce4a49..52400a6b5f15 100644 --- a/sound/pci/asihpi/hpimsginit.c +++ b/sound/pci/asihpi/hpimsginit.c | |||
@@ -46,7 +46,7 @@ static void hpi_init_message(struct hpi_message *phm, u16 object, | |||
46 | if (gwSSX2_bypass) | 46 | if (gwSSX2_bypass) |
47 | phm->type = HPI_TYPE_SSX2BYPASS_MESSAGE; | 47 | phm->type = HPI_TYPE_SSX2BYPASS_MESSAGE; |
48 | else | 48 | else |
49 | phm->type = HPI_TYPE_MESSAGE; | 49 | phm->type = HPI_TYPE_REQUEST; |
50 | phm->object = object; | 50 | phm->object = object; |
51 | phm->function = function; | 51 | phm->function = function; |
52 | phm->version = 0; | 52 | phm->version = 0; |
@@ -89,7 +89,7 @@ static void hpi_init_messageV1(struct hpi_message_header *phm, u16 size, | |||
89 | memset(phm, 0, sizeof(*phm)); | 89 | memset(phm, 0, sizeof(*phm)); |
90 | if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) { | 90 | if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) { |
91 | phm->size = size; | 91 | phm->size = size; |
92 | phm->type = HPI_TYPE_MESSAGE; | 92 | phm->type = HPI_TYPE_REQUEST; |
93 | phm->object = object; | 93 | phm->object = object; |
94 | phm->function = function; | 94 | phm->function = function; |
95 | phm->version = 1; | 95 | phm->version = 1; |
diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c index 7352a5f7b4f7..2e779421a618 100644 --- a/sound/pci/asihpi/hpimsgx.c +++ b/sound/pci/asihpi/hpimsgx.c | |||
@@ -16,7 +16,7 @@ | |||
16 | along with this program; if not, write to the Free Software | 16 | along with this program; if not, write to the Free Software |
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | 18 | ||
19 | Extended Message Function With Response Cacheing | 19 | Extended Message Function With Response Caching |
20 | 20 | ||
21 | (C) Copyright AudioScience Inc. 2002 | 21 | (C) Copyright AudioScience Inc. 2002 |
22 | *****************************************************************************/ | 22 | *****************************************************************************/ |
@@ -186,7 +186,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr, | |||
186 | /* Initialize this module's internal state */ | 186 | /* Initialize this module's internal state */ |
187 | hpios_msgxlock_init(&msgx_lock); | 187 | hpios_msgxlock_init(&msgx_lock); |
188 | memset(&hpi_entry_points, 0, sizeof(hpi_entry_points)); | 188 | memset(&hpi_entry_points, 0, sizeof(hpi_entry_points)); |
189 | hpios_locked_mem_init(); | ||
190 | /* Init subsys_findadapters response to no-adapters */ | 189 | /* Init subsys_findadapters response to no-adapters */ |
191 | HPIMSGX__reset(HPIMSGX_ALLADAPTERS); | 190 | HPIMSGX__reset(HPIMSGX_ALLADAPTERS); |
192 | hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, | 191 | hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, |
@@ -197,7 +196,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr, | |||
197 | case HPI_SUBSYS_DRIVER_UNLOAD: | 196 | case HPI_SUBSYS_DRIVER_UNLOAD: |
198 | HPI_COMMON(phm, phr); | 197 | HPI_COMMON(phm, phr); |
199 | HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner); | 198 | HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner); |
200 | hpios_locked_mem_free_all(); | ||
201 | hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, | 199 | hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, |
202 | HPI_SUBSYS_DRIVER_UNLOAD, 0); | 200 | HPI_SUBSYS_DRIVER_UNLOAD, 0); |
203 | return; | 201 | return; |
@@ -315,7 +313,7 @@ void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr, | |||
315 | { | 313 | { |
316 | HPI_DEBUG_MESSAGE(DEBUG, phm); | 314 | HPI_DEBUG_MESSAGE(DEBUG, phm); |
317 | 315 | ||
318 | if (phm->type != HPI_TYPE_MESSAGE) { | 316 | if (phm->type != HPI_TYPE_REQUEST) { |
319 | hpi_init_response(phr, phm->object, phm->function, | 317 | hpi_init_response(phr, phm->object, phm->function, |
320 | HPI_ERROR_INVALID_TYPE); | 318 | HPI_ERROR_INVALID_TYPE); |
321 | return; | 319 | return; |
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c index d8e7047512f8..65fcf4770731 100644 --- a/sound/pci/asihpi/hpioctl.c +++ b/sound/pci/asihpi/hpioctl.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************************* | 1 | /******************************************************************************* |
2 | 2 | ||
3 | AudioScience HPI driver | 3 | AudioScience HPI driver |
4 | Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com> | 4 | Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> |
5 | 5 | ||
6 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of version 2 of the GNU General Public License as | 7 | it under the terms of version 2 of the GNU General Public License as |
@@ -157,11 +157,6 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
157 | goto out; | 157 | goto out; |
158 | } | 158 | } |
159 | 159 | ||
160 | if (hm->h.adapter_index >= HPI_MAX_ADAPTERS) { | ||
161 | err = -EINVAL; | ||
162 | goto out; | ||
163 | } | ||
164 | |||
165 | switch (hm->h.function) { | 160 | switch (hm->h.function) { |
166 | case HPI_SUBSYS_CREATE_ADAPTER: | 161 | case HPI_SUBSYS_CREATE_ADAPTER: |
167 | case HPI_ADAPTER_DELETE: | 162 | case HPI_ADAPTER_DELETE: |
@@ -187,7 +182,6 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
187 | /* -1=no data 0=read from user mem, 1=write to user mem */ | 182 | /* -1=no data 0=read from user mem, 1=write to user mem */ |
188 | int wrflag = -1; | 183 | int wrflag = -1; |
189 | u32 adapter = hm->h.adapter_index; | 184 | u32 adapter = hm->h.adapter_index; |
190 | pa = &adapters[adapter]; | ||
191 | 185 | ||
192 | if ((adapter > HPI_MAX_ADAPTERS) || (!pa->type)) { | 186 | if ((adapter > HPI_MAX_ADAPTERS) || (!pa->type)) { |
193 | hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER, | 187 | hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER, |
@@ -203,6 +197,8 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
203 | goto out; | 197 | goto out; |
204 | } | 198 | } |
205 | 199 | ||
200 | pa = &adapters[adapter]; | ||
201 | |||
206 | if (mutex_lock_interruptible(&adapters[adapter].mutex)) { | 202 | if (mutex_lock_interruptible(&adapters[adapter].mutex)) { |
207 | err = -EINTR; | 203 | err = -EINTR; |
208 | goto out; | 204 | goto out; |
diff --git a/sound/pci/asihpi/hpios.c b/sound/pci/asihpi/hpios.c index 742ee12a9e17..ff2a19b544fa 100644 --- a/sound/pci/asihpi/hpios.c +++ b/sound/pci/asihpi/hpios.c | |||
@@ -39,10 +39,6 @@ void hpios_delay_micro_seconds(u32 num_micro_sec) | |||
39 | 39 | ||
40 | } | 40 | } |
41 | 41 | ||
42 | void hpios_locked_mem_init(void) | ||
43 | { | ||
44 | } | ||
45 | |||
46 | /** Allocated an area of locked memory for bus master DMA operations. | 42 | /** Allocated an area of locked memory for bus master DMA operations. |
47 | 43 | ||
48 | On error, return -ENOMEM, and *pMemArea.size = 0 | 44 | On error, return -ENOMEM, and *pMemArea.size = 0 |
@@ -85,7 +81,3 @@ u16 hpios_locked_mem_free(struct consistent_dma_area *p_mem_area) | |||
85 | return 1; | 81 | return 1; |
86 | } | 82 | } |
87 | } | 83 | } |
88 | |||
89 | void hpios_locked_mem_free_all(void) | ||
90 | { | ||
91 | } | ||
diff --git a/sound/pci/asihpi/hpios.h b/sound/pci/asihpi/hpios.h index 03273e729f99..2f605e34bad0 100644 --- a/sound/pci/asihpi/hpios.h +++ b/sound/pci/asihpi/hpios.h | |||
@@ -38,6 +38,7 @@ HPI Operating System Specific macros for Linux Kernel driver | |||
38 | #include <linux/firmware.h> | 38 | #include <linux/firmware.h> |
39 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
40 | #include <linux/pci.h> | 40 | #include <linux/pci.h> |
41 | #include <linux/mutex.h> | ||
41 | 42 | ||
42 | #define HPI_NO_OS_FILE_OPS | 43 | #define HPI_NO_OS_FILE_OPS |
43 | 44 | ||
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 3119cd97a217..537e0a2cc68a 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -1624,7 +1624,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card, | |||
1624 | } | 1624 | } |
1625 | 1625 | ||
1626 | if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED, | 1626 | if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED, |
1627 | card->shortname, chip)) { | 1627 | KBUILD_MODNAME, chip)) { |
1628 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1628 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1629 | snd_atiixp_free(chip); | 1629 | snd_atiixp_free(chip); |
1630 | return -EBUSY; | 1630 | return -EBUSY; |
@@ -1701,7 +1701,7 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci) | |||
1701 | } | 1701 | } |
1702 | 1702 | ||
1703 | static struct pci_driver driver = { | 1703 | static struct pci_driver driver = { |
1704 | .name = "ATI IXP AC97 controller", | 1704 | .name = KBUILD_MODNAME, |
1705 | .id_table = snd_atiixp_ids, | 1705 | .id_table = snd_atiixp_ids, |
1706 | .probe = snd_atiixp_probe, | 1706 | .probe = snd_atiixp_probe, |
1707 | .remove = __devexit_p(snd_atiixp_remove), | 1707 | .remove = __devexit_p(snd_atiixp_remove), |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 2f74c2fdf1ea..45df275c8248 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -1260,7 +1260,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card, | |||
1260 | } | 1260 | } |
1261 | 1261 | ||
1262 | if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED, | 1262 | if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED, |
1263 | card->shortname, chip)) { | 1263 | KBUILD_MODNAME, chip)) { |
1264 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1264 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1265 | snd_atiixp_free(chip); | 1265 | snd_atiixp_free(chip); |
1266 | return -EBUSY; | 1266 | return -EBUSY; |
@@ -1332,7 +1332,7 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci) | |||
1332 | } | 1332 | } |
1333 | 1333 | ||
1334 | static struct pci_driver driver = { | 1334 | static struct pci_driver driver = { |
1335 | .name = "ATI IXP MC97 controller", | 1335 | .name = KBUILD_MODNAME, |
1336 | .id_table = snd_atiixp_ids, | 1336 | .id_table = snd_atiixp_ids, |
1337 | .probe = snd_atiixp_probe, | 1337 | .probe = snd_atiixp_probe, |
1338 | .remove = __devexit_p(snd_atiixp_remove), | 1338 | .remove = __devexit_p(snd_atiixp_remove), |
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 7b72c88e449d..a38469986885 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c | |||
@@ -196,7 +196,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) | |||
196 | } | 196 | } |
197 | 197 | ||
198 | if ((err = request_irq(pci->irq, vortex_interrupt, | 198 | if ((err = request_irq(pci->irq, vortex_interrupt, |
199 | IRQF_SHARED, CARD_NAME_SHORT, | 199 | IRQF_SHARED, KBUILD_MODNAME, |
200 | chip)) != 0) { | 200 | chip)) != 0) { |
201 | printk(KERN_ERR "cannot grab irq\n"); | 201 | printk(KERN_ERR "cannot grab irq\n"); |
202 | goto irq_out; | 202 | goto irq_out; |
@@ -375,7 +375,7 @@ static void __devexit snd_vortex_remove(struct pci_dev *pci) | |||
375 | 375 | ||
376 | // pci_driver definition | 376 | // pci_driver definition |
377 | static struct pci_driver driver = { | 377 | static struct pci_driver driver = { |
378 | .name = CARD_NAME_SHORT, | 378 | .name = KBUILD_MODNAME, |
379 | .id_table = snd_vortex_ids, | 379 | .id_table = snd_vortex_ids, |
380 | .probe = snd_vortex_probe, | 380 | .probe = snd_vortex_probe, |
381 | .remove = __devexit_p(snd_vortex_remove), | 381 | .remove = __devexit_p(snd_vortex_remove), |
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index c15002242d98..f8569b11331b 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c | |||
@@ -171,7 +171,7 @@ MODULE_DEVICE_TABLE(pci, snd_aw2_ids); | |||
171 | 171 | ||
172 | /* pci_driver definition */ | 172 | /* pci_driver definition */ |
173 | static struct pci_driver driver = { | 173 | static struct pci_driver driver = { |
174 | .name = "Emagic Audiowerk 2", | 174 | .name = KBUILD_MODNAME, |
175 | .id_table = snd_aw2_ids, | 175 | .id_table = snd_aw2_ids, |
176 | .probe = snd_aw2_probe, | 176 | .probe = snd_aw2_probe, |
177 | .remove = __devexit_p(snd_aw2_remove), | 177 | .remove = __devexit_p(snd_aw2_remove), |
@@ -317,7 +317,7 @@ static int __devinit snd_aw2_create(struct snd_card *card, | |||
317 | snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt); | 317 | snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt); |
318 | 318 | ||
319 | if (request_irq(pci->irq, snd_aw2_saa7146_interrupt, | 319 | if (request_irq(pci->irq, snd_aw2_saa7146_interrupt, |
320 | IRQF_SHARED, "Audiowerk2", chip)) { | 320 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
321 | printk(KERN_ERR "aw2: Cannot grab irq %d\n", pci->irq); | 321 | printk(KERN_ERR "aw2: Cannot grab irq %d\n", pci->irq); |
322 | 322 | ||
323 | iounmap(chip->iobase_virt); | 323 | iounmap(chip->iobase_virt); |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 9b7a6346037a..e4d76a270c9f 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -2559,7 +2559,7 @@ snd_azf3328_create(struct snd_card *card, | |||
2559 | codec_setup->name = "I2S_OUT"; | 2559 | codec_setup->name = "I2S_OUT"; |
2560 | 2560 | ||
2561 | if (request_irq(pci->irq, snd_azf3328_interrupt, | 2561 | if (request_irq(pci->irq, snd_azf3328_interrupt, |
2562 | IRQF_SHARED, card->shortname, chip)) { | 2562 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
2563 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 2563 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
2564 | err = -EBUSY; | 2564 | err = -EBUSY; |
2565 | goto out_err; | 2565 | goto out_err; |
@@ -2860,7 +2860,7 @@ snd_azf3328_resume(struct pci_dev *pci) | |||
2860 | 2860 | ||
2861 | 2861 | ||
2862 | static struct pci_driver driver = { | 2862 | static struct pci_driver driver = { |
2863 | .name = "AZF3328", | 2863 | .name = KBUILD_MODNAME, |
2864 | .id_table = snd_azf3328_ids, | 2864 | .id_table = snd_azf3328_ids, |
2865 | .probe = snd_azf3328_probe, | 2865 | .probe = snd_azf3328_probe, |
2866 | .remove = __devexit_p(snd_azf3328_remove), | 2866 | .remove = __devexit_p(snd_azf3328_remove), |
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 2958a05b5293..39180335c237 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -760,7 +760,7 @@ static int __devinit snd_bt87x_create(struct snd_card *card, | |||
760 | snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); | 760 | snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); |
761 | 761 | ||
762 | err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, | 762 | err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, |
763 | "Bt87x audio", chip); | 763 | KBUILD_MODNAME, chip); |
764 | if (err < 0) { | 764 | if (err < 0) { |
765 | snd_printk(KERN_ERR "cannot grab irq %d\n", pci->irq); | 765 | snd_printk(KERN_ERR "cannot grab irq %d\n", pci->irq); |
766 | goto fail; | 766 | goto fail; |
@@ -965,7 +965,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_bt87x_default_ids) = { | |||
965 | }; | 965 | }; |
966 | 966 | ||
967 | static struct pci_driver driver = { | 967 | static struct pci_driver driver = { |
968 | .name = "Bt87x", | 968 | .name = KBUILD_MODNAME, |
969 | .id_table = snd_bt87x_ids, | 969 | .id_table = snd_bt87x_ids, |
970 | .probe = snd_bt87x_probe, | 970 | .probe = snd_bt87x_probe, |
971 | .remove = __devexit_p(snd_bt87x_remove), | 971 | .remove = __devexit_p(snd_bt87x_remove), |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 437759239694..061b7e654586 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -1666,7 +1666,7 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card, | |||
1666 | } | 1666 | } |
1667 | 1667 | ||
1668 | if (request_irq(pci->irq, snd_ca0106_interrupt, | 1668 | if (request_irq(pci->irq, snd_ca0106_interrupt, |
1669 | IRQF_SHARED, "snd_ca0106", chip)) { | 1669 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
1670 | snd_ca0106_free(chip); | 1670 | snd_ca0106_free(chip); |
1671 | printk(KERN_ERR "cannot grab irq\n"); | 1671 | printk(KERN_ERR "cannot grab irq\n"); |
1672 | return -EBUSY; | 1672 | return -EBUSY; |
@@ -1933,7 +1933,7 @@ MODULE_DEVICE_TABLE(pci, snd_ca0106_ids); | |||
1933 | 1933 | ||
1934 | // pci_driver definition | 1934 | // pci_driver definition |
1935 | static struct pci_driver driver = { | 1935 | static struct pci_driver driver = { |
1936 | .name = "CA0106", | 1936 | .name = KBUILD_MODNAME, |
1937 | .id_table = snd_ca0106_ids, | 1937 | .id_table = snd_ca0106_ids, |
1938 | .probe = snd_ca0106_probe, | 1938 | .probe = snd_ca0106_probe, |
1939 | .remove = __devexit_p(snd_ca0106_remove), | 1939 | .remove = __devexit_p(snd_ca0106_remove), |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index f4e573555da3..9cf99fb7eb9c 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -3053,7 +3053,7 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
3053 | cm->iobase = pci_resource_start(pci, 0); | 3053 | cm->iobase = pci_resource_start(pci, 0); |
3054 | 3054 | ||
3055 | if (request_irq(pci->irq, snd_cmipci_interrupt, | 3055 | if (request_irq(pci->irq, snd_cmipci_interrupt, |
3056 | IRQF_SHARED, card->driver, cm)) { | 3056 | IRQF_SHARED, KBUILD_MODNAME, cm)) { |
3057 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 3057 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
3058 | snd_cmipci_free(cm); | 3058 | snd_cmipci_free(cm); |
3059 | return -EBUSY; | 3059 | return -EBUSY; |
@@ -3398,7 +3398,7 @@ static int snd_cmipci_resume(struct pci_dev *pci) | |||
3398 | #endif /* CONFIG_PM */ | 3398 | #endif /* CONFIG_PM */ |
3399 | 3399 | ||
3400 | static struct pci_driver driver = { | 3400 | static struct pci_driver driver = { |
3401 | .name = "C-Media PCI", | 3401 | .name = KBUILD_MODNAME, |
3402 | .id_table = snd_cmipci_ids, | 3402 | .id_table = snd_cmipci_ids, |
3403 | .probe = snd_cmipci_probe, | 3403 | .probe = snd_cmipci_probe, |
3404 | .remove = __devexit_p(snd_cmipci_remove), | 3404 | .remove = __devexit_p(snd_cmipci_remove), |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 6772070ed492..07f04e390aa1 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -1382,7 +1382,7 @@ static int __devinit snd_cs4281_create(struct snd_card *card, | |||
1382 | } | 1382 | } |
1383 | 1383 | ||
1384 | if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_SHARED, | 1384 | if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_SHARED, |
1385 | "CS4281", chip)) { | 1385 | KBUILD_MODNAME, chip)) { |
1386 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1386 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1387 | snd_cs4281_free(chip); | 1387 | snd_cs4281_free(chip); |
1388 | return -ENOMEM; | 1388 | return -ENOMEM; |
@@ -2085,7 +2085,7 @@ static int cs4281_resume(struct pci_dev *pci) | |||
2085 | #endif /* CONFIG_PM */ | 2085 | #endif /* CONFIG_PM */ |
2086 | 2086 | ||
2087 | static struct pci_driver driver = { | 2087 | static struct pci_driver driver = { |
2088 | .name = "CS4281", | 2088 | .name = KBUILD_MODNAME, |
2089 | .id_table = snd_cs4281_ids, | 2089 | .id_table = snd_cs4281_ids, |
2090 | .probe = snd_cs4281_probe, | 2090 | .probe = snd_cs4281_probe, |
2091 | .remove = __devexit_p(snd_cs4281_remove), | 2091 | .remove = __devexit_p(snd_cs4281_remove), |
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 767fa7f06cd0..1af95559aaaa 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c | |||
@@ -162,7 +162,7 @@ static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci) | |||
162 | } | 162 | } |
163 | 163 | ||
164 | static struct pci_driver driver = { | 164 | static struct pci_driver driver = { |
165 | .name = "Sound Fusion CS46xx", | 165 | .name = KBUILD_MODNAME, |
166 | .id_table = snd_cs46xx_ids, | 166 | .id_table = snd_cs46xx_ids, |
167 | .probe = snd_card_cs46xx_probe, | 167 | .probe = snd_card_cs46xx_probe, |
168 | .remove = __devexit_p(snd_card_cs46xx_remove), | 168 | .remove = __devexit_p(snd_card_cs46xx_remove), |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index aad37082cb6e..9546bf07f0d1 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -3835,7 +3835,7 @@ int __devinit snd_cs46xx_create(struct snd_card *card, | |||
3835 | } | 3835 | } |
3836 | 3836 | ||
3837 | if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED, | 3837 | if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED, |
3838 | "CS46XX", chip)) { | 3838 | KBUILD_MODNAME, chip)) { |
3839 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 3839 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
3840 | snd_cs46xx_free(chip); | 3840 | snd_cs46xx_free(chip); |
3841 | return -EBUSY; | 3841 | return -EBUSY; |
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c index bc07e275d4d4..a4669346d146 100644 --- a/sound/pci/cs5530.c +++ b/sound/pci/cs5530.c | |||
@@ -285,7 +285,7 @@ static int __devinit snd_cs5530_probe(struct pci_dev *pci, | |||
285 | } | 285 | } |
286 | 286 | ||
287 | static struct pci_driver driver = { | 287 | static struct pci_driver driver = { |
288 | .name = "CS5530_Audio", | 288 | .name = KBUILD_MODNAME, |
289 | .id_table = snd_cs5530_ids, | 289 | .id_table = snd_cs5530_ids, |
290 | .probe = snd_cs5530_probe, | 290 | .probe = snd_cs5530_probe, |
291 | .remove = __devexit_p(snd_cs5530_remove), | 291 | .remove = __devexit_p(snd_cs5530_remove), |
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index afb803708416..10d22ed5fece 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c | |||
@@ -311,7 +311,7 @@ static int __devinit snd_cs5535audio_create(struct snd_card *card, | |||
311 | cs5535au->port = pci_resource_start(pci, 0); | 311 | cs5535au->port = pci_resource_start(pci, 0); |
312 | 312 | ||
313 | if (request_irq(pci->irq, snd_cs5535audio_interrupt, | 313 | if (request_irq(pci->irq, snd_cs5535audio_interrupt, |
314 | IRQF_SHARED, "CS5535 Audio", cs5535au)) { | 314 | IRQF_SHARED, KBUILD_MODNAME, cs5535au)) { |
315 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 315 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
316 | err = -EBUSY; | 316 | err = -EBUSY; |
317 | goto sndfail; | 317 | goto sndfail; |
@@ -395,7 +395,7 @@ static void __devexit snd_cs5535audio_remove(struct pci_dev *pci) | |||
395 | } | 395 | } |
396 | 396 | ||
397 | static struct pci_driver driver = { | 397 | static struct pci_driver driver = { |
398 | .name = DRIVER_NAME, | 398 | .name = KBUILD_MODNAME, |
399 | .id_table = snd_cs5535audio_ids, | 399 | .id_table = snd_cs5535audio_ids, |
400 | .probe = snd_cs5535audio_probe, | 400 | .probe = snd_cs5535audio_probe, |
401 | .remove = __devexit_p(snd_cs5535audio_remove), | 401 | .remove = __devexit_p(snd_cs5535audio_remove), |
diff --git a/sound/pci/ctxfi/ct20k2reg.h b/sound/pci/ctxfi/ct20k2reg.h index e0394e3996e8..ca501ba03d64 100644 --- a/sound/pci/ctxfi/ct20k2reg.h +++ b/sound/pci/ctxfi/ct20k2reg.h | |||
@@ -55,6 +55,7 @@ | |||
55 | /* GPIO Registers */ | 55 | /* GPIO Registers */ |
56 | #define GPIO_DATA 0x1B7020 | 56 | #define GPIO_DATA 0x1B7020 |
57 | #define GPIO_CTRL 0x1B7024 | 57 | #define GPIO_CTRL 0x1B7024 |
58 | #define GPIO_EXT_DATA 0x1B70A0 | ||
58 | 59 | ||
59 | /* Virtual memory registers */ | 60 | /* Virtual memory registers */ |
60 | #define VMEM_PTPAL 0x1C6300 /* 0x1C6300 + (16 * Chn) */ | 61 | #define VMEM_PTPAL 0x1C6300 /* 0x1C6300 + (16 * Chn) */ |
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 13f33c0719d3..d8a4423539ce 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include "ctatc.h" | 18 | #include "ctatc.h" |
19 | #include "ctpcm.h" | 19 | #include "ctpcm.h" |
20 | #include "ctmixer.h" | 20 | #include "ctmixer.h" |
21 | #include "cthardware.h" | ||
22 | #include "ctsrc.h" | 21 | #include "ctsrc.h" |
23 | #include "ctamixer.h" | 22 | #include "ctamixer.h" |
24 | #include "ctdaio.h" | 23 | #include "ctdaio.h" |
@@ -30,7 +29,6 @@ | |||
30 | #include <sound/asoundef.h> | 29 | #include <sound/asoundef.h> |
31 | 30 | ||
32 | #define MONO_SUM_SCALE 0x19a8 /* 2^(-0.5) in 14-bit floating format */ | 31 | #define MONO_SUM_SCALE 0x19a8 /* 2^(-0.5) in 14-bit floating format */ |
33 | #define DAIONUM 7 | ||
34 | #define MAX_MULTI_CHN 8 | 32 | #define MAX_MULTI_CHN 8 |
35 | 33 | ||
36 | #define IEC958_DEFAULT_CON ((IEC958_AES0_NONAUDIO \ | 34 | #define IEC958_DEFAULT_CON ((IEC958_AES0_NONAUDIO \ |
@@ -53,6 +51,8 @@ static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = { | |||
53 | static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = { | 51 | static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = { |
54 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760, | 52 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760, |
55 | "SB0760", CTSB0760), | 53 | "SB0760", CTSB0760), |
54 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB1270, | ||
55 | "SB1270", CTSB1270), | ||
56 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08801, | 56 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08801, |
57 | "SB0880", CTSB0880), | 57 | "SB0880", CTSB0880), |
58 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08802, | 58 | SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08802, |
@@ -75,6 +75,7 @@ static const char *ct_subsys_name[NUM_CTCARDS] = { | |||
75 | [CTSB0760] = "SB076x", | 75 | [CTSB0760] = "SB076x", |
76 | [CTHENDRIX] = "Hendrix", | 76 | [CTHENDRIX] = "Hendrix", |
77 | [CTSB0880] = "SB0880", | 77 | [CTSB0880] = "SB0880", |
78 | [CTSB1270] = "SB1270", | ||
78 | [CT20K2_UNKNOWN] = "Unknown", | 79 | [CT20K2_UNKNOWN] = "Unknown", |
79 | }; | 80 | }; |
80 | 81 | ||
@@ -459,12 +460,12 @@ static void setup_src_node_conf(struct ct_atc *atc, struct ct_atc_pcm *apcm, | |||
459 | apcm->substream->runtime->rate); | 460 | apcm->substream->runtime->rate); |
460 | *n_srcc = 0; | 461 | *n_srcc = 0; |
461 | 462 | ||
462 | if (1 == atc->msr) { | 463 | if (1 == atc->msr) { /* FIXME: do we really need SRC here if pitch==1 */ |
463 | *n_srcc = apcm->substream->runtime->channels; | 464 | *n_srcc = apcm->substream->runtime->channels; |
464 | conf[0].pitch = pitch; | 465 | conf[0].pitch = pitch; |
465 | conf[0].mix_msr = conf[0].imp_msr = conf[0].msr = 1; | 466 | conf[0].mix_msr = conf[0].imp_msr = conf[0].msr = 1; |
466 | conf[0].vo = 1; | 467 | conf[0].vo = 1; |
467 | } else if (2 == atc->msr) { | 468 | } else if (2 <= atc->msr) { |
468 | if (0x8000000 < pitch) { | 469 | if (0x8000000 < pitch) { |
469 | /* Need two-stage SRCs, SRCIMPs and | 470 | /* Need two-stage SRCs, SRCIMPs and |
470 | * AMIXERs for converting format */ | 471 | * AMIXERs for converting format */ |
@@ -970,11 +971,39 @@ static int atc_select_mic_in(struct ct_atc *atc) | |||
970 | return 0; | 971 | return 0; |
971 | } | 972 | } |
972 | 973 | ||
973 | static int atc_have_digit_io_switch(struct ct_atc *atc) | 974 | static struct capabilities atc_capabilities(struct ct_atc *atc) |
974 | { | 975 | { |
975 | struct hw *hw = atc->hw; | 976 | struct hw *hw = atc->hw; |
976 | 977 | ||
977 | return hw->have_digit_io_switch(hw); | 978 | return hw->capabilities(hw); |
979 | } | ||
980 | |||
981 | static int atc_output_switch_get(struct ct_atc *atc) | ||
982 | { | ||
983 | struct hw *hw = atc->hw; | ||
984 | |||
985 | return hw->output_switch_get(hw); | ||
986 | } | ||
987 | |||
988 | static int atc_output_switch_put(struct ct_atc *atc, int position) | ||
989 | { | ||
990 | struct hw *hw = atc->hw; | ||
991 | |||
992 | return hw->output_switch_put(hw, position); | ||
993 | } | ||
994 | |||
995 | static int atc_mic_source_switch_get(struct ct_atc *atc) | ||
996 | { | ||
997 | struct hw *hw = atc->hw; | ||
998 | |||
999 | return hw->mic_source_switch_get(hw); | ||
1000 | } | ||
1001 | |||
1002 | static int atc_mic_source_switch_put(struct ct_atc *atc, int position) | ||
1003 | { | ||
1004 | struct hw *hw = atc->hw; | ||
1005 | |||
1006 | return hw->mic_source_switch_put(hw, position); | ||
978 | } | 1007 | } |
979 | 1008 | ||
980 | static int atc_select_digit_io(struct ct_atc *atc) | 1009 | static int atc_select_digit_io(struct ct_atc *atc) |
@@ -1045,6 +1074,11 @@ static int atc_line_in_unmute(struct ct_atc *atc, unsigned char state) | |||
1045 | return atc_daio_unmute(atc, state, LINEIM); | 1074 | return atc_daio_unmute(atc, state, LINEIM); |
1046 | } | 1075 | } |
1047 | 1076 | ||
1077 | static int atc_mic_unmute(struct ct_atc *atc, unsigned char state) | ||
1078 | { | ||
1079 | return atc_daio_unmute(atc, state, MIC); | ||
1080 | } | ||
1081 | |||
1048 | static int atc_spdif_out_unmute(struct ct_atc *atc, unsigned char state) | 1082 | static int atc_spdif_out_unmute(struct ct_atc *atc, unsigned char state) |
1049 | { | 1083 | { |
1050 | return atc_daio_unmute(atc, state, SPDIFOO); | 1084 | return atc_daio_unmute(atc, state, SPDIFOO); |
@@ -1331,17 +1365,20 @@ static int atc_get_resources(struct ct_atc *atc) | |||
1331 | struct srcimp_mgr *srcimp_mgr; | 1365 | struct srcimp_mgr *srcimp_mgr; |
1332 | struct sum_desc sum_dsc = {0}; | 1366 | struct sum_desc sum_dsc = {0}; |
1333 | struct sum_mgr *sum_mgr; | 1367 | struct sum_mgr *sum_mgr; |
1334 | int err, i; | 1368 | int err, i, num_srcs, num_daios; |
1335 | 1369 | ||
1336 | atc->daios = kzalloc(sizeof(void *)*(DAIONUM), GFP_KERNEL); | 1370 | num_daios = ((atc->model == CTSB1270) ? 8 : 7); |
1371 | num_srcs = ((atc->model == CTSB1270) ? 6 : 4); | ||
1372 | |||
1373 | atc->daios = kzalloc(sizeof(void *)*num_daios, GFP_KERNEL); | ||
1337 | if (!atc->daios) | 1374 | if (!atc->daios) |
1338 | return -ENOMEM; | 1375 | return -ENOMEM; |
1339 | 1376 | ||
1340 | atc->srcs = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL); | 1377 | atc->srcs = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL); |
1341 | if (!atc->srcs) | 1378 | if (!atc->srcs) |
1342 | return -ENOMEM; | 1379 | return -ENOMEM; |
1343 | 1380 | ||
1344 | atc->srcimps = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL); | 1381 | atc->srcimps = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL); |
1345 | if (!atc->srcimps) | 1382 | if (!atc->srcimps) |
1346 | return -ENOMEM; | 1383 | return -ENOMEM; |
1347 | 1384 | ||
@@ -1351,8 +1388,9 @@ static int atc_get_resources(struct ct_atc *atc) | |||
1351 | 1388 | ||
1352 | daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO]; | 1389 | daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO]; |
1353 | da_desc.msr = atc->msr; | 1390 | da_desc.msr = atc->msr; |
1354 | for (i = 0, atc->n_daio = 0; i < DAIONUM-1; i++) { | 1391 | for (i = 0, atc->n_daio = 0; i < num_daios; i++) { |
1355 | da_desc.type = i; | 1392 | da_desc.type = (atc->model != CTSB073X) ? i : |
1393 | ((i == SPDIFIO) ? SPDIFI1 : i); | ||
1356 | err = daio_mgr->get_daio(daio_mgr, &da_desc, | 1394 | err = daio_mgr->get_daio(daio_mgr, &da_desc, |
1357 | (struct daio **)&atc->daios[i]); | 1395 | (struct daio **)&atc->daios[i]); |
1358 | if (err) { | 1396 | if (err) { |
@@ -1362,23 +1400,12 @@ static int atc_get_resources(struct ct_atc *atc) | |||
1362 | } | 1400 | } |
1363 | atc->n_daio++; | 1401 | atc->n_daio++; |
1364 | } | 1402 | } |
1365 | if (atc->model == CTSB073X) | ||
1366 | da_desc.type = SPDIFI1; | ||
1367 | else | ||
1368 | da_desc.type = SPDIFIO; | ||
1369 | err = daio_mgr->get_daio(daio_mgr, &da_desc, | ||
1370 | (struct daio **)&atc->daios[i]); | ||
1371 | if (err) { | ||
1372 | printk(KERN_ERR "ctxfi: Failed to get S/PDIF-in resource!!!\n"); | ||
1373 | return err; | ||
1374 | } | ||
1375 | atc->n_daio++; | ||
1376 | 1403 | ||
1377 | src_mgr = atc->rsc_mgrs[SRC]; | 1404 | src_mgr = atc->rsc_mgrs[SRC]; |
1378 | src_dsc.multi = 1; | 1405 | src_dsc.multi = 1; |
1379 | src_dsc.msr = atc->msr; | 1406 | src_dsc.msr = atc->msr; |
1380 | src_dsc.mode = ARCRW; | 1407 | src_dsc.mode = ARCRW; |
1381 | for (i = 0, atc->n_src = 0; i < (2*2); i++) { | 1408 | for (i = 0, atc->n_src = 0; i < num_srcs; i++) { |
1382 | err = src_mgr->get_src(src_mgr, &src_dsc, | 1409 | err = src_mgr->get_src(src_mgr, &src_dsc, |
1383 | (struct src **)&atc->srcs[i]); | 1410 | (struct src **)&atc->srcs[i]); |
1384 | if (err) | 1411 | if (err) |
@@ -1388,8 +1415,8 @@ static int atc_get_resources(struct ct_atc *atc) | |||
1388 | } | 1415 | } |
1389 | 1416 | ||
1390 | srcimp_mgr = atc->rsc_mgrs[SRCIMP]; | 1417 | srcimp_mgr = atc->rsc_mgrs[SRCIMP]; |
1391 | srcimp_dsc.msr = 8; /* SRCIMPs for S/PDIFIn SRT */ | 1418 | srcimp_dsc.msr = 8; |
1392 | for (i = 0, atc->n_srcimp = 0; i < (2*1); i++) { | 1419 | for (i = 0, atc->n_srcimp = 0; i < num_srcs; i++) { |
1393 | err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, | 1420 | err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, |
1394 | (struct srcimp **)&atc->srcimps[i]); | 1421 | (struct srcimp **)&atc->srcimps[i]); |
1395 | if (err) | 1422 | if (err) |
@@ -1397,15 +1424,6 @@ static int atc_get_resources(struct ct_atc *atc) | |||
1397 | 1424 | ||
1398 | atc->n_srcimp++; | 1425 | atc->n_srcimp++; |
1399 | } | 1426 | } |
1400 | srcimp_dsc.msr = 8; /* SRCIMPs for LINE/MICIn SRT */ | ||
1401 | for (i = 0; i < (2*1); i++) { | ||
1402 | err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, | ||
1403 | (struct srcimp **)&atc->srcimps[2*1+i]); | ||
1404 | if (err) | ||
1405 | return err; | ||
1406 | |||
1407 | atc->n_srcimp++; | ||
1408 | } | ||
1409 | 1427 | ||
1410 | sum_mgr = atc->rsc_mgrs[SUM]; | 1428 | sum_mgr = atc->rsc_mgrs[SUM]; |
1411 | sum_dsc.msr = atc->msr; | 1429 | sum_dsc.msr = atc->msr; |
@@ -1488,6 +1506,18 @@ static void atc_connect_resources(struct ct_atc *atc) | |||
1488 | src = atc->srcs[3]; | 1506 | src = atc->srcs[3]; |
1489 | mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc); | 1507 | mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc); |
1490 | 1508 | ||
1509 | if (atc->model == CTSB1270) { | ||
1510 | /* Titanium HD has a dedicated ADC for the Mic. */ | ||
1511 | dai = container_of(atc->daios[MIC], struct dai, daio); | ||
1512 | atc_connect_dai(atc->rsc_mgrs[SRC], dai, | ||
1513 | (struct src **)&atc->srcs[4], | ||
1514 | (struct srcimp **)&atc->srcimps[4]); | ||
1515 | src = atc->srcs[4]; | ||
1516 | mixer->set_input_left(mixer, MIX_MIC_IN, &src->rsc); | ||
1517 | src = atc->srcs[5]; | ||
1518 | mixer->set_input_right(mixer, MIX_MIC_IN, &src->rsc); | ||
1519 | } | ||
1520 | |||
1491 | dai = container_of(atc->daios[SPDIFIO], struct dai, daio); | 1521 | dai = container_of(atc->daios[SPDIFIO], struct dai, daio); |
1492 | atc_connect_dai(atc->rsc_mgrs[SRC], dai, | 1522 | atc_connect_dai(atc->rsc_mgrs[SRC], dai, |
1493 | (struct src **)&atc->srcs[0], | 1523 | (struct src **)&atc->srcs[0], |
@@ -1606,12 +1636,17 @@ static struct ct_atc atc_preset __devinitdata = { | |||
1606 | .line_clfe_unmute = atc_line_clfe_unmute, | 1636 | .line_clfe_unmute = atc_line_clfe_unmute, |
1607 | .line_rear_unmute = atc_line_rear_unmute, | 1637 | .line_rear_unmute = atc_line_rear_unmute, |
1608 | .line_in_unmute = atc_line_in_unmute, | 1638 | .line_in_unmute = atc_line_in_unmute, |
1639 | .mic_unmute = atc_mic_unmute, | ||
1609 | .spdif_out_unmute = atc_spdif_out_unmute, | 1640 | .spdif_out_unmute = atc_spdif_out_unmute, |
1610 | .spdif_in_unmute = atc_spdif_in_unmute, | 1641 | .spdif_in_unmute = atc_spdif_in_unmute, |
1611 | .spdif_out_get_status = atc_spdif_out_get_status, | 1642 | .spdif_out_get_status = atc_spdif_out_get_status, |
1612 | .spdif_out_set_status = atc_spdif_out_set_status, | 1643 | .spdif_out_set_status = atc_spdif_out_set_status, |
1613 | .spdif_out_passthru = atc_spdif_out_passthru, | 1644 | .spdif_out_passthru = atc_spdif_out_passthru, |
1614 | .have_digit_io_switch = atc_have_digit_io_switch, | 1645 | .capabilities = atc_capabilities, |
1646 | .output_switch_get = atc_output_switch_get, | ||
1647 | .output_switch_put = atc_output_switch_put, | ||
1648 | .mic_source_switch_get = atc_mic_source_switch_get, | ||
1649 | .mic_source_switch_put = atc_mic_source_switch_put, | ||
1615 | #ifdef CONFIG_PM | 1650 | #ifdef CONFIG_PM |
1616 | .suspend = atc_suspend, | 1651 | .suspend = atc_suspend, |
1617 | .resume = atc_resume, | 1652 | .resume = atc_resume, |
diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h index 7167c0185d52..3a0def656af0 100644 --- a/sound/pci/ctxfi/ctatc.h +++ b/sound/pci/ctxfi/ctatc.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <sound/core.h> | 25 | #include <sound/core.h> |
26 | 26 | ||
27 | #include "ctvmem.h" | 27 | #include "ctvmem.h" |
28 | #include "cthardware.h" | ||
28 | #include "ctresource.h" | 29 | #include "ctresource.h" |
29 | 30 | ||
30 | enum CTALSADEVS { /* Types of alsa devices */ | 31 | enum CTALSADEVS { /* Types of alsa devices */ |
@@ -115,12 +116,17 @@ struct ct_atc { | |||
115 | int (*line_clfe_unmute)(struct ct_atc *atc, unsigned char state); | 116 | int (*line_clfe_unmute)(struct ct_atc *atc, unsigned char state); |
116 | int (*line_rear_unmute)(struct ct_atc *atc, unsigned char state); | 117 | int (*line_rear_unmute)(struct ct_atc *atc, unsigned char state); |
117 | int (*line_in_unmute)(struct ct_atc *atc, unsigned char state); | 118 | int (*line_in_unmute)(struct ct_atc *atc, unsigned char state); |
119 | int (*mic_unmute)(struct ct_atc *atc, unsigned char state); | ||
118 | int (*spdif_out_unmute)(struct ct_atc *atc, unsigned char state); | 120 | int (*spdif_out_unmute)(struct ct_atc *atc, unsigned char state); |
119 | int (*spdif_in_unmute)(struct ct_atc *atc, unsigned char state); | 121 | int (*spdif_in_unmute)(struct ct_atc *atc, unsigned char state); |
120 | int (*spdif_out_get_status)(struct ct_atc *atc, unsigned int *status); | 122 | int (*spdif_out_get_status)(struct ct_atc *atc, unsigned int *status); |
121 | int (*spdif_out_set_status)(struct ct_atc *atc, unsigned int status); | 123 | int (*spdif_out_set_status)(struct ct_atc *atc, unsigned int status); |
122 | int (*spdif_out_passthru)(struct ct_atc *atc, unsigned char state); | 124 | int (*spdif_out_passthru)(struct ct_atc *atc, unsigned char state); |
123 | int (*have_digit_io_switch)(struct ct_atc *atc); | 125 | struct capabilities (*capabilities)(struct ct_atc *atc); |
126 | int (*output_switch_get)(struct ct_atc *atc); | ||
127 | int (*output_switch_put)(struct ct_atc *atc, int position); | ||
128 | int (*mic_source_switch_get)(struct ct_atc *atc); | ||
129 | int (*mic_source_switch_put)(struct ct_atc *atc, int position); | ||
124 | 130 | ||
125 | /* Don't touch! Used for internal object. */ | 131 | /* Don't touch! Used for internal object. */ |
126 | void *rsc_mgrs[NUM_RSCTYP]; /* chip resource managers */ | 132 | void *rsc_mgrs[NUM_RSCTYP]; /* chip resource managers */ |
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c index 47d9ea97de02..0c00eb4088ef 100644 --- a/sound/pci/ctxfi/ctdaio.c +++ b/sound/pci/ctxfi/ctdaio.c | |||
@@ -22,20 +22,9 @@ | |||
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | 24 | ||
25 | #define DAIO_RESOURCE_NUM NUM_DAIOTYP | ||
26 | #define DAIO_OUT_MAX SPDIFOO | 25 | #define DAIO_OUT_MAX SPDIFOO |
27 | 26 | ||
28 | union daio_usage { | 27 | struct daio_usage { |
29 | struct { | ||
30 | unsigned short lineo1:1; | ||
31 | unsigned short lineo2:1; | ||
32 | unsigned short lineo3:1; | ||
33 | unsigned short lineo4:1; | ||
34 | unsigned short spdifoo:1; | ||
35 | unsigned short lineim:1; | ||
36 | unsigned short spdifio:1; | ||
37 | unsigned short spdifi1:1; | ||
38 | } bf; | ||
39 | unsigned short data; | 28 | unsigned short data; |
40 | }; | 29 | }; |
41 | 30 | ||
@@ -61,6 +50,7 @@ struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { | |||
61 | [LINEO3] = {.left = 0x50, .right = 0x51}, | 50 | [LINEO3] = {.left = 0x50, .right = 0x51}, |
62 | [LINEO4] = {.left = 0x70, .right = 0x71}, | 51 | [LINEO4] = {.left = 0x70, .right = 0x71}, |
63 | [LINEIM] = {.left = 0x45, .right = 0xc5}, | 52 | [LINEIM] = {.left = 0x45, .right = 0xc5}, |
53 | [MIC] = {.left = 0x55, .right = 0xd5}, | ||
64 | [SPDIFOO] = {.left = 0x00, .right = 0x01}, | 54 | [SPDIFOO] = {.left = 0x00, .right = 0x01}, |
65 | [SPDIFIO] = {.left = 0x05, .right = 0x85}, | 55 | [SPDIFIO] = {.left = 0x05, .right = 0x85}, |
66 | }; | 56 | }; |
@@ -138,6 +128,7 @@ static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw) | |||
138 | case LINEO3: return 5; | 128 | case LINEO3: return 5; |
139 | case LINEO4: return 6; | 129 | case LINEO4: return 6; |
140 | case LINEIM: return 4; | 130 | case LINEIM: return 4; |
131 | case MIC: return 5; | ||
141 | default: return -EINVAL; | 132 | default: return -EINVAL; |
142 | } | 133 | } |
143 | default: | 134 | default: |
@@ -519,17 +510,17 @@ static int dai_rsc_uninit(struct dai *dai) | |||
519 | 510 | ||
520 | static int daio_mgr_get_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) | 511 | static int daio_mgr_get_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) |
521 | { | 512 | { |
522 | if (((union daio_usage *)mgr->rscs)->data & (0x1 << type)) | 513 | if (((struct daio_usage *)mgr->rscs)->data & (0x1 << type)) |
523 | return -ENOENT; | 514 | return -ENOENT; |
524 | 515 | ||
525 | ((union daio_usage *)mgr->rscs)->data |= (0x1 << type); | 516 | ((struct daio_usage *)mgr->rscs)->data |= (0x1 << type); |
526 | 517 | ||
527 | return 0; | 518 | return 0; |
528 | } | 519 | } |
529 | 520 | ||
530 | static int daio_mgr_put_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) | 521 | static int daio_mgr_put_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) |
531 | { | 522 | { |
532 | ((union daio_usage *)mgr->rscs)->data &= ~(0x1 << type); | 523 | ((struct daio_usage *)mgr->rscs)->data &= ~(0x1 << type); |
533 | 524 | ||
534 | return 0; | 525 | return 0; |
535 | } | 526 | } |
@@ -712,7 +703,7 @@ int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr) | |||
712 | if (!daio_mgr) | 703 | if (!daio_mgr) |
713 | return -ENOMEM; | 704 | return -ENOMEM; |
714 | 705 | ||
715 | err = rsc_mgr_init(&daio_mgr->mgr, DAIO, DAIO_RESOURCE_NUM, hw); | 706 | err = rsc_mgr_init(&daio_mgr->mgr, DAIO, NUM_DAIOTYP, hw); |
716 | if (err) | 707 | if (err) |
717 | goto error1; | 708 | goto error1; |
718 | 709 | ||
diff --git a/sound/pci/ctxfi/ctdaio.h b/sound/pci/ctxfi/ctdaio.h index 0f52ce571ee8..85ccb6ee1ab4 100644 --- a/sound/pci/ctxfi/ctdaio.h +++ b/sound/pci/ctxfi/ctdaio.h | |||
@@ -33,6 +33,7 @@ enum DAIOTYP { | |||
33 | SPDIFOO, /* S/PDIF Out (Flexijack/Optical) */ | 33 | SPDIFOO, /* S/PDIF Out (Flexijack/Optical) */ |
34 | LINEIM, | 34 | LINEIM, |
35 | SPDIFIO, /* S/PDIF In (Flexijack/Optical) on the card */ | 35 | SPDIFIO, /* S/PDIF In (Flexijack/Optical) on the card */ |
36 | MIC, /* Dedicated mic on Titanium HD */ | ||
36 | SPDIFI1, /* S/PDIF In on internal Drive Bay */ | 37 | SPDIFI1, /* S/PDIF In on internal Drive Bay */ |
37 | NUM_DAIOTYP | 38 | NUM_DAIOTYP |
38 | }; | 39 | }; |
diff --git a/sound/pci/ctxfi/cthardware.h b/sound/pci/ctxfi/cthardware.h index af55405f5dec..908315bec3b4 100644 --- a/sound/pci/ctxfi/cthardware.h +++ b/sound/pci/ctxfi/cthardware.h | |||
@@ -39,6 +39,7 @@ enum CTCARDS { | |||
39 | CT20K2_MODEL_FIRST = CTSB0760, | 39 | CT20K2_MODEL_FIRST = CTSB0760, |
40 | CTHENDRIX, | 40 | CTHENDRIX, |
41 | CTSB0880, | 41 | CTSB0880, |
42 | CTSB1270, | ||
42 | CT20K2_UNKNOWN, | 43 | CT20K2_UNKNOWN, |
43 | NUM_CTCARDS /* This should always be the last */ | 44 | NUM_CTCARDS /* This should always be the last */ |
44 | }; | 45 | }; |
@@ -60,6 +61,13 @@ struct card_conf { | |||
60 | unsigned int msr; /* master sample rate in rsrs */ | 61 | unsigned int msr; /* master sample rate in rsrs */ |
61 | }; | 62 | }; |
62 | 63 | ||
64 | struct capabilities { | ||
65 | unsigned int digit_io_switch:1; | ||
66 | unsigned int dedicated_mic:1; | ||
67 | unsigned int output_switch:1; | ||
68 | unsigned int mic_source_switch:1; | ||
69 | }; | ||
70 | |||
63 | struct hw { | 71 | struct hw { |
64 | int (*card_init)(struct hw *hw, struct card_conf *info); | 72 | int (*card_init)(struct hw *hw, struct card_conf *info); |
65 | int (*card_stop)(struct hw *hw); | 73 | int (*card_stop)(struct hw *hw); |
@@ -70,7 +78,11 @@ struct hw { | |||
70 | #endif | 78 | #endif |
71 | int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source); | 79 | int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source); |
72 | int (*select_adc_source)(struct hw *hw, enum ADCSRC source); | 80 | int (*select_adc_source)(struct hw *hw, enum ADCSRC source); |
73 | int (*have_digit_io_switch)(struct hw *hw); | 81 | struct capabilities (*capabilities)(struct hw *hw); |
82 | int (*output_switch_get)(struct hw *hw); | ||
83 | int (*output_switch_put)(struct hw *hw, int position); | ||
84 | int (*mic_source_switch_get)(struct hw *hw); | ||
85 | int (*mic_source_switch_put)(struct hw *hw, int position); | ||
74 | 86 | ||
75 | /* SRC operations */ | 87 | /* SRC operations */ |
76 | int (*src_rsc_get_ctrl_blk)(void **rblk); | 88 | int (*src_rsc_get_ctrl_blk)(void **rblk); |
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index a5c957db5cea..a7df19791f5a 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c | |||
@@ -1777,10 +1777,17 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | |||
1777 | return adc_init_SBx(hw, info->input, info->mic20db); | 1777 | return adc_init_SBx(hw, info->input, info->mic20db); |
1778 | } | 1778 | } |
1779 | 1779 | ||
1780 | static int hw_have_digit_io_switch(struct hw *hw) | 1780 | static struct capabilities hw_capabilities(struct hw *hw) |
1781 | { | 1781 | { |
1782 | struct capabilities cap; | ||
1783 | |||
1782 | /* SB073x and Vista compatible cards have no digit IO switch */ | 1784 | /* SB073x and Vista compatible cards have no digit IO switch */ |
1783 | return !(hw->model == CTSB073X || hw->model == CTUAA); | 1785 | cap.digit_io_switch = !(hw->model == CTSB073X || hw->model == CTUAA); |
1786 | cap.dedicated_mic = 0; | ||
1787 | cap.output_switch = 0; | ||
1788 | cap.mic_source_switch = 0; | ||
1789 | |||
1790 | return cap; | ||
1784 | } | 1791 | } |
1785 | 1792 | ||
1786 | #define CTLBITS(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) | 1793 | #define CTLBITS(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) |
@@ -1933,7 +1940,7 @@ static int hw_card_start(struct hw *hw) | |||
1933 | 1940 | ||
1934 | if (hw->irq < 0) { | 1941 | if (hw->irq < 0) { |
1935 | err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, | 1942 | err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, |
1936 | "ctxfi", hw); | 1943 | KBUILD_MODNAME, hw); |
1937 | if (err < 0) { | 1944 | if (err < 0) { |
1938 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); | 1945 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); |
1939 | goto error2; | 1946 | goto error2; |
@@ -2172,7 +2179,7 @@ static struct hw ct20k1_preset __devinitdata = { | |||
2172 | .pll_init = hw_pll_init, | 2179 | .pll_init = hw_pll_init, |
2173 | .is_adc_source_selected = hw_is_adc_input_selected, | 2180 | .is_adc_source_selected = hw_is_adc_input_selected, |
2174 | .select_adc_source = hw_adc_input_select, | 2181 | .select_adc_source = hw_adc_input_select, |
2175 | .have_digit_io_switch = hw_have_digit_io_switch, | 2182 | .capabilities = hw_capabilities, |
2176 | #ifdef CONFIG_PM | 2183 | #ifdef CONFIG_PM |
2177 | .suspend = hw_suspend, | 2184 | .suspend = hw_suspend, |
2178 | .resume = hw_resume, | 2185 | .resume = hw_resume, |
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index 5364164674e4..d6c54b524bfa 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * @File cthw20k2.c | 8 | * @File cthw20k2.c |
9 | * | 9 | * |
10 | * @Brief | 10 | * @Brief |
11 | * This file contains the implementation of hardware access methord for 20k2. | 11 | * This file contains the implementation of hardware access method for 20k2. |
12 | * | 12 | * |
13 | * @Author Liu Chun | 13 | * @Author Liu Chun |
14 | * @Date May 14 2008 | 14 | * @Date May 14 2008 |
@@ -38,6 +38,8 @@ struct hw20k2 { | |||
38 | unsigned char dev_id; | 38 | unsigned char dev_id; |
39 | unsigned char addr_size; | 39 | unsigned char addr_size; |
40 | unsigned char data_size; | 40 | unsigned char data_size; |
41 | |||
42 | int mic_source; | ||
41 | }; | 43 | }; |
42 | 44 | ||
43 | static u32 hw_read_20kx(struct hw *hw, u32 reg); | 45 | static u32 hw_read_20kx(struct hw *hw, u32 reg); |
@@ -1163,7 +1165,12 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1163 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x01010101); | 1165 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x01010101); |
1164 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); | 1166 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); |
1165 | } else if (2 == info->msr) { | 1167 | } else if (2 == info->msr) { |
1166 | hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111); | 1168 | if (hw->model != CTSB1270) { |
1169 | hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111); | ||
1170 | } else { | ||
1171 | /* PCM4220 on Titanium HD is different. */ | ||
1172 | hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11011111); | ||
1173 | } | ||
1167 | /* Specify all playing 96khz | 1174 | /* Specify all playing 96khz |
1168 | * EA [0] - Enabled | 1175 | * EA [0] - Enabled |
1169 | * RTA [4:5] - 96kHz | 1176 | * RTA [4:5] - 96kHz |
@@ -1175,6 +1182,10 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1175 | * RTD [28:29] - 96kHz */ | 1182 | * RTD [28:29] - 96kHz */ |
1176 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x11111111); | 1183 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x11111111); |
1177 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); | 1184 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); |
1185 | } else if ((4 == info->msr) && (hw->model == CTSB1270)) { | ||
1186 | hw_write_20kx(hw, AUDIO_IO_MCLK, 0x21011111); | ||
1187 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121); | ||
1188 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); | ||
1178 | } else { | 1189 | } else { |
1179 | printk(KERN_ALERT "ctxfi: ERROR!!! Invalid sampling rate!!!\n"); | 1190 | printk(KERN_ALERT "ctxfi: ERROR!!! Invalid sampling rate!!!\n"); |
1180 | return -EINVAL; | 1191 | return -EINVAL; |
@@ -1182,6 +1193,8 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1182 | 1193 | ||
1183 | for (i = 0; i < 8; i++) { | 1194 | for (i = 0; i < 8; i++) { |
1184 | if (i <= 3) { | 1195 | if (i <= 3) { |
1196 | /* This comment looks wrong since loop is over 4 */ | ||
1197 | /* channels and emu20k2 supports 4 spdif IOs. */ | ||
1185 | /* 1st 3 channels are SPDIFs (SB0960) */ | 1198 | /* 1st 3 channels are SPDIFs (SB0960) */ |
1186 | if (i == 3) | 1199 | if (i == 3) |
1187 | data = 0x1001001; | 1200 | data = 0x1001001; |
@@ -1206,12 +1219,16 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1206 | 1219 | ||
1207 | hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_H+(0x40*i), 0x0B); | 1220 | hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_H+(0x40*i), 0x0B); |
1208 | } else { | 1221 | } else { |
1222 | /* Again, loop is over 4 channels not 5. */ | ||
1209 | /* Next 5 channels are I2S (SB0960) */ | 1223 | /* Next 5 channels are I2S (SB0960) */ |
1210 | data = 0x11; | 1224 | data = 0x11; |
1211 | hw_write_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i), data); | 1225 | hw_write_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i), data); |
1212 | if (2 == info->msr) { | 1226 | if (2 == info->msr) { |
1213 | /* Four channels per sample period */ | 1227 | /* Four channels per sample period */ |
1214 | data |= 0x1000; | 1228 | data |= 0x1000; |
1229 | } else if (4 == info->msr) { | ||
1230 | /* FIXME: check this against the chip spec */ | ||
1231 | data |= 0x2000; | ||
1215 | } | 1232 | } |
1216 | hw_write_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i), data); | 1233 | hw_write_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i), data); |
1217 | } | 1234 | } |
@@ -1299,21 +1316,18 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr) | |||
1299 | 1316 | ||
1300 | pllenb = 0xB; | 1317 | pllenb = 0xB; |
1301 | hw_write_20kx(hw, PLL_ENB, pllenb); | 1318 | hw_write_20kx(hw, PLL_ENB, pllenb); |
1302 | pllctl = 0x20D00000; | 1319 | pllctl = 0x20C00000; |
1303 | set_field(&pllctl, PLLCTL_FD, 16 - 4); | 1320 | set_field(&pllctl, PLLCTL_B, 0); |
1321 | set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 4 : 147 - 4); | ||
1322 | set_field(&pllctl, PLLCTL_RD, 48000 == rsr ? 1 - 1 : 10 - 1); | ||
1304 | hw_write_20kx(hw, PLL_CTL, pllctl); | 1323 | hw_write_20kx(hw, PLL_CTL, pllctl); |
1305 | mdelay(40); | 1324 | mdelay(40); |
1325 | |||
1306 | pllctl = hw_read_20kx(hw, PLL_CTL); | 1326 | pllctl = hw_read_20kx(hw, PLL_CTL); |
1307 | set_field(&pllctl, PLLCTL_B, 0); | 1327 | set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 2 : 147 - 2); |
1308 | if (48000 == rsr) { | ||
1309 | set_field(&pllctl, PLLCTL_FD, 16 - 2); | ||
1310 | set_field(&pllctl, PLLCTL_RD, 1 - 1); /* 3000*16/1 = 48000 */ | ||
1311 | } else { /* 44100 */ | ||
1312 | set_field(&pllctl, PLLCTL_FD, 147 - 2); | ||
1313 | set_field(&pllctl, PLLCTL_RD, 10 - 1); /* 3000*147/10 = 44100 */ | ||
1314 | } | ||
1315 | hw_write_20kx(hw, PLL_CTL, pllctl); | 1328 | hw_write_20kx(hw, PLL_CTL, pllctl); |
1316 | mdelay(40); | 1329 | mdelay(40); |
1330 | |||
1317 | for (i = 0; i < 1000; i++) { | 1331 | for (i = 0; i < 1000; i++) { |
1318 | pllstat = hw_read_20kx(hw, PLL_STAT); | 1332 | pllstat = hw_read_20kx(hw, PLL_STAT); |
1319 | if (get_field(pllstat, PLLSTAT_PD)) | 1333 | if (get_field(pllstat, PLLSTAT_PD)) |
@@ -1557,7 +1571,7 @@ static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data) | |||
1557 | 1571 | ||
1558 | hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); | 1572 | hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); |
1559 | hw20k2_i2c_wait_data_ready(hw); | 1573 | hw20k2_i2c_wait_data_ready(hw); |
1560 | /* Dummy write to trigger the write oprtation */ | 1574 | /* Dummy write to trigger the write operation */ |
1561 | hw_write_20kx(hw, I2C_IF_WDATA, 0); | 1575 | hw_write_20kx(hw, I2C_IF_WDATA, 0); |
1562 | hw20k2_i2c_wait_data_ready(hw); | 1576 | hw20k2_i2c_wait_data_ready(hw); |
1563 | 1577 | ||
@@ -1568,6 +1582,30 @@ static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data) | |||
1568 | return 0; | 1582 | return 0; |
1569 | } | 1583 | } |
1570 | 1584 | ||
1585 | static void hw_dac_stop(struct hw *hw) | ||
1586 | { | ||
1587 | u32 data; | ||
1588 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1589 | data &= 0xFFFFFFFD; | ||
1590 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1591 | mdelay(10); | ||
1592 | } | ||
1593 | |||
1594 | static void hw_dac_start(struct hw *hw) | ||
1595 | { | ||
1596 | u32 data; | ||
1597 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1598 | data |= 0x2; | ||
1599 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1600 | mdelay(50); | ||
1601 | } | ||
1602 | |||
1603 | static void hw_dac_reset(struct hw *hw) | ||
1604 | { | ||
1605 | hw_dac_stop(hw); | ||
1606 | hw_dac_start(hw); | ||
1607 | } | ||
1608 | |||
1571 | static int hw_dac_init(struct hw *hw, const struct dac_conf *info) | 1609 | static int hw_dac_init(struct hw *hw, const struct dac_conf *info) |
1572 | { | 1610 | { |
1573 | int err; | 1611 | int err; |
@@ -1594,6 +1632,21 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info) | |||
1594 | 0x00000000 /* Vol Control B4 */ | 1632 | 0x00000000 /* Vol Control B4 */ |
1595 | }; | 1633 | }; |
1596 | 1634 | ||
1635 | if (hw->model == CTSB1270) { | ||
1636 | hw_dac_stop(hw); | ||
1637 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1638 | data &= ~0x0600; | ||
1639 | if (1 == info->msr) | ||
1640 | data |= 0x0000; /* Single Speed Mode 0-50kHz */ | ||
1641 | else if (2 == info->msr) | ||
1642 | data |= 0x0200; /* Double Speed Mode 50-100kHz */ | ||
1643 | else | ||
1644 | data |= 0x0600; /* Quad Speed Mode 100-200kHz */ | ||
1645 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1646 | hw_dac_start(hw); | ||
1647 | return 0; | ||
1648 | } | ||
1649 | |||
1597 | /* Set DAC reset bit as output */ | 1650 | /* Set DAC reset bit as output */ |
1598 | data = hw_read_20kx(hw, GPIO_CTRL); | 1651 | data = hw_read_20kx(hw, GPIO_CTRL); |
1599 | data |= 0x02; | 1652 | data |= 0x02; |
@@ -1606,22 +1659,8 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info) | |||
1606 | for (i = 0; i < 2; i++) { | 1659 | for (i = 0; i < 2; i++) { |
1607 | /* Reset DAC twice just in-case the chip | 1660 | /* Reset DAC twice just in-case the chip |
1608 | * didn't initialized properly */ | 1661 | * didn't initialized properly */ |
1609 | data = hw_read_20kx(hw, GPIO_DATA); | 1662 | hw_dac_reset(hw); |
1610 | /* GPIO data bit 1 */ | 1663 | hw_dac_reset(hw); |
1611 | data &= 0xFFFFFFFD; | ||
1612 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1613 | mdelay(10); | ||
1614 | data |= 0x2; | ||
1615 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1616 | mdelay(50); | ||
1617 | |||
1618 | /* Reset the 2nd time */ | ||
1619 | data &= 0xFFFFFFFD; | ||
1620 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1621 | mdelay(10); | ||
1622 | data |= 0x2; | ||
1623 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1624 | mdelay(50); | ||
1625 | 1664 | ||
1626 | if (hw20k2_i2c_read(hw, CS4382_MC1, &cs_read.mode_control_1)) | 1665 | if (hw20k2_i2c_read(hw, CS4382_MC1, &cs_read.mode_control_1)) |
1627 | continue; | 1666 | continue; |
@@ -1725,7 +1764,11 @@ End: | |||
1725 | static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) | 1764 | static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) |
1726 | { | 1765 | { |
1727 | u32 data; | 1766 | u32 data; |
1728 | 1767 | if (hw->model == CTSB1270) { | |
1768 | /* Titanium HD has two ADC chips, one for line in and one */ | ||
1769 | /* for MIC. We don't need to switch the ADC input. */ | ||
1770 | return 1; | ||
1771 | } | ||
1729 | data = hw_read_20kx(hw, GPIO_DATA); | 1772 | data = hw_read_20kx(hw, GPIO_DATA); |
1730 | switch (type) { | 1773 | switch (type) { |
1731 | case ADC_MICIN: | 1774 | case ADC_MICIN: |
@@ -1742,35 +1785,47 @@ static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) | |||
1742 | 1785 | ||
1743 | #define MIC_BOOST_0DB 0xCF | 1786 | #define MIC_BOOST_0DB 0xCF |
1744 | #define MIC_BOOST_STEPS_PER_DB 2 | 1787 | #define MIC_BOOST_STEPS_PER_DB 2 |
1745 | #define MIC_BOOST_20DB (MIC_BOOST_0DB + 20 * MIC_BOOST_STEPS_PER_DB) | 1788 | |
1789 | static void hw_wm8775_input_select(struct hw *hw, u8 input, s8 gain_in_db) | ||
1790 | { | ||
1791 | u32 adcmc, gain; | ||
1792 | |||
1793 | if (input > 3) | ||
1794 | input = 3; | ||
1795 | |||
1796 | adcmc = ((u32)1 << input) | 0x100; /* Link L+R gain... */ | ||
1797 | |||
1798 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, adcmc), | ||
1799 | MAKE_WM8775_DATA(adcmc)); | ||
1800 | |||
1801 | if (gain_in_db < -103) | ||
1802 | gain_in_db = -103; | ||
1803 | if (gain_in_db > 24) | ||
1804 | gain_in_db = 24; | ||
1805 | |||
1806 | gain = gain_in_db * MIC_BOOST_STEPS_PER_DB + MIC_BOOST_0DB; | ||
1807 | |||
1808 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, gain), | ||
1809 | MAKE_WM8775_DATA(gain)); | ||
1810 | /* ...so there should be no need for the following. */ | ||
1811 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, gain), | ||
1812 | MAKE_WM8775_DATA(gain)); | ||
1813 | } | ||
1746 | 1814 | ||
1747 | static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) | 1815 | static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) |
1748 | { | 1816 | { |
1749 | u32 data; | 1817 | u32 data; |
1750 | |||
1751 | data = hw_read_20kx(hw, GPIO_DATA); | 1818 | data = hw_read_20kx(hw, GPIO_DATA); |
1752 | switch (type) { | 1819 | switch (type) { |
1753 | case ADC_MICIN: | 1820 | case ADC_MICIN: |
1754 | data |= (0x1 << 14); | 1821 | data |= (0x1 << 14); |
1755 | hw_write_20kx(hw, GPIO_DATA, data); | 1822 | hw_write_20kx(hw, GPIO_DATA, data); |
1756 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101), | 1823 | hw_wm8775_input_select(hw, 0, 20); /* Mic, 20dB */ |
1757 | MAKE_WM8775_DATA(0x101)); /* Mic-in */ | ||
1758 | hw20k2_i2c_write(hw, | ||
1759 | MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB), | ||
1760 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1761 | hw20k2_i2c_write(hw, | ||
1762 | MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB), | ||
1763 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1764 | break; | 1824 | break; |
1765 | case ADC_LINEIN: | 1825 | case ADC_LINEIN: |
1766 | data &= ~(0x1 << 14); | 1826 | data &= ~(0x1 << 14); |
1767 | hw_write_20kx(hw, GPIO_DATA, data); | 1827 | hw_write_20kx(hw, GPIO_DATA, data); |
1768 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102), | 1828 | hw_wm8775_input_select(hw, 1, 0); /* Line-in, 0dB */ |
1769 | MAKE_WM8775_DATA(0x102)); /* Line-in */ | ||
1770 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF), | ||
1771 | MAKE_WM8775_DATA(0xCF)); /* No boost */ | ||
1772 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF), | ||
1773 | MAKE_WM8775_DATA(0xCF)); /* No boost */ | ||
1774 | break; | 1829 | break; |
1775 | default: | 1830 | default: |
1776 | break; | 1831 | break; |
@@ -1782,7 +1837,7 @@ static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) | |||
1782 | static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | 1837 | static int hw_adc_init(struct hw *hw, const struct adc_conf *info) |
1783 | { | 1838 | { |
1784 | int err; | 1839 | int err; |
1785 | u32 mux = 2, data, ctl; | 1840 | u32 data, ctl; |
1786 | 1841 | ||
1787 | /* Set ADC reset bit as output */ | 1842 | /* Set ADC reset bit as output */ |
1788 | data = hw_read_20kx(hw, GPIO_CTRL); | 1843 | data = hw_read_20kx(hw, GPIO_CTRL); |
@@ -1796,19 +1851,42 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | |||
1796 | goto error; | 1851 | goto error; |
1797 | } | 1852 | } |
1798 | 1853 | ||
1799 | /* Make ADC in normal operation */ | 1854 | /* Reset the ADC (reset is active low). */ |
1800 | data = hw_read_20kx(hw, GPIO_DATA); | 1855 | data = hw_read_20kx(hw, GPIO_DATA); |
1801 | data &= ~(0x1 << 15); | 1856 | data &= ~(0x1 << 15); |
1857 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1858 | |||
1859 | if (hw->model == CTSB1270) { | ||
1860 | /* Set up the PCM4220 ADC on Titanium HD */ | ||
1861 | data &= ~0x0C; | ||
1862 | if (1 == info->msr) | ||
1863 | data |= 0x00; /* Single Speed Mode 32-50kHz */ | ||
1864 | else if (2 == info->msr) | ||
1865 | data |= 0x08; /* Double Speed Mode 50-108kHz */ | ||
1866 | else | ||
1867 | data |= 0x04; /* Quad Speed Mode 108kHz-216kHz */ | ||
1868 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1869 | } | ||
1870 | |||
1802 | mdelay(10); | 1871 | mdelay(10); |
1872 | /* Return the ADC to normal operation. */ | ||
1803 | data |= (0x1 << 15); | 1873 | data |= (0x1 << 15); |
1804 | hw_write_20kx(hw, GPIO_DATA, data); | 1874 | hw_write_20kx(hw, GPIO_DATA, data); |
1805 | mdelay(50); | 1875 | mdelay(50); |
1806 | 1876 | ||
1877 | /* I2C write to register offset 0x0B to set ADC LRCLK polarity */ | ||
1878 | /* invert bit, interface format to I2S, word length to 24-bit, */ | ||
1879 | /* enable ADC high pass filter. Fixes bug 5323? */ | ||
1880 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_IC, 0x26), | ||
1881 | MAKE_WM8775_DATA(0x26)); | ||
1882 | |||
1807 | /* Set the master mode (256fs) */ | 1883 | /* Set the master mode (256fs) */ |
1808 | if (1 == info->msr) { | 1884 | if (1 == info->msr) { |
1885 | /* slave mode, 128x oversampling 256fs */ | ||
1809 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x02), | 1886 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x02), |
1810 | MAKE_WM8775_DATA(0x02)); | 1887 | MAKE_WM8775_DATA(0x02)); |
1811 | } else if (2 == info->msr) { | 1888 | } else if ((2 == info->msr) || (4 == info->msr)) { |
1889 | /* slave mode, 64x oversampling, 256fs */ | ||
1812 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A), | 1890 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A), |
1813 | MAKE_WM8775_DATA(0x0A)); | 1891 | MAKE_WM8775_DATA(0x0A)); |
1814 | } else { | 1892 | } else { |
@@ -1818,55 +1896,113 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | |||
1818 | goto error; | 1896 | goto error; |
1819 | } | 1897 | } |
1820 | 1898 | ||
1821 | /* Configure GPIO bit 14 change to line-in/mic-in */ | 1899 | if (hw->model != CTSB1270) { |
1822 | ctl = hw_read_20kx(hw, GPIO_CTRL); | 1900 | /* Configure GPIO bit 14 change to line-in/mic-in */ |
1823 | ctl |= 0x1 << 14; | 1901 | ctl = hw_read_20kx(hw, GPIO_CTRL); |
1824 | hw_write_20kx(hw, GPIO_CTRL, ctl); | 1902 | ctl |= 0x1 << 14; |
1825 | 1903 | hw_write_20kx(hw, GPIO_CTRL, ctl); | |
1826 | /* Check using Mic-in or Line-in */ | 1904 | hw_adc_input_select(hw, ADC_LINEIN); |
1827 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1828 | |||
1829 | if (mux == 1) { | ||
1830 | /* Configures GPIO data to select Mic-in */ | ||
1831 | data |= 0x1 << 14; | ||
1832 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1833 | |||
1834 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101), | ||
1835 | MAKE_WM8775_DATA(0x101)); /* Mic-in */ | ||
1836 | hw20k2_i2c_write(hw, | ||
1837 | MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB), | ||
1838 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1839 | hw20k2_i2c_write(hw, | ||
1840 | MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB), | ||
1841 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1842 | } else if (mux == 2) { | ||
1843 | /* Configures GPIO data to select Line-in */ | ||
1844 | data &= ~(0x1 << 14); | ||
1845 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1846 | |||
1847 | /* Setup ADC */ | ||
1848 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102), | ||
1849 | MAKE_WM8775_DATA(0x102)); /* Line-in */ | ||
1850 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF), | ||
1851 | MAKE_WM8775_DATA(0xCF)); /* No boost */ | ||
1852 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF), | ||
1853 | MAKE_WM8775_DATA(0xCF)); /* No boost */ | ||
1854 | } else { | 1905 | } else { |
1855 | printk(KERN_ALERT "ctxfi: ERROR!!! Invalid input mux!!!\n"); | 1906 | hw_wm8775_input_select(hw, 0, 0); |
1856 | err = -EINVAL; | ||
1857 | goto error; | ||
1858 | } | 1907 | } |
1859 | 1908 | ||
1860 | return 0; | 1909 | return 0; |
1861 | |||
1862 | error: | 1910 | error: |
1863 | hw20k2_i2c_uninit(hw); | 1911 | hw20k2_i2c_uninit(hw); |
1864 | return err; | 1912 | return err; |
1865 | } | 1913 | } |
1866 | 1914 | ||
1867 | static int hw_have_digit_io_switch(struct hw *hw) | 1915 | static struct capabilities hw_capabilities(struct hw *hw) |
1868 | { | 1916 | { |
1869 | return 0; | 1917 | struct capabilities cap; |
1918 | |||
1919 | cap.digit_io_switch = 0; | ||
1920 | cap.dedicated_mic = hw->model == CTSB1270; | ||
1921 | cap.output_switch = hw->model == CTSB1270; | ||
1922 | cap.mic_source_switch = hw->model == CTSB1270; | ||
1923 | |||
1924 | return cap; | ||
1925 | } | ||
1926 | |||
1927 | static int hw_output_switch_get(struct hw *hw) | ||
1928 | { | ||
1929 | u32 data = hw_read_20kx(hw, GPIO_EXT_DATA); | ||
1930 | |||
1931 | switch (data & 0x30) { | ||
1932 | case 0x00: | ||
1933 | return 0; | ||
1934 | case 0x10: | ||
1935 | return 1; | ||
1936 | case 0x20: | ||
1937 | return 2; | ||
1938 | default: | ||
1939 | return 3; | ||
1940 | } | ||
1941 | } | ||
1942 | |||
1943 | static int hw_output_switch_put(struct hw *hw, int position) | ||
1944 | { | ||
1945 | u32 data; | ||
1946 | |||
1947 | if (position == hw_output_switch_get(hw)) | ||
1948 | return 0; | ||
1949 | |||
1950 | /* Mute line and headphones (intended for anti-pop). */ | ||
1951 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1952 | data |= (0x03 << 11); | ||
1953 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1954 | |||
1955 | data = hw_read_20kx(hw, GPIO_EXT_DATA) & ~0x30; | ||
1956 | switch (position) { | ||
1957 | case 0: | ||
1958 | break; | ||
1959 | case 1: | ||
1960 | data |= 0x10; | ||
1961 | break; | ||
1962 | default: | ||
1963 | data |= 0x20; | ||
1964 | } | ||
1965 | hw_write_20kx(hw, GPIO_EXT_DATA, data); | ||
1966 | |||
1967 | /* Unmute line and headphones. */ | ||
1968 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1969 | data &= ~(0x03 << 11); | ||
1970 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1971 | |||
1972 | return 1; | ||
1973 | } | ||
1974 | |||
1975 | static int hw_mic_source_switch_get(struct hw *hw) | ||
1976 | { | ||
1977 | struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; | ||
1978 | |||
1979 | return hw20k2->mic_source; | ||
1980 | } | ||
1981 | |||
1982 | static int hw_mic_source_switch_put(struct hw *hw, int position) | ||
1983 | { | ||
1984 | struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; | ||
1985 | |||
1986 | if (position == hw20k2->mic_source) | ||
1987 | return 0; | ||
1988 | |||
1989 | switch (position) { | ||
1990 | case 0: | ||
1991 | hw_wm8775_input_select(hw, 0, 0); /* Mic, 0dB */ | ||
1992 | break; | ||
1993 | case 1: | ||
1994 | hw_wm8775_input_select(hw, 1, 0); /* FP Mic, 0dB */ | ||
1995 | break; | ||
1996 | case 2: | ||
1997 | hw_wm8775_input_select(hw, 3, 0); /* Aux Ext, 0dB */ | ||
1998 | break; | ||
1999 | default: | ||
2000 | return 0; | ||
2001 | } | ||
2002 | |||
2003 | hw20k2->mic_source = position; | ||
2004 | |||
2005 | return 1; | ||
1870 | } | 2006 | } |
1871 | 2007 | ||
1872 | static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id) | 2008 | static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id) |
@@ -1925,7 +2061,7 @@ static int hw_card_start(struct hw *hw) | |||
1925 | 2061 | ||
1926 | if (hw->irq < 0) { | 2062 | if (hw->irq < 0) { |
1927 | err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED, | 2063 | err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED, |
1928 | "ctxfi", hw); | 2064 | KBUILD_MODNAME, hw); |
1929 | if (err < 0) { | 2065 | if (err < 0) { |
1930 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); | 2066 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); |
1931 | goto error2; | 2067 | goto error2; |
@@ -2023,13 +2159,16 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) | |||
2023 | /* Reset all SRC pending interrupts */ | 2159 | /* Reset all SRC pending interrupts */ |
2024 | hw_write_20kx(hw, SRC_IP, 0); | 2160 | hw_write_20kx(hw, SRC_IP, 0); |
2025 | 2161 | ||
2026 | /* TODO: detect the card ID and configure GPIO accordingly. */ | 2162 | if (hw->model != CTSB1270) { |
2027 | /* Configures GPIO (0xD802 0x98028) */ | 2163 | /* TODO: detect the card ID and configure GPIO accordingly. */ |
2028 | /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/ | 2164 | /* Configures GPIO (0xD802 0x98028) */ |
2029 | /* Configures GPIO (SB0880) */ | 2165 | /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/ |
2030 | /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/ | 2166 | /* Configures GPIO (SB0880) */ |
2031 | hw_write_20kx(hw, GPIO_CTRL, 0xD802); | 2167 | /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/ |
2032 | 2168 | hw_write_20kx(hw, GPIO_CTRL, 0xD802); | |
2169 | } else { | ||
2170 | hw_write_20kx(hw, GPIO_CTRL, 0x9E5F); | ||
2171 | } | ||
2033 | /* Enable audio ring */ | 2172 | /* Enable audio ring */ |
2034 | hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01); | 2173 | hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01); |
2035 | 2174 | ||
@@ -2106,7 +2245,11 @@ static struct hw ct20k2_preset __devinitdata = { | |||
2106 | .pll_init = hw_pll_init, | 2245 | .pll_init = hw_pll_init, |
2107 | .is_adc_source_selected = hw_is_adc_input_selected, | 2246 | .is_adc_source_selected = hw_is_adc_input_selected, |
2108 | .select_adc_source = hw_adc_input_select, | 2247 | .select_adc_source = hw_adc_input_select, |
2109 | .have_digit_io_switch = hw_have_digit_io_switch, | 2248 | .capabilities = hw_capabilities, |
2249 | .output_switch_get = hw_output_switch_get, | ||
2250 | .output_switch_put = hw_output_switch_put, | ||
2251 | .mic_source_switch_get = hw_mic_source_switch_get, | ||
2252 | .mic_source_switch_put = hw_mic_source_switch_put, | ||
2110 | #ifdef CONFIG_PM | 2253 | #ifdef CONFIG_PM |
2111 | .suspend = hw_suspend, | 2254 | .suspend = hw_suspend, |
2112 | .resume = hw_resume, | 2255 | .resume = hw_resume, |
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index c3519ff42fbb..0cc13eeef8da 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c | |||
@@ -86,9 +86,7 @@ enum CTALSA_MIXER_CTL { | |||
86 | MIXER_LINEIN_C_S, | 86 | MIXER_LINEIN_C_S, |
87 | MIXER_MIC_C_S, | 87 | MIXER_MIC_C_S, |
88 | MIXER_SPDIFI_C_S, | 88 | MIXER_SPDIFI_C_S, |
89 | MIXER_LINEIN_P_S, | ||
90 | MIXER_SPDIFO_P_S, | 89 | MIXER_SPDIFO_P_S, |
91 | MIXER_SPDIFI_P_S, | ||
92 | MIXER_WAVEF_P_S, | 90 | MIXER_WAVEF_P_S, |
93 | MIXER_WAVER_P_S, | 91 | MIXER_WAVER_P_S, |
94 | MIXER_WAVEC_P_S, | 92 | MIXER_WAVEC_P_S, |
@@ -137,11 +135,11 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { | |||
137 | }, | 135 | }, |
138 | [MIXER_LINEIN_P] = { | 136 | [MIXER_LINEIN_P] = { |
139 | .ctl = 1, | 137 | .ctl = 1, |
140 | .name = "Line-in Playback Volume", | 138 | .name = "Line Playback Volume", |
141 | }, | 139 | }, |
142 | [MIXER_LINEIN_C] = { | 140 | [MIXER_LINEIN_C] = { |
143 | .ctl = 1, | 141 | .ctl = 1, |
144 | .name = "Line-in Capture Volume", | 142 | .name = "Line Capture Volume", |
145 | }, | 143 | }, |
146 | [MIXER_MIC_P] = { | 144 | [MIXER_MIC_P] = { |
147 | .ctl = 1, | 145 | .ctl = 1, |
@@ -153,15 +151,15 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { | |||
153 | }, | 151 | }, |
154 | [MIXER_SPDIFI_P] = { | 152 | [MIXER_SPDIFI_P] = { |
155 | .ctl = 1, | 153 | .ctl = 1, |
156 | .name = "S/PDIF-in Playback Volume", | 154 | .name = "IEC958 Playback Volume", |
157 | }, | 155 | }, |
158 | [MIXER_SPDIFI_C] = { | 156 | [MIXER_SPDIFI_C] = { |
159 | .ctl = 1, | 157 | .ctl = 1, |
160 | .name = "S/PDIF-in Capture Volume", | 158 | .name = "IEC958 Capture Volume", |
161 | }, | 159 | }, |
162 | [MIXER_SPDIFO_P] = { | 160 | [MIXER_SPDIFO_P] = { |
163 | .ctl = 1, | 161 | .ctl = 1, |
164 | .name = "S/PDIF-out Playback Volume", | 162 | .name = "Digital Playback Volume", |
165 | }, | 163 | }, |
166 | [MIXER_WAVEF_P] = { | 164 | [MIXER_WAVEF_P] = { |
167 | .ctl = 1, | 165 | .ctl = 1, |
@@ -179,14 +177,13 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { | |||
179 | .ctl = 1, | 177 | .ctl = 1, |
180 | .name = "Surround Playback Volume", | 178 | .name = "Surround Playback Volume", |
181 | }, | 179 | }, |
182 | |||
183 | [MIXER_PCM_C_S] = { | 180 | [MIXER_PCM_C_S] = { |
184 | .ctl = 1, | 181 | .ctl = 1, |
185 | .name = "PCM Capture Switch", | 182 | .name = "PCM Capture Switch", |
186 | }, | 183 | }, |
187 | [MIXER_LINEIN_C_S] = { | 184 | [MIXER_LINEIN_C_S] = { |
188 | .ctl = 1, | 185 | .ctl = 1, |
189 | .name = "Line-in Capture Switch", | 186 | .name = "Line Capture Switch", |
190 | }, | 187 | }, |
191 | [MIXER_MIC_C_S] = { | 188 | [MIXER_MIC_C_S] = { |
192 | .ctl = 1, | 189 | .ctl = 1, |
@@ -194,19 +191,11 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { | |||
194 | }, | 191 | }, |
195 | [MIXER_SPDIFI_C_S] = { | 192 | [MIXER_SPDIFI_C_S] = { |
196 | .ctl = 1, | 193 | .ctl = 1, |
197 | .name = "S/PDIF-in Capture Switch", | 194 | .name = "IEC958 Capture Switch", |
198 | }, | ||
199 | [MIXER_LINEIN_P_S] = { | ||
200 | .ctl = 1, | ||
201 | .name = "Line-in Playback Switch", | ||
202 | }, | 195 | }, |
203 | [MIXER_SPDIFO_P_S] = { | 196 | [MIXER_SPDIFO_P_S] = { |
204 | .ctl = 1, | 197 | .ctl = 1, |
205 | .name = "S/PDIF-out Playback Switch", | 198 | .name = "Digital Playback Switch", |
206 | }, | ||
207 | [MIXER_SPDIFI_P_S] = { | ||
208 | .ctl = 1, | ||
209 | .name = "S/PDIF-in Playback Switch", | ||
210 | }, | 199 | }, |
211 | [MIXER_WAVEF_P_S] = { | 200 | [MIXER_WAVEF_P_S] = { |
212 | .ctl = 1, | 201 | .ctl = 1, |
@@ -236,6 +225,8 @@ ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); | |||
236 | static void | 225 | static void |
237 | ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); | 226 | ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); |
238 | 227 | ||
228 | /* FIXME: this static looks like it would fail if more than one card was */ | ||
229 | /* installed. */ | ||
239 | static struct snd_kcontrol *kctls[2] = {NULL}; | 230 | static struct snd_kcontrol *kctls[2] = {NULL}; |
240 | 231 | ||
241 | static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index) | 232 | static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index) |
@@ -420,6 +411,77 @@ static struct snd_kcontrol_new vol_ctl = { | |||
420 | .tlv = { .p = ct_vol_db_scale }, | 411 | .tlv = { .p = ct_vol_db_scale }, |
421 | }; | 412 | }; |
422 | 413 | ||
414 | static int output_switch_info(struct snd_kcontrol *kcontrol, | ||
415 | struct snd_ctl_elem_info *info) | ||
416 | { | ||
417 | static const char *const names[3] = { | ||
418 | "FP Headphones", "Headphones", "Speakers" | ||
419 | }; | ||
420 | |||
421 | return snd_ctl_enum_info(info, 1, 3, names); | ||
422 | } | ||
423 | |||
424 | static int output_switch_get(struct snd_kcontrol *kcontrol, | ||
425 | struct snd_ctl_elem_value *ucontrol) | ||
426 | { | ||
427 | struct ct_atc *atc = snd_kcontrol_chip(kcontrol); | ||
428 | ucontrol->value.enumerated.item[0] = atc->output_switch_get(atc); | ||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static int output_switch_put(struct snd_kcontrol *kcontrol, | ||
433 | struct snd_ctl_elem_value *ucontrol) | ||
434 | { | ||
435 | struct ct_atc *atc = snd_kcontrol_chip(kcontrol); | ||
436 | if (ucontrol->value.enumerated.item[0] > 2) | ||
437 | return -EINVAL; | ||
438 | return atc->output_switch_put(atc, ucontrol->value.enumerated.item[0]); | ||
439 | } | ||
440 | |||
441 | static struct snd_kcontrol_new output_ctl = { | ||
442 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
443 | .name = "Analog Output Playback Enum", | ||
444 | .info = output_switch_info, | ||
445 | .get = output_switch_get, | ||
446 | .put = output_switch_put, | ||
447 | }; | ||
448 | |||
449 | static int mic_source_switch_info(struct snd_kcontrol *kcontrol, | ||
450 | struct snd_ctl_elem_info *info) | ||
451 | { | ||
452 | static const char *const names[3] = { | ||
453 | "Mic", "FP Mic", "Aux" | ||
454 | }; | ||
455 | |||
456 | return snd_ctl_enum_info(info, 1, 3, names); | ||
457 | } | ||
458 | |||
459 | static int mic_source_switch_get(struct snd_kcontrol *kcontrol, | ||
460 | struct snd_ctl_elem_value *ucontrol) | ||
461 | { | ||
462 | struct ct_atc *atc = snd_kcontrol_chip(kcontrol); | ||
463 | ucontrol->value.enumerated.item[0] = atc->mic_source_switch_get(atc); | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | static int mic_source_switch_put(struct snd_kcontrol *kcontrol, | ||
468 | struct snd_ctl_elem_value *ucontrol) | ||
469 | { | ||
470 | struct ct_atc *atc = snd_kcontrol_chip(kcontrol); | ||
471 | if (ucontrol->value.enumerated.item[0] > 2) | ||
472 | return -EINVAL; | ||
473 | return atc->mic_source_switch_put(atc, | ||
474 | ucontrol->value.enumerated.item[0]); | ||
475 | } | ||
476 | |||
477 | static struct snd_kcontrol_new mic_source_ctl = { | ||
478 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
479 | .name = "Mic Source Capture Enum", | ||
480 | .info = mic_source_switch_info, | ||
481 | .get = mic_source_switch_get, | ||
482 | .put = mic_source_switch_put, | ||
483 | }; | ||
484 | |||
423 | static void | 485 | static void |
424 | do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type) | 486 | do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type) |
425 | { | 487 | { |
@@ -465,6 +527,7 @@ do_digit_io_switch(struct ct_atc *atc, int state) | |||
465 | static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) | 527 | static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) |
466 | { | 528 | { |
467 | struct ct_mixer *mixer = atc->mixer; | 529 | struct ct_mixer *mixer = atc->mixer; |
530 | struct capabilities cap = atc->capabilities(atc); | ||
468 | 531 | ||
469 | /* Do changes in mixer. */ | 532 | /* Do changes in mixer. */ |
470 | if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) { | 533 | if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) { |
@@ -477,8 +540,17 @@ static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) | |||
477 | } | 540 | } |
478 | } | 541 | } |
479 | /* Do changes out of mixer. */ | 542 | /* Do changes out of mixer. */ |
480 | if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) | 543 | if (!cap.dedicated_mic && |
481 | do_line_mic_switch(atc, type); | 544 | (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) { |
545 | if (state) | ||
546 | do_line_mic_switch(atc, type); | ||
547 | atc->line_in_unmute(atc, state); | ||
548 | } else if (cap.dedicated_mic && (MIXER_LINEIN_C_S == type)) | ||
549 | atc->line_in_unmute(atc, state); | ||
550 | else if (cap.dedicated_mic && (MIXER_MIC_C_S == type)) | ||
551 | atc->mic_unmute(atc, state); | ||
552 | else if (MIXER_SPDIFI_C_S == type) | ||
553 | atc->spdif_in_unmute(atc, state); | ||
482 | else if (MIXER_WAVEF_P_S == type) | 554 | else if (MIXER_WAVEF_P_S == type) |
483 | atc->line_front_unmute(atc, state); | 555 | atc->line_front_unmute(atc, state); |
484 | else if (MIXER_WAVES_P_S == type) | 556 | else if (MIXER_WAVES_P_S == type) |
@@ -487,12 +559,8 @@ static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) | |||
487 | atc->line_clfe_unmute(atc, state); | 559 | atc->line_clfe_unmute(atc, state); |
488 | else if (MIXER_WAVER_P_S == type) | 560 | else if (MIXER_WAVER_P_S == type) |
489 | atc->line_rear_unmute(atc, state); | 561 | atc->line_rear_unmute(atc, state); |
490 | else if (MIXER_LINEIN_P_S == type) | ||
491 | atc->line_in_unmute(atc, state); | ||
492 | else if (MIXER_SPDIFO_P_S == type) | 562 | else if (MIXER_SPDIFO_P_S == type) |
493 | atc->spdif_out_unmute(atc, state); | 563 | atc->spdif_out_unmute(atc, state); |
494 | else if (MIXER_SPDIFI_P_S == type) | ||
495 | atc->spdif_in_unmute(atc, state); | ||
496 | else if (MIXER_DIGITAL_IO_S == type) | 564 | else if (MIXER_DIGITAL_IO_S == type) |
497 | do_digit_io_switch(atc, state); | 565 | do_digit_io_switch(atc, state); |
498 | 566 | ||
@@ -671,6 +739,7 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) | |||
671 | { | 739 | { |
672 | enum CTALSA_MIXER_CTL type; | 740 | enum CTALSA_MIXER_CTL type; |
673 | struct ct_atc *atc = mixer->atc; | 741 | struct ct_atc *atc = mixer->atc; |
742 | struct capabilities cap = atc->capabilities(atc); | ||
674 | int err; | 743 | int err; |
675 | 744 | ||
676 | /* Create snd kcontrol instances on demand */ | 745 | /* Create snd kcontrol instances on demand */ |
@@ -684,8 +753,8 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) | |||
684 | } | 753 | } |
685 | } | 754 | } |
686 | 755 | ||
687 | ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = | 756 | ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = cap.digit_io_switch; |
688 | atc->have_digit_io_switch(atc); | 757 | |
689 | for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) { | 758 | for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) { |
690 | if (ct_kcontrol_init_table[type].ctl) { | 759 | if (ct_kcontrol_init_table[type].ctl) { |
691 | swh_ctl.name = ct_kcontrol_init_table[type].name; | 760 | swh_ctl.name = ct_kcontrol_init_table[type].name; |
@@ -708,6 +777,17 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) | |||
708 | if (err) | 777 | if (err) |
709 | return err; | 778 | return err; |
710 | 779 | ||
780 | if (cap.output_switch) { | ||
781 | err = ct_mixer_kcontrol_new(mixer, &output_ctl); | ||
782 | if (err) | ||
783 | return err; | ||
784 | } | ||
785 | |||
786 | if (cap.mic_source_switch) { | ||
787 | err = ct_mixer_kcontrol_new(mixer, &mic_source_ctl); | ||
788 | if (err) | ||
789 | return err; | ||
790 | } | ||
711 | atc->line_front_unmute(atc, 1); | 791 | atc->line_front_unmute(atc, 1); |
712 | set_switch_state(mixer, MIXER_WAVEF_P_S, 1); | 792 | set_switch_state(mixer, MIXER_WAVEF_P_S, 1); |
713 | atc->line_surround_unmute(atc, 0); | 793 | atc->line_surround_unmute(atc, 0); |
@@ -719,13 +799,12 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) | |||
719 | atc->spdif_out_unmute(atc, 0); | 799 | atc->spdif_out_unmute(atc, 0); |
720 | set_switch_state(mixer, MIXER_SPDIFO_P_S, 0); | 800 | set_switch_state(mixer, MIXER_SPDIFO_P_S, 0); |
721 | atc->line_in_unmute(atc, 0); | 801 | atc->line_in_unmute(atc, 0); |
722 | set_switch_state(mixer, MIXER_LINEIN_P_S, 0); | 802 | if (cap.dedicated_mic) |
803 | atc->mic_unmute(atc, 0); | ||
723 | atc->spdif_in_unmute(atc, 0); | 804 | atc->spdif_in_unmute(atc, 0); |
724 | set_switch_state(mixer, MIXER_SPDIFI_P_S, 0); | 805 | set_switch_state(mixer, MIXER_PCM_C_S, 0); |
725 | 806 | set_switch_state(mixer, MIXER_LINEIN_C_S, 0); | |
726 | set_switch_state(mixer, MIXER_PCM_C_S, 1); | 807 | set_switch_state(mixer, MIXER_SPDIFI_C_S, 0); |
727 | set_switch_state(mixer, MIXER_LINEIN_C_S, 1); | ||
728 | set_switch_state(mixer, MIXER_SPDIFI_C_S, 1); | ||
729 | 808 | ||
730 | return 0; | 809 | return 0; |
731 | } | 810 | } |
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c index f42e7e1a1074..b259aa03a3a9 100644 --- a/sound/pci/ctxfi/xfi.c +++ b/sound/pci/ctxfi/xfi.c | |||
@@ -80,11 +80,11 @@ ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
80 | "are 48000 and 44100, Value 48000 is assumed.\n"); | 80 | "are 48000 and 44100, Value 48000 is assumed.\n"); |
81 | reference_rate = 48000; | 81 | reference_rate = 48000; |
82 | } | 82 | } |
83 | if ((multiple != 1) && (multiple != 2)) { | 83 | if ((multiple != 1) && (multiple != 2) && (multiple != 4)) { |
84 | printk(KERN_ERR "ctxfi: Invalid multiple value %u!!!\n", | 84 | printk(KERN_ERR "ctxfi: Invalid multiple value %u!!!\n", |
85 | multiple); | 85 | multiple); |
86 | printk(KERN_ERR "ctxfi: The valid values for multiple are " | 86 | printk(KERN_ERR "ctxfi: The valid values for multiple are " |
87 | "1 and 2, Value 2 is assumed.\n"); | 87 | "1, 2 and 4, Value 2 is assumed.\n"); |
88 | multiple = 2; | 88 | multiple = 2; |
89 | } | 89 | } |
90 | err = ct_atc_create(card, pci, reference_rate, multiple, | 90 | err = ct_atc_create(card, pci, reference_rate, multiple, |
@@ -143,7 +143,7 @@ static int ct_card_resume(struct pci_dev *pci) | |||
143 | #endif | 143 | #endif |
144 | 144 | ||
145 | static struct pci_driver ct_driver = { | 145 | static struct pci_driver ct_driver = { |
146 | .name = "SB-XFi", | 146 | .name = KBUILD_MODNAME, |
147 | .id_table = ct_pci_dev_ids, | 147 | .id_table = ct_pci_dev_ids, |
148 | .probe = ct_card_probe, | 148 | .probe = ct_card_probe, |
149 | .remove = __devexit_p(ct_card_remove), | 149 | .remove = __devexit_p(ct_card_remove), |
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 20763dd03fa0..d7306980d0f1 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
@@ -1995,7 +1995,7 @@ static __devinit int snd_echo_create(struct snd_card *card, | |||
1995 | ioremap_nocache(chip->dsp_registers_phys, sz); | 1995 | ioremap_nocache(chip->dsp_registers_phys, sz); |
1996 | 1996 | ||
1997 | if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED, | 1997 | if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED, |
1998 | ECHOCARD_NAME, chip)) { | 1998 | KBUILD_MODNAME, chip)) { |
1999 | snd_echo_free(chip); | 1999 | snd_echo_free(chip); |
2000 | snd_printk(KERN_ERR "cannot grab irq\n"); | 2000 | snd_printk(KERN_ERR "cannot grab irq\n"); |
2001 | return -EBUSY; | 2001 | return -EBUSY; |
@@ -2286,7 +2286,7 @@ static int snd_echo_resume(struct pci_dev *pci) | |||
2286 | kfree(commpage_bak); | 2286 | kfree(commpage_bak); |
2287 | 2287 | ||
2288 | if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED, | 2288 | if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED, |
2289 | ECHOCARD_NAME, chip)) { | 2289 | KBUILD_MODNAME, chip)) { |
2290 | snd_echo_free(chip); | 2290 | snd_echo_free(chip); |
2291 | snd_printk(KERN_ERR "cannot grab irq\n"); | 2291 | snd_printk(KERN_ERR "cannot grab irq\n"); |
2292 | return -EBUSY; | 2292 | return -EBUSY; |
@@ -2327,7 +2327,7 @@ static void __devexit snd_echo_remove(struct pci_dev *pci) | |||
2327 | 2327 | ||
2328 | /* pci_driver definition */ | 2328 | /* pci_driver definition */ |
2329 | static struct pci_driver driver = { | 2329 | static struct pci_driver driver = { |
2330 | .name = "Echoaudio " ECHOCARD_NAME, | 2330 | .name = KBUILD_MODNAME, |
2331 | .id_table = snd_echo_ids, | 2331 | .id_table = snd_echo_ids, |
2332 | .probe = snd_echo_probe, | 2332 | .probe = snd_echo_probe, |
2333 | .remove = __devexit_p(snd_echo_remove), | 2333 | .remove = __devexit_p(snd_echo_remove), |
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index aff8387c45cf..a9c45d2cdb13 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -264,7 +264,7 @@ static int snd_emu10k1_resume(struct pci_dev *pci) | |||
264 | #endif | 264 | #endif |
265 | 265 | ||
266 | static struct pci_driver driver = { | 266 | static struct pci_driver driver = { |
267 | .name = "EMU10K1_Audigy", | 267 | .name = KBUILD_MODNAME, |
268 | .id_table = snd_emu10k1_ids, | 268 | .id_table = snd_emu10k1_ids, |
269 | .probe = snd_card_emu10k1_probe, | 269 | .probe = snd_card_emu10k1_probe, |
270 | .remove = __devexit_p(snd_card_emu10k1_remove), | 270 | .remove = __devexit_p(snd_card_emu10k1_remove), |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 15f0161ce4a2..fcd4935766b2 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -1912,7 +1912,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1912 | 1912 | ||
1913 | /* irq handler must be registered after I/O ports are activated */ | 1913 | /* irq handler must be registered after I/O ports are activated */ |
1914 | if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_SHARED, | 1914 | if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_SHARED, |
1915 | "EMU10K1", emu)) { | 1915 | KBUILD_MODNAME, emu)) { |
1916 | err = -EBUSY; | 1916 | err = -EBUSY; |
1917 | goto error; | 1917 | goto error; |
1918 | } | 1918 | } |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 0c701e4ec8a5..d4fde1b4b093 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -925,7 +925,7 @@ static int __devinit snd_emu10k1x_create(struct snd_card *card, | |||
925 | } | 925 | } |
926 | 926 | ||
927 | if (request_irq(pci->irq, snd_emu10k1x_interrupt, | 927 | if (request_irq(pci->irq, snd_emu10k1x_interrupt, |
928 | IRQF_SHARED, "EMU10K1X", chip)) { | 928 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
929 | snd_printk(KERN_ERR "emu10k1x: cannot grab irq %d\n", pci->irq); | 929 | snd_printk(KERN_ERR "emu10k1x: cannot grab irq %d\n", pci->irq); |
930 | snd_emu10k1x_free(chip); | 930 | snd_emu10k1x_free(chip); |
931 | return -EBUSY; | 931 | return -EBUSY; |
@@ -1613,7 +1613,7 @@ MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids); | |||
1613 | 1613 | ||
1614 | // pci_driver definition | 1614 | // pci_driver definition |
1615 | static struct pci_driver driver = { | 1615 | static struct pci_driver driver = { |
1616 | .name = "EMU10K1X", | 1616 | .name = KBUILD_MODNAME, |
1617 | .id_table = snd_emu10k1x_ids, | 1617 | .id_table = snd_emu10k1x_ids, |
1618 | .probe = snd_emu10k1x_probe, | 1618 | .probe = snd_emu10k1x_probe, |
1619 | .remove = __devexit_p(snd_emu10k1x_remove), | 1619 | .remove = __devexit_p(snd_emu10k1x_remove), |
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 863eafea691f..f02e2f8d7122 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -2120,7 +2120,7 @@ static int __devinit snd_ensoniq_create(struct snd_card *card, | |||
2120 | } | 2120 | } |
2121 | ensoniq->port = pci_resource_start(pci, 0); | 2121 | ensoniq->port = pci_resource_start(pci, 0); |
2122 | if (request_irq(pci->irq, snd_audiopci_interrupt, IRQF_SHARED, | 2122 | if (request_irq(pci->irq, snd_audiopci_interrupt, IRQF_SHARED, |
2123 | "Ensoniq AudioPCI", ensoniq)) { | 2123 | KBUILD_MODNAME, ensoniq)) { |
2124 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 2124 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
2125 | snd_ensoniq_free(ensoniq); | 2125 | snd_ensoniq_free(ensoniq); |
2126 | return -EBUSY; | 2126 | return -EBUSY; |
@@ -2489,7 +2489,7 @@ static void __devexit snd_audiopci_remove(struct pci_dev *pci) | |||
2489 | } | 2489 | } |
2490 | 2490 | ||
2491 | static struct pci_driver driver = { | 2491 | static struct pci_driver driver = { |
2492 | .name = DRIVER_NAME, | 2492 | .name = KBUILD_MODNAME, |
2493 | .id_table = snd_audiopci_ids, | 2493 | .id_table = snd_audiopci_ids, |
2494 | .probe = snd_audiopci_probe, | 2494 | .probe = snd_audiopci_probe, |
2495 | .remove = __devexit_p(snd_audiopci_remove), | 2495 | .remove = __devexit_p(snd_audiopci_remove), |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 553b75217259..26a5a2f25d4b 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -1514,7 +1514,7 @@ static int es1938_resume(struct pci_dev *pci) | |||
1514 | } | 1514 | } |
1515 | 1515 | ||
1516 | if (request_irq(pci->irq, snd_es1938_interrupt, | 1516 | if (request_irq(pci->irq, snd_es1938_interrupt, |
1517 | IRQF_SHARED, "ES1938", chip)) { | 1517 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
1518 | printk(KERN_ERR "es1938: unable to grab IRQ %d, " | 1518 | printk(KERN_ERR "es1938: unable to grab IRQ %d, " |
1519 | "disabling device\n", pci->irq); | 1519 | "disabling device\n", pci->irq); |
1520 | snd_card_disconnect(card); | 1520 | snd_card_disconnect(card); |
@@ -1636,7 +1636,7 @@ static int __devinit snd_es1938_create(struct snd_card *card, | |||
1636 | chip->mpu_port = pci_resource_start(pci, 3); | 1636 | chip->mpu_port = pci_resource_start(pci, 3); |
1637 | chip->game_port = pci_resource_start(pci, 4); | 1637 | chip->game_port = pci_resource_start(pci, 4); |
1638 | if (request_irq(pci->irq, snd_es1938_interrupt, IRQF_SHARED, | 1638 | if (request_irq(pci->irq, snd_es1938_interrupt, IRQF_SHARED, |
1639 | "ES1938", chip)) { | 1639 | KBUILD_MODNAME, chip)) { |
1640 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1640 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1641 | snd_es1938_free(chip); | 1641 | snd_es1938_free(chip); |
1642 | return -EBUSY; | 1642 | return -EBUSY; |
@@ -1882,7 +1882,7 @@ static void __devexit snd_es1938_remove(struct pci_dev *pci) | |||
1882 | } | 1882 | } |
1883 | 1883 | ||
1884 | static struct pci_driver driver = { | 1884 | static struct pci_driver driver = { |
1885 | .name = "ESS ES1938 (Solo-1)", | 1885 | .name = KBUILD_MODNAME, |
1886 | .id_table = snd_es1938_ids, | 1886 | .id_table = snd_es1938_ids, |
1887 | .probe = snd_es1938_probe, | 1887 | .probe = snd_es1938_probe, |
1888 | .remove = __devexit_p(snd_es1938_remove), | 1888 | .remove = __devexit_p(snd_es1938_remove), |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index ab0a6156a704..99ea9320c6b5 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -554,9 +554,8 @@ struct es1968 { | |||
554 | #else | 554 | #else |
555 | struct snd_kcontrol *master_switch; /* for h/w volume control */ | 555 | struct snd_kcontrol *master_switch; /* for h/w volume control */ |
556 | struct snd_kcontrol *master_volume; | 556 | struct snd_kcontrol *master_volume; |
557 | spinlock_t ac97_lock; | ||
558 | struct tasklet_struct hwvol_tq; | ||
559 | #endif | 557 | #endif |
558 | struct work_struct hwvol_work; | ||
560 | 559 | ||
561 | #ifdef CONFIG_SND_ES1968_RADIO | 560 | #ifdef CONFIG_SND_ES1968_RADIO |
562 | struct snd_tea575x tea; | 561 | struct snd_tea575x tea; |
@@ -646,38 +645,23 @@ static int snd_es1968_ac97_wait_poll(struct es1968 *chip) | |||
646 | static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) | 645 | static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) |
647 | { | 646 | { |
648 | struct es1968 *chip = ac97->private_data; | 647 | struct es1968 *chip = ac97->private_data; |
649 | #ifndef CONFIG_SND_ES1968_INPUT | ||
650 | unsigned long flags; | ||
651 | #endif | ||
652 | 648 | ||
653 | snd_es1968_ac97_wait(chip); | 649 | snd_es1968_ac97_wait(chip); |
654 | 650 | ||
655 | /* Write the bus */ | 651 | /* Write the bus */ |
656 | #ifndef CONFIG_SND_ES1968_INPUT | ||
657 | spin_lock_irqsave(&chip->ac97_lock, flags); | ||
658 | #endif | ||
659 | outw(val, chip->io_port + ESM_AC97_DATA); | 652 | outw(val, chip->io_port + ESM_AC97_DATA); |
660 | /*msleep(1);*/ | 653 | /*msleep(1);*/ |
661 | outb(reg, chip->io_port + ESM_AC97_INDEX); | 654 | outb(reg, chip->io_port + ESM_AC97_INDEX); |
662 | /*msleep(1);*/ | 655 | /*msleep(1);*/ |
663 | #ifndef CONFIG_SND_ES1968_INPUT | ||
664 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | ||
665 | #endif | ||
666 | } | 656 | } |
667 | 657 | ||
668 | static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | 658 | static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg) |
669 | { | 659 | { |
670 | u16 data = 0; | 660 | u16 data = 0; |
671 | struct es1968 *chip = ac97->private_data; | 661 | struct es1968 *chip = ac97->private_data; |
672 | #ifndef CONFIG_SND_ES1968_INPUT | ||
673 | unsigned long flags; | ||
674 | #endif | ||
675 | 662 | ||
676 | snd_es1968_ac97_wait(chip); | 663 | snd_es1968_ac97_wait(chip); |
677 | 664 | ||
678 | #ifndef CONFIG_SND_ES1968_INPUT | ||
679 | spin_lock_irqsave(&chip->ac97_lock, flags); | ||
680 | #endif | ||
681 | outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX); | 665 | outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX); |
682 | /*msleep(1);*/ | 666 | /*msleep(1);*/ |
683 | 667 | ||
@@ -685,9 +669,6 @@ static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short | |||
685 | data = inw(chip->io_port + ESM_AC97_DATA); | 669 | data = inw(chip->io_port + ESM_AC97_DATA); |
686 | /*msleep(1);*/ | 670 | /*msleep(1);*/ |
687 | } | 671 | } |
688 | #ifndef CONFIG_SND_ES1968_INPUT | ||
689 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | ||
690 | #endif | ||
691 | 672 | ||
692 | return data; | 673 | return data; |
693 | } | 674 | } |
@@ -1904,13 +1885,10 @@ static void snd_es1968_update_pcm(struct es1968 *chip, struct esschan *es) | |||
1904 | (without wrap around) in response to volume button presses and then | 1885 | (without wrap around) in response to volume button presses and then |
1905 | generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7 | 1886 | generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7 |
1906 | of a byte wide register. The meaning of bits 0 and 4 is unknown. */ | 1887 | of a byte wide register. The meaning of bits 0 and 4 is unknown. */ |
1907 | static void es1968_update_hw_volume(unsigned long private_data) | 1888 | static void es1968_update_hw_volume(struct work_struct *work) |
1908 | { | 1889 | { |
1909 | struct es1968 *chip = (struct es1968 *) private_data; | 1890 | struct es1968 *chip = container_of(work, struct es1968, hwvol_work); |
1910 | int x, val; | 1891 | int x, val; |
1911 | #ifndef CONFIG_SND_ES1968_INPUT | ||
1912 | unsigned long flags; | ||
1913 | #endif | ||
1914 | 1892 | ||
1915 | /* Figure out which volume control button was pushed, | 1893 | /* Figure out which volume control button was pushed, |
1916 | based on differences from the default register | 1894 | based on differences from the default register |
@@ -1929,18 +1907,11 @@ static void es1968_update_hw_volume(unsigned long private_data) | |||
1929 | if (! chip->master_switch || ! chip->master_volume) | 1907 | if (! chip->master_switch || ! chip->master_volume) |
1930 | return; | 1908 | return; |
1931 | 1909 | ||
1932 | /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */ | 1910 | val = snd_ac97_read(chip->ac97, AC97_MASTER); |
1933 | spin_lock_irqsave(&chip->ac97_lock, flags); | ||
1934 | val = chip->ac97->regs[AC97_MASTER]; | ||
1935 | switch (x) { | 1911 | switch (x) { |
1936 | case 0x88: | 1912 | case 0x88: |
1937 | /* mute */ | 1913 | /* mute */ |
1938 | val ^= 0x8000; | 1914 | val ^= 0x8000; |
1939 | chip->ac97->regs[AC97_MASTER] = val; | ||
1940 | outw(val, chip->io_port + ESM_AC97_DATA); | ||
1941 | outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); | ||
1942 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1943 | &chip->master_switch->id); | ||
1944 | break; | 1915 | break; |
1945 | case 0xaa: | 1916 | case 0xaa: |
1946 | /* volume up */ | 1917 | /* volume up */ |
@@ -1948,11 +1919,6 @@ static void es1968_update_hw_volume(unsigned long private_data) | |||
1948 | val--; | 1919 | val--; |
1949 | if ((val & 0x7f00) > 0) | 1920 | if ((val & 0x7f00) > 0) |
1950 | val -= 0x0100; | 1921 | val -= 0x0100; |
1951 | chip->ac97->regs[AC97_MASTER] = val; | ||
1952 | outw(val, chip->io_port + ESM_AC97_DATA); | ||
1953 | outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); | ||
1954 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1955 | &chip->master_volume->id); | ||
1956 | break; | 1922 | break; |
1957 | case 0x66: | 1923 | case 0x66: |
1958 | /* volume down */ | 1924 | /* volume down */ |
@@ -1960,14 +1926,11 @@ static void es1968_update_hw_volume(unsigned long private_data) | |||
1960 | val++; | 1926 | val++; |
1961 | if ((val & 0x7f00) < 0x1f00) | 1927 | if ((val & 0x7f00) < 0x1f00) |
1962 | val += 0x0100; | 1928 | val += 0x0100; |
1963 | chip->ac97->regs[AC97_MASTER] = val; | ||
1964 | outw(val, chip->io_port + ESM_AC97_DATA); | ||
1965 | outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); | ||
1966 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1967 | &chip->master_volume->id); | ||
1968 | break; | 1929 | break; |
1969 | } | 1930 | } |
1970 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | 1931 | if (snd_ac97_update(chip->ac97, AC97_MASTER, val)) |
1932 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1933 | &chip->master_volume->id); | ||
1971 | #else | 1934 | #else |
1972 | if (!chip->input_dev) | 1935 | if (!chip->input_dev) |
1973 | return; | 1936 | return; |
@@ -2013,11 +1976,7 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id) | |||
2013 | outw(inw(chip->io_port + 4) & 1, chip->io_port + 4); | 1976 | outw(inw(chip->io_port + 4) & 1, chip->io_port + 4); |
2014 | 1977 | ||
2015 | if (event & ESM_HWVOL_IRQ) | 1978 | if (event & ESM_HWVOL_IRQ) |
2016 | #ifdef CONFIG_SND_ES1968_INPUT | 1979 | schedule_work(&chip->hwvol_work); |
2017 | es1968_update_hw_volume((unsigned long)chip); | ||
2018 | #else | ||
2019 | tasklet_schedule(&chip->hwvol_tq); /* we'll do this later */ | ||
2020 | #endif | ||
2021 | 1980 | ||
2022 | /* else ack 'em all, i imagine */ | 1981 | /* else ack 'em all, i imagine */ |
2023 | outb(0xFF, chip->io_port + 0x1A); | 1982 | outb(0xFF, chip->io_port + 0x1A); |
@@ -2426,6 +2385,7 @@ static int es1968_suspend(struct pci_dev *pci, pm_message_t state) | |||
2426 | return 0; | 2385 | return 0; |
2427 | 2386 | ||
2428 | chip->in_suspend = 1; | 2387 | chip->in_suspend = 1; |
2388 | cancel_work_sync(&chip->hwvol_work); | ||
2429 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 2389 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
2430 | snd_pcm_suspend_all(chip->pcm); | 2390 | snd_pcm_suspend_all(chip->pcm); |
2431 | snd_ac97_suspend(chip->ac97); | 2391 | snd_ac97_suspend(chip->ac97); |
@@ -2638,6 +2598,7 @@ static struct snd_tea575x_ops snd_es1968_tea_ops = { | |||
2638 | 2598 | ||
2639 | static int snd_es1968_free(struct es1968 *chip) | 2599 | static int snd_es1968_free(struct es1968 *chip) |
2640 | { | 2600 | { |
2601 | cancel_work_sync(&chip->hwvol_work); | ||
2641 | #ifdef CONFIG_SND_ES1968_INPUT | 2602 | #ifdef CONFIG_SND_ES1968_INPUT |
2642 | if (chip->input_dev) | 2603 | if (chip->input_dev) |
2643 | input_unregister_device(chip->input_dev); | 2604 | input_unregister_device(chip->input_dev); |
@@ -2728,10 +2689,7 @@ static int __devinit snd_es1968_create(struct snd_card *card, | |||
2728 | INIT_LIST_HEAD(&chip->buf_list); | 2689 | INIT_LIST_HEAD(&chip->buf_list); |
2729 | INIT_LIST_HEAD(&chip->substream_list); | 2690 | INIT_LIST_HEAD(&chip->substream_list); |
2730 | mutex_init(&chip->memory_mutex); | 2691 | mutex_init(&chip->memory_mutex); |
2731 | #ifndef CONFIG_SND_ES1968_INPUT | 2692 | INIT_WORK(&chip->hwvol_work, es1968_update_hw_volume); |
2732 | spin_lock_init(&chip->ac97_lock); | ||
2733 | tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip); | ||
2734 | #endif | ||
2735 | chip->card = card; | 2693 | chip->card = card; |
2736 | chip->pci = pci; | 2694 | chip->pci = pci; |
2737 | chip->irq = -1; | 2695 | chip->irq = -1; |
@@ -2746,7 +2704,7 @@ static int __devinit snd_es1968_create(struct snd_card *card, | |||
2746 | } | 2704 | } |
2747 | chip->io_port = pci_resource_start(pci, 0); | 2705 | chip->io_port = pci_resource_start(pci, 0); |
2748 | if (request_irq(pci->irq, snd_es1968_interrupt, IRQF_SHARED, | 2706 | if (request_irq(pci->irq, snd_es1968_interrupt, IRQF_SHARED, |
2749 | "ESS Maestro", chip)) { | 2707 | KBUILD_MODNAME, chip)) { |
2750 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 2708 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
2751 | snd_es1968_free(chip); | 2709 | snd_es1968_free(chip); |
2752 | return -EBUSY; | 2710 | return -EBUSY; |
@@ -2925,7 +2883,7 @@ static void __devexit snd_es1968_remove(struct pci_dev *pci) | |||
2925 | } | 2883 | } |
2926 | 2884 | ||
2927 | static struct pci_driver driver = { | 2885 | static struct pci_driver driver = { |
2928 | .name = "ES1968 (ESS Maestro)", | 2886 | .name = KBUILD_MODNAME, |
2929 | .id_table = snd_es1968_ids, | 2887 | .id_table = snd_es1968_ids, |
2930 | .probe = snd_es1968_probe, | 2888 | .probe = snd_es1968_probe, |
2931 | .remove = __devexit_p(snd_es1968_remove), | 2889 | .remove = __devexit_p(snd_es1968_remove), |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index a7ec7030cf87..f9123f09e83e 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -1199,7 +1199,7 @@ static int __devinit snd_fm801_create(struct snd_card *card, | |||
1199 | chip->port = pci_resource_start(pci, 0); | 1199 | chip->port = pci_resource_start(pci, 0); |
1200 | if ((tea575x_tuner & TUNER_ONLY) == 0) { | 1200 | if ((tea575x_tuner & TUNER_ONLY) == 0) { |
1201 | if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_SHARED, | 1201 | if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_SHARED, |
1202 | "FM801", chip)) { | 1202 | KBUILD_MODNAME, chip)) { |
1203 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq); | 1203 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq); |
1204 | snd_fm801_free(chip); | 1204 | snd_fm801_free(chip); |
1205 | return -EBUSY; | 1205 | return -EBUSY; |
@@ -1394,7 +1394,7 @@ static int snd_fm801_resume(struct pci_dev *pci) | |||
1394 | #endif | 1394 | #endif |
1395 | 1395 | ||
1396 | static struct pci_driver driver = { | 1396 | static struct pci_driver driver = { |
1397 | .name = "FM801", | 1397 | .name = KBUILD_MODNAME, |
1398 | .id_table = snd_fm801_ids, | 1398 | .id_table = snd_fm801_ids, |
1399 | .probe = snd_card_fm801_probe, | 1399 | .probe = snd_card_fm801_probe, |
1400 | .remove = __devexit_p(snd_card_fm801_remove), | 1400 | .remove = __devexit_p(snd_card_fm801_remove), |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 25b90eec915a..9c27a3a4c4d5 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -5128,17 +5128,15 @@ void *snd_array_new(struct snd_array *array) | |||
5128 | { | 5128 | { |
5129 | if (array->used >= array->alloced) { | 5129 | if (array->used >= array->alloced) { |
5130 | int num = array->alloced + array->alloc_align; | 5130 | int num = array->alloced + array->alloc_align; |
5131 | int size = (num + 1) * array->elem_size; | ||
5132 | int oldsize = array->alloced * array->elem_size; | ||
5131 | void *nlist; | 5133 | void *nlist; |
5132 | if (snd_BUG_ON(num >= 4096)) | 5134 | if (snd_BUG_ON(num >= 4096)) |
5133 | return NULL; | 5135 | return NULL; |
5134 | nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL); | 5136 | nlist = krealloc(array->list, size, GFP_KERNEL); |
5135 | if (!nlist) | 5137 | if (!nlist) |
5136 | return NULL; | 5138 | return NULL; |
5137 | if (array->list) { | 5139 | memset(nlist + oldsize, 0, size - oldsize); |
5138 | memcpy(nlist, array->list, | ||
5139 | array->elem_size * array->alloced); | ||
5140 | kfree(array->list); | ||
5141 | } | ||
5142 | array->list = nlist; | 5140 | array->list = nlist; |
5143 | array->alloced = num; | 5141 | array->alloced = num; |
5144 | } | 5142 | } |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 5ce9531cba67..be6982289c0d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -2169,7 +2169,7 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) | |||
2169 | { | 2169 | { |
2170 | if (request_irq(chip->pci->irq, azx_interrupt, | 2170 | if (request_irq(chip->pci->irq, azx_interrupt, |
2171 | chip->msi ? 0 : IRQF_SHARED, | 2171 | chip->msi ? 0 : IRQF_SHARED, |
2172 | "hda_intel", chip)) { | 2172 | KBUILD_MODNAME, chip)) { |
2173 | printk(KERN_ERR "hda-intel: unable to grab IRQ %d, " | 2173 | printk(KERN_ERR "hda-intel: unable to grab IRQ %d, " |
2174 | "disabling device\n", chip->pci->irq); | 2174 | "disabling device\n", chip->pci->irq); |
2175 | if (do_disconnect) | 2175 | if (do_disconnect) |
@@ -2936,7 +2936,7 @@ MODULE_DEVICE_TABLE(pci, azx_ids); | |||
2936 | 2936 | ||
2937 | /* pci_driver definition */ | 2937 | /* pci_driver definition */ |
2938 | static struct pci_driver driver = { | 2938 | static struct pci_driver driver = { |
2939 | .name = "HDA Intel", | 2939 | .name = KBUILD_MODNAME, |
2940 | .id_table = azx_ids, | 2940 | .id_table = azx_ids, |
2941 | .probe = azx_probe, | 2941 | .probe = azx_probe, |
2942 | .remove = __devexit_p(azx_remove), | 2942 | .remove = __devexit_p(azx_remove), |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index f4594d76b6ea..be06fb3e45a1 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -2607,7 +2607,7 @@ static int __devinit snd_ice1712_create(struct snd_card *card, | |||
2607 | ice->profi_port = pci_resource_start(pci, 3); | 2607 | ice->profi_port = pci_resource_start(pci, 3); |
2608 | 2608 | ||
2609 | if (request_irq(pci->irq, snd_ice1712_interrupt, IRQF_SHARED, | 2609 | if (request_irq(pci->irq, snd_ice1712_interrupt, IRQF_SHARED, |
2610 | "ICE1712", ice)) { | 2610 | KBUILD_MODNAME, ice)) { |
2611 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 2611 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
2612 | snd_ice1712_free(ice); | 2612 | snd_ice1712_free(ice); |
2613 | return -EIO; | 2613 | return -EIO; |
@@ -2802,7 +2802,7 @@ static void __devexit snd_ice1712_remove(struct pci_dev *pci) | |||
2802 | } | 2802 | } |
2803 | 2803 | ||
2804 | static struct pci_driver driver = { | 2804 | static struct pci_driver driver = { |
2805 | .name = "ICE1712", | 2805 | .name = KBUILD_MODNAME, |
2806 | .id_table = snd_ice1712_ids, | 2806 | .id_table = snd_ice1712_ids, |
2807 | .probe = snd_ice1712_probe, | 2807 | .probe = snd_ice1712_probe, |
2808 | .remove = __devexit_p(snd_ice1712_remove), | 2808 | .remove = __devexit_p(snd_ice1712_remove), |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index c1498fa5545f..c2b7f8bc41e4 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -2509,7 +2509,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card, | |||
2509 | ice->profi_port = pci_resource_start(pci, 1); | 2509 | ice->profi_port = pci_resource_start(pci, 1); |
2510 | 2510 | ||
2511 | if (request_irq(pci->irq, snd_vt1724_interrupt, | 2511 | if (request_irq(pci->irq, snd_vt1724_interrupt, |
2512 | IRQF_SHARED, "ICE1724", ice)) { | 2512 | IRQF_SHARED, KBUILD_MODNAME, ice)) { |
2513 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 2513 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
2514 | snd_vt1724_free(ice); | 2514 | snd_vt1724_free(ice); |
2515 | return -EIO; | 2515 | return -EIO; |
@@ -2802,7 +2802,7 @@ static int snd_vt1724_resume(struct pci_dev *pci) | |||
2802 | #endif | 2802 | #endif |
2803 | 2803 | ||
2804 | static struct pci_driver driver = { | 2804 | static struct pci_driver driver = { |
2805 | .name = "ICE1724", | 2805 | .name = KBUILD_MODNAME, |
2806 | .id_table = snd_vt1724_ids, | 2806 | .id_table = snd_vt1724_ids, |
2807 | .probe = snd_vt1724_probe, | 2807 | .probe = snd_vt1724_probe, |
2808 | .remove = __devexit_p(snd_vt1724_remove), | 2808 | .remove = __devexit_p(snd_vt1724_remove), |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 6c896dbfd796..6a5b387b97fd 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -1884,6 +1884,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { | |||
1884 | }, | 1884 | }, |
1885 | { | 1885 | { |
1886 | .subvendor = 0x1028, | 1886 | .subvendor = 0x1028, |
1887 | .subdevice = 0x0189, | ||
1888 | .name = "Dell Inspiron 9300", | ||
1889 | .type = AC97_TUNE_HP_MUTE_LED | ||
1890 | }, | ||
1891 | { | ||
1892 | .subvendor = 0x1028, | ||
1887 | .subdevice = 0x0191, | 1893 | .subdevice = 0x0191, |
1888 | .name = "Dell Inspiron 8600", | 1894 | .name = "Dell Inspiron 8600", |
1889 | .type = AC97_TUNE_HP_ONLY | 1895 | .type = AC97_TUNE_HP_ONLY |
@@ -2647,7 +2653,7 @@ static int intel8x0_resume(struct pci_dev *pci) | |||
2647 | pci_set_master(pci); | 2653 | pci_set_master(pci); |
2648 | snd_intel8x0_chip_init(chip, 0); | 2654 | snd_intel8x0_chip_init(chip, 0); |
2649 | if (request_irq(pci->irq, snd_intel8x0_interrupt, | 2655 | if (request_irq(pci->irq, snd_intel8x0_interrupt, |
2650 | IRQF_SHARED, card->shortname, chip)) { | 2656 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
2651 | printk(KERN_ERR "intel8x0: unable to grab IRQ %d, " | 2657 | printk(KERN_ERR "intel8x0: unable to grab IRQ %d, " |
2652 | "disabling device\n", pci->irq); | 2658 | "disabling device\n", pci->irq); |
2653 | snd_card_disconnect(card); | 2659 | snd_card_disconnect(card); |
@@ -3106,7 +3112,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, | |||
3106 | 3112 | ||
3107 | /* request irq after initializaing int_sta_mask, etc */ | 3113 | /* request irq after initializaing int_sta_mask, etc */ |
3108 | if (request_irq(pci->irq, snd_intel8x0_interrupt, | 3114 | if (request_irq(pci->irq, snd_intel8x0_interrupt, |
3109 | IRQF_SHARED, card->shortname, chip)) { | 3115 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
3110 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 3116 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
3111 | snd_intel8x0_free(chip); | 3117 | snd_intel8x0_free(chip); |
3112 | return -EBUSY; | 3118 | return -EBUSY; |
@@ -3266,7 +3272,7 @@ static void __devexit snd_intel8x0_remove(struct pci_dev *pci) | |||
3266 | } | 3272 | } |
3267 | 3273 | ||
3268 | static struct pci_driver driver = { | 3274 | static struct pci_driver driver = { |
3269 | .name = "Intel ICH", | 3275 | .name = KBUILD_MODNAME, |
3270 | .id_table = snd_intel8x0_ids, | 3276 | .id_table = snd_intel8x0_ids, |
3271 | .probe = snd_intel8x0_probe, | 3277 | .probe = snd_intel8x0_probe, |
3272 | .remove = __devexit_p(snd_intel8x0_remove), | 3278 | .remove = __devexit_p(snd_intel8x0_remove), |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index f3353b49c785..7c161645d865 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -1047,7 +1047,7 @@ static int intel8x0m_resume(struct pci_dev *pci) | |||
1047 | } | 1047 | } |
1048 | pci_set_master(pci); | 1048 | pci_set_master(pci); |
1049 | if (request_irq(pci->irq, snd_intel8x0m_interrupt, | 1049 | if (request_irq(pci->irq, snd_intel8x0m_interrupt, |
1050 | IRQF_SHARED, card->shortname, chip)) { | 1050 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
1051 | printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, " | 1051 | printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, " |
1052 | "disabling device\n", pci->irq); | 1052 | "disabling device\n", pci->irq); |
1053 | snd_card_disconnect(card); | 1053 | snd_card_disconnect(card); |
@@ -1174,7 +1174,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card, | |||
1174 | 1174 | ||
1175 | port_inited: | 1175 | port_inited: |
1176 | if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED, | 1176 | if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED, |
1177 | card->shortname, chip)) { | 1177 | KBUILD_MODNAME, chip)) { |
1178 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1178 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1179 | snd_intel8x0m_free(chip); | 1179 | snd_intel8x0m_free(chip); |
1180 | return -EBUSY; | 1180 | return -EBUSY; |
@@ -1325,7 +1325,7 @@ static void __devexit snd_intel8x0m_remove(struct pci_dev *pci) | |||
1325 | } | 1325 | } |
1326 | 1326 | ||
1327 | static struct pci_driver driver = { | 1327 | static struct pci_driver driver = { |
1328 | .name = "Intel ICH Modem", | 1328 | .name = KBUILD_MODNAME, |
1329 | .id_table = snd_intel8x0m_ids, | 1329 | .id_table = snd_intel8x0m_ids, |
1330 | .probe = snd_intel8x0m_probe, | 1330 | .probe = snd_intel8x0m_probe, |
1331 | .remove = __devexit_p(snd_intel8x0m_remove), | 1331 | .remove = __devexit_p(snd_intel8x0m_remove), |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 6d795700be79..fc1d573cf306 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
@@ -2241,7 +2241,7 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev * | |||
2241 | 2241 | ||
2242 | err = request_irq(pci->irq, snd_korg1212_interrupt, | 2242 | err = request_irq(pci->irq, snd_korg1212_interrupt, |
2243 | IRQF_SHARED, | 2243 | IRQF_SHARED, |
2244 | "korg1212", korg1212); | 2244 | KBUILD_MODNAME, korg1212); |
2245 | 2245 | ||
2246 | if (err) { | 2246 | if (err) { |
2247 | snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq); | 2247 | snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq); |
@@ -2477,7 +2477,7 @@ static void __devexit snd_korg1212_remove(struct pci_dev *pci) | |||
2477 | } | 2477 | } |
2478 | 2478 | ||
2479 | static struct pci_driver driver = { | 2479 | static struct pci_driver driver = { |
2480 | .name = "korg1212", | 2480 | .name = KBUILD_MODNAME, |
2481 | .id_table = snd_korg1212_ids, | 2481 | .id_table = snd_korg1212_ids, |
2482 | .probe = snd_korg1212_probe, | 2482 | .probe = snd_korg1212_probe, |
2483 | .remove = __devexit_p(snd_korg1212_remove), | 2483 | .remove = __devexit_p(snd_korg1212_remove), |
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c index 2692e5ae5f2d..3e92e5b5ec3d 100644 --- a/sound/pci/lola/lola.c +++ b/sound/pci/lola/lola.c | |||
@@ -648,7 +648,7 @@ static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci, | |||
648 | goto errout; | 648 | goto errout; |
649 | 649 | ||
650 | if (request_irq(pci->irq, lola_interrupt, IRQF_SHARED, | 650 | if (request_irq(pci->irq, lola_interrupt, IRQF_SHARED, |
651 | DRVNAME, chip)) { | 651 | KBUILD_MODNAME, chip)) { |
652 | printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); | 652 | printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); |
653 | err = -EBUSY; | 653 | err = -EBUSY; |
654 | goto errout; | 654 | goto errout; |
@@ -771,7 +771,7 @@ MODULE_DEVICE_TABLE(pci, lola_ids); | |||
771 | 771 | ||
772 | /* pci_driver definition */ | 772 | /* pci_driver definition */ |
773 | static struct pci_driver driver = { | 773 | static struct pci_driver driver = { |
774 | .name = DRVNAME, | 774 | .name = KBUILD_MODNAME, |
775 | .id_table = lola_ids, | 775 | .id_table = lola_ids, |
776 | .probe = lola_probe, | 776 | .probe = lola_probe, |
777 | .remove = __devexit_p(lola_remove), | 777 | .remove = __devexit_p(lola_remove), |
diff --git a/sound/pci/lola/lola.h b/sound/pci/lola/lola.h index d5708e29b16d..f0b100059efd 100644 --- a/sound/pci/lola/lola.h +++ b/sound/pci/lola/lola.h | |||
@@ -480,7 +480,7 @@ struct lola { | |||
480 | 480 | ||
481 | /* count values in the Vendor Specific Mixer Widget's Audio Widget Capabilities */ | 481 | /* count values in the Vendor Specific Mixer Widget's Audio Widget Capabilities */ |
482 | #define LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(res) ((res >> 2) & 0x1f) | 482 | #define LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(res) ((res >> 2) & 0x1f) |
483 | #define LOLA_MIXER_DEST_REC_OUTPUT_SEPATATION(res) ((res >> 7) & 0x1f) | 483 | #define LOLA_MIXER_DEST_REC_OUTPUT_SEPARATION(res) ((res >> 7) & 0x1f) |
484 | 484 | ||
485 | int lola_codec_write(struct lola *chip, unsigned int nid, unsigned int verb, | 485 | int lola_codec_write(struct lola *chip, unsigned int nid, unsigned int verb, |
486 | unsigned int data, unsigned int extdata); | 486 | unsigned int data, unsigned int extdata); |
diff --git a/sound/pci/lola/lola_mixer.c b/sound/pci/lola/lola_mixer.c index 5d518f1a712c..6b8d64812951 100644 --- a/sound/pci/lola/lola_mixer.c +++ b/sound/pci/lola/lola_mixer.c | |||
@@ -144,40 +144,61 @@ int __devinit lola_init_mixer_widget(struct lola *chip, int nid) | |||
144 | chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams; | 144 | chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams; |
145 | chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins; | 145 | chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins; |
146 | 146 | ||
147 | /* mixer matrix can have unused areas between PhysIn and | 147 | /* mixer matrix may have unused areas between PhysIn and |
148 | * Play or Record and PhysOut zones | 148 | * Play or Record and PhysOut zones |
149 | */ | 149 | */ |
150 | chip->mixer.src_stream_out_ofs = chip->mixer.src_phys_ins + | 150 | chip->mixer.src_stream_out_ofs = chip->mixer.src_phys_ins + |
151 | LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val); | 151 | LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val); |
152 | chip->mixer.dest_phys_out_ofs = chip->mixer.dest_stream_ins + | 152 | chip->mixer.dest_phys_out_ofs = chip->mixer.dest_stream_ins + |
153 | LOLA_MIXER_DEST_REC_OUTPUT_SEPATATION(val); | 153 | LOLA_MIXER_DEST_REC_OUTPUT_SEPARATION(val); |
154 | 154 | ||
155 | /* example : MixerMatrix of LoLa881 | 155 | /* example : MixerMatrix of LoLa881 (LoLa16161 uses unused zones) |
156 | * 0-------8------16-------8------16 | 156 | * +-+ 0-------8------16-------8------16 |
157 | * | | | | | | 157 | * | | | | | | | |
158 | * | INPUT | | INPUT | | | 158 | * |s| | INPUT | | INPUT | | |
159 | * | -> |unused | -> |unused | | 159 | * | |->| -> |unused | -> |unused | |
160 | * | RECORD| | OUTPUT| | | 160 | * |r| |CAPTURE| | OUTPUT| | |
161 | * | | | | | | 161 | * | | | MIX | | MIX | | |
162 | * 8-------------------------------- | 162 | * |c| 8-------------------------------- |
163 | * | | | | | | 163 | * | | | | | | | |
164 | * | | | | | | 164 | * | | | | | | | |
165 | * |unused |unused |unused |unused | | 165 | * |g| |unused |unused |unused |unused | |
166 | * | | | | | | 166 | * | | | | | | | |
167 | * | | | | | | 167 | * |a| | | | | | |
168 | * 16------------------------------- | 168 | * | | 16------------------------------- |
169 | * | | | | | | 169 | * |i| | | | | | |
170 | * | PLAY | | PLAY | | | 170 | * | | | PLAYBK| | PLAYBK| | |
171 | * | -> |unused | -> |unused | | 171 | * |n|->| -> |unused | -> |unused | |
172 | * | RECORD| | OUTPUT| | | 172 | * | | |CAPTURE| | OUTPUT| | |
173 | * | | | | | | 173 | * | | | MIX | | MIX | | |
174 | * 8-------------------------------- | 174 | * |a| 8-------------------------------- |
175 | * | | | | | | 175 | * |r| | | | | | |
176 | * | | | | | | 176 | * |r| | | | | | |
177 | * |unused |unused |unused |unused | | 177 | * |a| |unused |unused |unused |unused | |
178 | * | | | | | | 178 | * |y| | | | | | |
179 | * | | | | | | 179 | * | | | | | | | |
180 | * 16------------------------------- | 180 | * +++ 16--|---------------|------------ |
181 | * +---V---------------V-----------+ | ||
182 | * | dest_mix_gain_enable array | | ||
183 | * +-------------------------------+ | ||
184 | */ | ||
185 | /* example : MixerMatrix of LoLa280 | ||
186 | * +-+ 0-------8-2 | ||
187 | * | | | | | | ||
188 | * |s| | INPUT | | INPUT | ||
189 | * |r|->| -> | | -> | ||
190 | * |c| |CAPTURE| | <- OUTPUT | ||
191 | * | | | MIX | | MIX | ||
192 | * |g| 8---------- | ||
193 | * |a| | | | | ||
194 | * |i| | PLAYBK| | PLAYBACK | ||
195 | * |n|->| -> | | -> | ||
196 | * | | |CAPTURE| | <- OUTPUT | ||
197 | * |a| | MIX | | MIX | ||
198 | * |r| 8---|----|- | ||
199 | * |r| +---V----V-------------------+ | ||
200 | * |a| | dest_mix_gain_enable array | | ||
201 | * |y| +----------------------------+ | ||
181 | */ | 202 | */ |
182 | if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT || | 203 | if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT || |
183 | chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) { | 204 | chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) { |
@@ -192,6 +213,9 @@ int __devinit lola_init_mixer_widget(struct lola *chip, int nid) | |||
192 | (((1U << chip->mixer.dest_phys_outs) - 1) | 213 | (((1U << chip->mixer.dest_phys_outs) - 1) |
193 | << chip->mixer.dest_phys_out_ofs); | 214 | << chip->mixer.dest_phys_out_ofs); |
194 | 215 | ||
216 | snd_printdd("Mixer src_mask=%x, dest_mask=%x\n", | ||
217 | chip->mixer.src_mask, chip->mixer.dest_mask); | ||
218 | |||
195 | return 0; | 219 | return 0; |
196 | } | 220 | } |
197 | 221 | ||
@@ -202,12 +226,19 @@ static int lola_mixer_set_src_gain(struct lola *chip, unsigned int id, | |||
202 | 226 | ||
203 | if (!(chip->mixer.src_mask & (1 << id))) | 227 | if (!(chip->mixer.src_mask & (1 << id))) |
204 | return -EINVAL; | 228 | return -EINVAL; |
205 | writew(gain, &chip->mixer.array->src_gain[id]); | ||
206 | oldval = val = readl(&chip->mixer.array->src_gain_enable); | 229 | oldval = val = readl(&chip->mixer.array->src_gain_enable); |
207 | if (on) | 230 | if (on) |
208 | val |= (1 << id); | 231 | val |= (1 << id); |
209 | else | 232 | else |
210 | val &= ~(1 << id); | 233 | val &= ~(1 << id); |
234 | /* test if values unchanged */ | ||
235 | if ((val == oldval) && | ||
236 | (gain == readw(&chip->mixer.array->src_gain[id]))) | ||
237 | return 0; | ||
238 | |||
239 | snd_printdd("lola_mixer_set_src_gain (id=%d, gain=%d) enable=%x\n", | ||
240 | id, gain, val); | ||
241 | writew(gain, &chip->mixer.array->src_gain[id]); | ||
211 | writel(val, &chip->mixer.array->src_gain_enable); | 242 | writel(val, &chip->mixer.array->src_gain_enable); |
212 | lola_codec_flush(chip); | 243 | lola_codec_flush(chip); |
213 | /* inform micro-controller about the new source gain */ | 244 | /* inform micro-controller about the new source gain */ |
@@ -269,6 +300,7 @@ static int lola_mixer_set_mapping_gain(struct lola *chip, | |||
269 | src, dest); | 300 | src, dest); |
270 | } | 301 | } |
271 | 302 | ||
303 | #if 0 /* not used */ | ||
272 | static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id, | 304 | static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id, |
273 | unsigned int mask, unsigned short *gains) | 305 | unsigned int mask, unsigned short *gains) |
274 | { | 306 | { |
@@ -289,6 +321,7 @@ static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id, | |||
289 | return lola_codec_write(chip, chip->mixer.nid, | 321 | return lola_codec_write(chip, chip->mixer.nid, |
290 | LOLA_VERB_SET_DESTINATION_GAIN, id, 0); | 322 | LOLA_VERB_SET_DESTINATION_GAIN, id, 0); |
291 | } | 323 | } |
324 | #endif /* not used */ | ||
292 | 325 | ||
293 | /* | 326 | /* |
294 | */ | 327 | */ |
@@ -376,6 +409,8 @@ static int set_analog_volume(struct lola *chip, int dir, | |||
376 | return 0; | 409 | return 0; |
377 | if (external_call) | 410 | if (external_call) |
378 | lola_codec_flush(chip); | 411 | lola_codec_flush(chip); |
412 | snd_printdd("set_analog_volume (dir=%d idx=%d, volume=%d)\n", | ||
413 | dir, idx, val); | ||
379 | err = lola_codec_write(chip, pin->nid, | 414 | err = lola_codec_write(chip, pin->nid, |
380 | LOLA_VERB_SET_AMP_GAIN_MUTE, val, 0); | 415 | LOLA_VERB_SET_AMP_GAIN_MUTE, val, 0); |
381 | if (err < 0) | 416 | if (err < 0) |
@@ -427,23 +462,40 @@ static int init_mixer_values(struct lola *chip) | |||
427 | { | 462 | { |
428 | int i; | 463 | int i; |
429 | 464 | ||
430 | /* all src on */ | 465 | /* all sample rate converters on */ |
431 | lola_set_src_config(chip, (1 << chip->pin[CAPT].num_pins) - 1, false); | 466 | lola_set_src_config(chip, (1 << chip->pin[CAPT].num_pins) - 1, false); |
432 | 467 | ||
433 | /* clear all matrix */ | 468 | /* clear all mixer matrix settings */ |
434 | memset_io(chip->mixer.array, 0, sizeof(*chip->mixer.array)); | 469 | memset_io(chip->mixer.array, 0, sizeof(*chip->mixer.array)); |
435 | /* set src gain to 0dB */ | 470 | /* inform firmware about all updated matrix columns - capture part */ |
471 | for (i = 0; i < chip->mixer.dest_stream_ins; i++) | ||
472 | lola_codec_write(chip, chip->mixer.nid, | ||
473 | LOLA_VERB_SET_DESTINATION_GAIN, | ||
474 | i, 0); | ||
475 | /* inform firmware about all updated matrix columns - output part */ | ||
476 | for (i = 0; i < chip->mixer.dest_phys_outs; i++) | ||
477 | lola_codec_write(chip, chip->mixer.nid, | ||
478 | LOLA_VERB_SET_DESTINATION_GAIN, | ||
479 | chip->mixer.dest_phys_out_ofs + i, 0); | ||
480 | |||
481 | /* set all digital input source (master) gains to 0dB */ | ||
436 | for (i = 0; i < chip->mixer.src_phys_ins; i++) | 482 | for (i = 0; i < chip->mixer.src_phys_ins; i++) |
437 | lola_mixer_set_src_gain(chip, i, 336, true); /* 0dB */ | 483 | lola_mixer_set_src_gain(chip, i, 336, true); /* 0dB */ |
484 | |||
485 | /* set all digital playback source (master) gains to 0dB */ | ||
438 | for (i = 0; i < chip->mixer.src_stream_outs; i++) | 486 | for (i = 0; i < chip->mixer.src_stream_outs; i++) |
439 | lola_mixer_set_src_gain(chip, | 487 | lola_mixer_set_src_gain(chip, |
440 | i + chip->mixer.src_stream_out_ofs, | 488 | i + chip->mixer.src_stream_out_ofs, |
441 | 336, true); /* 0dB */ | 489 | 336, true); /* 0dB */ |
442 | /* set 1:1 dest gain */ | 490 | /* set gain value 0dB diagonally in matrix - part INPUT -> CAPTURE */ |
443 | for (i = 0; i < chip->mixer.dest_stream_ins; i++) { | 491 | for (i = 0; i < chip->mixer.dest_stream_ins; i++) { |
444 | int src = i % chip->mixer.src_phys_ins; | 492 | int src = i % chip->mixer.src_phys_ins; |
445 | lola_mixer_set_mapping_gain(chip, src, i, 336, true); | 493 | lola_mixer_set_mapping_gain(chip, src, i, 336, true); |
446 | } | 494 | } |
495 | /* set gain value 0dB diagonally in matrix , part PLAYBACK -> OUTPUT | ||
496 | * (LoLa280 : playback channel 0,2,4,6 linked to output channel 0) | ||
497 | * (LoLa280 : playback channel 1,3,5,7 linked to output channel 1) | ||
498 | */ | ||
447 | for (i = 0; i < chip->mixer.src_stream_outs; i++) { | 499 | for (i = 0; i < chip->mixer.src_stream_outs; i++) { |
448 | int src = chip->mixer.src_stream_out_ofs + i; | 500 | int src = chip->mixer.src_stream_out_ofs + i; |
449 | int dst = chip->mixer.dest_phys_out_ofs + | 501 | int dst = chip->mixer.dest_phys_out_ofs + |
@@ -693,6 +745,7 @@ static int __devinit create_src_gain_mixer(struct lola *chip, | |||
693 | snd_ctl_new1(&lola_src_gain_mixer, chip)); | 745 | snd_ctl_new1(&lola_src_gain_mixer, chip)); |
694 | } | 746 | } |
695 | 747 | ||
748 | #if 0 /* not used */ | ||
696 | /* | 749 | /* |
697 | * destination gain (matrix-like) mixer | 750 | * destination gain (matrix-like) mixer |
698 | */ | 751 | */ |
@@ -781,6 +834,7 @@ static int __devinit create_dest_gain_mixer(struct lola *chip, | |||
781 | return snd_ctl_add(chip->card, | 834 | return snd_ctl_add(chip->card, |
782 | snd_ctl_new1(&lola_dest_gain_mixer, chip)); | 835 | snd_ctl_new1(&lola_dest_gain_mixer, chip)); |
783 | } | 836 | } |
837 | #endif /* not used */ | ||
784 | 838 | ||
785 | /* | 839 | /* |
786 | */ | 840 | */ |
@@ -798,14 +852,16 @@ int __devinit lola_create_mixer(struct lola *chip) | |||
798 | if (err < 0) | 852 | if (err < 0) |
799 | return err; | 853 | return err; |
800 | err = create_src_gain_mixer(chip, chip->mixer.src_phys_ins, 0, | 854 | err = create_src_gain_mixer(chip, chip->mixer.src_phys_ins, 0, |
801 | "Line Source Gain Volume"); | 855 | "Digital Capture Volume"); |
802 | if (err < 0) | 856 | if (err < 0) |
803 | return err; | 857 | return err; |
804 | err = create_src_gain_mixer(chip, chip->mixer.src_stream_outs, | 858 | err = create_src_gain_mixer(chip, chip->mixer.src_stream_outs, |
805 | chip->mixer.src_stream_out_ofs, | 859 | chip->mixer.src_stream_out_ofs, |
806 | "Stream Source Gain Volume"); | 860 | "Digital Playback Volume"); |
807 | if (err < 0) | 861 | if (err < 0) |
808 | return err; | 862 | return err; |
863 | #if 0 | ||
864 | /* FIXME: buggy mixer matrix handling */ | ||
809 | err = create_dest_gain_mixer(chip, | 865 | err = create_dest_gain_mixer(chip, |
810 | chip->mixer.src_phys_ins, 0, | 866 | chip->mixer.src_phys_ins, 0, |
811 | chip->mixer.dest_stream_ins, 0, | 867 | chip->mixer.dest_stream_ins, 0, |
@@ -834,6 +890,6 @@ int __devinit lola_create_mixer(struct lola *chip) | |||
834 | "Stream Playback Volume"); | 890 | "Stream Playback Volume"); |
835 | if (err < 0) | 891 | if (err < 0) |
836 | return err; | 892 | return err; |
837 | 893 | #endif /* FIXME */ | |
838 | return init_mixer_values(chip); | 894 | return init_mixer_values(chip); |
839 | } | 895 | } |
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index 1bd7a540fd49..04ae84b2a107 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c | |||
@@ -762,7 +762,6 @@ static int lx_set_granularity(struct lx6464es *chip, u32 gran) | |||
762 | static int __devinit lx_init_dsp(struct lx6464es *chip) | 762 | static int __devinit lx_init_dsp(struct lx6464es *chip) |
763 | { | 763 | { |
764 | int err; | 764 | int err; |
765 | u8 mac_address[6]; | ||
766 | int i; | 765 | int i; |
767 | 766 | ||
768 | snd_printdd("->lx_init_dsp\n"); | 767 | snd_printdd("->lx_init_dsp\n"); |
@@ -787,11 +786,11 @@ static int __devinit lx_init_dsp(struct lx6464es *chip) | |||
787 | /** \todo the mac address should be ready by not, but it isn't, | 786 | /** \todo the mac address should be ready by not, but it isn't, |
788 | * so we wait for it */ | 787 | * so we wait for it */ |
789 | for (i = 0; i != 1000; ++i) { | 788 | for (i = 0; i != 1000; ++i) { |
790 | err = lx_dsp_get_mac(chip, mac_address); | 789 | err = lx_dsp_get_mac(chip); |
791 | if (err) | 790 | if (err) |
792 | return err; | 791 | return err; |
793 | if (mac_address[0] || mac_address[1] || mac_address[2] || | 792 | if (chip->mac_address[0] || chip->mac_address[1] || chip->mac_address[2] || |
794 | mac_address[3] || mac_address[4] || mac_address[5]) | 793 | chip->mac_address[3] || chip->mac_address[4] || chip->mac_address[5]) |
795 | goto mac_ready; | 794 | goto mac_ready; |
796 | msleep(1); | 795 | msleep(1); |
797 | } | 796 | } |
@@ -800,8 +799,8 @@ static int __devinit lx_init_dsp(struct lx6464es *chip) | |||
800 | mac_ready: | 799 | mac_ready: |
801 | snd_printd(LXP "mac address ready read after: %dms\n", i); | 800 | snd_printd(LXP "mac address ready read after: %dms\n", i); |
802 | snd_printk(LXP "mac address: %02X.%02X.%02X.%02X.%02X.%02X\n", | 801 | snd_printk(LXP "mac address: %02X.%02X.%02X.%02X.%02X.%02X\n", |
803 | mac_address[0], mac_address[1], mac_address[2], | 802 | chip->mac_address[0], chip->mac_address[1], chip->mac_address[2], |
804 | mac_address[3], mac_address[4], mac_address[5]); | 803 | chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]); |
805 | 804 | ||
806 | err = lx_init_get_version_features(chip); | 805 | err = lx_init_get_version_features(chip); |
807 | if (err) | 806 | if (err) |
@@ -1031,7 +1030,7 @@ static int __devinit snd_lx6464es_create(struct snd_card *card, | |||
1031 | chip->port_dsp_bar = pci_ioremap_bar(pci, 2); | 1030 | chip->port_dsp_bar = pci_ioremap_bar(pci, 2); |
1032 | 1031 | ||
1033 | err = request_irq(pci->irq, lx_interrupt, IRQF_SHARED, | 1032 | err = request_irq(pci->irq, lx_interrupt, IRQF_SHARED, |
1034 | card_name, chip); | 1033 | KBUILD_MODNAME, chip); |
1035 | if (err) { | 1034 | if (err) { |
1036 | snd_printk(KERN_ERR LXP "unable to grab IRQ %d\n", pci->irq); | 1035 | snd_printk(KERN_ERR LXP "unable to grab IRQ %d\n", pci->irq); |
1037 | goto request_irq_failed; | 1036 | goto request_irq_failed; |
@@ -1108,8 +1107,14 @@ static int __devinit snd_lx6464es_probe(struct pci_dev *pci, | |||
1108 | goto out_free; | 1107 | goto out_free; |
1109 | } | 1108 | } |
1110 | 1109 | ||
1111 | strcpy(card->driver, "lx6464es"); | 1110 | strcpy(card->driver, "LX6464ES"); |
1112 | strcpy(card->shortname, "Digigram LX6464ES"); | 1111 | sprintf(card->id, "LX6464ES_%02X%02X%02X", |
1112 | chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]); | ||
1113 | |||
1114 | sprintf(card->shortname, "LX6464ES %02X.%02X.%02X.%02X.%02X.%02X", | ||
1115 | chip->mac_address[0], chip->mac_address[1], chip->mac_address[2], | ||
1116 | chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]); | ||
1117 | |||
1113 | sprintf(card->longname, "%s at 0x%lx, 0x%p, irq %i", | 1118 | sprintf(card->longname, "%s at 0x%lx, 0x%p, irq %i", |
1114 | card->shortname, chip->port_plx, | 1119 | card->shortname, chip->port_plx, |
1115 | chip->port_dsp_bar, chip->irq); | 1120 | chip->port_dsp_bar, chip->irq); |
@@ -1137,7 +1142,7 @@ static void __devexit snd_lx6464es_remove(struct pci_dev *pci) | |||
1137 | 1142 | ||
1138 | 1143 | ||
1139 | static struct pci_driver driver = { | 1144 | static struct pci_driver driver = { |
1140 | .name = "Digigram LX6464ES", | 1145 | .name = KBUILD_MODNAME, |
1141 | .id_table = snd_lx6464es_ids, | 1146 | .id_table = snd_lx6464es_ids, |
1142 | .probe = snd_lx6464es_probe, | 1147 | .probe = snd_lx6464es_probe, |
1143 | .remove = __devexit_p(snd_lx6464es_remove), | 1148 | .remove = __devexit_p(snd_lx6464es_remove), |
diff --git a/sound/pci/lx6464es/lx6464es.h b/sound/pci/lx6464es/lx6464es.h index aea621eafbb5..e2a124ae27e8 100644 --- a/sound/pci/lx6464es/lx6464es.h +++ b/sound/pci/lx6464es/lx6464es.h | |||
@@ -69,6 +69,8 @@ struct lx6464es { | |||
69 | struct pci_dev *pci; | 69 | struct pci_dev *pci; |
70 | int irq; | 70 | int irq; |
71 | 71 | ||
72 | u8 mac_address[6]; | ||
73 | |||
72 | spinlock_t lock; /* interrupt spinlock */ | 74 | spinlock_t lock; /* interrupt spinlock */ |
73 | struct mutex setup_mutex; /* mutex used in hw_params, open | 75 | struct mutex setup_mutex; /* mutex used in hw_params, open |
74 | * and close */ | 76 | * and close */ |
diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index 617f98b0cbae..5c8717e29eeb 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c | |||
@@ -424,7 +424,7 @@ int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq) | |||
424 | return ret; | 424 | return ret; |
425 | } | 425 | } |
426 | 426 | ||
427 | int lx_dsp_get_mac(struct lx6464es *chip, u8 *mac_address) | 427 | int lx_dsp_get_mac(struct lx6464es *chip) |
428 | { | 428 | { |
429 | u32 macmsb, maclsb; | 429 | u32 macmsb, maclsb; |
430 | 430 | ||
@@ -432,12 +432,12 @@ int lx_dsp_get_mac(struct lx6464es *chip, u8 *mac_address) | |||
432 | maclsb = lx_dsp_reg_read(chip, eReg_ADMACESLSB) & 0x00FFFFFF; | 432 | maclsb = lx_dsp_reg_read(chip, eReg_ADMACESLSB) & 0x00FFFFFF; |
433 | 433 | ||
434 | /* todo: endianess handling */ | 434 | /* todo: endianess handling */ |
435 | mac_address[5] = ((u8 *)(&maclsb))[0]; | 435 | chip->mac_address[5] = ((u8 *)(&maclsb))[0]; |
436 | mac_address[4] = ((u8 *)(&maclsb))[1]; | 436 | chip->mac_address[4] = ((u8 *)(&maclsb))[1]; |
437 | mac_address[3] = ((u8 *)(&maclsb))[2]; | 437 | chip->mac_address[3] = ((u8 *)(&maclsb))[2]; |
438 | mac_address[2] = ((u8 *)(&macmsb))[0]; | 438 | chip->mac_address[2] = ((u8 *)(&macmsb))[0]; |
439 | mac_address[1] = ((u8 *)(&macmsb))[1]; | 439 | chip->mac_address[1] = ((u8 *)(&macmsb))[1]; |
440 | mac_address[0] = ((u8 *)(&macmsb))[2]; | 440 | chip->mac_address[0] = ((u8 *)(&macmsb))[2]; |
441 | 441 | ||
442 | return 0; | 442 | return 0; |
443 | } | 443 | } |
diff --git a/sound/pci/lx6464es/lx_core.h b/sound/pci/lx6464es/lx_core.h index 6bd9cbbbc68d..1dd562980b6c 100644 --- a/sound/pci/lx6464es/lx_core.h +++ b/sound/pci/lx6464es/lx_core.h | |||
@@ -116,7 +116,7 @@ int __devinit lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version); | |||
116 | int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq); | 116 | int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq); |
117 | int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran); | 117 | int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran); |
118 | int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data); | 118 | int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data); |
119 | int lx_dsp_get_mac(struct lx6464es *chip, u8 *mac_address); | 119 | int lx_dsp_get_mac(struct lx6464es *chip); |
120 | 120 | ||
121 | 121 | ||
122 | /* low-level pipe handling */ | 122 | /* low-level pipe handling */ |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 3c40d726b46e..0378126e6272 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -850,11 +850,10 @@ struct snd_m3 { | |||
850 | struct input_dev *input_dev; | 850 | struct input_dev *input_dev; |
851 | char phys[64]; /* physical device path */ | 851 | char phys[64]; /* physical device path */ |
852 | #else | 852 | #else |
853 | spinlock_t ac97_lock; | ||
854 | struct snd_kcontrol *master_switch; | 853 | struct snd_kcontrol *master_switch; |
855 | struct snd_kcontrol *master_volume; | 854 | struct snd_kcontrol *master_volume; |
856 | struct tasklet_struct hwvol_tq; | ||
857 | #endif | 855 | #endif |
856 | struct work_struct hwvol_work; | ||
858 | 857 | ||
859 | unsigned int in_suspend; | 858 | unsigned int in_suspend; |
860 | 859 | ||
@@ -1609,13 +1608,10 @@ static void snd_m3_update_ptr(struct snd_m3 *chip, struct m3_dma *s) | |||
1609 | (without wrap around) in response to volume button presses and then | 1608 | (without wrap around) in response to volume button presses and then |
1610 | generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7 | 1609 | generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7 |
1611 | of a byte wide register. The meaning of bits 0 and 4 is unknown. */ | 1610 | of a byte wide register. The meaning of bits 0 and 4 is unknown. */ |
1612 | static void snd_m3_update_hw_volume(unsigned long private_data) | 1611 | static void snd_m3_update_hw_volume(struct work_struct *work) |
1613 | { | 1612 | { |
1614 | struct snd_m3 *chip = (struct snd_m3 *) private_data; | 1613 | struct snd_m3 *chip = container_of(work, struct snd_m3, hwvol_work); |
1615 | int x, val; | 1614 | int x, val; |
1616 | #ifndef CONFIG_SND_MAESTRO3_INPUT | ||
1617 | unsigned long flags; | ||
1618 | #endif | ||
1619 | 1615 | ||
1620 | /* Figure out which volume control button was pushed, | 1616 | /* Figure out which volume control button was pushed, |
1621 | based on differences from the default register | 1617 | based on differences from the default register |
@@ -1645,21 +1641,13 @@ static void snd_m3_update_hw_volume(unsigned long private_data) | |||
1645 | if (!chip->master_switch || !chip->master_volume) | 1641 | if (!chip->master_switch || !chip->master_volume) |
1646 | return; | 1642 | return; |
1647 | 1643 | ||
1648 | /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */ | 1644 | val = snd_ac97_read(chip->ac97, AC97_MASTER); |
1649 | spin_lock_irqsave(&chip->ac97_lock, flags); | ||
1650 | |||
1651 | val = chip->ac97->regs[AC97_MASTER_VOL]; | ||
1652 | switch (x) { | 1645 | switch (x) { |
1653 | case 0x88: | 1646 | case 0x88: |
1654 | /* The counters have not changed, yet we've received a HV | 1647 | /* The counters have not changed, yet we've received a HV |
1655 | interrupt. According to tests run by various people this | 1648 | interrupt. According to tests run by various people this |
1656 | happens when pressing the mute button. */ | 1649 | happens when pressing the mute button. */ |
1657 | val ^= 0x8000; | 1650 | val ^= 0x8000; |
1658 | chip->ac97->regs[AC97_MASTER_VOL] = val; | ||
1659 | outw(val, chip->iobase + CODEC_DATA); | ||
1660 | outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); | ||
1661 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1662 | &chip->master_switch->id); | ||
1663 | break; | 1651 | break; |
1664 | case 0xaa: | 1652 | case 0xaa: |
1665 | /* counters increased by 1 -> volume up */ | 1653 | /* counters increased by 1 -> volume up */ |
@@ -1667,11 +1655,6 @@ static void snd_m3_update_hw_volume(unsigned long private_data) | |||
1667 | val--; | 1655 | val--; |
1668 | if ((val & 0x7f00) > 0) | 1656 | if ((val & 0x7f00) > 0) |
1669 | val -= 0x0100; | 1657 | val -= 0x0100; |
1670 | chip->ac97->regs[AC97_MASTER_VOL] = val; | ||
1671 | outw(val, chip->iobase + CODEC_DATA); | ||
1672 | outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); | ||
1673 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1674 | &chip->master_volume->id); | ||
1675 | break; | 1658 | break; |
1676 | case 0x66: | 1659 | case 0x66: |
1677 | /* counters decreased by 1 -> volume down */ | 1660 | /* counters decreased by 1 -> volume down */ |
@@ -1679,14 +1662,11 @@ static void snd_m3_update_hw_volume(unsigned long private_data) | |||
1679 | val++; | 1662 | val++; |
1680 | if ((val & 0x7f00) < 0x1f00) | 1663 | if ((val & 0x7f00) < 0x1f00) |
1681 | val += 0x0100; | 1664 | val += 0x0100; |
1682 | chip->ac97->regs[AC97_MASTER_VOL] = val; | ||
1683 | outw(val, chip->iobase + CODEC_DATA); | ||
1684 | outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); | ||
1685 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1686 | &chip->master_volume->id); | ||
1687 | break; | 1665 | break; |
1688 | } | 1666 | } |
1689 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | 1667 | if (snd_ac97_update(chip->ac97, AC97_MASTER, val)) |
1668 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1669 | &chip->master_switch->id); | ||
1690 | #else | 1670 | #else |
1691 | if (!chip->input_dev) | 1671 | if (!chip->input_dev) |
1692 | return; | 1672 | return; |
@@ -1730,11 +1710,7 @@ static irqreturn_t snd_m3_interrupt(int irq, void *dev_id) | |||
1730 | return IRQ_NONE; | 1710 | return IRQ_NONE; |
1731 | 1711 | ||
1732 | if (status & HV_INT_PENDING) | 1712 | if (status & HV_INT_PENDING) |
1733 | #ifdef CONFIG_SND_MAESTRO3_INPUT | 1713 | schedule_work(&chip->hwvol_work); |
1734 | snd_m3_update_hw_volume((unsigned long)chip); | ||
1735 | #else | ||
1736 | tasklet_schedule(&chip->hwvol_tq); | ||
1737 | #endif | ||
1738 | 1714 | ||
1739 | /* | 1715 | /* |
1740 | * ack an assp int if its running | 1716 | * ack an assp int if its running |
@@ -2000,24 +1976,14 @@ static unsigned short | |||
2000 | snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | 1976 | snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg) |
2001 | { | 1977 | { |
2002 | struct snd_m3 *chip = ac97->private_data; | 1978 | struct snd_m3 *chip = ac97->private_data; |
2003 | #ifndef CONFIG_SND_MAESTRO3_INPUT | ||
2004 | unsigned long flags; | ||
2005 | #endif | ||
2006 | unsigned short data = 0xffff; | 1979 | unsigned short data = 0xffff; |
2007 | 1980 | ||
2008 | if (snd_m3_ac97_wait(chip)) | 1981 | if (snd_m3_ac97_wait(chip)) |
2009 | goto fail; | 1982 | goto fail; |
2010 | #ifndef CONFIG_SND_MAESTRO3_INPUT | ||
2011 | spin_lock_irqsave(&chip->ac97_lock, flags); | ||
2012 | #endif | ||
2013 | snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); | 1983 | snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); |
2014 | if (snd_m3_ac97_wait(chip)) | 1984 | if (snd_m3_ac97_wait(chip)) |
2015 | goto fail_unlock; | 1985 | goto fail; |
2016 | data = snd_m3_inw(chip, CODEC_DATA); | 1986 | data = snd_m3_inw(chip, CODEC_DATA); |
2017 | fail_unlock: | ||
2018 | #ifndef CONFIG_SND_MAESTRO3_INPUT | ||
2019 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | ||
2020 | #endif | ||
2021 | fail: | 1987 | fail: |
2022 | return data; | 1988 | return data; |
2023 | } | 1989 | } |
@@ -2026,20 +1992,11 @@ static void | |||
2026 | snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) | 1992 | snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) |
2027 | { | 1993 | { |
2028 | struct snd_m3 *chip = ac97->private_data; | 1994 | struct snd_m3 *chip = ac97->private_data; |
2029 | #ifndef CONFIG_SND_MAESTRO3_INPUT | ||
2030 | unsigned long flags; | ||
2031 | #endif | ||
2032 | 1995 | ||
2033 | if (snd_m3_ac97_wait(chip)) | 1996 | if (snd_m3_ac97_wait(chip)) |
2034 | return; | 1997 | return; |
2035 | #ifndef CONFIG_SND_MAESTRO3_INPUT | ||
2036 | spin_lock_irqsave(&chip->ac97_lock, flags); | ||
2037 | #endif | ||
2038 | snd_m3_outw(chip, val, CODEC_DATA); | 1998 | snd_m3_outw(chip, val, CODEC_DATA); |
2039 | snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); | 1999 | snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); |
2040 | #ifndef CONFIG_SND_MAESTRO3_INPUT | ||
2041 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | ||
2042 | #endif | ||
2043 | } | 2000 | } |
2044 | 2001 | ||
2045 | 2002 | ||
@@ -2458,6 +2415,7 @@ static int snd_m3_free(struct snd_m3 *chip) | |||
2458 | struct m3_dma *s; | 2415 | struct m3_dma *s; |
2459 | int i; | 2416 | int i; |
2460 | 2417 | ||
2418 | cancel_work_sync(&chip->hwvol_work); | ||
2461 | #ifdef CONFIG_SND_MAESTRO3_INPUT | 2419 | #ifdef CONFIG_SND_MAESTRO3_INPUT |
2462 | if (chip->input_dev) | 2420 | if (chip->input_dev) |
2463 | input_unregister_device(chip->input_dev); | 2421 | input_unregister_device(chip->input_dev); |
@@ -2511,6 +2469,7 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state) | |||
2511 | return 0; | 2469 | return 0; |
2512 | 2470 | ||
2513 | chip->in_suspend = 1; | 2471 | chip->in_suspend = 1; |
2472 | cancel_work_sync(&chip->hwvol_work); | ||
2514 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 2473 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
2515 | snd_pcm_suspend_all(chip->pcm); | 2474 | snd_pcm_suspend_all(chip->pcm); |
2516 | snd_ac97_suspend(chip->ac97); | 2475 | snd_ac97_suspend(chip->ac97); |
@@ -2667,9 +2626,6 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
2667 | } | 2626 | } |
2668 | 2627 | ||
2669 | spin_lock_init(&chip->reg_lock); | 2628 | spin_lock_init(&chip->reg_lock); |
2670 | #ifndef CONFIG_SND_MAESTRO3_INPUT | ||
2671 | spin_lock_init(&chip->ac97_lock); | ||
2672 | #endif | ||
2673 | 2629 | ||
2674 | switch (pci->device) { | 2630 | switch (pci->device) { |
2675 | case PCI_DEVICE_ID_ESS_ALLEGRO: | 2631 | case PCI_DEVICE_ID_ESS_ALLEGRO: |
@@ -2683,6 +2639,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
2683 | chip->card = card; | 2639 | chip->card = card; |
2684 | chip->pci = pci; | 2640 | chip->pci = pci; |
2685 | chip->irq = -1; | 2641 | chip->irq = -1; |
2642 | INIT_WORK(&chip->hwvol_work, snd_m3_update_hw_volume); | ||
2686 | 2643 | ||
2687 | chip->external_amp = enable_amp; | 2644 | chip->external_amp = enable_amp; |
2688 | if (amp_gpio >= 0 && amp_gpio <= 0x0f) | 2645 | if (amp_gpio >= 0 && amp_gpio <= 0x0f) |
@@ -2752,12 +2709,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
2752 | 2709 | ||
2753 | snd_m3_hv_init(chip); | 2710 | snd_m3_hv_init(chip); |
2754 | 2711 | ||
2755 | #ifndef CONFIG_SND_MAESTRO3_INPUT | ||
2756 | tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); | ||
2757 | #endif | ||
2758 | |||
2759 | if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, | 2712 | if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, |
2760 | card->driver, chip)) { | 2713 | KBUILD_MODNAME, chip)) { |
2761 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 2714 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
2762 | snd_m3_free(chip); | 2715 | snd_m3_free(chip); |
2763 | return -ENOMEM; | 2716 | return -ENOMEM; |
@@ -2885,7 +2838,7 @@ static void __devexit snd_m3_remove(struct pci_dev *pci) | |||
2885 | } | 2838 | } |
2886 | 2839 | ||
2887 | static struct pci_driver driver = { | 2840 | static struct pci_driver driver = { |
2888 | .name = "Maestro3", | 2841 | .name = KBUILD_MODNAME, |
2889 | .id_table = snd_m3_ids, | 2842 | .id_table = snd_m3_ids, |
2890 | .probe = snd_m3_probe, | 2843 | .probe = snd_m3_probe, |
2891 | .remove = __devexit_p(snd_m3_remove), | 2844 | .remove = __devexit_p(snd_m3_remove), |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 6c3fd4d1c49d..dbee59906ae1 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -1268,7 +1268,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, | |||
1268 | } | 1268 | } |
1269 | 1269 | ||
1270 | if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED, | 1270 | if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED, |
1271 | CARD_NAME, mgr)) { | 1271 | KBUILD_MODNAME, mgr)) { |
1272 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1272 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1273 | snd_mixart_free(mgr); | 1273 | snd_mixart_free(mgr); |
1274 | return -EBUSY; | 1274 | return -EBUSY; |
@@ -1381,7 +1381,7 @@ static void __devexit snd_mixart_remove(struct pci_dev *pci) | |||
1381 | } | 1381 | } |
1382 | 1382 | ||
1383 | static struct pci_driver driver = { | 1383 | static struct pci_driver driver = { |
1384 | .name = "Digigram miXart", | 1384 | .name = KBUILD_MODNAME, |
1385 | .id_table = snd_mixart_ids, | 1385 | .id_table = snd_mixart_ids, |
1386 | .probe = snd_mixart_probe, | 1386 | .probe = snd_mixart_probe, |
1387 | .remove = __devexit_p(snd_mixart_remove), | 1387 | .remove = __devexit_p(snd_mixart_remove), |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 5a60492ac7b3..83ea7a7d3eec 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -465,7 +465,7 @@ static int snd_nm256_acquire_irq(struct nm256 *chip) | |||
465 | mutex_lock(&chip->irq_mutex); | 465 | mutex_lock(&chip->irq_mutex); |
466 | if (chip->irq < 0) { | 466 | if (chip->irq < 0) { |
467 | if (request_irq(chip->pci->irq, chip->interrupt, IRQF_SHARED, | 467 | if (request_irq(chip->pci->irq, chip->interrupt, IRQF_SHARED, |
468 | chip->card->driver, chip)) { | 468 | KBUILD_MODNAME, chip)) { |
469 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->pci->irq); | 469 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->pci->irq); |
470 | mutex_unlock(&chip->irq_mutex); | 470 | mutex_unlock(&chip->irq_mutex); |
471 | return -EBUSY; | 471 | return -EBUSY; |
@@ -1743,7 +1743,7 @@ static void __devexit snd_nm256_remove(struct pci_dev *pci) | |||
1743 | 1743 | ||
1744 | 1744 | ||
1745 | static struct pci_driver driver = { | 1745 | static struct pci_driver driver = { |
1746 | .name = "NeoMagic 256", | 1746 | .name = KBUILD_MODNAME, |
1747 | .id_table = snd_nm256_ids, | 1747 | .id_table = snd_nm256_ids, |
1748 | .probe = snd_nm256_probe, | 1748 | .probe = snd_nm256_probe, |
1749 | .remove = __devexit_p(snd_nm256_remove), | 1749 | .remove = __devexit_p(snd_nm256_remove), |
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index d7e8ddd9a67b..218d9854e5cb 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
@@ -859,7 +859,7 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci, | |||
859 | } | 859 | } |
860 | 860 | ||
861 | static struct pci_driver oxygen_driver = { | 861 | static struct pci_driver oxygen_driver = { |
862 | .name = "CMI8788", | 862 | .name = KBUILD_MODNAME, |
863 | .id_table = oxygen_ids, | 863 | .id_table = oxygen_ids, |
864 | .probe = generic_oxygen_probe, | 864 | .probe = generic_oxygen_probe, |
865 | .remove = __devexit_p(oxygen_pci_remove), | 865 | .remove = __devexit_p(oxygen_pci_remove), |
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 70b739816fcc..82311fcb86f6 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -655,7 +655,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
655 | chip->model.init(chip); | 655 | chip->model.init(chip); |
656 | 656 | ||
657 | err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED, | 657 | err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED, |
658 | DRIVER, chip); | 658 | KBUILD_MODNAME, chip); |
659 | if (err < 0) { | 659 | if (err < 0) { |
660 | snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq); | 660 | snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq); |
661 | goto err_card; | 661 | goto err_card; |
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index d5533e34ece9..cc0bcd9f3350 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c | |||
@@ -168,12 +168,6 @@ static int oxygen_open(struct snd_pcm_substream *substream, | |||
168 | if (err < 0) | 168 | if (err < 0) |
169 | return err; | 169 | return err; |
170 | } | 170 | } |
171 | if (channel == PCM_MULTICH) { | ||
172 | err = snd_pcm_hw_constraint_minmax | ||
173 | (runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 0, 8192000); | ||
174 | if (err < 0) | ||
175 | return err; | ||
176 | } | ||
177 | snd_pcm_set_sync(substream); | 171 | snd_pcm_set_sync(substream); |
178 | chip->streams[channel] = substream; | 172 | chip->streams[channel] = substream; |
179 | 173 | ||
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 469010a8b849..773db794b43f 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
@@ -88,7 +88,7 @@ static int __devinit xonar_probe(struct pci_dev *pci, | |||
88 | } | 88 | } |
89 | 89 | ||
90 | static struct pci_driver xonar_driver = { | 90 | static struct pci_driver xonar_driver = { |
91 | .name = "AV200", | 91 | .name = KBUILD_MODNAME, |
92 | .id_table = xonar_ids, | 92 | .id_table = xonar_ids, |
93 | .probe = xonar_probe, | 93 | .probe = xonar_probe, |
94 | .remove = __devexit_p(oxygen_pci_remove), | 94 | .remove = __devexit_p(oxygen_pci_remove), |
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index 54cad38ec30a..32d096c98f5b 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c | |||
@@ -327,8 +327,10 @@ static void pcm1796_init(struct oxygen *chip) | |||
327 | { | 327 | { |
328 | struct xonar_pcm179x *data = chip->model_data; | 328 | struct xonar_pcm179x *data = chip->model_data; |
329 | 329 | ||
330 | data->pcm1796_regs[0][18 - PCM1796_REG_BASE] = PCM1796_MUTE | | 330 | data->pcm1796_regs[0][18 - PCM1796_REG_BASE] = |
331 | PCM1796_DMF_DISABLED | PCM1796_FMT_24_I2S | PCM1796_ATLD; | 331 | PCM1796_DMF_DISABLED | PCM1796_FMT_24_I2S | PCM1796_ATLD; |
332 | if (!data->broken_i2c) | ||
333 | data->pcm1796_regs[0][18 - PCM1796_REG_BASE] |= PCM1796_MUTE; | ||
332 | data->pcm1796_regs[0][19 - PCM1796_REG_BASE] = | 334 | data->pcm1796_regs[0][19 - PCM1796_REG_BASE] = |
333 | PCM1796_FLT_SHARP | PCM1796_ATS_1; | 335 | PCM1796_FLT_SHARP | PCM1796_ATS_1; |
334 | data->pcm1796_regs[0][20 - PCM1796_REG_BASE] = | 336 | data->pcm1796_regs[0][20 - PCM1796_REG_BASE] = |
@@ -1123,6 +1125,7 @@ int __devinit get_xonar_pcm179x_model(struct oxygen *chip, | |||
1123 | chip->model.control_filter = xonar_st_h6_control_filter; | 1125 | chip->model.control_filter = xonar_st_h6_control_filter; |
1124 | chip->model.dac_channels_pcm = 8; | 1126 | chip->model.dac_channels_pcm = 8; |
1125 | chip->model.dac_channels_mixer = 8; | 1127 | chip->model.dac_channels_mixer = 8; |
1128 | chip->model.dac_volume_min = 255; | ||
1126 | chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128); | 1129 | chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128); |
1127 | break; | 1130 | break; |
1128 | } | 1131 | } |
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 95cfde27d25c..046578d26f98 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
@@ -1501,7 +1501,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, | |||
1501 | mgr->irq = -1; | 1501 | mgr->irq = -1; |
1502 | 1502 | ||
1503 | if (request_irq(pci->irq, pcxhr_interrupt, IRQF_SHARED, | 1503 | if (request_irq(pci->irq, pcxhr_interrupt, IRQF_SHARED, |
1504 | card_name, mgr)) { | 1504 | KBUILD_MODNAME, mgr)) { |
1505 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1505 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1506 | pcxhr_free(mgr); | 1506 | pcxhr_free(mgr); |
1507 | return -EBUSY; | 1507 | return -EBUSY; |
@@ -1608,7 +1608,7 @@ static void __devexit pcxhr_remove(struct pci_dev *pci) | |||
1608 | } | 1608 | } |
1609 | 1609 | ||
1610 | static struct pci_driver driver = { | 1610 | static struct pci_driver driver = { |
1611 | .name = "Digigram pcxhr", | 1611 | .name = KBUILD_MODNAME, |
1612 | .id_table = pcxhr_ids, | 1612 | .id_table = pcxhr_ids, |
1613 | .probe = pcxhr_probe, | 1613 | .probe = pcxhr_probe, |
1614 | .remove = __devexit_p(pcxhr_remove), | 1614 | .remove = __devexit_p(pcxhr_remove), |
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index ad5202efd7a9..e34ae14908b3 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c | |||
@@ -1890,7 +1890,7 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci, | |||
1890 | UNSET_AIE(hwport); | 1890 | UNSET_AIE(hwport); |
1891 | 1891 | ||
1892 | if (request_irq(pci->irq, snd_riptide_interrupt, IRQF_SHARED, | 1892 | if (request_irq(pci->irq, snd_riptide_interrupt, IRQF_SHARED, |
1893 | "RIPTIDE", chip)) { | 1893 | KBUILD_MODNAME, chip)) { |
1894 | snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n", | 1894 | snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n", |
1895 | pci->irq); | 1895 | pci->irq); |
1896 | snd_riptide_free(chip); | 1896 | snd_riptide_free(chip); |
@@ -2176,7 +2176,7 @@ static void __devexit snd_card_riptide_remove(struct pci_dev *pci) | |||
2176 | } | 2176 | } |
2177 | 2177 | ||
2178 | static struct pci_driver driver = { | 2178 | static struct pci_driver driver = { |
2179 | .name = "RIPTIDE", | 2179 | .name = KBUILD_MODNAME, |
2180 | .id_table = snd_riptide_ids, | 2180 | .id_table = snd_riptide_ids, |
2181 | .probe = snd_card_riptide_probe, | 2181 | .probe = snd_card_riptide_probe, |
2182 | .remove = __devexit_p(snd_card_riptide_remove), | 2182 | .remove = __devexit_p(snd_card_riptide_remove), |
@@ -2188,7 +2188,7 @@ static struct pci_driver driver = { | |||
2188 | 2188 | ||
2189 | #ifdef SUPPORT_JOYSTICK | 2189 | #ifdef SUPPORT_JOYSTICK |
2190 | static struct pci_driver joystick_driver = { | 2190 | static struct pci_driver joystick_driver = { |
2191 | .name = "Riptide Joystick", | 2191 | .name = KBUILD_MODNAME "-joystick", |
2192 | .id_table = snd_riptide_joystick_ids, | 2192 | .id_table = snd_riptide_joystick_ids, |
2193 | .probe = snd_riptide_joystick_probe, | 2193 | .probe = snd_riptide_joystick_probe, |
2194 | .remove = __devexit_p(snd_riptide_joystick_remove), | 2194 | .remove = __devexit_p(snd_riptide_joystick_remove), |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 3c04524de37c..6be77a264d47 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
@@ -1355,7 +1355,7 @@ static int __devinit snd_rme32_create(struct rme32 * rme32) | |||
1355 | } | 1355 | } |
1356 | 1356 | ||
1357 | if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_SHARED, | 1357 | if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_SHARED, |
1358 | "RME32", rme32)) { | 1358 | KBUILD_MODNAME, rme32)) { |
1359 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1359 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1360 | return -EBUSY; | 1360 | return -EBUSY; |
1361 | } | 1361 | } |
@@ -1985,7 +1985,7 @@ static void __devexit snd_rme32_remove(struct pci_dev *pci) | |||
1985 | } | 1985 | } |
1986 | 1986 | ||
1987 | static struct pci_driver driver = { | 1987 | static struct pci_driver driver = { |
1988 | .name = "RME Digi32", | 1988 | .name = KBUILD_MODNAME, |
1989 | .id_table = snd_rme32_ids, | 1989 | .id_table = snd_rme32_ids, |
1990 | .probe = snd_rme32_probe, | 1990 | .probe = snd_rme32_probe, |
1991 | .remove = __devexit_p(snd_rme32_remove), | 1991 | .remove = __devexit_p(snd_rme32_remove), |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 9ff247fc8871..409e5b89519d 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -1561,7 +1561,7 @@ snd_rme96_create(struct rme96 *rme96) | |||
1561 | } | 1561 | } |
1562 | 1562 | ||
1563 | if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_SHARED, | 1563 | if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_SHARED, |
1564 | "RME96", rme96)) { | 1564 | KBUILD_MODNAME, rme96)) { |
1565 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1565 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1566 | return -EBUSY; | 1566 | return -EBUSY; |
1567 | } | 1567 | } |
@@ -2396,7 +2396,7 @@ static void __devexit snd_rme96_remove(struct pci_dev *pci) | |||
2396 | } | 2396 | } |
2397 | 2397 | ||
2398 | static struct pci_driver driver = { | 2398 | static struct pci_driver driver = { |
2399 | .name = "RME Digi96", | 2399 | .name = KBUILD_MODNAME, |
2400 | .id_table = snd_rme96_ids, | 2400 | .id_table = snd_rme96_ids, |
2401 | .probe = snd_rme96_probe, | 2401 | .probe = snd_rme96_probe, |
2402 | .remove = __devexit_p(snd_rme96_remove), | 2402 | .remove = __devexit_p(snd_rme96_remove), |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 2d8332416c83..1c6d1e1c27c1 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -5482,7 +5482,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card, | |||
5482 | } | 5482 | } |
5483 | 5483 | ||
5484 | if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED, | 5484 | if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED, |
5485 | "hdsp", hdsp)) { | 5485 | KBUILD_MODNAME, hdsp)) { |
5486 | snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq); | 5486 | snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq); |
5487 | return -EBUSY; | 5487 | return -EBUSY; |
5488 | } | 5488 | } |
@@ -5637,7 +5637,7 @@ static void __devexit snd_hdsp_remove(struct pci_dev *pci) | |||
5637 | } | 5637 | } |
5638 | 5638 | ||
5639 | static struct pci_driver driver = { | 5639 | static struct pci_driver driver = { |
5640 | .name = "RME Hammerfall DSP", | 5640 | .name = KBUILD_MODNAME, |
5641 | .id_table = snd_hdsp_ids, | 5641 | .id_table = snd_hdsp_ids, |
5642 | .probe = snd_hdsp_probe, | 5642 | .probe = snd_hdsp_probe, |
5643 | .remove = __devexit_p(snd_hdsp_remove), | 5643 | .remove = __devexit_p(snd_hdsp_remove), |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index c8e402fc3782..af130ee0c45d 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -6441,7 +6441,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, | |||
6441 | hdspm->port + io_extent - 1); | 6441 | hdspm->port + io_extent - 1); |
6442 | 6442 | ||
6443 | if (request_irq(pci->irq, snd_hdspm_interrupt, | 6443 | if (request_irq(pci->irq, snd_hdspm_interrupt, |
6444 | IRQF_SHARED, "hdspm", hdspm)) { | 6444 | IRQF_SHARED, KBUILD_MODNAME, hdspm)) { |
6445 | snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); | 6445 | snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); |
6446 | return -EBUSY; | 6446 | return -EBUSY; |
6447 | } | 6447 | } |
@@ -6779,7 +6779,7 @@ static void __devexit snd_hdspm_remove(struct pci_dev *pci) | |||
6779 | } | 6779 | } |
6780 | 6780 | ||
6781 | static struct pci_driver driver = { | 6781 | static struct pci_driver driver = { |
6782 | .name = "RME Hammerfall DSP MADI", | 6782 | .name = KBUILD_MODNAME, |
6783 | .id_table = snd_hdspm_ids, | 6783 | .id_table = snd_hdspm_ids, |
6784 | .probe = snd_hdspm_probe, | 6784 | .probe = snd_hdspm_probe, |
6785 | .remove = __devexit_p(snd_hdspm_remove), | 6785 | .remove = __devexit_p(snd_hdspm_remove), |
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index c492af5b25f3..1c7bc1ef8186 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
@@ -2479,7 +2479,7 @@ static int __devinit snd_rme9652_create(struct snd_card *card, | |||
2479 | } | 2479 | } |
2480 | 2480 | ||
2481 | if (request_irq(pci->irq, snd_rme9652_interrupt, IRQF_SHARED, | 2481 | if (request_irq(pci->irq, snd_rme9652_interrupt, IRQF_SHARED, |
2482 | "rme9652", rme9652)) { | 2482 | KBUILD_MODNAME, rme9652)) { |
2483 | snd_printk(KERN_ERR "unable to request IRQ %d\n", pci->irq); | 2483 | snd_printk(KERN_ERR "unable to request IRQ %d\n", pci->irq); |
2484 | return -EBUSY; | 2484 | return -EBUSY; |
2485 | } | 2485 | } |
@@ -2632,7 +2632,7 @@ static void __devexit snd_rme9652_remove(struct pci_dev *pci) | |||
2632 | } | 2632 | } |
2633 | 2633 | ||
2634 | static struct pci_driver driver = { | 2634 | static struct pci_driver driver = { |
2635 | .name = "RME Digi9652 (Hammerfall)", | 2635 | .name = KBUILD_MODNAME, |
2636 | .id_table = snd_rme9652_ids, | 2636 | .id_table = snd_rme9652_ids, |
2637 | .probe = snd_rme9652_probe, | 2637 | .probe = snd_rme9652_probe, |
2638 | .remove = __devexit_p(snd_rme9652_remove), | 2638 | .remove = __devexit_p(snd_rme9652_remove), |
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index 2b5c7a95ae1f..bcf61524a13f 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c | |||
@@ -1235,7 +1235,7 @@ static int sis_resume(struct pci_dev *pci) | |||
1235 | } | 1235 | } |
1236 | 1236 | ||
1237 | if (request_irq(pci->irq, sis_interrupt, IRQF_DISABLED|IRQF_SHARED, | 1237 | if (request_irq(pci->irq, sis_interrupt, IRQF_DISABLED|IRQF_SHARED, |
1238 | card->shortname, sis)) { | 1238 | KBUILD_MODNAME, sis)) { |
1239 | printk(KERN_ERR "sis7019: unable to regain IRQ %d\n", pci->irq); | 1239 | printk(KERN_ERR "sis7019: unable to regain IRQ %d\n", pci->irq); |
1240 | goto error; | 1240 | goto error; |
1241 | } | 1241 | } |
@@ -1341,7 +1341,7 @@ static int __devinit sis_chip_create(struct snd_card *card, | |||
1341 | goto error_out_cleanup; | 1341 | goto error_out_cleanup; |
1342 | 1342 | ||
1343 | if (request_irq(pci->irq, sis_interrupt, IRQF_DISABLED|IRQF_SHARED, | 1343 | if (request_irq(pci->irq, sis_interrupt, IRQF_DISABLED|IRQF_SHARED, |
1344 | card->shortname, sis)) { | 1344 | KBUILD_MODNAME, sis)) { |
1345 | printk(KERN_ERR "unable to allocate irq %d\n", sis->irq); | 1345 | printk(KERN_ERR "unable to allocate irq %d\n", sis->irq); |
1346 | goto error_out_cleanup; | 1346 | goto error_out_cleanup; |
1347 | } | 1347 | } |
@@ -1436,7 +1436,7 @@ static void __devexit snd_sis7019_remove(struct pci_dev *pci) | |||
1436 | } | 1436 | } |
1437 | 1437 | ||
1438 | static struct pci_driver sis7019_driver = { | 1438 | static struct pci_driver sis7019_driver = { |
1439 | .name = "SiS7019", | 1439 | .name = KBUILD_MODNAME, |
1440 | .id_table = snd_sis7019_ids, | 1440 | .id_table = snd_sis7019_ids, |
1441 | .probe = snd_sis7019_probe, | 1441 | .probe = snd_sis7019_probe, |
1442 | .remove = __devexit_p(snd_sis7019_remove), | 1442 | .remove = __devexit_p(snd_sis7019_remove), |
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 337b9facadfd..2571a67b389a 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
@@ -1294,7 +1294,7 @@ static int __devinit snd_sonicvibes_create(struct snd_card *card, | |||
1294 | sonic->game_port = pci_resource_start(pci, 4); | 1294 | sonic->game_port = pci_resource_start(pci, 4); |
1295 | 1295 | ||
1296 | if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_SHARED, | 1296 | if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_SHARED, |
1297 | "S3 SonicVibes", sonic)) { | 1297 | KBUILD_MODNAME, sonic)) { |
1298 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1298 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1299 | snd_sonicvibes_free(sonic); | 1299 | snd_sonicvibes_free(sonic); |
1300 | return -EBUSY; | 1300 | return -EBUSY; |
@@ -1530,7 +1530,7 @@ static void __devexit snd_sonic_remove(struct pci_dev *pci) | |||
1530 | } | 1530 | } |
1531 | 1531 | ||
1532 | static struct pci_driver driver = { | 1532 | static struct pci_driver driver = { |
1533 | .name = "S3 SonicVibes", | 1533 | .name = KBUILD_MODNAME, |
1534 | .id_table = snd_sonic_ids, | 1534 | .id_table = snd_sonic_ids, |
1535 | .probe = snd_sonic_probe, | 1535 | .probe = snd_sonic_probe, |
1536 | .remove = __devexit_p(snd_sonic_remove), | 1536 | .remove = __devexit_p(snd_sonic_remove), |
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index 6d0581841d7a..d8a128f6fc02 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
@@ -172,7 +172,7 @@ static void __devexit snd_trident_remove(struct pci_dev *pci) | |||
172 | } | 172 | } |
173 | 173 | ||
174 | static struct pci_driver driver = { | 174 | static struct pci_driver driver = { |
175 | .name = "Trident4DWaveAudio", | 175 | .name = KBUILD_MODNAME, |
176 | .id_table = snd_trident_ids, | 176 | .id_table = snd_trident_ids, |
177 | .probe = snd_trident_probe, | 177 | .probe = snd_trident_probe, |
178 | .remove = __devexit_p(snd_trident_remove), | 178 | .remove = __devexit_p(snd_trident_remove), |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 2870a4fdc130..5bd57a7c52d2 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -3598,7 +3598,7 @@ int __devinit snd_trident_create(struct snd_card *card, | |||
3598 | trident->port = pci_resource_start(pci, 0); | 3598 | trident->port = pci_resource_start(pci, 0); |
3599 | 3599 | ||
3600 | if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED, | 3600 | if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED, |
3601 | "Trident Audio", trident)) { | 3601 | KBUILD_MODNAME, trident)) { |
3602 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 3602 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
3603 | snd_trident_free(trident); | 3603 | snd_trident_free(trident); |
3604 | return -EBUSY; | 3604 | return -EBUSY; |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 8c5f8b5a59f0..f03fd620a2a0 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -2377,7 +2377,7 @@ static int __devinit snd_via82xx_create(struct snd_card *card, | |||
2377 | chip_type == TYPE_VIA8233 ? | 2377 | chip_type == TYPE_VIA8233 ? |
2378 | snd_via8233_interrupt : snd_via686_interrupt, | 2378 | snd_via8233_interrupt : snd_via686_interrupt, |
2379 | IRQF_SHARED, | 2379 | IRQF_SHARED, |
2380 | card->driver, chip)) { | 2380 | KBUILD_MODNAME, chip)) { |
2381 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 2381 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
2382 | snd_via82xx_free(chip); | 2382 | snd_via82xx_free(chip); |
2383 | return -EBUSY; | 2383 | return -EBUSY; |
@@ -2611,7 +2611,7 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci) | |||
2611 | } | 2611 | } |
2612 | 2612 | ||
2613 | static struct pci_driver driver = { | 2613 | static struct pci_driver driver = { |
2614 | .name = "VIA 82xx Audio", | 2614 | .name = KBUILD_MODNAME, |
2615 | .id_table = snd_via82xx_ids, | 2615 | .id_table = snd_via82xx_ids, |
2616 | .probe = snd_via82xx_probe, | 2616 | .probe = snd_via82xx_probe, |
2617 | .remove = __devexit_p(snd_via82xx_remove), | 2617 | .remove = __devexit_p(snd_via82xx_remove), |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index f7e8bbbe3953..a386dd9f6732 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -1129,7 +1129,7 @@ static int __devinit snd_via82xx_create(struct snd_card *card, | |||
1129 | } | 1129 | } |
1130 | chip->port = pci_resource_start(pci, 0); | 1130 | chip->port = pci_resource_start(pci, 0); |
1131 | if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_SHARED, | 1131 | if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_SHARED, |
1132 | card->driver, chip)) { | 1132 | KBUILD_MODNAME, chip)) { |
1133 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1133 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1134 | snd_via82xx_free(chip); | 1134 | snd_via82xx_free(chip); |
1135 | return -EBUSY; | 1135 | return -EBUSY; |
@@ -1224,7 +1224,7 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci) | |||
1224 | } | 1224 | } |
1225 | 1225 | ||
1226 | static struct pci_driver driver = { | 1226 | static struct pci_driver driver = { |
1227 | .name = "VIA 82xx Modem", | 1227 | .name = KBUILD_MODNAME, |
1228 | .id_table = snd_via82xx_modem_ids, | 1228 | .id_table = snd_via82xx_modem_ids, |
1229 | .probe = snd_via82xx_probe, | 1229 | .probe = snd_via82xx_probe, |
1230 | .remove = __devexit_p(snd_via82xx_remove), | 1230 | .remove = __devexit_p(snd_via82xx_remove), |
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index 99a9a814be0b..5342d5e1366a 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c | |||
@@ -169,7 +169,7 @@ static int __devinit snd_vx222_create(struct snd_card *card, struct pci_dev *pci | |||
169 | vx->port[i] = pci_resource_start(pci, i + 1); | 169 | vx->port[i] = pci_resource_start(pci, i + 1); |
170 | 170 | ||
171 | if (request_irq(pci->irq, snd_vx_irq_handler, IRQF_SHARED, | 171 | if (request_irq(pci->irq, snd_vx_irq_handler, IRQF_SHARED, |
172 | CARD_NAME, chip)) { | 172 | KBUILD_MODNAME, chip)) { |
173 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 173 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
174 | snd_vx222_free(chip); | 174 | snd_vx222_free(chip); |
175 | return -EBUSY; | 175 | return -EBUSY; |
@@ -290,7 +290,7 @@ static int snd_vx222_resume(struct pci_dev *pci) | |||
290 | #endif | 290 | #endif |
291 | 291 | ||
292 | static struct pci_driver driver = { | 292 | static struct pci_driver driver = { |
293 | .name = "Digigram VX222", | 293 | .name = KBUILD_MODNAME, |
294 | .id_table = snd_vx222_ids, | 294 | .id_table = snd_vx222_ids, |
295 | .probe = snd_vx222_probe, | 295 | .probe = snd_vx222_probe, |
296 | .remove = __devexit_p(snd_vx222_remove), | 296 | .remove = __devexit_p(snd_vx222_remove), |
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 80c682113381..511d57653124 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
@@ -345,7 +345,7 @@ static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci) | |||
345 | } | 345 | } |
346 | 346 | ||
347 | static struct pci_driver driver = { | 347 | static struct pci_driver driver = { |
348 | .name = "Yamaha DS-1 PCI", | 348 | .name = KBUILD_MODNAME, |
349 | .id_table = snd_ymfpci_ids, | 349 | .id_table = snd_ymfpci_ids, |
350 | .probe = snd_card_ymfpci_probe, | 350 | .probe = snd_card_ymfpci_probe, |
351 | .remove = __devexit_p(snd_card_ymfpci_remove), | 351 | .remove = __devexit_p(snd_card_ymfpci_remove), |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index c94c051ad0c8..f3260e658b8a 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -2380,7 +2380,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card, | |||
2380 | return -EBUSY; | 2380 | return -EBUSY; |
2381 | } | 2381 | } |
2382 | if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_SHARED, | 2382 | if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_SHARED, |
2383 | "YMFPCI", chip)) { | 2383 | KBUILD_MODNAME, chip)) { |
2384 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 2384 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
2385 | snd_ymfpci_free(chip); | 2385 | snd_ymfpci_free(chip); |
2386 | return -EBUSY; | 2386 | return -EBUSY; |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index ce33be0e4e98..66488a7a5706 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c | |||
@@ -223,7 +223,7 @@ static int pdacf_config(struct pcmcia_device *link) | |||
223 | if (ret) | 223 | if (ret) |
224 | goto failed; | 224 | goto failed; |
225 | 225 | ||
226 | ret = pcmcia_request_exclusive_irq(link, pdacf_interrupt); | 226 | ret = pcmcia_request_irq(link, pdacf_interrupt); |
227 | if (ret) | 227 | if (ret) |
228 | goto failed; | 228 | goto failed; |
229 | 229 | ||
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index d9ef21d8fa73..31777d1ea49f 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c | |||
@@ -229,7 +229,7 @@ static int vxpocket_config(struct pcmcia_device *link) | |||
229 | if (ret) | 229 | if (ret) |
230 | goto failed; | 230 | goto failed; |
231 | 231 | ||
232 | ret = pcmcia_request_exclusive_irq(link, snd_vx_irq_handler); | 232 | ret = pcmcia_request_irq(link, snd_vx_irq_handler); |
233 | if (ret) | 233 | if (ret) |
234 | goto failed; | 234 | goto failed; |
235 | 235 | ||
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 1ed61c5df2c5..4f913876f332 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o | 1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o |
2 | snd-soc-core-objs += soc-pcm.o soc-io.o | ||
2 | 3 | ||
3 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o | 4 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o |
4 | obj-$(CONFIG_SND_SOC) += codecs/ | 5 | obj-$(CONFIG_SND_SOC) += codecs/ |
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c index d0e75323ec19..f81d4c3f8956 100644 --- a/sound/soc/atmel/atmel-pcm.c +++ b/sound/soc/atmel/atmel-pcm.c | |||
@@ -364,9 +364,11 @@ static struct snd_pcm_ops atmel_pcm_ops = { | |||
364 | \*--------------------------------------------------------------------------*/ | 364 | \*--------------------------------------------------------------------------*/ |
365 | static u64 atmel_pcm_dmamask = 0xffffffff; | 365 | static u64 atmel_pcm_dmamask = 0xffffffff; |
366 | 366 | ||
367 | static int atmel_pcm_new(struct snd_card *card, | 367 | static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd) |
368 | struct snd_soc_dai *dai, struct snd_pcm *pcm) | ||
369 | { | 368 | { |
369 | struct snd_card *card = rtd->card->snd_card; | ||
370 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
371 | struct snd_pcm *pcm = rtd->pcm; | ||
370 | int ret = 0; | 372 | int ret = 0; |
371 | 373 | ||
372 | if (!card->dev->dma_mask) | 374 | if (!card->dev->dma_mask) |
@@ -382,7 +384,7 @@ static int atmel_pcm_new(struct snd_card *card, | |||
382 | } | 384 | } |
383 | 385 | ||
384 | if (dai->driver->capture.channels_min) { | 386 | if (dai->driver->capture.channels_min) { |
385 | pr_debug("at32-pcm:" | 387 | pr_debug("atmel-pcm:" |
386 | "Allocating PCM capture DMA buffer\n"); | 388 | "Allocating PCM capture DMA buffer\n"); |
387 | ret = atmel_pcm_preallocate_dma_buffer(pcm, | 389 | ret = atmel_pcm_preallocate_dma_buffer(pcm, |
388 | SNDRV_PCM_STREAM_CAPTURE); | 390 | SNDRV_PCM_STREAM_CAPTURE); |
diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h index 2597329302e7..5e0a95e64329 100644 --- a/sound/soc/atmel/atmel-pcm.h +++ b/sound/soc/atmel/atmel-pcm.h | |||
@@ -60,7 +60,7 @@ struct atmel_ssc_mask { | |||
60 | * This structure, shared between the PCM driver and the interface, | 60 | * This structure, shared between the PCM driver and the interface, |
61 | * contains all information required by the PCM driver to perform the | 61 | * contains all information required by the PCM driver to perform the |
62 | * PDC DMA operation. All fields except dma_intr_handler() are initialized | 62 | * PDC DMA operation. All fields except dma_intr_handler() are initialized |
63 | * by the interface. The dms_intr_handler() pointer is set by the PCM | 63 | * by the interface. The dma_intr_handler() pointer is set by the PCM |
64 | * driver and called by the interface SSC interrupt handler if it is | 64 | * driver and called by the interface SSC interrupt handler if it is |
65 | * non-NULL. | 65 | * non-NULL. |
66 | */ | 66 | */ |
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index eda955b15834..71225090c49f 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -402,7 +402,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
402 | if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S | 402 | if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S |
403 | && bits > 16) { | 403 | && bits > 16) { |
404 | printk(KERN_WARNING | 404 | printk(KERN_WARNING |
405 | "atmel_ssc_dai: sample size %d" | 405 | "atmel_ssc_dai: sample size %d " |
406 | "is too large for I2S\n", bits); | 406 | "is too large for I2S\n", bits); |
407 | return -EINVAL; | 407 | return -EINVAL; |
408 | } | 408 | } |
@@ -838,10 +838,8 @@ int atmel_ssc_set_audio(int ssc_id) | |||
838 | } | 838 | } |
839 | 839 | ||
840 | ssc_pdev = platform_device_alloc("atmel-ssc-dai", ssc_id); | 840 | ssc_pdev = platform_device_alloc("atmel-ssc-dai", ssc_id); |
841 | if (!ssc_pdev) { | 841 | if (!ssc_pdev) |
842 | ssc_free(ssc); | ||
843 | return -ENOMEM; | 842 | return -ENOMEM; |
844 | } | ||
845 | 843 | ||
846 | /* If we can grab the SSC briefly to parent the DAI device off it */ | 844 | /* If we can grab the SSC briefly to parent the DAI device off it */ |
847 | ssc = ssc_request(ssc_id); | 845 | ssc = ssc_request(ssc_id); |
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 95572d290c27..bad3aa14d5b3 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c | |||
@@ -92,6 +92,7 @@ static struct snd_soc_ops at91sam9g20ek_ops = { | |||
92 | }; | 92 | }; |
93 | 93 | ||
94 | static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, | 94 | static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, |
95 | struct snd_soc_dapm_context *dapm, | ||
95 | enum snd_soc_bias_level level) | 96 | enum snd_soc_bias_level level) |
96 | { | 97 | { |
97 | static int mclk_on; | 98 | static int mclk_on; |
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 10fdd2854e58..20bb53a837b1 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c | |||
@@ -319,10 +319,11 @@ static void au1xpsc_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
319 | snd_pcm_lib_preallocate_free_for_all(pcm); | 319 | snd_pcm_lib_preallocate_free_for_all(pcm); |
320 | } | 320 | } |
321 | 321 | ||
322 | static int au1xpsc_pcm_new(struct snd_card *card, | 322 | static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd) |
323 | struct snd_soc_dai *dai, | ||
324 | struct snd_pcm *pcm) | ||
325 | { | 323 | { |
324 | struct snd_card *card = rtd->card->snd_card; | ||
325 | struct snd_pcm *pcm = rtd->pcm; | ||
326 | |||
326 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 327 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
327 | card->dev, AU1XPSC_BUFFER_MIN_BYTES, (4096 * 1024) - 1); | 328 | card->dev, AU1XPSC_BUFFER_MIN_BYTES, (4096 * 1024) - 1); |
328 | 329 | ||
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index ae403597fd31..fe9d548a6837 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig | |||
@@ -10,13 +10,36 @@ config SND_BF5XX_I2S | |||
10 | 10 | ||
11 | config SND_BF5XX_SOC_SSM2602 | 11 | config SND_BF5XX_SOC_SSM2602 |
12 | tristate "SoC SSM2602 Audio support for BF52x ezkit" | 12 | tristate "SoC SSM2602 Audio support for BF52x ezkit" |
13 | depends on SND_BF5XX_I2S | 13 | depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) |
14 | select SND_BF5XX_SOC_I2S | 14 | select SND_BF5XX_SOC_I2S |
15 | select SND_SOC_SSM2602 | 15 | select SND_SOC_SSM2602 |
16 | select I2C | ||
17 | help | 16 | help |
18 | Say Y if you want to add support for SoC audio on BF527-EZKIT. | 17 | Say Y if you want to add support for SoC audio on BF527-EZKIT. |
19 | 18 | ||
19 | config SND_SOC_BFIN_EVAL_ADAU1701 | ||
20 | tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards" | ||
21 | depends on SND_BF5XX_I2S | ||
22 | select SND_BF5XX_SOC_I2S | ||
23 | select SND_SOC_ADAU1701 | ||
24 | select I2C | ||
25 | help | ||
26 | Say Y if you want to add support for the Analog Devices EVAL-ADAU1701MINIZ | ||
27 | board connected to one of the Blackfin evaluation boards like the | ||
28 | BF5XX-STAMP or BF5XX-EZKIT. | ||
29 | |||
30 | config SND_SOC_BFIN_EVAL_ADAV80X | ||
31 | tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards" | ||
32 | depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) | ||
33 | select SND_BF5XX_SOC_I2S | ||
34 | select SND_SOC_ADAV80X | ||
35 | help | ||
36 | Say Y if you want to add support for the Analog Devices EVAL-ADAV801 or | ||
37 | EVAL-ADAV803 board connected to one of the Blackfin evaluation boards | ||
38 | like the BF5XX-STAMP or BF5XX-EZKIT. | ||
39 | |||
40 | Note: This driver assumes that the ADAV80X digital record and playback | ||
41 | interfaces are connected to the first SPORT port on the BF5XX board. | ||
42 | |||
20 | config SND_BF5XX_SOC_AD73311 | 43 | config SND_BF5XX_SOC_AD73311 |
21 | tristate "SoC AD73311 Audio support for Blackfin" | 44 | tristate "SoC AD73311 Audio support for Blackfin" |
22 | depends on SND_BF5XX_I2S | 45 | depends on SND_BF5XX_I2S |
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile index 49af3f32aec8..6018bf52a234 100644 --- a/sound/soc/blackfin/Makefile +++ b/sound/soc/blackfin/Makefile | |||
@@ -21,9 +21,13 @@ snd-ad1980-objs := bf5xx-ad1980.o | |||
21 | snd-ssm2602-objs := bf5xx-ssm2602.o | 21 | snd-ssm2602-objs := bf5xx-ssm2602.o |
22 | snd-ad73311-objs := bf5xx-ad73311.o | 22 | snd-ad73311-objs := bf5xx-ad73311.o |
23 | snd-ad193x-objs := bf5xx-ad193x.o | 23 | snd-ad193x-objs := bf5xx-ad193x.o |
24 | snd-soc-bfin-eval-adau1701-objs := bfin-eval-adau1701.o | ||
25 | snd-soc-bfin-eval-adav80x-objs := bfin-eval-adav80x.o | ||
24 | 26 | ||
25 | obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o | 27 | obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o |
26 | obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o | 28 | obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o |
27 | obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o | 29 | obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o |
28 | obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o | 30 | obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o |
29 | obj-$(CONFIG_SND_BF5XX_SOC_AD193X) += snd-ad193x.o | 31 | obj-$(CONFIG_SND_BF5XX_SOC_AD193X) += snd-ad193x.o |
32 | obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) += snd-soc-bfin-eval-adau1701.o | ||
33 | obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) += snd-soc-bfin-eval-adav80x.o | ||
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 98b44b316e78..9e59f680bc19 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c | |||
@@ -418,9 +418,11 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
418 | 418 | ||
419 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | 419 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); |
420 | 420 | ||
421 | int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai, | 421 | int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd) |
422 | struct snd_pcm *pcm) | ||
423 | { | 422 | { |
423 | struct snd_card *card = rtd->card->snd_card; | ||
424 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
425 | struct snd_pcm *pcm = rtd->pcm; | ||
424 | int ret = 0; | 426 | int ret = 0; |
425 | 427 | ||
426 | pr_debug("%s enter\n", __func__); | 428 | pr_debug("%s enter\n", __func__); |
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index b5101efd1c87..61ddf942fd4d 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -138,11 +138,20 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
138 | pr_debug("%s enter\n", __func__); | 138 | pr_debug("%s enter\n", __func__); |
139 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 139 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
140 | diff = sport_curr_offset_tx(sport); | 140 | diff = sport_curr_offset_tx(sport); |
141 | frames = bytes_to_frames(substream->runtime, diff); | ||
142 | } else { | 141 | } else { |
143 | diff = sport_curr_offset_rx(sport); | 142 | diff = sport_curr_offset_rx(sport); |
144 | frames = bytes_to_frames(substream->runtime, diff); | ||
145 | } | 143 | } |
144 | |||
145 | /* | ||
146 | * TX at least can report one frame beyond the end of the | ||
147 | * buffer if we hit the wraparound case - clamp to within the | ||
148 | * buffer as the ALSA APIs require. | ||
149 | */ | ||
150 | if (diff == snd_pcm_lib_buffer_bytes(substream)) | ||
151 | diff = 0; | ||
152 | |||
153 | frames = bytes_to_frames(substream->runtime, diff); | ||
154 | |||
146 | return frames; | 155 | return frames; |
147 | } | 156 | } |
148 | 157 | ||
@@ -159,7 +168,7 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | |||
159 | 168 | ||
160 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); | 169 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); |
161 | 170 | ||
162 | ret = snd_pcm_hw_constraint_integer(runtime, \ | 171 | ret = snd_pcm_hw_constraint_integer(runtime, |
163 | SNDRV_PCM_HW_PARAM_PERIODS); | 172 | SNDRV_PCM_HW_PARAM_PERIODS); |
164 | if (ret < 0) | 173 | if (ret < 0) |
165 | goto out; | 174 | goto out; |
@@ -248,9 +257,11 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
248 | 257 | ||
249 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | 258 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); |
250 | 259 | ||
251 | int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai, | 260 | int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd) |
252 | struct snd_pcm *pcm) | ||
253 | { | 261 | { |
262 | struct snd_card *card = rtd->card->snd_card; | ||
263 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
264 | struct snd_pcm *pcm = rtd->pcm; | ||
254 | int ret = 0; | 265 | int ret = 0; |
255 | 266 | ||
256 | pr_debug("%s enter\n", __func__); | 267 | pr_debug("%s enter\n", __func__); |
@@ -295,8 +306,8 @@ static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev) | |||
295 | 306 | ||
296 | static struct platform_driver bfin_i2s_pcm_driver = { | 307 | static struct platform_driver bfin_i2s_pcm_driver = { |
297 | .driver = { | 308 | .driver = { |
298 | .name = "bfin-i2s-pcm-audio", | 309 | .name = "bfin-i2s-pcm-audio", |
299 | .owner = THIS_MODULE, | 310 | .owner = THIS_MODULE, |
300 | }, | 311 | }, |
301 | 312 | ||
302 | .probe = bfin_i2s_soc_platform_probe, | 313 | .probe = bfin_i2s_soc_platform_probe, |
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c index 07cfc7a9e49a..c95cc03d583d 100644 --- a/sound/soc/blackfin/bf5xx-tdm-pcm.c +++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c | |||
@@ -283,9 +283,11 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
283 | 283 | ||
284 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | 284 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); |
285 | 285 | ||
286 | static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai, | 286 | static int bf5xx_pcm_tdm_new(struct snd_soc_pcm_runtime *rtd) |
287 | struct snd_pcm *pcm) | ||
288 | { | 287 | { |
288 | struct snd_card *card = rtd->card->snd_card; | ||
289 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
290 | struct snd_pcm *pcm = rtd->pcm; | ||
289 | int ret = 0; | 291 | int ret = 0; |
290 | 292 | ||
291 | if (!card->dev->dma_mask) | 293 | if (!card->dev->dma_mask) |
diff --git a/sound/soc/blackfin/bfin-eval-adau1701.c b/sound/soc/blackfin/bfin-eval-adau1701.c new file mode 100644 index 000000000000..e5550acba2c2 --- /dev/null +++ b/sound/soc/blackfin/bfin-eval-adau1701.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * Machine driver for EVAL-ADAU1701MINIZ on Analog Devices bfin | ||
3 | * evaluation boards. | ||
4 | * | ||
5 | * Copyright 2011 Analog Devices Inc. | ||
6 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
7 | * | ||
8 | * Licensed under the GPL-2 or later. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <sound/core.h> | ||
14 | #include <sound/pcm.h> | ||
15 | #include <sound/soc.h> | ||
16 | #include <sound/pcm_params.h> | ||
17 | |||
18 | #include "../codecs/adau1701.h" | ||
19 | |||
20 | static const struct snd_soc_dapm_widget bfin_eval_adau1701_dapm_widgets[] = { | ||
21 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
22 | SND_SOC_DAPM_LINE("Line Out", NULL), | ||
23 | SND_SOC_DAPM_LINE("Line In", NULL), | ||
24 | }; | ||
25 | |||
26 | static const struct snd_soc_dapm_route bfin_eval_adau1701_dapm_routes[] = { | ||
27 | { "Speaker", NULL, "OUT0" }, | ||
28 | { "Speaker", NULL, "OUT1" }, | ||
29 | { "Line Out", NULL, "OUT2" }, | ||
30 | { "Line Out", NULL, "OUT3" }, | ||
31 | |||
32 | { "IN0", NULL, "Line In" }, | ||
33 | { "IN1", NULL, "Line In" }, | ||
34 | }; | ||
35 | |||
36 | static int bfin_eval_adau1701_hw_params(struct snd_pcm_substream *substream, | ||
37 | struct snd_pcm_hw_params *params) | ||
38 | { | ||
39 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
40 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
42 | int ret; | ||
43 | |||
44 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
45 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
46 | if (ret) | ||
47 | return ret; | ||
48 | |||
49 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
50 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
51 | if (ret) | ||
52 | return ret; | ||
53 | |||
54 | ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1701_CLK_SRC_OSC, 12288000, | ||
55 | SND_SOC_CLOCK_IN); | ||
56 | |||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | static struct snd_soc_ops bfin_eval_adau1701_ops = { | ||
61 | .hw_params = bfin_eval_adau1701_hw_params, | ||
62 | }; | ||
63 | |||
64 | static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = { | ||
65 | { | ||
66 | .name = "adau1701", | ||
67 | .stream_name = "adau1701", | ||
68 | .cpu_dai_name = "bfin-i2s.0", | ||
69 | .codec_dai_name = "adau1701", | ||
70 | .platform_name = "bfin-i2s-pcm-audio", | ||
71 | .codec_name = "adau1701.0-0034", | ||
72 | .ops = &bfin_eval_adau1701_ops, | ||
73 | }, | ||
74 | { | ||
75 | .name = "adau1701", | ||
76 | .stream_name = "adau1701", | ||
77 | .cpu_dai_name = "bfin-i2s.1", | ||
78 | .codec_dai_name = "adau1701", | ||
79 | .platform_name = "bfin-i2s-pcm-audio", | ||
80 | .codec_name = "adau1701.0-0034", | ||
81 | .ops = &bfin_eval_adau1701_ops, | ||
82 | }, | ||
83 | }; | ||
84 | |||
85 | static struct snd_soc_card bfin_eval_adau1701 = { | ||
86 | .name = "bfin-eval-adau1701", | ||
87 | .dai_link = &bfin_eval_adau1701_dai[CONFIG_SND_BF5XX_SPORT_NUM], | ||
88 | .num_links = 1, | ||
89 | |||
90 | .dapm_widgets = bfin_eval_adau1701_dapm_widgets, | ||
91 | .num_dapm_widgets = ARRAY_SIZE(bfin_eval_adau1701_dapm_widgets), | ||
92 | .dapm_routes = bfin_eval_adau1701_dapm_routes, | ||
93 | .num_dapm_routes = ARRAY_SIZE(bfin_eval_adau1701_dapm_routes), | ||
94 | }; | ||
95 | |||
96 | static int bfin_eval_adau1701_probe(struct platform_device *pdev) | ||
97 | { | ||
98 | struct snd_soc_card *card = &bfin_eval_adau1701; | ||
99 | |||
100 | card->dev = &pdev->dev; | ||
101 | |||
102 | return snd_soc_register_card(&bfin_eval_adau1701); | ||
103 | } | ||
104 | |||
105 | static int __devexit bfin_eval_adau1701_remove(struct platform_device *pdev) | ||
106 | { | ||
107 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
108 | |||
109 | snd_soc_unregister_card(card); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static struct platform_driver bfin_eval_adau1701_driver = { | ||
115 | .driver = { | ||
116 | .name = "bfin-eval-adau1701", | ||
117 | .owner = THIS_MODULE, | ||
118 | .pm = &snd_soc_pm_ops, | ||
119 | }, | ||
120 | .probe = bfin_eval_adau1701_probe, | ||
121 | .remove = __devexit_p(bfin_eval_adau1701_remove), | ||
122 | }; | ||
123 | |||
124 | static int __init bfin_eval_adau1701_init(void) | ||
125 | { | ||
126 | return platform_driver_register(&bfin_eval_adau1701_driver); | ||
127 | } | ||
128 | module_init(bfin_eval_adau1701_init); | ||
129 | |||
130 | static void __exit bfin_eval_adau1701_exit(void) | ||
131 | { | ||
132 | platform_driver_unregister(&bfin_eval_adau1701_driver); | ||
133 | } | ||
134 | module_exit(bfin_eval_adau1701_exit); | ||
135 | |||
136 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
137 | MODULE_DESCRIPTION("ALSA SoC bfin ADAU1701 driver"); | ||
138 | MODULE_LICENSE("GPL"); | ||
139 | MODULE_ALIAS("platform:bfin-eval-adau1701"); | ||
diff --git a/sound/soc/blackfin/bfin-eval-adav80x.c b/sound/soc/blackfin/bfin-eval-adav80x.c new file mode 100644 index 000000000000..8d014d01626e --- /dev/null +++ b/sound/soc/blackfin/bfin-eval-adav80x.c | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | * Machine driver for EVAL-ADAV801 and EVAL-ADAV803 on Analog Devices bfin | ||
3 | * evaluation boards. | ||
4 | * | ||
5 | * Copyright 2011 Analog Devices Inc. | ||
6 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
7 | * | ||
8 | * Licensed under the GPL-2 or later. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <sound/core.h> | ||
14 | #include <sound/pcm.h> | ||
15 | #include <sound/soc.h> | ||
16 | |||
17 | #include "../codecs/adav80x.h" | ||
18 | |||
19 | static const struct snd_soc_dapm_widget bfin_eval_adav80x_dapm_widgets[] = { | ||
20 | SND_SOC_DAPM_LINE("Line Out", NULL), | ||
21 | SND_SOC_DAPM_LINE("Line In", NULL), | ||
22 | }; | ||
23 | |||
24 | static const struct snd_soc_dapm_route bfin_eval_adav80x_dapm_routes[] = { | ||
25 | { "Line Out", NULL, "VOUTL" }, | ||
26 | { "Line Out", NULL, "VOUTR" }, | ||
27 | |||
28 | { "VINL", NULL, "Line In" }, | ||
29 | { "VINR", NULL, "Line In" }, | ||
30 | }; | ||
31 | |||
32 | static int bfin_eval_adav80x_hw_params(struct snd_pcm_substream *substream, | ||
33 | struct snd_pcm_hw_params *params) | ||
34 | { | ||
35 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
36 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
37 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
38 | int ret; | ||
39 | |||
40 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
41 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
42 | if (ret) | ||
43 | return ret; | ||
44 | |||
45 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
46 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
47 | if (ret) | ||
48 | return ret; | ||
49 | |||
50 | ret = snd_soc_dai_set_pll(codec_dai, ADAV80X_PLL1, ADAV80X_PLL_SRC_XTAL, | ||
51 | 27000000, params_rate(params) * 256); | ||
52 | if (ret) | ||
53 | return ret; | ||
54 | |||
55 | ret = snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_PLL1, | ||
56 | params_rate(params) * 256, SND_SOC_CLOCK_IN); | ||
57 | |||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | static int bfin_eval_adav80x_codec_init(struct snd_soc_pcm_runtime *rtd) | ||
62 | { | ||
63 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
64 | |||
65 | snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_SYSCLK1, 0, | ||
66 | SND_SOC_CLOCK_OUT); | ||
67 | snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_SYSCLK2, 0, | ||
68 | SND_SOC_CLOCK_OUT); | ||
69 | snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_SYSCLK3, 0, | ||
70 | SND_SOC_CLOCK_OUT); | ||
71 | |||
72 | snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_XTAL, 2700000, 0); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static struct snd_soc_ops bfin_eval_adav80x_ops = { | ||
78 | .hw_params = bfin_eval_adav80x_hw_params, | ||
79 | }; | ||
80 | |||
81 | static struct snd_soc_dai_link bfin_eval_adav80x_dais[] = { | ||
82 | { | ||
83 | .name = "adav80x", | ||
84 | .stream_name = "ADAV80x HiFi", | ||
85 | .cpu_dai_name = "bfin-i2s.0", | ||
86 | .codec_dai_name = "adav80x-hifi", | ||
87 | .platform_name = "bfin-i2s-pcm-audio", | ||
88 | .init = bfin_eval_adav80x_codec_init, | ||
89 | .ops = &bfin_eval_adav80x_ops, | ||
90 | }, | ||
91 | }; | ||
92 | |||
93 | static struct snd_soc_card bfin_eval_adav80x = { | ||
94 | .name = "bfin-eval-adav80x", | ||
95 | .dai_link = bfin_eval_adav80x_dais, | ||
96 | .num_links = ARRAY_SIZE(bfin_eval_adav80x_dais), | ||
97 | |||
98 | .dapm_widgets = bfin_eval_adav80x_dapm_widgets, | ||
99 | .num_dapm_widgets = ARRAY_SIZE(bfin_eval_adav80x_dapm_widgets), | ||
100 | .dapm_routes = bfin_eval_adav80x_dapm_routes, | ||
101 | .num_dapm_routes = ARRAY_SIZE(bfin_eval_adav80x_dapm_routes), | ||
102 | }; | ||
103 | |||
104 | enum bfin_eval_adav80x_type { | ||
105 | BFIN_EVAL_ADAV801, | ||
106 | BFIN_EVAL_ADAV803, | ||
107 | }; | ||
108 | |||
109 | static int bfin_eval_adav80x_probe(struct platform_device *pdev) | ||
110 | { | ||
111 | struct snd_soc_card *card = &bfin_eval_adav80x; | ||
112 | const char *codec_name; | ||
113 | |||
114 | switch (platform_get_device_id(pdev)->driver_data) { | ||
115 | case BFIN_EVAL_ADAV801: | ||
116 | codec_name = "spi0.1"; | ||
117 | break; | ||
118 | case BFIN_EVAL_ADAV803: | ||
119 | codec_name = "adav803.0-0034"; | ||
120 | break; | ||
121 | default: | ||
122 | return -EINVAL; | ||
123 | } | ||
124 | |||
125 | bfin_eval_adav80x_dais[0].codec_name = codec_name; | ||
126 | |||
127 | card->dev = &pdev->dev; | ||
128 | |||
129 | return snd_soc_register_card(&bfin_eval_adav80x); | ||
130 | } | ||
131 | |||
132 | static int __devexit bfin_eval_adav80x_remove(struct platform_device *pdev) | ||
133 | { | ||
134 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
135 | |||
136 | snd_soc_unregister_card(card); | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static const struct platform_device_id bfin_eval_adav80x_ids[] = { | ||
142 | { "bfin-eval-adav801", BFIN_EVAL_ADAV801 }, | ||
143 | { "bfin-eval-adav803", BFIN_EVAL_ADAV803 }, | ||
144 | { }, | ||
145 | }; | ||
146 | MODULE_DEVICE_TABLE(platform, bfin_eval_adav80x_ids); | ||
147 | |||
148 | static struct platform_driver bfin_eval_adav80x_driver = { | ||
149 | .driver = { | ||
150 | .name = "bfin-eval-adav80x", | ||
151 | .owner = THIS_MODULE, | ||
152 | .pm = &snd_soc_pm_ops, | ||
153 | }, | ||
154 | .probe = bfin_eval_adav80x_probe, | ||
155 | .remove = __devexit_p(bfin_eval_adav80x_remove), | ||
156 | .id_table = bfin_eval_adav80x_ids, | ||
157 | }; | ||
158 | |||
159 | static int __init bfin_eval_adav80x_init(void) | ||
160 | { | ||
161 | return platform_driver_register(&bfin_eval_adav80x_driver); | ||
162 | } | ||
163 | module_init(bfin_eval_adav80x_init); | ||
164 | |||
165 | static void __exit bfin_eval_adav80x_exit(void) | ||
166 | { | ||
167 | platform_driver_unregister(&bfin_eval_adav80x_driver); | ||
168 | } | ||
169 | module_exit(bfin_eval_adav80x_exit); | ||
170 | |||
171 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
172 | MODULE_DESCRIPTION("ALSA SoC bfin adav80x driver"); | ||
173 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 98175a096df2..36a030f1d1f5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -17,6 +17,7 @@ config SND_SOC_ALL_CODECS | |||
17 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI | 17 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI |
18 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS | 18 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS |
19 | select SND_SOC_AD73311 | 19 | select SND_SOC_AD73311 |
20 | select SND_SOC_ADAV80X | ||
20 | select SND_SOC_ADS117X | 21 | select SND_SOC_ADS117X |
21 | select SND_SOC_AK4104 if SPI_MASTER | 22 | select SND_SOC_AK4104 if SPI_MASTER |
22 | select SND_SOC_AK4535 if I2C | 23 | select SND_SOC_AK4535 if I2C |
@@ -42,6 +43,7 @@ config SND_SOC_ALL_CODECS | |||
42 | select SND_SOC_SN95031 if INTEL_SCU_IPC | 43 | select SND_SOC_SN95031 if INTEL_SCU_IPC |
43 | select SND_SOC_SPDIF | 44 | select SND_SOC_SPDIF |
44 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI | 45 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI |
46 | select SND_SOC_STA32X if I2C | ||
45 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS | 47 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
46 | select SND_SOC_TLV320AIC23 if I2C | 48 | select SND_SOC_TLV320AIC23 if I2C |
47 | select SND_SOC_TLV320AIC26 if SPI_MASTER | 49 | select SND_SOC_TLV320AIC26 if SPI_MASTER |
@@ -71,6 +73,7 @@ config SND_SOC_ALL_CODECS | |||
71 | select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI | 73 | select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI |
72 | select SND_SOC_WM8770 if SPI_MASTER | 74 | select SND_SOC_WM8770 if SPI_MASTER |
73 | select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI | 75 | select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI |
76 | select SND_SOC_WM8782 | ||
74 | select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI | 77 | select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI |
75 | select SND_SOC_WM8900 if I2C | 78 | select SND_SOC_WM8900 if I2C |
76 | select SND_SOC_WM8903 if I2C | 79 | select SND_SOC_WM8903 if I2C |
@@ -84,6 +87,7 @@ config SND_SOC_ALL_CODECS | |||
84 | select SND_SOC_WM8971 if I2C | 87 | select SND_SOC_WM8971 if I2C |
85 | select SND_SOC_WM8974 if I2C | 88 | select SND_SOC_WM8974 if I2C |
86 | select SND_SOC_WM8978 if I2C | 89 | select SND_SOC_WM8978 if I2C |
90 | select SND_SOC_WM8983 if SND_SOC_I2C_AND_SPI | ||
87 | select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI | 91 | select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI |
88 | select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI | 92 | select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI |
89 | select SND_SOC_WM8990 if I2C | 93 | select SND_SOC_WM8990 if I2C |
@@ -130,7 +134,14 @@ config SND_SOC_AD1980 | |||
130 | 134 | ||
131 | config SND_SOC_AD73311 | 135 | config SND_SOC_AD73311 |
132 | tristate | 136 | tristate |
133 | 137 | ||
138 | config SND_SOC_ADAU1701 | ||
139 | select SIGMA | ||
140 | tristate | ||
141 | |||
142 | config SND_SOC_ADAV80X | ||
143 | tristate | ||
144 | |||
134 | config SND_SOC_ADS117X | 145 | config SND_SOC_ADS117X |
135 | tristate | 146 | tristate |
136 | 147 | ||
@@ -216,6 +227,9 @@ config SND_SOC_SPDIF | |||
216 | config SND_SOC_SSM2602 | 227 | config SND_SOC_SSM2602 |
217 | tristate | 228 | tristate |
218 | 229 | ||
230 | config SND_SOC_STA32X | ||
231 | tristate | ||
232 | |||
219 | config SND_SOC_STAC9766 | 233 | config SND_SOC_STAC9766 |
220 | tristate | 234 | tristate |
221 | 235 | ||
@@ -299,6 +313,9 @@ config SND_SOC_WM8770 | |||
299 | config SND_SOC_WM8776 | 313 | config SND_SOC_WM8776 |
300 | tristate | 314 | tristate |
301 | 315 | ||
316 | config SND_SOC_WM8782 | ||
317 | tristate | ||
318 | |||
302 | config SND_SOC_WM8804 | 319 | config SND_SOC_WM8804 |
303 | tristate | 320 | tristate |
304 | 321 | ||
@@ -338,6 +355,9 @@ config SND_SOC_WM8974 | |||
338 | config SND_SOC_WM8978 | 355 | config SND_SOC_WM8978 |
339 | tristate | 356 | tristate |
340 | 357 | ||
358 | config SND_SOC_WM8983 | ||
359 | tristate | ||
360 | |||
341 | config SND_SOC_WM8985 | 361 | config SND_SOC_WM8985 |
342 | tristate | 362 | tristate |
343 | 363 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index fd8558406ef0..da9990fb8569 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -4,6 +4,8 @@ snd-soc-ad1836-objs := ad1836.o | |||
4 | snd-soc-ad193x-objs := ad193x.o | 4 | snd-soc-ad193x-objs := ad193x.o |
5 | snd-soc-ad1980-objs := ad1980.o | 5 | snd-soc-ad1980-objs := ad1980.o |
6 | snd-soc-ad73311-objs := ad73311.o | 6 | snd-soc-ad73311-objs := ad73311.o |
7 | snd-soc-adau1701-objs := adau1701.o | ||
8 | snd-soc-adav80x-objs := adav80x.o | ||
7 | snd-soc-ads117x-objs := ads117x.o | 9 | snd-soc-ads117x-objs := ads117x.o |
8 | snd-soc-ak4104-objs := ak4104.o | 10 | snd-soc-ak4104-objs := ak4104.o |
9 | snd-soc-ak4535-objs := ak4535.o | 11 | snd-soc-ak4535-objs := ak4535.o |
@@ -28,6 +30,7 @@ snd-soc-alc5623-objs := alc5623.o | |||
28 | snd-soc-sn95031-objs := sn95031.o | 30 | snd-soc-sn95031-objs := sn95031.o |
29 | snd-soc-spdif-objs := spdif_transciever.o | 31 | snd-soc-spdif-objs := spdif_transciever.o |
30 | snd-soc-ssm2602-objs := ssm2602.o | 32 | snd-soc-ssm2602-objs := ssm2602.o |
33 | snd-soc-sta32x-objs := sta32x.o | ||
31 | snd-soc-stac9766-objs := stac9766.o | 34 | snd-soc-stac9766-objs := stac9766.o |
32 | snd-soc-tlv320aic23-objs := tlv320aic23.o | 35 | snd-soc-tlv320aic23-objs := tlv320aic23.o |
33 | snd-soc-tlv320aic26-objs := tlv320aic26.o | 36 | snd-soc-tlv320aic26-objs := tlv320aic26.o |
@@ -55,6 +58,7 @@ snd-soc-wm8750-objs := wm8750.o | |||
55 | snd-soc-wm8753-objs := wm8753.o | 58 | snd-soc-wm8753-objs := wm8753.o |
56 | snd-soc-wm8770-objs := wm8770.o | 59 | snd-soc-wm8770-objs := wm8770.o |
57 | snd-soc-wm8776-objs := wm8776.o | 60 | snd-soc-wm8776-objs := wm8776.o |
61 | snd-soc-wm8782-objs := wm8782.o | ||
58 | snd-soc-wm8804-objs := wm8804.o | 62 | snd-soc-wm8804-objs := wm8804.o |
59 | snd-soc-wm8900-objs := wm8900.o | 63 | snd-soc-wm8900-objs := wm8900.o |
60 | snd-soc-wm8903-objs := wm8903.o | 64 | snd-soc-wm8903-objs := wm8903.o |
@@ -68,6 +72,7 @@ snd-soc-wm8962-objs := wm8962.o | |||
68 | snd-soc-wm8971-objs := wm8971.o | 72 | snd-soc-wm8971-objs := wm8971.o |
69 | snd-soc-wm8974-objs := wm8974.o | 73 | snd-soc-wm8974-objs := wm8974.o |
70 | snd-soc-wm8978-objs := wm8978.o | 74 | snd-soc-wm8978-objs := wm8978.o |
75 | snd-soc-wm8983-objs := wm8983.o | ||
71 | snd-soc-wm8985-objs := wm8985.o | 76 | snd-soc-wm8985-objs := wm8985.o |
72 | snd-soc-wm8988-objs := wm8988.o | 77 | snd-soc-wm8988-objs := wm8988.o |
73 | snd-soc-wm8990-objs := wm8990.o | 78 | snd-soc-wm8990-objs := wm8990.o |
@@ -95,6 +100,8 @@ obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o | |||
95 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o | 100 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o |
96 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o | 101 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o |
97 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | 102 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o |
103 | obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o | ||
104 | obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o | ||
98 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o | 105 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o |
99 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o | 106 | obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o |
100 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o | 107 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o |
@@ -120,6 +127,7 @@ obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o | |||
120 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o | 127 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o |
121 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o | 128 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o |
122 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | 129 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
130 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o | ||
123 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o | 131 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o |
124 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o | 132 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
125 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o | 133 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o |
@@ -147,6 +155,7 @@ obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o | |||
147 | obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o | 155 | obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o |
148 | obj-$(CONFIG_SND_SOC_WM8770) += snd-soc-wm8770.o | 156 | obj-$(CONFIG_SND_SOC_WM8770) += snd-soc-wm8770.o |
149 | obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o | 157 | obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o |
158 | obj-$(CONFIG_SND_SOC_WM8782) += snd-soc-wm8782.o | ||
150 | obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o | 159 | obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o |
151 | obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o | 160 | obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o |
152 | obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o | 161 | obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o |
@@ -160,6 +169,7 @@ obj-$(CONFIG_SND_SOC_WM8962) += snd-soc-wm8962.o | |||
160 | obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o | 169 | obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o |
161 | obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o | 170 | obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o |
162 | obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o | 171 | obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o |
172 | obj-$(CONFIG_SND_SOC_WM8983) += snd-soc-wm8983.o | ||
163 | obj-$(CONFIG_SND_SOC_WM8985) += snd-soc-wm8985.o | 173 | obj-$(CONFIG_SND_SOC_WM8985) += snd-soc-wm8985.o |
164 | obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o | 174 | obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o |
165 | obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o | 175 | obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o |
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 754c496412bd..4e5c5726366b 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -1,19 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * File: sound/soc/codecs/ad1836.c | 2 | * Audio Codec driver supporting: |
3 | * Author: Barry Song <Barry.Song@analog.com> | 3 | * AD1835A, AD1836, AD1837A, AD1838A, AD1839A |
4 | * | ||
5 | * Created: Aug 04 2009 | ||
6 | * Description: Driver for AD1836 sound chip | ||
7 | * | ||
8 | * Modified: | ||
9 | * Copyright 2009 Analog Devices Inc. | ||
10 | * | 4 | * |
11 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 5 | * Copyright 2009-2011 Analog Devices Inc. |
12 | * | 6 | * |
13 | * This program is free software; you can redistribute it and/or modify | 7 | * Licensed under the GPL-2 or later. |
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | */ | 8 | */ |
18 | 9 | ||
19 | #include <linux/init.h> | 10 | #include <linux/init.h> |
@@ -30,10 +21,15 @@ | |||
30 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
31 | #include "ad1836.h" | 22 | #include "ad1836.h" |
32 | 23 | ||
24 | enum ad1836_type { | ||
25 | AD1835, | ||
26 | AD1836, | ||
27 | AD1838, | ||
28 | }; | ||
29 | |||
33 | /* codec private data */ | 30 | /* codec private data */ |
34 | struct ad1836_priv { | 31 | struct ad1836_priv { |
35 | enum snd_soc_control_type control_type; | 32 | enum ad1836_type type; |
36 | void *control_data; | ||
37 | }; | 33 | }; |
38 | 34 | ||
39 | /* | 35 | /* |
@@ -44,29 +40,60 @@ static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"}; | |||
44 | static const struct soc_enum ad1836_deemp_enum = | 40 | static const struct soc_enum ad1836_deemp_enum = |
45 | SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp); | 41 | SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp); |
46 | 42 | ||
47 | static const struct snd_kcontrol_new ad1836_snd_controls[] = { | 43 | #define AD1836_DAC_VOLUME(x) \ |
48 | /* DAC volume control */ | 44 | SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \ |
49 | SOC_DOUBLE_R("DAC1 Volume", AD1836_DAC_L1_VOL, | 45 | AD1836_DAC_R_VOL(x), 0, 0x3FF, 0) |
50 | AD1836_DAC_R1_VOL, 0, 0x3FF, 0), | 46 | |
51 | SOC_DOUBLE_R("DAC2 Volume", AD1836_DAC_L2_VOL, | 47 | #define AD1836_DAC_SWITCH(x) \ |
52 | AD1836_DAC_R2_VOL, 0, 0x3FF, 0), | 48 | SOC_DOUBLE("DAC" #x " Playback Switch", AD1836_DAC_CTRL2, \ |
53 | SOC_DOUBLE_R("DAC3 Volume", AD1836_DAC_L3_VOL, | 49 | AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1) |
54 | AD1836_DAC_R3_VOL, 0, 0x3FF, 0), | 50 | |
55 | 51 | #define AD1836_ADC_SWITCH(x) \ | |
56 | /* ADC switch control */ | 52 | SOC_DOUBLE("ADC" #x " Capture Switch", AD1836_ADC_CTRL2, \ |
57 | SOC_DOUBLE("ADC1 Switch", AD1836_ADC_CTRL2, AD1836_ADCL1_MUTE, | 53 | AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1) |
58 | AD1836_ADCR1_MUTE, 1, 1), | 54 | |
59 | SOC_DOUBLE("ADC2 Switch", AD1836_ADC_CTRL2, AD1836_ADCL2_MUTE, | 55 | static const struct snd_kcontrol_new ad183x_dac_controls[] = { |
60 | AD1836_ADCR2_MUTE, 1, 1), | 56 | AD1836_DAC_VOLUME(1), |
61 | 57 | AD1836_DAC_SWITCH(1), | |
62 | /* DAC switch control */ | 58 | AD1836_DAC_VOLUME(2), |
63 | SOC_DOUBLE("DAC1 Switch", AD1836_DAC_CTRL2, AD1836_DACL1_MUTE, | 59 | AD1836_DAC_SWITCH(2), |
64 | AD1836_DACR1_MUTE, 1, 1), | 60 | AD1836_DAC_VOLUME(3), |
65 | SOC_DOUBLE("DAC2 Switch", AD1836_DAC_CTRL2, AD1836_DACL2_MUTE, | 61 | AD1836_DAC_SWITCH(3), |
66 | AD1836_DACR2_MUTE, 1, 1), | 62 | AD1836_DAC_VOLUME(4), |
67 | SOC_DOUBLE("DAC3 Switch", AD1836_DAC_CTRL2, AD1836_DACL3_MUTE, | 63 | AD1836_DAC_SWITCH(4), |
68 | AD1836_DACR3_MUTE, 1, 1), | 64 | }; |
65 | |||
66 | static const struct snd_soc_dapm_widget ad183x_dac_dapm_widgets[] = { | ||
67 | SND_SOC_DAPM_OUTPUT("DAC1OUT"), | ||
68 | SND_SOC_DAPM_OUTPUT("DAC2OUT"), | ||
69 | SND_SOC_DAPM_OUTPUT("DAC3OUT"), | ||
70 | SND_SOC_DAPM_OUTPUT("DAC4OUT"), | ||
71 | }; | ||
72 | |||
73 | static const struct snd_soc_dapm_route ad183x_dac_routes[] = { | ||
74 | { "DAC1OUT", NULL, "DAC" }, | ||
75 | { "DAC2OUT", NULL, "DAC" }, | ||
76 | { "DAC3OUT", NULL, "DAC" }, | ||
77 | { "DAC4OUT", NULL, "DAC" }, | ||
78 | }; | ||
79 | |||
80 | static const struct snd_kcontrol_new ad183x_adc_controls[] = { | ||
81 | AD1836_ADC_SWITCH(1), | ||
82 | AD1836_ADC_SWITCH(2), | ||
83 | AD1836_ADC_SWITCH(3), | ||
84 | }; | ||
85 | |||
86 | static const struct snd_soc_dapm_widget ad183x_adc_dapm_widgets[] = { | ||
87 | SND_SOC_DAPM_INPUT("ADC1IN"), | ||
88 | SND_SOC_DAPM_INPUT("ADC2IN"), | ||
89 | }; | ||
90 | |||
91 | static const struct snd_soc_dapm_route ad183x_adc_routes[] = { | ||
92 | { "ADC", NULL, "ADC1IN" }, | ||
93 | { "ADC", NULL, "ADC2IN" }, | ||
94 | }; | ||
69 | 95 | ||
96 | static const struct snd_kcontrol_new ad183x_controls[] = { | ||
70 | /* ADC high-pass filter */ | 97 | /* ADC high-pass filter */ |
71 | SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1, | 98 | SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1, |
72 | AD1836_ADC_HIGHPASS_FILTER, 1, 0), | 99 | AD1836_ADC_HIGHPASS_FILTER, 1, 0), |
@@ -75,27 +102,24 @@ static const struct snd_kcontrol_new ad1836_snd_controls[] = { | |||
75 | SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum), | 102 | SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum), |
76 | }; | 103 | }; |
77 | 104 | ||
78 | static const struct snd_soc_dapm_widget ad1836_dapm_widgets[] = { | 105 | static const struct snd_soc_dapm_widget ad183x_dapm_widgets[] = { |
79 | SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1, | 106 | SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1, |
80 | AD1836_DAC_POWERDOWN, 1), | 107 | AD1836_DAC_POWERDOWN, 1), |
81 | SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), | 108 | SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), |
82 | SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1, | 109 | SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1, |
83 | AD1836_ADC_POWERDOWN, 1, NULL, 0), | 110 | AD1836_ADC_POWERDOWN, 1, NULL, 0), |
84 | SND_SOC_DAPM_OUTPUT("DAC1OUT"), | ||
85 | SND_SOC_DAPM_OUTPUT("DAC2OUT"), | ||
86 | SND_SOC_DAPM_OUTPUT("DAC3OUT"), | ||
87 | SND_SOC_DAPM_INPUT("ADC1IN"), | ||
88 | SND_SOC_DAPM_INPUT("ADC2IN"), | ||
89 | }; | 111 | }; |
90 | 112 | ||
91 | static const struct snd_soc_dapm_route audio_paths[] = { | 113 | static const struct snd_soc_dapm_route ad183x_dapm_routes[] = { |
92 | { "DAC", NULL, "ADC_PWR" }, | 114 | { "DAC", NULL, "ADC_PWR" }, |
93 | { "ADC", NULL, "ADC_PWR" }, | 115 | { "ADC", NULL, "ADC_PWR" }, |
94 | { "DAC1OUT", "DAC1 Switch", "DAC" }, | 116 | }; |
95 | { "DAC2OUT", "DAC2 Switch", "DAC" }, | 117 | |
96 | { "DAC3OUT", "DAC3 Switch", "DAC" }, | 118 | static const DECLARE_TLV_DB_SCALE(ad1836_in_tlv, 0, 300, 0); |
97 | { "ADC", "ADC1 Switch", "ADC1IN" }, | 119 | |
98 | { "ADC", "ADC2 Switch", "ADC2IN" }, | 120 | static const struct snd_kcontrol_new ad1836_controls[] = { |
121 | SOC_DOUBLE_TLV("ADC2 Capture Volume", AD1836_ADC_CTRL1, 3, 0, 4, 0, | ||
122 | ad1836_in_tlv), | ||
99 | }; | 123 | }; |
100 | 124 | ||
101 | /* | 125 | /* |
@@ -165,64 +189,69 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
165 | return 0; | 189 | return 0; |
166 | } | 190 | } |
167 | 191 | ||
192 | static struct snd_soc_dai_ops ad1836_dai_ops = { | ||
193 | .hw_params = ad1836_hw_params, | ||
194 | .set_fmt = ad1836_set_dai_fmt, | ||
195 | }; | ||
196 | |||
197 | #define AD183X_DAI(_name, num_dacs, num_adcs) \ | ||
198 | { \ | ||
199 | .name = _name "-hifi", \ | ||
200 | .playback = { \ | ||
201 | .stream_name = "Playback", \ | ||
202 | .channels_min = 2, \ | ||
203 | .channels_max = (num_dacs) * 2, \ | ||
204 | .rates = SNDRV_PCM_RATE_48000, \ | ||
205 | .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
206 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \ | ||
207 | }, \ | ||
208 | .capture = { \ | ||
209 | .stream_name = "Capture", \ | ||
210 | .channels_min = 2, \ | ||
211 | .channels_max = (num_adcs) * 2, \ | ||
212 | .rates = SNDRV_PCM_RATE_48000, \ | ||
213 | .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
214 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \ | ||
215 | }, \ | ||
216 | .ops = &ad1836_dai_ops, \ | ||
217 | } | ||
218 | |||
219 | static struct snd_soc_dai_driver ad183x_dais[] = { | ||
220 | [AD1835] = AD183X_DAI("ad1835", 4, 1), | ||
221 | [AD1836] = AD183X_DAI("ad1836", 3, 2), | ||
222 | [AD1838] = AD183X_DAI("ad1838", 3, 1), | ||
223 | }; | ||
224 | |||
168 | #ifdef CONFIG_PM | 225 | #ifdef CONFIG_PM |
169 | static int ad1836_soc_suspend(struct snd_soc_codec *codec, | 226 | static int ad1836_suspend(struct snd_soc_codec *codec, pm_message_t state) |
170 | pm_message_t state) | ||
171 | { | 227 | { |
172 | /* reset clock control mode */ | 228 | /* reset clock control mode */ |
173 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); | 229 | return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, |
174 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; | 230 | AD1836_ADC_SERFMT_MASK, 0); |
175 | |||
176 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); | ||
177 | } | 231 | } |
178 | 232 | ||
179 | static int ad1836_soc_resume(struct snd_soc_codec *codec) | 233 | static int ad1836_resume(struct snd_soc_codec *codec) |
180 | { | 234 | { |
181 | /* restore clock control mode */ | 235 | /* restore clock control mode */ |
182 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); | 236 | return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, |
183 | adc_ctrl2 |= AD1836_ADC_AUX; | 237 | AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX); |
184 | |||
185 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); | ||
186 | } | 238 | } |
187 | #else | 239 | #else |
188 | #define ad1836_soc_suspend NULL | 240 | #define ad1836_suspend NULL |
189 | #define ad1836_soc_resume NULL | 241 | #define ad1836_resume NULL |
190 | #endif | 242 | #endif |
191 | 243 | ||
192 | static struct snd_soc_dai_ops ad1836_dai_ops = { | ||
193 | .hw_params = ad1836_hw_params, | ||
194 | .set_fmt = ad1836_set_dai_fmt, | ||
195 | }; | ||
196 | |||
197 | /* codec DAI instance */ | ||
198 | static struct snd_soc_dai_driver ad1836_dai = { | ||
199 | .name = "ad1836-hifi", | ||
200 | .playback = { | ||
201 | .stream_name = "Playback", | ||
202 | .channels_min = 2, | ||
203 | .channels_max = 6, | ||
204 | .rates = SNDRV_PCM_RATE_48000, | ||
205 | .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | | ||
206 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
207 | }, | ||
208 | .capture = { | ||
209 | .stream_name = "Capture", | ||
210 | .channels_min = 2, | ||
211 | .channels_max = 4, | ||
212 | .rates = SNDRV_PCM_RATE_48000, | ||
213 | .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | | ||
214 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, | ||
215 | }, | ||
216 | .ops = &ad1836_dai_ops, | ||
217 | }; | ||
218 | |||
219 | static int ad1836_probe(struct snd_soc_codec *codec) | 244 | static int ad1836_probe(struct snd_soc_codec *codec) |
220 | { | 245 | { |
221 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); | 246 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); |
222 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 247 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
248 | int num_dacs, num_adcs; | ||
223 | int ret = 0; | 249 | int ret = 0; |
250 | int i; | ||
251 | |||
252 | num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2; | ||
253 | num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2; | ||
224 | 254 | ||
225 | codec->control_data = ad1836->control_data; | ||
226 | ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); | 255 | ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); |
227 | if (ret < 0) { | 256 | if (ret < 0) { |
228 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | 257 | dev_err(codec->dev, "failed to set cache I/O: %d\n", |
@@ -239,21 +268,46 @@ static int ad1836_probe(struct snd_soc_codec *codec) | |||
239 | snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); | 268 | snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); |
240 | /* unmute adc channles, adc aux mode */ | 269 | /* unmute adc channles, adc aux mode */ |
241 | snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); | 270 | snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); |
242 | /* left/right diff:PGA/MUX */ | ||
243 | snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); | ||
244 | /* volume */ | 271 | /* volume */ |
245 | snd_soc_write(codec, AD1836_DAC_L1_VOL, 0x3FF); | 272 | for (i = 1; i <= num_dacs; ++i) { |
246 | snd_soc_write(codec, AD1836_DAC_R1_VOL, 0x3FF); | 273 | snd_soc_write(codec, AD1836_DAC_L_VOL(i), 0x3FF); |
247 | snd_soc_write(codec, AD1836_DAC_L2_VOL, 0x3FF); | 274 | snd_soc_write(codec, AD1836_DAC_R_VOL(i), 0x3FF); |
248 | snd_soc_write(codec, AD1836_DAC_R2_VOL, 0x3FF); | 275 | } |
249 | snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); | 276 | |
250 | snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); | 277 | if (ad1836->type == AD1836) { |
251 | 278 | /* left/right diff:PGA/MUX */ | |
252 | snd_soc_add_controls(codec, ad1836_snd_controls, | 279 | snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); |
253 | ARRAY_SIZE(ad1836_snd_controls)); | 280 | ret = snd_soc_add_controls(codec, ad1836_controls, |
254 | snd_soc_dapm_new_controls(dapm, ad1836_dapm_widgets, | 281 | ARRAY_SIZE(ad1836_controls)); |
255 | ARRAY_SIZE(ad1836_dapm_widgets)); | 282 | if (ret) |
256 | snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths)); | 283 | return ret; |
284 | } else { | ||
285 | snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00); | ||
286 | } | ||
287 | |||
288 | ret = snd_soc_add_controls(codec, ad183x_dac_controls, num_dacs * 2); | ||
289 | if (ret) | ||
290 | return ret; | ||
291 | |||
292 | ret = snd_soc_add_controls(codec, ad183x_adc_controls, num_adcs); | ||
293 | if (ret) | ||
294 | return ret; | ||
295 | |||
296 | ret = snd_soc_dapm_new_controls(dapm, ad183x_dac_dapm_widgets, num_dacs); | ||
297 | if (ret) | ||
298 | return ret; | ||
299 | |||
300 | ret = snd_soc_dapm_new_controls(dapm, ad183x_adc_dapm_widgets, num_adcs); | ||
301 | if (ret) | ||
302 | return ret; | ||
303 | |||
304 | ret = snd_soc_dapm_add_routes(dapm, ad183x_dac_routes, num_dacs); | ||
305 | if (ret) | ||
306 | return ret; | ||
307 | |||
308 | ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs); | ||
309 | if (ret) | ||
310 | return ret; | ||
257 | 311 | ||
258 | return ret; | 312 | return ret; |
259 | } | 313 | } |
@@ -262,19 +316,24 @@ static int ad1836_probe(struct snd_soc_codec *codec) | |||
262 | static int ad1836_remove(struct snd_soc_codec *codec) | 316 | static int ad1836_remove(struct snd_soc_codec *codec) |
263 | { | 317 | { |
264 | /* reset clock control mode */ | 318 | /* reset clock control mode */ |
265 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); | 319 | return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, |
266 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; | 320 | AD1836_ADC_SERFMT_MASK, 0); |
267 | |||
268 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); | ||
269 | } | 321 | } |
270 | 322 | ||
271 | static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { | 323 | static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { |
272 | .probe = ad1836_probe, | 324 | .probe = ad1836_probe, |
273 | .remove = ad1836_remove, | 325 | .remove = ad1836_remove, |
274 | .suspend = ad1836_soc_suspend, | 326 | .suspend = ad1836_suspend, |
275 | .resume = ad1836_soc_resume, | 327 | .resume = ad1836_resume, |
276 | .reg_cache_size = AD1836_NUM_REGS, | 328 | .reg_cache_size = AD1836_NUM_REGS, |
277 | .reg_word_size = sizeof(u16), | 329 | .reg_word_size = sizeof(u16), |
330 | |||
331 | .controls = ad183x_controls, | ||
332 | .num_controls = ARRAY_SIZE(ad183x_controls), | ||
333 | .dapm_widgets = ad183x_dapm_widgets, | ||
334 | .num_dapm_widgets = ARRAY_SIZE(ad183x_dapm_widgets), | ||
335 | .dapm_routes = ad183x_dapm_routes, | ||
336 | .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), | ||
278 | }; | 337 | }; |
279 | 338 | ||
280 | static int __devinit ad1836_spi_probe(struct spi_device *spi) | 339 | static int __devinit ad1836_spi_probe(struct spi_device *spi) |
@@ -286,12 +345,12 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi) | |||
286 | if (ad1836 == NULL) | 345 | if (ad1836 == NULL) |
287 | return -ENOMEM; | 346 | return -ENOMEM; |
288 | 347 | ||
348 | ad1836->type = spi_get_device_id(spi)->driver_data; | ||
349 | |||
289 | spi_set_drvdata(spi, ad1836); | 350 | spi_set_drvdata(spi, ad1836); |
290 | ad1836->control_data = spi; | ||
291 | ad1836->control_type = SND_SOC_SPI; | ||
292 | 351 | ||
293 | ret = snd_soc_register_codec(&spi->dev, | 352 | ret = snd_soc_register_codec(&spi->dev, |
294 | &soc_codec_dev_ad1836, &ad1836_dai, 1); | 353 | &soc_codec_dev_ad1836, &ad183x_dais[ad1836->type], 1); |
295 | if (ret < 0) | 354 | if (ret < 0) |
296 | kfree(ad1836); | 355 | kfree(ad1836); |
297 | return ret; | 356 | return ret; |
@@ -303,27 +362,29 @@ static int __devexit ad1836_spi_remove(struct spi_device *spi) | |||
303 | kfree(spi_get_drvdata(spi)); | 362 | kfree(spi_get_drvdata(spi)); |
304 | return 0; | 363 | return 0; |
305 | } | 364 | } |
365 | static const struct spi_device_id ad1836_ids[] = { | ||
366 | { "ad1835", AD1835 }, | ||
367 | { "ad1836", AD1836 }, | ||
368 | { "ad1837", AD1835 }, | ||
369 | { "ad1838", AD1838 }, | ||
370 | { "ad1839", AD1838 }, | ||
371 | { }, | ||
372 | }; | ||
373 | MODULE_DEVICE_TABLE(spi, ad1836_ids); | ||
306 | 374 | ||
307 | static struct spi_driver ad1836_spi_driver = { | 375 | static struct spi_driver ad1836_spi_driver = { |
308 | .driver = { | 376 | .driver = { |
309 | .name = "ad1836-codec", | 377 | .name = "ad1836", |
310 | .owner = THIS_MODULE, | 378 | .owner = THIS_MODULE, |
311 | }, | 379 | }, |
312 | .probe = ad1836_spi_probe, | 380 | .probe = ad1836_spi_probe, |
313 | .remove = __devexit_p(ad1836_spi_remove), | 381 | .remove = __devexit_p(ad1836_spi_remove), |
382 | .id_table = ad1836_ids, | ||
314 | }; | 383 | }; |
315 | 384 | ||
316 | static int __init ad1836_init(void) | 385 | static int __init ad1836_init(void) |
317 | { | 386 | { |
318 | int ret; | 387 | return spi_register_driver(&ad1836_spi_driver); |
319 | |||
320 | ret = spi_register_driver(&ad1836_spi_driver); | ||
321 | if (ret != 0) { | ||
322 | printk(KERN_ERR "Failed to register ad1836 SPI driver: %d\n", | ||
323 | ret); | ||
324 | } | ||
325 | |||
326 | return ret; | ||
327 | } | 388 | } |
328 | module_init(ad1836_init); | 389 | module_init(ad1836_init); |
329 | 390 | ||
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index 9d6a3f8f8aaf..444747f0db26 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h | |||
@@ -1,19 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * File: sound/soc/codecs/ad1836.h | 2 | * Audio Codec driver supporting: |
3 | * Based on: | 3 | * AD1835A, AD1836, AD1837A, AD1838A, AD1839A |
4 | * Author: Barry Song <Barry.Song@analog.com> | ||
5 | * | 4 | * |
6 | * Created: Aug 04, 2009 | 5 | * Copyright 2009-2011 Analog Devices Inc. |
7 | * Description: definitions for AD1836 registers | ||
8 | * | 6 | * |
9 | * Modified: | 7 | * Licensed under the GPL-2 or later. |
10 | * | ||
11 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | */ | 8 | */ |
18 | 9 | ||
19 | #ifndef __AD1836_H__ | 10 | #ifndef __AD1836_H__ |
@@ -21,39 +12,30 @@ | |||
21 | 12 | ||
22 | #define AD1836_DAC_CTRL1 0 | 13 | #define AD1836_DAC_CTRL1 0 |
23 | #define AD1836_DAC_POWERDOWN 2 | 14 | #define AD1836_DAC_POWERDOWN 2 |
24 | #define AD1836_DAC_SERFMT_MASK 0xE0 | 15 | #define AD1836_DAC_SERFMT_MASK 0xE0 |
25 | #define AD1836_DAC_SERFMT_PCK256 (0x4 << 5) | 16 | #define AD1836_DAC_SERFMT_PCK256 (0x4 << 5) |
26 | #define AD1836_DAC_SERFMT_PCK128 (0x5 << 5) | 17 | #define AD1836_DAC_SERFMT_PCK128 (0x5 << 5) |
27 | #define AD1836_DAC_WORD_LEN_MASK 0x18 | 18 | #define AD1836_DAC_WORD_LEN_MASK 0x18 |
28 | #define AD1836_DAC_WORD_LEN_OFFSET 3 | 19 | #define AD1836_DAC_WORD_LEN_OFFSET 3 |
29 | 20 | ||
30 | #define AD1836_DAC_CTRL2 1 | 21 | #define AD1836_DAC_CTRL2 1 |
31 | #define AD1836_DACL1_MUTE 0 | ||
32 | #define AD1836_DACR1_MUTE 1 | ||
33 | #define AD1836_DACL2_MUTE 2 | ||
34 | #define AD1836_DACR2_MUTE 3 | ||
35 | #define AD1836_DACL3_MUTE 4 | ||
36 | #define AD1836_DACR3_MUTE 5 | ||
37 | 22 | ||
38 | #define AD1836_DAC_L1_VOL 2 | 23 | /* These macros are one-based. So AD183X_MUTE_LEFT(1) will return the mute bit |
39 | #define AD1836_DAC_R1_VOL 3 | 24 | * for the first ADC/DAC */ |
40 | #define AD1836_DAC_L2_VOL 4 | 25 | #define AD1836_MUTE_LEFT(x) (((x) * 2) - 2) |
41 | #define AD1836_DAC_R2_VOL 5 | 26 | #define AD1836_MUTE_RIGHT(x) (((x) * 2) - 1) |
42 | #define AD1836_DAC_L3_VOL 6 | 27 | |
43 | #define AD1836_DAC_R3_VOL 7 | 28 | #define AD1836_DAC_L_VOL(x) ((x) * 2) |
29 | #define AD1836_DAC_R_VOL(x) (1 + ((x) * 2)) | ||
44 | 30 | ||
45 | #define AD1836_ADC_CTRL1 12 | 31 | #define AD1836_ADC_CTRL1 12 |
46 | #define AD1836_ADC_POWERDOWN 7 | 32 | #define AD1836_ADC_POWERDOWN 7 |
47 | #define AD1836_ADC_HIGHPASS_FILTER 8 | 33 | #define AD1836_ADC_HIGHPASS_FILTER 8 |
48 | 34 | ||
49 | #define AD1836_ADC_CTRL2 13 | 35 | #define AD1836_ADC_CTRL2 13 |
50 | #define AD1836_ADCL1_MUTE 0 | ||
51 | #define AD1836_ADCR1_MUTE 1 | ||
52 | #define AD1836_ADCL2_MUTE 2 | ||
53 | #define AD1836_ADCR2_MUTE 3 | ||
54 | #define AD1836_ADC_WORD_LEN_MASK 0x30 | 36 | #define AD1836_ADC_WORD_LEN_MASK 0x30 |
55 | #define AD1836_ADC_WORD_OFFSET 5 | 37 | #define AD1836_ADC_WORD_OFFSET 5 |
56 | #define AD1836_ADC_SERFMT_MASK (7 << 6) | 38 | #define AD1836_ADC_SERFMT_MASK (7 << 6) |
57 | #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) | 39 | #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) |
58 | #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) | 40 | #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) |
59 | #define AD1836_ADC_AUX (0x6 << 6) | 41 | #define AD1836_ADC_AUX (0x6 << 6) |
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c new file mode 100644 index 000000000000..2758d5fc60d6 --- /dev/null +++ b/sound/soc/codecs/adau1701.c | |||
@@ -0,0 +1,549 @@ | |||
1 | /* | ||
2 | * Driver for ADAU1701 SigmaDSP processor | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * based on an inital version by Cliff Cai <cliff.cai@analog.com> | ||
7 | * | ||
8 | * Licensed under the GPL-2 or later. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/sigma.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | ||
21 | |||
22 | #include "adau1701.h" | ||
23 | |||
24 | #define ADAU1701_DSPCTRL 0x1c | ||
25 | #define ADAU1701_SEROCTL 0x1e | ||
26 | #define ADAU1701_SERICTL 0x1f | ||
27 | |||
28 | #define ADAU1701_AUXNPOW 0x22 | ||
29 | |||
30 | #define ADAU1701_OSCIPOW 0x26 | ||
31 | #define ADAU1701_DACSET 0x27 | ||
32 | |||
33 | #define ADAU1701_NUM_REGS 0x28 | ||
34 | |||
35 | #define ADAU1701_DSPCTRL_CR (1 << 2) | ||
36 | #define ADAU1701_DSPCTRL_DAM (1 << 3) | ||
37 | #define ADAU1701_DSPCTRL_ADM (1 << 4) | ||
38 | #define ADAU1701_DSPCTRL_SR_48 0x00 | ||
39 | #define ADAU1701_DSPCTRL_SR_96 0x01 | ||
40 | #define ADAU1701_DSPCTRL_SR_192 0x02 | ||
41 | #define ADAU1701_DSPCTRL_SR_MASK 0x03 | ||
42 | |||
43 | #define ADAU1701_SEROCTL_INV_LRCLK 0x2000 | ||
44 | #define ADAU1701_SEROCTL_INV_BCLK 0x1000 | ||
45 | #define ADAU1701_SEROCTL_MASTER 0x0800 | ||
46 | |||
47 | #define ADAU1701_SEROCTL_OBF16 0x0000 | ||
48 | #define ADAU1701_SEROCTL_OBF8 0x0200 | ||
49 | #define ADAU1701_SEROCTL_OBF4 0x0400 | ||
50 | #define ADAU1701_SEROCTL_OBF2 0x0600 | ||
51 | #define ADAU1701_SEROCTL_OBF_MASK 0x0600 | ||
52 | |||
53 | #define ADAU1701_SEROCTL_OLF1024 0x0000 | ||
54 | #define ADAU1701_SEROCTL_OLF512 0x0080 | ||
55 | #define ADAU1701_SEROCTL_OLF256 0x0100 | ||
56 | #define ADAU1701_SEROCTL_OLF_MASK 0x0180 | ||
57 | |||
58 | #define ADAU1701_SEROCTL_MSB_DEALY1 0x0000 | ||
59 | #define ADAU1701_SEROCTL_MSB_DEALY0 0x0004 | ||
60 | #define ADAU1701_SEROCTL_MSB_DEALY8 0x0008 | ||
61 | #define ADAU1701_SEROCTL_MSB_DEALY12 0x000c | ||
62 | #define ADAU1701_SEROCTL_MSB_DEALY16 0x0010 | ||
63 | #define ADAU1701_SEROCTL_MSB_DEALY_MASK 0x001c | ||
64 | |||
65 | #define ADAU1701_SEROCTL_WORD_LEN_24 0x0000 | ||
66 | #define ADAU1701_SEROCTL_WORD_LEN_20 0x0001 | ||
67 | #define ADAU1701_SEROCTL_WORD_LEN_16 0x0010 | ||
68 | #define ADAU1701_SEROCTL_WORD_LEN_MASK 0x0003 | ||
69 | |||
70 | #define ADAU1701_AUXNPOW_VBPD 0x40 | ||
71 | #define ADAU1701_AUXNPOW_VRPD 0x20 | ||
72 | |||
73 | #define ADAU1701_SERICTL_I2S 0 | ||
74 | #define ADAU1701_SERICTL_LEFTJ 1 | ||
75 | #define ADAU1701_SERICTL_TDM 2 | ||
76 | #define ADAU1701_SERICTL_RIGHTJ_24 3 | ||
77 | #define ADAU1701_SERICTL_RIGHTJ_20 4 | ||
78 | #define ADAU1701_SERICTL_RIGHTJ_18 5 | ||
79 | #define ADAU1701_SERICTL_RIGHTJ_16 6 | ||
80 | #define ADAU1701_SERICTL_MODE_MASK 7 | ||
81 | #define ADAU1701_SERICTL_INV_BCLK BIT(3) | ||
82 | #define ADAU1701_SERICTL_INV_LRCLK BIT(4) | ||
83 | |||
84 | #define ADAU1701_OSCIPOW_OPD 0x04 | ||
85 | #define ADAU1701_DACSET_DACINIT 1 | ||
86 | |||
87 | #define ADAU1701_FIRMWARE "adau1701.bin" | ||
88 | |||
89 | struct adau1701 { | ||
90 | unsigned int dai_fmt; | ||
91 | }; | ||
92 | |||
93 | static const struct snd_kcontrol_new adau1701_controls[] = { | ||
94 | SOC_SINGLE("Master Capture Switch", ADAU1701_DSPCTRL, 4, 1, 0), | ||
95 | }; | ||
96 | |||
97 | static const struct snd_soc_dapm_widget adau1701_dapm_widgets[] = { | ||
98 | SND_SOC_DAPM_DAC("DAC0", "Playback", ADAU1701_AUXNPOW, 3, 1), | ||
99 | SND_SOC_DAPM_DAC("DAC1", "Playback", ADAU1701_AUXNPOW, 2, 1), | ||
100 | SND_SOC_DAPM_DAC("DAC2", "Playback", ADAU1701_AUXNPOW, 1, 1), | ||
101 | SND_SOC_DAPM_DAC("DAC3", "Playback", ADAU1701_AUXNPOW, 0, 1), | ||
102 | SND_SOC_DAPM_ADC("ADC", "Capture", ADAU1701_AUXNPOW, 7, 1), | ||
103 | |||
104 | SND_SOC_DAPM_OUTPUT("OUT0"), | ||
105 | SND_SOC_DAPM_OUTPUT("OUT1"), | ||
106 | SND_SOC_DAPM_OUTPUT("OUT2"), | ||
107 | SND_SOC_DAPM_OUTPUT("OUT3"), | ||
108 | SND_SOC_DAPM_INPUT("IN0"), | ||
109 | SND_SOC_DAPM_INPUT("IN1"), | ||
110 | }; | ||
111 | |||
112 | static const struct snd_soc_dapm_route adau1701_dapm_routes[] = { | ||
113 | { "OUT0", NULL, "DAC0" }, | ||
114 | { "OUT1", NULL, "DAC1" }, | ||
115 | { "OUT2", NULL, "DAC2" }, | ||
116 | { "OUT3", NULL, "DAC3" }, | ||
117 | |||
118 | { "ADC", NULL, "IN0" }, | ||
119 | { "ADC", NULL, "IN1" }, | ||
120 | }; | ||
121 | |||
122 | static unsigned int adau1701_register_size(struct snd_soc_codec *codec, | ||
123 | unsigned int reg) | ||
124 | { | ||
125 | switch (reg) { | ||
126 | case ADAU1701_DSPCTRL: | ||
127 | case ADAU1701_SEROCTL: | ||
128 | case ADAU1701_AUXNPOW: | ||
129 | case ADAU1701_OSCIPOW: | ||
130 | case ADAU1701_DACSET: | ||
131 | return 2; | ||
132 | case ADAU1701_SERICTL: | ||
133 | return 1; | ||
134 | } | ||
135 | |||
136 | dev_err(codec->dev, "Unsupported register address: %d\n", reg); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static int adau1701_write(struct snd_soc_codec *codec, unsigned int reg, | ||
141 | unsigned int value) | ||
142 | { | ||
143 | unsigned int i; | ||
144 | unsigned int size; | ||
145 | uint8_t buf[4]; | ||
146 | int ret; | ||
147 | |||
148 | size = adau1701_register_size(codec, reg); | ||
149 | if (size == 0) | ||
150 | return -EINVAL; | ||
151 | |||
152 | snd_soc_cache_write(codec, reg, value); | ||
153 | |||
154 | buf[0] = 0x08; | ||
155 | buf[1] = reg; | ||
156 | |||
157 | for (i = size + 1; i >= 2; --i) { | ||
158 | buf[i] = value; | ||
159 | value >>= 8; | ||
160 | } | ||
161 | |||
162 | ret = i2c_master_send(to_i2c_client(codec->dev), buf, size + 2); | ||
163 | if (ret == size + 2) | ||
164 | return 0; | ||
165 | else if (ret < 0) | ||
166 | return ret; | ||
167 | else | ||
168 | return -EIO; | ||
169 | } | ||
170 | |||
171 | static unsigned int adau1701_read(struct snd_soc_codec *codec, unsigned int reg) | ||
172 | { | ||
173 | unsigned int value; | ||
174 | unsigned int ret; | ||
175 | |||
176 | ret = snd_soc_cache_read(codec, reg, &value); | ||
177 | if (ret) | ||
178 | return ret; | ||
179 | |||
180 | return value; | ||
181 | } | ||
182 | |||
183 | static int adau1701_load_firmware(struct snd_soc_codec *codec) | ||
184 | { | ||
185 | return process_sigma_firmware(codec->control_data, ADAU1701_FIRMWARE); | ||
186 | } | ||
187 | |||
188 | static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, | ||
189 | snd_pcm_format_t format) | ||
190 | { | ||
191 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
192 | unsigned int mask = ADAU1701_SEROCTL_WORD_LEN_MASK; | ||
193 | unsigned int val; | ||
194 | |||
195 | switch (format) { | ||
196 | case SNDRV_PCM_FORMAT_S16_LE: | ||
197 | val = ADAU1701_SEROCTL_WORD_LEN_16; | ||
198 | break; | ||
199 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
200 | val = ADAU1701_SEROCTL_WORD_LEN_20; | ||
201 | break; | ||
202 | case SNDRV_PCM_FORMAT_S24_LE: | ||
203 | val = ADAU1701_SEROCTL_WORD_LEN_24; | ||
204 | break; | ||
205 | default: | ||
206 | return -EINVAL; | ||
207 | } | ||
208 | |||
209 | if (adau1701->dai_fmt == SND_SOC_DAIFMT_RIGHT_J) { | ||
210 | switch (format) { | ||
211 | case SNDRV_PCM_FORMAT_S16_LE: | ||
212 | val |= ADAU1701_SEROCTL_MSB_DEALY16; | ||
213 | break; | ||
214 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
215 | val |= ADAU1701_SEROCTL_MSB_DEALY12; | ||
216 | break; | ||
217 | case SNDRV_PCM_FORMAT_S24_LE: | ||
218 | val |= ADAU1701_SEROCTL_MSB_DEALY8; | ||
219 | break; | ||
220 | } | ||
221 | mask |= ADAU1701_SEROCTL_MSB_DEALY_MASK; | ||
222 | } | ||
223 | |||
224 | snd_soc_update_bits(codec, ADAU1701_SEROCTL, mask, val); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int adau1701_set_playback_pcm_format(struct snd_soc_codec *codec, | ||
230 | snd_pcm_format_t format) | ||
231 | { | ||
232 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
233 | unsigned int val; | ||
234 | |||
235 | if (adau1701->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) | ||
236 | return 0; | ||
237 | |||
238 | switch (format) { | ||
239 | case SNDRV_PCM_FORMAT_S16_LE: | ||
240 | val = ADAU1701_SERICTL_RIGHTJ_16; | ||
241 | break; | ||
242 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
243 | val = ADAU1701_SERICTL_RIGHTJ_20; | ||
244 | break; | ||
245 | case SNDRV_PCM_FORMAT_S24_LE: | ||
246 | val = ADAU1701_SERICTL_RIGHTJ_24; | ||
247 | break; | ||
248 | default: | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | |||
252 | snd_soc_update_bits(codec, ADAU1701_SERICTL, | ||
253 | ADAU1701_SERICTL_MODE_MASK, val); | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int adau1701_hw_params(struct snd_pcm_substream *substream, | ||
259 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
260 | { | ||
261 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
262 | struct snd_soc_codec *codec = rtd->codec; | ||
263 | snd_pcm_format_t format; | ||
264 | unsigned int val; | ||
265 | |||
266 | switch (params_rate(params)) { | ||
267 | case 192000: | ||
268 | val = ADAU1701_DSPCTRL_SR_192; | ||
269 | break; | ||
270 | case 96000: | ||
271 | val = ADAU1701_DSPCTRL_SR_96; | ||
272 | break; | ||
273 | case 48000: | ||
274 | val = ADAU1701_DSPCTRL_SR_48; | ||
275 | break; | ||
276 | default: | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | |||
280 | snd_soc_update_bits(codec, ADAU1701_DSPCTRL, | ||
281 | ADAU1701_DSPCTRL_SR_MASK, val); | ||
282 | |||
283 | format = params_format(params); | ||
284 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
285 | return adau1701_set_playback_pcm_format(codec, format); | ||
286 | else | ||
287 | return adau1701_set_capture_pcm_format(codec, format); | ||
288 | } | ||
289 | |||
290 | static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
291 | unsigned int fmt) | ||
292 | { | ||
293 | struct snd_soc_codec *codec = codec_dai->codec; | ||
294 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
295 | unsigned int serictl = 0x00, seroctl = 0x00; | ||
296 | bool invert_lrclk; | ||
297 | |||
298 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
299 | case SND_SOC_DAIFMT_CBM_CFM: | ||
300 | /* master, 64-bits per sample, 1 frame per sample */ | ||
301 | seroctl |= ADAU1701_SEROCTL_MASTER | ADAU1701_SEROCTL_OBF16 | ||
302 | | ADAU1701_SEROCTL_OLF1024; | ||
303 | break; | ||
304 | case SND_SOC_DAIFMT_CBS_CFS: | ||
305 | break; | ||
306 | default: | ||
307 | return -EINVAL; | ||
308 | } | ||
309 | |||
310 | /* clock inversion */ | ||
311 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
312 | case SND_SOC_DAIFMT_NB_NF: | ||
313 | invert_lrclk = false; | ||
314 | break; | ||
315 | case SND_SOC_DAIFMT_NB_IF: | ||
316 | invert_lrclk = true; | ||
317 | break; | ||
318 | case SND_SOC_DAIFMT_IB_NF: | ||
319 | invert_lrclk = false; | ||
320 | serictl |= ADAU1701_SERICTL_INV_BCLK; | ||
321 | seroctl |= ADAU1701_SEROCTL_INV_BCLK; | ||
322 | break; | ||
323 | case SND_SOC_DAIFMT_IB_IF: | ||
324 | invert_lrclk = true; | ||
325 | serictl |= ADAU1701_SERICTL_INV_BCLK; | ||
326 | seroctl |= ADAU1701_SEROCTL_INV_BCLK; | ||
327 | break; | ||
328 | default: | ||
329 | return -EINVAL; | ||
330 | } | ||
331 | |||
332 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
333 | case SND_SOC_DAIFMT_I2S: | ||
334 | break; | ||
335 | case SND_SOC_DAIFMT_LEFT_J: | ||
336 | serictl |= ADAU1701_SERICTL_LEFTJ; | ||
337 | seroctl |= ADAU1701_SEROCTL_MSB_DEALY0; | ||
338 | invert_lrclk = !invert_lrclk; | ||
339 | break; | ||
340 | case SND_SOC_DAIFMT_RIGHT_J: | ||
341 | serictl |= ADAU1701_SERICTL_RIGHTJ_24; | ||
342 | seroctl |= ADAU1701_SEROCTL_MSB_DEALY8; | ||
343 | invert_lrclk = !invert_lrclk; | ||
344 | break; | ||
345 | default: | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | if (invert_lrclk) { | ||
350 | seroctl |= ADAU1701_SEROCTL_INV_LRCLK; | ||
351 | serictl |= ADAU1701_SERICTL_INV_LRCLK; | ||
352 | } | ||
353 | |||
354 | adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | ||
355 | |||
356 | snd_soc_write(codec, ADAU1701_SERICTL, serictl); | ||
357 | snd_soc_update_bits(codec, ADAU1701_SEROCTL, | ||
358 | ~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int adau1701_set_bias_level(struct snd_soc_codec *codec, | ||
364 | enum snd_soc_bias_level level) | ||
365 | { | ||
366 | unsigned int mask = ADAU1701_AUXNPOW_VBPD | ADAU1701_AUXNPOW_VRPD; | ||
367 | |||
368 | switch (level) { | ||
369 | case SND_SOC_BIAS_ON: | ||
370 | break; | ||
371 | case SND_SOC_BIAS_PREPARE: | ||
372 | break; | ||
373 | case SND_SOC_BIAS_STANDBY: | ||
374 | /* Enable VREF and VREF buffer */ | ||
375 | snd_soc_update_bits(codec, ADAU1701_AUXNPOW, mask, 0x00); | ||
376 | break; | ||
377 | case SND_SOC_BIAS_OFF: | ||
378 | /* Disable VREF and VREF buffer */ | ||
379 | snd_soc_update_bits(codec, ADAU1701_AUXNPOW, mask, mask); | ||
380 | break; | ||
381 | } | ||
382 | |||
383 | codec->dapm.bias_level = level; | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute) | ||
388 | { | ||
389 | struct snd_soc_codec *codec = dai->codec; | ||
390 | unsigned int mask = ADAU1701_DSPCTRL_DAM; | ||
391 | unsigned int val; | ||
392 | |||
393 | if (mute) | ||
394 | val = 0; | ||
395 | else | ||
396 | val = mask; | ||
397 | |||
398 | snd_soc_update_bits(codec, ADAU1701_DSPCTRL, mask, val); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id, | ||
404 | unsigned int freq, int dir) | ||
405 | { | ||
406 | unsigned int val; | ||
407 | |||
408 | switch (clk_id) { | ||
409 | case ADAU1701_CLK_SRC_OSC: | ||
410 | val = 0x0; | ||
411 | break; | ||
412 | case ADAU1701_CLK_SRC_MCLK: | ||
413 | val = ADAU1701_OSCIPOW_OPD; | ||
414 | break; | ||
415 | default: | ||
416 | return -EINVAL; | ||
417 | } | ||
418 | |||
419 | snd_soc_update_bits(codec, ADAU1701_OSCIPOW, ADAU1701_OSCIPOW_OPD, val); | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | #define ADAU1701_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \ | ||
425 | SNDRV_PCM_RATE_192000) | ||
426 | |||
427 | #define ADAU1701_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
428 | SNDRV_PCM_FMTBIT_S24_LE) | ||
429 | |||
430 | static const struct snd_soc_dai_ops adau1701_dai_ops = { | ||
431 | .set_fmt = adau1701_set_dai_fmt, | ||
432 | .hw_params = adau1701_hw_params, | ||
433 | .digital_mute = adau1701_digital_mute, | ||
434 | }; | ||
435 | |||
436 | static struct snd_soc_dai_driver adau1701_dai = { | ||
437 | .name = "adau1701", | ||
438 | .playback = { | ||
439 | .stream_name = "Playback", | ||
440 | .channels_min = 2, | ||
441 | .channels_max = 8, | ||
442 | .rates = ADAU1701_RATES, | ||
443 | .formats = ADAU1701_FORMATS, | ||
444 | }, | ||
445 | .capture = { | ||
446 | .stream_name = "Capture", | ||
447 | .channels_min = 2, | ||
448 | .channels_max = 8, | ||
449 | .rates = ADAU1701_RATES, | ||
450 | .formats = ADAU1701_FORMATS, | ||
451 | }, | ||
452 | .ops = &adau1701_dai_ops, | ||
453 | .symmetric_rates = 1, | ||
454 | }; | ||
455 | |||
456 | static int adau1701_probe(struct snd_soc_codec *codec) | ||
457 | { | ||
458 | int ret; | ||
459 | |||
460 | codec->dapm.idle_bias_off = 1; | ||
461 | |||
462 | ret = adau1701_load_firmware(codec); | ||
463 | if (ret) | ||
464 | dev_warn(codec->dev, "Failed to load firmware\n"); | ||
465 | |||
466 | snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT); | ||
467 | snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR); | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static struct snd_soc_codec_driver adau1701_codec_drv = { | ||
473 | .probe = adau1701_probe, | ||
474 | .set_bias_level = adau1701_set_bias_level, | ||
475 | |||
476 | .reg_cache_size = ADAU1701_NUM_REGS, | ||
477 | .reg_word_size = sizeof(u16), | ||
478 | |||
479 | .controls = adau1701_controls, | ||
480 | .num_controls = ARRAY_SIZE(adau1701_controls), | ||
481 | .dapm_widgets = adau1701_dapm_widgets, | ||
482 | .num_dapm_widgets = ARRAY_SIZE(adau1701_dapm_widgets), | ||
483 | .dapm_routes = adau1701_dapm_routes, | ||
484 | .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), | ||
485 | |||
486 | .write = adau1701_write, | ||
487 | .read = adau1701_read, | ||
488 | |||
489 | .set_sysclk = adau1701_set_sysclk, | ||
490 | }; | ||
491 | |||
492 | static __devinit int adau1701_i2c_probe(struct i2c_client *client, | ||
493 | const struct i2c_device_id *id) | ||
494 | { | ||
495 | struct adau1701 *adau1701; | ||
496 | int ret; | ||
497 | |||
498 | adau1701 = kzalloc(sizeof(*adau1701), GFP_KERNEL); | ||
499 | if (!adau1701) | ||
500 | return -ENOMEM; | ||
501 | |||
502 | i2c_set_clientdata(client, adau1701); | ||
503 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, | ||
504 | &adau1701_dai, 1); | ||
505 | if (ret < 0) | ||
506 | kfree(adau1701); | ||
507 | |||
508 | return ret; | ||
509 | } | ||
510 | |||
511 | static __devexit int adau1701_i2c_remove(struct i2c_client *client) | ||
512 | { | ||
513 | snd_soc_unregister_codec(&client->dev); | ||
514 | kfree(i2c_get_clientdata(client)); | ||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static const struct i2c_device_id adau1701_i2c_id[] = { | ||
519 | { "adau1701", 0 }, | ||
520 | { } | ||
521 | }; | ||
522 | MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id); | ||
523 | |||
524 | static struct i2c_driver adau1701_i2c_driver = { | ||
525 | .driver = { | ||
526 | .name = "adau1701", | ||
527 | .owner = THIS_MODULE, | ||
528 | }, | ||
529 | .probe = adau1701_i2c_probe, | ||
530 | .remove = __devexit_p(adau1701_i2c_remove), | ||
531 | .id_table = adau1701_i2c_id, | ||
532 | }; | ||
533 | |||
534 | static int __init adau1701_init(void) | ||
535 | { | ||
536 | return i2c_add_driver(&adau1701_i2c_driver); | ||
537 | } | ||
538 | module_init(adau1701_init); | ||
539 | |||
540 | static void __exit adau1701_exit(void) | ||
541 | { | ||
542 | i2c_del_driver(&adau1701_i2c_driver); | ||
543 | } | ||
544 | module_exit(adau1701_exit); | ||
545 | |||
546 | MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver"); | ||
547 | MODULE_AUTHOR("Cliff Cai <cliff.cai@analog.com>"); | ||
548 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
549 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/adau1701.h b/sound/soc/codecs/adau1701.h new file mode 100644 index 000000000000..8d0949a2aec9 --- /dev/null +++ b/sound/soc/codecs/adau1701.h | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * header file for ADAU1701 SigmaDSP processor | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #ifndef _ADAU1701_H | ||
10 | #define _ADAU1701_H | ||
11 | |||
12 | enum adau1701_clk_src { | ||
13 | ADAU1701_CLK_SRC_OSC, | ||
14 | ADAU1701_CLK_SRC_MCLK, | ||
15 | }; | ||
16 | |||
17 | #endif | ||
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c new file mode 100644 index 000000000000..300c04b70e71 --- /dev/null +++ b/sound/soc/codecs/adav80x.c | |||
@@ -0,0 +1,951 @@ | |||
1 | /* | ||
2 | * ADAV80X Audio Codec driver supporting ADAV801, ADAV803 | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * Author: Yi Li <yi.li@analog.com> | ||
6 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
7 | * | ||
8 | * Licensed under the GPL-2 or later. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/spi/spi.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/tlv.h> | ||
21 | #include <sound/soc.h> | ||
22 | |||
23 | #include "adav80x.h" | ||
24 | |||
25 | #define ADAV80X_PLAYBACK_CTRL 0x04 | ||
26 | #define ADAV80X_AUX_IN_CTRL 0x05 | ||
27 | #define ADAV80X_REC_CTRL 0x06 | ||
28 | #define ADAV80X_AUX_OUT_CTRL 0x07 | ||
29 | #define ADAV80X_DPATH_CTRL1 0x62 | ||
30 | #define ADAV80X_DPATH_CTRL2 0x63 | ||
31 | #define ADAV80X_DAC_CTRL1 0x64 | ||
32 | #define ADAV80X_DAC_CTRL2 0x65 | ||
33 | #define ADAV80X_DAC_CTRL3 0x66 | ||
34 | #define ADAV80X_DAC_L_VOL 0x68 | ||
35 | #define ADAV80X_DAC_R_VOL 0x69 | ||
36 | #define ADAV80X_PGA_L_VOL 0x6c | ||
37 | #define ADAV80X_PGA_R_VOL 0x6d | ||
38 | #define ADAV80X_ADC_CTRL1 0x6e | ||
39 | #define ADAV80X_ADC_CTRL2 0x6f | ||
40 | #define ADAV80X_ADC_L_VOL 0x70 | ||
41 | #define ADAV80X_ADC_R_VOL 0x71 | ||
42 | #define ADAV80X_PLL_CTRL1 0x74 | ||
43 | #define ADAV80X_PLL_CTRL2 0x75 | ||
44 | #define ADAV80X_ICLK_CTRL1 0x76 | ||
45 | #define ADAV80X_ICLK_CTRL2 0x77 | ||
46 | #define ADAV80X_PLL_CLK_SRC 0x78 | ||
47 | #define ADAV80X_PLL_OUTE 0x7a | ||
48 | |||
49 | #define ADAV80X_PLL_CLK_SRC_PLL_XIN(pll) 0x00 | ||
50 | #define ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll) (0x40 << (pll)) | ||
51 | #define ADAV80X_PLL_CLK_SRC_PLL_MASK(pll) (0x40 << (pll)) | ||
52 | |||
53 | #define ADAV80X_ICLK_CTRL1_DAC_SRC(src) ((src) << 5) | ||
54 | #define ADAV80X_ICLK_CTRL1_ADC_SRC(src) ((src) << 2) | ||
55 | #define ADAV80X_ICLK_CTRL1_ICLK2_SRC(src) (src) | ||
56 | #define ADAV80X_ICLK_CTRL2_ICLK1_SRC(src) ((src) << 3) | ||
57 | |||
58 | #define ADAV80X_PLL_CTRL1_PLLDIV 0x10 | ||
59 | #define ADAV80X_PLL_CTRL1_PLLPD(pll) (0x04 << (pll)) | ||
60 | #define ADAV80X_PLL_CTRL1_XTLPD 0x02 | ||
61 | |||
62 | #define ADAV80X_PLL_CTRL2_FIELD(pll, x) ((x) << ((pll) * 4)) | ||
63 | |||
64 | #define ADAV80X_PLL_CTRL2_FS_48(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x00) | ||
65 | #define ADAV80X_PLL_CTRL2_FS_32(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x08) | ||
66 | #define ADAV80X_PLL_CTRL2_FS_44(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0c) | ||
67 | |||
68 | #define ADAV80X_PLL_CTRL2_SEL(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x02) | ||
69 | #define ADAV80X_PLL_CTRL2_DOUB(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x01) | ||
70 | #define ADAV80X_PLL_CTRL2_PLL_MASK(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0f) | ||
71 | |||
72 | #define ADAV80X_ADC_CTRL1_MODULATOR_MASK 0x80 | ||
73 | #define ADAV80X_ADC_CTRL1_MODULATOR_128FS 0x00 | ||
74 | #define ADAV80X_ADC_CTRL1_MODULATOR_64FS 0x80 | ||
75 | |||
76 | #define ADAV80X_DAC_CTRL1_PD 0x80 | ||
77 | |||
78 | #define ADAV80X_DAC_CTRL2_DIV1 0x00 | ||
79 | #define ADAV80X_DAC_CTRL2_DIV1_5 0x10 | ||
80 | #define ADAV80X_DAC_CTRL2_DIV2 0x20 | ||
81 | #define ADAV80X_DAC_CTRL2_DIV3 0x30 | ||
82 | #define ADAV80X_DAC_CTRL2_DIV_MASK 0x30 | ||
83 | |||
84 | #define ADAV80X_DAC_CTRL2_INTERPOL_256FS 0x00 | ||
85 | #define ADAV80X_DAC_CTRL2_INTERPOL_128FS 0x40 | ||
86 | #define ADAV80X_DAC_CTRL2_INTERPOL_64FS 0x80 | ||
87 | #define ADAV80X_DAC_CTRL2_INTERPOL_MASK 0xc0 | ||
88 | |||
89 | #define ADAV80X_DAC_CTRL2_DEEMPH_NONE 0x00 | ||
90 | #define ADAV80X_DAC_CTRL2_DEEMPH_44 0x01 | ||
91 | #define ADAV80X_DAC_CTRL2_DEEMPH_32 0x02 | ||
92 | #define ADAV80X_DAC_CTRL2_DEEMPH_48 0x03 | ||
93 | #define ADAV80X_DAC_CTRL2_DEEMPH_MASK 0x01 | ||
94 | |||
95 | #define ADAV80X_CAPTURE_MODE_MASTER 0x20 | ||
96 | #define ADAV80X_CAPTURE_WORD_LEN24 0x00 | ||
97 | #define ADAV80X_CAPTURE_WORD_LEN20 0x04 | ||
98 | #define ADAV80X_CAPTRUE_WORD_LEN18 0x08 | ||
99 | #define ADAV80X_CAPTURE_WORD_LEN16 0x0c | ||
100 | #define ADAV80X_CAPTURE_WORD_LEN_MASK 0x0c | ||
101 | |||
102 | #define ADAV80X_CAPTURE_MODE_LEFT_J 0x00 | ||
103 | #define ADAV80X_CAPTURE_MODE_I2S 0x01 | ||
104 | #define ADAV80X_CAPTURE_MODE_RIGHT_J 0x03 | ||
105 | #define ADAV80X_CAPTURE_MODE_MASK 0x03 | ||
106 | |||
107 | #define ADAV80X_PLAYBACK_MODE_MASTER 0x10 | ||
108 | #define ADAV80X_PLAYBACK_MODE_LEFT_J 0x00 | ||
109 | #define ADAV80X_PLAYBACK_MODE_I2S 0x01 | ||
110 | #define ADAV80X_PLAYBACK_MODE_RIGHT_J_24 0x04 | ||
111 | #define ADAV80X_PLAYBACK_MODE_RIGHT_J_20 0x05 | ||
112 | #define ADAV80X_PLAYBACK_MODE_RIGHT_J_18 0x06 | ||
113 | #define ADAV80X_PLAYBACK_MODE_RIGHT_J_16 0x07 | ||
114 | #define ADAV80X_PLAYBACK_MODE_MASK 0x07 | ||
115 | |||
116 | #define ADAV80X_PLL_OUTE_SYSCLKPD(x) BIT(2 - (x)) | ||
117 | |||
118 | static u8 adav80x_default_regs[] = { | ||
119 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x01, 0x80, 0x26, 0x00, 0x00, | ||
120 | 0x02, 0x40, 0x20, 0x00, 0x09, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
121 | 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x92, 0xb1, 0x37, | ||
122 | 0x48, 0xd2, 0xfb, 0xca, 0xd2, 0x15, 0xe8, 0x29, 0xb9, 0x6a, 0xda, 0x2b, | ||
123 | 0xb7, 0xc0, 0x11, 0x65, 0x5c, 0xf6, 0xff, 0x8d, 0x00, 0x00, 0x00, 0x00, | ||
124 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
125 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, | ||
126 | 0x00, 0xe8, 0x46, 0xe1, 0x5b, 0xd3, 0x43, 0x77, 0x93, 0xa7, 0x44, 0xee, | ||
127 | 0x32, 0x12, 0xc0, 0x11, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x3f, | ||
128 | 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, | ||
129 | 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, | ||
130 | }; | ||
131 | |||
132 | struct adav80x { | ||
133 | enum snd_soc_control_type control_type; | ||
134 | |||
135 | enum adav80x_clk_src clk_src; | ||
136 | unsigned int sysclk; | ||
137 | enum adav80x_pll_src pll_src; | ||
138 | |||
139 | unsigned int dai_fmt[2]; | ||
140 | unsigned int rate; | ||
141 | bool deemph; | ||
142 | bool sysclk_pd[3]; | ||
143 | }; | ||
144 | |||
145 | static const char *adav80x_mux_text[] = { | ||
146 | "ADC", | ||
147 | "Playback", | ||
148 | "Aux Playback", | ||
149 | }; | ||
150 | |||
151 | static const unsigned int adav80x_mux_values[] = { | ||
152 | 0, 2, 3, | ||
153 | }; | ||
154 | |||
155 | #define ADAV80X_MUX_ENUM_DECL(name, reg, shift) \ | ||
156 | SOC_VALUE_ENUM_DOUBLE_DECL(name, reg, shift, 7, \ | ||
157 | ARRAY_SIZE(adav80x_mux_text), adav80x_mux_text, \ | ||
158 | adav80x_mux_values) | ||
159 | |||
160 | static ADAV80X_MUX_ENUM_DECL(adav80x_aux_capture_enum, ADAV80X_DPATH_CTRL1, 0); | ||
161 | static ADAV80X_MUX_ENUM_DECL(adav80x_capture_enum, ADAV80X_DPATH_CTRL1, 3); | ||
162 | static ADAV80X_MUX_ENUM_DECL(adav80x_dac_enum, ADAV80X_DPATH_CTRL2, 3); | ||
163 | |||
164 | static const struct snd_kcontrol_new adav80x_aux_capture_mux_ctrl = | ||
165 | SOC_DAPM_VALUE_ENUM("Route", adav80x_aux_capture_enum); | ||
166 | static const struct snd_kcontrol_new adav80x_capture_mux_ctrl = | ||
167 | SOC_DAPM_VALUE_ENUM("Route", adav80x_capture_enum); | ||
168 | static const struct snd_kcontrol_new adav80x_dac_mux_ctrl = | ||
169 | SOC_DAPM_VALUE_ENUM("Route", adav80x_dac_enum); | ||
170 | |||
171 | #define ADAV80X_MUX(name, ctrl) \ | ||
172 | SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) | ||
173 | |||
174 | static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = { | ||
175 | SND_SOC_DAPM_DAC("DAC", NULL, ADAV80X_DAC_CTRL1, 7, 1), | ||
176 | SND_SOC_DAPM_ADC("ADC", NULL, ADAV80X_ADC_CTRL1, 5, 1), | ||
177 | |||
178 | SND_SOC_DAPM_PGA("Right PGA", ADAV80X_ADC_CTRL1, 0, 1, NULL, 0), | ||
179 | SND_SOC_DAPM_PGA("Left PGA", ADAV80X_ADC_CTRL1, 1, 1, NULL, 0), | ||
180 | |||
181 | SND_SOC_DAPM_AIF_OUT("AIFOUT", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0), | ||
182 | SND_SOC_DAPM_AIF_IN("AIFIN", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), | ||
183 | |||
184 | SND_SOC_DAPM_AIF_OUT("AIFAUXOUT", "Aux Capture", 0, SND_SOC_NOPM, 0, 0), | ||
185 | SND_SOC_DAPM_AIF_IN("AIFAUXIN", "Aux Playback", 0, SND_SOC_NOPM, 0, 0), | ||
186 | |||
187 | ADAV80X_MUX("Aux Capture Select", &adav80x_aux_capture_mux_ctrl), | ||
188 | ADAV80X_MUX("Capture Select", &adav80x_capture_mux_ctrl), | ||
189 | ADAV80X_MUX("DAC Select", &adav80x_dac_mux_ctrl), | ||
190 | |||
191 | SND_SOC_DAPM_INPUT("VINR"), | ||
192 | SND_SOC_DAPM_INPUT("VINL"), | ||
193 | SND_SOC_DAPM_OUTPUT("VOUTR"), | ||
194 | SND_SOC_DAPM_OUTPUT("VOUTL"), | ||
195 | |||
196 | SND_SOC_DAPM_SUPPLY("SYSCLK", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
197 | SND_SOC_DAPM_SUPPLY("PLL1", ADAV80X_PLL_CTRL1, 2, 1, NULL, 0), | ||
198 | SND_SOC_DAPM_SUPPLY("PLL2", ADAV80X_PLL_CTRL1, 3, 1, NULL, 0), | ||
199 | SND_SOC_DAPM_SUPPLY("OSC", ADAV80X_PLL_CTRL1, 1, 1, NULL, 0), | ||
200 | }; | ||
201 | |||
202 | static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, | ||
203 | struct snd_soc_dapm_widget *sink) | ||
204 | { | ||
205 | struct snd_soc_codec *codec = source->codec; | ||
206 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
207 | const char *clk; | ||
208 | |||
209 | switch (adav80x->clk_src) { | ||
210 | case ADAV80X_CLK_PLL1: | ||
211 | clk = "PLL1"; | ||
212 | break; | ||
213 | case ADAV80X_CLK_PLL2: | ||
214 | clk = "PLL2"; | ||
215 | break; | ||
216 | case ADAV80X_CLK_XTAL: | ||
217 | clk = "OSC"; | ||
218 | break; | ||
219 | default: | ||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | return strcmp(source->name, clk) == 0; | ||
224 | } | ||
225 | |||
226 | static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source, | ||
227 | struct snd_soc_dapm_widget *sink) | ||
228 | { | ||
229 | struct snd_soc_codec *codec = source->codec; | ||
230 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
231 | |||
232 | return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL; | ||
233 | } | ||
234 | |||
235 | |||
236 | static const struct snd_soc_dapm_route adav80x_dapm_routes[] = { | ||
237 | { "DAC Select", "ADC", "ADC" }, | ||
238 | { "DAC Select", "Playback", "AIFIN" }, | ||
239 | { "DAC Select", "Aux Playback", "AIFAUXIN" }, | ||
240 | { "DAC", NULL, "DAC Select" }, | ||
241 | |||
242 | { "Capture Select", "ADC", "ADC" }, | ||
243 | { "Capture Select", "Playback", "AIFIN" }, | ||
244 | { "Capture Select", "Aux Playback", "AIFAUXIN" }, | ||
245 | { "AIFOUT", NULL, "Capture Select" }, | ||
246 | |||
247 | { "Aux Capture Select", "ADC", "ADC" }, | ||
248 | { "Aux Capture Select", "Playback", "AIFIN" }, | ||
249 | { "Aux Capture Select", "Aux Playback", "AIFAUXIN" }, | ||
250 | { "AIFAUXOUT", NULL, "Aux Capture Select" }, | ||
251 | |||
252 | { "VOUTR", NULL, "DAC" }, | ||
253 | { "VOUTL", NULL, "DAC" }, | ||
254 | |||
255 | { "Left PGA", NULL, "VINL" }, | ||
256 | { "Right PGA", NULL, "VINR" }, | ||
257 | { "ADC", NULL, "Left PGA" }, | ||
258 | { "ADC", NULL, "Right PGA" }, | ||
259 | |||
260 | { "SYSCLK", NULL, "PLL1", adav80x_dapm_sysclk_check }, | ||
261 | { "SYSCLK", NULL, "PLL2", adav80x_dapm_sysclk_check }, | ||
262 | { "SYSCLK", NULL, "OSC", adav80x_dapm_sysclk_check }, | ||
263 | { "PLL1", NULL, "OSC", adav80x_dapm_pll_check }, | ||
264 | { "PLL2", NULL, "OSC", adav80x_dapm_pll_check }, | ||
265 | |||
266 | { "ADC", NULL, "SYSCLK" }, | ||
267 | { "DAC", NULL, "SYSCLK" }, | ||
268 | { "AIFOUT", NULL, "SYSCLK" }, | ||
269 | { "AIFAUXOUT", NULL, "SYSCLK" }, | ||
270 | { "AIFIN", NULL, "SYSCLK" }, | ||
271 | { "AIFAUXIN", NULL, "SYSCLK" }, | ||
272 | }; | ||
273 | |||
274 | static int adav80x_set_deemph(struct snd_soc_codec *codec) | ||
275 | { | ||
276 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
277 | unsigned int val; | ||
278 | |||
279 | if (adav80x->deemph) { | ||
280 | switch (adav80x->rate) { | ||
281 | case 32000: | ||
282 | val = ADAV80X_DAC_CTRL2_DEEMPH_32; | ||
283 | break; | ||
284 | case 44100: | ||
285 | val = ADAV80X_DAC_CTRL2_DEEMPH_44; | ||
286 | break; | ||
287 | case 48000: | ||
288 | case 64000: | ||
289 | case 88200: | ||
290 | case 96000: | ||
291 | val = ADAV80X_DAC_CTRL2_DEEMPH_48; | ||
292 | break; | ||
293 | default: | ||
294 | val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; | ||
295 | break; | ||
296 | } | ||
297 | } else { | ||
298 | val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; | ||
299 | } | ||
300 | |||
301 | return snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2, | ||
302 | ADAV80X_DAC_CTRL2_DEEMPH_MASK, val); | ||
303 | } | ||
304 | |||
305 | static int adav80x_put_deemph(struct snd_kcontrol *kcontrol, | ||
306 | struct snd_ctl_elem_value *ucontrol) | ||
307 | { | ||
308 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
309 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
310 | unsigned int deemph = ucontrol->value.enumerated.item[0]; | ||
311 | |||
312 | if (deemph > 1) | ||
313 | return -EINVAL; | ||
314 | |||
315 | adav80x->deemph = deemph; | ||
316 | |||
317 | return adav80x_set_deemph(codec); | ||
318 | } | ||
319 | |||
320 | static int adav80x_get_deemph(struct snd_kcontrol *kcontrol, | ||
321 | struct snd_ctl_elem_value *ucontrol) | ||
322 | { | ||
323 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
324 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
325 | |||
326 | ucontrol->value.enumerated.item[0] = adav80x->deemph; | ||
327 | return 0; | ||
328 | }; | ||
329 | |||
330 | static const DECLARE_TLV_DB_SCALE(adav80x_inpga_tlv, 0, 50, 0); | ||
331 | static const DECLARE_TLV_DB_MINMAX(adav80x_digital_tlv, -9563, 0); | ||
332 | |||
333 | static const struct snd_kcontrol_new adav80x_controls[] = { | ||
334 | SOC_DOUBLE_R_TLV("Master Playback Volume", ADAV80X_DAC_L_VOL, | ||
335 | ADAV80X_DAC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), | ||
336 | SOC_DOUBLE_R_TLV("Master Capture Volume", ADAV80X_ADC_L_VOL, | ||
337 | ADAV80X_ADC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), | ||
338 | |||
339 | SOC_DOUBLE_R_TLV("PGA Capture Volume", ADAV80X_PGA_L_VOL, | ||
340 | ADAV80X_PGA_R_VOL, 0, 0x30, 0, adav80x_inpga_tlv), | ||
341 | |||
342 | SOC_DOUBLE("Master Playback Switch", ADAV80X_DAC_CTRL1, 0, 1, 1, 0), | ||
343 | SOC_DOUBLE("Master Capture Switch", ADAV80X_ADC_CTRL1, 2, 3, 1, 1), | ||
344 | |||
345 | SOC_SINGLE("ADC High Pass Filter Switch", ADAV80X_ADC_CTRL1, 6, 1, 0), | ||
346 | |||
347 | SOC_SINGLE_BOOL_EXT("Playback De-emphasis Switch", 0, | ||
348 | adav80x_get_deemph, adav80x_put_deemph), | ||
349 | }; | ||
350 | |||
351 | static unsigned int adav80x_port_ctrl_regs[2][2] = { | ||
352 | { ADAV80X_REC_CTRL, ADAV80X_PLAYBACK_CTRL, }, | ||
353 | { ADAV80X_AUX_OUT_CTRL, ADAV80X_AUX_IN_CTRL }, | ||
354 | }; | ||
355 | |||
356 | static int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
357 | { | ||
358 | struct snd_soc_codec *codec = dai->codec; | ||
359 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
360 | unsigned int capture = 0x00; | ||
361 | unsigned int playback = 0x00; | ||
362 | |||
363 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
364 | case SND_SOC_DAIFMT_CBM_CFM: | ||
365 | capture |= ADAV80X_CAPTURE_MODE_MASTER; | ||
366 | playback |= ADAV80X_PLAYBACK_MODE_MASTER; | ||
367 | case SND_SOC_DAIFMT_CBS_CFS: | ||
368 | break; | ||
369 | default: | ||
370 | return -EINVAL; | ||
371 | } | ||
372 | |||
373 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
374 | case SND_SOC_DAIFMT_I2S: | ||
375 | capture |= ADAV80X_CAPTURE_MODE_I2S; | ||
376 | playback |= ADAV80X_PLAYBACK_MODE_I2S; | ||
377 | break; | ||
378 | case SND_SOC_DAIFMT_LEFT_J: | ||
379 | capture |= ADAV80X_CAPTURE_MODE_LEFT_J; | ||
380 | playback |= ADAV80X_PLAYBACK_MODE_LEFT_J; | ||
381 | break; | ||
382 | case SND_SOC_DAIFMT_RIGHT_J: | ||
383 | capture |= ADAV80X_CAPTURE_MODE_RIGHT_J; | ||
384 | playback |= ADAV80X_PLAYBACK_MODE_RIGHT_J_24; | ||
385 | break; | ||
386 | default: | ||
387 | return -EINVAL; | ||
388 | } | ||
389 | |||
390 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
391 | case SND_SOC_DAIFMT_NB_NF: | ||
392 | break; | ||
393 | default: | ||
394 | return -EINVAL; | ||
395 | } | ||
396 | |||
397 | snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0], | ||
398 | ADAV80X_CAPTURE_MODE_MASK | ADAV80X_CAPTURE_MODE_MASTER, | ||
399 | capture); | ||
400 | snd_soc_write(codec, adav80x_port_ctrl_regs[dai->id][1], playback); | ||
401 | |||
402 | adav80x->dai_fmt[dai->id] = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | ||
403 | |||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | static int adav80x_set_adc_clock(struct snd_soc_codec *codec, | ||
408 | unsigned int sample_rate) | ||
409 | { | ||
410 | unsigned int val; | ||
411 | |||
412 | if (sample_rate <= 48000) | ||
413 | val = ADAV80X_ADC_CTRL1_MODULATOR_128FS; | ||
414 | else | ||
415 | val = ADAV80X_ADC_CTRL1_MODULATOR_64FS; | ||
416 | |||
417 | snd_soc_update_bits(codec, ADAV80X_ADC_CTRL1, | ||
418 | ADAV80X_ADC_CTRL1_MODULATOR_MASK, val); | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int adav80x_set_dac_clock(struct snd_soc_codec *codec, | ||
424 | unsigned int sample_rate) | ||
425 | { | ||
426 | unsigned int val; | ||
427 | |||
428 | if (sample_rate <= 48000) | ||
429 | val = ADAV80X_DAC_CTRL2_DIV1 | ADAV80X_DAC_CTRL2_INTERPOL_256FS; | ||
430 | else | ||
431 | val = ADAV80X_DAC_CTRL2_DIV2 | ADAV80X_DAC_CTRL2_INTERPOL_128FS; | ||
432 | |||
433 | snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2, | ||
434 | ADAV80X_DAC_CTRL2_DIV_MASK | ADAV80X_DAC_CTRL2_INTERPOL_MASK, | ||
435 | val); | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec, | ||
441 | struct snd_soc_dai *dai, snd_pcm_format_t format) | ||
442 | { | ||
443 | unsigned int val; | ||
444 | |||
445 | switch (format) { | ||
446 | case SNDRV_PCM_FORMAT_S16_LE: | ||
447 | val = ADAV80X_CAPTURE_WORD_LEN16; | ||
448 | break; | ||
449 | case SNDRV_PCM_FORMAT_S18_3LE: | ||
450 | val = ADAV80X_CAPTRUE_WORD_LEN18; | ||
451 | break; | ||
452 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
453 | val = ADAV80X_CAPTURE_WORD_LEN20; | ||
454 | break; | ||
455 | case SNDRV_PCM_FORMAT_S24_LE: | ||
456 | val = ADAV80X_CAPTURE_WORD_LEN24; | ||
457 | break; | ||
458 | default: | ||
459 | return -EINVAL; | ||
460 | } | ||
461 | |||
462 | snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0], | ||
463 | ADAV80X_CAPTURE_WORD_LEN_MASK, val); | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec, | ||
469 | struct snd_soc_dai *dai, snd_pcm_format_t format) | ||
470 | { | ||
471 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
472 | unsigned int val; | ||
473 | |||
474 | if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J) | ||
475 | return 0; | ||
476 | |||
477 | switch (format) { | ||
478 | case SNDRV_PCM_FORMAT_S16_LE: | ||
479 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16; | ||
480 | break; | ||
481 | case SNDRV_PCM_FORMAT_S18_3LE: | ||
482 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18; | ||
483 | break; | ||
484 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
485 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20; | ||
486 | break; | ||
487 | case SNDRV_PCM_FORMAT_S24_LE: | ||
488 | val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24; | ||
489 | break; | ||
490 | default: | ||
491 | return -EINVAL; | ||
492 | } | ||
493 | |||
494 | snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][1], | ||
495 | ADAV80X_PLAYBACK_MODE_MASK, val); | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | static int adav80x_hw_params(struct snd_pcm_substream *substream, | ||
501 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
502 | { | ||
503 | struct snd_soc_codec *codec = dai->codec; | ||
504 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
505 | unsigned int rate = params_rate(params); | ||
506 | |||
507 | if (rate * 256 != adav80x->sysclk) | ||
508 | return -EINVAL; | ||
509 | |||
510 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
511 | adav80x_set_playback_pcm_format(codec, dai, | ||
512 | params_format(params)); | ||
513 | adav80x_set_dac_clock(codec, rate); | ||
514 | } else { | ||
515 | adav80x_set_capture_pcm_format(codec, dai, | ||
516 | params_format(params)); | ||
517 | adav80x_set_adc_clock(codec, rate); | ||
518 | } | ||
519 | adav80x->rate = rate; | ||
520 | adav80x_set_deemph(codec); | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int adav80x_set_sysclk(struct snd_soc_codec *codec, | ||
526 | int clk_id, unsigned int freq, int dir) | ||
527 | { | ||
528 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
529 | |||
530 | if (dir == SND_SOC_CLOCK_IN) { | ||
531 | switch (clk_id) { | ||
532 | case ADAV80X_CLK_XIN: | ||
533 | case ADAV80X_CLK_XTAL: | ||
534 | case ADAV80X_CLK_MCLKI: | ||
535 | case ADAV80X_CLK_PLL1: | ||
536 | case ADAV80X_CLK_PLL2: | ||
537 | break; | ||
538 | default: | ||
539 | return -EINVAL; | ||
540 | } | ||
541 | |||
542 | adav80x->sysclk = freq; | ||
543 | |||
544 | if (adav80x->clk_src != clk_id) { | ||
545 | unsigned int iclk_ctrl1, iclk_ctrl2; | ||
546 | |||
547 | adav80x->clk_src = clk_id; | ||
548 | if (clk_id == ADAV80X_CLK_XTAL) | ||
549 | clk_id = ADAV80X_CLK_XIN; | ||
550 | |||
551 | iclk_ctrl1 = ADAV80X_ICLK_CTRL1_DAC_SRC(clk_id) | | ||
552 | ADAV80X_ICLK_CTRL1_ADC_SRC(clk_id) | | ||
553 | ADAV80X_ICLK_CTRL1_ICLK2_SRC(clk_id); | ||
554 | iclk_ctrl2 = ADAV80X_ICLK_CTRL2_ICLK1_SRC(clk_id); | ||
555 | |||
556 | snd_soc_write(codec, ADAV80X_ICLK_CTRL1, iclk_ctrl1); | ||
557 | snd_soc_write(codec, ADAV80X_ICLK_CTRL2, iclk_ctrl2); | ||
558 | |||
559 | snd_soc_dapm_sync(&codec->dapm); | ||
560 | } | ||
561 | } else { | ||
562 | unsigned int mask; | ||
563 | |||
564 | switch (clk_id) { | ||
565 | case ADAV80X_CLK_SYSCLK1: | ||
566 | case ADAV80X_CLK_SYSCLK2: | ||
567 | case ADAV80X_CLK_SYSCLK3: | ||
568 | break; | ||
569 | default: | ||
570 | return -EINVAL; | ||
571 | } | ||
572 | |||
573 | clk_id -= ADAV80X_CLK_SYSCLK1; | ||
574 | mask = ADAV80X_PLL_OUTE_SYSCLKPD(clk_id); | ||
575 | |||
576 | if (freq == 0) { | ||
577 | snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, mask); | ||
578 | adav80x->sysclk_pd[clk_id] = true; | ||
579 | } else { | ||
580 | snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, 0); | ||
581 | adav80x->sysclk_pd[clk_id] = false; | ||
582 | } | ||
583 | |||
584 | if (adav80x->sysclk_pd[0]) | ||
585 | snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); | ||
586 | else | ||
587 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); | ||
588 | |||
589 | if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) | ||
590 | snd_soc_dapm_disable_pin(&codec->dapm, "PLL2"); | ||
591 | else | ||
592 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); | ||
593 | |||
594 | snd_soc_dapm_sync(&codec->dapm); | ||
595 | } | ||
596 | |||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id, | ||
601 | int source, unsigned int freq_in, unsigned int freq_out) | ||
602 | { | ||
603 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
604 | unsigned int pll_ctrl1 = 0; | ||
605 | unsigned int pll_ctrl2 = 0; | ||
606 | unsigned int pll_src; | ||
607 | |||
608 | switch (source) { | ||
609 | case ADAV80X_PLL_SRC_XTAL: | ||
610 | case ADAV80X_PLL_SRC_XIN: | ||
611 | case ADAV80X_PLL_SRC_MCLKI: | ||
612 | break; | ||
613 | default: | ||
614 | return -EINVAL; | ||
615 | } | ||
616 | |||
617 | if (!freq_out) | ||
618 | return 0; | ||
619 | |||
620 | switch (freq_in) { | ||
621 | case 27000000: | ||
622 | break; | ||
623 | case 54000000: | ||
624 | if (source == ADAV80X_PLL_SRC_XIN) { | ||
625 | pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV; | ||
626 | break; | ||
627 | } | ||
628 | default: | ||
629 | return -EINVAL; | ||
630 | } | ||
631 | |||
632 | if (freq_out > 12288000) { | ||
633 | pll_ctrl2 |= ADAV80X_PLL_CTRL2_DOUB(pll_id); | ||
634 | freq_out /= 2; | ||
635 | } | ||
636 | |||
637 | /* freq_out = sample_rate * 256 */ | ||
638 | switch (freq_out) { | ||
639 | case 8192000: | ||
640 | pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_32(pll_id); | ||
641 | break; | ||
642 | case 11289600: | ||
643 | pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_44(pll_id); | ||
644 | break; | ||
645 | case 12288000: | ||
646 | pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_48(pll_id); | ||
647 | break; | ||
648 | default: | ||
649 | return -EINVAL; | ||
650 | } | ||
651 | |||
652 | snd_soc_update_bits(codec, ADAV80X_PLL_CTRL1, ADAV80X_PLL_CTRL1_PLLDIV, | ||
653 | pll_ctrl1); | ||
654 | snd_soc_update_bits(codec, ADAV80X_PLL_CTRL2, | ||
655 | ADAV80X_PLL_CTRL2_PLL_MASK(pll_id), pll_ctrl2); | ||
656 | |||
657 | if (source != adav80x->pll_src) { | ||
658 | if (source == ADAV80X_PLL_SRC_MCLKI) | ||
659 | pll_src = ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll_id); | ||
660 | else | ||
661 | pll_src = ADAV80X_PLL_CLK_SRC_PLL_XIN(pll_id); | ||
662 | |||
663 | snd_soc_update_bits(codec, ADAV80X_PLL_CLK_SRC, | ||
664 | ADAV80X_PLL_CLK_SRC_PLL_MASK(pll_id), pll_src); | ||
665 | |||
666 | adav80x->pll_src = source; | ||
667 | |||
668 | snd_soc_dapm_sync(&codec->dapm); | ||
669 | } | ||
670 | |||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | static int adav80x_set_bias_level(struct snd_soc_codec *codec, | ||
675 | enum snd_soc_bias_level level) | ||
676 | { | ||
677 | unsigned int mask = ADAV80X_DAC_CTRL1_PD; | ||
678 | |||
679 | switch (level) { | ||
680 | case SND_SOC_BIAS_ON: | ||
681 | break; | ||
682 | case SND_SOC_BIAS_PREPARE: | ||
683 | break; | ||
684 | case SND_SOC_BIAS_STANDBY: | ||
685 | snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, 0x00); | ||
686 | break; | ||
687 | case SND_SOC_BIAS_OFF: | ||
688 | snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, mask); | ||
689 | break; | ||
690 | } | ||
691 | |||
692 | codec->dapm.bias_level = level; | ||
693 | return 0; | ||
694 | } | ||
695 | |||
696 | /* Enforce the same sample rate on all audio interfaces */ | ||
697 | static int adav80x_dai_startup(struct snd_pcm_substream *substream, | ||
698 | struct snd_soc_dai *dai) | ||
699 | { | ||
700 | struct snd_soc_codec *codec = dai->codec; | ||
701 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
702 | |||
703 | if (!codec->active || !adav80x->rate) | ||
704 | return 0; | ||
705 | |||
706 | return snd_pcm_hw_constraint_minmax(substream->runtime, | ||
707 | SNDRV_PCM_HW_PARAM_RATE, adav80x->rate, adav80x->rate); | ||
708 | } | ||
709 | |||
710 | static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, | ||
711 | struct snd_soc_dai *dai) | ||
712 | { | ||
713 | struct snd_soc_codec *codec = dai->codec; | ||
714 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
715 | |||
716 | if (!codec->active) | ||
717 | adav80x->rate = 0; | ||
718 | } | ||
719 | |||
720 | static const struct snd_soc_dai_ops adav80x_dai_ops = { | ||
721 | .set_fmt = adav80x_set_dai_fmt, | ||
722 | .hw_params = adav80x_hw_params, | ||
723 | .startup = adav80x_dai_startup, | ||
724 | .shutdown = adav80x_dai_shutdown, | ||
725 | }; | ||
726 | |||
727 | #define ADAV80X_PLAYBACK_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
728 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | \ | ||
729 | SNDRV_PCM_RATE_96000) | ||
730 | |||
731 | #define ADAV80X_CAPTURE_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) | ||
732 | |||
733 | #define ADAV80X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ | ||
734 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) | ||
735 | |||
736 | static struct snd_soc_dai_driver adav80x_dais[] = { | ||
737 | { | ||
738 | .name = "adav80x-hifi", | ||
739 | .id = 0, | ||
740 | .playback = { | ||
741 | .stream_name = "HiFi Playback", | ||
742 | .channels_min = 2, | ||
743 | .channels_max = 2, | ||
744 | .rates = ADAV80X_PLAYBACK_RATES, | ||
745 | .formats = ADAV80X_FORMATS, | ||
746 | }, | ||
747 | .capture = { | ||
748 | .stream_name = "HiFi Capture", | ||
749 | .channels_min = 2, | ||
750 | .channels_max = 2, | ||
751 | .rates = ADAV80X_CAPTURE_RATES, | ||
752 | .formats = ADAV80X_FORMATS, | ||
753 | }, | ||
754 | .ops = &adav80x_dai_ops, | ||
755 | }, | ||
756 | { | ||
757 | .name = "adav80x-aux", | ||
758 | .id = 1, | ||
759 | .playback = { | ||
760 | .stream_name = "Aux Playback", | ||
761 | .channels_min = 2, | ||
762 | .channels_max = 2, | ||
763 | .rates = ADAV80X_PLAYBACK_RATES, | ||
764 | .formats = ADAV80X_FORMATS, | ||
765 | }, | ||
766 | .capture = { | ||
767 | .stream_name = "Aux Capture", | ||
768 | .channels_min = 2, | ||
769 | .channels_max = 2, | ||
770 | .rates = ADAV80X_CAPTURE_RATES, | ||
771 | .formats = ADAV80X_FORMATS, | ||
772 | }, | ||
773 | .ops = &adav80x_dai_ops, | ||
774 | }, | ||
775 | }; | ||
776 | |||
777 | static int adav80x_probe(struct snd_soc_codec *codec) | ||
778 | { | ||
779 | int ret; | ||
780 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | ||
781 | |||
782 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, adav80x->control_type); | ||
783 | if (ret) { | ||
784 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); | ||
785 | return ret; | ||
786 | } | ||
787 | |||
788 | /* Force PLLs on for SYSCLK output */ | ||
789 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); | ||
790 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); | ||
791 | |||
792 | /* Power down S/PDIF receiver, since it is currently not supported */ | ||
793 | snd_soc_write(codec, ADAV80X_PLL_OUTE, 0x20); | ||
794 | /* Disable DAC zero flag */ | ||
795 | snd_soc_write(codec, ADAV80X_DAC_CTRL3, 0x6); | ||
796 | |||
797 | return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
798 | } | ||
799 | |||
800 | static int adav80x_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
801 | { | ||
802 | return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
803 | } | ||
804 | |||
805 | static int adav80x_resume(struct snd_soc_codec *codec) | ||
806 | { | ||
807 | adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
808 | codec->cache_sync = 1; | ||
809 | snd_soc_cache_sync(codec); | ||
810 | |||
811 | return 0; | ||
812 | } | ||
813 | |||
814 | static int adav80x_remove(struct snd_soc_codec *codec) | ||
815 | { | ||
816 | return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
817 | } | ||
818 | |||
819 | static struct snd_soc_codec_driver adav80x_codec_driver = { | ||
820 | .probe = adav80x_probe, | ||
821 | .remove = adav80x_remove, | ||
822 | .suspend = adav80x_suspend, | ||
823 | .resume = adav80x_resume, | ||
824 | .set_bias_level = adav80x_set_bias_level, | ||
825 | |||
826 | .set_pll = adav80x_set_pll, | ||
827 | .set_sysclk = adav80x_set_sysclk, | ||
828 | |||
829 | .reg_word_size = sizeof(u8), | ||
830 | .reg_cache_size = ARRAY_SIZE(adav80x_default_regs), | ||
831 | .reg_cache_default = adav80x_default_regs, | ||
832 | |||
833 | .controls = adav80x_controls, | ||
834 | .num_controls = ARRAY_SIZE(adav80x_controls), | ||
835 | .dapm_widgets = adav80x_dapm_widgets, | ||
836 | .num_dapm_widgets = ARRAY_SIZE(adav80x_dapm_widgets), | ||
837 | .dapm_routes = adav80x_dapm_routes, | ||
838 | .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), | ||
839 | }; | ||
840 | |||
841 | static int __devinit adav80x_bus_probe(struct device *dev, | ||
842 | enum snd_soc_control_type control_type) | ||
843 | { | ||
844 | struct adav80x *adav80x; | ||
845 | int ret; | ||
846 | |||
847 | adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL); | ||
848 | if (!adav80x) | ||
849 | return -ENOMEM; | ||
850 | |||
851 | dev_set_drvdata(dev, adav80x); | ||
852 | adav80x->control_type = control_type; | ||
853 | |||
854 | ret = snd_soc_register_codec(dev, &adav80x_codec_driver, | ||
855 | adav80x_dais, ARRAY_SIZE(adav80x_dais)); | ||
856 | if (ret) | ||
857 | kfree(adav80x); | ||
858 | |||
859 | return ret; | ||
860 | } | ||
861 | |||
862 | static int __devexit adav80x_bus_remove(struct device *dev) | ||
863 | { | ||
864 | snd_soc_unregister_codec(dev); | ||
865 | kfree(dev_get_drvdata(dev)); | ||
866 | return 0; | ||
867 | } | ||
868 | |||
869 | #if defined(CONFIG_SPI_MASTER) | ||
870 | static int __devinit adav80x_spi_probe(struct spi_device *spi) | ||
871 | { | ||
872 | return adav80x_bus_probe(&spi->dev, SND_SOC_SPI); | ||
873 | } | ||
874 | |||
875 | static int __devexit adav80x_spi_remove(struct spi_device *spi) | ||
876 | { | ||
877 | return adav80x_bus_remove(&spi->dev); | ||
878 | } | ||
879 | |||
880 | static struct spi_driver adav80x_spi_driver = { | ||
881 | .driver = { | ||
882 | .name = "adav801", | ||
883 | .owner = THIS_MODULE, | ||
884 | }, | ||
885 | .probe = adav80x_spi_probe, | ||
886 | .remove = __devexit_p(adav80x_spi_remove), | ||
887 | }; | ||
888 | #endif | ||
889 | |||
890 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
891 | static const struct i2c_device_id adav80x_id[] = { | ||
892 | { "adav803", 0 }, | ||
893 | { } | ||
894 | }; | ||
895 | MODULE_DEVICE_TABLE(i2c, adav80x_id); | ||
896 | |||
897 | static int __devinit adav80x_i2c_probe(struct i2c_client *client, | ||
898 | const struct i2c_device_id *id) | ||
899 | { | ||
900 | return adav80x_bus_probe(&client->dev, SND_SOC_I2C); | ||
901 | } | ||
902 | |||
903 | static int __devexit adav80x_i2c_remove(struct i2c_client *client) | ||
904 | { | ||
905 | return adav80x_bus_remove(&client->dev); | ||
906 | } | ||
907 | |||
908 | static struct i2c_driver adav80x_i2c_driver = { | ||
909 | .driver = { | ||
910 | .name = "adav803", | ||
911 | .owner = THIS_MODULE, | ||
912 | }, | ||
913 | .probe = adav80x_i2c_probe, | ||
914 | .remove = __devexit_p(adav80x_i2c_remove), | ||
915 | .id_table = adav80x_id, | ||
916 | }; | ||
917 | #endif | ||
918 | |||
919 | static int __init adav80x_init(void) | ||
920 | { | ||
921 | int ret = 0; | ||
922 | |||
923 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
924 | ret = i2c_add_driver(&adav80x_i2c_driver); | ||
925 | if (ret) | ||
926 | return ret; | ||
927 | #endif | ||
928 | |||
929 | #if defined(CONFIG_SPI_MASTER) | ||
930 | ret = spi_register_driver(&adav80x_spi_driver); | ||
931 | #endif | ||
932 | |||
933 | return ret; | ||
934 | } | ||
935 | module_init(adav80x_init); | ||
936 | |||
937 | static void __exit adav80x_exit(void) | ||
938 | { | ||
939 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
940 | i2c_del_driver(&adav80x_i2c_driver); | ||
941 | #endif | ||
942 | #if defined(CONFIG_SPI_MASTER) | ||
943 | spi_unregister_driver(&adav80x_spi_driver); | ||
944 | #endif | ||
945 | } | ||
946 | module_exit(adav80x_exit); | ||
947 | |||
948 | MODULE_DESCRIPTION("ASoC ADAV80x driver"); | ||
949 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
950 | MODULE_AUTHOR("Yi Li <yi.li@analog.com>>"); | ||
951 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/adav80x.h b/sound/soc/codecs/adav80x.h new file mode 100644 index 000000000000..adb0fc76d4e3 --- /dev/null +++ b/sound/soc/codecs/adav80x.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * header file for ADAV80X parts | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #ifndef _ADAV80X_H | ||
10 | #define _ADAV80X_H | ||
11 | |||
12 | enum adav80x_pll_src { | ||
13 | ADAV80X_PLL_SRC_XIN, | ||
14 | ADAV80X_PLL_SRC_XTAL, | ||
15 | ADAV80X_PLL_SRC_MCLKI, | ||
16 | }; | ||
17 | |||
18 | enum adav80x_pll { | ||
19 | ADAV80X_PLL1 = 0, | ||
20 | ADAV80X_PLL2 = 1, | ||
21 | }; | ||
22 | |||
23 | enum adav80x_clk_src { | ||
24 | ADAV80X_CLK_XIN = 0, | ||
25 | ADAV80X_CLK_MCLKI = 1, | ||
26 | ADAV80X_CLK_PLL1 = 2, | ||
27 | ADAV80X_CLK_PLL2 = 3, | ||
28 | ADAV80X_CLK_XTAL = 6, | ||
29 | |||
30 | ADAV80X_CLK_SYSCLK1 = 6, | ||
31 | ADAV80X_CLK_SYSCLK2 = 7, | ||
32 | ADAV80X_CLK_SYSCLK3 = 8, | ||
33 | }; | ||
34 | |||
35 | #endif | ||
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index ed96f247c2da..7a64e58cddc4 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c | |||
@@ -457,7 +457,7 @@ static struct snd_soc_dai_ops ak4641_pcm_dai_ops = { | |||
457 | .set_sysclk = ak4641_set_dai_sysclk, | 457 | .set_sysclk = ak4641_set_dai_sysclk, |
458 | }; | 458 | }; |
459 | 459 | ||
460 | struct snd_soc_dai_driver ak4641_dai[] = { | 460 | static struct snd_soc_dai_driver ak4641_dai[] = { |
461 | { | 461 | { |
462 | .name = "ak4641-hifi", | 462 | .name = "ak4641-hifi", |
463 | .id = 1, | 463 | .id = 1, |
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 4be0570e3f1f..65f46047b1cb 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -357,7 +357,7 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
357 | default: | 357 | default: |
358 | return -EINVAL; | 358 | return -EINVAL; |
359 | } | 359 | } |
360 | snd_soc_update_bits(codec, PW_MGMT2, MS, data); | 360 | snd_soc_update_bits(codec, PW_MGMT2, MS | MCKO | PMPLL, data); |
361 | snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko); | 361 | snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko); |
362 | 362 | ||
363 | /* format type */ | 363 | /* format type */ |
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 0206a17d7283..6cc8678f49f3 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -636,10 +636,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec) | |||
636 | #endif /* CONFIG_PM */ | 636 | #endif /* CONFIG_PM */ |
637 | 637 | ||
638 | /* | 638 | /* |
639 | * ASoC codec device structure | 639 | * ASoC codec driver structure |
640 | * | ||
641 | * Assign this variable to the codec_dev field of the machine driver's | ||
642 | * snd_soc_device structure. | ||
643 | */ | 640 | */ |
644 | static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { | 641 | static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { |
645 | .probe = cs4270_probe, | 642 | .probe = cs4270_probe, |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 4173b67c94d1..ac65a2d36408 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -1397,8 +1397,6 @@ static int max98088_dai_set_sysclk(struct snd_soc_dai *dai, | |||
1397 | if (freq == max98088->sysclk) | 1397 | if (freq == max98088->sysclk) |
1398 | return 0; | 1398 | return 0; |
1399 | 1399 | ||
1400 | max98088->sysclk = freq; /* remember current sysclk */ | ||
1401 | |||
1402 | /* Setup clocks for slave mode, and using the PLL | 1400 | /* Setup clocks for slave mode, and using the PLL |
1403 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) | 1401 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) |
1404 | * 0x02 (when master clk is 20MHz to 30MHz).. | 1402 | * 0x02 (when master clk is 20MHz to 30MHz).. |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index e1d282d477da..668434d44303 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c | |||
@@ -1517,8 +1517,6 @@ static int max98095_dai_set_sysclk(struct snd_soc_dai *dai, | |||
1517 | if (freq == max98095->sysclk) | 1517 | if (freq == max98095->sysclk) |
1518 | return 0; | 1518 | return 0; |
1519 | 1519 | ||
1520 | max98095->sysclk = freq; /* remember current sysclk */ | ||
1521 | |||
1522 | /* Setup clocks for slave mode, and using the PLL | 1520 | /* Setup clocks for slave mode, and using the PLL |
1523 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) | 1521 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) |
1524 | * 0x02 (when master clk is 20MHz to 40MHz).. | 1522 | * 0x02 (when master clk is 20MHz to 40MHz).. |
@@ -2261,11 +2259,11 @@ static int max98095_probe(struct snd_soc_codec *codec) | |||
2261 | 2259 | ||
2262 | ret = snd_soc_read(codec, M98095_0FF_REV_ID); | 2260 | ret = snd_soc_read(codec, M98095_0FF_REV_ID); |
2263 | if (ret < 0) { | 2261 | if (ret < 0) { |
2264 | dev_err(codec->dev, "Failed to read device revision: %d\n", | 2262 | dev_err(codec->dev, "Failure reading hardware revision: %d\n", |
2265 | ret); | 2263 | ret); |
2266 | goto err_access; | 2264 | goto err_access; |
2267 | } | 2265 | } |
2268 | dev_info(codec->dev, "revision %c\n", ret + 'A'); | 2266 | dev_info(codec->dev, "Hardware revision: %c\n", ret - 0x40 + 'A'); |
2269 | 2267 | ||
2270 | snd_soc_write(codec, M98095_097_PWR_SYS, M98095_PWRSV); | 2268 | snd_soc_write(codec, M98095_097_PWR_SYS, M98095_PWRSV); |
2271 | 2269 | ||
@@ -2342,8 +2340,8 @@ static int max98095_i2c_probe(struct i2c_client *i2c, | |||
2342 | max98095->control_data = i2c; | 2340 | max98095->control_data = i2c; |
2343 | max98095->pdata = i2c->dev.platform_data; | 2341 | max98095->pdata = i2c->dev.platform_data; |
2344 | 2342 | ||
2345 | ret = snd_soc_register_codec(&i2c->dev, | 2343 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98095, |
2346 | &soc_codec_dev_max98095, &max98095_dai[0], 3); | 2344 | max98095_dai, ARRAY_SIZE(max98095_dai)); |
2347 | if (ret < 0) | 2345 | if (ret < 0) |
2348 | kfree(max98095); | 2346 | kfree(max98095); |
2349 | return ret; | 2347 | return ret; |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c new file mode 100644 index 000000000000..409d89d1f34c --- /dev/null +++ b/sound/soc/codecs/sta32x.c | |||
@@ -0,0 +1,917 @@ | |||
1 | /* | ||
2 | * Codec driver for ST STA32x 2.1-channel high-efficiency digital audio system | ||
3 | * | ||
4 | * Copyright: 2011 Raumfeld GmbH | ||
5 | * Author: Johannes Stezenbach <js@sig21.net> | ||
6 | * | ||
7 | * based on code from: | ||
8 | * Wolfson Microelectronics PLC. | ||
9 | * Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
10 | * Freescale Semiconductor, Inc. | ||
11 | * Timur Tabi <timur@freescale.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | */ | ||
18 | |||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s:%d: " fmt, __func__, __LINE__ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/pm.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/regulator/consumer.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <sound/core.h> | ||
31 | #include <sound/pcm.h> | ||
32 | #include <sound/pcm_params.h> | ||
33 | #include <sound/soc.h> | ||
34 | #include <sound/soc-dapm.h> | ||
35 | #include <sound/initval.h> | ||
36 | #include <sound/tlv.h> | ||
37 | |||
38 | #include "sta32x.h" | ||
39 | |||
40 | #define STA32X_RATES (SNDRV_PCM_RATE_32000 | \ | ||
41 | SNDRV_PCM_RATE_44100 | \ | ||
42 | SNDRV_PCM_RATE_48000 | \ | ||
43 | SNDRV_PCM_RATE_88200 | \ | ||
44 | SNDRV_PCM_RATE_96000 | \ | ||
45 | SNDRV_PCM_RATE_176400 | \ | ||
46 | SNDRV_PCM_RATE_192000) | ||
47 | |||
48 | #define STA32X_FORMATS \ | ||
49 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ | ||
50 | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ | ||
51 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ | ||
52 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ | ||
53 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \ | ||
54 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) | ||
55 | |||
56 | /* Power-up register defaults */ | ||
57 | static const u8 sta32x_regs[STA32X_REGISTER_COUNT] = { | ||
58 | 0x63, 0x80, 0xc2, 0x40, 0xc2, 0x5c, 0x10, 0xff, 0x60, 0x60, | ||
59 | 0x60, 0x80, 0x00, 0x00, 0x00, 0x40, 0x80, 0x77, 0x6a, 0x69, | ||
60 | 0x6a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, | ||
62 | 0xc0, 0xf3, 0x33, 0x00, 0x0c, | ||
63 | }; | ||
64 | |||
65 | /* regulator power supply names */ | ||
66 | static const char *sta32x_supply_names[] = { | ||
67 | "Vdda", /* analog supply, 3.3VV */ | ||
68 | "Vdd3", /* digital supply, 3.3V */ | ||
69 | "Vcc" /* power amp spply, 10V - 36V */ | ||
70 | }; | ||
71 | |||
72 | /* codec private data */ | ||
73 | struct sta32x_priv { | ||
74 | struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; | ||
75 | struct snd_soc_codec *codec; | ||
76 | |||
77 | unsigned int mclk; | ||
78 | unsigned int format; | ||
79 | }; | ||
80 | |||
81 | static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1); | ||
82 | static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1); | ||
83 | static const DECLARE_TLV_DB_SCALE(tone_tlv, -120, 200, 0); | ||
84 | |||
85 | static const char *sta32x_drc_ac[] = { | ||
86 | "Anti-Clipping", "Dynamic Range Compression" }; | ||
87 | static const char *sta32x_auto_eq_mode[] = { | ||
88 | "User", "Preset", "Loudness" }; | ||
89 | static const char *sta32x_auto_gc_mode[] = { | ||
90 | "User", "AC no clipping", "AC limited clipping (10%)", | ||
91 | "DRC nighttime listening mode" }; | ||
92 | static const char *sta32x_auto_xo_mode[] = { | ||
93 | "User", "80Hz", "100Hz", "120Hz", "140Hz", "160Hz", "180Hz", "200Hz", | ||
94 | "220Hz", "240Hz", "260Hz", "280Hz", "300Hz", "320Hz", "340Hz", "360Hz" }; | ||
95 | static const char *sta32x_preset_eq_mode[] = { | ||
96 | "Flat", "Rock", "Soft Rock", "Jazz", "Classical", "Dance", "Pop", "Soft", | ||
97 | "Hard", "Party", "Vocal", "Hip-Hop", "Dialog", "Bass-boost #1", | ||
98 | "Bass-boost #2", "Bass-boost #3", "Loudness 1", "Loudness 2", | ||
99 | "Loudness 3", "Loudness 4", "Loudness 5", "Loudness 6", "Loudness 7", | ||
100 | "Loudness 8", "Loudness 9", "Loudness 10", "Loudness 11", "Loudness 12", | ||
101 | "Loudness 13", "Loudness 14", "Loudness 15", "Loudness 16" }; | ||
102 | static const char *sta32x_limiter_select[] = { | ||
103 | "Limiter Disabled", "Limiter #1", "Limiter #2" }; | ||
104 | static const char *sta32x_limiter_attack_rate[] = { | ||
105 | "3.1584", "2.7072", "2.2560", "1.8048", "1.3536", "0.9024", | ||
106 | "0.4512", "0.2256", "0.1504", "0.1123", "0.0902", "0.0752", | ||
107 | "0.0645", "0.0564", "0.0501", "0.0451" }; | ||
108 | static const char *sta32x_limiter_release_rate[] = { | ||
109 | "0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299", | ||
110 | "0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137", | ||
111 | "0.0134", "0.0117", "0.0110", "0.0104" }; | ||
112 | |||
113 | static const unsigned int sta32x_limiter_ac_attack_tlv[] = { | ||
114 | TLV_DB_RANGE_HEAD(2), | ||
115 | 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0), | ||
116 | 8, 16, TLV_DB_SCALE_ITEM(300, 100, 0), | ||
117 | }; | ||
118 | |||
119 | static const unsigned int sta32x_limiter_ac_release_tlv[] = { | ||
120 | TLV_DB_RANGE_HEAD(5), | ||
121 | 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), | ||
122 | 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0), | ||
123 | 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0), | ||
124 | 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0), | ||
125 | 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0), | ||
126 | }; | ||
127 | |||
128 | static const unsigned int sta32x_limiter_drc_attack_tlv[] = { | ||
129 | TLV_DB_RANGE_HEAD(3), | ||
130 | 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0), | ||
131 | 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0), | ||
132 | 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0), | ||
133 | }; | ||
134 | |||
135 | static const unsigned int sta32x_limiter_drc_release_tlv[] = { | ||
136 | TLV_DB_RANGE_HEAD(5), | ||
137 | 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), | ||
138 | 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0), | ||
139 | 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0), | ||
140 | 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0), | ||
141 | 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0), | ||
142 | }; | ||
143 | |||
144 | static const struct soc_enum sta32x_drc_ac_enum = | ||
145 | SOC_ENUM_SINGLE(STA32X_CONFD, STA32X_CONFD_DRC_SHIFT, | ||
146 | 2, sta32x_drc_ac); | ||
147 | static const struct soc_enum sta32x_auto_eq_enum = | ||
148 | SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT, | ||
149 | 3, sta32x_auto_eq_mode); | ||
150 | static const struct soc_enum sta32x_auto_gc_enum = | ||
151 | SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT, | ||
152 | 4, sta32x_auto_gc_mode); | ||
153 | static const struct soc_enum sta32x_auto_xo_enum = | ||
154 | SOC_ENUM_SINGLE(STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT, | ||
155 | 16, sta32x_auto_xo_mode); | ||
156 | static const struct soc_enum sta32x_preset_eq_enum = | ||
157 | SOC_ENUM_SINGLE(STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT, | ||
158 | 32, sta32x_preset_eq_mode); | ||
159 | static const struct soc_enum sta32x_limiter_ch1_enum = | ||
160 | SOC_ENUM_SINGLE(STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT, | ||
161 | 3, sta32x_limiter_select); | ||
162 | static const struct soc_enum sta32x_limiter_ch2_enum = | ||
163 | SOC_ENUM_SINGLE(STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT, | ||
164 | 3, sta32x_limiter_select); | ||
165 | static const struct soc_enum sta32x_limiter_ch3_enum = | ||
166 | SOC_ENUM_SINGLE(STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT, | ||
167 | 3, sta32x_limiter_select); | ||
168 | static const struct soc_enum sta32x_limiter1_attack_rate_enum = | ||
169 | SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxA_SHIFT, | ||
170 | 16, sta32x_limiter_attack_rate); | ||
171 | static const struct soc_enum sta32x_limiter2_attack_rate_enum = | ||
172 | SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxA_SHIFT, | ||
173 | 16, sta32x_limiter_attack_rate); | ||
174 | static const struct soc_enum sta32x_limiter1_release_rate_enum = | ||
175 | SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxR_SHIFT, | ||
176 | 16, sta32x_limiter_release_rate); | ||
177 | static const struct soc_enum sta32x_limiter2_release_rate_enum = | ||
178 | SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxR_SHIFT, | ||
179 | 16, sta32x_limiter_release_rate); | ||
180 | |||
181 | /* byte array controls for setting biquad, mixer, scaling coefficients; | ||
182 | * for biquads all five coefficients need to be set in one go, | ||
183 | * mixer and pre/postscale coefs can be set individually; | ||
184 | * each coef is 24bit, the bytes are ordered in the same way | ||
185 | * as given in the STA32x data sheet (big endian; b1, b2, a1, a2, b0) | ||
186 | */ | ||
187 | |||
188 | static int sta32x_coefficient_info(struct snd_kcontrol *kcontrol, | ||
189 | struct snd_ctl_elem_info *uinfo) | ||
190 | { | ||
191 | int numcoef = kcontrol->private_value >> 16; | ||
192 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
193 | uinfo->count = 3 * numcoef; | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static int sta32x_coefficient_get(struct snd_kcontrol *kcontrol, | ||
198 | struct snd_ctl_elem_value *ucontrol) | ||
199 | { | ||
200 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
201 | int numcoef = kcontrol->private_value >> 16; | ||
202 | int index = kcontrol->private_value & 0xffff; | ||
203 | unsigned int cfud; | ||
204 | int i; | ||
205 | |||
206 | /* preserve reserved bits in STA32X_CFUD */ | ||
207 | cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; | ||
208 | /* chip documentation does not say if the bits are self clearing, | ||
209 | * so do it explicitly */ | ||
210 | snd_soc_write(codec, STA32X_CFUD, cfud); | ||
211 | |||
212 | snd_soc_write(codec, STA32X_CFADDR2, index); | ||
213 | if (numcoef == 1) | ||
214 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x04); | ||
215 | else if (numcoef == 5) | ||
216 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x08); | ||
217 | else | ||
218 | return -EINVAL; | ||
219 | for (i = 0; i < 3 * numcoef; i++) | ||
220 | ucontrol->value.bytes.data[i] = | ||
221 | snd_soc_read(codec, STA32X_B1CF1 + i); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol, | ||
227 | struct snd_ctl_elem_value *ucontrol) | ||
228 | { | ||
229 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
230 | int numcoef = kcontrol->private_value >> 16; | ||
231 | int index = kcontrol->private_value & 0xffff; | ||
232 | unsigned int cfud; | ||
233 | int i; | ||
234 | |||
235 | /* preserve reserved bits in STA32X_CFUD */ | ||
236 | cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; | ||
237 | /* chip documentation does not say if the bits are self clearing, | ||
238 | * so do it explicitly */ | ||
239 | snd_soc_write(codec, STA32X_CFUD, cfud); | ||
240 | |||
241 | snd_soc_write(codec, STA32X_CFADDR2, index); | ||
242 | for (i = 0; i < 3 * numcoef; i++) | ||
243 | snd_soc_write(codec, STA32X_B1CF1 + i, | ||
244 | ucontrol->value.bytes.data[i]); | ||
245 | if (numcoef == 1) | ||
246 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x01); | ||
247 | else if (numcoef == 5) | ||
248 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x02); | ||
249 | else | ||
250 | return -EINVAL; | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | #define SINGLE_COEF(xname, index) \ | ||
256 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
257 | .info = sta32x_coefficient_info, \ | ||
258 | .get = sta32x_coefficient_get,\ | ||
259 | .put = sta32x_coefficient_put, \ | ||
260 | .private_value = index | (1 << 16) } | ||
261 | |||
262 | #define BIQUAD_COEFS(xname, index) \ | ||
263 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
264 | .info = sta32x_coefficient_info, \ | ||
265 | .get = sta32x_coefficient_get,\ | ||
266 | .put = sta32x_coefficient_put, \ | ||
267 | .private_value = index | (5 << 16) } | ||
268 | |||
269 | static const struct snd_kcontrol_new sta32x_snd_controls[] = { | ||
270 | SOC_SINGLE_TLV("Master Volume", STA32X_MVOL, 0, 0xff, 1, mvol_tlv), | ||
271 | SOC_SINGLE("Master Switch", STA32X_MMUTE, 0, 1, 1), | ||
272 | SOC_SINGLE("Ch1 Switch", STA32X_MMUTE, 1, 1, 1), | ||
273 | SOC_SINGLE("Ch2 Switch", STA32X_MMUTE, 2, 1, 1), | ||
274 | SOC_SINGLE("Ch3 Switch", STA32X_MMUTE, 3, 1, 1), | ||
275 | SOC_SINGLE_TLV("Ch1 Volume", STA32X_C1VOL, 0, 0xff, 1, chvol_tlv), | ||
276 | SOC_SINGLE_TLV("Ch2 Volume", STA32X_C2VOL, 0, 0xff, 1, chvol_tlv), | ||
277 | SOC_SINGLE_TLV("Ch3 Volume", STA32X_C3VOL, 0, 0xff, 1, chvol_tlv), | ||
278 | SOC_SINGLE("De-emphasis Filter Switch", STA32X_CONFD, STA32X_CONFD_DEMP_SHIFT, 1, 0), | ||
279 | SOC_ENUM("Compressor/Limiter Switch", sta32x_drc_ac_enum), | ||
280 | SOC_SINGLE("Miami Mode Switch", STA32X_CONFD, STA32X_CONFD_MME_SHIFT, 1, 0), | ||
281 | SOC_SINGLE("Zero Cross Switch", STA32X_CONFE, STA32X_CONFE_ZCE_SHIFT, 1, 0), | ||
282 | SOC_SINGLE("Soft Ramp Switch", STA32X_CONFE, STA32X_CONFE_SVE_SHIFT, 1, 0), | ||
283 | SOC_SINGLE("Auto-Mute Switch", STA32X_CONFF, STA32X_CONFF_IDE_SHIFT, 1, 0), | ||
284 | SOC_ENUM("Automode EQ", sta32x_auto_eq_enum), | ||
285 | SOC_ENUM("Automode GC", sta32x_auto_gc_enum), | ||
286 | SOC_ENUM("Automode XO", sta32x_auto_xo_enum), | ||
287 | SOC_ENUM("Preset EQ", sta32x_preset_eq_enum), | ||
288 | SOC_SINGLE("Ch1 Tone Control Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0), | ||
289 | SOC_SINGLE("Ch2 Tone Control Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0), | ||
290 | SOC_SINGLE("Ch1 EQ Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0), | ||
291 | SOC_SINGLE("Ch2 EQ Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0), | ||
292 | SOC_SINGLE("Ch1 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0), | ||
293 | SOC_SINGLE("Ch2 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0), | ||
294 | SOC_SINGLE("Ch3 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0), | ||
295 | SOC_ENUM("Ch1 Limiter Select", sta32x_limiter_ch1_enum), | ||
296 | SOC_ENUM("Ch2 Limiter Select", sta32x_limiter_ch2_enum), | ||
297 | SOC_ENUM("Ch3 Limiter Select", sta32x_limiter_ch3_enum), | ||
298 | SOC_SINGLE_TLV("Bass Tone Control", STA32X_TONE, STA32X_TONE_BTC_SHIFT, 15, 0, tone_tlv), | ||
299 | SOC_SINGLE_TLV("Treble Tone Control", STA32X_TONE, STA32X_TONE_TTC_SHIFT, 15, 0, tone_tlv), | ||
300 | SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum), | ||
301 | SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum), | ||
302 | SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum), | ||
303 | SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum), | ||
304 | |||
305 | /* depending on mode, the attack/release thresholds have | ||
306 | * two different enum definitions; provide both | ||
307 | */ | ||
308 | SOC_SINGLE_TLV("Limiter1 Attack Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT, | ||
309 | 16, 0, sta32x_limiter_ac_attack_tlv), | ||
310 | SOC_SINGLE_TLV("Limiter2 Attack Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT, | ||
311 | 16, 0, sta32x_limiter_ac_attack_tlv), | ||
312 | SOC_SINGLE_TLV("Limiter1 Release Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT, | ||
313 | 16, 0, sta32x_limiter_ac_release_tlv), | ||
314 | SOC_SINGLE_TLV("Limiter2 Release Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT, | ||
315 | 16, 0, sta32x_limiter_ac_release_tlv), | ||
316 | SOC_SINGLE_TLV("Limiter1 Attack Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT, | ||
317 | 16, 0, sta32x_limiter_drc_attack_tlv), | ||
318 | SOC_SINGLE_TLV("Limiter2 Attack Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT, | ||
319 | 16, 0, sta32x_limiter_drc_attack_tlv), | ||
320 | SOC_SINGLE_TLV("Limiter1 Release Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT, | ||
321 | 16, 0, sta32x_limiter_drc_release_tlv), | ||
322 | SOC_SINGLE_TLV("Limiter2 Release Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT, | ||
323 | 16, 0, sta32x_limiter_drc_release_tlv), | ||
324 | |||
325 | BIQUAD_COEFS("Ch1 - Biquad 1", 0), | ||
326 | BIQUAD_COEFS("Ch1 - Biquad 2", 5), | ||
327 | BIQUAD_COEFS("Ch1 - Biquad 3", 10), | ||
328 | BIQUAD_COEFS("Ch1 - Biquad 4", 15), | ||
329 | BIQUAD_COEFS("Ch2 - Biquad 1", 20), | ||
330 | BIQUAD_COEFS("Ch2 - Biquad 2", 25), | ||
331 | BIQUAD_COEFS("Ch2 - Biquad 3", 30), | ||
332 | BIQUAD_COEFS("Ch2 - Biquad 4", 35), | ||
333 | BIQUAD_COEFS("High-pass", 40), | ||
334 | BIQUAD_COEFS("Low-pass", 45), | ||
335 | SINGLE_COEF("Ch1 - Prescale", 50), | ||
336 | SINGLE_COEF("Ch2 - Prescale", 51), | ||
337 | SINGLE_COEF("Ch1 - Postscale", 52), | ||
338 | SINGLE_COEF("Ch2 - Postscale", 53), | ||
339 | SINGLE_COEF("Ch3 - Postscale", 54), | ||
340 | SINGLE_COEF("Thermal warning - Postscale", 55), | ||
341 | SINGLE_COEF("Ch1 - Mix 1", 56), | ||
342 | SINGLE_COEF("Ch1 - Mix 2", 57), | ||
343 | SINGLE_COEF("Ch2 - Mix 1", 58), | ||
344 | SINGLE_COEF("Ch2 - Mix 2", 59), | ||
345 | SINGLE_COEF("Ch3 - Mix 1", 60), | ||
346 | SINGLE_COEF("Ch3 - Mix 2", 61), | ||
347 | }; | ||
348 | |||
349 | static const struct snd_soc_dapm_widget sta32x_dapm_widgets[] = { | ||
350 | SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), | ||
351 | SND_SOC_DAPM_OUTPUT("LEFT"), | ||
352 | SND_SOC_DAPM_OUTPUT("RIGHT"), | ||
353 | SND_SOC_DAPM_OUTPUT("SUB"), | ||
354 | }; | ||
355 | |||
356 | static const struct snd_soc_dapm_route sta32x_dapm_routes[] = { | ||
357 | { "LEFT", NULL, "DAC" }, | ||
358 | { "RIGHT", NULL, "DAC" }, | ||
359 | { "SUB", NULL, "DAC" }, | ||
360 | }; | ||
361 | |||
362 | /* MCLK interpolation ratio per fs */ | ||
363 | static struct { | ||
364 | int fs; | ||
365 | int ir; | ||
366 | } interpolation_ratios[] = { | ||
367 | { 32000, 0 }, | ||
368 | { 44100, 0 }, | ||
369 | { 48000, 0 }, | ||
370 | { 88200, 1 }, | ||
371 | { 96000, 1 }, | ||
372 | { 176400, 2 }, | ||
373 | { 192000, 2 }, | ||
374 | }; | ||
375 | |||
376 | /* MCLK to fs clock ratios */ | ||
377 | static struct { | ||
378 | int ratio; | ||
379 | int mcs; | ||
380 | } mclk_ratios[3][7] = { | ||
381 | { { 768, 0 }, { 512, 1 }, { 384, 2 }, { 256, 3 }, | ||
382 | { 128, 4 }, { 576, 5 }, { 0, 0 } }, | ||
383 | { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } }, | ||
384 | { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } }, | ||
385 | }; | ||
386 | |||
387 | |||
388 | /** | ||
389 | * sta32x_set_dai_sysclk - configure MCLK | ||
390 | * @codec_dai: the codec DAI | ||
391 | * @clk_id: the clock ID (ignored) | ||
392 | * @freq: the MCLK input frequency | ||
393 | * @dir: the clock direction (ignored) | ||
394 | * | ||
395 | * The value of MCLK is used to determine which sample rates are supported | ||
396 | * by the STA32X, based on the mclk_ratios table. | ||
397 | * | ||
398 | * This function must be called by the machine driver's 'startup' function, | ||
399 | * otherwise the list of supported sample rates will not be available in | ||
400 | * time for ALSA. | ||
401 | * | ||
402 | * For setups with variable MCLKs, pass 0 as 'freq' argument. This will cause | ||
403 | * theoretically possible sample rates to be enabled. Call it again with a | ||
404 | * proper value set one the external clock is set (most probably you would do | ||
405 | * that from a machine's driver 'hw_param' hook. | ||
406 | */ | ||
407 | static int sta32x_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
408 | int clk_id, unsigned int freq, int dir) | ||
409 | { | ||
410 | struct snd_soc_codec *codec = codec_dai->codec; | ||
411 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
412 | int i, j, ir, fs; | ||
413 | unsigned int rates = 0; | ||
414 | unsigned int rate_min = -1; | ||
415 | unsigned int rate_max = 0; | ||
416 | |||
417 | pr_debug("mclk=%u\n", freq); | ||
418 | sta32x->mclk = freq; | ||
419 | |||
420 | if (sta32x->mclk) { | ||
421 | for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) { | ||
422 | ir = interpolation_ratios[i].ir; | ||
423 | fs = interpolation_ratios[i].fs; | ||
424 | for (j = 0; mclk_ratios[ir][j].ratio; j++) { | ||
425 | if (mclk_ratios[ir][j].ratio * fs == freq) { | ||
426 | rates |= snd_pcm_rate_to_rate_bit(fs); | ||
427 | if (fs < rate_min) | ||
428 | rate_min = fs; | ||
429 | if (fs > rate_max) | ||
430 | rate_max = fs; | ||
431 | } | ||
432 | } | ||
433 | } | ||
434 | /* FIXME: soc should support a rate list */ | ||
435 | rates &= ~SNDRV_PCM_RATE_KNOT; | ||
436 | |||
437 | if (!rates) { | ||
438 | dev_err(codec->dev, "could not find a valid sample rate\n"); | ||
439 | return -EINVAL; | ||
440 | } | ||
441 | } else { | ||
442 | /* enable all possible rates */ | ||
443 | rates = STA32X_RATES; | ||
444 | rate_min = 32000; | ||
445 | rate_max = 192000; | ||
446 | } | ||
447 | |||
448 | codec_dai->driver->playback.rates = rates; | ||
449 | codec_dai->driver->playback.rate_min = rate_min; | ||
450 | codec_dai->driver->playback.rate_max = rate_max; | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | /** | ||
455 | * sta32x_set_dai_fmt - configure the codec for the selected audio format | ||
456 | * @codec_dai: the codec DAI | ||
457 | * @fmt: a SND_SOC_DAIFMT_x value indicating the data format | ||
458 | * | ||
459 | * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the | ||
460 | * codec accordingly. | ||
461 | */ | ||
462 | static int sta32x_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
463 | unsigned int fmt) | ||
464 | { | ||
465 | struct snd_soc_codec *codec = codec_dai->codec; | ||
466 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
467 | u8 confb = snd_soc_read(codec, STA32X_CONFB); | ||
468 | |||
469 | pr_debug("\n"); | ||
470 | confb &= ~(STA32X_CONFB_C1IM | STA32X_CONFB_C2IM); | ||
471 | |||
472 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
473 | case SND_SOC_DAIFMT_CBS_CFS: | ||
474 | break; | ||
475 | default: | ||
476 | return -EINVAL; | ||
477 | } | ||
478 | |||
479 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
480 | case SND_SOC_DAIFMT_I2S: | ||
481 | case SND_SOC_DAIFMT_RIGHT_J: | ||
482 | case SND_SOC_DAIFMT_LEFT_J: | ||
483 | sta32x->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | ||
484 | break; | ||
485 | default: | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | |||
489 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
490 | case SND_SOC_DAIFMT_NB_NF: | ||
491 | confb |= STA32X_CONFB_C2IM; | ||
492 | break; | ||
493 | case SND_SOC_DAIFMT_NB_IF: | ||
494 | confb |= STA32X_CONFB_C1IM; | ||
495 | break; | ||
496 | default: | ||
497 | return -EINVAL; | ||
498 | } | ||
499 | |||
500 | snd_soc_write(codec, STA32X_CONFB, confb); | ||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | /** | ||
505 | * sta32x_hw_params - program the STA32X with the given hardware parameters. | ||
506 | * @substream: the audio stream | ||
507 | * @params: the hardware parameters to set | ||
508 | * @dai: the SOC DAI (ignored) | ||
509 | * | ||
510 | * This function programs the hardware with the values provided. | ||
511 | * Specifically, the sample rate and the data format. | ||
512 | */ | ||
513 | static int sta32x_hw_params(struct snd_pcm_substream *substream, | ||
514 | struct snd_pcm_hw_params *params, | ||
515 | struct snd_soc_dai *dai) | ||
516 | { | ||
517 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
518 | struct snd_soc_codec *codec = rtd->codec; | ||
519 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
520 | unsigned int rate; | ||
521 | int i, mcs = -1, ir = -1; | ||
522 | u8 confa, confb; | ||
523 | |||
524 | rate = params_rate(params); | ||
525 | pr_debug("rate: %u\n", rate); | ||
526 | for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) | ||
527 | if (interpolation_ratios[i].fs == rate) | ||
528 | ir = interpolation_ratios[i].ir; | ||
529 | if (ir < 0) | ||
530 | return -EINVAL; | ||
531 | for (i = 0; mclk_ratios[ir][i].ratio; i++) | ||
532 | if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) | ||
533 | mcs = mclk_ratios[ir][i].mcs; | ||
534 | if (mcs < 0) | ||
535 | return -EINVAL; | ||
536 | |||
537 | confa = snd_soc_read(codec, STA32X_CONFA); | ||
538 | confa &= ~(STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK); | ||
539 | confa |= (ir << STA32X_CONFA_IR_SHIFT) | (mcs << STA32X_CONFA_MCS_SHIFT); | ||
540 | |||
541 | confb = snd_soc_read(codec, STA32X_CONFB); | ||
542 | confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB); | ||
543 | switch (params_format(params)) { | ||
544 | case SNDRV_PCM_FORMAT_S24_LE: | ||
545 | case SNDRV_PCM_FORMAT_S24_BE: | ||
546 | case SNDRV_PCM_FORMAT_S24_3LE: | ||
547 | case SNDRV_PCM_FORMAT_S24_3BE: | ||
548 | pr_debug("24bit\n"); | ||
549 | /* fall through */ | ||
550 | case SNDRV_PCM_FORMAT_S32_LE: | ||
551 | case SNDRV_PCM_FORMAT_S32_BE: | ||
552 | pr_debug("24bit or 32bit\n"); | ||
553 | switch (sta32x->format) { | ||
554 | case SND_SOC_DAIFMT_I2S: | ||
555 | confb |= 0x0; | ||
556 | break; | ||
557 | case SND_SOC_DAIFMT_LEFT_J: | ||
558 | confb |= 0x1; | ||
559 | break; | ||
560 | case SND_SOC_DAIFMT_RIGHT_J: | ||
561 | confb |= 0x2; | ||
562 | break; | ||
563 | } | ||
564 | |||
565 | break; | ||
566 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
567 | case SNDRV_PCM_FORMAT_S20_3BE: | ||
568 | pr_debug("20bit\n"); | ||
569 | switch (sta32x->format) { | ||
570 | case SND_SOC_DAIFMT_I2S: | ||
571 | confb |= 0x4; | ||
572 | break; | ||
573 | case SND_SOC_DAIFMT_LEFT_J: | ||
574 | confb |= 0x5; | ||
575 | break; | ||
576 | case SND_SOC_DAIFMT_RIGHT_J: | ||
577 | confb |= 0x6; | ||
578 | break; | ||
579 | } | ||
580 | |||
581 | break; | ||
582 | case SNDRV_PCM_FORMAT_S18_3LE: | ||
583 | case SNDRV_PCM_FORMAT_S18_3BE: | ||
584 | pr_debug("18bit\n"); | ||
585 | switch (sta32x->format) { | ||
586 | case SND_SOC_DAIFMT_I2S: | ||
587 | confb |= 0x8; | ||
588 | break; | ||
589 | case SND_SOC_DAIFMT_LEFT_J: | ||
590 | confb |= 0x9; | ||
591 | break; | ||
592 | case SND_SOC_DAIFMT_RIGHT_J: | ||
593 | confb |= 0xa; | ||
594 | break; | ||
595 | } | ||
596 | |||
597 | break; | ||
598 | case SNDRV_PCM_FORMAT_S16_LE: | ||
599 | case SNDRV_PCM_FORMAT_S16_BE: | ||
600 | pr_debug("16bit\n"); | ||
601 | switch (sta32x->format) { | ||
602 | case SND_SOC_DAIFMT_I2S: | ||
603 | confb |= 0x0; | ||
604 | break; | ||
605 | case SND_SOC_DAIFMT_LEFT_J: | ||
606 | confb |= 0xd; | ||
607 | break; | ||
608 | case SND_SOC_DAIFMT_RIGHT_J: | ||
609 | confb |= 0xe; | ||
610 | break; | ||
611 | } | ||
612 | |||
613 | break; | ||
614 | default: | ||
615 | return -EINVAL; | ||
616 | } | ||
617 | |||
618 | snd_soc_write(codec, STA32X_CONFA, confa); | ||
619 | snd_soc_write(codec, STA32X_CONFB, confb); | ||
620 | return 0; | ||
621 | } | ||
622 | |||
623 | /** | ||
624 | * sta32x_set_bias_level - DAPM callback | ||
625 | * @codec: the codec device | ||
626 | * @level: DAPM power level | ||
627 | * | ||
628 | * This is called by ALSA to put the codec into low power mode | ||
629 | * or to wake it up. If the codec is powered off completely | ||
630 | * all registers must be restored after power on. | ||
631 | */ | ||
632 | static int sta32x_set_bias_level(struct snd_soc_codec *codec, | ||
633 | enum snd_soc_bias_level level) | ||
634 | { | ||
635 | int ret; | ||
636 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
637 | |||
638 | pr_debug("level = %d\n", level); | ||
639 | switch (level) { | ||
640 | case SND_SOC_BIAS_ON: | ||
641 | break; | ||
642 | |||
643 | case SND_SOC_BIAS_PREPARE: | ||
644 | /* Full power on */ | ||
645 | snd_soc_update_bits(codec, STA32X_CONFF, | ||
646 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, | ||
647 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD); | ||
648 | break; | ||
649 | |||
650 | case SND_SOC_BIAS_STANDBY: | ||
651 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
652 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), | ||
653 | sta32x->supplies); | ||
654 | if (ret != 0) { | ||
655 | dev_err(codec->dev, | ||
656 | "Failed to enable supplies: %d\n", ret); | ||
657 | return ret; | ||
658 | } | ||
659 | |||
660 | snd_soc_cache_sync(codec); | ||
661 | } | ||
662 | |||
663 | /* Power up to mute */ | ||
664 | /* FIXME */ | ||
665 | snd_soc_update_bits(codec, STA32X_CONFF, | ||
666 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, | ||
667 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD); | ||
668 | |||
669 | break; | ||
670 | |||
671 | case SND_SOC_BIAS_OFF: | ||
672 | /* The chip runs through the power down sequence for us. */ | ||
673 | snd_soc_update_bits(codec, STA32X_CONFF, | ||
674 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, | ||
675 | STA32X_CONFF_PWDN); | ||
676 | msleep(300); | ||
677 | |||
678 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), | ||
679 | sta32x->supplies); | ||
680 | break; | ||
681 | } | ||
682 | codec->dapm.bias_level = level; | ||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | static struct snd_soc_dai_ops sta32x_dai_ops = { | ||
687 | .hw_params = sta32x_hw_params, | ||
688 | .set_sysclk = sta32x_set_dai_sysclk, | ||
689 | .set_fmt = sta32x_set_dai_fmt, | ||
690 | }; | ||
691 | |||
692 | static struct snd_soc_dai_driver sta32x_dai = { | ||
693 | .name = "STA32X", | ||
694 | .playback = { | ||
695 | .stream_name = "Playback", | ||
696 | .channels_min = 2, | ||
697 | .channels_max = 2, | ||
698 | .rates = STA32X_RATES, | ||
699 | .formats = STA32X_FORMATS, | ||
700 | }, | ||
701 | .ops = &sta32x_dai_ops, | ||
702 | }; | ||
703 | |||
704 | #ifdef CONFIG_PM | ||
705 | static int sta32x_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
706 | { | ||
707 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | static int sta32x_resume(struct snd_soc_codec *codec) | ||
712 | { | ||
713 | sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
714 | return 0; | ||
715 | } | ||
716 | #else | ||
717 | #define sta32x_suspend NULL | ||
718 | #define sta32x_resume NULL | ||
719 | #endif | ||
720 | |||
721 | static int sta32x_probe(struct snd_soc_codec *codec) | ||
722 | { | ||
723 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
724 | int i, ret = 0; | ||
725 | |||
726 | sta32x->codec = codec; | ||
727 | |||
728 | /* regulators */ | ||
729 | for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) | ||
730 | sta32x->supplies[i].supply = sta32x_supply_names[i]; | ||
731 | |||
732 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sta32x->supplies), | ||
733 | sta32x->supplies); | ||
734 | if (ret != 0) { | ||
735 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
736 | goto err; | ||
737 | } | ||
738 | |||
739 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), | ||
740 | sta32x->supplies); | ||
741 | if (ret != 0) { | ||
742 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
743 | goto err_get; | ||
744 | } | ||
745 | |||
746 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will | ||
747 | * then do the I2C transactions itself. | ||
748 | */ | ||
749 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | ||
750 | if (ret < 0) { | ||
751 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); | ||
752 | return ret; | ||
753 | } | ||
754 | |||
755 | /* read reg reset values into cache */ | ||
756 | for (i = 0; i < STA32X_REGISTER_COUNT; i++) | ||
757 | snd_soc_cache_write(codec, i, sta32x_regs[i]); | ||
758 | |||
759 | /* preserve reset values of reserved register bits */ | ||
760 | snd_soc_cache_write(codec, STA32X_CONFC, | ||
761 | codec->hw_read(codec, STA32X_CONFC)); | ||
762 | snd_soc_cache_write(codec, STA32X_CONFE, | ||
763 | codec->hw_read(codec, STA32X_CONFE)); | ||
764 | snd_soc_cache_write(codec, STA32X_CONFF, | ||
765 | codec->hw_read(codec, STA32X_CONFF)); | ||
766 | snd_soc_cache_write(codec, STA32X_MMUTE, | ||
767 | codec->hw_read(codec, STA32X_MMUTE)); | ||
768 | snd_soc_cache_write(codec, STA32X_AUTO1, | ||
769 | codec->hw_read(codec, STA32X_AUTO1)); | ||
770 | snd_soc_cache_write(codec, STA32X_AUTO3, | ||
771 | codec->hw_read(codec, STA32X_AUTO3)); | ||
772 | snd_soc_cache_write(codec, STA32X_C3CFG, | ||
773 | codec->hw_read(codec, STA32X_C3CFG)); | ||
774 | |||
775 | /* FIXME enable thermal warning adjustment and recovery */ | ||
776 | snd_soc_update_bits(codec, STA32X_CONFA, | ||
777 | STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, 0); | ||
778 | |||
779 | /* FIXME select 2.1 mode */ | ||
780 | snd_soc_update_bits(codec, STA32X_CONFF, | ||
781 | STA32X_CONFF_OCFG_MASK, | ||
782 | 1 << STA32X_CONFF_OCFG_SHIFT); | ||
783 | |||
784 | /* FIXME channel to output mapping */ | ||
785 | snd_soc_update_bits(codec, STA32X_C1CFG, | ||
786 | STA32X_CxCFG_OM_MASK, | ||
787 | 0 << STA32X_CxCFG_OM_SHIFT); | ||
788 | snd_soc_update_bits(codec, STA32X_C2CFG, | ||
789 | STA32X_CxCFG_OM_MASK, | ||
790 | 1 << STA32X_CxCFG_OM_SHIFT); | ||
791 | snd_soc_update_bits(codec, STA32X_C3CFG, | ||
792 | STA32X_CxCFG_OM_MASK, | ||
793 | 2 << STA32X_CxCFG_OM_SHIFT); | ||
794 | |||
795 | sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
796 | /* Bias level configuration will have done an extra enable */ | ||
797 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
798 | |||
799 | return 0; | ||
800 | |||
801 | err_get: | ||
802 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
803 | err: | ||
804 | return ret; | ||
805 | } | ||
806 | |||
807 | static int sta32x_remove(struct snd_soc_codec *codec) | ||
808 | { | ||
809 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
810 | |||
811 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
812 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
813 | |||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | static int sta32x_reg_is_volatile(struct snd_soc_codec *codec, | ||
818 | unsigned int reg) | ||
819 | { | ||
820 | switch (reg) { | ||
821 | case STA32X_CONFA ... STA32X_L2ATRT: | ||
822 | case STA32X_MPCC1 ... STA32X_FDRC2: | ||
823 | return 0; | ||
824 | } | ||
825 | return 1; | ||
826 | } | ||
827 | |||
828 | static const struct snd_soc_codec_driver sta32x_codec = { | ||
829 | .probe = sta32x_probe, | ||
830 | .remove = sta32x_remove, | ||
831 | .suspend = sta32x_suspend, | ||
832 | .resume = sta32x_resume, | ||
833 | .reg_cache_size = STA32X_REGISTER_COUNT, | ||
834 | .reg_word_size = sizeof(u8), | ||
835 | .volatile_register = sta32x_reg_is_volatile, | ||
836 | .set_bias_level = sta32x_set_bias_level, | ||
837 | .controls = sta32x_snd_controls, | ||
838 | .num_controls = ARRAY_SIZE(sta32x_snd_controls), | ||
839 | .dapm_widgets = sta32x_dapm_widgets, | ||
840 | .num_dapm_widgets = ARRAY_SIZE(sta32x_dapm_widgets), | ||
841 | .dapm_routes = sta32x_dapm_routes, | ||
842 | .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), | ||
843 | }; | ||
844 | |||
845 | static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, | ||
846 | const struct i2c_device_id *id) | ||
847 | { | ||
848 | struct sta32x_priv *sta32x; | ||
849 | int ret; | ||
850 | |||
851 | sta32x = kzalloc(sizeof(struct sta32x_priv), GFP_KERNEL); | ||
852 | if (!sta32x) | ||
853 | return -ENOMEM; | ||
854 | |||
855 | i2c_set_clientdata(i2c, sta32x); | ||
856 | |||
857 | ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); | ||
858 | if (ret != 0) { | ||
859 | dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret); | ||
860 | return ret; | ||
861 | } | ||
862 | |||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static __devexit int sta32x_i2c_remove(struct i2c_client *client) | ||
867 | { | ||
868 | struct sta32x_priv *sta32x = i2c_get_clientdata(client); | ||
869 | struct snd_soc_codec *codec = sta32x->codec; | ||
870 | |||
871 | if (codec) | ||
872 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
873 | |||
874 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
875 | |||
876 | if (codec) { | ||
877 | snd_soc_unregister_codec(&client->dev); | ||
878 | snd_soc_codec_set_drvdata(codec, NULL); | ||
879 | } | ||
880 | |||
881 | kfree(sta32x); | ||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | static const struct i2c_device_id sta32x_i2c_id[] = { | ||
886 | { "sta326", 0 }, | ||
887 | { "sta328", 0 }, | ||
888 | { "sta329", 0 }, | ||
889 | { } | ||
890 | }; | ||
891 | MODULE_DEVICE_TABLE(i2c, sta32x_i2c_id); | ||
892 | |||
893 | static struct i2c_driver sta32x_i2c_driver = { | ||
894 | .driver = { | ||
895 | .name = "sta32x", | ||
896 | .owner = THIS_MODULE, | ||
897 | }, | ||
898 | .probe = sta32x_i2c_probe, | ||
899 | .remove = __devexit_p(sta32x_i2c_remove), | ||
900 | .id_table = sta32x_i2c_id, | ||
901 | }; | ||
902 | |||
903 | static int __init sta32x_init(void) | ||
904 | { | ||
905 | return i2c_add_driver(&sta32x_i2c_driver); | ||
906 | } | ||
907 | module_init(sta32x_init); | ||
908 | |||
909 | static void __exit sta32x_exit(void) | ||
910 | { | ||
911 | i2c_del_driver(&sta32x_i2c_driver); | ||
912 | } | ||
913 | module_exit(sta32x_exit); | ||
914 | |||
915 | MODULE_DESCRIPTION("ASoC STA32X driver"); | ||
916 | MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>"); | ||
917 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/sta32x.h b/sound/soc/codecs/sta32x.h new file mode 100644 index 000000000000..b97ee5a75667 --- /dev/null +++ b/sound/soc/codecs/sta32x.h | |||
@@ -0,0 +1,210 @@ | |||
1 | /* | ||
2 | * Codec driver for ST STA32x 2.1-channel high-efficiency digital audio system | ||
3 | * | ||
4 | * Copyright: 2011 Raumfeld GmbH | ||
5 | * Author: Johannes Stezenbach <js@sig21.net> | ||
6 | * | ||
7 | * based on code from: | ||
8 | * Wolfson Microelectronics PLC. | ||
9 | * Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | #ifndef _ASOC_STA_32X_H | ||
17 | #define _ASOC_STA_32X_H | ||
18 | |||
19 | /* STA326 register addresses */ | ||
20 | |||
21 | #define STA32X_REGISTER_COUNT 0x2d | ||
22 | |||
23 | #define STA32X_CONFA 0x00 | ||
24 | #define STA32X_CONFB 0x01 | ||
25 | #define STA32X_CONFC 0x02 | ||
26 | #define STA32X_CONFD 0x03 | ||
27 | #define STA32X_CONFE 0x04 | ||
28 | #define STA32X_CONFF 0x05 | ||
29 | #define STA32X_MMUTE 0x06 | ||
30 | #define STA32X_MVOL 0x07 | ||
31 | #define STA32X_C1VOL 0x08 | ||
32 | #define STA32X_C2VOL 0x09 | ||
33 | #define STA32X_C3VOL 0x0a | ||
34 | #define STA32X_AUTO1 0x0b | ||
35 | #define STA32X_AUTO2 0x0c | ||
36 | #define STA32X_AUTO3 0x0d | ||
37 | #define STA32X_C1CFG 0x0e | ||
38 | #define STA32X_C2CFG 0x0f | ||
39 | #define STA32X_C3CFG 0x10 | ||
40 | #define STA32X_TONE 0x11 | ||
41 | #define STA32X_L1AR 0x12 | ||
42 | #define STA32X_L1ATRT 0x13 | ||
43 | #define STA32X_L2AR 0x14 | ||
44 | #define STA32X_L2ATRT 0x15 | ||
45 | #define STA32X_CFADDR2 0x16 | ||
46 | #define STA32X_B1CF1 0x17 | ||
47 | #define STA32X_B1CF2 0x18 | ||
48 | #define STA32X_B1CF3 0x19 | ||
49 | #define STA32X_B2CF1 0x1a | ||
50 | #define STA32X_B2CF2 0x1b | ||
51 | #define STA32X_B2CF3 0x1c | ||
52 | #define STA32X_A1CF1 0x1d | ||
53 | #define STA32X_A1CF2 0x1e | ||
54 | #define STA32X_A1CF3 0x1f | ||
55 | #define STA32X_A2CF1 0x20 | ||
56 | #define STA32X_A2CF2 0x21 | ||
57 | #define STA32X_A2CF3 0x22 | ||
58 | #define STA32X_B0CF1 0x23 | ||
59 | #define STA32X_B0CF2 0x24 | ||
60 | #define STA32X_B0CF3 0x25 | ||
61 | #define STA32X_CFUD 0x26 | ||
62 | #define STA32X_MPCC1 0x27 | ||
63 | #define STA32X_MPCC2 0x28 | ||
64 | /* Reserved 0x29 */ | ||
65 | /* Reserved 0x2a */ | ||
66 | #define STA32X_Reserved 0x2a | ||
67 | #define STA32X_FDRC1 0x2b | ||
68 | #define STA32X_FDRC2 0x2c | ||
69 | /* Reserved 0x2d */ | ||
70 | |||
71 | |||
72 | /* STA326 register field definitions */ | ||
73 | |||
74 | /* 0x00 CONFA */ | ||
75 | #define STA32X_CONFA_MCS_MASK 0x03 | ||
76 | #define STA32X_CONFA_MCS_SHIFT 0 | ||
77 | #define STA32X_CONFA_IR_MASK 0x18 | ||
78 | #define STA32X_CONFA_IR_SHIFT 3 | ||
79 | #define STA32X_CONFA_TWRB 0x20 | ||
80 | #define STA32X_CONFA_TWAB 0x40 | ||
81 | #define STA32X_CONFA_FDRB 0x80 | ||
82 | |||
83 | /* 0x01 CONFB */ | ||
84 | #define STA32X_CONFB_SAI_MASK 0x0f | ||
85 | #define STA32X_CONFB_SAI_SHIFT 0 | ||
86 | #define STA32X_CONFB_SAIFB 0x10 | ||
87 | #define STA32X_CONFB_DSCKE 0x20 | ||
88 | #define STA32X_CONFB_C1IM 0x40 | ||
89 | #define STA32X_CONFB_C2IM 0x80 | ||
90 | |||
91 | /* 0x02 CONFC */ | ||
92 | #define STA32X_CONFC_OM_MASK 0x03 | ||
93 | #define STA32X_CONFC_OM_SHIFT 0 | ||
94 | #define STA32X_CONFC_CSZ_MASK 0x7c | ||
95 | #define STA32X_CONFC_CSZ_SHIFT 2 | ||
96 | |||
97 | /* 0x03 CONFD */ | ||
98 | #define STA32X_CONFD_HPB 0x01 | ||
99 | #define STA32X_CONFD_HPB_SHIFT 0 | ||
100 | #define STA32X_CONFD_DEMP 0x02 | ||
101 | #define STA32X_CONFD_DEMP_SHIFT 1 | ||
102 | #define STA32X_CONFD_DSPB 0x04 | ||
103 | #define STA32X_CONFD_DSPB_SHIFT 2 | ||
104 | #define STA32X_CONFD_PSL 0x08 | ||
105 | #define STA32X_CONFD_PSL_SHIFT 3 | ||
106 | #define STA32X_CONFD_BQL 0x10 | ||
107 | #define STA32X_CONFD_BQL_SHIFT 4 | ||
108 | #define STA32X_CONFD_DRC 0x20 | ||
109 | #define STA32X_CONFD_DRC_SHIFT 5 | ||
110 | #define STA32X_CONFD_ZDE 0x40 | ||
111 | #define STA32X_CONFD_ZDE_SHIFT 6 | ||
112 | #define STA32X_CONFD_MME 0x80 | ||
113 | #define STA32X_CONFD_MME_SHIFT 7 | ||
114 | |||
115 | /* 0x04 CONFE */ | ||
116 | #define STA32X_CONFE_MPCV 0x01 | ||
117 | #define STA32X_CONFE_MPCV_SHIFT 0 | ||
118 | #define STA32X_CONFE_MPC 0x02 | ||
119 | #define STA32X_CONFE_MPC_SHIFT 1 | ||
120 | #define STA32X_CONFE_AME 0x08 | ||
121 | #define STA32X_CONFE_AME_SHIFT 3 | ||
122 | #define STA32X_CONFE_PWMS 0x10 | ||
123 | #define STA32X_CONFE_PWMS_SHIFT 4 | ||
124 | #define STA32X_CONFE_ZCE 0x40 | ||
125 | #define STA32X_CONFE_ZCE_SHIFT 6 | ||
126 | #define STA32X_CONFE_SVE 0x80 | ||
127 | #define STA32X_CONFE_SVE_SHIFT 7 | ||
128 | |||
129 | /* 0x05 CONFF */ | ||
130 | #define STA32X_CONFF_OCFG_MASK 0x03 | ||
131 | #define STA32X_CONFF_OCFG_SHIFT 0 | ||
132 | #define STA32X_CONFF_IDE 0x04 | ||
133 | #define STA32X_CONFF_IDE_SHIFT 3 | ||
134 | #define STA32X_CONFF_BCLE 0x08 | ||
135 | #define STA32X_CONFF_ECLE 0x20 | ||
136 | #define STA32X_CONFF_PWDN 0x40 | ||
137 | #define STA32X_CONFF_EAPD 0x80 | ||
138 | |||
139 | /* 0x06 MMUTE */ | ||
140 | #define STA32X_MMUTE_MMUTE 0x01 | ||
141 | |||
142 | /* 0x0b AUTO1 */ | ||
143 | #define STA32X_AUTO1_AMEQ_MASK 0x03 | ||
144 | #define STA32X_AUTO1_AMEQ_SHIFT 0 | ||
145 | #define STA32X_AUTO1_AMV_MASK 0xc0 | ||
146 | #define STA32X_AUTO1_AMV_SHIFT 2 | ||
147 | #define STA32X_AUTO1_AMGC_MASK 0x30 | ||
148 | #define STA32X_AUTO1_AMGC_SHIFT 4 | ||
149 | #define STA32X_AUTO1_AMPS 0x80 | ||
150 | |||
151 | /* 0x0c AUTO2 */ | ||
152 | #define STA32X_AUTO2_AMAME 0x01 | ||
153 | #define STA32X_AUTO2_AMAM_MASK 0x0e | ||
154 | #define STA32X_AUTO2_AMAM_SHIFT 1 | ||
155 | #define STA32X_AUTO2_XO_MASK 0xf0 | ||
156 | #define STA32X_AUTO2_XO_SHIFT 4 | ||
157 | |||
158 | /* 0x0d AUTO3 */ | ||
159 | #define STA32X_AUTO3_PEQ_MASK 0x1f | ||
160 | #define STA32X_AUTO3_PEQ_SHIFT 0 | ||
161 | |||
162 | /* 0x0e 0x0f 0x10 CxCFG */ | ||
163 | #define STA32X_CxCFG_TCB 0x01 /* only C1 and C2 */ | ||
164 | #define STA32X_CxCFG_TCB_SHIFT 0 | ||
165 | #define STA32X_CxCFG_EQBP 0x02 /* only C1 and C2 */ | ||
166 | #define STA32X_CxCFG_EQBP_SHIFT 1 | ||
167 | #define STA32X_CxCFG_VBP 0x03 | ||
168 | #define STA32X_CxCFG_VBP_SHIFT 2 | ||
169 | #define STA32X_CxCFG_BO 0x04 | ||
170 | #define STA32X_CxCFG_LS_MASK 0x30 | ||
171 | #define STA32X_CxCFG_LS_SHIFT 4 | ||
172 | #define STA32X_CxCFG_OM_MASK 0xc0 | ||
173 | #define STA32X_CxCFG_OM_SHIFT 6 | ||
174 | |||
175 | /* 0x11 TONE */ | ||
176 | #define STA32X_TONE_BTC_SHIFT 0 | ||
177 | #define STA32X_TONE_TTC_SHIFT 4 | ||
178 | |||
179 | /* 0x12 0x13 0x14 0x15 limiter attack/release */ | ||
180 | #define STA32X_LxA_SHIFT 0 | ||
181 | #define STA32X_LxR_SHIFT 4 | ||
182 | |||
183 | /* 0x26 CFUD */ | ||
184 | #define STA32X_CFUD_W1 0x01 | ||
185 | #define STA32X_CFUD_WA 0x02 | ||
186 | #define STA32X_CFUD_R1 0x04 | ||
187 | #define STA32X_CFUD_RA 0x08 | ||
188 | |||
189 | |||
190 | /* biquad filter coefficient table offsets */ | ||
191 | #define STA32X_C1_BQ_BASE 0 | ||
192 | #define STA32X_C2_BQ_BASE 20 | ||
193 | #define STA32X_CH_BQ_NUM 4 | ||
194 | #define STA32X_BQ_NUM_COEF 5 | ||
195 | #define STA32X_XO_HP_BQ_BASE 40 | ||
196 | #define STA32X_XO_LP_BQ_BASE 45 | ||
197 | #define STA32X_C1_PRESCALE 50 | ||
198 | #define STA32X_C2_PRESCALE 51 | ||
199 | #define STA32X_C1_POSTSCALE 52 | ||
200 | #define STA32X_C2_POSTSCALE 53 | ||
201 | #define STA32X_C3_POSTSCALE 54 | ||
202 | #define STA32X_TW_POSTSCALE 55 | ||
203 | #define STA32X_C1_MIX1 56 | ||
204 | #define STA32X_C1_MIX2 57 | ||
205 | #define STA32X_C2_MIX1 58 | ||
206 | #define STA32X_C2_MIX2 59 | ||
207 | #define STA32X_C3_MIX1 60 | ||
208 | #define STA32X_C3_MIX2 61 | ||
209 | |||
210 | #endif /* _ASOC_STA_32X_H */ | ||
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index e2a7608d3944..7859bdcc93db 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
@@ -161,10 +161,18 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, | |||
161 | dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL; | 161 | dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL; |
162 | } | 162 | } |
163 | 163 | ||
164 | /* Configure PLL */ | 164 | /** |
165 | * Configure PLL | ||
166 | * fsref = (mclk * PLLM) / 2048 | ||
167 | * where PLLM = J.DDDD (DDDD register ranges from 0 to 9999, decimal) | ||
168 | */ | ||
165 | pval = 1; | 169 | pval = 1; |
166 | jval = (fsref == 44100) ? 7 : 8; | 170 | /* compute J portion of multiplier */ |
167 | dval = (fsref == 44100) ? 5264 : 1920; | 171 | jval = fsref / (aic26->mclk / 2048); |
172 | /* compute fractional DDDD component of multiplier */ | ||
173 | dval = fsref - (jval * (aic26->mclk / 2048)); | ||
174 | dval = (10000 * dval) / (aic26->mclk / 2048); | ||
175 | dev_dbg(&aic26->spi->dev, "Setting PLLM to %d.%04d\n", jval, dval); | ||
168 | qval = 0; | 176 | qval = 0; |
169 | reg = 0x8000 | qval << 11 | pval << 8 | jval << 2; | 177 | reg = 0x8000 | qval << 11 | pval << 8 | jval << 2; |
170 | aic26_reg_write(codec, AIC26_REG_PLL_PROG1, reg); | 178 | aic26_reg_write(codec, AIC26_REG_PLL_PROG1, reg); |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index c3d96fc8c267..0963c4c7a83f 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -226,11 +226,13 @@ static const char *aic3x_adc_hpf[] = | |||
226 | #define RDAC_ENUM 1 | 226 | #define RDAC_ENUM 1 |
227 | #define LHPCOM_ENUM 2 | 227 | #define LHPCOM_ENUM 2 |
228 | #define RHPCOM_ENUM 3 | 228 | #define RHPCOM_ENUM 3 |
229 | #define LINE1L_ENUM 4 | 229 | #define LINE1L_2_L_ENUM 4 |
230 | #define LINE1R_ENUM 5 | 230 | #define LINE1L_2_R_ENUM 5 |
231 | #define LINE2L_ENUM 6 | 231 | #define LINE1R_2_L_ENUM 6 |
232 | #define LINE2R_ENUM 7 | 232 | #define LINE1R_2_R_ENUM 7 |
233 | #define ADC_HPF_ENUM 8 | 233 | #define LINE2L_ENUM 8 |
234 | #define LINE2R_ENUM 9 | ||
235 | #define ADC_HPF_ENUM 10 | ||
234 | 236 | ||
235 | static const struct soc_enum aic3x_enum[] = { | 237 | static const struct soc_enum aic3x_enum[] = { |
236 | SOC_ENUM_SINGLE(DAC_LINE_MUX, 6, 3, aic3x_left_dac_mux), | 238 | SOC_ENUM_SINGLE(DAC_LINE_MUX, 6, 3, aic3x_left_dac_mux), |
@@ -238,6 +240,8 @@ static const struct soc_enum aic3x_enum[] = { | |||
238 | SOC_ENUM_SINGLE(HPLCOM_CFG, 4, 3, aic3x_left_hpcom_mux), | 240 | SOC_ENUM_SINGLE(HPLCOM_CFG, 4, 3, aic3x_left_hpcom_mux), |
239 | SOC_ENUM_SINGLE(HPRCOM_CFG, 3, 5, aic3x_right_hpcom_mux), | 241 | SOC_ENUM_SINGLE(HPRCOM_CFG, 3, 5, aic3x_right_hpcom_mux), |
240 | SOC_ENUM_SINGLE(LINE1L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 242 | SOC_ENUM_SINGLE(LINE1L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), |
243 | SOC_ENUM_SINGLE(LINE1L_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), | ||
244 | SOC_ENUM_SINGLE(LINE1R_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), | ||
241 | SOC_ENUM_SINGLE(LINE1R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 245 | SOC_ENUM_SINGLE(LINE1R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), |
242 | SOC_ENUM_SINGLE(LINE2L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 246 | SOC_ENUM_SINGLE(LINE2L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), |
243 | SOC_ENUM_SINGLE(LINE2R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), | 247 | SOC_ENUM_SINGLE(LINE2R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), |
@@ -490,12 +494,16 @@ static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = { | |||
490 | }; | 494 | }; |
491 | 495 | ||
492 | /* Left Line1 Mux */ | 496 | /* Left Line1 Mux */ |
493 | static const struct snd_kcontrol_new aic3x_left_line1_mux_controls = | 497 | static const struct snd_kcontrol_new aic3x_left_line1l_mux_controls = |
494 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_ENUM]); | 498 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_2_L_ENUM]); |
499 | static const struct snd_kcontrol_new aic3x_right_line1l_mux_controls = | ||
500 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_2_R_ENUM]); | ||
495 | 501 | ||
496 | /* Right Line1 Mux */ | 502 | /* Right Line1 Mux */ |
497 | static const struct snd_kcontrol_new aic3x_right_line1_mux_controls = | 503 | static const struct snd_kcontrol_new aic3x_right_line1r_mux_controls = |
498 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_ENUM]); | 504 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_2_R_ENUM]); |
505 | static const struct snd_kcontrol_new aic3x_left_line1r_mux_controls = | ||
506 | SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_2_L_ENUM]); | ||
499 | 507 | ||
500 | /* Left Line2 Mux */ | 508 | /* Left Line2 Mux */ |
501 | static const struct snd_kcontrol_new aic3x_left_line2_mux_controls = | 509 | static const struct snd_kcontrol_new aic3x_left_line2_mux_controls = |
@@ -535,9 +543,9 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
535 | &aic3x_left_pga_mixer_controls[0], | 543 | &aic3x_left_pga_mixer_controls[0], |
536 | ARRAY_SIZE(aic3x_left_pga_mixer_controls)), | 544 | ARRAY_SIZE(aic3x_left_pga_mixer_controls)), |
537 | SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0, | 545 | SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0, |
538 | &aic3x_left_line1_mux_controls), | 546 | &aic3x_left_line1l_mux_controls), |
539 | SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0, | 547 | SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0, |
540 | &aic3x_left_line1_mux_controls), | 548 | &aic3x_left_line1r_mux_controls), |
541 | SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0, | 549 | SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0, |
542 | &aic3x_left_line2_mux_controls), | 550 | &aic3x_left_line2_mux_controls), |
543 | 551 | ||
@@ -548,9 +556,9 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
548 | &aic3x_right_pga_mixer_controls[0], | 556 | &aic3x_right_pga_mixer_controls[0], |
549 | ARRAY_SIZE(aic3x_right_pga_mixer_controls)), | 557 | ARRAY_SIZE(aic3x_right_pga_mixer_controls)), |
550 | SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0, | 558 | SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0, |
551 | &aic3x_right_line1_mux_controls), | 559 | &aic3x_right_line1l_mux_controls), |
552 | SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0, | 560 | SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0, |
553 | &aic3x_right_line1_mux_controls), | 561 | &aic3x_right_line1r_mux_controls), |
554 | SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0, | 562 | SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0, |
555 | &aic3x_right_line2_mux_controls), | 563 | &aic3x_right_line2_mux_controls), |
556 | 564 | ||
@@ -1114,12 +1122,19 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power) | |||
1114 | 1122 | ||
1115 | /* Sync reg_cache with the hardware */ | 1123 | /* Sync reg_cache with the hardware */ |
1116 | codec->cache_only = 0; | 1124 | codec->cache_only = 0; |
1117 | for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++) | 1125 | for (i = AIC3X_SAMPLE_RATE_SEL_REG; i < ARRAY_SIZE(aic3x_reg); i++) |
1118 | snd_soc_write(codec, i, cache[i]); | 1126 | snd_soc_write(codec, i, cache[i]); |
1119 | if (aic3x->model == AIC3X_MODEL_3007) | 1127 | if (aic3x->model == AIC3X_MODEL_3007) |
1120 | aic3x_init_3007(codec); | 1128 | aic3x_init_3007(codec); |
1121 | codec->cache_sync = 0; | 1129 | codec->cache_sync = 0; |
1122 | } else { | 1130 | } else { |
1131 | /* | ||
1132 | * Do soft reset to this codec instance in order to clear | ||
1133 | * possible VDD leakage currents in case the supply regulators | ||
1134 | * remain on | ||
1135 | */ | ||
1136 | snd_soc_write(codec, AIC3X_RESET, SOFT_RESET); | ||
1137 | codec->cache_sync = 1; | ||
1123 | aic3x->power = 0; | 1138 | aic3x->power = 0; |
1124 | /* HW writes are needless when bias is off */ | 1139 | /* HW writes are needless when bias is off */ |
1125 | codec->cache_only = 1; | 1140 | codec->cache_only = 1; |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 4c336636d4f5..cd63bba623df 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -954,9 +954,9 @@ static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0); | |||
954 | 954 | ||
955 | /* | 955 | /* |
956 | * MICGAIN volume control: | 956 | * MICGAIN volume control: |
957 | * from -6 to 30 dB in 6 dB steps | 957 | * from 6 to 30 dB in 6 dB steps |
958 | */ | 958 | */ |
959 | static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -600, 600, 0); | 959 | static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0); |
960 | 960 | ||
961 | /* | 961 | /* |
962 | * AFMGAIN volume control: | 962 | * AFMGAIN volume control: |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 2dc964b55e4f..76b4361e9b80 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -175,6 +175,7 @@ static const struct snd_kcontrol_new wm8731_input_mux_controls = | |||
175 | SOC_DAPM_ENUM("Input Select", wm8731_insel_enum); | 175 | SOC_DAPM_ENUM("Input Select", wm8731_insel_enum); |
176 | 176 | ||
177 | static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { | 177 | static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { |
178 | SND_SOC_DAPM_SUPPLY("ACTIVE",WM8731_ACTIVE, 0, 0, NULL, 0), | ||
178 | SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0), | 179 | SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0), |
179 | SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, | 180 | SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, |
180 | &wm8731_output_mixer_controls[0], | 181 | &wm8731_output_mixer_controls[0], |
@@ -204,6 +205,8 @@ static int wm8731_check_osc(struct snd_soc_dapm_widget *source, | |||
204 | static const struct snd_soc_dapm_route wm8731_intercon[] = { | 205 | static const struct snd_soc_dapm_route wm8731_intercon[] = { |
205 | {"DAC", NULL, "OSC", wm8731_check_osc}, | 206 | {"DAC", NULL, "OSC", wm8731_check_osc}, |
206 | {"ADC", NULL, "OSC", wm8731_check_osc}, | 207 | {"ADC", NULL, "OSC", wm8731_check_osc}, |
208 | {"DAC", NULL, "ACTIVE"}, | ||
209 | {"ADC", NULL, "ACTIVE"}, | ||
207 | 210 | ||
208 | /* output mixer */ | 211 | /* output mixer */ |
209 | {"Output Mixer", "Line Bypass Switch", "Line Input"}, | 212 | {"Output Mixer", "Line Bypass Switch", "Line Input"}, |
@@ -315,29 +318,6 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, | |||
315 | return 0; | 318 | return 0; |
316 | } | 319 | } |
317 | 320 | ||
318 | static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, | ||
319 | struct snd_soc_dai *dai) | ||
320 | { | ||
321 | struct snd_soc_codec *codec = dai->codec; | ||
322 | |||
323 | /* set active */ | ||
324 | snd_soc_write(codec, WM8731_ACTIVE, 0x0001); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static void wm8731_shutdown(struct snd_pcm_substream *substream, | ||
330 | struct snd_soc_dai *dai) | ||
331 | { | ||
332 | struct snd_soc_codec *codec = dai->codec; | ||
333 | |||
334 | /* deactivate */ | ||
335 | if (!codec->active) { | ||
336 | udelay(50); | ||
337 | snd_soc_write(codec, WM8731_ACTIVE, 0x0); | ||
338 | } | ||
339 | } | ||
340 | |||
341 | static int wm8731_mute(struct snd_soc_dai *dai, int mute) | 321 | static int wm8731_mute(struct snd_soc_dai *dai, int mute) |
342 | { | 322 | { |
343 | struct snd_soc_codec *codec = dai->codec; | 323 | struct snd_soc_codec *codec = dai->codec; |
@@ -480,7 +460,6 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, | |||
480 | snd_soc_write(codec, WM8731_PWR, reg | 0x0040); | 460 | snd_soc_write(codec, WM8731_PWR, reg | 0x0040); |
481 | break; | 461 | break; |
482 | case SND_SOC_BIAS_OFF: | 462 | case SND_SOC_BIAS_OFF: |
483 | snd_soc_write(codec, WM8731_ACTIVE, 0x0); | ||
484 | snd_soc_write(codec, WM8731_PWR, 0xffff); | 463 | snd_soc_write(codec, WM8731_PWR, 0xffff); |
485 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), | 464 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), |
486 | wm8731->supplies); | 465 | wm8731->supplies); |
@@ -496,9 +475,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, | |||
496 | SNDRV_PCM_FMTBIT_S24_LE) | 475 | SNDRV_PCM_FMTBIT_S24_LE) |
497 | 476 | ||
498 | static struct snd_soc_dai_ops wm8731_dai_ops = { | 477 | static struct snd_soc_dai_ops wm8731_dai_ops = { |
499 | .prepare = wm8731_pcm_prepare, | ||
500 | .hw_params = wm8731_hw_params, | 478 | .hw_params = wm8731_hw_params, |
501 | .shutdown = wm8731_shutdown, | ||
502 | .digital_mute = wm8731_mute, | 479 | .digital_mute = wm8731_mute, |
503 | .set_sysclk = wm8731_set_dai_sysclk, | 480 | .set_sysclk = wm8731_set_dai_sysclk, |
504 | .set_fmt = wm8731_set_dai_fmt, | 481 | .set_fmt = wm8731_set_dai_fmt, |
diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c new file mode 100644 index 000000000000..a2a09f85ea99 --- /dev/null +++ b/sound/soc/codecs/wm8782.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * sound/soc/codecs/wm8782.c | ||
3 | * simple, strap-pin configured 24bit 2ch ADC | ||
4 | * | ||
5 | * Copyright: 2011 Raumfeld GmbH | ||
6 | * Author: Johannes Stezenbach <js@sig21.net> | ||
7 | * | ||
8 | * based on ad73311.c | ||
9 | * Copyright: Analog Device Inc. | ||
10 | * Author: Cliff Cai <cliff.cai@analog.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/init.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/device.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/ac97_codec.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/soc.h> | ||
28 | |||
29 | static struct snd_soc_dai_driver wm8782_dai = { | ||
30 | .name = "wm8782", | ||
31 | .capture = { | ||
32 | .stream_name = "Capture", | ||
33 | .channels_min = 2, | ||
34 | .channels_max = 2, | ||
35 | /* For configurations with FSAMPEN=0 */ | ||
36 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
37 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
38 | SNDRV_PCM_FMTBIT_S20_3LE | | ||
39 | SNDRV_PCM_FMTBIT_S24_LE, | ||
40 | }, | ||
41 | }; | ||
42 | |||
43 | static struct snd_soc_codec_driver soc_codec_dev_wm8782; | ||
44 | |||
45 | static __devinit int wm8782_probe(struct platform_device *pdev) | ||
46 | { | ||
47 | return snd_soc_register_codec(&pdev->dev, | ||
48 | &soc_codec_dev_wm8782, &wm8782_dai, 1); | ||
49 | } | ||
50 | |||
51 | static int __devexit wm8782_remove(struct platform_device *pdev) | ||
52 | { | ||
53 | snd_soc_unregister_codec(&pdev->dev); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static struct platform_driver wm8782_codec_driver = { | ||
58 | .driver = { | ||
59 | .name = "wm8782", | ||
60 | .owner = THIS_MODULE, | ||
61 | }, | ||
62 | .probe = wm8782_probe, | ||
63 | .remove = wm8782_remove, | ||
64 | }; | ||
65 | |||
66 | static int __init wm8782_init(void) | ||
67 | { | ||
68 | return platform_driver_register(&wm8782_codec_driver); | ||
69 | } | ||
70 | module_init(wm8782_init); | ||
71 | |||
72 | static void __exit wm8782_exit(void) | ||
73 | { | ||
74 | platform_driver_unregister(&wm8782_codec_driver); | ||
75 | } | ||
76 | module_exit(wm8782_exit); | ||
77 | |||
78 | MODULE_DESCRIPTION("ASoC WM8782 driver"); | ||
79 | MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>"); | ||
80 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 449ea09a193d..082040eda8a2 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -1167,6 +1167,7 @@ static int wm8900_resume(struct snd_soc_codec *codec) | |||
1167 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); | 1167 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); |
1168 | if (ret != 0) { | 1168 | if (ret != 0) { |
1169 | dev_err(codec->dev, "Failed to restart FLL\n"); | 1169 | dev_err(codec->dev, "Failed to restart FLL\n"); |
1170 | kfree(cache); | ||
1170 | return ret; | 1171 | return ret; |
1171 | } | 1172 | } |
1172 | } | 1173 | } |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 9b3bba4df5b3..b085575d4aa5 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -2560,6 +2560,7 @@ static __devexit int wm8904_i2c_remove(struct i2c_client *client) | |||
2560 | static const struct i2c_device_id wm8904_i2c_id[] = { | 2560 | static const struct i2c_device_id wm8904_i2c_id[] = { |
2561 | { "wm8904", WM8904 }, | 2561 | { "wm8904", WM8904 }, |
2562 | { "wm8912", WM8912 }, | 2562 | { "wm8912", WM8912 }, |
2563 | { "wm8918", WM8904 }, /* Actually a subset, updates to follow */ | ||
2563 | { } | 2564 | { } |
2564 | }; | 2565 | }; |
2565 | MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); | 2566 | MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); |
diff --git a/sound/soc/codecs/wm8915.c b/sound/soc/codecs/wm8915.c index e2ab4fac2819..423baa9be241 100644 --- a/sound/soc/codecs/wm8915.c +++ b/sound/soc/codecs/wm8915.c | |||
@@ -41,14 +41,12 @@ | |||
41 | #define HPOUT2L 4 | 41 | #define HPOUT2L 4 |
42 | #define HPOUT2R 8 | 42 | #define HPOUT2R 8 |
43 | 43 | ||
44 | #define WM8915_NUM_SUPPLIES 6 | 44 | #define WM8915_NUM_SUPPLIES 4 |
45 | static const char *wm8915_supply_names[WM8915_NUM_SUPPLIES] = { | 45 | static const char *wm8915_supply_names[WM8915_NUM_SUPPLIES] = { |
46 | "DCVDD", | ||
47 | "DBVDD", | 46 | "DBVDD", |
48 | "AVDD1", | 47 | "AVDD1", |
49 | "AVDD2", | 48 | "AVDD2", |
50 | "CPVDD", | 49 | "CPVDD", |
51 | "MICVDD", | ||
52 | }; | 50 | }; |
53 | 51 | ||
54 | struct wm8915_priv { | 52 | struct wm8915_priv { |
@@ -57,6 +55,7 @@ struct wm8915_priv { | |||
57 | int ldo1ena; | 55 | int ldo1ena; |
58 | 56 | ||
59 | int sysclk; | 57 | int sysclk; |
58 | int sysclk_src; | ||
60 | 59 | ||
61 | int fll_src; | 60 | int fll_src; |
62 | int fll_fref; | 61 | int fll_fref; |
@@ -76,6 +75,7 @@ struct wm8915_priv { | |||
76 | struct wm8915_pdata pdata; | 75 | struct wm8915_pdata pdata; |
77 | 76 | ||
78 | int rx_rate[WM8915_AIFS]; | 77 | int rx_rate[WM8915_AIFS]; |
78 | int bclk_rate[WM8915_AIFS]; | ||
79 | 79 | ||
80 | /* Platform dependant ReTune mobile configuration */ | 80 | /* Platform dependant ReTune mobile configuration */ |
81 | int num_retune_mobile_texts; | 81 | int num_retune_mobile_texts; |
@@ -113,8 +113,6 @@ WM8915_REGULATOR_EVENT(0) | |||
113 | WM8915_REGULATOR_EVENT(1) | 113 | WM8915_REGULATOR_EVENT(1) |
114 | WM8915_REGULATOR_EVENT(2) | 114 | WM8915_REGULATOR_EVENT(2) |
115 | WM8915_REGULATOR_EVENT(3) | 115 | WM8915_REGULATOR_EVENT(3) |
116 | WM8915_REGULATOR_EVENT(4) | ||
117 | WM8915_REGULATOR_EVENT(5) | ||
118 | 116 | ||
119 | static const u16 wm8915_reg[WM8915_MAX_REGISTER] = { | 117 | static const u16 wm8915_reg[WM8915_MAX_REGISTER] = { |
120 | [WM8915_SOFTWARE_RESET] = 0x8915, | 118 | [WM8915_SOFTWARE_RESET] = 0x8915, |
@@ -1565,6 +1563,50 @@ static int wm8915_reset(struct snd_soc_codec *codec) | |||
1565 | return snd_soc_write(codec, WM8915_SOFTWARE_RESET, 0x8915); | 1563 | return snd_soc_write(codec, WM8915_SOFTWARE_RESET, 0x8915); |
1566 | } | 1564 | } |
1567 | 1565 | ||
1566 | static const int bclk_divs[] = { | ||
1567 | 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96 | ||
1568 | }; | ||
1569 | |||
1570 | static void wm8915_update_bclk(struct snd_soc_codec *codec) | ||
1571 | { | ||
1572 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | ||
1573 | int aif, best, cur_val, bclk_rate, bclk_reg, i; | ||
1574 | |||
1575 | /* Don't bother if we're in a low frequency idle mode that | ||
1576 | * can't support audio. | ||
1577 | */ | ||
1578 | if (wm8915->sysclk < 64000) | ||
1579 | return; | ||
1580 | |||
1581 | for (aif = 0; aif < WM8915_AIFS; aif++) { | ||
1582 | switch (aif) { | ||
1583 | case 0: | ||
1584 | bclk_reg = WM8915_AIF1_BCLK; | ||
1585 | break; | ||
1586 | case 1: | ||
1587 | bclk_reg = WM8915_AIF2_BCLK; | ||
1588 | break; | ||
1589 | } | ||
1590 | |||
1591 | bclk_rate = wm8915->bclk_rate[aif]; | ||
1592 | |||
1593 | /* Pick a divisor for BCLK as close as we can get to ideal */ | ||
1594 | best = 0; | ||
1595 | for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { | ||
1596 | cur_val = (wm8915->sysclk / bclk_divs[i]) - bclk_rate; | ||
1597 | if (cur_val < 0) /* BCLK table is sorted */ | ||
1598 | break; | ||
1599 | best = i; | ||
1600 | } | ||
1601 | bclk_rate = wm8915->sysclk / bclk_divs[best]; | ||
1602 | dev_dbg(codec->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n", | ||
1603 | bclk_divs[best], bclk_rate); | ||
1604 | |||
1605 | snd_soc_update_bits(codec, bclk_reg, | ||
1606 | WM8915_AIF1_BCLK_DIV_MASK, best); | ||
1607 | } | ||
1608 | } | ||
1609 | |||
1568 | static int wm8915_set_bias_level(struct snd_soc_codec *codec, | 1610 | static int wm8915_set_bias_level(struct snd_soc_codec *codec, |
1569 | enum snd_soc_bias_level level) | 1611 | enum snd_soc_bias_level level) |
1570 | { | 1612 | { |
@@ -1717,10 +1759,6 @@ static int wm8915_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
1717 | return 0; | 1759 | return 0; |
1718 | } | 1760 | } |
1719 | 1761 | ||
1720 | static const int bclk_divs[] = { | ||
1721 | 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96 | ||
1722 | }; | ||
1723 | |||
1724 | static const int dsp_divs[] = { | 1762 | static const int dsp_divs[] = { |
1725 | 48000, 32000, 16000, 8000 | 1763 | 48000, 32000, 16000, 8000 |
1726 | }; | 1764 | }; |
@@ -1731,17 +1769,11 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream, | |||
1731 | { | 1769 | { |
1732 | struct snd_soc_codec *codec = dai->codec; | 1770 | struct snd_soc_codec *codec = dai->codec; |
1733 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | 1771 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); |
1734 | int bits, i, bclk_rate, best, cur_val; | 1772 | int bits, i, bclk_rate; |
1735 | int aifdata = 0; | 1773 | int aifdata = 0; |
1736 | int bclk = 0; | ||
1737 | int lrclk = 0; | 1774 | int lrclk = 0; |
1738 | int dsp = 0; | 1775 | int dsp = 0; |
1739 | int aifdata_reg, bclk_reg, lrclk_reg, dsp_shift; | 1776 | int aifdata_reg, lrclk_reg, dsp_shift; |
1740 | |||
1741 | if (!wm8915->sysclk) { | ||
1742 | dev_err(codec->dev, "SYSCLK not configured\n"); | ||
1743 | return -EINVAL; | ||
1744 | } | ||
1745 | 1777 | ||
1746 | switch (dai->id) { | 1778 | switch (dai->id) { |
1747 | case 0: | 1779 | case 0: |
@@ -1753,7 +1785,6 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream, | |||
1753 | aifdata_reg = WM8915_AIF1TX_DATA_CONFIGURATION_1; | 1785 | aifdata_reg = WM8915_AIF1TX_DATA_CONFIGURATION_1; |
1754 | lrclk_reg = WM8915_AIF1_TX_LRCLK_1; | 1786 | lrclk_reg = WM8915_AIF1_TX_LRCLK_1; |
1755 | } | 1787 | } |
1756 | bclk_reg = WM8915_AIF1_BCLK; | ||
1757 | dsp_shift = 0; | 1788 | dsp_shift = 0; |
1758 | break; | 1789 | break; |
1759 | case 1: | 1790 | case 1: |
@@ -1765,7 +1796,6 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream, | |||
1765 | aifdata_reg = WM8915_AIF2TX_DATA_CONFIGURATION_1; | 1796 | aifdata_reg = WM8915_AIF2TX_DATA_CONFIGURATION_1; |
1766 | lrclk_reg = WM8915_AIF2_TX_LRCLK_1; | 1797 | lrclk_reg = WM8915_AIF2_TX_LRCLK_1; |
1767 | } | 1798 | } |
1768 | bclk_reg = WM8915_AIF2_BCLK; | ||
1769 | dsp_shift = WM8915_DSP2_DIV_SHIFT; | 1799 | dsp_shift = WM8915_DSP2_DIV_SHIFT; |
1770 | break; | 1800 | break; |
1771 | default: | 1801 | default: |
@@ -1779,6 +1809,9 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream, | |||
1779 | return bclk_rate; | 1809 | return bclk_rate; |
1780 | } | 1810 | } |
1781 | 1811 | ||
1812 | wm8915->bclk_rate[dai->id] = bclk_rate; | ||
1813 | wm8915->rx_rate[dai->id] = params_rate(params); | ||
1814 | |||
1782 | /* Needs looking at for TDM */ | 1815 | /* Needs looking at for TDM */ |
1783 | bits = snd_pcm_format_width(params_format(params)); | 1816 | bits = snd_pcm_format_width(params_format(params)); |
1784 | if (bits < 0) | 1817 | if (bits < 0) |
@@ -1796,18 +1829,7 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream, | |||
1796 | } | 1829 | } |
1797 | dsp |= i << dsp_shift; | 1830 | dsp |= i << dsp_shift; |
1798 | 1831 | ||
1799 | /* Pick a divisor for BCLK as close as we can get to ideal */ | 1832 | wm8915_update_bclk(codec); |
1800 | best = 0; | ||
1801 | for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { | ||
1802 | cur_val = (wm8915->sysclk / bclk_divs[i]) - bclk_rate; | ||
1803 | if (cur_val < 0) /* BCLK table is sorted */ | ||
1804 | break; | ||
1805 | best = i; | ||
1806 | } | ||
1807 | bclk_rate = wm8915->sysclk / bclk_divs[best]; | ||
1808 | dev_dbg(dai->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n", | ||
1809 | bclk_divs[best], bclk_rate); | ||
1810 | bclk |= best; | ||
1811 | 1833 | ||
1812 | lrclk = bclk_rate / params_rate(params); | 1834 | lrclk = bclk_rate / params_rate(params); |
1813 | dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", | 1835 | dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", |
@@ -1817,14 +1839,11 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream, | |||
1817 | WM8915_AIF1TX_WL_MASK | | 1839 | WM8915_AIF1TX_WL_MASK | |
1818 | WM8915_AIF1TX_SLOT_LEN_MASK, | 1840 | WM8915_AIF1TX_SLOT_LEN_MASK, |
1819 | aifdata); | 1841 | aifdata); |
1820 | snd_soc_update_bits(codec, bclk_reg, WM8915_AIF1_BCLK_DIV_MASK, bclk); | ||
1821 | snd_soc_update_bits(codec, lrclk_reg, WM8915_AIF1RX_RATE_MASK, | 1842 | snd_soc_update_bits(codec, lrclk_reg, WM8915_AIF1RX_RATE_MASK, |
1822 | lrclk); | 1843 | lrclk); |
1823 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_2, | 1844 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_2, |
1824 | WM8915_DSP1_DIV_SHIFT << dsp_shift, dsp); | 1845 | WM8915_DSP1_DIV_SHIFT << dsp_shift, dsp); |
1825 | 1846 | ||
1826 | wm8915->rx_rate[dai->id] = params_rate(params); | ||
1827 | |||
1828 | return 0; | 1847 | return 0; |
1829 | } | 1848 | } |
1830 | 1849 | ||
@@ -1838,6 +1857,9 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai, | |||
1838 | int src; | 1857 | int src; |
1839 | int old; | 1858 | int old; |
1840 | 1859 | ||
1860 | if (freq == wm8915->sysclk && clk_id == wm8915->sysclk_src) | ||
1861 | return 0; | ||
1862 | |||
1841 | /* Disable SYSCLK while we reconfigure */ | 1863 | /* Disable SYSCLK while we reconfigure */ |
1842 | old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1) & WM8915_SYSCLK_ENA; | 1864 | old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1) & WM8915_SYSCLK_ENA; |
1843 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, | 1865 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, |
@@ -1882,6 +1904,8 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai, | |||
1882 | return -EINVAL; | 1904 | return -EINVAL; |
1883 | } | 1905 | } |
1884 | 1906 | ||
1907 | wm8915_update_bclk(codec); | ||
1908 | |||
1885 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, | 1909 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, |
1886 | WM8915_SYSCLK_SRC_MASK | WM8915_SYSCLK_DIV_MASK, | 1910 | WM8915_SYSCLK_SRC_MASK | WM8915_SYSCLK_DIV_MASK, |
1887 | src << WM8915_SYSCLK_SRC_SHIFT | ratediv); | 1911 | src << WM8915_SYSCLK_SRC_SHIFT | ratediv); |
@@ -1889,6 +1913,8 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai, | |||
1889 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, | 1913 | snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, |
1890 | WM8915_SYSCLK_ENA, old); | 1914 | WM8915_SYSCLK_ENA, old); |
1891 | 1915 | ||
1916 | wm8915->sysclk_src = clk_id; | ||
1917 | |||
1892 | return 0; | 1918 | return 0; |
1893 | } | 1919 | } |
1894 | 1920 | ||
@@ -2007,6 +2033,7 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2007 | unsigned int Fref, unsigned int Fout) | 2033 | unsigned int Fref, unsigned int Fout) |
2008 | { | 2034 | { |
2009 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | 2035 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); |
2036 | struct i2c_client *i2c = to_i2c_client(codec->dev); | ||
2010 | struct _fll_div fll_div; | 2037 | struct _fll_div fll_div; |
2011 | unsigned long timeout; | 2038 | unsigned long timeout; |
2012 | int ret, reg; | 2039 | int ret, reg; |
@@ -2093,7 +2120,18 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2093 | else | 2120 | else |
2094 | timeout = msecs_to_jiffies(2); | 2121 | timeout = msecs_to_jiffies(2); |
2095 | 2122 | ||
2096 | wait_for_completion_timeout(&wm8915->fll_lock, timeout); | 2123 | /* Allow substantially longer if we've actually got the IRQ */ |
2124 | if (i2c->irq) | ||
2125 | timeout *= 1000; | ||
2126 | |||
2127 | ret = wait_for_completion_timeout(&wm8915->fll_lock, timeout); | ||
2128 | |||
2129 | if (ret == 0 && i2c->irq) { | ||
2130 | dev_err(codec->dev, "Timed out waiting for FLL\n"); | ||
2131 | ret = -ETIMEDOUT; | ||
2132 | } else { | ||
2133 | ret = 0; | ||
2134 | } | ||
2097 | 2135 | ||
2098 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); | 2136 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); |
2099 | 2137 | ||
@@ -2101,7 +2139,7 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2101 | wm8915->fll_fout = Fout; | 2139 | wm8915->fll_fout = Fout; |
2102 | wm8915->fll_src = source; | 2140 | wm8915->fll_src = source; |
2103 | 2141 | ||
2104 | return 0; | 2142 | return ret; |
2105 | } | 2143 | } |
2106 | 2144 | ||
2107 | #ifdef CONFIG_GPIOLIB | 2145 | #ifdef CONFIG_GPIOLIB |
@@ -2293,6 +2331,12 @@ static void wm8915_micd(struct snd_soc_codec *codec) | |||
2293 | SND_JACK_HEADSET | SND_JACK_BTN_0); | 2331 | SND_JACK_HEADSET | SND_JACK_BTN_0); |
2294 | wm8915->jack_mic = true; | 2332 | wm8915->jack_mic = true; |
2295 | wm8915->detecting = false; | 2333 | wm8915->detecting = false; |
2334 | |||
2335 | /* Increase poll rate to give better responsiveness | ||
2336 | * for buttons */ | ||
2337 | snd_soc_update_bits(codec, WM8915_MIC_DETECT_1, | ||
2338 | WM8915_MICD_RATE_MASK, | ||
2339 | 5 << WM8915_MICD_RATE_SHIFT); | ||
2296 | } | 2340 | } |
2297 | 2341 | ||
2298 | /* If we detected a lower impedence during initial startup | 2342 | /* If we detected a lower impedence during initial startup |
@@ -2333,15 +2377,17 @@ static void wm8915_micd(struct snd_soc_codec *codec) | |||
2333 | SND_JACK_HEADPHONE, | 2377 | SND_JACK_HEADPHONE, |
2334 | SND_JACK_HEADSET | | 2378 | SND_JACK_HEADSET | |
2335 | SND_JACK_BTN_0); | 2379 | SND_JACK_BTN_0); |
2380 | |||
2381 | /* Increase the detection rate a bit for | ||
2382 | * responsiveness. | ||
2383 | */ | ||
2384 | snd_soc_update_bits(codec, WM8915_MIC_DETECT_1, | ||
2385 | WM8915_MICD_RATE_MASK, | ||
2386 | 7 << WM8915_MICD_RATE_SHIFT); | ||
2387 | |||
2336 | wm8915->detecting = false; | 2388 | wm8915->detecting = false; |
2337 | } | 2389 | } |
2338 | } | 2390 | } |
2339 | |||
2340 | /* Increase poll rate to give better responsiveness for buttons */ | ||
2341 | if (!wm8915->detecting) | ||
2342 | snd_soc_update_bits(codec, WM8915_MIC_DETECT_1, | ||
2343 | WM8915_MICD_RATE_MASK, | ||
2344 | 5 << WM8915_MICD_RATE_SHIFT); | ||
2345 | } | 2391 | } |
2346 | 2392 | ||
2347 | static irqreturn_t wm8915_irq(int irq, void *data) | 2393 | static irqreturn_t wm8915_irq(int irq, void *data) |
@@ -2383,6 +2429,20 @@ static irqreturn_t wm8915_irq(int irq, void *data) | |||
2383 | } | 2429 | } |
2384 | } | 2430 | } |
2385 | 2431 | ||
2432 | static irqreturn_t wm8915_edge_irq(int irq, void *data) | ||
2433 | { | ||
2434 | irqreturn_t ret = IRQ_NONE; | ||
2435 | irqreturn_t val; | ||
2436 | |||
2437 | do { | ||
2438 | val = wm8915_irq(irq, data); | ||
2439 | if (val != IRQ_NONE) | ||
2440 | ret = val; | ||
2441 | } while (val != IRQ_NONE); | ||
2442 | |||
2443 | return ret; | ||
2444 | } | ||
2445 | |||
2386 | static void wm8915_retune_mobile_pdata(struct snd_soc_codec *codec) | 2446 | static void wm8915_retune_mobile_pdata(struct snd_soc_codec *codec) |
2387 | { | 2447 | { |
2388 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); | 2448 | struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); |
@@ -2482,8 +2542,6 @@ static int wm8915_probe(struct snd_soc_codec *codec) | |||
2482 | wm8915->disable_nb[1].notifier_call = wm8915_regulator_event_1; | 2542 | wm8915->disable_nb[1].notifier_call = wm8915_regulator_event_1; |
2483 | wm8915->disable_nb[2].notifier_call = wm8915_regulator_event_2; | 2543 | wm8915->disable_nb[2].notifier_call = wm8915_regulator_event_2; |
2484 | wm8915->disable_nb[3].notifier_call = wm8915_regulator_event_3; | 2544 | wm8915->disable_nb[3].notifier_call = wm8915_regulator_event_3; |
2485 | wm8915->disable_nb[4].notifier_call = wm8915_regulator_event_4; | ||
2486 | wm8915->disable_nb[5].notifier_call = wm8915_regulator_event_5; | ||
2487 | 2545 | ||
2488 | /* This should really be moved into the regulator core */ | 2546 | /* This should really be moved into the regulator core */ |
2489 | for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++) { | 2547 | for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++) { |
@@ -2709,8 +2767,14 @@ static int wm8915_probe(struct snd_soc_codec *codec) | |||
2709 | 2767 | ||
2710 | irq_flags |= IRQF_ONESHOT; | 2768 | irq_flags |= IRQF_ONESHOT; |
2711 | 2769 | ||
2712 | ret = request_threaded_irq(i2c->irq, NULL, wm8915_irq, | 2770 | if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) |
2713 | irq_flags, "wm8915", codec); | 2771 | ret = request_threaded_irq(i2c->irq, NULL, |
2772 | wm8915_edge_irq, | ||
2773 | irq_flags, "wm8915", codec); | ||
2774 | else | ||
2775 | ret = request_threaded_irq(i2c->irq, NULL, wm8915_irq, | ||
2776 | irq_flags, "wm8915", codec); | ||
2777 | |||
2714 | if (ret == 0) { | 2778 | if (ret == 0) { |
2715 | /* Unmask the interrupt */ | 2779 | /* Unmask the interrupt */ |
2716 | snd_soc_update_bits(codec, WM8915_INTERRUPT_CONTROL, | 2780 | snd_soc_update_bits(codec, WM8915_INTERRUPT_CONTROL, |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 25580e3ee7c4..056daa0010f9 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -297,8 +297,6 @@ static int wm8940_add_widgets(struct snd_soc_codec *codec) | |||
297 | if (ret) | 297 | if (ret) |
298 | goto error_ret; | 298 | goto error_ret; |
299 | ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | 299 | ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); |
300 | if (ret) | ||
301 | goto error_ret; | ||
302 | 300 | ||
303 | error_ret: | 301 | error_ret: |
304 | return ret; | 302 | return ret; |
@@ -683,8 +681,6 @@ static int wm8940_resume(struct snd_soc_codec *codec) | |||
683 | } | 681 | } |
684 | } | 682 | } |
685 | ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 683 | ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
686 | if (ret) | ||
687 | goto error_ret; | ||
688 | 684 | ||
689 | error_ret: | 685 | error_ret: |
690 | return ret; | 686 | return ret; |
@@ -730,9 +726,6 @@ static int wm8940_probe(struct snd_soc_codec *codec) | |||
730 | if (ret) | 726 | if (ret) |
731 | return ret; | 727 | return ret; |
732 | ret = wm8940_add_widgets(codec); | 728 | ret = wm8940_add_widgets(codec); |
733 | if (ret) | ||
734 | return ret; | ||
735 | |||
736 | return ret; | 729 | return ret; |
737 | } | 730 | } |
738 | 731 | ||
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 5e05eed96c38..8499c563a9b5 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -78,6 +78,8 @@ struct wm8962_priv { | |||
78 | #ifdef CONFIG_GPIOLIB | 78 | #ifdef CONFIG_GPIOLIB |
79 | struct gpio_chip gpio_chip; | 79 | struct gpio_chip gpio_chip; |
80 | #endif | 80 | #endif |
81 | |||
82 | int irq; | ||
81 | }; | 83 | }; |
82 | 84 | ||
83 | /* We can't use the same notifier block for more than one supply and | 85 | /* We can't use the same notifier block for more than one supply and |
@@ -1982,6 +1984,7 @@ static const unsigned int classd_tlv[] = { | |||
1982 | 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), | 1984 | 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), |
1983 | 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), | 1985 | 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), |
1984 | }; | 1986 | }; |
1987 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | ||
1985 | 1988 | ||
1986 | /* The VU bits for the headphones are in a different register to the mute | 1989 | /* The VU bits for the headphones are in a different register to the mute |
1987 | * bits and only take effect on the PGA if it is actually powered. | 1990 | * bits and only take effect on the PGA if it is actually powered. |
@@ -2119,6 +2122,18 @@ SOC_SINGLE_TLV("HPMIXR MIXINR Volume", WM8962_HEADPHONE_MIXER_4, | |||
2119 | 2122 | ||
2120 | SOC_SINGLE_TLV("Speaker Boost Volume", WM8962_CLASS_D_CONTROL_2, 0, 7, 0, | 2123 | SOC_SINGLE_TLV("Speaker Boost Volume", WM8962_CLASS_D_CONTROL_2, 0, 7, 0, |
2121 | classd_tlv), | 2124 | classd_tlv), |
2125 | |||
2126 | SOC_SINGLE("EQ Switch", WM8962_EQ1, WM8962_EQ_ENA_SHIFT, 1, 0), | ||
2127 | SOC_DOUBLE_R_TLV("EQ1 Volume", WM8962_EQ2, WM8962_EQ22, | ||
2128 | WM8962_EQL_B1_GAIN_SHIFT, 31, 0, eq_tlv), | ||
2129 | SOC_DOUBLE_R_TLV("EQ2 Volume", WM8962_EQ2, WM8962_EQ22, | ||
2130 | WM8962_EQL_B2_GAIN_SHIFT, 31, 0, eq_tlv), | ||
2131 | SOC_DOUBLE_R_TLV("EQ3 Volume", WM8962_EQ2, WM8962_EQ22, | ||
2132 | WM8962_EQL_B3_GAIN_SHIFT, 31, 0, eq_tlv), | ||
2133 | SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23, | ||
2134 | WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv), | ||
2135 | SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23, | ||
2136 | WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv), | ||
2122 | }; | 2137 | }; |
2123 | 2138 | ||
2124 | static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { | 2139 | static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { |
@@ -2184,6 +2199,8 @@ static int sysclk_event(struct snd_soc_dapm_widget *w, | |||
2184 | struct snd_kcontrol *kcontrol, int event) | 2199 | struct snd_kcontrol *kcontrol, int event) |
2185 | { | 2200 | { |
2186 | struct snd_soc_codec *codec = w->codec; | 2201 | struct snd_soc_codec *codec = w->codec; |
2202 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2203 | unsigned long timeout; | ||
2187 | int src; | 2204 | int src; |
2188 | int fll; | 2205 | int fll; |
2189 | 2206 | ||
@@ -2203,9 +2220,19 @@ static int sysclk_event(struct snd_soc_dapm_widget *w, | |||
2203 | 2220 | ||
2204 | switch (event) { | 2221 | switch (event) { |
2205 | case SND_SOC_DAPM_PRE_PMU: | 2222 | case SND_SOC_DAPM_PRE_PMU: |
2206 | if (fll) | 2223 | if (fll) { |
2207 | snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, | 2224 | snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, |
2208 | WM8962_FLL_ENA, WM8962_FLL_ENA); | 2225 | WM8962_FLL_ENA, WM8962_FLL_ENA); |
2226 | if (wm8962->irq) { | ||
2227 | timeout = msecs_to_jiffies(5); | ||
2228 | timeout = wait_for_completion_timeout(&wm8962->fll_lock, | ||
2229 | timeout); | ||
2230 | |||
2231 | if (timeout == 0) | ||
2232 | dev_err(codec->dev, | ||
2233 | "Timed out starting FLL\n"); | ||
2234 | } | ||
2235 | } | ||
2209 | break; | 2236 | break; |
2210 | 2237 | ||
2211 | case SND_SOC_DAPM_POST_PMD: | 2238 | case SND_SOC_DAPM_POST_PMD: |
@@ -2763,18 +2790,44 @@ static const int bclk_divs[] = { | |||
2763 | 1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32 | 2790 | 1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32 |
2764 | }; | 2791 | }; |
2765 | 2792 | ||
2793 | static const int sysclk_rates[] = { | ||
2794 | 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536, | ||
2795 | }; | ||
2796 | |||
2766 | static void wm8962_configure_bclk(struct snd_soc_codec *codec) | 2797 | static void wm8962_configure_bclk(struct snd_soc_codec *codec) |
2767 | { | 2798 | { |
2768 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 2799 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
2769 | int dspclk, i; | 2800 | int dspclk, i; |
2770 | int clocking2 = 0; | 2801 | int clocking2 = 0; |
2802 | int clocking4 = 0; | ||
2771 | int aif2 = 0; | 2803 | int aif2 = 0; |
2772 | 2804 | ||
2773 | if (!wm8962->bclk) { | 2805 | if (!wm8962->sysclk_rate) { |
2774 | dev_dbg(codec->dev, "No BCLK rate configured\n"); | 2806 | dev_dbg(codec->dev, "No SYSCLK configured\n"); |
2807 | return; | ||
2808 | } | ||
2809 | |||
2810 | if (!wm8962->bclk || !wm8962->lrclk) { | ||
2811 | dev_dbg(codec->dev, "No audio clocks configured\n"); | ||
2775 | return; | 2812 | return; |
2776 | } | 2813 | } |
2777 | 2814 | ||
2815 | for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) { | ||
2816 | if (sysclk_rates[i] == wm8962->sysclk_rate / wm8962->lrclk) { | ||
2817 | clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT; | ||
2818 | break; | ||
2819 | } | ||
2820 | } | ||
2821 | |||
2822 | if (i == ARRAY_SIZE(sysclk_rates)) { | ||
2823 | dev_err(codec->dev, "Unsupported sysclk ratio %d\n", | ||
2824 | wm8962->sysclk_rate / wm8962->lrclk); | ||
2825 | return; | ||
2826 | } | ||
2827 | |||
2828 | snd_soc_update_bits(codec, WM8962_CLOCKING_4, | ||
2829 | WM8962_SYSCLK_RATE_MASK, clocking4); | ||
2830 | |||
2778 | dspclk = snd_soc_read(codec, WM8962_CLOCKING1); | 2831 | dspclk = snd_soc_read(codec, WM8962_CLOCKING1); |
2779 | if (dspclk < 0) { | 2832 | if (dspclk < 0) { |
2780 | dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk); | 2833 | dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk); |
@@ -2844,6 +2897,8 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec, | |||
2844 | /* VMID 2*50k */ | 2897 | /* VMID 2*50k */ |
2845 | snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, | 2898 | snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, |
2846 | WM8962_VMID_SEL_MASK, 0x80); | 2899 | WM8962_VMID_SEL_MASK, 0x80); |
2900 | |||
2901 | wm8962_configure_bclk(codec); | ||
2847 | break; | 2902 | break; |
2848 | 2903 | ||
2849 | case SND_SOC_BIAS_STANDBY: | 2904 | case SND_SOC_BIAS_STANDBY: |
@@ -2876,8 +2931,6 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec, | |||
2876 | snd_soc_update_bits(codec, WM8962_CLOCKING2, | 2931 | snd_soc_update_bits(codec, WM8962_CLOCKING2, |
2877 | WM8962_CLKREG_OVD, | 2932 | WM8962_CLKREG_OVD, |
2878 | WM8962_CLKREG_OVD); | 2933 | WM8962_CLKREG_OVD); |
2879 | |||
2880 | wm8962_configure_bclk(codec); | ||
2881 | } | 2934 | } |
2882 | 2935 | ||
2883 | /* VMID 2*250k */ | 2936 | /* VMID 2*250k */ |
@@ -2918,10 +2971,6 @@ static const struct { | |||
2918 | { 96000, 6 }, | 2971 | { 96000, 6 }, |
2919 | }; | 2972 | }; |
2920 | 2973 | ||
2921 | static const int sysclk_rates[] = { | ||
2922 | 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536, | ||
2923 | }; | ||
2924 | |||
2925 | static int wm8962_hw_params(struct snd_pcm_substream *substream, | 2974 | static int wm8962_hw_params(struct snd_pcm_substream *substream, |
2926 | struct snd_pcm_hw_params *params, | 2975 | struct snd_pcm_hw_params *params, |
2927 | struct snd_soc_dai *dai) | 2976 | struct snd_soc_dai *dai) |
@@ -2929,41 +2978,27 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream, | |||
2929 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 2978 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
2930 | struct snd_soc_codec *codec = rtd->codec; | 2979 | struct snd_soc_codec *codec = rtd->codec; |
2931 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 2980 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
2932 | int rate = params_rate(params); | ||
2933 | int i; | 2981 | int i; |
2934 | int aif0 = 0; | 2982 | int aif0 = 0; |
2935 | int adctl3 = 0; | 2983 | int adctl3 = 0; |
2936 | int clocking4 = 0; | ||
2937 | 2984 | ||
2938 | wm8962->bclk = snd_soc_params_to_bclk(params); | 2985 | wm8962->bclk = snd_soc_params_to_bclk(params); |
2939 | wm8962->lrclk = params_rate(params); | 2986 | wm8962->lrclk = params_rate(params); |
2940 | 2987 | ||
2941 | for (i = 0; i < ARRAY_SIZE(sr_vals); i++) { | 2988 | for (i = 0; i < ARRAY_SIZE(sr_vals); i++) { |
2942 | if (sr_vals[i].rate == rate) { | 2989 | if (sr_vals[i].rate == wm8962->lrclk) { |
2943 | adctl3 |= sr_vals[i].reg; | 2990 | adctl3 |= sr_vals[i].reg; |
2944 | break; | 2991 | break; |
2945 | } | 2992 | } |
2946 | } | 2993 | } |
2947 | if (i == ARRAY_SIZE(sr_vals)) { | 2994 | if (i == ARRAY_SIZE(sr_vals)) { |
2948 | dev_err(codec->dev, "Unsupported rate %dHz\n", rate); | 2995 | dev_err(codec->dev, "Unsupported rate %dHz\n", wm8962->lrclk); |
2949 | return -EINVAL; | 2996 | return -EINVAL; |
2950 | } | 2997 | } |
2951 | 2998 | ||
2952 | if (rate % 8000 == 0) | 2999 | if (wm8962->lrclk % 8000 == 0) |
2953 | adctl3 |= WM8962_SAMPLE_RATE_INT_MODE; | 3000 | adctl3 |= WM8962_SAMPLE_RATE_INT_MODE; |
2954 | 3001 | ||
2955 | for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) { | ||
2956 | if (sysclk_rates[i] == wm8962->sysclk_rate / rate) { | ||
2957 | clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT; | ||
2958 | break; | ||
2959 | } | ||
2960 | } | ||
2961 | if (i == ARRAY_SIZE(sysclk_rates)) { | ||
2962 | dev_err(codec->dev, "Unsupported sysclk ratio %d\n", | ||
2963 | wm8962->sysclk_rate / rate); | ||
2964 | return -EINVAL; | ||
2965 | } | ||
2966 | |||
2967 | switch (params_format(params)) { | 3002 | switch (params_format(params)) { |
2968 | case SNDRV_PCM_FORMAT_S16_LE: | 3003 | case SNDRV_PCM_FORMAT_S16_LE: |
2969 | break; | 3004 | break; |
@@ -2985,8 +3020,6 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream, | |||
2985 | snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3, | 3020 | snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3, |
2986 | WM8962_SAMPLE_RATE_INT_MODE | | 3021 | WM8962_SAMPLE_RATE_INT_MODE | |
2987 | WM8962_SAMPLE_RATE_MASK, adctl3); | 3022 | WM8962_SAMPLE_RATE_MASK, adctl3); |
2988 | snd_soc_update_bits(codec, WM8962_CLOCKING_4, | ||
2989 | WM8962_SYSCLK_RATE_MASK, clocking4); | ||
2990 | 3023 | ||
2991 | wm8962_configure_bclk(codec); | 3024 | wm8962_configure_bclk(codec); |
2992 | 3025 | ||
@@ -3261,16 +3294,31 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
3261 | 3294 | ||
3262 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); | 3295 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); |
3263 | 3296 | ||
3264 | /* This should be a massive overestimate */ | 3297 | ret = 0; |
3265 | timeout = msecs_to_jiffies(1); | 3298 | |
3299 | if (fll1 & WM8962_FLL_ENA) { | ||
3300 | /* This should be a massive overestimate but go even | ||
3301 | * higher if we'll error out | ||
3302 | */ | ||
3303 | if (wm8962->irq) | ||
3304 | timeout = msecs_to_jiffies(5); | ||
3305 | else | ||
3306 | timeout = msecs_to_jiffies(1); | ||
3307 | |||
3308 | timeout = wait_for_completion_timeout(&wm8962->fll_lock, | ||
3309 | timeout); | ||
3266 | 3310 | ||
3267 | wait_for_completion_timeout(&wm8962->fll_lock, timeout); | 3311 | if (timeout == 0 && wm8962->irq) { |
3312 | dev_err(codec->dev, "FLL lock timed out"); | ||
3313 | ret = -ETIMEDOUT; | ||
3314 | } | ||
3315 | } | ||
3268 | 3316 | ||
3269 | wm8962->fll_fref = Fref; | 3317 | wm8962->fll_fref = Fref; |
3270 | wm8962->fll_fout = Fout; | 3318 | wm8962->fll_fout = Fout; |
3271 | wm8962->fll_src = source; | 3319 | wm8962->fll_src = source; |
3272 | 3320 | ||
3273 | return 0; | 3321 | return ret; |
3274 | } | 3322 | } |
3275 | 3323 | ||
3276 | static int wm8962_mute(struct snd_soc_dai *dai, int mute) | 3324 | static int wm8962_mute(struct snd_soc_dai *dai, int mute) |
@@ -3731,8 +3779,6 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3731 | int ret; | 3779 | int ret; |
3732 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3780 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3733 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); | 3781 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); |
3734 | struct i2c_client *i2c = container_of(codec->dev, struct i2c_client, | ||
3735 | dev); | ||
3736 | u16 *reg_cache = codec->reg_cache; | 3782 | u16 *reg_cache = codec->reg_cache; |
3737 | int i, trigger, irq_pol; | 3783 | int i, trigger, irq_pol; |
3738 | bool dmicclk, dmicdat; | 3784 | bool dmicclk, dmicdat; |
@@ -3871,6 +3917,9 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3871 | snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME, | 3917 | snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME, |
3872 | WM8962_HPOUT_VU, WM8962_HPOUT_VU); | 3918 | WM8962_HPOUT_VU, WM8962_HPOUT_VU); |
3873 | 3919 | ||
3920 | /* Stereo control for EQ */ | ||
3921 | snd_soc_update_bits(codec, WM8962_EQ1, WM8962_EQ_SHARED_COEFF, 0); | ||
3922 | |||
3874 | wm8962_add_widgets(codec); | 3923 | wm8962_add_widgets(codec); |
3875 | 3924 | ||
3876 | /* Save boards having to disable DMIC when not in use */ | 3925 | /* Save boards having to disable DMIC when not in use */ |
@@ -3899,7 +3948,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3899 | wm8962_init_beep(codec); | 3948 | wm8962_init_beep(codec); |
3900 | wm8962_init_gpio(codec); | 3949 | wm8962_init_gpio(codec); |
3901 | 3950 | ||
3902 | if (i2c->irq) { | 3951 | if (wm8962->irq) { |
3903 | if (pdata && pdata->irq_active_low) { | 3952 | if (pdata && pdata->irq_active_low) { |
3904 | trigger = IRQF_TRIGGER_LOW; | 3953 | trigger = IRQF_TRIGGER_LOW; |
3905 | irq_pol = WM8962_IRQ_POL; | 3954 | irq_pol = WM8962_IRQ_POL; |
@@ -3911,12 +3960,13 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3911 | snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL, | 3960 | snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL, |
3912 | WM8962_IRQ_POL, irq_pol); | 3961 | WM8962_IRQ_POL, irq_pol); |
3913 | 3962 | ||
3914 | ret = request_threaded_irq(i2c->irq, NULL, wm8962_irq, | 3963 | ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq, |
3915 | trigger | IRQF_ONESHOT, | 3964 | trigger | IRQF_ONESHOT, |
3916 | "wm8962", codec); | 3965 | "wm8962", codec); |
3917 | if (ret != 0) { | 3966 | if (ret != 0) { |
3918 | dev_err(codec->dev, "Failed to request IRQ %d: %d\n", | 3967 | dev_err(codec->dev, "Failed to request IRQ %d: %d\n", |
3919 | i2c->irq, ret); | 3968 | wm8962->irq, ret); |
3969 | wm8962->irq = 0; | ||
3920 | /* Non-fatal */ | 3970 | /* Non-fatal */ |
3921 | } else { | 3971 | } else { |
3922 | /* Enable some IRQs by default */ | 3972 | /* Enable some IRQs by default */ |
@@ -3941,12 +3991,10 @@ err: | |||
3941 | static int wm8962_remove(struct snd_soc_codec *codec) | 3991 | static int wm8962_remove(struct snd_soc_codec *codec) |
3942 | { | 3992 | { |
3943 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3993 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3944 | struct i2c_client *i2c = container_of(codec->dev, struct i2c_client, | ||
3945 | dev); | ||
3946 | int i; | 3994 | int i; |
3947 | 3995 | ||
3948 | if (i2c->irq) | 3996 | if (wm8962->irq) |
3949 | free_irq(i2c->irq, codec); | 3997 | free_irq(wm8962->irq, codec); |
3950 | 3998 | ||
3951 | cancel_delayed_work_sync(&wm8962->mic_work); | 3999 | cancel_delayed_work_sync(&wm8962->mic_work); |
3952 | 4000 | ||
@@ -3986,6 +4034,8 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3986 | 4034 | ||
3987 | i2c_set_clientdata(i2c, wm8962); | 4035 | i2c_set_clientdata(i2c, wm8962); |
3988 | 4036 | ||
4037 | wm8962->irq = i2c->irq; | ||
4038 | |||
3989 | ret = snd_soc_register_codec(&i2c->dev, | 4039 | ret = snd_soc_register_codec(&i2c->dev, |
3990 | &soc_codec_dev_wm8962, &wm8962_dai, 1); | 4040 | &soc_codec_dev_wm8962, &wm8962_dai, 1); |
3991 | if (ret < 0) | 4041 | if (ret < 0) |
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c new file mode 100644 index 000000000000..17f04ec2b940 --- /dev/null +++ b/sound/soc/codecs/wm8983.c | |||
@@ -0,0 +1,1203 @@ | |||
1 | /* | ||
2 | * wm8983.c -- WM8983 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2011 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/spi/spi.h> | ||
20 | #include <linux/slab.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/initval.h> | ||
26 | #include <sound/tlv.h> | ||
27 | |||
28 | #include "wm8983.h" | ||
29 | |||
30 | static const u16 wm8983_reg_defs[WM8983_MAX_REGISTER + 1] = { | ||
31 | [0x00] = 0x0000, /* R0 - Software Reset */ | ||
32 | [0x01] = 0x0000, /* R1 - Power management 1 */ | ||
33 | [0x02] = 0x0000, /* R2 - Power management 2 */ | ||
34 | [0x03] = 0x0000, /* R3 - Power management 3 */ | ||
35 | [0x04] = 0x0050, /* R4 - Audio Interface */ | ||
36 | [0x05] = 0x0000, /* R5 - Companding control */ | ||
37 | [0x06] = 0x0140, /* R6 - Clock Gen control */ | ||
38 | [0x07] = 0x0000, /* R7 - Additional control */ | ||
39 | [0x08] = 0x0000, /* R8 - GPIO Control */ | ||
40 | [0x09] = 0x0000, /* R9 - Jack Detect Control 1 */ | ||
41 | [0x0A] = 0x0000, /* R10 - DAC Control */ | ||
42 | [0x0B] = 0x00FF, /* R11 - Left DAC digital Vol */ | ||
43 | [0x0C] = 0x00FF, /* R12 - Right DAC digital vol */ | ||
44 | [0x0D] = 0x0000, /* R13 - Jack Detect Control 2 */ | ||
45 | [0x0E] = 0x0100, /* R14 - ADC Control */ | ||
46 | [0x0F] = 0x00FF, /* R15 - Left ADC Digital Vol */ | ||
47 | [0x10] = 0x00FF, /* R16 - Right ADC Digital Vol */ | ||
48 | [0x12] = 0x012C, /* R18 - EQ1 - low shelf */ | ||
49 | [0x13] = 0x002C, /* R19 - EQ2 - peak 1 */ | ||
50 | [0x14] = 0x002C, /* R20 - EQ3 - peak 2 */ | ||
51 | [0x15] = 0x002C, /* R21 - EQ4 - peak 3 */ | ||
52 | [0x16] = 0x002C, /* R22 - EQ5 - high shelf */ | ||
53 | [0x18] = 0x0032, /* R24 - DAC Limiter 1 */ | ||
54 | [0x19] = 0x0000, /* R25 - DAC Limiter 2 */ | ||
55 | [0x1B] = 0x0000, /* R27 - Notch Filter 1 */ | ||
56 | [0x1C] = 0x0000, /* R28 - Notch Filter 2 */ | ||
57 | [0x1D] = 0x0000, /* R29 - Notch Filter 3 */ | ||
58 | [0x1E] = 0x0000, /* R30 - Notch Filter 4 */ | ||
59 | [0x20] = 0x0038, /* R32 - ALC control 1 */ | ||
60 | [0x21] = 0x000B, /* R33 - ALC control 2 */ | ||
61 | [0x22] = 0x0032, /* R34 - ALC control 3 */ | ||
62 | [0x23] = 0x0000, /* R35 - Noise Gate */ | ||
63 | [0x24] = 0x0008, /* R36 - PLL N */ | ||
64 | [0x25] = 0x000C, /* R37 - PLL K 1 */ | ||
65 | [0x26] = 0x0093, /* R38 - PLL K 2 */ | ||
66 | [0x27] = 0x00E9, /* R39 - PLL K 3 */ | ||
67 | [0x29] = 0x0000, /* R41 - 3D control */ | ||
68 | [0x2A] = 0x0000, /* R42 - OUT4 to ADC */ | ||
69 | [0x2B] = 0x0000, /* R43 - Beep control */ | ||
70 | [0x2C] = 0x0033, /* R44 - Input ctrl */ | ||
71 | [0x2D] = 0x0010, /* R45 - Left INP PGA gain ctrl */ | ||
72 | [0x2E] = 0x0010, /* R46 - Right INP PGA gain ctrl */ | ||
73 | [0x2F] = 0x0100, /* R47 - Left ADC BOOST ctrl */ | ||
74 | [0x30] = 0x0100, /* R48 - Right ADC BOOST ctrl */ | ||
75 | [0x31] = 0x0002, /* R49 - Output ctrl */ | ||
76 | [0x32] = 0x0001, /* R50 - Left mixer ctrl */ | ||
77 | [0x33] = 0x0001, /* R51 - Right mixer ctrl */ | ||
78 | [0x34] = 0x0039, /* R52 - LOUT1 (HP) volume ctrl */ | ||
79 | [0x35] = 0x0039, /* R53 - ROUT1 (HP) volume ctrl */ | ||
80 | [0x36] = 0x0039, /* R54 - LOUT2 (SPK) volume ctrl */ | ||
81 | [0x37] = 0x0039, /* R55 - ROUT2 (SPK) volume ctrl */ | ||
82 | [0x38] = 0x0001, /* R56 - OUT3 mixer ctrl */ | ||
83 | [0x39] = 0x0001, /* R57 - OUT4 (MONO) mix ctrl */ | ||
84 | [0x3D] = 0x0000 /* R61 - BIAS CTRL */ | ||
85 | }; | ||
86 | |||
87 | static const struct wm8983_reg_access { | ||
88 | u16 read; /* Mask of readable bits */ | ||
89 | u16 write; /* Mask of writable bits */ | ||
90 | } wm8983_access_masks[WM8983_MAX_REGISTER + 1] = { | ||
91 | [0x00] = { 0x0000, 0x01FF }, /* R0 - Software Reset */ | ||
92 | [0x01] = { 0x0000, 0x01FF }, /* R1 - Power management 1 */ | ||
93 | [0x02] = { 0x0000, 0x01FF }, /* R2 - Power management 2 */ | ||
94 | [0x03] = { 0x0000, 0x01EF }, /* R3 - Power management 3 */ | ||
95 | [0x04] = { 0x0000, 0x01FF }, /* R4 - Audio Interface */ | ||
96 | [0x05] = { 0x0000, 0x003F }, /* R5 - Companding control */ | ||
97 | [0x06] = { 0x0000, 0x01FD }, /* R6 - Clock Gen control */ | ||
98 | [0x07] = { 0x0000, 0x000F }, /* R7 - Additional control */ | ||
99 | [0x08] = { 0x0000, 0x003F }, /* R8 - GPIO Control */ | ||
100 | [0x09] = { 0x0000, 0x0070 }, /* R9 - Jack Detect Control 1 */ | ||
101 | [0x0A] = { 0x0000, 0x004F }, /* R10 - DAC Control */ | ||
102 | [0x0B] = { 0x0000, 0x01FF }, /* R11 - Left DAC digital Vol */ | ||
103 | [0x0C] = { 0x0000, 0x01FF }, /* R12 - Right DAC digital vol */ | ||
104 | [0x0D] = { 0x0000, 0x00FF }, /* R13 - Jack Detect Control 2 */ | ||
105 | [0x0E] = { 0x0000, 0x01FB }, /* R14 - ADC Control */ | ||
106 | [0x0F] = { 0x0000, 0x01FF }, /* R15 - Left ADC Digital Vol */ | ||
107 | [0x10] = { 0x0000, 0x01FF }, /* R16 - Right ADC Digital Vol */ | ||
108 | [0x12] = { 0x0000, 0x017F }, /* R18 - EQ1 - low shelf */ | ||
109 | [0x13] = { 0x0000, 0x017F }, /* R19 - EQ2 - peak 1 */ | ||
110 | [0x14] = { 0x0000, 0x017F }, /* R20 - EQ3 - peak 2 */ | ||
111 | [0x15] = { 0x0000, 0x017F }, /* R21 - EQ4 - peak 3 */ | ||
112 | [0x16] = { 0x0000, 0x007F }, /* R22 - EQ5 - high shelf */ | ||
113 | [0x18] = { 0x0000, 0x01FF }, /* R24 - DAC Limiter 1 */ | ||
114 | [0x19] = { 0x0000, 0x007F }, /* R25 - DAC Limiter 2 */ | ||
115 | [0x1B] = { 0x0000, 0x01FF }, /* R27 - Notch Filter 1 */ | ||
116 | [0x1C] = { 0x0000, 0x017F }, /* R28 - Notch Filter 2 */ | ||
117 | [0x1D] = { 0x0000, 0x017F }, /* R29 - Notch Filter 3 */ | ||
118 | [0x1E] = { 0x0000, 0x017F }, /* R30 - Notch Filter 4 */ | ||
119 | [0x20] = { 0x0000, 0x01BF }, /* R32 - ALC control 1 */ | ||
120 | [0x21] = { 0x0000, 0x00FF }, /* R33 - ALC control 2 */ | ||
121 | [0x22] = { 0x0000, 0x01FF }, /* R34 - ALC control 3 */ | ||
122 | [0x23] = { 0x0000, 0x000F }, /* R35 - Noise Gate */ | ||
123 | [0x24] = { 0x0000, 0x001F }, /* R36 - PLL N */ | ||
124 | [0x25] = { 0x0000, 0x003F }, /* R37 - PLL K 1 */ | ||
125 | [0x26] = { 0x0000, 0x01FF }, /* R38 - PLL K 2 */ | ||
126 | [0x27] = { 0x0000, 0x01FF }, /* R39 - PLL K 3 */ | ||
127 | [0x29] = { 0x0000, 0x000F }, /* R41 - 3D control */ | ||
128 | [0x2A] = { 0x0000, 0x01E7 }, /* R42 - OUT4 to ADC */ | ||
129 | [0x2B] = { 0x0000, 0x01BF }, /* R43 - Beep control */ | ||
130 | [0x2C] = { 0x0000, 0x0177 }, /* R44 - Input ctrl */ | ||
131 | [0x2D] = { 0x0000, 0x01FF }, /* R45 - Left INP PGA gain ctrl */ | ||
132 | [0x2E] = { 0x0000, 0x01FF }, /* R46 - Right INP PGA gain ctrl */ | ||
133 | [0x2F] = { 0x0000, 0x0177 }, /* R47 - Left ADC BOOST ctrl */ | ||
134 | [0x30] = { 0x0000, 0x0177 }, /* R48 - Right ADC BOOST ctrl */ | ||
135 | [0x31] = { 0x0000, 0x007F }, /* R49 - Output ctrl */ | ||
136 | [0x32] = { 0x0000, 0x01FF }, /* R50 - Left mixer ctrl */ | ||
137 | [0x33] = { 0x0000, 0x01FF }, /* R51 - Right mixer ctrl */ | ||
138 | [0x34] = { 0x0000, 0x01FF }, /* R52 - LOUT1 (HP) volume ctrl */ | ||
139 | [0x35] = { 0x0000, 0x01FF }, /* R53 - ROUT1 (HP) volume ctrl */ | ||
140 | [0x36] = { 0x0000, 0x01FF }, /* R54 - LOUT2 (SPK) volume ctrl */ | ||
141 | [0x37] = { 0x0000, 0x01FF }, /* R55 - ROUT2 (SPK) volume ctrl */ | ||
142 | [0x38] = { 0x0000, 0x004F }, /* R56 - OUT3 mixer ctrl */ | ||
143 | [0x39] = { 0x0000, 0x00FF }, /* R57 - OUT4 (MONO) mix ctrl */ | ||
144 | [0x3D] = { 0x0000, 0x0100 } /* R61 - BIAS CTRL */ | ||
145 | }; | ||
146 | |||
147 | /* vol/gain update regs */ | ||
148 | static const int vol_update_regs[] = { | ||
149 | WM8983_LEFT_DAC_DIGITAL_VOL, | ||
150 | WM8983_RIGHT_DAC_DIGITAL_VOL, | ||
151 | WM8983_LEFT_ADC_DIGITAL_VOL, | ||
152 | WM8983_RIGHT_ADC_DIGITAL_VOL, | ||
153 | WM8983_LOUT1_HP_VOLUME_CTRL, | ||
154 | WM8983_ROUT1_HP_VOLUME_CTRL, | ||
155 | WM8983_LOUT2_SPK_VOLUME_CTRL, | ||
156 | WM8983_ROUT2_SPK_VOLUME_CTRL, | ||
157 | WM8983_LEFT_INP_PGA_GAIN_CTRL, | ||
158 | WM8983_RIGHT_INP_PGA_GAIN_CTRL | ||
159 | }; | ||
160 | |||
161 | struct wm8983_priv { | ||
162 | enum snd_soc_control_type control_type; | ||
163 | u32 sysclk; | ||
164 | u32 bclk; | ||
165 | }; | ||
166 | |||
167 | static const struct { | ||
168 | int div; | ||
169 | int ratio; | ||
170 | } fs_ratios[] = { | ||
171 | { 10, 128 }, | ||
172 | { 15, 192 }, | ||
173 | { 20, 256 }, | ||
174 | { 30, 384 }, | ||
175 | { 40, 512 }, | ||
176 | { 60, 768 }, | ||
177 | { 80, 1024 }, | ||
178 | { 120, 1536 } | ||
179 | }; | ||
180 | |||
181 | static const int srates[] = { 48000, 32000, 24000, 16000, 12000, 8000 }; | ||
182 | |||
183 | static const int bclk_divs[] = { | ||
184 | 1, 2, 4, 8, 16, 32 | ||
185 | }; | ||
186 | |||
187 | static int eqmode_get(struct snd_kcontrol *kcontrol, | ||
188 | struct snd_ctl_elem_value *ucontrol); | ||
189 | static int eqmode_put(struct snd_kcontrol *kcontrol, | ||
190 | struct snd_ctl_elem_value *ucontrol); | ||
191 | |||
192 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1); | ||
193 | static const DECLARE_TLV_DB_SCALE(adc_tlv, -12700, 50, 1); | ||
194 | static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); | ||
195 | static const DECLARE_TLV_DB_SCALE(lim_thresh_tlv, -600, 100, 0); | ||
196 | static const DECLARE_TLV_DB_SCALE(lim_boost_tlv, 0, 100, 0); | ||
197 | static const DECLARE_TLV_DB_SCALE(alc_min_tlv, -1200, 600, 0); | ||
198 | static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -675, 600, 0); | ||
199 | static const DECLARE_TLV_DB_SCALE(alc_tar_tlv, -2250, 150, 0); | ||
200 | static const DECLARE_TLV_DB_SCALE(pga_vol_tlv, -1200, 75, 0); | ||
201 | static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1); | ||
202 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | ||
203 | static const DECLARE_TLV_DB_SCALE(aux_tlv, -1500, 300, 0); | ||
204 | static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); | ||
205 | static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); | ||
206 | |||
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, | ||
209 | alc_sel_text); | ||
210 | |||
211 | static const char *alc_mode_text[] = { "ALC", "Limiter" }; | ||
212 | static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, | ||
213 | alc_mode_text); | ||
214 | |||
215 | static const char *filter_mode_text[] = { "Audio", "Application" }; | ||
216 | static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7, | ||
217 | filter_mode_text); | ||
218 | |||
219 | static const char *eq_bw_text[] = { "Narrow", "Wide" }; | ||
220 | static const char *eqmode_text[] = { "Capture", "Playback" }; | ||
221 | static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); | ||
222 | |||
223 | static const char *eq1_cutoff_text[] = { | ||
224 | "80Hz", "105Hz", "135Hz", "175Hz" | ||
225 | }; | ||
226 | static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5, | ||
227 | eq1_cutoff_text); | ||
228 | static const char *eq2_cutoff_text[] = { | ||
229 | "230Hz", "300Hz", "385Hz", "500Hz" | ||
230 | }; | ||
231 | static const 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, | ||
233 | eq2_cutoff_text); | ||
234 | static const char *eq3_cutoff_text[] = { | ||
235 | "650Hz", "850Hz", "1.1kHz", "1.4kHz" | ||
236 | }; | ||
237 | static const 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, | ||
239 | eq3_cutoff_text); | ||
240 | static const char *eq4_cutoff_text[] = { | ||
241 | "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" | ||
242 | }; | ||
243 | static const 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, | ||
245 | eq4_cutoff_text); | ||
246 | static const char *eq5_cutoff_text[] = { | ||
247 | "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" | ||
248 | }; | ||
249 | static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5, | ||
250 | eq5_cutoff_text); | ||
251 | |||
252 | static const char *speaker_mode_text[] = { "Class A/B", "Class D" }; | ||
253 | static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text); | ||
254 | |||
255 | static const char *depth_3d_text[] = { | ||
256 | "Off", | ||
257 | "6.67%", | ||
258 | "13.3%", | ||
259 | "20%", | ||
260 | "26.7%", | ||
261 | "33.3%", | ||
262 | "40%", | ||
263 | "46.6%", | ||
264 | "53.3%", | ||
265 | "60%", | ||
266 | "66.7%", | ||
267 | "73.3%", | ||
268 | "80%", | ||
269 | "86.7%", | ||
270 | "93.3%", | ||
271 | "100%" | ||
272 | }; | ||
273 | static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0, | ||
274 | depth_3d_text); | ||
275 | |||
276 | static const struct snd_kcontrol_new wm8983_snd_controls[] = { | ||
277 | SOC_SINGLE("Digital Loopback Switch", WM8983_COMPANDING_CONTROL, | ||
278 | 0, 1, 0), | ||
279 | |||
280 | SOC_ENUM("ALC Capture Function", alc_sel), | ||
281 | SOC_SINGLE_TLV("ALC Capture Max Volume", WM8983_ALC_CONTROL_1, | ||
282 | 3, 7, 0, alc_max_tlv), | ||
283 | SOC_SINGLE_TLV("ALC Capture Min Volume", WM8983_ALC_CONTROL_1, | ||
284 | 0, 7, 0, alc_min_tlv), | ||
285 | SOC_SINGLE_TLV("ALC Capture Target Volume", WM8983_ALC_CONTROL_2, | ||
286 | 0, 15, 0, alc_tar_tlv), | ||
287 | SOC_SINGLE("ALC Capture Attack", WM8983_ALC_CONTROL_3, 0, 10, 0), | ||
288 | SOC_SINGLE("ALC Capture Hold", WM8983_ALC_CONTROL_2, 4, 10, 0), | ||
289 | SOC_SINGLE("ALC Capture Decay", WM8983_ALC_CONTROL_3, 4, 10, 0), | ||
290 | SOC_ENUM("ALC Mode", alc_mode), | ||
291 | SOC_SINGLE("ALC Capture NG Switch", WM8983_NOISE_GATE, | ||
292 | 3, 1, 0), | ||
293 | SOC_SINGLE("ALC Capture NG Threshold", WM8983_NOISE_GATE, | ||
294 | 0, 7, 1), | ||
295 | |||
296 | SOC_DOUBLE_R_TLV("Capture Volume", WM8983_LEFT_ADC_DIGITAL_VOL, | ||
297 | WM8983_RIGHT_ADC_DIGITAL_VOL, 0, 255, 0, adc_tlv), | ||
298 | SOC_DOUBLE_R("Capture PGA ZC Switch", WM8983_LEFT_INP_PGA_GAIN_CTRL, | ||
299 | WM8983_RIGHT_INP_PGA_GAIN_CTRL, 7, 1, 0), | ||
300 | SOC_DOUBLE_R_TLV("Capture PGA Volume", WM8983_LEFT_INP_PGA_GAIN_CTRL, | ||
301 | WM8983_RIGHT_INP_PGA_GAIN_CTRL, 0, 63, 0, pga_vol_tlv), | ||
302 | |||
303 | SOC_DOUBLE_R_TLV("Capture PGA Boost Volume", | ||
304 | WM8983_LEFT_ADC_BOOST_CTRL, WM8983_RIGHT_ADC_BOOST_CTRL, | ||
305 | 8, 1, 0, pga_boost_tlv), | ||
306 | |||
307 | SOC_DOUBLE("ADC Inversion Switch", WM8983_ADC_CONTROL, 0, 1, 1, 0), | ||
308 | SOC_SINGLE("ADC 128x Oversampling Switch", WM8983_ADC_CONTROL, 8, 1, 0), | ||
309 | |||
310 | SOC_DOUBLE_R_TLV("Playback Volume", WM8983_LEFT_DAC_DIGITAL_VOL, | ||
311 | WM8983_RIGHT_DAC_DIGITAL_VOL, 0, 255, 0, dac_tlv), | ||
312 | |||
313 | SOC_SINGLE("DAC Playback Limiter Switch", WM8983_DAC_LIMITER_1, 8, 1, 0), | ||
314 | SOC_SINGLE("DAC Playback Limiter Decay", WM8983_DAC_LIMITER_1, 4, 10, 0), | ||
315 | SOC_SINGLE("DAC Playback Limiter Attack", WM8983_DAC_LIMITER_1, 0, 11, 0), | ||
316 | SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8983_DAC_LIMITER_2, | ||
317 | 4, 7, 1, lim_thresh_tlv), | ||
318 | SOC_SINGLE_TLV("DAC Playback Limiter Boost Volume", WM8983_DAC_LIMITER_2, | ||
319 | 0, 12, 0, lim_boost_tlv), | ||
320 | SOC_DOUBLE("DAC Inversion Switch", WM8983_DAC_CONTROL, 0, 1, 1, 0), | ||
321 | SOC_SINGLE("DAC Auto Mute Switch", WM8983_DAC_CONTROL, 2, 1, 0), | ||
322 | SOC_SINGLE("DAC 128x Oversampling Switch", WM8983_DAC_CONTROL, 3, 1, 0), | ||
323 | |||
324 | SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8983_LOUT1_HP_VOLUME_CTRL, | ||
325 | WM8983_ROUT1_HP_VOLUME_CTRL, 0, 63, 0, out_tlv), | ||
326 | SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8983_LOUT1_HP_VOLUME_CTRL, | ||
327 | WM8983_ROUT1_HP_VOLUME_CTRL, 7, 1, 0), | ||
328 | SOC_DOUBLE_R("Headphone Switch", WM8983_LOUT1_HP_VOLUME_CTRL, | ||
329 | WM8983_ROUT1_HP_VOLUME_CTRL, 6, 1, 1), | ||
330 | |||
331 | SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8983_LOUT2_SPK_VOLUME_CTRL, | ||
332 | WM8983_ROUT2_SPK_VOLUME_CTRL, 0, 63, 0, out_tlv), | ||
333 | SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8983_LOUT2_SPK_VOLUME_CTRL, | ||
334 | WM8983_ROUT2_SPK_VOLUME_CTRL, 7, 1, 0), | ||
335 | SOC_DOUBLE_R("Speaker Switch", WM8983_LOUT2_SPK_VOLUME_CTRL, | ||
336 | WM8983_ROUT2_SPK_VOLUME_CTRL, 6, 1, 1), | ||
337 | |||
338 | SOC_SINGLE("OUT3 Switch", WM8983_OUT3_MIXER_CTRL, | ||
339 | 6, 1, 1), | ||
340 | |||
341 | SOC_SINGLE("OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, | ||
342 | 6, 1, 1), | ||
343 | |||
344 | SOC_SINGLE("High Pass Filter Switch", WM8983_ADC_CONTROL, 8, 1, 0), | ||
345 | SOC_ENUM("High Pass Filter Mode", filter_mode), | ||
346 | SOC_SINGLE("High Pass Filter Cutoff", WM8983_ADC_CONTROL, 4, 7, 0), | ||
347 | |||
348 | SOC_DOUBLE_R_TLV("Aux Bypass Volume", | ||
349 | WM8983_LEFT_MIXER_CTRL, WM8983_RIGHT_MIXER_CTRL, 6, 7, 0, | ||
350 | aux_tlv), | ||
351 | |||
352 | SOC_DOUBLE_R_TLV("Input PGA Bypass Volume", | ||
353 | WM8983_LEFT_MIXER_CTRL, WM8983_RIGHT_MIXER_CTRL, 2, 7, 0, | ||
354 | bypass_tlv), | ||
355 | |||
356 | SOC_ENUM_EXT("Equalizer Function", eqmode, eqmode_get, eqmode_put), | ||
357 | SOC_ENUM("EQ1 Cutoff", eq1_cutoff), | ||
358 | SOC_SINGLE_TLV("EQ1 Volume", WM8983_EQ1_LOW_SHELF, 0, 24, 1, eq_tlv), | ||
359 | SOC_ENUM("EQ2 Bandwith", eq2_bw), | ||
360 | SOC_ENUM("EQ2 Cutoff", eq2_cutoff), | ||
361 | SOC_SINGLE_TLV("EQ2 Volume", WM8983_EQ2_PEAK_1, 0, 24, 1, eq_tlv), | ||
362 | SOC_ENUM("EQ3 Bandwith", eq3_bw), | ||
363 | SOC_ENUM("EQ3 Cutoff", eq3_cutoff), | ||
364 | SOC_SINGLE_TLV("EQ3 Volume", WM8983_EQ3_PEAK_2, 0, 24, 1, eq_tlv), | ||
365 | SOC_ENUM("EQ4 Bandwith", eq4_bw), | ||
366 | SOC_ENUM("EQ4 Cutoff", eq4_cutoff), | ||
367 | SOC_SINGLE_TLV("EQ4 Volume", WM8983_EQ4_PEAK_3, 0, 24, 1, eq_tlv), | ||
368 | SOC_ENUM("EQ5 Cutoff", eq5_cutoff), | ||
369 | SOC_SINGLE_TLV("EQ5 Volume", WM8983_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv), | ||
370 | |||
371 | SOC_ENUM("3D Depth", depth_3d), | ||
372 | |||
373 | SOC_ENUM("Speaker Mode", speaker_mode) | ||
374 | }; | ||
375 | |||
376 | static const struct snd_kcontrol_new left_out_mixer[] = { | ||
377 | SOC_DAPM_SINGLE("Line Switch", WM8983_LEFT_MIXER_CTRL, 1, 1, 0), | ||
378 | SOC_DAPM_SINGLE("Aux Switch", WM8983_LEFT_MIXER_CTRL, 5, 1, 0), | ||
379 | SOC_DAPM_SINGLE("PCM Switch", WM8983_LEFT_MIXER_CTRL, 0, 1, 0), | ||
380 | }; | ||
381 | |||
382 | static const struct snd_kcontrol_new right_out_mixer[] = { | ||
383 | SOC_DAPM_SINGLE("Line Switch", WM8983_RIGHT_MIXER_CTRL, 1, 1, 0), | ||
384 | SOC_DAPM_SINGLE("Aux Switch", WM8983_RIGHT_MIXER_CTRL, 5, 1, 0), | ||
385 | SOC_DAPM_SINGLE("PCM Switch", WM8983_RIGHT_MIXER_CTRL, 0, 1, 0), | ||
386 | }; | ||
387 | |||
388 | static const struct snd_kcontrol_new left_input_mixer[] = { | ||
389 | SOC_DAPM_SINGLE("L2 Switch", WM8983_INPUT_CTRL, 2, 1, 0), | ||
390 | SOC_DAPM_SINGLE("MicN Switch", WM8983_INPUT_CTRL, 1, 1, 0), | ||
391 | SOC_DAPM_SINGLE("MicP Switch", WM8983_INPUT_CTRL, 0, 1, 0), | ||
392 | }; | ||
393 | |||
394 | static const struct snd_kcontrol_new right_input_mixer[] = { | ||
395 | SOC_DAPM_SINGLE("R2 Switch", WM8983_INPUT_CTRL, 6, 1, 0), | ||
396 | SOC_DAPM_SINGLE("MicN Switch", WM8983_INPUT_CTRL, 5, 1, 0), | ||
397 | SOC_DAPM_SINGLE("MicP Switch", WM8983_INPUT_CTRL, 4, 1, 0), | ||
398 | }; | ||
399 | |||
400 | static const struct snd_kcontrol_new left_boost_mixer[] = { | ||
401 | SOC_DAPM_SINGLE_TLV("L2 Volume", WM8983_LEFT_ADC_BOOST_CTRL, | ||
402 | 4, 7, 0, boost_tlv), | ||
403 | SOC_DAPM_SINGLE_TLV("AUXL Volume", WM8983_LEFT_ADC_BOOST_CTRL, | ||
404 | 0, 7, 0, boost_tlv) | ||
405 | }; | ||
406 | |||
407 | static const struct snd_kcontrol_new out3_mixer[] = { | ||
408 | SOC_DAPM_SINGLE("LMIX2OUT3 Switch", WM8983_OUT3_MIXER_CTRL, | ||
409 | 1, 1, 0), | ||
410 | SOC_DAPM_SINGLE("LDAC2OUT3 Switch", WM8983_OUT3_MIXER_CTRL, | ||
411 | 0, 1, 0), | ||
412 | }; | ||
413 | |||
414 | static const struct snd_kcontrol_new out4_mixer[] = { | ||
415 | SOC_DAPM_SINGLE("LMIX2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, | ||
416 | 4, 1, 0), | ||
417 | SOC_DAPM_SINGLE("RMIX2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, | ||
418 | 1, 1, 0), | ||
419 | SOC_DAPM_SINGLE("LDAC2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, | ||
420 | 3, 1, 0), | ||
421 | SOC_DAPM_SINGLE("RDAC2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, | ||
422 | 0, 1, 0), | ||
423 | }; | ||
424 | |||
425 | static const struct snd_kcontrol_new right_boost_mixer[] = { | ||
426 | SOC_DAPM_SINGLE_TLV("R2 Volume", WM8983_RIGHT_ADC_BOOST_CTRL, | ||
427 | 4, 7, 0, boost_tlv), | ||
428 | SOC_DAPM_SINGLE_TLV("AUXR Volume", WM8983_RIGHT_ADC_BOOST_CTRL, | ||
429 | 0, 7, 0, boost_tlv) | ||
430 | }; | ||
431 | |||
432 | static const struct snd_soc_dapm_widget wm8983_dapm_widgets[] = { | ||
433 | SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8983_POWER_MANAGEMENT_3, | ||
434 | 0, 0), | ||
435 | SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8983_POWER_MANAGEMENT_3, | ||
436 | 1, 0), | ||
437 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8983_POWER_MANAGEMENT_2, | ||
438 | 0, 0), | ||
439 | SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8983_POWER_MANAGEMENT_2, | ||
440 | 1, 0), | ||
441 | |||
442 | SND_SOC_DAPM_MIXER("Left Output Mixer", WM8983_POWER_MANAGEMENT_3, | ||
443 | 2, 0, left_out_mixer, ARRAY_SIZE(left_out_mixer)), | ||
444 | SND_SOC_DAPM_MIXER("Right Output Mixer", WM8983_POWER_MANAGEMENT_3, | ||
445 | 3, 0, right_out_mixer, ARRAY_SIZE(right_out_mixer)), | ||
446 | |||
447 | SND_SOC_DAPM_MIXER("Left Input Mixer", WM8983_POWER_MANAGEMENT_2, | ||
448 | 2, 0, left_input_mixer, ARRAY_SIZE(left_input_mixer)), | ||
449 | SND_SOC_DAPM_MIXER("Right Input Mixer", WM8983_POWER_MANAGEMENT_2, | ||
450 | 3, 0, right_input_mixer, ARRAY_SIZE(right_input_mixer)), | ||
451 | |||
452 | SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8983_POWER_MANAGEMENT_2, | ||
453 | 4, 0, left_boost_mixer, ARRAY_SIZE(left_boost_mixer)), | ||
454 | SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8983_POWER_MANAGEMENT_2, | ||
455 | 5, 0, right_boost_mixer, ARRAY_SIZE(right_boost_mixer)), | ||
456 | |||
457 | SND_SOC_DAPM_MIXER("OUT3 Mixer", WM8983_POWER_MANAGEMENT_1, | ||
458 | 6, 0, out3_mixer, ARRAY_SIZE(out3_mixer)), | ||
459 | |||
460 | SND_SOC_DAPM_MIXER("OUT4 Mixer", WM8983_POWER_MANAGEMENT_1, | ||
461 | 7, 0, out4_mixer, ARRAY_SIZE(out4_mixer)), | ||
462 | |||
463 | SND_SOC_DAPM_PGA("Left Capture PGA", WM8983_LEFT_INP_PGA_GAIN_CTRL, | ||
464 | 6, 1, NULL, 0), | ||
465 | SND_SOC_DAPM_PGA("Right Capture PGA", WM8983_RIGHT_INP_PGA_GAIN_CTRL, | ||
466 | 6, 1, NULL, 0), | ||
467 | |||
468 | SND_SOC_DAPM_PGA("Left Headphone Out", WM8983_POWER_MANAGEMENT_2, | ||
469 | 7, 0, NULL, 0), | ||
470 | SND_SOC_DAPM_PGA("Right Headphone Out", WM8983_POWER_MANAGEMENT_2, | ||
471 | 8, 0, NULL, 0), | ||
472 | |||
473 | SND_SOC_DAPM_PGA("Left Speaker Out", WM8983_POWER_MANAGEMENT_3, | ||
474 | 5, 0, NULL, 0), | ||
475 | SND_SOC_DAPM_PGA("Right Speaker Out", WM8983_POWER_MANAGEMENT_3, | ||
476 | 6, 0, NULL, 0), | ||
477 | |||
478 | SND_SOC_DAPM_PGA("OUT3 Out", WM8983_POWER_MANAGEMENT_3, | ||
479 | 7, 0, NULL, 0), | ||
480 | |||
481 | SND_SOC_DAPM_PGA("OUT4 Out", WM8983_POWER_MANAGEMENT_3, | ||
482 | 8, 0, NULL, 0), | ||
483 | |||
484 | SND_SOC_DAPM_MICBIAS("Mic Bias", WM8983_POWER_MANAGEMENT_1, 4, 0), | ||
485 | |||
486 | SND_SOC_DAPM_INPUT("LIN"), | ||
487 | SND_SOC_DAPM_INPUT("LIP"), | ||
488 | SND_SOC_DAPM_INPUT("RIN"), | ||
489 | SND_SOC_DAPM_INPUT("RIP"), | ||
490 | SND_SOC_DAPM_INPUT("AUXL"), | ||
491 | SND_SOC_DAPM_INPUT("AUXR"), | ||
492 | SND_SOC_DAPM_INPUT("L2"), | ||
493 | SND_SOC_DAPM_INPUT("R2"), | ||
494 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
495 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
496 | SND_SOC_DAPM_OUTPUT("SPKL"), | ||
497 | SND_SOC_DAPM_OUTPUT("SPKR"), | ||
498 | SND_SOC_DAPM_OUTPUT("OUT3"), | ||
499 | SND_SOC_DAPM_OUTPUT("OUT4") | ||
500 | }; | ||
501 | |||
502 | static const struct snd_soc_dapm_route wm8983_audio_map[] = { | ||
503 | { "OUT3 Mixer", "LMIX2OUT3 Switch", "Left Output Mixer" }, | ||
504 | { "OUT3 Mixer", "LDAC2OUT3 Switch", "Left DAC" }, | ||
505 | |||
506 | { "OUT3 Out", NULL, "OUT3 Mixer" }, | ||
507 | { "OUT3", NULL, "OUT3 Out" }, | ||
508 | |||
509 | { "OUT4 Mixer", "LMIX2OUT4 Switch", "Left Output Mixer" }, | ||
510 | { "OUT4 Mixer", "RMIX2OUT4 Switch", "Right Output Mixer" }, | ||
511 | { "OUT4 Mixer", "LDAC2OUT4 Switch", "Left DAC" }, | ||
512 | { "OUT4 Mixer", "RDAC2OUT4 Switch", "Right DAC" }, | ||
513 | |||
514 | { "OUT4 Out", NULL, "OUT4 Mixer" }, | ||
515 | { "OUT4", NULL, "OUT4 Out" }, | ||
516 | |||
517 | { "Right Output Mixer", "PCM Switch", "Right DAC" }, | ||
518 | { "Right Output Mixer", "Aux Switch", "AUXR" }, | ||
519 | { "Right Output Mixer", "Line Switch", "Right Boost Mixer" }, | ||
520 | |||
521 | { "Left Output Mixer", "PCM Switch", "Left DAC" }, | ||
522 | { "Left Output Mixer", "Aux Switch", "AUXL" }, | ||
523 | { "Left Output Mixer", "Line Switch", "Left Boost Mixer" }, | ||
524 | |||
525 | { "Right Headphone Out", NULL, "Right Output Mixer" }, | ||
526 | { "HPR", NULL, "Right Headphone Out" }, | ||
527 | |||
528 | { "Left Headphone Out", NULL, "Left Output Mixer" }, | ||
529 | { "HPL", NULL, "Left Headphone Out" }, | ||
530 | |||
531 | { "Right Speaker Out", NULL, "Right Output Mixer" }, | ||
532 | { "SPKR", NULL, "Right Speaker Out" }, | ||
533 | |||
534 | { "Left Speaker Out", NULL, "Left Output Mixer" }, | ||
535 | { "SPKL", NULL, "Left Speaker Out" }, | ||
536 | |||
537 | { "Right ADC", NULL, "Right Boost Mixer" }, | ||
538 | |||
539 | { "Right Boost Mixer", "AUXR Volume", "AUXR" }, | ||
540 | { "Right Boost Mixer", NULL, "Right Capture PGA" }, | ||
541 | { "Right Boost Mixer", "R2 Volume", "R2" }, | ||
542 | |||
543 | { "Left ADC", NULL, "Left Boost Mixer" }, | ||
544 | |||
545 | { "Left Boost Mixer", "AUXL Volume", "AUXL" }, | ||
546 | { "Left Boost Mixer", NULL, "Left Capture PGA" }, | ||
547 | { "Left Boost Mixer", "L2 Volume", "L2" }, | ||
548 | |||
549 | { "Right Capture PGA", NULL, "Right Input Mixer" }, | ||
550 | { "Left Capture PGA", NULL, "Left Input Mixer" }, | ||
551 | |||
552 | { "Right Input Mixer", "R2 Switch", "R2" }, | ||
553 | { "Right Input Mixer", "MicN Switch", "RIN" }, | ||
554 | { "Right Input Mixer", "MicP Switch", "RIP" }, | ||
555 | |||
556 | { "Left Input Mixer", "L2 Switch", "L2" }, | ||
557 | { "Left Input Mixer", "MicN Switch", "LIN" }, | ||
558 | { "Left Input Mixer", "MicP Switch", "LIP" }, | ||
559 | }; | ||
560 | |||
561 | static int eqmode_get(struct snd_kcontrol *kcontrol, | ||
562 | struct snd_ctl_elem_value *ucontrol) | ||
563 | { | ||
564 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
565 | unsigned int reg; | ||
566 | |||
567 | reg = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF); | ||
568 | if (reg & WM8983_EQ3DMODE) | ||
569 | ucontrol->value.integer.value[0] = 1; | ||
570 | else | ||
571 | ucontrol->value.integer.value[0] = 0; | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | static int eqmode_put(struct snd_kcontrol *kcontrol, | ||
577 | struct snd_ctl_elem_value *ucontrol) | ||
578 | { | ||
579 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
580 | unsigned int regpwr2, regpwr3; | ||
581 | unsigned int reg_eq; | ||
582 | |||
583 | if (ucontrol->value.integer.value[0] != 0 | ||
584 | && ucontrol->value.integer.value[0] != 1) | ||
585 | return -EINVAL; | ||
586 | |||
587 | reg_eq = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF); | ||
588 | switch ((reg_eq & WM8983_EQ3DMODE) >> WM8983_EQ3DMODE_SHIFT) { | ||
589 | case 0: | ||
590 | if (!ucontrol->value.integer.value[0]) | ||
591 | return 0; | ||
592 | break; | ||
593 | case 1: | ||
594 | if (ucontrol->value.integer.value[0]) | ||
595 | return 0; | ||
596 | break; | ||
597 | } | ||
598 | |||
599 | regpwr2 = snd_soc_read(codec, WM8983_POWER_MANAGEMENT_2); | ||
600 | regpwr3 = snd_soc_read(codec, WM8983_POWER_MANAGEMENT_3); | ||
601 | /* disable the DACs and ADCs */ | ||
602 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_2, | ||
603 | WM8983_ADCENR_MASK | WM8983_ADCENL_MASK, 0); | ||
604 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_3, | ||
605 | WM8983_DACENR_MASK | WM8983_DACENL_MASK, 0); | ||
606 | /* set the desired eqmode */ | ||
607 | snd_soc_update_bits(codec, WM8983_EQ1_LOW_SHELF, | ||
608 | WM8983_EQ3DMODE_MASK, | ||
609 | ucontrol->value.integer.value[0] | ||
610 | << WM8983_EQ3DMODE_SHIFT); | ||
611 | /* restore DAC/ADC configuration */ | ||
612 | snd_soc_write(codec, WM8983_POWER_MANAGEMENT_2, regpwr2); | ||
613 | snd_soc_write(codec, WM8983_POWER_MANAGEMENT_3, regpwr3); | ||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | static int wm8983_readable(struct snd_soc_codec *codec, unsigned int reg) | ||
618 | { | ||
619 | if (reg > WM8983_MAX_REGISTER) | ||
620 | return 0; | ||
621 | |||
622 | return wm8983_access_masks[reg].read != 0; | ||
623 | } | ||
624 | |||
625 | static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute) | ||
626 | { | ||
627 | struct snd_soc_codec *codec = dai->codec; | ||
628 | |||
629 | return snd_soc_update_bits(codec, WM8983_DAC_CONTROL, | ||
630 | WM8983_SOFTMUTE_MASK, | ||
631 | !!mute << WM8983_SOFTMUTE_SHIFT); | ||
632 | } | ||
633 | |||
634 | static int wm8983_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
635 | { | ||
636 | struct snd_soc_codec *codec = dai->codec; | ||
637 | u16 format, master, bcp, lrp; | ||
638 | |||
639 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
640 | case SND_SOC_DAIFMT_I2S: | ||
641 | format = 0x2; | ||
642 | break; | ||
643 | case SND_SOC_DAIFMT_RIGHT_J: | ||
644 | format = 0x0; | ||
645 | break; | ||
646 | case SND_SOC_DAIFMT_LEFT_J: | ||
647 | format = 0x1; | ||
648 | break; | ||
649 | case SND_SOC_DAIFMT_DSP_A: | ||
650 | case SND_SOC_DAIFMT_DSP_B: | ||
651 | format = 0x3; | ||
652 | break; | ||
653 | default: | ||
654 | dev_err(dai->dev, "Unknown dai format\n"); | ||
655 | return -EINVAL; | ||
656 | } | ||
657 | |||
658 | snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE, | ||
659 | WM8983_FMT_MASK, format << WM8983_FMT_SHIFT); | ||
660 | |||
661 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
662 | case SND_SOC_DAIFMT_CBM_CFM: | ||
663 | master = 1; | ||
664 | break; | ||
665 | case SND_SOC_DAIFMT_CBS_CFS: | ||
666 | master = 0; | ||
667 | break; | ||
668 | default: | ||
669 | dev_err(dai->dev, "Unknown master/slave configuration\n"); | ||
670 | return -EINVAL; | ||
671 | } | ||
672 | |||
673 | snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, | ||
674 | WM8983_MS_MASK, master << WM8983_MS_SHIFT); | ||
675 | |||
676 | /* FIXME: We don't currently support DSP A/B modes */ | ||
677 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
678 | case SND_SOC_DAIFMT_DSP_A: | ||
679 | case SND_SOC_DAIFMT_DSP_B: | ||
680 | dev_err(dai->dev, "DSP A/B modes are not supported\n"); | ||
681 | return -EINVAL; | ||
682 | default: | ||
683 | break; | ||
684 | } | ||
685 | |||
686 | bcp = lrp = 0; | ||
687 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
688 | case SND_SOC_DAIFMT_NB_NF: | ||
689 | break; | ||
690 | case SND_SOC_DAIFMT_IB_IF: | ||
691 | bcp = lrp = 1; | ||
692 | break; | ||
693 | case SND_SOC_DAIFMT_IB_NF: | ||
694 | bcp = 1; | ||
695 | break; | ||
696 | case SND_SOC_DAIFMT_NB_IF: | ||
697 | lrp = 1; | ||
698 | break; | ||
699 | default: | ||
700 | dev_err(dai->dev, "Unknown polarity configuration\n"); | ||
701 | return -EINVAL; | ||
702 | } | ||
703 | |||
704 | snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE, | ||
705 | WM8983_LRCP_MASK, lrp << WM8983_LRCP_SHIFT); | ||
706 | snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE, | ||
707 | WM8983_BCP_MASK, bcp << WM8983_BCP_SHIFT); | ||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | static int wm8983_hw_params(struct snd_pcm_substream *substream, | ||
712 | struct snd_pcm_hw_params *params, | ||
713 | struct snd_soc_dai *dai) | ||
714 | { | ||
715 | int i; | ||
716 | struct snd_soc_codec *codec = dai->codec; | ||
717 | struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); | ||
718 | u16 blen, srate_idx; | ||
719 | u32 tmp; | ||
720 | int srate_best; | ||
721 | int ret; | ||
722 | |||
723 | ret = snd_soc_params_to_bclk(params); | ||
724 | if (ret < 0) { | ||
725 | dev_err(codec->dev, "Failed to convert params to bclk: %d\n", ret); | ||
726 | return ret; | ||
727 | } | ||
728 | |||
729 | wm8983->bclk = ret; | ||
730 | |||
731 | switch (params_format(params)) { | ||
732 | case SNDRV_PCM_FORMAT_S16_LE: | ||
733 | blen = 0x0; | ||
734 | break; | ||
735 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
736 | blen = 0x1; | ||
737 | break; | ||
738 | case SNDRV_PCM_FORMAT_S24_LE: | ||
739 | blen = 0x2; | ||
740 | break; | ||
741 | case SNDRV_PCM_FORMAT_S32_LE: | ||
742 | blen = 0x3; | ||
743 | break; | ||
744 | default: | ||
745 | dev_err(dai->dev, "Unsupported word length %u\n", | ||
746 | params_format(params)); | ||
747 | return -EINVAL; | ||
748 | } | ||
749 | |||
750 | snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE, | ||
751 | WM8983_WL_MASK, blen << WM8983_WL_SHIFT); | ||
752 | |||
753 | /* | ||
754 | * match to the nearest possible sample rate and rely | ||
755 | * on the array index to configure the SR register | ||
756 | */ | ||
757 | srate_idx = 0; | ||
758 | srate_best = abs(srates[0] - params_rate(params)); | ||
759 | for (i = 1; i < ARRAY_SIZE(srates); ++i) { | ||
760 | if (abs(srates[i] - params_rate(params)) >= srate_best) | ||
761 | continue; | ||
762 | srate_idx = i; | ||
763 | srate_best = abs(srates[i] - params_rate(params)); | ||
764 | } | ||
765 | |||
766 | dev_dbg(dai->dev, "Selected SRATE = %d\n", srates[srate_idx]); | ||
767 | snd_soc_update_bits(codec, WM8983_ADDITIONAL_CONTROL, | ||
768 | WM8983_SR_MASK, srate_idx << WM8983_SR_SHIFT); | ||
769 | |||
770 | dev_dbg(dai->dev, "Target BCLK = %uHz\n", wm8983->bclk); | ||
771 | dev_dbg(dai->dev, "SYSCLK = %uHz\n", wm8983->sysclk); | ||
772 | |||
773 | for (i = 0; i < ARRAY_SIZE(fs_ratios); ++i) { | ||
774 | if (wm8983->sysclk / params_rate(params) | ||
775 | == fs_ratios[i].ratio) | ||
776 | break; | ||
777 | } | ||
778 | |||
779 | if (i == ARRAY_SIZE(fs_ratios)) { | ||
780 | dev_err(dai->dev, "Unable to configure MCLK ratio %u/%u\n", | ||
781 | wm8983->sysclk, params_rate(params)); | ||
782 | return -EINVAL; | ||
783 | } | ||
784 | |||
785 | dev_dbg(dai->dev, "MCLK ratio = %dfs\n", fs_ratios[i].ratio); | ||
786 | snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, | ||
787 | WM8983_MCLKDIV_MASK, i << WM8983_MCLKDIV_SHIFT); | ||
788 | |||
789 | /* select the appropriate bclk divider */ | ||
790 | tmp = (wm8983->sysclk / fs_ratios[i].div) * 10; | ||
791 | for (i = 0; i < ARRAY_SIZE(bclk_divs); ++i) { | ||
792 | if (wm8983->bclk == tmp / bclk_divs[i]) | ||
793 | break; | ||
794 | } | ||
795 | |||
796 | if (i == ARRAY_SIZE(bclk_divs)) { | ||
797 | dev_err(dai->dev, "No matching BCLK divider found\n"); | ||
798 | return -EINVAL; | ||
799 | } | ||
800 | |||
801 | dev_dbg(dai->dev, "BCLK div = %d\n", i); | ||
802 | snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, | ||
803 | WM8983_BCLKDIV_MASK, i << WM8983_BCLKDIV_SHIFT); | ||
804 | |||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | struct pll_div { | ||
809 | u32 div2:1; | ||
810 | u32 n:4; | ||
811 | u32 k:24; | ||
812 | }; | ||
813 | |||
814 | #define FIXED_PLL_SIZE ((1ULL << 24) * 10) | ||
815 | static int pll_factors(struct pll_div *pll_div, unsigned int target, | ||
816 | unsigned int source) | ||
817 | { | ||
818 | u64 Kpart; | ||
819 | unsigned long int K, Ndiv, Nmod; | ||
820 | |||
821 | pll_div->div2 = 0; | ||
822 | Ndiv = target / source; | ||
823 | if (Ndiv < 6) { | ||
824 | source >>= 1; | ||
825 | pll_div->div2 = 1; | ||
826 | Ndiv = target / source; | ||
827 | } | ||
828 | |||
829 | if (Ndiv < 6 || Ndiv > 12) { | ||
830 | printk(KERN_ERR "%s: WM8983 N value is not within" | ||
831 | " the recommended range: %lu\n", __func__, Ndiv); | ||
832 | return -EINVAL; | ||
833 | } | ||
834 | pll_div->n = Ndiv; | ||
835 | |||
836 | Nmod = target % source; | ||
837 | Kpart = FIXED_PLL_SIZE * (u64)Nmod; | ||
838 | |||
839 | do_div(Kpart, source); | ||
840 | |||
841 | K = Kpart & 0xffffffff; | ||
842 | if ((K % 10) >= 5) | ||
843 | K += 5; | ||
844 | K /= 10; | ||
845 | pll_div->k = K; | ||
846 | return 0; | ||
847 | } | ||
848 | |||
849 | static int wm8983_set_pll(struct snd_soc_dai *dai, int pll_id, | ||
850 | int source, unsigned int freq_in, | ||
851 | unsigned int freq_out) | ||
852 | { | ||
853 | int ret; | ||
854 | struct snd_soc_codec *codec; | ||
855 | struct pll_div pll_div; | ||
856 | |||
857 | codec = dai->codec; | ||
858 | if (freq_in && freq_out) { | ||
859 | ret = pll_factors(&pll_div, freq_out * 4 * 2, freq_in); | ||
860 | if (ret) | ||
861 | return ret; | ||
862 | } | ||
863 | |||
864 | /* disable the PLL before re-programming it */ | ||
865 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
866 | WM8983_PLLEN_MASK, 0); | ||
867 | |||
868 | if (!freq_in || !freq_out) | ||
869 | return 0; | ||
870 | |||
871 | /* set PLLN and PRESCALE */ | ||
872 | snd_soc_write(codec, WM8983_PLL_N, | ||
873 | (pll_div.div2 << WM8983_PLL_PRESCALE_SHIFT) | ||
874 | | pll_div.n); | ||
875 | /* set PLLK */ | ||
876 | snd_soc_write(codec, WM8983_PLL_K_3, pll_div.k & 0x1ff); | ||
877 | snd_soc_write(codec, WM8983_PLL_K_2, (pll_div.k >> 9) & 0x1ff); | ||
878 | snd_soc_write(codec, WM8983_PLL_K_1, (pll_div.k >> 18)); | ||
879 | /* enable the PLL */ | ||
880 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
881 | WM8983_PLLEN_MASK, WM8983_PLLEN); | ||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | static int wm8983_set_sysclk(struct snd_soc_dai *dai, | ||
886 | int clk_id, unsigned int freq, int dir) | ||
887 | { | ||
888 | struct snd_soc_codec *codec = dai->codec; | ||
889 | struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); | ||
890 | |||
891 | switch (clk_id) { | ||
892 | case WM8983_CLKSRC_MCLK: | ||
893 | snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, | ||
894 | WM8983_CLKSEL_MASK, 0); | ||
895 | break; | ||
896 | case WM8983_CLKSRC_PLL: | ||
897 | snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, | ||
898 | WM8983_CLKSEL_MASK, WM8983_CLKSEL); | ||
899 | break; | ||
900 | default: | ||
901 | dev_err(dai->dev, "Unknown clock source: %d\n", clk_id); | ||
902 | return -EINVAL; | ||
903 | } | ||
904 | |||
905 | wm8983->sysclk = freq; | ||
906 | return 0; | ||
907 | } | ||
908 | |||
909 | static int wm8983_set_bias_level(struct snd_soc_codec *codec, | ||
910 | enum snd_soc_bias_level level) | ||
911 | { | ||
912 | int ret; | ||
913 | |||
914 | switch (level) { | ||
915 | case SND_SOC_BIAS_ON: | ||
916 | case SND_SOC_BIAS_PREPARE: | ||
917 | /* VMID at 100k */ | ||
918 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
919 | WM8983_VMIDSEL_MASK, | ||
920 | 1 << WM8983_VMIDSEL_SHIFT); | ||
921 | break; | ||
922 | case SND_SOC_BIAS_STANDBY: | ||
923 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
924 | ret = snd_soc_cache_sync(codec); | ||
925 | if (ret < 0) { | ||
926 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); | ||
927 | return ret; | ||
928 | } | ||
929 | /* enable anti-pop features */ | ||
930 | snd_soc_update_bits(codec, WM8983_OUT4_TO_ADC, | ||
931 | WM8983_POBCTRL_MASK | WM8983_DELEN_MASK, | ||
932 | WM8983_POBCTRL | WM8983_DELEN); | ||
933 | /* enable thermal shutdown */ | ||
934 | snd_soc_update_bits(codec, WM8983_OUTPUT_CTRL, | ||
935 | WM8983_TSDEN_MASK, WM8983_TSDEN); | ||
936 | /* enable BIASEN */ | ||
937 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
938 | WM8983_BIASEN_MASK, WM8983_BIASEN); | ||
939 | /* VMID at 100k */ | ||
940 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
941 | WM8983_VMIDSEL_MASK, | ||
942 | 1 << WM8983_VMIDSEL_SHIFT); | ||
943 | msleep(250); | ||
944 | /* disable anti-pop features */ | ||
945 | snd_soc_update_bits(codec, WM8983_OUT4_TO_ADC, | ||
946 | WM8983_POBCTRL_MASK | | ||
947 | WM8983_DELEN_MASK, 0); | ||
948 | } | ||
949 | |||
950 | /* VMID at 500k */ | ||
951 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
952 | WM8983_VMIDSEL_MASK, | ||
953 | 2 << WM8983_VMIDSEL_SHIFT); | ||
954 | break; | ||
955 | case SND_SOC_BIAS_OFF: | ||
956 | /* disable thermal shutdown */ | ||
957 | snd_soc_update_bits(codec, WM8983_OUTPUT_CTRL, | ||
958 | WM8983_TSDEN_MASK, 0); | ||
959 | /* disable VMIDSEL and BIASEN */ | ||
960 | snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, | ||
961 | WM8983_VMIDSEL_MASK | WM8983_BIASEN_MASK, | ||
962 | 0); | ||
963 | /* wait for VMID to discharge */ | ||
964 | msleep(100); | ||
965 | snd_soc_write(codec, WM8983_POWER_MANAGEMENT_1, 0); | ||
966 | snd_soc_write(codec, WM8983_POWER_MANAGEMENT_2, 0); | ||
967 | snd_soc_write(codec, WM8983_POWER_MANAGEMENT_3, 0); | ||
968 | break; | ||
969 | } | ||
970 | |||
971 | codec->dapm.bias_level = level; | ||
972 | return 0; | ||
973 | } | ||
974 | |||
975 | #ifdef CONFIG_PM | ||
976 | static int wm8983_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
977 | { | ||
978 | wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
979 | return 0; | ||
980 | } | ||
981 | |||
982 | static int wm8983_resume(struct snd_soc_codec *codec) | ||
983 | { | ||
984 | wm8983_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
985 | return 0; | ||
986 | } | ||
987 | #else | ||
988 | #define wm8983_suspend NULL | ||
989 | #define wm8983_resume NULL | ||
990 | #endif | ||
991 | |||
992 | static int wm8983_remove(struct snd_soc_codec *codec) | ||
993 | { | ||
994 | wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
995 | return 0; | ||
996 | } | ||
997 | |||
998 | static int wm8983_probe(struct snd_soc_codec *codec) | ||
999 | { | ||
1000 | int ret; | ||
1001 | struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); | ||
1002 | int i; | ||
1003 | |||
1004 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8983->control_type); | ||
1005 | if (ret < 0) { | ||
1006 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | ||
1007 | return ret; | ||
1008 | } | ||
1009 | |||
1010 | ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0x8983); | ||
1011 | if (ret < 0) { | ||
1012 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | ||
1013 | return ret; | ||
1014 | } | ||
1015 | |||
1016 | /* set the vol/gain update bits */ | ||
1017 | for (i = 0; i < ARRAY_SIZE(vol_update_regs); ++i) | ||
1018 | snd_soc_update_bits(codec, vol_update_regs[i], | ||
1019 | 0x100, 0x100); | ||
1020 | |||
1021 | /* mute all outputs and set PGAs to minimum gain */ | ||
1022 | for (i = WM8983_LOUT1_HP_VOLUME_CTRL; | ||
1023 | i <= WM8983_OUT4_MONO_MIX_CTRL; ++i) | ||
1024 | snd_soc_update_bits(codec, i, 0x40, 0x40); | ||
1025 | |||
1026 | /* enable soft mute */ | ||
1027 | snd_soc_update_bits(codec, WM8983_DAC_CONTROL, | ||
1028 | WM8983_SOFTMUTE_MASK, | ||
1029 | WM8983_SOFTMUTE); | ||
1030 | |||
1031 | /* enable BIASCUT */ | ||
1032 | snd_soc_update_bits(codec, WM8983_BIAS_CTRL, | ||
1033 | WM8983_BIASCUT, WM8983_BIASCUT); | ||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | static struct snd_soc_dai_ops wm8983_dai_ops = { | ||
1038 | .digital_mute = wm8983_dac_mute, | ||
1039 | .hw_params = wm8983_hw_params, | ||
1040 | .set_fmt = wm8983_set_fmt, | ||
1041 | .set_sysclk = wm8983_set_sysclk, | ||
1042 | .set_pll = wm8983_set_pll | ||
1043 | }; | ||
1044 | |||
1045 | #define WM8983_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
1046 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
1047 | |||
1048 | static struct snd_soc_dai_driver wm8983_dai = { | ||
1049 | .name = "wm8983-hifi", | ||
1050 | .playback = { | ||
1051 | .stream_name = "Playback", | ||
1052 | .channels_min = 2, | ||
1053 | .channels_max = 2, | ||
1054 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1055 | .formats = WM8983_FORMATS, | ||
1056 | }, | ||
1057 | .capture = { | ||
1058 | .stream_name = "Capture", | ||
1059 | .channels_min = 2, | ||
1060 | .channels_max = 2, | ||
1061 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1062 | .formats = WM8983_FORMATS, | ||
1063 | }, | ||
1064 | .ops = &wm8983_dai_ops, | ||
1065 | .symmetric_rates = 1 | ||
1066 | }; | ||
1067 | |||
1068 | static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { | ||
1069 | .probe = wm8983_probe, | ||
1070 | .remove = wm8983_remove, | ||
1071 | .suspend = wm8983_suspend, | ||
1072 | .resume = wm8983_resume, | ||
1073 | .set_bias_level = wm8983_set_bias_level, | ||
1074 | .reg_cache_size = ARRAY_SIZE(wm8983_reg_defs), | ||
1075 | .reg_word_size = sizeof(u16), | ||
1076 | .reg_cache_default = wm8983_reg_defs, | ||
1077 | .controls = wm8983_snd_controls, | ||
1078 | .num_controls = ARRAY_SIZE(wm8983_snd_controls), | ||
1079 | .dapm_widgets = wm8983_dapm_widgets, | ||
1080 | .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), | ||
1081 | .dapm_routes = wm8983_audio_map, | ||
1082 | .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), | ||
1083 | .readable_register = wm8983_readable | ||
1084 | }; | ||
1085 | |||
1086 | #if defined(CONFIG_SPI_MASTER) | ||
1087 | static int __devinit wm8983_spi_probe(struct spi_device *spi) | ||
1088 | { | ||
1089 | struct wm8983_priv *wm8983; | ||
1090 | int ret; | ||
1091 | |||
1092 | wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); | ||
1093 | if (!wm8983) | ||
1094 | return -ENOMEM; | ||
1095 | |||
1096 | wm8983->control_type = SND_SOC_SPI; | ||
1097 | spi_set_drvdata(spi, wm8983); | ||
1098 | |||
1099 | ret = snd_soc_register_codec(&spi->dev, | ||
1100 | &soc_codec_dev_wm8983, &wm8983_dai, 1); | ||
1101 | if (ret < 0) | ||
1102 | kfree(wm8983); | ||
1103 | return ret; | ||
1104 | } | ||
1105 | |||
1106 | static int __devexit wm8983_spi_remove(struct spi_device *spi) | ||
1107 | { | ||
1108 | snd_soc_unregister_codec(&spi->dev); | ||
1109 | kfree(spi_get_drvdata(spi)); | ||
1110 | return 0; | ||
1111 | } | ||
1112 | |||
1113 | static struct spi_driver wm8983_spi_driver = { | ||
1114 | .driver = { | ||
1115 | .name = "wm8983", | ||
1116 | .owner = THIS_MODULE, | ||
1117 | }, | ||
1118 | .probe = wm8983_spi_probe, | ||
1119 | .remove = __devexit_p(wm8983_spi_remove) | ||
1120 | }; | ||
1121 | #endif | ||
1122 | |||
1123 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1124 | static __devinit int wm8983_i2c_probe(struct i2c_client *i2c, | ||
1125 | const struct i2c_device_id *id) | ||
1126 | { | ||
1127 | struct wm8983_priv *wm8983; | ||
1128 | int ret; | ||
1129 | |||
1130 | wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); | ||
1131 | if (!wm8983) | ||
1132 | return -ENOMEM; | ||
1133 | |||
1134 | wm8983->control_type = SND_SOC_I2C; | ||
1135 | i2c_set_clientdata(i2c, wm8983); | ||
1136 | |||
1137 | ret = snd_soc_register_codec(&i2c->dev, | ||
1138 | &soc_codec_dev_wm8983, &wm8983_dai, 1); | ||
1139 | if (ret < 0) | ||
1140 | kfree(wm8983); | ||
1141 | return ret; | ||
1142 | } | ||
1143 | |||
1144 | static __devexit int wm8983_i2c_remove(struct i2c_client *client) | ||
1145 | { | ||
1146 | snd_soc_unregister_codec(&client->dev); | ||
1147 | kfree(i2c_get_clientdata(client)); | ||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | static const struct i2c_device_id wm8983_i2c_id[] = { | ||
1152 | { "wm8983", 0 }, | ||
1153 | { } | ||
1154 | }; | ||
1155 | MODULE_DEVICE_TABLE(i2c, wm8983_i2c_id); | ||
1156 | |||
1157 | static struct i2c_driver wm8983_i2c_driver = { | ||
1158 | .driver = { | ||
1159 | .name = "wm8983", | ||
1160 | .owner = THIS_MODULE, | ||
1161 | }, | ||
1162 | .probe = wm8983_i2c_probe, | ||
1163 | .remove = __devexit_p(wm8983_i2c_remove), | ||
1164 | .id_table = wm8983_i2c_id | ||
1165 | }; | ||
1166 | #endif | ||
1167 | |||
1168 | static int __init wm8983_modinit(void) | ||
1169 | { | ||
1170 | int ret = 0; | ||
1171 | |||
1172 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1173 | ret = i2c_add_driver(&wm8983_i2c_driver); | ||
1174 | if (ret) { | ||
1175 | printk(KERN_ERR "Failed to register wm8983 I2C driver: %d\n", | ||
1176 | ret); | ||
1177 | } | ||
1178 | #endif | ||
1179 | #if defined(CONFIG_SPI_MASTER) | ||
1180 | ret = spi_register_driver(&wm8983_spi_driver); | ||
1181 | if (ret != 0) { | ||
1182 | printk(KERN_ERR "Failed to register wm8983 SPI driver: %d\n", | ||
1183 | ret); | ||
1184 | } | ||
1185 | #endif | ||
1186 | return ret; | ||
1187 | } | ||
1188 | module_init(wm8983_modinit); | ||
1189 | |||
1190 | static void __exit wm8983_exit(void) | ||
1191 | { | ||
1192 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1193 | i2c_del_driver(&wm8983_i2c_driver); | ||
1194 | #endif | ||
1195 | #if defined(CONFIG_SPI_MASTER) | ||
1196 | spi_unregister_driver(&wm8983_spi_driver); | ||
1197 | #endif | ||
1198 | } | ||
1199 | module_exit(wm8983_exit); | ||
1200 | |||
1201 | MODULE_DESCRIPTION("ASoC WM8983 driver"); | ||
1202 | MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>"); | ||
1203 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8983.h b/sound/soc/codecs/wm8983.h new file mode 100644 index 000000000000..71ee619c2742 --- /dev/null +++ b/sound/soc/codecs/wm8983.h | |||
@@ -0,0 +1,1029 @@ | |||
1 | /* | ||
2 | * wm8983.h -- WM8983 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2011 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef _WM8983_H | ||
14 | #define _WM8983_H | ||
15 | |||
16 | /* | ||
17 | * Register values. | ||
18 | */ | ||
19 | #define WM8983_SOFTWARE_RESET 0x00 | ||
20 | #define WM8983_POWER_MANAGEMENT_1 0x01 | ||
21 | #define WM8983_POWER_MANAGEMENT_2 0x02 | ||
22 | #define WM8983_POWER_MANAGEMENT_3 0x03 | ||
23 | #define WM8983_AUDIO_INTERFACE 0x04 | ||
24 | #define WM8983_COMPANDING_CONTROL 0x05 | ||
25 | #define WM8983_CLOCK_GEN_CONTROL 0x06 | ||
26 | #define WM8983_ADDITIONAL_CONTROL 0x07 | ||
27 | #define WM8983_GPIO_CONTROL 0x08 | ||
28 | #define WM8983_JACK_DETECT_CONTROL_1 0x09 | ||
29 | #define WM8983_DAC_CONTROL 0x0A | ||
30 | #define WM8983_LEFT_DAC_DIGITAL_VOL 0x0B | ||
31 | #define WM8983_RIGHT_DAC_DIGITAL_VOL 0x0C | ||
32 | #define WM8983_JACK_DETECT_CONTROL_2 0x0D | ||
33 | #define WM8983_ADC_CONTROL 0x0E | ||
34 | #define WM8983_LEFT_ADC_DIGITAL_VOL 0x0F | ||
35 | #define WM8983_RIGHT_ADC_DIGITAL_VOL 0x10 | ||
36 | #define WM8983_EQ1_LOW_SHELF 0x12 | ||
37 | #define WM8983_EQ2_PEAK_1 0x13 | ||
38 | #define WM8983_EQ3_PEAK_2 0x14 | ||
39 | #define WM8983_EQ4_PEAK_3 0x15 | ||
40 | #define WM8983_EQ5_HIGH_SHELF 0x16 | ||
41 | #define WM8983_DAC_LIMITER_1 0x18 | ||
42 | #define WM8983_DAC_LIMITER_2 0x19 | ||
43 | #define WM8983_NOTCH_FILTER_1 0x1B | ||
44 | #define WM8983_NOTCH_FILTER_2 0x1C | ||
45 | #define WM8983_NOTCH_FILTER_3 0x1D | ||
46 | #define WM8983_NOTCH_FILTER_4 0x1E | ||
47 | #define WM8983_ALC_CONTROL_1 0x20 | ||
48 | #define WM8983_ALC_CONTROL_2 0x21 | ||
49 | #define WM8983_ALC_CONTROL_3 0x22 | ||
50 | #define WM8983_NOISE_GATE 0x23 | ||
51 | #define WM8983_PLL_N 0x24 | ||
52 | #define WM8983_PLL_K_1 0x25 | ||
53 | #define WM8983_PLL_K_2 0x26 | ||
54 | #define WM8983_PLL_K_3 0x27 | ||
55 | #define WM8983_3D_CONTROL 0x29 | ||
56 | #define WM8983_OUT4_TO_ADC 0x2A | ||
57 | #define WM8983_BEEP_CONTROL 0x2B | ||
58 | #define WM8983_INPUT_CTRL 0x2C | ||
59 | #define WM8983_LEFT_INP_PGA_GAIN_CTRL 0x2D | ||
60 | #define WM8983_RIGHT_INP_PGA_GAIN_CTRL 0x2E | ||
61 | #define WM8983_LEFT_ADC_BOOST_CTRL 0x2F | ||
62 | #define WM8983_RIGHT_ADC_BOOST_CTRL 0x30 | ||
63 | #define WM8983_OUTPUT_CTRL 0x31 | ||
64 | #define WM8983_LEFT_MIXER_CTRL 0x32 | ||
65 | #define WM8983_RIGHT_MIXER_CTRL 0x33 | ||
66 | #define WM8983_LOUT1_HP_VOLUME_CTRL 0x34 | ||
67 | #define WM8983_ROUT1_HP_VOLUME_CTRL 0x35 | ||
68 | #define WM8983_LOUT2_SPK_VOLUME_CTRL 0x36 | ||
69 | #define WM8983_ROUT2_SPK_VOLUME_CTRL 0x37 | ||
70 | #define WM8983_OUT3_MIXER_CTRL 0x38 | ||
71 | #define WM8983_OUT4_MONO_MIX_CTRL 0x39 | ||
72 | #define WM8983_BIAS_CTRL 0x3D | ||
73 | |||
74 | #define WM8983_REGISTER_COUNT 59 | ||
75 | #define WM8983_MAX_REGISTER 0x3F | ||
76 | |||
77 | /* | ||
78 | * Field Definitions. | ||
79 | */ | ||
80 | |||
81 | /* | ||
82 | * R0 (0x00) - Software Reset | ||
83 | */ | ||
84 | #define WM8983_SOFTWARE_RESET_MASK 0x01FF /* SOFTWARE_RESET - [8:0] */ | ||
85 | #define WM8983_SOFTWARE_RESET_SHIFT 0 /* SOFTWARE_RESET - [8:0] */ | ||
86 | #define WM8983_SOFTWARE_RESET_WIDTH 9 /* SOFTWARE_RESET - [8:0] */ | ||
87 | |||
88 | /* | ||
89 | * R1 (0x01) - Power management 1 | ||
90 | */ | ||
91 | #define WM8983_BUFDCOPEN 0x0100 /* BUFDCOPEN */ | ||
92 | #define WM8983_BUFDCOPEN_MASK 0x0100 /* BUFDCOPEN */ | ||
93 | #define WM8983_BUFDCOPEN_SHIFT 8 /* BUFDCOPEN */ | ||
94 | #define WM8983_BUFDCOPEN_WIDTH 1 /* BUFDCOPEN */ | ||
95 | #define WM8983_OUT4MIXEN 0x0080 /* OUT4MIXEN */ | ||
96 | #define WM8983_OUT4MIXEN_MASK 0x0080 /* OUT4MIXEN */ | ||
97 | #define WM8983_OUT4MIXEN_SHIFT 7 /* OUT4MIXEN */ | ||
98 | #define WM8983_OUT4MIXEN_WIDTH 1 /* OUT4MIXEN */ | ||
99 | #define WM8983_OUT3MIXEN 0x0040 /* OUT3MIXEN */ | ||
100 | #define WM8983_OUT3MIXEN_MASK 0x0040 /* OUT3MIXEN */ | ||
101 | #define WM8983_OUT3MIXEN_SHIFT 6 /* OUT3MIXEN */ | ||
102 | #define WM8983_OUT3MIXEN_WIDTH 1 /* OUT3MIXEN */ | ||
103 | #define WM8983_PLLEN 0x0020 /* PLLEN */ | ||
104 | #define WM8983_PLLEN_MASK 0x0020 /* PLLEN */ | ||
105 | #define WM8983_PLLEN_SHIFT 5 /* PLLEN */ | ||
106 | #define WM8983_PLLEN_WIDTH 1 /* PLLEN */ | ||
107 | #define WM8983_MICBEN 0x0010 /* MICBEN */ | ||
108 | #define WM8983_MICBEN_MASK 0x0010 /* MICBEN */ | ||
109 | #define WM8983_MICBEN_SHIFT 4 /* MICBEN */ | ||
110 | #define WM8983_MICBEN_WIDTH 1 /* MICBEN */ | ||
111 | #define WM8983_BIASEN 0x0008 /* BIASEN */ | ||
112 | #define WM8983_BIASEN_MASK 0x0008 /* BIASEN */ | ||
113 | #define WM8983_BIASEN_SHIFT 3 /* BIASEN */ | ||
114 | #define WM8983_BIASEN_WIDTH 1 /* BIASEN */ | ||
115 | #define WM8983_BUFIOEN 0x0004 /* BUFIOEN */ | ||
116 | #define WM8983_BUFIOEN_MASK 0x0004 /* BUFIOEN */ | ||
117 | #define WM8983_BUFIOEN_SHIFT 2 /* BUFIOEN */ | ||
118 | #define WM8983_BUFIOEN_WIDTH 1 /* BUFIOEN */ | ||
119 | #define WM8983_VMIDSEL_MASK 0x0003 /* VMIDSEL - [1:0] */ | ||
120 | #define WM8983_VMIDSEL_SHIFT 0 /* VMIDSEL - [1:0] */ | ||
121 | #define WM8983_VMIDSEL_WIDTH 2 /* VMIDSEL - [1:0] */ | ||
122 | |||
123 | /* | ||
124 | * R2 (0x02) - Power management 2 | ||
125 | */ | ||
126 | #define WM8983_ROUT1EN 0x0100 /* ROUT1EN */ | ||
127 | #define WM8983_ROUT1EN_MASK 0x0100 /* ROUT1EN */ | ||
128 | #define WM8983_ROUT1EN_SHIFT 8 /* ROUT1EN */ | ||
129 | #define WM8983_ROUT1EN_WIDTH 1 /* ROUT1EN */ | ||
130 | #define WM8983_LOUT1EN 0x0080 /* LOUT1EN */ | ||
131 | #define WM8983_LOUT1EN_MASK 0x0080 /* LOUT1EN */ | ||
132 | #define WM8983_LOUT1EN_SHIFT 7 /* LOUT1EN */ | ||
133 | #define WM8983_LOUT1EN_WIDTH 1 /* LOUT1EN */ | ||
134 | #define WM8983_SLEEP 0x0040 /* SLEEP */ | ||
135 | #define WM8983_SLEEP_MASK 0x0040 /* SLEEP */ | ||
136 | #define WM8983_SLEEP_SHIFT 6 /* SLEEP */ | ||
137 | #define WM8983_SLEEP_WIDTH 1 /* SLEEP */ | ||
138 | #define WM8983_BOOSTENR 0x0020 /* BOOSTENR */ | ||
139 | #define WM8983_BOOSTENR_MASK 0x0020 /* BOOSTENR */ | ||
140 | #define WM8983_BOOSTENR_SHIFT 5 /* BOOSTENR */ | ||
141 | #define WM8983_BOOSTENR_WIDTH 1 /* BOOSTENR */ | ||
142 | #define WM8983_BOOSTENL 0x0010 /* BOOSTENL */ | ||
143 | #define WM8983_BOOSTENL_MASK 0x0010 /* BOOSTENL */ | ||
144 | #define WM8983_BOOSTENL_SHIFT 4 /* BOOSTENL */ | ||
145 | #define WM8983_BOOSTENL_WIDTH 1 /* BOOSTENL */ | ||
146 | #define WM8983_INPGAENR 0x0008 /* INPGAENR */ | ||
147 | #define WM8983_INPGAENR_MASK 0x0008 /* INPGAENR */ | ||
148 | #define WM8983_INPGAENR_SHIFT 3 /* INPGAENR */ | ||
149 | #define WM8983_INPGAENR_WIDTH 1 /* INPGAENR */ | ||
150 | #define WM8983_INPPGAENL 0x0004 /* INPPGAENL */ | ||
151 | #define WM8983_INPPGAENL_MASK 0x0004 /* INPPGAENL */ | ||
152 | #define WM8983_INPPGAENL_SHIFT 2 /* INPPGAENL */ | ||
153 | #define WM8983_INPPGAENL_WIDTH 1 /* INPPGAENL */ | ||
154 | #define WM8983_ADCENR 0x0002 /* ADCENR */ | ||
155 | #define WM8983_ADCENR_MASK 0x0002 /* ADCENR */ | ||
156 | #define WM8983_ADCENR_SHIFT 1 /* ADCENR */ | ||
157 | #define WM8983_ADCENR_WIDTH 1 /* ADCENR */ | ||
158 | #define WM8983_ADCENL 0x0001 /* ADCENL */ | ||
159 | #define WM8983_ADCENL_MASK 0x0001 /* ADCENL */ | ||
160 | #define WM8983_ADCENL_SHIFT 0 /* ADCENL */ | ||
161 | #define WM8983_ADCENL_WIDTH 1 /* ADCENL */ | ||
162 | |||
163 | /* | ||
164 | * R3 (0x03) - Power management 3 | ||
165 | */ | ||
166 | #define WM8983_OUT4EN 0x0100 /* OUT4EN */ | ||
167 | #define WM8983_OUT4EN_MASK 0x0100 /* OUT4EN */ | ||
168 | #define WM8983_OUT4EN_SHIFT 8 /* OUT4EN */ | ||
169 | #define WM8983_OUT4EN_WIDTH 1 /* OUT4EN */ | ||
170 | #define WM8983_OUT3EN 0x0080 /* OUT3EN */ | ||
171 | #define WM8983_OUT3EN_MASK 0x0080 /* OUT3EN */ | ||
172 | #define WM8983_OUT3EN_SHIFT 7 /* OUT3EN */ | ||
173 | #define WM8983_OUT3EN_WIDTH 1 /* OUT3EN */ | ||
174 | #define WM8983_LOUT2EN 0x0040 /* LOUT2EN */ | ||
175 | #define WM8983_LOUT2EN_MASK 0x0040 /* LOUT2EN */ | ||
176 | #define WM8983_LOUT2EN_SHIFT 6 /* LOUT2EN */ | ||
177 | #define WM8983_LOUT2EN_WIDTH 1 /* LOUT2EN */ | ||
178 | #define WM8983_ROUT2EN 0x0020 /* ROUT2EN */ | ||
179 | #define WM8983_ROUT2EN_MASK 0x0020 /* ROUT2EN */ | ||
180 | #define WM8983_ROUT2EN_SHIFT 5 /* ROUT2EN */ | ||
181 | #define WM8983_ROUT2EN_WIDTH 1 /* ROUT2EN */ | ||
182 | #define WM8983_RMIXEN 0x0008 /* RMIXEN */ | ||
183 | #define WM8983_RMIXEN_MASK 0x0008 /* RMIXEN */ | ||
184 | #define WM8983_RMIXEN_SHIFT 3 /* RMIXEN */ | ||
185 | #define WM8983_RMIXEN_WIDTH 1 /* RMIXEN */ | ||
186 | #define WM8983_LMIXEN 0x0004 /* LMIXEN */ | ||
187 | #define WM8983_LMIXEN_MASK 0x0004 /* LMIXEN */ | ||
188 | #define WM8983_LMIXEN_SHIFT 2 /* LMIXEN */ | ||
189 | #define WM8983_LMIXEN_WIDTH 1 /* LMIXEN */ | ||
190 | #define WM8983_DACENR 0x0002 /* DACENR */ | ||
191 | #define WM8983_DACENR_MASK 0x0002 /* DACENR */ | ||
192 | #define WM8983_DACENR_SHIFT 1 /* DACENR */ | ||
193 | #define WM8983_DACENR_WIDTH 1 /* DACENR */ | ||
194 | #define WM8983_DACENL 0x0001 /* DACENL */ | ||
195 | #define WM8983_DACENL_MASK 0x0001 /* DACENL */ | ||
196 | #define WM8983_DACENL_SHIFT 0 /* DACENL */ | ||
197 | #define WM8983_DACENL_WIDTH 1 /* DACENL */ | ||
198 | |||
199 | /* | ||
200 | * R4 (0x04) - Audio Interface | ||
201 | */ | ||
202 | #define WM8983_BCP 0x0100 /* BCP */ | ||
203 | #define WM8983_BCP_MASK 0x0100 /* BCP */ | ||
204 | #define WM8983_BCP_SHIFT 8 /* BCP */ | ||
205 | #define WM8983_BCP_WIDTH 1 /* BCP */ | ||
206 | #define WM8983_LRCP 0x0080 /* LRCP */ | ||
207 | #define WM8983_LRCP_MASK 0x0080 /* LRCP */ | ||
208 | #define WM8983_LRCP_SHIFT 7 /* LRCP */ | ||
209 | #define WM8983_LRCP_WIDTH 1 /* LRCP */ | ||
210 | #define WM8983_WL_MASK 0x0060 /* WL - [6:5] */ | ||
211 | #define WM8983_WL_SHIFT 5 /* WL - [6:5] */ | ||
212 | #define WM8983_WL_WIDTH 2 /* WL - [6:5] */ | ||
213 | #define WM8983_FMT_MASK 0x0018 /* FMT - [4:3] */ | ||
214 | #define WM8983_FMT_SHIFT 3 /* FMT - [4:3] */ | ||
215 | #define WM8983_FMT_WIDTH 2 /* FMT - [4:3] */ | ||
216 | #define WM8983_DLRSWAP 0x0004 /* DLRSWAP */ | ||
217 | #define WM8983_DLRSWAP_MASK 0x0004 /* DLRSWAP */ | ||
218 | #define WM8983_DLRSWAP_SHIFT 2 /* DLRSWAP */ | ||
219 | #define WM8983_DLRSWAP_WIDTH 1 /* DLRSWAP */ | ||
220 | #define WM8983_ALRSWAP 0x0002 /* ALRSWAP */ | ||
221 | #define WM8983_ALRSWAP_MASK 0x0002 /* ALRSWAP */ | ||
222 | #define WM8983_ALRSWAP_SHIFT 1 /* ALRSWAP */ | ||
223 | #define WM8983_ALRSWAP_WIDTH 1 /* ALRSWAP */ | ||
224 | #define WM8983_MONO 0x0001 /* MONO */ | ||
225 | #define WM8983_MONO_MASK 0x0001 /* MONO */ | ||
226 | #define WM8983_MONO_SHIFT 0 /* MONO */ | ||
227 | #define WM8983_MONO_WIDTH 1 /* MONO */ | ||
228 | |||
229 | /* | ||
230 | * R5 (0x05) - Companding control | ||
231 | */ | ||
232 | #define WM8983_WL8 0x0020 /* WL8 */ | ||
233 | #define WM8983_WL8_MASK 0x0020 /* WL8 */ | ||
234 | #define WM8983_WL8_SHIFT 5 /* WL8 */ | ||
235 | #define WM8983_WL8_WIDTH 1 /* WL8 */ | ||
236 | #define WM8983_DAC_COMP_MASK 0x0018 /* DAC_COMP - [4:3] */ | ||
237 | #define WM8983_DAC_COMP_SHIFT 3 /* DAC_COMP - [4:3] */ | ||
238 | #define WM8983_DAC_COMP_WIDTH 2 /* DAC_COMP - [4:3] */ | ||
239 | #define WM8983_ADC_COMP_MASK 0x0006 /* ADC_COMP - [2:1] */ | ||
240 | #define WM8983_ADC_COMP_SHIFT 1 /* ADC_COMP - [2:1] */ | ||
241 | #define WM8983_ADC_COMP_WIDTH 2 /* ADC_COMP - [2:1] */ | ||
242 | #define WM8983_LOOPBACK 0x0001 /* LOOPBACK */ | ||
243 | #define WM8983_LOOPBACK_MASK 0x0001 /* LOOPBACK */ | ||
244 | #define WM8983_LOOPBACK_SHIFT 0 /* LOOPBACK */ | ||
245 | #define WM8983_LOOPBACK_WIDTH 1 /* LOOPBACK */ | ||
246 | |||
247 | /* | ||
248 | * R6 (0x06) - Clock Gen control | ||
249 | */ | ||
250 | #define WM8983_CLKSEL 0x0100 /* CLKSEL */ | ||
251 | #define WM8983_CLKSEL_MASK 0x0100 /* CLKSEL */ | ||
252 | #define WM8983_CLKSEL_SHIFT 8 /* CLKSEL */ | ||
253 | #define WM8983_CLKSEL_WIDTH 1 /* CLKSEL */ | ||
254 | #define WM8983_MCLKDIV_MASK 0x00E0 /* MCLKDIV - [7:5] */ | ||
255 | #define WM8983_MCLKDIV_SHIFT 5 /* MCLKDIV - [7:5] */ | ||
256 | #define WM8983_MCLKDIV_WIDTH 3 /* MCLKDIV - [7:5] */ | ||
257 | #define WM8983_BCLKDIV_MASK 0x001C /* BCLKDIV - [4:2] */ | ||
258 | #define WM8983_BCLKDIV_SHIFT 2 /* BCLKDIV - [4:2] */ | ||
259 | #define WM8983_BCLKDIV_WIDTH 3 /* BCLKDIV - [4:2] */ | ||
260 | #define WM8983_MS 0x0001 /* MS */ | ||
261 | #define WM8983_MS_MASK 0x0001 /* MS */ | ||
262 | #define WM8983_MS_SHIFT 0 /* MS */ | ||
263 | #define WM8983_MS_WIDTH 1 /* MS */ | ||
264 | |||
265 | /* | ||
266 | * R7 (0x07) - Additional control | ||
267 | */ | ||
268 | #define WM8983_SR_MASK 0x000E /* SR - [3:1] */ | ||
269 | #define WM8983_SR_SHIFT 1 /* SR - [3:1] */ | ||
270 | #define WM8983_SR_WIDTH 3 /* SR - [3:1] */ | ||
271 | #define WM8983_SLOWCLKEN 0x0001 /* SLOWCLKEN */ | ||
272 | #define WM8983_SLOWCLKEN_MASK 0x0001 /* SLOWCLKEN */ | ||
273 | #define WM8983_SLOWCLKEN_SHIFT 0 /* SLOWCLKEN */ | ||
274 | #define WM8983_SLOWCLKEN_WIDTH 1 /* SLOWCLKEN */ | ||
275 | |||
276 | /* | ||
277 | * R8 (0x08) - GPIO Control | ||
278 | */ | ||
279 | #define WM8983_OPCLKDIV_MASK 0x0030 /* OPCLKDIV - [5:4] */ | ||
280 | #define WM8983_OPCLKDIV_SHIFT 4 /* OPCLKDIV - [5:4] */ | ||
281 | #define WM8983_OPCLKDIV_WIDTH 2 /* OPCLKDIV - [5:4] */ | ||
282 | #define WM8983_GPIO1POL 0x0008 /* GPIO1POL */ | ||
283 | #define WM8983_GPIO1POL_MASK 0x0008 /* GPIO1POL */ | ||
284 | #define WM8983_GPIO1POL_SHIFT 3 /* GPIO1POL */ | ||
285 | #define WM8983_GPIO1POL_WIDTH 1 /* GPIO1POL */ | ||
286 | #define WM8983_GPIO1SEL_MASK 0x0007 /* GPIO1SEL - [2:0] */ | ||
287 | #define WM8983_GPIO1SEL_SHIFT 0 /* GPIO1SEL - [2:0] */ | ||
288 | #define WM8983_GPIO1SEL_WIDTH 3 /* GPIO1SEL - [2:0] */ | ||
289 | |||
290 | /* | ||
291 | * R9 (0x09) - Jack Detect Control 1 | ||
292 | */ | ||
293 | #define WM8983_JD_VMID1 0x0100 /* JD_VMID1 */ | ||
294 | #define WM8983_JD_VMID1_MASK 0x0100 /* JD_VMID1 */ | ||
295 | #define WM8983_JD_VMID1_SHIFT 8 /* JD_VMID1 */ | ||
296 | #define WM8983_JD_VMID1_WIDTH 1 /* JD_VMID1 */ | ||
297 | #define WM8983_JD_VMID0 0x0080 /* JD_VMID0 */ | ||
298 | #define WM8983_JD_VMID0_MASK 0x0080 /* JD_VMID0 */ | ||
299 | #define WM8983_JD_VMID0_SHIFT 7 /* JD_VMID0 */ | ||
300 | #define WM8983_JD_VMID0_WIDTH 1 /* JD_VMID0 */ | ||
301 | #define WM8983_JD_EN 0x0040 /* JD_EN */ | ||
302 | #define WM8983_JD_EN_MASK 0x0040 /* JD_EN */ | ||
303 | #define WM8983_JD_EN_SHIFT 6 /* JD_EN */ | ||
304 | #define WM8983_JD_EN_WIDTH 1 /* JD_EN */ | ||
305 | #define WM8983_JD_SEL_MASK 0x0030 /* JD_SEL - [5:4] */ | ||
306 | #define WM8983_JD_SEL_SHIFT 4 /* JD_SEL - [5:4] */ | ||
307 | #define WM8983_JD_SEL_WIDTH 2 /* JD_SEL - [5:4] */ | ||
308 | |||
309 | /* | ||
310 | * R10 (0x0A) - DAC Control | ||
311 | */ | ||
312 | #define WM8983_SOFTMUTE 0x0040 /* SOFTMUTE */ | ||
313 | #define WM8983_SOFTMUTE_MASK 0x0040 /* SOFTMUTE */ | ||
314 | #define WM8983_SOFTMUTE_SHIFT 6 /* SOFTMUTE */ | ||
315 | #define WM8983_SOFTMUTE_WIDTH 1 /* SOFTMUTE */ | ||
316 | #define WM8983_DACOSR128 0x0008 /* DACOSR128 */ | ||
317 | #define WM8983_DACOSR128_MASK 0x0008 /* DACOSR128 */ | ||
318 | #define WM8983_DACOSR128_SHIFT 3 /* DACOSR128 */ | ||
319 | #define WM8983_DACOSR128_WIDTH 1 /* DACOSR128 */ | ||
320 | #define WM8983_AMUTE 0x0004 /* AMUTE */ | ||
321 | #define WM8983_AMUTE_MASK 0x0004 /* AMUTE */ | ||
322 | #define WM8983_AMUTE_SHIFT 2 /* AMUTE */ | ||
323 | #define WM8983_AMUTE_WIDTH 1 /* AMUTE */ | ||
324 | #define WM8983_DACRPOL 0x0002 /* DACRPOL */ | ||
325 | #define WM8983_DACRPOL_MASK 0x0002 /* DACRPOL */ | ||
326 | #define WM8983_DACRPOL_SHIFT 1 /* DACRPOL */ | ||
327 | #define WM8983_DACRPOL_WIDTH 1 /* DACRPOL */ | ||
328 | #define WM8983_DACLPOL 0x0001 /* DACLPOL */ | ||
329 | #define WM8983_DACLPOL_MASK 0x0001 /* DACLPOL */ | ||
330 | #define WM8983_DACLPOL_SHIFT 0 /* DACLPOL */ | ||
331 | #define WM8983_DACLPOL_WIDTH 1 /* DACLPOL */ | ||
332 | |||
333 | /* | ||
334 | * R11 (0x0B) - Left DAC digital Vol | ||
335 | */ | ||
336 | #define WM8983_DACVU 0x0100 /* DACVU */ | ||
337 | #define WM8983_DACVU_MASK 0x0100 /* DACVU */ | ||
338 | #define WM8983_DACVU_SHIFT 8 /* DACVU */ | ||
339 | #define WM8983_DACVU_WIDTH 1 /* DACVU */ | ||
340 | #define WM8983_DACLVOL_MASK 0x00FF /* DACLVOL - [7:0] */ | ||
341 | #define WM8983_DACLVOL_SHIFT 0 /* DACLVOL - [7:0] */ | ||
342 | #define WM8983_DACLVOL_WIDTH 8 /* DACLVOL - [7:0] */ | ||
343 | |||
344 | /* | ||
345 | * R12 (0x0C) - Right DAC digital vol | ||
346 | */ | ||
347 | #define WM8983_DACVU 0x0100 /* DACVU */ | ||
348 | #define WM8983_DACVU_MASK 0x0100 /* DACVU */ | ||
349 | #define WM8983_DACVU_SHIFT 8 /* DACVU */ | ||
350 | #define WM8983_DACVU_WIDTH 1 /* DACVU */ | ||
351 | #define WM8983_DACRVOL_MASK 0x00FF /* DACRVOL - [7:0] */ | ||
352 | #define WM8983_DACRVOL_SHIFT 0 /* DACRVOL - [7:0] */ | ||
353 | #define WM8983_DACRVOL_WIDTH 8 /* DACRVOL - [7:0] */ | ||
354 | |||
355 | /* | ||
356 | * R13 (0x0D) - Jack Detect Control 2 | ||
357 | */ | ||
358 | #define WM8983_JD_EN1_MASK 0x00F0 /* JD_EN1 - [7:4] */ | ||
359 | #define WM8983_JD_EN1_SHIFT 4 /* JD_EN1 - [7:4] */ | ||
360 | #define WM8983_JD_EN1_WIDTH 4 /* JD_EN1 - [7:4] */ | ||
361 | #define WM8983_JD_EN0_MASK 0x000F /* JD_EN0 - [3:0] */ | ||
362 | #define WM8983_JD_EN0_SHIFT 0 /* JD_EN0 - [3:0] */ | ||
363 | #define WM8983_JD_EN0_WIDTH 4 /* JD_EN0 - [3:0] */ | ||
364 | |||
365 | /* | ||
366 | * R14 (0x0E) - ADC Control | ||
367 | */ | ||
368 | #define WM8983_HPFEN 0x0100 /* HPFEN */ | ||
369 | #define WM8983_HPFEN_MASK 0x0100 /* HPFEN */ | ||
370 | #define WM8983_HPFEN_SHIFT 8 /* HPFEN */ | ||
371 | #define WM8983_HPFEN_WIDTH 1 /* HPFEN */ | ||
372 | #define WM8983_HPFAPP 0x0080 /* HPFAPP */ | ||
373 | #define WM8983_HPFAPP_MASK 0x0080 /* HPFAPP */ | ||
374 | #define WM8983_HPFAPP_SHIFT 7 /* HPFAPP */ | ||
375 | #define WM8983_HPFAPP_WIDTH 1 /* HPFAPP */ | ||
376 | #define WM8983_HPFCUT_MASK 0x0070 /* HPFCUT - [6:4] */ | ||
377 | #define WM8983_HPFCUT_SHIFT 4 /* HPFCUT - [6:4] */ | ||
378 | #define WM8983_HPFCUT_WIDTH 3 /* HPFCUT - [6:4] */ | ||
379 | #define WM8983_ADCOSR128 0x0008 /* ADCOSR128 */ | ||
380 | #define WM8983_ADCOSR128_MASK 0x0008 /* ADCOSR128 */ | ||
381 | #define WM8983_ADCOSR128_SHIFT 3 /* ADCOSR128 */ | ||
382 | #define WM8983_ADCOSR128_WIDTH 1 /* ADCOSR128 */ | ||
383 | #define WM8983_ADCRPOL 0x0002 /* ADCRPOL */ | ||
384 | #define WM8983_ADCRPOL_MASK 0x0002 /* ADCRPOL */ | ||
385 | #define WM8983_ADCRPOL_SHIFT 1 /* ADCRPOL */ | ||
386 | #define WM8983_ADCRPOL_WIDTH 1 /* ADCRPOL */ | ||
387 | #define WM8983_ADCLPOL 0x0001 /* ADCLPOL */ | ||
388 | #define WM8983_ADCLPOL_MASK 0x0001 /* ADCLPOL */ | ||
389 | #define WM8983_ADCLPOL_SHIFT 0 /* ADCLPOL */ | ||
390 | #define WM8983_ADCLPOL_WIDTH 1 /* ADCLPOL */ | ||
391 | |||
392 | /* | ||
393 | * R15 (0x0F) - Left ADC Digital Vol | ||
394 | */ | ||
395 | #define WM8983_ADCVU 0x0100 /* ADCVU */ | ||
396 | #define WM8983_ADCVU_MASK 0x0100 /* ADCVU */ | ||
397 | #define WM8983_ADCVU_SHIFT 8 /* ADCVU */ | ||
398 | #define WM8983_ADCVU_WIDTH 1 /* ADCVU */ | ||
399 | #define WM8983_ADCLVOL_MASK 0x00FF /* ADCLVOL - [7:0] */ | ||
400 | #define WM8983_ADCLVOL_SHIFT 0 /* ADCLVOL - [7:0] */ | ||
401 | #define WM8983_ADCLVOL_WIDTH 8 /* ADCLVOL - [7:0] */ | ||
402 | |||
403 | /* | ||
404 | * R16 (0x10) - Right ADC Digital Vol | ||
405 | */ | ||
406 | #define WM8983_ADCVU 0x0100 /* ADCVU */ | ||
407 | #define WM8983_ADCVU_MASK 0x0100 /* ADCVU */ | ||
408 | #define WM8983_ADCVU_SHIFT 8 /* ADCVU */ | ||
409 | #define WM8983_ADCVU_WIDTH 1 /* ADCVU */ | ||
410 | #define WM8983_ADCRVOL_MASK 0x00FF /* ADCRVOL - [7:0] */ | ||
411 | #define WM8983_ADCRVOL_SHIFT 0 /* ADCRVOL - [7:0] */ | ||
412 | #define WM8983_ADCRVOL_WIDTH 8 /* ADCRVOL - [7:0] */ | ||
413 | |||
414 | /* | ||
415 | * R18 (0x12) - EQ1 - low shelf | ||
416 | */ | ||
417 | #define WM8983_EQ3DMODE 0x0100 /* EQ3DMODE */ | ||
418 | #define WM8983_EQ3DMODE_MASK 0x0100 /* EQ3DMODE */ | ||
419 | #define WM8983_EQ3DMODE_SHIFT 8 /* EQ3DMODE */ | ||
420 | #define WM8983_EQ3DMODE_WIDTH 1 /* EQ3DMODE */ | ||
421 | #define WM8983_EQ1C_MASK 0x0060 /* EQ1C - [6:5] */ | ||
422 | #define WM8983_EQ1C_SHIFT 5 /* EQ1C - [6:5] */ | ||
423 | #define WM8983_EQ1C_WIDTH 2 /* EQ1C - [6:5] */ | ||
424 | #define WM8983_EQ1G_MASK 0x001F /* EQ1G - [4:0] */ | ||
425 | #define WM8983_EQ1G_SHIFT 0 /* EQ1G - [4:0] */ | ||
426 | #define WM8983_EQ1G_WIDTH 5 /* EQ1G - [4:0] */ | ||
427 | |||
428 | /* | ||
429 | * R19 (0x13) - EQ2 - peak 1 | ||
430 | */ | ||
431 | #define WM8983_EQ2BW 0x0100 /* EQ2BW */ | ||
432 | #define WM8983_EQ2BW_MASK 0x0100 /* EQ2BW */ | ||
433 | #define WM8983_EQ2BW_SHIFT 8 /* EQ2BW */ | ||
434 | #define WM8983_EQ2BW_WIDTH 1 /* EQ2BW */ | ||
435 | #define WM8983_EQ2C_MASK 0x0060 /* EQ2C - [6:5] */ | ||
436 | #define WM8983_EQ2C_SHIFT 5 /* EQ2C - [6:5] */ | ||
437 | #define WM8983_EQ2C_WIDTH 2 /* EQ2C - [6:5] */ | ||
438 | #define WM8983_EQ2G_MASK 0x001F /* EQ2G - [4:0] */ | ||
439 | #define WM8983_EQ2G_SHIFT 0 /* EQ2G - [4:0] */ | ||
440 | #define WM8983_EQ2G_WIDTH 5 /* EQ2G - [4:0] */ | ||
441 | |||
442 | /* | ||
443 | * R20 (0x14) - EQ3 - peak 2 | ||
444 | */ | ||
445 | #define WM8983_EQ3BW 0x0100 /* EQ3BW */ | ||
446 | #define WM8983_EQ3BW_MASK 0x0100 /* EQ3BW */ | ||
447 | #define WM8983_EQ3BW_SHIFT 8 /* EQ3BW */ | ||
448 | #define WM8983_EQ3BW_WIDTH 1 /* EQ3BW */ | ||
449 | #define WM8983_EQ3C_MASK 0x0060 /* EQ3C - [6:5] */ | ||
450 | #define WM8983_EQ3C_SHIFT 5 /* EQ3C - [6:5] */ | ||
451 | #define WM8983_EQ3C_WIDTH 2 /* EQ3C - [6:5] */ | ||
452 | #define WM8983_EQ3G_MASK 0x001F /* EQ3G - [4:0] */ | ||
453 | #define WM8983_EQ3G_SHIFT 0 /* EQ3G - [4:0] */ | ||
454 | #define WM8983_EQ3G_WIDTH 5 /* EQ3G - [4:0] */ | ||
455 | |||
456 | /* | ||
457 | * R21 (0x15) - EQ4 - peak 3 | ||
458 | */ | ||
459 | #define WM8983_EQ4BW 0x0100 /* EQ4BW */ | ||
460 | #define WM8983_EQ4BW_MASK 0x0100 /* EQ4BW */ | ||
461 | #define WM8983_EQ4BW_SHIFT 8 /* EQ4BW */ | ||
462 | #define WM8983_EQ4BW_WIDTH 1 /* EQ4BW */ | ||
463 | #define WM8983_EQ4C_MASK 0x0060 /* EQ4C - [6:5] */ | ||
464 | #define WM8983_EQ4C_SHIFT 5 /* EQ4C - [6:5] */ | ||
465 | #define WM8983_EQ4C_WIDTH 2 /* EQ4C - [6:5] */ | ||
466 | #define WM8983_EQ4G_MASK 0x001F /* EQ4G - [4:0] */ | ||
467 | #define WM8983_EQ4G_SHIFT 0 /* EQ4G - [4:0] */ | ||
468 | #define WM8983_EQ4G_WIDTH 5 /* EQ4G - [4:0] */ | ||
469 | |||
470 | /* | ||
471 | * R22 (0x16) - EQ5 - high shelf | ||
472 | */ | ||
473 | #define WM8983_EQ5C_MASK 0x0060 /* EQ5C - [6:5] */ | ||
474 | #define WM8983_EQ5C_SHIFT 5 /* EQ5C - [6:5] */ | ||
475 | #define WM8983_EQ5C_WIDTH 2 /* EQ5C - [6:5] */ | ||
476 | #define WM8983_EQ5G_MASK 0x001F /* EQ5G - [4:0] */ | ||
477 | #define WM8983_EQ5G_SHIFT 0 /* EQ5G - [4:0] */ | ||
478 | #define WM8983_EQ5G_WIDTH 5 /* EQ5G - [4:0] */ | ||
479 | |||
480 | /* | ||
481 | * R24 (0x18) - DAC Limiter 1 | ||
482 | */ | ||
483 | #define WM8983_LIMEN 0x0100 /* LIMEN */ | ||
484 | #define WM8983_LIMEN_MASK 0x0100 /* LIMEN */ | ||
485 | #define WM8983_LIMEN_SHIFT 8 /* LIMEN */ | ||
486 | #define WM8983_LIMEN_WIDTH 1 /* LIMEN */ | ||
487 | #define WM8983_LIMDCY_MASK 0x00F0 /* LIMDCY - [7:4] */ | ||
488 | #define WM8983_LIMDCY_SHIFT 4 /* LIMDCY - [7:4] */ | ||
489 | #define WM8983_LIMDCY_WIDTH 4 /* LIMDCY - [7:4] */ | ||
490 | #define WM8983_LIMATK_MASK 0x000F /* LIMATK - [3:0] */ | ||
491 | #define WM8983_LIMATK_SHIFT 0 /* LIMATK - [3:0] */ | ||
492 | #define WM8983_LIMATK_WIDTH 4 /* LIMATK - [3:0] */ | ||
493 | |||
494 | /* | ||
495 | * R25 (0x19) - DAC Limiter 2 | ||
496 | */ | ||
497 | #define WM8983_LIMLVL_MASK 0x0070 /* LIMLVL - [6:4] */ | ||
498 | #define WM8983_LIMLVL_SHIFT 4 /* LIMLVL - [6:4] */ | ||
499 | #define WM8983_LIMLVL_WIDTH 3 /* LIMLVL - [6:4] */ | ||
500 | #define WM8983_LIMBOOST_MASK 0x000F /* LIMBOOST - [3:0] */ | ||
501 | #define WM8983_LIMBOOST_SHIFT 0 /* LIMBOOST - [3:0] */ | ||
502 | #define WM8983_LIMBOOST_WIDTH 4 /* LIMBOOST - [3:0] */ | ||
503 | |||
504 | /* | ||
505 | * R27 (0x1B) - Notch Filter 1 | ||
506 | */ | ||
507 | #define WM8983_NFU 0x0100 /* NFU */ | ||
508 | #define WM8983_NFU_MASK 0x0100 /* NFU */ | ||
509 | #define WM8983_NFU_SHIFT 8 /* NFU */ | ||
510 | #define WM8983_NFU_WIDTH 1 /* NFU */ | ||
511 | #define WM8983_NFEN 0x0080 /* NFEN */ | ||
512 | #define WM8983_NFEN_MASK 0x0080 /* NFEN */ | ||
513 | #define WM8983_NFEN_SHIFT 7 /* NFEN */ | ||
514 | #define WM8983_NFEN_WIDTH 1 /* NFEN */ | ||
515 | #define WM8983_NFA0_13_7_MASK 0x007F /* NFA0(13:7) - [6:0] */ | ||
516 | #define WM8983_NFA0_13_7_SHIFT 0 /* NFA0(13:7) - [6:0] */ | ||
517 | #define WM8983_NFA0_13_7_WIDTH 7 /* NFA0(13:7) - [6:0] */ | ||
518 | |||
519 | /* | ||
520 | * R28 (0x1C) - Notch Filter 2 | ||
521 | */ | ||
522 | #define WM8983_NFU 0x0100 /* NFU */ | ||
523 | #define WM8983_NFU_MASK 0x0100 /* NFU */ | ||
524 | #define WM8983_NFU_SHIFT 8 /* NFU */ | ||
525 | #define WM8983_NFU_WIDTH 1 /* NFU */ | ||
526 | #define WM8983_NFA0_6_0_MASK 0x007F /* NFA0(6:0) - [6:0] */ | ||
527 | #define WM8983_NFA0_6_0_SHIFT 0 /* NFA0(6:0) - [6:0] */ | ||
528 | #define WM8983_NFA0_6_0_WIDTH 7 /* NFA0(6:0) - [6:0] */ | ||
529 | |||
530 | /* | ||
531 | * R29 (0x1D) - Notch Filter 3 | ||
532 | */ | ||
533 | #define WM8983_NFU 0x0100 /* NFU */ | ||
534 | #define WM8983_NFU_MASK 0x0100 /* NFU */ | ||
535 | #define WM8983_NFU_SHIFT 8 /* NFU */ | ||
536 | #define WM8983_NFU_WIDTH 1 /* NFU */ | ||
537 | #define WM8983_NFA1_13_7_MASK 0x007F /* NFA1(13:7) - [6:0] */ | ||
538 | #define WM8983_NFA1_13_7_SHIFT 0 /* NFA1(13:7) - [6:0] */ | ||
539 | #define WM8983_NFA1_13_7_WIDTH 7 /* NFA1(13:7) - [6:0] */ | ||
540 | |||
541 | /* | ||
542 | * R30 (0x1E) - Notch Filter 4 | ||
543 | */ | ||
544 | #define WM8983_NFU 0x0100 /* NFU */ | ||
545 | #define WM8983_NFU_MASK 0x0100 /* NFU */ | ||
546 | #define WM8983_NFU_SHIFT 8 /* NFU */ | ||
547 | #define WM8983_NFU_WIDTH 1 /* NFU */ | ||
548 | #define WM8983_NFA1_6_0_MASK 0x007F /* NFA1(6:0) - [6:0] */ | ||
549 | #define WM8983_NFA1_6_0_SHIFT 0 /* NFA1(6:0) - [6:0] */ | ||
550 | #define WM8983_NFA1_6_0_WIDTH 7 /* NFA1(6:0) - [6:0] */ | ||
551 | |||
552 | /* | ||
553 | * R32 (0x20) - ALC control 1 | ||
554 | */ | ||
555 | #define WM8983_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */ | ||
556 | #define WM8983_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */ | ||
557 | #define WM8983_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */ | ||
558 | #define WM8983_ALCMAX_MASK 0x0038 /* ALCMAX - [5:3] */ | ||
559 | #define WM8983_ALCMAX_SHIFT 3 /* ALCMAX - [5:3] */ | ||
560 | #define WM8983_ALCMAX_WIDTH 3 /* ALCMAX - [5:3] */ | ||
561 | #define WM8983_ALCMIN_MASK 0x0007 /* ALCMIN - [2:0] */ | ||
562 | #define WM8983_ALCMIN_SHIFT 0 /* ALCMIN - [2:0] */ | ||
563 | #define WM8983_ALCMIN_WIDTH 3 /* ALCMIN - [2:0] */ | ||
564 | |||
565 | /* | ||
566 | * R33 (0x21) - ALC control 2 | ||
567 | */ | ||
568 | #define WM8983_ALCHLD_MASK 0x00F0 /* ALCHLD - [7:4] */ | ||
569 | #define WM8983_ALCHLD_SHIFT 4 /* ALCHLD - [7:4] */ | ||
570 | #define WM8983_ALCHLD_WIDTH 4 /* ALCHLD - [7:4] */ | ||
571 | #define WM8983_ALCLVL_MASK 0x000F /* ALCLVL - [3:0] */ | ||
572 | #define WM8983_ALCLVL_SHIFT 0 /* ALCLVL - [3:0] */ | ||
573 | #define WM8983_ALCLVL_WIDTH 4 /* ALCLVL - [3:0] */ | ||
574 | |||
575 | /* | ||
576 | * R34 (0x22) - ALC control 3 | ||
577 | */ | ||
578 | #define WM8983_ALCMODE 0x0100 /* ALCMODE */ | ||
579 | #define WM8983_ALCMODE_MASK 0x0100 /* ALCMODE */ | ||
580 | #define WM8983_ALCMODE_SHIFT 8 /* ALCMODE */ | ||
581 | #define WM8983_ALCMODE_WIDTH 1 /* ALCMODE */ | ||
582 | #define WM8983_ALCDCY_MASK 0x00F0 /* ALCDCY - [7:4] */ | ||
583 | #define WM8983_ALCDCY_SHIFT 4 /* ALCDCY - [7:4] */ | ||
584 | #define WM8983_ALCDCY_WIDTH 4 /* ALCDCY - [7:4] */ | ||
585 | #define WM8983_ALCATK_MASK 0x000F /* ALCATK - [3:0] */ | ||
586 | #define WM8983_ALCATK_SHIFT 0 /* ALCATK - [3:0] */ | ||
587 | #define WM8983_ALCATK_WIDTH 4 /* ALCATK - [3:0] */ | ||
588 | |||
589 | /* | ||
590 | * R35 (0x23) - Noise Gate | ||
591 | */ | ||
592 | #define WM8983_NGEN 0x0008 /* NGEN */ | ||
593 | #define WM8983_NGEN_MASK 0x0008 /* NGEN */ | ||
594 | #define WM8983_NGEN_SHIFT 3 /* NGEN */ | ||
595 | #define WM8983_NGEN_WIDTH 1 /* NGEN */ | ||
596 | #define WM8983_NGTH_MASK 0x0007 /* NGTH - [2:0] */ | ||
597 | #define WM8983_NGTH_SHIFT 0 /* NGTH - [2:0] */ | ||
598 | #define WM8983_NGTH_WIDTH 3 /* NGTH - [2:0] */ | ||
599 | |||
600 | /* | ||
601 | * R36 (0x24) - PLL N | ||
602 | */ | ||
603 | #define WM8983_PLL_PRESCALE 0x0010 /* PLL_PRESCALE */ | ||
604 | #define WM8983_PLL_PRESCALE_MASK 0x0010 /* PLL_PRESCALE */ | ||
605 | #define WM8983_PLL_PRESCALE_SHIFT 4 /* PLL_PRESCALE */ | ||
606 | #define WM8983_PLL_PRESCALE_WIDTH 1 /* PLL_PRESCALE */ | ||
607 | #define WM8983_PLLN_MASK 0x000F /* PLLN - [3:0] */ | ||
608 | #define WM8983_PLLN_SHIFT 0 /* PLLN - [3:0] */ | ||
609 | #define WM8983_PLLN_WIDTH 4 /* PLLN - [3:0] */ | ||
610 | |||
611 | /* | ||
612 | * R37 (0x25) - PLL K 1 | ||
613 | */ | ||
614 | #define WM8983_PLLK_23_18_MASK 0x003F /* PLLK(23:18) - [5:0] */ | ||
615 | #define WM8983_PLLK_23_18_SHIFT 0 /* PLLK(23:18) - [5:0] */ | ||
616 | #define WM8983_PLLK_23_18_WIDTH 6 /* PLLK(23:18) - [5:0] */ | ||
617 | |||
618 | /* | ||
619 | * R38 (0x26) - PLL K 2 | ||
620 | */ | ||
621 | #define WM8983_PLLK_17_9_MASK 0x01FF /* PLLK(17:9) - [8:0] */ | ||
622 | #define WM8983_PLLK_17_9_SHIFT 0 /* PLLK(17:9) - [8:0] */ | ||
623 | #define WM8983_PLLK_17_9_WIDTH 9 /* PLLK(17:9) - [8:0] */ | ||
624 | |||
625 | /* | ||
626 | * R39 (0x27) - PLL K 3 | ||
627 | */ | ||
628 | #define WM8983_PLLK_8_0_MASK 0x01FF /* PLLK(8:0) - [8:0] */ | ||
629 | #define WM8983_PLLK_8_0_SHIFT 0 /* PLLK(8:0) - [8:0] */ | ||
630 | #define WM8983_PLLK_8_0_WIDTH 9 /* PLLK(8:0) - [8:0] */ | ||
631 | |||
632 | /* | ||
633 | * R41 (0x29) - 3D control | ||
634 | */ | ||
635 | #define WM8983_DEPTH3D_MASK 0x000F /* DEPTH3D - [3:0] */ | ||
636 | #define WM8983_DEPTH3D_SHIFT 0 /* DEPTH3D - [3:0] */ | ||
637 | #define WM8983_DEPTH3D_WIDTH 4 /* DEPTH3D - [3:0] */ | ||
638 | |||
639 | /* | ||
640 | * R42 (0x2A) - OUT4 to ADC | ||
641 | */ | ||
642 | #define WM8983_OUT4_2ADCVOL_MASK 0x01C0 /* OUT4_2ADCVOL - [8:6] */ | ||
643 | #define WM8983_OUT4_2ADCVOL_SHIFT 6 /* OUT4_2ADCVOL - [8:6] */ | ||
644 | #define WM8983_OUT4_2ADCVOL_WIDTH 3 /* OUT4_2ADCVOL - [8:6] */ | ||
645 | #define WM8983_OUT4_2LNR 0x0020 /* OUT4_2LNR */ | ||
646 | #define WM8983_OUT4_2LNR_MASK 0x0020 /* OUT4_2LNR */ | ||
647 | #define WM8983_OUT4_2LNR_SHIFT 5 /* OUT4_2LNR */ | ||
648 | #define WM8983_OUT4_2LNR_WIDTH 1 /* OUT4_2LNR */ | ||
649 | #define WM8983_POBCTRL 0x0004 /* POBCTRL */ | ||
650 | #define WM8983_POBCTRL_MASK 0x0004 /* POBCTRL */ | ||
651 | #define WM8983_POBCTRL_SHIFT 2 /* POBCTRL */ | ||
652 | #define WM8983_POBCTRL_WIDTH 1 /* POBCTRL */ | ||
653 | #define WM8983_DELEN 0x0002 /* DELEN */ | ||
654 | #define WM8983_DELEN_MASK 0x0002 /* DELEN */ | ||
655 | #define WM8983_DELEN_SHIFT 1 /* DELEN */ | ||
656 | #define WM8983_DELEN_WIDTH 1 /* DELEN */ | ||
657 | #define WM8983_OUT1DEL 0x0001 /* OUT1DEL */ | ||
658 | #define WM8983_OUT1DEL_MASK 0x0001 /* OUT1DEL */ | ||
659 | #define WM8983_OUT1DEL_SHIFT 0 /* OUT1DEL */ | ||
660 | #define WM8983_OUT1DEL_WIDTH 1 /* OUT1DEL */ | ||
661 | |||
662 | /* | ||
663 | * R43 (0x2B) - Beep control | ||
664 | */ | ||
665 | #define WM8983_BYPL2RMIX 0x0100 /* BYPL2RMIX */ | ||
666 | #define WM8983_BYPL2RMIX_MASK 0x0100 /* BYPL2RMIX */ | ||
667 | #define WM8983_BYPL2RMIX_SHIFT 8 /* BYPL2RMIX */ | ||
668 | #define WM8983_BYPL2RMIX_WIDTH 1 /* BYPL2RMIX */ | ||
669 | #define WM8983_BYPR2LMIX 0x0080 /* BYPR2LMIX */ | ||
670 | #define WM8983_BYPR2LMIX_MASK 0x0080 /* BYPR2LMIX */ | ||
671 | #define WM8983_BYPR2LMIX_SHIFT 7 /* BYPR2LMIX */ | ||
672 | #define WM8983_BYPR2LMIX_WIDTH 1 /* BYPR2LMIX */ | ||
673 | #define WM8983_MUTERPGA2INV 0x0020 /* MUTERPGA2INV */ | ||
674 | #define WM8983_MUTERPGA2INV_MASK 0x0020 /* MUTERPGA2INV */ | ||
675 | #define WM8983_MUTERPGA2INV_SHIFT 5 /* MUTERPGA2INV */ | ||
676 | #define WM8983_MUTERPGA2INV_WIDTH 1 /* MUTERPGA2INV */ | ||
677 | #define WM8983_INVROUT2 0x0010 /* INVROUT2 */ | ||
678 | #define WM8983_INVROUT2_MASK 0x0010 /* INVROUT2 */ | ||
679 | #define WM8983_INVROUT2_SHIFT 4 /* INVROUT2 */ | ||
680 | #define WM8983_INVROUT2_WIDTH 1 /* INVROUT2 */ | ||
681 | #define WM8983_BEEPVOL_MASK 0x000E /* BEEPVOL - [3:1] */ | ||
682 | #define WM8983_BEEPVOL_SHIFT 1 /* BEEPVOL - [3:1] */ | ||
683 | #define WM8983_BEEPVOL_WIDTH 3 /* BEEPVOL - [3:1] */ | ||
684 | #define WM8983_BEEPEN 0x0001 /* BEEPEN */ | ||
685 | #define WM8983_BEEPEN_MASK 0x0001 /* BEEPEN */ | ||
686 | #define WM8983_BEEPEN_SHIFT 0 /* BEEPEN */ | ||
687 | #define WM8983_BEEPEN_WIDTH 1 /* BEEPEN */ | ||
688 | |||
689 | /* | ||
690 | * R44 (0x2C) - Input ctrl | ||
691 | */ | ||
692 | #define WM8983_MBVSEL 0x0100 /* MBVSEL */ | ||
693 | #define WM8983_MBVSEL_MASK 0x0100 /* MBVSEL */ | ||
694 | #define WM8983_MBVSEL_SHIFT 8 /* MBVSEL */ | ||
695 | #define WM8983_MBVSEL_WIDTH 1 /* MBVSEL */ | ||
696 | #define WM8983_R2_2INPPGA 0x0040 /* R2_2INPPGA */ | ||
697 | #define WM8983_R2_2INPPGA_MASK 0x0040 /* R2_2INPPGA */ | ||
698 | #define WM8983_R2_2INPPGA_SHIFT 6 /* R2_2INPPGA */ | ||
699 | #define WM8983_R2_2INPPGA_WIDTH 1 /* R2_2INPPGA */ | ||
700 | #define WM8983_RIN2INPPGA 0x0020 /* RIN2INPPGA */ | ||
701 | #define WM8983_RIN2INPPGA_MASK 0x0020 /* RIN2INPPGA */ | ||
702 | #define WM8983_RIN2INPPGA_SHIFT 5 /* RIN2INPPGA */ | ||
703 | #define WM8983_RIN2INPPGA_WIDTH 1 /* RIN2INPPGA */ | ||
704 | #define WM8983_RIP2INPPGA 0x0010 /* RIP2INPPGA */ | ||
705 | #define WM8983_RIP2INPPGA_MASK 0x0010 /* RIP2INPPGA */ | ||
706 | #define WM8983_RIP2INPPGA_SHIFT 4 /* RIP2INPPGA */ | ||
707 | #define WM8983_RIP2INPPGA_WIDTH 1 /* RIP2INPPGA */ | ||
708 | #define WM8983_L2_2INPPGA 0x0004 /* L2_2INPPGA */ | ||
709 | #define WM8983_L2_2INPPGA_MASK 0x0004 /* L2_2INPPGA */ | ||
710 | #define WM8983_L2_2INPPGA_SHIFT 2 /* L2_2INPPGA */ | ||
711 | #define WM8983_L2_2INPPGA_WIDTH 1 /* L2_2INPPGA */ | ||
712 | #define WM8983_LIN2INPPGA 0x0002 /* LIN2INPPGA */ | ||
713 | #define WM8983_LIN2INPPGA_MASK 0x0002 /* LIN2INPPGA */ | ||
714 | #define WM8983_LIN2INPPGA_SHIFT 1 /* LIN2INPPGA */ | ||
715 | #define WM8983_LIN2INPPGA_WIDTH 1 /* LIN2INPPGA */ | ||
716 | #define WM8983_LIP2INPPGA 0x0001 /* LIP2INPPGA */ | ||
717 | #define WM8983_LIP2INPPGA_MASK 0x0001 /* LIP2INPPGA */ | ||
718 | #define WM8983_LIP2INPPGA_SHIFT 0 /* LIP2INPPGA */ | ||
719 | #define WM8983_LIP2INPPGA_WIDTH 1 /* LIP2INPPGA */ | ||
720 | |||
721 | /* | ||
722 | * R45 (0x2D) - Left INP PGA gain ctrl | ||
723 | */ | ||
724 | #define WM8983_INPGAVU 0x0100 /* INPGAVU */ | ||
725 | #define WM8983_INPGAVU_MASK 0x0100 /* INPGAVU */ | ||
726 | #define WM8983_INPGAVU_SHIFT 8 /* INPGAVU */ | ||
727 | #define WM8983_INPGAVU_WIDTH 1 /* INPGAVU */ | ||
728 | #define WM8983_INPPGAZCL 0x0080 /* INPPGAZCL */ | ||
729 | #define WM8983_INPPGAZCL_MASK 0x0080 /* INPPGAZCL */ | ||
730 | #define WM8983_INPPGAZCL_SHIFT 7 /* INPPGAZCL */ | ||
731 | #define WM8983_INPPGAZCL_WIDTH 1 /* INPPGAZCL */ | ||
732 | #define WM8983_INPPGAMUTEL 0x0040 /* INPPGAMUTEL */ | ||
733 | #define WM8983_INPPGAMUTEL_MASK 0x0040 /* INPPGAMUTEL */ | ||
734 | #define WM8983_INPPGAMUTEL_SHIFT 6 /* INPPGAMUTEL */ | ||
735 | #define WM8983_INPPGAMUTEL_WIDTH 1 /* INPPGAMUTEL */ | ||
736 | #define WM8983_INPPGAVOLL_MASK 0x003F /* INPPGAVOLL - [5:0] */ | ||
737 | #define WM8983_INPPGAVOLL_SHIFT 0 /* INPPGAVOLL - [5:0] */ | ||
738 | #define WM8983_INPPGAVOLL_WIDTH 6 /* INPPGAVOLL - [5:0] */ | ||
739 | |||
740 | /* | ||
741 | * R46 (0x2E) - Right INP PGA gain ctrl | ||
742 | */ | ||
743 | #define WM8983_INPGAVU 0x0100 /* INPGAVU */ | ||
744 | #define WM8983_INPGAVU_MASK 0x0100 /* INPGAVU */ | ||
745 | #define WM8983_INPGAVU_SHIFT 8 /* INPGAVU */ | ||
746 | #define WM8983_INPGAVU_WIDTH 1 /* INPGAVU */ | ||
747 | #define WM8983_INPPGAZCR 0x0080 /* INPPGAZCR */ | ||
748 | #define WM8983_INPPGAZCR_MASK 0x0080 /* INPPGAZCR */ | ||
749 | #define WM8983_INPPGAZCR_SHIFT 7 /* INPPGAZCR */ | ||
750 | #define WM8983_INPPGAZCR_WIDTH 1 /* INPPGAZCR */ | ||
751 | #define WM8983_INPPGAMUTER 0x0040 /* INPPGAMUTER */ | ||
752 | #define WM8983_INPPGAMUTER_MASK 0x0040 /* INPPGAMUTER */ | ||
753 | #define WM8983_INPPGAMUTER_SHIFT 6 /* INPPGAMUTER */ | ||
754 | #define WM8983_INPPGAMUTER_WIDTH 1 /* INPPGAMUTER */ | ||
755 | #define WM8983_INPPGAVOLR_MASK 0x003F /* INPPGAVOLR - [5:0] */ | ||
756 | #define WM8983_INPPGAVOLR_SHIFT 0 /* INPPGAVOLR - [5:0] */ | ||
757 | #define WM8983_INPPGAVOLR_WIDTH 6 /* INPPGAVOLR - [5:0] */ | ||
758 | |||
759 | /* | ||
760 | * R47 (0x2F) - Left ADC BOOST ctrl | ||
761 | */ | ||
762 | #define WM8983_PGABOOSTL 0x0100 /* PGABOOSTL */ | ||
763 | #define WM8983_PGABOOSTL_MASK 0x0100 /* PGABOOSTL */ | ||
764 | #define WM8983_PGABOOSTL_SHIFT 8 /* PGABOOSTL */ | ||
765 | #define WM8983_PGABOOSTL_WIDTH 1 /* PGABOOSTL */ | ||
766 | #define WM8983_L2_2BOOSTVOL_MASK 0x0070 /* L2_2BOOSTVOL - [6:4] */ | ||
767 | #define WM8983_L2_2BOOSTVOL_SHIFT 4 /* L2_2BOOSTVOL - [6:4] */ | ||
768 | #define WM8983_L2_2BOOSTVOL_WIDTH 3 /* L2_2BOOSTVOL - [6:4] */ | ||
769 | #define WM8983_AUXL2BOOSTVOL_MASK 0x0007 /* AUXL2BOOSTVOL - [2:0] */ | ||
770 | #define WM8983_AUXL2BOOSTVOL_SHIFT 0 /* AUXL2BOOSTVOL - [2:0] */ | ||
771 | #define WM8983_AUXL2BOOSTVOL_WIDTH 3 /* AUXL2BOOSTVOL - [2:0] */ | ||
772 | |||
773 | /* | ||
774 | * R48 (0x30) - Right ADC BOOST ctrl | ||
775 | */ | ||
776 | #define WM8983_PGABOOSTR 0x0100 /* PGABOOSTR */ | ||
777 | #define WM8983_PGABOOSTR_MASK 0x0100 /* PGABOOSTR */ | ||
778 | #define WM8983_PGABOOSTR_SHIFT 8 /* PGABOOSTR */ | ||
779 | #define WM8983_PGABOOSTR_WIDTH 1 /* PGABOOSTR */ | ||
780 | #define WM8983_R2_2BOOSTVOL_MASK 0x0070 /* R2_2BOOSTVOL - [6:4] */ | ||
781 | #define WM8983_R2_2BOOSTVOL_SHIFT 4 /* R2_2BOOSTVOL - [6:4] */ | ||
782 | #define WM8983_R2_2BOOSTVOL_WIDTH 3 /* R2_2BOOSTVOL - [6:4] */ | ||
783 | #define WM8983_AUXR2BOOSTVOL_MASK 0x0007 /* AUXR2BOOSTVOL - [2:0] */ | ||
784 | #define WM8983_AUXR2BOOSTVOL_SHIFT 0 /* AUXR2BOOSTVOL - [2:0] */ | ||
785 | #define WM8983_AUXR2BOOSTVOL_WIDTH 3 /* AUXR2BOOSTVOL - [2:0] */ | ||
786 | |||
787 | /* | ||
788 | * R49 (0x31) - Output ctrl | ||
789 | */ | ||
790 | #define WM8983_DACL2RMIX 0x0040 /* DACL2RMIX */ | ||
791 | #define WM8983_DACL2RMIX_MASK 0x0040 /* DACL2RMIX */ | ||
792 | #define WM8983_DACL2RMIX_SHIFT 6 /* DACL2RMIX */ | ||
793 | #define WM8983_DACL2RMIX_WIDTH 1 /* DACL2RMIX */ | ||
794 | #define WM8983_DACR2LMIX 0x0020 /* DACR2LMIX */ | ||
795 | #define WM8983_DACR2LMIX_MASK 0x0020 /* DACR2LMIX */ | ||
796 | #define WM8983_DACR2LMIX_SHIFT 5 /* DACR2LMIX */ | ||
797 | #define WM8983_DACR2LMIX_WIDTH 1 /* DACR2LMIX */ | ||
798 | #define WM8983_OUT4BOOST 0x0010 /* OUT4BOOST */ | ||
799 | #define WM8983_OUT4BOOST_MASK 0x0010 /* OUT4BOOST */ | ||
800 | #define WM8983_OUT4BOOST_SHIFT 4 /* OUT4BOOST */ | ||
801 | #define WM8983_OUT4BOOST_WIDTH 1 /* OUT4BOOST */ | ||
802 | #define WM8983_OUT3BOOST 0x0008 /* OUT3BOOST */ | ||
803 | #define WM8983_OUT3BOOST_MASK 0x0008 /* OUT3BOOST */ | ||
804 | #define WM8983_OUT3BOOST_SHIFT 3 /* OUT3BOOST */ | ||
805 | #define WM8983_OUT3BOOST_WIDTH 1 /* OUT3BOOST */ | ||
806 | #define WM8983_SPKBOOST 0x0004 /* SPKBOOST */ | ||
807 | #define WM8983_SPKBOOST_MASK 0x0004 /* SPKBOOST */ | ||
808 | #define WM8983_SPKBOOST_SHIFT 2 /* SPKBOOST */ | ||
809 | #define WM8983_SPKBOOST_WIDTH 1 /* SPKBOOST */ | ||
810 | #define WM8983_TSDEN 0x0002 /* TSDEN */ | ||
811 | #define WM8983_TSDEN_MASK 0x0002 /* TSDEN */ | ||
812 | #define WM8983_TSDEN_SHIFT 1 /* TSDEN */ | ||
813 | #define WM8983_TSDEN_WIDTH 1 /* TSDEN */ | ||
814 | #define WM8983_VROI 0x0001 /* VROI */ | ||
815 | #define WM8983_VROI_MASK 0x0001 /* VROI */ | ||
816 | #define WM8983_VROI_SHIFT 0 /* VROI */ | ||
817 | #define WM8983_VROI_WIDTH 1 /* VROI */ | ||
818 | |||
819 | /* | ||
820 | * R50 (0x32) - Left mixer ctrl | ||
821 | */ | ||
822 | #define WM8983_AUXLMIXVOL_MASK 0x01C0 /* AUXLMIXVOL - [8:6] */ | ||
823 | #define WM8983_AUXLMIXVOL_SHIFT 6 /* AUXLMIXVOL - [8:6] */ | ||
824 | #define WM8983_AUXLMIXVOL_WIDTH 3 /* AUXLMIXVOL - [8:6] */ | ||
825 | #define WM8983_AUXL2LMIX 0x0020 /* AUXL2LMIX */ | ||
826 | #define WM8983_AUXL2LMIX_MASK 0x0020 /* AUXL2LMIX */ | ||
827 | #define WM8983_AUXL2LMIX_SHIFT 5 /* AUXL2LMIX */ | ||
828 | #define WM8983_AUXL2LMIX_WIDTH 1 /* AUXL2LMIX */ | ||
829 | #define WM8983_BYPLMIXVOL_MASK 0x001C /* BYPLMIXVOL - [4:2] */ | ||
830 | #define WM8983_BYPLMIXVOL_SHIFT 2 /* BYPLMIXVOL - [4:2] */ | ||
831 | #define WM8983_BYPLMIXVOL_WIDTH 3 /* BYPLMIXVOL - [4:2] */ | ||
832 | #define WM8983_BYPL2LMIX 0x0002 /* BYPL2LMIX */ | ||
833 | #define WM8983_BYPL2LMIX_MASK 0x0002 /* BYPL2LMIX */ | ||
834 | #define WM8983_BYPL2LMIX_SHIFT 1 /* BYPL2LMIX */ | ||
835 | #define WM8983_BYPL2LMIX_WIDTH 1 /* BYPL2LMIX */ | ||
836 | #define WM8983_DACL2LMIX 0x0001 /* DACL2LMIX */ | ||
837 | #define WM8983_DACL2LMIX_MASK 0x0001 /* DACL2LMIX */ | ||
838 | #define WM8983_DACL2LMIX_SHIFT 0 /* DACL2LMIX */ | ||
839 | #define WM8983_DACL2LMIX_WIDTH 1 /* DACL2LMIX */ | ||
840 | |||
841 | /* | ||
842 | * R51 (0x33) - Right mixer ctrl | ||
843 | */ | ||
844 | #define WM8983_AUXRMIXVOL_MASK 0x01C0 /* AUXRMIXVOL - [8:6] */ | ||
845 | #define WM8983_AUXRMIXVOL_SHIFT 6 /* AUXRMIXVOL - [8:6] */ | ||
846 | #define WM8983_AUXRMIXVOL_WIDTH 3 /* AUXRMIXVOL - [8:6] */ | ||
847 | #define WM8983_AUXR2RMIX 0x0020 /* AUXR2RMIX */ | ||
848 | #define WM8983_AUXR2RMIX_MASK 0x0020 /* AUXR2RMIX */ | ||
849 | #define WM8983_AUXR2RMIX_SHIFT 5 /* AUXR2RMIX */ | ||
850 | #define WM8983_AUXR2RMIX_WIDTH 1 /* AUXR2RMIX */ | ||
851 | #define WM8983_BYPRMIXVOL_MASK 0x001C /* BYPRMIXVOL - [4:2] */ | ||
852 | #define WM8983_BYPRMIXVOL_SHIFT 2 /* BYPRMIXVOL - [4:2] */ | ||
853 | #define WM8983_BYPRMIXVOL_WIDTH 3 /* BYPRMIXVOL - [4:2] */ | ||
854 | #define WM8983_BYPR2RMIX 0x0002 /* BYPR2RMIX */ | ||
855 | #define WM8983_BYPR2RMIX_MASK 0x0002 /* BYPR2RMIX */ | ||
856 | #define WM8983_BYPR2RMIX_SHIFT 1 /* BYPR2RMIX */ | ||
857 | #define WM8983_BYPR2RMIX_WIDTH 1 /* BYPR2RMIX */ | ||
858 | #define WM8983_DACR2RMIX 0x0001 /* DACR2RMIX */ | ||
859 | #define WM8983_DACR2RMIX_MASK 0x0001 /* DACR2RMIX */ | ||
860 | #define WM8983_DACR2RMIX_SHIFT 0 /* DACR2RMIX */ | ||
861 | #define WM8983_DACR2RMIX_WIDTH 1 /* DACR2RMIX */ | ||
862 | |||
863 | /* | ||
864 | * R52 (0x34) - LOUT1 (HP) volume ctrl | ||
865 | */ | ||
866 | #define WM8983_OUT1VU 0x0100 /* OUT1VU */ | ||
867 | #define WM8983_OUT1VU_MASK 0x0100 /* OUT1VU */ | ||
868 | #define WM8983_OUT1VU_SHIFT 8 /* OUT1VU */ | ||
869 | #define WM8983_OUT1VU_WIDTH 1 /* OUT1VU */ | ||
870 | #define WM8983_LOUT1ZC 0x0080 /* LOUT1ZC */ | ||
871 | #define WM8983_LOUT1ZC_MASK 0x0080 /* LOUT1ZC */ | ||
872 | #define WM8983_LOUT1ZC_SHIFT 7 /* LOUT1ZC */ | ||
873 | #define WM8983_LOUT1ZC_WIDTH 1 /* LOUT1ZC */ | ||
874 | #define WM8983_LOUT1MUTE 0x0040 /* LOUT1MUTE */ | ||
875 | #define WM8983_LOUT1MUTE_MASK 0x0040 /* LOUT1MUTE */ | ||
876 | #define WM8983_LOUT1MUTE_SHIFT 6 /* LOUT1MUTE */ | ||
877 | #define WM8983_LOUT1MUTE_WIDTH 1 /* LOUT1MUTE */ | ||
878 | #define WM8983_LOUT1VOL_MASK 0x003F /* LOUT1VOL - [5:0] */ | ||
879 | #define WM8983_LOUT1VOL_SHIFT 0 /* LOUT1VOL - [5:0] */ | ||
880 | #define WM8983_LOUT1VOL_WIDTH 6 /* LOUT1VOL - [5:0] */ | ||
881 | |||
882 | /* | ||
883 | * R53 (0x35) - ROUT1 (HP) volume ctrl | ||
884 | */ | ||
885 | #define WM8983_OUT1VU 0x0100 /* OUT1VU */ | ||
886 | #define WM8983_OUT1VU_MASK 0x0100 /* OUT1VU */ | ||
887 | #define WM8983_OUT1VU_SHIFT 8 /* OUT1VU */ | ||
888 | #define WM8983_OUT1VU_WIDTH 1 /* OUT1VU */ | ||
889 | #define WM8983_ROUT1ZC 0x0080 /* ROUT1ZC */ | ||
890 | #define WM8983_ROUT1ZC_MASK 0x0080 /* ROUT1ZC */ | ||
891 | #define WM8983_ROUT1ZC_SHIFT 7 /* ROUT1ZC */ | ||
892 | #define WM8983_ROUT1ZC_WIDTH 1 /* ROUT1ZC */ | ||
893 | #define WM8983_ROUT1MUTE 0x0040 /* ROUT1MUTE */ | ||
894 | #define WM8983_ROUT1MUTE_MASK 0x0040 /* ROUT1MUTE */ | ||
895 | #define WM8983_ROUT1MUTE_SHIFT 6 /* ROUT1MUTE */ | ||
896 | #define WM8983_ROUT1MUTE_WIDTH 1 /* ROUT1MUTE */ | ||
897 | #define WM8983_ROUT1VOL_MASK 0x003F /* ROUT1VOL - [5:0] */ | ||
898 | #define WM8983_ROUT1VOL_SHIFT 0 /* ROUT1VOL - [5:0] */ | ||
899 | #define WM8983_ROUT1VOL_WIDTH 6 /* ROUT1VOL - [5:0] */ | ||
900 | |||
901 | /* | ||
902 | * R54 (0x36) - LOUT2 (SPK) volume ctrl | ||
903 | */ | ||
904 | #define WM8983_OUT2VU 0x0100 /* OUT2VU */ | ||
905 | #define WM8983_OUT2VU_MASK 0x0100 /* OUT2VU */ | ||
906 | #define WM8983_OUT2VU_SHIFT 8 /* OUT2VU */ | ||
907 | #define WM8983_OUT2VU_WIDTH 1 /* OUT2VU */ | ||
908 | #define WM8983_LOUT2ZC 0x0080 /* LOUT2ZC */ | ||
909 | #define WM8983_LOUT2ZC_MASK 0x0080 /* LOUT2ZC */ | ||
910 | #define WM8983_LOUT2ZC_SHIFT 7 /* LOUT2ZC */ | ||
911 | #define WM8983_LOUT2ZC_WIDTH 1 /* LOUT2ZC */ | ||
912 | #define WM8983_LOUT2MUTE 0x0040 /* LOUT2MUTE */ | ||
913 | #define WM8983_LOUT2MUTE_MASK 0x0040 /* LOUT2MUTE */ | ||
914 | #define WM8983_LOUT2MUTE_SHIFT 6 /* LOUT2MUTE */ | ||
915 | #define WM8983_LOUT2MUTE_WIDTH 1 /* LOUT2MUTE */ | ||
916 | #define WM8983_LOUT2VOL_MASK 0x003F /* LOUT2VOL - [5:0] */ | ||
917 | #define WM8983_LOUT2VOL_SHIFT 0 /* LOUT2VOL - [5:0] */ | ||
918 | #define WM8983_LOUT2VOL_WIDTH 6 /* LOUT2VOL - [5:0] */ | ||
919 | |||
920 | /* | ||
921 | * R55 (0x37) - ROUT2 (SPK) volume ctrl | ||
922 | */ | ||
923 | #define WM8983_OUT2VU 0x0100 /* OUT2VU */ | ||
924 | #define WM8983_OUT2VU_MASK 0x0100 /* OUT2VU */ | ||
925 | #define WM8983_OUT2VU_SHIFT 8 /* OUT2VU */ | ||
926 | #define WM8983_OUT2VU_WIDTH 1 /* OUT2VU */ | ||
927 | #define WM8983_ROUT2ZC 0x0080 /* ROUT2ZC */ | ||
928 | #define WM8983_ROUT2ZC_MASK 0x0080 /* ROUT2ZC */ | ||
929 | #define WM8983_ROUT2ZC_SHIFT 7 /* ROUT2ZC */ | ||
930 | #define WM8983_ROUT2ZC_WIDTH 1 /* ROUT2ZC */ | ||
931 | #define WM8983_ROUT2MUTE 0x0040 /* ROUT2MUTE */ | ||
932 | #define WM8983_ROUT2MUTE_MASK 0x0040 /* ROUT2MUTE */ | ||
933 | #define WM8983_ROUT2MUTE_SHIFT 6 /* ROUT2MUTE */ | ||
934 | #define WM8983_ROUT2MUTE_WIDTH 1 /* ROUT2MUTE */ | ||
935 | #define WM8983_ROUT2VOL_MASK 0x003F /* ROUT2VOL - [5:0] */ | ||
936 | #define WM8983_ROUT2VOL_SHIFT 0 /* ROUT2VOL - [5:0] */ | ||
937 | #define WM8983_ROUT2VOL_WIDTH 6 /* ROUT2VOL - [5:0] */ | ||
938 | |||
939 | /* | ||
940 | * R56 (0x38) - OUT3 mixer ctrl | ||
941 | */ | ||
942 | #define WM8983_OUT3MUTE 0x0040 /* OUT3MUTE */ | ||
943 | #define WM8983_OUT3MUTE_MASK 0x0040 /* OUT3MUTE */ | ||
944 | #define WM8983_OUT3MUTE_SHIFT 6 /* OUT3MUTE */ | ||
945 | #define WM8983_OUT3MUTE_WIDTH 1 /* OUT3MUTE */ | ||
946 | #define WM8983_OUT4_2OUT3 0x0008 /* OUT4_2OUT3 */ | ||
947 | #define WM8983_OUT4_2OUT3_MASK 0x0008 /* OUT4_2OUT3 */ | ||
948 | #define WM8983_OUT4_2OUT3_SHIFT 3 /* OUT4_2OUT3 */ | ||
949 | #define WM8983_OUT4_2OUT3_WIDTH 1 /* OUT4_2OUT3 */ | ||
950 | #define WM8983_BYPL2OUT3 0x0004 /* BYPL2OUT3 */ | ||
951 | #define WM8983_BYPL2OUT3_MASK 0x0004 /* BYPL2OUT3 */ | ||
952 | #define WM8983_BYPL2OUT3_SHIFT 2 /* BYPL2OUT3 */ | ||
953 | #define WM8983_BYPL2OUT3_WIDTH 1 /* BYPL2OUT3 */ | ||
954 | #define WM8983_LMIX2OUT3 0x0002 /* LMIX2OUT3 */ | ||
955 | #define WM8983_LMIX2OUT3_MASK 0x0002 /* LMIX2OUT3 */ | ||
956 | #define WM8983_LMIX2OUT3_SHIFT 1 /* LMIX2OUT3 */ | ||
957 | #define WM8983_LMIX2OUT3_WIDTH 1 /* LMIX2OUT3 */ | ||
958 | #define WM8983_LDAC2OUT3 0x0001 /* LDAC2OUT3 */ | ||
959 | #define WM8983_LDAC2OUT3_MASK 0x0001 /* LDAC2OUT3 */ | ||
960 | #define WM8983_LDAC2OUT3_SHIFT 0 /* LDAC2OUT3 */ | ||
961 | #define WM8983_LDAC2OUT3_WIDTH 1 /* LDAC2OUT3 */ | ||
962 | |||
963 | /* | ||
964 | * R57 (0x39) - OUT4 (MONO) mix ctrl | ||
965 | */ | ||
966 | #define WM8983_OUT3_2OUT4 0x0080 /* OUT3_2OUT4 */ | ||
967 | #define WM8983_OUT3_2OUT4_MASK 0x0080 /* OUT3_2OUT4 */ | ||
968 | #define WM8983_OUT3_2OUT4_SHIFT 7 /* OUT3_2OUT4 */ | ||
969 | #define WM8983_OUT3_2OUT4_WIDTH 1 /* OUT3_2OUT4 */ | ||
970 | #define WM8983_OUT4MUTE 0x0040 /* OUT4MUTE */ | ||
971 | #define WM8983_OUT4MUTE_MASK 0x0040 /* OUT4MUTE */ | ||
972 | #define WM8983_OUT4MUTE_SHIFT 6 /* OUT4MUTE */ | ||
973 | #define WM8983_OUT4MUTE_WIDTH 1 /* OUT4MUTE */ | ||
974 | #define WM8983_OUT4ATTN 0x0020 /* OUT4ATTN */ | ||
975 | #define WM8983_OUT4ATTN_MASK 0x0020 /* OUT4ATTN */ | ||
976 | #define WM8983_OUT4ATTN_SHIFT 5 /* OUT4ATTN */ | ||
977 | #define WM8983_OUT4ATTN_WIDTH 1 /* OUT4ATTN */ | ||
978 | #define WM8983_LMIX2OUT4 0x0010 /* LMIX2OUT4 */ | ||
979 | #define WM8983_LMIX2OUT4_MASK 0x0010 /* LMIX2OUT4 */ | ||
980 | #define WM8983_LMIX2OUT4_SHIFT 4 /* LMIX2OUT4 */ | ||
981 | #define WM8983_LMIX2OUT4_WIDTH 1 /* LMIX2OUT4 */ | ||
982 | #define WM8983_LDAC2OUT4 0x0008 /* LDAC2OUT4 */ | ||
983 | #define WM8983_LDAC2OUT4_MASK 0x0008 /* LDAC2OUT4 */ | ||
984 | #define WM8983_LDAC2OUT4_SHIFT 3 /* LDAC2OUT4 */ | ||
985 | #define WM8983_LDAC2OUT4_WIDTH 1 /* LDAC2OUT4 */ | ||
986 | #define WM8983_BYPR2OUT4 0x0004 /* BYPR2OUT4 */ | ||
987 | #define WM8983_BYPR2OUT4_MASK 0x0004 /* BYPR2OUT4 */ | ||
988 | #define WM8983_BYPR2OUT4_SHIFT 2 /* BYPR2OUT4 */ | ||
989 | #define WM8983_BYPR2OUT4_WIDTH 1 /* BYPR2OUT4 */ | ||
990 | #define WM8983_RMIX2OUT4 0x0002 /* RMIX2OUT4 */ | ||
991 | #define WM8983_RMIX2OUT4_MASK 0x0002 /* RMIX2OUT4 */ | ||
992 | #define WM8983_RMIX2OUT4_SHIFT 1 /* RMIX2OUT4 */ | ||
993 | #define WM8983_RMIX2OUT4_WIDTH 1 /* RMIX2OUT4 */ | ||
994 | #define WM8983_RDAC2OUT4 0x0001 /* RDAC2OUT4 */ | ||
995 | #define WM8983_RDAC2OUT4_MASK 0x0001 /* RDAC2OUT4 */ | ||
996 | #define WM8983_RDAC2OUT4_SHIFT 0 /* RDAC2OUT4 */ | ||
997 | #define WM8983_RDAC2OUT4_WIDTH 1 /* RDAC2OUT4 */ | ||
998 | |||
999 | /* | ||
1000 | * R61 (0x3D) - BIAS CTRL | ||
1001 | */ | ||
1002 | #define WM8983_BIASCUT 0x0100 /* BIASCUT */ | ||
1003 | #define WM8983_BIASCUT_MASK 0x0100 /* BIASCUT */ | ||
1004 | #define WM8983_BIASCUT_SHIFT 8 /* BIASCUT */ | ||
1005 | #define WM8983_BIASCUT_WIDTH 1 /* BIASCUT */ | ||
1006 | #define WM8983_HALFIPBIAS 0x0080 /* HALFIPBIAS */ | ||
1007 | #define WM8983_HALFIPBIAS_MASK 0x0080 /* HALFIPBIAS */ | ||
1008 | #define WM8983_HALFIPBIAS_SHIFT 7 /* HALFIPBIAS */ | ||
1009 | #define WM8983_HALFIPBIAS_WIDTH 1 /* HALFIPBIAS */ | ||
1010 | #define WM8983_VBBIASTST_MASK 0x0060 /* VBBIASTST - [6:5] */ | ||
1011 | #define WM8983_VBBIASTST_SHIFT 5 /* VBBIASTST - [6:5] */ | ||
1012 | #define WM8983_VBBIASTST_WIDTH 2 /* VBBIASTST - [6:5] */ | ||
1013 | #define WM8983_BUFBIAS_MASK 0x0018 /* BUFBIAS - [4:3] */ | ||
1014 | #define WM8983_BUFBIAS_SHIFT 3 /* BUFBIAS - [4:3] */ | ||
1015 | #define WM8983_BUFBIAS_WIDTH 2 /* BUFBIAS - [4:3] */ | ||
1016 | #define WM8983_ADCBIAS_MASK 0x0006 /* ADCBIAS - [2:1] */ | ||
1017 | #define WM8983_ADCBIAS_SHIFT 1 /* ADCBIAS - [2:1] */ | ||
1018 | #define WM8983_ADCBIAS_WIDTH 2 /* ADCBIAS - [2:1] */ | ||
1019 | #define WM8983_HALFOPBIAS 0x0001 /* HALFOPBIAS */ | ||
1020 | #define WM8983_HALFOPBIAS_MASK 0x0001 /* HALFOPBIAS */ | ||
1021 | #define WM8983_HALFOPBIAS_SHIFT 0 /* HALFOPBIAS */ | ||
1022 | #define WM8983_HALFOPBIAS_WIDTH 1 /* HALFOPBIAS */ | ||
1023 | |||
1024 | enum clk_src { | ||
1025 | WM8983_CLKSRC_MCLK, | ||
1026 | WM8983_CLKSRC_PLL | ||
1027 | }; | ||
1028 | |||
1029 | #endif /* _WM8983_H */ | ||
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 9e5ff789b805..6e85b8869af7 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -876,7 +876,7 @@ SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0, | |||
876 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), | 876 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), |
877 | SND_SOC_DAPM_MIXER("SPKR", WM8993_POWER_MANAGEMENT_3, 9, 0, | 877 | SND_SOC_DAPM_MIXER("SPKR", WM8993_POWER_MANAGEMENT_3, 9, 0, |
878 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), | 878 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), |
879 | 879 | SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), | |
880 | }; | 880 | }; |
881 | 881 | ||
882 | static const struct snd_soc_dapm_route routes[] = { | 882 | static const struct snd_soc_dapm_route routes[] = { |
@@ -1434,6 +1434,7 @@ static int wm8993_probe(struct snd_soc_codec *codec) | |||
1434 | 1434 | ||
1435 | wm8993->hubs_data.hp_startup_mode = 1; | 1435 | wm8993->hubs_data.hp_startup_mode = 1; |
1436 | wm8993->hubs_data.dcs_codes = -2; | 1436 | wm8993->hubs_data.dcs_codes = -2; |
1437 | wm8993->hubs_data.series_startup = 1; | ||
1437 | 1438 | ||
1438 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1439 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
1439 | if (ret != 0) { | 1440 | if (ret != 0) { |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 970a95c5360b..09e680ae88b2 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -195,10 +195,6 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif) | |||
195 | aif + 1, rate); | 195 | aif + 1, rate); |
196 | } | 196 | } |
197 | 197 | ||
198 | if (rate && rate < 3000000) | ||
199 | dev_warn(codec->dev, "AIF%dCLK is %dHz, should be >=3MHz for optimal performance\n", | ||
200 | aif + 1, rate); | ||
201 | |||
202 | wm8994->aifclk[aif] = rate; | 198 | wm8994->aifclk[aif] = rate; |
203 | 199 | ||
204 | snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1 + offset, | 200 | snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1 + offset, |
@@ -1146,13 +1142,33 @@ SND_SOC_DAPM_PGA_E("Late DAC2L Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, | |||
1146 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | 1142 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1147 | SND_SOC_DAPM_PGA_E("Late DAC2R Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, | 1143 | SND_SOC_DAPM_PGA_E("Late DAC2R Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, |
1148 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | 1144 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), |
1145 | SND_SOC_DAPM_PGA_E("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
1146 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | ||
1147 | |||
1148 | SND_SOC_DAPM_MIXER_E("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, | ||
1149 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer), | ||
1150 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | ||
1151 | SND_SOC_DAPM_MIXER_E("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, | ||
1152 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer), | ||
1153 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | ||
1154 | SND_SOC_DAPM_MUX_E("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux, | ||
1155 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | ||
1156 | SND_SOC_DAPM_MUX_E("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux, | ||
1157 | late_enable_ev, SND_SOC_DAPM_PRE_PMU), | ||
1149 | 1158 | ||
1150 | SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev) | 1159 | SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev) |
1151 | }; | 1160 | }; |
1152 | 1161 | ||
1153 | static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { | 1162 | static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { |
1154 | SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0), | 1163 | SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0), |
1155 | SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0) | 1164 | SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0), |
1165 | SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1166 | SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, | ||
1167 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), | ||
1168 | SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, | ||
1169 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), | ||
1170 | SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), | ||
1171 | SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), | ||
1156 | }; | 1172 | }; |
1157 | 1173 | ||
1158 | static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = { | 1174 | static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = { |
@@ -1190,7 +1206,6 @@ SND_SOC_DAPM_INPUT("DMIC1DAT"), | |||
1190 | SND_SOC_DAPM_INPUT("DMIC2DAT"), | 1206 | SND_SOC_DAPM_INPUT("DMIC2DAT"), |
1191 | SND_SOC_DAPM_INPUT("Clock"), | 1207 | SND_SOC_DAPM_INPUT("Clock"), |
1192 | 1208 | ||
1193 | SND_SOC_DAPM_MICBIAS("MICBIAS", WM8994_MICBIAS, 2, 0), | ||
1194 | SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, | 1209 | SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, |
1195 | SND_SOC_DAPM_PRE_PMU), | 1210 | SND_SOC_DAPM_PRE_PMU), |
1196 | 1211 | ||
@@ -1283,14 +1298,6 @@ SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8994_POWER_MANAGEMENT_4, 2, 0), | |||
1283 | SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), | 1298 | SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), |
1284 | SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), | 1299 | SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), |
1285 | 1300 | ||
1286 | SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), | ||
1287 | SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), | ||
1288 | |||
1289 | SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, | ||
1290 | left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), | ||
1291 | SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, | ||
1292 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), | ||
1293 | |||
1294 | SND_SOC_DAPM_POST("Debug log", post_ev), | 1301 | SND_SOC_DAPM_POST("Debug log", post_ev), |
1295 | }; | 1302 | }; |
1296 | 1303 | ||
@@ -1509,8 +1516,10 @@ static const struct snd_soc_dapm_route wm8994_revd_intercon[] = { | |||
1509 | { "AIF2DACDAT", NULL, "AIF1DACDAT" }, | 1516 | { "AIF2DACDAT", NULL, "AIF1DACDAT" }, |
1510 | { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, | 1517 | { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, |
1511 | { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, | 1518 | { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, |
1512 | { "MICBIAS", NULL, "CLK_SYS" }, | 1519 | { "MICBIAS1", NULL, "CLK_SYS" }, |
1513 | { "MICBIAS", NULL, "MICBIAS Supply" }, | 1520 | { "MICBIAS1", NULL, "MICBIAS Supply" }, |
1521 | { "MICBIAS2", NULL, "CLK_SYS" }, | ||
1522 | { "MICBIAS2", NULL, "MICBIAS Supply" }, | ||
1514 | }; | 1523 | }; |
1515 | 1524 | ||
1516 | static const struct snd_soc_dapm_route wm8994_intercon[] = { | 1525 | static const struct snd_soc_dapm_route wm8994_intercon[] = { |
@@ -1623,6 +1632,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1623 | int reg_offset, ret; | 1632 | int reg_offset, ret; |
1624 | struct fll_div fll; | 1633 | struct fll_div fll; |
1625 | u16 reg, aif1, aif2; | 1634 | u16 reg, aif1, aif2; |
1635 | unsigned long timeout; | ||
1626 | 1636 | ||
1627 | aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) | 1637 | aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) |
1628 | & WM8994_AIF1CLK_ENA; | 1638 | & WM8994_AIF1CLK_ENA; |
@@ -1704,6 +1714,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1704 | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | | 1714 | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | |
1705 | (src - 1)); | 1715 | (src - 1)); |
1706 | 1716 | ||
1717 | /* Clear any pending completion from a previous failure */ | ||
1718 | try_wait_for_completion(&wm8994->fll_locked[id]); | ||
1719 | |||
1707 | /* Enable (with fractional mode if required) */ | 1720 | /* Enable (with fractional mode if required) */ |
1708 | if (freq_out) { | 1721 | if (freq_out) { |
1709 | if (fll.k) | 1722 | if (fll.k) |
@@ -1713,6 +1726,16 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1713 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, | 1726 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, |
1714 | WM8994_FLL1_ENA | WM8994_FLL1_FRAC, | 1727 | WM8994_FLL1_ENA | WM8994_FLL1_FRAC, |
1715 | reg); | 1728 | reg); |
1729 | |||
1730 | if (wm8994->fll_locked_irq) { | ||
1731 | timeout = wait_for_completion_timeout(&wm8994->fll_locked[id], | ||
1732 | msecs_to_jiffies(10)); | ||
1733 | if (timeout == 0) | ||
1734 | dev_warn(codec->dev, | ||
1735 | "Timed out waiting for FLL lock\n"); | ||
1736 | } else { | ||
1737 | msleep(5); | ||
1738 | } | ||
1716 | } | 1739 | } |
1717 | 1740 | ||
1718 | wm8994->fll[id].in = freq_in; | 1741 | wm8994->fll[id].in = freq_in; |
@@ -1730,6 +1753,14 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1730 | return 0; | 1753 | return 0; |
1731 | } | 1754 | } |
1732 | 1755 | ||
1756 | static irqreturn_t wm8994_fll_locked_irq(int irq, void *data) | ||
1757 | { | ||
1758 | struct completion *completion = data; | ||
1759 | |||
1760 | complete(completion); | ||
1761 | |||
1762 | return IRQ_HANDLED; | ||
1763 | } | ||
1733 | 1764 | ||
1734 | static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; | 1765 | static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; |
1735 | 1766 | ||
@@ -2269,6 +2300,33 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream, | |||
2269 | return snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_WL_MASK, aif1); | 2300 | return snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_WL_MASK, aif1); |
2270 | } | 2301 | } |
2271 | 2302 | ||
2303 | static void wm8994_aif_shutdown(struct snd_pcm_substream *substream, | ||
2304 | struct snd_soc_dai *dai) | ||
2305 | { | ||
2306 | struct snd_soc_codec *codec = dai->codec; | ||
2307 | int rate_reg = 0; | ||
2308 | |||
2309 | switch (dai->id) { | ||
2310 | case 1: | ||
2311 | rate_reg = WM8994_AIF1_RATE; | ||
2312 | break; | ||
2313 | case 2: | ||
2314 | rate_reg = WM8994_AIF1_RATE; | ||
2315 | break; | ||
2316 | default: | ||
2317 | break; | ||
2318 | } | ||
2319 | |||
2320 | /* If the DAI is idle then configure the divider tree for the | ||
2321 | * lowest output rate to save a little power if the clock is | ||
2322 | * still active (eg, because it is system clock). | ||
2323 | */ | ||
2324 | if (rate_reg && !dai->playback_active && !dai->capture_active) | ||
2325 | snd_soc_update_bits(codec, rate_reg, | ||
2326 | WM8994_AIF1_SR_MASK | | ||
2327 | WM8994_AIF1CLK_RATE_MASK, 0x9); | ||
2328 | } | ||
2329 | |||
2272 | static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute) | 2330 | static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute) |
2273 | { | 2331 | { |
2274 | struct snd_soc_codec *codec = codec_dai->codec; | 2332 | struct snd_soc_codec *codec = codec_dai->codec; |
@@ -2335,6 +2393,7 @@ static struct snd_soc_dai_ops wm8994_aif1_dai_ops = { | |||
2335 | .set_sysclk = wm8994_set_dai_sysclk, | 2393 | .set_sysclk = wm8994_set_dai_sysclk, |
2336 | .set_fmt = wm8994_set_dai_fmt, | 2394 | .set_fmt = wm8994_set_dai_fmt, |
2337 | .hw_params = wm8994_hw_params, | 2395 | .hw_params = wm8994_hw_params, |
2396 | .shutdown = wm8994_aif_shutdown, | ||
2338 | .digital_mute = wm8994_aif_mute, | 2397 | .digital_mute = wm8994_aif_mute, |
2339 | .set_pll = wm8994_set_fll, | 2398 | .set_pll = wm8994_set_fll, |
2340 | .set_tristate = wm8994_set_tristate, | 2399 | .set_tristate = wm8994_set_tristate, |
@@ -2344,6 +2403,7 @@ static struct snd_soc_dai_ops wm8994_aif2_dai_ops = { | |||
2344 | .set_sysclk = wm8994_set_dai_sysclk, | 2403 | .set_sysclk = wm8994_set_dai_sysclk, |
2345 | .set_fmt = wm8994_set_dai_fmt, | 2404 | .set_fmt = wm8994_set_dai_fmt, |
2346 | .hw_params = wm8994_hw_params, | 2405 | .hw_params = wm8994_hw_params, |
2406 | .shutdown = wm8994_aif_shutdown, | ||
2347 | .digital_mute = wm8994_aif_mute, | 2407 | .digital_mute = wm8994_aif_mute, |
2348 | .set_pll = wm8994_set_fll, | 2408 | .set_pll = wm8994_set_fll, |
2349 | .set_tristate = wm8994_set_tristate, | 2409 | .set_tristate = wm8994_set_tristate, |
@@ -2761,7 +2821,7 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
2761 | report = SND_JACK_MICROPHONE; | 2821 | report = SND_JACK_MICROPHONE; |
2762 | 2822 | ||
2763 | /* Everything else is buttons; just assign slots */ | 2823 | /* Everything else is buttons; just assign slots */ |
2764 | if (status & 0x1c0) | 2824 | if (status & 0x1c) |
2765 | report |= SND_JACK_BTN_0; | 2825 | report |= SND_JACK_BTN_0; |
2766 | 2826 | ||
2767 | done: | 2827 | done: |
@@ -2847,6 +2907,15 @@ out: | |||
2847 | return IRQ_HANDLED; | 2907 | return IRQ_HANDLED; |
2848 | } | 2908 | } |
2849 | 2909 | ||
2910 | static irqreturn_t wm8994_fifo_error(int irq, void *data) | ||
2911 | { | ||
2912 | struct snd_soc_codec *codec = data; | ||
2913 | |||
2914 | dev_err(codec->dev, "FIFO error\n"); | ||
2915 | |||
2916 | return IRQ_HANDLED; | ||
2917 | } | ||
2918 | |||
2850 | static int wm8994_codec_probe(struct snd_soc_codec *codec) | 2919 | static int wm8994_codec_probe(struct snd_soc_codec *codec) |
2851 | { | 2920 | { |
2852 | struct wm8994 *control; | 2921 | struct wm8994 *control; |
@@ -2865,6 +2934,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2865 | wm8994->pdata = dev_get_platdata(codec->dev->parent); | 2934 | wm8994->pdata = dev_get_platdata(codec->dev->parent); |
2866 | wm8994->codec = codec; | 2935 | wm8994->codec = codec; |
2867 | 2936 | ||
2937 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | ||
2938 | init_completion(&wm8994->fll_locked[i]); | ||
2939 | |||
2868 | if (wm8994->pdata && wm8994->pdata->micdet_irq) | 2940 | if (wm8994->pdata && wm8994->pdata->micdet_irq) |
2869 | wm8994->micdet_irq = wm8994->pdata->micdet_irq; | 2941 | wm8994->micdet_irq = wm8994->pdata->micdet_irq; |
2870 | else if (wm8994->pdata && wm8994->pdata->irq_base) | 2942 | else if (wm8994->pdata && wm8994->pdata->irq_base) |
@@ -2903,6 +2975,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2903 | wm8994->hubs.dcs_codes = -5; | 2975 | wm8994->hubs.dcs_codes = -5; |
2904 | wm8994->hubs.hp_startup_mode = 1; | 2976 | wm8994->hubs.hp_startup_mode = 1; |
2905 | wm8994->hubs.dcs_readback_mode = 1; | 2977 | wm8994->hubs.dcs_readback_mode = 1; |
2978 | wm8994->hubs.series_startup = 1; | ||
2906 | break; | 2979 | break; |
2907 | default: | 2980 | default: |
2908 | wm8994->hubs.dcs_readback_mode = 1; | 2981 | wm8994->hubs.dcs_readback_mode = 1; |
@@ -2917,6 +2990,15 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2917 | break; | 2990 | break; |
2918 | } | 2991 | } |
2919 | 2992 | ||
2993 | wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, | ||
2994 | wm8994_fifo_error, "FIFO error", codec); | ||
2995 | |||
2996 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE, | ||
2997 | wm_hubs_dcs_done, "DC servo done", | ||
2998 | &wm8994->hubs); | ||
2999 | if (ret == 0) | ||
3000 | wm8994->hubs.dcs_done_irq = true; | ||
3001 | |||
2920 | switch (control->type) { | 3002 | switch (control->type) { |
2921 | case WM8994: | 3003 | case WM8994: |
2922 | if (wm8994->micdet_irq) { | 3004 | if (wm8994->micdet_irq) { |
@@ -2973,6 +3055,16 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2973 | } | 3055 | } |
2974 | } | 3056 | } |
2975 | 3057 | ||
3058 | wm8994->fll_locked_irq = true; | ||
3059 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) { | ||
3060 | ret = wm8994_request_irq(codec->control_data, | ||
3061 | WM8994_IRQ_FLL1_LOCK + i, | ||
3062 | wm8994_fll_locked_irq, "FLL lock", | ||
3063 | &wm8994->fll_locked[i]); | ||
3064 | if (ret != 0) | ||
3065 | wm8994->fll_locked_irq = false; | ||
3066 | } | ||
3067 | |||
2976 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be | 3068 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be |
2977 | * configured on init - if a system wants to do this dynamically | 3069 | * configured on init - if a system wants to do this dynamically |
2978 | * at runtime we can deal with that then. | 3070 | * at runtime we can deal with that then. |
@@ -3048,10 +3140,18 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3048 | 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT, | 3140 | 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT, |
3049 | 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT); | 3141 | 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT); |
3050 | 3142 | ||
3051 | /* Unconditionally enable AIF1 ADC TDM mode; it only affects | 3143 | /* Unconditionally enable AIF1 ADC TDM mode on chips which can |
3052 | * behaviour on idle TDM clock cycles. */ | 3144 | * use this; it only affects behaviour on idle TDM clock |
3053 | snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1, | 3145 | * cycles. */ |
3054 | WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM); | 3146 | switch (control->type) { |
3147 | case WM8994: | ||
3148 | case WM8958: | ||
3149 | snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1, | ||
3150 | WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM); | ||
3151 | break; | ||
3152 | default: | ||
3153 | break; | ||
3154 | } | ||
3055 | 3155 | ||
3056 | wm8994_update_class_w(codec); | 3156 | wm8994_update_class_w(codec); |
3057 | 3157 | ||
@@ -3150,6 +3250,12 @@ err_irq: | |||
3150 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); | 3250 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); |
3151 | if (wm8994->micdet_irq) | 3251 | if (wm8994->micdet_irq) |
3152 | free_irq(wm8994->micdet_irq, wm8994); | 3252 | free_irq(wm8994->micdet_irq, wm8994); |
3253 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | ||
3254 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i, | ||
3255 | &wm8994->fll_locked[i]); | ||
3256 | wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, | ||
3257 | &wm8994->hubs); | ||
3258 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); | ||
3153 | err: | 3259 | err: |
3154 | kfree(wm8994); | 3260 | kfree(wm8994); |
3155 | return ret; | 3261 | return ret; |
@@ -3159,11 +3265,20 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) | |||
3159 | { | 3265 | { |
3160 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3266 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3161 | struct wm8994 *control = codec->control_data; | 3267 | struct wm8994 *control = codec->control_data; |
3268 | int i; | ||
3162 | 3269 | ||
3163 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); | 3270 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); |
3164 | 3271 | ||
3165 | pm_runtime_disable(codec->dev); | 3272 | pm_runtime_disable(codec->dev); |
3166 | 3273 | ||
3274 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | ||
3275 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i, | ||
3276 | &wm8994->fll_locked[i]); | ||
3277 | |||
3278 | wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, | ||
3279 | &wm8994->hubs); | ||
3280 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); | ||
3281 | |||
3167 | switch (control->type) { | 3282 | switch (control->type) { |
3168 | case WM8994: | 3283 | case WM8994: |
3169 | if (wm8994->micdet_irq) | 3284 | if (wm8994->micdet_irq) |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 0a1db04b73bd..1ab2266039f7 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <sound/soc.h> | 12 | #include <sound/soc.h> |
13 | #include <linux/firmware.h> | 13 | #include <linux/firmware.h> |
14 | #include <linux/completion.h> | ||
14 | 15 | ||
15 | #include "wm_hubs.h" | 16 | #include "wm_hubs.h" |
16 | 17 | ||
@@ -79,6 +80,8 @@ struct wm8994_priv { | |||
79 | int mclk[2]; | 80 | int mclk[2]; |
80 | int aifclk[2]; | 81 | int aifclk[2]; |
81 | struct wm8994_fll_config fll[2], fll_suspend[2]; | 82 | struct wm8994_fll_config fll[2], fll_suspend[2]; |
83 | struct completion fll_locked[2]; | ||
84 | bool fll_locked_irq; | ||
82 | 85 | ||
83 | int dac_rates[2]; | 86 | int dac_rates[2]; |
84 | int lrclk_shared[2]; | 87 | int lrclk_shared[2]; |
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 91c6b39de50c..a4691321f9b3 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -727,7 +727,7 @@ SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0, | |||
727 | SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0), | 727 | SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0), |
728 | 728 | ||
729 | SND_SOC_DAPM_PGA("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0), | 729 | SND_SOC_DAPM_PGA("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0), |
730 | SND_SOC_DAPM_PGA("Speaker", WM9081_POWER_MANAGEMENT, 1, 0, NULL, 0), | 730 | SND_SOC_DAPM_OUT_DRV("Speaker", WM9081_POWER_MANAGEMENT, 1, 0, NULL, 0), |
731 | 731 | ||
732 | SND_SOC_DAPM_OUTPUT("LINEOUT"), | 732 | SND_SOC_DAPM_OUTPUT("LINEOUT"), |
733 | SND_SOC_DAPM_OUTPUT("SPKN"), | 733 | SND_SOC_DAPM_OUTPUT("SPKN"), |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 9e370d14ad88..4cc2d567f22f 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -63,8 +63,10 @@ static const struct soc_enum speaker_mode = | |||
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 | { |
66 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | ||
66 | unsigned int reg; | 67 | unsigned int reg; |
67 | int count = 0; | 68 | int count = 0; |
69 | int timeout; | ||
68 | unsigned int val; | 70 | unsigned int val; |
69 | 71 | ||
70 | val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1; | 72 | val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1; |
@@ -74,18 +76,39 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) | |||
74 | 76 | ||
75 | dev_dbg(codec->dev, "Waiting for DC servo...\n"); | 77 | dev_dbg(codec->dev, "Waiting for DC servo...\n"); |
76 | 78 | ||
79 | if (hubs->dcs_done_irq) | ||
80 | timeout = 4; | ||
81 | else | ||
82 | timeout = 400; | ||
83 | |||
77 | do { | 84 | do { |
78 | count++; | 85 | count++; |
79 | msleep(1); | 86 | |
87 | if (hubs->dcs_done_irq) | ||
88 | wait_for_completion_timeout(&hubs->dcs_done, | ||
89 | msecs_to_jiffies(250)); | ||
90 | else | ||
91 | msleep(1); | ||
92 | |||
80 | reg = snd_soc_read(codec, WM8993_DC_SERVO_0); | 93 | reg = snd_soc_read(codec, WM8993_DC_SERVO_0); |
81 | dev_dbg(codec->dev, "DC servo: %x\n", reg); | 94 | dev_dbg(codec->dev, "DC servo: %x\n", reg); |
82 | } while (reg & op && count < 400); | 95 | } while (reg & op && count < timeout); |
83 | 96 | ||
84 | if (reg & op) | 97 | if (reg & op) |
85 | dev_err(codec->dev, "Timed out waiting for DC Servo %x\n", | 98 | dev_err(codec->dev, "Timed out waiting for DC Servo %x\n", |
86 | op); | 99 | op); |
87 | } | 100 | } |
88 | 101 | ||
102 | irqreturn_t wm_hubs_dcs_done(int irq, void *data) | ||
103 | { | ||
104 | struct wm_hubs_data *hubs = data; | ||
105 | |||
106 | complete(&hubs->dcs_done); | ||
107 | |||
108 | return IRQ_HANDLED; | ||
109 | } | ||
110 | EXPORT_SYMBOL_GPL(wm_hubs_dcs_done); | ||
111 | |||
89 | /* | 112 | /* |
90 | * Startup calibration of the DC servo | 113 | * Startup calibration of the DC servo |
91 | */ | 114 | */ |
@@ -107,8 +130,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
107 | return; | 130 | return; |
108 | } | 131 | } |
109 | 132 | ||
110 | /* Devices not using a DCS code correction have startup mode */ | 133 | if (hubs->series_startup) { |
111 | if (hubs->dcs_codes) { | ||
112 | /* Set for 32 series updates */ | 134 | /* Set for 32 series updates */ |
113 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, | 135 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, |
114 | WM8993_DCS_SERIES_NO_01_MASK, | 136 | WM8993_DCS_SERIES_NO_01_MASK, |
@@ -134,9 +156,9 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
134 | break; | 156 | break; |
135 | case 1: | 157 | case 1: |
136 | reg = snd_soc_read(codec, WM8993_DC_SERVO_3); | 158 | reg = snd_soc_read(codec, WM8993_DC_SERVO_3); |
137 | reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | 159 | reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) |
138 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 160 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
139 | reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | 161 | reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; |
140 | break; | 162 | break; |
141 | default: | 163 | default: |
142 | WARN(1, "Unknown DCS readback method\n"); | 164 | WARN(1, "Unknown DCS readback method\n"); |
@@ -150,13 +172,13 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
150 | dev_dbg(codec->dev, "Applying %d code DC servo correction\n", | 172 | dev_dbg(codec->dev, "Applying %d code DC servo correction\n", |
151 | hubs->dcs_codes); | 173 | hubs->dcs_codes); |
152 | 174 | ||
153 | /* HPOUT1L */ | 175 | /* HPOUT1R */ |
154 | offset = reg_l; | 176 | offset = reg_r; |
155 | offset += hubs->dcs_codes; | 177 | offset += hubs->dcs_codes; |
156 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 178 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
157 | 179 | ||
158 | /* HPOUT1R */ | 180 | /* HPOUT1L */ |
159 | offset = reg_r; | 181 | offset = reg_l; |
160 | offset += hubs->dcs_codes; | 182 | offset += hubs->dcs_codes; |
161 | dcs_cfg |= (u8)offset; | 183 | dcs_cfg |= (u8)offset; |
162 | 184 | ||
@@ -168,8 +190,8 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
168 | WM8993_DCS_TRIG_DAC_WR_0 | | 190 | WM8993_DCS_TRIG_DAC_WR_0 | |
169 | WM8993_DCS_TRIG_DAC_WR_1); | 191 | WM8993_DCS_TRIG_DAC_WR_1); |
170 | } else { | 192 | } else { |
171 | dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 193 | dcs_cfg = reg_r << WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
172 | dcs_cfg |= reg_r; | 194 | dcs_cfg |= reg_l; |
173 | } | 195 | } |
174 | 196 | ||
175 | /* Save the callibrated offset if we're in class W mode and | 197 | /* Save the callibrated offset if we're in class W mode and |
@@ -195,7 +217,7 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, | |||
195 | 217 | ||
196 | /* If we're applying an offset correction then updating the | 218 | /* If we're applying an offset correction then updating the |
197 | * callibration would be likely to introduce further offsets. */ | 219 | * callibration would be likely to introduce further offsets. */ |
198 | if (hubs->dcs_codes) | 220 | if (hubs->dcs_codes || hubs->no_series_update) |
199 | return ret; | 221 | return ret; |
200 | 222 | ||
201 | /* Only need to do this if the outputs are active */ | 223 | /* Only need to do this if the outputs are active */ |
@@ -599,9 +621,6 @@ SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0, | |||
599 | SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0, | 621 | SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0, |
600 | in2r_pga, ARRAY_SIZE(in2r_pga)), | 622 | in2r_pga, ARRAY_SIZE(in2r_pga)), |
601 | 623 | ||
602 | /* Dummy widgets to represent differential paths */ | ||
603 | SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
604 | |||
605 | SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0, | 624 | SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0, |
606 | mixinl, ARRAY_SIZE(mixinl)), | 625 | mixinl, ARRAY_SIZE(mixinl)), |
607 | SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0, | 626 | SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0, |
@@ -867,8 +886,11 @@ EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_controls); | |||
867 | int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, | 886 | int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, |
868 | int lineout1_diff, int lineout2_diff) | 887 | int lineout1_diff, int lineout2_diff) |
869 | { | 888 | { |
889 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | ||
870 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 890 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
871 | 891 | ||
892 | init_completion(&hubs->dcs_done); | ||
893 | |||
872 | snd_soc_dapm_add_routes(dapm, analogue_routes, | 894 | snd_soc_dapm_add_routes(dapm, analogue_routes, |
873 | ARRAY_SIZE(analogue_routes)); | 895 | ARRAY_SIZE(analogue_routes)); |
874 | 896 | ||
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index f8a5e976b5e6..676b1252ab91 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h | |||
@@ -14,6 +14,9 @@ | |||
14 | #ifndef _WM_HUBS_H | 14 | #ifndef _WM_HUBS_H |
15 | #define _WM_HUBS_H | 15 | #define _WM_HUBS_H |
16 | 16 | ||
17 | #include <linux/completion.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | |||
17 | struct snd_soc_codec; | 20 | struct snd_soc_codec; |
18 | 21 | ||
19 | extern const unsigned int wm_hubs_spkmix_tlv[]; | 22 | extern const unsigned int wm_hubs_spkmix_tlv[]; |
@@ -23,9 +26,14 @@ struct wm_hubs_data { | |||
23 | int dcs_codes; | 26 | int dcs_codes; |
24 | int dcs_readback_mode; | 27 | int dcs_readback_mode; |
25 | int hp_startup_mode; | 28 | int hp_startup_mode; |
29 | int series_startup; | ||
30 | int no_series_update; | ||
26 | 31 | ||
27 | bool class_w; | 32 | bool class_w; |
28 | u16 class_w_dcs; | 33 | u16 class_w_dcs; |
34 | |||
35 | bool dcs_done_irq; | ||
36 | struct completion dcs_done; | ||
29 | }; | 37 | }; |
30 | 38 | ||
31 | extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); | 39 | extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); |
@@ -36,4 +44,6 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *, | |||
36 | int jd_scthr, int jd_thr, | 44 | int jd_scthr, int jd_thr, |
37 | int micbias1_lvl, int micbias2_lvl); | 45 | int micbias1_lvl, int micbias2_lvl); |
38 | 46 | ||
47 | extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); | ||
48 | |||
39 | #endif | 49 | #endif |
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 9d35b8c1a624..a49e667373bc 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c | |||
@@ -46,11 +46,28 @@ static void print_buf_info(int slot, char *name) | |||
46 | } | 46 | } |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #define DAVINCI_PCM_FMTBITS (\ | ||
50 | SNDRV_PCM_FMTBIT_S8 |\ | ||
51 | SNDRV_PCM_FMTBIT_U8 |\ | ||
52 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
53 | SNDRV_PCM_FMTBIT_S16_BE |\ | ||
54 | SNDRV_PCM_FMTBIT_U16_LE |\ | ||
55 | SNDRV_PCM_FMTBIT_U16_BE |\ | ||
56 | SNDRV_PCM_FMTBIT_S24_LE |\ | ||
57 | SNDRV_PCM_FMTBIT_S24_BE |\ | ||
58 | SNDRV_PCM_FMTBIT_U24_LE |\ | ||
59 | SNDRV_PCM_FMTBIT_U24_BE |\ | ||
60 | SNDRV_PCM_FMTBIT_S32_LE |\ | ||
61 | SNDRV_PCM_FMTBIT_S32_BE |\ | ||
62 | SNDRV_PCM_FMTBIT_U32_LE |\ | ||
63 | SNDRV_PCM_FMTBIT_U32_BE) | ||
64 | |||
49 | static struct snd_pcm_hardware pcm_hardware_playback = { | 65 | static struct snd_pcm_hardware pcm_hardware_playback = { |
50 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 66 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
51 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 67 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
52 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), | 68 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME| |
53 | .formats = (SNDRV_PCM_FMTBIT_S16_LE), | 69 | SNDRV_PCM_INFO_BATCH), |
70 | .formats = DAVINCI_PCM_FMTBITS, | ||
54 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | | 71 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | |
55 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | | 72 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | |
56 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | | 73 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
@@ -59,7 +76,7 @@ static struct snd_pcm_hardware pcm_hardware_playback = { | |||
59 | .rate_min = 8000, | 76 | .rate_min = 8000, |
60 | .rate_max = 96000, | 77 | .rate_max = 96000, |
61 | .channels_min = 2, | 78 | .channels_min = 2, |
62 | .channels_max = 2, | 79 | .channels_max = 384, |
63 | .buffer_bytes_max = 128 * 1024, | 80 | .buffer_bytes_max = 128 * 1024, |
64 | .period_bytes_min = 32, | 81 | .period_bytes_min = 32, |
65 | .period_bytes_max = 8 * 1024, | 82 | .period_bytes_max = 8 * 1024, |
@@ -71,8 +88,9 @@ static struct snd_pcm_hardware pcm_hardware_playback = { | |||
71 | static struct snd_pcm_hardware pcm_hardware_capture = { | 88 | static struct snd_pcm_hardware pcm_hardware_capture = { |
72 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 89 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
73 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 90 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
74 | SNDRV_PCM_INFO_PAUSE), | 91 | SNDRV_PCM_INFO_PAUSE | |
75 | .formats = (SNDRV_PCM_FMTBIT_S16_LE), | 92 | SNDRV_PCM_INFO_BATCH), |
93 | .formats = DAVINCI_PCM_FMTBITS, | ||
76 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | | 94 | .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | |
77 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | | 95 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | |
78 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | | 96 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
@@ -81,7 +99,7 @@ static struct snd_pcm_hardware pcm_hardware_capture = { | |||
81 | .rate_min = 8000, | 99 | .rate_min = 8000, |
82 | .rate_max = 96000, | 100 | .rate_max = 96000, |
83 | .channels_min = 2, | 101 | .channels_min = 2, |
84 | .channels_max = 2, | 102 | .channels_max = 384, |
85 | .buffer_bytes_max = 128 * 1024, | 103 | .buffer_bytes_max = 128 * 1024, |
86 | .period_bytes_min = 32, | 104 | .period_bytes_min = 32, |
87 | .period_bytes_max = 8 * 1024, | 105 | .period_bytes_max = 8 * 1024, |
@@ -139,6 +157,22 @@ struct davinci_runtime_data { | |||
139 | struct edmacc_param ram_params; | 157 | struct edmacc_param ram_params; |
140 | }; | 158 | }; |
141 | 159 | ||
160 | static void davinci_pcm_period_elapsed(struct snd_pcm_substream *substream) | ||
161 | { | ||
162 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | ||
163 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
164 | |||
165 | prtd->period++; | ||
166 | if (unlikely(prtd->period >= runtime->periods)) | ||
167 | prtd->period = 0; | ||
168 | } | ||
169 | |||
170 | static void davinci_pcm_period_reset(struct snd_pcm_substream *substream) | ||
171 | { | ||
172 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | ||
173 | |||
174 | prtd->period = 0; | ||
175 | } | ||
142 | /* | 176 | /* |
143 | * Not used with ping/pong | 177 | * Not used with ping/pong |
144 | */ | 178 | */ |
@@ -199,10 +233,6 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) | |||
199 | else | 233 | else |
200 | edma_set_transfer_params(link, acnt, fifo_level, count, | 234 | edma_set_transfer_params(link, acnt, fifo_level, count, |
201 | fifo_level, ABSYNC); | 235 | fifo_level, ABSYNC); |
202 | |||
203 | prtd->period++; | ||
204 | if (unlikely(prtd->period >= runtime->periods)) | ||
205 | prtd->period = 0; | ||
206 | } | 236 | } |
207 | 237 | ||
208 | static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) | 238 | static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) |
@@ -217,12 +247,13 @@ static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) | |||
217 | return; | 247 | return; |
218 | 248 | ||
219 | if (snd_pcm_running(substream)) { | 249 | if (snd_pcm_running(substream)) { |
250 | spin_lock(&prtd->lock); | ||
220 | if (prtd->ram_channel < 0) { | 251 | if (prtd->ram_channel < 0) { |
221 | /* No ping/pong must fix up link dma data*/ | 252 | /* No ping/pong must fix up link dma data*/ |
222 | spin_lock(&prtd->lock); | ||
223 | davinci_pcm_enqueue_dma(substream); | 253 | davinci_pcm_enqueue_dma(substream); |
224 | spin_unlock(&prtd->lock); | ||
225 | } | 254 | } |
255 | davinci_pcm_period_elapsed(substream); | ||
256 | spin_unlock(&prtd->lock); | ||
226 | snd_pcm_period_elapsed(substream); | 257 | snd_pcm_period_elapsed(substream); |
227 | } | 258 | } |
228 | } | 259 | } |
@@ -425,7 +456,8 @@ static int request_ping_pong(struct snd_pcm_substream *substream, | |||
425 | 456 | ||
426 | edma_read_slot(link, &prtd->asp_params); | 457 | edma_read_slot(link, &prtd->asp_params); |
427 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN); | 458 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN); |
428 | prtd->asp_params.opt |= TCCHEN | EDMA_TCC(prtd->ram_channel & 0x3f); | 459 | prtd->asp_params.opt |= TCCHEN | |
460 | EDMA_TCC(prtd->ram_channel & 0x3f); | ||
429 | edma_write_slot(link, &prtd->asp_params); | 461 | edma_write_slot(link, &prtd->asp_params); |
430 | 462 | ||
431 | /* pong */ | 463 | /* pong */ |
@@ -439,7 +471,7 @@ static int request_ping_pong(struct snd_pcm_substream *substream, | |||
439 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f)); | 471 | prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f)); |
440 | /* interrupt after every pong completion */ | 472 | /* interrupt after every pong completion */ |
441 | prtd->asp_params.opt |= TCINTEN | TCCHEN | | 473 | prtd->asp_params.opt |= TCINTEN | TCCHEN | |
442 | EDMA_TCC(EDMA_CHAN_SLOT(prtd->ram_channel)); | 474 | EDMA_TCC(prtd->ram_channel & 0x3f); |
443 | edma_write_slot(link, &prtd->asp_params); | 475 | edma_write_slot(link, &prtd->asp_params); |
444 | 476 | ||
445 | /* ram */ | 477 | /* ram */ |
@@ -527,6 +559,13 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
527 | 559 | ||
528 | switch (cmd) { | 560 | switch (cmd) { |
529 | case SNDRV_PCM_TRIGGER_START: | 561 | case SNDRV_PCM_TRIGGER_START: |
562 | edma_start(prtd->asp_channel); | ||
563 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | ||
564 | prtd->ram_channel >= 0) { | ||
565 | /* copy 1st iram buffer */ | ||
566 | edma_start(prtd->ram_channel); | ||
567 | } | ||
568 | break; | ||
530 | case SNDRV_PCM_TRIGGER_RESUME: | 569 | case SNDRV_PCM_TRIGGER_RESUME: |
531 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 570 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
532 | edma_resume(prtd->asp_channel); | 571 | edma_resume(prtd->asp_channel); |
@@ -550,6 +589,7 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream) | |||
550 | { | 589 | { |
551 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | 590 | struct davinci_runtime_data *prtd = substream->runtime->private_data; |
552 | 591 | ||
592 | davinci_pcm_period_reset(substream); | ||
553 | if (prtd->ram_channel >= 0) { | 593 | if (prtd->ram_channel >= 0) { |
554 | int ret = ping_pong_dma_setup(substream); | 594 | int ret = ping_pong_dma_setup(substream); |
555 | if (ret < 0) | 595 | if (ret < 0) |
@@ -565,21 +605,31 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream) | |||
565 | print_buf_info(prtd->asp_link[0], "asp_link[0]"); | 605 | print_buf_info(prtd->asp_link[0], "asp_link[0]"); |
566 | print_buf_info(prtd->asp_link[1], "asp_link[1]"); | 606 | print_buf_info(prtd->asp_link[1], "asp_link[1]"); |
567 | 607 | ||
568 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 608 | /* |
569 | /* copy 1st iram buffer */ | 609 | * There is a phase offset of 2 periods between the position |
570 | edma_start(prtd->ram_channel); | 610 | * used by dma setup and the position reported in the pointer |
571 | } | 611 | * function. |
572 | edma_start(prtd->asp_channel); | 612 | * |
613 | * The phase offset, when not using ping-pong buffers, is due to | ||
614 | * the two consecutive calls to davinci_pcm_enqueue_dma() below. | ||
615 | * | ||
616 | * Whereas here, with ping-pong buffers, the phase is due to | ||
617 | * there being an entire buffer transfer complete before the | ||
618 | * first dma completion event triggers davinci_pcm_dma_irq(). | ||
619 | */ | ||
620 | davinci_pcm_period_elapsed(substream); | ||
621 | davinci_pcm_period_elapsed(substream); | ||
622 | |||
573 | return 0; | 623 | return 0; |
574 | } | 624 | } |
575 | prtd->period = 0; | ||
576 | davinci_pcm_enqueue_dma(substream); | 625 | davinci_pcm_enqueue_dma(substream); |
626 | davinci_pcm_period_elapsed(substream); | ||
577 | 627 | ||
578 | /* Copy self-linked parameter RAM entry into master channel */ | 628 | /* Copy self-linked parameter RAM entry into master channel */ |
579 | edma_read_slot(prtd->asp_link[0], &prtd->asp_params); | 629 | edma_read_slot(prtd->asp_link[0], &prtd->asp_params); |
580 | edma_write_slot(prtd->asp_channel, &prtd->asp_params); | 630 | edma_write_slot(prtd->asp_channel, &prtd->asp_params); |
581 | davinci_pcm_enqueue_dma(substream); | 631 | davinci_pcm_enqueue_dma(substream); |
582 | edma_start(prtd->asp_channel); | 632 | davinci_pcm_period_elapsed(substream); |
583 | 633 | ||
584 | return 0; | 634 | return 0; |
585 | } | 635 | } |
@@ -591,51 +641,23 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream) | |||
591 | struct davinci_runtime_data *prtd = runtime->private_data; | 641 | struct davinci_runtime_data *prtd = runtime->private_data; |
592 | unsigned int offset; | 642 | unsigned int offset; |
593 | int asp_count; | 643 | int asp_count; |
594 | dma_addr_t asp_src, asp_dst; | 644 | unsigned int period_size = snd_pcm_lib_period_bytes(substream); |
595 | 645 | ||
646 | /* | ||
647 | * There is a phase offset of 2 periods between the position used by dma | ||
648 | * setup and the position reported in the pointer function. Either +2 in | ||
649 | * the dma setup or -2 here in the pointer function (with wrapping, | ||
650 | * both) accounts for this offset -- choose the latter since it makes | ||
651 | * the first-time setup clearer. | ||
652 | */ | ||
596 | spin_lock(&prtd->lock); | 653 | spin_lock(&prtd->lock); |
597 | if (prtd->ram_channel >= 0) { | 654 | asp_count = prtd->period - 2; |
598 | int ram_count; | ||
599 | int mod_ram; | ||
600 | dma_addr_t ram_src, ram_dst; | ||
601 | unsigned int period_size = snd_pcm_lib_period_bytes(substream); | ||
602 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
603 | /* reading ram before asp should be safe | ||
604 | * as long as the asp transfers less than a ping size | ||
605 | * of bytes between the 2 reads | ||
606 | */ | ||
607 | edma_get_position(prtd->ram_channel, | ||
608 | &ram_src, &ram_dst); | ||
609 | edma_get_position(prtd->asp_channel, | ||
610 | &asp_src, &asp_dst); | ||
611 | asp_count = asp_src - prtd->asp_params.src; | ||
612 | ram_count = ram_src - prtd->ram_params.src; | ||
613 | mod_ram = ram_count % period_size; | ||
614 | mod_ram -= asp_count; | ||
615 | if (mod_ram < 0) | ||
616 | mod_ram += period_size; | ||
617 | else if (mod_ram == 0) { | ||
618 | if (snd_pcm_running(substream)) | ||
619 | mod_ram += period_size; | ||
620 | } | ||
621 | ram_count -= mod_ram; | ||
622 | if (ram_count < 0) | ||
623 | ram_count += period_size * runtime->periods; | ||
624 | } else { | ||
625 | edma_get_position(prtd->ram_channel, | ||
626 | &ram_src, &ram_dst); | ||
627 | ram_count = ram_dst - prtd->ram_params.dst; | ||
628 | } | ||
629 | asp_count = ram_count; | ||
630 | } else { | ||
631 | edma_get_position(prtd->asp_channel, &asp_src, &asp_dst); | ||
632 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
633 | asp_count = asp_src - runtime->dma_addr; | ||
634 | else | ||
635 | asp_count = asp_dst - runtime->dma_addr; | ||
636 | } | ||
637 | spin_unlock(&prtd->lock); | 655 | spin_unlock(&prtd->lock); |
638 | 656 | ||
657 | if (asp_count < 0) | ||
658 | asp_count += runtime->periods; | ||
659 | asp_count *= period_size; | ||
660 | |||
639 | offset = bytes_to_frames(runtime, asp_count); | 661 | offset = bytes_to_frames(runtime, asp_count); |
640 | if (offset >= runtime->buffer_size) | 662 | if (offset >= runtime->buffer_size) |
641 | offset = 0; | 663 | offset = 0; |
@@ -811,9 +833,11 @@ static void davinci_pcm_free(struct snd_pcm *pcm) | |||
811 | 833 | ||
812 | static u64 davinci_pcm_dmamask = 0xffffffff; | 834 | static u64 davinci_pcm_dmamask = 0xffffffff; |
813 | 835 | ||
814 | static int davinci_pcm_new(struct snd_card *card, | 836 | static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd) |
815 | struct snd_soc_dai *dai, struct snd_pcm *pcm) | ||
816 | { | 837 | { |
838 | struct snd_card *card = rtd->card->snd_card; | ||
839 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
840 | struct snd_pcm *pcm = rtd->pcm; | ||
817 | int ret; | 841 | int ret; |
818 | 842 | ||
819 | if (!card->dev->dma_mask) | 843 | if (!card->dev->dma_mask) |
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c index a456e491155f..e27c417da437 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/ep93xx/ep93xx-pcm.c | |||
@@ -266,9 +266,11 @@ static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
266 | 266 | ||
267 | static u64 ep93xx_pcm_dmamask = 0xffffffff; | 267 | static u64 ep93xx_pcm_dmamask = 0xffffffff; |
268 | 268 | ||
269 | static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | 269 | static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd) |
270 | struct snd_pcm *pcm) | ||
271 | { | 270 | { |
271 | struct snd_card *card = rtd->card->snd_card; | ||
272 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
273 | struct snd_pcm *pcm = rtd->pcm; | ||
272 | int ret = 0; | 274 | int ret = 0; |
273 | 275 | ||
274 | if (!card->dev->dma_mask) | 276 | if (!card->dev->dma_mask) |
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 6680c0b4d203..732208c8c0b4 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c | |||
@@ -294,9 +294,11 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id) | |||
294 | * Regardless of where the memory is actually allocated, since the device can | 294 | * Regardless of where the memory is actually allocated, since the device can |
295 | * technically DMA to any 36-bit address, we do need to set the DMA mask to 36. | 295 | * technically DMA to any 36-bit address, we do need to set the DMA mask to 36. |
296 | */ | 296 | */ |
297 | static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, | 297 | static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd) |
298 | struct snd_pcm *pcm) | ||
299 | { | 298 | { |
299 | struct snd_card *card = rtd->card->snd_card; | ||
300 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
301 | struct snd_pcm *pcm = rtd->pcm; | ||
300 | static u64 fsl_dma_dmamask = DMA_BIT_MASK(36); | 302 | static u64 fsl_dma_dmamask = DMA_BIT_MASK(36); |
301 | int ret; | 303 | int ret; |
302 | 304 | ||
@@ -939,7 +941,7 @@ static int __devinit fsl_soc_dma_probe(struct platform_device *pdev) | |||
939 | 941 | ||
940 | iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL); | 942 | iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL); |
941 | if (iprop) | 943 | if (iprop) |
942 | dma->ssi_fifo_depth = *iprop; | 944 | dma->ssi_fifo_depth = be32_to_cpup(iprop); |
943 | else | 945 | else |
944 | /* Older 8610 DTs didn't have the fifo-depth property */ | 946 | /* Older 8610 DTs didn't have the fifo-depth property */ |
945 | dma->ssi_fifo_depth = 8; | 947 | dma->ssi_fifo_depth = 8; |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 313e0ccedd5b..d48afea5d93d 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -678,7 +678,12 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) | |||
678 | kfree(ssi_private); | 678 | kfree(ssi_private); |
679 | return ret; | 679 | return ret; |
680 | } | 680 | } |
681 | ssi_private->ssi = ioremap(res.start, 1 + res.end - res.start); | 681 | ssi_private->ssi = of_iomap(np, 0); |
682 | if (!ssi_private->ssi) { | ||
683 | dev_err(&pdev->dev, "could not map device resources\n"); | ||
684 | kfree(ssi_private); | ||
685 | return -ENOMEM; | ||
686 | } | ||
682 | ssi_private->ssi_phys = res.start; | 687 | ssi_private->ssi_phys = res.start; |
683 | ssi_private->irq = irq_of_parse_and_map(np, 0); | 688 | ssi_private->irq = irq_of_parse_and_map(np, 0); |
684 | 689 | ||
@@ -691,7 +696,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) | |||
691 | /* Determine the FIFO depth. */ | 696 | /* Determine the FIFO depth. */ |
692 | iprop = of_get_property(np, "fsl,fifo-depth", NULL); | 697 | iprop = of_get_property(np, "fsl,fifo-depth", NULL); |
693 | if (iprop) | 698 | if (iprop) |
694 | ssi_private->fifo_depth = *iprop; | 699 | ssi_private->fifo_depth = be32_to_cpup(iprop); |
695 | else | 700 | else |
696 | /* Older 8610 DTs didn't have the fifo-depth property */ | 701 | /* Older 8610 DTs didn't have the fifo-depth property */ |
697 | ssi_private->fifo_depth = 8; | 702 | ssi_private->fifo_depth = 8; |
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index fff695ccdd3e..19ad0c1be67e 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c | |||
@@ -299,10 +299,11 @@ static struct snd_pcm_ops psc_dma_ops = { | |||
299 | }; | 299 | }; |
300 | 300 | ||
301 | static u64 psc_dma_dmamask = 0xffffffff; | 301 | static u64 psc_dma_dmamask = 0xffffffff; |
302 | static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai, | 302 | static int psc_dma_new(struct snd_soc_pcm_runtime *rtd) |
303 | struct snd_pcm *pcm) | ||
304 | { | 303 | { |
305 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; | 304 | struct snd_card *card = rtd->card->snd_card; |
305 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
306 | struct snd_pcm *pcm = rtd->pcm; | ||
306 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); | 307 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); |
307 | size_t size = psc_dma_hardware.buffer_bytes_max; | 308 | size_t size = psc_dma_hardware.buffer_bytes_max; |
308 | int rc = 0; | 309 | int rc = 0; |
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index c16c6b2eff95..a19297959587 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c | |||
@@ -233,7 +233,7 @@ static int get_parent_cell_index(struct device_node *np) | |||
233 | if (!iprop) | 233 | if (!iprop) |
234 | return -1; | 234 | return -1; |
235 | 235 | ||
236 | return *iprop; | 236 | return be32_to_cpup(iprop); |
237 | } | 237 | } |
238 | 238 | ||
239 | /** | 239 | /** |
@@ -258,7 +258,7 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len) | |||
258 | if (!iprop) | 258 | if (!iprop) |
259 | return -EINVAL; | 259 | return -EINVAL; |
260 | 260 | ||
261 | addr = *iprop; | 261 | addr = be32_to_cpup(iprop); |
262 | 262 | ||
263 | bus = get_parent_cell_index(np); | 263 | bus = get_parent_cell_index(np); |
264 | if (bus < 0) | 264 | if (bus < 0) |
@@ -305,7 +305,7 @@ static int get_dma_channel(struct device_node *ssi_np, | |||
305 | return -EINVAL; | 305 | return -EINVAL; |
306 | } | 306 | } |
307 | 307 | ||
308 | *dma_channel_id = *iprop; | 308 | *dma_channel_id = be32_to_cpup(iprop); |
309 | *dma_id = get_parent_cell_index(dma_channel_np); | 309 | *dma_id = get_parent_cell_index(dma_channel_np); |
310 | of_node_put(dma_channel_np); | 310 | of_node_put(dma_channel_np); |
311 | 311 | ||
@@ -379,7 +379,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) | |||
379 | ret = -EINVAL; | 379 | ret = -EINVAL; |
380 | goto error; | 380 | goto error; |
381 | } | 381 | } |
382 | machine_data->ssi_id = *iprop; | 382 | machine_data->ssi_id = be32_to_cpup(iprop); |
383 | 383 | ||
384 | /* Get the serial format and clock direction. */ | 384 | /* Get the serial format and clock direction. */ |
385 | sprop = of_get_property(np, "fsl,mode", NULL); | 385 | sprop = of_get_property(np, "fsl,mode", NULL); |
@@ -405,7 +405,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) | |||
405 | ret = -EINVAL; | 405 | ret = -EINVAL; |
406 | goto error; | 406 | goto error; |
407 | } | 407 | } |
408 | machine_data->clk_frequency = *iprop; | 408 | machine_data->clk_frequency = be32_to_cpup(iprop); |
409 | } else if (strcasecmp(sprop, "i2s-master") == 0) { | 409 | } else if (strcasecmp(sprop, "i2s-master") == 0) { |
410 | machine_data->dai_format = SND_SOC_DAIFMT_I2S; | 410 | machine_data->dai_format = SND_SOC_DAIFMT_I2S; |
411 | machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; | 411 | machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; |
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 66e0b68af147..8fa4d5f8eda1 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c | |||
@@ -232,7 +232,7 @@ static int get_parent_cell_index(struct device_node *np) | |||
232 | 232 | ||
233 | iprop = of_get_property(parent, "cell-index", NULL); | 233 | iprop = of_get_property(parent, "cell-index", NULL); |
234 | if (iprop) | 234 | if (iprop) |
235 | ret = *iprop; | 235 | ret = be32_to_cpup(iprop); |
236 | 236 | ||
237 | of_node_put(parent); | 237 | of_node_put(parent); |
238 | 238 | ||
@@ -261,7 +261,7 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len) | |||
261 | if (!iprop) | 261 | if (!iprop) |
262 | return -EINVAL; | 262 | return -EINVAL; |
263 | 263 | ||
264 | addr = *iprop; | 264 | addr = be32_to_cpup(iprop); |
265 | 265 | ||
266 | bus = get_parent_cell_index(np); | 266 | bus = get_parent_cell_index(np); |
267 | if (bus < 0) | 267 | if (bus < 0) |
@@ -308,7 +308,7 @@ static int get_dma_channel(struct device_node *ssi_np, | |||
308 | return -EINVAL; | 308 | return -EINVAL; |
309 | } | 309 | } |
310 | 310 | ||
311 | *dma_channel_id = *iprop; | 311 | *dma_channel_id = be32_to_cpup(iprop); |
312 | *dma_id = get_parent_cell_index(dma_channel_np); | 312 | *dma_id = get_parent_cell_index(dma_channel_np); |
313 | of_node_put(dma_channel_np); | 313 | of_node_put(dma_channel_np); |
314 | 314 | ||
@@ -379,7 +379,7 @@ static int p1022_ds_probe(struct platform_device *pdev) | |||
379 | ret = -EINVAL; | 379 | ret = -EINVAL; |
380 | goto error; | 380 | goto error; |
381 | } | 381 | } |
382 | mdata->ssi_id = *iprop; | 382 | mdata->ssi_id = be32_to_cpup(iprop); |
383 | 383 | ||
384 | /* Get the serial format and clock direction. */ | 384 | /* Get the serial format and clock direction. */ |
385 | sprop = of_get_property(np, "fsl,mode", NULL); | 385 | sprop = of_get_property(np, "fsl,mode", NULL); |
@@ -405,7 +405,7 @@ static int p1022_ds_probe(struct platform_device *pdev) | |||
405 | ret = -EINVAL; | 405 | ret = -EINVAL; |
406 | goto error; | 406 | goto error; |
407 | } | 407 | } |
408 | mdata->clk_frequency = *iprop; | 408 | mdata->clk_frequency = be32_to_cpup(iprop); |
409 | } else if (strcasecmp(sprop, "i2s-master") == 0) { | 409 | } else if (strcasecmp(sprop, "i2s-master") == 0) { |
410 | mdata->dai_format = SND_SOC_DAIFMT_I2S; | 410 | mdata->dai_format = SND_SOC_DAIFMT_I2S; |
411 | mdata->codec_clk_direction = SND_SOC_CLOCK_IN; | 411 | mdata->codec_clk_direction = SND_SOC_CLOCK_IN; |
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c index 413b78da248f..309c59e6fb6c 100644 --- a/sound/soc/imx/imx-pcm-fiq.c +++ b/sound/soc/imx/imx-pcm-fiq.c | |||
@@ -238,12 +238,14 @@ static struct snd_pcm_ops imx_pcm_ops = { | |||
238 | 238 | ||
239 | static int ssi_irq = 0; | 239 | static int ssi_irq = 0; |
240 | 240 | ||
241 | static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai, | 241 | static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd) |
242 | struct snd_pcm *pcm) | ||
243 | { | 242 | { |
243 | struct snd_card *card = rtd->card->snd_card; | ||
244 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
245 | struct snd_pcm *pcm = rtd->pcm; | ||
244 | int ret; | 246 | int ret; |
245 | 247 | ||
246 | ret = imx_pcm_new(card, dai, pcm); | 248 | ret = imx_pcm_new(rtd); |
247 | if (ret) | 249 | if (ret) |
248 | return ret; | 250 | return ret; |
249 | 251 | ||
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 61fceb09cdb5..10a8e2783751 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c | |||
@@ -388,10 +388,11 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | |||
388 | 388 | ||
389 | static u64 imx_pcm_dmamask = DMA_BIT_MASK(32); | 389 | static u64 imx_pcm_dmamask = DMA_BIT_MASK(32); |
390 | 390 | ||
391 | int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | 391 | int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) |
392 | struct snd_pcm *pcm) | ||
393 | { | 392 | { |
394 | 393 | struct snd_card *card = rtd->card->snd_card; | |
394 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
395 | struct snd_pcm *pcm = rtd->pcm; | ||
395 | int ret = 0; | 396 | int ret = 0; |
396 | 397 | ||
397 | if (!card->dev->dma_mask) | 398 | if (!card->dev->dma_mask) |
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h index dc8a87530e3e..0a84cec3599e 100644 --- a/sound/soc/imx/imx-ssi.h +++ b/sound/soc/imx/imx-ssi.h | |||
@@ -225,8 +225,7 @@ struct snd_soc_platform *imx_ssi_dma_mx2_init(struct platform_device *pdev, | |||
225 | struct imx_ssi *ssi); | 225 | struct imx_ssi *ssi); |
226 | 226 | ||
227 | int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma); | 227 | int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma); |
228 | int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | 228 | int imx_pcm_new(struct snd_soc_pcm_runtime *rtd); |
229 | struct snd_pcm *pcm); | ||
230 | void imx_pcm_free(struct snd_pcm *pcm); | 229 | void imx_pcm_free(struct snd_pcm *pcm); |
231 | 230 | ||
232 | /* | 231 | /* |
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c index fb1483f7c966..a7c9578be983 100644 --- a/sound/soc/jz4740/jz4740-pcm.c +++ b/sound/soc/jz4740/jz4740-pcm.c | |||
@@ -299,9 +299,11 @@ static void jz4740_pcm_free(struct snd_pcm *pcm) | |||
299 | 299 | ||
300 | static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32); | 300 | static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32); |
301 | 301 | ||
302 | int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | 302 | int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd) |
303 | struct snd_pcm *pcm) | ||
304 | { | 303 | { |
304 | struct snd_card *card = rtd->card->snd_card; | ||
305 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
306 | struct snd_pcm *pcm = rtd->pcm; | ||
305 | int ret = 0; | 307 | int ret = 0; |
306 | 308 | ||
307 | if (!card->dev->dma_mask) | 309 | if (!card->dev->dma_mask) |
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index e13c6ce46328..cd33de1c5b7a 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c | |||
@@ -312,9 +312,11 @@ static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm, | |||
312 | return 0; | 312 | return 0; |
313 | } | 313 | } |
314 | 314 | ||
315 | static int kirkwood_dma_new(struct snd_card *card, | 315 | static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd) |
316 | struct snd_soc_dai *dai, struct snd_pcm *pcm) | ||
317 | { | 316 | { |
317 | struct snd_card *card = rtd->card->snd_card; | ||
318 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
319 | struct snd_pcm *pcm = rtd->pcm; | ||
318 | int ret; | 320 | int ret; |
319 | 321 | ||
320 | if (!card->dev->dma_mask) | 322 | if (!card->dev->dma_mask) |
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c index 5a946b4115a2..3e7826058efe 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/mid-x86/sst_platform.c | |||
@@ -402,9 +402,10 @@ static void sst_pcm_free(struct snd_pcm *pcm) | |||
402 | snd_pcm_lib_preallocate_free_for_all(pcm); | 402 | snd_pcm_lib_preallocate_free_for_all(pcm); |
403 | } | 403 | } |
404 | 404 | ||
405 | int sst_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | 405 | int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) |
406 | struct snd_pcm *pcm) | ||
407 | { | 406 | { |
407 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
408 | struct snd_pcm *pcm = rtd->pcm; | ||
408 | int retval = 0; | 409 | int retval = 0; |
409 | 410 | ||
410 | pr_debug("sst_pcm_new called\n"); | 411 | pr_debug("sst_pcm_new called\n"); |
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index dac6732da969..9c0edad90d8b 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c | |||
@@ -356,7 +356,7 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev) | |||
356 | nuc900_audio->irq_num = platform_get_irq(pdev, 0); | 356 | nuc900_audio->irq_num = platform_get_irq(pdev, 0); |
357 | if (!nuc900_audio->irq_num) { | 357 | if (!nuc900_audio->irq_num) { |
358 | ret = -EBUSY; | 358 | ret = -EBUSY; |
359 | goto out2; | 359 | goto out3; |
360 | } | 360 | } |
361 | 361 | ||
362 | nuc900_ac97_data = nuc900_audio; | 362 | nuc900_ac97_data = nuc900_audio; |
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c index 8263f56dc665..d589ef14e917 100644 --- a/sound/soc/nuc900/nuc900-pcm.c +++ b/sound/soc/nuc900/nuc900-pcm.c | |||
@@ -315,9 +315,12 @@ static void nuc900_dma_free_dma_buffers(struct snd_pcm *pcm) | |||
315 | } | 315 | } |
316 | 316 | ||
317 | static u64 nuc900_pcm_dmamask = DMA_BIT_MASK(32); | 317 | static u64 nuc900_pcm_dmamask = DMA_BIT_MASK(32); |
318 | static int nuc900_dma_new(struct snd_card *card, | 318 | static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd) |
319 | struct snd_soc_dai *dai, struct snd_pcm *pcm) | ||
320 | { | 319 | { |
320 | struct snd_card *card = rtd->card->snd_card; | ||
321 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
322 | struct snd_pcm *pcm = rtd->pcm; | ||
323 | |||
321 | if (!card->dev->dma_mask) | 324 | if (!card->dev->dma_mask) |
322 | card->dev->dma_mask = &nuc900_pcm_dmamask; | 325 | card->dev->dma_mask = &nuc900_pcm_dmamask; |
323 | if (!card->dev->coherent_dma_mask) | 326 | if (!card->dev->coherent_dma_mask) |
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 99054cf1f68f..fe83d0d176be 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
@@ -9,6 +9,9 @@ config SND_OMAP_SOC_MCBSP | |||
9 | config SND_OMAP_SOC_MCPDM | 9 | config SND_OMAP_SOC_MCPDM |
10 | tristate | 10 | tristate |
11 | 11 | ||
12 | config SND_OMAP_SOC_HDMI | ||
13 | tristate | ||
14 | |||
12 | config SND_OMAP_SOC_N810 | 15 | config SND_OMAP_SOC_N810 |
13 | tristate "SoC Audio support for Nokia N810" | 16 | tristate "SoC Audio support for Nokia N810" |
14 | depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C | 17 | depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C |
@@ -100,6 +103,14 @@ config SND_OMAP_SOC_SDP4430 | |||
100 | Say Y if you want to add support for SoC audio on Texas Instruments | 103 | Say Y if you want to add support for SoC audio on Texas Instruments |
101 | SDP4430. | 104 | SDP4430. |
102 | 105 | ||
106 | config SND_OMAP_SOC_OMAP4_HDMI | ||
107 | tristate "SoC Audio support for Texas Instruments OMAP4 HDMI" | ||
108 | depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS && ARCH_OMAP4 | ||
109 | select SND_OMAP_SOC_HDMI | ||
110 | help | ||
111 | Say Y if you want to add support for SoC HDMI audio on Texas Instruments | ||
112 | OMAP4 chips | ||
113 | |||
103 | config SND_OMAP_SOC_OMAP3_PANDORA | 114 | config SND_OMAP_SOC_OMAP3_PANDORA |
104 | tristate "SoC Audio support for OMAP3 Pandora" | 115 | tristate "SoC Audio support for OMAP3 Pandora" |
105 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA | 116 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA |
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 6c2c87eed5bb..59e2c8d1e38d 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile | |||
@@ -2,10 +2,12 @@ | |||
2 | snd-soc-omap-objs := omap-pcm.o | 2 | snd-soc-omap-objs := omap-pcm.o |
3 | snd-soc-omap-mcbsp-objs := omap-mcbsp.o | 3 | snd-soc-omap-mcbsp-objs := omap-mcbsp.o |
4 | snd-soc-omap-mcpdm-objs := omap-mcpdm.o mcpdm.o | 4 | snd-soc-omap-mcpdm-objs := omap-mcpdm.o mcpdm.o |
5 | snd-soc-omap-hdmi-objs := omap-hdmi.o | ||
5 | 6 | ||
6 | obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o | 7 | obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o |
7 | obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o | 8 | obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o |
8 | obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o | 9 | obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o |
10 | obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o | ||
9 | 11 | ||
10 | # OMAP Machine Support | 12 | # OMAP Machine Support |
11 | snd-soc-n810-objs := n810.o | 13 | snd-soc-n810-objs := n810.o |
@@ -21,6 +23,7 @@ snd-soc-omap3pandora-objs := omap3pandora.o | |||
21 | snd-soc-omap3beagle-objs := omap3beagle.o | 23 | snd-soc-omap3beagle-objs := omap3beagle.o |
22 | snd-soc-zoom2-objs := zoom2.o | 24 | snd-soc-zoom2-objs := zoom2.o |
23 | snd-soc-igep0020-objs := igep0020.o | 25 | snd-soc-igep0020-objs := igep0020.o |
26 | snd-soc-omap4-hdmi-objs := omap4-hdmi-card.o | ||
24 | 27 | ||
25 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o | 28 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o |
26 | obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o | 29 | obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o |
@@ -36,3 +39,4 @@ obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o | |||
36 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o | 39 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o |
37 | obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o | 40 | obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o |
38 | obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o | 41 | obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o |
42 | obj-$(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) += snd-soc-omap4-hdmi.o | ||
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 462cbcbea74a..b40095a19883 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c | |||
@@ -427,7 +427,8 @@ static struct snd_soc_ops ams_delta_ops = { | |||
427 | 427 | ||
428 | /* Board specific codec bias level control */ | 428 | /* Board specific codec bias level control */ |
429 | static int ams_delta_set_bias_level(struct snd_soc_card *card, | 429 | static int ams_delta_set_bias_level(struct snd_soc_card *card, |
430 | enum snd_soc_bias_level level) | 430 | struct snd_soc_dapm_context *dapm, |
431 | enum snd_soc_bias_level level) | ||
431 | { | 432 | { |
432 | struct snd_soc_codec *codec = card->rtd->codec; | 433 | struct snd_soc_codec *codec = card->rtd->codec; |
433 | 434 | ||
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c new file mode 100644 index 000000000000..36c6eaeffb02 --- /dev/null +++ b/sound/soc/omap/omap-hdmi.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * omap-hdmi.c | ||
3 | * | ||
4 | * OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors. | ||
5 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
6 | * Authors: Jorge Candelaria <jorge.candelaria@ti.com> | ||
7 | * Ricardo Neri <ricardo.neri@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/init.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/device.h> | ||
28 | #include <sound/core.h> | ||
29 | #include <sound/pcm.h> | ||
30 | #include <sound/pcm_params.h> | ||
31 | #include <sound/initval.h> | ||
32 | #include <sound/soc.h> | ||
33 | |||
34 | #include <plat/dma.h> | ||
35 | #include "omap-pcm.h" | ||
36 | #include "omap-hdmi.h" | ||
37 | |||
38 | #define DRV_NAME "hdmi-audio-dai" | ||
39 | |||
40 | static struct omap_pcm_dma_data omap_hdmi_dai_dma_params = { | ||
41 | .name = "HDMI playback", | ||
42 | .sync_mode = OMAP_DMA_SYNC_PACKET, | ||
43 | }; | ||
44 | |||
45 | static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream, | ||
46 | struct snd_soc_dai *dai) | ||
47 | { | ||
48 | int err; | ||
49 | /* | ||
50 | * Make sure that the period bytes are multiple of the DMA packet size. | ||
51 | * Largest packet size we use is 32 32-bit words = 128 bytes | ||
52 | */ | ||
53 | err = snd_pcm_hw_constraint_step(substream->runtime, 0, | ||
54 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); | ||
55 | if (err < 0) | ||
56 | return err; | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, | ||
62 | struct snd_pcm_hw_params *params, | ||
63 | struct snd_soc_dai *dai) | ||
64 | { | ||
65 | int err = 0; | ||
66 | |||
67 | switch (params_format(params)) { | ||
68 | case SNDRV_PCM_FORMAT_S16_LE: | ||
69 | omap_hdmi_dai_dma_params.packet_size = 16; | ||
70 | break; | ||
71 | case SNDRV_PCM_FORMAT_S24_LE: | ||
72 | omap_hdmi_dai_dma_params.packet_size = 32; | ||
73 | break; | ||
74 | default: | ||
75 | err = -EINVAL; | ||
76 | } | ||
77 | |||
78 | omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32; | ||
79 | |||
80 | snd_soc_dai_set_dma_data(dai, substream, | ||
81 | &omap_hdmi_dai_dma_params); | ||
82 | |||
83 | return err; | ||
84 | } | ||
85 | |||
86 | static struct snd_soc_dai_ops omap_hdmi_dai_ops = { | ||
87 | .startup = omap_hdmi_dai_startup, | ||
88 | .hw_params = omap_hdmi_dai_hw_params, | ||
89 | }; | ||
90 | |||
91 | static struct snd_soc_dai_driver omap_hdmi_dai = { | ||
92 | .playback = { | ||
93 | .channels_min = 2, | ||
94 | .channels_max = 2, | ||
95 | .rates = OMAP_HDMI_RATES, | ||
96 | .formats = OMAP_HDMI_FORMATS, | ||
97 | }, | ||
98 | .ops = &omap_hdmi_dai_ops, | ||
99 | }; | ||
100 | |||
101 | static __devinit int omap_hdmi_probe(struct platform_device *pdev) | ||
102 | { | ||
103 | int ret; | ||
104 | struct resource *hdmi_rsrc; | ||
105 | |||
106 | hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
107 | if (!hdmi_rsrc) { | ||
108 | dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n"); | ||
109 | return -EINVAL; | ||
110 | } | ||
111 | |||
112 | omap_hdmi_dai_dma_params.port_addr = hdmi_rsrc->start | ||
113 | + OMAP_HDMI_AUDIO_DMA_PORT; | ||
114 | |||
115 | hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
116 | if (!hdmi_rsrc) { | ||
117 | dev_err(&pdev->dev, "Cannot obtain IORESOURCE_DMA HDMI\n"); | ||
118 | return -EINVAL; | ||
119 | } | ||
120 | |||
121 | omap_hdmi_dai_dma_params.dma_req = hdmi_rsrc->start; | ||
122 | |||
123 | ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai); | ||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | static int __devexit omap_hdmi_remove(struct platform_device *pdev) | ||
128 | { | ||
129 | snd_soc_unregister_dai(&pdev->dev); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static struct platform_driver hdmi_dai_driver = { | ||
134 | .driver = { | ||
135 | .name = DRV_NAME, | ||
136 | .owner = THIS_MODULE, | ||
137 | }, | ||
138 | .probe = omap_hdmi_probe, | ||
139 | .remove = __devexit_p(omap_hdmi_remove), | ||
140 | }; | ||
141 | |||
142 | static int __init hdmi_dai_init(void) | ||
143 | { | ||
144 | return platform_driver_register(&hdmi_dai_driver); | ||
145 | } | ||
146 | module_init(hdmi_dai_init); | ||
147 | |||
148 | static void __exit hdmi_dai_exit(void) | ||
149 | { | ||
150 | platform_driver_unregister(&hdmi_dai_driver); | ||
151 | } | ||
152 | module_exit(hdmi_dai_exit); | ||
153 | |||
154 | MODULE_AUTHOR("Jorge Candelaria <jorge.candelaria@ti.com>"); | ||
155 | MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>"); | ||
156 | MODULE_DESCRIPTION("OMAP HDMI SoC Interface"); | ||
157 | MODULE_LICENSE("GPL"); | ||
158 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/omap/omap-hdmi.h b/sound/soc/omap/omap-hdmi.h new file mode 100644 index 000000000000..34c298d5057e --- /dev/null +++ b/sound/soc/omap/omap-hdmi.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * omap-hdmi.h | ||
3 | * | ||
4 | * Definitions for OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors. | ||
5 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
6 | * Authors: Jorge Candelaria <jorge.candelaria@ti.com> | ||
7 | * Ricardo Neri <ricardo.neri@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __OMAP_HDMI_H__ | ||
26 | #define __OMAP_HDMI_H__ | ||
27 | |||
28 | #define OMAP_HDMI_AUDIO_DMA_PORT 0x8c | ||
29 | |||
30 | #define OMAP_HDMI_RATES (SNDRV_PCM_RATE_32000 | \ | ||
31 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | ||
32 | |||
33 | #define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
34 | SNDRV_PCM_FMTBIT_S24_LE) | ||
35 | |||
36 | #endif | ||
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index e6a6b991d05f..b2f5751edae3 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -366,9 +366,11 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
366 | } | 366 | } |
367 | } | 367 | } |
368 | 368 | ||
369 | static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | 369 | static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd) |
370 | struct snd_pcm *pcm) | ||
371 | { | 370 | { |
371 | struct snd_card *card = rtd->card->snd_card; | ||
372 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
373 | struct snd_pcm *pcm = rtd->pcm; | ||
372 | int ret = 0; | 374 | int ret = 0; |
373 | 375 | ||
374 | if (!card->dev->dma_mask) | 376 | if (!card->dev->dma_mask) |
diff --git a/sound/soc/omap/omap4-hdmi-card.c b/sound/soc/omap/omap4-hdmi-card.c new file mode 100644 index 000000000000..9f32615b81f7 --- /dev/null +++ b/sound/soc/omap/omap4-hdmi-card.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * omap4-hdmi-card.c | ||
3 | * | ||
4 | * OMAP ALSA SoC machine driver for TI OMAP4 HDMI | ||
5 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
6 | * Author: Ricardo Neri <ricardo.neri@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <asm/mach-types.h> | ||
27 | #include <video/omapdss.h> | ||
28 | |||
29 | #define DRV_NAME "omap4-hdmi-audio" | ||
30 | |||
31 | static int omap4_hdmi_dai_hw_params(struct snd_pcm_substream *substream, | ||
32 | struct snd_pcm_hw_params *params) | ||
33 | { | ||
34 | int i; | ||
35 | struct omap_overlay_manager *mgr = NULL; | ||
36 | struct device *dev = substream->pcm->card->dev; | ||
37 | |||
38 | /* Find DSS HDMI device */ | ||
39 | for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) { | ||
40 | mgr = omap_dss_get_overlay_manager(i); | ||
41 | if (mgr && mgr->device | ||
42 | && mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) | ||
43 | break; | ||
44 | } | ||
45 | |||
46 | if (i == omap_dss_get_num_overlay_managers()) { | ||
47 | dev_err(dev, "HDMI display device not found!\n"); | ||
48 | return -ENODEV; | ||
49 | } | ||
50 | |||
51 | /* Make sure HDMI is power-on to avoid L3 interconnect errors */ | ||
52 | if (mgr->device->state != OMAP_DSS_DISPLAY_ACTIVE) { | ||
53 | dev_err(dev, "HDMI display is not active!\n"); | ||
54 | return -EIO; | ||
55 | } | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static struct snd_soc_ops omap4_hdmi_dai_ops = { | ||
61 | .hw_params = omap4_hdmi_dai_hw_params, | ||
62 | }; | ||
63 | |||
64 | static struct snd_soc_dai_link omap4_hdmi_dai = { | ||
65 | .name = "HDMI", | ||
66 | .stream_name = "HDMI", | ||
67 | .cpu_dai_name = "hdmi-audio-dai", | ||
68 | .platform_name = "omap-pcm-audio", | ||
69 | .codec_name = "omapdss_hdmi", | ||
70 | .codec_dai_name = "hdmi-audio-codec", | ||
71 | .ops = &omap4_hdmi_dai_ops, | ||
72 | }; | ||
73 | |||
74 | static struct snd_soc_card snd_soc_omap4_hdmi = { | ||
75 | .name = "OMAP4HDMI", | ||
76 | .dai_link = &omap4_hdmi_dai, | ||
77 | .num_links = 1, | ||
78 | }; | ||
79 | |||
80 | static __devinit int omap4_hdmi_probe(struct platform_device *pdev) | ||
81 | { | ||
82 | struct snd_soc_card *card = &snd_soc_omap4_hdmi; | ||
83 | int ret; | ||
84 | |||
85 | card->dev = &pdev->dev; | ||
86 | |||
87 | ret = snd_soc_register_card(card); | ||
88 | if (ret) { | ||
89 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | ||
90 | card->dev = NULL; | ||
91 | return ret; | ||
92 | } | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int __devexit omap4_hdmi_remove(struct platform_device *pdev) | ||
97 | { | ||
98 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
99 | |||
100 | snd_soc_unregister_card(card); | ||
101 | card->dev = NULL; | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static struct platform_driver omap4_hdmi_driver = { | ||
106 | .driver = { | ||
107 | .name = "omap4-hdmi-audio", | ||
108 | .owner = THIS_MODULE, | ||
109 | }, | ||
110 | .probe = omap4_hdmi_probe, | ||
111 | .remove = __devexit_p(omap4_hdmi_remove), | ||
112 | }; | ||
113 | |||
114 | static int __init omap4_hdmi_init(void) | ||
115 | { | ||
116 | return platform_driver_register(&omap4_hdmi_driver); | ||
117 | } | ||
118 | module_init(omap4_hdmi_init); | ||
119 | |||
120 | static void __exit omap4_hdmi_exit(void) | ||
121 | { | ||
122 | platform_driver_unregister(&omap4_hdmi_driver); | ||
123 | } | ||
124 | module_exit(omap4_hdmi_exit); | ||
125 | |||
126 | MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>"); | ||
127 | MODULE_DESCRIPTION("OMAP4 HDMI machine ASoC driver"); | ||
128 | MODULE_LICENSE("GPL"); | ||
129 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index fab20a54e863..c43060053dd7 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c | |||
@@ -85,9 +85,10 @@ static struct snd_pcm_ops pxa2xx_pcm_ops = { | |||
85 | 85 | ||
86 | static u64 pxa2xx_pcm_dmamask = DMA_BIT_MASK(32); | 86 | static u64 pxa2xx_pcm_dmamask = DMA_BIT_MASK(32); |
87 | 87 | ||
88 | static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | 88 | static int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime *rtd) |
89 | struct snd_pcm *pcm) | ||
90 | { | 89 | { |
90 | struct snd_card *card = rtd->card->snd_card; | ||
91 | struct snd_pcm *pcm = rtd->pcm; | ||
91 | int ret = 0; | 92 | int ret = 0; |
92 | 93 | ||
93 | if (!card->dev->dma_mask) | 94 | if (!card->dev->dma_mask) |
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c index ab3ccaec72d2..80c85fd64e1a 100644 --- a/sound/soc/s6000/s6000-pcm.c +++ b/sound/soc/s6000/s6000-pcm.c | |||
@@ -443,10 +443,11 @@ static void s6000_pcm_free(struct snd_pcm *pcm) | |||
443 | 443 | ||
444 | static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32); | 444 | static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32); |
445 | 445 | ||
446 | static int s6000_pcm_new(struct snd_card *card, | 446 | static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime) |
447 | struct snd_soc_dai *dai, struct snd_pcm *pcm) | ||
448 | { | 447 | { |
449 | struct snd_soc_pcm_runtime *runtime = pcm->private_data; | 448 | struct snd_card *card = runtime->card->snd_card; |
449 | struct snd_soc_dai *dai = runtime->cpu_dai; | ||
450 | struct snd_pcm *pcm = runtime->pcm; | ||
450 | struct s6000_pcm_dma_params *params; | 451 | struct s6000_pcm_dma_params *params; |
451 | int res; | 452 | int res; |
452 | 453 | ||
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index d155cbb58e1c..54b0e4b7faf7 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -158,7 +158,7 @@ config SND_SOC_GONI_AQUILA_WM8994 | |||
158 | 158 | ||
159 | config SND_SOC_SAMSUNG_SMDK_SPDIF | 159 | config SND_SOC_SAMSUNG_SMDK_SPDIF |
160 | tristate "SoC S/PDIF Audio support for SMDK" | 160 | tristate "SoC S/PDIF Audio support for SMDK" |
161 | depends on SND_SOC_SAMSUNG && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210) | 161 | depends on SND_SOC_SAMSUNG && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210 || MACH_SMDKV310) |
162 | select SND_SAMSUNG_SPDIF | 162 | select SND_SAMSUNG_SPDIF |
163 | help | 163 | help |
164 | Say Y if you want to add support for SoC S/PDIF audio on the SMDK. | 164 | Say Y if you want to add support for SoC S/PDIF audio on the SMDK. |
@@ -171,9 +171,23 @@ config SND_SOC_SMDK_WM8580_PCM | |||
171 | help | 171 | help |
172 | Say Y if you want to add support for SoC audio on the SMDK. | 172 | Say Y if you want to add support for SoC audio on the SMDK. |
173 | 173 | ||
174 | config SND_SOC_SMDK_WM8994_PCM | ||
175 | tristate "SoC PCM Audio support for WM8994 on SMDK" | ||
176 | depends on SND_SOC_SAMSUNG && (MACH_SMDKC210 || MACH_SMDKV310) | ||
177 | select SND_SOC_WM8994 | ||
178 | select SND_SAMSUNG_PCM | ||
179 | help | ||
180 | Say Y if you want to add support for SoC audio on the SMDK | ||
181 | |||
174 | config SND_SOC_SPEYSIDE | 182 | config SND_SOC_SPEYSIDE |
175 | tristate "Audio support for Wolfson Speyside" | 183 | tristate "Audio support for Wolfson Speyside" |
176 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 | 184 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 |
177 | select SND_SAMSUNG_I2S | 185 | select SND_SAMSUNG_I2S |
178 | select SND_SOC_WM8915 | 186 | select SND_SOC_WM8915 |
179 | select SND_SOC_WM9081 | 187 | select SND_SOC_WM9081 |
188 | |||
189 | config SND_SOC_SPEYSIDE_WM8962 | ||
190 | tristate "Audio support for Wolfson Speyside with WM8962" | ||
191 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 | ||
192 | select SND_SAMSUNG_I2S | ||
193 | select SND_SOC_WM8962 | ||
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 683843a2744f..9eb3b12eb72f 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -35,7 +35,9 @@ snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o | |||
35 | snd-soc-goni-wm8994-objs := goni_wm8994.o | 35 | snd-soc-goni-wm8994-objs := goni_wm8994.o |
36 | snd-soc-smdk-spdif-objs := smdk_spdif.o | 36 | snd-soc-smdk-spdif-objs := smdk_spdif.o |
37 | snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o | 37 | snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o |
38 | snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o | ||
38 | snd-soc-speyside-objs := speyside.o | 39 | snd-soc-speyside-objs := speyside.o |
40 | snd-soc-speyside-wm8962-objs := speyside_wm8962.o | ||
39 | 41 | ||
40 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o | 42 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o |
41 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 43 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
@@ -54,4 +56,6 @@ obj-$(CONFIG_SND_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o | |||
54 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o | 56 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o |
55 | obj-$(CONFIG_SND_SOC_GONI_AQUILA_WM8994) += snd-soc-goni-wm8994.o | 57 | obj-$(CONFIG_SND_SOC_GONI_AQUILA_WM8994) += snd-soc-goni-wm8994.o |
56 | obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o | 58 | obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o |
59 | obj-$(CONFIG_SND_SOC_SMDK_WM8994_PCM) += snd-soc-smdk-wm8994pcm.o | ||
57 | obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o | 60 | obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o |
61 | obj-$(CONFIG_SND_SOC_SPEYSIDE_WM8962) += snd-soc-speyside-wm8962.o | ||
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index 5cb3b880f0d5..9465588b02f2 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c | |||
@@ -425,9 +425,11 @@ static void dma_free_dma_buffers(struct snd_pcm *pcm) | |||
425 | 425 | ||
426 | static u64 dma_mask = DMA_BIT_MASK(32); | 426 | static u64 dma_mask = DMA_BIT_MASK(32); |
427 | 427 | ||
428 | static int dma_new(struct snd_card *card, | 428 | static int dma_new(struct snd_soc_pcm_runtime *rtd) |
429 | struct snd_soc_dai *dai, struct snd_pcm *pcm) | ||
430 | { | 429 | { |
430 | struct snd_card *card = rtd->card->snd_card; | ||
431 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
432 | struct snd_pcm *pcm = rtd->pcm; | ||
431 | int ret = 0; | 433 | int ret = 0; |
432 | 434 | ||
433 | pr_debug("Entered %s\n", __func__); | 435 | pr_debug("Entered %s\n", __func__); |
diff --git a/sound/soc/samsung/i2s-regs.h b/sound/soc/samsung/i2s-regs.h new file mode 100644 index 000000000000..c0e6d9a19efc --- /dev/null +++ b/sound/soc/samsung/i2s-regs.h | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * linux/sound/soc/samsung/i2s-regs.h | ||
3 | * | ||
4 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
5 | * http://www.samsung.com | ||
6 | * | ||
7 | * Samsung I2S driver's register header | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | */ | ||
14 | |||
15 | #ifndef __SND_SOC_SAMSUNG_I2S_REGS_H | ||
16 | #define __SND_SOC_SAMSUNG_I2S_REGS_H | ||
17 | |||
18 | #define I2SCON 0x0 | ||
19 | #define I2SMOD 0x4 | ||
20 | #define I2SFIC 0x8 | ||
21 | #define I2SPSR 0xc | ||
22 | #define I2STXD 0x10 | ||
23 | #define I2SRXD 0x14 | ||
24 | #define I2SFICS 0x18 | ||
25 | #define I2STXDS 0x1c | ||
26 | #define I2SAHB 0x20 | ||
27 | #define I2SSTR0 0x24 | ||
28 | #define I2SSIZE 0x28 | ||
29 | #define I2STRNCNT 0x2c | ||
30 | #define I2SLVL0ADDR 0x30 | ||
31 | #define I2SLVL1ADDR 0x34 | ||
32 | #define I2SLVL2ADDR 0x38 | ||
33 | #define I2SLVL3ADDR 0x3c | ||
34 | |||
35 | #define CON_RSTCLR (1 << 31) | ||
36 | #define CON_FRXOFSTATUS (1 << 26) | ||
37 | #define CON_FRXORINTEN (1 << 25) | ||
38 | #define CON_FTXSURSTAT (1 << 24) | ||
39 | #define CON_FTXSURINTEN (1 << 23) | ||
40 | #define CON_TXSDMA_PAUSE (1 << 20) | ||
41 | #define CON_TXSDMA_ACTIVE (1 << 18) | ||
42 | |||
43 | #define CON_FTXURSTATUS (1 << 17) | ||
44 | #define CON_FTXURINTEN (1 << 16) | ||
45 | #define CON_TXFIFO2_EMPTY (1 << 15) | ||
46 | #define CON_TXFIFO1_EMPTY (1 << 14) | ||
47 | #define CON_TXFIFO2_FULL (1 << 13) | ||
48 | #define CON_TXFIFO1_FULL (1 << 12) | ||
49 | |||
50 | #define CON_LRINDEX (1 << 11) | ||
51 | #define CON_TXFIFO_EMPTY (1 << 10) | ||
52 | #define CON_RXFIFO_EMPTY (1 << 9) | ||
53 | #define CON_TXFIFO_FULL (1 << 8) | ||
54 | #define CON_RXFIFO_FULL (1 << 7) | ||
55 | #define CON_TXDMA_PAUSE (1 << 6) | ||
56 | #define CON_RXDMA_PAUSE (1 << 5) | ||
57 | #define CON_TXCH_PAUSE (1 << 4) | ||
58 | #define CON_RXCH_PAUSE (1 << 3) | ||
59 | #define CON_TXDMA_ACTIVE (1 << 2) | ||
60 | #define CON_RXDMA_ACTIVE (1 << 1) | ||
61 | #define CON_ACTIVE (1 << 0) | ||
62 | |||
63 | #define MOD_OPCLK_CDCLK_OUT (0 << 30) | ||
64 | #define MOD_OPCLK_CDCLK_IN (1 << 30) | ||
65 | #define MOD_OPCLK_BCLK_OUT (2 << 30) | ||
66 | #define MOD_OPCLK_PCLK (3 << 30) | ||
67 | #define MOD_OPCLK_MASK (3 << 30) | ||
68 | #define MOD_TXS_IDMA (1 << 28) /* Sec_TXFIFO use I-DMA */ | ||
69 | |||
70 | #define MOD_BLCS_SHIFT 26 | ||
71 | #define MOD_BLCS_16BIT (0 << MOD_BLCS_SHIFT) | ||
72 | #define MOD_BLCS_8BIT (1 << MOD_BLCS_SHIFT) | ||
73 | #define MOD_BLCS_24BIT (2 << MOD_BLCS_SHIFT) | ||
74 | #define MOD_BLCS_MASK (3 << MOD_BLCS_SHIFT) | ||
75 | #define MOD_BLCP_SHIFT 24 | ||
76 | #define MOD_BLCP_16BIT (0 << MOD_BLCP_SHIFT) | ||
77 | #define MOD_BLCP_8BIT (1 << MOD_BLCP_SHIFT) | ||
78 | #define MOD_BLCP_24BIT (2 << MOD_BLCP_SHIFT) | ||
79 | #define MOD_BLCP_MASK (3 << MOD_BLCP_SHIFT) | ||
80 | |||
81 | #define MOD_C2DD_HHALF (1 << 21) /* Discard Higher-half */ | ||
82 | #define MOD_C2DD_LHALF (1 << 20) /* Discard Lower-half */ | ||
83 | #define MOD_C1DD_HHALF (1 << 19) | ||
84 | #define MOD_C1DD_LHALF (1 << 18) | ||
85 | #define MOD_DC2_EN (1 << 17) | ||
86 | #define MOD_DC1_EN (1 << 16) | ||
87 | #define MOD_BLC_16BIT (0 << 13) | ||
88 | #define MOD_BLC_8BIT (1 << 13) | ||
89 | #define MOD_BLC_24BIT (2 << 13) | ||
90 | #define MOD_BLC_MASK (3 << 13) | ||
91 | |||
92 | #define MOD_IMS_SYSMUX (1 << 10) | ||
93 | #define MOD_SLAVE (1 << 11) | ||
94 | #define MOD_TXONLY (0 << 8) | ||
95 | #define MOD_RXONLY (1 << 8) | ||
96 | #define MOD_TXRX (2 << 8) | ||
97 | #define MOD_MASK (3 << 8) | ||
98 | #define MOD_LR_LLOW (0 << 7) | ||
99 | #define MOD_LR_RLOW (1 << 7) | ||
100 | #define MOD_SDF_IIS (0 << 5) | ||
101 | #define MOD_SDF_MSB (1 << 5) | ||
102 | #define MOD_SDF_LSB (2 << 5) | ||
103 | #define MOD_SDF_MASK (3 << 5) | ||
104 | #define MOD_RCLK_256FS (0 << 3) | ||
105 | #define MOD_RCLK_512FS (1 << 3) | ||
106 | #define MOD_RCLK_384FS (2 << 3) | ||
107 | #define MOD_RCLK_768FS (3 << 3) | ||
108 | #define MOD_RCLK_MASK (3 << 3) | ||
109 | #define MOD_BCLK_32FS (0 << 1) | ||
110 | #define MOD_BCLK_48FS (1 << 1) | ||
111 | #define MOD_BCLK_16FS (2 << 1) | ||
112 | #define MOD_BCLK_24FS (3 << 1) | ||
113 | #define MOD_BCLK_MASK (3 << 1) | ||
114 | #define MOD_8BIT (1 << 0) | ||
115 | |||
116 | #define MOD_CDCLKCON (1 << 12) | ||
117 | |||
118 | #define PSR_PSREN (1 << 15) | ||
119 | |||
120 | #define FIC_TX2COUNT(x) (((x) >> 24) & 0xf) | ||
121 | #define FIC_TX1COUNT(x) (((x) >> 16) & 0xf) | ||
122 | |||
123 | #define FIC_TXFLUSH (1 << 15) | ||
124 | #define FIC_RXFLUSH (1 << 7) | ||
125 | |||
126 | #define FIC_TXCOUNT(x) (((x) >> 8) & 0xf) | ||
127 | #define FIC_RXCOUNT(x) (((x) >> 0) & 0xf) | ||
128 | #define FICS_TXCOUNT(x) (((x) >> 8) & 0x7f) | ||
129 | |||
130 | #define AHB_INTENLVL0 (1 << 24) | ||
131 | #define AHB_LVL0INT (1 << 20) | ||
132 | #define AHB_CLRLVL0INT (1 << 16) | ||
133 | #define AHB_DMARLD (1 << 5) | ||
134 | #define AHB_INTMASK (1 << 3) | ||
135 | #define AHB_DMAEN (1 << 0) | ||
136 | #define AHB_LVLINTMASK (0xf << 20) | ||
137 | |||
138 | #define I2SSIZE_TRNMSK (0xffff) | ||
139 | #define I2SSIZE_SHIFT (16) | ||
140 | |||
141 | #endif /* __SND_SOC_SAMSUNG_I2S_REGS_H */ | ||
142 | |||
143 | |||
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 992a732b5211..1568eea31f41 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c | |||
@@ -22,109 +22,7 @@ | |||
22 | 22 | ||
23 | #include "dma.h" | 23 | #include "dma.h" |
24 | #include "i2s.h" | 24 | #include "i2s.h" |
25 | 25 | #include "i2s-regs.h" | |
26 | #define I2SCON 0x0 | ||
27 | #define I2SMOD 0x4 | ||
28 | #define I2SFIC 0x8 | ||
29 | #define I2SPSR 0xc | ||
30 | #define I2STXD 0x10 | ||
31 | #define I2SRXD 0x14 | ||
32 | #define I2SFICS 0x18 | ||
33 | #define I2STXDS 0x1c | ||
34 | |||
35 | #define CON_RSTCLR (1 << 31) | ||
36 | #define CON_FRXOFSTATUS (1 << 26) | ||
37 | #define CON_FRXORINTEN (1 << 25) | ||
38 | #define CON_FTXSURSTAT (1 << 24) | ||
39 | #define CON_FTXSURINTEN (1 << 23) | ||
40 | #define CON_TXSDMA_PAUSE (1 << 20) | ||
41 | #define CON_TXSDMA_ACTIVE (1 << 18) | ||
42 | |||
43 | #define CON_FTXURSTATUS (1 << 17) | ||
44 | #define CON_FTXURINTEN (1 << 16) | ||
45 | #define CON_TXFIFO2_EMPTY (1 << 15) | ||
46 | #define CON_TXFIFO1_EMPTY (1 << 14) | ||
47 | #define CON_TXFIFO2_FULL (1 << 13) | ||
48 | #define CON_TXFIFO1_FULL (1 << 12) | ||
49 | |||
50 | #define CON_LRINDEX (1 << 11) | ||
51 | #define CON_TXFIFO_EMPTY (1 << 10) | ||
52 | #define CON_RXFIFO_EMPTY (1 << 9) | ||
53 | #define CON_TXFIFO_FULL (1 << 8) | ||
54 | #define CON_RXFIFO_FULL (1 << 7) | ||
55 | #define CON_TXDMA_PAUSE (1 << 6) | ||
56 | #define CON_RXDMA_PAUSE (1 << 5) | ||
57 | #define CON_TXCH_PAUSE (1 << 4) | ||
58 | #define CON_RXCH_PAUSE (1 << 3) | ||
59 | #define CON_TXDMA_ACTIVE (1 << 2) | ||
60 | #define CON_RXDMA_ACTIVE (1 << 1) | ||
61 | #define CON_ACTIVE (1 << 0) | ||
62 | |||
63 | #define MOD_OPCLK_CDCLK_OUT (0 << 30) | ||
64 | #define MOD_OPCLK_CDCLK_IN (1 << 30) | ||
65 | #define MOD_OPCLK_BCLK_OUT (2 << 30) | ||
66 | #define MOD_OPCLK_PCLK (3 << 30) | ||
67 | #define MOD_OPCLK_MASK (3 << 30) | ||
68 | #define MOD_TXS_IDMA (1 << 28) /* Sec_TXFIFO use I-DMA */ | ||
69 | |||
70 | #define MOD_BLCS_SHIFT 26 | ||
71 | #define MOD_BLCS_16BIT (0 << MOD_BLCS_SHIFT) | ||
72 | #define MOD_BLCS_8BIT (1 << MOD_BLCS_SHIFT) | ||
73 | #define MOD_BLCS_24BIT (2 << MOD_BLCS_SHIFT) | ||
74 | #define MOD_BLCS_MASK (3 << MOD_BLCS_SHIFT) | ||
75 | #define MOD_BLCP_SHIFT 24 | ||
76 | #define MOD_BLCP_16BIT (0 << MOD_BLCP_SHIFT) | ||
77 | #define MOD_BLCP_8BIT (1 << MOD_BLCP_SHIFT) | ||
78 | #define MOD_BLCP_24BIT (2 << MOD_BLCP_SHIFT) | ||
79 | #define MOD_BLCP_MASK (3 << MOD_BLCP_SHIFT) | ||
80 | |||
81 | #define MOD_C2DD_HHALF (1 << 21) /* Discard Higher-half */ | ||
82 | #define MOD_C2DD_LHALF (1 << 20) /* Discard Lower-half */ | ||
83 | #define MOD_C1DD_HHALF (1 << 19) | ||
84 | #define MOD_C1DD_LHALF (1 << 18) | ||
85 | #define MOD_DC2_EN (1 << 17) | ||
86 | #define MOD_DC1_EN (1 << 16) | ||
87 | #define MOD_BLC_16BIT (0 << 13) | ||
88 | #define MOD_BLC_8BIT (1 << 13) | ||
89 | #define MOD_BLC_24BIT (2 << 13) | ||
90 | #define MOD_BLC_MASK (3 << 13) | ||
91 | |||
92 | #define MOD_IMS_SYSMUX (1 << 10) | ||
93 | #define MOD_SLAVE (1 << 11) | ||
94 | #define MOD_TXONLY (0 << 8) | ||
95 | #define MOD_RXONLY (1 << 8) | ||
96 | #define MOD_TXRX (2 << 8) | ||
97 | #define MOD_MASK (3 << 8) | ||
98 | #define MOD_LR_LLOW (0 << 7) | ||
99 | #define MOD_LR_RLOW (1 << 7) | ||
100 | #define MOD_SDF_IIS (0 << 5) | ||
101 | #define MOD_SDF_MSB (1 << 5) | ||
102 | #define MOD_SDF_LSB (2 << 5) | ||
103 | #define MOD_SDF_MASK (3 << 5) | ||
104 | #define MOD_RCLK_256FS (0 << 3) | ||
105 | #define MOD_RCLK_512FS (1 << 3) | ||
106 | #define MOD_RCLK_384FS (2 << 3) | ||
107 | #define MOD_RCLK_768FS (3 << 3) | ||
108 | #define MOD_RCLK_MASK (3 << 3) | ||
109 | #define MOD_BCLK_32FS (0 << 1) | ||
110 | #define MOD_BCLK_48FS (1 << 1) | ||
111 | #define MOD_BCLK_16FS (2 << 1) | ||
112 | #define MOD_BCLK_24FS (3 << 1) | ||
113 | #define MOD_BCLK_MASK (3 << 1) | ||
114 | #define MOD_8BIT (1 << 0) | ||
115 | |||
116 | #define MOD_CDCLKCON (1 << 12) | ||
117 | |||
118 | #define PSR_PSREN (1 << 15) | ||
119 | |||
120 | #define FIC_TX2COUNT(x) (((x) >> 24) & 0xf) | ||
121 | #define FIC_TX1COUNT(x) (((x) >> 16) & 0xf) | ||
122 | |||
123 | #define FIC_TXFLUSH (1 << 15) | ||
124 | #define FIC_RXFLUSH (1 << 7) | ||
125 | #define FIC_TXCOUNT(x) (((x) >> 8) & 0xf) | ||
126 | #define FIC_RXCOUNT(x) (((x) >> 0) & 0xf) | ||
127 | #define FICS_TXCOUNT(x) (((x) >> 8) & 0x7f) | ||
128 | 26 | ||
129 | #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) | 27 | #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) |
130 | 28 | ||
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index e7c1009a1e1d..45fbe2b3727f 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include "../codecs/wm8994.h" | 10 | #include "../codecs/wm8994.h" |
11 | #include <sound/pcm_params.h> | ||
11 | 12 | ||
12 | /* | 13 | /* |
13 | * Default CFG switch settings to use this driver: | 14 | * Default CFG switch settings to use this driver: |
@@ -44,7 +45,9 @@ static int smdk_hw_params(struct snd_pcm_substream *substream, | |||
44 | int ret; | 45 | int ret; |
45 | 46 | ||
46 | /* AIF1CLK should be >=3MHz for optimal performance */ | 47 | /* AIF1CLK should be >=3MHz for optimal performance */ |
47 | if (params_rate(params) == 8000 || params_rate(params) == 11025) | 48 | if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE) |
49 | pll_out = params_rate(params) * 384; | ||
50 | else if (params_rate(params) == 8000 || params_rate(params) == 11025) | ||
48 | pll_out = params_rate(params) * 512; | 51 | pll_out = params_rate(params) * 512; |
49 | else | 52 | else |
50 | pll_out = params_rate(params) * 256; | 53 | pll_out = params_rate(params) * 256; |
diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c new file mode 100644 index 000000000000..5f2111685480 --- /dev/null +++ b/sound/soc/samsung/smdk_wm8994pcm.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * sound/soc/samsung/smdk_wm8994pcm.c | ||
3 | * | ||
4 | * Copyright (c) 2011 Samsung Electronics Co., Ltd | ||
5 | * http://www.samsung.com | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | #include <sound/soc.h> | ||
13 | #include <sound/pcm.h> | ||
14 | #include <sound/pcm_params.h> | ||
15 | |||
16 | #include "../codecs/wm8994.h" | ||
17 | #include "dma.h" | ||
18 | #include "pcm.h" | ||
19 | |||
20 | /* | ||
21 | * Board Settings: | ||
22 | * o '1' means 'ON' | ||
23 | * o '0' means 'OFF' | ||
24 | * o 'X' means 'Don't care' | ||
25 | * | ||
26 | * SMDKC210, SMDKV310: CFG3- 1001, CFG5-1000, CFG7-111111 | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | * Configure audio route as :- | ||
31 | * $ amixer sset 'DAC1' on,on | ||
32 | * $ amixer sset 'Right Headphone Mux' 'DAC' | ||
33 | * $ amixer sset 'Left Headphone Mux' 'DAC' | ||
34 | * $ amixer sset 'DAC1R Mixer AIF1.1' on | ||
35 | * $ amixer sset 'DAC1L Mixer AIF1.1' on | ||
36 | * $ amixer sset 'IN2L' on | ||
37 | * $ amixer sset 'IN2L PGA IN2LN' on | ||
38 | * $ amixer sset 'MIXINL IN2L' on | ||
39 | * $ amixer sset 'AIF1ADC1L Mixer ADC/DMIC' on | ||
40 | * $ amixer sset 'IN2R' on | ||
41 | * $ amixer sset 'IN2R PGA IN2RN' on | ||
42 | * $ amixer sset 'MIXINR IN2R' on | ||
43 | * $ amixer sset 'AIF1ADC1R Mixer ADC/DMIC' on | ||
44 | */ | ||
45 | |||
46 | /* SMDK has a 16.9344MHZ crystal attached to WM8994 */ | ||
47 | #define SMDK_WM8994_FREQ 16934400 | ||
48 | |||
49 | static int smdk_wm8994_pcm_hw_params(struct snd_pcm_substream *substream, | ||
50 | struct snd_pcm_hw_params *params) | ||
51 | { | ||
52 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
53 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
54 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
55 | unsigned long mclk_freq; | ||
56 | int rfs, ret; | ||
57 | |||
58 | switch(params_rate(params)) { | ||
59 | case 8000: | ||
60 | rfs = 512; | ||
61 | break; | ||
62 | default: | ||
63 | dev_err(cpu_dai->dev, "%s:%d Sampling Rate %u not supported!\n", | ||
64 | __func__, __LINE__, params_rate(params)); | ||
65 | return -EINVAL; | ||
66 | } | ||
67 | |||
68 | mclk_freq = params_rate(params) * rfs; | ||
69 | |||
70 | /* Set the codec DAI configuration */ | ||
71 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | ||
72 | | SND_SOC_DAIFMT_IB_NF | ||
73 | | SND_SOC_DAIFMT_CBS_CFS); | ||
74 | if (ret < 0) | ||
75 | return ret; | ||
76 | |||
77 | /* Set the cpu DAI configuration */ | ||
78 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_B | ||
79 | | SND_SOC_DAIFMT_IB_NF | ||
80 | | SND_SOC_DAIFMT_CBS_CFS); | ||
81 | if (ret < 0) | ||
82 | return ret; | ||
83 | |||
84 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, | ||
85 | mclk_freq, SND_SOC_CLOCK_IN); | ||
86 | if (ret < 0) | ||
87 | return ret; | ||
88 | |||
89 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, | ||
90 | SMDK_WM8994_FREQ, mclk_freq); | ||
91 | if (ret < 0) | ||
92 | return ret; | ||
93 | |||
94 | /* Set PCM source clock on CPU */ | ||
95 | ret = snd_soc_dai_set_sysclk(cpu_dai, S3C_PCM_CLKSRC_MUX, | ||
96 | mclk_freq, SND_SOC_CLOCK_IN); | ||
97 | if (ret < 0) | ||
98 | return ret; | ||
99 | |||
100 | /* Set SCLK_DIV for making bclk */ | ||
101 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_PCM_SCLK_PER_FS, rfs); | ||
102 | if (ret < 0) | ||
103 | return ret; | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static struct snd_soc_ops smdk_wm8994_pcm_ops = { | ||
109 | .hw_params = smdk_wm8994_pcm_hw_params, | ||
110 | }; | ||
111 | |||
112 | static struct snd_soc_dai_link smdk_dai[] = { | ||
113 | { | ||
114 | .name = "WM8994 PAIF PCM", | ||
115 | .stream_name = "Primary PCM", | ||
116 | .cpu_dai_name = "samsung-pcm.0", | ||
117 | .codec_dai_name = "wm8994-aif1", | ||
118 | .platform_name = "samsung-audio", | ||
119 | .codec_name = "wm8994-codec", | ||
120 | .ops = &smdk_wm8994_pcm_ops, | ||
121 | }, | ||
122 | }; | ||
123 | |||
124 | static struct snd_soc_card smdk_pcm = { | ||
125 | .name = "SMDK-PCM", | ||
126 | .dai_link = smdk_dai, | ||
127 | .num_links = 1, | ||
128 | }; | ||
129 | |||
130 | static int __devinit snd_smdk_probe(struct platform_device *pdev) | ||
131 | { | ||
132 | int ret = 0; | ||
133 | |||
134 | smdk_pcm.dev = &pdev->dev; | ||
135 | ret = snd_soc_register_card(&smdk_pcm); | ||
136 | if (ret) { | ||
137 | dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret); | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int __devexit snd_smdk_remove(struct platform_device *pdev) | ||
145 | { | ||
146 | snd_soc_unregister_card(&smdk_pcm); | ||
147 | platform_set_drvdata(pdev, NULL); | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static struct platform_driver snd_smdk_driver = { | ||
152 | .driver = { | ||
153 | .owner = THIS_MODULE, | ||
154 | .name = "samsung-smdk-pcm", | ||
155 | }, | ||
156 | .probe = snd_smdk_probe, | ||
157 | .remove = __devexit_p(snd_smdk_remove), | ||
158 | }; | ||
159 | |||
160 | static int __init smdk_audio_init(void) | ||
161 | { | ||
162 | return platform_driver_register(&snd_smdk_driver); | ||
163 | } | ||
164 | |||
165 | module_init(smdk_audio_init); | ||
166 | |||
167 | static void __exit smdk_audio_exit(void) | ||
168 | { | ||
169 | platform_driver_unregister(&snd_smdk_driver); | ||
170 | } | ||
171 | |||
172 | module_exit(smdk_audio_exit); | ||
173 | |||
174 | MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>"); | ||
175 | MODULE_DESCRIPTION("ALSA SoC SMDK WM8994 for PCM"); | ||
176 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 360a333cb7c0..d6dee4d02036 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c | |||
@@ -20,24 +20,29 @@ | |||
20 | #define WM8915_HPSEL_GPIO 214 | 20 | #define WM8915_HPSEL_GPIO 214 |
21 | 21 | ||
22 | static int speyside_set_bias_level(struct snd_soc_card *card, | 22 | static int speyside_set_bias_level(struct snd_soc_card *card, |
23 | struct snd_soc_dapm_context *dapm, | ||
23 | enum snd_soc_bias_level level) | 24 | enum snd_soc_bias_level level) |
24 | { | 25 | { |
25 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | 26 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; |
26 | int ret; | 27 | int ret; |
27 | 28 | ||
29 | if (dapm->dev != codec_dai->dev) | ||
30 | return 0; | ||
31 | |||
28 | switch (level) { | 32 | switch (level) { |
29 | case SND_SOC_BIAS_STANDBY: | 33 | case SND_SOC_BIAS_STANDBY: |
30 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8915_SYSCLK_MCLK1, | 34 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8915_SYSCLK_MCLK2, |
31 | 32768, SND_SOC_CLOCK_IN); | 35 | 32768, SND_SOC_CLOCK_IN); |
32 | if (ret < 0) | 36 | if (ret < 0) |
33 | return ret; | 37 | return ret; |
34 | 38 | ||
35 | ret = snd_soc_dai_set_pll(codec_dai, WM8915_FLL_MCLK1, | 39 | ret = snd_soc_dai_set_pll(codec_dai, WM8915_FLL_MCLK2, |
36 | 0, 0, 0); | 40 | 0, 0, 0); |
37 | if (ret < 0) { | 41 | if (ret < 0) { |
38 | pr_err("Failed to stop FLL\n"); | 42 | pr_err("Failed to stop FLL\n"); |
39 | return ret; | 43 | return ret; |
40 | } | 44 | } |
45 | break; | ||
41 | 46 | ||
42 | default: | 47 | default: |
43 | break; | 48 | break; |
@@ -46,6 +51,45 @@ static int speyside_set_bias_level(struct snd_soc_card *card, | |||
46 | return 0; | 51 | return 0; |
47 | } | 52 | } |
48 | 53 | ||
54 | static int speyside_set_bias_level_post(struct snd_soc_card *card, | ||
55 | struct snd_soc_dapm_context *dapm, | ||
56 | enum snd_soc_bias_level level) | ||
57 | { | ||
58 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
59 | int ret; | ||
60 | |||
61 | if (dapm->dev != codec_dai->dev) | ||
62 | return 0; | ||
63 | |||
64 | switch (level) { | ||
65 | case SND_SOC_BIAS_PREPARE: | ||
66 | if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY) { | ||
67 | ret = snd_soc_dai_set_pll(codec_dai, 0, | ||
68 | WM8915_FLL_MCLK2, | ||
69 | 32768, 48000 * 256); | ||
70 | if (ret < 0) { | ||
71 | pr_err("Failed to start FLL\n"); | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
76 | WM8915_SYSCLK_FLL, | ||
77 | 48000 * 256, | ||
78 | SND_SOC_CLOCK_IN); | ||
79 | if (ret < 0) | ||
80 | return ret; | ||
81 | } | ||
82 | break; | ||
83 | |||
84 | default: | ||
85 | break; | ||
86 | } | ||
87 | |||
88 | card->dapm.bias_level = level; | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
49 | static int speyside_hw_params(struct snd_pcm_substream *substream, | 93 | static int speyside_hw_params(struct snd_pcm_substream *substream, |
50 | struct snd_pcm_hw_params *params) | 94 | struct snd_pcm_hw_params *params) |
51 | { | 95 | { |
@@ -66,16 +110,6 @@ static int speyside_hw_params(struct snd_pcm_substream *substream, | |||
66 | if (ret < 0) | 110 | if (ret < 0) |
67 | return ret; | 111 | return ret; |
68 | 112 | ||
69 | ret = snd_soc_dai_set_pll(codec_dai, 0, WM8915_FLL_MCLK1, | ||
70 | 32768, 256 * 48000); | ||
71 | if (ret < 0) | ||
72 | return ret; | ||
73 | |||
74 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8915_SYSCLK_FLL, | ||
75 | 256 * 48000, SND_SOC_CLOCK_IN); | ||
76 | if (ret < 0) | ||
77 | return ret; | ||
78 | |||
79 | return 0; | 113 | return 0; |
80 | } | 114 | } |
81 | 115 | ||
@@ -127,7 +161,7 @@ static int speyside_wm8915_init(struct snd_soc_pcm_runtime *rtd) | |||
127 | struct snd_soc_codec *codec = rtd->codec; | 161 | struct snd_soc_codec *codec = rtd->codec; |
128 | int ret; | 162 | int ret; |
129 | 163 | ||
130 | ret = snd_soc_dai_set_sysclk(dai, WM8915_SYSCLK_MCLK1, 32768, 0); | 164 | ret = snd_soc_dai_set_sysclk(dai, WM8915_SYSCLK_MCLK2, 32768, 0); |
131 | if (ret < 0) | 165 | if (ret < 0) |
132 | return ret; | 166 | return ret; |
133 | 167 | ||
@@ -267,6 +301,7 @@ static struct snd_soc_card speyside = { | |||
267 | .num_configs = ARRAY_SIZE(speyside_codec_conf), | 301 | .num_configs = ARRAY_SIZE(speyside_codec_conf), |
268 | 302 | ||
269 | .set_bias_level = speyside_set_bias_level, | 303 | .set_bias_level = speyside_set_bias_level, |
304 | .set_bias_level_post = speyside_set_bias_level_post, | ||
270 | 305 | ||
271 | .controls = controls, | 306 | .controls = controls, |
272 | .num_controls = ARRAY_SIZE(controls), | 307 | .num_controls = ARRAY_SIZE(controls), |
diff --git a/sound/soc/samsung/speyside_wm8962.c b/sound/soc/samsung/speyside_wm8962.c new file mode 100644 index 000000000000..8ac42bf82090 --- /dev/null +++ b/sound/soc/samsung/speyside_wm8962.c | |||
@@ -0,0 +1,264 @@ | |||
1 | /* | ||
2 | * Speyside with WM8962 audio support | ||
3 | * | ||
4 | * Copyright 2011 Wolfson Microelectronics | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <sound/soc.h> | ||
13 | #include <sound/soc-dapm.h> | ||
14 | #include <sound/jack.h> | ||
15 | #include <linux/gpio.h> | ||
16 | |||
17 | #include "../codecs/wm8962.h" | ||
18 | |||
19 | static int speyside_wm8962_set_bias_level(struct snd_soc_card *card, | ||
20 | struct snd_soc_dapm_context *dapm, | ||
21 | enum snd_soc_bias_level level) | ||
22 | { | ||
23 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
24 | int ret; | ||
25 | |||
26 | switch (level) { | ||
27 | case SND_SOC_BIAS_PREPARE: | ||
28 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { | ||
29 | ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL, | ||
30 | WM8962_FLL_MCLK, 32768, | ||
31 | 44100 * 256); | ||
32 | if (ret < 0) | ||
33 | pr_err("Failed to start FLL: %d\n", ret); | ||
34 | |||
35 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
36 | WM8962_SYSCLK_FLL, | ||
37 | 44100 * 256, | ||
38 | SND_SOC_CLOCK_IN); | ||
39 | if (ret < 0) { | ||
40 | pr_err("Failed to set SYSCLK: %d\n"); | ||
41 | return ret; | ||
42 | } | ||
43 | } | ||
44 | break; | ||
45 | |||
46 | default: | ||
47 | break; | ||
48 | } | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static int speyside_wm8962_set_bias_level_post(struct snd_soc_card *card, | ||
54 | struct snd_soc_dapm_context *dapm, | ||
55 | enum snd_soc_bias_level level) | ||
56 | { | ||
57 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
58 | int ret; | ||
59 | |||
60 | switch (level) { | ||
61 | case SND_SOC_BIAS_STANDBY: | ||
62 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK, | ||
63 | 32768, SND_SOC_CLOCK_IN); | ||
64 | if (ret < 0) { | ||
65 | pr_err("Failed to switch away from FLL: %d\n", ret); | ||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL, | ||
70 | 0, 0, 0); | ||
71 | if (ret < 0) { | ||
72 | pr_err("Failed to stop FLL: %d\n", ret); | ||
73 | return ret; | ||
74 | } | ||
75 | break; | ||
76 | |||
77 | default: | ||
78 | break; | ||
79 | } | ||
80 | |||
81 | dapm->bias_level = level; | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int speyside_wm8962_hw_params(struct snd_pcm_substream *substream, | ||
87 | struct snd_pcm_hw_params *params) | ||
88 | { | ||
89 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
90 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
91 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
92 | int ret; | ||
93 | |||
94 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | ||
95 | | SND_SOC_DAIFMT_NB_NF | ||
96 | | SND_SOC_DAIFMT_CBM_CFM); | ||
97 | if (ret < 0) | ||
98 | return ret; | ||
99 | |||
100 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | ||
101 | | SND_SOC_DAIFMT_NB_NF | ||
102 | | SND_SOC_DAIFMT_CBM_CFM); | ||
103 | if (ret < 0) | ||
104 | return ret; | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static struct snd_soc_ops speyside_wm8962_ops = { | ||
110 | .hw_params = speyside_wm8962_hw_params, | ||
111 | }; | ||
112 | |||
113 | static struct snd_soc_dai_link speyside_wm8962_dai[] = { | ||
114 | { | ||
115 | .name = "CPU", | ||
116 | .stream_name = "CPU", | ||
117 | .cpu_dai_name = "samsung-i2s.0", | ||
118 | .codec_dai_name = "wm8962", | ||
119 | .platform_name = "samsung-audio", | ||
120 | .codec_name = "wm8962.1-001a", | ||
121 | .ops = &speyside_wm8962_ops, | ||
122 | }, | ||
123 | }; | ||
124 | |||
125 | static const struct snd_kcontrol_new controls[] = { | ||
126 | SOC_DAPM_PIN_SWITCH("Main Speaker"), | ||
127 | }; | ||
128 | |||
129 | static struct snd_soc_dapm_widget widgets[] = { | ||
130 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
131 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
132 | |||
133 | SND_SOC_DAPM_MIC("DMIC", NULL), | ||
134 | |||
135 | SND_SOC_DAPM_SPK("Main Speaker", NULL), | ||
136 | }; | ||
137 | |||
138 | static struct snd_soc_dapm_route audio_paths[] = { | ||
139 | { "Headphone", NULL, "HPOUTL" }, | ||
140 | { "Headphone", NULL, "HPOUTR" }, | ||
141 | |||
142 | { "Main Speaker", NULL, "SPKOUTL" }, | ||
143 | { "Main Speaker", NULL, "SPKOUTR" }, | ||
144 | |||
145 | { "MICBIAS", NULL, "Headset Mic" }, | ||
146 | { "IN4L", NULL, "MICBIAS" }, | ||
147 | { "IN4R", NULL, "MICBIAS" }, | ||
148 | |||
149 | { "MICBIAS", NULL, "DMIC" }, | ||
150 | { "DMICDAT", NULL, "MICBIAS" }, | ||
151 | }; | ||
152 | |||
153 | static struct snd_soc_jack speyside_wm8962_headset; | ||
154 | |||
155 | /* Headset jack detection DAPM pins */ | ||
156 | static struct snd_soc_jack_pin speyside_wm8962_headset_pins[] = { | ||
157 | { | ||
158 | .pin = "Headset Mic", | ||
159 | .mask = SND_JACK_MICROPHONE, | ||
160 | }, | ||
161 | { | ||
162 | .pin = "Headphone", | ||
163 | .mask = SND_JACK_MICROPHONE, | ||
164 | }, | ||
165 | }; | ||
166 | |||
167 | static int speyside_wm8962_late_probe(struct snd_soc_card *card) | ||
168 | { | ||
169 | struct snd_soc_codec *codec = card->rtd[0].codec; | ||
170 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
171 | int ret; | ||
172 | |||
173 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK, | ||
174 | 32768, SND_SOC_CLOCK_IN); | ||
175 | if (ret < 0) | ||
176 | return ret; | ||
177 | |||
178 | ret = snd_soc_jack_new(codec, "Headset", | ||
179 | SND_JACK_HEADSET | SND_JACK_BTN_0, | ||
180 | &speyside_wm8962_headset); | ||
181 | if (ret) | ||
182 | return ret; | ||
183 | |||
184 | ret = snd_soc_jack_add_pins(&speyside_wm8962_headset, | ||
185 | ARRAY_SIZE(speyside_wm8962_headset_pins), | ||
186 | speyside_wm8962_headset_pins); | ||
187 | if (ret) | ||
188 | return ret; | ||
189 | |||
190 | wm8962_mic_detect(codec, &speyside_wm8962_headset); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static struct snd_soc_card speyside_wm8962 = { | ||
196 | .name = "Speyside WM8962", | ||
197 | .dai_link = speyside_wm8962_dai, | ||
198 | .num_links = ARRAY_SIZE(speyside_wm8962_dai), | ||
199 | |||
200 | .set_bias_level = speyside_wm8962_set_bias_level, | ||
201 | .set_bias_level_post = speyside_wm8962_set_bias_level_post, | ||
202 | |||
203 | .controls = controls, | ||
204 | .num_controls = ARRAY_SIZE(controls), | ||
205 | .dapm_widgets = widgets, | ||
206 | .num_dapm_widgets = ARRAY_SIZE(widgets), | ||
207 | .dapm_routes = audio_paths, | ||
208 | .num_dapm_routes = ARRAY_SIZE(audio_paths), | ||
209 | |||
210 | .late_probe = speyside_wm8962_late_probe, | ||
211 | }; | ||
212 | |||
213 | static __devinit int speyside_wm8962_probe(struct platform_device *pdev) | ||
214 | { | ||
215 | struct snd_soc_card *card = &speyside_wm8962; | ||
216 | int ret; | ||
217 | |||
218 | card->dev = &pdev->dev; | ||
219 | |||
220 | ret = snd_soc_register_card(card); | ||
221 | if (ret) { | ||
222 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
223 | ret); | ||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static int __devexit speyside_wm8962_remove(struct platform_device *pdev) | ||
231 | { | ||
232 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
233 | |||
234 | snd_soc_unregister_card(card); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static struct platform_driver speyside_wm8962_driver = { | ||
240 | .driver = { | ||
241 | .name = "speyside-wm8962", | ||
242 | .owner = THIS_MODULE, | ||
243 | .pm = &snd_soc_pm_ops, | ||
244 | }, | ||
245 | .probe = speyside_wm8962_probe, | ||
246 | .remove = __devexit_p(speyside_wm8962_remove), | ||
247 | }; | ||
248 | |||
249 | static int __init speyside_wm8962_audio_init(void) | ||
250 | { | ||
251 | return platform_driver_register(&speyside_wm8962_driver); | ||
252 | } | ||
253 | module_init(speyside_wm8962_audio_init); | ||
254 | |||
255 | static void __exit speyside_wm8962_audio_exit(void) | ||
256 | { | ||
257 | platform_driver_unregister(&speyside_wm8962_driver); | ||
258 | } | ||
259 | module_exit(speyside_wm8962_audio_exit); | ||
260 | |||
261 | MODULE_DESCRIPTION("Speyside WM8962 audio support"); | ||
262 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
263 | MODULE_LICENSE("GPL"); | ||
264 | MODULE_ALIAS("platform:speyside-wm8962"); | ||
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index c326d29992fe..db74005f37ce 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c | |||
@@ -327,10 +327,10 @@ static void camelot_pcm_free(struct snd_pcm *pcm) | |||
327 | snd_pcm_lib_preallocate_free_for_all(pcm); | 327 | snd_pcm_lib_preallocate_free_for_all(pcm); |
328 | } | 328 | } |
329 | 329 | ||
330 | static int camelot_pcm_new(struct snd_card *card, | 330 | static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd) |
331 | struct snd_soc_dai *dai, | ||
332 | struct snd_pcm *pcm) | ||
333 | { | 331 | { |
332 | struct snd_pcm *pcm = rtd->pcm; | ||
333 | |||
334 | /* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel | 334 | /* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel |
335 | * in MMAP mode (i.e. aplay -M) | 335 | * in MMAP mode (i.e. aplay -M) |
336 | */ | 336 | */ |
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c index d6f4703b3c07..770a71a15366 100644 --- a/sound/soc/sh/fsi-ak4642.c +++ b/sound/soc/sh/fsi-ak4642.c | |||
@@ -97,7 +97,7 @@ static int fsi_ak4642_remove(struct platform_device *pdev) | |||
97 | 97 | ||
98 | static struct fsi_ak4642_data fsi_a_ak4642 = { | 98 | static struct fsi_ak4642_data fsi_a_ak4642 = { |
99 | .name = "AK4642", | 99 | .name = "AK4642", |
100 | .card = "FSIA (AK4642)", | 100 | .card = "FSIA-AK4642", |
101 | .cpu_dai = "fsia-dai", | 101 | .cpu_dai = "fsia-dai", |
102 | .codec = "ak4642-codec.0-0012", | 102 | .codec = "ak4642-codec.0-0012", |
103 | .platform = "sh_fsi.0", | 103 | .platform = "sh_fsi.0", |
@@ -106,7 +106,7 @@ static struct fsi_ak4642_data fsi_a_ak4642 = { | |||
106 | 106 | ||
107 | static struct fsi_ak4642_data fsi_b_ak4642 = { | 107 | static struct fsi_ak4642_data fsi_b_ak4642 = { |
108 | .name = "AK4642", | 108 | .name = "AK4642", |
109 | .card = "FSIB (AK4642)", | 109 | .card = "FSIB-AK4642", |
110 | .cpu_dai = "fsib-dai", | 110 | .cpu_dai = "fsib-dai", |
111 | .codec = "ak4642-codec.0-0012", | 111 | .codec = "ak4642-codec.0-0012", |
112 | .platform = "sh_fsi.0", | 112 | .platform = "sh_fsi.0", |
@@ -115,7 +115,7 @@ static struct fsi_ak4642_data fsi_b_ak4642 = { | |||
115 | 115 | ||
116 | static struct fsi_ak4642_data fsi_a_ak4643 = { | 116 | static struct fsi_ak4642_data fsi_a_ak4643 = { |
117 | .name = "AK4643", | 117 | .name = "AK4643", |
118 | .card = "FSIA (AK4643)", | 118 | .card = "FSIA-AK4643", |
119 | .cpu_dai = "fsia-dai", | 119 | .cpu_dai = "fsia-dai", |
120 | .codec = "ak4642-codec.0-0013", | 120 | .codec = "ak4642-codec.0-0013", |
121 | .platform = "sh_fsi.0", | 121 | .platform = "sh_fsi.0", |
@@ -124,7 +124,7 @@ static struct fsi_ak4642_data fsi_a_ak4643 = { | |||
124 | 124 | ||
125 | static struct fsi_ak4642_data fsi_b_ak4643 = { | 125 | static struct fsi_ak4642_data fsi_b_ak4643 = { |
126 | .name = "AK4643", | 126 | .name = "AK4643", |
127 | .card = "FSIB (AK4643)", | 127 | .card = "FSIB-AK4643", |
128 | .cpu_dai = "fsib-dai", | 128 | .cpu_dai = "fsib-dai", |
129 | .codec = "ak4642-codec.0-0013", | 129 | .codec = "ak4642-codec.0-0013", |
130 | .platform = "sh_fsi.0", | 130 | .platform = "sh_fsi.0", |
@@ -133,7 +133,7 @@ static struct fsi_ak4642_data fsi_b_ak4643 = { | |||
133 | 133 | ||
134 | static struct fsi_ak4642_data fsi2_a_ak4642 = { | 134 | static struct fsi_ak4642_data fsi2_a_ak4642 = { |
135 | .name = "AK4642", | 135 | .name = "AK4642", |
136 | .card = "FSI2A (AK4642)", | 136 | .card = "FSI2A-AK4642", |
137 | .cpu_dai = "fsia-dai", | 137 | .cpu_dai = "fsia-dai", |
138 | .codec = "ak4642-codec.0-0012", | 138 | .codec = "ak4642-codec.0-0012", |
139 | .platform = "sh_fsi2", | 139 | .platform = "sh_fsi2", |
@@ -142,7 +142,7 @@ static struct fsi_ak4642_data fsi2_a_ak4642 = { | |||
142 | 142 | ||
143 | static struct fsi_ak4642_data fsi2_b_ak4642 = { | 143 | static struct fsi_ak4642_data fsi2_b_ak4642 = { |
144 | .name = "AK4642", | 144 | .name = "AK4642", |
145 | .card = "FSI2B (AK4642)", | 145 | .card = "FSI2B-AK4642", |
146 | .cpu_dai = "fsib-dai", | 146 | .cpu_dai = "fsib-dai", |
147 | .codec = "ak4642-codec.0-0012", | 147 | .codec = "ak4642-codec.0-0012", |
148 | .platform = "sh_fsi2", | 148 | .platform = "sh_fsi2", |
@@ -151,7 +151,7 @@ static struct fsi_ak4642_data fsi2_b_ak4642 = { | |||
151 | 151 | ||
152 | static struct fsi_ak4642_data fsi2_a_ak4643 = { | 152 | static struct fsi_ak4642_data fsi2_a_ak4643 = { |
153 | .name = "AK4643", | 153 | .name = "AK4643", |
154 | .card = "FSI2A (AK4643)", | 154 | .card = "FSI2A-AK4643", |
155 | .cpu_dai = "fsia-dai", | 155 | .cpu_dai = "fsia-dai", |
156 | .codec = "ak4642-codec.0-0013", | 156 | .codec = "ak4642-codec.0-0013", |
157 | .platform = "sh_fsi2", | 157 | .platform = "sh_fsi2", |
@@ -160,7 +160,7 @@ static struct fsi_ak4642_data fsi2_a_ak4643 = { | |||
160 | 160 | ||
161 | static struct fsi_ak4642_data fsi2_b_ak4643 = { | 161 | static struct fsi_ak4642_data fsi2_b_ak4643 = { |
162 | .name = "AK4643", | 162 | .name = "AK4643", |
163 | .card = "FSI2B (AK4643)", | 163 | .card = "FSI2B-AK4643", |
164 | .cpu_dai = "fsib-dai", | 164 | .cpu_dai = "fsib-dai", |
165 | .codec = "ak4642-codec.0-0013", | 165 | .codec = "ak4642-codec.0-0013", |
166 | .platform = "sh_fsi2", | 166 | .platform = "sh_fsi2", |
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c index dbafd7ac5590..59553fd8c2fb 100644 --- a/sound/soc/sh/fsi-da7210.c +++ b/sound/soc/sh/fsi-da7210.c | |||
@@ -42,7 +42,7 @@ static struct snd_soc_dai_link fsi_da7210_dai = { | |||
42 | }; | 42 | }; |
43 | 43 | ||
44 | static struct snd_soc_card fsi_soc_card = { | 44 | static struct snd_soc_card fsi_soc_card = { |
45 | .name = "FSI (DA7210)", | 45 | .name = "FSI-DA7210", |
46 | .dai_link = &fsi_da7210_dai, | 46 | .dai_link = &fsi_da7210_dai, |
47 | .num_links = 1, | 47 | .num_links = 1, |
48 | }; | 48 | }; |
diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c index 9719985eb82d..d3d9fd880680 100644 --- a/sound/soc/sh/fsi-hdmi.c +++ b/sound/soc/sh/fsi-hdmi.c | |||
@@ -83,13 +83,13 @@ static int fsi_hdmi_remove(struct platform_device *pdev) | |||
83 | 83 | ||
84 | static struct fsi_hdmi_data fsi2_a_hdmi = { | 84 | static struct fsi_hdmi_data fsi2_a_hdmi = { |
85 | .cpu_dai = "fsia-dai", | 85 | .cpu_dai = "fsia-dai", |
86 | .card = "FSI2A (SH MOBILE HDMI)", | 86 | .card = "FSI2A-HDMI", |
87 | .id = FSI_PORT_A, | 87 | .id = FSI_PORT_A, |
88 | }; | 88 | }; |
89 | 89 | ||
90 | static struct fsi_hdmi_data fsi2_b_hdmi = { | 90 | static struct fsi_hdmi_data fsi2_b_hdmi = { |
91 | .cpu_dai = "fsib-dai", | 91 | .cpu_dai = "fsib-dai", |
92 | .card = "FSI2B (SH MOBILE HDMI)", | 92 | .card = "FSI2B-HDMI", |
93 | .id = FSI_PORT_B, | 93 | .id = FSI_PORT_B, |
94 | }; | 94 | }; |
95 | 95 | ||
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 4a9da6b5f4e1..8e112ccffb13 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -118,10 +118,38 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena | |||
118 | /* | 118 | /* |
119 | * FSI driver use below type name for variable | 119 | * FSI driver use below type name for variable |
120 | * | 120 | * |
121 | * xxx_len : data length | ||
122 | * xxx_width : data width | ||
123 | * xxx_offset : data offset | ||
124 | * xxx_num : number of data | 121 | * xxx_num : number of data |
122 | * xxx_pos : position of data | ||
123 | * xxx_capa : capacity of data | ||
124 | */ | ||
125 | |||
126 | /* | ||
127 | * period/frame/sample image | ||
128 | * | ||
129 | * ex) PCM (2ch) | ||
130 | * | ||
131 | * period pos period pos | ||
132 | * [n] [n + 1] | ||
133 | * |<-------------------- period--------------------->| | ||
134 | * ==|============================================ ... =|== | ||
135 | * | | | ||
136 | * ||<----- frame ----->|<------ frame ----->| ... | | ||
137 | * |+--------------------+--------------------+- ... | | ||
138 | * ||[ sample ][ sample ]|[ sample ][ sample ]| ... | | ||
139 | * |+--------------------+--------------------+- ... | | ||
140 | * ==|============================================ ... =|== | ||
141 | */ | ||
142 | |||
143 | /* | ||
144 | * FSI FIFO image | ||
145 | * | ||
146 | * | | | ||
147 | * | | | ||
148 | * | [ sample ] | | ||
149 | * | [ sample ] | | ||
150 | * | [ sample ] | | ||
151 | * | [ sample ] | | ||
152 | * --> go to codecs | ||
125 | */ | 153 | */ |
126 | 154 | ||
127 | /* | 155 | /* |
@@ -131,12 +159,11 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena | |||
131 | struct fsi_stream { | 159 | struct fsi_stream { |
132 | struct snd_pcm_substream *substream; | 160 | struct snd_pcm_substream *substream; |
133 | 161 | ||
134 | int fifo_max_num; | 162 | int fifo_sample_capa; /* sample capacity of FSI FIFO */ |
135 | 163 | int buff_sample_capa; /* sample capacity of ALSA buffer */ | |
136 | int buff_offset; | 164 | int buff_sample_pos; /* sample position of ALSA buffer */ |
137 | int buff_len; | 165 | int period_samples; /* sample number / 1 period */ |
138 | int period_len; | 166 | int period_pos; /* current period position */ |
139 | int period_num; | ||
140 | 167 | ||
141 | int uerr_num; | 168 | int uerr_num; |
142 | int oerr_num; | 169 | int oerr_num; |
@@ -149,17 +176,14 @@ struct fsi_priv { | |||
149 | struct fsi_stream playback; | 176 | struct fsi_stream playback; |
150 | struct fsi_stream capture; | 177 | struct fsi_stream capture; |
151 | 178 | ||
179 | u32 do_fmt; | ||
180 | u32 di_fmt; | ||
181 | |||
152 | int chan_num:16; | 182 | int chan_num:16; |
153 | int clk_master:1; | 183 | int clk_master:1; |
184 | int spdif:1; | ||
154 | 185 | ||
155 | long rate; | 186 | long rate; |
156 | |||
157 | /* for suspend/resume */ | ||
158 | u32 saved_do_fmt; | ||
159 | u32 saved_di_fmt; | ||
160 | u32 saved_ckg1; | ||
161 | u32 saved_ckg2; | ||
162 | u32 saved_out_sel; | ||
163 | }; | 187 | }; |
164 | 188 | ||
165 | struct fsi_core { | 189 | struct fsi_core { |
@@ -180,14 +204,6 @@ struct fsi_master { | |||
180 | struct fsi_core *core; | 204 | struct fsi_core *core; |
181 | struct sh_fsi_platform_info *info; | 205 | struct sh_fsi_platform_info *info; |
182 | spinlock_t lock; | 206 | spinlock_t lock; |
183 | |||
184 | /* for suspend/resume */ | ||
185 | u32 saved_a_mclk; | ||
186 | u32 saved_b_mclk; | ||
187 | u32 saved_iemsk; | ||
188 | u32 saved_imsk; | ||
189 | u32 saved_clk_rst; | ||
190 | u32 saved_soft_rst; | ||
191 | }; | 207 | }; |
192 | 208 | ||
193 | /* | 209 | /* |
@@ -271,6 +287,11 @@ static int fsi_is_port_a(struct fsi_priv *fsi) | |||
271 | return fsi->master->base == fsi->base; | 287 | return fsi->master->base == fsi->base; |
272 | } | 288 | } |
273 | 289 | ||
290 | static int fsi_is_spdif(struct fsi_priv *fsi) | ||
291 | { | ||
292 | return fsi->spdif; | ||
293 | } | ||
294 | |||
274 | static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) | 295 | static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) |
275 | { | 296 | { |
276 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 297 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
@@ -342,28 +363,59 @@ static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) | |||
342 | return shift; | 363 | return shift; |
343 | } | 364 | } |
344 | 365 | ||
366 | static int fsi_frame2sample(struct fsi_priv *fsi, int frames) | ||
367 | { | ||
368 | return frames * fsi->chan_num; | ||
369 | } | ||
370 | |||
371 | static int fsi_sample2frame(struct fsi_priv *fsi, int samples) | ||
372 | { | ||
373 | return samples / fsi->chan_num; | ||
374 | } | ||
375 | |||
376 | static int fsi_stream_is_working(struct fsi_priv *fsi, | ||
377 | int is_play) | ||
378 | { | ||
379 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | ||
380 | struct fsi_master *master = fsi_get_master(fsi); | ||
381 | unsigned long flags; | ||
382 | int ret; | ||
383 | |||
384 | spin_lock_irqsave(&master->lock, flags); | ||
385 | ret = !!io->substream; | ||
386 | spin_unlock_irqrestore(&master->lock, flags); | ||
387 | |||
388 | return ret; | ||
389 | } | ||
390 | |||
345 | static void fsi_stream_push(struct fsi_priv *fsi, | 391 | static void fsi_stream_push(struct fsi_priv *fsi, |
346 | int is_play, | 392 | int is_play, |
347 | struct snd_pcm_substream *substream, | 393 | struct snd_pcm_substream *substream) |
348 | u32 buffer_len, | ||
349 | u32 period_len) | ||
350 | { | 394 | { |
351 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | 395 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); |
396 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
397 | struct fsi_master *master = fsi_get_master(fsi); | ||
398 | unsigned long flags; | ||
352 | 399 | ||
400 | spin_lock_irqsave(&master->lock, flags); | ||
353 | io->substream = substream; | 401 | io->substream = substream; |
354 | io->buff_len = buffer_len; | 402 | io->buff_sample_capa = fsi_frame2sample(fsi, runtime->buffer_size); |
355 | io->buff_offset = 0; | 403 | io->buff_sample_pos = 0; |
356 | io->period_len = period_len; | 404 | io->period_samples = fsi_frame2sample(fsi, runtime->period_size); |
357 | io->period_num = 0; | 405 | io->period_pos = 0; |
358 | io->oerr_num = -1; /* ignore 1st err */ | 406 | io->oerr_num = -1; /* ignore 1st err */ |
359 | io->uerr_num = -1; /* ignore 1st err */ | 407 | io->uerr_num = -1; /* ignore 1st err */ |
408 | spin_unlock_irqrestore(&master->lock, flags); | ||
360 | } | 409 | } |
361 | 410 | ||
362 | static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) | 411 | static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) |
363 | { | 412 | { |
364 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | 413 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); |
365 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); | 414 | struct snd_soc_dai *dai = fsi_get_dai(io->substream); |
415 | struct fsi_master *master = fsi_get_master(fsi); | ||
416 | unsigned long flags; | ||
366 | 417 | ||
418 | spin_lock_irqsave(&master->lock, flags); | ||
367 | 419 | ||
368 | if (io->oerr_num > 0) | 420 | if (io->oerr_num > 0) |
369 | dev_err(dai->dev, "over_run = %d\n", io->oerr_num); | 421 | dev_err(dai->dev, "over_run = %d\n", io->oerr_num); |
@@ -372,47 +424,27 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) | |||
372 | dev_err(dai->dev, "under_run = %d\n", io->uerr_num); | 424 | dev_err(dai->dev, "under_run = %d\n", io->uerr_num); |
373 | 425 | ||
374 | io->substream = NULL; | 426 | io->substream = NULL; |
375 | io->buff_len = 0; | 427 | io->buff_sample_capa = 0; |
376 | io->buff_offset = 0; | 428 | io->buff_sample_pos = 0; |
377 | io->period_len = 0; | 429 | io->period_samples = 0; |
378 | io->period_num = 0; | 430 | io->period_pos = 0; |
379 | io->oerr_num = 0; | 431 | io->oerr_num = 0; |
380 | io->uerr_num = 0; | 432 | io->uerr_num = 0; |
433 | spin_unlock_irqrestore(&master->lock, flags); | ||
381 | } | 434 | } |
382 | 435 | ||
383 | static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) | 436 | static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, int is_play) |
384 | { | 437 | { |
385 | u32 status; | 438 | u32 status; |
386 | int data_num; | 439 | int frames; |
387 | 440 | ||
388 | status = is_play ? | 441 | status = is_play ? |
389 | fsi_reg_read(fsi, DOFF_ST) : | 442 | fsi_reg_read(fsi, DOFF_ST) : |
390 | fsi_reg_read(fsi, DIFF_ST); | 443 | fsi_reg_read(fsi, DIFF_ST); |
391 | 444 | ||
392 | data_num = 0x1ff & (status >> 8); | 445 | frames = 0x1ff & (status >> 8); |
393 | data_num *= fsi->chan_num; | ||
394 | |||
395 | return data_num; | ||
396 | } | ||
397 | |||
398 | static int fsi_len2num(int len, int width) | ||
399 | { | ||
400 | return len / width; | ||
401 | } | ||
402 | |||
403 | #define fsi_num2offset(a, b) fsi_num2len(a, b) | ||
404 | static int fsi_num2len(int num, int width) | ||
405 | { | ||
406 | return num * width; | ||
407 | } | ||
408 | |||
409 | static int fsi_get_frame_width(struct fsi_priv *fsi, int is_play) | ||
410 | { | ||
411 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | ||
412 | struct snd_pcm_substream *substream = io->substream; | ||
413 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
414 | 446 | ||
415 | return frames_to_bytes(runtime, 1) / fsi->chan_num; | 447 | return fsi_frame2sample(fsi, frames); |
416 | } | 448 | } |
417 | 449 | ||
418 | static void fsi_count_fifo_err(struct fsi_priv *fsi) | 450 | static void fsi_count_fifo_err(struct fsi_priv *fsi) |
@@ -444,8 +476,10 @@ static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream) | |||
444 | { | 476 | { |
445 | int is_play = fsi_stream_is_play(stream); | 477 | int is_play = fsi_stream_is_play(stream); |
446 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | 478 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); |
479 | struct snd_pcm_runtime *runtime = io->substream->runtime; | ||
447 | 480 | ||
448 | return io->substream->runtime->dma_area + io->buff_offset; | 481 | return runtime->dma_area + |
482 | samples_to_bytes(runtime, io->buff_sample_pos); | ||
449 | } | 483 | } |
450 | 484 | ||
451 | static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num) | 485 | static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num) |
@@ -559,37 +593,94 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable) | |||
559 | /* | 593 | /* |
560 | * clock function | 594 | * clock function |
561 | */ | 595 | */ |
562 | #define fsi_module_init(m, d) __fsi_module_clk_ctrl(m, d, 1) | 596 | static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, |
563 | #define fsi_module_kill(m, d) __fsi_module_clk_ctrl(m, d, 0) | 597 | long rate, int enable) |
564 | static void __fsi_module_clk_ctrl(struct fsi_master *master, | ||
565 | struct device *dev, | ||
566 | int enable) | ||
567 | { | 598 | { |
568 | pm_runtime_get_sync(dev); | 599 | struct fsi_master *master = fsi_get_master(fsi); |
600 | set_rate_func set_rate = fsi_get_info_set_rate(master); | ||
601 | int fsi_ver = master->core->ver; | ||
602 | int ret; | ||
569 | 603 | ||
570 | if (enable) { | 604 | ret = set_rate(dev, fsi_is_port_a(fsi), rate, enable); |
571 | /* enable only SR */ | 605 | if (ret < 0) /* error */ |
572 | fsi_master_mask_set(master, SOFT_RST, FSISR, FSISR); | 606 | return ret; |
573 | fsi_master_mask_set(master, SOFT_RST, PASR | PBSR, 0); | 607 | |
574 | } else { | 608 | if (!enable) |
575 | /* clear all registers */ | 609 | return 0; |
576 | fsi_master_mask_set(master, SOFT_RST, FSISR, 0); | 610 | |
611 | if (ret > 0) { | ||
612 | u32 data = 0; | ||
613 | |||
614 | switch (ret & SH_FSI_ACKMD_MASK) { | ||
615 | default: | ||
616 | /* FALL THROUGH */ | ||
617 | case SH_FSI_ACKMD_512: | ||
618 | data |= (0x0 << 12); | ||
619 | break; | ||
620 | case SH_FSI_ACKMD_256: | ||
621 | data |= (0x1 << 12); | ||
622 | break; | ||
623 | case SH_FSI_ACKMD_128: | ||
624 | data |= (0x2 << 12); | ||
625 | break; | ||
626 | case SH_FSI_ACKMD_64: | ||
627 | data |= (0x3 << 12); | ||
628 | break; | ||
629 | case SH_FSI_ACKMD_32: | ||
630 | if (fsi_ver < 2) | ||
631 | dev_err(dev, "unsupported ACKMD\n"); | ||
632 | else | ||
633 | data |= (0x4 << 12); | ||
634 | break; | ||
635 | } | ||
636 | |||
637 | switch (ret & SH_FSI_BPFMD_MASK) { | ||
638 | default: | ||
639 | /* FALL THROUGH */ | ||
640 | case SH_FSI_BPFMD_32: | ||
641 | data |= (0x0 << 8); | ||
642 | break; | ||
643 | case SH_FSI_BPFMD_64: | ||
644 | data |= (0x1 << 8); | ||
645 | break; | ||
646 | case SH_FSI_BPFMD_128: | ||
647 | data |= (0x2 << 8); | ||
648 | break; | ||
649 | case SH_FSI_BPFMD_256: | ||
650 | data |= (0x3 << 8); | ||
651 | break; | ||
652 | case SH_FSI_BPFMD_512: | ||
653 | data |= (0x4 << 8); | ||
654 | break; | ||
655 | case SH_FSI_BPFMD_16: | ||
656 | if (fsi_ver < 2) | ||
657 | dev_err(dev, "unsupported ACKMD\n"); | ||
658 | else | ||
659 | data |= (0x7 << 8); | ||
660 | break; | ||
661 | } | ||
662 | |||
663 | fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); | ||
664 | udelay(10); | ||
665 | ret = 0; | ||
577 | } | 666 | } |
578 | 667 | ||
579 | pm_runtime_put_sync(dev); | 668 | return ret; |
580 | } | 669 | } |
581 | 670 | ||
582 | #define fsi_port_start(f) __fsi_port_clk_ctrl(f, 1) | 671 | #define fsi_port_start(f, i) __fsi_port_clk_ctrl(f, i, 1) |
583 | #define fsi_port_stop(f) __fsi_port_clk_ctrl(f, 0) | 672 | #define fsi_port_stop(f, i) __fsi_port_clk_ctrl(f, i, 0) |
584 | static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int enable) | 673 | static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable) |
585 | { | 674 | { |
586 | struct fsi_master *master = fsi_get_master(fsi); | 675 | struct fsi_master *master = fsi_get_master(fsi); |
587 | u32 soft = fsi_is_port_a(fsi) ? PASR : PBSR; | ||
588 | u32 clk = fsi_is_port_a(fsi) ? CRA : CRB; | 676 | u32 clk = fsi_is_port_a(fsi) ? CRA : CRB; |
589 | int is_master = fsi_is_clk_master(fsi); | ||
590 | 677 | ||
591 | fsi_master_mask_set(master, SOFT_RST, soft, (enable) ? soft : 0); | 678 | if (enable) |
592 | if (is_master) | 679 | fsi_irq_enable(fsi, is_play); |
680 | else | ||
681 | fsi_irq_disable(fsi, is_play); | ||
682 | |||
683 | if (fsi_is_clk_master(fsi)) | ||
593 | fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); | 684 | fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); |
594 | } | 685 | } |
595 | 686 | ||
@@ -598,18 +689,19 @@ static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int enable) | |||
598 | */ | 689 | */ |
599 | static void fsi_fifo_init(struct fsi_priv *fsi, | 690 | static void fsi_fifo_init(struct fsi_priv *fsi, |
600 | int is_play, | 691 | int is_play, |
601 | struct snd_soc_dai *dai) | 692 | struct device *dev) |
602 | { | 693 | { |
603 | struct fsi_master *master = fsi_get_master(fsi); | 694 | struct fsi_master *master = fsi_get_master(fsi); |
604 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | 695 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); |
605 | u32 shift, i; | 696 | u32 shift, i; |
697 | int frame_capa; | ||
606 | 698 | ||
607 | /* get on-chip RAM capacity */ | 699 | /* get on-chip RAM capacity */ |
608 | shift = fsi_master_read(master, FIFO_SZ); | 700 | shift = fsi_master_read(master, FIFO_SZ); |
609 | shift >>= fsi_get_port_shift(fsi, is_play); | 701 | shift >>= fsi_get_port_shift(fsi, is_play); |
610 | shift &= FIFO_SZ_MASK; | 702 | shift &= FIFO_SZ_MASK; |
611 | io->fifo_max_num = 256 << shift; | 703 | frame_capa = 256 << shift; |
612 | dev_dbg(dai->dev, "fifo = %d words\n", io->fifo_max_num); | 704 | dev_dbg(dev, "fifo = %d words\n", frame_capa); |
613 | 705 | ||
614 | /* | 706 | /* |
615 | * The maximum number of sample data varies depending | 707 | * The maximum number of sample data varies depending |
@@ -631,9 +723,11 @@ static void fsi_fifo_init(struct fsi_priv *fsi, | |||
631 | * 8 channels: 32 ( 32 x 8 = 256) | 723 | * 8 channels: 32 ( 32 x 8 = 256) |
632 | */ | 724 | */ |
633 | for (i = 1; i < fsi->chan_num; i <<= 1) | 725 | for (i = 1; i < fsi->chan_num; i <<= 1) |
634 | io->fifo_max_num >>= 1; | 726 | frame_capa >>= 1; |
635 | dev_dbg(dai->dev, "%d channel %d store\n", | 727 | dev_dbg(dev, "%d channel %d store\n", |
636 | fsi->chan_num, io->fifo_max_num); | 728 | fsi->chan_num, frame_capa); |
729 | |||
730 | io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa); | ||
637 | 731 | ||
638 | /* | 732 | /* |
639 | * set interrupt generation factor | 733 | * set interrupt generation factor |
@@ -654,10 +748,10 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) | |||
654 | struct snd_pcm_substream *substream = NULL; | 748 | struct snd_pcm_substream *substream = NULL; |
655 | int is_play = fsi_stream_is_play(stream); | 749 | int is_play = fsi_stream_is_play(stream); |
656 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | 750 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); |
657 | int data_residue_num; | 751 | int sample_residues; |
658 | int data_num; | 752 | int sample_width; |
659 | int data_num_max; | 753 | int samples; |
660 | int ch_width; | 754 | int samples_max; |
661 | int over_period; | 755 | int over_period; |
662 | void (*fn)(struct fsi_priv *fsi, int size); | 756 | void (*fn)(struct fsi_priv *fsi, int size); |
663 | 757 | ||
@@ -673,36 +767,35 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) | |||
673 | /* FSI FIFO has limit. | 767 | /* FSI FIFO has limit. |
674 | * So, this driver can not send periods data at a time | 768 | * So, this driver can not send periods data at a time |
675 | */ | 769 | */ |
676 | if (io->buff_offset >= | 770 | if (io->buff_sample_pos >= |
677 | fsi_num2offset(io->period_num + 1, io->period_len)) { | 771 | io->period_samples * (io->period_pos + 1)) { |
678 | 772 | ||
679 | over_period = 1; | 773 | over_period = 1; |
680 | io->period_num = (io->period_num + 1) % runtime->periods; | 774 | io->period_pos = (io->period_pos + 1) % runtime->periods; |
681 | 775 | ||
682 | if (0 == io->period_num) | 776 | if (0 == io->period_pos) |
683 | io->buff_offset = 0; | 777 | io->buff_sample_pos = 0; |
684 | } | 778 | } |
685 | 779 | ||
686 | /* get 1 channel data width */ | 780 | /* get 1 sample data width */ |
687 | ch_width = fsi_get_frame_width(fsi, is_play); | 781 | sample_width = samples_to_bytes(runtime, 1); |
688 | 782 | ||
689 | /* get residue data number of alsa */ | 783 | /* get number of residue samples */ |
690 | data_residue_num = fsi_len2num(io->buff_len - io->buff_offset, | 784 | sample_residues = io->buff_sample_capa - io->buff_sample_pos; |
691 | ch_width); | ||
692 | 785 | ||
693 | if (is_play) { | 786 | if (is_play) { |
694 | /* | 787 | /* |
695 | * for play-back | 788 | * for play-back |
696 | * | 789 | * |
697 | * data_num_max : number of FSI fifo free space | 790 | * samples_max : number of FSI fifo free samples space |
698 | * data_num : number of ALSA residue data | 791 | * samples : number of ALSA residue samples |
699 | */ | 792 | */ |
700 | data_num_max = io->fifo_max_num * fsi->chan_num; | 793 | samples_max = io->fifo_sample_capa; |
701 | data_num_max -= fsi_get_fifo_data_num(fsi, is_play); | 794 | samples_max -= fsi_get_current_fifo_samples(fsi, is_play); |
702 | 795 | ||
703 | data_num = data_residue_num; | 796 | samples = sample_residues; |
704 | 797 | ||
705 | switch (ch_width) { | 798 | switch (sample_width) { |
706 | case 2: | 799 | case 2: |
707 | fn = fsi_dma_soft_push16; | 800 | fn = fsi_dma_soft_push16; |
708 | break; | 801 | break; |
@@ -716,13 +809,13 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) | |||
716 | /* | 809 | /* |
717 | * for capture | 810 | * for capture |
718 | * | 811 | * |
719 | * data_num_max : number of ALSA free space | 812 | * samples_max : number of ALSA free samples space |
720 | * data_num : number of data in FSI fifo | 813 | * samples : number of samples in FSI fifo |
721 | */ | 814 | */ |
722 | data_num_max = data_residue_num; | 815 | samples_max = sample_residues; |
723 | data_num = fsi_get_fifo_data_num(fsi, is_play); | 816 | samples = fsi_get_current_fifo_samples(fsi, is_play); |
724 | 817 | ||
725 | switch (ch_width) { | 818 | switch (sample_width) { |
726 | case 2: | 819 | case 2: |
727 | fn = fsi_dma_soft_pop16; | 820 | fn = fsi_dma_soft_pop16; |
728 | break; | 821 | break; |
@@ -734,12 +827,12 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) | |||
734 | } | 827 | } |
735 | } | 828 | } |
736 | 829 | ||
737 | data_num = min(data_num, data_num_max); | 830 | samples = min(samples, samples_max); |
738 | 831 | ||
739 | fn(fsi, data_num); | 832 | fn(fsi, samples); |
740 | 833 | ||
741 | /* update buff_offset */ | 834 | /* update buff_sample_pos */ |
742 | io->buff_offset += fsi_num2offset(data_num, ch_width); | 835 | io->buff_sample_pos += samples; |
743 | 836 | ||
744 | if (over_period) | 837 | if (over_period) |
745 | snd_pcm_period_elapsed(substream); | 838 | snd_pcm_period_elapsed(substream); |
@@ -788,16 +881,20 @@ static irqreturn_t fsi_interrupt(int irq, void *data) | |||
788 | * dai ops | 881 | * dai ops |
789 | */ | 882 | */ |
790 | 883 | ||
791 | static int fsi_dai_startup(struct snd_pcm_substream *substream, | 884 | static int fsi_hw_startup(struct fsi_priv *fsi, |
792 | struct snd_soc_dai *dai) | 885 | int is_play, |
886 | struct device *dev) | ||
793 | { | 887 | { |
794 | struct fsi_priv *fsi = fsi_get_priv(substream); | ||
795 | u32 flags = fsi_get_info_flags(fsi); | 888 | u32 flags = fsi_get_info_flags(fsi); |
796 | u32 data; | 889 | u32 data = 0; |
797 | int is_play = fsi_is_play(substream); | ||
798 | 890 | ||
799 | pm_runtime_get_sync(dai->dev); | 891 | pm_runtime_get_sync(dev); |
800 | 892 | ||
893 | /* clock setting */ | ||
894 | if (fsi_is_clk_master(fsi)) | ||
895 | data = DIMD | DOMD; | ||
896 | |||
897 | fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); | ||
801 | 898 | ||
802 | /* clock inversion (CKG2) */ | 899 | /* clock inversion (CKG2) */ |
803 | data = 0; | 900 | data = 0; |
@@ -812,54 +909,70 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
812 | 909 | ||
813 | fsi_reg_write(fsi, CKG2, data); | 910 | fsi_reg_write(fsi, CKG2, data); |
814 | 911 | ||
912 | /* set format */ | ||
913 | fsi_reg_write(fsi, DO_FMT, fsi->do_fmt); | ||
914 | fsi_reg_write(fsi, DI_FMT, fsi->di_fmt); | ||
915 | |||
916 | /* spdif ? */ | ||
917 | if (fsi_is_spdif(fsi)) { | ||
918 | fsi_spdif_clk_ctrl(fsi, 1); | ||
919 | fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD); | ||
920 | } | ||
921 | |||
815 | /* irq clear */ | 922 | /* irq clear */ |
816 | fsi_irq_disable(fsi, is_play); | 923 | fsi_irq_disable(fsi, is_play); |
817 | fsi_irq_clear_status(fsi); | 924 | fsi_irq_clear_status(fsi); |
818 | 925 | ||
819 | /* fifo init */ | 926 | /* fifo init */ |
820 | fsi_fifo_init(fsi, is_play, dai); | 927 | fsi_fifo_init(fsi, is_play, dev); |
821 | 928 | ||
822 | return 0; | 929 | return 0; |
823 | } | 930 | } |
824 | 931 | ||
825 | static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | 932 | static void fsi_hw_shutdown(struct fsi_priv *fsi, |
826 | struct snd_soc_dai *dai) | 933 | int is_play, |
934 | struct device *dev) | ||
935 | { | ||
936 | if (fsi_is_clk_master(fsi)) | ||
937 | fsi_set_master_clk(dev, fsi, fsi->rate, 0); | ||
938 | |||
939 | pm_runtime_put_sync(dev); | ||
940 | } | ||
941 | |||
942 | static int fsi_dai_startup(struct snd_pcm_substream *substream, | ||
943 | struct snd_soc_dai *dai) | ||
827 | { | 944 | { |
828 | struct fsi_priv *fsi = fsi_get_priv(substream); | 945 | struct fsi_priv *fsi = fsi_get_priv(substream); |
829 | int is_play = fsi_is_play(substream); | 946 | int is_play = fsi_is_play(substream); |
830 | struct fsi_master *master = fsi_get_master(fsi); | ||
831 | set_rate_func set_rate = fsi_get_info_set_rate(master); | ||
832 | 947 | ||
833 | fsi_irq_disable(fsi, is_play); | 948 | return fsi_hw_startup(fsi, is_play, dai->dev); |
949 | } | ||
834 | 950 | ||
835 | if (fsi_is_clk_master(fsi)) | 951 | static void fsi_dai_shutdown(struct snd_pcm_substream *substream, |
836 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); | 952 | struct snd_soc_dai *dai) |
953 | { | ||
954 | struct fsi_priv *fsi = fsi_get_priv(substream); | ||
955 | int is_play = fsi_is_play(substream); | ||
837 | 956 | ||
957 | fsi_hw_shutdown(fsi, is_play, dai->dev); | ||
838 | fsi->rate = 0; | 958 | fsi->rate = 0; |
839 | |||
840 | pm_runtime_put_sync(dai->dev); | ||
841 | } | 959 | } |
842 | 960 | ||
843 | static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | 961 | static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, |
844 | struct snd_soc_dai *dai) | 962 | struct snd_soc_dai *dai) |
845 | { | 963 | { |
846 | struct fsi_priv *fsi = fsi_get_priv(substream); | 964 | struct fsi_priv *fsi = fsi_get_priv(substream); |
847 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
848 | int is_play = fsi_is_play(substream); | 965 | int is_play = fsi_is_play(substream); |
849 | int ret = 0; | 966 | int ret = 0; |
850 | 967 | ||
851 | switch (cmd) { | 968 | switch (cmd) { |
852 | case SNDRV_PCM_TRIGGER_START: | 969 | case SNDRV_PCM_TRIGGER_START: |
853 | fsi_stream_push(fsi, is_play, substream, | 970 | fsi_stream_push(fsi, is_play, substream); |
854 | frames_to_bytes(runtime, runtime->buffer_size), | ||
855 | frames_to_bytes(runtime, runtime->period_size)); | ||
856 | ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); | 971 | ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); |
857 | fsi_irq_enable(fsi, is_play); | 972 | fsi_port_start(fsi, is_play); |
858 | fsi_port_start(fsi); | ||
859 | break; | 973 | break; |
860 | case SNDRV_PCM_TRIGGER_STOP: | 974 | case SNDRV_PCM_TRIGGER_STOP: |
861 | fsi_port_stop(fsi); | 975 | fsi_port_stop(fsi, is_play); |
862 | fsi_irq_disable(fsi, is_play); | ||
863 | fsi_stream_pop(fsi, is_play); | 976 | fsi_stream_pop(fsi, is_play); |
864 | break; | 977 | break; |
865 | } | 978 | } |
@@ -884,8 +997,8 @@ static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt) | |||
884 | return -EINVAL; | 997 | return -EINVAL; |
885 | } | 998 | } |
886 | 999 | ||
887 | fsi_reg_write(fsi, DO_FMT, data); | 1000 | fsi->do_fmt = data; |
888 | fsi_reg_write(fsi, DI_FMT, data); | 1001 | fsi->di_fmt = data; |
889 | 1002 | ||
890 | return 0; | 1003 | return 0; |
891 | } | 1004 | } |
@@ -900,11 +1013,10 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi) | |||
900 | 1013 | ||
901 | data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; | 1014 | data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; |
902 | fsi->chan_num = 2; | 1015 | fsi->chan_num = 2; |
903 | fsi_spdif_clk_ctrl(fsi, 1); | 1016 | fsi->spdif = 1; |
904 | fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD); | ||
905 | 1017 | ||
906 | fsi_reg_write(fsi, DO_FMT, data); | 1018 | fsi->do_fmt = data; |
907 | fsi_reg_write(fsi, DI_FMT, data); | 1019 | fsi->di_fmt = data; |
908 | 1020 | ||
909 | return 0; | 1021 | return 0; |
910 | } | 1022 | } |
@@ -915,32 +1027,24 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
915 | struct fsi_master *master = fsi_get_master(fsi); | 1027 | struct fsi_master *master = fsi_get_master(fsi); |
916 | set_rate_func set_rate = fsi_get_info_set_rate(master); | 1028 | set_rate_func set_rate = fsi_get_info_set_rate(master); |
917 | u32 flags = fsi_get_info_flags(fsi); | 1029 | u32 flags = fsi_get_info_flags(fsi); |
918 | u32 data = 0; | ||
919 | int ret; | 1030 | int ret; |
920 | 1031 | ||
921 | pm_runtime_get_sync(dai->dev); | ||
922 | |||
923 | /* set master/slave audio interface */ | 1032 | /* set master/slave audio interface */ |
924 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 1033 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
925 | case SND_SOC_DAIFMT_CBM_CFM: | 1034 | case SND_SOC_DAIFMT_CBM_CFM: |
926 | data = DIMD | DOMD; | ||
927 | fsi->clk_master = 1; | 1035 | fsi->clk_master = 1; |
928 | break; | 1036 | break; |
929 | case SND_SOC_DAIFMT_CBS_CFS: | 1037 | case SND_SOC_DAIFMT_CBS_CFS: |
930 | break; | 1038 | break; |
931 | default: | 1039 | default: |
932 | ret = -EINVAL; | 1040 | return -EINVAL; |
933 | goto set_fmt_exit; | ||
934 | } | 1041 | } |
935 | 1042 | ||
936 | if (fsi_is_clk_master(fsi) && !set_rate) { | 1043 | if (fsi_is_clk_master(fsi) && !set_rate) { |
937 | dev_err(dai->dev, "platform doesn't have set_rate\n"); | 1044 | dev_err(dai->dev, "platform doesn't have set_rate\n"); |
938 | ret = -EINVAL; | 1045 | return -EINVAL; |
939 | goto set_fmt_exit; | ||
940 | } | 1046 | } |
941 | 1047 | ||
942 | fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); | ||
943 | |||
944 | /* set format */ | 1048 | /* set format */ |
945 | switch (flags & SH_FSI_FMT_MASK) { | 1049 | switch (flags & SH_FSI_FMT_MASK) { |
946 | case SH_FSI_FMT_DAI: | 1050 | case SH_FSI_FMT_DAI: |
@@ -953,9 +1057,6 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
953 | ret = -EINVAL; | 1057 | ret = -EINVAL; |
954 | } | 1058 | } |
955 | 1059 | ||
956 | set_fmt_exit: | ||
957 | pm_runtime_put_sync(dai->dev); | ||
958 | |||
959 | return ret; | 1060 | return ret; |
960 | } | 1061 | } |
961 | 1062 | ||
@@ -964,79 +1065,19 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | |||
964 | struct snd_soc_dai *dai) | 1065 | struct snd_soc_dai *dai) |
965 | { | 1066 | { |
966 | struct fsi_priv *fsi = fsi_get_priv(substream); | 1067 | struct fsi_priv *fsi = fsi_get_priv(substream); |
967 | struct fsi_master *master = fsi_get_master(fsi); | ||
968 | set_rate_func set_rate = fsi_get_info_set_rate(master); | ||
969 | int fsi_ver = master->core->ver; | ||
970 | long rate = params_rate(params); | 1068 | long rate = params_rate(params); |
971 | int ret; | 1069 | int ret; |
972 | 1070 | ||
973 | if (!fsi_is_clk_master(fsi)) | 1071 | if (!fsi_is_clk_master(fsi)) |
974 | return 0; | 1072 | return 0; |
975 | 1073 | ||
976 | ret = set_rate(dai->dev, fsi_is_port_a(fsi), rate, 1); | 1074 | ret = fsi_set_master_clk(dai->dev, fsi, rate, 1); |
977 | if (ret < 0) /* error */ | 1075 | if (ret < 0) |
978 | return ret; | 1076 | return ret; |
979 | 1077 | ||
980 | fsi->rate = rate; | 1078 | fsi->rate = rate; |
981 | if (ret > 0) { | ||
982 | u32 data = 0; | ||
983 | |||
984 | switch (ret & SH_FSI_ACKMD_MASK) { | ||
985 | default: | ||
986 | /* FALL THROUGH */ | ||
987 | case SH_FSI_ACKMD_512: | ||
988 | data |= (0x0 << 12); | ||
989 | break; | ||
990 | case SH_FSI_ACKMD_256: | ||
991 | data |= (0x1 << 12); | ||
992 | break; | ||
993 | case SH_FSI_ACKMD_128: | ||
994 | data |= (0x2 << 12); | ||
995 | break; | ||
996 | case SH_FSI_ACKMD_64: | ||
997 | data |= (0x3 << 12); | ||
998 | break; | ||
999 | case SH_FSI_ACKMD_32: | ||
1000 | if (fsi_ver < 2) | ||
1001 | dev_err(dai->dev, "unsupported ACKMD\n"); | ||
1002 | else | ||
1003 | data |= (0x4 << 12); | ||
1004 | break; | ||
1005 | } | ||
1006 | |||
1007 | switch (ret & SH_FSI_BPFMD_MASK) { | ||
1008 | default: | ||
1009 | /* FALL THROUGH */ | ||
1010 | case SH_FSI_BPFMD_32: | ||
1011 | data |= (0x0 << 8); | ||
1012 | break; | ||
1013 | case SH_FSI_BPFMD_64: | ||
1014 | data |= (0x1 << 8); | ||
1015 | break; | ||
1016 | case SH_FSI_BPFMD_128: | ||
1017 | data |= (0x2 << 8); | ||
1018 | break; | ||
1019 | case SH_FSI_BPFMD_256: | ||
1020 | data |= (0x3 << 8); | ||
1021 | break; | ||
1022 | case SH_FSI_BPFMD_512: | ||
1023 | data |= (0x4 << 8); | ||
1024 | break; | ||
1025 | case SH_FSI_BPFMD_16: | ||
1026 | if (fsi_ver < 2) | ||
1027 | dev_err(dai->dev, "unsupported ACKMD\n"); | ||
1028 | else | ||
1029 | data |= (0x7 << 8); | ||
1030 | break; | ||
1031 | } | ||
1032 | |||
1033 | fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); | ||
1034 | udelay(10); | ||
1035 | ret = 0; | ||
1036 | } | ||
1037 | 1079 | ||
1038 | return ret; | 1080 | return ret; |
1039 | |||
1040 | } | 1081 | } |
1041 | 1082 | ||
1042 | static struct snd_soc_dai_ops fsi_dai_ops = { | 1083 | static struct snd_soc_dai_ops fsi_dai_ops = { |
@@ -1097,16 +1138,14 @@ static int fsi_hw_free(struct snd_pcm_substream *substream) | |||
1097 | 1138 | ||
1098 | static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) | 1139 | static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) |
1099 | { | 1140 | { |
1100 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1101 | struct fsi_priv *fsi = fsi_get_priv(substream); | 1141 | struct fsi_priv *fsi = fsi_get_priv(substream); |
1102 | struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream)); | 1142 | struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream)); |
1103 | long location; | 1143 | int samples_pos = io->buff_sample_pos - 1; |
1104 | 1144 | ||
1105 | location = (io->buff_offset - 1); | 1145 | if (samples_pos < 0) |
1106 | if (location < 0) | 1146 | samples_pos = 0; |
1107 | location = 0; | ||
1108 | 1147 | ||
1109 | return bytes_to_frames(runtime, location); | 1148 | return fsi_sample2frame(fsi, samples_pos); |
1110 | } | 1149 | } |
1111 | 1150 | ||
1112 | static struct snd_pcm_ops fsi_pcm_ops = { | 1151 | static struct snd_pcm_ops fsi_pcm_ops = { |
@@ -1129,10 +1168,10 @@ static void fsi_pcm_free(struct snd_pcm *pcm) | |||
1129 | snd_pcm_lib_preallocate_free_for_all(pcm); | 1168 | snd_pcm_lib_preallocate_free_for_all(pcm); |
1130 | } | 1169 | } |
1131 | 1170 | ||
1132 | static int fsi_pcm_new(struct snd_card *card, | 1171 | static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd) |
1133 | struct snd_soc_dai *dai, | ||
1134 | struct snd_pcm *pcm) | ||
1135 | { | 1172 | { |
1173 | struct snd_pcm *pcm = rtd->pcm; | ||
1174 | |||
1136 | /* | 1175 | /* |
1137 | * dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel | 1176 | * dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel |
1138 | * in MMAP mode (i.e. aplay -M) | 1177 | * in MMAP mode (i.e. aplay -M) |
@@ -1246,8 +1285,6 @@ static int fsi_probe(struct platform_device *pdev) | |||
1246 | pm_runtime_enable(&pdev->dev); | 1285 | pm_runtime_enable(&pdev->dev); |
1247 | dev_set_drvdata(&pdev->dev, master); | 1286 | dev_set_drvdata(&pdev->dev, master); |
1248 | 1287 | ||
1249 | fsi_module_init(master, &pdev->dev); | ||
1250 | |||
1251 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, | 1288 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, |
1252 | id_entry->name, master); | 1289 | id_entry->name, master); |
1253 | if (ret) { | 1290 | if (ret) { |
@@ -1290,8 +1327,6 @@ static int fsi_remove(struct platform_device *pdev) | |||
1290 | 1327 | ||
1291 | master = dev_get_drvdata(&pdev->dev); | 1328 | master = dev_get_drvdata(&pdev->dev); |
1292 | 1329 | ||
1293 | fsi_module_kill(master, &pdev->dev); | ||
1294 | |||
1295 | free_irq(master->irq, master); | 1330 | free_irq(master->irq, master); |
1296 | pm_runtime_disable(&pdev->dev); | 1331 | pm_runtime_disable(&pdev->dev); |
1297 | 1332 | ||
@@ -1305,53 +1340,43 @@ static int fsi_remove(struct platform_device *pdev) | |||
1305 | } | 1340 | } |
1306 | 1341 | ||
1307 | static void __fsi_suspend(struct fsi_priv *fsi, | 1342 | static void __fsi_suspend(struct fsi_priv *fsi, |
1308 | struct device *dev, | 1343 | int is_play, |
1309 | set_rate_func set_rate) | 1344 | struct device *dev) |
1310 | { | 1345 | { |
1311 | fsi->saved_do_fmt = fsi_reg_read(fsi, DO_FMT); | 1346 | if (!fsi_stream_is_working(fsi, is_play)) |
1312 | fsi->saved_di_fmt = fsi_reg_read(fsi, DI_FMT); | 1347 | return; |
1313 | fsi->saved_ckg1 = fsi_reg_read(fsi, CKG1); | ||
1314 | fsi->saved_ckg2 = fsi_reg_read(fsi, CKG2); | ||
1315 | fsi->saved_out_sel = fsi_reg_read(fsi, OUT_SEL); | ||
1316 | 1348 | ||
1317 | if (fsi_is_clk_master(fsi)) | 1349 | fsi_port_stop(fsi, is_play); |
1318 | set_rate(dev, fsi_is_port_a(fsi), fsi->rate, 0); | 1350 | fsi_hw_shutdown(fsi, is_play, dev); |
1319 | } | 1351 | } |
1320 | 1352 | ||
1321 | static void __fsi_resume(struct fsi_priv *fsi, | 1353 | static void __fsi_resume(struct fsi_priv *fsi, |
1322 | struct device *dev, | 1354 | int is_play, |
1323 | set_rate_func set_rate) | 1355 | struct device *dev) |
1324 | { | 1356 | { |
1325 | fsi_reg_write(fsi, DO_FMT, fsi->saved_do_fmt); | 1357 | if (!fsi_stream_is_working(fsi, is_play)) |
1326 | fsi_reg_write(fsi, DI_FMT, fsi->saved_di_fmt); | 1358 | return; |
1327 | fsi_reg_write(fsi, CKG1, fsi->saved_ckg1); | 1359 | |
1328 | fsi_reg_write(fsi, CKG2, fsi->saved_ckg2); | 1360 | fsi_hw_startup(fsi, is_play, dev); |
1329 | fsi_reg_write(fsi, OUT_SEL, fsi->saved_out_sel); | 1361 | |
1362 | if (fsi_is_clk_master(fsi) && fsi->rate) | ||
1363 | fsi_set_master_clk(dev, fsi, fsi->rate, 1); | ||
1364 | |||
1365 | fsi_port_start(fsi, is_play); | ||
1330 | 1366 | ||
1331 | if (fsi_is_clk_master(fsi)) | ||
1332 | set_rate(dev, fsi_is_port_a(fsi), fsi->rate, 1); | ||
1333 | } | 1367 | } |
1334 | 1368 | ||
1335 | static int fsi_suspend(struct device *dev) | 1369 | static int fsi_suspend(struct device *dev) |
1336 | { | 1370 | { |
1337 | struct fsi_master *master = dev_get_drvdata(dev); | 1371 | struct fsi_master *master = dev_get_drvdata(dev); |
1338 | set_rate_func set_rate = fsi_get_info_set_rate(master); | 1372 | struct fsi_priv *fsia = &master->fsia; |
1339 | 1373 | struct fsi_priv *fsib = &master->fsib; | |
1340 | pm_runtime_get_sync(dev); | ||
1341 | |||
1342 | __fsi_suspend(&master->fsia, dev, set_rate); | ||
1343 | __fsi_suspend(&master->fsib, dev, set_rate); | ||
1344 | 1374 | ||
1345 | master->saved_a_mclk = fsi_core_read(master, a_mclk); | 1375 | __fsi_suspend(fsia, 1, dev); |
1346 | master->saved_b_mclk = fsi_core_read(master, b_mclk); | 1376 | __fsi_suspend(fsia, 0, dev); |
1347 | master->saved_iemsk = fsi_core_read(master, iemsk); | ||
1348 | master->saved_imsk = fsi_core_read(master, imsk); | ||
1349 | master->saved_clk_rst = fsi_master_read(master, CLK_RST); | ||
1350 | master->saved_soft_rst = fsi_master_read(master, SOFT_RST); | ||
1351 | 1377 | ||
1352 | fsi_module_kill(master, dev); | 1378 | __fsi_suspend(fsib, 1, dev); |
1353 | 1379 | __fsi_suspend(fsib, 0, dev); | |
1354 | pm_runtime_put_sync(dev); | ||
1355 | 1380 | ||
1356 | return 0; | 1381 | return 0; |
1357 | } | 1382 | } |
@@ -1359,23 +1384,14 @@ static int fsi_suspend(struct device *dev) | |||
1359 | static int fsi_resume(struct device *dev) | 1384 | static int fsi_resume(struct device *dev) |
1360 | { | 1385 | { |
1361 | struct fsi_master *master = dev_get_drvdata(dev); | 1386 | struct fsi_master *master = dev_get_drvdata(dev); |
1362 | set_rate_func set_rate = fsi_get_info_set_rate(master); | 1387 | struct fsi_priv *fsia = &master->fsia; |
1363 | 1388 | struct fsi_priv *fsib = &master->fsib; | |
1364 | pm_runtime_get_sync(dev); | ||
1365 | |||
1366 | fsi_module_init(master, dev); | ||
1367 | 1389 | ||
1368 | fsi_master_mask_set(master, SOFT_RST, 0xffff, master->saved_soft_rst); | 1390 | __fsi_resume(fsia, 1, dev); |
1369 | fsi_master_mask_set(master, CLK_RST, 0xffff, master->saved_clk_rst); | 1391 | __fsi_resume(fsia, 0, dev); |
1370 | fsi_core_mask_set(master, a_mclk, 0xffff, master->saved_a_mclk); | ||
1371 | fsi_core_mask_set(master, b_mclk, 0xffff, master->saved_b_mclk); | ||
1372 | fsi_core_mask_set(master, iemsk, 0xffff, master->saved_iemsk); | ||
1373 | fsi_core_mask_set(master, imsk, 0xffff, master->saved_imsk); | ||
1374 | 1392 | ||
1375 | __fsi_resume(&master->fsia, dev, set_rate); | 1393 | __fsi_resume(fsib, 1, dev); |
1376 | __fsi_resume(&master->fsib, dev, set_rate); | 1394 | __fsi_resume(fsib, 0, dev); |
1377 | |||
1378 | pm_runtime_put_sync(dev); | ||
1379 | 1395 | ||
1380 | return 0; | 1396 | return 0; |
1381 | } | 1397 | } |
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index a423babcf145..f8f681690a71 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c | |||
@@ -527,10 +527,11 @@ static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss) | |||
527 | return bytes_to_frames(ss->runtime, ptr); | 527 | return bytes_to_frames(ss->runtime, ptr); |
528 | } | 528 | } |
529 | 529 | ||
530 | static int siu_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | 530 | static int siu_pcm_new(struct snd_soc_pcm_runtime *rtd) |
531 | struct snd_pcm *pcm) | ||
532 | { | 531 | { |
533 | /* card->dev == socdev->dev, see snd_soc_new_pcms() */ | 532 | /* card->dev == socdev->dev, see snd_soc_new_pcms() */ |
533 | struct snd_card *card = rtd->card->snd_card; | ||
534 | struct snd_pcm *pcm = rtd->pcm; | ||
534 | struct siu_info *info = siu_i2s_data; | 535 | struct siu_info *info = siu_i2s_data; |
535 | struct platform_device *pdev = to_platform_device(card->dev); | 536 | struct platform_device *pdev = to_platform_device(card->dev); |
536 | int ret; | 537 | int ret; |
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 039b9532b270..d9f8aded51f3 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -20,422 +20,6 @@ | |||
20 | 20 | ||
21 | #include <trace/events/asoc.h> | 21 | #include <trace/events/asoc.h> |
22 | 22 | ||
23 | #ifdef CONFIG_SPI_MASTER | ||
24 | static int do_spi_write(void *control, const char *data, int len) | ||
25 | { | ||
26 | struct spi_device *spi = control; | ||
27 | int ret; | ||
28 | |||
29 | ret = spi_write(spi, data, len); | ||
30 | if (ret < 0) | ||
31 | return ret; | ||
32 | |||
33 | return len; | ||
34 | } | ||
35 | #endif | ||
36 | |||
37 | static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg, | ||
38 | unsigned int value, const void *data, int len) | ||
39 | { | ||
40 | int ret; | ||
41 | |||
42 | if (!snd_soc_codec_volatile_register(codec, reg) && | ||
43 | reg < codec->driver->reg_cache_size && | ||
44 | !codec->cache_bypass) { | ||
45 | ret = snd_soc_cache_write(codec, reg, value); | ||
46 | if (ret < 0) | ||
47 | return -1; | ||
48 | } | ||
49 | |||
50 | if (codec->cache_only) { | ||
51 | codec->cache_sync = 1; | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | ret = codec->hw_write(codec->control_data, data, len); | ||
56 | if (ret == len) | ||
57 | return 0; | ||
58 | if (ret < 0) | ||
59 | return ret; | ||
60 | else | ||
61 | return -EIO; | ||
62 | } | ||
63 | |||
64 | static unsigned int do_hw_read(struct snd_soc_codec *codec, unsigned int reg) | ||
65 | { | ||
66 | int ret; | ||
67 | unsigned int val; | ||
68 | |||
69 | if (reg >= codec->driver->reg_cache_size || | ||
70 | snd_soc_codec_volatile_register(codec, reg) || | ||
71 | codec->cache_bypass) { | ||
72 | if (codec->cache_only) | ||
73 | return -1; | ||
74 | |||
75 | BUG_ON(!codec->hw_read); | ||
76 | return codec->hw_read(codec, reg); | ||
77 | } | ||
78 | |||
79 | ret = snd_soc_cache_read(codec, reg, &val); | ||
80 | if (ret < 0) | ||
81 | return -1; | ||
82 | return val; | ||
83 | } | ||
84 | |||
85 | static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, | ||
86 | unsigned int reg) | ||
87 | { | ||
88 | return do_hw_read(codec, reg); | ||
89 | } | ||
90 | |||
91 | static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, | ||
92 | unsigned int value) | ||
93 | { | ||
94 | u16 data; | ||
95 | |||
96 | data = cpu_to_be16((reg << 12) | (value & 0xffffff)); | ||
97 | |||
98 | return do_hw_write(codec, reg, value, &data, 2); | ||
99 | } | ||
100 | |||
101 | static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, | ||
102 | unsigned int reg) | ||
103 | { | ||
104 | return do_hw_read(codec, reg); | ||
105 | } | ||
106 | |||
107 | static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, | ||
108 | unsigned int value) | ||
109 | { | ||
110 | u8 data[2]; | ||
111 | |||
112 | data[0] = (reg << 1) | ((value >> 8) & 0x0001); | ||
113 | data[1] = value & 0x00ff; | ||
114 | |||
115 | return do_hw_write(codec, reg, value, data, 2); | ||
116 | } | ||
117 | |||
118 | static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, | ||
119 | unsigned int value) | ||
120 | { | ||
121 | u8 data[2]; | ||
122 | |||
123 | reg &= 0xff; | ||
124 | data[0] = reg; | ||
125 | data[1] = value & 0xff; | ||
126 | |||
127 | return do_hw_write(codec, reg, value, data, 2); | ||
128 | } | ||
129 | |||
130 | static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec, | ||
131 | unsigned int reg) | ||
132 | { | ||
133 | return do_hw_read(codec, reg); | ||
134 | } | ||
135 | |||
136 | static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, | ||
137 | unsigned int value) | ||
138 | { | ||
139 | u8 data[3]; | ||
140 | |||
141 | data[0] = reg; | ||
142 | data[1] = (value >> 8) & 0xff; | ||
143 | data[2] = value & 0xff; | ||
144 | |||
145 | return do_hw_write(codec, reg, value, data, 3); | ||
146 | } | ||
147 | |||
148 | static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, | ||
149 | unsigned int reg) | ||
150 | { | ||
151 | return do_hw_read(codec, reg); | ||
152 | } | ||
153 | |||
154 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
155 | static unsigned int do_i2c_read(struct snd_soc_codec *codec, | ||
156 | void *reg, int reglen, | ||
157 | void *data, int datalen) | ||
158 | { | ||
159 | struct i2c_msg xfer[2]; | ||
160 | int ret; | ||
161 | struct i2c_client *client = codec->control_data; | ||
162 | |||
163 | /* Write register */ | ||
164 | xfer[0].addr = client->addr; | ||
165 | xfer[0].flags = 0; | ||
166 | xfer[0].len = reglen; | ||
167 | xfer[0].buf = reg; | ||
168 | |||
169 | /* Read data */ | ||
170 | xfer[1].addr = client->addr; | ||
171 | xfer[1].flags = I2C_M_RD; | ||
172 | xfer[1].len = datalen; | ||
173 | xfer[1].buf = data; | ||
174 | |||
175 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
176 | if (ret == 2) | ||
177 | return 0; | ||
178 | else if (ret < 0) | ||
179 | return ret; | ||
180 | else | ||
181 | return -EIO; | ||
182 | } | ||
183 | #endif | ||
184 | |||
185 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
186 | static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec, | ||
187 | unsigned int r) | ||
188 | { | ||
189 | u8 reg = r; | ||
190 | u8 data; | ||
191 | int ret; | ||
192 | |||
193 | ret = do_i2c_read(codec, ®, 1, &data, 1); | ||
194 | if (ret < 0) | ||
195 | return 0; | ||
196 | return data; | ||
197 | } | ||
198 | #else | ||
199 | #define snd_soc_8_8_read_i2c NULL | ||
200 | #endif | ||
201 | |||
202 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
203 | static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec, | ||
204 | unsigned int r) | ||
205 | { | ||
206 | u8 reg = r; | ||
207 | u16 data; | ||
208 | int ret; | ||
209 | |||
210 | ret = do_i2c_read(codec, ®, 1, &data, 2); | ||
211 | if (ret < 0) | ||
212 | return 0; | ||
213 | return (data >> 8) | ((data & 0xff) << 8); | ||
214 | } | ||
215 | #else | ||
216 | #define snd_soc_8_16_read_i2c NULL | ||
217 | #endif | ||
218 | |||
219 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
220 | static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec, | ||
221 | unsigned int r) | ||
222 | { | ||
223 | u16 reg = r; | ||
224 | u8 data; | ||
225 | int ret; | ||
226 | |||
227 | ret = do_i2c_read(codec, ®, 2, &data, 1); | ||
228 | if (ret < 0) | ||
229 | return 0; | ||
230 | return data; | ||
231 | } | ||
232 | #else | ||
233 | #define snd_soc_16_8_read_i2c NULL | ||
234 | #endif | ||
235 | |||
236 | static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, | ||
237 | unsigned int reg) | ||
238 | { | ||
239 | return do_hw_read(codec, reg); | ||
240 | } | ||
241 | |||
242 | static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, | ||
243 | unsigned int value) | ||
244 | { | ||
245 | u8 data[3]; | ||
246 | |||
247 | data[0] = (reg >> 8) & 0xff; | ||
248 | data[1] = reg & 0xff; | ||
249 | data[2] = value; | ||
250 | |||
251 | return do_hw_write(codec, reg, value, data, 3); | ||
252 | } | ||
253 | |||
254 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
255 | static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec, | ||
256 | unsigned int r) | ||
257 | { | ||
258 | u16 reg = cpu_to_be16(r); | ||
259 | u16 data; | ||
260 | int ret; | ||
261 | |||
262 | ret = do_i2c_read(codec, ®, 2, &data, 2); | ||
263 | if (ret < 0) | ||
264 | return 0; | ||
265 | return be16_to_cpu(data); | ||
266 | } | ||
267 | #else | ||
268 | #define snd_soc_16_16_read_i2c NULL | ||
269 | #endif | ||
270 | |||
271 | static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec, | ||
272 | unsigned int reg) | ||
273 | { | ||
274 | return do_hw_read(codec, reg); | ||
275 | } | ||
276 | |||
277 | static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, | ||
278 | unsigned int value) | ||
279 | { | ||
280 | u8 data[4]; | ||
281 | |||
282 | data[0] = (reg >> 8) & 0xff; | ||
283 | data[1] = reg & 0xff; | ||
284 | data[2] = (value >> 8) & 0xff; | ||
285 | data[3] = value & 0xff; | ||
286 | |||
287 | return do_hw_write(codec, reg, value, data, 4); | ||
288 | } | ||
289 | |||
290 | /* Primitive bulk write support for soc-cache. The data pointed to by | ||
291 | * `data' needs to already be in the form the hardware expects | ||
292 | * including any leading register specific data. Any data written | ||
293 | * through this function will not go through the cache as it only | ||
294 | * handles writing to volatile or out of bounds registers. | ||
295 | */ | ||
296 | static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg, | ||
297 | const void *data, size_t len) | ||
298 | { | ||
299 | int ret; | ||
300 | |||
301 | /* To ensure that we don't get out of sync with the cache, check | ||
302 | * whether the base register is volatile or if we've directly asked | ||
303 | * to bypass the cache. Out of bounds registers are considered | ||
304 | * volatile. | ||
305 | */ | ||
306 | if (!codec->cache_bypass | ||
307 | && !snd_soc_codec_volatile_register(codec, reg) | ||
308 | && reg < codec->driver->reg_cache_size) | ||
309 | return -EINVAL; | ||
310 | |||
311 | switch (codec->control_type) { | ||
312 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
313 | case SND_SOC_I2C: | ||
314 | ret = i2c_master_send(codec->control_data, data, len); | ||
315 | break; | ||
316 | #endif | ||
317 | #if defined(CONFIG_SPI_MASTER) | ||
318 | case SND_SOC_SPI: | ||
319 | ret = spi_write(codec->control_data, data, len); | ||
320 | break; | ||
321 | #endif | ||
322 | default: | ||
323 | BUG(); | ||
324 | } | ||
325 | |||
326 | if (ret == len) | ||
327 | return 0; | ||
328 | if (ret < 0) | ||
329 | return ret; | ||
330 | else | ||
331 | return -EIO; | ||
332 | } | ||
333 | |||
334 | static struct { | ||
335 | int addr_bits; | ||
336 | int data_bits; | ||
337 | int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int); | ||
338 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); | ||
339 | unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); | ||
340 | } io_types[] = { | ||
341 | { | ||
342 | .addr_bits = 4, .data_bits = 12, | ||
343 | .write = snd_soc_4_12_write, .read = snd_soc_4_12_read, | ||
344 | }, | ||
345 | { | ||
346 | .addr_bits = 7, .data_bits = 9, | ||
347 | .write = snd_soc_7_9_write, .read = snd_soc_7_9_read, | ||
348 | }, | ||
349 | { | ||
350 | .addr_bits = 8, .data_bits = 8, | ||
351 | .write = snd_soc_8_8_write, .read = snd_soc_8_8_read, | ||
352 | .i2c_read = snd_soc_8_8_read_i2c, | ||
353 | }, | ||
354 | { | ||
355 | .addr_bits = 8, .data_bits = 16, | ||
356 | .write = snd_soc_8_16_write, .read = snd_soc_8_16_read, | ||
357 | .i2c_read = snd_soc_8_16_read_i2c, | ||
358 | }, | ||
359 | { | ||
360 | .addr_bits = 16, .data_bits = 8, | ||
361 | .write = snd_soc_16_8_write, .read = snd_soc_16_8_read, | ||
362 | .i2c_read = snd_soc_16_8_read_i2c, | ||
363 | }, | ||
364 | { | ||
365 | .addr_bits = 16, .data_bits = 16, | ||
366 | .write = snd_soc_16_16_write, .read = snd_soc_16_16_read, | ||
367 | .i2c_read = snd_soc_16_16_read_i2c, | ||
368 | }, | ||
369 | }; | ||
370 | |||
371 | /** | ||
372 | * snd_soc_codec_set_cache_io: Set up standard I/O functions. | ||
373 | * | ||
374 | * @codec: CODEC to configure. | ||
375 | * @addr_bits: Number of bits of register address data. | ||
376 | * @data_bits: Number of bits of data per register. | ||
377 | * @control: Control bus used. | ||
378 | * | ||
379 | * Register formats are frequently shared between many I2C and SPI | ||
380 | * devices. In order to promote code reuse the ASoC core provides | ||
381 | * some standard implementations of CODEC read and write operations | ||
382 | * which can be set up using this function. | ||
383 | * | ||
384 | * The caller is responsible for allocating and initialising the | ||
385 | * actual cache. | ||
386 | * | ||
387 | * Note that at present this code cannot be used by CODECs with | ||
388 | * volatile registers. | ||
389 | */ | ||
390 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | ||
391 | int addr_bits, int data_bits, | ||
392 | enum snd_soc_control_type control) | ||
393 | { | ||
394 | int i; | ||
395 | |||
396 | for (i = 0; i < ARRAY_SIZE(io_types); i++) | ||
397 | if (io_types[i].addr_bits == addr_bits && | ||
398 | io_types[i].data_bits == data_bits) | ||
399 | break; | ||
400 | if (i == ARRAY_SIZE(io_types)) { | ||
401 | printk(KERN_ERR | ||
402 | "No I/O functions for %d bit address %d bit data\n", | ||
403 | addr_bits, data_bits); | ||
404 | return -EINVAL; | ||
405 | } | ||
406 | |||
407 | codec->write = io_types[i].write; | ||
408 | codec->read = io_types[i].read; | ||
409 | codec->bulk_write_raw = snd_soc_hw_bulk_write_raw; | ||
410 | |||
411 | switch (control) { | ||
412 | case SND_SOC_I2C: | ||
413 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
414 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
415 | #endif | ||
416 | if (io_types[i].i2c_read) | ||
417 | codec->hw_read = io_types[i].i2c_read; | ||
418 | |||
419 | codec->control_data = container_of(codec->dev, | ||
420 | struct i2c_client, | ||
421 | dev); | ||
422 | break; | ||
423 | |||
424 | case SND_SOC_SPI: | ||
425 | #ifdef CONFIG_SPI_MASTER | ||
426 | codec->hw_write = do_spi_write; | ||
427 | #endif | ||
428 | |||
429 | codec->control_data = container_of(codec->dev, | ||
430 | struct spi_device, | ||
431 | dev); | ||
432 | break; | ||
433 | } | ||
434 | |||
435 | return 0; | ||
436 | } | ||
437 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); | ||
438 | |||
439 | static bool snd_soc_set_cache_val(void *base, unsigned int idx, | 23 | static bool snd_soc_set_cache_val(void *base, unsigned int idx, |
440 | unsigned int val, unsigned int word_size) | 24 | unsigned int val, unsigned int word_size) |
441 | { | 25 | { |
@@ -483,31 +67,86 @@ static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx, | |||
483 | } | 67 | } |
484 | 68 | ||
485 | struct snd_soc_rbtree_node { | 69 | struct snd_soc_rbtree_node { |
486 | struct rb_node node; | 70 | struct rb_node node; /* the actual rbtree node holding this block */ |
487 | unsigned int reg; | 71 | unsigned int base_reg; /* base register handled by this block */ |
488 | unsigned int value; | 72 | unsigned int word_size; /* number of bytes needed to represent the register index */ |
489 | unsigned int defval; | 73 | void *block; /* block of adjacent registers */ |
74 | unsigned int blklen; /* number of registers available in the block */ | ||
490 | } __attribute__ ((packed)); | 75 | } __attribute__ ((packed)); |
491 | 76 | ||
492 | struct snd_soc_rbtree_ctx { | 77 | struct snd_soc_rbtree_ctx { |
493 | struct rb_root root; | 78 | struct rb_root root; |
79 | struct snd_soc_rbtree_node *cached_rbnode; | ||
494 | }; | 80 | }; |
495 | 81 | ||
82 | static inline void snd_soc_rbtree_get_base_top_reg( | ||
83 | struct snd_soc_rbtree_node *rbnode, | ||
84 | unsigned int *base, unsigned int *top) | ||
85 | { | ||
86 | *base = rbnode->base_reg; | ||
87 | *top = rbnode->base_reg + rbnode->blklen - 1; | ||
88 | } | ||
89 | |||
90 | static unsigned int snd_soc_rbtree_get_register( | ||
91 | struct snd_soc_rbtree_node *rbnode, unsigned int idx) | ||
92 | { | ||
93 | unsigned int val; | ||
94 | |||
95 | switch (rbnode->word_size) { | ||
96 | case 1: { | ||
97 | u8 *p = rbnode->block; | ||
98 | val = p[idx]; | ||
99 | return val; | ||
100 | } | ||
101 | case 2: { | ||
102 | u16 *p = rbnode->block; | ||
103 | val = p[idx]; | ||
104 | return val; | ||
105 | } | ||
106 | default: | ||
107 | BUG(); | ||
108 | break; | ||
109 | } | ||
110 | return -1; | ||
111 | } | ||
112 | |||
113 | static void snd_soc_rbtree_set_register(struct snd_soc_rbtree_node *rbnode, | ||
114 | unsigned int idx, unsigned int val) | ||
115 | { | ||
116 | switch (rbnode->word_size) { | ||
117 | case 1: { | ||
118 | u8 *p = rbnode->block; | ||
119 | p[idx] = val; | ||
120 | break; | ||
121 | } | ||
122 | case 2: { | ||
123 | u16 *p = rbnode->block; | ||
124 | p[idx] = val; | ||
125 | break; | ||
126 | } | ||
127 | default: | ||
128 | BUG(); | ||
129 | break; | ||
130 | } | ||
131 | } | ||
132 | |||
496 | static struct snd_soc_rbtree_node *snd_soc_rbtree_lookup( | 133 | static struct snd_soc_rbtree_node *snd_soc_rbtree_lookup( |
497 | struct rb_root *root, unsigned int reg) | 134 | struct rb_root *root, unsigned int reg) |
498 | { | 135 | { |
499 | struct rb_node *node; | 136 | struct rb_node *node; |
500 | struct snd_soc_rbtree_node *rbnode; | 137 | struct snd_soc_rbtree_node *rbnode; |
138 | unsigned int base_reg, top_reg; | ||
501 | 139 | ||
502 | node = root->rb_node; | 140 | node = root->rb_node; |
503 | while (node) { | 141 | while (node) { |
504 | rbnode = container_of(node, struct snd_soc_rbtree_node, node); | 142 | rbnode = container_of(node, struct snd_soc_rbtree_node, node); |
505 | if (rbnode->reg < reg) | 143 | snd_soc_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg); |
506 | node = node->rb_left; | 144 | if (reg >= base_reg && reg <= top_reg) |
507 | else if (rbnode->reg > reg) | ||
508 | node = node->rb_right; | ||
509 | else | ||
510 | return rbnode; | 145 | return rbnode; |
146 | else if (reg > top_reg) | ||
147 | node = node->rb_right; | ||
148 | else if (reg < base_reg) | ||
149 | node = node->rb_left; | ||
511 | } | 150 | } |
512 | 151 | ||
513 | return NULL; | 152 | return NULL; |
@@ -518,19 +157,28 @@ static int snd_soc_rbtree_insert(struct rb_root *root, | |||
518 | { | 157 | { |
519 | struct rb_node **new, *parent; | 158 | struct rb_node **new, *parent; |
520 | struct snd_soc_rbtree_node *rbnode_tmp; | 159 | struct snd_soc_rbtree_node *rbnode_tmp; |
160 | unsigned int base_reg_tmp, top_reg_tmp; | ||
161 | unsigned int base_reg; | ||
521 | 162 | ||
522 | parent = NULL; | 163 | parent = NULL; |
523 | new = &root->rb_node; | 164 | new = &root->rb_node; |
524 | while (*new) { | 165 | while (*new) { |
525 | rbnode_tmp = container_of(*new, struct snd_soc_rbtree_node, | 166 | rbnode_tmp = container_of(*new, struct snd_soc_rbtree_node, |
526 | node); | 167 | node); |
168 | /* base and top registers of the current rbnode */ | ||
169 | snd_soc_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp, | ||
170 | &top_reg_tmp); | ||
171 | /* base register of the rbnode to be added */ | ||
172 | base_reg = rbnode->base_reg; | ||
527 | parent = *new; | 173 | parent = *new; |
528 | if (rbnode_tmp->reg < rbnode->reg) | 174 | /* if this register has already been inserted, just return */ |
529 | new = &((*new)->rb_left); | 175 | if (base_reg >= base_reg_tmp && |
530 | else if (rbnode_tmp->reg > rbnode->reg) | 176 | base_reg <= top_reg_tmp) |
531 | new = &((*new)->rb_right); | ||
532 | else | ||
533 | return 0; | 177 | return 0; |
178 | else if (base_reg > top_reg_tmp) | ||
179 | new = &((*new)->rb_right); | ||
180 | else if (base_reg < base_reg_tmp) | ||
181 | new = &((*new)->rb_left); | ||
534 | } | 182 | } |
535 | 183 | ||
536 | /* insert the node into the rbtree */ | 184 | /* insert the node into the rbtree */ |
@@ -545,58 +193,146 @@ static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec) | |||
545 | struct snd_soc_rbtree_ctx *rbtree_ctx; | 193 | struct snd_soc_rbtree_ctx *rbtree_ctx; |
546 | struct rb_node *node; | 194 | struct rb_node *node; |
547 | struct snd_soc_rbtree_node *rbnode; | 195 | struct snd_soc_rbtree_node *rbnode; |
548 | unsigned int val; | 196 | unsigned int regtmp; |
197 | unsigned int val, def; | ||
549 | int ret; | 198 | int ret; |
199 | int i; | ||
550 | 200 | ||
551 | rbtree_ctx = codec->reg_cache; | 201 | rbtree_ctx = codec->reg_cache; |
552 | for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) { | 202 | for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) { |
553 | rbnode = rb_entry(node, struct snd_soc_rbtree_node, node); | 203 | rbnode = rb_entry(node, struct snd_soc_rbtree_node, node); |
554 | if (rbnode->value == rbnode->defval) | 204 | for (i = 0; i < rbnode->blklen; ++i) { |
555 | continue; | 205 | regtmp = rbnode->base_reg + i; |
556 | WARN_ON(codec->writable_register && | 206 | WARN_ON(codec->writable_register && |
557 | codec->writable_register(codec, rbnode->reg)); | 207 | codec->writable_register(codec, regtmp)); |
558 | ret = snd_soc_cache_read(codec, rbnode->reg, &val); | 208 | val = snd_soc_rbtree_get_register(rbnode, i); |
559 | if (ret) | 209 | def = snd_soc_get_cache_val(codec->reg_def_copy, i, |
560 | return ret; | 210 | rbnode->word_size); |
561 | codec->cache_bypass = 1; | 211 | if (val == def) |
562 | ret = snd_soc_write(codec, rbnode->reg, val); | 212 | continue; |
563 | codec->cache_bypass = 0; | 213 | |
564 | if (ret) | 214 | codec->cache_bypass = 1; |
565 | return ret; | 215 | ret = snd_soc_write(codec, regtmp, val); |
566 | dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", | 216 | codec->cache_bypass = 0; |
567 | rbnode->reg, val); | 217 | if (ret) |
218 | return ret; | ||
219 | dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", | ||
220 | regtmp, val); | ||
221 | } | ||
568 | } | 222 | } |
569 | 223 | ||
570 | return 0; | 224 | return 0; |
571 | } | 225 | } |
572 | 226 | ||
227 | static int snd_soc_rbtree_insert_to_block(struct snd_soc_rbtree_node *rbnode, | ||
228 | unsigned int pos, unsigned int reg, | ||
229 | unsigned int value) | ||
230 | { | ||
231 | u8 *blk; | ||
232 | |||
233 | blk = krealloc(rbnode->block, | ||
234 | (rbnode->blklen + 1) * rbnode->word_size, GFP_KERNEL); | ||
235 | if (!blk) | ||
236 | return -ENOMEM; | ||
237 | |||
238 | /* insert the register value in the correct place in the rbnode block */ | ||
239 | memmove(blk + (pos + 1) * rbnode->word_size, | ||
240 | blk + pos * rbnode->word_size, | ||
241 | (rbnode->blklen - pos) * rbnode->word_size); | ||
242 | |||
243 | /* update the rbnode block, its size and the base register */ | ||
244 | rbnode->block = blk; | ||
245 | rbnode->blklen++; | ||
246 | if (!pos) | ||
247 | rbnode->base_reg = reg; | ||
248 | |||
249 | snd_soc_rbtree_set_register(rbnode, pos, value); | ||
250 | return 0; | ||
251 | } | ||
252 | |||
573 | static int snd_soc_rbtree_cache_write(struct snd_soc_codec *codec, | 253 | static int snd_soc_rbtree_cache_write(struct snd_soc_codec *codec, |
574 | unsigned int reg, unsigned int value) | 254 | unsigned int reg, unsigned int value) |
575 | { | 255 | { |
576 | struct snd_soc_rbtree_ctx *rbtree_ctx; | 256 | struct snd_soc_rbtree_ctx *rbtree_ctx; |
577 | struct snd_soc_rbtree_node *rbnode; | 257 | struct snd_soc_rbtree_node *rbnode, *rbnode_tmp; |
258 | struct rb_node *node; | ||
259 | unsigned int val; | ||
260 | unsigned int reg_tmp; | ||
261 | unsigned int base_reg, top_reg; | ||
262 | unsigned int pos; | ||
263 | int i; | ||
264 | int ret; | ||
578 | 265 | ||
579 | rbtree_ctx = codec->reg_cache; | 266 | rbtree_ctx = codec->reg_cache; |
267 | /* look up the required register in the cached rbnode */ | ||
268 | rbnode = rbtree_ctx->cached_rbnode; | ||
269 | if (rbnode) { | ||
270 | snd_soc_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg); | ||
271 | if (reg >= base_reg && reg <= top_reg) { | ||
272 | reg_tmp = reg - base_reg; | ||
273 | val = snd_soc_rbtree_get_register(rbnode, reg_tmp); | ||
274 | if (val == value) | ||
275 | return 0; | ||
276 | snd_soc_rbtree_set_register(rbnode, reg_tmp, value); | ||
277 | return 0; | ||
278 | } | ||
279 | } | ||
280 | /* if we can't locate it in the cached rbnode we'll have | ||
281 | * to traverse the rbtree looking for it. | ||
282 | */ | ||
580 | rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg); | 283 | rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg); |
581 | if (rbnode) { | 284 | if (rbnode) { |
582 | if (rbnode->value == value) | 285 | reg_tmp = reg - rbnode->base_reg; |
286 | val = snd_soc_rbtree_get_register(rbnode, reg_tmp); | ||
287 | if (val == value) | ||
583 | return 0; | 288 | return 0; |
584 | rbnode->value = value; | 289 | snd_soc_rbtree_set_register(rbnode, reg_tmp, value); |
290 | rbtree_ctx->cached_rbnode = rbnode; | ||
585 | } else { | 291 | } else { |
586 | /* bail out early, no need to create the rbnode yet */ | 292 | /* bail out early, no need to create the rbnode yet */ |
587 | if (!value) | 293 | if (!value) |
588 | return 0; | 294 | return 0; |
589 | /* | 295 | /* look for an adjacent register to the one we are about to add */ |
590 | * for uninitialized registers whose value is changed | 296 | for (node = rb_first(&rbtree_ctx->root); node; |
591 | * from the default zero, create an rbnode and insert | 297 | node = rb_next(node)) { |
592 | * it into the tree. | 298 | rbnode_tmp = rb_entry(node, struct snd_soc_rbtree_node, node); |
299 | for (i = 0; i < rbnode_tmp->blklen; ++i) { | ||
300 | reg_tmp = rbnode_tmp->base_reg + i; | ||
301 | if (abs(reg_tmp - reg) != 1) | ||
302 | continue; | ||
303 | /* decide where in the block to place our register */ | ||
304 | if (reg_tmp + 1 == reg) | ||
305 | pos = i + 1; | ||
306 | else | ||
307 | pos = i; | ||
308 | ret = snd_soc_rbtree_insert_to_block(rbnode_tmp, pos, | ||
309 | reg, value); | ||
310 | if (ret) | ||
311 | return ret; | ||
312 | rbtree_ctx->cached_rbnode = rbnode_tmp; | ||
313 | return 0; | ||
314 | } | ||
315 | } | ||
316 | /* we did not manage to find a place to insert it in an existing | ||
317 | * block so create a new rbnode with a single register in its block. | ||
318 | * This block will get populated further if any other adjacent | ||
319 | * registers get modified in the future. | ||
593 | */ | 320 | */ |
594 | rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL); | 321 | rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL); |
595 | if (!rbnode) | 322 | if (!rbnode) |
596 | return -ENOMEM; | 323 | return -ENOMEM; |
597 | rbnode->reg = reg; | 324 | rbnode->blklen = 1; |
598 | rbnode->value = value; | 325 | rbnode->base_reg = reg; |
326 | rbnode->word_size = codec->driver->reg_word_size; | ||
327 | rbnode->block = kmalloc(rbnode->blklen * rbnode->word_size, | ||
328 | GFP_KERNEL); | ||
329 | if (!rbnode->block) { | ||
330 | kfree(rbnode); | ||
331 | return -ENOMEM; | ||
332 | } | ||
333 | snd_soc_rbtree_set_register(rbnode, 0, value); | ||
599 | snd_soc_rbtree_insert(&rbtree_ctx->root, rbnode); | 334 | snd_soc_rbtree_insert(&rbtree_ctx->root, rbnode); |
335 | rbtree_ctx->cached_rbnode = rbnode; | ||
600 | } | 336 | } |
601 | 337 | ||
602 | return 0; | 338 | return 0; |
@@ -607,11 +343,28 @@ static int snd_soc_rbtree_cache_read(struct snd_soc_codec *codec, | |||
607 | { | 343 | { |
608 | struct snd_soc_rbtree_ctx *rbtree_ctx; | 344 | struct snd_soc_rbtree_ctx *rbtree_ctx; |
609 | struct snd_soc_rbtree_node *rbnode; | 345 | struct snd_soc_rbtree_node *rbnode; |
346 | unsigned int base_reg, top_reg; | ||
347 | unsigned int reg_tmp; | ||
610 | 348 | ||
611 | rbtree_ctx = codec->reg_cache; | 349 | rbtree_ctx = codec->reg_cache; |
350 | /* look up the required register in the cached rbnode */ | ||
351 | rbnode = rbtree_ctx->cached_rbnode; | ||
352 | if (rbnode) { | ||
353 | snd_soc_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg); | ||
354 | if (reg >= base_reg && reg <= top_reg) { | ||
355 | reg_tmp = reg - base_reg; | ||
356 | *value = snd_soc_rbtree_get_register(rbnode, reg_tmp); | ||
357 | return 0; | ||
358 | } | ||
359 | } | ||
360 | /* if we can't locate it in the cached rbnode we'll have | ||
361 | * to traverse the rbtree looking for it. | ||
362 | */ | ||
612 | rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg); | 363 | rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg); |
613 | if (rbnode) { | 364 | if (rbnode) { |
614 | *value = rbnode->value; | 365 | reg_tmp = reg - rbnode->base_reg; |
366 | *value = snd_soc_rbtree_get_register(rbnode, reg_tmp); | ||
367 | rbtree_ctx->cached_rbnode = rbnode; | ||
615 | } else { | 368 | } else { |
616 | /* uninitialized registers default to 0 */ | 369 | /* uninitialized registers default to 0 */ |
617 | *value = 0; | 370 | *value = 0; |
@@ -637,6 +390,7 @@ static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec) | |||
637 | rbtree_node = rb_entry(next, struct snd_soc_rbtree_node, node); | 390 | rbtree_node = rb_entry(next, struct snd_soc_rbtree_node, node); |
638 | next = rb_next(&rbtree_node->node); | 391 | next = rb_next(&rbtree_node->node); |
639 | rb_erase(&rbtree_node->node, &rbtree_ctx->root); | 392 | rb_erase(&rbtree_node->node, &rbtree_ctx->root); |
393 | kfree(rbtree_node->block); | ||
640 | kfree(rbtree_node); | 394 | kfree(rbtree_node); |
641 | } | 395 | } |
642 | 396 | ||
@@ -649,10 +403,9 @@ static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec) | |||
649 | 403 | ||
650 | static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec) | 404 | static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec) |
651 | { | 405 | { |
652 | struct snd_soc_rbtree_node *rbtree_node; | ||
653 | struct snd_soc_rbtree_ctx *rbtree_ctx; | 406 | struct snd_soc_rbtree_ctx *rbtree_ctx; |
654 | unsigned int val; | ||
655 | unsigned int word_size; | 407 | unsigned int word_size; |
408 | unsigned int val; | ||
656 | int i; | 409 | int i; |
657 | int ret; | 410 | int ret; |
658 | 411 | ||
@@ -662,32 +415,27 @@ static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec) | |||
662 | 415 | ||
663 | rbtree_ctx = codec->reg_cache; | 416 | rbtree_ctx = codec->reg_cache; |
664 | rbtree_ctx->root = RB_ROOT; | 417 | rbtree_ctx->root = RB_ROOT; |
418 | rbtree_ctx->cached_rbnode = NULL; | ||
665 | 419 | ||
666 | if (!codec->reg_def_copy) | 420 | if (!codec->reg_def_copy) |
667 | return 0; | 421 | return 0; |
668 | 422 | ||
669 | /* | ||
670 | * populate the rbtree with the initialized registers. All other | ||
671 | * registers will be inserted when they are first modified. | ||
672 | */ | ||
673 | word_size = codec->driver->reg_word_size; | 423 | word_size = codec->driver->reg_word_size; |
674 | for (i = 0; i < codec->driver->reg_cache_size; ++i) { | 424 | for (i = 0; i < codec->driver->reg_cache_size; ++i) { |
675 | val = snd_soc_get_cache_val(codec->reg_def_copy, i, word_size); | 425 | val = snd_soc_get_cache_val(codec->reg_def_copy, i, |
426 | word_size); | ||
676 | if (!val) | 427 | if (!val) |
677 | continue; | 428 | continue; |
678 | rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL); | 429 | ret = snd_soc_rbtree_cache_write(codec, i, val); |
679 | if (!rbtree_node) { | 430 | if (ret) |
680 | ret = -ENOMEM; | 431 | goto err; |
681 | snd_soc_cache_exit(codec); | ||
682 | break; | ||
683 | } | ||
684 | rbtree_node->reg = i; | ||
685 | rbtree_node->value = val; | ||
686 | rbtree_node->defval = val; | ||
687 | snd_soc_rbtree_insert(&rbtree_ctx->root, rbtree_node); | ||
688 | } | 432 | } |
689 | 433 | ||
690 | return 0; | 434 | return 0; |
435 | |||
436 | err: | ||
437 | snd_soc_cache_exit(codec); | ||
438 | return ret; | ||
691 | } | 439 | } |
692 | 440 | ||
693 | #ifdef CONFIG_SND_SOC_CACHE_LZO | 441 | #ifdef CONFIG_SND_SOC_CACHE_LZO |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d75043ed7fc0..e44267f66216 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -44,7 +44,6 @@ | |||
44 | 44 | ||
45 | #define NAME_SIZE 32 | 45 | #define NAME_SIZE 32 |
46 | 46 | ||
47 | static DEFINE_MUTEX(pcm_mutex); | ||
48 | static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); | 47 | static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); |
49 | 48 | ||
50 | #ifdef CONFIG_DEBUG_FS | 49 | #ifdef CONFIG_DEBUG_FS |
@@ -58,7 +57,7 @@ static LIST_HEAD(dai_list); | |||
58 | static LIST_HEAD(platform_list); | 57 | static LIST_HEAD(platform_list); |
59 | static LIST_HEAD(codec_list); | 58 | static LIST_HEAD(codec_list); |
60 | 59 | ||
61 | static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); | 60 | int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); |
62 | 61 | ||
63 | /* | 62 | /* |
64 | * This is a timeout to do a DAPM powerdown after a stream is closed(). | 63 | * This is a timeout to do a DAPM powerdown after a stream is closed(). |
@@ -485,552 +484,6 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) | |||
485 | } | 484 | } |
486 | #endif | 485 | #endif |
487 | 486 | ||
488 | static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) | ||
489 | { | ||
490 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
491 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
492 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
493 | int ret; | ||
494 | |||
495 | if (!codec_dai->driver->symmetric_rates && | ||
496 | !cpu_dai->driver->symmetric_rates && | ||
497 | !rtd->dai_link->symmetric_rates) | ||
498 | return 0; | ||
499 | |||
500 | /* This can happen if multiple streams are starting simultaneously - | ||
501 | * the second can need to get its constraints before the first has | ||
502 | * picked a rate. Complain and allow the application to carry on. | ||
503 | */ | ||
504 | if (!rtd->rate) { | ||
505 | dev_warn(&rtd->dev, | ||
506 | "Not enforcing symmetric_rates due to race\n"); | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate); | ||
511 | |||
512 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, | ||
513 | SNDRV_PCM_HW_PARAM_RATE, | ||
514 | rtd->rate, rtd->rate); | ||
515 | if (ret < 0) { | ||
516 | dev_err(&rtd->dev, | ||
517 | "Unable to apply rate symmetry constraint: %d\n", ret); | ||
518 | return ret; | ||
519 | } | ||
520 | |||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | /* | ||
525 | * Called by ALSA when a PCM substream is opened, the runtime->hw record is | ||
526 | * then initialized and any private data can be allocated. This also calls | ||
527 | * startup for the cpu DAI, platform, machine and codec DAI. | ||
528 | */ | ||
529 | static int soc_pcm_open(struct snd_pcm_substream *substream) | ||
530 | { | ||
531 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
532 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
533 | struct snd_soc_platform *platform = rtd->platform; | ||
534 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
535 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
536 | struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; | ||
537 | struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; | ||
538 | int ret = 0; | ||
539 | |||
540 | mutex_lock(&pcm_mutex); | ||
541 | |||
542 | /* startup the audio subsystem */ | ||
543 | if (cpu_dai->driver->ops->startup) { | ||
544 | ret = cpu_dai->driver->ops->startup(substream, cpu_dai); | ||
545 | if (ret < 0) { | ||
546 | printk(KERN_ERR "asoc: can't open interface %s\n", | ||
547 | cpu_dai->name); | ||
548 | goto out; | ||
549 | } | ||
550 | } | ||
551 | |||
552 | if (platform->driver->ops && platform->driver->ops->open) { | ||
553 | ret = platform->driver->ops->open(substream); | ||
554 | if (ret < 0) { | ||
555 | printk(KERN_ERR "asoc: can't open platform %s\n", platform->name); | ||
556 | goto platform_err; | ||
557 | } | ||
558 | } | ||
559 | |||
560 | if (codec_dai->driver->ops->startup) { | ||
561 | ret = codec_dai->driver->ops->startup(substream, codec_dai); | ||
562 | if (ret < 0) { | ||
563 | printk(KERN_ERR "asoc: can't open codec %s\n", | ||
564 | codec_dai->name); | ||
565 | goto codec_dai_err; | ||
566 | } | ||
567 | } | ||
568 | |||
569 | if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { | ||
570 | ret = rtd->dai_link->ops->startup(substream); | ||
571 | if (ret < 0) { | ||
572 | printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name); | ||
573 | goto machine_err; | ||
574 | } | ||
575 | } | ||
576 | |||
577 | /* Check that the codec and cpu DAIs are compatible */ | ||
578 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
579 | runtime->hw.rate_min = | ||
580 | max(codec_dai_drv->playback.rate_min, | ||
581 | cpu_dai_drv->playback.rate_min); | ||
582 | runtime->hw.rate_max = | ||
583 | min(codec_dai_drv->playback.rate_max, | ||
584 | cpu_dai_drv->playback.rate_max); | ||
585 | runtime->hw.channels_min = | ||
586 | max(codec_dai_drv->playback.channels_min, | ||
587 | cpu_dai_drv->playback.channels_min); | ||
588 | runtime->hw.channels_max = | ||
589 | min(codec_dai_drv->playback.channels_max, | ||
590 | cpu_dai_drv->playback.channels_max); | ||
591 | runtime->hw.formats = | ||
592 | codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats; | ||
593 | runtime->hw.rates = | ||
594 | codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates; | ||
595 | if (codec_dai_drv->playback.rates | ||
596 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
597 | runtime->hw.rates |= cpu_dai_drv->playback.rates; | ||
598 | if (cpu_dai_drv->playback.rates | ||
599 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
600 | runtime->hw.rates |= codec_dai_drv->playback.rates; | ||
601 | } else { | ||
602 | runtime->hw.rate_min = | ||
603 | max(codec_dai_drv->capture.rate_min, | ||
604 | cpu_dai_drv->capture.rate_min); | ||
605 | runtime->hw.rate_max = | ||
606 | min(codec_dai_drv->capture.rate_max, | ||
607 | cpu_dai_drv->capture.rate_max); | ||
608 | runtime->hw.channels_min = | ||
609 | max(codec_dai_drv->capture.channels_min, | ||
610 | cpu_dai_drv->capture.channels_min); | ||
611 | runtime->hw.channels_max = | ||
612 | min(codec_dai_drv->capture.channels_max, | ||
613 | cpu_dai_drv->capture.channels_max); | ||
614 | runtime->hw.formats = | ||
615 | codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats; | ||
616 | runtime->hw.rates = | ||
617 | codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates; | ||
618 | if (codec_dai_drv->capture.rates | ||
619 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
620 | runtime->hw.rates |= cpu_dai_drv->capture.rates; | ||
621 | if (cpu_dai_drv->capture.rates | ||
622 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
623 | runtime->hw.rates |= codec_dai_drv->capture.rates; | ||
624 | } | ||
625 | |||
626 | ret = -EINVAL; | ||
627 | snd_pcm_limit_hw_rates(runtime); | ||
628 | if (!runtime->hw.rates) { | ||
629 | printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", | ||
630 | codec_dai->name, cpu_dai->name); | ||
631 | goto config_err; | ||
632 | } | ||
633 | if (!runtime->hw.formats) { | ||
634 | printk(KERN_ERR "asoc: %s <-> %s No matching formats\n", | ||
635 | codec_dai->name, cpu_dai->name); | ||
636 | goto config_err; | ||
637 | } | ||
638 | if (!runtime->hw.channels_min || !runtime->hw.channels_max || | ||
639 | runtime->hw.channels_min > runtime->hw.channels_max) { | ||
640 | printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", | ||
641 | codec_dai->name, cpu_dai->name); | ||
642 | goto config_err; | ||
643 | } | ||
644 | |||
645 | /* Symmetry only applies if we've already got an active stream. */ | ||
646 | if (cpu_dai->active || codec_dai->active) { | ||
647 | ret = soc_pcm_apply_symmetry(substream); | ||
648 | if (ret != 0) | ||
649 | goto config_err; | ||
650 | } | ||
651 | |||
652 | pr_debug("asoc: %s <-> %s info:\n", | ||
653 | codec_dai->name, cpu_dai->name); | ||
654 | pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); | ||
655 | pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, | ||
656 | runtime->hw.channels_max); | ||
657 | pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, | ||
658 | runtime->hw.rate_max); | ||
659 | |||
660 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
661 | cpu_dai->playback_active++; | ||
662 | codec_dai->playback_active++; | ||
663 | } else { | ||
664 | cpu_dai->capture_active++; | ||
665 | codec_dai->capture_active++; | ||
666 | } | ||
667 | cpu_dai->active++; | ||
668 | codec_dai->active++; | ||
669 | rtd->codec->active++; | ||
670 | mutex_unlock(&pcm_mutex); | ||
671 | return 0; | ||
672 | |||
673 | config_err: | ||
674 | if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) | ||
675 | rtd->dai_link->ops->shutdown(substream); | ||
676 | |||
677 | machine_err: | ||
678 | if (codec_dai->driver->ops->shutdown) | ||
679 | codec_dai->driver->ops->shutdown(substream, codec_dai); | ||
680 | |||
681 | codec_dai_err: | ||
682 | if (platform->driver->ops && platform->driver->ops->close) | ||
683 | platform->driver->ops->close(substream); | ||
684 | |||
685 | platform_err: | ||
686 | if (cpu_dai->driver->ops->shutdown) | ||
687 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | ||
688 | out: | ||
689 | mutex_unlock(&pcm_mutex); | ||
690 | return ret; | ||
691 | } | ||
692 | |||
693 | /* | ||
694 | * Power down the audio subsystem pmdown_time msecs after close is called. | ||
695 | * This is to ensure there are no pops or clicks in between any music tracks | ||
696 | * due to DAPM power cycling. | ||
697 | */ | ||
698 | static void close_delayed_work(struct work_struct *work) | ||
699 | { | ||
700 | struct snd_soc_pcm_runtime *rtd = | ||
701 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); | ||
702 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
703 | |||
704 | mutex_lock(&pcm_mutex); | ||
705 | |||
706 | pr_debug("pop wq checking: %s status: %s waiting: %s\n", | ||
707 | codec_dai->driver->playback.stream_name, | ||
708 | codec_dai->playback_active ? "active" : "inactive", | ||
709 | codec_dai->pop_wait ? "yes" : "no"); | ||
710 | |||
711 | /* are we waiting on this codec DAI stream */ | ||
712 | if (codec_dai->pop_wait == 1) { | ||
713 | codec_dai->pop_wait = 0; | ||
714 | snd_soc_dapm_stream_event(rtd, | ||
715 | codec_dai->driver->playback.stream_name, | ||
716 | SND_SOC_DAPM_STREAM_STOP); | ||
717 | } | ||
718 | |||
719 | mutex_unlock(&pcm_mutex); | ||
720 | } | ||
721 | |||
722 | /* | ||
723 | * Called by ALSA when a PCM substream is closed. Private data can be | ||
724 | * freed here. The cpu DAI, codec DAI, machine and platform are also | ||
725 | * shutdown. | ||
726 | */ | ||
727 | static int soc_codec_close(struct snd_pcm_substream *substream) | ||
728 | { | ||
729 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
730 | struct snd_soc_platform *platform = rtd->platform; | ||
731 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
732 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
733 | struct snd_soc_codec *codec = rtd->codec; | ||
734 | |||
735 | mutex_lock(&pcm_mutex); | ||
736 | |||
737 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
738 | cpu_dai->playback_active--; | ||
739 | codec_dai->playback_active--; | ||
740 | } else { | ||
741 | cpu_dai->capture_active--; | ||
742 | codec_dai->capture_active--; | ||
743 | } | ||
744 | |||
745 | cpu_dai->active--; | ||
746 | codec_dai->active--; | ||
747 | codec->active--; | ||
748 | |||
749 | /* Muting the DAC suppresses artifacts caused during digital | ||
750 | * shutdown, for example from stopping clocks. | ||
751 | */ | ||
752 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
753 | snd_soc_dai_digital_mute(codec_dai, 1); | ||
754 | |||
755 | if (cpu_dai->driver->ops->shutdown) | ||
756 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | ||
757 | |||
758 | if (codec_dai->driver->ops->shutdown) | ||
759 | codec_dai->driver->ops->shutdown(substream, codec_dai); | ||
760 | |||
761 | if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) | ||
762 | rtd->dai_link->ops->shutdown(substream); | ||
763 | |||
764 | if (platform->driver->ops && platform->driver->ops->close) | ||
765 | platform->driver->ops->close(substream); | ||
766 | cpu_dai->runtime = NULL; | ||
767 | |||
768 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
769 | /* start delayed pop wq here for playback streams */ | ||
770 | codec_dai->pop_wait = 1; | ||
771 | schedule_delayed_work(&rtd->delayed_work, | ||
772 | msecs_to_jiffies(rtd->pmdown_time)); | ||
773 | } else { | ||
774 | /* capture streams can be powered down now */ | ||
775 | snd_soc_dapm_stream_event(rtd, | ||
776 | codec_dai->driver->capture.stream_name, | ||
777 | SND_SOC_DAPM_STREAM_STOP); | ||
778 | } | ||
779 | |||
780 | mutex_unlock(&pcm_mutex); | ||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | /* | ||
785 | * Called by ALSA when the PCM substream is prepared, can set format, sample | ||
786 | * rate, etc. This function is non atomic and can be called multiple times, | ||
787 | * it can refer to the runtime info. | ||
788 | */ | ||
789 | static int soc_pcm_prepare(struct snd_pcm_substream *substream) | ||
790 | { | ||
791 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
792 | struct snd_soc_platform *platform = rtd->platform; | ||
793 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
794 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
795 | int ret = 0; | ||
796 | |||
797 | mutex_lock(&pcm_mutex); | ||
798 | |||
799 | if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) { | ||
800 | ret = rtd->dai_link->ops->prepare(substream); | ||
801 | if (ret < 0) { | ||
802 | printk(KERN_ERR "asoc: machine prepare error\n"); | ||
803 | goto out; | ||
804 | } | ||
805 | } | ||
806 | |||
807 | if (platform->driver->ops && platform->driver->ops->prepare) { | ||
808 | ret = platform->driver->ops->prepare(substream); | ||
809 | if (ret < 0) { | ||
810 | printk(KERN_ERR "asoc: platform prepare error\n"); | ||
811 | goto out; | ||
812 | } | ||
813 | } | ||
814 | |||
815 | if (codec_dai->driver->ops->prepare) { | ||
816 | ret = codec_dai->driver->ops->prepare(substream, codec_dai); | ||
817 | if (ret < 0) { | ||
818 | printk(KERN_ERR "asoc: codec DAI prepare error\n"); | ||
819 | goto out; | ||
820 | } | ||
821 | } | ||
822 | |||
823 | if (cpu_dai->driver->ops->prepare) { | ||
824 | ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); | ||
825 | if (ret < 0) { | ||
826 | printk(KERN_ERR "asoc: cpu DAI prepare error\n"); | ||
827 | goto out; | ||
828 | } | ||
829 | } | ||
830 | |||
831 | /* cancel any delayed stream shutdown that is pending */ | ||
832 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | ||
833 | codec_dai->pop_wait) { | ||
834 | codec_dai->pop_wait = 0; | ||
835 | cancel_delayed_work(&rtd->delayed_work); | ||
836 | } | ||
837 | |||
838 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
839 | snd_soc_dapm_stream_event(rtd, | ||
840 | codec_dai->driver->playback.stream_name, | ||
841 | SND_SOC_DAPM_STREAM_START); | ||
842 | else | ||
843 | snd_soc_dapm_stream_event(rtd, | ||
844 | codec_dai->driver->capture.stream_name, | ||
845 | SND_SOC_DAPM_STREAM_START); | ||
846 | |||
847 | snd_soc_dai_digital_mute(codec_dai, 0); | ||
848 | |||
849 | out: | ||
850 | mutex_unlock(&pcm_mutex); | ||
851 | return ret; | ||
852 | } | ||
853 | |||
854 | /* | ||
855 | * Called by ALSA when the hardware params are set by application. This | ||
856 | * function can also be called multiple times and can allocate buffers | ||
857 | * (using snd_pcm_lib_* ). It's non-atomic. | ||
858 | */ | ||
859 | static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | ||
860 | struct snd_pcm_hw_params *params) | ||
861 | { | ||
862 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
863 | struct snd_soc_platform *platform = rtd->platform; | ||
864 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
865 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
866 | int ret = 0; | ||
867 | |||
868 | mutex_lock(&pcm_mutex); | ||
869 | |||
870 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { | ||
871 | ret = rtd->dai_link->ops->hw_params(substream, params); | ||
872 | if (ret < 0) { | ||
873 | printk(KERN_ERR "asoc: machine hw_params failed\n"); | ||
874 | goto out; | ||
875 | } | ||
876 | } | ||
877 | |||
878 | if (codec_dai->driver->ops->hw_params) { | ||
879 | ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); | ||
880 | if (ret < 0) { | ||
881 | printk(KERN_ERR "asoc: can't set codec %s hw params\n", | ||
882 | codec_dai->name); | ||
883 | goto codec_err; | ||
884 | } | ||
885 | } | ||
886 | |||
887 | if (cpu_dai->driver->ops->hw_params) { | ||
888 | ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai); | ||
889 | if (ret < 0) { | ||
890 | printk(KERN_ERR "asoc: interface %s hw params failed\n", | ||
891 | cpu_dai->name); | ||
892 | goto interface_err; | ||
893 | } | ||
894 | } | ||
895 | |||
896 | if (platform->driver->ops && platform->driver->ops->hw_params) { | ||
897 | ret = platform->driver->ops->hw_params(substream, params); | ||
898 | if (ret < 0) { | ||
899 | printk(KERN_ERR "asoc: platform %s hw params failed\n", | ||
900 | platform->name); | ||
901 | goto platform_err; | ||
902 | } | ||
903 | } | ||
904 | |||
905 | rtd->rate = params_rate(params); | ||
906 | |||
907 | out: | ||
908 | mutex_unlock(&pcm_mutex); | ||
909 | return ret; | ||
910 | |||
911 | platform_err: | ||
912 | if (cpu_dai->driver->ops->hw_free) | ||
913 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | ||
914 | |||
915 | interface_err: | ||
916 | if (codec_dai->driver->ops->hw_free) | ||
917 | codec_dai->driver->ops->hw_free(substream, codec_dai); | ||
918 | |||
919 | codec_err: | ||
920 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) | ||
921 | rtd->dai_link->ops->hw_free(substream); | ||
922 | |||
923 | mutex_unlock(&pcm_mutex); | ||
924 | return ret; | ||
925 | } | ||
926 | |||
927 | /* | ||
928 | * Frees resources allocated by hw_params, can be called multiple times | ||
929 | */ | ||
930 | static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | ||
931 | { | ||
932 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
933 | struct snd_soc_platform *platform = rtd->platform; | ||
934 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
935 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
936 | struct snd_soc_codec *codec = rtd->codec; | ||
937 | |||
938 | mutex_lock(&pcm_mutex); | ||
939 | |||
940 | /* apply codec digital mute */ | ||
941 | if (!codec->active) | ||
942 | snd_soc_dai_digital_mute(codec_dai, 1); | ||
943 | |||
944 | /* free any machine hw params */ | ||
945 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) | ||
946 | rtd->dai_link->ops->hw_free(substream); | ||
947 | |||
948 | /* free any DMA resources */ | ||
949 | if (platform->driver->ops && platform->driver->ops->hw_free) | ||
950 | platform->driver->ops->hw_free(substream); | ||
951 | |||
952 | /* now free hw params for the DAIs */ | ||
953 | if (codec_dai->driver->ops->hw_free) | ||
954 | codec_dai->driver->ops->hw_free(substream, codec_dai); | ||
955 | |||
956 | if (cpu_dai->driver->ops->hw_free) | ||
957 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | ||
958 | |||
959 | mutex_unlock(&pcm_mutex); | ||
960 | return 0; | ||
961 | } | ||
962 | |||
963 | static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
964 | { | ||
965 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
966 | struct snd_soc_platform *platform = rtd->platform; | ||
967 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
968 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
969 | int ret; | ||
970 | |||
971 | if (codec_dai->driver->ops->trigger) { | ||
972 | ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai); | ||
973 | if (ret < 0) | ||
974 | return ret; | ||
975 | } | ||
976 | |||
977 | if (platform->driver->ops && platform->driver->ops->trigger) { | ||
978 | ret = platform->driver->ops->trigger(substream, cmd); | ||
979 | if (ret < 0) | ||
980 | return ret; | ||
981 | } | ||
982 | |||
983 | if (cpu_dai->driver->ops->trigger) { | ||
984 | ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai); | ||
985 | if (ret < 0) | ||
986 | return ret; | ||
987 | } | ||
988 | return 0; | ||
989 | } | ||
990 | |||
991 | /* | ||
992 | * soc level wrapper for pointer callback | ||
993 | * If cpu_dai, codec_dai, platform driver has the delay callback, than | ||
994 | * the runtime->delay will be updated accordingly. | ||
995 | */ | ||
996 | static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | ||
997 | { | ||
998 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
999 | struct snd_soc_platform *platform = rtd->platform; | ||
1000 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
1001 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
1002 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1003 | snd_pcm_uframes_t offset = 0; | ||
1004 | snd_pcm_sframes_t delay = 0; | ||
1005 | |||
1006 | if (platform->driver->ops && platform->driver->ops->pointer) | ||
1007 | offset = platform->driver->ops->pointer(substream); | ||
1008 | |||
1009 | if (cpu_dai->driver->ops->delay) | ||
1010 | delay += cpu_dai->driver->ops->delay(substream, cpu_dai); | ||
1011 | |||
1012 | if (codec_dai->driver->ops->delay) | ||
1013 | delay += codec_dai->driver->ops->delay(substream, codec_dai); | ||
1014 | |||
1015 | if (platform->driver->delay) | ||
1016 | delay += platform->driver->delay(substream, codec_dai); | ||
1017 | |||
1018 | runtime->delay = delay; | ||
1019 | |||
1020 | return offset; | ||
1021 | } | ||
1022 | |||
1023 | /* ASoC PCM operations */ | ||
1024 | static struct snd_pcm_ops soc_pcm_ops = { | ||
1025 | .open = soc_pcm_open, | ||
1026 | .close = soc_codec_close, | ||
1027 | .hw_params = soc_pcm_hw_params, | ||
1028 | .hw_free = soc_pcm_hw_free, | ||
1029 | .prepare = soc_pcm_prepare, | ||
1030 | .trigger = soc_pcm_trigger, | ||
1031 | .pointer = soc_pcm_pointer, | ||
1032 | }; | ||
1033 | |||
1034 | #ifdef CONFIG_PM_SLEEP | 487 | #ifdef CONFIG_PM_SLEEP |
1035 | /* powers down audio subsystem for suspend */ | 488 | /* powers down audio subsystem for suspend */ |
1036 | int snd_soc_suspend(struct device *dev) | 489 | int snd_soc_suspend(struct device *dev) |
@@ -1256,7 +709,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
1256 | int snd_soc_resume(struct device *dev) | 709 | int snd_soc_resume(struct device *dev) |
1257 | { | 710 | { |
1258 | struct snd_soc_card *card = dev_get_drvdata(dev); | 711 | struct snd_soc_card *card = dev_get_drvdata(dev); |
1259 | int i; | 712 | int i, ac97_control = 0; |
1260 | 713 | ||
1261 | /* AC97 devices might have other drivers hanging off them so | 714 | /* AC97 devices might have other drivers hanging off them so |
1262 | * need to resume immediately. Other drivers don't have that | 715 | * need to resume immediately. Other drivers don't have that |
@@ -1265,14 +718,15 @@ int snd_soc_resume(struct device *dev) | |||
1265 | */ | 718 | */ |
1266 | for (i = 0; i < card->num_rtd; i++) { | 719 | for (i = 0; i < card->num_rtd; i++) { |
1267 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 720 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
1268 | if (cpu_dai->driver->ac97_control) { | 721 | ac97_control |= cpu_dai->driver->ac97_control; |
1269 | dev_dbg(dev, "Resuming AC97 immediately\n"); | 722 | } |
1270 | soc_resume_deferred(&card->deferred_resume_work); | 723 | if (ac97_control) { |
1271 | } else { | 724 | dev_dbg(dev, "Resuming AC97 immediately\n"); |
1272 | dev_dbg(dev, "Scheduling resume work\n"); | 725 | soc_resume_deferred(&card->deferred_resume_work); |
1273 | if (!schedule_work(&card->deferred_resume_work)) | 726 | } else { |
1274 | dev_err(dev, "resume work item may be lost\n"); | 727 | dev_dbg(dev, "Scheduling resume work\n"); |
1275 | } | 728 | if (!schedule_work(&card->deferred_resume_work)) |
729 | dev_err(dev, "resume work item may be lost\n"); | ||
1276 | } | 730 | } |
1277 | 731 | ||
1278 | return 0; | 732 | return 0; |
@@ -1393,7 +847,7 @@ static void soc_remove_codec(struct snd_soc_codec *codec) | |||
1393 | module_put(codec->dev->driver->owner); | 847 | module_put(codec->dev->driver->owner); |
1394 | } | 848 | } |
1395 | 849 | ||
1396 | static void soc_remove_dai_link(struct snd_soc_card *card, int num) | 850 | static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) |
1397 | { | 851 | { |
1398 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 852 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1399 | struct snd_soc_codec *codec = rtd->codec; | 853 | struct snd_soc_codec *codec = rtd->codec; |
@@ -1410,7 +864,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) | |||
1410 | } | 864 | } |
1411 | 865 | ||
1412 | /* remove the CODEC DAI */ | 866 | /* remove the CODEC DAI */ |
1413 | if (codec_dai && codec_dai->probed) { | 867 | if (codec_dai && codec_dai->probed && |
868 | codec_dai->driver->remove_order == order) { | ||
1414 | if (codec_dai->driver->remove) { | 869 | if (codec_dai->driver->remove) { |
1415 | err = codec_dai->driver->remove(codec_dai); | 870 | err = codec_dai->driver->remove(codec_dai); |
1416 | if (err < 0) | 871 | if (err < 0) |
@@ -1421,7 +876,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) | |||
1421 | } | 876 | } |
1422 | 877 | ||
1423 | /* remove the platform */ | 878 | /* remove the platform */ |
1424 | if (platform && platform->probed) { | 879 | if (platform && platform->probed && |
880 | platform->driver->remove_order == order) { | ||
1425 | if (platform->driver->remove) { | 881 | if (platform->driver->remove) { |
1426 | err = platform->driver->remove(platform); | 882 | err = platform->driver->remove(platform); |
1427 | if (err < 0) | 883 | if (err < 0) |
@@ -1433,11 +889,13 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) | |||
1433 | } | 889 | } |
1434 | 890 | ||
1435 | /* remove the CODEC */ | 891 | /* remove the CODEC */ |
1436 | if (codec && codec->probed) | 892 | if (codec && codec->probed && |
893 | codec->driver->remove_order == order) | ||
1437 | soc_remove_codec(codec); | 894 | soc_remove_codec(codec); |
1438 | 895 | ||
1439 | /* remove the cpu_dai */ | 896 | /* remove the cpu_dai */ |
1440 | if (cpu_dai && cpu_dai->probed) { | 897 | if (cpu_dai && cpu_dai->probed && |
898 | cpu_dai->driver->remove_order == order) { | ||
1441 | if (cpu_dai->driver->remove) { | 899 | if (cpu_dai->driver->remove) { |
1442 | err = cpu_dai->driver->remove(cpu_dai); | 900 | err = cpu_dai->driver->remove(cpu_dai); |
1443 | if (err < 0) | 901 | if (err < 0) |
@@ -1451,11 +909,13 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) | |||
1451 | 909 | ||
1452 | static void soc_remove_dai_links(struct snd_soc_card *card) | 910 | static void soc_remove_dai_links(struct snd_soc_card *card) |
1453 | { | 911 | { |
1454 | int i; | 912 | int dai, order; |
1455 | |||
1456 | for (i = 0; i < card->num_rtd; i++) | ||
1457 | soc_remove_dai_link(card, i); | ||
1458 | 913 | ||
914 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | ||
915 | order++) { | ||
916 | for (dai = 0; dai < card->num_rtd; dai++) | ||
917 | soc_remove_dai_link(card, dai, order); | ||
918 | } | ||
1459 | card->num_rtd = 0; | 919 | card->num_rtd = 0; |
1460 | } | 920 | } |
1461 | 921 | ||
@@ -1526,6 +986,52 @@ err_probe: | |||
1526 | return ret; | 986 | return ret; |
1527 | } | 987 | } |
1528 | 988 | ||
989 | static int soc_probe_platform(struct snd_soc_card *card, | ||
990 | struct snd_soc_platform *platform) | ||
991 | { | ||
992 | int ret = 0; | ||
993 | const struct snd_soc_platform_driver *driver = platform->driver; | ||
994 | |||
995 | platform->card = card; | ||
996 | platform->dapm.card = card; | ||
997 | |||
998 | if (!try_module_get(platform->dev->driver->owner)) | ||
999 | return -ENODEV; | ||
1000 | |||
1001 | if (driver->dapm_widgets) | ||
1002 | snd_soc_dapm_new_controls(&platform->dapm, | ||
1003 | driver->dapm_widgets, driver->num_dapm_widgets); | ||
1004 | |||
1005 | if (driver->probe) { | ||
1006 | ret = driver->probe(platform); | ||
1007 | if (ret < 0) { | ||
1008 | dev_err(platform->dev, | ||
1009 | "asoc: failed to probe platform %s: %d\n", | ||
1010 | platform->name, ret); | ||
1011 | goto err_probe; | ||
1012 | } | ||
1013 | } | ||
1014 | |||
1015 | if (driver->controls) | ||
1016 | snd_soc_add_platform_controls(platform, driver->controls, | ||
1017 | driver->num_controls); | ||
1018 | if (driver->dapm_routes) | ||
1019 | snd_soc_dapm_add_routes(&platform->dapm, driver->dapm_routes, | ||
1020 | driver->num_dapm_routes); | ||
1021 | |||
1022 | /* mark platform as probed and add to card platform list */ | ||
1023 | platform->probed = 1; | ||
1024 | list_add(&platform->card_list, &card->platform_dev_list); | ||
1025 | list_add(&platform->dapm.list, &card->dapm_list); | ||
1026 | |||
1027 | return 0; | ||
1028 | |||
1029 | err_probe: | ||
1030 | module_put(platform->dev->driver->owner); | ||
1031 | |||
1032 | return ret; | ||
1033 | } | ||
1034 | |||
1529 | static void rtd_release(struct device *dev) {} | 1035 | static void rtd_release(struct device *dev) {} |
1530 | 1036 | ||
1531 | static int soc_post_component_init(struct snd_soc_card *card, | 1037 | static int soc_post_component_init(struct snd_soc_card *card, |
@@ -1572,6 +1078,7 @@ static int soc_post_component_init(struct snd_soc_card *card, | |||
1572 | rtd->dev.parent = card->dev; | 1078 | rtd->dev.parent = card->dev; |
1573 | rtd->dev.release = rtd_release; | 1079 | rtd->dev.release = rtd_release; |
1574 | rtd->dev.init_name = name; | 1080 | rtd->dev.init_name = name; |
1081 | mutex_init(&rtd->pcm_mutex); | ||
1575 | ret = device_register(&rtd->dev); | 1082 | ret = device_register(&rtd->dev); |
1576 | if (ret < 0) { | 1083 | if (ret < 0) { |
1577 | dev_err(card->dev, | 1084 | dev_err(card->dev, |
@@ -1596,7 +1103,7 @@ static int soc_post_component_init(struct snd_soc_card *card, | |||
1596 | return 0; | 1103 | return 0; |
1597 | } | 1104 | } |
1598 | 1105 | ||
1599 | static int soc_probe_dai_link(struct snd_soc_card *card, int num) | 1106 | static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) |
1600 | { | 1107 | { |
1601 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 1108 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
1602 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1109 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
@@ -1605,7 +1112,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1605 | struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; | 1112 | struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; |
1606 | int ret; | 1113 | int ret; |
1607 | 1114 | ||
1608 | dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num); | 1115 | dev_dbg(card->dev, "probe %s dai link %d late %d\n", |
1116 | card->name, num, order); | ||
1609 | 1117 | ||
1610 | /* config components */ | 1118 | /* config components */ |
1611 | codec_dai->codec = codec; | 1119 | codec_dai->codec = codec; |
@@ -1617,7 +1125,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1617 | rtd->pmdown_time = pmdown_time; | 1125 | rtd->pmdown_time = pmdown_time; |
1618 | 1126 | ||
1619 | /* probe the cpu_dai */ | 1127 | /* probe the cpu_dai */ |
1620 | if (!cpu_dai->probed) { | 1128 | if (!cpu_dai->probed && |
1129 | cpu_dai->driver->probe_order == order) { | ||
1621 | if (!try_module_get(cpu_dai->dev->driver->owner)) | 1130 | if (!try_module_get(cpu_dai->dev->driver->owner)) |
1622 | return -ENODEV; | 1131 | return -ENODEV; |
1623 | 1132 | ||
@@ -1636,33 +1145,23 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1636 | } | 1145 | } |
1637 | 1146 | ||
1638 | /* probe the CODEC */ | 1147 | /* probe the CODEC */ |
1639 | if (!codec->probed) { | 1148 | if (!codec->probed && |
1149 | codec->driver->probe_order == order) { | ||
1640 | ret = soc_probe_codec(card, codec); | 1150 | ret = soc_probe_codec(card, codec); |
1641 | if (ret < 0) | 1151 | if (ret < 0) |
1642 | return ret; | 1152 | return ret; |
1643 | } | 1153 | } |
1644 | 1154 | ||
1645 | /* probe the platform */ | 1155 | /* probe the platform */ |
1646 | if (!platform->probed) { | 1156 | if (!platform->probed && |
1647 | if (!try_module_get(platform->dev->driver->owner)) | 1157 | platform->driver->probe_order == order) { |
1648 | return -ENODEV; | 1158 | ret = soc_probe_platform(card, platform); |
1649 | 1159 | if (ret < 0) | |
1650 | if (platform->driver->probe) { | 1160 | return ret; |
1651 | ret = platform->driver->probe(platform); | ||
1652 | if (ret < 0) { | ||
1653 | printk(KERN_ERR "asoc: failed to probe platform %s\n", | ||
1654 | platform->name); | ||
1655 | module_put(platform->dev->driver->owner); | ||
1656 | return ret; | ||
1657 | } | ||
1658 | } | ||
1659 | /* mark platform as probed and add to card platform list */ | ||
1660 | platform->probed = 1; | ||
1661 | list_add(&platform->card_list, &card->platform_dev_list); | ||
1662 | } | 1161 | } |
1663 | 1162 | ||
1664 | /* probe the CODEC DAI */ | 1163 | /* probe the CODEC DAI */ |
1665 | if (!codec_dai->probed) { | 1164 | if (!codec_dai->probed && codec_dai->driver->probe_order == order) { |
1666 | if (codec_dai->driver->probe) { | 1165 | if (codec_dai->driver->probe) { |
1667 | ret = codec_dai->driver->probe(codec_dai); | 1166 | ret = codec_dai->driver->probe(codec_dai); |
1668 | if (ret < 0) { | 1167 | if (ret < 0) { |
@@ -1677,8 +1176,9 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1677 | list_add(&codec_dai->card_list, &card->dai_dev_list); | 1176 | list_add(&codec_dai->card_list, &card->dai_dev_list); |
1678 | } | 1177 | } |
1679 | 1178 | ||
1680 | /* DAPM dai link stream work */ | 1179 | /* complete DAI probe during last probe */ |
1681 | INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); | 1180 | if (order != SND_SOC_COMP_ORDER_LAST) |
1181 | return 0; | ||
1682 | 1182 | ||
1683 | ret = soc_post_component_init(card, codec, num, 0); | 1183 | ret = soc_post_component_init(card, codec, num, 0); |
1684 | if (ret) | 1184 | if (ret) |
@@ -1817,7 +1317,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1817 | struct snd_soc_codec *codec; | 1317 | struct snd_soc_codec *codec; |
1818 | struct snd_soc_codec_conf *codec_conf; | 1318 | struct snd_soc_codec_conf *codec_conf; |
1819 | enum snd_soc_compress_type compress_type; | 1319 | enum snd_soc_compress_type compress_type; |
1820 | int ret, i; | 1320 | int ret, i, order; |
1821 | 1321 | ||
1822 | mutex_lock(&card->mutex); | 1322 | mutex_lock(&card->mutex); |
1823 | 1323 | ||
@@ -1895,12 +1395,16 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1895 | goto card_probe_error; | 1395 | goto card_probe_error; |
1896 | } | 1396 | } |
1897 | 1397 | ||
1898 | for (i = 0; i < card->num_links; i++) { | 1398 | /* early DAI link probe */ |
1899 | ret = soc_probe_dai_link(card, i); | 1399 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; |
1900 | if (ret < 0) { | 1400 | order++) { |
1901 | pr_err("asoc: failed to instantiate card %s: %d\n", | 1401 | for (i = 0; i < card->num_links; i++) { |
1402 | ret = soc_probe_dai_link(card, i, order); | ||
1403 | if (ret < 0) { | ||
1404 | pr_err("asoc: failed to instantiate card %s: %d\n", | ||
1902 | card->name, ret); | 1405 | card->name, ret); |
1903 | goto probe_dai_err; | 1406 | goto probe_dai_err; |
1407 | } | ||
1904 | } | 1408 | } |
1905 | } | 1409 | } |
1906 | 1410 | ||
@@ -1929,8 +1433,9 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1929 | "%s", card->name); | 1433 | "%s", card->name); |
1930 | snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), | 1434 | snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), |
1931 | "%s", card->long_name ? card->long_name : card->name); | 1435 | "%s", card->long_name ? card->long_name : card->name); |
1932 | snprintf(card->snd_card->driver, sizeof(card->snd_card->driver), | 1436 | if (card->driver_name) |
1933 | "%s", card->driver_name ? card->driver_name : card->name); | 1437 | strlcpy(card->snd_card->driver, card->driver_name, |
1438 | sizeof(card->snd_card->driver)); | ||
1934 | 1439 | ||
1935 | if (card->late_probe) { | 1440 | if (card->late_probe) { |
1936 | ret = card->late_probe(card); | 1441 | ret = card->late_probe(card); |
@@ -2095,67 +1600,6 @@ static struct platform_driver soc_driver = { | |||
2095 | .remove = soc_remove, | 1600 | .remove = soc_remove, |
2096 | }; | 1601 | }; |
2097 | 1602 | ||
2098 | /* create a new pcm */ | ||
2099 | static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | ||
2100 | { | ||
2101 | struct snd_soc_codec *codec = rtd->codec; | ||
2102 | struct snd_soc_platform *platform = rtd->platform; | ||
2103 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
2104 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
2105 | struct snd_pcm *pcm; | ||
2106 | char new_name[64]; | ||
2107 | int ret = 0, playback = 0, capture = 0; | ||
2108 | |||
2109 | /* check client and interface hw capabilities */ | ||
2110 | snprintf(new_name, sizeof(new_name), "%s %s-%d", | ||
2111 | rtd->dai_link->stream_name, codec_dai->name, num); | ||
2112 | |||
2113 | if (codec_dai->driver->playback.channels_min) | ||
2114 | playback = 1; | ||
2115 | if (codec_dai->driver->capture.channels_min) | ||
2116 | capture = 1; | ||
2117 | |||
2118 | dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name); | ||
2119 | ret = snd_pcm_new(rtd->card->snd_card, new_name, | ||
2120 | num, playback, capture, &pcm); | ||
2121 | if (ret < 0) { | ||
2122 | printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name); | ||
2123 | return ret; | ||
2124 | } | ||
2125 | |||
2126 | rtd->pcm = pcm; | ||
2127 | pcm->private_data = rtd; | ||
2128 | if (platform->driver->ops) { | ||
2129 | soc_pcm_ops.mmap = platform->driver->ops->mmap; | ||
2130 | soc_pcm_ops.pointer = platform->driver->ops->pointer; | ||
2131 | soc_pcm_ops.ioctl = platform->driver->ops->ioctl; | ||
2132 | soc_pcm_ops.copy = platform->driver->ops->copy; | ||
2133 | soc_pcm_ops.silence = platform->driver->ops->silence; | ||
2134 | soc_pcm_ops.ack = platform->driver->ops->ack; | ||
2135 | soc_pcm_ops.page = platform->driver->ops->page; | ||
2136 | } | ||
2137 | |||
2138 | if (playback) | ||
2139 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); | ||
2140 | |||
2141 | if (capture) | ||
2142 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); | ||
2143 | |||
2144 | if (platform->driver->pcm_new) { | ||
2145 | ret = platform->driver->pcm_new(rtd->card->snd_card, | ||
2146 | codec_dai, pcm); | ||
2147 | if (ret < 0) { | ||
2148 | pr_err("asoc: platform pcm constructor failed\n"); | ||
2149 | return ret; | ||
2150 | } | ||
2151 | } | ||
2152 | |||
2153 | pcm->private_free = platform->driver->pcm_free; | ||
2154 | printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, | ||
2155 | cpu_dai->name); | ||
2156 | return ret; | ||
2157 | } | ||
2158 | |||
2159 | /** | 1603 | /** |
2160 | * snd_soc_codec_volatile_register: Report if a register is volatile. | 1604 | * snd_soc_codec_volatile_register: Report if a register is volatile. |
2161 | * | 1605 | * |
@@ -2210,6 +1654,38 @@ int snd_soc_codec_writable_register(struct snd_soc_codec *codec, | |||
2210 | } | 1654 | } |
2211 | EXPORT_SYMBOL_GPL(snd_soc_codec_writable_register); | 1655 | EXPORT_SYMBOL_GPL(snd_soc_codec_writable_register); |
2212 | 1656 | ||
1657 | int snd_soc_platform_read(struct snd_soc_platform *platform, | ||
1658 | unsigned int reg) | ||
1659 | { | ||
1660 | unsigned int ret; | ||
1661 | |||
1662 | if (!platform->driver->read) { | ||
1663 | dev_err(platform->dev, "platform has no read back\n"); | ||
1664 | return -1; | ||
1665 | } | ||
1666 | |||
1667 | ret = platform->driver->read(platform, reg); | ||
1668 | dev_dbg(platform->dev, "read %x => %x\n", reg, ret); | ||
1669 | trace_snd_soc_preg_read(platform, reg, ret); | ||
1670 | |||
1671 | return ret; | ||
1672 | } | ||
1673 | EXPORT_SYMBOL_GPL(snd_soc_platform_read); | ||
1674 | |||
1675 | int snd_soc_platform_write(struct snd_soc_platform *platform, | ||
1676 | unsigned int reg, unsigned int val) | ||
1677 | { | ||
1678 | if (!platform->driver->write) { | ||
1679 | dev_err(platform->dev, "platform has no write back\n"); | ||
1680 | return -1; | ||
1681 | } | ||
1682 | |||
1683 | dev_dbg(platform->dev, "write %x = %x\n", reg, val); | ||
1684 | trace_snd_soc_preg_write(platform, reg, val); | ||
1685 | return platform->driver->write(platform, reg, val); | ||
1686 | } | ||
1687 | EXPORT_SYMBOL_GPL(snd_soc_platform_write); | ||
1688 | |||
2213 | /** | 1689 | /** |
2214 | * snd_soc_new_ac97_codec - initailise AC97 device | 1690 | * snd_soc_new_ac97_codec - initailise AC97 device |
2215 | * @codec: audio codec | 1691 | * @codec: audio codec |
@@ -2322,7 +1798,7 @@ int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, | |||
2322 | return ret; | 1798 | return ret; |
2323 | 1799 | ||
2324 | old = ret; | 1800 | old = ret; |
2325 | new = (old & ~mask) | value; | 1801 | new = (old & ~mask) | (value & mask); |
2326 | change = old != new; | 1802 | change = old != new; |
2327 | if (change) { | 1803 | if (change) { |
2328 | ret = snd_soc_write(codec, reg, new); | 1804 | ret = snd_soc_write(codec, reg, new); |
@@ -2489,6 +1965,36 @@ int snd_soc_add_controls(struct snd_soc_codec *codec, | |||
2489 | EXPORT_SYMBOL_GPL(snd_soc_add_controls); | 1965 | EXPORT_SYMBOL_GPL(snd_soc_add_controls); |
2490 | 1966 | ||
2491 | /** | 1967 | /** |
1968 | * snd_soc_add_platform_controls - add an array of controls to a platform. | ||
1969 | * Convienience function to add a list of controls. | ||
1970 | * | ||
1971 | * @platform: platform to add controls to | ||
1972 | * @controls: array of controls to add | ||
1973 | * @num_controls: number of elements in the array | ||
1974 | * | ||
1975 | * Return 0 for success, else error. | ||
1976 | */ | ||
1977 | int snd_soc_add_platform_controls(struct snd_soc_platform *platform, | ||
1978 | const struct snd_kcontrol_new *controls, int num_controls) | ||
1979 | { | ||
1980 | struct snd_card *card = platform->card->snd_card; | ||
1981 | int err, i; | ||
1982 | |||
1983 | for (i = 0; i < num_controls; i++) { | ||
1984 | const struct snd_kcontrol_new *control = &controls[i]; | ||
1985 | err = snd_ctl_add(card, snd_soc_cnew(control, platform, | ||
1986 | control->name, NULL)); | ||
1987 | if (err < 0) { | ||
1988 | dev_err(platform->dev, "Failed to add %s %d\n",control->name, err); | ||
1989 | return err; | ||
1990 | } | ||
1991 | } | ||
1992 | |||
1993 | return 0; | ||
1994 | } | ||
1995 | EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls); | ||
1996 | |||
1997 | /** | ||
2492 | * snd_soc_info_enum_double - enumerated double mixer info callback | 1998 | * snd_soc_info_enum_double - enumerated double mixer info callback |
2493 | * @kcontrol: mixer control | 1999 | * @kcontrol: mixer control |
2494 | * @uinfo: control element information | 2000 | * @uinfo: control element information |
@@ -3632,6 +3138,8 @@ int snd_soc_register_platform(struct device *dev, | |||
3632 | 3138 | ||
3633 | platform->dev = dev; | 3139 | platform->dev = dev; |
3634 | platform->driver = platform_drv; | 3140 | platform->driver = platform_drv; |
3141 | platform->dapm.dev = dev; | ||
3142 | platform->dapm.platform = platform; | ||
3635 | 3143 | ||
3636 | mutex_lock(&client_mutex); | 3144 | mutex_lock(&client_mutex); |
3637 | list_add(&platform->list, &platform_list); | 3145 | list_add(&platform->list, &platform_list); |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 32ab7fc4579a..fbfcda062839 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -124,6 +124,51 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( | |||
124 | return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); | 124 | return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); |
125 | } | 125 | } |
126 | 126 | ||
127 | static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg) | ||
128 | { | ||
129 | if (w->codec) | ||
130 | return snd_soc_read(w->codec, reg); | ||
131 | else if (w->platform) | ||
132 | return snd_soc_platform_read(w->platform, reg); | ||
133 | |||
134 | dev_err(w->dapm->dev, "no valid widget read method\n"); | ||
135 | return -1; | ||
136 | } | ||
137 | |||
138 | static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val) | ||
139 | { | ||
140 | if (w->codec) | ||
141 | return snd_soc_write(w->codec, reg, val); | ||
142 | else if (w->platform) | ||
143 | return snd_soc_platform_write(w->platform, reg, val); | ||
144 | |||
145 | dev_err(w->dapm->dev, "no valid widget write method\n"); | ||
146 | return -1; | ||
147 | } | ||
148 | |||
149 | static int soc_widget_update_bits(struct snd_soc_dapm_widget *w, | ||
150 | unsigned short reg, unsigned int mask, unsigned int value) | ||
151 | { | ||
152 | int change; | ||
153 | unsigned int old, new; | ||
154 | int ret; | ||
155 | |||
156 | ret = soc_widget_read(w, reg); | ||
157 | if (ret < 0) | ||
158 | return ret; | ||
159 | |||
160 | old = ret; | ||
161 | new = (old & ~mask) | (value & mask); | ||
162 | change = old != new; | ||
163 | if (change) { | ||
164 | ret = soc_widget_write(w, reg, new); | ||
165 | if (ret < 0) | ||
166 | return ret; | ||
167 | } | ||
168 | |||
169 | return change; | ||
170 | } | ||
171 | |||
127 | /** | 172 | /** |
128 | * snd_soc_dapm_set_bias_level - set the bias level for the system | 173 | * snd_soc_dapm_set_bias_level - set the bias level for the system |
129 | * @dapm: DAPM context | 174 | * @dapm: DAPM context |
@@ -139,39 +184,26 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, | |||
139 | struct snd_soc_card *card = dapm->card; | 184 | struct snd_soc_card *card = dapm->card; |
140 | int ret = 0; | 185 | int ret = 0; |
141 | 186 | ||
142 | switch (level) { | ||
143 | case SND_SOC_BIAS_ON: | ||
144 | dev_dbg(dapm->dev, "Setting full bias\n"); | ||
145 | break; | ||
146 | case SND_SOC_BIAS_PREPARE: | ||
147 | dev_dbg(dapm->dev, "Setting bias prepare\n"); | ||
148 | break; | ||
149 | case SND_SOC_BIAS_STANDBY: | ||
150 | dev_dbg(dapm->dev, "Setting standby bias\n"); | ||
151 | break; | ||
152 | case SND_SOC_BIAS_OFF: | ||
153 | dev_dbg(dapm->dev, "Setting bias off\n"); | ||
154 | break; | ||
155 | default: | ||
156 | dev_err(dapm->dev, "Setting invalid bias %d\n", level); | ||
157 | return -EINVAL; | ||
158 | } | ||
159 | |||
160 | trace_snd_soc_bias_level_start(card, level); | 187 | trace_snd_soc_bias_level_start(card, level); |
161 | 188 | ||
162 | if (card && card->set_bias_level) | 189 | if (card && card->set_bias_level) |
163 | ret = card->set_bias_level(card, level); | 190 | ret = card->set_bias_level(card, dapm, level); |
164 | if (ret == 0) { | 191 | if (ret != 0) |
165 | if (dapm->codec && dapm->codec->driver->set_bias_level) | 192 | goto out; |
166 | ret = dapm->codec->driver->set_bias_level(dapm->codec, level); | 193 | |
194 | if (dapm->codec) { | ||
195 | if (dapm->codec->driver->set_bias_level) | ||
196 | ret = dapm->codec->driver->set_bias_level(dapm->codec, | ||
197 | level); | ||
167 | else | 198 | else |
168 | dapm->bias_level = level; | 199 | dapm->bias_level = level; |
169 | } | 200 | } |
170 | if (ret == 0) { | 201 | if (ret != 0) |
171 | if (card && card->set_bias_level_post) | 202 | goto out; |
172 | ret = card->set_bias_level_post(card, level); | ||
173 | } | ||
174 | 203 | ||
204 | if (card && card->set_bias_level_post) | ||
205 | ret = card->set_bias_level_post(card, dapm, level); | ||
206 | out: | ||
175 | trace_snd_soc_bias_level_done(card, level); | 207 | trace_snd_soc_bias_level_done(card, level); |
176 | 208 | ||
177 | return ret; | 209 | return ret; |
@@ -194,7 +226,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
194 | unsigned int mask = (1 << fls(max)) - 1; | 226 | unsigned int mask = (1 << fls(max)) - 1; |
195 | unsigned int invert = mc->invert; | 227 | unsigned int invert = mc->invert; |
196 | 228 | ||
197 | val = snd_soc_read(w->codec, reg); | 229 | val = soc_widget_read(w, reg); |
198 | val = (val >> shift) & mask; | 230 | val = (val >> shift) & mask; |
199 | 231 | ||
200 | if ((invert && !val) || (!invert && val)) | 232 | if ((invert && !val) || (!invert && val)) |
@@ -209,8 +241,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
209 | int val, item, bitmask; | 241 | int val, item, bitmask; |
210 | 242 | ||
211 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | 243 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) |
212 | ; | 244 | ; |
213 | val = snd_soc_read(w->codec, e->reg); | 245 | val = soc_widget_read(w, e->reg); |
214 | item = (val >> e->shift_l) & (bitmask - 1); | 246 | item = (val >> e->shift_l) & (bitmask - 1); |
215 | 247 | ||
216 | p->connect = 0; | 248 | p->connect = 0; |
@@ -240,7 +272,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
240 | w->kcontrol_news[i].private_value; | 272 | w->kcontrol_news[i].private_value; |
241 | int val, item; | 273 | int val, item; |
242 | 274 | ||
243 | val = snd_soc_read(w->codec, e->reg); | 275 | val = soc_widget_read(w, e->reg); |
244 | val = (val >> e->shift_l) & e->mask; | 276 | val = (val >> e->shift_l) & e->mask; |
245 | for (item = 0; item < e->max; item++) { | 277 | for (item = 0; item < e->max; item++) { |
246 | if (val == e->values[item]) | 278 | if (val == e->values[item]) |
@@ -606,6 +638,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget) | |||
606 | } | 638 | } |
607 | 639 | ||
608 | list_for_each_entry(path, &widget->sinks, list_source) { | 640 | list_for_each_entry(path, &widget->sinks, list_source) { |
641 | if (path->weak) | ||
642 | continue; | ||
643 | |||
609 | if (path->walked) | 644 | if (path->walked) |
610 | continue; | 645 | continue; |
611 | 646 | ||
@@ -656,6 +691,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget) | |||
656 | } | 691 | } |
657 | 692 | ||
658 | list_for_each_entry(path, &widget->sources, list_sink) { | 693 | list_for_each_entry(path, &widget->sources, list_sink) { |
694 | if (path->weak) | ||
695 | continue; | ||
696 | |||
659 | if (path->walked) | 697 | if (path->walked) |
660 | continue; | 698 | continue; |
661 | 699 | ||
@@ -681,7 +719,7 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w, | |||
681 | else | 719 | else |
682 | val = w->off_val; | 720 | val = w->off_val; |
683 | 721 | ||
684 | snd_soc_update_bits(w->codec, -(w->reg + 1), | 722 | soc_widget_update_bits(w, -(w->reg + 1), |
685 | w->mask << w->shift, val << w->shift); | 723 | w->mask << w->shift, val << w->shift); |
686 | 724 | ||
687 | return 0; | 725 | return 0; |
@@ -737,6 +775,9 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) | |||
737 | 775 | ||
738 | /* Check if one of our outputs is connected */ | 776 | /* Check if one of our outputs is connected */ |
739 | list_for_each_entry(path, &w->sinks, list_source) { | 777 | list_for_each_entry(path, &w->sinks, list_source) { |
778 | if (path->weak) | ||
779 | continue; | ||
780 | |||
740 | if (path->connected && | 781 | if (path->connected && |
741 | !path->connected(path->source, path->sink)) | 782 | !path->connected(path->source, path->sink)) |
742 | continue; | 783 | continue; |
@@ -885,11 +926,17 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, | |||
885 | } | 926 | } |
886 | 927 | ||
887 | if (reg >= 0) { | 928 | if (reg >= 0) { |
929 | /* Any widget will do, they should all be updating the | ||
930 | * same register. | ||
931 | */ | ||
932 | w = list_first_entry(pending, struct snd_soc_dapm_widget, | ||
933 | power_list); | ||
934 | |||
888 | pop_dbg(dapm->dev, card->pop_time, | 935 | pop_dbg(dapm->dev, card->pop_time, |
889 | "pop test : Applying 0x%x/0x%x to %x in %dms\n", | 936 | "pop test : Applying 0x%x/0x%x to %x in %dms\n", |
890 | value, mask, reg, card->pop_time); | 937 | value, mask, reg, card->pop_time); |
891 | pop_wait(card->pop_time); | 938 | pop_wait(card->pop_time); |
892 | snd_soc_update_bits(dapm->codec, reg, mask, value); | 939 | soc_widget_update_bits(w, reg, mask, value); |
893 | } | 940 | } |
894 | 941 | ||
895 | list_for_each_entry(w, pending, power_list) { | 942 | list_for_each_entry(w, pending, power_list) { |
@@ -942,7 +989,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | |||
942 | 989 | ||
943 | INIT_LIST_HEAD(&pending); | 990 | INIT_LIST_HEAD(&pending); |
944 | cur_sort = -1; | 991 | cur_sort = -1; |
945 | cur_subseq = -1; | 992 | cur_subseq = INT_MIN; |
946 | cur_reg = SND_SOC_NOPM; | 993 | cur_reg = SND_SOC_NOPM; |
947 | cur_dapm = NULL; | 994 | cur_dapm = NULL; |
948 | } | 995 | } |
@@ -1041,16 +1088,17 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie) | |||
1041 | struct snd_soc_dapm_context *d = data; | 1088 | struct snd_soc_dapm_context *d = data; |
1042 | int ret; | 1089 | int ret; |
1043 | 1090 | ||
1044 | if (d->dev_power && d->bias_level == SND_SOC_BIAS_OFF) { | 1091 | /* If we're off and we're not supposed to be go into STANDBY */ |
1092 | if (d->bias_level == SND_SOC_BIAS_OFF && | ||
1093 | d->target_bias_level != SND_SOC_BIAS_OFF) { | ||
1045 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY); | 1094 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY); |
1046 | if (ret != 0) | 1095 | if (ret != 0) |
1047 | dev_err(d->dev, | 1096 | dev_err(d->dev, |
1048 | "Failed to turn on bias: %d\n", ret); | 1097 | "Failed to turn on bias: %d\n", ret); |
1049 | } | 1098 | } |
1050 | 1099 | ||
1051 | /* If we're changing to all on or all off then prepare */ | 1100 | /* Prepare for a STADDBY->ON or ON->STANDBY transition */ |
1052 | if ((d->dev_power && d->bias_level == SND_SOC_BIAS_STANDBY) || | 1101 | if (d->bias_level != d->target_bias_level) { |
1053 | (!d->dev_power && d->bias_level == SND_SOC_BIAS_ON)) { | ||
1054 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE); | 1102 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE); |
1055 | if (ret != 0) | 1103 | if (ret != 0) |
1056 | dev_err(d->dev, | 1104 | dev_err(d->dev, |
@@ -1067,7 +1115,9 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie) | |||
1067 | int ret; | 1115 | int ret; |
1068 | 1116 | ||
1069 | /* If we just powered the last thing off drop to standby bias */ | 1117 | /* If we just powered the last thing off drop to standby bias */ |
1070 | if (d->bias_level == SND_SOC_BIAS_PREPARE && !d->dev_power) { | 1118 | if (d->bias_level == SND_SOC_BIAS_PREPARE && |
1119 | (d->target_bias_level == SND_SOC_BIAS_STANDBY || | ||
1120 | d->target_bias_level == SND_SOC_BIAS_OFF)) { | ||
1071 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY); | 1121 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY); |
1072 | if (ret != 0) | 1122 | if (ret != 0) |
1073 | dev_err(d->dev, "Failed to apply standby bias: %d\n", | 1123 | dev_err(d->dev, "Failed to apply standby bias: %d\n", |
@@ -1075,14 +1125,16 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie) | |||
1075 | } | 1125 | } |
1076 | 1126 | ||
1077 | /* If we're in standby and can support bias off then do that */ | 1127 | /* If we're in standby and can support bias off then do that */ |
1078 | if (d->bias_level == SND_SOC_BIAS_STANDBY && d->idle_bias_off) { | 1128 | if (d->bias_level == SND_SOC_BIAS_STANDBY && |
1129 | d->target_bias_level == SND_SOC_BIAS_OFF) { | ||
1079 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF); | 1130 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF); |
1080 | if (ret != 0) | 1131 | if (ret != 0) |
1081 | dev_err(d->dev, "Failed to turn off bias: %d\n", ret); | 1132 | dev_err(d->dev, "Failed to turn off bias: %d\n", ret); |
1082 | } | 1133 | } |
1083 | 1134 | ||
1084 | /* If we just powered up then move to active bias */ | 1135 | /* If we just powered up then move to active bias */ |
1085 | if (d->bias_level == SND_SOC_BIAS_PREPARE && d->dev_power) { | 1136 | if (d->bias_level == SND_SOC_BIAS_PREPARE && |
1137 | d->target_bias_level == SND_SOC_BIAS_ON) { | ||
1086 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON); | 1138 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON); |
1087 | if (ret != 0) | 1139 | if (ret != 0) |
1088 | dev_err(d->dev, "Failed to apply active bias: %d\n", | 1140 | dev_err(d->dev, "Failed to apply active bias: %d\n", |
@@ -1107,13 +1159,19 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1107 | LIST_HEAD(up_list); | 1159 | LIST_HEAD(up_list); |
1108 | LIST_HEAD(down_list); | 1160 | LIST_HEAD(down_list); |
1109 | LIST_HEAD(async_domain); | 1161 | LIST_HEAD(async_domain); |
1162 | enum snd_soc_bias_level bias; | ||
1110 | int power; | 1163 | int power; |
1111 | 1164 | ||
1112 | trace_snd_soc_dapm_start(card); | 1165 | trace_snd_soc_dapm_start(card); |
1113 | 1166 | ||
1114 | list_for_each_entry(d, &card->dapm_list, list) | 1167 | list_for_each_entry(d, &card->dapm_list, list) { |
1115 | if (d->n_widgets || d->codec == NULL) | 1168 | if (d->n_widgets || d->codec == NULL) { |
1116 | d->dev_power = 0; | 1169 | if (d->idle_bias_off) |
1170 | d->target_bias_level = SND_SOC_BIAS_OFF; | ||
1171 | else | ||
1172 | d->target_bias_level = SND_SOC_BIAS_STANDBY; | ||
1173 | } | ||
1174 | } | ||
1117 | 1175 | ||
1118 | /* Check which widgets we need to power and store them in | 1176 | /* Check which widgets we need to power and store them in |
1119 | * lists indicating if they should be powered up or down. | 1177 | * lists indicating if they should be powered up or down. |
@@ -1135,8 +1193,27 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1135 | power = w->power_check(w); | 1193 | power = w->power_check(w); |
1136 | else | 1194 | else |
1137 | power = 1; | 1195 | power = 1; |
1138 | if (power) | 1196 | |
1139 | w->dapm->dev_power = 1; | 1197 | if (power) { |
1198 | d = w->dapm; | ||
1199 | |||
1200 | /* Supplies and micbiases only bring | ||
1201 | * the context up to STANDBY as unless | ||
1202 | * something else is active and | ||
1203 | * passing audio they generally don't | ||
1204 | * require full power. | ||
1205 | */ | ||
1206 | switch (w->id) { | ||
1207 | case snd_soc_dapm_supply: | ||
1208 | case snd_soc_dapm_micbias: | ||
1209 | if (d->target_bias_level < SND_SOC_BIAS_STANDBY) | ||
1210 | d->target_bias_level = SND_SOC_BIAS_STANDBY; | ||
1211 | break; | ||
1212 | default: | ||
1213 | d->target_bias_level = SND_SOC_BIAS_ON; | ||
1214 | break; | ||
1215 | } | ||
1216 | } | ||
1140 | 1217 | ||
1141 | if (w->power == power) | 1218 | if (w->power == power) |
1142 | continue; | 1219 | continue; |
@@ -1160,24 +1237,19 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1160 | switch (event) { | 1237 | switch (event) { |
1161 | case SND_SOC_DAPM_STREAM_START: | 1238 | case SND_SOC_DAPM_STREAM_START: |
1162 | case SND_SOC_DAPM_STREAM_RESUME: | 1239 | case SND_SOC_DAPM_STREAM_RESUME: |
1163 | dapm->dev_power = 1; | 1240 | dapm->target_bias_level = SND_SOC_BIAS_ON; |
1164 | break; | 1241 | break; |
1165 | case SND_SOC_DAPM_STREAM_STOP: | 1242 | case SND_SOC_DAPM_STREAM_STOP: |
1166 | dapm->dev_power = !!dapm->codec->active; | 1243 | if (dapm->codec->active) |
1244 | dapm->target_bias_level = SND_SOC_BIAS_ON; | ||
1245 | else | ||
1246 | dapm->target_bias_level = SND_SOC_BIAS_STANDBY; | ||
1167 | break; | 1247 | break; |
1168 | case SND_SOC_DAPM_STREAM_SUSPEND: | 1248 | case SND_SOC_DAPM_STREAM_SUSPEND: |
1169 | dapm->dev_power = 0; | 1249 | dapm->target_bias_level = SND_SOC_BIAS_STANDBY; |
1170 | break; | 1250 | break; |
1171 | case SND_SOC_DAPM_STREAM_NOP: | 1251 | case SND_SOC_DAPM_STREAM_NOP: |
1172 | switch (dapm->bias_level) { | 1252 | dapm->target_bias_level = dapm->bias_level; |
1173 | case SND_SOC_BIAS_STANDBY: | ||
1174 | case SND_SOC_BIAS_OFF: | ||
1175 | dapm->dev_power = 0; | ||
1176 | break; | ||
1177 | default: | ||
1178 | dapm->dev_power = 1; | ||
1179 | break; | ||
1180 | } | ||
1181 | break; | 1253 | break; |
1182 | default: | 1254 | default: |
1183 | break; | 1255 | break; |
@@ -1185,12 +1257,12 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1185 | } | 1257 | } |
1186 | 1258 | ||
1187 | /* Force all contexts in the card to the same bias state */ | 1259 | /* Force all contexts in the card to the same bias state */ |
1188 | power = 0; | 1260 | bias = SND_SOC_BIAS_OFF; |
1189 | list_for_each_entry(d, &card->dapm_list, list) | 1261 | list_for_each_entry(d, &card->dapm_list, list) |
1190 | if (d->dev_power) | 1262 | if (d->target_bias_level > bias) |
1191 | power = 1; | 1263 | bias = d->target_bias_level; |
1192 | list_for_each_entry(d, &card->dapm_list, list) | 1264 | list_for_each_entry(d, &card->dapm_list, list) |
1193 | d->dev_power = power; | 1265 | d->target_bias_level = bias; |
1194 | 1266 | ||
1195 | 1267 | ||
1196 | /* Run all the bias changes in parallel */ | 1268 | /* Run all the bias changes in parallel */ |
@@ -1794,6 +1866,84 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, | |||
1794 | } | 1866 | } |
1795 | EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); | 1867 | EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); |
1796 | 1868 | ||
1869 | static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm, | ||
1870 | const struct snd_soc_dapm_route *route) | ||
1871 | { | ||
1872 | struct snd_soc_dapm_widget *source = dapm_find_widget(dapm, | ||
1873 | route->source, | ||
1874 | true); | ||
1875 | struct snd_soc_dapm_widget *sink = dapm_find_widget(dapm, | ||
1876 | route->sink, | ||
1877 | true); | ||
1878 | struct snd_soc_dapm_path *path; | ||
1879 | int count = 0; | ||
1880 | |||
1881 | if (!source) { | ||
1882 | dev_err(dapm->dev, "Unable to find source %s for weak route\n", | ||
1883 | route->source); | ||
1884 | return -ENODEV; | ||
1885 | } | ||
1886 | |||
1887 | if (!sink) { | ||
1888 | dev_err(dapm->dev, "Unable to find sink %s for weak route\n", | ||
1889 | route->sink); | ||
1890 | return -ENODEV; | ||
1891 | } | ||
1892 | |||
1893 | if (route->control || route->connected) | ||
1894 | dev_warn(dapm->dev, "Ignoring control for weak route %s->%s\n", | ||
1895 | route->source, route->sink); | ||
1896 | |||
1897 | list_for_each_entry(path, &source->sinks, list_source) { | ||
1898 | if (path->sink == sink) { | ||
1899 | path->weak = 1; | ||
1900 | count++; | ||
1901 | } | ||
1902 | } | ||
1903 | |||
1904 | if (count == 0) | ||
1905 | dev_err(dapm->dev, "No path found for weak route %s->%s\n", | ||
1906 | route->source, route->sink); | ||
1907 | if (count > 1) | ||
1908 | dev_warn(dapm->dev, "%d paths found for weak route %s->%s\n", | ||
1909 | count, route->source, route->sink); | ||
1910 | |||
1911 | return 0; | ||
1912 | } | ||
1913 | |||
1914 | /** | ||
1915 | * snd_soc_dapm_weak_routes - Mark routes between DAPM widgets as weak | ||
1916 | * @dapm: DAPM context | ||
1917 | * @route: audio routes | ||
1918 | * @num: number of routes | ||
1919 | * | ||
1920 | * Mark existing routes matching those specified in the passed array | ||
1921 | * as being weak, meaning that they are ignored for the purpose of | ||
1922 | * power decisions. The main intended use case is for sidetone paths | ||
1923 | * which couple audio between other independent paths if they are both | ||
1924 | * active in order to make the combination work better at the user | ||
1925 | * level but which aren't intended to be "used". | ||
1926 | * | ||
1927 | * Note that CODEC drivers should not use this as sidetone type paths | ||
1928 | * can frequently also be used as bypass paths. | ||
1929 | */ | ||
1930 | int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm, | ||
1931 | const struct snd_soc_dapm_route *route, int num) | ||
1932 | { | ||
1933 | int i, err; | ||
1934 | int ret = 0; | ||
1935 | |||
1936 | for (i = 0; i < num; i++) { | ||
1937 | err = snd_soc_dapm_weak_route(dapm, route); | ||
1938 | if (err) | ||
1939 | ret = err; | ||
1940 | route++; | ||
1941 | } | ||
1942 | |||
1943 | return ret; | ||
1944 | } | ||
1945 | EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes); | ||
1946 | |||
1797 | /** | 1947 | /** |
1798 | * snd_soc_dapm_new_widgets - add new dapm widgets | 1948 | * snd_soc_dapm_new_widgets - add new dapm widgets |
1799 | * @dapm: DAPM context | 1949 | * @dapm: DAPM context |
@@ -1865,7 +2015,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) | |||
1865 | 2015 | ||
1866 | /* Read the initial power state from the device */ | 2016 | /* Read the initial power state from the device */ |
1867 | if (w->reg >= 0) { | 2017 | if (w->reg >= 0) { |
1868 | val = snd_soc_read(w->codec, w->reg); | 2018 | val = soc_widget_read(w, w->reg); |
1869 | val &= 1 << w->shift; | 2019 | val &= 1 << w->shift; |
1870 | if (w->invert) | 2020 | if (w->invert) |
1871 | val = !val; | 2021 | val = !val; |
@@ -2353,6 +2503,7 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
2353 | dapm->n_widgets++; | 2503 | dapm->n_widgets++; |
2354 | w->dapm = dapm; | 2504 | w->dapm = dapm; |
2355 | w->codec = dapm->codec; | 2505 | w->codec = dapm->codec; |
2506 | w->platform = dapm->platform; | ||
2356 | INIT_LIST_HEAD(&w->sources); | 2507 | INIT_LIST_HEAD(&w->sources); |
2357 | INIT_LIST_HEAD(&w->sinks); | 2508 | INIT_LIST_HEAD(&w->sinks); |
2358 | INIT_LIST_HEAD(&w->list); | 2509 | INIT_LIST_HEAD(&w->list); |
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c new file mode 100644 index 000000000000..cca490c80589 --- /dev/null +++ b/sound/soc/soc-io.c | |||
@@ -0,0 +1,396 @@ | |||
1 | /* | ||
2 | * soc-io.c -- ASoC register I/O helpers | ||
3 | * | ||
4 | * Copyright 2009-2011 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/spi/spi.h> | ||
16 | #include <sound/soc.h> | ||
17 | |||
18 | #include <trace/events/asoc.h> | ||
19 | |||
20 | #ifdef CONFIG_SPI_MASTER | ||
21 | static int do_spi_write(void *control, const char *data, int len) | ||
22 | { | ||
23 | struct spi_device *spi = control; | ||
24 | int ret; | ||
25 | |||
26 | ret = spi_write(spi, data, len); | ||
27 | if (ret < 0) | ||
28 | return ret; | ||
29 | |||
30 | return len; | ||
31 | } | ||
32 | #endif | ||
33 | |||
34 | static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg, | ||
35 | unsigned int value, const void *data, int len) | ||
36 | { | ||
37 | int ret; | ||
38 | |||
39 | if (!snd_soc_codec_volatile_register(codec, reg) && | ||
40 | reg < codec->driver->reg_cache_size && | ||
41 | !codec->cache_bypass) { | ||
42 | ret = snd_soc_cache_write(codec, reg, value); | ||
43 | if (ret < 0) | ||
44 | return -1; | ||
45 | } | ||
46 | |||
47 | if (codec->cache_only) { | ||
48 | codec->cache_sync = 1; | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | ret = codec->hw_write(codec->control_data, data, len); | ||
53 | if (ret == len) | ||
54 | return 0; | ||
55 | if (ret < 0) | ||
56 | return ret; | ||
57 | else | ||
58 | return -EIO; | ||
59 | } | ||
60 | |||
61 | static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) | ||
62 | { | ||
63 | int ret; | ||
64 | unsigned int val; | ||
65 | |||
66 | if (reg >= codec->driver->reg_cache_size || | ||
67 | snd_soc_codec_volatile_register(codec, reg) || | ||
68 | codec->cache_bypass) { | ||
69 | if (codec->cache_only) | ||
70 | return -1; | ||
71 | |||
72 | BUG_ON(!codec->hw_read); | ||
73 | return codec->hw_read(codec, reg); | ||
74 | } | ||
75 | |||
76 | ret = snd_soc_cache_read(codec, reg, &val); | ||
77 | if (ret < 0) | ||
78 | return -1; | ||
79 | return val; | ||
80 | } | ||
81 | |||
82 | static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, | ||
83 | unsigned int value) | ||
84 | { | ||
85 | u16 data; | ||
86 | |||
87 | data = cpu_to_be16((reg << 12) | (value & 0xffffff)); | ||
88 | |||
89 | return do_hw_write(codec, reg, value, &data, 2); | ||
90 | } | ||
91 | |||
92 | static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, | ||
93 | unsigned int value) | ||
94 | { | ||
95 | u16 data; | ||
96 | |||
97 | data = cpu_to_be16((reg << 9) | (value & 0x1ff)); | ||
98 | |||
99 | return do_hw_write(codec, reg, value, &data, 2); | ||
100 | } | ||
101 | |||
102 | static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, | ||
103 | unsigned int value) | ||
104 | { | ||
105 | u8 data[2]; | ||
106 | |||
107 | reg &= 0xff; | ||
108 | data[0] = reg; | ||
109 | data[1] = value & 0xff; | ||
110 | |||
111 | return do_hw_write(codec, reg, value, data, 2); | ||
112 | } | ||
113 | |||
114 | static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, | ||
115 | unsigned int value) | ||
116 | { | ||
117 | u8 data[3]; | ||
118 | u16 val = cpu_to_be16(value); | ||
119 | |||
120 | data[0] = reg; | ||
121 | memcpy(&data[1], &val, sizeof(val)); | ||
122 | |||
123 | return do_hw_write(codec, reg, value, data, 3); | ||
124 | } | ||
125 | |||
126 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
127 | static unsigned int do_i2c_read(struct snd_soc_codec *codec, | ||
128 | void *reg, int reglen, | ||
129 | void *data, int datalen) | ||
130 | { | ||
131 | struct i2c_msg xfer[2]; | ||
132 | int ret; | ||
133 | struct i2c_client *client = codec->control_data; | ||
134 | |||
135 | /* Write register */ | ||
136 | xfer[0].addr = client->addr; | ||
137 | xfer[0].flags = 0; | ||
138 | xfer[0].len = reglen; | ||
139 | xfer[0].buf = reg; | ||
140 | |||
141 | /* Read data */ | ||
142 | xfer[1].addr = client->addr; | ||
143 | xfer[1].flags = I2C_M_RD; | ||
144 | xfer[1].len = datalen; | ||
145 | xfer[1].buf = data; | ||
146 | |||
147 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
148 | if (ret == 2) | ||
149 | return 0; | ||
150 | else if (ret < 0) | ||
151 | return ret; | ||
152 | else | ||
153 | return -EIO; | ||
154 | } | ||
155 | #endif | ||
156 | |||
157 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
158 | static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec, | ||
159 | unsigned int r) | ||
160 | { | ||
161 | u8 reg = r; | ||
162 | u8 data; | ||
163 | int ret; | ||
164 | |||
165 | ret = do_i2c_read(codec, ®, 1, &data, 1); | ||
166 | if (ret < 0) | ||
167 | return 0; | ||
168 | return data; | ||
169 | } | ||
170 | #else | ||
171 | #define snd_soc_8_8_read_i2c NULL | ||
172 | #endif | ||
173 | |||
174 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
175 | static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec, | ||
176 | unsigned int r) | ||
177 | { | ||
178 | u8 reg = r; | ||
179 | u16 data; | ||
180 | int ret; | ||
181 | |||
182 | ret = do_i2c_read(codec, ®, 1, &data, 2); | ||
183 | if (ret < 0) | ||
184 | return 0; | ||
185 | return (data >> 8) | ((data & 0xff) << 8); | ||
186 | } | ||
187 | #else | ||
188 | #define snd_soc_8_16_read_i2c NULL | ||
189 | #endif | ||
190 | |||
191 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
192 | static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec, | ||
193 | unsigned int r) | ||
194 | { | ||
195 | u16 reg = r; | ||
196 | u8 data; | ||
197 | int ret; | ||
198 | |||
199 | ret = do_i2c_read(codec, ®, 2, &data, 1); | ||
200 | if (ret < 0) | ||
201 | return 0; | ||
202 | return data; | ||
203 | } | ||
204 | #else | ||
205 | #define snd_soc_16_8_read_i2c NULL | ||
206 | #endif | ||
207 | |||
208 | static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, | ||
209 | unsigned int value) | ||
210 | { | ||
211 | u8 data[3]; | ||
212 | u16 rval = cpu_to_be16(reg); | ||
213 | |||
214 | memcpy(data, &rval, sizeof(rval)); | ||
215 | data[2] = value; | ||
216 | |||
217 | return do_hw_write(codec, reg, value, data, 3); | ||
218 | } | ||
219 | |||
220 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
221 | static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec, | ||
222 | unsigned int r) | ||
223 | { | ||
224 | u16 reg = cpu_to_be16(r); | ||
225 | u16 data; | ||
226 | int ret; | ||
227 | |||
228 | ret = do_i2c_read(codec, ®, 2, &data, 2); | ||
229 | if (ret < 0) | ||
230 | return 0; | ||
231 | return be16_to_cpu(data); | ||
232 | } | ||
233 | #else | ||
234 | #define snd_soc_16_16_read_i2c NULL | ||
235 | #endif | ||
236 | |||
237 | static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, | ||
238 | unsigned int value) | ||
239 | { | ||
240 | u16 data[2]; | ||
241 | |||
242 | data[0] = cpu_to_be16(reg); | ||
243 | data[1] = cpu_to_be16(value); | ||
244 | |||
245 | return do_hw_write(codec, reg, value, data, sizeof(data)); | ||
246 | } | ||
247 | |||
248 | /* Primitive bulk write support for soc-cache. The data pointed to by | ||
249 | * `data' needs to already be in the form the hardware expects | ||
250 | * including any leading register specific data. Any data written | ||
251 | * through this function will not go through the cache as it only | ||
252 | * handles writing to volatile or out of bounds registers. | ||
253 | */ | ||
254 | static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg, | ||
255 | const void *data, size_t len) | ||
256 | { | ||
257 | int ret; | ||
258 | |||
259 | /* To ensure that we don't get out of sync with the cache, check | ||
260 | * whether the base register is volatile or if we've directly asked | ||
261 | * to bypass the cache. Out of bounds registers are considered | ||
262 | * volatile. | ||
263 | */ | ||
264 | if (!codec->cache_bypass | ||
265 | && !snd_soc_codec_volatile_register(codec, reg) | ||
266 | && reg < codec->driver->reg_cache_size) | ||
267 | return -EINVAL; | ||
268 | |||
269 | switch (codec->control_type) { | ||
270 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
271 | case SND_SOC_I2C: | ||
272 | ret = i2c_master_send(to_i2c_client(codec->dev), data, len); | ||
273 | break; | ||
274 | #endif | ||
275 | #if defined(CONFIG_SPI_MASTER) | ||
276 | case SND_SOC_SPI: | ||
277 | ret = spi_write(to_spi_device(codec->dev), data, len); | ||
278 | break; | ||
279 | #endif | ||
280 | default: | ||
281 | BUG(); | ||
282 | } | ||
283 | |||
284 | if (ret == len) | ||
285 | return 0; | ||
286 | if (ret < 0) | ||
287 | return ret; | ||
288 | else | ||
289 | return -EIO; | ||
290 | } | ||
291 | |||
292 | static struct { | ||
293 | int addr_bits; | ||
294 | int data_bits; | ||
295 | int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int); | ||
296 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); | ||
297 | unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); | ||
298 | } io_types[] = { | ||
299 | { | ||
300 | .addr_bits = 4, .data_bits = 12, | ||
301 | .write = snd_soc_4_12_write, | ||
302 | }, | ||
303 | { | ||
304 | .addr_bits = 7, .data_bits = 9, | ||
305 | .write = snd_soc_7_9_write, | ||
306 | }, | ||
307 | { | ||
308 | .addr_bits = 8, .data_bits = 8, | ||
309 | .write = snd_soc_8_8_write, | ||
310 | .i2c_read = snd_soc_8_8_read_i2c, | ||
311 | }, | ||
312 | { | ||
313 | .addr_bits = 8, .data_bits = 16, | ||
314 | .write = snd_soc_8_16_write, | ||
315 | .i2c_read = snd_soc_8_16_read_i2c, | ||
316 | }, | ||
317 | { | ||
318 | .addr_bits = 16, .data_bits = 8, | ||
319 | .write = snd_soc_16_8_write, | ||
320 | .i2c_read = snd_soc_16_8_read_i2c, | ||
321 | }, | ||
322 | { | ||
323 | .addr_bits = 16, .data_bits = 16, | ||
324 | .write = snd_soc_16_16_write, | ||
325 | .i2c_read = snd_soc_16_16_read_i2c, | ||
326 | }, | ||
327 | }; | ||
328 | |||
329 | /** | ||
330 | * snd_soc_codec_set_cache_io: Set up standard I/O functions. | ||
331 | * | ||
332 | * @codec: CODEC to configure. | ||
333 | * @addr_bits: Number of bits of register address data. | ||
334 | * @data_bits: Number of bits of data per register. | ||
335 | * @control: Control bus used. | ||
336 | * | ||
337 | * Register formats are frequently shared between many I2C and SPI | ||
338 | * devices. In order to promote code reuse the ASoC core provides | ||
339 | * some standard implementations of CODEC read and write operations | ||
340 | * which can be set up using this function. | ||
341 | * | ||
342 | * The caller is responsible for allocating and initialising the | ||
343 | * actual cache. | ||
344 | * | ||
345 | * Note that at present this code cannot be used by CODECs with | ||
346 | * volatile registers. | ||
347 | */ | ||
348 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | ||
349 | int addr_bits, int data_bits, | ||
350 | enum snd_soc_control_type control) | ||
351 | { | ||
352 | int i; | ||
353 | |||
354 | for (i = 0; i < ARRAY_SIZE(io_types); i++) | ||
355 | if (io_types[i].addr_bits == addr_bits && | ||
356 | io_types[i].data_bits == data_bits) | ||
357 | break; | ||
358 | if (i == ARRAY_SIZE(io_types)) { | ||
359 | printk(KERN_ERR | ||
360 | "No I/O functions for %d bit address %d bit data\n", | ||
361 | addr_bits, data_bits); | ||
362 | return -EINVAL; | ||
363 | } | ||
364 | |||
365 | codec->write = io_types[i].write; | ||
366 | codec->read = hw_read; | ||
367 | codec->bulk_write_raw = snd_soc_hw_bulk_write_raw; | ||
368 | |||
369 | switch (control) { | ||
370 | case SND_SOC_I2C: | ||
371 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
372 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
373 | #endif | ||
374 | if (io_types[i].i2c_read) | ||
375 | codec->hw_read = io_types[i].i2c_read; | ||
376 | |||
377 | codec->control_data = container_of(codec->dev, | ||
378 | struct i2c_client, | ||
379 | dev); | ||
380 | break; | ||
381 | |||
382 | case SND_SOC_SPI: | ||
383 | #ifdef CONFIG_SPI_MASTER | ||
384 | codec->hw_write = do_spi_write; | ||
385 | #endif | ||
386 | |||
387 | codec->control_data = container_of(codec->dev, | ||
388 | struct spi_device, | ||
389 | dev); | ||
390 | break; | ||
391 | } | ||
392 | |||
393 | return 0; | ||
394 | } | ||
395 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); | ||
396 | |||
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c new file mode 100644 index 000000000000..b5759397afa3 --- /dev/null +++ b/sound/soc/soc-pcm.c | |||
@@ -0,0 +1,639 @@ | |||
1 | /* | ||
2 | * soc-pcm.c -- ALSA SoC PCM | ||
3 | * | ||
4 | * Copyright 2005 Wolfson Microelectronics PLC. | ||
5 | * Copyright 2005 Openedhand Ltd. | ||
6 | * Copyright (C) 2010 Slimlogic Ltd. | ||
7 | * Copyright (C) 2010 Texas Instruments Inc. | ||
8 | * | ||
9 | * Authors: Liam Girdwood <lrg@ti.com> | ||
10 | * Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/soc.h> | ||
28 | #include <sound/initval.h> | ||
29 | |||
30 | static DEFINE_MUTEX(pcm_mutex); | ||
31 | |||
32 | static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) | ||
33 | { | ||
34 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
35 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
36 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
37 | int ret; | ||
38 | |||
39 | if (!codec_dai->driver->symmetric_rates && | ||
40 | !cpu_dai->driver->symmetric_rates && | ||
41 | !rtd->dai_link->symmetric_rates) | ||
42 | return 0; | ||
43 | |||
44 | /* This can happen if multiple streams are starting simultaneously - | ||
45 | * the second can need to get its constraints before the first has | ||
46 | * picked a rate. Complain and allow the application to carry on. | ||
47 | */ | ||
48 | if (!rtd->rate) { | ||
49 | dev_warn(&rtd->dev, | ||
50 | "Not enforcing symmetric_rates due to race\n"); | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate); | ||
55 | |||
56 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, | ||
57 | SNDRV_PCM_HW_PARAM_RATE, | ||
58 | rtd->rate, rtd->rate); | ||
59 | if (ret < 0) { | ||
60 | dev_err(&rtd->dev, | ||
61 | "Unable to apply rate symmetry constraint: %d\n", ret); | ||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Called by ALSA when a PCM substream is opened, the runtime->hw record is | ||
70 | * then initialized and any private data can be allocated. This also calls | ||
71 | * startup for the cpu DAI, platform, machine and codec DAI. | ||
72 | */ | ||
73 | static int soc_pcm_open(struct snd_pcm_substream *substream) | ||
74 | { | ||
75 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
76 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
77 | struct snd_soc_platform *platform = rtd->platform; | ||
78 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
79 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
80 | struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; | ||
81 | struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver; | ||
82 | int ret = 0; | ||
83 | |||
84 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | ||
85 | |||
86 | /* startup the audio subsystem */ | ||
87 | if (cpu_dai->driver->ops->startup) { | ||
88 | ret = cpu_dai->driver->ops->startup(substream, cpu_dai); | ||
89 | if (ret < 0) { | ||
90 | printk(KERN_ERR "asoc: can't open interface %s\n", | ||
91 | cpu_dai->name); | ||
92 | goto out; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | if (platform->driver->ops && platform->driver->ops->open) { | ||
97 | ret = platform->driver->ops->open(substream); | ||
98 | if (ret < 0) { | ||
99 | printk(KERN_ERR "asoc: can't open platform %s\n", platform->name); | ||
100 | goto platform_err; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | if (codec_dai->driver->ops->startup) { | ||
105 | ret = codec_dai->driver->ops->startup(substream, codec_dai); | ||
106 | if (ret < 0) { | ||
107 | printk(KERN_ERR "asoc: can't open codec %s\n", | ||
108 | codec_dai->name); | ||
109 | goto codec_dai_err; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | if (rtd->dai_link->ops && rtd->dai_link->ops->startup) { | ||
114 | ret = rtd->dai_link->ops->startup(substream); | ||
115 | if (ret < 0) { | ||
116 | printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name); | ||
117 | goto machine_err; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | /* Check that the codec and cpu DAIs are compatible */ | ||
122 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
123 | runtime->hw.rate_min = | ||
124 | max(codec_dai_drv->playback.rate_min, | ||
125 | cpu_dai_drv->playback.rate_min); | ||
126 | runtime->hw.rate_max = | ||
127 | min(codec_dai_drv->playback.rate_max, | ||
128 | cpu_dai_drv->playback.rate_max); | ||
129 | runtime->hw.channels_min = | ||
130 | max(codec_dai_drv->playback.channels_min, | ||
131 | cpu_dai_drv->playback.channels_min); | ||
132 | runtime->hw.channels_max = | ||
133 | min(codec_dai_drv->playback.channels_max, | ||
134 | cpu_dai_drv->playback.channels_max); | ||
135 | runtime->hw.formats = | ||
136 | codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats; | ||
137 | runtime->hw.rates = | ||
138 | codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates; | ||
139 | if (codec_dai_drv->playback.rates | ||
140 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
141 | runtime->hw.rates |= cpu_dai_drv->playback.rates; | ||
142 | if (cpu_dai_drv->playback.rates | ||
143 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
144 | runtime->hw.rates |= codec_dai_drv->playback.rates; | ||
145 | } else { | ||
146 | runtime->hw.rate_min = | ||
147 | max(codec_dai_drv->capture.rate_min, | ||
148 | cpu_dai_drv->capture.rate_min); | ||
149 | runtime->hw.rate_max = | ||
150 | min(codec_dai_drv->capture.rate_max, | ||
151 | cpu_dai_drv->capture.rate_max); | ||
152 | runtime->hw.channels_min = | ||
153 | max(codec_dai_drv->capture.channels_min, | ||
154 | cpu_dai_drv->capture.channels_min); | ||
155 | runtime->hw.channels_max = | ||
156 | min(codec_dai_drv->capture.channels_max, | ||
157 | cpu_dai_drv->capture.channels_max); | ||
158 | runtime->hw.formats = | ||
159 | codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats; | ||
160 | runtime->hw.rates = | ||
161 | codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates; | ||
162 | if (codec_dai_drv->capture.rates | ||
163 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
164 | runtime->hw.rates |= cpu_dai_drv->capture.rates; | ||
165 | if (cpu_dai_drv->capture.rates | ||
166 | & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) | ||
167 | runtime->hw.rates |= codec_dai_drv->capture.rates; | ||
168 | } | ||
169 | |||
170 | ret = -EINVAL; | ||
171 | snd_pcm_limit_hw_rates(runtime); | ||
172 | if (!runtime->hw.rates) { | ||
173 | printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", | ||
174 | codec_dai->name, cpu_dai->name); | ||
175 | goto config_err; | ||
176 | } | ||
177 | if (!runtime->hw.formats) { | ||
178 | printk(KERN_ERR "asoc: %s <-> %s No matching formats\n", | ||
179 | codec_dai->name, cpu_dai->name); | ||
180 | goto config_err; | ||
181 | } | ||
182 | if (!runtime->hw.channels_min || !runtime->hw.channels_max || | ||
183 | runtime->hw.channels_min > runtime->hw.channels_max) { | ||
184 | printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", | ||
185 | codec_dai->name, cpu_dai->name); | ||
186 | goto config_err; | ||
187 | } | ||
188 | |||
189 | /* Symmetry only applies if we've already got an active stream. */ | ||
190 | if (cpu_dai->active || codec_dai->active) { | ||
191 | ret = soc_pcm_apply_symmetry(substream); | ||
192 | if (ret != 0) | ||
193 | goto config_err; | ||
194 | } | ||
195 | |||
196 | pr_debug("asoc: %s <-> %s info:\n", | ||
197 | codec_dai->name, cpu_dai->name); | ||
198 | pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); | ||
199 | pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, | ||
200 | runtime->hw.channels_max); | ||
201 | pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, | ||
202 | runtime->hw.rate_max); | ||
203 | |||
204 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
205 | cpu_dai->playback_active++; | ||
206 | codec_dai->playback_active++; | ||
207 | } else { | ||
208 | cpu_dai->capture_active++; | ||
209 | codec_dai->capture_active++; | ||
210 | } | ||
211 | cpu_dai->active++; | ||
212 | codec_dai->active++; | ||
213 | rtd->codec->active++; | ||
214 | mutex_unlock(&rtd->pcm_mutex); | ||
215 | return 0; | ||
216 | |||
217 | config_err: | ||
218 | if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) | ||
219 | rtd->dai_link->ops->shutdown(substream); | ||
220 | |||
221 | machine_err: | ||
222 | if (codec_dai->driver->ops->shutdown) | ||
223 | codec_dai->driver->ops->shutdown(substream, codec_dai); | ||
224 | |||
225 | codec_dai_err: | ||
226 | if (platform->driver->ops && platform->driver->ops->close) | ||
227 | platform->driver->ops->close(substream); | ||
228 | |||
229 | platform_err: | ||
230 | if (cpu_dai->driver->ops->shutdown) | ||
231 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | ||
232 | out: | ||
233 | mutex_unlock(&rtd->pcm_mutex); | ||
234 | return ret; | ||
235 | } | ||
236 | |||
237 | /* | ||
238 | * Power down the audio subsystem pmdown_time msecs after close is called. | ||
239 | * This is to ensure there are no pops or clicks in between any music tracks | ||
240 | * due to DAPM power cycling. | ||
241 | */ | ||
242 | static void close_delayed_work(struct work_struct *work) | ||
243 | { | ||
244 | struct snd_soc_pcm_runtime *rtd = | ||
245 | container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); | ||
246 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
247 | |||
248 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | ||
249 | |||
250 | pr_debug("pop wq checking: %s status: %s waiting: %s\n", | ||
251 | codec_dai->driver->playback.stream_name, | ||
252 | codec_dai->playback_active ? "active" : "inactive", | ||
253 | codec_dai->pop_wait ? "yes" : "no"); | ||
254 | |||
255 | /* are we waiting on this codec DAI stream */ | ||
256 | if (codec_dai->pop_wait == 1) { | ||
257 | codec_dai->pop_wait = 0; | ||
258 | snd_soc_dapm_stream_event(rtd, | ||
259 | codec_dai->driver->playback.stream_name, | ||
260 | SND_SOC_DAPM_STREAM_STOP); | ||
261 | } | ||
262 | |||
263 | mutex_unlock(&rtd->pcm_mutex); | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * Called by ALSA when a PCM substream is closed. Private data can be | ||
268 | * freed here. The cpu DAI, codec DAI, machine and platform are also | ||
269 | * shutdown. | ||
270 | */ | ||
271 | static int soc_pcm_close(struct snd_pcm_substream *substream) | ||
272 | { | ||
273 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
274 | struct snd_soc_platform *platform = rtd->platform; | ||
275 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
276 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
277 | struct snd_soc_codec *codec = rtd->codec; | ||
278 | |||
279 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | ||
280 | |||
281 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
282 | cpu_dai->playback_active--; | ||
283 | codec_dai->playback_active--; | ||
284 | } else { | ||
285 | cpu_dai->capture_active--; | ||
286 | codec_dai->capture_active--; | ||
287 | } | ||
288 | |||
289 | cpu_dai->active--; | ||
290 | codec_dai->active--; | ||
291 | codec->active--; | ||
292 | |||
293 | /* Muting the DAC suppresses artifacts caused during digital | ||
294 | * shutdown, for example from stopping clocks. | ||
295 | */ | ||
296 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
297 | snd_soc_dai_digital_mute(codec_dai, 1); | ||
298 | |||
299 | if (cpu_dai->driver->ops->shutdown) | ||
300 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | ||
301 | |||
302 | if (codec_dai->driver->ops->shutdown) | ||
303 | codec_dai->driver->ops->shutdown(substream, codec_dai); | ||
304 | |||
305 | if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown) | ||
306 | rtd->dai_link->ops->shutdown(substream); | ||
307 | |||
308 | if (platform->driver->ops && platform->driver->ops->close) | ||
309 | platform->driver->ops->close(substream); | ||
310 | cpu_dai->runtime = NULL; | ||
311 | |||
312 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
313 | /* start delayed pop wq here for playback streams */ | ||
314 | codec_dai->pop_wait = 1; | ||
315 | schedule_delayed_work(&rtd->delayed_work, | ||
316 | msecs_to_jiffies(rtd->pmdown_time)); | ||
317 | } else { | ||
318 | /* capture streams can be powered down now */ | ||
319 | snd_soc_dapm_stream_event(rtd, | ||
320 | codec_dai->driver->capture.stream_name, | ||
321 | SND_SOC_DAPM_STREAM_STOP); | ||
322 | } | ||
323 | |||
324 | mutex_unlock(&rtd->pcm_mutex); | ||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | * Called by ALSA when the PCM substream is prepared, can set format, sample | ||
330 | * rate, etc. This function is non atomic and can be called multiple times, | ||
331 | * it can refer to the runtime info. | ||
332 | */ | ||
333 | static int soc_pcm_prepare(struct snd_pcm_substream *substream) | ||
334 | { | ||
335 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
336 | struct snd_soc_platform *platform = rtd->platform; | ||
337 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
338 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
339 | int ret = 0; | ||
340 | |||
341 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | ||
342 | |||
343 | if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) { | ||
344 | ret = rtd->dai_link->ops->prepare(substream); | ||
345 | if (ret < 0) { | ||
346 | printk(KERN_ERR "asoc: machine prepare error\n"); | ||
347 | goto out; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | if (platform->driver->ops && platform->driver->ops->prepare) { | ||
352 | ret = platform->driver->ops->prepare(substream); | ||
353 | if (ret < 0) { | ||
354 | printk(KERN_ERR "asoc: platform prepare error\n"); | ||
355 | goto out; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | if (codec_dai->driver->ops->prepare) { | ||
360 | ret = codec_dai->driver->ops->prepare(substream, codec_dai); | ||
361 | if (ret < 0) { | ||
362 | printk(KERN_ERR "asoc: codec DAI prepare error\n"); | ||
363 | goto out; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | if (cpu_dai->driver->ops->prepare) { | ||
368 | ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); | ||
369 | if (ret < 0) { | ||
370 | printk(KERN_ERR "asoc: cpu DAI prepare error\n"); | ||
371 | goto out; | ||
372 | } | ||
373 | } | ||
374 | |||
375 | /* cancel any delayed stream shutdown that is pending */ | ||
376 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | ||
377 | codec_dai->pop_wait) { | ||
378 | codec_dai->pop_wait = 0; | ||
379 | cancel_delayed_work(&rtd->delayed_work); | ||
380 | } | ||
381 | |||
382 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
383 | snd_soc_dapm_stream_event(rtd, | ||
384 | codec_dai->driver->playback.stream_name, | ||
385 | SND_SOC_DAPM_STREAM_START); | ||
386 | else | ||
387 | snd_soc_dapm_stream_event(rtd, | ||
388 | codec_dai->driver->capture.stream_name, | ||
389 | SND_SOC_DAPM_STREAM_START); | ||
390 | |||
391 | snd_soc_dai_digital_mute(codec_dai, 0); | ||
392 | |||
393 | out: | ||
394 | mutex_unlock(&rtd->pcm_mutex); | ||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | /* | ||
399 | * Called by ALSA when the hardware params are set by application. This | ||
400 | * function can also be called multiple times and can allocate buffers | ||
401 | * (using snd_pcm_lib_* ). It's non-atomic. | ||
402 | */ | ||
403 | static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | ||
404 | struct snd_pcm_hw_params *params) | ||
405 | { | ||
406 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
407 | struct snd_soc_platform *platform = rtd->platform; | ||
408 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
409 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
410 | int ret = 0; | ||
411 | |||
412 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | ||
413 | |||
414 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { | ||
415 | ret = rtd->dai_link->ops->hw_params(substream, params); | ||
416 | if (ret < 0) { | ||
417 | printk(KERN_ERR "asoc: machine hw_params failed\n"); | ||
418 | goto out; | ||
419 | } | ||
420 | } | ||
421 | |||
422 | if (codec_dai->driver->ops->hw_params) { | ||
423 | ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); | ||
424 | if (ret < 0) { | ||
425 | printk(KERN_ERR "asoc: can't set codec %s hw params\n", | ||
426 | codec_dai->name); | ||
427 | goto codec_err; | ||
428 | } | ||
429 | } | ||
430 | |||
431 | if (cpu_dai->driver->ops->hw_params) { | ||
432 | ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai); | ||
433 | if (ret < 0) { | ||
434 | printk(KERN_ERR "asoc: interface %s hw params failed\n", | ||
435 | cpu_dai->name); | ||
436 | goto interface_err; | ||
437 | } | ||
438 | } | ||
439 | |||
440 | if (platform->driver->ops && platform->driver->ops->hw_params) { | ||
441 | ret = platform->driver->ops->hw_params(substream, params); | ||
442 | if (ret < 0) { | ||
443 | printk(KERN_ERR "asoc: platform %s hw params failed\n", | ||
444 | platform->name); | ||
445 | goto platform_err; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | rtd->rate = params_rate(params); | ||
450 | |||
451 | out: | ||
452 | mutex_unlock(&rtd->pcm_mutex); | ||
453 | return ret; | ||
454 | |||
455 | platform_err: | ||
456 | if (cpu_dai->driver->ops->hw_free) | ||
457 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | ||
458 | |||
459 | interface_err: | ||
460 | if (codec_dai->driver->ops->hw_free) | ||
461 | codec_dai->driver->ops->hw_free(substream, codec_dai); | ||
462 | |||
463 | codec_err: | ||
464 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) | ||
465 | rtd->dai_link->ops->hw_free(substream); | ||
466 | |||
467 | mutex_unlock(&rtd->pcm_mutex); | ||
468 | return ret; | ||
469 | } | ||
470 | |||
471 | /* | ||
472 | * Frees resources allocated by hw_params, can be called multiple times | ||
473 | */ | ||
474 | static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | ||
475 | { | ||
476 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
477 | struct snd_soc_platform *platform = rtd->platform; | ||
478 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
479 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
480 | struct snd_soc_codec *codec = rtd->codec; | ||
481 | |||
482 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | ||
483 | |||
484 | /* apply codec digital mute */ | ||
485 | if (!codec->active) | ||
486 | snd_soc_dai_digital_mute(codec_dai, 1); | ||
487 | |||
488 | /* free any machine hw params */ | ||
489 | if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free) | ||
490 | rtd->dai_link->ops->hw_free(substream); | ||
491 | |||
492 | /* free any DMA resources */ | ||
493 | if (platform->driver->ops && platform->driver->ops->hw_free) | ||
494 | platform->driver->ops->hw_free(substream); | ||
495 | |||
496 | /* now free hw params for the DAIs */ | ||
497 | if (codec_dai->driver->ops->hw_free) | ||
498 | codec_dai->driver->ops->hw_free(substream, codec_dai); | ||
499 | |||
500 | if (cpu_dai->driver->ops->hw_free) | ||
501 | cpu_dai->driver->ops->hw_free(substream, cpu_dai); | ||
502 | |||
503 | mutex_unlock(&rtd->pcm_mutex); | ||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
508 | { | ||
509 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
510 | struct snd_soc_platform *platform = rtd->platform; | ||
511 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
512 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
513 | int ret; | ||
514 | |||
515 | if (codec_dai->driver->ops->trigger) { | ||
516 | ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai); | ||
517 | if (ret < 0) | ||
518 | return ret; | ||
519 | } | ||
520 | |||
521 | if (platform->driver->ops && platform->driver->ops->trigger) { | ||
522 | ret = platform->driver->ops->trigger(substream, cmd); | ||
523 | if (ret < 0) | ||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | if (cpu_dai->driver->ops->trigger) { | ||
528 | ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai); | ||
529 | if (ret < 0) | ||
530 | return ret; | ||
531 | } | ||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | /* | ||
536 | * soc level wrapper for pointer callback | ||
537 | * If cpu_dai, codec_dai, platform driver has the delay callback, than | ||
538 | * the runtime->delay will be updated accordingly. | ||
539 | */ | ||
540 | static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | ||
541 | { | ||
542 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
543 | struct snd_soc_platform *platform = rtd->platform; | ||
544 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
545 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
546 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
547 | snd_pcm_uframes_t offset = 0; | ||
548 | snd_pcm_sframes_t delay = 0; | ||
549 | |||
550 | if (platform->driver->ops && platform->driver->ops->pointer) | ||
551 | offset = platform->driver->ops->pointer(substream); | ||
552 | |||
553 | if (cpu_dai->driver->ops->delay) | ||
554 | delay += cpu_dai->driver->ops->delay(substream, cpu_dai); | ||
555 | |||
556 | if (codec_dai->driver->ops->delay) | ||
557 | delay += codec_dai->driver->ops->delay(substream, codec_dai); | ||
558 | |||
559 | if (platform->driver->delay) | ||
560 | delay += platform->driver->delay(substream, codec_dai); | ||
561 | |||
562 | runtime->delay = delay; | ||
563 | |||
564 | return offset; | ||
565 | } | ||
566 | |||
567 | /* ASoC PCM operations */ | ||
568 | static struct snd_pcm_ops soc_pcm_ops = { | ||
569 | .open = soc_pcm_open, | ||
570 | .close = soc_pcm_close, | ||
571 | .hw_params = soc_pcm_hw_params, | ||
572 | .hw_free = soc_pcm_hw_free, | ||
573 | .prepare = soc_pcm_prepare, | ||
574 | .trigger = soc_pcm_trigger, | ||
575 | .pointer = soc_pcm_pointer, | ||
576 | }; | ||
577 | |||
578 | /* create a new pcm */ | ||
579 | int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | ||
580 | { | ||
581 | struct snd_soc_codec *codec = rtd->codec; | ||
582 | struct snd_soc_platform *platform = rtd->platform; | ||
583 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
584 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
585 | struct snd_pcm *pcm; | ||
586 | char new_name[64]; | ||
587 | int ret = 0, playback = 0, capture = 0; | ||
588 | |||
589 | /* check client and interface hw capabilities */ | ||
590 | snprintf(new_name, sizeof(new_name), "%s %s-%d", | ||
591 | rtd->dai_link->stream_name, codec_dai->name, num); | ||
592 | |||
593 | if (codec_dai->driver->playback.channels_min) | ||
594 | playback = 1; | ||
595 | if (codec_dai->driver->capture.channels_min) | ||
596 | capture = 1; | ||
597 | |||
598 | dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name); | ||
599 | ret = snd_pcm_new(rtd->card->snd_card, new_name, | ||
600 | num, playback, capture, &pcm); | ||
601 | if (ret < 0) { | ||
602 | printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name); | ||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | /* DAPM dai link stream work */ | ||
607 | INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); | ||
608 | |||
609 | rtd->pcm = pcm; | ||
610 | pcm->private_data = rtd; | ||
611 | if (platform->driver->ops) { | ||
612 | soc_pcm_ops.mmap = platform->driver->ops->mmap; | ||
613 | soc_pcm_ops.pointer = platform->driver->ops->pointer; | ||
614 | soc_pcm_ops.ioctl = platform->driver->ops->ioctl; | ||
615 | soc_pcm_ops.copy = platform->driver->ops->copy; | ||
616 | soc_pcm_ops.silence = platform->driver->ops->silence; | ||
617 | soc_pcm_ops.ack = platform->driver->ops->ack; | ||
618 | soc_pcm_ops.page = platform->driver->ops->page; | ||
619 | } | ||
620 | |||
621 | if (playback) | ||
622 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); | ||
623 | |||
624 | if (capture) | ||
625 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); | ||
626 | |||
627 | if (platform->driver->pcm_new) { | ||
628 | ret = platform->driver->pcm_new(rtd); | ||
629 | if (ret < 0) { | ||
630 | pr_err("asoc: platform pcm constructor failed\n"); | ||
631 | return ret; | ||
632 | } | ||
633 | } | ||
634 | |||
635 | pcm->private_free = platform->driver->pcm_free; | ||
636 | printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, | ||
637 | cpu_dai->name); | ||
638 | return ret; | ||
639 | } | ||
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 035d39a4beb4..c6af1fd707f5 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig | |||
@@ -12,6 +12,15 @@ config SND_SOC_TEGRA_I2S | |||
12 | Tegra I2S interface. You will also need to select the individual | 12 | Tegra I2S interface. You will also need to select the individual |
13 | machine drivers to support below. | 13 | machine drivers to support below. |
14 | 14 | ||
15 | config SND_SOC_TEGRA_SPDIF | ||
16 | tristate | ||
17 | depends on SND_SOC_TEGRA | ||
18 | default m | ||
19 | help | ||
20 | Say Y or M if you want to add support for the SPDIF interface. | ||
21 | You will also need to select the individual machine drivers to support | ||
22 | below. | ||
23 | |||
15 | config MACH_HAS_SND_SOC_TEGRA_WM8903 | 24 | config MACH_HAS_SND_SOC_TEGRA_WM8903 |
16 | bool | 25 | bool |
17 | help | 26 | help |
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index fa6574d92a31..4d943b3fe150 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile | |||
@@ -2,12 +2,14 @@ | |||
2 | snd-soc-tegra-das-objs := tegra_das.o | 2 | snd-soc-tegra-das-objs := tegra_das.o |
3 | snd-soc-tegra-pcm-objs := tegra_pcm.o | 3 | snd-soc-tegra-pcm-objs := tegra_pcm.o |
4 | snd-soc-tegra-i2s-objs := tegra_i2s.o | 4 | snd-soc-tegra-i2s-objs := tegra_i2s.o |
5 | snd-soc-tegra-spdif-objs := tegra_spdif.o | ||
5 | snd-soc-tegra-utils-objs += tegra_asoc_utils.o | 6 | snd-soc-tegra-utils-objs += tegra_asoc_utils.o |
6 | 7 | ||
7 | obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o | 8 | obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o |
8 | obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-das.o | 9 | obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-das.o |
9 | obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o | 10 | obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o |
10 | obj-$(CONFIG_SND_SOC_TEGRA_I2S) += snd-soc-tegra-i2s.o | 11 | obj-$(CONFIG_SND_SOC_TEGRA_I2S) += snd-soc-tegra-i2s.o |
12 | obj-$(CONFIG_SND_SOC_TEGRA_SPDIF) += snd-soc-tegra-spdif.o | ||
11 | 13 | ||
12 | # Tegra machine Support | 14 | # Tegra machine Support |
13 | snd-soc-tegra-wm8903-objs := tegra_wm8903.o | 15 | snd-soc-tegra-wm8903-objs := tegra_wm8903.o |
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c index 6b817e20548c..f36b9969cfec 100644 --- a/sound/soc/tegra/tegra_i2s.c +++ b/sound/soc/tegra/tegra_i2s.c | |||
@@ -222,12 +222,18 @@ static int tegra_i2s_hw_params(struct snd_pcm_substream *substream, | |||
222 | if (i2sclock % (2 * srate)) | 222 | if (i2sclock % (2 * srate)) |
223 | reg |= TEGRA_I2S_TIMING_NON_SYM_ENABLE; | 223 | reg |= TEGRA_I2S_TIMING_NON_SYM_ENABLE; |
224 | 224 | ||
225 | if (!i2s->clk_refs) | ||
226 | clk_enable(i2s->clk_i2s); | ||
227 | |||
225 | tegra_i2s_write(i2s, TEGRA_I2S_TIMING, reg); | 228 | tegra_i2s_write(i2s, TEGRA_I2S_TIMING, reg); |
226 | 229 | ||
227 | tegra_i2s_write(i2s, TEGRA_I2S_FIFO_SCR, | 230 | tegra_i2s_write(i2s, TEGRA_I2S_FIFO_SCR, |
228 | TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | | 231 | TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | |
229 | TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); | 232 | TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); |
230 | 233 | ||
234 | if (!i2s->clk_refs) | ||
235 | clk_disable(i2s->clk_i2s); | ||
236 | |||
231 | return 0; | 237 | return 0; |
232 | } | 238 | } |
233 | 239 | ||
@@ -348,7 +354,6 @@ struct snd_soc_dai_driver tegra_i2s_dai[] = { | |||
348 | static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev) | 354 | static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev) |
349 | { | 355 | { |
350 | struct tegra_i2s * i2s; | 356 | struct tegra_i2s * i2s; |
351 | char clk_name[12]; /* tegra-i2s.0 */ | ||
352 | struct resource *mem, *memregion, *dmareq; | 357 | struct resource *mem, *memregion, *dmareq; |
353 | int ret; | 358 | int ret; |
354 | 359 | ||
@@ -383,8 +388,7 @@ static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev) | |||
383 | } | 388 | } |
384 | dev_set_drvdata(&pdev->dev, i2s); | 389 | dev_set_drvdata(&pdev->dev, i2s); |
385 | 390 | ||
386 | snprintf(clk_name, sizeof(clk_name), DRV_NAME ".%d", pdev->id); | 391 | i2s->clk_i2s = clk_get(&pdev->dev, NULL); |
387 | i2s->clk_i2s = clk_get_sys(clk_name, NULL); | ||
388 | if (IS_ERR(i2s->clk_i2s)) { | 392 | if (IS_ERR(i2s->clk_i2s)) { |
389 | dev_err(&pdev->dev, "Can't retrieve i2s clock\n"); | 393 | dev_err(&pdev->dev, "Can't retrieve i2s clock\n"); |
390 | ret = PTR_ERR(i2s->clk_i2s); | 394 | ret = PTR_ERR(i2s->clk_i2s); |
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 3c271f953582..ff86e5e3db68 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c | |||
@@ -322,9 +322,11 @@ static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream) | |||
322 | 322 | ||
323 | static u64 tegra_dma_mask = DMA_BIT_MASK(32); | 323 | static u64 tegra_dma_mask = DMA_BIT_MASK(32); |
324 | 324 | ||
325 | static int tegra_pcm_new(struct snd_card *card, | 325 | static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd) |
326 | struct snd_soc_dai *dai, struct snd_pcm *pcm) | ||
327 | { | 326 | { |
327 | struct snd_card *card = rtd->card->snd_card; | ||
328 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
329 | struct snd_pcm *pcm = rtd->pcm; | ||
328 | int ret = 0; | 330 | int ret = 0; |
329 | 331 | ||
330 | if (!card->dev->dma_mask) | 332 | if (!card->dev->dma_mask) |
diff --git a/sound/soc/tegra/tegra_spdif.c b/sound/soc/tegra/tegra_spdif.c new file mode 100644 index 000000000000..abe606b0a29e --- /dev/null +++ b/sound/soc/tegra/tegra_spdif.c | |||
@@ -0,0 +1,371 @@ | |||
1 | /* | ||
2 | * tegra_spdif.c - Tegra SPDIF driver | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2011 - NVIDIA, Inc. | ||
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 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
19 | * 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/clk.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/debugfs.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/io.h> | ||
31 | #include <mach/iomap.h> | ||
32 | #include <sound/core.h> | ||
33 | #include <sound/pcm.h> | ||
34 | #include <sound/pcm_params.h> | ||
35 | #include <sound/soc.h> | ||
36 | |||
37 | #include "tegra_spdif.h" | ||
38 | |||
39 | #define DRV_NAME "tegra-spdif" | ||
40 | |||
41 | static inline void tegra_spdif_write(struct tegra_spdif *spdif, u32 reg, | ||
42 | u32 val) | ||
43 | { | ||
44 | __raw_writel(val, spdif->regs + reg); | ||
45 | } | ||
46 | |||
47 | static inline u32 tegra_spdif_read(struct tegra_spdif *spdif, u32 reg) | ||
48 | { | ||
49 | return __raw_readl(spdif->regs + reg); | ||
50 | } | ||
51 | |||
52 | #ifdef CONFIG_DEBUG_FS | ||
53 | static int tegra_spdif_show(struct seq_file *s, void *unused) | ||
54 | { | ||
55 | #define REG(r) { r, #r } | ||
56 | static const struct { | ||
57 | int offset; | ||
58 | const char *name; | ||
59 | } regs[] = { | ||
60 | REG(TEGRA_SPDIF_CTRL), | ||
61 | REG(TEGRA_SPDIF_STATUS), | ||
62 | REG(TEGRA_SPDIF_STROBE_CTRL), | ||
63 | REG(TEGRA_SPDIF_DATA_FIFO_CSR), | ||
64 | REG(TEGRA_SPDIF_CH_STA_RX_A), | ||
65 | REG(TEGRA_SPDIF_CH_STA_RX_B), | ||
66 | REG(TEGRA_SPDIF_CH_STA_RX_C), | ||
67 | REG(TEGRA_SPDIF_CH_STA_RX_D), | ||
68 | REG(TEGRA_SPDIF_CH_STA_RX_E), | ||
69 | REG(TEGRA_SPDIF_CH_STA_RX_F), | ||
70 | REG(TEGRA_SPDIF_CH_STA_TX_A), | ||
71 | REG(TEGRA_SPDIF_CH_STA_TX_B), | ||
72 | REG(TEGRA_SPDIF_CH_STA_TX_C), | ||
73 | REG(TEGRA_SPDIF_CH_STA_TX_D), | ||
74 | REG(TEGRA_SPDIF_CH_STA_TX_E), | ||
75 | REG(TEGRA_SPDIF_CH_STA_TX_F), | ||
76 | }; | ||
77 | #undef REG | ||
78 | |||
79 | struct tegra_spdif *spdif = s->private; | ||
80 | int i; | ||
81 | |||
82 | for (i = 0; i < ARRAY_SIZE(regs); i++) { | ||
83 | u32 val = tegra_spdif_read(spdif, regs[i].offset); | ||
84 | seq_printf(s, "%s = %08x\n", regs[i].name, val); | ||
85 | } | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int tegra_spdif_debug_open(struct inode *inode, struct file *file) | ||
91 | { | ||
92 | return single_open(file, tegra_spdif_show, inode->i_private); | ||
93 | } | ||
94 | |||
95 | static const struct file_operations tegra_spdif_debug_fops = { | ||
96 | .open = tegra_spdif_debug_open, | ||
97 | .read = seq_read, | ||
98 | .llseek = seq_lseek, | ||
99 | .release = single_release, | ||
100 | }; | ||
101 | |||
102 | static void tegra_spdif_debug_add(struct tegra_spdif *spdif) | ||
103 | { | ||
104 | spdif->debug = debugfs_create_file(DRV_NAME, S_IRUGO, | ||
105 | snd_soc_debugfs_root, spdif, | ||
106 | &tegra_spdif_debug_fops); | ||
107 | } | ||
108 | |||
109 | static void tegra_spdif_debug_remove(struct tegra_spdif *spdif) | ||
110 | { | ||
111 | if (spdif->debug) | ||
112 | debugfs_remove(spdif->debug); | ||
113 | } | ||
114 | #else | ||
115 | static inline void tegra_spdif_debug_add(struct tegra_spdif *spdif) | ||
116 | { | ||
117 | } | ||
118 | |||
119 | static inline void tegra_spdif_debug_remove(struct tegra_spdif *spdif) | ||
120 | { | ||
121 | } | ||
122 | #endif | ||
123 | |||
124 | static int tegra_spdif_hw_params(struct snd_pcm_substream *substream, | ||
125 | struct snd_pcm_hw_params *params, | ||
126 | struct snd_soc_dai *dai) | ||
127 | { | ||
128 | struct device *dev = substream->pcm->card->dev; | ||
129 | struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai); | ||
130 | int ret, srate, spdifclock; | ||
131 | |||
132 | spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_PACK; | ||
133 | spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_BIT_MODE_MASK; | ||
134 | switch (params_format(params)) { | ||
135 | case SNDRV_PCM_FORMAT_S16_LE: | ||
136 | spdif->reg_ctrl |= TEGRA_SPDIF_CTRL_PACK; | ||
137 | spdif->reg_ctrl |= TEGRA_SPDIF_CTRL_BIT_MODE_16BIT; | ||
138 | break; | ||
139 | default: | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | |||
143 | srate = params_rate(params); | ||
144 | switch (params_rate(params)) { | ||
145 | case 32000: | ||
146 | spdifclock = 4096000; | ||
147 | break; | ||
148 | case 44100: | ||
149 | spdifclock = 5644800; | ||
150 | break; | ||
151 | case 48000: | ||
152 | spdifclock = 6144000; | ||
153 | break; | ||
154 | case 88200: | ||
155 | spdifclock = 11289600; | ||
156 | break; | ||
157 | case 96000: | ||
158 | spdifclock = 12288000; | ||
159 | break; | ||
160 | case 176400: | ||
161 | spdifclock = 22579200; | ||
162 | break; | ||
163 | case 192000: | ||
164 | spdifclock = 24576000; | ||
165 | break; | ||
166 | default: | ||
167 | return -EINVAL; | ||
168 | } | ||
169 | |||
170 | ret = clk_set_rate(spdif->clk_spdif_out, spdifclock); | ||
171 | if (ret) { | ||
172 | dev_err(dev, "Can't set SPDIF clock rate: %d\n", ret); | ||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static void tegra_spdif_start_playback(struct tegra_spdif *spdif) | ||
180 | { | ||
181 | spdif->reg_ctrl |= TEGRA_SPDIF_CTRL_TX_EN; | ||
182 | tegra_spdif_write(spdif, TEGRA_SPDIF_CTRL, spdif->reg_ctrl); | ||
183 | } | ||
184 | |||
185 | static void tegra_spdif_stop_playback(struct tegra_spdif *spdif) | ||
186 | { | ||
187 | spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_TX_EN; | ||
188 | tegra_spdif_write(spdif, TEGRA_SPDIF_CTRL, spdif->reg_ctrl); | ||
189 | } | ||
190 | |||
191 | static int tegra_spdif_trigger(struct snd_pcm_substream *substream, int cmd, | ||
192 | struct snd_soc_dai *dai) | ||
193 | { | ||
194 | struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai); | ||
195 | |||
196 | switch (cmd) { | ||
197 | case SNDRV_PCM_TRIGGER_START: | ||
198 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
199 | case SNDRV_PCM_TRIGGER_RESUME: | ||
200 | if (!spdif->clk_refs) | ||
201 | clk_enable(spdif->clk_spdif_out); | ||
202 | spdif->clk_refs++; | ||
203 | tegra_spdif_start_playback(spdif); | ||
204 | break; | ||
205 | case SNDRV_PCM_TRIGGER_STOP: | ||
206 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
207 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
208 | tegra_spdif_stop_playback(spdif); | ||
209 | spdif->clk_refs--; | ||
210 | if (!spdif->clk_refs) | ||
211 | clk_disable(spdif->clk_spdif_out); | ||
212 | break; | ||
213 | default: | ||
214 | return -EINVAL; | ||
215 | } | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int tegra_spdif_probe(struct snd_soc_dai *dai) | ||
221 | { | ||
222 | struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai); | ||
223 | |||
224 | dai->capture_dma_data = NULL; | ||
225 | dai->playback_dma_data = &spdif->playback_dma_data; | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static struct snd_soc_dai_ops tegra_spdif_dai_ops = { | ||
231 | .hw_params = tegra_spdif_hw_params, | ||
232 | .trigger = tegra_spdif_trigger, | ||
233 | }; | ||
234 | |||
235 | struct snd_soc_dai_driver tegra_spdif_dai = { | ||
236 | .name = DRV_NAME, | ||
237 | .probe = tegra_spdif_probe, | ||
238 | .playback = { | ||
239 | .channels_min = 2, | ||
240 | .channels_max = 2, | ||
241 | .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | | ||
242 | SNDRV_PCM_RATE_48000, | ||
243 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
244 | }, | ||
245 | .ops = &tegra_spdif_dai_ops, | ||
246 | }; | ||
247 | |||
248 | static __devinit int tegra_spdif_platform_probe(struct platform_device *pdev) | ||
249 | { | ||
250 | struct tegra_spdif *spdif; | ||
251 | struct resource *mem, *memregion, *dmareq; | ||
252 | int ret; | ||
253 | |||
254 | spdif = kzalloc(sizeof(struct tegra_spdif), GFP_KERNEL); | ||
255 | if (!spdif) { | ||
256 | dev_err(&pdev->dev, "Can't allocate tegra_spdif\n"); | ||
257 | ret = -ENOMEM; | ||
258 | goto exit; | ||
259 | } | ||
260 | dev_set_drvdata(&pdev->dev, spdif); | ||
261 | |||
262 | spdif->clk_spdif_out = clk_get(&pdev->dev, "spdif_out"); | ||
263 | if (IS_ERR(spdif->clk_spdif_out)) { | ||
264 | pr_err("Can't retrieve spdif clock\n"); | ||
265 | ret = PTR_ERR(spdif->clk_spdif_out); | ||
266 | goto err_free; | ||
267 | } | ||
268 | |||
269 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
270 | if (!mem) { | ||
271 | dev_err(&pdev->dev, "No memory resource\n"); | ||
272 | ret = -ENODEV; | ||
273 | goto err_clk_put; | ||
274 | } | ||
275 | |||
276 | dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
277 | if (!dmareq) { | ||
278 | dev_err(&pdev->dev, "No DMA resource\n"); | ||
279 | ret = -ENODEV; | ||
280 | goto err_clk_put; | ||
281 | } | ||
282 | |||
283 | memregion = request_mem_region(mem->start, resource_size(mem), | ||
284 | DRV_NAME); | ||
285 | if (!memregion) { | ||
286 | dev_err(&pdev->dev, "Memory region already claimed\n"); | ||
287 | ret = -EBUSY; | ||
288 | goto err_clk_put; | ||
289 | } | ||
290 | |||
291 | spdif->regs = ioremap(mem->start, resource_size(mem)); | ||
292 | if (!spdif->regs) { | ||
293 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
294 | ret = -ENOMEM; | ||
295 | goto err_release; | ||
296 | } | ||
297 | |||
298 | spdif->playback_dma_data.addr = mem->start + TEGRA_SPDIF_DATA_OUT; | ||
299 | spdif->playback_dma_data.wrap = 4; | ||
300 | spdif->playback_dma_data.width = 32; | ||
301 | spdif->playback_dma_data.req_sel = dmareq->start; | ||
302 | |||
303 | ret = snd_soc_register_dai(&pdev->dev, &tegra_spdif_dai); | ||
304 | if (ret) { | ||
305 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); | ||
306 | ret = -ENOMEM; | ||
307 | goto err_unmap; | ||
308 | } | ||
309 | |||
310 | tegra_spdif_debug_add(spdif); | ||
311 | |||
312 | return 0; | ||
313 | |||
314 | err_unmap: | ||
315 | iounmap(spdif->regs); | ||
316 | err_release: | ||
317 | release_mem_region(mem->start, resource_size(mem)); | ||
318 | err_clk_put: | ||
319 | clk_put(spdif->clk_spdif_out); | ||
320 | err_free: | ||
321 | kfree(spdif); | ||
322 | exit: | ||
323 | return ret; | ||
324 | } | ||
325 | |||
326 | static int __devexit tegra_spdif_platform_remove(struct platform_device *pdev) | ||
327 | { | ||
328 | struct tegra_spdif *spdif = dev_get_drvdata(&pdev->dev); | ||
329 | struct resource *res; | ||
330 | |||
331 | snd_soc_unregister_dai(&pdev->dev); | ||
332 | |||
333 | tegra_spdif_debug_remove(spdif); | ||
334 | |||
335 | iounmap(spdif->regs); | ||
336 | |||
337 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
338 | release_mem_region(res->start, resource_size(res)); | ||
339 | |||
340 | clk_put(spdif->clk_spdif_out); | ||
341 | |||
342 | kfree(spdif); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static struct platform_driver tegra_spdif_driver = { | ||
348 | .driver = { | ||
349 | .name = DRV_NAME, | ||
350 | .owner = THIS_MODULE, | ||
351 | }, | ||
352 | .probe = tegra_spdif_platform_probe, | ||
353 | .remove = __devexit_p(tegra_spdif_platform_remove), | ||
354 | }; | ||
355 | |||
356 | static int __init snd_tegra_spdif_init(void) | ||
357 | { | ||
358 | return platform_driver_register(&tegra_spdif_driver); | ||
359 | } | ||
360 | module_init(snd_tegra_spdif_init); | ||
361 | |||
362 | static void __exit snd_tegra_spdif_exit(void) | ||
363 | { | ||
364 | platform_driver_unregister(&tegra_spdif_driver); | ||
365 | } | ||
366 | module_exit(snd_tegra_spdif_exit); | ||
367 | |||
368 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
369 | MODULE_DESCRIPTION("Tegra SPDIF ASoC driver"); | ||
370 | MODULE_LICENSE("GPL"); | ||
371 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/tegra/tegra_spdif.h b/sound/soc/tegra/tegra_spdif.h new file mode 100644 index 000000000000..2e03db430279 --- /dev/null +++ b/sound/soc/tegra/tegra_spdif.h | |||
@@ -0,0 +1,473 @@ | |||
1 | /* | ||
2 | * tegra_spdif.h - Definitions for Tegra SPDIF driver | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2011 - NVIDIA, Inc. | ||
6 | * | ||
7 | * Based on code copyright/by: | ||
8 | * Copyright (c) 2008-2009, NVIDIA Corporation | ||
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 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #ifndef __TEGRA_SPDIF_H__ | ||
27 | #define __TEGRA_SPDIF_H__ | ||
28 | |||
29 | #include "tegra_pcm.h" | ||
30 | |||
31 | /* Offsets from TEGRA_SPDIF_BASE */ | ||
32 | |||
33 | #define TEGRA_SPDIF_CTRL 0x0 | ||
34 | #define TEGRA_SPDIF_STATUS 0x4 | ||
35 | #define TEGRA_SPDIF_STROBE_CTRL 0x8 | ||
36 | #define TEGRA_SPDIF_DATA_FIFO_CSR 0x0C | ||
37 | #define TEGRA_SPDIF_DATA_OUT 0x40 | ||
38 | #define TEGRA_SPDIF_DATA_IN 0x80 | ||
39 | #define TEGRA_SPDIF_CH_STA_RX_A 0x100 | ||
40 | #define TEGRA_SPDIF_CH_STA_RX_B 0x104 | ||
41 | #define TEGRA_SPDIF_CH_STA_RX_C 0x108 | ||
42 | #define TEGRA_SPDIF_CH_STA_RX_D 0x10C | ||
43 | #define TEGRA_SPDIF_CH_STA_RX_E 0x110 | ||
44 | #define TEGRA_SPDIF_CH_STA_RX_F 0x114 | ||
45 | #define TEGRA_SPDIF_CH_STA_TX_A 0x140 | ||
46 | #define TEGRA_SPDIF_CH_STA_TX_B 0x144 | ||
47 | #define TEGRA_SPDIF_CH_STA_TX_C 0x148 | ||
48 | #define TEGRA_SPDIF_CH_STA_TX_D 0x14C | ||
49 | #define TEGRA_SPDIF_CH_STA_TX_E 0x150 | ||
50 | #define TEGRA_SPDIF_CH_STA_TX_F 0x154 | ||
51 | #define TEGRA_SPDIF_USR_STA_RX_A 0x180 | ||
52 | #define TEGRA_SPDIF_USR_DAT_TX_A 0x1C0 | ||
53 | |||
54 | /* Fields in TEGRA_SPDIF_CTRL */ | ||
55 | |||
56 | /* Start capturing from 0=right, 1=left channel */ | ||
57 | #define TEGRA_SPDIF_CTRL_CAP_LC (1 << 30) | ||
58 | |||
59 | /* SPDIF receiver(RX) enable */ | ||
60 | #define TEGRA_SPDIF_CTRL_RX_EN (1 << 29) | ||
61 | |||
62 | /* SPDIF Transmitter(TX) enable */ | ||
63 | #define TEGRA_SPDIF_CTRL_TX_EN (1 << 28) | ||
64 | |||
65 | /* Transmit Channel status */ | ||
66 | #define TEGRA_SPDIF_CTRL_TC_EN (1 << 27) | ||
67 | |||
68 | /* Transmit user Data */ | ||
69 | #define TEGRA_SPDIF_CTRL_TU_EN (1 << 26) | ||
70 | |||
71 | /* Interrupt on transmit error */ | ||
72 | #define TEGRA_SPDIF_CTRL_IE_TXE (1 << 25) | ||
73 | |||
74 | /* Interrupt on receive error */ | ||
75 | #define TEGRA_SPDIF_CTRL_IE_RXE (1 << 24) | ||
76 | |||
77 | /* Interrupt on invalid preamble */ | ||
78 | #define TEGRA_SPDIF_CTRL_IE_P (1 << 23) | ||
79 | |||
80 | /* Interrupt on "B" preamble */ | ||
81 | #define TEGRA_SPDIF_CTRL_IE_B (1 << 22) | ||
82 | |||
83 | /* Interrupt when block of channel status received */ | ||
84 | #define TEGRA_SPDIF_CTRL_IE_C (1 << 21) | ||
85 | |||
86 | /* Interrupt when a valid information unit (IU) is received */ | ||
87 | #define TEGRA_SPDIF_CTRL_IE_U (1 << 20) | ||
88 | |||
89 | /* Interrupt when RX user FIFO attention level is reached */ | ||
90 | #define TEGRA_SPDIF_CTRL_QE_RU (1 << 19) | ||
91 | |||
92 | /* Interrupt when TX user FIFO attention level is reached */ | ||
93 | #define TEGRA_SPDIF_CTRL_QE_TU (1 << 18) | ||
94 | |||
95 | /* Interrupt when RX data FIFO attention level is reached */ | ||
96 | #define TEGRA_SPDIF_CTRL_QE_RX (1 << 17) | ||
97 | |||
98 | /* Interrupt when TX data FIFO attention level is reached */ | ||
99 | #define TEGRA_SPDIF_CTRL_QE_TX (1 << 16) | ||
100 | |||
101 | /* Loopback test mode enable */ | ||
102 | #define TEGRA_SPDIF_CTRL_LBK_EN (1 << 15) | ||
103 | |||
104 | /* | ||
105 | * Pack data mode: | ||
106 | * 0 = Single data (16 bit needs to be padded to match the | ||
107 | * interface data bit size). | ||
108 | * 1 = Packeted left/right channel data into a single word. | ||
109 | */ | ||
110 | #define TEGRA_SPDIF_CTRL_PACK (1 << 14) | ||
111 | |||
112 | /* | ||
113 | * 00 = 16bit data | ||
114 | * 01 = 20bit data | ||
115 | * 10 = 24bit data | ||
116 | * 11 = raw data | ||
117 | */ | ||
118 | #define TEGRA_SPDIF_BIT_MODE_16BIT 0 | ||
119 | #define TEGRA_SPDIF_BIT_MODE_20BIT 1 | ||
120 | #define TEGRA_SPDIF_BIT_MODE_24BIT 2 | ||
121 | #define TEGRA_SPDIF_BIT_MODE_RAW 3 | ||
122 | |||
123 | #define TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT 12 | ||
124 | #define TEGRA_SPDIF_CTRL_BIT_MODE_MASK (3 << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT) | ||
125 | #define TEGRA_SPDIF_CTRL_BIT_MODE_16BIT (TEGRA_SPDIF_BIT_MODE_16BIT << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT) | ||
126 | #define TEGRA_SPDIF_CTRL_BIT_MODE_20BIT (TEGRA_SPDIF_BIT_MODE_20BIT << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT) | ||
127 | #define TEGRA_SPDIF_CTRL_BIT_MODE_24BIT (TEGRA_SPDIF_BIT_MODE_24BIT << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT) | ||
128 | #define TEGRA_SPDIF_CTRL_BIT_MODE_RAW (TEGRA_SPDIF_BIT_MODE_RAW << TEGRA_SPDIF_CTRL_BIT_MODE_SHIFT) | ||
129 | |||
130 | /* Fields in TEGRA_SPDIF_STATUS */ | ||
131 | |||
132 | /* | ||
133 | * Note: IS_P, IS_B, IS_C, and IS_U are sticky bits. Software must | ||
134 | * write a 1 to the corresponding bit location to clear the status. | ||
135 | */ | ||
136 | |||
137 | /* | ||
138 | * Receiver(RX) shifter is busy receiving data. | ||
139 | * This bit is asserted when the receiver first locked onto the | ||
140 | * preamble of the data stream after RX_EN is asserted. This bit is | ||
141 | * deasserted when either, | ||
142 | * (a) the end of a frame is reached after RX_EN is deeasserted, or | ||
143 | * (b) the SPDIF data stream becomes inactive. | ||
144 | */ | ||
145 | #define TEGRA_SPDIF_STATUS_RX_BSY (1 << 29) | ||
146 | |||
147 | /* | ||
148 | * Transmitter(TX) shifter is busy transmitting data. | ||
149 | * This bit is asserted when TX_EN is asserted. | ||
150 | * This bit is deasserted when the end of a frame is reached after | ||
151 | * TX_EN is deasserted. | ||
152 | */ | ||
153 | #define TEGRA_SPDIF_STATUS_TX_BSY (1 << 28) | ||
154 | |||
155 | /* | ||
156 | * TX is busy shifting out channel status. | ||
157 | * This bit is asserted when both TX_EN and TC_EN are asserted and | ||
158 | * data from CH_STA_TX_A register is loaded into the internal shifter. | ||
159 | * This bit is deasserted when either, | ||
160 | * (a) the end of a frame is reached after TX_EN is deasserted, or | ||
161 | * (b) CH_STA_TX_F register is loaded into the internal shifter. | ||
162 | */ | ||
163 | #define TEGRA_SPDIF_STATUS_TC_BSY (1 << 27) | ||
164 | |||
165 | /* | ||
166 | * TX User data FIFO busy. | ||
167 | * This bit is asserted when TX_EN and TXU_EN are asserted and | ||
168 | * there's data in the TX user FIFO. This bit is deassert when either, | ||
169 | * (a) the end of a frame is reached after TX_EN is deasserted, or | ||
170 | * (b) there's no data left in the TX user FIFO. | ||
171 | */ | ||
172 | #define TEGRA_SPDIF_STATUS_TU_BSY (1 << 26) | ||
173 | |||
174 | /* TX FIFO Underrun error status */ | ||
175 | #define TEGRA_SPDIF_STATUS_TX_ERR (1 << 25) | ||
176 | |||
177 | /* RX FIFO Overrun error status */ | ||
178 | #define TEGRA_SPDIF_STATUS_RX_ERR (1 << 24) | ||
179 | |||
180 | /* Preamble status: 0=Preamble OK, 1=bad/missing preamble */ | ||
181 | #define TEGRA_SPDIF_STATUS_IS_P (1 << 23) | ||
182 | |||
183 | /* B-preamble detection status: 0=not detected, 1=B-preamble detected */ | ||
184 | #define TEGRA_SPDIF_STATUS_IS_B (1 << 22) | ||
185 | |||
186 | /* | ||
187 | * RX channel block data receive status: | ||
188 | * 0=entire block not recieved yet. | ||
189 | * 1=received entire block of channel status, | ||
190 | */ | ||
191 | #define TEGRA_SPDIF_STATUS_IS_C (1 << 21) | ||
192 | |||
193 | /* RX User Data Valid flag: 1=valid IU detected, 0 = no IU detected. */ | ||
194 | #define TEGRA_SPDIF_STATUS_IS_U (1 << 20) | ||
195 | |||
196 | /* | ||
197 | * RX User FIFO Status: | ||
198 | * 1=attention level reached, 0=attention level not reached. | ||
199 | */ | ||
200 | #define TEGRA_SPDIF_STATUS_QS_RU (1 << 19) | ||
201 | |||
202 | /* | ||
203 | * TX User FIFO Status: | ||
204 | * 1=attention level reached, 0=attention level not reached. | ||
205 | */ | ||
206 | #define TEGRA_SPDIF_STATUS_QS_TU (1 << 18) | ||
207 | |||
208 | /* | ||
209 | * RX Data FIFO Status: | ||
210 | * 1=attention level reached, 0=attention level not reached. | ||
211 | */ | ||
212 | #define TEGRA_SPDIF_STATUS_QS_RX (1 << 17) | ||
213 | |||
214 | /* | ||
215 | * TX Data FIFO Status: | ||
216 | * 1=attention level reached, 0=attention level not reached. | ||
217 | */ | ||
218 | #define TEGRA_SPDIF_STATUS_QS_TX (1 << 16) | ||
219 | |||
220 | /* Fields in TEGRA_SPDIF_STROBE_CTRL */ | ||
221 | |||
222 | /* | ||
223 | * Indicates the approximate number of detected SPDIFIN clocks within a | ||
224 | * bi-phase period. | ||
225 | */ | ||
226 | #define TEGRA_SPDIF_STROBE_CTRL_PERIOD_SHIFT 16 | ||
227 | #define TEGRA_SPDIF_STROBE_CTRL_PERIOD_MASK (0xff << TEGRA_SPDIF_STROBE_CTRL_PERIOD_SHIFT) | ||
228 | |||
229 | /* Data strobe mode: 0=Auto-locked 1=Manual locked */ | ||
230 | #define TEGRA_SPDIF_STROBE_CTRL_STROBE (1 << 15) | ||
231 | |||
232 | /* | ||
233 | * Manual data strobe time within the bi-phase clock period (in terms of | ||
234 | * the number of over-sampling clocks). | ||
235 | */ | ||
236 | #define TEGRA_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT 8 | ||
237 | #define TEGRA_SPDIF_STROBE_CTRL_DATA_STROBES_MASK (0x1f << TEGRA_SPDIF_STROBE_CTRL_DATA_STROBES_SHIFT) | ||
238 | |||
239 | /* | ||
240 | * Manual SPDIFIN bi-phase clock period (in terms of the number of | ||
241 | * over-sampling clocks). | ||
242 | */ | ||
243 | #define TEGRA_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT 0 | ||
244 | #define TEGRA_SPDIF_STROBE_CTRL_CLOCK_PERIOD_MASK (0x3f << TEGRA_SPDIF_STROBE_CTRL_CLOCK_PERIOD_SHIFT) | ||
245 | |||
246 | /* Fields in SPDIF_DATA_FIFO_CSR */ | ||
247 | |||
248 | /* Clear Receiver User FIFO (RX USR.FIFO) */ | ||
249 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RU_CLR (1 << 31) | ||
250 | |||
251 | #define TEGRA_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT 0 | ||
252 | #define TEGRA_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS 1 | ||
253 | #define TEGRA_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS 2 | ||
254 | #define TEGRA_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS 3 | ||
255 | |||
256 | /* RU FIFO attention level */ | ||
257 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT 29 | ||
258 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_MASK \ | ||
259 | (0x3 << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT) | ||
260 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU1_WORD_FULL \ | ||
261 | (TEGRA_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT) | ||
262 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU2_WORD_FULL \ | ||
263 | (TEGRA_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT) | ||
264 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU3_WORD_FULL \ | ||
265 | (TEGRA_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT) | ||
266 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_RU4_WORD_FULL \ | ||
267 | (TEGRA_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RU_ATN_LVL_SHIFT) | ||
268 | |||
269 | /* Number of RX USR.FIFO levels with valid data. */ | ||
270 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_SHIFT 24 | ||
271 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_MASK (0x1f << TEGRA_SPDIF_DATA_FIFO_CSR_RU_FULL_COUNT_SHIFT) | ||
272 | |||
273 | /* Clear Transmitter User FIFO (TX USR.FIFO) */ | ||
274 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TU_CLR (1 << 23) | ||
275 | |||
276 | /* TU FIFO attention level */ | ||
277 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT 21 | ||
278 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_MASK \ | ||
279 | (0x3 << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT) | ||
280 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU1_WORD_FULL \ | ||
281 | (TEGRA_SPDIF_FIFO_ATN_LVL_U_ONE_SLOT << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT) | ||
282 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU2_WORD_FULL \ | ||
283 | (TEGRA_SPDIF_FIFO_ATN_LVL_U_TWO_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT) | ||
284 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU3_WORD_FULL \ | ||
285 | (TEGRA_SPDIF_FIFO_ATN_LVL_U_THREE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT) | ||
286 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_TU4_WORD_FULL \ | ||
287 | (TEGRA_SPDIF_FIFO_ATN_LVL_U_FOUR_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TU_ATN_LVL_SHIFT) | ||
288 | |||
289 | /* Number of TX USR.FIFO levels that could be filled. */ | ||
290 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_SHIFT 16 | ||
291 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_MASK (0x1f << SPDIF_DATA_FIFO_CSR_TU_EMPTY_COUNT_SHIFT) | ||
292 | |||
293 | /* Clear Receiver Data FIFO (RX DATA.FIFO) */ | ||
294 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RX_CLR (1 << 15) | ||
295 | |||
296 | #define TEGRA_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT 0 | ||
297 | #define TEGRA_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS 1 | ||
298 | #define TEGRA_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS 2 | ||
299 | #define TEGRA_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS 3 | ||
300 | |||
301 | /* RU FIFO attention level */ | ||
302 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT 13 | ||
303 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_MASK \ | ||
304 | (0x3 << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT) | ||
305 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU1_WORD_FULL \ | ||
306 | (TEGRA_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT) | ||
307 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU4_WORD_FULL \ | ||
308 | (TEGRA_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT) | ||
309 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU8_WORD_FULL \ | ||
310 | (TEGRA_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT) | ||
311 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_RU12_WORD_FULL \ | ||
312 | (TEGRA_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_RX_ATN_LVL_SHIFT) | ||
313 | |||
314 | /* Number of RX DATA.FIFO levels with valid data. */ | ||
315 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_SHIFT 8 | ||
316 | #define TEGRA_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_MASK (0x1f << TEGRA_SPDIF_DATA_FIFO_CSR_RX_FULL_COUNT_SHIFT) | ||
317 | |||
318 | /* Clear Transmitter Data FIFO (TX DATA.FIFO) */ | ||
319 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TX_CLR (1 << 7) | ||
320 | |||
321 | /* TU FIFO attention level */ | ||
322 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT 5 | ||
323 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_MASK \ | ||
324 | (0x3 << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT) | ||
325 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU1_WORD_FULL \ | ||
326 | (TEGRA_SPDIF_FIFO_ATN_LVL_D_ONE_SLOT << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT) | ||
327 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU4_WORD_FULL \ | ||
328 | (TEGRA_SPDIF_FIFO_ATN_LVL_D_FOUR_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT) | ||
329 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU8_WORD_FULL \ | ||
330 | (TEGRA_SPDIF_FIFO_ATN_LVL_D_EIGHT_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT) | ||
331 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_TU12_WORD_FULL \ | ||
332 | (TEGRA_SPDIF_FIFO_ATN_LVL_D_TWELVE_SLOTS << TEGRA_SPDIF_DATA_FIFO_CSR_TX_ATN_LVL_SHIFT) | ||
333 | |||
334 | /* Number of TX DATA.FIFO levels that could be filled. */ | ||
335 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_SHIFT 0 | ||
336 | #define TEGRA_SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_MASK (0x1f << SPDIF_DATA_FIFO_CSR_TX_EMPTY_COUNT_SHIFT) | ||
337 | |||
338 | /* Fields in TEGRA_SPDIF_DATA_OUT */ | ||
339 | |||
340 | /* | ||
341 | * This register has 5 different formats: | ||
342 | * 16-bit (BIT_MODE=00, PACK=0) | ||
343 | * 20-bit (BIT_MODE=01, PACK=0) | ||
344 | * 24-bit (BIT_MODE=10, PACK=0) | ||
345 | * raw (BIT_MODE=11, PACK=0) | ||
346 | * 16-bit packed (BIT_MODE=00, PACK=1) | ||
347 | */ | ||
348 | |||
349 | #define TEGRA_SPDIF_DATA_OUT_DATA_16_SHIFT 0 | ||
350 | #define TEGRA_SPDIF_DATA_OUT_DATA_16_MASK (0xffff << TEGRA_SPDIF_DATA_OUT_DATA_16_SHIFT) | ||
351 | |||
352 | #define TEGRA_SPDIF_DATA_OUT_DATA_20_SHIFT 0 | ||
353 | #define TEGRA_SPDIF_DATA_OUT_DATA_20_MASK (0xfffff << TEGRA_SPDIF_DATA_OUT_DATA_20_SHIFT) | ||
354 | |||
355 | #define TEGRA_SPDIF_DATA_OUT_DATA_24_SHIFT 0 | ||
356 | #define TEGRA_SPDIF_DATA_OUT_DATA_24_MASK (0xffffff << TEGRA_SPDIF_DATA_OUT_DATA_24_SHIFT) | ||
357 | |||
358 | #define TEGRA_SPDIF_DATA_OUT_DATA_RAW_P (1 << 31) | ||
359 | #define TEGRA_SPDIF_DATA_OUT_DATA_RAW_C (1 << 30) | ||
360 | #define TEGRA_SPDIF_DATA_OUT_DATA_RAW_U (1 << 29) | ||
361 | #define TEGRA_SPDIF_DATA_OUT_DATA_RAW_V (1 << 28) | ||
362 | |||
363 | #define TEGRA_SPDIF_DATA_OUT_DATA_RAW_DATA_SHIFT 8 | ||
364 | #define TEGRA_SPDIF_DATA_OUT_DATA_RAW_DATA_MASK (0xfffff << TEGRA_SPDIF_DATA_OUT_DATA_RAW_DATA_SHIFT) | ||
365 | |||
366 | #define TEGRA_SPDIF_DATA_OUT_DATA_RAW_AUX_SHIFT 4 | ||
367 | #define TEGRA_SPDIF_DATA_OUT_DATA_RAW_AUX_MASK (0xf << TEGRA_SPDIF_DATA_OUT_DATA_RAW_AUX_SHIFT) | ||
368 | |||
369 | #define TEGRA_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_SHIFT 0 | ||
370 | #define TEGRA_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_MASK (0xf << TEGRA_SPDIF_DATA_OUT_DATA_RAW_PREAMBLE_SHIFT) | ||
371 | |||
372 | #define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_SHIFT 16 | ||
373 | #define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_MASK (0xffff << TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_RIGHT_SHIFT) | ||
374 | |||
375 | #define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_SHIFT 0 | ||
376 | #define TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_MASK (0xffff << TEGRA_SPDIF_DATA_OUT_DATA_16_PACKED_LEFT_SHIFT) | ||
377 | |||
378 | /* Fields in TEGRA_SPDIF_DATA_IN */ | ||
379 | |||
380 | /* | ||
381 | * This register has 5 different formats: | ||
382 | * 16-bit (BIT_MODE=00, PACK=0) | ||
383 | * 20-bit (BIT_MODE=01, PACK=0) | ||
384 | * 24-bit (BIT_MODE=10, PACK=0) | ||
385 | * raw (BIT_MODE=11, PACK=0) | ||
386 | * 16-bit packed (BIT_MODE=00, PACK=1) | ||
387 | * | ||
388 | * Bits 31:24 are common to all modes except 16-bit packed | ||
389 | */ | ||
390 | |||
391 | #define TEGRA_SPDIF_DATA_IN_DATA_P (1 << 31) | ||
392 | #define TEGRA_SPDIF_DATA_IN_DATA_C (1 << 30) | ||
393 | #define TEGRA_SPDIF_DATA_IN_DATA_U (1 << 29) | ||
394 | #define TEGRA_SPDIF_DATA_IN_DATA_V (1 << 28) | ||
395 | |||
396 | #define TEGRA_SPDIF_DATA_IN_DATA_PREAMBLE_SHIFT 24 | ||
397 | #define TEGRA_SPDIF_DATA_IN_DATA_PREAMBLE_MASK (0xf << TEGRA_SPDIF_DATA_IN_DATA_PREAMBLE_SHIFT) | ||
398 | |||
399 | #define TEGRA_SPDIF_DATA_IN_DATA_16_SHIFT 0 | ||
400 | #define TEGRA_SPDIF_DATA_IN_DATA_16_MASK (0xffff << TEGRA_SPDIF_DATA_IN_DATA_16_SHIFT) | ||
401 | |||
402 | #define TEGRA_SPDIF_DATA_IN_DATA_20_SHIFT 0 | ||
403 | #define TEGRA_SPDIF_DATA_IN_DATA_20_MASK (0xfffff << TEGRA_SPDIF_DATA_IN_DATA_20_SHIFT) | ||
404 | |||
405 | #define TEGRA_SPDIF_DATA_IN_DATA_24_SHIFT 0 | ||
406 | #define TEGRA_SPDIF_DATA_IN_DATA_24_MASK (0xffffff << TEGRA_SPDIF_DATA_IN_DATA_24_SHIFT) | ||
407 | |||
408 | #define TEGRA_SPDIF_DATA_IN_DATA_RAW_DATA_SHIFT 8 | ||
409 | #define TEGRA_SPDIF_DATA_IN_DATA_RAW_DATA_MASK (0xfffff << TEGRA_SPDIF_DATA_IN_DATA_RAW_DATA_SHIFT) | ||
410 | |||
411 | #define TEGRA_SPDIF_DATA_IN_DATA_RAW_AUX_SHIFT 4 | ||
412 | #define TEGRA_SPDIF_DATA_IN_DATA_RAW_AUX_MASK (0xf << TEGRA_SPDIF_DATA_IN_DATA_RAW_AUX_SHIFT) | ||
413 | |||
414 | #define TEGRA_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_SHIFT 0 | ||
415 | #define TEGRA_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_MASK (0xf << TEGRA_SPDIF_DATA_IN_DATA_RAW_PREAMBLE_SHIFT) | ||
416 | |||
417 | #define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_SHIFT 16 | ||
418 | #define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_MASK (0xffff << TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_RIGHT_SHIFT) | ||
419 | |||
420 | #define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_SHIFT 0 | ||
421 | #define TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_MASK (0xffff << TEGRA_SPDIF_DATA_IN_DATA_16_PACKED_LEFT_SHIFT) | ||
422 | |||
423 | /* Fields in TEGRA_SPDIF_CH_STA_RX_A */ | ||
424 | /* Fields in TEGRA_SPDIF_CH_STA_RX_B */ | ||
425 | /* Fields in TEGRA_SPDIF_CH_STA_RX_C */ | ||
426 | /* Fields in TEGRA_SPDIF_CH_STA_RX_D */ | ||
427 | /* Fields in TEGRA_SPDIF_CH_STA_RX_E */ | ||
428 | /* Fields in TEGRA_SPDIF_CH_STA_RX_F */ | ||
429 | |||
430 | /* | ||
431 | * The 6-word receive channel data page buffer holds a block (192 frames) of | ||
432 | * channel status information. The order of receive is from LSB to MSB | ||
433 | * bit, and from CH_STA_RX_A to CH_STA_RX_F then back to CH_STA_RX_A. | ||
434 | */ | ||
435 | |||
436 | /* Fields in TEGRA_SPDIF_CH_STA_TX_A */ | ||
437 | /* Fields in TEGRA_SPDIF_CH_STA_TX_B */ | ||
438 | /* Fields in TEGRA_SPDIF_CH_STA_TX_C */ | ||
439 | /* Fields in TEGRA_SPDIF_CH_STA_TX_D */ | ||
440 | /* Fields in TEGRA_SPDIF_CH_STA_TX_E */ | ||
441 | /* Fields in TEGRA_SPDIF_CH_STA_TX_F */ | ||
442 | |||
443 | /* | ||
444 | * The 6-word transmit channel data page buffer holds a block (192 frames) of | ||
445 | * channel status information. The order of transmission is from LSB to MSB | ||
446 | * bit, and from CH_STA_TX_A to CH_STA_TX_F then back to CH_STA_TX_A. | ||
447 | */ | ||
448 | |||
449 | /* Fields in TEGRA_SPDIF_USR_STA_RX_A */ | ||
450 | |||
451 | /* | ||
452 | * This 4-word deep FIFO receives user FIFO field information. The order of | ||
453 | * receive is from LSB to MSB bit. | ||
454 | */ | ||
455 | |||
456 | /* Fields in TEGRA_SPDIF_USR_DAT_TX_A */ | ||
457 | |||
458 | /* | ||
459 | * This 4-word deep FIFO transmits user FIFO field information. The order of | ||
460 | * transmission is from LSB to MSB bit. | ||
461 | */ | ||
462 | |||
463 | struct tegra_spdif { | ||
464 | struct clk *clk_spdif_out; | ||
465 | int clk_refs; | ||
466 | struct tegra_pcm_dma_params capture_dma_data; | ||
467 | struct tegra_pcm_dma_params playback_dma_data; | ||
468 | void __iomem *regs; | ||
469 | struct dentry *debug; | ||
470 | u32 reg_ctrl; | ||
471 | }; | ||
472 | |||
473 | #endif | ||
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 0d6738a8b29a..a42e9ac30f28 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c | |||
@@ -267,7 +267,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) | |||
267 | } | 267 | } |
268 | machine->gpio_requested |= GPIO_HP_MUTE; | 268 | machine->gpio_requested |= GPIO_HP_MUTE; |
269 | 269 | ||
270 | gpio_direction_output(pdata->gpio_hp_mute, 0); | 270 | gpio_direction_output(pdata->gpio_hp_mute, 1); |
271 | } | 271 | } |
272 | 272 | ||
273 | if (gpio_is_valid(pdata->gpio_int_mic_en)) { | 273 | if (gpio_is_valid(pdata->gpio_int_mic_en)) { |
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index f4aa4e03c888..34aa972669ed 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c | |||
@@ -288,9 +288,10 @@ static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
288 | snd_pcm_lib_preallocate_free_for_all(pcm); | 288 | snd_pcm_lib_preallocate_free_for_all(pcm); |
289 | } | 289 | } |
290 | 290 | ||
291 | static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | 291 | static int txx9aclc_pcm_new(struct snd_soc_pcm_runtime *rtd) |
292 | struct snd_pcm *pcm) | ||
293 | { | 292 | { |
293 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
294 | struct snd_pcm *pcm = rtd->pcm; | ||
294 | struct platform_device *pdev = to_platform_device(dai->platform->dev); | 295 | struct platform_device *pdev = to_platform_device(dai->platform->dev); |
295 | struct txx9aclc_soc_device *dev; | 296 | struct txx9aclc_soc_device *dev; |
296 | struct resource *r; | 297 | struct resource *r; |
diff --git a/sound/usb/card.c b/sound/usb/card.c index 220c6167dd86..781d9e61adfb 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c | |||
@@ -433,9 +433,10 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
433 | * only at the first time. the successive calls of this function will | 433 | * only at the first time. the successive calls of this function will |
434 | * append the pcm interface to the corresponding card. | 434 | * append the pcm interface to the corresponding card. |
435 | */ | 435 | */ |
436 | static void *snd_usb_audio_probe(struct usb_device *dev, | 436 | static struct snd_usb_audio * |
437 | struct usb_interface *intf, | 437 | snd_usb_audio_probe(struct usb_device *dev, |
438 | const struct usb_device_id *usb_id) | 438 | struct usb_interface *intf, |
439 | const struct usb_device_id *usb_id) | ||
439 | { | 440 | { |
440 | const struct snd_usb_audio_quirk *quirk = (const struct snd_usb_audio_quirk *)usb_id->driver_info; | 441 | const struct snd_usb_audio_quirk *quirk = (const struct snd_usb_audio_quirk *)usb_id->driver_info; |
441 | int i, err; | 442 | int i, err; |
@@ -540,16 +541,15 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
540 | * we need to take care of counter, since disconnection can be called also | 541 | * we need to take care of counter, since disconnection can be called also |
541 | * many times as well as usb_audio_probe(). | 542 | * many times as well as usb_audio_probe(). |
542 | */ | 543 | */ |
543 | static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) | 544 | static void snd_usb_audio_disconnect(struct usb_device *dev, |
545 | struct snd_usb_audio *chip) | ||
544 | { | 546 | { |
545 | struct snd_usb_audio *chip; | ||
546 | struct snd_card *card; | 547 | struct snd_card *card; |
547 | struct list_head *p; | 548 | struct list_head *p; |
548 | 549 | ||
549 | if (ptr == (void *)-1L) | 550 | if (chip == (void *)-1L) |
550 | return; | 551 | return; |
551 | 552 | ||
552 | chip = ptr; | ||
553 | card = chip->card; | 553 | card = chip->card; |
554 | mutex_lock(®ister_mutex); | 554 | mutex_lock(®ister_mutex); |
555 | mutex_lock(&chip->shutdown_mutex); | 555 | mutex_lock(&chip->shutdown_mutex); |
@@ -585,7 +585,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) | |||
585 | static int usb_audio_probe(struct usb_interface *intf, | 585 | static int usb_audio_probe(struct usb_interface *intf, |
586 | const struct usb_device_id *id) | 586 | const struct usb_device_id *id) |
587 | { | 587 | { |
588 | void *chip; | 588 | struct snd_usb_audio *chip; |
589 | chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id); | 589 | chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id); |
590 | if (chip) { | 590 | if (chip) { |
591 | usb_set_intfdata(intf, chip); | 591 | usb_set_intfdata(intf, chip); |
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index b0ef9f501896..7c0d21ecd821 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
@@ -408,6 +408,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
408 | /* doesn't set the sample rate attribute, but supports it */ | 408 | /* doesn't set the sample rate attribute, but supports it */ |
409 | fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE; | 409 | fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE; |
410 | break; | 410 | break; |
411 | case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */ | ||
412 | case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */ | ||
411 | case USB_ID(0x047f, 0x0ca1): /* plantronics headset */ | 413 | case USB_ID(0x047f, 0x0ca1): /* plantronics headset */ |
412 | case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is | 414 | case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is |
413 | an older model 77d:223) */ | 415 | an older model 77d:223) */ |
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index fb5d68fa7ff4..67bec7612442 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c | |||
@@ -645,7 +645,7 @@ static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream, | |||
645 | err = snd_pcm_hw_constraint_minmax(substream->runtime, | 645 | err = snd_pcm_hw_constraint_minmax(substream->runtime, |
646 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | 646 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, |
647 | 1500000 / ua->packets_per_second, | 647 | 1500000 / ua->packets_per_second, |
648 | 8192000); | 648 | UINT_MAX); |
649 | if (err < 0) | 649 | if (err < 0) |
650 | return err; | 650 | return err; |
651 | err = snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24); | 651 | err = snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24); |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 0b2ae8e1c02d..dba0b7f11c54 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -1677,6 +1677,36 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1677 | } | 1677 | } |
1678 | } | 1678 | } |
1679 | }, | 1679 | }, |
1680 | { | ||
1681 | USB_DEVICE(0x0582, 0x011e), | ||
1682 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1683 | /* .vendor_name = "BOSS", */ | ||
1684 | /* .product_name = "BR-800", */ | ||
1685 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1686 | .type = QUIRK_COMPOSITE, | ||
1687 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1688 | { | ||
1689 | .ifnum = 0, | ||
1690 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1691 | }, | ||
1692 | { | ||
1693 | .ifnum = 1, | ||
1694 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1695 | }, | ||
1696 | { | ||
1697 | .ifnum = 2, | ||
1698 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1699 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1700 | .out_cables = 0x0001, | ||
1701 | .in_cables = 0x0001 | ||
1702 | } | ||
1703 | }, | ||
1704 | { | ||
1705 | .ifnum = -1 | ||
1706 | } | ||
1707 | } | ||
1708 | } | ||
1709 | }, | ||
1680 | 1710 | ||
1681 | /* Guillemot devices */ | 1711 | /* Guillemot devices */ |
1682 | { | 1712 | { |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 090e1930dfdc..77762c99afbe 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -369,6 +369,30 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev) | |||
369 | return 0; | 369 | return 0; |
370 | } | 370 | } |
371 | 371 | ||
372 | static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev) | ||
373 | { | ||
374 | int err; | ||
375 | |||
376 | if (dev->actconfig->desc.bConfigurationValue == 1) { | ||
377 | snd_printk(KERN_INFO "usb-audio: " | ||
378 | "Fast Track Pro switching to config #2\n"); | ||
379 | /* This function has to be available by the usb core module. | ||
380 | * if it is not avialable the boot quirk has to be left out | ||
381 | * and the configuration has to be set by udev or hotplug | ||
382 | * rules | ||
383 | */ | ||
384 | err = usb_driver_set_configuration(dev, 2); | ||
385 | if (err < 0) { | ||
386 | snd_printdd("error usb_driver_set_configuration: %d\n", | ||
387 | err); | ||
388 | return -ENODEV; | ||
389 | } | ||
390 | } else | ||
391 | snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n"); | ||
392 | |||
393 | return 0; | ||
394 | } | ||
395 | |||
372 | /* | 396 | /* |
373 | * C-Media CM106/CM106+ have four 16-bit internal registers that are nicely | 397 | * C-Media CM106/CM106+ have four 16-bit internal registers that are nicely |
374 | * documented in the device's data sheet. | 398 | * documented in the device's data sheet. |
@@ -471,16 +495,49 @@ static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev) | |||
471 | /* | 495 | /* |
472 | * Setup quirks | 496 | * Setup quirks |
473 | */ | 497 | */ |
474 | #define AUDIOPHILE_SET 0x01 /* if set, parse device_setup */ | 498 | #define MAUDIO_SET 0x01 /* parse device_setup */ |
475 | #define AUDIOPHILE_SET_DTS 0x02 /* if set, enable DTS Digital Output */ | 499 | #define MAUDIO_SET_COMPATIBLE 0x80 /* use only "win-compatible" interfaces */ |
476 | #define AUDIOPHILE_SET_96K 0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */ | 500 | #define MAUDIO_SET_DTS 0x02 /* enable DTS Digital Output */ |
477 | #define AUDIOPHILE_SET_24B 0x08 /* 24bits sample if set, 16bits otherwise */ | 501 | #define MAUDIO_SET_96K 0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */ |
478 | #define AUDIOPHILE_SET_DI 0x10 /* if set, enable Digital Input */ | 502 | #define MAUDIO_SET_24B 0x08 /* 24bits sample if set, 16bits otherwise */ |
479 | #define AUDIOPHILE_SET_MASK 0x1F /* bit mask for setup value */ | 503 | #define MAUDIO_SET_DI 0x10 /* enable Digital Input */ |
480 | #define AUDIOPHILE_SET_24B_48K_DI 0x19 /* value for 24bits+48KHz+Digital Input */ | 504 | #define MAUDIO_SET_MASK 0x1f /* bit mask for setup value */ |
481 | #define AUDIOPHILE_SET_24B_48K_NOTDI 0x09 /* value for 24bits+48KHz+No Digital Input */ | 505 | #define MAUDIO_SET_24B_48K_DI 0x19 /* 24bits+48KHz+Digital Input */ |
482 | #define AUDIOPHILE_SET_16B_48K_DI 0x11 /* value for 16bits+48KHz+Digital Input */ | 506 | #define MAUDIO_SET_24B_48K_NOTDI 0x09 /* 24bits+48KHz+No Digital Input */ |
483 | #define AUDIOPHILE_SET_16B_48K_NOTDI 0x01 /* value for 16bits+48KHz+No Digital Input */ | 507 | #define MAUDIO_SET_16B_48K_DI 0x11 /* 16bits+48KHz+Digital Input */ |
508 | #define MAUDIO_SET_16B_48K_NOTDI 0x01 /* 16bits+48KHz+No Digital Input */ | ||
509 | |||
510 | static int quattro_skip_setting_quirk(struct snd_usb_audio *chip, | ||
511 | int iface, int altno) | ||
512 | { | ||
513 | /* Reset ALL ifaces to 0 altsetting. | ||
514 | * Call it for every possible altsetting of every interface. | ||
515 | */ | ||
516 | usb_set_interface(chip->dev, iface, 0); | ||
517 | if (chip->setup & MAUDIO_SET) { | ||
518 | if (chip->setup & MAUDIO_SET_COMPATIBLE) { | ||
519 | if (iface != 1 && iface != 2) | ||
520 | return 1; /* skip all interfaces but 1 and 2 */ | ||
521 | } else { | ||
522 | unsigned int mask; | ||
523 | if (iface == 1 || iface == 2) | ||
524 | return 1; /* skip interfaces 1 and 2 */ | ||
525 | if ((chip->setup & MAUDIO_SET_96K) && altno != 1) | ||
526 | return 1; /* skip this altsetting */ | ||
527 | mask = chip->setup & MAUDIO_SET_MASK; | ||
528 | if (mask == MAUDIO_SET_24B_48K_DI && altno != 2) | ||
529 | return 1; /* skip this altsetting */ | ||
530 | if (mask == MAUDIO_SET_24B_48K_NOTDI && altno != 3) | ||
531 | return 1; /* skip this altsetting */ | ||
532 | if (mask == MAUDIO_SET_16B_48K_NOTDI && altno != 4) | ||
533 | return 1; /* skip this altsetting */ | ||
534 | } | ||
535 | } | ||
536 | snd_printdd(KERN_INFO | ||
537 | "using altsetting %d for interface %d config %d\n", | ||
538 | altno, iface, chip->setup); | ||
539 | return 0; /* keep this altsetting */ | ||
540 | } | ||
484 | 541 | ||
485 | static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip, | 542 | static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip, |
486 | int iface, | 543 | int iface, |
@@ -491,30 +548,65 @@ static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip, | |||
491 | */ | 548 | */ |
492 | usb_set_interface(chip->dev, iface, 0); | 549 | usb_set_interface(chip->dev, iface, 0); |
493 | 550 | ||
494 | if (chip->setup & AUDIOPHILE_SET) { | 551 | if (chip->setup & MAUDIO_SET) { |
495 | if ((chip->setup & AUDIOPHILE_SET_DTS) | 552 | unsigned int mask; |
496 | && altno != 6) | 553 | if ((chip->setup & MAUDIO_SET_DTS) && altno != 6) |
497 | return 1; /* skip this altsetting */ | 554 | return 1; /* skip this altsetting */ |
498 | if ((chip->setup & AUDIOPHILE_SET_96K) | 555 | if ((chip->setup & MAUDIO_SET_96K) && altno != 1) |
499 | && altno != 1) | ||
500 | return 1; /* skip this altsetting */ | 556 | return 1; /* skip this altsetting */ |
501 | if ((chip->setup & AUDIOPHILE_SET_MASK) == | 557 | mask = chip->setup & MAUDIO_SET_MASK; |
502 | AUDIOPHILE_SET_24B_48K_DI && altno != 2) | 558 | if (mask == MAUDIO_SET_24B_48K_DI && altno != 2) |
503 | return 1; /* skip this altsetting */ | 559 | return 1; /* skip this altsetting */ |
504 | if ((chip->setup & AUDIOPHILE_SET_MASK) == | 560 | if (mask == MAUDIO_SET_24B_48K_NOTDI && altno != 3) |
505 | AUDIOPHILE_SET_24B_48K_NOTDI && altno != 3) | ||
506 | return 1; /* skip this altsetting */ | 561 | return 1; /* skip this altsetting */ |
507 | if ((chip->setup & AUDIOPHILE_SET_MASK) == | 562 | if (mask == MAUDIO_SET_16B_48K_DI && altno != 4) |
508 | AUDIOPHILE_SET_16B_48K_DI && altno != 4) | ||
509 | return 1; /* skip this altsetting */ | 563 | return 1; /* skip this altsetting */ |
510 | if ((chip->setup & AUDIOPHILE_SET_MASK) == | 564 | if (mask == MAUDIO_SET_16B_48K_NOTDI && altno != 5) |
511 | AUDIOPHILE_SET_16B_48K_NOTDI && altno != 5) | ||
512 | return 1; /* skip this altsetting */ | 565 | return 1; /* skip this altsetting */ |
513 | } | 566 | } |
514 | 567 | ||
515 | return 0; /* keep this altsetting */ | 568 | return 0; /* keep this altsetting */ |
516 | } | 569 | } |
517 | 570 | ||
571 | |||
572 | static int fasttrackpro_skip_setting_quirk(struct snd_usb_audio *chip, | ||
573 | int iface, int altno) | ||
574 | { | ||
575 | /* Reset ALL ifaces to 0 altsetting. | ||
576 | * Call it for every possible altsetting of every interface. | ||
577 | */ | ||
578 | usb_set_interface(chip->dev, iface, 0); | ||
579 | |||
580 | /* possible configuration where both inputs and only one output is | ||
581 | *used is not supported by the current setup | ||
582 | */ | ||
583 | if (chip->setup & (MAUDIO_SET | MAUDIO_SET_24B)) { | ||
584 | if (chip->setup & MAUDIO_SET_96K) { | ||
585 | if (altno != 3 && altno != 6) | ||
586 | return 1; | ||
587 | } else if (chip->setup & MAUDIO_SET_DI) { | ||
588 | if (iface == 4) | ||
589 | return 1; /* no analog input */ | ||
590 | if (altno != 2 && altno != 5) | ||
591 | return 1; /* enable only altsets 2 and 5 */ | ||
592 | } else { | ||
593 | if (iface == 5) | ||
594 | return 1; /* disable digialt input */ | ||
595 | if (altno != 2 && altno != 5) | ||
596 | return 1; /* enalbe only altsets 2 and 5 */ | ||
597 | } | ||
598 | } else { | ||
599 | /* keep only 16-Bit mode */ | ||
600 | if (altno != 1) | ||
601 | return 1; | ||
602 | } | ||
603 | |||
604 | snd_printdd(KERN_INFO | ||
605 | "using altsetting %d for interface %d config %d\n", | ||
606 | altno, iface, chip->setup); | ||
607 | return 0; /* keep this altsetting */ | ||
608 | } | ||
609 | |||
518 | int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, | 610 | int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, |
519 | int iface, | 611 | int iface, |
520 | int altno) | 612 | int altno) |
@@ -522,6 +614,12 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, | |||
522 | /* audiophile usb: skip altsets incompatible with device_setup */ | 614 | /* audiophile usb: skip altsets incompatible with device_setup */ |
523 | if (chip->usb_id == USB_ID(0x0763, 0x2003)) | 615 | if (chip->usb_id == USB_ID(0x0763, 0x2003)) |
524 | return audiophile_skip_setting_quirk(chip, iface, altno); | 616 | return audiophile_skip_setting_quirk(chip, iface, altno); |
617 | /* quattro usb: skip altsets incompatible with device_setup */ | ||
618 | if (chip->usb_id == USB_ID(0x0763, 0x2001)) | ||
619 | return quattro_skip_setting_quirk(chip, iface, altno); | ||
620 | /* fasttrackpro usb: skip altsets incompatible with device_setup */ | ||
621 | if (chip->usb_id == USB_ID(0x0763, 0x2012)) | ||
622 | return fasttrackpro_skip_setting_quirk(chip, iface, altno); | ||
525 | 623 | ||
526 | return 0; | 624 | return 0; |
527 | } | 625 | } |
@@ -560,6 +658,8 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, | |||
560 | case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */ | 658 | case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */ |
561 | case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */ | 659 | case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */ |
562 | return snd_usb_nativeinstruments_boot_quirk(dev); | 660 | return snd_usb_nativeinstruments_boot_quirk(dev); |
661 | case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */ | ||
662 | return snd_usb_fasttrackpro_boot_quirk(dev); | ||
563 | } | 663 | } |
564 | 664 | ||
565 | return 0; | 665 | return 0; |
@@ -570,15 +670,24 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, | |||
570 | */ | 670 | */ |
571 | int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp) | 671 | int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp) |
572 | { | 672 | { |
673 | /* it depends on altsetting wether the device is big-endian or not */ | ||
573 | switch (chip->usb_id) { | 674 | switch (chip->usb_id) { |
574 | case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */ | 675 | case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */ |
575 | if (fp->endpoint & USB_DIR_IN) | 676 | if (fp->altsetting == 2 || fp->altsetting == 3 || |
677 | fp->altsetting == 5 || fp->altsetting == 6) | ||
576 | return 1; | 678 | return 1; |
577 | break; | 679 | break; |
578 | case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ | 680 | case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ |
579 | if (chip->setup == 0x00 || | 681 | if (chip->setup == 0x00 || |
580 | fp->altsetting==1 || fp->altsetting==2 || fp->altsetting==3) | 682 | fp->altsetting == 1 || fp->altsetting == 2 || |
683 | fp->altsetting == 3) | ||
684 | return 1; | ||
685 | break; | ||
686 | case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro */ | ||
687 | if (fp->altsetting == 2 || fp->altsetting == 3 || | ||
688 | fp->altsetting == 5 || fp->altsetting == 6) | ||
581 | return 1; | 689 | return 1; |
690 | break; | ||
582 | } | 691 | } |
583 | return 0; | 692 | return 0; |
584 | } | 693 | } |