diff options
Diffstat (limited to 'sound')
442 files changed, 12427 insertions, 4972 deletions
diff --git a/sound/aoa/soundbus/i2sbus/control.c b/sound/aoa/soundbus/i2sbus/control.c index 4dc9b49c02cf..f4495decc699 100644 --- a/sound/aoa/soundbus/i2sbus/control.c +++ b/sound/aoa/soundbus/i2sbus/control.c | |||
@@ -9,8 +9,8 @@ | |||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/io.h> | ||
12 | 13 | ||
13 | #include <asm/io.h> | ||
14 | #include <asm/prom.h> | 14 | #include <asm/prom.h> |
15 | #include <asm/macio.h> | 15 | #include <asm/macio.h> |
16 | #include <asm/pmac_feature.h> | 16 | #include <asm/pmac_feature.h> |
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index 4e2b4fbf2496..b9737fae656a 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c | |||
@@ -74,10 +74,9 @@ static void i2sbus_release_dev(struct device *dev) | |||
74 | int i; | 74 | int i; |
75 | 75 | ||
76 | i2sdev = container_of(dev, struct i2sbus_dev, sound.ofdev.dev); | 76 | i2sdev = container_of(dev, struct i2sbus_dev, sound.ofdev.dev); |
77 | 77 | iounmap(i2sdev->intfregs); | |
78 | if (i2sdev->intfregs) iounmap(i2sdev->intfregs); | 78 | iounmap(i2sdev->out.dbdma); |
79 | if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma); | 79 | iounmap(i2sdev->in.dbdma); |
80 | if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma); | ||
81 | for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) | 80 | for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) |
82 | release_and_free_resource(i2sdev->allocated_resource[i]); | 81 | release_and_free_resource(i2sdev->allocated_resource[i]); |
83 | free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring); | 82 | free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring); |
@@ -318,9 +317,9 @@ static int i2sbus_add_dev(struct macio_dev *macio, | |||
318 | free_irq(dev->interrupts[i], dev); | 317 | free_irq(dev->interrupts[i], dev); |
319 | free_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring); | 318 | free_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring); |
320 | free_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring); | 319 | free_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring); |
321 | if (dev->intfregs) iounmap(dev->intfregs); | 320 | iounmap(dev->intfregs); |
322 | if (dev->out.dbdma) iounmap(dev->out.dbdma); | 321 | iounmap(dev->out.dbdma); |
323 | if (dev->in.dbdma) iounmap(dev->in.dbdma); | 322 | iounmap(dev->in.dbdma); |
324 | for (i=0;i<3;i++) | 323 | for (i=0;i<3;i++) |
325 | release_and_free_resource(dev->allocated_resource[i]); | 324 | release_and_free_resource(dev->allocated_resource[i]); |
326 | mutex_destroy(&dev->lock); | 325 | mutex_destroy(&dev->lock); |
@@ -381,10 +380,8 @@ static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state) | |||
381 | 380 | ||
382 | list_for_each_entry(i2sdev, &control->list, item) { | 381 | list_for_each_entry(i2sdev, &control->list, item) { |
383 | /* Notify Alsa */ | 382 | /* Notify Alsa */ |
384 | if (i2sdev->sound.pcm) { | 383 | /* Suspend PCM streams */ |
385 | /* Suspend PCM streams */ | 384 | snd_pcm_suspend_all(i2sdev->sound.pcm); |
386 | snd_pcm_suspend_all(i2sdev->sound.pcm); | ||
387 | } | ||
388 | 385 | ||
389 | /* Notify codecs */ | 386 | /* Notify codecs */ |
390 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { | 387 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { |
diff --git a/sound/aoa/soundbus/i2sbus/pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c index 7b74a4ba75f8..053b09c79053 100644 --- a/sound/aoa/soundbus/i2sbus/pcm.c +++ b/sound/aoa/soundbus/i2sbus/pcm.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * GPL v2, can be found in COPYING. | 6 | * GPL v2, can be found in COPYING. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <asm/io.h> | 9 | #include <linux/io.h> |
10 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <sound/core.h> | 12 | #include <sound/core.h> |
@@ -968,7 +968,6 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, | |||
968 | printk(KERN_DEBUG "i2sbus: failed to create pcm\n"); | 968 | printk(KERN_DEBUG "i2sbus: failed to create pcm\n"); |
969 | goto out_put_ci_module; | 969 | goto out_put_ci_module; |
970 | } | 970 | } |
971 | dev->pcm->dev = &dev->ofdev.dev; | ||
972 | } | 971 | } |
973 | 972 | ||
974 | /* ALSA yet again sucks. | 973 | /* ALSA yet again sucks. |
@@ -988,6 +987,8 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, | |||
988 | goto out_put_ci_module; | 987 | goto out_put_ci_module; |
989 | snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, | 988 | snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, |
990 | &i2sbus_playback_ops); | 989 | &i2sbus_playback_ops); |
990 | dev->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].dev.parent = | ||
991 | &dev->ofdev.dev; | ||
991 | i2sdev->out.created = 1; | 992 | i2sdev->out.created = 1; |
992 | } | 993 | } |
993 | 994 | ||
@@ -1003,6 +1004,8 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, | |||
1003 | goto out_put_ci_module; | 1004 | goto out_put_ci_module; |
1004 | snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, | 1005 | snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, |
1005 | &i2sbus_record_ops); | 1006 | &i2sbus_record_ops); |
1007 | dev->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].dev.parent = | ||
1008 | &dev->ofdev.dev; | ||
1006 | i2sdev->in.created = 1; | 1009 | i2sdev->in.created = 1; |
1007 | } | 1010 | } |
1008 | 1011 | ||
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 0e83a73efb16..4140b1b95054 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c | |||
@@ -889,8 +889,8 @@ static int aaci_probe_ac97(struct aaci *aaci) | |||
889 | static void aaci_free_card(struct snd_card *card) | 889 | static void aaci_free_card(struct snd_card *card) |
890 | { | 890 | { |
891 | struct aaci *aaci = card->private_data; | 891 | struct aaci *aaci = card->private_data; |
892 | if (aaci->base) | 892 | |
893 | iounmap(aaci->base); | 893 | iounmap(aaci->base); |
894 | } | 894 | } |
895 | 895 | ||
896 | static struct aaci *aaci_init_card(struct amba_device *dev) | 896 | static struct aaci *aaci_init_card(struct amba_device *dev) |
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 4f6b14d704f3..cf4cedf2b420 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c | |||
@@ -22,6 +22,9 @@ | |||
22 | #include <linux/gpio.h> | 22 | #include <linux/gpio.h> |
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/of.h> | ||
26 | #include <linux/of_gpio.h> | ||
27 | #include <linux/of_device.h> | ||
25 | 28 | ||
26 | #include <sound/core.h> | 29 | #include <sound/core.h> |
27 | #include <sound/initval.h> | 30 | #include <sound/initval.h> |
@@ -34,10 +37,10 @@ | |||
34 | #include <linux/platform_data/dma-dw.h> | 37 | #include <linux/platform_data/dma-dw.h> |
35 | #include <linux/dma/dw.h> | 38 | #include <linux/dma/dw.h> |
36 | 39 | ||
40 | #ifdef CONFIG_AVR32 | ||
37 | #include <mach/cpu.h> | 41 | #include <mach/cpu.h> |
38 | 42 | #else | |
39 | #ifdef CONFIG_ARCH_AT91 | 43 | #define cpu_is_at32ap7000() 0 |
40 | #include <mach/hardware.h> | ||
41 | #endif | 44 | #endif |
42 | 45 | ||
43 | #include "ac97c.h" | 46 | #include "ac97c.h" |
@@ -902,6 +905,40 @@ static void atmel_ac97c_reset(struct atmel_ac97c *chip) | |||
902 | } | 905 | } |
903 | } | 906 | } |
904 | 907 | ||
908 | #ifdef CONFIG_OF | ||
909 | static const struct of_device_id atmel_ac97c_dt_ids[] = { | ||
910 | { .compatible = "atmel,at91sam9263-ac97c", }, | ||
911 | { } | ||
912 | }; | ||
913 | MODULE_DEVICE_TABLE(of, atmel_ac97c_dt_ids); | ||
914 | |||
915 | static struct ac97c_platform_data *atmel_ac97c_probe_dt(struct device *dev) | ||
916 | { | ||
917 | struct ac97c_platform_data *pdata; | ||
918 | struct device_node *node = dev->of_node; | ||
919 | const struct of_device_id *match; | ||
920 | |||
921 | if (!node) { | ||
922 | dev_err(dev, "Device does not have associated DT data\n"); | ||
923 | return ERR_PTR(-EINVAL); | ||
924 | } | ||
925 | |||
926 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
927 | if (!pdata) | ||
928 | return ERR_PTR(-ENOMEM); | ||
929 | |||
930 | pdata->reset_pin = of_get_named_gpio(dev->of_node, "ac97-gpios", 2); | ||
931 | |||
932 | return pdata; | ||
933 | } | ||
934 | #else | ||
935 | static struct ac97c_platform_data *atmel_ac97c_probe_dt(struct device *dev) | ||
936 | { | ||
937 | dev_err(dev, "no platform data defined\n"); | ||
938 | return ERR_PTR(-ENXIO); | ||
939 | } | ||
940 | #endif | ||
941 | |||
905 | static int atmel_ac97c_probe(struct platform_device *pdev) | 942 | static int atmel_ac97c_probe(struct platform_device *pdev) |
906 | { | 943 | { |
907 | struct snd_card *card; | 944 | struct snd_card *card; |
@@ -922,10 +959,11 @@ static int atmel_ac97c_probe(struct platform_device *pdev) | |||
922 | return -ENXIO; | 959 | return -ENXIO; |
923 | } | 960 | } |
924 | 961 | ||
925 | pdata = pdev->dev.platform_data; | 962 | pdata = dev_get_platdata(&pdev->dev); |
926 | if (!pdata) { | 963 | if (!pdata) { |
927 | dev_dbg(&pdev->dev, "no platform data\n"); | 964 | pdata = atmel_ac97c_probe_dt(&pdev->dev); |
928 | return -ENXIO; | 965 | if (IS_ERR(pdata)) |
966 | return PTR_ERR(pdata); | ||
929 | } | 967 | } |
930 | 968 | ||
931 | irq = platform_get_irq(pdev, 0); | 969 | irq = platform_get_irq(pdev, 0); |
@@ -1204,6 +1242,7 @@ static struct platform_driver atmel_ac97c_driver = { | |||
1204 | .driver = { | 1242 | .driver = { |
1205 | .name = "atmel_ac97c", | 1243 | .name = "atmel_ac97c", |
1206 | .pm = ATMEL_AC97C_PM_OPS, | 1244 | .pm = ATMEL_AC97C_PM_OPS, |
1245 | .of_match_table = of_match_ptr(atmel_ac97c_dt_ids), | ||
1207 | }, | 1246 | }, |
1208 | }; | 1247 | }; |
1209 | module_platform_driver(atmel_ac97c_driver); | 1248 | module_platform_driver(atmel_ac97c_driver); |
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 89028fab64fd..b123c42e7dc8 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c | |||
@@ -868,12 +868,12 @@ static int snd_compress_dev_register(struct snd_device *device) | |||
868 | return -EBADFD; | 868 | return -EBADFD; |
869 | compr = device->device_data; | 869 | compr = device->device_data; |
870 | 870 | ||
871 | sprintf(str, "comprC%iD%i", compr->card->number, compr->device); | ||
872 | pr_debug("reg %s for device %s, direction %d\n", str, compr->name, | 871 | pr_debug("reg %s for device %s, direction %d\n", str, compr->name, |
873 | compr->direction); | 872 | compr->direction); |
874 | /* register compressed device */ | 873 | /* register compressed device */ |
875 | ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card, | 874 | ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, |
876 | compr->device, &snd_compr_file_ops, compr, str); | 875 | compr->card, compr->device, |
876 | &snd_compr_file_ops, compr, &compr->dev); | ||
877 | if (ret < 0) { | 877 | if (ret < 0) { |
878 | pr_err("snd_register_device failed\n %d", ret); | 878 | pr_err("snd_register_device failed\n %d", ret); |
879 | return ret; | 879 | return ret; |
@@ -887,8 +887,16 @@ static int snd_compress_dev_disconnect(struct snd_device *device) | |||
887 | struct snd_compr *compr; | 887 | struct snd_compr *compr; |
888 | 888 | ||
889 | compr = device->device_data; | 889 | compr = device->device_data; |
890 | snd_unregister_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card, | 890 | snd_unregister_device(&compr->dev); |
891 | compr->device); | 891 | return 0; |
892 | } | ||
893 | |||
894 | static int snd_compress_dev_free(struct snd_device *device) | ||
895 | { | ||
896 | struct snd_compr *compr; | ||
897 | |||
898 | compr = device->device_data; | ||
899 | put_device(&compr->dev); | ||
892 | return 0; | 900 | return 0; |
893 | } | 901 | } |
894 | 902 | ||
@@ -903,7 +911,7 @@ int snd_compress_new(struct snd_card *card, int device, | |||
903 | int dirn, struct snd_compr *compr) | 911 | int dirn, struct snd_compr *compr) |
904 | { | 912 | { |
905 | static struct snd_device_ops ops = { | 913 | static struct snd_device_ops ops = { |
906 | .dev_free = NULL, | 914 | .dev_free = snd_compress_dev_free, |
907 | .dev_register = snd_compress_dev_register, | 915 | .dev_register = snd_compress_dev_register, |
908 | .dev_disconnect = snd_compress_dev_disconnect, | 916 | .dev_disconnect = snd_compress_dev_disconnect, |
909 | }; | 917 | }; |
@@ -911,6 +919,10 @@ int snd_compress_new(struct snd_card *card, int device, | |||
911 | compr->card = card; | 919 | compr->card = card; |
912 | compr->device = device; | 920 | compr->device = device; |
913 | compr->direction = dirn; | 921 | compr->direction = dirn; |
922 | |||
923 | snd_device_initialize(&compr->dev, card); | ||
924 | dev_set_name(&compr->dev, "comprC%iD%i", card->number, device); | ||
925 | |||
914 | return snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops); | 926 | return snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops); |
915 | } | 927 | } |
916 | EXPORT_SYMBOL_GPL(snd_compress_new); | 928 | EXPORT_SYMBOL_GPL(snd_compress_new); |
@@ -948,7 +960,7 @@ int snd_compress_register(struct snd_compr *device) | |||
948 | { | 960 | { |
949 | int retval; | 961 | int retval; |
950 | 962 | ||
951 | if (device->name == NULL || device->dev == NULL || device->ops == NULL) | 963 | if (device->name == NULL || device->ops == NULL) |
952 | return -EINVAL; | 964 | return -EINVAL; |
953 | 965 | ||
954 | pr_debug("Registering compressed device %s\n", device->name); | 966 | pr_debug("Registering compressed device %s\n", device->name); |
diff --git a/sound/core/control.c b/sound/core/control.c index bb96a467e88d..35324a8e83c8 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -50,7 +50,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file) | |||
50 | unsigned long flags; | 50 | unsigned long flags; |
51 | struct snd_card *card; | 51 | struct snd_card *card; |
52 | struct snd_ctl_file *ctl; | 52 | struct snd_ctl_file *ctl; |
53 | int err; | 53 | int i, err; |
54 | 54 | ||
55 | err = nonseekable_open(inode, file); | 55 | err = nonseekable_open(inode, file); |
56 | if (err < 0) | 56 | if (err < 0) |
@@ -79,8 +79,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file) | |||
79 | init_waitqueue_head(&ctl->change_sleep); | 79 | init_waitqueue_head(&ctl->change_sleep); |
80 | spin_lock_init(&ctl->read_lock); | 80 | spin_lock_init(&ctl->read_lock); |
81 | ctl->card = card; | 81 | ctl->card = card; |
82 | ctl->prefer_pcm_subdevice = -1; | 82 | for (i = 0; i < SND_CTL_SUBDEV_ITEMS; i++) |
83 | ctl->prefer_rawmidi_subdevice = -1; | 83 | ctl->preferred_subdevice[i] = -1; |
84 | ctl->pid = get_pid(task_pid(current)); | 84 | ctl->pid = get_pid(task_pid(current)); |
85 | file->private_data = ctl; | 85 | file->private_data = ctl; |
86 | write_lock_irqsave(&card->ctl_files_rwlock, flags); | 86 | write_lock_irqsave(&card->ctl_files_rwlock, flags); |
@@ -373,6 +373,7 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) | |||
373 | card->controls_count += kcontrol->count; | 373 | card->controls_count += kcontrol->count; |
374 | kcontrol->id.numid = card->last_numid + 1; | 374 | kcontrol->id.numid = card->last_numid + 1; |
375 | card->last_numid += kcontrol->count; | 375 | card->last_numid += kcontrol->count; |
376 | id = kcontrol->id; | ||
376 | count = kcontrol->count; | 377 | count = kcontrol->count; |
377 | up_write(&card->controls_rwsem); | 378 | up_write(&card->controls_rwsem); |
378 | for (idx = 0; idx < count; idx++, id.index++, id.numid++) | 379 | for (idx = 0; idx < count; idx++, id.index++, id.numid++) |
@@ -439,6 +440,7 @@ add: | |||
439 | card->controls_count += kcontrol->count; | 440 | card->controls_count += kcontrol->count; |
440 | kcontrol->id.numid = card->last_numid + 1; | 441 | kcontrol->id.numid = card->last_numid + 1; |
441 | card->last_numid += kcontrol->count; | 442 | card->last_numid += kcontrol->count; |
443 | id = kcontrol->id; | ||
442 | count = kcontrol->count; | 444 | count = kcontrol->count; |
443 | up_write(&card->controls_rwsem); | 445 | up_write(&card->controls_rwsem); |
444 | for (idx = 0; idx < count; idx++, id.index++, id.numid++) | 446 | for (idx = 0; idx < count; idx++, id.index++, id.numid++) |
@@ -1607,6 +1609,27 @@ static int snd_ctl_fasync(int fd, struct file * file, int on) | |||
1607 | return fasync_helper(fd, file, on, &ctl->fasync); | 1609 | return fasync_helper(fd, file, on, &ctl->fasync); |
1608 | } | 1610 | } |
1609 | 1611 | ||
1612 | /* return the preferred subdevice number if already assigned; | ||
1613 | * otherwise return -1 | ||
1614 | */ | ||
1615 | int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type) | ||
1616 | { | ||
1617 | struct snd_ctl_file *kctl; | ||
1618 | int subdevice = -1; | ||
1619 | |||
1620 | read_lock(&card->ctl_files_rwlock); | ||
1621 | list_for_each_entry(kctl, &card->ctl_files, list) { | ||
1622 | if (kctl->pid == task_pid(current)) { | ||
1623 | subdevice = kctl->preferred_subdevice[type]; | ||
1624 | if (subdevice != -1) | ||
1625 | break; | ||
1626 | } | ||
1627 | } | ||
1628 | read_unlock(&card->ctl_files_rwlock); | ||
1629 | return subdevice; | ||
1630 | } | ||
1631 | EXPORT_SYMBOL_GPL(snd_ctl_get_preferred_subdevice); | ||
1632 | |||
1610 | /* | 1633 | /* |
1611 | * ioctl32 compat | 1634 | * ioctl32 compat |
1612 | */ | 1635 | */ |
@@ -1639,19 +1662,9 @@ static const struct file_operations snd_ctl_f_ops = | |||
1639 | static int snd_ctl_dev_register(struct snd_device *device) | 1662 | static int snd_ctl_dev_register(struct snd_device *device) |
1640 | { | 1663 | { |
1641 | struct snd_card *card = device->device_data; | 1664 | struct snd_card *card = device->device_data; |
1642 | int err, cardnum; | ||
1643 | char name[16]; | ||
1644 | 1665 | ||
1645 | if (snd_BUG_ON(!card)) | 1666 | return snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1, |
1646 | return -ENXIO; | 1667 | &snd_ctl_f_ops, card, &card->ctl_dev); |
1647 | cardnum = card->number; | ||
1648 | if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS)) | ||
1649 | return -ENXIO; | ||
1650 | sprintf(name, "controlC%i", cardnum); | ||
1651 | if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1, | ||
1652 | &snd_ctl_f_ops, card, name)) < 0) | ||
1653 | return err; | ||
1654 | return 0; | ||
1655 | } | 1668 | } |
1656 | 1669 | ||
1657 | /* | 1670 | /* |
@@ -1661,13 +1674,6 @@ static int snd_ctl_dev_disconnect(struct snd_device *device) | |||
1661 | { | 1674 | { |
1662 | struct snd_card *card = device->device_data; | 1675 | struct snd_card *card = device->device_data; |
1663 | struct snd_ctl_file *ctl; | 1676 | struct snd_ctl_file *ctl; |
1664 | int err, cardnum; | ||
1665 | |||
1666 | if (snd_BUG_ON(!card)) | ||
1667 | return -ENXIO; | ||
1668 | cardnum = card->number; | ||
1669 | if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS)) | ||
1670 | return -ENXIO; | ||
1671 | 1677 | ||
1672 | read_lock(&card->ctl_files_rwlock); | 1678 | read_lock(&card->ctl_files_rwlock); |
1673 | list_for_each_entry(ctl, &card->ctl_files, list) { | 1679 | list_for_each_entry(ctl, &card->ctl_files, list) { |
@@ -1676,10 +1682,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device) | |||
1676 | } | 1682 | } |
1677 | read_unlock(&card->ctl_files_rwlock); | 1683 | read_unlock(&card->ctl_files_rwlock); |
1678 | 1684 | ||
1679 | if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, | 1685 | return snd_unregister_device(&card->ctl_dev); |
1680 | card, -1)) < 0) | ||
1681 | return err; | ||
1682 | return 0; | ||
1683 | } | 1686 | } |
1684 | 1687 | ||
1685 | /* | 1688 | /* |
@@ -1696,6 +1699,7 @@ static int snd_ctl_dev_free(struct snd_device *device) | |||
1696 | snd_ctl_remove(card, control); | 1699 | snd_ctl_remove(card, control); |
1697 | } | 1700 | } |
1698 | up_write(&card->controls_rwsem); | 1701 | up_write(&card->controls_rwsem); |
1702 | put_device(&card->ctl_dev); | ||
1699 | return 0; | 1703 | return 0; |
1700 | } | 1704 | } |
1701 | 1705 | ||
@@ -1710,10 +1714,20 @@ int snd_ctl_create(struct snd_card *card) | |||
1710 | .dev_register = snd_ctl_dev_register, | 1714 | .dev_register = snd_ctl_dev_register, |
1711 | .dev_disconnect = snd_ctl_dev_disconnect, | 1715 | .dev_disconnect = snd_ctl_dev_disconnect, |
1712 | }; | 1716 | }; |
1717 | int err; | ||
1713 | 1718 | ||
1714 | if (snd_BUG_ON(!card)) | 1719 | if (snd_BUG_ON(!card)) |
1715 | return -ENXIO; | 1720 | return -ENXIO; |
1716 | return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); | 1721 | if (snd_BUG_ON(card->number < 0 || card->number >= SNDRV_CARDS)) |
1722 | return -ENXIO; | ||
1723 | |||
1724 | snd_device_initialize(&card->ctl_dev, card); | ||
1725 | dev_set_name(&card->ctl_dev, "controlC%d", card->number); | ||
1726 | |||
1727 | err = snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); | ||
1728 | if (err < 0) | ||
1729 | put_device(&card->ctl_dev); | ||
1730 | return err; | ||
1717 | } | 1731 | } |
1718 | 1732 | ||
1719 | /* | 1733 | /* |
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 69459e5f712e..84244a5143cf 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c | |||
@@ -38,7 +38,6 @@ MODULE_LICENSE("GPL"); | |||
38 | static LIST_HEAD(snd_hwdep_devices); | 38 | static LIST_HEAD(snd_hwdep_devices); |
39 | static DEFINE_MUTEX(register_mutex); | 39 | static DEFINE_MUTEX(register_mutex); |
40 | 40 | ||
41 | static int snd_hwdep_free(struct snd_hwdep *hwdep); | ||
42 | static int snd_hwdep_dev_free(struct snd_device *device); | 41 | static int snd_hwdep_dev_free(struct snd_device *device); |
43 | static int snd_hwdep_dev_register(struct snd_device *device); | 42 | static int snd_hwdep_dev_register(struct snd_device *device); |
44 | static int snd_hwdep_dev_disconnect(struct snd_device *device); | 43 | static int snd_hwdep_dev_disconnect(struct snd_device *device); |
@@ -345,6 +344,11 @@ static const struct file_operations snd_hwdep_f_ops = | |||
345 | .mmap = snd_hwdep_mmap, | 344 | .mmap = snd_hwdep_mmap, |
346 | }; | 345 | }; |
347 | 346 | ||
347 | static void release_hwdep_device(struct device *dev) | ||
348 | { | ||
349 | kfree(container_of(dev, struct snd_hwdep, dev)); | ||
350 | } | ||
351 | |||
348 | /** | 352 | /** |
349 | * snd_hwdep_new - create a new hwdep instance | 353 | * snd_hwdep_new - create a new hwdep instance |
350 | * @card: the card instance | 354 | * @card: the card instance |
@@ -378,48 +382,49 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, | |||
378 | dev_err(card->dev, "hwdep: cannot allocate\n"); | 382 | dev_err(card->dev, "hwdep: cannot allocate\n"); |
379 | return -ENOMEM; | 383 | return -ENOMEM; |
380 | } | 384 | } |
385 | |||
386 | init_waitqueue_head(&hwdep->open_wait); | ||
387 | mutex_init(&hwdep->open_mutex); | ||
381 | hwdep->card = card; | 388 | hwdep->card = card; |
382 | hwdep->device = device; | 389 | hwdep->device = device; |
383 | if (id) | 390 | if (id) |
384 | strlcpy(hwdep->id, id, sizeof(hwdep->id)); | 391 | strlcpy(hwdep->id, id, sizeof(hwdep->id)); |
392 | |||
393 | snd_device_initialize(&hwdep->dev, card); | ||
394 | hwdep->dev.release = release_hwdep_device; | ||
395 | dev_set_name(&hwdep->dev, "hwC%iD%i", card->number, device); | ||
385 | #ifdef CONFIG_SND_OSSEMUL | 396 | #ifdef CONFIG_SND_OSSEMUL |
386 | hwdep->oss_type = -1; | 397 | hwdep->oss_type = -1; |
387 | #endif | 398 | #endif |
388 | if ((err = snd_device_new(card, SNDRV_DEV_HWDEP, hwdep, &ops)) < 0) { | 399 | |
389 | snd_hwdep_free(hwdep); | 400 | err = snd_device_new(card, SNDRV_DEV_HWDEP, hwdep, &ops); |
401 | if (err < 0) { | ||
402 | put_device(&hwdep->dev); | ||
390 | return err; | 403 | return err; |
391 | } | 404 | } |
392 | init_waitqueue_head(&hwdep->open_wait); | 405 | |
393 | mutex_init(&hwdep->open_mutex); | ||
394 | if (rhwdep) | 406 | if (rhwdep) |
395 | *rhwdep = hwdep; | 407 | *rhwdep = hwdep; |
396 | return 0; | 408 | return 0; |
397 | } | 409 | } |
398 | EXPORT_SYMBOL(snd_hwdep_new); | 410 | EXPORT_SYMBOL(snd_hwdep_new); |
399 | 411 | ||
400 | static int snd_hwdep_free(struct snd_hwdep *hwdep) | 412 | static int snd_hwdep_dev_free(struct snd_device *device) |
401 | { | 413 | { |
414 | struct snd_hwdep *hwdep = device->device_data; | ||
402 | if (!hwdep) | 415 | if (!hwdep) |
403 | return 0; | 416 | return 0; |
404 | if (hwdep->private_free) | 417 | if (hwdep->private_free) |
405 | hwdep->private_free(hwdep); | 418 | hwdep->private_free(hwdep); |
406 | kfree(hwdep); | 419 | put_device(&hwdep->dev); |
407 | return 0; | 420 | return 0; |
408 | } | 421 | } |
409 | 422 | ||
410 | static int snd_hwdep_dev_free(struct snd_device *device) | ||
411 | { | ||
412 | struct snd_hwdep *hwdep = device->device_data; | ||
413 | return snd_hwdep_free(hwdep); | ||
414 | } | ||
415 | |||
416 | static int snd_hwdep_dev_register(struct snd_device *device) | 423 | static int snd_hwdep_dev_register(struct snd_device *device) |
417 | { | 424 | { |
418 | struct snd_hwdep *hwdep = device->device_data; | 425 | struct snd_hwdep *hwdep = device->device_data; |
419 | struct snd_card *card = hwdep->card; | 426 | struct snd_card *card = hwdep->card; |
420 | struct device *dev; | ||
421 | int err; | 427 | int err; |
422 | char name[32]; | ||
423 | 428 | ||
424 | mutex_lock(®ister_mutex); | 429 | mutex_lock(®ister_mutex); |
425 | if (snd_hwdep_search(card, hwdep->device)) { | 430 | if (snd_hwdep_search(card, hwdep->device)) { |
@@ -427,53 +432,30 @@ static int snd_hwdep_dev_register(struct snd_device *device) | |||
427 | return -EBUSY; | 432 | return -EBUSY; |
428 | } | 433 | } |
429 | list_add_tail(&hwdep->list, &snd_hwdep_devices); | 434 | list_add_tail(&hwdep->list, &snd_hwdep_devices); |
430 | sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device); | 435 | err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP, |
431 | dev = hwdep->dev; | 436 | hwdep->card, hwdep->device, |
432 | if (!dev) | 437 | &snd_hwdep_f_ops, hwdep, &hwdep->dev); |
433 | dev = snd_card_get_device_link(hwdep->card); | ||
434 | err = snd_register_device_for_dev(SNDRV_DEVICE_TYPE_HWDEP, | ||
435 | hwdep->card, hwdep->device, | ||
436 | &snd_hwdep_f_ops, hwdep, name, dev); | ||
437 | if (err < 0) { | 438 | if (err < 0) { |
438 | dev_err(dev, | 439 | dev_err(&hwdep->dev, "unable to register\n"); |
439 | "unable to register hardware dependent device %i:%i\n", | ||
440 | card->number, hwdep->device); | ||
441 | list_del(&hwdep->list); | 440 | list_del(&hwdep->list); |
442 | mutex_unlock(®ister_mutex); | 441 | mutex_unlock(®ister_mutex); |
443 | return err; | 442 | return err; |
444 | } | 443 | } |
445 | 444 | ||
446 | if (hwdep->groups) { | ||
447 | struct device *d = snd_get_device(SNDRV_DEVICE_TYPE_HWDEP, | ||
448 | hwdep->card, hwdep->device); | ||
449 | if (d) { | ||
450 | if (hwdep->private_data) | ||
451 | dev_set_drvdata(d, hwdep->private_data); | ||
452 | err = sysfs_create_groups(&d->kobj, hwdep->groups); | ||
453 | if (err < 0) | ||
454 | dev_warn(dev, | ||
455 | "hwdep %d:%d: cannot create sysfs groups\n", | ||
456 | card->number, hwdep->device); | ||
457 | put_device(d); | ||
458 | } | ||
459 | } | ||
460 | |||
461 | #ifdef CONFIG_SND_OSSEMUL | 445 | #ifdef CONFIG_SND_OSSEMUL |
462 | hwdep->ossreg = 0; | 446 | hwdep->ossreg = 0; |
463 | if (hwdep->oss_type >= 0) { | 447 | if (hwdep->oss_type >= 0) { |
464 | if ((hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM) && (hwdep->device != 0)) { | 448 | if (hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM && |
465 | dev_warn(dev, | 449 | hwdep->device) |
450 | dev_warn(&hwdep->dev, | ||
466 | "only hwdep device 0 can be registered as OSS direct FM device!\n"); | 451 | "only hwdep device 0 can be registered as OSS direct FM device!\n"); |
467 | } else { | 452 | else if (snd_register_oss_device(hwdep->oss_type, |
468 | if (snd_register_oss_device(hwdep->oss_type, | 453 | card, hwdep->device, |
469 | card, hwdep->device, | 454 | &snd_hwdep_f_ops, hwdep) < 0) |
470 | &snd_hwdep_f_ops, hwdep) < 0) { | 455 | dev_warn(&hwdep->dev, |
471 | dev_err(dev, | 456 | "unable to register OSS compatibility device\n"); |
472 | "unable to register OSS compatibility device %i:%i\n", | 457 | else |
473 | card->number, hwdep->device); | 458 | hwdep->ossreg = 1; |
474 | } else | ||
475 | hwdep->ossreg = 1; | ||
476 | } | ||
477 | } | 459 | } |
478 | #endif | 460 | #endif |
479 | mutex_unlock(®ister_mutex); | 461 | mutex_unlock(®ister_mutex); |
@@ -497,7 +479,7 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) | |||
497 | if (hwdep->ossreg) | 479 | if (hwdep->ossreg) |
498 | snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); | 480 | snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); |
499 | #endif | 481 | #endif |
500 | snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); | 482 | snd_unregister_device(&hwdep->dev); |
501 | list_del_init(&hwdep->list); | 483 | list_del_init(&hwdep->list); |
502 | mutex_unlock(&hwdep->open_mutex); | 484 | mutex_unlock(&hwdep->open_mutex); |
503 | mutex_unlock(®ister_mutex); | 485 | mutex_unlock(®ister_mutex); |
diff --git a/sound/core/init.c b/sound/core/init.c index 074875d68c15..35419054821c 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -157,8 +157,31 @@ static int get_slot_from_bitmask(int mask, int (*check)(struct module *, int), | |||
157 | return mask; /* unchanged */ | 157 | return mask; /* unchanged */ |
158 | } | 158 | } |
159 | 159 | ||
160 | /* the default release callback set in snd_device_initialize() below; | ||
161 | * this is just NOP for now, as almost all jobs are already done in | ||
162 | * dev_free callback of snd_device chain instead. | ||
163 | */ | ||
164 | static void default_release(struct device *dev) | ||
165 | { | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * snd_device_initialize - Initialize struct device for sound devices | ||
170 | * @dev: device to initialize | ||
171 | * @card: card to assign, optional | ||
172 | */ | ||
173 | void snd_device_initialize(struct device *dev, struct snd_card *card) | ||
174 | { | ||
175 | device_initialize(dev); | ||
176 | if (card) | ||
177 | dev->parent = &card->card_dev; | ||
178 | dev->class = sound_class; | ||
179 | dev->release = default_release; | ||
180 | } | ||
181 | EXPORT_SYMBOL_GPL(snd_device_initialize); | ||
182 | |||
160 | static int snd_card_do_free(struct snd_card *card); | 183 | static int snd_card_do_free(struct snd_card *card); |
161 | static const struct attribute_group *card_dev_attr_groups[]; | 184 | static const struct attribute_group card_dev_attr_group; |
162 | 185 | ||
163 | static void release_card_device(struct device *dev) | 186 | static void release_card_device(struct device *dev) |
164 | { | 187 | { |
@@ -246,7 +269,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid, | |||
246 | card->card_dev.parent = parent; | 269 | card->card_dev.parent = parent; |
247 | card->card_dev.class = sound_class; | 270 | card->card_dev.class = sound_class; |
248 | card->card_dev.release = release_card_device; | 271 | card->card_dev.release = release_card_device; |
249 | card->card_dev.groups = card_dev_attr_groups; | 272 | card->card_dev.groups = card->dev_groups; |
273 | card->dev_groups[0] = &card_dev_attr_group; | ||
250 | err = kobject_set_name(&card->card_dev.kobj, "card%d", idx); | 274 | err = kobject_set_name(&card->card_dev.kobj, "card%d", idx); |
251 | if (err < 0) | 275 | if (err < 0) |
252 | goto __error; | 276 | goto __error; |
@@ -677,14 +701,32 @@ static struct attribute *card_dev_attrs[] = { | |||
677 | NULL | 701 | NULL |
678 | }; | 702 | }; |
679 | 703 | ||
680 | static struct attribute_group card_dev_attr_group = { | 704 | static const struct attribute_group card_dev_attr_group = { |
681 | .attrs = card_dev_attrs, | 705 | .attrs = card_dev_attrs, |
682 | }; | 706 | }; |
683 | 707 | ||
684 | static const struct attribute_group *card_dev_attr_groups[] = { | 708 | /** |
685 | &card_dev_attr_group, | 709 | * snd_card_add_dev_attr - Append a new sysfs attribute group to card |
686 | NULL | 710 | * @card: card instance |
711 | * @group: attribute group to append | ||
712 | */ | ||
713 | int snd_card_add_dev_attr(struct snd_card *card, | ||
714 | const struct attribute_group *group) | ||
715 | { | ||
716 | int i; | ||
717 | |||
718 | /* loop for (arraysize-1) here to keep NULL at the last entry */ | ||
719 | for (i = 0; i < ARRAY_SIZE(card->dev_groups) - 1; i++) { | ||
720 | if (!card->dev_groups[i]) { | ||
721 | card->dev_groups[i] = group; | ||
722 | return 0; | ||
723 | } | ||
724 | } | ||
725 | |||
726 | dev_err(card->dev, "Too many groups assigned\n"); | ||
727 | return -ENOSPC; | ||
687 | }; | 728 | }; |
729 | EXPORT_SYMBOL_GPL(snd_card_add_dev_attr); | ||
688 | 730 | ||
689 | /** | 731 | /** |
690 | * snd_card_register - register the soundcard | 732 | * snd_card_register - register the soundcard |
diff --git a/sound/core/memory.c b/sound/core/memory.c index 36c0f1a2e189..4cd664efad77 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c | |||
@@ -21,8 +21,8 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/export.h> | 23 | #include <linux/export.h> |
24 | #include <asm/io.h> | 24 | #include <linux/io.h> |
25 | #include <asm/uaccess.h> | 25 | #include <linux/uaccess.h> |
26 | #include <sound/core.h> | 26 | #include <sound/core.h> |
27 | 27 | ||
28 | /** | 28 | /** |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index ada69d7a8d70..80423a4ccab6 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -719,7 +719,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, | |||
719 | 719 | ||
720 | oss_buffer_size = snd_pcm_plug_client_size(substream, | 720 | oss_buffer_size = snd_pcm_plug_client_size(substream, |
721 | snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; | 721 | snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; |
722 | oss_buffer_size = 1 << ld2(oss_buffer_size); | 722 | oss_buffer_size = rounddown_pow_of_two(oss_buffer_size); |
723 | if (atomic_read(&substream->mmap_count)) { | 723 | if (atomic_read(&substream->mmap_count)) { |
724 | if (oss_buffer_size > runtime->oss.mmap_bytes) | 724 | if (oss_buffer_size > runtime->oss.mmap_bytes) |
725 | oss_buffer_size = runtime->oss.mmap_bytes; | 725 | oss_buffer_size = runtime->oss.mmap_bytes; |
@@ -755,14 +755,14 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, | |||
755 | min_period_size = snd_pcm_plug_client_size(substream, | 755 | min_period_size = snd_pcm_plug_client_size(substream, |
756 | snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); | 756 | snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); |
757 | min_period_size *= oss_frame_size; | 757 | min_period_size *= oss_frame_size; |
758 | min_period_size = 1 << (ld2(min_period_size - 1) + 1); | 758 | min_period_size = roundup_pow_of_two(min_period_size); |
759 | if (oss_period_size < min_period_size) | 759 | if (oss_period_size < min_period_size) |
760 | oss_period_size = min_period_size; | 760 | oss_period_size = min_period_size; |
761 | 761 | ||
762 | max_period_size = snd_pcm_plug_client_size(substream, | 762 | max_period_size = snd_pcm_plug_client_size(substream, |
763 | snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); | 763 | snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); |
764 | max_period_size *= oss_frame_size; | 764 | max_period_size *= oss_frame_size; |
765 | max_period_size = 1 << ld2(max_period_size); | 765 | max_period_size = rounddown_pow_of_two(max_period_size); |
766 | if (oss_period_size > max_period_size) | 766 | if (oss_period_size > max_period_size) |
767 | oss_period_size = max_period_size; | 767 | oss_period_size = max_period_size; |
768 | 768 | ||
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index cfc56c806964..0345e53a340c 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -161,7 +161,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, | |||
161 | 161 | ||
162 | if (get_user(val, (int __user *)arg)) | 162 | if (get_user(val, (int __user *)arg)) |
163 | return -EFAULT; | 163 | return -EFAULT; |
164 | control->prefer_pcm_subdevice = val; | 164 | control->preferred_subdevice[SND_CTL_SUBDEV_PCM] = val; |
165 | return 0; | 165 | return 0; |
166 | } | 166 | } |
167 | } | 167 | } |
@@ -673,6 +673,8 @@ static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substrea | |||
673 | static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; } | 673 | static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; } |
674 | #endif /* CONFIG_SND_VERBOSE_PROCFS */ | 674 | #endif /* CONFIG_SND_VERBOSE_PROCFS */ |
675 | 675 | ||
676 | static const struct attribute_group *pcm_dev_attr_groups[]; | ||
677 | |||
676 | /** | 678 | /** |
677 | * snd_pcm_new_stream - create a new PCM stream | 679 | * snd_pcm_new_stream - create a new PCM stream |
678 | * @pcm: the pcm instance | 680 | * @pcm: the pcm instance |
@@ -698,7 +700,15 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) | |||
698 | pstr->stream = stream; | 700 | pstr->stream = stream; |
699 | pstr->pcm = pcm; | 701 | pstr->pcm = pcm; |
700 | pstr->substream_count = substream_count; | 702 | pstr->substream_count = substream_count; |
701 | if (substream_count > 0 && !pcm->internal) { | 703 | if (!substream_count) |
704 | return 0; | ||
705 | |||
706 | snd_device_initialize(&pstr->dev, pcm->card); | ||
707 | pstr->dev.groups = pcm_dev_attr_groups; | ||
708 | dev_set_name(&pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device, | ||
709 | stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c'); | ||
710 | |||
711 | if (!pcm->internal) { | ||
702 | err = snd_pcm_stream_proc_init(pstr); | 712 | err = snd_pcm_stream_proc_init(pstr); |
703 | if (err < 0) { | 713 | if (err < 0) { |
704 | pcm_err(pcm, "Error in snd_pcm_stream_proc_init\n"); | 714 | pcm_err(pcm, "Error in snd_pcm_stream_proc_init\n"); |
@@ -868,6 +878,8 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr) | |||
868 | kfree(setup); | 878 | kfree(setup); |
869 | } | 879 | } |
870 | #endif | 880 | #endif |
881 | if (pstr->substream_count) | ||
882 | put_device(&pstr->dev); | ||
871 | } | 883 | } |
872 | 884 | ||
873 | static int snd_pcm_free(struct snd_pcm *pcm) | 885 | static int snd_pcm_free(struct snd_pcm *pcm) |
@@ -901,9 +913,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
901 | struct snd_pcm_str * pstr; | 913 | struct snd_pcm_str * pstr; |
902 | struct snd_pcm_substream *substream; | 914 | struct snd_pcm_substream *substream; |
903 | struct snd_pcm_runtime *runtime; | 915 | struct snd_pcm_runtime *runtime; |
904 | struct snd_ctl_file *kctl; | ||
905 | struct snd_card *card; | 916 | struct snd_card *card; |
906 | int prefer_subdevice = -1; | 917 | int prefer_subdevice; |
907 | size_t size; | 918 | size_t size; |
908 | 919 | ||
909 | if (snd_BUG_ON(!pcm || !rsubstream)) | 920 | if (snd_BUG_ON(!pcm || !rsubstream)) |
@@ -914,15 +925,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
914 | return -ENODEV; | 925 | return -ENODEV; |
915 | 926 | ||
916 | card = pcm->card; | 927 | card = pcm->card; |
917 | read_lock(&card->ctl_files_rwlock); | 928 | prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM); |
918 | list_for_each_entry(kctl, &card->ctl_files, list) { | ||
919 | if (kctl->pid == task_pid(current)) { | ||
920 | prefer_subdevice = kctl->prefer_pcm_subdevice; | ||
921 | if (prefer_subdevice != -1) | ||
922 | break; | ||
923 | } | ||
924 | } | ||
925 | read_unlock(&card->ctl_files_rwlock); | ||
926 | 929 | ||
927 | switch (stream) { | 930 | switch (stream) { |
928 | case SNDRV_PCM_STREAM_PLAYBACK: | 931 | case SNDRV_PCM_STREAM_PLAYBACK: |
@@ -1078,9 +1081,7 @@ static int snd_pcm_dev_register(struct snd_device *device) | |||
1078 | int cidx, err; | 1081 | int cidx, err; |
1079 | struct snd_pcm_substream *substream; | 1082 | struct snd_pcm_substream *substream; |
1080 | struct snd_pcm_notify *notify; | 1083 | struct snd_pcm_notify *notify; |
1081 | char str[16]; | ||
1082 | struct snd_pcm *pcm; | 1084 | struct snd_pcm *pcm; |
1083 | struct device *dev; | ||
1084 | 1085 | ||
1085 | if (snd_BUG_ON(!device || !device->device_data)) | 1086 | if (snd_BUG_ON(!device || !device->device_data)) |
1086 | return -ENXIO; | 1087 | return -ENXIO; |
@@ -1097,42 +1098,22 @@ static int snd_pcm_dev_register(struct snd_device *device) | |||
1097 | continue; | 1098 | continue; |
1098 | switch (cidx) { | 1099 | switch (cidx) { |
1099 | case SNDRV_PCM_STREAM_PLAYBACK: | 1100 | case SNDRV_PCM_STREAM_PLAYBACK: |
1100 | sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device); | ||
1101 | devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK; | 1101 | devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK; |
1102 | break; | 1102 | break; |
1103 | case SNDRV_PCM_STREAM_CAPTURE: | 1103 | case SNDRV_PCM_STREAM_CAPTURE: |
1104 | sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device); | ||
1105 | devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE; | 1104 | devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE; |
1106 | break; | 1105 | break; |
1107 | } | 1106 | } |
1108 | /* device pointer to use, pcm->dev takes precedence if | ||
1109 | * it is assigned, otherwise fall back to card's device | ||
1110 | * if possible */ | ||
1111 | dev = pcm->dev; | ||
1112 | if (!dev) | ||
1113 | dev = snd_card_get_device_link(pcm->card); | ||
1114 | /* register pcm */ | 1107 | /* register pcm */ |
1115 | err = snd_register_device_for_dev(devtype, pcm->card, | 1108 | err = snd_register_device(devtype, pcm->card, pcm->device, |
1116 | pcm->device, | 1109 | &snd_pcm_f_ops[cidx], pcm, |
1117 | &snd_pcm_f_ops[cidx], | 1110 | &pcm->streams[cidx].dev); |
1118 | pcm, str, dev); | ||
1119 | if (err < 0) { | 1111 | if (err < 0) { |
1120 | list_del(&pcm->list); | 1112 | list_del(&pcm->list); |
1121 | mutex_unlock(®ister_mutex); | 1113 | mutex_unlock(®ister_mutex); |
1122 | return err; | 1114 | return err; |
1123 | } | 1115 | } |
1124 | 1116 | ||
1125 | dev = snd_get_device(devtype, pcm->card, pcm->device); | ||
1126 | if (dev) { | ||
1127 | err = sysfs_create_groups(&dev->kobj, | ||
1128 | pcm_dev_attr_groups); | ||
1129 | if (err < 0) | ||
1130 | dev_warn(dev, | ||
1131 | "pcm %d:%d: cannot create sysfs groups\n", | ||
1132 | pcm->card->number, pcm->device); | ||
1133 | put_device(dev); | ||
1134 | } | ||
1135 | |||
1136 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) | 1117 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) |
1137 | snd_pcm_timer_init(substream); | 1118 | snd_pcm_timer_init(substream); |
1138 | } | 1119 | } |
@@ -1149,7 +1130,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
1149 | struct snd_pcm *pcm = device->device_data; | 1130 | struct snd_pcm *pcm = device->device_data; |
1150 | struct snd_pcm_notify *notify; | 1131 | struct snd_pcm_notify *notify; |
1151 | struct snd_pcm_substream *substream; | 1132 | struct snd_pcm_substream *substream; |
1152 | int cidx, devtype; | 1133 | int cidx; |
1153 | 1134 | ||
1154 | mutex_lock(®ister_mutex); | 1135 | mutex_lock(®ister_mutex); |
1155 | if (list_empty(&pcm->list)) | 1136 | if (list_empty(&pcm->list)) |
@@ -1172,16 +1153,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
1172 | notify->n_disconnect(pcm); | 1153 | notify->n_disconnect(pcm); |
1173 | } | 1154 | } |
1174 | for (cidx = 0; cidx < 2; cidx++) { | 1155 | for (cidx = 0; cidx < 2; cidx++) { |
1175 | devtype = -1; | 1156 | snd_unregister_device(&pcm->streams[cidx].dev); |
1176 | switch (cidx) { | ||
1177 | case SNDRV_PCM_STREAM_PLAYBACK: | ||
1178 | devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK; | ||
1179 | break; | ||
1180 | case SNDRV_PCM_STREAM_CAPTURE: | ||
1181 | devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE; | ||
1182 | break; | ||
1183 | } | ||
1184 | snd_unregister_device(devtype, pcm->card, pcm->device); | ||
1185 | if (pcm->streams[cidx].chmap_kctl) { | 1157 | if (pcm->streams[cidx].chmap_kctl) { |
1186 | snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl); | 1158 | snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl); |
1187 | pcm->streams[cidx].chmap_kctl = NULL; | 1159 | pcm->streams[cidx].chmap_kctl = NULL; |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index ec9e7866177f..ffd656012ab8 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -1015,6 +1015,60 @@ int snd_interval_list(struct snd_interval *i, unsigned int count, | |||
1015 | 1015 | ||
1016 | EXPORT_SYMBOL(snd_interval_list); | 1016 | EXPORT_SYMBOL(snd_interval_list); |
1017 | 1017 | ||
1018 | /** | ||
1019 | * snd_interval_ranges - refine the interval value from the list of ranges | ||
1020 | * @i: the interval value to refine | ||
1021 | * @count: the number of elements in the list of ranges | ||
1022 | * @ranges: the ranges list | ||
1023 | * @mask: the bit-mask to evaluate | ||
1024 | * | ||
1025 | * Refines the interval value from the list of ranges. | ||
1026 | * When mask is non-zero, only the elements corresponding to bit 1 are | ||
1027 | * evaluated. | ||
1028 | * | ||
1029 | * Return: Positive if the value is changed, zero if it's not changed, or a | ||
1030 | * negative error code. | ||
1031 | */ | ||
1032 | int snd_interval_ranges(struct snd_interval *i, unsigned int count, | ||
1033 | const struct snd_interval *ranges, unsigned int mask) | ||
1034 | { | ||
1035 | unsigned int k; | ||
1036 | struct snd_interval range_union; | ||
1037 | struct snd_interval range; | ||
1038 | |||
1039 | if (!count) { | ||
1040 | snd_interval_none(i); | ||
1041 | return -EINVAL; | ||
1042 | } | ||
1043 | snd_interval_any(&range_union); | ||
1044 | range_union.min = UINT_MAX; | ||
1045 | range_union.max = 0; | ||
1046 | for (k = 0; k < count; k++) { | ||
1047 | if (mask && !(mask & (1 << k))) | ||
1048 | continue; | ||
1049 | snd_interval_copy(&range, &ranges[k]); | ||
1050 | if (snd_interval_refine(&range, i) < 0) | ||
1051 | continue; | ||
1052 | if (snd_interval_empty(&range)) | ||
1053 | continue; | ||
1054 | |||
1055 | if (range.min < range_union.min) { | ||
1056 | range_union.min = range.min; | ||
1057 | range_union.openmin = 1; | ||
1058 | } | ||
1059 | if (range.min == range_union.min && !range.openmin) | ||
1060 | range_union.openmin = 0; | ||
1061 | if (range.max > range_union.max) { | ||
1062 | range_union.max = range.max; | ||
1063 | range_union.openmax = 1; | ||
1064 | } | ||
1065 | if (range.max == range_union.max && !range.openmax) | ||
1066 | range_union.openmax = 0; | ||
1067 | } | ||
1068 | return snd_interval_refine(i, &range_union); | ||
1069 | } | ||
1070 | EXPORT_SYMBOL(snd_interval_ranges); | ||
1071 | |||
1018 | static int snd_interval_step(struct snd_interval *i, unsigned int step) | 1072 | static int snd_interval_step(struct snd_interval *i, unsigned int step) |
1019 | { | 1073 | { |
1020 | unsigned int n; | 1074 | unsigned int n; |
@@ -1221,6 +1275,37 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, | |||
1221 | 1275 | ||
1222 | EXPORT_SYMBOL(snd_pcm_hw_constraint_list); | 1276 | EXPORT_SYMBOL(snd_pcm_hw_constraint_list); |
1223 | 1277 | ||
1278 | static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params, | ||
1279 | struct snd_pcm_hw_rule *rule) | ||
1280 | { | ||
1281 | struct snd_pcm_hw_constraint_ranges *r = rule->private; | ||
1282 | return snd_interval_ranges(hw_param_interval(params, rule->var), | ||
1283 | r->count, r->ranges, r->mask); | ||
1284 | } | ||
1285 | |||
1286 | |||
1287 | /** | ||
1288 | * snd_pcm_hw_constraint_ranges - apply list of range constraints to a parameter | ||
1289 | * @runtime: PCM runtime instance | ||
1290 | * @cond: condition bits | ||
1291 | * @var: hw_params variable to apply the list of range constraints | ||
1292 | * @r: ranges | ||
1293 | * | ||
1294 | * Apply the list of range constraints to an interval parameter. | ||
1295 | * | ||
1296 | * Return: Zero if successful, or a negative error code on failure. | ||
1297 | */ | ||
1298 | int snd_pcm_hw_constraint_ranges(struct snd_pcm_runtime *runtime, | ||
1299 | unsigned int cond, | ||
1300 | snd_pcm_hw_param_t var, | ||
1301 | const struct snd_pcm_hw_constraint_ranges *r) | ||
1302 | { | ||
1303 | return snd_pcm_hw_rule_add(runtime, cond, var, | ||
1304 | snd_pcm_hw_rule_ranges, (void *)r, | ||
1305 | var, -1); | ||
1306 | } | ||
1307 | EXPORT_SYMBOL(snd_pcm_hw_constraint_ranges); | ||
1308 | |||
1224 | static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params, | 1309 | static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params, |
1225 | struct snd_pcm_hw_rule *rule) | 1310 | struct snd_pcm_hw_rule *rule) |
1226 | { | 1311 | { |
@@ -1299,8 +1384,14 @@ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, | |||
1299 | int width = l & 0xffff; | 1384 | int width = l & 0xffff; |
1300 | unsigned int msbits = l >> 16; | 1385 | unsigned int msbits = l >> 16; |
1301 | struct snd_interval *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); | 1386 | struct snd_interval *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); |
1302 | if (snd_interval_single(i) && snd_interval_value(i) == width) | 1387 | |
1303 | params->msbits = msbits; | 1388 | if (!snd_interval_single(i)) |
1389 | return 0; | ||
1390 | |||
1391 | if ((snd_interval_value(i) == width) || | ||
1392 | (width == 0 && snd_interval_value(i) > msbits)) | ||
1393 | params->msbits = min_not_zero(params->msbits, msbits); | ||
1394 | |||
1304 | return 0; | 1395 | return 0; |
1305 | } | 1396 | } |
1306 | 1397 | ||
@@ -1311,6 +1402,11 @@ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, | |||
1311 | * @width: sample bits width | 1402 | * @width: sample bits width |
1312 | * @msbits: msbits width | 1403 | * @msbits: msbits width |
1313 | * | 1404 | * |
1405 | * This constraint will set the number of most significant bits (msbits) if a | ||
1406 | * sample format with the specified width has been select. If width is set to 0 | ||
1407 | * the msbits will be set for any sample format with a width larger than the | ||
1408 | * specified msbits. | ||
1409 | * | ||
1314 | * Return: Zero if successful, or a negative error code on failure. | 1410 | * Return: Zero if successful, or a negative error code on failure. |
1315 | */ | 1411 | */ |
1316 | int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime, | 1412 | int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime, |
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index 54debc07f5cb..b45f6aa32264 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <asm/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/time.h> | 23 | #include <linux/time.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 095d9572ad2b..279e24f61305 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/time.h> | 26 | #include <linux/time.h> |
27 | #include <linux/pm_qos.h> | 27 | #include <linux/pm_qos.h> |
28 | #include <linux/aio.h> | 28 | #include <linux/aio.h> |
29 | #include <linux/io.h> | ||
29 | #include <linux/dma-mapping.h> | 30 | #include <linux/dma-mapping.h> |
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/control.h> | 32 | #include <sound/control.h> |
@@ -34,7 +35,6 @@ | |||
34 | #include <sound/pcm_params.h> | 35 | #include <sound/pcm_params.h> |
35 | #include <sound/timer.h> | 36 | #include <sound/timer.h> |
36 | #include <sound/minors.h> | 37 | #include <sound/minors.h> |
37 | #include <asm/io.h> | ||
38 | 38 | ||
39 | /* | 39 | /* |
40 | * Compatibility | 40 | * Compatibility |
@@ -420,7 +420,8 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, | |||
420 | 420 | ||
421 | hw = &substream->runtime->hw; | 421 | hw = &substream->runtime->hw; |
422 | if (!params->info) { | 422 | if (!params->info) { |
423 | params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES; | 423 | params->info = hw->info & ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES | |
424 | SNDRV_PCM_INFO_DRAIN_TRIGGER); | ||
424 | if (!hw_support_mmap(substream)) | 425 | if (!hw_support_mmap(substream)) |
425 | params->info &= ~(SNDRV_PCM_INFO_MMAP | | 426 | params->info &= ~(SNDRV_PCM_INFO_MMAP | |
426 | SNDRV_PCM_INFO_MMAP_VALID); | 427 | SNDRV_PCM_INFO_MMAP_VALID); |
@@ -719,8 +720,11 @@ int snd_pcm_status(struct snd_pcm_substream *substream, | |||
719 | runtime->status->audio_tstamp; | 720 | runtime->status->audio_tstamp; |
720 | goto _tstamp_end; | 721 | goto _tstamp_end; |
721 | } | 722 | } |
723 | } else { | ||
724 | /* get tstamp only in fallback mode and only if enabled */ | ||
725 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) | ||
726 | snd_pcm_gettime(runtime, &status->tstamp); | ||
722 | } | 727 | } |
723 | snd_pcm_gettime(runtime, &status->tstamp); | ||
724 | _tstamp_end: | 728 | _tstamp_end: |
725 | status->appl_ptr = runtime->control->appl_ptr; | 729 | status->appl_ptr = runtime->control->appl_ptr; |
726 | status->hw_ptr = runtime->status->hw_ptr; | 730 | status->hw_ptr = runtime->status->hw_ptr; |
@@ -806,7 +810,8 @@ static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream) | |||
806 | if (runtime->trigger_master == NULL) | 810 | if (runtime->trigger_master == NULL) |
807 | return; | 811 | return; |
808 | if (runtime->trigger_master == substream) { | 812 | if (runtime->trigger_master == substream) { |
809 | snd_pcm_gettime(runtime, &runtime->trigger_tstamp); | 813 | if (!runtime->trigger_tstamp_latched) |
814 | snd_pcm_gettime(runtime, &runtime->trigger_tstamp); | ||
810 | } else { | 815 | } else { |
811 | snd_pcm_trigger_tstamp(runtime->trigger_master); | 816 | snd_pcm_trigger_tstamp(runtime->trigger_master); |
812 | runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp; | 817 | runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp; |
@@ -975,6 +980,7 @@ static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state) | |||
975 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | 980 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
976 | !snd_pcm_playback_data(substream)) | 981 | !snd_pcm_playback_data(substream)) |
977 | return -EPIPE; | 982 | return -EPIPE; |
983 | runtime->trigger_tstamp_latched = false; | ||
978 | runtime->trigger_master = substream; | 984 | runtime->trigger_master = substream; |
979 | return 0; | 985 | return 0; |
980 | } | 986 | } |
@@ -1546,6 +1552,8 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state) | |||
1546 | if (! snd_pcm_playback_empty(substream)) { | 1552 | if (! snd_pcm_playback_empty(substream)) { |
1547 | snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING); | 1553 | snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING); |
1548 | snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING); | 1554 | snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING); |
1555 | } else { | ||
1556 | runtime->status->state = SNDRV_PCM_STATE_SETUP; | ||
1549 | } | 1557 | } |
1550 | break; | 1558 | break; |
1551 | case SNDRV_PCM_STATE_RUNNING: | 1559 | case SNDRV_PCM_STATE_RUNNING: |
@@ -1566,6 +1574,13 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state) | |||
1566 | snd_pcm_post_stop(substream, new_state); | 1574 | snd_pcm_post_stop(substream, new_state); |
1567 | } | 1575 | } |
1568 | } | 1576 | } |
1577 | |||
1578 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING && | ||
1579 | runtime->trigger_master == substream && | ||
1580 | (runtime->hw.info & SNDRV_PCM_INFO_DRAIN_TRIGGER)) | ||
1581 | return substream->ops->trigger(substream, | ||
1582 | SNDRV_PCM_TRIGGER_DRAIN); | ||
1583 | |||
1569 | return 0; | 1584 | return 0; |
1570 | } | 1585 | } |
1571 | 1586 | ||
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 6fc71a4c8a51..b5a748596fc4 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
@@ -57,11 +57,11 @@ static LIST_HEAD(snd_rawmidi_devices); | |||
57 | static DEFINE_MUTEX(register_mutex); | 57 | static DEFINE_MUTEX(register_mutex); |
58 | 58 | ||
59 | #define rmidi_err(rmidi, fmt, args...) \ | 59 | #define rmidi_err(rmidi, fmt, args...) \ |
60 | dev_err((rmidi)->card->dev, fmt, ##args) | 60 | dev_err(&(rmidi)->dev, fmt, ##args) |
61 | #define rmidi_warn(rmidi, fmt, args...) \ | 61 | #define rmidi_warn(rmidi, fmt, args...) \ |
62 | dev_warn((rmidi)->card->dev, fmt, ##args) | 62 | dev_warn(&(rmidi)->dev, fmt, ##args) |
63 | #define rmidi_dbg(rmidi, fmt, args...) \ | 63 | #define rmidi_dbg(rmidi, fmt, args...) \ |
64 | dev_dbg((rmidi)->card->dev, fmt, ##args) | 64 | dev_dbg(&(rmidi)->dev, fmt, ##args) |
65 | 65 | ||
66 | static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device) | 66 | static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device) |
67 | { | 67 | { |
@@ -369,7 +369,6 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) | |||
369 | struct snd_rawmidi *rmidi; | 369 | struct snd_rawmidi *rmidi; |
370 | struct snd_rawmidi_file *rawmidi_file = NULL; | 370 | struct snd_rawmidi_file *rawmidi_file = NULL; |
371 | wait_queue_t wait; | 371 | wait_queue_t wait; |
372 | struct snd_ctl_file *kctl; | ||
373 | 372 | ||
374 | if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) | 373 | if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) |
375 | return -EINVAL; /* invalid combination */ | 374 | return -EINVAL; /* invalid combination */ |
@@ -413,16 +412,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) | |||
413 | init_waitqueue_entry(&wait, current); | 412 | init_waitqueue_entry(&wait, current); |
414 | add_wait_queue(&rmidi->open_wait, &wait); | 413 | add_wait_queue(&rmidi->open_wait, &wait); |
415 | while (1) { | 414 | while (1) { |
416 | subdevice = -1; | 415 | subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_RAWMIDI); |
417 | read_lock(&card->ctl_files_rwlock); | ||
418 | list_for_each_entry(kctl, &card->ctl_files, list) { | ||
419 | if (kctl->pid == task_pid(current)) { | ||
420 | subdevice = kctl->prefer_rawmidi_subdevice; | ||
421 | if (subdevice != -1) | ||
422 | break; | ||
423 | } | ||
424 | } | ||
425 | read_unlock(&card->ctl_files_rwlock); | ||
426 | err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file); | 416 | err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file); |
427 | if (err >= 0) | 417 | if (err >= 0) |
428 | break; | 418 | break; |
@@ -862,7 +852,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, | |||
862 | 852 | ||
863 | if (get_user(val, (int __user *)argp)) | 853 | if (get_user(val, (int __user *)argp)) |
864 | return -EFAULT; | 854 | return -EFAULT; |
865 | control->prefer_rawmidi_subdevice = val; | 855 | control->preferred_subdevice[SND_CTL_SUBDEV_RAWMIDI] = val; |
866 | return 0; | 856 | return 0; |
867 | } | 857 | } |
868 | case SNDRV_CTL_IOCTL_RAWMIDI_INFO: | 858 | case SNDRV_CTL_IOCTL_RAWMIDI_INFO: |
@@ -1453,6 +1443,11 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi, | |||
1453 | return 0; | 1443 | return 0; |
1454 | } | 1444 | } |
1455 | 1445 | ||
1446 | static void release_rawmidi_device(struct device *dev) | ||
1447 | { | ||
1448 | kfree(container_of(dev, struct snd_rawmidi, dev)); | ||
1449 | } | ||
1450 | |||
1456 | /** | 1451 | /** |
1457 | * snd_rawmidi_new - create a rawmidi instance | 1452 | * snd_rawmidi_new - create a rawmidi instance |
1458 | * @card: the card instance | 1453 | * @card: the card instance |
@@ -1497,6 +1492,11 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, | |||
1497 | 1492 | ||
1498 | if (id != NULL) | 1493 | if (id != NULL) |
1499 | strlcpy(rmidi->id, id, sizeof(rmidi->id)); | 1494 | strlcpy(rmidi->id, id, sizeof(rmidi->id)); |
1495 | |||
1496 | snd_device_initialize(&rmidi->dev, card); | ||
1497 | rmidi->dev.release = release_rawmidi_device; | ||
1498 | dev_set_name(&rmidi->dev, "midiC%iD%i", card->number, device); | ||
1499 | |||
1500 | if ((err = snd_rawmidi_alloc_substreams(rmidi, | 1500 | if ((err = snd_rawmidi_alloc_substreams(rmidi, |
1501 | &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], | 1501 | &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], |
1502 | SNDRV_RAWMIDI_STREAM_INPUT, | 1502 | SNDRV_RAWMIDI_STREAM_INPUT, |
@@ -1548,7 +1548,7 @@ static int snd_rawmidi_free(struct snd_rawmidi *rmidi) | |||
1548 | snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); | 1548 | snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); |
1549 | if (rmidi->private_free) | 1549 | if (rmidi->private_free) |
1550 | rmidi->private_free(rmidi); | 1550 | rmidi->private_free(rmidi); |
1551 | kfree(rmidi); | 1551 | put_device(&rmidi->dev); |
1552 | return 0; | 1552 | return 0; |
1553 | } | 1553 | } |
1554 | 1554 | ||
@@ -1581,19 +1581,18 @@ static int snd_rawmidi_dev_register(struct snd_device *device) | |||
1581 | return -EBUSY; | 1581 | return -EBUSY; |
1582 | } | 1582 | } |
1583 | list_add_tail(&rmidi->list, &snd_rawmidi_devices); | 1583 | list_add_tail(&rmidi->list, &snd_rawmidi_devices); |
1584 | sprintf(name, "midiC%iD%i", rmidi->card->number, rmidi->device); | 1584 | err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, |
1585 | if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, | 1585 | rmidi->card, rmidi->device, |
1586 | rmidi->card, rmidi->device, | 1586 | &snd_rawmidi_f_ops, rmidi, &rmidi->dev); |
1587 | &snd_rawmidi_f_ops, rmidi, name)) < 0) { | 1587 | if (err < 0) { |
1588 | rmidi_err(rmidi, "unable to register rawmidi device %i:%i\n", | 1588 | rmidi_err(rmidi, "unable to register\n"); |
1589 | rmidi->card->number, rmidi->device); | ||
1590 | list_del(&rmidi->list); | 1589 | list_del(&rmidi->list); |
1591 | mutex_unlock(®ister_mutex); | 1590 | mutex_unlock(®ister_mutex); |
1592 | return err; | 1591 | return err; |
1593 | } | 1592 | } |
1594 | if (rmidi->ops && rmidi->ops->dev_register && | 1593 | if (rmidi->ops && rmidi->ops->dev_register && |
1595 | (err = rmidi->ops->dev_register(rmidi)) < 0) { | 1594 | (err = rmidi->ops->dev_register(rmidi)) < 0) { |
1596 | snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); | 1595 | snd_unregister_device(&rmidi->dev); |
1597 | list_del(&rmidi->list); | 1596 | list_del(&rmidi->list); |
1598 | mutex_unlock(®ister_mutex); | 1597 | mutex_unlock(®ister_mutex); |
1599 | return err; | 1598 | return err; |
@@ -1681,7 +1680,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) | |||
1681 | rmidi->ossreg = 0; | 1680 | rmidi->ossreg = 0; |
1682 | } | 1681 | } |
1683 | #endif /* CONFIG_SND_OSSEMUL */ | 1682 | #endif /* CONFIG_SND_OSSEMUL */ |
1684 | snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); | 1683 | snd_unregister_device(&rmidi->dev); |
1685 | mutex_unlock(&rmidi->open_mutex); | 1684 | mutex_unlock(&rmidi->open_mutex); |
1686 | mutex_unlock(®ister_mutex); | 1685 | mutex_unlock(®ister_mutex); |
1687 | return 0; | 1686 | return 0; |
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index 3a4569669efa..e79cc44b1394 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c | |||
@@ -237,8 +237,7 @@ snd_seq_oss_midi_check_exit_port(int client, int port) | |||
237 | spin_unlock_irqrestore(®ister_lock, flags); | 237 | spin_unlock_irqrestore(®ister_lock, flags); |
238 | snd_use_lock_free(&mdev->use_lock); | 238 | snd_use_lock_free(&mdev->use_lock); |
239 | snd_use_lock_sync(&mdev->use_lock); | 239 | snd_use_lock_sync(&mdev->use_lock); |
240 | if (mdev->coder) | 240 | snd_midi_event_free(mdev->coder); |
241 | snd_midi_event_free(mdev->coder); | ||
242 | kfree(mdev); | 241 | kfree(mdev); |
243 | } | 242 | } |
244 | spin_lock_irqsave(®ister_lock, flags); | 243 | spin_lock_irqsave(®ister_lock, flags); |
@@ -265,8 +264,7 @@ snd_seq_oss_midi_clear_all(void) | |||
265 | spin_lock_irqsave(®ister_lock, flags); | 264 | spin_lock_irqsave(®ister_lock, flags); |
266 | for (i = 0; i < max_midi_devs; i++) { | 265 | for (i = 0; i < max_midi_devs; i++) { |
267 | if ((mdev = midi_devs[i]) != NULL) { | 266 | if ((mdev = midi_devs[i]) != NULL) { |
268 | if (mdev->coder) | 267 | snd_midi_event_free(mdev->coder); |
269 | snd_midi_event_free(mdev->coder); | ||
270 | kfree(mdev); | 268 | kfree(mdev); |
271 | midi_devs[i] = NULL; | 269 | midi_devs[i] = NULL; |
272 | } | 270 | } |
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 225c73152ee9..48287651ac77 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c | |||
@@ -1133,7 +1133,7 @@ static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void __user | |||
1133 | /* fill the info fields */ | 1133 | /* fill the info fields */ |
1134 | info.queues = SNDRV_SEQ_MAX_QUEUES; | 1134 | info.queues = SNDRV_SEQ_MAX_QUEUES; |
1135 | info.clients = SNDRV_SEQ_MAX_CLIENTS; | 1135 | info.clients = SNDRV_SEQ_MAX_CLIENTS; |
1136 | info.ports = 256; /* fixed limit */ | 1136 | info.ports = SNDRV_SEQ_MAX_PORTS; |
1137 | info.channels = 256; /* fixed limit */ | 1137 | info.channels = 256; /* fixed limit */ |
1138 | info.cur_clients = client_usage.cur; | 1138 | info.cur_clients = client_usage.cur; |
1139 | info.cur_queues = snd_seq_queue_get_cur_queues(); | 1139 | info.cur_queues = snd_seq_queue_get_cur_queues(); |
@@ -1279,7 +1279,6 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, | |||
1279 | port->owner = callback->owner; | 1279 | port->owner = callback->owner; |
1280 | port->private_data = callback->private_data; | 1280 | port->private_data = callback->private_data; |
1281 | port->private_free = callback->private_free; | 1281 | port->private_free = callback->private_free; |
1282 | port->callback_all = callback->callback_all; | ||
1283 | port->event_input = callback->event_input; | 1282 | port->event_input = callback->event_input; |
1284 | port->c_src.open = callback->subscribe; | 1283 | port->c_src.open = callback->subscribe; |
1285 | port->c_src.close = callback->unsubscribe; | 1284 | port->c_src.close = callback->unsubscribe; |
@@ -2571,6 +2570,8 @@ static const struct file_operations snd_seq_f_ops = | |||
2571 | .compat_ioctl = snd_seq_ioctl_compat, | 2570 | .compat_ioctl = snd_seq_ioctl_compat, |
2572 | }; | 2571 | }; |
2573 | 2572 | ||
2573 | static struct device seq_dev; | ||
2574 | |||
2574 | /* | 2575 | /* |
2575 | * register sequencer device | 2576 | * register sequencer device |
2576 | */ | 2577 | */ |
@@ -2578,12 +2579,17 @@ int __init snd_sequencer_device_init(void) | |||
2578 | { | 2579 | { |
2579 | int err; | 2580 | int err; |
2580 | 2581 | ||
2582 | snd_device_initialize(&seq_dev, NULL); | ||
2583 | dev_set_name(&seq_dev, "seq"); | ||
2584 | |||
2581 | if (mutex_lock_interruptible(®ister_mutex)) | 2585 | if (mutex_lock_interruptible(®ister_mutex)) |
2582 | return -ERESTARTSYS; | 2586 | return -ERESTARTSYS; |
2583 | 2587 | ||
2584 | if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, | 2588 | err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, |
2585 | &snd_seq_f_ops, NULL, "seq")) < 0) { | 2589 | &snd_seq_f_ops, NULL, &seq_dev); |
2590 | if (err < 0) { | ||
2586 | mutex_unlock(®ister_mutex); | 2591 | mutex_unlock(®ister_mutex); |
2592 | put_device(&seq_dev); | ||
2587 | return err; | 2593 | return err; |
2588 | } | 2594 | } |
2589 | 2595 | ||
@@ -2599,5 +2605,6 @@ int __init snd_sequencer_device_init(void) | |||
2599 | */ | 2605 | */ |
2600 | void __exit snd_sequencer_device_done(void) | 2606 | void __exit snd_sequencer_device_done(void) |
2601 | { | 2607 | { |
2602 | snd_unregister_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0); | 2608 | snd_unregister_device(&seq_dev); |
2609 | put_device(&seq_dev); | ||
2603 | } | 2610 | } |
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index a1fd77af6059..68fec776da26 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c | |||
@@ -268,8 +268,7 @@ static void snd_seq_midisynth_delete(struct seq_midisynth *msynth) | |||
268 | snd_seq_event_port_detach(msynth->seq_client, msynth->seq_port); | 268 | snd_seq_event_port_detach(msynth->seq_client, msynth->seq_port); |
269 | } | 269 | } |
270 | 270 | ||
271 | if (msynth->parser) | 271 | snd_midi_event_free(msynth->parser); |
272 | snd_midi_event_free(msynth->parser); | ||
273 | } | 272 | } |
274 | 273 | ||
275 | /* register new midi synth port */ | 274 | /* register new midi synth port */ |
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index 9b6470cdcf24..7ba937399ac7 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c | |||
@@ -269,6 +269,9 @@ do_control(struct snd_midi_op *ops, void *drv, struct snd_midi_channel_set *chse | |||
269 | { | 269 | { |
270 | int i; | 270 | int i; |
271 | 271 | ||
272 | if (control >= ARRAY_SIZE(chan->control)) | ||
273 | return; | ||
274 | |||
272 | /* Switches */ | 275 | /* Switches */ |
273 | if ((control >=64 && control <=69) || (control >= 80 && control <= 83)) { | 276 | if ((control >=64 && control <=69) || (control >= 80 && control <= 83)) { |
274 | /* These are all switches; either off or on so set to 0 or 127 */ | 277 | /* These are all switches; either off or on so set to 0 or 127 */ |
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 794a341bf0e5..46ff593f618d 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c | |||
@@ -134,7 +134,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, | |||
134 | if (snd_BUG_ON(!client)) | 134 | if (snd_BUG_ON(!client)) |
135 | return NULL; | 135 | return NULL; |
136 | 136 | ||
137 | if (client->num_ports >= SNDRV_SEQ_MAX_PORTS - 1) { | 137 | if (client->num_ports >= SNDRV_SEQ_MAX_PORTS) { |
138 | pr_warn("ALSA: seq: too many ports for client %d\n", client->number); | 138 | pr_warn("ALSA: seq: too many ports for client %d\n", client->number); |
139 | return NULL; | 139 | return NULL; |
140 | } | 140 | } |
@@ -411,9 +411,6 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port, | |||
411 | * invoked. | 411 | * invoked. |
412 | * This feature is useful if these callbacks are associated with | 412 | * This feature is useful if these callbacks are associated with |
413 | * initialization or termination of devices (see seq_midi.c). | 413 | * initialization or termination of devices (see seq_midi.c). |
414 | * | ||
415 | * If callback_all option is set, the callback function is invoked | ||
416 | * at each connection/disconnection. | ||
417 | */ | 414 | */ |
418 | 415 | ||
419 | static int subscribe_port(struct snd_seq_client *client, | 416 | static int subscribe_port(struct snd_seq_client *client, |
@@ -427,7 +424,7 @@ static int subscribe_port(struct snd_seq_client *client, | |||
427 | if (!try_module_get(port->owner)) | 424 | if (!try_module_get(port->owner)) |
428 | return -EFAULT; | 425 | return -EFAULT; |
429 | grp->count++; | 426 | grp->count++; |
430 | if (grp->open && (port->callback_all || grp->count == 1)) { | 427 | if (grp->open && grp->count == 1) { |
431 | err = grp->open(port->private_data, info); | 428 | err = grp->open(port->private_data, info); |
432 | if (err < 0) { | 429 | if (err < 0) { |
433 | module_put(port->owner); | 430 | module_put(port->owner); |
@@ -452,7 +449,7 @@ static int unsubscribe_port(struct snd_seq_client *client, | |||
452 | if (! grp->count) | 449 | if (! grp->count) |
453 | return -EINVAL; | 450 | return -EINVAL; |
454 | grp->count--; | 451 | grp->count--; |
455 | if (grp->close && (port->callback_all || grp->count == 0)) | 452 | if (grp->close && grp->count == 0) |
456 | err = grp->close(port->private_data, info); | 453 | err = grp->close(port->private_data, info); |
457 | if (send_ack && client->type == USER_CLIENT) | 454 | if (send_ack && client->type == USER_CLIENT) |
458 | snd_seq_client_notify_subscription(port->addr.client, port->addr.port, | 455 | snd_seq_client_notify_subscription(port->addr.client, port->addr.port, |
diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h index 9d7117118ba4..26bd71f36c41 100644 --- a/sound/core/seq/seq_ports.h +++ b/sound/core/seq/seq_ports.h | |||
@@ -73,7 +73,6 @@ struct snd_seq_client_port { | |||
73 | int atomic, int hop); | 73 | int atomic, int hop); |
74 | void (*private_free)(void *private_data); | 74 | void (*private_free)(void *private_data); |
75 | void *private_data; | 75 | void *private_data; |
76 | unsigned int callback_all : 1; | ||
77 | unsigned int closing : 1; | 76 | unsigned int closing : 1; |
78 | unsigned int timestamping: 1; | 77 | unsigned int timestamping: 1; |
79 | unsigned int time_real: 1; | 78 | unsigned int time_real: 1; |
diff --git a/sound/core/sound.c b/sound/core/sound.c index f1333060bf1c..185cec01ee25 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c | |||
@@ -242,30 +242,30 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev) | |||
242 | #endif | 242 | #endif |
243 | 243 | ||
244 | /** | 244 | /** |
245 | * snd_register_device_for_dev - Register the ALSA device file for the card | 245 | * snd_register_device - Register the ALSA device file for the card |
246 | * @type: the device type, SNDRV_DEVICE_TYPE_XXX | 246 | * @type: the device type, SNDRV_DEVICE_TYPE_XXX |
247 | * @card: the card instance | 247 | * @card: the card instance |
248 | * @dev: the device index | 248 | * @dev: the device index |
249 | * @f_ops: the file operations | 249 | * @f_ops: the file operations |
250 | * @private_data: user pointer for f_ops->open() | 250 | * @private_data: user pointer for f_ops->open() |
251 | * @name: the device file name | 251 | * @device: the device to register |
252 | * @device: the &struct device to link this new device to | ||
253 | * | 252 | * |
254 | * Registers an ALSA device file for the given card. | 253 | * Registers an ALSA device file for the given card. |
255 | * The operators have to be set in reg parameter. | 254 | * The operators have to be set in reg parameter. |
256 | * | 255 | * |
257 | * Return: Zero if successful, or a negative error code on failure. | 256 | * Return: Zero if successful, or a negative error code on failure. |
258 | */ | 257 | */ |
259 | int snd_register_device_for_dev(int type, struct snd_card *card, int dev, | 258 | int snd_register_device(int type, struct snd_card *card, int dev, |
260 | const struct file_operations *f_ops, | 259 | const struct file_operations *f_ops, |
261 | void *private_data, | 260 | void *private_data, struct device *device) |
262 | const char *name, struct device *device) | ||
263 | { | 261 | { |
264 | int minor; | 262 | int minor; |
263 | int err = 0; | ||
265 | struct snd_minor *preg; | 264 | struct snd_minor *preg; |
266 | 265 | ||
267 | if (snd_BUG_ON(!name)) | 266 | if (snd_BUG_ON(!device)) |
268 | return -EINVAL; | 267 | return -EINVAL; |
268 | |||
269 | preg = kmalloc(sizeof *preg, GFP_KERNEL); | 269 | preg = kmalloc(sizeof *preg, GFP_KERNEL); |
270 | if (preg == NULL) | 270 | if (preg == NULL) |
271 | return -ENOMEM; | 271 | return -ENOMEM; |
@@ -284,102 +284,56 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev, | |||
284 | minor = -EBUSY; | 284 | minor = -EBUSY; |
285 | #endif | 285 | #endif |
286 | if (minor < 0) { | 286 | if (minor < 0) { |
287 | mutex_unlock(&sound_mutex); | 287 | err = minor; |
288 | kfree(preg); | 288 | goto error; |
289 | return minor; | ||
290 | } | ||
291 | snd_minors[minor] = preg; | ||
292 | preg->dev = device_create(sound_class, device, MKDEV(major, minor), | ||
293 | private_data, "%s", name); | ||
294 | if (IS_ERR(preg->dev)) { | ||
295 | snd_minors[minor] = NULL; | ||
296 | mutex_unlock(&sound_mutex); | ||
297 | minor = PTR_ERR(preg->dev); | ||
298 | kfree(preg); | ||
299 | return minor; | ||
300 | } | 289 | } |
301 | 290 | ||
302 | mutex_unlock(&sound_mutex); | 291 | preg->dev = device; |
303 | return 0; | 292 | device->devt = MKDEV(major, minor); |
304 | } | 293 | err = device_add(device); |
305 | 294 | if (err < 0) | |
306 | EXPORT_SYMBOL(snd_register_device_for_dev); | 295 | goto error; |
307 | |||
308 | /* find the matching minor record | ||
309 | * return the index of snd_minor, or -1 if not found | ||
310 | */ | ||
311 | static int find_snd_minor(int type, struct snd_card *card, int dev) | ||
312 | { | ||
313 | int cardnum, minor; | ||
314 | struct snd_minor *mptr; | ||
315 | 296 | ||
316 | cardnum = card ? card->number : -1; | 297 | snd_minors[minor] = preg; |
317 | for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) | 298 | error: |
318 | if ((mptr = snd_minors[minor]) != NULL && | 299 | mutex_unlock(&sound_mutex); |
319 | mptr->type == type && | 300 | if (err < 0) |
320 | mptr->card == cardnum && | 301 | kfree(preg); |
321 | mptr->device == dev) | 302 | return err; |
322 | return minor; | ||
323 | return -1; | ||
324 | } | 303 | } |
304 | EXPORT_SYMBOL(snd_register_device); | ||
325 | 305 | ||
326 | /** | 306 | /** |
327 | * snd_unregister_device - unregister the device on the given card | 307 | * snd_unregister_device - unregister the device on the given card |
328 | * @type: the device type, SNDRV_DEVICE_TYPE_XXX | 308 | * @dev: the device instance |
329 | * @card: the card instance | ||
330 | * @dev: the device index | ||
331 | * | 309 | * |
332 | * Unregisters the device file already registered via | 310 | * Unregisters the device file already registered via |
333 | * snd_register_device(). | 311 | * snd_register_device(). |
334 | * | 312 | * |
335 | * Return: Zero if successful, or a negative error code on failure. | 313 | * Return: Zero if successful, or a negative error code on failure. |
336 | */ | 314 | */ |
337 | int snd_unregister_device(int type, struct snd_card *card, int dev) | 315 | int snd_unregister_device(struct device *dev) |
338 | { | 316 | { |
339 | int minor; | 317 | int minor; |
318 | struct snd_minor *preg; | ||
340 | 319 | ||
341 | mutex_lock(&sound_mutex); | 320 | mutex_lock(&sound_mutex); |
342 | minor = find_snd_minor(type, card, dev); | 321 | for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) { |
343 | if (minor < 0) { | 322 | preg = snd_minors[minor]; |
344 | mutex_unlock(&sound_mutex); | 323 | if (preg && preg->dev == dev) { |
345 | return -EINVAL; | 324 | snd_minors[minor] = NULL; |
325 | device_del(dev); | ||
326 | kfree(preg); | ||
327 | break; | ||
328 | } | ||
346 | } | 329 | } |
347 | |||
348 | device_destroy(sound_class, MKDEV(major, minor)); | ||
349 | |||
350 | kfree(snd_minors[minor]); | ||
351 | snd_minors[minor] = NULL; | ||
352 | mutex_unlock(&sound_mutex); | 330 | mutex_unlock(&sound_mutex); |
331 | if (minor >= ARRAY_SIZE(snd_minors)) | ||
332 | return -ENOENT; | ||
353 | return 0; | 333 | return 0; |
354 | } | 334 | } |
355 | |||
356 | EXPORT_SYMBOL(snd_unregister_device); | 335 | EXPORT_SYMBOL(snd_unregister_device); |
357 | 336 | ||
358 | /** | ||
359 | * snd_get_device - get the assigned device to the given type and device number | ||
360 | * @type: the device type, SNDRV_DEVICE_TYPE_XXX | ||
361 | * @card:the card instance | ||
362 | * @dev: the device index | ||
363 | * | ||
364 | * The caller needs to release it via put_device() after using it. | ||
365 | */ | ||
366 | struct device *snd_get_device(int type, struct snd_card *card, int dev) | ||
367 | { | ||
368 | int minor; | ||
369 | struct device *d = NULL; | ||
370 | |||
371 | mutex_lock(&sound_mutex); | ||
372 | minor = find_snd_minor(type, card, dev); | ||
373 | if (minor >= 0) { | ||
374 | d = snd_minors[minor]->dev; | ||
375 | if (d) | ||
376 | get_device(d); | ||
377 | } | ||
378 | mutex_unlock(&sound_mutex); | ||
379 | return d; | ||
380 | } | ||
381 | EXPORT_SYMBOL(snd_get_device); | ||
382 | |||
383 | #ifdef CONFIG_PROC_FS | 337 | #ifdef CONFIG_PROC_FS |
384 | /* | 338 | /* |
385 | * INFO PART | 339 | * INFO PART |
diff --git a/sound/core/timer.c b/sound/core/timer.c index 777a45e08e53..490b489d713d 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -1030,9 +1030,7 @@ static int snd_timer_register_system(void) | |||
1030 | snd_timer_free(timer); | 1030 | snd_timer_free(timer); |
1031 | return -ENOMEM; | 1031 | return -ENOMEM; |
1032 | } | 1032 | } |
1033 | init_timer(&priv->tlist); | 1033 | setup_timer(&priv->tlist, snd_timer_s_function, (unsigned long) timer); |
1034 | priv->tlist.function = snd_timer_s_function; | ||
1035 | priv->tlist.data = (unsigned long) timer; | ||
1036 | timer->private_data = priv; | 1034 | timer->private_data = priv; |
1037 | timer->private_free = snd_timer_free_system; | 1035 | timer->private_free = snd_timer_free_system; |
1038 | return snd_timer_global_register(timer); | 1036 | return snd_timer_global_register(timer); |
@@ -1942,6 +1940,17 @@ static const struct file_operations snd_timer_f_ops = | |||
1942 | .fasync = snd_timer_user_fasync, | 1940 | .fasync = snd_timer_user_fasync, |
1943 | }; | 1941 | }; |
1944 | 1942 | ||
1943 | /* unregister the system timer */ | ||
1944 | static void snd_timer_free_all(void) | ||
1945 | { | ||
1946 | struct snd_timer *timer, *n; | ||
1947 | |||
1948 | list_for_each_entry_safe(timer, n, &snd_timer_list, device_list) | ||
1949 | snd_timer_free(timer); | ||
1950 | } | ||
1951 | |||
1952 | static struct device timer_dev; | ||
1953 | |||
1945 | /* | 1954 | /* |
1946 | * ENTRY functions | 1955 | * ENTRY functions |
1947 | */ | 1956 | */ |
@@ -1950,30 +1959,39 @@ static int __init alsa_timer_init(void) | |||
1950 | { | 1959 | { |
1951 | int err; | 1960 | int err; |
1952 | 1961 | ||
1962 | snd_device_initialize(&timer_dev, NULL); | ||
1963 | dev_set_name(&timer_dev, "timer"); | ||
1964 | |||
1953 | #ifdef SNDRV_OSS_INFO_DEV_TIMERS | 1965 | #ifdef SNDRV_OSS_INFO_DEV_TIMERS |
1954 | snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1, | 1966 | snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1, |
1955 | "system timer"); | 1967 | "system timer"); |
1956 | #endif | 1968 | #endif |
1957 | 1969 | ||
1958 | if ((err = snd_timer_register_system()) < 0) | 1970 | err = snd_timer_register_system(); |
1971 | if (err < 0) { | ||
1959 | pr_err("ALSA: unable to register system timer (%i)\n", err); | 1972 | pr_err("ALSA: unable to register system timer (%i)\n", err); |
1960 | if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0, | 1973 | put_device(&timer_dev); |
1961 | &snd_timer_f_ops, NULL, "timer")) < 0) | 1974 | return err; |
1975 | } | ||
1976 | |||
1977 | err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0, | ||
1978 | &snd_timer_f_ops, NULL, &timer_dev); | ||
1979 | if (err < 0) { | ||
1962 | pr_err("ALSA: unable to register timer device (%i)\n", err); | 1980 | pr_err("ALSA: unable to register timer device (%i)\n", err); |
1981 | snd_timer_free_all(); | ||
1982 | put_device(&timer_dev); | ||
1983 | return err; | ||
1984 | } | ||
1985 | |||
1963 | snd_timer_proc_init(); | 1986 | snd_timer_proc_init(); |
1964 | return 0; | 1987 | return 0; |
1965 | } | 1988 | } |
1966 | 1989 | ||
1967 | static void __exit alsa_timer_exit(void) | 1990 | static void __exit alsa_timer_exit(void) |
1968 | { | 1991 | { |
1969 | struct list_head *p, *n; | 1992 | snd_unregister_device(&timer_dev); |
1970 | 1993 | snd_timer_free_all(); | |
1971 | snd_unregister_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0); | 1994 | put_device(&timer_dev); |
1972 | /* unregister the system timer */ | ||
1973 | list_for_each_safe(p, n, &snd_timer_list) { | ||
1974 | struct snd_timer *timer = list_entry(p, struct snd_timer, device_list); | ||
1975 | snd_timer_free(timer); | ||
1976 | } | ||
1977 | snd_timer_proc_done(); | 1995 | snd_timer_proc_done(); |
1978 | #ifdef SNDRV_OSS_INFO_DEV_TIMERS | 1996 | #ifdef SNDRV_OSS_INFO_DEV_TIMERS |
1979 | snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1); | 1997 | snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1); |
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 7ea53399404d..7f9126efc1e5 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c | |||
@@ -181,8 +181,7 @@ static void loopback_timer_start(struct loopback_pcm *dpcm) | |||
181 | } | 181 | } |
182 | tick = dpcm->period_size_frac - dpcm->irq_pos; | 182 | tick = dpcm->period_size_frac - dpcm->irq_pos; |
183 | tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; | 183 | tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; |
184 | dpcm->timer.expires = jiffies + tick; | 184 | mod_timer(&dpcm->timer, jiffies + tick); |
185 | add_timer(&dpcm->timer); | ||
186 | } | 185 | } |
187 | 186 | ||
188 | /* call in cable->lock */ | 187 | /* call in cable->lock */ |
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 5d0dfb787cec..d11baaf0f0b4 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
@@ -245,9 +245,8 @@ struct dummy_systimer_pcm { | |||
245 | 245 | ||
246 | static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm) | 246 | static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm) |
247 | { | 247 | { |
248 | dpcm->timer.expires = jiffies + | 248 | mod_timer(&dpcm->timer, jiffies + |
249 | (dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate; | 249 | (dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate); |
250 | add_timer(&dpcm->timer); | ||
251 | } | 250 | } |
252 | 251 | ||
253 | static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm) | 252 | static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm) |
@@ -340,9 +339,8 @@ static int dummy_systimer_create(struct snd_pcm_substream *substream) | |||
340 | if (!dpcm) | 339 | if (!dpcm) |
341 | return -ENOMEM; | 340 | return -ENOMEM; |
342 | substream->runtime->private_data = dpcm; | 341 | substream->runtime->private_data = dpcm; |
343 | init_timer(&dpcm->timer); | 342 | setup_timer(&dpcm->timer, dummy_systimer_callback, |
344 | dpcm->timer.data = (unsigned long) dpcm; | 343 | (unsigned long) dpcm); |
345 | dpcm->timer.function = dummy_systimer_callback; | ||
346 | spin_lock_init(&dpcm->lock); | 344 | spin_lock_init(&dpcm->lock); |
347 | dpcm->substream = substream; | 345 | dpcm->substream = substream; |
348 | return 0; | 346 | return 0; |
diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c index bcca825a1c8d..bdcb5721393b 100644 --- a/sound/drivers/ml403-ac97cr.c +++ b/sound/drivers/ml403-ac97cr.c | |||
@@ -1094,8 +1094,7 @@ static int snd_ml403_ac97cr_free(struct snd_ml403_ac97cr *ml403_ac97cr) | |||
1094 | if (ml403_ac97cr->capture_irq >= 0) | 1094 | if (ml403_ac97cr->capture_irq >= 0) |
1095 | free_irq(ml403_ac97cr->capture_irq, ml403_ac97cr); | 1095 | free_irq(ml403_ac97cr->capture_irq, ml403_ac97cr); |
1096 | /* give back "port" */ | 1096 | /* give back "port" */ |
1097 | if (ml403_ac97cr->port != NULL) | 1097 | iounmap(ml403_ac97cr->port); |
1098 | iounmap(ml403_ac97cr->port); | ||
1099 | kfree(ml403_ac97cr); | 1098 | kfree(ml403_ac97cr); |
1100 | PDEBUG(INIT_INFO, "free(): (done)\n"); | 1099 | PDEBUG(INIT_INFO, "free(): (done)\n"); |
1101 | return 0; | 1100 | return 0; |
@@ -1238,14 +1237,11 @@ snd_ml403_ac97cr_mixer(struct snd_ml403_ac97cr *ml403_ac97cr) | |||
1238 | } | 1237 | } |
1239 | 1238 | ||
1240 | static int | 1239 | static int |
1241 | snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device, | 1240 | snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device) |
1242 | struct snd_pcm **rpcm) | ||
1243 | { | 1241 | { |
1244 | struct snd_pcm *pcm; | 1242 | struct snd_pcm *pcm; |
1245 | int err; | 1243 | int err; |
1246 | 1244 | ||
1247 | if (rpcm) | ||
1248 | *rpcm = NULL; | ||
1249 | err = snd_pcm_new(ml403_ac97cr->card, "ML403AC97CR/1", device, 1, 1, | 1245 | err = snd_pcm_new(ml403_ac97cr->card, "ML403AC97CR/1", device, 1, 1, |
1250 | &pcm); | 1246 | &pcm); |
1251 | if (err < 0) | 1247 | if (err < 0) |
@@ -1263,8 +1259,6 @@ snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device, | |||
1263 | snd_dma_continuous_data(GFP_KERNEL), | 1259 | snd_dma_continuous_data(GFP_KERNEL), |
1264 | 64 * 1024, | 1260 | 64 * 1024, |
1265 | 128 * 1024); | 1261 | 128 * 1024); |
1266 | if (rpcm) | ||
1267 | *rpcm = pcm; | ||
1268 | return 0; | 1262 | return 0; |
1269 | } | 1263 | } |
1270 | 1264 | ||
@@ -1298,7 +1292,7 @@ static int snd_ml403_ac97cr_probe(struct platform_device *pfdev) | |||
1298 | return err; | 1292 | return err; |
1299 | } | 1293 | } |
1300 | PDEBUG(INIT_INFO, "probe(): mixer done\n"); | 1294 | PDEBUG(INIT_INFO, "probe(): mixer done\n"); |
1301 | err = snd_ml403_ac97cr_pcm(ml403_ac97cr, 0, NULL); | 1295 | err = snd_ml403_ac97cr_pcm(ml403_ac97cr, 0); |
1302 | if (err < 0) { | 1296 | if (err < 0) { |
1303 | snd_card_free(card); | 1297 | snd_card_free(card); |
1304 | return err; | 1298 | return err; |
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index e3a90d043f03..776596b5ee05 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c | |||
@@ -28,7 +28,7 @@ | |||
28 | * | 28 | * |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <asm/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
@@ -176,8 +176,7 @@ static void snd_mpu401_uart_timer(unsigned long data) | |||
176 | 176 | ||
177 | spin_lock_irqsave(&mpu->timer_lock, flags); | 177 | spin_lock_irqsave(&mpu->timer_lock, flags); |
178 | /*mpu->mode |= MPU401_MODE_TIMER;*/ | 178 | /*mpu->mode |= MPU401_MODE_TIMER;*/ |
179 | mpu->timer.expires = 1 + jiffies; | 179 | mod_timer(&mpu->timer, 1 + jiffies); |
180 | add_timer(&mpu->timer); | ||
181 | spin_unlock_irqrestore(&mpu->timer_lock, flags); | 180 | spin_unlock_irqrestore(&mpu->timer_lock, flags); |
182 | if (mpu->rmidi) | 181 | if (mpu->rmidi) |
183 | _snd_mpu401_uart_interrupt(mpu); | 182 | _snd_mpu401_uart_interrupt(mpu); |
@@ -192,11 +191,9 @@ static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input) | |||
192 | 191 | ||
193 | spin_lock_irqsave (&mpu->timer_lock, flags); | 192 | spin_lock_irqsave (&mpu->timer_lock, flags); |
194 | if (mpu->timer_invoked == 0) { | 193 | if (mpu->timer_invoked == 0) { |
195 | init_timer(&mpu->timer); | 194 | setup_timer(&mpu->timer, snd_mpu401_uart_timer, |
196 | mpu->timer.data = (unsigned long)mpu; | 195 | (unsigned long)mpu); |
197 | mpu->timer.function = snd_mpu401_uart_timer; | 196 | mod_timer(&mpu->timer, 1 + jiffies); |
198 | mpu->timer.expires = 1 + jiffies; | ||
199 | add_timer(&mpu->timer); | ||
200 | } | 197 | } |
201 | mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : | 198 | mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : |
202 | MPU401_MODE_OUTPUT_TIMER; | 199 | MPU401_MODE_OUTPUT_TIMER; |
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 15769447688f..30e8a1d5bc87 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c | |||
@@ -414,8 +414,7 @@ static void snd_mtpav_output_timer(unsigned long data) | |||
414 | 414 | ||
415 | spin_lock_irqsave(&chip->spinlock, flags); | 415 | spin_lock_irqsave(&chip->spinlock, flags); |
416 | /* reprogram timer */ | 416 | /* reprogram timer */ |
417 | chip->timer.expires = 1 + jiffies; | 417 | mod_timer(&chip->timer, 1 + jiffies); |
418 | add_timer(&chip->timer); | ||
419 | /* process each port */ | 418 | /* process each port */ |
420 | for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) { | 419 | for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) { |
421 | struct mtpav_port *portp = &chip->ports[p]; | 420 | struct mtpav_port *portp = &chip->ports[p]; |
@@ -428,8 +427,7 @@ static void snd_mtpav_output_timer(unsigned long data) | |||
428 | /* spinlock held! */ | 427 | /* spinlock held! */ |
429 | static void snd_mtpav_add_output_timer(struct mtpav *chip) | 428 | static void snd_mtpav_add_output_timer(struct mtpav *chip) |
430 | { | 429 | { |
431 | chip->timer.expires = 1 + jiffies; | 430 | mod_timer(&chip->timer, 1 + jiffies); |
432 | add_timer(&chip->timer); | ||
433 | } | 431 | } |
434 | 432 | ||
435 | /* spinlock held! */ | 433 | /* spinlock held! */ |
@@ -704,15 +702,13 @@ static int snd_mtpav_probe(struct platform_device *dev) | |||
704 | 702 | ||
705 | mtp_card = card->private_data; | 703 | mtp_card = card->private_data; |
706 | spin_lock_init(&mtp_card->spinlock); | 704 | spin_lock_init(&mtp_card->spinlock); |
707 | init_timer(&mtp_card->timer); | ||
708 | mtp_card->card = card; | 705 | mtp_card->card = card; |
709 | mtp_card->irq = -1; | 706 | mtp_card->irq = -1; |
710 | mtp_card->share_irq = 0; | 707 | mtp_card->share_irq = 0; |
711 | mtp_card->inmidistate = 0; | 708 | mtp_card->inmidistate = 0; |
712 | mtp_card->outmidihwport = 0xffffffff; | 709 | mtp_card->outmidihwport = 0xffffffff; |
713 | init_timer(&mtp_card->timer); | 710 | setup_timer(&mtp_card->timer, snd_mtpav_output_timer, |
714 | mtp_card->timer.function = snd_mtpav_output_timer; | 711 | (unsigned long) mtp_card); |
715 | mtp_card->timer.data = (unsigned long) mtp_card; | ||
716 | 712 | ||
717 | card->private_free = snd_mtpav_free; | 713 | card->private_free = snd_mtpav_free; |
718 | 714 | ||
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index f66af5884c40..369cef212ea9 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c | |||
@@ -24,7 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <sound/opl3.h> | 26 | #include <sound/opl3.h> |
27 | #include <asm/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index 6c6d09a51f42..f62780ed64ad 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c | |||
@@ -258,12 +258,10 @@ void snd_opl3_timer_func(unsigned long data) | |||
258 | spin_unlock_irqrestore(&opl3->voice_lock, flags); | 258 | spin_unlock_irqrestore(&opl3->voice_lock, flags); |
259 | 259 | ||
260 | spin_lock_irqsave(&opl3->sys_timer_lock, flags); | 260 | spin_lock_irqsave(&opl3->sys_timer_lock, flags); |
261 | if (again) { | 261 | if (again) |
262 | opl3->tlist.expires = jiffies + 1; /* invoke again */ | 262 | mod_timer(&opl3->tlist, jiffies + 1); /* invoke again */ |
263 | add_timer(&opl3->tlist); | 263 | else |
264 | } else { | ||
265 | opl3->sys_timer_status = 0; | 264 | opl3->sys_timer_status = 0; |
266 | } | ||
267 | spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); | 265 | spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); |
268 | } | 266 | } |
269 | 267 | ||
@@ -275,8 +273,7 @@ static void snd_opl3_start_timer(struct snd_opl3 *opl3) | |||
275 | unsigned long flags; | 273 | unsigned long flags; |
276 | spin_lock_irqsave(&opl3->sys_timer_lock, flags); | 274 | spin_lock_irqsave(&opl3->sys_timer_lock, flags); |
277 | if (! opl3->sys_timer_status) { | 275 | if (! opl3->sys_timer_status) { |
278 | opl3->tlist.expires = jiffies + 1; | 276 | mod_timer(&opl3->tlist, jiffies + 1); |
279 | add_timer(&opl3->tlist); | ||
280 | opl3->sys_timer_status = 1; | 277 | opl3->sys_timer_status = 1; |
281 | } | 278 | } |
282 | spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); | 279 | spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); |
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c index 68399538e435..a9f618e06a22 100644 --- a/sound/drivers/opl3/opl3_seq.c +++ b/sound/drivers/opl3/opl3_seq.c | |||
@@ -247,9 +247,7 @@ static int snd_opl3_seq_new_device(struct snd_seq_device *dev) | |||
247 | } | 247 | } |
248 | 248 | ||
249 | /* setup system timer */ | 249 | /* setup system timer */ |
250 | init_timer(&opl3->tlist); | 250 | setup_timer(&opl3->tlist, snd_opl3_timer_func, (unsigned long) opl3); |
251 | opl3->tlist.function = snd_opl3_timer_func; | ||
252 | opl3->tlist.data = (unsigned long) opl3; | ||
253 | spin_lock_init(&opl3->sys_timer_lock); | 251 | spin_lock_init(&opl3->sys_timer_lock); |
254 | opl3->sys_timer_status = 0; | 252 | opl3->sys_timer_status = 0; |
255 | 253 | ||
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index b953fb4aa298..3b0ee42a5343 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <asm/io.h> | 26 | #include <linux/io.h> |
27 | 27 | ||
28 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | 28 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
29 | MODULE_DESCRIPTION("OPL4 driver"); | 29 | MODULE_DESCRIPTION("OPL4 driver"); |
diff --git a/sound/drivers/opl4/opl4_synth.c b/sound/drivers/opl4/opl4_synth.c index 4b91adc0238c..7bc1e58c95aa 100644 --- a/sound/drivers/opl4/opl4_synth.c +++ b/sound/drivers/opl4/opl4_synth.c | |||
@@ -33,7 +33,7 @@ | |||
33 | 33 | ||
34 | #include "opl4_local.h" | 34 | #include "opl4_local.h" |
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | #include <asm/io.h> | 36 | #include <linux/io.h> |
37 | #include <sound/asoundef.h> | 37 | #include <sound/asoundef.h> |
38 | 38 | ||
39 | /* GM2 controllers */ | 39 | /* GM2 controllers */ |
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index 2adc7548ffca..d9647bd84d0f 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <sound/pcm.h> | 13 | #include <sound/pcm.h> |
14 | #include <linux/input.h> | 14 | #include <linux/input.h> |
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <asm/bitops.h> | 16 | #include <linux/bitops.h> |
17 | #include "pcsp_input.h" | 17 | #include "pcsp_input.h" |
18 | #include "pcsp.h" | 18 | #include "pcsp.h" |
19 | 19 | ||
diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c index 0ecf8a453e01..bfc25811985f 100644 --- a/sound/drivers/pcsp/pcsp_input.c +++ b/sound/drivers/pcsp/pcsp_input.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/input.h> | 16 | #include <linux/input.h> |
17 | #include <asm/io.h> | 17 | #include <linux/io.h> |
18 | #include "pcsp.h" | 18 | #include "pcsp.h" |
19 | #include "pcsp_input.h" | 19 | #include "pcsp_input.h" |
20 | 20 | ||
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index 29ebaa4ec0fd..3689f5f6be64 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c | |||
@@ -10,8 +10,8 @@ | |||
10 | #include <linux/gfp.h> | 10 | #include <linux/gfp.h> |
11 | #include <linux/moduleparam.h> | 11 | #include <linux/moduleparam.h> |
12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
13 | #include <linux/io.h> | ||
13 | #include <sound/pcm.h> | 14 | #include <sound/pcm.h> |
14 | #include <asm/io.h> | ||
15 | #include "pcsp.h" | 15 | #include "pcsp.h" |
16 | 16 | ||
17 | static bool nforce_wa; | 17 | static bool nforce_wa; |
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 13a34e3c6382..1927b89e1d1f 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/ioport.h> | 38 | #include <linux/ioport.h> |
39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
40 | #include <linux/io.h> | ||
40 | #include <sound/core.h> | 41 | #include <sound/core.h> |
41 | #include <sound/rawmidi.h> | 42 | #include <sound/rawmidi.h> |
42 | #include <sound/initval.h> | 43 | #include <sound/initval.h> |
@@ -44,8 +45,6 @@ | |||
44 | #include <linux/serial_reg.h> | 45 | #include <linux/serial_reg.h> |
45 | #include <linux/jiffies.h> | 46 | #include <linux/jiffies.h> |
46 | 47 | ||
47 | #include <asm/io.h> | ||
48 | |||
49 | MODULE_DESCRIPTION("MIDI serial u16550"); | 48 | MODULE_DESCRIPTION("MIDI serial u16550"); |
50 | MODULE_LICENSE("GPL"); | 49 | MODULE_LICENSE("GPL"); |
51 | MODULE_SUPPORTED_DEVICE("{{ALSA, MIDI serial u16550}}"); | 50 | MODULE_SUPPORTED_DEVICE("{{ALSA, MIDI serial u16550}}"); |
@@ -174,9 +173,8 @@ static inline void snd_uart16550_add_timer(struct snd_uart16550 *uart) | |||
174 | { | 173 | { |
175 | if (!uart->timer_running) { | 174 | if (!uart->timer_running) { |
176 | /* timer 38600bps * 10bit * 16byte */ | 175 | /* timer 38600bps * 10bit * 16byte */ |
177 | uart->buffer_timer.expires = jiffies + (HZ+255)/256; | 176 | mod_timer(&uart->buffer_timer, jiffies + (HZ + 255) / 256); |
178 | uart->timer_running = 1; | 177 | uart->timer_running = 1; |
179 | add_timer(&uart->buffer_timer); | ||
180 | } | 178 | } |
181 | } | 179 | } |
182 | 180 | ||
@@ -830,9 +828,8 @@ static int snd_uart16550_create(struct snd_card *card, | |||
830 | uart->prev_in = 0; | 828 | uart->prev_in = 0; |
831 | uart->rstatus = 0; | 829 | uart->rstatus = 0; |
832 | memset(uart->prev_status, 0x80, sizeof(unsigned char) * SNDRV_SERIAL_MAX_OUTS); | 830 | memset(uart->prev_status, 0x80, sizeof(unsigned char) * SNDRV_SERIAL_MAX_OUTS); |
833 | init_timer(&uart->buffer_timer); | 831 | setup_timer(&uart->buffer_timer, snd_uart16550_buffer_timer, |
834 | uart->buffer_timer.function = snd_uart16550_buffer_timer; | 832 | (unsigned long)uart); |
835 | uart->buffer_timer.data = (unsigned long)uart; | ||
836 | uart->timer_running = 0; | 833 | uart->timer_running = 0; |
837 | 834 | ||
838 | /* Register device */ | 835 | /* Register device */ |
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index fc05a37fd017..289f041706cd 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c | |||
@@ -27,11 +27,11 @@ | |||
27 | #include <linux/device.h> | 27 | #include <linux/device.h> |
28 | #include <linux/firmware.h> | 28 | #include <linux/firmware.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/io.h> | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
32 | #include <sound/asoundef.h> | 33 | #include <sound/asoundef.h> |
33 | #include <sound/info.h> | 34 | #include <sound/info.h> |
34 | #include <asm/io.h> | ||
35 | #include <sound/vx_core.h> | 35 | #include <sound/vx_core.h> |
36 | #include "vx_cmd.h" | 36 | #include "vx_cmd.h" |
37 | 37 | ||
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c index 0d580186ef1a..5cc356db5351 100644 --- a/sound/firewire/amdtp.c +++ b/sound/firewire/amdtp.c | |||
@@ -33,7 +33,7 @@ | |||
33 | */ | 33 | */ |
34 | #define MAX_MIDI_RX_BLOCKS 8 | 34 | #define MAX_MIDI_RX_BLOCKS 8 |
35 | 35 | ||
36 | #define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 µs */ | 36 | #define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 microseconds */ |
37 | 37 | ||
38 | /* isochronous header parameters */ | 38 | /* isochronous header parameters */ |
39 | #define ISO_DATA_LENGTH_SHIFT 16 | 39 | #define ISO_DATA_LENGTH_SHIFT 16 |
@@ -78,7 +78,7 @@ static void pcm_period_tasklet(unsigned long data); | |||
78 | int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, | 78 | int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, |
79 | enum amdtp_stream_direction dir, enum cip_flags flags) | 79 | enum amdtp_stream_direction dir, enum cip_flags flags) |
80 | { | 80 | { |
81 | s->unit = fw_unit_get(unit); | 81 | s->unit = unit; |
82 | s->direction = dir; | 82 | s->direction = dir; |
83 | s->flags = flags; | 83 | s->flags = flags; |
84 | s->context = ERR_PTR(-1); | 84 | s->context = ERR_PTR(-1); |
@@ -102,7 +102,6 @@ void amdtp_stream_destroy(struct amdtp_stream *s) | |||
102 | { | 102 | { |
103 | WARN_ON(amdtp_stream_running(s)); | 103 | WARN_ON(amdtp_stream_running(s)); |
104 | mutex_destroy(&s->mutex); | 104 | mutex_destroy(&s->mutex); |
105 | fw_unit_put(s->unit); | ||
106 | } | 105 | } |
107 | EXPORT_SYMBOL(amdtp_stream_destroy); | 106 | EXPORT_SYMBOL(amdtp_stream_destroy); |
108 | 107 | ||
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index fc19c99654aa..611b7dae7ee5 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c | |||
@@ -116,11 +116,22 @@ end: | |||
116 | return err; | 116 | return err; |
117 | } | 117 | } |
118 | 118 | ||
119 | /* | ||
120 | * This module releases the FireWire unit data after all ALSA character devices | ||
121 | * are released by applications. This is for releasing stream data or finishing | ||
122 | * transactions safely. Thus at returning from .remove(), this module still keep | ||
123 | * references for the unit. | ||
124 | */ | ||
119 | static void | 125 | static void |
120 | bebob_card_free(struct snd_card *card) | 126 | bebob_card_free(struct snd_card *card) |
121 | { | 127 | { |
122 | struct snd_bebob *bebob = card->private_data; | 128 | struct snd_bebob *bebob = card->private_data; |
123 | 129 | ||
130 | snd_bebob_stream_destroy_duplex(bebob); | ||
131 | fw_unit_put(bebob->unit); | ||
132 | |||
133 | kfree(bebob->maudio_special_quirk); | ||
134 | |||
124 | if (bebob->card_index >= 0) { | 135 | if (bebob->card_index >= 0) { |
125 | mutex_lock(&devices_mutex); | 136 | mutex_lock(&devices_mutex); |
126 | clear_bit(bebob->card_index, devices_used); | 137 | clear_bit(bebob->card_index, devices_used); |
@@ -205,7 +216,7 @@ bebob_probe(struct fw_unit *unit, | |||
205 | card->private_free = bebob_card_free; | 216 | card->private_free = bebob_card_free; |
206 | 217 | ||
207 | bebob->card = card; | 218 | bebob->card = card; |
208 | bebob->unit = unit; | 219 | bebob->unit = fw_unit_get(unit); |
209 | bebob->spec = spec; | 220 | bebob->spec = spec; |
210 | mutex_init(&bebob->mutex); | 221 | mutex_init(&bebob->mutex); |
211 | spin_lock_init(&bebob->lock); | 222 | spin_lock_init(&bebob->lock); |
@@ -306,10 +317,11 @@ static void bebob_remove(struct fw_unit *unit) | |||
306 | if (bebob == NULL) | 317 | if (bebob == NULL) |
307 | return; | 318 | return; |
308 | 319 | ||
309 | kfree(bebob->maudio_special_quirk); | 320 | /* Awake bus-reset waiters. */ |
321 | if (!completion_done(&bebob->bus_reset)) | ||
322 | complete_all(&bebob->bus_reset); | ||
310 | 323 | ||
311 | snd_bebob_stream_destroy_duplex(bebob); | 324 | /* No need to wait for releasing card object in this context. */ |
312 | snd_card_disconnect(bebob->card); | ||
313 | snd_card_free_when_closed(bebob->card); | 325 | snd_card_free_when_closed(bebob->card); |
314 | } | 326 | } |
315 | 327 | ||
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 0ebcabfdc7ce..98e4fc8121a1 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c | |||
@@ -410,8 +410,6 @@ break_both_connections(struct snd_bebob *bebob) | |||
410 | static void | 410 | static void |
411 | destroy_both_connections(struct snd_bebob *bebob) | 411 | destroy_both_connections(struct snd_bebob *bebob) |
412 | { | 412 | { |
413 | break_both_connections(bebob); | ||
414 | |||
415 | cmp_connection_destroy(&bebob->in_conn); | 413 | cmp_connection_destroy(&bebob->in_conn); |
416 | cmp_connection_destroy(&bebob->out_conn); | 414 | cmp_connection_destroy(&bebob->out_conn); |
417 | } | 415 | } |
@@ -712,22 +710,16 @@ void snd_bebob_stream_update_duplex(struct snd_bebob *bebob) | |||
712 | mutex_unlock(&bebob->mutex); | 710 | mutex_unlock(&bebob->mutex); |
713 | } | 711 | } |
714 | 712 | ||
713 | /* | ||
714 | * This function should be called before starting streams or after stopping | ||
715 | * streams. | ||
716 | */ | ||
715 | void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob) | 717 | void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob) |
716 | { | 718 | { |
717 | mutex_lock(&bebob->mutex); | ||
718 | |||
719 | amdtp_stream_pcm_abort(&bebob->rx_stream); | ||
720 | amdtp_stream_pcm_abort(&bebob->tx_stream); | ||
721 | |||
722 | amdtp_stream_stop(&bebob->rx_stream); | ||
723 | amdtp_stream_stop(&bebob->tx_stream); | ||
724 | |||
725 | amdtp_stream_destroy(&bebob->rx_stream); | 719 | amdtp_stream_destroy(&bebob->rx_stream); |
726 | amdtp_stream_destroy(&bebob->tx_stream); | 720 | amdtp_stream_destroy(&bebob->tx_stream); |
727 | 721 | ||
728 | destroy_both_connections(bebob); | 722 | destroy_both_connections(bebob); |
729 | |||
730 | mutex_unlock(&bebob->mutex); | ||
731 | } | 723 | } |
732 | 724 | ||
733 | /* | 725 | /* |
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index fa9cf761b610..07dbd01d7a6b 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c | |||
@@ -311,14 +311,21 @@ end: | |||
311 | return err; | 311 | return err; |
312 | } | 312 | } |
313 | 313 | ||
314 | /* | ||
315 | * This function should be called before starting streams or after stopping | ||
316 | * streams. | ||
317 | */ | ||
314 | static void destroy_stream(struct snd_dice *dice, struct amdtp_stream *stream) | 318 | static void destroy_stream(struct snd_dice *dice, struct amdtp_stream *stream) |
315 | { | 319 | { |
316 | amdtp_stream_destroy(stream); | 320 | struct fw_iso_resources *resources; |
317 | 321 | ||
318 | if (stream == &dice->tx_stream) | 322 | if (stream == &dice->tx_stream) |
319 | fw_iso_resources_destroy(&dice->tx_resources); | 323 | resources = &dice->tx_resources; |
320 | else | 324 | else |
321 | fw_iso_resources_destroy(&dice->rx_resources); | 325 | resources = &dice->rx_resources; |
326 | |||
327 | amdtp_stream_destroy(stream); | ||
328 | fw_iso_resources_destroy(resources); | ||
322 | } | 329 | } |
323 | 330 | ||
324 | int snd_dice_stream_init_duplex(struct snd_dice *dice) | 331 | int snd_dice_stream_init_duplex(struct snd_dice *dice) |
@@ -332,6 +339,8 @@ int snd_dice_stream_init_duplex(struct snd_dice *dice) | |||
332 | goto end; | 339 | goto end; |
333 | 340 | ||
334 | err = init_stream(dice, &dice->rx_stream); | 341 | err = init_stream(dice, &dice->rx_stream); |
342 | if (err < 0) | ||
343 | destroy_stream(dice, &dice->tx_stream); | ||
335 | end: | 344 | end: |
336 | return err; | 345 | return err; |
337 | } | 346 | } |
@@ -340,10 +349,7 @@ void snd_dice_stream_destroy_duplex(struct snd_dice *dice) | |||
340 | { | 349 | { |
341 | snd_dice_transaction_clear_enable(dice); | 350 | snd_dice_transaction_clear_enable(dice); |
342 | 351 | ||
343 | stop_stream(dice, &dice->tx_stream); | ||
344 | destroy_stream(dice, &dice->tx_stream); | 352 | destroy_stream(dice, &dice->tx_stream); |
345 | |||
346 | stop_stream(dice, &dice->rx_stream); | ||
347 | destroy_stream(dice, &dice->rx_stream); | 353 | destroy_stream(dice, &dice->rx_stream); |
348 | 354 | ||
349 | dice->substreams_counter = 0; | 355 | dice->substreams_counter = 0; |
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 90d8f40ff727..70a111d7f428 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c | |||
@@ -226,11 +226,20 @@ static void dice_card_strings(struct snd_dice *dice) | |||
226 | strcpy(card->mixername, "DICE"); | 226 | strcpy(card->mixername, "DICE"); |
227 | } | 227 | } |
228 | 228 | ||
229 | /* | ||
230 | * This module releases the FireWire unit data after all ALSA character devices | ||
231 | * are released by applications. This is for releasing stream data or finishing | ||
232 | * transactions safely. Thus at returning from .remove(), this module still keep | ||
233 | * references for the unit. | ||
234 | */ | ||
229 | static void dice_card_free(struct snd_card *card) | 235 | static void dice_card_free(struct snd_card *card) |
230 | { | 236 | { |
231 | struct snd_dice *dice = card->private_data; | 237 | struct snd_dice *dice = card->private_data; |
232 | 238 | ||
239 | snd_dice_stream_destroy_duplex(dice); | ||
233 | snd_dice_transaction_destroy(dice); | 240 | snd_dice_transaction_destroy(dice); |
241 | fw_unit_put(dice->unit); | ||
242 | |||
234 | mutex_destroy(&dice->mutex); | 243 | mutex_destroy(&dice->mutex); |
235 | } | 244 | } |
236 | 245 | ||
@@ -251,7 +260,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) | |||
251 | 260 | ||
252 | dice = card->private_data; | 261 | dice = card->private_data; |
253 | dice->card = card; | 262 | dice->card = card; |
254 | dice->unit = unit; | 263 | dice->unit = fw_unit_get(unit); |
255 | card->private_free = dice_card_free; | 264 | card->private_free = dice_card_free; |
256 | 265 | ||
257 | spin_lock_init(&dice->lock); | 266 | spin_lock_init(&dice->lock); |
@@ -305,10 +314,7 @@ static void dice_remove(struct fw_unit *unit) | |||
305 | { | 314 | { |
306 | struct snd_dice *dice = dev_get_drvdata(&unit->device); | 315 | struct snd_dice *dice = dev_get_drvdata(&unit->device); |
307 | 316 | ||
308 | snd_card_disconnect(dice->card); | 317 | /* No need to wait for releasing card object in this context. */ |
309 | |||
310 | snd_dice_stream_destroy_duplex(dice); | ||
311 | |||
312 | snd_card_free_when_closed(dice->card); | 318 | snd_card_free_when_closed(dice->card); |
313 | } | 319 | } |
314 | 320 | ||
diff --git a/sound/firewire/fireworks/fireworks.c b/sound/firewire/fireworks/fireworks.c index 3e2ed8e82cbc..2682e7e3e5c9 100644 --- a/sound/firewire/fireworks/fireworks.c +++ b/sound/firewire/fireworks/fireworks.c | |||
@@ -173,11 +173,23 @@ end: | |||
173 | return err; | 173 | return err; |
174 | } | 174 | } |
175 | 175 | ||
176 | /* | ||
177 | * This module releases the FireWire unit data after all ALSA character devices | ||
178 | * are released by applications. This is for releasing stream data or finishing | ||
179 | * transactions safely. Thus at returning from .remove(), this module still keep | ||
180 | * references for the unit. | ||
181 | */ | ||
176 | static void | 182 | static void |
177 | efw_card_free(struct snd_card *card) | 183 | efw_card_free(struct snd_card *card) |
178 | { | 184 | { |
179 | struct snd_efw *efw = card->private_data; | 185 | struct snd_efw *efw = card->private_data; |
180 | 186 | ||
187 | snd_efw_stream_destroy_duplex(efw); | ||
188 | snd_efw_transaction_remove_instance(efw); | ||
189 | fw_unit_put(efw->unit); | ||
190 | |||
191 | kfree(efw->resp_buf); | ||
192 | |||
181 | if (efw->card_index >= 0) { | 193 | if (efw->card_index >= 0) { |
182 | mutex_lock(&devices_mutex); | 194 | mutex_lock(&devices_mutex); |
183 | clear_bit(efw->card_index, devices_used); | 195 | clear_bit(efw->card_index, devices_used); |
@@ -185,7 +197,6 @@ efw_card_free(struct snd_card *card) | |||
185 | } | 197 | } |
186 | 198 | ||
187 | mutex_destroy(&efw->mutex); | 199 | mutex_destroy(&efw->mutex); |
188 | kfree(efw->resp_buf); | ||
189 | } | 200 | } |
190 | 201 | ||
191 | static int | 202 | static int |
@@ -218,7 +229,7 @@ efw_probe(struct fw_unit *unit, | |||
218 | card->private_free = efw_card_free; | 229 | card->private_free = efw_card_free; |
219 | 230 | ||
220 | efw->card = card; | 231 | efw->card = card; |
221 | efw->unit = unit; | 232 | efw->unit = fw_unit_get(unit); |
222 | mutex_init(&efw->mutex); | 233 | mutex_init(&efw->mutex); |
223 | spin_lock_init(&efw->lock); | 234 | spin_lock_init(&efw->lock); |
224 | init_waitqueue_head(&efw->hwdep_wait); | 235 | init_waitqueue_head(&efw->hwdep_wait); |
@@ -289,10 +300,7 @@ static void efw_remove(struct fw_unit *unit) | |||
289 | { | 300 | { |
290 | struct snd_efw *efw = dev_get_drvdata(&unit->device); | 301 | struct snd_efw *efw = dev_get_drvdata(&unit->device); |
291 | 302 | ||
292 | snd_efw_stream_destroy_duplex(efw); | 303 | /* No need to wait for releasing card object in this context. */ |
293 | snd_efw_transaction_remove_instance(efw); | ||
294 | |||
295 | snd_card_disconnect(efw->card); | ||
296 | snd_card_free_when_closed(efw->card); | 304 | snd_card_free_when_closed(efw->card); |
297 | } | 305 | } |
298 | 306 | ||
diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 4f440e163667..c55db1bddc80 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c | |||
@@ -100,17 +100,22 @@ end: | |||
100 | return err; | 100 | return err; |
101 | } | 101 | } |
102 | 102 | ||
103 | /* | ||
104 | * This function should be called before starting the stream or after stopping | ||
105 | * the streams. | ||
106 | */ | ||
103 | static void | 107 | static void |
104 | destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream) | 108 | destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream) |
105 | { | 109 | { |
106 | stop_stream(efw, stream); | 110 | struct cmp_connection *conn; |
107 | |||
108 | amdtp_stream_destroy(stream); | ||
109 | 111 | ||
110 | if (stream == &efw->tx_stream) | 112 | if (stream == &efw->tx_stream) |
111 | cmp_connection_destroy(&efw->out_conn); | 113 | conn = &efw->out_conn; |
112 | else | 114 | else |
113 | cmp_connection_destroy(&efw->in_conn); | 115 | conn = &efw->in_conn; |
116 | |||
117 | amdtp_stream_destroy(stream); | ||
118 | cmp_connection_destroy(&efw->out_conn); | ||
114 | } | 119 | } |
115 | 120 | ||
116 | static int | 121 | static int |
@@ -319,12 +324,8 @@ void snd_efw_stream_update_duplex(struct snd_efw *efw) | |||
319 | 324 | ||
320 | void snd_efw_stream_destroy_duplex(struct snd_efw *efw) | 325 | void snd_efw_stream_destroy_duplex(struct snd_efw *efw) |
321 | { | 326 | { |
322 | mutex_lock(&efw->mutex); | ||
323 | |||
324 | destroy_stream(efw, &efw->rx_stream); | 327 | destroy_stream(efw, &efw->rx_stream); |
325 | destroy_stream(efw, &efw->tx_stream); | 328 | destroy_stream(efw, &efw->tx_stream); |
326 | |||
327 | mutex_unlock(&efw->mutex); | ||
328 | } | 329 | } |
329 | 330 | ||
330 | void snd_efw_stream_lock_changed(struct snd_efw *efw) | 331 | void snd_efw_stream_lock_changed(struct snd_efw *efw) |
diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index bda845afb470..29ccb3637164 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c | |||
@@ -337,6 +337,10 @@ void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw, | |||
337 | stop_stream(oxfw, stream); | 337 | stop_stream(oxfw, stream); |
338 | } | 338 | } |
339 | 339 | ||
340 | /* | ||
341 | * This function should be called before starting the stream or after stopping | ||
342 | * the streams. | ||
343 | */ | ||
340 | void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw, | 344 | void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw, |
341 | struct amdtp_stream *stream) | 345 | struct amdtp_stream *stream) |
342 | { | 346 | { |
@@ -347,8 +351,6 @@ void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw, | |||
347 | else | 351 | else |
348 | conn = &oxfw->in_conn; | 352 | conn = &oxfw->in_conn; |
349 | 353 | ||
350 | stop_stream(oxfw, stream); | ||
351 | |||
352 | amdtp_stream_destroy(stream); | 354 | amdtp_stream_destroy(stream); |
353 | cmp_connection_destroy(conn); | 355 | cmp_connection_destroy(conn); |
354 | } | 356 | } |
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index 60e5cad0531a..8c6ce019f437 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c | |||
@@ -104,11 +104,23 @@ end: | |||
104 | return err; | 104 | return err; |
105 | } | 105 | } |
106 | 106 | ||
107 | /* | ||
108 | * This module releases the FireWire unit data after all ALSA character devices | ||
109 | * are released by applications. This is for releasing stream data or finishing | ||
110 | * transactions safely. Thus at returning from .remove(), this module still keep | ||
111 | * references for the unit. | ||
112 | */ | ||
107 | static void oxfw_card_free(struct snd_card *card) | 113 | static void oxfw_card_free(struct snd_card *card) |
108 | { | 114 | { |
109 | struct snd_oxfw *oxfw = card->private_data; | 115 | struct snd_oxfw *oxfw = card->private_data; |
110 | unsigned int i; | 116 | unsigned int i; |
111 | 117 | ||
118 | snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream); | ||
119 | if (oxfw->has_output) | ||
120 | snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream); | ||
121 | |||
122 | fw_unit_put(oxfw->unit); | ||
123 | |||
112 | for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { | 124 | for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { |
113 | kfree(oxfw->tx_stream_formats[i]); | 125 | kfree(oxfw->tx_stream_formats[i]); |
114 | kfree(oxfw->rx_stream_formats[i]); | 126 | kfree(oxfw->rx_stream_formats[i]); |
@@ -136,7 +148,7 @@ static int oxfw_probe(struct fw_unit *unit, | |||
136 | oxfw = card->private_data; | 148 | oxfw = card->private_data; |
137 | oxfw->card = card; | 149 | oxfw->card = card; |
138 | mutex_init(&oxfw->mutex); | 150 | mutex_init(&oxfw->mutex); |
139 | oxfw->unit = unit; | 151 | oxfw->unit = fw_unit_get(unit); |
140 | oxfw->device_info = (const struct device_info *)id->driver_data; | 152 | oxfw->device_info = (const struct device_info *)id->driver_data; |
141 | spin_lock_init(&oxfw->lock); | 153 | spin_lock_init(&oxfw->lock); |
142 | init_waitqueue_head(&oxfw->hwdep_wait); | 154 | init_waitqueue_head(&oxfw->hwdep_wait); |
@@ -212,12 +224,7 @@ static void oxfw_remove(struct fw_unit *unit) | |||
212 | { | 224 | { |
213 | struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); | 225 | struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); |
214 | 226 | ||
215 | snd_card_disconnect(oxfw->card); | 227 | /* No need to wait for releasing card object in this context. */ |
216 | |||
217 | snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream); | ||
218 | if (oxfw->has_output) | ||
219 | snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream); | ||
220 | |||
221 | snd_card_free_when_closed(oxfw->card); | 228 | snd_card_free_when_closed(oxfw->card); |
222 | } | 229 | } |
223 | 230 | ||
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c index c6bba99a90b2..88844881cbff 100644 --- a/sound/i2c/other/ak4113.c +++ b/sound/i2c/other/ak4113.c | |||
@@ -89,6 +89,7 @@ int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read, | |||
89 | chip->private_data = private_data; | 89 | chip->private_data = private_data; |
90 | INIT_DELAYED_WORK(&chip->work, ak4113_stats); | 90 | INIT_DELAYED_WORK(&chip->work, ak4113_stats); |
91 | atomic_set(&chip->wq_processing, 0); | 91 | atomic_set(&chip->wq_processing, 0); |
92 | mutex_init(&chip->reinit_mutex); | ||
92 | 93 | ||
93 | for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++) | 94 | for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++) |
94 | chip->regmap[reg] = pgm[reg]; | 95 | chip->regmap[reg] = pgm[reg]; |
@@ -141,7 +142,9 @@ void snd_ak4113_reinit(struct ak4113 *chip) | |||
141 | { | 142 | { |
142 | if (atomic_inc_return(&chip->wq_processing) == 1) | 143 | if (atomic_inc_return(&chip->wq_processing) == 1) |
143 | cancel_delayed_work_sync(&chip->work); | 144 | cancel_delayed_work_sync(&chip->work); |
145 | mutex_lock(&chip->reinit_mutex); | ||
144 | ak4113_init_regs(chip); | 146 | ak4113_init_regs(chip); |
147 | mutex_unlock(&chip->reinit_mutex); | ||
145 | /* bring up statistics / event queing */ | 148 | /* bring up statistics / event queing */ |
146 | if (atomic_dec_and_test(&chip->wq_processing)) | 149 | if (atomic_dec_and_test(&chip->wq_processing)) |
147 | schedule_delayed_work(&chip->work, HZ / 10); | 150 | schedule_delayed_work(&chip->work, HZ / 10); |
@@ -636,3 +639,19 @@ static void ak4113_stats(struct work_struct *work) | |||
636 | if (atomic_dec_and_test(&chip->wq_processing)) | 639 | if (atomic_dec_and_test(&chip->wq_processing)) |
637 | schedule_delayed_work(&chip->work, HZ / 10); | 640 | schedule_delayed_work(&chip->work, HZ / 10); |
638 | } | 641 | } |
642 | |||
643 | #ifdef CONFIG_PM | ||
644 | void snd_ak4113_suspend(struct ak4113 *chip) | ||
645 | { | ||
646 | atomic_inc(&chip->wq_processing); /* don't schedule new work */ | ||
647 | cancel_delayed_work_sync(&chip->work); | ||
648 | } | ||
649 | EXPORT_SYMBOL(snd_ak4113_suspend); | ||
650 | |||
651 | void snd_ak4113_resume(struct ak4113 *chip) | ||
652 | { | ||
653 | atomic_dec(&chip->wq_processing); | ||
654 | snd_ak4113_reinit(chip); | ||
655 | } | ||
656 | EXPORT_SYMBOL(snd_ak4113_resume); | ||
657 | #endif | ||
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index b70e6eccbd03..5a4cf3fab4ae 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c | |||
@@ -100,6 +100,7 @@ int snd_ak4114_create(struct snd_card *card, | |||
100 | chip->private_data = private_data; | 100 | chip->private_data = private_data; |
101 | INIT_DELAYED_WORK(&chip->work, ak4114_stats); | 101 | INIT_DELAYED_WORK(&chip->work, ak4114_stats); |
102 | atomic_set(&chip->wq_processing, 0); | 102 | atomic_set(&chip->wq_processing, 0); |
103 | mutex_init(&chip->reinit_mutex); | ||
103 | 104 | ||
104 | for (reg = 0; reg < 6; reg++) | 105 | for (reg = 0; reg < 6; reg++) |
105 | chip->regmap[reg] = pgm[reg]; | 106 | chip->regmap[reg] = pgm[reg]; |
@@ -122,6 +123,7 @@ int snd_ak4114_create(struct snd_card *card, | |||
122 | snd_ak4114_free(chip); | 123 | snd_ak4114_free(chip); |
123 | return err < 0 ? err : -EIO; | 124 | return err < 0 ? err : -EIO; |
124 | } | 125 | } |
126 | EXPORT_SYMBOL(snd_ak4114_create); | ||
125 | 127 | ||
126 | void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char mask, unsigned char val) | 128 | void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char mask, unsigned char val) |
127 | { | 129 | { |
@@ -131,6 +133,7 @@ void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char | |||
131 | reg_write(chip, reg, | 133 | reg_write(chip, reg, |
132 | (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val); | 134 | (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val); |
133 | } | 135 | } |
136 | EXPORT_SYMBOL(snd_ak4114_reg_write); | ||
134 | 137 | ||
135 | static void ak4114_init_regs(struct ak4114 *chip) | 138 | static void ak4114_init_regs(struct ak4114 *chip) |
136 | { | 139 | { |
@@ -154,11 +157,14 @@ void snd_ak4114_reinit(struct ak4114 *chip) | |||
154 | { | 157 | { |
155 | if (atomic_inc_return(&chip->wq_processing) == 1) | 158 | if (atomic_inc_return(&chip->wq_processing) == 1) |
156 | cancel_delayed_work_sync(&chip->work); | 159 | cancel_delayed_work_sync(&chip->work); |
160 | mutex_lock(&chip->reinit_mutex); | ||
157 | ak4114_init_regs(chip); | 161 | ak4114_init_regs(chip); |
162 | mutex_unlock(&chip->reinit_mutex); | ||
158 | /* bring up statistics / event queing */ | 163 | /* bring up statistics / event queing */ |
159 | if (atomic_dec_and_test(&chip->wq_processing)) | 164 | if (atomic_dec_and_test(&chip->wq_processing)) |
160 | schedule_delayed_work(&chip->work, HZ / 10); | 165 | schedule_delayed_work(&chip->work, HZ / 10); |
161 | } | 166 | } |
167 | EXPORT_SYMBOL(snd_ak4114_reinit); | ||
162 | 168 | ||
163 | static unsigned int external_rate(unsigned char rcs1) | 169 | static unsigned int external_rate(unsigned char rcs1) |
164 | { | 170 | { |
@@ -503,6 +509,7 @@ int snd_ak4114_build(struct ak4114 *ak4114, | |||
503 | schedule_delayed_work(&ak4114->work, HZ / 10); | 509 | schedule_delayed_work(&ak4114->work, HZ / 10); |
504 | return 0; | 510 | return 0; |
505 | } | 511 | } |
512 | EXPORT_SYMBOL(snd_ak4114_build); | ||
506 | 513 | ||
507 | /* notify kcontrols if any parameters are changed */ | 514 | /* notify kcontrols if any parameters are changed */ |
508 | static void ak4114_notify(struct ak4114 *ak4114, | 515 | static void ak4114_notify(struct ak4114 *ak4114, |
@@ -558,6 +565,7 @@ int snd_ak4114_external_rate(struct ak4114 *ak4114) | |||
558 | rcs1 = reg_read(ak4114, AK4114_REG_RCS1); | 565 | rcs1 = reg_read(ak4114, AK4114_REG_RCS1); |
559 | return external_rate(rcs1); | 566 | return external_rate(rcs1); |
560 | } | 567 | } |
568 | EXPORT_SYMBOL(snd_ak4114_external_rate); | ||
561 | 569 | ||
562 | int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) | 570 | int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) |
563 | { | 571 | { |
@@ -605,6 +613,7 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) | |||
605 | } | 613 | } |
606 | return res; | 614 | return res; |
607 | } | 615 | } |
616 | EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors); | ||
608 | 617 | ||
609 | static void ak4114_stats(struct work_struct *work) | 618 | static void ak4114_stats(struct work_struct *work) |
610 | { | 619 | { |
@@ -616,9 +625,18 @@ static void ak4114_stats(struct work_struct *work) | |||
616 | schedule_delayed_work(&chip->work, HZ / 10); | 625 | schedule_delayed_work(&chip->work, HZ / 10); |
617 | } | 626 | } |
618 | 627 | ||
619 | EXPORT_SYMBOL(snd_ak4114_create); | 628 | #ifdef CONFIG_PM |
620 | EXPORT_SYMBOL(snd_ak4114_reg_write); | 629 | void snd_ak4114_suspend(struct ak4114 *chip) |
621 | EXPORT_SYMBOL(snd_ak4114_reinit); | 630 | { |
622 | EXPORT_SYMBOL(snd_ak4114_build); | 631 | atomic_inc(&chip->wq_processing); /* don't schedule new work */ |
623 | EXPORT_SYMBOL(snd_ak4114_external_rate); | 632 | cancel_delayed_work_sync(&chip->work); |
624 | EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors); | 633 | } |
634 | EXPORT_SYMBOL(snd_ak4114_suspend); | ||
635 | |||
636 | void snd_ak4114_resume(struct ak4114 *chip) | ||
637 | { | ||
638 | atomic_dec(&chip->wq_processing); | ||
639 | snd_ak4114_reinit(chip); | ||
640 | } | ||
641 | EXPORT_SYMBOL(snd_ak4114_resume); | ||
642 | #endif | ||
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index 88452e899bd9..48848909a5a9 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c | |||
@@ -91,9 +91,7 @@ int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t | |||
91 | chip->read = read; | 91 | chip->read = read; |
92 | chip->write = write; | 92 | chip->write = write; |
93 | chip->private_data = private_data; | 93 | chip->private_data = private_data; |
94 | init_timer(&chip->timer); | 94 | setup_timer(&chip->timer, snd_ak4117_timer, (unsigned long)chip); |
95 | chip->timer.data = (unsigned long)chip; | ||
96 | chip->timer.function = snd_ak4117_timer; | ||
97 | 95 | ||
98 | for (reg = 0; reg < 5; reg++) | 96 | for (reg = 0; reg < 5; reg++) |
99 | chip->regmap[reg] = pgm[reg]; | 97 | chip->regmap[reg] = pgm[reg]; |
@@ -139,8 +137,7 @@ void snd_ak4117_reinit(struct ak4117 *chip) | |||
139 | /* release powerdown, everything is initialized now */ | 137 | /* release powerdown, everything is initialized now */ |
140 | reg_write(chip, AK4117_REG_PWRDN, old | AK4117_RST | AK4117_PWN); | 138 | reg_write(chip, AK4117_REG_PWRDN, old | AK4117_RST | AK4117_PWN); |
141 | chip->init = 0; | 139 | chip->init = 0; |
142 | chip->timer.expires = 1 + jiffies; | 140 | mod_timer(&chip->timer, 1 + jiffies); |
143 | add_timer(&chip->timer); | ||
144 | } | 141 | } |
145 | 142 | ||
146 | static unsigned int external_rate(unsigned char rcs1) | 143 | static unsigned int external_rate(unsigned char rcs1) |
@@ -540,8 +537,7 @@ static void snd_ak4117_timer(unsigned long data) | |||
540 | if (chip->init) | 537 | if (chip->init) |
541 | return; | 538 | return; |
542 | snd_ak4117_check_rate_and_errors(chip, 0); | 539 | snd_ak4117_check_rate_and_errors(chip, 0); |
543 | chip->timer.expires = 1 + jiffies; | 540 | mod_timer(&chip->timer, 1 + jiffies); |
544 | add_timer(&chip->timer); | ||
545 | } | 541 | } |
546 | 542 | ||
547 | EXPORT_SYMBOL(snd_ak4117_create); | 543 | EXPORT_SYMBOL(snd_ak4117_create); |
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index 67dbfde837ab..c65731088aa2 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c | |||
@@ -21,7 +21,7 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <asm/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index f481a41e027e..769226515f0d 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c | |||
@@ -142,7 +142,6 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard, | |||
142 | struct snd_card *card; | 142 | struct snd_card *card; |
143 | struct snd_ad1816a *chip; | 143 | struct snd_ad1816a *chip; |
144 | struct snd_opl3 *opl3; | 144 | struct snd_opl3 *opl3; |
145 | struct snd_timer *timer; | ||
146 | 145 | ||
147 | error = snd_card_new(&pcard->card->dev, | 146 | error = snd_card_new(&pcard->card->dev, |
148 | index[dev], id[dev], THIS_MODULE, | 147 | index[dev], id[dev], THIS_MODULE, |
@@ -172,7 +171,7 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard, | |||
172 | sprintf(card->longname, "%s, SS at 0x%lx, irq %d, dma %d&%d", | 171 | sprintf(card->longname, "%s, SS at 0x%lx, irq %d, dma %d&%d", |
173 | card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]); | 172 | card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]); |
174 | 173 | ||
175 | if ((error = snd_ad1816a_pcm(chip, 0, NULL)) < 0) { | 174 | if ((error = snd_ad1816a_pcm(chip, 0)) < 0) { |
176 | snd_card_free(card); | 175 | snd_card_free(card); |
177 | return error; | 176 | return error; |
178 | } | 177 | } |
@@ -182,7 +181,7 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard, | |||
182 | return error; | 181 | return error; |
183 | } | 182 | } |
184 | 183 | ||
185 | error = snd_ad1816a_timer(chip, 0, &timer); | 184 | error = snd_ad1816a_timer(chip, 0); |
186 | if (error < 0) { | 185 | if (error < 0) { |
187 | snd_card_free(card); | 186 | snd_card_free(card); |
188 | return error; | 187 | return error; |
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 01a07986f4a3..5c815f5fb044 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c | |||
@@ -22,11 +22,11 @@ | |||
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/ioport.h> | 24 | #include <linux/ioport.h> |
25 | #include <linux/io.h> | ||
25 | #include <sound/core.h> | 26 | #include <sound/core.h> |
26 | #include <sound/tlv.h> | 27 | #include <sound/tlv.h> |
27 | #include <sound/ad1816a.h> | 28 | #include <sound/ad1816a.h> |
28 | 29 | ||
29 | #include <asm/io.h> | ||
30 | #include <asm/dma.h> | 30 | #include <asm/dma.h> |
31 | 31 | ||
32 | static inline int snd_ad1816a_busy_wait(struct snd_ad1816a *chip) | 32 | static inline int snd_ad1816a_busy_wait(struct snd_ad1816a *chip) |
@@ -675,7 +675,7 @@ static struct snd_pcm_ops snd_ad1816a_capture_ops = { | |||
675 | .pointer = snd_ad1816a_capture_pointer, | 675 | .pointer = snd_ad1816a_capture_pointer, |
676 | }; | 676 | }; |
677 | 677 | ||
678 | int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm) | 678 | int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device) |
679 | { | 679 | { |
680 | int error; | 680 | int error; |
681 | struct snd_pcm *pcm; | 681 | struct snd_pcm *pcm; |
@@ -697,13 +697,10 @@ int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm) | |||
697 | 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024); | 697 | 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024); |
698 | 698 | ||
699 | chip->pcm = pcm; | 699 | chip->pcm = pcm; |
700 | if (rpcm) | ||
701 | *rpcm = pcm; | ||
702 | return 0; | 700 | return 0; |
703 | } | 701 | } |
704 | 702 | ||
705 | int snd_ad1816a_timer(struct snd_ad1816a *chip, int device, | 703 | int snd_ad1816a_timer(struct snd_ad1816a *chip, int device) |
706 | struct snd_timer **rtimer) | ||
707 | { | 704 | { |
708 | struct snd_timer *timer; | 705 | struct snd_timer *timer; |
709 | struct snd_timer_id tid; | 706 | struct snd_timer_id tid; |
@@ -720,8 +717,6 @@ int snd_ad1816a_timer(struct snd_ad1816a *chip, int device, | |||
720 | timer->private_data = chip; | 717 | timer->private_data = chip; |
721 | chip->timer = timer; | 718 | chip->timer = timer; |
722 | timer->hw = snd_ad1816a_timer_table; | 719 | timer->hw = snd_ad1816a_timer_table; |
723 | if (rtimer) | ||
724 | *rtimer = timer; | ||
725 | return 0; | 720 | return 0; |
726 | } | 721 | } |
727 | 722 | ||
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 093f22a464d7..f159da4ec890 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c | |||
@@ -88,7 +88,6 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n) | |||
88 | { | 88 | { |
89 | struct snd_card *card; | 89 | struct snd_card *card; |
90 | struct snd_wss *chip; | 90 | struct snd_wss *chip; |
91 | struct snd_pcm *pcm; | ||
92 | int error; | 91 | int error; |
93 | 92 | ||
94 | error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card); | 93 | error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card); |
@@ -103,7 +102,7 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n) | |||
103 | 102 | ||
104 | card->private_data = chip; | 103 | card->private_data = chip; |
105 | 104 | ||
106 | error = snd_wss_pcm(chip, 0, &pcm); | 105 | error = snd_wss_pcm(chip, 0); |
107 | if (error < 0) | 106 | if (error < 0) |
108 | goto out; | 107 | goto out; |
109 | 108 | ||
@@ -112,10 +111,10 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n) | |||
112 | goto out; | 111 | goto out; |
113 | 112 | ||
114 | strcpy(card->driver, "AD1848"); | 113 | strcpy(card->driver, "AD1848"); |
115 | strcpy(card->shortname, pcm->name); | 114 | strcpy(card->shortname, chip->pcm->name); |
116 | 115 | ||
117 | sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", | 116 | sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", |
118 | pcm->name, chip->port, irq[n], dma1[n]); | 117 | chip->pcm->name, chip->port, irq[n], dma1[n]); |
119 | if (thinkpad[n]) | 118 | if (thinkpad[n]) |
120 | strcat(card->longname, " [Thinkpad]"); | 119 | strcat(card->longname, " [Thinkpad]"); |
121 | 120 | ||
diff --git a/sound/isa/als100.c b/sound/isa/als100.c index 32d01525211d..bc9ea306ee02 100644 --- a/sound/isa/als100.c +++ b/sound/isa/als100.c | |||
@@ -233,7 +233,7 @@ static int snd_card_als100_probe(int dev, | |||
233 | irq[dev], dma8[dev], dma16[dev]); | 233 | irq[dev], dma8[dev], dma16[dev]); |
234 | } | 234 | } |
235 | 235 | ||
236 | if ((error = snd_sb16dsp_pcm(chip, 0, &chip->pcm)) < 0) { | 236 | if ((error = snd_sb16dsp_pcm(chip, 0)) < 0) { |
237 | snd_card_free(card); | 237 | snd_card_free(card); |
238 | return error; | 238 | return error; |
239 | } | 239 | } |
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c index 0ea75fc62072..fff186fa621e 100644 --- a/sound/isa/azt2320.c +++ b/sound/isa/azt2320.c | |||
@@ -29,7 +29,7 @@ | |||
29 | activation method (full-duplex audio!). | 29 | activation method (full-duplex audio!). |
30 | */ | 30 | */ |
31 | 31 | ||
32 | #include <asm/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/time.h> | 35 | #include <linux/time.h> |
@@ -215,7 +215,7 @@ static int snd_card_azt2320_probe(int dev, | |||
215 | sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i", | 215 | sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i", |
216 | card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]); | 216 | card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]); |
217 | 217 | ||
218 | error = snd_wss_pcm(chip, 0, NULL); | 218 | error = snd_wss_pcm(chip, 0); |
219 | if (error < 0) { | 219 | if (error < 0) { |
220 | snd_card_free(card); | 220 | snd_card_free(card); |
221 | return error; | 221 | return error; |
@@ -225,7 +225,7 @@ static int snd_card_azt2320_probe(int dev, | |||
225 | snd_card_free(card); | 225 | snd_card_free(card); |
226 | return error; | 226 | return error; |
227 | } | 227 | } |
228 | error = snd_wss_timer(chip, 0, NULL); | 228 | error = snd_wss_timer(chip, 0); |
229 | if (error < 0) { | 229 | if (error < 0) { |
230 | snd_card_free(card); | 230 | snd_card_free(card); |
231 | return error; | 231 | return error; |
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c index 4778852a1201..2c89d95da674 100644 --- a/sound/isa/cmi8328.c +++ b/sound/isa/cmi8328.c | |||
@@ -307,7 +307,7 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev) | |||
307 | if (err < 0) | 307 | if (err < 0) |
308 | goto error; | 308 | goto error; |
309 | 309 | ||
310 | err = snd_wss_pcm(cmi->wss, 0, NULL); | 310 | err = snd_wss_pcm(cmi->wss, 0); |
311 | if (err < 0) | 311 | if (err < 0) |
312 | goto error; | 312 | goto error; |
313 | 313 | ||
@@ -318,7 +318,7 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev) | |||
318 | if (err < 0) | 318 | if (err < 0) |
319 | goto error; | 319 | goto error; |
320 | 320 | ||
321 | if (snd_wss_timer(cmi->wss, 0, NULL) < 0) | 321 | if (snd_wss_timer(cmi->wss, 0) < 0) |
322 | snd_printk(KERN_WARNING "error initializing WSS timer\n"); | 322 | snd_printk(KERN_WARNING "error initializing WSS timer\n"); |
323 | 323 | ||
324 | if (mpuport[ndev] == SNDRV_AUTO_PORT) { | 324 | if (mpuport[ndev] == SNDRV_AUTO_PORT) { |
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index 7dba07a4343a..282cd75d2235 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c | |||
@@ -92,7 +92,6 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n) | |||
92 | { | 92 | { |
93 | struct snd_card *card; | 93 | struct snd_card *card; |
94 | struct snd_wss *chip; | 94 | struct snd_wss *chip; |
95 | struct snd_pcm *pcm; | ||
96 | int error; | 95 | int error; |
97 | 96 | ||
98 | error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card); | 97 | error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card); |
@@ -106,15 +105,15 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n) | |||
106 | 105 | ||
107 | card->private_data = chip; | 106 | card->private_data = chip; |
108 | 107 | ||
109 | error = snd_wss_pcm(chip, 0, &pcm); | 108 | error = snd_wss_pcm(chip, 0); |
110 | if (error < 0) | 109 | if (error < 0) |
111 | goto out; | 110 | goto out; |
112 | 111 | ||
113 | strcpy(card->driver, "CS4231"); | 112 | strcpy(card->driver, "CS4231"); |
114 | strcpy(card->shortname, pcm->name); | 113 | strcpy(card->shortname, chip->pcm->name); |
115 | 114 | ||
116 | sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", | 115 | sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", |
117 | pcm->name, chip->port, irq[n], dma1[n]); | 116 | chip->pcm->name, chip->port, irq[n], dma1[n]); |
118 | if (dma2[n] >= 0) | 117 | if (dma2[n] >= 0) |
119 | sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]); | 118 | sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]); |
120 | 119 | ||
@@ -122,7 +121,7 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n) | |||
122 | if (error < 0) | 121 | if (error < 0) |
123 | goto out; | 122 | goto out; |
124 | 123 | ||
125 | error = snd_wss_timer(chip, 0, NULL); | 124 | error = snd_wss_timer(chip, 0); |
126 | if (error < 0) | 125 | if (error < 0) |
127 | goto out; | 126 | goto out; |
128 | 127 | ||
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 750f51c904fc..9d7582c90a95 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c | |||
@@ -382,7 +382,6 @@ static int snd_cs423x_card_new(struct device *pdev, int dev, | |||
382 | static int snd_cs423x_probe(struct snd_card *card, int dev) | 382 | static int snd_cs423x_probe(struct snd_card *card, int dev) |
383 | { | 383 | { |
384 | struct snd_card_cs4236 *acard; | 384 | struct snd_card_cs4236 *acard; |
385 | struct snd_pcm *pcm; | ||
386 | struct snd_wss *chip; | 385 | struct snd_wss *chip; |
387 | struct snd_opl3 *opl3; | 386 | struct snd_opl3 *opl3; |
388 | int err; | 387 | int err; |
@@ -404,7 +403,7 @@ static int snd_cs423x_probe(struct snd_card *card, int dev) | |||
404 | acard->chip = chip; | 403 | acard->chip = chip; |
405 | if (chip->hardware & WSS_HW_CS4236B_MASK) { | 404 | if (chip->hardware & WSS_HW_CS4236B_MASK) { |
406 | 405 | ||
407 | err = snd_cs4236_pcm(chip, 0, &pcm); | 406 | err = snd_cs4236_pcm(chip, 0); |
408 | if (err < 0) | 407 | if (err < 0) |
409 | return err; | 408 | return err; |
410 | 409 | ||
@@ -412,7 +411,7 @@ static int snd_cs423x_probe(struct snd_card *card, int dev) | |||
412 | if (err < 0) | 411 | if (err < 0) |
413 | return err; | 412 | return err; |
414 | } else { | 413 | } else { |
415 | err = snd_wss_pcm(chip, 0, &pcm); | 414 | err = snd_wss_pcm(chip, 0); |
416 | if (err < 0) | 415 | if (err < 0) |
417 | return err; | 416 | return err; |
418 | 417 | ||
@@ -420,17 +419,17 @@ static int snd_cs423x_probe(struct snd_card *card, int dev) | |||
420 | if (err < 0) | 419 | if (err < 0) |
421 | return err; | 420 | return err; |
422 | } | 421 | } |
423 | strcpy(card->driver, pcm->name); | 422 | strcpy(card->driver, chip->pcm->name); |
424 | strcpy(card->shortname, pcm->name); | 423 | strcpy(card->shortname, chip->pcm->name); |
425 | sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", | 424 | sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", |
426 | pcm->name, | 425 | chip->pcm->name, |
427 | chip->port, | 426 | chip->port, |
428 | irq[dev], | 427 | irq[dev], |
429 | dma1[dev]); | 428 | dma1[dev]); |
430 | if (dma2[dev] >= 0) | 429 | if (dma2[dev] >= 0) |
431 | sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); | 430 | sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); |
432 | 431 | ||
433 | err = snd_wss_timer(chip, 0, NULL); | 432 | err = snd_wss_timer(chip, 0); |
434 | if (err < 0) | 433 | if (err < 0) |
435 | return err; | 434 | return err; |
436 | 435 | ||
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index c5adca300632..2b7cc596f4c6 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c | |||
@@ -79,7 +79,7 @@ | |||
79 | * | 79 | * |
80 | */ | 80 | */ |
81 | 81 | ||
82 | #include <asm/io.h> | 82 | #include <linux/io.h> |
83 | #include <linux/delay.h> | 83 | #include <linux/delay.h> |
84 | #include <linux/init.h> | 84 | #include <linux/init.h> |
85 | #include <linux/time.h> | 85 | #include <linux/time.h> |
@@ -376,17 +376,14 @@ int snd_cs4236_create(struct snd_card *card, | |||
376 | return 0; | 376 | return 0; |
377 | } | 377 | } |
378 | 378 | ||
379 | int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) | 379 | int snd_cs4236_pcm(struct snd_wss *chip, int device) |
380 | { | 380 | { |
381 | struct snd_pcm *pcm; | ||
382 | int err; | 381 | int err; |
383 | 382 | ||
384 | err = snd_wss_pcm(chip, device, &pcm); | 383 | err = snd_wss_pcm(chip, device); |
385 | if (err < 0) | 384 | if (err < 0) |
386 | return err; | 385 | return err; |
387 | pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX; | 386 | chip->pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX; |
388 | if (rpcm) | ||
389 | *rpcm = pcm; | ||
390 | return 0; | 387 | return 0; |
391 | } | 388 | } |
392 | 389 | ||
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index 76001fe0579d..1901c2bb6c3b 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c | |||
@@ -138,10 +138,9 @@ static int snd_es1688_probe(struct snd_card *card, unsigned int n) | |||
138 | { | 138 | { |
139 | struct snd_es1688 *chip = card->private_data; | 139 | struct snd_es1688 *chip = card->private_data; |
140 | struct snd_opl3 *opl3; | 140 | struct snd_opl3 *opl3; |
141 | struct snd_pcm *pcm; | ||
142 | int error; | 141 | int error; |
143 | 142 | ||
144 | error = snd_es1688_pcm(card, chip, 0, &pcm); | 143 | error = snd_es1688_pcm(card, chip, 0); |
145 | if (error < 0) | 144 | if (error < 0) |
146 | return error; | 145 | return error; |
147 | 146 | ||
@@ -150,9 +149,9 @@ static int snd_es1688_probe(struct snd_card *card, unsigned int n) | |||
150 | return error; | 149 | return error; |
151 | 150 | ||
152 | strlcpy(card->driver, "ES1688", sizeof(card->driver)); | 151 | strlcpy(card->driver, "ES1688", sizeof(card->driver)); |
153 | strlcpy(card->shortname, pcm->name, sizeof(card->shortname)); | 152 | strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname)); |
154 | snprintf(card->longname, sizeof(card->longname), | 153 | snprintf(card->longname, sizeof(card->longname), |
155 | "%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port, | 154 | "%s at 0x%lx, irq %i, dma %i", chip->pcm->name, chip->port, |
156 | chip->irq, chip->dma8); | 155 | chip->irq, chip->dma8); |
157 | 156 | ||
158 | if (fm_port[n] == SNDRV_AUTO_PORT) | 157 | if (fm_port[n] == SNDRV_AUTO_PORT) |
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index b5450143407b..e2cf508841b1 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c | |||
@@ -25,11 +25,11 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/ioport.h> | 26 | #include <linux/ioport.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/io.h> | ||
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
29 | #include <sound/es1688.h> | 30 | #include <sound/es1688.h> |
30 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
31 | 32 | ||
32 | #include <asm/io.h> | ||
33 | #include <asm/dma.h> | 33 | #include <asm/dma.h> |
34 | 34 | ||
35 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 35 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
@@ -728,8 +728,7 @@ static struct snd_pcm_ops snd_es1688_capture_ops = { | |||
728 | .pointer = snd_es1688_capture_pointer, | 728 | .pointer = snd_es1688_capture_pointer, |
729 | }; | 729 | }; |
730 | 730 | ||
731 | int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, | 731 | int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, int device) |
732 | int device, struct snd_pcm **rpcm) | ||
733 | { | 732 | { |
734 | struct snd_pcm *pcm; | 733 | struct snd_pcm *pcm; |
735 | int err; | 734 | int err; |
@@ -749,9 +748,6 @@ int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, | |||
749 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 748 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
750 | snd_dma_isa_data(), | 749 | snd_dma_isa_data(), |
751 | 64*1024, 64*1024); | 750 | 64*1024, 64*1024); |
752 | |||
753 | if (rpcm) | ||
754 | *rpcm = pcm; | ||
755 | return 0; | 751 | return 0; |
756 | } | 752 | } |
757 | 753 | ||
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index b481bb8c31bc..5094b62d8f77 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c | |||
@@ -84,8 +84,8 @@ | |||
84 | #include <linux/isapnp.h> | 84 | #include <linux/isapnp.h> |
85 | #include <linux/module.h> | 85 | #include <linux/module.h> |
86 | #include <linux/delay.h> | 86 | #include <linux/delay.h> |
87 | #include <linux/io.h> | ||
87 | 88 | ||
88 | #include <asm/io.h> | ||
89 | #include <asm/dma.h> | 89 | #include <asm/dma.h> |
90 | #include <sound/core.h> | 90 | #include <sound/core.h> |
91 | #include <sound/control.h> | 91 | #include <sound/control.h> |
@@ -1687,16 +1687,13 @@ static struct snd_pcm_ops snd_es18xx_capture_ops = { | |||
1687 | .pointer = snd_es18xx_capture_pointer, | 1687 | .pointer = snd_es18xx_capture_pointer, |
1688 | }; | 1688 | }; |
1689 | 1689 | ||
1690 | static int snd_es18xx_pcm(struct snd_card *card, int device, | 1690 | static int snd_es18xx_pcm(struct snd_card *card, int device) |
1691 | struct snd_pcm **rpcm) | ||
1692 | { | 1691 | { |
1693 | struct snd_es18xx *chip = card->private_data; | 1692 | struct snd_es18xx *chip = card->private_data; |
1694 | struct snd_pcm *pcm; | 1693 | struct snd_pcm *pcm; |
1695 | char str[16]; | 1694 | char str[16]; |
1696 | int err; | 1695 | int err; |
1697 | 1696 | ||
1698 | if (rpcm) | ||
1699 | *rpcm = NULL; | ||
1700 | sprintf(str, "ES%x", chip->version); | 1697 | sprintf(str, "ES%x", chip->version); |
1701 | if (chip->caps & ES18XX_PCM2) | 1698 | if (chip->caps & ES18XX_PCM2) |
1702 | err = snd_pcm_new(card, str, device, 2, 1, &pcm); | 1699 | err = snd_pcm_new(card, str, device, 2, 1, &pcm); |
@@ -1722,9 +1719,6 @@ static int snd_es18xx_pcm(struct snd_card *card, int device, | |||
1722 | snd_dma_isa_data(), | 1719 | snd_dma_isa_data(), |
1723 | 64*1024, | 1720 | 64*1024, |
1724 | chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024); | 1721 | chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024); |
1725 | |||
1726 | if (rpcm) | ||
1727 | *rpcm = pcm; | ||
1728 | return 0; | 1722 | return 0; |
1729 | } | 1723 | } |
1730 | 1724 | ||
@@ -2154,7 +2148,7 @@ static int snd_audiodrive_probe(struct snd_card *card, int dev) | |||
2154 | chip->port, | 2148 | chip->port, |
2155 | irq[dev], dma1[dev]); | 2149 | irq[dev], dma1[dev]); |
2156 | 2150 | ||
2157 | err = snd_es18xx_pcm(card, 0, NULL); | 2151 | err = snd_es18xx_pcm(card, 0); |
2158 | if (err < 0) | 2152 | if (err < 0) |
2159 | return err; | 2153 | return err; |
2160 | 2154 | ||
diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c index 1eb2b1ec0fd9..32278847884f 100644 --- a/sound/isa/galaxy/galaxy.c +++ b/sound/isa/galaxy/galaxy.c | |||
@@ -569,7 +569,7 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n) | |||
569 | if (err < 0) | 569 | if (err < 0) |
570 | goto error; | 570 | goto error; |
571 | 571 | ||
572 | err = snd_wss_pcm(chip, 0, NULL); | 572 | err = snd_wss_pcm(chip, 0); |
573 | if (err < 0) | 573 | if (err < 0) |
574 | goto error; | 574 | goto error; |
575 | 575 | ||
@@ -577,7 +577,7 @@ static int snd_galaxy_probe(struct device *dev, unsigned int n) | |||
577 | if (err < 0) | 577 | if (err < 0) |
578 | goto error; | 578 | goto error; |
579 | 579 | ||
580 | err = snd_wss_timer(chip, 0, NULL); | 580 | err = snd_wss_timer(chip, 0); |
581 | if (err < 0) | 581 | if (err < 0) |
582 | goto error; | 582 | goto error; |
583 | 583 | ||
diff --git a/sound/isa/gus/gus_instr.c b/sound/isa/gus/gus_instr.c deleted file mode 100644 index 4dc9caf8ddcf..000000000000 --- a/sound/isa/gus/gus_instr.c +++ /dev/null | |||
@@ -1,172 +0,0 @@ | |||
1 | /* | ||
2 | * Routines for Gravis UltraSound soundcards - Synthesizer | ||
3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | ||
4 | * | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/time.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/gus.h> | ||
25 | |||
26 | /* | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | int snd_gus_iwffff_put_sample(void *private_data, struct iwffff_wave *wave, | ||
31 | char __user *data, long len, int atomic) | ||
32 | { | ||
33 | struct snd_gus_card *gus = private_data; | ||
34 | struct snd_gf1_mem_block *block; | ||
35 | int err; | ||
36 | |||
37 | if (wave->format & IWFFFF_WAVE_ROM) | ||
38 | return 0; /* it's probably ok - verify the address? */ | ||
39 | if (wave->format & IWFFFF_WAVE_STEREO) | ||
40 | return -EINVAL; /* not supported */ | ||
41 | block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, | ||
42 | SNDRV_GF1_MEM_OWNER_WAVE_IWFFFF, | ||
43 | NULL, wave->size, | ||
44 | wave->format & IWFFFF_WAVE_16BIT, 1, | ||
45 | wave->share_id); | ||
46 | if (block == NULL) | ||
47 | return -ENOMEM; | ||
48 | err = snd_gus_dram_write(gus, data, | ||
49 | block->ptr, wave->size); | ||
50 | if (err < 0) { | ||
51 | snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0); | ||
52 | snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block); | ||
53 | snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1); | ||
54 | return err; | ||
55 | } | ||
56 | wave->address.memory = block->ptr; | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | int snd_gus_iwffff_get_sample(void *private_data, struct iwffff_wave *wave, | ||
61 | char __user *data, long len, int atomic) | ||
62 | { | ||
63 | struct snd_gus_card *gus = private_data; | ||
64 | |||
65 | return snd_gus_dram_read(gus, data, wave->address.memory, wave->size, | ||
66 | wave->format & IWFFFF_WAVE_ROM ? 1 : 0); | ||
67 | } | ||
68 | |||
69 | int snd_gus_iwffff_remove_sample(void *private_data, struct iwffff_wave *wave, | ||
70 | int atomic) | ||
71 | { | ||
72 | struct snd_gus_card *gus = private_data; | ||
73 | |||
74 | if (wave->format & IWFFFF_WAVE_ROM) | ||
75 | return 0; /* it's probably ok - verify the address? */ | ||
76 | return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory); | ||
77 | } | ||
78 | |||
79 | /* | ||
80 | * | ||
81 | */ | ||
82 | |||
83 | int snd_gus_gf1_put_sample(void *private_data, struct gf1_wave *wave, | ||
84 | char __user *data, long len, int atomic) | ||
85 | { | ||
86 | struct snd_gus_card *gus = private_data; | ||
87 | struct snd_gf1_mem_block *block; | ||
88 | int err; | ||
89 | |||
90 | if (wave->format & GF1_WAVE_STEREO) | ||
91 | return -EINVAL; /* not supported */ | ||
92 | block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, | ||
93 | SNDRV_GF1_MEM_OWNER_WAVE_GF1, | ||
94 | NULL, wave->size, | ||
95 | wave->format & GF1_WAVE_16BIT, 1, | ||
96 | wave->share_id); | ||
97 | if (block == NULL) | ||
98 | return -ENOMEM; | ||
99 | err = snd_gus_dram_write(gus, data, | ||
100 | block->ptr, wave->size); | ||
101 | if (err < 0) { | ||
102 | snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0); | ||
103 | snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block); | ||
104 | snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1); | ||
105 | return err; | ||
106 | } | ||
107 | wave->address.memory = block->ptr; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | int snd_gus_gf1_get_sample(void *private_data, struct gf1_wave *wave, | ||
112 | char __user *data, long len, int atomic) | ||
113 | { | ||
114 | struct snd_gus_card *gus = private_data; | ||
115 | |||
116 | return snd_gus_dram_read(gus, data, wave->address.memory, wave->size, 0); | ||
117 | } | ||
118 | |||
119 | int snd_gus_gf1_remove_sample(void *private_data, struct gf1_wave *wave, | ||
120 | int atomic) | ||
121 | { | ||
122 | struct snd_gus_card *gus = private_data; | ||
123 | |||
124 | return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory); | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * | ||
129 | */ | ||
130 | |||
131 | int snd_gus_simple_put_sample(void *private_data, struct simple_instrument *instr, | ||
132 | char __user *data, long len, int atomic) | ||
133 | { | ||
134 | struct snd_gus_card *gus = private_data; | ||
135 | struct snd_gf1_mem_block *block; | ||
136 | int err; | ||
137 | |||
138 | if (instr->format & SIMPLE_WAVE_STEREO) | ||
139 | return -EINVAL; /* not supported */ | ||
140 | block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, | ||
141 | SNDRV_GF1_MEM_OWNER_WAVE_SIMPLE, | ||
142 | NULL, instr->size, | ||
143 | instr->format & SIMPLE_WAVE_16BIT, 1, | ||
144 | instr->share_id); | ||
145 | if (block == NULL) | ||
146 | return -ENOMEM; | ||
147 | err = snd_gus_dram_write(gus, data, block->ptr, instr->size); | ||
148 | if (err < 0) { | ||
149 | snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0); | ||
150 | snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block); | ||
151 | snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1); | ||
152 | return err; | ||
153 | } | ||
154 | instr->address.memory = block->ptr; | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | int snd_gus_simple_get_sample(void *private_data, struct simple_instrument *instr, | ||
159 | char __user *data, long len, int atomic) | ||
160 | { | ||
161 | struct snd_gus_card *gus = private_data; | ||
162 | |||
163 | return snd_gus_dram_read(gus, data, instr->address.memory, instr->size, 0); | ||
164 | } | ||
165 | |||
166 | int snd_gus_simple_remove_sample(void *private_data, struct simple_instrument *instr, | ||
167 | int atomic) | ||
168 | { | ||
169 | struct snd_gus_card *gus = private_data; | ||
170 | |||
171 | return snd_gf1_mem_free(&gus->gf1.mem_alloc, instr->address.memory); | ||
172 | } | ||
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index 2dcf45bf7293..25f6788ccef3 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c | |||
@@ -849,7 +849,7 @@ static struct snd_pcm_ops snd_gf1_pcm_capture_ops = { | |||
849 | .pointer = snd_gf1_pcm_capture_pointer, | 849 | .pointer = snd_gf1_pcm_capture_pointer, |
850 | }; | 850 | }; |
851 | 851 | ||
852 | int snd_gf1_pcm_new(struct snd_gus_card * gus, int pcm_dev, int control_index, struct snd_pcm ** rpcm) | 852 | int snd_gf1_pcm_new(struct snd_gus_card *gus, int pcm_dev, int control_index) |
853 | { | 853 | { |
854 | struct snd_card *card; | 854 | struct snd_card *card; |
855 | struct snd_kcontrol *kctl; | 855 | struct snd_kcontrol *kctl; |
@@ -857,8 +857,6 @@ int snd_gf1_pcm_new(struct snd_gus_card * gus, int pcm_dev, int control_index, s | |||
857 | struct snd_pcm_substream *substream; | 857 | struct snd_pcm_substream *substream; |
858 | int capture, err; | 858 | int capture, err; |
859 | 859 | ||
860 | if (rpcm) | ||
861 | *rpcm = NULL; | ||
862 | card = gus->card; | 860 | card = gus->card; |
863 | capture = !gus->interwave && !gus->ess_flag && !gus->ace_flag ? 1 : 0; | 861 | capture = !gus->interwave && !gus->ess_flag && !gus->ace_flag ? 1 : 0; |
864 | err = snd_pcm_new(card, | 862 | err = snd_pcm_new(card, |
@@ -903,8 +901,6 @@ int snd_gf1_pcm_new(struct snd_gus_card * gus, int pcm_dev, int control_index, s | |||
903 | return err; | 901 | return err; |
904 | kctl->id.index = control_index; | 902 | kctl->id.index = control_index; |
905 | 903 | ||
906 | if (rpcm) | ||
907 | *rpcm = pcm; | ||
908 | return 0; | 904 | return 0; |
909 | } | 905 | } |
910 | 906 | ||
diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c index 21cc42e4c4be..3992912743f5 100644 --- a/sound/isa/gus/gus_uart.c +++ b/sound/isa/gus/gus_uart.c | |||
@@ -241,13 +241,11 @@ static struct snd_rawmidi_ops snd_gf1_uart_input = | |||
241 | .trigger = snd_gf1_uart_input_trigger, | 241 | .trigger = snd_gf1_uart_input_trigger, |
242 | }; | 242 | }; |
243 | 243 | ||
244 | int snd_gf1_rawmidi_new(struct snd_gus_card * gus, int device, struct snd_rawmidi ** rrawmidi) | 244 | int snd_gf1_rawmidi_new(struct snd_gus_card *gus, int device) |
245 | { | 245 | { |
246 | struct snd_rawmidi *rmidi; | 246 | struct snd_rawmidi *rmidi; |
247 | int err; | 247 | int err; |
248 | 248 | ||
249 | if (rrawmidi) | ||
250 | *rrawmidi = NULL; | ||
251 | if ((err = snd_rawmidi_new(gus->card, "GF1", device, 1, 1, &rmidi)) < 0) | 249 | if ((err = snd_rawmidi_new(gus->card, "GF1", device, 1, 1, &rmidi)) < 0) |
252 | return err; | 250 | return err; |
253 | strcpy(rmidi->name, gus->interwave ? "AMD InterWave" : "GF1"); | 251 | strcpy(rmidi->name, gus->interwave ? "AMD InterWave" : "GF1"); |
@@ -256,7 +254,5 @@ int snd_gf1_rawmidi_new(struct snd_gus_card * gus, int device, struct snd_rawmid | |||
256 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; | 254 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; |
257 | rmidi->private_data = gus; | 255 | rmidi->private_data = gus; |
258 | gus->midi_uart = rmidi; | 256 | gus->midi_uart = rmidi; |
259 | if (rrawmidi) | ||
260 | *rrawmidi = rmidi; | ||
261 | return err; | 257 | return err; |
262 | } | 258 | } |
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 7ce29ffa1af9..f0019715d82e 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c | |||
@@ -181,12 +181,12 @@ static int snd_gusclassic_probe(struct device *dev, unsigned int n) | |||
181 | if (error < 0) | 181 | if (error < 0) |
182 | goto out; | 182 | goto out; |
183 | 183 | ||
184 | error = snd_gf1_pcm_new(gus, 0, 0, NULL); | 184 | error = snd_gf1_pcm_new(gus, 0, 0); |
185 | if (error < 0) | 185 | if (error < 0) |
186 | goto out; | 186 | goto out; |
187 | 187 | ||
188 | if (!gus->ace_flag) { | 188 | if (!gus->ace_flag) { |
189 | error = snd_gf1_rawmidi_new(gus, 0, NULL); | 189 | error = snd_gf1_rawmidi_new(gus, 0); |
190 | if (error < 0) | 190 | if (error < 0) |
191 | goto out; | 191 | goto out; |
192 | } | 192 | } |
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 28a16936a397..693d95f46804 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c | |||
@@ -284,7 +284,7 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n) | |||
284 | } | 284 | } |
285 | gus->codec_flag = 1; | 285 | gus->codec_flag = 1; |
286 | 286 | ||
287 | error = snd_es1688_pcm(card, es1688, 0, NULL); | 287 | error = snd_es1688_pcm(card, es1688, 0); |
288 | if (error < 0) | 288 | if (error < 0) |
289 | goto out; | 289 | goto out; |
290 | 290 | ||
@@ -295,7 +295,7 @@ static int snd_gusextreme_probe(struct device *dev, unsigned int n) | |||
295 | snd_component_add(card, "ES1688"); | 295 | snd_component_add(card, "ES1688"); |
296 | 296 | ||
297 | if (pcm_channels[n] > 0) { | 297 | if (pcm_channels[n] > 0) { |
298 | error = snd_gf1_pcm_new(gus, 1, 1, NULL); | 298 | error = snd_gf1_pcm_new(gus, 1, 1); |
299 | if (error < 0) | 299 | if (error < 0) |
300 | goto out; | 300 | goto out; |
301 | } | 301 | } |
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index 39df36ca3acb..8216e8d8f017 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c | |||
@@ -309,7 +309,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) | |||
309 | if (err < 0) | 309 | if (err < 0) |
310 | goto _err; | 310 | goto _err; |
311 | 311 | ||
312 | err = snd_wss_pcm(wss, 0, NULL); | 312 | err = snd_wss_pcm(wss, 0); |
313 | if (err < 0) | 313 | if (err < 0) |
314 | goto _err; | 314 | goto _err; |
315 | 315 | ||
@@ -317,19 +317,19 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) | |||
317 | if (err < 0) | 317 | if (err < 0) |
318 | goto _err; | 318 | goto _err; |
319 | 319 | ||
320 | err = snd_wss_timer(wss, 2, NULL); | 320 | err = snd_wss_timer(wss, 2); |
321 | if (err < 0) | 321 | if (err < 0) |
322 | goto _err; | 322 | goto _err; |
323 | 323 | ||
324 | if (pcm_channels[dev] > 0) { | 324 | if (pcm_channels[dev] > 0) { |
325 | if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) | 325 | if ((err = snd_gf1_pcm_new(gus, 1, 1)) < 0) |
326 | goto _err; | 326 | goto _err; |
327 | } | 327 | } |
328 | err = snd_gusmax_mixer(wss); | 328 | err = snd_gusmax_mixer(wss); |
329 | if (err < 0) | 329 | if (err < 0) |
330 | goto _err; | 330 | goto _err; |
331 | 331 | ||
332 | err = snd_gf1_rawmidi_new(gus, 0, NULL); | 332 | err = snd_gf1_rawmidi_new(gus, 0); |
333 | if (err < 0) | 333 | if (err < 0) |
334 | goto _err; | 334 | goto _err; |
335 | 335 | ||
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index ad55e5cb8e94..70d0040484c8 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c | |||
@@ -647,7 +647,6 @@ static int snd_interwave_probe(struct snd_card *card, int dev) | |||
647 | #ifdef SNDRV_STB | 647 | #ifdef SNDRV_STB |
648 | struct snd_i2c_bus *i2c_bus; | 648 | struct snd_i2c_bus *i2c_bus; |
649 | #endif | 649 | #endif |
650 | struct snd_pcm *pcm; | ||
651 | char *str; | 650 | char *str; |
652 | int err; | 651 | int err; |
653 | 652 | ||
@@ -695,14 +694,15 @@ static int snd_interwave_probe(struct snd_card *card, int dev) | |||
695 | if (err < 0) | 694 | if (err < 0) |
696 | return err; | 695 | return err; |
697 | 696 | ||
698 | err = snd_wss_pcm(wss, 0, &pcm); | 697 | err = snd_wss_pcm(wss, 0); |
699 | if (err < 0) | 698 | if (err < 0) |
700 | return err; | 699 | return err; |
701 | 700 | ||
702 | sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A'); | 701 | sprintf(wss->pcm->name + strlen(wss->pcm->name), " rev %c", |
703 | strcat(pcm->name, " (codec)"); | 702 | gus->revision + 'A'); |
703 | strcat(wss->pcm->name, " (codec)"); | ||
704 | 704 | ||
705 | err = snd_wss_timer(wss, 2, NULL); | 705 | err = snd_wss_timer(wss, 2); |
706 | if (err < 0) | 706 | if (err < 0) |
707 | return err; | 707 | return err; |
708 | 708 | ||
@@ -711,7 +711,7 @@ static int snd_interwave_probe(struct snd_card *card, int dev) | |||
711 | return err; | 711 | return err; |
712 | 712 | ||
713 | if (pcm_channels[dev] > 0) { | 713 | if (pcm_channels[dev] > 0) { |
714 | err = snd_gf1_pcm_new(gus, 1, 1, NULL); | 714 | err = snd_gf1_pcm_new(gus, 1, 1); |
715 | if (err < 0) | 715 | if (err < 0) |
716 | return err; | 716 | return err; |
717 | } | 717 | } |
@@ -740,7 +740,7 @@ static int snd_interwave_probe(struct snd_card *card, int dev) | |||
740 | #endif | 740 | #endif |
741 | 741 | ||
742 | gus->uart_enable = midi[dev]; | 742 | gus->uart_enable = midi[dev]; |
743 | if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) | 743 | if ((err = snd_gf1_rawmidi_new(gus, 0)) < 0) |
744 | return err; | 744 | return err; |
745 | 745 | ||
746 | #ifndef SNDRV_STB | 746 | #ifndef SNDRV_STB |
diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c index 1cee18fb28a8..835d4aa26761 100644 --- a/sound/isa/msnd/msnd.c +++ b/sound/isa/msnd/msnd.c | |||
@@ -679,8 +679,7 @@ static struct snd_pcm_ops snd_msnd_capture_ops = { | |||
679 | }; | 679 | }; |
680 | 680 | ||
681 | 681 | ||
682 | int snd_msnd_pcm(struct snd_card *card, int device, | 682 | int snd_msnd_pcm(struct snd_card *card, int device) |
683 | struct snd_pcm **rpcm) | ||
684 | { | 683 | { |
685 | struct snd_msnd *chip = card->private_data; | 684 | struct snd_msnd *chip = card->private_data; |
686 | struct snd_pcm *pcm; | 685 | struct snd_pcm *pcm; |
@@ -696,9 +695,6 @@ int snd_msnd_pcm(struct snd_card *card, int device, | |||
696 | pcm->private_data = chip; | 695 | pcm->private_data = chip; |
697 | strcpy(pcm->name, "Hurricane"); | 696 | strcpy(pcm->name, "Hurricane"); |
698 | 697 | ||
699 | |||
700 | if (rpcm) | ||
701 | *rpcm = pcm; | ||
702 | return 0; | 698 | return 0; |
703 | } | 699 | } |
704 | EXPORT_SYMBOL(snd_msnd_pcm); | 700 | EXPORT_SYMBOL(snd_msnd_pcm); |
diff --git a/sound/isa/msnd/msnd.h b/sound/isa/msnd/msnd.h index dbac3a42347b..5f3c7dcd9f9d 100644 --- a/sound/isa/msnd/msnd.h +++ b/sound/isa/msnd/msnd.h | |||
@@ -297,7 +297,7 @@ int snd_msnd_disable_irq(struct snd_msnd *chip); | |||
297 | void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file); | 297 | void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file); |
298 | int snd_msnd_DAPQ(struct snd_msnd *chip, int start); | 298 | int snd_msnd_DAPQ(struct snd_msnd *chip, int start); |
299 | int snd_msnd_DARQ(struct snd_msnd *chip, int start); | 299 | int snd_msnd_DARQ(struct snd_msnd *chip, int start); |
300 | int snd_msnd_pcm(struct snd_card *card, int device, struct snd_pcm **rpcm); | 300 | int snd_msnd_pcm(struct snd_card *card, int device); |
301 | 301 | ||
302 | int snd_msndmidi_new(struct snd_card *card, int device); | 302 | int snd_msndmidi_new(struct snd_card *card, int device); |
303 | void snd_msndmidi_input_read(void *mpu); | 303 | void snd_msndmidi_input_read(void *mpu); |
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 5016bf957f51..4c072666115d 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c | |||
@@ -582,7 +582,7 @@ static int snd_msnd_attach(struct snd_card *card) | |||
582 | if (err < 0) | 582 | if (err < 0) |
583 | goto err_release_region; | 583 | goto err_release_region; |
584 | 584 | ||
585 | err = snd_msnd_pcm(card, 0, NULL); | 585 | err = snd_msnd_pcm(card, 0); |
586 | if (err < 0) { | 586 | if (err < 0) { |
587 | printk(KERN_ERR LOGNAME ": error creating new PCM device\n"); | 587 | printk(KERN_ERR LOGNAME ": error creating new PCM device\n"); |
588 | goto err_release_region; | 588 | goto err_release_region; |
@@ -627,8 +627,7 @@ static int snd_msnd_attach(struct snd_card *card) | |||
627 | return 0; | 627 | return 0; |
628 | 628 | ||
629 | err_release_region: | 629 | err_release_region: |
630 | if (chip->mappedbase) | 630 | iounmap(chip->mappedbase); |
631 | iounmap(chip->mappedbase); | ||
632 | release_mem_region(chip->base, BUFFSIZE); | 631 | release_mem_region(chip->base, BUFFSIZE); |
633 | release_region(chip->io, DSP_NUMIO); | 632 | release_region(chip->io, DSP_NUMIO); |
634 | free_irq(chip->irq, chip); | 633 | free_irq(chip->irq, chip); |
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index a219bc37816b..ae133633a420 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/pm.h> | 26 | #include <linux/pm.h> |
27 | #include <linux/pnp.h> | 27 | #include <linux/pnp.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/io.h> | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/wss.h> | 31 | #include <sound/wss.h> |
31 | #include <sound/mpu401.h> | 32 | #include <sound/mpu401.h> |
@@ -33,8 +34,6 @@ | |||
33 | #include <sound/initval.h> | 34 | #include <sound/initval.h> |
34 | #include <sound/tlv.h> | 35 | #include <sound/tlv.h> |
35 | 36 | ||
36 | #include <asm/io.h> | ||
37 | |||
38 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 37 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
39 | MODULE_DESCRIPTION("Yamaha OPL3SA2+"); | 38 | MODULE_DESCRIPTION("Yamaha OPL3SA2+"); |
40 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
@@ -684,7 +683,7 @@ static int snd_opl3sa2_probe(struct snd_card *card, int dev) | |||
684 | return err; | 683 | return err; |
685 | } | 684 | } |
686 | chip->wss = wss; | 685 | chip->wss = wss; |
687 | err = snd_wss_pcm(wss, 0, NULL); | 686 | err = snd_wss_pcm(wss, 0); |
688 | if (err < 0) | 687 | if (err < 0) |
689 | return err; | 688 | return err; |
690 | err = snd_wss_mixer(wss); | 689 | err = snd_wss_mixer(wss); |
@@ -693,7 +692,7 @@ static int snd_opl3sa2_probe(struct snd_card *card, int dev) | |||
693 | err = snd_opl3sa2_mixer(card); | 692 | err = snd_opl3sa2_mixer(card); |
694 | if (err < 0) | 693 | if (err < 0) |
695 | return err; | 694 | return err; |
696 | err = snd_wss_timer(wss, 0, NULL); | 695 | err = snd_wss_timer(wss, 0); |
697 | if (err < 0) | 696 | if (err < 0) |
698 | return err; | 697 | return err; |
699 | if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) { | 698 | if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) { |
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index c2ca681ac51b..3a9067db1a84 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <asm/io.h> | 32 | #include <linux/io.h> |
33 | #include <asm/dma.h> | 33 | #include <asm/dma.h> |
34 | #include <sound/core.h> | 34 | #include <sound/core.h> |
35 | #include <sound/wss.h> | 35 | #include <sound/wss.h> |
@@ -1270,8 +1270,6 @@ static int snd_miro_probe(struct snd_card *card) | |||
1270 | int error; | 1270 | int error; |
1271 | struct snd_miro *miro = card->private_data; | 1271 | struct snd_miro *miro = card->private_data; |
1272 | struct snd_wss *codec; | 1272 | struct snd_wss *codec; |
1273 | struct snd_timer *timer; | ||
1274 | struct snd_pcm *pcm; | ||
1275 | struct snd_rawmidi *rmidi; | 1273 | struct snd_rawmidi *rmidi; |
1276 | 1274 | ||
1277 | if (!miro->res_mc_base) { | 1275 | if (!miro->res_mc_base) { |
@@ -1310,7 +1308,7 @@ static int snd_miro_probe(struct snd_card *card) | |||
1310 | if (error < 0) | 1308 | if (error < 0) |
1311 | return error; | 1309 | return error; |
1312 | 1310 | ||
1313 | error = snd_wss_pcm(codec, 0, &pcm); | 1311 | error = snd_wss_pcm(codec, 0); |
1314 | if (error < 0) | 1312 | if (error < 0) |
1315 | return error; | 1313 | return error; |
1316 | 1314 | ||
@@ -1318,11 +1316,11 @@ static int snd_miro_probe(struct snd_card *card) | |||
1318 | if (error < 0) | 1316 | if (error < 0) |
1319 | return error; | 1317 | return error; |
1320 | 1318 | ||
1321 | error = snd_wss_timer(codec, 0, &timer); | 1319 | error = snd_wss_timer(codec, 0); |
1322 | if (error < 0) | 1320 | if (error < 0) |
1323 | return error; | 1321 | return error; |
1324 | 1322 | ||
1325 | miro->pcm = pcm; | 1323 | miro->pcm = codec->pcm; |
1326 | 1324 | ||
1327 | error = snd_miro_mixer(card, miro); | 1325 | error = snd_miro_mixer(card, miro); |
1328 | if (error < 0) | 1326 | if (error < 0) |
@@ -1356,8 +1354,8 @@ static int snd_miro_probe(struct snd_card *card) | |||
1356 | 1354 | ||
1357 | strcpy(card->driver, "miro"); | 1355 | strcpy(card->driver, "miro"); |
1358 | sprintf(card->longname, "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d", | 1356 | sprintf(card->longname, "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d", |
1359 | card->shortname, miro->name, pcm->name, miro->wss_base + 4, | 1357 | card->shortname, miro->name, codec->pcm->name, |
1360 | miro->irq, miro->dma1, miro->dma2); | 1358 | miro->wss_base + 4, miro->irq, miro->dma1, miro->dma2); |
1361 | 1359 | ||
1362 | if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) | 1360 | if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) |
1363 | rmidi = NULL; | 1361 | rmidi = NULL; |
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index c9b582848603..0a5266003786 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/pnp.h> | 30 | #include <linux/pnp.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <asm/io.h> | 32 | #include <linux/io.h> |
33 | #include <asm/dma.h> | 33 | #include <asm/dma.h> |
34 | #include <sound/core.h> | 34 | #include <sound/core.h> |
35 | #include <sound/tlv.h> | 35 | #include <sound/tlv.h> |
@@ -820,10 +820,6 @@ static int snd_opti9xx_probe(struct snd_card *card) | |||
820 | int xdma2; | 820 | int xdma2; |
821 | struct snd_opti9xx *chip = card->private_data; | 821 | struct snd_opti9xx *chip = card->private_data; |
822 | struct snd_wss *codec; | 822 | struct snd_wss *codec; |
823 | #ifdef CS4231 | ||
824 | struct snd_timer *timer; | ||
825 | #endif | ||
826 | struct snd_pcm *pcm; | ||
827 | struct snd_rawmidi *rmidi; | 823 | struct snd_rawmidi *rmidi; |
828 | struct snd_hwdep *synth; | 824 | struct snd_hwdep *synth; |
829 | 825 | ||
@@ -855,7 +851,7 @@ static int snd_opti9xx_probe(struct snd_card *card) | |||
855 | if (error < 0) | 851 | if (error < 0) |
856 | return error; | 852 | return error; |
857 | chip->codec = codec; | 853 | chip->codec = codec; |
858 | error = snd_wss_pcm(codec, 0, &pcm); | 854 | error = snd_wss_pcm(codec, 0); |
859 | if (error < 0) | 855 | if (error < 0) |
860 | return error; | 856 | return error; |
861 | error = snd_wss_mixer(codec); | 857 | error = snd_wss_mixer(codec); |
@@ -867,7 +863,7 @@ static int snd_opti9xx_probe(struct snd_card *card) | |||
867 | return error; | 863 | return error; |
868 | #endif | 864 | #endif |
869 | #ifdef CS4231 | 865 | #ifdef CS4231 |
870 | error = snd_wss_timer(codec, 0, &timer); | 866 | error = snd_wss_timer(codec, 0); |
871 | if (error < 0) | 867 | if (error < 0) |
872 | return error; | 868 | return error; |
873 | #endif | 869 | #endif |
@@ -884,11 +880,12 @@ static int snd_opti9xx_probe(struct snd_card *card) | |||
884 | sprintf(card->shortname, "OPTi %s", card->driver); | 880 | sprintf(card->shortname, "OPTi %s", card->driver); |
885 | #if defined(CS4231) || defined(OPTi93X) | 881 | #if defined(CS4231) || defined(OPTi93X) |
886 | sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", | 882 | sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", |
887 | card->shortname, pcm->name, | 883 | card->shortname, codec->pcm->name, |
888 | chip->wss_base + 4, irq, dma1, xdma2); | 884 | chip->wss_base + 4, irq, dma1, xdma2); |
889 | #else | 885 | #else |
890 | sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", | 886 | sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", |
891 | card->shortname, pcm->name, chip->wss_base + 4, irq, dma1); | 887 | card->shortname, codec->pcm->name, chip->wss_base + 4, irq, |
888 | dma1); | ||
892 | #endif /* CS4231 || OPTi93X */ | 889 | #endif /* CS4231 || OPTi93X */ |
893 | 890 | ||
894 | if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) | 891 | if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) |
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index 45fcdff611f9..94c411299e5a 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c | |||
@@ -26,11 +26,11 @@ | |||
26 | #include <linux/ioport.h> | 26 | #include <linux/ioport.h> |
27 | #include <linux/export.h> | 27 | #include <linux/export.h> |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/io.h> | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/emu8000.h> | 31 | #include <sound/emu8000.h> |
31 | #include <sound/emu8000_reg.h> | 32 | #include <sound/emu8000_reg.h> |
32 | #include <asm/io.h> | 33 | #include <linux/uaccess.h> |
33 | #include <asm/uaccess.h> | ||
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <sound/control.h> | 35 | #include <sound/control.h> |
36 | #include <sound/initval.h> | 36 | #include <sound/initval.h> |
@@ -378,13 +378,12 @@ init_arrays(struct snd_emu8000 *emu) | |||
378 | static void | 378 | static void |
379 | size_dram(struct snd_emu8000 *emu) | 379 | size_dram(struct snd_emu8000 *emu) |
380 | { | 380 | { |
381 | int i, size, detected_size; | 381 | int i, size; |
382 | 382 | ||
383 | if (emu->dram_checked) | 383 | if (emu->dram_checked) |
384 | return; | 384 | return; |
385 | 385 | ||
386 | size = 0; | 386 | size = 0; |
387 | detected_size = 0; | ||
388 | 387 | ||
389 | /* write out a magic number */ | 388 | /* write out a magic number */ |
390 | snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE); | 389 | snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE); |
@@ -392,10 +391,19 @@ size_dram(struct snd_emu8000 *emu) | |||
392 | EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET); | 391 | EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET); |
393 | EMU8000_SMLD_WRITE(emu, UNIQUE_ID1); | 392 | EMU8000_SMLD_WRITE(emu, UNIQUE_ID1); |
394 | snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */ | 393 | snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */ |
394 | snd_emu8000_write_wait(emu); | ||
395 | 395 | ||
396 | while (size < EMU8000_MAX_DRAM) { | 396 | /* |
397 | * Detect first 512 KiB. If a write succeeds at the beginning of a | ||
398 | * 512 KiB page we assume that the whole page is there. | ||
399 | */ | ||
400 | EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET); | ||
401 | EMU8000_SMLD_READ(emu); /* discard stale data */ | ||
402 | if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1) | ||
403 | goto skip_detect; /* No RAM */ | ||
404 | snd_emu8000_read_wait(emu); | ||
397 | 405 | ||
398 | size += 512 * 1024; /* increment 512kbytes */ | 406 | for (size = 512 * 1024; size < EMU8000_MAX_DRAM; size += 512 * 1024) { |
399 | 407 | ||
400 | /* Write a unique data on the test address. | 408 | /* Write a unique data on the test address. |
401 | * if the address is out of range, the data is written on | 409 | * if the address is out of range, the data is written on |
@@ -431,18 +439,9 @@ size_dram(struct snd_emu8000 *emu) | |||
431 | snd_emu8000_read_wait(emu); | 439 | snd_emu8000_read_wait(emu); |
432 | 440 | ||
433 | /* Otherwise, it's valid memory. */ | 441 | /* Otherwise, it's valid memory. */ |
434 | detected_size = size + 512 * 1024; | ||
435 | } | ||
436 | |||
437 | /* Distinguish 512 KiB from 0. */ | ||
438 | if (detected_size == 0) { | ||
439 | snd_emu8000_read_wait(emu); | ||
440 | EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET); | ||
441 | EMU8000_SMLD_READ(emu); /* discard stale data */ | ||
442 | if (EMU8000_SMLD_READ(emu) == UNIQUE_ID1) | ||
443 | detected_size = 512 * 1024; | ||
444 | } | 442 | } |
445 | 443 | ||
444 | skip_detect: | ||
446 | /* wait until FULL bit in SMAxW register is false */ | 445 | /* wait until FULL bit in SMAxW register is false */ |
447 | for (i = 0; i < 10000; i++) { | 446 | for (i = 0; i < 10000; i++) { |
448 | if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0) | 447 | if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0) |
@@ -454,10 +453,10 @@ size_dram(struct snd_emu8000 *emu) | |||
454 | snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE); | 453 | snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE); |
455 | snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE); | 454 | snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE); |
456 | 455 | ||
457 | snd_printdd("EMU8000 [0x%lx]: %d Kb on-board memory detected\n", | 456 | pr_info("EMU8000 [0x%lx]: %d KiB on-board DRAM detected\n", |
458 | emu->port1, detected_size/1024); | 457 | emu->port1, size/1024); |
459 | 458 | ||
460 | emu->mem_size = detected_size; | 459 | emu->mem_size = size; |
461 | emu->dram_checked = 1; | 460 | emu->dram_checked = 1; |
462 | } | 461 | } |
463 | 462 | ||
diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c index c99c6078be33..71d13c0bb746 100644 --- a/sound/isa/sb/emu8000_patch.c +++ b/sound/isa/sb/emu8000_patch.c | |||
@@ -20,7 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include "emu8000_local.h" | 22 | #include "emu8000_local.h" |
23 | #include <asm/uaccess.h> | 23 | #include <linux/uaccess.h> |
24 | #include <linux/moduleparam.h> | 24 | #include <linux/moduleparam.h> |
25 | 25 | ||
26 | static int emu8000_reset_addr; | 26 | static int emu8000_reset_addr; |
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index 2f85c66f8e38..250fd0006b53 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c | |||
@@ -207,8 +207,7 @@ static void emu8k_pcm_timer_func(unsigned long data) | |||
207 | rec->last_ptr = ptr; | 207 | rec->last_ptr = ptr; |
208 | 208 | ||
209 | /* reprogram timer */ | 209 | /* reprogram timer */ |
210 | rec->timer.expires = jiffies + 1; | 210 | mod_timer(&rec->timer, jiffies + 1); |
211 | add_timer(&rec->timer); | ||
212 | 211 | ||
213 | /* update period */ | 212 | /* update period */ |
214 | if (rec->period_pos >= (int)rec->period_size) { | 213 | if (rec->period_pos >= (int)rec->period_size) { |
@@ -240,9 +239,7 @@ static int emu8k_pcm_open(struct snd_pcm_substream *subs) | |||
240 | runtime->private_data = rec; | 239 | runtime->private_data = rec; |
241 | 240 | ||
242 | spin_lock_init(&rec->timer_lock); | 241 | spin_lock_init(&rec->timer_lock); |
243 | init_timer(&rec->timer); | 242 | setup_timer(&rec->timer, emu8k_pcm_timer_func, (unsigned long)rec); |
244 | rec->timer.function = emu8k_pcm_timer_func; | ||
245 | rec->timer.data = (unsigned long)rec; | ||
246 | 243 | ||
247 | runtime->hw = emu8k_pcm_hw; | 244 | runtime->hw = emu8k_pcm_hw; |
248 | runtime->hw.buffer_bytes_max = emu->mem_size - LOOP_BLANK_SIZE * 3; | 245 | runtime->hw.buffer_bytes_max = emu->mem_size - LOOP_BLANK_SIZE * 3; |
@@ -359,8 +356,7 @@ static void start_voice(struct snd_emu8k_pcm *rec, int ch) | |||
359 | /* start timer */ | 356 | /* start timer */ |
360 | spin_lock_irqsave(&rec->timer_lock, flags); | 357 | spin_lock_irqsave(&rec->timer_lock, flags); |
361 | if (! rec->timer_running) { | 358 | if (! rec->timer_running) { |
362 | rec->timer.expires = jiffies + 1; | 359 | mod_timer(&rec->timer, jiffies + 1); |
363 | add_timer(&rec->timer); | ||
364 | rec->timer_running = 1; | 360 | rec->timer_running = 1; |
365 | } | 361 | } |
366 | spin_unlock_irqrestore(&rec->timer_lock, flags); | 362 | spin_unlock_irqrestore(&rec->timer_lock, flags); |
diff --git a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c index 95b39beb61c1..72332dfada9a 100644 --- a/sound/isa/sb/emu8000_synth.c +++ b/sound/isa/sb/emu8000_synth.c | |||
@@ -103,8 +103,7 @@ static int snd_emu8000_delete_device(struct snd_seq_device *dev) | |||
103 | hw = dev->driver_data; | 103 | hw = dev->driver_data; |
104 | if (hw->pcm) | 104 | if (hw->pcm) |
105 | snd_device_free(dev->card, hw->pcm); | 105 | snd_device_free(dev->card, hw->pcm); |
106 | if (hw->emu) | 106 | snd_emux_free(hw->emu); |
107 | snd_emux_free(hw->emu); | ||
108 | snd_util_memhdr_free(hw->memhdr); | 107 | snd_util_memhdr_free(hw->memhdr); |
109 | hw->emu = NULL; | 108 | hw->emu = NULL; |
110 | hw->memhdr = NULL; | 109 | hw->memhdr = NULL; |
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c index 90d2eba549e9..6b4884d052a5 100644 --- a/sound/isa/sb/jazz16.c +++ b/sound/isa/sb/jazz16.c | |||
@@ -297,7 +297,7 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev) | |||
297 | "Media Vision Jazz16 at 0x%lx, irq %d, dma8 %d, dma16 %d", | 297 | "Media Vision Jazz16 at 0x%lx, irq %d, dma8 %d, dma16 %d", |
298 | port[dev], xirq, xdma8, xdma16); | 298 | port[dev], xirq, xdma8, xdma16); |
299 | 299 | ||
300 | err = snd_sb8dsp_pcm(chip, 0, NULL); | 300 | err = snd_sb8dsp_pcm(chip, 0); |
301 | if (err < 0) | 301 | if (err < 0) |
302 | goto err_free; | 302 | goto err_free; |
303 | err = snd_sbmixer_new(chip); | 303 | err = snd_sbmixer_new(chip); |
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 3f694543a7ea..4a7d7c89808f 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c | |||
@@ -374,7 +374,7 @@ static int snd_sb16_probe(struct snd_card *card, int dev) | |||
374 | if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0) | 374 | if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0) |
375 | return err; | 375 | return err; |
376 | 376 | ||
377 | if ((err = snd_sb16dsp_pcm(chip, 0, &chip->pcm)) < 0) | 377 | if ((err = snd_sb16dsp_pcm(chip, 0)) < 0) |
378 | return err; | 378 | return err; |
379 | 379 | ||
380 | strcpy(card->driver, | 380 | strcpy(card->driver, |
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index 72b10f4f3e70..8b2d6c6bfe97 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c | |||
@@ -33,7 +33,7 @@ | |||
33 | * | 33 | * |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #include <asm/io.h> | 36 | #include <linux/io.h> |
37 | #include <asm/dma.h> | 37 | #include <asm/dma.h> |
38 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | #include <linux/time.h> | 39 | #include <linux/time.h> |
@@ -860,19 +860,18 @@ static struct snd_pcm_ops snd_sb16_capture_ops = { | |||
860 | .pointer = snd_sb16_capture_pointer, | 860 | .pointer = snd_sb16_capture_pointer, |
861 | }; | 861 | }; |
862 | 862 | ||
863 | int snd_sb16dsp_pcm(struct snd_sb * chip, int device, struct snd_pcm ** rpcm) | 863 | int snd_sb16dsp_pcm(struct snd_sb *chip, int device) |
864 | { | 864 | { |
865 | struct snd_card *card = chip->card; | 865 | struct snd_card *card = chip->card; |
866 | struct snd_pcm *pcm; | 866 | struct snd_pcm *pcm; |
867 | int err; | 867 | int err; |
868 | 868 | ||
869 | if (rpcm) | ||
870 | *rpcm = NULL; | ||
871 | if ((err = snd_pcm_new(card, "SB16 DSP", device, 1, 1, &pcm)) < 0) | 869 | if ((err = snd_pcm_new(card, "SB16 DSP", device, 1, 1, &pcm)) < 0) |
872 | return err; | 870 | return err; |
873 | sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff); | 871 | sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff); |
874 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; | 872 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; |
875 | pcm->private_data = chip; | 873 | pcm->private_data = chip; |
874 | chip->pcm = pcm; | ||
876 | 875 | ||
877 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb16_playback_ops); | 876 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb16_playback_ops); |
878 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb16_capture_ops); | 877 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb16_capture_ops); |
@@ -885,9 +884,6 @@ int snd_sb16dsp_pcm(struct snd_sb * chip, int device, struct snd_pcm ** rpcm) | |||
885 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 884 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
886 | snd_dma_isa_data(), | 885 | snd_dma_isa_data(), |
887 | 64*1024, 128*1024); | 886 | 64*1024, 128*1024); |
888 | |||
889 | if (rpcm) | ||
890 | *rpcm = pcm; | ||
891 | return 0; | 887 | return 0; |
892 | } | 888 | } |
893 | 889 | ||
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index 6c32b3aa34af..b8e2391c33ff 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c | |||
@@ -157,7 +157,7 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev) | |||
157 | goto _err; | 157 | goto _err; |
158 | } | 158 | } |
159 | 159 | ||
160 | if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) | 160 | if ((err = snd_sb8dsp_pcm(chip, 0)) < 0) |
161 | goto _err; | 161 | goto _err; |
162 | 162 | ||
163 | if ((err = snd_sbmixer_new(chip)) < 0) | 163 | if ((err = snd_sbmixer_new(chip)) < 0) |
@@ -182,7 +182,7 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev) | |||
182 | goto _err; | 182 | goto _err; |
183 | } | 183 | } |
184 | 184 | ||
185 | if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0) | 185 | if ((err = snd_sb8dsp_midi(chip, 0)) < 0) |
186 | goto _err; | 186 | goto _err; |
187 | 187 | ||
188 | strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8"); | 188 | strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8"); |
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index 24d4121ab0e0..9043397fe62f 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c | |||
@@ -30,7 +30,7 @@ | |||
30 | * Cleaned up and rewrote lowlevel routines. | 30 | * Cleaned up and rewrote lowlevel routines. |
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <asm/io.h> | 33 | #include <linux/io.h> |
34 | #include <asm/dma.h> | 34 | #include <asm/dma.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/time.h> | 36 | #include <linux/time.h> |
@@ -594,15 +594,13 @@ static struct snd_pcm_ops snd_sb8_capture_ops = { | |||
594 | .pointer = snd_sb8_capture_pointer, | 594 | .pointer = snd_sb8_capture_pointer, |
595 | }; | 595 | }; |
596 | 596 | ||
597 | int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm) | 597 | int snd_sb8dsp_pcm(struct snd_sb *chip, int device) |
598 | { | 598 | { |
599 | struct snd_card *card = chip->card; | 599 | struct snd_card *card = chip->card; |
600 | struct snd_pcm *pcm; | 600 | struct snd_pcm *pcm; |
601 | int err; | 601 | int err; |
602 | size_t max_prealloc = 64 * 1024; | 602 | size_t max_prealloc = 64 * 1024; |
603 | 603 | ||
604 | if (rpcm) | ||
605 | *rpcm = NULL; | ||
606 | if ((err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm)) < 0) | 604 | if ((err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm)) < 0) |
607 | return err; | 605 | return err; |
608 | sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff); | 606 | sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff); |
@@ -618,8 +616,6 @@ int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm) | |||
618 | snd_dma_isa_data(), | 616 | snd_dma_isa_data(), |
619 | 64*1024, max_prealloc); | 617 | 64*1024, max_prealloc); |
620 | 618 | ||
621 | if (rpcm) | ||
622 | *rpcm = pcm; | ||
623 | return 0; | 619 | return 0; |
624 | } | 620 | } |
625 | 621 | ||
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c index 988a8b73475f..d551c50e549f 100644 --- a/sound/isa/sb/sb8_midi.c +++ b/sound/isa/sb/sb8_midi.c | |||
@@ -26,7 +26,7 @@ | |||
26 | * Added full duplex UART mode for DSP version 2.0 and later. | 26 | * Added full duplex UART mode for DSP version 2.0 and later. |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <asm/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/time.h> | 30 | #include <linux/time.h> |
31 | #include <sound/core.h> | 31 | #include <sound/core.h> |
32 | #include <sound/sb.h> | 32 | #include <sound/sb.h> |
@@ -216,8 +216,7 @@ static void snd_sb8dsp_midi_output_timer(unsigned long data) | |||
216 | unsigned long flags; | 216 | unsigned long flags; |
217 | 217 | ||
218 | spin_lock_irqsave(&chip->open_lock, flags); | 218 | spin_lock_irqsave(&chip->open_lock, flags); |
219 | chip->midi_timer.expires = 1 + jiffies; | 219 | mod_timer(&chip->midi_timer, 1 + jiffies); |
220 | add_timer(&chip->midi_timer); | ||
221 | spin_unlock_irqrestore(&chip->open_lock, flags); | 220 | spin_unlock_irqrestore(&chip->open_lock, flags); |
222 | snd_sb8dsp_midi_output_write(substream); | 221 | snd_sb8dsp_midi_output_write(substream); |
223 | } | 222 | } |
@@ -231,11 +230,10 @@ static void snd_sb8dsp_midi_output_trigger(struct snd_rawmidi_substream *substre | |||
231 | spin_lock_irqsave(&chip->open_lock, flags); | 230 | spin_lock_irqsave(&chip->open_lock, flags); |
232 | if (up) { | 231 | if (up) { |
233 | if (!(chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER)) { | 232 | if (!(chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER)) { |
234 | init_timer(&chip->midi_timer); | 233 | setup_timer(&chip->midi_timer, |
235 | chip->midi_timer.function = snd_sb8dsp_midi_output_timer; | 234 | snd_sb8dsp_midi_output_timer, |
236 | chip->midi_timer.data = (unsigned long) substream; | 235 | (unsigned long) substream); |
237 | chip->midi_timer.expires = 1 + jiffies; | 236 | mod_timer(&chip->midi_timer, 1 + jiffies); |
238 | add_timer(&chip->midi_timer); | ||
239 | chip->open |= SB_OPEN_MIDI_OUTPUT_TRIGGER; | 237 | chip->open |= SB_OPEN_MIDI_OUTPUT_TRIGGER; |
240 | } | 238 | } |
241 | } else { | 239 | } else { |
@@ -263,13 +261,11 @@ static struct snd_rawmidi_ops snd_sb8dsp_midi_input = | |||
263 | .trigger = snd_sb8dsp_midi_input_trigger, | 261 | .trigger = snd_sb8dsp_midi_input_trigger, |
264 | }; | 262 | }; |
265 | 263 | ||
266 | int snd_sb8dsp_midi(struct snd_sb *chip, int device, struct snd_rawmidi ** rrawmidi) | 264 | int snd_sb8dsp_midi(struct snd_sb *chip, int device) |
267 | { | 265 | { |
268 | struct snd_rawmidi *rmidi; | 266 | struct snd_rawmidi *rmidi; |
269 | int err; | 267 | int err; |
270 | 268 | ||
271 | if (rrawmidi) | ||
272 | *rrawmidi = NULL; | ||
273 | if ((err = snd_rawmidi_new(chip->card, "SB8 MIDI", device, 1, 1, &rmidi)) < 0) | 269 | if ((err = snd_rawmidi_new(chip->card, "SB8 MIDI", device, 1, 1, &rmidi)) < 0) |
274 | return err; | 270 | return err; |
275 | strcpy(rmidi->name, "SB8 MIDI"); | 271 | strcpy(rmidi->name, "SB8 MIDI"); |
@@ -280,7 +276,5 @@ int snd_sb8dsp_midi(struct snd_sb *chip, int device, struct snd_rawmidi ** rrawm | |||
280 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; | 276 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; |
281 | rmidi->private_data = chip; | 277 | rmidi->private_data = chip; |
282 | chip->rmidi = rmidi; | 278 | chip->rmidi = rmidi; |
283 | if (rrawmidi) | ||
284 | *rrawmidi = rmidi; | ||
285 | return 0; | 279 | return 0; |
286 | } | 280 | } |
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index f22b4480828e..787a4ade4afd 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c | |||
@@ -26,11 +26,11 @@ | |||
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/io.h> | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/sb.h> | 31 | #include <sound/sb.h> |
31 | #include <sound/initval.h> | 32 | #include <sound/initval.h> |
32 | 33 | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/dma.h> | 34 | #include <asm/dma.h> |
35 | 35 | ||
36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index e403334a19ad..add1d3f99609 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <asm/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/time.h> | 24 | #include <linux/time.h> |
25 | #include <sound/core.h> | 25 | #include <sound/core.h> |
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 15a152eaa2e8..51cfa7615f72 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c | |||
@@ -625,7 +625,7 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev) | |||
625 | if (err < 0) | 625 | if (err < 0) |
626 | goto err_unmap2; | 626 | goto err_unmap2; |
627 | 627 | ||
628 | err = snd_wss_pcm(chip, 0, NULL); | 628 | err = snd_wss_pcm(chip, 0); |
629 | if (err < 0) { | 629 | if (err < 0) { |
630 | snd_printk(KERN_ERR PFX | 630 | snd_printk(KERN_ERR PFX |
631 | "error creating new WSS PCM device\n"); | 631 | "error creating new WSS PCM device\n"); |
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 44405df7d4be..7b248cdf06e2 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/err.h> | 25 | #include <linux/err.h> |
26 | #include <linux/io.h> | ||
26 | #include <linux/isa.h> | 27 | #include <linux/isa.h> |
27 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
28 | #include <linux/firmware.h> | 29 | #include <linux/firmware.h> |
@@ -877,7 +878,6 @@ static int create_ad1845(struct snd_card *card, unsigned port, | |||
877 | codec_type, WSS_HWSHARE_DMA1, &chip); | 878 | codec_type, WSS_HWSHARE_DMA1, &chip); |
878 | if (!err) { | 879 | if (!err) { |
879 | unsigned long flags; | 880 | unsigned long flags; |
880 | struct snd_pcm *pcm; | ||
881 | 881 | ||
882 | if (sscape->type != SSCAPE_VIVO) { | 882 | if (sscape->type != SSCAPE_VIVO) { |
883 | /* | 883 | /* |
@@ -893,7 +893,7 @@ static int create_ad1845(struct snd_card *card, unsigned port, | |||
893 | 893 | ||
894 | } | 894 | } |
895 | 895 | ||
896 | err = snd_wss_pcm(chip, 0, &pcm); | 896 | err = snd_wss_pcm(chip, 0); |
897 | if (err < 0) { | 897 | if (err < 0) { |
898 | snd_printk(KERN_ERR "sscape: No PCM device " | 898 | snd_printk(KERN_ERR "sscape: No PCM device " |
899 | "for AD1845 chip\n"); | 899 | "for AD1845 chip\n"); |
@@ -907,7 +907,7 @@ static int create_ad1845(struct snd_card *card, unsigned port, | |||
907 | goto _error; | 907 | goto _error; |
908 | } | 908 | } |
909 | if (chip->hardware != WSS_HW_AD1848) { | 909 | if (chip->hardware != WSS_HW_AD1848) { |
910 | err = snd_wss_timer(chip, 0, NULL); | 910 | err = snd_wss_timer(chip, 0); |
911 | if (err < 0) { | 911 | if (err < 0) { |
912 | snd_printk(KERN_ERR "sscape: No timer device " | 912 | snd_printk(KERN_ERR "sscape: No timer device " |
913 | "for AD1845 chip\n"); | 913 | "for AD1845 chip\n"); |
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index bfbf38cf9841..a0987a57c8a9 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c | |||
@@ -380,11 +380,11 @@ snd_wavefront_probe (struct snd_card *card, int dev) | |||
380 | return err; | 380 | return err; |
381 | } | 381 | } |
382 | 382 | ||
383 | err = snd_wss_pcm(chip, 0, NULL); | 383 | err = snd_wss_pcm(chip, 0); |
384 | if (err < 0) | 384 | if (err < 0) |
385 | return err; | 385 | return err; |
386 | 386 | ||
387 | err = snd_wss_timer(chip, 0, NULL); | 387 | err = snd_wss_timer(chip, 0); |
388 | if (err < 0) | 388 | if (err < 0) |
389 | return err; | 389 | return err; |
390 | 390 | ||
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c index b77883c7ee76..b5a19708473a 100644 --- a/sound/isa/wavefront/wavefront_fx.c +++ b/sound/isa/wavefront/wavefront_fx.c | |||
@@ -16,7 +16,7 @@ | |||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <asm/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/time.h> | 21 | #include <linux/time.h> |
22 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c index 7dc991682297..8a80fc6a616b 100644 --- a/sound/isa/wavefront/wavefront_midi.c +++ b/sound/isa/wavefront/wavefront_midi.c | |||
@@ -47,7 +47,7 @@ | |||
47 | * | 47 | * |
48 | */ | 48 | */ |
49 | 49 | ||
50 | #include <asm/io.h> | 50 | #include <linux/io.h> |
51 | #include <linux/init.h> | 51 | #include <linux/init.h> |
52 | #include <linux/time.h> | 52 | #include <linux/time.h> |
53 | #include <linux/wait.h> | 53 | #include <linux/wait.h> |
@@ -356,8 +356,7 @@ static void snd_wavefront_midi_output_timer(unsigned long data) | |||
356 | unsigned long flags; | 356 | unsigned long flags; |
357 | 357 | ||
358 | spin_lock_irqsave (&midi->virtual, flags); | 358 | spin_lock_irqsave (&midi->virtual, flags); |
359 | midi->timer.expires = 1 + jiffies; | 359 | mod_timer(&midi->timer, 1 + jiffies); |
360 | add_timer(&midi->timer); | ||
361 | spin_unlock_irqrestore (&midi->virtual, flags); | 360 | spin_unlock_irqrestore (&midi->virtual, flags); |
362 | snd_wavefront_midi_output_write(card); | 361 | snd_wavefront_midi_output_write(card); |
363 | } | 362 | } |
@@ -384,11 +383,10 @@ static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *subs | |||
384 | if (up) { | 383 | if (up) { |
385 | if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) { | 384 | if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) { |
386 | if (!midi->istimer) { | 385 | if (!midi->istimer) { |
387 | init_timer(&midi->timer); | 386 | setup_timer(&midi->timer, |
388 | midi->timer.function = snd_wavefront_midi_output_timer; | 387 | snd_wavefront_midi_output_timer, |
389 | midi->timer.data = (unsigned long) substream->rmidi->card->private_data; | 388 | (unsigned long) substream->rmidi->card->private_data); |
390 | midi->timer.expires = 1 + jiffies; | 389 | mod_timer(&midi->timer, 1 + jiffies); |
391 | add_timer(&midi->timer); | ||
392 | } | 390 | } |
393 | midi->istimer++; | 391 | midi->istimer++; |
394 | midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER; | 392 | midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER; |
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index e5db001363ee..33f5ec14fcfa 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c | |||
@@ -20,7 +20,7 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <asm/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 347bb1bda110..913b731d2236 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c | |||
@@ -31,12 +31,12 @@ | |||
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/ioport.h> | 32 | #include <linux/ioport.h> |
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/io.h> | ||
34 | #include <sound/core.h> | 35 | #include <sound/core.h> |
35 | #include <sound/wss.h> | 36 | #include <sound/wss.h> |
36 | #include <sound/pcm_params.h> | 37 | #include <sound/pcm_params.h> |
37 | #include <sound/tlv.h> | 38 | #include <sound/tlv.h> |
38 | 39 | ||
39 | #include <asm/io.h> | ||
40 | #include <asm/dma.h> | 40 | #include <asm/dma.h> |
41 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
42 | 42 | ||
@@ -1923,7 +1923,7 @@ static struct snd_pcm_ops snd_wss_capture_ops = { | |||
1923 | .pointer = snd_wss_capture_pointer, | 1923 | .pointer = snd_wss_capture_pointer, |
1924 | }; | 1924 | }; |
1925 | 1925 | ||
1926 | int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) | 1926 | int snd_wss_pcm(struct snd_wss *chip, int device) |
1927 | { | 1927 | { |
1928 | struct snd_pcm *pcm; | 1928 | struct snd_pcm *pcm; |
1929 | int err; | 1929 | int err; |
@@ -1949,8 +1949,6 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) | |||
1949 | 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024); | 1949 | 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024); |
1950 | 1950 | ||
1951 | chip->pcm = pcm; | 1951 | chip->pcm = pcm; |
1952 | if (rpcm) | ||
1953 | *rpcm = pcm; | ||
1954 | return 0; | 1952 | return 0; |
1955 | } | 1953 | } |
1956 | EXPORT_SYMBOL(snd_wss_pcm); | 1954 | EXPORT_SYMBOL(snd_wss_pcm); |
@@ -1961,7 +1959,7 @@ static void snd_wss_timer_free(struct snd_timer *timer) | |||
1961 | chip->timer = NULL; | 1959 | chip->timer = NULL; |
1962 | } | 1960 | } |
1963 | 1961 | ||
1964 | int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer) | 1962 | int snd_wss_timer(struct snd_wss *chip, int device) |
1965 | { | 1963 | { |
1966 | struct snd_timer *timer; | 1964 | struct snd_timer *timer; |
1967 | struct snd_timer_id tid; | 1965 | struct snd_timer_id tid; |
@@ -1980,8 +1978,6 @@ int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer) | |||
1980 | timer->private_free = snd_wss_timer_free; | 1978 | timer->private_free = snd_wss_timer_free; |
1981 | timer->hw = snd_wss_timer_table; | 1979 | timer->hw = snd_wss_timer_table; |
1982 | chip->timer = timer; | 1980 | chip->timer = timer; |
1983 | if (rtimer) | ||
1984 | *rtimer = timer; | ||
1985 | return 0; | 1981 | return 0; |
1986 | } | 1982 | } |
1987 | EXPORT_SYMBOL(snd_wss_timer); | 1983 | EXPORT_SYMBOL(snd_wss_timer); |
diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c index 13c214466d3b..1c56bf58eff9 100644 --- a/sound/oss/dmasound/dmasound_atari.c +++ b/sound/oss/dmasound/dmasound_atari.c | |||
@@ -851,7 +851,7 @@ static int __init AtaIrqInit(void) | |||
851 | st_mfp.tim_dt_a = 1; /* Cause interrupt after first event. */ | 851 | st_mfp.tim_dt_a = 1; /* Cause interrupt after first event. */ |
852 | st_mfp.tim_ct_a = 8; /* Turn on event counting. */ | 852 | st_mfp.tim_ct_a = 8; /* Turn on event counting. */ |
853 | /* Register interrupt handler. */ | 853 | /* Register interrupt handler. */ |
854 | if (request_irq(IRQ_MFP_TIMA, AtaInterrupt, IRQ_TYPE_SLOW, "DMA sound", | 854 | if (request_irq(IRQ_MFP_TIMA, AtaInterrupt, 0, "DMA sound", |
855 | AtaInterrupt)) | 855 | AtaInterrupt)) |
856 | return 0; | 856 | return 0; |
857 | st_mfp.int_en_a |= 0x20; /* Turn interrupt on. */ | 857 | st_mfp.int_en_a |= 0x20; /* Turn interrupt on. */ |
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c index c23f9f95bfa5..a8ceef8d1a8d 100644 --- a/sound/oss/msnd_pinnacle.c +++ b/sound/oss/msnd_pinnacle.c | |||
@@ -675,7 +675,7 @@ static void dsp_write_flush(void) | |||
675 | timeout); | 675 | timeout); |
676 | clear_bit(F_WRITEFLUSH, &dev.flags); | 676 | clear_bit(F_WRITEFLUSH, &dev.flags); |
677 | if (!signal_pending(current)) { | 677 | if (!signal_pending(current)) { |
678 | current->state = TASK_INTERRUPTIBLE; | 678 | __set_current_state(TASK_INTERRUPTIBLE); |
679 | schedule_timeout(get_play_delay_jiffies(DAP_BUFF_SIZE)); | 679 | schedule_timeout(get_play_delay_jiffies(DAP_BUFF_SIZE)); |
680 | } | 680 | } |
681 | clear_bit(F_WRITING, &dev.flags); | 681 | clear_bit(F_WRITING, &dev.flags); |
@@ -1288,7 +1288,7 @@ static int __init calibrate_adc(WORD srate) | |||
1288 | & ~0x0001, dev.SMA + SMA_wCurrHostStatusFlags); | 1288 | & ~0x0001, dev.SMA + SMA_wCurrHostStatusFlags); |
1289 | if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && | 1289 | if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && |
1290 | chk_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) { | 1290 | chk_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) { |
1291 | current->state = TASK_INTERRUPTIBLE; | 1291 | __set_current_state(TASK_INTERRUPTIBLE); |
1292 | schedule_timeout(HZ / 3); | 1292 | schedule_timeout(HZ / 3); |
1293 | return 0; | 1293 | return 0; |
1294 | } | 1294 | } |
diff --git a/sound/oss/pss.c b/sound/oss/pss.c index ca0d6e9f49f5..81314f9e2ccb 100644 --- a/sound/oss/pss.c +++ b/sound/oss/pss.c | |||
@@ -1228,7 +1228,7 @@ static void __exit cleanup_pss(void) | |||
1228 | { | 1228 | { |
1229 | if(!pss_no_sound) | 1229 | if(!pss_no_sound) |
1230 | { | 1230 | { |
1231 | if(fw_load && pss_synth) | 1231 | if (fw_load) |
1232 | vfree(pss_synth); | 1232 | vfree(pss_synth); |
1233 | if(pssmss) | 1233 | if(pssmss) |
1234 | unload_pss_mss(&cfg2); | 1234 | unload_pss_mss(&cfg2); |
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index a33e8ce8085b..213a416b6e0b 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c | |||
@@ -1654,7 +1654,7 @@ static int drain_dac(struct cs4297a_state *s, int nonblock) | |||
1654 | s->dma_dac.hwptr = s->dma_dac.swptr = hwptr; | 1654 | s->dma_dac.hwptr = s->dma_dac.swptr = hwptr; |
1655 | spin_unlock_irqrestore(&s->lock, flags); | 1655 | spin_unlock_irqrestore(&s->lock, flags); |
1656 | remove_wait_queue(&s->dma_dac.wait, &wait); | 1656 | remove_wait_queue(&s->dma_dac.wait, &wait); |
1657 | current->state = TASK_RUNNING; | 1657 | __set_current_state(TASK_RUNNING); |
1658 | return 0; | 1658 | return 0; |
1659 | } | 1659 | } |
1660 | 1660 | ||
diff --git a/sound/oss/trix.c b/sound/oss/trix.c index 944e0c015485..3c494dc93b93 100644 --- a/sound/oss/trix.c +++ b/sound/oss/trix.c | |||
@@ -487,7 +487,7 @@ static int __init init_trix(void) | |||
487 | 487 | ||
488 | static void __exit cleanup_trix(void) | 488 | static void __exit cleanup_trix(void) |
489 | { | 489 | { |
490 | if (fw_load && trix_boot) | 490 | if (fw_load) |
491 | vfree(trix_boot); | 491 | vfree(trix_boot); |
492 | if (sb) | 492 | if (sb) |
493 | unload_trix_sb(&cfg2); | 493 | unload_trix_sb(&cfg2); |
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 29604a239c44..99b64cb3cef8 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/interrupt.h> | 44 | #include <linux/interrupt.h> |
45 | #include <linux/spinlock.h> | 45 | #include <linux/spinlock.h> |
46 | #include <linux/dma-mapping.h> | 46 | #include <linux/dma-mapping.h> |
47 | #include <linux/io.h> | ||
47 | 48 | ||
48 | #include <sound/core.h> | 49 | #include <sound/core.h> |
49 | #include <sound/pcm.h> | 50 | #include <sound/pcm.h> |
@@ -52,7 +53,6 @@ | |||
52 | #include <sound/initval.h> | 53 | #include <sound/initval.h> |
53 | #include <sound/info.h> | 54 | #include <sound/info.h> |
54 | 55 | ||
55 | #include <asm/io.h> | ||
56 | #include <asm/hardware.h> | 56 | #include <asm/hardware.h> |
57 | #include <asm/parisc-device.h> | 57 | #include <asm/parisc-device.h> |
58 | 58 | ||
@@ -893,9 +893,7 @@ snd_harmony_free(struct snd_harmony *h) | |||
893 | if (h->irq >= 0) | 893 | if (h->irq >= 0) |
894 | free_irq(h->irq, h); | 894 | free_irq(h->irq, h); |
895 | 895 | ||
896 | if (h->iobase) | 896 | iounmap(h->iobase); |
897 | iounmap(h->iobase); | ||
898 | |||
899 | kfree(h); | 897 | kfree(h); |
900 | return 0; | 898 | return 0; |
901 | } | 899 | } |
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 50dd0086cfb1..edfc1b8d553e 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -793,6 +793,15 @@ config SND_RME9652 | |||
793 | To compile this driver as a module, choose M here: the module | 793 | To compile this driver as a module, choose M here: the module |
794 | will be called snd-rme9652. | 794 | will be called snd-rme9652. |
795 | 795 | ||
796 | config SND_SE6X | ||
797 | tristate "Studio Evolution SE6X" | ||
798 | depends on SND_OXYGEN=n && SND_VIRTUOSO=n # PCI ID conflict | ||
799 | select SND_OXYGEN_LIB | ||
800 | select SND_PCM | ||
801 | select SND_MPU401_UART | ||
802 | help | ||
803 | Say Y or M here only if you actually have this sound card. | ||
804 | |||
796 | config SND_SIS7019 | 805 | config SND_SIS7019 |
797 | tristate "SiS 7019 Audio Accelerator" | 806 | tristate "SiS 7019 Audio Accelerator" |
798 | depends on X86_32 | 807 | depends on X86_32 |
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 1610c38337af..850a8c984c25 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c | |||
@@ -40,14 +40,13 @@ | |||
40 | #include <linux/compiler.h> | 40 | #include <linux/compiler.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/module.h> | 42 | #include <linux/module.h> |
43 | #include <linux/io.h> | ||
43 | 44 | ||
44 | #include <sound/core.h> | 45 | #include <sound/core.h> |
45 | #include <sound/pcm.h> | 46 | #include <sound/pcm.h> |
46 | #include <sound/initval.h> | 47 | #include <sound/initval.h> |
47 | #include <sound/ac97_codec.h> | 48 | #include <sound/ac97_codec.h> |
48 | 49 | ||
49 | #include <asm/io.h> | ||
50 | |||
51 | #include "ad1889.h" | 50 | #include "ad1889.h" |
52 | #include "ac97/ac97_id.h" | 51 | #include "ac97/ac97_id.h" |
53 | 52 | ||
@@ -623,14 +622,11 @@ snd_ad1889_interrupt(int irq, void *dev_id) | |||
623 | } | 622 | } |
624 | 623 | ||
625 | static int | 624 | static int |
626 | snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, struct snd_pcm **rpcm) | 625 | snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device) |
627 | { | 626 | { |
628 | int err; | 627 | int err; |
629 | struct snd_pcm *pcm; | 628 | struct snd_pcm *pcm; |
630 | 629 | ||
631 | if (rpcm) | ||
632 | *rpcm = NULL; | ||
633 | |||
634 | err = snd_pcm_new(chip->card, chip->card->driver, device, 1, 1, &pcm); | 630 | err = snd_pcm_new(chip->card, chip->card->driver, device, 1, 1, &pcm); |
635 | if (err < 0) | 631 | if (err < 0) |
636 | return err; | 632 | return err; |
@@ -658,9 +654,6 @@ snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, struct snd_pcm **rpcm) | |||
658 | return err; | 654 | return err; |
659 | } | 655 | } |
660 | 656 | ||
661 | if (rpcm) | ||
662 | *rpcm = pcm; | ||
663 | |||
664 | return 0; | 657 | return 0; |
665 | } | 658 | } |
666 | 659 | ||
@@ -859,12 +852,9 @@ snd_ad1889_free(struct snd_ad1889 *chip) | |||
859 | free_irq(chip->irq, chip); | 852 | free_irq(chip->irq, chip); |
860 | 853 | ||
861 | skip_hw: | 854 | skip_hw: |
862 | if (chip->iobase) | 855 | iounmap(chip->iobase); |
863 | iounmap(chip->iobase); | ||
864 | |||
865 | pci_release_regions(chip->pci); | 856 | pci_release_regions(chip->pci); |
866 | pci_disable_device(chip->pci); | 857 | pci_disable_device(chip->pci); |
867 | |||
868 | kfree(chip); | 858 | kfree(chip); |
869 | return 0; | 859 | return 0; |
870 | } | 860 | } |
@@ -1016,7 +1006,7 @@ snd_ad1889_probe(struct pci_dev *pci, | |||
1016 | if (err < 0) | 1006 | if (err < 0) |
1017 | goto free_and_ret; | 1007 | goto free_and_ret; |
1018 | 1008 | ||
1019 | err = snd_ad1889_pcm_init(chip, 0, NULL); | 1009 | err = snd_ad1889_pcm_init(chip, 0); |
1020 | if (err < 0) | 1010 | if (err < 0) |
1021 | goto free_and_ret; | 1011 | goto free_and_ret; |
1022 | 1012 | ||
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index af89e42b2160..c8d499575c01 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <asm/io.h> | 28 | #include <linux/io.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
@@ -1873,7 +1873,6 @@ static int snd_ali_mixer(struct snd_ali *codec) | |||
1873 | #ifdef CONFIG_PM_SLEEP | 1873 | #ifdef CONFIG_PM_SLEEP |
1874 | static int ali_suspend(struct device *dev) | 1874 | static int ali_suspend(struct device *dev) |
1875 | { | 1875 | { |
1876 | struct pci_dev *pci = to_pci_dev(dev); | ||
1877 | struct snd_card *card = dev_get_drvdata(dev); | 1876 | struct snd_card *card = dev_get_drvdata(dev); |
1878 | struct snd_ali *chip = card->private_data; | 1877 | struct snd_ali *chip = card->private_data; |
1879 | struct snd_ali_image *im; | 1878 | struct snd_ali_image *im; |
@@ -1914,16 +1913,11 @@ static int ali_suspend(struct device *dev) | |||
1914 | outl(0xffffffff, ALI_REG(chip, ALI_STOP)); | 1913 | outl(0xffffffff, ALI_REG(chip, ALI_STOP)); |
1915 | 1914 | ||
1916 | spin_unlock_irq(&chip->reg_lock); | 1915 | spin_unlock_irq(&chip->reg_lock); |
1917 | |||
1918 | pci_disable_device(pci); | ||
1919 | pci_save_state(pci); | ||
1920 | pci_set_power_state(pci, PCI_D3hot); | ||
1921 | return 0; | 1916 | return 0; |
1922 | } | 1917 | } |
1923 | 1918 | ||
1924 | static int ali_resume(struct device *dev) | 1919 | static int ali_resume(struct device *dev) |
1925 | { | 1920 | { |
1926 | struct pci_dev *pci = to_pci_dev(dev); | ||
1927 | struct snd_card *card = dev_get_drvdata(dev); | 1921 | struct snd_card *card = dev_get_drvdata(dev); |
1928 | struct snd_ali *chip = card->private_data; | 1922 | struct snd_ali *chip = card->private_data; |
1929 | struct snd_ali_image *im; | 1923 | struct snd_ali_image *im; |
@@ -1933,15 +1927,6 @@ static int ali_resume(struct device *dev) | |||
1933 | if (!im) | 1927 | if (!im) |
1934 | return 0; | 1928 | return 0; |
1935 | 1929 | ||
1936 | pci_set_power_state(pci, PCI_D0); | ||
1937 | pci_restore_state(pci); | ||
1938 | if (pci_enable_device(pci) < 0) { | ||
1939 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
1940 | snd_card_disconnect(card); | ||
1941 | return -EIO; | ||
1942 | } | ||
1943 | pci_set_master(pci); | ||
1944 | |||
1945 | spin_lock_irq(&chip->reg_lock); | 1930 | spin_lock_irq(&chip->reg_lock); |
1946 | 1931 | ||
1947 | for (i = 0; i < ALI_CHANNELS; i++) { | 1932 | for (i = 0; i < ALI_CHANNELS; i++) { |
diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 7bb6ac565107..57e034f208dc 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c | |||
@@ -37,8 +37,7 @@ | |||
37 | #include <linux/dma-mapping.h> | 37 | #include <linux/dma-mapping.h> |
38 | #include <linux/interrupt.h> | 38 | #include <linux/interrupt.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | 40 | #include <linux/io.h> | |
41 | #include <asm/io.h> | ||
42 | 41 | ||
43 | #include <sound/core.h> | 42 | #include <sound/core.h> |
44 | #include <sound/control.h> | 43 | #include <sound/control.h> |
@@ -728,35 +727,20 @@ static int snd_als300_create(struct snd_card *card, | |||
728 | #ifdef CONFIG_PM_SLEEP | 727 | #ifdef CONFIG_PM_SLEEP |
729 | static int snd_als300_suspend(struct device *dev) | 728 | static int snd_als300_suspend(struct device *dev) |
730 | { | 729 | { |
731 | struct pci_dev *pci = to_pci_dev(dev); | ||
732 | struct snd_card *card = dev_get_drvdata(dev); | 730 | struct snd_card *card = dev_get_drvdata(dev); |
733 | struct snd_als300 *chip = card->private_data; | 731 | struct snd_als300 *chip = card->private_data; |
734 | 732 | ||
735 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 733 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
736 | snd_pcm_suspend_all(chip->pcm); | 734 | snd_pcm_suspend_all(chip->pcm); |
737 | snd_ac97_suspend(chip->ac97); | 735 | snd_ac97_suspend(chip->ac97); |
738 | |||
739 | pci_disable_device(pci); | ||
740 | pci_save_state(pci); | ||
741 | pci_set_power_state(pci, PCI_D3hot); | ||
742 | return 0; | 736 | return 0; |
743 | } | 737 | } |
744 | 738 | ||
745 | static int snd_als300_resume(struct device *dev) | 739 | static int snd_als300_resume(struct device *dev) |
746 | { | 740 | { |
747 | struct pci_dev *pci = to_pci_dev(dev); | ||
748 | struct snd_card *card = dev_get_drvdata(dev); | 741 | struct snd_card *card = dev_get_drvdata(dev); |
749 | struct snd_als300 *chip = card->private_data; | 742 | struct snd_als300 *chip = card->private_data; |
750 | 743 | ||
751 | pci_set_power_state(pci, PCI_D0); | ||
752 | pci_restore_state(pci); | ||
753 | if (pci_enable_device(pci) < 0) { | ||
754 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
755 | snd_card_disconnect(card); | ||
756 | return -EIO; | ||
757 | } | ||
758 | pci_set_master(pci); | ||
759 | |||
760 | snd_als300_init(chip); | 744 | snd_als300_init(chip); |
761 | snd_ac97_resume(chip->ac97); | 745 | snd_ac97_resume(chip->ac97); |
762 | 746 | ||
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index d3e6424ee656..a3dea464134d 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
@@ -65,7 +65,7 @@ | |||
65 | * - power management? (card can do voice wakeup according to datasheet!!) | 65 | * - power management? (card can do voice wakeup according to datasheet!!) |
66 | */ | 66 | */ |
67 | 67 | ||
68 | #include <asm/io.h> | 68 | #include <linux/io.h> |
69 | #include <linux/init.h> | 69 | #include <linux/init.h> |
70 | #include <linux/pci.h> | 70 | #include <linux/pci.h> |
71 | #include <linux/gameport.h> | 71 | #include <linux/gameport.h> |
@@ -988,7 +988,6 @@ static void snd_card_als4000_remove(struct pci_dev *pci) | |||
988 | #ifdef CONFIG_PM_SLEEP | 988 | #ifdef CONFIG_PM_SLEEP |
989 | static int snd_als4000_suspend(struct device *dev) | 989 | static int snd_als4000_suspend(struct device *dev) |
990 | { | 990 | { |
991 | struct pci_dev *pci = to_pci_dev(dev); | ||
992 | struct snd_card *card = dev_get_drvdata(dev); | 991 | struct snd_card *card = dev_get_drvdata(dev); |
993 | struct snd_card_als4000 *acard = card->private_data; | 992 | struct snd_card_als4000 *acard = card->private_data; |
994 | struct snd_sb *chip = acard->chip; | 993 | struct snd_sb *chip = acard->chip; |
@@ -997,29 +996,15 @@ static int snd_als4000_suspend(struct device *dev) | |||
997 | 996 | ||
998 | snd_pcm_suspend_all(chip->pcm); | 997 | snd_pcm_suspend_all(chip->pcm); |
999 | snd_sbmixer_suspend(chip); | 998 | snd_sbmixer_suspend(chip); |
1000 | |||
1001 | pci_disable_device(pci); | ||
1002 | pci_save_state(pci); | ||
1003 | pci_set_power_state(pci, PCI_D3hot); | ||
1004 | return 0; | 999 | return 0; |
1005 | } | 1000 | } |
1006 | 1001 | ||
1007 | static int snd_als4000_resume(struct device *dev) | 1002 | static int snd_als4000_resume(struct device *dev) |
1008 | { | 1003 | { |
1009 | struct pci_dev *pci = to_pci_dev(dev); | ||
1010 | struct snd_card *card = dev_get_drvdata(dev); | 1004 | struct snd_card *card = dev_get_drvdata(dev); |
1011 | struct snd_card_als4000 *acard = card->private_data; | 1005 | struct snd_card_als4000 *acard = card->private_data; |
1012 | struct snd_sb *chip = acard->chip; | 1006 | struct snd_sb *chip = acard->chip; |
1013 | 1007 | ||
1014 | pci_set_power_state(pci, PCI_D0); | ||
1015 | pci_restore_state(pci); | ||
1016 | if (pci_enable_device(pci) < 0) { | ||
1017 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
1018 | snd_card_disconnect(card); | ||
1019 | return -EIO; | ||
1020 | } | ||
1021 | pci_set_master(pci); | ||
1022 | |||
1023 | snd_als4000_configure(chip); | 1008 | snd_als4000_configure(chip); |
1024 | snd_sbdsp_reset(chip); | 1009 | snd_sbdsp_reset(chip); |
1025 | snd_sbmixer_resume(chip); | 1010 | snd_sbmixer_resume(chip); |
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index e9273fb2a505..e5cd7be85355 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c | |||
@@ -540,9 +540,8 @@ static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream * | |||
540 | expiry = HZ / 200; | 540 | expiry = HZ / 200; |
541 | 541 | ||
542 | expiry = max(expiry, 1); /* don't let it be zero! */ | 542 | expiry = max(expiry, 1); /* don't let it be zero! */ |
543 | dpcm->timer.expires = jiffies + expiry; | 543 | mod_timer(&dpcm->timer, jiffies + expiry); |
544 | dpcm->respawn_timer = 1; | 544 | dpcm->respawn_timer = 1; |
545 | add_timer(&dpcm->timer); | ||
546 | } | 545 | } |
547 | 546 | ||
548 | static void snd_card_asihpi_pcm_timer_stop(struct snd_pcm_substream *substream) | 547 | static void snd_card_asihpi_pcm_timer_stop(struct snd_pcm_substream *substream) |
@@ -1064,9 +1063,8 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) | |||
1064 | If internal and other stream playing, can't switch | 1063 | If internal and other stream playing, can't switch |
1065 | */ | 1064 | */ |
1066 | 1065 | ||
1067 | init_timer(&dpcm->timer); | 1066 | setup_timer(&dpcm->timer, snd_card_asihpi_timer_function, |
1068 | dpcm->timer.data = (unsigned long) dpcm; | 1067 | (unsigned long) dpcm); |
1069 | dpcm->timer.function = snd_card_asihpi_timer_function; | ||
1070 | dpcm->substream = substream; | 1068 | dpcm->substream = substream; |
1071 | runtime->private_data = dpcm; | 1069 | runtime->private_data = dpcm; |
1072 | runtime->private_free = snd_card_asihpi_runtime_free; | 1070 | runtime->private_free = snd_card_asihpi_runtime_free; |
@@ -1246,9 +1244,8 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream) | |||
1246 | if (err) | 1244 | if (err) |
1247 | return -EIO; | 1245 | return -EIO; |
1248 | 1246 | ||
1249 | init_timer(&dpcm->timer); | 1247 | setup_timer(&dpcm->timer, snd_card_asihpi_timer_function, |
1250 | dpcm->timer.data = (unsigned long) dpcm; | 1248 | (unsigned long) dpcm); |
1251 | dpcm->timer.function = snd_card_asihpi_timer_function; | ||
1252 | dpcm->substream = substream; | 1249 | dpcm->substream = substream; |
1253 | runtime->private_data = dpcm; | 1250 | runtime->private_data = dpcm; |
1254 | runtime->private_free = snd_card_asihpi_runtime_free; | 1251 | runtime->private_free = snd_card_asihpi_runtime_free; |
@@ -2832,14 +2829,11 @@ static int snd_asihpi_hpi_ioctl(struct snd_hwdep *hw, struct file *file, | |||
2832 | /* results in /dev/snd/hwC#D0 file for each card with index # | 2829 | /* results in /dev/snd/hwC#D0 file for each card with index # |
2833 | also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card' | 2830 | also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card' |
2834 | */ | 2831 | */ |
2835 | static int snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi, | 2832 | static int snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi, int device) |
2836 | int device, struct snd_hwdep **rhwdep) | ||
2837 | { | 2833 | { |
2838 | struct snd_hwdep *hw; | 2834 | struct snd_hwdep *hw; |
2839 | int err; | 2835 | int err; |
2840 | 2836 | ||
2841 | if (rhwdep) | ||
2842 | *rhwdep = NULL; | ||
2843 | err = snd_hwdep_new(asihpi->card, "HPI", device, &hw); | 2837 | err = snd_hwdep_new(asihpi->card, "HPI", device, &hw); |
2844 | if (err < 0) | 2838 | if (err < 0) |
2845 | return err; | 2839 | return err; |
@@ -2849,8 +2843,6 @@ static int snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi, | |||
2849 | hw->ops.ioctl = snd_asihpi_hpi_ioctl; | 2843 | hw->ops.ioctl = snd_asihpi_hpi_ioctl; |
2850 | hw->ops.release = snd_asihpi_hpi_release; | 2844 | hw->ops.release = snd_asihpi_hpi_release; |
2851 | hw->private_data = asihpi; | 2845 | hw->private_data = asihpi; |
2852 | if (rhwdep) | ||
2853 | *rhwdep = hw; | ||
2854 | return 0; | 2846 | return 0; |
2855 | } | 2847 | } |
2856 | 2848 | ||
@@ -2993,7 +2985,7 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2993 | 2985 | ||
2994 | /* always create, can be enabled or disabled dynamically | 2986 | /* always create, can be enabled or disabled dynamically |
2995 | by enable_hwdep module param*/ | 2987 | by enable_hwdep module param*/ |
2996 | snd_asihpi_hpi_new(asihpi, 0, NULL); | 2988 | snd_asihpi_hpi_new(asihpi, 0); |
2997 | 2989 | ||
2998 | strcpy(card->driver, "ASIHPI"); | 2990 | strcpy(card->driver, "ASIHPI"); |
2999 | 2991 | ||
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c index 2414d7a2239d..2d6364825d4d 100644 --- a/sound/pci/asihpi/hpi6000.c +++ b/sound/pci/asihpi/hpi6000.c | |||
@@ -47,7 +47,7 @@ | |||
47 | 47 | ||
48 | /* operational/messaging errors */ | 48 | /* operational/messaging errors */ |
49 | #define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT 901 | 49 | #define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT 901 |
50 | 50 | #define HPI6000_ERROR_RESP_GET_LEN 902 | |
51 | #define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK 903 | 51 | #define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK 903 |
52 | #define HPI6000_ERROR_MSG_GET_ADR 904 | 52 | #define HPI6000_ERROR_MSG_GET_ADR 904 |
53 | #define HPI6000_ERROR_RESP_GET_ADR 905 | 53 | #define HPI6000_ERROR_RESP_GET_ADR 905 |
@@ -1365,7 +1365,10 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, | |||
1365 | length = hpi_read_word(pdo, HPI_HIF_ADDR(length)); | 1365 | length = hpi_read_word(pdo, HPI_HIF_ADDR(length)); |
1366 | } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout); | 1366 | } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout); |
1367 | if (!timeout) | 1367 | if (!timeout) |
1368 | length = sizeof(struct hpi_response); | 1368 | return HPI6000_ERROR_RESP_GET_LEN; |
1369 | |||
1370 | if (length > phr->size) | ||
1371 | return HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; | ||
1369 | 1372 | ||
1370 | /* get the response */ | 1373 | /* get the response */ |
1371 | p_data = (u32 *)phr; | 1374 | p_data = (u32 *)phr; |
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c index 6aa677e60555..6610bd096fc9 100644 --- a/sound/pci/asihpi/hpioctl.c +++ b/sound/pci/asihpi/hpioctl.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/moduleparam.h> | 30 | #include <linux/moduleparam.h> |
31 | #include <asm/uaccess.h> | 31 | #include <linux/uaccess.h> |
32 | #include <linux/pci.h> | 32 | #include <linux/pci.h> |
33 | #include <linux/stringify.h> | 33 | #include <linux/stringify.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
@@ -153,6 +153,8 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
153 | goto out; | 153 | goto out; |
154 | } | 154 | } |
155 | 155 | ||
156 | res_max_size = min_t(size_t, res_max_size, sizeof(*hr)); | ||
157 | |||
156 | switch (hm->h.function) { | 158 | switch (hm->h.function) { |
157 | case HPI_SUBSYS_CREATE_ADAPTER: | 159 | case HPI_SUBSYS_CREATE_ADAPTER: |
158 | case HPI_ADAPTER_DELETE: | 160 | case HPI_ADAPTER_DELETE: |
@@ -539,10 +541,8 @@ void asihpi_adapter_remove(struct pci_dev *pci_dev) | |||
539 | hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); | 541 | hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); |
540 | 542 | ||
541 | /* unmap PCI memory space, mapped during device init. */ | 543 | /* unmap PCI memory space, mapped during device init. */ |
542 | for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) { | 544 | for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; ++idx) |
543 | if (pci.ap_mem_base[idx]) | 545 | iounmap(pci.ap_mem_base[idx]); |
544 | iounmap(pci.ap_mem_base[idx]); | ||
545 | } | ||
546 | 546 | ||
547 | if (pa->irq) | 547 | if (pa->irq) |
548 | free_irq(pa->irq, pa); | 548 | free_irq(pa->irq, pa); |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 9c1c4452a8ee..d5f15c9bbeda 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <asm/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
@@ -1474,7 +1474,6 @@ static int snd_atiixp_mixer_new(struct atiixp *chip, int clock, | |||
1474 | */ | 1474 | */ |
1475 | static int snd_atiixp_suspend(struct device *dev) | 1475 | static int snd_atiixp_suspend(struct device *dev) |
1476 | { | 1476 | { |
1477 | struct pci_dev *pci = to_pci_dev(dev); | ||
1478 | struct snd_card *card = dev_get_drvdata(dev); | 1477 | struct snd_card *card = dev_get_drvdata(dev); |
1479 | struct atiixp *chip = card->private_data; | 1478 | struct atiixp *chip = card->private_data; |
1480 | int i; | 1479 | int i; |
@@ -1492,29 +1491,15 @@ static int snd_atiixp_suspend(struct device *dev) | |||
1492 | snd_ac97_suspend(chip->ac97[i]); | 1491 | snd_ac97_suspend(chip->ac97[i]); |
1493 | snd_atiixp_aclink_down(chip); | 1492 | snd_atiixp_aclink_down(chip); |
1494 | snd_atiixp_chip_stop(chip); | 1493 | snd_atiixp_chip_stop(chip); |
1495 | |||
1496 | pci_disable_device(pci); | ||
1497 | pci_save_state(pci); | ||
1498 | pci_set_power_state(pci, PCI_D3hot); | ||
1499 | return 0; | 1494 | return 0; |
1500 | } | 1495 | } |
1501 | 1496 | ||
1502 | static int snd_atiixp_resume(struct device *dev) | 1497 | static int snd_atiixp_resume(struct device *dev) |
1503 | { | 1498 | { |
1504 | struct pci_dev *pci = to_pci_dev(dev); | ||
1505 | struct snd_card *card = dev_get_drvdata(dev); | 1499 | struct snd_card *card = dev_get_drvdata(dev); |
1506 | struct atiixp *chip = card->private_data; | 1500 | struct atiixp *chip = card->private_data; |
1507 | int i; | 1501 | int i; |
1508 | 1502 | ||
1509 | pci_set_power_state(pci, PCI_D0); | ||
1510 | pci_restore_state(pci); | ||
1511 | if (pci_enable_device(pci) < 0) { | ||
1512 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
1513 | snd_card_disconnect(card); | ||
1514 | return -EIO; | ||
1515 | } | ||
1516 | pci_set_master(pci); | ||
1517 | |||
1518 | snd_atiixp_aclink_reset(chip); | 1503 | snd_atiixp_aclink_reset(chip); |
1519 | snd_atiixp_chip_start(chip); | 1504 | snd_atiixp_chip_start(chip); |
1520 | 1505 | ||
@@ -1585,8 +1570,7 @@ static int snd_atiixp_free(struct atiixp *chip) | |||
1585 | __hw_end: | 1570 | __hw_end: |
1586 | if (chip->irq >= 0) | 1571 | if (chip->irq >= 0) |
1587 | free_irq(chip->irq, chip); | 1572 | free_irq(chip->irq, chip); |
1588 | if (chip->remap_addr) | 1573 | iounmap(chip->remap_addr); |
1589 | iounmap(chip->remap_addr); | ||
1590 | pci_release_regions(chip->pci); | 1574 | pci_release_regions(chip->pci); |
1591 | pci_disable_device(chip->pci); | 1575 | pci_disable_device(chip->pci); |
1592 | kfree(chip); | 1576 | kfree(chip); |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index b2f63e0727de..0a38e08164ab 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <asm/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
@@ -1120,7 +1120,6 @@ static int snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock) | |||
1120 | */ | 1120 | */ |
1121 | static int snd_atiixp_suspend(struct device *dev) | 1121 | static int snd_atiixp_suspend(struct device *dev) |
1122 | { | 1122 | { |
1123 | struct pci_dev *pci = to_pci_dev(dev); | ||
1124 | struct snd_card *card = dev_get_drvdata(dev); | 1123 | struct snd_card *card = dev_get_drvdata(dev); |
1125 | struct atiixp_modem *chip = card->private_data; | 1124 | struct atiixp_modem *chip = card->private_data; |
1126 | int i; | 1125 | int i; |
@@ -1132,29 +1131,15 @@ static int snd_atiixp_suspend(struct device *dev) | |||
1132 | snd_ac97_suspend(chip->ac97[i]); | 1131 | snd_ac97_suspend(chip->ac97[i]); |
1133 | snd_atiixp_aclink_down(chip); | 1132 | snd_atiixp_aclink_down(chip); |
1134 | snd_atiixp_chip_stop(chip); | 1133 | snd_atiixp_chip_stop(chip); |
1135 | |||
1136 | pci_disable_device(pci); | ||
1137 | pci_save_state(pci); | ||
1138 | pci_set_power_state(pci, PCI_D3hot); | ||
1139 | return 0; | 1134 | return 0; |
1140 | } | 1135 | } |
1141 | 1136 | ||
1142 | static int snd_atiixp_resume(struct device *dev) | 1137 | static int snd_atiixp_resume(struct device *dev) |
1143 | { | 1138 | { |
1144 | struct pci_dev *pci = to_pci_dev(dev); | ||
1145 | struct snd_card *card = dev_get_drvdata(dev); | 1139 | struct snd_card *card = dev_get_drvdata(dev); |
1146 | struct atiixp_modem *chip = card->private_data; | 1140 | struct atiixp_modem *chip = card->private_data; |
1147 | int i; | 1141 | int i; |
1148 | 1142 | ||
1149 | pci_set_power_state(pci, PCI_D0); | ||
1150 | pci_restore_state(pci); | ||
1151 | if (pci_enable_device(pci) < 0) { | ||
1152 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
1153 | snd_card_disconnect(card); | ||
1154 | return -EIO; | ||
1155 | } | ||
1156 | pci_set_master(pci); | ||
1157 | |||
1158 | snd_atiixp_aclink_reset(chip); | 1143 | snd_atiixp_aclink_reset(chip); |
1159 | snd_atiixp_chip_start(chip); | 1144 | snd_atiixp_chip_start(chip); |
1160 | 1145 | ||
@@ -1211,8 +1196,7 @@ static int snd_atiixp_free(struct atiixp_modem *chip) | |||
1211 | __hw_end: | 1196 | __hw_end: |
1212 | if (chip->irq >= 0) | 1197 | if (chip->irq >= 0) |
1213 | free_irq(chip->irq, chip); | 1198 | free_irq(chip->irq, chip); |
1214 | if (chip->remap_addr) | 1199 | iounmap(chip->remap_addr); |
1215 | iounmap(chip->remap_addr); | ||
1216 | pci_release_regions(chip->pci); | 1200 | pci_release_regions(chip->pci); |
1217 | pci_disable_device(chip->pci); | 1201 | pci_disable_device(chip->pci); |
1218 | kfree(chip); | 1202 | kfree(chip); |
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h index 3a8fefefea77..bcc648bf6478 100644 --- a/sound/pci/au88x0/au88x0.h +++ b/sound/pci/au88x0/au88x0.h | |||
@@ -17,9 +17,8 @@ | |||
17 | #ifndef __SOUND_AU88X0_H | 17 | #ifndef __SOUND_AU88X0_H |
18 | #define __SOUND_AU88X0_H | 18 | #define __SOUND_AU88X0_H |
19 | 19 | ||
20 | #ifdef __KERNEL__ | ||
21 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
22 | #include <asm/io.h> | 21 | #include <linux/io.h> |
23 | #include <sound/core.h> | 22 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
25 | #include <sound/rawmidi.h> | 24 | #include <sound/rawmidi.h> |
@@ -27,7 +26,6 @@ | |||
27 | #include <sound/hwdep.h> | 26 | #include <sound/hwdep.h> |
28 | #include <sound/ac97_codec.h> | 27 | #include <sound/ac97_codec.h> |
29 | #include <sound/tlv.h> | 28 | #include <sound/tlv.h> |
30 | #endif | ||
31 | 29 | ||
32 | #ifndef CHIP_AU8820 | 30 | #ifndef CHIP_AU8820 |
33 | #include "au88x0_eq.h" | 31 | #include "au88x0_eq.h" |
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index e1cf01949fda..8d2fee7b33bd 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c | |||
@@ -229,9 +229,7 @@ static int snd_aw2_dev_free(struct snd_device *device) | |||
229 | if (chip->irq >= 0) | 229 | if (chip->irq >= 0) |
230 | free_irq(chip->irq, (void *)chip); | 230 | free_irq(chip->irq, (void *)chip); |
231 | /* release the i/o ports & memory */ | 231 | /* release the i/o ports & memory */ |
232 | if (chip->iobase_virt) | 232 | iounmap(chip->iobase_virt); |
233 | iounmap(chip->iobase_virt); | ||
234 | |||
235 | pci_release_regions(chip->pci); | 233 | pci_release_regions(chip->pci); |
236 | /* disable the PCI entry */ | 234 | /* disable the PCI entry */ |
237 | pci_disable_device(chip->pci); | 235 | pci_disable_device(chip->pci); |
diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c index 6d24e9536777..1d7890459334 100644 --- a/sound/pci/aw2/aw2-saa7146.c +++ b/sound/pci/aw2/aw2-saa7146.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <asm/io.h> | 30 | #include <linux/io.h> |
31 | #include <sound/core.h> | 31 | #include <sound/core.h> |
32 | #include <sound/initval.h> | 32 | #include <sound/initval.h> |
33 | #include <sound/pcm.h> | 33 | #include <sound/pcm.h> |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index fdbb9c05c77b..a40a2b4c8fd7 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -179,7 +179,7 @@ | |||
179 | * - use MMIO (memory-mapped I/O)? Slightly faster access, e.g. for gameport. | 179 | * - use MMIO (memory-mapped I/O)? Slightly faster access, e.g. for gameport. |
180 | */ | 180 | */ |
181 | 181 | ||
182 | #include <asm/io.h> | 182 | #include <linux/io.h> |
183 | #include <linux/init.h> | 183 | #include <linux/init.h> |
184 | #include <linux/bug.h> /* WARN_ONCE */ | 184 | #include <linux/bug.h> /* WARN_ONCE */ |
185 | #include <linux/pci.h> | 185 | #include <linux/pci.h> |
@@ -2694,7 +2694,6 @@ snd_azf3328_resume_ac97(const struct snd_azf3328 *chip) | |||
2694 | static int | 2694 | static int |
2695 | snd_azf3328_suspend(struct device *dev) | 2695 | snd_azf3328_suspend(struct device *dev) |
2696 | { | 2696 | { |
2697 | struct pci_dev *pci = to_pci_dev(dev); | ||
2698 | struct snd_card *card = dev_get_drvdata(dev); | 2697 | struct snd_card *card = dev_get_drvdata(dev); |
2699 | struct snd_azf3328 *chip = card->private_data; | 2698 | struct snd_azf3328 *chip = card->private_data; |
2700 | u16 *saved_regs_ctrl_u16; | 2699 | u16 *saved_regs_ctrl_u16; |
@@ -2720,29 +2719,15 @@ snd_azf3328_suspend(struct device *dev) | |||
2720 | ARRAY_SIZE(chip->saved_regs_mpu), chip->saved_regs_mpu); | 2719 | ARRAY_SIZE(chip->saved_regs_mpu), chip->saved_regs_mpu); |
2721 | snd_azf3328_suspend_regs(chip, chip->opl3_io, | 2720 | snd_azf3328_suspend_regs(chip, chip->opl3_io, |
2722 | ARRAY_SIZE(chip->saved_regs_opl3), chip->saved_regs_opl3); | 2721 | ARRAY_SIZE(chip->saved_regs_opl3), chip->saved_regs_opl3); |
2723 | |||
2724 | pci_disable_device(pci); | ||
2725 | pci_save_state(pci); | ||
2726 | pci_set_power_state(pci, PCI_D3hot); | ||
2727 | return 0; | 2722 | return 0; |
2728 | } | 2723 | } |
2729 | 2724 | ||
2730 | static int | 2725 | static int |
2731 | snd_azf3328_resume(struct device *dev) | 2726 | snd_azf3328_resume(struct device *dev) |
2732 | { | 2727 | { |
2733 | struct pci_dev *pci = to_pci_dev(dev); | ||
2734 | struct snd_card *card = dev_get_drvdata(dev); | 2728 | struct snd_card *card = dev_get_drvdata(dev); |
2735 | const struct snd_azf3328 *chip = card->private_data; | 2729 | const struct snd_azf3328 *chip = card->private_data; |
2736 | 2730 | ||
2737 | pci_set_power_state(pci, PCI_D0); | ||
2738 | pci_restore_state(pci); | ||
2739 | if (pci_enable_device(pci) < 0) { | ||
2740 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
2741 | snd_card_disconnect(card); | ||
2742 | return -EIO; | ||
2743 | } | ||
2744 | pci_set_master(pci); | ||
2745 | |||
2746 | snd_azf3328_resume_regs(chip, chip->saved_regs_game, chip->game_io, | 2731 | snd_azf3328_resume_regs(chip, chip->saved_regs_game, chip->game_io, |
2747 | ARRAY_SIZE(chip->saved_regs_game)); | 2732 | ARRAY_SIZE(chip->saved_regs_game)); |
2748 | snd_azf3328_resume_regs(chip, chip->saved_regs_mpu, chip->mpu_io, | 2733 | snd_azf3328_resume_regs(chip, chip->saved_regs_mpu, chip->mpu_io, |
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 058b9973c09c..5925b7170e25 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/bitops.h> | 29 | #include <linux/bitops.h> |
30 | #include <asm/io.h> | 30 | #include <linux/io.h> |
31 | #include <sound/core.h> | 31 | #include <sound/core.h> |
32 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
33 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
@@ -690,8 +690,7 @@ static int snd_bt87x_free(struct snd_bt87x *chip) | |||
690 | snd_bt87x_stop(chip); | 690 | snd_bt87x_stop(chip); |
691 | if (chip->irq >= 0) | 691 | if (chip->irq >= 0) |
692 | free_irq(chip->irq, chip); | 692 | free_irq(chip->irq, chip); |
693 | if (chip->mmio) | 693 | iounmap(chip->mmio); |
694 | iounmap(chip->mmio); | ||
695 | pci_release_regions(chip->pci); | 694 | pci_release_regions(chip->pci); |
696 | pci_disable_device(chip->pci); | 695 | pci_disable_device(chip->pci); |
697 | kfree(chip); | 696 | kfree(chip); |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 96af33965b51..dd75b7536fa2 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -1910,7 +1910,6 @@ static void snd_ca0106_remove(struct pci_dev *pci) | |||
1910 | #ifdef CONFIG_PM_SLEEP | 1910 | #ifdef CONFIG_PM_SLEEP |
1911 | static int snd_ca0106_suspend(struct device *dev) | 1911 | static int snd_ca0106_suspend(struct device *dev) |
1912 | { | 1912 | { |
1913 | struct pci_dev *pci = to_pci_dev(dev); | ||
1914 | struct snd_card *card = dev_get_drvdata(dev); | 1913 | struct snd_card *card = dev_get_drvdata(dev); |
1915 | struct snd_ca0106 *chip = card->private_data; | 1914 | struct snd_ca0106 *chip = card->private_data; |
1916 | int i; | 1915 | int i; |
@@ -1923,30 +1922,15 @@ static int snd_ca0106_suspend(struct device *dev) | |||
1923 | snd_ca0106_mixer_suspend(chip); | 1922 | snd_ca0106_mixer_suspend(chip); |
1924 | 1923 | ||
1925 | ca0106_stop_chip(chip); | 1924 | ca0106_stop_chip(chip); |
1926 | |||
1927 | pci_disable_device(pci); | ||
1928 | pci_save_state(pci); | ||
1929 | pci_set_power_state(pci, PCI_D3hot); | ||
1930 | return 0; | 1925 | return 0; |
1931 | } | 1926 | } |
1932 | 1927 | ||
1933 | static int snd_ca0106_resume(struct device *dev) | 1928 | static int snd_ca0106_resume(struct device *dev) |
1934 | { | 1929 | { |
1935 | struct pci_dev *pci = to_pci_dev(dev); | ||
1936 | struct snd_card *card = dev_get_drvdata(dev); | 1930 | struct snd_card *card = dev_get_drvdata(dev); |
1937 | struct snd_ca0106 *chip = card->private_data; | 1931 | struct snd_ca0106 *chip = card->private_data; |
1938 | int i; | 1932 | int i; |
1939 | 1933 | ||
1940 | pci_set_power_state(pci, PCI_D0); | ||
1941 | pci_restore_state(pci); | ||
1942 | |||
1943 | if (pci_enable_device(pci) < 0) { | ||
1944 | snd_card_disconnect(card); | ||
1945 | return -EIO; | ||
1946 | } | ||
1947 | |||
1948 | pci_set_master(pci); | ||
1949 | |||
1950 | ca0106_init_chip(chip, 1); | 1934 | ca0106_init_chip(chip, 1); |
1951 | 1935 | ||
1952 | if (chip->details->ac97) | 1936 | if (chip->details->ac97) |
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 68c0eb0a2807..025805cba779 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -70,7 +70,7 @@ | |||
70 | #include <sound/ac97_codec.h> | 70 | #include <sound/ac97_codec.h> |
71 | #include <sound/info.h> | 71 | #include <sound/info.h> |
72 | #include <sound/tlv.h> | 72 | #include <sound/tlv.h> |
73 | #include <asm/io.h> | 73 | #include <linux/io.h> |
74 | 74 | ||
75 | #include "ca0106.h" | 75 | #include "ca0106.h" |
76 | 76 | ||
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c index 4f9c2821bb31..2c5c28adbefd 100644 --- a/sound/pci/ca0106/ca0106_proc.c +++ b/sound/pci/ca0106/ca0106_proc.c | |||
@@ -64,13 +64,13 @@ | |||
64 | #include <linux/init.h> | 64 | #include <linux/init.h> |
65 | #include <linux/interrupt.h> | 65 | #include <linux/interrupt.h> |
66 | #include <linux/moduleparam.h> | 66 | #include <linux/moduleparam.h> |
67 | #include <linux/io.h> | ||
67 | #include <sound/core.h> | 68 | #include <sound/core.h> |
68 | #include <sound/initval.h> | 69 | #include <sound/initval.h> |
69 | #include <sound/pcm.h> | 70 | #include <sound/pcm.h> |
70 | #include <sound/ac97_codec.h> | 71 | #include <sound/ac97_codec.h> |
71 | #include <sound/info.h> | 72 | #include <sound/info.h> |
72 | #include <sound/asoundef.h> | 73 | #include <sound/asoundef.h> |
73 | #include <asm/io.h> | ||
74 | 74 | ||
75 | #include "ca0106.h" | 75 | #include "ca0106.h" |
76 | 76 | ||
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 85ed40339db9..1d0f2cad2f5a 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -20,7 +20,7 @@ | |||
20 | /* Does not work. Warning may block system in capture mode */ | 20 | /* Does not work. Warning may block system in capture mode */ |
21 | /* #define USE_VAR48KRATE */ | 21 | /* #define USE_VAR48KRATE */ |
22 | 22 | ||
23 | #include <asm/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
@@ -3347,7 +3347,6 @@ static unsigned char saved_mixers[] = { | |||
3347 | 3347 | ||
3348 | static int snd_cmipci_suspend(struct device *dev) | 3348 | static int snd_cmipci_suspend(struct device *dev) |
3349 | { | 3349 | { |
3350 | struct pci_dev *pci = to_pci_dev(dev); | ||
3351 | struct snd_card *card = dev_get_drvdata(dev); | 3350 | struct snd_card *card = dev_get_drvdata(dev); |
3352 | struct cmipci *cm = card->private_data; | 3351 | struct cmipci *cm = card->private_data; |
3353 | int i; | 3352 | int i; |
@@ -3366,29 +3365,15 @@ static int snd_cmipci_suspend(struct device *dev) | |||
3366 | 3365 | ||
3367 | /* disable ints */ | 3366 | /* disable ints */ |
3368 | snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); | 3367 | snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); |
3369 | |||
3370 | pci_disable_device(pci); | ||
3371 | pci_save_state(pci); | ||
3372 | pci_set_power_state(pci, PCI_D3hot); | ||
3373 | return 0; | 3368 | return 0; |
3374 | } | 3369 | } |
3375 | 3370 | ||
3376 | static int snd_cmipci_resume(struct device *dev) | 3371 | static int snd_cmipci_resume(struct device *dev) |
3377 | { | 3372 | { |
3378 | struct pci_dev *pci = to_pci_dev(dev); | ||
3379 | struct snd_card *card = dev_get_drvdata(dev); | 3373 | struct snd_card *card = dev_get_drvdata(dev); |
3380 | struct cmipci *cm = card->private_data; | 3374 | struct cmipci *cm = card->private_data; |
3381 | int i; | 3375 | int i; |
3382 | 3376 | ||
3383 | pci_set_power_state(pci, PCI_D0); | ||
3384 | pci_restore_state(pci); | ||
3385 | if (pci_enable_device(pci) < 0) { | ||
3386 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
3387 | snd_card_disconnect(card); | ||
3388 | return -EIO; | ||
3389 | } | ||
3390 | pci_set_master(pci); | ||
3391 | |||
3392 | /* reset / initialize to a sane state */ | 3377 | /* reset / initialize to a sane state */ |
3393 | snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); | 3378 | snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); |
3394 | snd_cmipci_ch_reset(cm, CM_CH_PLAY); | 3379 | snd_cmipci_ch_reset(cm, CM_CH_PLAY); |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 4c49b5c8a7b3..c296fd0dbc9c 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <asm/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
@@ -973,14 +973,11 @@ static struct snd_pcm_ops snd_cs4281_capture_ops = { | |||
973 | .pointer = snd_cs4281_pointer, | 973 | .pointer = snd_cs4281_pointer, |
974 | }; | 974 | }; |
975 | 975 | ||
976 | static int snd_cs4281_pcm(struct cs4281 *chip, int device, | 976 | static int snd_cs4281_pcm(struct cs4281 *chip, int device) |
977 | struct snd_pcm **rpcm) | ||
978 | { | 977 | { |
979 | struct snd_pcm *pcm; | 978 | struct snd_pcm *pcm; |
980 | int err; | 979 | int err; |
981 | 980 | ||
982 | if (rpcm) | ||
983 | *rpcm = NULL; | ||
984 | err = snd_pcm_new(chip->card, "CS4281", device, 1, 1, &pcm); | 981 | err = snd_pcm_new(chip->card, "CS4281", device, 1, 1, &pcm); |
985 | if (err < 0) | 982 | if (err < 0) |
986 | return err; | 983 | return err; |
@@ -996,8 +993,6 @@ static int snd_cs4281_pcm(struct cs4281 *chip, int device, | |||
996 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 993 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
997 | snd_dma_pci_data(chip->pci), 64*1024, 512*1024); | 994 | snd_dma_pci_data(chip->pci), 64*1024, 512*1024); |
998 | 995 | ||
999 | if (rpcm) | ||
1000 | *rpcm = pcm; | ||
1001 | return 0; | 996 | return 0; |
1002 | } | 997 | } |
1003 | 998 | ||
@@ -1321,10 +1316,8 @@ static int snd_cs4281_free(struct cs4281 *chip) | |||
1321 | 1316 | ||
1322 | if (chip->irq >= 0) | 1317 | if (chip->irq >= 0) |
1323 | free_irq(chip->irq, chip); | 1318 | free_irq(chip->irq, chip); |
1324 | if (chip->ba0) | 1319 | iounmap(chip->ba0); |
1325 | iounmap(chip->ba0); | 1320 | iounmap(chip->ba1); |
1326 | if (chip->ba1) | ||
1327 | iounmap(chip->ba1); | ||
1328 | pci_release_regions(chip->pci); | 1321 | pci_release_regions(chip->pci); |
1329 | pci_disable_device(chip->pci); | 1322 | pci_disable_device(chip->pci); |
1330 | 1323 | ||
@@ -1788,14 +1781,11 @@ static struct snd_rawmidi_ops snd_cs4281_midi_input = | |||
1788 | .trigger = snd_cs4281_midi_input_trigger, | 1781 | .trigger = snd_cs4281_midi_input_trigger, |
1789 | }; | 1782 | }; |
1790 | 1783 | ||
1791 | static int snd_cs4281_midi(struct cs4281 *chip, int device, | 1784 | static int snd_cs4281_midi(struct cs4281 *chip, int device) |
1792 | struct snd_rawmidi **rrawmidi) | ||
1793 | { | 1785 | { |
1794 | struct snd_rawmidi *rmidi; | 1786 | struct snd_rawmidi *rmidi; |
1795 | int err; | 1787 | int err; |
1796 | 1788 | ||
1797 | if (rrawmidi) | ||
1798 | *rrawmidi = NULL; | ||
1799 | if ((err = snd_rawmidi_new(chip->card, "CS4281", device, 1, 1, &rmidi)) < 0) | 1789 | if ((err = snd_rawmidi_new(chip->card, "CS4281", device, 1, 1, &rmidi)) < 0) |
1800 | return err; | 1790 | return err; |
1801 | strcpy(rmidi->name, "CS4281"); | 1791 | strcpy(rmidi->name, "CS4281"); |
@@ -1804,8 +1794,6 @@ static int snd_cs4281_midi(struct cs4281 *chip, int device, | |||
1804 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; | 1794 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; |
1805 | rmidi->private_data = chip; | 1795 | rmidi->private_data = chip; |
1806 | chip->rmidi = rmidi; | 1796 | chip->rmidi = rmidi; |
1807 | if (rrawmidi) | ||
1808 | *rrawmidi = rmidi; | ||
1809 | return 0; | 1797 | return 0; |
1810 | } | 1798 | } |
1811 | 1799 | ||
@@ -1941,11 +1929,11 @@ static int snd_cs4281_probe(struct pci_dev *pci, | |||
1941 | snd_card_free(card); | 1929 | snd_card_free(card); |
1942 | return err; | 1930 | return err; |
1943 | } | 1931 | } |
1944 | if ((err = snd_cs4281_pcm(chip, 0, NULL)) < 0) { | 1932 | if ((err = snd_cs4281_pcm(chip, 0)) < 0) { |
1945 | snd_card_free(card); | 1933 | snd_card_free(card); |
1946 | return err; | 1934 | return err; |
1947 | } | 1935 | } |
1948 | if ((err = snd_cs4281_midi(chip, 0, NULL)) < 0) { | 1936 | if ((err = snd_cs4281_midi(chip, 0)) < 0) { |
1949 | snd_card_free(card); | 1937 | snd_card_free(card); |
1950 | return err; | 1938 | return err; |
1951 | } | 1939 | } |
@@ -2008,7 +1996,6 @@ static int saved_regs[SUSPEND_REGISTERS] = { | |||
2008 | 1996 | ||
2009 | static int cs4281_suspend(struct device *dev) | 1997 | static int cs4281_suspend(struct device *dev) |
2010 | { | 1998 | { |
2011 | struct pci_dev *pci = to_pci_dev(dev); | ||
2012 | struct snd_card *card = dev_get_drvdata(dev); | 1999 | struct snd_card *card = dev_get_drvdata(dev); |
2013 | struct cs4281 *chip = card->private_data; | 2000 | struct cs4281 *chip = card->private_data; |
2014 | u32 ulCLK; | 2001 | u32 ulCLK; |
@@ -2047,30 +2034,16 @@ static int cs4281_suspend(struct device *dev) | |||
2047 | ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1); | 2034 | ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1); |
2048 | ulCLK &= ~CLKCR1_CKRA; | 2035 | ulCLK &= ~CLKCR1_CKRA; |
2049 | snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK); | 2036 | snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK); |
2050 | |||
2051 | pci_disable_device(pci); | ||
2052 | pci_save_state(pci); | ||
2053 | pci_set_power_state(pci, PCI_D3hot); | ||
2054 | return 0; | 2037 | return 0; |
2055 | } | 2038 | } |
2056 | 2039 | ||
2057 | static int cs4281_resume(struct device *dev) | 2040 | static int cs4281_resume(struct device *dev) |
2058 | { | 2041 | { |
2059 | struct pci_dev *pci = to_pci_dev(dev); | ||
2060 | struct snd_card *card = dev_get_drvdata(dev); | 2042 | struct snd_card *card = dev_get_drvdata(dev); |
2061 | struct cs4281 *chip = card->private_data; | 2043 | struct cs4281 *chip = card->private_data; |
2062 | unsigned int i; | 2044 | unsigned int i; |
2063 | u32 ulCLK; | 2045 | u32 ulCLK; |
2064 | 2046 | ||
2065 | pci_set_power_state(pci, PCI_D0); | ||
2066 | pci_restore_state(pci); | ||
2067 | if (pci_enable_device(pci) < 0) { | ||
2068 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
2069 | snd_card_disconnect(card); | ||
2070 | return -EIO; | ||
2071 | } | ||
2072 | pci_set_master(pci); | ||
2073 | |||
2074 | ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1); | 2047 | ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1); |
2075 | ulCLK |= CLKCR1_CKRA; | 2048 | ulCLK |= CLKCR1_CKRA; |
2076 | snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK); | 2049 | snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK); |
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 6a6858c07826..655fbea1692c 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c | |||
@@ -100,16 +100,16 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci, | |||
100 | } | 100 | } |
101 | card->private_data = chip; | 101 | card->private_data = chip; |
102 | chip->accept_valid = mmap_valid[dev]; | 102 | chip->accept_valid = mmap_valid[dev]; |
103 | if ((err = snd_cs46xx_pcm(chip, 0, NULL)) < 0) { | 103 | if ((err = snd_cs46xx_pcm(chip, 0)) < 0) { |
104 | snd_card_free(card); | 104 | snd_card_free(card); |
105 | return err; | 105 | return err; |
106 | } | 106 | } |
107 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | 107 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
108 | if ((err = snd_cs46xx_pcm_rear(chip,1, NULL)) < 0) { | 108 | if ((err = snd_cs46xx_pcm_rear(chip, 1)) < 0) { |
109 | snd_card_free(card); | 109 | snd_card_free(card); |
110 | return err; | 110 | return err; |
111 | } | 111 | } |
112 | if ((err = snd_cs46xx_pcm_iec958(chip,2,NULL)) < 0) { | 112 | if ((err = snd_cs46xx_pcm_iec958(chip, 2)) < 0) { |
113 | snd_card_free(card); | 113 | snd_card_free(card); |
114 | return err; | 114 | return err; |
115 | } | 115 | } |
@@ -120,13 +120,13 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci, | |||
120 | } | 120 | } |
121 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | 121 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
122 | if (chip->nr_ac97_codecs ==2) { | 122 | if (chip->nr_ac97_codecs ==2) { |
123 | if ((err = snd_cs46xx_pcm_center_lfe(chip,3,NULL)) < 0) { | 123 | if ((err = snd_cs46xx_pcm_center_lfe(chip, 3)) < 0) { |
124 | snd_card_free(card); | 124 | snd_card_free(card); |
125 | return err; | 125 | return err; |
126 | } | 126 | } |
127 | } | 127 | } |
128 | #endif | 128 | #endif |
129 | if ((err = snd_cs46xx_midi(chip, 0, NULL)) < 0) { | 129 | if ((err = snd_cs46xx_midi(chip, 0)) < 0) { |
130 | snd_card_free(card); | 130 | snd_card_free(card); |
131 | return err; | 131 | return err; |
132 | } | 132 | } |
diff --git a/sound/pci/cs46xx/cs46xx.h b/sound/pci/cs46xx/cs46xx.h index c49a082c378b..9c9f89a8be5f 100644 --- a/sound/pci/cs46xx/cs46xx.h +++ b/sound/pci/cs46xx/cs46xx.h | |||
@@ -1737,12 +1737,12 @@ int snd_cs46xx_create(struct snd_card *card, | |||
1737 | struct snd_cs46xx **rcodec); | 1737 | struct snd_cs46xx **rcodec); |
1738 | extern const struct dev_pm_ops snd_cs46xx_pm; | 1738 | extern const struct dev_pm_ops snd_cs46xx_pm; |
1739 | 1739 | ||
1740 | int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm); | 1740 | int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device); |
1741 | int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm); | 1741 | int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device); |
1742 | int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm); | 1742 | int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device); |
1743 | int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm); | 1743 | int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device); |
1744 | int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device); | 1744 | int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device); |
1745 | int snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rmidi); | 1745 | int snd_cs46xx_midi(struct snd_cs46xx *chip, int device); |
1746 | int snd_cs46xx_start_dsp(struct snd_cs46xx *chip); | 1746 | int snd_cs46xx_start_dsp(struct snd_cs46xx *chip); |
1747 | int snd_cs46xx_gameport(struct snd_cs46xx *chip); | 1747 | int snd_cs46xx_gameport(struct snd_cs46xx *chip); |
1748 | 1748 | ||
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 32b44f25b5c8..8d74004b1ed2 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/module.h> | 57 | #include <linux/module.h> |
58 | #include <linux/firmware.h> | 58 | #include <linux/firmware.h> |
59 | #include <linux/vmalloc.h> | 59 | #include <linux/vmalloc.h> |
60 | #include <linux/io.h> | ||
60 | 61 | ||
61 | #include <sound/core.h> | 62 | #include <sound/core.h> |
62 | #include <sound/control.h> | 63 | #include <sound/control.h> |
@@ -65,8 +66,6 @@ | |||
65 | #include <sound/pcm_params.h> | 66 | #include <sound/pcm_params.h> |
66 | #include "cs46xx.h" | 67 | #include "cs46xx.h" |
67 | 68 | ||
68 | #include <asm/io.h> | ||
69 | |||
70 | #include "cs46xx_lib.h" | 69 | #include "cs46xx_lib.h" |
71 | #include "dsp_spos.h" | 70 | #include "dsp_spos.h" |
72 | 71 | ||
@@ -1778,13 +1777,11 @@ static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = { | |||
1778 | #define MAX_PLAYBACK_CHANNELS 1 | 1777 | #define MAX_PLAYBACK_CHANNELS 1 |
1779 | #endif | 1778 | #endif |
1780 | 1779 | ||
1781 | int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm) | 1780 | int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device) |
1782 | { | 1781 | { |
1783 | struct snd_pcm *pcm; | 1782 | struct snd_pcm *pcm; |
1784 | int err; | 1783 | int err; |
1785 | 1784 | ||
1786 | if (rpcm) | ||
1787 | *rpcm = NULL; | ||
1788 | if ((err = snd_pcm_new(chip->card, "CS46xx", device, MAX_PLAYBACK_CHANNELS, 1, &pcm)) < 0) | 1785 | if ((err = snd_pcm_new(chip->card, "CS46xx", device, MAX_PLAYBACK_CHANNELS, 1, &pcm)) < 0) |
1789 | return err; | 1786 | return err; |
1790 | 1787 | ||
@@ -1801,23 +1798,16 @@ int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm) | |||
1801 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1798 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1802 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); | 1799 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); |
1803 | 1800 | ||
1804 | if (rpcm) | ||
1805 | *rpcm = pcm; | ||
1806 | |||
1807 | return 0; | 1801 | return 0; |
1808 | } | 1802 | } |
1809 | 1803 | ||
1810 | 1804 | ||
1811 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | 1805 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
1812 | int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, | 1806 | int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device) |
1813 | struct snd_pcm **rpcm) | ||
1814 | { | 1807 | { |
1815 | struct snd_pcm *pcm; | 1808 | struct snd_pcm *pcm; |
1816 | int err; | 1809 | int err; |
1817 | 1810 | ||
1818 | if (rpcm) | ||
1819 | *rpcm = NULL; | ||
1820 | |||
1821 | if ((err = snd_pcm_new(chip->card, "CS46xx - Rear", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0) | 1811 | if ((err = snd_pcm_new(chip->card, "CS46xx - Rear", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0) |
1822 | return err; | 1812 | return err; |
1823 | 1813 | ||
@@ -1833,21 +1823,14 @@ int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, | |||
1833 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1823 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1834 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); | 1824 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); |
1835 | 1825 | ||
1836 | if (rpcm) | ||
1837 | *rpcm = pcm; | ||
1838 | |||
1839 | return 0; | 1826 | return 0; |
1840 | } | 1827 | } |
1841 | 1828 | ||
1842 | int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, | 1829 | int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device) |
1843 | struct snd_pcm **rpcm) | ||
1844 | { | 1830 | { |
1845 | struct snd_pcm *pcm; | 1831 | struct snd_pcm *pcm; |
1846 | int err; | 1832 | int err; |
1847 | 1833 | ||
1848 | if (rpcm) | ||
1849 | *rpcm = NULL; | ||
1850 | |||
1851 | if ((err = snd_pcm_new(chip->card, "CS46xx - Center LFE", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0) | 1834 | if ((err = snd_pcm_new(chip->card, "CS46xx - Center LFE", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0) |
1852 | return err; | 1835 | return err; |
1853 | 1836 | ||
@@ -1863,21 +1846,14 @@ int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, | |||
1863 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1846 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1864 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); | 1847 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); |
1865 | 1848 | ||
1866 | if (rpcm) | ||
1867 | *rpcm = pcm; | ||
1868 | |||
1869 | return 0; | 1849 | return 0; |
1870 | } | 1850 | } |
1871 | 1851 | ||
1872 | int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, | 1852 | int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device) |
1873 | struct snd_pcm **rpcm) | ||
1874 | { | 1853 | { |
1875 | struct snd_pcm *pcm; | 1854 | struct snd_pcm *pcm; |
1876 | int err; | 1855 | int err; |
1877 | 1856 | ||
1878 | if (rpcm) | ||
1879 | *rpcm = NULL; | ||
1880 | |||
1881 | if ((err = snd_pcm_new(chip->card, "CS46xx - IEC958", device, 1, 0, &pcm)) < 0) | 1857 | if ((err = snd_pcm_new(chip->card, "CS46xx - IEC958", device, 1, 0, &pcm)) < 0) |
1882 | return err; | 1858 | return err; |
1883 | 1859 | ||
@@ -1893,9 +1869,6 @@ int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, | |||
1893 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1869 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1894 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); | 1870 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); |
1895 | 1871 | ||
1896 | if (rpcm) | ||
1897 | *rpcm = pcm; | ||
1898 | |||
1899 | return 0; | 1872 | return 0; |
1900 | } | 1873 | } |
1901 | #endif | 1874 | #endif |
@@ -2724,13 +2697,11 @@ static struct snd_rawmidi_ops snd_cs46xx_midi_input = | |||
2724 | .trigger = snd_cs46xx_midi_input_trigger, | 2697 | .trigger = snd_cs46xx_midi_input_trigger, |
2725 | }; | 2698 | }; |
2726 | 2699 | ||
2727 | int snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi) | 2700 | int snd_cs46xx_midi(struct snd_cs46xx *chip, int device) |
2728 | { | 2701 | { |
2729 | struct snd_rawmidi *rmidi; | 2702 | struct snd_rawmidi *rmidi; |
2730 | int err; | 2703 | int err; |
2731 | 2704 | ||
2732 | if (rrawmidi) | ||
2733 | *rrawmidi = NULL; | ||
2734 | if ((err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi)) < 0) | 2705 | if ((err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi)) < 0) |
2735 | return err; | 2706 | return err; |
2736 | strcpy(rmidi->name, "CS46XX"); | 2707 | strcpy(rmidi->name, "CS46XX"); |
@@ -2739,8 +2710,6 @@ int snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rr | |||
2739 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; | 2710 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; |
2740 | rmidi->private_data = chip; | 2711 | rmidi->private_data = chip; |
2741 | chip->rmidi = rmidi; | 2712 | chip->rmidi = rmidi; |
2742 | if (rrawmidi) | ||
2743 | *rrawmidi = NULL; | ||
2744 | return 0; | 2713 | return 0; |
2745 | } | 2714 | } |
2746 | 2715 | ||
@@ -2979,8 +2948,8 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip) | |||
2979 | 2948 | ||
2980 | for (idx = 0; idx < 5; idx++) { | 2949 | for (idx = 0; idx < 5; idx++) { |
2981 | struct snd_cs46xx_region *region = &chip->region.idx[idx]; | 2950 | struct snd_cs46xx_region *region = &chip->region.idx[idx]; |
2982 | if (region->remap_addr) | 2951 | |
2983 | iounmap(region->remap_addr); | 2952 | iounmap(region->remap_addr); |
2984 | release_and_free_resource(region->resource); | 2953 | release_and_free_resource(region->resource); |
2985 | } | 2954 | } |
2986 | 2955 | ||
@@ -3804,7 +3773,6 @@ static unsigned int saved_regs[] = { | |||
3804 | 3773 | ||
3805 | static int snd_cs46xx_suspend(struct device *dev) | 3774 | static int snd_cs46xx_suspend(struct device *dev) |
3806 | { | 3775 | { |
3807 | struct pci_dev *pci = to_pci_dev(dev); | ||
3808 | struct snd_card *card = dev_get_drvdata(dev); | 3776 | struct snd_card *card = dev_get_drvdata(dev); |
3809 | struct snd_cs46xx *chip = card->private_data; | 3777 | struct snd_cs46xx *chip = card->private_data; |
3810 | int i, amp_saved; | 3778 | int i, amp_saved; |
@@ -3829,16 +3797,11 @@ static int snd_cs46xx_suspend(struct device *dev) | |||
3829 | /* disable CLKRUN */ | 3797 | /* disable CLKRUN */ |
3830 | chip->active_ctrl(chip, -chip->amplifier); | 3798 | chip->active_ctrl(chip, -chip->amplifier); |
3831 | chip->amplifier = amp_saved; /* restore the status */ | 3799 | chip->amplifier = amp_saved; /* restore the status */ |
3832 | |||
3833 | pci_disable_device(pci); | ||
3834 | pci_save_state(pci); | ||
3835 | pci_set_power_state(pci, PCI_D3hot); | ||
3836 | return 0; | 3800 | return 0; |
3837 | } | 3801 | } |
3838 | 3802 | ||
3839 | static int snd_cs46xx_resume(struct device *dev) | 3803 | static int snd_cs46xx_resume(struct device *dev) |
3840 | { | 3804 | { |
3841 | struct pci_dev *pci = to_pci_dev(dev); | ||
3842 | struct snd_card *card = dev_get_drvdata(dev); | 3805 | struct snd_card *card = dev_get_drvdata(dev); |
3843 | struct snd_cs46xx *chip = card->private_data; | 3806 | struct snd_cs46xx *chip = card->private_data; |
3844 | int amp_saved; | 3807 | int amp_saved; |
@@ -3847,15 +3810,6 @@ static int snd_cs46xx_resume(struct device *dev) | |||
3847 | #endif | 3810 | #endif |
3848 | unsigned int tmp; | 3811 | unsigned int tmp; |
3849 | 3812 | ||
3850 | pci_set_power_state(pci, PCI_D0); | ||
3851 | pci_restore_state(pci); | ||
3852 | if (pci_enable_device(pci) < 0) { | ||
3853 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
3854 | snd_card_disconnect(card); | ||
3855 | return -EIO; | ||
3856 | } | ||
3857 | pci_set_master(pci); | ||
3858 | |||
3859 | amp_saved = chip->amplifier; | 3813 | amp_saved = chip->amplifier; |
3860 | chip->amplifier = 0; | 3814 | chip->amplifier = 0; |
3861 | chip->active_ctrl(chip, 1); /* force to on */ | 3815 | chip->active_ctrl(chip, 1); /* force to on */ |
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 1c4a0fb3ffef..5c99efb004c0 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c | |||
@@ -20,7 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | 22 | ||
23 | #include <asm/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 8284bc9b5858..2c90c0bded69 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c | |||
@@ -21,7 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | 23 | ||
24 | #include <asm/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/pm.h> | 26 | #include <linux/pm.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c index b1025507a467..0a8cf94c4858 100644 --- a/sound/pci/cs5530.c +++ b/sound/pci/cs5530.c | |||
@@ -223,7 +223,7 @@ static int snd_cs5530_create(struct snd_card *card, | |||
223 | return err; | 223 | return err; |
224 | } | 224 | } |
225 | 225 | ||
226 | err = snd_sb16dsp_pcm(chip->sb, 0, &chip->sb->pcm); | 226 | err = snd_sb16dsp_pcm(chip->sb, 0); |
227 | if (err < 0) { | 227 | if (err < 0) { |
228 | dev_err(card->dev, "Could not create PCM\n"); | 228 | dev_err(card->dev, "Could not create PCM\n"); |
229 | snd_cs5530_free(chip); | 229 | snd_cs5530_free(chip); |
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 16288e4d338a..802c33f1cc59 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <asm/io.h> | 30 | #include <linux/io.h> |
31 | #include <sound/core.h> | 31 | #include <sound/core.h> |
32 | #include <sound/control.h> | 32 | #include <sound/control.h> |
33 | #include <sound/pcm.h> | 33 | #include <sound/pcm.h> |
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c index 34cc60057d0c..06ac5d8da362 100644 --- a/sound/pci/cs5535audio/cs5535audio_pm.c +++ b/sound/pci/cs5535audio/cs5535audio_pm.c | |||
@@ -57,7 +57,6 @@ static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au) | |||
57 | 57 | ||
58 | static int snd_cs5535audio_suspend(struct device *dev) | 58 | static int snd_cs5535audio_suspend(struct device *dev) |
59 | { | 59 | { |
60 | struct pci_dev *pci = to_pci_dev(dev); | ||
61 | struct snd_card *card = dev_get_drvdata(dev); | 60 | struct snd_card *card = dev_get_drvdata(dev); |
62 | struct cs5535audio *cs5535au = card->private_data; | 61 | struct cs5535audio *cs5535au = card->private_data; |
63 | int i; | 62 | int i; |
@@ -72,34 +71,17 @@ static int snd_cs5535audio_suspend(struct device *dev) | |||
72 | } | 71 | } |
73 | /* save important regs, then disable aclink in hw */ | 72 | /* save important regs, then disable aclink in hw */ |
74 | snd_cs5535audio_stop_hardware(cs5535au); | 73 | snd_cs5535audio_stop_hardware(cs5535au); |
75 | |||
76 | if (pci_save_state(pci)) { | ||
77 | dev_err(dev, "pci_save_state failed!\n"); | ||
78 | return -EIO; | ||
79 | } | ||
80 | pci_disable_device(pci); | ||
81 | pci_set_power_state(pci, PCI_D3hot); | ||
82 | return 0; | 74 | return 0; |
83 | } | 75 | } |
84 | 76 | ||
85 | static int snd_cs5535audio_resume(struct device *dev) | 77 | static int snd_cs5535audio_resume(struct device *dev) |
86 | { | 78 | { |
87 | struct pci_dev *pci = to_pci_dev(dev); | ||
88 | struct snd_card *card = dev_get_drvdata(dev); | 79 | struct snd_card *card = dev_get_drvdata(dev); |
89 | struct cs5535audio *cs5535au = card->private_data; | 80 | struct cs5535audio *cs5535au = card->private_data; |
90 | u32 tmp; | 81 | u32 tmp; |
91 | int timeout; | 82 | int timeout; |
92 | int i; | 83 | int i; |
93 | 84 | ||
94 | pci_set_power_state(pci, PCI_D0); | ||
95 | pci_restore_state(pci); | ||
96 | if (pci_enable_device(pci) < 0) { | ||
97 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
98 | snd_card_disconnect(card); | ||
99 | return -EIO; | ||
100 | } | ||
101 | pci_set_master(pci); | ||
102 | |||
103 | /* set LNK_WRM_RST to reset AC link */ | 85 | /* set LNK_WRM_RST to reset AC link */ |
104 | cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST); | 86 | cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST); |
105 | 87 | ||
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index b425aa8ee578..1cac55fd1139 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c | |||
@@ -1985,10 +1985,7 @@ static int hw_card_shutdown(struct hw *hw) | |||
1985 | free_irq(hw->irq, hw); | 1985 | free_irq(hw->irq, hw); |
1986 | 1986 | ||
1987 | hw->irq = -1; | 1987 | hw->irq = -1; |
1988 | 1988 | iounmap(hw->mem_base); | |
1989 | if (hw->mem_base) | ||
1990 | iounmap(hw->mem_base); | ||
1991 | |||
1992 | hw->mem_base = NULL; | 1989 | hw->mem_base = NULL; |
1993 | 1990 | ||
1994 | if (hw->io_base) | 1991 | if (hw->io_base) |
@@ -2099,20 +2096,11 @@ static int hw_suspend(struct hw *hw) | |||
2099 | pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x0); | 2096 | pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x0); |
2100 | } | 2097 | } |
2101 | 2098 | ||
2102 | pci_disable_device(pci); | ||
2103 | pci_save_state(pci); | ||
2104 | pci_set_power_state(pci, PCI_D3hot); | ||
2105 | |||
2106 | return 0; | 2099 | return 0; |
2107 | } | 2100 | } |
2108 | 2101 | ||
2109 | static int hw_resume(struct hw *hw, struct card_conf *info) | 2102 | static int hw_resume(struct hw *hw, struct card_conf *info) |
2110 | { | 2103 | { |
2111 | struct pci_dev *pci = hw->pci; | ||
2112 | |||
2113 | pci_set_power_state(pci, PCI_D0); | ||
2114 | pci_restore_state(pci); | ||
2115 | |||
2116 | /* Re-initialize card hardware. */ | 2104 | /* Re-initialize card hardware. */ |
2117 | return hw_card_init(hw, info); | 2105 | return hw_card_init(hw, info); |
2118 | } | 2106 | } |
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index 253899d13790..955ad871e9a8 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c | |||
@@ -2110,10 +2110,7 @@ static int hw_card_shutdown(struct hw *hw) | |||
2110 | free_irq(hw->irq, hw); | 2110 | free_irq(hw->irq, hw); |
2111 | 2111 | ||
2112 | hw->irq = -1; | 2112 | hw->irq = -1; |
2113 | 2113 | iounmap(hw->mem_base); | |
2114 | if (hw->mem_base) | ||
2115 | iounmap(hw->mem_base); | ||
2116 | |||
2117 | hw->mem_base = NULL; | 2114 | hw->mem_base = NULL; |
2118 | 2115 | ||
2119 | if (hw->io_base) | 2116 | if (hw->io_base) |
@@ -2209,24 +2206,12 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) | |||
2209 | #ifdef CONFIG_PM_SLEEP | 2206 | #ifdef CONFIG_PM_SLEEP |
2210 | static int hw_suspend(struct hw *hw) | 2207 | static int hw_suspend(struct hw *hw) |
2211 | { | 2208 | { |
2212 | struct pci_dev *pci = hw->pci; | ||
2213 | |||
2214 | hw_card_stop(hw); | 2209 | hw_card_stop(hw); |
2215 | |||
2216 | pci_disable_device(pci); | ||
2217 | pci_save_state(pci); | ||
2218 | pci_set_power_state(pci, PCI_D3hot); | ||
2219 | |||
2220 | return 0; | 2210 | return 0; |
2221 | } | 2211 | } |
2222 | 2212 | ||
2223 | static int hw_resume(struct hw *hw, struct card_conf *info) | 2213 | static int hw_resume(struct hw *hw, struct card_conf *info) |
2224 | { | 2214 | { |
2225 | struct pci_dev *pci = hw->pci; | ||
2226 | |||
2227 | pci_set_power_state(pci, PCI_D0); | ||
2228 | pci_restore_state(pci); | ||
2229 | |||
2230 | /* Re-initialize card hardware. */ | 2215 | /* Re-initialize card hardware. */ |
2231 | return hw_card_init(hw, info); | 2216 | return hw_card_init(hw, info); |
2232 | } | 2217 | } |
diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c index 4632946205a8..c95da6301677 100644 --- a/sound/pci/echoaudio/darla20.c +++ b/sound/pci/echoaudio/darla20.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/module.h> | 43 | #include <linux/module.h> |
44 | #include <linux/firmware.h> | 44 | #include <linux/firmware.h> |
45 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
46 | #include <linux/io.h> | ||
46 | #include <sound/core.h> | 47 | #include <sound/core.h> |
47 | #include <sound/info.h> | 48 | #include <sound/info.h> |
48 | #include <sound/control.h> | 49 | #include <sound/control.h> |
@@ -51,7 +52,6 @@ | |||
51 | #include <sound/pcm_params.h> | 52 | #include <sound/pcm_params.h> |
52 | #include <sound/asoundef.h> | 53 | #include <sound/asoundef.h> |
53 | #include <sound/initval.h> | 54 | #include <sound/initval.h> |
54 | #include <asm/io.h> | ||
55 | #include <linux/atomic.h> | 55 | #include <linux/atomic.h> |
56 | #include "echoaudio.h" | 56 | #include "echoaudio.h" |
57 | 57 | ||
diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c index f81c839cc887..3013b4daa19e 100644 --- a/sound/pci/echoaudio/darla24.c +++ b/sound/pci/echoaudio/darla24.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
48 | #include <linux/firmware.h> | 48 | #include <linux/firmware.h> |
49 | #include <linux/slab.h> | 49 | #include <linux/slab.h> |
50 | #include <linux/io.h> | ||
50 | #include <sound/core.h> | 51 | #include <sound/core.h> |
51 | #include <sound/info.h> | 52 | #include <sound/info.h> |
52 | #include <sound/control.h> | 53 | #include <sound/control.h> |
@@ -55,7 +56,6 @@ | |||
55 | #include <sound/pcm_params.h> | 56 | #include <sound/pcm_params.h> |
56 | #include <sound/asoundef.h> | 57 | #include <sound/asoundef.h> |
57 | #include <sound/initval.h> | 58 | #include <sound/initval.h> |
58 | #include <asm/io.h> | ||
59 | #include <linux/atomic.h> | 59 | #include <linux/atomic.h> |
60 | #include "echoaudio.h" | 60 | #include "echoaudio.h" |
61 | 61 | ||
diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c index 3a5346c33d76..1f34a07b0b19 100644 --- a/sound/pci/echoaudio/echo3g.c +++ b/sound/pci/echoaudio/echo3g.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include <linux/module.h> | 54 | #include <linux/module.h> |
55 | #include <linux/firmware.h> | 55 | #include <linux/firmware.h> |
56 | #include <linux/slab.h> | 56 | #include <linux/slab.h> |
57 | #include <linux/io.h> | ||
57 | #include <sound/core.h> | 58 | #include <sound/core.h> |
58 | #include <sound/info.h> | 59 | #include <sound/info.h> |
59 | #include <sound/control.h> | 60 | #include <sound/control.h> |
@@ -63,7 +64,6 @@ | |||
63 | #include <sound/asoundef.h> | 64 | #include <sound/asoundef.h> |
64 | #include <sound/initval.h> | 65 | #include <sound/initval.h> |
65 | #include <sound/rawmidi.h> | 66 | #include <sound/rawmidi.h> |
66 | #include <asm/io.h> | ||
67 | #include <linux/atomic.h> | 67 | #include <linux/atomic.h> |
68 | #include "echoaudio.h" | 68 | #include "echoaudio.h" |
69 | 69 | ||
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 21228adaa70c..a962de03ebb6 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
@@ -1872,12 +1872,8 @@ static int snd_echo_free(struct echoaudio *chip) | |||
1872 | if (chip->comm_page) | 1872 | if (chip->comm_page) |
1873 | snd_dma_free_pages(&chip->commpage_dma_buf); | 1873 | snd_dma_free_pages(&chip->commpage_dma_buf); |
1874 | 1874 | ||
1875 | if (chip->dsp_registers) | 1875 | iounmap(chip->dsp_registers); |
1876 | iounmap(chip->dsp_registers); | ||
1877 | |||
1878 | release_and_free_resource(chip->iores); | 1876 | release_and_free_resource(chip->iores); |
1879 | |||
1880 | |||
1881 | pci_disable_device(chip->pci); | 1877 | pci_disable_device(chip->pci); |
1882 | 1878 | ||
1883 | /* release chip data */ | 1879 | /* release chip data */ |
@@ -2162,7 +2158,6 @@ ctl_error: | |||
2162 | 2158 | ||
2163 | static int snd_echo_suspend(struct device *dev) | 2159 | static int snd_echo_suspend(struct device *dev) |
2164 | { | 2160 | { |
2165 | struct pci_dev *pci = to_pci_dev(dev); | ||
2166 | struct echoaudio *chip = dev_get_drvdata(dev); | 2161 | struct echoaudio *chip = dev_get_drvdata(dev); |
2167 | 2162 | ||
2168 | snd_pcm_suspend_all(chip->analog_pcm); | 2163 | snd_pcm_suspend_all(chip->analog_pcm); |
@@ -2188,9 +2183,6 @@ static int snd_echo_suspend(struct device *dev) | |||
2188 | chip->dsp_code = NULL; | 2183 | chip->dsp_code = NULL; |
2189 | free_irq(chip->irq, chip); | 2184 | free_irq(chip->irq, chip); |
2190 | chip->irq = -1; | 2185 | chip->irq = -1; |
2191 | pci_save_state(pci); | ||
2192 | pci_disable_device(pci); | ||
2193 | |||
2194 | return 0; | 2186 | return 0; |
2195 | } | 2187 | } |
2196 | 2188 | ||
@@ -2204,7 +2196,6 @@ static int snd_echo_resume(struct device *dev) | |||
2204 | u32 pipe_alloc_mask; | 2196 | u32 pipe_alloc_mask; |
2205 | int err; | 2197 | int err; |
2206 | 2198 | ||
2207 | pci_restore_state(pci); | ||
2208 | commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL); | 2199 | commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL); |
2209 | if (commpage_bak == NULL) | 2200 | if (commpage_bak == NULL) |
2210 | return -ENOMEM; | 2201 | return -ENOMEM; |
diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c index 9cb81c500824..4fa32a2e97db 100644 --- a/sound/pci/echoaudio/gina20.c +++ b/sound/pci/echoaudio/gina20.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
48 | #include <linux/firmware.h> | 48 | #include <linux/firmware.h> |
49 | #include <linux/slab.h> | 49 | #include <linux/slab.h> |
50 | #include <linux/io.h> | ||
50 | #include <sound/core.h> | 51 | #include <sound/core.h> |
51 | #include <sound/info.h> | 52 | #include <sound/info.h> |
52 | #include <sound/control.h> | 53 | #include <sound/control.h> |
@@ -55,7 +56,6 @@ | |||
55 | #include <sound/pcm_params.h> | 56 | #include <sound/pcm_params.h> |
56 | #include <sound/asoundef.h> | 57 | #include <sound/asoundef.h> |
57 | #include <sound/initval.h> | 58 | #include <sound/initval.h> |
58 | #include <asm/io.h> | ||
59 | #include <linux/atomic.h> | 59 | #include <linux/atomic.h> |
60 | #include "echoaudio.h" | 60 | #include "echoaudio.h" |
61 | 61 | ||
diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c index 35d3e6eac990..b1bcacaef257 100644 --- a/sound/pci/echoaudio/gina24.c +++ b/sound/pci/echoaudio/gina24.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <linux/module.h> | 53 | #include <linux/module.h> |
54 | #include <linux/firmware.h> | 54 | #include <linux/firmware.h> |
55 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
56 | #include <linux/io.h> | ||
56 | #include <sound/core.h> | 57 | #include <sound/core.h> |
57 | #include <sound/info.h> | 58 | #include <sound/info.h> |
58 | #include <sound/control.h> | 59 | #include <sound/control.h> |
@@ -61,7 +62,6 @@ | |||
61 | #include <sound/pcm_params.h> | 62 | #include <sound/pcm_params.h> |
62 | #include <sound/asoundef.h> | 63 | #include <sound/asoundef.h> |
63 | #include <sound/initval.h> | 64 | #include <sound/initval.h> |
64 | #include <asm/io.h> | ||
65 | #include <linux/atomic.h> | 65 | #include <linux/atomic.h> |
66 | #include "echoaudio.h" | 66 | #include "echoaudio.h" |
67 | 67 | ||
diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c index 8d91842d1268..175af9b1435f 100644 --- a/sound/pci/echoaudio/indigo.c +++ b/sound/pci/echoaudio/indigo.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/module.h> | 45 | #include <linux/module.h> |
46 | #include <linux/firmware.h> | 46 | #include <linux/firmware.h> |
47 | #include <linux/slab.h> | 47 | #include <linux/slab.h> |
48 | #include <linux/io.h> | ||
48 | #include <sound/core.h> | 49 | #include <sound/core.h> |
49 | #include <sound/info.h> | 50 | #include <sound/info.h> |
50 | #include <sound/control.h> | 51 | #include <sound/control.h> |
@@ -53,7 +54,6 @@ | |||
53 | #include <sound/pcm_params.h> | 54 | #include <sound/pcm_params.h> |
54 | #include <sound/asoundef.h> | 55 | #include <sound/asoundef.h> |
55 | #include <sound/initval.h> | 56 | #include <sound/initval.h> |
56 | #include <asm/io.h> | ||
57 | #include <linux/atomic.h> | 57 | #include <linux/atomic.h> |
58 | #include "echoaudio.h" | 58 | #include "echoaudio.h" |
59 | 59 | ||
diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c index 289cb969f5b9..8c60314e4901 100644 --- a/sound/pci/echoaudio/indigodj.c +++ b/sound/pci/echoaudio/indigodj.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/module.h> | 45 | #include <linux/module.h> |
46 | #include <linux/firmware.h> | 46 | #include <linux/firmware.h> |
47 | #include <linux/slab.h> | 47 | #include <linux/slab.h> |
48 | #include <linux/io.h> | ||
48 | #include <sound/core.h> | 49 | #include <sound/core.h> |
49 | #include <sound/info.h> | 50 | #include <sound/info.h> |
50 | #include <sound/control.h> | 51 | #include <sound/control.h> |
@@ -53,7 +54,6 @@ | |||
53 | #include <sound/pcm_params.h> | 54 | #include <sound/pcm_params.h> |
54 | #include <sound/asoundef.h> | 55 | #include <sound/asoundef.h> |
55 | #include <sound/initval.h> | 56 | #include <sound/initval.h> |
56 | #include <asm/io.h> | ||
57 | #include <linux/atomic.h> | 57 | #include <linux/atomic.h> |
58 | #include "echoaudio.h" | 58 | #include "echoaudio.h" |
59 | 59 | ||
diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c index 405a3f2e496f..f7618edfd79c 100644 --- a/sound/pci/echoaudio/indigoio.c +++ b/sound/pci/echoaudio/indigoio.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/module.h> | 46 | #include <linux/module.h> |
47 | #include <linux/firmware.h> | 47 | #include <linux/firmware.h> |
48 | #include <linux/slab.h> | 48 | #include <linux/slab.h> |
49 | #include <linux/io.h> | ||
49 | #include <sound/core.h> | 50 | #include <sound/core.h> |
50 | #include <sound/info.h> | 51 | #include <sound/info.h> |
51 | #include <sound/control.h> | 52 | #include <sound/control.h> |
@@ -54,7 +55,6 @@ | |||
54 | #include <sound/pcm_params.h> | 55 | #include <sound/pcm_params.h> |
55 | #include <sound/asoundef.h> | 56 | #include <sound/asoundef.h> |
56 | #include <sound/initval.h> | 57 | #include <sound/initval.h> |
57 | #include <asm/io.h> | ||
58 | #include <linux/atomic.h> | 58 | #include <linux/atomic.h> |
59 | #include "echoaudio.h" | 59 | #include "echoaudio.h" |
60 | 60 | ||
diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c index b392dd776b71..12e5d2164dc4 100644 --- a/sound/pci/echoaudio/layla20.c +++ b/sound/pci/echoaudio/layla20.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <linux/module.h> | 52 | #include <linux/module.h> |
53 | #include <linux/firmware.h> | 53 | #include <linux/firmware.h> |
54 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
55 | #include <linux/io.h> | ||
55 | #include <sound/core.h> | 56 | #include <sound/core.h> |
56 | #include <sound/info.h> | 57 | #include <sound/info.h> |
57 | #include <sound/control.h> | 58 | #include <sound/control.h> |
@@ -61,7 +62,6 @@ | |||
61 | #include <sound/asoundef.h> | 62 | #include <sound/asoundef.h> |
62 | #include <sound/initval.h> | 63 | #include <sound/initval.h> |
63 | #include <sound/rawmidi.h> | 64 | #include <sound/rawmidi.h> |
64 | #include <asm/io.h> | ||
65 | #include <linux/atomic.h> | 65 | #include <linux/atomic.h> |
66 | #include "echoaudio.h" | 66 | #include "echoaudio.h" |
67 | 67 | ||
diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c index bc7f730b0ec6..6e4023728ef5 100644 --- a/sound/pci/echoaudio/layla24.c +++ b/sound/pci/echoaudio/layla24.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include <linux/module.h> | 54 | #include <linux/module.h> |
55 | #include <linux/firmware.h> | 55 | #include <linux/firmware.h> |
56 | #include <linux/slab.h> | 56 | #include <linux/slab.h> |
57 | #include <linux/io.h> | ||
57 | #include <sound/core.h> | 58 | #include <sound/core.h> |
58 | #include <sound/info.h> | 59 | #include <sound/info.h> |
59 | #include <sound/control.h> | 60 | #include <sound/control.h> |
@@ -63,7 +64,6 @@ | |||
63 | #include <sound/asoundef.h> | 64 | #include <sound/asoundef.h> |
64 | #include <sound/initval.h> | 65 | #include <sound/initval.h> |
65 | #include <sound/rawmidi.h> | 66 | #include <sound/rawmidi.h> |
66 | #include <asm/io.h> | ||
67 | #include <linux/atomic.h> | 67 | #include <linux/atomic.h> |
68 | #include "echoaudio.h" | 68 | #include "echoaudio.h" |
69 | 69 | ||
diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c index 27a9a6e5db2d..2f7562f1aefb 100644 --- a/sound/pci/echoaudio/mia.c +++ b/sound/pci/echoaudio/mia.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <linux/module.h> | 53 | #include <linux/module.h> |
54 | #include <linux/firmware.h> | 54 | #include <linux/firmware.h> |
55 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
56 | #include <linux/io.h> | ||
56 | #include <sound/core.h> | 57 | #include <sound/core.h> |
57 | #include <sound/info.h> | 58 | #include <sound/info.h> |
58 | #include <sound/control.h> | 59 | #include <sound/control.h> |
@@ -62,7 +63,6 @@ | |||
62 | #include <sound/asoundef.h> | 63 | #include <sound/asoundef.h> |
63 | #include <sound/initval.h> | 64 | #include <sound/initval.h> |
64 | #include <sound/rawmidi.h> | 65 | #include <sound/rawmidi.h> |
65 | #include <asm/io.h> | ||
66 | #include <linux/atomic.h> | 66 | #include <linux/atomic.h> |
67 | #include "echoaudio.h" | 67 | #include "echoaudio.h" |
68 | 68 | ||
diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c index d913749d154a..a8fe58335ddc 100644 --- a/sound/pci/echoaudio/midi.c +++ b/sound/pci/echoaudio/midi.c | |||
@@ -257,9 +257,8 @@ static void snd_echo_midi_output_trigger(struct snd_rawmidi_substream *substream | |||
257 | spin_lock_irq(&chip->lock); | 257 | spin_lock_irq(&chip->lock); |
258 | if (up) { | 258 | if (up) { |
259 | if (!chip->tinuse) { | 259 | if (!chip->tinuse) { |
260 | init_timer(&chip->timer); | 260 | setup_timer(&chip->timer, snd_echo_midi_output_write, |
261 | chip->timer.function = snd_echo_midi_output_write; | 261 | (unsigned long)chip); |
262 | chip->timer.data = (unsigned long)chip; | ||
263 | chip->tinuse = 1; | 262 | chip->tinuse = 1; |
264 | } | 263 | } |
265 | } else { | 264 | } else { |
diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c index 3d13875c303d..34d499466393 100644 --- a/sound/pci/echoaudio/mona.c +++ b/sound/pci/echoaudio/mona.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/module.h> | 51 | #include <linux/module.h> |
52 | #include <linux/firmware.h> | 52 | #include <linux/firmware.h> |
53 | #include <linux/slab.h> | 53 | #include <linux/slab.h> |
54 | #include <linux/io.h> | ||
54 | #include <sound/core.h> | 55 | #include <sound/core.h> |
55 | #include <sound/info.h> | 56 | #include <sound/info.h> |
56 | #include <sound/control.h> | 57 | #include <sound/control.h> |
@@ -59,7 +60,6 @@ | |||
59 | #include <sound/pcm_params.h> | 60 | #include <sound/pcm_params.h> |
60 | #include <sound/asoundef.h> | 61 | #include <sound/asoundef.h> |
61 | #include <sound/initval.h> | 62 | #include <sound/initval.h> |
62 | #include <asm/io.h> | ||
63 | #include <linux/atomic.h> | 63 | #include <linux/atomic.h> |
64 | #include "echoaudio.h" | 64 | #include "echoaudio.h" |
65 | 65 | ||
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 4c171636efcd..37d0220a094c 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -132,11 +132,11 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, | |||
132 | goto error; | 132 | goto error; |
133 | card->private_data = emu; | 133 | card->private_data = emu; |
134 | emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f; | 134 | emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f; |
135 | if ((err = snd_emu10k1_pcm(emu, 0, NULL)) < 0) | 135 | if ((err = snd_emu10k1_pcm(emu, 0)) < 0) |
136 | goto error; | 136 | goto error; |
137 | if ((err = snd_emu10k1_pcm_mic(emu, 1, NULL)) < 0) | 137 | if ((err = snd_emu10k1_pcm_mic(emu, 1)) < 0) |
138 | goto error; | 138 | goto error; |
139 | if ((err = snd_emu10k1_pcm_efx(emu, 2, NULL)) < 0) | 139 | if ((err = snd_emu10k1_pcm_efx(emu, 2)) < 0) |
140 | goto error; | 140 | goto error; |
141 | /* This stores the periods table. */ | 141 | /* This stores the periods table. */ |
142 | if (emu->card_capabilities->ca0151_chip) { /* P16V */ | 142 | if (emu->card_capabilities->ca0151_chip) { /* P16V */ |
@@ -151,10 +151,10 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, | |||
151 | if ((err = snd_emu10k1_timer(emu, 0)) < 0) | 151 | if ((err = snd_emu10k1_timer(emu, 0)) < 0) |
152 | goto error; | 152 | goto error; |
153 | 153 | ||
154 | if ((err = snd_emu10k1_pcm_multi(emu, 3, NULL)) < 0) | 154 | if ((err = snd_emu10k1_pcm_multi(emu, 3)) < 0) |
155 | goto error; | 155 | goto error; |
156 | if (emu->card_capabilities->ca0151_chip) { /* P16V */ | 156 | if (emu->card_capabilities->ca0151_chip) { /* P16V */ |
157 | if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0) | 157 | if ((err = snd_p16v_pcm(emu, 4)) < 0) |
158 | goto error; | 158 | goto error; |
159 | } | 159 | } |
160 | if (emu->audigy) { | 160 | if (emu->audigy) { |
@@ -164,7 +164,7 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, | |||
164 | if ((err = snd_emu10k1_midi(emu)) < 0) | 164 | if ((err = snd_emu10k1_midi(emu)) < 0) |
165 | goto error; | 165 | goto error; |
166 | } | 166 | } |
167 | if ((err = snd_emu10k1_fx8010_new(emu, 0, NULL)) < 0) | 167 | if ((err = snd_emu10k1_fx8010_new(emu, 0)) < 0) |
168 | goto error; | 168 | goto error; |
169 | #ifdef ENABLE_SYNTH | 169 | #ifdef ENABLE_SYNTH |
170 | if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, | 170 | if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, |
@@ -210,7 +210,6 @@ static void snd_card_emu10k1_remove(struct pci_dev *pci) | |||
210 | #ifdef CONFIG_PM_SLEEP | 210 | #ifdef CONFIG_PM_SLEEP |
211 | static int snd_emu10k1_suspend(struct device *dev) | 211 | static int snd_emu10k1_suspend(struct device *dev) |
212 | { | 212 | { |
213 | struct pci_dev *pci = to_pci_dev(dev); | ||
214 | struct snd_card *card = dev_get_drvdata(dev); | 213 | struct snd_card *card = dev_get_drvdata(dev); |
215 | struct snd_emu10k1 *emu = card->private_data; | 214 | struct snd_emu10k1 *emu = card->private_data; |
216 | 215 | ||
@@ -232,28 +231,14 @@ static int snd_emu10k1_suspend(struct device *dev) | |||
232 | snd_p16v_suspend(emu); | 231 | snd_p16v_suspend(emu); |
233 | 232 | ||
234 | snd_emu10k1_done(emu); | 233 | snd_emu10k1_done(emu); |
235 | |||
236 | pci_disable_device(pci); | ||
237 | pci_save_state(pci); | ||
238 | pci_set_power_state(pci, PCI_D3hot); | ||
239 | return 0; | 234 | return 0; |
240 | } | 235 | } |
241 | 236 | ||
242 | static int snd_emu10k1_resume(struct device *dev) | 237 | static int snd_emu10k1_resume(struct device *dev) |
243 | { | 238 | { |
244 | struct pci_dev *pci = to_pci_dev(dev); | ||
245 | struct snd_card *card = dev_get_drvdata(dev); | 239 | struct snd_card *card = dev_get_drvdata(dev); |
246 | struct snd_emu10k1 *emu = card->private_data; | 240 | struct snd_emu10k1 *emu = card->private_data; |
247 | 241 | ||
248 | pci_set_power_state(pci, PCI_D0); | ||
249 | pci_restore_state(pci); | ||
250 | if (pci_enable_device(pci) < 0) { | ||
251 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
252 | snd_card_disconnect(card); | ||
253 | return -EIO; | ||
254 | } | ||
255 | pci_set_master(pci); | ||
256 | |||
257 | snd_emu10k1_resume_init(emu); | 242 | snd_emu10k1_resume_init(emu); |
258 | snd_emu10k1_efx_resume(emu); | 243 | snd_emu10k1_efx_resume(emu); |
259 | snd_ac97_resume(emu->ac97); | 244 | snd_ac97_resume(emu->ac97); |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 15933f92f63a..6d1b98d14327 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -847,15 +847,13 @@ static const struct snd_pcm_chmap_elem clfe_map[] = { | |||
847 | { } | 847 | { } |
848 | }; | 848 | }; |
849 | 849 | ||
850 | static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm) | 850 | static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device) |
851 | { | 851 | { |
852 | struct snd_pcm *pcm; | 852 | struct snd_pcm *pcm; |
853 | const struct snd_pcm_chmap_elem *map = NULL; | 853 | const struct snd_pcm_chmap_elem *map = NULL; |
854 | int err; | 854 | int err; |
855 | int capture = 0; | 855 | int capture = 0; |
856 | 856 | ||
857 | if (rpcm) | ||
858 | *rpcm = NULL; | ||
859 | if (device == 0) | 857 | if (device == 0) |
860 | capture = 1; | 858 | capture = 1; |
861 | 859 | ||
@@ -896,15 +894,8 @@ static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **r | |||
896 | snd_dma_pci_data(emu->pci), | 894 | snd_dma_pci_data(emu->pci), |
897 | 32*1024, 32*1024); | 895 | 32*1024, 32*1024); |
898 | 896 | ||
899 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, 2, | 897 | return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, 2, |
900 | 1 << 2, NULL); | 898 | 1 << 2, NULL); |
901 | if (err < 0) | ||
902 | return err; | ||
903 | |||
904 | if (rpcm) | ||
905 | *rpcm = pcm; | ||
906 | |||
907 | return 0; | ||
908 | } | 899 | } |
909 | 900 | ||
910 | static int snd_emu10k1x_create(struct snd_card *card, | 901 | static int snd_emu10k1x_create(struct snd_card *card, |
@@ -1583,15 +1574,15 @@ static int snd_emu10k1x_probe(struct pci_dev *pci, | |||
1583 | return err; | 1574 | return err; |
1584 | } | 1575 | } |
1585 | 1576 | ||
1586 | if ((err = snd_emu10k1x_pcm(chip, 0, NULL)) < 0) { | 1577 | if ((err = snd_emu10k1x_pcm(chip, 0)) < 0) { |
1587 | snd_card_free(card); | 1578 | snd_card_free(card); |
1588 | return err; | 1579 | return err; |
1589 | } | 1580 | } |
1590 | if ((err = snd_emu10k1x_pcm(chip, 1, NULL)) < 0) { | 1581 | if ((err = snd_emu10k1x_pcm(chip, 1)) < 0) { |
1591 | snd_card_free(card); | 1582 | snd_card_free(card); |
1592 | return err; | 1583 | return err; |
1593 | } | 1584 | } |
1594 | if ((err = snd_emu10k1x_pcm(chip, 2, NULL)) < 0) { | 1585 | if ((err = snd_emu10k1x_pcm(chip, 2)) < 0) { |
1595 | snd_card_free(card); | 1586 | snd_card_free(card); |
1596 | return err; | 1587 | return err; |
1597 | } | 1588 | } |
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index eb5c0aba41c1..56fc47bd6dba 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
@@ -2641,14 +2641,11 @@ static int snd_emu10k1_fx8010_release(struct snd_hwdep * hw, struct file *file) | |||
2641 | return 0; | 2641 | return 0; |
2642 | } | 2642 | } |
2643 | 2643 | ||
2644 | int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, | 2644 | int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device) |
2645 | struct snd_hwdep **rhwdep) | ||
2646 | { | 2645 | { |
2647 | struct snd_hwdep *hw; | 2646 | struct snd_hwdep *hw; |
2648 | int err; | 2647 | int err; |
2649 | 2648 | ||
2650 | if (rhwdep) | ||
2651 | *rhwdep = NULL; | ||
2652 | if ((err = snd_hwdep_new(emu->card, "FX8010", device, &hw)) < 0) | 2649 | if ((err = snd_hwdep_new(emu->card, "FX8010", device, &hw)) < 0) |
2653 | return err; | 2650 | return err; |
2654 | strcpy(hw->name, "EMU10K1 (FX8010)"); | 2651 | strcpy(hw->name, "EMU10K1 (FX8010)"); |
@@ -2657,8 +2654,6 @@ int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, | |||
2657 | hw->ops.ioctl = snd_emu10k1_fx8010_ioctl; | 2654 | hw->ops.ioctl = snd_emu10k1_fx8010_ioctl; |
2658 | hw->ops.release = snd_emu10k1_fx8010_release; | 2655 | hw->ops.release = snd_emu10k1_fx8010_release; |
2659 | hw->private_data = emu; | 2656 | hw->private_data = emu; |
2660 | if (rhwdep) | ||
2661 | *rhwdep = hw; | ||
2662 | return 0; | 2657 | return 0; |
2663 | } | 2658 | } |
2664 | 2659 | ||
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index f82481bd2542..0dc07385af0e 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c | |||
@@ -1400,15 +1400,12 @@ static struct snd_pcm_ops snd_emu10k1_efx_playback_ops = { | |||
1400 | .page = snd_pcm_sgbuf_ops_page, | 1400 | .page = snd_pcm_sgbuf_ops_page, |
1401 | }; | 1401 | }; |
1402 | 1402 | ||
1403 | int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm) | 1403 | int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device) |
1404 | { | 1404 | { |
1405 | struct snd_pcm *pcm; | 1405 | struct snd_pcm *pcm; |
1406 | struct snd_pcm_substream *substream; | 1406 | struct snd_pcm_substream *substream; |
1407 | int err; | 1407 | int err; |
1408 | 1408 | ||
1409 | if (rpcm) | ||
1410 | *rpcm = NULL; | ||
1411 | |||
1412 | if ((err = snd_pcm_new(emu->card, "emu10k1", device, 32, 1, &pcm)) < 0) | 1409 | if ((err = snd_pcm_new(emu->card, "emu10k1", device, 32, 1, &pcm)) < 0) |
1413 | return err; | 1410 | return err; |
1414 | 1411 | ||
@@ -1429,22 +1426,15 @@ int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm) | |||
1429 | for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) | 1426 | for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) |
1430 | snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); | 1427 | snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); |
1431 | 1428 | ||
1432 | if (rpcm) | ||
1433 | *rpcm = pcm; | ||
1434 | |||
1435 | return 0; | 1429 | return 0; |
1436 | } | 1430 | } |
1437 | 1431 | ||
1438 | int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device, | 1432 | int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device) |
1439 | struct snd_pcm **rpcm) | ||
1440 | { | 1433 | { |
1441 | struct snd_pcm *pcm; | 1434 | struct snd_pcm *pcm; |
1442 | struct snd_pcm_substream *substream; | 1435 | struct snd_pcm_substream *substream; |
1443 | int err; | 1436 | int err; |
1444 | 1437 | ||
1445 | if (rpcm) | ||
1446 | *rpcm = NULL; | ||
1447 | |||
1448 | if ((err = snd_pcm_new(emu->card, "emu10k1", device, 1, 0, &pcm)) < 0) | 1438 | if ((err = snd_pcm_new(emu->card, "emu10k1", device, 1, 0, &pcm)) < 0) |
1449 | return err; | 1439 | return err; |
1450 | 1440 | ||
@@ -1461,9 +1451,6 @@ int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device, | |||
1461 | if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0) | 1451 | if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0) |
1462 | return err; | 1452 | return err; |
1463 | 1453 | ||
1464 | if (rpcm) | ||
1465 | *rpcm = pcm; | ||
1466 | |||
1467 | return 0; | 1454 | return 0; |
1468 | } | 1455 | } |
1469 | 1456 | ||
@@ -1479,15 +1466,11 @@ static struct snd_pcm_ops snd_emu10k1_capture_mic_ops = { | |||
1479 | .pointer = snd_emu10k1_capture_pointer, | 1466 | .pointer = snd_emu10k1_capture_pointer, |
1480 | }; | 1467 | }; |
1481 | 1468 | ||
1482 | int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device, | 1469 | int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device) |
1483 | struct snd_pcm **rpcm) | ||
1484 | { | 1470 | { |
1485 | struct snd_pcm *pcm; | 1471 | struct snd_pcm *pcm; |
1486 | int err; | 1472 | int err; |
1487 | 1473 | ||
1488 | if (rpcm) | ||
1489 | *rpcm = NULL; | ||
1490 | |||
1491 | if ((err = snd_pcm_new(emu->card, "emu10k1 mic", device, 0, 1, &pcm)) < 0) | 1474 | if ((err = snd_pcm_new(emu->card, "emu10k1 mic", device, 0, 1, &pcm)) < 0) |
1492 | return err; | 1475 | return err; |
1493 | 1476 | ||
@@ -1501,8 +1484,6 @@ int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device, | |||
1501 | 1484 | ||
1502 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); | 1485 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); |
1503 | 1486 | ||
1504 | if (rpcm) | ||
1505 | *rpcm = pcm; | ||
1506 | return 0; | 1487 | return 0; |
1507 | } | 1488 | } |
1508 | 1489 | ||
@@ -1822,16 +1803,12 @@ static struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = { | |||
1822 | .ack = snd_emu10k1_fx8010_playback_transfer, | 1803 | .ack = snd_emu10k1_fx8010_playback_transfer, |
1823 | }; | 1804 | }; |
1824 | 1805 | ||
1825 | int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device, | 1806 | int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device) |
1826 | struct snd_pcm **rpcm) | ||
1827 | { | 1807 | { |
1828 | struct snd_pcm *pcm; | 1808 | struct snd_pcm *pcm; |
1829 | struct snd_kcontrol *kctl; | 1809 | struct snd_kcontrol *kctl; |
1830 | int err; | 1810 | int err; |
1831 | 1811 | ||
1832 | if (rpcm) | ||
1833 | *rpcm = NULL; | ||
1834 | |||
1835 | if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm)) < 0) | 1812 | if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm)) < 0) |
1836 | return err; | 1813 | return err; |
1837 | 1814 | ||
@@ -1843,8 +1820,6 @@ int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device, | |||
1843 | pcm->info_flags = 0; | 1820 | pcm->info_flags = 0; |
1844 | strcpy(pcm->name, "Multichannel Capture/PT Playback"); | 1821 | strcpy(pcm->name, "Multichannel Capture/PT Playback"); |
1845 | emu->pcm_efx = pcm; | 1822 | emu->pcm_efx = pcm; |
1846 | if (rpcm) | ||
1847 | *rpcm = pcm; | ||
1848 | 1823 | ||
1849 | /* EFX capture - record the "FXBUS2" channels, by default we connect the EXTINs | 1824 | /* EFX capture - record the "FXBUS2" channels, by default we connect the EXTINs |
1850 | * to these | 1825 | * to these |
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 7ef3898a7806..3c60b433de9f 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c | |||
@@ -166,11 +166,8 @@ static struct snd_pcm_hardware snd_p16v_capture_hw = { | |||
166 | static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime) | 166 | static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime) |
167 | { | 167 | { |
168 | struct snd_emu10k1_pcm *epcm = runtime->private_data; | 168 | struct snd_emu10k1_pcm *epcm = runtime->private_data; |
169 | 169 | ||
170 | if (epcm) { | 170 | kfree(epcm); |
171 | /* dev_dbg(emu->card->dev, "epcm free: %p\n", epcm); */ | ||
172 | kfree(epcm); | ||
173 | } | ||
174 | } | 171 | } |
175 | 172 | ||
176 | /* open_playback callback */ | 173 | /* open_playback callback */ |
@@ -640,7 +637,7 @@ int snd_p16v_free(struct snd_emu10k1 *chip) | |||
640 | return 0; | 637 | return 0; |
641 | } | 638 | } |
642 | 639 | ||
643 | int snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm) | 640 | int snd_p16v_pcm(struct snd_emu10k1 *emu, int device) |
644 | { | 641 | { |
645 | struct snd_pcm *pcm; | 642 | struct snd_pcm *pcm; |
646 | struct snd_pcm_substream *substream; | 643 | struct snd_pcm_substream *substream; |
@@ -649,8 +646,6 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm) | |||
649 | 646 | ||
650 | /* dev_dbg(emu->card->dev, "snd_p16v_pcm called. device=%d\n", device); */ | 647 | /* dev_dbg(emu->card->dev, "snd_p16v_pcm called. device=%d\n", device); */ |
651 | emu->p16v_device_offset = device; | 648 | emu->p16v_device_offset = device; |
652 | if (rpcm) | ||
653 | *rpcm = NULL; | ||
654 | 649 | ||
655 | if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0) | 650 | if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0) |
656 | return err; | 651 | return err; |
@@ -694,9 +689,6 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm) | |||
694 | */ | 689 | */ |
695 | } | 690 | } |
696 | 691 | ||
697 | if (rpcm) | ||
698 | *rpcm = pcm; | ||
699 | |||
700 | return 0; | 692 | return 0; |
701 | } | 693 | } |
702 | 694 | ||
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index d94cb3ca7a64..0dc44ebb0032 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -26,7 +26,7 @@ | |||
26 | * by Kurt J. Bosch | 26 | * by Kurt J. Bosch |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <asm/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
@@ -1268,14 +1268,11 @@ static const struct snd_pcm_chmap_elem surround_map[] = { | |||
1268 | { } | 1268 | { } |
1269 | }; | 1269 | }; |
1270 | 1270 | ||
1271 | static int snd_ensoniq_pcm(struct ensoniq *ensoniq, int device, | 1271 | static int snd_ensoniq_pcm(struct ensoniq *ensoniq, int device) |
1272 | struct snd_pcm **rpcm) | ||
1273 | { | 1272 | { |
1274 | struct snd_pcm *pcm; | 1273 | struct snd_pcm *pcm; |
1275 | int err; | 1274 | int err; |
1276 | 1275 | ||
1277 | if (rpcm) | ||
1278 | *rpcm = NULL; | ||
1279 | err = snd_pcm_new(ensoniq->card, CHIP_NAME "/1", device, 1, 1, &pcm); | 1276 | err = snd_pcm_new(ensoniq->card, CHIP_NAME "/1", device, 1, 1, &pcm); |
1280 | if (err < 0) | 1277 | if (err < 0) |
1281 | return err; | 1278 | return err; |
@@ -1302,22 +1299,14 @@ static int snd_ensoniq_pcm(struct ensoniq *ensoniq, int device, | |||
1302 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | 1299 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, |
1303 | snd_pcm_std_chmaps, 2, 0, NULL); | 1300 | snd_pcm_std_chmaps, 2, 0, NULL); |
1304 | #endif | 1301 | #endif |
1305 | if (err < 0) | 1302 | return err; |
1306 | return err; | ||
1307 | |||
1308 | if (rpcm) | ||
1309 | *rpcm = pcm; | ||
1310 | return 0; | ||
1311 | } | 1303 | } |
1312 | 1304 | ||
1313 | static int snd_ensoniq_pcm2(struct ensoniq *ensoniq, int device, | 1305 | static int snd_ensoniq_pcm2(struct ensoniq *ensoniq, int device) |
1314 | struct snd_pcm **rpcm) | ||
1315 | { | 1306 | { |
1316 | struct snd_pcm *pcm; | 1307 | struct snd_pcm *pcm; |
1317 | int err; | 1308 | int err; |
1318 | 1309 | ||
1319 | if (rpcm) | ||
1320 | *rpcm = NULL; | ||
1321 | err = snd_pcm_new(ensoniq->card, CHIP_NAME "/2", device, 1, 0, &pcm); | 1310 | err = snd_pcm_new(ensoniq->card, CHIP_NAME "/2", device, 1, 0, &pcm); |
1322 | if (err < 0) | 1311 | if (err < 0) |
1323 | return err; | 1312 | return err; |
@@ -1342,12 +1331,7 @@ static int snd_ensoniq_pcm2(struct ensoniq *ensoniq, int device, | |||
1342 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | 1331 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, |
1343 | surround_map, 2, 0, NULL); | 1332 | surround_map, 2, 0, NULL); |
1344 | #endif | 1333 | #endif |
1345 | if (err < 0) | 1334 | return err; |
1346 | return err; | ||
1347 | |||
1348 | if (rpcm) | ||
1349 | *rpcm = pcm; | ||
1350 | return 0; | ||
1351 | } | 1335 | } |
1352 | 1336 | ||
1353 | /* | 1337 | /* |
@@ -2049,7 +2033,6 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq) | |||
2049 | #ifdef CONFIG_PM_SLEEP | 2033 | #ifdef CONFIG_PM_SLEEP |
2050 | static int snd_ensoniq_suspend(struct device *dev) | 2034 | static int snd_ensoniq_suspend(struct device *dev) |
2051 | { | 2035 | { |
2052 | struct pci_dev *pci = to_pci_dev(dev); | ||
2053 | struct snd_card *card = dev_get_drvdata(dev); | 2036 | struct snd_card *card = dev_get_drvdata(dev); |
2054 | struct ensoniq *ensoniq = card->private_data; | 2037 | struct ensoniq *ensoniq = card->private_data; |
2055 | 2038 | ||
@@ -2070,28 +2053,14 @@ static int snd_ensoniq_suspend(struct device *dev) | |||
2070 | udelay(100); | 2053 | udelay(100); |
2071 | snd_ak4531_suspend(ensoniq->u.es1370.ak4531); | 2054 | snd_ak4531_suspend(ensoniq->u.es1370.ak4531); |
2072 | #endif | 2055 | #endif |
2073 | |||
2074 | pci_disable_device(pci); | ||
2075 | pci_save_state(pci); | ||
2076 | pci_set_power_state(pci, PCI_D3hot); | ||
2077 | return 0; | 2056 | return 0; |
2078 | } | 2057 | } |
2079 | 2058 | ||
2080 | static int snd_ensoniq_resume(struct device *dev) | 2059 | static int snd_ensoniq_resume(struct device *dev) |
2081 | { | 2060 | { |
2082 | struct pci_dev *pci = to_pci_dev(dev); | ||
2083 | struct snd_card *card = dev_get_drvdata(dev); | 2061 | struct snd_card *card = dev_get_drvdata(dev); |
2084 | struct ensoniq *ensoniq = card->private_data; | 2062 | struct ensoniq *ensoniq = card->private_data; |
2085 | 2063 | ||
2086 | pci_set_power_state(pci, PCI_D0); | ||
2087 | pci_restore_state(pci); | ||
2088 | if (pci_enable_device(pci) < 0) { | ||
2089 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
2090 | snd_card_disconnect(card); | ||
2091 | return -EIO; | ||
2092 | } | ||
2093 | pci_set_master(pci); | ||
2094 | |||
2095 | snd_ensoniq_chip_init(ensoniq); | 2064 | snd_ensoniq_chip_init(ensoniq); |
2096 | 2065 | ||
2097 | #ifdef CHIP1371 | 2066 | #ifdef CHIP1371 |
@@ -2362,14 +2331,11 @@ static struct snd_rawmidi_ops snd_ensoniq_midi_input = | |||
2362 | .trigger = snd_ensoniq_midi_input_trigger, | 2331 | .trigger = snd_ensoniq_midi_input_trigger, |
2363 | }; | 2332 | }; |
2364 | 2333 | ||
2365 | static int snd_ensoniq_midi(struct ensoniq *ensoniq, int device, | 2334 | static int snd_ensoniq_midi(struct ensoniq *ensoniq, int device) |
2366 | struct snd_rawmidi **rrawmidi) | ||
2367 | { | 2335 | { |
2368 | struct snd_rawmidi *rmidi; | 2336 | struct snd_rawmidi *rmidi; |
2369 | int err; | 2337 | int err; |
2370 | 2338 | ||
2371 | if (rrawmidi) | ||
2372 | *rrawmidi = NULL; | ||
2373 | if ((err = snd_rawmidi_new(ensoniq->card, "ES1370/1", device, 1, 1, &rmidi)) < 0) | 2339 | if ((err = snd_rawmidi_new(ensoniq->card, "ES1370/1", device, 1, 1, &rmidi)) < 0) |
2374 | return err; | 2340 | return err; |
2375 | strcpy(rmidi->name, CHIP_NAME); | 2341 | strcpy(rmidi->name, CHIP_NAME); |
@@ -2379,8 +2345,6 @@ static int snd_ensoniq_midi(struct ensoniq *ensoniq, int device, | |||
2379 | SNDRV_RAWMIDI_INFO_DUPLEX; | 2345 | SNDRV_RAWMIDI_INFO_DUPLEX; |
2380 | rmidi->private_data = ensoniq; | 2346 | rmidi->private_data = ensoniq; |
2381 | ensoniq->rmidi = rmidi; | 2347 | ensoniq->rmidi = rmidi; |
2382 | if (rrawmidi) | ||
2383 | *rrawmidi = rmidi; | ||
2384 | return 0; | 2348 | return 0; |
2385 | } | 2349 | } |
2386 | 2350 | ||
@@ -2462,15 +2426,15 @@ static int snd_audiopci_probe(struct pci_dev *pci, | |||
2462 | return err; | 2426 | return err; |
2463 | } | 2427 | } |
2464 | #endif | 2428 | #endif |
2465 | if ((err = snd_ensoniq_pcm(ensoniq, 0, NULL)) < 0) { | 2429 | if ((err = snd_ensoniq_pcm(ensoniq, 0)) < 0) { |
2466 | snd_card_free(card); | 2430 | snd_card_free(card); |
2467 | return err; | 2431 | return err; |
2468 | } | 2432 | } |
2469 | if ((err = snd_ensoniq_pcm2(ensoniq, 1, NULL)) < 0) { | 2433 | if ((err = snd_ensoniq_pcm2(ensoniq, 1)) < 0) { |
2470 | snd_card_free(card); | 2434 | snd_card_free(card); |
2471 | return err; | 2435 | return err; |
2472 | } | 2436 | } |
2473 | if ((err = snd_ensoniq_midi(ensoniq, 0, NULL)) < 0) { | 2437 | if ((err = snd_ensoniq_midi(ensoniq, 0)) < 0) { |
2474 | snd_card_free(card); | 2438 | snd_card_free(card); |
2475 | return err; | 2439 | return err; |
2476 | } | 2440 | } |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 0fc46eb4e251..e1858d9d23d8 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <linux/module.h> | 55 | #include <linux/module.h> |
56 | #include <linux/delay.h> | 56 | #include <linux/delay.h> |
57 | #include <linux/dma-mapping.h> | 57 | #include <linux/dma-mapping.h> |
58 | #include <linux/io.h> | ||
58 | #include <sound/core.h> | 59 | #include <sound/core.h> |
59 | #include <sound/control.h> | 60 | #include <sound/control.h> |
60 | #include <sound/pcm.h> | 61 | #include <sound/pcm.h> |
@@ -63,8 +64,6 @@ | |||
63 | #include <sound/initval.h> | 64 | #include <sound/initval.h> |
64 | #include <sound/tlv.h> | 65 | #include <sound/tlv.h> |
65 | 66 | ||
66 | #include <asm/io.h> | ||
67 | |||
68 | MODULE_AUTHOR("Jaromir Koutek <miri@punknet.cz>"); | 67 | MODULE_AUTHOR("Jaromir Koutek <miri@punknet.cz>"); |
69 | MODULE_DESCRIPTION("ESS Solo-1"); | 68 | MODULE_DESCRIPTION("ESS Solo-1"); |
70 | MODULE_LICENSE("GPL"); | 69 | MODULE_LICENSE("GPL"); |
@@ -1454,7 +1453,6 @@ static unsigned char saved_regs[SAVED_REG_SIZE+1] = { | |||
1454 | 1453 | ||
1455 | static int es1938_suspend(struct device *dev) | 1454 | static int es1938_suspend(struct device *dev) |
1456 | { | 1455 | { |
1457 | struct pci_dev *pci = to_pci_dev(dev); | ||
1458 | struct snd_card *card = dev_get_drvdata(dev); | 1456 | struct snd_card *card = dev_get_drvdata(dev); |
1459 | struct es1938 *chip = card->private_data; | 1457 | struct es1938 *chip = card->private_data; |
1460 | unsigned char *s, *d; | 1458 | unsigned char *s, *d; |
@@ -1471,9 +1469,6 @@ static int es1938_suspend(struct device *dev) | |||
1471 | free_irq(chip->irq, chip); | 1469 | free_irq(chip->irq, chip); |
1472 | chip->irq = -1; | 1470 | chip->irq = -1; |
1473 | } | 1471 | } |
1474 | pci_disable_device(pci); | ||
1475 | pci_save_state(pci); | ||
1476 | pci_set_power_state(pci, PCI_D3hot); | ||
1477 | return 0; | 1472 | return 0; |
1478 | } | 1473 | } |
1479 | 1474 | ||
@@ -1484,14 +1479,6 @@ static int es1938_resume(struct device *dev) | |||
1484 | struct es1938 *chip = card->private_data; | 1479 | struct es1938 *chip = card->private_data; |
1485 | unsigned char *s, *d; | 1480 | unsigned char *s, *d; |
1486 | 1481 | ||
1487 | pci_set_power_state(pci, PCI_D0); | ||
1488 | pci_restore_state(pci); | ||
1489 | if (pci_enable_device(pci) < 0) { | ||
1490 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
1491 | snd_card_disconnect(card); | ||
1492 | return -EIO; | ||
1493 | } | ||
1494 | |||
1495 | if (request_irq(pci->irq, snd_es1938_interrupt, | 1482 | if (request_irq(pci->irq, snd_es1938_interrupt, |
1496 | IRQF_SHARED, KBUILD_MODNAME, chip)) { | 1483 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
1497 | dev_err(dev, "unable to grab IRQ %d, disabling device\n", | 1484 | dev_err(dev, "unable to grab IRQ %d, disabling device\n", |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 6039700f8579..059f3846d7b8 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -94,7 +94,7 @@ | |||
94 | * places. | 94 | * places. |
95 | */ | 95 | */ |
96 | 96 | ||
97 | #include <asm/io.h> | 97 | #include <linux/io.h> |
98 | #include <linux/delay.h> | 98 | #include <linux/delay.h> |
99 | #include <linux/interrupt.h> | 99 | #include <linux/interrupt.h> |
100 | #include <linux/init.h> | 100 | #include <linux/init.h> |
@@ -2383,7 +2383,6 @@ static void snd_es1968_start_irq(struct es1968 *chip) | |||
2383 | */ | 2383 | */ |
2384 | static int es1968_suspend(struct device *dev) | 2384 | static int es1968_suspend(struct device *dev) |
2385 | { | 2385 | { |
2386 | struct pci_dev *pci = to_pci_dev(dev); | ||
2387 | struct snd_card *card = dev_get_drvdata(dev); | 2386 | struct snd_card *card = dev_get_drvdata(dev); |
2388 | struct es1968 *chip = card->private_data; | 2387 | struct es1968 *chip = card->private_data; |
2389 | 2388 | ||
@@ -2396,16 +2395,11 @@ static int es1968_suspend(struct device *dev) | |||
2396 | snd_pcm_suspend_all(chip->pcm); | 2395 | snd_pcm_suspend_all(chip->pcm); |
2397 | snd_ac97_suspend(chip->ac97); | 2396 | snd_ac97_suspend(chip->ac97); |
2398 | snd_es1968_bob_stop(chip); | 2397 | snd_es1968_bob_stop(chip); |
2399 | |||
2400 | pci_disable_device(pci); | ||
2401 | pci_save_state(pci); | ||
2402 | pci_set_power_state(pci, PCI_D3hot); | ||
2403 | return 0; | 2398 | return 0; |
2404 | } | 2399 | } |
2405 | 2400 | ||
2406 | static int es1968_resume(struct device *dev) | 2401 | static int es1968_resume(struct device *dev) |
2407 | { | 2402 | { |
2408 | struct pci_dev *pci = to_pci_dev(dev); | ||
2409 | struct snd_card *card = dev_get_drvdata(dev); | 2403 | struct snd_card *card = dev_get_drvdata(dev); |
2410 | struct es1968 *chip = card->private_data; | 2404 | struct es1968 *chip = card->private_data; |
2411 | struct esschan *es; | 2405 | struct esschan *es; |
@@ -2413,16 +2407,6 @@ static int es1968_resume(struct device *dev) | |||
2413 | if (! chip->do_pm) | 2407 | if (! chip->do_pm) |
2414 | return 0; | 2408 | return 0; |
2415 | 2409 | ||
2416 | /* restore all our config */ | ||
2417 | pci_set_power_state(pci, PCI_D0); | ||
2418 | pci_restore_state(pci); | ||
2419 | if (pci_enable_device(pci) < 0) { | ||
2420 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
2421 | snd_card_disconnect(card); | ||
2422 | return -EIO; | ||
2423 | } | ||
2424 | pci_set_master(pci); | ||
2425 | |||
2426 | snd_es1968_chip_init(chip); | 2410 | snd_es1968_chip_init(chip); |
2427 | 2411 | ||
2428 | /* need to restore the base pointers.. */ | 2412 | /* need to restore the base pointers.. */ |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index d167afffce5f..1fdd92b6f18f 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -2,8 +2,6 @@ | |||
2 | * The driver for the ForteMedia FM801 based soundcards | 2 | * The driver for the ForteMedia FM801 based soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * Support FM only card by Andy Shevchenko <andy@smile.org.ua> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or | 7 | * the Free Software Foundation; either version 2 of the License, or |
@@ -14,10 +12,6 @@ | |||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
16 | * | 14 | * |
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | 15 | */ |
22 | 16 | ||
23 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
@@ -704,13 +698,11 @@ static struct snd_pcm_ops snd_fm801_capture_ops = { | |||
704 | .pointer = snd_fm801_capture_pointer, | 698 | .pointer = snd_fm801_capture_pointer, |
705 | }; | 699 | }; |
706 | 700 | ||
707 | static int snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pcm **rpcm) | 701 | static int snd_fm801_pcm(struct fm801 *chip, int device) |
708 | { | 702 | { |
709 | struct snd_pcm *pcm; | 703 | struct snd_pcm *pcm; |
710 | int err; | 704 | int err; |
711 | 705 | ||
712 | if (rpcm) | ||
713 | *rpcm = NULL; | ||
714 | if ((err = snd_pcm_new(chip->card, "FM801", device, 1, 1, &pcm)) < 0) | 706 | if ((err = snd_pcm_new(chip->card, "FM801", device, 1, 1, &pcm)) < 0) |
715 | return err; | 707 | return err; |
716 | 708 | ||
@@ -726,16 +718,10 @@ static int snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pcm **rpcm) | |||
726 | snd_dma_pci_data(chip->pci), | 718 | snd_dma_pci_data(chip->pci), |
727 | chip->multichannel ? 128*1024 : 64*1024, 128*1024); | 719 | chip->multichannel ? 128*1024 : 64*1024, 128*1024); |
728 | 720 | ||
729 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | 721 | return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, |
730 | snd_pcm_alt_chmaps, | 722 | snd_pcm_alt_chmaps, |
731 | chip->multichannel ? 6 : 2, 0, | 723 | chip->multichannel ? 6 : 2, 0, |
732 | NULL); | 724 | NULL); |
733 | if (err < 0) | ||
734 | return err; | ||
735 | |||
736 | if (rpcm) | ||
737 | *rpcm = pcm; | ||
738 | return 0; | ||
739 | } | 725 | } |
740 | 726 | ||
741 | /* | 727 | /* |
@@ -1186,12 +1172,6 @@ static int snd_fm801_free(struct fm801 *chip) | |||
1186 | v4l2_device_unregister(&chip->v4l2_dev); | 1172 | v4l2_device_unregister(&chip->v4l2_dev); |
1187 | } | 1173 | } |
1188 | #endif | 1174 | #endif |
1189 | if (chip->irq >= 0) | ||
1190 | free_irq(chip->irq, chip); | ||
1191 | pci_release_regions(chip->pci); | ||
1192 | pci_disable_device(chip->pci); | ||
1193 | |||
1194 | kfree(chip); | ||
1195 | return 0; | 1175 | return 0; |
1196 | } | 1176 | } |
1197 | 1177 | ||
@@ -1214,28 +1194,23 @@ static int snd_fm801_create(struct snd_card *card, | |||
1214 | }; | 1194 | }; |
1215 | 1195 | ||
1216 | *rchip = NULL; | 1196 | *rchip = NULL; |
1217 | if ((err = pci_enable_device(pci)) < 0) | 1197 | if ((err = pcim_enable_device(pci)) < 0) |
1218 | return err; | 1198 | return err; |
1219 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 1199 | chip = devm_kzalloc(&pci->dev, sizeof(*chip), GFP_KERNEL); |
1220 | if (chip == NULL) { | 1200 | if (chip == NULL) |
1221 | pci_disable_device(pci); | ||
1222 | return -ENOMEM; | 1201 | return -ENOMEM; |
1223 | } | ||
1224 | spin_lock_init(&chip->reg_lock); | 1202 | spin_lock_init(&chip->reg_lock); |
1225 | chip->card = card; | 1203 | chip->card = card; |
1226 | chip->pci = pci; | 1204 | chip->pci = pci; |
1227 | chip->irq = -1; | 1205 | chip->irq = -1; |
1228 | chip->tea575x_tuner = tea575x_tuner; | 1206 | chip->tea575x_tuner = tea575x_tuner; |
1229 | if ((err = pci_request_regions(pci, "FM801")) < 0) { | 1207 | if ((err = pci_request_regions(pci, "FM801")) < 0) |
1230 | kfree(chip); | ||
1231 | pci_disable_device(pci); | ||
1232 | return err; | 1208 | return err; |
1233 | } | ||
1234 | chip->port = pci_resource_start(pci, 0); | 1209 | chip->port = pci_resource_start(pci, 0); |
1235 | if ((tea575x_tuner & TUNER_ONLY) == 0) { | 1210 | if ((tea575x_tuner & TUNER_ONLY) == 0) { |
1236 | if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_SHARED, | 1211 | if (devm_request_irq(&pci->dev, pci->irq, snd_fm801_interrupt, |
1237 | KBUILD_MODNAME, chip)) { | 1212 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
1238 | dev_err(card->dev, "unable to grab IRQ %d\n", chip->irq); | 1213 | dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); |
1239 | snd_fm801_free(chip); | 1214 | snd_fm801_free(chip); |
1240 | return -EBUSY; | 1215 | return -EBUSY; |
1241 | } | 1216 | } |
@@ -1250,12 +1225,6 @@ static int snd_fm801_create(struct snd_card *card, | |||
1250 | /* init might set tuner access method */ | 1225 | /* init might set tuner access method */ |
1251 | tea575x_tuner = chip->tea575x_tuner; | 1226 | tea575x_tuner = chip->tea575x_tuner; |
1252 | 1227 | ||
1253 | if (chip->irq >= 0 && (tea575x_tuner & TUNER_ONLY)) { | ||
1254 | pci_clear_master(pci); | ||
1255 | free_irq(chip->irq, chip); | ||
1256 | chip->irq = -1; | ||
1257 | } | ||
1258 | |||
1259 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | 1228 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { |
1260 | snd_fm801_free(chip); | 1229 | snd_fm801_free(chip); |
1261 | return err; | 1230 | return err; |
@@ -1340,7 +1309,7 @@ static int snd_card_fm801_probe(struct pci_dev *pci, | |||
1340 | if (chip->tea575x_tuner & TUNER_ONLY) | 1309 | if (chip->tea575x_tuner & TUNER_ONLY) |
1341 | goto __fm801_tuner_only; | 1310 | goto __fm801_tuner_only; |
1342 | 1311 | ||
1343 | if ((err = snd_fm801_pcm(chip, 0, NULL)) < 0) { | 1312 | if ((err = snd_fm801_pcm(chip, 0)) < 0) { |
1344 | snd_card_free(card); | 1313 | snd_card_free(card); |
1345 | return err; | 1314 | return err; |
1346 | } | 1315 | } |
@@ -1392,7 +1361,6 @@ static unsigned char saved_regs[] = { | |||
1392 | 1361 | ||
1393 | static int snd_fm801_suspend(struct device *dev) | 1362 | static int snd_fm801_suspend(struct device *dev) |
1394 | { | 1363 | { |
1395 | struct pci_dev *pci = to_pci_dev(dev); | ||
1396 | struct snd_card *card = dev_get_drvdata(dev); | 1364 | struct snd_card *card = dev_get_drvdata(dev); |
1397 | struct fm801 *chip = card->private_data; | 1365 | struct fm801 *chip = card->private_data; |
1398 | int i; | 1366 | int i; |
@@ -1404,29 +1372,15 @@ static int snd_fm801_suspend(struct device *dev) | |||
1404 | for (i = 0; i < ARRAY_SIZE(saved_regs); i++) | 1372 | for (i = 0; i < ARRAY_SIZE(saved_regs); i++) |
1405 | chip->saved_regs[i] = inw(chip->port + saved_regs[i]); | 1373 | chip->saved_regs[i] = inw(chip->port + saved_regs[i]); |
1406 | /* FIXME: tea575x suspend */ | 1374 | /* FIXME: tea575x suspend */ |
1407 | |||
1408 | pci_disable_device(pci); | ||
1409 | pci_save_state(pci); | ||
1410 | pci_set_power_state(pci, PCI_D3hot); | ||
1411 | return 0; | 1375 | return 0; |
1412 | } | 1376 | } |
1413 | 1377 | ||
1414 | static int snd_fm801_resume(struct device *dev) | 1378 | static int snd_fm801_resume(struct device *dev) |
1415 | { | 1379 | { |
1416 | struct pci_dev *pci = to_pci_dev(dev); | ||
1417 | struct snd_card *card = dev_get_drvdata(dev); | 1380 | struct snd_card *card = dev_get_drvdata(dev); |
1418 | struct fm801 *chip = card->private_data; | 1381 | struct fm801 *chip = card->private_data; |
1419 | int i; | 1382 | int i; |
1420 | 1383 | ||
1421 | pci_set_power_state(pci, PCI_D0); | ||
1422 | pci_restore_state(pci); | ||
1423 | if (pci_enable_device(pci) < 0) { | ||
1424 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
1425 | snd_card_disconnect(card); | ||
1426 | return -EIO; | ||
1427 | } | ||
1428 | pci_set_master(pci); | ||
1429 | |||
1430 | snd_fm801_chip_init(chip, 1); | 1384 | snd_fm801_chip_init(chip, 1); |
1431 | snd_ac97_resume(chip->ac97); | 1385 | snd_ac97_resume(chip->ac97); |
1432 | snd_ac97_resume(chip->ac97_sec); | 1386 | snd_ac97_resume(chip->ac97_sec); |
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index ebf4c2fb99df..7f0f2c5a4e97 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -107,6 +107,7 @@ config SND_HDA_PATCH_LOADER | |||
107 | config SND_HDA_CODEC_REALTEK | 107 | config SND_HDA_CODEC_REALTEK |
108 | tristate "Build Realtek HD-audio codec support" | 108 | tristate "Build Realtek HD-audio codec support" |
109 | select SND_HDA_GENERIC | 109 | select SND_HDA_GENERIC |
110 | select INPUT | ||
110 | help | 111 | help |
111 | Say Y or M here to include Realtek HD-audio codec support in | 112 | Say Y or M here to include Realtek HD-audio codec support in |
112 | snd-hda-intel driver, such as ALC880. | 113 | snd-hda-intel driver, such as ALC880. |
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 1ede82200ee5..3f8706bb3d16 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c | |||
@@ -409,10 +409,10 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, | |||
409 | /* | 409 | /* |
410 | * debug prints of the parsed results | 410 | * debug prints of the parsed results |
411 | */ | 411 | */ |
412 | codec_info(codec, "autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n", | 412 | codec_info(codec, "autoconfig for %s: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n", |
413 | cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1], | 413 | codec->chip_name, cfg->line_outs, cfg->line_out_pins[0], |
414 | cfg->line_out_pins[2], cfg->line_out_pins[3], | 414 | cfg->line_out_pins[1], cfg->line_out_pins[2], |
415 | cfg->line_out_pins[4], | 415 | cfg->line_out_pins[3], cfg->line_out_pins[4], |
416 | cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" : | 416 | cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" : |
417 | (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ? | 417 | (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ? |
418 | "speaker" : "line")); | 418 | "speaker" : "line")); |
@@ -920,6 +920,8 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec, | |||
920 | codec->fixup_id = pq->value; | 920 | codec->fixup_id = pq->value; |
921 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 921 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
922 | codec->fixup_name = pq->name; | 922 | codec->fixup_name = pq->name; |
923 | codec_dbg(codec, "%s: picked fixup %s (pin match)\n", | ||
924 | codec->chip_name, codec->fixup_name); | ||
923 | #endif | 925 | #endif |
924 | codec->fixup_list = fixlist; | 926 | codec->fixup_list = fixlist; |
925 | return; | 927 | return; |
@@ -960,6 +962,8 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
960 | codec->fixup_list = NULL; | 962 | codec->fixup_list = NULL; |
961 | codec->fixup_name = NULL; | 963 | codec->fixup_name = NULL; |
962 | codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP; | 964 | codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP; |
965 | codec_dbg(codec, "%s: picked no fixup (nofixup specified)\n", | ||
966 | codec->chip_name); | ||
963 | return; | 967 | return; |
964 | } | 968 | } |
965 | 969 | ||
@@ -969,6 +973,8 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
969 | codec->fixup_id = models->id; | 973 | codec->fixup_id = models->id; |
970 | codec->fixup_name = models->name; | 974 | codec->fixup_name = models->name; |
971 | codec->fixup_list = fixlist; | 975 | codec->fixup_list = fixlist; |
976 | codec_dbg(codec, "%s: picked fixup %s (model specified)\n", | ||
977 | codec->chip_name, codec->fixup_name); | ||
972 | return; | 978 | return; |
973 | } | 979 | } |
974 | models++; | 980 | models++; |
@@ -980,6 +986,8 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
980 | id = q->value; | 986 | id = q->value; |
981 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 987 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
982 | name = q->name; | 988 | name = q->name; |
989 | codec_dbg(codec, "%s: picked fixup %s (PCI SSID%s)\n", | ||
990 | codec->chip_name, name, q->subdevice_mask ? "" : " - vendor generic"); | ||
983 | #endif | 991 | #endif |
984 | } | 992 | } |
985 | } | 993 | } |
@@ -992,6 +1000,8 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
992 | id = q->value; | 1000 | id = q->value; |
993 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 1001 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
994 | name = q->name; | 1002 | name = q->name; |
1003 | codec_dbg(codec, "%s: picked fixup %s (codec SSID)\n", | ||
1004 | codec->chip_name, name); | ||
995 | #endif | 1005 | #endif |
996 | break; | 1006 | break; |
997 | } | 1007 | } |
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 0cfc9c8c4b4e..a2ce773bdc62 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
@@ -657,6 +657,9 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
657 | azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits); | 657 | azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits); |
658 | if (start) { | 658 | if (start) { |
659 | azx_timecounter_init(substream, 0, 0); | 659 | azx_timecounter_init(substream, 0, 0); |
660 | snd_pcm_gettime(substream->runtime, &substream->runtime->trigger_tstamp); | ||
661 | substream->runtime->trigger_tstamp_latched = true; | ||
662 | |||
660 | if (nsync > 1) { | 663 | if (nsync > 1) { |
661 | cycle_t cycle_last; | 664 | cycle_t cycle_last; |
662 | 665 | ||
@@ -939,7 +942,8 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, | |||
939 | chip->card->dev, | 942 | chip->card->dev, |
940 | size, MAX_PREALLOC_SIZE); | 943 | size, MAX_PREALLOC_SIZE); |
941 | /* link to codec */ | 944 | /* link to codec */ |
942 | pcm->dev = &codec->dev; | 945 | for (s = 0; s < 2; s++) |
946 | pcm->streams[s].dev.parent = &codec->dev; | ||
943 | return 0; | 947 | return 0; |
944 | } | 948 | } |
945 | 949 | ||
@@ -957,7 +961,6 @@ static int azx_alloc_cmd_io(struct azx *chip) | |||
957 | dev_err(chip->card->dev, "cannot allocate CORB/RIRB\n"); | 961 | dev_err(chip->card->dev, "cannot allocate CORB/RIRB\n"); |
958 | return err; | 962 | return err; |
959 | } | 963 | } |
960 | EXPORT_SYMBOL_GPL(azx_alloc_cmd_io); | ||
961 | 964 | ||
962 | static void azx_init_cmd_io(struct azx *chip) | 965 | static void azx_init_cmd_io(struct azx *chip) |
963 | { | 966 | { |
@@ -1022,7 +1025,6 @@ static void azx_init_cmd_io(struct azx *chip) | |||
1022 | azx_writeb(chip, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN); | 1025 | azx_writeb(chip, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN); |
1023 | spin_unlock_irq(&chip->reg_lock); | 1026 | spin_unlock_irq(&chip->reg_lock); |
1024 | } | 1027 | } |
1025 | EXPORT_SYMBOL_GPL(azx_init_cmd_io); | ||
1026 | 1028 | ||
1027 | static void azx_free_cmd_io(struct azx *chip) | 1029 | static void azx_free_cmd_io(struct azx *chip) |
1028 | { | 1030 | { |
@@ -1032,7 +1034,6 @@ static void azx_free_cmd_io(struct azx *chip) | |||
1032 | azx_writeb(chip, CORBCTL, 0); | 1034 | azx_writeb(chip, CORBCTL, 0); |
1033 | spin_unlock_irq(&chip->reg_lock); | 1035 | spin_unlock_irq(&chip->reg_lock); |
1034 | } | 1036 | } |
1035 | EXPORT_SYMBOL_GPL(azx_free_cmd_io); | ||
1036 | 1037 | ||
1037 | static unsigned int azx_command_addr(u32 cmd) | 1038 | static unsigned int azx_command_addr(u32 cmd) |
1038 | { | 1039 | { |
@@ -1312,7 +1313,6 @@ static int azx_send_cmd(struct hda_bus *bus, unsigned int val) | |||
1312 | else | 1313 | else |
1313 | return azx_corb_send_cmd(bus, val); | 1314 | return azx_corb_send_cmd(bus, val); |
1314 | } | 1315 | } |
1315 | EXPORT_SYMBOL_GPL(azx_send_cmd); | ||
1316 | 1316 | ||
1317 | /* get a response */ | 1317 | /* get a response */ |
1318 | static unsigned int azx_get_response(struct hda_bus *bus, | 1318 | static unsigned int azx_get_response(struct hda_bus *bus, |
@@ -1326,7 +1326,6 @@ static unsigned int azx_get_response(struct hda_bus *bus, | |||
1326 | else | 1326 | else |
1327 | return azx_rirb_get_response(bus, addr); | 1327 | return azx_rirb_get_response(bus, addr); |
1328 | } | 1328 | } |
1329 | EXPORT_SYMBOL_GPL(azx_get_response); | ||
1330 | 1329 | ||
1331 | #ifdef CONFIG_SND_HDA_DSP_LOADER | 1330 | #ifdef CONFIG_SND_HDA_DSP_LOADER |
1332 | /* | 1331 | /* |
@@ -1993,4 +1992,4 @@ void azx_notifier_unregister(struct azx *chip) | |||
1993 | EXPORT_SYMBOL_GPL(azx_notifier_unregister); | 1992 | EXPORT_SYMBOL_GPL(azx_notifier_unregister); |
1994 | 1993 | ||
1995 | MODULE_LICENSE("GPL"); | 1994 | MODULE_LICENSE("GPL"); |
1996 | MODULE_DESCRIPTION("Common HDA driver funcitons"); | 1995 | MODULE_DESCRIPTION("Common HDA driver functions"); |
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index 014a7849e8fd..11b5a42b4ec8 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -109,7 +109,6 @@ int snd_hda_create_hwdep(struct hda_codec *codec) | |||
109 | hwdep->iface = SNDRV_HWDEP_IFACE_HDA; | 109 | hwdep->iface = SNDRV_HWDEP_IFACE_HDA; |
110 | hwdep->private_data = codec; | 110 | hwdep->private_data = codec; |
111 | hwdep->exclusive = 1; | 111 | hwdep->exclusive = 1; |
112 | hwdep->groups = snd_hda_dev_attr_groups; | ||
113 | 112 | ||
114 | hwdep->ops.open = hda_hwdep_open; | 113 | hwdep->ops.open = hda_hwdep_open; |
115 | hwdep->ops.ioctl = hda_hwdep_ioctl; | 114 | hwdep->ops.ioctl = hda_hwdep_ioctl; |
@@ -118,7 +117,11 @@ int snd_hda_create_hwdep(struct hda_codec *codec) | |||
118 | #endif | 117 | #endif |
119 | 118 | ||
120 | /* link to codec */ | 119 | /* link to codec */ |
121 | hwdep->dev = &codec->dev; | 120 | hwdep->dev.parent = &codec->dev; |
121 | |||
122 | /* for sysfs */ | ||
123 | hwdep->dev.groups = snd_hda_dev_attr_groups; | ||
124 | dev_set_drvdata(&hwdep->dev, codec); | ||
122 | 125 | ||
123 | return 0; | 126 | return 0; |
124 | } | 127 | } |
diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c index d4d0375ac181..714894527e06 100644 --- a/sound/pci/hda/hda_i915.c +++ b/sound/pci/hda/hda_i915.c | |||
@@ -18,10 +18,12 @@ | |||
18 | 18 | ||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/pci.h> | ||
22 | #include <linux/component.h> | ||
23 | #include <drm/i915_component.h> | ||
21 | #include <sound/core.h> | 24 | #include <sound/core.h> |
22 | #include <drm/i915_powerwell.h> | ||
23 | #include "hda_priv.h" | 25 | #include "hda_priv.h" |
24 | #include "hda_i915.h" | 26 | #include "hda_intel.h" |
25 | 27 | ||
26 | /* Intel HSW/BDW display HDA controller Extended Mode registers. | 28 | /* Intel HSW/BDW display HDA controller Extended Mode registers. |
27 | * EM4 (M value) and EM5 (N Value) are used to convert CDClk (Core Display | 29 | * EM4 (M value) and EM5 (N Value) are used to convert CDClk (Core Display |
@@ -31,32 +33,33 @@ | |||
31 | #define AZX_REG_EM4 0x100c | 33 | #define AZX_REG_EM4 0x100c |
32 | #define AZX_REG_EM5 0x1010 | 34 | #define AZX_REG_EM5 0x1010 |
33 | 35 | ||
34 | static int (*get_power)(void); | 36 | int hda_display_power(struct hda_intel *hda, bool enable) |
35 | static int (*put_power)(void); | ||
36 | static int (*get_cdclk)(void); | ||
37 | |||
38 | int hda_display_power(bool enable) | ||
39 | { | 37 | { |
40 | if (!get_power || !put_power) | 38 | struct i915_audio_component *acomp = &hda->audio_component; |
39 | |||
40 | if (!acomp->ops) | ||
41 | return -ENODEV; | 41 | return -ENODEV; |
42 | 42 | ||
43 | pr_debug("HDA display power %s \n", | 43 | dev_dbg(&hda->chip.pci->dev, "display power %s\n", |
44 | enable ? "Enable" : "Disable"); | 44 | enable ? "enable" : "disable"); |
45 | if (enable) | 45 | if (enable) |
46 | return get_power(); | 46 | acomp->ops->get_power(acomp->dev); |
47 | else | 47 | else |
48 | return put_power(); | 48 | acomp->ops->put_power(acomp->dev); |
49 | |||
50 | return 0; | ||
49 | } | 51 | } |
50 | 52 | ||
51 | void haswell_set_bclk(struct azx *chip) | 53 | void haswell_set_bclk(struct hda_intel *hda) |
52 | { | 54 | { |
53 | int cdclk_freq; | 55 | int cdclk_freq; |
54 | unsigned int bclk_m, bclk_n; | 56 | unsigned int bclk_m, bclk_n; |
57 | struct i915_audio_component *acomp = &hda->audio_component; | ||
55 | 58 | ||
56 | if (!get_cdclk) | 59 | if (!acomp->ops) |
57 | return; | 60 | return; |
58 | 61 | ||
59 | cdclk_freq = get_cdclk(); | 62 | cdclk_freq = acomp->ops->get_cdclk_freq(acomp->dev); |
60 | switch (cdclk_freq) { | 63 | switch (cdclk_freq) { |
61 | case 337500: | 64 | case 337500: |
62 | bclk_m = 16; | 65 | bclk_m = 16; |
@@ -80,51 +83,108 @@ void haswell_set_bclk(struct azx *chip) | |||
80 | break; | 83 | break; |
81 | } | 84 | } |
82 | 85 | ||
83 | azx_writew(chip, EM4, bclk_m); | 86 | azx_writew(&hda->chip, EM4, bclk_m); |
84 | azx_writew(chip, EM5, bclk_n); | 87 | azx_writew(&hda->chip, EM5, bclk_n); |
85 | } | 88 | } |
86 | 89 | ||
87 | 90 | static int hda_component_master_bind(struct device *dev) | |
88 | int hda_i915_init(void) | ||
89 | { | 91 | { |
90 | int err = 0; | 92 | struct snd_card *card = dev_get_drvdata(dev); |
91 | 93 | struct azx *chip = card->private_data; | |
92 | get_power = symbol_request(i915_request_power_well); | 94 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); |
93 | if (!get_power) { | 95 | struct i915_audio_component *acomp = &hda->audio_component; |
94 | pr_warn("hda-i915: get_power symbol get fail\n"); | 96 | int ret; |
95 | return -ENODEV; | 97 | |
98 | ret = component_bind_all(dev, acomp); | ||
99 | if (ret < 0) | ||
100 | return ret; | ||
101 | |||
102 | if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power && | ||
103 | acomp->ops->put_power && acomp->ops->get_cdclk_freq))) { | ||
104 | ret = -EINVAL; | ||
105 | goto out_unbind; | ||
96 | } | 106 | } |
97 | 107 | ||
98 | put_power = symbol_request(i915_release_power_well); | 108 | /* |
99 | if (!put_power) { | 109 | * Atm, we don't support dynamic unbinding initiated by the child |
100 | symbol_put(i915_request_power_well); | 110 | * component, so pin its containing module until we unbind. |
101 | get_power = NULL; | 111 | */ |
102 | return -ENODEV; | 112 | if (!try_module_get(acomp->ops->owner)) { |
113 | ret = -ENODEV; | ||
114 | goto out_unbind; | ||
103 | } | 115 | } |
104 | 116 | ||
105 | get_cdclk = symbol_request(i915_get_cdclk_freq); | 117 | return 0; |
106 | if (!get_cdclk) /* may have abnormal BCLK and audio playback rate */ | ||
107 | pr_warn("hda-i915: get_cdclk symbol get fail\n"); | ||
108 | 118 | ||
109 | pr_debug("HDA driver get symbol successfully from i915 module\n"); | 119 | out_unbind: |
120 | component_unbind_all(dev, acomp); | ||
110 | 121 | ||
111 | return err; | 122 | return ret; |
112 | } | 123 | } |
113 | 124 | ||
114 | int hda_i915_exit(void) | 125 | static void hda_component_master_unbind(struct device *dev) |
115 | { | 126 | { |
116 | if (get_power) { | 127 | struct snd_card *card = dev_get_drvdata(dev); |
117 | symbol_put(i915_request_power_well); | 128 | struct azx *chip = card->private_data; |
118 | get_power = NULL; | 129 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); |
119 | } | 130 | struct i915_audio_component *acomp = &hda->audio_component; |
120 | if (put_power) { | 131 | |
121 | symbol_put(i915_release_power_well); | 132 | module_put(acomp->ops->owner); |
122 | put_power = NULL; | 133 | component_unbind_all(dev, acomp); |
123 | } | 134 | WARN_ON(acomp->ops || acomp->dev); |
124 | if (get_cdclk) { | 135 | } |
125 | symbol_put(i915_get_cdclk_freq); | 136 | |
126 | get_cdclk = NULL; | 137 | static const struct component_master_ops hda_component_master_ops = { |
138 | .bind = hda_component_master_bind, | ||
139 | .unbind = hda_component_master_unbind, | ||
140 | }; | ||
141 | |||
142 | static int hda_component_master_match(struct device *dev, void *data) | ||
143 | { | ||
144 | /* i915 is the only supported component */ | ||
145 | return !strcmp(dev->driver->name, "i915"); | ||
146 | } | ||
147 | |||
148 | int hda_i915_init(struct hda_intel *hda) | ||
149 | { | ||
150 | struct component_match *match = NULL; | ||
151 | struct device *dev = &hda->chip.pci->dev; | ||
152 | struct i915_audio_component *acomp = &hda->audio_component; | ||
153 | int ret; | ||
154 | |||
155 | component_match_add(dev, &match, hda_component_master_match, hda); | ||
156 | ret = component_master_add_with_match(dev, &hda_component_master_ops, | ||
157 | match); | ||
158 | if (ret < 0) | ||
159 | goto out_err; | ||
160 | |||
161 | /* | ||
162 | * Atm, we don't support deferring the component binding, so make sure | ||
163 | * i915 is loaded and that the binding successfully completes. | ||
164 | */ | ||
165 | request_module("i915"); | ||
166 | |||
167 | if (!acomp->ops) { | ||
168 | ret = -ENODEV; | ||
169 | goto out_master_del; | ||
127 | } | 170 | } |
128 | 171 | ||
172 | dev_dbg(dev, "bound to i915 component master\n"); | ||
173 | |||
174 | return 0; | ||
175 | out_master_del: | ||
176 | component_master_del(dev, &hda_component_master_ops); | ||
177 | out_err: | ||
178 | dev_err(dev, "failed to add i915 component master (%d)\n", ret); | ||
179 | |||
180 | return ret; | ||
181 | } | ||
182 | |||
183 | int hda_i915_exit(struct hda_intel *hda) | ||
184 | { | ||
185 | struct device *dev = &hda->chip.pci->dev; | ||
186 | |||
187 | component_master_del(dev, &hda_component_master_ops); | ||
188 | |||
129 | return 0; | 189 | return 0; |
130 | } | 190 | } |
diff --git a/sound/pci/hda/hda_i915.h b/sound/pci/hda/hda_i915.h deleted file mode 100644 index e6072c627583..000000000000 --- a/sound/pci/hda/hda_i915.h +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License as published by the Free | ||
4 | * Software Foundation; either version 2 of the License, or (at your option) | ||
5 | * any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
8 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
9 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
10 | * more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License along with | ||
13 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
14 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
15 | */ | ||
16 | #ifndef __SOUND_HDA_I915_H | ||
17 | #define __SOUND_HDA_I915_H | ||
18 | |||
19 | #ifdef CONFIG_SND_HDA_I915 | ||
20 | int hda_display_power(bool enable); | ||
21 | void haswell_set_bclk(struct azx *chip); | ||
22 | int hda_i915_init(void); | ||
23 | int hda_i915_exit(void); | ||
24 | #else | ||
25 | static inline int hda_display_power(bool enable) { return 0; } | ||
26 | static inline void haswell_set_bclk(struct azx *chip) { return; } | ||
27 | static inline int hda_i915_init(void) | ||
28 | { | ||
29 | return -ENODEV; | ||
30 | } | ||
31 | static inline int hda_i915_exit(void) | ||
32 | { | ||
33 | return 0; | ||
34 | } | ||
35 | #endif | ||
36 | |||
37 | #endif | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d426a0bd6a5f..4ca3d5d02436 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -63,7 +63,7 @@ | |||
63 | #include "hda_codec.h" | 63 | #include "hda_codec.h" |
64 | #include "hda_controller.h" | 64 | #include "hda_controller.h" |
65 | #include "hda_priv.h" | 65 | #include "hda_priv.h" |
66 | #include "hda_i915.h" | 66 | #include "hda_intel.h" |
67 | 67 | ||
68 | /* position fix mode */ | 68 | /* position fix mode */ |
69 | enum { | 69 | enum { |
@@ -354,31 +354,6 @@ static char *driver_short_names[] = { | |||
354 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", | 354 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", |
355 | }; | 355 | }; |
356 | 356 | ||
357 | struct hda_intel { | ||
358 | struct azx chip; | ||
359 | |||
360 | /* for pending irqs */ | ||
361 | struct work_struct irq_pending_work; | ||
362 | |||
363 | /* sync probing */ | ||
364 | struct completion probe_wait; | ||
365 | struct work_struct probe_work; | ||
366 | |||
367 | /* card list (for power_save trigger) */ | ||
368 | struct list_head list; | ||
369 | |||
370 | /* extra flags */ | ||
371 | unsigned int irq_pending_warned:1; | ||
372 | |||
373 | /* VGA-switcheroo setup */ | ||
374 | unsigned int use_vga_switcheroo:1; | ||
375 | unsigned int vga_switcheroo_registered:1; | ||
376 | unsigned int init_failed:1; /* delayed init failed */ | ||
377 | |||
378 | /* secondary power domain for hdmi audio under vga device */ | ||
379 | struct dev_pm_domain hdmi_pm_domain; | ||
380 | }; | ||
381 | |||
382 | #ifdef CONFIG_X86 | 357 | #ifdef CONFIG_X86 |
383 | static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) | 358 | static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) |
384 | { | 359 | { |
@@ -795,7 +770,6 @@ static int param_set_xint(const char *val, const struct kernel_param *kp) | |||
795 | */ | 770 | */ |
796 | static int azx_suspend(struct device *dev) | 771 | static int azx_suspend(struct device *dev) |
797 | { | 772 | { |
798 | struct pci_dev *pci = to_pci_dev(dev); | ||
799 | struct snd_card *card = dev_get_drvdata(dev); | 773 | struct snd_card *card = dev_get_drvdata(dev); |
800 | struct azx *chip; | 774 | struct azx *chip; |
801 | struct hda_intel *hda; | 775 | struct hda_intel *hda; |
@@ -824,11 +798,8 @@ static int azx_suspend(struct device *dev) | |||
824 | 798 | ||
825 | if (chip->msi) | 799 | if (chip->msi) |
826 | pci_disable_msi(chip->pci); | 800 | pci_disable_msi(chip->pci); |
827 | pci_disable_device(pci); | ||
828 | pci_save_state(pci); | ||
829 | pci_set_power_state(pci, PCI_D3hot); | ||
830 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) | 801 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) |
831 | hda_display_power(false); | 802 | hda_display_power(hda, false); |
832 | return 0; | 803 | return 0; |
833 | } | 804 | } |
834 | 805 | ||
@@ -848,18 +819,9 @@ static int azx_resume(struct device *dev) | |||
848 | return 0; | 819 | return 0; |
849 | 820 | ||
850 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 821 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { |
851 | hda_display_power(true); | 822 | hda_display_power(hda, true); |
852 | haswell_set_bclk(chip); | 823 | haswell_set_bclk(hda); |
853 | } | ||
854 | pci_set_power_state(pci, PCI_D0); | ||
855 | pci_restore_state(pci); | ||
856 | if (pci_enable_device(pci) < 0) { | ||
857 | dev_err(chip->card->dev, | ||
858 | "pci_enable_device failed, disabling device\n"); | ||
859 | snd_card_disconnect(card); | ||
860 | return -EIO; | ||
861 | } | 824 | } |
862 | pci_set_master(pci); | ||
863 | if (chip->msi) | 825 | if (chip->msi) |
864 | if (pci_enable_msi(pci) < 0) | 826 | if (pci_enable_msi(pci) < 0) |
865 | chip->msi = 0; | 827 | chip->msi = 0; |
@@ -901,7 +863,7 @@ static int azx_runtime_suspend(struct device *dev) | |||
901 | azx_enter_link_reset(chip); | 863 | azx_enter_link_reset(chip); |
902 | azx_clear_irq_pending(chip); | 864 | azx_clear_irq_pending(chip); |
903 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) | 865 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) |
904 | hda_display_power(false); | 866 | hda_display_power(hda, false); |
905 | 867 | ||
906 | return 0; | 868 | return 0; |
907 | } | 869 | } |
@@ -927,8 +889,8 @@ static int azx_runtime_resume(struct device *dev) | |||
927 | return 0; | 889 | return 0; |
928 | 890 | ||
929 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 891 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { |
930 | hda_display_power(true); | 892 | hda_display_power(hda, true); |
931 | haswell_set_bclk(chip); | 893 | haswell_set_bclk(hda); |
932 | } | 894 | } |
933 | 895 | ||
934 | /* Read STATESTS before controller reset */ | 896 | /* Read STATESTS before controller reset */ |
@@ -1138,8 +1100,7 @@ static int azx_free(struct azx *chip) | |||
1138 | free_irq(chip->irq, (void*)chip); | 1100 | free_irq(chip->irq, (void*)chip); |
1139 | if (chip->msi) | 1101 | if (chip->msi) |
1140 | pci_disable_msi(chip->pci); | 1102 | pci_disable_msi(chip->pci); |
1141 | if (chip->remap_addr) | 1103 | iounmap(chip->remap_addr); |
1142 | iounmap(chip->remap_addr); | ||
1143 | 1104 | ||
1144 | azx_free_stream_pages(chip); | 1105 | azx_free_stream_pages(chip); |
1145 | if (chip->region_requested) | 1106 | if (chip->region_requested) |
@@ -1150,8 +1111,8 @@ static int azx_free(struct azx *chip) | |||
1150 | release_firmware(chip->fw); | 1111 | release_firmware(chip->fw); |
1151 | #endif | 1112 | #endif |
1152 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 1113 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { |
1153 | hda_display_power(false); | 1114 | hda_display_power(hda, false); |
1154 | hda_i915_exit(); | 1115 | hda_i915_exit(hda); |
1155 | } | 1116 | } |
1156 | kfree(hda); | 1117 | kfree(hda); |
1157 | 1118 | ||
@@ -1629,8 +1590,12 @@ static int azx_first_init(struct azx *chip) | |||
1629 | /* initialize chip */ | 1590 | /* initialize chip */ |
1630 | azx_init_pci(chip); | 1591 | azx_init_pci(chip); |
1631 | 1592 | ||
1632 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) | 1593 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { |
1633 | haswell_set_bclk(chip); | 1594 | struct hda_intel *hda; |
1595 | |||
1596 | hda = container_of(chip, struct hda_intel, chip); | ||
1597 | haswell_set_bclk(hda); | ||
1598 | } | ||
1634 | 1599 | ||
1635 | azx_init_chip(chip, (probe_only[dev] & 2) == 0); | 1600 | azx_init_chip(chip, (probe_only[dev] & 2) == 0); |
1636 | 1601 | ||
@@ -1910,13 +1875,10 @@ static int azx_probe_continue(struct azx *chip) | |||
1910 | /* Request power well for Haswell HDA controller and codec */ | 1875 | /* Request power well for Haswell HDA controller and codec */ |
1911 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 1876 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { |
1912 | #ifdef CONFIG_SND_HDA_I915 | 1877 | #ifdef CONFIG_SND_HDA_I915 |
1913 | err = hda_i915_init(); | 1878 | err = hda_i915_init(hda); |
1914 | if (err < 0) { | 1879 | if (err < 0) |
1915 | dev_err(chip->card->dev, | ||
1916 | "Error request power-well from i915\n"); | ||
1917 | goto out_free; | 1880 | goto out_free; |
1918 | } | 1881 | err = hda_display_power(hda, true); |
1919 | err = hda_display_power(true); | ||
1920 | if (err < 0) { | 1882 | if (err < 0) { |
1921 | dev_err(chip->card->dev, | 1883 | dev_err(chip->card->dev, |
1922 | "Cannot turn on display power on i915\n"); | 1884 | "Cannot turn on display power on i915\n"); |
@@ -2004,7 +1966,7 @@ static const struct pci_device_id azx_ids[] = { | |||
2004 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, | 1966 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, |
2005 | /* Panther Point */ | 1967 | /* Panther Point */ |
2006 | { PCI_DEVICE(0x8086, 0x1e20), | 1968 | { PCI_DEVICE(0x8086, 0x1e20), |
2007 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | 1969 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, |
2008 | /* Lynx Point */ | 1970 | /* Lynx Point */ |
2009 | { PCI_DEVICE(0x8086, 0x8c20), | 1971 | { PCI_DEVICE(0x8086, 0x8c20), |
2010 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | 1972 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, |
diff --git a/sound/pci/hda/hda_intel.h b/sound/pci/hda/hda_intel.h new file mode 100644 index 000000000000..348611835476 --- /dev/null +++ b/sound/pci/hda/hda_intel.h | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License as published by the Free | ||
4 | * Software Foundation; either version 2 of the License, or (at your option) | ||
5 | * any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
8 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
9 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
10 | * more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License along with | ||
13 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
14 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
15 | */ | ||
16 | #ifndef __SOUND_HDA_INTEL_H | ||
17 | #define __SOUND_HDA_INTEL_H | ||
18 | |||
19 | #include <drm/i915_component.h> | ||
20 | #include "hda_priv.h" | ||
21 | |||
22 | struct hda_intel { | ||
23 | struct azx chip; | ||
24 | |||
25 | /* for pending irqs */ | ||
26 | struct work_struct irq_pending_work; | ||
27 | |||
28 | /* sync probing */ | ||
29 | struct completion probe_wait; | ||
30 | struct work_struct probe_work; | ||
31 | |||
32 | /* card list (for power_save trigger) */ | ||
33 | struct list_head list; | ||
34 | |||
35 | /* extra flags */ | ||
36 | unsigned int irq_pending_warned:1; | ||
37 | |||
38 | /* VGA-switcheroo setup */ | ||
39 | unsigned int use_vga_switcheroo:1; | ||
40 | unsigned int vga_switcheroo_registered:1; | ||
41 | unsigned int init_failed:1; /* delayed init failed */ | ||
42 | |||
43 | /* secondary power domain for hdmi audio under vga device */ | ||
44 | struct dev_pm_domain hdmi_pm_domain; | ||
45 | |||
46 | /* i915 component interface */ | ||
47 | struct i915_audio_component audio_component; | ||
48 | }; | ||
49 | |||
50 | #ifdef CONFIG_SND_HDA_I915 | ||
51 | int hda_display_power(struct hda_intel *hda, bool enable); | ||
52 | void haswell_set_bclk(struct hda_intel *hda); | ||
53 | int hda_i915_init(struct hda_intel *hda); | ||
54 | int hda_i915_exit(struct hda_intel *hda); | ||
55 | #else | ||
56 | static inline int hda_display_power(struct hda_intel *hda, bool enable) | ||
57 | { | ||
58 | return 0; | ||
59 | } | ||
60 | static inline void haswell_set_bclk(struct hda_intel *hda) { return; } | ||
61 | static inline int hda_i915_init(struct hda_intel *hda) | ||
62 | { | ||
63 | return -ENODEV; | ||
64 | } | ||
65 | static inline int hda_i915_exit(struct hda_intel *hda) | ||
66 | { | ||
67 | return 0; | ||
68 | } | ||
69 | #endif | ||
70 | |||
71 | #endif | ||
diff --git a/sound/pci/hda/hda_priv.h b/sound/pci/hda/hda_priv.h index 166e3e84b963..daf458299753 100644 --- a/sound/pci/hda/hda_priv.h +++ b/sound/pci/hda/hda_priv.h | |||
@@ -15,7 +15,7 @@ | |||
15 | #ifndef __SOUND_HDA_PRIV_H | 15 | #ifndef __SOUND_HDA_PRIV_H |
16 | #define __SOUND_HDA_PRIV_H | 16 | #define __SOUND_HDA_PRIV_H |
17 | 17 | ||
18 | #include <linux/clocksource.h> | 18 | #include <linux/timecounter.h> |
19 | #include <sound/core.h> | 19 | #include <sound/core.h> |
20 | #include <sound/pcm.h> | 20 | #include <sound/pcm.h> |
21 | 21 | ||
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 227990bc02e3..375e94f4cf52 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c | |||
@@ -329,8 +329,8 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) | |||
329 | 329 | ||
330 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 330 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
331 | hda->regs = devm_ioremap_resource(dev, res); | 331 | hda->regs = devm_ioremap_resource(dev, res); |
332 | if (IS_ERR(chip->remap_addr)) | 332 | if (IS_ERR(hda->regs)) |
333 | return PTR_ERR(chip->remap_addr); | 333 | return PTR_ERR(hda->regs); |
334 | 334 | ||
335 | chip->remap_addr = hda->regs + HDA_BAR0; | 335 | chip->remap_addr = hda->regs + HDA_BAR0; |
336 | chip->addr = res->start + HDA_BAR0; | 336 | chip->addr = res->start + HDA_BAR0; |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index a9d78e275138..d285904cdb64 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -739,39 +739,6 @@ static int patch_ad1981(struct hda_codec *codec) | |||
739 | * E/F quad mic array | 739 | * E/F quad mic array |
740 | */ | 740 | */ |
741 | 741 | ||
742 | #ifdef ENABLE_AD_STATIC_QUIRKS | ||
743 | static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol, | ||
744 | struct snd_ctl_elem_info *uinfo) | ||
745 | { | ||
746 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
747 | struct ad198x_spec *spec = codec->spec; | ||
748 | return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, | ||
749 | spec->num_channel_mode); | ||
750 | } | ||
751 | |||
752 | static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol, | ||
753 | struct snd_ctl_elem_value *ucontrol) | ||
754 | { | ||
755 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
756 | struct ad198x_spec *spec = codec->spec; | ||
757 | return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, | ||
758 | spec->num_channel_mode, spec->multiout.max_channels); | ||
759 | } | ||
760 | |||
761 | static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, | ||
762 | struct snd_ctl_elem_value *ucontrol) | ||
763 | { | ||
764 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
765 | struct ad198x_spec *spec = codec->spec; | ||
766 | int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, | ||
767 | spec->num_channel_mode, | ||
768 | &spec->multiout.max_channels); | ||
769 | if (err >= 0 && spec->need_dac_fix) | ||
770 | spec->multiout.num_dacs = spec->multiout.max_channels / 2; | ||
771 | return err; | ||
772 | } | ||
773 | #endif /* ENABLE_AD_STATIC_QUIRKS */ | ||
774 | |||
775 | static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol, | 742 | static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol, |
776 | struct snd_ctl_elem_info *uinfo) | 743 | struct snd_ctl_elem_info *uinfo) |
777 | { | 744 | { |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 65f1f4e18ea5..b2b24a8b3dac 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
30 | #include <linux/dmi.h> | 30 | #include <linux/dmi.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/input.h> | ||
32 | #include <sound/core.h> | 33 | #include <sound/core.h> |
33 | #include <sound/jack.h> | 34 | #include <sound/jack.h> |
34 | #include "hda_codec.h" | 35 | #include "hda_codec.h" |
@@ -120,6 +121,7 @@ struct alc_spec { | |||
120 | hda_nid_t pll_nid; | 121 | hda_nid_t pll_nid; |
121 | unsigned int pll_coef_idx, pll_coef_bit; | 122 | unsigned int pll_coef_idx, pll_coef_bit; |
122 | unsigned int coef0; | 123 | unsigned int coef0; |
124 | struct input_dev *kb_dev; | ||
123 | }; | 125 | }; |
124 | 126 | ||
125 | /* | 127 | /* |
@@ -3472,6 +3474,79 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec, | |||
3472 | } | 3474 | } |
3473 | } | 3475 | } |
3474 | 3476 | ||
3477 | static void gpio2_mic_hotkey_event(struct hda_codec *codec, | ||
3478 | struct hda_jack_callback *event) | ||
3479 | { | ||
3480 | struct alc_spec *spec = codec->spec; | ||
3481 | |||
3482 | /* GPIO2 just toggles on a keypress/keyrelease cycle. Therefore | ||
3483 | send both key on and key off event for every interrupt. */ | ||
3484 | input_report_key(spec->kb_dev, KEY_MICMUTE, 1); | ||
3485 | input_sync(spec->kb_dev); | ||
3486 | input_report_key(spec->kb_dev, KEY_MICMUTE, 0); | ||
3487 | input_sync(spec->kb_dev); | ||
3488 | } | ||
3489 | |||
3490 | static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec, | ||
3491 | const struct hda_fixup *fix, int action) | ||
3492 | { | ||
3493 | /* GPIO1 = set according to SKU external amp | ||
3494 | GPIO2 = mic mute hotkey | ||
3495 | GPIO3 = mute LED | ||
3496 | GPIO4 = mic mute LED */ | ||
3497 | static const struct hda_verb gpio_init[] = { | ||
3498 | { 0x01, AC_VERB_SET_GPIO_MASK, 0x1e }, | ||
3499 | { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x1a }, | ||
3500 | { 0x01, AC_VERB_SET_GPIO_DATA, 0x02 }, | ||
3501 | {} | ||
3502 | }; | ||
3503 | |||
3504 | struct alc_spec *spec = codec->spec; | ||
3505 | |||
3506 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
3507 | spec->kb_dev = input_allocate_device(); | ||
3508 | if (!spec->kb_dev) { | ||
3509 | codec_err(codec, "Out of memory (input_allocate_device)\n"); | ||
3510 | return; | ||
3511 | } | ||
3512 | spec->kb_dev->name = "Microphone Mute Button"; | ||
3513 | spec->kb_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
3514 | spec->kb_dev->keybit[BIT_WORD(KEY_MICMUTE)] = BIT_MASK(KEY_MICMUTE); | ||
3515 | if (input_register_device(spec->kb_dev)) { | ||
3516 | codec_err(codec, "input_register_device failed\n"); | ||
3517 | input_free_device(spec->kb_dev); | ||
3518 | spec->kb_dev = NULL; | ||
3519 | return; | ||
3520 | } | ||
3521 | |||
3522 | snd_hda_add_verbs(codec, gpio_init); | ||
3523 | snd_hda_codec_write_cache(codec, codec->afg, 0, | ||
3524 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x04); | ||
3525 | snd_hda_jack_detect_enable_callback(codec, codec->afg, | ||
3526 | gpio2_mic_hotkey_event); | ||
3527 | |||
3528 | spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; | ||
3529 | spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook; | ||
3530 | spec->gpio_led = 0; | ||
3531 | spec->mute_led_polarity = 0; | ||
3532 | spec->gpio_mute_led_mask = 0x08; | ||
3533 | spec->gpio_mic_led_mask = 0x10; | ||
3534 | return; | ||
3535 | } | ||
3536 | |||
3537 | if (!spec->kb_dev) | ||
3538 | return; | ||
3539 | |||
3540 | switch (action) { | ||
3541 | case HDA_FIXUP_ACT_PROBE: | ||
3542 | spec->init_amp = ALC_INIT_DEFAULT; | ||
3543 | break; | ||
3544 | case HDA_FIXUP_ACT_FREE: | ||
3545 | input_unregister_device(spec->kb_dev); | ||
3546 | spec->kb_dev = NULL; | ||
3547 | } | ||
3548 | } | ||
3549 | |||
3475 | static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, | 3550 | static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, |
3476 | const struct hda_fixup *fix, int action) | 3551 | const struct hda_fixup *fix, int action) |
3477 | { | 3552 | { |
@@ -4341,6 +4416,8 @@ enum { | |||
4341 | ALC282_FIXUP_ASPIRE_V5_PINS, | 4416 | ALC282_FIXUP_ASPIRE_V5_PINS, |
4342 | ALC280_FIXUP_HP_GPIO4, | 4417 | ALC280_FIXUP_HP_GPIO4, |
4343 | ALC286_FIXUP_HP_GPIO_LED, | 4418 | ALC286_FIXUP_HP_GPIO_LED, |
4419 | ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY, | ||
4420 | ALC280_FIXUP_HP_DOCK_PINS, | ||
4344 | }; | 4421 | }; |
4345 | 4422 | ||
4346 | static const struct hda_fixup alc269_fixups[] = { | 4423 | static const struct hda_fixup alc269_fixups[] = { |
@@ -4814,6 +4891,21 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4814 | .type = HDA_FIXUP_FUNC, | 4891 | .type = HDA_FIXUP_FUNC, |
4815 | .v.func = alc286_fixup_hp_gpio_led, | 4892 | .v.func = alc286_fixup_hp_gpio_led, |
4816 | }, | 4893 | }, |
4894 | [ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY] = { | ||
4895 | .type = HDA_FIXUP_FUNC, | ||
4896 | .v.func = alc280_fixup_hp_gpio2_mic_hotkey, | ||
4897 | }, | ||
4898 | [ALC280_FIXUP_HP_DOCK_PINS] = { | ||
4899 | .type = HDA_FIXUP_PINS, | ||
4900 | .v.pins = (const struct hda_pintbl[]) { | ||
4901 | { 0x1b, 0x21011020 }, /* line-out */ | ||
4902 | { 0x1a, 0x01a1903c }, /* headset mic */ | ||
4903 | { 0x18, 0x2181103f }, /* line-in */ | ||
4904 | { }, | ||
4905 | }, | ||
4906 | .chained = true, | ||
4907 | .chain_id = ALC280_FIXUP_HP_GPIO4 | ||
4908 | }, | ||
4817 | }; | 4909 | }; |
4818 | 4910 | ||
4819 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 4911 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
@@ -4843,7 +4935,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4843 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), | 4935 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), |
4844 | SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED), | 4936 | SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED), |
4845 | SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), | 4937 | SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), |
4938 | SND_PCI_QUIRK(0x103c, 0x225f, "HP", ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY), | ||
4846 | /* ALC282 */ | 4939 | /* ALC282 */ |
4940 | SND_PCI_QUIRK(0x103c, 0x21f9, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | ||
4847 | SND_PCI_QUIRK(0x103c, 0x2210, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4941 | SND_PCI_QUIRK(0x103c, 0x2210, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4848 | SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4942 | SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4849 | SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | 4943 | SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), |
@@ -4856,6 +4950,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4856 | SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4950 | SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4857 | SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4951 | SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4858 | SND_PCI_QUIRK(0x103c, 0x2271, "HP", ALC286_FIXUP_HP_GPIO_LED), | 4952 | SND_PCI_QUIRK(0x103c, 0x2271, "HP", ALC286_FIXUP_HP_GPIO_LED), |
4953 | SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC280_FIXUP_HP_DOCK_PINS), | ||
4954 | SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC280_FIXUP_HP_DOCK_PINS), | ||
4859 | SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4955 | SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4860 | SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4956 | SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4861 | SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4957 | SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 605d14003d25..87eff3173ce9 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -79,6 +79,7 @@ enum { | |||
79 | STAC_ALIENWARE_M17X, | 79 | STAC_ALIENWARE_M17X, |
80 | STAC_92HD89XX_HP_FRONT_JACK, | 80 | STAC_92HD89XX_HP_FRONT_JACK, |
81 | STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK, | 81 | STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK, |
82 | STAC_92HD73XX_ASUS_MOBO, | ||
82 | STAC_92HD73XX_MODELS | 83 | STAC_92HD73XX_MODELS |
83 | }; | 84 | }; |
84 | 85 | ||
@@ -99,6 +100,7 @@ enum { | |||
99 | STAC_HP_ENVY_BASS, | 100 | STAC_HP_ENVY_BASS, |
100 | STAC_HP_BNB13_EQ, | 101 | STAC_HP_BNB13_EQ, |
101 | STAC_HP_ENVY_TS_BASS, | 102 | STAC_HP_ENVY_TS_BASS, |
103 | STAC_92HD83XXX_GPIO10_EAPD, | ||
102 | STAC_92HD83XXX_MODELS | 104 | STAC_92HD83XXX_MODELS |
103 | }; | 105 | }; |
104 | 106 | ||
@@ -1910,7 +1912,18 @@ static const struct hda_fixup stac92hd73xx_fixups[] = { | |||
1910 | [STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = { | 1912 | [STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = { |
1911 | .type = HDA_FIXUP_PINS, | 1913 | .type = HDA_FIXUP_PINS, |
1912 | .v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs, | 1914 | .v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs, |
1913 | } | 1915 | }, |
1916 | [STAC_92HD73XX_ASUS_MOBO] = { | ||
1917 | .type = HDA_FIXUP_PINS, | ||
1918 | .v.pins = (const struct hda_pintbl[]) { | ||
1919 | /* enable 5.1 and SPDIF out */ | ||
1920 | { 0x0c, 0x01014411 }, | ||
1921 | { 0x0d, 0x01014410 }, | ||
1922 | { 0x0e, 0x01014412 }, | ||
1923 | { 0x22, 0x014b1180 }, | ||
1924 | { } | ||
1925 | } | ||
1926 | }, | ||
1914 | }; | 1927 | }; |
1915 | 1928 | ||
1916 | static const struct hda_model_fixup stac92hd73xx_models[] = { | 1929 | static const struct hda_model_fixup stac92hd73xx_models[] = { |
@@ -1922,6 +1935,7 @@ static const struct hda_model_fixup stac92hd73xx_models[] = { | |||
1922 | { .id = STAC_DELL_M6_BOTH, .name = "dell-m6" }, | 1935 | { .id = STAC_DELL_M6_BOTH, .name = "dell-m6" }, |
1923 | { .id = STAC_DELL_EQ, .name = "dell-eq" }, | 1936 | { .id = STAC_DELL_EQ, .name = "dell-eq" }, |
1924 | { .id = STAC_ALIENWARE_M17X, .name = "alienware" }, | 1937 | { .id = STAC_ALIENWARE_M17X, .name = "alienware" }, |
1938 | { .id = STAC_92HD73XX_ASUS_MOBO, .name = "asus-mobo" }, | ||
1925 | {} | 1939 | {} |
1926 | }; | 1940 | }; |
1927 | 1941 | ||
@@ -1974,6 +1988,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = { | |||
1974 | "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK), | 1988 | "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK), |
1975 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, | 1989 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, |
1976 | "unknown HP", STAC_92HD89XX_HP_FRONT_JACK), | 1990 | "unknown HP", STAC_92HD89XX_HP_FRONT_JACK), |
1991 | SND_PCI_QUIRK(PCI_VENDOR_ID_ASUSTEK, 0x83f8, "ASUS AT4NM10", | ||
1992 | STAC_92HD73XX_ASUS_MOBO), | ||
1977 | {} /* terminator */ | 1993 | {} /* terminator */ |
1978 | }; | 1994 | }; |
1979 | 1995 | ||
@@ -2141,6 +2157,19 @@ static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec, | |||
2141 | spec->headset_jack = 1; | 2157 | spec->headset_jack = 1; |
2142 | } | 2158 | } |
2143 | 2159 | ||
2160 | static void stac92hd83xxx_fixup_gpio10_eapd(struct hda_codec *codec, | ||
2161 | const struct hda_fixup *fix, | ||
2162 | int action) | ||
2163 | { | ||
2164 | struct sigmatel_spec *spec = codec->spec; | ||
2165 | |||
2166 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | ||
2167 | return; | ||
2168 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = | ||
2169 | spec->gpio_data = 0x10; | ||
2170 | spec->eapd_switch = 0; | ||
2171 | } | ||
2172 | |||
2144 | static const struct hda_verb hp_bnb13_eq_verbs[] = { | 2173 | static const struct hda_verb hp_bnb13_eq_verbs[] = { |
2145 | /* 44.1KHz base */ | 2174 | /* 44.1KHz base */ |
2146 | { 0x22, 0x7A6, 0x3E }, | 2175 | { 0x22, 0x7A6, 0x3E }, |
@@ -2656,6 +2685,10 @@ static const struct hda_fixup stac92hd83xxx_fixups[] = { | |||
2656 | {} | 2685 | {} |
2657 | }, | 2686 | }, |
2658 | }, | 2687 | }, |
2688 | [STAC_92HD83XXX_GPIO10_EAPD] = { | ||
2689 | .type = HDA_FIXUP_FUNC, | ||
2690 | .v.func = stac92hd83xxx_fixup_gpio10_eapd, | ||
2691 | }, | ||
2659 | }; | 2692 | }; |
2660 | 2693 | ||
2661 | static const struct hda_model_fixup stac92hd83xxx_models[] = { | 2694 | static const struct hda_model_fixup stac92hd83xxx_models[] = { |
@@ -2861,6 +2894,8 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = { | |||
2861 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x148a, | 2894 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x148a, |
2862 | "HP Mini", STAC_92HD83XXX_HP_LED), | 2895 | "HP Mini", STAC_92HD83XXX_HP_LED), |
2863 | SND_PCI_QUIRK_VENDOR(PCI_VENDOR_ID_HP, "HP", STAC_92HD83XXX_HP), | 2896 | SND_PCI_QUIRK_VENDOR(PCI_VENDOR_ID_HP, "HP", STAC_92HD83XXX_HP), |
2897 | SND_PCI_QUIRK(PCI_VENDOR_ID_TOSHIBA, 0xfa91, | ||
2898 | "Toshiba Satellite S50D", STAC_92HD83XXX_GPIO10_EAPD), | ||
2864 | {} /* terminator */ | 2899 | {} /* terminator */ |
2865 | }; | 2900 | }; |
2866 | 2901 | ||
diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c index 3981823f9094..179ef7a5f0d1 100644 --- a/sound/pci/ice1712/ak4xxx.c +++ b/sound/pci/ice1712/ak4xxx.c | |||
@@ -21,7 +21,7 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <asm/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index b039b46152c6..f7b1523e8a82 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -880,13 +880,11 @@ static struct snd_pcm_ops snd_ice1712_capture_ops = { | |||
880 | .pointer = snd_ice1712_capture_pointer, | 880 | .pointer = snd_ice1712_capture_pointer, |
881 | }; | 881 | }; |
882 | 882 | ||
883 | static int snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm) | 883 | static int snd_ice1712_pcm(struct snd_ice1712 *ice, int device) |
884 | { | 884 | { |
885 | struct snd_pcm *pcm; | 885 | struct snd_pcm *pcm; |
886 | int err; | 886 | int err; |
887 | 887 | ||
888 | if (rpcm) | ||
889 | *rpcm = NULL; | ||
890 | err = snd_pcm_new(ice->card, "ICE1712 consumer", device, 1, 1, &pcm); | 888 | err = snd_pcm_new(ice->card, "ICE1712 consumer", device, 1, 1, &pcm); |
891 | if (err < 0) | 889 | if (err < 0) |
892 | return err; | 890 | return err; |
@@ -902,22 +900,17 @@ static int snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct snd_pcm * | |||
902 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 900 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
903 | snd_dma_pci_data(ice->pci), 64*1024, 64*1024); | 901 | snd_dma_pci_data(ice->pci), 64*1024, 64*1024); |
904 | 902 | ||
905 | if (rpcm) | ||
906 | *rpcm = pcm; | ||
907 | |||
908 | dev_warn(ice->card->dev, | 903 | dev_warn(ice->card->dev, |
909 | "Consumer PCM code does not work well at the moment --jk\n"); | 904 | "Consumer PCM code does not work well at the moment --jk\n"); |
910 | 905 | ||
911 | return 0; | 906 | return 0; |
912 | } | 907 | } |
913 | 908 | ||
914 | static int snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm) | 909 | static int snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device) |
915 | { | 910 | { |
916 | struct snd_pcm *pcm; | 911 | struct snd_pcm *pcm; |
917 | int err; | 912 | int err; |
918 | 913 | ||
919 | if (rpcm) | ||
920 | *rpcm = NULL; | ||
921 | err = snd_pcm_new(ice->card, "ICE1712 consumer (DS)", device, 6, 0, &pcm); | 914 | err = snd_pcm_new(ice->card, "ICE1712 consumer (DS)", device, 6, 0, &pcm); |
922 | if (err < 0) | 915 | if (err < 0) |
923 | return err; | 916 | return err; |
@@ -932,9 +925,6 @@ static int snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device, struct snd_pc | |||
932 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 925 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
933 | snd_dma_pci_data(ice->pci), 64*1024, 128*1024); | 926 | snd_dma_pci_data(ice->pci), 64*1024, 128*1024); |
934 | 927 | ||
935 | if (rpcm) | ||
936 | *rpcm = pcm; | ||
937 | |||
938 | return 0; | 928 | return 0; |
939 | } | 929 | } |
940 | 930 | ||
@@ -1260,13 +1250,11 @@ static struct snd_pcm_ops snd_ice1712_capture_pro_ops = { | |||
1260 | .pointer = snd_ice1712_capture_pro_pointer, | 1250 | .pointer = snd_ice1712_capture_pro_pointer, |
1261 | }; | 1251 | }; |
1262 | 1252 | ||
1263 | static int snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm) | 1253 | static int snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device) |
1264 | { | 1254 | { |
1265 | struct snd_pcm *pcm; | 1255 | struct snd_pcm *pcm; |
1266 | int err; | 1256 | int err; |
1267 | 1257 | ||
1268 | if (rpcm) | ||
1269 | *rpcm = NULL; | ||
1270 | err = snd_pcm_new(ice->card, "ICE1712 multi", device, 1, 1, &pcm); | 1258 | err = snd_pcm_new(ice->card, "ICE1712 multi", device, 1, 1, &pcm); |
1271 | if (err < 0) | 1259 | if (err < 0) |
1272 | return err; | 1260 | return err; |
@@ -1282,8 +1270,6 @@ static int snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device, struct snd | |||
1282 | snd_dma_pci_data(ice->pci), 256*1024, 256*1024); | 1270 | snd_dma_pci_data(ice->pci), 256*1024, 256*1024); |
1283 | 1271 | ||
1284 | ice->pcm_pro = pcm; | 1272 | ice->pcm_pro = pcm; |
1285 | if (rpcm) | ||
1286 | *rpcm = pcm; | ||
1287 | 1273 | ||
1288 | if (ice->cs8427) { | 1274 | if (ice->cs8427) { |
1289 | /* assign channels to iec958 */ | 1275 | /* assign channels to iec958 */ |
@@ -2691,14 +2677,14 @@ static int snd_ice1712_probe(struct pci_dev *pci, | |||
2691 | c = &no_matched; | 2677 | c = &no_matched; |
2692 | __found: | 2678 | __found: |
2693 | 2679 | ||
2694 | err = snd_ice1712_pcm_profi(ice, pcm_dev++, NULL); | 2680 | err = snd_ice1712_pcm_profi(ice, pcm_dev++); |
2695 | if (err < 0) { | 2681 | if (err < 0) { |
2696 | snd_card_free(card); | 2682 | snd_card_free(card); |
2697 | return err; | 2683 | return err; |
2698 | } | 2684 | } |
2699 | 2685 | ||
2700 | if (ice_has_con_ac97(ice)) { | 2686 | if (ice_has_con_ac97(ice)) { |
2701 | err = snd_ice1712_pcm(ice, pcm_dev++, NULL); | 2687 | err = snd_ice1712_pcm(ice, pcm_dev++); |
2702 | if (err < 0) { | 2688 | if (err < 0) { |
2703 | snd_card_free(card); | 2689 | snd_card_free(card); |
2704 | return err; | 2690 | return err; |
@@ -2726,7 +2712,7 @@ static int snd_ice1712_probe(struct pci_dev *pci, | |||
2726 | } | 2712 | } |
2727 | 2713 | ||
2728 | if (ice_has_con_ac97(ice)) { | 2714 | if (ice_has_con_ac97(ice)) { |
2729 | err = snd_ice1712_pcm_ds(ice, pcm_dev++, NULL); | 2715 | err = snd_ice1712_pcm_ds(ice, pcm_dev++); |
2730 | if (err < 0) { | 2716 | if (err < 0) { |
2731 | snd_card_free(card); | 2717 | snd_card_free(card); |
2732 | return err; | 2718 | return err; |
@@ -2798,7 +2784,6 @@ static void snd_ice1712_remove(struct pci_dev *pci) | |||
2798 | #ifdef CONFIG_PM_SLEEP | 2784 | #ifdef CONFIG_PM_SLEEP |
2799 | static int snd_ice1712_suspend(struct device *dev) | 2785 | static int snd_ice1712_suspend(struct device *dev) |
2800 | { | 2786 | { |
2801 | struct pci_dev *pci = to_pci_dev(dev); | ||
2802 | struct snd_card *card = dev_get_drvdata(dev); | 2787 | struct snd_card *card = dev_get_drvdata(dev); |
2803 | struct snd_ice1712 *ice = card->private_data; | 2788 | struct snd_ice1712 *ice = card->private_data; |
2804 | 2789 | ||
@@ -2820,16 +2805,11 @@ static int snd_ice1712_suspend(struct device *dev) | |||
2820 | 2805 | ||
2821 | if (ice->pm_suspend) | 2806 | if (ice->pm_suspend) |
2822 | ice->pm_suspend(ice); | 2807 | ice->pm_suspend(ice); |
2823 | |||
2824 | pci_disable_device(pci); | ||
2825 | pci_save_state(pci); | ||
2826 | pci_set_power_state(pci, PCI_D3hot); | ||
2827 | return 0; | 2808 | return 0; |
2828 | } | 2809 | } |
2829 | 2810 | ||
2830 | static int snd_ice1712_resume(struct device *dev) | 2811 | static int snd_ice1712_resume(struct device *dev) |
2831 | { | 2812 | { |
2832 | struct pci_dev *pci = to_pci_dev(dev); | ||
2833 | struct snd_card *card = dev_get_drvdata(dev); | 2813 | struct snd_card *card = dev_get_drvdata(dev); |
2834 | struct snd_ice1712 *ice = card->private_data; | 2814 | struct snd_ice1712 *ice = card->private_data; |
2835 | int rate; | 2815 | int rate; |
@@ -2837,16 +2817,6 @@ static int snd_ice1712_resume(struct device *dev) | |||
2837 | if (!ice->pm_suspend_enabled) | 2817 | if (!ice->pm_suspend_enabled) |
2838 | return 0; | 2818 | return 0; |
2839 | 2819 | ||
2840 | pci_set_power_state(pci, PCI_D0); | ||
2841 | pci_restore_state(pci); | ||
2842 | |||
2843 | if (pci_enable_device(pci) < 0) { | ||
2844 | snd_card_disconnect(card); | ||
2845 | return -EIO; | ||
2846 | } | ||
2847 | |||
2848 | pci_set_master(pci); | ||
2849 | |||
2850 | if (ice->cur_rate) | 2820 | if (ice->cur_rate) |
2851 | rate = ice->cur_rate; | 2821 | rate = ice->cur_rate; |
2852 | else | 2822 | else |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index d73da157ea14..0b22c00642bb 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -2798,7 +2798,6 @@ static void snd_vt1724_remove(struct pci_dev *pci) | |||
2798 | #ifdef CONFIG_PM_SLEEP | 2798 | #ifdef CONFIG_PM_SLEEP |
2799 | static int snd_vt1724_suspend(struct device *dev) | 2799 | static int snd_vt1724_suspend(struct device *dev) |
2800 | { | 2800 | { |
2801 | struct pci_dev *pci = to_pci_dev(dev); | ||
2802 | struct snd_card *card = dev_get_drvdata(dev); | 2801 | struct snd_card *card = dev_get_drvdata(dev); |
2803 | struct snd_ice1712 *ice = card->private_data; | 2802 | struct snd_ice1712 *ice = card->private_data; |
2804 | 2803 | ||
@@ -2821,32 +2820,17 @@ static int snd_vt1724_suspend(struct device *dev) | |||
2821 | 2820 | ||
2822 | if (ice->pm_suspend) | 2821 | if (ice->pm_suspend) |
2823 | ice->pm_suspend(ice); | 2822 | ice->pm_suspend(ice); |
2824 | |||
2825 | pci_disable_device(pci); | ||
2826 | pci_save_state(pci); | ||
2827 | pci_set_power_state(pci, PCI_D3hot); | ||
2828 | return 0; | 2823 | return 0; |
2829 | } | 2824 | } |
2830 | 2825 | ||
2831 | static int snd_vt1724_resume(struct device *dev) | 2826 | static int snd_vt1724_resume(struct device *dev) |
2832 | { | 2827 | { |
2833 | struct pci_dev *pci = to_pci_dev(dev); | ||
2834 | struct snd_card *card = dev_get_drvdata(dev); | 2828 | struct snd_card *card = dev_get_drvdata(dev); |
2835 | struct snd_ice1712 *ice = card->private_data; | 2829 | struct snd_ice1712 *ice = card->private_data; |
2836 | 2830 | ||
2837 | if (!ice->pm_suspend_enabled) | 2831 | if (!ice->pm_suspend_enabled) |
2838 | return 0; | 2832 | return 0; |
2839 | 2833 | ||
2840 | pci_set_power_state(pci, PCI_D0); | ||
2841 | pci_restore_state(pci); | ||
2842 | |||
2843 | if (pci_enable_device(pci) < 0) { | ||
2844 | snd_card_disconnect(card); | ||
2845 | return -EIO; | ||
2846 | } | ||
2847 | |||
2848 | pci_set_master(pci); | ||
2849 | |||
2850 | snd_vt1724_chip_reset(ice); | 2834 | snd_vt1724_chip_reset(ice); |
2851 | 2835 | ||
2852 | if (snd_vt1724_chip_init(ice) < 0) { | 2836 | if (snd_vt1724_chip_init(ice) < 0) { |
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index a1536c1a7ed4..4f0213427152 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c | |||
@@ -491,15 +491,17 @@ static int juli_resume(struct snd_ice1712 *ice) | |||
491 | /* akm4358 un-reset, un-mute */ | 491 | /* akm4358 un-reset, un-mute */ |
492 | snd_akm4xxx_reset(ak, 0); | 492 | snd_akm4xxx_reset(ak, 0); |
493 | /* reinit ak4114 */ | 493 | /* reinit ak4114 */ |
494 | snd_ak4114_reinit(spec->ak4114); | 494 | snd_ak4114_resume(spec->ak4114); |
495 | return 0; | 495 | return 0; |
496 | } | 496 | } |
497 | 497 | ||
498 | static int juli_suspend(struct snd_ice1712 *ice) | 498 | static int juli_suspend(struct snd_ice1712 *ice) |
499 | { | 499 | { |
500 | struct snd_akm4xxx *ak = ice->akm; | 500 | struct snd_akm4xxx *ak = ice->akm; |
501 | struct juli_spec *spec = ice->spec; | ||
501 | /* akm4358 reset and soft-mute */ | 502 | /* akm4358 reset and soft-mute */ |
502 | snd_akm4xxx_reset(ak, 1); | 503 | snd_akm4xxx_reset(ak, 1); |
504 | snd_ak4114_suspend(spec->ak4114); | ||
503 | return 0; | 505 | return 0; |
504 | } | 506 | } |
505 | #endif | 507 | #endif |
diff --git a/sound/pci/ice1712/wm8766.c b/sound/pci/ice1712/wm8766.c index 21b373b2e260..f7ac8d5e862c 100644 --- a/sound/pci/ice1712/wm8766.c +++ b/sound/pci/ice1712/wm8766.c | |||
@@ -183,22 +183,6 @@ void snd_wm8766_set_if(struct snd_wm8766 *wm, u16 dac) | |||
183 | snd_wm8766_write(wm, WM8766_REG_IFCTRL, val | dac); | 183 | snd_wm8766_write(wm, WM8766_REG_IFCTRL, val | dac); |
184 | } | 184 | } |
185 | 185 | ||
186 | void snd_wm8766_set_master_mode(struct snd_wm8766 *wm, u16 mode) | ||
187 | { | ||
188 | u16 val = wm->regs[WM8766_REG_DACCTRL3] & ~WM8766_DAC3_MSTR_MASK; | ||
189 | |||
190 | mode &= WM8766_DAC3_MSTR_MASK; | ||
191 | snd_wm8766_write(wm, WM8766_REG_DACCTRL3, val | mode); | ||
192 | } | ||
193 | |||
194 | void snd_wm8766_set_power(struct snd_wm8766 *wm, u16 power) | ||
195 | { | ||
196 | u16 val = wm->regs[WM8766_REG_DACCTRL3] & ~WM8766_DAC3_POWER_MASK; | ||
197 | |||
198 | power &= WM8766_DAC3_POWER_MASK; | ||
199 | snd_wm8766_write(wm, WM8766_REG_DACCTRL3, val | power); | ||
200 | } | ||
201 | |||
202 | void snd_wm8766_volume_restore(struct snd_wm8766 *wm) | 186 | void snd_wm8766_volume_restore(struct snd_wm8766 *wm) |
203 | { | 187 | { |
204 | u16 val = wm->regs[WM8766_REG_DACR1]; | 188 | u16 val = wm->regs[WM8766_REG_DACR1]; |
diff --git a/sound/pci/ice1712/wm8766.h b/sound/pci/ice1712/wm8766.h index c119f84bd2c2..18c8d9d47b38 100644 --- a/sound/pci/ice1712/wm8766.h +++ b/sound/pci/ice1712/wm8766.h | |||
@@ -155,8 +155,6 @@ struct snd_wm8766 { | |||
155 | void snd_wm8766_init(struct snd_wm8766 *wm); | 155 | void snd_wm8766_init(struct snd_wm8766 *wm); |
156 | void snd_wm8766_resume(struct snd_wm8766 *wm); | 156 | void snd_wm8766_resume(struct snd_wm8766 *wm); |
157 | void snd_wm8766_set_if(struct snd_wm8766 *wm, u16 dac); | 157 | void snd_wm8766_set_if(struct snd_wm8766 *wm, u16 dac); |
158 | void snd_wm8766_set_master_mode(struct snd_wm8766 *wm, u16 mode); | ||
159 | void snd_wm8766_set_power(struct snd_wm8766 *wm, u16 power); | ||
160 | void snd_wm8766_volume_restore(struct snd_wm8766 *wm); | 158 | void snd_wm8766_volume_restore(struct snd_wm8766 *wm); |
161 | int snd_wm8766_build_controls(struct snd_wm8766 *wm); | 159 | int snd_wm8766_build_controls(struct snd_wm8766 *wm); |
162 | 160 | ||
diff --git a/sound/pci/ice1712/wm8776.c b/sound/pci/ice1712/wm8776.c index e66c0da62014..ebd2fe4b4a57 100644 --- a/sound/pci/ice1712/wm8776.c +++ b/sound/pci/ice1712/wm8776.c | |||
@@ -452,21 +452,6 @@ void snd_wm8776_resume(struct snd_wm8776 *wm) | |||
452 | snd_wm8776_write(wm, i, wm->regs[i]); | 452 | snd_wm8776_write(wm, i, wm->regs[i]); |
453 | } | 453 | } |
454 | 454 | ||
455 | void snd_wm8776_set_dac_if(struct snd_wm8776 *wm, u16 dac) | ||
456 | { | ||
457 | snd_wm8776_write(wm, WM8776_REG_DACIFCTRL, dac); | ||
458 | } | ||
459 | |||
460 | void snd_wm8776_set_adc_if(struct snd_wm8776 *wm, u16 adc) | ||
461 | { | ||
462 | snd_wm8776_write(wm, WM8776_REG_ADCIFCTRL, adc); | ||
463 | } | ||
464 | |||
465 | void snd_wm8776_set_master_mode(struct snd_wm8776 *wm, u16 mode) | ||
466 | { | ||
467 | snd_wm8776_write(wm, WM8776_REG_MSTRCTRL, mode); | ||
468 | } | ||
469 | |||
470 | void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power) | 455 | void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power) |
471 | { | 456 | { |
472 | snd_wm8776_write(wm, WM8776_REG_PWRDOWN, power); | 457 | snd_wm8776_write(wm, WM8776_REG_PWRDOWN, power); |
diff --git a/sound/pci/ice1712/wm8776.h b/sound/pci/ice1712/wm8776.h index 93a2d6971154..42acef05540c 100644 --- a/sound/pci/ice1712/wm8776.h +++ b/sound/pci/ice1712/wm8776.h | |||
@@ -216,9 +216,6 @@ struct snd_wm8776 { | |||
216 | 216 | ||
217 | void snd_wm8776_init(struct snd_wm8776 *wm); | 217 | void snd_wm8776_init(struct snd_wm8776 *wm); |
218 | void snd_wm8776_resume(struct snd_wm8776 *wm); | 218 | void snd_wm8776_resume(struct snd_wm8776 *wm); |
219 | void snd_wm8776_set_dac_if(struct snd_wm8776 *wm, u16 dac); | ||
220 | void snd_wm8776_set_adc_if(struct snd_wm8776 *wm, u16 adc); | ||
221 | void snd_wm8776_set_master_mode(struct snd_wm8776 *wm, u16 mode); | ||
222 | void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power); | 219 | void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power); |
223 | void snd_wm8776_volume_restore(struct snd_wm8776 *wm); | 220 | void snd_wm8776_volume_restore(struct snd_wm8776 *wm); |
224 | int snd_wm8776_build_controls(struct snd_wm8776 *wm); | 221 | int snd_wm8776_build_controls(struct snd_wm8776 *wm); |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 4a28252a42b9..2c5484eeb963 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -26,7 +26,7 @@ | |||
26 | * | 26 | * |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <asm/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
@@ -2654,7 +2654,6 @@ static int snd_intel8x0_free(struct intel8x0 *chip) | |||
2654 | */ | 2654 | */ |
2655 | static int intel8x0_suspend(struct device *dev) | 2655 | static int intel8x0_suspend(struct device *dev) |
2656 | { | 2656 | { |
2657 | struct pci_dev *pci = to_pci_dev(dev); | ||
2658 | struct snd_card *card = dev_get_drvdata(dev); | 2657 | struct snd_card *card = dev_get_drvdata(dev); |
2659 | struct intel8x0 *chip = card->private_data; | 2658 | struct intel8x0 *chip = card->private_data; |
2660 | int i; | 2659 | int i; |
@@ -2682,12 +2681,6 @@ static int intel8x0_suspend(struct device *dev) | |||
2682 | free_irq(chip->irq, chip); | 2681 | free_irq(chip->irq, chip); |
2683 | chip->irq = -1; | 2682 | chip->irq = -1; |
2684 | } | 2683 | } |
2685 | pci_disable_device(pci); | ||
2686 | pci_save_state(pci); | ||
2687 | /* The call below may disable built-in speaker on some laptops | ||
2688 | * after S2RAM. So, don't touch it. | ||
2689 | */ | ||
2690 | /* pci_set_power_state(pci, PCI_D3hot); */ | ||
2691 | return 0; | 2684 | return 0; |
2692 | } | 2685 | } |
2693 | 2686 | ||
@@ -2698,14 +2691,6 @@ static int intel8x0_resume(struct device *dev) | |||
2698 | struct intel8x0 *chip = card->private_data; | 2691 | struct intel8x0 *chip = card->private_data; |
2699 | int i; | 2692 | int i; |
2700 | 2693 | ||
2701 | pci_set_power_state(pci, PCI_D0); | ||
2702 | pci_restore_state(pci); | ||
2703 | if (pci_enable_device(pci) < 0) { | ||
2704 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
2705 | snd_card_disconnect(card); | ||
2706 | return -EIO; | ||
2707 | } | ||
2708 | pci_set_master(pci); | ||
2709 | snd_intel8x0_chip_init(chip, 0); | 2694 | snd_intel8x0_chip_init(chip, 0); |
2710 | if (request_irq(pci->irq, snd_intel8x0_interrupt, | 2695 | if (request_irq(pci->irq, snd_intel8x0_interrupt, |
2711 | IRQF_SHARED, KBUILD_MODNAME, chip)) { | 2696 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 6b40235be13c..7577f31cd504 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -23,7 +23,7 @@ | |||
23 | * | 23 | * |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <asm/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
@@ -1023,7 +1023,6 @@ static int snd_intel8x0m_free(struct intel8x0m *chip) | |||
1023 | */ | 1023 | */ |
1024 | static int intel8x0m_suspend(struct device *dev) | 1024 | static int intel8x0m_suspend(struct device *dev) |
1025 | { | 1025 | { |
1026 | struct pci_dev *pci = to_pci_dev(dev); | ||
1027 | struct snd_card *card = dev_get_drvdata(dev); | 1026 | struct snd_card *card = dev_get_drvdata(dev); |
1028 | struct intel8x0m *chip = card->private_data; | 1027 | struct intel8x0m *chip = card->private_data; |
1029 | int i; | 1028 | int i; |
@@ -1036,9 +1035,6 @@ static int intel8x0m_suspend(struct device *dev) | |||
1036 | free_irq(chip->irq, chip); | 1035 | free_irq(chip->irq, chip); |
1037 | chip->irq = -1; | 1036 | chip->irq = -1; |
1038 | } | 1037 | } |
1039 | pci_disable_device(pci); | ||
1040 | pci_save_state(pci); | ||
1041 | pci_set_power_state(pci, PCI_D3hot); | ||
1042 | return 0; | 1038 | return 0; |
1043 | } | 1039 | } |
1044 | 1040 | ||
@@ -1048,14 +1044,6 @@ static int intel8x0m_resume(struct device *dev) | |||
1048 | struct snd_card *card = dev_get_drvdata(dev); | 1044 | struct snd_card *card = dev_get_drvdata(dev); |
1049 | struct intel8x0m *chip = card->private_data; | 1045 | struct intel8x0m *chip = card->private_data; |
1050 | 1046 | ||
1051 | pci_set_power_state(pci, PCI_D0); | ||
1052 | pci_restore_state(pci); | ||
1053 | if (pci_enable_device(pci) < 0) { | ||
1054 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
1055 | snd_card_disconnect(card); | ||
1056 | return -EIO; | ||
1057 | } | ||
1058 | pci_set_master(pci); | ||
1059 | if (request_irq(pci->irq, snd_intel8x0m_interrupt, | 1047 | if (request_irq(pci->irq, snd_intel8x0m_interrupt, |
1060 | IRQF_SHARED, KBUILD_MODNAME, chip)) { | 1048 | IRQF_SHARED, KBUILD_MODNAME, chip)) { |
1061 | dev_err(dev, "unable to grab IRQ %d, disabling device\n", | 1049 | dev_err(dev, "unable to grab IRQ %d, disabling device\n", |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 59d21c9401d2..7acbc21d642a 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
30 | #include <linux/firmware.h> | 30 | #include <linux/firmware.h> |
31 | #include <linux/io.h> | ||
31 | 32 | ||
32 | #include <sound/core.h> | 33 | #include <sound/core.h> |
33 | #include <sound/info.h> | 34 | #include <sound/info.h> |
@@ -36,8 +37,6 @@ | |||
36 | #include <sound/pcm_params.h> | 37 | #include <sound/pcm_params.h> |
37 | #include <sound/initval.h> | 38 | #include <sound/initval.h> |
38 | 39 | ||
39 | #include <asm/io.h> | ||
40 | |||
41 | // ---------------------------------------------------------------------------- | 40 | // ---------------------------------------------------------------------------- |
42 | // Debug Stuff | 41 | // Debug Stuff |
43 | // ---------------------------------------------------------------------------- | 42 | // ---------------------------------------------------------------------------- |
@@ -585,8 +584,7 @@ static void snd_korg1212_SendStop(struct snd_korg1212 *korg1212) | |||
585 | korg1212->sharedBufferPtr->cardCommand = 0xffffffff; | 584 | korg1212->sharedBufferPtr->cardCommand = 0xffffffff; |
586 | /* program the timer */ | 585 | /* program the timer */ |
587 | korg1212->stop_pending_cnt = HZ; | 586 | korg1212->stop_pending_cnt = HZ; |
588 | korg1212->timer.expires = jiffies + 1; | 587 | mod_timer(&korg1212->timer, jiffies + 1); |
589 | add_timer(&korg1212->timer); | ||
590 | } | 588 | } |
591 | } | 589 | } |
592 | 590 | ||
@@ -617,8 +615,7 @@ static void snd_korg1212_timer_func(unsigned long data) | |||
617 | } else { | 615 | } else { |
618 | if (--korg1212->stop_pending_cnt > 0) { | 616 | if (--korg1212->stop_pending_cnt > 0) { |
619 | /* reprogram timer */ | 617 | /* reprogram timer */ |
620 | korg1212->timer.expires = jiffies + 1; | 618 | mod_timer(&korg1212->timer, jiffies + 1); |
621 | add_timer(&korg1212->timer); | ||
622 | } else { | 619 | } else { |
623 | snd_printd("korg1212_timer_func timeout\n"); | 620 | snd_printd("korg1212_timer_func timeout\n"); |
624 | korg1212->sharedBufferPtr->cardCommand = 0; | 621 | korg1212->sharedBufferPtr->cardCommand = 0; |
@@ -2172,9 +2169,8 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci, | |||
2172 | init_waitqueue_head(&korg1212->wait); | 2169 | init_waitqueue_head(&korg1212->wait); |
2173 | spin_lock_init(&korg1212->lock); | 2170 | spin_lock_init(&korg1212->lock); |
2174 | mutex_init(&korg1212->open_mutex); | 2171 | mutex_init(&korg1212->open_mutex); |
2175 | init_timer(&korg1212->timer); | 2172 | setup_timer(&korg1212->timer, snd_korg1212_timer_func, |
2176 | korg1212->timer.function = snd_korg1212_timer_func; | 2173 | (unsigned long)korg1212); |
2177 | korg1212->timer.data = (unsigned long)korg1212; | ||
2178 | 2174 | ||
2179 | korg1212->irq = -1; | 2175 | korg1212->irq = -1; |
2180 | korg1212->clkSource = K1212_CLKIDX_Local; | 2176 | korg1212->clkSource = K1212_CLKIDX_Local; |
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c index 4cf4be5ef82a..9ff600084973 100644 --- a/sound/pci/lola/lola.c +++ b/sound/pci/lola/lola.c | |||
@@ -551,10 +551,8 @@ static void lola_free(struct lola *chip) | |||
551 | lola_free_mixer(chip); | 551 | lola_free_mixer(chip); |
552 | if (chip->irq >= 0) | 552 | if (chip->irq >= 0) |
553 | free_irq(chip->irq, (void *)chip); | 553 | free_irq(chip->irq, (void *)chip); |
554 | if (chip->bar[0].remap_addr) | 554 | iounmap(chip->bar[0].remap_addr); |
555 | iounmap(chip->bar[0].remap_addr); | 555 | iounmap(chip->bar[1].remap_addr); |
556 | if (chip->bar[1].remap_addr) | ||
557 | iounmap(chip->bar[1].remap_addr); | ||
558 | if (chip->rb.area) | 556 | if (chip->rb.area) |
559 | snd_dma_free_pages(&chip->rb); | 557 | snd_dma_free_pages(&chip->rb); |
560 | pci_release_regions(chip->pci); | 558 | pci_release_regions(chip->pci); |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 98823d11d485..9be660993bd0 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #define CARD_NAME "ESS Maestro3/Allegro/Canyon3D-2" | 31 | #define CARD_NAME "ESS Maestro3/Allegro/Canyon3D-2" |
32 | #define DRIVER_NAME "Maestro3" | 32 | #define DRIVER_NAME "Maestro3" |
33 | 33 | ||
34 | #include <asm/io.h> | 34 | #include <linux/io.h> |
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
@@ -2395,7 +2395,6 @@ static int snd_m3_free(struct snd_m3 *chip) | |||
2395 | #ifdef CONFIG_PM_SLEEP | 2395 | #ifdef CONFIG_PM_SLEEP |
2396 | static int m3_suspend(struct device *dev) | 2396 | static int m3_suspend(struct device *dev) |
2397 | { | 2397 | { |
2398 | struct pci_dev *pci = to_pci_dev(dev); | ||
2399 | struct snd_card *card = dev_get_drvdata(dev); | 2398 | struct snd_card *card = dev_get_drvdata(dev); |
2400 | struct snd_m3 *chip = card->private_data; | 2399 | struct snd_m3 *chip = card->private_data; |
2401 | int i, dsp_index; | 2400 | int i, dsp_index; |
@@ -2421,16 +2420,11 @@ static int m3_suspend(struct device *dev) | |||
2421 | for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++) | 2420 | for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++) |
2422 | chip->suspend_mem[dsp_index++] = | 2421 | chip->suspend_mem[dsp_index++] = |
2423 | snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i); | 2422 | snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i); |
2424 | |||
2425 | pci_disable_device(pci); | ||
2426 | pci_save_state(pci); | ||
2427 | pci_set_power_state(pci, PCI_D3hot); | ||
2428 | return 0; | 2423 | return 0; |
2429 | } | 2424 | } |
2430 | 2425 | ||
2431 | static int m3_resume(struct device *dev) | 2426 | static int m3_resume(struct device *dev) |
2432 | { | 2427 | { |
2433 | struct pci_dev *pci = to_pci_dev(dev); | ||
2434 | struct snd_card *card = dev_get_drvdata(dev); | 2428 | struct snd_card *card = dev_get_drvdata(dev); |
2435 | struct snd_m3 *chip = card->private_data; | 2429 | struct snd_m3 *chip = card->private_data; |
2436 | int i, dsp_index; | 2430 | int i, dsp_index; |
@@ -2438,15 +2432,6 @@ static int m3_resume(struct device *dev) | |||
2438 | if (chip->suspend_mem == NULL) | 2432 | if (chip->suspend_mem == NULL) |
2439 | return 0; | 2433 | return 0; |
2440 | 2434 | ||
2441 | pci_set_power_state(pci, PCI_D0); | ||
2442 | pci_restore_state(pci); | ||
2443 | if (pci_enable_device(pci) < 0) { | ||
2444 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
2445 | snd_card_disconnect(card); | ||
2446 | return -EIO; | ||
2447 | } | ||
2448 | pci_set_master(pci); | ||
2449 | |||
2450 | /* first lets just bring everything back. .*/ | 2435 | /* first lets just bring everything back. .*/ |
2451 | snd_m3_outw(chip, 0, 0x54); | 2436 | snd_m3_outw(chip, 0, 0x54); |
2452 | snd_m3_outw(chip, 0, 0x56); | 2437 | snd_m3_outw(chip, 0, 0x56); |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 1faf47e81570..c3a9f39f8d61 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -1114,10 +1114,9 @@ static int snd_mixart_free(struct mixart_mgr *mgr) | |||
1114 | } | 1114 | } |
1115 | 1115 | ||
1116 | /* release the i/o ports */ | 1116 | /* release the i/o ports */ |
1117 | for (i = 0; i < 2; i++) { | 1117 | for (i = 0; i < 2; ++i) |
1118 | if (mgr->mem[i].virt) | 1118 | iounmap(mgr->mem[i].virt); |
1119 | iounmap(mgr->mem[i].virt); | 1119 | |
1120 | } | ||
1121 | pci_release_regions(mgr->pci); | 1120 | pci_release_regions(mgr->pci); |
1122 | 1121 | ||
1123 | /* free flowarray */ | 1122 | /* free flowarray */ |
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index fe80313674d9..dccf3db48fe0 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c | |||
@@ -23,8 +23,8 @@ | |||
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/io.h> | ||
26 | 27 | ||
27 | #include <asm/io.h> | ||
28 | #include <sound/core.h> | 28 | #include <sound/core.h> |
29 | #include "mixart.h" | 29 | #include "mixart.h" |
30 | #include "mixart_hwdep.h" | 30 | #include "mixart_hwdep.h" |
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c index 9996a4dead0f..5bfd3ac80db5 100644 --- a/sound/pci/mixart/mixart_hwdep.c +++ b/sound/pci/mixart/mixart_hwdep.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/vmalloc.h> | 26 | #include <linux/vmalloc.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <asm/io.h> | 29 | #include <linux/io.h> |
30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
31 | #include "mixart.h" | 31 | #include "mixart.h" |
32 | #include "mixart_mixer.h" | 32 | #include "mixart_mixer.h" |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 4e41a4e29a1e..4735e27cc773 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -24,7 +24,7 @@ | |||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <asm/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
@@ -1392,7 +1392,6 @@ snd_nm256_peek_for_sig(struct nm256 *chip) | |||
1392 | */ | 1392 | */ |
1393 | static int nm256_suspend(struct device *dev) | 1393 | static int nm256_suspend(struct device *dev) |
1394 | { | 1394 | { |
1395 | struct pci_dev *pci = to_pci_dev(dev); | ||
1396 | struct snd_card *card = dev_get_drvdata(dev); | 1395 | struct snd_card *card = dev_get_drvdata(dev); |
1397 | struct nm256 *chip = card->private_data; | 1396 | struct nm256 *chip = card->private_data; |
1398 | 1397 | ||
@@ -1400,15 +1399,11 @@ static int nm256_suspend(struct device *dev) | |||
1400 | snd_pcm_suspend_all(chip->pcm); | 1399 | snd_pcm_suspend_all(chip->pcm); |
1401 | snd_ac97_suspend(chip->ac97); | 1400 | snd_ac97_suspend(chip->ac97); |
1402 | chip->coeffs_current = 0; | 1401 | chip->coeffs_current = 0; |
1403 | pci_disable_device(pci); | ||
1404 | pci_save_state(pci); | ||
1405 | pci_set_power_state(pci, PCI_D3hot); | ||
1406 | return 0; | 1402 | return 0; |
1407 | } | 1403 | } |
1408 | 1404 | ||
1409 | static int nm256_resume(struct device *dev) | 1405 | static int nm256_resume(struct device *dev) |
1410 | { | 1406 | { |
1411 | struct pci_dev *pci = to_pci_dev(dev); | ||
1412 | struct snd_card *card = dev_get_drvdata(dev); | 1407 | struct snd_card *card = dev_get_drvdata(dev); |
1413 | struct nm256 *chip = card->private_data; | 1408 | struct nm256 *chip = card->private_data; |
1414 | int i; | 1409 | int i; |
@@ -1416,15 +1411,6 @@ static int nm256_resume(struct device *dev) | |||
1416 | /* Perform a full reset on the hardware */ | 1411 | /* Perform a full reset on the hardware */ |
1417 | chip->in_resume = 1; | 1412 | chip->in_resume = 1; |
1418 | 1413 | ||
1419 | pci_set_power_state(pci, PCI_D0); | ||
1420 | pci_restore_state(pci); | ||
1421 | if (pci_enable_device(pci) < 0) { | ||
1422 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
1423 | snd_card_disconnect(card); | ||
1424 | return -EIO; | ||
1425 | } | ||
1426 | pci_set_master(pci); | ||
1427 | |||
1428 | snd_nm256_init_chip(chip); | 1414 | snd_nm256_init_chip(chip); |
1429 | 1415 | ||
1430 | /* restore ac97 */ | 1416 | /* restore ac97 */ |
@@ -1460,10 +1446,8 @@ static int snd_nm256_free(struct nm256 *chip) | |||
1460 | if (chip->irq >= 0) | 1446 | if (chip->irq >= 0) |
1461 | free_irq(chip->irq, chip); | 1447 | free_irq(chip->irq, chip); |
1462 | 1448 | ||
1463 | if (chip->cport) | 1449 | iounmap(chip->cport); |
1464 | iounmap(chip->cport); | 1450 | iounmap(chip->buffer); |
1465 | if (chip->buffer) | ||
1466 | iounmap(chip->buffer); | ||
1467 | release_and_free_resource(chip->res_cport); | 1451 | release_and_free_resource(chip->res_cport); |
1468 | release_and_free_resource(chip->res_buffer); | 1452 | release_and_free_resource(chip->res_buffer); |
1469 | 1453 | ||
diff --git a/sound/pci/oxygen/Makefile b/sound/pci/oxygen/Makefile index 8f4c409f7e45..ab085d753661 100644 --- a/sound/pci/oxygen/Makefile +++ b/sound/pci/oxygen/Makefile | |||
@@ -1,8 +1,10 @@ | |||
1 | snd-oxygen-lib-objs := oxygen_io.o oxygen_lib.o oxygen_mixer.o oxygen_pcm.o | 1 | snd-oxygen-lib-objs := oxygen_io.o oxygen_lib.o oxygen_mixer.o oxygen_pcm.o |
2 | snd-oxygen-objs := oxygen.o xonar_dg_mixer.o xonar_dg.o | 2 | snd-oxygen-objs := oxygen.o xonar_dg_mixer.o xonar_dg.o |
3 | snd-se6x-objs := se6x.o | ||
3 | snd-virtuoso-objs := virtuoso.o xonar_lib.o \ | 4 | snd-virtuoso-objs := virtuoso.o xonar_lib.o \ |
4 | xonar_pcm179x.o xonar_cs43xx.o xonar_wm87x6.o xonar_hdmi.o | 5 | xonar_pcm179x.o xonar_cs43xx.o xonar_wm87x6.o xonar_hdmi.o |
5 | 6 | ||
6 | obj-$(CONFIG_SND_OXYGEN_LIB) += snd-oxygen-lib.o | 7 | obj-$(CONFIG_SND_OXYGEN_LIB) += snd-oxygen-lib.o |
7 | obj-$(CONFIG_SND_OXYGEN) += snd-oxygen.o | 8 | obj-$(CONFIG_SND_OXYGEN) += snd-oxygen.o |
9 | obj-$(CONFIG_SND_SE6X) += snd-se6x.o | ||
8 | obj-$(CONFIG_SND_VIRTUOSO) += snd-virtuoso.o | 10 | obj-$(CONFIG_SND_VIRTUOSO) += snd-virtuoso.o |
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index c10ab077afd8..293d0b9a50c3 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
@@ -35,7 +35,7 @@ | |||
35 | #define CAPTURE_1_FROM_SPDIF 0x0080 | 35 | #define CAPTURE_1_FROM_SPDIF 0x0080 |
36 | #define CAPTURE_2_FROM_I2S_2 0x0100 | 36 | #define CAPTURE_2_FROM_I2S_2 0x0100 |
37 | #define CAPTURE_2_FROM_AC97_1 0x0200 | 37 | #define CAPTURE_2_FROM_AC97_1 0x0200 |
38 | /* CAPTURE_3_FROM_I2S_3 not implemented */ | 38 | #define CAPTURE_3_FROM_I2S_3 0x0400 |
39 | #define MIDI_OUTPUT 0x0800 | 39 | #define MIDI_OUTPUT 0x0800 |
40 | #define MIDI_INPUT 0x1000 | 40 | #define MIDI_INPUT 0x1000 |
41 | #define AC97_CD_INPUT 0x2000 | 41 | #define AC97_CD_INPUT 0x2000 |
diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c index 4b8a32c37e31..c7851da37749 100644 --- a/sound/pci/oxygen/oxygen_io.c +++ b/sound/pci/oxygen/oxygen_io.c | |||
@@ -20,9 +20,9 @@ | |||
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
22 | #include <linux/export.h> | 22 | #include <linux/export.h> |
23 | #include <linux/io.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/mpu401.h> | 25 | #include <sound/mpu401.h> |
25 | #include <asm/io.h> | ||
26 | #include "oxygen.h" | 26 | #include "oxygen.h" |
27 | 27 | ||
28 | u8 oxygen_read8(struct oxygen *chip, unsigned int reg) | 28 | u8 oxygen_read8(struct oxygen *chip, unsigned int reg) |
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index b67e30602473..ffff3b25fd73 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -319,11 +319,12 @@ static void oxygen_restore_eeprom(struct oxygen *chip, | |||
319 | 319 | ||
320 | static void configure_pcie_bridge(struct pci_dev *pci) | 320 | static void configure_pcie_bridge(struct pci_dev *pci) |
321 | { | 321 | { |
322 | enum { PEX811X, PI7C9X110 }; | 322 | enum { PEX811X, PI7C9X110, XIO2001 }; |
323 | static const struct pci_device_id bridge_ids[] = { | 323 | static const struct pci_device_id bridge_ids[] = { |
324 | { PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X }, | 324 | { PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X }, |
325 | { PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X }, | 325 | { PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X }, |
326 | { PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 }, | 326 | { PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 }, |
327 | { PCI_VDEVICE(TI, 0x8240), .driver_data = XIO2001 }, | ||
327 | { } | 328 | { } |
328 | }; | 329 | }; |
329 | struct pci_dev *bridge; | 330 | struct pci_dev *bridge; |
@@ -357,6 +358,14 @@ static void configure_pcie_bridge(struct pci_dev *pci) | |||
357 | tmp |= 1; /* park the PCI arbiter to the sound chip */ | 358 | tmp |= 1; /* park the PCI arbiter to the sound chip */ |
358 | pci_write_config_dword(bridge, 0x40, tmp); | 359 | pci_write_config_dword(bridge, 0x40, tmp); |
359 | break; | 360 | break; |
361 | |||
362 | case XIO2001: /* Texas Instruments XIO2001 PCIe/PCI bridge */ | ||
363 | pci_read_config_dword(bridge, 0xe8, &tmp); | ||
364 | tmp &= ~0xf; /* request length limit: 64 bytes */ | ||
365 | tmp &= ~(0xf << 8); | ||
366 | tmp |= 1 << 8; /* request count limit: one buffer */ | ||
367 | pci_write_config_dword(bridge, 0xe8, tmp); | ||
368 | break; | ||
360 | } | 369 | } |
361 | } | 370 | } |
362 | 371 | ||
@@ -441,9 +450,18 @@ static void oxygen_init(struct oxygen *chip) | |||
441 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, | 450 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, |
442 | OXYGEN_I2S_MASTER | | 451 | OXYGEN_I2S_MASTER | |
443 | OXYGEN_I2S_MUTE_MCLK); | 452 | OXYGEN_I2S_MUTE_MCLK); |
444 | oxygen_write16(chip, OXYGEN_I2S_C_FORMAT, | 453 | if (chip->model.device_config & CAPTURE_3_FROM_I2S_3) |
445 | OXYGEN_I2S_MASTER | | 454 | oxygen_write16(chip, OXYGEN_I2S_C_FORMAT, |
446 | OXYGEN_I2S_MUTE_MCLK); | 455 | OXYGEN_RATE_48000 | |
456 | chip->model.adc_i2s_format | | ||
457 | OXYGEN_I2S_MCLK(chip->model.adc_mclks) | | ||
458 | OXYGEN_I2S_BITS_16 | | ||
459 | OXYGEN_I2S_MASTER | | ||
460 | OXYGEN_I2S_BCLK_64); | ||
461 | else | ||
462 | oxygen_write16(chip, OXYGEN_I2S_C_FORMAT, | ||
463 | OXYGEN_I2S_MASTER | | ||
464 | OXYGEN_I2S_MUTE_MCLK); | ||
447 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, | 465 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, |
448 | OXYGEN_SPDIF_OUT_ENABLE | | 466 | OXYGEN_SPDIF_OUT_ENABLE | |
449 | OXYGEN_SPDIF_LOOPBACK); | 467 | OXYGEN_SPDIF_LOOPBACK); |
@@ -728,7 +746,6 @@ EXPORT_SYMBOL(oxygen_pci_remove); | |||
728 | #ifdef CONFIG_PM_SLEEP | 746 | #ifdef CONFIG_PM_SLEEP |
729 | static int oxygen_pci_suspend(struct device *dev) | 747 | static int oxygen_pci_suspend(struct device *dev) |
730 | { | 748 | { |
731 | struct pci_dev *pci = to_pci_dev(dev); | ||
732 | struct snd_card *card = dev_get_drvdata(dev); | 749 | struct snd_card *card = dev_get_drvdata(dev); |
733 | struct oxygen *chip = card->private_data; | 750 | struct oxygen *chip = card->private_data; |
734 | unsigned int i, saved_interrupt_mask; | 751 | unsigned int i, saved_interrupt_mask; |
@@ -736,8 +753,7 @@ static int oxygen_pci_suspend(struct device *dev) | |||
736 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 753 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
737 | 754 | ||
738 | for (i = 0; i < PCM_COUNT; ++i) | 755 | for (i = 0; i < PCM_COUNT; ++i) |
739 | if (chip->streams[i]) | 756 | snd_pcm_suspend(chip->streams[i]); |
740 | snd_pcm_suspend(chip->streams[i]); | ||
741 | 757 | ||
742 | if (chip->model.suspend) | 758 | if (chip->model.suspend) |
743 | chip->model.suspend(chip); | 759 | chip->model.suspend(chip); |
@@ -753,10 +769,6 @@ static int oxygen_pci_suspend(struct device *dev) | |||
753 | flush_work(&chip->spdif_input_bits_work); | 769 | flush_work(&chip->spdif_input_bits_work); |
754 | flush_work(&chip->gpio_work); | 770 | flush_work(&chip->gpio_work); |
755 | chip->interrupt_mask = saved_interrupt_mask; | 771 | chip->interrupt_mask = saved_interrupt_mask; |
756 | |||
757 | pci_disable_device(pci); | ||
758 | pci_save_state(pci); | ||
759 | pci_set_power_state(pci, PCI_D3hot); | ||
760 | return 0; | 772 | return 0; |
761 | } | 773 | } |
762 | 774 | ||
@@ -788,20 +800,10 @@ static void oxygen_restore_ac97(struct oxygen *chip, unsigned int codec) | |||
788 | 800 | ||
789 | static int oxygen_pci_resume(struct device *dev) | 801 | static int oxygen_pci_resume(struct device *dev) |
790 | { | 802 | { |
791 | struct pci_dev *pci = to_pci_dev(dev); | ||
792 | struct snd_card *card = dev_get_drvdata(dev); | 803 | struct snd_card *card = dev_get_drvdata(dev); |
793 | struct oxygen *chip = card->private_data; | 804 | struct oxygen *chip = card->private_data; |
794 | unsigned int i; | 805 | unsigned int i; |
795 | 806 | ||
796 | pci_set_power_state(pci, PCI_D0); | ||
797 | pci_restore_state(pci); | ||
798 | if (pci_enable_device(pci) < 0) { | ||
799 | dev_err(dev, "cannot reenable device"); | ||
800 | snd_card_disconnect(card); | ||
801 | return -EIO; | ||
802 | } | ||
803 | pci_set_master(pci); | ||
804 | |||
805 | oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); | 807 | oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); |
806 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); | 808 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); |
807 | for (i = 0; i < OXYGEN_IO_SIZE; ++i) | 809 | for (i = 0; i < OXYGEN_IO_SIZE; ++i) |
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index 5988e044c519..6492bca8c70f 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c | |||
@@ -786,6 +786,9 @@ static const struct snd_kcontrol_new controls[] = { | |||
786 | .get = upmix_get, | 786 | .get = upmix_get, |
787 | .put = upmix_put, | 787 | .put = upmix_put, |
788 | }, | 788 | }, |
789 | }; | ||
790 | |||
791 | static const struct snd_kcontrol_new spdif_output_controls[] = { | ||
789 | { | 792 | { |
790 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 793 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
791 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), | 794 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), |
@@ -938,6 +941,33 @@ static const struct { | |||
938 | }, | 941 | }, |
939 | }, | 942 | }, |
940 | { | 943 | { |
944 | .pcm_dev = CAPTURE_3_FROM_I2S_3, | ||
945 | .controls = { | ||
946 | { | ||
947 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
948 | .name = "Analog Input Monitor Playback Switch", | ||
949 | .index = 2, | ||
950 | .info = snd_ctl_boolean_mono_info, | ||
951 | .get = monitor_get, | ||
952 | .put = monitor_put, | ||
953 | .private_value = OXYGEN_ADC_MONITOR_C, | ||
954 | }, | ||
955 | { | ||
956 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
957 | .name = "Analog Input Monitor Playback Volume", | ||
958 | .index = 2, | ||
959 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
960 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
961 | .info = monitor_volume_info, | ||
962 | .get = monitor_get, | ||
963 | .put = monitor_put, | ||
964 | .private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL | ||
965 | | (1 << 8), | ||
966 | .tlv = { .p = monitor_db_scale, }, | ||
967 | }, | ||
968 | }, | ||
969 | }, | ||
970 | { | ||
941 | .pcm_dev = CAPTURE_1_FROM_SPDIF, | 971 | .pcm_dev = CAPTURE_1_FROM_SPDIF, |
942 | .controls = { | 972 | .controls = { |
943 | { | 973 | { |
@@ -1073,6 +1103,12 @@ int oxygen_mixer_init(struct oxygen *chip) | |||
1073 | err = add_controls(chip, controls, ARRAY_SIZE(controls)); | 1103 | err = add_controls(chip, controls, ARRAY_SIZE(controls)); |
1074 | if (err < 0) | 1104 | if (err < 0) |
1075 | return err; | 1105 | return err; |
1106 | if (chip->model.device_config & PLAYBACK_1_TO_SPDIF) { | ||
1107 | err = add_controls(chip, spdif_output_controls, | ||
1108 | ARRAY_SIZE(spdif_output_controls)); | ||
1109 | if (err < 0) | ||
1110 | return err; | ||
1111 | } | ||
1076 | if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) { | 1112 | if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) { |
1077 | err = add_controls(chip, spdif_input_controls, | 1113 | err = add_controls(chip, spdif_input_controls, |
1078 | ARRAY_SIZE(spdif_input_controls)); | 1114 | ARRAY_SIZE(spdif_input_controls)); |
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index 02828240ba15..aa2ebd1d6d12 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c | |||
@@ -144,9 +144,11 @@ static int oxygen_open(struct snd_pcm_substream *substream, | |||
144 | runtime->hw = *oxygen_hardware[channel]; | 144 | runtime->hw = *oxygen_hardware[channel]; |
145 | switch (channel) { | 145 | switch (channel) { |
146 | case PCM_C: | 146 | case PCM_C: |
147 | runtime->hw.rates &= ~(SNDRV_PCM_RATE_32000 | | 147 | if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) { |
148 | SNDRV_PCM_RATE_64000); | 148 | runtime->hw.rates &= ~(SNDRV_PCM_RATE_32000 | |
149 | runtime->hw.rate_min = 44100; | 149 | SNDRV_PCM_RATE_64000); |
150 | runtime->hw.rate_min = 44100; | ||
151 | } | ||
150 | /* fall through */ | 152 | /* fall through */ |
151 | case PCM_A: | 153 | case PCM_A: |
152 | case PCM_B: | 154 | case PCM_B: |
@@ -430,17 +432,36 @@ static int oxygen_rec_c_hw_params(struct snd_pcm_substream *substream, | |||
430 | struct snd_pcm_hw_params *hw_params) | 432 | struct snd_pcm_hw_params *hw_params) |
431 | { | 433 | { |
432 | struct oxygen *chip = snd_pcm_substream_chip(substream); | 434 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
435 | bool is_spdif; | ||
433 | int err; | 436 | int err; |
434 | 437 | ||
435 | err = oxygen_hw_params(substream, hw_params); | 438 | err = oxygen_hw_params(substream, hw_params); |
436 | if (err < 0) | 439 | if (err < 0) |
437 | return err; | 440 | return err; |
438 | 441 | ||
442 | is_spdif = chip->model.device_config & CAPTURE_1_FROM_SPDIF; | ||
443 | |||
439 | spin_lock_irq(&chip->reg_lock); | 444 | spin_lock_irq(&chip->reg_lock); |
440 | oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, | 445 | oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, |
441 | oxygen_format(hw_params) << OXYGEN_REC_FORMAT_C_SHIFT, | 446 | oxygen_format(hw_params) << OXYGEN_REC_FORMAT_C_SHIFT, |
442 | OXYGEN_REC_FORMAT_C_MASK); | 447 | OXYGEN_REC_FORMAT_C_MASK); |
448 | if (!is_spdif) | ||
449 | oxygen_write16_masked(chip, OXYGEN_I2S_C_FORMAT, | ||
450 | oxygen_rate(hw_params) | | ||
451 | chip->model.adc_i2s_format | | ||
452 | get_mclk(chip, PCM_B, hw_params) | | ||
453 | oxygen_i2s_bits(hw_params), | ||
454 | OXYGEN_I2S_RATE_MASK | | ||
455 | OXYGEN_I2S_FORMAT_MASK | | ||
456 | OXYGEN_I2S_MCLK_MASK | | ||
457 | OXYGEN_I2S_BITS_MASK); | ||
443 | spin_unlock_irq(&chip->reg_lock); | 458 | spin_unlock_irq(&chip->reg_lock); |
459 | |||
460 | if (!is_spdif) { | ||
461 | mutex_lock(&chip->mutex); | ||
462 | chip->model.set_adc_params(chip, hw_params); | ||
463 | mutex_unlock(&chip->mutex); | ||
464 | } | ||
444 | return 0; | 465 | return 0; |
445 | } | 466 | } |
446 | 467 | ||
@@ -676,11 +697,6 @@ static struct snd_pcm_ops oxygen_ac97_ops = { | |||
676 | .pointer = oxygen_pointer, | 697 | .pointer = oxygen_pointer, |
677 | }; | 698 | }; |
678 | 699 | ||
679 | static void oxygen_pcm_free(struct snd_pcm *pcm) | ||
680 | { | ||
681 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
682 | } | ||
683 | |||
684 | int oxygen_pcm_init(struct oxygen *chip) | 700 | int oxygen_pcm_init(struct oxygen *chip) |
685 | { | 701 | { |
686 | struct snd_pcm *pcm; | 702 | struct snd_pcm *pcm; |
@@ -705,7 +721,6 @@ int oxygen_pcm_init(struct oxygen *chip) | |||
705 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | 721 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, |
706 | &oxygen_rec_b_ops); | 722 | &oxygen_rec_b_ops); |
707 | pcm->private_data = chip; | 723 | pcm->private_data = chip; |
708 | pcm->private_free = oxygen_pcm_free; | ||
709 | strcpy(pcm->name, "Multichannel"); | 724 | strcpy(pcm->name, "Multichannel"); |
710 | if (outs) | 725 | if (outs) |
711 | snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, | 726 | snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, |
@@ -734,7 +749,6 @@ int oxygen_pcm_init(struct oxygen *chip) | |||
734 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | 749 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, |
735 | &oxygen_rec_c_ops); | 750 | &oxygen_rec_c_ops); |
736 | pcm->private_data = chip; | 751 | pcm->private_data = chip; |
737 | pcm->private_free = oxygen_pcm_free; | ||
738 | strcpy(pcm->name, "Digital"); | 752 | strcpy(pcm->name, "Digital"); |
739 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 753 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
740 | snd_dma_pci_data(chip->pci), | 754 | snd_dma_pci_data(chip->pci), |
@@ -765,12 +779,29 @@ int oxygen_pcm_init(struct oxygen *chip) | |||
765 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | 779 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, |
766 | &oxygen_rec_b_ops); | 780 | &oxygen_rec_b_ops); |
767 | pcm->private_data = chip; | 781 | pcm->private_data = chip; |
768 | pcm->private_free = oxygen_pcm_free; | ||
769 | strcpy(pcm->name, outs ? "Front Panel" : "Analog 2"); | 782 | strcpy(pcm->name, outs ? "Front Panel" : "Analog 2"); |
770 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 783 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
771 | snd_dma_pci_data(chip->pci), | 784 | snd_dma_pci_data(chip->pci), |
772 | DEFAULT_BUFFER_BYTES, | 785 | DEFAULT_BUFFER_BYTES, |
773 | BUFFER_BYTES_MAX); | 786 | BUFFER_BYTES_MAX); |
774 | } | 787 | } |
788 | |||
789 | ins = !!(chip->model.device_config & CAPTURE_3_FROM_I2S_3); | ||
790 | if (ins) { | ||
791 | err = snd_pcm_new(chip->card, "Analog3", 3, 0, ins, &pcm); | ||
792 | if (err < 0) | ||
793 | return err; | ||
794 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | ||
795 | &oxygen_rec_c_ops); | ||
796 | oxygen_write8_masked(chip, OXYGEN_REC_ROUTING, | ||
797 | OXYGEN_REC_C_ROUTE_I2S_ADC_3, | ||
798 | OXYGEN_REC_C_ROUTE_MASK); | ||
799 | pcm->private_data = chip; | ||
800 | strcpy(pcm->name, "Analog 3"); | ||
801 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | ||
802 | snd_dma_pci_data(chip->pci), | ||
803 | DEFAULT_BUFFER_BYTES, | ||
804 | BUFFER_BYTES_MAX); | ||
805 | } | ||
775 | return 0; | 806 | return 0; |
776 | } | 807 | } |
diff --git a/sound/pci/oxygen/se6x.c b/sound/pci/oxygen/se6x.c new file mode 100644 index 000000000000..f70d514c1084 --- /dev/null +++ b/sound/pci/oxygen/se6x.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * C-Media CMI8787 driver for the Studio Evolution SE6X | ||
3 | * | ||
4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | ||
5 | * | ||
6 | * This driver is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License, version 2. | ||
8 | * | ||
9 | * This driver is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this driver; if not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | |||
18 | /* | ||
19 | * CMI8787: | ||
20 | * | ||
21 | * SPI -> microcontroller (not actually used) | ||
22 | * GPIO 0 -> do. | ||
23 | * GPIO 2 -> do. | ||
24 | * | ||
25 | * DAC0 -> both PCM1792A (L+R, each in mono mode) | ||
26 | * ADC1 <- 1st PCM1804 | ||
27 | * ADC2 <- 2nd PCM1804 | ||
28 | * ADC3 <- 3rd PCM1804 | ||
29 | */ | ||
30 | |||
31 | #include <linux/pci.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <sound/core.h> | ||
34 | #include <sound/control.h> | ||
35 | #include <sound/initval.h> | ||
36 | #include <sound/pcm.h> | ||
37 | #include "oxygen.h" | ||
38 | |||
39 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | ||
40 | MODULE_DESCRIPTION("Studio Evolution SE6X driver"); | ||
41 | MODULE_LICENSE("GPL v2"); | ||
42 | MODULE_SUPPORTED_DEVICE("{{Studio Evolution,SE6X}}"); | ||
43 | |||
44 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
45 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | ||
46 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | ||
47 | |||
48 | module_param_array(index, int, NULL, 0444); | ||
49 | MODULE_PARM_DESC(index, "card index"); | ||
50 | module_param_array(id, charp, NULL, 0444); | ||
51 | MODULE_PARM_DESC(id, "ID string"); | ||
52 | module_param_array(enable, bool, NULL, 0444); | ||
53 | MODULE_PARM_DESC(enable, "enable card"); | ||
54 | |||
55 | static const struct pci_device_id se6x_ids[] = { | ||
56 | { OXYGEN_PCI_SUBID(0x13f6, 0x8788) }, | ||
57 | { } | ||
58 | }; | ||
59 | MODULE_DEVICE_TABLE(pci, se6x_ids); | ||
60 | |||
61 | static void se6x_init(struct oxygen *chip) | ||
62 | { | ||
63 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, 0x005); | ||
64 | |||
65 | snd_component_add(chip->card, "PCM1792A"); | ||
66 | snd_component_add(chip->card, "PCM1804"); | ||
67 | } | ||
68 | |||
69 | static int se6x_control_filter(struct snd_kcontrol_new *template) | ||
70 | { | ||
71 | /* no DAC volume/mute */ | ||
72 | if (!strncmp(template->name, "Master Playback ", 16)) | ||
73 | return 1; | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static void se6x_cleanup(struct oxygen *chip) | ||
78 | { | ||
79 | } | ||
80 | |||
81 | static void set_pcm1792a_params(struct oxygen *chip, | ||
82 | struct snd_pcm_hw_params *params) | ||
83 | { | ||
84 | /* nothing to do (the microcontroller monitors DAC_LRCK) */ | ||
85 | } | ||
86 | |||
87 | static void set_pcm1804_params(struct oxygen *chip, | ||
88 | struct snd_pcm_hw_params *params) | ||
89 | { | ||
90 | } | ||
91 | |||
92 | static unsigned int se6x_adjust_dac_routing(struct oxygen *chip, | ||
93 | unsigned int play_routing) | ||
94 | { | ||
95 | /* route the same stereo pair to DAC0 and DAC1 */ | ||
96 | return ( play_routing & OXYGEN_PLAY_DAC0_SOURCE_MASK) | | ||
97 | ((play_routing << 2) & OXYGEN_PLAY_DAC1_SOURCE_MASK); | ||
98 | } | ||
99 | |||
100 | static const struct oxygen_model model_se6x = { | ||
101 | .shortname = "Studio Evolution SE6X", | ||
102 | .longname = "C-Media Oxygen HD Audio", | ||
103 | .chip = "CMI8787", | ||
104 | .init = se6x_init, | ||
105 | .control_filter = se6x_control_filter, | ||
106 | .cleanup = se6x_cleanup, | ||
107 | .set_dac_params = set_pcm1792a_params, | ||
108 | .set_adc_params = set_pcm1804_params, | ||
109 | .adjust_dac_routing = se6x_adjust_dac_routing, | ||
110 | .device_config = PLAYBACK_0_TO_I2S | | ||
111 | CAPTURE_0_FROM_I2S_1 | | ||
112 | CAPTURE_2_FROM_I2S_2 | | ||
113 | CAPTURE_3_FROM_I2S_3, | ||
114 | .dac_channels_pcm = 2, | ||
115 | .function_flags = OXYGEN_FUNCTION_SPI, | ||
116 | .dac_mclks = OXYGEN_MCLKS(256, 128, 128), | ||
117 | .adc_mclks = OXYGEN_MCLKS(256, 256, 128), | ||
118 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
119 | .adc_i2s_format = OXYGEN_I2S_FORMAT_I2S, | ||
120 | }; | ||
121 | |||
122 | static int se6x_get_model(struct oxygen *chip, | ||
123 | const struct pci_device_id *pci_id) | ||
124 | { | ||
125 | chip->model = model_se6x; | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int se6x_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | ||
130 | { | ||
131 | static int dev; | ||
132 | int err; | ||
133 | |||
134 | if (dev >= SNDRV_CARDS) | ||
135 | return -ENODEV; | ||
136 | if (!enable[dev]) { | ||
137 | ++dev; | ||
138 | return -ENOENT; | ||
139 | } | ||
140 | err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, | ||
141 | se6x_ids, se6x_get_model); | ||
142 | if (err >= 0) | ||
143 | ++dev; | ||
144 | return err; | ||
145 | } | ||
146 | |||
147 | static struct pci_driver se6x_driver = { | ||
148 | .name = KBUILD_MODNAME, | ||
149 | .id_table = se6x_ids, | ||
150 | .probe = se6x_probe, | ||
151 | .remove = oxygen_pci_remove, | ||
152 | #ifdef CONFIG_PM_SLEEP | ||
153 | .driver = { | ||
154 | .pm = &oxygen_pci_pm, | ||
155 | }, | ||
156 | #endif | ||
157 | .shutdown = oxygen_pci_shutdown, | ||
158 | }; | ||
159 | |||
160 | module_pci_driver(se6x_driver); | ||
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index 181f7729d409..c5194f5b150a 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/firmware.h> | 24 | #include <linux/firmware.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <asm/io.h> | 27 | #include <linux/io.h> |
28 | #include <sound/core.h> | 28 | #include <sound/core.h> |
29 | #include "pcxhr.h" | 29 | #include "pcxhr.h" |
30 | #include "pcxhr_mixer.h" | 30 | #include "pcxhr_mixer.h" |
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c index 15a8ce5f1f48..80633055e17e 100644 --- a/sound/pci/pcxhr/pcxhr_hwdep.c +++ b/sound/pci/pcxhr/pcxhr_hwdep.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/firmware.h> | 25 | #include <linux/firmware.h> |
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <asm/io.h> | 28 | #include <linux/io.h> |
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |
30 | #include <sound/hwdep.h> | 30 | #include <sound/hwdep.h> |
31 | #include "pcxhr.h" | 31 | #include "pcxhr.h" |
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 6abc2ac8fffb..94639d6b5fb5 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c | |||
@@ -99,7 +99,7 @@ | |||
99 | #include <linux/firmware.h> | 99 | #include <linux/firmware.h> |
100 | #include <linux/kernel.h> | 100 | #include <linux/kernel.h> |
101 | #include <linux/module.h> | 101 | #include <linux/module.h> |
102 | #include <asm/io.h> | 102 | #include <linux/io.h> |
103 | #include <sound/core.h> | 103 | #include <sound/core.h> |
104 | #include <sound/info.h> | 104 | #include <sound/info.h> |
105 | #include <sound/control.h> | 105 | #include <sound/control.h> |
@@ -1153,7 +1153,6 @@ static void riptide_handleirq(unsigned long dev_id) | |||
1153 | #ifdef CONFIG_PM_SLEEP | 1153 | #ifdef CONFIG_PM_SLEEP |
1154 | static int riptide_suspend(struct device *dev) | 1154 | static int riptide_suspend(struct device *dev) |
1155 | { | 1155 | { |
1156 | struct pci_dev *pci = to_pci_dev(dev); | ||
1157 | struct snd_card *card = dev_get_drvdata(dev); | 1156 | struct snd_card *card = dev_get_drvdata(dev); |
1158 | struct snd_riptide *chip = card->private_data; | 1157 | struct snd_riptide *chip = card->private_data; |
1159 | 1158 | ||
@@ -1161,27 +1160,14 @@ static int riptide_suspend(struct device *dev) | |||
1161 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 1160 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
1162 | snd_pcm_suspend_all(chip->pcm); | 1161 | snd_pcm_suspend_all(chip->pcm); |
1163 | snd_ac97_suspend(chip->ac97); | 1162 | snd_ac97_suspend(chip->ac97); |
1164 | pci_disable_device(pci); | ||
1165 | pci_save_state(pci); | ||
1166 | pci_set_power_state(pci, PCI_D3hot); | ||
1167 | return 0; | 1163 | return 0; |
1168 | } | 1164 | } |
1169 | 1165 | ||
1170 | static int riptide_resume(struct device *dev) | 1166 | static int riptide_resume(struct device *dev) |
1171 | { | 1167 | { |
1172 | struct pci_dev *pci = to_pci_dev(dev); | ||
1173 | struct snd_card *card = dev_get_drvdata(dev); | 1168 | struct snd_card *card = dev_get_drvdata(dev); |
1174 | struct snd_riptide *chip = card->private_data; | 1169 | struct snd_riptide *chip = card->private_data; |
1175 | 1170 | ||
1176 | pci_set_power_state(pci, PCI_D0); | ||
1177 | pci_restore_state(pci); | ||
1178 | if (pci_enable_device(pci) < 0) { | ||
1179 | printk(KERN_ERR "riptide: pci_enable_device failed, " | ||
1180 | "disabling device\n"); | ||
1181 | snd_card_disconnect(card); | ||
1182 | return -EIO; | ||
1183 | } | ||
1184 | pci_set_master(pci); | ||
1185 | snd_riptide_initialize(chip); | 1171 | snd_riptide_initialize(chip); |
1186 | snd_ac97_resume(chip->ac97); | 1172 | snd_ac97_resume(chip->ac97); |
1187 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1173 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
@@ -1706,14 +1692,11 @@ static struct snd_pcm_ops snd_riptide_capture_ops = { | |||
1706 | .pointer = snd_riptide_pointer, | 1692 | .pointer = snd_riptide_pointer, |
1707 | }; | 1693 | }; |
1708 | 1694 | ||
1709 | static int | 1695 | static int snd_riptide_pcm(struct snd_riptide *chip, int device) |
1710 | snd_riptide_pcm(struct snd_riptide *chip, int device, struct snd_pcm **rpcm) | ||
1711 | { | 1696 | { |
1712 | struct snd_pcm *pcm; | 1697 | struct snd_pcm *pcm; |
1713 | int err; | 1698 | int err; |
1714 | 1699 | ||
1715 | if (rpcm) | ||
1716 | *rpcm = NULL; | ||
1717 | if ((err = | 1700 | if ((err = |
1718 | snd_pcm_new(chip->card, "RIPTIDE", device, PLAYBACK_SUBSTREAMS, 1, | 1701 | snd_pcm_new(chip->card, "RIPTIDE", device, PLAYBACK_SUBSTREAMS, 1, |
1719 | &pcm)) < 0) | 1702 | &pcm)) < 0) |
@@ -1729,8 +1712,6 @@ snd_riptide_pcm(struct snd_riptide *chip, int device, struct snd_pcm **rpcm) | |||
1729 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1712 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1730 | snd_dma_pci_data(chip->pci), | 1713 | snd_dma_pci_data(chip->pci), |
1731 | 64 * 1024, 128 * 1024); | 1714 | 64 * 1024, 128 * 1024); |
1732 | if (rpcm) | ||
1733 | *rpcm = pcm; | ||
1734 | return 0; | 1715 | return 0; |
1735 | } | 1716 | } |
1736 | 1717 | ||
@@ -2030,32 +2011,43 @@ snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id) | |||
2030 | { | 2011 | { |
2031 | static int dev; | 2012 | static int dev; |
2032 | struct gameport *gameport; | 2013 | struct gameport *gameport; |
2014 | int ret; | ||
2033 | 2015 | ||
2034 | if (dev >= SNDRV_CARDS) | 2016 | if (dev >= SNDRV_CARDS) |
2035 | return -ENODEV; | 2017 | return -ENODEV; |
2018 | |||
2036 | if (!enable[dev]) { | 2019 | if (!enable[dev]) { |
2037 | dev++; | 2020 | ret = -ENOENT; |
2038 | return -ENOENT; | 2021 | goto inc_dev; |
2039 | } | 2022 | } |
2040 | 2023 | ||
2041 | if (!joystick_port[dev++]) | 2024 | if (!joystick_port[dev]) { |
2042 | return 0; | 2025 | ret = 0; |
2026 | goto inc_dev; | ||
2027 | } | ||
2043 | 2028 | ||
2044 | gameport = gameport_allocate_port(); | 2029 | gameport = gameport_allocate_port(); |
2045 | if (!gameport) | 2030 | if (!gameport) { |
2046 | return -ENOMEM; | 2031 | ret = -ENOMEM; |
2032 | goto inc_dev; | ||
2033 | } | ||
2047 | if (!request_region(joystick_port[dev], 8, "Riptide gameport")) { | 2034 | if (!request_region(joystick_port[dev], 8, "Riptide gameport")) { |
2048 | snd_printk(KERN_WARNING | 2035 | snd_printk(KERN_WARNING |
2049 | "Riptide: cannot grab gameport 0x%x\n", | 2036 | "Riptide: cannot grab gameport 0x%x\n", |
2050 | joystick_port[dev]); | 2037 | joystick_port[dev]); |
2051 | gameport_free_port(gameport); | 2038 | gameport_free_port(gameport); |
2052 | return -EBUSY; | 2039 | ret = -EBUSY; |
2040 | goto inc_dev; | ||
2053 | } | 2041 | } |
2054 | 2042 | ||
2055 | gameport->io = joystick_port[dev]; | 2043 | gameport->io = joystick_port[dev]; |
2056 | gameport_register_port(gameport); | 2044 | gameport_register_port(gameport); |
2057 | pci_set_drvdata(pci, gameport); | 2045 | pci_set_drvdata(pci, gameport); |
2058 | return 0; | 2046 | |
2047 | ret = 0; | ||
2048 | inc_dev: | ||
2049 | dev++; | ||
2050 | return ret; | ||
2059 | } | 2051 | } |
2060 | 2052 | ||
2061 | static void snd_riptide_joystick_remove(struct pci_dev *pci) | 2053 | static void snd_riptide_joystick_remove(struct pci_dev *pci) |
@@ -2092,7 +2084,7 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
2092 | if (err < 0) | 2084 | if (err < 0) |
2093 | goto error; | 2085 | goto error; |
2094 | card->private_data = chip; | 2086 | card->private_data = chip; |
2095 | err = snd_riptide_pcm(chip, 0, NULL); | 2087 | err = snd_riptide_pcm(chip, 0); |
2096 | if (err < 0) | 2088 | if (err < 0) |
2097 | goto error; | 2089 | goto error; |
2098 | err = snd_riptide_mixer(chip); | 2090 | err = snd_riptide_mixer(chip); |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 6c60dcd2e5a1..23d7f5d30c41 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
@@ -75,6 +75,7 @@ | |||
75 | #include <linux/interrupt.h> | 75 | #include <linux/interrupt.h> |
76 | #include <linux/pci.h> | 76 | #include <linux/pci.h> |
77 | #include <linux/module.h> | 77 | #include <linux/module.h> |
78 | #include <linux/io.h> | ||
78 | 79 | ||
79 | #include <sound/core.h> | 80 | #include <sound/core.h> |
80 | #include <sound/info.h> | 81 | #include <sound/info.h> |
@@ -85,8 +86,6 @@ | |||
85 | #include <sound/asoundef.h> | 86 | #include <sound/asoundef.h> |
86 | #include <sound/initval.h> | 87 | #include <sound/initval.h> |
87 | 88 | ||
88 | #include <asm/io.h> | ||
89 | |||
90 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 89 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
91 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 90 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
92 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | 91 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ |
@@ -632,7 +631,7 @@ snd_rme32_setframelog(struct rme32 * rme32, int n_channels, int is_playback) | |||
632 | } | 631 | } |
633 | } | 632 | } |
634 | 633 | ||
635 | static int snd_rme32_setformat(struct rme32 * rme32, int format) | 634 | static int snd_rme32_setformat(struct rme32 *rme32, snd_pcm_format_t format) |
636 | { | 635 | { |
637 | switch (format) { | 636 | switch (format) { |
638 | case SNDRV_PCM_FORMAT_S16_LE: | 637 | case SNDRV_PCM_FORMAT_S16_LE: |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 2f1a85185a16..2306ccf7281e 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/vmalloc.h> | 31 | #include <linux/vmalloc.h> |
32 | #include <linux/io.h> | ||
32 | 33 | ||
33 | #include <sound/core.h> | 34 | #include <sound/core.h> |
34 | #include <sound/info.h> | 35 | #include <sound/info.h> |
@@ -38,8 +39,6 @@ | |||
38 | #include <sound/asoundef.h> | 39 | #include <sound/asoundef.h> |
39 | #include <sound/initval.h> | 40 | #include <sound/initval.h> |
40 | 41 | ||
41 | #include <asm/io.h> | ||
42 | |||
43 | /* note, two last pcis should be equal, it is not a bug */ | 42 | /* note, two last pcis should be equal, it is not a bug */ |
44 | 43 | ||
45 | MODULE_AUTHOR("Anders Torger <torger@ludd.luth.se>"); | 44 | MODULE_AUTHOR("Anders Torger <torger@ludd.luth.se>"); |
@@ -922,8 +921,7 @@ snd_rme96_setframelog(struct rme96 *rme96, | |||
922 | } | 921 | } |
923 | 922 | ||
924 | static int | 923 | static int |
925 | snd_rme96_playback_setformat(struct rme96 *rme96, | 924 | snd_rme96_playback_setformat(struct rme96 *rme96, snd_pcm_format_t format) |
926 | int format) | ||
927 | { | 925 | { |
928 | switch (format) { | 926 | switch (format) { |
929 | case SNDRV_PCM_FORMAT_S16_LE: | 927 | case SNDRV_PCM_FORMAT_S16_LE: |
@@ -940,8 +938,7 @@ snd_rme96_playback_setformat(struct rme96 *rme96, | |||
940 | } | 938 | } |
941 | 939 | ||
942 | static int | 940 | static int |
943 | snd_rme96_capture_setformat(struct rme96 *rme96, | 941 | snd_rme96_capture_setformat(struct rme96 *rme96, snd_pcm_format_t format) |
944 | int format) | ||
945 | { | 942 | { |
946 | switch (format) { | 943 | switch (format) { |
947 | case SNDRV_PCM_FORMAT_S16_LE: | 944 | case SNDRV_PCM_FORMAT_S16_LE: |
@@ -2358,7 +2355,6 @@ snd_rme96_create_switches(struct snd_card *card, | |||
2358 | 2355 | ||
2359 | static int rme96_suspend(struct device *dev) | 2356 | static int rme96_suspend(struct device *dev) |
2360 | { | 2357 | { |
2361 | struct pci_dev *pci = to_pci_dev(dev); | ||
2362 | struct snd_card *card = dev_get_drvdata(dev); | 2358 | struct snd_card *card = dev_get_drvdata(dev); |
2363 | struct rme96 *rme96 = card->private_data; | 2359 | struct rme96 *rme96 = card->private_data; |
2364 | 2360 | ||
@@ -2381,26 +2377,14 @@ static int rme96_suspend(struct device *dev) | |||
2381 | /* disable the DAC */ | 2377 | /* disable the DAC */ |
2382 | rme96->areg &= ~RME96_AR_DAC_EN; | 2378 | rme96->areg &= ~RME96_AR_DAC_EN; |
2383 | writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); | 2379 | writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); |
2384 | |||
2385 | pci_disable_device(pci); | ||
2386 | pci_save_state(pci); | ||
2387 | |||
2388 | return 0; | 2380 | return 0; |
2389 | } | 2381 | } |
2390 | 2382 | ||
2391 | static int rme96_resume(struct device *dev) | 2383 | static int rme96_resume(struct device *dev) |
2392 | { | 2384 | { |
2393 | struct pci_dev *pci = to_pci_dev(dev); | ||
2394 | struct snd_card *card = dev_get_drvdata(dev); | 2385 | struct snd_card *card = dev_get_drvdata(dev); |
2395 | struct rme96 *rme96 = card->private_data; | 2386 | struct rme96 *rme96 = card->private_data; |
2396 | 2387 | ||
2397 | pci_restore_state(pci); | ||
2398 | if (pci_enable_device(pci) < 0) { | ||
2399 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
2400 | snd_card_disconnect(card); | ||
2401 | return -EIO; | ||
2402 | } | ||
2403 | |||
2404 | /* reset playback and record buffer pointers */ | 2388 | /* reset playback and record buffer pointers */ |
2405 | writel(0, rme96->iobase + RME96_IO_SET_PLAY_POS | 2389 | writel(0, rme96->iobase + RME96_IO_SET_PLAY_POS |
2406 | + rme96->playback_pointer); | 2390 | + rme96->playback_pointer); |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index cf5a6c8b9a63..c19e021ccf66 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/math64.h> | 30 | #include <linux/math64.h> |
31 | #include <linux/vmalloc.h> | 31 | #include <linux/vmalloc.h> |
32 | #include <linux/io.h> | ||
32 | 33 | ||
33 | #include <sound/core.h> | 34 | #include <sound/core.h> |
34 | #include <sound/control.h> | 35 | #include <sound/control.h> |
@@ -42,7 +43,6 @@ | |||
42 | 43 | ||
43 | #include <asm/byteorder.h> | 44 | #include <asm/byteorder.h> |
44 | #include <asm/current.h> | 45 | #include <asm/current.h> |
45 | #include <asm/io.h> | ||
46 | 46 | ||
47 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 47 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
48 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 48 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
@@ -1428,10 +1428,8 @@ static void snd_hdsp_midi_output_timer(unsigned long data) | |||
1428 | leaving istimer wherever it was set before. | 1428 | leaving istimer wherever it was set before. |
1429 | */ | 1429 | */ |
1430 | 1430 | ||
1431 | if (hmidi->istimer) { | 1431 | if (hmidi->istimer) |
1432 | hmidi->timer.expires = 1 + jiffies; | 1432 | mod_timer(&hmidi->timer, 1 + jiffies); |
1433 | add_timer(&hmidi->timer); | ||
1434 | } | ||
1435 | 1433 | ||
1436 | spin_unlock_irqrestore (&hmidi->lock, flags); | 1434 | spin_unlock_irqrestore (&hmidi->lock, flags); |
1437 | } | 1435 | } |
@@ -1445,11 +1443,9 @@ static void snd_hdsp_midi_output_trigger(struct snd_rawmidi_substream *substream | |||
1445 | spin_lock_irqsave (&hmidi->lock, flags); | 1443 | spin_lock_irqsave (&hmidi->lock, flags); |
1446 | if (up) { | 1444 | if (up) { |
1447 | if (!hmidi->istimer) { | 1445 | if (!hmidi->istimer) { |
1448 | init_timer(&hmidi->timer); | 1446 | setup_timer(&hmidi->timer, snd_hdsp_midi_output_timer, |
1449 | hmidi->timer.function = snd_hdsp_midi_output_timer; | 1447 | (unsigned long) hmidi); |
1450 | hmidi->timer.data = (unsigned long) hmidi; | 1448 | mod_timer(&hmidi->timer, 1 + jiffies); |
1451 | hmidi->timer.expires = 1 + jiffies; | ||
1452 | add_timer(&hmidi->timer); | ||
1453 | hmidi->istimer++; | 1449 | hmidi->istimer++; |
1454 | } | 1450 | } |
1455 | } else { | 1451 | } else { |
@@ -5309,9 +5305,7 @@ static int snd_hdsp_free(struct hdsp *hdsp) | |||
5309 | 5305 | ||
5310 | release_firmware(hdsp->firmware); | 5306 | release_firmware(hdsp->firmware); |
5311 | vfree(hdsp->fw_uploaded); | 5307 | vfree(hdsp->fw_uploaded); |
5312 | 5308 | iounmap(hdsp->iobase); | |
5313 | if (hdsp->iobase) | ||
5314 | iounmap(hdsp->iobase); | ||
5315 | 5309 | ||
5316 | if (hdsp->port) | 5310 | if (hdsp->port) |
5317 | pci_release_regions(hdsp->pci); | 5311 | pci_release_regions(hdsp->pci); |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 3342705a5715..ca67f896d117 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -136,7 +136,7 @@ | |||
136 | #include <linux/slab.h> | 136 | #include <linux/slab.h> |
137 | #include <linux/pci.h> | 137 | #include <linux/pci.h> |
138 | #include <linux/math64.h> | 138 | #include <linux/math64.h> |
139 | #include <asm/io.h> | 139 | #include <linux/io.h> |
140 | 140 | ||
141 | #include <sound/core.h> | 141 | #include <sound/core.h> |
142 | #include <sound/control.h> | 142 | #include <sound/control.h> |
@@ -1957,10 +1957,8 @@ static void snd_hdspm_midi_output_timer(unsigned long data) | |||
1957 | leaving istimer wherever it was set before. | 1957 | leaving istimer wherever it was set before. |
1958 | */ | 1958 | */ |
1959 | 1959 | ||
1960 | if (hmidi->istimer) { | 1960 | if (hmidi->istimer) |
1961 | hmidi->timer.expires = 1 + jiffies; | 1961 | mod_timer(&hmidi->timer, 1 + jiffies); |
1962 | add_timer(&hmidi->timer); | ||
1963 | } | ||
1964 | 1962 | ||
1965 | spin_unlock_irqrestore (&hmidi->lock, flags); | 1963 | spin_unlock_irqrestore (&hmidi->lock, flags); |
1966 | } | 1964 | } |
@@ -1975,11 +1973,9 @@ snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) | |||
1975 | spin_lock_irqsave (&hmidi->lock, flags); | 1973 | spin_lock_irqsave (&hmidi->lock, flags); |
1976 | if (up) { | 1974 | if (up) { |
1977 | if (!hmidi->istimer) { | 1975 | if (!hmidi->istimer) { |
1978 | init_timer(&hmidi->timer); | 1976 | setup_timer(&hmidi->timer, snd_hdspm_midi_output_timer, |
1979 | hmidi->timer.function = snd_hdspm_midi_output_timer; | 1977 | (unsigned long) hmidi); |
1980 | hmidi->timer.data = (unsigned long) hmidi; | 1978 | mod_timer(&hmidi->timer, 1 + jiffies); |
1981 | hmidi->timer.expires = 1 + jiffies; | ||
1982 | add_timer(&hmidi->timer); | ||
1983 | hmidi->istimer++; | 1979 | hmidi->istimer++; |
1984 | } | 1980 | } |
1985 | } else { | 1981 | } else { |
@@ -6086,6 +6082,9 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream) | |||
6086 | snd_pcm_hw_constraint_minmax(runtime, | 6082 | snd_pcm_hw_constraint_minmax(runtime, |
6087 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | 6083 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, |
6088 | 64, 8192); | 6084 | 64, 8192); |
6085 | snd_pcm_hw_constraint_minmax(runtime, | ||
6086 | SNDRV_PCM_HW_PARAM_PERIODS, | ||
6087 | 2, 2); | ||
6089 | break; | 6088 | break; |
6090 | } | 6089 | } |
6091 | 6090 | ||
@@ -6160,6 +6159,9 @@ static int snd_hdspm_capture_open(struct snd_pcm_substream *substream) | |||
6160 | snd_pcm_hw_constraint_minmax(runtime, | 6159 | snd_pcm_hw_constraint_minmax(runtime, |
6161 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | 6160 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, |
6162 | 64, 8192); | 6161 | 64, 8192); |
6162 | snd_pcm_hw_constraint_minmax(runtime, | ||
6163 | SNDRV_PCM_HW_PARAM_PERIODS, | ||
6164 | 2, 2); | ||
6163 | break; | 6165 | break; |
6164 | } | 6166 | } |
6165 | 6167 | ||
@@ -6965,9 +6967,7 @@ static int snd_hdspm_free(struct hdspm * hdspm) | |||
6965 | free_irq(hdspm->irq, (void *) hdspm); | 6967 | free_irq(hdspm->irq, (void *) hdspm); |
6966 | 6968 | ||
6967 | kfree(hdspm->mixer); | 6969 | kfree(hdspm->mixer); |
6968 | 6970 | iounmap(hdspm->iobase); | |
6969 | if (hdspm->iobase) | ||
6970 | iounmap(hdspm->iobase); | ||
6971 | 6971 | ||
6972 | if (hdspm->port) | 6972 | if (hdspm->port) |
6973 | pci_release_regions(hdspm->pci); | 6973 | pci_release_regions(hdspm->pci); |
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 6521521853b8..fdbc0aa2776a 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/io.h> | ||
28 | 29 | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/control.h> | 31 | #include <sound/control.h> |
@@ -34,7 +35,6 @@ | |||
34 | #include <sound/initval.h> | 35 | #include <sound/initval.h> |
35 | 36 | ||
36 | #include <asm/current.h> | 37 | #include <asm/current.h> |
37 | #include <asm/io.h> | ||
38 | 38 | ||
39 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 39 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
40 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 40 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
@@ -1756,8 +1756,7 @@ static int snd_rme9652_free(struct snd_rme9652 *rme9652) | |||
1756 | 1756 | ||
1757 | if (rme9652->irq >= 0) | 1757 | if (rme9652->irq >= 0) |
1758 | free_irq(rme9652->irq, (void *)rme9652); | 1758 | free_irq(rme9652->irq, (void *)rme9652); |
1759 | if (rme9652->iobase) | 1759 | iounmap(rme9652->iobase); |
1760 | iounmap(rme9652->iobase); | ||
1761 | if (rme9652->port) | 1760 | if (rme9652->port) |
1762 | pci_release_regions(rme9652->pci); | 1761 | pci_release_regions(rme9652->pci); |
1763 | 1762 | ||
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index 7f6a0a0d115a..efe669b80256 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c | |||
@@ -1064,12 +1064,9 @@ static int sis_chip_free(struct sis7019 *sis) | |||
1064 | if (sis->irq >= 0) | 1064 | if (sis->irq >= 0) |
1065 | free_irq(sis->irq, sis); | 1065 | free_irq(sis->irq, sis); |
1066 | 1066 | ||
1067 | if (sis->ioaddr) | 1067 | iounmap(sis->ioaddr); |
1068 | iounmap(sis->ioaddr); | ||
1069 | |||
1070 | pci_release_regions(sis->pci); | 1068 | pci_release_regions(sis->pci); |
1071 | pci_disable_device(sis->pci); | 1069 | pci_disable_device(sis->pci); |
1072 | |||
1073 | sis_free_suspend(sis); | 1070 | sis_free_suspend(sis); |
1074 | return 0; | 1071 | return 0; |
1075 | } | 1072 | } |
@@ -1211,7 +1208,6 @@ static int sis_chip_init(struct sis7019 *sis) | |||
1211 | #ifdef CONFIG_PM_SLEEP | 1208 | #ifdef CONFIG_PM_SLEEP |
1212 | static int sis_suspend(struct device *dev) | 1209 | static int sis_suspend(struct device *dev) |
1213 | { | 1210 | { |
1214 | struct pci_dev *pci = to_pci_dev(dev); | ||
1215 | struct snd_card *card = dev_get_drvdata(dev); | 1211 | struct snd_card *card = dev_get_drvdata(dev); |
1216 | struct sis7019 *sis = card->private_data; | 1212 | struct sis7019 *sis = card->private_data; |
1217 | void __iomem *ioaddr = sis->ioaddr; | 1213 | void __iomem *ioaddr = sis->ioaddr; |
@@ -1240,9 +1236,6 @@ static int sis_suspend(struct device *dev) | |||
1240 | ioaddr += 4096; | 1236 | ioaddr += 4096; |
1241 | } | 1237 | } |
1242 | 1238 | ||
1243 | pci_disable_device(pci); | ||
1244 | pci_save_state(pci); | ||
1245 | pci_set_power_state(pci, PCI_D3hot); | ||
1246 | return 0; | 1239 | return 0; |
1247 | } | 1240 | } |
1248 | 1241 | ||
@@ -1254,14 +1247,6 @@ static int sis_resume(struct device *dev) | |||
1254 | void __iomem *ioaddr = sis->ioaddr; | 1247 | void __iomem *ioaddr = sis->ioaddr; |
1255 | int i; | 1248 | int i; |
1256 | 1249 | ||
1257 | pci_set_power_state(pci, PCI_D0); | ||
1258 | pci_restore_state(pci); | ||
1259 | |||
1260 | if (pci_enable_device(pci) < 0) { | ||
1261 | dev_err(&pci->dev, "unable to re-enable device\n"); | ||
1262 | goto error; | ||
1263 | } | ||
1264 | |||
1265 | if (sis_chip_init(sis)) { | 1250 | if (sis_chip_init(sis)) { |
1266 | dev_err(&pci->dev, "unable to re-init controller\n"); | 1251 | dev_err(&pci->dev, "unable to re-init controller\n"); |
1267 | goto error; | 1252 | goto error; |
@@ -1284,7 +1269,6 @@ static int sis_resume(struct device *dev) | |||
1284 | memset(sis->suspend_state[0], 0, 4096); | 1269 | memset(sis->suspend_state[0], 0, 4096); |
1285 | 1270 | ||
1286 | sis->irq = pci->irq; | 1271 | sis->irq = pci->irq; |
1287 | pci_set_master(pci); | ||
1288 | 1272 | ||
1289 | if (sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT) | 1273 | if (sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT) |
1290 | snd_ac97_resume(sis->ac97[0]); | 1274 | snd_ac97_resume(sis->ac97[0]); |
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 313a7328bf9c..0f40624a4275 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/gameport.h> | 30 | #include <linux/gameport.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
33 | #include <linux/io.h> | ||
33 | 34 | ||
34 | #include <sound/core.h> | 35 | #include <sound/core.h> |
35 | #include <sound/pcm.h> | 36 | #include <sound/pcm.h> |
@@ -39,8 +40,6 @@ | |||
39 | #include <sound/opl3.h> | 40 | #include <sound/opl3.h> |
40 | #include <sound/initval.h> | 41 | #include <sound/initval.h> |
41 | 42 | ||
42 | #include <asm/io.h> | ||
43 | |||
44 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 43 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
45 | MODULE_DESCRIPTION("S3 SonicVibes PCI"); | 44 | MODULE_DESCRIPTION("S3 SonicVibes PCI"); |
46 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
@@ -880,8 +879,7 @@ static struct snd_pcm_ops snd_sonicvibes_capture_ops = { | |||
880 | .pointer = snd_sonicvibes_capture_pointer, | 879 | .pointer = snd_sonicvibes_capture_pointer, |
881 | }; | 880 | }; |
882 | 881 | ||
883 | static int snd_sonicvibes_pcm(struct sonicvibes *sonic, int device, | 882 | static int snd_sonicvibes_pcm(struct sonicvibes *sonic, int device) |
884 | struct snd_pcm **rpcm) | ||
885 | { | 883 | { |
886 | struct snd_pcm *pcm; | 884 | struct snd_pcm *pcm; |
887 | int err; | 885 | int err; |
@@ -902,8 +900,6 @@ static int snd_sonicvibes_pcm(struct sonicvibes *sonic, int device, | |||
902 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 900 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
903 | snd_dma_pci_data(sonic->pci), 64*1024, 128*1024); | 901 | snd_dma_pci_data(sonic->pci), 64*1024, 128*1024); |
904 | 902 | ||
905 | if (rpcm) | ||
906 | *rpcm = pcm; | ||
907 | return 0; | 903 | return 0; |
908 | } | 904 | } |
909 | 905 | ||
@@ -1491,7 +1487,7 @@ static int snd_sonic_probe(struct pci_dev *pci, | |||
1491 | (unsigned long long)pci_resource_start(pci, 1), | 1487 | (unsigned long long)pci_resource_start(pci, 1), |
1492 | sonic->irq); | 1488 | sonic->irq); |
1493 | 1489 | ||
1494 | if ((err = snd_sonicvibes_pcm(sonic, 0, NULL)) < 0) { | 1490 | if ((err = snd_sonicvibes_pcm(sonic, 0)) < 0) { |
1495 | snd_card_free(card); | 1491 | snd_card_free(card); |
1496 | return err; | 1492 | return err; |
1497 | } | 1493 | } |
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index a54cd6879b31..cedf13b64803 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
@@ -127,21 +127,21 @@ static int snd_trident_probe(struct pci_dev *pci, | |||
127 | sprintf(card->longname, "%s PCI Audio at 0x%lx, irq %d", | 127 | sprintf(card->longname, "%s PCI Audio at 0x%lx, irq %d", |
128 | card->shortname, trident->port, trident->irq); | 128 | card->shortname, trident->port, trident->irq); |
129 | 129 | ||
130 | if ((err = snd_trident_pcm(trident, pcm_dev++, NULL)) < 0) { | 130 | if ((err = snd_trident_pcm(trident, pcm_dev++)) < 0) { |
131 | snd_card_free(card); | 131 | snd_card_free(card); |
132 | return err; | 132 | return err; |
133 | } | 133 | } |
134 | switch (trident->device) { | 134 | switch (trident->device) { |
135 | case TRIDENT_DEVICE_ID_DX: | 135 | case TRIDENT_DEVICE_ID_DX: |
136 | case TRIDENT_DEVICE_ID_NX: | 136 | case TRIDENT_DEVICE_ID_NX: |
137 | if ((err = snd_trident_foldback_pcm(trident, pcm_dev++, NULL)) < 0) { | 137 | if ((err = snd_trident_foldback_pcm(trident, pcm_dev++)) < 0) { |
138 | snd_card_free(card); | 138 | snd_card_free(card); |
139 | return err; | 139 | return err; |
140 | } | 140 | } |
141 | break; | 141 | break; |
142 | } | 142 | } |
143 | if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) { | 143 | if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) { |
144 | if ((err = snd_trident_spdif_pcm(trident, pcm_dev++, NULL)) < 0) { | 144 | if ((err = snd_trident_spdif_pcm(trident, pcm_dev++)) < 0) { |
145 | snd_card_free(card); | 145 | snd_card_free(card); |
146 | return err; | 146 | return err; |
147 | } | 147 | } |
diff --git a/sound/pci/trident/trident.h b/sound/pci/trident/trident.h index 5f110eb56e47..9624e5937719 100644 --- a/sound/pci/trident/trident.h +++ b/sound/pci/trident/trident.h | |||
@@ -420,9 +420,9 @@ int snd_trident_create(struct snd_card *card, | |||
420 | struct snd_trident ** rtrident); | 420 | struct snd_trident ** rtrident); |
421 | int snd_trident_create_gameport(struct snd_trident *trident); | 421 | int snd_trident_create_gameport(struct snd_trident *trident); |
422 | 422 | ||
423 | int snd_trident_pcm(struct snd_trident * trident, int device, struct snd_pcm **rpcm); | 423 | int snd_trident_pcm(struct snd_trident *trident, int device); |
424 | int snd_trident_foldback_pcm(struct snd_trident * trident, int device, struct snd_pcm **rpcm); | 424 | int snd_trident_foldback_pcm(struct snd_trident *trident, int device); |
425 | int snd_trident_spdif_pcm(struct snd_trident * trident, int device, struct snd_pcm **rpcm); | 425 | int snd_trident_spdif_pcm(struct snd_trident *trident, int device); |
426 | int snd_trident_attach_synthesizer(struct snd_trident * trident); | 426 | int snd_trident_attach_synthesizer(struct snd_trident * trident); |
427 | struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, | 427 | struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, |
428 | int client, int port); | 428 | int client, int port); |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 57cd757acfe7..b72be035f785 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/gameport.h> | 36 | #include <linux/gameport.h> |
37 | #include <linux/dma-mapping.h> | 37 | #include <linux/dma-mapping.h> |
38 | #include <linux/export.h> | 38 | #include <linux/export.h> |
39 | #include <linux/io.h> | ||
39 | 40 | ||
40 | #include <sound/core.h> | 41 | #include <sound/core.h> |
41 | #include <sound/info.h> | 42 | #include <sound/info.h> |
@@ -44,8 +45,6 @@ | |||
44 | #include "trident.h" | 45 | #include "trident.h" |
45 | #include <sound/asoundef.h> | 46 | #include <sound/asoundef.h> |
46 | 47 | ||
47 | #include <asm/io.h> | ||
48 | |||
49 | static int snd_trident_pcm_mixer_build(struct snd_trident *trident, | 48 | static int snd_trident_pcm_mixer_build(struct snd_trident *trident, |
50 | struct snd_trident_voice * voice, | 49 | struct snd_trident_voice * voice, |
51 | struct snd_pcm_substream *substream); | 50 | struct snd_pcm_substream *substream); |
@@ -2172,14 +2171,11 @@ static struct snd_pcm_ops snd_trident_spdif_7018_ops = { | |||
2172 | 2171 | ||
2173 | ---------------------------------------------------------------------------*/ | 2172 | ---------------------------------------------------------------------------*/ |
2174 | 2173 | ||
2175 | int snd_trident_pcm(struct snd_trident *trident, | 2174 | int snd_trident_pcm(struct snd_trident *trident, int device) |
2176 | int device, struct snd_pcm **rpcm) | ||
2177 | { | 2175 | { |
2178 | struct snd_pcm *pcm; | 2176 | struct snd_pcm *pcm; |
2179 | int err; | 2177 | int err; |
2180 | 2178 | ||
2181 | if (rpcm) | ||
2182 | *rpcm = NULL; | ||
2183 | if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, trident->ChanPCM, 1, &pcm)) < 0) | 2179 | if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, trident->ChanPCM, 1, &pcm)) < 0) |
2184 | return err; | 2180 | return err; |
2185 | 2181 | ||
@@ -2214,8 +2210,6 @@ int snd_trident_pcm(struct snd_trident *trident, | |||
2214 | snd_dma_pci_data(trident->pci), 64*1024, 128*1024); | 2210 | snd_dma_pci_data(trident->pci), 64*1024, 128*1024); |
2215 | } | 2211 | } |
2216 | 2212 | ||
2217 | if (rpcm) | ||
2218 | *rpcm = pcm; | ||
2219 | return 0; | 2213 | return 0; |
2220 | } | 2214 | } |
2221 | 2215 | ||
@@ -2230,16 +2224,13 @@ int snd_trident_pcm(struct snd_trident *trident, | |||
2230 | 2224 | ||
2231 | ---------------------------------------------------------------------------*/ | 2225 | ---------------------------------------------------------------------------*/ |
2232 | 2226 | ||
2233 | int snd_trident_foldback_pcm(struct snd_trident *trident, | 2227 | int snd_trident_foldback_pcm(struct snd_trident *trident, int device) |
2234 | int device, struct snd_pcm **rpcm) | ||
2235 | { | 2228 | { |
2236 | struct snd_pcm *foldback; | 2229 | struct snd_pcm *foldback; |
2237 | int err; | 2230 | int err; |
2238 | int num_chan = 3; | 2231 | int num_chan = 3; |
2239 | struct snd_pcm_substream *substream; | 2232 | struct snd_pcm_substream *substream; |
2240 | 2233 | ||
2241 | if (rpcm) | ||
2242 | *rpcm = NULL; | ||
2243 | if (trident->device == TRIDENT_DEVICE_ID_NX) | 2234 | if (trident->device == TRIDENT_DEVICE_ID_NX) |
2244 | num_chan = 4; | 2235 | num_chan = 4; |
2245 | if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, 0, num_chan, &foldback)) < 0) | 2236 | if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, 0, num_chan, &foldback)) < 0) |
@@ -2271,8 +2262,6 @@ int snd_trident_foldback_pcm(struct snd_trident *trident, | |||
2271 | snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV, | 2262 | snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV, |
2272 | snd_dma_pci_data(trident->pci), 64*1024, 128*1024); | 2263 | snd_dma_pci_data(trident->pci), 64*1024, 128*1024); |
2273 | 2264 | ||
2274 | if (rpcm) | ||
2275 | *rpcm = foldback; | ||
2276 | return 0; | 2265 | return 0; |
2277 | } | 2266 | } |
2278 | 2267 | ||
@@ -2287,14 +2276,11 @@ int snd_trident_foldback_pcm(struct snd_trident *trident, | |||
2287 | 2276 | ||
2288 | ---------------------------------------------------------------------------*/ | 2277 | ---------------------------------------------------------------------------*/ |
2289 | 2278 | ||
2290 | int snd_trident_spdif_pcm(struct snd_trident *trident, | 2279 | int snd_trident_spdif_pcm(struct snd_trident *trident, int device) |
2291 | int device, struct snd_pcm **rpcm) | ||
2292 | { | 2280 | { |
2293 | struct snd_pcm *spdif; | 2281 | struct snd_pcm *spdif; |
2294 | int err; | 2282 | int err; |
2295 | 2283 | ||
2296 | if (rpcm) | ||
2297 | *rpcm = NULL; | ||
2298 | if ((err = snd_pcm_new(trident->card, "trident_dx_nx IEC958", device, 1, 0, &spdif)) < 0) | 2284 | if ((err = snd_pcm_new(trident->card, "trident_dx_nx IEC958", device, 1, 0, &spdif)) < 0) |
2299 | return err; | 2285 | return err; |
2300 | 2286 | ||
@@ -2310,8 +2296,6 @@ int snd_trident_spdif_pcm(struct snd_trident *trident, | |||
2310 | 2296 | ||
2311 | snd_pcm_lib_preallocate_pages_for_all(spdif, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), 64*1024, 128*1024); | 2297 | snd_pcm_lib_preallocate_pages_for_all(spdif, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), 64*1024, 128*1024); |
2312 | 2298 | ||
2313 | if (rpcm) | ||
2314 | *rpcm = spdif; | ||
2315 | return 0; | 2299 | return 0; |
2316 | } | 2300 | } |
2317 | 2301 | ||
@@ -3926,7 +3910,6 @@ static void snd_trident_clear_voices(struct snd_trident * trident, unsigned shor | |||
3926 | #ifdef CONFIG_PM_SLEEP | 3910 | #ifdef CONFIG_PM_SLEEP |
3927 | static int snd_trident_suspend(struct device *dev) | 3911 | static int snd_trident_suspend(struct device *dev) |
3928 | { | 3912 | { |
3929 | struct pci_dev *pci = to_pci_dev(dev); | ||
3930 | struct snd_card *card = dev_get_drvdata(dev); | 3913 | struct snd_card *card = dev_get_drvdata(dev); |
3931 | struct snd_trident *trident = card->private_data; | 3914 | struct snd_trident *trident = card->private_data; |
3932 | 3915 | ||
@@ -3938,28 +3921,14 @@ static int snd_trident_suspend(struct device *dev) | |||
3938 | 3921 | ||
3939 | snd_ac97_suspend(trident->ac97); | 3922 | snd_ac97_suspend(trident->ac97); |
3940 | snd_ac97_suspend(trident->ac97_sec); | 3923 | snd_ac97_suspend(trident->ac97_sec); |
3941 | |||
3942 | pci_disable_device(pci); | ||
3943 | pci_save_state(pci); | ||
3944 | pci_set_power_state(pci, PCI_D3hot); | ||
3945 | return 0; | 3924 | return 0; |
3946 | } | 3925 | } |
3947 | 3926 | ||
3948 | static int snd_trident_resume(struct device *dev) | 3927 | static int snd_trident_resume(struct device *dev) |
3949 | { | 3928 | { |
3950 | struct pci_dev *pci = to_pci_dev(dev); | ||
3951 | struct snd_card *card = dev_get_drvdata(dev); | 3929 | struct snd_card *card = dev_get_drvdata(dev); |
3952 | struct snd_trident *trident = card->private_data; | 3930 | struct snd_trident *trident = card->private_data; |
3953 | 3931 | ||
3954 | pci_set_power_state(pci, PCI_D0); | ||
3955 | pci_restore_state(pci); | ||
3956 | if (pci_enable_device(pci) < 0) { | ||
3957 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
3958 | snd_card_disconnect(card); | ||
3959 | return -EIO; | ||
3960 | } | ||
3961 | pci_set_master(pci); | ||
3962 | |||
3963 | switch (trident->device) { | 3932 | switch (trident->device) { |
3964 | case TRIDENT_DEVICE_ID_DX: | 3933 | case TRIDENT_DEVICE_ID_DX: |
3965 | snd_trident_4d_dx_init(trident); | 3934 | snd_trident_4d_dx_init(trident); |
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index 04c474658e3c..b9ebb51893c5 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c | |||
@@ -23,7 +23,7 @@ | |||
23 | * | 23 | * |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <asm/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <linux/time.h> | 28 | #include <linux/time.h> |
29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index e088467fb736..8622283e89f3 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -46,7 +46,7 @@ | |||
46 | * - Optimize position calculation for the 823x chips. | 46 | * - Optimize position calculation for the 823x chips. |
47 | */ | 47 | */ |
48 | 48 | ||
49 | #include <asm/io.h> | 49 | #include <linux/io.h> |
50 | #include <linux/delay.h> | 50 | #include <linux/delay.h> |
51 | #include <linux/interrupt.h> | 51 | #include <linux/interrupt.h> |
52 | #include <linux/init.h> | 52 | #include <linux/init.h> |
@@ -2271,7 +2271,6 @@ static int snd_via82xx_chip_init(struct via82xx *chip) | |||
2271 | */ | 2271 | */ |
2272 | static int snd_via82xx_suspend(struct device *dev) | 2272 | static int snd_via82xx_suspend(struct device *dev) |
2273 | { | 2273 | { |
2274 | struct pci_dev *pci = to_pci_dev(dev); | ||
2275 | struct snd_card *card = dev_get_drvdata(dev); | 2274 | struct snd_card *card = dev_get_drvdata(dev); |
2276 | struct via82xx *chip = card->private_data; | 2275 | struct via82xx *chip = card->private_data; |
2277 | int i; | 2276 | int i; |
@@ -2291,28 +2290,15 @@ static int snd_via82xx_suspend(struct device *dev) | |||
2291 | chip->capture_src_saved[1] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10); | 2290 | chip->capture_src_saved[1] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10); |
2292 | } | 2291 | } |
2293 | 2292 | ||
2294 | pci_disable_device(pci); | ||
2295 | pci_save_state(pci); | ||
2296 | pci_set_power_state(pci, PCI_D3hot); | ||
2297 | return 0; | 2293 | return 0; |
2298 | } | 2294 | } |
2299 | 2295 | ||
2300 | static int snd_via82xx_resume(struct device *dev) | 2296 | static int snd_via82xx_resume(struct device *dev) |
2301 | { | 2297 | { |
2302 | struct pci_dev *pci = to_pci_dev(dev); | ||
2303 | struct snd_card *card = dev_get_drvdata(dev); | 2298 | struct snd_card *card = dev_get_drvdata(dev); |
2304 | struct via82xx *chip = card->private_data; | 2299 | struct via82xx *chip = card->private_data; |
2305 | int i; | 2300 | int i; |
2306 | 2301 | ||
2307 | pci_set_power_state(pci, PCI_D0); | ||
2308 | pci_restore_state(pci); | ||
2309 | if (pci_enable_device(pci) < 0) { | ||
2310 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
2311 | snd_card_disconnect(card); | ||
2312 | return -EIO; | ||
2313 | } | ||
2314 | pci_set_master(pci); | ||
2315 | |||
2316 | snd_via82xx_chip_init(chip); | 2302 | snd_via82xx_chip_init(chip); |
2317 | 2303 | ||
2318 | if (chip->chip_type == TYPE_VIA686) { | 2304 | if (chip->chip_type == TYPE_VIA686) { |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index fd46ffe12e4f..99b9137bc677 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -31,7 +31,7 @@ | |||
31 | * modems. | 31 | * modems. |
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <asm/io.h> | 34 | #include <linux/io.h> |
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
@@ -1031,7 +1031,6 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) | |||
1031 | */ | 1031 | */ |
1032 | static int snd_via82xx_suspend(struct device *dev) | 1032 | static int snd_via82xx_suspend(struct device *dev) |
1033 | { | 1033 | { |
1034 | struct pci_dev *pci = to_pci_dev(dev); | ||
1035 | struct snd_card *card = dev_get_drvdata(dev); | 1034 | struct snd_card *card = dev_get_drvdata(dev); |
1036 | struct via82xx_modem *chip = card->private_data; | 1035 | struct via82xx_modem *chip = card->private_data; |
1037 | int i; | 1036 | int i; |
@@ -1043,29 +1042,15 @@ static int snd_via82xx_suspend(struct device *dev) | |||
1043 | snd_via82xx_channel_reset(chip, &chip->devs[i]); | 1042 | snd_via82xx_channel_reset(chip, &chip->devs[i]); |
1044 | synchronize_irq(chip->irq); | 1043 | synchronize_irq(chip->irq); |
1045 | snd_ac97_suspend(chip->ac97); | 1044 | snd_ac97_suspend(chip->ac97); |
1046 | |||
1047 | pci_disable_device(pci); | ||
1048 | pci_save_state(pci); | ||
1049 | pci_set_power_state(pci, PCI_D3hot); | ||
1050 | return 0; | 1045 | return 0; |
1051 | } | 1046 | } |
1052 | 1047 | ||
1053 | static int snd_via82xx_resume(struct device *dev) | 1048 | static int snd_via82xx_resume(struct device *dev) |
1054 | { | 1049 | { |
1055 | struct pci_dev *pci = to_pci_dev(dev); | ||
1056 | struct snd_card *card = dev_get_drvdata(dev); | 1050 | struct snd_card *card = dev_get_drvdata(dev); |
1057 | struct via82xx_modem *chip = card->private_data; | 1051 | struct via82xx_modem *chip = card->private_data; |
1058 | int i; | 1052 | int i; |
1059 | 1053 | ||
1060 | pci_set_power_state(pci, PCI_D0); | ||
1061 | pci_restore_state(pci); | ||
1062 | if (pci_enable_device(pci) < 0) { | ||
1063 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
1064 | snd_card_disconnect(card); | ||
1065 | return -EIO; | ||
1066 | } | ||
1067 | pci_set_master(pci); | ||
1068 | |||
1069 | snd_via82xx_chip_init(chip); | 1054 | snd_via82xx_chip_init(chip); |
1070 | 1055 | ||
1071 | snd_ac97_resume(chip->ac97); | 1056 | snd_ac97_resume(chip->ac97); |
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index c5a25e39e3a8..ecbaf473fc1e 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c | |||
@@ -259,32 +259,17 @@ static void snd_vx222_remove(struct pci_dev *pci) | |||
259 | #ifdef CONFIG_PM_SLEEP | 259 | #ifdef CONFIG_PM_SLEEP |
260 | static int snd_vx222_suspend(struct device *dev) | 260 | static int snd_vx222_suspend(struct device *dev) |
261 | { | 261 | { |
262 | struct pci_dev *pci = to_pci_dev(dev); | ||
263 | struct snd_card *card = dev_get_drvdata(dev); | 262 | struct snd_card *card = dev_get_drvdata(dev); |
264 | struct snd_vx222 *vx = card->private_data; | 263 | struct snd_vx222 *vx = card->private_data; |
265 | int err; | ||
266 | 264 | ||
267 | err = snd_vx_suspend(&vx->core); | 265 | return snd_vx_suspend(&vx->core); |
268 | pci_disable_device(pci); | ||
269 | pci_save_state(pci); | ||
270 | pci_set_power_state(pci, PCI_D3hot); | ||
271 | return err; | ||
272 | } | 266 | } |
273 | 267 | ||
274 | static int snd_vx222_resume(struct device *dev) | 268 | static int snd_vx222_resume(struct device *dev) |
275 | { | 269 | { |
276 | struct pci_dev *pci = to_pci_dev(dev); | ||
277 | struct snd_card *card = dev_get_drvdata(dev); | 270 | struct snd_card *card = dev_get_drvdata(dev); |
278 | struct snd_vx222 *vx = card->private_data; | 271 | struct snd_vx222 *vx = card->private_data; |
279 | 272 | ||
280 | pci_set_power_state(pci, PCI_D0); | ||
281 | pci_restore_state(pci); | ||
282 | if (pci_enable_device(pci) < 0) { | ||
283 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
284 | snd_card_disconnect(card); | ||
285 | return -EIO; | ||
286 | } | ||
287 | pci_set_master(pci); | ||
288 | return snd_vx_resume(&vx->core); | 273 | return snd_vx_resume(&vx->core); |
289 | } | 274 | } |
290 | 275 | ||
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index 52c1a8d5b88a..af83b3b38052 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c | |||
@@ -24,11 +24,11 @@ | |||
24 | #include <linux/device.h> | 24 | #include <linux/device.h> |
25 | #include <linux/firmware.h> | 25 | #include <linux/firmware.h> |
26 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
27 | #include <linux/io.h> | ||
27 | 28 | ||
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
29 | #include <sound/control.h> | 30 | #include <sound/control.h> |
30 | #include <sound/tlv.h> | 31 | #include <sound/tlv.h> |
31 | #include <asm/io.h> | ||
32 | #include "vx222.h" | 32 | #include "vx222.h" |
33 | 33 | ||
34 | 34 | ||
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 47a192369e8f..812e27a1bcbc 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
@@ -283,11 +283,11 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, | |||
283 | card->shortname, | 283 | card->shortname, |
284 | chip->reg_area_phys, | 284 | chip->reg_area_phys, |
285 | chip->irq); | 285 | chip->irq); |
286 | if ((err = snd_ymfpci_pcm(chip, 0, NULL)) < 0) { | 286 | if ((err = snd_ymfpci_pcm(chip, 0)) < 0) { |
287 | snd_card_free(card); | 287 | snd_card_free(card); |
288 | return err; | 288 | return err; |
289 | } | 289 | } |
290 | if ((err = snd_ymfpci_pcm_spdif(chip, 1, NULL)) < 0) { | 290 | if ((err = snd_ymfpci_pcm_spdif(chip, 1)) < 0) { |
291 | snd_card_free(card); | 291 | snd_card_free(card); |
292 | return err; | 292 | return err; |
293 | } | 293 | } |
@@ -297,12 +297,12 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, | |||
297 | return err; | 297 | return err; |
298 | } | 298 | } |
299 | if (chip->ac97->ext_id & AC97_EI_SDAC) { | 299 | if (chip->ac97->ext_id & AC97_EI_SDAC) { |
300 | err = snd_ymfpci_pcm_4ch(chip, 2, NULL); | 300 | err = snd_ymfpci_pcm_4ch(chip, 2); |
301 | if (err < 0) { | 301 | if (err < 0) { |
302 | snd_card_free(card); | 302 | snd_card_free(card); |
303 | return err; | 303 | return err; |
304 | } | 304 | } |
305 | err = snd_ymfpci_pcm2(chip, 3, NULL); | 305 | err = snd_ymfpci_pcm2(chip, 3); |
306 | if (err < 0) { | 306 | if (err < 0) { |
307 | snd_card_free(card); | 307 | snd_card_free(card); |
308 | return err; | 308 | return err; |
diff --git a/sound/pci/ymfpci/ymfpci.h b/sound/pci/ymfpci/ymfpci.h index 4631a2348915..149d4cb46998 100644 --- a/sound/pci/ymfpci/ymfpci.h +++ b/sound/pci/ymfpci/ymfpci.h | |||
@@ -379,10 +379,10 @@ void snd_ymfpci_free_gameport(struct snd_ymfpci *chip); | |||
379 | 379 | ||
380 | extern const struct dev_pm_ops snd_ymfpci_pm; | 380 | extern const struct dev_pm_ops snd_ymfpci_pm; |
381 | 381 | ||
382 | int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); | 382 | int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device); |
383 | int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); | 383 | int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device); |
384 | int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); | 384 | int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device); |
385 | int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); | 385 | int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device); |
386 | int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch); | 386 | int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch); |
387 | int snd_ymfpci_timer(struct snd_ymfpci *chip, int device); | 387 | int snd_ymfpci_timer(struct snd_ymfpci *chip, int device); |
388 | 388 | ||
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 81c916a5eb96..4c26076dbf78 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/io.h> | ||
30 | 31 | ||
31 | #include <sound/core.h> | 32 | #include <sound/core.h> |
32 | #include <sound/control.h> | 33 | #include <sound/control.h> |
@@ -36,7 +37,6 @@ | |||
36 | #include <sound/asoundef.h> | 37 | #include <sound/asoundef.h> |
37 | #include <sound/mpu401.h> | 38 | #include <sound/mpu401.h> |
38 | 39 | ||
39 | #include <asm/io.h> | ||
40 | #include <asm/byteorder.h> | 40 | #include <asm/byteorder.h> |
41 | 41 | ||
42 | /* | 42 | /* |
@@ -1145,13 +1145,11 @@ static struct snd_pcm_ops snd_ymfpci_capture_rec_ops = { | |||
1145 | .pointer = snd_ymfpci_capture_pointer, | 1145 | .pointer = snd_ymfpci_capture_pointer, |
1146 | }; | 1146 | }; |
1147 | 1147 | ||
1148 | int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm) | 1148 | int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device) |
1149 | { | 1149 | { |
1150 | struct snd_pcm *pcm; | 1150 | struct snd_pcm *pcm; |
1151 | int err; | 1151 | int err; |
1152 | 1152 | ||
1153 | if (rpcm) | ||
1154 | *rpcm = NULL; | ||
1155 | if ((err = snd_pcm_new(chip->card, "YMFPCI", device, 32, 1, &pcm)) < 0) | 1153 | if ((err = snd_pcm_new(chip->card, "YMFPCI", device, 32, 1, &pcm)) < 0) |
1156 | return err; | 1154 | return err; |
1157 | pcm->private_data = chip; | 1155 | pcm->private_data = chip; |
@@ -1167,14 +1165,8 @@ int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm) | |||
1167 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1165 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1168 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); | 1166 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); |
1169 | 1167 | ||
1170 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | 1168 | return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, |
1171 | snd_pcm_std_chmaps, 2, 0, NULL); | 1169 | snd_pcm_std_chmaps, 2, 0, NULL); |
1172 | if (err < 0) | ||
1173 | return err; | ||
1174 | |||
1175 | if (rpcm) | ||
1176 | *rpcm = pcm; | ||
1177 | return 0; | ||
1178 | } | 1170 | } |
1179 | 1171 | ||
1180 | static struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = { | 1172 | static struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = { |
@@ -1188,13 +1180,11 @@ static struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = { | |||
1188 | .pointer = snd_ymfpci_capture_pointer, | 1180 | .pointer = snd_ymfpci_capture_pointer, |
1189 | }; | 1181 | }; |
1190 | 1182 | ||
1191 | int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm) | 1183 | int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device) |
1192 | { | 1184 | { |
1193 | struct snd_pcm *pcm; | 1185 | struct snd_pcm *pcm; |
1194 | int err; | 1186 | int err; |
1195 | 1187 | ||
1196 | if (rpcm) | ||
1197 | *rpcm = NULL; | ||
1198 | if ((err = snd_pcm_new(chip->card, "YMFPCI - PCM2", device, 0, 1, &pcm)) < 0) | 1188 | if ((err = snd_pcm_new(chip->card, "YMFPCI - PCM2", device, 0, 1, &pcm)) < 0) |
1199 | return err; | 1189 | return err; |
1200 | pcm->private_data = chip; | 1190 | pcm->private_data = chip; |
@@ -1210,8 +1200,6 @@ int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm) | |||
1210 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1200 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1211 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); | 1201 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); |
1212 | 1202 | ||
1213 | if (rpcm) | ||
1214 | *rpcm = pcm; | ||
1215 | return 0; | 1203 | return 0; |
1216 | } | 1204 | } |
1217 | 1205 | ||
@@ -1226,14 +1214,11 @@ static struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = { | |||
1226 | .pointer = snd_ymfpci_playback_pointer, | 1214 | .pointer = snd_ymfpci_playback_pointer, |
1227 | }; | 1215 | }; |
1228 | 1216 | ||
1229 | int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, | 1217 | int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device) |
1230 | struct snd_pcm **rpcm) | ||
1231 | { | 1218 | { |
1232 | struct snd_pcm *pcm; | 1219 | struct snd_pcm *pcm; |
1233 | int err; | 1220 | int err; |
1234 | 1221 | ||
1235 | if (rpcm) | ||
1236 | *rpcm = NULL; | ||
1237 | if ((err = snd_pcm_new(chip->card, "YMFPCI - IEC958", device, 1, 0, &pcm)) < 0) | 1222 | if ((err = snd_pcm_new(chip->card, "YMFPCI - IEC958", device, 1, 0, &pcm)) < 0) |
1238 | return err; | 1223 | return err; |
1239 | pcm->private_data = chip; | 1224 | pcm->private_data = chip; |
@@ -1248,8 +1233,6 @@ int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, | |||
1248 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1233 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1249 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); | 1234 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); |
1250 | 1235 | ||
1251 | if (rpcm) | ||
1252 | *rpcm = pcm; | ||
1253 | return 0; | 1236 | return 0; |
1254 | } | 1237 | } |
1255 | 1238 | ||
@@ -1272,14 +1255,11 @@ static const struct snd_pcm_chmap_elem surround_map[] = { | |||
1272 | { } | 1255 | { } |
1273 | }; | 1256 | }; |
1274 | 1257 | ||
1275 | int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, | 1258 | int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device) |
1276 | struct snd_pcm **rpcm) | ||
1277 | { | 1259 | { |
1278 | struct snd_pcm *pcm; | 1260 | struct snd_pcm *pcm; |
1279 | int err; | 1261 | int err; |
1280 | 1262 | ||
1281 | if (rpcm) | ||
1282 | *rpcm = NULL; | ||
1283 | if ((err = snd_pcm_new(chip->card, "YMFPCI - Rear", device, 1, 0, &pcm)) < 0) | 1263 | if ((err = snd_pcm_new(chip->card, "YMFPCI - Rear", device, 1, 0, &pcm)) < 0) |
1284 | return err; | 1264 | return err; |
1285 | pcm->private_data = chip; | 1265 | pcm->private_data = chip; |
@@ -1294,14 +1274,8 @@ int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, | |||
1294 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1274 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1295 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); | 1275 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); |
1296 | 1276 | ||
1297 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | 1277 | return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, |
1298 | surround_map, 2, 0, NULL); | 1278 | surround_map, 2, 0, NULL); |
1299 | if (err < 0) | ||
1300 | return err; | ||
1301 | |||
1302 | if (rpcm) | ||
1303 | *rpcm = pcm; | ||
1304 | return 0; | ||
1305 | } | 1279 | } |
1306 | 1280 | ||
1307 | static int snd_ymfpci_spdif_default_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1281 | static int snd_ymfpci_spdif_default_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
@@ -2272,8 +2246,7 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip) | |||
2272 | release_and_free_resource(chip->mpu_res); | 2246 | release_and_free_resource(chip->mpu_res); |
2273 | release_and_free_resource(chip->fm_res); | 2247 | release_and_free_resource(chip->fm_res); |
2274 | snd_ymfpci_free_gameport(chip); | 2248 | snd_ymfpci_free_gameport(chip); |
2275 | if (chip->reg_area_virt) | 2249 | iounmap(chip->reg_area_virt); |
2276 | iounmap(chip->reg_area_virt); | ||
2277 | if (chip->work_ptr.area) | 2250 | if (chip->work_ptr.area) |
2278 | snd_dma_free_pages(&chip->work_ptr); | 2251 | snd_dma_free_pages(&chip->work_ptr); |
2279 | 2252 | ||
@@ -2326,7 +2299,6 @@ static int saved_regs_index[] = { | |||
2326 | 2299 | ||
2327 | static int snd_ymfpci_suspend(struct device *dev) | 2300 | static int snd_ymfpci_suspend(struct device *dev) |
2328 | { | 2301 | { |
2329 | struct pci_dev *pci = to_pci_dev(dev); | ||
2330 | struct snd_card *card = dev_get_drvdata(dev); | 2302 | struct snd_card *card = dev_get_drvdata(dev); |
2331 | struct snd_ymfpci *chip = card->private_data; | 2303 | struct snd_ymfpci *chip = card->private_data; |
2332 | unsigned int i; | 2304 | unsigned int i; |
@@ -2347,9 +2319,6 @@ static int snd_ymfpci_suspend(struct device *dev) | |||
2347 | snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); | 2319 | snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); |
2348 | snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0); | 2320 | snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0); |
2349 | snd_ymfpci_disable_dsp(chip); | 2321 | snd_ymfpci_disable_dsp(chip); |
2350 | pci_disable_device(pci); | ||
2351 | pci_save_state(pci); | ||
2352 | pci_set_power_state(pci, PCI_D3hot); | ||
2353 | return 0; | 2322 | return 0; |
2354 | } | 2323 | } |
2355 | 2324 | ||
@@ -2360,14 +2329,6 @@ static int snd_ymfpci_resume(struct device *dev) | |||
2360 | struct snd_ymfpci *chip = card->private_data; | 2329 | struct snd_ymfpci *chip = card->private_data; |
2361 | unsigned int i; | 2330 | unsigned int i; |
2362 | 2331 | ||
2363 | pci_set_power_state(pci, PCI_D0); | ||
2364 | pci_restore_state(pci); | ||
2365 | if (pci_enable_device(pci) < 0) { | ||
2366 | dev_err(dev, "pci_enable_device failed, disabling device\n"); | ||
2367 | snd_card_disconnect(card); | ||
2368 | return -EIO; | ||
2369 | } | ||
2370 | pci_set_master(pci); | ||
2371 | snd_ymfpci_aclink_reset(pci); | 2332 | snd_ymfpci_aclink_reset(pci); |
2372 | snd_ymfpci_codec_ready(chip, 0); | 2333 | snd_ymfpci_codec_ready(chip, 0); |
2373 | snd_ymfpci_download_image(chip); | 2334 | snd_ymfpci_download_image(chip); |
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index 5fbf5db2543d..09da7b52bc2e 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c | |||
@@ -20,7 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | 22 | ||
23 | #include <asm/io.h> | 23 | #include <linux/io.h> |
24 | #include <asm/nvram.h> | 24 | #include <asm/nvram.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c index 0040f048221f..d3524f9fa05d 100644 --- a/sound/ppc/beep.c +++ b/sound/ppc/beep.c | |||
@@ -18,7 +18,7 @@ | |||
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 | 20 | ||
21 | #include <asm/io.h> | 21 | #include <linux/io.h> |
22 | #include <asm/irq.h> | 22 | #include <asm/irq.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c index cb4f0a5e984e..b86159e04493 100644 --- a/sound/ppc/burgundy.c +++ b/sound/ppc/burgundy.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <asm/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <sound/core.h> | 25 | #include <sound/core.h> |
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 5a13b22748b2..13146d701413 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c | |||
@@ -20,7 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | 22 | ||
23 | #include <asm/io.h> | 23 | #include <linux/io.h> |
24 | #include <asm/irq.h> | 24 | #include <asm/irq.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
@@ -867,16 +867,11 @@ static int snd_pmac_free(struct snd_pmac *chip) | |||
867 | snd_pmac_dbdma_free(chip, &chip->capture.cmd); | 867 | snd_pmac_dbdma_free(chip, &chip->capture.cmd); |
868 | snd_pmac_dbdma_free(chip, &chip->extra_dma); | 868 | snd_pmac_dbdma_free(chip, &chip->extra_dma); |
869 | snd_pmac_dbdma_free(chip, &emergency_dbdma); | 869 | snd_pmac_dbdma_free(chip, &emergency_dbdma); |
870 | if (chip->macio_base) | 870 | iounmap(chip->macio_base); |
871 | iounmap(chip->macio_base); | 871 | iounmap(chip->latch_base); |
872 | if (chip->latch_base) | 872 | iounmap(chip->awacs); |
873 | iounmap(chip->latch_base); | 873 | iounmap(chip->playback.dma); |
874 | if (chip->awacs) | 874 | iounmap(chip->capture.dma); |
875 | iounmap(chip->awacs); | ||
876 | if (chip->playback.dma) | ||
877 | iounmap(chip->playback.dma); | ||
878 | if (chip->capture.dma) | ||
879 | iounmap(chip->capture.dma); | ||
880 | 875 | ||
881 | if (chip->node) { | 876 | if (chip->node) { |
882 | int i; | 877 | int i; |
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 58f292a87f98..368242519279 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c | |||
@@ -1044,7 +1044,7 @@ static int snd_ps3_driver_probe(struct ps3_system_bus_device *dev) | |||
1044 | if (!the_card.null_buffer_start_vaddr) { | 1044 | if (!the_card.null_buffer_start_vaddr) { |
1045 | pr_info("%s: nullbuffer alloc failed\n", __func__); | 1045 | pr_info("%s: nullbuffer alloc failed\n", __func__); |
1046 | ret = -ENOMEM; | 1046 | ret = -ENOMEM; |
1047 | goto clean_preallocate; | 1047 | goto clean_card; |
1048 | } | 1048 | } |
1049 | pr_debug("%s: null vaddr=%p dma=%#llx\n", __func__, | 1049 | pr_debug("%s: null vaddr=%p dma=%#llx\n", __func__, |
1050 | the_card.null_buffer_start_vaddr, | 1050 | the_card.null_buffer_start_vaddr, |
@@ -1066,8 +1066,6 @@ clean_dma_map: | |||
1066 | PAGE_SIZE, | 1066 | PAGE_SIZE, |
1067 | the_card.null_buffer_start_vaddr, | 1067 | the_card.null_buffer_start_vaddr, |
1068 | the_card.null_buffer_start_dma_addr); | 1068 | the_card.null_buffer_start_dma_addr); |
1069 | clean_preallocate: | ||
1070 | snd_pcm_lib_preallocate_free_for_all(the_card.pcm); | ||
1071 | clean_card: | 1069 | clean_card: |
1072 | snd_card_free(the_card.card); | 1070 | snd_card_free(the_card.card); |
1073 | clean_irq: | 1071 | clean_irq: |
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 24c8766a925d..c8fafba218a5 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c | |||
@@ -32,8 +32,8 @@ | |||
32 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
33 | #include <linux/string.h> | 33 | #include <linux/string.h> |
34 | #include <linux/of_irq.h> | 34 | #include <linux/of_irq.h> |
35 | #include <linux/io.h> | ||
35 | #include <sound/core.h> | 36 | #include <sound/core.h> |
36 | #include <asm/io.h> | ||
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
38 | #include <asm/machdep.h> | 38 | #include <asm/machdep.h> |
39 | #include <asm/pmac_feature.h> | 39 | #include <asm/pmac_feature.h> |
diff --git a/sound/sh/aica.c b/sound/sh/aica.c index f44dda610ed2..ad3d9ae38034 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c | |||
@@ -35,12 +35,12 @@ | |||
35 | #include <linux/timer.h> | 35 | #include <linux/timer.h> |
36 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
37 | #include <linux/workqueue.h> | 37 | #include <linux/workqueue.h> |
38 | #include <linux/io.h> | ||
38 | #include <sound/core.h> | 39 | #include <sound/core.h> |
39 | #include <sound/control.h> | 40 | #include <sound/control.h> |
40 | #include <sound/pcm.h> | 41 | #include <sound/pcm.h> |
41 | #include <sound/initval.h> | 42 | #include <sound/initval.h> |
42 | #include <sound/info.h> | 43 | #include <sound/info.h> |
43 | #include <asm/io.h> | ||
44 | #include <asm/dma.h> | 44 | #include <asm/dma.h> |
45 | #include <mach/sysasic.h> | 45 | #include <mach/sysasic.h> |
46 | #include "aica.h" | 46 | #include "aica.h" |
@@ -343,11 +343,9 @@ static void spu_begin_dma(struct snd_pcm_substream *substream) | |||
343 | mod_timer(&dreamcastcard->timer, jiffies + 4); | 343 | mod_timer(&dreamcastcard->timer, jiffies + 4); |
344 | return; | 344 | return; |
345 | } | 345 | } |
346 | init_timer(&(dreamcastcard->timer)); | 346 | setup_timer(&dreamcastcard->timer, aica_period_elapsed, |
347 | dreamcastcard->timer.data = (unsigned long) substream; | 347 | (unsigned long) substream); |
348 | dreamcastcard->timer.function = aica_period_elapsed; | 348 | mod_timer(&dreamcastcard->timer, jiffies + 4); |
349 | dreamcastcard->timer.expires = jiffies + 4; | ||
350 | add_timer(&(dreamcastcard->timer)); | ||
351 | } | 349 | } |
352 | 350 | ||
353 | static int snd_aicapcm_pcm_open(struct snd_pcm_substream | 351 | static int snd_aicapcm_pcm_open(struct snd_pcm_substream |
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 7d5d6444a837..dcc79aa0236b 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -55,6 +55,7 @@ source "sound/soc/spear/Kconfig" | |||
55 | source "sound/soc/tegra/Kconfig" | 55 | source "sound/soc/tegra/Kconfig" |
56 | source "sound/soc/txx9/Kconfig" | 56 | source "sound/soc/txx9/Kconfig" |
57 | source "sound/soc/ux500/Kconfig" | 57 | source "sound/soc/ux500/Kconfig" |
58 | source "sound/soc/xtensa/Kconfig" | ||
58 | 59 | ||
59 | # Supported codecs | 60 | # Supported codecs |
60 | source "sound/soc/codecs/Kconfig" | 61 | source "sound/soc/codecs/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 865e090c8061..5b3c8f67c8db 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -36,3 +36,4 @@ obj-$(CONFIG_SND_SOC) += spear/ | |||
36 | obj-$(CONFIG_SND_SOC) += tegra/ | 36 | obj-$(CONFIG_SND_SOC) += tegra/ |
37 | obj-$(CONFIG_SND_SOC) += txx9/ | 37 | obj-$(CONFIG_SND_SOC) += txx9/ |
38 | obj-$(CONFIG_SND_SOC) += ux500/ | 38 | obj-$(CONFIG_SND_SOC) += ux500/ |
39 | obj-$(CONFIG_SND_SOC) += xtensa/ | ||
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index fb3878312bf8..1579e994acf8 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig | |||
@@ -45,7 +45,7 @@ config SND_ATMEL_SOC_WM8904 | |||
45 | 45 | ||
46 | config SND_AT91_SOC_SAM9X5_WM8731 | 46 | config SND_AT91_SOC_SAM9X5_WM8731 |
47 | tristate "SoC Audio support for WM8731-based at91sam9x5 board" | 47 | tristate "SoC Audio support for WM8731-based at91sam9x5 board" |
48 | depends on ATMEL_SSC && SND_ATMEL_SOC && SOC_AT91SAM9X5 | 48 | depends on ARCH_AT91 && ATMEL_SSC && SND_ATMEL_SOC |
49 | select SND_ATMEL_SOC_SSC | 49 | select SND_ATMEL_SOC_SSC |
50 | select SND_ATMEL_SOC_DMA | 50 | select SND_ATMEL_SOC_DMA |
51 | select SND_SOC_WM8731 | 51 | select SND_SOC_WM8731 |
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c index 33fb3bb133df..b8e7bad05eb1 100644 --- a/sound/soc/atmel/atmel-pcm-dma.c +++ b/sound/soc/atmel/atmel-pcm-dma.c | |||
@@ -105,13 +105,11 @@ static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream, | |||
105 | return ret; | 105 | return ret; |
106 | } | 106 | } |
107 | 107 | ||
108 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 108 | slave_config->dst_addr = ssc->phybase + SSC_THR; |
109 | slave_config->dst_addr = ssc->phybase + SSC_THR; | 109 | slave_config->dst_maxburst = 1; |
110 | slave_config->dst_maxburst = 1; | 110 | |
111 | } else { | 111 | slave_config->src_addr = ssc->phybase + SSC_RHR; |
112 | slave_config->src_addr = ssc->phybase + SSC_RHR; | 112 | slave_config->src_maxburst = 1; |
113 | slave_config->src_maxburst = 1; | ||
114 | } | ||
115 | 113 | ||
116 | prtd->dma_intr_handler = atmel_pcm_dma_irq; | 114 | prtd->dma_intr_handler = atmel_pcm_dma_irq; |
117 | 115 | ||
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 35e44e463cfe..fb0b7e8b08ff 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -204,6 +204,13 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream, | |||
204 | pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", | 204 | pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", |
205 | ssc_readl(ssc_p->ssc->regs, SR)); | 205 | ssc_readl(ssc_p->ssc->regs, SR)); |
206 | 206 | ||
207 | /* Enable PMC peripheral clock for this SSC */ | ||
208 | pr_debug("atmel_ssc_dai: Starting clock\n"); | ||
209 | clk_enable(ssc_p->ssc->clk); | ||
210 | |||
211 | /* Reset the SSC to keep it at a clean status */ | ||
212 | ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); | ||
213 | |||
207 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 214 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
208 | dir = 0; | 215 | dir = 0; |
209 | dir_mask = SSC_DIR_MASK_PLAYBACK; | 216 | dir_mask = SSC_DIR_MASK_PLAYBACK; |
@@ -250,11 +257,6 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, | |||
250 | dma_params = ssc_p->dma_params[dir]; | 257 | dma_params = ssc_p->dma_params[dir]; |
251 | 258 | ||
252 | if (dma_params != NULL) { | 259 | if (dma_params != NULL) { |
253 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable); | ||
254 | pr_debug("atmel_ssc_shutdown: %s disabled SSC_SR=0x%08x\n", | ||
255 | (dir ? "receive" : "transmit"), | ||
256 | ssc_readl(ssc_p->ssc->regs, SR)); | ||
257 | |||
258 | dma_params->ssc = NULL; | 260 | dma_params->ssc = NULL; |
259 | dma_params->substream = NULL; | 261 | dma_params->substream = NULL; |
260 | ssc_p->dma_params[dir] = NULL; | 262 | ssc_p->dma_params[dir] = NULL; |
@@ -266,10 +268,6 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, | |||
266 | ssc_p->dir_mask &= ~dir_mask; | 268 | ssc_p->dir_mask &= ~dir_mask; |
267 | if (!ssc_p->dir_mask) { | 269 | if (!ssc_p->dir_mask) { |
268 | if (ssc_p->initialized) { | 270 | if (ssc_p->initialized) { |
269 | /* Shutdown the SSC clock. */ | ||
270 | pr_debug("atmel_ssc_dai: Stopping clock\n"); | ||
271 | clk_disable(ssc_p->ssc->clk); | ||
272 | |||
273 | free_irq(ssc_p->ssc->irq, ssc_p); | 271 | free_irq(ssc_p->ssc->irq, ssc_p); |
274 | ssc_p->initialized = 0; | 272 | ssc_p->initialized = 0; |
275 | } | 273 | } |
@@ -280,6 +278,10 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, | |||
280 | ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0; | 278 | ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0; |
281 | } | 279 | } |
282 | spin_unlock_irq(&ssc_p->lock); | 280 | spin_unlock_irq(&ssc_p->lock); |
281 | |||
282 | /* Shutdown the SSC clock. */ | ||
283 | pr_debug("atmel_ssc_dai: Stopping clock\n"); | ||
284 | clk_disable(ssc_p->ssc->clk); | ||
283 | } | 285 | } |
284 | 286 | ||
285 | 287 | ||
@@ -450,13 +452,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
450 | break; | 452 | break; |
451 | 453 | ||
452 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: | 454 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: |
453 | /* | 455 | /* I2S format, CODEC supplies BCLK and LRC clocks. */ |
454 | * I2S format, CODEC supplies BCLK and LRC clocks. | ||
455 | * | ||
456 | * The SSC transmit clock is obtained from the BCLK signal on | ||
457 | * on the TK line, and the SSC receive clock is | ||
458 | * generated from the transmit clock. | ||
459 | */ | ||
460 | rcmr = SSC_BF(RCMR_PERIOD, 0) | 456 | rcmr = SSC_BF(RCMR_PERIOD, 0) |
461 | | SSC_BF(RCMR_STTDLY, START_DELAY) | 457 | | SSC_BF(RCMR_STTDLY, START_DELAY) |
462 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | 458 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) |
@@ -491,6 +487,54 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
491 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | 487 | | SSC_BF(TFMR_DATLEN, (bits - 1)); |
492 | break; | 488 | break; |
493 | 489 | ||
490 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFS: | ||
491 | /* I2S format, CODEC supplies BCLK, SSC supplies LRCLK. */ | ||
492 | if (bits > 16 && !ssc->pdata->has_fslen_ext) { | ||
493 | dev_err(dai->dev, | ||
494 | "sample size %d is too large for SSC device\n", | ||
495 | bits); | ||
496 | return -EINVAL; | ||
497 | } | ||
498 | |||
499 | fslen_ext = (bits - 1) / 16; | ||
500 | fslen = (bits - 1) % 16; | ||
501 | |||
502 | rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | ||
503 | | SSC_BF(RCMR_STTDLY, START_DELAY) | ||
504 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | ||
505 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
506 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
507 | | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? | ||
508 | SSC_CKS_PIN : SSC_CKS_CLOCK); | ||
509 | |||
510 | rfmr = SSC_BF(RFMR_FSLEN_EXT, fslen_ext) | ||
511 | | SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
512 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) | ||
513 | | SSC_BF(RFMR_FSLEN, fslen) | ||
514 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
515 | | SSC_BIT(RFMR_MSBF) | ||
516 | | SSC_BF(RFMR_LOOP, 0) | ||
517 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
518 | |||
519 | tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) | ||
520 | | SSC_BF(TCMR_STTDLY, START_DELAY) | ||
521 | | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | ||
522 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
523 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | ||
524 | | SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ? | ||
525 | SSC_CKS_CLOCK : SSC_CKS_PIN); | ||
526 | |||
527 | tfmr = SSC_BF(TFMR_FSLEN_EXT, fslen_ext) | ||
528 | | SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_NEGATIVE) | ||
529 | | SSC_BF(TFMR_FSDEN, 0) | ||
530 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) | ||
531 | | SSC_BF(TFMR_FSLEN, fslen) | ||
532 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
533 | | SSC_BIT(TFMR_MSBF) | ||
534 | | SSC_BF(TFMR_DATDEF, 0) | ||
535 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
536 | break; | ||
537 | |||
494 | case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: | 538 | case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: |
495 | /* | 539 | /* |
496 | * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. | 540 | * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. |
@@ -535,10 +579,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
535 | /* | 579 | /* |
536 | * DSP/PCM Mode A format, CODEC supplies BCLK and LRC clocks. | 580 | * DSP/PCM Mode A format, CODEC supplies BCLK and LRC clocks. |
537 | * | 581 | * |
538 | * The SSC transmit clock is obtained from the BCLK signal on | ||
539 | * on the TK line, and the SSC receive clock is | ||
540 | * generated from the transmit clock. | ||
541 | * | ||
542 | * Data is transferred on first BCLK after LRC pulse rising | 582 | * Data is transferred on first BCLK after LRC pulse rising |
543 | * edge.If stereo, the right channel data is contiguous with | 583 | * edge.If stereo, the right channel data is contiguous with |
544 | * the left channel data. | 584 | * the left channel data. |
@@ -587,23 +627,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | |||
587 | rcmr, rfmr, tcmr, tfmr); | 627 | rcmr, rfmr, tcmr, tfmr); |
588 | 628 | ||
589 | if (!ssc_p->initialized) { | 629 | if (!ssc_p->initialized) { |
590 | 630 | if (!ssc_p->ssc->pdata->use_dma) { | |
591 | /* Enable PMC peripheral clock for this SSC */ | 631 | ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0); |
592 | pr_debug("atmel_ssc_dai: Starting clock\n"); | 632 | ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0); |
593 | clk_enable(ssc_p->ssc->clk); | 633 | ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0); |
594 | 634 | ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0); | |
595 | /* Reset the SSC and its PDC registers */ | 635 | |
596 | ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); | 636 | ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0); |
597 | 637 | ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0); | |
598 | ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0); | 638 | ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0); |
599 | ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0); | 639 | ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0); |
600 | ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0); | 640 | } |
601 | ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0); | ||
602 | |||
603 | ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0); | ||
604 | ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0); | ||
605 | ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0); | ||
606 | ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0); | ||
607 | 641 | ||
608 | ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0, | 642 | ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0, |
609 | ssc_p->name, ssc_p); | 643 | ssc_p->name, ssc_p); |
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 66b66d0e7514..8de836165cf2 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c | |||
@@ -46,9 +46,6 @@ | |||
46 | #include <sound/pcm_params.h> | 46 | #include <sound/pcm_params.h> |
47 | #include <sound/soc.h> | 47 | #include <sound/soc.h> |
48 | 48 | ||
49 | #include <asm/mach-types.h> | ||
50 | #include <mach/hardware.h> | ||
51 | |||
52 | #include "../codecs/wm8731.h" | 49 | #include "../codecs/wm8731.h" |
53 | #include "atmel-pcm.h" | 50 | #include "atmel-pcm.h" |
54 | #include "atmel_ssc_dai.h" | 51 | #include "atmel_ssc_dai.h" |
@@ -64,33 +61,6 @@ | |||
64 | 61 | ||
65 | static struct clk *mclk; | 62 | static struct clk *mclk; |
66 | 63 | ||
67 | static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream, | ||
68 | struct snd_pcm_hw_params *params) | ||
69 | { | ||
70 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
71 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
72 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
73 | int ret; | ||
74 | |||
75 | /* set codec DAI configuration */ | ||
76 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
77 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
78 | if (ret < 0) | ||
79 | return ret; | ||
80 | |||
81 | /* set cpu DAI configuration */ | ||
82 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
83 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
84 | if (ret < 0) | ||
85 | return ret; | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static struct snd_soc_ops at91sam9g20ek_ops = { | ||
91 | .hw_params = at91sam9g20ek_hw_params, | ||
92 | }; | ||
93 | |||
94 | static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, | 64 | static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, |
95 | struct snd_soc_dapm_context *dapm, | 65 | struct snd_soc_dapm_context *dapm, |
96 | enum snd_soc_bias_level level) | 66 | enum snd_soc_bias_level level) |
@@ -173,7 +143,8 @@ static struct snd_soc_dai_link at91sam9g20ek_dai = { | |||
173 | .init = at91sam9g20ek_wm8731_init, | 143 | .init = at91sam9g20ek_wm8731_init, |
174 | .platform_name = "at91rm9200_ssc.0", | 144 | .platform_name = "at91rm9200_ssc.0", |
175 | .codec_name = "wm8731.0-001b", | 145 | .codec_name = "wm8731.0-001b", |
176 | .ops = &at91sam9g20ek_ops, | 146 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | |
147 | SND_SOC_DAIFMT_CBM_CFM, | ||
177 | }; | 148 | }; |
178 | 149 | ||
179 | static struct snd_soc_card snd_soc_at91sam9g20ek = { | 150 | static struct snd_soc_card snd_soc_at91sam9g20ek = { |
@@ -198,9 +169,7 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev) | |||
198 | int ret; | 169 | int ret; |
199 | 170 | ||
200 | if (!np) { | 171 | if (!np) { |
201 | if (!(machine_is_at91sam9g20ek() || | 172 | return -ENODEV; |
202 | machine_is_at91sam9g20ek_2mmc())) | ||
203 | return -ENODEV; | ||
204 | } | 173 | } |
205 | 174 | ||
206 | ret = atmel_ssc_set_audio(0); | 175 | ret = atmel_ssc_set_audio(0); |
@@ -237,39 +206,37 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev) | |||
237 | card->dev = &pdev->dev; | 206 | card->dev = &pdev->dev; |
238 | 207 | ||
239 | /* Parse device node info */ | 208 | /* Parse device node info */ |
240 | if (np) { | 209 | ret = snd_soc_of_parse_card_name(card, "atmel,model"); |
241 | ret = snd_soc_of_parse_card_name(card, "atmel,model"); | 210 | if (ret) |
242 | if (ret) | 211 | goto err; |
243 | goto err; | 212 | |
244 | 213 | ret = snd_soc_of_parse_audio_routing(card, | |
245 | ret = snd_soc_of_parse_audio_routing(card, | 214 | "atmel,audio-routing"); |
246 | "atmel,audio-routing"); | 215 | if (ret) |
247 | if (ret) | 216 | goto err; |
248 | goto err; | 217 | |
249 | 218 | /* Parse codec info */ | |
250 | /* Parse codec info */ | 219 | at91sam9g20ek_dai.codec_name = NULL; |
251 | at91sam9g20ek_dai.codec_name = NULL; | 220 | codec_np = of_parse_phandle(np, "atmel,audio-codec", 0); |
252 | codec_np = of_parse_phandle(np, "atmel,audio-codec", 0); | 221 | if (!codec_np) { |
253 | if (!codec_np) { | 222 | dev_err(&pdev->dev, "codec info missing\n"); |
254 | dev_err(&pdev->dev, "codec info missing\n"); | 223 | return -EINVAL; |
255 | return -EINVAL; | ||
256 | } | ||
257 | at91sam9g20ek_dai.codec_of_node = codec_np; | ||
258 | |||
259 | /* Parse dai and platform info */ | ||
260 | at91sam9g20ek_dai.cpu_dai_name = NULL; | ||
261 | at91sam9g20ek_dai.platform_name = NULL; | ||
262 | cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0); | ||
263 | if (!cpu_np) { | ||
264 | dev_err(&pdev->dev, "dai and pcm info missing\n"); | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | at91sam9g20ek_dai.cpu_of_node = cpu_np; | ||
268 | at91sam9g20ek_dai.platform_of_node = cpu_np; | ||
269 | |||
270 | of_node_put(codec_np); | ||
271 | of_node_put(cpu_np); | ||
272 | } | 224 | } |
225 | at91sam9g20ek_dai.codec_of_node = codec_np; | ||
226 | |||
227 | /* Parse dai and platform info */ | ||
228 | at91sam9g20ek_dai.cpu_dai_name = NULL; | ||
229 | at91sam9g20ek_dai.platform_name = NULL; | ||
230 | cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0); | ||
231 | if (!cpu_np) { | ||
232 | dev_err(&pdev->dev, "dai and pcm info missing\n"); | ||
233 | return -EINVAL; | ||
234 | } | ||
235 | at91sam9g20ek_dai.cpu_of_node = cpu_np; | ||
236 | at91sam9g20ek_dai.platform_of_node = cpu_np; | ||
237 | |||
238 | of_node_put(codec_np); | ||
239 | of_node_put(cpu_np); | ||
273 | 240 | ||
274 | ret = snd_soc_register_card(card); | 241 | ret = snd_soc_register_card(card); |
275 | if (ret) { | 242 | if (ret) { |
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index a747ac0b399f..c75995f2779c 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c | |||
@@ -91,27 +91,12 @@ static int db1200_i2s_startup(struct snd_pcm_substream *substream) | |||
91 | { | 91 | { |
92 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 92 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
93 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 93 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
94 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
95 | int ret; | ||
96 | 94 | ||
97 | /* WM8731 has its own 12MHz crystal */ | 95 | /* WM8731 has its own 12MHz crystal */ |
98 | snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, | 96 | snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, |
99 | 12000000, SND_SOC_CLOCK_IN); | 97 | 12000000, SND_SOC_CLOCK_IN); |
100 | 98 | ||
101 | /* codec is bitclock and lrclk master */ | 99 | return 0; |
102 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | | ||
103 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
104 | if (ret < 0) | ||
105 | goto out; | ||
106 | |||
107 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_LEFT_J | | ||
108 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
109 | if (ret < 0) | ||
110 | goto out; | ||
111 | |||
112 | ret = 0; | ||
113 | out: | ||
114 | return ret; | ||
115 | } | 100 | } |
116 | 101 | ||
117 | static struct snd_soc_ops db1200_i2s_wm8731_ops = { | 102 | static struct snd_soc_ops db1200_i2s_wm8731_ops = { |
@@ -125,6 +110,8 @@ static struct snd_soc_dai_link db1200_i2s_dai = { | |||
125 | .cpu_dai_name = "au1xpsc_i2s.1", | 110 | .cpu_dai_name = "au1xpsc_i2s.1", |
126 | .platform_name = "au1xpsc-pcm.1", | 111 | .platform_name = "au1xpsc-pcm.1", |
127 | .codec_name = "wm8731.0-001b", | 112 | .codec_name = "wm8731.0-001b", |
113 | .dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | | ||
114 | SND_SOC_DAIFMT_CBM_CFM, | ||
128 | .ops = &db1200_i2s_wm8731_ops, | 115 | .ops = &db1200_i2s_wm8731_ops, |
129 | }; | 116 | }; |
130 | 117 | ||
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index b06b8d8128c6..dd94fea72d5d 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c | |||
@@ -315,11 +315,6 @@ static struct snd_pcm_ops au1xpsc_pcm_ops = { | |||
315 | .pointer = au1xpsc_pcm_pointer, | 315 | .pointer = au1xpsc_pcm_pointer, |
316 | }; | 316 | }; |
317 | 317 | ||
318 | static void au1xpsc_pcm_free_dma_buffers(struct snd_pcm *pcm) | ||
319 | { | ||
320 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
321 | } | ||
322 | |||
323 | static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd) | 318 | static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd) |
324 | { | 319 | { |
325 | struct snd_card *card = rtd->card->snd_card; | 320 | struct snd_card *card = rtd->card->snd_card; |
@@ -335,7 +330,6 @@ static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
335 | static struct snd_soc_platform_driver au1xpsc_soc_platform = { | 330 | static struct snd_soc_platform_driver au1xpsc_soc_platform = { |
336 | .ops = &au1xpsc_pcm_ops, | 331 | .ops = &au1xpsc_pcm_ops, |
337 | .pcm_new = au1xpsc_pcm_new, | 332 | .pcm_new = au1xpsc_pcm_new, |
338 | .pcm_free = au1xpsc_pcm_free_dma_buffers, | ||
339 | }; | 333 | }; |
340 | 334 | ||
341 | static int au1xpsc_pcm_drvprobe(struct platform_device *pdev) | 335 | static int au1xpsc_pcm_drvprobe(struct platform_device *pdev) |
diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c index 6ffaaff469c7..24cc7f40d87a 100644 --- a/sound/soc/au1x/dma.c +++ b/sound/soc/au1x/dma.c | |||
@@ -287,11 +287,6 @@ static struct snd_pcm_ops alchemy_pcm_ops = { | |||
287 | .pointer = alchemy_pcm_pointer, | 287 | .pointer = alchemy_pcm_pointer, |
288 | }; | 288 | }; |
289 | 289 | ||
290 | static void alchemy_pcm_free_dma_buffers(struct snd_pcm *pcm) | ||
291 | { | ||
292 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
293 | } | ||
294 | |||
295 | static int alchemy_pcm_new(struct snd_soc_pcm_runtime *rtd) | 290 | static int alchemy_pcm_new(struct snd_soc_pcm_runtime *rtd) |
296 | { | 291 | { |
297 | struct snd_pcm *pcm = rtd->pcm; | 292 | struct snd_pcm *pcm = rtd->pcm; |
@@ -305,7 +300,6 @@ static int alchemy_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
305 | static struct snd_soc_platform_driver alchemy_pcm_soc_platform = { | 300 | static struct snd_soc_platform_driver alchemy_pcm_soc_platform = { |
306 | .ops = &alchemy_pcm_ops, | 301 | .ops = &alchemy_pcm_ops, |
307 | .pcm_new = alchemy_pcm_new, | 302 | .pcm_new = alchemy_pcm_new, |
308 | .pcm_free = alchemy_pcm_free_dma_buffers, | ||
309 | }; | 303 | }; |
310 | 304 | ||
311 | static int alchemy_pcm_drvprobe(struct platform_device *pdev) | 305 | static int alchemy_pcm_drvprobe(struct platform_device *pdev) |
diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 7b7fbcd49e5e..c7cd60f009e9 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig | |||
@@ -16,7 +16,7 @@ config SND_EP93XX_SOC_AC97 | |||
16 | 16 | ||
17 | config SND_EP93XX_SOC_SNAPPERCL15 | 17 | config SND_EP93XX_SOC_SNAPPERCL15 |
18 | tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" | 18 | tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" |
19 | depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 | 19 | depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 && I2C |
20 | select SND_EP93XX_SOC_I2S | 20 | select SND_EP93XX_SOC_I2S |
21 | select SND_SOC_TLV320AIC23_I2C | 21 | select SND_SOC_TLV320AIC23_I2C |
22 | help | 22 | help |
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index a2bf27f4baab..a0f265327fdf 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c | |||
@@ -386,7 +386,7 @@ static int snd_soc_put_volsw_2r_out(struct snd_kcontrol *kcontrol, | |||
386 | static int pm860x_rsync_event(struct snd_soc_dapm_widget *w, | 386 | static int pm860x_rsync_event(struct snd_soc_dapm_widget *w, |
387 | struct snd_kcontrol *kcontrol, int event) | 387 | struct snd_kcontrol *kcontrol, int event) |
388 | { | 388 | { |
389 | struct snd_soc_codec *codec = w->codec; | 389 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
390 | 390 | ||
391 | /* | 391 | /* |
392 | * In order to avoid current on the load, mute power-on and power-off | 392 | * In order to avoid current on the load, mute power-on and power-off |
@@ -403,7 +403,7 @@ static int pm860x_rsync_event(struct snd_soc_dapm_widget *w, | |||
403 | static int pm860x_dac_event(struct snd_soc_dapm_widget *w, | 403 | static int pm860x_dac_event(struct snd_soc_dapm_widget *w, |
404 | struct snd_kcontrol *kcontrol, int event) | 404 | struct snd_kcontrol *kcontrol, int event) |
405 | { | 405 | { |
406 | struct snd_soc_codec *codec = w->codec; | 406 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
407 | unsigned int dac = 0; | 407 | unsigned int dac = 0; |
408 | int data; | 408 | int data; |
409 | 409 | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 8349f982a586..ea9f0e31f9d4 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -69,6 +69,7 @@ config SND_SOC_ALL_CODECS | |||
69 | select SND_SOC_MAX98088 if I2C | 69 | select SND_SOC_MAX98088 if I2C |
70 | select SND_SOC_MAX98090 if I2C | 70 | select SND_SOC_MAX98090 if I2C |
71 | select SND_SOC_MAX98095 if I2C | 71 | select SND_SOC_MAX98095 if I2C |
72 | select SND_SOC_MAX98357A if GPIOLIB | ||
72 | select SND_SOC_MAX9850 if I2C | 73 | select SND_SOC_MAX9850 if I2C |
73 | select SND_SOC_MAX9768 if I2C | 74 | select SND_SOC_MAX9768 if I2C |
74 | select SND_SOC_MAX9877 if I2C | 75 | select SND_SOC_MAX9877 if I2C |
@@ -456,6 +457,9 @@ config SND_SOC_MAX98090 | |||
456 | config SND_SOC_MAX98095 | 457 | config SND_SOC_MAX98095 |
457 | tristate | 458 | tristate |
458 | 459 | ||
460 | config SND_SOC_MAX98357A | ||
461 | tristate | ||
462 | |||
459 | config SND_SOC_MAX9850 | 463 | config SND_SOC_MAX9850 |
460 | tristate | 464 | tristate |
461 | 465 | ||
@@ -525,7 +529,7 @@ config SND_SOC_RT5677 | |||
525 | 529 | ||
526 | config SND_SOC_RT5677_SPI | 530 | config SND_SOC_RT5677_SPI |
527 | tristate | 531 | tristate |
528 | default SND_SOC_RT5677 | 532 | default SND_SOC_RT5677 && SPI |
529 | 533 | ||
530 | #Freescale sgtl5000 codec | 534 | #Freescale sgtl5000 codec |
531 | config SND_SOC_SGTL5000 | 535 | config SND_SOC_SGTL5000 |
@@ -580,7 +584,9 @@ config SND_SOC_SSM4567 | |||
580 | depends on I2C | 584 | depends on I2C |
581 | 585 | ||
582 | config SND_SOC_STA32X | 586 | config SND_SOC_STA32X |
583 | tristate | 587 | tristate "STA326, STA328 and STA329 speaker amplifier" |
588 | depends on I2C | ||
589 | select REGMAP_I2C | ||
584 | 590 | ||
585 | config SND_SOC_STA350 | 591 | config SND_SOC_STA350 |
586 | tristate "STA350 speaker amplifier" | 592 | tristate "STA350 speaker amplifier" |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bbdfd1e1c182..69b8666d187a 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -64,6 +64,7 @@ snd-soc-max9768-objs := max9768.o | |||
64 | snd-soc-max98088-objs := max98088.o | 64 | snd-soc-max98088-objs := max98088.o |
65 | snd-soc-max98090-objs := max98090.o | 65 | snd-soc-max98090-objs := max98090.o |
66 | snd-soc-max98095-objs := max98095.o | 66 | snd-soc-max98095-objs := max98095.o |
67 | snd-soc-max98357a-objs := max98357a.o | ||
67 | snd-soc-max9850-objs := max9850.o | 68 | snd-soc-max9850-objs := max9850.o |
68 | snd-soc-mc13783-objs := mc13783.o | 69 | snd-soc-mc13783-objs := mc13783.o |
69 | snd-soc-ml26124-objs := ml26124.o | 70 | snd-soc-ml26124-objs := ml26124.o |
@@ -245,6 +246,7 @@ obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o | |||
245 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o | 246 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o |
246 | obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o | 247 | obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o |
247 | obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o | 248 | obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o |
249 | obj-$(CONFIG_SND_SOC_MAX98357A) += snd-soc-max98357a.o | ||
248 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o | 250 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o |
249 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o | 251 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o |
250 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o | 252 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 387530b0b0fd..17c953595660 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -333,8 +333,8 @@ static int ad193x_codec_probe(struct snd_soc_codec *codec) | |||
333 | regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0); | 333 | regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0); |
334 | /* de-emphasis: 48kHz, powedown dac */ | 334 | /* de-emphasis: 48kHz, powedown dac */ |
335 | regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A); | 335 | regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A); |
336 | /* powerdown dac, dac in tdm mode */ | 336 | /* dac in tdm mode */ |
337 | regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x41); | 337 | regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x40); |
338 | /* high-pass filter enable */ | 338 | /* high-pass filter enable */ |
339 | regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3); | 339 | regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3); |
340 | /* sata delay=1, adc aux mode */ | 340 | /* sata delay=1, adc aux mode */ |
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 686cacb0e835..632e89f793a7 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c | |||
@@ -163,7 +163,7 @@ static const struct snd_kcontrol_new ak4671_snd_controls[] = { | |||
163 | static int ak4671_out2_event(struct snd_soc_dapm_widget *w, | 163 | static int ak4671_out2_event(struct snd_soc_dapm_widget *w, |
164 | struct snd_kcontrol *kcontrol, int event) | 164 | struct snd_kcontrol *kcontrol, int event) |
165 | { | 165 | { |
166 | struct snd_soc_codec *codec = w->codec; | 166 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
167 | 167 | ||
168 | switch (event) { | 168 | switch (event) { |
169 | case SND_SOC_DAPM_POST_PMU: | 169 | case SND_SOC_DAPM_POST_PMU: |
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index bdf8c5ac8ca4..0e357996864b 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c | |||
@@ -55,18 +55,20 @@ static inline int alc5623_reset(struct snd_soc_codec *codec) | |||
55 | static int amp_mixer_event(struct snd_soc_dapm_widget *w, | 55 | static int amp_mixer_event(struct snd_soc_dapm_widget *w, |
56 | struct snd_kcontrol *kcontrol, int event) | 56 | struct snd_kcontrol *kcontrol, int event) |
57 | { | 57 | { |
58 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
59 | |||
58 | /* to power-on/off class-d amp generators/speaker */ | 60 | /* to power-on/off class-d amp generators/speaker */ |
59 | /* need to write to 'index-46h' register : */ | 61 | /* need to write to 'index-46h' register : */ |
60 | /* so write index num (here 0x46) to reg 0x6a */ | 62 | /* so write index num (here 0x46) to reg 0x6a */ |
61 | /* and then 0xffff/0 to reg 0x6c */ | 63 | /* and then 0xffff/0 to reg 0x6c */ |
62 | snd_soc_write(w->codec, ALC5623_HID_CTRL_INDEX, 0x46); | 64 | snd_soc_write(codec, ALC5623_HID_CTRL_INDEX, 0x46); |
63 | 65 | ||
64 | switch (event) { | 66 | switch (event) { |
65 | case SND_SOC_DAPM_PRE_PMU: | 67 | case SND_SOC_DAPM_PRE_PMU: |
66 | snd_soc_write(w->codec, ALC5623_HID_CTRL_DATA, 0xFFFF); | 68 | snd_soc_write(codec, ALC5623_HID_CTRL_DATA, 0xFFFF); |
67 | break; | 69 | break; |
68 | case SND_SOC_DAPM_POST_PMD: | 70 | case SND_SOC_DAPM_POST_PMD: |
69 | snd_soc_write(w->codec, ALC5623_HID_CTRL_DATA, 0); | 71 | snd_soc_write(codec, ALC5623_HID_CTRL_DATA, 0); |
70 | break; | 72 | break; |
71 | } | 73 | } |
72 | 74 | ||
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index d1fdbc266631..db3283abbe18 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c | |||
@@ -116,18 +116,20 @@ static inline int alc5632_reset(struct regmap *map) | |||
116 | static int amp_mixer_event(struct snd_soc_dapm_widget *w, | 116 | static int amp_mixer_event(struct snd_soc_dapm_widget *w, |
117 | struct snd_kcontrol *kcontrol, int event) | 117 | struct snd_kcontrol *kcontrol, int event) |
118 | { | 118 | { |
119 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
120 | |||
119 | /* to power-on/off class-d amp generators/speaker */ | 121 | /* to power-on/off class-d amp generators/speaker */ |
120 | /* need to write to 'index-46h' register : */ | 122 | /* need to write to 'index-46h' register : */ |
121 | /* so write index num (here 0x46) to reg 0x6a */ | 123 | /* so write index num (here 0x46) to reg 0x6a */ |
122 | /* and then 0xffff/0 to reg 0x6c */ | 124 | /* and then 0xffff/0 to reg 0x6c */ |
123 | snd_soc_write(w->codec, ALC5632_HID_CTRL_INDEX, 0x46); | 125 | snd_soc_write(codec, ALC5632_HID_CTRL_INDEX, 0x46); |
124 | 126 | ||
125 | switch (event) { | 127 | switch (event) { |
126 | case SND_SOC_DAPM_PRE_PMU: | 128 | case SND_SOC_DAPM_PRE_PMU: |
127 | snd_soc_write(w->codec, ALC5632_HID_CTRL_DATA, 0xFFFF); | 129 | snd_soc_write(codec, ALC5632_HID_CTRL_DATA, 0xFFFF); |
128 | break; | 130 | break; |
129 | case SND_SOC_DAPM_POST_PMD: | 131 | case SND_SOC_DAPM_POST_PMD: |
130 | snd_soc_write(w->codec, ALC5632_HID_CTRL_DATA, 0); | 132 | snd_soc_write(codec, ALC5632_HID_CTRL_DATA, 0); |
131 | break; | 133 | break; |
132 | } | 134 | } |
133 | 135 | ||
@@ -1066,7 +1068,7 @@ static int alc5632_probe(struct snd_soc_codec *codec) | |||
1066 | return 0; | 1068 | return 0; |
1067 | } | 1069 | } |
1068 | 1070 | ||
1069 | static struct snd_soc_codec_driver soc_codec_device_alc5632 = { | 1071 | static const struct snd_soc_codec_driver soc_codec_device_alc5632 = { |
1070 | .probe = alc5632_probe, | 1072 | .probe = alc5632_probe, |
1071 | .resume = alc5632_resume, | 1073 | .resume = alc5632_resume, |
1072 | .set_bias_level = alc5632_set_bias_level, | 1074 | .set_bias_level = alc5632_set_bias_level, |
@@ -1080,7 +1082,7 @@ static struct snd_soc_codec_driver soc_codec_device_alc5632 = { | |||
1080 | .num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes), | 1082 | .num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes), |
1081 | }; | 1083 | }; |
1082 | 1084 | ||
1083 | static struct regmap_config alc5632_regmap = { | 1085 | static const struct regmap_config alc5632_regmap = { |
1084 | .reg_bits = 8, | 1086 | .reg_bits = 8, |
1085 | .val_bits = 16, | 1087 | .val_bits = 16, |
1086 | 1088 | ||
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 9550d7433ad0..29202610dd0d 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -84,7 +84,7 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w, | |||
84 | struct snd_kcontrol *kcontrol, | 84 | struct snd_kcontrol *kcontrol, |
85 | int event) | 85 | int event) |
86 | { | 86 | { |
87 | struct snd_soc_codec *codec = w->codec; | 87 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
88 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 88 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
89 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | 89 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); |
90 | bool manual_ena = false; | 90 | bool manual_ena = false; |
@@ -692,7 +692,8 @@ static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena) | |||
692 | int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, | 692 | int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, |
693 | int event) | 693 | int event) |
694 | { | 694 | { |
695 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec); | 695 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
696 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
696 | unsigned int reg; | 697 | unsigned int reg; |
697 | 698 | ||
698 | if (w->shift % 2) | 699 | if (w->shift % 2) |
@@ -705,25 +706,25 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, | |||
705 | priv->in_pending++; | 706 | priv->in_pending++; |
706 | break; | 707 | break; |
707 | case SND_SOC_DAPM_POST_PMU: | 708 | case SND_SOC_DAPM_POST_PMU: |
708 | snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0); | 709 | snd_soc_update_bits(codec, reg, ARIZONA_IN1L_MUTE, 0); |
709 | 710 | ||
710 | /* If this is the last input pending then allow VU */ | 711 | /* If this is the last input pending then allow VU */ |
711 | priv->in_pending--; | 712 | priv->in_pending--; |
712 | if (priv->in_pending == 0) { | 713 | if (priv->in_pending == 0) { |
713 | msleep(1); | 714 | msleep(1); |
714 | arizona_in_set_vu(w->codec, 1); | 715 | arizona_in_set_vu(codec, 1); |
715 | } | 716 | } |
716 | break; | 717 | break; |
717 | case SND_SOC_DAPM_PRE_PMD: | 718 | case SND_SOC_DAPM_PRE_PMD: |
718 | snd_soc_update_bits(w->codec, reg, | 719 | snd_soc_update_bits(codec, reg, |
719 | ARIZONA_IN1L_MUTE | ARIZONA_IN_VU, | 720 | ARIZONA_IN1L_MUTE | ARIZONA_IN_VU, |
720 | ARIZONA_IN1L_MUTE | ARIZONA_IN_VU); | 721 | ARIZONA_IN1L_MUTE | ARIZONA_IN_VU); |
721 | break; | 722 | break; |
722 | case SND_SOC_DAPM_POST_PMD: | 723 | case SND_SOC_DAPM_POST_PMD: |
723 | /* Disable volume updates if no inputs are enabled */ | 724 | /* Disable volume updates if no inputs are enabled */ |
724 | reg = snd_soc_read(w->codec, ARIZONA_INPUT_ENABLES); | 725 | reg = snd_soc_read(codec, ARIZONA_INPUT_ENABLES); |
725 | if (reg == 0) | 726 | if (reg == 0) |
726 | arizona_in_set_vu(w->codec, 0); | 727 | arizona_in_set_vu(codec, 0); |
727 | } | 728 | } |
728 | 729 | ||
729 | return 0; | 730 | return 0; |
@@ -734,7 +735,25 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, | |||
734 | struct snd_kcontrol *kcontrol, | 735 | struct snd_kcontrol *kcontrol, |
735 | int event) | 736 | int event) |
736 | { | 737 | { |
738 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
739 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
740 | |||
737 | switch (event) { | 741 | switch (event) { |
742 | case SND_SOC_DAPM_PRE_PMU: | ||
743 | switch (w->shift) { | ||
744 | case ARIZONA_OUT1L_ENA_SHIFT: | ||
745 | case ARIZONA_OUT1R_ENA_SHIFT: | ||
746 | case ARIZONA_OUT2L_ENA_SHIFT: | ||
747 | case ARIZONA_OUT2R_ENA_SHIFT: | ||
748 | case ARIZONA_OUT3L_ENA_SHIFT: | ||
749 | case ARIZONA_OUT3R_ENA_SHIFT: | ||
750 | priv->out_up_pending++; | ||
751 | priv->out_up_delay += 17; | ||
752 | break; | ||
753 | default: | ||
754 | break; | ||
755 | } | ||
756 | break; | ||
738 | case SND_SOC_DAPM_POST_PMU: | 757 | case SND_SOC_DAPM_POST_PMU: |
739 | switch (w->shift) { | 758 | switch (w->shift) { |
740 | case ARIZONA_OUT1L_ENA_SHIFT: | 759 | case ARIZONA_OUT1L_ENA_SHIFT: |
@@ -743,13 +762,50 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, | |||
743 | case ARIZONA_OUT2R_ENA_SHIFT: | 762 | case ARIZONA_OUT2R_ENA_SHIFT: |
744 | case ARIZONA_OUT3L_ENA_SHIFT: | 763 | case ARIZONA_OUT3L_ENA_SHIFT: |
745 | case ARIZONA_OUT3R_ENA_SHIFT: | 764 | case ARIZONA_OUT3R_ENA_SHIFT: |
746 | msleep(17); | 765 | priv->out_up_pending--; |
766 | if (!priv->out_up_pending) { | ||
767 | msleep(priv->out_up_delay); | ||
768 | priv->out_up_delay = 0; | ||
769 | } | ||
747 | break; | 770 | break; |
748 | 771 | ||
749 | default: | 772 | default: |
750 | break; | 773 | break; |
751 | } | 774 | } |
752 | break; | 775 | break; |
776 | case SND_SOC_DAPM_PRE_PMD: | ||
777 | switch (w->shift) { | ||
778 | case ARIZONA_OUT1L_ENA_SHIFT: | ||
779 | case ARIZONA_OUT1R_ENA_SHIFT: | ||
780 | case ARIZONA_OUT2L_ENA_SHIFT: | ||
781 | case ARIZONA_OUT2R_ENA_SHIFT: | ||
782 | case ARIZONA_OUT3L_ENA_SHIFT: | ||
783 | case ARIZONA_OUT3R_ENA_SHIFT: | ||
784 | priv->out_down_pending++; | ||
785 | priv->out_down_delay++; | ||
786 | break; | ||
787 | default: | ||
788 | break; | ||
789 | } | ||
790 | break; | ||
791 | case SND_SOC_DAPM_POST_PMD: | ||
792 | switch (w->shift) { | ||
793 | case ARIZONA_OUT1L_ENA_SHIFT: | ||
794 | case ARIZONA_OUT1R_ENA_SHIFT: | ||
795 | case ARIZONA_OUT2L_ENA_SHIFT: | ||
796 | case ARIZONA_OUT2R_ENA_SHIFT: | ||
797 | case ARIZONA_OUT3L_ENA_SHIFT: | ||
798 | case ARIZONA_OUT3R_ENA_SHIFT: | ||
799 | priv->out_down_pending--; | ||
800 | if (!priv->out_down_pending) { | ||
801 | msleep(priv->out_down_delay); | ||
802 | priv->out_down_delay = 0; | ||
803 | } | ||
804 | break; | ||
805 | default: | ||
806 | break; | ||
807 | } | ||
808 | break; | ||
753 | } | 809 | } |
754 | 810 | ||
755 | return 0; | 811 | return 0; |
@@ -760,7 +816,8 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w, | |||
760 | struct snd_kcontrol *kcontrol, | 816 | struct snd_kcontrol *kcontrol, |
761 | int event) | 817 | int event) |
762 | { | 818 | { |
763 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec); | 819 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
820 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
764 | struct arizona *arizona = priv->arizona; | 821 | struct arizona *arizona = priv->arizona; |
765 | unsigned int mask = 1 << w->shift; | 822 | unsigned int mask = 1 << w->shift; |
766 | unsigned int val; | 823 | unsigned int val; |
@@ -772,6 +829,9 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w, | |||
772 | case SND_SOC_DAPM_PRE_PMD: | 829 | case SND_SOC_DAPM_PRE_PMD: |
773 | val = 0; | 830 | val = 0; |
774 | break; | 831 | break; |
832 | case SND_SOC_DAPM_PRE_PMU: | ||
833 | case SND_SOC_DAPM_POST_PMD: | ||
834 | return arizona_out_ev(w, kcontrol, event); | ||
775 | default: | 835 | default: |
776 | return -EINVAL; | 836 | return -EINVAL; |
777 | } | 837 | } |
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 942cfb197b6d..11ff899b0272 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
@@ -77,6 +77,11 @@ struct arizona_priv { | |||
77 | int num_inputs; | 77 | int num_inputs; |
78 | unsigned int in_pending; | 78 | unsigned int in_pending; |
79 | 79 | ||
80 | unsigned int out_up_pending; | ||
81 | unsigned int out_up_delay; | ||
82 | unsigned int out_down_pending; | ||
83 | unsigned int out_down_delay; | ||
84 | |||
80 | unsigned int spk_ena:2; | 85 | unsigned int spk_ena:2; |
81 | unsigned int spk_ena_pending:1; | 86 | unsigned int spk_ena_pending:1; |
82 | }; | 87 | }; |
diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c index 5075bf0a7276..e7238b8904bc 100644 --- a/sound/soc/codecs/bt-sco.c +++ b/sound/soc/codecs/bt-sco.c | |||
@@ -86,5 +86,5 @@ static struct platform_driver bt_sco_driver = { | |||
86 | module_platform_driver(bt_sco_driver); | 86 | module_platform_driver(bt_sco_driver); |
87 | 87 | ||
88 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 88 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
89 | MODULE_DESCRIPTION("ASoC generic bluethooth sco link driver"); | 89 | MODULE_DESCRIPTION("ASoC generic bluetooth sco link driver"); |
90 | MODULE_LICENSE("GPL"); | 90 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index ec55c590afd0..f2b8aad21274 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c | |||
@@ -264,7 +264,7 @@ static int cs35l32_codec_set_sysclk(struct snd_soc_codec *codec, | |||
264 | CS35L32_MCLK_DIV2_MASK | CS35L32_MCLK_RATIO_MASK, val); | 264 | CS35L32_MCLK_DIV2_MASK | CS35L32_MCLK_RATIO_MASK, val); |
265 | } | 265 | } |
266 | 266 | ||
267 | static struct snd_soc_codec_driver soc_codec_dev_cs35l32 = { | 267 | static const struct snd_soc_codec_driver soc_codec_dev_cs35l32 = { |
268 | .set_sysclk = cs35l32_codec_set_sysclk, | 268 | .set_sysclk = cs35l32_codec_set_sysclk, |
269 | 269 | ||
270 | .dapm_widgets = cs35l32_dapm_widgets, | 270 | .dapm_widgets = cs35l32_dapm_widgets, |
@@ -288,7 +288,7 @@ static const struct reg_default cs35l32_monitor_patch[] = { | |||
288 | { 0x00, 0x00 }, | 288 | { 0x00, 0x00 }, |
289 | }; | 289 | }; |
290 | 290 | ||
291 | static struct regmap_config cs35l32_regmap = { | 291 | static const struct regmap_config cs35l32_regmap = { |
292 | .reg_bits = 8, | 292 | .reg_bits = 8, |
293 | .val_bits = 8, | 293 | .val_bits = 8, |
294 | 294 | ||
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 35fbef743fbe..1589e7a881d8 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -1103,7 +1103,7 @@ static int cs42l52_remove(struct snd_soc_codec *codec) | |||
1103 | return 0; | 1103 | return 0; |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | static struct snd_soc_codec_driver soc_codec_dev_cs42l52 = { | 1106 | static const struct snd_soc_codec_driver soc_codec_dev_cs42l52 = { |
1107 | .probe = cs42l52_probe, | 1107 | .probe = cs42l52_probe, |
1108 | .remove = cs42l52_remove, | 1108 | .remove = cs42l52_remove, |
1109 | .set_bias_level = cs42l52_set_bias_level, | 1109 | .set_bias_level = cs42l52_set_bias_level, |
@@ -1130,7 +1130,7 @@ static const struct reg_default cs42l52_threshold_patch[] = { | |||
1130 | 1130 | ||
1131 | }; | 1131 | }; |
1132 | 1132 | ||
1133 | static struct regmap_config cs42l52_regmap = { | 1133 | static const struct regmap_config cs42l52_regmap = { |
1134 | .reg_bits = 8, | 1134 | .reg_bits = 8, |
1135 | .val_bits = 8, | 1135 | .val_bits = 8, |
1136 | 1136 | ||
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index 2ddc7ac10ad7..cbc654fe48c7 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c | |||
@@ -1164,7 +1164,7 @@ static int cs42l56_remove(struct snd_soc_codec *codec) | |||
1164 | return 0; | 1164 | return 0; |
1165 | } | 1165 | } |
1166 | 1166 | ||
1167 | static struct snd_soc_codec_driver soc_codec_dev_cs42l56 = { | 1167 | static const struct snd_soc_codec_driver soc_codec_dev_cs42l56 = { |
1168 | .probe = cs42l56_probe, | 1168 | .probe = cs42l56_probe, |
1169 | .remove = cs42l56_remove, | 1169 | .remove = cs42l56_remove, |
1170 | .set_bias_level = cs42l56_set_bias_level, | 1170 | .set_bias_level = cs42l56_set_bias_level, |
@@ -1179,7 +1179,7 @@ static struct snd_soc_codec_driver soc_codec_dev_cs42l56 = { | |||
1179 | .num_controls = ARRAY_SIZE(cs42l56_snd_controls), | 1179 | .num_controls = ARRAY_SIZE(cs42l56_snd_controls), |
1180 | }; | 1180 | }; |
1181 | 1181 | ||
1182 | static struct regmap_config cs42l56_regmap = { | 1182 | static const struct regmap_config cs42l56_regmap = { |
1183 | .reg_bits = 8, | 1183 | .reg_bits = 8, |
1184 | .val_bits = 8, | 1184 | .val_bits = 8, |
1185 | 1185 | ||
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 7c55537c69cf..8ecedba79606 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -1347,7 +1347,7 @@ static int cs42l73_probe(struct snd_soc_codec *codec) | |||
1347 | return 0; | 1347 | return 0; |
1348 | } | 1348 | } |
1349 | 1349 | ||
1350 | static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = { | 1350 | static const struct snd_soc_codec_driver soc_codec_dev_cs42l73 = { |
1351 | .probe = cs42l73_probe, | 1351 | .probe = cs42l73_probe, |
1352 | .set_bias_level = cs42l73_set_bias_level, | 1352 | .set_bias_level = cs42l73_set_bias_level, |
1353 | .suspend_bias_off = true, | 1353 | .suspend_bias_off = true, |
@@ -1361,7 +1361,7 @@ static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = { | |||
1361 | .num_controls = ARRAY_SIZE(cs42l73_snd_controls), | 1361 | .num_controls = ARRAY_SIZE(cs42l73_snd_controls), |
1362 | }; | 1362 | }; |
1363 | 1363 | ||
1364 | static struct regmap_config cs42l73_regmap = { | 1364 | static const struct regmap_config cs42l73_regmap = { |
1365 | .reg_bits = 8, | 1365 | .reg_bits = 8, |
1366 | .val_bits = 8, | 1366 | .val_bits = 8, |
1367 | 1367 | ||
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 61b2f9a2eef1..ffe96175a8a5 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c | |||
@@ -609,7 +609,7 @@ static const struct snd_kcontrol_new da732x_snd_controls[] = { | |||
609 | static int da732x_adc_event(struct snd_soc_dapm_widget *w, | 609 | static int da732x_adc_event(struct snd_soc_dapm_widget *w, |
610 | struct snd_kcontrol *kcontrol, int event) | 610 | struct snd_kcontrol *kcontrol, int event) |
611 | { | 611 | { |
612 | struct snd_soc_codec *codec = w->codec; | 612 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
613 | 613 | ||
614 | switch (event) { | 614 | switch (event) { |
615 | case SND_SOC_DAPM_POST_PMU: | 615 | case SND_SOC_DAPM_POST_PMU: |
@@ -663,7 +663,7 @@ static int da732x_adc_event(struct snd_soc_dapm_widget *w, | |||
663 | static int da732x_out_pga_event(struct snd_soc_dapm_widget *w, | 663 | static int da732x_out_pga_event(struct snd_soc_dapm_widget *w, |
664 | struct snd_kcontrol *kcontrol, int event) | 664 | struct snd_kcontrol *kcontrol, int event) |
665 | { | 665 | { |
666 | struct snd_soc_codec *codec = w->codec; | 666 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
667 | 667 | ||
668 | switch (event) { | 668 | switch (event) { |
669 | case SND_SOC_DAPM_POST_PMU: | 669 | case SND_SOC_DAPM_POST_PMU: |
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c new file mode 100644 index 000000000000..e9e6efbc21dd --- /dev/null +++ b/sound/soc/codecs/max98357a.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * max98357a.c -- MAX98357A ALSA SoC Codec driver | ||
13 | */ | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/gpio.h> | ||
18 | #include <linux/gpio/consumer.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/mod_devicetable.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/soc-dai.h> | ||
27 | #include <sound/soc-dapm.h> | ||
28 | |||
29 | #define DRV_NAME "max98357a" | ||
30 | |||
31 | static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, | ||
32 | int cmd, struct snd_soc_dai *dai) | ||
33 | { | ||
34 | struct gpio_desc *sdmode = snd_soc_dai_get_drvdata(dai); | ||
35 | |||
36 | switch (cmd) { | ||
37 | case SNDRV_PCM_TRIGGER_START: | ||
38 | case SNDRV_PCM_TRIGGER_RESUME: | ||
39 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
40 | gpiod_set_value(sdmode, 1); | ||
41 | break; | ||
42 | case SNDRV_PCM_TRIGGER_STOP: | ||
43 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
44 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
45 | gpiod_set_value(sdmode, 0); | ||
46 | break; | ||
47 | } | ||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static const struct snd_soc_dapm_widget max98357a_dapm_widgets[] = { | ||
53 | SND_SOC_DAPM_DAC("SDMode", NULL, SND_SOC_NOPM, 0, 0), | ||
54 | SND_SOC_DAPM_OUTPUT("Speaker"), | ||
55 | }; | ||
56 | |||
57 | static const struct snd_soc_dapm_route max98357a_dapm_routes[] = { | ||
58 | {"Speaker", NULL, "SDMode"}, | ||
59 | }; | ||
60 | |||
61 | static int max98357a_codec_probe(struct snd_soc_codec *codec) | ||
62 | { | ||
63 | struct gpio_desc *sdmode; | ||
64 | |||
65 | sdmode = devm_gpiod_get(codec->dev, "sdmode"); | ||
66 | if (IS_ERR(sdmode)) { | ||
67 | dev_err(codec->dev, "%s() unable to get sdmode GPIO: %ld\n", | ||
68 | __func__, PTR_ERR(sdmode)); | ||
69 | return PTR_ERR(sdmode); | ||
70 | } | ||
71 | gpiod_direction_output(sdmode, 0); | ||
72 | snd_soc_codec_set_drvdata(codec, sdmode); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static struct snd_soc_codec_driver max98357a_codec_driver = { | ||
78 | .probe = max98357a_codec_probe, | ||
79 | .dapm_widgets = max98357a_dapm_widgets, | ||
80 | .num_dapm_widgets = ARRAY_SIZE(max98357a_dapm_widgets), | ||
81 | .dapm_routes = max98357a_dapm_routes, | ||
82 | .num_dapm_routes = ARRAY_SIZE(max98357a_dapm_routes), | ||
83 | }; | ||
84 | |||
85 | static struct snd_soc_dai_ops max98357a_dai_ops = { | ||
86 | .trigger = max98357a_daiops_trigger, | ||
87 | }; | ||
88 | |||
89 | static struct snd_soc_dai_driver max98357a_dai_driver = { | ||
90 | .name = DRV_NAME, | ||
91 | .playback = { | ||
92 | .stream_name = DRV_NAME "-playback", | ||
93 | .formats = SNDRV_PCM_FMTBIT_S16 | | ||
94 | SNDRV_PCM_FMTBIT_S24 | | ||
95 | SNDRV_PCM_FMTBIT_S32, | ||
96 | .rates = SNDRV_PCM_RATE_8000 | | ||
97 | SNDRV_PCM_RATE_16000 | | ||
98 | SNDRV_PCM_RATE_48000 | | ||
99 | SNDRV_PCM_RATE_96000, | ||
100 | .rate_min = 8000, | ||
101 | .rate_max = 96000, | ||
102 | .channels_min = 1, | ||
103 | .channels_max = 2, | ||
104 | }, | ||
105 | .ops = &max98357a_dai_ops, | ||
106 | }; | ||
107 | |||
108 | static int max98357a_platform_probe(struct platform_device *pdev) | ||
109 | { | ||
110 | int ret; | ||
111 | |||
112 | ret = snd_soc_register_codec(&pdev->dev, &max98357a_codec_driver, | ||
113 | &max98357a_dai_driver, 1); | ||
114 | if (ret) | ||
115 | dev_err(&pdev->dev, "%s() error registering codec driver: %d\n", | ||
116 | __func__, ret); | ||
117 | |||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static int max98357a_platform_remove(struct platform_device *pdev) | ||
122 | { | ||
123 | snd_soc_unregister_codec(&pdev->dev); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | #ifdef CONFIG_OF | ||
129 | static const struct of_device_id max98357a_device_id[] = { | ||
130 | { .compatible = "maxim," DRV_NAME, }, | ||
131 | {} | ||
132 | }; | ||
133 | MODULE_DEVICE_TABLE(of, max98357a_device_id); | ||
134 | #endif | ||
135 | |||
136 | static struct platform_driver max98357a_platform_driver = { | ||
137 | .driver = { | ||
138 | .name = DRV_NAME, | ||
139 | .of_match_table = of_match_ptr(max98357a_device_id), | ||
140 | }, | ||
141 | .probe = max98357a_platform_probe, | ||
142 | .remove = max98357a_platform_remove, | ||
143 | }; | ||
144 | module_platform_driver(max98357a_platform_driver); | ||
145 | |||
146 | MODULE_DESCRIPTION("Maxim MAX98357A Codec Driver"); | ||
147 | MODULE_LICENSE("GPL v2"); | ||
148 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index c1e441c2c8af..2ffb9a0570dc 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c | |||
@@ -328,16 +328,16 @@ static int mc13783_set_tdm_slot_dac(struct snd_soc_dai *dai, | |||
328 | } | 328 | } |
329 | 329 | ||
330 | switch (rx_mask) { | 330 | switch (rx_mask) { |
331 | case 0xfffffffc: | 331 | case 0x03: |
332 | val |= SSI_NETWORK_DAC_RXSLOT_0_1; | 332 | val |= SSI_NETWORK_DAC_RXSLOT_0_1; |
333 | break; | 333 | break; |
334 | case 0xfffffff3: | 334 | case 0x0c: |
335 | val |= SSI_NETWORK_DAC_RXSLOT_2_3; | 335 | val |= SSI_NETWORK_DAC_RXSLOT_2_3; |
336 | break; | 336 | break; |
337 | case 0xffffffcf: | 337 | case 0x30: |
338 | val |= SSI_NETWORK_DAC_RXSLOT_4_5; | 338 | val |= SSI_NETWORK_DAC_RXSLOT_4_5; |
339 | break; | 339 | break; |
340 | case 0xffffff3f: | 340 | case 0xc0: |
341 | val |= SSI_NETWORK_DAC_RXSLOT_6_7; | 341 | val |= SSI_NETWORK_DAC_RXSLOT_6_7; |
342 | break; | 342 | break; |
343 | default: | 343 | default: |
@@ -360,7 +360,7 @@ static int mc13783_set_tdm_slot_codec(struct snd_soc_dai *dai, | |||
360 | if (slots != 4) | 360 | if (slots != 4) |
361 | return -EINVAL; | 361 | return -EINVAL; |
362 | 362 | ||
363 | if (tx_mask != 0xfffffffc) | 363 | if (tx_mask != 0x3) |
364 | return -EINVAL; | 364 | return -EINVAL; |
365 | 365 | ||
366 | val |= (0x00 << 2); /* primary timeslot RX/TX(?) is 0 */ | 366 | val |= (0x00 << 2); /* primary timeslot RX/TX(?) is 0 */ |
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 7e73fa4b3183..8fb445f33f6f 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c | |||
@@ -32,7 +32,7 @@ static int pcm3008_dac_ev(struct snd_soc_dapm_widget *w, | |||
32 | struct snd_kcontrol *kcontrol, | 32 | struct snd_kcontrol *kcontrol, |
33 | int event) | 33 | int event) |
34 | { | 34 | { |
35 | struct snd_soc_codec *codec = w->codec; | 35 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
36 | struct pcm3008_setup_data *setup = codec->dev->platform_data; | 36 | struct pcm3008_setup_data *setup = codec->dev->platform_data; |
37 | 37 | ||
38 | gpio_set_value_cansleep(setup->pdda_pin, | 38 | gpio_set_value_cansleep(setup->pdda_pin, |
@@ -45,7 +45,7 @@ static int pcm3008_adc_ev(struct snd_soc_dapm_widget *w, | |||
45 | struct snd_kcontrol *kcontrol, | 45 | struct snd_kcontrol *kcontrol, |
46 | int event) | 46 | int event) |
47 | { | 47 | { |
48 | struct snd_soc_codec *codec = w->codec; | 48 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
49 | struct pcm3008_setup_data *setup = codec->dev->platform_data; | 49 | struct pcm3008_setup_data *setup = codec->dev->platform_data; |
50 | 50 | ||
51 | gpio_set_value_cansleep(setup->pdad_pin, | 51 | gpio_set_value_cansleep(setup->pdad_pin, |
diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c index d0547fa275fc..dcdfac0ffeb1 100644 --- a/sound/soc/codecs/pcm512x-i2c.c +++ b/sound/soc/codecs/pcm512x-i2c.c | |||
@@ -46,6 +46,8 @@ static int pcm512x_i2c_remove(struct i2c_client *i2c) | |||
46 | static const struct i2c_device_id pcm512x_i2c_id[] = { | 46 | static const struct i2c_device_id pcm512x_i2c_id[] = { |
47 | { "pcm5121", }, | 47 | { "pcm5121", }, |
48 | { "pcm5122", }, | 48 | { "pcm5122", }, |
49 | { "pcm5141", }, | ||
50 | { "pcm5142", }, | ||
49 | { } | 51 | { } |
50 | }; | 52 | }; |
51 | MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); | 53 | MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); |
@@ -53,6 +55,8 @@ MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); | |||
53 | static const struct of_device_id pcm512x_of_match[] = { | 55 | static const struct of_device_id pcm512x_of_match[] = { |
54 | { .compatible = "ti,pcm5121", }, | 56 | { .compatible = "ti,pcm5121", }, |
55 | { .compatible = "ti,pcm5122", }, | 57 | { .compatible = "ti,pcm5122", }, |
58 | { .compatible = "ti,pcm5141", }, | ||
59 | { .compatible = "ti,pcm5142", }, | ||
56 | { } | 60 | { } |
57 | }; | 61 | }; |
58 | MODULE_DEVICE_TABLE(of, pcm512x_of_match); | 62 | MODULE_DEVICE_TABLE(of, pcm512x_of_match); |
diff --git a/sound/soc/codecs/pcm512x-spi.c b/sound/soc/codecs/pcm512x-spi.c index f297058c0038..7b64a9cef704 100644 --- a/sound/soc/codecs/pcm512x-spi.c +++ b/sound/soc/codecs/pcm512x-spi.c | |||
@@ -43,6 +43,8 @@ static int pcm512x_spi_remove(struct spi_device *spi) | |||
43 | static const struct spi_device_id pcm512x_spi_id[] = { | 43 | static const struct spi_device_id pcm512x_spi_id[] = { |
44 | { "pcm5121", }, | 44 | { "pcm5121", }, |
45 | { "pcm5122", }, | 45 | { "pcm5122", }, |
46 | { "pcm5141", }, | ||
47 | { "pcm5142", }, | ||
46 | { }, | 48 | { }, |
47 | }; | 49 | }; |
48 | MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); | 50 | MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); |
@@ -50,6 +52,8 @@ MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); | |||
50 | static const struct of_device_id pcm512x_of_match[] = { | 52 | static const struct of_device_id pcm512x_of_match[] = { |
51 | { .compatible = "ti,pcm5121", }, | 53 | { .compatible = "ti,pcm5121", }, |
52 | { .compatible = "ti,pcm5122", }, | 54 | { .compatible = "ti,pcm5122", }, |
55 | { .compatible = "ti,pcm5141", }, | ||
56 | { .compatible = "ti,pcm5142", }, | ||
53 | { } | 57 | { } |
54 | }; | 58 | }; |
55 | MODULE_DEVICE_TABLE(of, pcm512x_of_match); | 59 | MODULE_DEVICE_TABLE(of, pcm512x_of_match); |
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 30c673cdc12e..9974f201a08f 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c | |||
@@ -21,12 +21,19 @@ | |||
21 | #include <linux/pm_runtime.h> | 21 | #include <linux/pm_runtime.h> |
22 | #include <linux/regmap.h> | 22 | #include <linux/regmap.h> |
23 | #include <linux/regulator/consumer.h> | 23 | #include <linux/regulator/consumer.h> |
24 | #include <linux/gcd.h> | ||
24 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
25 | #include <sound/soc-dapm.h> | 26 | #include <sound/soc-dapm.h> |
27 | #include <sound/pcm_params.h> | ||
26 | #include <sound/tlv.h> | 28 | #include <sound/tlv.h> |
27 | 29 | ||
28 | #include "pcm512x.h" | 30 | #include "pcm512x.h" |
29 | 31 | ||
32 | #define DIV_ROUND_DOWN_ULL(ll, d) \ | ||
33 | ({ unsigned long long _tmp = (ll); do_div(_tmp, d); _tmp; }) | ||
34 | #define DIV_ROUND_CLOSEST_ULL(ll, d) \ | ||
35 | ({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; }) | ||
36 | |||
30 | #define PCM512x_NUM_SUPPLIES 3 | 37 | #define PCM512x_NUM_SUPPLIES 3 |
31 | static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { | 38 | static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { |
32 | "AVDD", | 39 | "AVDD", |
@@ -39,6 +46,14 @@ struct pcm512x_priv { | |||
39 | struct clk *sclk; | 46 | struct clk *sclk; |
40 | struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES]; | 47 | struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES]; |
41 | struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES]; | 48 | struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES]; |
49 | int fmt; | ||
50 | int pll_in; | ||
51 | int pll_out; | ||
52 | int pll_r; | ||
53 | int pll_j; | ||
54 | int pll_d; | ||
55 | int pll_p; | ||
56 | unsigned long real_pll; | ||
42 | }; | 57 | }; |
43 | 58 | ||
44 | /* | 59 | /* |
@@ -69,6 +84,7 @@ static const struct reg_default pcm512x_reg_defaults[] = { | |||
69 | { PCM512x_MUTE, 0x00 }, | 84 | { PCM512x_MUTE, 0x00 }, |
70 | { PCM512x_DSP, 0x00 }, | 85 | { PCM512x_DSP, 0x00 }, |
71 | { PCM512x_PLL_REF, 0x00 }, | 86 | { PCM512x_PLL_REF, 0x00 }, |
87 | { PCM512x_DAC_REF, 0x00 }, | ||
72 | { PCM512x_DAC_ROUTING, 0x11 }, | 88 | { PCM512x_DAC_ROUTING, 0x11 }, |
73 | { PCM512x_DSP_PROGRAM, 0x01 }, | 89 | { PCM512x_DSP_PROGRAM, 0x01 }, |
74 | { PCM512x_CLKDET, 0x00 }, | 90 | { PCM512x_CLKDET, 0x00 }, |
@@ -87,6 +103,25 @@ static const struct reg_default pcm512x_reg_defaults[] = { | |||
87 | { PCM512x_ANALOG_GAIN_BOOST, 0x00 }, | 103 | { PCM512x_ANALOG_GAIN_BOOST, 0x00 }, |
88 | { PCM512x_VCOM_CTRL_1, 0x00 }, | 104 | { PCM512x_VCOM_CTRL_1, 0x00 }, |
89 | { PCM512x_VCOM_CTRL_2, 0x01 }, | 105 | { PCM512x_VCOM_CTRL_2, 0x01 }, |
106 | { PCM512x_BCLK_LRCLK_CFG, 0x00 }, | ||
107 | { PCM512x_MASTER_MODE, 0x7c }, | ||
108 | { PCM512x_GPIO_DACIN, 0x00 }, | ||
109 | { PCM512x_GPIO_PLLIN, 0x00 }, | ||
110 | { PCM512x_SYNCHRONIZE, 0x10 }, | ||
111 | { PCM512x_PLL_COEFF_0, 0x00 }, | ||
112 | { PCM512x_PLL_COEFF_1, 0x00 }, | ||
113 | { PCM512x_PLL_COEFF_2, 0x00 }, | ||
114 | { PCM512x_PLL_COEFF_3, 0x00 }, | ||
115 | { PCM512x_PLL_COEFF_4, 0x00 }, | ||
116 | { PCM512x_DSP_CLKDIV, 0x00 }, | ||
117 | { PCM512x_DAC_CLKDIV, 0x00 }, | ||
118 | { PCM512x_NCP_CLKDIV, 0x00 }, | ||
119 | { PCM512x_OSR_CLKDIV, 0x00 }, | ||
120 | { PCM512x_MASTER_CLKDIV_1, 0x00 }, | ||
121 | { PCM512x_MASTER_CLKDIV_2, 0x00 }, | ||
122 | { PCM512x_FS_SPEED_MODE, 0x00 }, | ||
123 | { PCM512x_IDAC_1, 0x01 }, | ||
124 | { PCM512x_IDAC_2, 0x00 }, | ||
90 | }; | 125 | }; |
91 | 126 | ||
92 | static bool pcm512x_readable(struct device *dev, unsigned int reg) | 127 | static bool pcm512x_readable(struct device *dev, unsigned int reg) |
@@ -103,6 +138,10 @@ static bool pcm512x_readable(struct device *dev, unsigned int reg) | |||
103 | case PCM512x_DSP_GPIO_INPUT: | 138 | case PCM512x_DSP_GPIO_INPUT: |
104 | case PCM512x_MASTER_MODE: | 139 | case PCM512x_MASTER_MODE: |
105 | case PCM512x_PLL_REF: | 140 | case PCM512x_PLL_REF: |
141 | case PCM512x_DAC_REF: | ||
142 | case PCM512x_GPIO_DACIN: | ||
143 | case PCM512x_GPIO_PLLIN: | ||
144 | case PCM512x_SYNCHRONIZE: | ||
106 | case PCM512x_PLL_COEFF_0: | 145 | case PCM512x_PLL_COEFF_0: |
107 | case PCM512x_PLL_COEFF_1: | 146 | case PCM512x_PLL_COEFF_1: |
108 | case PCM512x_PLL_COEFF_2: | 147 | case PCM512x_PLL_COEFF_2: |
@@ -143,6 +182,7 @@ static bool pcm512x_readable(struct device *dev, unsigned int reg) | |||
143 | case PCM512x_RATE_DET_2: | 182 | case PCM512x_RATE_DET_2: |
144 | case PCM512x_RATE_DET_3: | 183 | case PCM512x_RATE_DET_3: |
145 | case PCM512x_RATE_DET_4: | 184 | case PCM512x_RATE_DET_4: |
185 | case PCM512x_CLOCK_STATUS: | ||
146 | case PCM512x_ANALOG_MUTE_DET: | 186 | case PCM512x_ANALOG_MUTE_DET: |
147 | case PCM512x_GPIN: | 187 | case PCM512x_GPIN: |
148 | case PCM512x_DIGITAL_MUTE_DET: | 188 | case PCM512x_DIGITAL_MUTE_DET: |
@@ -154,6 +194,8 @@ static bool pcm512x_readable(struct device *dev, unsigned int reg) | |||
154 | case PCM512x_VCOM_CTRL_1: | 194 | case PCM512x_VCOM_CTRL_1: |
155 | case PCM512x_VCOM_CTRL_2: | 195 | case PCM512x_VCOM_CTRL_2: |
156 | case PCM512x_CRAM_CTRL: | 196 | case PCM512x_CRAM_CTRL: |
197 | case PCM512x_FLEX_A: | ||
198 | case PCM512x_FLEX_B: | ||
157 | return true; | 199 | return true; |
158 | default: | 200 | default: |
159 | /* There are 256 raw register addresses */ | 201 | /* There are 256 raw register addresses */ |
@@ -170,6 +212,7 @@ static bool pcm512x_volatile(struct device *dev, unsigned int reg) | |||
170 | case PCM512x_RATE_DET_2: | 212 | case PCM512x_RATE_DET_2: |
171 | case PCM512x_RATE_DET_3: | 213 | case PCM512x_RATE_DET_3: |
172 | case PCM512x_RATE_DET_4: | 214 | case PCM512x_RATE_DET_4: |
215 | case PCM512x_CLOCK_STATUS: | ||
173 | case PCM512x_ANALOG_MUTE_DET: | 216 | case PCM512x_ANALOG_MUTE_DET: |
174 | case PCM512x_GPIN: | 217 | case PCM512x_GPIN: |
175 | case PCM512x_DIGITAL_MUTE_DET: | 218 | case PCM512x_DIGITAL_MUTE_DET: |
@@ -277,7 +320,7 @@ SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r), | |||
277 | SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3, | 320 | SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3, |
278 | PCM512x_ACTL_SHIFT, 1, 0), | 321 | PCM512x_ACTL_SHIFT, 1, 0), |
279 | SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT, | 322 | SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT, |
280 | PCM512x_AMLR_SHIFT, 1, 0), | 323 | PCM512x_AMRE_SHIFT, 1, 0), |
281 | 324 | ||
282 | SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf), | 325 | SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf), |
283 | SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds), | 326 | SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds), |
@@ -303,6 +346,136 @@ static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = { | |||
303 | { "OUTR", NULL, "DACR" }, | 346 | { "OUTR", NULL, "DACR" }, |
304 | }; | 347 | }; |
305 | 348 | ||
349 | static const u32 pcm512x_dai_rates[] = { | ||
350 | 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, | ||
351 | 88200, 96000, 176400, 192000, 384000, | ||
352 | }; | ||
353 | |||
354 | static const struct snd_pcm_hw_constraint_list constraints_slave = { | ||
355 | .count = ARRAY_SIZE(pcm512x_dai_rates), | ||
356 | .list = pcm512x_dai_rates, | ||
357 | }; | ||
358 | |||
359 | static int pcm512x_hw_rule_rate(struct snd_pcm_hw_params *params, | ||
360 | struct snd_pcm_hw_rule *rule) | ||
361 | { | ||
362 | struct snd_interval ranges[2]; | ||
363 | int frame_size; | ||
364 | |||
365 | frame_size = snd_soc_params_to_frame_size(params); | ||
366 | if (frame_size < 0) | ||
367 | return frame_size; | ||
368 | |||
369 | switch (frame_size) { | ||
370 | case 32: | ||
371 | /* No hole when the frame size is 32. */ | ||
372 | return 0; | ||
373 | case 48: | ||
374 | case 64: | ||
375 | /* There is only one hole in the range of supported | ||
376 | * rates, but it moves with the frame size. | ||
377 | */ | ||
378 | memset(ranges, 0, sizeof(ranges)); | ||
379 | ranges[0].min = 8000; | ||
380 | ranges[0].max = 25000000 / frame_size / 2; | ||
381 | ranges[1].min = DIV_ROUND_UP(16000000, frame_size); | ||
382 | ranges[1].max = 384000; | ||
383 | break; | ||
384 | default: | ||
385 | return -EINVAL; | ||
386 | } | ||
387 | |||
388 | return snd_interval_ranges(hw_param_interval(params, rule->var), | ||
389 | ARRAY_SIZE(ranges), ranges, 0); | ||
390 | } | ||
391 | |||
392 | static int pcm512x_dai_startup_master(struct snd_pcm_substream *substream, | ||
393 | struct snd_soc_dai *dai) | ||
394 | { | ||
395 | struct snd_soc_codec *codec = dai->codec; | ||
396 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
397 | struct device *dev = dai->dev; | ||
398 | struct snd_pcm_hw_constraint_ratnums *constraints_no_pll; | ||
399 | struct snd_ratnum *rats_no_pll; | ||
400 | |||
401 | if (IS_ERR(pcm512x->sclk)) { | ||
402 | dev_err(dev, "Need SCLK for master mode: %ld\n", | ||
403 | PTR_ERR(pcm512x->sclk)); | ||
404 | return PTR_ERR(pcm512x->sclk); | ||
405 | } | ||
406 | |||
407 | if (pcm512x->pll_out) | ||
408 | return snd_pcm_hw_rule_add(substream->runtime, 0, | ||
409 | SNDRV_PCM_HW_PARAM_RATE, | ||
410 | pcm512x_hw_rule_rate, | ||
411 | NULL, | ||
412 | SNDRV_PCM_HW_PARAM_FRAME_BITS, | ||
413 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
414 | |||
415 | constraints_no_pll = devm_kzalloc(dev, sizeof(*constraints_no_pll), | ||
416 | GFP_KERNEL); | ||
417 | if (!constraints_no_pll) | ||
418 | return -ENOMEM; | ||
419 | constraints_no_pll->nrats = 1; | ||
420 | rats_no_pll = devm_kzalloc(dev, sizeof(*rats_no_pll), GFP_KERNEL); | ||
421 | if (!rats_no_pll) | ||
422 | return -ENOMEM; | ||
423 | constraints_no_pll->rats = rats_no_pll; | ||
424 | rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64; | ||
425 | rats_no_pll->den_min = 1; | ||
426 | rats_no_pll->den_max = 128; | ||
427 | rats_no_pll->den_step = 1; | ||
428 | |||
429 | return snd_pcm_hw_constraint_ratnums(substream->runtime, 0, | ||
430 | SNDRV_PCM_HW_PARAM_RATE, | ||
431 | constraints_no_pll); | ||
432 | } | ||
433 | |||
434 | static int pcm512x_dai_startup_slave(struct snd_pcm_substream *substream, | ||
435 | struct snd_soc_dai *dai) | ||
436 | { | ||
437 | struct snd_soc_codec *codec = dai->codec; | ||
438 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
439 | struct device *dev = dai->dev; | ||
440 | struct regmap *regmap = pcm512x->regmap; | ||
441 | |||
442 | if (IS_ERR(pcm512x->sclk)) { | ||
443 | dev_info(dev, "No SCLK, using BCLK: %ld\n", | ||
444 | PTR_ERR(pcm512x->sclk)); | ||
445 | |||
446 | /* Disable reporting of missing SCLK as an error */ | ||
447 | regmap_update_bits(regmap, PCM512x_ERROR_DETECT, | ||
448 | PCM512x_IDCH, PCM512x_IDCH); | ||
449 | |||
450 | /* Switch PLL input to BCLK */ | ||
451 | regmap_update_bits(regmap, PCM512x_PLL_REF, | ||
452 | PCM512x_SREF, PCM512x_SREF_BCK); | ||
453 | } | ||
454 | |||
455 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
456 | SNDRV_PCM_HW_PARAM_RATE, | ||
457 | &constraints_slave); | ||
458 | } | ||
459 | |||
460 | static int pcm512x_dai_startup(struct snd_pcm_substream *substream, | ||
461 | struct snd_soc_dai *dai) | ||
462 | { | ||
463 | struct snd_soc_codec *codec = dai->codec; | ||
464 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
465 | |||
466 | switch (pcm512x->fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
467 | case SND_SOC_DAIFMT_CBM_CFM: | ||
468 | case SND_SOC_DAIFMT_CBM_CFS: | ||
469 | return pcm512x_dai_startup_master(substream, dai); | ||
470 | |||
471 | case SND_SOC_DAIFMT_CBS_CFS: | ||
472 | return pcm512x_dai_startup_slave(substream, dai); | ||
473 | |||
474 | default: | ||
475 | return -EINVAL; | ||
476 | } | ||
477 | } | ||
478 | |||
306 | static int pcm512x_set_bias_level(struct snd_soc_codec *codec, | 479 | static int pcm512x_set_bias_level(struct snd_soc_codec *codec, |
307 | enum snd_soc_bias_level level) | 480 | enum snd_soc_bias_level level) |
308 | { | 481 | { |
@@ -340,17 +513,717 @@ static int pcm512x_set_bias_level(struct snd_soc_codec *codec, | |||
340 | return 0; | 513 | return 0; |
341 | } | 514 | } |
342 | 515 | ||
516 | static unsigned long pcm512x_find_sck(struct snd_soc_dai *dai, | ||
517 | unsigned long bclk_rate) | ||
518 | { | ||
519 | struct device *dev = dai->dev; | ||
520 | unsigned long sck_rate; | ||
521 | int pow2; | ||
522 | |||
523 | /* 64 MHz <= pll_rate <= 100 MHz, VREF mode */ | ||
524 | /* 16 MHz <= sck_rate <= 25 MHz, VREF mode */ | ||
525 | |||
526 | /* select sck_rate as a multiple of bclk_rate but still with | ||
527 | * as many factors of 2 as possible, as that makes it easier | ||
528 | * to find a fast DAC rate | ||
529 | */ | ||
530 | pow2 = 1 << fls((25000000 - 16000000) / bclk_rate); | ||
531 | for (; pow2; pow2 >>= 1) { | ||
532 | sck_rate = rounddown(25000000, bclk_rate * pow2); | ||
533 | if (sck_rate >= 16000000) | ||
534 | break; | ||
535 | } | ||
536 | if (!pow2) { | ||
537 | dev_err(dev, "Impossible to generate a suitable SCK\n"); | ||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | dev_dbg(dev, "sck_rate %lu\n", sck_rate); | ||
542 | return sck_rate; | ||
543 | } | ||
544 | |||
545 | /* pll_rate = pllin_rate * R * J.D / P | ||
546 | * 1 <= R <= 16 | ||
547 | * 1 <= J <= 63 | ||
548 | * 0 <= D <= 9999 | ||
549 | * 1 <= P <= 15 | ||
550 | * 64 MHz <= pll_rate <= 100 MHz | ||
551 | * if D == 0 | ||
552 | * 1 MHz <= pllin_rate / P <= 20 MHz | ||
553 | * else if D > 0 | ||
554 | * 6.667 MHz <= pllin_rate / P <= 20 MHz | ||
555 | * 4 <= J <= 11 | ||
556 | * R = 1 | ||
557 | */ | ||
558 | static int pcm512x_find_pll_coeff(struct snd_soc_dai *dai, | ||
559 | unsigned long pllin_rate, | ||
560 | unsigned long pll_rate) | ||
561 | { | ||
562 | struct device *dev = dai->dev; | ||
563 | struct snd_soc_codec *codec = dai->codec; | ||
564 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
565 | unsigned long common; | ||
566 | int R, J, D, P; | ||
567 | unsigned long K; /* 10000 * J.D */ | ||
568 | unsigned long num; | ||
569 | unsigned long den; | ||
570 | |||
571 | common = gcd(pll_rate, pllin_rate); | ||
572 | dev_dbg(dev, "pll %lu pllin %lu common %lu\n", | ||
573 | pll_rate, pllin_rate, common); | ||
574 | num = pll_rate / common; | ||
575 | den = pllin_rate / common; | ||
576 | |||
577 | /* pllin_rate / P (or here, den) cannot be greater than 20 MHz */ | ||
578 | if (pllin_rate / den > 20000000 && num < 8) { | ||
579 | num *= 20000000 / (pllin_rate / den); | ||
580 | den *= 20000000 / (pllin_rate / den); | ||
581 | } | ||
582 | dev_dbg(dev, "num / den = %lu / %lu\n", num, den); | ||
583 | |||
584 | P = den; | ||
585 | if (den <= 15 && num <= 16 * 63 | ||
586 | && 1000000 <= pllin_rate / P && pllin_rate / P <= 20000000) { | ||
587 | /* Try the case with D = 0 */ | ||
588 | D = 0; | ||
589 | /* factor 'num' into J and R, such that R <= 16 and J <= 63 */ | ||
590 | for (R = 16; R; R--) { | ||
591 | if (num % R) | ||
592 | continue; | ||
593 | J = num / R; | ||
594 | if (J == 0 || J > 63) | ||
595 | continue; | ||
596 | |||
597 | dev_dbg(dev, "R * J / P = %d * %d / %d\n", R, J, P); | ||
598 | pcm512x->real_pll = pll_rate; | ||
599 | goto done; | ||
600 | } | ||
601 | /* no luck */ | ||
602 | } | ||
603 | |||
604 | R = 1; | ||
605 | |||
606 | if (num > 0xffffffffUL / 10000) | ||
607 | goto fallback; | ||
608 | |||
609 | /* Try to find an exact pll_rate using the D > 0 case */ | ||
610 | common = gcd(10000 * num, den); | ||
611 | num = 10000 * num / common; | ||
612 | den /= common; | ||
613 | dev_dbg(dev, "num %lu den %lu common %lu\n", num, den, common); | ||
614 | |||
615 | for (P = den; P <= 15; P++) { | ||
616 | if (pllin_rate / P < 6667000 || 200000000 < pllin_rate / P) | ||
617 | continue; | ||
618 | if (num * P % den) | ||
619 | continue; | ||
620 | K = num * P / den; | ||
621 | /* J == 12 is ok if D == 0 */ | ||
622 | if (K < 40000 || K > 120000) | ||
623 | continue; | ||
624 | |||
625 | J = K / 10000; | ||
626 | D = K % 10000; | ||
627 | dev_dbg(dev, "J.D / P = %d.%04d / %d\n", J, D, P); | ||
628 | pcm512x->real_pll = pll_rate; | ||
629 | goto done; | ||
630 | } | ||
631 | |||
632 | /* Fall back to an approximate pll_rate */ | ||
633 | |||
634 | fallback: | ||
635 | /* find smallest possible P */ | ||
636 | P = DIV_ROUND_UP(pllin_rate, 20000000); | ||
637 | if (!P) | ||
638 | P = 1; | ||
639 | else if (P > 15) { | ||
640 | dev_err(dev, "Need a slower clock as pll-input\n"); | ||
641 | return -EINVAL; | ||
642 | } | ||
643 | if (pllin_rate / P < 6667000) { | ||
644 | dev_err(dev, "Need a faster clock as pll-input\n"); | ||
645 | return -EINVAL; | ||
646 | } | ||
647 | K = DIV_ROUND_CLOSEST_ULL(10000ULL * pll_rate * P, pllin_rate); | ||
648 | if (K < 40000) | ||
649 | K = 40000; | ||
650 | /* J == 12 is ok if D == 0 */ | ||
651 | if (K > 120000) | ||
652 | K = 120000; | ||
653 | J = K / 10000; | ||
654 | D = K % 10000; | ||
655 | dev_dbg(dev, "J.D / P ~ %d.%04d / %d\n", J, D, P); | ||
656 | pcm512x->real_pll = DIV_ROUND_DOWN_ULL((u64)K * pllin_rate, 10000 * P); | ||
657 | |||
658 | done: | ||
659 | pcm512x->pll_r = R; | ||
660 | pcm512x->pll_j = J; | ||
661 | pcm512x->pll_d = D; | ||
662 | pcm512x->pll_p = P; | ||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | static unsigned long pcm512x_pllin_dac_rate(struct snd_soc_dai *dai, | ||
667 | unsigned long osr_rate, | ||
668 | unsigned long pllin_rate) | ||
669 | { | ||
670 | struct snd_soc_codec *codec = dai->codec; | ||
671 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
672 | unsigned long dac_rate; | ||
673 | |||
674 | if (!pcm512x->pll_out) | ||
675 | return 0; /* no PLL to bypass, force SCK as DAC input */ | ||
676 | |||
677 | if (pllin_rate % osr_rate) | ||
678 | return 0; /* futile, quit early */ | ||
679 | |||
680 | /* run DAC no faster than 6144000 Hz */ | ||
681 | for (dac_rate = rounddown(6144000, osr_rate); | ||
682 | dac_rate; | ||
683 | dac_rate -= osr_rate) { | ||
684 | |||
685 | if (pllin_rate / dac_rate > 128) | ||
686 | return 0; /* DAC divider would be too big */ | ||
687 | |||
688 | if (!(pllin_rate % dac_rate)) | ||
689 | return dac_rate; | ||
690 | |||
691 | dac_rate -= osr_rate; | ||
692 | } | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static int pcm512x_set_dividers(struct snd_soc_dai *dai, | ||
698 | struct snd_pcm_hw_params *params) | ||
699 | { | ||
700 | struct device *dev = dai->dev; | ||
701 | struct snd_soc_codec *codec = dai->codec; | ||
702 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
703 | unsigned long pllin_rate = 0; | ||
704 | unsigned long pll_rate; | ||
705 | unsigned long sck_rate; | ||
706 | unsigned long mck_rate; | ||
707 | unsigned long bclk_rate; | ||
708 | unsigned long sample_rate; | ||
709 | unsigned long osr_rate; | ||
710 | unsigned long dacsrc_rate; | ||
711 | int bclk_div; | ||
712 | int lrclk_div; | ||
713 | int dsp_div; | ||
714 | int dac_div; | ||
715 | unsigned long dac_rate; | ||
716 | int ncp_div; | ||
717 | int osr_div; | ||
718 | int ret; | ||
719 | int idac; | ||
720 | int fssp; | ||
721 | int gpio; | ||
722 | |||
723 | lrclk_div = snd_soc_params_to_frame_size(params); | ||
724 | if (lrclk_div == 0) { | ||
725 | dev_err(dev, "No LRCLK?\n"); | ||
726 | return -EINVAL; | ||
727 | } | ||
728 | |||
729 | if (!pcm512x->pll_out) { | ||
730 | sck_rate = clk_get_rate(pcm512x->sclk); | ||
731 | bclk_div = params->rate_den * 64 / lrclk_div; | ||
732 | bclk_rate = DIV_ROUND_CLOSEST(sck_rate, bclk_div); | ||
733 | |||
734 | mck_rate = sck_rate; | ||
735 | } else { | ||
736 | ret = snd_soc_params_to_bclk(params); | ||
737 | if (ret < 0) { | ||
738 | dev_err(dev, "Failed to find suitable BCLK: %d\n", ret); | ||
739 | return ret; | ||
740 | } | ||
741 | if (ret == 0) { | ||
742 | dev_err(dev, "No BCLK?\n"); | ||
743 | return -EINVAL; | ||
744 | } | ||
745 | bclk_rate = ret; | ||
746 | |||
747 | pllin_rate = clk_get_rate(pcm512x->sclk); | ||
748 | |||
749 | sck_rate = pcm512x_find_sck(dai, bclk_rate); | ||
750 | if (!sck_rate) | ||
751 | return -EINVAL; | ||
752 | pll_rate = 4 * sck_rate; | ||
753 | |||
754 | ret = pcm512x_find_pll_coeff(dai, pllin_rate, pll_rate); | ||
755 | if (ret != 0) | ||
756 | return ret; | ||
757 | |||
758 | ret = regmap_write(pcm512x->regmap, | ||
759 | PCM512x_PLL_COEFF_0, pcm512x->pll_p - 1); | ||
760 | if (ret != 0) { | ||
761 | dev_err(dev, "Failed to write PLL P: %d\n", ret); | ||
762 | return ret; | ||
763 | } | ||
764 | |||
765 | ret = regmap_write(pcm512x->regmap, | ||
766 | PCM512x_PLL_COEFF_1, pcm512x->pll_j); | ||
767 | if (ret != 0) { | ||
768 | dev_err(dev, "Failed to write PLL J: %d\n", ret); | ||
769 | return ret; | ||
770 | } | ||
771 | |||
772 | ret = regmap_write(pcm512x->regmap, | ||
773 | PCM512x_PLL_COEFF_2, pcm512x->pll_d >> 8); | ||
774 | if (ret != 0) { | ||
775 | dev_err(dev, "Failed to write PLL D msb: %d\n", ret); | ||
776 | return ret; | ||
777 | } | ||
778 | |||
779 | ret = regmap_write(pcm512x->regmap, | ||
780 | PCM512x_PLL_COEFF_3, pcm512x->pll_d & 0xff); | ||
781 | if (ret != 0) { | ||
782 | dev_err(dev, "Failed to write PLL D lsb: %d\n", ret); | ||
783 | return ret; | ||
784 | } | ||
785 | |||
786 | ret = regmap_write(pcm512x->regmap, | ||
787 | PCM512x_PLL_COEFF_4, pcm512x->pll_r - 1); | ||
788 | if (ret != 0) { | ||
789 | dev_err(dev, "Failed to write PLL R: %d\n", ret); | ||
790 | return ret; | ||
791 | } | ||
792 | |||
793 | mck_rate = pcm512x->real_pll; | ||
794 | |||
795 | bclk_div = DIV_ROUND_CLOSEST(sck_rate, bclk_rate); | ||
796 | } | ||
797 | |||
798 | if (bclk_div > 128) { | ||
799 | dev_err(dev, "Failed to find BCLK divider\n"); | ||
800 | return -EINVAL; | ||
801 | } | ||
802 | |||
803 | /* the actual rate */ | ||
804 | sample_rate = sck_rate / bclk_div / lrclk_div; | ||
805 | osr_rate = 16 * sample_rate; | ||
806 | |||
807 | /* run DSP no faster than 50 MHz */ | ||
808 | dsp_div = mck_rate > 50000000 ? 2 : 1; | ||
809 | |||
810 | dac_rate = pcm512x_pllin_dac_rate(dai, osr_rate, pllin_rate); | ||
811 | if (dac_rate) { | ||
812 | /* the desired clock rate is "compatible" with the pll input | ||
813 | * clock, so use that clock as dac input instead of the pll | ||
814 | * output clock since the pll will introduce jitter and thus | ||
815 | * noise. | ||
816 | */ | ||
817 | dev_dbg(dev, "using pll input as dac input\n"); | ||
818 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF, | ||
819 | PCM512x_SDAC, PCM512x_SDAC_GPIO); | ||
820 | if (ret != 0) { | ||
821 | dev_err(codec->dev, | ||
822 | "Failed to set gpio as dacref: %d\n", ret); | ||
823 | return ret; | ||
824 | } | ||
825 | |||
826 | gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1; | ||
827 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_DACIN, | ||
828 | PCM512x_GREF, gpio); | ||
829 | if (ret != 0) { | ||
830 | dev_err(codec->dev, | ||
831 | "Failed to set gpio %d as dacin: %d\n", | ||
832 | pcm512x->pll_in, ret); | ||
833 | return ret; | ||
834 | } | ||
835 | |||
836 | dacsrc_rate = pllin_rate; | ||
837 | } else { | ||
838 | /* run DAC no faster than 6144000 Hz */ | ||
839 | unsigned long dac_mul = 6144000 / osr_rate; | ||
840 | unsigned long sck_mul = sck_rate / osr_rate; | ||
841 | |||
842 | for (; dac_mul; dac_mul--) { | ||
843 | if (!(sck_mul % dac_mul)) | ||
844 | break; | ||
845 | } | ||
846 | if (!dac_mul) { | ||
847 | dev_err(dev, "Failed to find DAC rate\n"); | ||
848 | return -EINVAL; | ||
849 | } | ||
850 | |||
851 | dac_rate = dac_mul * osr_rate; | ||
852 | dev_dbg(dev, "dac_rate %lu sample_rate %lu\n", | ||
853 | dac_rate, sample_rate); | ||
854 | |||
855 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF, | ||
856 | PCM512x_SDAC, PCM512x_SDAC_SCK); | ||
857 | if (ret != 0) { | ||
858 | dev_err(codec->dev, | ||
859 | "Failed to set sck as dacref: %d\n", ret); | ||
860 | return ret; | ||
861 | } | ||
862 | |||
863 | dacsrc_rate = sck_rate; | ||
864 | } | ||
865 | |||
866 | dac_div = DIV_ROUND_CLOSEST(dacsrc_rate, dac_rate); | ||
867 | if (dac_div > 128) { | ||
868 | dev_err(dev, "Failed to find DAC divider\n"); | ||
869 | return -EINVAL; | ||
870 | } | ||
871 | |||
872 | ncp_div = DIV_ROUND_CLOSEST(dacsrc_rate / dac_div, 1536000); | ||
873 | if (ncp_div > 128 || dacsrc_rate / dac_div / ncp_div > 2048000) { | ||
874 | /* run NCP no faster than 2048000 Hz, but why? */ | ||
875 | ncp_div = DIV_ROUND_UP(dacsrc_rate / dac_div, 2048000); | ||
876 | if (ncp_div > 128) { | ||
877 | dev_err(dev, "Failed to find NCP divider\n"); | ||
878 | return -EINVAL; | ||
879 | } | ||
880 | } | ||
881 | |||
882 | osr_div = DIV_ROUND_CLOSEST(dac_rate, osr_rate); | ||
883 | if (osr_div > 128) { | ||
884 | dev_err(dev, "Failed to find OSR divider\n"); | ||
885 | return -EINVAL; | ||
886 | } | ||
887 | |||
888 | idac = mck_rate / (dsp_div * sample_rate); | ||
889 | |||
890 | ret = regmap_write(pcm512x->regmap, PCM512x_DSP_CLKDIV, dsp_div - 1); | ||
891 | if (ret != 0) { | ||
892 | dev_err(dev, "Failed to write DSP divider: %d\n", ret); | ||
893 | return ret; | ||
894 | } | ||
895 | |||
896 | ret = regmap_write(pcm512x->regmap, PCM512x_DAC_CLKDIV, dac_div - 1); | ||
897 | if (ret != 0) { | ||
898 | dev_err(dev, "Failed to write DAC divider: %d\n", ret); | ||
899 | return ret; | ||
900 | } | ||
901 | |||
902 | ret = regmap_write(pcm512x->regmap, PCM512x_NCP_CLKDIV, ncp_div - 1); | ||
903 | if (ret != 0) { | ||
904 | dev_err(dev, "Failed to write NCP divider: %d\n", ret); | ||
905 | return ret; | ||
906 | } | ||
907 | |||
908 | ret = regmap_write(pcm512x->regmap, PCM512x_OSR_CLKDIV, osr_div - 1); | ||
909 | if (ret != 0) { | ||
910 | dev_err(dev, "Failed to write OSR divider: %d\n", ret); | ||
911 | return ret; | ||
912 | } | ||
913 | |||
914 | ret = regmap_write(pcm512x->regmap, | ||
915 | PCM512x_MASTER_CLKDIV_1, bclk_div - 1); | ||
916 | if (ret != 0) { | ||
917 | dev_err(dev, "Failed to write BCLK divider: %d\n", ret); | ||
918 | return ret; | ||
919 | } | ||
920 | |||
921 | ret = regmap_write(pcm512x->regmap, | ||
922 | PCM512x_MASTER_CLKDIV_2, lrclk_div - 1); | ||
923 | if (ret != 0) { | ||
924 | dev_err(dev, "Failed to write LRCLK divider: %d\n", ret); | ||
925 | return ret; | ||
926 | } | ||
927 | |||
928 | ret = regmap_write(pcm512x->regmap, PCM512x_IDAC_1, idac >> 8); | ||
929 | if (ret != 0) { | ||
930 | dev_err(dev, "Failed to write IDAC msb divider: %d\n", ret); | ||
931 | return ret; | ||
932 | } | ||
933 | |||
934 | ret = regmap_write(pcm512x->regmap, PCM512x_IDAC_2, idac & 0xff); | ||
935 | if (ret != 0) { | ||
936 | dev_err(dev, "Failed to write IDAC lsb divider: %d\n", ret); | ||
937 | return ret; | ||
938 | } | ||
939 | |||
940 | if (sample_rate <= 48000) | ||
941 | fssp = PCM512x_FSSP_48KHZ; | ||
942 | else if (sample_rate <= 96000) | ||
943 | fssp = PCM512x_FSSP_96KHZ; | ||
944 | else if (sample_rate <= 192000) | ||
945 | fssp = PCM512x_FSSP_192KHZ; | ||
946 | else | ||
947 | fssp = PCM512x_FSSP_384KHZ; | ||
948 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_FS_SPEED_MODE, | ||
949 | PCM512x_FSSP, fssp); | ||
950 | if (ret != 0) { | ||
951 | dev_err(codec->dev, "Failed to set fs speed: %d\n", ret); | ||
952 | return ret; | ||
953 | } | ||
954 | |||
955 | dev_dbg(codec->dev, "DSP divider %d\n", dsp_div); | ||
956 | dev_dbg(codec->dev, "DAC divider %d\n", dac_div); | ||
957 | dev_dbg(codec->dev, "NCP divider %d\n", ncp_div); | ||
958 | dev_dbg(codec->dev, "OSR divider %d\n", osr_div); | ||
959 | dev_dbg(codec->dev, "BCK divider %d\n", bclk_div); | ||
960 | dev_dbg(codec->dev, "LRCK divider %d\n", lrclk_div); | ||
961 | dev_dbg(codec->dev, "IDAC %d\n", idac); | ||
962 | dev_dbg(codec->dev, "1<<FSSP %d\n", 1 << fssp); | ||
963 | |||
964 | return 0; | ||
965 | } | ||
966 | |||
967 | static int pcm512x_hw_params(struct snd_pcm_substream *substream, | ||
968 | struct snd_pcm_hw_params *params, | ||
969 | struct snd_soc_dai *dai) | ||
970 | { | ||
971 | struct snd_soc_codec *codec = dai->codec; | ||
972 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
973 | int alen; | ||
974 | int gpio; | ||
975 | int clock_output; | ||
976 | int master_mode; | ||
977 | int ret; | ||
978 | |||
979 | dev_dbg(codec->dev, "hw_params %u Hz, %u channels\n", | ||
980 | params_rate(params), | ||
981 | params_channels(params)); | ||
982 | |||
983 | switch (snd_pcm_format_width(params_format(params))) { | ||
984 | case 16: | ||
985 | alen = PCM512x_ALEN_16; | ||
986 | break; | ||
987 | case 20: | ||
988 | alen = PCM512x_ALEN_20; | ||
989 | break; | ||
990 | case 24: | ||
991 | alen = PCM512x_ALEN_24; | ||
992 | break; | ||
993 | case 32: | ||
994 | alen = PCM512x_ALEN_32; | ||
995 | break; | ||
996 | default: | ||
997 | dev_err(codec->dev, "Bad frame size: %d\n", | ||
998 | snd_pcm_format_width(params_format(params))); | ||
999 | return -EINVAL; | ||
1000 | } | ||
1001 | |||
1002 | switch (pcm512x->fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1003 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1004 | ret = regmap_update_bits(pcm512x->regmap, | ||
1005 | PCM512x_BCLK_LRCLK_CFG, | ||
1006 | PCM512x_BCKP | ||
1007 | | PCM512x_BCKO | PCM512x_LRKO, | ||
1008 | 0); | ||
1009 | if (ret != 0) { | ||
1010 | dev_err(codec->dev, | ||
1011 | "Failed to enable slave mode: %d\n", ret); | ||
1012 | return ret; | ||
1013 | } | ||
1014 | |||
1015 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, | ||
1016 | PCM512x_DCAS, 0); | ||
1017 | if (ret != 0) { | ||
1018 | dev_err(codec->dev, | ||
1019 | "Failed to enable clock divider autoset: %d\n", | ||
1020 | ret); | ||
1021 | return ret; | ||
1022 | } | ||
1023 | return 0; | ||
1024 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1025 | clock_output = PCM512x_BCKO | PCM512x_LRKO; | ||
1026 | master_mode = PCM512x_RLRK | PCM512x_RBCK; | ||
1027 | break; | ||
1028 | case SND_SOC_DAIFMT_CBM_CFS: | ||
1029 | clock_output = PCM512x_BCKO; | ||
1030 | master_mode = PCM512x_RBCK; | ||
1031 | break; | ||
1032 | default: | ||
1033 | return -EINVAL; | ||
1034 | } | ||
1035 | |||
1036 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1, | ||
1037 | PCM512x_ALEN, alen); | ||
1038 | if (ret != 0) { | ||
1039 | dev_err(codec->dev, "Failed to set frame size: %d\n", ret); | ||
1040 | return ret; | ||
1041 | } | ||
1042 | |||
1043 | if (pcm512x->pll_out) { | ||
1044 | ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_A, 0x11); | ||
1045 | if (ret != 0) { | ||
1046 | dev_err(codec->dev, "Failed to set FLEX_A: %d\n", ret); | ||
1047 | return ret; | ||
1048 | } | ||
1049 | |||
1050 | ret = regmap_write(pcm512x->regmap, PCM512x_FLEX_B, 0xff); | ||
1051 | if (ret != 0) { | ||
1052 | dev_err(codec->dev, "Failed to set FLEX_B: %d\n", ret); | ||
1053 | return ret; | ||
1054 | } | ||
1055 | |||
1056 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, | ||
1057 | PCM512x_IDFS | PCM512x_IDBK | ||
1058 | | PCM512x_IDSK | PCM512x_IDCH | ||
1059 | | PCM512x_IDCM | PCM512x_DCAS | ||
1060 | | PCM512x_IPLK, | ||
1061 | PCM512x_IDFS | PCM512x_IDBK | ||
1062 | | PCM512x_IDSK | PCM512x_IDCH | ||
1063 | | PCM512x_DCAS); | ||
1064 | if (ret != 0) { | ||
1065 | dev_err(codec->dev, | ||
1066 | "Failed to ignore auto-clock failures: %d\n", | ||
1067 | ret); | ||
1068 | return ret; | ||
1069 | } | ||
1070 | } else { | ||
1071 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_ERROR_DETECT, | ||
1072 | PCM512x_IDFS | PCM512x_IDBK | ||
1073 | | PCM512x_IDSK | PCM512x_IDCH | ||
1074 | | PCM512x_IDCM | PCM512x_DCAS | ||
1075 | | PCM512x_IPLK, | ||
1076 | PCM512x_IDFS | PCM512x_IDBK | ||
1077 | | PCM512x_IDSK | PCM512x_IDCH | ||
1078 | | PCM512x_DCAS | PCM512x_IPLK); | ||
1079 | if (ret != 0) { | ||
1080 | dev_err(codec->dev, | ||
1081 | "Failed to ignore auto-clock failures: %d\n", | ||
1082 | ret); | ||
1083 | return ret; | ||
1084 | } | ||
1085 | |||
1086 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN, | ||
1087 | PCM512x_PLLE, 0); | ||
1088 | if (ret != 0) { | ||
1089 | dev_err(codec->dev, "Failed to disable pll: %d\n", ret); | ||
1090 | return ret; | ||
1091 | } | ||
1092 | } | ||
1093 | |||
1094 | ret = pcm512x_set_dividers(dai, params); | ||
1095 | if (ret != 0) | ||
1096 | return ret; | ||
1097 | |||
1098 | if (pcm512x->pll_out) { | ||
1099 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_REF, | ||
1100 | PCM512x_SREF, PCM512x_SREF_GPIO); | ||
1101 | if (ret != 0) { | ||
1102 | dev_err(codec->dev, | ||
1103 | "Failed to set gpio as pllref: %d\n", ret); | ||
1104 | return ret; | ||
1105 | } | ||
1106 | |||
1107 | gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1; | ||
1108 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_PLLIN, | ||
1109 | PCM512x_GREF, gpio); | ||
1110 | if (ret != 0) { | ||
1111 | dev_err(codec->dev, | ||
1112 | "Failed to set gpio %d as pllin: %d\n", | ||
1113 | pcm512x->pll_in, ret); | ||
1114 | return ret; | ||
1115 | } | ||
1116 | |||
1117 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN, | ||
1118 | PCM512x_PLLE, PCM512x_PLLE); | ||
1119 | if (ret != 0) { | ||
1120 | dev_err(codec->dev, "Failed to enable pll: %d\n", ret); | ||
1121 | return ret; | ||
1122 | } | ||
1123 | } | ||
1124 | |||
1125 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_BCLK_LRCLK_CFG, | ||
1126 | PCM512x_BCKP | PCM512x_BCKO | PCM512x_LRKO, | ||
1127 | clock_output); | ||
1128 | if (ret != 0) { | ||
1129 | dev_err(codec->dev, "Failed to enable clock output: %d\n", ret); | ||
1130 | return ret; | ||
1131 | } | ||
1132 | |||
1133 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_MASTER_MODE, | ||
1134 | PCM512x_RLRK | PCM512x_RBCK, | ||
1135 | master_mode); | ||
1136 | if (ret != 0) { | ||
1137 | dev_err(codec->dev, "Failed to enable master mode: %d\n", ret); | ||
1138 | return ret; | ||
1139 | } | ||
1140 | |||
1141 | if (pcm512x->pll_out) { | ||
1142 | gpio = PCM512x_G1OE << (pcm512x->pll_out - 1); | ||
1143 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_EN, | ||
1144 | gpio, gpio); | ||
1145 | if (ret != 0) { | ||
1146 | dev_err(codec->dev, "Failed to enable gpio %d: %d\n", | ||
1147 | pcm512x->pll_out, ret); | ||
1148 | return ret; | ||
1149 | } | ||
1150 | |||
1151 | gpio = PCM512x_GPIO_OUTPUT_1 + pcm512x->pll_out - 1; | ||
1152 | ret = regmap_update_bits(pcm512x->regmap, gpio, | ||
1153 | PCM512x_GxSL, PCM512x_GxSL_PLLCK); | ||
1154 | if (ret != 0) { | ||
1155 | dev_err(codec->dev, "Failed to output pll on %d: %d\n", | ||
1156 | ret, pcm512x->pll_out); | ||
1157 | return ret; | ||
1158 | } | ||
1159 | |||
1160 | gpio = PCM512x_G1OE << (4 - 1); | ||
1161 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_EN, | ||
1162 | gpio, gpio); | ||
1163 | if (ret != 0) { | ||
1164 | dev_err(codec->dev, "Failed to enable gpio %d: %d\n", | ||
1165 | 4, ret); | ||
1166 | return ret; | ||
1167 | } | ||
1168 | |||
1169 | gpio = PCM512x_GPIO_OUTPUT_1 + 4 - 1; | ||
1170 | ret = regmap_update_bits(pcm512x->regmap, gpio, | ||
1171 | PCM512x_GxSL, PCM512x_GxSL_PLLLK); | ||
1172 | if (ret != 0) { | ||
1173 | dev_err(codec->dev, | ||
1174 | "Failed to output pll lock on %d: %d\n", | ||
1175 | ret, 4); | ||
1176 | return ret; | ||
1177 | } | ||
1178 | } | ||
1179 | |||
1180 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE, | ||
1181 | PCM512x_RQSY, PCM512x_RQSY_HALT); | ||
1182 | if (ret != 0) { | ||
1183 | dev_err(codec->dev, "Failed to halt clocks: %d\n", ret); | ||
1184 | return ret; | ||
1185 | } | ||
1186 | |||
1187 | ret = regmap_update_bits(pcm512x->regmap, PCM512x_SYNCHRONIZE, | ||
1188 | PCM512x_RQSY, PCM512x_RQSY_RESUME); | ||
1189 | if (ret != 0) { | ||
1190 | dev_err(codec->dev, "Failed to resume clocks: %d\n", ret); | ||
1191 | return ret; | ||
1192 | } | ||
1193 | |||
1194 | return 0; | ||
1195 | } | ||
1196 | |||
1197 | static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
1198 | { | ||
1199 | struct snd_soc_codec *codec = dai->codec; | ||
1200 | struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); | ||
1201 | |||
1202 | pcm512x->fmt = fmt; | ||
1203 | |||
1204 | return 0; | ||
1205 | } | ||
1206 | |||
1207 | static const struct snd_soc_dai_ops pcm512x_dai_ops = { | ||
1208 | .startup = pcm512x_dai_startup, | ||
1209 | .hw_params = pcm512x_hw_params, | ||
1210 | .set_fmt = pcm512x_set_fmt, | ||
1211 | }; | ||
1212 | |||
343 | static struct snd_soc_dai_driver pcm512x_dai = { | 1213 | static struct snd_soc_dai_driver pcm512x_dai = { |
344 | .name = "pcm512x-hifi", | 1214 | .name = "pcm512x-hifi", |
345 | .playback = { | 1215 | .playback = { |
346 | .stream_name = "Playback", | 1216 | .stream_name = "Playback", |
347 | .channels_min = 2, | 1217 | .channels_min = 2, |
348 | .channels_max = 2, | 1218 | .channels_max = 2, |
349 | .rates = SNDRV_PCM_RATE_8000_192000, | 1219 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
1220 | .rate_min = 8000, | ||
1221 | .rate_max = 384000, | ||
350 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 1222 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
351 | SNDRV_PCM_FMTBIT_S24_LE | | 1223 | SNDRV_PCM_FMTBIT_S24_LE | |
352 | SNDRV_PCM_FMTBIT_S32_LE | 1224 | SNDRV_PCM_FMTBIT_S32_LE |
353 | }, | 1225 | }, |
1226 | .ops = &pcm512x_dai_ops, | ||
354 | }; | 1227 | }; |
355 | 1228 | ||
356 | static struct snd_soc_codec_driver pcm512x_codec_driver = { | 1229 | static struct snd_soc_codec_driver pcm512x_codec_driver = { |
@@ -448,21 +1321,9 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap) | |||
448 | } | 1321 | } |
449 | 1322 | ||
450 | pcm512x->sclk = devm_clk_get(dev, NULL); | 1323 | pcm512x->sclk = devm_clk_get(dev, NULL); |
451 | if (IS_ERR(pcm512x->sclk)) { | 1324 | if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) |
452 | if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) | 1325 | return -EPROBE_DEFER; |
453 | return -EPROBE_DEFER; | 1326 | if (!IS_ERR(pcm512x->sclk)) { |
454 | |||
455 | dev_info(dev, "No SCLK, using BCLK: %ld\n", | ||
456 | PTR_ERR(pcm512x->sclk)); | ||
457 | |||
458 | /* Disable reporting of missing SCLK as an error */ | ||
459 | regmap_update_bits(regmap, PCM512x_ERROR_DETECT, | ||
460 | PCM512x_IDCH, PCM512x_IDCH); | ||
461 | |||
462 | /* Switch PLL input to BCLK */ | ||
463 | regmap_update_bits(regmap, PCM512x_PLL_REF, | ||
464 | PCM512x_SREF, PCM512x_SREF); | ||
465 | } else { | ||
466 | ret = clk_prepare_enable(pcm512x->sclk); | 1327 | ret = clk_prepare_enable(pcm512x->sclk); |
467 | if (ret != 0) { | 1328 | if (ret != 0) { |
468 | dev_err(dev, "Failed to enable SCLK: %d\n", ret); | 1329 | dev_err(dev, "Failed to enable SCLK: %d\n", ret); |
@@ -483,6 +1344,43 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap) | |||
483 | pm_runtime_enable(dev); | 1344 | pm_runtime_enable(dev); |
484 | pm_runtime_idle(dev); | 1345 | pm_runtime_idle(dev); |
485 | 1346 | ||
1347 | #ifdef CONFIG_OF | ||
1348 | if (dev->of_node) { | ||
1349 | const struct device_node *np = dev->of_node; | ||
1350 | u32 val; | ||
1351 | |||
1352 | if (of_property_read_u32(np, "pll-in", &val) >= 0) { | ||
1353 | if (val > 6) { | ||
1354 | dev_err(dev, "Invalid pll-in\n"); | ||
1355 | ret = -EINVAL; | ||
1356 | goto err_clk; | ||
1357 | } | ||
1358 | pcm512x->pll_in = val; | ||
1359 | } | ||
1360 | |||
1361 | if (of_property_read_u32(np, "pll-out", &val) >= 0) { | ||
1362 | if (val > 6) { | ||
1363 | dev_err(dev, "Invalid pll-out\n"); | ||
1364 | ret = -EINVAL; | ||
1365 | goto err_clk; | ||
1366 | } | ||
1367 | pcm512x->pll_out = val; | ||
1368 | } | ||
1369 | |||
1370 | if (!pcm512x->pll_in != !pcm512x->pll_out) { | ||
1371 | dev_err(dev, | ||
1372 | "Error: both pll-in and pll-out, or none\n"); | ||
1373 | ret = -EINVAL; | ||
1374 | goto err_clk; | ||
1375 | } | ||
1376 | if (pcm512x->pll_in && pcm512x->pll_in == pcm512x->pll_out) { | ||
1377 | dev_err(dev, "Error: pll-in == pll-out\n"); | ||
1378 | ret = -EINVAL; | ||
1379 | goto err_clk; | ||
1380 | } | ||
1381 | } | ||
1382 | #endif | ||
1383 | |||
486 | ret = snd_soc_register_codec(dev, &pcm512x_codec_driver, | 1384 | ret = snd_soc_register_codec(dev, &pcm512x_codec_driver, |
487 | &pcm512x_dai, 1); | 1385 | &pcm512x_dai, 1); |
488 | if (ret != 0) { | 1386 | if (ret != 0) { |
diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h index 6ee76aaca09a..b7c310207223 100644 --- a/sound/soc/codecs/pcm512x.h +++ b/sound/soc/codecs/pcm512x.h | |||
@@ -37,6 +37,10 @@ | |||
37 | #define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_BASE(0) + 10) | 37 | #define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_BASE(0) + 10) |
38 | #define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12) | 38 | #define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12) |
39 | #define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13) | 39 | #define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13) |
40 | #define PCM512x_DAC_REF (PCM512x_PAGE_BASE(0) + 14) | ||
41 | #define PCM512x_GPIO_DACIN (PCM512x_PAGE_BASE(0) + 16) | ||
42 | #define PCM512x_GPIO_PLLIN (PCM512x_PAGE_BASE(0) + 18) | ||
43 | #define PCM512x_SYNCHRONIZE (PCM512x_PAGE_BASE(0) + 19) | ||
40 | #define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20) | 44 | #define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20) |
41 | #define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_BASE(0) + 21) | 45 | #define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_BASE(0) + 21) |
42 | #define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_BASE(0) + 22) | 46 | #define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_BASE(0) + 22) |
@@ -77,6 +81,7 @@ | |||
77 | #define PCM512x_RATE_DET_2 (PCM512x_PAGE_BASE(0) + 92) | 81 | #define PCM512x_RATE_DET_2 (PCM512x_PAGE_BASE(0) + 92) |
78 | #define PCM512x_RATE_DET_3 (PCM512x_PAGE_BASE(0) + 93) | 82 | #define PCM512x_RATE_DET_3 (PCM512x_PAGE_BASE(0) + 93) |
79 | #define PCM512x_RATE_DET_4 (PCM512x_PAGE_BASE(0) + 94) | 83 | #define PCM512x_RATE_DET_4 (PCM512x_PAGE_BASE(0) + 94) |
84 | #define PCM512x_CLOCK_STATUS (PCM512x_PAGE_BASE(0) + 95) | ||
80 | #define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_BASE(0) + 108) | 85 | #define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_BASE(0) + 108) |
81 | #define PCM512x_GPIN (PCM512x_PAGE_BASE(0) + 119) | 86 | #define PCM512x_GPIN (PCM512x_PAGE_BASE(0) + 119) |
82 | #define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_BASE(0) + 120) | 87 | #define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_BASE(0) + 120) |
@@ -91,7 +96,10 @@ | |||
91 | 96 | ||
92 | #define PCM512x_CRAM_CTRL (PCM512x_PAGE_BASE(44) + 1) | 97 | #define PCM512x_CRAM_CTRL (PCM512x_PAGE_BASE(44) + 1) |
93 | 98 | ||
94 | #define PCM512x_MAX_REGISTER (PCM512x_PAGE_BASE(44) + 1) | 99 | #define PCM512x_FLEX_A (PCM512x_PAGE_BASE(253) + 63) |
100 | #define PCM512x_FLEX_B (PCM512x_PAGE_BASE(253) + 64) | ||
101 | |||
102 | #define PCM512x_MAX_REGISTER (PCM512x_PAGE_BASE(253) + 64) | ||
95 | 103 | ||
96 | /* Page 0, Register 1 - reset */ | 104 | /* Page 0, Register 1 - reset */ |
97 | #define PCM512x_RSTR (1 << 0) | 105 | #define PCM512x_RSTR (1 << 0) |
@@ -108,8 +116,8 @@ | |||
108 | #define PCM512x_RQML_SHIFT 4 | 116 | #define PCM512x_RQML_SHIFT 4 |
109 | 117 | ||
110 | /* Page 0, Register 4 - PLL */ | 118 | /* Page 0, Register 4 - PLL */ |
111 | #define PCM512x_PLCE (1 << 0) | 119 | #define PCM512x_PLLE (1 << 0) |
112 | #define PCM512x_RLCE_SHIFT 0 | 120 | #define PCM512x_PLLE_SHIFT 0 |
113 | #define PCM512x_PLCK (1 << 4) | 121 | #define PCM512x_PLCK (1 << 4) |
114 | #define PCM512x_PLCK_SHIFT 4 | 122 | #define PCM512x_PLCK_SHIFT 4 |
115 | 123 | ||
@@ -119,8 +127,66 @@ | |||
119 | #define PCM512x_DEMP (1 << 4) | 127 | #define PCM512x_DEMP (1 << 4) |
120 | #define PCM512x_DEMP_SHIFT 4 | 128 | #define PCM512x_DEMP_SHIFT 4 |
121 | 129 | ||
130 | /* Page 0, Register 8 - GPIO output enable */ | ||
131 | #define PCM512x_G1OE (1 << 0) | ||
132 | #define PCM512x_G2OE (1 << 1) | ||
133 | #define PCM512x_G3OE (1 << 2) | ||
134 | #define PCM512x_G4OE (1 << 3) | ||
135 | #define PCM512x_G5OE (1 << 4) | ||
136 | #define PCM512x_G6OE (1 << 5) | ||
137 | |||
138 | /* Page 0, Register 9 - BCK, LRCLK configuration */ | ||
139 | #define PCM512x_LRKO (1 << 0) | ||
140 | #define PCM512x_LRKO_SHIFT 0 | ||
141 | #define PCM512x_BCKO (1 << 4) | ||
142 | #define PCM512x_BCKO_SHIFT 4 | ||
143 | #define PCM512x_BCKP (1 << 5) | ||
144 | #define PCM512x_BCKP_SHIFT 5 | ||
145 | |||
146 | /* Page 0, Register 12 - Master mode BCK, LRCLK reset */ | ||
147 | #define PCM512x_RLRK (1 << 0) | ||
148 | #define PCM512x_RLRK_SHIFT 0 | ||
149 | #define PCM512x_RBCK (1 << 1) | ||
150 | #define PCM512x_RBCK_SHIFT 1 | ||
151 | |||
122 | /* Page 0, Register 13 - PLL reference */ | 152 | /* Page 0, Register 13 - PLL reference */ |
123 | #define PCM512x_SREF (1 << 4) | 153 | #define PCM512x_SREF (7 << 4) |
154 | #define PCM512x_SREF_SHIFT 4 | ||
155 | #define PCM512x_SREF_SCK (0 << 4) | ||
156 | #define PCM512x_SREF_BCK (1 << 4) | ||
157 | #define PCM512x_SREF_GPIO (3 << 4) | ||
158 | |||
159 | /* Page 0, Register 14 - DAC reference */ | ||
160 | #define PCM512x_SDAC (7 << 4) | ||
161 | #define PCM512x_SDAC_SHIFT 4 | ||
162 | #define PCM512x_SDAC_MCK (0 << 4) | ||
163 | #define PCM512x_SDAC_PLL (1 << 4) | ||
164 | #define PCM512x_SDAC_SCK (3 << 4) | ||
165 | #define PCM512x_SDAC_BCK (4 << 4) | ||
166 | #define PCM512x_SDAC_GPIO (5 << 4) | ||
167 | |||
168 | /* Page 0, Register 16, 18 - GPIO source for DAC, PLL */ | ||
169 | #define PCM512x_GREF (7 << 0) | ||
170 | #define PCM512x_GREF_SHIFT 0 | ||
171 | #define PCM512x_GREF_GPIO1 (0 << 0) | ||
172 | #define PCM512x_GREF_GPIO2 (1 << 0) | ||
173 | #define PCM512x_GREF_GPIO3 (2 << 0) | ||
174 | #define PCM512x_GREF_GPIO4 (3 << 0) | ||
175 | #define PCM512x_GREF_GPIO5 (4 << 0) | ||
176 | #define PCM512x_GREF_GPIO6 (5 << 0) | ||
177 | |||
178 | /* Page 0, Register 19 - synchronize */ | ||
179 | #define PCM512x_RQSY (1 << 0) | ||
180 | #define PCM512x_RQSY_RESUME (0 << 0) | ||
181 | #define PCM512x_RQSY_HALT (1 << 0) | ||
182 | |||
183 | /* Page 0, Register 34 - fs speed mode */ | ||
184 | #define PCM512x_FSSP (3 << 0) | ||
185 | #define PCM512x_FSSP_SHIFT 0 | ||
186 | #define PCM512x_FSSP_48KHZ (0 << 0) | ||
187 | #define PCM512x_FSSP_96KHZ (1 << 0) | ||
188 | #define PCM512x_FSSP_192KHZ (2 << 0) | ||
189 | #define PCM512x_FSSP_384KHZ (3 << 0) | ||
124 | 190 | ||
125 | /* Page 0, Register 37 - Error detection */ | 191 | /* Page 0, Register 37 - Error detection */ |
126 | #define PCM512x_IPLK (1 << 0) | 192 | #define PCM512x_IPLK (1 << 0) |
@@ -131,6 +197,20 @@ | |||
131 | #define PCM512x_IDBK (1 << 5) | 197 | #define PCM512x_IDBK (1 << 5) |
132 | #define PCM512x_IDFS (1 << 6) | 198 | #define PCM512x_IDFS (1 << 6) |
133 | 199 | ||
200 | /* Page 0, Register 40 - I2S configuration */ | ||
201 | #define PCM512x_ALEN (3 << 0) | ||
202 | #define PCM512x_ALEN_SHIFT 0 | ||
203 | #define PCM512x_ALEN_16 (0 << 0) | ||
204 | #define PCM512x_ALEN_20 (1 << 0) | ||
205 | #define PCM512x_ALEN_24 (2 << 0) | ||
206 | #define PCM512x_ALEN_32 (3 << 0) | ||
207 | #define PCM512x_AFMT (3 << 4) | ||
208 | #define PCM512x_AFMT_SHIFT 4 | ||
209 | #define PCM512x_AFMT_I2S (0 << 4) | ||
210 | #define PCM512x_AFMT_DSP (1 << 4) | ||
211 | #define PCM512x_AFMT_RTJ (2 << 4) | ||
212 | #define PCM512x_AFMT_LTJ (3 << 4) | ||
213 | |||
134 | /* Page 0, Register 42 - DAC routing */ | 214 | /* Page 0, Register 42 - DAC routing */ |
135 | #define PCM512x_AUPR_SHIFT 0 | 215 | #define PCM512x_AUPR_SHIFT 0 |
136 | #define PCM512x_AUPL_SHIFT 4 | 216 | #define PCM512x_AUPL_SHIFT 4 |
@@ -152,7 +232,26 @@ | |||
152 | /* Page 0, Register 65 - Digital mute enables */ | 232 | /* Page 0, Register 65 - Digital mute enables */ |
153 | #define PCM512x_ACTL_SHIFT 2 | 233 | #define PCM512x_ACTL_SHIFT 2 |
154 | #define PCM512x_AMLE_SHIFT 1 | 234 | #define PCM512x_AMLE_SHIFT 1 |
155 | #define PCM512x_AMLR_SHIFT 0 | 235 | #define PCM512x_AMRE_SHIFT 0 |
236 | |||
237 | /* Page 0, Register 80-85, GPIO output selection */ | ||
238 | #define PCM512x_GxSL (31 << 0) | ||
239 | #define PCM512x_GxSL_SHIFT 0 | ||
240 | #define PCM512x_GxSL_OFF (0 << 0) | ||
241 | #define PCM512x_GxSL_DSP (1 << 0) | ||
242 | #define PCM512x_GxSL_REG (2 << 0) | ||
243 | #define PCM512x_GxSL_AMUTB (3 << 0) | ||
244 | #define PCM512x_GxSL_AMUTL (4 << 0) | ||
245 | #define PCM512x_GxSL_AMUTR (5 << 0) | ||
246 | #define PCM512x_GxSL_CLKI (6 << 0) | ||
247 | #define PCM512x_GxSL_SDOUT (7 << 0) | ||
248 | #define PCM512x_GxSL_ANMUL (8 << 0) | ||
249 | #define PCM512x_GxSL_ANMUR (9 << 0) | ||
250 | #define PCM512x_GxSL_PLLLK (10 << 0) | ||
251 | #define PCM512x_GxSL_CPCLK (11 << 0) | ||
252 | #define PCM512x_GxSL_UV0_7 (14 << 0) | ||
253 | #define PCM512x_GxSL_UV0_3 (15 << 0) | ||
254 | #define PCM512x_GxSL_PLLCK (16 << 0) | ||
156 | 255 | ||
157 | /* Page 1, Register 2 - analog volume control */ | 256 | /* Page 1, Register 2 - analog volume control */ |
158 | #define PCM512x_RAGN_SHIFT 0 | 257 | #define PCM512x_RAGN_SHIFT 0 |
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 1d1c7f8a9af2..f374840a5a7c 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "rt286.h" | 34 | #include "rt286.h" |
35 | 35 | ||
36 | #define RT286_VENDOR_ID 0x10ec0286 | 36 | #define RT286_VENDOR_ID 0x10ec0286 |
37 | #define RT288_VENDOR_ID 0x10ec0288 | ||
37 | 38 | ||
38 | struct rt286_priv { | 39 | struct rt286_priv { |
39 | struct regmap *regmap; | 40 | struct regmap *regmap; |
@@ -305,6 +306,8 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) | |||
305 | *hp = false; | 306 | *hp = false; |
306 | *mic = false; | 307 | *mic = false; |
307 | 308 | ||
309 | if (!rt286->codec) | ||
310 | return -EINVAL; | ||
308 | if (rt286->pdata.cbj_en) { | 311 | if (rt286->pdata.cbj_en) { |
309 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); | 312 | regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf); |
310 | *hp = buf & 0x80000000; | 313 | *hp = buf & 0x80000000; |
@@ -403,7 +406,8 @@ EXPORT_SYMBOL_GPL(rt286_mic_detect); | |||
403 | static int is_mclk_mode(struct snd_soc_dapm_widget *source, | 406 | static int is_mclk_mode(struct snd_soc_dapm_widget *source, |
404 | struct snd_soc_dapm_widget *sink) | 407 | struct snd_soc_dapm_widget *sink) |
405 | { | 408 | { |
406 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(source->codec); | 409 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
410 | struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); | ||
407 | 411 | ||
408 | if (rt286->clk_id == RT286_SCLK_S_MCLK) | 412 | if (rt286->clk_id == RT286_SCLK_S_MCLK) |
409 | return 1; | 413 | return 1; |
@@ -417,6 +421,8 @@ static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); | |||
417 | static const struct snd_kcontrol_new rt286_snd_controls[] = { | 421 | static const struct snd_kcontrol_new rt286_snd_controls[] = { |
418 | SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT286_DACL_GAIN, | 422 | SOC_DOUBLE_R_TLV("DAC0 Playback Volume", RT286_DACL_GAIN, |
419 | RT286_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv), | 423 | RT286_DACR_GAIN, 0, 0x7f, 0, out_vol_tlv), |
424 | SOC_DOUBLE_R("ADC0 Capture Switch", RT286_ADCL_GAIN, | ||
425 | RT286_ADCR_GAIN, 7, 1, 1), | ||
420 | SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT286_ADCL_GAIN, | 426 | SOC_DOUBLE_R_TLV("ADC0 Capture Volume", RT286_ADCL_GAIN, |
421 | RT286_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv), | 427 | RT286_ADCR_GAIN, 0, 0x7f, 0, out_vol_tlv), |
422 | SOC_SINGLE_TLV("AMIC Volume", RT286_MIC_GAIN, | 428 | SOC_SINGLE_TLV("AMIC Volume", RT286_MIC_GAIN, |
@@ -500,7 +506,7 @@ SOC_DAPM_ENUM("SPO source", rt286_spo_enum); | |||
500 | static int rt286_spk_event(struct snd_soc_dapm_widget *w, | 506 | static int rt286_spk_event(struct snd_soc_dapm_widget *w, |
501 | struct snd_kcontrol *kcontrol, int event) | 507 | struct snd_kcontrol *kcontrol, int event) |
502 | { | 508 | { |
503 | struct snd_soc_codec *codec = w->codec; | 509 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
504 | 510 | ||
505 | switch (event) { | 511 | switch (event) { |
506 | case SND_SOC_DAPM_POST_PMU: | 512 | case SND_SOC_DAPM_POST_PMU: |
@@ -522,7 +528,7 @@ static int rt286_spk_event(struct snd_soc_dapm_widget *w, | |||
522 | static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w, | 528 | static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w, |
523 | struct snd_kcontrol *kcontrol, int event) | 529 | struct snd_kcontrol *kcontrol, int event) |
524 | { | 530 | { |
525 | struct snd_soc_codec *codec = w->codec; | 531 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
526 | 532 | ||
527 | switch (event) { | 533 | switch (event) { |
528 | case SND_SOC_DAPM_POST_PMU: | 534 | case SND_SOC_DAPM_POST_PMU: |
@@ -538,36 +544,10 @@ static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w, | |||
538 | return 0; | 544 | return 0; |
539 | } | 545 | } |
540 | 546 | ||
541 | static int rt286_adc_event(struct snd_soc_dapm_widget *w, | ||
542 | struct snd_kcontrol *kcontrol, int event) | ||
543 | { | ||
544 | struct snd_soc_codec *codec = w->codec; | ||
545 | unsigned int nid; | ||
546 | |||
547 | nid = (w->reg >> 20) & 0xff; | ||
548 | |||
549 | switch (event) { | ||
550 | case SND_SOC_DAPM_POST_PMU: | ||
551 | snd_soc_update_bits(codec, | ||
552 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), | ||
553 | 0x7080, 0x7000); | ||
554 | break; | ||
555 | case SND_SOC_DAPM_PRE_PMD: | ||
556 | snd_soc_update_bits(codec, | ||
557 | VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, nid, 0), | ||
558 | 0x7080, 0x7080); | ||
559 | break; | ||
560 | default: | ||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | static int rt286_vref_event(struct snd_soc_dapm_widget *w, | 547 | static int rt286_vref_event(struct snd_soc_dapm_widget *w, |
568 | struct snd_kcontrol *kcontrol, int event) | 548 | struct snd_kcontrol *kcontrol, int event) |
569 | { | 549 | { |
570 | struct snd_soc_codec *codec = w->codec; | 550 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
571 | 551 | ||
572 | switch (event) { | 552 | switch (event) { |
573 | case SND_SOC_DAPM_PRE_PMU: | 553 | case SND_SOC_DAPM_PRE_PMU: |
@@ -585,7 +565,7 @@ static int rt286_vref_event(struct snd_soc_dapm_widget *w, | |||
585 | static int rt286_ldo2_event(struct snd_soc_dapm_widget *w, | 565 | static int rt286_ldo2_event(struct snd_soc_dapm_widget *w, |
586 | struct snd_kcontrol *kcontrol, int event) | 566 | struct snd_kcontrol *kcontrol, int event) |
587 | { | 567 | { |
588 | struct snd_soc_codec *codec = w->codec; | 568 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
589 | 569 | ||
590 | switch (event) { | 570 | switch (event) { |
591 | case SND_SOC_DAPM_POST_PMU: | 571 | case SND_SOC_DAPM_POST_PMU: |
@@ -604,7 +584,7 @@ static int rt286_ldo2_event(struct snd_soc_dapm_widget *w, | |||
604 | static int rt286_mic1_event(struct snd_soc_dapm_widget *w, | 584 | static int rt286_mic1_event(struct snd_soc_dapm_widget *w, |
605 | struct snd_kcontrol *kcontrol, int event) | 585 | struct snd_kcontrol *kcontrol, int event) |
606 | { | 586 | { |
607 | struct snd_soc_codec *codec = w->codec; | 587 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
608 | 588 | ||
609 | switch (event) { | 589 | switch (event) { |
610 | case SND_SOC_DAPM_PRE_PMU: | 590 | case SND_SOC_DAPM_PRE_PMU: |
@@ -667,12 +647,10 @@ static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = { | |||
667 | SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), | 647 | SND_SOC_DAPM_ADC("ADC 1", NULL, SND_SOC_NOPM, 0, 0), |
668 | 648 | ||
669 | /* ADC Mux */ | 649 | /* ADC Mux */ |
670 | SND_SOC_DAPM_MUX_E("ADC 0 Mux", RT286_SET_POWER(RT286_ADC_IN1), 0, 1, | 650 | SND_SOC_DAPM_MUX("ADC 0 Mux", RT286_SET_POWER(RT286_ADC_IN1), 0, 1, |
671 | &rt286_adc0_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD | | 651 | &rt286_adc0_mux), |
672 | SND_SOC_DAPM_POST_PMU), | 652 | SND_SOC_DAPM_MUX("ADC 1 Mux", RT286_SET_POWER(RT286_ADC_IN2), 0, 1, |
673 | SND_SOC_DAPM_MUX_E("ADC 1 Mux", RT286_SET_POWER(RT286_ADC_IN2), 0, 1, | 653 | &rt286_adc1_mux), |
674 | &rt286_adc1_mux, rt286_adc_event, SND_SOC_DAPM_PRE_PMD | | ||
675 | SND_SOC_DAPM_POST_PMU), | ||
676 | 654 | ||
677 | /* Audio Interface */ | 655 | /* Audio Interface */ |
678 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | 656 | SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), |
@@ -1194,6 +1172,7 @@ static const struct regmap_config rt286_regmap = { | |||
1194 | 1172 | ||
1195 | static const struct i2c_device_id rt286_i2c_id[] = { | 1173 | static const struct i2c_device_id rt286_i2c_id[] = { |
1196 | {"rt286", 0}, | 1174 | {"rt286", 0}, |
1175 | {"rt288", 0}, | ||
1197 | {} | 1176 | {} |
1198 | }; | 1177 | }; |
1199 | MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); | 1178 | MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); |
@@ -1214,6 +1193,17 @@ static struct dmi_system_id force_combo_jack_table[] = { | |||
1214 | { } | 1193 | { } |
1215 | }; | 1194 | }; |
1216 | 1195 | ||
1196 | static struct dmi_system_id dmi_dell_dino[] = { | ||
1197 | { | ||
1198 | .ident = "Dell Dino", | ||
1199 | .matches = { | ||
1200 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
1201 | DMI_MATCH(DMI_BOARD_NAME, "0144P8") | ||
1202 | } | ||
1203 | }, | ||
1204 | { } | ||
1205 | }; | ||
1206 | |||
1217 | static int rt286_i2c_probe(struct i2c_client *i2c, | 1207 | static int rt286_i2c_probe(struct i2c_client *i2c, |
1218 | const struct i2c_device_id *id) | 1208 | const struct i2c_device_id *id) |
1219 | { | 1209 | { |
@@ -1236,7 +1226,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1236 | 1226 | ||
1237 | regmap_read(rt286->regmap, | 1227 | regmap_read(rt286->regmap, |
1238 | RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret); | 1228 | RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &ret); |
1239 | if (ret != RT286_VENDOR_ID) { | 1229 | if (ret != RT286_VENDOR_ID && ret != RT288_VENDOR_ID) { |
1240 | dev_err(&i2c->dev, | 1230 | dev_err(&i2c->dev, |
1241 | "Device with ID register %x is not rt286\n", ret); | 1231 | "Device with ID register %x is not rt286\n", ret); |
1242 | return -ENODEV; | 1232 | return -ENODEV; |
@@ -1249,7 +1239,8 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1249 | if (pdata) | 1239 | if (pdata) |
1250 | rt286->pdata = *pdata; | 1240 | rt286->pdata = *pdata; |
1251 | 1241 | ||
1252 | if (dmi_check_system(force_combo_jack_table)) | 1242 | if (dmi_check_system(force_combo_jack_table) || |
1243 | dmi_check_system(dmi_dell_dino)) | ||
1253 | rt286->pdata.cbj_en = true; | 1244 | rt286->pdata.cbj_en = true; |
1254 | 1245 | ||
1255 | regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); | 1246 | regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); |
@@ -1288,6 +1279,17 @@ static int rt286_i2c_probe(struct i2c_client *i2c, | |||
1288 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); | 1279 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); |
1289 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); | 1280 | regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); |
1290 | 1281 | ||
1282 | if (dmi_check_system(dmi_dell_dino)) { | ||
1283 | regmap_update_bits(rt286->regmap, | ||
1284 | RT286_SET_GPIO_MASK, 0x40, 0x40); | ||
1285 | regmap_update_bits(rt286->regmap, | ||
1286 | RT286_SET_GPIO_DIRECTION, 0x40, 0x40); | ||
1287 | regmap_update_bits(rt286->regmap, | ||
1288 | RT286_SET_GPIO_DATA, 0x40, 0x40); | ||
1289 | regmap_update_bits(rt286->regmap, | ||
1290 | RT286_GPIO_CTRL, 0xc, 0x8); | ||
1291 | } | ||
1292 | |||
1291 | if (rt286->i2c->irq) { | 1293 | if (rt286->i2c->irq) { |
1292 | ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq, | 1294 | ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq, |
1293 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286); | 1295 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286); |
diff --git a/sound/soc/codecs/rt286.h b/sound/soc/codecs/rt286.h index b539b7320a79..7130edb152ef 100644 --- a/sound/soc/codecs/rt286.h +++ b/sound/soc/codecs/rt286.h | |||
@@ -117,6 +117,12 @@ | |||
117 | VERB_CMD(AC_VERB_SET_COEF_INDEX, RT286_VENDOR_REGISTERS, 0) | 117 | VERB_CMD(AC_VERB_SET_COEF_INDEX, RT286_VENDOR_REGISTERS, 0) |
118 | #define RT286_PROC_COEF\ | 118 | #define RT286_PROC_COEF\ |
119 | VERB_CMD(AC_VERB_SET_PROC_COEF, RT286_VENDOR_REGISTERS, 0) | 119 | VERB_CMD(AC_VERB_SET_PROC_COEF, RT286_VENDOR_REGISTERS, 0) |
120 | #define RT286_SET_GPIO_MASK\ | ||
121 | VERB_CMD(AC_VERB_SET_GPIO_MASK, RT286_AUDIO_FUNCTION_GROUP, 0) | ||
122 | #define RT286_SET_GPIO_DIRECTION\ | ||
123 | VERB_CMD(AC_VERB_SET_GPIO_DIRECTION, RT286_AUDIO_FUNCTION_GROUP, 0) | ||
124 | #define RT286_SET_GPIO_DATA\ | ||
125 | VERB_CMD(AC_VERB_SET_GPIO_DATA, RT286_AUDIO_FUNCTION_GROUP, 0) | ||
120 | 126 | ||
121 | /* Index registers */ | 127 | /* Index registers */ |
122 | #define RT286_A_BIAS_CTRL1 0x01 | 128 | #define RT286_A_BIAS_CTRL1 0x01 |
@@ -131,6 +137,7 @@ | |||
131 | #define RT286_POWER_CTRL3 0x0f | 137 | #define RT286_POWER_CTRL3 0x0f |
132 | #define RT286_MIC1_DET_CTRL 0x19 | 138 | #define RT286_MIC1_DET_CTRL 0x19 |
133 | #define RT286_MISC_CTRL1 0x20 | 139 | #define RT286_MISC_CTRL1 0x20 |
140 | #define RT286_GPIO_CTRL 0x29 | ||
134 | #define RT286_IRQ_CTRL 0x33 | 141 | #define RT286_IRQ_CTRL 0x33 |
135 | #define RT286_PLL_CTRL1 0x49 | 142 | #define RT286_PLL_CTRL1 0x49 |
136 | #define RT286_CBJ_CTRL1 0x4f | 143 | #define RT286_CBJ_CTRL1 0x4f |
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 6d7b7ca7d530..c61852742ee3 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c | |||
@@ -287,70 +287,78 @@ static const struct snd_kcontrol_new rt5631_snd_controls[] = { | |||
287 | static int check_sysclk1_source(struct snd_soc_dapm_widget *source, | 287 | static int check_sysclk1_source(struct snd_soc_dapm_widget *source, |
288 | struct snd_soc_dapm_widget *sink) | 288 | struct snd_soc_dapm_widget *sink) |
289 | { | 289 | { |
290 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
290 | unsigned int reg; | 291 | unsigned int reg; |
291 | 292 | ||
292 | reg = snd_soc_read(source->codec, RT5631_GLOBAL_CLK_CTRL); | 293 | reg = snd_soc_read(codec, RT5631_GLOBAL_CLK_CTRL); |
293 | return reg & RT5631_SYSCLK_SOUR_SEL_PLL; | 294 | return reg & RT5631_SYSCLK_SOUR_SEL_PLL; |
294 | } | 295 | } |
295 | 296 | ||
296 | static int check_dmic_used(struct snd_soc_dapm_widget *source, | 297 | static int check_dmic_used(struct snd_soc_dapm_widget *source, |
297 | struct snd_soc_dapm_widget *sink) | 298 | struct snd_soc_dapm_widget *sink) |
298 | { | 299 | { |
299 | struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(source->codec); | 300 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
301 | struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); | ||
300 | return rt5631->dmic_used_flag; | 302 | return rt5631->dmic_used_flag; |
301 | } | 303 | } |
302 | 304 | ||
303 | static int check_dacl_to_outmixl(struct snd_soc_dapm_widget *source, | 305 | static int check_dacl_to_outmixl(struct snd_soc_dapm_widget *source, |
304 | struct snd_soc_dapm_widget *sink) | 306 | struct snd_soc_dapm_widget *sink) |
305 | { | 307 | { |
308 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
306 | unsigned int reg; | 309 | unsigned int reg; |
307 | 310 | ||
308 | reg = snd_soc_read(source->codec, RT5631_OUTMIXER_L_CTRL); | 311 | reg = snd_soc_read(codec, RT5631_OUTMIXER_L_CTRL); |
309 | return !(reg & RT5631_M_DAC_L_TO_OUTMIXER_L); | 312 | return !(reg & RT5631_M_DAC_L_TO_OUTMIXER_L); |
310 | } | 313 | } |
311 | 314 | ||
312 | static int check_dacr_to_outmixr(struct snd_soc_dapm_widget *source, | 315 | static int check_dacr_to_outmixr(struct snd_soc_dapm_widget *source, |
313 | struct snd_soc_dapm_widget *sink) | 316 | struct snd_soc_dapm_widget *sink) |
314 | { | 317 | { |
318 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
315 | unsigned int reg; | 319 | unsigned int reg; |
316 | 320 | ||
317 | reg = snd_soc_read(source->codec, RT5631_OUTMIXER_R_CTRL); | 321 | reg = snd_soc_read(codec, RT5631_OUTMIXER_R_CTRL); |
318 | return !(reg & RT5631_M_DAC_R_TO_OUTMIXER_R); | 322 | return !(reg & RT5631_M_DAC_R_TO_OUTMIXER_R); |
319 | } | 323 | } |
320 | 324 | ||
321 | static int check_dacl_to_spkmixl(struct snd_soc_dapm_widget *source, | 325 | static int check_dacl_to_spkmixl(struct snd_soc_dapm_widget *source, |
322 | struct snd_soc_dapm_widget *sink) | 326 | struct snd_soc_dapm_widget *sink) |
323 | { | 327 | { |
328 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
324 | unsigned int reg; | 329 | unsigned int reg; |
325 | 330 | ||
326 | reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL); | 331 | reg = snd_soc_read(codec, RT5631_SPK_MIXER_CTRL); |
327 | return !(reg & RT5631_M_DAC_L_TO_SPKMIXER_L); | 332 | return !(reg & RT5631_M_DAC_L_TO_SPKMIXER_L); |
328 | } | 333 | } |
329 | 334 | ||
330 | static int check_dacr_to_spkmixr(struct snd_soc_dapm_widget *source, | 335 | static int check_dacr_to_spkmixr(struct snd_soc_dapm_widget *source, |
331 | struct snd_soc_dapm_widget *sink) | 336 | struct snd_soc_dapm_widget *sink) |
332 | { | 337 | { |
338 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
333 | unsigned int reg; | 339 | unsigned int reg; |
334 | 340 | ||
335 | reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL); | 341 | reg = snd_soc_read(codec, RT5631_SPK_MIXER_CTRL); |
336 | return !(reg & RT5631_M_DAC_R_TO_SPKMIXER_R); | 342 | return !(reg & RT5631_M_DAC_R_TO_SPKMIXER_R); |
337 | } | 343 | } |
338 | 344 | ||
339 | static int check_adcl_select(struct snd_soc_dapm_widget *source, | 345 | static int check_adcl_select(struct snd_soc_dapm_widget *source, |
340 | struct snd_soc_dapm_widget *sink) | 346 | struct snd_soc_dapm_widget *sink) |
341 | { | 347 | { |
348 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
342 | unsigned int reg; | 349 | unsigned int reg; |
343 | 350 | ||
344 | reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER); | 351 | reg = snd_soc_read(codec, RT5631_ADC_REC_MIXER); |
345 | return !(reg & RT5631_M_MIC1_TO_RECMIXER_L); | 352 | return !(reg & RT5631_M_MIC1_TO_RECMIXER_L); |
346 | } | 353 | } |
347 | 354 | ||
348 | static int check_adcr_select(struct snd_soc_dapm_widget *source, | 355 | static int check_adcr_select(struct snd_soc_dapm_widget *source, |
349 | struct snd_soc_dapm_widget *sink) | 356 | struct snd_soc_dapm_widget *sink) |
350 | { | 357 | { |
358 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
351 | unsigned int reg; | 359 | unsigned int reg; |
352 | 360 | ||
353 | reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER); | 361 | reg = snd_soc_read(codec, RT5631_ADC_REC_MIXER); |
354 | return !(reg & RT5631_M_MIC2_TO_RECMIXER_R); | 362 | return !(reg & RT5631_M_MIC2_TO_RECMIXER_R); |
355 | } | 363 | } |
356 | 364 | ||
@@ -556,7 +564,7 @@ static void depop_seq_mute_stage(struct snd_soc_codec *codec, int enable) | |||
556 | static int hp_event(struct snd_soc_dapm_widget *w, | 564 | static int hp_event(struct snd_soc_dapm_widget *w, |
557 | struct snd_kcontrol *kcontrol, int event) | 565 | struct snd_kcontrol *kcontrol, int event) |
558 | { | 566 | { |
559 | struct snd_soc_codec *codec = w->codec; | 567 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
560 | struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); | 568 | struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); |
561 | 569 | ||
562 | switch (event) { | 570 | switch (event) { |
@@ -590,7 +598,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, | |||
590 | static int set_dmic_params(struct snd_soc_dapm_widget *w, | 598 | static int set_dmic_params(struct snd_soc_dapm_widget *w, |
591 | struct snd_kcontrol *kcontrol, int event) | 599 | struct snd_kcontrol *kcontrol, int event) |
592 | { | 600 | { |
593 | struct snd_soc_codec *codec = w->codec; | 601 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
594 | struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); | 602 | struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); |
595 | 603 | ||
596 | switch (rt5631->rx_rate) { | 604 | switch (rt5631->rx_rate) { |
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 1ff726c29249..178e55d4d481 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c | |||
@@ -458,7 +458,7 @@ static const struct snd_kcontrol_new rt5640_specific_snd_controls[] = { | |||
458 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, | 458 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, |
459 | struct snd_kcontrol *kcontrol, int event) | 459 | struct snd_kcontrol *kcontrol, int event) |
460 | { | 460 | { |
461 | struct snd_soc_codec *codec = w->codec; | 461 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
462 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | 462 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); |
463 | int idx = -EINVAL; | 463 | int idx = -EINVAL; |
464 | 464 | ||
@@ -475,9 +475,10 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
475 | static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, | 475 | static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, |
476 | struct snd_soc_dapm_widget *sink) | 476 | struct snd_soc_dapm_widget *sink) |
477 | { | 477 | { |
478 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
478 | unsigned int val; | 479 | unsigned int val; |
479 | 480 | ||
480 | val = snd_soc_read(source->codec, RT5640_GLB_CLK); | 481 | val = snd_soc_read(codec, RT5640_GLB_CLK); |
481 | val &= RT5640_SCLK_SRC_MASK; | 482 | val &= RT5640_SCLK_SRC_MASK; |
482 | if (val == RT5640_SCLK_SRC_PLL1) | 483 | if (val == RT5640_SCLK_SRC_PLL1) |
483 | return 1; | 484 | return 1; |
@@ -963,7 +964,7 @@ static void rt5640_pmu_depop(struct snd_soc_codec *codec) | |||
963 | static int rt5640_hp_event(struct snd_soc_dapm_widget *w, | 964 | static int rt5640_hp_event(struct snd_soc_dapm_widget *w, |
964 | struct snd_kcontrol *kcontrol, int event) | 965 | struct snd_kcontrol *kcontrol, int event) |
965 | { | 966 | { |
966 | struct snd_soc_codec *codec = w->codec; | 967 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
967 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | 968 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); |
968 | 969 | ||
969 | switch (event) { | 970 | switch (event) { |
@@ -987,7 +988,7 @@ static int rt5640_hp_event(struct snd_soc_dapm_widget *w, | |||
987 | static int rt5640_hp_power_event(struct snd_soc_dapm_widget *w, | 988 | static int rt5640_hp_power_event(struct snd_soc_dapm_widget *w, |
988 | struct snd_kcontrol *kcontrol, int event) | 989 | struct snd_kcontrol *kcontrol, int event) |
989 | { | 990 | { |
990 | struct snd_soc_codec *codec = w->codec; | 991 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
991 | 992 | ||
992 | switch (event) { | 993 | switch (event) { |
993 | case SND_SOC_DAPM_POST_PMU: | 994 | case SND_SOC_DAPM_POST_PMU: |
@@ -1003,7 +1004,7 @@ static int rt5640_hp_power_event(struct snd_soc_dapm_widget *w, | |||
1003 | static int rt5640_hp_post_event(struct snd_soc_dapm_widget *w, | 1004 | static int rt5640_hp_post_event(struct snd_soc_dapm_widget *w, |
1004 | struct snd_kcontrol *kcontrol, int event) | 1005 | struct snd_kcontrol *kcontrol, int event) |
1005 | { | 1006 | { |
1006 | struct snd_soc_codec *codec = w->codec; | 1007 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1007 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | 1008 | struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); |
1008 | 1009 | ||
1009 | switch (event) { | 1010 | switch (event) { |
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 27141e2df878..c9a4c5be083b 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "rt5645.h" | 31 | #include "rt5645.h" |
32 | 32 | ||
33 | #define RT5645_DEVICE_ID 0x6308 | 33 | #define RT5645_DEVICE_ID 0x6308 |
34 | #define RT5650_DEVICE_ID 0x6419 | ||
34 | 35 | ||
35 | #define RT5645_PR_RANGE_BASE (0xff + 1) | 36 | #define RT5645_PR_RANGE_BASE (0xff + 1) |
36 | #define RT5645_PR_SPACING 0x100 | 37 | #define RT5645_PR_SPACING 0x100 |
@@ -59,6 +60,10 @@ static const struct reg_default init_list[] = { | |||
59 | }; | 60 | }; |
60 | #define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list) | 61 | #define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list) |
61 | 62 | ||
63 | static const struct reg_default rt5650_init_list[] = { | ||
64 | {0xf6, 0x0100}, | ||
65 | }; | ||
66 | |||
62 | static const struct reg_default rt5645_reg[] = { | 67 | static const struct reg_default rt5645_reg[] = { |
63 | { 0x00, 0x0000 }, | 68 | { 0x00, 0x0000 }, |
64 | { 0x01, 0xc8c8 }, | 69 | { 0x01, 0xc8c8 }, |
@@ -86,6 +91,7 @@ static const struct reg_default rt5645_reg[] = { | |||
86 | { 0x2a, 0x5656 }, | 91 | { 0x2a, 0x5656 }, |
87 | { 0x2b, 0x5454 }, | 92 | { 0x2b, 0x5454 }, |
88 | { 0x2c, 0xaaa0 }, | 93 | { 0x2c, 0xaaa0 }, |
94 | { 0x2d, 0x0000 }, | ||
89 | { 0x2f, 0x1002 }, | 95 | { 0x2f, 0x1002 }, |
90 | { 0x31, 0x5000 }, | 96 | { 0x31, 0x5000 }, |
91 | { 0x32, 0x0000 }, | 97 | { 0x32, 0x0000 }, |
@@ -193,6 +199,8 @@ static const struct reg_default rt5645_reg[] = { | |||
193 | { 0xdb, 0x0003 }, | 199 | { 0xdb, 0x0003 }, |
194 | { 0xdc, 0x0049 }, | 200 | { 0xdc, 0x0049 }, |
195 | { 0xdd, 0x001b }, | 201 | { 0xdd, 0x001b }, |
202 | { 0xdf, 0x0008 }, | ||
203 | { 0xe0, 0x4000 }, | ||
196 | { 0xe6, 0x8000 }, | 204 | { 0xe6, 0x8000 }, |
197 | { 0xe7, 0x0200 }, | 205 | { 0xe7, 0x0200 }, |
198 | { 0xec, 0xb300 }, | 206 | { 0xec, 0xb300 }, |
@@ -242,6 +250,7 @@ static bool rt5645_volatile_register(struct device *dev, unsigned int reg) | |||
242 | case RT5645_IRQ_CTRL3: | 250 | case RT5645_IRQ_CTRL3: |
243 | case RT5645_INT_IRQ_ST: | 251 | case RT5645_INT_IRQ_ST: |
244 | case RT5645_IL_CMD: | 252 | case RT5645_IL_CMD: |
253 | case RT5650_4BTN_IL_CMD1: | ||
245 | case RT5645_VENDOR_ID: | 254 | case RT5645_VENDOR_ID: |
246 | case RT5645_VENDOR_ID1: | 255 | case RT5645_VENDOR_ID1: |
247 | case RT5645_VENDOR_ID2: | 256 | case RT5645_VENDOR_ID2: |
@@ -287,6 +296,7 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg) | |||
287 | case RT5645_STO_DAC_MIXER: | 296 | case RT5645_STO_DAC_MIXER: |
288 | case RT5645_MONO_DAC_MIXER: | 297 | case RT5645_MONO_DAC_MIXER: |
289 | case RT5645_DIG_MIXER: | 298 | case RT5645_DIG_MIXER: |
299 | case RT5650_A_DAC_SOUR: | ||
290 | case RT5645_DIG_INF1_DATA: | 300 | case RT5645_DIG_INF1_DATA: |
291 | case RT5645_PDM_OUT_CTRL: | 301 | case RT5645_PDM_OUT_CTRL: |
292 | case RT5645_REC_L1_MIXER: | 302 | case RT5645_REC_L1_MIXER: |
@@ -378,6 +388,8 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg) | |||
378 | case RT5645_IL_CMD: | 388 | case RT5645_IL_CMD: |
379 | case RT5645_IL_CMD2: | 389 | case RT5645_IL_CMD2: |
380 | case RT5645_IL_CMD3: | 390 | case RT5645_IL_CMD3: |
391 | case RT5650_4BTN_IL_CMD1: | ||
392 | case RT5650_4BTN_IL_CMD2: | ||
381 | case RT5645_DRC1_HL_CTRL1: | 393 | case RT5645_DRC1_HL_CTRL1: |
382 | case RT5645_DRC2_HL_CTRL1: | 394 | case RT5645_DRC2_HL_CTRL1: |
383 | case RT5645_ADC_MONO_HP_CTRL1: | 395 | case RT5645_ADC_MONO_HP_CTRL1: |
@@ -527,7 +539,7 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = { | |||
527 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, | 539 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, |
528 | struct snd_kcontrol *kcontrol, int event) | 540 | struct snd_kcontrol *kcontrol, int event) |
529 | { | 541 | { |
530 | struct snd_soc_codec *codec = w->codec; | 542 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
531 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 543 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); |
532 | int idx = -EINVAL; | 544 | int idx = -EINVAL; |
533 | 545 | ||
@@ -544,9 +556,10 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
544 | static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, | 556 | static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, |
545 | struct snd_soc_dapm_widget *sink) | 557 | struct snd_soc_dapm_widget *sink) |
546 | { | 558 | { |
559 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
547 | unsigned int val; | 560 | unsigned int val; |
548 | 561 | ||
549 | val = snd_soc_read(source->codec, RT5645_GLB_CLK); | 562 | val = snd_soc_read(codec, RT5645_GLB_CLK); |
550 | val &= RT5645_SCLK_SRC_MASK; | 563 | val &= RT5645_SCLK_SRC_MASK; |
551 | if (val == RT5645_SCLK_SRC_PLL1) | 564 | if (val == RT5645_SCLK_SRC_PLL1) |
552 | return 1; | 565 | return 1; |
@@ -557,6 +570,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, | |||
557 | static int is_using_asrc(struct snd_soc_dapm_widget *source, | 570 | static int is_using_asrc(struct snd_soc_dapm_widget *source, |
558 | struct snd_soc_dapm_widget *sink) | 571 | struct snd_soc_dapm_widget *sink) |
559 | { | 572 | { |
573 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
560 | unsigned int reg, shift, val; | 574 | unsigned int reg, shift, val; |
561 | 575 | ||
562 | switch (source->shift) { | 576 | switch (source->shift) { |
@@ -588,7 +602,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source, | |||
588 | return 0; | 602 | return 0; |
589 | } | 603 | } |
590 | 604 | ||
591 | val = (snd_soc_read(source->codec, reg) >> shift) & 0xf; | 605 | val = (snd_soc_read(codec, reg) >> shift) & 0xf; |
592 | switch (val) { | 606 | switch (val) { |
593 | case 1: | 607 | case 1: |
594 | case 2: | 608 | case 2: |
@@ -601,6 +615,87 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source, | |||
601 | 615 | ||
602 | } | 616 | } |
603 | 617 | ||
618 | /** | ||
619 | * rt5645_sel_asrc_clk_src - select ASRC clock source for a set of filters | ||
620 | * @codec: SoC audio codec device. | ||
621 | * @filter_mask: mask of filters. | ||
622 | * @clk_src: clock source | ||
623 | * | ||
624 | * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5645 can | ||
625 | * only support standard 32fs or 64fs i2s format, ASRC should be enabled to | ||
626 | * support special i2s clock format such as Intel's 100fs(100 * sampling rate). | ||
627 | * ASRC function will track i2s clock and generate a corresponding system clock | ||
628 | * for codec. This function provides an API to select the clock source for a | ||
629 | * set of filters specified by the mask. And the codec driver will turn on ASRC | ||
630 | * for these filters if ASRC is selected as their clock source. | ||
631 | */ | ||
632 | int rt5645_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
633 | unsigned int filter_mask, unsigned int clk_src) | ||
634 | { | ||
635 | unsigned int asrc2_mask = 0; | ||
636 | unsigned int asrc2_value = 0; | ||
637 | unsigned int asrc3_mask = 0; | ||
638 | unsigned int asrc3_value = 0; | ||
639 | |||
640 | switch (clk_src) { | ||
641 | case RT5645_CLK_SEL_SYS: | ||
642 | case RT5645_CLK_SEL_I2S1_ASRC: | ||
643 | case RT5645_CLK_SEL_I2S2_ASRC: | ||
644 | case RT5645_CLK_SEL_SYS2: | ||
645 | break; | ||
646 | |||
647 | default: | ||
648 | return -EINVAL; | ||
649 | } | ||
650 | |||
651 | if (filter_mask & RT5645_DA_STEREO_FILTER) { | ||
652 | asrc2_mask |= RT5645_DA_STO_CLK_SEL_MASK; | ||
653 | asrc2_value = (asrc2_value & ~RT5645_DA_STO_CLK_SEL_MASK) | ||
654 | | (clk_src << RT5645_DA_STO_CLK_SEL_SFT); | ||
655 | } | ||
656 | |||
657 | if (filter_mask & RT5645_DA_MONO_L_FILTER) { | ||
658 | asrc2_mask |= RT5645_DA_MONOL_CLK_SEL_MASK; | ||
659 | asrc2_value = (asrc2_value & ~RT5645_DA_MONOL_CLK_SEL_MASK) | ||
660 | | (clk_src << RT5645_DA_MONOL_CLK_SEL_SFT); | ||
661 | } | ||
662 | |||
663 | if (filter_mask & RT5645_DA_MONO_R_FILTER) { | ||
664 | asrc2_mask |= RT5645_DA_MONOR_CLK_SEL_MASK; | ||
665 | asrc2_value = (asrc2_value & ~RT5645_DA_MONOR_CLK_SEL_MASK) | ||
666 | | (clk_src << RT5645_DA_MONOR_CLK_SEL_SFT); | ||
667 | } | ||
668 | |||
669 | if (filter_mask & RT5645_AD_STEREO_FILTER) { | ||
670 | asrc2_mask |= RT5645_AD_STO1_CLK_SEL_MASK; | ||
671 | asrc2_value = (asrc2_value & ~RT5645_AD_STO1_CLK_SEL_MASK) | ||
672 | | (clk_src << RT5645_AD_STO1_CLK_SEL_SFT); | ||
673 | } | ||
674 | |||
675 | if (filter_mask & RT5645_AD_MONO_L_FILTER) { | ||
676 | asrc3_mask |= RT5645_AD_MONOL_CLK_SEL_MASK; | ||
677 | asrc3_value = (asrc3_value & ~RT5645_AD_MONOL_CLK_SEL_MASK) | ||
678 | | (clk_src << RT5645_AD_MONOL_CLK_SEL_SFT); | ||
679 | } | ||
680 | |||
681 | if (filter_mask & RT5645_AD_MONO_R_FILTER) { | ||
682 | asrc3_mask |= RT5645_AD_MONOR_CLK_SEL_MASK; | ||
683 | asrc3_value = (asrc3_value & ~RT5645_AD_MONOR_CLK_SEL_MASK) | ||
684 | | (clk_src << RT5645_AD_MONOR_CLK_SEL_SFT); | ||
685 | } | ||
686 | |||
687 | if (asrc2_mask) | ||
688 | snd_soc_update_bits(codec, RT5645_ASRC_2, | ||
689 | asrc2_mask, asrc2_value); | ||
690 | |||
691 | if (asrc3_mask) | ||
692 | snd_soc_update_bits(codec, RT5645_ASRC_3, | ||
693 | asrc3_mask, asrc3_value); | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | EXPORT_SYMBOL_GPL(rt5645_sel_asrc_clk_src); | ||
698 | |||
604 | /* Digital Mixer */ | 699 | /* Digital Mixer */ |
605 | static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = { | 700 | static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = { |
606 | SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER, | 701 | SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER, |
@@ -1007,6 +1102,44 @@ static SOC_ENUM_SINGLE_DECL( | |||
1007 | static const struct snd_kcontrol_new rt5645_if1_adc_in_mux = | 1102 | static const struct snd_kcontrol_new rt5645_if1_adc_in_mux = |
1008 | SOC_DAPM_ENUM("IF1 ADC IN source", rt5645_if1_adc_in_enum); | 1103 | SOC_DAPM_ENUM("IF1 ADC IN source", rt5645_if1_adc_in_enum); |
1009 | 1104 | ||
1105 | /* MX-2d [3] [2] */ | ||
1106 | static const char * const rt5650_a_dac1_src[] = { | ||
1107 | "DAC1", "Stereo DAC Mixer" | ||
1108 | }; | ||
1109 | |||
1110 | static SOC_ENUM_SINGLE_DECL( | ||
1111 | rt5650_a_dac1_l_enum, RT5650_A_DAC_SOUR, | ||
1112 | RT5650_A_DAC1_L_IN_SFT, rt5650_a_dac1_src); | ||
1113 | |||
1114 | static const struct snd_kcontrol_new rt5650_a_dac1_l_mux = | ||
1115 | SOC_DAPM_ENUM("A DAC1 L source", rt5650_a_dac1_l_enum); | ||
1116 | |||
1117 | static SOC_ENUM_SINGLE_DECL( | ||
1118 | rt5650_a_dac1_r_enum, RT5650_A_DAC_SOUR, | ||
1119 | RT5650_A_DAC1_R_IN_SFT, rt5650_a_dac1_src); | ||
1120 | |||
1121 | static const struct snd_kcontrol_new rt5650_a_dac1_r_mux = | ||
1122 | SOC_DAPM_ENUM("A DAC1 R source", rt5650_a_dac1_r_enum); | ||
1123 | |||
1124 | /* MX-2d [1] [0] */ | ||
1125 | static const char * const rt5650_a_dac2_src[] = { | ||
1126 | "Stereo DAC Mixer", "Mono DAC Mixer" | ||
1127 | }; | ||
1128 | |||
1129 | static SOC_ENUM_SINGLE_DECL( | ||
1130 | rt5650_a_dac2_l_enum, RT5650_A_DAC_SOUR, | ||
1131 | RT5650_A_DAC2_L_IN_SFT, rt5650_a_dac2_src); | ||
1132 | |||
1133 | static const struct snd_kcontrol_new rt5650_a_dac2_l_mux = | ||
1134 | SOC_DAPM_ENUM("A DAC2 L source", rt5650_a_dac2_l_enum); | ||
1135 | |||
1136 | static SOC_ENUM_SINGLE_DECL( | ||
1137 | rt5650_a_dac2_r_enum, RT5650_A_DAC_SOUR, | ||
1138 | RT5650_A_DAC2_R_IN_SFT, rt5650_a_dac2_src); | ||
1139 | |||
1140 | static const struct snd_kcontrol_new rt5650_a_dac2_r_mux = | ||
1141 | SOC_DAPM_ENUM("A DAC2 R source", rt5650_a_dac2_r_enum); | ||
1142 | |||
1010 | /* MX-2F [13:12] */ | 1143 | /* MX-2F [13:12] */ |
1011 | static const char * const rt5645_if2_adc_in_src[] = { | 1144 | static const char * const rt5645_if2_adc_in_src[] = { |
1012 | "IF_ADC1", "IF_ADC2", "VAD_ADC" | 1145 | "IF_ADC1", "IF_ADC2", "VAD_ADC" |
@@ -1144,18 +1277,23 @@ static void hp_amp_power(struct snd_soc_codec *codec, int on) | |||
1144 | static int rt5645_hp_event(struct snd_soc_dapm_widget *w, | 1277 | static int rt5645_hp_event(struct snd_soc_dapm_widget *w, |
1145 | struct snd_kcontrol *kcontrol, int event) | 1278 | struct snd_kcontrol *kcontrol, int event) |
1146 | { | 1279 | { |
1147 | struct snd_soc_codec *codec = w->codec; | 1280 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1148 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 1281 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); |
1149 | 1282 | ||
1150 | switch (event) { | 1283 | switch (event) { |
1151 | case SND_SOC_DAPM_POST_PMU: | 1284 | case SND_SOC_DAPM_POST_PMU: |
1152 | hp_amp_power(codec, 1); | 1285 | hp_amp_power(codec, 1); |
1153 | /* headphone unmute sequence */ | 1286 | /* headphone unmute sequence */ |
1154 | snd_soc_update_bits(codec, RT5645_DEPOP_M3, RT5645_CP_FQ1_MASK | | 1287 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { |
1155 | RT5645_CP_FQ2_MASK | RT5645_CP_FQ3_MASK, | 1288 | snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737); |
1156 | (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ1_SFT) | | 1289 | } else { |
1157 | (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) | | 1290 | snd_soc_update_bits(codec, RT5645_DEPOP_M3, |
1158 | (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ3_SFT)); | 1291 | RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK | |
1292 | RT5645_CP_FQ3_MASK, | ||
1293 | (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ1_SFT) | | ||
1294 | (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) | | ||
1295 | (RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ3_SFT)); | ||
1296 | } | ||
1159 | regmap_write(rt5645->regmap, | 1297 | regmap_write(rt5645->regmap, |
1160 | RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00); | 1298 | RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00); |
1161 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | 1299 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, |
@@ -1175,12 +1313,16 @@ static int rt5645_hp_event(struct snd_soc_dapm_widget *w, | |||
1175 | 1313 | ||
1176 | case SND_SOC_DAPM_PRE_PMD: | 1314 | case SND_SOC_DAPM_PRE_PMD: |
1177 | /* headphone mute sequence */ | 1315 | /* headphone mute sequence */ |
1178 | snd_soc_update_bits(codec, RT5645_DEPOP_M3, | 1316 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { |
1179 | RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK | | 1317 | snd_soc_write(codec, RT5645_DEPOP_M3, 0x0737); |
1180 | RT5645_CP_FQ3_MASK, | 1318 | } else { |
1181 | (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ1_SFT) | | 1319 | snd_soc_update_bits(codec, RT5645_DEPOP_M3, |
1182 | (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) | | 1320 | RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK | |
1183 | (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ3_SFT)); | 1321 | RT5645_CP_FQ3_MASK, |
1322 | (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ1_SFT) | | ||
1323 | (RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) | | ||
1324 | (RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ3_SFT)); | ||
1325 | } | ||
1184 | regmap_write(rt5645->regmap, | 1326 | regmap_write(rt5645->regmap, |
1185 | RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00); | 1327 | RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00); |
1186 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, | 1328 | snd_soc_update_bits(codec, RT5645_DEPOP_M1, |
@@ -1205,7 +1347,7 @@ static int rt5645_hp_event(struct snd_soc_dapm_widget *w, | |||
1205 | static int rt5645_spk_event(struct snd_soc_dapm_widget *w, | 1347 | static int rt5645_spk_event(struct snd_soc_dapm_widget *w, |
1206 | struct snd_kcontrol *kcontrol, int event) | 1348 | struct snd_kcontrol *kcontrol, int event) |
1207 | { | 1349 | { |
1208 | struct snd_soc_codec *codec = w->codec; | 1350 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1209 | 1351 | ||
1210 | switch (event) { | 1352 | switch (event) { |
1211 | case SND_SOC_DAPM_POST_PMU: | 1353 | case SND_SOC_DAPM_POST_PMU: |
@@ -1232,7 +1374,7 @@ static int rt5645_spk_event(struct snd_soc_dapm_widget *w, | |||
1232 | static int rt5645_lout_event(struct snd_soc_dapm_widget *w, | 1374 | static int rt5645_lout_event(struct snd_soc_dapm_widget *w, |
1233 | struct snd_kcontrol *kcontrol, int event) | 1375 | struct snd_kcontrol *kcontrol, int event) |
1234 | { | 1376 | { |
1235 | struct snd_soc_codec *codec = w->codec; | 1377 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1236 | 1378 | ||
1237 | switch (event) { | 1379 | switch (event) { |
1238 | case SND_SOC_DAPM_POST_PMU: | 1380 | case SND_SOC_DAPM_POST_PMU: |
@@ -1262,7 +1404,7 @@ static int rt5645_lout_event(struct snd_soc_dapm_widget *w, | |||
1262 | static int rt5645_bst2_event(struct snd_soc_dapm_widget *w, | 1404 | static int rt5645_bst2_event(struct snd_soc_dapm_widget *w, |
1263 | struct snd_kcontrol *kcontrol, int event) | 1405 | struct snd_kcontrol *kcontrol, int event) |
1264 | { | 1406 | { |
1265 | struct snd_soc_codec *codec = w->codec; | 1407 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1266 | 1408 | ||
1267 | switch (event) { | 1409 | switch (event) { |
1268 | case SND_SOC_DAPM_POST_PMU: | 1410 | case SND_SOC_DAPM_POST_PMU: |
@@ -1574,6 +1716,17 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { | |||
1574 | SND_SOC_DAPM_OUTPUT("SPOR"), | 1716 | SND_SOC_DAPM_OUTPUT("SPOR"), |
1575 | }; | 1717 | }; |
1576 | 1718 | ||
1719 | static const struct snd_soc_dapm_widget rt5650_specific_dapm_widgets[] = { | ||
1720 | SND_SOC_DAPM_MUX("A DAC1 L Mux", SND_SOC_NOPM, | ||
1721 | 0, 0, &rt5650_a_dac1_l_mux), | ||
1722 | SND_SOC_DAPM_MUX("A DAC1 R Mux", SND_SOC_NOPM, | ||
1723 | 0, 0, &rt5650_a_dac1_r_mux), | ||
1724 | SND_SOC_DAPM_MUX("A DAC2 L Mux", SND_SOC_NOPM, | ||
1725 | 0, 0, &rt5650_a_dac2_l_mux), | ||
1726 | SND_SOC_DAPM_MUX("A DAC2 R Mux", SND_SOC_NOPM, | ||
1727 | 0, 0, &rt5650_a_dac2_r_mux), | ||
1728 | }; | ||
1729 | |||
1577 | static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { | 1730 | static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { |
1578 | { "adc stereo1 filter", NULL, "ADC STO1 ASRC", is_using_asrc }, | 1731 | { "adc stereo1 filter", NULL, "ADC STO1 ASRC", is_using_asrc }, |
1579 | { "adc stereo2 filter", NULL, "ADC STO2 ASRC", is_using_asrc }, | 1732 | { "adc stereo2 filter", NULL, "ADC STO2 ASRC", is_using_asrc }, |
@@ -1779,13 +1932,9 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { | |||
1779 | { "DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" }, | 1932 | { "DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" }, |
1780 | { "DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" }, | 1933 | { "DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" }, |
1781 | 1934 | ||
1782 | { "DAC L1", NULL, "Stereo DAC MIXL" }, | ||
1783 | { "DAC L1", NULL, "PLL1", is_sys_clk_from_pll }, | 1935 | { "DAC L1", NULL, "PLL1", is_sys_clk_from_pll }, |
1784 | { "DAC R1", NULL, "Stereo DAC MIXR" }, | ||
1785 | { "DAC R1", NULL, "PLL1", is_sys_clk_from_pll }, | 1936 | { "DAC R1", NULL, "PLL1", is_sys_clk_from_pll }, |
1786 | { "DAC L2", NULL, "Mono DAC MIXL" }, | ||
1787 | { "DAC L2", NULL, "PLL1", is_sys_clk_from_pll }, | 1937 | { "DAC L2", NULL, "PLL1", is_sys_clk_from_pll }, |
1788 | { "DAC R2", NULL, "Mono DAC MIXR" }, | ||
1789 | { "DAC R2", NULL, "PLL1", is_sys_clk_from_pll }, | 1938 | { "DAC R2", NULL, "PLL1", is_sys_clk_from_pll }, |
1790 | 1939 | ||
1791 | { "SPK MIXL", "BST1 Switch", "BST1" }, | 1940 | { "SPK MIXL", "BST1 Switch", "BST1" }, |
@@ -1874,6 +2023,30 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { | |||
1874 | { "SPOR", NULL, "SPK amp" }, | 2023 | { "SPOR", NULL, "SPK amp" }, |
1875 | }; | 2024 | }; |
1876 | 2025 | ||
2026 | static const struct snd_soc_dapm_route rt5650_specific_dapm_routes[] = { | ||
2027 | { "A DAC1 L Mux", "DAC1", "DAC1 MIXL"}, | ||
2028 | { "A DAC1 L Mux", "Stereo DAC Mixer", "Stereo DAC MIXL"}, | ||
2029 | { "A DAC1 R Mux", "DAC1", "DAC1 MIXR"}, | ||
2030 | { "A DAC1 R Mux", "Stereo DAC Mixer", "Stereo DAC MIXR"}, | ||
2031 | |||
2032 | { "A DAC2 L Mux", "Stereo DAC Mixer", "Stereo DAC MIXL"}, | ||
2033 | { "A DAC2 L Mux", "Mono DAC Mixer", "Mono DAC MIXL"}, | ||
2034 | { "A DAC2 R Mux", "Stereo DAC Mixer", "Stereo DAC MIXR"}, | ||
2035 | { "A DAC2 R Mux", "Mono DAC Mixer", "Mono DAC MIXR"}, | ||
2036 | |||
2037 | { "DAC L1", NULL, "A DAC1 L Mux" }, | ||
2038 | { "DAC R1", NULL, "A DAC1 R Mux" }, | ||
2039 | { "DAC L2", NULL, "A DAC2 L Mux" }, | ||
2040 | { "DAC R2", NULL, "A DAC2 R Mux" }, | ||
2041 | }; | ||
2042 | |||
2043 | static const struct snd_soc_dapm_route rt5645_specific_dapm_routes[] = { | ||
2044 | { "DAC L1", NULL, "Stereo DAC MIXL" }, | ||
2045 | { "DAC R1", NULL, "Stereo DAC MIXR" }, | ||
2046 | { "DAC L2", NULL, "Mono DAC MIXL" }, | ||
2047 | { "DAC R2", NULL, "Mono DAC MIXR" }, | ||
2048 | }; | ||
2049 | |||
1877 | static int rt5645_hw_params(struct snd_pcm_substream *substream, | 2050 | static int rt5645_hw_params(struct snd_pcm_substream *substream, |
1878 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 2051 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
1879 | { | 2052 | { |
@@ -2293,6 +2466,22 @@ static int rt5645_probe(struct snd_soc_codec *codec) | |||
2293 | 2466 | ||
2294 | rt5645->codec = codec; | 2467 | rt5645->codec = codec; |
2295 | 2468 | ||
2469 | switch (rt5645->codec_type) { | ||
2470 | case CODEC_TYPE_RT5645: | ||
2471 | snd_soc_dapm_add_routes(&codec->dapm, | ||
2472 | rt5645_specific_dapm_routes, | ||
2473 | ARRAY_SIZE(rt5645_specific_dapm_routes)); | ||
2474 | break; | ||
2475 | case CODEC_TYPE_RT5650: | ||
2476 | snd_soc_dapm_new_controls(&codec->dapm, | ||
2477 | rt5650_specific_dapm_widgets, | ||
2478 | ARRAY_SIZE(rt5650_specific_dapm_widgets)); | ||
2479 | snd_soc_dapm_add_routes(&codec->dapm, | ||
2480 | rt5650_specific_dapm_routes, | ||
2481 | ARRAY_SIZE(rt5650_specific_dapm_routes)); | ||
2482 | break; | ||
2483 | } | ||
2484 | |||
2296 | rt5645_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2485 | rt5645_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2297 | 2486 | ||
2298 | snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200); | 2487 | snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200); |
@@ -2424,6 +2613,7 @@ static const struct regmap_config rt5645_regmap = { | |||
2424 | 2613 | ||
2425 | static const struct i2c_device_id rt5645_i2c_id[] = { | 2614 | static const struct i2c_device_id rt5645_i2c_id[] = { |
2426 | { "rt5645", 0 }, | 2615 | { "rt5645", 0 }, |
2616 | { "rt5650", 0 }, | ||
2427 | { } | 2617 | { } |
2428 | }; | 2618 | }; |
2429 | MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id); | 2619 | MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id); |
@@ -2456,9 +2646,18 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2456 | } | 2646 | } |
2457 | 2647 | ||
2458 | regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val); | 2648 | regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val); |
2459 | if (val != RT5645_DEVICE_ID) { | 2649 | |
2650 | switch (val) { | ||
2651 | case RT5645_DEVICE_ID: | ||
2652 | rt5645->codec_type = CODEC_TYPE_RT5645; | ||
2653 | break; | ||
2654 | case RT5650_DEVICE_ID: | ||
2655 | rt5645->codec_type = CODEC_TYPE_RT5650; | ||
2656 | break; | ||
2657 | default: | ||
2460 | dev_err(&i2c->dev, | 2658 | dev_err(&i2c->dev, |
2461 | "Device with ID register %x is not rt5645\n", val); | 2659 | "Device with ID register %x is not rt5645 or rt5650\n", |
2660 | val); | ||
2462 | return -ENODEV; | 2661 | return -ENODEV; |
2463 | } | 2662 | } |
2464 | 2663 | ||
@@ -2469,6 +2668,14 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2469 | if (ret != 0) | 2668 | if (ret != 0) |
2470 | dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); | 2669 | dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); |
2471 | 2670 | ||
2671 | if (rt5645->codec_type == CODEC_TYPE_RT5650) { | ||
2672 | ret = regmap_register_patch(rt5645->regmap, rt5650_init_list, | ||
2673 | ARRAY_SIZE(rt5650_init_list)); | ||
2674 | if (ret != 0) | ||
2675 | dev_warn(&i2c->dev, "Apply rt5650 patch failed: %d\n", | ||
2676 | ret); | ||
2677 | } | ||
2678 | |||
2472 | if (rt5645->pdata.in2_diff) | 2679 | if (rt5645->pdata.in2_diff) |
2473 | regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL, | 2680 | regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL, |
2474 | RT5645_IN_DF2, RT5645_IN_DF2); | 2681 | RT5645_IN_DF2, RT5645_IN_DF2); |
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h index a815e36a2bdb..dbfd98c22f4d 100644 --- a/sound/soc/codecs/rt5645.h +++ b/sound/soc/codecs/rt5645.h | |||
@@ -47,6 +47,7 @@ | |||
47 | #define RT5645_STO_DAC_MIXER 0x2a | 47 | #define RT5645_STO_DAC_MIXER 0x2a |
48 | #define RT5645_MONO_DAC_MIXER 0x2b | 48 | #define RT5645_MONO_DAC_MIXER 0x2b |
49 | #define RT5645_DIG_MIXER 0x2c | 49 | #define RT5645_DIG_MIXER 0x2c |
50 | #define RT5650_A_DAC_SOUR 0x2d | ||
50 | #define RT5645_DIG_INF1_DATA 0x2f | 51 | #define RT5645_DIG_INF1_DATA 0x2f |
51 | /* Mixer - PDM */ | 52 | /* Mixer - PDM */ |
52 | #define RT5645_PDM_OUT_CTRL 0x31 | 53 | #define RT5645_PDM_OUT_CTRL 0x31 |
@@ -150,6 +151,8 @@ | |||
150 | #define RT5645_IL_CMD 0xdb | 151 | #define RT5645_IL_CMD 0xdb |
151 | #define RT5645_IL_CMD2 0xdc | 152 | #define RT5645_IL_CMD2 0xdc |
152 | #define RT5645_IL_CMD3 0xdd | 153 | #define RT5645_IL_CMD3 0xdd |
154 | #define RT5650_4BTN_IL_CMD1 0xdf | ||
155 | #define RT5650_4BTN_IL_CMD2 0xe0 | ||
153 | #define RT5645_DRC1_HL_CTRL1 0xe7 | 156 | #define RT5645_DRC1_HL_CTRL1 0xe7 |
154 | #define RT5645_DRC2_HL_CTRL1 0xe9 | 157 | #define RT5645_DRC2_HL_CTRL1 0xe9 |
155 | #define RT5645_MUTI_DRC_CTRL1 0xea | 158 | #define RT5645_MUTI_DRC_CTRL1 0xea |
@@ -472,6 +475,12 @@ | |||
472 | #define RT5645_DAC_L2_DAC_R_VOL_MASK (0x1 << 4) | 475 | #define RT5645_DAC_L2_DAC_R_VOL_MASK (0x1 << 4) |
473 | #define RT5645_DAC_L2_DAC_R_VOL_SFT 4 | 476 | #define RT5645_DAC_L2_DAC_R_VOL_SFT 4 |
474 | 477 | ||
478 | /* Analog DAC1/2 Input Source Control (0x2d) */ | ||
479 | #define RT5650_A_DAC1_L_IN_SFT 3 | ||
480 | #define RT5650_A_DAC1_R_IN_SFT 2 | ||
481 | #define RT5650_A_DAC2_L_IN_SFT 1 | ||
482 | #define RT5650_A_DAC2_R_IN_SFT 0 | ||
483 | |||
475 | /* Digital Interface Data Control (0x2f) */ | 484 | /* Digital Interface Data Control (0x2f) */ |
476 | #define RT5645_IF1_ADC2_IN_SEL (0x1 << 15) | 485 | #define RT5645_IF1_ADC2_IN_SEL (0x1 << 15) |
477 | #define RT5645_IF1_ADC2_IN_SFT 15 | 486 | #define RT5645_IF1_ADC2_IN_SFT 15 |
@@ -1111,50 +1120,27 @@ | |||
1111 | #define RT5645_DMIC_2_M_NOR (0x0 << 8) | 1120 | #define RT5645_DMIC_2_M_NOR (0x0 << 8) |
1112 | #define RT5645_DMIC_2_M_ASYN (0x1 << 8) | 1121 | #define RT5645_DMIC_2_M_ASYN (0x1 << 8) |
1113 | 1122 | ||
1123 | /* ASRC clock source selection (0x84, 0x85) */ | ||
1124 | #define RT5645_CLK_SEL_SYS (0x0) | ||
1125 | #define RT5645_CLK_SEL_I2S1_ASRC (0x1) | ||
1126 | #define RT5645_CLK_SEL_I2S2_ASRC (0x2) | ||
1127 | #define RT5645_CLK_SEL_SYS2 (0x5) | ||
1128 | |||
1114 | /* ASRC Control 2 (0x84) */ | 1129 | /* ASRC Control 2 (0x84) */ |
1115 | #define RT5645_MDA_L_M_MASK (0x1 << 15) | 1130 | #define RT5645_DA_STO_CLK_SEL_MASK (0xf << 12) |
1116 | #define RT5645_MDA_L_M_SFT 15 | 1131 | #define RT5645_DA_STO_CLK_SEL_SFT 12 |
1117 | #define RT5645_MDA_L_M_NOR (0x0 << 15) | 1132 | #define RT5645_DA_MONOL_CLK_SEL_MASK (0xf << 8) |
1118 | #define RT5645_MDA_L_M_ASYN (0x1 << 15) | 1133 | #define RT5645_DA_MONOL_CLK_SEL_SFT 8 |
1119 | #define RT5645_MDA_R_M_MASK (0x1 << 14) | 1134 | #define RT5645_DA_MONOR_CLK_SEL_MASK (0xf << 4) |
1120 | #define RT5645_MDA_R_M_SFT 14 | 1135 | #define RT5645_DA_MONOR_CLK_SEL_SFT 4 |
1121 | #define RT5645_MDA_R_M_NOR (0x0 << 14) | 1136 | #define RT5645_AD_STO1_CLK_SEL_MASK (0xf << 0) |
1122 | #define RT5645_MDA_R_M_ASYN (0x1 << 14) | 1137 | #define RT5645_AD_STO1_CLK_SEL_SFT 0 |
1123 | #define RT5645_MAD_L_M_MASK (0x1 << 13) | ||
1124 | #define RT5645_MAD_L_M_SFT 13 | ||
1125 | #define RT5645_MAD_L_M_NOR (0x0 << 13) | ||
1126 | #define RT5645_MAD_L_M_ASYN (0x1 << 13) | ||
1127 | #define RT5645_MAD_R_M_MASK (0x1 << 12) | ||
1128 | #define RT5645_MAD_R_M_SFT 12 | ||
1129 | #define RT5645_MAD_R_M_NOR (0x0 << 12) | ||
1130 | #define RT5645_MAD_R_M_ASYN (0x1 << 12) | ||
1131 | #define RT5645_ADC_M_MASK (0x1 << 11) | ||
1132 | #define RT5645_ADC_M_SFT 11 | ||
1133 | #define RT5645_ADC_M_NOR (0x0 << 11) | ||
1134 | #define RT5645_ADC_M_ASYN (0x1 << 11) | ||
1135 | #define RT5645_STO_DAC_M_MASK (0x1 << 5) | ||
1136 | #define RT5645_STO_DAC_M_SFT 5 | ||
1137 | #define RT5645_STO_DAC_M_NOR (0x0 << 5) | ||
1138 | #define RT5645_STO_DAC_M_ASYN (0x1 << 5) | ||
1139 | #define RT5645_I2S1_R_D_MASK (0x1 << 4) | ||
1140 | #define RT5645_I2S1_R_D_SFT 4 | ||
1141 | #define RT5645_I2S1_R_D_DIS (0x0 << 4) | ||
1142 | #define RT5645_I2S1_R_D_EN (0x1 << 4) | ||
1143 | #define RT5645_I2S2_R_D_MASK (0x1 << 3) | ||
1144 | #define RT5645_I2S2_R_D_SFT 3 | ||
1145 | #define RT5645_I2S2_R_D_DIS (0x0 << 3) | ||
1146 | #define RT5645_I2S2_R_D_EN (0x1 << 3) | ||
1147 | #define RT5645_PRE_SCLK_MASK (0x3) | ||
1148 | #define RT5645_PRE_SCLK_SFT 0 | ||
1149 | #define RT5645_PRE_SCLK_512 (0x0) | ||
1150 | #define RT5645_PRE_SCLK_1024 (0x1) | ||
1151 | #define RT5645_PRE_SCLK_2048 (0x2) | ||
1152 | 1138 | ||
1153 | /* ASRC Control 3 (0x85) */ | 1139 | /* ASRC Control 3 (0x85) */ |
1154 | #define RT5645_I2S1_RATE_MASK (0xf << 12) | 1140 | #define RT5645_AD_MONOL_CLK_SEL_MASK (0xf << 4) |
1155 | #define RT5645_I2S1_RATE_SFT 12 | 1141 | #define RT5645_AD_MONOL_CLK_SEL_SFT 4 |
1156 | #define RT5645_I2S2_RATE_MASK (0xf << 8) | 1142 | #define RT5645_AD_MONOR_CLK_SEL_MASK (0xf << 0) |
1157 | #define RT5645_I2S2_RATE_SFT 8 | 1143 | #define RT5645_AD_MONOR_CLK_SEL_SFT 0 |
1158 | 1144 | ||
1159 | /* ASRC Control 4 (0x89) */ | 1145 | /* ASRC Control 4 (0x89) */ |
1160 | #define RT5645_I2S1_PD_MASK (0x7 << 12) | 1146 | #define RT5645_I2S1_PD_MASK (0x7 << 12) |
@@ -2175,6 +2161,24 @@ enum { | |||
2175 | RT5645_DMIC_DATA_GPIO11, | 2161 | RT5645_DMIC_DATA_GPIO11, |
2176 | }; | 2162 | }; |
2177 | 2163 | ||
2164 | enum { | ||
2165 | CODEC_TYPE_RT5645, | ||
2166 | CODEC_TYPE_RT5650, | ||
2167 | }; | ||
2168 | |||
2169 | /* filter mask */ | ||
2170 | enum { | ||
2171 | RT5645_DA_STEREO_FILTER = 0x1, | ||
2172 | RT5645_DA_MONO_L_FILTER = (0x1 << 1), | ||
2173 | RT5645_DA_MONO_R_FILTER = (0x1 << 2), | ||
2174 | RT5645_AD_STEREO_FILTER = (0x1 << 3), | ||
2175 | RT5645_AD_MONO_L_FILTER = (0x1 << 4), | ||
2176 | RT5645_AD_MONO_R_FILTER = (0x1 << 5), | ||
2177 | }; | ||
2178 | |||
2179 | int rt5645_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
2180 | unsigned int filter_mask, unsigned int clk_src); | ||
2181 | |||
2178 | struct rt5645_priv { | 2182 | struct rt5645_priv { |
2179 | struct snd_soc_codec *codec; | 2183 | struct snd_soc_codec *codec; |
2180 | struct rt5645_platform_data pdata; | 2184 | struct rt5645_platform_data pdata; |
@@ -2184,6 +2188,7 @@ struct rt5645_priv { | |||
2184 | struct snd_soc_jack *mic_jack; | 2188 | struct snd_soc_jack *mic_jack; |
2185 | struct delayed_work jack_detect_work; | 2189 | struct delayed_work jack_detect_work; |
2186 | 2190 | ||
2191 | int codec_type; | ||
2187 | int sysclk; | 2192 | int sysclk; |
2188 | int sysclk_src; | 2193 | int sysclk_src; |
2189 | int lrck[RT5645_AIFS]; | 2194 | int lrck[RT5645_AIFS]; |
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index bb0a3ab5416c..9f4c7be6d798 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c | |||
@@ -376,7 +376,7 @@ static const struct snd_kcontrol_new rt5651_snd_controls[] = { | |||
376 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, | 376 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, |
377 | struct snd_kcontrol *kcontrol, int event) | 377 | struct snd_kcontrol *kcontrol, int event) |
378 | { | 378 | { |
379 | struct snd_soc_codec *codec = w->codec; | 379 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
380 | struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); | 380 | struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); |
381 | int idx = -EINVAL; | 381 | int idx = -EINVAL; |
382 | 382 | ||
@@ -394,9 +394,10 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
394 | static int is_sysclk_from_pll(struct snd_soc_dapm_widget *source, | 394 | static int is_sysclk_from_pll(struct snd_soc_dapm_widget *source, |
395 | struct snd_soc_dapm_widget *sink) | 395 | struct snd_soc_dapm_widget *sink) |
396 | { | 396 | { |
397 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
397 | unsigned int val; | 398 | unsigned int val; |
398 | 399 | ||
399 | val = snd_soc_read(source->codec, RT5651_GLB_CLK); | 400 | val = snd_soc_read(codec, RT5651_GLB_CLK); |
400 | val &= RT5651_SCLK_SRC_MASK; | 401 | val &= RT5651_SCLK_SRC_MASK; |
401 | if (val == RT5651_SCLK_SRC_PLL1) | 402 | if (val == RT5651_SCLK_SRC_PLL1) |
402 | return 1; | 403 | return 1; |
@@ -731,7 +732,7 @@ static const struct snd_kcontrol_new rt5651_pdm_r_mux = | |||
731 | static int rt5651_amp_power_event(struct snd_soc_dapm_widget *w, | 732 | static int rt5651_amp_power_event(struct snd_soc_dapm_widget *w, |
732 | struct snd_kcontrol *kcontrol, int event) | 733 | struct snd_kcontrol *kcontrol, int event) |
733 | { | 734 | { |
734 | struct snd_soc_codec *codec = w->codec; | 735 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
735 | struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); | 736 | struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); |
736 | 737 | ||
737 | switch (event) { | 738 | switch (event) { |
@@ -769,7 +770,7 @@ static int rt5651_amp_power_event(struct snd_soc_dapm_widget *w, | |||
769 | static int rt5651_hp_event(struct snd_soc_dapm_widget *w, | 770 | static int rt5651_hp_event(struct snd_soc_dapm_widget *w, |
770 | struct snd_kcontrol *kcontrol, int event) | 771 | struct snd_kcontrol *kcontrol, int event) |
771 | { | 772 | { |
772 | struct snd_soc_codec *codec = w->codec; | 773 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
773 | struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); | 774 | struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); |
774 | 775 | ||
775 | switch (event) { | 776 | switch (event) { |
@@ -813,7 +814,8 @@ static int rt5651_hp_event(struct snd_soc_dapm_widget *w, | |||
813 | static int rt5651_hp_post_event(struct snd_soc_dapm_widget *w, | 814 | static int rt5651_hp_post_event(struct snd_soc_dapm_widget *w, |
814 | struct snd_kcontrol *kcontrol, int event) | 815 | struct snd_kcontrol *kcontrol, int event) |
815 | { | 816 | { |
816 | struct snd_soc_codec *codec = w->codec; | 817 | |
818 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
817 | struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); | 819 | struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); |
818 | 820 | ||
819 | switch (event) { | 821 | switch (event) { |
@@ -833,7 +835,7 @@ static int rt5651_hp_post_event(struct snd_soc_dapm_widget *w, | |||
833 | static int rt5651_bst1_event(struct snd_soc_dapm_widget *w, | 835 | static int rt5651_bst1_event(struct snd_soc_dapm_widget *w, |
834 | struct snd_kcontrol *kcontrol, int event) | 836 | struct snd_kcontrol *kcontrol, int event) |
835 | { | 837 | { |
836 | struct snd_soc_codec *codec = w->codec; | 838 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
837 | 839 | ||
838 | switch (event) { | 840 | switch (event) { |
839 | case SND_SOC_DAPM_POST_PMU: | 841 | case SND_SOC_DAPM_POST_PMU: |
@@ -856,7 +858,7 @@ static int rt5651_bst1_event(struct snd_soc_dapm_widget *w, | |||
856 | static int rt5651_bst2_event(struct snd_soc_dapm_widget *w, | 858 | static int rt5651_bst2_event(struct snd_soc_dapm_widget *w, |
857 | struct snd_kcontrol *kcontrol, int event) | 859 | struct snd_kcontrol *kcontrol, int event) |
858 | { | 860 | { |
859 | struct snd_soc_codec *codec = w->codec; | 861 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
860 | 862 | ||
861 | switch (event) { | 863 | switch (event) { |
862 | case SND_SOC_DAPM_POST_PMU: | 864 | case SND_SOC_DAPM_POST_PMU: |
@@ -879,7 +881,7 @@ static int rt5651_bst2_event(struct snd_soc_dapm_widget *w, | |||
879 | static int rt5651_bst3_event(struct snd_soc_dapm_widget *w, | 881 | static int rt5651_bst3_event(struct snd_soc_dapm_widget *w, |
880 | struct snd_kcontrol *kcontrol, int event) | 882 | struct snd_kcontrol *kcontrol, int event) |
881 | { | 883 | { |
882 | struct snd_soc_codec *codec = w->codec; | 884 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
883 | 885 | ||
884 | switch (event) { | 886 | switch (event) { |
885 | case SND_SOC_DAPM_POST_PMU: | 887 | case SND_SOC_DAPM_POST_PMU: |
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 8a0833de1665..fd102613d20d 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c | |||
@@ -14,10 +14,12 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
17 | #include <linux/pm_runtime.h> | ||
17 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
19 | #include <linux/acpi.h> | 20 | #include <linux/acpi.h> |
20 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/dmi.h> | ||
21 | #include <sound/core.h> | 23 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
@@ -223,7 +225,6 @@ static bool rt5670_volatile_register(struct device *dev, unsigned int reg) | |||
223 | case RT5670_ADC_EQ_CTRL1: | 225 | case RT5670_ADC_EQ_CTRL1: |
224 | case RT5670_EQ_CTRL1: | 226 | case RT5670_EQ_CTRL1: |
225 | case RT5670_ALC_CTRL_1: | 227 | case RT5670_ALC_CTRL_1: |
226 | case RT5670_IRQ_CTRL1: | ||
227 | case RT5670_IRQ_CTRL2: | 228 | case RT5670_IRQ_CTRL2: |
228 | case RT5670_INT_IRQ_ST: | 229 | case RT5670_INT_IRQ_ST: |
229 | case RT5670_IL_CMD: | 230 | case RT5670_IL_CMD: |
@@ -498,7 +499,7 @@ static const struct snd_kcontrol_new rt5670_snd_controls[] = { | |||
498 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, | 499 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, |
499 | struct snd_kcontrol *kcontrol, int event) | 500 | struct snd_kcontrol *kcontrol, int event) |
500 | { | 501 | { |
501 | struct snd_soc_codec *codec = w->codec; | 502 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
502 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | 503 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); |
503 | int idx = -EINVAL; | 504 | int idx = -EINVAL; |
504 | 505 | ||
@@ -515,9 +516,10 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
515 | static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, | 516 | static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, |
516 | struct snd_soc_dapm_widget *sink) | 517 | struct snd_soc_dapm_widget *sink) |
517 | { | 518 | { |
519 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
518 | unsigned int val; | 520 | unsigned int val; |
519 | 521 | ||
520 | val = snd_soc_read(source->codec, RT5670_GLB_CLK); | 522 | val = snd_soc_read(codec, RT5670_GLB_CLK); |
521 | val &= RT5670_SCLK_SRC_MASK; | 523 | val &= RT5670_SCLK_SRC_MASK; |
522 | if (val == RT5670_SCLK_SRC_PLL1) | 524 | if (val == RT5670_SCLK_SRC_PLL1) |
523 | return 1; | 525 | return 1; |
@@ -528,6 +530,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, | |||
528 | static int is_using_asrc(struct snd_soc_dapm_widget *source, | 530 | static int is_using_asrc(struct snd_soc_dapm_widget *source, |
529 | struct snd_soc_dapm_widget *sink) | 531 | struct snd_soc_dapm_widget *sink) |
530 | { | 532 | { |
533 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
531 | unsigned int reg, shift, val; | 534 | unsigned int reg, shift, val; |
532 | 535 | ||
533 | switch (source->shift) { | 536 | switch (source->shift) { |
@@ -563,7 +566,7 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source, | |||
563 | return 0; | 566 | return 0; |
564 | } | 567 | } |
565 | 568 | ||
566 | val = (snd_soc_read(source->codec, reg) >> shift) & 0xf; | 569 | val = (snd_soc_read(codec, reg) >> shift) & 0xf; |
567 | switch (val) { | 570 | switch (val) { |
568 | case 1: | 571 | case 1: |
569 | case 2: | 572 | case 2: |
@@ -588,6 +591,89 @@ static int can_use_asrc(struct snd_soc_dapm_widget *source, | |||
588 | return 0; | 591 | return 0; |
589 | } | 592 | } |
590 | 593 | ||
594 | |||
595 | /** | ||
596 | * rt5670_sel_asrc_clk_src - select ASRC clock source for a set of filters | ||
597 | * @codec: SoC audio codec device. | ||
598 | * @filter_mask: mask of filters. | ||
599 | * @clk_src: clock source | ||
600 | * | ||
601 | * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5670 can | ||
602 | * only support standard 32fs or 64fs i2s format, ASRC should be enabled to | ||
603 | * support special i2s clock format such as Intel's 100fs(100 * sampling rate). | ||
604 | * ASRC function will track i2s clock and generate a corresponding system clock | ||
605 | * for codec. This function provides an API to select the clock source for a | ||
606 | * set of filters specified by the mask. And the codec driver will turn on ASRC | ||
607 | * for these filters if ASRC is selected as their clock source. | ||
608 | */ | ||
609 | int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
610 | unsigned int filter_mask, unsigned int clk_src) | ||
611 | { | ||
612 | unsigned int asrc2_mask = 0, asrc2_value = 0; | ||
613 | unsigned int asrc3_mask = 0, asrc3_value = 0; | ||
614 | |||
615 | if (clk_src > RT5670_CLK_SEL_SYS3) | ||
616 | return -EINVAL; | ||
617 | |||
618 | if (filter_mask & RT5670_DA_STEREO_FILTER) { | ||
619 | asrc2_mask |= RT5670_DA_STO_CLK_SEL_MASK; | ||
620 | asrc2_value = (asrc2_value & ~RT5670_DA_STO_CLK_SEL_MASK) | ||
621 | | (clk_src << RT5670_DA_STO_CLK_SEL_SFT); | ||
622 | } | ||
623 | |||
624 | if (filter_mask & RT5670_DA_MONO_L_FILTER) { | ||
625 | asrc2_mask |= RT5670_DA_MONOL_CLK_SEL_MASK; | ||
626 | asrc2_value = (asrc2_value & ~RT5670_DA_MONOL_CLK_SEL_MASK) | ||
627 | | (clk_src << RT5670_DA_MONOL_CLK_SEL_SFT); | ||
628 | } | ||
629 | |||
630 | if (filter_mask & RT5670_DA_MONO_R_FILTER) { | ||
631 | asrc2_mask |= RT5670_DA_MONOR_CLK_SEL_MASK; | ||
632 | asrc2_value = (asrc2_value & ~RT5670_DA_MONOR_CLK_SEL_MASK) | ||
633 | | (clk_src << RT5670_DA_MONOR_CLK_SEL_SFT); | ||
634 | } | ||
635 | |||
636 | if (filter_mask & RT5670_AD_STEREO_FILTER) { | ||
637 | asrc2_mask |= RT5670_AD_STO1_CLK_SEL_MASK; | ||
638 | asrc2_value = (asrc2_value & ~RT5670_AD_STO1_CLK_SEL_MASK) | ||
639 | | (clk_src << RT5670_AD_STO1_CLK_SEL_SFT); | ||
640 | } | ||
641 | |||
642 | if (filter_mask & RT5670_AD_MONO_L_FILTER) { | ||
643 | asrc3_mask |= RT5670_AD_MONOL_CLK_SEL_MASK; | ||
644 | asrc3_value = (asrc3_value & ~RT5670_AD_MONOL_CLK_SEL_MASK) | ||
645 | | (clk_src << RT5670_AD_MONOL_CLK_SEL_SFT); | ||
646 | } | ||
647 | |||
648 | if (filter_mask & RT5670_AD_MONO_R_FILTER) { | ||
649 | asrc3_mask |= RT5670_AD_MONOR_CLK_SEL_MASK; | ||
650 | asrc3_value = (asrc3_value & ~RT5670_AD_MONOR_CLK_SEL_MASK) | ||
651 | | (clk_src << RT5670_AD_MONOR_CLK_SEL_SFT); | ||
652 | } | ||
653 | |||
654 | if (filter_mask & RT5670_UP_RATE_FILTER) { | ||
655 | asrc3_mask |= RT5670_UP_CLK_SEL_MASK; | ||
656 | asrc3_value = (asrc3_value & ~RT5670_UP_CLK_SEL_MASK) | ||
657 | | (clk_src << RT5670_UP_CLK_SEL_SFT); | ||
658 | } | ||
659 | |||
660 | if (filter_mask & RT5670_DOWN_RATE_FILTER) { | ||
661 | asrc3_mask |= RT5670_DOWN_CLK_SEL_MASK; | ||
662 | asrc3_value = (asrc3_value & ~RT5670_DOWN_CLK_SEL_MASK) | ||
663 | | (clk_src << RT5670_DOWN_CLK_SEL_SFT); | ||
664 | } | ||
665 | |||
666 | if (asrc2_mask) | ||
667 | snd_soc_update_bits(codec, RT5670_ASRC_2, | ||
668 | asrc2_mask, asrc2_value); | ||
669 | |||
670 | if (asrc3_mask) | ||
671 | snd_soc_update_bits(codec, RT5670_ASRC_3, | ||
672 | asrc3_mask, asrc3_value); | ||
673 | return 0; | ||
674 | } | ||
675 | EXPORT_SYMBOL_GPL(rt5670_sel_asrc_clk_src); | ||
676 | |||
591 | /* Digital Mixer */ | 677 | /* Digital Mixer */ |
592 | static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = { | 678 | static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = { |
593 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER, | 679 | SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER, |
@@ -1146,7 +1232,7 @@ static const struct snd_kcontrol_new rt5670_vad_adc_mux = | |||
1146 | static int rt5670_hp_power_event(struct snd_soc_dapm_widget *w, | 1232 | static int rt5670_hp_power_event(struct snd_soc_dapm_widget *w, |
1147 | struct snd_kcontrol *kcontrol, int event) | 1233 | struct snd_kcontrol *kcontrol, int event) |
1148 | { | 1234 | { |
1149 | struct snd_soc_codec *codec = w->codec; | 1235 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1150 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | 1236 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); |
1151 | 1237 | ||
1152 | switch (event) { | 1238 | switch (event) { |
@@ -1182,7 +1268,7 @@ static int rt5670_hp_power_event(struct snd_soc_dapm_widget *w, | |||
1182 | static int rt5670_hp_event(struct snd_soc_dapm_widget *w, | 1268 | static int rt5670_hp_event(struct snd_soc_dapm_widget *w, |
1183 | struct snd_kcontrol *kcontrol, int event) | 1269 | struct snd_kcontrol *kcontrol, int event) |
1184 | { | 1270 | { |
1185 | struct snd_soc_codec *codec = w->codec; | 1271 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1186 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | 1272 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); |
1187 | 1273 | ||
1188 | switch (event) { | 1274 | switch (event) { |
@@ -1232,7 +1318,7 @@ static int rt5670_hp_event(struct snd_soc_dapm_widget *w, | |||
1232 | static int rt5670_bst1_event(struct snd_soc_dapm_widget *w, | 1318 | static int rt5670_bst1_event(struct snd_soc_dapm_widget *w, |
1233 | struct snd_kcontrol *kcontrol, int event) | 1319 | struct snd_kcontrol *kcontrol, int event) |
1234 | { | 1320 | { |
1235 | struct snd_soc_codec *codec = w->codec; | 1321 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1236 | 1322 | ||
1237 | switch (event) { | 1323 | switch (event) { |
1238 | case SND_SOC_DAPM_POST_PMU: | 1324 | case SND_SOC_DAPM_POST_PMU: |
@@ -1255,7 +1341,7 @@ static int rt5670_bst1_event(struct snd_soc_dapm_widget *w, | |||
1255 | static int rt5670_bst2_event(struct snd_soc_dapm_widget *w, | 1341 | static int rt5670_bst2_event(struct snd_soc_dapm_widget *w, |
1256 | struct snd_kcontrol *kcontrol, int event) | 1342 | struct snd_kcontrol *kcontrol, int event) |
1257 | { | 1343 | { |
1258 | struct snd_soc_codec *codec = w->codec; | 1344 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1259 | 1345 | ||
1260 | switch (event) { | 1346 | switch (event) { |
1261 | case SND_SOC_DAPM_POST_PMU: | 1347 | case SND_SOC_DAPM_POST_PMU: |
@@ -2188,6 +2274,13 @@ static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai, | |||
2188 | if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src) | 2274 | if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src) |
2189 | return 0; | 2275 | return 0; |
2190 | 2276 | ||
2277 | if (rt5670->pdata.jd_mode) { | ||
2278 | if (clk_id == RT5670_SCLK_S_PLL1) | ||
2279 | snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); | ||
2280 | else | ||
2281 | snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); | ||
2282 | snd_soc_dapm_sync(&codec->dapm); | ||
2283 | } | ||
2191 | switch (clk_id) { | 2284 | switch (clk_id) { |
2192 | case RT5670_SCLK_S_MCLK: | 2285 | case RT5670_SCLK_S_MCLK: |
2193 | reg_val |= RT5670_SCLK_SRC_MCLK; | 2286 | reg_val |= RT5670_SCLK_SRC_MCLK; |
@@ -2522,6 +2615,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5670 = { | |||
2522 | static const struct regmap_config rt5670_regmap = { | 2615 | static const struct regmap_config rt5670_regmap = { |
2523 | .reg_bits = 8, | 2616 | .reg_bits = 8, |
2524 | .val_bits = 16, | 2617 | .val_bits = 16, |
2618 | .use_single_rw = true, | ||
2525 | .max_register = RT5670_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5670_ranges) * | 2619 | .max_register = RT5670_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5670_ranges) * |
2526 | RT5670_PR_SPACING), | 2620 | RT5670_PR_SPACING), |
2527 | .volatile_reg = rt5670_volatile_register, | 2621 | .volatile_reg = rt5670_volatile_register, |
@@ -2549,6 +2643,17 @@ static struct acpi_device_id rt5670_acpi_match[] = { | |||
2549 | MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match); | 2643 | MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match); |
2550 | #endif | 2644 | #endif |
2551 | 2645 | ||
2646 | static const struct dmi_system_id dmi_platform_intel_braswell[] = { | ||
2647 | { | ||
2648 | .ident = "Intel Braswell", | ||
2649 | .matches = { | ||
2650 | DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), | ||
2651 | DMI_MATCH(DMI_BOARD_NAME, "Braswell CRB"), | ||
2652 | }, | ||
2653 | }, | ||
2654 | {} | ||
2655 | }; | ||
2656 | |||
2552 | static int rt5670_i2c_probe(struct i2c_client *i2c, | 2657 | static int rt5670_i2c_probe(struct i2c_client *i2c, |
2553 | const struct i2c_device_id *id) | 2658 | const struct i2c_device_id *id) |
2554 | { | 2659 | { |
@@ -2568,6 +2673,12 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, | |||
2568 | if (pdata) | 2673 | if (pdata) |
2569 | rt5670->pdata = *pdata; | 2674 | rt5670->pdata = *pdata; |
2570 | 2675 | ||
2676 | if (dmi_check_system(dmi_platform_intel_braswell)) { | ||
2677 | rt5670->pdata.dmic_en = true; | ||
2678 | rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; | ||
2679 | rt5670->pdata.jd_mode = 1; | ||
2680 | } | ||
2681 | |||
2571 | rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); | 2682 | rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); |
2572 | if (IS_ERR(rt5670->regmap)) { | 2683 | if (IS_ERR(rt5670->regmap)) { |
2573 | ret = PTR_ERR(rt5670->regmap); | 2684 | ret = PTR_ERR(rt5670->regmap); |
@@ -2591,6 +2702,12 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, | |||
2591 | 2702 | ||
2592 | regmap_write(rt5670->regmap, RT5670_RESET, 0); | 2703 | regmap_write(rt5670->regmap, RT5670_RESET, 0); |
2593 | 2704 | ||
2705 | regmap_read(rt5670->regmap, RT5670_VENDOR_ID, &val); | ||
2706 | if (val >= 4) | ||
2707 | regmap_write(rt5670->regmap, RT5670_GPIO_CTRL3, 0x0980); | ||
2708 | else | ||
2709 | regmap_write(rt5670->regmap, RT5670_GPIO_CTRL3, 0x0d00); | ||
2710 | |||
2594 | ret = regmap_register_patch(rt5670->regmap, init_list, | 2711 | ret = regmap_register_patch(rt5670->regmap, init_list, |
2595 | ARRAY_SIZE(init_list)); | 2712 | ARRAY_SIZE(init_list)); |
2596 | if (ret != 0) | 2713 | if (ret != 0) |
@@ -2609,6 +2726,10 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, | |||
2609 | } | 2726 | } |
2610 | 2727 | ||
2611 | if (rt5670->pdata.jd_mode) { | 2728 | if (rt5670->pdata.jd_mode) { |
2729 | regmap_update_bits(rt5670->regmap, RT5670_GLB_CLK, | ||
2730 | RT5670_SCLK_SRC_MASK, RT5670_SCLK_SRC_RCCLK); | ||
2731 | rt5670->sysclk = 0; | ||
2732 | rt5670->sysclk_src = RT5670_SCLK_S_RCCLK; | ||
2612 | regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1, | 2733 | regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1, |
2613 | RT5670_PWR_MB, RT5670_PWR_MB); | 2734 | RT5670_PWR_MB, RT5670_PWR_MB); |
2614 | regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG2, | 2735 | regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG2, |
@@ -2716,18 +2837,26 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, | |||
2716 | 2837 | ||
2717 | } | 2838 | } |
2718 | 2839 | ||
2840 | pm_runtime_enable(&i2c->dev); | ||
2841 | pm_request_idle(&i2c->dev); | ||
2842 | |||
2719 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5670, | 2843 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5670, |
2720 | rt5670_dai, ARRAY_SIZE(rt5670_dai)); | 2844 | rt5670_dai, ARRAY_SIZE(rt5670_dai)); |
2721 | if (ret < 0) | 2845 | if (ret < 0) |
2722 | goto err; | 2846 | goto err; |
2723 | 2847 | ||
2848 | pm_runtime_put(&i2c->dev); | ||
2849 | |||
2724 | return 0; | 2850 | return 0; |
2725 | err: | 2851 | err: |
2852 | pm_runtime_disable(&i2c->dev); | ||
2853 | |||
2726 | return ret; | 2854 | return ret; |
2727 | } | 2855 | } |
2728 | 2856 | ||
2729 | static int rt5670_i2c_remove(struct i2c_client *i2c) | 2857 | static int rt5670_i2c_remove(struct i2c_client *i2c) |
2730 | { | 2858 | { |
2859 | pm_runtime_disable(&i2c->dev); | ||
2731 | snd_soc_unregister_codec(&i2c->dev); | 2860 | snd_soc_unregister_codec(&i2c->dev); |
2732 | 2861 | ||
2733 | return 0; | 2862 | return 0; |
diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h index d11b9c207e26..21f8e18c13c4 100644 --- a/sound/soc/codecs/rt5670.h +++ b/sound/soc/codecs/rt5670.h | |||
@@ -1023,50 +1023,33 @@ | |||
1023 | #define RT5670_DMIC_2_M_NOR (0x0 << 8) | 1023 | #define RT5670_DMIC_2_M_NOR (0x0 << 8) |
1024 | #define RT5670_DMIC_2_M_ASYN (0x1 << 8) | 1024 | #define RT5670_DMIC_2_M_ASYN (0x1 << 8) |
1025 | 1025 | ||
1026 | /* ASRC clock source selection (0x84, 0x85) */ | ||
1027 | #define RT5670_CLK_SEL_SYS (0x0) | ||
1028 | #define RT5670_CLK_SEL_I2S1_ASRC (0x1) | ||
1029 | #define RT5670_CLK_SEL_I2S2_ASRC (0x2) | ||
1030 | #define RT5670_CLK_SEL_I2S3_ASRC (0x3) | ||
1031 | #define RT5670_CLK_SEL_SYS2 (0x5) | ||
1032 | #define RT5670_CLK_SEL_SYS3 (0x6) | ||
1033 | |||
1026 | /* ASRC Control 2 (0x84) */ | 1034 | /* ASRC Control 2 (0x84) */ |
1027 | #define RT5670_MDA_L_M_MASK (0x1 << 15) | 1035 | #define RT5670_DA_STO_CLK_SEL_MASK (0xf << 12) |
1028 | #define RT5670_MDA_L_M_SFT 15 | 1036 | #define RT5670_DA_STO_CLK_SEL_SFT 12 |
1029 | #define RT5670_MDA_L_M_NOR (0x0 << 15) | 1037 | #define RT5670_DA_MONOL_CLK_SEL_MASK (0xf << 8) |
1030 | #define RT5670_MDA_L_M_ASYN (0x1 << 15) | 1038 | #define RT5670_DA_MONOL_CLK_SEL_SFT 8 |
1031 | #define RT5670_MDA_R_M_MASK (0x1 << 14) | 1039 | #define RT5670_DA_MONOR_CLK_SEL_MASK (0xf << 4) |
1032 | #define RT5670_MDA_R_M_SFT 14 | 1040 | #define RT5670_DA_MONOR_CLK_SEL_SFT 4 |
1033 | #define RT5670_MDA_R_M_NOR (0x0 << 14) | 1041 | #define RT5670_AD_STO1_CLK_SEL_MASK (0xf << 0) |
1034 | #define RT5670_MDA_R_M_ASYN (0x1 << 14) | 1042 | #define RT5670_AD_STO1_CLK_SEL_SFT 0 |
1035 | #define RT5670_MAD_L_M_MASK (0x1 << 13) | ||
1036 | #define RT5670_MAD_L_M_SFT 13 | ||
1037 | #define RT5670_MAD_L_M_NOR (0x0 << 13) | ||
1038 | #define RT5670_MAD_L_M_ASYN (0x1 << 13) | ||
1039 | #define RT5670_MAD_R_M_MASK (0x1 << 12) | ||
1040 | #define RT5670_MAD_R_M_SFT 12 | ||
1041 | #define RT5670_MAD_R_M_NOR (0x0 << 12) | ||
1042 | #define RT5670_MAD_R_M_ASYN (0x1 << 12) | ||
1043 | #define RT5670_ADC_M_MASK (0x1 << 11) | ||
1044 | #define RT5670_ADC_M_SFT 11 | ||
1045 | #define RT5670_ADC_M_NOR (0x0 << 11) | ||
1046 | #define RT5670_ADC_M_ASYN (0x1 << 11) | ||
1047 | #define RT5670_STO_DAC_M_MASK (0x1 << 5) | ||
1048 | #define RT5670_STO_DAC_M_SFT 5 | ||
1049 | #define RT5670_STO_DAC_M_NOR (0x0 << 5) | ||
1050 | #define RT5670_STO_DAC_M_ASYN (0x1 << 5) | ||
1051 | #define RT5670_I2S1_R_D_MASK (0x1 << 4) | ||
1052 | #define RT5670_I2S1_R_D_SFT 4 | ||
1053 | #define RT5670_I2S1_R_D_DIS (0x0 << 4) | ||
1054 | #define RT5670_I2S1_R_D_EN (0x1 << 4) | ||
1055 | #define RT5670_I2S2_R_D_MASK (0x1 << 3) | ||
1056 | #define RT5670_I2S2_R_D_SFT 3 | ||
1057 | #define RT5670_I2S2_R_D_DIS (0x0 << 3) | ||
1058 | #define RT5670_I2S2_R_D_EN (0x1 << 3) | ||
1059 | #define RT5670_PRE_SCLK_MASK (0x3) | ||
1060 | #define RT5670_PRE_SCLK_SFT 0 | ||
1061 | #define RT5670_PRE_SCLK_512 (0x0) | ||
1062 | #define RT5670_PRE_SCLK_1024 (0x1) | ||
1063 | #define RT5670_PRE_SCLK_2048 (0x2) | ||
1064 | 1043 | ||
1065 | /* ASRC Control 3 (0x85) */ | 1044 | /* ASRC Control 3 (0x85) */ |
1066 | #define RT5670_I2S1_RATE_MASK (0xf << 12) | 1045 | #define RT5670_UP_CLK_SEL_MASK (0xf << 12) |
1067 | #define RT5670_I2S1_RATE_SFT 12 | 1046 | #define RT5670_UP_CLK_SEL_SFT 12 |
1068 | #define RT5670_I2S2_RATE_MASK (0xf << 8) | 1047 | #define RT5670_DOWN_CLK_SEL_MASK (0xf << 8) |
1069 | #define RT5670_I2S2_RATE_SFT 8 | 1048 | #define RT5670_DOWN_CLK_SEL_SFT 8 |
1049 | #define RT5670_AD_MONOL_CLK_SEL_MASK (0xf << 4) | ||
1050 | #define RT5670_AD_MONOL_CLK_SEL_SFT 4 | ||
1051 | #define RT5670_AD_MONOR_CLK_SEL_MASK (0xf << 0) | ||
1052 | #define RT5670_AD_MONOR_CLK_SEL_SFT 0 | ||
1070 | 1053 | ||
1071 | /* ASRC Control 4 (0x89) */ | 1054 | /* ASRC Control 4 (0x89) */ |
1072 | #define RT5670_I2S1_PD_MASK (0x7 << 12) | 1055 | #define RT5670_I2S1_PD_MASK (0x7 << 12) |
@@ -1983,6 +1966,21 @@ enum { | |||
1983 | RT5670_DMIC_DATA_GPIO5, | 1966 | RT5670_DMIC_DATA_GPIO5, |
1984 | }; | 1967 | }; |
1985 | 1968 | ||
1969 | /* filter mask */ | ||
1970 | enum { | ||
1971 | RT5670_DA_STEREO_FILTER = 0x1, | ||
1972 | RT5670_DA_MONO_L_FILTER = (0x1 << 1), | ||
1973 | RT5670_DA_MONO_R_FILTER = (0x1 << 2), | ||
1974 | RT5670_AD_STEREO_FILTER = (0x1 << 3), | ||
1975 | RT5670_AD_MONO_L_FILTER = (0x1 << 4), | ||
1976 | RT5670_AD_MONO_R_FILTER = (0x1 << 5), | ||
1977 | RT5670_UP_RATE_FILTER = (0x1 << 6), | ||
1978 | RT5670_DOWN_RATE_FILTER = (0x1 << 7), | ||
1979 | }; | ||
1980 | |||
1981 | int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
1982 | unsigned int filter_mask, unsigned int clk_src); | ||
1983 | |||
1986 | struct rt5670_priv { | 1984 | struct rt5670_priv { |
1987 | struct snd_soc_codec *codec; | 1985 | struct snd_soc_codec *codec; |
1988 | struct rt5670_platform_data pdata; | 1986 | struct rt5670_platform_data pdata; |
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 918ada9738b0..fb9c20eace3f 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
@@ -702,6 +702,9 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on) | |||
702 | static bool activity; | 702 | static bool activity; |
703 | int ret; | 703 | int ret; |
704 | 704 | ||
705 | if (!IS_ENABLED(CONFIG_SND_SOC_RT5677_SPI)) | ||
706 | return -ENXIO; | ||
707 | |||
705 | if (on && !activity) { | 708 | if (on && !activity) { |
706 | activity = true; | 709 | activity = true; |
707 | 710 | ||
@@ -896,7 +899,7 @@ static const struct snd_kcontrol_new rt5677_snd_controls[] = { | |||
896 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, | 899 | static int set_dmic_clk(struct snd_soc_dapm_widget *w, |
897 | struct snd_kcontrol *kcontrol, int event) | 900 | struct snd_kcontrol *kcontrol, int event) |
898 | { | 901 | { |
899 | struct snd_soc_codec *codec = w->codec; | 902 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
900 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 903 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
901 | int idx = rl6231_calc_dmic_clk(rt5677->sysclk); | 904 | int idx = rl6231_calc_dmic_clk(rt5677->sysclk); |
902 | 905 | ||
@@ -911,7 +914,8 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, | |||
911 | static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, | 914 | static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, |
912 | struct snd_soc_dapm_widget *sink) | 915 | struct snd_soc_dapm_widget *sink) |
913 | { | 916 | { |
914 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(source->codec); | 917 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
918 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | ||
915 | unsigned int val; | 919 | unsigned int val; |
916 | 920 | ||
917 | regmap_read(rt5677->regmap, RT5677_GLB_CLK1, &val); | 921 | regmap_read(rt5677->regmap, RT5677_GLB_CLK1, &val); |
@@ -922,6 +926,101 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, | |||
922 | return 0; | 926 | return 0; |
923 | } | 927 | } |
924 | 928 | ||
929 | static int is_using_asrc(struct snd_soc_dapm_widget *source, | ||
930 | struct snd_soc_dapm_widget *sink) | ||
931 | { | ||
932 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
933 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | ||
934 | unsigned int reg, shift, val; | ||
935 | |||
936 | if (source->reg == RT5677_ASRC_1) { | ||
937 | switch (source->shift) { | ||
938 | case 12: | ||
939 | reg = RT5677_ASRC_4; | ||
940 | shift = 0; | ||
941 | break; | ||
942 | case 13: | ||
943 | reg = RT5677_ASRC_4; | ||
944 | shift = 4; | ||
945 | break; | ||
946 | case 14: | ||
947 | reg = RT5677_ASRC_4; | ||
948 | shift = 8; | ||
949 | break; | ||
950 | case 15: | ||
951 | reg = RT5677_ASRC_4; | ||
952 | shift = 12; | ||
953 | break; | ||
954 | default: | ||
955 | return 0; | ||
956 | } | ||
957 | } else { | ||
958 | switch (source->shift) { | ||
959 | case 0: | ||
960 | reg = RT5677_ASRC_6; | ||
961 | shift = 8; | ||
962 | break; | ||
963 | case 1: | ||
964 | reg = RT5677_ASRC_6; | ||
965 | shift = 12; | ||
966 | break; | ||
967 | case 2: | ||
968 | reg = RT5677_ASRC_5; | ||
969 | shift = 0; | ||
970 | break; | ||
971 | case 3: | ||
972 | reg = RT5677_ASRC_5; | ||
973 | shift = 4; | ||
974 | break; | ||
975 | case 4: | ||
976 | reg = RT5677_ASRC_5; | ||
977 | shift = 8; | ||
978 | break; | ||
979 | case 5: | ||
980 | reg = RT5677_ASRC_5; | ||
981 | shift = 12; | ||
982 | break; | ||
983 | case 12: | ||
984 | reg = RT5677_ASRC_3; | ||
985 | shift = 0; | ||
986 | break; | ||
987 | case 13: | ||
988 | reg = RT5677_ASRC_3; | ||
989 | shift = 4; | ||
990 | break; | ||
991 | case 14: | ||
992 | reg = RT5677_ASRC_3; | ||
993 | shift = 12; | ||
994 | break; | ||
995 | default: | ||
996 | return 0; | ||
997 | } | ||
998 | } | ||
999 | |||
1000 | regmap_read(rt5677->regmap, reg, &val); | ||
1001 | val = (val >> shift) & 0xf; | ||
1002 | |||
1003 | switch (val) { | ||
1004 | case 1 ... 6: | ||
1005 | return 1; | ||
1006 | default: | ||
1007 | return 0; | ||
1008 | } | ||
1009 | |||
1010 | } | ||
1011 | |||
1012 | static int can_use_asrc(struct snd_soc_dapm_widget *source, | ||
1013 | struct snd_soc_dapm_widget *sink) | ||
1014 | { | ||
1015 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
1016 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | ||
1017 | |||
1018 | if (rt5677->sysclk > rt5677->lrck[RT5677_AIF1] * 384) | ||
1019 | return 1; | ||
1020 | |||
1021 | return 0; | ||
1022 | } | ||
1023 | |||
925 | /* Digital Mixer */ | 1024 | /* Digital Mixer */ |
926 | static const struct snd_kcontrol_new rt5677_sto1_adc_l_mix[] = { | 1025 | static const struct snd_kcontrol_new rt5677_sto1_adc_l_mix[] = { |
927 | SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER, | 1026 | SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER, |
@@ -2031,7 +2130,7 @@ static const struct snd_kcontrol_new rt5677_if2_dac7_tdm_sel_mux = | |||
2031 | static int rt5677_bst1_event(struct snd_soc_dapm_widget *w, | 2130 | static int rt5677_bst1_event(struct snd_soc_dapm_widget *w, |
2032 | struct snd_kcontrol *kcontrol, int event) | 2131 | struct snd_kcontrol *kcontrol, int event) |
2033 | { | 2132 | { |
2034 | struct snd_soc_codec *codec = w->codec; | 2133 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
2035 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 2134 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
2036 | 2135 | ||
2037 | switch (event) { | 2136 | switch (event) { |
@@ -2055,7 +2154,7 @@ static int rt5677_bst1_event(struct snd_soc_dapm_widget *w, | |||
2055 | static int rt5677_bst2_event(struct snd_soc_dapm_widget *w, | 2154 | static int rt5677_bst2_event(struct snd_soc_dapm_widget *w, |
2056 | struct snd_kcontrol *kcontrol, int event) | 2155 | struct snd_kcontrol *kcontrol, int event) |
2057 | { | 2156 | { |
2058 | struct snd_soc_codec *codec = w->codec; | 2157 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
2059 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 2158 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
2060 | 2159 | ||
2061 | switch (event) { | 2160 | switch (event) { |
@@ -2079,7 +2178,7 @@ static int rt5677_bst2_event(struct snd_soc_dapm_widget *w, | |||
2079 | static int rt5677_set_pll1_event(struct snd_soc_dapm_widget *w, | 2178 | static int rt5677_set_pll1_event(struct snd_soc_dapm_widget *w, |
2080 | struct snd_kcontrol *kcontrol, int event) | 2179 | struct snd_kcontrol *kcontrol, int event) |
2081 | { | 2180 | { |
2082 | struct snd_soc_codec *codec = w->codec; | 2181 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
2083 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 2182 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
2084 | 2183 | ||
2085 | switch (event) { | 2184 | switch (event) { |
@@ -2101,7 +2200,7 @@ static int rt5677_set_pll1_event(struct snd_soc_dapm_widget *w, | |||
2101 | static int rt5677_set_pll2_event(struct snd_soc_dapm_widget *w, | 2200 | static int rt5677_set_pll2_event(struct snd_soc_dapm_widget *w, |
2102 | struct snd_kcontrol *kcontrol, int event) | 2201 | struct snd_kcontrol *kcontrol, int event) |
2103 | { | 2202 | { |
2104 | struct snd_soc_codec *codec = w->codec; | 2203 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
2105 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 2204 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
2106 | 2205 | ||
2107 | switch (event) { | 2206 | switch (event) { |
@@ -2123,7 +2222,7 @@ static int rt5677_set_pll2_event(struct snd_soc_dapm_widget *w, | |||
2123 | static int rt5677_set_micbias1_event(struct snd_soc_dapm_widget *w, | 2222 | static int rt5677_set_micbias1_event(struct snd_soc_dapm_widget *w, |
2124 | struct snd_kcontrol *kcontrol, int event) | 2223 | struct snd_kcontrol *kcontrol, int event) |
2125 | { | 2224 | { |
2126 | struct snd_soc_codec *codec = w->codec; | 2225 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
2127 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 2226 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
2128 | 2227 | ||
2129 | switch (event) { | 2228 | switch (event) { |
@@ -2150,7 +2249,7 @@ static int rt5677_set_micbias1_event(struct snd_soc_dapm_widget *w, | |||
2150 | static int rt5677_if1_adc_tdm_event(struct snd_soc_dapm_widget *w, | 2249 | static int rt5677_if1_adc_tdm_event(struct snd_soc_dapm_widget *w, |
2151 | struct snd_kcontrol *kcontrol, int event) | 2250 | struct snd_kcontrol *kcontrol, int event) |
2152 | { | 2251 | { |
2153 | struct snd_soc_codec *codec = w->codec; | 2252 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
2154 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 2253 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
2155 | unsigned int value; | 2254 | unsigned int value; |
2156 | 2255 | ||
@@ -2173,7 +2272,7 @@ static int rt5677_if1_adc_tdm_event(struct snd_soc_dapm_widget *w, | |||
2173 | static int rt5677_if2_adc_tdm_event(struct snd_soc_dapm_widget *w, | 2272 | static int rt5677_if2_adc_tdm_event(struct snd_soc_dapm_widget *w, |
2174 | struct snd_kcontrol *kcontrol, int event) | 2273 | struct snd_kcontrol *kcontrol, int event) |
2175 | { | 2274 | { |
2176 | struct snd_soc_codec *codec = w->codec; | 2275 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
2177 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 2276 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
2178 | unsigned int value; | 2277 | unsigned int value; |
2179 | 2278 | ||
@@ -2196,7 +2295,7 @@ static int rt5677_if2_adc_tdm_event(struct snd_soc_dapm_widget *w, | |||
2196 | static int rt5677_vref_event(struct snd_soc_dapm_widget *w, | 2295 | static int rt5677_vref_event(struct snd_soc_dapm_widget *w, |
2197 | struct snd_kcontrol *kcontrol, int event) | 2296 | struct snd_kcontrol *kcontrol, int event) |
2198 | { | 2297 | { |
2199 | struct snd_soc_codec *codec = w->codec; | 2298 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
2200 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 2299 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
2201 | 2300 | ||
2202 | switch (event) { | 2301 | switch (event) { |
@@ -2226,6 +2325,45 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
2226 | 0, rt5677_set_pll2_event, SND_SOC_DAPM_PRE_PMU | | 2325 | 0, rt5677_set_pll2_event, SND_SOC_DAPM_PRE_PMU | |
2227 | SND_SOC_DAPM_POST_PMU), | 2326 | SND_SOC_DAPM_POST_PMU), |
2228 | 2327 | ||
2328 | /* ASRC */ | ||
2329 | SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5677_ASRC_1, 0, 0, NULL, 0), | ||
2330 | SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5677_ASRC_1, 1, 0, NULL, 0), | ||
2331 | SND_SOC_DAPM_SUPPLY_S("I2S3 ASRC", 1, RT5677_ASRC_1, 2, 0, NULL, 0), | ||
2332 | SND_SOC_DAPM_SUPPLY_S("I2S4 ASRC", 1, RT5677_ASRC_1, 3, 0, NULL, 0), | ||
2333 | SND_SOC_DAPM_SUPPLY_S("DAC STO ASRC", 1, RT5677_ASRC_2, 14, 0, NULL, 0), | ||
2334 | SND_SOC_DAPM_SUPPLY_S("DAC MONO2 L ASRC", 1, RT5677_ASRC_2, 13, 0, NULL, | ||
2335 | 0), | ||
2336 | SND_SOC_DAPM_SUPPLY_S("DAC MONO2 R ASRC", 1, RT5677_ASRC_2, 12, 0, NULL, | ||
2337 | 0), | ||
2338 | SND_SOC_DAPM_SUPPLY_S("DAC MONO3 L ASRC", 1, RT5677_ASRC_1, 15, 0, NULL, | ||
2339 | 0), | ||
2340 | SND_SOC_DAPM_SUPPLY_S("DAC MONO3 R ASRC", 1, RT5677_ASRC_1, 14, 0, NULL, | ||
2341 | 0), | ||
2342 | SND_SOC_DAPM_SUPPLY_S("DAC MONO4 L ASRC", 1, RT5677_ASRC_1, 13, 0, NULL, | ||
2343 | 0), | ||
2344 | SND_SOC_DAPM_SUPPLY_S("DAC MONO4 R ASRC", 1, RT5677_ASRC_1, 12, 0, NULL, | ||
2345 | 0), | ||
2346 | SND_SOC_DAPM_SUPPLY_S("DMIC STO1 ASRC", 1, RT5677_ASRC_2, 11, 0, NULL, | ||
2347 | 0), | ||
2348 | SND_SOC_DAPM_SUPPLY_S("DMIC STO2 ASRC", 1, RT5677_ASRC_2, 10, 0, NULL, | ||
2349 | 0), | ||
2350 | SND_SOC_DAPM_SUPPLY_S("DMIC STO3 ASRC", 1, RT5677_ASRC_2, 9, 0, NULL, | ||
2351 | 0), | ||
2352 | SND_SOC_DAPM_SUPPLY_S("DMIC STO4 ASRC", 1, RT5677_ASRC_2, 8, 0, NULL, | ||
2353 | 0), | ||
2354 | SND_SOC_DAPM_SUPPLY_S("DMIC MONO L ASRC", 1, RT5677_ASRC_2, 7, 0, NULL, | ||
2355 | 0), | ||
2356 | SND_SOC_DAPM_SUPPLY_S("DMIC MONO R ASRC", 1, RT5677_ASRC_2, 6, 0, NULL, | ||
2357 | 0), | ||
2358 | SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5677_ASRC_2, 5, 0, NULL, 0), | ||
2359 | SND_SOC_DAPM_SUPPLY_S("ADC STO2 ASRC", 1, RT5677_ASRC_2, 4, 0, NULL, 0), | ||
2360 | SND_SOC_DAPM_SUPPLY_S("ADC STO3 ASRC", 1, RT5677_ASRC_2, 3, 0, NULL, 0), | ||
2361 | SND_SOC_DAPM_SUPPLY_S("ADC STO4 ASRC", 1, RT5677_ASRC_2, 2, 0, NULL, 0), | ||
2362 | SND_SOC_DAPM_SUPPLY_S("ADC MONO L ASRC", 1, RT5677_ASRC_2, 1, 0, NULL, | ||
2363 | 0), | ||
2364 | SND_SOC_DAPM_SUPPLY_S("ADC MONO R ASRC", 1, RT5677_ASRC_2, 0, 0, NULL, | ||
2365 | 0), | ||
2366 | |||
2229 | /* Input Side */ | 2367 | /* Input Side */ |
2230 | /* micbias */ | 2368 | /* micbias */ |
2231 | SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5677_PWR_ANLG2, RT5677_PWR_MB1_BIT, | 2369 | SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5677_PWR_ANLG2, RT5677_PWR_MB1_BIT, |
@@ -2656,10 +2794,18 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
2656 | /* DAC Mixer */ | 2794 | /* DAC Mixer */ |
2657 | SND_SOC_DAPM_SUPPLY("dac stereo1 filter", RT5677_PWR_DIG2, | 2795 | SND_SOC_DAPM_SUPPLY("dac stereo1 filter", RT5677_PWR_DIG2, |
2658 | RT5677_PWR_DAC_S1F_BIT, 0, NULL, 0), | 2796 | RT5677_PWR_DAC_S1F_BIT, 0, NULL, 0), |
2659 | SND_SOC_DAPM_SUPPLY("dac mono left filter", RT5677_PWR_DIG2, | 2797 | SND_SOC_DAPM_SUPPLY("dac mono2 left filter", RT5677_PWR_DIG2, |
2660 | RT5677_PWR_DAC_M2F_L_BIT, 0, NULL, 0), | 2798 | RT5677_PWR_DAC_M2F_L_BIT, 0, NULL, 0), |
2661 | SND_SOC_DAPM_SUPPLY("dac mono right filter", RT5677_PWR_DIG2, | 2799 | SND_SOC_DAPM_SUPPLY("dac mono2 right filter", RT5677_PWR_DIG2, |
2662 | RT5677_PWR_DAC_M2F_R_BIT, 0, NULL, 0), | 2800 | RT5677_PWR_DAC_M2F_R_BIT, 0, NULL, 0), |
2801 | SND_SOC_DAPM_SUPPLY("dac mono3 left filter", RT5677_PWR_DIG2, | ||
2802 | RT5677_PWR_DAC_M3F_L_BIT, 0, NULL, 0), | ||
2803 | SND_SOC_DAPM_SUPPLY("dac mono3 right filter", RT5677_PWR_DIG2, | ||
2804 | RT5677_PWR_DAC_M3F_R_BIT, 0, NULL, 0), | ||
2805 | SND_SOC_DAPM_SUPPLY("dac mono4 left filter", RT5677_PWR_DIG2, | ||
2806 | RT5677_PWR_DAC_M4F_L_BIT, 0, NULL, 0), | ||
2807 | SND_SOC_DAPM_SUPPLY("dac mono4 right filter", RT5677_PWR_DIG2, | ||
2808 | RT5677_PWR_DAC_M4F_R_BIT, 0, NULL, 0), | ||
2663 | 2809 | ||
2664 | SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0, | 2810 | SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0, |
2665 | rt5677_sto1_dac_l_mix, ARRAY_SIZE(rt5677_sto1_dac_l_mix)), | 2811 | rt5677_sto1_dac_l_mix, ARRAY_SIZE(rt5677_sto1_dac_l_mix)), |
@@ -2732,6 +2878,31 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { | |||
2732 | }; | 2878 | }; |
2733 | 2879 | ||
2734 | static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | 2880 | static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { |
2881 | { "Stereo1 DMIC Mux", NULL, "DMIC STO1 ASRC", can_use_asrc }, | ||
2882 | { "Stereo2 DMIC Mux", NULL, "DMIC STO2 ASRC", can_use_asrc }, | ||
2883 | { "Stereo3 DMIC Mux", NULL, "DMIC STO3 ASRC", can_use_asrc }, | ||
2884 | { "Stereo4 DMIC Mux", NULL, "DMIC STO4 ASRC", can_use_asrc }, | ||
2885 | { "Mono DMIC L Mux", NULL, "DMIC MONO L ASRC", can_use_asrc }, | ||
2886 | { "Mono DMIC R Mux", NULL, "DMIC MONO R ASRC", can_use_asrc }, | ||
2887 | { "I2S1", NULL, "I2S1 ASRC", can_use_asrc}, | ||
2888 | { "I2S2", NULL, "I2S2 ASRC", can_use_asrc}, | ||
2889 | { "I2S3", NULL, "I2S3 ASRC", can_use_asrc}, | ||
2890 | { "I2S4", NULL, "I2S4 ASRC", can_use_asrc}, | ||
2891 | |||
2892 | { "dac stereo1 filter", NULL, "DAC STO ASRC", is_using_asrc }, | ||
2893 | { "dac mono2 left filter", NULL, "DAC MONO2 L ASRC", is_using_asrc }, | ||
2894 | { "dac mono2 right filter", NULL, "DAC MONO2 R ASRC", is_using_asrc }, | ||
2895 | { "dac mono3 left filter", NULL, "DAC MONO3 L ASRC", is_using_asrc }, | ||
2896 | { "dac mono3 right filter", NULL, "DAC MONO3 R ASRC", is_using_asrc }, | ||
2897 | { "dac mono4 left filter", NULL, "DAC MONO4 L ASRC", is_using_asrc }, | ||
2898 | { "dac mono4 right filter", NULL, "DAC MONO4 R ASRC", is_using_asrc }, | ||
2899 | { "adc stereo1 filter", NULL, "ADC STO1 ASRC", is_using_asrc }, | ||
2900 | { "adc stereo2 filter", NULL, "ADC STO2 ASRC", is_using_asrc }, | ||
2901 | { "adc stereo3 filter", NULL, "ADC STO3 ASRC", is_using_asrc }, | ||
2902 | { "adc stereo4 filter", NULL, "ADC STO4 ASRC", is_using_asrc }, | ||
2903 | { "adc mono left filter", NULL, "ADC MONO L ASRC", is_using_asrc }, | ||
2904 | { "adc mono right filter", NULL, "ADC MONO R ASRC", is_using_asrc }, | ||
2905 | |||
2735 | { "DMIC1", NULL, "DMIC L1" }, | 2906 | { "DMIC1", NULL, "DMIC L1" }, |
2736 | { "DMIC1", NULL, "DMIC R1" }, | 2907 | { "DMIC1", NULL, "DMIC R1" }, |
2737 | { "DMIC2", NULL, "DMIC L2" }, | 2908 | { "DMIC2", NULL, "DMIC L2" }, |
@@ -2862,8 +3033,6 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2862 | 3033 | ||
2863 | { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, | 3034 | { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, |
2864 | { "Stereo1 ADC MIXL", NULL, "adc stereo1 filter" }, | 3035 | { "Stereo1 ADC MIXL", NULL, "adc stereo1 filter" }, |
2865 | { "adc stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
2866 | |||
2867 | { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, | 3036 | { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, |
2868 | { "Stereo1 ADC MIXR", NULL, "adc stereo1 filter" }, | 3037 | { "Stereo1 ADC MIXR", NULL, "adc stereo1 filter" }, |
2869 | { "adc stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll }, | 3038 | { "adc stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll }, |
@@ -2884,8 +3053,6 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2884 | 3053 | ||
2885 | { "Stereo2 ADC MIXL", NULL, "Stereo2 ADC LR Mux" }, | 3054 | { "Stereo2 ADC MIXL", NULL, "Stereo2 ADC LR Mux" }, |
2886 | { "Stereo2 ADC MIXL", NULL, "adc stereo2 filter" }, | 3055 | { "Stereo2 ADC MIXL", NULL, "adc stereo2 filter" }, |
2887 | { "adc stereo2 filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
2888 | |||
2889 | { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" }, | 3056 | { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" }, |
2890 | { "Stereo2 ADC MIXR", NULL, "adc stereo2 filter" }, | 3057 | { "Stereo2 ADC MIXR", NULL, "adc stereo2 filter" }, |
2891 | { "adc stereo2 filter", NULL, "PLL1", is_sys_clk_from_pll }, | 3058 | { "adc stereo2 filter", NULL, "PLL1", is_sys_clk_from_pll }, |
@@ -2900,8 +3067,6 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2900 | 3067 | ||
2901 | { "Stereo3 ADC MIXL", NULL, "Sto3 ADC MIXL" }, | 3068 | { "Stereo3 ADC MIXL", NULL, "Sto3 ADC MIXL" }, |
2902 | { "Stereo3 ADC MIXL", NULL, "adc stereo3 filter" }, | 3069 | { "Stereo3 ADC MIXL", NULL, "adc stereo3 filter" }, |
2903 | { "adc stereo3 filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
2904 | |||
2905 | { "Stereo3 ADC MIXR", NULL, "Sto3 ADC MIXR" }, | 3070 | { "Stereo3 ADC MIXR", NULL, "Sto3 ADC MIXR" }, |
2906 | { "Stereo3 ADC MIXR", NULL, "adc stereo3 filter" }, | 3071 | { "Stereo3 ADC MIXR", NULL, "adc stereo3 filter" }, |
2907 | { "adc stereo3 filter", NULL, "PLL1", is_sys_clk_from_pll }, | 3072 | { "adc stereo3 filter", NULL, "PLL1", is_sys_clk_from_pll }, |
@@ -2916,8 +3081,6 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
2916 | 3081 | ||
2917 | { "Stereo4 ADC MIXL", NULL, "Sto4 ADC MIXL" }, | 3082 | { "Stereo4 ADC MIXL", NULL, "Sto4 ADC MIXL" }, |
2918 | { "Stereo4 ADC MIXL", NULL, "adc stereo4 filter" }, | 3083 | { "Stereo4 ADC MIXL", NULL, "adc stereo4 filter" }, |
2919 | { "adc stereo4 filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
2920 | |||
2921 | { "Stereo4 ADC MIXR", NULL, "Sto4 ADC MIXR" }, | 3084 | { "Stereo4 ADC MIXR", NULL, "Sto4 ADC MIXR" }, |
2922 | { "Stereo4 ADC MIXR", NULL, "adc stereo4 filter" }, | 3085 | { "Stereo4 ADC MIXR", NULL, "adc stereo4 filter" }, |
2923 | { "adc stereo4 filter", NULL, "PLL1", is_sys_clk_from_pll }, | 3086 | { "adc stereo4 filter", NULL, "PLL1", is_sys_clk_from_pll }, |
@@ -3121,8 +3284,8 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
3121 | { "IB45 Bypass Mux", "Bypass", "IB45 Mux" }, | 3284 | { "IB45 Bypass Mux", "Bypass", "IB45 Mux" }, |
3122 | { "IB45 Bypass Mux", "Pass SRC", "IB45 Mux" }, | 3285 | { "IB45 Bypass Mux", "Pass SRC", "IB45 Mux" }, |
3123 | 3286 | ||
3124 | { "IB6 Mux", "IF1 DAC 6", "IF1 DAC6" }, | 3287 | { "IB6 Mux", "IF1 DAC 6", "IF1 DAC6 Mux" }, |
3125 | { "IB6 Mux", "IF2 DAC 6", "IF2 DAC6" }, | 3288 | { "IB6 Mux", "IF2 DAC 6", "IF2 DAC6 Mux" }, |
3126 | { "IB6 Mux", "SLB DAC 6", "SLB DAC6" }, | 3289 | { "IB6 Mux", "SLB DAC 6", "SLB DAC6" }, |
3127 | { "IB6 Mux", "STO4 ADC MIX L", "Stereo4 ADC MIXL" }, | 3290 | { "IB6 Mux", "STO4 ADC MIX L", "Stereo4 ADC MIXL" }, |
3128 | { "IB6 Mux", "IF4 DAC L", "IF4 DAC L" }, | 3291 | { "IB6 Mux", "IF4 DAC L", "IF4 DAC L" }, |
@@ -3130,8 +3293,8 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
3130 | { "IB6 Mux", "STO2 ADC MIX L", "Stereo2 ADC MIXL" }, | 3293 | { "IB6 Mux", "STO2 ADC MIX L", "Stereo2 ADC MIXL" }, |
3131 | { "IB6 Mux", "STO3 ADC MIX L", "Stereo3 ADC MIXL" }, | 3294 | { "IB6 Mux", "STO3 ADC MIX L", "Stereo3 ADC MIXL" }, |
3132 | 3295 | ||
3133 | { "IB7 Mux", "IF1 DAC 7", "IF1 DAC7" }, | 3296 | { "IB7 Mux", "IF1 DAC 7", "IF1 DAC7 Mux" }, |
3134 | { "IB7 Mux", "IF2 DAC 7", "IF2 DAC7" }, | 3297 | { "IB7 Mux", "IF2 DAC 7", "IF2 DAC7 Mux" }, |
3135 | { "IB7 Mux", "SLB DAC 7", "SLB DAC7" }, | 3298 | { "IB7 Mux", "SLB DAC 7", "SLB DAC7" }, |
3136 | { "IB7 Mux", "STO4 ADC MIX R", "Stereo4 ADC MIXR" }, | 3299 | { "IB7 Mux", "STO4 ADC MIX R", "Stereo4 ADC MIXR" }, |
3137 | { "IB7 Mux", "IF4 DAC R", "IF4 DAC R" }, | 3300 | { "IB7 Mux", "IF4 DAC R", "IF4 DAC R" }, |
@@ -3466,23 +3629,21 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
3466 | 3629 | ||
3467 | { "DAC1 MIXL", "Stereo ADC Switch", "ADDA1 Mux" }, | 3630 | { "DAC1 MIXL", "Stereo ADC Switch", "ADDA1 Mux" }, |
3468 | { "DAC1 MIXL", "DAC1 Switch", "DAC1 Mux" }, | 3631 | { "DAC1 MIXL", "DAC1 Switch", "DAC1 Mux" }, |
3469 | { "DAC1 MIXL", NULL, "dac stereo1 filter" }, | ||
3470 | { "DAC1 MIXR", "Stereo ADC Switch", "ADDA1 Mux" }, | 3632 | { "DAC1 MIXR", "Stereo ADC Switch", "ADDA1 Mux" }, |
3471 | { "DAC1 MIXR", "DAC1 Switch", "DAC1 Mux" }, | 3633 | { "DAC1 MIXR", "DAC1 Switch", "DAC1 Mux" }, |
3472 | { "DAC1 MIXR", NULL, "dac stereo1 filter" }, | ||
3473 | 3634 | ||
3474 | { "DAC1 FS", NULL, "DAC1 MIXL" }, | 3635 | { "DAC1 FS", NULL, "DAC1 MIXL" }, |
3475 | { "DAC1 FS", NULL, "DAC1 MIXR" }, | 3636 | { "DAC1 FS", NULL, "DAC1 MIXR" }, |
3476 | 3637 | ||
3477 | { "DAC2 L Mux", "IF1 DAC 2", "IF1 DAC2" }, | 3638 | { "DAC2 L Mux", "IF1 DAC 2", "IF1 DAC2 Mux" }, |
3478 | { "DAC2 L Mux", "IF2 DAC 2", "IF2 DAC2" }, | 3639 | { "DAC2 L Mux", "IF2 DAC 2", "IF2 DAC2 Mux" }, |
3479 | { "DAC2 L Mux", "IF3 DAC L", "IF3 DAC L" }, | 3640 | { "DAC2 L Mux", "IF3 DAC L", "IF3 DAC L" }, |
3480 | { "DAC2 L Mux", "IF4 DAC L", "IF4 DAC L" }, | 3641 | { "DAC2 L Mux", "IF4 DAC L", "IF4 DAC L" }, |
3481 | { "DAC2 L Mux", "SLB DAC 2", "SLB DAC2" }, | 3642 | { "DAC2 L Mux", "SLB DAC 2", "SLB DAC2" }, |
3482 | { "DAC2 L Mux", "OB 2", "OutBound2" }, | 3643 | { "DAC2 L Mux", "OB 2", "OutBound2" }, |
3483 | 3644 | ||
3484 | { "DAC2 R Mux", "IF1 DAC 3", "IF1 DAC3" }, | 3645 | { "DAC2 R Mux", "IF1 DAC 3", "IF1 DAC3 Mux" }, |
3485 | { "DAC2 R Mux", "IF2 DAC 3", "IF2 DAC3" }, | 3646 | { "DAC2 R Mux", "IF2 DAC 3", "IF2 DAC3 Mux" }, |
3486 | { "DAC2 R Mux", "IF3 DAC R", "IF3 DAC R" }, | 3647 | { "DAC2 R Mux", "IF3 DAC R", "IF3 DAC R" }, |
3487 | { "DAC2 R Mux", "IF4 DAC R", "IF4 DAC R" }, | 3648 | { "DAC2 R Mux", "IF4 DAC R", "IF4 DAC R" }, |
3488 | { "DAC2 R Mux", "SLB DAC 3", "SLB DAC3" }, | 3649 | { "DAC2 R Mux", "SLB DAC 3", "SLB DAC3" }, |
@@ -3490,29 +3651,29 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
3490 | { "DAC2 R Mux", "Haptic Generator", "Haptic Generator" }, | 3651 | { "DAC2 R Mux", "Haptic Generator", "Haptic Generator" }, |
3491 | { "DAC2 R Mux", "VAD ADC", "VAD ADC Mux" }, | 3652 | { "DAC2 R Mux", "VAD ADC", "VAD ADC Mux" }, |
3492 | 3653 | ||
3493 | { "DAC3 L Mux", "IF1 DAC 4", "IF1 DAC4" }, | 3654 | { "DAC3 L Mux", "IF1 DAC 4", "IF1 DAC4 Mux" }, |
3494 | { "DAC3 L Mux", "IF2 DAC 4", "IF2 DAC4" }, | 3655 | { "DAC3 L Mux", "IF2 DAC 4", "IF2 DAC4 Mux" }, |
3495 | { "DAC3 L Mux", "IF3 DAC L", "IF3 DAC L" }, | 3656 | { "DAC3 L Mux", "IF3 DAC L", "IF3 DAC L" }, |
3496 | { "DAC3 L Mux", "IF4 DAC L", "IF4 DAC L" }, | 3657 | { "DAC3 L Mux", "IF4 DAC L", "IF4 DAC L" }, |
3497 | { "DAC3 L Mux", "SLB DAC 4", "SLB DAC4" }, | 3658 | { "DAC3 L Mux", "SLB DAC 4", "SLB DAC4" }, |
3498 | { "DAC3 L Mux", "OB 4", "OutBound4" }, | 3659 | { "DAC3 L Mux", "OB 4", "OutBound4" }, |
3499 | 3660 | ||
3500 | { "DAC3 R Mux", "IF1 DAC 5", "IF1 DAC4" }, | 3661 | { "DAC3 R Mux", "IF1 DAC 5", "IF1 DAC5 Mux" }, |
3501 | { "DAC3 R Mux", "IF2 DAC 5", "IF2 DAC4" }, | 3662 | { "DAC3 R Mux", "IF2 DAC 5", "IF2 DAC5 Mux" }, |
3502 | { "DAC3 R Mux", "IF3 DAC R", "IF3 DAC R" }, | 3663 | { "DAC3 R Mux", "IF3 DAC R", "IF3 DAC R" }, |
3503 | { "DAC3 R Mux", "IF4 DAC R", "IF4 DAC R" }, | 3664 | { "DAC3 R Mux", "IF4 DAC R", "IF4 DAC R" }, |
3504 | { "DAC3 R Mux", "SLB DAC 5", "SLB DAC5" }, | 3665 | { "DAC3 R Mux", "SLB DAC 5", "SLB DAC5" }, |
3505 | { "DAC3 R Mux", "OB 5", "OutBound5" }, | 3666 | { "DAC3 R Mux", "OB 5", "OutBound5" }, |
3506 | 3667 | ||
3507 | { "DAC4 L Mux", "IF1 DAC 6", "IF1 DAC6" }, | 3668 | { "DAC4 L Mux", "IF1 DAC 6", "IF1 DAC6 Mux" }, |
3508 | { "DAC4 L Mux", "IF2 DAC 6", "IF2 DAC6" }, | 3669 | { "DAC4 L Mux", "IF2 DAC 6", "IF2 DAC6 Mux" }, |
3509 | { "DAC4 L Mux", "IF3 DAC L", "IF3 DAC L" }, | 3670 | { "DAC4 L Mux", "IF3 DAC L", "IF3 DAC L" }, |
3510 | { "DAC4 L Mux", "IF4 DAC L", "IF4 DAC L" }, | 3671 | { "DAC4 L Mux", "IF4 DAC L", "IF4 DAC L" }, |
3511 | { "DAC4 L Mux", "SLB DAC 6", "SLB DAC6" }, | 3672 | { "DAC4 L Mux", "SLB DAC 6", "SLB DAC6" }, |
3512 | { "DAC4 L Mux", "OB 6", "OutBound6" }, | 3673 | { "DAC4 L Mux", "OB 6", "OutBound6" }, |
3513 | 3674 | ||
3514 | { "DAC4 R Mux", "IF1 DAC 7", "IF1 DAC7" }, | 3675 | { "DAC4 R Mux", "IF1 DAC 7", "IF1 DAC7 Mux" }, |
3515 | { "DAC4 R Mux", "IF2 DAC 7", "IF2 DAC7" }, | 3676 | { "DAC4 R Mux", "IF2 DAC 7", "IF2 DAC7 Mux" }, |
3516 | { "DAC4 R Mux", "IF3 DAC R", "IF3 DAC R" }, | 3677 | { "DAC4 R Mux", "IF3 DAC R", "IF3 DAC R" }, |
3517 | { "DAC4 R Mux", "IF4 DAC R", "IF4 DAC R" }, | 3678 | { "DAC4 R Mux", "IF4 DAC R", "IF4 DAC R" }, |
3518 | { "DAC4 R Mux", "SLB DAC 7", "SLB DAC7" }, | 3679 | { "DAC4 R Mux", "SLB DAC 7", "SLB DAC7" }, |
@@ -3536,35 +3697,46 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
3536 | { "Stereo DAC MIXR", "DAC2 R Switch", "DAC2 R Mux" }, | 3697 | { "Stereo DAC MIXR", "DAC2 R Switch", "DAC2 R Mux" }, |
3537 | { "Stereo DAC MIXR", "DAC1 L Switch", "DAC1 MIXL" }, | 3698 | { "Stereo DAC MIXR", "DAC1 L Switch", "DAC1 MIXL" }, |
3538 | { "Stereo DAC MIXR", NULL, "dac stereo1 filter" }, | 3699 | { "Stereo DAC MIXR", NULL, "dac stereo1 filter" }, |
3700 | { "dac stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
3539 | 3701 | ||
3540 | { "Mono DAC MIXL", "ST L Switch", "Sidetone Mux" }, | 3702 | { "Mono DAC MIXL", "ST L Switch", "Sidetone Mux" }, |
3541 | { "Mono DAC MIXL", "DAC1 L Switch", "DAC1 MIXL" }, | 3703 | { "Mono DAC MIXL", "DAC1 L Switch", "DAC1 MIXL" }, |
3542 | { "Mono DAC MIXL", "DAC2 L Switch", "DAC2 L Mux" }, | 3704 | { "Mono DAC MIXL", "DAC2 L Switch", "DAC2 L Mux" }, |
3543 | { "Mono DAC MIXL", "DAC2 R Switch", "DAC2 R Mux" }, | 3705 | { "Mono DAC MIXL", "DAC2 R Switch", "DAC2 R Mux" }, |
3544 | { "Mono DAC MIXL", NULL, "dac mono left filter" }, | 3706 | { "Mono DAC MIXL", NULL, "dac mono2 left filter" }, |
3707 | { "dac mono2 left filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
3545 | { "Mono DAC MIXR", "ST R Switch", "Sidetone Mux" }, | 3708 | { "Mono DAC MIXR", "ST R Switch", "Sidetone Mux" }, |
3546 | { "Mono DAC MIXR", "DAC1 R Switch", "DAC1 MIXR" }, | 3709 | { "Mono DAC MIXR", "DAC1 R Switch", "DAC1 MIXR" }, |
3547 | { "Mono DAC MIXR", "DAC2 R Switch", "DAC2 R Mux" }, | 3710 | { "Mono DAC MIXR", "DAC2 R Switch", "DAC2 R Mux" }, |
3548 | { "Mono DAC MIXR", "DAC2 L Switch", "DAC2 L Mux" }, | 3711 | { "Mono DAC MIXR", "DAC2 L Switch", "DAC2 L Mux" }, |
3549 | { "Mono DAC MIXR", NULL, "dac mono right filter" }, | 3712 | { "Mono DAC MIXR", NULL, "dac mono2 right filter" }, |
3713 | { "dac mono2 right filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
3550 | 3714 | ||
3551 | { "DD1 MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" }, | 3715 | { "DD1 MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" }, |
3552 | { "DD1 MIXL", "Mono DAC Mix L Switch", "Mono DAC MIXL" }, | 3716 | { "DD1 MIXL", "Mono DAC Mix L Switch", "Mono DAC MIXL" }, |
3553 | { "DD1 MIXL", "DAC3 L Switch", "DAC3 L Mux" }, | 3717 | { "DD1 MIXL", "DAC3 L Switch", "DAC3 L Mux" }, |
3554 | { "DD1 MIXL", "DAC3 R Switch", "DAC3 R Mux" }, | 3718 | { "DD1 MIXL", "DAC3 R Switch", "DAC3 R Mux" }, |
3719 | { "DD1 MIXL", NULL, "dac mono3 left filter" }, | ||
3720 | { "dac mono3 left filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
3555 | { "DD1 MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" }, | 3721 | { "DD1 MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" }, |
3556 | { "DD1 MIXR", "Mono DAC Mix R Switch", "Mono DAC MIXR" }, | 3722 | { "DD1 MIXR", "Mono DAC Mix R Switch", "Mono DAC MIXR" }, |
3557 | { "DD1 MIXR", "DAC3 L Switch", "DAC3 L Mux" }, | 3723 | { "DD1 MIXR", "DAC3 L Switch", "DAC3 L Mux" }, |
3558 | { "DD1 MIXR", "DAC3 R Switch", "DAC3 R Mux" }, | 3724 | { "DD1 MIXR", "DAC3 R Switch", "DAC3 R Mux" }, |
3725 | { "DD1 MIXR", NULL, "dac mono3 right filter" }, | ||
3726 | { "dac mono3 right filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
3559 | 3727 | ||
3560 | { "DD2 MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" }, | 3728 | { "DD2 MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" }, |
3561 | { "DD2 MIXL", "Mono DAC Mix L Switch", "Mono DAC MIXL" }, | 3729 | { "DD2 MIXL", "Mono DAC Mix L Switch", "Mono DAC MIXL" }, |
3562 | { "DD2 MIXL", "DAC4 L Switch", "DAC4 L Mux" }, | 3730 | { "DD2 MIXL", "DAC4 L Switch", "DAC4 L Mux" }, |
3563 | { "DD2 MIXL", "DAC4 R Switch", "DAC4 R Mux" }, | 3731 | { "DD2 MIXL", "DAC4 R Switch", "DAC4 R Mux" }, |
3732 | { "DD2 MIXL", NULL, "dac mono4 left filter" }, | ||
3733 | { "dac mono4 left filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
3564 | { "DD2 MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" }, | 3734 | { "DD2 MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" }, |
3565 | { "DD2 MIXR", "Mono DAC Mix R Switch", "Mono DAC MIXR" }, | 3735 | { "DD2 MIXR", "Mono DAC Mix R Switch", "Mono DAC MIXR" }, |
3566 | { "DD2 MIXR", "DAC4 L Switch", "DAC4 L Mux" }, | 3736 | { "DD2 MIXR", "DAC4 L Switch", "DAC4 L Mux" }, |
3567 | { "DD2 MIXR", "DAC4 R Switch", "DAC4 R Mux" }, | 3737 | { "DD2 MIXR", "DAC4 R Switch", "DAC4 R Mux" }, |
3738 | { "DD2 MIXR", NULL, "dac mono4 right filter" }, | ||
3739 | { "dac mono4 right filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
3568 | 3740 | ||
3569 | { "Stereo DAC MIX", NULL, "Stereo DAC MIXL" }, | 3741 | { "Stereo DAC MIX", NULL, "Stereo DAC MIXL" }, |
3570 | { "Stereo DAC MIX", NULL, "Stereo DAC MIXR" }, | 3742 | { "Stereo DAC MIX", NULL, "Stereo DAC MIXR" }, |
@@ -3586,11 +3758,8 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { | |||
3586 | { "DAC3 SRC Mux", "DD MIX2L", "DD2 MIXL" }, | 3758 | { "DAC3 SRC Mux", "DD MIX2L", "DD2 MIXL" }, |
3587 | 3759 | ||
3588 | { "DAC 1", NULL, "DAC12 SRC Mux" }, | 3760 | { "DAC 1", NULL, "DAC12 SRC Mux" }, |
3589 | { "DAC 1", NULL, "PLL1", is_sys_clk_from_pll }, | ||
3590 | { "DAC 2", NULL, "DAC12 SRC Mux" }, | 3761 | { "DAC 2", NULL, "DAC12 SRC Mux" }, |
3591 | { "DAC 2", NULL, "PLL1", is_sys_clk_from_pll }, | ||
3592 | { "DAC 3", NULL, "DAC3 SRC Mux" }, | 3762 | { "DAC 3", NULL, "DAC3 SRC Mux" }, |
3593 | { "DAC 3", NULL, "PLL1", is_sys_clk_from_pll }, | ||
3594 | 3763 | ||
3595 | { "PDM1 L Mux", "STO1 DAC MIX", "Stereo DAC MIXL" }, | 3764 | { "PDM1 L Mux", "STO1 DAC MIX", "Stereo DAC MIXL" }, |
3596 | { "PDM1 L Mux", "MONO DAC MIX", "Mono DAC MIXL" }, | 3765 | { "PDM1 L Mux", "MONO DAC MIX", "Mono DAC MIXL" }, |
@@ -3937,7 +4106,8 @@ static int rt5677_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
3937 | unsigned int rx_mask, int slots, int slot_width) | 4106 | unsigned int rx_mask, int slots, int slot_width) |
3938 | { | 4107 | { |
3939 | struct snd_soc_codec *codec = dai->codec; | 4108 | struct snd_soc_codec *codec = dai->codec; |
3940 | unsigned int val = 0; | 4109 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); |
4110 | unsigned int val = 0, slot_width_25 = 0; | ||
3941 | 4111 | ||
3942 | if (rx_mask || tx_mask) | 4112 | if (rx_mask || tx_mask) |
3943 | val |= (1 << 12); | 4113 | val |= (1 << 12); |
@@ -3961,6 +4131,8 @@ static int rt5677_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
3961 | case 20: | 4131 | case 20: |
3962 | val |= (1 << 8); | 4132 | val |= (1 << 8); |
3963 | break; | 4133 | break; |
4134 | case 25: | ||
4135 | slot_width_25 = 0x8080; | ||
3964 | case 24: | 4136 | case 24: |
3965 | val |= (2 << 8); | 4137 | val |= (2 << 8); |
3966 | break; | 4138 | break; |
@@ -3974,10 +4146,16 @@ static int rt5677_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
3974 | 4146 | ||
3975 | switch (dai->id) { | 4147 | switch (dai->id) { |
3976 | case RT5677_AIF1: | 4148 | case RT5677_AIF1: |
3977 | snd_soc_update_bits(codec, RT5677_TDM1_CTRL1, 0x1f00, val); | 4149 | regmap_update_bits(rt5677->regmap, RT5677_TDM1_CTRL1, 0x1f00, |
4150 | val); | ||
4151 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x8000, | ||
4152 | slot_width_25); | ||
3978 | break; | 4153 | break; |
3979 | case RT5677_AIF2: | 4154 | case RT5677_AIF2: |
3980 | snd_soc_update_bits(codec, RT5677_TDM2_CTRL1, 0x1f00, val); | 4155 | regmap_update_bits(rt5677->regmap, RT5677_TDM2_CTRL1, 0x1f00, |
4156 | val); | ||
4157 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x80, | ||
4158 | slot_width_25); | ||
3981 | break; | 4159 | break; |
3982 | default: | 4160 | default: |
3983 | break; | 4161 | break; |
@@ -4762,6 +4940,11 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
4762 | RT5677_GPIO5_DIR_OUT); | 4940 | RT5677_GPIO5_DIR_OUT); |
4763 | } | 4941 | } |
4764 | 4942 | ||
4943 | if (rt5677->pdata.micbias1_vdd_3v3) | ||
4944 | regmap_update_bits(rt5677->regmap, RT5677_MICBIAS, | ||
4945 | RT5677_MICBIAS1_CTRL_VDD_MASK, | ||
4946 | RT5677_MICBIAS1_CTRL_VDD_3_3V); | ||
4947 | |||
4765 | rt5677_init_gpio(i2c); | 4948 | rt5677_init_gpio(i2c); |
4766 | rt5677_init_irq(i2c); | 4949 | rt5677_init_irq(i2c); |
4767 | 4950 | ||
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index aa98be32bb60..e182e6569bbd 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -155,18 +155,19 @@ struct sgtl5000_priv { | |||
155 | static int mic_bias_event(struct snd_soc_dapm_widget *w, | 155 | static int mic_bias_event(struct snd_soc_dapm_widget *w, |
156 | struct snd_kcontrol *kcontrol, int event) | 156 | struct snd_kcontrol *kcontrol, int event) |
157 | { | 157 | { |
158 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(w->codec); | 158 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
159 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | ||
159 | 160 | ||
160 | switch (event) { | 161 | switch (event) { |
161 | case SND_SOC_DAPM_POST_PMU: | 162 | case SND_SOC_DAPM_POST_PMU: |
162 | /* change mic bias resistor */ | 163 | /* change mic bias resistor */ |
163 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL, | 164 | snd_soc_update_bits(codec, SGTL5000_CHIP_MIC_CTRL, |
164 | SGTL5000_BIAS_R_MASK, | 165 | SGTL5000_BIAS_R_MASK, |
165 | sgtl5000->micbias_resistor << SGTL5000_BIAS_R_SHIFT); | 166 | sgtl5000->micbias_resistor << SGTL5000_BIAS_R_SHIFT); |
166 | break; | 167 | break; |
167 | 168 | ||
168 | case SND_SOC_DAPM_PRE_PMD: | 169 | case SND_SOC_DAPM_PRE_PMD: |
169 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL, | 170 | snd_soc_update_bits(codec, SGTL5000_CHIP_MIC_CTRL, |
170 | SGTL5000_BIAS_R_MASK, 0); | 171 | SGTL5000_BIAS_R_MASK, 0); |
171 | break; | 172 | break; |
172 | } | 173 | } |
@@ -181,11 +182,12 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, | |||
181 | static int power_vag_event(struct snd_soc_dapm_widget *w, | 182 | static int power_vag_event(struct snd_soc_dapm_widget *w, |
182 | struct snd_kcontrol *kcontrol, int event) | 183 | struct snd_kcontrol *kcontrol, int event) |
183 | { | 184 | { |
185 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
184 | const u32 mask = SGTL5000_DAC_POWERUP | SGTL5000_ADC_POWERUP; | 186 | const u32 mask = SGTL5000_DAC_POWERUP | SGTL5000_ADC_POWERUP; |
185 | 187 | ||
186 | switch (event) { | 188 | switch (event) { |
187 | case SND_SOC_DAPM_POST_PMU: | 189 | case SND_SOC_DAPM_POST_PMU: |
188 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, | 190 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, |
189 | SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); | 191 | SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); |
190 | break; | 192 | break; |
191 | 193 | ||
@@ -195,9 +197,9 @@ static int power_vag_event(struct snd_soc_dapm_widget *w, | |||
195 | * operational to prevent inadvertently starving the | 197 | * operational to prevent inadvertently starving the |
196 | * other one of them. | 198 | * other one of them. |
197 | */ | 199 | */ |
198 | if ((snd_soc_read(w->codec, SGTL5000_CHIP_ANA_POWER) & | 200 | if ((snd_soc_read(codec, SGTL5000_CHIP_ANA_POWER) & |
199 | mask) != mask) { | 201 | mask) != mask) { |
200 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, | 202 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, |
201 | SGTL5000_VAG_POWERUP, 0); | 203 | SGTL5000_VAG_POWERUP, 0); |
202 | msleep(400); | 204 | msleep(400); |
203 | } | 205 | } |
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 1f451a1946eb..47b257e41809 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c | |||
@@ -233,16 +233,18 @@ static int sn95031_set_vaud_bias(struct snd_soc_codec *codec, | |||
233 | static int sn95031_vhs_event(struct snd_soc_dapm_widget *w, | 233 | static int sn95031_vhs_event(struct snd_soc_dapm_widget *w, |
234 | struct snd_kcontrol *kcontrol, int event) | 234 | struct snd_kcontrol *kcontrol, int event) |
235 | { | 235 | { |
236 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
237 | |||
236 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 238 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
237 | pr_debug("VHS SND_SOC_DAPM_EVENT_ON doing rail startup now\n"); | 239 | pr_debug("VHS SND_SOC_DAPM_EVENT_ON doing rail startup now\n"); |
238 | /* power up the rail */ | 240 | /* power up the rail */ |
239 | snd_soc_write(w->codec, SN95031_VHSP, 0x3D); | 241 | snd_soc_write(codec, SN95031_VHSP, 0x3D); |
240 | snd_soc_write(w->codec, SN95031_VHSN, 0x3F); | 242 | snd_soc_write(codec, SN95031_VHSN, 0x3F); |
241 | msleep(1); | 243 | msleep(1); |
242 | } else if (SND_SOC_DAPM_EVENT_OFF(event)) { | 244 | } else if (SND_SOC_DAPM_EVENT_OFF(event)) { |
243 | pr_debug("VHS SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n"); | 245 | pr_debug("VHS SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n"); |
244 | snd_soc_write(w->codec, SN95031_VHSP, 0xC4); | 246 | snd_soc_write(codec, SN95031_VHSP, 0xC4); |
245 | snd_soc_write(w->codec, SN95031_VHSN, 0x04); | 247 | snd_soc_write(codec, SN95031_VHSN, 0x04); |
246 | } | 248 | } |
247 | return 0; | 249 | return 0; |
248 | } | 250 | } |
@@ -250,14 +252,16 @@ static int sn95031_vhs_event(struct snd_soc_dapm_widget *w, | |||
250 | static int sn95031_vihf_event(struct snd_soc_dapm_widget *w, | 252 | static int sn95031_vihf_event(struct snd_soc_dapm_widget *w, |
251 | struct snd_kcontrol *kcontrol, int event) | 253 | struct snd_kcontrol *kcontrol, int event) |
252 | { | 254 | { |
255 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
256 | |||
253 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 257 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
254 | pr_debug("VIHF SND_SOC_DAPM_EVENT_ON doing rail startup now\n"); | 258 | pr_debug("VIHF SND_SOC_DAPM_EVENT_ON doing rail startup now\n"); |
255 | /* power up the rail */ | 259 | /* power up the rail */ |
256 | snd_soc_write(w->codec, SN95031_VIHF, 0x27); | 260 | snd_soc_write(codec, SN95031_VIHF, 0x27); |
257 | msleep(1); | 261 | msleep(1); |
258 | } else if (SND_SOC_DAPM_EVENT_OFF(event)) { | 262 | } else if (SND_SOC_DAPM_EVENT_OFF(event)) { |
259 | pr_debug("VIHF SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n"); | 263 | pr_debug("VIHF SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n"); |
260 | snd_soc_write(w->codec, SN95031_VIHF, 0x24); | 264 | snd_soc_write(codec, SN95031_VIHF, 0x24); |
261 | } | 265 | } |
262 | return 0; | 266 | return 0; |
263 | } | 267 | } |
@@ -265,6 +269,7 @@ static int sn95031_vihf_event(struct snd_soc_dapm_widget *w, | |||
265 | static int sn95031_dmic12_event(struct snd_soc_dapm_widget *w, | 269 | static int sn95031_dmic12_event(struct snd_soc_dapm_widget *w, |
266 | struct snd_kcontrol *k, int event) | 270 | struct snd_kcontrol *k, int event) |
267 | { | 271 | { |
272 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
268 | unsigned int ldo = 0, clk_dir = 0, data_dir = 0; | 273 | unsigned int ldo = 0, clk_dir = 0, data_dir = 0; |
269 | 274 | ||
270 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 275 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
@@ -273,15 +278,16 @@ static int sn95031_dmic12_event(struct snd_soc_dapm_widget *w, | |||
273 | data_dir = BIT(7); | 278 | data_dir = BIT(7); |
274 | } | 279 | } |
275 | /* program DMIC LDO, clock and set clock */ | 280 | /* program DMIC LDO, clock and set clock */ |
276 | snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo); | 281 | snd_soc_update_bits(codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo); |
277 | snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(0), clk_dir); | 282 | snd_soc_update_bits(codec, SN95031_DMICBUF0123, BIT(0), clk_dir); |
278 | snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(7), data_dir); | 283 | snd_soc_update_bits(codec, SN95031_DMICBUF0123, BIT(7), data_dir); |
279 | return 0; | 284 | return 0; |
280 | } | 285 | } |
281 | 286 | ||
282 | static int sn95031_dmic34_event(struct snd_soc_dapm_widget *w, | 287 | static int sn95031_dmic34_event(struct snd_soc_dapm_widget *w, |
283 | struct snd_kcontrol *k, int event) | 288 | struct snd_kcontrol *k, int event) |
284 | { | 289 | { |
290 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
285 | unsigned int ldo = 0, clk_dir = 0, data_dir = 0; | 291 | unsigned int ldo = 0, clk_dir = 0, data_dir = 0; |
286 | 292 | ||
287 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 293 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
@@ -290,22 +296,23 @@ static int sn95031_dmic34_event(struct snd_soc_dapm_widget *w, | |||
290 | data_dir = BIT(1); | 296 | data_dir = BIT(1); |
291 | } | 297 | } |
292 | /* program DMIC LDO, clock and set clock */ | 298 | /* program DMIC LDO, clock and set clock */ |
293 | snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo); | 299 | snd_soc_update_bits(codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo); |
294 | snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(2), clk_dir); | 300 | snd_soc_update_bits(codec, SN95031_DMICBUF0123, BIT(2), clk_dir); |
295 | snd_soc_update_bits(w->codec, SN95031_DMICBUF45, BIT(1), data_dir); | 301 | snd_soc_update_bits(codec, SN95031_DMICBUF45, BIT(1), data_dir); |
296 | return 0; | 302 | return 0; |
297 | } | 303 | } |
298 | 304 | ||
299 | static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w, | 305 | static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w, |
300 | struct snd_kcontrol *k, int event) | 306 | struct snd_kcontrol *k, int event) |
301 | { | 307 | { |
308 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
302 | unsigned int ldo = 0; | 309 | unsigned int ldo = 0; |
303 | 310 | ||
304 | if (SND_SOC_DAPM_EVENT_ON(event)) | 311 | if (SND_SOC_DAPM_EVENT_ON(event)) |
305 | ldo = BIT(7)|BIT(6); | 312 | ldo = BIT(7)|BIT(6); |
306 | 313 | ||
307 | /* program DMIC LDO */ | 314 | /* program DMIC LDO */ |
308 | snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(7)|BIT(6), ldo); | 315 | snd_soc_update_bits(codec, SN95031_MICBIAS, BIT(7)|BIT(6), ldo); |
309 | return 0; | 316 | return 0; |
310 | } | 317 | } |
311 | 318 | ||
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 7e18200dd6a9..3a1343fa109b 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -24,8 +24,11 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
27 | #include <linux/of_device.h> | ||
28 | #include <linux/of_gpio.h> | ||
27 | #include <linux/regmap.h> | 29 | #include <linux/regmap.h> |
28 | #include <linux/regulator/consumer.h> | 30 | #include <linux/regulator/consumer.h> |
31 | #include <linux/gpio/consumer.h> | ||
29 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
30 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
31 | #include <sound/core.h> | 34 | #include <sound/core.h> |
@@ -102,6 +105,35 @@ static const struct reg_default sta32x_regs[] = { | |||
102 | { 0x2c, 0x0c }, | 105 | { 0x2c, 0x0c }, |
103 | }; | 106 | }; |
104 | 107 | ||
108 | static const struct regmap_range sta32x_write_regs_range[] = { | ||
109 | regmap_reg_range(STA32X_CONFA, STA32X_AUTO2), | ||
110 | regmap_reg_range(STA32X_C1CFG, STA32X_FDRC2), | ||
111 | }; | ||
112 | |||
113 | static const struct regmap_range sta32x_read_regs_range[] = { | ||
114 | regmap_reg_range(STA32X_CONFA, STA32X_AUTO2), | ||
115 | regmap_reg_range(STA32X_C1CFG, STA32X_FDRC2), | ||
116 | }; | ||
117 | |||
118 | static const struct regmap_range sta32x_volatile_regs_range[] = { | ||
119 | regmap_reg_range(STA32X_CFADDR2, STA32X_CFUD), | ||
120 | }; | ||
121 | |||
122 | static const struct regmap_access_table sta32x_write_regs = { | ||
123 | .yes_ranges = sta32x_write_regs_range, | ||
124 | .n_yes_ranges = ARRAY_SIZE(sta32x_write_regs_range), | ||
125 | }; | ||
126 | |||
127 | static const struct regmap_access_table sta32x_read_regs = { | ||
128 | .yes_ranges = sta32x_read_regs_range, | ||
129 | .n_yes_ranges = ARRAY_SIZE(sta32x_read_regs_range), | ||
130 | }; | ||
131 | |||
132 | static const struct regmap_access_table sta32x_volatile_regs = { | ||
133 | .yes_ranges = sta32x_volatile_regs_range, | ||
134 | .n_yes_ranges = ARRAY_SIZE(sta32x_volatile_regs_range), | ||
135 | }; | ||
136 | |||
105 | /* regulator power supply names */ | 137 | /* regulator power supply names */ |
106 | static const char *sta32x_supply_names[] = { | 138 | static const char *sta32x_supply_names[] = { |
107 | "Vdda", /* analog supply, 3.3VV */ | 139 | "Vdda", /* analog supply, 3.3VV */ |
@@ -122,6 +154,8 @@ struct sta32x_priv { | |||
122 | u32 coef_shadow[STA32X_COEF_COUNT]; | 154 | u32 coef_shadow[STA32X_COEF_COUNT]; |
123 | struct delayed_work watchdog_work; | 155 | struct delayed_work watchdog_work; |
124 | int shutdown; | 156 | int shutdown; |
157 | struct gpio_desc *gpiod_nreset; | ||
158 | struct mutex coeff_lock; | ||
125 | }; | 159 | }; |
126 | 160 | ||
127 | static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1); | 161 | static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1); |
@@ -155,37 +189,32 @@ static const char *sta32x_limiter_release_rate[] = { | |||
155 | "0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299", | 189 | "0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299", |
156 | "0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137", | 190 | "0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137", |
157 | "0.0134", "0.0117", "0.0110", "0.0104" }; | 191 | "0.0134", "0.0117", "0.0110", "0.0104" }; |
158 | 192 | static DECLARE_TLV_DB_RANGE(sta32x_limiter_ac_attack_tlv, | |
159 | static const unsigned int sta32x_limiter_ac_attack_tlv[] = { | ||
160 | TLV_DB_RANGE_HEAD(2), | ||
161 | 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0), | 193 | 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0), |
162 | 8, 16, TLV_DB_SCALE_ITEM(300, 100, 0), | 194 | 8, 16, TLV_DB_SCALE_ITEM(300, 100, 0), |
163 | }; | 195 | ); |
164 | 196 | ||
165 | static const unsigned int sta32x_limiter_ac_release_tlv[] = { | 197 | static DECLARE_TLV_DB_RANGE(sta32x_limiter_ac_release_tlv, |
166 | TLV_DB_RANGE_HEAD(5), | ||
167 | 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), | 198 | 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), |
168 | 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0), | 199 | 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0), |
169 | 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0), | 200 | 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0), |
170 | 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0), | 201 | 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0), |
171 | 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0), | 202 | 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0), |
172 | }; | 203 | ); |
173 | 204 | ||
174 | static const unsigned int sta32x_limiter_drc_attack_tlv[] = { | 205 | static DECLARE_TLV_DB_RANGE(sta32x_limiter_drc_attack_tlv, |
175 | TLV_DB_RANGE_HEAD(3), | ||
176 | 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0), | 206 | 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0), |
177 | 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0), | 207 | 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0), |
178 | 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0), | 208 | 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0), |
179 | }; | 209 | ); |
180 | 210 | ||
181 | static const unsigned int sta32x_limiter_drc_release_tlv[] = { | 211 | static DECLARE_TLV_DB_RANGE(sta32x_limiter_drc_release_tlv, |
182 | TLV_DB_RANGE_HEAD(5), | ||
183 | 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), | 212 | 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), |
184 | 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0), | 213 | 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0), |
185 | 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0), | 214 | 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0), |
186 | 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0), | 215 | 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0), |
187 | 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0), | 216 | 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0), |
188 | }; | 217 | ); |
189 | 218 | ||
190 | static SOC_ENUM_SINGLE_DECL(sta32x_drc_ac_enum, | 219 | static SOC_ENUM_SINGLE_DECL(sta32x_drc_ac_enum, |
191 | STA32X_CONFD, STA32X_CONFD_DRC_SHIFT, | 220 | STA32X_CONFD, STA32X_CONFD_DRC_SHIFT, |
@@ -244,29 +273,42 @@ static int sta32x_coefficient_get(struct snd_kcontrol *kcontrol, | |||
244 | struct snd_ctl_elem_value *ucontrol) | 273 | struct snd_ctl_elem_value *ucontrol) |
245 | { | 274 | { |
246 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 275 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
276 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | ||
247 | int numcoef = kcontrol->private_value >> 16; | 277 | int numcoef = kcontrol->private_value >> 16; |
248 | int index = kcontrol->private_value & 0xffff; | 278 | int index = kcontrol->private_value & 0xffff; |
249 | unsigned int cfud; | 279 | unsigned int cfud, val; |
250 | int i; | 280 | int i, ret = 0; |
281 | |||
282 | mutex_lock(&sta32x->coeff_lock); | ||
251 | 283 | ||
252 | /* preserve reserved bits in STA32X_CFUD */ | 284 | /* preserve reserved bits in STA32X_CFUD */ |
253 | cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; | 285 | regmap_read(sta32x->regmap, STA32X_CFUD, &cfud); |
254 | /* chip documentation does not say if the bits are self clearing, | 286 | cfud &= 0xf0; |
255 | * so do it explicitly */ | 287 | /* |
256 | snd_soc_write(codec, STA32X_CFUD, cfud); | 288 | * chip documentation does not say if the bits are self clearing, |
289 | * so do it explicitly | ||
290 | */ | ||
291 | regmap_write(sta32x->regmap, STA32X_CFUD, cfud); | ||
257 | 292 | ||
258 | snd_soc_write(codec, STA32X_CFADDR2, index); | 293 | regmap_write(sta32x->regmap, STA32X_CFADDR2, index); |
259 | if (numcoef == 1) | 294 | if (numcoef == 1) { |
260 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x04); | 295 | regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x04); |
261 | else if (numcoef == 5) | 296 | } else if (numcoef == 5) { |
262 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x08); | 297 | regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x08); |
263 | else | 298 | } else { |
264 | return -EINVAL; | 299 | ret = -EINVAL; |
265 | for (i = 0; i < 3 * numcoef; i++) | 300 | goto exit_unlock; |
266 | ucontrol->value.bytes.data[i] = | 301 | } |
267 | snd_soc_read(codec, STA32X_B1CF1 + i); | ||
268 | 302 | ||
269 | return 0; | 303 | for (i = 0; i < 3 * numcoef; i++) { |
304 | regmap_read(sta32x->regmap, STA32X_B1CF1 + i, &val); | ||
305 | ucontrol->value.bytes.data[i] = val; | ||
306 | } | ||
307 | |||
308 | exit_unlock: | ||
309 | mutex_unlock(&sta32x->coeff_lock); | ||
310 | |||
311 | return ret; | ||
270 | } | 312 | } |
271 | 313 | ||
272 | static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol, | 314 | static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol, |
@@ -280,24 +322,27 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol, | |||
280 | int i; | 322 | int i; |
281 | 323 | ||
282 | /* preserve reserved bits in STA32X_CFUD */ | 324 | /* preserve reserved bits in STA32X_CFUD */ |
283 | cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; | 325 | regmap_read(sta32x->regmap, STA32X_CFUD, &cfud); |
284 | /* chip documentation does not say if the bits are self clearing, | 326 | cfud &= 0xf0; |
285 | * so do it explicitly */ | 327 | /* |
286 | snd_soc_write(codec, STA32X_CFUD, cfud); | 328 | * chip documentation does not say if the bits are self clearing, |
329 | * so do it explicitly | ||
330 | */ | ||
331 | regmap_write(sta32x->regmap, STA32X_CFUD, cfud); | ||
287 | 332 | ||
288 | snd_soc_write(codec, STA32X_CFADDR2, index); | 333 | regmap_write(sta32x->regmap, STA32X_CFADDR2, index); |
289 | for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++) | 334 | for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++) |
290 | sta32x->coef_shadow[index + i] = | 335 | sta32x->coef_shadow[index + i] = |
291 | (ucontrol->value.bytes.data[3 * i] << 16) | 336 | (ucontrol->value.bytes.data[3 * i] << 16) |
292 | | (ucontrol->value.bytes.data[3 * i + 1] << 8) | 337 | | (ucontrol->value.bytes.data[3 * i + 1] << 8) |
293 | | (ucontrol->value.bytes.data[3 * i + 2]); | 338 | | (ucontrol->value.bytes.data[3 * i + 2]); |
294 | for (i = 0; i < 3 * numcoef; i++) | 339 | for (i = 0; i < 3 * numcoef; i++) |
295 | snd_soc_write(codec, STA32X_B1CF1 + i, | 340 | regmap_write(sta32x->regmap, STA32X_B1CF1 + i, |
296 | ucontrol->value.bytes.data[i]); | 341 | ucontrol->value.bytes.data[i]); |
297 | if (numcoef == 1) | 342 | if (numcoef == 1) |
298 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x01); | 343 | regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x01); |
299 | else if (numcoef == 5) | 344 | else if (numcoef == 5) |
300 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x02); | 345 | regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x02); |
301 | else | 346 | else |
302 | return -EINVAL; | 347 | return -EINVAL; |
303 | 348 | ||
@@ -311,20 +356,23 @@ static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec) | |||
311 | int i; | 356 | int i; |
312 | 357 | ||
313 | /* preserve reserved bits in STA32X_CFUD */ | 358 | /* preserve reserved bits in STA32X_CFUD */ |
314 | cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; | 359 | regmap_read(sta32x->regmap, STA32X_CFUD, &cfud); |
360 | cfud &= 0xf0; | ||
315 | 361 | ||
316 | for (i = 0; i < STA32X_COEF_COUNT; i++) { | 362 | for (i = 0; i < STA32X_COEF_COUNT; i++) { |
317 | snd_soc_write(codec, STA32X_CFADDR2, i); | 363 | regmap_write(sta32x->regmap, STA32X_CFADDR2, i); |
318 | snd_soc_write(codec, STA32X_B1CF1, | 364 | regmap_write(sta32x->regmap, STA32X_B1CF1, |
319 | (sta32x->coef_shadow[i] >> 16) & 0xff); | 365 | (sta32x->coef_shadow[i] >> 16) & 0xff); |
320 | snd_soc_write(codec, STA32X_B1CF2, | 366 | regmap_write(sta32x->regmap, STA32X_B1CF2, |
321 | (sta32x->coef_shadow[i] >> 8) & 0xff); | 367 | (sta32x->coef_shadow[i] >> 8) & 0xff); |
322 | snd_soc_write(codec, STA32X_B1CF3, | 368 | regmap_write(sta32x->regmap, STA32X_B1CF3, |
323 | (sta32x->coef_shadow[i]) & 0xff); | 369 | (sta32x->coef_shadow[i]) & 0xff); |
324 | /* chip documentation does not say if the bits are | 370 | /* |
325 | * self-clearing, so do it explicitly */ | 371 | * chip documentation does not say if the bits are |
326 | snd_soc_write(codec, STA32X_CFUD, cfud); | 372 | * self-clearing, so do it explicitly |
327 | snd_soc_write(codec, STA32X_CFUD, cfud | 0x01); | 373 | */ |
374 | regmap_write(sta32x->regmap, STA32X_CFUD, cfud); | ||
375 | regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x01); | ||
328 | } | 376 | } |
329 | return 0; | 377 | return 0; |
330 | } | 378 | } |
@@ -336,11 +384,11 @@ static int sta32x_cache_sync(struct snd_soc_codec *codec) | |||
336 | int rc; | 384 | int rc; |
337 | 385 | ||
338 | /* mute during register sync */ | 386 | /* mute during register sync */ |
339 | mute = snd_soc_read(codec, STA32X_MMUTE); | 387 | regmap_read(sta32x->regmap, STA32X_MMUTE, &mute); |
340 | snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); | 388 | regmap_write(sta32x->regmap, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); |
341 | sta32x_sync_coef_shadow(codec); | 389 | sta32x_sync_coef_shadow(codec); |
342 | rc = regcache_sync(sta32x->regmap); | 390 | rc = regcache_sync(sta32x->regmap); |
343 | snd_soc_write(codec, STA32X_MMUTE, mute); | 391 | regmap_write(sta32x->regmap, STA32X_MMUTE, mute); |
344 | return rc; | 392 | return rc; |
345 | } | 393 | } |
346 | 394 | ||
@@ -508,17 +556,12 @@ static struct { | |||
508 | }; | 556 | }; |
509 | 557 | ||
510 | /* MCLK to fs clock ratios */ | 558 | /* MCLK to fs clock ratios */ |
511 | static struct { | 559 | static int mcs_ratio_table[3][7] = { |
512 | int ratio; | 560 | { 768, 512, 384, 256, 128, 576, 0 }, |
513 | int mcs; | 561 | { 384, 256, 192, 128, 64, 0 }, |
514 | } mclk_ratios[3][7] = { | 562 | { 384, 256, 192, 128, 64, 0 }, |
515 | { { 768, 0 }, { 512, 1 }, { 384, 2 }, { 256, 3 }, | ||
516 | { 128, 4 }, { 576, 5 }, { 0, 0 } }, | ||
517 | { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } }, | ||
518 | { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } }, | ||
519 | }; | 563 | }; |
520 | 564 | ||
521 | |||
522 | /** | 565 | /** |
523 | * sta32x_set_dai_sysclk - configure MCLK | 566 | * sta32x_set_dai_sysclk - configure MCLK |
524 | * @codec_dai: the codec DAI | 567 | * @codec_dai: the codec DAI |
@@ -543,46 +586,10 @@ static int sta32x_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
543 | { | 586 | { |
544 | struct snd_soc_codec *codec = codec_dai->codec; | 587 | struct snd_soc_codec *codec = codec_dai->codec; |
545 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | 588 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); |
546 | int i, j, ir, fs; | ||
547 | unsigned int rates = 0; | ||
548 | unsigned int rate_min = -1; | ||
549 | unsigned int rate_max = 0; | ||
550 | 589 | ||
551 | pr_debug("mclk=%u\n", freq); | 590 | dev_dbg(codec->dev, "mclk=%u\n", freq); |
552 | sta32x->mclk = freq; | 591 | sta32x->mclk = freq; |
553 | 592 | ||
554 | if (sta32x->mclk) { | ||
555 | for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) { | ||
556 | ir = interpolation_ratios[i].ir; | ||
557 | fs = interpolation_ratios[i].fs; | ||
558 | for (j = 0; mclk_ratios[ir][j].ratio; j++) { | ||
559 | if (mclk_ratios[ir][j].ratio * fs == freq) { | ||
560 | rates |= snd_pcm_rate_to_rate_bit(fs); | ||
561 | if (fs < rate_min) | ||
562 | rate_min = fs; | ||
563 | if (fs > rate_max) | ||
564 | rate_max = fs; | ||
565 | break; | ||
566 | } | ||
567 | } | ||
568 | } | ||
569 | /* FIXME: soc should support a rate list */ | ||
570 | rates &= ~SNDRV_PCM_RATE_KNOT; | ||
571 | |||
572 | if (!rates) { | ||
573 | dev_err(codec->dev, "could not find a valid sample rate\n"); | ||
574 | return -EINVAL; | ||
575 | } | ||
576 | } else { | ||
577 | /* enable all possible rates */ | ||
578 | rates = STA32X_RATES; | ||
579 | rate_min = 32000; | ||
580 | rate_max = 192000; | ||
581 | } | ||
582 | |||
583 | codec_dai->driver->playback.rates = rates; | ||
584 | codec_dai->driver->playback.rate_min = rate_min; | ||
585 | codec_dai->driver->playback.rate_max = rate_max; | ||
586 | return 0; | 593 | return 0; |
587 | } | 594 | } |
588 | 595 | ||
@@ -599,10 +606,7 @@ static int sta32x_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
599 | { | 606 | { |
600 | struct snd_soc_codec *codec = codec_dai->codec; | 607 | struct snd_soc_codec *codec = codec_dai->codec; |
601 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | 608 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); |
602 | u8 confb = snd_soc_read(codec, STA32X_CONFB); | 609 | u8 confb = 0; |
603 | |||
604 | pr_debug("\n"); | ||
605 | confb &= ~(STA32X_CONFB_C1IM | STA32X_CONFB_C2IM); | ||
606 | 610 | ||
607 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 611 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
608 | case SND_SOC_DAIFMT_CBS_CFS: | 612 | case SND_SOC_DAIFMT_CBS_CFS: |
@@ -632,8 +636,8 @@ static int sta32x_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
632 | return -EINVAL; | 636 | return -EINVAL; |
633 | } | 637 | } |
634 | 638 | ||
635 | snd_soc_write(codec, STA32X_CONFB, confb); | 639 | return regmap_update_bits(sta32x->regmap, STA32X_CONFB, |
636 | return 0; | 640 | STA32X_CONFB_C1IM | STA32X_CONFB_C2IM, confb); |
637 | } | 641 | } |
638 | 642 | ||
639 | /** | 643 | /** |
@@ -651,39 +655,55 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, | |||
651 | { | 655 | { |
652 | struct snd_soc_codec *codec = dai->codec; | 656 | struct snd_soc_codec *codec = dai->codec; |
653 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | 657 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); |
654 | unsigned int rate; | 658 | int i, mcs = -EINVAL, ir = -EINVAL; |
655 | int i, mcs = -1, ir = -1; | 659 | unsigned int confa, confb; |
656 | u8 confa, confb; | 660 | unsigned int rate, ratio; |
661 | int ret; | ||
662 | |||
663 | if (!sta32x->mclk) { | ||
664 | dev_err(codec->dev, | ||
665 | "sta32x->mclk is unset. Unable to determine ratio\n"); | ||
666 | return -EIO; | ||
667 | } | ||
657 | 668 | ||
658 | rate = params_rate(params); | 669 | rate = params_rate(params); |
659 | pr_debug("rate: %u\n", rate); | 670 | ratio = sta32x->mclk / rate; |
660 | for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) | 671 | dev_dbg(codec->dev, "rate: %u, ratio: %u\n", rate, ratio); |
672 | |||
673 | for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) { | ||
661 | if (interpolation_ratios[i].fs == rate) { | 674 | if (interpolation_ratios[i].fs == rate) { |
662 | ir = interpolation_ratios[i].ir; | 675 | ir = interpolation_ratios[i].ir; |
663 | break; | 676 | break; |
664 | } | 677 | } |
665 | if (ir < 0) | 678 | } |
679 | |||
680 | if (ir < 0) { | ||
681 | dev_err(codec->dev, "Unsupported samplerate: %u\n", rate); | ||
666 | return -EINVAL; | 682 | return -EINVAL; |
667 | for (i = 0; mclk_ratios[ir][i].ratio; i++) | 683 | } |
668 | if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) { | 684 | |
669 | mcs = mclk_ratios[ir][i].mcs; | 685 | for (i = 0; i < 6; i++) { |
686 | if (mcs_ratio_table[ir][i] == ratio) { | ||
687 | mcs = i; | ||
670 | break; | 688 | break; |
671 | } | 689 | } |
672 | if (mcs < 0) | 690 | } |
691 | |||
692 | if (mcs < 0) { | ||
693 | dev_err(codec->dev, "Unresolvable ratio: %u\n", ratio); | ||
673 | return -EINVAL; | 694 | return -EINVAL; |
695 | } | ||
674 | 696 | ||
675 | confa = snd_soc_read(codec, STA32X_CONFA); | 697 | confa = (ir << STA32X_CONFA_IR_SHIFT) | |
676 | confa &= ~(STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK); | 698 | (mcs << STA32X_CONFA_MCS_SHIFT); |
677 | confa |= (ir << STA32X_CONFA_IR_SHIFT) | (mcs << STA32X_CONFA_MCS_SHIFT); | 699 | confb = 0; |
678 | 700 | ||
679 | confb = snd_soc_read(codec, STA32X_CONFB); | ||
680 | confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB); | ||
681 | switch (params_width(params)) { | 701 | switch (params_width(params)) { |
682 | case 24: | 702 | case 24: |
683 | pr_debug("24bit\n"); | 703 | dev_dbg(codec->dev, "24bit\n"); |
684 | /* fall through */ | 704 | /* fall through */ |
685 | case 32: | 705 | case 32: |
686 | pr_debug("24bit or 32bit\n"); | 706 | dev_dbg(codec->dev, "24bit or 32bit\n"); |
687 | switch (sta32x->format) { | 707 | switch (sta32x->format) { |
688 | case SND_SOC_DAIFMT_I2S: | 708 | case SND_SOC_DAIFMT_I2S: |
689 | confb |= 0x0; | 709 | confb |= 0x0; |
@@ -698,7 +718,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, | |||
698 | 718 | ||
699 | break; | 719 | break; |
700 | case 20: | 720 | case 20: |
701 | pr_debug("20bit\n"); | 721 | dev_dbg(codec->dev, "20bit\n"); |
702 | switch (sta32x->format) { | 722 | switch (sta32x->format) { |
703 | case SND_SOC_DAIFMT_I2S: | 723 | case SND_SOC_DAIFMT_I2S: |
704 | confb |= 0x4; | 724 | confb |= 0x4; |
@@ -713,7 +733,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, | |||
713 | 733 | ||
714 | break; | 734 | break; |
715 | case 18: | 735 | case 18: |
716 | pr_debug("18bit\n"); | 736 | dev_dbg(codec->dev, "18bit\n"); |
717 | switch (sta32x->format) { | 737 | switch (sta32x->format) { |
718 | case SND_SOC_DAIFMT_I2S: | 738 | case SND_SOC_DAIFMT_I2S: |
719 | confb |= 0x8; | 739 | confb |= 0x8; |
@@ -728,7 +748,7 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, | |||
728 | 748 | ||
729 | break; | 749 | break; |
730 | case 16: | 750 | case 16: |
731 | pr_debug("16bit\n"); | 751 | dev_dbg(codec->dev, "16bit\n"); |
732 | switch (sta32x->format) { | 752 | switch (sta32x->format) { |
733 | case SND_SOC_DAIFMT_I2S: | 753 | case SND_SOC_DAIFMT_I2S: |
734 | confb |= 0x0; | 754 | confb |= 0x0; |
@@ -746,8 +766,30 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, | |||
746 | return -EINVAL; | 766 | return -EINVAL; |
747 | } | 767 | } |
748 | 768 | ||
749 | snd_soc_write(codec, STA32X_CONFA, confa); | 769 | ret = regmap_update_bits(sta32x->regmap, STA32X_CONFA, |
750 | snd_soc_write(codec, STA32X_CONFB, confb); | 770 | STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK, |
771 | confa); | ||
772 | if (ret < 0) | ||
773 | return ret; | ||
774 | |||
775 | ret = regmap_update_bits(sta32x->regmap, STA32X_CONFB, | ||
776 | STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB, | ||
777 | confb); | ||
778 | if (ret < 0) | ||
779 | return ret; | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | static int sta32x_startup_sequence(struct sta32x_priv *sta32x) | ||
785 | { | ||
786 | if (sta32x->gpiod_nreset) { | ||
787 | gpiod_set_value(sta32x->gpiod_nreset, 0); | ||
788 | mdelay(1); | ||
789 | gpiod_set_value(sta32x->gpiod_nreset, 1); | ||
790 | mdelay(1); | ||
791 | } | ||
792 | |||
751 | return 0; | 793 | return 0; |
752 | } | 794 | } |
753 | 795 | ||
@@ -766,14 +808,14 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec, | |||
766 | int ret; | 808 | int ret; |
767 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | 809 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); |
768 | 810 | ||
769 | pr_debug("level = %d\n", level); | 811 | dev_dbg(codec->dev, "level = %d\n", level); |
770 | switch (level) { | 812 | switch (level) { |
771 | case SND_SOC_BIAS_ON: | 813 | case SND_SOC_BIAS_ON: |
772 | break; | 814 | break; |
773 | 815 | ||
774 | case SND_SOC_BIAS_PREPARE: | 816 | case SND_SOC_BIAS_PREPARE: |
775 | /* Full power on */ | 817 | /* Full power on */ |
776 | snd_soc_update_bits(codec, STA32X_CONFF, | 818 | regmap_update_bits(sta32x->regmap, STA32X_CONFF, |
777 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, | 819 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, |
778 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD); | 820 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD); |
779 | break; | 821 | break; |
@@ -788,25 +830,28 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec, | |||
788 | return ret; | 830 | return ret; |
789 | } | 831 | } |
790 | 832 | ||
833 | sta32x_startup_sequence(sta32x); | ||
791 | sta32x_cache_sync(codec); | 834 | sta32x_cache_sync(codec); |
792 | sta32x_watchdog_start(sta32x); | 835 | sta32x_watchdog_start(sta32x); |
793 | } | 836 | } |
794 | 837 | ||
795 | /* Power up to mute */ | 838 | /* Power down */ |
796 | /* FIXME */ | 839 | regmap_update_bits(sta32x->regmap, STA32X_CONFF, |
797 | snd_soc_update_bits(codec, STA32X_CONFF, | 840 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, |
798 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, | 841 | 0); |
799 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD); | ||
800 | 842 | ||
801 | break; | 843 | break; |
802 | 844 | ||
803 | case SND_SOC_BIAS_OFF: | 845 | case SND_SOC_BIAS_OFF: |
804 | /* The chip runs through the power down sequence for us. */ | 846 | /* The chip runs through the power down sequence for us. */ |
805 | snd_soc_update_bits(codec, STA32X_CONFF, | 847 | regmap_update_bits(sta32x->regmap, STA32X_CONFF, |
806 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, | 848 | STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, 0); |
807 | STA32X_CONFF_PWDN); | ||
808 | msleep(300); | 849 | msleep(300); |
809 | sta32x_watchdog_stop(sta32x); | 850 | sta32x_watchdog_stop(sta32x); |
851 | |||
852 | if (sta32x->gpiod_nreset) | ||
853 | gpiod_set_value(sta32x->gpiod_nreset, 0); | ||
854 | |||
810 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), | 855 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), |
811 | sta32x->supplies); | 856 | sta32x->supplies); |
812 | break; | 857 | break; |
@@ -822,7 +867,7 @@ static const struct snd_soc_dai_ops sta32x_dai_ops = { | |||
822 | }; | 867 | }; |
823 | 868 | ||
824 | static struct snd_soc_dai_driver sta32x_dai = { | 869 | static struct snd_soc_dai_driver sta32x_dai = { |
825 | .name = "STA32X", | 870 | .name = "sta32x-hifi", |
826 | .playback = { | 871 | .playback = { |
827 | .stream_name = "Playback", | 872 | .stream_name = "Playback", |
828 | .channels_min = 2, | 873 | .channels_min = 2, |
@@ -836,11 +881,8 @@ static struct snd_soc_dai_driver sta32x_dai = { | |||
836 | static int sta32x_probe(struct snd_soc_codec *codec) | 881 | static int sta32x_probe(struct snd_soc_codec *codec) |
837 | { | 882 | { |
838 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | 883 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); |
884 | struct sta32x_platform_data *pdata = sta32x->pdata; | ||
839 | int i, ret = 0, thermal = 0; | 885 | int i, ret = 0, thermal = 0; |
840 | |||
841 | sta32x->codec = codec; | ||
842 | sta32x->pdata = dev_get_platdata(codec->dev); | ||
843 | |||
844 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), | 886 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), |
845 | sta32x->supplies); | 887 | sta32x->supplies); |
846 | if (ret != 0) { | 888 | if (ret != 0) { |
@@ -848,50 +890,73 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
848 | return ret; | 890 | return ret; |
849 | } | 891 | } |
850 | 892 | ||
851 | /* Chip documentation explicitly requires that the reset values | 893 | ret = sta32x_startup_sequence(sta32x); |
852 | * of reserved register bits are left untouched. | 894 | if (ret < 0) { |
853 | * Write the register default value to cache for reserved registers, | 895 | dev_err(codec->dev, "Failed to startup device\n"); |
854 | * so the write to the these registers are suppressed by the cache | 896 | return ret; |
855 | * restore code when it skips writes of default registers. | 897 | } |
856 | */ | 898 | |
857 | regcache_cache_only(sta32x->regmap, true); | 899 | /* CONFA */ |
858 | snd_soc_write(codec, STA32X_CONFC, 0xc2); | 900 | if (!pdata->thermal_warning_recovery) |
859 | snd_soc_write(codec, STA32X_CONFE, 0xc2); | ||
860 | snd_soc_write(codec, STA32X_CONFF, 0x5c); | ||
861 | snd_soc_write(codec, STA32X_MMUTE, 0x10); | ||
862 | snd_soc_write(codec, STA32X_AUTO1, 0x60); | ||
863 | snd_soc_write(codec, STA32X_AUTO3, 0x00); | ||
864 | snd_soc_write(codec, STA32X_C3CFG, 0x40); | ||
865 | regcache_cache_only(sta32x->regmap, false); | ||
866 | |||
867 | /* set thermal warning adjustment and recovery */ | ||
868 | if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE)) | ||
869 | thermal |= STA32X_CONFA_TWAB; | 901 | thermal |= STA32X_CONFA_TWAB; |
870 | if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_RECOVERY_ENABLE)) | 902 | if (!pdata->thermal_warning_adjustment) |
871 | thermal |= STA32X_CONFA_TWRB; | 903 | thermal |= STA32X_CONFA_TWRB; |
872 | snd_soc_update_bits(codec, STA32X_CONFA, | 904 | if (!pdata->fault_detect_recovery) |
873 | STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, | 905 | thermal |= STA32X_CONFA_FDRB; |
874 | thermal); | 906 | regmap_update_bits(sta32x->regmap, STA32X_CONFA, |
907 | STA32X_CONFA_TWAB | STA32X_CONFA_TWRB | | ||
908 | STA32X_CONFA_FDRB, | ||
909 | thermal); | ||
910 | |||
911 | /* CONFC */ | ||
912 | regmap_update_bits(sta32x->regmap, STA32X_CONFC, | ||
913 | STA32X_CONFC_CSZ_MASK, | ||
914 | pdata->drop_compensation_ns | ||
915 | << STA32X_CONFC_CSZ_SHIFT); | ||
916 | |||
917 | /* CONFE */ | ||
918 | regmap_update_bits(sta32x->regmap, STA32X_CONFE, | ||
919 | STA32X_CONFE_MPCV, | ||
920 | pdata->max_power_use_mpcc ? | ||
921 | STA32X_CONFE_MPCV : 0); | ||
922 | regmap_update_bits(sta32x->regmap, STA32X_CONFE, | ||
923 | STA32X_CONFE_MPC, | ||
924 | pdata->max_power_correction ? | ||
925 | STA32X_CONFE_MPC : 0); | ||
926 | regmap_update_bits(sta32x->regmap, STA32X_CONFE, | ||
927 | STA32X_CONFE_AME, | ||
928 | pdata->am_reduction_mode ? | ||
929 | STA32X_CONFE_AME : 0); | ||
930 | regmap_update_bits(sta32x->regmap, STA32X_CONFE, | ||
931 | STA32X_CONFE_PWMS, | ||
932 | pdata->odd_pwm_speed_mode ? | ||
933 | STA32X_CONFE_PWMS : 0); | ||
934 | |||
935 | /* CONFF */ | ||
936 | regmap_update_bits(sta32x->regmap, STA32X_CONFF, | ||
937 | STA32X_CONFF_IDE, | ||
938 | pdata->invalid_input_detect_mute ? | ||
939 | STA32X_CONFF_IDE : 0); | ||
875 | 940 | ||
876 | /* select output configuration */ | 941 | /* select output configuration */ |
877 | snd_soc_update_bits(codec, STA32X_CONFF, | 942 | regmap_update_bits(sta32x->regmap, STA32X_CONFF, |
878 | STA32X_CONFF_OCFG_MASK, | 943 | STA32X_CONFF_OCFG_MASK, |
879 | sta32x->pdata->output_conf | 944 | pdata->output_conf |
880 | << STA32X_CONFF_OCFG_SHIFT); | 945 | << STA32X_CONFF_OCFG_SHIFT); |
881 | 946 | ||
882 | /* channel to output mapping */ | 947 | /* channel to output mapping */ |
883 | snd_soc_update_bits(codec, STA32X_C1CFG, | 948 | regmap_update_bits(sta32x->regmap, STA32X_C1CFG, |
884 | STA32X_CxCFG_OM_MASK, | 949 | STA32X_CxCFG_OM_MASK, |
885 | sta32x->pdata->ch1_output_mapping | 950 | pdata->ch1_output_mapping |
886 | << STA32X_CxCFG_OM_SHIFT); | 951 | << STA32X_CxCFG_OM_SHIFT); |
887 | snd_soc_update_bits(codec, STA32X_C2CFG, | 952 | regmap_update_bits(sta32x->regmap, STA32X_C2CFG, |
888 | STA32X_CxCFG_OM_MASK, | 953 | STA32X_CxCFG_OM_MASK, |
889 | sta32x->pdata->ch2_output_mapping | 954 | pdata->ch2_output_mapping |
890 | << STA32X_CxCFG_OM_SHIFT); | 955 | << STA32X_CxCFG_OM_SHIFT); |
891 | snd_soc_update_bits(codec, STA32X_C3CFG, | 956 | regmap_update_bits(sta32x->regmap, STA32X_C3CFG, |
892 | STA32X_CxCFG_OM_MASK, | 957 | STA32X_CxCFG_OM_MASK, |
893 | sta32x->pdata->ch3_output_mapping | 958 | pdata->ch3_output_mapping |
894 | << STA32X_CxCFG_OM_SHIFT); | 959 | << STA32X_CxCFG_OM_SHIFT); |
895 | 960 | ||
896 | /* initialize coefficient shadow RAM with reset values */ | 961 | /* initialize coefficient shadow RAM with reset values */ |
897 | for (i = 4; i <= 49; i += 5) | 962 | for (i = 4; i <= 49; i += 5) |
@@ -924,16 +989,6 @@ static int sta32x_remove(struct snd_soc_codec *codec) | |||
924 | return 0; | 989 | return 0; |
925 | } | 990 | } |
926 | 991 | ||
927 | static bool sta32x_reg_is_volatile(struct device *dev, unsigned int reg) | ||
928 | { | ||
929 | switch (reg) { | ||
930 | case STA32X_CONFA ... STA32X_L2ATRT: | ||
931 | case STA32X_MPCC1 ... STA32X_FDRC2: | ||
932 | return 0; | ||
933 | } | ||
934 | return 1; | ||
935 | } | ||
936 | |||
937 | static const struct snd_soc_codec_driver sta32x_codec = { | 992 | static const struct snd_soc_codec_driver sta32x_codec = { |
938 | .probe = sta32x_probe, | 993 | .probe = sta32x_probe, |
939 | .remove = sta32x_remove, | 994 | .remove = sta32x_remove, |
@@ -954,12 +1009,75 @@ static const struct regmap_config sta32x_regmap = { | |||
954 | .reg_defaults = sta32x_regs, | 1009 | .reg_defaults = sta32x_regs, |
955 | .num_reg_defaults = ARRAY_SIZE(sta32x_regs), | 1010 | .num_reg_defaults = ARRAY_SIZE(sta32x_regs), |
956 | .cache_type = REGCACHE_RBTREE, | 1011 | .cache_type = REGCACHE_RBTREE, |
957 | .volatile_reg = sta32x_reg_is_volatile, | 1012 | .wr_table = &sta32x_write_regs, |
1013 | .rd_table = &sta32x_read_regs, | ||
1014 | .volatile_table = &sta32x_volatile_regs, | ||
958 | }; | 1015 | }; |
959 | 1016 | ||
1017 | #ifdef CONFIG_OF | ||
1018 | static const struct of_device_id st32x_dt_ids[] = { | ||
1019 | { .compatible = "st,sta32x", }, | ||
1020 | { } | ||
1021 | }; | ||
1022 | MODULE_DEVICE_TABLE(of, st32x_dt_ids); | ||
1023 | |||
1024 | static int sta32x_probe_dt(struct device *dev, struct sta32x_priv *sta32x) | ||
1025 | { | ||
1026 | struct device_node *np = dev->of_node; | ||
1027 | struct sta32x_platform_data *pdata; | ||
1028 | u16 tmp; | ||
1029 | |||
1030 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
1031 | if (!pdata) | ||
1032 | return -ENOMEM; | ||
1033 | |||
1034 | of_property_read_u8(np, "st,output-conf", | ||
1035 | &pdata->output_conf); | ||
1036 | of_property_read_u8(np, "st,ch1-output-mapping", | ||
1037 | &pdata->ch1_output_mapping); | ||
1038 | of_property_read_u8(np, "st,ch2-output-mapping", | ||
1039 | &pdata->ch2_output_mapping); | ||
1040 | of_property_read_u8(np, "st,ch3-output-mapping", | ||
1041 | &pdata->ch3_output_mapping); | ||
1042 | |||
1043 | if (of_get_property(np, "st,thermal-warning-recovery", NULL)) | ||
1044 | pdata->thermal_warning_recovery = 1; | ||
1045 | if (of_get_property(np, "st,thermal-warning-adjustment", NULL)) | ||
1046 | pdata->thermal_warning_adjustment = 1; | ||
1047 | if (of_get_property(np, "st,needs_esd_watchdog", NULL)) | ||
1048 | pdata->needs_esd_watchdog = 1; | ||
1049 | |||
1050 | tmp = 140; | ||
1051 | of_property_read_u16(np, "st,drop-compensation-ns", &tmp); | ||
1052 | pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20; | ||
1053 | |||
1054 | /* CONFE */ | ||
1055 | if (of_get_property(np, "st,max-power-use-mpcc", NULL)) | ||
1056 | pdata->max_power_use_mpcc = 1; | ||
1057 | |||
1058 | if (of_get_property(np, "st,max-power-correction", NULL)) | ||
1059 | pdata->max_power_correction = 1; | ||
1060 | |||
1061 | if (of_get_property(np, "st,am-reduction-mode", NULL)) | ||
1062 | pdata->am_reduction_mode = 1; | ||
1063 | |||
1064 | if (of_get_property(np, "st,odd-pwm-speed-mode", NULL)) | ||
1065 | pdata->odd_pwm_speed_mode = 1; | ||
1066 | |||
1067 | /* CONFF */ | ||
1068 | if (of_get_property(np, "st,invalid-input-detect-mute", NULL)) | ||
1069 | pdata->invalid_input_detect_mute = 1; | ||
1070 | |||
1071 | sta32x->pdata = pdata; | ||
1072 | |||
1073 | return 0; | ||
1074 | } | ||
1075 | #endif | ||
1076 | |||
960 | static int sta32x_i2c_probe(struct i2c_client *i2c, | 1077 | static int sta32x_i2c_probe(struct i2c_client *i2c, |
961 | const struct i2c_device_id *id) | 1078 | const struct i2c_device_id *id) |
962 | { | 1079 | { |
1080 | struct device *dev = &i2c->dev; | ||
963 | struct sta32x_priv *sta32x; | 1081 | struct sta32x_priv *sta32x; |
964 | int ret, i; | 1082 | int ret, i; |
965 | 1083 | ||
@@ -968,6 +1086,29 @@ static int sta32x_i2c_probe(struct i2c_client *i2c, | |||
968 | if (!sta32x) | 1086 | if (!sta32x) |
969 | return -ENOMEM; | 1087 | return -ENOMEM; |
970 | 1088 | ||
1089 | mutex_init(&sta32x->coeff_lock); | ||
1090 | sta32x->pdata = dev_get_platdata(dev); | ||
1091 | |||
1092 | #ifdef CONFIG_OF | ||
1093 | if (dev->of_node) { | ||
1094 | ret = sta32x_probe_dt(dev, sta32x); | ||
1095 | if (ret < 0) | ||
1096 | return ret; | ||
1097 | } | ||
1098 | #endif | ||
1099 | |||
1100 | /* GPIOs */ | ||
1101 | sta32x->gpiod_nreset = devm_gpiod_get(dev, "reset"); | ||
1102 | if (IS_ERR(sta32x->gpiod_nreset)) { | ||
1103 | ret = PTR_ERR(sta32x->gpiod_nreset); | ||
1104 | if (ret != -ENOENT && ret != -ENOSYS) | ||
1105 | return ret; | ||
1106 | |||
1107 | sta32x->gpiod_nreset = NULL; | ||
1108 | } else { | ||
1109 | gpiod_direction_output(sta32x->gpiod_nreset, 0); | ||
1110 | } | ||
1111 | |||
971 | /* regulators */ | 1112 | /* regulators */ |
972 | for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) | 1113 | for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) |
973 | sta32x->supplies[i].supply = sta32x_supply_names[i]; | 1114 | sta32x->supplies[i].supply = sta32x_supply_names[i]; |
@@ -982,15 +1123,15 @@ static int sta32x_i2c_probe(struct i2c_client *i2c, | |||
982 | sta32x->regmap = devm_regmap_init_i2c(i2c, &sta32x_regmap); | 1123 | sta32x->regmap = devm_regmap_init_i2c(i2c, &sta32x_regmap); |
983 | if (IS_ERR(sta32x->regmap)) { | 1124 | if (IS_ERR(sta32x->regmap)) { |
984 | ret = PTR_ERR(sta32x->regmap); | 1125 | ret = PTR_ERR(sta32x->regmap); |
985 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); | 1126 | dev_err(dev, "Failed to init regmap: %d\n", ret); |
986 | return ret; | 1127 | return ret; |
987 | } | 1128 | } |
988 | 1129 | ||
989 | i2c_set_clientdata(i2c, sta32x); | 1130 | i2c_set_clientdata(i2c, sta32x); |
990 | 1131 | ||
991 | ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); | 1132 | ret = snd_soc_register_codec(dev, &sta32x_codec, &sta32x_dai, 1); |
992 | if (ret != 0) | 1133 | if (ret < 0) |
993 | dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret); | 1134 | dev_err(dev, "Failed to register codec (%d)\n", ret); |
994 | 1135 | ||
995 | return ret; | 1136 | return ret; |
996 | } | 1137 | } |
@@ -1013,6 +1154,7 @@ static struct i2c_driver sta32x_i2c_driver = { | |||
1013 | .driver = { | 1154 | .driver = { |
1014 | .name = "sta32x", | 1155 | .name = "sta32x", |
1015 | .owner = THIS_MODULE, | 1156 | .owner = THIS_MODULE, |
1157 | .of_match_table = of_match_ptr(st32x_dt_ids), | ||
1016 | }, | 1158 | }, |
1017 | .probe = sta32x_i2c_probe, | 1159 | .probe = sta32x_i2c_probe, |
1018 | .remove = sta32x_i2c_remove, | 1160 | .remove = sta32x_i2c_remove, |
diff --git a/sound/soc/codecs/sta32x.h b/sound/soc/codecs/sta32x.h index d8e32a6262ee..d3191c983d71 100644 --- a/sound/soc/codecs/sta32x.h +++ b/sound/soc/codecs/sta32x.h | |||
@@ -131,7 +131,7 @@ | |||
131 | #define STA32X_CONFF_OCFG_MASK 0x03 | 131 | #define STA32X_CONFF_OCFG_MASK 0x03 |
132 | #define STA32X_CONFF_OCFG_SHIFT 0 | 132 | #define STA32X_CONFF_OCFG_SHIFT 0 |
133 | #define STA32X_CONFF_IDE 0x04 | 133 | #define STA32X_CONFF_IDE 0x04 |
134 | #define STA32X_CONFF_IDE_SHIFT 3 | 134 | #define STA32X_CONFF_IDE_SHIFT 2 |
135 | #define STA32X_CONFF_BCLE 0x08 | 135 | #define STA32X_CONFF_BCLE 0x08 |
136 | #define STA32X_CONFF_ECLE 0x20 | 136 | #define STA32X_CONFF_ECLE 0x20 |
137 | #define STA32X_CONFF_PWDN 0x40 | 137 | #define STA32X_CONFF_PWDN 0x40 |
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index dc3223d6eca1..c86dd9aae157 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -349,7 +349,8 @@ static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg, | |||
349 | static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w, | 349 | static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w, |
350 | struct snd_kcontrol *kcontrol, int event) | 350 | struct snd_kcontrol *kcontrol, int event) |
351 | { | 351 | { |
352 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(w->codec); | 352 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
353 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | ||
353 | unsigned int reg = AIC31XX_DACFLAG1; | 354 | unsigned int reg = AIC31XX_DACFLAG1; |
354 | unsigned int mask; | 355 | unsigned int mask; |
355 | 356 | ||
@@ -377,7 +378,7 @@ static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w, | |||
377 | reg = AIC31XX_ADCFLAG; | 378 | reg = AIC31XX_ADCFLAG; |
378 | break; | 379 | break; |
379 | default: | 380 | default: |
380 | dev_err(w->codec->dev, "Unknown widget '%s' calling %s\n", | 381 | dev_err(codec->dev, "Unknown widget '%s' calling %s\n", |
381 | w->name, __func__); | 382 | w->name, __func__); |
382 | return -EINVAL; | 383 | return -EINVAL; |
383 | } | 384 | } |
@@ -388,7 +389,7 @@ static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w, | |||
388 | case SND_SOC_DAPM_POST_PMD: | 389 | case SND_SOC_DAPM_POST_PMD: |
389 | return aic31xx_wait_bits(aic31xx, reg, mask, 0, 5000, 100); | 390 | return aic31xx_wait_bits(aic31xx, reg, mask, 0, 5000, 100); |
390 | default: | 391 | default: |
391 | dev_dbg(w->codec->dev, | 392 | dev_dbg(codec->dev, |
392 | "Unhandled dapm widget event %d from %s\n", | 393 | "Unhandled dapm widget event %d from %s\n", |
393 | event, w->name); | 394 | event, w->name); |
394 | } | 395 | } |
@@ -433,7 +434,7 @@ static const struct snd_kcontrol_new aic31xx_dapm_spr_switch = | |||
433 | static int mic_bias_event(struct snd_soc_dapm_widget *w, | 434 | static int mic_bias_event(struct snd_soc_dapm_widget *w, |
434 | struct snd_kcontrol *kcontrol, int event) | 435 | struct snd_kcontrol *kcontrol, int event) |
435 | { | 436 | { |
436 | struct snd_soc_codec *codec = w->codec; | 437 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
437 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); | 438 | struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); |
438 | 439 | ||
439 | switch (event) { | 440 | switch (event) { |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index dd222b10ce13..51c4713ac6e3 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -87,6 +87,7 @@ struct aic3x_priv { | |||
87 | #define AIC3X_MODEL_3X 0 | 87 | #define AIC3X_MODEL_3X 0 |
88 | #define AIC3X_MODEL_33 1 | 88 | #define AIC3X_MODEL_33 1 |
89 | #define AIC3X_MODEL_3007 2 | 89 | #define AIC3X_MODEL_3007 2 |
90 | #define AIC3X_MODEL_3104 3 | ||
90 | u16 model; | 91 | u16 model; |
91 | 92 | ||
92 | /* Selects the micbias voltage */ | 93 | /* Selects the micbias voltage */ |
@@ -197,7 +198,7 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, | |||
197 | static int mic_bias_event(struct snd_soc_dapm_widget *w, | 198 | static int mic_bias_event(struct snd_soc_dapm_widget *w, |
198 | struct snd_kcontrol *kcontrol, int event) | 199 | struct snd_kcontrol *kcontrol, int event) |
199 | { | 200 | { |
200 | struct snd_soc_codec *codec = w->codec; | 201 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
201 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | 202 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
202 | 203 | ||
203 | switch (event) { | 204 | switch (event) { |
@@ -316,52 +317,37 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
316 | * only for swapped L-to-R and R-to-L routes. See below stereo controls | 317 | * only for swapped L-to-R and R-to-L routes. See below stereo controls |
317 | * for direct L-to-L and R-to-R routes. | 318 | * for direct L-to-L and R-to-R routes. |
318 | */ | 319 | */ |
319 | SOC_SINGLE_TLV("Left Line Mixer Line2R Bypass Volume", | ||
320 | LINE2R_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), | ||
321 | SOC_SINGLE_TLV("Left Line Mixer PGAR Bypass Volume", | 320 | SOC_SINGLE_TLV("Left Line Mixer PGAR Bypass Volume", |
322 | PGAR_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), | 321 | PGAR_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), |
323 | SOC_SINGLE_TLV("Left Line Mixer DACR1 Playback Volume", | 322 | SOC_SINGLE_TLV("Left Line Mixer DACR1 Playback Volume", |
324 | DACR1_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), | 323 | DACR1_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), |
325 | 324 | ||
326 | SOC_SINGLE_TLV("Right Line Mixer Line2L Bypass Volume", | ||
327 | LINE2L_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), | ||
328 | SOC_SINGLE_TLV("Right Line Mixer PGAL Bypass Volume", | 325 | SOC_SINGLE_TLV("Right Line Mixer PGAL Bypass Volume", |
329 | PGAL_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), | 326 | PGAL_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), |
330 | SOC_SINGLE_TLV("Right Line Mixer DACL1 Playback Volume", | 327 | SOC_SINGLE_TLV("Right Line Mixer DACL1 Playback Volume", |
331 | DACL1_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), | 328 | DACL1_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), |
332 | 329 | ||
333 | SOC_SINGLE_TLV("Left HP Mixer Line2R Bypass Volume", | ||
334 | LINE2R_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), | ||
335 | SOC_SINGLE_TLV("Left HP Mixer PGAR Bypass Volume", | 330 | SOC_SINGLE_TLV("Left HP Mixer PGAR Bypass Volume", |
336 | PGAR_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), | 331 | PGAR_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), |
337 | SOC_SINGLE_TLV("Left HP Mixer DACR1 Playback Volume", | 332 | SOC_SINGLE_TLV("Left HP Mixer DACR1 Playback Volume", |
338 | DACR1_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), | 333 | DACR1_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), |
339 | 334 | ||
340 | SOC_SINGLE_TLV("Right HP Mixer Line2L Bypass Volume", | ||
341 | LINE2L_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), | ||
342 | SOC_SINGLE_TLV("Right HP Mixer PGAL Bypass Volume", | 335 | SOC_SINGLE_TLV("Right HP Mixer PGAL Bypass Volume", |
343 | PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), | 336 | PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), |
344 | SOC_SINGLE_TLV("Right HP Mixer DACL1 Playback Volume", | 337 | SOC_SINGLE_TLV("Right HP Mixer DACL1 Playback Volume", |
345 | DACL1_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), | 338 | DACL1_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), |
346 | 339 | ||
347 | SOC_SINGLE_TLV("Left HPCOM Mixer Line2R Bypass Volume", | ||
348 | LINE2R_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), | ||
349 | SOC_SINGLE_TLV("Left HPCOM Mixer PGAR Bypass Volume", | 340 | SOC_SINGLE_TLV("Left HPCOM Mixer PGAR Bypass Volume", |
350 | PGAR_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), | 341 | PGAR_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), |
351 | SOC_SINGLE_TLV("Left HPCOM Mixer DACR1 Playback Volume", | 342 | SOC_SINGLE_TLV("Left HPCOM Mixer DACR1 Playback Volume", |
352 | DACR1_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), | 343 | DACR1_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), |
353 | 344 | ||
354 | SOC_SINGLE_TLV("Right HPCOM Mixer Line2L Bypass Volume", | ||
355 | LINE2L_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), | ||
356 | SOC_SINGLE_TLV("Right HPCOM Mixer PGAL Bypass Volume", | 345 | SOC_SINGLE_TLV("Right HPCOM Mixer PGAL Bypass Volume", |
357 | PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), | 346 | PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), |
358 | SOC_SINGLE_TLV("Right HPCOM Mixer DACL1 Playback Volume", | 347 | SOC_SINGLE_TLV("Right HPCOM Mixer DACL1 Playback Volume", |
359 | DACL1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), | 348 | DACL1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), |
360 | 349 | ||
361 | /* Stereo output controls for direct L-to-L and R-to-R routes */ | 350 | /* Stereo output controls for direct L-to-L and R-to-R routes */ |
362 | SOC_DOUBLE_R_TLV("Line Line2 Bypass Volume", | ||
363 | LINE2L_2_LLOPM_VOL, LINE2R_2_RLOPM_VOL, | ||
364 | 0, 118, 1, output_stage_tlv), | ||
365 | SOC_DOUBLE_R_TLV("Line PGA Bypass Volume", | 351 | SOC_DOUBLE_R_TLV("Line PGA Bypass Volume", |
366 | PGAL_2_LLOPM_VOL, PGAR_2_RLOPM_VOL, | 352 | PGAL_2_LLOPM_VOL, PGAR_2_RLOPM_VOL, |
367 | 0, 118, 1, output_stage_tlv), | 353 | 0, 118, 1, output_stage_tlv), |
@@ -369,9 +355,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
369 | DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL, | 355 | DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL, |
370 | 0, 118, 1, output_stage_tlv), | 356 | 0, 118, 1, output_stage_tlv), |
371 | 357 | ||
372 | SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume", | ||
373 | LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL, | ||
374 | 0, 118, 1, output_stage_tlv), | ||
375 | SOC_DOUBLE_R_TLV("HP PGA Bypass Volume", | 358 | SOC_DOUBLE_R_TLV("HP PGA Bypass Volume", |
376 | PGAL_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL, | 359 | PGAL_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL, |
377 | 0, 118, 1, output_stage_tlv), | 360 | 0, 118, 1, output_stage_tlv), |
@@ -379,9 +362,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
379 | DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL, | 362 | DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL, |
380 | 0, 118, 1, output_stage_tlv), | 363 | 0, 118, 1, output_stage_tlv), |
381 | 364 | ||
382 | SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Volume", | ||
383 | LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL, | ||
384 | 0, 118, 1, output_stage_tlv), | ||
385 | SOC_DOUBLE_R_TLV("HPCOM PGA Bypass Volume", | 365 | SOC_DOUBLE_R_TLV("HPCOM PGA Bypass Volume", |
386 | PGAL_2_HPLCOM_VOL, PGAR_2_HPRCOM_VOL, | 366 | PGAL_2_HPLCOM_VOL, PGAR_2_HPRCOM_VOL, |
387 | 0, 118, 1, output_stage_tlv), | 367 | 0, 118, 1, output_stage_tlv), |
@@ -424,6 +404,45 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
424 | SOC_ENUM("Output Driver Ramp-up step", aic3x_rampup_step_enum), | 404 | SOC_ENUM("Output Driver Ramp-up step", aic3x_rampup_step_enum), |
425 | }; | 405 | }; |
426 | 406 | ||
407 | /* For other than tlv320aic3104 */ | ||
408 | static const struct snd_kcontrol_new aic3x_extra_snd_controls[] = { | ||
409 | /* | ||
410 | * Output controls that map to output mixer switches. Note these are | ||
411 | * only for swapped L-to-R and R-to-L routes. See below stereo controls | ||
412 | * for direct L-to-L and R-to-R routes. | ||
413 | */ | ||
414 | SOC_SINGLE_TLV("Left Line Mixer Line2R Bypass Volume", | ||
415 | LINE2R_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), | ||
416 | |||
417 | SOC_SINGLE_TLV("Right Line Mixer Line2L Bypass Volume", | ||
418 | LINE2L_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), | ||
419 | |||
420 | SOC_SINGLE_TLV("Left HP Mixer Line2R Bypass Volume", | ||
421 | LINE2R_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), | ||
422 | |||
423 | SOC_SINGLE_TLV("Right HP Mixer Line2L Bypass Volume", | ||
424 | LINE2L_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), | ||
425 | |||
426 | SOC_SINGLE_TLV("Left HPCOM Mixer Line2R Bypass Volume", | ||
427 | LINE2R_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), | ||
428 | |||
429 | SOC_SINGLE_TLV("Right HPCOM Mixer Line2L Bypass Volume", | ||
430 | LINE2L_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), | ||
431 | |||
432 | /* Stereo output controls for direct L-to-L and R-to-R routes */ | ||
433 | SOC_DOUBLE_R_TLV("Line Line2 Bypass Volume", | ||
434 | LINE2L_2_LLOPM_VOL, LINE2R_2_RLOPM_VOL, | ||
435 | 0, 118, 1, output_stage_tlv), | ||
436 | |||
437 | SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume", | ||
438 | LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL, | ||
439 | 0, 118, 1, output_stage_tlv), | ||
440 | |||
441 | SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Volume", | ||
442 | LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL, | ||
443 | 0, 118, 1, output_stage_tlv), | ||
444 | }; | ||
445 | |||
427 | static const struct snd_kcontrol_new aic3x_mono_controls[] = { | 446 | static const struct snd_kcontrol_new aic3x_mono_controls[] = { |
428 | SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume", | 447 | SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume", |
429 | LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL, | 448 | LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL, |
@@ -464,22 +483,24 @@ SOC_DAPM_ENUM("Route", aic3x_right_hpcom_enum); | |||
464 | 483 | ||
465 | /* Left Line Mixer */ | 484 | /* Left Line Mixer */ |
466 | static const struct snd_kcontrol_new aic3x_left_line_mixer_controls[] = { | 485 | static const struct snd_kcontrol_new aic3x_left_line_mixer_controls[] = { |
467 | SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0), | ||
468 | SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_LLOPM_VOL, 7, 1, 0), | 486 | SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_LLOPM_VOL, 7, 1, 0), |
469 | SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_LLOPM_VOL, 7, 1, 0), | 487 | SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_LLOPM_VOL, 7, 1, 0), |
470 | SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0), | ||
471 | SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_LLOPM_VOL, 7, 1, 0), | 488 | SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_LLOPM_VOL, 7, 1, 0), |
472 | SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_LLOPM_VOL, 7, 1, 0), | 489 | SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_LLOPM_VOL, 7, 1, 0), |
490 | /* Not on tlv320aic3104 */ | ||
491 | SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0), | ||
492 | SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0), | ||
473 | }; | 493 | }; |
474 | 494 | ||
475 | /* Right Line Mixer */ | 495 | /* Right Line Mixer */ |
476 | static const struct snd_kcontrol_new aic3x_right_line_mixer_controls[] = { | 496 | static const struct snd_kcontrol_new aic3x_right_line_mixer_controls[] = { |
477 | SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0), | ||
478 | SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_RLOPM_VOL, 7, 1, 0), | 497 | SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_RLOPM_VOL, 7, 1, 0), |
479 | SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_RLOPM_VOL, 7, 1, 0), | 498 | SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_RLOPM_VOL, 7, 1, 0), |
480 | SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0), | ||
481 | SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_RLOPM_VOL, 7, 1, 0), | 499 | SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_RLOPM_VOL, 7, 1, 0), |
482 | SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_RLOPM_VOL, 7, 1, 0), | 500 | SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_RLOPM_VOL, 7, 1, 0), |
501 | /* Not on tlv320aic3104 */ | ||
502 | SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0), | ||
503 | SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0), | ||
483 | }; | 504 | }; |
484 | 505 | ||
485 | /* Mono Mixer */ | 506 | /* Mono Mixer */ |
@@ -494,42 +515,46 @@ static const struct snd_kcontrol_new aic3x_mono_mixer_controls[] = { | |||
494 | 515 | ||
495 | /* Left HP Mixer */ | 516 | /* Left HP Mixer */ |
496 | static const struct snd_kcontrol_new aic3x_left_hp_mixer_controls[] = { | 517 | static const struct snd_kcontrol_new aic3x_left_hp_mixer_controls[] = { |
497 | SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0), | ||
498 | SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0), | 518 | SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0), |
499 | SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0), | 519 | SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0), |
500 | SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLOUT_VOL, 7, 1, 0), | ||
501 | SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0), | 520 | SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0), |
502 | SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLOUT_VOL, 7, 1, 0), | 521 | SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLOUT_VOL, 7, 1, 0), |
522 | /* Not on tlv320aic3104 */ | ||
523 | SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0), | ||
524 | SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLOUT_VOL, 7, 1, 0), | ||
503 | }; | 525 | }; |
504 | 526 | ||
505 | /* Right HP Mixer */ | 527 | /* Right HP Mixer */ |
506 | static const struct snd_kcontrol_new aic3x_right_hp_mixer_controls[] = { | 528 | static const struct snd_kcontrol_new aic3x_right_hp_mixer_controls[] = { |
507 | SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPROUT_VOL, 7, 1, 0), | ||
508 | SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPROUT_VOL, 7, 1, 0), | 529 | SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPROUT_VOL, 7, 1, 0), |
509 | SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPROUT_VOL, 7, 1, 0), | 530 | SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPROUT_VOL, 7, 1, 0), |
510 | SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0), | ||
511 | SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPROUT_VOL, 7, 1, 0), | 531 | SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPROUT_VOL, 7, 1, 0), |
512 | SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPROUT_VOL, 7, 1, 0), | 532 | SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPROUT_VOL, 7, 1, 0), |
533 | /* Not on tlv320aic3104 */ | ||
534 | SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPROUT_VOL, 7, 1, 0), | ||
535 | SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0), | ||
513 | }; | 536 | }; |
514 | 537 | ||
515 | /* Left HPCOM Mixer */ | 538 | /* Left HPCOM Mixer */ |
516 | static const struct snd_kcontrol_new aic3x_left_hpcom_mixer_controls[] = { | 539 | static const struct snd_kcontrol_new aic3x_left_hpcom_mixer_controls[] = { |
517 | SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0), | ||
518 | SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0), | 540 | SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0), |
519 | SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0), | 541 | SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0), |
520 | SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLCOM_VOL, 7, 1, 0), | ||
521 | SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0), | 542 | SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0), |
522 | SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLCOM_VOL, 7, 1, 0), | 543 | SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLCOM_VOL, 7, 1, 0), |
544 | /* Not on tlv320aic3104 */ | ||
545 | SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0), | ||
546 | SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLCOM_VOL, 7, 1, 0), | ||
523 | }; | 547 | }; |
524 | 548 | ||
525 | /* Right HPCOM Mixer */ | 549 | /* Right HPCOM Mixer */ |
526 | static const struct snd_kcontrol_new aic3x_right_hpcom_mixer_controls[] = { | 550 | static const struct snd_kcontrol_new aic3x_right_hpcom_mixer_controls[] = { |
527 | SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPRCOM_VOL, 7, 1, 0), | ||
528 | SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0), | 551 | SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0), |
529 | SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPRCOM_VOL, 7, 1, 0), | 552 | SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPRCOM_VOL, 7, 1, 0), |
530 | SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0), | ||
531 | SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0), | 553 | SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0), |
532 | SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0), | 554 | SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0), |
555 | /* Not on tlv320aic3104 */ | ||
556 | SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPRCOM_VOL, 7, 1, 0), | ||
557 | SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0), | ||
533 | }; | 558 | }; |
534 | 559 | ||
535 | /* Left PGA Mixer */ | 560 | /* Left PGA Mixer */ |
@@ -550,6 +575,22 @@ static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = { | |||
550 | SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1), | 575 | SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1), |
551 | }; | 576 | }; |
552 | 577 | ||
578 | /* Left PGA Mixer for tlv320aic3104 */ | ||
579 | static const struct snd_kcontrol_new aic3104_left_pga_mixer_controls[] = { | ||
580 | SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_LADC_CTRL, 3, 1, 1), | ||
581 | SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_LADC_CTRL, 3, 1, 1), | ||
582 | SOC_DAPM_SINGLE_AIC3X("Mic2L Switch", MIC3LR_2_LADC_CTRL, 4, 1, 1), | ||
583 | SOC_DAPM_SINGLE_AIC3X("Mic2R Switch", MIC3LR_2_LADC_CTRL, 0, 1, 1), | ||
584 | }; | ||
585 | |||
586 | /* Right PGA Mixer for tlv320aic3104 */ | ||
587 | static const struct snd_kcontrol_new aic3104_right_pga_mixer_controls[] = { | ||
588 | SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_RADC_CTRL, 3, 1, 1), | ||
589 | SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_RADC_CTRL, 3, 1, 1), | ||
590 | SOC_DAPM_SINGLE_AIC3X("Mic2L Switch", MIC3LR_2_RADC_CTRL, 4, 1, 1), | ||
591 | SOC_DAPM_SINGLE_AIC3X("Mic2R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1), | ||
592 | }; | ||
593 | |||
553 | /* Left Line1 Mux */ | 594 | /* Left Line1 Mux */ |
554 | static const struct snd_kcontrol_new aic3x_left_line1l_mux_controls = | 595 | static const struct snd_kcontrol_new aic3x_left_line1l_mux_controls = |
555 | SOC_DAPM_ENUM("Route", aic3x_line1l_2_l_enum); | 596 | SOC_DAPM_ENUM("Route", aic3x_line1l_2_l_enum); |
@@ -593,26 +634,56 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
593 | 634 | ||
594 | /* Inputs to Left ADC */ | 635 | /* Inputs to Left ADC */ |
595 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0), | 636 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0), |
596 | SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0, | ||
597 | &aic3x_left_pga_mixer_controls[0], | ||
598 | ARRAY_SIZE(aic3x_left_pga_mixer_controls)), | ||
599 | SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0, | 637 | SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0, |
600 | &aic3x_left_line1l_mux_controls), | 638 | &aic3x_left_line1l_mux_controls), |
601 | SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0, | 639 | SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0, |
602 | &aic3x_left_line1r_mux_controls), | 640 | &aic3x_left_line1r_mux_controls), |
603 | SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0, | ||
604 | &aic3x_left_line2_mux_controls), | ||
605 | 641 | ||
606 | /* Inputs to Right ADC */ | 642 | /* Inputs to Right ADC */ |
607 | SND_SOC_DAPM_ADC("Right ADC", "Right Capture", | 643 | SND_SOC_DAPM_ADC("Right ADC", "Right Capture", |
608 | LINE1R_2_RADC_CTRL, 2, 0), | 644 | LINE1R_2_RADC_CTRL, 2, 0), |
609 | SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0, | ||
610 | &aic3x_right_pga_mixer_controls[0], | ||
611 | ARRAY_SIZE(aic3x_right_pga_mixer_controls)), | ||
612 | SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0, | 645 | SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0, |
613 | &aic3x_right_line1l_mux_controls), | 646 | &aic3x_right_line1l_mux_controls), |
614 | SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0, | 647 | SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0, |
615 | &aic3x_right_line1r_mux_controls), | 648 | &aic3x_right_line1r_mux_controls), |
649 | |||
650 | /* Mic Bias */ | ||
651 | SND_SOC_DAPM_SUPPLY("Mic Bias", MICBIAS_CTRL, 6, 0, | ||
652 | mic_bias_event, | ||
653 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
654 | |||
655 | SND_SOC_DAPM_OUTPUT("LLOUT"), | ||
656 | SND_SOC_DAPM_OUTPUT("RLOUT"), | ||
657 | SND_SOC_DAPM_OUTPUT("HPLOUT"), | ||
658 | SND_SOC_DAPM_OUTPUT("HPROUT"), | ||
659 | SND_SOC_DAPM_OUTPUT("HPLCOM"), | ||
660 | SND_SOC_DAPM_OUTPUT("HPRCOM"), | ||
661 | |||
662 | SND_SOC_DAPM_INPUT("LINE1L"), | ||
663 | SND_SOC_DAPM_INPUT("LINE1R"), | ||
664 | |||
665 | /* | ||
666 | * Virtual output pin to detection block inside codec. This can be | ||
667 | * used to keep codec bias on if gpio or detection features are needed. | ||
668 | * Force pin on or construct a path with an input jack and mic bias | ||
669 | * widgets. | ||
670 | */ | ||
671 | SND_SOC_DAPM_OUTPUT("Detection"), | ||
672 | }; | ||
673 | |||
674 | /* For other than tlv320aic3104 */ | ||
675 | static const struct snd_soc_dapm_widget aic3x_extra_dapm_widgets[] = { | ||
676 | /* Inputs to Left ADC */ | ||
677 | SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0, | ||
678 | &aic3x_left_pga_mixer_controls[0], | ||
679 | ARRAY_SIZE(aic3x_left_pga_mixer_controls)), | ||
680 | SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0, | ||
681 | &aic3x_left_line2_mux_controls), | ||
682 | |||
683 | /* Inputs to Right ADC */ | ||
684 | SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0, | ||
685 | &aic3x_right_pga_mixer_controls[0], | ||
686 | ARRAY_SIZE(aic3x_right_pga_mixer_controls)), | ||
616 | SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0, | 687 | SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0, |
617 | &aic3x_right_line2_mux_controls), | 688 | &aic3x_right_line2_mux_controls), |
618 | 689 | ||
@@ -637,11 +708,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
637 | SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 32", | 708 | SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 32", |
638 | AIC3X_ASD_INTF_CTRLA, 0, 3, 3, 0), | 709 | AIC3X_ASD_INTF_CTRLA, 0, 3, 3, 0), |
639 | 710 | ||
640 | /* Mic Bias */ | ||
641 | SND_SOC_DAPM_SUPPLY("Mic Bias", MICBIAS_CTRL, 6, 0, | ||
642 | mic_bias_event, | ||
643 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
644 | |||
645 | /* Output mixers */ | 711 | /* Output mixers */ |
646 | SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0, | 712 | SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0, |
647 | &aic3x_left_line_mixer_controls[0], | 713 | &aic3x_left_line_mixer_controls[0], |
@@ -662,27 +728,46 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
662 | &aic3x_right_hpcom_mixer_controls[0], | 728 | &aic3x_right_hpcom_mixer_controls[0], |
663 | ARRAY_SIZE(aic3x_right_hpcom_mixer_controls)), | 729 | ARRAY_SIZE(aic3x_right_hpcom_mixer_controls)), |
664 | 730 | ||
665 | SND_SOC_DAPM_OUTPUT("LLOUT"), | ||
666 | SND_SOC_DAPM_OUTPUT("RLOUT"), | ||
667 | SND_SOC_DAPM_OUTPUT("HPLOUT"), | ||
668 | SND_SOC_DAPM_OUTPUT("HPROUT"), | ||
669 | SND_SOC_DAPM_OUTPUT("HPLCOM"), | ||
670 | SND_SOC_DAPM_OUTPUT("HPRCOM"), | ||
671 | |||
672 | SND_SOC_DAPM_INPUT("MIC3L"), | 731 | SND_SOC_DAPM_INPUT("MIC3L"), |
673 | SND_SOC_DAPM_INPUT("MIC3R"), | 732 | SND_SOC_DAPM_INPUT("MIC3R"), |
674 | SND_SOC_DAPM_INPUT("LINE1L"), | ||
675 | SND_SOC_DAPM_INPUT("LINE1R"), | ||
676 | SND_SOC_DAPM_INPUT("LINE2L"), | 733 | SND_SOC_DAPM_INPUT("LINE2L"), |
677 | SND_SOC_DAPM_INPUT("LINE2R"), | 734 | SND_SOC_DAPM_INPUT("LINE2R"), |
735 | }; | ||
678 | 736 | ||
679 | /* | 737 | /* For tlv320aic3104 */ |
680 | * Virtual output pin to detection block inside codec. This can be | 738 | static const struct snd_soc_dapm_widget aic3104_extra_dapm_widgets[] = { |
681 | * used to keep codec bias on if gpio or detection features are needed. | 739 | /* Inputs to Left ADC */ |
682 | * Force pin on or construct a path with an input jack and mic bias | 740 | SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0, |
683 | * widgets. | 741 | &aic3104_left_pga_mixer_controls[0], |
684 | */ | 742 | ARRAY_SIZE(aic3104_left_pga_mixer_controls)), |
685 | SND_SOC_DAPM_OUTPUT("Detection"), | 743 | |
744 | /* Inputs to Right ADC */ | ||
745 | SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0, | ||
746 | &aic3104_right_pga_mixer_controls[0], | ||
747 | ARRAY_SIZE(aic3104_right_pga_mixer_controls)), | ||
748 | |||
749 | /* Output mixers */ | ||
750 | SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0, | ||
751 | &aic3x_left_line_mixer_controls[0], | ||
752 | ARRAY_SIZE(aic3x_left_line_mixer_controls) - 2), | ||
753 | SND_SOC_DAPM_MIXER("Right Line Mixer", SND_SOC_NOPM, 0, 0, | ||
754 | &aic3x_right_line_mixer_controls[0], | ||
755 | ARRAY_SIZE(aic3x_right_line_mixer_controls) - 2), | ||
756 | SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0, | ||
757 | &aic3x_left_hp_mixer_controls[0], | ||
758 | ARRAY_SIZE(aic3x_left_hp_mixer_controls) - 2), | ||
759 | SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0, | ||
760 | &aic3x_right_hp_mixer_controls[0], | ||
761 | ARRAY_SIZE(aic3x_right_hp_mixer_controls) - 2), | ||
762 | SND_SOC_DAPM_MIXER("Left HPCOM Mixer", SND_SOC_NOPM, 0, 0, | ||
763 | &aic3x_left_hpcom_mixer_controls[0], | ||
764 | ARRAY_SIZE(aic3x_left_hpcom_mixer_controls) - 2), | ||
765 | SND_SOC_DAPM_MIXER("Right HPCOM Mixer", SND_SOC_NOPM, 0, 0, | ||
766 | &aic3x_right_hpcom_mixer_controls[0], | ||
767 | ARRAY_SIZE(aic3x_right_hpcom_mixer_controls) - 2), | ||
768 | |||
769 | SND_SOC_DAPM_INPUT("MIC2L"), | ||
770 | SND_SOC_DAPM_INPUT("MIC2R"), | ||
686 | }; | 771 | }; |
687 | 772 | ||
688 | static const struct snd_soc_dapm_widget aic3x_dapm_mono_widgets[] = { | 773 | static const struct snd_soc_dapm_widget aic3x_dapm_mono_widgets[] = { |
@@ -712,17 +797,10 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
712 | {"Left Line1R Mux", "single-ended", "LINE1R"}, | 797 | {"Left Line1R Mux", "single-ended", "LINE1R"}, |
713 | {"Left Line1R Mux", "differential", "LINE1R"}, | 798 | {"Left Line1R Mux", "differential", "LINE1R"}, |
714 | 799 | ||
715 | {"Left Line2L Mux", "single-ended", "LINE2L"}, | ||
716 | {"Left Line2L Mux", "differential", "LINE2L"}, | ||
717 | |||
718 | {"Left PGA Mixer", "Line1L Switch", "Left Line1L Mux"}, | 800 | {"Left PGA Mixer", "Line1L Switch", "Left Line1L Mux"}, |
719 | {"Left PGA Mixer", "Line1R Switch", "Left Line1R Mux"}, | 801 | {"Left PGA Mixer", "Line1R Switch", "Left Line1R Mux"}, |
720 | {"Left PGA Mixer", "Line2L Switch", "Left Line2L Mux"}, | ||
721 | {"Left PGA Mixer", "Mic3L Switch", "MIC3L"}, | ||
722 | {"Left PGA Mixer", "Mic3R Switch", "MIC3R"}, | ||
723 | 802 | ||
724 | {"Left ADC", NULL, "Left PGA Mixer"}, | 803 | {"Left ADC", NULL, "Left PGA Mixer"}, |
725 | {"Left ADC", NULL, "GPIO1 dmic modclk"}, | ||
726 | 804 | ||
727 | /* Right Input */ | 805 | /* Right Input */ |
728 | {"Right Line1R Mux", "single-ended", "LINE1R"}, | 806 | {"Right Line1R Mux", "single-ended", "LINE1R"}, |
@@ -730,25 +808,10 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
730 | {"Right Line1L Mux", "single-ended", "LINE1L"}, | 808 | {"Right Line1L Mux", "single-ended", "LINE1L"}, |
731 | {"Right Line1L Mux", "differential", "LINE1L"}, | 809 | {"Right Line1L Mux", "differential", "LINE1L"}, |
732 | 810 | ||
733 | {"Right Line2R Mux", "single-ended", "LINE2R"}, | ||
734 | {"Right Line2R Mux", "differential", "LINE2R"}, | ||
735 | |||
736 | {"Right PGA Mixer", "Line1L Switch", "Right Line1L Mux"}, | 811 | {"Right PGA Mixer", "Line1L Switch", "Right Line1L Mux"}, |
737 | {"Right PGA Mixer", "Line1R Switch", "Right Line1R Mux"}, | 812 | {"Right PGA Mixer", "Line1R Switch", "Right Line1R Mux"}, |
738 | {"Right PGA Mixer", "Line2R Switch", "Right Line2R Mux"}, | ||
739 | {"Right PGA Mixer", "Mic3L Switch", "MIC3L"}, | ||
740 | {"Right PGA Mixer", "Mic3R Switch", "MIC3R"}, | ||
741 | 813 | ||
742 | {"Right ADC", NULL, "Right PGA Mixer"}, | 814 | {"Right ADC", NULL, "Right PGA Mixer"}, |
743 | {"Right ADC", NULL, "GPIO1 dmic modclk"}, | ||
744 | |||
745 | /* | ||
746 | * Logical path between digital mic enable and GPIO1 modulator clock | ||
747 | * output function | ||
748 | */ | ||
749 | {"GPIO1 dmic modclk", NULL, "DMic Rate 128"}, | ||
750 | {"GPIO1 dmic modclk", NULL, "DMic Rate 64"}, | ||
751 | {"GPIO1 dmic modclk", NULL, "DMic Rate 32"}, | ||
752 | 815 | ||
753 | /* Left DAC Output */ | 816 | /* Left DAC Output */ |
754 | {"Left DAC Mux", "DAC_L1", "Left DAC"}, | 817 | {"Left DAC Mux", "DAC_L1", "Left DAC"}, |
@@ -761,10 +824,8 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
761 | {"Right DAC Mux", "DAC_R3", "Right DAC"}, | 824 | {"Right DAC Mux", "DAC_R3", "Right DAC"}, |
762 | 825 | ||
763 | /* Left Line Output */ | 826 | /* Left Line Output */ |
764 | {"Left Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
765 | {"Left Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, | 827 | {"Left Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, |
766 | {"Left Line Mixer", "DACL1 Switch", "Left DAC Mux"}, | 828 | {"Left Line Mixer", "DACL1 Switch", "Left DAC Mux"}, |
767 | {"Left Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
768 | {"Left Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, | 829 | {"Left Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, |
769 | {"Left Line Mixer", "DACR1 Switch", "Right DAC Mux"}, | 830 | {"Left Line Mixer", "DACR1 Switch", "Right DAC Mux"}, |
770 | 831 | ||
@@ -773,10 +834,8 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
773 | {"LLOUT", NULL, "Left Line Out"}, | 834 | {"LLOUT", NULL, "Left Line Out"}, |
774 | 835 | ||
775 | /* Right Line Output */ | 836 | /* Right Line Output */ |
776 | {"Right Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
777 | {"Right Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, | 837 | {"Right Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, |
778 | {"Right Line Mixer", "DACL1 Switch", "Left DAC Mux"}, | 838 | {"Right Line Mixer", "DACL1 Switch", "Left DAC Mux"}, |
779 | {"Right Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
780 | {"Right Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, | 839 | {"Right Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, |
781 | {"Right Line Mixer", "DACR1 Switch", "Right DAC Mux"}, | 840 | {"Right Line Mixer", "DACR1 Switch", "Right DAC Mux"}, |
782 | 841 | ||
@@ -785,10 +844,8 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
785 | {"RLOUT", NULL, "Right Line Out"}, | 844 | {"RLOUT", NULL, "Right Line Out"}, |
786 | 845 | ||
787 | /* Left HP Output */ | 846 | /* Left HP Output */ |
788 | {"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
789 | {"Left HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, | 847 | {"Left HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, |
790 | {"Left HP Mixer", "DACL1 Switch", "Left DAC Mux"}, | 848 | {"Left HP Mixer", "DACL1 Switch", "Left DAC Mux"}, |
791 | {"Left HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
792 | {"Left HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, | 849 | {"Left HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, |
793 | {"Left HP Mixer", "DACR1 Switch", "Right DAC Mux"}, | 850 | {"Left HP Mixer", "DACR1 Switch", "Right DAC Mux"}, |
794 | 851 | ||
@@ -797,10 +854,8 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
797 | {"HPLOUT", NULL, "Left HP Out"}, | 854 | {"HPLOUT", NULL, "Left HP Out"}, |
798 | 855 | ||
799 | /* Right HP Output */ | 856 | /* Right HP Output */ |
800 | {"Right HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
801 | {"Right HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, | 857 | {"Right HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, |
802 | {"Right HP Mixer", "DACL1 Switch", "Left DAC Mux"}, | 858 | {"Right HP Mixer", "DACL1 Switch", "Left DAC Mux"}, |
803 | {"Right HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
804 | {"Right HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, | 859 | {"Right HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, |
805 | {"Right HP Mixer", "DACR1 Switch", "Right DAC Mux"}, | 860 | {"Right HP Mixer", "DACR1 Switch", "Right DAC Mux"}, |
806 | 861 | ||
@@ -809,10 +864,8 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
809 | {"HPROUT", NULL, "Right HP Out"}, | 864 | {"HPROUT", NULL, "Right HP Out"}, |
810 | 865 | ||
811 | /* Left HPCOM Output */ | 866 | /* Left HPCOM Output */ |
812 | {"Left HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
813 | {"Left HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, | 867 | {"Left HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, |
814 | {"Left HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"}, | 868 | {"Left HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"}, |
815 | {"Left HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
816 | {"Left HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, | 869 | {"Left HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, |
817 | {"Left HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"}, | 870 | {"Left HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"}, |
818 | 871 | ||
@@ -823,10 +876,8 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
823 | {"HPLCOM", NULL, "Left HP Com"}, | 876 | {"HPLCOM", NULL, "Left HP Com"}, |
824 | 877 | ||
825 | /* Right HPCOM Output */ | 878 | /* Right HPCOM Output */ |
826 | {"Right HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
827 | {"Right HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, | 879 | {"Right HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, |
828 | {"Right HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"}, | 880 | {"Right HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"}, |
829 | {"Right HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
830 | {"Right HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, | 881 | {"Right HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, |
831 | {"Right HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"}, | 882 | {"Right HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"}, |
832 | 883 | ||
@@ -839,6 +890,72 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
839 | {"HPRCOM", NULL, "Right HP Com"}, | 890 | {"HPRCOM", NULL, "Right HP Com"}, |
840 | }; | 891 | }; |
841 | 892 | ||
893 | /* For other than tlv320aic3104 */ | ||
894 | static const struct snd_soc_dapm_route intercon_extra[] = { | ||
895 | /* Left Input */ | ||
896 | {"Left Line2L Mux", "single-ended", "LINE2L"}, | ||
897 | {"Left Line2L Mux", "differential", "LINE2L"}, | ||
898 | |||
899 | {"Left PGA Mixer", "Line2L Switch", "Left Line2L Mux"}, | ||
900 | {"Left PGA Mixer", "Mic3L Switch", "MIC3L"}, | ||
901 | {"Left PGA Mixer", "Mic3R Switch", "MIC3R"}, | ||
902 | |||
903 | {"Left ADC", NULL, "GPIO1 dmic modclk"}, | ||
904 | |||
905 | /* Right Input */ | ||
906 | {"Right Line2R Mux", "single-ended", "LINE2R"}, | ||
907 | {"Right Line2R Mux", "differential", "LINE2R"}, | ||
908 | |||
909 | {"Right PGA Mixer", "Line2R Switch", "Right Line2R Mux"}, | ||
910 | {"Right PGA Mixer", "Mic3L Switch", "MIC3L"}, | ||
911 | {"Right PGA Mixer", "Mic3R Switch", "MIC3R"}, | ||
912 | |||
913 | {"Right ADC", NULL, "GPIO1 dmic modclk"}, | ||
914 | |||
915 | /* | ||
916 | * Logical path between digital mic enable and GPIO1 modulator clock | ||
917 | * output function | ||
918 | */ | ||
919 | {"GPIO1 dmic modclk", NULL, "DMic Rate 128"}, | ||
920 | {"GPIO1 dmic modclk", NULL, "DMic Rate 64"}, | ||
921 | {"GPIO1 dmic modclk", NULL, "DMic Rate 32"}, | ||
922 | |||
923 | /* Left Line Output */ | ||
924 | {"Left Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
925 | {"Left Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
926 | |||
927 | /* Right Line Output */ | ||
928 | {"Right Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
929 | {"Right Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
930 | |||
931 | /* Left HP Output */ | ||
932 | {"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
933 | {"Left HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
934 | |||
935 | /* Right HP Output */ | ||
936 | {"Right HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
937 | {"Right HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
938 | |||
939 | /* Left HPCOM Output */ | ||
940 | {"Left HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
941 | {"Left HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
942 | |||
943 | /* Right HPCOM Output */ | ||
944 | {"Right HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | ||
945 | {"Right HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, | ||
946 | }; | ||
947 | |||
948 | /* For tlv320aic3104 */ | ||
949 | static const struct snd_soc_dapm_route intercon_extra_3104[] = { | ||
950 | /* Left Input */ | ||
951 | {"Left PGA Mixer", "Mic2L Switch", "MIC2L"}, | ||
952 | {"Left PGA Mixer", "Mic2R Switch", "MIC2R"}, | ||
953 | |||
954 | /* Right Input */ | ||
955 | {"Right PGA Mixer", "Mic2L Switch", "MIC2L"}, | ||
956 | {"Right PGA Mixer", "Mic2R Switch", "MIC2R"}, | ||
957 | }; | ||
958 | |||
842 | static const struct snd_soc_dapm_route intercon_mono[] = { | 959 | static const struct snd_soc_dapm_route intercon_mono[] = { |
843 | /* Mono Output */ | 960 | /* Mono Output */ |
844 | {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, | 961 | {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, |
@@ -867,17 +984,31 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec) | |||
867 | switch (aic3x->model) { | 984 | switch (aic3x->model) { |
868 | case AIC3X_MODEL_3X: | 985 | case AIC3X_MODEL_3X: |
869 | case AIC3X_MODEL_33: | 986 | case AIC3X_MODEL_33: |
987 | snd_soc_dapm_new_controls(dapm, aic3x_extra_dapm_widgets, | ||
988 | ARRAY_SIZE(aic3x_extra_dapm_widgets)); | ||
989 | snd_soc_dapm_add_routes(dapm, intercon_extra, | ||
990 | ARRAY_SIZE(intercon_extra)); | ||
870 | snd_soc_dapm_new_controls(dapm, aic3x_dapm_mono_widgets, | 991 | snd_soc_dapm_new_controls(dapm, aic3x_dapm_mono_widgets, |
871 | ARRAY_SIZE(aic3x_dapm_mono_widgets)); | 992 | ARRAY_SIZE(aic3x_dapm_mono_widgets)); |
872 | snd_soc_dapm_add_routes(dapm, intercon_mono, | 993 | snd_soc_dapm_add_routes(dapm, intercon_mono, |
873 | ARRAY_SIZE(intercon_mono)); | 994 | ARRAY_SIZE(intercon_mono)); |
874 | break; | 995 | break; |
875 | case AIC3X_MODEL_3007: | 996 | case AIC3X_MODEL_3007: |
997 | snd_soc_dapm_new_controls(dapm, aic3x_extra_dapm_widgets, | ||
998 | ARRAY_SIZE(aic3x_extra_dapm_widgets)); | ||
999 | snd_soc_dapm_add_routes(dapm, intercon_extra, | ||
1000 | ARRAY_SIZE(intercon_extra)); | ||
876 | snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets, | 1001 | snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets, |
877 | ARRAY_SIZE(aic3007_dapm_widgets)); | 1002 | ARRAY_SIZE(aic3007_dapm_widgets)); |
878 | snd_soc_dapm_add_routes(dapm, intercon_3007, | 1003 | snd_soc_dapm_add_routes(dapm, intercon_3007, |
879 | ARRAY_SIZE(intercon_3007)); | 1004 | ARRAY_SIZE(intercon_3007)); |
880 | break; | 1005 | break; |
1006 | case AIC3X_MODEL_3104: | ||
1007 | snd_soc_dapm_new_controls(dapm, aic3104_extra_dapm_widgets, | ||
1008 | ARRAY_SIZE(aic3104_extra_dapm_widgets)); | ||
1009 | snd_soc_dapm_add_routes(dapm, intercon_extra_3104, | ||
1010 | ARRAY_SIZE(intercon_extra_3104)); | ||
1011 | break; | ||
881 | } | 1012 | } |
882 | 1013 | ||
883 | return 0; | 1014 | return 0; |
@@ -1438,23 +1569,33 @@ static int aic3x_probe(struct snd_soc_codec *codec) | |||
1438 | aic3x_init(codec); | 1569 | aic3x_init(codec); |
1439 | 1570 | ||
1440 | if (aic3x->setup) { | 1571 | if (aic3x->setup) { |
1441 | /* setup GPIO functions */ | 1572 | if (aic3x->model != AIC3X_MODEL_3104) { |
1442 | snd_soc_write(codec, AIC3X_GPIO1_REG, | 1573 | /* setup GPIO functions */ |
1443 | (aic3x->setup->gpio_func[0] & 0xf) << 4); | 1574 | snd_soc_write(codec, AIC3X_GPIO1_REG, |
1444 | snd_soc_write(codec, AIC3X_GPIO2_REG, | 1575 | (aic3x->setup->gpio_func[0] & 0xf) << 4); |
1445 | (aic3x->setup->gpio_func[1] & 0xf) << 4); | 1576 | snd_soc_write(codec, AIC3X_GPIO2_REG, |
1577 | (aic3x->setup->gpio_func[1] & 0xf) << 4); | ||
1578 | } else { | ||
1579 | dev_warn(codec->dev, "GPIO functionality is not supported on tlv320aic3104\n"); | ||
1580 | } | ||
1446 | } | 1581 | } |
1447 | 1582 | ||
1448 | switch (aic3x->model) { | 1583 | switch (aic3x->model) { |
1449 | case AIC3X_MODEL_3X: | 1584 | case AIC3X_MODEL_3X: |
1450 | case AIC3X_MODEL_33: | 1585 | case AIC3X_MODEL_33: |
1586 | snd_soc_add_codec_controls(codec, aic3x_extra_snd_controls, | ||
1587 | ARRAY_SIZE(aic3x_extra_snd_controls)); | ||
1451 | snd_soc_add_codec_controls(codec, aic3x_mono_controls, | 1588 | snd_soc_add_codec_controls(codec, aic3x_mono_controls, |
1452 | ARRAY_SIZE(aic3x_mono_controls)); | 1589 | ARRAY_SIZE(aic3x_mono_controls)); |
1453 | break; | 1590 | break; |
1454 | case AIC3X_MODEL_3007: | 1591 | case AIC3X_MODEL_3007: |
1592 | snd_soc_add_codec_controls(codec, aic3x_extra_snd_controls, | ||
1593 | ARRAY_SIZE(aic3x_extra_snd_controls)); | ||
1455 | snd_soc_add_codec_controls(codec, | 1594 | snd_soc_add_codec_controls(codec, |
1456 | &aic3x_classd_amp_gain_ctrl, 1); | 1595 | &aic3x_classd_amp_gain_ctrl, 1); |
1457 | break; | 1596 | break; |
1597 | case AIC3X_MODEL_3104: | ||
1598 | break; | ||
1458 | } | 1599 | } |
1459 | 1600 | ||
1460 | /* set mic bias voltage */ | 1601 | /* set mic bias voltage */ |
@@ -1522,6 +1663,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = { | |||
1522 | { "tlv320aic33", AIC3X_MODEL_33 }, | 1663 | { "tlv320aic33", AIC3X_MODEL_33 }, |
1523 | { "tlv320aic3007", AIC3X_MODEL_3007 }, | 1664 | { "tlv320aic3007", AIC3X_MODEL_3007 }, |
1524 | { "tlv320aic3106", AIC3X_MODEL_3X }, | 1665 | { "tlv320aic3106", AIC3X_MODEL_3X }, |
1666 | { "tlv320aic3104", AIC3X_MODEL_3104 }, | ||
1525 | { } | 1667 | { } |
1526 | }; | 1668 | }; |
1527 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); | 1669 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); |
@@ -1673,6 +1815,7 @@ static const struct of_device_id tlv320aic3x_of_match[] = { | |||
1673 | { .compatible = "ti,tlv320aic33" }, | 1815 | { .compatible = "ti,tlv320aic33" }, |
1674 | { .compatible = "ti,tlv320aic3007" }, | 1816 | { .compatible = "ti,tlv320aic3007" }, |
1675 | { .compatible = "ti,tlv320aic3106" }, | 1817 | { .compatible = "ti,tlv320aic3106" }, |
1818 | { .compatible = "ti,tlv320aic3104" }, | ||
1676 | {}, | 1819 | {}, |
1677 | }; | 1820 | }; |
1678 | MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); | 1821 | MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 0fe2ced5b09f..4e3e607dec13 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -423,17 +423,18 @@ exit: | |||
423 | static int dac33_playback_event(struct snd_soc_dapm_widget *w, | 423 | static int dac33_playback_event(struct snd_soc_dapm_widget *w, |
424 | struct snd_kcontrol *kcontrol, int event) | 424 | struct snd_kcontrol *kcontrol, int event) |
425 | { | 425 | { |
426 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec); | 426 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
427 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | ||
427 | 428 | ||
428 | switch (event) { | 429 | switch (event) { |
429 | case SND_SOC_DAPM_PRE_PMU: | 430 | case SND_SOC_DAPM_PRE_PMU: |
430 | if (likely(dac33->substream)) { | 431 | if (likely(dac33->substream)) { |
431 | dac33_calculate_times(dac33->substream, w->codec); | 432 | dac33_calculate_times(dac33->substream, codec); |
432 | dac33_prepare_chip(dac33->substream, w->codec); | 433 | dac33_prepare_chip(dac33->substream, codec); |
433 | } | 434 | } |
434 | break; | 435 | break; |
435 | case SND_SOC_DAPM_POST_PMD: | 436 | case SND_SOC_DAPM_POST_PMD: |
436 | dac33_disable_digital(w->codec); | 437 | dac33_disable_digital(codec); |
437 | break; | 438 | break; |
438 | } | 439 | } |
439 | return 0; | 440 | return 0; |
diff --git a/sound/soc/codecs/ts3a227e.c b/sound/soc/codecs/ts3a227e.c index 9f2dced046de..9fd80ac1897f 100644 --- a/sound/soc/codecs/ts3a227e.c +++ b/sound/soc/codecs/ts3a227e.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <sound/jack.h> | 20 | #include <sound/jack.h> |
21 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
22 | 22 | ||
23 | #include "ts3a227e.h" | ||
24 | |||
23 | struct ts3a227e { | 25 | struct ts3a227e { |
24 | struct regmap *regmap; | 26 | struct regmap *regmap; |
25 | struct snd_soc_jack *jack; | 27 | struct snd_soc_jack *jack; |
@@ -79,6 +81,10 @@ static const int ts3a227e_buttons[] = { | |||
79 | /* TS3A227E_REG_SETTING_2 0x05 */ | 81 | /* TS3A227E_REG_SETTING_2 0x05 */ |
80 | #define KP_ENABLE 0x04 | 82 | #define KP_ENABLE 0x04 |
81 | 83 | ||
84 | /* TS3A227E_REG_SETTING_3 0x06 */ | ||
85 | #define MICBIAS_SETTING_SFT (3) | ||
86 | #define MICBIAS_SETTING_MASK (0x7 << MICBIAS_SETTING_SFT) | ||
87 | |||
82 | /* TS3A227E_REG_ACCESSORY_STATUS 0x0b */ | 88 | /* TS3A227E_REG_ACCESSORY_STATUS 0x0b */ |
83 | #define TYPE_3_POLE 0x01 | 89 | #define TYPE_3_POLE 0x01 |
84 | #define TYPE_4_POLE_OMTP 0x02 | 90 | #define TYPE_4_POLE_OMTP 0x02 |
@@ -221,9 +227,9 @@ int ts3a227e_enable_jack_detect(struct snd_soc_component *component, | |||
221 | struct ts3a227e *ts3a227e = snd_soc_component_get_drvdata(component); | 227 | struct ts3a227e *ts3a227e = snd_soc_component_get_drvdata(component); |
222 | 228 | ||
223 | snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA); | 229 | snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA); |
224 | snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP); | 230 | snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); |
225 | snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); | 231 | snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); |
226 | snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); | 232 | snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); |
227 | 233 | ||
228 | ts3a227e->jack = jack; | 234 | ts3a227e->jack = jack; |
229 | ts3a227e_jack_report(ts3a227e); | 235 | ts3a227e_jack_report(ts3a227e); |
@@ -248,6 +254,21 @@ static const struct regmap_config ts3a227e_regmap_config = { | |||
248 | .num_reg_defaults = ARRAY_SIZE(ts3a227e_reg_defaults), | 254 | .num_reg_defaults = ARRAY_SIZE(ts3a227e_reg_defaults), |
249 | }; | 255 | }; |
250 | 256 | ||
257 | static int ts3a227e_parse_dt(struct ts3a227e *ts3a227e, struct device_node *np) | ||
258 | { | ||
259 | u32 micbias; | ||
260 | int err; | ||
261 | |||
262 | err = of_property_read_u32(np, "ti,micbias", &micbias); | ||
263 | if (!err) { | ||
264 | regmap_update_bits(ts3a227e->regmap, TS3A227E_REG_SETTING_3, | ||
265 | MICBIAS_SETTING_MASK, | ||
266 | (micbias & 0x07) << MICBIAS_SETTING_SFT); | ||
267 | } | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
251 | static int ts3a227e_i2c_probe(struct i2c_client *i2c, | 272 | static int ts3a227e_i2c_probe(struct i2c_client *i2c, |
252 | const struct i2c_device_id *id) | 273 | const struct i2c_device_id *id) |
253 | { | 274 | { |
@@ -266,6 +287,14 @@ static int ts3a227e_i2c_probe(struct i2c_client *i2c, | |||
266 | if (IS_ERR(ts3a227e->regmap)) | 287 | if (IS_ERR(ts3a227e->regmap)) |
267 | return PTR_ERR(ts3a227e->regmap); | 288 | return PTR_ERR(ts3a227e->regmap); |
268 | 289 | ||
290 | if (dev->of_node) { | ||
291 | ret = ts3a227e_parse_dt(ts3a227e, dev->of_node); | ||
292 | if (ret) { | ||
293 | dev_err(dev, "Failed to parse device tree: %d\n", ret); | ||
294 | return ret; | ||
295 | } | ||
296 | } | ||
297 | |||
269 | ret = devm_request_threaded_irq(dev, i2c->irq, NULL, ts3a227e_interrupt, | 298 | ret = devm_request_threaded_irq(dev, i2c->irq, NULL, ts3a227e_interrupt, |
270 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | 299 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, |
271 | "TS3A227E", ts3a227e); | 300 | "TS3A227E", ts3a227e); |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 44af3188afb9..d04693e9cf9f 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -567,12 +567,13 @@ static const struct snd_kcontrol_new twl4030_dapm_dbypassv_control = | |||
567 | static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ | 567 | static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ |
568 | struct snd_kcontrol *kcontrol, int event) \ | 568 | struct snd_kcontrol *kcontrol, int event) \ |
569 | { \ | 569 | { \ |
570 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); \ | 570 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); \ |
571 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); \ | ||
571 | \ | 572 | \ |
572 | switch (event) { \ | 573 | switch (event) { \ |
573 | case SND_SOC_DAPM_POST_PMU: \ | 574 | case SND_SOC_DAPM_POST_PMU: \ |
574 | twl4030->pin_name##_enabled = 1; \ | 575 | twl4030->pin_name##_enabled = 1; \ |
575 | twl4030_write(w->codec, reg, twl4030_read(w->codec, reg)); \ | 576 | twl4030_write(codec, reg, twl4030_read(codec, reg)); \ |
576 | break; \ | 577 | break; \ |
577 | case SND_SOC_DAPM_POST_PMD: \ | 578 | case SND_SOC_DAPM_POST_PMD: \ |
578 | twl4030->pin_name##_enabled = 0; \ | 579 | twl4030->pin_name##_enabled = 0; \ |
@@ -621,12 +622,14 @@ static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp) | |||
621 | static int handsfreelpga_event(struct snd_soc_dapm_widget *w, | 622 | static int handsfreelpga_event(struct snd_soc_dapm_widget *w, |
622 | struct snd_kcontrol *kcontrol, int event) | 623 | struct snd_kcontrol *kcontrol, int event) |
623 | { | 624 | { |
625 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
626 | |||
624 | switch (event) { | 627 | switch (event) { |
625 | case SND_SOC_DAPM_POST_PMU: | 628 | case SND_SOC_DAPM_POST_PMU: |
626 | handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 1); | 629 | handsfree_ramp(codec, TWL4030_REG_HFL_CTL, 1); |
627 | break; | 630 | break; |
628 | case SND_SOC_DAPM_POST_PMD: | 631 | case SND_SOC_DAPM_POST_PMD: |
629 | handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 0); | 632 | handsfree_ramp(codec, TWL4030_REG_HFL_CTL, 0); |
630 | break; | 633 | break; |
631 | } | 634 | } |
632 | return 0; | 635 | return 0; |
@@ -635,12 +638,14 @@ static int handsfreelpga_event(struct snd_soc_dapm_widget *w, | |||
635 | static int handsfreerpga_event(struct snd_soc_dapm_widget *w, | 638 | static int handsfreerpga_event(struct snd_soc_dapm_widget *w, |
636 | struct snd_kcontrol *kcontrol, int event) | 639 | struct snd_kcontrol *kcontrol, int event) |
637 | { | 640 | { |
641 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
642 | |||
638 | switch (event) { | 643 | switch (event) { |
639 | case SND_SOC_DAPM_POST_PMU: | 644 | case SND_SOC_DAPM_POST_PMU: |
640 | handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 1); | 645 | handsfree_ramp(codec, TWL4030_REG_HFR_CTL, 1); |
641 | break; | 646 | break; |
642 | case SND_SOC_DAPM_POST_PMD: | 647 | case SND_SOC_DAPM_POST_PMD: |
643 | handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 0); | 648 | handsfree_ramp(codec, TWL4030_REG_HFR_CTL, 0); |
644 | break; | 649 | break; |
645 | } | 650 | } |
646 | return 0; | 651 | return 0; |
@@ -649,19 +654,23 @@ static int handsfreerpga_event(struct snd_soc_dapm_widget *w, | |||
649 | static int vibramux_event(struct snd_soc_dapm_widget *w, | 654 | static int vibramux_event(struct snd_soc_dapm_widget *w, |
650 | struct snd_kcontrol *kcontrol, int event) | 655 | struct snd_kcontrol *kcontrol, int event) |
651 | { | 656 | { |
652 | twl4030_write(w->codec, TWL4030_REG_VIBRA_SET, 0xff); | 657 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
658 | |||
659 | twl4030_write(codec, TWL4030_REG_VIBRA_SET, 0xff); | ||
653 | return 0; | 660 | return 0; |
654 | } | 661 | } |
655 | 662 | ||
656 | static int apll_event(struct snd_soc_dapm_widget *w, | 663 | static int apll_event(struct snd_soc_dapm_widget *w, |
657 | struct snd_kcontrol *kcontrol, int event) | 664 | struct snd_kcontrol *kcontrol, int event) |
658 | { | 665 | { |
666 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
667 | |||
659 | switch (event) { | 668 | switch (event) { |
660 | case SND_SOC_DAPM_PRE_PMU: | 669 | case SND_SOC_DAPM_PRE_PMU: |
661 | twl4030_apll_enable(w->codec, 1); | 670 | twl4030_apll_enable(codec, 1); |
662 | break; | 671 | break; |
663 | case SND_SOC_DAPM_POST_PMD: | 672 | case SND_SOC_DAPM_POST_PMD: |
664 | twl4030_apll_enable(w->codec, 0); | 673 | twl4030_apll_enable(codec, 0); |
665 | break; | 674 | break; |
666 | } | 675 | } |
667 | return 0; | 676 | return 0; |
@@ -670,23 +679,24 @@ static int apll_event(struct snd_soc_dapm_widget *w, | |||
670 | static int aif_event(struct snd_soc_dapm_widget *w, | 679 | static int aif_event(struct snd_soc_dapm_widget *w, |
671 | struct snd_kcontrol *kcontrol, int event) | 680 | struct snd_kcontrol *kcontrol, int event) |
672 | { | 681 | { |
682 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
673 | u8 audio_if; | 683 | u8 audio_if; |
674 | 684 | ||
675 | audio_if = twl4030_read(w->codec, TWL4030_REG_AUDIO_IF); | 685 | audio_if = twl4030_read(codec, TWL4030_REG_AUDIO_IF); |
676 | switch (event) { | 686 | switch (event) { |
677 | case SND_SOC_DAPM_PRE_PMU: | 687 | case SND_SOC_DAPM_PRE_PMU: |
678 | /* Enable AIF */ | 688 | /* Enable AIF */ |
679 | /* enable the PLL before we use it to clock the DAI */ | 689 | /* enable the PLL before we use it to clock the DAI */ |
680 | twl4030_apll_enable(w->codec, 1); | 690 | twl4030_apll_enable(codec, 1); |
681 | 691 | ||
682 | twl4030_write(w->codec, TWL4030_REG_AUDIO_IF, | 692 | twl4030_write(codec, TWL4030_REG_AUDIO_IF, |
683 | audio_if | TWL4030_AIF_EN); | 693 | audio_if | TWL4030_AIF_EN); |
684 | break; | 694 | break; |
685 | case SND_SOC_DAPM_POST_PMD: | 695 | case SND_SOC_DAPM_POST_PMD: |
686 | /* disable the DAI before we stop it's source PLL */ | 696 | /* disable the DAI before we stop it's source PLL */ |
687 | twl4030_write(w->codec, TWL4030_REG_AUDIO_IF, | 697 | twl4030_write(codec, TWL4030_REG_AUDIO_IF, |
688 | audio_if & ~TWL4030_AIF_EN); | 698 | audio_if & ~TWL4030_AIF_EN); |
689 | twl4030_apll_enable(w->codec, 0); | 699 | twl4030_apll_enable(codec, 0); |
690 | break; | 700 | break; |
691 | } | 701 | } |
692 | return 0; | 702 | return 0; |
@@ -758,20 +768,21 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
758 | static int headsetlpga_event(struct snd_soc_dapm_widget *w, | 768 | static int headsetlpga_event(struct snd_soc_dapm_widget *w, |
759 | struct snd_kcontrol *kcontrol, int event) | 769 | struct snd_kcontrol *kcontrol, int event) |
760 | { | 770 | { |
761 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); | 771 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
772 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | ||
762 | 773 | ||
763 | switch (event) { | 774 | switch (event) { |
764 | case SND_SOC_DAPM_POST_PMU: | 775 | case SND_SOC_DAPM_POST_PMU: |
765 | /* Do the ramp-up only once */ | 776 | /* Do the ramp-up only once */ |
766 | if (!twl4030->hsr_enabled) | 777 | if (!twl4030->hsr_enabled) |
767 | headset_ramp(w->codec, 1); | 778 | headset_ramp(codec, 1); |
768 | 779 | ||
769 | twl4030->hsl_enabled = 1; | 780 | twl4030->hsl_enabled = 1; |
770 | break; | 781 | break; |
771 | case SND_SOC_DAPM_POST_PMD: | 782 | case SND_SOC_DAPM_POST_PMD: |
772 | /* Do the ramp-down only if both headsetL/R is disabled */ | 783 | /* Do the ramp-down only if both headsetL/R is disabled */ |
773 | if (!twl4030->hsr_enabled) | 784 | if (!twl4030->hsr_enabled) |
774 | headset_ramp(w->codec, 0); | 785 | headset_ramp(codec, 0); |
775 | 786 | ||
776 | twl4030->hsl_enabled = 0; | 787 | twl4030->hsl_enabled = 0; |
777 | break; | 788 | break; |
@@ -782,20 +793,21 @@ static int headsetlpga_event(struct snd_soc_dapm_widget *w, | |||
782 | static int headsetrpga_event(struct snd_soc_dapm_widget *w, | 793 | static int headsetrpga_event(struct snd_soc_dapm_widget *w, |
783 | struct snd_kcontrol *kcontrol, int event) | 794 | struct snd_kcontrol *kcontrol, int event) |
784 | { | 795 | { |
785 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); | 796 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
797 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | ||
786 | 798 | ||
787 | switch (event) { | 799 | switch (event) { |
788 | case SND_SOC_DAPM_POST_PMU: | 800 | case SND_SOC_DAPM_POST_PMU: |
789 | /* Do the ramp-up only once */ | 801 | /* Do the ramp-up only once */ |
790 | if (!twl4030->hsl_enabled) | 802 | if (!twl4030->hsl_enabled) |
791 | headset_ramp(w->codec, 1); | 803 | headset_ramp(codec, 1); |
792 | 804 | ||
793 | twl4030->hsr_enabled = 1; | 805 | twl4030->hsr_enabled = 1; |
794 | break; | 806 | break; |
795 | case SND_SOC_DAPM_POST_PMD: | 807 | case SND_SOC_DAPM_POST_PMD: |
796 | /* Do the ramp-down only if both headsetL/R is disabled */ | 808 | /* Do the ramp-down only if both headsetL/R is disabled */ |
797 | if (!twl4030->hsl_enabled) | 809 | if (!twl4030->hsl_enabled) |
798 | headset_ramp(w->codec, 0); | 810 | headset_ramp(codec, 0); |
799 | 811 | ||
800 | twl4030->hsr_enabled = 0; | 812 | twl4030->hsr_enabled = 0; |
801 | break; | 813 | break; |
@@ -806,7 +818,8 @@ static int headsetrpga_event(struct snd_soc_dapm_widget *w, | |||
806 | static int digimic_event(struct snd_soc_dapm_widget *w, | 818 | static int digimic_event(struct snd_soc_dapm_widget *w, |
807 | struct snd_kcontrol *kcontrol, int event) | 819 | struct snd_kcontrol *kcontrol, int event) |
808 | { | 820 | { |
809 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); | 821 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
822 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | ||
810 | struct twl4030_codec_data *pdata = twl4030->pdata; | 823 | struct twl4030_codec_data *pdata = twl4030->pdata; |
811 | 824 | ||
812 | if (pdata && pdata->digimic_delay) | 825 | if (pdata && pdata->digimic_delay) |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 90f47f988b3f..aeec27b6f1af 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -234,7 +234,7 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf) | |||
234 | static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w, | 234 | static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w, |
235 | struct snd_kcontrol *kcontrol, int event) | 235 | struct snd_kcontrol *kcontrol, int event) |
236 | { | 236 | { |
237 | struct snd_soc_codec *codec = w->codec; | 237 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
238 | u8 hslctl, hsrctl; | 238 | u8 hslctl, hsrctl; |
239 | 239 | ||
240 | /* | 240 | /* |
@@ -261,7 +261,7 @@ static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w, | |||
261 | static int twl6040_ep_drv_event(struct snd_soc_dapm_widget *w, | 261 | static int twl6040_ep_drv_event(struct snd_soc_dapm_widget *w, |
262 | struct snd_kcontrol *kcontrol, int event) | 262 | struct snd_kcontrol *kcontrol, int event) |
263 | { | 263 | { |
264 | struct snd_soc_codec *codec = w->codec; | 264 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
265 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | 265 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); |
266 | int ret = 0; | 266 | int ret = 0; |
267 | 267 | ||
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 34ef65c52a7d..8d9de49a5052 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -683,7 +683,7 @@ static const struct snd_kcontrol_new wm2000_controls[] = { | |||
683 | static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w, | 683 | static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w, |
684 | struct snd_kcontrol *kcontrol, int event) | 684 | struct snd_kcontrol *kcontrol, int event) |
685 | { | 685 | { |
686 | struct snd_soc_codec *codec = w->codec; | 686 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
687 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); | 687 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); |
688 | int ret; | 688 | int ret; |
689 | 689 | ||
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index b80970dc2d2f..ea09db585aa1 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c | |||
@@ -775,7 +775,8 @@ static int wm5100_out_ev(struct snd_soc_dapm_widget *w, | |||
775 | struct snd_kcontrol *kcontrol, | 775 | struct snd_kcontrol *kcontrol, |
776 | int event) | 776 | int event) |
777 | { | 777 | { |
778 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(w->codec); | 778 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
779 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | ||
779 | 780 | ||
780 | switch (w->reg) { | 781 | switch (w->reg) { |
781 | case WM5100_CHANNEL_ENABLES_1: | 782 | case WM5100_CHANNEL_ENABLES_1: |
@@ -839,7 +840,7 @@ static int wm5100_post_ev(struct snd_soc_dapm_widget *w, | |||
839 | struct snd_kcontrol *kcontrol, | 840 | struct snd_kcontrol *kcontrol, |
840 | int event) | 841 | int event) |
841 | { | 842 | { |
842 | struct snd_soc_codec *codec = w->codec; | 843 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
843 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | 844 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); |
844 | int ret; | 845 | int ret; |
845 | 846 | ||
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index f439ae052128..6d0fe0ac95a3 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -28,6 +28,7 @@ | |||
28 | 28 | ||
29 | #include <linux/mfd/arizona/core.h> | 29 | #include <linux/mfd/arizona/core.h> |
30 | #include <linux/mfd/arizona/registers.h> | 30 | #include <linux/mfd/arizona/registers.h> |
31 | #include <asm/unaligned.h> | ||
31 | 32 | ||
32 | #include "arizona.h" | 33 | #include "arizona.h" |
33 | #include "wm5102.h" | 34 | #include "wm5102.h" |
@@ -580,7 +581,7 @@ static const struct reg_default wm5102_sysclk_revb_patch[] = { | |||
580 | static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, | 581 | static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, |
581 | struct snd_kcontrol *kcontrol, int event) | 582 | struct snd_kcontrol *kcontrol, int event) |
582 | { | 583 | { |
583 | struct snd_soc_codec *codec = w->codec; | 584 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
584 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 585 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
585 | struct regmap *regmap = arizona->regmap; | 586 | struct regmap *regmap = arizona->regmap; |
586 | const struct reg_default *patch = NULL; | 587 | const struct reg_default *patch = NULL; |
@@ -617,11 +618,10 @@ static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, | |||
617 | { | 618 | { |
618 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 619 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
619 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 620 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
620 | uint16_t data; | ||
621 | 621 | ||
622 | mutex_lock(&arizona->dac_comp_lock); | 622 | mutex_lock(&arizona->dac_comp_lock); |
623 | data = cpu_to_be16(arizona->dac_comp_coeff); | 623 | put_unaligned_be16(arizona->dac_comp_coeff, |
624 | memcpy(ucontrol->value.bytes.data, &data, sizeof(data)); | 624 | ucontrol->value.bytes.data); |
625 | mutex_unlock(&arizona->dac_comp_lock); | 625 | mutex_unlock(&arizona->dac_comp_lock); |
626 | 626 | ||
627 | return 0; | 627 | return 0; |
@@ -1272,19 +1272,24 @@ SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | |||
1272 | 1272 | ||
1273 | SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, | 1273 | SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, |
1274 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, | 1274 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, |
1275 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 1275 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
1276 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
1276 | SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, | 1277 | SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, |
1277 | ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, | 1278 | ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, |
1278 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 1279 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
1280 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
1279 | SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, | 1281 | SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, |
1280 | ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 1282 | ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
1281 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 1283 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
1284 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
1282 | SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, | 1285 | SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, |
1283 | ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 1286 | ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
1284 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 1287 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
1288 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
1285 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, | 1289 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, |
1286 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 1290 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
1287 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 1291 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
1292 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
1288 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, | 1293 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, |
1289 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 1294 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
1290 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 1295 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 4456b38a3ef5..fbaeddb3e903 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -134,7 +134,7 @@ static const struct reg_default wm5110_sysclk_revd_patch[] = { | |||
134 | static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, | 134 | static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, |
135 | struct snd_kcontrol *kcontrol, int event) | 135 | struct snd_kcontrol *kcontrol, int event) |
136 | { | 136 | { |
137 | struct snd_soc_codec *codec = w->codec; | 137 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
138 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 138 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
139 | struct regmap *regmap = arizona->regmap; | 139 | struct regmap *regmap = arizona->regmap; |
140 | const struct reg_default *patch = NULL; | 140 | const struct reg_default *patch = NULL; |
@@ -905,22 +905,28 @@ SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | |||
905 | 905 | ||
906 | SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, | 906 | SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, |
907 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, | 907 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, |
908 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 908 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
909 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
909 | SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, | 910 | SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, |
910 | ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, | 911 | ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, |
911 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 912 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
913 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
912 | SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, | 914 | SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, |
913 | ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 915 | ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
914 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 916 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
917 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
915 | SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, | 918 | SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, |
916 | ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 919 | ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
917 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 920 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
921 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
918 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, | 922 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, |
919 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 923 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
920 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 924 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
925 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
921 | SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1, | 926 | SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1, |
922 | ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 927 | ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
923 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 928 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
929 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
924 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, | 930 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, |
925 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 931 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
926 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 932 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 574579b98872..c81a9eab3e3e 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -259,7 +259,7 @@ static void wm8350_pga_work(struct work_struct *work) | |||
259 | static int pga_event(struct snd_soc_dapm_widget *w, | 259 | static int pga_event(struct snd_soc_dapm_widget *w, |
260 | struct snd_kcontrol *kcontrol, int event) | 260 | struct snd_kcontrol *kcontrol, int event) |
261 | { | 261 | { |
262 | struct snd_soc_codec *codec = w->codec; | 262 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
263 | struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); | 263 | struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); |
264 | struct wm8350_output *out; | 264 | struct wm8350_output *out; |
265 | 265 | ||
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 8ee446987aa9..b0d84e552fca 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -324,6 +324,7 @@ SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, | |||
324 | static int outmixer_event (struct snd_soc_dapm_widget *w, | 324 | static int outmixer_event (struct snd_soc_dapm_widget *w, |
325 | struct snd_kcontrol * kcontrol, int event) | 325 | struct snd_kcontrol * kcontrol, int event) |
326 | { | 326 | { |
327 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
327 | struct soc_mixer_control *mc = | 328 | struct soc_mixer_control *mc = |
328 | (struct soc_mixer_control *)kcontrol->private_value; | 329 | (struct soc_mixer_control *)kcontrol->private_value; |
329 | u32 reg_shift = mc->shift; | 330 | u32 reg_shift = mc->shift; |
@@ -332,7 +333,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, | |||
332 | 333 | ||
333 | switch (reg_shift) { | 334 | switch (reg_shift) { |
334 | case WM8400_SPEAKER_MIXER | (WM8400_LDSPK << 8) : | 335 | case WM8400_SPEAKER_MIXER | (WM8400_LDSPK << 8) : |
335 | reg = snd_soc_read(w->codec, WM8400_OUTPUT_MIXER1); | 336 | reg = snd_soc_read(codec, WM8400_OUTPUT_MIXER1); |
336 | if (reg & WM8400_LDLO) { | 337 | if (reg & WM8400_LDLO) { |
337 | printk(KERN_WARNING | 338 | printk(KERN_WARNING |
338 | "Cannot set as Output Mixer 1 LDLO Set\n"); | 339 | "Cannot set as Output Mixer 1 LDLO Set\n"); |
@@ -340,7 +341,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, | |||
340 | } | 341 | } |
341 | break; | 342 | break; |
342 | case WM8400_SPEAKER_MIXER | (WM8400_RDSPK << 8): | 343 | case WM8400_SPEAKER_MIXER | (WM8400_RDSPK << 8): |
343 | reg = snd_soc_read(w->codec, WM8400_OUTPUT_MIXER2); | 344 | reg = snd_soc_read(codec, WM8400_OUTPUT_MIXER2); |
344 | if (reg & WM8400_RDRO) { | 345 | if (reg & WM8400_RDRO) { |
345 | printk(KERN_WARNING | 346 | printk(KERN_WARNING |
346 | "Cannot set as Output Mixer 2 RDRO Set\n"); | 347 | "Cannot set as Output Mixer 2 RDRO Set\n"); |
@@ -348,7 +349,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, | |||
348 | } | 349 | } |
349 | break; | 350 | break; |
350 | case WM8400_OUTPUT_MIXER1 | (WM8400_LDLO << 8): | 351 | case WM8400_OUTPUT_MIXER1 | (WM8400_LDLO << 8): |
351 | reg = snd_soc_read(w->codec, WM8400_SPEAKER_MIXER); | 352 | reg = snd_soc_read(codec, WM8400_SPEAKER_MIXER); |
352 | if (reg & WM8400_LDSPK) { | 353 | if (reg & WM8400_LDSPK) { |
353 | printk(KERN_WARNING | 354 | printk(KERN_WARNING |
354 | "Cannot set as Speaker Mixer LDSPK Set\n"); | 355 | "Cannot set as Speaker Mixer LDSPK Set\n"); |
@@ -356,7 +357,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, | |||
356 | } | 357 | } |
357 | break; | 358 | break; |
358 | case WM8400_OUTPUT_MIXER2 | (WM8400_RDRO << 8): | 359 | case WM8400_OUTPUT_MIXER2 | (WM8400_RDRO << 8): |
359 | reg = snd_soc_read(w->codec, WM8400_SPEAKER_MIXER); | 360 | reg = snd_soc_read(codec, WM8400_SPEAKER_MIXER); |
360 | if (reg & WM8400_RDSPK) { | 361 | if (reg & WM8400_RDSPK) { |
361 | printk(KERN_WARNING | 362 | printk(KERN_WARNING |
362 | "Cannot set as Speaker Mixer RDSPK Set\n"); | 363 | "Cannot set as Speaker Mixer RDSPK Set\n"); |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index b115ed815db9..098c143f44d6 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -217,7 +217,8 @@ SND_SOC_DAPM_INPUT("LLINEIN"), | |||
217 | static int wm8731_check_osc(struct snd_soc_dapm_widget *source, | 217 | static int wm8731_check_osc(struct snd_soc_dapm_widget *source, |
218 | struct snd_soc_dapm_widget *sink) | 218 | struct snd_soc_dapm_widget *sink) |
219 | { | 219 | { |
220 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(source->codec); | 220 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
221 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | ||
221 | 222 | ||
222 | return wm8731->sysclk_type == WM8731_SYSCLK_XTAL; | 223 | return wm8731->sysclk_type == WM8731_SYSCLK_XTAL; |
223 | } | 224 | } |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index f6847fdd6ddd..eb0a1644ba11 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -323,7 +323,7 @@ static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = { | |||
323 | SND_SOC_DAPM_OUTPUT("ROUT2"), | 323 | SND_SOC_DAPM_OUTPUT("ROUT2"), |
324 | SND_SOC_DAPM_OUTPUT("MONO1"), | 324 | SND_SOC_DAPM_OUTPUT("MONO1"), |
325 | SND_SOC_DAPM_OUTPUT("OUT3"), | 325 | SND_SOC_DAPM_OUTPUT("OUT3"), |
326 | SND_SOC_DAPM_OUTPUT("VREF"), | 326 | SND_SOC_DAPM_VMID("VREF"), |
327 | 327 | ||
328 | SND_SOC_DAPM_INPUT("LINPUT1"), | 328 | SND_SOC_DAPM_INPUT("LINPUT1"), |
329 | SND_SOC_DAPM_INPUT("LINPUT2"), | 329 | SND_SOC_DAPM_INPUT("LINPUT2"), |
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 180e7a098726..53e977da2f86 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c | |||
@@ -308,9 +308,7 @@ static const struct snd_soc_dapm_route wm8770_intercon[] = { | |||
308 | static int vout12supply_event(struct snd_soc_dapm_widget *w, | 308 | static int vout12supply_event(struct snd_soc_dapm_widget *w, |
309 | struct snd_kcontrol *kcontrol, int event) | 309 | struct snd_kcontrol *kcontrol, int event) |
310 | { | 310 | { |
311 | struct snd_soc_codec *codec; | 311 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
312 | |||
313 | codec = w->codec; | ||
314 | 312 | ||
315 | switch (event) { | 313 | switch (event) { |
316 | case SND_SOC_DAPM_PRE_PMU: | 314 | case SND_SOC_DAPM_PRE_PMU: |
@@ -327,9 +325,7 @@ static int vout12supply_event(struct snd_soc_dapm_widget *w, | |||
327 | static int vout34supply_event(struct snd_soc_dapm_widget *w, | 325 | static int vout34supply_event(struct snd_soc_dapm_widget *w, |
328 | struct snd_kcontrol *kcontrol, int event) | 326 | struct snd_kcontrol *kcontrol, int event) |
329 | { | 327 | { |
330 | struct snd_soc_codec *codec; | 328 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
331 | |||
332 | codec = w->codec; | ||
333 | 329 | ||
334 | switch (event) { | 330 | switch (event) { |
335 | case SND_SOC_DAPM_PRE_PMU: | 331 | case SND_SOC_DAPM_PRE_PMU: |
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 1315f7642503..b2b0e68f707e 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -648,7 +648,7 @@ static struct snd_soc_dai_driver wm8804_dai = { | |||
648 | .symmetric_rates = 1 | 648 | .symmetric_rates = 1 |
649 | }; | 649 | }; |
650 | 650 | ||
651 | static struct snd_soc_codec_driver soc_codec_dev_wm8804 = { | 651 | static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { |
652 | .probe = wm8804_probe, | 652 | .probe = wm8804_probe, |
653 | .remove = wm8804_remove, | 653 | .remove = wm8804_remove, |
654 | .set_bias_level = wm8804_set_bias_level, | 654 | .set_bias_level = wm8804_set_bias_level, |
@@ -664,7 +664,7 @@ static const struct of_device_id wm8804_of_match[] = { | |||
664 | }; | 664 | }; |
665 | MODULE_DEVICE_TABLE(of, wm8804_of_match); | 665 | MODULE_DEVICE_TABLE(of, wm8804_of_match); |
666 | 666 | ||
667 | static struct regmap_config wm8804_regmap_config = { | 667 | static const struct regmap_config wm8804_regmap_config = { |
668 | .reg_bits = 8, | 668 | .reg_bits = 8, |
669 | .val_bits = 8, | 669 | .val_bits = 8, |
670 | 670 | ||
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 3a0d4b7d692f..2eb986c19b88 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -224,7 +224,7 @@ static void wm8900_reset(struct snd_soc_codec *codec) | |||
224 | static int wm8900_hp_event(struct snd_soc_dapm_widget *w, | 224 | static int wm8900_hp_event(struct snd_soc_dapm_widget *w, |
225 | struct snd_kcontrol *kcontrol, int event) | 225 | struct snd_kcontrol *kcontrol, int event) |
226 | { | 226 | { |
227 | struct snd_soc_codec *codec = w->codec; | 227 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
228 | u16 hpctl1 = snd_soc_read(codec, WM8900_REG_HPCTL1); | 228 | u16 hpctl1 = snd_soc_read(codec, WM8900_REG_HPCTL1); |
229 | 229 | ||
230 | switch (event) { | 230 | switch (event) { |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index cc6b0ef98a34..dde462c082be 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -260,7 +260,7 @@ static int wm8903_cp_event(struct snd_soc_dapm_widget *w, | |||
260 | static int wm8903_dcs_event(struct snd_soc_dapm_widget *w, | 260 | static int wm8903_dcs_event(struct snd_soc_dapm_widget *w, |
261 | struct snd_kcontrol *kcontrol, int event) | 261 | struct snd_kcontrol *kcontrol, int event) |
262 | { | 262 | { |
263 | struct snd_soc_codec *codec = w->codec; | 263 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
264 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 264 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
265 | 265 | ||
266 | switch (event) { | 266 | switch (event) { |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 75b87c5c0f04..d3b3f57668cc 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -673,7 +673,7 @@ static int cp_event(struct snd_soc_dapm_widget *w, | |||
673 | static int sysclk_event(struct snd_soc_dapm_widget *w, | 673 | static int sysclk_event(struct snd_soc_dapm_widget *w, |
674 | struct snd_kcontrol *kcontrol, int event) | 674 | struct snd_kcontrol *kcontrol, int event) |
675 | { | 675 | { |
676 | struct snd_soc_codec *codec = w->codec; | 676 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
677 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | 677 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
678 | 678 | ||
679 | switch (event) { | 679 | switch (event) { |
@@ -711,7 +711,7 @@ static int sysclk_event(struct snd_soc_dapm_widget *w, | |||
711 | static int out_pga_event(struct snd_soc_dapm_widget *w, | 711 | static int out_pga_event(struct snd_soc_dapm_widget *w, |
712 | struct snd_kcontrol *kcontrol, int event) | 712 | struct snd_kcontrol *kcontrol, int event) |
713 | { | 713 | { |
714 | struct snd_soc_codec *codec = w->codec; | 714 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
715 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | 715 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
716 | int reg, val; | 716 | int reg, val; |
717 | int dcs_mask; | 717 | int dcs_mask; |
@@ -2105,6 +2105,24 @@ static const struct regmap_config wm8904_regmap = { | |||
2105 | .num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults), | 2105 | .num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults), |
2106 | }; | 2106 | }; |
2107 | 2107 | ||
2108 | #ifdef CONFIG_OF | ||
2109 | static enum wm8904_type wm8904_data = WM8904; | ||
2110 | static enum wm8904_type wm8912_data = WM8912; | ||
2111 | |||
2112 | static const struct of_device_id wm8904_of_match[] = { | ||
2113 | { | ||
2114 | .compatible = "wlf,wm8904", | ||
2115 | .data = &wm8904_data, | ||
2116 | }, { | ||
2117 | .compatible = "wlf,wm8912", | ||
2118 | .data = &wm8912_data, | ||
2119 | }, { | ||
2120 | /* sentinel */ | ||
2121 | } | ||
2122 | }; | ||
2123 | MODULE_DEVICE_TABLE(of, wm8904_of_match); | ||
2124 | #endif | ||
2125 | |||
2108 | static int wm8904_i2c_probe(struct i2c_client *i2c, | 2126 | static int wm8904_i2c_probe(struct i2c_client *i2c, |
2109 | const struct i2c_device_id *id) | 2127 | const struct i2c_device_id *id) |
2110 | { | 2128 | { |
@@ -2132,7 +2150,17 @@ static int wm8904_i2c_probe(struct i2c_client *i2c, | |||
2132 | return ret; | 2150 | return ret; |
2133 | } | 2151 | } |
2134 | 2152 | ||
2135 | wm8904->devtype = id->driver_data; | 2153 | if (i2c->dev.of_node) { |
2154 | const struct of_device_id *match; | ||
2155 | |||
2156 | match = of_match_node(wm8904_of_match, i2c->dev.of_node); | ||
2157 | if (match == NULL) | ||
2158 | return -EINVAL; | ||
2159 | wm8904->devtype = *((enum wm8904_type *)match->data); | ||
2160 | } else { | ||
2161 | wm8904->devtype = id->driver_data; | ||
2162 | } | ||
2163 | |||
2136 | i2c_set_clientdata(i2c, wm8904); | 2164 | i2c_set_clientdata(i2c, wm8904); |
2137 | wm8904->pdata = i2c->dev.platform_data; | 2165 | wm8904->pdata = i2c->dev.platform_data; |
2138 | 2166 | ||
@@ -2266,6 +2294,7 @@ static struct i2c_driver wm8904_i2c_driver = { | |||
2266 | .driver = { | 2294 | .driver = { |
2267 | .name = "wm8904", | 2295 | .name = "wm8904", |
2268 | .owner = THIS_MODULE, | 2296 | .owner = THIS_MODULE, |
2297 | .of_match_table = of_match_ptr(wm8904_of_match), | ||
2269 | }, | 2298 | }, |
2270 | .probe = wm8904_i2c_probe, | 2299 | .probe = wm8904_i2c_probe, |
2271 | .remove = wm8904_i2c_remove, | 2300 | .remove = wm8904_i2c_remove, |
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 1173f7fef5a7..1ab2d462afad 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -333,7 +333,7 @@ static int wm8955_configure_clocking(struct snd_soc_codec *codec) | |||
333 | static int wm8955_sysclk(struct snd_soc_dapm_widget *w, | 333 | static int wm8955_sysclk(struct snd_soc_dapm_widget *w, |
334 | struct snd_kcontrol *kcontrol, int event) | 334 | struct snd_kcontrol *kcontrol, int event) |
335 | { | 335 | { |
336 | struct snd_soc_codec *codec = w->codec; | 336 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
337 | int ret = 0; | 337 | int ret = 0; |
338 | 338 | ||
339 | /* Always disable the clocks - if we're doing reconfiguration this | 339 | /* Always disable the clocks - if we're doing reconfiguration this |
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 3cbc82b33292..c799cca5abeb 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c | |||
@@ -418,7 +418,7 @@ static void wm8958_dsp_apply(struct snd_soc_codec *codec, int path, int start) | |||
418 | int wm8958_aif_ev(struct snd_soc_dapm_widget *w, | 418 | int wm8958_aif_ev(struct snd_soc_dapm_widget *w, |
419 | struct snd_kcontrol *kcontrol, int event) | 419 | struct snd_kcontrol *kcontrol, int event) |
420 | { | 420 | { |
421 | struct snd_soc_codec *codec = w->codec; | 421 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
422 | int i; | 422 | int i; |
423 | 423 | ||
424 | switch (event) { | 424 | switch (event) { |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index a96eb497a379..cf8fecf97f2c 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/clk.h> | ||
18 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
@@ -117,6 +118,7 @@ static bool wm8960_volatile(struct device *dev, unsigned int reg) | |||
117 | } | 118 | } |
118 | 119 | ||
119 | struct wm8960_priv { | 120 | struct wm8960_priv { |
121 | struct clk *mclk; | ||
120 | struct regmap *regmap; | 122 | struct regmap *regmap; |
121 | int (*set_bias_level)(struct snd_soc_codec *, | 123 | int (*set_bias_level)(struct snd_soc_codec *, |
122 | enum snd_soc_bias_level level); | 124 | enum snd_soc_bias_level level); |
@@ -618,14 +620,38 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, | |||
618 | enum snd_soc_bias_level level) | 620 | enum snd_soc_bias_level level) |
619 | { | 621 | { |
620 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 622 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
623 | int ret; | ||
621 | 624 | ||
622 | switch (level) { | 625 | switch (level) { |
623 | case SND_SOC_BIAS_ON: | 626 | case SND_SOC_BIAS_ON: |
624 | break; | 627 | break; |
625 | 628 | ||
626 | case SND_SOC_BIAS_PREPARE: | 629 | case SND_SOC_BIAS_PREPARE: |
627 | /* Set VMID to 2x50k */ | 630 | switch (codec->dapm.bias_level) { |
628 | snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80); | 631 | case SND_SOC_BIAS_STANDBY: |
632 | if (!IS_ERR(wm8960->mclk)) { | ||
633 | ret = clk_prepare_enable(wm8960->mclk); | ||
634 | if (ret) { | ||
635 | dev_err(codec->dev, | ||
636 | "Failed to enable MCLK: %d\n", | ||
637 | ret); | ||
638 | return ret; | ||
639 | } | ||
640 | } | ||
641 | |||
642 | /* Set VMID to 2x50k */ | ||
643 | snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80); | ||
644 | break; | ||
645 | |||
646 | case SND_SOC_BIAS_ON: | ||
647 | if (!IS_ERR(wm8960->mclk)) | ||
648 | clk_disable_unprepare(wm8960->mclk); | ||
649 | break; | ||
650 | |||
651 | default: | ||
652 | break; | ||
653 | } | ||
654 | |||
629 | break; | 655 | break; |
630 | 656 | ||
631 | case SND_SOC_BIAS_STANDBY: | 657 | case SND_SOC_BIAS_STANDBY: |
@@ -674,7 +700,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | |||
674 | enum snd_soc_bias_level level) | 700 | enum snd_soc_bias_level level) |
675 | { | 701 | { |
676 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 702 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
677 | int reg; | 703 | int reg, ret; |
678 | 704 | ||
679 | switch (level) { | 705 | switch (level) { |
680 | case SND_SOC_BIAS_ON: | 706 | case SND_SOC_BIAS_ON: |
@@ -715,9 +741,22 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | |||
715 | WM8960_VREF, WM8960_VREF); | 741 | WM8960_VREF, WM8960_VREF); |
716 | 742 | ||
717 | msleep(100); | 743 | msleep(100); |
744 | |||
745 | if (!IS_ERR(wm8960->mclk)) { | ||
746 | ret = clk_prepare_enable(wm8960->mclk); | ||
747 | if (ret) { | ||
748 | dev_err(codec->dev, | ||
749 | "Failed to enable MCLK: %d\n", | ||
750 | ret); | ||
751 | return ret; | ||
752 | } | ||
753 | } | ||
718 | break; | 754 | break; |
719 | 755 | ||
720 | case SND_SOC_BIAS_ON: | 756 | case SND_SOC_BIAS_ON: |
757 | if (!IS_ERR(wm8960->mclk)) | ||
758 | clk_disable_unprepare(wm8960->mclk); | ||
759 | |||
721 | /* Enable anti-pop mode */ | 760 | /* Enable anti-pop mode */ |
722 | snd_soc_update_bits(codec, WM8960_APOP1, | 761 | snd_soc_update_bits(codec, WM8960_APOP1, |
723 | WM8960_POBCTRL | WM8960_SOFT_ST | | 762 | WM8960_POBCTRL | WM8960_SOFT_ST | |
@@ -1002,6 +1041,12 @@ static int wm8960_i2c_probe(struct i2c_client *i2c, | |||
1002 | if (wm8960 == NULL) | 1041 | if (wm8960 == NULL) |
1003 | return -ENOMEM; | 1042 | return -ENOMEM; |
1004 | 1043 | ||
1044 | wm8960->mclk = devm_clk_get(&i2c->dev, "mclk"); | ||
1045 | if (IS_ERR(wm8960->mclk)) { | ||
1046 | if (PTR_ERR(wm8960->mclk) == -EPROBE_DEFER) | ||
1047 | return -EPROBE_DEFER; | ||
1048 | } | ||
1049 | |||
1005 | wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap); | 1050 | wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap); |
1006 | if (IS_ERR(wm8960->regmap)) | 1051 | if (IS_ERR(wm8960->regmap)) |
1007 | return PTR_ERR(wm8960->regmap); | 1052 | return PTR_ERR(wm8960->regmap); |
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index eeffd05384b4..95e2c1bfc809 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -194,7 +194,7 @@ static bool wm8961_readable(struct device *dev, unsigned int reg) | |||
194 | static int wm8961_hp_event(struct snd_soc_dapm_widget *w, | 194 | static int wm8961_hp_event(struct snd_soc_dapm_widget *w, |
195 | struct snd_kcontrol *kcontrol, int event) | 195 | struct snd_kcontrol *kcontrol, int event) |
196 | { | 196 | { |
197 | struct snd_soc_codec *codec = w->codec; | 197 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
198 | u16 hp_reg = snd_soc_read(codec, WM8961_ANALOGUE_HP_0); | 198 | u16 hp_reg = snd_soc_read(codec, WM8961_ANALOGUE_HP_0); |
199 | u16 cp_reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_1); | 199 | u16 cp_reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_1); |
200 | u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2); | 200 | u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2); |
@@ -286,7 +286,7 @@ static int wm8961_hp_event(struct snd_soc_dapm_widget *w, | |||
286 | static int wm8961_spk_event(struct snd_soc_dapm_widget *w, | 286 | static int wm8961_spk_event(struct snd_soc_dapm_widget *w, |
287 | struct snd_kcontrol *kcontrol, int event) | 287 | struct snd_kcontrol *kcontrol, int event) |
288 | { | 288 | { |
289 | struct snd_soc_codec *codec = w->codec; | 289 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
290 | u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2); | 290 | u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2); |
291 | u16 spk_reg = snd_soc_read(codec, WM8961_CLASS_D_CONTROL_1); | 291 | u16 spk_reg = snd_soc_read(codec, WM8961_CLASS_D_CONTROL_1); |
292 | 292 | ||
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index d32d554f5b34..118b0034ba23 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -1866,7 +1866,7 @@ static int cp_event(struct snd_soc_dapm_widget *w, | |||
1866 | static int hp_event(struct snd_soc_dapm_widget *w, | 1866 | static int hp_event(struct snd_soc_dapm_widget *w, |
1867 | struct snd_kcontrol *kcontrol, int event) | 1867 | struct snd_kcontrol *kcontrol, int event) |
1868 | { | 1868 | { |
1869 | struct snd_soc_codec *codec = w->codec; | 1869 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1870 | int timeout; | 1870 | int timeout; |
1871 | int reg; | 1871 | int reg; |
1872 | int expected = (WM8962_DCS_STARTUP_DONE_HP1L | | 1872 | int expected = (WM8962_DCS_STARTUP_DONE_HP1L | |
@@ -1960,7 +1960,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, | |||
1960 | static int out_pga_event(struct snd_soc_dapm_widget *w, | 1960 | static int out_pga_event(struct snd_soc_dapm_widget *w, |
1961 | struct snd_kcontrol *kcontrol, int event) | 1961 | struct snd_kcontrol *kcontrol, int event) |
1962 | { | 1962 | { |
1963 | struct snd_soc_codec *codec = w->codec; | 1963 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1964 | int reg; | 1964 | int reg; |
1965 | 1965 | ||
1966 | switch (w->shift) { | 1966 | switch (w->shift) { |
@@ -1993,7 +1993,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, | |||
1993 | static int dsp2_event(struct snd_soc_dapm_widget *w, | 1993 | static int dsp2_event(struct snd_soc_dapm_widget *w, |
1994 | struct snd_kcontrol *kcontrol, int event) | 1994 | struct snd_kcontrol *kcontrol, int event) |
1995 | { | 1995 | { |
1996 | struct snd_soc_codec *codec = w->codec; | 1996 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1997 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 1997 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
1998 | 1998 | ||
1999 | switch (event) { | 1999 | switch (event) { |
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index e418199155a8..24968aa8618a 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c | |||
@@ -244,7 +244,7 @@ SOC_DOUBLE_R_TLV("Output 2 Playback Volume", WM8988_LOUT2V, WM8988_ROUT2V, | |||
244 | static int wm8988_lrc_control(struct snd_soc_dapm_widget *w, | 244 | static int wm8988_lrc_control(struct snd_soc_dapm_widget *w, |
245 | struct snd_kcontrol *kcontrol, int event) | 245 | struct snd_kcontrol *kcontrol, int event) |
246 | { | 246 | { |
247 | struct snd_soc_codec *codec = w->codec; | 247 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
248 | u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2); | 248 | u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2); |
249 | 249 | ||
250 | /* Use the DAC to gate LRC if active, otherwise use ADC */ | 250 | /* Use the DAC to gate LRC if active, otherwise use ADC */ |
@@ -813,7 +813,7 @@ static int wm8988_probe(struct snd_soc_codec *codec) | |||
813 | return 0; | 813 | return 0; |
814 | } | 814 | } |
815 | 815 | ||
816 | static struct snd_soc_codec_driver soc_codec_dev_wm8988 = { | 816 | static const struct snd_soc_codec_driver soc_codec_dev_wm8988 = { |
817 | .probe = wm8988_probe, | 817 | .probe = wm8988_probe, |
818 | .set_bias_level = wm8988_set_bias_level, | 818 | .set_bias_level = wm8988_set_bias_level, |
819 | .suspend_bias_off = true, | 819 | .suspend_bias_off = true, |
@@ -826,7 +826,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8988 = { | |||
826 | .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes), | 826 | .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes), |
827 | }; | 827 | }; |
828 | 828 | ||
829 | static struct regmap_config wm8988_regmap = { | 829 | static const struct regmap_config wm8988_regmap = { |
830 | .reg_bits = 7, | 830 | .reg_bits = 7, |
831 | .val_bits = 9, | 831 | .val_bits = 9, |
832 | 832 | ||
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 8a584229310a..c93bffcb3cfb 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -374,13 +374,14 @@ SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME, | |||
374 | static int outmixer_event(struct snd_soc_dapm_widget *w, | 374 | static int outmixer_event(struct snd_soc_dapm_widget *w, |
375 | struct snd_kcontrol *kcontrol, int event) | 375 | struct snd_kcontrol *kcontrol, int event) |
376 | { | 376 | { |
377 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
377 | u32 reg_shift = kcontrol->private_value & 0xfff; | 378 | u32 reg_shift = kcontrol->private_value & 0xfff; |
378 | int ret = 0; | 379 | int ret = 0; |
379 | u16 reg; | 380 | u16 reg; |
380 | 381 | ||
381 | switch (reg_shift) { | 382 | switch (reg_shift) { |
382 | case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) : | 383 | case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) : |
383 | reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER1); | 384 | reg = snd_soc_read(codec, WM8990_OUTPUT_MIXER1); |
384 | if (reg & WM8990_LDLO) { | 385 | if (reg & WM8990_LDLO) { |
385 | printk(KERN_WARNING | 386 | printk(KERN_WARNING |
386 | "Cannot set as Output Mixer 1 LDLO Set\n"); | 387 | "Cannot set as Output Mixer 1 LDLO Set\n"); |
@@ -388,7 +389,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, | |||
388 | } | 389 | } |
389 | break; | 390 | break; |
390 | case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8): | 391 | case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8): |
391 | reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER2); | 392 | reg = snd_soc_read(codec, WM8990_OUTPUT_MIXER2); |
392 | if (reg & WM8990_RDRO) { | 393 | if (reg & WM8990_RDRO) { |
393 | printk(KERN_WARNING | 394 | printk(KERN_WARNING |
394 | "Cannot set as Output Mixer 2 RDRO Set\n"); | 395 | "Cannot set as Output Mixer 2 RDRO Set\n"); |
@@ -396,7 +397,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, | |||
396 | } | 397 | } |
397 | break; | 398 | break; |
398 | case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8): | 399 | case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8): |
399 | reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER); | 400 | reg = snd_soc_read(codec, WM8990_SPEAKER_MIXER); |
400 | if (reg & WM8990_LDSPK) { | 401 | if (reg & WM8990_LDSPK) { |
401 | printk(KERN_WARNING | 402 | printk(KERN_WARNING |
402 | "Cannot set as Speaker Mixer LDSPK Set\n"); | 403 | "Cannot set as Speaker Mixer LDSPK Set\n"); |
@@ -404,7 +405,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, | |||
404 | } | 405 | } |
405 | break; | 406 | break; |
406 | case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8): | 407 | case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8): |
407 | reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER); | 408 | reg = snd_soc_read(codec, WM8990_SPEAKER_MIXER); |
408 | if (reg & WM8990_RDSPK) { | 409 | if (reg & WM8990_RDSPK) { |
409 | printk(KERN_WARNING | 410 | printk(KERN_WARNING |
410 | "Cannot set as Speaker Mixer RDSPK Set\n"); | 411 | "Cannot set as Speaker Mixer RDSPK Set\n"); |
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index b0ac2c3e31b9..49df0dc607e6 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c | |||
@@ -382,13 +382,14 @@ static const struct snd_kcontrol_new wm8991_snd_controls[] = { | |||
382 | static int outmixer_event(struct snd_soc_dapm_widget *w, | 382 | static int outmixer_event(struct snd_soc_dapm_widget *w, |
383 | struct snd_kcontrol *kcontrol, int event) | 383 | struct snd_kcontrol *kcontrol, int event) |
384 | { | 384 | { |
385 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
385 | u32 reg_shift = kcontrol->private_value & 0xfff; | 386 | u32 reg_shift = kcontrol->private_value & 0xfff; |
386 | int ret = 0; | 387 | int ret = 0; |
387 | u16 reg; | 388 | u16 reg; |
388 | 389 | ||
389 | switch (reg_shift) { | 390 | switch (reg_shift) { |
390 | case WM8991_SPEAKER_MIXER | (WM8991_LDSPK_BIT << 8): | 391 | case WM8991_SPEAKER_MIXER | (WM8991_LDSPK_BIT << 8): |
391 | reg = snd_soc_read(w->codec, WM8991_OUTPUT_MIXER1); | 392 | reg = snd_soc_read(codec, WM8991_OUTPUT_MIXER1); |
392 | if (reg & WM8991_LDLO) { | 393 | if (reg & WM8991_LDLO) { |
393 | printk(KERN_WARNING | 394 | printk(KERN_WARNING |
394 | "Cannot set as Output Mixer 1 LDLO Set\n"); | 395 | "Cannot set as Output Mixer 1 LDLO Set\n"); |
@@ -397,7 +398,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, | |||
397 | break; | 398 | break; |
398 | 399 | ||
399 | case WM8991_SPEAKER_MIXER | (WM8991_RDSPK_BIT << 8): | 400 | case WM8991_SPEAKER_MIXER | (WM8991_RDSPK_BIT << 8): |
400 | reg = snd_soc_read(w->codec, WM8991_OUTPUT_MIXER2); | 401 | reg = snd_soc_read(codec, WM8991_OUTPUT_MIXER2); |
401 | if (reg & WM8991_RDRO) { | 402 | if (reg & WM8991_RDRO) { |
402 | printk(KERN_WARNING | 403 | printk(KERN_WARNING |
403 | "Cannot set as Output Mixer 2 RDRO Set\n"); | 404 | "Cannot set as Output Mixer 2 RDRO Set\n"); |
@@ -406,7 +407,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, | |||
406 | break; | 407 | break; |
407 | 408 | ||
408 | case WM8991_OUTPUT_MIXER1 | (WM8991_LDLO_BIT << 8): | 409 | case WM8991_OUTPUT_MIXER1 | (WM8991_LDLO_BIT << 8): |
409 | reg = snd_soc_read(w->codec, WM8991_SPEAKER_MIXER); | 410 | reg = snd_soc_read(codec, WM8991_SPEAKER_MIXER); |
410 | if (reg & WM8991_LDSPK) { | 411 | if (reg & WM8991_LDSPK) { |
411 | printk(KERN_WARNING | 412 | printk(KERN_WARNING |
412 | "Cannot set as Speaker Mixer LDSPK Set\n"); | 413 | "Cannot set as Speaker Mixer LDSPK Set\n"); |
@@ -415,7 +416,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, | |||
415 | break; | 416 | break; |
416 | 417 | ||
417 | case WM8991_OUTPUT_MIXER2 | (WM8991_RDRO_BIT << 8): | 418 | case WM8991_OUTPUT_MIXER2 | (WM8991_RDRO_BIT << 8): |
418 | reg = snd_soc_read(w->codec, WM8991_SPEAKER_MIXER); | 419 | reg = snd_soc_read(codec, WM8991_SPEAKER_MIXER); |
419 | if (reg & WM8991_RDSPK) { | 420 | if (reg & WM8991_RDSPK) { |
420 | printk(KERN_WARNING | 421 | printk(KERN_WARNING |
421 | "Cannot set as Speaker Mixer RDSPK Set\n"); | 422 | "Cannot set as Speaker Mixer RDSPK Set\n"); |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 53c6fe359496..2e70a270eb28 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -810,7 +810,7 @@ SOC_SINGLE_TLV("EQ5 Volume", WM8993_EQ6, 0, 24, 0, eq_tlv), | |||
810 | static int clk_sys_event(struct snd_soc_dapm_widget *w, | 810 | static int clk_sys_event(struct snd_soc_dapm_widget *w, |
811 | struct snd_kcontrol *kcontrol, int event) | 811 | struct snd_kcontrol *kcontrol, int event) |
812 | { | 812 | { |
813 | struct snd_soc_codec *codec = w->codec; | 813 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
814 | 814 | ||
815 | switch (event) { | 815 | switch (event) { |
816 | case SND_SOC_DAPM_PRE_PMU: | 816 | case SND_SOC_DAPM_PRE_PMU: |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 1b97de2e4e67..4fbc7689339a 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -249,7 +249,8 @@ static int configure_clock(struct snd_soc_codec *codec) | |||
249 | static int check_clk_sys(struct snd_soc_dapm_widget *source, | 249 | static int check_clk_sys(struct snd_soc_dapm_widget *source, |
250 | struct snd_soc_dapm_widget *sink) | 250 | struct snd_soc_dapm_widget *sink) |
251 | { | 251 | { |
252 | int reg = snd_soc_read(source->codec, WM8994_CLOCKING_1); | 252 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
253 | int reg = snd_soc_read(codec, WM8994_CLOCKING_1); | ||
253 | const char *clk; | 254 | const char *clk; |
254 | 255 | ||
255 | /* Check what we're currently using for CLK_SYS */ | 256 | /* Check what we're currently using for CLK_SYS */ |
@@ -806,7 +807,7 @@ static void active_dereference(struct snd_soc_codec *codec) | |||
806 | static int clk_sys_event(struct snd_soc_dapm_widget *w, | 807 | static int clk_sys_event(struct snd_soc_dapm_widget *w, |
807 | struct snd_kcontrol *kcontrol, int event) | 808 | struct snd_kcontrol *kcontrol, int event) |
808 | { | 809 | { |
809 | struct snd_soc_codec *codec = w->codec; | 810 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
810 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 811 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
811 | 812 | ||
812 | switch (event) { | 813 | switch (event) { |
@@ -981,7 +982,7 @@ static void vmid_dereference(struct snd_soc_codec *codec) | |||
981 | static int vmid_event(struct snd_soc_dapm_widget *w, | 982 | static int vmid_event(struct snd_soc_dapm_widget *w, |
982 | struct snd_kcontrol *kcontrol, int event) | 983 | struct snd_kcontrol *kcontrol, int event) |
983 | { | 984 | { |
984 | struct snd_soc_codec *codec = w->codec; | 985 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
985 | 986 | ||
986 | switch (event) { | 987 | switch (event) { |
987 | case SND_SOC_DAPM_PRE_PMU: | 988 | case SND_SOC_DAPM_PRE_PMU: |
@@ -1037,7 +1038,7 @@ static bool wm8994_check_class_w_digital(struct snd_soc_codec *codec) | |||
1037 | static int aif1clk_ev(struct snd_soc_dapm_widget *w, | 1038 | static int aif1clk_ev(struct snd_soc_dapm_widget *w, |
1038 | struct snd_kcontrol *kcontrol, int event) | 1039 | struct snd_kcontrol *kcontrol, int event) |
1039 | { | 1040 | { |
1040 | struct snd_soc_codec *codec = w->codec; | 1041 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1041 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1042 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
1042 | struct wm8994 *control = wm8994->wm8994; | 1043 | struct wm8994 *control = wm8994->wm8994; |
1043 | int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; | 1044 | int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; |
@@ -1135,7 +1136,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, | |||
1135 | static int aif2clk_ev(struct snd_soc_dapm_widget *w, | 1136 | static int aif2clk_ev(struct snd_soc_dapm_widget *w, |
1136 | struct snd_kcontrol *kcontrol, int event) | 1137 | struct snd_kcontrol *kcontrol, int event) |
1137 | { | 1138 | { |
1138 | struct snd_soc_codec *codec = w->codec; | 1139 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1139 | int i; | 1140 | int i; |
1140 | int dac; | 1141 | int dac; |
1141 | int adc; | 1142 | int adc; |
@@ -1220,7 +1221,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, | |||
1220 | static int aif1clk_late_ev(struct snd_soc_dapm_widget *w, | 1221 | static int aif1clk_late_ev(struct snd_soc_dapm_widget *w, |
1221 | struct snd_kcontrol *kcontrol, int event) | 1222 | struct snd_kcontrol *kcontrol, int event) |
1222 | { | 1223 | { |
1223 | struct snd_soc_codec *codec = w->codec; | 1224 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1224 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1225 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
1225 | 1226 | ||
1226 | switch (event) { | 1227 | switch (event) { |
@@ -1238,7 +1239,7 @@ static int aif1clk_late_ev(struct snd_soc_dapm_widget *w, | |||
1238 | static int aif2clk_late_ev(struct snd_soc_dapm_widget *w, | 1239 | static int aif2clk_late_ev(struct snd_soc_dapm_widget *w, |
1239 | struct snd_kcontrol *kcontrol, int event) | 1240 | struct snd_kcontrol *kcontrol, int event) |
1240 | { | 1241 | { |
1241 | struct snd_soc_codec *codec = w->codec; | 1242 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1242 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1243 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
1243 | 1244 | ||
1244 | switch (event) { | 1245 | switch (event) { |
@@ -1256,7 +1257,7 @@ static int aif2clk_late_ev(struct snd_soc_dapm_widget *w, | |||
1256 | static int late_enable_ev(struct snd_soc_dapm_widget *w, | 1257 | static int late_enable_ev(struct snd_soc_dapm_widget *w, |
1257 | struct snd_kcontrol *kcontrol, int event) | 1258 | struct snd_kcontrol *kcontrol, int event) |
1258 | { | 1259 | { |
1259 | struct snd_soc_codec *codec = w->codec; | 1260 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1260 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1261 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
1261 | 1262 | ||
1262 | switch (event) { | 1263 | switch (event) { |
@@ -1289,7 +1290,7 @@ static int late_enable_ev(struct snd_soc_dapm_widget *w, | |||
1289 | static int late_disable_ev(struct snd_soc_dapm_widget *w, | 1290 | static int late_disable_ev(struct snd_soc_dapm_widget *w, |
1290 | struct snd_kcontrol *kcontrol, int event) | 1291 | struct snd_kcontrol *kcontrol, int event) |
1291 | { | 1292 | { |
1292 | struct snd_soc_codec *codec = w->codec; | 1293 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1293 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1294 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
1294 | 1295 | ||
1295 | switch (event) { | 1296 | switch (event) { |
@@ -1331,7 +1332,7 @@ static int micbias_ev(struct snd_soc_dapm_widget *w, | |||
1331 | static int dac_ev(struct snd_soc_dapm_widget *w, | 1332 | static int dac_ev(struct snd_soc_dapm_widget *w, |
1332 | struct snd_kcontrol *kcontrol, int event) | 1333 | struct snd_kcontrol *kcontrol, int event) |
1333 | { | 1334 | { |
1334 | struct snd_soc_codec *codec = w->codec; | 1335 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1335 | unsigned int mask = 1 << w->shift; | 1336 | unsigned int mask = 1 << w->shift; |
1336 | 1337 | ||
1337 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, | 1338 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, |
@@ -1372,7 +1373,7 @@ SOC_DAPM_SINGLE("DAC1 Switch", WM8994_SPEAKER_MIXER, 0, 1, 0), | |||
1372 | static int post_ev(struct snd_soc_dapm_widget *w, | 1373 | static int post_ev(struct snd_soc_dapm_widget *w, |
1373 | struct snd_kcontrol *kcontrol, int event) | 1374 | struct snd_kcontrol *kcontrol, int event) |
1374 | { | 1375 | { |
1375 | struct snd_soc_codec *codec = w->codec; | 1376 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1376 | dev_dbg(codec->dev, "SRC status: %x\n", | 1377 | dev_dbg(codec->dev, "SRC status: %x\n", |
1377 | snd_soc_read(codec, | 1378 | snd_soc_read(codec, |
1378 | WM8994_RATE_STATUS)); | 1379 | WM8994_RATE_STATUS)); |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index c280f0a3a424..66103c2b012e 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -44,7 +44,7 @@ static const char *wm8995_supply_names[WM8995_NUM_SUPPLIES] = { | |||
44 | "MICVDD" | 44 | "MICVDD" |
45 | }; | 45 | }; |
46 | 46 | ||
47 | static struct reg_default wm8995_reg_defaults[] = { | 47 | static const struct reg_default wm8995_reg_defaults[] = { |
48 | { 0, 0x8995 }, | 48 | { 0, 0x8995 }, |
49 | { 5, 0x0100 }, | 49 | { 5, 0x0100 }, |
50 | { 16, 0x000b }, | 50 | { 16, 0x000b }, |
@@ -534,10 +534,11 @@ static void wm8995_update_class_w(struct snd_soc_codec *codec) | |||
534 | static int check_clk_sys(struct snd_soc_dapm_widget *source, | 534 | static int check_clk_sys(struct snd_soc_dapm_widget *source, |
535 | struct snd_soc_dapm_widget *sink) | 535 | struct snd_soc_dapm_widget *sink) |
536 | { | 536 | { |
537 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); | ||
537 | unsigned int reg; | 538 | unsigned int reg; |
538 | const char *clk; | 539 | const char *clk; |
539 | 540 | ||
540 | reg = snd_soc_read(source->codec, WM8995_CLOCKING_1); | 541 | reg = snd_soc_read(codec, WM8995_CLOCKING_1); |
541 | /* Check what we're currently using for CLK_SYS */ | 542 | /* Check what we're currently using for CLK_SYS */ |
542 | if (reg & WM8995_SYSCLK_SRC) | 543 | if (reg & WM8995_SYSCLK_SRC) |
543 | clk = "AIF2CLK"; | 544 | clk = "AIF2CLK"; |
@@ -560,9 +561,7 @@ static int wm8995_put_class_w(struct snd_kcontrol *kcontrol, | |||
560 | static int hp_supply_event(struct snd_soc_dapm_widget *w, | 561 | static int hp_supply_event(struct snd_soc_dapm_widget *w, |
561 | struct snd_kcontrol *kcontrol, int event) | 562 | struct snd_kcontrol *kcontrol, int event) |
562 | { | 563 | { |
563 | struct snd_soc_codec *codec; | 564 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
564 | |||
565 | codec = w->codec; | ||
566 | 565 | ||
567 | switch (event) { | 566 | switch (event) { |
568 | case SND_SOC_DAPM_PRE_PMU: | 567 | case SND_SOC_DAPM_PRE_PMU: |
@@ -611,10 +610,9 @@ static void dc_servo_cmd(struct snd_soc_codec *codec, | |||
611 | static int hp_event(struct snd_soc_dapm_widget *w, | 610 | static int hp_event(struct snd_soc_dapm_widget *w, |
612 | struct snd_kcontrol *kcontrol, int event) | 611 | struct snd_kcontrol *kcontrol, int event) |
613 | { | 612 | { |
614 | struct snd_soc_codec *codec; | 613 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
615 | unsigned int reg; | 614 | unsigned int reg; |
616 | 615 | ||
617 | codec = w->codec; | ||
618 | reg = snd_soc_read(codec, WM8995_ANALOGUE_HP_1); | 616 | reg = snd_soc_read(codec, WM8995_ANALOGUE_HP_1); |
619 | 617 | ||
620 | switch (event) { | 618 | switch (event) { |
@@ -761,9 +759,7 @@ static int configure_clock(struct snd_soc_codec *codec) | |||
761 | static int clk_sys_event(struct snd_soc_dapm_widget *w, | 759 | static int clk_sys_event(struct snd_soc_dapm_widget *w, |
762 | struct snd_kcontrol *kcontrol, int event) | 760 | struct snd_kcontrol *kcontrol, int event) |
763 | { | 761 | { |
764 | struct snd_soc_codec *codec; | 762 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
765 | |||
766 | codec = w->codec; | ||
767 | 763 | ||
768 | switch (event) { | 764 | switch (event) { |
769 | case SND_SOC_DAPM_PRE_PMU: | 765 | case SND_SOC_DAPM_PRE_PMU: |
@@ -2190,7 +2186,7 @@ static struct snd_soc_dai_driver wm8995_dai[] = { | |||
2190 | } | 2186 | } |
2191 | }; | 2187 | }; |
2192 | 2188 | ||
2193 | static struct snd_soc_codec_driver soc_codec_dev_wm8995 = { | 2189 | static const struct snd_soc_codec_driver soc_codec_dev_wm8995 = { |
2194 | .probe = wm8995_probe, | 2190 | .probe = wm8995_probe, |
2195 | .remove = wm8995_remove, | 2191 | .remove = wm8995_remove, |
2196 | .set_bias_level = wm8995_set_bias_level, | 2192 | .set_bias_level = wm8995_set_bias_level, |
@@ -2204,7 +2200,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8995 = { | |||
2204 | .num_dapm_routes = ARRAY_SIZE(wm8995_intercon), | 2200 | .num_dapm_routes = ARRAY_SIZE(wm8995_intercon), |
2205 | }; | 2201 | }; |
2206 | 2202 | ||
2207 | static struct regmap_config wm8995_regmap = { | 2203 | static const struct regmap_config wm8995_regmap = { |
2208 | .reg_bits = 16, | 2204 | .reg_bits = 16, |
2209 | .val_bits = 16, | 2205 | .val_bits = 16, |
2210 | 2206 | ||
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index b1dcc11c1b23..dc92d5e4e942 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -599,7 +599,7 @@ static void wm8996_bg_disable(struct snd_soc_codec *codec) | |||
599 | static int bg_event(struct snd_soc_dapm_widget *w, | 599 | static int bg_event(struct snd_soc_dapm_widget *w, |
600 | struct snd_kcontrol *kcontrol, int event) | 600 | struct snd_kcontrol *kcontrol, int event) |
601 | { | 601 | { |
602 | struct snd_soc_codec *codec = w->codec; | 602 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
603 | int ret = 0; | 603 | int ret = 0; |
604 | 604 | ||
605 | switch (event) { | 605 | switch (event) { |
@@ -634,7 +634,8 @@ static int cp_event(struct snd_soc_dapm_widget *w, | |||
634 | static int rmv_short_event(struct snd_soc_dapm_widget *w, | 634 | static int rmv_short_event(struct snd_soc_dapm_widget *w, |
635 | struct snd_kcontrol *kcontrol, int event) | 635 | struct snd_kcontrol *kcontrol, int event) |
636 | { | 636 | { |
637 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(w->codec); | 637 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
638 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
638 | 639 | ||
639 | /* Record which outputs we enabled */ | 640 | /* Record which outputs we enabled */ |
640 | switch (event) { | 641 | switch (event) { |
@@ -758,7 +759,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm, | |||
758 | static int dcs_start(struct snd_soc_dapm_widget *w, | 759 | static int dcs_start(struct snd_soc_dapm_widget *w, |
759 | struct snd_kcontrol *kcontrol, int event) | 760 | struct snd_kcontrol *kcontrol, int event) |
760 | { | 761 | { |
761 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(w->codec); | 762 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
763 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
762 | 764 | ||
763 | switch (event) { | 765 | switch (event) { |
764 | case SND_SOC_DAPM_POST_PMU: | 766 | case SND_SOC_DAPM_POST_PMU: |
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 7e8bfe27566b..a4d11770630c 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c | |||
@@ -84,7 +84,7 @@ static const struct reg_default wm8997_sysclk_reva_patch[] = { | |||
84 | static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w, | 84 | static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w, |
85 | struct snd_kcontrol *kcontrol, int event) | 85 | struct snd_kcontrol *kcontrol, int event) |
86 | { | 86 | { |
87 | struct snd_soc_codec *codec = w->codec; | 87 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
88 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 88 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
89 | struct regmap *regmap = arizona->regmap; | 89 | struct regmap *regmap = arizona->regmap; |
90 | const struct reg_default *patch = NULL; | 90 | const struct reg_default *patch = NULL; |
@@ -610,13 +610,16 @@ SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | |||
610 | 610 | ||
611 | SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, | 611 | SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM, |
612 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, | 612 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, |
613 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 613 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
614 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
614 | SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, | 615 | SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM, |
615 | ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, | 616 | ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev, |
616 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 617 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
618 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
617 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, | 619 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, |
618 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 620 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
619 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 621 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD | |
622 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), | ||
620 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, | 623 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, |
621 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 624 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
622 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 625 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index b1d946facd57..13a3f335ea5b 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -734,7 +734,7 @@ static int configure_clock(struct snd_soc_codec *codec) | |||
734 | static int clk_sys_event(struct snd_soc_dapm_widget *w, | 734 | static int clk_sys_event(struct snd_soc_dapm_widget *w, |
735 | struct snd_kcontrol *kcontrol, int event) | 735 | struct snd_kcontrol *kcontrol, int event) |
736 | { | 736 | { |
737 | struct snd_soc_codec *codec = w->codec; | 737 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
738 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); | 738 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); |
739 | 739 | ||
740 | /* This should be done on init() for bypass paths */ | 740 | /* This should be done on init() for bypass paths */ |
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 6ffe8dc4f3fa..60d243c904f5 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -254,7 +254,7 @@ SOC_SINGLE_TLV("MIXOUTR IN2B Volume", WM9090_OUTPUT_MIXER4, 0, 3, 1, | |||
254 | static int hp_ev(struct snd_soc_dapm_widget *w, | 254 | static int hp_ev(struct snd_soc_dapm_widget *w, |
255 | struct snd_kcontrol *kcontrol, int event) | 255 | struct snd_kcontrol *kcontrol, int event) |
256 | { | 256 | { |
257 | struct snd_soc_codec *codec = w->codec; | 257 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
258 | unsigned int reg = snd_soc_read(codec, WM9090_ANALOGUE_HP_0); | 258 | unsigned int reg = snd_soc_read(codec, WM9090_ANALOGUE_HP_0); |
259 | 259 | ||
260 | switch (event) { | 260 | switch (event) { |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 6ab1122a3872..68222917b396 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -217,7 +217,7 @@ SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), | |||
217 | static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w, | 217 | static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w, |
218 | struct snd_kcontrol *kcontrol, int event) | 218 | struct snd_kcontrol *kcontrol, int event) |
219 | { | 219 | { |
220 | struct snd_soc_codec *codec = w->codec; | 220 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
221 | u16 status, rate; | 221 | u16 status, rate; |
222 | 222 | ||
223 | if (WARN_ON(event != SND_SOC_DAPM_PRE_PMD)) | 223 | if (WARN_ON(event != SND_SOC_DAPM_PRE_PMD)) |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 720d6e852986..ff67b334065b 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -1373,7 +1373,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
1373 | struct snd_kcontrol *kcontrol, | 1373 | struct snd_kcontrol *kcontrol, |
1374 | int event) | 1374 | int event) |
1375 | { | 1375 | { |
1376 | struct snd_soc_codec *codec = w->codec; | 1376 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1377 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | 1377 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); |
1378 | struct wm_adsp *dsp = &dsps[w->shift]; | 1378 | struct wm_adsp *dsp = &dsps[w->shift]; |
1379 | struct wm_adsp_alg_region *alg_region; | 1379 | struct wm_adsp_alg_region *alg_region; |
@@ -1605,7 +1605,7 @@ err: | |||
1605 | int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, | 1605 | int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, |
1606 | struct snd_kcontrol *kcontrol, int event) | 1606 | struct snd_kcontrol *kcontrol, int event) |
1607 | { | 1607 | { |
1608 | struct snd_soc_codec *codec = w->codec; | 1608 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1609 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | 1609 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); |
1610 | struct wm_adsp *dsp = &dsps[w->shift]; | 1610 | struct wm_adsp *dsp = &dsps[w->shift]; |
1611 | 1611 | ||
@@ -1626,7 +1626,7 @@ EXPORT_SYMBOL_GPL(wm_adsp2_early_event); | |||
1626 | int wm_adsp2_event(struct snd_soc_dapm_widget *w, | 1626 | int wm_adsp2_event(struct snd_soc_dapm_widget *w, |
1627 | struct snd_kcontrol *kcontrol, int event) | 1627 | struct snd_kcontrol *kcontrol, int event) |
1628 | { | 1628 | { |
1629 | struct snd_soc_codec *codec = w->codec; | 1629 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
1630 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | 1630 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); |
1631 | struct wm_adsp *dsp = &dsps[w->shift]; | 1631 | struct wm_adsp *dsp = &dsps[w->shift]; |
1632 | struct wm_adsp_alg_region *alg_region; | 1632 | struct wm_adsp_alg_region *alg_region; |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 374537d5e179..8366e19657a7 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -500,7 +500,7 @@ SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1, | |||
500 | static int hp_supply_event(struct snd_soc_dapm_widget *w, | 500 | static int hp_supply_event(struct snd_soc_dapm_widget *w, |
501 | struct snd_kcontrol *kcontrol, int event) | 501 | struct snd_kcontrol *kcontrol, int event) |
502 | { | 502 | { |
503 | struct snd_soc_codec *codec = w->codec; | 503 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
504 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 504 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
505 | 505 | ||
506 | switch (event) { | 506 | switch (event) { |
@@ -542,7 +542,7 @@ static int hp_supply_event(struct snd_soc_dapm_widget *w, | |||
542 | static int hp_event(struct snd_soc_dapm_widget *w, | 542 | static int hp_event(struct snd_soc_dapm_widget *w, |
543 | struct snd_kcontrol *kcontrol, int event) | 543 | struct snd_kcontrol *kcontrol, int event) |
544 | { | 544 | { |
545 | struct snd_soc_codec *codec = w->codec; | 545 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
546 | unsigned int reg = snd_soc_read(codec, WM8993_ANALOGUE_HP_0); | 546 | unsigned int reg = snd_soc_read(codec, WM8993_ANALOGUE_HP_0); |
547 | 547 | ||
548 | switch (event) { | 548 | switch (event) { |
@@ -594,7 +594,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, | |||
594 | static int earpiece_event(struct snd_soc_dapm_widget *w, | 594 | static int earpiece_event(struct snd_soc_dapm_widget *w, |
595 | struct snd_kcontrol *control, int event) | 595 | struct snd_kcontrol *control, int event) |
596 | { | 596 | { |
597 | struct snd_soc_codec *codec = w->codec; | 597 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
598 | u16 reg = snd_soc_read(codec, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA; | 598 | u16 reg = snd_soc_read(codec, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA; |
599 | 599 | ||
600 | switch (event) { | 600 | switch (event) { |
@@ -619,7 +619,7 @@ static int earpiece_event(struct snd_soc_dapm_widget *w, | |||
619 | static int lineout_event(struct snd_soc_dapm_widget *w, | 619 | static int lineout_event(struct snd_soc_dapm_widget *w, |
620 | struct snd_kcontrol *control, int event) | 620 | struct snd_kcontrol *control, int event) |
621 | { | 621 | { |
622 | struct snd_soc_codec *codec = w->codec; | 622 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
623 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 623 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
624 | bool *flag; | 624 | bool *flag; |
625 | 625 | ||
@@ -649,7 +649,7 @@ static int lineout_event(struct snd_soc_dapm_widget *w, | |||
649 | static int micbias_event(struct snd_soc_dapm_widget *w, | 649 | static int micbias_event(struct snd_soc_dapm_widget *w, |
650 | struct snd_kcontrol *kcontrol, int event) | 650 | struct snd_kcontrol *kcontrol, int event) |
651 | { | 651 | { |
652 | struct snd_soc_codec *codec = w->codec; | 652 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
653 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 653 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
654 | 654 | ||
655 | switch (w->shift) { | 655 | switch (w->shift) { |
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig index 8e948c63f3d9..2b81ca418d2a 100644 --- a/sound/soc/davinci/Kconfig +++ b/sound/soc/davinci/Kconfig | |||
@@ -58,13 +58,12 @@ choice | |||
58 | depends on MACH_DAVINCI_DM365_EVM | 58 | depends on MACH_DAVINCI_DM365_EVM |
59 | 59 | ||
60 | config SND_DM365_AIC3X_CODEC | 60 | config SND_DM365_AIC3X_CODEC |
61 | bool "Audio Codec - AIC3101" | 61 | tristate "Audio Codec - AIC3101" |
62 | help | 62 | help |
63 | Say Y if you want to add support for AIC3101 audio codec | 63 | Say Y if you want to add support for AIC3101 audio codec |
64 | 64 | ||
65 | config SND_DM365_VOICE_CODEC | 65 | config SND_DM365_VOICE_CODEC |
66 | tristate "Voice Codec - CQ93VC" | 66 | tristate "Voice Codec - CQ93VC" |
67 | depends on SND_DAVINCI_SOC | ||
68 | select MFD_DAVINCI_VOICECODEC | 67 | select MFD_DAVINCI_VOICECODEC |
69 | select SND_DAVINCI_SOC_VCIF | 68 | select SND_DAVINCI_SOC_VCIF |
70 | select SND_SOC_CQ0093VC | 69 | select SND_SOC_CQ0093VC |
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 158cb3d1db70..b6bb5947a8a8 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/timer.h> | 14 | #include <linux/timer.h> |
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/platform_data/edma.h> | ||
18 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
19 | #include <linux/of_platform.h> | 18 | #include <linux/of_platform.h> |
20 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
@@ -25,11 +24,6 @@ | |||
25 | #include <asm/dma.h> | 24 | #include <asm/dma.h> |
26 | #include <asm/mach-types.h> | 25 | #include <asm/mach-types.h> |
27 | 26 | ||
28 | #include <linux/edma.h> | ||
29 | |||
30 | #include "davinci-pcm.h" | ||
31 | #include "davinci-i2s.h" | ||
32 | |||
33 | struct snd_soc_card_drvdata_davinci { | 27 | struct snd_soc_card_drvdata_davinci { |
34 | struct clk *mclk; | 28 | struct clk *mclk; |
35 | unsigned sysclk; | 29 | unsigned sysclk; |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 30b94d4f9c5d..de3b155a5011 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -364,6 +364,20 @@ static irqreturn_t davinci_mcasp_rx_irq_handler(int irq, void *data) | |||
364 | return IRQ_RETVAL(handled_mask); | 364 | return IRQ_RETVAL(handled_mask); |
365 | } | 365 | } |
366 | 366 | ||
367 | static irqreturn_t davinci_mcasp_common_irq_handler(int irq, void *data) | ||
368 | { | ||
369 | struct davinci_mcasp *mcasp = (struct davinci_mcasp *)data; | ||
370 | irqreturn_t ret = IRQ_NONE; | ||
371 | |||
372 | if (mcasp->substreams[SNDRV_PCM_STREAM_PLAYBACK]) | ||
373 | ret = davinci_mcasp_tx_irq_handler(irq, data); | ||
374 | |||
375 | if (mcasp->substreams[SNDRV_PCM_STREAM_CAPTURE]) | ||
376 | ret |= davinci_mcasp_rx_irq_handler(irq, data); | ||
377 | |||
378 | return ret; | ||
379 | } | ||
380 | |||
367 | static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 381 | static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
368 | unsigned int fmt) | 382 | unsigned int fmt) |
369 | { | 383 | { |
@@ -1313,16 +1327,19 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of( | |||
1313 | 1327 | ||
1314 | pdata->tx_dma_channel = dma_spec.args[0]; | 1328 | pdata->tx_dma_channel = dma_spec.args[0]; |
1315 | 1329 | ||
1316 | ret = of_property_match_string(np, "dma-names", "rx"); | 1330 | /* RX is not valid in DIT mode */ |
1317 | if (ret < 0) | 1331 | if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE) { |
1318 | goto nodata; | 1332 | ret = of_property_match_string(np, "dma-names", "rx"); |
1333 | if (ret < 0) | ||
1334 | goto nodata; | ||
1319 | 1335 | ||
1320 | ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret, | 1336 | ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret, |
1321 | &dma_spec); | 1337 | &dma_spec); |
1322 | if (ret < 0) | 1338 | if (ret < 0) |
1323 | goto nodata; | 1339 | goto nodata; |
1324 | 1340 | ||
1325 | pdata->rx_dma_channel = dma_spec.args[0]; | 1341 | pdata->rx_dma_channel = dma_spec.args[0]; |
1342 | } | ||
1326 | 1343 | ||
1327 | ret = of_property_read_u32(np, "tx-num-evt", &val); | 1344 | ret = of_property_read_u32(np, "tx-num-evt", &val); |
1328 | if (ret >= 0) | 1345 | if (ret >= 0) |
@@ -1441,6 +1458,23 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1441 | 1458 | ||
1442 | mcasp->dev = &pdev->dev; | 1459 | mcasp->dev = &pdev->dev; |
1443 | 1460 | ||
1461 | irq = platform_get_irq_byname(pdev, "common"); | ||
1462 | if (irq >= 0) { | ||
1463 | irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_common\n", | ||
1464 | dev_name(&pdev->dev)); | ||
1465 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, | ||
1466 | davinci_mcasp_common_irq_handler, | ||
1467 | IRQF_ONESHOT | IRQF_SHARED, | ||
1468 | irq_name, mcasp); | ||
1469 | if (ret) { | ||
1470 | dev_err(&pdev->dev, "common IRQ request failed\n"); | ||
1471 | goto err; | ||
1472 | } | ||
1473 | |||
1474 | mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK] = XUNDRN; | ||
1475 | mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN; | ||
1476 | } | ||
1477 | |||
1444 | irq = platform_get_irq_byname(pdev, "rx"); | 1478 | irq = platform_get_irq_byname(pdev, "rx"); |
1445 | if (irq >= 0) { | 1479 | if (irq >= 0) { |
1446 | irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_rx\n", | 1480 | irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_rx\n", |
@@ -1501,19 +1535,34 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1501 | else | 1535 | else |
1502 | dma_data->filter_data = &dma_params->channel; | 1536 | dma_data->filter_data = &dma_params->channel; |
1503 | 1537 | ||
1504 | dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; | 1538 | /* RX is not valid in DIT mode */ |
1505 | dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; | 1539 | if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) { |
1506 | dma_params->asp_chan_q = pdata->asp_chan_q; | 1540 | dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; |
1507 | dma_params->ram_chan_q = pdata->ram_chan_q; | 1541 | dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; |
1508 | dma_params->sram_pool = pdata->sram_pool; | 1542 | dma_params->asp_chan_q = pdata->asp_chan_q; |
1509 | dma_params->sram_size = pdata->sram_size_capture; | 1543 | dma_params->ram_chan_q = pdata->ram_chan_q; |
1510 | if (dat) | 1544 | dma_params->sram_pool = pdata->sram_pool; |
1511 | dma_params->dma_addr = dat->start; | 1545 | dma_params->sram_size = pdata->sram_size_capture; |
1512 | else | 1546 | if (dat) |
1513 | dma_params->dma_addr = mem->start + pdata->rx_dma_offset; | 1547 | dma_params->dma_addr = dat->start; |
1514 | 1548 | else | |
1515 | /* Unconditional dmaengine stuff */ | 1549 | dma_params->dma_addr = mem->start + pdata->rx_dma_offset; |
1516 | dma_data->addr = dma_params->dma_addr; | 1550 | |
1551 | /* Unconditional dmaengine stuff */ | ||
1552 | dma_data->addr = dma_params->dma_addr; | ||
1553 | |||
1554 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
1555 | if (res) | ||
1556 | dma_params->channel = res->start; | ||
1557 | else | ||
1558 | dma_params->channel = pdata->rx_dma_channel; | ||
1559 | |||
1560 | /* dmaengine filter data for DT and non-DT boot */ | ||
1561 | if (pdev->dev.of_node) | ||
1562 | dma_data->filter_data = "rx"; | ||
1563 | else | ||
1564 | dma_data->filter_data = &dma_params->channel; | ||
1565 | } | ||
1517 | 1566 | ||
1518 | if (mcasp->version < MCASP_VERSION_3) { | 1567 | if (mcasp->version < MCASP_VERSION_3) { |
1519 | mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE; | 1568 | mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE; |
@@ -1523,18 +1572,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1523 | mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE; | 1572 | mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE; |
1524 | } | 1573 | } |
1525 | 1574 | ||
1526 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
1527 | if (res) | ||
1528 | dma_params->channel = res->start; | ||
1529 | else | ||
1530 | dma_params->channel = pdata->rx_dma_channel; | ||
1531 | |||
1532 | /* dmaengine filter data for DT and non-DT boot */ | ||
1533 | if (pdev->dev.of_node) | ||
1534 | dma_data->filter_data = "rx"; | ||
1535 | else | ||
1536 | dma_data->filter_data = &dma_params->channel; | ||
1537 | |||
1538 | dev_set_drvdata(&pdev->dev, mcasp); | 1575 | dev_set_drvdata(&pdev->dev, mcasp); |
1539 | 1576 | ||
1540 | mcasp_reparent_fck(pdev); | 1577 | mcasp_reparent_fck(pdev); |
diff --git a/sound/soc/dwc/Kconfig b/sound/soc/dwc/Kconfig index e334900cf0b8..d50e08517dce 100644 --- a/sound/soc/dwc/Kconfig +++ b/sound/soc/dwc/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config SND_DESIGNWARE_I2S | 1 | config SND_DESIGNWARE_I2S |
2 | tristate "Synopsys I2S Device Driver" | 2 | tristate "Synopsys I2S Device Driver" |
3 | depends on CLKDEV_LOOKUP | 3 | depends on CLKDEV_LOOKUP |
4 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
4 | help | 5 | help |
5 | Say Y or M if you want to add support for I2S driver for | 6 | Say Y or M if you want to add support for I2S driver for |
6 | Synopsys desigwnware I2S device. The device supports upto | 7 | Synopsys desigwnware I2S device. The device supports upto |
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c index 8d18bbda661b..a3e97b46b64e 100644 --- a/sound/soc/dwc/designware_i2s.c +++ b/sound/soc/dwc/designware_i2s.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 23 | #include <sound/pcm_params.h> |
24 | #include <sound/soc.h> | 24 | #include <sound/soc.h> |
25 | #include <sound/dmaengine_pcm.h> | ||
25 | 26 | ||
26 | /* common register for all channel */ | 27 | /* common register for all channel */ |
27 | #define IER 0x000 | 28 | #define IER 0x000 |
@@ -54,9 +55,39 @@ | |||
54 | #define I2S_COMP_VERSION 0x01F8 | 55 | #define I2S_COMP_VERSION 0x01F8 |
55 | #define I2S_COMP_TYPE 0x01FC | 56 | #define I2S_COMP_TYPE 0x01FC |
56 | 57 | ||
58 | /* | ||
59 | * Component parameter register fields - define the I2S block's | ||
60 | * configuration. | ||
61 | */ | ||
62 | #define COMP1_TX_WORDSIZE_3(r) (((r) & GENMASK(27, 25)) >> 25) | ||
63 | #define COMP1_TX_WORDSIZE_2(r) (((r) & GENMASK(24, 22)) >> 22) | ||
64 | #define COMP1_TX_WORDSIZE_1(r) (((r) & GENMASK(21, 19)) >> 19) | ||
65 | #define COMP1_TX_WORDSIZE_0(r) (((r) & GENMASK(18, 16)) >> 16) | ||
66 | #define COMP1_TX_CHANNELS(r) (((r) & GENMASK(10, 9)) >> 9) | ||
67 | #define COMP1_RX_CHANNELS(r) (((r) & GENMASK(8, 7)) >> 7) | ||
68 | #define COMP1_RX_ENABLED(r) (((r) & BIT(6)) >> 6) | ||
69 | #define COMP1_TX_ENABLED(r) (((r) & BIT(5)) >> 5) | ||
70 | #define COMP1_MODE_EN(r) (((r) & BIT(4)) >> 4) | ||
71 | #define COMP1_FIFO_DEPTH_GLOBAL(r) (((r) & GENMASK(3, 2)) >> 2) | ||
72 | #define COMP1_APB_DATA_WIDTH(r) (((r) & GENMASK(1, 0)) >> 0) | ||
73 | |||
74 | #define COMP2_RX_WORDSIZE_3(r) (((r) & GENMASK(12, 10)) >> 10) | ||
75 | #define COMP2_RX_WORDSIZE_2(r) (((r) & GENMASK(9, 7)) >> 7) | ||
76 | #define COMP2_RX_WORDSIZE_1(r) (((r) & GENMASK(5, 3)) >> 3) | ||
77 | #define COMP2_RX_WORDSIZE_0(r) (((r) & GENMASK(2, 0)) >> 0) | ||
78 | |||
79 | /* Number of entries in WORDSIZE and DATA_WIDTH parameter registers */ | ||
80 | #define COMP_MAX_WORDSIZE (1 << 3) | ||
81 | #define COMP_MAX_DATA_WIDTH (1 << 2) | ||
82 | |||
57 | #define MAX_CHANNEL_NUM 8 | 83 | #define MAX_CHANNEL_NUM 8 |
58 | #define MIN_CHANNEL_NUM 2 | 84 | #define MIN_CHANNEL_NUM 2 |
59 | 85 | ||
86 | union dw_i2s_snd_dma_data { | ||
87 | struct i2s_dma_data pd; | ||
88 | struct snd_dmaengine_dai_dma_data dt; | ||
89 | }; | ||
90 | |||
60 | struct dw_i2s_dev { | 91 | struct dw_i2s_dev { |
61 | void __iomem *i2s_base; | 92 | void __iomem *i2s_base; |
62 | struct clk *clk; | 93 | struct clk *clk; |
@@ -65,8 +96,8 @@ struct dw_i2s_dev { | |||
65 | struct device *dev; | 96 | struct device *dev; |
66 | 97 | ||
67 | /* data related to DMA transfers b/w i2s and DMAC */ | 98 | /* data related to DMA transfers b/w i2s and DMAC */ |
68 | struct i2s_dma_data play_dma_data; | 99 | union dw_i2s_snd_dma_data play_dma_data; |
69 | struct i2s_dma_data capture_dma_data; | 100 | union dw_i2s_snd_dma_data capture_dma_data; |
70 | struct i2s_clk_config_data config; | 101 | struct i2s_clk_config_data config; |
71 | int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); | 102 | int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); |
72 | }; | 103 | }; |
@@ -153,7 +184,7 @@ static int dw_i2s_startup(struct snd_pcm_substream *substream, | |||
153 | struct snd_soc_dai *cpu_dai) | 184 | struct snd_soc_dai *cpu_dai) |
154 | { | 185 | { |
155 | struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); | 186 | struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); |
156 | struct i2s_dma_data *dma_data = NULL; | 187 | union dw_i2s_snd_dma_data *dma_data = NULL; |
157 | 188 | ||
158 | if (!(dev->capability & DWC_I2S_RECORD) && | 189 | if (!(dev->capability & DWC_I2S_RECORD) && |
159 | (substream->stream == SNDRV_PCM_STREAM_CAPTURE)) | 190 | (substream->stream == SNDRV_PCM_STREAM_CAPTURE)) |
@@ -242,13 +273,21 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream, | |||
242 | 273 | ||
243 | config->sample_rate = params_rate(params); | 274 | config->sample_rate = params_rate(params); |
244 | 275 | ||
245 | if (!dev->i2s_clk_cfg) | 276 | if (dev->i2s_clk_cfg) { |
246 | return -EINVAL; | 277 | ret = dev->i2s_clk_cfg(config); |
278 | if (ret < 0) { | ||
279 | dev_err(dev->dev, "runtime audio clk config fail\n"); | ||
280 | return ret; | ||
281 | } | ||
282 | } else { | ||
283 | u32 bitclk = config->sample_rate * config->data_width * 2; | ||
247 | 284 | ||
248 | ret = dev->i2s_clk_cfg(config); | 285 | ret = clk_set_rate(dev->clk, bitclk); |
249 | if (ret < 0) { | 286 | if (ret) { |
250 | dev_err(dev->dev, "runtime audio clk config fail\n"); | 287 | dev_err(dev->dev, "Can't set I2S clock rate: %d\n", |
251 | return ret; | 288 | ret); |
289 | return ret; | ||
290 | } | ||
252 | } | 291 | } |
253 | 292 | ||
254 | return 0; | 293 | return 0; |
@@ -335,20 +374,162 @@ static int dw_i2s_resume(struct snd_soc_dai *dai) | |||
335 | #define dw_i2s_resume NULL | 374 | #define dw_i2s_resume NULL |
336 | #endif | 375 | #endif |
337 | 376 | ||
377 | /* | ||
378 | * The following tables allow a direct lookup of various parameters | ||
379 | * defined in the I2S block's configuration in terms of sound system | ||
380 | * parameters. Each table is sized to the number of entries possible | ||
381 | * according to the number of configuration bits describing an I2S | ||
382 | * block parameter. | ||
383 | */ | ||
384 | |||
385 | /* Maximum bit resolution of a channel - not uniformly spaced */ | ||
386 | static const u32 fifo_width[COMP_MAX_WORDSIZE] = { | ||
387 | 12, 16, 20, 24, 32, 0, 0, 0 | ||
388 | }; | ||
389 | |||
390 | /* Width of (DMA) bus */ | ||
391 | static const u32 bus_widths[COMP_MAX_DATA_WIDTH] = { | ||
392 | DMA_SLAVE_BUSWIDTH_1_BYTE, | ||
393 | DMA_SLAVE_BUSWIDTH_2_BYTES, | ||
394 | DMA_SLAVE_BUSWIDTH_4_BYTES, | ||
395 | DMA_SLAVE_BUSWIDTH_UNDEFINED | ||
396 | }; | ||
397 | |||
398 | /* PCM format to support channel resolution */ | ||
399 | static const u32 formats[COMP_MAX_WORDSIZE] = { | ||
400 | SNDRV_PCM_FMTBIT_S16_LE, | ||
401 | SNDRV_PCM_FMTBIT_S16_LE, | ||
402 | SNDRV_PCM_FMTBIT_S24_LE, | ||
403 | SNDRV_PCM_FMTBIT_S24_LE, | ||
404 | SNDRV_PCM_FMTBIT_S32_LE, | ||
405 | 0, | ||
406 | 0, | ||
407 | 0 | ||
408 | }; | ||
409 | |||
410 | static int dw_configure_dai(struct dw_i2s_dev *dev, | ||
411 | struct snd_soc_dai_driver *dw_i2s_dai, | ||
412 | unsigned int rates) | ||
413 | { | ||
414 | /* | ||
415 | * Read component parameter registers to extract | ||
416 | * the I2S block's configuration. | ||
417 | */ | ||
418 | u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1); | ||
419 | u32 comp2 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_2); | ||
420 | u32 idx; | ||
421 | |||
422 | if (COMP1_TX_ENABLED(comp1)) { | ||
423 | dev_dbg(dev->dev, " designware: play supported\n"); | ||
424 | idx = COMP1_TX_WORDSIZE_0(comp1); | ||
425 | if (WARN_ON(idx >= ARRAY_SIZE(formats))) | ||
426 | return -EINVAL; | ||
427 | dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM; | ||
428 | dw_i2s_dai->playback.channels_max = | ||
429 | 1 << (COMP1_TX_CHANNELS(comp1) + 1); | ||
430 | dw_i2s_dai->playback.formats = formats[idx]; | ||
431 | dw_i2s_dai->playback.rates = rates; | ||
432 | } | ||
433 | |||
434 | if (COMP1_RX_ENABLED(comp1)) { | ||
435 | dev_dbg(dev->dev, "designware: record supported\n"); | ||
436 | idx = COMP2_RX_WORDSIZE_0(comp2); | ||
437 | if (WARN_ON(idx >= ARRAY_SIZE(formats))) | ||
438 | return -EINVAL; | ||
439 | dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; | ||
440 | dw_i2s_dai->capture.channels_max = | ||
441 | 1 << (COMP1_RX_CHANNELS(comp1) + 1); | ||
442 | dw_i2s_dai->capture.formats = formats[idx]; | ||
443 | dw_i2s_dai->capture.rates = rates; | ||
444 | } | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | static int dw_configure_dai_by_pd(struct dw_i2s_dev *dev, | ||
450 | struct snd_soc_dai_driver *dw_i2s_dai, | ||
451 | struct resource *res, | ||
452 | const struct i2s_platform_data *pdata) | ||
453 | { | ||
454 | u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1); | ||
455 | u32 idx = COMP1_APB_DATA_WIDTH(comp1); | ||
456 | int ret; | ||
457 | |||
458 | if (WARN_ON(idx >= ARRAY_SIZE(bus_widths))) | ||
459 | return -EINVAL; | ||
460 | |||
461 | ret = dw_configure_dai(dev, dw_i2s_dai, pdata->snd_rates); | ||
462 | if (ret < 0) | ||
463 | return ret; | ||
464 | |||
465 | /* Set DMA slaves info */ | ||
466 | dev->play_dma_data.pd.data = pdata->play_dma_data; | ||
467 | dev->capture_dma_data.pd.data = pdata->capture_dma_data; | ||
468 | dev->play_dma_data.pd.addr = res->start + I2S_TXDMA; | ||
469 | dev->capture_dma_data.pd.addr = res->start + I2S_RXDMA; | ||
470 | dev->play_dma_data.pd.max_burst = 16; | ||
471 | dev->capture_dma_data.pd.max_burst = 16; | ||
472 | dev->play_dma_data.pd.addr_width = bus_widths[idx]; | ||
473 | dev->capture_dma_data.pd.addr_width = bus_widths[idx]; | ||
474 | dev->play_dma_data.pd.filter = pdata->filter; | ||
475 | dev->capture_dma_data.pd.filter = pdata->filter; | ||
476 | |||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev, | ||
481 | struct snd_soc_dai_driver *dw_i2s_dai, | ||
482 | struct resource *res) | ||
483 | { | ||
484 | u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1); | ||
485 | u32 comp2 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_2); | ||
486 | u32 fifo_depth = 1 << (1 + COMP1_FIFO_DEPTH_GLOBAL(comp1)); | ||
487 | u32 idx = COMP1_APB_DATA_WIDTH(comp1); | ||
488 | u32 idx2; | ||
489 | int ret; | ||
490 | |||
491 | if (WARN_ON(idx >= ARRAY_SIZE(bus_widths))) | ||
492 | return -EINVAL; | ||
493 | |||
494 | ret = dw_configure_dai(dev, dw_i2s_dai, SNDRV_PCM_RATE_8000_192000); | ||
495 | if (ret < 0) | ||
496 | return ret; | ||
497 | |||
498 | if (COMP1_TX_ENABLED(comp1)) { | ||
499 | idx2 = COMP1_TX_WORDSIZE_0(comp1); | ||
500 | |||
501 | dev->capability |= DWC_I2S_PLAY; | ||
502 | dev->play_dma_data.dt.addr = res->start + I2S_TXDMA; | ||
503 | dev->play_dma_data.dt.addr_width = bus_widths[idx]; | ||
504 | dev->play_dma_data.dt.chan_name = "TX"; | ||
505 | dev->play_dma_data.dt.fifo_size = fifo_depth * | ||
506 | (fifo_width[idx2]) >> 8; | ||
507 | dev->play_dma_data.dt.maxburst = 16; | ||
508 | } | ||
509 | if (COMP1_RX_ENABLED(comp1)) { | ||
510 | idx2 = COMP2_RX_WORDSIZE_0(comp2); | ||
511 | |||
512 | dev->capability |= DWC_I2S_RECORD; | ||
513 | dev->capture_dma_data.dt.addr = res->start + I2S_RXDMA; | ||
514 | dev->capture_dma_data.dt.addr_width = bus_widths[idx]; | ||
515 | dev->capture_dma_data.dt.chan_name = "RX"; | ||
516 | dev->capture_dma_data.dt.fifo_size = fifo_depth * | ||
517 | (fifo_width[idx2] >> 8); | ||
518 | dev->capture_dma_data.dt.maxburst = 16; | ||
519 | } | ||
520 | |||
521 | return 0; | ||
522 | |||
523 | } | ||
524 | |||
338 | static int dw_i2s_probe(struct platform_device *pdev) | 525 | static int dw_i2s_probe(struct platform_device *pdev) |
339 | { | 526 | { |
340 | const struct i2s_platform_data *pdata = pdev->dev.platform_data; | 527 | const struct i2s_platform_data *pdata = pdev->dev.platform_data; |
341 | struct dw_i2s_dev *dev; | 528 | struct dw_i2s_dev *dev; |
342 | struct resource *res; | 529 | struct resource *res; |
343 | int ret; | 530 | int ret; |
344 | unsigned int cap; | ||
345 | struct snd_soc_dai_driver *dw_i2s_dai; | 531 | struct snd_soc_dai_driver *dw_i2s_dai; |
346 | 532 | ||
347 | if (!pdata) { | ||
348 | dev_err(&pdev->dev, "Invalid platform data\n"); | ||
349 | return -EINVAL; | ||
350 | } | ||
351 | |||
352 | dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); | 533 | dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); |
353 | if (!dev) { | 534 | if (!dev) { |
354 | dev_warn(&pdev->dev, "kzalloc fail\n"); | 535 | dev_warn(&pdev->dev, "kzalloc fail\n"); |
@@ -356,83 +537,67 @@ static int dw_i2s_probe(struct platform_device *pdev) | |||
356 | } | 537 | } |
357 | 538 | ||
358 | dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL); | 539 | dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL); |
359 | if (!dw_i2s_dai) { | 540 | if (!dw_i2s_dai) |
360 | dev_err(&pdev->dev, "mem allocation failed for dai driver\n"); | ||
361 | return -ENOMEM; | 541 | return -ENOMEM; |
362 | } | ||
363 | 542 | ||
364 | dw_i2s_dai->ops = &dw_i2s_dai_ops; | 543 | dw_i2s_dai->ops = &dw_i2s_dai_ops; |
365 | dw_i2s_dai->suspend = dw_i2s_suspend; | 544 | dw_i2s_dai->suspend = dw_i2s_suspend; |
366 | dw_i2s_dai->resume = dw_i2s_resume; | 545 | dw_i2s_dai->resume = dw_i2s_resume; |
367 | 546 | ||
368 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 547 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
369 | if (!res) { | ||
370 | dev_err(&pdev->dev, "no i2s resource defined\n"); | ||
371 | return -ENODEV; | ||
372 | } | ||
373 | |||
374 | dev->i2s_base = devm_ioremap_resource(&pdev->dev, res); | 548 | dev->i2s_base = devm_ioremap_resource(&pdev->dev, res); |
375 | if (IS_ERR(dev->i2s_base)) { | 549 | if (IS_ERR(dev->i2s_base)) |
376 | dev_err(&pdev->dev, "ioremap fail for i2s_region\n"); | ||
377 | return PTR_ERR(dev->i2s_base); | 550 | return PTR_ERR(dev->i2s_base); |
378 | } | ||
379 | 551 | ||
380 | cap = pdata->cap; | 552 | dev->dev = &pdev->dev; |
381 | dev->capability = cap; | 553 | if (pdata) { |
382 | dev->i2s_clk_cfg = pdata->i2s_clk_cfg; | 554 | ret = dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata); |
555 | if (ret < 0) | ||
556 | return ret; | ||
557 | |||
558 | dev->capability = pdata->cap; | ||
559 | dev->i2s_clk_cfg = pdata->i2s_clk_cfg; | ||
560 | if (!dev->i2s_clk_cfg) { | ||
561 | dev_err(&pdev->dev, "no clock configure method\n"); | ||
562 | return -ENODEV; | ||
563 | } | ||
383 | 564 | ||
384 | /* Set DMA slaves info */ | 565 | dev->clk = devm_clk_get(&pdev->dev, NULL); |
566 | } else { | ||
567 | ret = dw_configure_dai_by_dt(dev, dw_i2s_dai, res); | ||
568 | if (ret < 0) | ||
569 | return ret; | ||
385 | 570 | ||
386 | dev->play_dma_data.data = pdata->play_dma_data; | 571 | dev->clk = devm_clk_get(&pdev->dev, "i2sclk"); |
387 | dev->capture_dma_data.data = pdata->capture_dma_data; | 572 | } |
388 | dev->play_dma_data.addr = res->start + I2S_TXDMA; | ||
389 | dev->capture_dma_data.addr = res->start + I2S_RXDMA; | ||
390 | dev->play_dma_data.max_burst = 16; | ||
391 | dev->capture_dma_data.max_burst = 16; | ||
392 | dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
393 | dev->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
394 | dev->play_dma_data.filter = pdata->filter; | ||
395 | dev->capture_dma_data.filter = pdata->filter; | ||
396 | |||
397 | dev->clk = clk_get(&pdev->dev, NULL); | ||
398 | if (IS_ERR(dev->clk)) | 573 | if (IS_ERR(dev->clk)) |
399 | return PTR_ERR(dev->clk); | 574 | return PTR_ERR(dev->clk); |
400 | 575 | ||
401 | ret = clk_enable(dev->clk); | 576 | ret = clk_prepare_enable(dev->clk); |
402 | if (ret < 0) | 577 | if (ret < 0) |
403 | goto err_clk_put; | 578 | return ret; |
404 | |||
405 | if (cap & DWC_I2S_PLAY) { | ||
406 | dev_dbg(&pdev->dev, " designware: play supported\n"); | ||
407 | dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM; | ||
408 | dw_i2s_dai->playback.channels_max = pdata->channel; | ||
409 | dw_i2s_dai->playback.formats = pdata->snd_fmts; | ||
410 | dw_i2s_dai->playback.rates = pdata->snd_rates; | ||
411 | } | ||
412 | |||
413 | if (cap & DWC_I2S_RECORD) { | ||
414 | dev_dbg(&pdev->dev, "designware: record supported\n"); | ||
415 | dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; | ||
416 | dw_i2s_dai->capture.channels_max = pdata->channel; | ||
417 | dw_i2s_dai->capture.formats = pdata->snd_fmts; | ||
418 | dw_i2s_dai->capture.rates = pdata->snd_rates; | ||
419 | } | ||
420 | 579 | ||
421 | dev->dev = &pdev->dev; | ||
422 | dev_set_drvdata(&pdev->dev, dev); | 580 | dev_set_drvdata(&pdev->dev, dev); |
423 | ret = snd_soc_register_component(&pdev->dev, &dw_i2s_component, | 581 | ret = devm_snd_soc_register_component(&pdev->dev, &dw_i2s_component, |
424 | dw_i2s_dai, 1); | 582 | dw_i2s_dai, 1); |
425 | if (ret != 0) { | 583 | if (ret != 0) { |
426 | dev_err(&pdev->dev, "not able to register dai\n"); | 584 | dev_err(&pdev->dev, "not able to register dai\n"); |
427 | goto err_clk_disable; | 585 | goto err_clk_disable; |
428 | } | 586 | } |
429 | 587 | ||
588 | if (!pdata) { | ||
589 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | ||
590 | if (ret) { | ||
591 | dev_err(&pdev->dev, | ||
592 | "Could not register PCM: %d\n", ret); | ||
593 | goto err_clk_disable; | ||
594 | } | ||
595 | } | ||
596 | |||
430 | return 0; | 597 | return 0; |
431 | 598 | ||
432 | err_clk_disable: | 599 | err_clk_disable: |
433 | clk_disable(dev->clk); | 600 | clk_disable_unprepare(dev->clk); |
434 | err_clk_put: | ||
435 | clk_put(dev->clk); | ||
436 | return ret; | 601 | return ret; |
437 | } | 602 | } |
438 | 603 | ||
@@ -440,18 +605,26 @@ static int dw_i2s_remove(struct platform_device *pdev) | |||
440 | { | 605 | { |
441 | struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev); | 606 | struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev); |
442 | 607 | ||
443 | snd_soc_unregister_component(&pdev->dev); | 608 | clk_disable_unprepare(dev->clk); |
444 | |||
445 | clk_put(dev->clk); | ||
446 | 609 | ||
447 | return 0; | 610 | return 0; |
448 | } | 611 | } |
449 | 612 | ||
613 | #ifdef CONFIG_OF | ||
614 | static const struct of_device_id dw_i2s_of_match[] = { | ||
615 | { .compatible = "snps,designware-i2s", }, | ||
616 | {}, | ||
617 | }; | ||
618 | |||
619 | MODULE_DEVICE_TABLE(of, dw_i2s_of_match); | ||
620 | #endif | ||
621 | |||
450 | static struct platform_driver dw_i2s_driver = { | 622 | static struct platform_driver dw_i2s_driver = { |
451 | .probe = dw_i2s_probe, | 623 | .probe = dw_i2s_probe, |
452 | .remove = dw_i2s_remove, | 624 | .remove = dw_i2s_remove, |
453 | .driver = { | 625 | .driver = { |
454 | .name = "designware-i2s", | 626 | .name = "designware-i2s", |
627 | .of_match_table = of_match_ptr(dw_i2s_of_match), | ||
455 | }, | 628 | }, |
456 | }; | 629 | }; |
457 | 630 | ||
diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 9ce70fc67b09..e1aa3834b101 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c | |||
@@ -42,25 +42,6 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, | |||
42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
43 | int ret; | 43 | int ret; |
44 | 44 | ||
45 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
46 | SND_SOC_DAIFMT_NB_NF | | ||
47 | SND_SOC_DAIFMT_CBM_CFM); | ||
48 | /* fsl_ssi lacks the set_fmt ops. */ | ||
49 | if (ret && ret != -ENOTSUPP) { | ||
50 | dev_err(cpu_dai->dev, | ||
51 | "Failed to set the cpu dai format.\n"); | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
56 | SND_SOC_DAIFMT_NB_NF | | ||
57 | SND_SOC_DAIFMT_CBM_CFM); | ||
58 | if (ret) { | ||
59 | dev_err(cpu_dai->dev, | ||
60 | "Failed to set the codec format.\n"); | ||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, | 45 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, |
65 | CODEC_CLOCK, SND_SOC_CLOCK_OUT); | 46 | CODEC_CLOCK, SND_SOC_CLOCK_OUT); |
66 | if (ret) { | 47 | if (ret) { |
@@ -69,7 +50,7 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, | |||
69 | return ret; | 50 | return ret; |
70 | } | 51 | } |
71 | 52 | ||
72 | snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0); | 53 | snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 0); |
73 | 54 | ||
74 | ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, | 55 | ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, |
75 | SND_SOC_CLOCK_IN); | 56 | SND_SOC_CLOCK_IN); |
@@ -91,6 +72,8 @@ static struct snd_soc_dai_link eukrea_tlv320_dai = { | |||
91 | .name = "tlv320aic23", | 72 | .name = "tlv320aic23", |
92 | .stream_name = "TLV320AIC23", | 73 | .stream_name = "TLV320AIC23", |
93 | .codec_dai_name = "tlv320aic23-hifi", | 74 | .codec_dai_name = "tlv320aic23-hifi", |
75 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
76 | SND_SOC_DAIFMT_CBM_CFM, | ||
94 | .ops = &eukrea_tlv320_snd_ops, | 77 | .ops = &eukrea_tlv320_snd_ops, |
95 | }; | 78 | }; |
96 | 79 | ||
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 026a80117540..c068494bae30 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c | |||
@@ -818,7 +818,6 @@ static int fsl_asrc_probe(struct platform_device *pdev) | |||
818 | return -ENOMEM; | 818 | return -ENOMEM; |
819 | 819 | ||
820 | asrc_priv->pdev = pdev; | 820 | asrc_priv->pdev = pdev; |
821 | strncpy(asrc_priv->name, np->name, sizeof(asrc_priv->name) - 1); | ||
822 | 821 | ||
823 | /* Get the addresses and IRQ */ | 822 | /* Get the addresses and IRQ */ |
824 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 823 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -837,12 +836,12 @@ static int fsl_asrc_probe(struct platform_device *pdev) | |||
837 | 836 | ||
838 | irq = platform_get_irq(pdev, 0); | 837 | irq = platform_get_irq(pdev, 0); |
839 | if (irq < 0) { | 838 | if (irq < 0) { |
840 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | 839 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); |
841 | return irq; | 840 | return irq; |
842 | } | 841 | } |
843 | 842 | ||
844 | ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0, | 843 | ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0, |
845 | asrc_priv->name, asrc_priv); | 844 | dev_name(&pdev->dev), asrc_priv); |
846 | if (ret) { | 845 | if (ret) { |
847 | dev_err(&pdev->dev, "failed to claim irq %u: %d\n", irq, ret); | 846 | dev_err(&pdev->dev, "failed to claim irq %u: %d\n", irq, ret); |
848 | return ret; | 847 | return ret; |
diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h index a3f211f53c23..4aed63c4b431 100644 --- a/sound/soc/fsl/fsl_asrc.h +++ b/sound/soc/fsl/fsl_asrc.h | |||
@@ -433,7 +433,6 @@ struct fsl_asrc_pair { | |||
433 | * @channel_avail: non-occupied channel numbers | 433 | * @channel_avail: non-occupied channel numbers |
434 | * @asrc_rate: default sample rate for ASoC Back-Ends | 434 | * @asrc_rate: default sample rate for ASoC Back-Ends |
435 | * @asrc_width: default sample width for ASoC Back-Ends | 435 | * @asrc_width: default sample width for ASoC Back-Ends |
436 | * @name: driver name | ||
437 | */ | 436 | */ |
438 | struct fsl_asrc { | 437 | struct fsl_asrc { |
439 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 438 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
@@ -452,8 +451,6 @@ struct fsl_asrc { | |||
452 | 451 | ||
453 | int asrc_rate; | 452 | int asrc_rate; |
454 | int asrc_width; | 453 | int asrc_width; |
455 | |||
456 | char name[32]; | ||
457 | }; | 454 | }; |
458 | 455 | ||
459 | extern struct snd_soc_platform_driver fsl_asrc_platform; | 456 | extern struct snd_soc_platform_driver fsl_asrc_platform; |
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 1c08ab13637c..5c7597191e3f 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c | |||
@@ -774,7 +774,7 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
774 | 774 | ||
775 | irq = platform_get_irq(pdev, 0); | 775 | irq = platform_get_irq(pdev, 0); |
776 | if (irq < 0) { | 776 | if (irq < 0) { |
777 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | 777 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); |
778 | return irq; | 778 | return irq; |
779 | } | 779 | } |
780 | 780 | ||
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 032d2d33619c..ec79c3d5e65e 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c | |||
@@ -612,7 +612,7 @@ static int fsl_sai_probe(struct platform_device *pdev) | |||
612 | 612 | ||
613 | irq = platform_get_irq(pdev, 0); | 613 | irq = platform_get_irq(pdev, 0); |
614 | if (irq < 0) { | 614 | if (irq < 0) { |
615 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | 615 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); |
616 | return irq; | 616 | return irq; |
617 | } | 617 | } |
618 | 618 | ||
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index af0429421fc8..75870c0ea2c9 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c | |||
@@ -90,7 +90,6 @@ struct spdif_mixer_control { | |||
90 | * @sysclk: system clock for rx clock rate measurement | 90 | * @sysclk: system clock for rx clock rate measurement |
91 | * @dma_params_tx: DMA parameters for transmit channel | 91 | * @dma_params_tx: DMA parameters for transmit channel |
92 | * @dma_params_rx: DMA parameters for receive channel | 92 | * @dma_params_rx: DMA parameters for receive channel |
93 | * @name: driver name | ||
94 | */ | 93 | */ |
95 | struct fsl_spdif_priv { | 94 | struct fsl_spdif_priv { |
96 | struct spdif_mixer_control fsl_spdif_control; | 95 | struct spdif_mixer_control fsl_spdif_control; |
@@ -109,12 +108,8 @@ struct fsl_spdif_priv { | |||
109 | struct clk *sysclk; | 108 | struct clk *sysclk; |
110 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 109 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
111 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 110 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
112 | |||
113 | /* The name space will be allocated dynamically */ | ||
114 | char name[0]; | ||
115 | }; | 111 | }; |
116 | 112 | ||
117 | |||
118 | /* DPLL locked and lock loss interrupt handler */ | 113 | /* DPLL locked and lock loss interrupt handler */ |
119 | static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv) | 114 | static void spdif_irq_dpll_lock(struct fsl_spdif_priv *spdif_priv) |
120 | { | 115 | { |
@@ -1169,19 +1164,15 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
1169 | if (!np) | 1164 | if (!np) |
1170 | return -ENODEV; | 1165 | return -ENODEV; |
1171 | 1166 | ||
1172 | spdif_priv = devm_kzalloc(&pdev->dev, | 1167 | spdif_priv = devm_kzalloc(&pdev->dev, sizeof(*spdif_priv), GFP_KERNEL); |
1173 | sizeof(struct fsl_spdif_priv) + strlen(np->name) + 1, | ||
1174 | GFP_KERNEL); | ||
1175 | if (!spdif_priv) | 1168 | if (!spdif_priv) |
1176 | return -ENOMEM; | 1169 | return -ENOMEM; |
1177 | 1170 | ||
1178 | strcpy(spdif_priv->name, np->name); | ||
1179 | |||
1180 | spdif_priv->pdev = pdev; | 1171 | spdif_priv->pdev = pdev; |
1181 | 1172 | ||
1182 | /* Initialize this copy of the CPU DAI driver structure */ | 1173 | /* Initialize this copy of the CPU DAI driver structure */ |
1183 | memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); | 1174 | memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); |
1184 | spdif_priv->cpu_dai_drv.name = spdif_priv->name; | 1175 | spdif_priv->cpu_dai_drv.name = dev_name(&pdev->dev); |
1185 | 1176 | ||
1186 | /* Get the addresses and IRQ */ | 1177 | /* Get the addresses and IRQ */ |
1187 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1178 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -1198,12 +1189,12 @@ static int fsl_spdif_probe(struct platform_device *pdev) | |||
1198 | 1189 | ||
1199 | irq = platform_get_irq(pdev, 0); | 1190 | irq = platform_get_irq(pdev, 0); |
1200 | if (irq < 0) { | 1191 | if (irq < 0) { |
1201 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | 1192 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); |
1202 | return irq; | 1193 | return irq; |
1203 | } | 1194 | } |
1204 | 1195 | ||
1205 | ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0, | 1196 | ret = devm_request_irq(&pdev->dev, irq, spdif_isr, 0, |
1206 | spdif_priv->name, spdif_priv); | 1197 | dev_name(&pdev->dev), spdif_priv); |
1207 | if (ret) { | 1198 | if (ret) { |
1208 | dev_err(&pdev->dev, "could not claim irq %u\n", irq); | 1199 | dev_err(&pdev->dev, "could not claim irq %u\n", irq); |
1209 | return ret; | 1200 | return ret; |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 059496ed9ad7..b9fabbf69db6 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -160,7 +160,7 @@ struct fsl_ssi_soc_data { | |||
160 | */ | 160 | */ |
161 | struct fsl_ssi_private { | 161 | struct fsl_ssi_private { |
162 | struct regmap *regs; | 162 | struct regmap *regs; |
163 | unsigned int irq; | 163 | int irq; |
164 | struct snd_soc_dai_driver cpu_dai_drv; | 164 | struct snd_soc_dai_driver cpu_dai_drv; |
165 | 165 | ||
166 | unsigned int dai_fmt; | 166 | unsigned int dai_fmt; |
@@ -603,10 +603,6 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, | |||
603 | factor = (div2 + 1) * (7 * psr + 1) * 2; | 603 | factor = (div2 + 1) * (7 * psr + 1) * 2; |
604 | 604 | ||
605 | for (i = 0; i < 255; i++) { | 605 | for (i = 0; i < 255; i++) { |
606 | /* The bclk rate must be smaller than 1/5 sysclk rate */ | ||
607 | if (factor * (i + 1) < 5) | ||
608 | continue; | ||
609 | |||
610 | tmprate = freq * factor * (i + 2); | 606 | tmprate = freq * factor * (i + 2); |
611 | 607 | ||
612 | if (baudclk_is_used) | 608 | if (baudclk_is_used) |
@@ -614,6 +610,13 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, | |||
614 | else | 610 | else |
615 | clkrate = clk_round_rate(ssi_private->baudclk, tmprate); | 611 | clkrate = clk_round_rate(ssi_private->baudclk, tmprate); |
616 | 612 | ||
613 | /* | ||
614 | * Hardware limitation: The bclk rate must be | ||
615 | * never greater than 1/5 IPG clock rate | ||
616 | */ | ||
617 | if (clkrate * 5 > clk_get_rate(ssi_private->clk)) | ||
618 | continue; | ||
619 | |||
617 | clkrate /= factor; | 620 | clkrate /= factor; |
618 | afreq = clkrate / (i + 1); | 621 | afreq = clkrate / (i + 1); |
619 | 622 | ||
@@ -992,8 +995,8 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask, | |||
992 | regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_SSIEN, | 995 | regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_SSIEN, |
993 | CCSR_SSI_SCR_SSIEN); | 996 | CCSR_SSI_SCR_SSIEN); |
994 | 997 | ||
995 | regmap_write(regs, CCSR_SSI_STMSK, tx_mask); | 998 | regmap_write(regs, CCSR_SSI_STMSK, ~tx_mask); |
996 | regmap_write(regs, CCSR_SSI_SRMSK, rx_mask); | 999 | regmap_write(regs, CCSR_SSI_SRMSK, ~rx_mask); |
997 | 1000 | ||
998 | regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_SSIEN, val); | 1001 | regmap_update_bits(regs, CCSR_SSI_SCR, CCSR_SSI_SCR_SSIEN, val); |
999 | 1002 | ||
@@ -1362,8 +1365,8 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
1362 | } | 1365 | } |
1363 | 1366 | ||
1364 | ssi_private->irq = platform_get_irq(pdev, 0); | 1367 | ssi_private->irq = platform_get_irq(pdev, 0); |
1365 | if (ssi_private->irq < 0) { | 1368 | if (!ssi_private->irq) { |
1366 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | 1369 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); |
1367 | return ssi_private->irq; | 1370 | return ssi_private->irq; |
1368 | } | 1371 | } |
1369 | 1372 | ||
diff --git a/sound/soc/fsl/fsl_utils.c b/sound/soc/fsl/fsl_utils.c index 2ac7755da876..b9e42b503a37 100644 --- a/sound/soc/fsl/fsl_utils.c +++ b/sound/soc/fsl/fsl_utils.c | |||
@@ -86,33 +86,6 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, | |||
86 | } | 86 | } |
87 | EXPORT_SYMBOL(fsl_asoc_get_dma_channel); | 87 | EXPORT_SYMBOL(fsl_asoc_get_dma_channel); |
88 | 88 | ||
89 | /** | ||
90 | * fsl_asoc_xlate_tdm_slot_mask - generate TDM slot TX/RX mask. | ||
91 | * | ||
92 | * @slots: Number of slots in use. | ||
93 | * @tx_mask: bitmask representing active TX slots. | ||
94 | * @rx_mask: bitmask representing active RX slots. | ||
95 | * | ||
96 | * This function used to generate the TDM slot TX/RX mask. And the TX/RX | ||
97 | * mask will use a 0 bit for an active slot as default, and the default | ||
98 | * active bits are at the LSB of the mask value. | ||
99 | */ | ||
100 | int fsl_asoc_xlate_tdm_slot_mask(unsigned int slots, | ||
101 | unsigned int *tx_mask, | ||
102 | unsigned int *rx_mask) | ||
103 | { | ||
104 | if (!slots) | ||
105 | return -EINVAL; | ||
106 | |||
107 | if (tx_mask) | ||
108 | *tx_mask = ~((1 << slots) - 1); | ||
109 | if (rx_mask) | ||
110 | *rx_mask = ~((1 << slots) - 1); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | EXPORT_SYMBOL_GPL(fsl_asoc_xlate_tdm_slot_mask); | ||
115 | |||
116 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 89 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); |
117 | MODULE_DESCRIPTION("Freescale ASoC utility code"); | 90 | MODULE_DESCRIPTION("Freescale ASoC utility code"); |
118 | MODULE_LICENSE("GPL v2"); | 91 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/fsl/fsl_utils.h b/sound/soc/fsl/fsl_utils.h index df535db40313..1687b66ef18e 100644 --- a/sound/soc/fsl/fsl_utils.h +++ b/sound/soc/fsl/fsl_utils.h | |||
@@ -22,7 +22,4 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, const char *name, | |||
22 | struct snd_soc_dai_link *dai, | 22 | struct snd_soc_dai_link *dai, |
23 | unsigned int *dma_channel_id, | 23 | unsigned int *dma_channel_id, |
24 | unsigned int *dma_id); | 24 | unsigned int *dma_id); |
25 | int fsl_asoc_xlate_tdm_slot_mask(unsigned int slots, | ||
26 | unsigned int *tx_mask, | ||
27 | unsigned int *rx_mask); | ||
28 | #endif /* _FSL_UTILS_H */ | 25 | #endif /* _FSL_UTILS_H */ |
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c index 6bf5bce01a92..9e6493d4e7ff 100644 --- a/sound/soc/fsl/imx-mc13783.c +++ b/sound/soc/fsl/imx-mc13783.c | |||
@@ -37,8 +37,7 @@ static int imx_mc13783_hifi_hw_params(struct snd_pcm_substream *substream, | |||
37 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 37 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
38 | int ret; | 38 | int ret; |
39 | 39 | ||
40 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xfffffffc, 0xfffffffc, | 40 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 4, 16); |
41 | 4, 16); | ||
42 | if (ret) | 41 | if (ret) |
43 | return ret; | 42 | return ret; |
44 | 43 | ||
@@ -46,7 +45,7 @@ static int imx_mc13783_hifi_hw_params(struct snd_pcm_substream *substream, | |||
46 | if (ret) | 45 | if (ret) |
47 | return ret; | 46 | return ret; |
48 | 47 | ||
49 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x0, 0xfffffffc, 2, 16); | 48 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 16); |
50 | if (ret) | 49 | if (ret) |
51 | return ret; | 50 | return ret; |
52 | 51 | ||
diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index e94704f1b9ee..33da26a12457 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c | |||
@@ -60,6 +60,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) | |||
60 | data->card.dev = &pdev->dev; | 60 | data->card.dev = &pdev->dev; |
61 | data->card.dai_link = &data->dai; | 61 | data->card.dai_link = &data->dai; |
62 | data->card.num_links = 1; | 62 | data->card.num_links = 1; |
63 | data->card.owner = THIS_MODULE; | ||
63 | 64 | ||
64 | ret = snd_soc_of_parse_card_name(&data->card, "model"); | 65 | ret = snd_soc_of_parse_card_name(&data->card, "model"); |
65 | if (ret) | 66 | if (ret) |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index fa801e17c51e..461ce27b884f 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
@@ -74,8 +74,8 @@ static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, | |||
74 | sccr |= SSI_STCCR_DC(slots - 1); | 74 | sccr |= SSI_STCCR_DC(slots - 1); |
75 | writel(sccr, ssi->base + SSI_SRCCR); | 75 | writel(sccr, ssi->base + SSI_SRCCR); |
76 | 76 | ||
77 | writel(tx_mask, ssi->base + SSI_STMSK); | 77 | writel(~tx_mask, ssi->base + SSI_STMSK); |
78 | writel(rx_mask, ssi->base + SSI_SRMSK); | 78 | writel(~rx_mask, ssi->base + SSI_SRMSK); |
79 | 79 | ||
80 | return 0; | 80 | return 0; |
81 | } | 81 | } |
@@ -340,7 +340,6 @@ static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { | |||
340 | .set_fmt = imx_ssi_set_dai_fmt, | 340 | .set_fmt = imx_ssi_set_dai_fmt, |
341 | .set_clkdiv = imx_ssi_set_dai_clkdiv, | 341 | .set_clkdiv = imx_ssi_set_dai_clkdiv, |
342 | .set_sysclk = imx_ssi_set_dai_sysclk, | 342 | .set_sysclk = imx_ssi_set_dai_sysclk, |
343 | .xlate_tdm_slot_mask = fsl_asoc_xlate_tdm_slot_mask, | ||
344 | .set_tdm_slot = imx_ssi_set_dai_tdm_slot, | 343 | .set_tdm_slot = imx_ssi_set_dai_tdm_slot, |
345 | .trigger = imx_ssi_trigger, | 344 | .trigger = imx_ssi_trigger, |
346 | }; | 345 | }; |
diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c index b1ced7b8d80c..198eeb3f3f7a 100644 --- a/sound/soc/fsl/mx27vis-aic32x4.c +++ b/sound/soc/fsl/mx27vis-aic32x4.c | |||
@@ -55,16 +55,6 @@ static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, | |||
55 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 55 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
56 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 56 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
57 | int ret; | 57 | int ret; |
58 | u32 dai_format; | ||
59 | |||
60 | dai_format = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | | ||
61 | SND_SOC_DAIFMT_CBM_CFM; | ||
62 | |||
63 | /* set codec DAI configuration */ | ||
64 | snd_soc_dai_set_fmt(codec_dai, dai_format); | ||
65 | |||
66 | /* set cpu DAI configuration */ | ||
67 | snd_soc_dai_set_fmt(cpu_dai, dai_format); | ||
68 | 58 | ||
69 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, | 59 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, |
70 | 25000000, SND_SOC_CLOCK_OUT); | 60 | 25000000, SND_SOC_CLOCK_OUT); |
@@ -164,6 +154,8 @@ static struct snd_soc_dai_link mx27vis_aic32x4_dai = { | |||
164 | .platform_name = "imx-ssi.0", | 154 | .platform_name = "imx-ssi.0", |
165 | .codec_name = "tlv320aic32x4.0-0018", | 155 | .codec_name = "tlv320aic32x4.0-0018", |
166 | .cpu_dai_name = "imx-ssi.0", | 156 | .cpu_dai_name = "imx-ssi.0", |
157 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | | ||
158 | SND_SOC_DAIFMT_CBM_CFM, | ||
167 | .ops = &mx27vis_aic32x4_snd_ops, | 159 | .ops = &mx27vis_aic32x4_snd_ops, |
168 | }; | 160 | }; |
169 | 161 | ||
diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c index 804749a6c61e..a958937ab405 100644 --- a/sound/soc/fsl/wm1133-ev1.c +++ b/sound/soc/fsl/wm1133-ev1.c | |||
@@ -87,7 +87,6 @@ static int wm1133_ev1_hw_params(struct snd_pcm_substream *substream, | |||
87 | snd_pcm_format_t format = params_format(params); | 87 | snd_pcm_format_t format = params_format(params); |
88 | unsigned int rate = params_rate(params); | 88 | unsigned int rate = params_rate(params); |
89 | unsigned int channels = params_channels(params); | 89 | unsigned int channels = params_channels(params); |
90 | u32 dai_format; | ||
91 | 90 | ||
92 | /* find the correct audio parameters */ | 91 | /* find the correct audio parameters */ |
93 | for (i = 0; i < ARRAY_SIZE(wm8350_audio); i++) { | 92 | for (i = 0; i < ARRAY_SIZE(wm8350_audio); i++) { |
@@ -104,22 +103,13 @@ static int wm1133_ev1_hw_params(struct snd_pcm_substream *substream, | |||
104 | /* codec FLL input is 14.75 MHz from MCLK */ | 103 | /* codec FLL input is 14.75 MHz from MCLK */ |
105 | snd_soc_dai_set_pll(codec_dai, 0, 0, 14750000, wm8350_audio[i].sysclk); | 104 | snd_soc_dai_set_pll(codec_dai, 0, 0, 14750000, wm8350_audio[i].sysclk); |
106 | 105 | ||
107 | dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
108 | SND_SOC_DAIFMT_CBM_CFM; | ||
109 | |||
110 | /* set codec DAI configuration */ | ||
111 | snd_soc_dai_set_fmt(codec_dai, dai_format); | ||
112 | |||
113 | /* set cpu DAI configuration */ | ||
114 | snd_soc_dai_set_fmt(cpu_dai, dai_format); | ||
115 | |||
116 | /* TODO: The SSI driver should figure this out for us */ | 106 | /* TODO: The SSI driver should figure this out for us */ |
117 | switch (channels) { | 107 | switch (channels) { |
118 | case 2: | 108 | case 2: |
119 | snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0); | 109 | snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 0); |
120 | break; | 110 | break; |
121 | case 1: | 111 | case 1: |
122 | snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffe, 0xffffffe, 1, 0); | 112 | snd_soc_dai_set_tdm_slot(cpu_dai, 0x1, 0x1, 1, 0); |
123 | break; | 113 | break; |
124 | default: | 114 | default: |
125 | return -EINVAL; | 115 | return -EINVAL; |
@@ -244,6 +234,8 @@ static struct snd_soc_dai_link wm1133_ev1_dai = { | |||
244 | .init = wm1133_ev1_init, | 234 | .init = wm1133_ev1_init, |
245 | .ops = &wm1133_ev1_ops, | 235 | .ops = &wm1133_ev1_ops, |
246 | .symmetric_rates = 1, | 236 | .symmetric_rates = 1, |
237 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
238 | SND_SOC_DAIFMT_CBM_CFM, | ||
247 | }; | 239 | }; |
248 | 240 | ||
249 | static struct snd_soc_card wm1133_ev1 = { | 241 | static struct snd_soc_card wm1133_ev1 = { |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 7fe3009b1c43..f7c6734bd5da 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -39,6 +39,37 @@ struct simple_card_data { | |||
39 | #define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i) | 39 | #define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i) |
40 | #define simple_priv_to_props(priv, i) ((priv)->dai_props + i) | 40 | #define simple_priv_to_props(priv, i) ((priv)->dai_props + i) |
41 | 41 | ||
42 | static int asoc_simple_card_startup(struct snd_pcm_substream *substream) | ||
43 | { | ||
44 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
45 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | ||
46 | struct simple_dai_props *dai_props = | ||
47 | &priv->dai_props[rtd - rtd->card->rtd]; | ||
48 | int ret; | ||
49 | |||
50 | ret = clk_prepare_enable(dai_props->cpu_dai.clk); | ||
51 | if (ret) | ||
52 | return ret; | ||
53 | |||
54 | ret = clk_prepare_enable(dai_props->codec_dai.clk); | ||
55 | if (ret) | ||
56 | clk_disable_unprepare(dai_props->cpu_dai.clk); | ||
57 | |||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) | ||
62 | { | ||
63 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
64 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | ||
65 | struct simple_dai_props *dai_props = | ||
66 | &priv->dai_props[rtd - rtd->card->rtd]; | ||
67 | |||
68 | clk_disable_unprepare(dai_props->cpu_dai.clk); | ||
69 | |||
70 | clk_disable_unprepare(dai_props->codec_dai.clk); | ||
71 | } | ||
72 | |||
42 | static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, | 73 | static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, |
43 | struct snd_pcm_hw_params *params) | 74 | struct snd_pcm_hw_params *params) |
44 | { | 75 | { |
@@ -58,6 +89,8 @@ static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, | |||
58 | } | 89 | } |
59 | 90 | ||
60 | static struct snd_soc_ops asoc_simple_card_ops = { | 91 | static struct snd_soc_ops asoc_simple_card_ops = { |
92 | .startup = asoc_simple_card_startup, | ||
93 | .shutdown = asoc_simple_card_shutdown, | ||
61 | .hw_params = asoc_simple_card_hw_params, | 94 | .hw_params = asoc_simple_card_hw_params, |
62 | }; | 95 | }; |
63 | 96 | ||
@@ -219,6 +252,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
219 | } | 252 | } |
220 | 253 | ||
221 | dai->sysclk = clk_get_rate(clk); | 254 | dai->sysclk = clk_get_rate(clk); |
255 | dai->clk = clk; | ||
222 | } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { | 256 | } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { |
223 | dai->sysclk = val; | 257 | dai->sysclk = val; |
224 | } else { | 258 | } else { |
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index f86de1211b96..ee03dbdda235 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -46,7 +46,7 @@ config SND_SOC_INTEL_BAYTRAIL | |||
46 | 46 | ||
47 | config SND_SOC_INTEL_HASWELL_MACH | 47 | config SND_SOC_INTEL_HASWELL_MACH |
48 | tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" | 48 | tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" |
49 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C && \\ | 49 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C && \ |
50 | I2C_DESIGNWARE_PLATFORM | 50 | I2C_DESIGNWARE_PLATFORM |
51 | select SND_SOC_INTEL_HASWELL | 51 | select SND_SOC_INTEL_HASWELL |
52 | select SND_SOC_RT5640 | 52 | select SND_SOC_RT5640 |
@@ -76,7 +76,7 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH | |||
76 | 76 | ||
77 | config SND_SOC_INTEL_BROADWELL_MACH | 77 | config SND_SOC_INTEL_BROADWELL_MACH |
78 | tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint" | 78 | tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint" |
79 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC && \\ | 79 | depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC && \ |
80 | I2C_DESIGNWARE_PLATFORM | 80 | I2C_DESIGNWARE_PLATFORM |
81 | select SND_SOC_INTEL_HASWELL | 81 | select SND_SOC_INTEL_HASWELL |
82 | select SND_COMPRESS_OFFLOAD | 82 | select SND_COMPRESS_OFFLOAD |
@@ -110,3 +110,14 @@ config SND_SOC_INTEL_CHT_BSW_RT5672_MACH | |||
110 | platforms with RT5672 audio codec. | 110 | platforms with RT5672 audio codec. |
111 | Say Y if you have such a device | 111 | Say Y if you have such a device |
112 | If unsure select "N". | 112 | If unsure select "N". |
113 | |||
114 | config SND_SOC_INTEL_CHT_BSW_RT5645_MACH | ||
115 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645 codec" | ||
116 | depends on X86_INTEL_LPSS | ||
117 | select SND_SOC_RT5645 | ||
118 | select SND_SST_MFLD_PLATFORM | ||
119 | select SND_SST_IPC_ACPI | ||
120 | help | ||
121 | This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell | ||
122 | platforms with RT5645 audio codec. | ||
123 | If unsure select "N". | ||
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index e928ec385300..a8e53c45c6b6 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile | |||
@@ -28,6 +28,7 @@ snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o | |||
28 | snd-soc-sst-broadwell-objs := broadwell.o | 28 | snd-soc-sst-broadwell-objs := broadwell.o |
29 | snd-soc-sst-bytcr-dpcm-rt5640-objs := bytcr_dpcm_rt5640.o | 29 | snd-soc-sst-bytcr-dpcm-rt5640-objs := bytcr_dpcm_rt5640.o |
30 | snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o | 30 | snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o |
31 | snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o | ||
31 | 32 | ||
32 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o | 33 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o |
33 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o | 34 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o |
@@ -35,6 +36,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o | |||
35 | obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o | 36 | obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o |
36 | obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-dpcm-rt5640.o | 37 | obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-dpcm-rt5640.o |
37 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o | 38 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o |
39 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o | ||
38 | 40 | ||
39 | # DSP driver | 41 | # DSP driver |
40 | obj-$(CONFIG_SND_SST_IPC) += sst/ | 42 | obj-$(CONFIG_SND_SST_IPC) += sst/ |
diff --git a/sound/soc/intel/broadwell.c b/sound/soc/intel/broadwell.c index 7cf95d5d5d80..9cf7d01479ad 100644 --- a/sound/soc/intel/broadwell.c +++ b/sound/soc/intel/broadwell.c | |||
@@ -140,8 +140,6 @@ static struct snd_soc_ops broadwell_rt286_ops = { | |||
140 | 140 | ||
141 | static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) | 141 | static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) |
142 | { | 142 | { |
143 | struct snd_soc_codec *codec = rtd->codec; | ||
144 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
145 | struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev); | 143 | struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev); |
146 | struct sst_hsw *broadwell = pdata->dsp; | 144 | struct sst_hsw *broadwell = pdata->dsp; |
147 | int ret; | 145 | int ret; |
@@ -155,14 +153,6 @@ static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) | |||
155 | return ret; | 153 | return ret; |
156 | } | 154 | } |
157 | 155 | ||
158 | /* always connected - check HP for jack detect */ | ||
159 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | ||
160 | snd_soc_dapm_enable_pin(dapm, "Speaker"); | ||
161 | snd_soc_dapm_enable_pin(dapm, "Mic Jack"); | ||
162 | snd_soc_dapm_enable_pin(dapm, "Line Jack"); | ||
163 | snd_soc_dapm_enable_pin(dapm, "DMIC1"); | ||
164 | snd_soc_dapm_enable_pin(dapm, "DMIC2"); | ||
165 | |||
166 | return 0; | 156 | return 0; |
167 | } | 157 | } |
168 | 158 | ||
diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c index 0cba7830c5e9..354eaad886e1 100644 --- a/sound/soc/intel/byt-rt5640.c +++ b/sound/soc/intel/byt-rt5640.c | |||
@@ -132,7 +132,6 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) | |||
132 | { | 132 | { |
133 | int ret; | 133 | int ret; |
134 | struct snd_soc_codec *codec = runtime->codec; | 134 | struct snd_soc_codec *codec = runtime->codec; |
135 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
136 | struct snd_soc_card *card = runtime->card; | 135 | struct snd_soc_card *card = runtime->card; |
137 | const struct snd_soc_dapm_route *custom_map; | 136 | const struct snd_soc_dapm_route *custom_map; |
138 | int num_routes; | 137 | int num_routes; |
@@ -161,7 +160,7 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) | |||
161 | num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); | 160 | num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); |
162 | } | 161 | } |
163 | 162 | ||
164 | ret = snd_soc_dapm_add_routes(dapm, custom_map, num_routes); | 163 | ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); |
165 | if (ret) | 164 | if (ret) |
166 | return ret; | 165 | return ret; |
167 | 166 | ||
@@ -171,13 +170,8 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) | |||
171 | return ret; | 170 | return ret; |
172 | } | 171 | } |
173 | 172 | ||
174 | snd_soc_dapm_ignore_suspend(dapm, "HPOL"); | 173 | snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); |
175 | snd_soc_dapm_ignore_suspend(dapm, "HPOR"); | 174 | snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); |
176 | |||
177 | snd_soc_dapm_ignore_suspend(dapm, "SPOLP"); | ||
178 | snd_soc_dapm_ignore_suspend(dapm, "SPOLN"); | ||
179 | snd_soc_dapm_ignore_suspend(dapm, "SPORP"); | ||
180 | snd_soc_dapm_ignore_suspend(dapm, "SPORN"); | ||
181 | 175 | ||
182 | return ret; | 176 | return ret; |
183 | } | 177 | } |
diff --git a/sound/soc/intel/bytcr_dpcm_rt5640.c b/sound/soc/intel/bytcr_dpcm_rt5640.c index eef0c56ec32e..59308629043e 100644 --- a/sound/soc/intel/bytcr_dpcm_rt5640.c +++ b/sound/soc/intel/bytcr_dpcm_rt5640.c | |||
@@ -215,7 +215,6 @@ static int snd_byt_mc_probe(struct platform_device *pdev) | |||
215 | 215 | ||
216 | static struct platform_driver snd_byt_mc_driver = { | 216 | static struct platform_driver snd_byt_mc_driver = { |
217 | .driver = { | 217 | .driver = { |
218 | .owner = THIS_MODULE, | ||
219 | .name = "bytt100_rt5640", | 218 | .name = "bytt100_rt5640", |
220 | .pm = &snd_soc_pm_ops, | 219 | .pm = &snd_soc_pm_ops, |
221 | }, | 220 | }, |
diff --git a/sound/soc/intel/cht_bsw_rt5645.c b/sound/soc/intel/cht_bsw_rt5645.c new file mode 100644 index 000000000000..bd29617a9ab9 --- /dev/null +++ b/sound/soc/intel/cht_bsw_rt5645.c | |||
@@ -0,0 +1,326 @@ | |||
1 | /* | ||
2 | * cht-bsw-rt5645.c - ASoc Machine driver for Intel Cherryview-based platforms | ||
3 | * Cherrytrail and Braswell, with RT5645 codec. | ||
4 | * | ||
5 | * Copyright (C) 2015 Intel Corp | ||
6 | * Author: Fang, Yang A <yang.a.fang@intel.com> | ||
7 | * N,Harshapriya <harshapriya.n@intel.com> | ||
8 | * This file is modified from cht_bsw_rt5672.c | ||
9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; version 2 of the License. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/pcm_params.h> | ||
28 | #include <sound/soc.h> | ||
29 | #include <sound/jack.h> | ||
30 | #include "../codecs/rt5645.h" | ||
31 | #include "sst-atom-controls.h" | ||
32 | |||
33 | #define CHT_PLAT_CLK_3_HZ 19200000 | ||
34 | #define CHT_CODEC_DAI "rt5645-aif1" | ||
35 | |||
36 | struct cht_mc_private { | ||
37 | struct snd_soc_jack hp_jack; | ||
38 | struct snd_soc_jack mic_jack; | ||
39 | }; | ||
40 | |||
41 | static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) | ||
42 | { | ||
43 | int i; | ||
44 | |||
45 | for (i = 0; i < card->num_rtd; i++) { | ||
46 | struct snd_soc_pcm_runtime *rtd; | ||
47 | |||
48 | rtd = card->rtd + i; | ||
49 | if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI, | ||
50 | strlen(CHT_CODEC_DAI))) | ||
51 | return rtd->codec_dai; | ||
52 | } | ||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | static int platform_clock_control(struct snd_soc_dapm_widget *w, | ||
57 | struct snd_kcontrol *k, int event) | ||
58 | { | ||
59 | struct snd_soc_dapm_context *dapm = w->dapm; | ||
60 | struct snd_soc_card *card = dapm->card; | ||
61 | struct snd_soc_dai *codec_dai; | ||
62 | int ret; | ||
63 | |||
64 | codec_dai = cht_get_codec_dai(card); | ||
65 | if (!codec_dai) { | ||
66 | dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n"); | ||
67 | return -EIO; | ||
68 | } | ||
69 | |||
70 | if (!SND_SOC_DAPM_EVENT_OFF(event)) | ||
71 | return 0; | ||
72 | |||
73 | /* Set codec sysclk source to its internal clock because codec PLL will | ||
74 | * be off when idle and MCLK will also be off by ACPI when codec is | ||
75 | * runtime suspended. Codec needs clock for jack detection and button | ||
76 | * press. | ||
77 | */ | ||
78 | ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_RCCLK, | ||
79 | 0, SND_SOC_CLOCK_IN); | ||
80 | if (ret < 0) { | ||
81 | dev_err(card->dev, "can't set codec sysclk: %d\n", ret); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static const struct snd_soc_dapm_widget cht_dapm_widgets[] = { | ||
89 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
90 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
91 | SND_SOC_DAPM_MIC("Int Mic", NULL), | ||
92 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | ||
93 | SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, | ||
94 | platform_clock_control, SND_SOC_DAPM_POST_PMD), | ||
95 | }; | ||
96 | |||
97 | static const struct snd_soc_dapm_route cht_audio_map[] = { | ||
98 | {"IN1P", NULL, "Headset Mic"}, | ||
99 | {"IN1N", NULL, "Headset Mic"}, | ||
100 | {"DMIC L1", NULL, "Int Mic"}, | ||
101 | {"DMIC R1", NULL, "Int Mic"}, | ||
102 | {"Headphone", NULL, "HPOL"}, | ||
103 | {"Headphone", NULL, "HPOR"}, | ||
104 | {"Ext Spk", NULL, "SPOL"}, | ||
105 | {"Ext Spk", NULL, "SPOR"}, | ||
106 | {"AIF1 Playback", NULL, "ssp2 Tx"}, | ||
107 | {"ssp2 Tx", NULL, "codec_out0"}, | ||
108 | {"ssp2 Tx", NULL, "codec_out1"}, | ||
109 | {"codec_in0", NULL, "ssp2 Rx" }, | ||
110 | {"codec_in1", NULL, "ssp2 Rx" }, | ||
111 | {"ssp2 Rx", NULL, "AIF1 Capture"}, | ||
112 | {"Headphone", NULL, "Platform Clock"}, | ||
113 | {"Headset Mic", NULL, "Platform Clock"}, | ||
114 | {"Int Mic", NULL, "Platform Clock"}, | ||
115 | {"Ext Spk", NULL, "Platform Clock"}, | ||
116 | }; | ||
117 | |||
118 | static const struct snd_kcontrol_new cht_mc_controls[] = { | ||
119 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
120 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
121 | SOC_DAPM_PIN_SWITCH("Int Mic"), | ||
122 | SOC_DAPM_PIN_SWITCH("Ext Spk"), | ||
123 | }; | ||
124 | |||
125 | static int cht_aif1_hw_params(struct snd_pcm_substream *substream, | ||
126 | struct snd_pcm_hw_params *params) | ||
127 | { | ||
128 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
129 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
130 | int ret; | ||
131 | |||
132 | /* set codec PLL source to the 19.2MHz platform clock (MCLK) */ | ||
133 | ret = snd_soc_dai_set_pll(codec_dai, 0, RT5645_PLL1_S_MCLK, | ||
134 | CHT_PLAT_CLK_3_HZ, params_rate(params) * 512); | ||
135 | if (ret < 0) { | ||
136 | dev_err(rtd->dev, "can't set codec pll: %d\n", ret); | ||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | ret = snd_soc_dai_set_sysclk(codec_dai, RT5645_SCLK_S_PLL1, | ||
141 | params_rate(params) * 512, SND_SOC_CLOCK_IN); | ||
142 | if (ret < 0) { | ||
143 | dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret); | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | ||
151 | { | ||
152 | int ret; | ||
153 | struct snd_soc_codec *codec = runtime->codec; | ||
154 | struct snd_soc_dai *codec_dai = runtime->codec_dai; | ||
155 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card); | ||
156 | |||
157 | /* Select clk_i2s1_asrc as ASRC clock source */ | ||
158 | rt5645_sel_asrc_clk_src(codec, | ||
159 | RT5645_DA_STEREO_FILTER | | ||
160 | RT5645_DA_MONO_L_FILTER | | ||
161 | RT5645_DA_MONO_R_FILTER | | ||
162 | RT5645_AD_STEREO_FILTER, | ||
163 | RT5645_CLK_SEL_I2S1_ASRC); | ||
164 | |||
165 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ | ||
166 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); | ||
167 | if (ret < 0) { | ||
168 | dev_err(runtime->dev, "can't set codec TDM slot %d\n", ret); | ||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | ret = snd_soc_jack_new(codec, "Headphone Jack", | ||
173 | SND_JACK_HEADPHONE, | ||
174 | &ctx->hp_jack); | ||
175 | if (ret) { | ||
176 | dev_err(runtime->dev, "HP jack creation failed %d\n", ret); | ||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | ret = snd_soc_jack_new(codec, "Mic Jack", | ||
181 | SND_JACK_MICROPHONE, | ||
182 | &ctx->mic_jack); | ||
183 | if (ret) { | ||
184 | dev_err(runtime->dev, "Mic jack creation failed %d\n", ret); | ||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | rt5645_set_jack_detect(codec, &ctx->hp_jack, &ctx->mic_jack); | ||
189 | |||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, | ||
194 | struct snd_pcm_hw_params *params) | ||
195 | { | ||
196 | struct snd_interval *rate = hw_param_interval(params, | ||
197 | SNDRV_PCM_HW_PARAM_RATE); | ||
198 | struct snd_interval *channels = hw_param_interval(params, | ||
199 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
200 | |||
201 | /* The DSP will covert the FE rate to 48k, stereo, 24bits */ | ||
202 | rate->min = rate->max = 48000; | ||
203 | channels->min = channels->max = 2; | ||
204 | |||
205 | /* set SSP2 to 24-bit */ | ||
206 | snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - | ||
207 | SNDRV_PCM_HW_PARAM_FIRST_MASK], | ||
208 | SNDRV_PCM_FORMAT_S24_LE); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static unsigned int rates_48000[] = { | ||
213 | 48000, | ||
214 | }; | ||
215 | |||
216 | static struct snd_pcm_hw_constraint_list constraints_48000 = { | ||
217 | .count = ARRAY_SIZE(rates_48000), | ||
218 | .list = rates_48000, | ||
219 | }; | ||
220 | |||
221 | static int cht_aif1_startup(struct snd_pcm_substream *substream) | ||
222 | { | ||
223 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
224 | SNDRV_PCM_HW_PARAM_RATE, | ||
225 | &constraints_48000); | ||
226 | } | ||
227 | |||
228 | static struct snd_soc_ops cht_aif1_ops = { | ||
229 | .startup = cht_aif1_startup, | ||
230 | }; | ||
231 | |||
232 | static struct snd_soc_ops cht_be_ssp2_ops = { | ||
233 | .hw_params = cht_aif1_hw_params, | ||
234 | }; | ||
235 | |||
236 | static struct snd_soc_dai_link cht_dailink[] = { | ||
237 | [MERR_DPCM_AUDIO] = { | ||
238 | .name = "Audio Port", | ||
239 | .stream_name = "Audio", | ||
240 | .cpu_dai_name = "media-cpu-dai", | ||
241 | .codec_dai_name = "snd-soc-dummy-dai", | ||
242 | .codec_name = "snd-soc-dummy", | ||
243 | .platform_name = "sst-mfld-platform", | ||
244 | .ignore_suspend = 1, | ||
245 | .dynamic = 1, | ||
246 | .dpcm_playback = 1, | ||
247 | .dpcm_capture = 1, | ||
248 | .ops = &cht_aif1_ops, | ||
249 | }, | ||
250 | [MERR_DPCM_COMPR] = { | ||
251 | .name = "Compressed Port", | ||
252 | .stream_name = "Compress", | ||
253 | .cpu_dai_name = "compress-cpu-dai", | ||
254 | .codec_dai_name = "snd-soc-dummy-dai", | ||
255 | .codec_name = "snd-soc-dummy", | ||
256 | .platform_name = "sst-mfld-platform", | ||
257 | }, | ||
258 | /* CODEC<->CODEC link */ | ||
259 | /* back ends */ | ||
260 | { | ||
261 | .name = "SSP2-Codec", | ||
262 | .be_id = 1, | ||
263 | .cpu_dai_name = "ssp2-port", | ||
264 | .platform_name = "sst-mfld-platform", | ||
265 | .no_pcm = 1, | ||
266 | .codec_dai_name = "rt5645-aif1", | ||
267 | .codec_name = "i2c-10EC5645:00", | ||
268 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | ||
269 | | SND_SOC_DAIFMT_CBS_CFS, | ||
270 | .init = cht_codec_init, | ||
271 | .be_hw_params_fixup = cht_codec_fixup, | ||
272 | .ignore_suspend = 1, | ||
273 | .dpcm_playback = 1, | ||
274 | .dpcm_capture = 1, | ||
275 | .ops = &cht_be_ssp2_ops, | ||
276 | }, | ||
277 | }; | ||
278 | |||
279 | /* SoC card */ | ||
280 | static struct snd_soc_card snd_soc_card_cht = { | ||
281 | .name = "chtrt5645", | ||
282 | .dai_link = cht_dailink, | ||
283 | .num_links = ARRAY_SIZE(cht_dailink), | ||
284 | .dapm_widgets = cht_dapm_widgets, | ||
285 | .num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets), | ||
286 | .dapm_routes = cht_audio_map, | ||
287 | .num_dapm_routes = ARRAY_SIZE(cht_audio_map), | ||
288 | .controls = cht_mc_controls, | ||
289 | .num_controls = ARRAY_SIZE(cht_mc_controls), | ||
290 | }; | ||
291 | |||
292 | static int snd_cht_mc_probe(struct platform_device *pdev) | ||
293 | { | ||
294 | int ret_val = 0; | ||
295 | struct cht_mc_private *drv; | ||
296 | |||
297 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); | ||
298 | if (!drv) | ||
299 | return -ENOMEM; | ||
300 | |||
301 | snd_soc_card_cht.dev = &pdev->dev; | ||
302 | snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); | ||
303 | ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); | ||
304 | if (ret_val) { | ||
305 | dev_err(&pdev->dev, | ||
306 | "snd_soc_register_card failed %d\n", ret_val); | ||
307 | return ret_val; | ||
308 | } | ||
309 | platform_set_drvdata(pdev, &snd_soc_card_cht); | ||
310 | return ret_val; | ||
311 | } | ||
312 | |||
313 | static struct platform_driver snd_cht_mc_driver = { | ||
314 | .driver = { | ||
315 | .name = "cht-bsw-rt5645", | ||
316 | .pm = &snd_soc_pm_ops, | ||
317 | }, | ||
318 | .probe = snd_cht_mc_probe, | ||
319 | }; | ||
320 | |||
321 | module_platform_driver(snd_cht_mc_driver) | ||
322 | |||
323 | MODULE_DESCRIPTION("ASoC Intel(R) Braswell Machine driver"); | ||
324 | MODULE_AUTHOR("Fang, Yang A,N,Harshapriya"); | ||
325 | MODULE_LICENSE("GPL v2"); | ||
326 | MODULE_ALIAS("platform:cht-bsw-rt5645"); | ||
diff --git a/sound/soc/intel/cht_bsw_rt5672.c b/sound/soc/intel/cht_bsw_rt5672.c index 9b8b561171b7..ff016621583a 100644 --- a/sound/soc/intel/cht_bsw_rt5672.c +++ b/sound/soc/intel/cht_bsw_rt5672.c | |||
@@ -140,6 +140,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | |||
140 | { | 140 | { |
141 | int ret; | 141 | int ret; |
142 | struct snd_soc_dai *codec_dai = runtime->codec_dai; | 142 | struct snd_soc_dai *codec_dai = runtime->codec_dai; |
143 | struct snd_soc_codec *codec = codec_dai->codec; | ||
143 | 144 | ||
144 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ | 145 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ |
145 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); | 146 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); |
@@ -148,6 +149,19 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | |||
148 | return ret; | 149 | return ret; |
149 | } | 150 | } |
150 | 151 | ||
152 | /* Select codec ASRC clock source to track I2S1 clock, because codec | ||
153 | * is in slave mode and 100fs I2S format (BCLK = 100 * LRCLK) cannot | ||
154 | * be supported by RT5672. Otherwise, ASRC will be disabled and cause | ||
155 | * noise. | ||
156 | */ | ||
157 | rt5670_sel_asrc_clk_src(codec, | ||
158 | RT5670_DA_STEREO_FILTER | ||
159 | | RT5670_DA_MONO_L_FILTER | ||
160 | | RT5670_DA_MONO_R_FILTER | ||
161 | | RT5670_AD_STEREO_FILTER | ||
162 | | RT5670_AD_MONO_L_FILTER | ||
163 | | RT5670_AD_MONO_R_FILTER, | ||
164 | RT5670_CLK_SEL_I2S1_ASRC); | ||
151 | return 0; | 165 | return 0; |
152 | } | 166 | } |
153 | 167 | ||
@@ -270,7 +284,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev) | |||
270 | 284 | ||
271 | static struct platform_driver snd_cht_mc_driver = { | 285 | static struct platform_driver snd_cht_mc_driver = { |
272 | .driver = { | 286 | .driver = { |
273 | .owner = THIS_MODULE, | ||
274 | .name = "cht-bsw-rt5672", | 287 | .name = "cht-bsw-rt5672", |
275 | .pm = &snd_soc_pm_ops, | 288 | .pm = &snd_soc_pm_ops, |
276 | }, | 289 | }, |
diff --git a/sound/soc/intel/sst-atom-controls.h b/sound/soc/intel/sst-atom-controls.h index dfebfdd5eb2a..daecc58f28af 100644 --- a/sound/soc/intel/sst-atom-controls.h +++ b/sound/soc/intel/sst-atom-controls.h | |||
@@ -150,7 +150,7 @@ enum sst_cmd_type { | |||
150 | 150 | ||
151 | enum sst_task { | 151 | enum sst_task { |
152 | SST_TASK_SBA = 1, | 152 | SST_TASK_SBA = 1, |
153 | SST_TASK_MMX, | 153 | SST_TASK_MMX = 3, |
154 | }; | 154 | }; |
155 | 155 | ||
156 | enum sst_type { | 156 | enum sst_type { |
diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/sst-baytrail-pcm.c index 3bb6288d8b4d..224c49c9f135 100644 --- a/sound/soc/intel/sst-baytrail-pcm.c +++ b/sound/soc/intel/sst-baytrail-pcm.c | |||
@@ -320,11 +320,6 @@ static struct snd_pcm_ops sst_byt_pcm_ops = { | |||
320 | .mmap = sst_byt_pcm_mmap, | 320 | .mmap = sst_byt_pcm_mmap, |
321 | }; | 321 | }; |
322 | 322 | ||
323 | static void sst_byt_pcm_free(struct snd_pcm *pcm) | ||
324 | { | ||
325 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
326 | } | ||
327 | |||
328 | static int sst_byt_pcm_new(struct snd_soc_pcm_runtime *rtd) | 323 | static int sst_byt_pcm_new(struct snd_soc_pcm_runtime *rtd) |
329 | { | 324 | { |
330 | struct snd_pcm *pcm = rtd->pcm; | 325 | struct snd_pcm *pcm = rtd->pcm; |
@@ -403,7 +398,6 @@ static struct snd_soc_platform_driver byt_soc_platform = { | |||
403 | .remove = sst_byt_pcm_remove, | 398 | .remove = sst_byt_pcm_remove, |
404 | .ops = &sst_byt_pcm_ops, | 399 | .ops = &sst_byt_pcm_ops, |
405 | .pcm_new = sst_byt_pcm_new, | 400 | .pcm_new = sst_byt_pcm_new, |
406 | .pcm_free = sst_byt_pcm_free, | ||
407 | }; | 401 | }; |
408 | 402 | ||
409 | static const struct snd_soc_component_driver byt_dai_component = { | 403 | static const struct snd_soc_component_driver byt_dai_component = { |
diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c index 86e410845670..64e94212d2d2 100644 --- a/sound/soc/intel/sst-dsp.c +++ b/sound/soc/intel/sst-dsp.c | |||
@@ -410,8 +410,7 @@ void sst_dsp_free(struct sst_dsp *sst) | |||
410 | if (sst->ops->free) | 410 | if (sst->ops->free) |
411 | sst->ops->free(sst); | 411 | sst->ops->free(sst); |
412 | 412 | ||
413 | if (sst->dma) | 413 | sst_dma_free(sst->dma); |
414 | sst_dma_free(sst->dma); | ||
415 | } | 414 | } |
416 | EXPORT_SYMBOL_GPL(sst_dsp_free); | 415 | EXPORT_SYMBOL_GPL(sst_dsp_free); |
417 | 416 | ||
diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c index b3f9489794a6..5f71ef607a57 100644 --- a/sound/soc/intel/sst-firmware.c +++ b/sound/soc/intel/sst-firmware.c | |||
@@ -497,6 +497,7 @@ struct sst_module *sst_module_new(struct sst_fw *sst_fw, | |||
497 | sst_module->sst_fw = sst_fw; | 497 | sst_module->sst_fw = sst_fw; |
498 | sst_module->scratch_size = template->scratch_size; | 498 | sst_module->scratch_size = template->scratch_size; |
499 | sst_module->persistent_size = template->persistent_size; | 499 | sst_module->persistent_size = template->persistent_size; |
500 | sst_module->entry = template->entry; | ||
500 | 501 | ||
501 | INIT_LIST_HEAD(&sst_module->block_list); | 502 | INIT_LIST_HEAD(&sst_module->block_list); |
502 | INIT_LIST_HEAD(&sst_module->runtime_list); | 503 | INIT_LIST_HEAD(&sst_module->runtime_list); |
@@ -790,6 +791,7 @@ int sst_module_alloc_blocks(struct sst_module *module) | |||
790 | struct sst_block_allocator ba; | 791 | struct sst_block_allocator ba; |
791 | int ret; | 792 | int ret; |
792 | 793 | ||
794 | memset(&ba, 0, sizeof(ba)); | ||
793 | ba.size = module->size; | 795 | ba.size = module->size; |
794 | ba.type = module->type; | 796 | ba.type = module->type; |
795 | ba.offset = module->offset; | 797 | ba.offset = module->offset; |
@@ -863,6 +865,7 @@ int sst_module_runtime_alloc_blocks(struct sst_module_runtime *runtime, | |||
863 | if (module->persistent_size == 0) | 865 | if (module->persistent_size == 0) |
864 | return 0; | 866 | return 0; |
865 | 867 | ||
868 | memset(&ba, 0, sizeof(ba)); | ||
866 | ba.size = module->persistent_size; | 869 | ba.size = module->persistent_size; |
867 | ba.type = SST_MEM_DRAM; | 870 | ba.type = SST_MEM_DRAM; |
868 | 871 | ||
diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c index 57039b00efc2..c42ffae5fe9f 100644 --- a/sound/soc/intel/sst-haswell-dsp.c +++ b/sound/soc/intel/sst-haswell-dsp.c | |||
@@ -306,7 +306,7 @@ static void hsw_reset(struct sst_dsp *sst) | |||
306 | static int hsw_set_dsp_D0(struct sst_dsp *sst) | 306 | static int hsw_set_dsp_D0(struct sst_dsp *sst) |
307 | { | 307 | { |
308 | int tries = 10; | 308 | int tries = 10; |
309 | u32 reg; | 309 | u32 reg, fw_dump_bit; |
310 | 310 | ||
311 | /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */ | 311 | /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */ |
312 | reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); | 312 | reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); |
@@ -368,7 +368,9 @@ finish: | |||
368 | can't be accessed, please enable each block before accessing. */ | 368 | can't be accessed, please enable each block before accessing. */ |
369 | reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0); | 369 | reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0); |
370 | reg |= SST_VDRTCL0_DSRAMPGE_MASK | SST_VDRTCL0_ISRAMPGE_MASK; | 370 | reg |= SST_VDRTCL0_DSRAMPGE_MASK | SST_VDRTCL0_ISRAMPGE_MASK; |
371 | writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0); | 371 | /* for D0, always enable the block(DSRAM[0]) used for FW dump */ |
372 | fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT; | ||
373 | writel(reg & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0); | ||
372 | 374 | ||
373 | 375 | ||
374 | /* disable DMA finish function for SSP0 & SSP1 */ | 376 | /* disable DMA finish function for SSP0 & SSP1 */ |
@@ -491,6 +493,7 @@ static const struct sst_sram_shift sram_shift[] = { | |||
491 | {SST_DEV_ID_LYNX_POINT, 6, 16}, /* lp */ | 493 | {SST_DEV_ID_LYNX_POINT, 6, 16}, /* lp */ |
492 | {SST_DEV_ID_WILDCAT_POINT, 2, 12}, /* wpt */ | 494 | {SST_DEV_ID_WILDCAT_POINT, 2, 12}, /* wpt */ |
493 | }; | 495 | }; |
496 | |||
494 | static u32 hsw_block_get_bit(struct sst_mem_block *block) | 497 | static u32 hsw_block_get_bit(struct sst_mem_block *block) |
495 | { | 498 | { |
496 | u32 bit = 0, shift = 0, index; | 499 | u32 bit = 0, shift = 0, index; |
@@ -587,7 +590,9 @@ static int hsw_block_disable(struct sst_mem_block *block) | |||
587 | 590 | ||
588 | val = readl(sst->addr.pci_cfg + SST_VDRTCTL0); | 591 | val = readl(sst->addr.pci_cfg + SST_VDRTCTL0); |
589 | bit = hsw_block_get_bit(block); | 592 | bit = hsw_block_get_bit(block); |
590 | writel(val | bit, sst->addr.pci_cfg + SST_VDRTCTL0); | 593 | /* don't disable DSRAM[0], keep it always enable for FW dump*/ |
594 | if (bit != (1 << SST_VDRTCL0_DSRAMPGE_SHIFT)) | ||
595 | writel(val | bit, sst->addr.pci_cfg + SST_VDRTCTL0); | ||
591 | 596 | ||
592 | /* wait 18 DSP clock ticks */ | 597 | /* wait 18 DSP clock ticks */ |
593 | udelay(10); | 598 | udelay(10); |
@@ -612,7 +617,7 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) | |||
612 | const struct sst_adsp_memregion *region; | 617 | const struct sst_adsp_memregion *region; |
613 | struct device *dev; | 618 | struct device *dev; |
614 | int ret = -ENODEV, i, j, region_count; | 619 | int ret = -ENODEV, i, j, region_count; |
615 | u32 offset, size; | 620 | u32 offset, size, fw_dump_bit; |
616 | 621 | ||
617 | dev = sst->dma_dev; | 622 | dev = sst->dma_dev; |
618 | 623 | ||
@@ -669,9 +674,11 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) | |||
669 | } | 674 | } |
670 | } | 675 | } |
671 | 676 | ||
677 | /* always enable the block(DSRAM[0]) used for FW dump */ | ||
678 | fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT; | ||
672 | /* set default power gating control, enable power gating control for all blocks. that is, | 679 | /* set default power gating control, enable power gating control for all blocks. that is, |
673 | can't be accessed, please enable each block before accessing. */ | 680 | can't be accessed, please enable each block before accessing. */ |
674 | writel(0xffffffff, sst->addr.pci_cfg + SST_VDRTCTL0); | 681 | writel(0xffffffff & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0); |
675 | 682 | ||
676 | return 0; | 683 | return 0; |
677 | } | 684 | } |
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index 8156cc1accb7..394af5684c05 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/dma-mapping.h> | 31 | #include <linux/dma-mapping.h> |
32 | #include <linux/debugfs.h> | 32 | #include <linux/debugfs.h> |
33 | #include <linux/pm_runtime.h> | 33 | #include <linux/pm_runtime.h> |
34 | #include <sound/asound.h> | ||
34 | 35 | ||
35 | #include "sst-haswell-ipc.h" | 36 | #include "sst-haswell-ipc.h" |
36 | #include "sst-dsp.h" | 37 | #include "sst-dsp.h" |
@@ -94,6 +95,8 @@ | |||
94 | /* Mailbox */ | 95 | /* Mailbox */ |
95 | #define IPC_MAX_MAILBOX_BYTES 256 | 96 | #define IPC_MAX_MAILBOX_BYTES 256 |
96 | 97 | ||
98 | #define INVALID_STREAM_HW_ID 0xffffffff | ||
99 | |||
97 | /* Global Message - Types and Replies */ | 100 | /* Global Message - Types and Replies */ |
98 | enum ipc_glb_type { | 101 | enum ipc_glb_type { |
99 | IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */ | 102 | IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */ |
@@ -240,6 +243,9 @@ struct sst_hsw_stream { | |||
240 | u32 (*notify_position)(struct sst_hsw_stream *stream, void *data); | 243 | u32 (*notify_position)(struct sst_hsw_stream *stream, void *data); |
241 | void *pdata; | 244 | void *pdata; |
242 | 245 | ||
246 | /* record the fw read position when playback */ | ||
247 | snd_pcm_uframes_t old_position; | ||
248 | bool play_silence; | ||
243 | struct list_head node; | 249 | struct list_head node; |
244 | }; | 250 | }; |
245 | 251 | ||
@@ -275,7 +281,6 @@ struct sst_hsw { | |||
275 | /* FW config */ | 281 | /* FW config */ |
276 | struct sst_hsw_ipc_fw_ready fw_ready; | 282 | struct sst_hsw_ipc_fw_ready fw_ready; |
277 | struct sst_hsw_ipc_fw_version version; | 283 | struct sst_hsw_ipc_fw_version version; |
278 | struct sst_module *scratch; | ||
279 | bool fw_done; | 284 | bool fw_done; |
280 | struct sst_fw *sst_fw; | 285 | struct sst_fw *sst_fw; |
281 | 286 | ||
@@ -337,12 +342,6 @@ static inline u32 msg_get_stage_type(u32 msg) | |||
337 | return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; | 342 | return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; |
338 | } | 343 | } |
339 | 344 | ||
340 | static inline u32 msg_set_stage_type(u32 msg, u32 type) | ||
341 | { | ||
342 | return (msg & ~IPC_STG_TYPE_MASK) + | ||
343 | (type << IPC_STG_TYPE_SHIFT); | ||
344 | } | ||
345 | |||
346 | static inline u32 msg_get_stream_id(u32 msg) | 345 | static inline u32 msg_get_stream_id(u32 msg) |
347 | { | 346 | { |
348 | return (msg & IPC_STR_ID_MASK) >> IPC_STR_ID_SHIFT; | 347 | return (msg & IPC_STR_ID_MASK) >> IPC_STR_ID_SHIFT; |
@@ -969,45 +968,6 @@ int sst_hsw_fw_get_version(struct sst_hsw *hsw, | |||
969 | } | 968 | } |
970 | 969 | ||
971 | /* Mixer Controls */ | 970 | /* Mixer Controls */ |
972 | int sst_hsw_stream_mute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
973 | u32 stage_id, u32 channel) | ||
974 | { | ||
975 | int ret; | ||
976 | |||
977 | ret = sst_hsw_stream_get_volume(hsw, stream, stage_id, channel, | ||
978 | &stream->mute_volume[channel]); | ||
979 | if (ret < 0) | ||
980 | return ret; | ||
981 | |||
982 | ret = sst_hsw_stream_set_volume(hsw, stream, stage_id, channel, 0); | ||
983 | if (ret < 0) { | ||
984 | dev_err(hsw->dev, "error: can't unmute stream %d channel %d\n", | ||
985 | stream->reply.stream_hw_id, channel); | ||
986 | return ret; | ||
987 | } | ||
988 | |||
989 | stream->mute[channel] = 1; | ||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | int sst_hsw_stream_unmute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
994 | u32 stage_id, u32 channel) | ||
995 | |||
996 | { | ||
997 | int ret; | ||
998 | |||
999 | stream->mute[channel] = 0; | ||
1000 | ret = sst_hsw_stream_set_volume(hsw, stream, stage_id, channel, | ||
1001 | stream->mute_volume[channel]); | ||
1002 | if (ret < 0) { | ||
1003 | dev_err(hsw->dev, "error: can't unmute stream %d channel %d\n", | ||
1004 | stream->reply.stream_hw_id, channel); | ||
1005 | return ret; | ||
1006 | } | ||
1007 | |||
1008 | return 0; | ||
1009 | } | ||
1010 | |||
1011 | int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | 971 | int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, |
1012 | u32 stage_id, u32 channel, u32 *volume) | 972 | u32 stage_id, u32 channel, u32 *volume) |
1013 | { | 973 | { |
@@ -1021,17 +981,6 @@ int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream | |||
1021 | return 0; | 981 | return 0; |
1022 | } | 982 | } |
1023 | 983 | ||
1024 | int sst_hsw_stream_set_volume_curve(struct sst_hsw *hsw, | ||
1025 | struct sst_hsw_stream *stream, u64 curve_duration, | ||
1026 | enum sst_hsw_volume_curve curve) | ||
1027 | { | ||
1028 | /* curve duration in steps of 100ns */ | ||
1029 | stream->vol_req.curve_duration = curve_duration; | ||
1030 | stream->vol_req.curve_type = curve; | ||
1031 | |||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
1035 | /* stream volume */ | 984 | /* stream volume */ |
1036 | int sst_hsw_stream_set_volume(struct sst_hsw *hsw, | 985 | int sst_hsw_stream_set_volume(struct sst_hsw *hsw, |
1037 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume) | 986 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume) |
@@ -1083,42 +1032,6 @@ int sst_hsw_stream_set_volume(struct sst_hsw *hsw, | |||
1083 | return 0; | 1032 | return 0; |
1084 | } | 1033 | } |
1085 | 1034 | ||
1086 | int sst_hsw_mixer_mute(struct sst_hsw *hsw, u32 stage_id, u32 channel) | ||
1087 | { | ||
1088 | int ret; | ||
1089 | |||
1090 | ret = sst_hsw_mixer_get_volume(hsw, stage_id, channel, | ||
1091 | &hsw->mute_volume[channel]); | ||
1092 | if (ret < 0) | ||
1093 | return ret; | ||
1094 | |||
1095 | ret = sst_hsw_mixer_set_volume(hsw, stage_id, channel, 0); | ||
1096 | if (ret < 0) { | ||
1097 | dev_err(hsw->dev, "error: failed to unmute mixer channel %d\n", | ||
1098 | channel); | ||
1099 | return ret; | ||
1100 | } | ||
1101 | |||
1102 | hsw->mute[channel] = 1; | ||
1103 | return 0; | ||
1104 | } | ||
1105 | |||
1106 | int sst_hsw_mixer_unmute(struct sst_hsw *hsw, u32 stage_id, u32 channel) | ||
1107 | { | ||
1108 | int ret; | ||
1109 | |||
1110 | ret = sst_hsw_mixer_set_volume(hsw, stage_id, channel, | ||
1111 | hsw->mixer_info.volume_register_address[channel]); | ||
1112 | if (ret < 0) { | ||
1113 | dev_err(hsw->dev, "error: failed to unmute mixer channel %d\n", | ||
1114 | channel); | ||
1115 | return ret; | ||
1116 | } | ||
1117 | |||
1118 | hsw->mute[channel] = 0; | ||
1119 | return 0; | ||
1120 | } | ||
1121 | |||
1122 | int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | 1035 | int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, |
1123 | u32 *volume) | 1036 | u32 *volume) |
1124 | { | 1037 | { |
@@ -1132,16 +1045,6 @@ int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | |||
1132 | return 0; | 1045 | return 0; |
1133 | } | 1046 | } |
1134 | 1047 | ||
1135 | int sst_hsw_mixer_set_volume_curve(struct sst_hsw *hsw, | ||
1136 | u64 curve_duration, enum sst_hsw_volume_curve curve) | ||
1137 | { | ||
1138 | /* curve duration in steps of 100ns */ | ||
1139 | hsw->curve_duration = curve_duration; | ||
1140 | hsw->curve_type = curve; | ||
1141 | |||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1145 | /* global mixer volume */ | 1048 | /* global mixer volume */ |
1146 | int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | 1049 | int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, |
1147 | u32 volume) | 1050 | u32 volume) |
@@ -1208,6 +1111,7 @@ struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, | |||
1208 | return NULL; | 1111 | return NULL; |
1209 | 1112 | ||
1210 | spin_lock_irqsave(&sst->spinlock, flags); | 1113 | spin_lock_irqsave(&sst->spinlock, flags); |
1114 | stream->reply.stream_hw_id = INVALID_STREAM_HW_ID; | ||
1211 | list_add(&stream->node, &hsw->stream_list); | 1115 | list_add(&stream->node, &hsw->stream_list); |
1212 | stream->notify_position = notify_position; | 1116 | stream->notify_position = notify_position; |
1213 | stream->pdata = data; | 1117 | stream->pdata = data; |
@@ -1447,50 +1351,32 @@ int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream) | |||
1447 | return 0; | 1351 | return 0; |
1448 | } | 1352 | } |
1449 | 1353 | ||
1450 | /* Stream Information - these calls could be inline but we want the IPC | 1354 | snd_pcm_uframes_t sst_hsw_stream_get_old_position(struct sst_hsw *hsw, |
1451 | ABI to be opaque to client PCM drivers to cope with any future ABI changes */ | ||
1452 | int sst_hsw_stream_get_hw_id(struct sst_hsw *hsw, | ||
1453 | struct sst_hsw_stream *stream) | 1355 | struct sst_hsw_stream *stream) |
1454 | { | 1356 | { |
1455 | return stream->reply.stream_hw_id; | 1357 | return stream->old_position; |
1456 | } | 1358 | } |
1457 | 1359 | ||
1458 | int sst_hsw_stream_get_mixer_id(struct sst_hsw *hsw, | 1360 | void sst_hsw_stream_set_old_position(struct sst_hsw *hsw, |
1459 | struct sst_hsw_stream *stream) | 1361 | struct sst_hsw_stream *stream, snd_pcm_uframes_t val) |
1460 | { | 1362 | { |
1461 | return stream->reply.mixer_hw_id; | 1363 | stream->old_position = val; |
1462 | } | 1364 | } |
1463 | 1365 | ||
1464 | u32 sst_hsw_stream_get_read_reg(struct sst_hsw *hsw, | 1366 | bool sst_hsw_stream_get_silence_start(struct sst_hsw *hsw, |
1465 | struct sst_hsw_stream *stream) | 1367 | struct sst_hsw_stream *stream) |
1466 | { | 1368 | { |
1467 | return stream->reply.read_position_register_address; | 1369 | return stream->play_silence; |
1468 | } | ||
1469 | |||
1470 | u32 sst_hsw_stream_get_pointer_reg(struct sst_hsw *hsw, | ||
1471 | struct sst_hsw_stream *stream) | ||
1472 | { | ||
1473 | return stream->reply.presentation_position_register_address; | ||
1474 | } | ||
1475 | |||
1476 | u32 sst_hsw_stream_get_peak_reg(struct sst_hsw *hsw, | ||
1477 | struct sst_hsw_stream *stream, u32 channel) | ||
1478 | { | ||
1479 | if (channel >= 2) | ||
1480 | return 0; | ||
1481 | |||
1482 | return stream->reply.peak_meter_register_address[channel]; | ||
1483 | } | 1370 | } |
1484 | 1371 | ||
1485 | u32 sst_hsw_stream_get_vol_reg(struct sst_hsw *hsw, | 1372 | void sst_hsw_stream_set_silence_start(struct sst_hsw *hsw, |
1486 | struct sst_hsw_stream *stream, u32 channel) | 1373 | struct sst_hsw_stream *stream, bool val) |
1487 | { | 1374 | { |
1488 | if (channel >= 2) | 1375 | stream->play_silence = val; |
1489 | return 0; | ||
1490 | |||
1491 | return stream->reply.volume_register_address[channel]; | ||
1492 | } | 1376 | } |
1493 | 1377 | ||
1378 | /* Stream Information - these calls could be inline but we want the IPC | ||
1379 | ABI to be opaque to client PCM drivers to cope with any future ABI changes */ | ||
1494 | int sst_hsw_mixer_get_info(struct sst_hsw *hsw) | 1380 | int sst_hsw_mixer_get_info(struct sst_hsw *hsw) |
1495 | { | 1381 | { |
1496 | struct sst_hsw_ipc_stream_info_reply *reply; | 1382 | struct sst_hsw_ipc_stream_info_reply *reply; |
@@ -1628,30 +1514,6 @@ u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw, | |||
1628 | return ppos; | 1514 | return ppos; |
1629 | } | 1515 | } |
1630 | 1516 | ||
1631 | int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, | ||
1632 | struct sst_hsw_stream *stream, u32 stage_id, u32 position) | ||
1633 | { | ||
1634 | u32 header; | ||
1635 | int ret; | ||
1636 | |||
1637 | trace_stream_write_position(stream->reply.stream_hw_id, position); | ||
1638 | |||
1639 | header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | | ||
1640 | IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); | ||
1641 | header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); | ||
1642 | header |= (IPC_STG_SET_WRITE_POSITION << IPC_STG_TYPE_SHIFT); | ||
1643 | header |= (stage_id << IPC_STG_ID_SHIFT); | ||
1644 | stream->wpos.position = position; | ||
1645 | |||
1646 | ret = ipc_tx_message_nowait(hsw, header, &stream->wpos, | ||
1647 | sizeof(stream->wpos)); | ||
1648 | if (ret < 0) | ||
1649 | dev_err(hsw->dev, "error: stream %d set position %d failed\n", | ||
1650 | stream->reply.stream_hw_id, position); | ||
1651 | |||
1652 | return ret; | ||
1653 | } | ||
1654 | |||
1655 | /* physical BE config */ | 1517 | /* physical BE config */ |
1656 | int sst_hsw_device_set_config(struct sst_hsw *hsw, | 1518 | int sst_hsw_device_set_config(struct sst_hsw *hsw, |
1657 | enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, | 1519 | enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, |
@@ -2132,7 +1994,6 @@ void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata) | |||
2132 | dma_free_coherent(hsw->dsp->dma_dev, SST_HSW_DX_CONTEXT_SIZE, | 1994 | dma_free_coherent(hsw->dsp->dma_dev, SST_HSW_DX_CONTEXT_SIZE, |
2133 | hsw->dx_context, hsw->dx_context_paddr); | 1995 | hsw->dx_context, hsw->dx_context_paddr); |
2134 | sst_dsp_free(hsw->dsp); | 1996 | sst_dsp_free(hsw->dsp); |
2135 | kfree(hsw->scratch); | ||
2136 | kthread_stop(hsw->tx_thread); | 1997 | kthread_stop(hsw->tx_thread); |
2137 | kfree(hsw->msg); | 1998 | kfree(hsw->msg); |
2138 | } | 1999 | } |
diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/sst-haswell-ipc.h index 138e894ab413..858096041cb1 100644 --- a/sound/soc/intel/sst-haswell-ipc.h +++ b/sound/soc/intel/sst-haswell-ipc.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <sound/asound.h> | ||
23 | 24 | ||
24 | #define SST_HSW_NO_CHANNELS 4 | 25 | #define SST_HSW_NO_CHANNELS 4 |
25 | #define SST_HSW_MAX_DX_REGIONS 14 | 26 | #define SST_HSW_MAX_DX_REGIONS 14 |
@@ -376,32 +377,17 @@ int sst_hsw_fw_get_version(struct sst_hsw *hsw, | |||
376 | u32 create_channel_map(enum sst_hsw_channel_config config); | 377 | u32 create_channel_map(enum sst_hsw_channel_config config); |
377 | 378 | ||
378 | /* Stream Mixer Controls - */ | 379 | /* Stream Mixer Controls - */ |
379 | int sst_hsw_stream_mute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
380 | u32 stage_id, u32 channel); | ||
381 | int sst_hsw_stream_unmute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, | ||
382 | u32 stage_id, u32 channel); | ||
383 | |||
384 | int sst_hsw_stream_set_volume(struct sst_hsw *hsw, | 380 | int sst_hsw_stream_set_volume(struct sst_hsw *hsw, |
385 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume); | 381 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume); |
386 | int sst_hsw_stream_get_volume(struct sst_hsw *hsw, | 382 | int sst_hsw_stream_get_volume(struct sst_hsw *hsw, |
387 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 *volume); | 383 | struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 *volume); |
388 | 384 | ||
389 | int sst_hsw_stream_set_volume_curve(struct sst_hsw *hsw, | ||
390 | struct sst_hsw_stream *stream, u64 curve_duration, | ||
391 | enum sst_hsw_volume_curve curve); | ||
392 | |||
393 | /* Global Mixer Controls - */ | 385 | /* Global Mixer Controls - */ |
394 | int sst_hsw_mixer_mute(struct sst_hsw *hsw, u32 stage_id, u32 channel); | ||
395 | int sst_hsw_mixer_unmute(struct sst_hsw *hsw, u32 stage_id, u32 channel); | ||
396 | |||
397 | int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | 386 | int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, |
398 | u32 volume); | 387 | u32 volume); |
399 | int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, | 388 | int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, |
400 | u32 *volume); | 389 | u32 *volume); |
401 | 390 | ||
402 | int sst_hsw_mixer_set_volume_curve(struct sst_hsw *hsw, | ||
403 | u64 curve_duration, enum sst_hsw_volume_curve curve); | ||
404 | |||
405 | /* Stream API */ | 391 | /* Stream API */ |
406 | struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, | 392 | struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, |
407 | u32 (*get_write_position)(struct sst_hsw_stream *stream, void *data), | 393 | u32 (*get_write_position)(struct sst_hsw_stream *stream, void *data), |
@@ -440,18 +426,14 @@ int sst_hsw_stream_set_pmemory_info(struct sst_hsw *hsw, | |||
440 | struct sst_hsw_stream *stream, u32 offset, u32 size); | 426 | struct sst_hsw_stream *stream, u32 offset, u32 size); |
441 | int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw, | 427 | int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw, |
442 | struct sst_hsw_stream *stream, u32 offset, u32 size); | 428 | struct sst_hsw_stream *stream, u32 offset, u32 size); |
443 | int sst_hsw_stream_get_hw_id(struct sst_hsw *hsw, | 429 | snd_pcm_uframes_t sst_hsw_stream_get_old_position(struct sst_hsw *hsw, |
444 | struct sst_hsw_stream *stream); | ||
445 | int sst_hsw_stream_get_mixer_id(struct sst_hsw *hsw, | ||
446 | struct sst_hsw_stream *stream); | ||
447 | u32 sst_hsw_stream_get_read_reg(struct sst_hsw *hsw, | ||
448 | struct sst_hsw_stream *stream); | 430 | struct sst_hsw_stream *stream); |
449 | u32 sst_hsw_stream_get_pointer_reg(struct sst_hsw *hsw, | 431 | void sst_hsw_stream_set_old_position(struct sst_hsw *hsw, |
432 | struct sst_hsw_stream *stream, snd_pcm_uframes_t val); | ||
433 | bool sst_hsw_stream_get_silence_start(struct sst_hsw *hsw, | ||
450 | struct sst_hsw_stream *stream); | 434 | struct sst_hsw_stream *stream); |
451 | u32 sst_hsw_stream_get_peak_reg(struct sst_hsw *hsw, | 435 | void sst_hsw_stream_set_silence_start(struct sst_hsw *hsw, |
452 | struct sst_hsw_stream *stream, u32 channel); | 436 | struct sst_hsw_stream *stream, bool val); |
453 | u32 sst_hsw_stream_get_vol_reg(struct sst_hsw *hsw, | ||
454 | struct sst_hsw_stream *stream, u32 channel); | ||
455 | int sst_hsw_mixer_get_info(struct sst_hsw *hsw); | 437 | int sst_hsw_mixer_get_info(struct sst_hsw *hsw); |
456 | 438 | ||
457 | /* Stream ALSA trigger operations */ | 439 | /* Stream ALSA trigger operations */ |
@@ -466,8 +448,6 @@ int sst_hsw_stream_get_read_pos(struct sst_hsw *hsw, | |||
466 | struct sst_hsw_stream *stream, u32 *position); | 448 | struct sst_hsw_stream *stream, u32 *position); |
467 | int sst_hsw_stream_get_write_pos(struct sst_hsw *hsw, | 449 | int sst_hsw_stream_get_write_pos(struct sst_hsw *hsw, |
468 | struct sst_hsw_stream *stream, u32 *position); | 450 | struct sst_hsw_stream *stream, u32 *position); |
469 | int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, | ||
470 | struct sst_hsw_stream *stream, u32 stage_id, u32 position); | ||
471 | u32 sst_hsw_get_dsp_position(struct sst_hsw *hsw, | 451 | u32 sst_hsw_get_dsp_position(struct sst_hsw *hsw, |
472 | struct sst_hsw_stream *stream); | 452 | struct sst_hsw_stream *stream); |
473 | u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw, | 453 | u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw, |
@@ -481,8 +461,6 @@ int sst_hsw_device_set_config(struct sst_hsw *hsw, | |||
481 | /* DX Config */ | 461 | /* DX Config */ |
482 | int sst_hsw_dx_set_state(struct sst_hsw *hsw, | 462 | int sst_hsw_dx_set_state(struct sst_hsw *hsw, |
483 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx); | 463 | enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx); |
484 | int sst_hsw_dx_get_state(struct sst_hsw *hsw, u32 item, | ||
485 | u32 *offset, u32 *size, u32 *source); | ||
486 | 464 | ||
487 | /* init */ | 465 | /* init */ |
488 | int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata); | 466 | int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata); |
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index 619525200705..7e21e8f85885 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c | |||
@@ -36,6 +36,11 @@ | |||
36 | #define HSW_PCM_COUNT 6 | 36 | #define HSW_PCM_COUNT 6 |
37 | #define HSW_VOLUME_MAX 0x7FFFFFFF /* 0dB */ | 37 | #define HSW_VOLUME_MAX 0x7FFFFFFF /* 0dB */ |
38 | 38 | ||
39 | #define SST_OLD_POSITION(d, r, o) ((d) + \ | ||
40 | frames_to_bytes(r, o)) | ||
41 | #define SST_SAMPLES(r, x) (bytes_to_samples(r, \ | ||
42 | frames_to_bytes(r, (x)))) | ||
43 | |||
39 | /* simple volume table */ | 44 | /* simple volume table */ |
40 | static const u32 volume_map[] = { | 45 | static const u32 volume_map[] = { |
41 | HSW_VOLUME_MAX >> 30, | 46 | HSW_VOLUME_MAX >> 30, |
@@ -78,7 +83,6 @@ static const u32 volume_map[] = { | |||
78 | #define HSW_PCM_DAI_ID_OFFLOAD0 1 | 83 | #define HSW_PCM_DAI_ID_OFFLOAD0 1 |
79 | #define HSW_PCM_DAI_ID_OFFLOAD1 2 | 84 | #define HSW_PCM_DAI_ID_OFFLOAD1 2 |
80 | #define HSW_PCM_DAI_ID_LOOPBACK 3 | 85 | #define HSW_PCM_DAI_ID_LOOPBACK 3 |
81 | #define HSW_PCM_DAI_ID_CAPTURE 4 | ||
82 | 86 | ||
83 | 87 | ||
84 | static const struct snd_pcm_hardware hsw_pcm_hardware = { | 88 | static const struct snd_pcm_hardware hsw_pcm_hardware = { |
@@ -87,7 +91,8 @@ static const struct snd_pcm_hardware hsw_pcm_hardware = { | |||
87 | SNDRV_PCM_INFO_INTERLEAVED | | 91 | SNDRV_PCM_INFO_INTERLEAVED | |
88 | SNDRV_PCM_INFO_PAUSE | | 92 | SNDRV_PCM_INFO_PAUSE | |
89 | SNDRV_PCM_INFO_RESUME | | 93 | SNDRV_PCM_INFO_RESUME | |
90 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, | 94 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP | |
95 | SNDRV_PCM_INFO_DRAIN_TRIGGER, | ||
91 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | | 96 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | |
92 | SNDRV_PCM_FMTBIT_S32_LE, | 97 | SNDRV_PCM_FMTBIT_S32_LE, |
93 | .period_bytes_min = PAGE_SIZE, | 98 | .period_bytes_min = PAGE_SIZE, |
@@ -99,6 +104,7 @@ static const struct snd_pcm_hardware hsw_pcm_hardware = { | |||
99 | 104 | ||
100 | struct hsw_pcm_module_map { | 105 | struct hsw_pcm_module_map { |
101 | int dai_id; | 106 | int dai_id; |
107 | int stream; | ||
102 | enum sst_hsw_module_id mod_id; | 108 | enum sst_hsw_module_id mod_id; |
103 | }; | 109 | }; |
104 | 110 | ||
@@ -119,8 +125,9 @@ struct hsw_pcm_data { | |||
119 | }; | 125 | }; |
120 | 126 | ||
121 | enum hsw_pm_state { | 127 | enum hsw_pm_state { |
122 | HSW_PM_STATE_D3 = 0, | 128 | HSW_PM_STATE_D0 = 0, |
123 | HSW_PM_STATE_D0 = 1, | 129 | HSW_PM_STATE_RTD3 = 1, |
130 | HSW_PM_STATE_D3 = 2, | ||
124 | }; | 131 | }; |
125 | 132 | ||
126 | /* private data for the driver */ | 133 | /* private data for the driver */ |
@@ -135,7 +142,17 @@ struct hsw_priv_data { | |||
135 | struct snd_dma_buffer dmab[HSW_PCM_COUNT][2]; | 142 | struct snd_dma_buffer dmab[HSW_PCM_COUNT][2]; |
136 | 143 | ||
137 | /* DAI data */ | 144 | /* DAI data */ |
138 | struct hsw_pcm_data pcm[HSW_PCM_COUNT]; | 145 | struct hsw_pcm_data pcm[HSW_PCM_COUNT][2]; |
146 | }; | ||
147 | |||
148 | |||
149 | /* static mappings between PCMs and modules - may be dynamic in future */ | ||
150 | static struct hsw_pcm_module_map mod_map[] = { | ||
151 | {HSW_PCM_DAI_ID_SYSTEM, 0, SST_HSW_MODULE_PCM_SYSTEM}, | ||
152 | {HSW_PCM_DAI_ID_OFFLOAD0, 0, SST_HSW_MODULE_PCM}, | ||
153 | {HSW_PCM_DAI_ID_OFFLOAD1, 0, SST_HSW_MODULE_PCM}, | ||
154 | {HSW_PCM_DAI_ID_LOOPBACK, 1, SST_HSW_MODULE_PCM_REFERENCE}, | ||
155 | {HSW_PCM_DAI_ID_SYSTEM, 1, SST_HSW_MODULE_PCM_CAPTURE}, | ||
139 | }; | 156 | }; |
140 | 157 | ||
141 | static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data); | 158 | static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data); |
@@ -168,9 +185,14 @@ static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol, | |||
168 | (struct soc_mixer_control *)kcontrol->private_value; | 185 | (struct soc_mixer_control *)kcontrol->private_value; |
169 | struct hsw_priv_data *pdata = | 186 | struct hsw_priv_data *pdata = |
170 | snd_soc_platform_get_drvdata(platform); | 187 | snd_soc_platform_get_drvdata(platform); |
171 | struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; | 188 | struct hsw_pcm_data *pcm_data; |
172 | struct sst_hsw *hsw = pdata->hsw; | 189 | struct sst_hsw *hsw = pdata->hsw; |
173 | u32 volume; | 190 | u32 volume; |
191 | int dai, stream; | ||
192 | |||
193 | dai = mod_map[mc->reg].dai_id; | ||
194 | stream = mod_map[mc->reg].stream; | ||
195 | pcm_data = &pdata->pcm[dai][stream]; | ||
174 | 196 | ||
175 | mutex_lock(&pcm_data->mutex); | 197 | mutex_lock(&pcm_data->mutex); |
176 | pm_runtime_get_sync(pdata->dev); | 198 | pm_runtime_get_sync(pdata->dev); |
@@ -212,9 +234,14 @@ static int hsw_stream_volume_get(struct snd_kcontrol *kcontrol, | |||
212 | (struct soc_mixer_control *)kcontrol->private_value; | 234 | (struct soc_mixer_control *)kcontrol->private_value; |
213 | struct hsw_priv_data *pdata = | 235 | struct hsw_priv_data *pdata = |
214 | snd_soc_platform_get_drvdata(platform); | 236 | snd_soc_platform_get_drvdata(platform); |
215 | struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; | 237 | struct hsw_pcm_data *pcm_data; |
216 | struct sst_hsw *hsw = pdata->hsw; | 238 | struct sst_hsw *hsw = pdata->hsw; |
217 | u32 volume; | 239 | u32 volume; |
240 | int dai, stream; | ||
241 | |||
242 | dai = mod_map[mc->reg].dai_id; | ||
243 | stream = mod_map[mc->reg].stream; | ||
244 | pcm_data = &pdata->pcm[dai][stream]; | ||
218 | 245 | ||
219 | mutex_lock(&pcm_data->mutex); | 246 | mutex_lock(&pcm_data->mutex); |
220 | pm_runtime_get_sync(pdata->dev); | 247 | pm_runtime_get_sync(pdata->dev); |
@@ -309,7 +336,7 @@ static const struct snd_kcontrol_new hsw_volume_controls[] = { | |||
309 | ARRAY_SIZE(volume_map) - 1, 0, | 336 | ARRAY_SIZE(volume_map) - 1, 0, |
310 | hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), | 337 | hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), |
311 | /* Mic Capture volume */ | 338 | /* Mic Capture volume */ |
312 | SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 0, 0, 8, | 339 | SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 4, 0, 8, |
313 | ARRAY_SIZE(volume_map) - 1, 0, | 340 | ARRAY_SIZE(volume_map) - 1, 0, |
314 | hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), | 341 | hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), |
315 | }; | 342 | }; |
@@ -353,7 +380,7 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, | |||
353 | struct snd_pcm_runtime *runtime = substream->runtime; | 380 | struct snd_pcm_runtime *runtime = substream->runtime; |
354 | struct hsw_priv_data *pdata = | 381 | struct hsw_priv_data *pdata = |
355 | snd_soc_platform_get_drvdata(rtd->platform); | 382 | snd_soc_platform_get_drvdata(rtd->platform); |
356 | struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | 383 | struct hsw_pcm_data *pcm_data; |
357 | struct sst_hsw *hsw = pdata->hsw; | 384 | struct sst_hsw *hsw = pdata->hsw; |
358 | struct sst_module *module_data; | 385 | struct sst_module *module_data; |
359 | struct sst_dsp *dsp; | 386 | struct sst_dsp *dsp; |
@@ -362,7 +389,10 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, | |||
362 | enum sst_hsw_stream_path_id path_id; | 389 | enum sst_hsw_stream_path_id path_id; |
363 | u32 rate, bits, map, pages, module_id; | 390 | u32 rate, bits, map, pages, module_id; |
364 | u8 channels; | 391 | u8 channels; |
365 | int ret; | 392 | int ret, dai; |
393 | |||
394 | dai = mod_map[rtd->cpu_dai->id].dai_id; | ||
395 | pcm_data = &pdata->pcm[dai][substream->stream]; | ||
366 | 396 | ||
367 | /* check if we are being called a subsequent time */ | 397 | /* check if we are being called a subsequent time */ |
368 | if (pcm_data->allocated) { | 398 | if (pcm_data->allocated) { |
@@ -552,20 +582,35 @@ static int hsw_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
552 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 582 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
553 | struct hsw_priv_data *pdata = | 583 | struct hsw_priv_data *pdata = |
554 | snd_soc_platform_get_drvdata(rtd->platform); | 584 | snd_soc_platform_get_drvdata(rtd->platform); |
555 | struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | 585 | struct hsw_pcm_data *pcm_data; |
586 | struct sst_hsw_stream *sst_stream; | ||
556 | struct sst_hsw *hsw = pdata->hsw; | 587 | struct sst_hsw *hsw = pdata->hsw; |
588 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
589 | snd_pcm_uframes_t pos; | ||
590 | int dai; | ||
591 | |||
592 | dai = mod_map[rtd->cpu_dai->id].dai_id; | ||
593 | pcm_data = &pdata->pcm[dai][substream->stream]; | ||
594 | sst_stream = pcm_data->stream; | ||
557 | 595 | ||
558 | switch (cmd) { | 596 | switch (cmd) { |
559 | case SNDRV_PCM_TRIGGER_START: | 597 | case SNDRV_PCM_TRIGGER_START: |
560 | case SNDRV_PCM_TRIGGER_RESUME: | 598 | case SNDRV_PCM_TRIGGER_RESUME: |
561 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 599 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
600 | sst_hsw_stream_set_silence_start(hsw, sst_stream, false); | ||
562 | sst_hsw_stream_resume(hsw, pcm_data->stream, 0); | 601 | sst_hsw_stream_resume(hsw, pcm_data->stream, 0); |
563 | break; | 602 | break; |
564 | case SNDRV_PCM_TRIGGER_STOP: | 603 | case SNDRV_PCM_TRIGGER_STOP: |
565 | case SNDRV_PCM_TRIGGER_SUSPEND: | 604 | case SNDRV_PCM_TRIGGER_SUSPEND: |
566 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 605 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
606 | sst_hsw_stream_set_silence_start(hsw, sst_stream, false); | ||
567 | sst_hsw_stream_pause(hsw, pcm_data->stream, 0); | 607 | sst_hsw_stream_pause(hsw, pcm_data->stream, 0); |
568 | break; | 608 | break; |
609 | case SNDRV_PCM_TRIGGER_DRAIN: | ||
610 | pos = runtime->control->appl_ptr % runtime->buffer_size; | ||
611 | sst_hsw_stream_set_old_position(hsw, pcm_data->stream, pos); | ||
612 | sst_hsw_stream_set_silence_start(hsw, sst_stream, true); | ||
613 | break; | ||
569 | default: | 614 | default: |
570 | break; | 615 | break; |
571 | } | 616 | } |
@@ -579,13 +624,62 @@ static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data) | |||
579 | struct snd_pcm_substream *substream = pcm_data->substream; | 624 | struct snd_pcm_substream *substream = pcm_data->substream; |
580 | struct snd_pcm_runtime *runtime = substream->runtime; | 625 | struct snd_pcm_runtime *runtime = substream->runtime; |
581 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 626 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
627 | struct hsw_priv_data *pdata = | ||
628 | snd_soc_platform_get_drvdata(rtd->platform); | ||
629 | struct sst_hsw *hsw = pdata->hsw; | ||
582 | u32 pos; | 630 | u32 pos; |
631 | snd_pcm_uframes_t position = bytes_to_frames(runtime, | ||
632 | sst_hsw_get_dsp_position(hsw, pcm_data->stream)); | ||
633 | unsigned char *dma_area = runtime->dma_area; | ||
634 | snd_pcm_uframes_t dma_frames = | ||
635 | bytes_to_frames(runtime, runtime->dma_bytes); | ||
636 | snd_pcm_uframes_t old_position; | ||
637 | ssize_t samples; | ||
583 | 638 | ||
584 | pos = frames_to_bytes(runtime, | 639 | pos = frames_to_bytes(runtime, |
585 | (runtime->control->appl_ptr % runtime->buffer_size)); | 640 | (runtime->control->appl_ptr % runtime->buffer_size)); |
586 | 641 | ||
587 | dev_vdbg(rtd->dev, "PCM: App pointer %d bytes\n", pos); | 642 | dev_vdbg(rtd->dev, "PCM: App pointer %d bytes\n", pos); |
588 | 643 | ||
644 | /* SST fw don't know where to stop dma | ||
645 | * So, SST driver need to clean the data which has been consumed | ||
646 | */ | ||
647 | if (dma_area == NULL || dma_frames <= 0 | ||
648 | || (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
649 | || !sst_hsw_stream_get_silence_start(hsw, stream)) { | ||
650 | snd_pcm_period_elapsed(substream); | ||
651 | return pos; | ||
652 | } | ||
653 | |||
654 | old_position = sst_hsw_stream_get_old_position(hsw, stream); | ||
655 | if (position > old_position) { | ||
656 | if (position < dma_frames) { | ||
657 | samples = SST_SAMPLES(runtime, position - old_position); | ||
658 | snd_pcm_format_set_silence(runtime->format, | ||
659 | SST_OLD_POSITION(dma_area, | ||
660 | runtime, old_position), | ||
661 | samples); | ||
662 | } else | ||
663 | dev_err(rtd->dev, "PCM: position is wrong\n"); | ||
664 | } else { | ||
665 | if (old_position < dma_frames) { | ||
666 | samples = SST_SAMPLES(runtime, | ||
667 | dma_frames - old_position); | ||
668 | snd_pcm_format_set_silence(runtime->format, | ||
669 | SST_OLD_POSITION(dma_area, | ||
670 | runtime, old_position), | ||
671 | samples); | ||
672 | } else | ||
673 | dev_err(rtd->dev, "PCM: dma_bytes is wrong\n"); | ||
674 | if (position < dma_frames) { | ||
675 | samples = SST_SAMPLES(runtime, position); | ||
676 | snd_pcm_format_set_silence(runtime->format, | ||
677 | dma_area, samples); | ||
678 | } else | ||
679 | dev_err(rtd->dev, "PCM: position is wrong\n"); | ||
680 | } | ||
681 | sst_hsw_stream_set_old_position(hsw, stream, position); | ||
682 | |||
589 | /* let alsa know we have play a period */ | 683 | /* let alsa know we have play a period */ |
590 | snd_pcm_period_elapsed(substream); | 684 | snd_pcm_period_elapsed(substream); |
591 | return pos; | 685 | return pos; |
@@ -597,11 +691,16 @@ static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_pcm_substream *substream) | |||
597 | struct snd_pcm_runtime *runtime = substream->runtime; | 691 | struct snd_pcm_runtime *runtime = substream->runtime; |
598 | struct hsw_priv_data *pdata = | 692 | struct hsw_priv_data *pdata = |
599 | snd_soc_platform_get_drvdata(rtd->platform); | 693 | snd_soc_platform_get_drvdata(rtd->platform); |
600 | struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | 694 | struct hsw_pcm_data *pcm_data; |
601 | struct sst_hsw *hsw = pdata->hsw; | 695 | struct sst_hsw *hsw = pdata->hsw; |
602 | snd_pcm_uframes_t offset; | 696 | snd_pcm_uframes_t offset; |
603 | uint64_t ppos; | 697 | uint64_t ppos; |
604 | u32 position = sst_hsw_get_dsp_position(hsw, pcm_data->stream); | 698 | u32 position; |
699 | int dai; | ||
700 | |||
701 | dai = mod_map[rtd->cpu_dai->id].dai_id; | ||
702 | pcm_data = &pdata->pcm[dai][substream->stream]; | ||
703 | position = sst_hsw_get_dsp_position(hsw, pcm_data->stream); | ||
605 | 704 | ||
606 | offset = bytes_to_frames(runtime, position); | 705 | offset = bytes_to_frames(runtime, position); |
607 | ppos = sst_hsw_get_dsp_presentation_position(hsw, pcm_data->stream); | 706 | ppos = sst_hsw_get_dsp_presentation_position(hsw, pcm_data->stream); |
@@ -618,8 +717,10 @@ static int hsw_pcm_open(struct snd_pcm_substream *substream) | |||
618 | snd_soc_platform_get_drvdata(rtd->platform); | 717 | snd_soc_platform_get_drvdata(rtd->platform); |
619 | struct hsw_pcm_data *pcm_data; | 718 | struct hsw_pcm_data *pcm_data; |
620 | struct sst_hsw *hsw = pdata->hsw; | 719 | struct sst_hsw *hsw = pdata->hsw; |
720 | int dai; | ||
621 | 721 | ||
622 | pcm_data = &pdata->pcm[rtd->cpu_dai->id]; | 722 | dai = mod_map[rtd->cpu_dai->id].dai_id; |
723 | pcm_data = &pdata->pcm[dai][substream->stream]; | ||
623 | 724 | ||
624 | mutex_lock(&pcm_data->mutex); | 725 | mutex_lock(&pcm_data->mutex); |
625 | pm_runtime_get_sync(pdata->dev); | 726 | pm_runtime_get_sync(pdata->dev); |
@@ -648,9 +749,12 @@ static int hsw_pcm_close(struct snd_pcm_substream *substream) | |||
648 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 749 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
649 | struct hsw_priv_data *pdata = | 750 | struct hsw_priv_data *pdata = |
650 | snd_soc_platform_get_drvdata(rtd->platform); | 751 | snd_soc_platform_get_drvdata(rtd->platform); |
651 | struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); | 752 | struct hsw_pcm_data *pcm_data; |
652 | struct sst_hsw *hsw = pdata->hsw; | 753 | struct sst_hsw *hsw = pdata->hsw; |
653 | int ret; | 754 | int ret, dai; |
755 | |||
756 | dai = mod_map[rtd->cpu_dai->id].dai_id; | ||
757 | pcm_data = &pdata->pcm[dai][substream->stream]; | ||
654 | 758 | ||
655 | mutex_lock(&pcm_data->mutex); | 759 | mutex_lock(&pcm_data->mutex); |
656 | ret = sst_hsw_stream_reset(hsw, pcm_data->stream); | 760 | ret = sst_hsw_stream_reset(hsw, pcm_data->stream); |
@@ -685,15 +789,6 @@ static struct snd_pcm_ops hsw_pcm_ops = { | |||
685 | .page = snd_pcm_sgbuf_ops_page, | 789 | .page = snd_pcm_sgbuf_ops_page, |
686 | }; | 790 | }; |
687 | 791 | ||
688 | /* static mappings between PCMs and modules - may be dynamic in future */ | ||
689 | static struct hsw_pcm_module_map mod_map[] = { | ||
690 | {HSW_PCM_DAI_ID_SYSTEM, SST_HSW_MODULE_PCM_SYSTEM}, | ||
691 | {HSW_PCM_DAI_ID_OFFLOAD0, SST_HSW_MODULE_PCM}, | ||
692 | {HSW_PCM_DAI_ID_OFFLOAD1, SST_HSW_MODULE_PCM}, | ||
693 | {HSW_PCM_DAI_ID_LOOPBACK, SST_HSW_MODULE_PCM_REFERENCE}, | ||
694 | {HSW_PCM_DAI_ID_CAPTURE, SST_HSW_MODULE_PCM_CAPTURE}, | ||
695 | }; | ||
696 | |||
697 | static int hsw_pcm_create_modules(struct hsw_priv_data *pdata) | 792 | static int hsw_pcm_create_modules(struct hsw_priv_data *pdata) |
698 | { | 793 | { |
699 | struct sst_hsw *hsw = pdata->hsw; | 794 | struct sst_hsw *hsw = pdata->hsw; |
@@ -701,7 +796,7 @@ static int hsw_pcm_create_modules(struct hsw_priv_data *pdata) | |||
701 | int i; | 796 | int i; |
702 | 797 | ||
703 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { | 798 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { |
704 | pcm_data = &pdata->pcm[i]; | 799 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; |
705 | 800 | ||
706 | /* create new runtime module, use same offset if recreated */ | 801 | /* create new runtime module, use same offset if recreated */ |
707 | pcm_data->runtime = sst_hsw_runtime_module_create(hsw, | 802 | pcm_data->runtime = sst_hsw_runtime_module_create(hsw, |
@@ -716,7 +811,7 @@ static int hsw_pcm_create_modules(struct hsw_priv_data *pdata) | |||
716 | 811 | ||
717 | err: | 812 | err: |
718 | for (--i; i >= 0; i--) { | 813 | for (--i; i >= 0; i--) { |
719 | pcm_data = &pdata->pcm[i]; | 814 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; |
720 | sst_hsw_runtime_module_free(pcm_data->runtime); | 815 | sst_hsw_runtime_module_free(pcm_data->runtime); |
721 | } | 816 | } |
722 | 817 | ||
@@ -729,17 +824,12 @@ static void hsw_pcm_free_modules(struct hsw_priv_data *pdata) | |||
729 | int i; | 824 | int i; |
730 | 825 | ||
731 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { | 826 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { |
732 | pcm_data = &pdata->pcm[i]; | 827 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; |
733 | 828 | ||
734 | sst_hsw_runtime_module_free(pcm_data->runtime); | 829 | sst_hsw_runtime_module_free(pcm_data->runtime); |
735 | } | 830 | } |
736 | } | 831 | } |
737 | 832 | ||
738 | static void hsw_pcm_free(struct snd_pcm *pcm) | ||
739 | { | ||
740 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
741 | } | ||
742 | |||
743 | static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) | 833 | static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) |
744 | { | 834 | { |
745 | struct snd_pcm *pcm = rtd->pcm; | 835 | struct snd_pcm *pcm = rtd->pcm; |
@@ -762,7 +852,10 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
762 | return ret; | 852 | return ret; |
763 | } | 853 | } |
764 | } | 854 | } |
765 | priv_data->pcm[rtd->cpu_dai->id].hsw_pcm = pcm; | 855 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) |
856 | priv_data->pcm[rtd->cpu_dai->id][SNDRV_PCM_STREAM_PLAYBACK].hsw_pcm = pcm; | ||
857 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) | ||
858 | priv_data->pcm[rtd->cpu_dai->id][SNDRV_PCM_STREAM_CAPTURE].hsw_pcm = pcm; | ||
766 | 859 | ||
767 | return ret; | 860 | return ret; |
768 | } | 861 | } |
@@ -871,10 +964,9 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform) | |||
871 | /* allocate DSP buffer page tables */ | 964 | /* allocate DSP buffer page tables */ |
872 | for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { | 965 | for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { |
873 | 966 | ||
874 | mutex_init(&priv_data->pcm[i].mutex); | ||
875 | |||
876 | /* playback */ | 967 | /* playback */ |
877 | if (hsw_dais[i].playback.channels_min) { | 968 | if (hsw_dais[i].playback.channels_min) { |
969 | mutex_init(&priv_data->pcm[i][SNDRV_PCM_STREAM_PLAYBACK].mutex); | ||
878 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dma_dev, | 970 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dma_dev, |
879 | PAGE_SIZE, &priv_data->dmab[i][0]); | 971 | PAGE_SIZE, &priv_data->dmab[i][0]); |
880 | if (ret < 0) | 972 | if (ret < 0) |
@@ -883,6 +975,7 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform) | |||
883 | 975 | ||
884 | /* capture */ | 976 | /* capture */ |
885 | if (hsw_dais[i].capture.channels_min) { | 977 | if (hsw_dais[i].capture.channels_min) { |
978 | mutex_init(&priv_data->pcm[i][SNDRV_PCM_STREAM_CAPTURE].mutex); | ||
886 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dma_dev, | 979 | ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dma_dev, |
887 | PAGE_SIZE, &priv_data->dmab[i][1]); | 980 | PAGE_SIZE, &priv_data->dmab[i][1]); |
888 | if (ret < 0) | 981 | if (ret < 0) |
@@ -936,7 +1029,6 @@ static struct snd_soc_platform_driver hsw_soc_platform = { | |||
936 | .remove = hsw_pcm_remove, | 1029 | .remove = hsw_pcm_remove, |
937 | .ops = &hsw_pcm_ops, | 1030 | .ops = &hsw_pcm_ops, |
938 | .pcm_new = hsw_pcm_new, | 1031 | .pcm_new = hsw_pcm_new, |
939 | .pcm_free = hsw_pcm_free, | ||
940 | }; | 1032 | }; |
941 | 1033 | ||
942 | static const struct snd_soc_component_driver hsw_dai_component = { | 1034 | static const struct snd_soc_component_driver hsw_dai_component = { |
@@ -1010,12 +1102,12 @@ static int hsw_pcm_runtime_suspend(struct device *dev) | |||
1010 | struct hsw_priv_data *pdata = dev_get_drvdata(dev); | 1102 | struct hsw_priv_data *pdata = dev_get_drvdata(dev); |
1011 | struct sst_hsw *hsw = pdata->hsw; | 1103 | struct sst_hsw *hsw = pdata->hsw; |
1012 | 1104 | ||
1013 | if (pdata->pm_state == HSW_PM_STATE_D3) | 1105 | if (pdata->pm_state >= HSW_PM_STATE_RTD3) |
1014 | return 0; | 1106 | return 0; |
1015 | 1107 | ||
1016 | sst_hsw_dsp_runtime_suspend(hsw); | 1108 | sst_hsw_dsp_runtime_suspend(hsw); |
1017 | sst_hsw_dsp_runtime_sleep(hsw); | 1109 | sst_hsw_dsp_runtime_sleep(hsw); |
1018 | pdata->pm_state = HSW_PM_STATE_D3; | 1110 | pdata->pm_state = HSW_PM_STATE_RTD3; |
1019 | 1111 | ||
1020 | return 0; | 1112 | return 0; |
1021 | } | 1113 | } |
@@ -1026,7 +1118,7 @@ static int hsw_pcm_runtime_resume(struct device *dev) | |||
1026 | struct sst_hsw *hsw = pdata->hsw; | 1118 | struct sst_hsw *hsw = pdata->hsw; |
1027 | int ret; | 1119 | int ret; |
1028 | 1120 | ||
1029 | if (pdata->pm_state == HSW_PM_STATE_D0) | 1121 | if (pdata->pm_state != HSW_PM_STATE_RTD3) |
1030 | return 0; | 1122 | return 0; |
1031 | 1123 | ||
1032 | ret = sst_hsw_dsp_load(hsw); | 1124 | ret = sst_hsw_dsp_load(hsw); |
@@ -1066,7 +1158,7 @@ static void hsw_pcm_complete(struct device *dev) | |||
1066 | struct hsw_pcm_data *pcm_data; | 1158 | struct hsw_pcm_data *pcm_data; |
1067 | int i, err; | 1159 | int i, err; |
1068 | 1160 | ||
1069 | if (pdata->pm_state == HSW_PM_STATE_D0) | 1161 | if (pdata->pm_state != HSW_PM_STATE_D3) |
1070 | return; | 1162 | return; |
1071 | 1163 | ||
1072 | err = sst_hsw_dsp_load(hsw); | 1164 | err = sst_hsw_dsp_load(hsw); |
@@ -1081,8 +1173,8 @@ static void hsw_pcm_complete(struct device *dev) | |||
1081 | return; | 1173 | return; |
1082 | } | 1174 | } |
1083 | 1175 | ||
1084 | for (i = 0; i < HSW_PCM_DAI_ID_CAPTURE + 1; i++) { | 1176 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { |
1085 | pcm_data = &pdata->pcm[i]; | 1177 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; |
1086 | 1178 | ||
1087 | if (!pcm_data->substream) | 1179 | if (!pcm_data->substream) |
1088 | continue; | 1180 | continue; |
@@ -1114,41 +1206,42 @@ static int hsw_pcm_prepare(struct device *dev) | |||
1114 | 1206 | ||
1115 | if (pdata->pm_state == HSW_PM_STATE_D3) | 1207 | if (pdata->pm_state == HSW_PM_STATE_D3) |
1116 | return 0; | 1208 | return 0; |
1117 | /* suspend all active streams */ | 1209 | else if (pdata->pm_state == HSW_PM_STATE_D0) { |
1118 | for (i = 0; i < HSW_PCM_DAI_ID_CAPTURE + 1; i++) { | 1210 | /* suspend all active streams */ |
1119 | pcm_data = &pdata->pcm[i]; | 1211 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { |
1212 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; | ||
1213 | |||
1214 | if (!pcm_data->substream) | ||
1215 | continue; | ||
1216 | dev_dbg(dev, "suspending pcm %d\n", i); | ||
1217 | snd_pcm_suspend_all(pcm_data->hsw_pcm); | ||
1218 | |||
1219 | /* We need to wait until the DSP FW stops the streams */ | ||
1220 | msleep(2); | ||
1221 | } | ||
1120 | 1222 | ||
1121 | if (!pcm_data->substream) | 1223 | /* preserve persistent memory */ |
1122 | continue; | 1224 | for (i = 0; i < ARRAY_SIZE(mod_map); i++) { |
1123 | dev_dbg(dev, "suspending pcm %d\n", i); | 1225 | pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; |
1124 | snd_pcm_suspend_all(pcm_data->hsw_pcm); | 1226 | |
1227 | if (!pcm_data->substream) | ||
1228 | continue; | ||
1125 | 1229 | ||
1126 | /* We need to wait until the DSP FW stops the streams */ | 1230 | dev_dbg(dev, "saving context pcm %d\n", i); |
1127 | msleep(2); | 1231 | err = sst_module_runtime_save(pcm_data->runtime, |
1232 | &pcm_data->context); | ||
1233 | if (err < 0) | ||
1234 | dev_err(dev, "failed to save context for PCM %d\n", i); | ||
1235 | } | ||
1236 | /* enter D3 state and stall */ | ||
1237 | sst_hsw_dsp_runtime_suspend(hsw); | ||
1238 | /* put the DSP to sleep */ | ||
1239 | sst_hsw_dsp_runtime_sleep(hsw); | ||
1128 | } | 1240 | } |
1129 | 1241 | ||
1130 | snd_soc_suspend(pdata->soc_card->dev); | 1242 | snd_soc_suspend(pdata->soc_card->dev); |
1131 | snd_soc_poweroff(pdata->soc_card->dev); | 1243 | snd_soc_poweroff(pdata->soc_card->dev); |
1132 | 1244 | ||
1133 | /* enter D3 state and stall */ | ||
1134 | sst_hsw_dsp_runtime_suspend(hsw); | ||
1135 | |||
1136 | /* preserve persistent memory */ | ||
1137 | for (i = 0; i < HSW_PCM_DAI_ID_CAPTURE + 1; i++) { | ||
1138 | pcm_data = &pdata->pcm[i]; | ||
1139 | |||
1140 | if (!pcm_data->substream) | ||
1141 | continue; | ||
1142 | |||
1143 | dev_dbg(dev, "saving context pcm %d\n", i); | ||
1144 | err = sst_module_runtime_save(pcm_data->runtime, | ||
1145 | &pcm_data->context); | ||
1146 | if (err < 0) | ||
1147 | dev_err(dev, "failed to save context for PCM %d\n", i); | ||
1148 | } | ||
1149 | |||
1150 | /* put the DSP to sleep */ | ||
1151 | sst_hsw_dsp_runtime_sleep(hsw); | ||
1152 | pdata->pm_state = HSW_PM_STATE_D3; | 1245 | pdata->pm_state = HSW_PM_STATE_D3; |
1153 | 1246 | ||
1154 | return 0; | 1247 | return 0; |
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/sst-mfld-platform-pcm.c index a1a8d9d91539..7523cbef8780 100644 --- a/sound/soc/intel/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/sst-mfld-platform-pcm.c | |||
@@ -643,12 +643,6 @@ static struct snd_pcm_ops sst_platform_ops = { | |||
643 | .pointer = sst_platform_pcm_pointer, | 643 | .pointer = sst_platform_pcm_pointer, |
644 | }; | 644 | }; |
645 | 645 | ||
646 | static void sst_pcm_free(struct snd_pcm *pcm) | ||
647 | { | ||
648 | dev_dbg(pcm->dev, "sst_pcm_free called\n"); | ||
649 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
650 | } | ||
651 | |||
652 | static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) | 646 | static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) |
653 | { | 647 | { |
654 | struct snd_soc_dai *dai = rtd->cpu_dai; | 648 | struct snd_soc_dai *dai = rtd->cpu_dai; |
@@ -679,7 +673,6 @@ static struct snd_soc_platform_driver sst_soc_platform_drv = { | |||
679 | .ops = &sst_platform_ops, | 673 | .ops = &sst_platform_ops, |
680 | .compr_ops = &sst_platform_compr_ops, | 674 | .compr_ops = &sst_platform_compr_ops, |
681 | .pcm_new = sst_pcm_new, | 675 | .pcm_new = sst_pcm_new, |
682 | .pcm_free = sst_pcm_free, | ||
683 | }; | 676 | }; |
684 | 677 | ||
685 | static const struct snd_soc_component_driver sst_component = { | 678 | static const struct snd_soc_component_driver sst_component = { |
diff --git a/sound/soc/intel/sst/sst.c b/sound/soc/intel/sst/sst.c index 8a8d56a146e7..11c578651c1c 100644 --- a/sound/soc/intel/sst/sst.c +++ b/sound/soc/intel/sst/sst.c | |||
@@ -350,7 +350,9 @@ static inline void sst_save_shim64(struct intel_sst_drv *ctx, | |||
350 | 350 | ||
351 | spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags); | 351 | spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags); |
352 | 352 | ||
353 | shim_regs->imrx = sst_shim_read64(shim, SST_IMRX), | 353 | shim_regs->imrx = sst_shim_read64(shim, SST_IMRX); |
354 | shim_regs->csr = sst_shim_read64(shim, SST_CSR); | ||
355 | |||
354 | 356 | ||
355 | spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags); | 357 | spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags); |
356 | } | 358 | } |
@@ -367,6 +369,7 @@ static inline void sst_restore_shim64(struct intel_sst_drv *ctx, | |||
367 | */ | 369 | */ |
368 | spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags); | 370 | spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags); |
369 | sst_shim_write64(shim, SST_IMRX, shim_regs->imrx), | 371 | sst_shim_write64(shim, SST_IMRX, shim_regs->imrx), |
372 | sst_shim_write64(shim, SST_CSR, shim_regs->csr), | ||
370 | spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags); | 373 | spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags); |
371 | } | 374 | } |
372 | 375 | ||
@@ -379,6 +382,10 @@ void sst_configure_runtime_pm(struct intel_sst_drv *ctx) | |||
379 | * initially active. So change the state to active before | 382 | * initially active. So change the state to active before |
380 | * enabling the pm | 383 | * enabling the pm |
381 | */ | 384 | */ |
385 | |||
386 | if (!acpi_disabled) | ||
387 | pm_runtime_set_active(ctx->dev); | ||
388 | |||
382 | pm_runtime_enable(ctx->dev); | 389 | pm_runtime_enable(ctx->dev); |
383 | 390 | ||
384 | if (acpi_disabled) | 391 | if (acpi_disabled) |
@@ -409,6 +416,7 @@ static int intel_sst_runtime_suspend(struct device *dev) | |||
409 | synchronize_irq(ctx->irq_num); | 416 | synchronize_irq(ctx->irq_num); |
410 | flush_workqueue(ctx->post_msg_wq); | 417 | flush_workqueue(ctx->post_msg_wq); |
411 | 418 | ||
419 | ctx->ops->reset(ctx); | ||
412 | /* save the shim registers because PMC doesn't save state */ | 420 | /* save the shim registers because PMC doesn't save state */ |
413 | sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64); | 421 | sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64); |
414 | 422 | ||
diff --git a/sound/soc/intel/sst/sst.h b/sound/soc/intel/sst/sst.h index 7f4bbfcbc6f5..562bc483d6b7 100644 --- a/sound/soc/intel/sst/sst.h +++ b/sound/soc/intel/sst/sst.h | |||
@@ -58,6 +58,7 @@ enum sst_algo_ops { | |||
58 | #define SST_BLOCK_TIMEOUT 1000 | 58 | #define SST_BLOCK_TIMEOUT 1000 |
59 | 59 | ||
60 | #define FW_SIGNATURE_SIZE 4 | 60 | #define FW_SIGNATURE_SIZE 4 |
61 | #define FW_NAME_SIZE 32 | ||
61 | 62 | ||
62 | /* stream states */ | 63 | /* stream states */ |
63 | enum sst_stream_states { | 64 | enum sst_stream_states { |
@@ -426,7 +427,7 @@ struct intel_sst_drv { | |||
426 | * Holder for firmware name. Due to async call it needs to be | 427 | * Holder for firmware name. Due to async call it needs to be |
427 | * persistent till worker thread gets called | 428 | * persistent till worker thread gets called |
428 | */ | 429 | */ |
429 | char firmware_name[20]; | 430 | char firmware_name[FW_NAME_SIZE]; |
430 | }; | 431 | }; |
431 | 432 | ||
432 | /* misc definitions */ | 433 | /* misc definitions */ |
diff --git a/sound/soc/intel/sst/sst_acpi.c b/sound/soc/intel/sst/sst_acpi.c index b3360139c41a..b782dfdcdbba 100644 --- a/sound/soc/intel/sst/sst_acpi.c +++ b/sound/soc/intel/sst/sst_acpi.c | |||
@@ -47,7 +47,7 @@ struct sst_machines { | |||
47 | char board[32]; | 47 | char board[32]; |
48 | char machine[32]; | 48 | char machine[32]; |
49 | void (*machine_quirk)(void); | 49 | void (*machine_quirk)(void); |
50 | char firmware[32]; | 50 | char firmware[FW_NAME_SIZE]; |
51 | struct sst_platform_info *pdata; | 51 | struct sst_platform_info *pdata; |
52 | 52 | ||
53 | }; | 53 | }; |
@@ -245,7 +245,7 @@ static struct sst_machines *sst_acpi_find_machine( | |||
245 | return NULL; | 245 | return NULL; |
246 | } | 246 | } |
247 | 247 | ||
248 | int sst_acpi_probe(struct platform_device *pdev) | 248 | static int sst_acpi_probe(struct platform_device *pdev) |
249 | { | 249 | { |
250 | struct device *dev = &pdev->dev; | 250 | struct device *dev = &pdev->dev; |
251 | int ret = 0; | 251 | int ret = 0; |
@@ -332,7 +332,7 @@ do_sst_cleanup: | |||
332 | * This function is called by OS when a device is unloaded | 332 | * This function is called by OS when a device is unloaded |
333 | * This frees the interrupt etc | 333 | * This frees the interrupt etc |
334 | */ | 334 | */ |
335 | int sst_acpi_remove(struct platform_device *pdev) | 335 | static int sst_acpi_remove(struct platform_device *pdev) |
336 | { | 336 | { |
337 | struct intel_sst_drv *ctx; | 337 | struct intel_sst_drv *ctx; |
338 | 338 | ||
@@ -352,6 +352,8 @@ static struct sst_machines sst_acpi_bytcr[] = { | |||
352 | static struct sst_machines sst_acpi_chv[] = { | 352 | static struct sst_machines sst_acpi_chv[] = { |
353 | {"10EC5670", "cht-bsw", "cht-bsw-rt5672", NULL, "intel/fw_sst_22a8.bin", | 353 | {"10EC5670", "cht-bsw", "cht-bsw-rt5672", NULL, "intel/fw_sst_22a8.bin", |
354 | &chv_platform_data }, | 354 | &chv_platform_data }, |
355 | {"10EC5645", "cht-bsw", "cht-bsw-rt5645", NULL, "intel/fw_sst_22a8.bin", | ||
356 | &chv_platform_data }, | ||
355 | {}, | 357 | {}, |
356 | }; | 358 | }; |
357 | 359 | ||
@@ -366,7 +368,6 @@ MODULE_DEVICE_TABLE(acpi, sst_acpi_ids); | |||
366 | static struct platform_driver sst_acpi_driver = { | 368 | static struct platform_driver sst_acpi_driver = { |
367 | .driver = { | 369 | .driver = { |
368 | .name = "intel_sst_acpi", | 370 | .name = "intel_sst_acpi", |
369 | .owner = THIS_MODULE, | ||
370 | .acpi_match_table = ACPI_PTR(sst_acpi_ids), | 371 | .acpi_match_table = ACPI_PTR(sst_acpi_ids), |
371 | .pm = &intel_sst_pm, | 372 | .pm = &intel_sst_pm, |
372 | }, | 373 | }, |
diff --git a/sound/soc/intel/sst/sst_loader.c b/sound/soc/intel/sst/sst_loader.c index b580f96e25e5..7888cd707853 100644 --- a/sound/soc/intel/sst/sst_loader.c +++ b/sound/soc/intel/sst/sst_loader.c | |||
@@ -324,8 +324,7 @@ void sst_firmware_load_cb(const struct firmware *fw, void *context) | |||
324 | 324 | ||
325 | if (ctx->sst_state != SST_RESET || | 325 | if (ctx->sst_state != SST_RESET || |
326 | ctx->fw_in_mem != NULL) { | 326 | ctx->fw_in_mem != NULL) { |
327 | if (fw != NULL) | 327 | release_firmware(fw); |
328 | release_firmware(fw); | ||
329 | mutex_unlock(&ctx->sst_lock); | 328 | mutex_unlock(&ctx->sst_lock); |
330 | return; | 329 | return; |
331 | } | 330 | } |
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index d3d45c6f064f..07f77815a586 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c | |||
@@ -14,6 +14,8 @@ | |||
14 | 14 | ||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/of.h> | ||
18 | #include <linux/of_device.h> | ||
17 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | 20 | #include <linux/module.h> |
19 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
@@ -83,6 +85,8 @@ | |||
83 | #define JZ_AIC_I2S_STATUS_BUSY BIT(2) | 85 | #define JZ_AIC_I2S_STATUS_BUSY BIT(2) |
84 | 86 | ||
85 | #define JZ_AIC_CLK_DIV_MASK 0xf | 87 | #define JZ_AIC_CLK_DIV_MASK 0xf |
88 | #define I2SDIV_DV_SHIFT 8 | ||
89 | #define I2SDIV_DV_MASK (0xf << I2SDIV_DV_SHIFT) | ||
86 | 90 | ||
87 | struct jz4740_i2s { | 91 | struct jz4740_i2s { |
88 | struct resource *mem; | 92 | struct resource *mem; |
@@ -237,10 +241,14 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | |||
237 | { | 241 | { |
238 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 242 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
239 | unsigned int sample_size; | 243 | unsigned int sample_size; |
240 | uint32_t ctrl; | 244 | uint32_t ctrl, div_reg; |
245 | int div; | ||
241 | 246 | ||
242 | ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL); | 247 | ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL); |
243 | 248 | ||
249 | div_reg = jz4740_i2s_read(i2s, JZ_REG_AIC_CLK_DIV); | ||
250 | div = clk_get_rate(i2s->clk_i2s) / (64 * params_rate(params)); | ||
251 | |||
244 | switch (params_format(params)) { | 252 | switch (params_format(params)) { |
245 | case SNDRV_PCM_FORMAT_S8: | 253 | case SNDRV_PCM_FORMAT_S8: |
246 | sample_size = 0; | 254 | sample_size = 0; |
@@ -264,7 +272,10 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | |||
264 | ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; | 272 | ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; |
265 | } | 273 | } |
266 | 274 | ||
275 | div_reg &= ~I2SDIV_DV_MASK; | ||
276 | div_reg |= (div - 1) << I2SDIV_DV_SHIFT; | ||
267 | jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); | 277 | jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); |
278 | jz4740_i2s_write(i2s, JZ_REG_AIC_CLK_DIV, div_reg); | ||
268 | 279 | ||
269 | return 0; | 280 | return 0; |
270 | } | 281 | } |
@@ -415,6 +426,13 @@ static const struct snd_soc_component_driver jz4740_i2s_component = { | |||
415 | .name = "jz4740-i2s", | 426 | .name = "jz4740-i2s", |
416 | }; | 427 | }; |
417 | 428 | ||
429 | #ifdef CONFIG_OF | ||
430 | static const struct of_device_id jz4740_of_matches[] = { | ||
431 | { .compatible = "ingenic,jz4740-i2s" }, | ||
432 | { /* sentinel */ } | ||
433 | }; | ||
434 | #endif | ||
435 | |||
418 | static int jz4740_i2s_dev_probe(struct platform_device *pdev) | 436 | static int jz4740_i2s_dev_probe(struct platform_device *pdev) |
419 | { | 437 | { |
420 | struct jz4740_i2s *i2s; | 438 | struct jz4740_i2s *i2s; |
@@ -455,6 +473,7 @@ static struct platform_driver jz4740_i2s_driver = { | |||
455 | .probe = jz4740_i2s_dev_probe, | 473 | .probe = jz4740_i2s_dev_probe, |
456 | .driver = { | 474 | .driver = { |
457 | .name = "jz4740-i2s", | 475 | .name = "jz4740-i2s", |
476 | .of_match_table = of_match_ptr(jz4740_of_matches) | ||
458 | }, | 477 | }, |
459 | }; | 478 | }; |
460 | 479 | ||
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index d9865082160c..c866ade28ad0 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
@@ -710,7 +710,7 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
710 | struct device_node *np = pdev->dev.of_node; | 710 | struct device_node *np = pdev->dev.of_node; |
711 | struct resource *iores; | 711 | struct resource *iores; |
712 | struct mxs_saif *saif; | 712 | struct mxs_saif *saif; |
713 | int ret = 0; | 713 | int irq, ret = 0; |
714 | struct device_node *master; | 714 | struct device_node *master; |
715 | 715 | ||
716 | if (!np) | 716 | if (!np) |
@@ -763,16 +763,16 @@ static int mxs_saif_probe(struct platform_device *pdev) | |||
763 | if (IS_ERR(saif->base)) | 763 | if (IS_ERR(saif->base)) |
764 | return PTR_ERR(saif->base); | 764 | return PTR_ERR(saif->base); |
765 | 765 | ||
766 | saif->irq = platform_get_irq(pdev, 0); | 766 | irq = platform_get_irq(pdev, 0); |
767 | if (saif->irq < 0) { | 767 | if (irq < 0) { |
768 | ret = saif->irq; | 768 | ret = irq; |
769 | dev_err(&pdev->dev, "failed to get irq resource: %d\n", | 769 | dev_err(&pdev->dev, "failed to get irq resource: %d\n", |
770 | ret); | 770 | ret); |
771 | return ret; | 771 | return ret; |
772 | } | 772 | } |
773 | 773 | ||
774 | saif->dev = &pdev->dev; | 774 | saif->dev = &pdev->dev; |
775 | ret = devm_request_irq(&pdev->dev, saif->irq, mxs_saif_irq, 0, | 775 | ret = devm_request_irq(&pdev->dev, irq, mxs_saif_irq, 0, |
776 | dev_name(&pdev->dev), saif); | 776 | dev_name(&pdev->dev), saif); |
777 | if (ret) { | 777 | if (ret) { |
778 | dev_err(&pdev->dev, "failed to request irq\n"); | 778 | dev_err(&pdev->dev, "failed to request irq\n"); |
diff --git a/sound/soc/mxs/mxs-saif.h b/sound/soc/mxs/mxs-saif.h index fbaf7badfdfb..9a4c0b291b9e 100644 --- a/sound/soc/mxs/mxs-saif.h +++ b/sound/soc/mxs/mxs-saif.h | |||
@@ -116,7 +116,6 @@ struct mxs_saif { | |||
116 | unsigned int mclk; | 116 | unsigned int mclk; |
117 | unsigned int mclk_in_use; | 117 | unsigned int mclk_in_use; |
118 | void __iomem *base; | 118 | void __iomem *base; |
119 | int irq; | ||
120 | unsigned int id; | 119 | unsigned int id; |
121 | unsigned int master_id; | 120 | unsigned int master_id; |
122 | unsigned int cur_rate; | 121 | unsigned int cur_rate; |
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 6f1916b71815..6e6fce6a14ba 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c | |||
@@ -36,7 +36,7 @@ static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream, | |||
36 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 36 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
37 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 37 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
38 | unsigned int rate = params_rate(params); | 38 | unsigned int rate = params_rate(params); |
39 | u32 dai_format, mclk; | 39 | u32 mclk; |
40 | int ret; | 40 | int ret; |
41 | 41 | ||
42 | /* sgtl5000 does not support 512*rate when in 96000 fs */ | 42 | /* sgtl5000 does not support 512*rate when in 96000 fs */ |
@@ -65,26 +65,6 @@ static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream, | |||
65 | return ret; | 65 | return ret; |
66 | } | 66 | } |
67 | 67 | ||
68 | /* set codec to slave mode */ | ||
69 | dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
70 | SND_SOC_DAIFMT_CBS_CFS; | ||
71 | |||
72 | /* set codec DAI configuration */ | ||
73 | ret = snd_soc_dai_set_fmt(codec_dai, dai_format); | ||
74 | if (ret) { | ||
75 | dev_err(codec_dai->dev, "Failed to set dai format to %08x\n", | ||
76 | dai_format); | ||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | /* set cpu DAI configuration */ | ||
81 | ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); | ||
82 | if (ret) { | ||
83 | dev_err(cpu_dai->dev, "Failed to set dai format to %08x\n", | ||
84 | dai_format); | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | return 0; | 68 | return 0; |
89 | } | 69 | } |
90 | 70 | ||
@@ -92,17 +72,22 @@ static struct snd_soc_ops mxs_sgtl5000_hifi_ops = { | |||
92 | .hw_params = mxs_sgtl5000_hw_params, | 72 | .hw_params = mxs_sgtl5000_hw_params, |
93 | }; | 73 | }; |
94 | 74 | ||
75 | #define MXS_SGTL5000_DAI_FMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \ | ||
76 | SND_SOC_DAIFMT_CBS_CFS) | ||
77 | |||
95 | static struct snd_soc_dai_link mxs_sgtl5000_dai[] = { | 78 | static struct snd_soc_dai_link mxs_sgtl5000_dai[] = { |
96 | { | 79 | { |
97 | .name = "HiFi Tx", | 80 | .name = "HiFi Tx", |
98 | .stream_name = "HiFi Playback", | 81 | .stream_name = "HiFi Playback", |
99 | .codec_dai_name = "sgtl5000", | 82 | .codec_dai_name = "sgtl5000", |
83 | .dai_fmt = MXS_SGTL5000_DAI_FMT, | ||
100 | .ops = &mxs_sgtl5000_hifi_ops, | 84 | .ops = &mxs_sgtl5000_hifi_ops, |
101 | .playback_only = true, | 85 | .playback_only = true, |
102 | }, { | 86 | }, { |
103 | .name = "HiFi Rx", | 87 | .name = "HiFi Rx", |
104 | .stream_name = "HiFi Capture", | 88 | .stream_name = "HiFi Capture", |
105 | .codec_dai_name = "sgtl5000", | 89 | .codec_dai_name = "sgtl5000", |
90 | .dai_fmt = MXS_SGTL5000_DAI_FMT, | ||
106 | .ops = &mxs_sgtl5000_hifi_ops, | 91 | .ops = &mxs_sgtl5000_hifi_ops, |
107 | .capture_only = true, | 92 | .capture_only = true, |
108 | }, | 93 | }, |
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c index b779a3d9b5dd..b809fa909e4d 100644 --- a/sound/soc/nuc900/nuc900-pcm.c +++ b/sound/soc/nuc900/nuc900-pcm.c | |||
@@ -306,11 +306,6 @@ static struct snd_pcm_ops nuc900_dma_ops = { | |||
306 | .mmap = nuc900_dma_mmap, | 306 | .mmap = nuc900_dma_mmap, |
307 | }; | 307 | }; |
308 | 308 | ||
309 | static void nuc900_dma_free_dma_buffers(struct snd_pcm *pcm) | ||
310 | { | ||
311 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
312 | } | ||
313 | |||
314 | static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd) | 309 | static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd) |
315 | { | 310 | { |
316 | struct snd_card *card = rtd->card->snd_card; | 311 | struct snd_card *card = rtd->card->snd_card; |
@@ -330,7 +325,6 @@ static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd) | |||
330 | static struct snd_soc_platform_driver nuc900_soc_platform = { | 325 | static struct snd_soc_platform_driver nuc900_soc_platform = { |
331 | .ops = &nuc900_dma_ops, | 326 | .ops = &nuc900_dma_ops, |
332 | .pcm_new = nuc900_dma_new, | 327 | .pcm_new = nuc900_dma_new, |
333 | .pcm_free = nuc900_dma_free_dma_buffers, | ||
334 | }; | 328 | }; |
335 | 329 | ||
336 | static int nuc900_soc_platform_probe(struct platform_device *pdev) | 330 | static int nuc900_soc_platform_probe(struct platform_device *pdev) |
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 4c6afb75eea6..706613077c15 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c | |||
@@ -412,21 +412,7 @@ static struct tty_ldisc_ops cx81801_ops = { | |||
412 | * over the modem port. | 412 | * over the modem port. |
413 | */ | 413 | */ |
414 | 414 | ||
415 | static int ams_delta_hw_params(struct snd_pcm_substream *substream, | 415 | static struct snd_soc_ops ams_delta_ops; |
416 | struct snd_pcm_hw_params *params) | ||
417 | { | ||
418 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
419 | |||
420 | /* Set cpu DAI configuration */ | ||
421 | return snd_soc_dai_set_fmt(rtd->cpu_dai, | ||
422 | SND_SOC_DAIFMT_DSP_A | | ||
423 | SND_SOC_DAIFMT_NB_NF | | ||
424 | SND_SOC_DAIFMT_CBM_CFM); | ||
425 | } | ||
426 | |||
427 | static struct snd_soc_ops ams_delta_ops = { | ||
428 | .hw_params = ams_delta_hw_params, | ||
429 | }; | ||
430 | 416 | ||
431 | 417 | ||
432 | /* Digital mute implemented using modem/CPU multiplexer. | 418 | /* Digital mute implemented using modem/CPU multiplexer. |
@@ -546,6 +532,8 @@ static struct snd_soc_dai_link ams_delta_dai_link = { | |||
546 | .platform_name = "omap-mcbsp.1", | 532 | .platform_name = "omap-mcbsp.1", |
547 | .codec_name = "cx20442-codec", | 533 | .codec_name = "cx20442-codec", |
548 | .ops = &ams_delta_ops, | 534 | .ops = &ams_delta_ops, |
535 | .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | | ||
536 | SND_SOC_DAIFMT_CBM_CFM, | ||
549 | }; | 537 | }; |
550 | 538 | ||
551 | /* Audio card driver */ | 539 | /* Audio card driver */ |
diff --git a/sound/soc/omap/omap-hdmi-audio.c b/sound/soc/omap/omap-hdmi-audio.c index 3f9ac7dbdc80..f7eb42aa3f38 100644 --- a/sound/soc/omap/omap-hdmi-audio.c +++ b/sound/soc/omap/omap-hdmi-audio.c | |||
@@ -352,6 +352,9 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) | |||
352 | return ret; | 352 | return ret; |
353 | 353 | ||
354 | card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); | 354 | card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); |
355 | if (!card) | ||
356 | return -ENOMEM; | ||
357 | |||
355 | card->name = devm_kasprintf(dev, GFP_KERNEL, | 358 | card->name = devm_kasprintf(dev, GFP_KERNEL, |
356 | "HDMI %s", dev_name(ad->dssdev)); | 359 | "HDMI %s", dev_name(ad->dssdev)); |
357 | card->owner = THIS_MODULE; | 360 | card->owner = THIS_MODULE; |
@@ -393,7 +396,6 @@ static int omap_hdmi_audio_remove(struct platform_device *pdev) | |||
393 | static struct platform_driver hdmi_audio_driver = { | 396 | static struct platform_driver hdmi_audio_driver = { |
394 | .driver = { | 397 | .driver = { |
395 | .name = DRV_NAME, | 398 | .name = DRV_NAME, |
396 | .owner = THIS_MODULE, | ||
397 | }, | 399 | }, |
398 | .probe = omap_hdmi_audio_probe, | 400 | .probe = omap_hdmi_audio_probe, |
399 | .remove = omap_hdmi_audio_remove, | 401 | .remove = omap_hdmi_audio_remove, |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index c7eb9dd67f60..fd99d89de6a8 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -530,8 +530,19 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
530 | 530 | ||
531 | case OMAP_MCBSP_SYSCLK_CLKX_EXT: | 531 | case OMAP_MCBSP_SYSCLK_CLKX_EXT: |
532 | regs->srgr2 |= CLKSM; | 532 | regs->srgr2 |= CLKSM; |
533 | regs->pcr0 |= SCLKME; | ||
534 | /* | ||
535 | * If McBSP is master but yet the CLKX/CLKR pin drives the SRG, | ||
536 | * disable output on those pins. This enables to inject the | ||
537 | * reference clock through CLKX/CLKR. For this to work | ||
538 | * set_dai_sysclk() _needs_ to be called after set_dai_fmt(). | ||
539 | */ | ||
540 | regs->pcr0 &= ~CLKXM; | ||
541 | break; | ||
533 | case OMAP_MCBSP_SYSCLK_CLKR_EXT: | 542 | case OMAP_MCBSP_SYSCLK_CLKR_EXT: |
534 | regs->pcr0 |= SCLKME; | 543 | regs->pcr0 |= SCLKME; |
544 | /* Disable ouput on CLKR pin in master mode */ | ||
545 | regs->pcr0 &= ~CLKRM; | ||
535 | break; | 546 | break; |
536 | default: | 547 | default: |
537 | err = -ENODEV; | 548 | err = -ENODEV; |
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index f4b05bc23e4b..1343ecbf0bd5 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -201,7 +201,7 @@ static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
201 | struct snd_pcm *pcm = rtd->pcm; | 201 | struct snd_pcm *pcm = rtd->pcm; |
202 | int ret; | 202 | int ret; |
203 | 203 | ||
204 | ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(64)); | 204 | ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); |
205 | if (ret) | 205 | if (ret) |
206 | return ret; | 206 | return ret; |
207 | 207 | ||
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c index 5e551c762b7a..fb1f6bb87cd4 100644 --- a/sound/soc/omap/omap-twl4030.c +++ b/sound/soc/omap/omap-twl4030.c | |||
@@ -53,11 +53,7 @@ static int omap_twl4030_hw_params(struct snd_pcm_substream *substream, | |||
53 | struct snd_pcm_hw_params *params) | 53 | struct snd_pcm_hw_params *params) |
54 | { | 54 | { |
55 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 55 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
56 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
57 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
58 | struct snd_soc_card *card = rtd->card; | ||
59 | unsigned int fmt; | 56 | unsigned int fmt; |
60 | int ret; | ||
61 | 57 | ||
62 | switch (params_channels(params)) { | 58 | switch (params_channels(params)) { |
63 | case 2: /* Stereo I2S mode */ | 59 | case 2: /* Stereo I2S mode */ |
@@ -74,21 +70,7 @@ static int omap_twl4030_hw_params(struct snd_pcm_substream *substream, | |||
74 | return -EINVAL; | 70 | return -EINVAL; |
75 | } | 71 | } |
76 | 72 | ||
77 | /* Set codec DAI configuration */ | 73 | return snd_soc_runtime_set_dai_fmt(rtd, fmt); |
78 | ret = snd_soc_dai_set_fmt(codec_dai, fmt); | ||
79 | if (ret < 0) { | ||
80 | dev_err(card->dev, "can't set codec DAI configuration\n"); | ||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | /* Set cpu DAI configuration */ | ||
85 | ret = snd_soc_dai_set_fmt(cpu_dai, fmt); | ||
86 | if (ret < 0) { | ||
87 | dev_err(card->dev, "can't set cpu DAI configuration\n"); | ||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | return 0; | ||
92 | } | 74 | } |
93 | 75 | ||
94 | static struct snd_soc_ops omap_twl4030_ops = { | 76 | static struct snd_soc_ops omap_twl4030_ops = { |
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 04896d6252a2..7f299357c2d2 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c | |||
@@ -250,14 +250,14 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
250 | {"FM Transmitter", NULL, "LLOUT"}, | 250 | {"FM Transmitter", NULL, "LLOUT"}, |
251 | {"FM Transmitter", NULL, "RLOUT"}, | 251 | {"FM Transmitter", NULL, "RLOUT"}, |
252 | 252 | ||
253 | {"DMic Rate 64", NULL, "Mic Bias"}, | 253 | {"DMic Rate 64", NULL, "DMic"}, |
254 | {"Mic Bias", NULL, "DMic"}, | 254 | {"DMic", NULL, "Mic Bias"}, |
255 | 255 | ||
256 | {"b LINE2R", NULL, "MONO_LOUT"}, | 256 | {"b LINE2R", NULL, "MONO_LOUT"}, |
257 | {"Earphone", NULL, "b HPLOUT"}, | 257 | {"Earphone", NULL, "b HPLOUT"}, |
258 | 258 | ||
259 | {"LINE1L", NULL, "b Mic Bias"}, | 259 | {"LINE1L", NULL, "HS Mic"}, |
260 | {"b Mic Bias", NULL, "HS Mic"} | 260 | {"HS Mic", NULL, "b Mic Bias"}, |
261 | }; | 261 | }; |
262 | 262 | ||
263 | static const char * const spk_function[] = {"Off", "On"}; | 263 | static const char * const spk_function[] = {"Off", "On"}; |
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 2434b6d61675..39cea80846c3 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
@@ -140,7 +140,7 @@ config SND_PXA910_SOC | |||
140 | Marvell PXA910 reference platform. | 140 | Marvell PXA910 reference platform. |
141 | 141 | ||
142 | config SND_SOC_TTC_DKB | 142 | config SND_SOC_TTC_DKB |
143 | bool "SoC Audio support for TTC DKB" | 143 | tristate "SoC Audio support for TTC DKB" |
144 | depends on SND_PXA910_SOC && MACH_TTC_DKB && I2C=y | 144 | depends on SND_PXA910_SOC && MACH_TTC_DKB && I2C=y |
145 | select PXA_SSP | 145 | select PXA_SSP |
146 | select SND_PXA_SOC_SSP | 146 | select SND_PXA_SOC_SSP |
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index b7cd0a71fd70..3580d10c9f28 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c | |||
@@ -259,20 +259,6 @@ static const struct snd_kcontrol_new wm8731_corgi_controls[] = { | |||
259 | corgi_set_spk), | 259 | corgi_set_spk), |
260 | }; | 260 | }; |
261 | 261 | ||
262 | /* | ||
263 | * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device | ||
264 | */ | ||
265 | static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd) | ||
266 | { | ||
267 | struct snd_soc_codec *codec = rtd->codec; | ||
268 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
269 | |||
270 | snd_soc_dapm_nc_pin(dapm, "LLINEIN"); | ||
271 | snd_soc_dapm_nc_pin(dapm, "RLINEIN"); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | /* corgi digital audio interface glue - connects codec <--> CPU */ | 262 | /* corgi digital audio interface glue - connects codec <--> CPU */ |
277 | static struct snd_soc_dai_link corgi_dai = { | 263 | static struct snd_soc_dai_link corgi_dai = { |
278 | .name = "WM8731", | 264 | .name = "WM8731", |
@@ -281,7 +267,6 @@ static struct snd_soc_dai_link corgi_dai = { | |||
281 | .codec_dai_name = "wm8731-hifi", | 267 | .codec_dai_name = "wm8731-hifi", |
282 | .platform_name = "pxa-pcm-audio", | 268 | .platform_name = "pxa-pcm-audio", |
283 | .codec_name = "wm8731.0-001b", | 269 | .codec_name = "wm8731.0-001b", |
284 | .init = corgi_wm8731_init, | ||
285 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | 270 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | |
286 | SND_SOC_DAIFMT_CBS_CFS, | 271 | SND_SOC_DAIFMT_CBS_CFS, |
287 | .ops = &corgi_ops, | 272 | .ops = &corgi_ops, |
@@ -300,6 +285,7 @@ static struct snd_soc_card corgi = { | |||
300 | .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), | 285 | .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), |
301 | .dapm_routes = corgi_audio_map, | 286 | .dapm_routes = corgi_audio_map, |
302 | .num_dapm_routes = ARRAY_SIZE(corgi_audio_map), | 287 | .num_dapm_routes = ARRAY_SIZE(corgi_audio_map), |
288 | .fully_routed = true, | ||
303 | }; | 289 | }; |
304 | 290 | ||
305 | static int corgi_probe(struct platform_device *pdev) | 291 | static int corgi_probe(struct platform_device *pdev) |
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index 7c691aae8af2..d72e124a3676 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c | |||
@@ -88,24 +88,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
88 | {"Mic Amp", NULL, "Mic (Internal)"}, | 88 | {"Mic Amp", NULL, "Mic (Internal)"}, |
89 | }; | 89 | }; |
90 | 90 | ||
91 | static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd) | ||
92 | { | ||
93 | struct snd_soc_codec *codec = rtd->codec; | ||
94 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
95 | |||
96 | snd_soc_dapm_nc_pin(dapm, "HPOUTL"); | ||
97 | snd_soc_dapm_nc_pin(dapm, "HPOUTR"); | ||
98 | snd_soc_dapm_nc_pin(dapm, "PHONE"); | ||
99 | snd_soc_dapm_nc_pin(dapm, "LINEINL"); | ||
100 | snd_soc_dapm_nc_pin(dapm, "LINEINR"); | ||
101 | snd_soc_dapm_nc_pin(dapm, "CDINL"); | ||
102 | snd_soc_dapm_nc_pin(dapm, "CDINR"); | ||
103 | snd_soc_dapm_nc_pin(dapm, "PCBEEP"); | ||
104 | snd_soc_dapm_nc_pin(dapm, "MIC2"); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static struct snd_soc_dai_link e740_dai[] = { | 91 | static struct snd_soc_dai_link e740_dai[] = { |
110 | { | 92 | { |
111 | .name = "AC97", | 93 | .name = "AC97", |
@@ -114,7 +96,6 @@ static struct snd_soc_dai_link e740_dai[] = { | |||
114 | .codec_dai_name = "wm9705-hifi", | 96 | .codec_dai_name = "wm9705-hifi", |
115 | .platform_name = "pxa-pcm-audio", | 97 | .platform_name = "pxa-pcm-audio", |
116 | .codec_name = "wm9705-codec", | 98 | .codec_name = "wm9705-codec", |
117 | .init = e740_ac97_init, | ||
118 | }, | 99 | }, |
119 | { | 100 | { |
120 | .name = "AC97 Aux", | 101 | .name = "AC97 Aux", |
@@ -136,6 +117,7 @@ static struct snd_soc_card e740 = { | |||
136 | .num_dapm_widgets = ARRAY_SIZE(e740_dapm_widgets), | 117 | .num_dapm_widgets = ARRAY_SIZE(e740_dapm_widgets), |
137 | .dapm_routes = audio_map, | 118 | .dapm_routes = audio_map, |
138 | .num_dapm_routes = ARRAY_SIZE(audio_map), | 119 | .num_dapm_routes = ARRAY_SIZE(audio_map), |
120 | .fully_routed = true, | ||
139 | }; | 121 | }; |
140 | 122 | ||
141 | static struct gpio e740_audio_gpios[] = { | 123 | static struct gpio e740_audio_gpios[] = { |
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index 30544b65b5a8..48f2d7c2e68c 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c | |||
@@ -70,24 +70,6 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
70 | {"MIC1", NULL, "Mic (Internal)"}, | 70 | {"MIC1", NULL, "Mic (Internal)"}, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd) | ||
74 | { | ||
75 | struct snd_soc_codec *codec = rtd->codec; | ||
76 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
77 | |||
78 | snd_soc_dapm_nc_pin(dapm, "LOUT"); | ||
79 | snd_soc_dapm_nc_pin(dapm, "ROUT"); | ||
80 | snd_soc_dapm_nc_pin(dapm, "PHONE"); | ||
81 | snd_soc_dapm_nc_pin(dapm, "LINEINL"); | ||
82 | snd_soc_dapm_nc_pin(dapm, "LINEINR"); | ||
83 | snd_soc_dapm_nc_pin(dapm, "CDINL"); | ||
84 | snd_soc_dapm_nc_pin(dapm, "CDINR"); | ||
85 | snd_soc_dapm_nc_pin(dapm, "PCBEEP"); | ||
86 | snd_soc_dapm_nc_pin(dapm, "MIC2"); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static struct snd_soc_dai_link e750_dai[] = { | 73 | static struct snd_soc_dai_link e750_dai[] = { |
92 | { | 74 | { |
93 | .name = "AC97", | 75 | .name = "AC97", |
@@ -96,7 +78,6 @@ static struct snd_soc_dai_link e750_dai[] = { | |||
96 | .codec_dai_name = "wm9705-hifi", | 78 | .codec_dai_name = "wm9705-hifi", |
97 | .platform_name = "pxa-pcm-audio", | 79 | .platform_name = "pxa-pcm-audio", |
98 | .codec_name = "wm9705-codec", | 80 | .codec_name = "wm9705-codec", |
99 | .init = e750_ac97_init, | ||
100 | /* use ops to check startup state */ | 81 | /* use ops to check startup state */ |
101 | }, | 82 | }, |
102 | { | 83 | { |
@@ -119,6 +100,7 @@ static struct snd_soc_card e750 = { | |||
119 | .num_dapm_widgets = ARRAY_SIZE(e750_dapm_widgets), | 100 | .num_dapm_widgets = ARRAY_SIZE(e750_dapm_widgets), |
120 | .dapm_routes = audio_map, | 101 | .dapm_routes = audio_map, |
121 | .num_dapm_routes = ARRAY_SIZE(audio_map), | 102 | .num_dapm_routes = ARRAY_SIZE(audio_map), |
103 | .fully_routed = true, | ||
122 | }; | 104 | }; |
123 | 105 | ||
124 | static struct gpio e750_audio_gpios[] = { | 106 | static struct gpio e750_audio_gpios[] = { |
diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c index ce26551052a3..73eb5ddf9753 100644 --- a/sound/soc/pxa/hx4700.c +++ b/sound/soc/pxa/hx4700.c | |||
@@ -127,15 +127,8 @@ static const struct snd_soc_dapm_route hx4700_audio_map[] = { | |||
127 | static int hx4700_ak4641_init(struct snd_soc_pcm_runtime *rtd) | 127 | static int hx4700_ak4641_init(struct snd_soc_pcm_runtime *rtd) |
128 | { | 128 | { |
129 | struct snd_soc_codec *codec = rtd->codec; | 129 | struct snd_soc_codec *codec = rtd->codec; |
130 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
131 | int err; | 130 | int err; |
132 | 131 | ||
133 | /* NC codec pins */ | ||
134 | /* FIXME: is anything connected here? */ | ||
135 | snd_soc_dapm_nc_pin(dapm, "MOUT1"); | ||
136 | snd_soc_dapm_nc_pin(dapm, "MICEXT"); | ||
137 | snd_soc_dapm_nc_pin(dapm, "AUX"); | ||
138 | |||
139 | /* Jack detection API stuff */ | 132 | /* Jack detection API stuff */ |
140 | err = snd_soc_jack_new(codec, "Headphone Jack", | 133 | err = snd_soc_jack_new(codec, "Headphone Jack", |
141 | SND_JACK_HEADPHONE, &hs_jack); | 134 | SND_JACK_HEADPHONE, &hs_jack); |
@@ -184,6 +177,7 @@ static struct snd_soc_card snd_soc_card_hx4700 = { | |||
184 | .num_dapm_widgets = ARRAY_SIZE(hx4700_dapm_widgets), | 177 | .num_dapm_widgets = ARRAY_SIZE(hx4700_dapm_widgets), |
185 | .dapm_routes = hx4700_audio_map, | 178 | .dapm_routes = hx4700_audio_map, |
186 | .num_dapm_routes = ARRAY_SIZE(hx4700_audio_map), | 179 | .num_dapm_routes = ARRAY_SIZE(hx4700_audio_map), |
180 | .fully_routed = true, | ||
187 | }; | 181 | }; |
188 | 182 | ||
189 | static struct gpio hx4700_audio_gpios[] = { | 183 | static struct gpio hx4700_audio_gpios[] = { |
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index 259e048681c0..241d0be42d7a 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c | |||
@@ -391,25 +391,6 @@ static const struct snd_kcontrol_new uda1380_magician_controls[] = { | |||
391 | magician_get_input, magician_set_input), | 391 | magician_get_input, magician_set_input), |
392 | }; | 392 | }; |
393 | 393 | ||
394 | /* | ||
395 | * Logic for a uda1380 as connected on a HTC Magician | ||
396 | */ | ||
397 | static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd) | ||
398 | { | ||
399 | struct snd_soc_codec *codec = rtd->codec; | ||
400 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
401 | |||
402 | /* NC codec pins */ | ||
403 | snd_soc_dapm_nc_pin(dapm, "VOUTLHP"); | ||
404 | snd_soc_dapm_nc_pin(dapm, "VOUTRHP"); | ||
405 | |||
406 | /* FIXME: is anything connected here? */ | ||
407 | snd_soc_dapm_nc_pin(dapm, "VINL"); | ||
408 | snd_soc_dapm_nc_pin(dapm, "VINR"); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | /* magician digital audio interface glue - connects codec <--> CPU */ | 394 | /* magician digital audio interface glue - connects codec <--> CPU */ |
414 | static struct snd_soc_dai_link magician_dai[] = { | 395 | static struct snd_soc_dai_link magician_dai[] = { |
415 | { | 396 | { |
@@ -419,7 +400,6 @@ static struct snd_soc_dai_link magician_dai[] = { | |||
419 | .codec_dai_name = "uda1380-hifi-playback", | 400 | .codec_dai_name = "uda1380-hifi-playback", |
420 | .platform_name = "pxa-pcm-audio", | 401 | .platform_name = "pxa-pcm-audio", |
421 | .codec_name = "uda1380-codec.0-0018", | 402 | .codec_name = "uda1380-codec.0-0018", |
422 | .init = magician_uda1380_init, | ||
423 | .ops = &magician_playback_ops, | 403 | .ops = &magician_playback_ops, |
424 | }, | 404 | }, |
425 | { | 405 | { |
@@ -446,6 +426,7 @@ static struct snd_soc_card snd_soc_card_magician = { | |||
446 | .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), | 426 | .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), |
447 | .dapm_routes = audio_map, | 427 | .dapm_routes = audio_map, |
448 | .num_dapm_routes = ARRAY_SIZE(audio_map), | 428 | .num_dapm_routes = ARRAY_SIZE(audio_map), |
429 | .fully_routed = true, | ||
449 | }; | 430 | }; |
450 | 431 | ||
451 | static struct platform_device *magician_snd_device; | 432 | static struct platform_device *magician_snd_device; |
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 396dbd51a64f..a9615a574546 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c | |||
@@ -81,7 +81,7 @@ static int rear_amp_power(struct snd_soc_codec *codec, int power) | |||
81 | static int rear_amp_event(struct snd_soc_dapm_widget *widget, | 81 | static int rear_amp_event(struct snd_soc_dapm_widget *widget, |
82 | struct snd_kcontrol *kctl, int event) | 82 | struct snd_kcontrol *kctl, int event) |
83 | { | 83 | { |
84 | struct snd_soc_codec *codec = widget->codec; | 84 | struct snd_soc_codec *codec = widget->dapm->card->rtd[0].codec; |
85 | 85 | ||
86 | return rear_amp_power(codec, SND_SOC_DAPM_EVENT_ON(event)); | 86 | return rear_amp_power(codec, SND_SOC_DAPM_EVENT_ON(event)); |
87 | } | 87 | } |
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 1eebca2f0a97..910336c5ebeb 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c | |||
@@ -68,7 +68,7 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
68 | {"Ext. Speaker", NULL, "ROUT2"}, | 68 | {"Ext. Speaker", NULL, "ROUT2"}, |
69 | 69 | ||
70 | /* mic connected to MIC1 */ | 70 | /* mic connected to MIC1 */ |
71 | {"Ext. Microphone", NULL, "MIC1"}, | 71 | {"MIC1", NULL, "Ext. Microphone"}, |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static struct snd_soc_card palm27x_asoc; | 74 | static struct snd_soc_card palm27x_asoc; |
@@ -76,18 +76,8 @@ static struct snd_soc_card palm27x_asoc; | |||
76 | static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd) | 76 | static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd) |
77 | { | 77 | { |
78 | struct snd_soc_codec *codec = rtd->codec; | 78 | struct snd_soc_codec *codec = rtd->codec; |
79 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
80 | int err; | 79 | int err; |
81 | 80 | ||
82 | /* not connected pins */ | ||
83 | snd_soc_dapm_nc_pin(dapm, "OUT3"); | ||
84 | snd_soc_dapm_nc_pin(dapm, "MONOOUT"); | ||
85 | snd_soc_dapm_nc_pin(dapm, "LINEINL"); | ||
86 | snd_soc_dapm_nc_pin(dapm, "LINEINR"); | ||
87 | snd_soc_dapm_nc_pin(dapm, "PCBEEP"); | ||
88 | snd_soc_dapm_nc_pin(dapm, "PHONE"); | ||
89 | snd_soc_dapm_nc_pin(dapm, "MIC2"); | ||
90 | |||
91 | /* Jack detection API stuff */ | 81 | /* Jack detection API stuff */ |
92 | err = snd_soc_jack_new(codec, "Headphone Jack", | 82 | err = snd_soc_jack_new(codec, "Headphone Jack", |
93 | SND_JACK_HEADPHONE, &hs_jack); | 83 | SND_JACK_HEADPHONE, &hs_jack); |
@@ -133,7 +123,8 @@ static struct snd_soc_card palm27x_asoc = { | |||
133 | .dapm_widgets = palm27x_dapm_widgets, | 123 | .dapm_widgets = palm27x_dapm_widgets, |
134 | .num_dapm_widgets = ARRAY_SIZE(palm27x_dapm_widgets), | 124 | .num_dapm_widgets = ARRAY_SIZE(palm27x_dapm_widgets), |
135 | .dapm_routes = audio_map, | 125 | .dapm_routes = audio_map, |
136 | .num_dapm_routes = ARRAY_SIZE(audio_map) | 126 | .num_dapm_routes = ARRAY_SIZE(audio_map), |
127 | .fully_routed = true, | ||
137 | }; | 128 | }; |
138 | 129 | ||
139 | static int palm27x_asoc_probe(struct platform_device *pdev) | 130 | static int palm27x_asoc_probe(struct platform_device *pdev) |
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c index 083706595495..552b763005ed 100644 --- a/sound/soc/pxa/raumfeld.c +++ b/sound/soc/pxa/raumfeld.c | |||
@@ -88,7 +88,7 @@ static int raumfeld_cs4270_hw_params(struct snd_pcm_substream *substream, | |||
88 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 88 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
89 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 89 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
90 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 90 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
91 | unsigned int fmt, clk = 0; | 91 | unsigned int clk = 0; |
92 | int ret = 0; | 92 | int ret = 0; |
93 | 93 | ||
94 | switch (params_rate(params)) { | 94 | switch (params_rate(params)) { |
@@ -112,15 +112,6 @@ static int raumfeld_cs4270_hw_params(struct snd_pcm_substream *substream, | |||
112 | return -EINVAL; | 112 | return -EINVAL; |
113 | } | 113 | } |
114 | 114 | ||
115 | fmt = SND_SOC_DAIFMT_I2S | | ||
116 | SND_SOC_DAIFMT_NB_NF | | ||
117 | SND_SOC_DAIFMT_CBS_CFS; | ||
118 | |||
119 | /* setup the CODEC DAI */ | ||
120 | ret = snd_soc_dai_set_fmt(codec_dai, fmt); | ||
121 | if (ret < 0) | ||
122 | return ret; | ||
123 | |||
124 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk, 0); | 115 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk, 0); |
125 | if (ret < 0) | 116 | if (ret < 0) |
126 | return ret; | 117 | return ret; |
@@ -130,10 +121,6 @@ static int raumfeld_cs4270_hw_params(struct snd_pcm_substream *substream, | |||
130 | if (ret < 0) | 121 | if (ret < 0) |
131 | return ret; | 122 | return ret; |
132 | 123 | ||
133 | ret = snd_soc_dai_set_fmt(cpu_dai, fmt); | ||
134 | if (ret < 0) | ||
135 | return ret; | ||
136 | |||
137 | ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_DIV_SCR, 4); | 124 | ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_DIV_SCR, 4); |
138 | if (ret < 0) | 125 | if (ret < 0) |
139 | return ret; | 126 | return ret; |
@@ -169,9 +156,8 @@ static int raumfeld_ak4104_hw_params(struct snd_pcm_substream *substream, | |||
169 | struct snd_pcm_hw_params *params) | 156 | struct snd_pcm_hw_params *params) |
170 | { | 157 | { |
171 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 158 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
172 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
173 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 159 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
174 | int fmt, ret = 0, clk = 0; | 160 | int ret = 0, clk = 0; |
175 | 161 | ||
176 | switch (params_rate(params)) { | 162 | switch (params_rate(params)) { |
177 | case 44100: | 163 | case 44100: |
@@ -194,22 +180,11 @@ static int raumfeld_ak4104_hw_params(struct snd_pcm_substream *substream, | |||
194 | return -EINVAL; | 180 | return -EINVAL; |
195 | } | 181 | } |
196 | 182 | ||
197 | fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF; | ||
198 | |||
199 | /* setup the CODEC DAI */ | ||
200 | ret = snd_soc_dai_set_fmt(codec_dai, fmt | SND_SOC_DAIFMT_CBS_CFS); | ||
201 | if (ret < 0) | ||
202 | return ret; | ||
203 | |||
204 | /* setup the CPU DAI */ | 183 | /* setup the CPU DAI */ |
205 | ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, clk); | 184 | ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, clk); |
206 | if (ret < 0) | 185 | if (ret < 0) |
207 | return ret; | 186 | return ret; |
208 | 187 | ||
209 | ret = snd_soc_dai_set_fmt(cpu_dai, fmt | SND_SOC_DAIFMT_CBS_CFS); | ||
210 | if (ret < 0) | ||
211 | return ret; | ||
212 | |||
213 | ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_DIV_SCR, 4); | 188 | ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_DIV_SCR, 4); |
214 | if (ret < 0) | 189 | if (ret < 0) |
215 | return ret; | 190 | return ret; |
@@ -233,6 +208,9 @@ static struct snd_soc_ops raumfeld_ak4104_ops = { | |||
233 | .platform_name = "pxa-pcm-audio", \ | 208 | .platform_name = "pxa-pcm-audio", \ |
234 | .codec_dai_name = "cs4270-hifi", \ | 209 | .codec_dai_name = "cs4270-hifi", \ |
235 | .codec_name = "cs4270.0-0048", \ | 210 | .codec_name = "cs4270.0-0048", \ |
211 | .dai_fmt = SND_SOC_DAIFMT_I2S | \ | ||
212 | SND_SOC_DAIFMT_NB_NF | \ | ||
213 | SND_SOC_DAIFMT_CBS_CFS, \ | ||
236 | .ops = &raumfeld_cs4270_ops, \ | 214 | .ops = &raumfeld_cs4270_ops, \ |
237 | } | 215 | } |
238 | 216 | ||
@@ -243,6 +221,9 @@ static struct snd_soc_ops raumfeld_ak4104_ops = { | |||
243 | .cpu_dai_name = "pxa-ssp-dai.1", \ | 221 | .cpu_dai_name = "pxa-ssp-dai.1", \ |
244 | .codec_dai_name = "ak4104-hifi", \ | 222 | .codec_dai_name = "ak4104-hifi", \ |
245 | .platform_name = "pxa-pcm-audio", \ | 223 | .platform_name = "pxa-pcm-audio", \ |
224 | .dai_fmt = SND_SOC_DAIFMT_I2S | \ | ||
225 | SND_SOC_DAIFMT_NB_NF | \ | ||
226 | SND_SOC_DAIFMT_CBS_CFS, \ | ||
246 | .ops = &raumfeld_ak4104_ops, \ | 227 | .ops = &raumfeld_ak4104_ops, \ |
247 | .codec_name = "spi0.0", \ | 228 | .codec_name = "spi0.0", \ |
248 | } | 229 | } |
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index d7d5fb20ea6f..461123ad5ff2 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c | |||
@@ -256,26 +256,6 @@ static const struct snd_kcontrol_new wm8750_spitz_controls[] = { | |||
256 | spitz_set_spk), | 256 | spitz_set_spk), |
257 | }; | 257 | }; |
258 | 258 | ||
259 | /* | ||
260 | * Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device | ||
261 | */ | ||
262 | static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd) | ||
263 | { | ||
264 | struct snd_soc_codec *codec = rtd->codec; | ||
265 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
266 | |||
267 | /* NC codec pins */ | ||
268 | snd_soc_dapm_nc_pin(dapm, "RINPUT1"); | ||
269 | snd_soc_dapm_nc_pin(dapm, "LINPUT2"); | ||
270 | snd_soc_dapm_nc_pin(dapm, "RINPUT2"); | ||
271 | snd_soc_dapm_nc_pin(dapm, "LINPUT3"); | ||
272 | snd_soc_dapm_nc_pin(dapm, "RINPUT3"); | ||
273 | snd_soc_dapm_nc_pin(dapm, "OUT3"); | ||
274 | snd_soc_dapm_nc_pin(dapm, "MONO1"); | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | /* spitz digital audio interface glue - connects codec <--> CPU */ | 259 | /* spitz digital audio interface glue - connects codec <--> CPU */ |
280 | static struct snd_soc_dai_link spitz_dai = { | 260 | static struct snd_soc_dai_link spitz_dai = { |
281 | .name = "wm8750", | 261 | .name = "wm8750", |
@@ -284,7 +264,6 @@ static struct snd_soc_dai_link spitz_dai = { | |||
284 | .codec_dai_name = "wm8750-hifi", | 264 | .codec_dai_name = "wm8750-hifi", |
285 | .platform_name = "pxa-pcm-audio", | 265 | .platform_name = "pxa-pcm-audio", |
286 | .codec_name = "wm8750.0-001b", | 266 | .codec_name = "wm8750.0-001b", |
287 | .init = spitz_wm8750_init, | ||
288 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | 267 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | |
289 | SND_SOC_DAIFMT_CBS_CFS, | 268 | SND_SOC_DAIFMT_CBS_CFS, |
290 | .ops = &spitz_ops, | 269 | .ops = &spitz_ops, |
@@ -303,6 +282,7 @@ static struct snd_soc_card snd_soc_spitz = { | |||
303 | .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), | 282 | .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), |
304 | .dapm_routes = spitz_audio_map, | 283 | .dapm_routes = spitz_audio_map, |
305 | .num_dapm_routes = ARRAY_SIZE(spitz_audio_map), | 284 | .num_dapm_routes = ARRAY_SIZE(spitz_audio_map), |
285 | .fully_routed = true, | ||
306 | }; | 286 | }; |
307 | 287 | ||
308 | static int spitz_probe(struct platform_device *pdev) | 288 | static int spitz_probe(struct platform_device *pdev) |
@@ -352,7 +332,6 @@ static int spitz_remove(struct platform_device *pdev) | |||
352 | static struct platform_driver spitz_driver = { | 332 | static struct platform_driver spitz_driver = { |
353 | .driver = { | 333 | .driver = { |
354 | .name = "spitz-audio", | 334 | .name = "spitz-audio", |
355 | .owner = THIS_MODULE, | ||
356 | .pm = &snd_soc_pm_ops, | 335 | .pm = &snd_soc_pm_ops, |
357 | }, | 336 | }, |
358 | .probe = spitz_probe, | 337 | .probe = spitz_probe, |
diff --git a/sound/soc/pxa/ttc-dkb.c b/sound/soc/pxa/ttc-dkb.c index e3d7257ad09c..5001dbb9b257 100644 --- a/sound/soc/pxa/ttc-dkb.c +++ b/sound/soc/pxa/ttc-dkb.c | |||
@@ -76,10 +76,6 @@ static const struct snd_soc_dapm_route ttc_audio_map[] = { | |||
76 | static int ttc_pm860x_init(struct snd_soc_pcm_runtime *rtd) | 76 | static int ttc_pm860x_init(struct snd_soc_pcm_runtime *rtd) |
77 | { | 77 | { |
78 | struct snd_soc_codec *codec = rtd->codec; | 78 | struct snd_soc_codec *codec = rtd->codec; |
79 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
80 | |||
81 | snd_soc_dapm_disable_pin(dapm, "Headset Mic 2"); | ||
82 | snd_soc_dapm_disable_pin(dapm, "Headset Stereophone"); | ||
83 | 79 | ||
84 | /* Headset jack detection */ | 80 | /* Headset jack detection */ |
85 | snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE | 81 | snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE |
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 23bf991e95d5..8f301c72ee5e 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c | |||
@@ -130,16 +130,6 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
130 | if (ret < 0) | 130 | if (ret < 0) |
131 | return ret; | 131 | return ret; |
132 | 132 | ||
133 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
134 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
135 | if (ret < 0) | ||
136 | return ret; | ||
137 | |||
138 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
139 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
140 | if (ret < 0) | ||
141 | return ret; | ||
142 | |||
143 | return 0; | 133 | return 0; |
144 | } | 134 | } |
145 | 135 | ||
@@ -172,6 +162,8 @@ static struct snd_soc_dai_link zylonite_dai[] = { | |||
172 | .platform_name = "pxa-pcm-audio", | 162 | .platform_name = "pxa-pcm-audio", |
173 | .cpu_dai_name = "pxa-ssp-dai.2", | 163 | .cpu_dai_name = "pxa-ssp-dai.2", |
174 | .codec_dai_name = "wm9713-voice", | 164 | .codec_dai_name = "wm9713-voice", |
165 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
166 | SND_SOC_DAIFMT_CBS_CFS, | ||
175 | .ops = &zylonite_voice_ops, | 167 | .ops = &zylonite_voice_ops, |
176 | }, | 168 | }, |
177 | }; | 169 | }; |
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index dcc26eda0539..acb5be53bfb4 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c | |||
@@ -247,6 +247,10 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, | |||
247 | 247 | ||
248 | regmap_update_bits(i2s->regmap, I2S_TXCR, I2S_TXCR_VDW_MASK, val); | 248 | regmap_update_bits(i2s->regmap, I2S_TXCR, I2S_TXCR_VDW_MASK, val); |
249 | regmap_update_bits(i2s->regmap, I2S_RXCR, I2S_RXCR_VDW_MASK, val); | 249 | regmap_update_bits(i2s->regmap, I2S_RXCR, I2S_RXCR_VDW_MASK, val); |
250 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK, | ||
251 | I2S_DMACR_TDL(16)); | ||
252 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, | ||
253 | I2S_DMACR_RDL(16)); | ||
250 | 254 | ||
251 | return 0; | 255 | return 0; |
252 | } | 256 | } |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index e0c4a4ec4280..0632a36852c8 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -54,7 +54,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750 | |||
54 | config SND_SOC_SAMSUNG_SMDK_WM8580 | 54 | config SND_SOC_SAMSUNG_SMDK_WM8580 |
55 | tristate "SoC I2S Audio support for WM8580 on SMDK" | 55 | tristate "SoC I2S Audio support for WM8580 on SMDK" |
56 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) | 56 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) |
57 | depends on REGMAP_I2C | 57 | depends on I2C |
58 | select SND_SOC_WM8580 | 58 | select SND_SOC_WM8580 |
59 | select SND_SAMSUNG_I2S | 59 | select SND_SAMSUNG_I2S |
60 | help | 60 | help |
@@ -146,17 +146,6 @@ config SND_SOC_SMARTQ | |||
146 | select SND_SAMSUNG_I2S | 146 | select SND_SAMSUNG_I2S |
147 | select SND_SOC_WM8750 | 147 | select SND_SOC_WM8750 |
148 | 148 | ||
149 | config SND_SOC_GONI_AQUILA_WM8994 | ||
150 | tristate "SoC I2S Audio support for AQUILA/GONI - WM8994" | ||
151 | depends on SND_SOC_SAMSUNG && (MACH_GONI || MACH_AQUILA) | ||
152 | depends on I2C=y | ||
153 | select SND_SAMSUNG_I2S | ||
154 | select MFD_WM8994 | ||
155 | select SND_SOC_WM8994 | ||
156 | help | ||
157 | Say Y if you want to add support for SoC audio on goni or aquila | ||
158 | with the WM8994. | ||
159 | |||
160 | config SND_SOC_SAMSUNG_SMDK_SPDIF | 149 | config SND_SOC_SAMSUNG_SMDK_SPDIF |
161 | tristate "SoC S/PDIF Audio support for SMDK" | 150 | tristate "SoC S/PDIF Audio support for SMDK" |
162 | depends on SND_SOC_SAMSUNG | 151 | depends on SND_SOC_SAMSUNG |
@@ -167,7 +156,7 @@ config SND_SOC_SAMSUNG_SMDK_SPDIF | |||
167 | config SND_SOC_SMDK_WM8580_PCM | 156 | config SND_SOC_SMDK_WM8580_PCM |
168 | tristate "SoC PCM Audio support for WM8580 on SMDK" | 157 | tristate "SoC PCM Audio support for WM8580 on SMDK" |
169 | depends on SND_SOC_SAMSUNG && (MACH_SMDKV210 || MACH_SMDKC110) | 158 | depends on SND_SOC_SAMSUNG && (MACH_SMDKV210 || MACH_SMDKC110) |
170 | depends on REGMAP_I2C | 159 | depends on I2C |
171 | select SND_SOC_WM8580 | 160 | select SND_SOC_WM8580 |
172 | select SND_SAMSUNG_PCM | 161 | select SND_SAMSUNG_PCM |
173 | help | 162 | help |
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 31e3dba7e3b5..052fe71be518 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -35,7 +35,6 @@ snd-soc-smdk-wm8994-objs := smdk_wm8994.o | |||
35 | snd-soc-snow-objs := snow.o | 35 | snd-soc-snow-objs := snow.o |
36 | snd-soc-smdk-wm9713-objs := smdk_wm9713.o | 36 | snd-soc-smdk-wm9713-objs := smdk_wm9713.o |
37 | snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o | 37 | snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o |
38 | snd-soc-goni-wm8994-objs := goni_wm8994.o | ||
39 | snd-soc-smdk-spdif-objs := smdk_spdif.o | 38 | snd-soc-smdk-spdif-objs := smdk_spdif.o |
40 | snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o | 39 | snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o |
41 | snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o | 40 | snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o |
@@ -63,7 +62,6 @@ obj-$(CONFIG_SND_SOC_SNOW) += snd-soc-snow.o | |||
63 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM9713) += snd-soc-smdk-wm9713.o | 62 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM9713) += snd-soc-smdk-wm9713.o |
64 | obj-$(CONFIG_SND_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o | 63 | obj-$(CONFIG_SND_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o |
65 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o | 64 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o |
66 | obj-$(CONFIG_SND_SOC_GONI_AQUILA_WM8994) += snd-soc-goni-wm8994.o | ||
67 | obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o | 65 | obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o |
68 | obj-$(CONFIG_SND_SOC_SMDK_WM8994_PCM) += snd-soc-smdk-wm8994pcm.o | 66 | obj-$(CONFIG_SND_SOC_SMDK_WM8994_PCM) += snd-soc-smdk-wm8994pcm.o |
69 | obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o | 67 | obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o |
diff --git a/sound/soc/samsung/arndale_rt5631.c b/sound/soc/samsung/arndale_rt5631.c index 1e2b61ca8db2..8bf2e2c4bafb 100644 --- a/sound/soc/samsung/arndale_rt5631.c +++ b/sound/soc/samsung/arndale_rt5631.c | |||
@@ -135,7 +135,6 @@ MODULE_DEVICE_TABLE(of, samsung_arndale_rt5631_of_match); | |||
135 | static struct platform_driver arndale_audio_driver = { | 135 | static struct platform_driver arndale_audio_driver = { |
136 | .driver = { | 136 | .driver = { |
137 | .name = "arndale-audio", | 137 | .name = "arndale-audio", |
138 | .owner = THIS_MODULE, | ||
139 | .pm = &snd_soc_pm_ops, | 138 | .pm = &snd_soc_pm_ops, |
140 | .of_match_table = of_match_ptr(samsung_arndale_rt5631_of_match), | 139 | .of_match_table = of_match_ptr(samsung_arndale_rt5631_of_match), |
141 | }, | 140 | }, |
diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c deleted file mode 100644 index 3b527dcfc0aa..000000000000 --- a/sound/soc/samsung/goni_wm8994.c +++ /dev/null | |||
@@ -1,304 +0,0 @@ | |||
1 | /* | ||
2 | * goni_wm8994.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
5 | * Author: Chanwoo Choi <cw00.choi@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 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <sound/soc.h> | ||
16 | #include <sound/jack.h> | ||
17 | |||
18 | #include <asm/mach-types.h> | ||
19 | #include <mach/gpio-samsung.h> | ||
20 | |||
21 | #include "../codecs/wm8994.h" | ||
22 | |||
23 | #define MACHINE_NAME 0 | ||
24 | #define CPU_VOICE_DAI 1 | ||
25 | |||
26 | static const char *aquila_str[] = { | ||
27 | [MACHINE_NAME] = "aquila", | ||
28 | [CPU_VOICE_DAI] = "aquila-voice-dai", | ||
29 | }; | ||
30 | |||
31 | static struct snd_soc_card goni; | ||
32 | static struct platform_device *goni_snd_device; | ||
33 | |||
34 | /* 3.5 pie jack */ | ||
35 | static struct snd_soc_jack jack; | ||
36 | |||
37 | /* 3.5 pie jack detection DAPM pins */ | ||
38 | static struct snd_soc_jack_pin jack_pins[] = { | ||
39 | { | ||
40 | .pin = "Headset Mic", | ||
41 | .mask = SND_JACK_MICROPHONE, | ||
42 | }, { | ||
43 | .pin = "Headset Stereophone", | ||
44 | .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL | | ||
45 | SND_JACK_AVOUT, | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | /* 3.5 pie jack detection gpios */ | ||
50 | static struct snd_soc_jack_gpio jack_gpios[] = { | ||
51 | { | ||
52 | .gpio = S5PV210_GPH0(6), | ||
53 | .name = "DET_3.5", | ||
54 | .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL | | ||
55 | SND_JACK_AVOUT, | ||
56 | .debounce_time = 200, | ||
57 | }, | ||
58 | }; | ||
59 | |||
60 | static const struct snd_soc_dapm_widget goni_dapm_widgets[] = { | ||
61 | SND_SOC_DAPM_SPK("Ext Left Spk", NULL), | ||
62 | SND_SOC_DAPM_SPK("Ext Right Spk", NULL), | ||
63 | SND_SOC_DAPM_SPK("Ext Rcv", NULL), | ||
64 | SND_SOC_DAPM_HP("Headset Stereophone", NULL), | ||
65 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
66 | SND_SOC_DAPM_MIC("Main Mic", NULL), | ||
67 | SND_SOC_DAPM_MIC("2nd Mic", NULL), | ||
68 | SND_SOC_DAPM_LINE("Radio In", NULL), | ||
69 | }; | ||
70 | |||
71 | static const struct snd_soc_dapm_route goni_dapm_routes[] = { | ||
72 | {"Ext Left Spk", NULL, "SPKOUTLP"}, | ||
73 | {"Ext Left Spk", NULL, "SPKOUTLN"}, | ||
74 | |||
75 | {"Ext Right Spk", NULL, "SPKOUTRP"}, | ||
76 | {"Ext Right Spk", NULL, "SPKOUTRN"}, | ||
77 | |||
78 | {"Ext Rcv", NULL, "HPOUT2N"}, | ||
79 | {"Ext Rcv", NULL, "HPOUT2P"}, | ||
80 | |||
81 | {"Headset Stereophone", NULL, "HPOUT1L"}, | ||
82 | {"Headset Stereophone", NULL, "HPOUT1R"}, | ||
83 | |||
84 | {"IN1RN", NULL, "Headset Mic"}, | ||
85 | {"IN1RP", NULL, "Headset Mic"}, | ||
86 | |||
87 | {"IN1RN", NULL, "2nd Mic"}, | ||
88 | {"IN1RP", NULL, "2nd Mic"}, | ||
89 | |||
90 | {"IN1LN", NULL, "Main Mic"}, | ||
91 | {"IN1LP", NULL, "Main Mic"}, | ||
92 | |||
93 | {"IN2LN", NULL, "Radio In"}, | ||
94 | {"IN2RN", NULL, "Radio In"}, | ||
95 | }; | ||
96 | |||
97 | static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd) | ||
98 | { | ||
99 | struct snd_soc_codec *codec = rtd->codec; | ||
100 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
101 | int ret; | ||
102 | |||
103 | /* set endpoints to not connected */ | ||
104 | snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN"); | ||
105 | snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP"); | ||
106 | snd_soc_dapm_nc_pin(dapm, "LINEOUT1N"); | ||
107 | snd_soc_dapm_nc_pin(dapm, "LINEOUT1P"); | ||
108 | snd_soc_dapm_nc_pin(dapm, "LINEOUT2N"); | ||
109 | snd_soc_dapm_nc_pin(dapm, "LINEOUT2P"); | ||
110 | |||
111 | if (machine_is_aquila()) { | ||
112 | snd_soc_dapm_nc_pin(dapm, "SPKOUTRN"); | ||
113 | snd_soc_dapm_nc_pin(dapm, "SPKOUTRP"); | ||
114 | } | ||
115 | |||
116 | /* Headset jack detection */ | ||
117 | ret = snd_soc_jack_new(codec, "Headset Jack", | ||
118 | SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, | ||
119 | &jack); | ||
120 | if (ret) | ||
121 | return ret; | ||
122 | |||
123 | ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); | ||
124 | if (ret) | ||
125 | return ret; | ||
126 | |||
127 | ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); | ||
128 | if (ret) | ||
129 | return ret; | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int goni_hifi_hw_params(struct snd_pcm_substream *substream, | ||
135 | struct snd_pcm_hw_params *params) | ||
136 | { | ||
137 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
138 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
139 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
140 | unsigned int pll_out = 24000000; | ||
141 | int ret = 0; | ||
142 | |||
143 | /* set the cpu DAI configuration */ | ||
144 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
145 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
146 | if (ret < 0) | ||
147 | return ret; | ||
148 | |||
149 | /* set codec DAI configuration */ | ||
150 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
151 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | ||
152 | if (ret < 0) | ||
153 | return ret; | ||
154 | |||
155 | /* set the codec FLL */ | ||
156 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out, | ||
157 | params_rate(params) * 256); | ||
158 | if (ret < 0) | ||
159 | return ret; | ||
160 | |||
161 | /* set the codec system clock */ | ||
162 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, | ||
163 | params_rate(params) * 256, SND_SOC_CLOCK_IN); | ||
164 | if (ret < 0) | ||
165 | return ret; | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static struct snd_soc_ops goni_hifi_ops = { | ||
171 | .hw_params = goni_hifi_hw_params, | ||
172 | }; | ||
173 | |||
174 | static int goni_voice_hw_params(struct snd_pcm_substream *substream, | ||
175 | struct snd_pcm_hw_params *params) | ||
176 | { | ||
177 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
178 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
179 | unsigned int pll_out = 24000000; | ||
180 | int ret = 0; | ||
181 | |||
182 | if (params_rate(params) != 8000) | ||
183 | return -EINVAL; | ||
184 | |||
185 | /* set codec DAI configuration */ | ||
186 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | | ||
187 | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); | ||
188 | if (ret < 0) | ||
189 | return ret; | ||
190 | |||
191 | /* set the codec FLL */ | ||
192 | ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out, | ||
193 | params_rate(params) * 256); | ||
194 | if (ret < 0) | ||
195 | return ret; | ||
196 | |||
197 | /* set the codec system clock */ | ||
198 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, | ||
199 | params_rate(params) * 256, SND_SOC_CLOCK_IN); | ||
200 | if (ret < 0) | ||
201 | return ret; | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static struct snd_soc_dai_driver voice_dai = { | ||
207 | .name = "goni-voice-dai", | ||
208 | .id = 0, | ||
209 | .playback = { | ||
210 | .channels_min = 1, | ||
211 | .channels_max = 2, | ||
212 | .rates = SNDRV_PCM_RATE_8000, | ||
213 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
214 | .capture = { | ||
215 | .channels_min = 1, | ||
216 | .channels_max = 2, | ||
217 | .rates = SNDRV_PCM_RATE_8000, | ||
218 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
219 | }; | ||
220 | |||
221 | static const struct snd_soc_component_driver voice_component = { | ||
222 | .name = "goni-voice", | ||
223 | }; | ||
224 | |||
225 | static struct snd_soc_ops goni_voice_ops = { | ||
226 | .hw_params = goni_voice_hw_params, | ||
227 | }; | ||
228 | |||
229 | static struct snd_soc_dai_link goni_dai[] = { | ||
230 | { | ||
231 | .name = "WM8994", | ||
232 | .stream_name = "WM8994 HiFi", | ||
233 | .cpu_dai_name = "samsung-i2s.0", | ||
234 | .codec_dai_name = "wm8994-aif1", | ||
235 | .platform_name = "samsung-i2s.0", | ||
236 | .codec_name = "wm8994-codec.0-001a", | ||
237 | .init = goni_wm8994_init, | ||
238 | .ops = &goni_hifi_ops, | ||
239 | }, { | ||
240 | .name = "WM8994 Voice", | ||
241 | .stream_name = "Voice", | ||
242 | .cpu_dai_name = "goni-voice-dai", | ||
243 | .codec_dai_name = "wm8994-aif2", | ||
244 | .codec_name = "wm8994-codec.0-001a", | ||
245 | .ops = &goni_voice_ops, | ||
246 | }, | ||
247 | }; | ||
248 | |||
249 | static struct snd_soc_card goni = { | ||
250 | .name = "goni", | ||
251 | .owner = THIS_MODULE, | ||
252 | .dai_link = goni_dai, | ||
253 | .num_links = ARRAY_SIZE(goni_dai), | ||
254 | |||
255 | .dapm_widgets = goni_dapm_widgets, | ||
256 | .num_dapm_widgets = ARRAY_SIZE(goni_dapm_widgets), | ||
257 | .dapm_routes = goni_dapm_routes, | ||
258 | .num_dapm_routes = ARRAY_SIZE(goni_dapm_routes), | ||
259 | }; | ||
260 | |||
261 | static int __init goni_init(void) | ||
262 | { | ||
263 | int ret; | ||
264 | |||
265 | if (machine_is_aquila()) { | ||
266 | voice_dai.name = aquila_str[CPU_VOICE_DAI]; | ||
267 | goni_dai[1].cpu_dai_name = aquila_str[CPU_VOICE_DAI]; | ||
268 | goni.name = aquila_str[MACHINE_NAME]; | ||
269 | } else if (!machine_is_goni()) | ||
270 | return -ENODEV; | ||
271 | |||
272 | goni_snd_device = platform_device_alloc("soc-audio", -1); | ||
273 | if (!goni_snd_device) | ||
274 | return -ENOMEM; | ||
275 | |||
276 | /* register voice DAI here */ | ||
277 | ret = devm_snd_soc_register_component(&goni_snd_device->dev, | ||
278 | &voice_component, &voice_dai, 1); | ||
279 | if (ret) { | ||
280 | platform_device_put(goni_snd_device); | ||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | platform_set_drvdata(goni_snd_device, &goni); | ||
285 | ret = platform_device_add(goni_snd_device); | ||
286 | |||
287 | if (ret) | ||
288 | platform_device_put(goni_snd_device); | ||
289 | |||
290 | return ret; | ||
291 | } | ||
292 | |||
293 | static void __exit goni_exit(void) | ||
294 | { | ||
295 | platform_device_unregister(goni_snd_device); | ||
296 | } | ||
297 | |||
298 | module_init(goni_init); | ||
299 | module_exit(goni_exit); | ||
300 | |||
301 | /* Module information */ | ||
302 | MODULE_DESCRIPTION("ALSA SoC WM8994 GONI(S5PV210)"); | ||
303 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); | ||
304 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index f2d7980d7ddc..59b044255b78 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c | |||
@@ -76,7 +76,6 @@ static int h1940_hw_params(struct snd_pcm_substream *substream, | |||
76 | { | 76 | { |
77 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 77 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
78 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 78 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
79 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
80 | int div; | 79 | int div; |
81 | int ret; | 80 | int ret; |
82 | unsigned int rate = params_rate(params); | 81 | unsigned int rate = params_rate(params); |
@@ -95,18 +94,6 @@ static int h1940_hw_params(struct snd_pcm_substream *substream, | |||
95 | return -EINVAL; | 94 | return -EINVAL; |
96 | } | 95 | } |
97 | 96 | ||
98 | /* set codec DAI configuration */ | ||
99 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
100 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
101 | if (ret < 0) | ||
102 | return ret; | ||
103 | |||
104 | /* set cpu DAI configuration */ | ||
105 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
106 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
107 | if (ret < 0) | ||
108 | return ret; | ||
109 | |||
110 | /* select clock source */ | 97 | /* select clock source */ |
111 | ret = snd_soc_dai_set_sysclk(cpu_dai, S3C24XX_CLKSRC_PCLK, rate, | 98 | ret = snd_soc_dai_set_sysclk(cpu_dai, S3C24XX_CLKSRC_PCLK, rate, |
112 | SND_SOC_CLOCK_OUT); | 99 | SND_SOC_CLOCK_OUT); |
@@ -207,6 +194,8 @@ static struct snd_soc_dai_link h1940_uda1380_dai[] = { | |||
207 | .init = h1940_uda1380_init, | 194 | .init = h1940_uda1380_init, |
208 | .platform_name = "s3c24xx-iis", | 195 | .platform_name = "s3c24xx-iis", |
209 | .codec_name = "uda1380-codec.0-001a", | 196 | .codec_name = "uda1380-codec.0-001a", |
197 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
198 | SND_SOC_DAIFMT_CBS_CFS, | ||
210 | .ops = &h1940_ops, | 199 | .ops = &h1940_ops, |
211 | }, | 200 | }, |
212 | }; | 201 | }; |
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index b5a80c528d86..b92ab40d2be6 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c | |||
@@ -10,9 +10,11 @@ | |||
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <dt-bindings/sound/samsung-i2s.h> | ||
13 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
15 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
17 | #include <linux/clk-provider.h> | ||
16 | #include <linux/io.h> | 18 | #include <linux/io.h> |
17 | #include <linux/module.h> | 19 | #include <linux/module.h> |
18 | #include <linux/of.h> | 20 | #include <linux/of.h> |
@@ -59,10 +61,8 @@ struct samsung_i2s_dai_data { | |||
59 | struct i2s_dai { | 61 | struct i2s_dai { |
60 | /* Platform device for this DAI */ | 62 | /* Platform device for this DAI */ |
61 | struct platform_device *pdev; | 63 | struct platform_device *pdev; |
62 | /* IOREMAP'd SFRs */ | 64 | /* Memory mapped SFR region */ |
63 | void __iomem *addr; | 65 | void __iomem *addr; |
64 | /* Physical base address of SFRs */ | ||
65 | u32 base; | ||
66 | /* Rate of RCLK source clock */ | 66 | /* Rate of RCLK source clock */ |
67 | unsigned long rclk_srcrate; | 67 | unsigned long rclk_srcrate; |
68 | /* Frame Clock */ | 68 | /* Frame Clock */ |
@@ -83,8 +83,6 @@ struct i2s_dai { | |||
83 | #define DAI_OPENED (1 << 0) /* Dai is opened */ | 83 | #define DAI_OPENED (1 << 0) /* Dai is opened */ |
84 | #define DAI_MANAGER (1 << 1) /* Dai is the manager */ | 84 | #define DAI_MANAGER (1 << 1) /* Dai is the manager */ |
85 | unsigned mode; | 85 | unsigned mode; |
86 | /* CDCLK pin direction: 0 - input, 1 - output */ | ||
87 | unsigned int cdclk_out:1; | ||
88 | /* Driver for this DAI */ | 86 | /* Driver for this DAI */ |
89 | struct snd_soc_dai_driver i2s_dai_drv; | 87 | struct snd_soc_dai_driver i2s_dai_drv; |
90 | /* DMA parameters */ | 88 | /* DMA parameters */ |
@@ -95,8 +93,15 @@ struct i2s_dai { | |||
95 | u32 suspend_i2smod; | 93 | u32 suspend_i2smod; |
96 | u32 suspend_i2scon; | 94 | u32 suspend_i2scon; |
97 | u32 suspend_i2spsr; | 95 | u32 suspend_i2spsr; |
98 | unsigned long gpios[7]; /* i2s gpio line numbers */ | ||
99 | const struct samsung_i2s_variant_regs *variant_regs; | 96 | const struct samsung_i2s_variant_regs *variant_regs; |
97 | |||
98 | /* Spinlock protecting access to the device's registers */ | ||
99 | spinlock_t spinlock; | ||
100 | spinlock_t *lock; | ||
101 | |||
102 | /* Below fields are only valid if this is the primary FIFO */ | ||
103 | struct clk *clk_table[3]; | ||
104 | struct clk_onecell_data clk_data; | ||
100 | }; | 105 | }; |
101 | 106 | ||
102 | /* Lock for cross i/f checks */ | 107 | /* Lock for cross i/f checks */ |
@@ -133,10 +138,16 @@ static inline bool tx_active(struct i2s_dai *i2s) | |||
133 | return active ? true : false; | 138 | return active ? true : false; |
134 | } | 139 | } |
135 | 140 | ||
141 | /* Return pointer to the other DAI */ | ||
142 | static inline struct i2s_dai *get_other_dai(struct i2s_dai *i2s) | ||
143 | { | ||
144 | return i2s->pri_dai ? : i2s->sec_dai; | ||
145 | } | ||
146 | |||
136 | /* If the other interface of the controller is transmitting data */ | 147 | /* If the other interface of the controller is transmitting data */ |
137 | static inline bool other_tx_active(struct i2s_dai *i2s) | 148 | static inline bool other_tx_active(struct i2s_dai *i2s) |
138 | { | 149 | { |
139 | struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; | 150 | struct i2s_dai *other = get_other_dai(i2s); |
140 | 151 | ||
141 | return tx_active(other); | 152 | return tx_active(other); |
142 | } | 153 | } |
@@ -163,7 +174,7 @@ static inline bool rx_active(struct i2s_dai *i2s) | |||
163 | /* If the other interface of the controller is receiving data */ | 174 | /* If the other interface of the controller is receiving data */ |
164 | static inline bool other_rx_active(struct i2s_dai *i2s) | 175 | static inline bool other_rx_active(struct i2s_dai *i2s) |
165 | { | 176 | { |
166 | struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; | 177 | struct i2s_dai *other = get_other_dai(i2s); |
167 | 178 | ||
168 | return rx_active(other); | 179 | return rx_active(other); |
169 | } | 180 | } |
@@ -464,18 +475,23 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, | |||
464 | int clk_id, unsigned int rfs, int dir) | 475 | int clk_id, unsigned int rfs, int dir) |
465 | { | 476 | { |
466 | struct i2s_dai *i2s = to_info(dai); | 477 | struct i2s_dai *i2s = to_info(dai); |
467 | struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; | 478 | struct i2s_dai *other = get_other_dai(i2s); |
468 | u32 mod = readl(i2s->addr + I2SMOD); | ||
469 | const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs; | 479 | const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs; |
470 | unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off; | 480 | unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off; |
471 | unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off; | 481 | unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off; |
482 | u32 mod, mask, val = 0; | ||
483 | |||
484 | spin_lock(i2s->lock); | ||
485 | mod = readl(i2s->addr + I2SMOD); | ||
486 | spin_unlock(i2s->lock); | ||
472 | 487 | ||
473 | switch (clk_id) { | 488 | switch (clk_id) { |
474 | case SAMSUNG_I2S_OPCLK: | 489 | case SAMSUNG_I2S_OPCLK: |
475 | mod &= ~MOD_OPCLK_MASK; | 490 | mask = MOD_OPCLK_MASK; |
476 | mod |= dir; | 491 | val = dir; |
477 | break; | 492 | break; |
478 | case SAMSUNG_I2S_CDCLK: | 493 | case SAMSUNG_I2S_CDCLK: |
494 | mask = 1 << i2s_regs->cdclkcon_off; | ||
479 | /* Shouldn't matter in GATING(CLOCK_IN) mode */ | 495 | /* Shouldn't matter in GATING(CLOCK_IN) mode */ |
480 | if (dir == SND_SOC_CLOCK_IN) | 496 | if (dir == SND_SOC_CLOCK_IN) |
481 | rfs = 0; | 497 | rfs = 0; |
@@ -492,15 +508,15 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, | |||
492 | } | 508 | } |
493 | 509 | ||
494 | if (dir == SND_SOC_CLOCK_IN) | 510 | if (dir == SND_SOC_CLOCK_IN) |
495 | mod |= 1 << i2s_regs->cdclkcon_off; | 511 | val = 1 << i2s_regs->cdclkcon_off; |
496 | else | ||
497 | mod &= ~(1 << i2s_regs->cdclkcon_off); | ||
498 | 512 | ||
499 | i2s->rfs = rfs; | 513 | i2s->rfs = rfs; |
500 | break; | 514 | break; |
501 | 515 | ||
502 | case SAMSUNG_I2S_RCLKSRC_0: /* clock corrsponding to IISMOD[10] := 0 */ | 516 | case SAMSUNG_I2S_RCLKSRC_0: /* clock corrsponding to IISMOD[10] := 0 */ |
503 | case SAMSUNG_I2S_RCLKSRC_1: /* clock corrsponding to IISMOD[10] := 1 */ | 517 | case SAMSUNG_I2S_RCLKSRC_1: /* clock corrsponding to IISMOD[10] := 1 */ |
518 | mask = 1 << i2s_regs->rclksrc_off; | ||
519 | |||
504 | if ((i2s->quirks & QUIRK_NO_MUXPSR) | 520 | if ((i2s->quirks & QUIRK_NO_MUXPSR) |
505 | || (clk_id == SAMSUNG_I2S_RCLKSRC_0)) | 521 | || (clk_id == SAMSUNG_I2S_RCLKSRC_0)) |
506 | clk_id = 0; | 522 | clk_id = 0; |
@@ -550,18 +566,19 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, | |||
550 | return 0; | 566 | return 0; |
551 | } | 567 | } |
552 | 568 | ||
553 | if (clk_id == 0) | 569 | if (clk_id == 1) |
554 | mod &= ~(1 << i2s_regs->rclksrc_off); | 570 | val = 1 << i2s_regs->rclksrc_off; |
555 | else | ||
556 | mod |= 1 << i2s_regs->rclksrc_off; | ||
557 | |||
558 | break; | 571 | break; |
559 | default: | 572 | default: |
560 | dev_err(&i2s->pdev->dev, "We don't serve that!\n"); | 573 | dev_err(&i2s->pdev->dev, "We don't serve that!\n"); |
561 | return -EINVAL; | 574 | return -EINVAL; |
562 | } | 575 | } |
563 | 576 | ||
577 | spin_lock(i2s->lock); | ||
578 | mod = readl(i2s->addr + I2SMOD); | ||
579 | mod = (mod & ~mask) | val; | ||
564 | writel(mod, i2s->addr + I2SMOD); | 580 | writel(mod, i2s->addr + I2SMOD); |
581 | spin_unlock(i2s->lock); | ||
565 | 582 | ||
566 | return 0; | 583 | return 0; |
567 | } | 584 | } |
@@ -570,9 +587,8 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, | |||
570 | unsigned int fmt) | 587 | unsigned int fmt) |
571 | { | 588 | { |
572 | struct i2s_dai *i2s = to_info(dai); | 589 | struct i2s_dai *i2s = to_info(dai); |
573 | u32 mod = readl(i2s->addr + I2SMOD); | ||
574 | int lrp_shift, sdf_shift, sdf_mask, lrp_rlow, mod_slave; | 590 | int lrp_shift, sdf_shift, sdf_mask, lrp_rlow, mod_slave; |
575 | u32 tmp = 0; | 591 | u32 mod, tmp = 0; |
576 | 592 | ||
577 | lrp_shift = i2s->variant_regs->lrp_off; | 593 | lrp_shift = i2s->variant_regs->lrp_off; |
578 | sdf_shift = i2s->variant_regs->sdf_off; | 594 | sdf_shift = i2s->variant_regs->sdf_off; |
@@ -632,12 +648,15 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, | |||
632 | return -EINVAL; | 648 | return -EINVAL; |
633 | } | 649 | } |
634 | 650 | ||
651 | spin_lock(i2s->lock); | ||
652 | mod = readl(i2s->addr + I2SMOD); | ||
635 | /* | 653 | /* |
636 | * Don't change the I2S mode if any controller is active on this | 654 | * Don't change the I2S mode if any controller is active on this |
637 | * channel. | 655 | * channel. |
638 | */ | 656 | */ |
639 | if (any_active(i2s) && | 657 | if (any_active(i2s) && |
640 | ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) { | 658 | ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) { |
659 | spin_unlock(i2s->lock); | ||
641 | dev_err(&i2s->pdev->dev, | 660 | dev_err(&i2s->pdev->dev, |
642 | "%s:%d Other DAI busy\n", __func__, __LINE__); | 661 | "%s:%d Other DAI busy\n", __func__, __LINE__); |
643 | return -EAGAIN; | 662 | return -EAGAIN; |
@@ -646,6 +665,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, | |||
646 | mod &= ~(sdf_mask | lrp_rlow | mod_slave); | 665 | mod &= ~(sdf_mask | lrp_rlow | mod_slave); |
647 | mod |= tmp; | 666 | mod |= tmp; |
648 | writel(mod, i2s->addr + I2SMOD); | 667 | writel(mod, i2s->addr + I2SMOD); |
668 | spin_unlock(i2s->lock); | ||
649 | 669 | ||
650 | return 0; | 670 | return 0; |
651 | } | 671 | } |
@@ -654,16 +674,16 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, | |||
654 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 674 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
655 | { | 675 | { |
656 | struct i2s_dai *i2s = to_info(dai); | 676 | struct i2s_dai *i2s = to_info(dai); |
657 | u32 mod = readl(i2s->addr + I2SMOD); | 677 | u32 mod, mask = 0, val = 0; |
658 | 678 | ||
659 | if (!is_secondary(i2s)) | 679 | if (!is_secondary(i2s)) |
660 | mod &= ~(MOD_DC2_EN | MOD_DC1_EN); | 680 | mask |= (MOD_DC2_EN | MOD_DC1_EN); |
661 | 681 | ||
662 | switch (params_channels(params)) { | 682 | switch (params_channels(params)) { |
663 | case 6: | 683 | case 6: |
664 | mod |= MOD_DC2_EN; | 684 | val |= MOD_DC2_EN; |
665 | case 4: | 685 | case 4: |
666 | mod |= MOD_DC1_EN; | 686 | val |= MOD_DC1_EN; |
667 | break; | 687 | break; |
668 | case 2: | 688 | case 2: |
669 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 689 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -685,44 +705,49 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, | |||
685 | } | 705 | } |
686 | 706 | ||
687 | if (is_secondary(i2s)) | 707 | if (is_secondary(i2s)) |
688 | mod &= ~MOD_BLCS_MASK; | 708 | mask |= MOD_BLCS_MASK; |
689 | else | 709 | else |
690 | mod &= ~MOD_BLCP_MASK; | 710 | mask |= MOD_BLCP_MASK; |
691 | 711 | ||
692 | if (is_manager(i2s)) | 712 | if (is_manager(i2s)) |
693 | mod &= ~MOD_BLC_MASK; | 713 | mask |= MOD_BLC_MASK; |
694 | 714 | ||
695 | switch (params_width(params)) { | 715 | switch (params_width(params)) { |
696 | case 8: | 716 | case 8: |
697 | if (is_secondary(i2s)) | 717 | if (is_secondary(i2s)) |
698 | mod |= MOD_BLCS_8BIT; | 718 | val |= MOD_BLCS_8BIT; |
699 | else | 719 | else |
700 | mod |= MOD_BLCP_8BIT; | 720 | val |= MOD_BLCP_8BIT; |
701 | if (is_manager(i2s)) | 721 | if (is_manager(i2s)) |
702 | mod |= MOD_BLC_8BIT; | 722 | val |= MOD_BLC_8BIT; |
703 | break; | 723 | break; |
704 | case 16: | 724 | case 16: |
705 | if (is_secondary(i2s)) | 725 | if (is_secondary(i2s)) |
706 | mod |= MOD_BLCS_16BIT; | 726 | val |= MOD_BLCS_16BIT; |
707 | else | 727 | else |
708 | mod |= MOD_BLCP_16BIT; | 728 | val |= MOD_BLCP_16BIT; |
709 | if (is_manager(i2s)) | 729 | if (is_manager(i2s)) |
710 | mod |= MOD_BLC_16BIT; | 730 | val |= MOD_BLC_16BIT; |
711 | break; | 731 | break; |
712 | case 24: | 732 | case 24: |
713 | if (is_secondary(i2s)) | 733 | if (is_secondary(i2s)) |
714 | mod |= MOD_BLCS_24BIT; | 734 | val |= MOD_BLCS_24BIT; |
715 | else | 735 | else |
716 | mod |= MOD_BLCP_24BIT; | 736 | val |= MOD_BLCP_24BIT; |
717 | if (is_manager(i2s)) | 737 | if (is_manager(i2s)) |
718 | mod |= MOD_BLC_24BIT; | 738 | val |= MOD_BLC_24BIT; |
719 | break; | 739 | break; |
720 | default: | 740 | default: |
721 | dev_err(&i2s->pdev->dev, "Format(%d) not supported\n", | 741 | dev_err(&i2s->pdev->dev, "Format(%d) not supported\n", |
722 | params_format(params)); | 742 | params_format(params)); |
723 | return -EINVAL; | 743 | return -EINVAL; |
724 | } | 744 | } |
745 | |||
746 | spin_lock(i2s->lock); | ||
747 | mod = readl(i2s->addr + I2SMOD); | ||
748 | mod = (mod & ~mask) | val; | ||
725 | writel(mod, i2s->addr + I2SMOD); | 749 | writel(mod, i2s->addr + I2SMOD); |
750 | spin_unlock(i2s->lock); | ||
726 | 751 | ||
727 | samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); | 752 | samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); |
728 | 753 | ||
@@ -736,7 +761,7 @@ static int i2s_startup(struct snd_pcm_substream *substream, | |||
736 | struct snd_soc_dai *dai) | 761 | struct snd_soc_dai *dai) |
737 | { | 762 | { |
738 | struct i2s_dai *i2s = to_info(dai); | 763 | struct i2s_dai *i2s = to_info(dai); |
739 | struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; | 764 | struct i2s_dai *other = get_other_dai(i2s); |
740 | unsigned long flags; | 765 | unsigned long flags; |
741 | 766 | ||
742 | spin_lock_irqsave(&lock, flags); | 767 | spin_lock_irqsave(&lock, flags); |
@@ -753,9 +778,6 @@ static int i2s_startup(struct snd_pcm_substream *substream, | |||
753 | 778 | ||
754 | spin_unlock_irqrestore(&lock, flags); | 779 | spin_unlock_irqrestore(&lock, flags); |
755 | 780 | ||
756 | if (!is_opened(other) && i2s->cdclk_out) | ||
757 | i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK, | ||
758 | 0, SND_SOC_CLOCK_OUT); | ||
759 | return 0; | 781 | return 0; |
760 | } | 782 | } |
761 | 783 | ||
@@ -763,38 +785,27 @@ static void i2s_shutdown(struct snd_pcm_substream *substream, | |||
763 | struct snd_soc_dai *dai) | 785 | struct snd_soc_dai *dai) |
764 | { | 786 | { |
765 | struct i2s_dai *i2s = to_info(dai); | 787 | struct i2s_dai *i2s = to_info(dai); |
766 | struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; | 788 | struct i2s_dai *other = get_other_dai(i2s); |
767 | unsigned long flags; | 789 | unsigned long flags; |
768 | const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs; | ||
769 | 790 | ||
770 | spin_lock_irqsave(&lock, flags); | 791 | spin_lock_irqsave(&lock, flags); |
771 | 792 | ||
772 | i2s->mode &= ~DAI_OPENED; | 793 | i2s->mode &= ~DAI_OPENED; |
773 | i2s->mode &= ~DAI_MANAGER; | 794 | i2s->mode &= ~DAI_MANAGER; |
774 | 795 | ||
775 | if (is_opened(other)) { | 796 | if (is_opened(other)) |
776 | other->mode |= DAI_MANAGER; | 797 | other->mode |= DAI_MANAGER; |
777 | } else { | 798 | |
778 | u32 mod = readl(i2s->addr + I2SMOD); | ||
779 | i2s->cdclk_out = !(mod & (1 << i2s_regs->cdclkcon_off)); | ||
780 | if (other) | ||
781 | other->cdclk_out = i2s->cdclk_out; | ||
782 | } | ||
783 | /* Reset any constraint on RFS and BFS */ | 799 | /* Reset any constraint on RFS and BFS */ |
784 | i2s->rfs = 0; | 800 | i2s->rfs = 0; |
785 | i2s->bfs = 0; | 801 | i2s->bfs = 0; |
786 | 802 | ||
787 | spin_unlock_irqrestore(&lock, flags); | 803 | spin_unlock_irqrestore(&lock, flags); |
788 | |||
789 | /* Gate CDCLK by default */ | ||
790 | if (!is_opened(other)) | ||
791 | i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK, | ||
792 | 0, SND_SOC_CLOCK_IN); | ||
793 | } | 804 | } |
794 | 805 | ||
795 | static int config_setup(struct i2s_dai *i2s) | 806 | static int config_setup(struct i2s_dai *i2s) |
796 | { | 807 | { |
797 | struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; | 808 | struct i2s_dai *other = get_other_dai(i2s); |
798 | unsigned rfs, bfs, blc; | 809 | unsigned rfs, bfs, blc; |
799 | u32 psr; | 810 | u32 psr; |
800 | 811 | ||
@@ -864,10 +875,10 @@ static int i2s_trigger(struct snd_pcm_substream *substream, | |||
864 | case SNDRV_PCM_TRIGGER_START: | 875 | case SNDRV_PCM_TRIGGER_START: |
865 | case SNDRV_PCM_TRIGGER_RESUME: | 876 | case SNDRV_PCM_TRIGGER_RESUME: |
866 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 877 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
867 | local_irq_save(flags); | 878 | spin_lock_irqsave(i2s->lock, flags); |
868 | 879 | ||
869 | if (config_setup(i2s)) { | 880 | if (config_setup(i2s)) { |
870 | local_irq_restore(flags); | 881 | spin_unlock_irqrestore(i2s->lock, flags); |
871 | return -EINVAL; | 882 | return -EINVAL; |
872 | } | 883 | } |
873 | 884 | ||
@@ -876,12 +887,12 @@ static int i2s_trigger(struct snd_pcm_substream *substream, | |||
876 | else | 887 | else |
877 | i2s_txctrl(i2s, 1); | 888 | i2s_txctrl(i2s, 1); |
878 | 889 | ||
879 | local_irq_restore(flags); | 890 | spin_unlock_irqrestore(i2s->lock, flags); |
880 | break; | 891 | break; |
881 | case SNDRV_PCM_TRIGGER_STOP: | 892 | case SNDRV_PCM_TRIGGER_STOP: |
882 | case SNDRV_PCM_TRIGGER_SUSPEND: | 893 | case SNDRV_PCM_TRIGGER_SUSPEND: |
883 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 894 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
884 | local_irq_save(flags); | 895 | spin_lock_irqsave(i2s->lock, flags); |
885 | 896 | ||
886 | if (capture) { | 897 | if (capture) { |
887 | i2s_rxctrl(i2s, 0); | 898 | i2s_rxctrl(i2s, 0); |
@@ -891,7 +902,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream, | |||
891 | i2s_fifo(i2s, FIC_TXFLUSH); | 902 | i2s_fifo(i2s, FIC_TXFLUSH); |
892 | } | 903 | } |
893 | 904 | ||
894 | local_irq_restore(flags); | 905 | spin_unlock_irqrestore(i2s->lock, flags); |
895 | break; | 906 | break; |
896 | } | 907 | } |
897 | 908 | ||
@@ -902,7 +913,7 @@ static int i2s_set_clkdiv(struct snd_soc_dai *dai, | |||
902 | int div_id, int div) | 913 | int div_id, int div) |
903 | { | 914 | { |
904 | struct i2s_dai *i2s = to_info(dai); | 915 | struct i2s_dai *i2s = to_info(dai); |
905 | struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; | 916 | struct i2s_dai *other = get_other_dai(i2s); |
906 | 917 | ||
907 | switch (div_id) { | 918 | switch (div_id) { |
908 | case SAMSUNG_I2S_DIV_BCLK: | 919 | case SAMSUNG_I2S_DIV_BCLK: |
@@ -971,58 +982,36 @@ static int i2s_resume(struct snd_soc_dai *dai) | |||
971 | static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) | 982 | static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) |
972 | { | 983 | { |
973 | struct i2s_dai *i2s = to_info(dai); | 984 | struct i2s_dai *i2s = to_info(dai); |
974 | struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; | 985 | struct i2s_dai *other = get_other_dai(i2s); |
975 | int ret; | 986 | unsigned long flags; |
976 | 987 | ||
977 | if (other && other->clk) { /* If this is probe on secondary */ | 988 | if (is_secondary(i2s)) { /* If this is probe on the secondary DAI */ |
978 | samsung_asoc_init_dma_data(dai, &other->sec_dai->dma_playback, | 989 | samsung_asoc_init_dma_data(dai, &other->sec_dai->dma_playback, |
979 | NULL); | 990 | NULL); |
980 | goto probe_exit; | 991 | } else { |
981 | } | 992 | samsung_asoc_init_dma_data(dai, &i2s->dma_playback, |
982 | 993 | &i2s->dma_capture); | |
983 | i2s->addr = ioremap(i2s->base, 0x100); | ||
984 | if (i2s->addr == NULL) { | ||
985 | dev_err(&i2s->pdev->dev, "cannot ioremap registers\n"); | ||
986 | return -ENXIO; | ||
987 | } | ||
988 | |||
989 | i2s->clk = clk_get(&i2s->pdev->dev, "iis"); | ||
990 | if (IS_ERR(i2s->clk)) { | ||
991 | dev_err(&i2s->pdev->dev, "failed to get i2s_clock\n"); | ||
992 | iounmap(i2s->addr); | ||
993 | return PTR_ERR(i2s->clk); | ||
994 | } | ||
995 | |||
996 | ret = clk_prepare_enable(i2s->clk); | ||
997 | if (ret != 0) { | ||
998 | dev_err(&i2s->pdev->dev, "failed to enable clock: %d\n", ret); | ||
999 | return ret; | ||
1000 | } | ||
1001 | |||
1002 | samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); | ||
1003 | |||
1004 | if (other) { | ||
1005 | other->addr = i2s->addr; | ||
1006 | other->clk = i2s->clk; | ||
1007 | } | ||
1008 | 994 | ||
1009 | if (i2s->quirks & QUIRK_NEED_RSTCLR) | 995 | if (i2s->quirks & QUIRK_NEED_RSTCLR) |
1010 | writel(CON_RSTCLR, i2s->addr + I2SCON); | 996 | writel(CON_RSTCLR, i2s->addr + I2SCON); |
1011 | 997 | ||
1012 | if (i2s->quirks & QUIRK_SUPPORTS_IDMA) | 998 | if (i2s->quirks & QUIRK_SUPPORTS_IDMA) |
1013 | idma_reg_addr_init(i2s->addr, | 999 | idma_reg_addr_init(i2s->addr, |
1014 | i2s->sec_dai->idma_playback.dma_addr); | 1000 | i2s->sec_dai->idma_playback.dma_addr); |
1001 | } | ||
1015 | 1002 | ||
1016 | probe_exit: | ||
1017 | /* Reset any constraint on RFS and BFS */ | 1003 | /* Reset any constraint on RFS and BFS */ |
1018 | i2s->rfs = 0; | 1004 | i2s->rfs = 0; |
1019 | i2s->bfs = 0; | 1005 | i2s->bfs = 0; |
1020 | i2s->rclk_srcrate = 0; | 1006 | i2s->rclk_srcrate = 0; |
1007 | |||
1008 | spin_lock_irqsave(i2s->lock, flags); | ||
1021 | i2s_txctrl(i2s, 0); | 1009 | i2s_txctrl(i2s, 0); |
1022 | i2s_rxctrl(i2s, 0); | 1010 | i2s_rxctrl(i2s, 0); |
1023 | i2s_fifo(i2s, FIC_TXFLUSH); | 1011 | i2s_fifo(i2s, FIC_TXFLUSH); |
1024 | i2s_fifo(other, FIC_TXFLUSH); | 1012 | i2s_fifo(other, FIC_TXFLUSH); |
1025 | i2s_fifo(i2s, FIC_RXFLUSH); | 1013 | i2s_fifo(i2s, FIC_RXFLUSH); |
1014 | spin_unlock_irqrestore(i2s->lock, flags); | ||
1026 | 1015 | ||
1027 | /* Gate CDCLK by default */ | 1016 | /* Gate CDCLK by default */ |
1028 | if (!is_opened(other)) | 1017 | if (!is_opened(other)) |
@@ -1035,21 +1024,15 @@ probe_exit: | |||
1035 | static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) | 1024 | static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) |
1036 | { | 1025 | { |
1037 | struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai); | 1026 | struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai); |
1038 | struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; | ||
1039 | |||
1040 | if (!other || !other->clk) { | ||
1041 | 1027 | ||
1042 | if (i2s->quirks & QUIRK_NEED_RSTCLR) | 1028 | if (!is_secondary(i2s)) { |
1029 | if (i2s->quirks & QUIRK_NEED_RSTCLR) { | ||
1030 | spin_lock(i2s->lock); | ||
1043 | writel(0, i2s->addr + I2SCON); | 1031 | writel(0, i2s->addr + I2SCON); |
1044 | 1032 | spin_unlock(i2s->lock); | |
1045 | clk_disable_unprepare(i2s->clk); | 1033 | } |
1046 | clk_put(i2s->clk); | ||
1047 | |||
1048 | iounmap(i2s->addr); | ||
1049 | } | 1034 | } |
1050 | 1035 | ||
1051 | i2s->clk = NULL; | ||
1052 | |||
1053 | return 0; | 1036 | return 0; |
1054 | } | 1037 | } |
1055 | 1038 | ||
@@ -1124,15 +1107,14 @@ static const struct of_device_id exynos_i2s_match[]; | |||
1124 | static inline const struct samsung_i2s_dai_data *samsung_i2s_get_driver_data( | 1107 | static inline const struct samsung_i2s_dai_data *samsung_i2s_get_driver_data( |
1125 | struct platform_device *pdev) | 1108 | struct platform_device *pdev) |
1126 | { | 1109 | { |
1127 | #ifdef CONFIG_OF | 1110 | if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { |
1128 | if (pdev->dev.of_node) { | ||
1129 | const struct of_device_id *match; | 1111 | const struct of_device_id *match; |
1130 | match = of_match_node(exynos_i2s_match, pdev->dev.of_node); | 1112 | match = of_match_node(exynos_i2s_match, pdev->dev.of_node); |
1131 | return match->data; | 1113 | return match ? match->data : NULL; |
1132 | } else | 1114 | } else { |
1133 | #endif | ||
1134 | return (struct samsung_i2s_dai_data *) | 1115 | return (struct samsung_i2s_dai_data *) |
1135 | platform_get_device_id(pdev)->driver_data; | 1116 | platform_get_device_id(pdev)->driver_data; |
1117 | } | ||
1136 | } | 1118 | } |
1137 | 1119 | ||
1138 | #ifdef CONFIG_PM | 1120 | #ifdef CONFIG_PM |
@@ -1155,6 +1137,87 @@ static int i2s_runtime_resume(struct device *dev) | |||
1155 | } | 1137 | } |
1156 | #endif /* CONFIG_PM */ | 1138 | #endif /* CONFIG_PM */ |
1157 | 1139 | ||
1140 | static void i2s_unregister_clocks(struct i2s_dai *i2s) | ||
1141 | { | ||
1142 | int i; | ||
1143 | |||
1144 | for (i = 0; i < i2s->clk_data.clk_num; i++) { | ||
1145 | if (!IS_ERR(i2s->clk_table[i])) | ||
1146 | clk_unregister(i2s->clk_table[i]); | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | static void i2s_unregister_clock_provider(struct platform_device *pdev) | ||
1151 | { | ||
1152 | struct i2s_dai *i2s = dev_get_drvdata(&pdev->dev); | ||
1153 | |||
1154 | of_clk_del_provider(pdev->dev.of_node); | ||
1155 | i2s_unregister_clocks(i2s); | ||
1156 | } | ||
1157 | |||
1158 | static int i2s_register_clock_provider(struct platform_device *pdev) | ||
1159 | { | ||
1160 | struct device *dev = &pdev->dev; | ||
1161 | struct i2s_dai *i2s = dev_get_drvdata(dev); | ||
1162 | const char *clk_name[2] = { "i2s_opclk0", "i2s_opclk1" }; | ||
1163 | const char *p_names[2] = { NULL }; | ||
1164 | const struct samsung_i2s_variant_regs *reg_info = i2s->variant_regs; | ||
1165 | struct clk *rclksrc; | ||
1166 | int ret, i; | ||
1167 | |||
1168 | /* Register the clock provider only if it's expected in the DTB */ | ||
1169 | if (!of_find_property(dev->of_node, "#clock-cells", NULL)) | ||
1170 | return 0; | ||
1171 | |||
1172 | /* Get the RCLKSRC mux clock parent clock names */ | ||
1173 | for (i = 0; i < ARRAY_SIZE(p_names); i++) { | ||
1174 | rclksrc = clk_get(dev, clk_name[i]); | ||
1175 | if (IS_ERR(rclksrc)) | ||
1176 | continue; | ||
1177 | p_names[i] = __clk_get_name(rclksrc); | ||
1178 | clk_put(rclksrc); | ||
1179 | } | ||
1180 | |||
1181 | if (!(i2s->quirks & QUIRK_NO_MUXPSR)) { | ||
1182 | /* Activate the prescaler */ | ||
1183 | u32 val = readl(i2s->addr + I2SPSR); | ||
1184 | writel(val | PSR_PSREN, i2s->addr + I2SPSR); | ||
1185 | |||
1186 | i2s->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(NULL, | ||
1187 | "i2s_rclksrc", p_names, ARRAY_SIZE(p_names), | ||
1188 | CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, | ||
1189 | i2s->addr + I2SMOD, reg_info->rclksrc_off, | ||
1190 | 1, 0, i2s->lock); | ||
1191 | |||
1192 | i2s->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(NULL, | ||
1193 | "i2s_presc", "i2s_rclksrc", | ||
1194 | CLK_SET_RATE_PARENT, | ||
1195 | i2s->addr + I2SPSR, 8, 6, 0, i2s->lock); | ||
1196 | |||
1197 | p_names[0] = "i2s_presc"; | ||
1198 | i2s->clk_data.clk_num = 2; | ||
1199 | } | ||
1200 | of_property_read_string_index(dev->of_node, | ||
1201 | "clock-output-names", 0, &clk_name[0]); | ||
1202 | |||
1203 | i2s->clk_table[CLK_I2S_CDCLK] = clk_register_gate(NULL, clk_name[0], | ||
1204 | p_names[0], CLK_SET_RATE_PARENT, | ||
1205 | i2s->addr + I2SMOD, reg_info->cdclkcon_off, | ||
1206 | CLK_GATE_SET_TO_DISABLE, i2s->lock); | ||
1207 | |||
1208 | i2s->clk_data.clk_num += 1; | ||
1209 | i2s->clk_data.clks = i2s->clk_table; | ||
1210 | |||
1211 | ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, | ||
1212 | &i2s->clk_data); | ||
1213 | if (ret < 0) { | ||
1214 | dev_err(dev, "failed to add clock provider: %d\n", ret); | ||
1215 | i2s_unregister_clocks(i2s); | ||
1216 | } | ||
1217 | |||
1218 | return ret; | ||
1219 | } | ||
1220 | |||
1158 | static int samsung_i2s_probe(struct platform_device *pdev) | 1221 | static int samsung_i2s_probe(struct platform_device *pdev) |
1159 | { | 1222 | { |
1160 | struct i2s_dai *pri_dai, *sec_dai = NULL; | 1223 | struct i2s_dai *pri_dai, *sec_dai = NULL; |
@@ -1164,7 +1227,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1164 | u32 regs_base, quirks = 0, idma_addr = 0; | 1227 | u32 regs_base, quirks = 0, idma_addr = 0; |
1165 | struct device_node *np = pdev->dev.of_node; | 1228 | struct device_node *np = pdev->dev.of_node; |
1166 | const struct samsung_i2s_dai_data *i2s_dai_data; | 1229 | const struct samsung_i2s_dai_data *i2s_dai_data; |
1167 | int ret = 0; | 1230 | int ret; |
1168 | 1231 | ||
1169 | /* Call during Seconday interface registration */ | 1232 | /* Call during Seconday interface registration */ |
1170 | i2s_dai_data = samsung_i2s_get_driver_data(pdev); | 1233 | i2s_dai_data = samsung_i2s_get_driver_data(pdev); |
@@ -1175,11 +1238,13 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1175 | dev_err(&pdev->dev, "Unable to get drvdata\n"); | 1238 | dev_err(&pdev->dev, "Unable to get drvdata\n"); |
1176 | return -EFAULT; | 1239 | return -EFAULT; |
1177 | } | 1240 | } |
1178 | devm_snd_soc_register_component(&sec_dai->pdev->dev, | 1241 | ret = devm_snd_soc_register_component(&sec_dai->pdev->dev, |
1179 | &samsung_i2s_component, | 1242 | &samsung_i2s_component, |
1180 | &sec_dai->i2s_dai_drv, 1); | 1243 | &sec_dai->i2s_dai_drv, 1); |
1181 | samsung_asoc_dma_platform_register(&pdev->dev); | 1244 | if (ret != 0) |
1182 | return 0; | 1245 | return ret; |
1246 | |||
1247 | return samsung_asoc_dma_platform_register(&pdev->dev); | ||
1183 | } | 1248 | } |
1184 | 1249 | ||
1185 | pri_dai = i2s_alloc_dai(pdev, false); | 1250 | pri_dai = i2s_alloc_dai(pdev, false); |
@@ -1188,6 +1253,9 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1188 | return -ENOMEM; | 1253 | return -ENOMEM; |
1189 | } | 1254 | } |
1190 | 1255 | ||
1256 | spin_lock_init(&pri_dai->spinlock); | ||
1257 | pri_dai->lock = &pri_dai->spinlock; | ||
1258 | |||
1191 | if (!np) { | 1259 | if (!np) { |
1192 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 1260 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
1193 | if (!res) { | 1261 | if (!res) { |
@@ -1229,25 +1297,29 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1229 | } | 1297 | } |
1230 | 1298 | ||
1231 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1299 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1232 | if (!res) { | 1300 | pri_dai->addr = devm_ioremap_resource(&pdev->dev, res); |
1233 | dev_err(&pdev->dev, "Unable to get I2S SFR address\n"); | 1301 | if (IS_ERR(pri_dai->addr)) |
1234 | return -ENXIO; | 1302 | return PTR_ERR(pri_dai->addr); |
1235 | } | ||
1236 | 1303 | ||
1237 | if (!request_mem_region(res->start, resource_size(res), | ||
1238 | "samsung-i2s")) { | ||
1239 | dev_err(&pdev->dev, "Unable to request SFR region\n"); | ||
1240 | return -EBUSY; | ||
1241 | } | ||
1242 | regs_base = res->start; | 1304 | regs_base = res->start; |
1243 | 1305 | ||
1306 | pri_dai->clk = devm_clk_get(&pdev->dev, "iis"); | ||
1307 | if (IS_ERR(pri_dai->clk)) { | ||
1308 | dev_err(&pdev->dev, "Failed to get iis clock\n"); | ||
1309 | return PTR_ERR(pri_dai->clk); | ||
1310 | } | ||
1311 | |||
1312 | ret = clk_prepare_enable(pri_dai->clk); | ||
1313 | if (ret != 0) { | ||
1314 | dev_err(&pdev->dev, "failed to enable clock: %d\n", ret); | ||
1315 | return ret; | ||
1316 | } | ||
1244 | pri_dai->dma_playback.dma_addr = regs_base + I2STXD; | 1317 | pri_dai->dma_playback.dma_addr = regs_base + I2STXD; |
1245 | pri_dai->dma_capture.dma_addr = regs_base + I2SRXD; | 1318 | pri_dai->dma_capture.dma_addr = regs_base + I2SRXD; |
1246 | pri_dai->dma_playback.ch_name = "tx"; | 1319 | pri_dai->dma_playback.ch_name = "tx"; |
1247 | pri_dai->dma_capture.ch_name = "rx"; | 1320 | pri_dai->dma_capture.ch_name = "rx"; |
1248 | pri_dai->dma_playback.dma_size = 4; | 1321 | pri_dai->dma_playback.dma_size = 4; |
1249 | pri_dai->dma_capture.dma_size = 4; | 1322 | pri_dai->dma_capture.dma_size = 4; |
1250 | pri_dai->base = regs_base; | ||
1251 | pri_dai->quirks = quirks; | 1323 | pri_dai->quirks = quirks; |
1252 | pri_dai->variant_regs = i2s_dai_data->i2s_variant_regs; | 1324 | pri_dai->variant_regs = i2s_dai_data->i2s_variant_regs; |
1253 | 1325 | ||
@@ -1258,10 +1330,10 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1258 | sec_dai = i2s_alloc_dai(pdev, true); | 1330 | sec_dai = i2s_alloc_dai(pdev, true); |
1259 | if (!sec_dai) { | 1331 | if (!sec_dai) { |
1260 | dev_err(&pdev->dev, "Unable to alloc I2S_sec\n"); | 1332 | dev_err(&pdev->dev, "Unable to alloc I2S_sec\n"); |
1261 | ret = -ENOMEM; | 1333 | return -ENOMEM; |
1262 | goto err; | ||
1263 | } | 1334 | } |
1264 | 1335 | ||
1336 | sec_dai->lock = &pri_dai->spinlock; | ||
1265 | sec_dai->variant_regs = pri_dai->variant_regs; | 1337 | sec_dai->variant_regs = pri_dai->variant_regs; |
1266 | sec_dai->dma_playback.dma_addr = regs_base + I2STXDS; | 1338 | sec_dai->dma_playback.dma_addr = regs_base + I2STXDS; |
1267 | sec_dai->dma_playback.ch_name = "tx-sec"; | 1339 | sec_dai->dma_playback.ch_name = "tx-sec"; |
@@ -1273,7 +1345,8 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1273 | } | 1345 | } |
1274 | 1346 | ||
1275 | sec_dai->dma_playback.dma_size = 4; | 1347 | sec_dai->dma_playback.dma_size = 4; |
1276 | sec_dai->base = regs_base; | 1348 | sec_dai->addr = pri_dai->addr; |
1349 | sec_dai->clk = pri_dai->clk; | ||
1277 | sec_dai->quirks = quirks; | 1350 | sec_dai->quirks = quirks; |
1278 | sec_dai->idma_playback.dma_addr = idma_addr; | 1351 | sec_dai->idma_playback.dma_addr = idma_addr; |
1279 | sec_dai->pri_dai = pri_dai; | 1352 | sec_dai->pri_dai = pri_dai; |
@@ -1282,8 +1355,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1282 | 1355 | ||
1283 | if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { | 1356 | if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { |
1284 | dev_err(&pdev->dev, "Unable to configure gpio\n"); | 1357 | dev_err(&pdev->dev, "Unable to configure gpio\n"); |
1285 | ret = -EINVAL; | 1358 | return -EINVAL; |
1286 | goto err; | ||
1287 | } | 1359 | } |
1288 | 1360 | ||
1289 | devm_snd_soc_register_component(&pri_dai->pdev->dev, | 1361 | devm_snd_soc_register_component(&pri_dai->pdev->dev, |
@@ -1292,32 +1364,30 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1292 | 1364 | ||
1293 | pm_runtime_enable(&pdev->dev); | 1365 | pm_runtime_enable(&pdev->dev); |
1294 | 1366 | ||
1295 | samsung_asoc_dma_platform_register(&pdev->dev); | 1367 | ret = samsung_asoc_dma_platform_register(&pdev->dev); |
1296 | 1368 | if (ret != 0) | |
1297 | return 0; | 1369 | return ret; |
1298 | err: | ||
1299 | if (res) | ||
1300 | release_mem_region(regs_base, resource_size(res)); | ||
1301 | 1370 | ||
1302 | return ret; | 1371 | return i2s_register_clock_provider(pdev); |
1303 | } | 1372 | } |
1304 | 1373 | ||
1305 | static int samsung_i2s_remove(struct platform_device *pdev) | 1374 | static int samsung_i2s_remove(struct platform_device *pdev) |
1306 | { | 1375 | { |
1307 | struct i2s_dai *i2s, *other; | 1376 | struct i2s_dai *i2s, *other; |
1308 | struct resource *res; | ||
1309 | 1377 | ||
1310 | i2s = dev_get_drvdata(&pdev->dev); | 1378 | i2s = dev_get_drvdata(&pdev->dev); |
1311 | other = i2s->pri_dai ? : i2s->sec_dai; | 1379 | other = get_other_dai(i2s); |
1312 | 1380 | ||
1313 | if (other) { | 1381 | if (other) { |
1314 | other->pri_dai = NULL; | 1382 | other->pri_dai = NULL; |
1315 | other->sec_dai = NULL; | 1383 | other->sec_dai = NULL; |
1316 | } else { | 1384 | } else { |
1317 | pm_runtime_disable(&pdev->dev); | 1385 | pm_runtime_disable(&pdev->dev); |
1318 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1386 | } |
1319 | if (res) | 1387 | |
1320 | release_mem_region(res->start, resource_size(res)); | 1388 | if (!is_secondary(i2s)) { |
1389 | i2s_unregister_clock_provider(pdev); | ||
1390 | clk_disable_unprepare(i2s->clk); | ||
1321 | } | 1391 | } |
1322 | 1392 | ||
1323 | i2s->pri_dai = NULL; | 1393 | i2s->pri_dai = NULL; |
diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c index b5f6abd9d221..7fcb51faa2a0 100644 --- a/sound/soc/samsung/jive_wm8750.c +++ b/sound/soc/samsung/jive_wm8750.c | |||
@@ -61,20 +61,6 @@ static int jive_hw_params(struct snd_pcm_substream *substream, | |||
61 | s3c_i2sv2_iis_calc_rate(&div, NULL, params_rate(params), | 61 | s3c_i2sv2_iis_calc_rate(&div, NULL, params_rate(params), |
62 | s3c_i2sv2_get_clock(cpu_dai)); | 62 | s3c_i2sv2_get_clock(cpu_dai)); |
63 | 63 | ||
64 | /* set codec DAI configuration */ | ||
65 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
66 | SND_SOC_DAIFMT_NB_NF | | ||
67 | SND_SOC_DAIFMT_CBS_CFS); | ||
68 | if (ret < 0) | ||
69 | return ret; | ||
70 | |||
71 | /* set cpu DAI configuration */ | ||
72 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
73 | SND_SOC_DAIFMT_NB_NF | | ||
74 | SND_SOC_DAIFMT_CBS_CFS); | ||
75 | if (ret < 0) | ||
76 | return ret; | ||
77 | |||
78 | /* set the codec system clock for DAC and ADC */ | 64 | /* set the codec system clock for DAC and ADC */ |
79 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk, | 65 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk, |
80 | SND_SOC_CLOCK_IN); | 66 | SND_SOC_CLOCK_IN); |
@@ -97,22 +83,6 @@ static struct snd_soc_ops jive_ops = { | |||
97 | .hw_params = jive_hw_params, | 83 | .hw_params = jive_hw_params, |
98 | }; | 84 | }; |
99 | 85 | ||
100 | static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd) | ||
101 | { | ||
102 | struct snd_soc_codec *codec = rtd->codec; | ||
103 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
104 | |||
105 | /* These endpoints are not being used. */ | ||
106 | snd_soc_dapm_nc_pin(dapm, "LINPUT2"); | ||
107 | snd_soc_dapm_nc_pin(dapm, "RINPUT2"); | ||
108 | snd_soc_dapm_nc_pin(dapm, "LINPUT3"); | ||
109 | snd_soc_dapm_nc_pin(dapm, "RINPUT3"); | ||
110 | snd_soc_dapm_nc_pin(dapm, "OUT3"); | ||
111 | snd_soc_dapm_nc_pin(dapm, "MONO"); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static struct snd_soc_dai_link jive_dai = { | 86 | static struct snd_soc_dai_link jive_dai = { |
117 | .name = "wm8750", | 87 | .name = "wm8750", |
118 | .stream_name = "WM8750", | 88 | .stream_name = "WM8750", |
@@ -120,7 +90,8 @@ static struct snd_soc_dai_link jive_dai = { | |||
120 | .codec_dai_name = "wm8750-hifi", | 90 | .codec_dai_name = "wm8750-hifi", |
121 | .platform_name = "s3c2412-i2s", | 91 | .platform_name = "s3c2412-i2s", |
122 | .codec_name = "wm8750.0-001a", | 92 | .codec_name = "wm8750.0-001a", |
123 | .init = jive_wm8750_init, | 93 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | |
94 | SND_SOC_DAIFMT_CBS_CFS, | ||
124 | .ops = &jive_ops, | 95 | .ops = &jive_ops, |
125 | }; | 96 | }; |
126 | 97 | ||
@@ -135,6 +106,7 @@ static struct snd_soc_card snd_soc_machine_jive = { | |||
135 | .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), | 106 | .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), |
136 | .dapm_routes = audio_map, | 107 | .dapm_routes = audio_map, |
137 | .num_dapm_routes = ARRAY_SIZE(audio_map), | 108 | .num_dapm_routes = ARRAY_SIZE(audio_map), |
109 | .fully_routed = true, | ||
138 | }; | 110 | }; |
139 | 111 | ||
140 | static struct platform_device *jive_snd_device; | 112 | static struct platform_device *jive_snd_device; |
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 9b4a09f14b6c..65602b935377 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c | |||
@@ -70,20 +70,6 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, | |||
70 | break; | 70 | break; |
71 | } | 71 | } |
72 | 72 | ||
73 | /* set codec DAI configuration */ | ||
74 | ret = snd_soc_dai_set_fmt(codec_dai, | ||
75 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
76 | SND_SOC_DAIFMT_CBM_CFM); | ||
77 | if (ret < 0) | ||
78 | return ret; | ||
79 | |||
80 | /* set cpu DAI configuration */ | ||
81 | ret = snd_soc_dai_set_fmt(cpu_dai, | ||
82 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
83 | SND_SOC_DAIFMT_CBM_CFM); | ||
84 | if (ret < 0) | ||
85 | return ret; | ||
86 | |||
87 | /* set the codec system clock for DAC and ADC */ | 73 | /* set the codec system clock for DAC and ADC */ |
88 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out, | 74 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out, |
89 | SND_SOC_CLOCK_IN); | 75 | SND_SOC_CLOCK_IN); |
@@ -151,13 +137,6 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, | |||
151 | 137 | ||
152 | pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */ | 138 | pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */ |
153 | 139 | ||
154 | /* todo: gg check mode (DSP_B) against CSR datasheet */ | ||
155 | /* set codec DAI configuration */ | ||
156 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | | ||
157 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
158 | if (ret < 0) | ||
159 | return ret; | ||
160 | |||
161 | /* set the codec system clock for DAC and ADC */ | 140 | /* set the codec system clock for DAC and ADC */ |
162 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, 12288000, | 141 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, 12288000, |
163 | SND_SOC_CLOCK_IN); | 142 | SND_SOC_CLOCK_IN); |
@@ -300,6 +279,8 @@ static struct snd_soc_dai_link neo1973_dai[] = { | |||
300 | .cpu_dai_name = "s3c24xx-iis", | 279 | .cpu_dai_name = "s3c24xx-iis", |
301 | .codec_dai_name = "wm8753-hifi", | 280 | .codec_dai_name = "wm8753-hifi", |
302 | .codec_name = "wm8753.0-001a", | 281 | .codec_name = "wm8753.0-001a", |
282 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
283 | SND_SOC_DAIFMT_CBM_CFM, | ||
303 | .init = neo1973_wm8753_init, | 284 | .init = neo1973_wm8753_init, |
304 | .ops = &neo1973_hifi_ops, | 285 | .ops = &neo1973_hifi_ops, |
305 | }, | 286 | }, |
@@ -309,6 +290,8 @@ static struct snd_soc_dai_link neo1973_dai[] = { | |||
309 | .cpu_dai_name = "bt-sco-pcm", | 290 | .cpu_dai_name = "bt-sco-pcm", |
310 | .codec_dai_name = "wm8753-voice", | 291 | .codec_dai_name = "wm8753-voice", |
311 | .codec_name = "wm8753.0-001a", | 292 | .codec_name = "wm8753.0-001a", |
293 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | | ||
294 | SND_SOC_DAIFMT_CBS_CFS, | ||
312 | .ops = &neo1973_voice_ops, | 295 | .ops = &neo1973_voice_ops, |
313 | }, | 296 | }, |
314 | }; | 297 | }; |
diff --git a/sound/soc/samsung/odroidx2_max98090.c b/sound/soc/samsung/odroidx2_max98090.c index fa4f1d2f69bf..596f1180a369 100644 --- a/sound/soc/samsung/odroidx2_max98090.c +++ b/sound/soc/samsung/odroidx2_max98090.c | |||
@@ -21,6 +21,8 @@ struct odroidx2_drv_data { | |||
21 | /* The I2S CDCLK output clock frequency for the MAX98090 codec */ | 21 | /* The I2S CDCLK output clock frequency for the MAX98090 codec */ |
22 | #define MAX98090_MCLK 19200000 | 22 | #define MAX98090_MCLK 19200000 |
23 | 23 | ||
24 | static struct snd_soc_dai_link odroidx2_dai[]; | ||
25 | |||
24 | static int odroidx2_late_probe(struct snd_soc_card *card) | 26 | static int odroidx2_late_probe(struct snd_soc_card *card) |
25 | { | 27 | { |
26 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | 28 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; |
@@ -29,7 +31,9 @@ static int odroidx2_late_probe(struct snd_soc_card *card) | |||
29 | 31 | ||
30 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, MAX98090_MCLK, | 32 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, MAX98090_MCLK, |
31 | SND_SOC_CLOCK_IN); | 33 | SND_SOC_CLOCK_IN); |
32 | if (ret < 0) | 34 | |
35 | if (ret < 0 || of_find_property(odroidx2_dai[0].codec_of_node, | ||
36 | "clocks", NULL)) | ||
33 | return ret; | 37 | return ret; |
34 | 38 | ||
35 | /* Set the cpu DAI configuration in order to use CDCLK */ | 39 | /* Set the cpu DAI configuration in order to use CDCLK */ |
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index 37688ebbb2b4..873f2cb4bebe 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c | |||
@@ -89,6 +89,8 @@ static struct snd_soc_dai_link rx1950_uda1380_dai[] = { | |||
89 | .init = rx1950_uda1380_init, | 89 | .init = rx1950_uda1380_init, |
90 | .platform_name = "s3c24xx-iis", | 90 | .platform_name = "s3c24xx-iis", |
91 | .codec_name = "uda1380-codec.0-001a", | 91 | .codec_name = "uda1380-codec.0-001a", |
92 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
93 | SND_SOC_DAIFMT_CBS_CFS, | ||
92 | .ops = &rx1950_ops, | 94 | .ops = &rx1950_ops, |
93 | }, | 95 | }, |
94 | }; | 96 | }; |
@@ -154,7 +156,6 @@ static int rx1950_hw_params(struct snd_pcm_substream *substream, | |||
154 | { | 156 | { |
155 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 157 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
156 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 158 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
157 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
158 | int div; | 159 | int div; |
159 | int ret; | 160 | int ret; |
160 | unsigned int rate = params_rate(params); | 161 | unsigned int rate = params_rate(params); |
@@ -181,18 +182,6 @@ static int rx1950_hw_params(struct snd_pcm_substream *substream, | |||
181 | return -EINVAL; | 182 | return -EINVAL; |
182 | } | 183 | } |
183 | 184 | ||
184 | /* set codec DAI configuration */ | ||
185 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
186 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
187 | if (ret < 0) | ||
188 | return ret; | ||
189 | |||
190 | /* set cpu DAI configuration */ | ||
191 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
192 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
193 | if (ret < 0) | ||
194 | return ret; | ||
195 | |||
196 | /* select clock source */ | 185 | /* select clock source */ |
197 | ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source, rate, | 186 | ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source, rate, |
198 | SND_SOC_CLOCK_OUT); | 187 | SND_SOC_CLOCK_OUT); |
diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c index 2c015f62ead6..dcc008d1e1ab 100644 --- a/sound/soc/samsung/s3c24xx_simtec.c +++ b/sound/soc/samsung/s3c24xx_simtec.c | |||
@@ -169,24 +169,6 @@ static int simtec_hw_params(struct snd_pcm_substream *substream, | |||
169 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 169 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
170 | int ret; | 170 | int ret; |
171 | 171 | ||
172 | /* Set the CODEC as the bus clock master, I2S */ | ||
173 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
174 | SND_SOC_DAIFMT_NB_NF | | ||
175 | SND_SOC_DAIFMT_CBM_CFM); | ||
176 | if (ret) { | ||
177 | pr_err("%s: failed set cpu dai format\n", __func__); | ||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | /* Set the CODEC as the bus clock master */ | ||
182 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
183 | SND_SOC_DAIFMT_NB_NF | | ||
184 | SND_SOC_DAIFMT_CBM_CFM); | ||
185 | if (ret) { | ||
186 | pr_err("%s: failed set codec dai format\n", __func__); | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, | 172 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, |
191 | CODEC_CLOCK, SND_SOC_CLOCK_IN); | 173 | CODEC_CLOCK, SND_SOC_CLOCK_IN); |
192 | if (ret) { | 174 | if (ret) { |
@@ -320,6 +302,8 @@ int simtec_audio_core_probe(struct platform_device *pdev, | |||
320 | int ret; | 302 | int ret; |
321 | 303 | ||
322 | card->dai_link->ops = &simtec_snd_ops; | 304 | card->dai_link->ops = &simtec_snd_ops; |
305 | card->dai_link->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
306 | SND_SOC_DAIFMT_CBM_CFM; | ||
323 | 307 | ||
324 | pdata = pdev->dev.platform_data; | 308 | pdata = pdev->dev.platform_data; |
325 | if (!pdata) { | 309 | if (!pdata) { |
diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index 9c6f7db56f60..50849e137fc0 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c | |||
@@ -173,16 +173,6 @@ static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream, | |||
173 | return -EINVAL; | 173 | return -EINVAL; |
174 | } | 174 | } |
175 | 175 | ||
176 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
177 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
178 | if (ret < 0) | ||
179 | return ret; | ||
180 | |||
181 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
182 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
183 | if (ret < 0) | ||
184 | return ret; | ||
185 | |||
186 | ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source , clk, | 176 | ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source , clk, |
187 | SND_SOC_CLOCK_IN); | 177 | SND_SOC_CLOCK_IN); |
188 | if (ret < 0) | 178 | if (ret < 0) |
@@ -223,6 +213,8 @@ static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { | |||
223 | .codec_name = "uda134x-codec", | 213 | .codec_name = "uda134x-codec", |
224 | .codec_dai_name = "uda134x-hifi", | 214 | .codec_dai_name = "uda134x-hifi", |
225 | .cpu_dai_name = "s3c24xx-iis", | 215 | .cpu_dai_name = "s3c24xx-iis", |
216 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
217 | SND_SOC_DAIFMT_CBS_CFS, | ||
226 | .ops = &s3c24xx_uda134x_ops, | 218 | .ops = &s3c24xx_uda134x_ops, |
227 | .platform_name = "s3c24xx-iis", | 219 | .platform_name = "s3c24xx-iis", |
228 | }; | 220 | }; |
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c index 9b0ffacab790..8291d2a5f152 100644 --- a/sound/soc/samsung/smartq_wm8987.c +++ b/sound/soc/samsung/smartq_wm8987.c | |||
@@ -56,20 +56,6 @@ static int smartq_hifi_hw_params(struct snd_pcm_substream *substream, | |||
56 | break; | 56 | break; |
57 | } | 57 | } |
58 | 58 | ||
59 | /* set codec DAI configuration */ | ||
60 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
61 | SND_SOC_DAIFMT_NB_NF | | ||
62 | SND_SOC_DAIFMT_CBS_CFS); | ||
63 | if (ret < 0) | ||
64 | return ret; | ||
65 | |||
66 | /* set cpu DAI configuration */ | ||
67 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
68 | SND_SOC_DAIFMT_NB_NF | | ||
69 | SND_SOC_DAIFMT_CBS_CFS); | ||
70 | if (ret < 0) | ||
71 | return ret; | ||
72 | |||
73 | /* Use PCLK for I2S signal generation */ | 59 | /* Use PCLK for I2S signal generation */ |
74 | ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_0, | 60 | ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_0, |
75 | 0, SND_SOC_CLOCK_IN); | 61 | 0, SND_SOC_CLOCK_IN); |
@@ -199,6 +185,8 @@ static struct snd_soc_dai_link smartq_dai[] = { | |||
199 | .platform_name = "samsung-i2s.0", | 185 | .platform_name = "samsung-i2s.0", |
200 | .codec_name = "wm8750.0-0x1a", | 186 | .codec_name = "wm8750.0-0x1a", |
201 | .init = smartq_wm8987_init, | 187 | .init = smartq_wm8987_init, |
188 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
189 | SND_SOC_DAIFMT_CBS_CFS, | ||
202 | .ops = &smartq_hifi_ops, | 190 | .ops = &smartq_hifi_ops, |
203 | }, | 191 | }, |
204 | }; | 192 | }; |
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c index b1a519f83b29..548bfd993788 100644 --- a/sound/soc/samsung/smdk_wm8580.c +++ b/sound/soc/samsung/smdk_wm8580.c | |||
@@ -32,7 +32,6 @@ static int smdk_hw_params(struct snd_pcm_substream *substream, | |||
32 | struct snd_pcm_hw_params *params) | 32 | struct snd_pcm_hw_params *params) |
33 | { | 33 | { |
34 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 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; | 35 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
37 | unsigned int pll_out; | 36 | unsigned int pll_out; |
38 | int bfs, rfs, ret; | 37 | int bfs, rfs, ret; |
@@ -77,20 +76,6 @@ static int smdk_hw_params(struct snd_pcm_substream *substream, | |||
77 | } | 76 | } |
78 | pll_out = params_rate(params) * rfs; | 77 | pll_out = params_rate(params) * rfs; |
79 | 78 | ||
80 | /* Set the Codec DAI configuration */ | ||
81 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | ||
82 | | SND_SOC_DAIFMT_NB_NF | ||
83 | | SND_SOC_DAIFMT_CBM_CFM); | ||
84 | if (ret < 0) | ||
85 | return ret; | ||
86 | |||
87 | /* Set the AP DAI configuration */ | ||
88 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | ||
89 | | SND_SOC_DAIFMT_NB_NF | ||
90 | | SND_SOC_DAIFMT_CBM_CFM); | ||
91 | if (ret < 0) | ||
92 | return ret; | ||
93 | |||
94 | /* Set WM8580 to drive MCLK from its PLLA */ | 79 | /* Set WM8580 to drive MCLK from its PLLA */ |
95 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK, | 80 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK, |
96 | WM8580_CLKSRC_PLLA); | 81 | WM8580_CLKSRC_PLLA); |
@@ -151,13 +136,10 @@ static const struct snd_soc_dapm_route smdk_wm8580_audio_map[] = { | |||
151 | 136 | ||
152 | static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd) | 137 | static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd) |
153 | { | 138 | { |
154 | struct snd_soc_codec *codec = rtd->codec; | ||
155 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
156 | |||
157 | /* Enabling the microphone requires the fitting of a 0R | 139 | /* Enabling the microphone requires the fitting of a 0R |
158 | * resistor to connect the line from the microphone jack. | 140 | * resistor to connect the line from the microphone jack. |
159 | */ | 141 | */ |
160 | snd_soc_dapm_disable_pin(dapm, "MicIn"); | 142 | snd_soc_dapm_disable_pin(&rtd->card->dapm, "MicIn"); |
161 | 143 | ||
162 | return 0; | 144 | return 0; |
163 | } | 145 | } |
@@ -168,6 +150,9 @@ enum { | |||
168 | SEC_PLAYBACK, | 150 | SEC_PLAYBACK, |
169 | }; | 151 | }; |
170 | 152 | ||
153 | #define SMDK_DAI_FMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \ | ||
154 | SND_SOC_DAIFMT_CBM_CFM) | ||
155 | |||
171 | static struct snd_soc_dai_link smdk_dai[] = { | 156 | static struct snd_soc_dai_link smdk_dai[] = { |
172 | [PRI_PLAYBACK] = { /* Primary Playback i/f */ | 157 | [PRI_PLAYBACK] = { /* Primary Playback i/f */ |
173 | .name = "WM8580 PAIF RX", | 158 | .name = "WM8580 PAIF RX", |
@@ -176,6 +161,7 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
176 | .codec_dai_name = "wm8580-hifi-playback", | 161 | .codec_dai_name = "wm8580-hifi-playback", |
177 | .platform_name = "samsung-i2s.0", | 162 | .platform_name = "samsung-i2s.0", |
178 | .codec_name = "wm8580.0-001b", | 163 | .codec_name = "wm8580.0-001b", |
164 | .dai_fmt = SMDK_DAI_FMT, | ||
179 | .ops = &smdk_ops, | 165 | .ops = &smdk_ops, |
180 | }, | 166 | }, |
181 | [PRI_CAPTURE] = { /* Primary Capture i/f */ | 167 | [PRI_CAPTURE] = { /* Primary Capture i/f */ |
@@ -185,6 +171,7 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
185 | .codec_dai_name = "wm8580-hifi-capture", | 171 | .codec_dai_name = "wm8580-hifi-capture", |
186 | .platform_name = "samsung-i2s.0", | 172 | .platform_name = "samsung-i2s.0", |
187 | .codec_name = "wm8580.0-001b", | 173 | .codec_name = "wm8580.0-001b", |
174 | .dai_fmt = SMDK_DAI_FMT, | ||
188 | .init = smdk_wm8580_init_paiftx, | 175 | .init = smdk_wm8580_init_paiftx, |
189 | .ops = &smdk_ops, | 176 | .ops = &smdk_ops, |
190 | }, | 177 | }, |
@@ -195,6 +182,7 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
195 | .codec_dai_name = "wm8580-hifi-playback", | 182 | .codec_dai_name = "wm8580-hifi-playback", |
196 | .platform_name = "samsung-i2s-sec", | 183 | .platform_name = "samsung-i2s-sec", |
197 | .codec_name = "wm8580.0-001b", | 184 | .codec_name = "wm8580.0-001b", |
185 | .dai_fmt = SMDK_DAI_FMT, | ||
198 | .ops = &smdk_ops, | 186 | .ops = &smdk_ops, |
199 | }, | 187 | }, |
200 | }; | 188 | }; |
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c index 05c609c62de9..6deec5234c92 100644 --- a/sound/soc/samsung/smdk_wm8580pcm.c +++ b/sound/soc/samsung/smdk_wm8580pcm.c | |||
@@ -62,20 +62,6 @@ static int smdk_wm8580_pcm_hw_params(struct snd_pcm_substream *substream, | |||
62 | 62 | ||
63 | rfs = mclk_freq / params_rate(params) / 2; | 63 | rfs = mclk_freq / params_rate(params) / 2; |
64 | 64 | ||
65 | /* Set the codec DAI configuration */ | ||
66 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | ||
67 | | SND_SOC_DAIFMT_IB_NF | ||
68 | | SND_SOC_DAIFMT_CBS_CFS); | ||
69 | if (ret < 0) | ||
70 | return ret; | ||
71 | |||
72 | /* Set the cpu DAI configuration */ | ||
73 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_B | ||
74 | | SND_SOC_DAIFMT_IB_NF | ||
75 | | SND_SOC_DAIFMT_CBS_CFS); | ||
76 | if (ret < 0) | ||
77 | return ret; | ||
78 | |||
79 | if (mclk_freq == xtal_freq) { | 65 | if (mclk_freq == xtal_freq) { |
80 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_MCLK, | 66 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_MCLK, |
81 | mclk_freq, SND_SOC_CLOCK_IN); | 67 | mclk_freq, SND_SOC_CLOCK_IN); |
@@ -121,6 +107,9 @@ static struct snd_soc_ops smdk_wm8580_pcm_ops = { | |||
121 | .hw_params = smdk_wm8580_pcm_hw_params, | 107 | .hw_params = smdk_wm8580_pcm_hw_params, |
122 | }; | 108 | }; |
123 | 109 | ||
110 | #define SMDK_DAI_FMT (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | \ | ||
111 | SND_SOC_DAIFMT_CBS_CFS) | ||
112 | |||
124 | static struct snd_soc_dai_link smdk_dai[] = { | 113 | static struct snd_soc_dai_link smdk_dai[] = { |
125 | { | 114 | { |
126 | .name = "WM8580 PAIF PCM RX", | 115 | .name = "WM8580 PAIF PCM RX", |
@@ -129,6 +118,7 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
129 | .codec_dai_name = "wm8580-hifi-playback", | 118 | .codec_dai_name = "wm8580-hifi-playback", |
130 | .platform_name = "samsung-audio", | 119 | .platform_name = "samsung-audio", |
131 | .codec_name = "wm8580.0-001b", | 120 | .codec_name = "wm8580.0-001b", |
121 | .dai_fmt = SMDK_DAI_FMT, | ||
132 | .ops = &smdk_wm8580_pcm_ops, | 122 | .ops = &smdk_wm8580_pcm_ops, |
133 | }, { | 123 | }, { |
134 | .name = "WM8580 PAIF PCM TX", | 124 | .name = "WM8580 PAIF PCM TX", |
@@ -137,6 +127,7 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
137 | .codec_dai_name = "wm8580-hifi-capture", | 127 | .codec_dai_name = "wm8580-hifi-capture", |
138 | .platform_name = "samsung-pcm.0", | 128 | .platform_name = "samsung-pcm.0", |
139 | .codec_name = "wm8580.0-001b", | 129 | .codec_name = "wm8580.0-001b", |
130 | .dai_fmt = SMDK_DAI_FMT, | ||
140 | .ops = &smdk_wm8580_pcm_ops, | 131 | .ops = &smdk_wm8580_pcm_ops, |
141 | }, | 132 | }, |
142 | }; | 133 | }; |
diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c index c470e8eed6e1..b1c89ec2d999 100644 --- a/sound/soc/samsung/smdk_wm8994pcm.c +++ b/sound/soc/samsung/smdk_wm8994pcm.c | |||
@@ -68,20 +68,6 @@ static int smdk_wm8994_pcm_hw_params(struct snd_pcm_substream *substream, | |||
68 | 68 | ||
69 | mclk_freq = params_rate(params) * rfs; | 69 | mclk_freq = params_rate(params) * rfs; |
70 | 70 | ||
71 | /* Set the codec DAI configuration */ | ||
72 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | ||
73 | | SND_SOC_DAIFMT_IB_NF | ||
74 | | SND_SOC_DAIFMT_CBS_CFS); | ||
75 | if (ret < 0) | ||
76 | return ret; | ||
77 | |||
78 | /* Set the cpu DAI configuration */ | ||
79 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_B | ||
80 | | SND_SOC_DAIFMT_IB_NF | ||
81 | | SND_SOC_DAIFMT_CBS_CFS); | ||
82 | if (ret < 0) | ||
83 | return ret; | ||
84 | |||
85 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, | 71 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, |
86 | mclk_freq, SND_SOC_CLOCK_IN); | 72 | mclk_freq, SND_SOC_CLOCK_IN); |
87 | if (ret < 0) | 73 | if (ret < 0) |
@@ -118,6 +104,8 @@ static struct snd_soc_dai_link smdk_dai[] = { | |||
118 | .codec_dai_name = "wm8994-aif1", | 104 | .codec_dai_name = "wm8994-aif1", |
119 | .platform_name = "samsung-pcm.0", | 105 | .platform_name = "samsung-pcm.0", |
120 | .codec_name = "wm8994-codec", | 106 | .codec_name = "wm8994-codec", |
107 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | | ||
108 | SND_SOC_DAIFMT_CBS_CFS, | ||
121 | .ops = &smdk_wm8994_pcm_ops, | 109 | .ops = &smdk_wm8994_pcm_ops, |
122 | }, | 110 | }, |
123 | }; | 111 | }; |
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index a5b2c4ea90d9..fd11404a3bc7 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c | |||
@@ -305,11 +305,6 @@ static struct snd_pcm_ops camelot_pcm_ops = { | |||
305 | .pointer = camelot_pos, | 305 | .pointer = camelot_pos, |
306 | }; | 306 | }; |
307 | 307 | ||
308 | static void camelot_pcm_free(struct snd_pcm *pcm) | ||
309 | { | ||
310 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
311 | } | ||
312 | |||
313 | static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd) | 308 | static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd) |
314 | { | 309 | { |
315 | struct snd_pcm *pcm = rtd->pcm; | 310 | struct snd_pcm *pcm = rtd->pcm; |
@@ -328,7 +323,6 @@ static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
328 | static struct snd_soc_platform_driver sh7760_soc_platform = { | 323 | static struct snd_soc_platform_driver sh7760_soc_platform = { |
329 | .ops = &camelot_pcm_ops, | 324 | .ops = &camelot_pcm_ops, |
330 | .pcm_new = camelot_pcm_new, | 325 | .pcm_new = camelot_pcm_new, |
331 | .pcm_free = camelot_pcm_free, | ||
332 | }; | 326 | }; |
333 | 327 | ||
334 | static int sh7760_soc_platform_probe(struct platform_device *pdev) | 328 | static int sh7760_soc_platform_probe(struct platform_device *pdev) |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 8869971d7884..b87b22e88e43 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -820,12 +820,9 @@ static int fsi_clk_enable(struct device *dev, | |||
820 | return ret; | 820 | return ret; |
821 | } | 821 | } |
822 | 822 | ||
823 | if (clock->xck) | 823 | clk_enable(clock->xck); |
824 | clk_enable(clock->xck); | 824 | clk_enable(clock->ick); |
825 | if (clock->ick) | 825 | clk_enable(clock->div); |
826 | clk_enable(clock->ick); | ||
827 | if (clock->div) | ||
828 | clk_enable(clock->div); | ||
829 | 826 | ||
830 | clock->count++; | 827 | clock->count++; |
831 | } | 828 | } |
@@ -1765,11 +1762,6 @@ static struct snd_pcm_ops fsi_pcm_ops = { | |||
1765 | #define PREALLOC_BUFFER (32 * 1024) | 1762 | #define PREALLOC_BUFFER (32 * 1024) |
1766 | #define PREALLOC_BUFFER_MAX (32 * 1024) | 1763 | #define PREALLOC_BUFFER_MAX (32 * 1024) |
1767 | 1764 | ||
1768 | static void fsi_pcm_free(struct snd_pcm *pcm) | ||
1769 | { | ||
1770 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
1771 | } | ||
1772 | |||
1773 | static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd) | 1765 | static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd) |
1774 | { | 1766 | { |
1775 | return snd_pcm_lib_preallocate_pages_for_all( | 1767 | return snd_pcm_lib_preallocate_pages_for_all( |
@@ -1821,7 +1813,6 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = { | |||
1821 | static struct snd_soc_platform_driver fsi_soc_platform = { | 1813 | static struct snd_soc_platform_driver fsi_soc_platform = { |
1822 | .ops = &fsi_pcm_ops, | 1814 | .ops = &fsi_pcm_ops, |
1823 | .pcm_new = fsi_pcm_new, | 1815 | .pcm_new = fsi_pcm_new, |
1824 | .pcm_free = fsi_pcm_free, | ||
1825 | }; | 1816 | }; |
1826 | 1817 | ||
1827 | static const struct snd_soc_component_driver fsi_soc_component = { | 1818 | static const struct snd_soc_component_driver fsi_soc_component = { |
diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index c58c2529f103..82f582344fe7 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c | |||
@@ -63,16 +63,6 @@ static int migor_hw_params(struct snd_pcm_substream *substream, | |||
63 | if (ret < 0) | 63 | if (ret < 0) |
64 | return ret; | 64 | return ret; |
65 | 65 | ||
66 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_NB_IF | | ||
67 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS); | ||
68 | if (ret < 0) | ||
69 | return ret; | ||
70 | |||
71 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_NB_IF | | ||
72 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS); | ||
73 | if (ret < 0) | ||
74 | return ret; | ||
75 | |||
76 | codec_freq = rate * 512; | 66 | codec_freq = rate * 512; |
77 | /* | 67 | /* |
78 | * This propagates the parent frequency change to children and | 68 | * This propagates the parent frequency change to children and |
@@ -144,6 +134,8 @@ static struct snd_soc_dai_link migor_dai = { | |||
144 | .codec_dai_name = "wm8978-hifi", | 134 | .codec_dai_name = "wm8978-hifi", |
145 | .platform_name = "siu-pcm-audio", | 135 | .platform_name = "siu-pcm-audio", |
146 | .codec_name = "wm8978.0-001a", | 136 | .codec_name = "wm8978.0-001a", |
137 | .dai_fmt = SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_I2S | | ||
138 | SND_SOC_DAIFMT_CBS_CFS, | ||
147 | .ops = &migor_dai_ops, | 139 | .ops = &migor_dai_ops, |
148 | }; | 140 | }; |
149 | 141 | ||
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 14d1a7193469..7ac35c9d1cb8 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c | |||
@@ -57,8 +57,7 @@ static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io) | |||
57 | return (0x6 + ws) << 8; | 57 | return (0x6 + ws) << 8; |
58 | } | 58 | } |
59 | 59 | ||
60 | int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_dai *rdai, | 60 | int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod, |
61 | struct rsnd_mod *mod, | ||
62 | struct rsnd_dai_stream *io) | 61 | struct rsnd_dai_stream *io) |
63 | { | 62 | { |
64 | int id = rsnd_mod_id(mod); | 63 | int id = rsnd_mod_id(mod); |
@@ -75,12 +74,11 @@ int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_dai *rdai, | |||
75 | return 0; | 74 | return 0; |
76 | } | 75 | } |
77 | 76 | ||
78 | static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, | 77 | static int rsnd_adg_set_src_timsel_gen2(struct rsnd_mod *mod, |
79 | struct rsnd_mod *mod, | ||
80 | struct rsnd_dai_stream *io, | 78 | struct rsnd_dai_stream *io, |
81 | u32 timsel) | 79 | u32 timsel) |
82 | { | 80 | { |
83 | int is_play = rsnd_dai_is_play(rdai, io); | 81 | int is_play = rsnd_io_is_play(io); |
84 | int id = rsnd_mod_id(mod); | 82 | int id = rsnd_mod_id(mod); |
85 | int shift = (id % 2) ? 16 : 0; | 83 | int shift = (id % 2) ? 16 : 0; |
86 | u32 mask, ws; | 84 | u32 mask, ws; |
@@ -122,7 +120,6 @@ static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, | |||
122 | } | 120 | } |
123 | 121 | ||
124 | int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, | 122 | int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, |
125 | struct rsnd_dai *rdai, | ||
126 | struct rsnd_dai_stream *io, | 123 | struct rsnd_dai_stream *io, |
127 | unsigned int src_rate, | 124 | unsigned int src_rate, |
128 | unsigned int dst_rate) | 125 | unsigned int dst_rate) |
@@ -178,7 +175,7 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, | |||
178 | return -EIO; | 175 | return -EIO; |
179 | } | 176 | } |
180 | 177 | ||
181 | ret = rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); | 178 | ret = rsnd_adg_set_src_timsel_gen2(mod, io, val); |
182 | if (ret < 0) { | 179 | if (ret < 0) { |
183 | dev_err(dev, "timsel error\n"); | 180 | dev_err(dev, "timsel error\n"); |
184 | return ret; | 181 | return ret; |
@@ -190,12 +187,11 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, | |||
190 | } | 187 | } |
191 | 188 | ||
192 | int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, | 189 | int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, |
193 | struct rsnd_dai *rdai, | ||
194 | struct rsnd_dai_stream *io) | 190 | struct rsnd_dai_stream *io) |
195 | { | 191 | { |
196 | u32 val = rsnd_adg_ssi_ws_timing_gen2(io); | 192 | u32 val = rsnd_adg_ssi_ws_timing_gen2(io); |
197 | 193 | ||
198 | return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); | 194 | return rsnd_adg_set_src_timsel_gen2(mod, io, val); |
199 | } | 195 | } |
200 | 196 | ||
201 | int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, | 197 | int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, |
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 75308bbc2ce8..110577c52317 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -149,16 +149,16 @@ char *rsnd_mod_dma_name(struct rsnd_mod *mod) | |||
149 | return mod->ops->dma_name(mod); | 149 | return mod->ops->dma_name(mod); |
150 | } | 150 | } |
151 | 151 | ||
152 | void rsnd_mod_init(struct rsnd_priv *priv, | 152 | void rsnd_mod_init(struct rsnd_mod *mod, |
153 | struct rsnd_mod *mod, | ||
154 | struct rsnd_mod_ops *ops, | 153 | struct rsnd_mod_ops *ops, |
154 | struct clk *clk, | ||
155 | enum rsnd_mod_type type, | 155 | enum rsnd_mod_type type, |
156 | int id) | 156 | int id) |
157 | { | 157 | { |
158 | mod->priv = priv; | ||
159 | mod->id = id; | 158 | mod->id = id; |
160 | mod->ops = ops; | 159 | mod->ops = ops; |
161 | mod->type = type; | 160 | mod->type = type; |
161 | mod->clk = clk; | ||
162 | } | 162 | } |
163 | 163 | ||
164 | /* | 164 | /* |
@@ -412,7 +412,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) | |||
412 | /* | 412 | /* |
413 | * rsnd_dai functions | 413 | * rsnd_dai functions |
414 | */ | 414 | */ |
415 | #define __rsnd_mod_call(mod, func, rdai...) \ | 415 | #define __rsnd_mod_call(mod, func, param...) \ |
416 | ({ \ | 416 | ({ \ |
417 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ | 417 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ |
418 | struct device *dev = rsnd_priv_to_dev(priv); \ | 418 | struct device *dev = rsnd_priv_to_dev(priv); \ |
@@ -422,18 +422,18 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) | |||
422 | if ((mod->status & mask) == call) { \ | 422 | if ((mod->status & mask) == call) { \ |
423 | dev_dbg(dev, "%s[%d] %s\n", \ | 423 | dev_dbg(dev, "%s[%d] %s\n", \ |
424 | rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ | 424 | rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ |
425 | ret = (mod)->ops->func(mod, rdai); \ | 425 | ret = (mod)->ops->func(mod, param); \ |
426 | mod->status = (mod->status & ~mask) | (~call & mask); \ | 426 | mod->status = (mod->status & ~mask) | (~call & mask); \ |
427 | } \ | 427 | } \ |
428 | ret; \ | 428 | ret; \ |
429 | }) | 429 | }) |
430 | 430 | ||
431 | #define rsnd_mod_call(mod, func, rdai...) \ | 431 | #define rsnd_mod_call(mod, func, param...) \ |
432 | (!(mod) ? -ENODEV : \ | 432 | (!(mod) ? -ENODEV : \ |
433 | !((mod)->ops->func) ? 0 : \ | 433 | !((mod)->ops->func) ? 0 : \ |
434 | __rsnd_mod_call(mod, func, rdai)) | 434 | __rsnd_mod_call(mod, func, param)) |
435 | 435 | ||
436 | #define rsnd_dai_call(fn, io, rdai...) \ | 436 | #define rsnd_dai_call(fn, io, param...) \ |
437 | ({ \ | 437 | ({ \ |
438 | struct rsnd_mod *mod; \ | 438 | struct rsnd_mod *mod; \ |
439 | int ret = 0, i; \ | 439 | int ret = 0, i; \ |
@@ -441,7 +441,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) | |||
441 | mod = (io)->mod[i]; \ | 441 | mod = (io)->mod[i]; \ |
442 | if (!mod) \ | 442 | if (!mod) \ |
443 | continue; \ | 443 | continue; \ |
444 | ret = rsnd_mod_call(mod, fn, rdai); \ | 444 | ret = rsnd_mod_call(mod, fn, param); \ |
445 | if (ret < 0) \ | 445 | if (ret < 0) \ |
446 | break; \ | 446 | break; \ |
447 | } \ | 447 | } \ |
@@ -477,17 +477,7 @@ static void rsnd_dai_disconnect(struct rsnd_mod *mod, | |||
477 | io->mod[mod->type] = NULL; | 477 | io->mod[mod->type] = NULL; |
478 | } | 478 | } |
479 | 479 | ||
480 | int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) | 480 | struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id) |
481 | { | ||
482 | int id = rdai - priv->rdai; | ||
483 | |||
484 | if ((id < 0) || (id >= rsnd_rdai_nr(priv))) | ||
485 | return -EINVAL; | ||
486 | |||
487 | return id; | ||
488 | } | ||
489 | |||
490 | struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id) | ||
491 | { | 481 | { |
492 | if ((id < 0) || (id >= rsnd_rdai_nr(priv))) | 482 | if ((id < 0) || (id >= rsnd_rdai_nr(priv))) |
493 | return NULL; | 483 | return NULL; |
@@ -499,12 +489,7 @@ static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai) | |||
499 | { | 489 | { |
500 | struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai); | 490 | struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai); |
501 | 491 | ||
502 | return rsnd_dai_get(priv, dai->id); | 492 | return rsnd_rdai_get(priv, dai->id); |
503 | } | ||
504 | |||
505 | int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io) | ||
506 | { | ||
507 | return &rdai->playback == io; | ||
508 | } | 493 | } |
509 | 494 | ||
510 | /* | 495 | /* |
@@ -598,20 +583,20 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
598 | if (ret < 0) | 583 | if (ret < 0) |
599 | goto dai_trigger_end; | 584 | goto dai_trigger_end; |
600 | 585 | ||
601 | ret = rsnd_dai_call(init, io, rdai); | 586 | ret = rsnd_dai_call(init, io, priv); |
602 | if (ret < 0) | 587 | if (ret < 0) |
603 | goto dai_trigger_end; | 588 | goto dai_trigger_end; |
604 | 589 | ||
605 | ret = rsnd_dai_call(start, io, rdai); | 590 | ret = rsnd_dai_call(start, io, priv); |
606 | if (ret < 0) | 591 | if (ret < 0) |
607 | goto dai_trigger_end; | 592 | goto dai_trigger_end; |
608 | break; | 593 | break; |
609 | case SNDRV_PCM_TRIGGER_STOP: | 594 | case SNDRV_PCM_TRIGGER_STOP: |
610 | ret = rsnd_dai_call(stop, io, rdai); | 595 | ret = rsnd_dai_call(stop, io, priv); |
611 | if (ret < 0) | 596 | if (ret < 0) |
612 | goto dai_trigger_end; | 597 | goto dai_trigger_end; |
613 | 598 | ||
614 | ret = rsnd_dai_call(quit, io, rdai); | 599 | ret = rsnd_dai_call(quit, io, priv); |
615 | if (ret < 0) | 600 | if (ret < 0) |
616 | goto dai_trigger_end; | 601 | goto dai_trigger_end; |
617 | 602 | ||
@@ -873,15 +858,15 @@ static int rsnd_dai_probe(struct platform_device *pdev, | |||
873 | priv->rdai = rdai; | 858 | priv->rdai = rdai; |
874 | 859 | ||
875 | for (i = 0; i < dai_nr; i++) { | 860 | for (i = 0; i < dai_nr; i++) { |
876 | rdai[i].info = &info->dai_info[i]; | ||
877 | 861 | ||
878 | pmod = rdai[i].info->playback.ssi; | 862 | pmod = info->dai_info[i].playback.ssi; |
879 | cmod = rdai[i].info->capture.ssi; | 863 | cmod = info->dai_info[i].capture.ssi; |
880 | 864 | ||
881 | /* | 865 | /* |
882 | * init rsnd_dai | 866 | * init rsnd_dai |
883 | */ | 867 | */ |
884 | snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i); | 868 | snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i); |
869 | rdai[i].priv = priv; | ||
885 | 870 | ||
886 | /* | 871 | /* |
887 | * init snd_soc_dai_driver | 872 | * init snd_soc_dai_driver |
@@ -895,6 +880,7 @@ static int rsnd_dai_probe(struct platform_device *pdev, | |||
895 | drv[i].playback.channels_max = 2; | 880 | drv[i].playback.channels_max = 2; |
896 | 881 | ||
897 | rdai[i].playback.info = &info->dai_info[i].playback; | 882 | rdai[i].playback.info = &info->dai_info[i].playback; |
883 | rdai[i].playback.rdai = rdai + i; | ||
898 | rsnd_path_init(priv, &rdai[i], &rdai[i].playback); | 884 | rsnd_path_init(priv, &rdai[i], &rdai[i].playback); |
899 | } | 885 | } |
900 | if (cmod) { | 886 | if (cmod) { |
@@ -904,6 +890,7 @@ static int rsnd_dai_probe(struct platform_device *pdev, | |||
904 | drv[i].capture.channels_max = 2; | 890 | drv[i].capture.channels_max = 2; |
905 | 891 | ||
906 | rdai[i].capture.info = &info->dai_info[i].capture; | 892 | rdai[i].capture.info = &info->dai_info[i].capture; |
893 | rdai[i].capture.rdai = rdai + i; | ||
907 | rsnd_path_init(priv, &rdai[i], &rdai[i].capture); | 894 | rsnd_path_init(priv, &rdai[i], &rdai[i].capture); |
908 | } | 895 | } |
909 | 896 | ||
@@ -1037,7 +1024,6 @@ static int rsnd_kctrl_put(struct snd_kcontrol *kctrl, | |||
1037 | } | 1024 | } |
1038 | 1025 | ||
1039 | static int __rsnd_kctrl_new(struct rsnd_mod *mod, | 1026 | static int __rsnd_kctrl_new(struct rsnd_mod *mod, |
1040 | struct rsnd_dai *rdai, | ||
1041 | struct snd_soc_pcm_runtime *rtd, | 1027 | struct snd_soc_pcm_runtime *rtd, |
1042 | const unsigned char *name, | 1028 | const unsigned char *name, |
1043 | struct rsnd_kctrl_cfg *cfg, | 1029 | struct rsnd_kctrl_cfg *cfg, |
@@ -1060,16 +1046,24 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod, | |||
1060 | return -ENOMEM; | 1046 | return -ENOMEM; |
1061 | 1047 | ||
1062 | ret = snd_ctl_add(card, kctrl); | 1048 | ret = snd_ctl_add(card, kctrl); |
1063 | if (ret < 0) | 1049 | if (ret < 0) { |
1050 | snd_ctl_free_one(kctrl); | ||
1064 | return ret; | 1051 | return ret; |
1052 | } | ||
1065 | 1053 | ||
1066 | cfg->update = update; | 1054 | cfg->update = update; |
1055 | cfg->card = card; | ||
1056 | cfg->kctrl = kctrl; | ||
1067 | 1057 | ||
1068 | return 0; | 1058 | return 0; |
1069 | } | 1059 | } |
1070 | 1060 | ||
1061 | void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg) | ||
1062 | { | ||
1063 | snd_ctl_remove(cfg->card, cfg->kctrl); | ||
1064 | } | ||
1065 | |||
1071 | int rsnd_kctrl_new_m(struct rsnd_mod *mod, | 1066 | int rsnd_kctrl_new_m(struct rsnd_mod *mod, |
1072 | struct rsnd_dai *rdai, | ||
1073 | struct snd_soc_pcm_runtime *rtd, | 1067 | struct snd_soc_pcm_runtime *rtd, |
1074 | const unsigned char *name, | 1068 | const unsigned char *name, |
1075 | void (*update)(struct rsnd_mod *mod), | 1069 | void (*update)(struct rsnd_mod *mod), |
@@ -1079,11 +1073,10 @@ int rsnd_kctrl_new_m(struct rsnd_mod *mod, | |||
1079 | _cfg->cfg.max = max; | 1073 | _cfg->cfg.max = max; |
1080 | _cfg->cfg.size = RSND_DVC_CHANNELS; | 1074 | _cfg->cfg.size = RSND_DVC_CHANNELS; |
1081 | _cfg->cfg.val = _cfg->val; | 1075 | _cfg->cfg.val = _cfg->val; |
1082 | return __rsnd_kctrl_new(mod, rdai, rtd, name, &_cfg->cfg, update); | 1076 | return __rsnd_kctrl_new(mod, rtd, name, &_cfg->cfg, update); |
1083 | } | 1077 | } |
1084 | 1078 | ||
1085 | int rsnd_kctrl_new_s(struct rsnd_mod *mod, | 1079 | int rsnd_kctrl_new_s(struct rsnd_mod *mod, |
1086 | struct rsnd_dai *rdai, | ||
1087 | struct snd_soc_pcm_runtime *rtd, | 1080 | struct snd_soc_pcm_runtime *rtd, |
1088 | const unsigned char *name, | 1081 | const unsigned char *name, |
1089 | void (*update)(struct rsnd_mod *mod), | 1082 | void (*update)(struct rsnd_mod *mod), |
@@ -1093,11 +1086,10 @@ int rsnd_kctrl_new_s(struct rsnd_mod *mod, | |||
1093 | _cfg->cfg.max = max; | 1086 | _cfg->cfg.max = max; |
1094 | _cfg->cfg.size = 1; | 1087 | _cfg->cfg.size = 1; |
1095 | _cfg->cfg.val = &_cfg->val; | 1088 | _cfg->cfg.val = &_cfg->val; |
1096 | return __rsnd_kctrl_new(mod, rdai, rtd, name, &_cfg->cfg, update); | 1089 | return __rsnd_kctrl_new(mod, rtd, name, &_cfg->cfg, update); |
1097 | } | 1090 | } |
1098 | 1091 | ||
1099 | int rsnd_kctrl_new_e(struct rsnd_mod *mod, | 1092 | int rsnd_kctrl_new_e(struct rsnd_mod *mod, |
1100 | struct rsnd_dai *rdai, | ||
1101 | struct snd_soc_pcm_runtime *rtd, | 1093 | struct snd_soc_pcm_runtime *rtd, |
1102 | const unsigned char *name, | 1094 | const unsigned char *name, |
1103 | struct rsnd_kctrl_cfg_s *_cfg, | 1095 | struct rsnd_kctrl_cfg_s *_cfg, |
@@ -1109,7 +1101,7 @@ int rsnd_kctrl_new_e(struct rsnd_mod *mod, | |||
1109 | _cfg->cfg.size = 1; | 1101 | _cfg->cfg.size = 1; |
1110 | _cfg->cfg.val = &_cfg->val; | 1102 | _cfg->cfg.val = &_cfg->val; |
1111 | _cfg->cfg.texts = texts; | 1103 | _cfg->cfg.texts = texts; |
1112 | return __rsnd_kctrl_new(mod, rdai, rtd, name, &_cfg->cfg, update); | 1104 | return __rsnd_kctrl_new(mod, rtd, name, &_cfg->cfg, update); |
1113 | } | 1105 | } |
1114 | 1106 | ||
1115 | /* | 1107 | /* |
@@ -1125,11 +1117,11 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
1125 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | 1117 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
1126 | int ret; | 1118 | int ret; |
1127 | 1119 | ||
1128 | ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd); | 1120 | ret = rsnd_dai_call(pcm_new, &rdai->playback, rtd); |
1129 | if (ret) | 1121 | if (ret) |
1130 | return ret; | 1122 | return ret; |
1131 | 1123 | ||
1132 | ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd); | 1124 | ret = rsnd_dai_call(pcm_new, &rdai->capture, rtd); |
1133 | if (ret) | 1125 | if (ret) |
1134 | return ret; | 1126 | return ret; |
1135 | 1127 | ||
@@ -1140,15 +1132,9 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
1140 | PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); | 1132 | PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); |
1141 | } | 1133 | } |
1142 | 1134 | ||
1143 | static void rsnd_pcm_free(struct snd_pcm *pcm) | ||
1144 | { | ||
1145 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
1146 | } | ||
1147 | |||
1148 | static struct snd_soc_platform_driver rsnd_soc_platform = { | 1135 | static struct snd_soc_platform_driver rsnd_soc_platform = { |
1149 | .ops = &rsnd_pcm_ops, | 1136 | .ops = &rsnd_pcm_ops, |
1150 | .pcm_new = rsnd_pcm_new, | 1137 | .pcm_new = rsnd_pcm_new, |
1151 | .pcm_free = rsnd_pcm_free, | ||
1152 | }; | 1138 | }; |
1153 | 1139 | ||
1154 | static const struct snd_soc_component_driver rsnd_soc_component = { | 1140 | static const struct snd_soc_component_driver rsnd_soc_component = { |
@@ -1156,13 +1142,11 @@ static const struct snd_soc_component_driver rsnd_soc_component = { | |||
1156 | }; | 1142 | }; |
1157 | 1143 | ||
1158 | static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv, | 1144 | static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv, |
1159 | struct rsnd_dai *rdai, | 1145 | struct rsnd_dai_stream *io) |
1160 | int is_play) | ||
1161 | { | 1146 | { |
1162 | struct rsnd_dai_stream *io = is_play ? &rdai->playback : &rdai->capture; | ||
1163 | int ret; | 1147 | int ret; |
1164 | 1148 | ||
1165 | ret = rsnd_dai_call(probe, io, rdai); | 1149 | ret = rsnd_dai_call(probe, io, priv); |
1166 | if (ret == -EAGAIN) { | 1150 | if (ret == -EAGAIN) { |
1167 | /* | 1151 | /* |
1168 | * Fallback to PIO mode | 1152 | * Fallback to PIO mode |
@@ -1175,7 +1159,7 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv, | |||
1175 | * rsnd_dma_init() | 1159 | * rsnd_dma_init() |
1176 | * rsnd_ssi_fallback() | 1160 | * rsnd_ssi_fallback() |
1177 | */ | 1161 | */ |
1178 | rsnd_dai_call(remove, io, rdai); | 1162 | rsnd_dai_call(remove, io, priv); |
1179 | 1163 | ||
1180 | /* | 1164 | /* |
1181 | * remove SRC/DVC from DAI, | 1165 | * remove SRC/DVC from DAI, |
@@ -1186,13 +1170,13 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv, | |||
1186 | /* | 1170 | /* |
1187 | * fallback | 1171 | * fallback |
1188 | */ | 1172 | */ |
1189 | rsnd_dai_call(fallback, io, rdai); | 1173 | rsnd_dai_call(fallback, io, priv); |
1190 | 1174 | ||
1191 | /* | 1175 | /* |
1192 | * retry to "probe". | 1176 | * retry to "probe". |
1193 | * DAI has SSI which is PIO mode only now. | 1177 | * DAI has SSI which is PIO mode only now. |
1194 | */ | 1178 | */ |
1195 | ret = rsnd_dai_call(probe, io, rdai); | 1179 | ret = rsnd_dai_call(probe, io, priv); |
1196 | } | 1180 | } |
1197 | 1181 | ||
1198 | return ret; | 1182 | return ret; |
@@ -1259,15 +1243,17 @@ static int rsnd_probe(struct platform_device *pdev) | |||
1259 | } | 1243 | } |
1260 | 1244 | ||
1261 | for_each_rsnd_dai(rdai, priv, i) { | 1245 | for_each_rsnd_dai(rdai, priv, i) { |
1262 | ret = rsnd_rdai_continuance_probe(priv, rdai, 1); | 1246 | ret = rsnd_rdai_continuance_probe(priv, &rdai->playback); |
1263 | if (ret) | 1247 | if (ret) |
1264 | goto exit_snd_probe; | 1248 | goto exit_snd_probe; |
1265 | 1249 | ||
1266 | ret = rsnd_rdai_continuance_probe(priv, rdai, 0); | 1250 | ret = rsnd_rdai_continuance_probe(priv, &rdai->capture); |
1267 | if (ret) | 1251 | if (ret) |
1268 | goto exit_snd_probe; | 1252 | goto exit_snd_probe; |
1269 | } | 1253 | } |
1270 | 1254 | ||
1255 | dev_set_drvdata(dev, priv); | ||
1256 | |||
1271 | /* | 1257 | /* |
1272 | * asoc register | 1258 | * asoc register |
1273 | */ | 1259 | */ |
@@ -1284,8 +1270,6 @@ static int rsnd_probe(struct platform_device *pdev) | |||
1284 | goto exit_snd_soc; | 1270 | goto exit_snd_soc; |
1285 | } | 1271 | } |
1286 | 1272 | ||
1287 | dev_set_drvdata(dev, priv); | ||
1288 | |||
1289 | pm_runtime_enable(dev); | 1273 | pm_runtime_enable(dev); |
1290 | 1274 | ||
1291 | dev_info(dev, "probed\n"); | 1275 | dev_info(dev, "probed\n"); |
@@ -1295,8 +1279,8 @@ exit_snd_soc: | |||
1295 | snd_soc_unregister_platform(dev); | 1279 | snd_soc_unregister_platform(dev); |
1296 | exit_snd_probe: | 1280 | exit_snd_probe: |
1297 | for_each_rsnd_dai(rdai, priv, i) { | 1281 | for_each_rsnd_dai(rdai, priv, i) { |
1298 | rsnd_dai_call(remove, &rdai->playback, rdai); | 1282 | rsnd_dai_call(remove, &rdai->playback, priv); |
1299 | rsnd_dai_call(remove, &rdai->capture, rdai); | 1283 | rsnd_dai_call(remove, &rdai->capture, priv); |
1300 | } | 1284 | } |
1301 | 1285 | ||
1302 | return ret; | 1286 | return ret; |
@@ -1311,10 +1295,13 @@ static int rsnd_remove(struct platform_device *pdev) | |||
1311 | pm_runtime_disable(&pdev->dev); | 1295 | pm_runtime_disable(&pdev->dev); |
1312 | 1296 | ||
1313 | for_each_rsnd_dai(rdai, priv, i) { | 1297 | for_each_rsnd_dai(rdai, priv, i) { |
1314 | ret |= rsnd_dai_call(remove, &rdai->playback, rdai); | 1298 | ret |= rsnd_dai_call(remove, &rdai->playback, priv); |
1315 | ret |= rsnd_dai_call(remove, &rdai->capture, rdai); | 1299 | ret |= rsnd_dai_call(remove, &rdai->capture, priv); |
1316 | } | 1300 | } |
1317 | 1301 | ||
1302 | snd_soc_unregister_component(&pdev->dev); | ||
1303 | snd_soc_unregister_platform(&pdev->dev); | ||
1304 | |||
1318 | return ret; | 1305 | return ret; |
1319 | } | 1306 | } |
1320 | 1307 | ||
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index 5380a4827ba7..d7f9ed959c4e 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c | |||
@@ -17,7 +17,6 @@ | |||
17 | struct rsnd_dvc { | 17 | struct rsnd_dvc { |
18 | struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ | 18 | struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ |
19 | struct rsnd_mod mod; | 19 | struct rsnd_mod mod; |
20 | struct clk *clk; | ||
21 | struct rsnd_kctrl_cfg_m volume; | 20 | struct rsnd_kctrl_cfg_m volume; |
22 | struct rsnd_kctrl_cfg_m mute; | 21 | struct rsnd_kctrl_cfg_m mute; |
23 | struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */ | 22 | struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */ |
@@ -118,9 +117,8 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod) | |||
118 | } | 117 | } |
119 | 118 | ||
120 | static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, | 119 | static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, |
121 | struct rsnd_dai *rdai) | 120 | struct rsnd_priv *priv) |
122 | { | 121 | { |
123 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
124 | struct device *dev = rsnd_priv_to_dev(priv); | 122 | struct device *dev = rsnd_priv_to_dev(priv); |
125 | 123 | ||
126 | dev_dbg(dev, "%s[%d] (Gen2) is probed\n", | 124 | dev_dbg(dev, "%s[%d] (Gen2) is probed\n", |
@@ -129,12 +127,24 @@ static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, | |||
129 | return 0; | 127 | return 0; |
130 | } | 128 | } |
131 | 129 | ||
130 | static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod, | ||
131 | struct rsnd_priv *priv) | ||
132 | { | ||
133 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
134 | |||
135 | rsnd_kctrl_remove(dvc->volume); | ||
136 | rsnd_kctrl_remove(dvc->mute); | ||
137 | rsnd_kctrl_remove(dvc->ren); | ||
138 | rsnd_kctrl_remove(dvc->rup); | ||
139 | rsnd_kctrl_remove(dvc->rdown); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
132 | static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, | 144 | static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, |
133 | struct rsnd_dai *rdai) | 145 | struct rsnd_priv *priv) |
134 | { | 146 | { |
135 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(dvc_mod); | ||
136 | struct rsnd_dai_stream *io = rsnd_mod_to_io(dvc_mod); | 147 | struct rsnd_dai_stream *io = rsnd_mod_to_io(dvc_mod); |
137 | struct rsnd_priv *priv = rsnd_mod_to_priv(dvc_mod); | ||
138 | struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); | 148 | struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); |
139 | struct device *dev = rsnd_priv_to_dev(priv); | 149 | struct device *dev = rsnd_priv_to_dev(priv); |
140 | int dvc_id = rsnd_mod_id(dvc_mod); | 150 | int dvc_id = rsnd_mod_id(dvc_mod); |
@@ -153,7 +163,7 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, | |||
153 | return -EINVAL; | 163 | return -EINVAL; |
154 | } | 164 | } |
155 | 165 | ||
156 | clk_prepare_enable(dvc->clk); | 166 | rsnd_mod_hw_start(dvc_mod); |
157 | 167 | ||
158 | /* | 168 | /* |
159 | * fixme | 169 | * fixme |
@@ -173,23 +183,21 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, | |||
173 | 183 | ||
174 | rsnd_mod_write(dvc_mod, DVC_DVUIR, 0); | 184 | rsnd_mod_write(dvc_mod, DVC_DVUIR, 0); |
175 | 185 | ||
176 | rsnd_adg_set_cmd_timsel_gen2(rdai, dvc_mod, io); | 186 | rsnd_adg_set_cmd_timsel_gen2(dvc_mod, io); |
177 | 187 | ||
178 | return 0; | 188 | return 0; |
179 | } | 189 | } |
180 | 190 | ||
181 | static int rsnd_dvc_quit(struct rsnd_mod *mod, | 191 | static int rsnd_dvc_quit(struct rsnd_mod *mod, |
182 | struct rsnd_dai *rdai) | 192 | struct rsnd_priv *priv) |
183 | { | 193 | { |
184 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 194 | rsnd_mod_hw_stop(mod); |
185 | |||
186 | clk_disable_unprepare(dvc->clk); | ||
187 | 195 | ||
188 | return 0; | 196 | return 0; |
189 | } | 197 | } |
190 | 198 | ||
191 | static int rsnd_dvc_start(struct rsnd_mod *mod, | 199 | static int rsnd_dvc_start(struct rsnd_mod *mod, |
192 | struct rsnd_dai *rdai) | 200 | struct rsnd_priv *priv) |
193 | { | 201 | { |
194 | rsnd_mod_write(mod, CMD_CTRL, 0x10); | 202 | rsnd_mod_write(mod, CMD_CTRL, 0x10); |
195 | 203 | ||
@@ -197,7 +205,7 @@ static int rsnd_dvc_start(struct rsnd_mod *mod, | |||
197 | } | 205 | } |
198 | 206 | ||
199 | static int rsnd_dvc_stop(struct rsnd_mod *mod, | 207 | static int rsnd_dvc_stop(struct rsnd_mod *mod, |
200 | struct rsnd_dai *rdai) | 208 | struct rsnd_priv *priv) |
201 | { | 209 | { |
202 | rsnd_mod_write(mod, CMD_CTRL, 0); | 210 | rsnd_mod_write(mod, CMD_CTRL, 0); |
203 | 211 | ||
@@ -205,16 +213,16 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod, | |||
205 | } | 213 | } |
206 | 214 | ||
207 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | 215 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, |
208 | struct rsnd_dai *rdai, | ||
209 | struct snd_soc_pcm_runtime *rtd) | 216 | struct snd_soc_pcm_runtime *rtd) |
210 | { | 217 | { |
211 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 218 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
212 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 219 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); |
220 | int is_play = rsnd_io_is_play(io); | ||
213 | int ret; | 221 | int ret; |
214 | 222 | ||
215 | /* Volume */ | 223 | /* Volume */ |
216 | ret = rsnd_kctrl_new_m(mod, rdai, rtd, | 224 | ret = rsnd_kctrl_new_m(mod, rtd, |
217 | rsnd_dai_is_play(rdai, io) ? | 225 | is_play ? |
218 | "DVC Out Playback Volume" : "DVC In Capture Volume", | 226 | "DVC Out Playback Volume" : "DVC In Capture Volume", |
219 | rsnd_dvc_volume_update, | 227 | rsnd_dvc_volume_update, |
220 | &dvc->volume, 0x00800000 - 1); | 228 | &dvc->volume, 0x00800000 - 1); |
@@ -222,8 +230,8 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
222 | return ret; | 230 | return ret; |
223 | 231 | ||
224 | /* Mute */ | 232 | /* Mute */ |
225 | ret = rsnd_kctrl_new_m(mod, rdai, rtd, | 233 | ret = rsnd_kctrl_new_m(mod, rtd, |
226 | rsnd_dai_is_play(rdai, io) ? | 234 | is_play ? |
227 | "DVC Out Mute Switch" : "DVC In Mute Switch", | 235 | "DVC Out Mute Switch" : "DVC In Mute Switch", |
228 | rsnd_dvc_volume_update, | 236 | rsnd_dvc_volume_update, |
229 | &dvc->mute, 1); | 237 | &dvc->mute, 1); |
@@ -231,16 +239,16 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
231 | return ret; | 239 | return ret; |
232 | 240 | ||
233 | /* Ramp */ | 241 | /* Ramp */ |
234 | ret = rsnd_kctrl_new_s(mod, rdai, rtd, | 242 | ret = rsnd_kctrl_new_s(mod, rtd, |
235 | rsnd_dai_is_play(rdai, io) ? | 243 | is_play ? |
236 | "DVC Out Ramp Switch" : "DVC In Ramp Switch", | 244 | "DVC Out Ramp Switch" : "DVC In Ramp Switch", |
237 | rsnd_dvc_volume_update, | 245 | rsnd_dvc_volume_update, |
238 | &dvc->ren, 1); | 246 | &dvc->ren, 1); |
239 | if (ret < 0) | 247 | if (ret < 0) |
240 | return ret; | 248 | return ret; |
241 | 249 | ||
242 | ret = rsnd_kctrl_new_e(mod, rdai, rtd, | 250 | ret = rsnd_kctrl_new_e(mod, rtd, |
243 | rsnd_dai_is_play(rdai, io) ? | 251 | is_play ? |
244 | "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate", | 252 | "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate", |
245 | &dvc->rup, | 253 | &dvc->rup, |
246 | rsnd_dvc_volume_update, | 254 | rsnd_dvc_volume_update, |
@@ -248,8 +256,8 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
248 | if (ret < 0) | 256 | if (ret < 0) |
249 | return ret; | 257 | return ret; |
250 | 258 | ||
251 | ret = rsnd_kctrl_new_e(mod, rdai, rtd, | 259 | ret = rsnd_kctrl_new_e(mod, rtd, |
252 | rsnd_dai_is_play(rdai, io) ? | 260 | is_play ? |
253 | "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate", | 261 | "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate", |
254 | &dvc->rdown, | 262 | &dvc->rdown, |
255 | rsnd_dvc_volume_update, | 263 | rsnd_dvc_volume_update, |
@@ -264,6 +272,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
264 | static struct rsnd_mod_ops rsnd_dvc_ops = { | 272 | static struct rsnd_mod_ops rsnd_dvc_ops = { |
265 | .name = DVC_NAME, | 273 | .name = DVC_NAME, |
266 | .probe = rsnd_dvc_probe_gen2, | 274 | .probe = rsnd_dvc_probe_gen2, |
275 | .remove = rsnd_dvc_remove_gen2, | ||
267 | .init = rsnd_dvc_init, | 276 | .init = rsnd_dvc_init, |
268 | .quit = rsnd_dvc_quit, | 277 | .quit = rsnd_dvc_quit, |
269 | .start = rsnd_dvc_start, | 278 | .start = rsnd_dvc_start, |
@@ -356,9 +365,9 @@ int rsnd_dvc_probe(struct platform_device *pdev, | |||
356 | return PTR_ERR(clk); | 365 | return PTR_ERR(clk); |
357 | 366 | ||
358 | dvc->info = &info->dvc_info[i]; | 367 | dvc->info = &info->dvc_info[i]; |
359 | dvc->clk = clk; | ||
360 | 368 | ||
361 | rsnd_mod_init(priv, &dvc->mod, &rsnd_dvc_ops, RSND_MOD_DVC, i); | 369 | rsnd_mod_init(&dvc->mod, &rsnd_dvc_ops, |
370 | clk, RSND_MOD_DVC, i); | ||
362 | 371 | ||
363 | dev_dbg(dev, "CMD%d probed\n", i); | 372 | dev_dbg(dev, "CMD%d probed\n", i); |
364 | } | 373 | } |
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 87a6f2d62775..de0685f2abae 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c | |||
@@ -309,8 +309,13 @@ static int rsnd_gen2_probe(struct platform_device *pdev, | |||
309 | RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20), | 309 | RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20), |
310 | RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), | 310 | RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), |
311 | RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), | 311 | RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), |
312 | RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20), | ||
312 | RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20), | 313 | RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20), |
313 | RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20), | 314 | RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20), |
315 | RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8), | ||
316 | RSND_GEN_S_REG(SCU_SYS_INT_EN0, 0x1cc), | ||
317 | RSND_GEN_S_REG(SCU_SYS_STATUS1, 0x1d0), | ||
318 | RSND_GEN_S_REG(SCU_SYS_INT_EN1, 0x1c4), | ||
314 | RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), | 319 | RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), |
315 | RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), | 320 | RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), |
316 | RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), | 321 | RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), |
@@ -403,6 +408,16 @@ static int rsnd_gen1_probe(struct platform_device *pdev, | |||
403 | RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), | 408 | RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), |
404 | RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), | 409 | RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), |
405 | RSND_GEN_M_REG(SRC_MNFSR, 0x228, 0x40), | 410 | RSND_GEN_M_REG(SRC_MNFSR, 0x228, 0x40), |
411 | /* | ||
412 | * ADD US | ||
413 | * | ||
414 | * SRC_STATUS | ||
415 | * SRC_INT_EN | ||
416 | * SCU_SYS_STATUS0 | ||
417 | * SCU_SYS_STATUS1 | ||
418 | * SCU_SYS_INT_EN0 | ||
419 | * SCU_SYS_INT_EN1 | ||
420 | */ | ||
406 | }; | 421 | }; |
407 | struct rsnd_regmap_field_conf conf_adg[] = { | 422 | struct rsnd_regmap_field_conf conf_adg[] = { |
408 | RSND_GEN_S_REG(BRRA, 0x00), | 423 | RSND_GEN_S_REG(BRRA, 0x00), |
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 5826c8abf794..e7914bd610e2 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -44,6 +44,8 @@ enum rsnd_reg { | |||
44 | RSND_REG_SRC_IFSCR, | 44 | RSND_REG_SRC_IFSCR, |
45 | RSND_REG_SRC_IFSVR, | 45 | RSND_REG_SRC_IFSVR, |
46 | RSND_REG_SRC_SRCCR, | 46 | RSND_REG_SRC_SRCCR, |
47 | RSND_REG_SCU_SYS_STATUS0, | ||
48 | RSND_REG_SCU_SYS_INT_EN0, | ||
47 | RSND_REG_CMD_ROUTE_SLCT, | 49 | RSND_REG_CMD_ROUTE_SLCT, |
48 | RSND_REG_DVC_SWRSR, | 50 | RSND_REG_DVC_SWRSR, |
49 | RSND_REG_DVC_DVUIR, | 51 | RSND_REG_DVC_DVUIR, |
@@ -94,6 +96,9 @@ enum rsnd_reg { | |||
94 | RSND_REG_SHARE23, | 96 | RSND_REG_SHARE23, |
95 | RSND_REG_SHARE24, | 97 | RSND_REG_SHARE24, |
96 | RSND_REG_SHARE25, | 98 | RSND_REG_SHARE25, |
99 | RSND_REG_SHARE26, | ||
100 | RSND_REG_SHARE27, | ||
101 | RSND_REG_SHARE28, | ||
97 | 102 | ||
98 | RSND_REG_MAX, | 103 | RSND_REG_MAX, |
99 | }; | 104 | }; |
@@ -135,6 +140,9 @@ enum rsnd_reg { | |||
135 | #define RSND_REG_DVC_VRCTR RSND_REG_SHARE23 | 140 | #define RSND_REG_DVC_VRCTR RSND_REG_SHARE23 |
136 | #define RSND_REG_DVC_VRPDR RSND_REG_SHARE24 | 141 | #define RSND_REG_DVC_VRPDR RSND_REG_SHARE24 |
137 | #define RSND_REG_DVC_VRDBR RSND_REG_SHARE25 | 142 | #define RSND_REG_DVC_VRDBR RSND_REG_SHARE25 |
143 | #define RSND_REG_SCU_SYS_STATUS1 RSND_REG_SHARE26 | ||
144 | #define RSND_REG_SCU_SYS_INT_EN1 RSND_REG_SHARE27 | ||
145 | #define RSND_REG_SRC_INT_ENABLE0 RSND_REG_SHARE28 | ||
138 | 146 | ||
139 | struct rsnd_of_data; | 147 | struct rsnd_of_data; |
140 | struct rsnd_priv; | 148 | struct rsnd_priv; |
@@ -182,9 +190,9 @@ void rsnd_dma_quit(struct rsnd_priv *priv, | |||
182 | * R-Car sound mod | 190 | * R-Car sound mod |
183 | */ | 191 | */ |
184 | enum rsnd_mod_type { | 192 | enum rsnd_mod_type { |
185 | RSND_MOD_SRC = 0, | 193 | RSND_MOD_DVC = 0, |
194 | RSND_MOD_SRC, | ||
186 | RSND_MOD_SSI, | 195 | RSND_MOD_SSI, |
187 | RSND_MOD_DVC, | ||
188 | RSND_MOD_MAX, | 196 | RSND_MOD_MAX, |
189 | }; | 197 | }; |
190 | 198 | ||
@@ -192,32 +200,31 @@ struct rsnd_mod_ops { | |||
192 | char *name; | 200 | char *name; |
193 | char* (*dma_name)(struct rsnd_mod *mod); | 201 | char* (*dma_name)(struct rsnd_mod *mod); |
194 | int (*probe)(struct rsnd_mod *mod, | 202 | int (*probe)(struct rsnd_mod *mod, |
195 | struct rsnd_dai *rdai); | 203 | struct rsnd_priv *priv); |
196 | int (*remove)(struct rsnd_mod *mod, | 204 | int (*remove)(struct rsnd_mod *mod, |
197 | struct rsnd_dai *rdai); | 205 | struct rsnd_priv *priv); |
198 | int (*init)(struct rsnd_mod *mod, | 206 | int (*init)(struct rsnd_mod *mod, |
199 | struct rsnd_dai *rdai); | 207 | struct rsnd_priv *priv); |
200 | int (*quit)(struct rsnd_mod *mod, | 208 | int (*quit)(struct rsnd_mod *mod, |
201 | struct rsnd_dai *rdai); | 209 | struct rsnd_priv *priv); |
202 | int (*start)(struct rsnd_mod *mod, | 210 | int (*start)(struct rsnd_mod *mod, |
203 | struct rsnd_dai *rdai); | 211 | struct rsnd_priv *priv); |
204 | int (*stop)(struct rsnd_mod *mod, | 212 | int (*stop)(struct rsnd_mod *mod, |
205 | struct rsnd_dai *rdai); | 213 | struct rsnd_priv *priv); |
206 | int (*pcm_new)(struct rsnd_mod *mod, | 214 | int (*pcm_new)(struct rsnd_mod *mod, |
207 | struct rsnd_dai *rdai, | ||
208 | struct snd_soc_pcm_runtime *rtd); | 215 | struct snd_soc_pcm_runtime *rtd); |
209 | int (*fallback)(struct rsnd_mod *mod, | 216 | int (*fallback)(struct rsnd_mod *mod, |
210 | struct rsnd_dai *rdai); | 217 | struct rsnd_priv *priv); |
211 | }; | 218 | }; |
212 | 219 | ||
213 | struct rsnd_dai_stream; | 220 | struct rsnd_dai_stream; |
214 | struct rsnd_mod { | 221 | struct rsnd_mod { |
215 | int id; | 222 | int id; |
216 | enum rsnd_mod_type type; | 223 | enum rsnd_mod_type type; |
217 | struct rsnd_priv *priv; | ||
218 | struct rsnd_mod_ops *ops; | 224 | struct rsnd_mod_ops *ops; |
219 | struct rsnd_dma dma; | 225 | struct rsnd_dma dma; |
220 | struct rsnd_dai_stream *io; | 226 | struct rsnd_dai_stream *io; |
227 | struct clk *clk; | ||
221 | u32 status; | 228 | u32 status; |
222 | }; | 229 | }; |
223 | /* | 230 | /* |
@@ -248,15 +255,17 @@ struct rsnd_mod { | |||
248 | #define __rsnd_mod_call_pcm_new 0 | 255 | #define __rsnd_mod_call_pcm_new 0 |
249 | #define __rsnd_mod_call_fallback 0 | 256 | #define __rsnd_mod_call_fallback 0 |
250 | 257 | ||
251 | #define rsnd_mod_to_priv(mod) ((mod)->priv) | 258 | #define rsnd_mod_to_priv(mod) (rsnd_io_to_priv(rsnd_mod_to_io(mod))) |
252 | #define rsnd_mod_to_dma(mod) (&(mod)->dma) | 259 | #define rsnd_mod_to_dma(mod) (&(mod)->dma) |
253 | #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) | 260 | #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) |
254 | #define rsnd_mod_to_io(mod) ((mod)->io) | 261 | #define rsnd_mod_to_io(mod) ((mod)->io) |
255 | #define rsnd_mod_id(mod) ((mod)->id) | 262 | #define rsnd_mod_id(mod) ((mod)->id) |
263 | #define rsnd_mod_hw_start(mod) clk_prepare_enable((mod)->clk) | ||
264 | #define rsnd_mod_hw_stop(mod) clk_disable_unprepare((mod)->clk) | ||
256 | 265 | ||
257 | void rsnd_mod_init(struct rsnd_priv *priv, | 266 | void rsnd_mod_init(struct rsnd_mod *mod, |
258 | struct rsnd_mod *mod, | ||
259 | struct rsnd_mod_ops *ops, | 267 | struct rsnd_mod_ops *ops, |
268 | struct clk *clk, | ||
260 | enum rsnd_mod_type type, | 269 | enum rsnd_mod_type type, |
261 | int id); | 270 | int id); |
262 | char *rsnd_mod_name(struct rsnd_mod *mod); | 271 | char *rsnd_mod_name(struct rsnd_mod *mod); |
@@ -270,6 +279,7 @@ struct rsnd_dai_stream { | |||
270 | struct snd_pcm_substream *substream; | 279 | struct snd_pcm_substream *substream; |
271 | struct rsnd_mod *mod[RSND_MOD_MAX]; | 280 | struct rsnd_mod *mod[RSND_MOD_MAX]; |
272 | struct rsnd_dai_path_info *info; /* rcar_snd.h */ | 281 | struct rsnd_dai_path_info *info; /* rcar_snd.h */ |
282 | struct rsnd_dai *rdai; | ||
273 | int byte_pos; | 283 | int byte_pos; |
274 | int period_pos; | 284 | int period_pos; |
275 | int byte_per_period; | 285 | int byte_per_period; |
@@ -278,12 +288,18 @@ struct rsnd_dai_stream { | |||
278 | #define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) | 288 | #define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) |
279 | #define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC]) | 289 | #define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC]) |
280 | #define rsnd_io_to_mod_dvc(io) ((io)->mod[RSND_MOD_DVC]) | 290 | #define rsnd_io_to_mod_dvc(io) ((io)->mod[RSND_MOD_DVC]) |
291 | #define rsnd_io_to_rdai(io) ((io)->rdai) | ||
292 | #define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io))) | ||
293 | #define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io) | ||
294 | #define rsnd_io_to_runtime(io) ((io)->substream ? \ | ||
295 | (io)->substream->runtime : NULL) | ||
296 | |||
281 | 297 | ||
282 | struct rsnd_dai { | 298 | struct rsnd_dai { |
283 | char name[RSND_DAI_NAME_SIZE]; | 299 | char name[RSND_DAI_NAME_SIZE]; |
284 | struct rsnd_dai_platform_info *info; /* rcar_snd.h */ | ||
285 | struct rsnd_dai_stream playback; | 300 | struct rsnd_dai_stream playback; |
286 | struct rsnd_dai_stream capture; | 301 | struct rsnd_dai_stream capture; |
302 | struct rsnd_priv *priv; | ||
287 | 303 | ||
288 | unsigned int clk_master:1; | 304 | unsigned int clk_master:1; |
289 | unsigned int bit_clk_inv:1; | 305 | unsigned int bit_clk_inv:1; |
@@ -293,22 +309,18 @@ struct rsnd_dai { | |||
293 | }; | 309 | }; |
294 | 310 | ||
295 | #define rsnd_rdai_nr(priv) ((priv)->rdai_nr) | 311 | #define rsnd_rdai_nr(priv) ((priv)->rdai_nr) |
312 | #define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master) | ||
313 | #define rsnd_rdai_to_priv(rdai) ((rdai)->priv) | ||
296 | #define for_each_rsnd_dai(rdai, priv, i) \ | 314 | #define for_each_rsnd_dai(rdai, priv, i) \ |
297 | for (i = 0; \ | 315 | for (i = 0; \ |
298 | (i < rsnd_rdai_nr(priv)) && \ | 316 | (i < rsnd_rdai_nr(priv)) && \ |
299 | ((rdai) = rsnd_dai_get(priv, i)); \ | 317 | ((rdai) = rsnd_rdai_get(priv, i)); \ |
300 | i++) | 318 | i++) |
301 | 319 | ||
302 | struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); | 320 | struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id); |
303 | int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io); | ||
304 | int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); | ||
305 | #define rsnd_dai_get_platform_info(rdai) ((rdai)->info) | ||
306 | #define rsnd_io_to_runtime(io) ((io)->substream ? \ | ||
307 | (io)->substream->runtime : NULL) | ||
308 | 321 | ||
309 | void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); | 322 | void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); |
310 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); | 323 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); |
311 | #define rsnd_dai_is_clk_master(rdai) ((rdai)->clk_master) | ||
312 | 324 | ||
313 | /* | 325 | /* |
314 | * R-Car Gen1/Gen2 | 326 | * R-Car Gen1/Gen2 |
@@ -339,15 +351,12 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, | |||
339 | unsigned int src_rate, | 351 | unsigned int src_rate, |
340 | unsigned int dst_rate); | 352 | unsigned int dst_rate); |
341 | int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, | 353 | int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, |
342 | struct rsnd_dai *rdai, | ||
343 | struct rsnd_dai_stream *io, | 354 | struct rsnd_dai_stream *io, |
344 | unsigned int src_rate, | 355 | unsigned int src_rate, |
345 | unsigned int dst_rate); | 356 | unsigned int dst_rate); |
346 | int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, | 357 | int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, |
347 | struct rsnd_dai *rdai, | ||
348 | struct rsnd_dai_stream *io); | 358 | struct rsnd_dai_stream *io); |
349 | int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_dai *rdai, | 359 | int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod, |
350 | struct rsnd_mod *mod, | ||
351 | struct rsnd_dai_stream *io); | 360 | struct rsnd_dai_stream *io); |
352 | 361 | ||
353 | /* | 362 | /* |
@@ -427,6 +436,8 @@ struct rsnd_kctrl_cfg { | |||
427 | u32 *val; | 436 | u32 *val; |
428 | const char * const *texts; | 437 | const char * const *texts; |
429 | void (*update)(struct rsnd_mod *mod); | 438 | void (*update)(struct rsnd_mod *mod); |
439 | struct snd_card *card; | ||
440 | struct snd_kcontrol *kctrl; | ||
430 | }; | 441 | }; |
431 | 442 | ||
432 | #define RSND_DVC_CHANNELS 2 | 443 | #define RSND_DVC_CHANNELS 2 |
@@ -440,22 +451,22 @@ struct rsnd_kctrl_cfg_s { | |||
440 | u32 val; | 451 | u32 val; |
441 | }; | 452 | }; |
442 | 453 | ||
454 | void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg); | ||
455 | #define rsnd_kctrl_remove(_cfg) _rsnd_kctrl_remove(&((_cfg).cfg)) | ||
456 | |||
443 | int rsnd_kctrl_new_m(struct rsnd_mod *mod, | 457 | int rsnd_kctrl_new_m(struct rsnd_mod *mod, |
444 | struct rsnd_dai *rdai, | ||
445 | struct snd_soc_pcm_runtime *rtd, | 458 | struct snd_soc_pcm_runtime *rtd, |
446 | const unsigned char *name, | 459 | const unsigned char *name, |
447 | void (*update)(struct rsnd_mod *mod), | 460 | void (*update)(struct rsnd_mod *mod), |
448 | struct rsnd_kctrl_cfg_m *_cfg, | 461 | struct rsnd_kctrl_cfg_m *_cfg, |
449 | u32 max); | 462 | u32 max); |
450 | int rsnd_kctrl_new_s(struct rsnd_mod *mod, | 463 | int rsnd_kctrl_new_s(struct rsnd_mod *mod, |
451 | struct rsnd_dai *rdai, | ||
452 | struct snd_soc_pcm_runtime *rtd, | 464 | struct snd_soc_pcm_runtime *rtd, |
453 | const unsigned char *name, | 465 | const unsigned char *name, |
454 | void (*update)(struct rsnd_mod *mod), | 466 | void (*update)(struct rsnd_mod *mod), |
455 | struct rsnd_kctrl_cfg_s *_cfg, | 467 | struct rsnd_kctrl_cfg_s *_cfg, |
456 | u32 max); | 468 | u32 max); |
457 | int rsnd_kctrl_new_e(struct rsnd_mod *mod, | 469 | int rsnd_kctrl_new_e(struct rsnd_mod *mod, |
458 | struct rsnd_dai *rdai, | ||
459 | struct snd_soc_pcm_runtime *rtd, | 470 | struct snd_soc_pcm_runtime *rtd, |
460 | const unsigned char *name, | 471 | const unsigned char *name, |
461 | struct rsnd_kctrl_cfg_s *_cfg, | 472 | struct rsnd_kctrl_cfg_s *_cfg, |
@@ -474,14 +485,10 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, | |||
474 | struct rsnd_dai_stream *io, | 485 | struct rsnd_dai_stream *io, |
475 | struct snd_pcm_runtime *runtime); | 486 | struct snd_pcm_runtime *runtime); |
476 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, | 487 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, |
477 | struct rsnd_dai *rdai, | ||
478 | int use_busif); | 488 | int use_busif); |
479 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, | 489 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod); |
480 | struct rsnd_dai *rdai); | 490 | int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod); |
481 | int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod, | 491 | int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod); |
482 | struct rsnd_dai *rdai); | ||
483 | int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod, | ||
484 | struct rsnd_dai *rdai); | ||
485 | 492 | ||
486 | #define rsnd_src_nr(priv) ((priv)->src_nr) | 493 | #define rsnd_src_nr(priv) ((priv)->src_nr) |
487 | 494 | ||
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index eede3ac6eed2..81c182b4bad5 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c | |||
@@ -12,10 +12,17 @@ | |||
12 | 12 | ||
13 | #define SRC_NAME "src" | 13 | #define SRC_NAME "src" |
14 | 14 | ||
15 | /* SRCx_STATUS */ | ||
16 | #define OUF_SRCO ((1 << 12) | (1 << 13)) | ||
17 | #define OUF_SRCI ((1 << 9) | (1 << 8)) | ||
18 | |||
19 | /* SCU_SYSTEM_STATUS0/1 */ | ||
20 | #define OUF_SRC(id) ((1 << (id + 16)) | (1 << id)) | ||
21 | |||
15 | struct rsnd_src { | 22 | struct rsnd_src { |
16 | struct rsnd_src_platform_info *info; /* rcar_snd.h */ | 23 | struct rsnd_src_platform_info *info; /* rcar_snd.h */ |
17 | struct rsnd_mod mod; | 24 | struct rsnd_mod mod; |
18 | struct clk *clk; | 25 | int err; |
19 | }; | 26 | }; |
20 | 27 | ||
21 | #define RSND_SRC_NAME_SIZE 16 | 28 | #define RSND_SRC_NAME_SIZE 16 |
@@ -107,10 +114,10 @@ struct rsnd_src { | |||
107 | * Gen1/Gen2 common functions | 114 | * Gen1/Gen2 common functions |
108 | */ | 115 | */ |
109 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, | 116 | int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, |
110 | struct rsnd_dai *rdai, | ||
111 | int use_busif) | 117 | int use_busif) |
112 | { | 118 | { |
113 | struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); | 119 | struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); |
120 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | ||
114 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 121 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
115 | int ssi_id = rsnd_mod_id(ssi_mod); | 122 | int ssi_id = rsnd_mod_id(ssi_mod); |
116 | 123 | ||
@@ -140,7 +147,7 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, | |||
140 | if (shift >= 0) | 147 | if (shift >= 0) |
141 | rsnd_mod_bset(ssi_mod, SSI_MODE1, | 148 | rsnd_mod_bset(ssi_mod, SSI_MODE1, |
142 | 0x3 << shift, | 149 | 0x3 << shift, |
143 | rsnd_dai_is_clk_master(rdai) ? | 150 | rsnd_rdai_is_clk_master(rdai) ? |
144 | 0x2 << shift : 0x1 << shift); | 151 | 0x2 << shift : 0x1 << shift); |
145 | } | 152 | } |
146 | 153 | ||
@@ -174,8 +181,7 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, | |||
174 | return 0; | 181 | return 0; |
175 | } | 182 | } |
176 | 183 | ||
177 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, | 184 | int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod) |
178 | struct rsnd_dai *rdai) | ||
179 | { | 185 | { |
180 | /* | 186 | /* |
181 | * DMA settings for SSIU | 187 | * DMA settings for SSIU |
@@ -185,8 +191,7 @@ int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, | |||
185 | return 0; | 191 | return 0; |
186 | } | 192 | } |
187 | 193 | ||
188 | int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod, | 194 | int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod) |
189 | struct rsnd_dai *rdai) | ||
190 | { | 195 | { |
191 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); | 196 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); |
192 | 197 | ||
@@ -202,8 +207,7 @@ int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod, | |||
202 | return 0; | 207 | return 0; |
203 | } | 208 | } |
204 | 209 | ||
205 | int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod, | 210 | int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod) |
206 | struct rsnd_dai *rdai) | ||
207 | { | 211 | { |
208 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); | 212 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); |
209 | 213 | ||
@@ -240,8 +244,7 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, | |||
240 | return rate; | 244 | return rate; |
241 | } | 245 | } |
242 | 246 | ||
243 | static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, | 247 | static int rsnd_src_set_convert_rate(struct rsnd_mod *mod) |
244 | struct rsnd_dai *rdai) | ||
245 | { | 248 | { |
246 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 249 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
247 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 250 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
@@ -273,12 +276,13 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, | |||
273 | return 0; | 276 | return 0; |
274 | } | 277 | } |
275 | 278 | ||
276 | static int rsnd_src_init(struct rsnd_mod *mod, | 279 | static int rsnd_src_init(struct rsnd_mod *mod) |
277 | struct rsnd_dai *rdai) | ||
278 | { | 280 | { |
279 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 281 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
280 | 282 | ||
281 | clk_prepare_enable(src->clk); | 283 | rsnd_mod_hw_start(mod); |
284 | |||
285 | src->err = 0; | ||
282 | 286 | ||
283 | /* | 287 | /* |
284 | * Initialize the operation of the SRC internal circuits | 288 | * Initialize the operation of the SRC internal circuits |
@@ -290,11 +294,16 @@ static int rsnd_src_init(struct rsnd_mod *mod, | |||
290 | } | 294 | } |
291 | 295 | ||
292 | static int rsnd_src_quit(struct rsnd_mod *mod, | 296 | static int rsnd_src_quit(struct rsnd_mod *mod, |
293 | struct rsnd_dai *rdai) | 297 | struct rsnd_priv *priv) |
294 | { | 298 | { |
295 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 299 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
300 | struct device *dev = rsnd_priv_to_dev(priv); | ||
301 | |||
302 | rsnd_mod_hw_stop(mod); | ||
296 | 303 | ||
297 | clk_disable_unprepare(src->clk); | 304 | if (src->err) |
305 | dev_warn(dev, "%s[%d] under/over flow err = %d\n", | ||
306 | rsnd_mod_name(mod), rsnd_mod_id(mod), src->err); | ||
298 | 307 | ||
299 | return 0; | 308 | return 0; |
300 | } | 309 | } |
@@ -319,8 +328,7 @@ static int rsnd_src_stop(struct rsnd_mod *mod) | |||
319 | /* | 328 | /* |
320 | * Gen1 functions | 329 | * Gen1 functions |
321 | */ | 330 | */ |
322 | static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, | 331 | static int rsnd_src_set_route_gen1(struct rsnd_mod *mod) |
323 | struct rsnd_dai *rdai) | ||
324 | { | 332 | { |
325 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 333 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
326 | struct src_route_config { | 334 | struct src_route_config { |
@@ -348,7 +356,7 @@ static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, | |||
348 | /* | 356 | /* |
349 | * SRC_ROUTE_SELECT | 357 | * SRC_ROUTE_SELECT |
350 | */ | 358 | */ |
351 | val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; | 359 | val = rsnd_io_is_play(io) ? 0x1 : 0x2; |
352 | val = val << routes[id].shift; | 360 | val = val << routes[id].shift; |
353 | mask = routes[id].mask << routes[id].shift; | 361 | mask = routes[id].mask << routes[id].shift; |
354 | 362 | ||
@@ -357,8 +365,7 @@ static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, | |||
357 | return 0; | 365 | return 0; |
358 | } | 366 | } |
359 | 367 | ||
360 | static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod, | 368 | static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod) |
361 | struct rsnd_dai *rdai) | ||
362 | { | 369 | { |
363 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 370 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
364 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 371 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
@@ -416,13 +423,12 @@ static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod, | |||
416 | return 0; | 423 | return 0; |
417 | } | 424 | } |
418 | 425 | ||
419 | static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, | 426 | static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod) |
420 | struct rsnd_dai *rdai) | ||
421 | { | 427 | { |
422 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 428 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
423 | int ret; | 429 | int ret; |
424 | 430 | ||
425 | ret = rsnd_src_set_convert_rate(mod, rdai); | 431 | ret = rsnd_src_set_convert_rate(mod); |
426 | if (ret < 0) | 432 | if (ret < 0) |
427 | return ret; | 433 | return ret; |
428 | 434 | ||
@@ -443,9 +449,8 @@ static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, | |||
443 | } | 449 | } |
444 | 450 | ||
445 | static int rsnd_src_probe_gen1(struct rsnd_mod *mod, | 451 | static int rsnd_src_probe_gen1(struct rsnd_mod *mod, |
446 | struct rsnd_dai *rdai) | 452 | struct rsnd_priv *priv) |
447 | { | 453 | { |
448 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
449 | struct device *dev = rsnd_priv_to_dev(priv); | 454 | struct device *dev = rsnd_priv_to_dev(priv); |
450 | 455 | ||
451 | dev_dbg(dev, "%s[%d] (Gen1) is probed\n", | 456 | dev_dbg(dev, "%s[%d] (Gen1) is probed\n", |
@@ -455,23 +460,23 @@ static int rsnd_src_probe_gen1(struct rsnd_mod *mod, | |||
455 | } | 460 | } |
456 | 461 | ||
457 | static int rsnd_src_init_gen1(struct rsnd_mod *mod, | 462 | static int rsnd_src_init_gen1(struct rsnd_mod *mod, |
458 | struct rsnd_dai *rdai) | 463 | struct rsnd_priv *priv) |
459 | { | 464 | { |
460 | int ret; | 465 | int ret; |
461 | 466 | ||
462 | ret = rsnd_src_init(mod, rdai); | 467 | ret = rsnd_src_init(mod); |
463 | if (ret < 0) | 468 | if (ret < 0) |
464 | return ret; | 469 | return ret; |
465 | 470 | ||
466 | ret = rsnd_src_set_route_gen1(mod, rdai); | 471 | ret = rsnd_src_set_route_gen1(mod); |
467 | if (ret < 0) | 472 | if (ret < 0) |
468 | return ret; | 473 | return ret; |
469 | 474 | ||
470 | ret = rsnd_src_set_convert_rate_gen1(mod, rdai); | 475 | ret = rsnd_src_set_convert_rate_gen1(mod); |
471 | if (ret < 0) | 476 | if (ret < 0) |
472 | return ret; | 477 | return ret; |
473 | 478 | ||
474 | ret = rsnd_src_set_convert_timing_gen1(mod, rdai); | 479 | ret = rsnd_src_set_convert_timing_gen1(mod); |
475 | if (ret < 0) | 480 | if (ret < 0) |
476 | return ret; | 481 | return ret; |
477 | 482 | ||
@@ -479,7 +484,7 @@ static int rsnd_src_init_gen1(struct rsnd_mod *mod, | |||
479 | } | 484 | } |
480 | 485 | ||
481 | static int rsnd_src_start_gen1(struct rsnd_mod *mod, | 486 | static int rsnd_src_start_gen1(struct rsnd_mod *mod, |
482 | struct rsnd_dai *rdai) | 487 | struct rsnd_priv *priv) |
483 | { | 488 | { |
484 | int id = rsnd_mod_id(mod); | 489 | int id = rsnd_mod_id(mod); |
485 | 490 | ||
@@ -489,7 +494,7 @@ static int rsnd_src_start_gen1(struct rsnd_mod *mod, | |||
489 | } | 494 | } |
490 | 495 | ||
491 | static int rsnd_src_stop_gen1(struct rsnd_mod *mod, | 496 | static int rsnd_src_stop_gen1(struct rsnd_mod *mod, |
492 | struct rsnd_dai *rdai) | 497 | struct rsnd_priv *priv) |
493 | { | 498 | { |
494 | int id = rsnd_mod_id(mod); | 499 | int id = rsnd_mod_id(mod); |
495 | 500 | ||
@@ -510,8 +515,111 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = { | |||
510 | /* | 515 | /* |
511 | * Gen2 functions | 516 | * Gen2 functions |
512 | */ | 517 | */ |
513 | static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, | 518 | #define rsnd_src_irq_enable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 1) |
514 | struct rsnd_dai *rdai) | 519 | #define rsnd_src_irq_disable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 0) |
520 | static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable) | ||
521 | { | ||
522 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
523 | u32 sys_int_val, int_val, sys_int_mask; | ||
524 | int irq = src->info->irq; | ||
525 | int id = rsnd_mod_id(mod); | ||
526 | |||
527 | sys_int_val = | ||
528 | sys_int_mask = OUF_SRC(id); | ||
529 | int_val = 0x3300; | ||
530 | |||
531 | /* | ||
532 | * IRQ is not supported on non-DT | ||
533 | * see | ||
534 | * rsnd_src_probe_gen2() | ||
535 | */ | ||
536 | if ((irq <= 0) || !enable) { | ||
537 | sys_int_val = 0; | ||
538 | int_val = 0; | ||
539 | } | ||
540 | |||
541 | rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val); | ||
542 | rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val); | ||
543 | rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val); | ||
544 | } | ||
545 | |||
546 | static void rsnd_src_error_clear_gen2(struct rsnd_mod *mod) | ||
547 | { | ||
548 | u32 val = OUF_SRC(rsnd_mod_id(mod)); | ||
549 | |||
550 | rsnd_mod_bset(mod, SCU_SYS_STATUS0, val, val); | ||
551 | rsnd_mod_bset(mod, SCU_SYS_STATUS1, val, val); | ||
552 | } | ||
553 | |||
554 | static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod) | ||
555 | { | ||
556 | u32 val = OUF_SRC(rsnd_mod_id(mod)); | ||
557 | bool ret = false; | ||
558 | |||
559 | if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val) || | ||
560 | (rsnd_mod_read(mod, SCU_SYS_STATUS1) & val)) { | ||
561 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
562 | |||
563 | src->err++; | ||
564 | ret = true; | ||
565 | } | ||
566 | |||
567 | /* clear error static */ | ||
568 | rsnd_src_error_clear_gen2(mod); | ||
569 | |||
570 | return ret; | ||
571 | } | ||
572 | |||
573 | static int _rsnd_src_start_gen2(struct rsnd_mod *mod) | ||
574 | { | ||
575 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
576 | u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11; | ||
577 | |||
578 | rsnd_mod_write(mod, SRC_CTRL, val); | ||
579 | |||
580 | rsnd_src_error_clear_gen2(mod); | ||
581 | |||
582 | rsnd_src_start(mod); | ||
583 | |||
584 | rsnd_src_irq_enable_gen2(mod); | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | static int _rsnd_src_stop_gen2(struct rsnd_mod *mod) | ||
590 | { | ||
591 | rsnd_src_irq_disable_gen2(mod); | ||
592 | |||
593 | rsnd_mod_write(mod, SRC_CTRL, 0); | ||
594 | |||
595 | rsnd_src_error_record_gen2(mod); | ||
596 | |||
597 | return rsnd_src_stop(mod); | ||
598 | } | ||
599 | |||
600 | static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data) | ||
601 | { | ||
602 | struct rsnd_mod *mod = data; | ||
603 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
604 | |||
605 | if (!io) | ||
606 | return IRQ_NONE; | ||
607 | |||
608 | if (rsnd_src_error_record_gen2(mod)) { | ||
609 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
610 | struct device *dev = rsnd_priv_to_dev(priv); | ||
611 | |||
612 | _rsnd_src_stop_gen2(mod); | ||
613 | _rsnd_src_start_gen2(mod); | ||
614 | |||
615 | dev_dbg(dev, "%s[%d] restart\n", | ||
616 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
617 | } | ||
618 | |||
619 | return IRQ_HANDLED; | ||
620 | } | ||
621 | |||
622 | static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod) | ||
515 | { | 623 | { |
516 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 624 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
517 | struct device *dev = rsnd_priv_to_dev(priv); | 625 | struct device *dev = rsnd_priv_to_dev(priv); |
@@ -535,7 +643,7 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, | |||
535 | return -EINVAL; | 643 | return -EINVAL; |
536 | } | 644 | } |
537 | 645 | ||
538 | ret = rsnd_src_set_convert_rate(mod, rdai); | 646 | ret = rsnd_src_set_convert_rate(mod); |
539 | if (ret < 0) | 647 | if (ret < 0) |
540 | return ret; | 648 | return ret; |
541 | 649 | ||
@@ -563,8 +671,7 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, | |||
563 | return 0; | 671 | return 0; |
564 | } | 672 | } |
565 | 673 | ||
566 | static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod, | 674 | static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod) |
567 | struct rsnd_dai *rdai) | ||
568 | { | 675 | { |
569 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 676 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
570 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 677 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
@@ -573,59 +680,78 @@ static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod, | |||
573 | int ret; | 680 | int ret; |
574 | 681 | ||
575 | if (convert_rate) | 682 | if (convert_rate) |
576 | ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, | 683 | ret = rsnd_adg_set_convert_clk_gen2(mod, io, |
577 | runtime->rate, | 684 | runtime->rate, |
578 | convert_rate); | 685 | convert_rate); |
579 | else | 686 | else |
580 | ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); | 687 | ret = rsnd_adg_set_convert_timing_gen2(mod, io); |
581 | 688 | ||
582 | return ret; | 689 | return ret; |
583 | } | 690 | } |
584 | 691 | ||
585 | static int rsnd_src_probe_gen2(struct rsnd_mod *mod, | 692 | static int rsnd_src_probe_gen2(struct rsnd_mod *mod, |
586 | struct rsnd_dai *rdai) | 693 | struct rsnd_priv *priv) |
587 | { | 694 | { |
588 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
589 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 695 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
590 | struct device *dev = rsnd_priv_to_dev(priv); | 696 | struct device *dev = rsnd_priv_to_dev(priv); |
697 | int irq = src->info->irq; | ||
591 | int ret; | 698 | int ret; |
592 | 699 | ||
700 | if (irq > 0) { | ||
701 | /* | ||
702 | * IRQ is not supported on non-DT | ||
703 | * see | ||
704 | * rsnd_src_irq_enable_gen2() | ||
705 | */ | ||
706 | ret = devm_request_irq(dev, irq, | ||
707 | rsnd_src_interrupt_gen2, | ||
708 | IRQF_SHARED, | ||
709 | dev_name(dev), mod); | ||
710 | if (ret) | ||
711 | goto rsnd_src_probe_gen2_fail; | ||
712 | } | ||
713 | |||
593 | ret = rsnd_dma_init(priv, | 714 | ret = rsnd_dma_init(priv, |
594 | rsnd_mod_to_dma(mod), | 715 | rsnd_mod_to_dma(mod), |
595 | rsnd_info_is_playback(priv, src), | 716 | rsnd_info_is_playback(priv, src), |
596 | src->info->dma_id); | 717 | src->info->dma_id); |
597 | if (ret < 0) | 718 | if (ret) |
598 | dev_err(dev, "%s[%d] (Gen2) failed\n", | 719 | goto rsnd_src_probe_gen2_fail; |
599 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | 720 | |
600 | else | 721 | dev_dbg(dev, "%s[%d] (Gen2) is probed\n", |
601 | dev_dbg(dev, "%s[%d] (Gen2) is probed\n", | 722 | rsnd_mod_name(mod), rsnd_mod_id(mod)); |
602 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | 723 | |
724 | return ret; | ||
725 | |||
726 | rsnd_src_probe_gen2_fail: | ||
727 | dev_err(dev, "%s[%d] (Gen2) failed\n", | ||
728 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
603 | 729 | ||
604 | return ret; | 730 | return ret; |
605 | } | 731 | } |
606 | 732 | ||
607 | static int rsnd_src_remove_gen2(struct rsnd_mod *mod, | 733 | static int rsnd_src_remove_gen2(struct rsnd_mod *mod, |
608 | struct rsnd_dai *rdai) | 734 | struct rsnd_priv *priv) |
609 | { | 735 | { |
610 | rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); | 736 | rsnd_dma_quit(priv, rsnd_mod_to_dma(mod)); |
611 | 737 | ||
612 | return 0; | 738 | return 0; |
613 | } | 739 | } |
614 | 740 | ||
615 | static int rsnd_src_init_gen2(struct rsnd_mod *mod, | 741 | static int rsnd_src_init_gen2(struct rsnd_mod *mod, |
616 | struct rsnd_dai *rdai) | 742 | struct rsnd_priv *priv) |
617 | { | 743 | { |
618 | int ret; | 744 | int ret; |
619 | 745 | ||
620 | ret = rsnd_src_init(mod, rdai); | 746 | ret = rsnd_src_init(mod); |
621 | if (ret < 0) | 747 | if (ret < 0) |
622 | return ret; | 748 | return ret; |
623 | 749 | ||
624 | ret = rsnd_src_set_convert_rate_gen2(mod, rdai); | 750 | ret = rsnd_src_set_convert_rate_gen2(mod); |
625 | if (ret < 0) | 751 | if (ret < 0) |
626 | return ret; | 752 | return ret; |
627 | 753 | ||
628 | ret = rsnd_src_set_convert_timing_gen2(mod, rdai); | 754 | ret = rsnd_src_set_convert_timing_gen2(mod); |
629 | if (ret < 0) | 755 | if (ret < 0) |
630 | return ret; | 756 | return ret; |
631 | 757 | ||
@@ -633,29 +759,23 @@ static int rsnd_src_init_gen2(struct rsnd_mod *mod, | |||
633 | } | 759 | } |
634 | 760 | ||
635 | static int rsnd_src_start_gen2(struct rsnd_mod *mod, | 761 | static int rsnd_src_start_gen2(struct rsnd_mod *mod, |
636 | struct rsnd_dai *rdai) | 762 | struct rsnd_priv *priv) |
637 | { | 763 | { |
638 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 764 | rsnd_dma_start(rsnd_mod_to_dma(mod)); |
639 | struct rsnd_src *src = rsnd_mod_to_src(mod); | ||
640 | u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11; | ||
641 | |||
642 | rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); | ||
643 | 765 | ||
644 | rsnd_mod_write(mod, SRC_CTRL, val); | 766 | return _rsnd_src_start_gen2(mod); |
645 | |||
646 | return rsnd_src_start(mod); | ||
647 | } | 767 | } |
648 | 768 | ||
649 | static int rsnd_src_stop_gen2(struct rsnd_mod *mod, | 769 | static int rsnd_src_stop_gen2(struct rsnd_mod *mod, |
650 | struct rsnd_dai *rdai) | 770 | struct rsnd_priv *priv) |
651 | { | 771 | { |
652 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 772 | int ret; |
653 | 773 | ||
654 | rsnd_mod_write(mod, SRC_CTRL, 0); | 774 | ret = _rsnd_src_stop_gen2(mod); |
655 | 775 | ||
656 | rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); | 776 | rsnd_dma_stop(rsnd_mod_to_dma(mod)); |
657 | 777 | ||
658 | return rsnd_src_stop(mod); | 778 | return ret; |
659 | } | 779 | } |
660 | 780 | ||
661 | static struct rsnd_mod_ops rsnd_src_gen2_ops = { | 781 | static struct rsnd_mod_ops rsnd_src_gen2_ops = { |
@@ -681,10 +801,11 @@ static void rsnd_of_parse_src(struct platform_device *pdev, | |||
681 | struct rsnd_priv *priv) | 801 | struct rsnd_priv *priv) |
682 | { | 802 | { |
683 | struct device_node *src_node; | 803 | struct device_node *src_node; |
804 | struct device_node *np; | ||
684 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | 805 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); |
685 | struct rsnd_src_platform_info *src_info; | 806 | struct rsnd_src_platform_info *src_info; |
686 | struct device *dev = &pdev->dev; | 807 | struct device *dev = &pdev->dev; |
687 | int nr; | 808 | int nr, i; |
688 | 809 | ||
689 | if (!of_data) | 810 | if (!of_data) |
690 | return; | 811 | return; |
@@ -708,6 +829,13 @@ static void rsnd_of_parse_src(struct platform_device *pdev, | |||
708 | info->src_info = src_info; | 829 | info->src_info = src_info; |
709 | info->src_info_nr = nr; | 830 | info->src_info_nr = nr; |
710 | 831 | ||
832 | i = 0; | ||
833 | for_each_child_of_node(src_node, np) { | ||
834 | src_info[i].irq = irq_of_parse_and_map(np, 0); | ||
835 | |||
836 | i++; | ||
837 | } | ||
838 | |||
711 | rsnd_of_parse_src_end: | 839 | rsnd_of_parse_src_end: |
712 | of_node_put(src_node); | 840 | of_node_put(src_node); |
713 | } | 841 | } |
@@ -761,9 +889,8 @@ int rsnd_src_probe(struct platform_device *pdev, | |||
761 | return PTR_ERR(clk); | 889 | return PTR_ERR(clk); |
762 | 890 | ||
763 | src->info = &info->src_info[i]; | 891 | src->info = &info->src_info[i]; |
764 | src->clk = clk; | ||
765 | 892 | ||
766 | rsnd_mod_init(priv, &src->mod, ops, RSND_MOD_SRC, i); | 893 | rsnd_mod_init(&src->mod, ops, clk, RSND_MOD_SRC, i); |
767 | 894 | ||
768 | dev_dbg(dev, "SRC%d probed\n", i); | 895 | dev_dbg(dev, "SRC%d probed\n", i); |
769 | } | 896 | } |
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 3844fbef4664..9e7b627c08e2 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -60,17 +60,14 @@ | |||
60 | #define SSI_NAME "ssi" | 60 | #define SSI_NAME "ssi" |
61 | 61 | ||
62 | struct rsnd_ssi { | 62 | struct rsnd_ssi { |
63 | struct clk *clk; | ||
64 | struct rsnd_ssi_platform_info *info; /* rcar_snd.h */ | 63 | struct rsnd_ssi_platform_info *info; /* rcar_snd.h */ |
65 | struct rsnd_ssi *parent; | 64 | struct rsnd_ssi *parent; |
66 | struct rsnd_mod mod; | 65 | struct rsnd_mod mod; |
67 | 66 | ||
68 | struct rsnd_dai *rdai; | ||
69 | u32 cr_own; | 67 | u32 cr_own; |
70 | u32 cr_clk; | 68 | u32 cr_clk; |
71 | int err; | 69 | int err; |
72 | unsigned int usrcnt; | 70 | unsigned int usrcnt; |
73 | unsigned int rate; | ||
74 | }; | 71 | }; |
75 | 72 | ||
76 | #define for_each_rsnd_ssi(pos, priv, i) \ | 73 | #define for_each_rsnd_ssi(pos, priv, i) \ |
@@ -128,7 +125,7 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod, | |||
128 | static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, | 125 | static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, |
129 | struct rsnd_dai_stream *io) | 126 | struct rsnd_dai_stream *io) |
130 | { | 127 | { |
131 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); | 128 | struct rsnd_priv *priv = rsnd_io_to_priv(io); |
132 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 129 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
133 | struct device *dev = rsnd_priv_to_dev(priv); | 130 | struct device *dev = rsnd_priv_to_dev(priv); |
134 | int i, j, ret; | 131 | int i, j, ret; |
@@ -157,7 +154,6 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, | |||
157 | 154 | ||
158 | ret = rsnd_adg_ssi_clk_try_start(&ssi->mod, main_rate); | 155 | ret = rsnd_adg_ssi_clk_try_start(&ssi->mod, main_rate); |
159 | if (0 == ret) { | 156 | if (0 == ret) { |
160 | ssi->rate = rate; | ||
161 | ssi->cr_clk = FORCE | SWL_32 | | 157 | ssi->cr_clk = FORCE | SWL_32 | |
162 | SCKD | SWSD | CKDV(j); | 158 | SCKD | SWSD | CKDV(j); |
163 | 159 | ||
@@ -176,26 +172,25 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, | |||
176 | 172 | ||
177 | static void rsnd_ssi_master_clk_stop(struct rsnd_ssi *ssi) | 173 | static void rsnd_ssi_master_clk_stop(struct rsnd_ssi *ssi) |
178 | { | 174 | { |
179 | ssi->rate = 0; | ||
180 | ssi->cr_clk = 0; | 175 | ssi->cr_clk = 0; |
181 | rsnd_adg_ssi_clk_stop(&ssi->mod); | 176 | rsnd_adg_ssi_clk_stop(&ssi->mod); |
182 | } | 177 | } |
183 | 178 | ||
184 | static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, | 179 | static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, |
185 | struct rsnd_dai *rdai, | ||
186 | struct rsnd_dai_stream *io) | 180 | struct rsnd_dai_stream *io) |
187 | { | 181 | { |
188 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); | 182 | struct rsnd_priv *priv = rsnd_io_to_priv(io); |
183 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | ||
189 | struct device *dev = rsnd_priv_to_dev(priv); | 184 | struct device *dev = rsnd_priv_to_dev(priv); |
190 | u32 cr_mode; | 185 | u32 cr_mode; |
191 | u32 cr; | 186 | u32 cr; |
192 | 187 | ||
193 | if (0 == ssi->usrcnt) { | 188 | if (0 == ssi->usrcnt) { |
194 | clk_prepare_enable(ssi->clk); | 189 | rsnd_mod_hw_start(&ssi->mod); |
195 | 190 | ||
196 | if (rsnd_dai_is_clk_master(rdai)) { | 191 | if (rsnd_rdai_is_clk_master(rdai)) { |
197 | if (rsnd_ssi_clk_from_parent(ssi)) | 192 | if (rsnd_ssi_clk_from_parent(ssi)) |
198 | rsnd_ssi_hw_start(ssi->parent, rdai, io); | 193 | rsnd_ssi_hw_start(ssi->parent, io); |
199 | else | 194 | else |
200 | rsnd_ssi_master_clk_start(ssi, io); | 195 | rsnd_ssi_master_clk_start(ssi, io); |
201 | } | 196 | } |
@@ -214,7 +209,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, | |||
214 | rsnd_mod_write(&ssi->mod, SSICR, cr); | 209 | rsnd_mod_write(&ssi->mod, SSICR, cr); |
215 | 210 | ||
216 | /* enable WS continue */ | 211 | /* enable WS continue */ |
217 | if (rsnd_dai_is_clk_master(rdai)) | 212 | if (rsnd_rdai_is_clk_master(rdai)) |
218 | rsnd_mod_write(&ssi->mod, SSIWSR, CONT); | 213 | rsnd_mod_write(&ssi->mod, SSIWSR, CONT); |
219 | 214 | ||
220 | /* clear error status */ | 215 | /* clear error status */ |
@@ -226,10 +221,11 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, | |||
226 | rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod)); | 221 | rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod)); |
227 | } | 222 | } |
228 | 223 | ||
229 | static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, | 224 | static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) |
230 | struct rsnd_dai *rdai) | ||
231 | { | 225 | { |
232 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); | 226 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); |
227 | struct rsnd_dai_stream *io = rsnd_mod_to_io(&ssi->mod); | ||
228 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | ||
233 | struct device *dev = rsnd_priv_to_dev(priv); | 229 | struct device *dev = rsnd_priv_to_dev(priv); |
234 | u32 cr; | 230 | u32 cr; |
235 | 231 | ||
@@ -256,14 +252,14 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, | |||
256 | rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */ | 252 | rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */ |
257 | rsnd_ssi_status_check(&ssi->mod, IIRQ); | 253 | rsnd_ssi_status_check(&ssi->mod, IIRQ); |
258 | 254 | ||
259 | if (rsnd_dai_is_clk_master(rdai)) { | 255 | if (rsnd_rdai_is_clk_master(rdai)) { |
260 | if (rsnd_ssi_clk_from_parent(ssi)) | 256 | if (rsnd_ssi_clk_from_parent(ssi)) |
261 | rsnd_ssi_hw_stop(ssi->parent, rdai); | 257 | rsnd_ssi_hw_stop(ssi->parent); |
262 | else | 258 | else |
263 | rsnd_ssi_master_clk_stop(ssi); | 259 | rsnd_ssi_master_clk_stop(ssi); |
264 | } | 260 | } |
265 | 261 | ||
266 | clk_disable_unprepare(ssi->clk); | 262 | rsnd_mod_hw_stop(&ssi->mod); |
267 | } | 263 | } |
268 | 264 | ||
269 | dev_dbg(dev, "%s[%d] hw stopped\n", | 265 | dev_dbg(dev, "%s[%d] hw stopped\n", |
@@ -274,10 +270,11 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, | |||
274 | * SSI mod common functions | 270 | * SSI mod common functions |
275 | */ | 271 | */ |
276 | static int rsnd_ssi_init(struct rsnd_mod *mod, | 272 | static int rsnd_ssi_init(struct rsnd_mod *mod, |
277 | struct rsnd_dai *rdai) | 273 | struct rsnd_priv *priv) |
278 | { | 274 | { |
279 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 275 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
280 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 276 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
277 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | ||
281 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 278 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
282 | u32 cr; | 279 | u32 cr; |
283 | 280 | ||
@@ -311,13 +308,12 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, | |||
311 | cr |= SDTA; | 308 | cr |= SDTA; |
312 | if (rdai->sys_delay) | 309 | if (rdai->sys_delay) |
313 | cr |= DEL; | 310 | cr |= DEL; |
314 | if (rsnd_dai_is_play(rdai, io)) | 311 | if (rsnd_io_is_play(io)) |
315 | cr |= TRMD; | 312 | cr |= TRMD; |
316 | 313 | ||
317 | /* | 314 | /* |
318 | * set ssi parameter | 315 | * set ssi parameter |
319 | */ | 316 | */ |
320 | ssi->rdai = rdai; | ||
321 | ssi->cr_own = cr; | 317 | ssi->cr_own = cr; |
322 | ssi->err = -1; /* ignore 1st error */ | 318 | ssi->err = -1; /* ignore 1st error */ |
323 | 319 | ||
@@ -325,16 +321,15 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, | |||
325 | } | 321 | } |
326 | 322 | ||
327 | static int rsnd_ssi_quit(struct rsnd_mod *mod, | 323 | static int rsnd_ssi_quit(struct rsnd_mod *mod, |
328 | struct rsnd_dai *rdai) | 324 | struct rsnd_priv *priv) |
329 | { | 325 | { |
330 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 326 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
331 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
332 | struct device *dev = rsnd_priv_to_dev(priv); | 327 | struct device *dev = rsnd_priv_to_dev(priv); |
333 | 328 | ||
334 | if (ssi->err > 0) | 329 | if (ssi->err > 0) |
335 | dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err); | 330 | dev_warn(dev, "%s[%d] under/over flow err = %d\n", |
331 | rsnd_mod_name(mod), rsnd_mod_id(mod), ssi->err); | ||
336 | 332 | ||
337 | ssi->rdai = NULL; | ||
338 | ssi->cr_own = 0; | 333 | ssi->cr_own = 0; |
339 | ssi->err = 0; | 334 | ssi->err = 0; |
340 | 335 | ||
@@ -353,32 +348,32 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) | |||
353 | } | 348 | } |
354 | 349 | ||
355 | static int rsnd_ssi_start(struct rsnd_mod *mod, | 350 | static int rsnd_ssi_start(struct rsnd_mod *mod, |
356 | struct rsnd_dai *rdai) | 351 | struct rsnd_priv *priv) |
357 | { | 352 | { |
358 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 353 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
359 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 354 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
360 | 355 | ||
361 | rsnd_src_ssiu_start(mod, rdai, rsnd_ssi_use_busif(mod)); | 356 | rsnd_src_ssiu_start(mod, rsnd_ssi_use_busif(mod)); |
362 | 357 | ||
363 | rsnd_ssi_hw_start(ssi, rdai, io); | 358 | rsnd_ssi_hw_start(ssi, io); |
364 | 359 | ||
365 | rsnd_src_ssi_irq_enable(mod, rdai); | 360 | rsnd_src_ssi_irq_enable(mod); |
366 | 361 | ||
367 | return 0; | 362 | return 0; |
368 | } | 363 | } |
369 | 364 | ||
370 | static int rsnd_ssi_stop(struct rsnd_mod *mod, | 365 | static int rsnd_ssi_stop(struct rsnd_mod *mod, |
371 | struct rsnd_dai *rdai) | 366 | struct rsnd_priv *priv) |
372 | { | 367 | { |
373 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 368 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
374 | 369 | ||
375 | rsnd_src_ssi_irq_disable(mod, rdai); | 370 | rsnd_src_ssi_irq_disable(mod); |
376 | 371 | ||
377 | rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); | 372 | rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); |
378 | 373 | ||
379 | rsnd_ssi_hw_stop(ssi, rdai); | 374 | rsnd_ssi_hw_stop(ssi); |
380 | 375 | ||
381 | rsnd_src_ssiu_stop(mod, rdai); | 376 | rsnd_src_ssiu_stop(mod); |
382 | 377 | ||
383 | return 0; | 378 | return 0; |
384 | } | 379 | } |
@@ -386,16 +381,17 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod, | |||
386 | static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | 381 | static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) |
387 | { | 382 | { |
388 | struct rsnd_ssi *ssi = data; | 383 | struct rsnd_ssi *ssi = data; |
389 | struct rsnd_dai *rdai = ssi->rdai; | ||
390 | struct rsnd_mod *mod = &ssi->mod; | 384 | struct rsnd_mod *mod = &ssi->mod; |
385 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
391 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 386 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
387 | int is_dma = rsnd_ssi_is_dma_mode(mod); | ||
392 | u32 status = rsnd_mod_read(mod, SSISR); | 388 | u32 status = rsnd_mod_read(mod, SSISR); |
393 | 389 | ||
394 | if (!io) | 390 | if (!io) |
395 | return IRQ_NONE; | 391 | return IRQ_NONE; |
396 | 392 | ||
397 | /* PIO only */ | 393 | /* PIO only */ |
398 | if (status & DIRQ) { | 394 | if (!is_dma && (status & DIRQ)) { |
399 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 395 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
400 | u32 *buf = (u32 *)(runtime->dma_area + | 396 | u32 *buf = (u32 *)(runtime->dma_area + |
401 | rsnd_dai_pointer_offset(io, 0)); | 397 | rsnd_dai_pointer_offset(io, 0)); |
@@ -405,7 +401,7 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | |||
405 | * directly as 32bit data | 401 | * directly as 32bit data |
406 | * see rsnd_ssi_init() | 402 | * see rsnd_ssi_init() |
407 | */ | 403 | */ |
408 | if (rsnd_dai_is_play(rdai, io)) | 404 | if (rsnd_io_is_play(io)) |
409 | rsnd_mod_write(mod, SSITDR, *buf); | 405 | rsnd_mod_write(mod, SSITDR, *buf); |
410 | else | 406 | else |
411 | *buf = rsnd_mod_read(mod, SSIRDR); | 407 | *buf = rsnd_mod_read(mod, SSIRDR); |
@@ -415,14 +411,13 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | |||
415 | 411 | ||
416 | /* PIO / DMA */ | 412 | /* PIO / DMA */ |
417 | if (status & (UIRQ | OIRQ)) { | 413 | if (status & (UIRQ | OIRQ)) { |
418 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
419 | struct device *dev = rsnd_priv_to_dev(priv); | 414 | struct device *dev = rsnd_priv_to_dev(priv); |
420 | 415 | ||
421 | /* | 416 | /* |
422 | * restart SSI | 417 | * restart SSI |
423 | */ | 418 | */ |
424 | rsnd_ssi_stop(mod, rdai); | 419 | rsnd_ssi_stop(mod, priv); |
425 | rsnd_ssi_start(mod, rdai); | 420 | rsnd_ssi_start(mod, priv); |
426 | 421 | ||
427 | dev_dbg(dev, "%s[%d] restart\n", | 422 | dev_dbg(dev, "%s[%d] restart\n", |
428 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | 423 | rsnd_mod_name(mod), rsnd_mod_id(mod)); |
@@ -437,9 +432,8 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | |||
437 | * SSI PIO | 432 | * SSI PIO |
438 | */ | 433 | */ |
439 | static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, | 434 | static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, |
440 | struct rsnd_dai *rdai) | 435 | struct rsnd_priv *priv) |
441 | { | 436 | { |
442 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
443 | struct device *dev = rsnd_priv_to_dev(priv); | 437 | struct device *dev = rsnd_priv_to_dev(priv); |
444 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 438 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
445 | int ret; | 439 | int ret; |
@@ -468,9 +462,8 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { | |||
468 | }; | 462 | }; |
469 | 463 | ||
470 | static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, | 464 | static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, |
471 | struct rsnd_dai *rdai) | 465 | struct rsnd_priv *priv) |
472 | { | 466 | { |
473 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
474 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 467 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
475 | struct device *dev = rsnd_priv_to_dev(priv); | 468 | struct device *dev = rsnd_priv_to_dev(priv); |
476 | int dma_id = ssi->info->dma_id; | 469 | int dma_id = ssi->info->dma_id; |
@@ -503,14 +496,13 @@ rsnd_ssi_dma_probe_fail: | |||
503 | } | 496 | } |
504 | 497 | ||
505 | static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, | 498 | static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, |
506 | struct rsnd_dai *rdai) | 499 | struct rsnd_priv *priv) |
507 | { | 500 | { |
508 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
509 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 501 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
510 | struct device *dev = rsnd_priv_to_dev(priv); | 502 | struct device *dev = rsnd_priv_to_dev(priv); |
511 | int irq = ssi->info->irq; | 503 | int irq = ssi->info->irq; |
512 | 504 | ||
513 | rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); | 505 | rsnd_dma_quit(priv, rsnd_mod_to_dma(mod)); |
514 | 506 | ||
515 | /* PIO will request IRQ again */ | 507 | /* PIO will request IRQ again */ |
516 | devm_free_irq(dev, irq, ssi); | 508 | devm_free_irq(dev, irq, ssi); |
@@ -519,9 +511,8 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, | |||
519 | } | 511 | } |
520 | 512 | ||
521 | static int rsnd_ssi_fallback(struct rsnd_mod *mod, | 513 | static int rsnd_ssi_fallback(struct rsnd_mod *mod, |
522 | struct rsnd_dai *rdai) | 514 | struct rsnd_priv *priv) |
523 | { | 515 | { |
524 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
525 | struct device *dev = rsnd_priv_to_dev(priv); | 516 | struct device *dev = rsnd_priv_to_dev(priv); |
526 | 517 | ||
527 | /* | 518 | /* |
@@ -540,25 +531,25 @@ static int rsnd_ssi_fallback(struct rsnd_mod *mod, | |||
540 | } | 531 | } |
541 | 532 | ||
542 | static int rsnd_ssi_dma_start(struct rsnd_mod *mod, | 533 | static int rsnd_ssi_dma_start(struct rsnd_mod *mod, |
543 | struct rsnd_dai *rdai) | 534 | struct rsnd_priv *priv) |
544 | { | 535 | { |
545 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); | 536 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
546 | 537 | ||
547 | rsnd_ssi_start(mod, rdai); | ||
548 | |||
549 | rsnd_dma_start(dma); | 538 | rsnd_dma_start(dma); |
550 | 539 | ||
540 | rsnd_ssi_start(mod, priv); | ||
541 | |||
551 | return 0; | 542 | return 0; |
552 | } | 543 | } |
553 | 544 | ||
554 | static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, | 545 | static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, |
555 | struct rsnd_dai *rdai) | 546 | struct rsnd_priv *priv) |
556 | { | 547 | { |
557 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); | 548 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
558 | 549 | ||
559 | rsnd_dma_stop(dma); | 550 | rsnd_ssi_stop(mod, priv); |
560 | 551 | ||
561 | rsnd_ssi_stop(mod, rdai); | 552 | rsnd_dma_stop(dma); |
562 | 553 | ||
563 | return 0; | 554 | return 0; |
564 | } | 555 | } |
@@ -734,7 +725,6 @@ int rsnd_ssi_probe(struct platform_device *pdev, | |||
734 | return PTR_ERR(clk); | 725 | return PTR_ERR(clk); |
735 | 726 | ||
736 | ssi->info = pinfo; | 727 | ssi->info = pinfo; |
737 | ssi->clk = clk; | ||
738 | 728 | ||
739 | ops = &rsnd_ssi_non_ops; | 729 | ops = &rsnd_ssi_non_ops; |
740 | if (pinfo->dma_id > 0) | 730 | if (pinfo->dma_id > 0) |
@@ -742,7 +732,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, | |||
742 | else if (rsnd_ssi_pio_available(ssi)) | 732 | else if (rsnd_ssi_pio_available(ssi)) |
743 | ops = &rsnd_ssi_pio_ops; | 733 | ops = &rsnd_ssi_pio_ops; |
744 | 734 | ||
745 | rsnd_mod_init(priv, &ssi->mod, ops, RSND_MOD_SSI, i); | 735 | rsnd_mod_init(&ssi->mod, ops, clk, RSND_MOD_SSI, i); |
746 | 736 | ||
747 | rsnd_ssi_parent_clk_setup(priv, ssi); | 737 | rsnd_ssi_parent_clk_setup(priv, ssi); |
748 | } | 738 | } |
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index 32eb6da2d2bd..82902f56e82f 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c | |||
@@ -589,7 +589,6 @@ static void siu_pcm_free(struct snd_pcm *pcm) | |||
589 | tasklet_kill(&port_info->playback.tasklet); | 589 | tasklet_kill(&port_info->playback.tasklet); |
590 | 590 | ||
591 | siu_free_port(port_info); | 591 | siu_free_port(port_info); |
592 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
593 | 592 | ||
594 | dev_dbg(pcm->card->dev, "%s\n", __func__); | 593 | dev_dbg(pcm->card->dev, "%s\n", __func__); |
595 | } | 594 | } |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2c62620abca6..30579ca5bacb 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -191,6 +191,39 @@ static ssize_t pmdown_time_set(struct device *dev, | |||
191 | 191 | ||
192 | static DEVICE_ATTR(pmdown_time, 0644, pmdown_time_show, pmdown_time_set); | 192 | static DEVICE_ATTR(pmdown_time, 0644, pmdown_time_show, pmdown_time_set); |
193 | 193 | ||
194 | static struct attribute *soc_dev_attrs[] = { | ||
195 | &dev_attr_codec_reg.attr, | ||
196 | &dev_attr_pmdown_time.attr, | ||
197 | NULL | ||
198 | }; | ||
199 | |||
200 | static umode_t soc_dev_attr_is_visible(struct kobject *kobj, | ||
201 | struct attribute *attr, int idx) | ||
202 | { | ||
203 | struct device *dev = kobj_to_dev(kobj); | ||
204 | struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev); | ||
205 | |||
206 | if (attr == &dev_attr_pmdown_time.attr) | ||
207 | return attr->mode; /* always visible */ | ||
208 | return rtd->codec ? attr->mode : 0; /* enabled only with codec */ | ||
209 | } | ||
210 | |||
211 | static const struct attribute_group soc_dapm_dev_group = { | ||
212 | .attrs = soc_dapm_dev_attrs, | ||
213 | .is_visible = soc_dev_attr_is_visible, | ||
214 | }; | ||
215 | |||
216 | static const struct attribute_group soc_dev_roup = { | ||
217 | .attrs = soc_dev_attrs, | ||
218 | .is_visible = soc_dev_attr_is_visible, | ||
219 | }; | ||
220 | |||
221 | static const struct attribute_group *soc_dev_attr_groups[] = { | ||
222 | &soc_dapm_dev_group, | ||
223 | &soc_dev_roup, | ||
224 | NULL | ||
225 | }; | ||
226 | |||
194 | #ifdef CONFIG_DEBUG_FS | 227 | #ifdef CONFIG_DEBUG_FS |
195 | static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, | 228 | static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, |
196 | size_t count, loff_t *ppos) | 229 | size_t count, loff_t *ppos) |
@@ -949,8 +982,6 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) | |||
949 | 982 | ||
950 | /* unregister the rtd device */ | 983 | /* unregister the rtd device */ |
951 | if (rtd->dev_registered) { | 984 | if (rtd->dev_registered) { |
952 | device_remove_file(rtd->dev, &dev_attr_pmdown_time); | ||
953 | device_remove_file(rtd->dev, &dev_attr_codec_reg); | ||
954 | device_unregister(rtd->dev); | 985 | device_unregister(rtd->dev); |
955 | rtd->dev_registered = 0; | 986 | rtd->dev_registered = 0; |
956 | } | 987 | } |
@@ -1120,6 +1151,7 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, | |||
1120 | device_initialize(rtd->dev); | 1151 | device_initialize(rtd->dev); |
1121 | rtd->dev->parent = rtd->card->dev; | 1152 | rtd->dev->parent = rtd->card->dev; |
1122 | rtd->dev->release = rtd_release; | 1153 | rtd->dev->release = rtd_release; |
1154 | rtd->dev->groups = soc_dev_attr_groups; | ||
1123 | dev_set_name(rtd->dev, "%s", name); | 1155 | dev_set_name(rtd->dev, "%s", name); |
1124 | dev_set_drvdata(rtd->dev, rtd); | 1156 | dev_set_drvdata(rtd->dev, rtd); |
1125 | mutex_init(&rtd->pcm_mutex); | 1157 | mutex_init(&rtd->pcm_mutex); |
@@ -1136,23 +1168,6 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, | |||
1136 | return ret; | 1168 | return ret; |
1137 | } | 1169 | } |
1138 | rtd->dev_registered = 1; | 1170 | rtd->dev_registered = 1; |
1139 | |||
1140 | if (rtd->codec) { | ||
1141 | /* add DAPM sysfs entries for this codec */ | ||
1142 | ret = snd_soc_dapm_sys_add(rtd->dev); | ||
1143 | if (ret < 0) | ||
1144 | dev_err(rtd->dev, | ||
1145 | "ASoC: failed to add codec dapm sysfs entries: %d\n", | ||
1146 | ret); | ||
1147 | |||
1148 | /* add codec sysfs entries */ | ||
1149 | ret = device_create_file(rtd->dev, &dev_attr_codec_reg); | ||
1150 | if (ret < 0) | ||
1151 | dev_err(rtd->dev, | ||
1152 | "ASoC: failed to add codec sysfs files: %d\n", | ||
1153 | ret); | ||
1154 | } | ||
1155 | |||
1156 | return 0; | 1171 | return 0; |
1157 | } | 1172 | } |
1158 | 1173 | ||
@@ -1308,11 +1323,6 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1308 | } | 1323 | } |
1309 | #endif | 1324 | #endif |
1310 | 1325 | ||
1311 | ret = device_create_file(rtd->dev, &dev_attr_pmdown_time); | ||
1312 | if (ret < 0) | ||
1313 | dev_warn(rtd->dev, "ASoC: failed to add pmdown_time sysfs: %d\n", | ||
1314 | ret); | ||
1315 | |||
1316 | if (cpu_dai->driver->compress_dai) { | 1326 | if (cpu_dai->driver->compress_dai) { |
1317 | /*create compress_device"*/ | 1327 | /*create compress_device"*/ |
1318 | ret = soc_new_compress(rtd, num); | 1328 | ret = soc_new_compress(rtd, num); |
@@ -1427,11 +1437,76 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec) | |||
1427 | return 0; | 1437 | return 0; |
1428 | } | 1438 | } |
1429 | 1439 | ||
1440 | /** | ||
1441 | * snd_soc_runtime_set_dai_fmt() - Change DAI link format for a ASoC runtime | ||
1442 | * @rtd: The runtime for which the DAI link format should be changed | ||
1443 | * @dai_fmt: The new DAI link format | ||
1444 | * | ||
1445 | * This function updates the DAI link format for all DAIs connected to the DAI | ||
1446 | * link for the specified runtime. | ||
1447 | * | ||
1448 | * Note: For setups with a static format set the dai_fmt field in the | ||
1449 | * corresponding snd_dai_link struct instead of using this function. | ||
1450 | * | ||
1451 | * Returns 0 on success, otherwise a negative error code. | ||
1452 | */ | ||
1453 | int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, | ||
1454 | unsigned int dai_fmt) | ||
1455 | { | ||
1456 | struct snd_soc_dai **codec_dais = rtd->codec_dais; | ||
1457 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
1458 | unsigned int i; | ||
1459 | int ret; | ||
1460 | |||
1461 | for (i = 0; i < rtd->num_codecs; i++) { | ||
1462 | struct snd_soc_dai *codec_dai = codec_dais[i]; | ||
1463 | |||
1464 | ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt); | ||
1465 | if (ret != 0 && ret != -ENOTSUPP) { | ||
1466 | dev_warn(codec_dai->dev, | ||
1467 | "ASoC: Failed to set DAI format: %d\n", ret); | ||
1468 | return ret; | ||
1469 | } | ||
1470 | } | ||
1471 | |||
1472 | /* Flip the polarity for the "CPU" end of a CODEC<->CODEC link */ | ||
1473 | if (cpu_dai->codec) { | ||
1474 | unsigned int inv_dai_fmt; | ||
1475 | |||
1476 | inv_dai_fmt = dai_fmt & ~SND_SOC_DAIFMT_MASTER_MASK; | ||
1477 | switch (dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1478 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1479 | inv_dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; | ||
1480 | break; | ||
1481 | case SND_SOC_DAIFMT_CBM_CFS: | ||
1482 | inv_dai_fmt |= SND_SOC_DAIFMT_CBS_CFM; | ||
1483 | break; | ||
1484 | case SND_SOC_DAIFMT_CBS_CFM: | ||
1485 | inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFS; | ||
1486 | break; | ||
1487 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1488 | inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; | ||
1489 | break; | ||
1490 | } | ||
1491 | |||
1492 | dai_fmt = inv_dai_fmt; | ||
1493 | } | ||
1494 | |||
1495 | ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt); | ||
1496 | if (ret != 0 && ret != -ENOTSUPP) { | ||
1497 | dev_warn(cpu_dai->dev, | ||
1498 | "ASoC: Failed to set DAI format: %d\n", ret); | ||
1499 | return ret; | ||
1500 | } | ||
1501 | |||
1502 | return 0; | ||
1503 | } | ||
1504 | EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt); | ||
1505 | |||
1430 | static int snd_soc_instantiate_card(struct snd_soc_card *card) | 1506 | static int snd_soc_instantiate_card(struct snd_soc_card *card) |
1431 | { | 1507 | { |
1432 | struct snd_soc_codec *codec; | 1508 | struct snd_soc_codec *codec; |
1433 | struct snd_soc_dai_link *dai_link; | 1509 | int ret, i, order; |
1434 | int ret, i, order, dai_fmt; | ||
1435 | 1510 | ||
1436 | mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); | 1511 | mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); |
1437 | 1512 | ||
@@ -1542,60 +1617,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1542 | card->num_dapm_routes); | 1617 | card->num_dapm_routes); |
1543 | 1618 | ||
1544 | for (i = 0; i < card->num_links; i++) { | 1619 | for (i = 0; i < card->num_links; i++) { |
1545 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | 1620 | if (card->dai_link[i].dai_fmt) |
1546 | dai_link = &card->dai_link[i]; | 1621 | snd_soc_runtime_set_dai_fmt(&card->rtd[i], |
1547 | dai_fmt = dai_link->dai_fmt; | 1622 | card->dai_link[i].dai_fmt); |
1548 | |||
1549 | if (dai_fmt) { | ||
1550 | struct snd_soc_dai **codec_dais = rtd->codec_dais; | ||
1551 | int j; | ||
1552 | |||
1553 | for (j = 0; j < rtd->num_codecs; j++) { | ||
1554 | struct snd_soc_dai *codec_dai = codec_dais[j]; | ||
1555 | |||
1556 | ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt); | ||
1557 | if (ret != 0 && ret != -ENOTSUPP) | ||
1558 | dev_warn(codec_dai->dev, | ||
1559 | "ASoC: Failed to set DAI format: %d\n", | ||
1560 | ret); | ||
1561 | } | ||
1562 | } | ||
1563 | |||
1564 | /* If this is a regular CPU link there will be a platform */ | ||
1565 | if (dai_fmt && | ||
1566 | (dai_link->platform_name || dai_link->platform_of_node)) { | ||
1567 | ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai, | ||
1568 | dai_fmt); | ||
1569 | if (ret != 0 && ret != -ENOTSUPP) | ||
1570 | dev_warn(card->rtd[i].cpu_dai->dev, | ||
1571 | "ASoC: Failed to set DAI format: %d\n", | ||
1572 | ret); | ||
1573 | } else if (dai_fmt) { | ||
1574 | /* Flip the polarity for the "CPU" end */ | ||
1575 | dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK; | ||
1576 | switch (dai_link->dai_fmt & | ||
1577 | SND_SOC_DAIFMT_MASTER_MASK) { | ||
1578 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1579 | dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; | ||
1580 | break; | ||
1581 | case SND_SOC_DAIFMT_CBM_CFS: | ||
1582 | dai_fmt |= SND_SOC_DAIFMT_CBS_CFM; | ||
1583 | break; | ||
1584 | case SND_SOC_DAIFMT_CBS_CFM: | ||
1585 | dai_fmt |= SND_SOC_DAIFMT_CBM_CFS; | ||
1586 | break; | ||
1587 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1588 | dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; | ||
1589 | break; | ||
1590 | } | ||
1591 | |||
1592 | ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai, | ||
1593 | dai_fmt); | ||
1594 | if (ret != 0 && ret != -ENOTSUPP) | ||
1595 | dev_warn(card->rtd[i].cpu_dai->dev, | ||
1596 | "ASoC: Failed to set DAI format: %d\n", | ||
1597 | ret); | ||
1598 | } | ||
1599 | } | 1623 | } |
1600 | 1624 | ||
1601 | snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), | 1625 | snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), |
@@ -1626,9 +1650,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1626 | } | 1650 | } |
1627 | } | 1651 | } |
1628 | 1652 | ||
1629 | if (card->fully_routed) | ||
1630 | snd_soc_dapm_auto_nc_pins(card); | ||
1631 | |||
1632 | snd_soc_dapm_new_widgets(card); | 1653 | snd_soc_dapm_new_widgets(card); |
1633 | 1654 | ||
1634 | ret = snd_card_register(card->snd_card); | 1655 | ret = snd_card_register(card->snd_card); |
@@ -2119,15 +2140,27 @@ static int snd_soc_xlate_tdm_slot_mask(unsigned int slots, | |||
2119 | } | 2140 | } |
2120 | 2141 | ||
2121 | /** | 2142 | /** |
2122 | * snd_soc_dai_set_tdm_slot - configure DAI TDM. | 2143 | * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation |
2123 | * @dai: DAI | 2144 | * @dai: The DAI to configure |
2124 | * @tx_mask: bitmask representing active TX slots. | 2145 | * @tx_mask: bitmask representing active TX slots. |
2125 | * @rx_mask: bitmask representing active RX slots. | 2146 | * @rx_mask: bitmask representing active RX slots. |
2126 | * @slots: Number of slots in use. | 2147 | * @slots: Number of slots in use. |
2127 | * @slot_width: Width in bits for each slot. | 2148 | * @slot_width: Width in bits for each slot. |
2128 | * | 2149 | * |
2129 | * Configures a DAI for TDM operation. Both mask and slots are codec and DAI | 2150 | * This function configures the specified DAI for TDM operation. @slot contains |
2130 | * specific. | 2151 | * the total number of slots of the TDM stream and @slot_with the width of each |
2152 | * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the | ||
2153 | * active slots of the TDM stream for the specified DAI, i.e. which slots the | ||
2154 | * DAI should write to or read from. If a bit is set the corresponding slot is | ||
2155 | * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to | ||
2156 | * the first slot, bit 1 to the second slot and so on. The first active slot | ||
2157 | * maps to the first channel of the DAI, the second active slot to the second | ||
2158 | * channel and so on. | ||
2159 | * | ||
2160 | * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask, | ||
2161 | * @rx_mask and @slot_width will be ignored. | ||
2162 | * | ||
2163 | * Returns 0 on success, a negative error code otherwise. | ||
2131 | */ | 2164 | */ |
2132 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | 2165 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, |
2133 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) | 2166 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) |
@@ -2386,8 +2419,8 @@ int snd_soc_unregister_card(struct snd_soc_card *card) | |||
2386 | card->instantiated = false; | 2419 | card->instantiated = false; |
2387 | snd_soc_dapm_shutdown(card); | 2420 | snd_soc_dapm_shutdown(card); |
2388 | soc_cleanup_card_resources(card); | 2421 | soc_cleanup_card_resources(card); |
2422 | dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name); | ||
2389 | } | 2423 | } |
2390 | dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name); | ||
2391 | 2424 | ||
2392 | return 0; | 2425 | return 0; |
2393 | } | 2426 | } |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c5136bb1f982..b6f88202b8c9 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -517,8 +517,8 @@ static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm, | |||
517 | { | 517 | { |
518 | if (!dapm->component) | 518 | if (!dapm->component) |
519 | return -EIO; | 519 | return -EIO; |
520 | return snd_soc_component_update_bits_async(dapm->component, reg, | 520 | return snd_soc_component_update_bits(dapm->component, reg, |
521 | mask, value); | 521 | mask, value); |
522 | } | 522 | } |
523 | 523 | ||
524 | static int soc_dapm_test_bits(struct snd_soc_dapm_context *dapm, | 524 | static int soc_dapm_test_bits(struct snd_soc_dapm_context *dapm, |
@@ -2127,15 +2127,10 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
2127 | 2127 | ||
2128 | static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); | 2128 | static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); |
2129 | 2129 | ||
2130 | int snd_soc_dapm_sys_add(struct device *dev) | 2130 | struct attribute *soc_dapm_dev_attrs[] = { |
2131 | { | 2131 | &dev_attr_dapm_widget.attr, |
2132 | return device_create_file(dev, &dev_attr_dapm_widget); | 2132 | NULL |
2133 | } | 2133 | }; |
2134 | |||
2135 | static void snd_soc_dapm_sys_remove(struct device *dev) | ||
2136 | { | ||
2137 | device_remove_file(dev, &dev_attr_dapm_widget); | ||
2138 | } | ||
2139 | 2134 | ||
2140 | static void dapm_free_path(struct snd_soc_dapm_path *path) | 2135 | static void dapm_free_path(struct snd_soc_dapm_path *path) |
2141 | { | 2136 | { |
@@ -2279,6 +2274,9 @@ static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w) | |||
2279 | 2274 | ||
2280 | switch (w->id) { | 2275 | switch (w->id) { |
2281 | case snd_soc_dapm_input: | 2276 | case snd_soc_dapm_input: |
2277 | /* On a fully routed card a input is never a source */ | ||
2278 | if (w->dapm->card->fully_routed) | ||
2279 | break; | ||
2282 | w->is_source = 1; | 2280 | w->is_source = 1; |
2283 | list_for_each_entry(p, &w->sources, list_sink) { | 2281 | list_for_each_entry(p, &w->sources, list_sink) { |
2284 | if (p->source->id == snd_soc_dapm_micbias || | 2282 | if (p->source->id == snd_soc_dapm_micbias || |
@@ -2291,6 +2289,9 @@ static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w) | |||
2291 | } | 2289 | } |
2292 | break; | 2290 | break; |
2293 | case snd_soc_dapm_output: | 2291 | case snd_soc_dapm_output: |
2292 | /* On a fully routed card a output is never a sink */ | ||
2293 | if (w->dapm->card->fully_routed) | ||
2294 | break; | ||
2294 | w->is_sink = 1; | 2295 | w->is_sink = 1; |
2295 | list_for_each_entry(p, &w->sinks, list_source) { | 2296 | list_for_each_entry(p, &w->sinks, list_source) { |
2296 | if (p->sink->id == snd_soc_dapm_spk || | 2297 | if (p->sink->id == snd_soc_dapm_spk || |
@@ -3085,16 +3086,24 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3085 | 3086 | ||
3086 | switch (w->id) { | 3087 | switch (w->id) { |
3087 | case snd_soc_dapm_mic: | 3088 | case snd_soc_dapm_mic: |
3088 | case snd_soc_dapm_input: | ||
3089 | w->is_source = 1; | 3089 | w->is_source = 1; |
3090 | w->power_check = dapm_generic_check_power; | 3090 | w->power_check = dapm_generic_check_power; |
3091 | break; | 3091 | break; |
3092 | case snd_soc_dapm_input: | ||
3093 | if (!dapm->card->fully_routed) | ||
3094 | w->is_source = 1; | ||
3095 | w->power_check = dapm_generic_check_power; | ||
3096 | break; | ||
3092 | case snd_soc_dapm_spk: | 3097 | case snd_soc_dapm_spk: |
3093 | case snd_soc_dapm_hp: | 3098 | case snd_soc_dapm_hp: |
3094 | case snd_soc_dapm_output: | ||
3095 | w->is_sink = 1; | 3099 | w->is_sink = 1; |
3096 | w->power_check = dapm_generic_check_power; | 3100 | w->power_check = dapm_generic_check_power; |
3097 | break; | 3101 | break; |
3102 | case snd_soc_dapm_output: | ||
3103 | if (!dapm->card->fully_routed) | ||
3104 | w->is_sink = 1; | ||
3105 | w->power_check = dapm_generic_check_power; | ||
3106 | break; | ||
3098 | case snd_soc_dapm_vmid: | 3107 | case snd_soc_dapm_vmid: |
3099 | case snd_soc_dapm_siggen: | 3108 | case snd_soc_dapm_siggen: |
3100 | w->is_source = 1; | 3109 | w->is_source = 1; |
@@ -3130,8 +3139,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3130 | } | 3139 | } |
3131 | 3140 | ||
3132 | w->dapm = dapm; | 3141 | w->dapm = dapm; |
3133 | if (dapm->component) | ||
3134 | w->codec = dapm->component->codec; | ||
3135 | INIT_LIST_HEAD(&w->sources); | 3142 | INIT_LIST_HEAD(&w->sources); |
3136 | INIT_LIST_HEAD(&w->sinks); | 3143 | INIT_LIST_HEAD(&w->sinks); |
3137 | INIT_LIST_HEAD(&w->list); | 3144 | INIT_LIST_HEAD(&w->list); |
@@ -3809,93 +3816,6 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, | |||
3809 | EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); | 3816 | EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); |
3810 | 3817 | ||
3811 | /** | 3818 | /** |
3812 | * dapm_is_external_path() - Checks if a path is a external path | ||
3813 | * @card: The card the path belongs to | ||
3814 | * @path: The path to check | ||
3815 | * | ||
3816 | * Returns true if the path is either between two different DAPM contexts or | ||
3817 | * between two external pins of the same DAPM context. Otherwise returns | ||
3818 | * false. | ||
3819 | */ | ||
3820 | static bool dapm_is_external_path(struct snd_soc_card *card, | ||
3821 | struct snd_soc_dapm_path *path) | ||
3822 | { | ||
3823 | dev_dbg(card->dev, | ||
3824 | "... Path %s(id:%d dapm:%p) - %s(id:%d dapm:%p)\n", | ||
3825 | path->source->name, path->source->id, path->source->dapm, | ||
3826 | path->sink->name, path->sink->id, path->sink->dapm); | ||
3827 | |||
3828 | /* Connection between two different DAPM contexts */ | ||
3829 | if (path->source->dapm != path->sink->dapm) | ||
3830 | return true; | ||
3831 | |||
3832 | /* Loopback connection from external pin to external pin */ | ||
3833 | if (path->sink->id == snd_soc_dapm_input) { | ||
3834 | switch (path->source->id) { | ||
3835 | case snd_soc_dapm_output: | ||
3836 | case snd_soc_dapm_micbias: | ||
3837 | return true; | ||
3838 | default: | ||
3839 | break; | ||
3840 | } | ||
3841 | } | ||
3842 | |||
3843 | return false; | ||
3844 | } | ||
3845 | |||
3846 | static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card, | ||
3847 | struct snd_soc_dapm_widget *w) | ||
3848 | { | ||
3849 | struct snd_soc_dapm_path *p; | ||
3850 | |||
3851 | list_for_each_entry(p, &w->sources, list_sink) { | ||
3852 | if (dapm_is_external_path(card, p)) | ||
3853 | return true; | ||
3854 | } | ||
3855 | |||
3856 | list_for_each_entry(p, &w->sinks, list_source) { | ||
3857 | if (dapm_is_external_path(card, p)) | ||
3858 | return true; | ||
3859 | } | ||
3860 | |||
3861 | return false; | ||
3862 | } | ||
3863 | |||
3864 | /** | ||
3865 | * snd_soc_dapm_auto_nc_pins - call snd_soc_dapm_nc_pin for unused pins | ||
3866 | * @card: The card whose pins should be processed | ||
3867 | * | ||
3868 | * Automatically call snd_soc_dapm_nc_pin() for any external pins in the card | ||
3869 | * which are unused. Pins are used if they are connected externally to a | ||
3870 | * component, whether that be to some other device, or a loop-back connection to | ||
3871 | * the component itself. | ||
3872 | */ | ||
3873 | void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card) | ||
3874 | { | ||
3875 | struct snd_soc_dapm_widget *w; | ||
3876 | |||
3877 | dev_dbg(card->dev, "ASoC: Auto NC: DAPMs: card:%p\n", &card->dapm); | ||
3878 | |||
3879 | list_for_each_entry(w, &card->widgets, list) { | ||
3880 | switch (w->id) { | ||
3881 | case snd_soc_dapm_input: | ||
3882 | case snd_soc_dapm_output: | ||
3883 | case snd_soc_dapm_micbias: | ||
3884 | dev_dbg(card->dev, "ASoC: Auto NC: Checking widget %s\n", | ||
3885 | w->name); | ||
3886 | if (!snd_soc_dapm_widget_in_card_paths(card, w)) { | ||
3887 | dev_dbg(card->dev, | ||
3888 | "... Not in map; disabling\n"); | ||
3889 | snd_soc_dapm_nc_pin(w->dapm, w->name); | ||
3890 | } | ||
3891 | break; | ||
3892 | default: | ||
3893 | break; | ||
3894 | } | ||
3895 | } | ||
3896 | } | ||
3897 | |||
3898 | /** | ||
3899 | * snd_soc_dapm_free - free dapm resources | 3819 | * snd_soc_dapm_free - free dapm resources |
3900 | * @dapm: DAPM context | 3820 | * @dapm: DAPM context |
3901 | * | 3821 | * |
@@ -3903,7 +3823,6 @@ void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card) | |||
3903 | */ | 3823 | */ |
3904 | void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm) | 3824 | void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm) |
3905 | { | 3825 | { |
3906 | snd_soc_dapm_sys_remove(dapm->dev); | ||
3907 | dapm_debugfs_cleanup(dapm); | 3826 | dapm_debugfs_cleanup(dapm); |
3908 | dapm_free_widgets(dapm); | 3827 | dapm_free_widgets(dapm); |
3909 | list_del(&dapm->list); | 3828 | list_del(&dapm->list); |
diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c index 057e5ef7dcce..a57921eeee81 100644 --- a/sound/soc/soc-devres.c +++ b/sound/soc/soc-devres.c | |||
@@ -60,7 +60,7 @@ static void devm_platform_release(struct device *dev, void *res) | |||
60 | /** | 60 | /** |
61 | * devm_snd_soc_register_platform - resource managed platform registration | 61 | * devm_snd_soc_register_platform - resource managed platform registration |
62 | * @dev: Device used to manage platform | 62 | * @dev: Device used to manage platform |
63 | * @platform: platform to register | 63 | * @platform_drv: platform to register |
64 | * | 64 | * |
65 | * Register a platform driver with automatic unregistration when the device is | 65 | * Register a platform driver with automatic unregistration when the device is |
66 | * unregistered. | 66 | * unregistered. |
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index b329b84bc5af..c9917ca5de1a 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -151,7 +151,7 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea | |||
151 | hw.info |= SNDRV_PCM_INFO_BATCH; | 151 | hw.info |= SNDRV_PCM_INFO_BATCH; |
152 | 152 | ||
153 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 153 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
154 | addr_widths = dma_caps.dstn_addr_widths; | 154 | addr_widths = dma_caps.dst_addr_widths; |
155 | else | 155 | else |
156 | addr_widths = dma_caps.src_addr_widths; | 156 | addr_widths = dma_caps.src_addr_widths; |
157 | } | 157 | } |
@@ -200,11 +200,6 @@ static int dmaengine_pcm_open(struct snd_pcm_substream *substream) | |||
200 | return snd_dmaengine_pcm_open(substream, chan); | 200 | return snd_dmaengine_pcm_open(substream, chan); |
201 | } | 201 | } |
202 | 202 | ||
203 | static void dmaengine_pcm_free(struct snd_pcm *pcm) | ||
204 | { | ||
205 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
206 | } | ||
207 | |||
208 | static struct dma_chan *dmaengine_pcm_compat_request_channel( | 203 | static struct dma_chan *dmaengine_pcm_compat_request_channel( |
209 | struct snd_soc_pcm_runtime *rtd, | 204 | struct snd_soc_pcm_runtime *rtd, |
210 | struct snd_pcm_substream *substream) | 205 | struct snd_pcm_substream *substream) |
@@ -283,8 +278,7 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
283 | if (!pcm->chan[i]) { | 278 | if (!pcm->chan[i]) { |
284 | dev_err(rtd->platform->dev, | 279 | dev_err(rtd->platform->dev, |
285 | "Missing dma channel for stream: %d\n", i); | 280 | "Missing dma channel for stream: %d\n", i); |
286 | ret = -EINVAL; | 281 | return -EINVAL; |
287 | goto err_free; | ||
288 | } | 282 | } |
289 | 283 | ||
290 | ret = snd_pcm_lib_preallocate_pages(substream, | 284 | ret = snd_pcm_lib_preallocate_pages(substream, |
@@ -293,7 +287,7 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
293 | prealloc_buffer_size, | 287 | prealloc_buffer_size, |
294 | max_buffer_size); | 288 | max_buffer_size); |
295 | if (ret) | 289 | if (ret) |
296 | goto err_free; | 290 | return ret; |
297 | 291 | ||
298 | /* | 292 | /* |
299 | * This will only return false if we know for sure that at least | 293 | * This will only return false if we know for sure that at least |
@@ -307,10 +301,6 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
307 | } | 301 | } |
308 | 302 | ||
309 | return 0; | 303 | return 0; |
310 | |||
311 | err_free: | ||
312 | dmaengine_pcm_free(rtd->pcm); | ||
313 | return ret; | ||
314 | } | 304 | } |
315 | 305 | ||
316 | static snd_pcm_uframes_t dmaengine_pcm_pointer( | 306 | static snd_pcm_uframes_t dmaengine_pcm_pointer( |
@@ -341,7 +331,6 @@ static const struct snd_soc_platform_driver dmaengine_pcm_platform = { | |||
341 | }, | 331 | }, |
342 | .ops = &dmaengine_pcm_ops, | 332 | .ops = &dmaengine_pcm_ops, |
343 | .pcm_new = dmaengine_pcm_new, | 333 | .pcm_new = dmaengine_pcm_new, |
344 | .pcm_free = dmaengine_pcm_free, | ||
345 | }; | 334 | }; |
346 | 335 | ||
347 | static const char * const dmaengine_pcm_dma_channel_names[] = { | 336 | static const char * const dmaengine_pcm_dma_channel_names[] = { |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index eb87d96e2cf0..6b0136e7cb88 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -301,34 +301,18 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) | |||
301 | return symmetry; | 301 | return symmetry; |
302 | } | 302 | } |
303 | 303 | ||
304 | /* | ||
305 | * List of sample sizes that might go over the bus for parameter | ||
306 | * application. There ought to be a wildcard sample size for things | ||
307 | * like the DAC/ADC resolution to use but there isn't right now. | ||
308 | */ | ||
309 | static int sample_sizes[] = { | ||
310 | 24, 32, | ||
311 | }; | ||
312 | |||
313 | static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits) | 304 | static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits) |
314 | { | 305 | { |
315 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 306 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
316 | int ret, i; | 307 | int ret; |
317 | 308 | ||
318 | if (!bits) | 309 | if (!bits) |
319 | return; | 310 | return; |
320 | 311 | ||
321 | for (i = 0; i < ARRAY_SIZE(sample_sizes); i++) { | 312 | ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0, 0, bits); |
322 | if (bits >= sample_sizes[i]) | 313 | if (ret != 0) |
323 | continue; | 314 | dev_warn(rtd->dev, "ASoC: Failed to set MSB %d: %d\n", |
324 | 315 | bits, ret); | |
325 | ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0, | ||
326 | sample_sizes[i], bits); | ||
327 | if (ret != 0) | ||
328 | dev_warn(rtd->dev, | ||
329 | "ASoC: Failed to set MSB %d/%d: %d\n", | ||
330 | bits, sample_sizes[i], ret); | ||
331 | } | ||
332 | } | 316 | } |
333 | 317 | ||
334 | static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) | 318 | static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) |
@@ -746,7 +730,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
746 | codec_dai); | 730 | codec_dai); |
747 | if (ret < 0) { | 731 | if (ret < 0) { |
748 | dev_err(codec_dai->dev, | 732 | dev_err(codec_dai->dev, |
749 | "ASoC: DAI prepare error: %d\n", ret); | 733 | "ASoC: codec DAI prepare error: %d\n", |
734 | ret); | ||
750 | goto out; | 735 | goto out; |
751 | } | 736 | } |
752 | } | 737 | } |
@@ -755,8 +740,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
755 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->prepare) { | 740 | if (cpu_dai->driver->ops && cpu_dai->driver->ops->prepare) { |
756 | ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); | 741 | ret = cpu_dai->driver->ops->prepare(substream, cpu_dai); |
757 | if (ret < 0) { | 742 | if (ret < 0) { |
758 | dev_err(cpu_dai->dev, "ASoC: DAI prepare error: %d\n", | 743 | dev_err(cpu_dai->dev, |
759 | ret); | 744 | "ASoC: cpu DAI prepare error: %d\n", ret); |
760 | goto out; | 745 | goto out; |
761 | } | 746 | } |
762 | } | 747 | } |
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 31198cf7f88d..a6768f832c6f 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig | |||
@@ -128,3 +128,13 @@ config SND_SOC_TEGRA_MAX98090 | |||
128 | help | 128 | help |
129 | Say Y or M here if you want to add support for SoC audio on Tegra | 129 | Say Y or M here if you want to add support for SoC audio on Tegra |
130 | boards using the MAX98090 codec, such as Venice2. | 130 | boards using the MAX98090 codec, such as Venice2. |
131 | |||
132 | config SND_SOC_TEGRA_RT5677 | ||
133 | tristate "SoC Audio support for Tegra boards using a RT5677 codec" | ||
134 | depends on SND_SOC_TEGRA && I2C && GPIOLIB | ||
135 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC | ||
136 | select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC | ||
137 | select SND_SOC_RT5677 | ||
138 | help | ||
139 | Say Y or M here if you want to add support for SoC audio on Tegra | ||
140 | boards using the RT5677 codec, such as Ryu. | ||
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index 5ae588cd96c4..9171655ad843 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile | |||
@@ -19,6 +19,7 @@ obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o | |||
19 | 19 | ||
20 | # Tegra machine Support | 20 | # Tegra machine Support |
21 | snd-soc-tegra-rt5640-objs := tegra_rt5640.o | 21 | snd-soc-tegra-rt5640-objs := tegra_rt5640.o |
22 | snd-soc-tegra-rt5677-objs := tegra_rt5677.o | ||
22 | snd-soc-tegra-wm8753-objs := tegra_wm8753.o | 23 | snd-soc-tegra-wm8753-objs := tegra_wm8753.o |
23 | snd-soc-tegra-wm8903-objs := tegra_wm8903.o | 24 | snd-soc-tegra-wm8903-objs := tegra_wm8903.o |
24 | snd-soc-tegra-wm9712-objs := tegra_wm9712.o | 25 | snd-soc-tegra-wm9712-objs := tegra_wm9712.o |
@@ -27,6 +28,7 @@ snd-soc-tegra-alc5632-objs := tegra_alc5632.o | |||
27 | snd-soc-tegra-max98090-objs := tegra_max98090.o | 28 | snd-soc-tegra-max98090-objs := tegra_max98090.o |
28 | 29 | ||
29 | obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o | 30 | obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o |
31 | obj-$(CONFIG_SND_SOC_TEGRA_RT5677) += snd-soc-tegra-rt5677.o | ||
30 | obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o | 32 | obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o |
31 | obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o | 33 | obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o |
32 | obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o | 34 | obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o |
diff --git a/sound/soc/tegra/tegra_rt5677.c b/sound/soc/tegra/tegra_rt5677.c new file mode 100644 index 000000000000..e4cf978a6e3a --- /dev/null +++ b/sound/soc/tegra/tegra_rt5677.c | |||
@@ -0,0 +1,347 @@ | |||
1 | /* | ||
2 | * tegra_rt5677.c - Tegra machine ASoC driver for boards using RT5677 codec. | ||
3 | * | ||
4 | * Copyright (c) 2014, The Chromium OS Authors. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * Based on code copyright/by: | ||
19 | * | ||
20 | * Copyright (C) 2010-2012 - NVIDIA, Inc. | ||
21 | * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net> | ||
22 | * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd. | ||
23 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/gpio.h> | ||
30 | #include <linux/of_gpio.h> | ||
31 | |||
32 | #include <sound/core.h> | ||
33 | #include <sound/jack.h> | ||
34 | #include <sound/pcm.h> | ||
35 | #include <sound/pcm_params.h> | ||
36 | #include <sound/soc.h> | ||
37 | |||
38 | #include "../codecs/rt5677.h" | ||
39 | |||
40 | #include "tegra_asoc_utils.h" | ||
41 | |||
42 | #define DRV_NAME "tegra-snd-rt5677" | ||
43 | |||
44 | struct tegra_rt5677 { | ||
45 | struct tegra_asoc_utils_data util_data; | ||
46 | int gpio_hp_det; | ||
47 | int gpio_hp_en; | ||
48 | int gpio_mic_present; | ||
49 | int gpio_dmic_clk_en; | ||
50 | }; | ||
51 | |||
52 | static int tegra_rt5677_asoc_hw_params(struct snd_pcm_substream *substream, | ||
53 | struct snd_pcm_hw_params *params) | ||
54 | { | ||
55 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
56 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
57 | struct snd_soc_card *card = rtd->card; | ||
58 | struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(card); | ||
59 | int srate, mclk, err; | ||
60 | |||
61 | srate = params_rate(params); | ||
62 | mclk = 256 * srate; | ||
63 | |||
64 | err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); | ||
65 | if (err < 0) { | ||
66 | dev_err(card->dev, "Can't configure clocks\n"); | ||
67 | return err; | ||
68 | } | ||
69 | |||
70 | err = snd_soc_dai_set_sysclk(codec_dai, RT5677_SCLK_S_MCLK, mclk, | ||
71 | SND_SOC_CLOCK_IN); | ||
72 | if (err < 0) { | ||
73 | dev_err(card->dev, "codec_dai clock not set\n"); | ||
74 | return err; | ||
75 | } | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int tegra_rt5677_event_hp(struct snd_soc_dapm_widget *w, | ||
81 | struct snd_kcontrol *k, int event) | ||
82 | { | ||
83 | struct snd_soc_dapm_context *dapm = w->dapm; | ||
84 | struct snd_soc_card *card = dapm->card; | ||
85 | struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(card); | ||
86 | |||
87 | if (!gpio_is_valid(machine->gpio_hp_en)) | ||
88 | return 0; | ||
89 | |||
90 | gpio_set_value_cansleep(machine->gpio_hp_en, | ||
91 | SND_SOC_DAPM_EVENT_ON(event)); | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static struct snd_soc_ops tegra_rt5677_ops = { | ||
97 | .hw_params = tegra_rt5677_asoc_hw_params, | ||
98 | }; | ||
99 | |||
100 | static struct snd_soc_jack tegra_rt5677_hp_jack; | ||
101 | |||
102 | static struct snd_soc_jack_pin tegra_rt5677_hp_jack_pins = { | ||
103 | .pin = "Headphone", | ||
104 | .mask = SND_JACK_HEADPHONE, | ||
105 | }; | ||
106 | static struct snd_soc_jack_gpio tegra_rt5677_hp_jack_gpio = { | ||
107 | .name = "Headphone detection", | ||
108 | .report = SND_JACK_HEADPHONE, | ||
109 | .debounce_time = 150, | ||
110 | }; | ||
111 | |||
112 | static struct snd_soc_jack tegra_rt5677_mic_jack; | ||
113 | |||
114 | static struct snd_soc_jack_pin tegra_rt5677_mic_jack_pins = { | ||
115 | .pin = "Headset Mic", | ||
116 | .mask = SND_JACK_MICROPHONE, | ||
117 | }; | ||
118 | |||
119 | static struct snd_soc_jack_gpio tegra_rt5677_mic_jack_gpio = { | ||
120 | .name = "Headset Mic detection", | ||
121 | .report = SND_JACK_MICROPHONE, | ||
122 | .debounce_time = 150, | ||
123 | .invert = 1 | ||
124 | }; | ||
125 | |||
126 | static const struct snd_soc_dapm_widget tegra_rt5677_dapm_widgets[] = { | ||
127 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
128 | SND_SOC_DAPM_HP("Headphone", tegra_rt5677_event_hp), | ||
129 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
130 | SND_SOC_DAPM_MIC("Internal Mic 1", NULL), | ||
131 | SND_SOC_DAPM_MIC("Internal Mic 2", NULL), | ||
132 | }; | ||
133 | |||
134 | static const struct snd_kcontrol_new tegra_rt5677_controls[] = { | ||
135 | SOC_DAPM_PIN_SWITCH("Speaker"), | ||
136 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
137 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
138 | SOC_DAPM_PIN_SWITCH("Internal Mic 1"), | ||
139 | SOC_DAPM_PIN_SWITCH("Internal Mic 2"), | ||
140 | }; | ||
141 | |||
142 | static int tegra_rt5677_asoc_init(struct snd_soc_pcm_runtime *rtd) | ||
143 | { | ||
144 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
145 | struct snd_soc_codec *codec = codec_dai->codec; | ||
146 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
147 | struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(rtd->card); | ||
148 | |||
149 | snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, | ||
150 | &tegra_rt5677_hp_jack); | ||
151 | snd_soc_jack_add_pins(&tegra_rt5677_hp_jack, 1, | ||
152 | &tegra_rt5677_hp_jack_pins); | ||
153 | |||
154 | if (gpio_is_valid(machine->gpio_hp_det)) { | ||
155 | tegra_rt5677_hp_jack_gpio.gpio = machine->gpio_hp_det; | ||
156 | snd_soc_jack_add_gpios(&tegra_rt5677_hp_jack, 1, | ||
157 | &tegra_rt5677_hp_jack_gpio); | ||
158 | } | ||
159 | |||
160 | |||
161 | snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, | ||
162 | &tegra_rt5677_mic_jack); | ||
163 | snd_soc_jack_add_pins(&tegra_rt5677_mic_jack, 1, | ||
164 | &tegra_rt5677_mic_jack_pins); | ||
165 | |||
166 | if (gpio_is_valid(machine->gpio_mic_present)) { | ||
167 | tegra_rt5677_mic_jack_gpio.gpio = machine->gpio_mic_present; | ||
168 | snd_soc_jack_add_gpios(&tegra_rt5677_mic_jack, 1, | ||
169 | &tegra_rt5677_mic_jack_gpio); | ||
170 | } | ||
171 | |||
172 | snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static int tegra_rt5677_card_remove(struct snd_soc_card *card) | ||
178 | { | ||
179 | struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(card); | ||
180 | |||
181 | if (gpio_is_valid(machine->gpio_hp_det)) { | ||
182 | snd_soc_jack_free_gpios(&tegra_rt5677_hp_jack, 1, | ||
183 | &tegra_rt5677_hp_jack_gpio); | ||
184 | } | ||
185 | |||
186 | if (gpio_is_valid(machine->gpio_mic_present)) { | ||
187 | snd_soc_jack_free_gpios(&tegra_rt5677_mic_jack, 1, | ||
188 | &tegra_rt5677_mic_jack_gpio); | ||
189 | } | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static struct snd_soc_dai_link tegra_rt5677_dai = { | ||
195 | .name = "RT5677", | ||
196 | .stream_name = "RT5677 PCM", | ||
197 | .codec_dai_name = "rt5677-aif1", | ||
198 | .init = tegra_rt5677_asoc_init, | ||
199 | .ops = &tegra_rt5677_ops, | ||
200 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
201 | SND_SOC_DAIFMT_CBS_CFS, | ||
202 | }; | ||
203 | |||
204 | static struct snd_soc_card snd_soc_tegra_rt5677 = { | ||
205 | .name = "tegra-rt5677", | ||
206 | .owner = THIS_MODULE, | ||
207 | .remove = tegra_rt5677_card_remove, | ||
208 | .dai_link = &tegra_rt5677_dai, | ||
209 | .num_links = 1, | ||
210 | .controls = tegra_rt5677_controls, | ||
211 | .num_controls = ARRAY_SIZE(tegra_rt5677_controls), | ||
212 | .dapm_widgets = tegra_rt5677_dapm_widgets, | ||
213 | .num_dapm_widgets = ARRAY_SIZE(tegra_rt5677_dapm_widgets), | ||
214 | .fully_routed = true, | ||
215 | }; | ||
216 | |||
217 | static int tegra_rt5677_probe(struct platform_device *pdev) | ||
218 | { | ||
219 | struct device_node *np = pdev->dev.of_node; | ||
220 | struct snd_soc_card *card = &snd_soc_tegra_rt5677; | ||
221 | struct tegra_rt5677 *machine; | ||
222 | int ret; | ||
223 | |||
224 | machine = devm_kzalloc(&pdev->dev, | ||
225 | sizeof(struct tegra_rt5677), GFP_KERNEL); | ||
226 | if (!machine) | ||
227 | return -ENOMEM; | ||
228 | |||
229 | card->dev = &pdev->dev; | ||
230 | platform_set_drvdata(pdev, card); | ||
231 | snd_soc_card_set_drvdata(card, machine); | ||
232 | |||
233 | machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); | ||
234 | if (machine->gpio_hp_det == -EPROBE_DEFER) | ||
235 | return -EPROBE_DEFER; | ||
236 | |||
237 | machine->gpio_mic_present = of_get_named_gpio(np, | ||
238 | "nvidia,mic-present-gpios", 0); | ||
239 | if (machine->gpio_mic_present == -EPROBE_DEFER) | ||
240 | return -EPROBE_DEFER; | ||
241 | |||
242 | machine->gpio_hp_en = of_get_named_gpio(np, "nvidia,hp-en-gpios", 0); | ||
243 | if (machine->gpio_hp_en == -EPROBE_DEFER) | ||
244 | return -EPROBE_DEFER; | ||
245 | if (gpio_is_valid(machine->gpio_hp_en)) { | ||
246 | ret = devm_gpio_request_one(&pdev->dev, machine->gpio_hp_en, | ||
247 | GPIOF_OUT_INIT_LOW, "hp_en"); | ||
248 | if (ret) { | ||
249 | dev_err(card->dev, "cannot get hp_en gpio\n"); | ||
250 | return ret; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | machine->gpio_dmic_clk_en = of_get_named_gpio(np, | ||
255 | "nvidia,dmic-clk-en-gpios", 0); | ||
256 | if (machine->gpio_dmic_clk_en == -EPROBE_DEFER) | ||
257 | return -EPROBE_DEFER; | ||
258 | if (gpio_is_valid(machine->gpio_dmic_clk_en)) { | ||
259 | ret = devm_gpio_request_one(&pdev->dev, | ||
260 | machine->gpio_dmic_clk_en, | ||
261 | GPIOF_OUT_INIT_HIGH, "dmic_clk_en"); | ||
262 | if (ret) { | ||
263 | dev_err(card->dev, "cannot get dmic_clk_en gpio\n"); | ||
264 | return ret; | ||
265 | } | ||
266 | } | ||
267 | |||
268 | ret = snd_soc_of_parse_card_name(card, "nvidia,model"); | ||
269 | if (ret) | ||
270 | goto err; | ||
271 | |||
272 | ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); | ||
273 | if (ret) | ||
274 | goto err; | ||
275 | |||
276 | tegra_rt5677_dai.codec_of_node = of_parse_phandle(np, | ||
277 | "nvidia,audio-codec", 0); | ||
278 | if (!tegra_rt5677_dai.codec_of_node) { | ||
279 | dev_err(&pdev->dev, | ||
280 | "Property 'nvidia,audio-codec' missing or invalid\n"); | ||
281 | ret = -EINVAL; | ||
282 | goto err; | ||
283 | } | ||
284 | |||
285 | tegra_rt5677_dai.cpu_of_node = of_parse_phandle(np, | ||
286 | "nvidia,i2s-controller", 0); | ||
287 | if (!tegra_rt5677_dai.cpu_of_node) { | ||
288 | dev_err(&pdev->dev, | ||
289 | "Property 'nvidia,i2s-controller' missing or invalid\n"); | ||
290 | ret = -EINVAL; | ||
291 | goto err; | ||
292 | } | ||
293 | tegra_rt5677_dai.platform_of_node = tegra_rt5677_dai.cpu_of_node; | ||
294 | |||
295 | ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); | ||
296 | if (ret) | ||
297 | goto err; | ||
298 | |||
299 | ret = snd_soc_register_card(card); | ||
300 | if (ret) { | ||
301 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", | ||
302 | ret); | ||
303 | goto err_fini_utils; | ||
304 | } | ||
305 | |||
306 | return 0; | ||
307 | |||
308 | err_fini_utils: | ||
309 | tegra_asoc_utils_fini(&machine->util_data); | ||
310 | err: | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | static int tegra_rt5677_remove(struct platform_device *pdev) | ||
315 | { | ||
316 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
317 | struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(card); | ||
318 | |||
319 | snd_soc_unregister_card(card); | ||
320 | |||
321 | tegra_asoc_utils_fini(&machine->util_data); | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static const struct of_device_id tegra_rt5677_of_match[] = { | ||
327 | { .compatible = "nvidia,tegra-audio-rt5677", }, | ||
328 | {}, | ||
329 | }; | ||
330 | |||
331 | static struct platform_driver tegra_rt5677_driver = { | ||
332 | .driver = { | ||
333 | .name = DRV_NAME, | ||
334 | .owner = THIS_MODULE, | ||
335 | .pm = &snd_soc_pm_ops, | ||
336 | .of_match_table = tegra_rt5677_of_match, | ||
337 | }, | ||
338 | .probe = tegra_rt5677_probe, | ||
339 | .remove = tegra_rt5677_remove, | ||
340 | }; | ||
341 | module_platform_driver(tegra_rt5677_driver); | ||
342 | |||
343 | MODULE_AUTHOR("Anatol Pomozov <anatol@google.com>"); | ||
344 | MODULE_DESCRIPTION("Tegra+RT5677 machine ASoC driver"); | ||
345 | MODULE_LICENSE("GPL v2"); | ||
346 | MODULE_ALIAS("platform:" DRV_NAME); | ||
347 | MODULE_DEVICE_TABLE(of, tegra_rt5677_of_match); | ||
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index 070e44e251ce..88eacfd83da6 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c | |||
@@ -282,11 +282,6 @@ static struct snd_pcm_ops txx9aclc_pcm_ops = { | |||
282 | .pointer = txx9aclc_pcm_pointer, | 282 | .pointer = txx9aclc_pcm_pointer, |
283 | }; | 283 | }; |
284 | 284 | ||
285 | static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm) | ||
286 | { | ||
287 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
288 | } | ||
289 | |||
290 | static int txx9aclc_pcm_new(struct snd_soc_pcm_runtime *rtd) | 285 | static int txx9aclc_pcm_new(struct snd_soc_pcm_runtime *rtd) |
291 | { | 286 | { |
292 | struct snd_card *card = rtd->card->snd_card; | 287 | struct snd_card *card = rtd->card->snd_card; |
@@ -412,7 +407,6 @@ static struct snd_soc_platform_driver txx9aclc_soc_platform = { | |||
412 | .remove = txx9aclc_pcm_remove, | 407 | .remove = txx9aclc_pcm_remove, |
413 | .ops = &txx9aclc_pcm_ops, | 408 | .ops = &txx9aclc_pcm_ops, |
414 | .pcm_new = txx9aclc_pcm_new, | 409 | .pcm_new = txx9aclc_pcm_new, |
415 | .pcm_free = txx9aclc_pcm_free_dma_buffers, | ||
416 | }; | 410 | }; |
417 | 411 | ||
418 | static int txx9aclc_soc_platform_probe(struct platform_device *pdev) | 412 | static int txx9aclc_soc_platform_probe(struct platform_device *pdev) |
diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c index be4f1ac7cd5e..aa65370db82a 100644 --- a/sound/soc/ux500/mop500_ab8500.c +++ b/sound/soc/ux500/mop500_ab8500.c | |||
@@ -290,21 +290,9 @@ static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, | |||
290 | SND_SOC_DAIFMT_GATED; | 290 | SND_SOC_DAIFMT_GATED; |
291 | } | 291 | } |
292 | 292 | ||
293 | ret = snd_soc_dai_set_fmt(codec_dai, fmt); | 293 | ret = snd_soc_runtime_set_dai_fmt(rtd, fmt); |
294 | if (ret < 0) { | 294 | if (ret) |
295 | dev_err(dev, | ||
296 | "%s: ERROR: snd_soc_dai_set_fmt failed for codec_dai (ret = %d)!\n", | ||
297 | __func__, ret); | ||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | ret = snd_soc_dai_set_fmt(cpu_dai, fmt); | ||
302 | if (ret < 0) { | ||
303 | dev_err(dev, | ||
304 | "%s: ERROR: snd_soc_dai_set_fmt failed for cpu_dai (ret = %d)!\n", | ||
305 | __func__, ret); | ||
306 | return ret; | 295 | return ret; |
307 | } | ||
308 | 296 | ||
309 | /* Setup TDM-slots */ | 297 | /* Setup TDM-slots */ |
310 | 298 | ||
diff --git a/sound/soc/xtensa/Kconfig b/sound/soc/xtensa/Kconfig new file mode 100644 index 000000000000..c201beb36de6 --- /dev/null +++ b/sound/soc/xtensa/Kconfig | |||
@@ -0,0 +1,7 @@ | |||
1 | config SND_SOC_XTFPGA_I2S | ||
2 | tristate "XTFPGA I2S master" | ||
3 | select REGMAP_MMIO | ||
4 | help | ||
5 | Say Y or M if you want to add support for codecs attached to the | ||
6 | I2S interface on XTFPGA daughter board. You will also need to select | ||
7 | the drivers for the rest of XTFPGA audio subsystem. | ||
diff --git a/sound/soc/xtensa/Makefile b/sound/soc/xtensa/Makefile new file mode 100644 index 000000000000..15efbf914226 --- /dev/null +++ b/sound/soc/xtensa/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | snd-soc-xtfpga-i2s-objs := xtfpga-i2s.o | ||
2 | |||
3 | obj-$(CONFIG_SND_SOC_XTFPGA_I2S) += snd-soc-xtfpga-i2s.o | ||
diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c new file mode 100644 index 000000000000..1cfb19e12949 --- /dev/null +++ b/sound/soc/xtensa/xtfpga-i2s.c | |||
@@ -0,0 +1,675 @@ | |||
1 | /* | ||
2 | * Xtfpga I2S controller driver | ||
3 | * | ||
4 | * Copyright (c) 2014 Cadence Design Systems Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/clk.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/pm_runtime.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | #include <sound/soc.h> | ||
19 | |||
20 | #define DRV_NAME "xtfpga-i2s" | ||
21 | |||
22 | #define XTFPGA_I2S_VERSION 0x00 | ||
23 | #define XTFPGA_I2S_CONFIG 0x04 | ||
24 | #define XTFPGA_I2S_INT_MASK 0x08 | ||
25 | #define XTFPGA_I2S_INT_STATUS 0x0c | ||
26 | #define XTFPGA_I2S_CHAN0_DATA 0x10 | ||
27 | #define XTFPGA_I2S_CHAN1_DATA 0x14 | ||
28 | #define XTFPGA_I2S_CHAN2_DATA 0x18 | ||
29 | #define XTFPGA_I2S_CHAN3_DATA 0x1c | ||
30 | |||
31 | #define XTFPGA_I2S_CONFIG_TX_ENABLE 0x1 | ||
32 | #define XTFPGA_I2S_CONFIG_INT_ENABLE 0x2 | ||
33 | #define XTFPGA_I2S_CONFIG_LEFT 0x4 | ||
34 | #define XTFPGA_I2S_CONFIG_RATIO_BASE 8 | ||
35 | #define XTFPGA_I2S_CONFIG_RATIO_MASK 0x0000ff00 | ||
36 | #define XTFPGA_I2S_CONFIG_RES_BASE 16 | ||
37 | #define XTFPGA_I2S_CONFIG_RES_MASK 0x003f0000 | ||
38 | #define XTFPGA_I2S_CONFIG_LEVEL_BASE 24 | ||
39 | #define XTFPGA_I2S_CONFIG_LEVEL_MASK 0x0f000000 | ||
40 | #define XTFPGA_I2S_CONFIG_CHANNEL_BASE 28 | ||
41 | |||
42 | #define XTFPGA_I2S_INT_UNDERRUN 0x1 | ||
43 | #define XTFPGA_I2S_INT_LEVEL 0x2 | ||
44 | #define XTFPGA_I2S_INT_VALID 0x3 | ||
45 | |||
46 | #define XTFPGA_I2S_FIFO_SIZE 8192 | ||
47 | |||
48 | /* | ||
49 | * I2S controller operation: | ||
50 | * | ||
51 | * Enabling TX: output 1 period of zeros (starting with left channel) | ||
52 | * and then queued data. | ||
53 | * | ||
54 | * Level status and interrupt: whenever FIFO level is below FIFO trigger, | ||
55 | * level status is 1 and an IRQ is asserted (if enabled). | ||
56 | * | ||
57 | * Underrun status and interrupt: whenever FIFO is empty, underrun status | ||
58 | * is 1 and an IRQ is asserted (if enabled). | ||
59 | */ | ||
60 | struct xtfpga_i2s { | ||
61 | struct device *dev; | ||
62 | struct clk *clk; | ||
63 | struct regmap *regmap; | ||
64 | void __iomem *regs; | ||
65 | |||
66 | /* current playback substream. NULL if not playing. | ||
67 | * | ||
68 | * Access to that field is synchronized between the interrupt handler | ||
69 | * and userspace through RCU. | ||
70 | * | ||
71 | * Interrupt handler (threaded part) does PIO on substream data in RCU | ||
72 | * read-side critical section. Trigger callback sets and clears the | ||
73 | * pointer when the playback is started and stopped with | ||
74 | * rcu_assign_pointer. When userspace is about to free the playback | ||
75 | * stream in the pcm_close callback it synchronizes with the interrupt | ||
76 | * handler by means of synchronize_rcu call. | ||
77 | */ | ||
78 | struct snd_pcm_substream *tx_substream; | ||
79 | unsigned (*tx_fn)(struct xtfpga_i2s *i2s, | ||
80 | struct snd_pcm_runtime *runtime, | ||
81 | unsigned tx_ptr); | ||
82 | unsigned tx_ptr; /* next frame index in the sample buffer */ | ||
83 | |||
84 | /* current fifo level estimate. | ||
85 | * Doesn't have to be perfectly accurate, but must be not less than | ||
86 | * the actual FIFO level in order to avoid stall on push attempt. | ||
87 | */ | ||
88 | unsigned tx_fifo_level; | ||
89 | |||
90 | /* FIFO level at which level interrupt occurs */ | ||
91 | unsigned tx_fifo_low; | ||
92 | |||
93 | /* maximal FIFO level */ | ||
94 | unsigned tx_fifo_high; | ||
95 | }; | ||
96 | |||
97 | static bool xtfpga_i2s_wr_reg(struct device *dev, unsigned int reg) | ||
98 | { | ||
99 | return reg >= XTFPGA_I2S_CONFIG; | ||
100 | } | ||
101 | |||
102 | static bool xtfpga_i2s_rd_reg(struct device *dev, unsigned int reg) | ||
103 | { | ||
104 | return reg < XTFPGA_I2S_CHAN0_DATA; | ||
105 | } | ||
106 | |||
107 | static bool xtfpga_i2s_volatile_reg(struct device *dev, unsigned int reg) | ||
108 | { | ||
109 | return reg == XTFPGA_I2S_INT_STATUS; | ||
110 | } | ||
111 | |||
112 | static const struct regmap_config xtfpga_i2s_regmap_config = { | ||
113 | .reg_bits = 32, | ||
114 | .reg_stride = 4, | ||
115 | .val_bits = 32, | ||
116 | .max_register = XTFPGA_I2S_CHAN3_DATA, | ||
117 | .writeable_reg = xtfpga_i2s_wr_reg, | ||
118 | .readable_reg = xtfpga_i2s_rd_reg, | ||
119 | .volatile_reg = xtfpga_i2s_volatile_reg, | ||
120 | .cache_type = REGCACHE_FLAT, | ||
121 | }; | ||
122 | |||
123 | /* Generate functions that do PIO from TX DMA area to FIFO for all supported | ||
124 | * stream formats. | ||
125 | * Functions will be called xtfpga_pcm_tx_<channels>x<sample bits>, e.g. | ||
126 | * xtfpga_pcm_tx_2x16 for 16-bit stereo. | ||
127 | * | ||
128 | * FIFO consists of 32-bit words, one word per channel, always 2 channels. | ||
129 | * If I2S interface is configured with smaller sample resolution, only | ||
130 | * the LSB of each word is used. | ||
131 | */ | ||
132 | #define xtfpga_pcm_tx_fn(channels, sample_bits) \ | ||
133 | static unsigned xtfpga_pcm_tx_##channels##x##sample_bits( \ | ||
134 | struct xtfpga_i2s *i2s, struct snd_pcm_runtime *runtime, \ | ||
135 | unsigned tx_ptr) \ | ||
136 | { \ | ||
137 | const u##sample_bits (*p)[channels] = \ | ||
138 | (void *)runtime->dma_area; \ | ||
139 | \ | ||
140 | for (; i2s->tx_fifo_level < i2s->tx_fifo_high; \ | ||
141 | i2s->tx_fifo_level += 2) { \ | ||
142 | iowrite32(p[tx_ptr][0], \ | ||
143 | i2s->regs + XTFPGA_I2S_CHAN0_DATA); \ | ||
144 | iowrite32(p[tx_ptr][channels - 1], \ | ||
145 | i2s->regs + XTFPGA_I2S_CHAN0_DATA); \ | ||
146 | if (++tx_ptr >= runtime->buffer_size) \ | ||
147 | tx_ptr = 0; \ | ||
148 | } \ | ||
149 | return tx_ptr; \ | ||
150 | } | ||
151 | |||
152 | xtfpga_pcm_tx_fn(1, 16) | ||
153 | xtfpga_pcm_tx_fn(2, 16) | ||
154 | xtfpga_pcm_tx_fn(1, 32) | ||
155 | xtfpga_pcm_tx_fn(2, 32) | ||
156 | |||
157 | #undef xtfpga_pcm_tx_fn | ||
158 | |||
159 | static bool xtfpga_pcm_push_tx(struct xtfpga_i2s *i2s) | ||
160 | { | ||
161 | struct snd_pcm_substream *tx_substream; | ||
162 | bool tx_active; | ||
163 | |||
164 | rcu_read_lock(); | ||
165 | tx_substream = rcu_dereference(i2s->tx_substream); | ||
166 | tx_active = tx_substream && snd_pcm_running(tx_substream); | ||
167 | if (tx_active) { | ||
168 | unsigned tx_ptr = ACCESS_ONCE(i2s->tx_ptr); | ||
169 | unsigned new_tx_ptr = i2s->tx_fn(i2s, tx_substream->runtime, | ||
170 | tx_ptr); | ||
171 | |||
172 | cmpxchg(&i2s->tx_ptr, tx_ptr, new_tx_ptr); | ||
173 | } | ||
174 | rcu_read_unlock(); | ||
175 | |||
176 | return tx_active; | ||
177 | } | ||
178 | |||
179 | static void xtfpga_pcm_refill_fifo(struct xtfpga_i2s *i2s) | ||
180 | { | ||
181 | unsigned int_status; | ||
182 | unsigned i; | ||
183 | |||
184 | regmap_read(i2s->regmap, XTFPGA_I2S_INT_STATUS, | ||
185 | &int_status); | ||
186 | |||
187 | for (i = 0; i < 2; ++i) { | ||
188 | bool tx_active = xtfpga_pcm_push_tx(i2s); | ||
189 | |||
190 | regmap_write(i2s->regmap, XTFPGA_I2S_INT_STATUS, | ||
191 | XTFPGA_I2S_INT_VALID); | ||
192 | if (tx_active) | ||
193 | regmap_read(i2s->regmap, XTFPGA_I2S_INT_STATUS, | ||
194 | &int_status); | ||
195 | |||
196 | if (!tx_active || | ||
197 | !(int_status & XTFPGA_I2S_INT_LEVEL)) | ||
198 | break; | ||
199 | |||
200 | /* After the push the level IRQ is still asserted, | ||
201 | * means FIFO level is below tx_fifo_low. Estimate | ||
202 | * it as tx_fifo_low. | ||
203 | */ | ||
204 | i2s->tx_fifo_level = i2s->tx_fifo_low; | ||
205 | } | ||
206 | |||
207 | if (!(int_status & XTFPGA_I2S_INT_LEVEL)) | ||
208 | regmap_write(i2s->regmap, XTFPGA_I2S_INT_MASK, | ||
209 | XTFPGA_I2S_INT_VALID); | ||
210 | else if (!(int_status & XTFPGA_I2S_INT_UNDERRUN)) | ||
211 | regmap_write(i2s->regmap, XTFPGA_I2S_INT_MASK, | ||
212 | XTFPGA_I2S_INT_UNDERRUN); | ||
213 | |||
214 | if (!(int_status & XTFPGA_I2S_INT_UNDERRUN)) | ||
215 | regmap_update_bits(i2s->regmap, XTFPGA_I2S_CONFIG, | ||
216 | XTFPGA_I2S_CONFIG_INT_ENABLE | | ||
217 | XTFPGA_I2S_CONFIG_TX_ENABLE, | ||
218 | XTFPGA_I2S_CONFIG_INT_ENABLE | | ||
219 | XTFPGA_I2S_CONFIG_TX_ENABLE); | ||
220 | else | ||
221 | regmap_update_bits(i2s->regmap, XTFPGA_I2S_CONFIG, | ||
222 | XTFPGA_I2S_CONFIG_INT_ENABLE | | ||
223 | XTFPGA_I2S_CONFIG_TX_ENABLE, 0); | ||
224 | } | ||
225 | |||
226 | static irqreturn_t xtfpga_i2s_threaded_irq_handler(int irq, void *dev_id) | ||
227 | { | ||
228 | struct xtfpga_i2s *i2s = dev_id; | ||
229 | struct snd_pcm_substream *tx_substream; | ||
230 | unsigned config, int_status, int_mask; | ||
231 | |||
232 | regmap_read(i2s->regmap, XTFPGA_I2S_CONFIG, &config); | ||
233 | regmap_read(i2s->regmap, XTFPGA_I2S_INT_MASK, &int_mask); | ||
234 | regmap_read(i2s->regmap, XTFPGA_I2S_INT_STATUS, &int_status); | ||
235 | |||
236 | if (!(config & XTFPGA_I2S_CONFIG_INT_ENABLE) || | ||
237 | !(int_status & int_mask & XTFPGA_I2S_INT_VALID)) | ||
238 | return IRQ_NONE; | ||
239 | |||
240 | /* Update FIFO level estimate in accordance with interrupt status | ||
241 | * register. | ||
242 | */ | ||
243 | if (int_status & XTFPGA_I2S_INT_UNDERRUN) { | ||
244 | i2s->tx_fifo_level = 0; | ||
245 | regmap_update_bits(i2s->regmap, XTFPGA_I2S_CONFIG, | ||
246 | XTFPGA_I2S_CONFIG_TX_ENABLE, 0); | ||
247 | } else { | ||
248 | /* The FIFO isn't empty, but is below tx_fifo_low. Estimate | ||
249 | * it as tx_fifo_low. | ||
250 | */ | ||
251 | i2s->tx_fifo_level = i2s->tx_fifo_low; | ||
252 | } | ||
253 | |||
254 | rcu_read_lock(); | ||
255 | tx_substream = rcu_dereference(i2s->tx_substream); | ||
256 | |||
257 | if (tx_substream && snd_pcm_running(tx_substream)) { | ||
258 | snd_pcm_period_elapsed(tx_substream); | ||
259 | if (int_status & XTFPGA_I2S_INT_UNDERRUN) | ||
260 | dev_dbg_ratelimited(i2s->dev, "%s: underrun\n", | ||
261 | __func__); | ||
262 | } | ||
263 | rcu_read_unlock(); | ||
264 | |||
265 | /* Refill FIFO, update allowed IRQ reasons, enable IRQ if FIFO is | ||
266 | * not empty. | ||
267 | */ | ||
268 | xtfpga_pcm_refill_fifo(i2s); | ||
269 | |||
270 | return IRQ_HANDLED; | ||
271 | } | ||
272 | |||
273 | static int xtfpga_i2s_startup(struct snd_pcm_substream *substream, | ||
274 | struct snd_soc_dai *dai) | ||
275 | { | ||
276 | struct xtfpga_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
277 | |||
278 | snd_soc_dai_set_dma_data(dai, substream, i2s); | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static int xtfpga_i2s_hw_params(struct snd_pcm_substream *substream, | ||
283 | struct snd_pcm_hw_params *params, | ||
284 | struct snd_soc_dai *dai) | ||
285 | { | ||
286 | struct xtfpga_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
287 | unsigned srate = params_rate(params); | ||
288 | unsigned channels = params_channels(params); | ||
289 | unsigned period_size = params_period_size(params); | ||
290 | unsigned sample_size = snd_pcm_format_width(params_format(params)); | ||
291 | unsigned freq, ratio, level; | ||
292 | int err; | ||
293 | |||
294 | regmap_update_bits(i2s->regmap, XTFPGA_I2S_CONFIG, | ||
295 | XTFPGA_I2S_CONFIG_RES_MASK, | ||
296 | sample_size << XTFPGA_I2S_CONFIG_RES_BASE); | ||
297 | |||
298 | freq = 256 * srate; | ||
299 | err = clk_set_rate(i2s->clk, freq); | ||
300 | if (err < 0) | ||
301 | return err; | ||
302 | |||
303 | /* ratio field of the config register controls MCLK->I2S clock | ||
304 | * derivation: I2S clock = MCLK / (2 * (ratio + 2)). | ||
305 | * | ||
306 | * So with MCLK = 256 * sample rate ratio is 0 for 32 bit stereo | ||
307 | * and 2 for 16 bit stereo. | ||
308 | */ | ||
309 | ratio = (freq - (srate * sample_size * 8)) / | ||
310 | (srate * sample_size * 4); | ||
311 | |||
312 | regmap_update_bits(i2s->regmap, XTFPGA_I2S_CONFIG, | ||
313 | XTFPGA_I2S_CONFIG_RATIO_MASK, | ||
314 | ratio << XTFPGA_I2S_CONFIG_RATIO_BASE); | ||
315 | |||
316 | i2s->tx_fifo_low = XTFPGA_I2S_FIFO_SIZE / 2; | ||
317 | |||
318 | /* period_size * 2: FIFO always gets 2 samples per frame */ | ||
319 | for (level = 1; | ||
320 | i2s->tx_fifo_low / 2 >= period_size * 2 && | ||
321 | level < (XTFPGA_I2S_CONFIG_LEVEL_MASK >> | ||
322 | XTFPGA_I2S_CONFIG_LEVEL_BASE); ++level) | ||
323 | i2s->tx_fifo_low /= 2; | ||
324 | |||
325 | i2s->tx_fifo_high = 2 * i2s->tx_fifo_low; | ||
326 | |||
327 | regmap_update_bits(i2s->regmap, XTFPGA_I2S_CONFIG, | ||
328 | XTFPGA_I2S_CONFIG_LEVEL_MASK, | ||
329 | level << XTFPGA_I2S_CONFIG_LEVEL_BASE); | ||
330 | |||
331 | dev_dbg(i2s->dev, | ||
332 | "%s srate: %u, channels: %u, sample_size: %u, period_size: %u\n", | ||
333 | __func__, srate, channels, sample_size, period_size); | ||
334 | dev_dbg(i2s->dev, "%s freq: %u, ratio: %u, level: %u\n", | ||
335 | __func__, freq, ratio, level); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static int xtfpga_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | ||
341 | unsigned int fmt) | ||
342 | { | ||
343 | if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) | ||
344 | return -EINVAL; | ||
345 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) | ||
346 | return -EINVAL; | ||
347 | if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) | ||
348 | return -EINVAL; | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | /* PCM */ | ||
354 | |||
355 | static const struct snd_pcm_hardware xtfpga_pcm_hardware = { | ||
356 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
357 | SNDRV_PCM_INFO_MMAP_VALID | | ||
358 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
359 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
360 | SNDRV_PCM_FMTBIT_S32_LE, | ||
361 | .channels_min = 1, | ||
362 | .channels_max = 2, | ||
363 | .period_bytes_min = 2, | ||
364 | .period_bytes_max = XTFPGA_I2S_FIFO_SIZE / 2 * 8, | ||
365 | .periods_min = 2, | ||
366 | .periods_max = XTFPGA_I2S_FIFO_SIZE * 8 / 2, | ||
367 | .buffer_bytes_max = XTFPGA_I2S_FIFO_SIZE * 8, | ||
368 | .fifo_size = 16, | ||
369 | }; | ||
370 | |||
371 | static int xtfpga_pcm_open(struct snd_pcm_substream *substream) | ||
372 | { | ||
373 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
374 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
375 | void *p; | ||
376 | |||
377 | snd_soc_set_runtime_hwparams(substream, &xtfpga_pcm_hardware); | ||
378 | p = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
379 | runtime->private_data = p; | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static int xtfpga_pcm_close(struct snd_pcm_substream *substream) | ||
385 | { | ||
386 | synchronize_rcu(); | ||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static int xtfpga_pcm_hw_params(struct snd_pcm_substream *substream, | ||
391 | struct snd_pcm_hw_params *hw_params) | ||
392 | { | ||
393 | int ret; | ||
394 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
395 | struct xtfpga_i2s *i2s = runtime->private_data; | ||
396 | unsigned channels = params_channels(hw_params); | ||
397 | |||
398 | switch (channels) { | ||
399 | case 1: | ||
400 | case 2: | ||
401 | break; | ||
402 | |||
403 | default: | ||
404 | return -EINVAL; | ||
405 | |||
406 | } | ||
407 | |||
408 | switch (params_format(hw_params)) { | ||
409 | case SNDRV_PCM_FORMAT_S16_LE: | ||
410 | i2s->tx_fn = (channels == 1) ? | ||
411 | xtfpga_pcm_tx_1x16 : | ||
412 | xtfpga_pcm_tx_2x16; | ||
413 | break; | ||
414 | |||
415 | case SNDRV_PCM_FORMAT_S32_LE: | ||
416 | i2s->tx_fn = (channels == 1) ? | ||
417 | xtfpga_pcm_tx_1x32 : | ||
418 | xtfpga_pcm_tx_2x32; | ||
419 | break; | ||
420 | |||
421 | default: | ||
422 | return -EINVAL; | ||
423 | } | ||
424 | |||
425 | ret = snd_pcm_lib_malloc_pages(substream, | ||
426 | params_buffer_bytes(hw_params)); | ||
427 | return ret; | ||
428 | } | ||
429 | |||
430 | static int xtfpga_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
431 | { | ||
432 | int ret = 0; | ||
433 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
434 | struct xtfpga_i2s *i2s = runtime->private_data; | ||
435 | |||
436 | switch (cmd) { | ||
437 | case SNDRV_PCM_TRIGGER_START: | ||
438 | case SNDRV_PCM_TRIGGER_RESUME: | ||
439 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
440 | ACCESS_ONCE(i2s->tx_ptr) = 0; | ||
441 | rcu_assign_pointer(i2s->tx_substream, substream); | ||
442 | xtfpga_pcm_refill_fifo(i2s); | ||
443 | break; | ||
444 | |||
445 | case SNDRV_PCM_TRIGGER_STOP: | ||
446 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
447 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
448 | rcu_assign_pointer(i2s->tx_substream, NULL); | ||
449 | break; | ||
450 | |||
451 | default: | ||
452 | ret = -EINVAL; | ||
453 | break; | ||
454 | } | ||
455 | return ret; | ||
456 | } | ||
457 | |||
458 | static snd_pcm_uframes_t xtfpga_pcm_pointer(struct snd_pcm_substream *substream) | ||
459 | { | ||
460 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
461 | struct xtfpga_i2s *i2s = runtime->private_data; | ||
462 | snd_pcm_uframes_t pos = ACCESS_ONCE(i2s->tx_ptr); | ||
463 | |||
464 | return pos < runtime->buffer_size ? pos : 0; | ||
465 | } | ||
466 | |||
467 | static int xtfpga_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
468 | { | ||
469 | struct snd_card *card = rtd->card->snd_card; | ||
470 | size_t size = xtfpga_pcm_hardware.buffer_bytes_max; | ||
471 | |||
472 | return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, | ||
473 | SNDRV_DMA_TYPE_DEV, | ||
474 | card->dev, size, size); | ||
475 | } | ||
476 | |||
477 | static void xtfpga_pcm_free(struct snd_pcm *pcm) | ||
478 | { | ||
479 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
480 | } | ||
481 | |||
482 | static const struct snd_pcm_ops xtfpga_pcm_ops = { | ||
483 | .open = xtfpga_pcm_open, | ||
484 | .close = xtfpga_pcm_close, | ||
485 | .ioctl = snd_pcm_lib_ioctl, | ||
486 | .hw_params = xtfpga_pcm_hw_params, | ||
487 | .trigger = xtfpga_pcm_trigger, | ||
488 | .pointer = xtfpga_pcm_pointer, | ||
489 | }; | ||
490 | |||
491 | static const struct snd_soc_platform_driver xtfpga_soc_platform = { | ||
492 | .pcm_new = xtfpga_pcm_new, | ||
493 | .pcm_free = xtfpga_pcm_free, | ||
494 | .ops = &xtfpga_pcm_ops, | ||
495 | }; | ||
496 | |||
497 | static const struct snd_soc_component_driver xtfpga_i2s_component = { | ||
498 | .name = DRV_NAME, | ||
499 | }; | ||
500 | |||
501 | static const struct snd_soc_dai_ops xtfpga_i2s_dai_ops = { | ||
502 | .startup = xtfpga_i2s_startup, | ||
503 | .hw_params = xtfpga_i2s_hw_params, | ||
504 | .set_fmt = xtfpga_i2s_set_fmt, | ||
505 | }; | ||
506 | |||
507 | static struct snd_soc_dai_driver xtfpga_i2s_dai[] = { | ||
508 | { | ||
509 | .name = "xtfpga-i2s", | ||
510 | .id = 0, | ||
511 | .playback = { | ||
512 | .channels_min = 1, | ||
513 | .channels_max = 2, | ||
514 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
515 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
516 | SNDRV_PCM_FMTBIT_S32_LE, | ||
517 | }, | ||
518 | .ops = &xtfpga_i2s_dai_ops, | ||
519 | }, | ||
520 | }; | ||
521 | |||
522 | static int xtfpga_i2s_runtime_suspend(struct device *dev) | ||
523 | { | ||
524 | struct xtfpga_i2s *i2s = dev_get_drvdata(dev); | ||
525 | |||
526 | clk_disable_unprepare(i2s->clk); | ||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static int xtfpga_i2s_runtime_resume(struct device *dev) | ||
531 | { | ||
532 | struct xtfpga_i2s *i2s = dev_get_drvdata(dev); | ||
533 | int ret; | ||
534 | |||
535 | ret = clk_prepare_enable(i2s->clk); | ||
536 | if (ret) { | ||
537 | dev_err(dev, "clk_prepare_enable failed: %d\n", ret); | ||
538 | return ret; | ||
539 | } | ||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | static int xtfpga_i2s_probe(struct platform_device *pdev) | ||
544 | { | ||
545 | struct xtfpga_i2s *i2s; | ||
546 | struct resource *mem; | ||
547 | int err, irq; | ||
548 | |||
549 | i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); | ||
550 | if (!i2s) { | ||
551 | err = -ENOMEM; | ||
552 | goto err; | ||
553 | } | ||
554 | platform_set_drvdata(pdev, i2s); | ||
555 | i2s->dev = &pdev->dev; | ||
556 | dev_dbg(&pdev->dev, "dev: %p, i2s: %p\n", &pdev->dev, i2s); | ||
557 | |||
558 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
559 | i2s->regs = devm_ioremap_resource(&pdev->dev, mem); | ||
560 | if (IS_ERR(i2s->regs)) { | ||
561 | err = PTR_ERR(i2s->regs); | ||
562 | goto err; | ||
563 | } | ||
564 | |||
565 | i2s->regmap = devm_regmap_init_mmio(&pdev->dev, i2s->regs, | ||
566 | &xtfpga_i2s_regmap_config); | ||
567 | if (IS_ERR(i2s->regmap)) { | ||
568 | dev_err(&pdev->dev, "regmap init failed\n"); | ||
569 | err = PTR_ERR(i2s->regmap); | ||
570 | goto err; | ||
571 | } | ||
572 | |||
573 | i2s->clk = devm_clk_get(&pdev->dev, NULL); | ||
574 | if (IS_ERR(i2s->clk)) { | ||
575 | dev_err(&pdev->dev, "couldn't get clock\n"); | ||
576 | err = PTR_ERR(i2s->clk); | ||
577 | goto err; | ||
578 | } | ||
579 | |||
580 | regmap_write(i2s->regmap, XTFPGA_I2S_CONFIG, | ||
581 | (0x1 << XTFPGA_I2S_CONFIG_CHANNEL_BASE)); | ||
582 | regmap_write(i2s->regmap, XTFPGA_I2S_INT_STATUS, XTFPGA_I2S_INT_VALID); | ||
583 | regmap_write(i2s->regmap, XTFPGA_I2S_INT_MASK, XTFPGA_I2S_INT_UNDERRUN); | ||
584 | |||
585 | irq = platform_get_irq(pdev, 0); | ||
586 | if (irq < 0) { | ||
587 | dev_err(&pdev->dev, "No IRQ resource\n"); | ||
588 | err = irq; | ||
589 | goto err; | ||
590 | } | ||
591 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, | ||
592 | xtfpga_i2s_threaded_irq_handler, | ||
593 | IRQF_SHARED | IRQF_ONESHOT, | ||
594 | pdev->name, i2s); | ||
595 | if (err < 0) { | ||
596 | dev_err(&pdev->dev, "request_irq failed\n"); | ||
597 | goto err; | ||
598 | } | ||
599 | |||
600 | err = snd_soc_register_platform(&pdev->dev, &xtfpga_soc_platform); | ||
601 | if (err < 0) { | ||
602 | dev_err(&pdev->dev, "couldn't register platform\n"); | ||
603 | goto err; | ||
604 | } | ||
605 | err = devm_snd_soc_register_component(&pdev->dev, | ||
606 | &xtfpga_i2s_component, | ||
607 | xtfpga_i2s_dai, | ||
608 | ARRAY_SIZE(xtfpga_i2s_dai)); | ||
609 | if (err < 0) { | ||
610 | dev_err(&pdev->dev, "couldn't register component\n"); | ||
611 | goto err_unregister_platform; | ||
612 | } | ||
613 | |||
614 | pm_runtime_enable(&pdev->dev); | ||
615 | if (!pm_runtime_enabled(&pdev->dev)) { | ||
616 | err = xtfpga_i2s_runtime_resume(&pdev->dev); | ||
617 | if (err) | ||
618 | goto err_pm_disable; | ||
619 | } | ||
620 | return 0; | ||
621 | |||
622 | err_pm_disable: | ||
623 | pm_runtime_disable(&pdev->dev); | ||
624 | err_unregister_platform: | ||
625 | snd_soc_unregister_platform(&pdev->dev); | ||
626 | err: | ||
627 | dev_err(&pdev->dev, "%s: err = %d\n", __func__, err); | ||
628 | return err; | ||
629 | } | ||
630 | |||
631 | static int xtfpga_i2s_remove(struct platform_device *pdev) | ||
632 | { | ||
633 | struct xtfpga_i2s *i2s = dev_get_drvdata(&pdev->dev); | ||
634 | |||
635 | snd_soc_unregister_platform(&pdev->dev); | ||
636 | if (i2s->regmap && !IS_ERR(i2s->regmap)) { | ||
637 | regmap_write(i2s->regmap, XTFPGA_I2S_CONFIG, 0); | ||
638 | regmap_write(i2s->regmap, XTFPGA_I2S_INT_MASK, 0); | ||
639 | regmap_write(i2s->regmap, XTFPGA_I2S_INT_STATUS, | ||
640 | XTFPGA_I2S_INT_VALID); | ||
641 | } | ||
642 | pm_runtime_disable(&pdev->dev); | ||
643 | if (!pm_runtime_status_suspended(&pdev->dev)) | ||
644 | xtfpga_i2s_runtime_suspend(&pdev->dev); | ||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | #ifdef CONFIG_OF | ||
649 | static const struct of_device_id xtfpga_i2s_of_match[] = { | ||
650 | { .compatible = "cdns,xtfpga-i2s", }, | ||
651 | {}, | ||
652 | }; | ||
653 | MODULE_DEVICE_TABLE(of, xtfpga_i2s_of_match); | ||
654 | #endif | ||
655 | |||
656 | static const struct dev_pm_ops xtfpga_i2s_pm_ops = { | ||
657 | SET_RUNTIME_PM_OPS(xtfpga_i2s_runtime_suspend, | ||
658 | xtfpga_i2s_runtime_resume, NULL) | ||
659 | }; | ||
660 | |||
661 | static struct platform_driver xtfpga_i2s_driver = { | ||
662 | .probe = xtfpga_i2s_probe, | ||
663 | .remove = xtfpga_i2s_remove, | ||
664 | .driver = { | ||
665 | .name = "xtfpga-i2s", | ||
666 | .of_match_table = of_match_ptr(xtfpga_i2s_of_match), | ||
667 | .pm = &xtfpga_i2s_pm_ops, | ||
668 | }, | ||
669 | }; | ||
670 | |||
671 | module_platform_driver(xtfpga_i2s_driver); | ||
672 | |||
673 | MODULE_AUTHOR("Max Filippov <jcmvbkbc@gmail.com>"); | ||
674 | MODULE_DESCRIPTION("xtfpga I2S controller driver"); | ||
675 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 86280d63b76d..1b1a89e80d13 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/moduleparam.h> | 37 | #include <linux/moduleparam.h> |
38 | #include <linux/of.h> | 38 | #include <linux/of.h> |
39 | #include <linux/of_device.h> | 39 | #include <linux/of_device.h> |
40 | #include <linux/io.h> | ||
40 | 41 | ||
41 | #include <sound/core.h> | 42 | #include <sound/core.h> |
42 | #include <sound/pcm.h> | 43 | #include <sound/pcm.h> |
@@ -44,7 +45,6 @@ | |||
44 | #include <sound/control.h> | 45 | #include <sound/control.h> |
45 | #include <sound/initval.h> | 46 | #include <sound/initval.h> |
46 | 47 | ||
47 | #include <asm/io.h> | ||
48 | #include <asm/irq.h> | 48 | #include <asm/irq.h> |
49 | #include <asm/prom.h> | 49 | #include <asm/prom.h> |
50 | 50 | ||
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index 93522072bc87..49195325fdf6 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c | |||
@@ -53,9 +53,7 @@ int snd_emux_new(struct snd_emux **remu) | |||
53 | emu->max_voices = 0; | 53 | emu->max_voices = 0; |
54 | emu->use_time = 0; | 54 | emu->use_time = 0; |
55 | 55 | ||
56 | init_timer(&emu->tlist); | 56 | setup_timer(&emu->tlist, snd_emux_timer_callback, (unsigned long)emu); |
57 | emu->tlist.function = snd_emux_timer_callback; | ||
58 | emu->tlist.data = (unsigned long)emu; | ||
59 | emu->timer_active = 0; | 57 | emu->timer_active = 0; |
60 | 58 | ||
61 | *remu = emu; | 59 | *remu = emu; |
@@ -160,12 +158,8 @@ int snd_emux_free(struct snd_emux *emu) | |||
160 | snd_emux_detach_seq_oss(emu); | 158 | snd_emux_detach_seq_oss(emu); |
161 | #endif | 159 | #endif |
162 | snd_emux_detach_seq(emu); | 160 | snd_emux_detach_seq(emu); |
163 | |||
164 | snd_emux_delete_hwdep(emu); | 161 | snd_emux_delete_hwdep(emu); |
165 | 162 | snd_sf_free(emu->sflist); | |
166 | if (emu->sflist) | ||
167 | snd_sf_free(emu->sflist); | ||
168 | |||
169 | kfree(emu->voices); | 163 | kfree(emu->voices); |
170 | kfree(emu->name); | 164 | kfree(emu->name); |
171 | kfree(emu); | 165 | kfree(emu); |
diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c index 5ae1eae9f6db..e557946718a9 100644 --- a/sound/synth/emux/emux_hwdep.c +++ b/sound/synth/emux/emux_hwdep.c | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | #include <sound/core.h> | 22 | #include <sound/core.h> |
23 | #include <sound/hwdep.h> | 23 | #include <sound/hwdep.h> |
24 | #include <asm/uaccess.h> | 24 | #include <linux/uaccess.h> |
25 | #include "emux_voice.h" | 25 | #include "emux_voice.h" |
26 | 26 | ||
27 | 27 | ||
diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c index 319754cf6208..ab37add269ae 100644 --- a/sound/synth/emux/emux_oss.c +++ b/sound/synth/emux/emux_oss.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #ifdef CONFIG_SND_SEQUENCER_OSS | 26 | #ifdef CONFIG_SND_SEQUENCER_OSS |
27 | 27 | ||
28 | #include <linux/export.h> | 28 | #include <linux/export.h> |
29 | #include <asm/uaccess.h> | 29 | #include <linux/uaccess.h> |
30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
31 | #include "emux_voice.h" | 31 | #include "emux_voice.h" |
32 | #include <sound/asoundef.h> | 32 | #include <sound/asoundef.h> |
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c index 9a38de459acb..599551b5af44 100644 --- a/sound/synth/emux/emux_synth.c +++ b/sound/synth/emux/emux_synth.c | |||
@@ -186,8 +186,7 @@ snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan) | |||
186 | */ | 186 | */ |
187 | vp->state = SNDRV_EMUX_ST_PENDING; | 187 | vp->state = SNDRV_EMUX_ST_PENDING; |
188 | if (! emu->timer_active) { | 188 | if (! emu->timer_active) { |
189 | emu->tlist.expires = jiffies + 1; | 189 | mod_timer(&emu->tlist, jiffies + 1); |
190 | add_timer(&emu->tlist); | ||
191 | emu->timer_active = 1; | 190 | emu->timer_active = 1; |
192 | } | 191 | } |
193 | } else | 192 | } else |
@@ -223,8 +222,7 @@ void snd_emux_timer_callback(unsigned long data) | |||
223 | } | 222 | } |
224 | } | 223 | } |
225 | if (do_again) { | 224 | if (do_again) { |
226 | emu->tlist.expires = jiffies + 1; | 225 | mod_timer(&emu->tlist, jiffies + 1); |
227 | add_timer(&emu->tlist); | ||
228 | emu->timer_active = 1; | 226 | emu->timer_active = 1; |
229 | } else | 227 | } else |
230 | emu->timer_active = 0; | 228 | emu->timer_active = 0; |
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index 78683b2064f7..31a4ea94830e 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * of doing things so that the old sfxload utility can be used. | 25 | * of doing things so that the old sfxload utility can be used. |
26 | * Everything may change when there is an alsa way of doing things. | 26 | * Everything may change when there is an alsa way of doing things. |
27 | */ | 27 | */ |
28 | #include <asm/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/export.h> | 30 | #include <linux/export.h> |
31 | #include <sound/core.h> | 31 | #include <sound/core.h> |
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index d393153c474f..a452ad7cec40 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -160,5 +160,7 @@ config SND_BCD2000 | |||
160 | To compile this driver as a module, choose M here: the module | 160 | To compile this driver as a module, choose M here: the module |
161 | will be called snd-bcd2000. | 161 | will be called snd-bcd2000. |
162 | 162 | ||
163 | source "sound/usb/line6/Kconfig" | ||
164 | |||
163 | endif # SND_USB | 165 | endif # SND_USB |
164 | 166 | ||
diff --git a/sound/usb/Makefile b/sound/usb/Makefile index bcee4060fd18..2d2d122b069f 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile | |||
@@ -25,3 +25,4 @@ obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o | |||
25 | obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o | 25 | obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o |
26 | 26 | ||
27 | obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/ | 27 | obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/ |
28 | obj-$(CONFIG_SND_USB_LINE6) += line6/ | ||
diff --git a/sound/usb/card.h b/sound/usb/card.h index 97acb906acc2..ef580b43f1e3 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h | |||
@@ -153,6 +153,8 @@ struct snd_usb_substream { | |||
153 | int channel; | 153 | int channel; |
154 | int byte_idx; | 154 | int byte_idx; |
155 | } dsd_dop; | 155 | } dsd_dop; |
156 | |||
157 | bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */ | ||
156 | }; | 158 | }; |
157 | 159 | ||
158 | struct snd_usb_stream { | 160 | struct snd_usb_stream { |
diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 03fed6611d9e..2ed260b10f6d 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c | |||
@@ -303,6 +303,11 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, | |||
303 | return err; | 303 | return err; |
304 | } | 304 | } |
305 | 305 | ||
306 | /* Don't check the sample rate for devices which we know don't | ||
307 | * support reading */ | ||
308 | if (snd_usb_get_sample_rate_quirk(chip)) | ||
309 | return 0; | ||
310 | |||
306 | if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR, | 311 | if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR, |
307 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN, | 312 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN, |
308 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, | 313 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, |
diff --git a/sound/usb/line6/Kconfig b/sound/usb/line6/Kconfig new file mode 100644 index 000000000000..f4585d378ef3 --- /dev/null +++ b/sound/usb/line6/Kconfig | |||
@@ -0,0 +1,42 @@ | |||
1 | config SND_USB_LINE6 | ||
2 | tristate | ||
3 | select SND_RAWMIDI | ||
4 | select SND_PCM | ||
5 | |||
6 | config SND_USB_POD | ||
7 | tristate "Line 6 POD USB support" | ||
8 | select SND_USB_LINE6 | ||
9 | help | ||
10 | This is a driver for PODxt and other similar devices, | ||
11 | supporting the following features: | ||
12 | * Reading/writing individual parameters | ||
13 | * Reading/writing complete channel, effects setup, and amp | ||
14 | setup data | ||
15 | * Channel switching | ||
16 | * Virtual MIDI interface | ||
17 | * Tuner access | ||
18 | * Playback/capture/mixer device for any ALSA-compatible PCM | ||
19 | audio application | ||
20 | * Signal routing (record clean/processed guitar signal, | ||
21 | re-amping) | ||
22 | |||
23 | config SND_USB_PODHD | ||
24 | tristate "Line 6 POD HD300/400/500 USB support" | ||
25 | select SND_USB_LINE6 | ||
26 | help | ||
27 | This is a driver for POD HD300, 400 and 500 devices. | ||
28 | |||
29 | config SND_USB_TONEPORT | ||
30 | tristate "TonePort GX, UX1 and UX2 USB support" | ||
31 | select SND_USB_LINE6 | ||
32 | select NEW_LEDS | ||
33 | select LEDS_CLASS | ||
34 | help | ||
35 | This is a driver for TonePort GX, UX1 and UX2 devices. | ||
36 | |||
37 | config SND_USB_VARIAX | ||
38 | tristate "Variax Workbench USB support" | ||
39 | select SND_USB_LINE6 | ||
40 | help | ||
41 | This is a driver for Variax Workbench device. | ||
42 | |||
diff --git a/sound/usb/line6/Makefile b/sound/usb/line6/Makefile new file mode 100644 index 000000000000..b8b3b2a543d8 --- /dev/null +++ b/sound/usb/line6/Makefile | |||
@@ -0,0 +1,18 @@ | |||
1 | snd-usb-line6-y := \ | ||
2 | capture.o \ | ||
3 | driver.o \ | ||
4 | midi.o \ | ||
5 | midibuf.o \ | ||
6 | pcm.o \ | ||
7 | playback.o | ||
8 | |||
9 | snd-usb-pod-y := pod.o | ||
10 | snd-usb-podhd-y := podhd.o | ||
11 | snd-usb-toneport-y := toneport.o | ||
12 | snd-usb-variax-y := variax.o | ||
13 | |||
14 | obj-$(CONFIG_SND_USB_LINE6) += snd-usb-line6.o | ||
15 | obj-$(CONFIG_SND_USB_POD) += snd-usb-pod.o | ||
16 | obj-$(CONFIG_SND_USB_PODHD) += snd-usb-podhd.o | ||
17 | obj-$(CONFIG_SND_USB_TONEPORT) += snd-usb-toneport.o | ||
18 | obj-$(CONFIG_SND_USB_VARIAX) += snd-usb-variax.o | ||
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c new file mode 100644 index 000000000000..f518fbbe88de --- /dev/null +++ b/sound/usb/line6/capture.c | |||
@@ -0,0 +1,275 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/slab.h> | ||
13 | #include <sound/core.h> | ||
14 | #include <sound/pcm.h> | ||
15 | #include <sound/pcm_params.h> | ||
16 | |||
17 | #include "capture.h" | ||
18 | #include "driver.h" | ||
19 | #include "pcm.h" | ||
20 | |||
21 | /* | ||
22 | Find a free URB and submit it. | ||
23 | must be called in line6pcm->in.lock context | ||
24 | */ | ||
25 | static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm) | ||
26 | { | ||
27 | int index; | ||
28 | int i, urb_size; | ||
29 | int ret; | ||
30 | struct urb *urb_in; | ||
31 | |||
32 | index = | ||
33 | find_first_zero_bit(&line6pcm->in.active_urbs, LINE6_ISO_BUFFERS); | ||
34 | |||
35 | if (index < 0 || index >= LINE6_ISO_BUFFERS) { | ||
36 | dev_err(line6pcm->line6->ifcdev, "no free URB found\n"); | ||
37 | return -EINVAL; | ||
38 | } | ||
39 | |||
40 | urb_in = line6pcm->in.urbs[index]; | ||
41 | urb_size = 0; | ||
42 | |||
43 | for (i = 0; i < LINE6_ISO_PACKETS; ++i) { | ||
44 | struct usb_iso_packet_descriptor *fin = | ||
45 | &urb_in->iso_frame_desc[i]; | ||
46 | fin->offset = urb_size; | ||
47 | fin->length = line6pcm->max_packet_size; | ||
48 | urb_size += line6pcm->max_packet_size; | ||
49 | } | ||
50 | |||
51 | urb_in->transfer_buffer = | ||
52 | line6pcm->in.buffer + | ||
53 | index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; | ||
54 | urb_in->transfer_buffer_length = urb_size; | ||
55 | urb_in->context = line6pcm; | ||
56 | |||
57 | ret = usb_submit_urb(urb_in, GFP_ATOMIC); | ||
58 | |||
59 | if (ret == 0) | ||
60 | set_bit(index, &line6pcm->in.active_urbs); | ||
61 | else | ||
62 | dev_err(line6pcm->line6->ifcdev, | ||
63 | "URB in #%d submission failed (%d)\n", index, ret); | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | Submit all currently available capture URBs. | ||
70 | must be called in line6pcm->in.lock context | ||
71 | */ | ||
72 | int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm) | ||
73 | { | ||
74 | int ret = 0, i; | ||
75 | |||
76 | for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { | ||
77 | ret = submit_audio_in_urb(line6pcm); | ||
78 | if (ret < 0) | ||
79 | break; | ||
80 | } | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | Copy data into ALSA capture buffer. | ||
87 | */ | ||
88 | void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize) | ||
89 | { | ||
90 | struct snd_pcm_substream *substream = | ||
91 | get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE); | ||
92 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
93 | const int bytes_per_frame = line6pcm->properties->bytes_per_frame; | ||
94 | int frames = fsize / bytes_per_frame; | ||
95 | |||
96 | if (runtime == NULL) | ||
97 | return; | ||
98 | |||
99 | if (line6pcm->in.pos_done + frames > runtime->buffer_size) { | ||
100 | /* | ||
101 | The transferred area goes over buffer boundary, | ||
102 | copy two separate chunks. | ||
103 | */ | ||
104 | int len; | ||
105 | |||
106 | len = runtime->buffer_size - line6pcm->in.pos_done; | ||
107 | |||
108 | if (len > 0) { | ||
109 | memcpy(runtime->dma_area + | ||
110 | line6pcm->in.pos_done * bytes_per_frame, fbuf, | ||
111 | len * bytes_per_frame); | ||
112 | memcpy(runtime->dma_area, fbuf + len * bytes_per_frame, | ||
113 | (frames - len) * bytes_per_frame); | ||
114 | } else { | ||
115 | /* this is somewhat paranoid */ | ||
116 | dev_err(line6pcm->line6->ifcdev, | ||
117 | "driver bug: len = %d\n", len); | ||
118 | } | ||
119 | } else { | ||
120 | /* copy single chunk */ | ||
121 | memcpy(runtime->dma_area + | ||
122 | line6pcm->in.pos_done * bytes_per_frame, fbuf, fsize); | ||
123 | } | ||
124 | |||
125 | line6pcm->in.pos_done += frames; | ||
126 | if (line6pcm->in.pos_done >= runtime->buffer_size) | ||
127 | line6pcm->in.pos_done -= runtime->buffer_size; | ||
128 | } | ||
129 | |||
130 | void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length) | ||
131 | { | ||
132 | struct snd_pcm_substream *substream = | ||
133 | get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE); | ||
134 | |||
135 | line6pcm->in.bytes += length; | ||
136 | if (line6pcm->in.bytes >= line6pcm->in.period) { | ||
137 | line6pcm->in.bytes %= line6pcm->in.period; | ||
138 | spin_unlock(&line6pcm->in.lock); | ||
139 | snd_pcm_period_elapsed(substream); | ||
140 | spin_lock(&line6pcm->in.lock); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * Callback for completed capture URB. | ||
146 | */ | ||
147 | static void audio_in_callback(struct urb *urb) | ||
148 | { | ||
149 | int i, index, length = 0, shutdown = 0; | ||
150 | unsigned long flags; | ||
151 | |||
152 | struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context; | ||
153 | |||
154 | line6pcm->in.last_frame = urb->start_frame; | ||
155 | |||
156 | /* find index of URB */ | ||
157 | for (index = 0; index < LINE6_ISO_BUFFERS; ++index) | ||
158 | if (urb == line6pcm->in.urbs[index]) | ||
159 | break; | ||
160 | |||
161 | spin_lock_irqsave(&line6pcm->in.lock, flags); | ||
162 | |||
163 | for (i = 0; i < LINE6_ISO_PACKETS; ++i) { | ||
164 | char *fbuf; | ||
165 | int fsize; | ||
166 | struct usb_iso_packet_descriptor *fin = &urb->iso_frame_desc[i]; | ||
167 | |||
168 | if (fin->status == -EXDEV) { | ||
169 | shutdown = 1; | ||
170 | break; | ||
171 | } | ||
172 | |||
173 | fbuf = urb->transfer_buffer + fin->offset; | ||
174 | fsize = fin->actual_length; | ||
175 | |||
176 | if (fsize > line6pcm->max_packet_size) { | ||
177 | dev_err(line6pcm->line6->ifcdev, | ||
178 | "driver and/or device bug: packet too large (%d > %d)\n", | ||
179 | fsize, line6pcm->max_packet_size); | ||
180 | } | ||
181 | |||
182 | length += fsize; | ||
183 | |||
184 | /* the following assumes LINE6_ISO_PACKETS == 1: */ | ||
185 | line6pcm->prev_fbuf = fbuf; | ||
186 | line6pcm->prev_fsize = fsize; | ||
187 | |||
188 | if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) && | ||
189 | test_bit(LINE6_STREAM_PCM, &line6pcm->in.running) && | ||
190 | fsize > 0) | ||
191 | line6_capture_copy(line6pcm, fbuf, fsize); | ||
192 | } | ||
193 | |||
194 | clear_bit(index, &line6pcm->in.active_urbs); | ||
195 | |||
196 | if (test_and_clear_bit(index, &line6pcm->in.unlink_urbs)) | ||
197 | shutdown = 1; | ||
198 | |||
199 | if (!shutdown) { | ||
200 | submit_audio_in_urb(line6pcm); | ||
201 | |||
202 | if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) && | ||
203 | test_bit(LINE6_STREAM_PCM, &line6pcm->in.running)) | ||
204 | line6_capture_check_period(line6pcm, length); | ||
205 | } | ||
206 | |||
207 | spin_unlock_irqrestore(&line6pcm->in.lock, flags); | ||
208 | } | ||
209 | |||
210 | /* open capture callback */ | ||
211 | static int snd_line6_capture_open(struct snd_pcm_substream *substream) | ||
212 | { | ||
213 | int err; | ||
214 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
215 | struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); | ||
216 | |||
217 | err = snd_pcm_hw_constraint_ratdens(runtime, 0, | ||
218 | SNDRV_PCM_HW_PARAM_RATE, | ||
219 | &line6pcm->properties->rates); | ||
220 | if (err < 0) | ||
221 | return err; | ||
222 | |||
223 | runtime->hw = line6pcm->properties->capture_hw; | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | /* close capture callback */ | ||
228 | static int snd_line6_capture_close(struct snd_pcm_substream *substream) | ||
229 | { | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | /* capture operators */ | ||
234 | struct snd_pcm_ops snd_line6_capture_ops = { | ||
235 | .open = snd_line6_capture_open, | ||
236 | .close = snd_line6_capture_close, | ||
237 | .ioctl = snd_pcm_lib_ioctl, | ||
238 | .hw_params = snd_line6_hw_params, | ||
239 | .hw_free = snd_line6_hw_free, | ||
240 | .prepare = snd_line6_prepare, | ||
241 | .trigger = snd_line6_trigger, | ||
242 | .pointer = snd_line6_pointer, | ||
243 | }; | ||
244 | |||
245 | int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm) | ||
246 | { | ||
247 | struct usb_line6 *line6 = line6pcm->line6; | ||
248 | int i; | ||
249 | |||
250 | /* create audio URBs and fill in constant values: */ | ||
251 | for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { | ||
252 | struct urb *urb; | ||
253 | |||
254 | /* URB for audio in: */ | ||
255 | urb = line6pcm->in.urbs[i] = | ||
256 | usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); | ||
257 | |||
258 | if (urb == NULL) | ||
259 | return -ENOMEM; | ||
260 | |||
261 | urb->dev = line6->usbdev; | ||
262 | urb->pipe = | ||
263 | usb_rcvisocpipe(line6->usbdev, | ||
264 | line6->properties->ep_audio_r & | ||
265 | USB_ENDPOINT_NUMBER_MASK); | ||
266 | urb->transfer_flags = URB_ISO_ASAP; | ||
267 | urb->start_frame = -1; | ||
268 | urb->number_of_packets = LINE6_ISO_PACKETS; | ||
269 | urb->interval = LINE6_ISO_INTERVAL; | ||
270 | urb->error_count = 0; | ||
271 | urb->complete = audio_in_callback; | ||
272 | } | ||
273 | |||
274 | return 0; | ||
275 | } | ||
diff --git a/sound/usb/line6/capture.h b/sound/usb/line6/capture.h new file mode 100644 index 000000000000..890b21bff18c --- /dev/null +++ b/sound/usb/line6/capture.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef CAPTURE_H | ||
13 | #define CAPTURE_H | ||
14 | |||
15 | #include <sound/pcm.h> | ||
16 | |||
17 | #include "driver.h" | ||
18 | #include "pcm.h" | ||
19 | |||
20 | extern struct snd_pcm_ops snd_line6_capture_ops; | ||
21 | |||
22 | extern void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, | ||
23 | int fsize); | ||
24 | extern void line6_capture_check_period(struct snd_line6_pcm *line6pcm, | ||
25 | int length); | ||
26 | extern int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm); | ||
27 | extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm); | ||
28 | |||
29 | #endif | ||
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c new file mode 100644 index 000000000000..81b7da8e56d3 --- /dev/null +++ b/sound/usb/line6/driver.c | |||
@@ -0,0 +1,672 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/export.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/usb.h> | ||
17 | |||
18 | #include <sound/core.h> | ||
19 | #include <sound/initval.h> | ||
20 | |||
21 | #include "capture.h" | ||
22 | #include "driver.h" | ||
23 | #include "midi.h" | ||
24 | #include "playback.h" | ||
25 | |||
26 | #define DRIVER_AUTHOR "Markus Grabner <grabner@icg.tugraz.at>" | ||
27 | #define DRIVER_DESC "Line 6 USB Driver" | ||
28 | |||
29 | /* | ||
30 | This is Line 6's MIDI manufacturer ID. | ||
31 | */ | ||
32 | const unsigned char line6_midi_id[] = { | ||
33 | 0x00, 0x01, 0x0c | ||
34 | }; | ||
35 | EXPORT_SYMBOL_GPL(line6_midi_id); | ||
36 | |||
37 | /* | ||
38 | Code to request version of POD, Variax interface | ||
39 | (and maybe other devices). | ||
40 | */ | ||
41 | static const char line6_request_version[] = { | ||
42 | 0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7 | ||
43 | }; | ||
44 | |||
45 | /* | ||
46 | Class for asynchronous messages. | ||
47 | */ | ||
48 | struct message { | ||
49 | struct usb_line6 *line6; | ||
50 | const char *buffer; | ||
51 | int size; | ||
52 | int done; | ||
53 | }; | ||
54 | |||
55 | /* | ||
56 | Forward declarations. | ||
57 | */ | ||
58 | static void line6_data_received(struct urb *urb); | ||
59 | static int line6_send_raw_message_async_part(struct message *msg, | ||
60 | struct urb *urb); | ||
61 | |||
62 | /* | ||
63 | Start to listen on endpoint. | ||
64 | */ | ||
65 | static int line6_start_listen(struct usb_line6 *line6) | ||
66 | { | ||
67 | int err; | ||
68 | |||
69 | usb_fill_int_urb(line6->urb_listen, line6->usbdev, | ||
70 | usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r), | ||
71 | line6->buffer_listen, LINE6_BUFSIZE_LISTEN, | ||
72 | line6_data_received, line6, line6->interval); | ||
73 | line6->urb_listen->actual_length = 0; | ||
74 | err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC); | ||
75 | return err; | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | Stop listening on endpoint. | ||
80 | */ | ||
81 | static void line6_stop_listen(struct usb_line6 *line6) | ||
82 | { | ||
83 | usb_kill_urb(line6->urb_listen); | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | Send raw message in pieces of wMaxPacketSize bytes. | ||
88 | */ | ||
89 | static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, | ||
90 | int size) | ||
91 | { | ||
92 | int i, done = 0; | ||
93 | |||
94 | for (i = 0; i < size; i += line6->max_packet_size) { | ||
95 | int partial; | ||
96 | const char *frag_buf = buffer + i; | ||
97 | int frag_size = min(line6->max_packet_size, size - i); | ||
98 | int retval; | ||
99 | |||
100 | retval = usb_interrupt_msg(line6->usbdev, | ||
101 | usb_sndintpipe(line6->usbdev, | ||
102 | line6->properties->ep_ctrl_w), | ||
103 | (char *)frag_buf, frag_size, | ||
104 | &partial, LINE6_TIMEOUT * HZ); | ||
105 | |||
106 | if (retval) { | ||
107 | dev_err(line6->ifcdev, | ||
108 | "usb_interrupt_msg failed (%d)\n", retval); | ||
109 | break; | ||
110 | } | ||
111 | |||
112 | done += frag_size; | ||
113 | } | ||
114 | |||
115 | return done; | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | Notification of completion of asynchronous request transmission. | ||
120 | */ | ||
121 | static void line6_async_request_sent(struct urb *urb) | ||
122 | { | ||
123 | struct message *msg = (struct message *)urb->context; | ||
124 | |||
125 | if (msg->done >= msg->size) { | ||
126 | usb_free_urb(urb); | ||
127 | kfree(msg); | ||
128 | } else | ||
129 | line6_send_raw_message_async_part(msg, urb); | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | Asynchronously send part of a raw message. | ||
134 | */ | ||
135 | static int line6_send_raw_message_async_part(struct message *msg, | ||
136 | struct urb *urb) | ||
137 | { | ||
138 | int retval; | ||
139 | struct usb_line6 *line6 = msg->line6; | ||
140 | int done = msg->done; | ||
141 | int bytes = min(msg->size - done, line6->max_packet_size); | ||
142 | |||
143 | usb_fill_int_urb(urb, line6->usbdev, | ||
144 | usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w), | ||
145 | (char *)msg->buffer + done, bytes, | ||
146 | line6_async_request_sent, msg, line6->interval); | ||
147 | |||
148 | msg->done += bytes; | ||
149 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
150 | |||
151 | if (retval < 0) { | ||
152 | dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n", | ||
153 | __func__, retval); | ||
154 | usb_free_urb(urb); | ||
155 | kfree(msg); | ||
156 | return retval; | ||
157 | } | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | Setup and start timer. | ||
164 | */ | ||
165 | void line6_start_timer(struct timer_list *timer, unsigned long msecs, | ||
166 | void (*function)(unsigned long), unsigned long data) | ||
167 | { | ||
168 | setup_timer(timer, function, data); | ||
169 | mod_timer(timer, jiffies + msecs_to_jiffies(msecs)); | ||
170 | } | ||
171 | EXPORT_SYMBOL_GPL(line6_start_timer); | ||
172 | |||
173 | /* | ||
174 | Asynchronously send raw message. | ||
175 | */ | ||
176 | int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer, | ||
177 | int size) | ||
178 | { | ||
179 | struct message *msg; | ||
180 | struct urb *urb; | ||
181 | |||
182 | /* create message: */ | ||
183 | msg = kmalloc(sizeof(struct message), GFP_ATOMIC); | ||
184 | if (msg == NULL) | ||
185 | return -ENOMEM; | ||
186 | |||
187 | /* create URB: */ | ||
188 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
189 | |||
190 | if (urb == NULL) { | ||
191 | kfree(msg); | ||
192 | return -ENOMEM; | ||
193 | } | ||
194 | |||
195 | /* set message data: */ | ||
196 | msg->line6 = line6; | ||
197 | msg->buffer = buffer; | ||
198 | msg->size = size; | ||
199 | msg->done = 0; | ||
200 | |||
201 | /* start sending: */ | ||
202 | return line6_send_raw_message_async_part(msg, urb); | ||
203 | } | ||
204 | EXPORT_SYMBOL_GPL(line6_send_raw_message_async); | ||
205 | |||
206 | /* | ||
207 | Send asynchronous device version request. | ||
208 | */ | ||
209 | int line6_version_request_async(struct usb_line6 *line6) | ||
210 | { | ||
211 | char *buffer; | ||
212 | int retval; | ||
213 | |||
214 | buffer = kmemdup(line6_request_version, | ||
215 | sizeof(line6_request_version), GFP_ATOMIC); | ||
216 | if (buffer == NULL) | ||
217 | return -ENOMEM; | ||
218 | |||
219 | retval = line6_send_raw_message_async(line6, buffer, | ||
220 | sizeof(line6_request_version)); | ||
221 | kfree(buffer); | ||
222 | return retval; | ||
223 | } | ||
224 | EXPORT_SYMBOL_GPL(line6_version_request_async); | ||
225 | |||
226 | /* | ||
227 | Send sysex message in pieces of wMaxPacketSize bytes. | ||
228 | */ | ||
229 | int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer, | ||
230 | int size) | ||
231 | { | ||
232 | return line6_send_raw_message(line6, buffer, | ||
233 | size + SYSEX_EXTRA_SIZE) - | ||
234 | SYSEX_EXTRA_SIZE; | ||
235 | } | ||
236 | EXPORT_SYMBOL_GPL(line6_send_sysex_message); | ||
237 | |||
238 | /* | ||
239 | Allocate buffer for sysex message and prepare header. | ||
240 | @param code sysex message code | ||
241 | @param size number of bytes between code and sysex end | ||
242 | */ | ||
243 | char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, int code2, | ||
244 | int size) | ||
245 | { | ||
246 | char *buffer = kmalloc(size + SYSEX_EXTRA_SIZE, GFP_ATOMIC); | ||
247 | |||
248 | if (!buffer) | ||
249 | return NULL; | ||
250 | |||
251 | buffer[0] = LINE6_SYSEX_BEGIN; | ||
252 | memcpy(buffer + 1, line6_midi_id, sizeof(line6_midi_id)); | ||
253 | buffer[sizeof(line6_midi_id) + 1] = code1; | ||
254 | buffer[sizeof(line6_midi_id) + 2] = code2; | ||
255 | buffer[sizeof(line6_midi_id) + 3 + size] = LINE6_SYSEX_END; | ||
256 | return buffer; | ||
257 | } | ||
258 | EXPORT_SYMBOL_GPL(line6_alloc_sysex_buffer); | ||
259 | |||
260 | /* | ||
261 | Notification of data received from the Line 6 device. | ||
262 | */ | ||
263 | static void line6_data_received(struct urb *urb) | ||
264 | { | ||
265 | struct usb_line6 *line6 = (struct usb_line6 *)urb->context; | ||
266 | struct midi_buffer *mb = &line6->line6midi->midibuf_in; | ||
267 | int done; | ||
268 | |||
269 | if (urb->status == -ESHUTDOWN) | ||
270 | return; | ||
271 | |||
272 | done = | ||
273 | line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length); | ||
274 | |||
275 | if (done < urb->actual_length) { | ||
276 | line6_midibuf_ignore(mb, done); | ||
277 | dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n", | ||
278 | done, urb->actual_length); | ||
279 | } | ||
280 | |||
281 | for (;;) { | ||
282 | done = | ||
283 | line6_midibuf_read(mb, line6->buffer_message, | ||
284 | LINE6_MESSAGE_MAXLEN); | ||
285 | |||
286 | if (done == 0) | ||
287 | break; | ||
288 | |||
289 | line6->message_length = done; | ||
290 | line6_midi_receive(line6, line6->buffer_message, done); | ||
291 | |||
292 | if (line6->process_message) | ||
293 | line6->process_message(line6); | ||
294 | } | ||
295 | |||
296 | line6_start_listen(line6); | ||
297 | } | ||
298 | |||
299 | #define LINE6_READ_WRITE_STATUS_DELAY 2 /* milliseconds */ | ||
300 | #define LINE6_READ_WRITE_MAX_RETRIES 50 | ||
301 | |||
302 | /* | ||
303 | Read data from device. | ||
304 | */ | ||
305 | int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, | ||
306 | unsigned datalen) | ||
307 | { | ||
308 | struct usb_device *usbdev = line6->usbdev; | ||
309 | int ret; | ||
310 | unsigned char len; | ||
311 | unsigned count; | ||
312 | |||
313 | if (address > 0xffff || datalen > 0xff) | ||
314 | return -EINVAL; | ||
315 | |||
316 | /* query the serial number: */ | ||
317 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, | ||
318 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
319 | (datalen << 8) | 0x21, address, | ||
320 | NULL, 0, LINE6_TIMEOUT * HZ); | ||
321 | |||
322 | if (ret < 0) { | ||
323 | dev_err(line6->ifcdev, "read request failed (error %d)\n", ret); | ||
324 | return ret; | ||
325 | } | ||
326 | |||
327 | /* Wait for data length. We'll get 0xff until length arrives. */ | ||
328 | for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) { | ||
329 | mdelay(LINE6_READ_WRITE_STATUS_DELAY); | ||
330 | |||
331 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, | ||
332 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | | ||
333 | USB_DIR_IN, | ||
334 | 0x0012, 0x0000, &len, 1, | ||
335 | LINE6_TIMEOUT * HZ); | ||
336 | if (ret < 0) { | ||
337 | dev_err(line6->ifcdev, | ||
338 | "receive length failed (error %d)\n", ret); | ||
339 | return ret; | ||
340 | } | ||
341 | |||
342 | if (len != 0xff) | ||
343 | break; | ||
344 | } | ||
345 | |||
346 | if (len == 0xff) { | ||
347 | dev_err(line6->ifcdev, "read failed after %d retries\n", | ||
348 | count); | ||
349 | return -EIO; | ||
350 | } else if (len != datalen) { | ||
351 | /* should be equal or something went wrong */ | ||
352 | dev_err(line6->ifcdev, | ||
353 | "length mismatch (expected %d, got %d)\n", | ||
354 | (int)datalen, (int)len); | ||
355 | return -EIO; | ||
356 | } | ||
357 | |||
358 | /* receive the result: */ | ||
359 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, | ||
360 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
361 | 0x0013, 0x0000, data, datalen, | ||
362 | LINE6_TIMEOUT * HZ); | ||
363 | |||
364 | if (ret < 0) { | ||
365 | dev_err(line6->ifcdev, "read failed (error %d)\n", ret); | ||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | return 0; | ||
370 | } | ||
371 | EXPORT_SYMBOL_GPL(line6_read_data); | ||
372 | |||
373 | /* | ||
374 | Write data to device. | ||
375 | */ | ||
376 | int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, | ||
377 | unsigned datalen) | ||
378 | { | ||
379 | struct usb_device *usbdev = line6->usbdev; | ||
380 | int ret; | ||
381 | unsigned char status; | ||
382 | int count; | ||
383 | |||
384 | if (address > 0xffff || datalen > 0xffff) | ||
385 | return -EINVAL; | ||
386 | |||
387 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, | ||
388 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
389 | 0x0022, address, data, datalen, | ||
390 | LINE6_TIMEOUT * HZ); | ||
391 | |||
392 | if (ret < 0) { | ||
393 | dev_err(line6->ifcdev, | ||
394 | "write request failed (error %d)\n", ret); | ||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) { | ||
399 | mdelay(LINE6_READ_WRITE_STATUS_DELAY); | ||
400 | |||
401 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), | ||
402 | 0x67, | ||
403 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | | ||
404 | USB_DIR_IN, | ||
405 | 0x0012, 0x0000, | ||
406 | &status, 1, LINE6_TIMEOUT * HZ); | ||
407 | |||
408 | if (ret < 0) { | ||
409 | dev_err(line6->ifcdev, | ||
410 | "receiving status failed (error %d)\n", ret); | ||
411 | return ret; | ||
412 | } | ||
413 | |||
414 | if (status != 0xff) | ||
415 | break; | ||
416 | } | ||
417 | |||
418 | if (status == 0xff) { | ||
419 | dev_err(line6->ifcdev, "write failed after %d retries\n", | ||
420 | count); | ||
421 | return -EIO; | ||
422 | } else if (status != 0) { | ||
423 | dev_err(line6->ifcdev, "write failed (error %d)\n", ret); | ||
424 | return -EIO; | ||
425 | } | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | EXPORT_SYMBOL_GPL(line6_write_data); | ||
430 | |||
431 | /* | ||
432 | Read Line 6 device serial number. | ||
433 | (POD, TonePort, GuitarPort) | ||
434 | */ | ||
435 | int line6_read_serial_number(struct usb_line6 *line6, u32 *serial_number) | ||
436 | { | ||
437 | return line6_read_data(line6, 0x80d0, serial_number, | ||
438 | sizeof(*serial_number)); | ||
439 | } | ||
440 | EXPORT_SYMBOL_GPL(line6_read_serial_number); | ||
441 | |||
442 | /* | ||
443 | Card destructor. | ||
444 | */ | ||
445 | static void line6_destruct(struct snd_card *card) | ||
446 | { | ||
447 | struct usb_line6 *line6 = card->private_data; | ||
448 | struct usb_device *usbdev = line6->usbdev; | ||
449 | |||
450 | /* free buffer memory first: */ | ||
451 | kfree(line6->buffer_message); | ||
452 | kfree(line6->buffer_listen); | ||
453 | |||
454 | /* then free URBs: */ | ||
455 | usb_free_urb(line6->urb_listen); | ||
456 | |||
457 | /* decrement reference counters: */ | ||
458 | usb_put_dev(usbdev); | ||
459 | } | ||
460 | |||
461 | /* get data from endpoint descriptor (see usb_maxpacket): */ | ||
462 | static void line6_get_interval(struct usb_line6 *line6) | ||
463 | { | ||
464 | struct usb_device *usbdev = line6->usbdev; | ||
465 | struct usb_host_endpoint *ep; | ||
466 | unsigned pipe = usb_rcvintpipe(usbdev, line6->properties->ep_ctrl_r); | ||
467 | unsigned epnum = usb_pipeendpoint(pipe); | ||
468 | |||
469 | ep = usbdev->ep_in[epnum]; | ||
470 | if (ep) { | ||
471 | line6->interval = ep->desc.bInterval; | ||
472 | line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); | ||
473 | } else { | ||
474 | dev_err(line6->ifcdev, | ||
475 | "endpoint not available, using fallback values"); | ||
476 | line6->interval = LINE6_FALLBACK_INTERVAL; | ||
477 | line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE; | ||
478 | } | ||
479 | } | ||
480 | |||
481 | static int line6_init_cap_control(struct usb_line6 *line6) | ||
482 | { | ||
483 | int ret; | ||
484 | |||
485 | /* initialize USB buffers: */ | ||
486 | line6->buffer_listen = kmalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL); | ||
487 | if (!line6->buffer_listen) | ||
488 | return -ENOMEM; | ||
489 | |||
490 | line6->buffer_message = kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL); | ||
491 | if (!line6->buffer_message) | ||
492 | return -ENOMEM; | ||
493 | |||
494 | line6->urb_listen = usb_alloc_urb(0, GFP_KERNEL); | ||
495 | if (!line6->urb_listen) | ||
496 | return -ENOMEM; | ||
497 | |||
498 | ret = line6_start_listen(line6); | ||
499 | if (ret < 0) { | ||
500 | dev_err(line6->ifcdev, "cannot start listening: %d\n", ret); | ||
501 | return ret; | ||
502 | } | ||
503 | |||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | /* | ||
508 | Probe USB device. | ||
509 | */ | ||
510 | int line6_probe(struct usb_interface *interface, | ||
511 | const struct usb_device_id *id, | ||
512 | const char *driver_name, | ||
513 | const struct line6_properties *properties, | ||
514 | int (*private_init)(struct usb_line6 *, const struct usb_device_id *id), | ||
515 | size_t data_size) | ||
516 | { | ||
517 | struct usb_device *usbdev = interface_to_usbdev(interface); | ||
518 | struct snd_card *card; | ||
519 | struct usb_line6 *line6; | ||
520 | int interface_number; | ||
521 | int ret; | ||
522 | |||
523 | if (WARN_ON(data_size < sizeof(*line6))) | ||
524 | return -EINVAL; | ||
525 | |||
526 | /* we don't handle multiple configurations */ | ||
527 | if (usbdev->descriptor.bNumConfigurations != 1) | ||
528 | return -ENODEV; | ||
529 | |||
530 | ret = snd_card_new(&interface->dev, | ||
531 | SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | ||
532 | THIS_MODULE, data_size, &card); | ||
533 | if (ret < 0) | ||
534 | return ret; | ||
535 | |||
536 | /* store basic data: */ | ||
537 | line6 = card->private_data; | ||
538 | line6->card = card; | ||
539 | line6->properties = properties; | ||
540 | line6->usbdev = usbdev; | ||
541 | line6->ifcdev = &interface->dev; | ||
542 | |||
543 | strcpy(card->id, properties->id); | ||
544 | strcpy(card->driver, driver_name); | ||
545 | strcpy(card->shortname, properties->name); | ||
546 | sprintf(card->longname, "Line 6 %s at USB %s", properties->name, | ||
547 | dev_name(line6->ifcdev)); | ||
548 | card->private_free = line6_destruct; | ||
549 | |||
550 | usb_set_intfdata(interface, line6); | ||
551 | |||
552 | /* increment reference counters: */ | ||
553 | usb_get_dev(usbdev); | ||
554 | |||
555 | /* initialize device info: */ | ||
556 | dev_info(&interface->dev, "Line 6 %s found\n", properties->name); | ||
557 | |||
558 | /* query interface number */ | ||
559 | interface_number = interface->cur_altsetting->desc.bInterfaceNumber; | ||
560 | |||
561 | ret = usb_set_interface(usbdev, interface_number, | ||
562 | properties->altsetting); | ||
563 | if (ret < 0) { | ||
564 | dev_err(&interface->dev, "set_interface failed\n"); | ||
565 | goto error; | ||
566 | } | ||
567 | |||
568 | line6_get_interval(line6); | ||
569 | |||
570 | if (properties->capabilities & LINE6_CAP_CONTROL) { | ||
571 | ret = line6_init_cap_control(line6); | ||
572 | if (ret < 0) | ||
573 | goto error; | ||
574 | } | ||
575 | |||
576 | /* initialize device data based on device: */ | ||
577 | ret = private_init(line6, id); | ||
578 | if (ret < 0) | ||
579 | goto error; | ||
580 | |||
581 | /* creation of additional special files should go here */ | ||
582 | |||
583 | dev_info(&interface->dev, "Line 6 %s now attached\n", | ||
584 | properties->name); | ||
585 | |||
586 | return 0; | ||
587 | |||
588 | error: | ||
589 | if (line6->disconnect) | ||
590 | line6->disconnect(line6); | ||
591 | snd_card_free(card); | ||
592 | return ret; | ||
593 | } | ||
594 | EXPORT_SYMBOL_GPL(line6_probe); | ||
595 | |||
596 | /* | ||
597 | Line 6 device disconnected. | ||
598 | */ | ||
599 | void line6_disconnect(struct usb_interface *interface) | ||
600 | { | ||
601 | struct usb_line6 *line6 = usb_get_intfdata(interface); | ||
602 | struct usb_device *usbdev = interface_to_usbdev(interface); | ||
603 | |||
604 | if (!line6) | ||
605 | return; | ||
606 | |||
607 | if (WARN_ON(usbdev != line6->usbdev)) | ||
608 | return; | ||
609 | |||
610 | if (line6->urb_listen != NULL) | ||
611 | line6_stop_listen(line6); | ||
612 | |||
613 | snd_card_disconnect(line6->card); | ||
614 | if (line6->line6pcm) | ||
615 | line6_pcm_disconnect(line6->line6pcm); | ||
616 | if (line6->disconnect) | ||
617 | line6->disconnect(line6); | ||
618 | |||
619 | dev_info(&interface->dev, "Line 6 %s now disconnected\n", | ||
620 | line6->properties->name); | ||
621 | |||
622 | /* make sure the device isn't destructed twice: */ | ||
623 | usb_set_intfdata(interface, NULL); | ||
624 | |||
625 | snd_card_free_when_closed(line6->card); | ||
626 | } | ||
627 | EXPORT_SYMBOL_GPL(line6_disconnect); | ||
628 | |||
629 | #ifdef CONFIG_PM | ||
630 | |||
631 | /* | ||
632 | Suspend Line 6 device. | ||
633 | */ | ||
634 | int line6_suspend(struct usb_interface *interface, pm_message_t message) | ||
635 | { | ||
636 | struct usb_line6 *line6 = usb_get_intfdata(interface); | ||
637 | struct snd_line6_pcm *line6pcm = line6->line6pcm; | ||
638 | |||
639 | snd_power_change_state(line6->card, SNDRV_CTL_POWER_D3hot); | ||
640 | |||
641 | if (line6->properties->capabilities & LINE6_CAP_CONTROL) | ||
642 | line6_stop_listen(line6); | ||
643 | |||
644 | if (line6pcm != NULL) { | ||
645 | snd_pcm_suspend_all(line6pcm->pcm); | ||
646 | line6pcm->flags = 0; | ||
647 | } | ||
648 | |||
649 | return 0; | ||
650 | } | ||
651 | EXPORT_SYMBOL_GPL(line6_suspend); | ||
652 | |||
653 | /* | ||
654 | Resume Line 6 device. | ||
655 | */ | ||
656 | int line6_resume(struct usb_interface *interface) | ||
657 | { | ||
658 | struct usb_line6 *line6 = usb_get_intfdata(interface); | ||
659 | |||
660 | if (line6->properties->capabilities & LINE6_CAP_CONTROL) | ||
661 | line6_start_listen(line6); | ||
662 | |||
663 | snd_power_change_state(line6->card, SNDRV_CTL_POWER_D0); | ||
664 | return 0; | ||
665 | } | ||
666 | EXPORT_SYMBOL_GPL(line6_resume); | ||
667 | |||
668 | #endif /* CONFIG_PM */ | ||
669 | |||
670 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
671 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
672 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h new file mode 100644 index 000000000000..7da643e79e3b --- /dev/null +++ b/sound/usb/line6/driver.h | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef DRIVER_H | ||
13 | #define DRIVER_H | ||
14 | |||
15 | #include <linux/spinlock.h> | ||
16 | #include <linux/usb.h> | ||
17 | #include <sound/core.h> | ||
18 | |||
19 | #include "midi.h" | ||
20 | |||
21 | #define USB_INTERVALS_PER_SECOND 1000 | ||
22 | |||
23 | /* Fallback USB interval and max packet size values */ | ||
24 | #define LINE6_FALLBACK_INTERVAL 10 | ||
25 | #define LINE6_FALLBACK_MAXPACKETSIZE 16 | ||
26 | |||
27 | #define LINE6_TIMEOUT 1 | ||
28 | #define LINE6_BUFSIZE_LISTEN 32 | ||
29 | #define LINE6_MESSAGE_MAXLEN 256 | ||
30 | |||
31 | /* | ||
32 | Line 6 MIDI control commands | ||
33 | */ | ||
34 | #define LINE6_PARAM_CHANGE 0xb0 | ||
35 | #define LINE6_PROGRAM_CHANGE 0xc0 | ||
36 | #define LINE6_SYSEX_BEGIN 0xf0 | ||
37 | #define LINE6_SYSEX_END 0xf7 | ||
38 | #define LINE6_RESET 0xff | ||
39 | |||
40 | /* | ||
41 | MIDI channel for messages initiated by the host | ||
42 | (and eventually echoed back by the device) | ||
43 | */ | ||
44 | #define LINE6_CHANNEL_HOST 0x00 | ||
45 | |||
46 | /* | ||
47 | MIDI channel for messages initiated by the device | ||
48 | */ | ||
49 | #define LINE6_CHANNEL_DEVICE 0x02 | ||
50 | |||
51 | #define LINE6_CHANNEL_UNKNOWN 5 /* don't know yet what this is good for */ | ||
52 | |||
53 | #define LINE6_CHANNEL_MASK 0x0f | ||
54 | |||
55 | #define CHECK_STARTUP_PROGRESS(x, n) \ | ||
56 | do { \ | ||
57 | if ((x) >= (n)) \ | ||
58 | return; \ | ||
59 | x = (n); \ | ||
60 | } while (0) | ||
61 | |||
62 | extern const unsigned char line6_midi_id[3]; | ||
63 | |||
64 | static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3; | ||
65 | static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4; | ||
66 | |||
67 | /* | ||
68 | Common properties of Line 6 devices. | ||
69 | */ | ||
70 | struct line6_properties { | ||
71 | /* Card id string (maximum 16 characters). | ||
72 | * This can be used to address the device in ALSA programs as | ||
73 | * "default:CARD=<id>" | ||
74 | */ | ||
75 | const char *id; | ||
76 | |||
77 | /* Card short name (maximum 32 characters) */ | ||
78 | const char *name; | ||
79 | |||
80 | /* Bit vector defining this device's capabilities in line6usb driver */ | ||
81 | int capabilities; | ||
82 | |||
83 | int altsetting; | ||
84 | |||
85 | unsigned ep_ctrl_r; | ||
86 | unsigned ep_ctrl_w; | ||
87 | unsigned ep_audio_r; | ||
88 | unsigned ep_audio_w; | ||
89 | }; | ||
90 | |||
91 | /* Capability bits */ | ||
92 | enum { | ||
93 | /* device supports settings parameter via USB */ | ||
94 | LINE6_CAP_CONTROL = 1 << 0, | ||
95 | /* device supports PCM input/output via USB */ | ||
96 | LINE6_CAP_PCM = 1 << 1, | ||
97 | /* device support hardware monitoring */ | ||
98 | LINE6_CAP_HWMON = 1 << 2, | ||
99 | }; | ||
100 | |||
101 | /* | ||
102 | Common data shared by all Line 6 devices. | ||
103 | Corresponds to a pair of USB endpoints. | ||
104 | */ | ||
105 | struct usb_line6 { | ||
106 | /* USB device */ | ||
107 | struct usb_device *usbdev; | ||
108 | |||
109 | /* Properties */ | ||
110 | const struct line6_properties *properties; | ||
111 | |||
112 | /* Interval (ms) */ | ||
113 | int interval; | ||
114 | |||
115 | /* Maximum size of USB packet */ | ||
116 | int max_packet_size; | ||
117 | |||
118 | /* Device representing the USB interface */ | ||
119 | struct device *ifcdev; | ||
120 | |||
121 | /* Line 6 sound card data structure. | ||
122 | * Each device has at least MIDI or PCM. | ||
123 | */ | ||
124 | struct snd_card *card; | ||
125 | |||
126 | /* Line 6 PCM device data structure */ | ||
127 | struct snd_line6_pcm *line6pcm; | ||
128 | |||
129 | /* Line 6 MIDI device data structure */ | ||
130 | struct snd_line6_midi *line6midi; | ||
131 | |||
132 | /* URB for listening to PODxt Pro control endpoint */ | ||
133 | struct urb *urb_listen; | ||
134 | |||
135 | /* Buffer for listening to PODxt Pro control endpoint */ | ||
136 | unsigned char *buffer_listen; | ||
137 | |||
138 | /* Buffer for message to be processed */ | ||
139 | unsigned char *buffer_message; | ||
140 | |||
141 | /* Length of message to be processed */ | ||
142 | int message_length; | ||
143 | |||
144 | void (*process_message)(struct usb_line6 *); | ||
145 | void (*disconnect)(struct usb_line6 *line6); | ||
146 | }; | ||
147 | |||
148 | extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, | ||
149 | int code2, int size); | ||
150 | extern int line6_read_data(struct usb_line6 *line6, unsigned address, | ||
151 | void *data, unsigned datalen); | ||
152 | extern int line6_read_serial_number(struct usb_line6 *line6, | ||
153 | u32 *serial_number); | ||
154 | extern int line6_send_raw_message_async(struct usb_line6 *line6, | ||
155 | const char *buffer, int size); | ||
156 | extern int line6_send_sysex_message(struct usb_line6 *line6, | ||
157 | const char *buffer, int size); | ||
158 | extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr, | ||
159 | const char *buf, size_t count); | ||
160 | extern void line6_start_timer(struct timer_list *timer, unsigned long msecs, | ||
161 | void (*function)(unsigned long), | ||
162 | unsigned long data); | ||
163 | extern int line6_version_request_async(struct usb_line6 *line6); | ||
164 | extern int line6_write_data(struct usb_line6 *line6, unsigned address, | ||
165 | void *data, unsigned datalen); | ||
166 | |||
167 | int line6_probe(struct usb_interface *interface, | ||
168 | const struct usb_device_id *id, | ||
169 | const char *driver_name, | ||
170 | const struct line6_properties *properties, | ||
171 | int (*private_init)(struct usb_line6 *, const struct usb_device_id *id), | ||
172 | size_t data_size); | ||
173 | |||
174 | void line6_disconnect(struct usb_interface *interface); | ||
175 | |||
176 | #ifdef CONFIG_PM | ||
177 | int line6_suspend(struct usb_interface *interface, pm_message_t message); | ||
178 | int line6_resume(struct usb_interface *interface); | ||
179 | #endif | ||
180 | |||
181 | #endif | ||
diff --git a/sound/usb/line6/midi.c b/sound/usb/line6/midi.c new file mode 100644 index 000000000000..cebea9b7f769 --- /dev/null +++ b/sound/usb/line6/midi.c | |||
@@ -0,0 +1,292 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/slab.h> | ||
13 | #include <linux/usb.h> | ||
14 | #include <linux/export.h> | ||
15 | #include <sound/core.h> | ||
16 | #include <sound/rawmidi.h> | ||
17 | |||
18 | #include "driver.h" | ||
19 | #include "midi.h" | ||
20 | |||
21 | #define line6_rawmidi_substream_midi(substream) \ | ||
22 | ((struct snd_line6_midi *)((substream)->rmidi->private_data)) | ||
23 | |||
24 | static int send_midi_async(struct usb_line6 *line6, unsigned char *data, | ||
25 | int length); | ||
26 | |||
27 | /* | ||
28 | Pass data received via USB to MIDI. | ||
29 | */ | ||
30 | void line6_midi_receive(struct usb_line6 *line6, unsigned char *data, | ||
31 | int length) | ||
32 | { | ||
33 | if (line6->line6midi->substream_receive) | ||
34 | snd_rawmidi_receive(line6->line6midi->substream_receive, | ||
35 | data, length); | ||
36 | } | ||
37 | |||
38 | /* | ||
39 | Read data from MIDI buffer and transmit them via USB. | ||
40 | */ | ||
41 | static void line6_midi_transmit(struct snd_rawmidi_substream *substream) | ||
42 | { | ||
43 | struct usb_line6 *line6 = | ||
44 | line6_rawmidi_substream_midi(substream)->line6; | ||
45 | struct snd_line6_midi *line6midi = line6->line6midi; | ||
46 | struct midi_buffer *mb = &line6midi->midibuf_out; | ||
47 | unsigned char chunk[LINE6_FALLBACK_MAXPACKETSIZE]; | ||
48 | int req, done; | ||
49 | |||
50 | for (;;) { | ||
51 | req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size); | ||
52 | done = snd_rawmidi_transmit_peek(substream, chunk, req); | ||
53 | |||
54 | if (done == 0) | ||
55 | break; | ||
56 | |||
57 | line6_midibuf_write(mb, chunk, done); | ||
58 | snd_rawmidi_transmit_ack(substream, done); | ||
59 | } | ||
60 | |||
61 | for (;;) { | ||
62 | done = line6_midibuf_read(mb, chunk, | ||
63 | LINE6_FALLBACK_MAXPACKETSIZE); | ||
64 | |||
65 | if (done == 0) | ||
66 | break; | ||
67 | |||
68 | send_midi_async(line6, chunk, done); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | Notification of completion of MIDI transmission. | ||
74 | */ | ||
75 | static void midi_sent(struct urb *urb) | ||
76 | { | ||
77 | unsigned long flags; | ||
78 | int status; | ||
79 | int num; | ||
80 | struct usb_line6 *line6 = (struct usb_line6 *)urb->context; | ||
81 | |||
82 | status = urb->status; | ||
83 | kfree(urb->transfer_buffer); | ||
84 | usb_free_urb(urb); | ||
85 | |||
86 | if (status == -ESHUTDOWN) | ||
87 | return; | ||
88 | |||
89 | spin_lock_irqsave(&line6->line6midi->lock, flags); | ||
90 | num = --line6->line6midi->num_active_send_urbs; | ||
91 | |||
92 | if (num == 0) { | ||
93 | line6_midi_transmit(line6->line6midi->substream_transmit); | ||
94 | num = line6->line6midi->num_active_send_urbs; | ||
95 | } | ||
96 | |||
97 | if (num == 0) | ||
98 | wake_up(&line6->line6midi->send_wait); | ||
99 | |||
100 | spin_unlock_irqrestore(&line6->line6midi->lock, flags); | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | Send an asynchronous MIDI message. | ||
105 | Assumes that line6->line6midi->lock is held | ||
106 | (i.e., this function is serialized). | ||
107 | */ | ||
108 | static int send_midi_async(struct usb_line6 *line6, unsigned char *data, | ||
109 | int length) | ||
110 | { | ||
111 | struct urb *urb; | ||
112 | int retval; | ||
113 | unsigned char *transfer_buffer; | ||
114 | |||
115 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
116 | |||
117 | if (urb == NULL) | ||
118 | return -ENOMEM; | ||
119 | |||
120 | transfer_buffer = kmemdup(data, length, GFP_ATOMIC); | ||
121 | |||
122 | if (transfer_buffer == NULL) { | ||
123 | usb_free_urb(urb); | ||
124 | return -ENOMEM; | ||
125 | } | ||
126 | |||
127 | usb_fill_int_urb(urb, line6->usbdev, | ||
128 | usb_sndbulkpipe(line6->usbdev, | ||
129 | line6->properties->ep_ctrl_w), | ||
130 | transfer_buffer, length, midi_sent, line6, | ||
131 | line6->interval); | ||
132 | urb->actual_length = 0; | ||
133 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
134 | |||
135 | if (retval < 0) { | ||
136 | dev_err(line6->ifcdev, "usb_submit_urb failed\n"); | ||
137 | usb_free_urb(urb); | ||
138 | return retval; | ||
139 | } | ||
140 | |||
141 | ++line6->line6midi->num_active_send_urbs; | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int line6_midi_output_open(struct snd_rawmidi_substream *substream) | ||
146 | { | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static int line6_midi_output_close(struct snd_rawmidi_substream *substream) | ||
151 | { | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream, | ||
156 | int up) | ||
157 | { | ||
158 | unsigned long flags; | ||
159 | struct usb_line6 *line6 = | ||
160 | line6_rawmidi_substream_midi(substream)->line6; | ||
161 | |||
162 | line6->line6midi->substream_transmit = substream; | ||
163 | spin_lock_irqsave(&line6->line6midi->lock, flags); | ||
164 | |||
165 | if (line6->line6midi->num_active_send_urbs == 0) | ||
166 | line6_midi_transmit(substream); | ||
167 | |||
168 | spin_unlock_irqrestore(&line6->line6midi->lock, flags); | ||
169 | } | ||
170 | |||
171 | static void line6_midi_output_drain(struct snd_rawmidi_substream *substream) | ||
172 | { | ||
173 | struct usb_line6 *line6 = | ||
174 | line6_rawmidi_substream_midi(substream)->line6; | ||
175 | struct snd_line6_midi *midi = line6->line6midi; | ||
176 | |||
177 | wait_event_interruptible(midi->send_wait, | ||
178 | midi->num_active_send_urbs == 0); | ||
179 | } | ||
180 | |||
181 | static int line6_midi_input_open(struct snd_rawmidi_substream *substream) | ||
182 | { | ||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static int line6_midi_input_close(struct snd_rawmidi_substream *substream) | ||
187 | { | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream, | ||
192 | int up) | ||
193 | { | ||
194 | struct usb_line6 *line6 = | ||
195 | line6_rawmidi_substream_midi(substream)->line6; | ||
196 | |||
197 | if (up) | ||
198 | line6->line6midi->substream_receive = substream; | ||
199 | else | ||
200 | line6->line6midi->substream_receive = NULL; | ||
201 | } | ||
202 | |||
203 | static struct snd_rawmidi_ops line6_midi_output_ops = { | ||
204 | .open = line6_midi_output_open, | ||
205 | .close = line6_midi_output_close, | ||
206 | .trigger = line6_midi_output_trigger, | ||
207 | .drain = line6_midi_output_drain, | ||
208 | }; | ||
209 | |||
210 | static struct snd_rawmidi_ops line6_midi_input_ops = { | ||
211 | .open = line6_midi_input_open, | ||
212 | .close = line6_midi_input_close, | ||
213 | .trigger = line6_midi_input_trigger, | ||
214 | }; | ||
215 | |||
216 | /* Create a MIDI device */ | ||
217 | static int snd_line6_new_midi(struct usb_line6 *line6, | ||
218 | struct snd_rawmidi **rmidi_ret) | ||
219 | { | ||
220 | struct snd_rawmidi *rmidi; | ||
221 | int err; | ||
222 | |||
223 | err = snd_rawmidi_new(line6->card, "Line 6 MIDI", 0, 1, 1, rmidi_ret); | ||
224 | if (err < 0) | ||
225 | return err; | ||
226 | |||
227 | rmidi = *rmidi_ret; | ||
228 | strcpy(rmidi->id, line6->properties->id); | ||
229 | strcpy(rmidi->name, line6->properties->name); | ||
230 | |||
231 | rmidi->info_flags = | ||
232 | SNDRV_RAWMIDI_INFO_OUTPUT | | ||
233 | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; | ||
234 | |||
235 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, | ||
236 | &line6_midi_output_ops); | ||
237 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | ||
238 | &line6_midi_input_ops); | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | /* MIDI device destructor */ | ||
243 | static void snd_line6_midi_free(struct snd_rawmidi *rmidi) | ||
244 | { | ||
245 | struct snd_line6_midi *line6midi = rmidi->private_data; | ||
246 | |||
247 | line6_midibuf_destroy(&line6midi->midibuf_in); | ||
248 | line6_midibuf_destroy(&line6midi->midibuf_out); | ||
249 | kfree(line6midi); | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | Initialize the Line 6 MIDI subsystem. | ||
254 | */ | ||
255 | int line6_init_midi(struct usb_line6 *line6) | ||
256 | { | ||
257 | int err; | ||
258 | struct snd_rawmidi *rmidi; | ||
259 | struct snd_line6_midi *line6midi; | ||
260 | |||
261 | if (!(line6->properties->capabilities & LINE6_CAP_CONTROL)) { | ||
262 | /* skip MIDI initialization and report success */ | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | err = snd_line6_new_midi(line6, &rmidi); | ||
267 | if (err < 0) | ||
268 | return err; | ||
269 | |||
270 | line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL); | ||
271 | if (!line6midi) | ||
272 | return -ENOMEM; | ||
273 | |||
274 | rmidi->private_data = line6midi; | ||
275 | rmidi->private_free = snd_line6_midi_free; | ||
276 | |||
277 | init_waitqueue_head(&line6midi->send_wait); | ||
278 | spin_lock_init(&line6midi->lock); | ||
279 | line6midi->line6 = line6; | ||
280 | |||
281 | err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0); | ||
282 | if (err < 0) | ||
283 | return err; | ||
284 | |||
285 | err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1); | ||
286 | if (err < 0) | ||
287 | return err; | ||
288 | |||
289 | line6->line6midi = line6midi; | ||
290 | return 0; | ||
291 | } | ||
292 | EXPORT_SYMBOL_GPL(line6_init_midi); | ||
diff --git a/sound/usb/line6/midi.h b/sound/usb/line6/midi.h new file mode 100644 index 000000000000..cf82d69e2747 --- /dev/null +++ b/sound/usb/line6/midi.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef MIDI_H | ||
13 | #define MIDI_H | ||
14 | |||
15 | #include <sound/rawmidi.h> | ||
16 | |||
17 | #include "midibuf.h" | ||
18 | |||
19 | #define MIDI_BUFFER_SIZE 1024 | ||
20 | |||
21 | struct snd_line6_midi { | ||
22 | /* Pointer back to the Line 6 driver data structure */ | ||
23 | struct usb_line6 *line6; | ||
24 | |||
25 | /* MIDI substream for receiving (or NULL if not active) */ | ||
26 | struct snd_rawmidi_substream *substream_receive; | ||
27 | |||
28 | /* MIDI substream for transmitting (or NULL if not active) */ | ||
29 | struct snd_rawmidi_substream *substream_transmit; | ||
30 | |||
31 | /* Number of currently active MIDI send URBs */ | ||
32 | int num_active_send_urbs; | ||
33 | |||
34 | /* Spin lock to protect MIDI buffer handling */ | ||
35 | spinlock_t lock; | ||
36 | |||
37 | /* Wait queue for MIDI transmission */ | ||
38 | wait_queue_head_t send_wait; | ||
39 | |||
40 | /* Buffer for incoming MIDI stream */ | ||
41 | struct midi_buffer midibuf_in; | ||
42 | |||
43 | /* Buffer for outgoing MIDI stream */ | ||
44 | struct midi_buffer midibuf_out; | ||
45 | }; | ||
46 | |||
47 | extern int line6_init_midi(struct usb_line6 *line6); | ||
48 | extern void line6_midi_receive(struct usb_line6 *line6, unsigned char *data, | ||
49 | int length); | ||
50 | |||
51 | #endif | ||
diff --git a/sound/usb/line6/midibuf.c b/sound/usb/line6/midibuf.c new file mode 100644 index 000000000000..36a610ba342e --- /dev/null +++ b/sound/usb/line6/midibuf.c | |||
@@ -0,0 +1,252 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/slab.h> | ||
13 | |||
14 | #include "midibuf.h" | ||
15 | |||
16 | static int midibuf_message_length(unsigned char code) | ||
17 | { | ||
18 | int message_length; | ||
19 | |||
20 | if (code < 0x80) | ||
21 | message_length = -1; | ||
22 | else if (code < 0xf0) { | ||
23 | static const int length[] = { 3, 3, 3, 3, 2, 2, 3 }; | ||
24 | |||
25 | message_length = length[(code >> 4) - 8]; | ||
26 | } else { | ||
27 | /* | ||
28 | Note that according to the MIDI specification 0xf2 is | ||
29 | the "Song Position Pointer", but this is used by Line 6 | ||
30 | to send sysex messages to the host. | ||
31 | */ | ||
32 | static const int length[] = { -1, 2, -1, 2, -1, -1, 1, 1, 1, 1, | ||
33 | 1, 1, 1, -1, 1, 1 | ||
34 | }; | ||
35 | message_length = length[code & 0x0f]; | ||
36 | } | ||
37 | |||
38 | return message_length; | ||
39 | } | ||
40 | |||
41 | static int midibuf_is_empty(struct midi_buffer *this) | ||
42 | { | ||
43 | return (this->pos_read == this->pos_write) && !this->full; | ||
44 | } | ||
45 | |||
46 | static int midibuf_is_full(struct midi_buffer *this) | ||
47 | { | ||
48 | return this->full; | ||
49 | } | ||
50 | |||
51 | void line6_midibuf_reset(struct midi_buffer *this) | ||
52 | { | ||
53 | this->pos_read = this->pos_write = this->full = 0; | ||
54 | this->command_prev = -1; | ||
55 | } | ||
56 | |||
57 | int line6_midibuf_init(struct midi_buffer *this, int size, int split) | ||
58 | { | ||
59 | this->buf = kmalloc(size, GFP_KERNEL); | ||
60 | |||
61 | if (this->buf == NULL) | ||
62 | return -ENOMEM; | ||
63 | |||
64 | this->size = size; | ||
65 | this->split = split; | ||
66 | line6_midibuf_reset(this); | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | int line6_midibuf_bytes_free(struct midi_buffer *this) | ||
71 | { | ||
72 | return | ||
73 | midibuf_is_full(this) ? | ||
74 | 0 : | ||
75 | (this->pos_read - this->pos_write + this->size - 1) % this->size + | ||
76 | 1; | ||
77 | } | ||
78 | |||
79 | int line6_midibuf_bytes_used(struct midi_buffer *this) | ||
80 | { | ||
81 | return | ||
82 | midibuf_is_empty(this) ? | ||
83 | 0 : | ||
84 | (this->pos_write - this->pos_read + this->size - 1) % this->size + | ||
85 | 1; | ||
86 | } | ||
87 | |||
88 | int line6_midibuf_write(struct midi_buffer *this, unsigned char *data, | ||
89 | int length) | ||
90 | { | ||
91 | int bytes_free; | ||
92 | int length1, length2; | ||
93 | int skip_active_sense = 0; | ||
94 | |||
95 | if (midibuf_is_full(this) || (length <= 0)) | ||
96 | return 0; | ||
97 | |||
98 | /* skip trailing active sense */ | ||
99 | if (data[length - 1] == 0xfe) { | ||
100 | --length; | ||
101 | skip_active_sense = 1; | ||
102 | } | ||
103 | |||
104 | bytes_free = line6_midibuf_bytes_free(this); | ||
105 | |||
106 | if (length > bytes_free) | ||
107 | length = bytes_free; | ||
108 | |||
109 | if (length > 0) { | ||
110 | length1 = this->size - this->pos_write; | ||
111 | |||
112 | if (length < length1) { | ||
113 | /* no buffer wraparound */ | ||
114 | memcpy(this->buf + this->pos_write, data, length); | ||
115 | this->pos_write += length; | ||
116 | } else { | ||
117 | /* buffer wraparound */ | ||
118 | length2 = length - length1; | ||
119 | memcpy(this->buf + this->pos_write, data, length1); | ||
120 | memcpy(this->buf, data + length1, length2); | ||
121 | this->pos_write = length2; | ||
122 | } | ||
123 | |||
124 | if (this->pos_write == this->pos_read) | ||
125 | this->full = 1; | ||
126 | } | ||
127 | |||
128 | return length + skip_active_sense; | ||
129 | } | ||
130 | |||
131 | int line6_midibuf_read(struct midi_buffer *this, unsigned char *data, | ||
132 | int length) | ||
133 | { | ||
134 | int bytes_used; | ||
135 | int length1, length2; | ||
136 | int command; | ||
137 | int midi_length; | ||
138 | int repeat = 0; | ||
139 | int i; | ||
140 | |||
141 | /* we need to be able to store at least a 3 byte MIDI message */ | ||
142 | if (length < 3) | ||
143 | return -EINVAL; | ||
144 | |||
145 | if (midibuf_is_empty(this)) | ||
146 | return 0; | ||
147 | |||
148 | bytes_used = line6_midibuf_bytes_used(this); | ||
149 | |||
150 | if (length > bytes_used) | ||
151 | length = bytes_used; | ||
152 | |||
153 | length1 = this->size - this->pos_read; | ||
154 | |||
155 | /* check MIDI command length */ | ||
156 | command = this->buf[this->pos_read]; | ||
157 | |||
158 | if (command & 0x80) { | ||
159 | midi_length = midibuf_message_length(command); | ||
160 | this->command_prev = command; | ||
161 | } else { | ||
162 | if (this->command_prev > 0) { | ||
163 | int midi_length_prev = | ||
164 | midibuf_message_length(this->command_prev); | ||
165 | |||
166 | if (midi_length_prev > 0) { | ||
167 | midi_length = midi_length_prev - 1; | ||
168 | repeat = 1; | ||
169 | } else | ||
170 | midi_length = -1; | ||
171 | } else | ||
172 | midi_length = -1; | ||
173 | } | ||
174 | |||
175 | if (midi_length < 0) { | ||
176 | /* search for end of message */ | ||
177 | if (length < length1) { | ||
178 | /* no buffer wraparound */ | ||
179 | for (i = 1; i < length; ++i) | ||
180 | if (this->buf[this->pos_read + i] & 0x80) | ||
181 | break; | ||
182 | |||
183 | midi_length = i; | ||
184 | } else { | ||
185 | /* buffer wraparound */ | ||
186 | length2 = length - length1; | ||
187 | |||
188 | for (i = 1; i < length1; ++i) | ||
189 | if (this->buf[this->pos_read + i] & 0x80) | ||
190 | break; | ||
191 | |||
192 | if (i < length1) | ||
193 | midi_length = i; | ||
194 | else { | ||
195 | for (i = 0; i < length2; ++i) | ||
196 | if (this->buf[i] & 0x80) | ||
197 | break; | ||
198 | |||
199 | midi_length = length1 + i; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | if (midi_length == length) | ||
204 | midi_length = -1; /* end of message not found */ | ||
205 | } | ||
206 | |||
207 | if (midi_length < 0) { | ||
208 | if (!this->split) | ||
209 | return 0; /* command is not yet complete */ | ||
210 | } else { | ||
211 | if (length < midi_length) | ||
212 | return 0; /* command is not yet complete */ | ||
213 | |||
214 | length = midi_length; | ||
215 | } | ||
216 | |||
217 | if (length < length1) { | ||
218 | /* no buffer wraparound */ | ||
219 | memcpy(data + repeat, this->buf + this->pos_read, length); | ||
220 | this->pos_read += length; | ||
221 | } else { | ||
222 | /* buffer wraparound */ | ||
223 | length2 = length - length1; | ||
224 | memcpy(data + repeat, this->buf + this->pos_read, length1); | ||
225 | memcpy(data + repeat + length1, this->buf, length2); | ||
226 | this->pos_read = length2; | ||
227 | } | ||
228 | |||
229 | if (repeat) | ||
230 | data[0] = this->command_prev; | ||
231 | |||
232 | this->full = 0; | ||
233 | return length + repeat; | ||
234 | } | ||
235 | |||
236 | int line6_midibuf_ignore(struct midi_buffer *this, int length) | ||
237 | { | ||
238 | int bytes_used = line6_midibuf_bytes_used(this); | ||
239 | |||
240 | if (length > bytes_used) | ||
241 | length = bytes_used; | ||
242 | |||
243 | this->pos_read = (this->pos_read + length) % this->size; | ||
244 | this->full = 0; | ||
245 | return length; | ||
246 | } | ||
247 | |||
248 | void line6_midibuf_destroy(struct midi_buffer *this) | ||
249 | { | ||
250 | kfree(this->buf); | ||
251 | this->buf = NULL; | ||
252 | } | ||
diff --git a/sound/usb/line6/midibuf.h b/sound/usb/line6/midibuf.h new file mode 100644 index 000000000000..6ea21ffb6627 --- /dev/null +++ b/sound/usb/line6/midibuf.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef MIDIBUF_H | ||
13 | #define MIDIBUF_H | ||
14 | |||
15 | struct midi_buffer { | ||
16 | unsigned char *buf; | ||
17 | int size; | ||
18 | int split; | ||
19 | int pos_read, pos_write; | ||
20 | int full; | ||
21 | int command_prev; | ||
22 | }; | ||
23 | |||
24 | extern int line6_midibuf_bytes_used(struct midi_buffer *mb); | ||
25 | extern int line6_midibuf_bytes_free(struct midi_buffer *mb); | ||
26 | extern void line6_midibuf_destroy(struct midi_buffer *mb); | ||
27 | extern int line6_midibuf_ignore(struct midi_buffer *mb, int length); | ||
28 | extern int line6_midibuf_init(struct midi_buffer *mb, int size, int split); | ||
29 | extern int line6_midibuf_read(struct midi_buffer *mb, unsigned char *data, | ||
30 | int length); | ||
31 | extern void line6_midibuf_reset(struct midi_buffer *mb); | ||
32 | extern int line6_midibuf_write(struct midi_buffer *mb, unsigned char *data, | ||
33 | int length); | ||
34 | |||
35 | #endif | ||
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c new file mode 100644 index 000000000000..8461d6bf992f --- /dev/null +++ b/sound/usb/line6/pcm.c | |||
@@ -0,0 +1,588 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/slab.h> | ||
13 | #include <linux/export.h> | ||
14 | #include <sound/core.h> | ||
15 | #include <sound/control.h> | ||
16 | #include <sound/pcm.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | |||
19 | #include "capture.h" | ||
20 | #include "driver.h" | ||
21 | #include "playback.h" | ||
22 | |||
23 | /* impulse response volume controls */ | ||
24 | static int snd_line6_impulse_volume_info(struct snd_kcontrol *kcontrol, | ||
25 | struct snd_ctl_elem_info *uinfo) | ||
26 | { | ||
27 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
28 | uinfo->count = 1; | ||
29 | uinfo->value.integer.min = 0; | ||
30 | uinfo->value.integer.max = 255; | ||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | static int snd_line6_impulse_volume_get(struct snd_kcontrol *kcontrol, | ||
35 | struct snd_ctl_elem_value *ucontrol) | ||
36 | { | ||
37 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); | ||
38 | |||
39 | ucontrol->value.integer.value[0] = line6pcm->impulse_volume; | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol, | ||
44 | struct snd_ctl_elem_value *ucontrol) | ||
45 | { | ||
46 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); | ||
47 | int value = ucontrol->value.integer.value[0]; | ||
48 | int err; | ||
49 | |||
50 | if (line6pcm->impulse_volume == value) | ||
51 | return 0; | ||
52 | |||
53 | line6pcm->impulse_volume = value; | ||
54 | if (value > 0) { | ||
55 | err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE); | ||
56 | if (err < 0) { | ||
57 | line6pcm->impulse_volume = 0; | ||
58 | line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE); | ||
59 | return err; | ||
60 | } | ||
61 | } else { | ||
62 | line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE); | ||
63 | } | ||
64 | return 1; | ||
65 | } | ||
66 | |||
67 | /* impulse response period controls */ | ||
68 | static int snd_line6_impulse_period_info(struct snd_kcontrol *kcontrol, | ||
69 | struct snd_ctl_elem_info *uinfo) | ||
70 | { | ||
71 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
72 | uinfo->count = 1; | ||
73 | uinfo->value.integer.min = 0; | ||
74 | uinfo->value.integer.max = 2000; | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static int snd_line6_impulse_period_get(struct snd_kcontrol *kcontrol, | ||
79 | struct snd_ctl_elem_value *ucontrol) | ||
80 | { | ||
81 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); | ||
82 | |||
83 | ucontrol->value.integer.value[0] = line6pcm->impulse_period; | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int snd_line6_impulse_period_put(struct snd_kcontrol *kcontrol, | ||
88 | struct snd_ctl_elem_value *ucontrol) | ||
89 | { | ||
90 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); | ||
91 | int value = ucontrol->value.integer.value[0]; | ||
92 | |||
93 | if (line6pcm->impulse_period == value) | ||
94 | return 0; | ||
95 | |||
96 | line6pcm->impulse_period = value; | ||
97 | return 1; | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | Unlink all currently active URBs. | ||
102 | */ | ||
103 | static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm, | ||
104 | struct line6_pcm_stream *pcms) | ||
105 | { | ||
106 | int i; | ||
107 | |||
108 | for (i = 0; i < LINE6_ISO_BUFFERS; i++) { | ||
109 | if (test_bit(i, &pcms->active_urbs)) { | ||
110 | if (!test_and_set_bit(i, &pcms->unlink_urbs)) | ||
111 | usb_unlink_urb(pcms->urbs[i]); | ||
112 | } | ||
113 | } | ||
114 | } | ||
115 | |||
116 | /* | ||
117 | Wait until unlinking of all currently active URBs has been finished. | ||
118 | */ | ||
119 | static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm, | ||
120 | struct line6_pcm_stream *pcms) | ||
121 | { | ||
122 | int timeout = HZ; | ||
123 | int i; | ||
124 | int alive; | ||
125 | |||
126 | do { | ||
127 | alive = 0; | ||
128 | for (i = 0; i < LINE6_ISO_BUFFERS; i++) { | ||
129 | if (test_bit(i, &pcms->active_urbs)) | ||
130 | alive++; | ||
131 | } | ||
132 | if (!alive) | ||
133 | break; | ||
134 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
135 | schedule_timeout(1); | ||
136 | } while (--timeout > 0); | ||
137 | if (alive) | ||
138 | dev_err(line6pcm->line6->ifcdev, | ||
139 | "timeout: still %d active urbs..\n", alive); | ||
140 | } | ||
141 | |||
142 | static inline struct line6_pcm_stream * | ||
143 | get_stream(struct snd_line6_pcm *line6pcm, int direction) | ||
144 | { | ||
145 | return (direction == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
146 | &line6pcm->out : &line6pcm->in; | ||
147 | } | ||
148 | |||
149 | /* allocate a buffer if not opened yet; | ||
150 | * call this in line6pcm.state_change mutex | ||
151 | */ | ||
152 | static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm, | ||
153 | struct line6_pcm_stream *pstr, int type) | ||
154 | { | ||
155 | /* Invoked multiple times in a row so allocate once only */ | ||
156 | if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) { | ||
157 | pstr->buffer = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * | ||
158 | line6pcm->max_packet_size, GFP_KERNEL); | ||
159 | if (!pstr->buffer) | ||
160 | return -ENOMEM; | ||
161 | } | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | /* free a buffer if all streams are closed; | ||
166 | * call this in line6pcm.state_change mutex | ||
167 | */ | ||
168 | static void line6_buffer_release(struct snd_line6_pcm *line6pcm, | ||
169 | struct line6_pcm_stream *pstr, int type) | ||
170 | { | ||
171 | |||
172 | clear_bit(type, &pstr->opened); | ||
173 | if (!pstr->opened) { | ||
174 | line6_wait_clear_audio_urbs(line6pcm, pstr); | ||
175 | kfree(pstr->buffer); | ||
176 | pstr->buffer = NULL; | ||
177 | } | ||
178 | } | ||
179 | |||
180 | /* start a PCM stream */ | ||
181 | static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction, | ||
182 | int type) | ||
183 | { | ||
184 | unsigned long flags; | ||
185 | struct line6_pcm_stream *pstr = get_stream(line6pcm, direction); | ||
186 | int ret = 0; | ||
187 | |||
188 | spin_lock_irqsave(&pstr->lock, flags); | ||
189 | if (!test_and_set_bit(type, &pstr->running)) { | ||
190 | if (pstr->active_urbs || pstr->unlink_urbs) { | ||
191 | ret = -EBUSY; | ||
192 | goto error; | ||
193 | } | ||
194 | |||
195 | pstr->count = 0; | ||
196 | /* Submit all currently available URBs */ | ||
197 | if (direction == SNDRV_PCM_STREAM_PLAYBACK) | ||
198 | ret = line6_submit_audio_out_all_urbs(line6pcm); | ||
199 | else | ||
200 | ret = line6_submit_audio_in_all_urbs(line6pcm); | ||
201 | } | ||
202 | error: | ||
203 | if (ret < 0) | ||
204 | clear_bit(type, &pstr->running); | ||
205 | spin_unlock_irqrestore(&pstr->lock, flags); | ||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | /* stop a PCM stream; this doesn't sync with the unlinked URBs */ | ||
210 | static void line6_stream_stop(struct snd_line6_pcm *line6pcm, int direction, | ||
211 | int type) | ||
212 | { | ||
213 | unsigned long flags; | ||
214 | struct line6_pcm_stream *pstr = get_stream(line6pcm, direction); | ||
215 | |||
216 | spin_lock_irqsave(&pstr->lock, flags); | ||
217 | clear_bit(type, &pstr->running); | ||
218 | if (!pstr->running) { | ||
219 | line6_unlink_audio_urbs(line6pcm, pstr); | ||
220 | if (direction == SNDRV_PCM_STREAM_CAPTURE) { | ||
221 | line6pcm->prev_fbuf = NULL; | ||
222 | line6pcm->prev_fsize = 0; | ||
223 | } | ||
224 | } | ||
225 | spin_unlock_irqrestore(&pstr->lock, flags); | ||
226 | } | ||
227 | |||
228 | /* common PCM trigger callback */ | ||
229 | int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) | ||
230 | { | ||
231 | struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); | ||
232 | struct snd_pcm_substream *s; | ||
233 | int err; | ||
234 | |||
235 | clear_bit(LINE6_FLAG_PREPARED, &line6pcm->flags); | ||
236 | |||
237 | snd_pcm_group_for_each_entry(s, substream) { | ||
238 | if (s->pcm->card != substream->pcm->card) | ||
239 | continue; | ||
240 | |||
241 | switch (cmd) { | ||
242 | case SNDRV_PCM_TRIGGER_START: | ||
243 | case SNDRV_PCM_TRIGGER_RESUME: | ||
244 | err = line6_stream_start(line6pcm, s->stream, | ||
245 | LINE6_STREAM_PCM); | ||
246 | if (err < 0) | ||
247 | return err; | ||
248 | break; | ||
249 | |||
250 | case SNDRV_PCM_TRIGGER_STOP: | ||
251 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
252 | line6_stream_stop(line6pcm, s->stream, | ||
253 | LINE6_STREAM_PCM); | ||
254 | break; | ||
255 | |||
256 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
257 | if (s->stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
258 | return -EINVAL; | ||
259 | set_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags); | ||
260 | break; | ||
261 | |||
262 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
263 | if (s->stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
264 | return -EINVAL; | ||
265 | clear_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags); | ||
266 | break; | ||
267 | |||
268 | default: | ||
269 | return -EINVAL; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | /* common PCM pointer callback */ | ||
277 | snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream) | ||
278 | { | ||
279 | struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); | ||
280 | struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); | ||
281 | |||
282 | return pstr->pos_done; | ||
283 | } | ||
284 | |||
285 | /* Acquire and start duplex streams: | ||
286 | * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR | ||
287 | */ | ||
288 | int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type) | ||
289 | { | ||
290 | struct line6_pcm_stream *pstr; | ||
291 | int ret = 0, dir; | ||
292 | |||
293 | mutex_lock(&line6pcm->state_mutex); | ||
294 | for (dir = 0; dir < 2; dir++) { | ||
295 | pstr = get_stream(line6pcm, dir); | ||
296 | ret = line6_buffer_acquire(line6pcm, pstr, type); | ||
297 | if (ret < 0) | ||
298 | goto error; | ||
299 | if (!pstr->running) | ||
300 | line6_wait_clear_audio_urbs(line6pcm, pstr); | ||
301 | } | ||
302 | for (dir = 0; dir < 2; dir++) { | ||
303 | ret = line6_stream_start(line6pcm, dir, type); | ||
304 | if (ret < 0) | ||
305 | goto error; | ||
306 | } | ||
307 | error: | ||
308 | mutex_unlock(&line6pcm->state_mutex); | ||
309 | if (ret < 0) | ||
310 | line6_pcm_release(line6pcm, type); | ||
311 | return ret; | ||
312 | } | ||
313 | EXPORT_SYMBOL_GPL(line6_pcm_acquire); | ||
314 | |||
315 | /* Stop and release duplex streams */ | ||
316 | void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type) | ||
317 | { | ||
318 | struct line6_pcm_stream *pstr; | ||
319 | int dir; | ||
320 | |||
321 | mutex_lock(&line6pcm->state_mutex); | ||
322 | for (dir = 0; dir < 2; dir++) | ||
323 | line6_stream_stop(line6pcm, dir, type); | ||
324 | for (dir = 0; dir < 2; dir++) { | ||
325 | pstr = get_stream(line6pcm, dir); | ||
326 | line6_buffer_release(line6pcm, pstr, type); | ||
327 | } | ||
328 | mutex_unlock(&line6pcm->state_mutex); | ||
329 | } | ||
330 | EXPORT_SYMBOL_GPL(line6_pcm_release); | ||
331 | |||
332 | /* common PCM hw_params callback */ | ||
333 | int snd_line6_hw_params(struct snd_pcm_substream *substream, | ||
334 | struct snd_pcm_hw_params *hw_params) | ||
335 | { | ||
336 | int ret; | ||
337 | struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); | ||
338 | struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); | ||
339 | |||
340 | mutex_lock(&line6pcm->state_mutex); | ||
341 | ret = line6_buffer_acquire(line6pcm, pstr, LINE6_STREAM_PCM); | ||
342 | if (ret < 0) | ||
343 | goto error; | ||
344 | |||
345 | ret = snd_pcm_lib_malloc_pages(substream, | ||
346 | params_buffer_bytes(hw_params)); | ||
347 | if (ret < 0) { | ||
348 | line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM); | ||
349 | goto error; | ||
350 | } | ||
351 | |||
352 | pstr->period = params_period_bytes(hw_params); | ||
353 | error: | ||
354 | mutex_unlock(&line6pcm->state_mutex); | ||
355 | return ret; | ||
356 | } | ||
357 | |||
358 | /* common PCM hw_free callback */ | ||
359 | int snd_line6_hw_free(struct snd_pcm_substream *substream) | ||
360 | { | ||
361 | struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); | ||
362 | struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); | ||
363 | |||
364 | mutex_lock(&line6pcm->state_mutex); | ||
365 | line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM); | ||
366 | mutex_unlock(&line6pcm->state_mutex); | ||
367 | return snd_pcm_lib_free_pages(substream); | ||
368 | } | ||
369 | |||
370 | |||
371 | /* control info callback */ | ||
372 | static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol, | ||
373 | struct snd_ctl_elem_info *uinfo) | ||
374 | { | ||
375 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
376 | uinfo->count = 2; | ||
377 | uinfo->value.integer.min = 0; | ||
378 | uinfo->value.integer.max = 256; | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | /* control get callback */ | ||
383 | static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol, | ||
384 | struct snd_ctl_elem_value *ucontrol) | ||
385 | { | ||
386 | int i; | ||
387 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); | ||
388 | |||
389 | for (i = 0; i < 2; i++) | ||
390 | ucontrol->value.integer.value[i] = line6pcm->volume_playback[i]; | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | /* control put callback */ | ||
396 | static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol, | ||
397 | struct snd_ctl_elem_value *ucontrol) | ||
398 | { | ||
399 | int i, changed = 0; | ||
400 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); | ||
401 | |||
402 | for (i = 0; i < 2; i++) | ||
403 | if (line6pcm->volume_playback[i] != | ||
404 | ucontrol->value.integer.value[i]) { | ||
405 | line6pcm->volume_playback[i] = | ||
406 | ucontrol->value.integer.value[i]; | ||
407 | changed = 1; | ||
408 | } | ||
409 | |||
410 | return changed; | ||
411 | } | ||
412 | |||
413 | /* control definition */ | ||
414 | static struct snd_kcontrol_new line6_controls[] = { | ||
415 | { | ||
416 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
417 | .name = "PCM Playback Volume", | ||
418 | .info = snd_line6_control_playback_info, | ||
419 | .get = snd_line6_control_playback_get, | ||
420 | .put = snd_line6_control_playback_put | ||
421 | }, | ||
422 | { | ||
423 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
424 | .name = "Impulse Response Volume", | ||
425 | .info = snd_line6_impulse_volume_info, | ||
426 | .get = snd_line6_impulse_volume_get, | ||
427 | .put = snd_line6_impulse_volume_put | ||
428 | }, | ||
429 | { | ||
430 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
431 | .name = "Impulse Response Period", | ||
432 | .info = snd_line6_impulse_period_info, | ||
433 | .get = snd_line6_impulse_period_get, | ||
434 | .put = snd_line6_impulse_period_put | ||
435 | }, | ||
436 | }; | ||
437 | |||
438 | /* | ||
439 | Cleanup the PCM device. | ||
440 | */ | ||
441 | static void cleanup_urbs(struct line6_pcm_stream *pcms) | ||
442 | { | ||
443 | int i; | ||
444 | |||
445 | for (i = 0; i < LINE6_ISO_BUFFERS; i++) { | ||
446 | if (pcms->urbs[i]) { | ||
447 | usb_kill_urb(pcms->urbs[i]); | ||
448 | usb_free_urb(pcms->urbs[i]); | ||
449 | } | ||
450 | } | ||
451 | } | ||
452 | |||
453 | static void line6_cleanup_pcm(struct snd_pcm *pcm) | ||
454 | { | ||
455 | struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm); | ||
456 | |||
457 | cleanup_urbs(&line6pcm->out); | ||
458 | cleanup_urbs(&line6pcm->in); | ||
459 | kfree(line6pcm); | ||
460 | } | ||
461 | |||
462 | /* create a PCM device */ | ||
463 | static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret) | ||
464 | { | ||
465 | struct snd_pcm *pcm; | ||
466 | int err; | ||
467 | |||
468 | err = snd_pcm_new(line6->card, (char *)line6->properties->name, | ||
469 | 0, 1, 1, pcm_ret); | ||
470 | if (err < 0) | ||
471 | return err; | ||
472 | pcm = *pcm_ret; | ||
473 | strcpy(pcm->name, line6->properties->name); | ||
474 | |||
475 | /* set operators */ | ||
476 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
477 | &snd_line6_playback_ops); | ||
478 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops); | ||
479 | |||
480 | /* pre-allocation of buffers */ | ||
481 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, | ||
482 | snd_dma_continuous_data | ||
483 | (GFP_KERNEL), 64 * 1024, | ||
484 | 128 * 1024); | ||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | /* | ||
489 | Sync with PCM stream stops. | ||
490 | */ | ||
491 | void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm) | ||
492 | { | ||
493 | line6_unlink_audio_urbs(line6pcm, &line6pcm->out); | ||
494 | line6_unlink_audio_urbs(line6pcm, &line6pcm->in); | ||
495 | line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out); | ||
496 | line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in); | ||
497 | } | ||
498 | |||
499 | /* | ||
500 | Create and register the PCM device and mixer entries. | ||
501 | Create URBs for playback and capture. | ||
502 | */ | ||
503 | int line6_init_pcm(struct usb_line6 *line6, | ||
504 | struct line6_pcm_properties *properties) | ||
505 | { | ||
506 | int i, err; | ||
507 | unsigned ep_read = line6->properties->ep_audio_r; | ||
508 | unsigned ep_write = line6->properties->ep_audio_w; | ||
509 | struct snd_pcm *pcm; | ||
510 | struct snd_line6_pcm *line6pcm; | ||
511 | |||
512 | if (!(line6->properties->capabilities & LINE6_CAP_PCM)) | ||
513 | return 0; /* skip PCM initialization and report success */ | ||
514 | |||
515 | err = snd_line6_new_pcm(line6, &pcm); | ||
516 | if (err < 0) | ||
517 | return err; | ||
518 | |||
519 | line6pcm = kzalloc(sizeof(*line6pcm), GFP_KERNEL); | ||
520 | if (!line6pcm) | ||
521 | return -ENOMEM; | ||
522 | |||
523 | mutex_init(&line6pcm->state_mutex); | ||
524 | line6pcm->pcm = pcm; | ||
525 | line6pcm->properties = properties; | ||
526 | line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255; | ||
527 | line6pcm->volume_monitor = 255; | ||
528 | line6pcm->line6 = line6; | ||
529 | |||
530 | /* Read and write buffers are sized identically, so choose minimum */ | ||
531 | line6pcm->max_packet_size = min( | ||
532 | usb_maxpacket(line6->usbdev, | ||
533 | usb_rcvisocpipe(line6->usbdev, ep_read), 0), | ||
534 | usb_maxpacket(line6->usbdev, | ||
535 | usb_sndisocpipe(line6->usbdev, ep_write), 1)); | ||
536 | |||
537 | spin_lock_init(&line6pcm->out.lock); | ||
538 | spin_lock_init(&line6pcm->in.lock); | ||
539 | line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD; | ||
540 | |||
541 | line6->line6pcm = line6pcm; | ||
542 | |||
543 | pcm->private_data = line6pcm; | ||
544 | pcm->private_free = line6_cleanup_pcm; | ||
545 | |||
546 | err = line6_create_audio_out_urbs(line6pcm); | ||
547 | if (err < 0) | ||
548 | return err; | ||
549 | |||
550 | err = line6_create_audio_in_urbs(line6pcm); | ||
551 | if (err < 0) | ||
552 | return err; | ||
553 | |||
554 | /* mixer: */ | ||
555 | for (i = 0; i < ARRAY_SIZE(line6_controls); i++) { | ||
556 | err = snd_ctl_add(line6->card, | ||
557 | snd_ctl_new1(&line6_controls[i], line6pcm)); | ||
558 | if (err < 0) | ||
559 | return err; | ||
560 | } | ||
561 | |||
562 | return 0; | ||
563 | } | ||
564 | EXPORT_SYMBOL_GPL(line6_init_pcm); | ||
565 | |||
566 | /* prepare pcm callback */ | ||
567 | int snd_line6_prepare(struct snd_pcm_substream *substream) | ||
568 | { | ||
569 | struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); | ||
570 | struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); | ||
571 | |||
572 | mutex_lock(&line6pcm->state_mutex); | ||
573 | if (!pstr->running) | ||
574 | line6_wait_clear_audio_urbs(line6pcm, pstr); | ||
575 | |||
576 | if (!test_and_set_bit(LINE6_FLAG_PREPARED, &line6pcm->flags)) { | ||
577 | line6pcm->out.count = 0; | ||
578 | line6pcm->out.pos = 0; | ||
579 | line6pcm->out.pos_done = 0; | ||
580 | line6pcm->out.bytes = 0; | ||
581 | line6pcm->in.count = 0; | ||
582 | line6pcm->in.pos_done = 0; | ||
583 | line6pcm->in.bytes = 0; | ||
584 | } | ||
585 | |||
586 | mutex_unlock(&line6pcm->state_mutex); | ||
587 | return 0; | ||
588 | } | ||
diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h new file mode 100644 index 000000000000..508410adbd51 --- /dev/null +++ b/sound/usb/line6/pcm.h | |||
@@ -0,0 +1,197 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | PCM interface to POD series devices. | ||
14 | */ | ||
15 | |||
16 | #ifndef PCM_H | ||
17 | #define PCM_H | ||
18 | |||
19 | #include <sound/pcm.h> | ||
20 | |||
21 | #include "driver.h" | ||
22 | |||
23 | /* number of URBs */ | ||
24 | #define LINE6_ISO_BUFFERS 2 | ||
25 | |||
26 | /* | ||
27 | number of USB frames per URB | ||
28 | The Line 6 Windows driver always transmits two frames per packet, but | ||
29 | the Linux driver performs significantly better (i.e., lower latency) | ||
30 | with only one frame per packet. | ||
31 | */ | ||
32 | #define LINE6_ISO_PACKETS 1 | ||
33 | |||
34 | /* in a "full speed" device (such as the PODxt Pro) this means 1ms */ | ||
35 | #define LINE6_ISO_INTERVAL 1 | ||
36 | |||
37 | #define LINE6_IMPULSE_DEFAULT_PERIOD 100 | ||
38 | |||
39 | /* | ||
40 | Get substream from Line 6 PCM data structure | ||
41 | */ | ||
42 | #define get_substream(line6pcm, stream) \ | ||
43 | (line6pcm->pcm->streams[stream].substream) | ||
44 | |||
45 | /* | ||
46 | PCM mode bits. | ||
47 | |||
48 | There are several features of the Line 6 USB driver which require PCM | ||
49 | data to be exchanged with the device: | ||
50 | *) PCM playback and capture via ALSA | ||
51 | *) software monitoring (for devices without hardware monitoring) | ||
52 | *) optional impulse response measurement | ||
53 | However, from the device's point of view, there is just a single | ||
54 | capture and playback stream, which must be shared between these | ||
55 | subsystems. It is therefore necessary to maintain the state of the | ||
56 | subsystems with respect to PCM usage. | ||
57 | |||
58 | We define two bit flags, "opened" and "running", for each playback | ||
59 | or capture stream. Both can contain the bit flag corresponding to | ||
60 | LINE6_STREAM_* type, | ||
61 | LINE6_STREAM_PCM = ALSA PCM playback or capture | ||
62 | LINE6_STREAM_MONITOR = software monitoring | ||
63 | IMPULSE = optional impulse response measurement | ||
64 | The opened flag indicates whether the buffer is allocated while | ||
65 | the running flag indicates whether the stream is running. | ||
66 | |||
67 | For monitor or impulse operations, the driver needs to call | ||
68 | line6_pcm_acquire() or line6_pcm_release() with the appropriate | ||
69 | LINE6_STREAM_* flag. | ||
70 | */ | ||
71 | |||
72 | /* stream types */ | ||
73 | enum { | ||
74 | LINE6_STREAM_PCM, | ||
75 | LINE6_STREAM_MONITOR, | ||
76 | LINE6_STREAM_IMPULSE, | ||
77 | }; | ||
78 | |||
79 | /* misc bit flags for PCM operation */ | ||
80 | enum { | ||
81 | LINE6_FLAG_PAUSE_PLAYBACK, | ||
82 | LINE6_FLAG_PREPARED, | ||
83 | }; | ||
84 | |||
85 | struct line6_pcm_properties { | ||
86 | struct snd_pcm_hardware playback_hw, capture_hw; | ||
87 | struct snd_pcm_hw_constraint_ratdens rates; | ||
88 | int bytes_per_frame; | ||
89 | }; | ||
90 | |||
91 | struct line6_pcm_stream { | ||
92 | /* allocated URBs */ | ||
93 | struct urb *urbs[LINE6_ISO_BUFFERS]; | ||
94 | |||
95 | /* Temporary buffer; | ||
96 | * Since the packet size is not known in advance, this buffer is | ||
97 | * large enough to store maximum size packets. | ||
98 | */ | ||
99 | unsigned char *buffer; | ||
100 | |||
101 | /* Free frame position in the buffer. */ | ||
102 | snd_pcm_uframes_t pos; | ||
103 | |||
104 | /* Count processed bytes; | ||
105 | * This is modulo period size (to determine when a period is finished). | ||
106 | */ | ||
107 | unsigned bytes; | ||
108 | |||
109 | /* Counter to create desired sample rate */ | ||
110 | unsigned count; | ||
111 | |||
112 | /* period size in bytes */ | ||
113 | unsigned period; | ||
114 | |||
115 | /* Processed frame position in the buffer; | ||
116 | * The contents of the ring buffer have been consumed by the USB | ||
117 | * subsystem (i.e., sent to the USB device) up to this position. | ||
118 | */ | ||
119 | snd_pcm_uframes_t pos_done; | ||
120 | |||
121 | /* Bit mask of active URBs */ | ||
122 | unsigned long active_urbs; | ||
123 | |||
124 | /* Bit mask of URBs currently being unlinked */ | ||
125 | unsigned long unlink_urbs; | ||
126 | |||
127 | /* Spin lock to protect updates of the buffer positions (not contents) | ||
128 | */ | ||
129 | spinlock_t lock; | ||
130 | |||
131 | /* Bit flags for operational stream types */ | ||
132 | unsigned long opened; | ||
133 | |||
134 | /* Bit flags for running stream types */ | ||
135 | unsigned long running; | ||
136 | |||
137 | int last_frame; | ||
138 | }; | ||
139 | |||
140 | struct snd_line6_pcm { | ||
141 | /* Pointer back to the Line 6 driver data structure */ | ||
142 | struct usb_line6 *line6; | ||
143 | |||
144 | /* Properties. */ | ||
145 | struct line6_pcm_properties *properties; | ||
146 | |||
147 | /* ALSA pcm stream */ | ||
148 | struct snd_pcm *pcm; | ||
149 | |||
150 | /* protection to state changes of in/out streams */ | ||
151 | struct mutex state_mutex; | ||
152 | |||
153 | /* Capture and playback streams */ | ||
154 | struct line6_pcm_stream in; | ||
155 | struct line6_pcm_stream out; | ||
156 | |||
157 | /* Previously captured frame (for software monitoring) */ | ||
158 | unsigned char *prev_fbuf; | ||
159 | |||
160 | /* Size of previously captured frame (for software monitoring) */ | ||
161 | int prev_fsize; | ||
162 | |||
163 | /* Maximum size of USB packet */ | ||
164 | int max_packet_size; | ||
165 | |||
166 | /* PCM playback volume (left and right) */ | ||
167 | int volume_playback[2]; | ||
168 | |||
169 | /* PCM monitor volume */ | ||
170 | int volume_monitor; | ||
171 | |||
172 | /* Volume of impulse response test signal (if zero, test is disabled) */ | ||
173 | int impulse_volume; | ||
174 | |||
175 | /* Period of impulse response test signal */ | ||
176 | int impulse_period; | ||
177 | |||
178 | /* Counter for impulse response test signal */ | ||
179 | int impulse_count; | ||
180 | |||
181 | /* Several status bits (see LINE6_FLAG_*) */ | ||
182 | unsigned long flags; | ||
183 | }; | ||
184 | |||
185 | extern int line6_init_pcm(struct usb_line6 *line6, | ||
186 | struct line6_pcm_properties *properties); | ||
187 | extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd); | ||
188 | extern int snd_line6_prepare(struct snd_pcm_substream *substream); | ||
189 | extern int snd_line6_hw_params(struct snd_pcm_substream *substream, | ||
190 | struct snd_pcm_hw_params *hw_params); | ||
191 | extern int snd_line6_hw_free(struct snd_pcm_substream *substream); | ||
192 | extern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream); | ||
193 | extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); | ||
194 | extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type); | ||
195 | extern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type); | ||
196 | |||
197 | #endif | ||
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c new file mode 100644 index 000000000000..05dee690f487 --- /dev/null +++ b/sound/usb/line6/playback.c | |||
@@ -0,0 +1,429 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/slab.h> | ||
13 | #include <sound/core.h> | ||
14 | #include <sound/pcm.h> | ||
15 | #include <sound/pcm_params.h> | ||
16 | |||
17 | #include "capture.h" | ||
18 | #include "driver.h" | ||
19 | #include "pcm.h" | ||
20 | #include "playback.h" | ||
21 | |||
22 | /* | ||
23 | Software stereo volume control. | ||
24 | */ | ||
25 | static void change_volume(struct urb *urb_out, int volume[], | ||
26 | int bytes_per_frame) | ||
27 | { | ||
28 | int chn = 0; | ||
29 | |||
30 | if (volume[0] == 256 && volume[1] == 256) | ||
31 | return; /* maximum volume - no change */ | ||
32 | |||
33 | if (bytes_per_frame == 4) { | ||
34 | __le16 *p, *buf_end; | ||
35 | |||
36 | p = (__le16 *)urb_out->transfer_buffer; | ||
37 | buf_end = p + urb_out->transfer_buffer_length / sizeof(*p); | ||
38 | |||
39 | for (; p < buf_end; ++p) { | ||
40 | short pv = le16_to_cpu(*p); | ||
41 | int val = (pv * volume[chn & 1]) >> 8; | ||
42 | pv = clamp(val, 0x7fff, -0x8000); | ||
43 | *p = cpu_to_le16(pv); | ||
44 | ++chn; | ||
45 | } | ||
46 | } else if (bytes_per_frame == 6) { | ||
47 | unsigned char *p, *buf_end; | ||
48 | |||
49 | p = (unsigned char *)urb_out->transfer_buffer; | ||
50 | buf_end = p + urb_out->transfer_buffer_length; | ||
51 | |||
52 | for (; p < buf_end; p += 3) { | ||
53 | int val; | ||
54 | |||
55 | val = p[0] + (p[1] << 8) + ((signed char)p[2] << 16); | ||
56 | val = (val * volume[chn & 1]) >> 8; | ||
57 | val = clamp(val, 0x7fffff, -0x800000); | ||
58 | p[0] = val; | ||
59 | p[1] = val >> 8; | ||
60 | p[2] = val >> 16; | ||
61 | ++chn; | ||
62 | } | ||
63 | } | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | Create signal for impulse response test. | ||
68 | */ | ||
69 | static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm, | ||
70 | struct urb *urb_out, int bytes_per_frame) | ||
71 | { | ||
72 | int frames = urb_out->transfer_buffer_length / bytes_per_frame; | ||
73 | |||
74 | if (bytes_per_frame == 4) { | ||
75 | int i; | ||
76 | short *pi = (short *)line6pcm->prev_fbuf; | ||
77 | short *po = (short *)urb_out->transfer_buffer; | ||
78 | |||
79 | for (i = 0; i < frames; ++i) { | ||
80 | po[0] = pi[0]; | ||
81 | po[1] = 0; | ||
82 | pi += 2; | ||
83 | po += 2; | ||
84 | } | ||
85 | } else if (bytes_per_frame == 6) { | ||
86 | int i, j; | ||
87 | unsigned char *pi = line6pcm->prev_fbuf; | ||
88 | unsigned char *po = urb_out->transfer_buffer; | ||
89 | |||
90 | for (i = 0; i < frames; ++i) { | ||
91 | for (j = 0; j < bytes_per_frame / 2; ++j) | ||
92 | po[j] = pi[j]; | ||
93 | |||
94 | for (; j < bytes_per_frame; ++j) | ||
95 | po[j] = 0; | ||
96 | |||
97 | pi += bytes_per_frame; | ||
98 | po += bytes_per_frame; | ||
99 | } | ||
100 | } | ||
101 | if (--line6pcm->impulse_count <= 0) { | ||
102 | ((unsigned char *)(urb_out->transfer_buffer))[bytes_per_frame - | ||
103 | 1] = | ||
104 | line6pcm->impulse_volume; | ||
105 | line6pcm->impulse_count = line6pcm->impulse_period; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | Add signal to buffer for software monitoring. | ||
111 | */ | ||
112 | static void add_monitor_signal(struct urb *urb_out, unsigned char *signal, | ||
113 | int volume, int bytes_per_frame) | ||
114 | { | ||
115 | if (volume == 0) | ||
116 | return; /* zero volume - no change */ | ||
117 | |||
118 | if (bytes_per_frame == 4) { | ||
119 | __le16 *pi, *po, *buf_end; | ||
120 | |||
121 | pi = (__le16 *)signal; | ||
122 | po = (__le16 *)urb_out->transfer_buffer; | ||
123 | buf_end = po + urb_out->transfer_buffer_length / sizeof(*po); | ||
124 | |||
125 | for (; po < buf_end; ++pi, ++po) { | ||
126 | short pov = le16_to_cpu(*po); | ||
127 | short piv = le16_to_cpu(*pi); | ||
128 | int val = pov + ((piv * volume) >> 8); | ||
129 | pov = clamp(val, 0x7fff, -0x8000); | ||
130 | *po = cpu_to_le16(pov); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | We don't need to handle devices with 6 bytes per frame here | ||
136 | since they all support hardware monitoring. | ||
137 | */ | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | Find a free URB, prepare audio data, and submit URB. | ||
142 | must be called in line6pcm->out.lock context | ||
143 | */ | ||
144 | static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) | ||
145 | { | ||
146 | int index; | ||
147 | int i, urb_size, urb_frames; | ||
148 | int ret; | ||
149 | const int bytes_per_frame = line6pcm->properties->bytes_per_frame; | ||
150 | const int frame_increment = | ||
151 | line6pcm->properties->rates.rats[0].num_min; | ||
152 | const int frame_factor = | ||
153 | line6pcm->properties->rates.rats[0].den * | ||
154 | (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL); | ||
155 | struct urb *urb_out; | ||
156 | |||
157 | index = | ||
158 | find_first_zero_bit(&line6pcm->out.active_urbs, LINE6_ISO_BUFFERS); | ||
159 | |||
160 | if (index < 0 || index >= LINE6_ISO_BUFFERS) { | ||
161 | dev_err(line6pcm->line6->ifcdev, "no free URB found\n"); | ||
162 | return -EINVAL; | ||
163 | } | ||
164 | |||
165 | urb_out = line6pcm->out.urbs[index]; | ||
166 | urb_size = 0; | ||
167 | |||
168 | for (i = 0; i < LINE6_ISO_PACKETS; ++i) { | ||
169 | /* compute frame size for given sampling rate */ | ||
170 | int fsize = 0; | ||
171 | struct usb_iso_packet_descriptor *fout = | ||
172 | &urb_out->iso_frame_desc[i]; | ||
173 | |||
174 | fsize = line6pcm->prev_fsize; | ||
175 | if (fsize == 0) { | ||
176 | int n; | ||
177 | |||
178 | line6pcm->out.count += frame_increment; | ||
179 | n = line6pcm->out.count / frame_factor; | ||
180 | line6pcm->out.count -= n * frame_factor; | ||
181 | fsize = n * bytes_per_frame; | ||
182 | } | ||
183 | |||
184 | fout->offset = urb_size; | ||
185 | fout->length = fsize; | ||
186 | urb_size += fsize; | ||
187 | } | ||
188 | |||
189 | if (urb_size == 0) { | ||
190 | /* can't determine URB size */ | ||
191 | dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n"); | ||
192 | return -EINVAL; | ||
193 | } | ||
194 | |||
195 | urb_frames = urb_size / bytes_per_frame; | ||
196 | urb_out->transfer_buffer = | ||
197 | line6pcm->out.buffer + | ||
198 | index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; | ||
199 | urb_out->transfer_buffer_length = urb_size; | ||
200 | urb_out->context = line6pcm; | ||
201 | |||
202 | if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running) && | ||
203 | !test_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags)) { | ||
204 | struct snd_pcm_runtime *runtime = | ||
205 | get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime; | ||
206 | |||
207 | if (line6pcm->out.pos + urb_frames > runtime->buffer_size) { | ||
208 | /* | ||
209 | The transferred area goes over buffer boundary, | ||
210 | copy the data to the temp buffer. | ||
211 | */ | ||
212 | int len; | ||
213 | |||
214 | len = runtime->buffer_size - line6pcm->out.pos; | ||
215 | |||
216 | if (len > 0) { | ||
217 | memcpy(urb_out->transfer_buffer, | ||
218 | runtime->dma_area + | ||
219 | line6pcm->out.pos * bytes_per_frame, | ||
220 | len * bytes_per_frame); | ||
221 | memcpy(urb_out->transfer_buffer + | ||
222 | len * bytes_per_frame, runtime->dma_area, | ||
223 | (urb_frames - len) * bytes_per_frame); | ||
224 | } else | ||
225 | dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n", | ||
226 | len); | ||
227 | } else { | ||
228 | memcpy(urb_out->transfer_buffer, | ||
229 | runtime->dma_area + | ||
230 | line6pcm->out.pos * bytes_per_frame, | ||
231 | urb_out->transfer_buffer_length); | ||
232 | } | ||
233 | |||
234 | line6pcm->out.pos += urb_frames; | ||
235 | if (line6pcm->out.pos >= runtime->buffer_size) | ||
236 | line6pcm->out.pos -= runtime->buffer_size; | ||
237 | |||
238 | change_volume(urb_out, line6pcm->volume_playback, | ||
239 | bytes_per_frame); | ||
240 | } else { | ||
241 | memset(urb_out->transfer_buffer, 0, | ||
242 | urb_out->transfer_buffer_length); | ||
243 | } | ||
244 | |||
245 | spin_lock_nested(&line6pcm->in.lock, SINGLE_DEPTH_NESTING); | ||
246 | if (line6pcm->prev_fbuf) { | ||
247 | if (test_bit(LINE6_STREAM_IMPULSE, &line6pcm->out.running)) { | ||
248 | create_impulse_test_signal(line6pcm, urb_out, | ||
249 | bytes_per_frame); | ||
250 | if (test_bit(LINE6_STREAM_PCM, &line6pcm->in.running)) { | ||
251 | line6_capture_copy(line6pcm, | ||
252 | urb_out->transfer_buffer, | ||
253 | urb_out-> | ||
254 | transfer_buffer_length); | ||
255 | line6_capture_check_period(line6pcm, | ||
256 | urb_out->transfer_buffer_length); | ||
257 | } | ||
258 | } else { | ||
259 | if (!(line6pcm->line6->properties->capabilities & LINE6_CAP_HWMON) | ||
260 | && line6pcm->out.running && line6pcm->in.running) | ||
261 | add_monitor_signal(urb_out, line6pcm->prev_fbuf, | ||
262 | line6pcm->volume_monitor, | ||
263 | bytes_per_frame); | ||
264 | } | ||
265 | line6pcm->prev_fbuf = NULL; | ||
266 | line6pcm->prev_fsize = 0; | ||
267 | } | ||
268 | spin_unlock(&line6pcm->in.lock); | ||
269 | |||
270 | ret = usb_submit_urb(urb_out, GFP_ATOMIC); | ||
271 | |||
272 | if (ret == 0) | ||
273 | set_bit(index, &line6pcm->out.active_urbs); | ||
274 | else | ||
275 | dev_err(line6pcm->line6->ifcdev, | ||
276 | "URB out #%d submission failed (%d)\n", index, ret); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | /* | ||
282 | Submit all currently available playback URBs. | ||
283 | must be called in line6pcm->out.lock context | ||
284 | */ | ||
285 | int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm) | ||
286 | { | ||
287 | int ret = 0, i; | ||
288 | |||
289 | for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { | ||
290 | ret = submit_audio_out_urb(line6pcm); | ||
291 | if (ret < 0) | ||
292 | break; | ||
293 | } | ||
294 | |||
295 | return ret; | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | Callback for completed playback URB. | ||
300 | */ | ||
301 | static void audio_out_callback(struct urb *urb) | ||
302 | { | ||
303 | int i, index, length = 0, shutdown = 0; | ||
304 | unsigned long flags; | ||
305 | struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context; | ||
306 | struct snd_pcm_substream *substream = | ||
307 | get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK); | ||
308 | |||
309 | #if USE_CLEAR_BUFFER_WORKAROUND | ||
310 | memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); | ||
311 | #endif | ||
312 | |||
313 | line6pcm->out.last_frame = urb->start_frame; | ||
314 | |||
315 | /* find index of URB */ | ||
316 | for (index = 0; index < LINE6_ISO_BUFFERS; index++) | ||
317 | if (urb == line6pcm->out.urbs[index]) | ||
318 | break; | ||
319 | |||
320 | if (index >= LINE6_ISO_BUFFERS) | ||
321 | return; /* URB has been unlinked asynchronously */ | ||
322 | |||
323 | for (i = 0; i < LINE6_ISO_PACKETS; i++) | ||
324 | length += urb->iso_frame_desc[i].length; | ||
325 | |||
326 | spin_lock_irqsave(&line6pcm->out.lock, flags); | ||
327 | |||
328 | if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) { | ||
329 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
330 | |||
331 | line6pcm->out.pos_done += | ||
332 | length / line6pcm->properties->bytes_per_frame; | ||
333 | |||
334 | if (line6pcm->out.pos_done >= runtime->buffer_size) | ||
335 | line6pcm->out.pos_done -= runtime->buffer_size; | ||
336 | } | ||
337 | |||
338 | clear_bit(index, &line6pcm->out.active_urbs); | ||
339 | |||
340 | for (i = 0; i < LINE6_ISO_PACKETS; i++) | ||
341 | if (urb->iso_frame_desc[i].status == -EXDEV) { | ||
342 | shutdown = 1; | ||
343 | break; | ||
344 | } | ||
345 | |||
346 | if (test_and_clear_bit(index, &line6pcm->out.unlink_urbs)) | ||
347 | shutdown = 1; | ||
348 | |||
349 | if (!shutdown) { | ||
350 | submit_audio_out_urb(line6pcm); | ||
351 | |||
352 | if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) { | ||
353 | line6pcm->out.bytes += length; | ||
354 | if (line6pcm->out.bytes >= line6pcm->out.period) { | ||
355 | line6pcm->out.bytes %= line6pcm->out.period; | ||
356 | spin_unlock(&line6pcm->out.lock); | ||
357 | snd_pcm_period_elapsed(substream); | ||
358 | spin_lock(&line6pcm->out.lock); | ||
359 | } | ||
360 | } | ||
361 | } | ||
362 | spin_unlock_irqrestore(&line6pcm->out.lock, flags); | ||
363 | } | ||
364 | |||
365 | /* open playback callback */ | ||
366 | static int snd_line6_playback_open(struct snd_pcm_substream *substream) | ||
367 | { | ||
368 | int err; | ||
369 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
370 | struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); | ||
371 | |||
372 | err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
373 | &line6pcm->properties->rates); | ||
374 | if (err < 0) | ||
375 | return err; | ||
376 | |||
377 | runtime->hw = line6pcm->properties->playback_hw; | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | /* close playback callback */ | ||
382 | static int snd_line6_playback_close(struct snd_pcm_substream *substream) | ||
383 | { | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | /* playback operators */ | ||
388 | struct snd_pcm_ops snd_line6_playback_ops = { | ||
389 | .open = snd_line6_playback_open, | ||
390 | .close = snd_line6_playback_close, | ||
391 | .ioctl = snd_pcm_lib_ioctl, | ||
392 | .hw_params = snd_line6_hw_params, | ||
393 | .hw_free = snd_line6_hw_free, | ||
394 | .prepare = snd_line6_prepare, | ||
395 | .trigger = snd_line6_trigger, | ||
396 | .pointer = snd_line6_pointer, | ||
397 | }; | ||
398 | |||
399 | int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm) | ||
400 | { | ||
401 | struct usb_line6 *line6 = line6pcm->line6; | ||
402 | int i; | ||
403 | |||
404 | /* create audio URBs and fill in constant values: */ | ||
405 | for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { | ||
406 | struct urb *urb; | ||
407 | |||
408 | /* URB for audio out: */ | ||
409 | urb = line6pcm->out.urbs[i] = | ||
410 | usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); | ||
411 | |||
412 | if (urb == NULL) | ||
413 | return -ENOMEM; | ||
414 | |||
415 | urb->dev = line6->usbdev; | ||
416 | urb->pipe = | ||
417 | usb_sndisocpipe(line6->usbdev, | ||
418 | line6->properties->ep_audio_w & | ||
419 | USB_ENDPOINT_NUMBER_MASK); | ||
420 | urb->transfer_flags = URB_ISO_ASAP; | ||
421 | urb->start_frame = -1; | ||
422 | urb->number_of_packets = LINE6_ISO_PACKETS; | ||
423 | urb->interval = LINE6_ISO_INTERVAL; | ||
424 | urb->error_count = 0; | ||
425 | urb->complete = audio_out_callback; | ||
426 | } | ||
427 | |||
428 | return 0; | ||
429 | } | ||
diff --git a/sound/usb/line6/playback.h b/sound/usb/line6/playback.h new file mode 100644 index 000000000000..51fce29e8726 --- /dev/null +++ b/sound/usb/line6/playback.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef PLAYBACK_H | ||
13 | #define PLAYBACK_H | ||
14 | |||
15 | #include <sound/pcm.h> | ||
16 | |||
17 | #include "driver.h" | ||
18 | |||
19 | /* | ||
20 | * When the TonePort is used with jack in full duplex mode and the outputs are | ||
21 | * not connected, the software monitor produces an ugly noise since everything | ||
22 | * written to the output buffer (i.e., the input signal) will be repeated in | ||
23 | * the next period (sounds like a delay effect). As a workaround, the output | ||
24 | * buffer is cleared after the data have been read, but there must be a better | ||
25 | * solution. Until one is found, this workaround can be used to fix the | ||
26 | * problem. | ||
27 | */ | ||
28 | #define USE_CLEAR_BUFFER_WORKAROUND 1 | ||
29 | |||
30 | extern struct snd_pcm_ops snd_line6_playback_ops; | ||
31 | |||
32 | extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm); | ||
33 | extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm); | ||
34 | |||
35 | #endif | ||
diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c new file mode 100644 index 000000000000..daf81d169a42 --- /dev/null +++ b/sound/usb/line6/pod.c | |||
@@ -0,0 +1,584 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/slab.h> | ||
13 | #include <linux/wait.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/usb.h> | ||
17 | |||
18 | #include <sound/core.h> | ||
19 | #include <sound/control.h> | ||
20 | |||
21 | #include "capture.h" | ||
22 | #include "driver.h" | ||
23 | #include "playback.h" | ||
24 | |||
25 | /* | ||
26 | Locate name in binary program dump | ||
27 | */ | ||
28 | #define POD_NAME_OFFSET 0 | ||
29 | #define POD_NAME_LENGTH 16 | ||
30 | |||
31 | /* | ||
32 | Other constants | ||
33 | */ | ||
34 | #define POD_CONTROL_SIZE 0x80 | ||
35 | #define POD_BUFSIZE_DUMPREQ 7 | ||
36 | #define POD_STARTUP_DELAY 1000 | ||
37 | |||
38 | /* | ||
39 | Stages of POD startup procedure | ||
40 | */ | ||
41 | enum { | ||
42 | POD_STARTUP_INIT = 1, | ||
43 | POD_STARTUP_VERSIONREQ, | ||
44 | POD_STARTUP_WORKQUEUE, | ||
45 | POD_STARTUP_SETUP, | ||
46 | POD_STARTUP_LAST = POD_STARTUP_SETUP - 1 | ||
47 | }; | ||
48 | |||
49 | enum { | ||
50 | LINE6_BASSPODXT, | ||
51 | LINE6_BASSPODXTLIVE, | ||
52 | LINE6_BASSPODXTPRO, | ||
53 | LINE6_POCKETPOD, | ||
54 | LINE6_PODXT, | ||
55 | LINE6_PODXTLIVE_POD, | ||
56 | LINE6_PODXTPRO, | ||
57 | }; | ||
58 | |||
59 | struct usb_line6_pod { | ||
60 | /* Generic Line 6 USB data */ | ||
61 | struct usb_line6 line6; | ||
62 | |||
63 | /* Instrument monitor level */ | ||
64 | int monitor_level; | ||
65 | |||
66 | /* Timer for device initialization */ | ||
67 | struct timer_list startup_timer; | ||
68 | |||
69 | /* Work handler for device initialization */ | ||
70 | struct work_struct startup_work; | ||
71 | |||
72 | /* Current progress in startup procedure */ | ||
73 | int startup_progress; | ||
74 | |||
75 | /* Serial number of device */ | ||
76 | u32 serial_number; | ||
77 | |||
78 | /* Firmware version (x 100) */ | ||
79 | int firmware_version; | ||
80 | |||
81 | /* Device ID */ | ||
82 | int device_id; | ||
83 | }; | ||
84 | |||
85 | #define POD_SYSEX_CODE 3 | ||
86 | #define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ | ||
87 | |||
88 | /* *INDENT-OFF* */ | ||
89 | |||
90 | enum { | ||
91 | POD_SYSEX_SAVE = 0x24, | ||
92 | POD_SYSEX_SYSTEM = 0x56, | ||
93 | POD_SYSEX_SYSTEMREQ = 0x57, | ||
94 | /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */ | ||
95 | POD_SYSEX_STORE = 0x71, | ||
96 | POD_SYSEX_FINISH = 0x72, | ||
97 | POD_SYSEX_DUMPMEM = 0x73, | ||
98 | POD_SYSEX_DUMP = 0x74, | ||
99 | POD_SYSEX_DUMPREQ = 0x75 | ||
100 | |||
101 | /* dumps entire internal memory of PODxt Pro */ | ||
102 | /* POD_SYSEX_DUMPMEM2 = 0x76 */ | ||
103 | }; | ||
104 | |||
105 | enum { | ||
106 | POD_MONITOR_LEVEL = 0x04, | ||
107 | POD_SYSTEM_INVALID = 0x10000 | ||
108 | }; | ||
109 | |||
110 | /* *INDENT-ON* */ | ||
111 | |||
112 | enum { | ||
113 | POD_DUMP_MEMORY = 2 | ||
114 | }; | ||
115 | |||
116 | enum { | ||
117 | POD_BUSY_READ, | ||
118 | POD_BUSY_WRITE, | ||
119 | POD_CHANNEL_DIRTY, | ||
120 | POD_SAVE_PRESSED, | ||
121 | POD_BUSY_MIDISEND | ||
122 | }; | ||
123 | |||
124 | static struct snd_ratden pod_ratden = { | ||
125 | .num_min = 78125, | ||
126 | .num_max = 78125, | ||
127 | .num_step = 1, | ||
128 | .den = 2 | ||
129 | }; | ||
130 | |||
131 | static struct line6_pcm_properties pod_pcm_properties = { | ||
132 | .playback_hw = { | ||
133 | .info = (SNDRV_PCM_INFO_MMAP | | ||
134 | SNDRV_PCM_INFO_INTERLEAVED | | ||
135 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
136 | SNDRV_PCM_INFO_MMAP_VALID | | ||
137 | SNDRV_PCM_INFO_PAUSE | | ||
138 | SNDRV_PCM_INFO_SYNC_START), | ||
139 | .formats = SNDRV_PCM_FMTBIT_S24_3LE, | ||
140 | .rates = SNDRV_PCM_RATE_KNOT, | ||
141 | .rate_min = 39062, | ||
142 | .rate_max = 39063, | ||
143 | .channels_min = 2, | ||
144 | .channels_max = 2, | ||
145 | .buffer_bytes_max = 60000, | ||
146 | .period_bytes_min = 64, | ||
147 | .period_bytes_max = 8192, | ||
148 | .periods_min = 1, | ||
149 | .periods_max = 1024}, | ||
150 | .capture_hw = { | ||
151 | .info = (SNDRV_PCM_INFO_MMAP | | ||
152 | SNDRV_PCM_INFO_INTERLEAVED | | ||
153 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
154 | SNDRV_PCM_INFO_MMAP_VALID | | ||
155 | SNDRV_PCM_INFO_SYNC_START), | ||
156 | .formats = SNDRV_PCM_FMTBIT_S24_3LE, | ||
157 | .rates = SNDRV_PCM_RATE_KNOT, | ||
158 | .rate_min = 39062, | ||
159 | .rate_max = 39063, | ||
160 | .channels_min = 2, | ||
161 | .channels_max = 2, | ||
162 | .buffer_bytes_max = 60000, | ||
163 | .period_bytes_min = 64, | ||
164 | .period_bytes_max = 8192, | ||
165 | .periods_min = 1, | ||
166 | .periods_max = 1024}, | ||
167 | .rates = { | ||
168 | .nrats = 1, | ||
169 | .rats = &pod_ratden}, | ||
170 | .bytes_per_frame = POD_BYTES_PER_FRAME | ||
171 | }; | ||
172 | |||
173 | static const char pod_version_header[] = { | ||
174 | 0xf2, 0x7e, 0x7f, 0x06, 0x02 | ||
175 | }; | ||
176 | |||
177 | /* forward declarations: */ | ||
178 | static void pod_startup2(unsigned long data); | ||
179 | static void pod_startup3(struct usb_line6_pod *pod); | ||
180 | |||
181 | static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, | ||
182 | int size) | ||
183 | { | ||
184 | return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code, | ||
185 | size); | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | Process a completely received message. | ||
190 | */ | ||
191 | static void line6_pod_process_message(struct usb_line6 *line6) | ||
192 | { | ||
193 | struct usb_line6_pod *pod = (struct usb_line6_pod *) line6; | ||
194 | const unsigned char *buf = pod->line6.buffer_message; | ||
195 | |||
196 | if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) { | ||
197 | pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15]; | ||
198 | pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) | | ||
199 | (int) buf[10]; | ||
200 | pod_startup3(pod); | ||
201 | return; | ||
202 | } | ||
203 | |||
204 | /* Only look for sysex messages from this device */ | ||
205 | if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) && | ||
206 | buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) { | ||
207 | return; | ||
208 | } | ||
209 | if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0) | ||
210 | return; | ||
211 | |||
212 | if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) { | ||
213 | short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) | | ||
214 | ((int)buf[9] << 4) | (int)buf[10]; | ||
215 | pod->monitor_level = value; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | Send system parameter (from integer). | ||
221 | */ | ||
222 | static int pod_set_system_param_int(struct usb_line6_pod *pod, int value, | ||
223 | int code) | ||
224 | { | ||
225 | char *sysex; | ||
226 | static const int size = 5; | ||
227 | |||
228 | sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size); | ||
229 | if (!sysex) | ||
230 | return -ENOMEM; | ||
231 | sysex[SYSEX_DATA_OFS] = code; | ||
232 | sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f; | ||
233 | sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f; | ||
234 | sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f; | ||
235 | sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f; | ||
236 | line6_send_sysex_message(&pod->line6, sysex, size); | ||
237 | kfree(sysex); | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | /* | ||
242 | "read" request on "serial_number" special file. | ||
243 | */ | ||
244 | static ssize_t serial_number_show(struct device *dev, | ||
245 | struct device_attribute *attr, char *buf) | ||
246 | { | ||
247 | struct usb_interface *interface = to_usb_interface(dev); | ||
248 | struct usb_line6_pod *pod = usb_get_intfdata(interface); | ||
249 | |||
250 | return sprintf(buf, "%u\n", pod->serial_number); | ||
251 | } | ||
252 | |||
253 | /* | ||
254 | "read" request on "firmware_version" special file. | ||
255 | */ | ||
256 | static ssize_t firmware_version_show(struct device *dev, | ||
257 | struct device_attribute *attr, char *buf) | ||
258 | { | ||
259 | struct usb_interface *interface = to_usb_interface(dev); | ||
260 | struct usb_line6_pod *pod = usb_get_intfdata(interface); | ||
261 | |||
262 | return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100, | ||
263 | pod->firmware_version % 100); | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | "read" request on "device_id" special file. | ||
268 | */ | ||
269 | static ssize_t device_id_show(struct device *dev, | ||
270 | struct device_attribute *attr, char *buf) | ||
271 | { | ||
272 | struct usb_interface *interface = to_usb_interface(dev); | ||
273 | struct usb_line6_pod *pod = usb_get_intfdata(interface); | ||
274 | |||
275 | return sprintf(buf, "%d\n", pod->device_id); | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | POD startup procedure. | ||
280 | This is a sequence of functions with special requirements (e.g., must | ||
281 | not run immediately after initialization, must not run in interrupt | ||
282 | context). After the last one has finished, the device is ready to use. | ||
283 | */ | ||
284 | |||
285 | static void pod_startup1(struct usb_line6_pod *pod) | ||
286 | { | ||
287 | CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT); | ||
288 | |||
289 | /* delay startup procedure: */ | ||
290 | line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2, | ||
291 | (unsigned long)pod); | ||
292 | } | ||
293 | |||
294 | static void pod_startup2(unsigned long data) | ||
295 | { | ||
296 | struct usb_line6_pod *pod = (struct usb_line6_pod *)data; | ||
297 | struct usb_line6 *line6 = &pod->line6; | ||
298 | |||
299 | CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ); | ||
300 | |||
301 | /* request firmware version: */ | ||
302 | line6_version_request_async(line6); | ||
303 | } | ||
304 | |||
305 | static void pod_startup3(struct usb_line6_pod *pod) | ||
306 | { | ||
307 | CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE); | ||
308 | |||
309 | /* schedule work for global work queue: */ | ||
310 | schedule_work(&pod->startup_work); | ||
311 | } | ||
312 | |||
313 | static void pod_startup4(struct work_struct *work) | ||
314 | { | ||
315 | struct usb_line6_pod *pod = | ||
316 | container_of(work, struct usb_line6_pod, startup_work); | ||
317 | struct usb_line6 *line6 = &pod->line6; | ||
318 | |||
319 | CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP); | ||
320 | |||
321 | /* serial number: */ | ||
322 | line6_read_serial_number(&pod->line6, &pod->serial_number); | ||
323 | |||
324 | /* ALSA audio interface: */ | ||
325 | snd_card_register(line6->card); | ||
326 | } | ||
327 | |||
328 | /* POD special files: */ | ||
329 | static DEVICE_ATTR_RO(device_id); | ||
330 | static DEVICE_ATTR_RO(firmware_version); | ||
331 | static DEVICE_ATTR_RO(serial_number); | ||
332 | |||
333 | static struct attribute *pod_dev_attrs[] = { | ||
334 | &dev_attr_device_id.attr, | ||
335 | &dev_attr_firmware_version.attr, | ||
336 | &dev_attr_serial_number.attr, | ||
337 | NULL | ||
338 | }; | ||
339 | |||
340 | static const struct attribute_group pod_dev_attr_group = { | ||
341 | .name = "pod", | ||
342 | .attrs = pod_dev_attrs, | ||
343 | }; | ||
344 | |||
345 | /* control info callback */ | ||
346 | static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol, | ||
347 | struct snd_ctl_elem_info *uinfo) | ||
348 | { | ||
349 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
350 | uinfo->count = 1; | ||
351 | uinfo->value.integer.min = 0; | ||
352 | uinfo->value.integer.max = 65535; | ||
353 | return 0; | ||
354 | } | ||
355 | |||
356 | /* control get callback */ | ||
357 | static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol, | ||
358 | struct snd_ctl_elem_value *ucontrol) | ||
359 | { | ||
360 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); | ||
361 | struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6; | ||
362 | |||
363 | ucontrol->value.integer.value[0] = pod->monitor_level; | ||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | /* control put callback */ | ||
368 | static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol, | ||
369 | struct snd_ctl_elem_value *ucontrol) | ||
370 | { | ||
371 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); | ||
372 | struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6; | ||
373 | |||
374 | if (ucontrol->value.integer.value[0] == pod->monitor_level) | ||
375 | return 0; | ||
376 | |||
377 | pod->monitor_level = ucontrol->value.integer.value[0]; | ||
378 | pod_set_system_param_int(pod, ucontrol->value.integer.value[0], | ||
379 | POD_MONITOR_LEVEL); | ||
380 | return 1; | ||
381 | } | ||
382 | |||
383 | /* control definition */ | ||
384 | static struct snd_kcontrol_new pod_control_monitor = { | ||
385 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
386 | .name = "Monitor Playback Volume", | ||
387 | .index = 0, | ||
388 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
389 | .info = snd_pod_control_monitor_info, | ||
390 | .get = snd_pod_control_monitor_get, | ||
391 | .put = snd_pod_control_monitor_put | ||
392 | }; | ||
393 | |||
394 | /* | ||
395 | POD device disconnected. | ||
396 | */ | ||
397 | static void line6_pod_disconnect(struct usb_line6 *line6) | ||
398 | { | ||
399 | struct usb_line6_pod *pod = (struct usb_line6_pod *)line6; | ||
400 | |||
401 | del_timer_sync(&pod->startup_timer); | ||
402 | cancel_work_sync(&pod->startup_work); | ||
403 | } | ||
404 | |||
405 | /* | ||
406 | Try to init POD device. | ||
407 | */ | ||
408 | static int pod_init(struct usb_line6 *line6, | ||
409 | const struct usb_device_id *id) | ||
410 | { | ||
411 | int err; | ||
412 | struct usb_line6_pod *pod = (struct usb_line6_pod *) line6; | ||
413 | |||
414 | line6->process_message = line6_pod_process_message; | ||
415 | line6->disconnect = line6_pod_disconnect; | ||
416 | |||
417 | init_timer(&pod->startup_timer); | ||
418 | INIT_WORK(&pod->startup_work, pod_startup4); | ||
419 | |||
420 | /* create sysfs entries: */ | ||
421 | err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group); | ||
422 | if (err < 0) | ||
423 | return err; | ||
424 | |||
425 | /* initialize MIDI subsystem: */ | ||
426 | err = line6_init_midi(line6); | ||
427 | if (err < 0) | ||
428 | return err; | ||
429 | |||
430 | /* initialize PCM subsystem: */ | ||
431 | err = line6_init_pcm(line6, &pod_pcm_properties); | ||
432 | if (err < 0) | ||
433 | return err; | ||
434 | |||
435 | /* register monitor control: */ | ||
436 | err = snd_ctl_add(line6->card, | ||
437 | snd_ctl_new1(&pod_control_monitor, line6->line6pcm)); | ||
438 | if (err < 0) | ||
439 | return err; | ||
440 | |||
441 | /* | ||
442 | When the sound card is registered at this point, the PODxt Live | ||
443 | displays "Invalid Code Error 07", so we do it later in the event | ||
444 | handler. | ||
445 | */ | ||
446 | |||
447 | if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { | ||
448 | pod->monitor_level = POD_SYSTEM_INVALID; | ||
449 | |||
450 | /* initiate startup procedure: */ | ||
451 | pod_startup1(pod); | ||
452 | } | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod) | ||
458 | #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n) | ||
459 | |||
460 | /* table of devices that work with this driver */ | ||
461 | static const struct usb_device_id pod_id_table[] = { | ||
462 | { LINE6_DEVICE(0x4250), .driver_info = LINE6_BASSPODXT }, | ||
463 | { LINE6_DEVICE(0x4642), .driver_info = LINE6_BASSPODXTLIVE }, | ||
464 | { LINE6_DEVICE(0x4252), .driver_info = LINE6_BASSPODXTPRO }, | ||
465 | { LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD }, | ||
466 | { LINE6_DEVICE(0x5044), .driver_info = LINE6_PODXT }, | ||
467 | { LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD }, | ||
468 | { LINE6_DEVICE(0x5050), .driver_info = LINE6_PODXTPRO }, | ||
469 | {} | ||
470 | }; | ||
471 | |||
472 | MODULE_DEVICE_TABLE(usb, pod_id_table); | ||
473 | |||
474 | static const struct line6_properties pod_properties_table[] = { | ||
475 | [LINE6_BASSPODXT] = { | ||
476 | .id = "BassPODxt", | ||
477 | .name = "BassPODxt", | ||
478 | .capabilities = LINE6_CAP_CONTROL | ||
479 | | LINE6_CAP_PCM | ||
480 | | LINE6_CAP_HWMON, | ||
481 | .altsetting = 5, | ||
482 | .ep_ctrl_r = 0x84, | ||
483 | .ep_ctrl_w = 0x03, | ||
484 | .ep_audio_r = 0x82, | ||
485 | .ep_audio_w = 0x01, | ||
486 | }, | ||
487 | [LINE6_BASSPODXTLIVE] = { | ||
488 | .id = "BassPODxtLive", | ||
489 | .name = "BassPODxt Live", | ||
490 | .capabilities = LINE6_CAP_CONTROL | ||
491 | | LINE6_CAP_PCM | ||
492 | | LINE6_CAP_HWMON, | ||
493 | .altsetting = 1, | ||
494 | .ep_ctrl_r = 0x84, | ||
495 | .ep_ctrl_w = 0x03, | ||
496 | .ep_audio_r = 0x82, | ||
497 | .ep_audio_w = 0x01, | ||
498 | }, | ||
499 | [LINE6_BASSPODXTPRO] = { | ||
500 | .id = "BassPODxtPro", | ||
501 | .name = "BassPODxt Pro", | ||
502 | .capabilities = LINE6_CAP_CONTROL | ||
503 | | LINE6_CAP_PCM | ||
504 | | LINE6_CAP_HWMON, | ||
505 | .altsetting = 5, | ||
506 | .ep_ctrl_r = 0x84, | ||
507 | .ep_ctrl_w = 0x03, | ||
508 | .ep_audio_r = 0x82, | ||
509 | .ep_audio_w = 0x01, | ||
510 | }, | ||
511 | [LINE6_POCKETPOD] = { | ||
512 | .id = "PocketPOD", | ||
513 | .name = "Pocket POD", | ||
514 | .capabilities = LINE6_CAP_CONTROL, | ||
515 | .altsetting = 0, | ||
516 | .ep_ctrl_r = 0x82, | ||
517 | .ep_ctrl_w = 0x02, | ||
518 | /* no audio channel */ | ||
519 | }, | ||
520 | [LINE6_PODXT] = { | ||
521 | .id = "PODxt", | ||
522 | .name = "PODxt", | ||
523 | .capabilities = LINE6_CAP_CONTROL | ||
524 | | LINE6_CAP_PCM | ||
525 | | LINE6_CAP_HWMON, | ||
526 | .altsetting = 5, | ||
527 | .ep_ctrl_r = 0x84, | ||
528 | .ep_ctrl_w = 0x03, | ||
529 | .ep_audio_r = 0x82, | ||
530 | .ep_audio_w = 0x01, | ||
531 | }, | ||
532 | [LINE6_PODXTLIVE_POD] = { | ||
533 | .id = "PODxtLive", | ||
534 | .name = "PODxt Live", | ||
535 | .capabilities = LINE6_CAP_CONTROL | ||
536 | | LINE6_CAP_PCM | ||
537 | | LINE6_CAP_HWMON, | ||
538 | .altsetting = 1, | ||
539 | .ep_ctrl_r = 0x84, | ||
540 | .ep_ctrl_w = 0x03, | ||
541 | .ep_audio_r = 0x82, | ||
542 | .ep_audio_w = 0x01, | ||
543 | }, | ||
544 | [LINE6_PODXTPRO] = { | ||
545 | .id = "PODxtPro", | ||
546 | .name = "PODxt Pro", | ||
547 | .capabilities = LINE6_CAP_CONTROL | ||
548 | | LINE6_CAP_PCM | ||
549 | | LINE6_CAP_HWMON, | ||
550 | .altsetting = 5, | ||
551 | .ep_ctrl_r = 0x84, | ||
552 | .ep_ctrl_w = 0x03, | ||
553 | .ep_audio_r = 0x82, | ||
554 | .ep_audio_w = 0x01, | ||
555 | }, | ||
556 | }; | ||
557 | |||
558 | /* | ||
559 | Probe USB device. | ||
560 | */ | ||
561 | static int pod_probe(struct usb_interface *interface, | ||
562 | const struct usb_device_id *id) | ||
563 | { | ||
564 | return line6_probe(interface, id, "Line6-POD", | ||
565 | &pod_properties_table[id->driver_info], | ||
566 | pod_init, sizeof(struct usb_line6_pod)); | ||
567 | } | ||
568 | |||
569 | static struct usb_driver pod_driver = { | ||
570 | .name = KBUILD_MODNAME, | ||
571 | .probe = pod_probe, | ||
572 | .disconnect = line6_disconnect, | ||
573 | #ifdef CONFIG_PM | ||
574 | .suspend = line6_suspend, | ||
575 | .resume = line6_resume, | ||
576 | .reset_resume = line6_resume, | ||
577 | #endif | ||
578 | .id_table = pod_id_table, | ||
579 | }; | ||
580 | |||
581 | module_usb_driver(pod_driver); | ||
582 | |||
583 | MODULE_DESCRIPTION("Line 6 POD USB driver"); | ||
584 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c new file mode 100644 index 000000000000..63dcaef41ac3 --- /dev/null +++ b/sound/usb/line6/podhd.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /* | ||
2 | * Line 6 Pod HD | ||
3 | * | ||
4 | * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/usb.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <sound/core.h> | ||
16 | #include <sound/pcm.h> | ||
17 | |||
18 | #include "driver.h" | ||
19 | #include "pcm.h" | ||
20 | |||
21 | enum { | ||
22 | LINE6_PODHD300, | ||
23 | LINE6_PODHD400, | ||
24 | LINE6_PODHD500_0, | ||
25 | LINE6_PODHD500_1, | ||
26 | }; | ||
27 | |||
28 | #define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ | ||
29 | |||
30 | static struct snd_ratden podhd_ratden = { | ||
31 | .num_min = 48000, | ||
32 | .num_max = 48000, | ||
33 | .num_step = 1, | ||
34 | .den = 1, | ||
35 | }; | ||
36 | |||
37 | static struct line6_pcm_properties podhd_pcm_properties = { | ||
38 | .playback_hw = { | ||
39 | .info = (SNDRV_PCM_INFO_MMAP | | ||
40 | SNDRV_PCM_INFO_INTERLEAVED | | ||
41 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
42 | SNDRV_PCM_INFO_MMAP_VALID | | ||
43 | SNDRV_PCM_INFO_PAUSE | | ||
44 | SNDRV_PCM_INFO_SYNC_START), | ||
45 | .formats = SNDRV_PCM_FMTBIT_S24_3LE, | ||
46 | .rates = SNDRV_PCM_RATE_48000, | ||
47 | .rate_min = 48000, | ||
48 | .rate_max = 48000, | ||
49 | .channels_min = 2, | ||
50 | .channels_max = 2, | ||
51 | .buffer_bytes_max = 60000, | ||
52 | .period_bytes_min = 64, | ||
53 | .period_bytes_max = 8192, | ||
54 | .periods_min = 1, | ||
55 | .periods_max = 1024}, | ||
56 | .capture_hw = { | ||
57 | .info = (SNDRV_PCM_INFO_MMAP | | ||
58 | SNDRV_PCM_INFO_INTERLEAVED | | ||
59 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
60 | SNDRV_PCM_INFO_MMAP_VALID | | ||
61 | SNDRV_PCM_INFO_SYNC_START), | ||
62 | .formats = SNDRV_PCM_FMTBIT_S24_3LE, | ||
63 | .rates = SNDRV_PCM_RATE_48000, | ||
64 | .rate_min = 48000, | ||
65 | .rate_max = 48000, | ||
66 | .channels_min = 2, | ||
67 | .channels_max = 2, | ||
68 | .buffer_bytes_max = 60000, | ||
69 | .period_bytes_min = 64, | ||
70 | .period_bytes_max = 8192, | ||
71 | .periods_min = 1, | ||
72 | .periods_max = 1024}, | ||
73 | .rates = { | ||
74 | .nrats = 1, | ||
75 | .rats = &podhd_ratden}, | ||
76 | .bytes_per_frame = PODHD_BYTES_PER_FRAME | ||
77 | }; | ||
78 | |||
79 | /* | ||
80 | Try to init POD HD device. | ||
81 | */ | ||
82 | static int podhd_init(struct usb_line6 *line6, | ||
83 | const struct usb_device_id *id) | ||
84 | { | ||
85 | int err; | ||
86 | |||
87 | /* initialize MIDI subsystem: */ | ||
88 | err = line6_init_midi(line6); | ||
89 | if (err < 0) | ||
90 | return err; | ||
91 | |||
92 | /* initialize PCM subsystem: */ | ||
93 | err = line6_init_pcm(line6, &podhd_pcm_properties); | ||
94 | if (err < 0) | ||
95 | return err; | ||
96 | |||
97 | /* register USB audio system: */ | ||
98 | return snd_card_register(line6->card); | ||
99 | } | ||
100 | |||
101 | #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod) | ||
102 | #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n) | ||
103 | |||
104 | /* table of devices that work with this driver */ | ||
105 | static const struct usb_device_id podhd_id_table[] = { | ||
106 | { LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 }, | ||
107 | { LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 }, | ||
108 | { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 }, | ||
109 | { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 }, | ||
110 | {} | ||
111 | }; | ||
112 | |||
113 | MODULE_DEVICE_TABLE(usb, podhd_id_table); | ||
114 | |||
115 | static const struct line6_properties podhd_properties_table[] = { | ||
116 | [LINE6_PODHD300] = { | ||
117 | .id = "PODHD300", | ||
118 | .name = "POD HD300", | ||
119 | .capabilities = LINE6_CAP_CONTROL | ||
120 | | LINE6_CAP_PCM | ||
121 | | LINE6_CAP_HWMON, | ||
122 | .altsetting = 5, | ||
123 | .ep_ctrl_r = 0x84, | ||
124 | .ep_ctrl_w = 0x03, | ||
125 | .ep_audio_r = 0x82, | ||
126 | .ep_audio_w = 0x01, | ||
127 | }, | ||
128 | [LINE6_PODHD400] = { | ||
129 | .id = "PODHD400", | ||
130 | .name = "POD HD400", | ||
131 | .capabilities = LINE6_CAP_CONTROL | ||
132 | | LINE6_CAP_PCM | ||
133 | | LINE6_CAP_HWMON, | ||
134 | .altsetting = 5, | ||
135 | .ep_ctrl_r = 0x84, | ||
136 | .ep_ctrl_w = 0x03, | ||
137 | .ep_audio_r = 0x82, | ||
138 | .ep_audio_w = 0x01, | ||
139 | }, | ||
140 | [LINE6_PODHD500_0] = { | ||
141 | .id = "PODHD500", | ||
142 | .name = "POD HD500", | ||
143 | .capabilities = LINE6_CAP_CONTROL | ||
144 | | LINE6_CAP_PCM | ||
145 | | LINE6_CAP_HWMON, | ||
146 | .altsetting = 1, | ||
147 | .ep_ctrl_r = 0x81, | ||
148 | .ep_ctrl_w = 0x01, | ||
149 | .ep_audio_r = 0x86, | ||
150 | .ep_audio_w = 0x02, | ||
151 | }, | ||
152 | [LINE6_PODHD500_1] = { | ||
153 | .id = "PODHD500", | ||
154 | .name = "POD HD500", | ||
155 | .capabilities = LINE6_CAP_CONTROL | ||
156 | | LINE6_CAP_PCM | ||
157 | | LINE6_CAP_HWMON, | ||
158 | .altsetting = 1, | ||
159 | .ep_ctrl_r = 0x81, | ||
160 | .ep_ctrl_w = 0x01, | ||
161 | .ep_audio_r = 0x86, | ||
162 | .ep_audio_w = 0x02, | ||
163 | }, | ||
164 | }; | ||
165 | |||
166 | /* | ||
167 | Probe USB device. | ||
168 | */ | ||
169 | static int podhd_probe(struct usb_interface *interface, | ||
170 | const struct usb_device_id *id) | ||
171 | { | ||
172 | return line6_probe(interface, id, "Line6-PODHD", | ||
173 | &podhd_properties_table[id->driver_info], | ||
174 | podhd_init, sizeof(struct usb_line6)); | ||
175 | } | ||
176 | |||
177 | static struct usb_driver podhd_driver = { | ||
178 | .name = KBUILD_MODNAME, | ||
179 | .probe = podhd_probe, | ||
180 | .disconnect = line6_disconnect, | ||
181 | #ifdef CONFIG_PM | ||
182 | .suspend = line6_suspend, | ||
183 | .resume = line6_resume, | ||
184 | .reset_resume = line6_resume, | ||
185 | #endif | ||
186 | .id_table = podhd_id_table, | ||
187 | }; | ||
188 | |||
189 | module_usb_driver(podhd_driver); | ||
190 | |||
191 | MODULE_DESCRIPTION("Line 6 PODHD USB driver"); | ||
192 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c new file mode 100644 index 000000000000..6d4c50c9b17d --- /dev/null +++ b/sound/usb/line6/toneport.c | |||
@@ -0,0 +1,580 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * Emil Myhrman (emil.myhrman@gmail.com) | ||
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 as | ||
9 | * published by the Free Software Foundation, version 2. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/wait.h> | ||
14 | #include <linux/usb.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/leds.h> | ||
18 | #include <sound/core.h> | ||
19 | #include <sound/control.h> | ||
20 | |||
21 | #include "capture.h" | ||
22 | #include "driver.h" | ||
23 | #include "playback.h" | ||
24 | |||
25 | enum line6_device_type { | ||
26 | LINE6_GUITARPORT, | ||
27 | LINE6_PODSTUDIO_GX, | ||
28 | LINE6_PODSTUDIO_UX1, | ||
29 | LINE6_PODSTUDIO_UX2, | ||
30 | LINE6_TONEPORT_GX, | ||
31 | LINE6_TONEPORT_UX1, | ||
32 | LINE6_TONEPORT_UX2, | ||
33 | }; | ||
34 | |||
35 | struct usb_line6_toneport; | ||
36 | |||
37 | struct toneport_led { | ||
38 | struct led_classdev dev; | ||
39 | char name[64]; | ||
40 | struct usb_line6_toneport *toneport; | ||
41 | bool registered; | ||
42 | }; | ||
43 | |||
44 | struct usb_line6_toneport { | ||
45 | /* Generic Line 6 USB data */ | ||
46 | struct usb_line6 line6; | ||
47 | |||
48 | /* Source selector */ | ||
49 | int source; | ||
50 | |||
51 | /* Serial number of device */ | ||
52 | u32 serial_number; | ||
53 | |||
54 | /* Firmware version (x 100) */ | ||
55 | u8 firmware_version; | ||
56 | |||
57 | /* Timer for delayed PCM startup */ | ||
58 | struct timer_list timer; | ||
59 | |||
60 | /* Device type */ | ||
61 | enum line6_device_type type; | ||
62 | |||
63 | /* LED instances */ | ||
64 | struct toneport_led leds[2]; | ||
65 | }; | ||
66 | |||
67 | static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2); | ||
68 | |||
69 | #define TONEPORT_PCM_DELAY 1 | ||
70 | |||
71 | static struct snd_ratden toneport_ratden = { | ||
72 | .num_min = 44100, | ||
73 | .num_max = 44100, | ||
74 | .num_step = 1, | ||
75 | .den = 1 | ||
76 | }; | ||
77 | |||
78 | static struct line6_pcm_properties toneport_pcm_properties = { | ||
79 | .playback_hw = { | ||
80 | .info = (SNDRV_PCM_INFO_MMAP | | ||
81 | SNDRV_PCM_INFO_INTERLEAVED | | ||
82 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
83 | SNDRV_PCM_INFO_MMAP_VALID | | ||
84 | SNDRV_PCM_INFO_PAUSE | | ||
85 | SNDRV_PCM_INFO_SYNC_START), | ||
86 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
87 | .rates = SNDRV_PCM_RATE_KNOT, | ||
88 | .rate_min = 44100, | ||
89 | .rate_max = 44100, | ||
90 | .channels_min = 2, | ||
91 | .channels_max = 2, | ||
92 | .buffer_bytes_max = 60000, | ||
93 | .period_bytes_min = 64, | ||
94 | .period_bytes_max = 8192, | ||
95 | .periods_min = 1, | ||
96 | .periods_max = 1024}, | ||
97 | .capture_hw = { | ||
98 | .info = (SNDRV_PCM_INFO_MMAP | | ||
99 | SNDRV_PCM_INFO_INTERLEAVED | | ||
100 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
101 | SNDRV_PCM_INFO_MMAP_VALID | | ||
102 | SNDRV_PCM_INFO_SYNC_START), | ||
103 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
104 | .rates = SNDRV_PCM_RATE_KNOT, | ||
105 | .rate_min = 44100, | ||
106 | .rate_max = 44100, | ||
107 | .channels_min = 2, | ||
108 | .channels_max = 2, | ||
109 | .buffer_bytes_max = 60000, | ||
110 | .period_bytes_min = 64, | ||
111 | .period_bytes_max = 8192, | ||
112 | .periods_min = 1, | ||
113 | .periods_max = 1024}, | ||
114 | .rates = { | ||
115 | .nrats = 1, | ||
116 | .rats = &toneport_ratden}, | ||
117 | .bytes_per_frame = 4 | ||
118 | }; | ||
119 | |||
120 | static const struct { | ||
121 | const char *name; | ||
122 | int code; | ||
123 | } toneport_source_info[] = { | ||
124 | {"Microphone", 0x0a01}, | ||
125 | {"Line", 0x0801}, | ||
126 | {"Instrument", 0x0b01}, | ||
127 | {"Inst & Mic", 0x0901} | ||
128 | }; | ||
129 | |||
130 | static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) | ||
131 | { | ||
132 | int ret; | ||
133 | |||
134 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, | ||
135 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
136 | cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ); | ||
137 | |||
138 | if (ret < 0) { | ||
139 | dev_err(&usbdev->dev, "send failed (error %d)\n", ret); | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | /* monitor info callback */ | ||
147 | static int snd_toneport_monitor_info(struct snd_kcontrol *kcontrol, | ||
148 | struct snd_ctl_elem_info *uinfo) | ||
149 | { | ||
150 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
151 | uinfo->count = 1; | ||
152 | uinfo->value.integer.min = 0; | ||
153 | uinfo->value.integer.max = 256; | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | /* monitor get callback */ | ||
158 | static int snd_toneport_monitor_get(struct snd_kcontrol *kcontrol, | ||
159 | struct snd_ctl_elem_value *ucontrol) | ||
160 | { | ||
161 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); | ||
162 | |||
163 | ucontrol->value.integer.value[0] = line6pcm->volume_monitor; | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | /* monitor put callback */ | ||
168 | static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol, | ||
169 | struct snd_ctl_elem_value *ucontrol) | ||
170 | { | ||
171 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); | ||
172 | int err; | ||
173 | |||
174 | if (ucontrol->value.integer.value[0] == line6pcm->volume_monitor) | ||
175 | return 0; | ||
176 | |||
177 | line6pcm->volume_monitor = ucontrol->value.integer.value[0]; | ||
178 | |||
179 | if (line6pcm->volume_monitor > 0) { | ||
180 | err = line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR); | ||
181 | if (err < 0) { | ||
182 | line6pcm->volume_monitor = 0; | ||
183 | line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR); | ||
184 | return err; | ||
185 | } | ||
186 | } else { | ||
187 | line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR); | ||
188 | } | ||
189 | |||
190 | return 1; | ||
191 | } | ||
192 | |||
193 | /* source info callback */ | ||
194 | static int snd_toneport_source_info(struct snd_kcontrol *kcontrol, | ||
195 | struct snd_ctl_elem_info *uinfo) | ||
196 | { | ||
197 | const int size = ARRAY_SIZE(toneport_source_info); | ||
198 | |||
199 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
200 | uinfo->count = 1; | ||
201 | uinfo->value.enumerated.items = size; | ||
202 | |||
203 | if (uinfo->value.enumerated.item >= size) | ||
204 | uinfo->value.enumerated.item = size - 1; | ||
205 | |||
206 | strcpy(uinfo->value.enumerated.name, | ||
207 | toneport_source_info[uinfo->value.enumerated.item].name); | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | /* source get callback */ | ||
213 | static int snd_toneport_source_get(struct snd_kcontrol *kcontrol, | ||
214 | struct snd_ctl_elem_value *ucontrol) | ||
215 | { | ||
216 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); | ||
217 | struct usb_line6_toneport *toneport = | ||
218 | (struct usb_line6_toneport *)line6pcm->line6; | ||
219 | ucontrol->value.enumerated.item[0] = toneport->source; | ||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | /* source put callback */ | ||
224 | static int snd_toneport_source_put(struct snd_kcontrol *kcontrol, | ||
225 | struct snd_ctl_elem_value *ucontrol) | ||
226 | { | ||
227 | struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); | ||
228 | struct usb_line6_toneport *toneport = | ||
229 | (struct usb_line6_toneport *)line6pcm->line6; | ||
230 | unsigned int source; | ||
231 | |||
232 | source = ucontrol->value.enumerated.item[0]; | ||
233 | if (source >= ARRAY_SIZE(toneport_source_info)) | ||
234 | return -EINVAL; | ||
235 | if (source == toneport->source) | ||
236 | return 0; | ||
237 | |||
238 | toneport->source = source; | ||
239 | toneport_send_cmd(toneport->line6.usbdev, | ||
240 | toneport_source_info[source].code, 0x0000); | ||
241 | return 1; | ||
242 | } | ||
243 | |||
244 | static void toneport_start_pcm(unsigned long arg) | ||
245 | { | ||
246 | struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg; | ||
247 | struct usb_line6 *line6 = &toneport->line6; | ||
248 | |||
249 | line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR); | ||
250 | } | ||
251 | |||
252 | /* control definition */ | ||
253 | static struct snd_kcontrol_new toneport_control_monitor = { | ||
254 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
255 | .name = "Monitor Playback Volume", | ||
256 | .index = 0, | ||
257 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
258 | .info = snd_toneport_monitor_info, | ||
259 | .get = snd_toneport_monitor_get, | ||
260 | .put = snd_toneport_monitor_put | ||
261 | }; | ||
262 | |||
263 | /* source selector definition */ | ||
264 | static struct snd_kcontrol_new toneport_control_source = { | ||
265 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
266 | .name = "PCM Capture Source", | ||
267 | .index = 0, | ||
268 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
269 | .info = snd_toneport_source_info, | ||
270 | .get = snd_toneport_source_get, | ||
271 | .put = snd_toneport_source_put | ||
272 | }; | ||
273 | |||
274 | /* | ||
275 | For the led on Guitarport. | ||
276 | Brightness goes from 0x00 to 0x26. Set a value above this to have led | ||
277 | blink. | ||
278 | (void cmd_0x02(byte red, byte green) | ||
279 | */ | ||
280 | |||
281 | static bool toneport_has_led(struct usb_line6_toneport *toneport) | ||
282 | { | ||
283 | switch (toneport->type) { | ||
284 | case LINE6_GUITARPORT: | ||
285 | case LINE6_TONEPORT_GX: | ||
286 | /* add your device here if you are missing support for the LEDs */ | ||
287 | return true; | ||
288 | |||
289 | default: | ||
290 | return false; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | static const char * const led_colors[2] = { "red", "green" }; | ||
295 | static const int led_init_vals[2] = { 0x00, 0x26 }; | ||
296 | |||
297 | static void toneport_update_led(struct usb_line6_toneport *toneport) | ||
298 | { | ||
299 | toneport_send_cmd(toneport->line6.usbdev, | ||
300 | (toneport->leds[0].dev.brightness << 8) | 0x0002, | ||
301 | toneport->leds[1].dev.brightness); | ||
302 | } | ||
303 | |||
304 | static void toneport_led_brightness_set(struct led_classdev *led_cdev, | ||
305 | enum led_brightness brightness) | ||
306 | { | ||
307 | struct toneport_led *leds = | ||
308 | container_of(led_cdev, struct toneport_led, dev); | ||
309 | toneport_update_led(leds->toneport); | ||
310 | } | ||
311 | |||
312 | static int toneport_init_leds(struct usb_line6_toneport *toneport) | ||
313 | { | ||
314 | struct device *dev = &toneport->line6.usbdev->dev; | ||
315 | int i, err; | ||
316 | |||
317 | for (i = 0; i < 2; i++) { | ||
318 | struct toneport_led *led = &toneport->leds[i]; | ||
319 | struct led_classdev *leddev = &led->dev; | ||
320 | |||
321 | led->toneport = toneport; | ||
322 | snprintf(led->name, sizeof(led->name), "%s::%s", | ||
323 | dev_name(dev), led_colors[i]); | ||
324 | leddev->name = led->name; | ||
325 | leddev->brightness = led_init_vals[i]; | ||
326 | leddev->max_brightness = 0x26; | ||
327 | leddev->brightness_set = toneport_led_brightness_set; | ||
328 | err = led_classdev_register(dev, leddev); | ||
329 | if (err) | ||
330 | return err; | ||
331 | led->registered = true; | ||
332 | } | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static void toneport_remove_leds(struct usb_line6_toneport *toneport) | ||
338 | { | ||
339 | struct toneport_led *led; | ||
340 | int i; | ||
341 | |||
342 | for (i = 0; i < 2; i++) { | ||
343 | led = &toneport->leds[i]; | ||
344 | if (!led->registered) | ||
345 | break; | ||
346 | led_classdev_unregister(&led->dev); | ||
347 | led->registered = false; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | static bool toneport_has_source_select(struct usb_line6_toneport *toneport) | ||
352 | { | ||
353 | switch (toneport->type) { | ||
354 | case LINE6_TONEPORT_UX1: | ||
355 | case LINE6_TONEPORT_UX2: | ||
356 | case LINE6_PODSTUDIO_UX1: | ||
357 | case LINE6_PODSTUDIO_UX2: | ||
358 | return true; | ||
359 | |||
360 | default: | ||
361 | return false; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | /* | ||
366 | Setup Toneport device. | ||
367 | */ | ||
368 | static void toneport_setup(struct usb_line6_toneport *toneport) | ||
369 | { | ||
370 | int ticks; | ||
371 | struct usb_line6 *line6 = &toneport->line6; | ||
372 | struct usb_device *usbdev = line6->usbdev; | ||
373 | |||
374 | /* sync time on device with host: */ | ||
375 | ticks = (int)get_seconds(); | ||
376 | line6_write_data(line6, 0x80c6, &ticks, 4); | ||
377 | |||
378 | /* enable device: */ | ||
379 | toneport_send_cmd(usbdev, 0x0301, 0x0000); | ||
380 | |||
381 | /* initialize source select: */ | ||
382 | if (toneport_has_source_select(toneport)) | ||
383 | toneport_send_cmd(usbdev, | ||
384 | toneport_source_info[toneport->source].code, | ||
385 | 0x0000); | ||
386 | |||
387 | if (toneport_has_led(toneport)) | ||
388 | toneport_update_led(toneport); | ||
389 | |||
390 | mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ); | ||
391 | } | ||
392 | |||
393 | /* | ||
394 | Toneport device disconnected. | ||
395 | */ | ||
396 | static void line6_toneport_disconnect(struct usb_line6 *line6) | ||
397 | { | ||
398 | struct usb_line6_toneport *toneport = | ||
399 | (struct usb_line6_toneport *)line6; | ||
400 | |||
401 | del_timer_sync(&toneport->timer); | ||
402 | |||
403 | if (toneport_has_led(toneport)) | ||
404 | toneport_remove_leds(toneport); | ||
405 | } | ||
406 | |||
407 | |||
408 | /* | ||
409 | Try to init Toneport device. | ||
410 | */ | ||
411 | static int toneport_init(struct usb_line6 *line6, | ||
412 | const struct usb_device_id *id) | ||
413 | { | ||
414 | int err; | ||
415 | struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6; | ||
416 | |||
417 | toneport->type = id->driver_info; | ||
418 | setup_timer(&toneport->timer, toneport_start_pcm, | ||
419 | (unsigned long)toneport); | ||
420 | |||
421 | line6->disconnect = line6_toneport_disconnect; | ||
422 | |||
423 | /* initialize PCM subsystem: */ | ||
424 | err = line6_init_pcm(line6, &toneport_pcm_properties); | ||
425 | if (err < 0) | ||
426 | return err; | ||
427 | |||
428 | /* register monitor control: */ | ||
429 | err = snd_ctl_add(line6->card, | ||
430 | snd_ctl_new1(&toneport_control_monitor, | ||
431 | line6->line6pcm)); | ||
432 | if (err < 0) | ||
433 | return err; | ||
434 | |||
435 | /* register source select control: */ | ||
436 | if (toneport_has_source_select(toneport)) { | ||
437 | err = | ||
438 | snd_ctl_add(line6->card, | ||
439 | snd_ctl_new1(&toneport_control_source, | ||
440 | line6->line6pcm)); | ||
441 | if (err < 0) | ||
442 | return err; | ||
443 | } | ||
444 | |||
445 | line6_read_serial_number(line6, &toneport->serial_number); | ||
446 | line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1); | ||
447 | |||
448 | if (toneport_has_led(toneport)) { | ||
449 | err = toneport_init_leds(toneport); | ||
450 | if (err < 0) | ||
451 | return err; | ||
452 | } | ||
453 | |||
454 | toneport_setup(toneport); | ||
455 | |||
456 | /* register audio system: */ | ||
457 | return snd_card_register(line6->card); | ||
458 | } | ||
459 | |||
460 | #ifdef CONFIG_PM | ||
461 | /* | ||
462 | Resume Toneport device after reset. | ||
463 | */ | ||
464 | static int toneport_reset_resume(struct usb_interface *interface) | ||
465 | { | ||
466 | toneport_setup(usb_get_intfdata(interface)); | ||
467 | return line6_resume(interface); | ||
468 | } | ||
469 | #endif | ||
470 | |||
471 | #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod) | ||
472 | #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n) | ||
473 | |||
474 | /* table of devices that work with this driver */ | ||
475 | static const struct usb_device_id toneport_id_table[] = { | ||
476 | { LINE6_DEVICE(0x4750), .driver_info = LINE6_GUITARPORT }, | ||
477 | { LINE6_DEVICE(0x4153), .driver_info = LINE6_PODSTUDIO_GX }, | ||
478 | { LINE6_DEVICE(0x4150), .driver_info = LINE6_PODSTUDIO_UX1 }, | ||
479 | { LINE6_IF_NUM(0x4151, 0), .driver_info = LINE6_PODSTUDIO_UX2 }, | ||
480 | { LINE6_DEVICE(0x4147), .driver_info = LINE6_TONEPORT_GX }, | ||
481 | { LINE6_DEVICE(0x4141), .driver_info = LINE6_TONEPORT_UX1 }, | ||
482 | { LINE6_IF_NUM(0x4142, 0), .driver_info = LINE6_TONEPORT_UX2 }, | ||
483 | {} | ||
484 | }; | ||
485 | |||
486 | MODULE_DEVICE_TABLE(usb, toneport_id_table); | ||
487 | |||
488 | static const struct line6_properties toneport_properties_table[] = { | ||
489 | [LINE6_GUITARPORT] = { | ||
490 | .id = "GuitarPort", | ||
491 | .name = "GuitarPort", | ||
492 | .capabilities = LINE6_CAP_PCM, | ||
493 | .altsetting = 2, /* 1..4 seem to be ok */ | ||
494 | /* no control channel */ | ||
495 | .ep_audio_r = 0x82, | ||
496 | .ep_audio_w = 0x01, | ||
497 | }, | ||
498 | [LINE6_PODSTUDIO_GX] = { | ||
499 | .id = "PODStudioGX", | ||
500 | .name = "POD Studio GX", | ||
501 | .capabilities = LINE6_CAP_PCM, | ||
502 | .altsetting = 2, /* 1..4 seem to be ok */ | ||
503 | /* no control channel */ | ||
504 | .ep_audio_r = 0x82, | ||
505 | .ep_audio_w = 0x01, | ||
506 | }, | ||
507 | [LINE6_PODSTUDIO_UX1] = { | ||
508 | .id = "PODStudioUX1", | ||
509 | .name = "POD Studio UX1", | ||
510 | .capabilities = LINE6_CAP_PCM, | ||
511 | .altsetting = 2, /* 1..4 seem to be ok */ | ||
512 | /* no control channel */ | ||
513 | .ep_audio_r = 0x82, | ||
514 | .ep_audio_w = 0x01, | ||
515 | }, | ||
516 | [LINE6_PODSTUDIO_UX2] = { | ||
517 | .id = "PODStudioUX2", | ||
518 | .name = "POD Studio UX2", | ||
519 | .capabilities = LINE6_CAP_PCM, | ||
520 | .altsetting = 2, /* defaults to 44.1kHz, 16-bit */ | ||
521 | /* no control channel */ | ||
522 | .ep_audio_r = 0x82, | ||
523 | .ep_audio_w = 0x01, | ||
524 | }, | ||
525 | [LINE6_TONEPORT_GX] = { | ||
526 | .id = "TonePortGX", | ||
527 | .name = "TonePort GX", | ||
528 | .capabilities = LINE6_CAP_PCM, | ||
529 | .altsetting = 2, /* 1..4 seem to be ok */ | ||
530 | /* no control channel */ | ||
531 | .ep_audio_r = 0x82, | ||
532 | .ep_audio_w = 0x01, | ||
533 | }, | ||
534 | [LINE6_TONEPORT_UX1] = { | ||
535 | .id = "TonePortUX1", | ||
536 | .name = "TonePort UX1", | ||
537 | .capabilities = LINE6_CAP_PCM, | ||
538 | .altsetting = 2, /* 1..4 seem to be ok */ | ||
539 | /* no control channel */ | ||
540 | .ep_audio_r = 0x82, | ||
541 | .ep_audio_w = 0x01, | ||
542 | }, | ||
543 | [LINE6_TONEPORT_UX2] = { | ||
544 | .id = "TonePortUX2", | ||
545 | .name = "TonePort UX2", | ||
546 | .capabilities = LINE6_CAP_PCM, | ||
547 | .altsetting = 2, /* defaults to 44.1kHz, 16-bit */ | ||
548 | /* no control channel */ | ||
549 | .ep_audio_r = 0x82, | ||
550 | .ep_audio_w = 0x01, | ||
551 | }, | ||
552 | }; | ||
553 | |||
554 | /* | ||
555 | Probe USB device. | ||
556 | */ | ||
557 | static int toneport_probe(struct usb_interface *interface, | ||
558 | const struct usb_device_id *id) | ||
559 | { | ||
560 | return line6_probe(interface, id, "Line6-TonePort", | ||
561 | &toneport_properties_table[id->driver_info], | ||
562 | toneport_init, sizeof(struct usb_line6_toneport)); | ||
563 | } | ||
564 | |||
565 | static struct usb_driver toneport_driver = { | ||
566 | .name = KBUILD_MODNAME, | ||
567 | .probe = toneport_probe, | ||
568 | .disconnect = line6_disconnect, | ||
569 | #ifdef CONFIG_PM | ||
570 | .suspend = line6_suspend, | ||
571 | .resume = line6_resume, | ||
572 | .reset_resume = toneport_reset_resume, | ||
573 | #endif | ||
574 | .id_table = toneport_id_table, | ||
575 | }; | ||
576 | |||
577 | module_usb_driver(toneport_driver); | ||
578 | |||
579 | MODULE_DESCRIPTION("TonePort USB driver"); | ||
580 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c new file mode 100644 index 000000000000..ddc23ddf0750 --- /dev/null +++ b/sound/usb/line6/variax.c | |||
@@ -0,0 +1,306 @@ | |||
1 | /* | ||
2 | * Line 6 Linux USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/slab.h> | ||
13 | #include <linux/spinlock.h> | ||
14 | #include <linux/usb.h> | ||
15 | #include <linux/wait.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <sound/core.h> | ||
18 | |||
19 | #include "driver.h" | ||
20 | |||
21 | #define VARIAX_STARTUP_DELAY1 1000 | ||
22 | #define VARIAX_STARTUP_DELAY3 100 | ||
23 | #define VARIAX_STARTUP_DELAY4 100 | ||
24 | |||
25 | /* | ||
26 | Stages of Variax startup procedure | ||
27 | */ | ||
28 | enum { | ||
29 | VARIAX_STARTUP_INIT = 1, | ||
30 | VARIAX_STARTUP_VERSIONREQ, | ||
31 | VARIAX_STARTUP_WAIT, | ||
32 | VARIAX_STARTUP_ACTIVATE, | ||
33 | VARIAX_STARTUP_WORKQUEUE, | ||
34 | VARIAX_STARTUP_SETUP, | ||
35 | VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1 | ||
36 | }; | ||
37 | |||
38 | enum { | ||
39 | LINE6_PODXTLIVE_VARIAX, | ||
40 | LINE6_VARIAX | ||
41 | }; | ||
42 | |||
43 | struct usb_line6_variax { | ||
44 | /* Generic Line 6 USB data */ | ||
45 | struct usb_line6 line6; | ||
46 | |||
47 | /* Buffer for activation code */ | ||
48 | unsigned char *buffer_activate; | ||
49 | |||
50 | /* Handler for device initialization */ | ||
51 | struct work_struct startup_work; | ||
52 | |||
53 | /* Timers for device initialization */ | ||
54 | struct timer_list startup_timer1; | ||
55 | struct timer_list startup_timer2; | ||
56 | |||
57 | /* Current progress in startup procedure */ | ||
58 | int startup_progress; | ||
59 | }; | ||
60 | |||
61 | #define VARIAX_OFFSET_ACTIVATE 7 | ||
62 | |||
63 | /* | ||
64 | This message is sent by the device during initialization and identifies | ||
65 | the connected guitar version. | ||
66 | */ | ||
67 | static const char variax_init_version[] = { | ||
68 | 0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c, | ||
69 | 0x07, 0x00, 0x00, 0x00 | ||
70 | }; | ||
71 | |||
72 | /* | ||
73 | This message is the last one sent by the device during initialization. | ||
74 | */ | ||
75 | static const char variax_init_done[] = { | ||
76 | 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b | ||
77 | }; | ||
78 | |||
79 | static const char variax_activate[] = { | ||
80 | 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01, | ||
81 | 0xf7 | ||
82 | }; | ||
83 | |||
84 | /* forward declarations: */ | ||
85 | static void variax_startup2(unsigned long data); | ||
86 | static void variax_startup4(unsigned long data); | ||
87 | static void variax_startup5(unsigned long data); | ||
88 | |||
89 | static void variax_activate_async(struct usb_line6_variax *variax, int a) | ||
90 | { | ||
91 | variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a; | ||
92 | line6_send_raw_message_async(&variax->line6, variax->buffer_activate, | ||
93 | sizeof(variax_activate)); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | Variax startup procedure. | ||
98 | This is a sequence of functions with special requirements (e.g., must | ||
99 | not run immediately after initialization, must not run in interrupt | ||
100 | context). After the last one has finished, the device is ready to use. | ||
101 | */ | ||
102 | |||
103 | static void variax_startup1(struct usb_line6_variax *variax) | ||
104 | { | ||
105 | CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT); | ||
106 | |||
107 | /* delay startup procedure: */ | ||
108 | line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1, | ||
109 | variax_startup2, (unsigned long)variax); | ||
110 | } | ||
111 | |||
112 | static void variax_startup2(unsigned long data) | ||
113 | { | ||
114 | struct usb_line6_variax *variax = (struct usb_line6_variax *)data; | ||
115 | struct usb_line6 *line6 = &variax->line6; | ||
116 | |||
117 | /* schedule another startup procedure until startup is complete: */ | ||
118 | if (variax->startup_progress >= VARIAX_STARTUP_LAST) | ||
119 | return; | ||
120 | |||
121 | variax->startup_progress = VARIAX_STARTUP_VERSIONREQ; | ||
122 | line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1, | ||
123 | variax_startup2, (unsigned long)variax); | ||
124 | |||
125 | /* request firmware version: */ | ||
126 | line6_version_request_async(line6); | ||
127 | } | ||
128 | |||
129 | static void variax_startup3(struct usb_line6_variax *variax) | ||
130 | { | ||
131 | CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT); | ||
132 | |||
133 | /* delay startup procedure: */ | ||
134 | line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3, | ||
135 | variax_startup4, (unsigned long)variax); | ||
136 | } | ||
137 | |||
138 | static void variax_startup4(unsigned long data) | ||
139 | { | ||
140 | struct usb_line6_variax *variax = (struct usb_line6_variax *)data; | ||
141 | |||
142 | CHECK_STARTUP_PROGRESS(variax->startup_progress, | ||
143 | VARIAX_STARTUP_ACTIVATE); | ||
144 | |||
145 | /* activate device: */ | ||
146 | variax_activate_async(variax, 1); | ||
147 | line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4, | ||
148 | variax_startup5, (unsigned long)variax); | ||
149 | } | ||
150 | |||
151 | static void variax_startup5(unsigned long data) | ||
152 | { | ||
153 | struct usb_line6_variax *variax = (struct usb_line6_variax *)data; | ||
154 | |||
155 | CHECK_STARTUP_PROGRESS(variax->startup_progress, | ||
156 | VARIAX_STARTUP_WORKQUEUE); | ||
157 | |||
158 | /* schedule work for global work queue: */ | ||
159 | schedule_work(&variax->startup_work); | ||
160 | } | ||
161 | |||
162 | static void variax_startup6(struct work_struct *work) | ||
163 | { | ||
164 | struct usb_line6_variax *variax = | ||
165 | container_of(work, struct usb_line6_variax, startup_work); | ||
166 | |||
167 | CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP); | ||
168 | |||
169 | /* ALSA audio interface: */ | ||
170 | snd_card_register(variax->line6.card); | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | Process a completely received message. | ||
175 | */ | ||
176 | static void line6_variax_process_message(struct usb_line6 *line6) | ||
177 | { | ||
178 | struct usb_line6_variax *variax = (struct usb_line6_variax *) line6; | ||
179 | const unsigned char *buf = variax->line6.buffer_message; | ||
180 | |||
181 | switch (buf[0]) { | ||
182 | case LINE6_RESET: | ||
183 | dev_info(variax->line6.ifcdev, "VARIAX reset\n"); | ||
184 | break; | ||
185 | |||
186 | case LINE6_SYSEX_BEGIN: | ||
187 | if (memcmp(buf + 1, variax_init_version + 1, | ||
188 | sizeof(variax_init_version) - 1) == 0) { | ||
189 | variax_startup3(variax); | ||
190 | } else if (memcmp(buf + 1, variax_init_done + 1, | ||
191 | sizeof(variax_init_done) - 1) == 0) { | ||
192 | /* notify of complete initialization: */ | ||
193 | variax_startup4((unsigned long)variax); | ||
194 | } | ||
195 | break; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | Variax destructor. | ||
201 | */ | ||
202 | static void line6_variax_disconnect(struct usb_line6 *line6) | ||
203 | { | ||
204 | struct usb_line6_variax *variax = (struct usb_line6_variax *)line6; | ||
205 | |||
206 | del_timer(&variax->startup_timer1); | ||
207 | del_timer(&variax->startup_timer2); | ||
208 | cancel_work_sync(&variax->startup_work); | ||
209 | |||
210 | kfree(variax->buffer_activate); | ||
211 | } | ||
212 | |||
213 | /* | ||
214 | Try to init workbench device. | ||
215 | */ | ||
216 | static int variax_init(struct usb_line6 *line6, | ||
217 | const struct usb_device_id *id) | ||
218 | { | ||
219 | struct usb_line6_variax *variax = (struct usb_line6_variax *) line6; | ||
220 | int err; | ||
221 | |||
222 | line6->process_message = line6_variax_process_message; | ||
223 | line6->disconnect = line6_variax_disconnect; | ||
224 | |||
225 | init_timer(&variax->startup_timer1); | ||
226 | init_timer(&variax->startup_timer2); | ||
227 | INIT_WORK(&variax->startup_work, variax_startup6); | ||
228 | |||
229 | /* initialize USB buffers: */ | ||
230 | variax->buffer_activate = kmemdup(variax_activate, | ||
231 | sizeof(variax_activate), GFP_KERNEL); | ||
232 | |||
233 | if (variax->buffer_activate == NULL) | ||
234 | return -ENOMEM; | ||
235 | |||
236 | /* initialize MIDI subsystem: */ | ||
237 | err = line6_init_midi(&variax->line6); | ||
238 | if (err < 0) | ||
239 | return err; | ||
240 | |||
241 | /* initiate startup procedure: */ | ||
242 | variax_startup1(variax); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod) | ||
247 | #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n) | ||
248 | |||
249 | /* table of devices that work with this driver */ | ||
250 | static const struct usb_device_id variax_id_table[] = { | ||
251 | { LINE6_IF_NUM(0x4650, 1), .driver_info = LINE6_PODXTLIVE_VARIAX }, | ||
252 | { LINE6_DEVICE(0x534d), .driver_info = LINE6_VARIAX }, | ||
253 | {} | ||
254 | }; | ||
255 | |||
256 | MODULE_DEVICE_TABLE(usb, variax_id_table); | ||
257 | |||
258 | static const struct line6_properties variax_properties_table[] = { | ||
259 | [LINE6_PODXTLIVE_VARIAX] = { | ||
260 | .id = "PODxtLive", | ||
261 | .name = "PODxt Live", | ||
262 | .capabilities = LINE6_CAP_CONTROL, | ||
263 | .altsetting = 1, | ||
264 | .ep_ctrl_r = 0x86, | ||
265 | .ep_ctrl_w = 0x05, | ||
266 | .ep_audio_r = 0x82, | ||
267 | .ep_audio_w = 0x01, | ||
268 | }, | ||
269 | [LINE6_VARIAX] = { | ||
270 | .id = "Variax", | ||
271 | .name = "Variax Workbench", | ||
272 | .capabilities = LINE6_CAP_CONTROL, | ||
273 | .altsetting = 1, | ||
274 | .ep_ctrl_r = 0x82, | ||
275 | .ep_ctrl_w = 0x01, | ||
276 | /* no audio channel */ | ||
277 | } | ||
278 | }; | ||
279 | |||
280 | /* | ||
281 | Probe USB device. | ||
282 | */ | ||
283 | static int variax_probe(struct usb_interface *interface, | ||
284 | const struct usb_device_id *id) | ||
285 | { | ||
286 | return line6_probe(interface, id, "Line6-Variax", | ||
287 | &variax_properties_table[id->driver_info], | ||
288 | variax_init, sizeof(struct usb_line6_variax)); | ||
289 | } | ||
290 | |||
291 | static struct usb_driver variax_driver = { | ||
292 | .name = KBUILD_MODNAME, | ||
293 | .probe = variax_probe, | ||
294 | .disconnect = line6_disconnect, | ||
295 | #ifdef CONFIG_PM | ||
296 | .suspend = line6_suspend, | ||
297 | .resume = line6_resume, | ||
298 | .reset_resume = line6_resume, | ||
299 | #endif | ||
300 | .id_table = variax_id_table, | ||
301 | }; | ||
302 | |||
303 | module_usb_driver(variax_driver); | ||
304 | |||
305 | MODULE_DESCRIPTION("Vairax Workbench USB driver"); | ||
306 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 5bfb695547f8..417ebb11cf48 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c | |||
@@ -2292,14 +2292,13 @@ int snd_usbmidi_create(struct snd_card *card, | |||
2292 | umidi->iface = iface; | 2292 | umidi->iface = iface; |
2293 | umidi->quirk = quirk; | 2293 | umidi->quirk = quirk; |
2294 | umidi->usb_protocol_ops = &snd_usbmidi_standard_ops; | 2294 | umidi->usb_protocol_ops = &snd_usbmidi_standard_ops; |
2295 | init_timer(&umidi->error_timer); | ||
2296 | spin_lock_init(&umidi->disc_lock); | 2295 | spin_lock_init(&umidi->disc_lock); |
2297 | init_rwsem(&umidi->disc_rwsem); | 2296 | init_rwsem(&umidi->disc_rwsem); |
2298 | mutex_init(&umidi->mutex); | 2297 | mutex_init(&umidi->mutex); |
2299 | umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor), | 2298 | umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor), |
2300 | le16_to_cpu(umidi->dev->descriptor.idProduct)); | 2299 | le16_to_cpu(umidi->dev->descriptor.idProduct)); |
2301 | umidi->error_timer.function = snd_usbmidi_error_timer; | 2300 | setup_timer(&umidi->error_timer, snd_usbmidi_error_timer, |
2302 | umidi->error_timer.data = (unsigned long)umidi; | 2301 | (unsigned long)umidi); |
2303 | 2302 | ||
2304 | /* detect the endpoint(s) to use */ | 2303 | /* detect the endpoint(s) to use */ |
2305 | memset(endpoints, 0, sizeof(endpoints)); | 2304 | memset(endpoints, 0, sizeof(endpoints)); |
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 0d8aba5fe1a8..b4ef410e5a98 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -1464,6 +1464,14 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, | |||
1464 | subs->last_frame_number = usb_get_current_frame_number(subs->dev); | 1464 | subs->last_frame_number = usb_get_current_frame_number(subs->dev); |
1465 | subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ | 1465 | subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ |
1466 | 1466 | ||
1467 | if (subs->trigger_tstamp_pending_update) { | ||
1468 | /* this is the first actual URB submitted, | ||
1469 | * update trigger timestamp to reflect actual start time | ||
1470 | */ | ||
1471 | snd_pcm_gettime(runtime, &runtime->trigger_tstamp); | ||
1472 | subs->trigger_tstamp_pending_update = false; | ||
1473 | } | ||
1474 | |||
1467 | spin_unlock_irqrestore(&subs->lock, flags); | 1475 | spin_unlock_irqrestore(&subs->lock, flags); |
1468 | urb->transfer_buffer_length = bytes; | 1476 | urb->transfer_buffer_length = bytes; |
1469 | if (period_elapsed) | 1477 | if (period_elapsed) |
@@ -1550,6 +1558,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea | |||
1550 | 1558 | ||
1551 | switch (cmd) { | 1559 | switch (cmd) { |
1552 | case SNDRV_PCM_TRIGGER_START: | 1560 | case SNDRV_PCM_TRIGGER_START: |
1561 | subs->trigger_tstamp_pending_update = true; | ||
1553 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 1562 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
1554 | subs->data_endpoint->prepare_data_urb = prepare_playback_urb; | 1563 | subs->data_endpoint->prepare_data_urb = prepare_playback_urb; |
1555 | subs->data_endpoint->retire_data_urb = retire_playback_urb; | 1564 | subs->data_endpoint->retire_data_urb = retire_playback_urb; |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 0a598af9b38b..67d476548dcf 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -2486,6 +2486,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2486 | } | 2486 | } |
2487 | }, | 2487 | }, |
2488 | 2488 | ||
2489 | { | ||
2490 | /* Akai MPC Element */ | ||
2491 | USB_DEVICE(0x09e8, 0x0021), | ||
2492 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
2493 | .ifnum = QUIRK_ANY_INTERFACE, | ||
2494 | .type = QUIRK_COMPOSITE, | ||
2495 | .data = & (const struct snd_usb_audio_quirk[]) { | ||
2496 | { | ||
2497 | .ifnum = 0, | ||
2498 | .type = QUIRK_IGNORE_INTERFACE | ||
2499 | }, | ||
2500 | { | ||
2501 | .ifnum = 1, | ||
2502 | .type = QUIRK_MIDI_STANDARD_INTERFACE | ||
2503 | }, | ||
2504 | { | ||
2505 | .ifnum = -1 | ||
2506 | } | ||
2507 | } | ||
2508 | } | ||
2509 | }, | ||
2510 | |||
2489 | /* TerraTec devices */ | 2511 | /* TerraTec devices */ |
2490 | { | 2512 | { |
2491 | USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012), | 2513 | USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012), |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index a7398412310b..753a47de8459 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -1111,6 +1111,11 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, | |||
1111 | } | 1111 | } |
1112 | } | 1112 | } |
1113 | 1113 | ||
1114 | bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) | ||
1115 | { | ||
1116 | /* MS Lifecam HD-5000 doesn't support reading the sample rate. */ | ||
1117 | return chip->usb_id == USB_ID(0x045E, 0x076D); | ||
1118 | } | ||
1114 | 1119 | ||
1115 | /* Marantz/Denon USB DACs need a vendor cmd to switch | 1120 | /* Marantz/Denon USB DACs need a vendor cmd to switch |
1116 | * between PCM and native DSD mode | 1121 | * between PCM and native DSD mode |
@@ -1122,6 +1127,7 @@ int snd_usb_select_mode_quirk(struct snd_usb_substream *subs, | |||
1122 | int err; | 1127 | int err; |
1123 | 1128 | ||
1124 | switch (subs->stream->chip->usb_id) { | 1129 | switch (subs->stream->chip->usb_id) { |
1130 | case USB_ID(0x154e, 0x1003): /* Denon DA-300USB */ | ||
1125 | case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */ | 1131 | case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */ |
1126 | case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */ | 1132 | case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */ |
1127 | 1133 | ||
@@ -1201,6 +1207,7 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, | |||
1201 | (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) { | 1207 | (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) { |
1202 | 1208 | ||
1203 | switch (le16_to_cpu(dev->descriptor.idProduct)) { | 1209 | switch (le16_to_cpu(dev->descriptor.idProduct)) { |
1210 | case 0x1003: /* Denon DA300-USB */ | ||
1204 | case 0x3005: /* Marantz HD-DAC1 */ | 1211 | case 0x3005: /* Marantz HD-DAC1 */ |
1205 | case 0x3006: /* Marantz SA-14S1 */ | 1212 | case 0x3006: /* Marantz SA-14S1 */ |
1206 | mdelay(20); | 1213 | mdelay(20); |
@@ -1262,6 +1269,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, | |||
1262 | 1269 | ||
1263 | /* Denon/Marantz devices with USB DAC functionality */ | 1270 | /* Denon/Marantz devices with USB DAC functionality */ |
1264 | switch (chip->usb_id) { | 1271 | switch (chip->usb_id) { |
1272 | case USB_ID(0x154e, 0x1003): /* Denon DA300-USB */ | ||
1265 | case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */ | 1273 | case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */ |
1266 | case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */ | 1274 | case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */ |
1267 | if (fp->altsetting == 2) | 1275 | if (fp->altsetting == 2) |
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 1b862386577d..2cd71ed1201f 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h | |||
@@ -21,6 +21,8 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, | |||
21 | void snd_usb_set_format_quirk(struct snd_usb_substream *subs, | 21 | void snd_usb_set_format_quirk(struct snd_usb_substream *subs, |
22 | struct audioformat *fmt); | 22 | struct audioformat *fmt); |
23 | 23 | ||
24 | bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip); | ||
25 | |||
24 | int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, | 26 | int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, |
25 | struct audioformat *fp); | 27 | struct audioformat *fp); |
26 | 28 | ||
diff --git a/sound/usb/usx2y/usb_stream.h b/sound/usb/usx2y/usb_stream.h index 4dd74ab1e9cc..90369001eab6 100644 --- a/sound/usb/usx2y/usb_stream.h +++ b/sound/usb/usx2y/usb_stream.h | |||
@@ -1,76 +1,7 @@ | |||
1 | /* | 1 | #ifndef __USB_STREAM_H |
2 | * Copyright (C) 2007, 2008 Karsten Wiese <fzu@wemgehoertderstaat.de> | 2 | #define __USB_STREAM_H |
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
11 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software Foundation, | ||
16 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | 3 | ||
19 | #define USB_STREAM_INTERFACE_VERSION 2 | 4 | #include <uapi/sound/usb_stream.h> |
20 | |||
21 | #define SNDRV_USB_STREAM_IOCTL_SET_PARAMS \ | ||
22 | _IOW('H', 0x90, struct usb_stream_config) | ||
23 | |||
24 | struct usb_stream_packet { | ||
25 | unsigned offset; | ||
26 | unsigned length; | ||
27 | }; | ||
28 | |||
29 | |||
30 | struct usb_stream_config { | ||
31 | unsigned version; | ||
32 | unsigned sample_rate; | ||
33 | unsigned period_frames; | ||
34 | unsigned frame_size; | ||
35 | }; | ||
36 | |||
37 | struct usb_stream { | ||
38 | struct usb_stream_config cfg; | ||
39 | unsigned read_size; | ||
40 | unsigned write_size; | ||
41 | |||
42 | int period_size; | ||
43 | |||
44 | unsigned state; | ||
45 | |||
46 | int idle_insize; | ||
47 | int idle_outsize; | ||
48 | int sync_packet; | ||
49 | unsigned insize_done; | ||
50 | unsigned periods_done; | ||
51 | unsigned periods_polled; | ||
52 | |||
53 | struct usb_stream_packet outpacket[2]; | ||
54 | unsigned inpackets; | ||
55 | unsigned inpacket_head; | ||
56 | unsigned inpacket_split; | ||
57 | unsigned inpacket_split_at; | ||
58 | unsigned next_inpacket_split; | ||
59 | unsigned next_inpacket_split_at; | ||
60 | struct usb_stream_packet inpacket[0]; | ||
61 | }; | ||
62 | |||
63 | enum usb_stream_state { | ||
64 | usb_stream_invalid, | ||
65 | usb_stream_stopped, | ||
66 | usb_stream_sync0, | ||
67 | usb_stream_sync1, | ||
68 | usb_stream_ready, | ||
69 | usb_stream_running, | ||
70 | usb_stream_xrun, | ||
71 | }; | ||
72 | |||
73 | #if __KERNEL__ | ||
74 | 5 | ||
75 | #define USB_STREAM_NURBS 4 | 6 | #define USB_STREAM_NURBS 4 |
76 | #define USB_STREAM_URBDEPTH 4 | 7 | #define USB_STREAM_URBDEPTH 4 |
@@ -108,5 +39,4 @@ void usb_stream_free(struct usb_stream_kernel *); | |||
108 | int usb_stream_start(struct usb_stream_kernel *); | 39 | int usb_stream_start(struct usb_stream_kernel *); |
109 | void usb_stream_stop(struct usb_stream_kernel *); | 40 | void usb_stream_stop(struct usb_stream_kernel *); |
110 | 41 | ||
111 | 42 | #endif /* __USB_STREAM_H */ | |
112 | #endif | ||