diff options
Diffstat (limited to 'sound')
228 files changed, 22285 insertions, 2435 deletions
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index 270790d384e2..4cedc6950d72 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c | |||
@@ -997,45 +997,10 @@ static void onyx_exit_codec(struct aoa_codec *codec) | |||
997 | onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); | 997 | onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); |
998 | } | 998 | } |
999 | 999 | ||
1000 | static int onyx_create(struct i2c_adapter *adapter, | ||
1001 | struct device_node *node, | ||
1002 | int addr) | ||
1003 | { | ||
1004 | struct i2c_board_info info; | ||
1005 | struct i2c_client *client; | ||
1006 | |||
1007 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
1008 | strlcpy(info.type, "aoa_codec_onyx", I2C_NAME_SIZE); | ||
1009 | info.addr = addr; | ||
1010 | info.platform_data = node; | ||
1011 | client = i2c_new_device(adapter, &info); | ||
1012 | if (!client) | ||
1013 | return -ENODEV; | ||
1014 | |||
1015 | /* | ||
1016 | * We know the driver is already loaded, so the device should be | ||
1017 | * already bound. If not it means binding failed, which suggests | ||
1018 | * the device doesn't really exist and should be deleted. | ||
1019 | * Ideally this would be replaced by better checks _before_ | ||
1020 | * instantiating the device. | ||
1021 | */ | ||
1022 | if (!client->driver) { | ||
1023 | i2c_unregister_device(client); | ||
1024 | return -ENODEV; | ||
1025 | } | ||
1026 | |||
1027 | /* | ||
1028 | * Let i2c-core delete that device on driver removal. | ||
1029 | * This is safe because i2c-core holds the core_lock mutex for us. | ||
1030 | */ | ||
1031 | list_add_tail(&client->detected, &client->driver->clients); | ||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
1035 | static int onyx_i2c_probe(struct i2c_client *client, | 1000 | static int onyx_i2c_probe(struct i2c_client *client, |
1036 | const struct i2c_device_id *id) | 1001 | const struct i2c_device_id *id) |
1037 | { | 1002 | { |
1038 | struct device_node *node = client->dev.platform_data; | 1003 | struct device_node *node = client->dev.of_node; |
1039 | struct onyx *onyx; | 1004 | struct onyx *onyx; |
1040 | u8 dummy; | 1005 | u8 dummy; |
1041 | 1006 | ||
@@ -1071,40 +1036,6 @@ static int onyx_i2c_probe(struct i2c_client *client, | |||
1071 | return -ENODEV; | 1036 | return -ENODEV; |
1072 | } | 1037 | } |
1073 | 1038 | ||
1074 | static int onyx_i2c_attach(struct i2c_adapter *adapter) | ||
1075 | { | ||
1076 | struct device_node *busnode, *dev = NULL; | ||
1077 | struct pmac_i2c_bus *bus; | ||
1078 | |||
1079 | bus = pmac_i2c_adapter_to_bus(adapter); | ||
1080 | if (bus == NULL) | ||
1081 | return -ENODEV; | ||
1082 | busnode = pmac_i2c_get_bus_node(bus); | ||
1083 | |||
1084 | while ((dev = of_get_next_child(busnode, dev)) != NULL) { | ||
1085 | if (of_device_is_compatible(dev, "pcm3052")) { | ||
1086 | const u32 *addr; | ||
1087 | printk(KERN_DEBUG PFX "found pcm3052\n"); | ||
1088 | addr = of_get_property(dev, "reg", NULL); | ||
1089 | if (!addr) | ||
1090 | return -ENODEV; | ||
1091 | return onyx_create(adapter, dev, (*addr)>>1); | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | /* if that didn't work, try desperate mode for older | ||
1096 | * machines that have stuff missing from the device tree */ | ||
1097 | |||
1098 | if (!of_device_is_compatible(busnode, "k2-i2c")) | ||
1099 | return -ENODEV; | ||
1100 | |||
1101 | printk(KERN_DEBUG PFX "found k2-i2c, checking if onyx chip is on it\n"); | ||
1102 | /* probe both possible addresses for the onyx chip */ | ||
1103 | if (onyx_create(adapter, NULL, 0x46) == 0) | ||
1104 | return 0; | ||
1105 | return onyx_create(adapter, NULL, 0x47); | ||
1106 | } | ||
1107 | |||
1108 | static int onyx_i2c_remove(struct i2c_client *client) | 1039 | static int onyx_i2c_remove(struct i2c_client *client) |
1109 | { | 1040 | { |
1110 | struct onyx *onyx = i2c_get_clientdata(client); | 1041 | struct onyx *onyx = i2c_get_clientdata(client); |
@@ -1117,16 +1048,16 @@ static int onyx_i2c_remove(struct i2c_client *client) | |||
1117 | } | 1048 | } |
1118 | 1049 | ||
1119 | static const struct i2c_device_id onyx_i2c_id[] = { | 1050 | static const struct i2c_device_id onyx_i2c_id[] = { |
1120 | { "aoa_codec_onyx", 0 }, | 1051 | { "MAC,pcm3052", 0 }, |
1121 | { } | 1052 | { } |
1122 | }; | 1053 | }; |
1054 | MODULE_DEVICE_TABLE(i2c,onyx_i2c_id); | ||
1123 | 1055 | ||
1124 | static struct i2c_driver onyx_driver = { | 1056 | static struct i2c_driver onyx_driver = { |
1125 | .driver = { | 1057 | .driver = { |
1126 | .name = "aoa_codec_onyx", | 1058 | .name = "aoa_codec_onyx", |
1127 | .owner = THIS_MODULE, | 1059 | .owner = THIS_MODULE, |
1128 | }, | 1060 | }, |
1129 | .attach_adapter = onyx_i2c_attach, | ||
1130 | .probe = onyx_i2c_probe, | 1061 | .probe = onyx_i2c_probe, |
1131 | .remove = onyx_i2c_remove, | 1062 | .remove = onyx_i2c_remove, |
1132 | .id_table = onyx_i2c_id, | 1063 | .id_table = onyx_i2c_id, |
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index 8e63d1f35ce1..c491ae0f749c 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c | |||
@@ -883,43 +883,10 @@ static void tas_exit_codec(struct aoa_codec *codec) | |||
883 | } | 883 | } |
884 | 884 | ||
885 | 885 | ||
886 | static int tas_create(struct i2c_adapter *adapter, | ||
887 | struct device_node *node, | ||
888 | int addr) | ||
889 | { | ||
890 | struct i2c_board_info info; | ||
891 | struct i2c_client *client; | ||
892 | |||
893 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
894 | strlcpy(info.type, "aoa_codec_tas", I2C_NAME_SIZE); | ||
895 | info.addr = addr; | ||
896 | info.platform_data = node; | ||
897 | |||
898 | client = i2c_new_device(adapter, &info); | ||
899 | if (!client) | ||
900 | return -ENODEV; | ||
901 | /* | ||
902 | * We know the driver is already loaded, so the device should be | ||
903 | * already bound. If not it means binding failed, and then there | ||
904 | * is no point in keeping the device instantiated. | ||
905 | */ | ||
906 | if (!client->driver) { | ||
907 | i2c_unregister_device(client); | ||
908 | return -ENODEV; | ||
909 | } | ||
910 | |||
911 | /* | ||
912 | * Let i2c-core delete that device on driver removal. | ||
913 | * This is safe because i2c-core holds the core_lock mutex for us. | ||
914 | */ | ||
915 | list_add_tail(&client->detected, &client->driver->clients); | ||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | static int tas_i2c_probe(struct i2c_client *client, | 886 | static int tas_i2c_probe(struct i2c_client *client, |
920 | const struct i2c_device_id *id) | 887 | const struct i2c_device_id *id) |
921 | { | 888 | { |
922 | struct device_node *node = client->dev.platform_data; | 889 | struct device_node *node = client->dev.of_node; |
923 | struct tas *tas; | 890 | struct tas *tas; |
924 | 891 | ||
925 | tas = kzalloc(sizeof(struct tas), GFP_KERNEL); | 892 | tas = kzalloc(sizeof(struct tas), GFP_KERNEL); |
@@ -953,47 +920,6 @@ static int tas_i2c_probe(struct i2c_client *client, | |||
953 | return -EINVAL; | 920 | return -EINVAL; |
954 | } | 921 | } |
955 | 922 | ||
956 | static int tas_i2c_attach(struct i2c_adapter *adapter) | ||
957 | { | ||
958 | struct device_node *busnode, *dev = NULL; | ||
959 | struct pmac_i2c_bus *bus; | ||
960 | |||
961 | bus = pmac_i2c_adapter_to_bus(adapter); | ||
962 | if (bus == NULL) | ||
963 | return -ENODEV; | ||
964 | busnode = pmac_i2c_get_bus_node(bus); | ||
965 | |||
966 | while ((dev = of_get_next_child(busnode, dev)) != NULL) { | ||
967 | if (of_device_is_compatible(dev, "tas3004")) { | ||
968 | const u32 *addr; | ||
969 | printk(KERN_DEBUG PFX "found tas3004\n"); | ||
970 | addr = of_get_property(dev, "reg", NULL); | ||
971 | if (!addr) | ||
972 | continue; | ||
973 | return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f); | ||
974 | } | ||
975 | /* older machines have no 'codec' node with a 'compatible' | ||
976 | * property that says 'tas3004', they just have a 'deq' | ||
977 | * node without any such property... */ | ||
978 | if (strcmp(dev->name, "deq") == 0) { | ||
979 | const u32 *_addr; | ||
980 | u32 addr; | ||
981 | printk(KERN_DEBUG PFX "found 'deq' node\n"); | ||
982 | _addr = of_get_property(dev, "i2c-address", NULL); | ||
983 | if (!_addr) | ||
984 | continue; | ||
985 | addr = ((*_addr) >> 1) & 0x7f; | ||
986 | /* now, if the address doesn't match any of the two | ||
987 | * that a tas3004 can have, we cannot handle this. | ||
988 | * I doubt it ever happens but hey. */ | ||
989 | if (addr != 0x34 && addr != 0x35) | ||
990 | continue; | ||
991 | return tas_create(adapter, dev, addr); | ||
992 | } | ||
993 | } | ||
994 | return -ENODEV; | ||
995 | } | ||
996 | |||
997 | static int tas_i2c_remove(struct i2c_client *client) | 923 | static int tas_i2c_remove(struct i2c_client *client) |
998 | { | 924 | { |
999 | struct tas *tas = i2c_get_clientdata(client); | 925 | struct tas *tas = i2c_get_clientdata(client); |
@@ -1011,16 +937,16 @@ static int tas_i2c_remove(struct i2c_client *client) | |||
1011 | } | 937 | } |
1012 | 938 | ||
1013 | static const struct i2c_device_id tas_i2c_id[] = { | 939 | static const struct i2c_device_id tas_i2c_id[] = { |
1014 | { "aoa_codec_tas", 0 }, | 940 | { "MAC,tas3004", 0 }, |
1015 | { } | 941 | { } |
1016 | }; | 942 | }; |
943 | MODULE_DEVICE_TABLE(i2c,tas_i2c_id); | ||
1017 | 944 | ||
1018 | static struct i2c_driver tas_driver = { | 945 | static struct i2c_driver tas_driver = { |
1019 | .driver = { | 946 | .driver = { |
1020 | .name = "aoa_codec_tas", | 947 | .name = "aoa_codec_tas", |
1021 | .owner = THIS_MODULE, | 948 | .owner = THIS_MODULE, |
1022 | }, | 949 | }, |
1023 | .attach_adapter = tas_i2c_attach, | ||
1024 | .probe = tas_i2c_probe, | 950 | .probe = tas_i2c_probe, |
1025 | .remove = tas_i2c_remove, | 951 | .remove = tas_i2c_remove, |
1026 | .id_table = tas_i2c_id, | 952 | .id_table = tas_i2c_id, |
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index afef72c4f0d3..0d7b25e81643 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c | |||
@@ -108,7 +108,7 @@ static struct pxa2xx_pcm_client pxa2xx_ac97_pcm_client = { | |||
108 | 108 | ||
109 | #ifdef CONFIG_PM | 109 | #ifdef CONFIG_PM |
110 | 110 | ||
111 | static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state) | 111 | static int pxa2xx_ac97_do_suspend(struct snd_card *card) |
112 | { | 112 | { |
113 | pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; | 113 | pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; |
114 | 114 | ||
@@ -144,7 +144,7 @@ static int pxa2xx_ac97_suspend(struct device *dev) | |||
144 | int ret = 0; | 144 | int ret = 0; |
145 | 145 | ||
146 | if (card) | 146 | if (card) |
147 | ret = pxa2xx_ac97_do_suspend(card, PMSG_SUSPEND); | 147 | ret = pxa2xx_ac97_do_suspend(card); |
148 | 148 | ||
149 | return ret; | 149 | return ret; |
150 | } | 150 | } |
@@ -160,10 +160,7 @@ static int pxa2xx_ac97_resume(struct device *dev) | |||
160 | return ret; | 160 | return ret; |
161 | } | 161 | } |
162 | 162 | ||
163 | static const struct dev_pm_ops pxa2xx_ac97_pm_ops = { | 163 | static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, pxa2xx_ac97_suspend, pxa2xx_ac97_resume); |
164 | .suspend = pxa2xx_ac97_suspend, | ||
165 | .resume = pxa2xx_ac97_resume, | ||
166 | }; | ||
167 | #endif | 164 | #endif |
168 | 165 | ||
169 | static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) | 166 | static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) |
diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c index f7c2bb08055d..eb4ceb71123e 100644 --- a/sound/atmel/abdac.c +++ b/sound/atmel/abdac.c | |||
@@ -535,9 +535,9 @@ out_put_pclk: | |||
535 | } | 535 | } |
536 | 536 | ||
537 | #ifdef CONFIG_PM | 537 | #ifdef CONFIG_PM |
538 | static int atmel_abdac_suspend(struct platform_device *pdev, pm_message_t msg) | 538 | static int atmel_abdac_suspend(struct device *pdev) |
539 | { | 539 | { |
540 | struct snd_card *card = platform_get_drvdata(pdev); | 540 | struct snd_card *card = dev_get_drvdata(pdev); |
541 | struct atmel_abdac *dac = card->private_data; | 541 | struct atmel_abdac *dac = card->private_data; |
542 | 542 | ||
543 | dw_dma_cyclic_stop(dac->dma.chan); | 543 | dw_dma_cyclic_stop(dac->dma.chan); |
@@ -547,9 +547,9 @@ static int atmel_abdac_suspend(struct platform_device *pdev, pm_message_t msg) | |||
547 | return 0; | 547 | return 0; |
548 | } | 548 | } |
549 | 549 | ||
550 | static int atmel_abdac_resume(struct platform_device *pdev) | 550 | static int atmel_abdac_resume(struct device *pdev) |
551 | { | 551 | { |
552 | struct snd_card *card = platform_get_drvdata(pdev); | 552 | struct snd_card *card = dev_get_drvdata(pdev); |
553 | struct atmel_abdac *dac = card->private_data; | 553 | struct atmel_abdac *dac = card->private_data; |
554 | 554 | ||
555 | clk_enable(dac->pclk); | 555 | clk_enable(dac->pclk); |
@@ -559,9 +559,11 @@ static int atmel_abdac_resume(struct platform_device *pdev) | |||
559 | 559 | ||
560 | return 0; | 560 | return 0; |
561 | } | 561 | } |
562 | |||
563 | static SIMPLE_DEV_PM_OPS(atmel_abdac_pm, atmel_abdac_suspend, atmel_abdac_resume); | ||
564 | #define ATMEL_ABDAC_PM_OPS &atmel_abdac_pm | ||
562 | #else | 565 | #else |
563 | #define atmel_abdac_suspend NULL | 566 | #define ATMEL_ABDAC_PM_OPS NULL |
564 | #define atmel_abdac_resume NULL | ||
565 | #endif | 567 | #endif |
566 | 568 | ||
567 | static int __devexit atmel_abdac_remove(struct platform_device *pdev) | 569 | static int __devexit atmel_abdac_remove(struct platform_device *pdev) |
@@ -589,9 +591,9 @@ static struct platform_driver atmel_abdac_driver = { | |||
589 | .remove = __devexit_p(atmel_abdac_remove), | 591 | .remove = __devexit_p(atmel_abdac_remove), |
590 | .driver = { | 592 | .driver = { |
591 | .name = "atmel_abdac", | 593 | .name = "atmel_abdac", |
594 | .owner = THIS_MODULE, | ||
595 | .pm = ATMEL_ABDAC_PM_OPS, | ||
592 | }, | 596 | }, |
593 | .suspend = atmel_abdac_suspend, | ||
594 | .resume = atmel_abdac_resume, | ||
595 | }; | 597 | }; |
596 | 598 | ||
597 | static int __init atmel_abdac_init(void) | 599 | static int __init atmel_abdac_init(void) |
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index f5ded640b395..bf47025bdf45 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c | |||
@@ -1135,9 +1135,9 @@ err_snd_card_new: | |||
1135 | } | 1135 | } |
1136 | 1136 | ||
1137 | #ifdef CONFIG_PM | 1137 | #ifdef CONFIG_PM |
1138 | static int atmel_ac97c_suspend(struct platform_device *pdev, pm_message_t msg) | 1138 | static int atmel_ac97c_suspend(struct device *pdev) |
1139 | { | 1139 | { |
1140 | struct snd_card *card = platform_get_drvdata(pdev); | 1140 | struct snd_card *card = dev_get_drvdata(pdev); |
1141 | struct atmel_ac97c *chip = card->private_data; | 1141 | struct atmel_ac97c *chip = card->private_data; |
1142 | 1142 | ||
1143 | if (cpu_is_at32ap7000()) { | 1143 | if (cpu_is_at32ap7000()) { |
@@ -1151,9 +1151,9 @@ static int atmel_ac97c_suspend(struct platform_device *pdev, pm_message_t msg) | |||
1151 | return 0; | 1151 | return 0; |
1152 | } | 1152 | } |
1153 | 1153 | ||
1154 | static int atmel_ac97c_resume(struct platform_device *pdev) | 1154 | static int atmel_ac97c_resume(struct device *pdev) |
1155 | { | 1155 | { |
1156 | struct snd_card *card = platform_get_drvdata(pdev); | 1156 | struct snd_card *card = dev_get_drvdata(pdev); |
1157 | struct atmel_ac97c *chip = card->private_data; | 1157 | struct atmel_ac97c *chip = card->private_data; |
1158 | 1158 | ||
1159 | clk_enable(chip->pclk); | 1159 | clk_enable(chip->pclk); |
@@ -1165,9 +1165,11 @@ static int atmel_ac97c_resume(struct platform_device *pdev) | |||
1165 | } | 1165 | } |
1166 | return 0; | 1166 | return 0; |
1167 | } | 1167 | } |
1168 | |||
1169 | static SIMPLE_DEV_PM_OPS(atmel_ac97c_pm, atmel_ac97c_suspend, atmel_ac97c_resume); | ||
1170 | #define ATMEL_AC97C_PM_OPS &atmel_ac97c_pm | ||
1168 | #else | 1171 | #else |
1169 | #define atmel_ac97c_suspend NULL | 1172 | #define ATMEL_AC97C_PM_OPS NULL |
1170 | #define atmel_ac97c_resume NULL | ||
1171 | #endif | 1173 | #endif |
1172 | 1174 | ||
1173 | static int __devexit atmel_ac97c_remove(struct platform_device *pdev) | 1175 | static int __devexit atmel_ac97c_remove(struct platform_device *pdev) |
@@ -1210,9 +1212,9 @@ static struct platform_driver atmel_ac97c_driver = { | |||
1210 | .remove = __devexit_p(atmel_ac97c_remove), | 1212 | .remove = __devexit_p(atmel_ac97c_remove), |
1211 | .driver = { | 1213 | .driver = { |
1212 | .name = "atmel_ac97c", | 1214 | .name = "atmel_ac97c", |
1215 | .owner = THIS_MODULE, | ||
1216 | .pm = ATMEL_AC97C_PM_OPS, | ||
1213 | }, | 1217 | }, |
1214 | .suspend = atmel_ac97c_suspend, | ||
1215 | .resume = atmel_ac97c_resume, | ||
1216 | }; | 1218 | }; |
1217 | 1219 | ||
1218 | static int __init atmel_ac97c_init(void) | 1220 | static int __init atmel_ac97c_init(void) |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 8f312fa6c282..7ae671923393 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -1250,10 +1250,10 @@ static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params, | |||
1250 | int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, | 1250 | int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, |
1251 | unsigned int cond, | 1251 | unsigned int cond, |
1252 | snd_pcm_hw_param_t var, | 1252 | snd_pcm_hw_param_t var, |
1253 | struct snd_pcm_hw_constraint_list *l) | 1253 | const struct snd_pcm_hw_constraint_list *l) |
1254 | { | 1254 | { |
1255 | return snd_pcm_hw_rule_add(runtime, cond, var, | 1255 | return snd_pcm_hw_rule_add(runtime, cond, var, |
1256 | snd_pcm_hw_rule_list, l, | 1256 | snd_pcm_hw_rule_list, (void *)l, |
1257 | var, -1); | 1257 | var, -1); |
1258 | } | 1258 | } |
1259 | 1259 | ||
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 9c9eff9afbac..d4fc1bfbe457 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c | |||
@@ -488,3 +488,21 @@ unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate) | |||
488 | return SNDRV_PCM_RATE_KNOT; | 488 | return SNDRV_PCM_RATE_KNOT; |
489 | } | 489 | } |
490 | EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit); | 490 | EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit); |
491 | |||
492 | /** | ||
493 | * snd_pcm_rate_bit_to_rate - converts SNDRV_PCM_RATE_xxx bit to sample rate | ||
494 | * @rate_bit: the rate bit to convert | ||
495 | * | ||
496 | * Returns the sample rate that corresponds to the given SNDRV_PCM_RATE_xxx flag | ||
497 | * or 0 for an unknown rate bit | ||
498 | */ | ||
499 | unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit) | ||
500 | { | ||
501 | unsigned int i; | ||
502 | |||
503 | for (i = 0; i < snd_pcm_known_rates.count; i++) | ||
504 | if ((1u << i) == rate_bit) | ||
505 | return snd_pcm_known_rates.list[i]; | ||
506 | return 0; | ||
507 | } | ||
508 | EXPORT_SYMBOL(snd_pcm_rate_bit_to_rate); | ||
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 8b5c36f4d303..1128b35b2b05 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c | |||
@@ -1177,10 +1177,9 @@ static int __devexit loopback_remove(struct platform_device *devptr) | |||
1177 | } | 1177 | } |
1178 | 1178 | ||
1179 | #ifdef CONFIG_PM | 1179 | #ifdef CONFIG_PM |
1180 | static int loopback_suspend(struct platform_device *pdev, | 1180 | static int loopback_suspend(struct device *pdev) |
1181 | pm_message_t state) | ||
1182 | { | 1181 | { |
1183 | struct snd_card *card = platform_get_drvdata(pdev); | 1182 | struct snd_card *card = dev_get_drvdata(pdev); |
1184 | struct loopback *loopback = card->private_data; | 1183 | struct loopback *loopback = card->private_data; |
1185 | 1184 | ||
1186 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 1185 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
@@ -1190,13 +1189,18 @@ static int loopback_suspend(struct platform_device *pdev, | |||
1190 | return 0; | 1189 | return 0; |
1191 | } | 1190 | } |
1192 | 1191 | ||
1193 | static int loopback_resume(struct platform_device *pdev) | 1192 | static int loopback_resume(struct device *pdev) |
1194 | { | 1193 | { |
1195 | struct snd_card *card = platform_get_drvdata(pdev); | 1194 | struct snd_card *card = dev_get_drvdata(pdev); |
1196 | 1195 | ||
1197 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1196 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1198 | return 0; | 1197 | return 0; |
1199 | } | 1198 | } |
1199 | |||
1200 | static SIMPLE_DEV_PM_OPS(loopback_pm, loopback_suspend, loopback_resume); | ||
1201 | #define LOOPBACK_PM_OPS &loopback_pm | ||
1202 | #else | ||
1203 | #define LOOPBACK_PM_OPS NULL | ||
1200 | #endif | 1204 | #endif |
1201 | 1205 | ||
1202 | #define SND_LOOPBACK_DRIVER "snd_aloop" | 1206 | #define SND_LOOPBACK_DRIVER "snd_aloop" |
@@ -1204,12 +1208,10 @@ static int loopback_resume(struct platform_device *pdev) | |||
1204 | static struct platform_driver loopback_driver = { | 1208 | static struct platform_driver loopback_driver = { |
1205 | .probe = loopback_probe, | 1209 | .probe = loopback_probe, |
1206 | .remove = __devexit_p(loopback_remove), | 1210 | .remove = __devexit_p(loopback_remove), |
1207 | #ifdef CONFIG_PM | ||
1208 | .suspend = loopback_suspend, | ||
1209 | .resume = loopback_resume, | ||
1210 | #endif | ||
1211 | .driver = { | 1211 | .driver = { |
1212 | .name = SND_LOOPBACK_DRIVER | 1212 | .name = SND_LOOPBACK_DRIVER, |
1213 | .owner = THIS_MODULE, | ||
1214 | .pm = LOOPBACK_PM_OPS, | ||
1213 | }, | 1215 | }, |
1214 | }; | 1216 | }; |
1215 | 1217 | ||
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index ad9434fd6370..f7d3bfc6bca8 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
@@ -1065,9 +1065,9 @@ static int __devexit snd_dummy_remove(struct platform_device *devptr) | |||
1065 | } | 1065 | } |
1066 | 1066 | ||
1067 | #ifdef CONFIG_PM | 1067 | #ifdef CONFIG_PM |
1068 | static int snd_dummy_suspend(struct platform_device *pdev, pm_message_t state) | 1068 | static int snd_dummy_suspend(struct device *pdev) |
1069 | { | 1069 | { |
1070 | struct snd_card *card = platform_get_drvdata(pdev); | 1070 | struct snd_card *card = dev_get_drvdata(pdev); |
1071 | struct snd_dummy *dummy = card->private_data; | 1071 | struct snd_dummy *dummy = card->private_data; |
1072 | 1072 | ||
1073 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 1073 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
@@ -1075,13 +1075,18 @@ static int snd_dummy_suspend(struct platform_device *pdev, pm_message_t state) | |||
1075 | return 0; | 1075 | return 0; |
1076 | } | 1076 | } |
1077 | 1077 | ||
1078 | static int snd_dummy_resume(struct platform_device *pdev) | 1078 | static int snd_dummy_resume(struct device *pdev) |
1079 | { | 1079 | { |
1080 | struct snd_card *card = platform_get_drvdata(pdev); | 1080 | struct snd_card *card = dev_get_drvdata(pdev); |
1081 | 1081 | ||
1082 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1082 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1083 | return 0; | 1083 | return 0; |
1084 | } | 1084 | } |
1085 | |||
1086 | static SIMPLE_DEV_PM_OPS(snd_dummy_pm, snd_dummy_suspend, snd_dummy_resume); | ||
1087 | #define SND_DUMMY_PM_OPS &snd_dummy_pm | ||
1088 | #else | ||
1089 | #define SND_DUMMY_PM_OPS NULL | ||
1085 | #endif | 1090 | #endif |
1086 | 1091 | ||
1087 | #define SND_DUMMY_DRIVER "snd_dummy" | 1092 | #define SND_DUMMY_DRIVER "snd_dummy" |
@@ -1089,12 +1094,10 @@ static int snd_dummy_resume(struct platform_device *pdev) | |||
1089 | static struct platform_driver snd_dummy_driver = { | 1094 | static struct platform_driver snd_dummy_driver = { |
1090 | .probe = snd_dummy_probe, | 1095 | .probe = snd_dummy_probe, |
1091 | .remove = __devexit_p(snd_dummy_remove), | 1096 | .remove = __devexit_p(snd_dummy_remove), |
1092 | #ifdef CONFIG_PM | ||
1093 | .suspend = snd_dummy_suspend, | ||
1094 | .resume = snd_dummy_resume, | ||
1095 | #endif | ||
1096 | .driver = { | 1097 | .driver = { |
1097 | .name = SND_DUMMY_DRIVER | 1098 | .name = SND_DUMMY_DRIVER, |
1099 | .owner = THIS_MODULE, | ||
1100 | .pm = SND_DUMMY_PM_OPS, | ||
1098 | }, | 1101 | }, |
1099 | }; | 1102 | }; |
1100 | 1103 | ||
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 86f5fbc2da72..bc03a2046c9c 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c | |||
@@ -139,7 +139,8 @@ static struct platform_driver snd_mpu401_driver = { | |||
139 | .probe = snd_mpu401_probe, | 139 | .probe = snd_mpu401_probe, |
140 | .remove = __devexit_p(snd_mpu401_remove), | 140 | .remove = __devexit_p(snd_mpu401_remove), |
141 | .driver = { | 141 | .driver = { |
142 | .name = SND_MPU401_DRIVER | 142 | .name = SND_MPU401_DRIVER, |
143 | .owner = THIS_MODULE, | ||
143 | }, | 144 | }, |
144 | }; | 145 | }; |
145 | 146 | ||
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 76930793fb69..cad73af3860c 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c | |||
@@ -759,7 +759,8 @@ static struct platform_driver snd_mtpav_driver = { | |||
759 | .probe = snd_mtpav_probe, | 759 | .probe = snd_mtpav_probe, |
760 | .remove = __devexit_p(snd_mtpav_remove), | 760 | .remove = __devexit_p(snd_mtpav_remove), |
761 | .driver = { | 761 | .driver = { |
762 | .name = SND_MTPAV_DRIVER | 762 | .name = SND_MTPAV_DRIVER, |
763 | .owner = THIS_MODULE, | ||
763 | }, | 764 | }, |
764 | }; | 765 | }; |
765 | 766 | ||
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index 621e60e2029f..2d5514b0a290 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c | |||
@@ -1040,7 +1040,8 @@ static struct platform_driver snd_mts64_driver = { | |||
1040 | .probe = snd_mts64_probe, | 1040 | .probe = snd_mts64_probe, |
1041 | .remove = __devexit_p(snd_mts64_remove), | 1041 | .remove = __devexit_p(snd_mts64_remove), |
1042 | .driver = { | 1042 | .driver = { |
1043 | .name = PLATFORM_DRIVER | 1043 | .name = PLATFORM_DRIVER, |
1044 | .owner = THIS_MODULE, | ||
1044 | } | 1045 | } |
1045 | }; | 1046 | }; |
1046 | 1047 | ||
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index 99704e6a2e26..6ca59fc6dcb9 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c | |||
@@ -200,15 +200,18 @@ static void pcsp_stop_beep(struct snd_pcsp *chip) | |||
200 | } | 200 | } |
201 | 201 | ||
202 | #ifdef CONFIG_PM | 202 | #ifdef CONFIG_PM |
203 | static int pcsp_suspend(struct platform_device *dev, pm_message_t state) | 203 | static int pcsp_suspend(struct device *dev) |
204 | { | 204 | { |
205 | struct snd_pcsp *chip = platform_get_drvdata(dev); | 205 | struct snd_pcsp *chip = dev_get_drvdata(dev); |
206 | pcsp_stop_beep(chip); | 206 | pcsp_stop_beep(chip); |
207 | snd_pcm_suspend_all(chip->pcm); | 207 | snd_pcm_suspend_all(chip->pcm); |
208 | return 0; | 208 | return 0; |
209 | } | 209 | } |
210 | |||
211 | static SIMPLE_DEV_PM_OPS(pcsp_pm, pcsp_suspend, NULL); | ||
212 | #define PCSP_PM_OPS &pcsp_pm | ||
210 | #else | 213 | #else |
211 | #define pcsp_suspend NULL | 214 | #define PCSP_PM_OPS NULL |
212 | #endif /* CONFIG_PM */ | 215 | #endif /* CONFIG_PM */ |
213 | 216 | ||
214 | static void pcsp_shutdown(struct platform_device *dev) | 217 | static void pcsp_shutdown(struct platform_device *dev) |
@@ -221,10 +224,10 @@ static struct platform_driver pcsp_platform_driver = { | |||
221 | .driver = { | 224 | .driver = { |
222 | .name = "pcspkr", | 225 | .name = "pcspkr", |
223 | .owner = THIS_MODULE, | 226 | .owner = THIS_MODULE, |
227 | .pm = PCSP_PM_OPS, | ||
224 | }, | 228 | }, |
225 | .probe = pcsp_probe, | 229 | .probe = pcsp_probe, |
226 | .remove = __devexit_p(pcsp_remove), | 230 | .remove = __devexit_p(pcsp_remove), |
227 | .suspend = pcsp_suspend, | ||
228 | .shutdown = pcsp_shutdown, | 231 | .shutdown = pcsp_shutdown, |
229 | }; | 232 | }; |
230 | 233 | ||
diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index 3e32bd3d95d9..8364855ed14f 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c | |||
@@ -829,7 +829,8 @@ static struct platform_driver snd_portman_driver = { | |||
829 | .probe = snd_portman_probe, | 829 | .probe = snd_portman_probe, |
830 | .remove = __devexit_p(snd_portman_remove), | 830 | .remove = __devexit_p(snd_portman_remove), |
831 | .driver = { | 831 | .driver = { |
832 | .name = PLATFORM_DRIVER | 832 | .name = PLATFORM_DRIVER, |
833 | .owner = THIS_MODULE, | ||
833 | } | 834 | } |
834 | }; | 835 | }; |
835 | 836 | ||
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index b2d0e8e49bed..86700671d1ac 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c | |||
@@ -995,7 +995,8 @@ static struct platform_driver snd_serial_driver = { | |||
995 | .probe = snd_serial_probe, | 995 | .probe = snd_serial_probe, |
996 | .remove = __devexit_p( snd_serial_remove), | 996 | .remove = __devexit_p( snd_serial_remove), |
997 | .driver = { | 997 | .driver = { |
998 | .name = SND_SERIAL_DRIVER | 998 | .name = SND_SERIAL_DRIVER, |
999 | .owner = THIS_MODULE, | ||
999 | }, | 1000 | }, |
1000 | }; | 1001 | }; |
1001 | 1002 | ||
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index 9d97478a18b3..d7d514df9058 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c | |||
@@ -142,7 +142,8 @@ static struct platform_driver snd_virmidi_driver = { | |||
142 | .probe = snd_virmidi_probe, | 142 | .probe = snd_virmidi_probe, |
143 | .remove = __devexit_p(snd_virmidi_remove), | 143 | .remove = __devexit_p(snd_virmidi_remove), |
144 | .driver = { | 144 | .driver = { |
145 | .name = SND_VIRMIDI_DRIVER | 145 | .name = SND_VIRMIDI_DRIVER, |
146 | .owner = THIS_MODULE, | ||
146 | }, | 147 | }, |
147 | }; | 148 | }; |
148 | 149 | ||
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index b8e515999bc2..de5055a3b0d0 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c | |||
@@ -725,7 +725,7 @@ EXPORT_SYMBOL(snd_vx_dsp_load); | |||
725 | /* | 725 | /* |
726 | * suspend | 726 | * suspend |
727 | */ | 727 | */ |
728 | int snd_vx_suspend(struct vx_core *chip, pm_message_t state) | 728 | int snd_vx_suspend(struct vx_core *chip) |
729 | { | 729 | { |
730 | unsigned int i; | 730 | unsigned int i; |
731 | 731 | ||
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index d7ccf28bd66a..f8fbe22515c9 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
@@ -135,10 +135,9 @@ struct snd_opti9xx { | |||
135 | unsigned long mc_base_size; | 135 | unsigned long mc_base_size; |
136 | #ifdef OPTi93X | 136 | #ifdef OPTi93X |
137 | unsigned long mc_indir_index; | 137 | unsigned long mc_indir_index; |
138 | unsigned long mc_indir_size; | ||
139 | struct resource *res_mc_indir; | 138 | struct resource *res_mc_indir; |
140 | struct snd_wss *codec; | ||
141 | #endif /* OPTi93X */ | 139 | #endif /* OPTi93X */ |
140 | struct snd_wss *codec; | ||
142 | unsigned long pwd_reg; | 141 | unsigned long pwd_reg; |
143 | 142 | ||
144 | spinlock_t lock; | 143 | spinlock_t lock; |
@@ -245,10 +244,8 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, | |||
245 | case OPTi9XX_HW_82C931: | 244 | case OPTi9XX_HW_82C931: |
246 | case OPTi9XX_HW_82C933: | 245 | case OPTi9XX_HW_82C933: |
247 | chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d; | 246 | chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d; |
248 | if (!chip->mc_indir_index) { | 247 | if (!chip->mc_indir_index) |
249 | chip->mc_indir_index = 0xe0e; | 248 | chip->mc_indir_index = 0xe0e; |
250 | chip->mc_indir_size = 2; | ||
251 | } | ||
252 | chip->password = 0xe4; | 249 | chip->password = 0xe4; |
253 | chip->pwd_reg = 0; | 250 | chip->pwd_reg = 0; |
254 | break; | 251 | break; |
@@ -351,7 +348,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, | |||
351 | (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask))) | 348 | (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask))) |
352 | 349 | ||
353 | 350 | ||
354 | static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, | 351 | static int snd_opti9xx_configure(struct snd_opti9xx *chip, |
355 | long port, | 352 | long port, |
356 | int irq, int dma1, int dma2, | 353 | int irq, int dma1, int dma2, |
357 | long mpu_port, int mpu_irq) | 354 | long mpu_port, int mpu_irq) |
@@ -403,7 +400,9 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, | |||
403 | 400 | ||
404 | #else /* OPTi93X */ | 401 | #else /* OPTi93X */ |
405 | case OPTi9XX_HW_82C931: | 402 | case OPTi9XX_HW_82C931: |
406 | case OPTi9XX_HW_82C933: | 403 | /* disable 3D sound (set GPIO1 as output, low) */ |
404 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(20), 0x04, 0x0c); | ||
405 | case OPTi9XX_HW_82C933: /* FALL THROUGH */ | ||
407 | /* | 406 | /* |
408 | * The BTC 1817DW has QS1000 wavetable which is connected | 407 | * The BTC 1817DW has QS1000 wavetable which is connected |
409 | * to the serial digital input of the OPTI931. | 408 | * to the serial digital input of the OPTI931. |
@@ -696,8 +695,7 @@ static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip) | |||
696 | if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1))) | 695 | if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1))) |
697 | return 0; | 696 | return 0; |
698 | #else /* OPTi93X */ | 697 | #else /* OPTi93X */ |
699 | chip->res_mc_indir = request_region(chip->mc_indir_index, | 698 | chip->res_mc_indir = request_region(chip->mc_indir_index, 2, |
700 | chip->mc_indir_size, | ||
701 | "OPTi93x MC"); | 699 | "OPTi93x MC"); |
702 | if (chip->res_mc_indir == NULL) | 700 | if (chip->res_mc_indir == NULL) |
703 | return -EBUSY; | 701 | return -EBUSY; |
@@ -770,8 +768,9 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, | |||
770 | #ifdef OPTi93X | 768 | #ifdef OPTi93X |
771 | port = pnp_port_start(pdev, 0) - 4; | 769 | port = pnp_port_start(pdev, 0) - 4; |
772 | fm_port = pnp_port_start(pdev, 1) + 8; | 770 | fm_port = pnp_port_start(pdev, 1) + 8; |
773 | chip->mc_indir_index = pnp_port_start(pdev, 3) + 2; | 771 | /* adjust mc_indir_index - some cards report it at 0xe?d, |
774 | chip->mc_indir_size = pnp_port_len(pdev, 3) - 2; | 772 | other at 0xe?c but it really is always at 0xe?e */ |
773 | chip->mc_indir_index = (pnp_port_start(pdev, 3) & ~0xf) | 0xe; | ||
775 | #else | 774 | #else |
776 | devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); | 775 | devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); |
777 | if (devmc == NULL) | 776 | if (devmc == NULL) |
@@ -871,9 +870,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
871 | &codec); | 870 | &codec); |
872 | if (error < 0) | 871 | if (error < 0) |
873 | return error; | 872 | return error; |
874 | #ifdef OPTi93X | ||
875 | chip->codec = codec; | 873 | chip->codec = codec; |
876 | #endif | ||
877 | error = snd_wss_pcm(codec, 0, &pcm); | 874 | error = snd_wss_pcm(codec, 0, &pcm); |
878 | if (error < 0) | 875 | if (error < 0) |
879 | return error; | 876 | return error; |
@@ -1054,11 +1051,55 @@ static int __devexit snd_opti9xx_isa_remove(struct device *devptr, | |||
1054 | return 0; | 1051 | return 0; |
1055 | } | 1052 | } |
1056 | 1053 | ||
1054 | #ifdef CONFIG_PM | ||
1055 | static int snd_opti9xx_suspend(struct snd_card *card) | ||
1056 | { | ||
1057 | struct snd_opti9xx *chip = card->private_data; | ||
1058 | |||
1059 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | ||
1060 | chip->codec->suspend(chip->codec); | ||
1061 | return 0; | ||
1062 | } | ||
1063 | |||
1064 | static int snd_opti9xx_resume(struct snd_card *card) | ||
1065 | { | ||
1066 | struct snd_opti9xx *chip = card->private_data; | ||
1067 | int error, xdma2; | ||
1068 | #if defined(CS4231) || defined(OPTi93X) | ||
1069 | xdma2 = dma2; | ||
1070 | #else | ||
1071 | xdma2 = -1; | ||
1072 | #endif | ||
1073 | |||
1074 | error = snd_opti9xx_configure(chip, port, irq, dma1, xdma2, | ||
1075 | mpu_port, mpu_irq); | ||
1076 | if (error) | ||
1077 | return error; | ||
1078 | chip->codec->resume(chip->codec); | ||
1079 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
1080 | return 0; | ||
1081 | } | ||
1082 | |||
1083 | static int snd_opti9xx_isa_suspend(struct device *dev, unsigned int n, | ||
1084 | pm_message_t state) | ||
1085 | { | ||
1086 | return snd_opti9xx_suspend(dev_get_drvdata(dev)); | ||
1087 | } | ||
1088 | |||
1089 | static int snd_opti9xx_isa_resume(struct device *dev, unsigned int n) | ||
1090 | { | ||
1091 | return snd_opti9xx_resume(dev_get_drvdata(dev)); | ||
1092 | } | ||
1093 | #endif | ||
1094 | |||
1057 | static struct isa_driver snd_opti9xx_driver = { | 1095 | static struct isa_driver snd_opti9xx_driver = { |
1058 | .match = snd_opti9xx_isa_match, | 1096 | .match = snd_opti9xx_isa_match, |
1059 | .probe = snd_opti9xx_isa_probe, | 1097 | .probe = snd_opti9xx_isa_probe, |
1060 | .remove = __devexit_p(snd_opti9xx_isa_remove), | 1098 | .remove = __devexit_p(snd_opti9xx_isa_remove), |
1061 | /* FIXME: suspend/resume */ | 1099 | #ifdef CONFIG_PM |
1100 | .suspend = snd_opti9xx_isa_suspend, | ||
1101 | .resume = snd_opti9xx_isa_resume, | ||
1102 | #endif | ||
1062 | .driver = { | 1103 | .driver = { |
1063 | .name = DEV_NAME | 1104 | .name = DEV_NAME |
1064 | }, | 1105 | }, |
@@ -1124,12 +1165,29 @@ static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard) | |||
1124 | snd_opti9xx_pnp_is_probed = 0; | 1165 | snd_opti9xx_pnp_is_probed = 0; |
1125 | } | 1166 | } |
1126 | 1167 | ||
1168 | #ifdef CONFIG_PM | ||
1169 | static int snd_opti9xx_pnp_suspend(struct pnp_card_link *pcard, | ||
1170 | pm_message_t state) | ||
1171 | { | ||
1172 | return snd_opti9xx_suspend(pnp_get_card_drvdata(pcard)); | ||
1173 | } | ||
1174 | |||
1175 | static int snd_opti9xx_pnp_resume(struct pnp_card_link *pcard) | ||
1176 | { | ||
1177 | return snd_opti9xx_resume(pnp_get_card_drvdata(pcard)); | ||
1178 | } | ||
1179 | #endif | ||
1180 | |||
1127 | static struct pnp_card_driver opti9xx_pnpc_driver = { | 1181 | static struct pnp_card_driver opti9xx_pnpc_driver = { |
1128 | .flags = PNP_DRIVER_RES_DISABLE, | 1182 | .flags = PNP_DRIVER_RES_DISABLE, |
1129 | .name = "opti9xx", | 1183 | .name = "opti9xx", |
1130 | .id_table = snd_opti9xx_pnpids, | 1184 | .id_table = snd_opti9xx_pnpids, |
1131 | .probe = snd_opti9xx_pnp_probe, | 1185 | .probe = snd_opti9xx_pnp_probe, |
1132 | .remove = __devexit_p(snd_opti9xx_pnp_remove), | 1186 | .remove = __devexit_p(snd_opti9xx_pnp_remove), |
1187 | #ifdef CONFIG_PM | ||
1188 | .suspend = snd_opti9xx_pnp_suspend, | ||
1189 | .resume = snd_opti9xx_pnp_resume, | ||
1190 | #endif | ||
1133 | }; | 1191 | }; |
1134 | #endif | 1192 | #endif |
1135 | 1193 | ||
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 49c8a0c2442c..360b08b03e1d 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c | |||
@@ -1456,7 +1456,6 @@ static struct snd_pcm_hardware snd_wss_playback = | |||
1456 | { | 1456 | { |
1457 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 1457 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
1458 | SNDRV_PCM_INFO_MMAP_VALID | | 1458 | SNDRV_PCM_INFO_MMAP_VALID | |
1459 | SNDRV_PCM_INFO_RESUME | | ||
1460 | SNDRV_PCM_INFO_SYNC_START), | 1459 | SNDRV_PCM_INFO_SYNC_START), |
1461 | .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM | | 1460 | .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM | |
1462 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE), | 1461 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE), |
@@ -1657,6 +1656,10 @@ static void snd_wss_resume(struct snd_wss *chip) | |||
1657 | break; | 1656 | break; |
1658 | } | 1657 | } |
1659 | } | 1658 | } |
1659 | /* Yamaha needs this to resume properly */ | ||
1660 | if (chip->hardware == WSS_HW_OPL3SA2) | ||
1661 | snd_wss_out(chip, CS4231_PLAYBK_FORMAT, | ||
1662 | chip->image[CS4231_PLAYBK_FORMAT]); | ||
1660 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1663 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
1661 | #if 1 | 1664 | #if 1 |
1662 | snd_wss_mce_down(chip); | 1665 | snd_wss_mce_down(chip); |
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index 09d46484bc1a..7d8803a00b79 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c | |||
@@ -69,7 +69,6 @@ | |||
69 | #include <linux/sound.h> | 69 | #include <linux/sound.h> |
70 | #include <linux/slab.h> | 70 | #include <linux/slab.h> |
71 | #include <linux/soundcard.h> | 71 | #include <linux/soundcard.h> |
72 | #include <linux/ac97_codec.h> | ||
73 | #include <linux/pci.h> | 72 | #include <linux/pci.h> |
74 | #include <linux/bitops.h> | 73 | #include <linux/bitops.h> |
75 | #include <linux/interrupt.h> | 74 | #include <linux/interrupt.h> |
@@ -199,6 +198,22 @@ static const char invalid_magic[] = | |||
199 | } \ | 198 | } \ |
200 | }) | 199 | }) |
201 | 200 | ||
201 | /* AC97 registers */ | ||
202 | #define AC97_MASTER_VOL_STEREO 0x0002 /* Line Out */ | ||
203 | #define AC97_PCBEEP_VOL 0x000a /* none */ | ||
204 | #define AC97_PHONE_VOL 0x000c /* TAD Input (mono) */ | ||
205 | #define AC97_MIC_VOL 0x000e /* MIC Input (mono) */ | ||
206 | #define AC97_LINEIN_VOL 0x0010 /* Line Input (stereo) */ | ||
207 | #define AC97_CD_VOL 0x0012 /* CD Input (stereo) */ | ||
208 | #define AC97_AUX_VOL 0x0016 /* Aux Input (stereo) */ | ||
209 | #define AC97_PCMOUT_VOL 0x0018 /* Wave Output (stereo) */ | ||
210 | #define AC97_RECORD_SELECT 0x001a /* */ | ||
211 | #define AC97_RECORD_GAIN 0x001c | ||
212 | #define AC97_GENERAL_PURPOSE 0x0020 | ||
213 | #define AC97_3D_CONTROL 0x0022 | ||
214 | #define AC97_POWER_CONTROL 0x0026 | ||
215 | #define AC97_VENDOR_ID1 0x007c | ||
216 | |||
202 | struct list_head cs4297a_devs = { &cs4297a_devs, &cs4297a_devs }; | 217 | struct list_head cs4297a_devs = { &cs4297a_devs, &cs4297a_devs }; |
203 | 218 | ||
204 | typedef struct serdma_descr_s { | 219 | typedef struct serdma_descr_s { |
diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c index 643f1113b1d8..7e814a5c3677 100644 --- a/sound/oss/vwsnd.c +++ b/sound/oss/vwsnd.c | |||
@@ -438,7 +438,7 @@ static __inline__ void li_writeb(lithium_t *lith, int off, unsigned char val) | |||
438 | * | 438 | * |
439 | * Observe that (mask & -mask) is (1 << low_set_bit_of(mask)). | 439 | * Observe that (mask & -mask) is (1 << low_set_bit_of(mask)). |
440 | * As long as mask is constant, we trust the compiler will change the | 440 | * As long as mask is constant, we trust the compiler will change the |
441 | * multipy and divide into shifts. | 441 | * multiply and divide into shifts. |
442 | */ | 442 | */ |
443 | 443 | ||
444 | #define SHIFT_FIELD(val, mask) (((val) * ((mask) & -(mask))) & (mask)) | 444 | #define SHIFT_FIELD(val, mask) (((val) * ((mask) & -(mask))) & (mask)) |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 9dfc27bf6cc6..ee895f3c8605 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -1884,9 +1884,10 @@ static int __devinit snd_ali_mixer(struct snd_ali * codec) | |||
1884 | } | 1884 | } |
1885 | 1885 | ||
1886 | #ifdef CONFIG_PM | 1886 | #ifdef CONFIG_PM |
1887 | static int ali_suspend(struct pci_dev *pci, pm_message_t state) | 1887 | static int ali_suspend(struct device *dev) |
1888 | { | 1888 | { |
1889 | struct snd_card *card = pci_get_drvdata(pci); | 1889 | struct pci_dev *pci = to_pci_dev(dev); |
1890 | struct snd_card *card = dev_get_drvdata(dev); | ||
1890 | struct snd_ali *chip = card->private_data; | 1891 | struct snd_ali *chip = card->private_data; |
1891 | struct snd_ali_image *im; | 1892 | struct snd_ali_image *im; |
1892 | int i, j; | 1893 | int i, j; |
@@ -1929,13 +1930,14 @@ static int ali_suspend(struct pci_dev *pci, pm_message_t state) | |||
1929 | 1930 | ||
1930 | pci_disable_device(pci); | 1931 | pci_disable_device(pci); |
1931 | pci_save_state(pci); | 1932 | pci_save_state(pci); |
1932 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 1933 | pci_set_power_state(pci, PCI_D3hot); |
1933 | return 0; | 1934 | return 0; |
1934 | } | 1935 | } |
1935 | 1936 | ||
1936 | static int ali_resume(struct pci_dev *pci) | 1937 | static int ali_resume(struct device *dev) |
1937 | { | 1938 | { |
1938 | struct snd_card *card = pci_get_drvdata(pci); | 1939 | struct pci_dev *pci = to_pci_dev(dev); |
1940 | struct snd_card *card = dev_get_drvdata(dev); | ||
1939 | struct snd_ali *chip = card->private_data; | 1941 | struct snd_ali *chip = card->private_data; |
1940 | struct snd_ali_image *im; | 1942 | struct snd_ali_image *im; |
1941 | int i, j; | 1943 | int i, j; |
@@ -1982,6 +1984,11 @@ static int ali_resume(struct pci_dev *pci) | |||
1982 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1984 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1983 | return 0; | 1985 | return 0; |
1984 | } | 1986 | } |
1987 | |||
1988 | static SIMPLE_DEV_PM_OPS(ali_pm, ali_suspend, ali_resume); | ||
1989 | #define ALI_PM_OPS &ali_pm | ||
1990 | #else | ||
1991 | #define ALI_PM_OPS NULL | ||
1985 | #endif /* CONFIG_PM */ | 1992 | #endif /* CONFIG_PM */ |
1986 | 1993 | ||
1987 | static int snd_ali_free(struct snd_ali * codec) | 1994 | static int snd_ali_free(struct snd_ali * codec) |
@@ -2299,10 +2306,9 @@ static struct pci_driver ali5451_driver = { | |||
2299 | .id_table = snd_ali_ids, | 2306 | .id_table = snd_ali_ids, |
2300 | .probe = snd_ali_probe, | 2307 | .probe = snd_ali_probe, |
2301 | .remove = __devexit_p(snd_ali_remove), | 2308 | .remove = __devexit_p(snd_ali_remove), |
2302 | #ifdef CONFIG_PM | 2309 | .driver = { |
2303 | .suspend = ali_suspend, | 2310 | .pm = ALI_PM_OPS, |
2304 | .resume = ali_resume, | 2311 | }, |
2305 | #endif | ||
2306 | }; | 2312 | }; |
2307 | 2313 | ||
2308 | module_pci_driver(ali5451_driver); | 2314 | module_pci_driver(ali5451_driver); |
diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 59d65388faf5..68c4469c6d19 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c | |||
@@ -766,9 +766,10 @@ static int __devinit snd_als300_create(struct snd_card *card, | |||
766 | } | 766 | } |
767 | 767 | ||
768 | #ifdef CONFIG_PM | 768 | #ifdef CONFIG_PM |
769 | static int snd_als300_suspend(struct pci_dev *pci, pm_message_t state) | 769 | static int snd_als300_suspend(struct device *dev) |
770 | { | 770 | { |
771 | struct snd_card *card = pci_get_drvdata(pci); | 771 | struct pci_dev *pci = to_pci_dev(dev); |
772 | struct snd_card *card = dev_get_drvdata(dev); | ||
772 | struct snd_als300 *chip = card->private_data; | 773 | struct snd_als300 *chip = card->private_data; |
773 | 774 | ||
774 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 775 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
@@ -777,13 +778,14 @@ static int snd_als300_suspend(struct pci_dev *pci, pm_message_t state) | |||
777 | 778 | ||
778 | pci_disable_device(pci); | 779 | pci_disable_device(pci); |
779 | pci_save_state(pci); | 780 | pci_save_state(pci); |
780 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 781 | pci_set_power_state(pci, PCI_D3hot); |
781 | return 0; | 782 | return 0; |
782 | } | 783 | } |
783 | 784 | ||
784 | static int snd_als300_resume(struct pci_dev *pci) | 785 | static int snd_als300_resume(struct device *dev) |
785 | { | 786 | { |
786 | struct snd_card *card = pci_get_drvdata(pci); | 787 | struct pci_dev *pci = to_pci_dev(dev); |
788 | struct snd_card *card = dev_get_drvdata(dev); | ||
787 | struct snd_als300 *chip = card->private_data; | 789 | struct snd_als300 *chip = card->private_data; |
788 | 790 | ||
789 | pci_set_power_state(pci, PCI_D0); | 791 | pci_set_power_state(pci, PCI_D0); |
@@ -802,6 +804,11 @@ static int snd_als300_resume(struct pci_dev *pci) | |||
802 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 804 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
803 | return 0; | 805 | return 0; |
804 | } | 806 | } |
807 | |||
808 | static SIMPLE_DEV_PM_OPS(snd_als300_pm, snd_als300_suspend, snd_als300_resume); | ||
809 | #define SND_ALS300_PM_OPS &snd_als300_pm | ||
810 | #else | ||
811 | #define SND_ALS300_PM_OPS NULL | ||
805 | #endif | 812 | #endif |
806 | 813 | ||
807 | static int __devinit snd_als300_probe(struct pci_dev *pci, | 814 | static int __devinit snd_als300_probe(struct pci_dev *pci, |
@@ -857,10 +864,9 @@ static struct pci_driver als300_driver = { | |||
857 | .id_table = snd_als300_ids, | 864 | .id_table = snd_als300_ids, |
858 | .probe = snd_als300_probe, | 865 | .probe = snd_als300_probe, |
859 | .remove = __devexit_p(snd_als300_remove), | 866 | .remove = __devexit_p(snd_als300_remove), |
860 | #ifdef CONFIG_PM | 867 | .driver = { |
861 | .suspend = snd_als300_suspend, | 868 | .pm = SND_ALS300_PM_OPS, |
862 | .resume = snd_als300_resume, | 869 | }, |
863 | #endif | ||
864 | }; | 870 | }; |
865 | 871 | ||
866 | module_pci_driver(als300_driver); | 872 | module_pci_driver(als300_driver); |
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 7d7f2598c748..0eeca49c5754 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
@@ -988,9 +988,10 @@ static void __devexit snd_card_als4000_remove(struct pci_dev *pci) | |||
988 | } | 988 | } |
989 | 989 | ||
990 | #ifdef CONFIG_PM | 990 | #ifdef CONFIG_PM |
991 | static int snd_als4000_suspend(struct pci_dev *pci, pm_message_t state) | 991 | static int snd_als4000_suspend(struct device *dev) |
992 | { | 992 | { |
993 | struct snd_card *card = pci_get_drvdata(pci); | 993 | struct pci_dev *pci = to_pci_dev(dev); |
994 | struct snd_card *card = dev_get_drvdata(dev); | ||
994 | struct snd_card_als4000 *acard = card->private_data; | 995 | struct snd_card_als4000 *acard = card->private_data; |
995 | struct snd_sb *chip = acard->chip; | 996 | struct snd_sb *chip = acard->chip; |
996 | 997 | ||
@@ -1001,13 +1002,14 @@ static int snd_als4000_suspend(struct pci_dev *pci, pm_message_t state) | |||
1001 | 1002 | ||
1002 | pci_disable_device(pci); | 1003 | pci_disable_device(pci); |
1003 | pci_save_state(pci); | 1004 | pci_save_state(pci); |
1004 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 1005 | pci_set_power_state(pci, PCI_D3hot); |
1005 | return 0; | 1006 | return 0; |
1006 | } | 1007 | } |
1007 | 1008 | ||
1008 | static int snd_als4000_resume(struct pci_dev *pci) | 1009 | static int snd_als4000_resume(struct device *dev) |
1009 | { | 1010 | { |
1010 | struct snd_card *card = pci_get_drvdata(pci); | 1011 | struct pci_dev *pci = to_pci_dev(dev); |
1012 | struct snd_card *card = dev_get_drvdata(dev); | ||
1011 | struct snd_card_als4000 *acard = card->private_data; | 1013 | struct snd_card_als4000 *acard = card->private_data; |
1012 | struct snd_sb *chip = acard->chip; | 1014 | struct snd_sb *chip = acard->chip; |
1013 | 1015 | ||
@@ -1033,18 +1035,21 @@ static int snd_als4000_resume(struct pci_dev *pci) | |||
1033 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1035 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1034 | return 0; | 1036 | return 0; |
1035 | } | 1037 | } |
1036 | #endif /* CONFIG_PM */ | ||
1037 | 1038 | ||
1039 | static SIMPLE_DEV_PM_OPS(snd_als4000_pm, snd_als4000_suspend, snd_als4000_resume); | ||
1040 | #define SND_ALS4000_PM_OPS &snd_als4000_pm | ||
1041 | #else | ||
1042 | #define SND_ALS4000_PM_OPS NULL | ||
1043 | #endif /* CONFIG_PM */ | ||
1038 | 1044 | ||
1039 | static struct pci_driver als4000_driver = { | 1045 | static struct pci_driver als4000_driver = { |
1040 | .name = KBUILD_MODNAME, | 1046 | .name = KBUILD_MODNAME, |
1041 | .id_table = snd_als4000_ids, | 1047 | .id_table = snd_als4000_ids, |
1042 | .probe = snd_card_als4000_probe, | 1048 | .probe = snd_card_als4000_probe, |
1043 | .remove = __devexit_p(snd_card_als4000_remove), | 1049 | .remove = __devexit_p(snd_card_als4000_remove), |
1044 | #ifdef CONFIG_PM | 1050 | .driver = { |
1045 | .suspend = snd_als4000_suspend, | 1051 | .pm = SND_ALS4000_PM_OPS, |
1046 | .resume = snd_als4000_resume, | 1052 | }, |
1047 | #endif | ||
1048 | }; | 1053 | }; |
1049 | 1054 | ||
1050 | module_pci_driver(als4000_driver); | 1055 | module_pci_driver(als4000_driver); |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 156a94f8a123..31020d2a868b 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -1462,9 +1462,10 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp *chip, int clock, | |||
1462 | /* | 1462 | /* |
1463 | * power management | 1463 | * power management |
1464 | */ | 1464 | */ |
1465 | static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) | 1465 | static int snd_atiixp_suspend(struct device *dev) |
1466 | { | 1466 | { |
1467 | struct snd_card *card = pci_get_drvdata(pci); | 1467 | struct pci_dev *pci = to_pci_dev(dev); |
1468 | struct snd_card *card = dev_get_drvdata(dev); | ||
1468 | struct atiixp *chip = card->private_data; | 1469 | struct atiixp *chip = card->private_data; |
1469 | int i; | 1470 | int i; |
1470 | 1471 | ||
@@ -1484,13 +1485,14 @@ static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) | |||
1484 | 1485 | ||
1485 | pci_disable_device(pci); | 1486 | pci_disable_device(pci); |
1486 | pci_save_state(pci); | 1487 | pci_save_state(pci); |
1487 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 1488 | pci_set_power_state(pci, PCI_D3hot); |
1488 | return 0; | 1489 | return 0; |
1489 | } | 1490 | } |
1490 | 1491 | ||
1491 | static int snd_atiixp_resume(struct pci_dev *pci) | 1492 | static int snd_atiixp_resume(struct device *dev) |
1492 | { | 1493 | { |
1493 | struct snd_card *card = pci_get_drvdata(pci); | 1494 | struct pci_dev *pci = to_pci_dev(dev); |
1495 | struct snd_card *card = dev_get_drvdata(dev); | ||
1494 | struct atiixp *chip = card->private_data; | 1496 | struct atiixp *chip = card->private_data; |
1495 | int i; | 1497 | int i; |
1496 | 1498 | ||
@@ -1526,6 +1528,11 @@ static int snd_atiixp_resume(struct pci_dev *pci) | |||
1526 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1528 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1527 | return 0; | 1529 | return 0; |
1528 | } | 1530 | } |
1531 | |||
1532 | static SIMPLE_DEV_PM_OPS(snd_atiixp_pm, snd_atiixp_suspend, snd_atiixp_resume); | ||
1533 | #define SND_ATIIXP_PM_OPS &snd_atiixp_pm | ||
1534 | #else | ||
1535 | #define SND_ATIIXP_PM_OPS NULL | ||
1529 | #endif /* CONFIG_PM */ | 1536 | #endif /* CONFIG_PM */ |
1530 | 1537 | ||
1531 | 1538 | ||
@@ -1705,10 +1712,9 @@ static struct pci_driver atiixp_driver = { | |||
1705 | .id_table = snd_atiixp_ids, | 1712 | .id_table = snd_atiixp_ids, |
1706 | .probe = snd_atiixp_probe, | 1713 | .probe = snd_atiixp_probe, |
1707 | .remove = __devexit_p(snd_atiixp_remove), | 1714 | .remove = __devexit_p(snd_atiixp_remove), |
1708 | #ifdef CONFIG_PM | 1715 | .driver = { |
1709 | .suspend = snd_atiixp_suspend, | 1716 | .pm = SND_ATIIXP_PM_OPS, |
1710 | .resume = snd_atiixp_resume, | 1717 | }, |
1711 | #endif | ||
1712 | }; | 1718 | }; |
1713 | 1719 | ||
1714 | module_pci_driver(atiixp_driver); | 1720 | module_pci_driver(atiixp_driver); |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 30a4fd96ce73..79e204ec623f 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -1117,9 +1117,10 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock) | |||
1117 | /* | 1117 | /* |
1118 | * power management | 1118 | * power management |
1119 | */ | 1119 | */ |
1120 | static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) | 1120 | static int snd_atiixp_suspend(struct device *dev) |
1121 | { | 1121 | { |
1122 | struct snd_card *card = pci_get_drvdata(pci); | 1122 | struct pci_dev *pci = to_pci_dev(dev); |
1123 | struct snd_card *card = dev_get_drvdata(dev); | ||
1123 | struct atiixp_modem *chip = card->private_data; | 1124 | struct atiixp_modem *chip = card->private_data; |
1124 | int i; | 1125 | int i; |
1125 | 1126 | ||
@@ -1133,13 +1134,14 @@ static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) | |||
1133 | 1134 | ||
1134 | pci_disable_device(pci); | 1135 | pci_disable_device(pci); |
1135 | pci_save_state(pci); | 1136 | pci_save_state(pci); |
1136 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 1137 | pci_set_power_state(pci, PCI_D3hot); |
1137 | return 0; | 1138 | return 0; |
1138 | } | 1139 | } |
1139 | 1140 | ||
1140 | static int snd_atiixp_resume(struct pci_dev *pci) | 1141 | static int snd_atiixp_resume(struct device *dev) |
1141 | { | 1142 | { |
1142 | struct snd_card *card = pci_get_drvdata(pci); | 1143 | struct pci_dev *pci = to_pci_dev(dev); |
1144 | struct snd_card *card = dev_get_drvdata(dev); | ||
1143 | struct atiixp_modem *chip = card->private_data; | 1145 | struct atiixp_modem *chip = card->private_data; |
1144 | int i; | 1146 | int i; |
1145 | 1147 | ||
@@ -1162,8 +1164,12 @@ static int snd_atiixp_resume(struct pci_dev *pci) | |||
1162 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1164 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1163 | return 0; | 1165 | return 0; |
1164 | } | 1166 | } |
1165 | #endif /* CONFIG_PM */ | ||
1166 | 1167 | ||
1168 | static SIMPLE_DEV_PM_OPS(snd_atiixp_pm, snd_atiixp_suspend, snd_atiixp_resume); | ||
1169 | #define SND_ATIIXP_PM_OPS &snd_atiixp_pm | ||
1170 | #else | ||
1171 | #define SND_ATIIXP_PM_OPS NULL | ||
1172 | #endif /* CONFIG_PM */ | ||
1167 | 1173 | ||
1168 | #ifdef CONFIG_PROC_FS | 1174 | #ifdef CONFIG_PROC_FS |
1169 | /* | 1175 | /* |
@@ -1336,10 +1342,9 @@ static struct pci_driver atiixp_modem_driver = { | |||
1336 | .id_table = snd_atiixp_ids, | 1342 | .id_table = snd_atiixp_ids, |
1337 | .probe = snd_atiixp_probe, | 1343 | .probe = snd_atiixp_probe, |
1338 | .remove = __devexit_p(snd_atiixp_remove), | 1344 | .remove = __devexit_p(snd_atiixp_remove), |
1339 | #ifdef CONFIG_PM | 1345 | .driver = { |
1340 | .suspend = snd_atiixp_suspend, | 1346 | .pm = SND_ATIIXP_PM_OPS, |
1341 | .resume = snd_atiixp_resume, | 1347 | }, |
1342 | #endif | ||
1343 | }; | 1348 | }; |
1344 | 1349 | ||
1345 | module_pci_driver(atiixp_modem_driver); | 1350 | module_pci_driver(atiixp_modem_driver); |
diff --git a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c index 557c782ae4fc..fa13efbebdaf 100644 --- a/sound/pci/au88x0/au88x0_mixer.c +++ b/sound/pci/au88x0/au88x0_mixer.c | |||
@@ -10,6 +10,15 @@ | |||
10 | #include <sound/core.h> | 10 | #include <sound/core.h> |
11 | #include "au88x0.h" | 11 | #include "au88x0.h" |
12 | 12 | ||
13 | static int remove_ctl(struct snd_card *card, const char *name) | ||
14 | { | ||
15 | struct snd_ctl_elem_id id; | ||
16 | memset(&id, 0, sizeof(id)); | ||
17 | strcpy(id.name, name); | ||
18 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
19 | return snd_ctl_remove_id(card, &id); | ||
20 | } | ||
21 | |||
13 | static int __devinit snd_vortex_mixer(vortex_t * vortex) | 22 | static int __devinit snd_vortex_mixer(vortex_t * vortex) |
14 | { | 23 | { |
15 | struct snd_ac97_bus *pbus; | 24 | struct snd_ac97_bus *pbus; |
@@ -28,5 +37,7 @@ static int __devinit snd_vortex_mixer(vortex_t * vortex) | |||
28 | ac97.scaps = AC97_SCAP_NO_SPDIF; | 37 | ac97.scaps = AC97_SCAP_NO_SPDIF; |
29 | err = snd_ac97_mixer(pbus, &ac97, &vortex->codec); | 38 | err = snd_ac97_mixer(pbus, &ac97, &vortex->codec); |
30 | vortex->isquad = ((vortex->codec == NULL) ? 0 : (vortex->codec->ext_id&0x80)); | 39 | vortex->isquad = ((vortex->codec == NULL) ? 0 : (vortex->codec->ext_id&0x80)); |
40 | remove_ctl(vortex->card, "Master Mono Playback Volume"); | ||
41 | remove_ctl(vortex->card, "Master Mono Playback Switch"); | ||
31 | return err; | 42 | return err; |
32 | } | 43 | } |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index f0b4d7493af5..4dddd871548b 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -2794,9 +2794,10 @@ snd_azf3328_resume_ac97(const struct snd_azf3328 *chip) | |||
2794 | } | 2794 | } |
2795 | 2795 | ||
2796 | static int | 2796 | static int |
2797 | snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) | 2797 | snd_azf3328_suspend(struct device *dev) |
2798 | { | 2798 | { |
2799 | struct snd_card *card = pci_get_drvdata(pci); | 2799 | struct pci_dev *pci = to_pci_dev(dev); |
2800 | struct snd_card *card = dev_get_drvdata(dev); | ||
2800 | struct snd_azf3328 *chip = card->private_data; | 2801 | struct snd_azf3328 *chip = card->private_data; |
2801 | u16 *saved_regs_ctrl_u16; | 2802 | u16 *saved_regs_ctrl_u16; |
2802 | 2803 | ||
@@ -2824,14 +2825,15 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) | |||
2824 | 2825 | ||
2825 | pci_disable_device(pci); | 2826 | pci_disable_device(pci); |
2826 | pci_save_state(pci); | 2827 | pci_save_state(pci); |
2827 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 2828 | pci_set_power_state(pci, PCI_D3hot); |
2828 | return 0; | 2829 | return 0; |
2829 | } | 2830 | } |
2830 | 2831 | ||
2831 | static int | 2832 | static int |
2832 | snd_azf3328_resume(struct pci_dev *pci) | 2833 | snd_azf3328_resume(struct device *dev) |
2833 | { | 2834 | { |
2834 | struct snd_card *card = pci_get_drvdata(pci); | 2835 | struct pci_dev *pci = to_pci_dev(dev); |
2836 | struct snd_card *card = dev_get_drvdata(dev); | ||
2835 | const struct snd_azf3328 *chip = card->private_data; | 2837 | const struct snd_azf3328 *chip = card->private_data; |
2836 | 2838 | ||
2837 | pci_set_power_state(pci, PCI_D0); | 2839 | pci_set_power_state(pci, PCI_D0); |
@@ -2859,18 +2861,21 @@ snd_azf3328_resume(struct pci_dev *pci) | |||
2859 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2861 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
2860 | return 0; | 2862 | return 0; |
2861 | } | 2863 | } |
2862 | #endif /* CONFIG_PM */ | ||
2863 | 2864 | ||
2865 | static SIMPLE_DEV_PM_OPS(snd_azf3328_pm, snd_azf3328_suspend, snd_azf3328_resume); | ||
2866 | #define SND_AZF3328_PM_OPS &snd_azf3328_pm | ||
2867 | #else | ||
2868 | #define SND_AZF3328_PM_OPS NULL | ||
2869 | #endif /* CONFIG_PM */ | ||
2864 | 2870 | ||
2865 | static struct pci_driver azf3328_driver = { | 2871 | static struct pci_driver azf3328_driver = { |
2866 | .name = KBUILD_MODNAME, | 2872 | .name = KBUILD_MODNAME, |
2867 | .id_table = snd_azf3328_ids, | 2873 | .id_table = snd_azf3328_ids, |
2868 | .probe = snd_azf3328_probe, | 2874 | .probe = snd_azf3328_probe, |
2869 | .remove = __devexit_p(snd_azf3328_remove), | 2875 | .remove = __devexit_p(snd_azf3328_remove), |
2870 | #ifdef CONFIG_PM | 2876 | .driver = { |
2871 | .suspend = snd_azf3328_suspend, | 2877 | .pm = SND_AZF3328_PM_OPS, |
2872 | .resume = snd_azf3328_resume, | 2878 | }, |
2873 | #endif | ||
2874 | }; | 2879 | }; |
2875 | 2880 | ||
2876 | module_pci_driver(azf3328_driver); | 2881 | module_pci_driver(azf3328_driver); |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index e76d68a7081f..83277b747b36 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -1872,9 +1872,10 @@ static void __devexit snd_ca0106_remove(struct pci_dev *pci) | |||
1872 | } | 1872 | } |
1873 | 1873 | ||
1874 | #ifdef CONFIG_PM | 1874 | #ifdef CONFIG_PM |
1875 | static int snd_ca0106_suspend(struct pci_dev *pci, pm_message_t state) | 1875 | static int snd_ca0106_suspend(struct device *dev) |
1876 | { | 1876 | { |
1877 | struct snd_card *card = pci_get_drvdata(pci); | 1877 | struct pci_dev *pci = to_pci_dev(dev); |
1878 | struct snd_card *card = dev_get_drvdata(dev); | ||
1878 | struct snd_ca0106 *chip = card->private_data; | 1879 | struct snd_ca0106 *chip = card->private_data; |
1879 | int i; | 1880 | int i; |
1880 | 1881 | ||
@@ -1889,13 +1890,14 @@ static int snd_ca0106_suspend(struct pci_dev *pci, pm_message_t state) | |||
1889 | 1890 | ||
1890 | pci_disable_device(pci); | 1891 | pci_disable_device(pci); |
1891 | pci_save_state(pci); | 1892 | pci_save_state(pci); |
1892 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 1893 | pci_set_power_state(pci, PCI_D3hot); |
1893 | return 0; | 1894 | return 0; |
1894 | } | 1895 | } |
1895 | 1896 | ||
1896 | static int snd_ca0106_resume(struct pci_dev *pci) | 1897 | static int snd_ca0106_resume(struct device *dev) |
1897 | { | 1898 | { |
1898 | struct snd_card *card = pci_get_drvdata(pci); | 1899 | struct pci_dev *pci = to_pci_dev(dev); |
1900 | struct snd_card *card = dev_get_drvdata(dev); | ||
1899 | struct snd_ca0106 *chip = card->private_data; | 1901 | struct snd_ca0106 *chip = card->private_data; |
1900 | int i; | 1902 | int i; |
1901 | 1903 | ||
@@ -1922,6 +1924,11 @@ static int snd_ca0106_resume(struct pci_dev *pci) | |||
1922 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1924 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1923 | return 0; | 1925 | return 0; |
1924 | } | 1926 | } |
1927 | |||
1928 | static SIMPLE_DEV_PM_OPS(snd_ca0106_pm, snd_ca0106_suspend, snd_ca0106_resume); | ||
1929 | #define SND_CA0106_PM_OPS &snd_ca0106_pm | ||
1930 | #else | ||
1931 | #define SND_CA0106_PM_OPS NULL | ||
1925 | #endif | 1932 | #endif |
1926 | 1933 | ||
1927 | // PCI IDs | 1934 | // PCI IDs |
@@ -1937,10 +1944,9 @@ static struct pci_driver ca0106_driver = { | |||
1937 | .id_table = snd_ca0106_ids, | 1944 | .id_table = snd_ca0106_ids, |
1938 | .probe = snd_ca0106_probe, | 1945 | .probe = snd_ca0106_probe, |
1939 | .remove = __devexit_p(snd_ca0106_remove), | 1946 | .remove = __devexit_p(snd_ca0106_remove), |
1940 | #ifdef CONFIG_PM | 1947 | .driver = { |
1941 | .suspend = snd_ca0106_suspend, | 1948 | .pm = SND_CA0106_PM_OPS, |
1942 | .resume = snd_ca0106_resume, | 1949 | }, |
1943 | #endif | ||
1944 | }; | 1950 | }; |
1945 | 1951 | ||
1946 | module_pci_driver(ca0106_driver); | 1952 | module_pci_driver(ca0106_driver); |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 3815bd4c6779..b7d6f2b886ef 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -3338,9 +3338,10 @@ static unsigned char saved_mixers[] = { | |||
3338 | SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, | 3338 | SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, |
3339 | }; | 3339 | }; |
3340 | 3340 | ||
3341 | static int snd_cmipci_suspend(struct pci_dev *pci, pm_message_t state) | 3341 | static int snd_cmipci_suspend(struct device *dev) |
3342 | { | 3342 | { |
3343 | struct snd_card *card = pci_get_drvdata(pci); | 3343 | struct pci_dev *pci = to_pci_dev(dev); |
3344 | struct snd_card *card = dev_get_drvdata(dev); | ||
3344 | struct cmipci *cm = card->private_data; | 3345 | struct cmipci *cm = card->private_data; |
3345 | int i; | 3346 | int i; |
3346 | 3347 | ||
@@ -3361,13 +3362,14 @@ static int snd_cmipci_suspend(struct pci_dev *pci, pm_message_t state) | |||
3361 | 3362 | ||
3362 | pci_disable_device(pci); | 3363 | pci_disable_device(pci); |
3363 | pci_save_state(pci); | 3364 | pci_save_state(pci); |
3364 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 3365 | pci_set_power_state(pci, PCI_D3hot); |
3365 | return 0; | 3366 | return 0; |
3366 | } | 3367 | } |
3367 | 3368 | ||
3368 | static int snd_cmipci_resume(struct pci_dev *pci) | 3369 | static int snd_cmipci_resume(struct device *dev) |
3369 | { | 3370 | { |
3370 | struct snd_card *card = pci_get_drvdata(pci); | 3371 | struct pci_dev *pci = to_pci_dev(dev); |
3372 | struct snd_card *card = dev_get_drvdata(dev); | ||
3371 | struct cmipci *cm = card->private_data; | 3373 | struct cmipci *cm = card->private_data; |
3372 | int i; | 3374 | int i; |
3373 | 3375 | ||
@@ -3396,6 +3398,11 @@ static int snd_cmipci_resume(struct pci_dev *pci) | |||
3396 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 3398 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
3397 | return 0; | 3399 | return 0; |
3398 | } | 3400 | } |
3401 | |||
3402 | static SIMPLE_DEV_PM_OPS(snd_cmipci_pm, snd_cmipci_suspend, snd_cmipci_resume); | ||
3403 | #define SND_CMIPCI_PM_OPS &snd_cmipci_pm | ||
3404 | #else | ||
3405 | #define SND_CMIPCI_PM_OPS NULL | ||
3399 | #endif /* CONFIG_PM */ | 3406 | #endif /* CONFIG_PM */ |
3400 | 3407 | ||
3401 | static struct pci_driver cmipci_driver = { | 3408 | static struct pci_driver cmipci_driver = { |
@@ -3403,10 +3410,9 @@ static struct pci_driver cmipci_driver = { | |||
3403 | .id_table = snd_cmipci_ids, | 3410 | .id_table = snd_cmipci_ids, |
3404 | .probe = snd_cmipci_probe, | 3411 | .probe = snd_cmipci_probe, |
3405 | .remove = __devexit_p(snd_cmipci_remove), | 3412 | .remove = __devexit_p(snd_cmipci_remove), |
3406 | #ifdef CONFIG_PM | 3413 | .driver = { |
3407 | .suspend = snd_cmipci_suspend, | 3414 | .pm = SND_CMIPCI_PM_OPS, |
3408 | .resume = snd_cmipci_resume, | 3415 | }, |
3409 | #endif | ||
3410 | }; | 3416 | }; |
3411 | 3417 | ||
3412 | module_pci_driver(cmipci_driver); | 3418 | module_pci_driver(cmipci_driver); |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 33506ee569bd..45a8317085f4 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -1997,9 +1997,10 @@ static int saved_regs[SUSPEND_REGISTERS] = { | |||
1997 | 1997 | ||
1998 | #define CLKCR1_CKRA 0x00010000L | 1998 | #define CLKCR1_CKRA 0x00010000L |
1999 | 1999 | ||
2000 | static int cs4281_suspend(struct pci_dev *pci, pm_message_t state) | 2000 | static int cs4281_suspend(struct device *dev) |
2001 | { | 2001 | { |
2002 | struct snd_card *card = pci_get_drvdata(pci); | 2002 | struct pci_dev *pci = to_pci_dev(dev); |
2003 | struct snd_card *card = dev_get_drvdata(dev); | ||
2003 | struct cs4281 *chip = card->private_data; | 2004 | struct cs4281 *chip = card->private_data; |
2004 | u32 ulCLK; | 2005 | u32 ulCLK; |
2005 | unsigned int i; | 2006 | unsigned int i; |
@@ -2040,13 +2041,14 @@ static int cs4281_suspend(struct pci_dev *pci, pm_message_t state) | |||
2040 | 2041 | ||
2041 | pci_disable_device(pci); | 2042 | pci_disable_device(pci); |
2042 | pci_save_state(pci); | 2043 | pci_save_state(pci); |
2043 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 2044 | pci_set_power_state(pci, PCI_D3hot); |
2044 | return 0; | 2045 | return 0; |
2045 | } | 2046 | } |
2046 | 2047 | ||
2047 | static int cs4281_resume(struct pci_dev *pci) | 2048 | static int cs4281_resume(struct device *dev) |
2048 | { | 2049 | { |
2049 | struct snd_card *card = pci_get_drvdata(pci); | 2050 | struct pci_dev *pci = to_pci_dev(dev); |
2051 | struct snd_card *card = dev_get_drvdata(dev); | ||
2050 | struct cs4281 *chip = card->private_data; | 2052 | struct cs4281 *chip = card->private_data; |
2051 | unsigned int i; | 2053 | unsigned int i; |
2052 | u32 ulCLK; | 2054 | u32 ulCLK; |
@@ -2082,6 +2084,11 @@ static int cs4281_resume(struct pci_dev *pci) | |||
2082 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2084 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
2083 | return 0; | 2085 | return 0; |
2084 | } | 2086 | } |
2087 | |||
2088 | static SIMPLE_DEV_PM_OPS(cs4281_pm, cs4281_suspend, cs4281_resume); | ||
2089 | #define CS4281_PM_OPS &cs4281_pm | ||
2090 | #else | ||
2091 | #define CS4281_PM_OPS NULL | ||
2085 | #endif /* CONFIG_PM */ | 2092 | #endif /* CONFIG_PM */ |
2086 | 2093 | ||
2087 | static struct pci_driver cs4281_driver = { | 2094 | static struct pci_driver cs4281_driver = { |
@@ -2089,10 +2096,9 @@ static struct pci_driver cs4281_driver = { | |||
2089 | .id_table = snd_cs4281_ids, | 2096 | .id_table = snd_cs4281_ids, |
2090 | .probe = snd_cs4281_probe, | 2097 | .probe = snd_cs4281_probe, |
2091 | .remove = __devexit_p(snd_cs4281_remove), | 2098 | .remove = __devexit_p(snd_cs4281_remove), |
2092 | #ifdef CONFIG_PM | 2099 | .driver = { |
2093 | .suspend = cs4281_suspend, | 2100 | .pm = CS4281_PM_OPS, |
2094 | .resume = cs4281_resume, | 2101 | }, |
2095 | #endif | ||
2096 | }; | 2102 | }; |
2097 | 2103 | ||
2098 | module_pci_driver(cs4281_driver); | 2104 | module_pci_driver(cs4281_driver); |
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 6cc7404e0e8f..1e007c736a8b 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <sound/core.h> | 32 | #include <sound/core.h> |
33 | #include <sound/cs46xx.h> | 33 | #include "cs46xx.h" |
34 | #include <sound/initval.h> | 34 | #include <sound/initval.h> |
35 | 35 | ||
36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
@@ -167,8 +167,9 @@ static struct pci_driver cs46xx_driver = { | |||
167 | .probe = snd_card_cs46xx_probe, | 167 | .probe = snd_card_cs46xx_probe, |
168 | .remove = __devexit_p(snd_card_cs46xx_remove), | 168 | .remove = __devexit_p(snd_card_cs46xx_remove), |
169 | #ifdef CONFIG_PM | 169 | #ifdef CONFIG_PM |
170 | .suspend = snd_cs46xx_suspend, | 170 | .driver = { |
171 | .resume = snd_cs46xx_resume, | 171 | .pm = &snd_cs46xx_pm, |
172 | }, | ||
172 | #endif | 173 | #endif |
173 | }; | 174 | }; |
174 | 175 | ||
diff --git a/sound/pci/cs46xx/cs46xx.h b/sound/pci/cs46xx/cs46xx.h new file mode 100644 index 000000000000..29d8a8da1ba7 --- /dev/null +++ b/sound/pci/cs46xx/cs46xx.h | |||
@@ -0,0 +1,1744 @@ | |||
1 | #ifndef __SOUND_CS46XX_H | ||
2 | #define __SOUND_CS46XX_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, | ||
6 | * Cirrus Logic, Inc. | ||
7 | * Definitions for Cirrus Logic CS46xx chips | ||
8 | * | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/pcm-indirect.h> | ||
28 | #include <sound/rawmidi.h> | ||
29 | #include <sound/ac97_codec.h> | ||
30 | #include "cs46xx_dsp_spos.h" | ||
31 | |||
32 | /* | ||
33 | * Direct registers | ||
34 | */ | ||
35 | |||
36 | /* | ||
37 | * The following define the offsets of the registers accessed via base address | ||
38 | * register zero on the CS46xx part. | ||
39 | */ | ||
40 | #define BA0_HISR 0x00000000 | ||
41 | #define BA0_HSR0 0x00000004 | ||
42 | #define BA0_HICR 0x00000008 | ||
43 | #define BA0_DMSR 0x00000100 | ||
44 | #define BA0_HSAR 0x00000110 | ||
45 | #define BA0_HDAR 0x00000114 | ||
46 | #define BA0_HDMR 0x00000118 | ||
47 | #define BA0_HDCR 0x0000011C | ||
48 | #define BA0_PFMC 0x00000200 | ||
49 | #define BA0_PFCV1 0x00000204 | ||
50 | #define BA0_PFCV2 0x00000208 | ||
51 | #define BA0_PCICFG00 0x00000300 | ||
52 | #define BA0_PCICFG04 0x00000304 | ||
53 | #define BA0_PCICFG08 0x00000308 | ||
54 | #define BA0_PCICFG0C 0x0000030C | ||
55 | #define BA0_PCICFG10 0x00000310 | ||
56 | #define BA0_PCICFG14 0x00000314 | ||
57 | #define BA0_PCICFG18 0x00000318 | ||
58 | #define BA0_PCICFG1C 0x0000031C | ||
59 | #define BA0_PCICFG20 0x00000320 | ||
60 | #define BA0_PCICFG24 0x00000324 | ||
61 | #define BA0_PCICFG28 0x00000328 | ||
62 | #define BA0_PCICFG2C 0x0000032C | ||
63 | #define BA0_PCICFG30 0x00000330 | ||
64 | #define BA0_PCICFG34 0x00000334 | ||
65 | #define BA0_PCICFG38 0x00000338 | ||
66 | #define BA0_PCICFG3C 0x0000033C | ||
67 | #define BA0_CLKCR1 0x00000400 | ||
68 | #define BA0_CLKCR2 0x00000404 | ||
69 | #define BA0_PLLM 0x00000408 | ||
70 | #define BA0_PLLCC 0x0000040C | ||
71 | #define BA0_FRR 0x00000410 | ||
72 | #define BA0_CFL1 0x00000414 | ||
73 | #define BA0_CFL2 0x00000418 | ||
74 | #define BA0_SERMC1 0x00000420 | ||
75 | #define BA0_SERMC2 0x00000424 | ||
76 | #define BA0_SERC1 0x00000428 | ||
77 | #define BA0_SERC2 0x0000042C | ||
78 | #define BA0_SERC3 0x00000430 | ||
79 | #define BA0_SERC4 0x00000434 | ||
80 | #define BA0_SERC5 0x00000438 | ||
81 | #define BA0_SERBSP 0x0000043C | ||
82 | #define BA0_SERBST 0x00000440 | ||
83 | #define BA0_SERBCM 0x00000444 | ||
84 | #define BA0_SERBAD 0x00000448 | ||
85 | #define BA0_SERBCF 0x0000044C | ||
86 | #define BA0_SERBWP 0x00000450 | ||
87 | #define BA0_SERBRP 0x00000454 | ||
88 | #ifndef NO_CS4612 | ||
89 | #define BA0_ASER_FADDR 0x00000458 | ||
90 | #endif | ||
91 | #define BA0_ACCTL 0x00000460 | ||
92 | #define BA0_ACSTS 0x00000464 | ||
93 | #define BA0_ACOSV 0x00000468 | ||
94 | #define BA0_ACCAD 0x0000046C | ||
95 | #define BA0_ACCDA 0x00000470 | ||
96 | #define BA0_ACISV 0x00000474 | ||
97 | #define BA0_ACSAD 0x00000478 | ||
98 | #define BA0_ACSDA 0x0000047C | ||
99 | #define BA0_JSPT 0x00000480 | ||
100 | #define BA0_JSCTL 0x00000484 | ||
101 | #define BA0_JSC1 0x00000488 | ||
102 | #define BA0_JSC2 0x0000048C | ||
103 | #define BA0_MIDCR 0x00000490 | ||
104 | #define BA0_MIDSR 0x00000494 | ||
105 | #define BA0_MIDWP 0x00000498 | ||
106 | #define BA0_MIDRP 0x0000049C | ||
107 | #define BA0_JSIO 0x000004A0 | ||
108 | #ifndef NO_CS4612 | ||
109 | #define BA0_ASER_MASTER 0x000004A4 | ||
110 | #endif | ||
111 | #define BA0_CFGI 0x000004B0 | ||
112 | #define BA0_SSVID 0x000004B4 | ||
113 | #define BA0_GPIOR 0x000004B8 | ||
114 | #ifndef NO_CS4612 | ||
115 | #define BA0_EGPIODR 0x000004BC | ||
116 | #define BA0_EGPIOPTR 0x000004C0 | ||
117 | #define BA0_EGPIOTR 0x000004C4 | ||
118 | #define BA0_EGPIOWR 0x000004C8 | ||
119 | #define BA0_EGPIOSR 0x000004CC | ||
120 | #define BA0_SERC6 0x000004D0 | ||
121 | #define BA0_SERC7 0x000004D4 | ||
122 | #define BA0_SERACC 0x000004D8 | ||
123 | #define BA0_ACCTL2 0x000004E0 | ||
124 | #define BA0_ACSTS2 0x000004E4 | ||
125 | #define BA0_ACOSV2 0x000004E8 | ||
126 | #define BA0_ACCAD2 0x000004EC | ||
127 | #define BA0_ACCDA2 0x000004F0 | ||
128 | #define BA0_ACISV2 0x000004F4 | ||
129 | #define BA0_ACSAD2 0x000004F8 | ||
130 | #define BA0_ACSDA2 0x000004FC | ||
131 | #define BA0_IOTAC0 0x00000500 | ||
132 | #define BA0_IOTAC1 0x00000504 | ||
133 | #define BA0_IOTAC2 0x00000508 | ||
134 | #define BA0_IOTAC3 0x0000050C | ||
135 | #define BA0_IOTAC4 0x00000510 | ||
136 | #define BA0_IOTAC5 0x00000514 | ||
137 | #define BA0_IOTAC6 0x00000518 | ||
138 | #define BA0_IOTAC7 0x0000051C | ||
139 | #define BA0_IOTAC8 0x00000520 | ||
140 | #define BA0_IOTAC9 0x00000524 | ||
141 | #define BA0_IOTAC10 0x00000528 | ||
142 | #define BA0_IOTAC11 0x0000052C | ||
143 | #define BA0_IOTFR0 0x00000540 | ||
144 | #define BA0_IOTFR1 0x00000544 | ||
145 | #define BA0_IOTFR2 0x00000548 | ||
146 | #define BA0_IOTFR3 0x0000054C | ||
147 | #define BA0_IOTFR4 0x00000550 | ||
148 | #define BA0_IOTFR5 0x00000554 | ||
149 | #define BA0_IOTFR6 0x00000558 | ||
150 | #define BA0_IOTFR7 0x0000055C | ||
151 | #define BA0_IOTFIFO 0x00000580 | ||
152 | #define BA0_IOTRRD 0x00000584 | ||
153 | #define BA0_IOTFP 0x00000588 | ||
154 | #define BA0_IOTCR 0x0000058C | ||
155 | #define BA0_DPCID 0x00000590 | ||
156 | #define BA0_DPCIA 0x00000594 | ||
157 | #define BA0_DPCIC 0x00000598 | ||
158 | #define BA0_PCPCIR 0x00000600 | ||
159 | #define BA0_PCPCIG 0x00000604 | ||
160 | #define BA0_PCPCIEN 0x00000608 | ||
161 | #define BA0_EPCIPMC 0x00000610 | ||
162 | #endif | ||
163 | |||
164 | /* | ||
165 | * The following define the offsets of the registers and memories accessed via | ||
166 | * base address register one on the CS46xx part. | ||
167 | */ | ||
168 | #define BA1_SP_DMEM0 0x00000000 | ||
169 | #define BA1_SP_DMEM1 0x00010000 | ||
170 | #define BA1_SP_PMEM 0x00020000 | ||
171 | #define BA1_SP_REG 0x00030000 | ||
172 | #define BA1_SPCR 0x00030000 | ||
173 | #define BA1_DREG 0x00030004 | ||
174 | #define BA1_DSRWP 0x00030008 | ||
175 | #define BA1_TWPR 0x0003000C | ||
176 | #define BA1_SPWR 0x00030010 | ||
177 | #define BA1_SPIR 0x00030014 | ||
178 | #define BA1_FGR1 0x00030020 | ||
179 | #define BA1_SPCS 0x00030028 | ||
180 | #define BA1_SDSR 0x0003002C | ||
181 | #define BA1_FRMT 0x00030030 | ||
182 | #define BA1_FRCC 0x00030034 | ||
183 | #define BA1_FRSC 0x00030038 | ||
184 | #define BA1_OMNI_MEM 0x000E0000 | ||
185 | |||
186 | |||
187 | /* | ||
188 | * The following defines are for the flags in the host interrupt status | ||
189 | * register. | ||
190 | */ | ||
191 | #define HISR_VC_MASK 0x0000FFFF | ||
192 | #define HISR_VC0 0x00000001 | ||
193 | #define HISR_VC1 0x00000002 | ||
194 | #define HISR_VC2 0x00000004 | ||
195 | #define HISR_VC3 0x00000008 | ||
196 | #define HISR_VC4 0x00000010 | ||
197 | #define HISR_VC5 0x00000020 | ||
198 | #define HISR_VC6 0x00000040 | ||
199 | #define HISR_VC7 0x00000080 | ||
200 | #define HISR_VC8 0x00000100 | ||
201 | #define HISR_VC9 0x00000200 | ||
202 | #define HISR_VC10 0x00000400 | ||
203 | #define HISR_VC11 0x00000800 | ||
204 | #define HISR_VC12 0x00001000 | ||
205 | #define HISR_VC13 0x00002000 | ||
206 | #define HISR_VC14 0x00004000 | ||
207 | #define HISR_VC15 0x00008000 | ||
208 | #define HISR_INT0 0x00010000 | ||
209 | #define HISR_INT1 0x00020000 | ||
210 | #define HISR_DMAI 0x00040000 | ||
211 | #define HISR_FROVR 0x00080000 | ||
212 | #define HISR_MIDI 0x00100000 | ||
213 | #ifdef NO_CS4612 | ||
214 | #define HISR_RESERVED 0x0FE00000 | ||
215 | #else | ||
216 | #define HISR_SBINT 0x00200000 | ||
217 | #define HISR_RESERVED 0x0FC00000 | ||
218 | #endif | ||
219 | #define HISR_H0P 0x40000000 | ||
220 | #define HISR_INTENA 0x80000000 | ||
221 | |||
222 | /* | ||
223 | * The following defines are for the flags in the host signal register 0. | ||
224 | */ | ||
225 | #define HSR0_VC_MASK 0xFFFFFFFF | ||
226 | #define HSR0_VC16 0x00000001 | ||
227 | #define HSR0_VC17 0x00000002 | ||
228 | #define HSR0_VC18 0x00000004 | ||
229 | #define HSR0_VC19 0x00000008 | ||
230 | #define HSR0_VC20 0x00000010 | ||
231 | #define HSR0_VC21 0x00000020 | ||
232 | #define HSR0_VC22 0x00000040 | ||
233 | #define HSR0_VC23 0x00000080 | ||
234 | #define HSR0_VC24 0x00000100 | ||
235 | #define HSR0_VC25 0x00000200 | ||
236 | #define HSR0_VC26 0x00000400 | ||
237 | #define HSR0_VC27 0x00000800 | ||
238 | #define HSR0_VC28 0x00001000 | ||
239 | #define HSR0_VC29 0x00002000 | ||
240 | #define HSR0_VC30 0x00004000 | ||
241 | #define HSR0_VC31 0x00008000 | ||
242 | #define HSR0_VC32 0x00010000 | ||
243 | #define HSR0_VC33 0x00020000 | ||
244 | #define HSR0_VC34 0x00040000 | ||
245 | #define HSR0_VC35 0x00080000 | ||
246 | #define HSR0_VC36 0x00100000 | ||
247 | #define HSR0_VC37 0x00200000 | ||
248 | #define HSR0_VC38 0x00400000 | ||
249 | #define HSR0_VC39 0x00800000 | ||
250 | #define HSR0_VC40 0x01000000 | ||
251 | #define HSR0_VC41 0x02000000 | ||
252 | #define HSR0_VC42 0x04000000 | ||
253 | #define HSR0_VC43 0x08000000 | ||
254 | #define HSR0_VC44 0x10000000 | ||
255 | #define HSR0_VC45 0x20000000 | ||
256 | #define HSR0_VC46 0x40000000 | ||
257 | #define HSR0_VC47 0x80000000 | ||
258 | |||
259 | /* | ||
260 | * The following defines are for the flags in the host interrupt control | ||
261 | * register. | ||
262 | */ | ||
263 | #define HICR_IEV 0x00000001 | ||
264 | #define HICR_CHGM 0x00000002 | ||
265 | |||
266 | /* | ||
267 | * The following defines are for the flags in the DMA status register. | ||
268 | */ | ||
269 | #define DMSR_HP 0x00000001 | ||
270 | #define DMSR_HR 0x00000002 | ||
271 | #define DMSR_SP 0x00000004 | ||
272 | #define DMSR_SR 0x00000008 | ||
273 | |||
274 | /* | ||
275 | * The following defines are for the flags in the host DMA source address | ||
276 | * register. | ||
277 | */ | ||
278 | #define HSAR_HOST_ADDR_MASK 0xFFFFFFFF | ||
279 | #define HSAR_DSP_ADDR_MASK 0x0000FFFF | ||
280 | #define HSAR_MEMID_MASK 0x000F0000 | ||
281 | #define HSAR_MEMID_SP_DMEM0 0x00000000 | ||
282 | #define HSAR_MEMID_SP_DMEM1 0x00010000 | ||
283 | #define HSAR_MEMID_SP_PMEM 0x00020000 | ||
284 | #define HSAR_MEMID_SP_DEBUG 0x00030000 | ||
285 | #define HSAR_MEMID_OMNI_MEM 0x000E0000 | ||
286 | #define HSAR_END 0x40000000 | ||
287 | #define HSAR_ERR 0x80000000 | ||
288 | |||
289 | /* | ||
290 | * The following defines are for the flags in the host DMA destination address | ||
291 | * register. | ||
292 | */ | ||
293 | #define HDAR_HOST_ADDR_MASK 0xFFFFFFFF | ||
294 | #define HDAR_DSP_ADDR_MASK 0x0000FFFF | ||
295 | #define HDAR_MEMID_MASK 0x000F0000 | ||
296 | #define HDAR_MEMID_SP_DMEM0 0x00000000 | ||
297 | #define HDAR_MEMID_SP_DMEM1 0x00010000 | ||
298 | #define HDAR_MEMID_SP_PMEM 0x00020000 | ||
299 | #define HDAR_MEMID_SP_DEBUG 0x00030000 | ||
300 | #define HDAR_MEMID_OMNI_MEM 0x000E0000 | ||
301 | #define HDAR_END 0x40000000 | ||
302 | #define HDAR_ERR 0x80000000 | ||
303 | |||
304 | /* | ||
305 | * The following defines are for the flags in the host DMA control register. | ||
306 | */ | ||
307 | #define HDMR_AC_MASK 0x0000F000 | ||
308 | #define HDMR_AC_8_16 0x00001000 | ||
309 | #define HDMR_AC_M_S 0x00002000 | ||
310 | #define HDMR_AC_B_L 0x00004000 | ||
311 | #define HDMR_AC_S_U 0x00008000 | ||
312 | |||
313 | /* | ||
314 | * The following defines are for the flags in the host DMA control register. | ||
315 | */ | ||
316 | #define HDCR_COUNT_MASK 0x000003FF | ||
317 | #define HDCR_DONE 0x00004000 | ||
318 | #define HDCR_OPT 0x00008000 | ||
319 | #define HDCR_WBD 0x00400000 | ||
320 | #define HDCR_WBS 0x00800000 | ||
321 | #define HDCR_DMS_MASK 0x07000000 | ||
322 | #define HDCR_DMS_LINEAR 0x00000000 | ||
323 | #define HDCR_DMS_16_DWORDS 0x01000000 | ||
324 | #define HDCR_DMS_32_DWORDS 0x02000000 | ||
325 | #define HDCR_DMS_64_DWORDS 0x03000000 | ||
326 | #define HDCR_DMS_128_DWORDS 0x04000000 | ||
327 | #define HDCR_DMS_256_DWORDS 0x05000000 | ||
328 | #define HDCR_DMS_512_DWORDS 0x06000000 | ||
329 | #define HDCR_DMS_1024_DWORDS 0x07000000 | ||
330 | #define HDCR_DH 0x08000000 | ||
331 | #define HDCR_SMS_MASK 0x70000000 | ||
332 | #define HDCR_SMS_LINEAR 0x00000000 | ||
333 | #define HDCR_SMS_16_DWORDS 0x10000000 | ||
334 | #define HDCR_SMS_32_DWORDS 0x20000000 | ||
335 | #define HDCR_SMS_64_DWORDS 0x30000000 | ||
336 | #define HDCR_SMS_128_DWORDS 0x40000000 | ||
337 | #define HDCR_SMS_256_DWORDS 0x50000000 | ||
338 | #define HDCR_SMS_512_DWORDS 0x60000000 | ||
339 | #define HDCR_SMS_1024_DWORDS 0x70000000 | ||
340 | #define HDCR_SH 0x80000000 | ||
341 | #define HDCR_COUNT_SHIFT 0 | ||
342 | |||
343 | /* | ||
344 | * The following defines are for the flags in the performance monitor control | ||
345 | * register. | ||
346 | */ | ||
347 | #define PFMC_C1SS_MASK 0x0000001F | ||
348 | #define PFMC_C1EV 0x00000020 | ||
349 | #define PFMC_C1RS 0x00008000 | ||
350 | #define PFMC_C2SS_MASK 0x001F0000 | ||
351 | #define PFMC_C2EV 0x00200000 | ||
352 | #define PFMC_C2RS 0x80000000 | ||
353 | #define PFMC_C1SS_SHIFT 0 | ||
354 | #define PFMC_C2SS_SHIFT 16 | ||
355 | #define PFMC_BUS_GRANT 0 | ||
356 | #define PFMC_GRANT_AFTER_REQ 1 | ||
357 | #define PFMC_TRANSACTION 2 | ||
358 | #define PFMC_DWORD_TRANSFER 3 | ||
359 | #define PFMC_SLAVE_READ 4 | ||
360 | #define PFMC_SLAVE_WRITE 5 | ||
361 | #define PFMC_PREEMPTION 6 | ||
362 | #define PFMC_DISCONNECT_RETRY 7 | ||
363 | #define PFMC_INTERRUPT 8 | ||
364 | #define PFMC_BUS_OWNERSHIP 9 | ||
365 | #define PFMC_TRANSACTION_LAG 10 | ||
366 | #define PFMC_PCI_CLOCK 11 | ||
367 | #define PFMC_SERIAL_CLOCK 12 | ||
368 | #define PFMC_SP_CLOCK 13 | ||
369 | |||
370 | /* | ||
371 | * The following defines are for the flags in the performance counter value 1 | ||
372 | * register. | ||
373 | */ | ||
374 | #define PFCV1_PC1V_MASK 0xFFFFFFFF | ||
375 | #define PFCV1_PC1V_SHIFT 0 | ||
376 | |||
377 | /* | ||
378 | * The following defines are for the flags in the performance counter value 2 | ||
379 | * register. | ||
380 | */ | ||
381 | #define PFCV2_PC2V_MASK 0xFFFFFFFF | ||
382 | #define PFCV2_PC2V_SHIFT 0 | ||
383 | |||
384 | /* | ||
385 | * The following defines are for the flags in the clock control register 1. | ||
386 | */ | ||
387 | #define CLKCR1_OSCS 0x00000001 | ||
388 | #define CLKCR1_OSCP 0x00000002 | ||
389 | #define CLKCR1_PLLSS_MASK 0x0000000C | ||
390 | #define CLKCR1_PLLSS_SERIAL 0x00000000 | ||
391 | #define CLKCR1_PLLSS_CRYSTAL 0x00000004 | ||
392 | #define CLKCR1_PLLSS_PCI 0x00000008 | ||
393 | #define CLKCR1_PLLSS_RESERVED 0x0000000C | ||
394 | #define CLKCR1_PLLP 0x00000010 | ||
395 | #define CLKCR1_SWCE 0x00000020 | ||
396 | #define CLKCR1_PLLOS 0x00000040 | ||
397 | |||
398 | /* | ||
399 | * The following defines are for the flags in the clock control register 2. | ||
400 | */ | ||
401 | #define CLKCR2_PDIVS_MASK 0x0000000F | ||
402 | #define CLKCR2_PDIVS_1 0x00000001 | ||
403 | #define CLKCR2_PDIVS_2 0x00000002 | ||
404 | #define CLKCR2_PDIVS_4 0x00000004 | ||
405 | #define CLKCR2_PDIVS_7 0x00000007 | ||
406 | #define CLKCR2_PDIVS_8 0x00000008 | ||
407 | #define CLKCR2_PDIVS_16 0x00000000 | ||
408 | |||
409 | /* | ||
410 | * The following defines are for the flags in the PLL multiplier register. | ||
411 | */ | ||
412 | #define PLLM_MASK 0x000000FF | ||
413 | #define PLLM_SHIFT 0 | ||
414 | |||
415 | /* | ||
416 | * The following defines are for the flags in the PLL capacitor coefficient | ||
417 | * register. | ||
418 | */ | ||
419 | #define PLLCC_CDR_MASK 0x00000007 | ||
420 | #ifndef NO_CS4610 | ||
421 | #define PLLCC_CDR_240_350_MHZ 0x00000000 | ||
422 | #define PLLCC_CDR_184_265_MHZ 0x00000001 | ||
423 | #define PLLCC_CDR_144_205_MHZ 0x00000002 | ||
424 | #define PLLCC_CDR_111_160_MHZ 0x00000003 | ||
425 | #define PLLCC_CDR_87_123_MHZ 0x00000004 | ||
426 | #define PLLCC_CDR_67_96_MHZ 0x00000005 | ||
427 | #define PLLCC_CDR_52_74_MHZ 0x00000006 | ||
428 | #define PLLCC_CDR_45_58_MHZ 0x00000007 | ||
429 | #endif | ||
430 | #ifndef NO_CS4612 | ||
431 | #define PLLCC_CDR_271_398_MHZ 0x00000000 | ||
432 | #define PLLCC_CDR_227_330_MHZ 0x00000001 | ||
433 | #define PLLCC_CDR_167_239_MHZ 0x00000002 | ||
434 | #define PLLCC_CDR_150_215_MHZ 0x00000003 | ||
435 | #define PLLCC_CDR_107_154_MHZ 0x00000004 | ||
436 | #define PLLCC_CDR_98_140_MHZ 0x00000005 | ||
437 | #define PLLCC_CDR_73_104_MHZ 0x00000006 | ||
438 | #define PLLCC_CDR_63_90_MHZ 0x00000007 | ||
439 | #endif | ||
440 | #define PLLCC_LPF_MASK 0x000000F8 | ||
441 | #ifndef NO_CS4610 | ||
442 | #define PLLCC_LPF_23850_60000_KHZ 0x00000000 | ||
443 | #define PLLCC_LPF_7960_26290_KHZ 0x00000008 | ||
444 | #define PLLCC_LPF_4160_10980_KHZ 0x00000018 | ||
445 | #define PLLCC_LPF_1740_4580_KHZ 0x00000038 | ||
446 | #define PLLCC_LPF_724_1910_KHZ 0x00000078 | ||
447 | #define PLLCC_LPF_317_798_KHZ 0x000000F8 | ||
448 | #endif | ||
449 | #ifndef NO_CS4612 | ||
450 | #define PLLCC_LPF_25580_64530_KHZ 0x00000000 | ||
451 | #define PLLCC_LPF_14360_37270_KHZ 0x00000008 | ||
452 | #define PLLCC_LPF_6100_16020_KHZ 0x00000018 | ||
453 | #define PLLCC_LPF_2540_6690_KHZ 0x00000038 | ||
454 | #define PLLCC_LPF_1050_2780_KHZ 0x00000078 | ||
455 | #define PLLCC_LPF_450_1160_KHZ 0x000000F8 | ||
456 | #endif | ||
457 | |||
458 | /* | ||
459 | * The following defines are for the flags in the feature reporting register. | ||
460 | */ | ||
461 | #define FRR_FAB_MASK 0x00000003 | ||
462 | #define FRR_MASK_MASK 0x0000001C | ||
463 | #ifdef NO_CS4612 | ||
464 | #define FRR_CFOP_MASK 0x000000E0 | ||
465 | #else | ||
466 | #define FRR_CFOP_MASK 0x00000FE0 | ||
467 | #endif | ||
468 | #define FRR_CFOP_NOT_DVD 0x00000020 | ||
469 | #define FRR_CFOP_A3D 0x00000040 | ||
470 | #define FRR_CFOP_128_PIN 0x00000080 | ||
471 | #ifndef NO_CS4612 | ||
472 | #define FRR_CFOP_CS4280 0x00000800 | ||
473 | #endif | ||
474 | #define FRR_FAB_SHIFT 0 | ||
475 | #define FRR_MASK_SHIFT 2 | ||
476 | #define FRR_CFOP_SHIFT 5 | ||
477 | |||
478 | /* | ||
479 | * The following defines are for the flags in the configuration load 1 | ||
480 | * register. | ||
481 | */ | ||
482 | #define CFL1_CLOCK_SOURCE_MASK 0x00000003 | ||
483 | #define CFL1_CLOCK_SOURCE_CS423X 0x00000000 | ||
484 | #define CFL1_CLOCK_SOURCE_AC97 0x00000001 | ||
485 | #define CFL1_CLOCK_SOURCE_CRYSTAL 0x00000002 | ||
486 | #define CFL1_CLOCK_SOURCE_DUAL_AC97 0x00000003 | ||
487 | #define CFL1_VALID_DATA_MASK 0x000000FF | ||
488 | |||
489 | /* | ||
490 | * The following defines are for the flags in the configuration load 2 | ||
491 | * register. | ||
492 | */ | ||
493 | #define CFL2_VALID_DATA_MASK 0x000000FF | ||
494 | |||
495 | /* | ||
496 | * The following defines are for the flags in the serial port master control | ||
497 | * register 1. | ||
498 | */ | ||
499 | #define SERMC1_MSPE 0x00000001 | ||
500 | #define SERMC1_PTC_MASK 0x0000000E | ||
501 | #define SERMC1_PTC_CS423X 0x00000000 | ||
502 | #define SERMC1_PTC_AC97 0x00000002 | ||
503 | #define SERMC1_PTC_DAC 0x00000004 | ||
504 | #define SERMC1_PLB 0x00000010 | ||
505 | #define SERMC1_XLB 0x00000020 | ||
506 | |||
507 | /* | ||
508 | * The following defines are for the flags in the serial port master control | ||
509 | * register 2. | ||
510 | */ | ||
511 | #define SERMC2_LROE 0x00000001 | ||
512 | #define SERMC2_MCOE 0x00000002 | ||
513 | #define SERMC2_MCDIV 0x00000004 | ||
514 | |||
515 | /* | ||
516 | * The following defines are for the flags in the serial port 1 configuration | ||
517 | * register. | ||
518 | */ | ||
519 | #define SERC1_SO1EN 0x00000001 | ||
520 | #define SERC1_SO1F_MASK 0x0000000E | ||
521 | #define SERC1_SO1F_CS423X 0x00000000 | ||
522 | #define SERC1_SO1F_AC97 0x00000002 | ||
523 | #define SERC1_SO1F_DAC 0x00000004 | ||
524 | #define SERC1_SO1F_SPDIF 0x00000006 | ||
525 | |||
526 | /* | ||
527 | * The following defines are for the flags in the serial port 2 configuration | ||
528 | * register. | ||
529 | */ | ||
530 | #define SERC2_SI1EN 0x00000001 | ||
531 | #define SERC2_SI1F_MASK 0x0000000E | ||
532 | #define SERC2_SI1F_CS423X 0x00000000 | ||
533 | #define SERC2_SI1F_AC97 0x00000002 | ||
534 | #define SERC2_SI1F_ADC 0x00000004 | ||
535 | #define SERC2_SI1F_SPDIF 0x00000006 | ||
536 | |||
537 | /* | ||
538 | * The following defines are for the flags in the serial port 3 configuration | ||
539 | * register. | ||
540 | */ | ||
541 | #define SERC3_SO2EN 0x00000001 | ||
542 | #define SERC3_SO2F_MASK 0x00000006 | ||
543 | #define SERC3_SO2F_DAC 0x00000000 | ||
544 | #define SERC3_SO2F_SPDIF 0x00000002 | ||
545 | |||
546 | /* | ||
547 | * The following defines are for the flags in the serial port 4 configuration | ||
548 | * register. | ||
549 | */ | ||
550 | #define SERC4_SO3EN 0x00000001 | ||
551 | #define SERC4_SO3F_MASK 0x00000006 | ||
552 | #define SERC4_SO3F_DAC 0x00000000 | ||
553 | #define SERC4_SO3F_SPDIF 0x00000002 | ||
554 | |||
555 | /* | ||
556 | * The following defines are for the flags in the serial port 5 configuration | ||
557 | * register. | ||
558 | */ | ||
559 | #define SERC5_SI2EN 0x00000001 | ||
560 | #define SERC5_SI2F_MASK 0x00000006 | ||
561 | #define SERC5_SI2F_ADC 0x00000000 | ||
562 | #define SERC5_SI2F_SPDIF 0x00000002 | ||
563 | |||
564 | /* | ||
565 | * The following defines are for the flags in the serial port backdoor sample | ||
566 | * pointer register. | ||
567 | */ | ||
568 | #define SERBSP_FSP_MASK 0x0000000F | ||
569 | #define SERBSP_FSP_SHIFT 0 | ||
570 | |||
571 | /* | ||
572 | * The following defines are for the flags in the serial port backdoor status | ||
573 | * register. | ||
574 | */ | ||
575 | #define SERBST_RRDY 0x00000001 | ||
576 | #define SERBST_WBSY 0x00000002 | ||
577 | |||
578 | /* | ||
579 | * The following defines are for the flags in the serial port backdoor command | ||
580 | * register. | ||
581 | */ | ||
582 | #define SERBCM_RDC 0x00000001 | ||
583 | #define SERBCM_WRC 0x00000002 | ||
584 | |||
585 | /* | ||
586 | * The following defines are for the flags in the serial port backdoor address | ||
587 | * register. | ||
588 | */ | ||
589 | #ifdef NO_CS4612 | ||
590 | #define SERBAD_FAD_MASK 0x000000FF | ||
591 | #else | ||
592 | #define SERBAD_FAD_MASK 0x000001FF | ||
593 | #endif | ||
594 | #define SERBAD_FAD_SHIFT 0 | ||
595 | |||
596 | /* | ||
597 | * The following defines are for the flags in the serial port backdoor | ||
598 | * configuration register. | ||
599 | */ | ||
600 | #define SERBCF_HBP 0x00000001 | ||
601 | |||
602 | /* | ||
603 | * The following defines are for the flags in the serial port backdoor write | ||
604 | * port register. | ||
605 | */ | ||
606 | #define SERBWP_FWD_MASK 0x000FFFFF | ||
607 | #define SERBWP_FWD_SHIFT 0 | ||
608 | |||
609 | /* | ||
610 | * The following defines are for the flags in the serial port backdoor read | ||
611 | * port register. | ||
612 | */ | ||
613 | #define SERBRP_FRD_MASK 0x000FFFFF | ||
614 | #define SERBRP_FRD_SHIFT 0 | ||
615 | |||
616 | /* | ||
617 | * The following defines are for the flags in the async FIFO address register. | ||
618 | */ | ||
619 | #ifndef NO_CS4612 | ||
620 | #define ASER_FADDR_A1_MASK 0x000001FF | ||
621 | #define ASER_FADDR_EN1 0x00008000 | ||
622 | #define ASER_FADDR_A2_MASK 0x01FF0000 | ||
623 | #define ASER_FADDR_EN2 0x80000000 | ||
624 | #define ASER_FADDR_A1_SHIFT 0 | ||
625 | #define ASER_FADDR_A2_SHIFT 16 | ||
626 | #endif | ||
627 | |||
628 | /* | ||
629 | * The following defines are for the flags in the AC97 control register. | ||
630 | */ | ||
631 | #define ACCTL_RSTN 0x00000001 | ||
632 | #define ACCTL_ESYN 0x00000002 | ||
633 | #define ACCTL_VFRM 0x00000004 | ||
634 | #define ACCTL_DCV 0x00000008 | ||
635 | #define ACCTL_CRW 0x00000010 | ||
636 | #define ACCTL_ASYN 0x00000020 | ||
637 | #ifndef NO_CS4612 | ||
638 | #define ACCTL_TC 0x00000040 | ||
639 | #endif | ||
640 | |||
641 | /* | ||
642 | * The following defines are for the flags in the AC97 status register. | ||
643 | */ | ||
644 | #define ACSTS_CRDY 0x00000001 | ||
645 | #define ACSTS_VSTS 0x00000002 | ||
646 | #ifndef NO_CS4612 | ||
647 | #define ACSTS_WKUP 0x00000004 | ||
648 | #endif | ||
649 | |||
650 | /* | ||
651 | * The following defines are for the flags in the AC97 output slot valid | ||
652 | * register. | ||
653 | */ | ||
654 | #define ACOSV_SLV3 0x00000001 | ||
655 | #define ACOSV_SLV4 0x00000002 | ||
656 | #define ACOSV_SLV5 0x00000004 | ||
657 | #define ACOSV_SLV6 0x00000008 | ||
658 | #define ACOSV_SLV7 0x00000010 | ||
659 | #define ACOSV_SLV8 0x00000020 | ||
660 | #define ACOSV_SLV9 0x00000040 | ||
661 | #define ACOSV_SLV10 0x00000080 | ||
662 | #define ACOSV_SLV11 0x00000100 | ||
663 | #define ACOSV_SLV12 0x00000200 | ||
664 | |||
665 | /* | ||
666 | * The following defines are for the flags in the AC97 command address | ||
667 | * register. | ||
668 | */ | ||
669 | #define ACCAD_CI_MASK 0x0000007F | ||
670 | #define ACCAD_CI_SHIFT 0 | ||
671 | |||
672 | /* | ||
673 | * The following defines are for the flags in the AC97 command data register. | ||
674 | */ | ||
675 | #define ACCDA_CD_MASK 0x0000FFFF | ||
676 | #define ACCDA_CD_SHIFT 0 | ||
677 | |||
678 | /* | ||
679 | * The following defines are for the flags in the AC97 input slot valid | ||
680 | * register. | ||
681 | */ | ||
682 | #define ACISV_ISV3 0x00000001 | ||
683 | #define ACISV_ISV4 0x00000002 | ||
684 | #define ACISV_ISV5 0x00000004 | ||
685 | #define ACISV_ISV6 0x00000008 | ||
686 | #define ACISV_ISV7 0x00000010 | ||
687 | #define ACISV_ISV8 0x00000020 | ||
688 | #define ACISV_ISV9 0x00000040 | ||
689 | #define ACISV_ISV10 0x00000080 | ||
690 | #define ACISV_ISV11 0x00000100 | ||
691 | #define ACISV_ISV12 0x00000200 | ||
692 | |||
693 | /* | ||
694 | * The following defines are for the flags in the AC97 status address | ||
695 | * register. | ||
696 | */ | ||
697 | #define ACSAD_SI_MASK 0x0000007F | ||
698 | #define ACSAD_SI_SHIFT 0 | ||
699 | |||
700 | /* | ||
701 | * The following defines are for the flags in the AC97 status data register. | ||
702 | */ | ||
703 | #define ACSDA_SD_MASK 0x0000FFFF | ||
704 | #define ACSDA_SD_SHIFT 0 | ||
705 | |||
706 | /* | ||
707 | * The following defines are for the flags in the joystick poll/trigger | ||
708 | * register. | ||
709 | */ | ||
710 | #define JSPT_CAX 0x00000001 | ||
711 | #define JSPT_CAY 0x00000002 | ||
712 | #define JSPT_CBX 0x00000004 | ||
713 | #define JSPT_CBY 0x00000008 | ||
714 | #define JSPT_BA1 0x00000010 | ||
715 | #define JSPT_BA2 0x00000020 | ||
716 | #define JSPT_BB1 0x00000040 | ||
717 | #define JSPT_BB2 0x00000080 | ||
718 | |||
719 | /* | ||
720 | * The following defines are for the flags in the joystick control register. | ||
721 | */ | ||
722 | #define JSCTL_SP_MASK 0x00000003 | ||
723 | #define JSCTL_SP_SLOW 0x00000000 | ||
724 | #define JSCTL_SP_MEDIUM_SLOW 0x00000001 | ||
725 | #define JSCTL_SP_MEDIUM_FAST 0x00000002 | ||
726 | #define JSCTL_SP_FAST 0x00000003 | ||
727 | #define JSCTL_ARE 0x00000004 | ||
728 | |||
729 | /* | ||
730 | * The following defines are for the flags in the joystick coordinate pair 1 | ||
731 | * readback register. | ||
732 | */ | ||
733 | #define JSC1_Y1V_MASK 0x0000FFFF | ||
734 | #define JSC1_X1V_MASK 0xFFFF0000 | ||
735 | #define JSC1_Y1V_SHIFT 0 | ||
736 | #define JSC1_X1V_SHIFT 16 | ||
737 | |||
738 | /* | ||
739 | * The following defines are for the flags in the joystick coordinate pair 2 | ||
740 | * readback register. | ||
741 | */ | ||
742 | #define JSC2_Y2V_MASK 0x0000FFFF | ||
743 | #define JSC2_X2V_MASK 0xFFFF0000 | ||
744 | #define JSC2_Y2V_SHIFT 0 | ||
745 | #define JSC2_X2V_SHIFT 16 | ||
746 | |||
747 | /* | ||
748 | * The following defines are for the flags in the MIDI control register. | ||
749 | */ | ||
750 | #define MIDCR_TXE 0x00000001 /* Enable transmitting. */ | ||
751 | #define MIDCR_RXE 0x00000002 /* Enable receiving. */ | ||
752 | #define MIDCR_RIE 0x00000004 /* Interrupt upon tx ready. */ | ||
753 | #define MIDCR_TIE 0x00000008 /* Interrupt upon rx ready. */ | ||
754 | #define MIDCR_MLB 0x00000010 /* Enable midi loopback. */ | ||
755 | #define MIDCR_MRST 0x00000020 /* Reset interface. */ | ||
756 | |||
757 | /* | ||
758 | * The following defines are for the flags in the MIDI status register. | ||
759 | */ | ||
760 | #define MIDSR_TBF 0x00000001 /* Tx FIFO is full. */ | ||
761 | #define MIDSR_RBE 0x00000002 /* Rx FIFO is empty. */ | ||
762 | |||
763 | /* | ||
764 | * The following defines are for the flags in the MIDI write port register. | ||
765 | */ | ||
766 | #define MIDWP_MWD_MASK 0x000000FF | ||
767 | #define MIDWP_MWD_SHIFT 0 | ||
768 | |||
769 | /* | ||
770 | * The following defines are for the flags in the MIDI read port register. | ||
771 | */ | ||
772 | #define MIDRP_MRD_MASK 0x000000FF | ||
773 | #define MIDRP_MRD_SHIFT 0 | ||
774 | |||
775 | /* | ||
776 | * The following defines are for the flags in the joystick GPIO register. | ||
777 | */ | ||
778 | #define JSIO_DAX 0x00000001 | ||
779 | #define JSIO_DAY 0x00000002 | ||
780 | #define JSIO_DBX 0x00000004 | ||
781 | #define JSIO_DBY 0x00000008 | ||
782 | #define JSIO_AXOE 0x00000010 | ||
783 | #define JSIO_AYOE 0x00000020 | ||
784 | #define JSIO_BXOE 0x00000040 | ||
785 | #define JSIO_BYOE 0x00000080 | ||
786 | |||
787 | /* | ||
788 | * The following defines are for the flags in the master async/sync serial | ||
789 | * port enable register. | ||
790 | */ | ||
791 | #ifndef NO_CS4612 | ||
792 | #define ASER_MASTER_ME 0x00000001 | ||
793 | #endif | ||
794 | |||
795 | /* | ||
796 | * The following defines are for the flags in the configuration interface | ||
797 | * register. | ||
798 | */ | ||
799 | #define CFGI_CLK 0x00000001 | ||
800 | #define CFGI_DOUT 0x00000002 | ||
801 | #define CFGI_DIN_EEN 0x00000004 | ||
802 | #define CFGI_EELD 0x00000008 | ||
803 | |||
804 | /* | ||
805 | * The following defines are for the flags in the subsystem ID and vendor ID | ||
806 | * register. | ||
807 | */ | ||
808 | #define SSVID_VID_MASK 0x0000FFFF | ||
809 | #define SSVID_SID_MASK 0xFFFF0000 | ||
810 | #define SSVID_VID_SHIFT 0 | ||
811 | #define SSVID_SID_SHIFT 16 | ||
812 | |||
813 | /* | ||
814 | * The following defines are for the flags in the GPIO pin interface register. | ||
815 | */ | ||
816 | #define GPIOR_VOLDN 0x00000001 | ||
817 | #define GPIOR_VOLUP 0x00000002 | ||
818 | #define GPIOR_SI2D 0x00000004 | ||
819 | #define GPIOR_SI2OE 0x00000008 | ||
820 | |||
821 | /* | ||
822 | * The following defines are for the flags in the extended GPIO pin direction | ||
823 | * register. | ||
824 | */ | ||
825 | #ifndef NO_CS4612 | ||
826 | #define EGPIODR_GPOE0 0x00000001 | ||
827 | #define EGPIODR_GPOE1 0x00000002 | ||
828 | #define EGPIODR_GPOE2 0x00000004 | ||
829 | #define EGPIODR_GPOE3 0x00000008 | ||
830 | #define EGPIODR_GPOE4 0x00000010 | ||
831 | #define EGPIODR_GPOE5 0x00000020 | ||
832 | #define EGPIODR_GPOE6 0x00000040 | ||
833 | #define EGPIODR_GPOE7 0x00000080 | ||
834 | #define EGPIODR_GPOE8 0x00000100 | ||
835 | #endif | ||
836 | |||
837 | /* | ||
838 | * The following defines are for the flags in the extended GPIO pin polarity/ | ||
839 | * type register. | ||
840 | */ | ||
841 | #ifndef NO_CS4612 | ||
842 | #define EGPIOPTR_GPPT0 0x00000001 | ||
843 | #define EGPIOPTR_GPPT1 0x00000002 | ||
844 | #define EGPIOPTR_GPPT2 0x00000004 | ||
845 | #define EGPIOPTR_GPPT3 0x00000008 | ||
846 | #define EGPIOPTR_GPPT4 0x00000010 | ||
847 | #define EGPIOPTR_GPPT5 0x00000020 | ||
848 | #define EGPIOPTR_GPPT6 0x00000040 | ||
849 | #define EGPIOPTR_GPPT7 0x00000080 | ||
850 | #define EGPIOPTR_GPPT8 0x00000100 | ||
851 | #endif | ||
852 | |||
853 | /* | ||
854 | * The following defines are for the flags in the extended GPIO pin sticky | ||
855 | * register. | ||
856 | */ | ||
857 | #ifndef NO_CS4612 | ||
858 | #define EGPIOTR_GPS0 0x00000001 | ||
859 | #define EGPIOTR_GPS1 0x00000002 | ||
860 | #define EGPIOTR_GPS2 0x00000004 | ||
861 | #define EGPIOTR_GPS3 0x00000008 | ||
862 | #define EGPIOTR_GPS4 0x00000010 | ||
863 | #define EGPIOTR_GPS5 0x00000020 | ||
864 | #define EGPIOTR_GPS6 0x00000040 | ||
865 | #define EGPIOTR_GPS7 0x00000080 | ||
866 | #define EGPIOTR_GPS8 0x00000100 | ||
867 | #endif | ||
868 | |||
869 | /* | ||
870 | * The following defines are for the flags in the extended GPIO ping wakeup | ||
871 | * register. | ||
872 | */ | ||
873 | #ifndef NO_CS4612 | ||
874 | #define EGPIOWR_GPW0 0x00000001 | ||
875 | #define EGPIOWR_GPW1 0x00000002 | ||
876 | #define EGPIOWR_GPW2 0x00000004 | ||
877 | #define EGPIOWR_GPW3 0x00000008 | ||
878 | #define EGPIOWR_GPW4 0x00000010 | ||
879 | #define EGPIOWR_GPW5 0x00000020 | ||
880 | #define EGPIOWR_GPW6 0x00000040 | ||
881 | #define EGPIOWR_GPW7 0x00000080 | ||
882 | #define EGPIOWR_GPW8 0x00000100 | ||
883 | #endif | ||
884 | |||
885 | /* | ||
886 | * The following defines are for the flags in the extended GPIO pin status | ||
887 | * register. | ||
888 | */ | ||
889 | #ifndef NO_CS4612 | ||
890 | #define EGPIOSR_GPS0 0x00000001 | ||
891 | #define EGPIOSR_GPS1 0x00000002 | ||
892 | #define EGPIOSR_GPS2 0x00000004 | ||
893 | #define EGPIOSR_GPS3 0x00000008 | ||
894 | #define EGPIOSR_GPS4 0x00000010 | ||
895 | #define EGPIOSR_GPS5 0x00000020 | ||
896 | #define EGPIOSR_GPS6 0x00000040 | ||
897 | #define EGPIOSR_GPS7 0x00000080 | ||
898 | #define EGPIOSR_GPS8 0x00000100 | ||
899 | #endif | ||
900 | |||
901 | /* | ||
902 | * The following defines are for the flags in the serial port 6 configuration | ||
903 | * register. | ||
904 | */ | ||
905 | #ifndef NO_CS4612 | ||
906 | #define SERC6_ASDO2EN 0x00000001 | ||
907 | #endif | ||
908 | |||
909 | /* | ||
910 | * The following defines are for the flags in the serial port 7 configuration | ||
911 | * register. | ||
912 | */ | ||
913 | #ifndef NO_CS4612 | ||
914 | #define SERC7_ASDI2EN 0x00000001 | ||
915 | #define SERC7_POSILB 0x00000002 | ||
916 | #define SERC7_SIPOLB 0x00000004 | ||
917 | #define SERC7_SOSILB 0x00000008 | ||
918 | #define SERC7_SISOLB 0x00000010 | ||
919 | #endif | ||
920 | |||
921 | /* | ||
922 | * The following defines are for the flags in the serial port AC link | ||
923 | * configuration register. | ||
924 | */ | ||
925 | #ifndef NO_CS4612 | ||
926 | #define SERACC_CHIP_TYPE_MASK 0x00000001 | ||
927 | #define SERACC_CHIP_TYPE_1_03 0x00000000 | ||
928 | #define SERACC_CHIP_TYPE_2_0 0x00000001 | ||
929 | #define SERACC_TWO_CODECS 0x00000002 | ||
930 | #define SERACC_MDM 0x00000004 | ||
931 | #define SERACC_HSP 0x00000008 | ||
932 | #define SERACC_ODT 0x00000010 /* only CS4630 */ | ||
933 | #endif | ||
934 | |||
935 | /* | ||
936 | * The following defines are for the flags in the AC97 control register 2. | ||
937 | */ | ||
938 | #ifndef NO_CS4612 | ||
939 | #define ACCTL2_RSTN 0x00000001 | ||
940 | #define ACCTL2_ESYN 0x00000002 | ||
941 | #define ACCTL2_VFRM 0x00000004 | ||
942 | #define ACCTL2_DCV 0x00000008 | ||
943 | #define ACCTL2_CRW 0x00000010 | ||
944 | #define ACCTL2_ASYN 0x00000020 | ||
945 | #endif | ||
946 | |||
947 | /* | ||
948 | * The following defines are for the flags in the AC97 status register 2. | ||
949 | */ | ||
950 | #ifndef NO_CS4612 | ||
951 | #define ACSTS2_CRDY 0x00000001 | ||
952 | #define ACSTS2_VSTS 0x00000002 | ||
953 | #endif | ||
954 | |||
955 | /* | ||
956 | * The following defines are for the flags in the AC97 output slot valid | ||
957 | * register 2. | ||
958 | */ | ||
959 | #ifndef NO_CS4612 | ||
960 | #define ACOSV2_SLV3 0x00000001 | ||
961 | #define ACOSV2_SLV4 0x00000002 | ||
962 | #define ACOSV2_SLV5 0x00000004 | ||
963 | #define ACOSV2_SLV6 0x00000008 | ||
964 | #define ACOSV2_SLV7 0x00000010 | ||
965 | #define ACOSV2_SLV8 0x00000020 | ||
966 | #define ACOSV2_SLV9 0x00000040 | ||
967 | #define ACOSV2_SLV10 0x00000080 | ||
968 | #define ACOSV2_SLV11 0x00000100 | ||
969 | #define ACOSV2_SLV12 0x00000200 | ||
970 | #endif | ||
971 | |||
972 | /* | ||
973 | * The following defines are for the flags in the AC97 command address | ||
974 | * register 2. | ||
975 | */ | ||
976 | #ifndef NO_CS4612 | ||
977 | #define ACCAD2_CI_MASK 0x0000007F | ||
978 | #define ACCAD2_CI_SHIFT 0 | ||
979 | #endif | ||
980 | |||
981 | /* | ||
982 | * The following defines are for the flags in the AC97 command data register | ||
983 | * 2. | ||
984 | */ | ||
985 | #ifndef NO_CS4612 | ||
986 | #define ACCDA2_CD_MASK 0x0000FFFF | ||
987 | #define ACCDA2_CD_SHIFT 0 | ||
988 | #endif | ||
989 | |||
990 | /* | ||
991 | * The following defines are for the flags in the AC97 input slot valid | ||
992 | * register 2. | ||
993 | */ | ||
994 | #ifndef NO_CS4612 | ||
995 | #define ACISV2_ISV3 0x00000001 | ||
996 | #define ACISV2_ISV4 0x00000002 | ||
997 | #define ACISV2_ISV5 0x00000004 | ||
998 | #define ACISV2_ISV6 0x00000008 | ||
999 | #define ACISV2_ISV7 0x00000010 | ||
1000 | #define ACISV2_ISV8 0x00000020 | ||
1001 | #define ACISV2_ISV9 0x00000040 | ||
1002 | #define ACISV2_ISV10 0x00000080 | ||
1003 | #define ACISV2_ISV11 0x00000100 | ||
1004 | #define ACISV2_ISV12 0x00000200 | ||
1005 | #endif | ||
1006 | |||
1007 | /* | ||
1008 | * The following defines are for the flags in the AC97 status address | ||
1009 | * register 2. | ||
1010 | */ | ||
1011 | #ifndef NO_CS4612 | ||
1012 | #define ACSAD2_SI_MASK 0x0000007F | ||
1013 | #define ACSAD2_SI_SHIFT 0 | ||
1014 | #endif | ||
1015 | |||
1016 | /* | ||
1017 | * The following defines are for the flags in the AC97 status data register 2. | ||
1018 | */ | ||
1019 | #ifndef NO_CS4612 | ||
1020 | #define ACSDA2_SD_MASK 0x0000FFFF | ||
1021 | #define ACSDA2_SD_SHIFT 0 | ||
1022 | #endif | ||
1023 | |||
1024 | /* | ||
1025 | * The following defines are for the flags in the I/O trap address and control | ||
1026 | * registers (all 12). | ||
1027 | */ | ||
1028 | #ifndef NO_CS4612 | ||
1029 | #define IOTAC_SA_MASK 0x0000FFFF | ||
1030 | #define IOTAC_MSK_MASK 0x000F0000 | ||
1031 | #define IOTAC_IODC_MASK 0x06000000 | ||
1032 | #define IOTAC_IODC_16_BIT 0x00000000 | ||
1033 | #define IOTAC_IODC_10_BIT 0x02000000 | ||
1034 | #define IOTAC_IODC_12_BIT 0x04000000 | ||
1035 | #define IOTAC_WSPI 0x08000000 | ||
1036 | #define IOTAC_RSPI 0x10000000 | ||
1037 | #define IOTAC_WSE 0x20000000 | ||
1038 | #define IOTAC_WE 0x40000000 | ||
1039 | #define IOTAC_RE 0x80000000 | ||
1040 | #define IOTAC_SA_SHIFT 0 | ||
1041 | #define IOTAC_MSK_SHIFT 16 | ||
1042 | #endif | ||
1043 | |||
1044 | /* | ||
1045 | * The following defines are for the flags in the I/O trap fast read registers | ||
1046 | * (all 8). | ||
1047 | */ | ||
1048 | #ifndef NO_CS4612 | ||
1049 | #define IOTFR_D_MASK 0x0000FFFF | ||
1050 | #define IOTFR_A_MASK 0x000F0000 | ||
1051 | #define IOTFR_R_MASK 0x0F000000 | ||
1052 | #define IOTFR_ALL 0x40000000 | ||
1053 | #define IOTFR_VL 0x80000000 | ||
1054 | #define IOTFR_D_SHIFT 0 | ||
1055 | #define IOTFR_A_SHIFT 16 | ||
1056 | #define IOTFR_R_SHIFT 24 | ||
1057 | #endif | ||
1058 | |||
1059 | /* | ||
1060 | * The following defines are for the flags in the I/O trap FIFO register. | ||
1061 | */ | ||
1062 | #ifndef NO_CS4612 | ||
1063 | #define IOTFIFO_BA_MASK 0x00003FFF | ||
1064 | #define IOTFIFO_S_MASK 0x00FF0000 | ||
1065 | #define IOTFIFO_OF 0x40000000 | ||
1066 | #define IOTFIFO_SPIOF 0x80000000 | ||
1067 | #define IOTFIFO_BA_SHIFT 0 | ||
1068 | #define IOTFIFO_S_SHIFT 16 | ||
1069 | #endif | ||
1070 | |||
1071 | /* | ||
1072 | * The following defines are for the flags in the I/O trap retry read data | ||
1073 | * register. | ||
1074 | */ | ||
1075 | #ifndef NO_CS4612 | ||
1076 | #define IOTRRD_D_MASK 0x0000FFFF | ||
1077 | #define IOTRRD_RDV 0x80000000 | ||
1078 | #define IOTRRD_D_SHIFT 0 | ||
1079 | #endif | ||
1080 | |||
1081 | /* | ||
1082 | * The following defines are for the flags in the I/O trap FIFO pointer | ||
1083 | * register. | ||
1084 | */ | ||
1085 | #ifndef NO_CS4612 | ||
1086 | #define IOTFP_CA_MASK 0x00003FFF | ||
1087 | #define IOTFP_PA_MASK 0x3FFF0000 | ||
1088 | #define IOTFP_CA_SHIFT 0 | ||
1089 | #define IOTFP_PA_SHIFT 16 | ||
1090 | #endif | ||
1091 | |||
1092 | /* | ||
1093 | * The following defines are for the flags in the I/O trap control register. | ||
1094 | */ | ||
1095 | #ifndef NO_CS4612 | ||
1096 | #define IOTCR_ITD 0x00000001 | ||
1097 | #define IOTCR_HRV 0x00000002 | ||
1098 | #define IOTCR_SRV 0x00000004 | ||
1099 | #define IOTCR_DTI 0x00000008 | ||
1100 | #define IOTCR_DFI 0x00000010 | ||
1101 | #define IOTCR_DDP 0x00000020 | ||
1102 | #define IOTCR_JTE 0x00000040 | ||
1103 | #define IOTCR_PPE 0x00000080 | ||
1104 | #endif | ||
1105 | |||
1106 | /* | ||
1107 | * The following defines are for the flags in the direct PCI data register. | ||
1108 | */ | ||
1109 | #ifndef NO_CS4612 | ||
1110 | #define DPCID_D_MASK 0xFFFFFFFF | ||
1111 | #define DPCID_D_SHIFT 0 | ||
1112 | #endif | ||
1113 | |||
1114 | /* | ||
1115 | * The following defines are for the flags in the direct PCI address register. | ||
1116 | */ | ||
1117 | #ifndef NO_CS4612 | ||
1118 | #define DPCIA_A_MASK 0xFFFFFFFF | ||
1119 | #define DPCIA_A_SHIFT 0 | ||
1120 | #endif | ||
1121 | |||
1122 | /* | ||
1123 | * The following defines are for the flags in the direct PCI command register. | ||
1124 | */ | ||
1125 | #ifndef NO_CS4612 | ||
1126 | #define DPCIC_C_MASK 0x0000000F | ||
1127 | #define DPCIC_C_IOREAD 0x00000002 | ||
1128 | #define DPCIC_C_IOWRITE 0x00000003 | ||
1129 | #define DPCIC_BE_MASK 0x000000F0 | ||
1130 | #endif | ||
1131 | |||
1132 | /* | ||
1133 | * The following defines are for the flags in the PC/PCI request register. | ||
1134 | */ | ||
1135 | #ifndef NO_CS4612 | ||
1136 | #define PCPCIR_RDC_MASK 0x00000007 | ||
1137 | #define PCPCIR_C_MASK 0x00007000 | ||
1138 | #define PCPCIR_REQ 0x00008000 | ||
1139 | #define PCPCIR_RDC_SHIFT 0 | ||
1140 | #define PCPCIR_C_SHIFT 12 | ||
1141 | #endif | ||
1142 | |||
1143 | /* | ||
1144 | * The following defines are for the flags in the PC/PCI grant register. | ||
1145 | */ | ||
1146 | #ifndef NO_CS4612 | ||
1147 | #define PCPCIG_GDC_MASK 0x00000007 | ||
1148 | #define PCPCIG_VL 0x00008000 | ||
1149 | #define PCPCIG_GDC_SHIFT 0 | ||
1150 | #endif | ||
1151 | |||
1152 | /* | ||
1153 | * The following defines are for the flags in the PC/PCI master enable | ||
1154 | * register. | ||
1155 | */ | ||
1156 | #ifndef NO_CS4612 | ||
1157 | #define PCPCIEN_EN 0x00000001 | ||
1158 | #endif | ||
1159 | |||
1160 | /* | ||
1161 | * The following defines are for the flags in the extended PCI power | ||
1162 | * management control register. | ||
1163 | */ | ||
1164 | #ifndef NO_CS4612 | ||
1165 | #define EPCIPMC_GWU 0x00000001 | ||
1166 | #define EPCIPMC_FSPC 0x00000002 | ||
1167 | #endif | ||
1168 | |||
1169 | /* | ||
1170 | * The following defines are for the flags in the SP control register. | ||
1171 | */ | ||
1172 | #define SPCR_RUN 0x00000001 | ||
1173 | #define SPCR_STPFR 0x00000002 | ||
1174 | #define SPCR_RUNFR 0x00000004 | ||
1175 | #define SPCR_TICK 0x00000008 | ||
1176 | #define SPCR_DRQEN 0x00000020 | ||
1177 | #define SPCR_RSTSP 0x00000040 | ||
1178 | #define SPCR_OREN 0x00000080 | ||
1179 | #ifndef NO_CS4612 | ||
1180 | #define SPCR_PCIINT 0x00000100 | ||
1181 | #define SPCR_OINTD 0x00000200 | ||
1182 | #define SPCR_CRE 0x00008000 | ||
1183 | #endif | ||
1184 | |||
1185 | /* | ||
1186 | * The following defines are for the flags in the debug index register. | ||
1187 | */ | ||
1188 | #define DREG_REGID_MASK 0x0000007F | ||
1189 | #define DREG_DEBUG 0x00000080 | ||
1190 | #define DREG_RGBK_MASK 0x00000700 | ||
1191 | #define DREG_TRAP 0x00000800 | ||
1192 | #if !defined(NO_CS4612) | ||
1193 | #if !defined(NO_CS4615) | ||
1194 | #define DREG_TRAPX 0x00001000 | ||
1195 | #endif | ||
1196 | #endif | ||
1197 | #define DREG_REGID_SHIFT 0 | ||
1198 | #define DREG_RGBK_SHIFT 8 | ||
1199 | #define DREG_RGBK_REGID_MASK 0x0000077F | ||
1200 | #define DREG_REGID_R0 0x00000010 | ||
1201 | #define DREG_REGID_R1 0x00000011 | ||
1202 | #define DREG_REGID_R2 0x00000012 | ||
1203 | #define DREG_REGID_R3 0x00000013 | ||
1204 | #define DREG_REGID_R4 0x00000014 | ||
1205 | #define DREG_REGID_R5 0x00000015 | ||
1206 | #define DREG_REGID_R6 0x00000016 | ||
1207 | #define DREG_REGID_R7 0x00000017 | ||
1208 | #define DREG_REGID_R8 0x00000018 | ||
1209 | #define DREG_REGID_R9 0x00000019 | ||
1210 | #define DREG_REGID_RA 0x0000001A | ||
1211 | #define DREG_REGID_RB 0x0000001B | ||
1212 | #define DREG_REGID_RC 0x0000001C | ||
1213 | #define DREG_REGID_RD 0x0000001D | ||
1214 | #define DREG_REGID_RE 0x0000001E | ||
1215 | #define DREG_REGID_RF 0x0000001F | ||
1216 | #define DREG_REGID_RA_BUS_LOW 0x00000020 | ||
1217 | #define DREG_REGID_RA_BUS_HIGH 0x00000038 | ||
1218 | #define DREG_REGID_YBUS_LOW 0x00000050 | ||
1219 | #define DREG_REGID_YBUS_HIGH 0x00000058 | ||
1220 | #define DREG_REGID_TRAP_0 0x00000100 | ||
1221 | #define DREG_REGID_TRAP_1 0x00000101 | ||
1222 | #define DREG_REGID_TRAP_2 0x00000102 | ||
1223 | #define DREG_REGID_TRAP_3 0x00000103 | ||
1224 | #define DREG_REGID_TRAP_4 0x00000104 | ||
1225 | #define DREG_REGID_TRAP_5 0x00000105 | ||
1226 | #define DREG_REGID_TRAP_6 0x00000106 | ||
1227 | #define DREG_REGID_TRAP_7 0x00000107 | ||
1228 | #define DREG_REGID_INDIRECT_ADDRESS 0x0000010E | ||
1229 | #define DREG_REGID_TOP_OF_STACK 0x0000010F | ||
1230 | #if !defined(NO_CS4612) | ||
1231 | #if !defined(NO_CS4615) | ||
1232 | #define DREG_REGID_TRAP_8 0x00000110 | ||
1233 | #define DREG_REGID_TRAP_9 0x00000111 | ||
1234 | #define DREG_REGID_TRAP_10 0x00000112 | ||
1235 | #define DREG_REGID_TRAP_11 0x00000113 | ||
1236 | #define DREG_REGID_TRAP_12 0x00000114 | ||
1237 | #define DREG_REGID_TRAP_13 0x00000115 | ||
1238 | #define DREG_REGID_TRAP_14 0x00000116 | ||
1239 | #define DREG_REGID_TRAP_15 0x00000117 | ||
1240 | #define DREG_REGID_TRAP_16 0x00000118 | ||
1241 | #define DREG_REGID_TRAP_17 0x00000119 | ||
1242 | #define DREG_REGID_TRAP_18 0x0000011A | ||
1243 | #define DREG_REGID_TRAP_19 0x0000011B | ||
1244 | #define DREG_REGID_TRAP_20 0x0000011C | ||
1245 | #define DREG_REGID_TRAP_21 0x0000011D | ||
1246 | #define DREG_REGID_TRAP_22 0x0000011E | ||
1247 | #define DREG_REGID_TRAP_23 0x0000011F | ||
1248 | #endif | ||
1249 | #endif | ||
1250 | #define DREG_REGID_RSA0_LOW 0x00000200 | ||
1251 | #define DREG_REGID_RSA0_HIGH 0x00000201 | ||
1252 | #define DREG_REGID_RSA1_LOW 0x00000202 | ||
1253 | #define DREG_REGID_RSA1_HIGH 0x00000203 | ||
1254 | #define DREG_REGID_RSA2 0x00000204 | ||
1255 | #define DREG_REGID_RSA3 0x00000205 | ||
1256 | #define DREG_REGID_RSI0_LOW 0x00000206 | ||
1257 | #define DREG_REGID_RSI0_HIGH 0x00000207 | ||
1258 | #define DREG_REGID_RSI1 0x00000208 | ||
1259 | #define DREG_REGID_RSI2 0x00000209 | ||
1260 | #define DREG_REGID_SAGUSTATUS 0x0000020A | ||
1261 | #define DREG_REGID_RSCONFIG01_LOW 0x0000020B | ||
1262 | #define DREG_REGID_RSCONFIG01_HIGH 0x0000020C | ||
1263 | #define DREG_REGID_RSCONFIG23_LOW 0x0000020D | ||
1264 | #define DREG_REGID_RSCONFIG23_HIGH 0x0000020E | ||
1265 | #define DREG_REGID_RSDMA01E 0x0000020F | ||
1266 | #define DREG_REGID_RSDMA23E 0x00000210 | ||
1267 | #define DREG_REGID_RSD0_LOW 0x00000211 | ||
1268 | #define DREG_REGID_RSD0_HIGH 0x00000212 | ||
1269 | #define DREG_REGID_RSD1_LOW 0x00000213 | ||
1270 | #define DREG_REGID_RSD1_HIGH 0x00000214 | ||
1271 | #define DREG_REGID_RSD2_LOW 0x00000215 | ||
1272 | #define DREG_REGID_RSD2_HIGH 0x00000216 | ||
1273 | #define DREG_REGID_RSD3_LOW 0x00000217 | ||
1274 | #define DREG_REGID_RSD3_HIGH 0x00000218 | ||
1275 | #define DREG_REGID_SRAR_HIGH 0x0000021A | ||
1276 | #define DREG_REGID_SRAR_LOW 0x0000021B | ||
1277 | #define DREG_REGID_DMA_STATE 0x0000021C | ||
1278 | #define DREG_REGID_CURRENT_DMA_STREAM 0x0000021D | ||
1279 | #define DREG_REGID_NEXT_DMA_STREAM 0x0000021E | ||
1280 | #define DREG_REGID_CPU_STATUS 0x00000300 | ||
1281 | #define DREG_REGID_MAC_MODE 0x00000301 | ||
1282 | #define DREG_REGID_STACK_AND_REPEAT 0x00000302 | ||
1283 | #define DREG_REGID_INDEX0 0x00000304 | ||
1284 | #define DREG_REGID_INDEX1 0x00000305 | ||
1285 | #define DREG_REGID_DMA_STATE_0_3 0x00000400 | ||
1286 | #define DREG_REGID_DMA_STATE_4_7 0x00000404 | ||
1287 | #define DREG_REGID_DMA_STATE_8_11 0x00000408 | ||
1288 | #define DREG_REGID_DMA_STATE_12_15 0x0000040C | ||
1289 | #define DREG_REGID_DMA_STATE_16_19 0x00000410 | ||
1290 | #define DREG_REGID_DMA_STATE_20_23 0x00000414 | ||
1291 | #define DREG_REGID_DMA_STATE_24_27 0x00000418 | ||
1292 | #define DREG_REGID_DMA_STATE_28_31 0x0000041C | ||
1293 | #define DREG_REGID_DMA_STATE_32_35 0x00000420 | ||
1294 | #define DREG_REGID_DMA_STATE_36_39 0x00000424 | ||
1295 | #define DREG_REGID_DMA_STATE_40_43 0x00000428 | ||
1296 | #define DREG_REGID_DMA_STATE_44_47 0x0000042C | ||
1297 | #define DREG_REGID_DMA_STATE_48_51 0x00000430 | ||
1298 | #define DREG_REGID_DMA_STATE_52_55 0x00000434 | ||
1299 | #define DREG_REGID_DMA_STATE_56_59 0x00000438 | ||
1300 | #define DREG_REGID_DMA_STATE_60_63 0x0000043C | ||
1301 | #define DREG_REGID_DMA_STATE_64_67 0x00000440 | ||
1302 | #define DREG_REGID_DMA_STATE_68_71 0x00000444 | ||
1303 | #define DREG_REGID_DMA_STATE_72_75 0x00000448 | ||
1304 | #define DREG_REGID_DMA_STATE_76_79 0x0000044C | ||
1305 | #define DREG_REGID_DMA_STATE_80_83 0x00000450 | ||
1306 | #define DREG_REGID_DMA_STATE_84_87 0x00000454 | ||
1307 | #define DREG_REGID_DMA_STATE_88_91 0x00000458 | ||
1308 | #define DREG_REGID_DMA_STATE_92_95 0x0000045C | ||
1309 | #define DREG_REGID_TRAP_SELECT 0x00000500 | ||
1310 | #define DREG_REGID_TRAP_WRITE_0 0x00000500 | ||
1311 | #define DREG_REGID_TRAP_WRITE_1 0x00000501 | ||
1312 | #define DREG_REGID_TRAP_WRITE_2 0x00000502 | ||
1313 | #define DREG_REGID_TRAP_WRITE_3 0x00000503 | ||
1314 | #define DREG_REGID_TRAP_WRITE_4 0x00000504 | ||
1315 | #define DREG_REGID_TRAP_WRITE_5 0x00000505 | ||
1316 | #define DREG_REGID_TRAP_WRITE_6 0x00000506 | ||
1317 | #define DREG_REGID_TRAP_WRITE_7 0x00000507 | ||
1318 | #if !defined(NO_CS4612) | ||
1319 | #if !defined(NO_CS4615) | ||
1320 | #define DREG_REGID_TRAP_WRITE_8 0x00000510 | ||
1321 | #define DREG_REGID_TRAP_WRITE_9 0x00000511 | ||
1322 | #define DREG_REGID_TRAP_WRITE_10 0x00000512 | ||
1323 | #define DREG_REGID_TRAP_WRITE_11 0x00000513 | ||
1324 | #define DREG_REGID_TRAP_WRITE_12 0x00000514 | ||
1325 | #define DREG_REGID_TRAP_WRITE_13 0x00000515 | ||
1326 | #define DREG_REGID_TRAP_WRITE_14 0x00000516 | ||
1327 | #define DREG_REGID_TRAP_WRITE_15 0x00000517 | ||
1328 | #define DREG_REGID_TRAP_WRITE_16 0x00000518 | ||
1329 | #define DREG_REGID_TRAP_WRITE_17 0x00000519 | ||
1330 | #define DREG_REGID_TRAP_WRITE_18 0x0000051A | ||
1331 | #define DREG_REGID_TRAP_WRITE_19 0x0000051B | ||
1332 | #define DREG_REGID_TRAP_WRITE_20 0x0000051C | ||
1333 | #define DREG_REGID_TRAP_WRITE_21 0x0000051D | ||
1334 | #define DREG_REGID_TRAP_WRITE_22 0x0000051E | ||
1335 | #define DREG_REGID_TRAP_WRITE_23 0x0000051F | ||
1336 | #endif | ||
1337 | #endif | ||
1338 | #define DREG_REGID_MAC0_ACC0_LOW 0x00000600 | ||
1339 | #define DREG_REGID_MAC0_ACC1_LOW 0x00000601 | ||
1340 | #define DREG_REGID_MAC0_ACC2_LOW 0x00000602 | ||
1341 | #define DREG_REGID_MAC0_ACC3_LOW 0x00000603 | ||
1342 | #define DREG_REGID_MAC1_ACC0_LOW 0x00000604 | ||
1343 | #define DREG_REGID_MAC1_ACC1_LOW 0x00000605 | ||
1344 | #define DREG_REGID_MAC1_ACC2_LOW 0x00000606 | ||
1345 | #define DREG_REGID_MAC1_ACC3_LOW 0x00000607 | ||
1346 | #define DREG_REGID_MAC0_ACC0_MID 0x00000608 | ||
1347 | #define DREG_REGID_MAC0_ACC1_MID 0x00000609 | ||
1348 | #define DREG_REGID_MAC0_ACC2_MID 0x0000060A | ||
1349 | #define DREG_REGID_MAC0_ACC3_MID 0x0000060B | ||
1350 | #define DREG_REGID_MAC1_ACC0_MID 0x0000060C | ||
1351 | #define DREG_REGID_MAC1_ACC1_MID 0x0000060D | ||
1352 | #define DREG_REGID_MAC1_ACC2_MID 0x0000060E | ||
1353 | #define DREG_REGID_MAC1_ACC3_MID 0x0000060F | ||
1354 | #define DREG_REGID_MAC0_ACC0_HIGH 0x00000610 | ||
1355 | #define DREG_REGID_MAC0_ACC1_HIGH 0x00000611 | ||
1356 | #define DREG_REGID_MAC0_ACC2_HIGH 0x00000612 | ||
1357 | #define DREG_REGID_MAC0_ACC3_HIGH 0x00000613 | ||
1358 | #define DREG_REGID_MAC1_ACC0_HIGH 0x00000614 | ||
1359 | #define DREG_REGID_MAC1_ACC1_HIGH 0x00000615 | ||
1360 | #define DREG_REGID_MAC1_ACC2_HIGH 0x00000616 | ||
1361 | #define DREG_REGID_MAC1_ACC3_HIGH 0x00000617 | ||
1362 | #define DREG_REGID_RSHOUT_LOW 0x00000620 | ||
1363 | #define DREG_REGID_RSHOUT_MID 0x00000628 | ||
1364 | #define DREG_REGID_RSHOUT_HIGH 0x00000630 | ||
1365 | |||
1366 | /* | ||
1367 | * The following defines are for the flags in the DMA stream requestor write | ||
1368 | */ | ||
1369 | #define DSRWP_DSR_MASK 0x0000000F | ||
1370 | #define DSRWP_DSR_BG_RQ 0x00000001 | ||
1371 | #define DSRWP_DSR_PRIORITY_MASK 0x00000006 | ||
1372 | #define DSRWP_DSR_PRIORITY_0 0x00000000 | ||
1373 | #define DSRWP_DSR_PRIORITY_1 0x00000002 | ||
1374 | #define DSRWP_DSR_PRIORITY_2 0x00000004 | ||
1375 | #define DSRWP_DSR_PRIORITY_3 0x00000006 | ||
1376 | #define DSRWP_DSR_RQ_PENDING 0x00000008 | ||
1377 | |||
1378 | /* | ||
1379 | * The following defines are for the flags in the trap write port register. | ||
1380 | */ | ||
1381 | #define TWPR_TW_MASK 0x0000FFFF | ||
1382 | #define TWPR_TW_SHIFT 0 | ||
1383 | |||
1384 | /* | ||
1385 | * The following defines are for the flags in the stack pointer write | ||
1386 | * register. | ||
1387 | */ | ||
1388 | #define SPWR_STKP_MASK 0x0000000F | ||
1389 | #define SPWR_STKP_SHIFT 0 | ||
1390 | |||
1391 | /* | ||
1392 | * The following defines are for the flags in the SP interrupt register. | ||
1393 | */ | ||
1394 | #define SPIR_FRI 0x00000001 | ||
1395 | #define SPIR_DOI 0x00000002 | ||
1396 | #define SPIR_GPI2 0x00000004 | ||
1397 | #define SPIR_GPI3 0x00000008 | ||
1398 | #define SPIR_IP0 0x00000010 | ||
1399 | #define SPIR_IP1 0x00000020 | ||
1400 | #define SPIR_IP2 0x00000040 | ||
1401 | #define SPIR_IP3 0x00000080 | ||
1402 | |||
1403 | /* | ||
1404 | * The following defines are for the flags in the functional group 1 register. | ||
1405 | */ | ||
1406 | #define FGR1_F1S_MASK 0x0000FFFF | ||
1407 | #define FGR1_F1S_SHIFT 0 | ||
1408 | |||
1409 | /* | ||
1410 | * The following defines are for the flags in the SP clock status register. | ||
1411 | */ | ||
1412 | #define SPCS_FRI 0x00000001 | ||
1413 | #define SPCS_DOI 0x00000002 | ||
1414 | #define SPCS_GPI2 0x00000004 | ||
1415 | #define SPCS_GPI3 0x00000008 | ||
1416 | #define SPCS_IP0 0x00000010 | ||
1417 | #define SPCS_IP1 0x00000020 | ||
1418 | #define SPCS_IP2 0x00000040 | ||
1419 | #define SPCS_IP3 0x00000080 | ||
1420 | #define SPCS_SPRUN 0x00000100 | ||
1421 | #define SPCS_SLEEP 0x00000200 | ||
1422 | #define SPCS_FG 0x00000400 | ||
1423 | #define SPCS_ORUN 0x00000800 | ||
1424 | #define SPCS_IRQ 0x00001000 | ||
1425 | #define SPCS_FGN_MASK 0x0000E000 | ||
1426 | #define SPCS_FGN_SHIFT 13 | ||
1427 | |||
1428 | /* | ||
1429 | * The following defines are for the flags in the SP DMA requestor status | ||
1430 | * register. | ||
1431 | */ | ||
1432 | #define SDSR_DCS_MASK 0x000000FF | ||
1433 | #define SDSR_DCS_SHIFT 0 | ||
1434 | #define SDSR_DCS_NONE 0x00000007 | ||
1435 | |||
1436 | /* | ||
1437 | * The following defines are for the flags in the frame timer register. | ||
1438 | */ | ||
1439 | #define FRMT_FTV_MASK 0x0000FFFF | ||
1440 | #define FRMT_FTV_SHIFT 0 | ||
1441 | |||
1442 | /* | ||
1443 | * The following defines are for the flags in the frame timer current count | ||
1444 | * register. | ||
1445 | */ | ||
1446 | #define FRCC_FCC_MASK 0x0000FFFF | ||
1447 | #define FRCC_FCC_SHIFT 0 | ||
1448 | |||
1449 | /* | ||
1450 | * The following defines are for the flags in the frame timer save count | ||
1451 | * register. | ||
1452 | */ | ||
1453 | #define FRSC_FCS_MASK 0x0000FFFF | ||
1454 | #define FRSC_FCS_SHIFT 0 | ||
1455 | |||
1456 | /* | ||
1457 | * The following define the various flags stored in the scatter/gather | ||
1458 | * descriptors. | ||
1459 | */ | ||
1460 | #define DMA_SG_NEXT_ENTRY_MASK 0x00000FF8 | ||
1461 | #define DMA_SG_SAMPLE_END_MASK 0x0FFF0000 | ||
1462 | #define DMA_SG_SAMPLE_END_FLAG 0x10000000 | ||
1463 | #define DMA_SG_LOOP_END_FLAG 0x20000000 | ||
1464 | #define DMA_SG_SIGNAL_END_FLAG 0x40000000 | ||
1465 | #define DMA_SG_SIGNAL_PAGE_FLAG 0x80000000 | ||
1466 | #define DMA_SG_NEXT_ENTRY_SHIFT 3 | ||
1467 | #define DMA_SG_SAMPLE_END_SHIFT 16 | ||
1468 | |||
1469 | /* | ||
1470 | * The following define the offsets of the fields within the on-chip generic | ||
1471 | * DMA requestor. | ||
1472 | */ | ||
1473 | #define DMA_RQ_CONTROL1 0x00000000 | ||
1474 | #define DMA_RQ_CONTROL2 0x00000004 | ||
1475 | #define DMA_RQ_SOURCE_ADDR 0x00000008 | ||
1476 | #define DMA_RQ_DESTINATION_ADDR 0x0000000C | ||
1477 | #define DMA_RQ_NEXT_PAGE_ADDR 0x00000010 | ||
1478 | #define DMA_RQ_NEXT_PAGE_SGDESC 0x00000014 | ||
1479 | #define DMA_RQ_LOOP_START_ADDR 0x00000018 | ||
1480 | #define DMA_RQ_POST_LOOP_ADDR 0x0000001C | ||
1481 | #define DMA_RQ_PAGE_MAP_ADDR 0x00000020 | ||
1482 | |||
1483 | /* | ||
1484 | * The following defines are for the flags in the first control word of the | ||
1485 | * on-chip generic DMA requestor. | ||
1486 | */ | ||
1487 | #define DMA_RQ_C1_COUNT_MASK 0x000003FF | ||
1488 | #define DMA_RQ_C1_DESTINATION_SCATTER 0x00001000 | ||
1489 | #define DMA_RQ_C1_SOURCE_GATHER 0x00002000 | ||
1490 | #define DMA_RQ_C1_DONE_FLAG 0x00004000 | ||
1491 | #define DMA_RQ_C1_OPTIMIZE_STATE 0x00008000 | ||
1492 | #define DMA_RQ_C1_SAMPLE_END_STATE_MASK 0x00030000 | ||
1493 | #define DMA_RQ_C1_FULL_PAGE 0x00000000 | ||
1494 | #define DMA_RQ_C1_BEFORE_SAMPLE_END 0x00010000 | ||
1495 | #define DMA_RQ_C1_PAGE_MAP_ERROR 0x00020000 | ||
1496 | #define DMA_RQ_C1_AT_SAMPLE_END 0x00030000 | ||
1497 | #define DMA_RQ_C1_LOOP_END_STATE_MASK 0x000C0000 | ||
1498 | #define DMA_RQ_C1_NOT_LOOP_END 0x00000000 | ||
1499 | #define DMA_RQ_C1_BEFORE_LOOP_END 0x00040000 | ||
1500 | #define DMA_RQ_C1_2PAGE_LOOP_BEGIN 0x00080000 | ||
1501 | #define DMA_RQ_C1_LOOP_BEGIN 0x000C0000 | ||
1502 | #define DMA_RQ_C1_PAGE_MAP_MASK 0x00300000 | ||
1503 | #define DMA_RQ_C1_PM_NONE_PENDING 0x00000000 | ||
1504 | #define DMA_RQ_C1_PM_NEXT_PENDING 0x00100000 | ||
1505 | #define DMA_RQ_C1_PM_RESERVED 0x00200000 | ||
1506 | #define DMA_RQ_C1_PM_LOOP_NEXT_PENDING 0x00300000 | ||
1507 | #define DMA_RQ_C1_WRITEBACK_DEST_FLAG 0x00400000 | ||
1508 | #define DMA_RQ_C1_WRITEBACK_SRC_FLAG 0x00800000 | ||
1509 | #define DMA_RQ_C1_DEST_SIZE_MASK 0x07000000 | ||
1510 | #define DMA_RQ_C1_DEST_LINEAR 0x00000000 | ||
1511 | #define DMA_RQ_C1_DEST_MOD16 0x01000000 | ||
1512 | #define DMA_RQ_C1_DEST_MOD32 0x02000000 | ||
1513 | #define DMA_RQ_C1_DEST_MOD64 0x03000000 | ||
1514 | #define DMA_RQ_C1_DEST_MOD128 0x04000000 | ||
1515 | #define DMA_RQ_C1_DEST_MOD256 0x05000000 | ||
1516 | #define DMA_RQ_C1_DEST_MOD512 0x06000000 | ||
1517 | #define DMA_RQ_C1_DEST_MOD1024 0x07000000 | ||
1518 | #define DMA_RQ_C1_DEST_ON_HOST 0x08000000 | ||
1519 | #define DMA_RQ_C1_SOURCE_SIZE_MASK 0x70000000 | ||
1520 | #define DMA_RQ_C1_SOURCE_LINEAR 0x00000000 | ||
1521 | #define DMA_RQ_C1_SOURCE_MOD16 0x10000000 | ||
1522 | #define DMA_RQ_C1_SOURCE_MOD32 0x20000000 | ||
1523 | #define DMA_RQ_C1_SOURCE_MOD64 0x30000000 | ||
1524 | #define DMA_RQ_C1_SOURCE_MOD128 0x40000000 | ||
1525 | #define DMA_RQ_C1_SOURCE_MOD256 0x50000000 | ||
1526 | #define DMA_RQ_C1_SOURCE_MOD512 0x60000000 | ||
1527 | #define DMA_RQ_C1_SOURCE_MOD1024 0x70000000 | ||
1528 | #define DMA_RQ_C1_SOURCE_ON_HOST 0x80000000 | ||
1529 | #define DMA_RQ_C1_COUNT_SHIFT 0 | ||
1530 | |||
1531 | /* | ||
1532 | * The following defines are for the flags in the second control word of the | ||
1533 | * on-chip generic DMA requestor. | ||
1534 | */ | ||
1535 | #define DMA_RQ_C2_VIRTUAL_CHANNEL_MASK 0x0000003F | ||
1536 | #define DMA_RQ_C2_VIRTUAL_SIGNAL_MASK 0x00000300 | ||
1537 | #define DMA_RQ_C2_NO_VIRTUAL_SIGNAL 0x00000000 | ||
1538 | #define DMA_RQ_C2_SIGNAL_EVERY_DMA 0x00000100 | ||
1539 | #define DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG 0x00000200 | ||
1540 | #define DMA_RQ_C2_SIGNAL_DEST_PINGPONG 0x00000300 | ||
1541 | #define DMA_RQ_C2_AUDIO_CONVERT_MASK 0x0000F000 | ||
1542 | #define DMA_RQ_C2_AC_NONE 0x00000000 | ||
1543 | #define DMA_RQ_C2_AC_8_TO_16_BIT 0x00001000 | ||
1544 | #define DMA_RQ_C2_AC_MONO_TO_STEREO 0x00002000 | ||
1545 | #define DMA_RQ_C2_AC_ENDIAN_CONVERT 0x00004000 | ||
1546 | #define DMA_RQ_C2_AC_SIGNED_CONVERT 0x00008000 | ||
1547 | #define DMA_RQ_C2_LOOP_END_MASK 0x0FFF0000 | ||
1548 | #define DMA_RQ_C2_LOOP_MASK 0x30000000 | ||
1549 | #define DMA_RQ_C2_NO_LOOP 0x00000000 | ||
1550 | #define DMA_RQ_C2_ONE_PAGE_LOOP 0x10000000 | ||
1551 | #define DMA_RQ_C2_TWO_PAGE_LOOP 0x20000000 | ||
1552 | #define DMA_RQ_C2_MULTI_PAGE_LOOP 0x30000000 | ||
1553 | #define DMA_RQ_C2_SIGNAL_LOOP_BACK 0x40000000 | ||
1554 | #define DMA_RQ_C2_SIGNAL_POST_BEGIN_PAGE 0x80000000 | ||
1555 | #define DMA_RQ_C2_VIRTUAL_CHANNEL_SHIFT 0 | ||
1556 | #define DMA_RQ_C2_LOOP_END_SHIFT 16 | ||
1557 | |||
1558 | /* | ||
1559 | * The following defines are for the flags in the source and destination words | ||
1560 | * of the on-chip generic DMA requestor. | ||
1561 | */ | ||
1562 | #define DMA_RQ_SD_ADDRESS_MASK 0x0000FFFF | ||
1563 | #define DMA_RQ_SD_MEMORY_ID_MASK 0x000F0000 | ||
1564 | #define DMA_RQ_SD_SP_PARAM_ADDR 0x00000000 | ||
1565 | #define DMA_RQ_SD_SP_SAMPLE_ADDR 0x00010000 | ||
1566 | #define DMA_RQ_SD_SP_PROGRAM_ADDR 0x00020000 | ||
1567 | #define DMA_RQ_SD_SP_DEBUG_ADDR 0x00030000 | ||
1568 | #define DMA_RQ_SD_OMNIMEM_ADDR 0x000E0000 | ||
1569 | #define DMA_RQ_SD_END_FLAG 0x40000000 | ||
1570 | #define DMA_RQ_SD_ERROR_FLAG 0x80000000 | ||
1571 | #define DMA_RQ_SD_ADDRESS_SHIFT 0 | ||
1572 | |||
1573 | /* | ||
1574 | * The following defines are for the flags in the page map address word of the | ||
1575 | * on-chip generic DMA requestor. | ||
1576 | */ | ||
1577 | #define DMA_RQ_PMA_LOOP_THIRD_PAGE_ENTRY_MASK 0x00000FF8 | ||
1578 | #define DMA_RQ_PMA_PAGE_TABLE_MASK 0xFFFFF000 | ||
1579 | #define DMA_RQ_PMA_LOOP_THIRD_PAGE_ENTRY_SHIFT 3 | ||
1580 | #define DMA_RQ_PMA_PAGE_TABLE_SHIFT 12 | ||
1581 | |||
1582 | #define BA1_VARIDEC_BUF_1 0x000 | ||
1583 | |||
1584 | #define BA1_PDTC 0x0c0 /* BA1_PLAY_DMA_TRANSACTION_COUNT_REG */ | ||
1585 | #define BA1_PFIE 0x0c4 /* BA1_PLAY_FORMAT_&_INTERRUPT_ENABLE_REG */ | ||
1586 | #define BA1_PBA 0x0c8 /* BA1_PLAY_BUFFER_ADDRESS */ | ||
1587 | #define BA1_PVOL 0x0f8 /* BA1_PLAY_VOLUME_REG */ | ||
1588 | #define BA1_PSRC 0x288 /* BA1_PLAY_SAMPLE_RATE_CORRECTION_REG */ | ||
1589 | #define BA1_PCTL 0x2a4 /* BA1_PLAY_CONTROL_REG */ | ||
1590 | #define BA1_PPI 0x2b4 /* BA1_PLAY_PHASE_INCREMENT_REG */ | ||
1591 | |||
1592 | #define BA1_CCTL 0x064 /* BA1_CAPTURE_CONTROL_REG */ | ||
1593 | #define BA1_CIE 0x104 /* BA1_CAPTURE_INTERRUPT_ENABLE_REG */ | ||
1594 | #define BA1_CBA 0x10c /* BA1_CAPTURE_BUFFER_ADDRESS */ | ||
1595 | #define BA1_CSRC 0x2c8 /* BA1_CAPTURE_SAMPLE_RATE_CORRECTION_REG */ | ||
1596 | #define BA1_CCI 0x2d8 /* BA1_CAPTURE_COEFFICIENT_INCREMENT_REG */ | ||
1597 | #define BA1_CD 0x2e0 /* BA1_CAPTURE_DELAY_REG */ | ||
1598 | #define BA1_CPI 0x2f4 /* BA1_CAPTURE_PHASE_INCREMENT_REG */ | ||
1599 | #define BA1_CVOL 0x2f8 /* BA1_CAPTURE_VOLUME_REG */ | ||
1600 | |||
1601 | #define BA1_CFG1 0x134 /* BA1_CAPTURE_FRAME_GROUP_1_REG */ | ||
1602 | #define BA1_CFG2 0x138 /* BA1_CAPTURE_FRAME_GROUP_2_REG */ | ||
1603 | #define BA1_CCST 0x13c /* BA1_CAPTURE_CONSTANT_REG */ | ||
1604 | #define BA1_CSPB 0x340 /* BA1_CAPTURE_SPB_ADDRESS */ | ||
1605 | |||
1606 | /* | ||
1607 | * | ||
1608 | */ | ||
1609 | |||
1610 | #define CS46XX_MODE_OUTPUT (1<<0) /* MIDI UART - output */ | ||
1611 | #define CS46XX_MODE_INPUT (1<<1) /* MIDI UART - input */ | ||
1612 | |||
1613 | /* | ||
1614 | * | ||
1615 | */ | ||
1616 | |||
1617 | #define SAVE_REG_MAX 0x10 | ||
1618 | #define POWER_DOWN_ALL 0x7f0f | ||
1619 | |||
1620 | /* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */ | ||
1621 | #define MAX_NR_AC97 4 | ||
1622 | #define CS46XX_PRIMARY_CODEC_INDEX 0 | ||
1623 | #define CS46XX_SECONDARY_CODEC_INDEX 1 | ||
1624 | #define CS46XX_SECONDARY_CODEC_OFFSET 0x80 | ||
1625 | #define CS46XX_DSP_CAPTURE_CHANNEL 1 | ||
1626 | |||
1627 | /* capture */ | ||
1628 | #define CS46XX_DSP_CAPTURE_CHANNEL 1 | ||
1629 | |||
1630 | /* mixer */ | ||
1631 | #define CS46XX_MIXER_SPDIF_INPUT_ELEMENT 1 | ||
1632 | #define CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT 2 | ||
1633 | |||
1634 | |||
1635 | struct snd_cs46xx_pcm { | ||
1636 | struct snd_dma_buffer hw_buf; | ||
1637 | |||
1638 | unsigned int ctl; | ||
1639 | unsigned int shift; /* Shift count to trasform frames in bytes */ | ||
1640 | struct snd_pcm_indirect pcm_rec; | ||
1641 | struct snd_pcm_substream *substream; | ||
1642 | |||
1643 | struct dsp_pcm_channel_descriptor * pcm_channel; | ||
1644 | |||
1645 | int pcm_channel_id; /* Fron Rear, Center Lfe ... */ | ||
1646 | }; | ||
1647 | |||
1648 | struct snd_cs46xx_region { | ||
1649 | char name[24]; | ||
1650 | unsigned long base; | ||
1651 | void __iomem *remap_addr; | ||
1652 | unsigned long size; | ||
1653 | struct resource *resource; | ||
1654 | }; | ||
1655 | |||
1656 | struct snd_cs46xx { | ||
1657 | int irq; | ||
1658 | unsigned long ba0_addr; | ||
1659 | unsigned long ba1_addr; | ||
1660 | union { | ||
1661 | struct { | ||
1662 | struct snd_cs46xx_region ba0; | ||
1663 | struct snd_cs46xx_region data0; | ||
1664 | struct snd_cs46xx_region data1; | ||
1665 | struct snd_cs46xx_region pmem; | ||
1666 | struct snd_cs46xx_region reg; | ||
1667 | } name; | ||
1668 | struct snd_cs46xx_region idx[5]; | ||
1669 | } region; | ||
1670 | |||
1671 | unsigned int mode; | ||
1672 | |||
1673 | struct { | ||
1674 | struct snd_dma_buffer hw_buf; | ||
1675 | |||
1676 | unsigned int ctl; | ||
1677 | unsigned int shift; /* Shift count to trasform frames in bytes */ | ||
1678 | struct snd_pcm_indirect pcm_rec; | ||
1679 | struct snd_pcm_substream *substream; | ||
1680 | } capt; | ||
1681 | |||
1682 | |||
1683 | int nr_ac97_codecs; | ||
1684 | struct snd_ac97_bus *ac97_bus; | ||
1685 | struct snd_ac97 *ac97[MAX_NR_AC97]; | ||
1686 | |||
1687 | struct pci_dev *pci; | ||
1688 | struct snd_card *card; | ||
1689 | struct snd_pcm *pcm; | ||
1690 | |||
1691 | struct snd_rawmidi *rmidi; | ||
1692 | struct snd_rawmidi_substream *midi_input; | ||
1693 | struct snd_rawmidi_substream *midi_output; | ||
1694 | |||
1695 | spinlock_t reg_lock; | ||
1696 | unsigned int midcr; | ||
1697 | unsigned int uartm; | ||
1698 | |||
1699 | int amplifier; | ||
1700 | void (*amplifier_ctrl)(struct snd_cs46xx *, int); | ||
1701 | void (*active_ctrl)(struct snd_cs46xx *, int); | ||
1702 | void (*mixer_init)(struct snd_cs46xx *); | ||
1703 | |||
1704 | int acpi_port; | ||
1705 | struct snd_kcontrol *eapd_switch; /* for amplifier hack */ | ||
1706 | int accept_valid; /* accept mmap valid (for OSS) */ | ||
1707 | int in_suspend; | ||
1708 | |||
1709 | struct gameport *gameport; | ||
1710 | |||
1711 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | ||
1712 | struct mutex spos_mutex; | ||
1713 | |||
1714 | struct dsp_spos_instance * dsp_spos_instance; | ||
1715 | |||
1716 | struct snd_pcm *pcm_rear; | ||
1717 | struct snd_pcm *pcm_center_lfe; | ||
1718 | struct snd_pcm *pcm_iec958; | ||
1719 | #else /* for compatibility */ | ||
1720 | struct snd_cs46xx_pcm *playback_pcm; | ||
1721 | unsigned int play_ctl; | ||
1722 | #endif | ||
1723 | |||
1724 | #ifdef CONFIG_PM | ||
1725 | u32 *saved_regs; | ||
1726 | #endif | ||
1727 | }; | ||
1728 | |||
1729 | int snd_cs46xx_create(struct snd_card *card, | ||
1730 | struct pci_dev *pci, | ||
1731 | int external_amp, int thinkpad, | ||
1732 | struct snd_cs46xx **rcodec); | ||
1733 | extern const struct dev_pm_ops snd_cs46xx_pm; | ||
1734 | |||
1735 | int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm); | ||
1736 | int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm); | ||
1737 | int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm); | ||
1738 | int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm); | ||
1739 | int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device); | ||
1740 | int snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rmidi); | ||
1741 | int snd_cs46xx_start_dsp(struct snd_cs46xx *chip); | ||
1742 | int snd_cs46xx_gameport(struct snd_cs46xx *chip); | ||
1743 | |||
1744 | #endif /* __SOUND_CS46XX_H */ | ||
diff --git a/sound/pci/cs46xx/cs46xx_dsp_scb_types.h b/sound/pci/cs46xx/cs46xx_dsp_scb_types.h new file mode 100644 index 000000000000..080857ad0ca2 --- /dev/null +++ b/sound/pci/cs46xx/cs46xx_dsp_scb_types.h | |||
@@ -0,0 +1,1213 @@ | |||
1 | /* | ||
2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards | ||
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 | * NOTE: comments are copy/paste from cwcemb80.lst | ||
22 | * provided by Tom Woller at Cirrus (my only | ||
23 | * documentation about the SP OS running inside | ||
24 | * the DSP) | ||
25 | */ | ||
26 | |||
27 | #ifndef __CS46XX_DSP_SCB_TYPES_H__ | ||
28 | #define __CS46XX_DSP_SCB_TYPES_H__ | ||
29 | |||
30 | #include <asm/byteorder.h> | ||
31 | |||
32 | #ifndef ___DSP_DUAL_16BIT_ALLOC | ||
33 | #if defined(__LITTLE_ENDIAN) | ||
34 | #define ___DSP_DUAL_16BIT_ALLOC(a,b) u16 a; u16 b; | ||
35 | #elif defined(__BIG_ENDIAN) | ||
36 | #define ___DSP_DUAL_16BIT_ALLOC(a,b) u16 b; u16 a; | ||
37 | #else | ||
38 | #error Not __LITTLE_ENDIAN and not __BIG_ENDIAN, then what ??? | ||
39 | #endif | ||
40 | #endif | ||
41 | |||
42 | /* This structs are used internally by the SP */ | ||
43 | |||
44 | struct dsp_basic_dma_req { | ||
45 | /* DMA Requestor Word 0 (DCW) fields: | ||
46 | |||
47 | 31 [30-28]27 [26:24] 23 22 21 20 [19:18] [17:16] 15 14 13 12 11 10 9 8 7 6 [5:0] | ||
48 | _______________________________________________________________________________________ | ||
49 | |S| SBT |D| DBT |wb|wb| | | LS | SS |Opt|Do|SSG|DSG| | | | | | | Dword | | ||
50 | |H|_____ |H|_________|S_|D |__|__|______|_______|___|ne|__ |__ |__|__|_|_|_|_|_Count -1| | ||
51 | */ | ||
52 | u32 dcw; /* DMA Control Word */ | ||
53 | u32 dmw; /* DMA Mode Word */ | ||
54 | u32 saw; /* Source Address Word */ | ||
55 | u32 daw; /* Destination Address Word */ | ||
56 | }; | ||
57 | |||
58 | struct dsp_scatter_gather_ext { | ||
59 | u32 npaw; /* Next-Page Address Word */ | ||
60 | |||
61 | /* DMA Requestor Word 5 (NPCW) fields: | ||
62 | |||
63 | 31-30 29 28 [27:16] [15:12] [11:3] [2:0] | ||
64 | _________________________________________________________________________________________ | ||
65 | |SV |LE|SE| Sample-end byte offset | | Page-map entry offset for next | | | ||
66 | |page|__|__| ___________________________|_________|__page, if !sample-end___________|____| | ||
67 | */ | ||
68 | u32 npcw; /* Next-Page Control Word */ | ||
69 | u32 lbaw; /* Loop-Begin Address Word */ | ||
70 | u32 nplbaw; /* Next-Page after Loop-Begin Address Word */ | ||
71 | u32 sgaw; /* Scatter/Gather Address Word */ | ||
72 | }; | ||
73 | |||
74 | struct dsp_volume_control { | ||
75 | ___DSP_DUAL_16BIT_ALLOC( | ||
76 | rightTarg, /* Target volume for left & right channels */ | ||
77 | leftTarg | ||
78 | ) | ||
79 | ___DSP_DUAL_16BIT_ALLOC( | ||
80 | rightVol, /* Current left & right channel volumes */ | ||
81 | leftVol | ||
82 | ) | ||
83 | }; | ||
84 | |||
85 | /* Generic stream control block (SCB) structure definition */ | ||
86 | struct dsp_generic_scb { | ||
87 | /* For streaming I/O, the DSP should never alter any words in the DMA | ||
88 | requestor or the scatter/gather extension. Only ad hoc DMA request | ||
89 | streams are free to alter the requestor (currently only occur in the | ||
90 | DOS-based MIDI controller and in debugger-inserted code). | ||
91 | |||
92 | If an SCB does not have any associated DMA requestor, these 9 ints | ||
93 | may be freed for use by other tasks, but the pointer to the SCB must | ||
94 | still be such that the insOrd:nextSCB appear at offset 9 from the | ||
95 | SCB pointer. | ||
96 | |||
97 | Basic (non scatter/gather) DMA requestor (4 ints) | ||
98 | */ | ||
99 | |||
100 | /* Initialized by the host, only modified by DMA | ||
101 | R/O for the DSP task */ | ||
102 | struct dsp_basic_dma_req basic_req; /* Optional */ | ||
103 | |||
104 | /* Scatter/gather DMA requestor extension (5 ints) | ||
105 | Initialized by the host, only modified by DMA | ||
106 | DSP task never needs to even read these. | ||
107 | */ | ||
108 | struct dsp_scatter_gather_ext sg_ext; /* Optional */ | ||
109 | |||
110 | /* Sublist pointer & next stream control block (SCB) link. | ||
111 | Initialized & modified by the host R/O for the DSP task | ||
112 | */ | ||
113 | ___DSP_DUAL_16BIT_ALLOC( | ||
114 | next_scb, /* REQUIRED */ | ||
115 | sub_list_ptr /* REQUIRED */ | ||
116 | ) | ||
117 | |||
118 | /* Pointer to this tasks parameter block & stream function pointer | ||
119 | Initialized by the host R/O for the DSP task */ | ||
120 | ___DSP_DUAL_16BIT_ALLOC( | ||
121 | entry_point, /* REQUIRED */ | ||
122 | this_spb /* REQUIRED */ | ||
123 | ) | ||
124 | |||
125 | /* rsConfig register for stream buffer (rsDMA reg. | ||
126 | is loaded from basicReq.daw for incoming streams, or | ||
127 | basicReq.saw, for outgoing streams) | ||
128 | |||
129 | 31 30 29 [28:24] [23:16] 15 14 13 12 11 10 9 8 7 6 5 4 [3:0] | ||
130 | ______________________________________________________________________________ | ||
131 | |DMA |D|maxDMAsize| streamNum|dir|p| | | | | | |ds |shr 1|rev Cy | mod | | ||
132 | |prio |_|__________|__________|___|_|__|__|__|__|_|_|___|_____|_______|_______| | ||
133 | 31 30 29 [28:24] [23:16] 15 14 13 12 11 10 9 8 7 6 5 4 [3:0] | ||
134 | |||
135 | |||
136 | Initialized by the host R/O for the DSP task | ||
137 | */ | ||
138 | u32 strm_rs_config; /* REQUIRED */ | ||
139 | // | ||
140 | /* On mixer input streams: indicates mixer input stream configuration | ||
141 | On Tees, this is copied from the stream being snooped | ||
142 | |||
143 | Stream sample pointer & MAC-unit mode for this stream | ||
144 | |||
145 | Initialized by the host Updated by the DSP task | ||
146 | */ | ||
147 | u32 strm_buf_ptr; /* REQUIRED */ | ||
148 | |||
149 | /* On mixer input streams: points to next mixer input and is updated by the | ||
150 | mixer subroutine in the "parent" DSP task | ||
151 | (least-significant 16 bits are preserved, unused) | ||
152 | |||
153 | On Tees, the pointer is copied from the stream being snooped on | ||
154 | initialization, and, subsequently, it is copied into the | ||
155 | stream being snooped. | ||
156 | |||
157 | On wavetable/3D voices: the strmBufPtr will use all 32 bits to allow for | ||
158 | fractional phase accumulation | ||
159 | |||
160 | Fractional increment per output sample in the input sample buffer | ||
161 | |||
162 | (Not used on mixer input streams & redefined on Tees) | ||
163 | On wavetable/3D voices: this 32-bit word specifies the integer.fractional | ||
164 | increment per output sample. | ||
165 | */ | ||
166 | u32 strmPhiIncr; | ||
167 | |||
168 | |||
169 | /* Standard stereo volume control | ||
170 | Initialized by the host (host updates target volumes) | ||
171 | |||
172 | Current volumes update by the DSP task | ||
173 | On mixer input streams: required & updated by the mixer subroutine in the | ||
174 | "parent" DSP task | ||
175 | |||
176 | On Tees, both current & target volumes are copied up on initialization, | ||
177 | and, subsequently, the target volume is copied up while the current | ||
178 | volume is copied down. | ||
179 | |||
180 | These two 32-bit words are redefined for wavetable & 3-D voices. | ||
181 | */ | ||
182 | struct dsp_volume_control vol_ctrl_t; /* Optional */ | ||
183 | }; | ||
184 | |||
185 | |||
186 | struct dsp_spos_control_block { | ||
187 | /* WARNING: Certain items in this structure are modified by the host | ||
188 | Any dword that can be modified by the host, must not be | ||
189 | modified by the SP as the host can only do atomic dword | ||
190 | writes, and to do otherwise, even a read modify write, | ||
191 | may lead to corrupted data on the SP. | ||
192 | |||
193 | This rule does not apply to one off boot time initialisation prior to starting the SP | ||
194 | */ | ||
195 | |||
196 | |||
197 | ___DSP_DUAL_16BIT_ALLOC( | ||
198 | /* First element on the Hyper forground task tree */ | ||
199 | hfg_tree_root_ptr, /* HOST */ | ||
200 | /* First 3 dwords are written by the host and read-only on the DSP */ | ||
201 | hfg_stack_base /* HOST */ | ||
202 | ) | ||
203 | |||
204 | ___DSP_DUAL_16BIT_ALLOC( | ||
205 | /* Point to this data structure to enable easy access */ | ||
206 | spos_cb_ptr, /* SP */ | ||
207 | prev_task_tree_ptr /* SP && HOST */ | ||
208 | ) | ||
209 | |||
210 | ___DSP_DUAL_16BIT_ALLOC( | ||
211 | /* Currently Unused */ | ||
212 | xxinterval_timer_period, | ||
213 | /* Enable extension of SPOS data structure */ | ||
214 | HFGSPB_ptr | ||
215 | ) | ||
216 | |||
217 | |||
218 | ___DSP_DUAL_16BIT_ALLOC( | ||
219 | xxnum_HFG_ticks_thisInterval, | ||
220 | /* Modified by the DSP */ | ||
221 | xxnum_tntervals | ||
222 | ) | ||
223 | |||
224 | |||
225 | /* Set by DSP upon encountering a trap (breakpoint) or a spurious | ||
226 | interrupt. The host must clear this dword after reading it | ||
227 | upon receiving spInt1. */ | ||
228 | ___DSP_DUAL_16BIT_ALLOC( | ||
229 | spurious_int_flag, /* (Host & SP) Nature of the spurious interrupt */ | ||
230 | trap_flag /* (Host & SP) Nature of detected Trap */ | ||
231 | ) | ||
232 | |||
233 | ___DSP_DUAL_16BIT_ALLOC( | ||
234 | unused2, | ||
235 | invalid_IP_flag /* (Host & SP ) Indicate detection of invalid instruction pointer */ | ||
236 | ) | ||
237 | |||
238 | ___DSP_DUAL_16BIT_ALLOC( | ||
239 | /* pointer to forground task tree header for use in next task search */ | ||
240 | fg_task_tree_hdr_ptr, /* HOST */ | ||
241 | /* Data structure for controlling synchronous link update */ | ||
242 | hfg_sync_update_ptr /* HOST */ | ||
243 | ) | ||
244 | |||
245 | ___DSP_DUAL_16BIT_ALLOC( | ||
246 | begin_foreground_FCNT, /* SP */ | ||
247 | /* Place holder for holding sleep timing */ | ||
248 | last_FCNT_before_sleep /* SP */ | ||
249 | ) | ||
250 | |||
251 | ___DSP_DUAL_16BIT_ALLOC( | ||
252 | unused7, /* SP */ | ||
253 | next_task_treePtr /* SP */ | ||
254 | ) | ||
255 | |||
256 | u32 unused5; | ||
257 | |||
258 | ___DSP_DUAL_16BIT_ALLOC( | ||
259 | active_flags, /* SP */ | ||
260 | /* State flags, used to assist control of execution of Hyper Forground */ | ||
261 | HFG_flags /* SP */ | ||
262 | ) | ||
263 | |||
264 | ___DSP_DUAL_16BIT_ALLOC( | ||
265 | unused9, | ||
266 | unused8 | ||
267 | ) | ||
268 | |||
269 | /* Space for saving enough context so that we can set up enough | ||
270 | to save some more context. | ||
271 | */ | ||
272 | u32 rFE_save_for_invalid_IP; | ||
273 | u32 r32_save_for_spurious_int; | ||
274 | u32 r32_save_for_trap; | ||
275 | u32 r32_save_for_HFG; | ||
276 | }; | ||
277 | |||
278 | /* SPB for MIX_TO_OSTREAM algorithm family */ | ||
279 | struct dsp_mix2_ostream_spb | ||
280 | { | ||
281 | /* 16b.16b integer.frac approximation to the | ||
282 | number of 3 sample triplets to output each | ||
283 | frame. (approximation must be floor, to | ||
284 | insure that the fractional error is always | ||
285 | positive) | ||
286 | */ | ||
287 | u32 outTripletsPerFrame; | ||
288 | |||
289 | /* 16b.16b integer.frac accumulated number of | ||
290 | output triplets since the start of group | ||
291 | */ | ||
292 | u32 accumOutTriplets; | ||
293 | }; | ||
294 | |||
295 | /* SCB for Timing master algorithm */ | ||
296 | struct dsp_timing_master_scb { | ||
297 | /* First 12 dwords from generic_scb_t */ | ||
298 | struct dsp_basic_dma_req basic_req; /* Optional */ | ||
299 | struct dsp_scatter_gather_ext sg_ext; /* Optional */ | ||
300 | ___DSP_DUAL_16BIT_ALLOC( | ||
301 | next_scb, /* REQUIRED */ | ||
302 | sub_list_ptr /* REQUIRED */ | ||
303 | ) | ||
304 | |||
305 | ___DSP_DUAL_16BIT_ALLOC( | ||
306 | entry_point, /* REQUIRED */ | ||
307 | this_spb /* REQUIRED */ | ||
308 | ) | ||
309 | |||
310 | ___DSP_DUAL_16BIT_ALLOC( | ||
311 | /* Initial values are 0000:xxxx */ | ||
312 | reserved, | ||
313 | extra_sample_accum | ||
314 | ) | ||
315 | |||
316 | |||
317 | /* Initial values are xxxx:0000 | ||
318 | hi: Current CODEC output FIFO pointer | ||
319 | (0 to 0x0f) | ||
320 | lo: Flag indicating that the CODEC | ||
321 | FIFO is sync'd (host clears to | ||
322 | resynchronize the FIFO pointer | ||
323 | upon start/restart) | ||
324 | */ | ||
325 | ___DSP_DUAL_16BIT_ALLOC( | ||
326 | codec_FIFO_syncd, | ||
327 | codec_FIFO_ptr | ||
328 | ) | ||
329 | |||
330 | /* Init. 8000:0005 for 44.1k | ||
331 | 8000:0001 for 48k | ||
332 | hi: Fractional sample accumulator 0.16b | ||
333 | lo: Number of frames remaining to be | ||
334 | processed in the current group of | ||
335 | frames | ||
336 | */ | ||
337 | ___DSP_DUAL_16BIT_ALLOC( | ||
338 | frac_samp_accum_qm1, | ||
339 | TM_frms_left_in_group | ||
340 | ) | ||
341 | |||
342 | /* Init. 0001:0005 for 44.1k | ||
343 | 0000:0001 for 48k | ||
344 | hi: Fractional sample correction factor 0.16b | ||
345 | to be added every frameGroupLength frames | ||
346 | to correct for truncation error in | ||
347 | nsamp_per_frm_q15 | ||
348 | lo: Number of frames in the group | ||
349 | */ | ||
350 | ___DSP_DUAL_16BIT_ALLOC( | ||
351 | frac_samp_correction_qm1, | ||
352 | TM_frm_group_length | ||
353 | ) | ||
354 | |||
355 | /* Init. 44.1k*65536/8k = 0x00058333 for 44.1k | ||
356 | 48k*65536/8k = 0x00060000 for 48k | ||
357 | 16b.16b integer.frac approximation to the | ||
358 | number of samples to output each frame. | ||
359 | (approximation must be floor, to insure */ | ||
360 | u32 nsamp_per_frm_q15; | ||
361 | }; | ||
362 | |||
363 | /* SCB for CODEC output algorithm */ | ||
364 | struct dsp_codec_output_scb { | ||
365 | /* First 13 dwords from generic_scb_t */ | ||
366 | struct dsp_basic_dma_req basic_req; /* Optional */ | ||
367 | struct dsp_scatter_gather_ext sg_ext; /* Optional */ | ||
368 | ___DSP_DUAL_16BIT_ALLOC( | ||
369 | next_scb, /* REQUIRED */ | ||
370 | sub_list_ptr /* REQUIRED */ | ||
371 | ) | ||
372 | |||
373 | ___DSP_DUAL_16BIT_ALLOC( | ||
374 | entry_point, /* REQUIRED */ | ||
375 | this_spb /* REQUIRED */ | ||
376 | ) | ||
377 | |||
378 | u32 strm_rs_config; /* REQUIRED */ | ||
379 | |||
380 | u32 strm_buf_ptr; /* REQUIRED */ | ||
381 | |||
382 | /* NOTE: The CODEC output task reads samples from the first task on its | ||
383 | sublist at the stream buffer pointer (init. to lag DMA destination | ||
384 | address word). After the required number of samples is transferred, | ||
385 | the CODEC output task advances sub_list_ptr->strm_buf_ptr past the samples | ||
386 | consumed. | ||
387 | */ | ||
388 | |||
389 | /* Init. 0000:0010 for SDout | ||
390 | 0060:0010 for SDout2 | ||
391 | 0080:0010 for SDout3 | ||
392 | hi: Base IO address of FIFO to which | ||
393 | the left-channel samples are to | ||
394 | be written. | ||
395 | lo: Displacement for the base IO | ||
396 | address for left-channel to obtain | ||
397 | the base IO address for the FIFO | ||
398 | to which the right-channel samples | ||
399 | are to be written. | ||
400 | */ | ||
401 | ___DSP_DUAL_16BIT_ALLOC( | ||
402 | left_chan_base_IO_addr, | ||
403 | right_chan_IO_disp | ||
404 | ) | ||
405 | |||
406 | |||
407 | /* Init: 0x0080:0004 for non-AC-97 | ||
408 | Init: 0x0080:0000 for AC-97 | ||
409 | hi: Exponential volume change rate | ||
410 | for input stream | ||
411 | lo: Positive shift count to shift the | ||
412 | 16-bit input sample to obtain the | ||
413 | 32-bit output word | ||
414 | */ | ||
415 | ___DSP_DUAL_16BIT_ALLOC( | ||
416 | CO_scale_shift_count, | ||
417 | CO_exp_vol_change_rate | ||
418 | ) | ||
419 | |||
420 | /* Pointer to SCB at end of input chain */ | ||
421 | ___DSP_DUAL_16BIT_ALLOC( | ||
422 | reserved, | ||
423 | last_sub_ptr | ||
424 | ) | ||
425 | }; | ||
426 | |||
427 | /* SCB for CODEC input algorithm */ | ||
428 | struct dsp_codec_input_scb { | ||
429 | /* First 13 dwords from generic_scb_t */ | ||
430 | struct dsp_basic_dma_req basic_req; /* Optional */ | ||
431 | struct dsp_scatter_gather_ext sg_ext; /* Optional */ | ||
432 | ___DSP_DUAL_16BIT_ALLOC( | ||
433 | next_scb, /* REQUIRED */ | ||
434 | sub_list_ptr /* REQUIRED */ | ||
435 | ) | ||
436 | |||
437 | ___DSP_DUAL_16BIT_ALLOC( | ||
438 | entry_point, /* REQUIRED */ | ||
439 | this_spb /* REQUIRED */ | ||
440 | ) | ||
441 | |||
442 | u32 strm_rs_config; /* REQUIRED */ | ||
443 | u32 strm_buf_ptr; /* REQUIRED */ | ||
444 | |||
445 | /* NOTE: The CODEC input task reads samples from the hardware FIFO | ||
446 | sublist at the DMA source address word (sub_list_ptr->basic_req.saw). | ||
447 | After the required number of samples is transferred, the CODEC | ||
448 | output task advances sub_list_ptr->basic_req.saw past the samples | ||
449 | consumed. SPuD must initialize the sub_list_ptr->basic_req.saw | ||
450 | to point half-way around from the initial sub_list_ptr->strm_nuf_ptr | ||
451 | to allow for lag/lead. | ||
452 | */ | ||
453 | |||
454 | /* Init. 0000:0010 for SDout | ||
455 | 0060:0010 for SDout2 | ||
456 | 0080:0010 for SDout3 | ||
457 | hi: Base IO address of FIFO to which | ||
458 | the left-channel samples are to | ||
459 | be written. | ||
460 | lo: Displacement for the base IO | ||
461 | address for left-channel to obtain | ||
462 | the base IO address for the FIFO | ||
463 | to which the right-channel samples | ||
464 | are to be written. | ||
465 | */ | ||
466 | ___DSP_DUAL_16BIT_ALLOC( | ||
467 | rightChanINdisp, | ||
468 | left_chan_base_IN_addr | ||
469 | ) | ||
470 | /* Init. ?:fffc | ||
471 | lo: Negative shift count to shift the | ||
472 | 32-bit input dword to obtain the | ||
473 | 16-bit sample msb-aligned (count | ||
474 | is negative to shift left) | ||
475 | */ | ||
476 | ___DSP_DUAL_16BIT_ALLOC( | ||
477 | scaleShiftCount, | ||
478 | reserver1 | ||
479 | ) | ||
480 | |||
481 | u32 reserved2; | ||
482 | }; | ||
483 | |||
484 | |||
485 | struct dsp_pcm_serial_input_scb { | ||
486 | /* First 13 dwords from generic_scb_t */ | ||
487 | struct dsp_basic_dma_req basic_req; /* Optional */ | ||
488 | struct dsp_scatter_gather_ext sg_ext; /* Optional */ | ||
489 | ___DSP_DUAL_16BIT_ALLOC( | ||
490 | next_scb, /* REQUIRED */ | ||
491 | sub_list_ptr /* REQUIRED */ | ||
492 | ) | ||
493 | |||
494 | ___DSP_DUAL_16BIT_ALLOC( | ||
495 | entry_point, /* REQUIRED */ | ||
496 | this_spb /* REQUIRED */ | ||
497 | ) | ||
498 | |||
499 | u32 strm_buf_ptr; /* REQUIRED */ | ||
500 | u32 strm_rs_config; /* REQUIRED */ | ||
501 | |||
502 | /* Init. Ptr to CODEC input SCB | ||
503 | hi: Pointer to the SCB containing the | ||
504 | input buffer to which CODEC input | ||
505 | samples are written | ||
506 | lo: Flag indicating the link to the CODEC | ||
507 | input task is to be initialized | ||
508 | */ | ||
509 | ___DSP_DUAL_16BIT_ALLOC( | ||
510 | init_codec_input_link, | ||
511 | codec_input_buf_scb | ||
512 | ) | ||
513 | |||
514 | /* Initialized by the host (host updates target volumes) */ | ||
515 | struct dsp_volume_control psi_vol_ctrl; | ||
516 | |||
517 | }; | ||
518 | |||
519 | struct dsp_src_task_scb { | ||
520 | ___DSP_DUAL_16BIT_ALLOC( | ||
521 | frames_left_in_gof, | ||
522 | gofs_left_in_sec | ||
523 | ) | ||
524 | |||
525 | ___DSP_DUAL_16BIT_ALLOC( | ||
526 | const2_thirds, | ||
527 | num_extra_tnput_samples | ||
528 | ) | ||
529 | |||
530 | ___DSP_DUAL_16BIT_ALLOC( | ||
531 | cor_per_gof, | ||
532 | correction_per_sec | ||
533 | ) | ||
534 | |||
535 | ___DSP_DUAL_16BIT_ALLOC( | ||
536 | output_buf_producer_ptr, | ||
537 | junk_DMA_MID | ||
538 | ) | ||
539 | |||
540 | ___DSP_DUAL_16BIT_ALLOC( | ||
541 | gof_length, | ||
542 | gofs_per_sec | ||
543 | ) | ||
544 | |||
545 | u32 input_buf_strm_config; | ||
546 | |||
547 | ___DSP_DUAL_16BIT_ALLOC( | ||
548 | reserved_for_SRC_use, | ||
549 | input_buf_consumer_ptr | ||
550 | ) | ||
551 | |||
552 | u32 accum_phi; | ||
553 | |||
554 | ___DSP_DUAL_16BIT_ALLOC( | ||
555 | exp_src_vol_change_rate, | ||
556 | input_buf_producer_ptr | ||
557 | ) | ||
558 | |||
559 | ___DSP_DUAL_16BIT_ALLOC( | ||
560 | src_next_scb, | ||
561 | src_sub_list_ptr | ||
562 | ) | ||
563 | |||
564 | ___DSP_DUAL_16BIT_ALLOC( | ||
565 | src_entry_point, | ||
566 | src_this_sbp | ||
567 | ) | ||
568 | |||
569 | u32 src_strm_rs_config; | ||
570 | u32 src_strm_buf_ptr; | ||
571 | |||
572 | u32 phiIncr6int_26frac; | ||
573 | |||
574 | struct dsp_volume_control src_vol_ctrl; | ||
575 | }; | ||
576 | |||
577 | struct dsp_decimate_by_pow2_scb { | ||
578 | /* decimationFactor = 2, 4, or 8 (larger factors waste too much memory | ||
579 | when compared to cascading decimators) | ||
580 | */ | ||
581 | ___DSP_DUAL_16BIT_ALLOC( | ||
582 | dec2_coef_base_ptr, | ||
583 | dec2_coef_increment | ||
584 | ) | ||
585 | |||
586 | /* coefIncrement = 128 / decimationFactor (for our ROM filter) | ||
587 | coefBasePtr = 0x8000 (for our ROM filter) | ||
588 | */ | ||
589 | ___DSP_DUAL_16BIT_ALLOC( | ||
590 | dec2_in_samples_per_out_triplet, | ||
591 | dec2_extra_in_samples | ||
592 | ) | ||
593 | /* extraInSamples: # of accumulated, unused input samples (init. to 0) | ||
594 | inSamplesPerOutTriplet = 3 * decimationFactor | ||
595 | */ | ||
596 | |||
597 | ___DSP_DUAL_16BIT_ALLOC( | ||
598 | dec2_const2_thirds, | ||
599 | dec2_half_num_taps_mp5 | ||
600 | ) | ||
601 | /* halfNumTapsM5: (1/2 number of taps in decimation filter) minus 5 | ||
602 | const2thirds: constant 2/3 in 16Q0 format (sign.15) | ||
603 | */ | ||
604 | |||
605 | ___DSP_DUAL_16BIT_ALLOC( | ||
606 | dec2_output_buf_producer_ptr, | ||
607 | dec2_junkdma_mid | ||
608 | ) | ||
609 | |||
610 | u32 dec2_reserved2; | ||
611 | |||
612 | u32 dec2_input_nuf_strm_config; | ||
613 | /* inputBufStrmConfig: rsConfig for the input buffer to the decimator | ||
614 | (buffer size = decimationFactor * 32 dwords) | ||
615 | */ | ||
616 | |||
617 | ___DSP_DUAL_16BIT_ALLOC( | ||
618 | dec2_phi_incr, | ||
619 | dec2_input_buf_consumer_ptr | ||
620 | ) | ||
621 | /* inputBufConsumerPtr: Input buffer read pointer (into SRC filter) | ||
622 | phiIncr = decimationFactor * 4 | ||
623 | */ | ||
624 | |||
625 | u32 dec2_reserved3; | ||
626 | |||
627 | ___DSP_DUAL_16BIT_ALLOC( | ||
628 | dec2_exp_vol_change_rate, | ||
629 | dec2_input_buf_producer_ptr | ||
630 | ) | ||
631 | /* inputBufProducerPtr: Input buffer write pointer | ||
632 | expVolChangeRate: Exponential volume change rate for possible | ||
633 | future mixer on input streams | ||
634 | */ | ||
635 | |||
636 | ___DSP_DUAL_16BIT_ALLOC( | ||
637 | dec2_next_scb, | ||
638 | dec2_sub_list_ptr | ||
639 | ) | ||
640 | |||
641 | ___DSP_DUAL_16BIT_ALLOC( | ||
642 | dec2_entry_point, | ||
643 | dec2_this_spb | ||
644 | ) | ||
645 | |||
646 | u32 dec2_strm_rs_config; | ||
647 | u32 dec2_strm_buf_ptr; | ||
648 | |||
649 | u32 dec2_reserved4; | ||
650 | |||
651 | struct dsp_volume_control dec2_vol_ctrl; /* Not used! */ | ||
652 | }; | ||
653 | |||
654 | struct dsp_vari_decimate_scb { | ||
655 | ___DSP_DUAL_16BIT_ALLOC( | ||
656 | vdec_frames_left_in_gof, | ||
657 | vdec_gofs_left_in_sec | ||
658 | ) | ||
659 | |||
660 | ___DSP_DUAL_16BIT_ALLOC( | ||
661 | vdec_const2_thirds, | ||
662 | vdec_extra_in_samples | ||
663 | ) | ||
664 | /* extraInSamples: # of accumulated, unused input samples (init. to 0) | ||
665 | const2thirds: constant 2/3 in 16Q0 format (sign.15) */ | ||
666 | |||
667 | ___DSP_DUAL_16BIT_ALLOC( | ||
668 | vdec_cor_per_gof, | ||
669 | vdec_correction_per_sec | ||
670 | ) | ||
671 | |||
672 | ___DSP_DUAL_16BIT_ALLOC( | ||
673 | vdec_output_buf_producer_ptr, | ||
674 | vdec_input_buf_consumer_ptr | ||
675 | ) | ||
676 | /* inputBufConsumerPtr: Input buffer read pointer (into SRC filter) */ | ||
677 | ___DSP_DUAL_16BIT_ALLOC( | ||
678 | vdec_gof_length, | ||
679 | vdec_gofs_per_sec | ||
680 | ) | ||
681 | |||
682 | u32 vdec_input_buf_strm_config; | ||
683 | /* inputBufStrmConfig: rsConfig for the input buffer to the decimator | ||
684 | (buffer size = 64 dwords) */ | ||
685 | u32 vdec_coef_increment; | ||
686 | /* coefIncrement = - 128.0 / decimationFactor (as a 32Q15 number) */ | ||
687 | |||
688 | u32 vdec_accumphi; | ||
689 | /* accumPhi: accumulated fractional phase increment (6.26) */ | ||
690 | |||
691 | ___DSP_DUAL_16BIT_ALLOC( | ||
692 | vdec_exp_vol_change_rate, | ||
693 | vdec_input_buf_producer_ptr | ||
694 | ) | ||
695 | /* inputBufProducerPtr: Input buffer write pointer | ||
696 | expVolChangeRate: Exponential volume change rate for possible | ||
697 | future mixer on input streams */ | ||
698 | |||
699 | ___DSP_DUAL_16BIT_ALLOC( | ||
700 | vdec_next_scb, | ||
701 | vdec_sub_list_ptr | ||
702 | ) | ||
703 | |||
704 | ___DSP_DUAL_16BIT_ALLOC( | ||
705 | vdec_entry_point, | ||
706 | vdec_this_spb | ||
707 | ) | ||
708 | |||
709 | u32 vdec_strm_rs_config; | ||
710 | u32 vdec_strm_buf_ptr; | ||
711 | |||
712 | u32 vdec_phi_incr_6int_26frac; | ||
713 | |||
714 | struct dsp_volume_control vdec_vol_ctrl; | ||
715 | }; | ||
716 | |||
717 | |||
718 | /* SCB for MIX_TO_OSTREAM algorithm family */ | ||
719 | struct dsp_mix2_ostream_scb { | ||
720 | /* First 13 dwords from generic_scb_t */ | ||
721 | struct dsp_basic_dma_req basic_req; /* Optional */ | ||
722 | struct dsp_scatter_gather_ext sg_ext; /* Optional */ | ||
723 | ___DSP_DUAL_16BIT_ALLOC( | ||
724 | next_scb, /* REQUIRED */ | ||
725 | sub_list_ptr /* REQUIRED */ | ||
726 | ) | ||
727 | |||
728 | ___DSP_DUAL_16BIT_ALLOC( | ||
729 | entry_point, /* REQUIRED */ | ||
730 | this_spb /* REQUIRED */ | ||
731 | ) | ||
732 | |||
733 | u32 strm_rs_config; /* REQUIRED */ | ||
734 | u32 strm_buf_ptr; /* REQUIRED */ | ||
735 | |||
736 | |||
737 | /* hi: Number of mixed-down input triplets | ||
738 | computed since start of group | ||
739 | lo: Number of frames remaining to be | ||
740 | processed in the current group of | ||
741 | frames | ||
742 | */ | ||
743 | ___DSP_DUAL_16BIT_ALLOC( | ||
744 | frames_left_in_group, | ||
745 | accum_input_triplets | ||
746 | ) | ||
747 | |||
748 | /* hi: Exponential volume change rate | ||
749 | for mixer on input streams | ||
750 | lo: Number of frames in the group | ||
751 | */ | ||
752 | ___DSP_DUAL_16BIT_ALLOC( | ||
753 | frame_group_length, | ||
754 | exp_vol_change_rate | ||
755 | ) | ||
756 | |||
757 | ___DSP_DUAL_16BIT_ALLOC( | ||
758 | const_FFFF, | ||
759 | const_zero | ||
760 | ) | ||
761 | }; | ||
762 | |||
763 | |||
764 | /* SCB for S16_MIX algorithm */ | ||
765 | struct dsp_mix_only_scb { | ||
766 | /* First 13 dwords from generic_scb_t */ | ||
767 | struct dsp_basic_dma_req basic_req; /* Optional */ | ||
768 | struct dsp_scatter_gather_ext sg_ext; /* Optional */ | ||
769 | ___DSP_DUAL_16BIT_ALLOC( | ||
770 | next_scb, /* REQUIRED */ | ||
771 | sub_list_ptr /* REQUIRED */ | ||
772 | ) | ||
773 | |||
774 | ___DSP_DUAL_16BIT_ALLOC( | ||
775 | entry_point, /* REQUIRED */ | ||
776 | this_spb /* REQUIRED */ | ||
777 | ) | ||
778 | |||
779 | u32 strm_rs_config; /* REQUIRED */ | ||
780 | u32 strm_buf_ptr; /* REQUIRED */ | ||
781 | |||
782 | u32 reserved; | ||
783 | struct dsp_volume_control vol_ctrl; | ||
784 | }; | ||
785 | |||
786 | /* SCB for the async. CODEC input algorithm */ | ||
787 | struct dsp_async_codec_input_scb { | ||
788 | u32 io_free2; | ||
789 | |||
790 | u32 io_current_total; | ||
791 | u32 io_previous_total; | ||
792 | |||
793 | u16 io_count; | ||
794 | u16 io_count_limit; | ||
795 | |||
796 | u16 o_fifo_base_addr; | ||
797 | u16 ost_mo_format; | ||
798 | /* 1 = stereo; 0 = mono | ||
799 | xxx for ASER 1 (not allowed); 118 for ASER2 */ | ||
800 | |||
801 | u32 ostrm_rs_config; | ||
802 | u32 ostrm_buf_ptr; | ||
803 | |||
804 | ___DSP_DUAL_16BIT_ALLOC( | ||
805 | io_sclks_per_lr_clk, | ||
806 | io_io_enable | ||
807 | ) | ||
808 | |||
809 | u32 io_free4; | ||
810 | |||
811 | ___DSP_DUAL_16BIT_ALLOC( | ||
812 | io_next_scb, | ||
813 | io_sub_list_ptr | ||
814 | ) | ||
815 | |||
816 | ___DSP_DUAL_16BIT_ALLOC( | ||
817 | io_entry_point, | ||
818 | io_this_spb | ||
819 | ) | ||
820 | |||
821 | u32 istrm_rs_config; | ||
822 | u32 istrm_buf_ptr; | ||
823 | |||
824 | /* Init. 0000:8042: for ASER1 | ||
825 | 0000:8044: for ASER2 */ | ||
826 | ___DSP_DUAL_16BIT_ALLOC( | ||
827 | io_stat_reg_addr, | ||
828 | iofifo_pointer | ||
829 | ) | ||
830 | |||
831 | /* Init 1 stero:100 ASER1 | ||
832 | Init 0 mono:110 ASER2 | ||
833 | */ | ||
834 | ___DSP_DUAL_16BIT_ALLOC( | ||
835 | ififo_base_addr, | ||
836 | ist_mo_format | ||
837 | ) | ||
838 | |||
839 | u32 i_free; | ||
840 | }; | ||
841 | |||
842 | |||
843 | /* SCB for the SP/DIF CODEC input and output */ | ||
844 | struct dsp_spdifiscb { | ||
845 | ___DSP_DUAL_16BIT_ALLOC( | ||
846 | status_ptr, | ||
847 | status_start_ptr | ||
848 | ) | ||
849 | |||
850 | u32 current_total; | ||
851 | u32 previous_total; | ||
852 | |||
853 | ___DSP_DUAL_16BIT_ALLOC( | ||
854 | count, | ||
855 | count_limit | ||
856 | ) | ||
857 | |||
858 | u32 status_data; | ||
859 | |||
860 | ___DSP_DUAL_16BIT_ALLOC( | ||
861 | status, | ||
862 | free4 | ||
863 | ) | ||
864 | |||
865 | u32 free3; | ||
866 | |||
867 | ___DSP_DUAL_16BIT_ALLOC( | ||
868 | free2, | ||
869 | bit_count | ||
870 | ) | ||
871 | |||
872 | u32 temp_status; | ||
873 | |||
874 | ___DSP_DUAL_16BIT_ALLOC( | ||
875 | next_SCB, | ||
876 | sub_list_ptr | ||
877 | ) | ||
878 | |||
879 | ___DSP_DUAL_16BIT_ALLOC( | ||
880 | entry_point, | ||
881 | this_spb | ||
882 | ) | ||
883 | |||
884 | u32 strm_rs_config; | ||
885 | u32 strm_buf_ptr; | ||
886 | |||
887 | ___DSP_DUAL_16BIT_ALLOC( | ||
888 | stat_reg_addr, | ||
889 | fifo_pointer | ||
890 | ) | ||
891 | |||
892 | ___DSP_DUAL_16BIT_ALLOC( | ||
893 | fifo_base_addr, | ||
894 | st_mo_format | ||
895 | ) | ||
896 | |||
897 | u32 free1; | ||
898 | }; | ||
899 | |||
900 | |||
901 | /* SCB for the SP/DIF CODEC input and output */ | ||
902 | struct dsp_spdifoscb { | ||
903 | |||
904 | u32 free2; | ||
905 | |||
906 | u32 free3[4]; | ||
907 | |||
908 | /* Need to be here for compatibility with AsynchFGTxCode */ | ||
909 | u32 strm_rs_config; | ||
910 | |||
911 | u32 strm_buf_ptr; | ||
912 | |||
913 | ___DSP_DUAL_16BIT_ALLOC( | ||
914 | status, | ||
915 | free5 | ||
916 | ) | ||
917 | |||
918 | u32 free4; | ||
919 | |||
920 | ___DSP_DUAL_16BIT_ALLOC( | ||
921 | next_scb, | ||
922 | sub_list_ptr | ||
923 | ) | ||
924 | |||
925 | ___DSP_DUAL_16BIT_ALLOC( | ||
926 | entry_point, | ||
927 | this_spb | ||
928 | ) | ||
929 | |||
930 | u32 free6[2]; | ||
931 | |||
932 | ___DSP_DUAL_16BIT_ALLOC( | ||
933 | stat_reg_addr, | ||
934 | fifo_pointer | ||
935 | ) | ||
936 | |||
937 | ___DSP_DUAL_16BIT_ALLOC( | ||
938 | fifo_base_addr, | ||
939 | st_mo_format | ||
940 | ) | ||
941 | |||
942 | u32 free1; | ||
943 | }; | ||
944 | |||
945 | |||
946 | struct dsp_asynch_fg_rx_scb { | ||
947 | ___DSP_DUAL_16BIT_ALLOC( | ||
948 | bot_buf_mask, | ||
949 | buf_Mask | ||
950 | ) | ||
951 | |||
952 | ___DSP_DUAL_16BIT_ALLOC( | ||
953 | max, | ||
954 | min | ||
955 | ) | ||
956 | |||
957 | ___DSP_DUAL_16BIT_ALLOC( | ||
958 | old_producer_pointer, | ||
959 | hfg_scb_ptr | ||
960 | ) | ||
961 | |||
962 | ___DSP_DUAL_16BIT_ALLOC( | ||
963 | delta, | ||
964 | adjust_count | ||
965 | ) | ||
966 | |||
967 | u32 unused2[5]; | ||
968 | |||
969 | ___DSP_DUAL_16BIT_ALLOC( | ||
970 | sibling_ptr, | ||
971 | child_ptr | ||
972 | ) | ||
973 | |||
974 | ___DSP_DUAL_16BIT_ALLOC( | ||
975 | code_ptr, | ||
976 | this_ptr | ||
977 | ) | ||
978 | |||
979 | u32 strm_rs_config; | ||
980 | |||
981 | u32 strm_buf_ptr; | ||
982 | |||
983 | u32 unused_phi_incr; | ||
984 | |||
985 | ___DSP_DUAL_16BIT_ALLOC( | ||
986 | right_targ, | ||
987 | left_targ | ||
988 | ) | ||
989 | |||
990 | ___DSP_DUAL_16BIT_ALLOC( | ||
991 | right_vol, | ||
992 | left_vol | ||
993 | ) | ||
994 | }; | ||
995 | |||
996 | |||
997 | struct dsp_asynch_fg_tx_scb { | ||
998 | ___DSP_DUAL_16BIT_ALLOC( | ||
999 | not_buf_mask, | ||
1000 | buf_mask | ||
1001 | ) | ||
1002 | |||
1003 | ___DSP_DUAL_16BIT_ALLOC( | ||
1004 | max, | ||
1005 | min | ||
1006 | ) | ||
1007 | |||
1008 | ___DSP_DUAL_16BIT_ALLOC( | ||
1009 | unused1, | ||
1010 | hfg_scb_ptr | ||
1011 | ) | ||
1012 | |||
1013 | ___DSP_DUAL_16BIT_ALLOC( | ||
1014 | delta, | ||
1015 | adjust_count | ||
1016 | ) | ||
1017 | |||
1018 | u32 accum_phi; | ||
1019 | |||
1020 | ___DSP_DUAL_16BIT_ALLOC( | ||
1021 | unused2, | ||
1022 | const_one_third | ||
1023 | ) | ||
1024 | |||
1025 | u32 unused3[3]; | ||
1026 | |||
1027 | ___DSP_DUAL_16BIT_ALLOC( | ||
1028 | sibling_ptr, | ||
1029 | child_ptr | ||
1030 | ) | ||
1031 | |||
1032 | ___DSP_DUAL_16BIT_ALLOC( | ||
1033 | codePtr, | ||
1034 | this_ptr | ||
1035 | ) | ||
1036 | |||
1037 | u32 strm_rs_config; | ||
1038 | |||
1039 | u32 strm_buf_ptr; | ||
1040 | |||
1041 | u32 phi_incr; | ||
1042 | |||
1043 | ___DSP_DUAL_16BIT_ALLOC( | ||
1044 | unused_right_targ, | ||
1045 | unused_left_targ | ||
1046 | ) | ||
1047 | |||
1048 | ___DSP_DUAL_16BIT_ALLOC( | ||
1049 | unused_right_vol, | ||
1050 | unused_left_vol | ||
1051 | ) | ||
1052 | }; | ||
1053 | |||
1054 | |||
1055 | struct dsp_output_snoop_scb { | ||
1056 | /* First 13 dwords from generic_scb_t */ | ||
1057 | struct dsp_basic_dma_req basic_req; /* Optional */ | ||
1058 | struct dsp_scatter_gather_ext sg_ext; /* Optional */ | ||
1059 | ___DSP_DUAL_16BIT_ALLOC( | ||
1060 | next_scb, /* REQUIRED */ | ||
1061 | sub_list_ptr /* REQUIRED */ | ||
1062 | ) | ||
1063 | |||
1064 | ___DSP_DUAL_16BIT_ALLOC( | ||
1065 | entry_point, /* REQUIRED */ | ||
1066 | this_spb /* REQUIRED */ | ||
1067 | ) | ||
1068 | |||
1069 | u32 strm_rs_config; /* REQUIRED */ | ||
1070 | u32 strm_buf_ptr; /* REQUIRED */ | ||
1071 | |||
1072 | ___DSP_DUAL_16BIT_ALLOC( | ||
1073 | init_snoop_input_link, | ||
1074 | snoop_child_input_scb | ||
1075 | ) | ||
1076 | |||
1077 | u32 snoop_input_buf_ptr; | ||
1078 | |||
1079 | ___DSP_DUAL_16BIT_ALLOC( | ||
1080 | reserved, | ||
1081 | input_scb | ||
1082 | ) | ||
1083 | }; | ||
1084 | |||
1085 | struct dsp_spio_write_scb { | ||
1086 | ___DSP_DUAL_16BIT_ALLOC( | ||
1087 | address1, | ||
1088 | address2 | ||
1089 | ) | ||
1090 | |||
1091 | u32 data1; | ||
1092 | |||
1093 | u32 data2; | ||
1094 | |||
1095 | ___DSP_DUAL_16BIT_ALLOC( | ||
1096 | address3, | ||
1097 | address4 | ||
1098 | ) | ||
1099 | |||
1100 | u32 data3; | ||
1101 | |||
1102 | u32 data4; | ||
1103 | |||
1104 | ___DSP_DUAL_16BIT_ALLOC( | ||
1105 | unused1, | ||
1106 | data_ptr | ||
1107 | ) | ||
1108 | |||
1109 | u32 unused2[2]; | ||
1110 | |||
1111 | ___DSP_DUAL_16BIT_ALLOC( | ||
1112 | sibling_ptr, | ||
1113 | child_ptr | ||
1114 | ) | ||
1115 | |||
1116 | ___DSP_DUAL_16BIT_ALLOC( | ||
1117 | entry_point, | ||
1118 | this_ptr | ||
1119 | ) | ||
1120 | |||
1121 | u32 unused3[5]; | ||
1122 | }; | ||
1123 | |||
1124 | struct dsp_magic_snoop_task { | ||
1125 | u32 i0; | ||
1126 | u32 i1; | ||
1127 | |||
1128 | u32 strm_buf_ptr1; | ||
1129 | |||
1130 | u16 i2; | ||
1131 | u16 snoop_scb; | ||
1132 | |||
1133 | u32 i3; | ||
1134 | u32 i4; | ||
1135 | u32 i5; | ||
1136 | u32 i6; | ||
1137 | |||
1138 | u32 i7; | ||
1139 | |||
1140 | ___DSP_DUAL_16BIT_ALLOC( | ||
1141 | next_scb, | ||
1142 | sub_list_ptr | ||
1143 | ) | ||
1144 | |||
1145 | ___DSP_DUAL_16BIT_ALLOC( | ||
1146 | entry_point, | ||
1147 | this_ptr | ||
1148 | ) | ||
1149 | |||
1150 | u32 strm_buf_config; | ||
1151 | u32 strm_buf_ptr2; | ||
1152 | |||
1153 | u32 i8; | ||
1154 | |||
1155 | struct dsp_volume_control vdec_vol_ctrl; | ||
1156 | }; | ||
1157 | |||
1158 | |||
1159 | struct dsp_filter_scb { | ||
1160 | ___DSP_DUAL_16BIT_ALLOC( | ||
1161 | a0_right, /* 0x00 */ | ||
1162 | a0_left | ||
1163 | ) | ||
1164 | ___DSP_DUAL_16BIT_ALLOC( | ||
1165 | a1_right, /* 0x01 */ | ||
1166 | a1_left | ||
1167 | ) | ||
1168 | ___DSP_DUAL_16BIT_ALLOC( | ||
1169 | a2_right, /* 0x02 */ | ||
1170 | a2_left | ||
1171 | ) | ||
1172 | ___DSP_DUAL_16BIT_ALLOC( | ||
1173 | output_buf_ptr, /* 0x03 */ | ||
1174 | init | ||
1175 | ) | ||
1176 | |||
1177 | ___DSP_DUAL_16BIT_ALLOC( | ||
1178 | filter_unused3, /* 0x04 */ | ||
1179 | filter_unused2 | ||
1180 | ) | ||
1181 | |||
1182 | u32 prev_sample_output1; /* 0x05 */ | ||
1183 | u32 prev_sample_output2; /* 0x06 */ | ||
1184 | u32 prev_sample_input1; /* 0x07 */ | ||
1185 | u32 prev_sample_input2; /* 0x08 */ | ||
1186 | |||
1187 | ___DSP_DUAL_16BIT_ALLOC( | ||
1188 | next_scb_ptr, /* 0x09 */ | ||
1189 | sub_list_ptr | ||
1190 | ) | ||
1191 | |||
1192 | ___DSP_DUAL_16BIT_ALLOC( | ||
1193 | entry_point, /* 0x0A */ | ||
1194 | spb_ptr | ||
1195 | ) | ||
1196 | |||
1197 | u32 strm_rs_config; /* 0x0B */ | ||
1198 | u32 strm_buf_ptr; /* 0x0C */ | ||
1199 | |||
1200 | ___DSP_DUAL_16BIT_ALLOC( | ||
1201 | b0_right, /* 0x0D */ | ||
1202 | b0_left | ||
1203 | ) | ||
1204 | ___DSP_DUAL_16BIT_ALLOC( | ||
1205 | b1_right, /* 0x0E */ | ||
1206 | b1_left | ||
1207 | ) | ||
1208 | ___DSP_DUAL_16BIT_ALLOC( | ||
1209 | b2_right, /* 0x0F */ | ||
1210 | b2_left | ||
1211 | ) | ||
1212 | }; | ||
1213 | #endif /* __DSP_SCB_TYPES_H__ */ | ||
diff --git a/sound/pci/cs46xx/cs46xx_dsp_spos.h b/sound/pci/cs46xx/cs46xx_dsp_spos.h new file mode 100644 index 000000000000..8008c59288a6 --- /dev/null +++ b/sound/pci/cs46xx/cs46xx_dsp_spos.h | |||
@@ -0,0 +1,234 @@ | |||
1 | /* | ||
2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards | ||
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 | #ifndef __CS46XX_DSP_SPOS_H__ | ||
23 | #define __CS46XX_DSP_SPOS_H__ | ||
24 | |||
25 | #include "cs46xx_dsp_scb_types.h" | ||
26 | #include "cs46xx_dsp_task_types.h" | ||
27 | |||
28 | #define SYMBOL_CONSTANT 0x0 | ||
29 | #define SYMBOL_SAMPLE 0x1 | ||
30 | #define SYMBOL_PARAMETER 0x2 | ||
31 | #define SYMBOL_CODE 0x3 | ||
32 | |||
33 | #define SEGTYPE_SP_PROGRAM 0x00000001 | ||
34 | #define SEGTYPE_SP_PARAMETER 0x00000002 | ||
35 | #define SEGTYPE_SP_SAMPLE 0x00000003 | ||
36 | #define SEGTYPE_SP_COEFFICIENT 0x00000004 | ||
37 | |||
38 | #define DSP_SPOS_UU 0x0deadul /* unused */ | ||
39 | #define DSP_SPOS_DC 0x0badul /* don't care */ | ||
40 | #define DSP_SPOS_DC_DC 0x0bad0badul /* don't care */ | ||
41 | #define DSP_SPOS_UUUU 0xdeadc0edul /* unused */ | ||
42 | #define DSP_SPOS_UUHI 0xdeadul | ||
43 | #define DSP_SPOS_UULO 0xc0edul | ||
44 | #define DSP_SPOS_DCDC 0x0badf1d0ul /* don't care */ | ||
45 | #define DSP_SPOS_DCDCHI 0x0badul | ||
46 | #define DSP_SPOS_DCDCLO 0xf1d0ul | ||
47 | |||
48 | #define DSP_MAX_TASK_NAME 60 | ||
49 | #define DSP_MAX_SYMBOL_NAME 100 | ||
50 | #define DSP_MAX_SCB_NAME 60 | ||
51 | #define DSP_MAX_SCB_DESC 200 | ||
52 | #define DSP_MAX_TASK_DESC 50 | ||
53 | |||
54 | #define DSP_MAX_PCM_CHANNELS 32 | ||
55 | #define DSP_MAX_SRC_NR 14 | ||
56 | |||
57 | #define DSP_PCM_MAIN_CHANNEL 1 | ||
58 | #define DSP_PCM_REAR_CHANNEL 2 | ||
59 | #define DSP_PCM_CENTER_LFE_CHANNEL 3 | ||
60 | #define DSP_PCM_S71_CHANNEL 4 /* surround 7.1 */ | ||
61 | #define DSP_IEC958_CHANNEL 5 | ||
62 | |||
63 | #define DSP_SPDIF_STATUS_OUTPUT_ENABLED 1 | ||
64 | #define DSP_SPDIF_STATUS_PLAYBACK_OPEN 2 | ||
65 | #define DSP_SPDIF_STATUS_HW_ENABLED 4 | ||
66 | #define DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED 8 | ||
67 | |||
68 | struct dsp_symbol_entry { | ||
69 | u32 address; | ||
70 | char symbol_name[DSP_MAX_SYMBOL_NAME]; | ||
71 | int symbol_type; | ||
72 | |||
73 | /* initialized by driver */ | ||
74 | struct dsp_module_desc * module; | ||
75 | int deleted; | ||
76 | }; | ||
77 | |||
78 | struct dsp_symbol_desc { | ||
79 | int nsymbols; | ||
80 | |||
81 | struct dsp_symbol_entry *symbols; | ||
82 | |||
83 | /* initialized by driver */ | ||
84 | int highest_frag_index; | ||
85 | }; | ||
86 | |||
87 | struct dsp_segment_desc { | ||
88 | int segment_type; | ||
89 | u32 offset; | ||
90 | u32 size; | ||
91 | u32 * data; | ||
92 | }; | ||
93 | |||
94 | struct dsp_module_desc { | ||
95 | char * module_name; | ||
96 | struct dsp_symbol_desc symbol_table; | ||
97 | int nsegments; | ||
98 | struct dsp_segment_desc * segments; | ||
99 | |||
100 | /* initialized by driver */ | ||
101 | u32 overlay_begin_address; | ||
102 | u32 load_address; | ||
103 | int nfixups; | ||
104 | }; | ||
105 | |||
106 | struct dsp_scb_descriptor { | ||
107 | char scb_name[DSP_MAX_SCB_NAME]; | ||
108 | u32 address; | ||
109 | int index; | ||
110 | u32 *data; | ||
111 | |||
112 | struct dsp_scb_descriptor * sub_list_ptr; | ||
113 | struct dsp_scb_descriptor * next_scb_ptr; | ||
114 | struct dsp_scb_descriptor * parent_scb_ptr; | ||
115 | |||
116 | struct dsp_symbol_entry * task_entry; | ||
117 | struct dsp_symbol_entry * scb_symbol; | ||
118 | |||
119 | struct snd_info_entry *proc_info; | ||
120 | int ref_count; | ||
121 | |||
122 | u16 volume[2]; | ||
123 | unsigned int deleted :1; | ||
124 | unsigned int updated :1; | ||
125 | unsigned int volume_set :1; | ||
126 | }; | ||
127 | |||
128 | struct dsp_task_descriptor { | ||
129 | char task_name[DSP_MAX_TASK_NAME]; | ||
130 | int size; | ||
131 | u32 address; | ||
132 | int index; | ||
133 | u32 *data; | ||
134 | }; | ||
135 | |||
136 | struct dsp_pcm_channel_descriptor { | ||
137 | int active; | ||
138 | int src_slot; | ||
139 | int pcm_slot; | ||
140 | u32 sample_rate; | ||
141 | u32 unlinked; | ||
142 | struct dsp_scb_descriptor * pcm_reader_scb; | ||
143 | struct dsp_scb_descriptor * src_scb; | ||
144 | struct dsp_scb_descriptor * mixer_scb; | ||
145 | |||
146 | void * private_data; | ||
147 | }; | ||
148 | |||
149 | struct dsp_spos_instance { | ||
150 | struct dsp_symbol_desc symbol_table; /* currently available loaded symbols in SP */ | ||
151 | |||
152 | int nmodules; | ||
153 | struct dsp_module_desc * modules; /* modules loaded into SP */ | ||
154 | |||
155 | struct dsp_segment_desc code; | ||
156 | |||
157 | /* Main PCM playback mixer */ | ||
158 | struct dsp_scb_descriptor * master_mix_scb; | ||
159 | u16 dac_volume_right; | ||
160 | u16 dac_volume_left; | ||
161 | |||
162 | /* Rear/surround PCM playback mixer */ | ||
163 | struct dsp_scb_descriptor * rear_mix_scb; | ||
164 | |||
165 | /* Center/LFE mixer */ | ||
166 | struct dsp_scb_descriptor * center_lfe_mix_scb; | ||
167 | |||
168 | int npcm_channels; | ||
169 | int nsrc_scb; | ||
170 | struct dsp_pcm_channel_descriptor pcm_channels[DSP_MAX_PCM_CHANNELS]; | ||
171 | int src_scb_slots[DSP_MAX_SRC_NR]; | ||
172 | |||
173 | /* cache this symbols */ | ||
174 | struct dsp_symbol_entry * null_algorithm; /* used by PCMreaderSCB's */ | ||
175 | struct dsp_symbol_entry * s16_up; /* used by SRCtaskSCB's */ | ||
176 | |||
177 | /* proc fs */ | ||
178 | struct snd_card *snd_card; | ||
179 | struct snd_info_entry * proc_dsp_dir; | ||
180 | struct snd_info_entry * proc_sym_info_entry; | ||
181 | struct snd_info_entry * proc_modules_info_entry; | ||
182 | struct snd_info_entry * proc_parameter_dump_info_entry; | ||
183 | struct snd_info_entry * proc_sample_dump_info_entry; | ||
184 | |||
185 | /* SCB's descriptors */ | ||
186 | int nscb; | ||
187 | int scb_highest_frag_index; | ||
188 | struct dsp_scb_descriptor scbs[DSP_MAX_SCB_DESC]; | ||
189 | struct snd_info_entry * proc_scb_info_entry; | ||
190 | struct dsp_scb_descriptor * the_null_scb; | ||
191 | |||
192 | /* Task's descriptors */ | ||
193 | int ntask; | ||
194 | struct dsp_task_descriptor tasks[DSP_MAX_TASK_DESC]; | ||
195 | struct snd_info_entry * proc_task_info_entry; | ||
196 | |||
197 | /* SPDIF status */ | ||
198 | int spdif_status_out; | ||
199 | int spdif_status_in; | ||
200 | u16 spdif_input_volume_right; | ||
201 | u16 spdif_input_volume_left; | ||
202 | /* spdif channel status, | ||
203 | left right and user validity bits */ | ||
204 | unsigned int spdif_csuv_default; | ||
205 | unsigned int spdif_csuv_stream; | ||
206 | |||
207 | /* SPDIF input sample rate converter */ | ||
208 | struct dsp_scb_descriptor * spdif_in_src; | ||
209 | /* SPDIF input asynch. receiver */ | ||
210 | struct dsp_scb_descriptor * asynch_rx_scb; | ||
211 | |||
212 | /* Capture record mixer SCB */ | ||
213 | struct dsp_scb_descriptor * record_mixer_scb; | ||
214 | |||
215 | /* CODEC input SCB */ | ||
216 | struct dsp_scb_descriptor * codec_in_scb; | ||
217 | |||
218 | /* reference snooper */ | ||
219 | struct dsp_scb_descriptor * ref_snoop_scb; | ||
220 | |||
221 | /* SPDIF output PCM reference */ | ||
222 | struct dsp_scb_descriptor * spdif_pcm_input_scb; | ||
223 | |||
224 | /* asynch TX task */ | ||
225 | struct dsp_scb_descriptor * asynch_tx_scb; | ||
226 | |||
227 | /* record sources */ | ||
228 | struct dsp_scb_descriptor * pcm_input; | ||
229 | struct dsp_scb_descriptor * adc_input; | ||
230 | |||
231 | int spdif_in_sample_rate; | ||
232 | }; | ||
233 | |||
234 | #endif /* __DSP_SPOS_H__ */ | ||
diff --git a/sound/pci/cs46xx/cs46xx_dsp_task_types.h b/sound/pci/cs46xx/cs46xx_dsp_task_types.h new file mode 100644 index 000000000000..5cf920bfda27 --- /dev/null +++ b/sound/pci/cs46xx/cs46xx_dsp_task_types.h | |||
@@ -0,0 +1,252 @@ | |||
1 | /* | ||
2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards | ||
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 | * NOTE: comments are copy/paste from cwcemb80.lst | ||
22 | * provided by Tom Woller at Cirrus (my only | ||
23 | * documentation about the SP OS running inside | ||
24 | * the DSP) | ||
25 | */ | ||
26 | |||
27 | #ifndef __CS46XX_DSP_TASK_TYPES_H__ | ||
28 | #define __CS46XX_DSP_TASK_TYPES_H__ | ||
29 | |||
30 | #include "cs46xx_dsp_scb_types.h" | ||
31 | |||
32 | /********************************************************************************************* | ||
33 | Example hierarchy of stream control blocks in the SP | ||
34 | |||
35 | hfgTree | ||
36 | Ptr____Call (c) | ||
37 | \ | ||
38 | -------+------ ------------- ------------- ------------- ----- | ||
39 | | SBlaster IF |______\| Foreground |___\| Middlegr'nd |___\| Background |___\| Nul | | ||
40 | | |Goto /| tree header |g /| tree header |g /| tree header |g /| SCB |r | ||
41 | -------------- (g) ------------- ------------- ------------- ----- | ||
42 | |c |c |c |c | ||
43 | | | | | | ||
44 | \/ ------------- ------------- ------------- | ||
45 | | Foreground |_\ | Middlegr'nd |_\ | Background |_\ | ||
46 | | tree |g/ | tree |g/ | tree |g/ | ||
47 | ------------- ------------- ------------- | ||
48 | |c |c |c | ||
49 | | | | | ||
50 | \/ \/ \/ | ||
51 | |||
52 | *********************************************************************************************/ | ||
53 | |||
54 | #define HFG_FIRST_EXECUTE_MODE 0x0001 | ||
55 | #define HFG_FIRST_EXECUTE_MODE_BIT 0 | ||
56 | #define HFG_CONTEXT_SWITCH_MODE 0x0002 | ||
57 | #define HFG_CONTEXT_SWITCH_MODE_BIT 1 | ||
58 | |||
59 | #define MAX_FG_STACK_SIZE 32 /* THESE NEED TO BE COMPUTED PROPERLY */ | ||
60 | #define MAX_MG_STACK_SIZE 16 | ||
61 | #define MAX_BG_STACK_SIZE 9 | ||
62 | #define MAX_HFG_STACK_SIZE 4 | ||
63 | |||
64 | #define SLEEP_ACTIVE_INCREMENT 0 /* Enable task tree thread to go to sleep | ||
65 | This should only ever be used on the Background thread */ | ||
66 | #define STANDARD_ACTIVE_INCREMENT 1 /* Task tree thread normal operation */ | ||
67 | #define SUSPEND_ACTIVE_INCREMENT 2 /* Cause execution to suspend in the task tree thread | ||
68 | This should only ever be used on the Background thread */ | ||
69 | |||
70 | #define HOSTFLAGS_DISABLE_BG_SLEEP 0 /* Host-controlled flag that determines whether we go to sleep | ||
71 | at the end of BG */ | ||
72 | |||
73 | /* Minimal context save area for Hyper Forground */ | ||
74 | struct dsp_hf_save_area { | ||
75 | u32 r10_save; | ||
76 | u32 r54_save; | ||
77 | u32 r98_save; | ||
78 | |||
79 | ___DSP_DUAL_16BIT_ALLOC( | ||
80 | status_save, | ||
81 | ind_save | ||
82 | ) | ||
83 | |||
84 | ___DSP_DUAL_16BIT_ALLOC( | ||
85 | rci1_save, | ||
86 | rci0_save | ||
87 | ) | ||
88 | |||
89 | u32 r32_save; | ||
90 | u32 r76_save; | ||
91 | u32 rsd2_save; | ||
92 | |||
93 | ___DSP_DUAL_16BIT_ALLOC( | ||
94 | rsi2_save, /* See TaskTreeParameterBlock for | ||
95 | remainder of registers */ | ||
96 | rsa2Save | ||
97 | ) | ||
98 | /* saved as part of HFG context */ | ||
99 | }; | ||
100 | |||
101 | |||
102 | /* Task link data structure */ | ||
103 | struct dsp_tree_link { | ||
104 | ___DSP_DUAL_16BIT_ALLOC( | ||
105 | /* Pointer to sibling task control block */ | ||
106 | next_scb, | ||
107 | /* Pointer to child task control block */ | ||
108 | sub_ptr | ||
109 | ) | ||
110 | |||
111 | ___DSP_DUAL_16BIT_ALLOC( | ||
112 | /* Pointer to code entry point */ | ||
113 | entry_point, | ||
114 | /* Pointer to local data */ | ||
115 | this_spb | ||
116 | ) | ||
117 | }; | ||
118 | |||
119 | |||
120 | struct dsp_task_tree_data { | ||
121 | ___DSP_DUAL_16BIT_ALLOC( | ||
122 | /* Initial tock count; controls task tree execution rate */ | ||
123 | tock_count_limit, | ||
124 | /* Tock down counter */ | ||
125 | tock_count | ||
126 | ) | ||
127 | |||
128 | /* Add to ActiveCount when TockCountLimit reached: | ||
129 | Subtract on task tree termination */ | ||
130 | ___DSP_DUAL_16BIT_ALLOC( | ||
131 | active_tncrement, | ||
132 | /* Number of pending activations for task tree */ | ||
133 | active_count | ||
134 | ) | ||
135 | |||
136 | ___DSP_DUAL_16BIT_ALLOC( | ||
137 | /* BitNumber to enable modification of correct bit in ActiveTaskFlags */ | ||
138 | active_bit, | ||
139 | /* Pointer to OS location for indicating current activity on task level */ | ||
140 | active_task_flags_ptr | ||
141 | ) | ||
142 | |||
143 | /* Data structure for controlling movement of memory blocks:- | ||
144 | currently unused */ | ||
145 | ___DSP_DUAL_16BIT_ALLOC( | ||
146 | mem_upd_ptr, | ||
147 | /* Data structure for controlling synchronous link update */ | ||
148 | link_upd_ptr | ||
149 | ) | ||
150 | |||
151 | ___DSP_DUAL_16BIT_ALLOC( | ||
152 | /* Save area for remainder of full context. */ | ||
153 | save_area, | ||
154 | /* Address of start of local stack for data storage */ | ||
155 | data_stack_base_ptr | ||
156 | ) | ||
157 | |||
158 | }; | ||
159 | |||
160 | |||
161 | struct dsp_interval_timer_data | ||
162 | { | ||
163 | /* These data items have the same relative locations to those */ | ||
164 | ___DSP_DUAL_16BIT_ALLOC( | ||
165 | interval_timer_period, | ||
166 | itd_unused | ||
167 | ) | ||
168 | |||
169 | /* used for this data in the SPOS control block for SPOS 1.0 */ | ||
170 | ___DSP_DUAL_16BIT_ALLOC( | ||
171 | num_FG_ticks_this_interval, | ||
172 | num_intervals | ||
173 | ) | ||
174 | }; | ||
175 | |||
176 | |||
177 | /* This structure contains extra storage for the task tree | ||
178 | Currently, this additional data is related only to a full context save */ | ||
179 | struct dsp_task_tree_context_block { | ||
180 | /* Up to 10 values are saved onto the stack. 8 for the task tree, 1 for | ||
181 | The access to the context switch (call or interrupt), and 1 spare that | ||
182 | users should never use. This last may be required by the system */ | ||
183 | ___DSP_DUAL_16BIT_ALLOC( | ||
184 | stack1, | ||
185 | stack0 | ||
186 | ) | ||
187 | ___DSP_DUAL_16BIT_ALLOC( | ||
188 | stack3, | ||
189 | stack2 | ||
190 | ) | ||
191 | ___DSP_DUAL_16BIT_ALLOC( | ||
192 | stack5, | ||
193 | stack4 | ||
194 | ) | ||
195 | ___DSP_DUAL_16BIT_ALLOC( | ||
196 | stack7, | ||
197 | stack6 | ||
198 | ) | ||
199 | ___DSP_DUAL_16BIT_ALLOC( | ||
200 | stack9, | ||
201 | stack8 | ||
202 | ) | ||
203 | |||
204 | u32 saverfe; | ||
205 | |||
206 | /* Value may be overwriten by stack save algorithm. | ||
207 | Retain the size of the stack data saved here if used */ | ||
208 | ___DSP_DUAL_16BIT_ALLOC( | ||
209 | reserved1, | ||
210 | stack_size | ||
211 | ) | ||
212 | u32 saverba; /* (HFG) */ | ||
213 | u32 saverdc; | ||
214 | u32 savers_config_23; /* (HFG) */ | ||
215 | u32 savers_DMA23; /* (HFG) */ | ||
216 | u32 saversa0; | ||
217 | u32 saversi0; | ||
218 | u32 saversa1; | ||
219 | u32 saversi1; | ||
220 | u32 saversa3; | ||
221 | u32 saversd0; | ||
222 | u32 saversd1; | ||
223 | u32 saversd3; | ||
224 | u32 savers_config01; | ||
225 | u32 savers_DMA01; | ||
226 | u32 saveacc0hl; | ||
227 | u32 saveacc1hl; | ||
228 | u32 saveacc0xacc1x; | ||
229 | u32 saveacc2hl; | ||
230 | u32 saveacc3hl; | ||
231 | u32 saveacc2xacc3x; | ||
232 | u32 saveaux0hl; | ||
233 | u32 saveaux1hl; | ||
234 | u32 saveaux0xaux1x; | ||
235 | u32 saveaux2hl; | ||
236 | u32 saveaux3hl; | ||
237 | u32 saveaux2xaux3x; | ||
238 | u32 savershouthl; | ||
239 | u32 savershoutxmacmode; | ||
240 | }; | ||
241 | |||
242 | |||
243 | struct dsp_task_tree_control_block { | ||
244 | struct dsp_hf_save_area context; | ||
245 | struct dsp_tree_link links; | ||
246 | struct dsp_task_tree_data data; | ||
247 | struct dsp_task_tree_context_block context_blk; | ||
248 | struct dsp_interval_timer_data int_timer; | ||
249 | }; | ||
250 | |||
251 | |||
252 | #endif /* __DSP_TASK_TYPES_H__ */ | ||
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 4fa53161b094..f75f5ffdfdfb 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -61,7 +61,7 @@ | |||
61 | #include <sound/info.h> | 61 | #include <sound/info.h> |
62 | #include <sound/pcm.h> | 62 | #include <sound/pcm.h> |
63 | #include <sound/pcm_params.h> | 63 | #include <sound/pcm_params.h> |
64 | #include <sound/cs46xx.h> | 64 | #include "cs46xx.h" |
65 | 65 | ||
66 | #include <asm/io.h> | 66 | #include <asm/io.h> |
67 | 67 | ||
@@ -3599,9 +3599,10 @@ static unsigned int saved_regs[] = { | |||
3599 | BA1_CVOL, | 3599 | BA1_CVOL, |
3600 | }; | 3600 | }; |
3601 | 3601 | ||
3602 | int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) | 3602 | static int snd_cs46xx_suspend(struct device *dev) |
3603 | { | 3603 | { |
3604 | struct snd_card *card = pci_get_drvdata(pci); | 3604 | struct pci_dev *pci = to_pci_dev(dev); |
3605 | struct snd_card *card = dev_get_drvdata(dev); | ||
3605 | struct snd_cs46xx *chip = card->private_data; | 3606 | struct snd_cs46xx *chip = card->private_data; |
3606 | int i, amp_saved; | 3607 | int i, amp_saved; |
3607 | 3608 | ||
@@ -3628,13 +3629,14 @@ int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) | |||
3628 | 3629 | ||
3629 | pci_disable_device(pci); | 3630 | pci_disable_device(pci); |
3630 | pci_save_state(pci); | 3631 | pci_save_state(pci); |
3631 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 3632 | pci_set_power_state(pci, PCI_D3hot); |
3632 | return 0; | 3633 | return 0; |
3633 | } | 3634 | } |
3634 | 3635 | ||
3635 | int snd_cs46xx_resume(struct pci_dev *pci) | 3636 | static int snd_cs46xx_resume(struct device *dev) |
3636 | { | 3637 | { |
3637 | struct snd_card *card = pci_get_drvdata(pci); | 3638 | struct pci_dev *pci = to_pci_dev(dev); |
3639 | struct snd_card *card = dev_get_drvdata(dev); | ||
3638 | struct snd_cs46xx *chip = card->private_data; | 3640 | struct snd_cs46xx *chip = card->private_data; |
3639 | int amp_saved; | 3641 | int amp_saved; |
3640 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | 3642 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
@@ -3707,6 +3709,8 @@ int snd_cs46xx_resume(struct pci_dev *pci) | |||
3707 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 3709 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
3708 | return 0; | 3710 | return 0; |
3709 | } | 3711 | } |
3712 | |||
3713 | SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume); | ||
3710 | #endif /* CONFIG_PM */ | 3714 | #endif /* CONFIG_PM */ |
3711 | 3715 | ||
3712 | 3716 | ||
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index e377287192aa..56fec0bc0efb 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include <sound/control.h> | 32 | #include <sound/control.h> |
33 | #include <sound/info.h> | 33 | #include <sound/info.h> |
34 | #include <sound/asoundef.h> | 34 | #include <sound/asoundef.h> |
35 | #include <sound/cs46xx.h> | 35 | #include "cs46xx.h" |
36 | 36 | ||
37 | #include "cs46xx_lib.h" | 37 | #include "cs46xx_lib.h" |
38 | #include "dsp_spos.h" | 38 | #include "dsp_spos.h" |
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 00b148a10239..c2c695b07f8c 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <sound/core.h> | 31 | #include <sound/core.h> |
32 | #include <sound/control.h> | 32 | #include <sound/control.h> |
33 | #include <sound/info.h> | 33 | #include <sound/info.h> |
34 | #include <sound/cs46xx.h> | 34 | #include "cs46xx.h" |
35 | 35 | ||
36 | #include "cs46xx_lib.h" | 36 | #include "cs46xx_lib.h" |
37 | #include "dsp_spos.h" | 37 | #include "dsp_spos.h" |
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 2c9697cf0a1a..51f64ba5facf 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c | |||
@@ -400,8 +400,9 @@ static struct pci_driver cs5535audio_driver = { | |||
400 | .probe = snd_cs5535audio_probe, | 400 | .probe = snd_cs5535audio_probe, |
401 | .remove = __devexit_p(snd_cs5535audio_remove), | 401 | .remove = __devexit_p(snd_cs5535audio_remove), |
402 | #ifdef CONFIG_PM | 402 | #ifdef CONFIG_PM |
403 | .suspend = snd_cs5535audio_suspend, | 403 | .driver = { |
404 | .resume = snd_cs5535audio_resume, | 404 | .pm = &snd_cs5535audio_pm, |
405 | }, | ||
405 | #endif | 406 | #endif |
406 | }; | 407 | }; |
407 | 408 | ||
diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h index 51966d782a3c..bb3cc641130c 100644 --- a/sound/pci/cs5535audio/cs5535audio.h +++ b/sound/pci/cs5535audio/cs5535audio.h | |||
@@ -94,10 +94,7 @@ struct cs5535audio { | |||
94 | struct cs5535audio_dma dmas[NUM_CS5535AUDIO_DMAS]; | 94 | struct cs5535audio_dma dmas[NUM_CS5535AUDIO_DMAS]; |
95 | }; | 95 | }; |
96 | 96 | ||
97 | #ifdef CONFIG_PM | 97 | extern const struct dev_pm_ops snd_cs5535audio_pm; |
98 | int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state); | ||
99 | int snd_cs5535audio_resume(struct pci_dev *pci); | ||
100 | #endif | ||
101 | 98 | ||
102 | #ifdef CONFIG_OLPC | 99 | #ifdef CONFIG_OLPC |
103 | void __devinit olpc_prequirks(struct snd_card *card, | 100 | void __devinit olpc_prequirks(struct snd_card *card, |
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c index 185b00088320..6c34def5986d 100644 --- a/sound/pci/cs5535audio/cs5535audio_pm.c +++ b/sound/pci/cs5535audio/cs5535audio_pm.c | |||
@@ -55,9 +55,10 @@ static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au) | |||
55 | 55 | ||
56 | } | 56 | } |
57 | 57 | ||
58 | int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state) | 58 | static int snd_cs5535audio_suspend(struct device *dev) |
59 | { | 59 | { |
60 | struct snd_card *card = pci_get_drvdata(pci); | 60 | struct pci_dev *pci = to_pci_dev(dev); |
61 | struct snd_card *card = dev_get_drvdata(dev); | ||
61 | struct cs5535audio *cs5535au = card->private_data; | 62 | struct cs5535audio *cs5535au = card->private_data; |
62 | int i; | 63 | int i; |
63 | 64 | ||
@@ -77,13 +78,14 @@ int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state) | |||
77 | return -EIO; | 78 | return -EIO; |
78 | } | 79 | } |
79 | pci_disable_device(pci); | 80 | pci_disable_device(pci); |
80 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 81 | pci_set_power_state(pci, PCI_D3hot); |
81 | return 0; | 82 | return 0; |
82 | } | 83 | } |
83 | 84 | ||
84 | int snd_cs5535audio_resume(struct pci_dev *pci) | 85 | static int snd_cs5535audio_resume(struct device *dev) |
85 | { | 86 | { |
86 | struct snd_card *card = pci_get_drvdata(pci); | 87 | struct pci_dev *pci = to_pci_dev(dev); |
88 | struct snd_card *card = dev_get_drvdata(dev); | ||
87 | struct cs5535audio *cs5535au = card->private_data; | 89 | struct cs5535audio *cs5535au = card->private_data; |
88 | u32 tmp; | 90 | u32 tmp; |
89 | int timeout; | 91 | int timeout; |
@@ -129,3 +131,4 @@ int snd_cs5535audio_resume(struct pci_dev *pci) | |||
129 | return 0; | 131 | return 0; |
130 | } | 132 | } |
131 | 133 | ||
134 | SIMPLE_DEV_PM_OPS(snd_cs5535audio_pm, snd_cs5535audio_suspend, snd_cs5535audio_resume); | ||
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index d8a4423539ce..8e40262d4117 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c | |||
@@ -1537,7 +1537,7 @@ static void atc_connect_resources(struct ct_atc *atc) | |||
1537 | } | 1537 | } |
1538 | 1538 | ||
1539 | #ifdef CONFIG_PM | 1539 | #ifdef CONFIG_PM |
1540 | static int atc_suspend(struct ct_atc *atc, pm_message_t state) | 1540 | static int atc_suspend(struct ct_atc *atc) |
1541 | { | 1541 | { |
1542 | int i; | 1542 | int i; |
1543 | struct hw *hw = atc->hw; | 1543 | struct hw *hw = atc->hw; |
@@ -1553,7 +1553,7 @@ static int atc_suspend(struct ct_atc *atc, pm_message_t state) | |||
1553 | 1553 | ||
1554 | atc_release_resources(atc); | 1554 | atc_release_resources(atc); |
1555 | 1555 | ||
1556 | hw->suspend(hw, state); | 1556 | hw->suspend(hw); |
1557 | 1557 | ||
1558 | return 0; | 1558 | return 0; |
1559 | } | 1559 | } |
diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h index 3a0def656af0..653e813ad142 100644 --- a/sound/pci/ctxfi/ctatc.h +++ b/sound/pci/ctxfi/ctatc.h | |||
@@ -144,7 +144,7 @@ struct ct_atc { | |||
144 | struct ct_timer *timer; | 144 | struct ct_timer *timer; |
145 | 145 | ||
146 | #ifdef CONFIG_PM | 146 | #ifdef CONFIG_PM |
147 | int (*suspend)(struct ct_atc *atc, pm_message_t state); | 147 | int (*suspend)(struct ct_atc *atc); |
148 | int (*resume)(struct ct_atc *atc); | 148 | int (*resume)(struct ct_atc *atc); |
149 | #define NUM_PCMS (NUM_CTALSADEVS - 1) | 149 | #define NUM_PCMS (NUM_CTALSADEVS - 1) |
150 | struct snd_pcm *pcms[NUM_PCMS]; | 150 | struct snd_pcm *pcms[NUM_PCMS]; |
diff --git a/sound/pci/ctxfi/cthardware.h b/sound/pci/ctxfi/cthardware.h index 908315bec3b4..c56fe533b3f3 100644 --- a/sound/pci/ctxfi/cthardware.h +++ b/sound/pci/ctxfi/cthardware.h | |||
@@ -73,7 +73,7 @@ struct hw { | |||
73 | int (*card_stop)(struct hw *hw); | 73 | int (*card_stop)(struct hw *hw); |
74 | int (*pll_init)(struct hw *hw, unsigned int rsr); | 74 | int (*pll_init)(struct hw *hw, unsigned int rsr); |
75 | #ifdef CONFIG_PM | 75 | #ifdef CONFIG_PM |
76 | int (*suspend)(struct hw *hw, pm_message_t state); | 76 | int (*suspend)(struct hw *hw); |
77 | int (*resume)(struct hw *hw, struct card_conf *info); | 77 | int (*resume)(struct hw *hw, struct card_conf *info); |
78 | #endif | 78 | #endif |
79 | int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source); | 79 | int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source); |
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index a7df19791f5a..dc1969bc67d4 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c | |||
@@ -2086,7 +2086,7 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) | |||
2086 | } | 2086 | } |
2087 | 2087 | ||
2088 | #ifdef CONFIG_PM | 2088 | #ifdef CONFIG_PM |
2089 | static int hw_suspend(struct hw *hw, pm_message_t state) | 2089 | static int hw_suspend(struct hw *hw) |
2090 | { | 2090 | { |
2091 | struct pci_dev *pci = hw->pci; | 2091 | struct pci_dev *pci = hw->pci; |
2092 | 2092 | ||
@@ -2099,7 +2099,7 @@ static int hw_suspend(struct hw *hw, pm_message_t state) | |||
2099 | 2099 | ||
2100 | pci_disable_device(pci); | 2100 | pci_disable_device(pci); |
2101 | pci_save_state(pci); | 2101 | pci_save_state(pci); |
2102 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 2102 | pci_set_power_state(pci, PCI_D3hot); |
2103 | 2103 | ||
2104 | return 0; | 2104 | return 0; |
2105 | } | 2105 | } |
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index d6c54b524bfa..9d1231dc4ae2 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c | |||
@@ -2202,7 +2202,7 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) | |||
2202 | } | 2202 | } |
2203 | 2203 | ||
2204 | #ifdef CONFIG_PM | 2204 | #ifdef CONFIG_PM |
2205 | static int hw_suspend(struct hw *hw, pm_message_t state) | 2205 | static int hw_suspend(struct hw *hw) |
2206 | { | 2206 | { |
2207 | struct pci_dev *pci = hw->pci; | 2207 | struct pci_dev *pci = hw->pci; |
2208 | 2208 | ||
@@ -2210,7 +2210,7 @@ static int hw_suspend(struct hw *hw, pm_message_t state) | |||
2210 | 2210 | ||
2211 | pci_disable_device(pci); | 2211 | pci_disable_device(pci); |
2212 | pci_save_state(pci); | 2212 | pci_save_state(pci); |
2213 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 2213 | pci_set_power_state(pci, PCI_D3hot); |
2214 | 2214 | ||
2215 | return 0; | 2215 | return 0; |
2216 | } | 2216 | } |
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c index 75aa2c338410..e002183ef8b2 100644 --- a/sound/pci/ctxfi/xfi.c +++ b/sound/pci/ctxfi/xfi.c | |||
@@ -126,21 +126,26 @@ static void __devexit ct_card_remove(struct pci_dev *pci) | |||
126 | } | 126 | } |
127 | 127 | ||
128 | #ifdef CONFIG_PM | 128 | #ifdef CONFIG_PM |
129 | static int ct_card_suspend(struct pci_dev *pci, pm_message_t state) | 129 | static int ct_card_suspend(struct device *dev) |
130 | { | 130 | { |
131 | struct snd_card *card = pci_get_drvdata(pci); | 131 | struct snd_card *card = dev_get_drvdata(dev); |
132 | struct ct_atc *atc = card->private_data; | 132 | struct ct_atc *atc = card->private_data; |
133 | 133 | ||
134 | return atc->suspend(atc, state); | 134 | return atc->suspend(atc); |
135 | } | 135 | } |
136 | 136 | ||
137 | static int ct_card_resume(struct pci_dev *pci) | 137 | static int ct_card_resume(struct device *dev) |
138 | { | 138 | { |
139 | struct snd_card *card = pci_get_drvdata(pci); | 139 | struct snd_card *card = dev_get_drvdata(dev); |
140 | struct ct_atc *atc = card->private_data; | 140 | struct ct_atc *atc = card->private_data; |
141 | 141 | ||
142 | return atc->resume(atc); | 142 | return atc->resume(atc); |
143 | } | 143 | } |
144 | |||
145 | static SIMPLE_DEV_PM_OPS(ct_card_pm, ct_card_suspend, ct_card_resume); | ||
146 | #define CT_CARD_PM_OPS &ct_card_pm | ||
147 | #else | ||
148 | #define CT_CARD_PM_OPS NULL | ||
144 | #endif | 149 | #endif |
145 | 150 | ||
146 | static struct pci_driver ct_driver = { | 151 | static struct pci_driver ct_driver = { |
@@ -148,10 +153,9 @@ static struct pci_driver ct_driver = { | |||
148 | .id_table = ct_pci_dev_ids, | 153 | .id_table = ct_pci_dev_ids, |
149 | .probe = ct_card_probe, | 154 | .probe = ct_card_probe, |
150 | .remove = __devexit_p(ct_card_remove), | 155 | .remove = __devexit_p(ct_card_remove), |
151 | #ifdef CONFIG_PM | 156 | .driver = { |
152 | .suspend = ct_card_suspend, | 157 | .pm = CT_CARD_PM_OPS, |
153 | .resume = ct_card_resume, | 158 | }, |
154 | #endif | ||
155 | }; | 159 | }; |
156 | 160 | ||
157 | module_pci_driver(ct_driver); | 161 | module_pci_driver(ct_driver); |
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 0f8eda1dafdb..0ff754f180d0 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
@@ -2205,9 +2205,10 @@ ctl_error: | |||
2205 | 2205 | ||
2206 | #if defined(CONFIG_PM) | 2206 | #if defined(CONFIG_PM) |
2207 | 2207 | ||
2208 | static int snd_echo_suspend(struct pci_dev *pci, pm_message_t state) | 2208 | static int snd_echo_suspend(struct device *dev) |
2209 | { | 2209 | { |
2210 | struct echoaudio *chip = pci_get_drvdata(pci); | 2210 | struct pci_dev *pci = to_pci_dev(dev); |
2211 | struct echoaudio *chip = dev_get_drvdata(dev); | ||
2211 | 2212 | ||
2212 | DE_INIT(("suspend start\n")); | 2213 | DE_INIT(("suspend start\n")); |
2213 | snd_pcm_suspend_all(chip->analog_pcm); | 2214 | snd_pcm_suspend_all(chip->analog_pcm); |
@@ -2242,9 +2243,10 @@ static int snd_echo_suspend(struct pci_dev *pci, pm_message_t state) | |||
2242 | 2243 | ||
2243 | 2244 | ||
2244 | 2245 | ||
2245 | static int snd_echo_resume(struct pci_dev *pci) | 2246 | static int snd_echo_resume(struct device *dev) |
2246 | { | 2247 | { |
2247 | struct echoaudio *chip = pci_get_drvdata(pci); | 2248 | struct pci_dev *pci = to_pci_dev(dev); |
2249 | struct echoaudio *chip = dev_get_drvdata(dev); | ||
2248 | struct comm_page *commpage, *commpage_bak; | 2250 | struct comm_page *commpage, *commpage_bak; |
2249 | u32 pipe_alloc_mask; | 2251 | u32 pipe_alloc_mask; |
2250 | int err; | 2252 | int err; |
@@ -2307,10 +2309,13 @@ static int snd_echo_resume(struct pci_dev *pci) | |||
2307 | return 0; | 2309 | return 0; |
2308 | } | 2310 | } |
2309 | 2311 | ||
2312 | static SIMPLE_DEV_PM_OPS(snd_echo_pm, snd_echo_suspend, snd_echo_resume); | ||
2313 | #define SND_ECHO_PM_OPS &snd_echo_pm | ||
2314 | #else | ||
2315 | #define SND_ECHO_PM_OPS NULL | ||
2310 | #endif /* CONFIG_PM */ | 2316 | #endif /* CONFIG_PM */ |
2311 | 2317 | ||
2312 | 2318 | ||
2313 | |||
2314 | static void __devexit snd_echo_remove(struct pci_dev *pci) | 2319 | static void __devexit snd_echo_remove(struct pci_dev *pci) |
2315 | { | 2320 | { |
2316 | struct echoaudio *chip; | 2321 | struct echoaudio *chip; |
@@ -2333,10 +2338,9 @@ static struct pci_driver echo_driver = { | |||
2333 | .id_table = snd_echo_ids, | 2338 | .id_table = snd_echo_ids, |
2334 | .probe = snd_echo_probe, | 2339 | .probe = snd_echo_probe, |
2335 | .remove = __devexit_p(snd_echo_remove), | 2340 | .remove = __devexit_p(snd_echo_remove), |
2336 | #ifdef CONFIG_PM | 2341 | .driver = { |
2337 | .suspend = snd_echo_suspend, | 2342 | .pm = SND_ECHO_PM_OPS, |
2338 | .resume = snd_echo_resume, | 2343 | }, |
2339 | #endif /* CONFIG_PM */ | ||
2340 | }; | 2344 | }; |
2341 | 2345 | ||
2342 | module_pci_driver(echo_driver); | 2346 | module_pci_driver(echo_driver); |
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 7fdbbe4d9965..ddac4e6d660d 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -207,9 +207,10 @@ static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci) | |||
207 | 207 | ||
208 | 208 | ||
209 | #ifdef CONFIG_PM | 209 | #ifdef CONFIG_PM |
210 | static int snd_emu10k1_suspend(struct pci_dev *pci, pm_message_t state) | 210 | static int snd_emu10k1_suspend(struct device *dev) |
211 | { | 211 | { |
212 | struct snd_card *card = pci_get_drvdata(pci); | 212 | struct pci_dev *pci = to_pci_dev(dev); |
213 | struct snd_card *card = dev_get_drvdata(dev); | ||
213 | struct snd_emu10k1 *emu = card->private_data; | 214 | struct snd_emu10k1 *emu = card->private_data; |
214 | 215 | ||
215 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 216 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
@@ -231,13 +232,14 @@ static int snd_emu10k1_suspend(struct pci_dev *pci, pm_message_t state) | |||
231 | 232 | ||
232 | pci_disable_device(pci); | 233 | pci_disable_device(pci); |
233 | pci_save_state(pci); | 234 | pci_save_state(pci); |
234 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 235 | pci_set_power_state(pci, PCI_D3hot); |
235 | return 0; | 236 | return 0; |
236 | } | 237 | } |
237 | 238 | ||
238 | static int snd_emu10k1_resume(struct pci_dev *pci) | 239 | static int snd_emu10k1_resume(struct device *dev) |
239 | { | 240 | { |
240 | struct snd_card *card = pci_get_drvdata(pci); | 241 | struct pci_dev *pci = to_pci_dev(dev); |
242 | struct snd_card *card = dev_get_drvdata(dev); | ||
241 | struct snd_emu10k1 *emu = card->private_data; | 243 | struct snd_emu10k1 *emu = card->private_data; |
242 | 244 | ||
243 | pci_set_power_state(pci, PCI_D0); | 245 | pci_set_power_state(pci, PCI_D0); |
@@ -261,17 +263,21 @@ static int snd_emu10k1_resume(struct pci_dev *pci) | |||
261 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 263 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
262 | return 0; | 264 | return 0; |
263 | } | 265 | } |
264 | #endif | 266 | |
267 | static SIMPLE_DEV_PM_OPS(snd_emu10k1_pm, snd_emu10k1_suspend, snd_emu10k1_resume); | ||
268 | #define SND_EMU10K1_PM_OPS &snd_emu10k1_pm | ||
269 | #else | ||
270 | #define SND_EMU10K1_PM_OPS NULL | ||
271 | #endif /* CONFIG_PM */ | ||
265 | 272 | ||
266 | static struct pci_driver emu10k1_driver = { | 273 | static struct pci_driver emu10k1_driver = { |
267 | .name = KBUILD_MODNAME, | 274 | .name = KBUILD_MODNAME, |
268 | .id_table = snd_emu10k1_ids, | 275 | .id_table = snd_emu10k1_ids, |
269 | .probe = snd_card_emu10k1_probe, | 276 | .probe = snd_card_emu10k1_probe, |
270 | .remove = __devexit_p(snd_card_emu10k1_remove), | 277 | .remove = __devexit_p(snd_card_emu10k1_remove), |
271 | #ifdef CONFIG_PM | 278 | .driver = { |
272 | .suspend = snd_emu10k1_suspend, | 279 | .pm = SND_EMU10K1_PM_OPS, |
273 | .resume = snd_emu10k1_resume, | 280 | }, |
274 | #endif | ||
275 | }; | 281 | }; |
276 | 282 | ||
277 | module_pci_driver(emu10k1_driver); | 283 | module_pci_driver(emu10k1_driver); |
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 3821c81d1c99..f7e6f73186e1 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -2033,9 +2033,10 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq) | |||
2033 | } | 2033 | } |
2034 | 2034 | ||
2035 | #ifdef CONFIG_PM | 2035 | #ifdef CONFIG_PM |
2036 | static int snd_ensoniq_suspend(struct pci_dev *pci, pm_message_t state) | 2036 | static int snd_ensoniq_suspend(struct device *dev) |
2037 | { | 2037 | { |
2038 | struct snd_card *card = pci_get_drvdata(pci); | 2038 | struct pci_dev *pci = to_pci_dev(dev); |
2039 | struct snd_card *card = dev_get_drvdata(dev); | ||
2039 | struct ensoniq *ensoniq = card->private_data; | 2040 | struct ensoniq *ensoniq = card->private_data; |
2040 | 2041 | ||
2041 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 2042 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
@@ -2058,13 +2059,14 @@ static int snd_ensoniq_suspend(struct pci_dev *pci, pm_message_t state) | |||
2058 | 2059 | ||
2059 | pci_disable_device(pci); | 2060 | pci_disable_device(pci); |
2060 | pci_save_state(pci); | 2061 | pci_save_state(pci); |
2061 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 2062 | pci_set_power_state(pci, PCI_D3hot); |
2062 | return 0; | 2063 | return 0; |
2063 | } | 2064 | } |
2064 | 2065 | ||
2065 | static int snd_ensoniq_resume(struct pci_dev *pci) | 2066 | static int snd_ensoniq_resume(struct device *dev) |
2066 | { | 2067 | { |
2067 | struct snd_card *card = pci_get_drvdata(pci); | 2068 | struct pci_dev *pci = to_pci_dev(dev); |
2069 | struct snd_card *card = dev_get_drvdata(dev); | ||
2068 | struct ensoniq *ensoniq = card->private_data; | 2070 | struct ensoniq *ensoniq = card->private_data; |
2069 | 2071 | ||
2070 | pci_set_power_state(pci, PCI_D0); | 2072 | pci_set_power_state(pci, PCI_D0); |
@@ -2087,8 +2089,12 @@ static int snd_ensoniq_resume(struct pci_dev *pci) | |||
2087 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2089 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
2088 | return 0; | 2090 | return 0; |
2089 | } | 2091 | } |
2090 | #endif /* CONFIG_PM */ | ||
2091 | 2092 | ||
2093 | static SIMPLE_DEV_PM_OPS(snd_ensoniq_pm, snd_ensoniq_suspend, snd_ensoniq_resume); | ||
2094 | #define SND_ENSONIQ_PM_OPS &snd_ensoniq_pm | ||
2095 | #else | ||
2096 | #define SND_ENSONIQ_PM_OPS NULL | ||
2097 | #endif /* CONFIG_PM */ | ||
2092 | 2098 | ||
2093 | static int __devinit snd_ensoniq_create(struct snd_card *card, | 2099 | static int __devinit snd_ensoniq_create(struct snd_card *card, |
2094 | struct pci_dev *pci, | 2100 | struct pci_dev *pci, |
@@ -2493,10 +2499,9 @@ static struct pci_driver ens137x_driver = { | |||
2493 | .id_table = snd_audiopci_ids, | 2499 | .id_table = snd_audiopci_ids, |
2494 | .probe = snd_audiopci_probe, | 2500 | .probe = snd_audiopci_probe, |
2495 | .remove = __devexit_p(snd_audiopci_remove), | 2501 | .remove = __devexit_p(snd_audiopci_remove), |
2496 | #ifdef CONFIG_PM | 2502 | .driver = { |
2497 | .suspend = snd_ensoniq_suspend, | 2503 | .pm = SND_ENSONIQ_PM_OPS, |
2498 | .resume = snd_ensoniq_resume, | 2504 | }, |
2499 | #endif | ||
2500 | }; | 2505 | }; |
2501 | 2506 | ||
2502 | module_pci_driver(ens137x_driver); | 2507 | module_pci_driver(ens137x_driver); |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 82c8d8c5c52a..dbb81807bc1a 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -1321,35 +1321,30 @@ static int snd_es1938_put_double(struct snd_kcontrol *kcontrol, | |||
1321 | return change; | 1321 | return change; |
1322 | } | 1322 | } |
1323 | 1323 | ||
1324 | static unsigned int db_scale_master[] = { | 1324 | static const DECLARE_TLV_DB_RANGE(db_scale_master, |
1325 | TLV_DB_RANGE_HEAD(2), | ||
1326 | 0, 54, TLV_DB_SCALE_ITEM(-3600, 50, 1), | 1325 | 0, 54, TLV_DB_SCALE_ITEM(-3600, 50, 1), |
1327 | 54, 63, TLV_DB_SCALE_ITEM(-900, 100, 0), | 1326 | 54, 63, TLV_DB_SCALE_ITEM(-900, 100, 0), |
1328 | }; | 1327 | ); |
1329 | 1328 | ||
1330 | static unsigned int db_scale_audio1[] = { | 1329 | static const DECLARE_TLV_DB_RANGE(db_scale_audio1, |
1331 | TLV_DB_RANGE_HEAD(2), | ||
1332 | 0, 8, TLV_DB_SCALE_ITEM(-3300, 300, 1), | 1330 | 0, 8, TLV_DB_SCALE_ITEM(-3300, 300, 1), |
1333 | 8, 15, TLV_DB_SCALE_ITEM(-900, 150, 0), | 1331 | 8, 15, TLV_DB_SCALE_ITEM(-900, 150, 0), |
1334 | }; | 1332 | ); |
1335 | 1333 | ||
1336 | static unsigned int db_scale_audio2[] = { | 1334 | static const DECLARE_TLV_DB_RANGE(db_scale_audio2, |
1337 | TLV_DB_RANGE_HEAD(2), | ||
1338 | 0, 8, TLV_DB_SCALE_ITEM(-3450, 300, 1), | 1335 | 0, 8, TLV_DB_SCALE_ITEM(-3450, 300, 1), |
1339 | 8, 15, TLV_DB_SCALE_ITEM(-1050, 150, 0), | 1336 | 8, 15, TLV_DB_SCALE_ITEM(-1050, 150, 0), |
1340 | }; | 1337 | ); |
1341 | 1338 | ||
1342 | static unsigned int db_scale_mic[] = { | 1339 | static const DECLARE_TLV_DB_RANGE(db_scale_mic, |
1343 | TLV_DB_RANGE_HEAD(2), | ||
1344 | 0, 8, TLV_DB_SCALE_ITEM(-2400, 300, 1), | 1340 | 0, 8, TLV_DB_SCALE_ITEM(-2400, 300, 1), |
1345 | 8, 15, TLV_DB_SCALE_ITEM(0, 150, 0), | 1341 | 8, 15, TLV_DB_SCALE_ITEM(0, 150, 0), |
1346 | }; | 1342 | ); |
1347 | 1343 | ||
1348 | static unsigned int db_scale_line[] = { | 1344 | static const DECLARE_TLV_DB_RANGE(db_scale_line, |
1349 | TLV_DB_RANGE_HEAD(2), | ||
1350 | 0, 8, TLV_DB_SCALE_ITEM(-3150, 300, 1), | 1345 | 0, 8, TLV_DB_SCALE_ITEM(-3150, 300, 1), |
1351 | 8, 15, TLV_DB_SCALE_ITEM(-750, 150, 0), | 1346 | 8, 15, TLV_DB_SCALE_ITEM(-750, 150, 0), |
1352 | }; | 1347 | ); |
1353 | 1348 | ||
1354 | static const DECLARE_TLV_DB_SCALE(db_scale_capture, 0, 150, 0); | 1349 | static const DECLARE_TLV_DB_SCALE(db_scale_capture, 0, 150, 0); |
1355 | 1350 | ||
@@ -1474,9 +1469,10 @@ static unsigned char saved_regs[SAVED_REG_SIZE+1] = { | |||
1474 | }; | 1469 | }; |
1475 | 1470 | ||
1476 | 1471 | ||
1477 | static int es1938_suspend(struct pci_dev *pci, pm_message_t state) | 1472 | static int es1938_suspend(struct device *dev) |
1478 | { | 1473 | { |
1479 | struct snd_card *card = pci_get_drvdata(pci); | 1474 | struct pci_dev *pci = to_pci_dev(dev); |
1475 | struct snd_card *card = dev_get_drvdata(dev); | ||
1480 | struct es1938 *chip = card->private_data; | 1476 | struct es1938 *chip = card->private_data; |
1481 | unsigned char *s, *d; | 1477 | unsigned char *s, *d; |
1482 | 1478 | ||
@@ -1494,13 +1490,14 @@ static int es1938_suspend(struct pci_dev *pci, pm_message_t state) | |||
1494 | } | 1490 | } |
1495 | pci_disable_device(pci); | 1491 | pci_disable_device(pci); |
1496 | pci_save_state(pci); | 1492 | pci_save_state(pci); |
1497 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 1493 | pci_set_power_state(pci, PCI_D3hot); |
1498 | return 0; | 1494 | return 0; |
1499 | } | 1495 | } |
1500 | 1496 | ||
1501 | static int es1938_resume(struct pci_dev *pci) | 1497 | static int es1938_resume(struct device *dev) |
1502 | { | 1498 | { |
1503 | struct snd_card *card = pci_get_drvdata(pci); | 1499 | struct pci_dev *pci = to_pci_dev(dev); |
1500 | struct snd_card *card = dev_get_drvdata(dev); | ||
1504 | struct es1938 *chip = card->private_data; | 1501 | struct es1938 *chip = card->private_data; |
1505 | unsigned char *s, *d; | 1502 | unsigned char *s, *d; |
1506 | 1503 | ||
@@ -1534,6 +1531,11 @@ static int es1938_resume(struct pci_dev *pci) | |||
1534 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1531 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1535 | return 0; | 1532 | return 0; |
1536 | } | 1533 | } |
1534 | |||
1535 | static SIMPLE_DEV_PM_OPS(es1938_pm, es1938_suspend, es1938_resume); | ||
1536 | #define ES1938_PM_OPS &es1938_pm | ||
1537 | #else | ||
1538 | #define ES1938_PM_OPS NULL | ||
1537 | #endif /* CONFIG_PM */ | 1539 | #endif /* CONFIG_PM */ |
1538 | 1540 | ||
1539 | #ifdef SUPPORT_JOYSTICK | 1541 | #ifdef SUPPORT_JOYSTICK |
@@ -1887,10 +1889,9 @@ static struct pci_driver es1938_driver = { | |||
1887 | .id_table = snd_es1938_ids, | 1889 | .id_table = snd_es1938_ids, |
1888 | .probe = snd_es1938_probe, | 1890 | .probe = snd_es1938_probe, |
1889 | .remove = __devexit_p(snd_es1938_remove), | 1891 | .remove = __devexit_p(snd_es1938_remove), |
1890 | #ifdef CONFIG_PM | 1892 | .driver = { |
1891 | .suspend = es1938_suspend, | 1893 | .pm = ES1938_PM_OPS, |
1892 | .resume = es1938_resume, | 1894 | }, |
1893 | #endif | ||
1894 | }; | 1895 | }; |
1895 | 1896 | ||
1896 | module_pci_driver(es1938_driver); | 1897 | module_pci_driver(es1938_driver); |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 52b5c0bf90c1..fb4c90b99c00 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -2381,9 +2381,10 @@ static void snd_es1968_start_irq(struct es1968 *chip) | |||
2381 | /* | 2381 | /* |
2382 | * PM support | 2382 | * PM support |
2383 | */ | 2383 | */ |
2384 | static int es1968_suspend(struct pci_dev *pci, pm_message_t state) | 2384 | static int es1968_suspend(struct device *dev) |
2385 | { | 2385 | { |
2386 | struct snd_card *card = pci_get_drvdata(pci); | 2386 | struct pci_dev *pci = to_pci_dev(dev); |
2387 | struct snd_card *card = dev_get_drvdata(dev); | ||
2387 | struct es1968 *chip = card->private_data; | 2388 | struct es1968 *chip = card->private_data; |
2388 | 2389 | ||
2389 | if (! chip->do_pm) | 2390 | if (! chip->do_pm) |
@@ -2398,13 +2399,14 @@ static int es1968_suspend(struct pci_dev *pci, pm_message_t state) | |||
2398 | 2399 | ||
2399 | pci_disable_device(pci); | 2400 | pci_disable_device(pci); |
2400 | pci_save_state(pci); | 2401 | pci_save_state(pci); |
2401 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 2402 | pci_set_power_state(pci, PCI_D3hot); |
2402 | return 0; | 2403 | return 0; |
2403 | } | 2404 | } |
2404 | 2405 | ||
2405 | static int es1968_resume(struct pci_dev *pci) | 2406 | static int es1968_resume(struct device *dev) |
2406 | { | 2407 | { |
2407 | struct snd_card *card = pci_get_drvdata(pci); | 2408 | struct pci_dev *pci = to_pci_dev(dev); |
2409 | struct snd_card *card = dev_get_drvdata(dev); | ||
2408 | struct es1968 *chip = card->private_data; | 2410 | struct es1968 *chip = card->private_data; |
2409 | struct esschan *es; | 2411 | struct esschan *es; |
2410 | 2412 | ||
@@ -2454,6 +2456,11 @@ static int es1968_resume(struct pci_dev *pci) | |||
2454 | chip->in_suspend = 0; | 2456 | chip->in_suspend = 0; |
2455 | return 0; | 2457 | return 0; |
2456 | } | 2458 | } |
2459 | |||
2460 | static SIMPLE_DEV_PM_OPS(es1968_pm, es1968_suspend, es1968_resume); | ||
2461 | #define ES1968_PM_OPS &es1968_pm | ||
2462 | #else | ||
2463 | #define ES1968_PM_OPS NULL | ||
2457 | #endif /* CONFIG_PM */ | 2464 | #endif /* CONFIG_PM */ |
2458 | 2465 | ||
2459 | #ifdef SUPPORT_JOYSTICK | 2466 | #ifdef SUPPORT_JOYSTICK |
@@ -2903,10 +2910,9 @@ static struct pci_driver es1968_driver = { | |||
2903 | .id_table = snd_es1968_ids, | 2910 | .id_table = snd_es1968_ids, |
2904 | .probe = snd_es1968_probe, | 2911 | .probe = snd_es1968_probe, |
2905 | .remove = __devexit_p(snd_es1968_remove), | 2912 | .remove = __devexit_p(snd_es1968_remove), |
2906 | #ifdef CONFIG_PM | 2913 | .driver = { |
2907 | .suspend = es1968_suspend, | 2914 | .pm = ES1968_PM_OPS, |
2908 | .resume = es1968_resume, | 2915 | }, |
2909 | #endif | ||
2910 | }; | 2916 | }; |
2911 | 2917 | ||
2912 | module_pci_driver(es1968_driver); | 2918 | module_pci_driver(es1968_driver); |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index b32e8024ea86..522c8706f244 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -1369,9 +1369,10 @@ static unsigned char saved_regs[] = { | |||
1369 | FM801_CODEC_CTRL, FM801_I2S_MODE, FM801_VOLUME, FM801_GEN_CTRL, | 1369 | FM801_CODEC_CTRL, FM801_I2S_MODE, FM801_VOLUME, FM801_GEN_CTRL, |
1370 | }; | 1370 | }; |
1371 | 1371 | ||
1372 | static int snd_fm801_suspend(struct pci_dev *pci, pm_message_t state) | 1372 | static int snd_fm801_suspend(struct device *dev) |
1373 | { | 1373 | { |
1374 | struct snd_card *card = pci_get_drvdata(pci); | 1374 | struct pci_dev *pci = to_pci_dev(dev); |
1375 | struct snd_card *card = dev_get_drvdata(dev); | ||
1375 | struct fm801 *chip = card->private_data; | 1376 | struct fm801 *chip = card->private_data; |
1376 | int i; | 1377 | int i; |
1377 | 1378 | ||
@@ -1385,13 +1386,14 @@ static int snd_fm801_suspend(struct pci_dev *pci, pm_message_t state) | |||
1385 | 1386 | ||
1386 | pci_disable_device(pci); | 1387 | pci_disable_device(pci); |
1387 | pci_save_state(pci); | 1388 | pci_save_state(pci); |
1388 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 1389 | pci_set_power_state(pci, PCI_D3hot); |
1389 | return 0; | 1390 | return 0; |
1390 | } | 1391 | } |
1391 | 1392 | ||
1392 | static int snd_fm801_resume(struct pci_dev *pci) | 1393 | static int snd_fm801_resume(struct device *dev) |
1393 | { | 1394 | { |
1394 | struct snd_card *card = pci_get_drvdata(pci); | 1395 | struct pci_dev *pci = to_pci_dev(dev); |
1396 | struct snd_card *card = dev_get_drvdata(dev); | ||
1395 | struct fm801 *chip = card->private_data; | 1397 | struct fm801 *chip = card->private_data; |
1396 | int i; | 1398 | int i; |
1397 | 1399 | ||
@@ -1414,17 +1416,21 @@ static int snd_fm801_resume(struct pci_dev *pci) | |||
1414 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1416 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1415 | return 0; | 1417 | return 0; |
1416 | } | 1418 | } |
1417 | #endif | 1419 | |
1420 | static SIMPLE_DEV_PM_OPS(snd_fm801_pm, snd_fm801_suspend, snd_fm801_resume); | ||
1421 | #define SND_FM801_PM_OPS &snd_fm801_pm | ||
1422 | #else | ||
1423 | #define SND_FM801_PM_OPS NULL | ||
1424 | #endif /* CONFIG_PM */ | ||
1418 | 1425 | ||
1419 | static struct pci_driver fm801_driver = { | 1426 | static struct pci_driver fm801_driver = { |
1420 | .name = KBUILD_MODNAME, | 1427 | .name = KBUILD_MODNAME, |
1421 | .id_table = snd_fm801_ids, | 1428 | .id_table = snd_fm801_ids, |
1422 | .probe = snd_card_fm801_probe, | 1429 | .probe = snd_card_fm801_probe, |
1423 | .remove = __devexit_p(snd_card_fm801_remove), | 1430 | .remove = __devexit_p(snd_card_fm801_remove), |
1424 | #ifdef CONFIG_PM | 1431 | .driver = { |
1425 | .suspend = snd_fm801_suspend, | 1432 | .pm = SND_FM801_PM_OPS, |
1426 | .resume = snd_fm801_resume, | 1433 | }, |
1427 | #endif | ||
1428 | }; | 1434 | }; |
1429 | 1435 | ||
1430 | module_pci_driver(fm801_driver); | 1436 | module_pci_driver(fm801_driver); |
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index d03079764189..194d625c1f83 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -53,15 +53,14 @@ config SND_HDA_INPUT_BEEP | |||
53 | driver. This interface is used to generate digital beeps. | 53 | driver. This interface is used to generate digital beeps. |
54 | 54 | ||
55 | config SND_HDA_INPUT_BEEP_MODE | 55 | config SND_HDA_INPUT_BEEP_MODE |
56 | int "Digital beep registration mode (0=off, 1=on, 2=mute sw on/off)" | 56 | int "Digital beep registration mode (0=off, 1=on)" |
57 | depends on SND_HDA_INPUT_BEEP=y | 57 | depends on SND_HDA_INPUT_BEEP=y |
58 | default "1" | 58 | default "1" |
59 | range 0 2 | 59 | range 0 1 |
60 | help | 60 | help |
61 | Set 0 to disable the digital beep interface for HD-audio by default. | 61 | Set 0 to disable the digital beep interface for HD-audio by default. |
62 | Set 1 to always enable the digital beep interface for HD-audio by | 62 | Set 1 to always enable the digital beep interface for HD-audio by |
63 | default. Set 2 to control the beep device registration to input | 63 | default. |
64 | layer using a "Beep Switch" in mixer applications. | ||
65 | 64 | ||
66 | config SND_HDA_INPUT_JACK | 65 | config SND_HDA_INPUT_JACK |
67 | bool "Support jack plugging notification via input layer" | 66 | bool "Support jack plugging notification via input layer" |
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index f7520b9f909c..647218d69f68 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c | |||
@@ -727,7 +727,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
727 | models++; | 727 | models++; |
728 | } | 728 | } |
729 | } | 729 | } |
730 | if (id < 0) { | 730 | if (id < 0 && quirk) { |
731 | q = snd_pci_quirk_lookup(codec->bus->pci, quirk); | 731 | q = snd_pci_quirk_lookup(codec->bus->pci, quirk); |
732 | if (q) { | 732 | if (q) { |
733 | id = q->value; | 733 | id = q->value; |
@@ -736,7 +736,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
736 | #endif | 736 | #endif |
737 | } | 737 | } |
738 | } | 738 | } |
739 | if (id < 0) { | 739 | if (id < 0 && quirk) { |
740 | for (q = quirk; q->subvendor; q++) { | 740 | for (q = quirk; q->subvendor; q++) { |
741 | unsigned int vendorid = | 741 | unsigned int vendorid = |
742 | q->subdevice | (q->subvendor << 16); | 742 | q->subdevice | (q->subvendor << 16); |
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 60738e52b8f9..0bc2315b181d 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c | |||
@@ -162,50 +162,20 @@ static int snd_hda_do_attach(struct hda_beep *beep) | |||
162 | return 0; | 162 | return 0; |
163 | } | 163 | } |
164 | 164 | ||
165 | static void snd_hda_do_register(struct work_struct *work) | ||
166 | { | ||
167 | struct hda_beep *beep = | ||
168 | container_of(work, struct hda_beep, register_work); | ||
169 | |||
170 | mutex_lock(&beep->mutex); | ||
171 | if (beep->enabled && !beep->dev) | ||
172 | snd_hda_do_attach(beep); | ||
173 | mutex_unlock(&beep->mutex); | ||
174 | } | ||
175 | |||
176 | static void snd_hda_do_unregister(struct work_struct *work) | ||
177 | { | ||
178 | struct hda_beep *beep = | ||
179 | container_of(work, struct hda_beep, unregister_work.work); | ||
180 | |||
181 | mutex_lock(&beep->mutex); | ||
182 | if (!beep->enabled && beep->dev) | ||
183 | snd_hda_do_detach(beep); | ||
184 | mutex_unlock(&beep->mutex); | ||
185 | } | ||
186 | |||
187 | int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) | 165 | int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) |
188 | { | 166 | { |
189 | struct hda_beep *beep = codec->beep; | 167 | struct hda_beep *beep = codec->beep; |
190 | enable = !!enable; | 168 | if (!beep) |
191 | if (beep == NULL) | ||
192 | return 0; | 169 | return 0; |
170 | enable = !!enable; | ||
193 | if (beep->enabled != enable) { | 171 | if (beep->enabled != enable) { |
194 | beep->enabled = enable; | 172 | beep->enabled = enable; |
195 | if (!enable) { | 173 | if (!enable) { |
174 | cancel_work_sync(&beep->beep_work); | ||
196 | /* turn off beep */ | 175 | /* turn off beep */ |
197 | snd_hda_codec_write(beep->codec, beep->nid, 0, | 176 | snd_hda_codec_write(beep->codec, beep->nid, 0, |
198 | AC_VERB_SET_BEEP_CONTROL, 0); | 177 | AC_VERB_SET_BEEP_CONTROL, 0); |
199 | } | 178 | } |
200 | if (beep->mode == HDA_BEEP_MODE_SWREG) { | ||
201 | if (enable) { | ||
202 | cancel_delayed_work(&beep->unregister_work); | ||
203 | schedule_work(&beep->register_work); | ||
204 | } else { | ||
205 | schedule_delayed_work(&beep->unregister_work, | ||
206 | HZ); | ||
207 | } | ||
208 | } | ||
209 | return 1; | 179 | return 1; |
210 | } | 180 | } |
211 | return 0; | 181 | return 0; |
@@ -215,6 +185,7 @@ EXPORT_SYMBOL_HDA(snd_hda_enable_beep_device); | |||
215 | int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) | 185 | int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) |
216 | { | 186 | { |
217 | struct hda_beep *beep; | 187 | struct hda_beep *beep; |
188 | int err; | ||
218 | 189 | ||
219 | if (!snd_hda_get_bool_hint(codec, "beep")) | 190 | if (!snd_hda_get_bool_hint(codec, "beep")) |
220 | return 0; /* disabled explicitly by hints */ | 191 | return 0; /* disabled explicitly by hints */ |
@@ -232,21 +203,16 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) | |||
232 | 203 | ||
233 | beep->nid = nid; | 204 | beep->nid = nid; |
234 | beep->codec = codec; | 205 | beep->codec = codec; |
235 | beep->mode = codec->beep_mode; | ||
236 | codec->beep = beep; | 206 | codec->beep = beep; |
237 | 207 | ||
238 | INIT_WORK(&beep->register_work, &snd_hda_do_register); | ||
239 | INIT_DELAYED_WORK(&beep->unregister_work, &snd_hda_do_unregister); | ||
240 | INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); | 208 | INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); |
241 | mutex_init(&beep->mutex); | 209 | mutex_init(&beep->mutex); |
242 | 210 | ||
243 | if (beep->mode == HDA_BEEP_MODE_ON) { | 211 | err = snd_hda_do_attach(beep); |
244 | int err = snd_hda_do_attach(beep); | 212 | if (err < 0) { |
245 | if (err < 0) { | 213 | kfree(beep); |
246 | kfree(beep); | 214 | codec->beep = NULL; |
247 | codec->beep = NULL; | 215 | return err; |
248 | return err; | ||
249 | } | ||
250 | } | 216 | } |
251 | 217 | ||
252 | return 0; | 218 | return 0; |
@@ -257,8 +223,6 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) | |||
257 | { | 223 | { |
258 | struct hda_beep *beep = codec->beep; | 224 | struct hda_beep *beep = codec->beep; |
259 | if (beep) { | 225 | if (beep) { |
260 | cancel_work_sync(&beep->register_work); | ||
261 | cancel_delayed_work(&beep->unregister_work); | ||
262 | if (beep->dev) | 226 | if (beep->dev) |
263 | snd_hda_do_detach(beep); | 227 | snd_hda_do_detach(beep); |
264 | codec->beep = NULL; | 228 | codec->beep = NULL; |
@@ -266,3 +230,31 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) | |||
266 | } | 230 | } |
267 | } | 231 | } |
268 | EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); | 232 | EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); |
233 | |||
234 | /* get/put callbacks for beep mute mixer switches */ | ||
235 | int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol, | ||
236 | struct snd_ctl_elem_value *ucontrol) | ||
237 | { | ||
238 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
239 | struct hda_beep *beep = codec->beep; | ||
240 | if (beep) { | ||
241 | ucontrol->value.integer.value[0] = | ||
242 | ucontrol->value.integer.value[1] = | ||
243 | beep->enabled; | ||
244 | return 0; | ||
245 | } | ||
246 | return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); | ||
247 | } | ||
248 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get_beep); | ||
249 | |||
250 | int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, | ||
251 | struct snd_ctl_elem_value *ucontrol) | ||
252 | { | ||
253 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
254 | struct hda_beep *beep = codec->beep; | ||
255 | if (beep) | ||
256 | snd_hda_enable_beep_device(codec, | ||
257 | *ucontrol->value.integer.value); | ||
258 | return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
259 | } | ||
260 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep); | ||
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index 55f0647458c7..4dc6933bc655 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h | |||
@@ -26,21 +26,16 @@ | |||
26 | 26 | ||
27 | #define HDA_BEEP_MODE_OFF 0 | 27 | #define HDA_BEEP_MODE_OFF 0 |
28 | #define HDA_BEEP_MODE_ON 1 | 28 | #define HDA_BEEP_MODE_ON 1 |
29 | #define HDA_BEEP_MODE_SWREG 2 | ||
30 | 29 | ||
31 | /* beep information */ | 30 | /* beep information */ |
32 | struct hda_beep { | 31 | struct hda_beep { |
33 | struct input_dev *dev; | 32 | struct input_dev *dev; |
34 | struct hda_codec *codec; | 33 | struct hda_codec *codec; |
35 | unsigned int mode; | ||
36 | char phys[32]; | 34 | char phys[32]; |
37 | int tone; | 35 | int tone; |
38 | hda_nid_t nid; | 36 | hda_nid_t nid; |
39 | unsigned int enabled:1; | 37 | unsigned int enabled:1; |
40 | unsigned int request_enable:1; | ||
41 | unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ | 38 | unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ |
42 | struct work_struct register_work; /* registration work */ | ||
43 | struct delayed_work unregister_work; /* unregistration work */ | ||
44 | struct work_struct beep_work; /* scheduled task for beep event */ | 39 | struct work_struct beep_work; /* scheduled task for beep event */ |
45 | struct mutex mutex; | 40 | struct mutex mutex; |
46 | }; | 41 | }; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 51cb2a2e4fce..88a9c20eb7a2 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2676,25 +2676,6 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | |||
2676 | } | 2676 | } |
2677 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put); | 2677 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put); |
2678 | 2678 | ||
2679 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | ||
2680 | /** | ||
2681 | * snd_hda_mixer_amp_switch_put_beep - Put callback for a beep AMP switch | ||
2682 | * | ||
2683 | * This function calls snd_hda_enable_beep_device(), which behaves differently | ||
2684 | * depending on beep_mode option. | ||
2685 | */ | ||
2686 | int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, | ||
2687 | struct snd_ctl_elem_value *ucontrol) | ||
2688 | { | ||
2689 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2690 | long *valp = ucontrol->value.integer.value; | ||
2691 | |||
2692 | snd_hda_enable_beep_device(codec, *valp); | ||
2693 | return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
2694 | } | ||
2695 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep); | ||
2696 | #endif /* CONFIG_SND_HDA_INPUT_BEEP */ | ||
2697 | |||
2698 | /* | 2679 | /* |
2699 | * bound volume controls | 2680 | * bound volume controls |
2700 | * | 2681 | * |
@@ -3509,22 +3490,52 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, | |||
3509 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); | 3490 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); |
3510 | 3491 | ||
3511 | /* | 3492 | /* |
3493 | * supported power states check | ||
3494 | */ | ||
3495 | static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg, | ||
3496 | unsigned int power_state) | ||
3497 | { | ||
3498 | int sup = snd_hda_param_read(codec, fg, AC_PAR_POWER_STATE); | ||
3499 | |||
3500 | if (sup < 0) | ||
3501 | return false; | ||
3502 | if (sup & power_state) | ||
3503 | return true; | ||
3504 | else | ||
3505 | return false; | ||
3506 | } | ||
3507 | |||
3508 | /* | ||
3512 | * set power state of the codec | 3509 | * set power state of the codec |
3513 | */ | 3510 | */ |
3514 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 3511 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, |
3515 | unsigned int power_state) | 3512 | unsigned int power_state) |
3516 | { | 3513 | { |
3514 | int count; | ||
3515 | unsigned int state; | ||
3516 | |||
3517 | if (codec->patch_ops.set_power_state) { | 3517 | if (codec->patch_ops.set_power_state) { |
3518 | codec->patch_ops.set_power_state(codec, fg, power_state); | 3518 | codec->patch_ops.set_power_state(codec, fg, power_state); |
3519 | return; | 3519 | return; |
3520 | } | 3520 | } |
3521 | 3521 | ||
3522 | /* this delay seems necessary to avoid click noise at power-down */ | 3522 | /* this delay seems necessary to avoid click noise at power-down */ |
3523 | if (power_state == AC_PWRST_D3) | 3523 | if (power_state == AC_PWRST_D3) { |
3524 | msleep(100); | 3524 | /* transition time less than 10ms for power down */ |
3525 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | 3525 | bool epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS); |
3526 | power_state); | 3526 | msleep(epss ? 10 : 100); |
3527 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | 3527 | } |
3528 | |||
3529 | /* repeat power states setting at most 10 times*/ | ||
3530 | for (count = 0; count < 10; count++) { | ||
3531 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | ||
3532 | power_state); | ||
3533 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | ||
3534 | state = snd_hda_codec_read(codec, fg, 0, | ||
3535 | AC_VERB_GET_POWER_STATE, 0); | ||
3536 | if (!(state & AC_PWRST_ERROR)) | ||
3537 | break; | ||
3538 | } | ||
3528 | } | 3539 | } |
3529 | 3540 | ||
3530 | #ifdef CONFIG_SND_HDA_HWDEP | 3541 | #ifdef CONFIG_SND_HDA_HWDEP |
@@ -3545,7 +3556,7 @@ static inline void hda_exec_init_verbs(struct hda_codec *codec) {} | |||
3545 | static void hda_call_codec_suspend(struct hda_codec *codec) | 3556 | static void hda_call_codec_suspend(struct hda_codec *codec) |
3546 | { | 3557 | { |
3547 | if (codec->patch_ops.suspend) | 3558 | if (codec->patch_ops.suspend) |
3548 | codec->patch_ops.suspend(codec, PMSG_SUSPEND); | 3559 | codec->patch_ops.suspend(codec); |
3549 | hda_cleanup_all_streams(codec); | 3560 | hda_cleanup_all_streams(codec); |
3550 | hda_set_power_state(codec, | 3561 | hda_set_power_state(codec, |
3551 | codec->afg ? codec->afg : codec->mfg, | 3562 | codec->afg ? codec->afg : codec->mfg, |
@@ -4418,6 +4429,13 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) | |||
4418 | cancel_delayed_work_sync(&codec->power_work); | 4429 | cancel_delayed_work_sync(&codec->power_work); |
4419 | 4430 | ||
4420 | spin_lock(&codec->power_lock); | 4431 | spin_lock(&codec->power_lock); |
4432 | /* If the power down delayed work was cancelled above before starting, | ||
4433 | * then there is no need to go through power up here. | ||
4434 | */ | ||
4435 | if (codec->power_on) { | ||
4436 | spin_unlock(&codec->power_lock); | ||
4437 | return; | ||
4438 | } | ||
4421 | trace_hda_power_up(codec); | 4439 | trace_hda_power_up(codec); |
4422 | snd_hda_update_power_acct(codec); | 4440 | snd_hda_update_power_acct(codec); |
4423 | codec->power_on = 1; | 4441 | codec->power_on = 1; |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 2fdaadbb4326..c422d330ca54 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -323,6 +323,9 @@ enum { | |||
323 | #define AC_PWRST_D1 0x01 | 323 | #define AC_PWRST_D1 0x01 |
324 | #define AC_PWRST_D2 0x02 | 324 | #define AC_PWRST_D2 0x02 |
325 | #define AC_PWRST_D3 0x03 | 325 | #define AC_PWRST_D3 0x03 |
326 | #define AC_PWRST_ERROR (1<<8) | ||
327 | #define AC_PWRST_CLK_STOP_OK (1<<9) | ||
328 | #define AC_PWRST_SETTING_RESET (1<<10) | ||
326 | 329 | ||
327 | /* Processing capabilies */ | 330 | /* Processing capabilies */ |
328 | #define AC_PCAP_BENIGN (1<<0) | 331 | #define AC_PCAP_BENIGN (1<<0) |
@@ -703,7 +706,7 @@ struct hda_codec_ops { | |||
703 | void (*set_power_state)(struct hda_codec *codec, hda_nid_t fg, | 706 | void (*set_power_state)(struct hda_codec *codec, hda_nid_t fg, |
704 | unsigned int power_state); | 707 | unsigned int power_state); |
705 | #ifdef CONFIG_PM | 708 | #ifdef CONFIG_PM |
706 | int (*suspend)(struct hda_codec *codec, pm_message_t state); | 709 | int (*suspend)(struct hda_codec *codec); |
707 | int (*resume)(struct hda_codec *codec); | 710 | int (*resume)(struct hda_codec *codec); |
708 | #endif | 711 | #endif |
709 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 712 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 7757536b9d5f..c8aced182fd1 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -72,7 +72,7 @@ static int enable_msi = -1; | |||
72 | static char *patch[SNDRV_CARDS]; | 72 | static char *patch[SNDRV_CARDS]; |
73 | #endif | 73 | #endif |
74 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 74 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
75 | static int beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = | 75 | static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = |
76 | CONFIG_SND_HDA_INPUT_BEEP_MODE}; | 76 | CONFIG_SND_HDA_INPUT_BEEP_MODE}; |
77 | #endif | 77 | #endif |
78 | 78 | ||
@@ -103,9 +103,9 @@ module_param_array(patch, charp, NULL, 0444); | |||
103 | MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface."); | 103 | MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface."); |
104 | #endif | 104 | #endif |
105 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 105 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
106 | module_param_array(beep_mode, int, NULL, 0444); | 106 | module_param_array(beep_mode, bool, NULL, 0444); |
107 | MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " | 107 | MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " |
108 | "(0=off, 1=on, 2=mute switch on/off) (default=1)."); | 108 | "(0=off, 1=on) (default=1)."); |
109 | #endif | 109 | #endif |
110 | 110 | ||
111 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 111 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
@@ -151,6 +151,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," | |||
151 | "{Intel, CPT}," | 151 | "{Intel, CPT}," |
152 | "{Intel, PPT}," | 152 | "{Intel, PPT}," |
153 | "{Intel, LPT}," | 153 | "{Intel, LPT}," |
154 | "{Intel, HPT}," | ||
154 | "{Intel, PBG}," | 155 | "{Intel, PBG}," |
155 | "{Intel, SCH}," | 156 | "{Intel, SCH}," |
156 | "{ATI, SB450}," | 157 | "{ATI, SB450}," |
@@ -535,6 +536,7 @@ enum { | |||
535 | #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ | 536 | #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ |
536 | #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ | 537 | #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ |
537 | #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ | 538 | #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ |
539 | #define AZX_DCAPS_POSFIX_COMBO (1 << 24) /* Use COMBO as default */ | ||
538 | 540 | ||
539 | /* quirks for ATI SB / AMD Hudson */ | 541 | /* quirks for ATI SB / AMD Hudson */ |
540 | #define AZX_DCAPS_PRESET_ATI_SB \ | 542 | #define AZX_DCAPS_PRESET_ATI_SB \ |
@@ -2403,9 +2405,10 @@ static void azx_power_notify(struct hda_bus *bus) | |||
2403 | * power management | 2405 | * power management |
2404 | */ | 2406 | */ |
2405 | 2407 | ||
2406 | static int azx_suspend(struct pci_dev *pci, pm_message_t state) | 2408 | static int azx_suspend(struct device *dev) |
2407 | { | 2409 | { |
2408 | struct snd_card *card = pci_get_drvdata(pci); | 2410 | struct pci_dev *pci = to_pci_dev(dev); |
2411 | struct snd_card *card = dev_get_drvdata(dev); | ||
2409 | struct azx *chip = card->private_data; | 2412 | struct azx *chip = card->private_data; |
2410 | struct azx_pcm *p; | 2413 | struct azx_pcm *p; |
2411 | 2414 | ||
@@ -2424,13 +2427,14 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |||
2424 | pci_disable_msi(chip->pci); | 2427 | pci_disable_msi(chip->pci); |
2425 | pci_disable_device(pci); | 2428 | pci_disable_device(pci); |
2426 | pci_save_state(pci); | 2429 | pci_save_state(pci); |
2427 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 2430 | pci_set_power_state(pci, PCI_D3hot); |
2428 | return 0; | 2431 | return 0; |
2429 | } | 2432 | } |
2430 | 2433 | ||
2431 | static int azx_resume(struct pci_dev *pci) | 2434 | static int azx_resume(struct device *dev) |
2432 | { | 2435 | { |
2433 | struct snd_card *card = pci_get_drvdata(pci); | 2436 | struct pci_dev *pci = to_pci_dev(dev); |
2437 | struct snd_card *card = dev_get_drvdata(dev); | ||
2434 | struct azx *chip = card->private_data; | 2438 | struct azx *chip = card->private_data; |
2435 | 2439 | ||
2436 | pci_set_power_state(pci, PCI_D0); | 2440 | pci_set_power_state(pci, PCI_D0); |
@@ -2455,6 +2459,12 @@ static int azx_resume(struct pci_dev *pci) | |||
2455 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2459 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
2456 | return 0; | 2460 | return 0; |
2457 | } | 2461 | } |
2462 | static SIMPLE_DEV_PM_OPS(azx_pm, azx_suspend, azx_resume); | ||
2463 | #define AZX_PM_OPS &azx_pm | ||
2464 | #else | ||
2465 | #define azx_suspend(dev) | ||
2466 | #define azx_resume(dev) | ||
2467 | #define AZX_PM_OPS NULL | ||
2458 | #endif /* CONFIG_PM */ | 2468 | #endif /* CONFIG_PM */ |
2459 | 2469 | ||
2460 | 2470 | ||
@@ -2521,13 +2531,13 @@ static void azx_vs_set_state(struct pci_dev *pci, | |||
2521 | disabled ? "Disabling" : "Enabling", | 2531 | disabled ? "Disabling" : "Enabling", |
2522 | pci_name(chip->pci)); | 2532 | pci_name(chip->pci)); |
2523 | if (disabled) { | 2533 | if (disabled) { |
2524 | azx_suspend(pci, PMSG_FREEZE); | 2534 | azx_suspend(&pci->dev); |
2525 | chip->disabled = true; | 2535 | chip->disabled = true; |
2526 | snd_hda_lock_devices(chip->bus); | 2536 | snd_hda_lock_devices(chip->bus); |
2527 | } else { | 2537 | } else { |
2528 | snd_hda_unlock_devices(chip->bus); | 2538 | snd_hda_unlock_devices(chip->bus); |
2529 | chip->disabled = false; | 2539 | chip->disabled = false; |
2530 | azx_resume(pci); | 2540 | azx_resume(&pci->dev); |
2531 | } | 2541 | } |
2532 | } | 2542 | } |
2533 | } | 2543 | } |
@@ -2731,6 +2741,10 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
2731 | snd_printd(SFX "Using LPIB position fix\n"); | 2741 | snd_printd(SFX "Using LPIB position fix\n"); |
2732 | return POS_FIX_LPIB; | 2742 | return POS_FIX_LPIB; |
2733 | } | 2743 | } |
2744 | if (chip->driver_caps & AZX_DCAPS_POSFIX_COMBO) { | ||
2745 | snd_printd(SFX "Using COMBO position fix\n"); | ||
2746 | return POS_FIX_COMBO; | ||
2747 | } | ||
2734 | return POS_FIX_AUTO; | 2748 | return POS_FIX_AUTO; |
2735 | } | 2749 | } |
2736 | 2750 | ||
@@ -3243,7 +3257,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
3243 | /* CPT */ | 3257 | /* CPT */ |
3244 | { PCI_DEVICE(0x8086, 0x1c20), | 3258 | { PCI_DEVICE(0x8086, 0x1c20), |
3245 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3259 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
3246 | AZX_DCAPS_BUFSIZE }, | 3260 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, |
3247 | /* PBG */ | 3261 | /* PBG */ |
3248 | { PCI_DEVICE(0x8086, 0x1d20), | 3262 | { PCI_DEVICE(0x8086, 0x1d20), |
3249 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3263 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
@@ -3251,11 +3265,15 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
3251 | /* Panther Point */ | 3265 | /* Panther Point */ |
3252 | { PCI_DEVICE(0x8086, 0x1e20), | 3266 | { PCI_DEVICE(0x8086, 0x1e20), |
3253 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3267 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
3254 | AZX_DCAPS_BUFSIZE}, | 3268 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, |
3255 | /* Lynx Point */ | 3269 | /* Lynx Point */ |
3256 | { PCI_DEVICE(0x8086, 0x8c20), | 3270 | { PCI_DEVICE(0x8086, 0x8c20), |
3257 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3271 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
3258 | AZX_DCAPS_BUFSIZE}, | 3272 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, |
3273 | /* Haswell */ | ||
3274 | { PCI_DEVICE(0x8086, 0x0c0c), | ||
3275 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | | ||
3276 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, | ||
3259 | /* SCH */ | 3277 | /* SCH */ |
3260 | { PCI_DEVICE(0x8086, 0x811b), | 3278 | { PCI_DEVICE(0x8086, 0x811b), |
3261 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | | 3279 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | |
@@ -3341,6 +3359,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
3341 | /* VIA VT8251/VT8237A */ | 3359 | /* VIA VT8251/VT8237A */ |
3342 | { PCI_DEVICE(0x1106, 0x3288), | 3360 | { PCI_DEVICE(0x1106, 0x3288), |
3343 | .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, | 3361 | .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, |
3362 | /* VIA GFX VT7122/VX900 */ | ||
3363 | { PCI_DEVICE(0x1106, 0x9170), .driver_data = AZX_DRIVER_GENERIC }, | ||
3364 | /* VIA GFX VT6122/VX11 */ | ||
3365 | { PCI_DEVICE(0x1106, 0x9140), .driver_data = AZX_DRIVER_GENERIC }, | ||
3344 | /* SIS966 */ | 3366 | /* SIS966 */ |
3345 | { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS }, | 3367 | { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS }, |
3346 | /* ULI M5461 */ | 3368 | /* ULI M5461 */ |
@@ -3398,10 +3420,9 @@ static struct pci_driver azx_driver = { | |||
3398 | .id_table = azx_ids, | 3420 | .id_table = azx_ids, |
3399 | .probe = azx_probe, | 3421 | .probe = azx_probe, |
3400 | .remove = __devexit_p(azx_remove), | 3422 | .remove = __devexit_p(azx_remove), |
3401 | #ifdef CONFIG_PM | 3423 | .driver = { |
3402 | .suspend = azx_suspend, | 3424 | .pm = AZX_PM_OPS, |
3403 | .resume = azx_resume, | 3425 | }, |
3404 | #endif | ||
3405 | }; | 3426 | }; |
3406 | 3427 | ||
3407 | module_pci_driver(azx_driver); | 3428 | module_pci_driver(azx_driver); |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 2dd1c113a4c1..aaccc0236bda 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c | |||
@@ -127,10 +127,15 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec) | |||
127 | static void jack_detect_update(struct hda_codec *codec, | 127 | static void jack_detect_update(struct hda_codec *codec, |
128 | struct hda_jack_tbl *jack) | 128 | struct hda_jack_tbl *jack) |
129 | { | 129 | { |
130 | if (jack->jack_dirty || !jack->jack_detect) { | 130 | if (!jack->jack_dirty) |
131 | return; | ||
132 | |||
133 | if (jack->phantom_jack) | ||
134 | jack->pin_sense = AC_PINSENSE_PRESENCE; | ||
135 | else | ||
131 | jack->pin_sense = read_pin_sense(codec, jack->nid); | 136 | jack->pin_sense = read_pin_sense(codec, jack->nid); |
132 | jack->jack_dirty = 0; | 137 | |
133 | } | 138 | jack->jack_dirty = 0; |
134 | } | 139 | } |
135 | 140 | ||
136 | /** | 141 | /** |
@@ -264,8 +269,8 @@ static void hda_free_jack_priv(struct snd_jack *jack) | |||
264 | * This assigns a jack-detection kctl to the given pin. The kcontrol | 269 | * This assigns a jack-detection kctl to the given pin. The kcontrol |
265 | * will have the given name and index. | 270 | * will have the given name and index. |
266 | */ | 271 | */ |
267 | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | 272 | static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, |
268 | const char *name, int idx) | 273 | const char *name, int idx, bool phantom_jack) |
269 | { | 274 | { |
270 | struct hda_jack_tbl *jack; | 275 | struct hda_jack_tbl *jack; |
271 | struct snd_kcontrol *kctl; | 276 | struct snd_kcontrol *kctl; |
@@ -283,47 +288,81 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | |||
283 | if (err < 0) | 288 | if (err < 0) |
284 | return err; | 289 | return err; |
285 | jack->kctl = kctl; | 290 | jack->kctl = kctl; |
291 | jack->phantom_jack = !!phantom_jack; | ||
292 | |||
286 | state = snd_hda_jack_detect(codec, nid); | 293 | state = snd_hda_jack_detect(codec, nid); |
287 | snd_kctl_jack_report(codec->bus->card, kctl, state); | 294 | snd_kctl_jack_report(codec->bus->card, kctl, state); |
288 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 295 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
289 | jack->type = get_input_jack_type(codec, nid); | 296 | if (!phantom_jack) { |
290 | err = snd_jack_new(codec->bus->card, name, jack->type, &jack->jack); | 297 | jack->type = get_input_jack_type(codec, nid); |
291 | if (err < 0) | 298 | err = snd_jack_new(codec->bus->card, name, jack->type, |
292 | return err; | 299 | &jack->jack); |
293 | jack->jack->private_data = jack; | 300 | if (err < 0) |
294 | jack->jack->private_free = hda_free_jack_priv; | 301 | return err; |
295 | snd_jack_report(jack->jack, state ? jack->type : 0); | 302 | jack->jack->private_data = jack; |
303 | jack->jack->private_free = hda_free_jack_priv; | ||
304 | snd_jack_report(jack->jack, state ? jack->type : 0); | ||
305 | } | ||
296 | #endif | 306 | #endif |
297 | return 0; | 307 | return 0; |
298 | } | 308 | } |
309 | |||
310 | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | ||
311 | const char *name, int idx) | ||
312 | { | ||
313 | return __snd_hda_jack_add_kctl(codec, nid, name, idx, false); | ||
314 | } | ||
299 | EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); | 315 | EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); |
300 | 316 | ||
317 | /* get the unique index number for the given kctl name */ | ||
318 | static int get_unique_index(struct hda_codec *codec, const char *name, int idx) | ||
319 | { | ||
320 | struct hda_jack_tbl *jack; | ||
321 | int i, len = strlen(name); | ||
322 | again: | ||
323 | jack = codec->jacktbl.list; | ||
324 | for (i = 0; i < codec->jacktbl.used; i++, jack++) { | ||
325 | /* jack->kctl.id contains "XXX Jack" name string with index */ | ||
326 | if (jack->kctl && | ||
327 | !strncmp(name, jack->kctl->id.name, len) && | ||
328 | !strcmp(" Jack", jack->kctl->id.name + len) && | ||
329 | jack->kctl->id.index == idx) { | ||
330 | idx++; | ||
331 | goto again; | ||
332 | } | ||
333 | } | ||
334 | return idx; | ||
335 | } | ||
336 | |||
301 | static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, | 337 | static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, |
302 | const struct auto_pin_cfg *cfg, | 338 | const struct auto_pin_cfg *cfg) |
303 | char *lastname, int *lastidx) | ||
304 | { | 339 | { |
305 | unsigned int def_conf, conn; | 340 | unsigned int def_conf, conn; |
306 | char name[44]; | 341 | char name[44]; |
307 | int idx, err; | 342 | int idx, err; |
343 | bool phantom_jack; | ||
308 | 344 | ||
309 | if (!nid) | 345 | if (!nid) |
310 | return 0; | 346 | return 0; |
311 | if (!is_jack_detectable(codec, nid)) | ||
312 | return 0; | ||
313 | def_conf = snd_hda_codec_get_pincfg(codec, nid); | 347 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
314 | conn = get_defcfg_connect(def_conf); | 348 | conn = get_defcfg_connect(def_conf); |
315 | if (conn != AC_JACK_PORT_COMPLEX) | 349 | if (conn == AC_JACK_PORT_NONE) |
316 | return 0; | 350 | return 0; |
351 | phantom_jack = (conn != AC_JACK_PORT_COMPLEX) || | ||
352 | !is_jack_detectable(codec, nid); | ||
317 | 353 | ||
318 | snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); | 354 | snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); |
319 | if (!strcmp(name, lastname) && idx == *lastidx) | 355 | if (phantom_jack) |
320 | idx++; | 356 | /* Example final name: "Internal Mic Phantom Jack" */ |
321 | strncpy(lastname, name, 44); | 357 | strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); |
322 | *lastidx = idx; | 358 | idx = get_unique_index(codec, name, idx); |
323 | err = snd_hda_jack_add_kctl(codec, nid, name, idx); | 359 | err = __snd_hda_jack_add_kctl(codec, nid, name, idx, phantom_jack); |
324 | if (err < 0) | 360 | if (err < 0) |
325 | return err; | 361 | return err; |
326 | return snd_hda_jack_detect_enable(codec, nid, 0); | 362 | |
363 | if (!phantom_jack) | ||
364 | return snd_hda_jack_detect_enable(codec, nid, 0); | ||
365 | return 0; | ||
327 | } | 366 | } |
328 | 367 | ||
329 | /** | 368 | /** |
@@ -333,42 +372,41 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, | |||
333 | const struct auto_pin_cfg *cfg) | 372 | const struct auto_pin_cfg *cfg) |
334 | { | 373 | { |
335 | const hda_nid_t *p; | 374 | const hda_nid_t *p; |
336 | int i, err, lastidx = 0; | 375 | int i, err; |
337 | char lastname[44] = ""; | ||
338 | 376 | ||
339 | for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { | 377 | for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { |
340 | err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); | 378 | err = add_jack_kctl(codec, *p, cfg); |
341 | if (err < 0) | 379 | if (err < 0) |
342 | return err; | 380 | return err; |
343 | } | 381 | } |
344 | for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { | 382 | for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { |
345 | if (*p == *cfg->line_out_pins) /* might be duplicated */ | 383 | if (*p == *cfg->line_out_pins) /* might be duplicated */ |
346 | break; | 384 | break; |
347 | err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); | 385 | err = add_jack_kctl(codec, *p, cfg); |
348 | if (err < 0) | 386 | if (err < 0) |
349 | return err; | 387 | return err; |
350 | } | 388 | } |
351 | for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { | 389 | for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { |
352 | if (*p == *cfg->line_out_pins) /* might be duplicated */ | 390 | if (*p == *cfg->line_out_pins) /* might be duplicated */ |
353 | break; | 391 | break; |
354 | err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); | 392 | err = add_jack_kctl(codec, *p, cfg); |
355 | if (err < 0) | 393 | if (err < 0) |
356 | return err; | 394 | return err; |
357 | } | 395 | } |
358 | for (i = 0; i < cfg->num_inputs; i++) { | 396 | for (i = 0; i < cfg->num_inputs; i++) { |
359 | err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx); | 397 | err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg); |
360 | if (err < 0) | 398 | if (err < 0) |
361 | return err; | 399 | return err; |
362 | } | 400 | } |
363 | for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { | 401 | for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { |
364 | err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); | 402 | err = add_jack_kctl(codec, *p, cfg); |
365 | if (err < 0) | 403 | if (err < 0) |
366 | return err; | 404 | return err; |
367 | } | 405 | } |
368 | err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx); | 406 | err = add_jack_kctl(codec, cfg->dig_in_pin, cfg); |
369 | if (err < 0) | 407 | if (err < 0) |
370 | return err; | 408 | return err; |
371 | err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx); | 409 | err = add_jack_kctl(codec, cfg->mono_out_pin, cfg); |
372 | if (err < 0) | 410 | if (err < 0) |
373 | return err; | 411 | return err; |
374 | return 0; | 412 | return 0; |
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index 8ae52465ec5d..a9803da633c0 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h | |||
@@ -23,6 +23,7 @@ struct hda_jack_tbl { | |||
23 | unsigned int pin_sense; /* cached pin-sense value */ | 23 | unsigned int pin_sense; /* cached pin-sense value */ |
24 | unsigned int jack_detect:1; /* capable of jack-detection? */ | 24 | unsigned int jack_detect:1; /* capable of jack-detection? */ |
25 | unsigned int jack_dirty:1; /* needs to update? */ | 25 | unsigned int jack_dirty:1; /* needs to update? */ |
26 | unsigned int phantom_jack:1; /* a fixed, always present port? */ | ||
26 | struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ | 27 | struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ |
27 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 28 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
28 | int type; | 29 | int type; |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 9a096a8e0fc5..1b4c12941baa 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -89,7 +89,7 @@ | |||
89 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 89 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
90 | .subdevice = HDA_SUBDEV_AMP_FLAG, \ | 90 | .subdevice = HDA_SUBDEV_AMP_FLAG, \ |
91 | .info = snd_hda_mixer_amp_switch_info, \ | 91 | .info = snd_hda_mixer_amp_switch_info, \ |
92 | .get = snd_hda_mixer_amp_switch_get, \ | 92 | .get = snd_hda_mixer_amp_switch_get_beep, \ |
93 | .put = snd_hda_mixer_amp_switch_put_beep, \ | 93 | .put = snd_hda_mixer_amp_switch_put_beep, \ |
94 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } | 94 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } |
95 | #else | 95 | #else |
@@ -121,6 +121,8 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, | |||
121 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | 121 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, |
122 | struct snd_ctl_elem_value *ucontrol); | 122 | struct snd_ctl_elem_value *ucontrol); |
123 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 123 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
124 | int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol, | ||
125 | struct snd_ctl_elem_value *ucontrol); | ||
124 | int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, | 126 | int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, |
125 | struct snd_ctl_elem_value *ucontrol); | 127 | struct snd_ctl_elem_value *ucontrol); |
126 | #endif | 128 | #endif |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index e59e2f059b6e..7e46258fc700 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -426,10 +426,10 @@ static void print_digital_conv(struct snd_info_buffer *buffer, | |||
426 | 426 | ||
427 | static const char *get_pwr_state(u32 state) | 427 | static const char *get_pwr_state(u32 state) |
428 | { | 428 | { |
429 | static const char * const buf[4] = { | 429 | static const char * const buf[] = { |
430 | "D0", "D1", "D2", "D3" | 430 | "D0", "D1", "D2", "D3", "D3cold" |
431 | }; | 431 | }; |
432 | if (state < 4) | 432 | if (state < ARRAY_SIZE(buf)) |
433 | return buf[state]; | 433 | return buf[state]; |
434 | return "UNKNOWN"; | 434 | return "UNKNOWN"; |
435 | } | 435 | } |
@@ -451,14 +451,21 @@ static void print_power_state(struct snd_info_buffer *buffer, | |||
451 | int sup = snd_hda_param_read(codec, nid, AC_PAR_POWER_STATE); | 451 | int sup = snd_hda_param_read(codec, nid, AC_PAR_POWER_STATE); |
452 | int pwr = snd_hda_codec_read(codec, nid, 0, | 452 | int pwr = snd_hda_codec_read(codec, nid, 0, |
453 | AC_VERB_GET_POWER_STATE, 0); | 453 | AC_VERB_GET_POWER_STATE, 0); |
454 | if (sup) | 454 | if (sup != -1) |
455 | snd_iprintf(buffer, " Power states: %s\n", | 455 | snd_iprintf(buffer, " Power states: %s\n", |
456 | bits_names(sup, names, ARRAY_SIZE(names))); | 456 | bits_names(sup, names, ARRAY_SIZE(names))); |
457 | 457 | ||
458 | snd_iprintf(buffer, " Power: setting=%s, actual=%s\n", | 458 | snd_iprintf(buffer, " Power: setting=%s, actual=%s", |
459 | get_pwr_state(pwr & AC_PWRST_SETTING), | 459 | get_pwr_state(pwr & AC_PWRST_SETTING), |
460 | get_pwr_state((pwr & AC_PWRST_ACTUAL) >> | 460 | get_pwr_state((pwr & AC_PWRST_ACTUAL) >> |
461 | AC_PWRST_ACTUAL_SHIFT)); | 461 | AC_PWRST_ACTUAL_SHIFT)); |
462 | if (pwr & AC_PWRST_ERROR) | ||
463 | snd_iprintf(buffer, ", Error"); | ||
464 | if (pwr & AC_PWRST_CLK_STOP_OK) | ||
465 | snd_iprintf(buffer, ", Clock-stop-OK"); | ||
466 | if (pwr & AC_PWRST_SETTING_RESET) | ||
467 | snd_iprintf(buffer, ", Setting-reset"); | ||
468 | snd_iprintf(buffer, "\n"); | ||
462 | } | 469 | } |
463 | 470 | ||
464 | static void print_unsol_cap(struct snd_info_buffer *buffer, | 471 | static void print_unsol_cap(struct snd_info_buffer *buffer, |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index d8b2d6dee986..0208fa121e5a 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -642,7 +642,7 @@ static void ad198x_free(struct hda_codec *codec) | |||
642 | } | 642 | } |
643 | 643 | ||
644 | #ifdef CONFIG_PM | 644 | #ifdef CONFIG_PM |
645 | static int ad198x_suspend(struct hda_codec *codec, pm_message_t state) | 645 | static int ad198x_suspend(struct hda_codec *codec) |
646 | { | 646 | { |
647 | ad198x_shutup(codec); | 647 | ad198x_shutup(codec); |
648 | return 0; | 648 | return 0; |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 9647ed4d7929..0c4c1a61b378 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -1892,7 +1892,7 @@ static int cs421x_parse_auto_config(struct hda_codec *codec) | |||
1892 | Manage PDREF, when transitioning to D3hot | 1892 | Manage PDREF, when transitioning to D3hot |
1893 | (DAC,ADC) -> D3, PDREF=1, AFG->D3 | 1893 | (DAC,ADC) -> D3, PDREF=1, AFG->D3 |
1894 | */ | 1894 | */ |
1895 | static int cs421x_suspend(struct hda_codec *codec, pm_message_t state) | 1895 | static int cs421x_suspend(struct hda_codec *codec) |
1896 | { | 1896 | { |
1897 | struct cs_spec *spec = codec->spec; | 1897 | struct cs_spec *spec = codec->spec; |
1898 | unsigned int coef; | 1898 | unsigned int coef; |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 2bf99fc1cbf2..14361184ae1e 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -554,7 +554,7 @@ static int conexant_build_controls(struct hda_codec *codec) | |||
554 | } | 554 | } |
555 | 555 | ||
556 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 556 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
557 | static int conexant_suspend(struct hda_codec *codec, pm_message_t state) | 557 | static int conexant_suspend(struct hda_codec *codec) |
558 | { | 558 | { |
559 | snd_hda_shutup_pins(codec); | 559 | snd_hda_shutup_pins(codec); |
560 | return 0; | 560 | return 0; |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index ad319d4dc32f..641408dc28c0 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -85,7 +85,7 @@ struct hdmi_spec { | |||
85 | * Non-generic ATI/NVIDIA specific | 85 | * Non-generic ATI/NVIDIA specific |
86 | */ | 86 | */ |
87 | struct hda_multi_out multiout; | 87 | struct hda_multi_out multiout; |
88 | const struct hda_pcm_stream *pcm_playback; | 88 | struct hda_pcm_stream pcm_playback; |
89 | }; | 89 | }; |
90 | 90 | ||
91 | 91 | ||
@@ -787,7 +787,7 @@ static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | |||
787 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); | 787 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); |
788 | 788 | ||
789 | printk(KERN_INFO | 789 | printk(KERN_INFO |
790 | "HDMI CP event: CODEC=%d PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | 790 | "HDMI CP event: CODEC=%d TAG=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", |
791 | codec->addr, | 791 | codec->addr, |
792 | tag, | 792 | tag, |
793 | subtag, | 793 | subtag, |
@@ -876,7 +876,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
876 | struct hdmi_spec_per_pin *per_pin; | 876 | struct hdmi_spec_per_pin *per_pin; |
877 | struct hdmi_eld *eld; | 877 | struct hdmi_eld *eld; |
878 | struct hdmi_spec_per_cvt *per_cvt = NULL; | 878 | struct hdmi_spec_per_cvt *per_cvt = NULL; |
879 | int pinctl; | ||
880 | 879 | ||
881 | /* Validate hinfo */ | 880 | /* Validate hinfo */ |
882 | pin_idx = hinfo_to_pin_index(spec, hinfo); | 881 | pin_idx = hinfo_to_pin_index(spec, hinfo); |
@@ -912,11 +911,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
912 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, | 911 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, |
913 | AC_VERB_SET_CONNECT_SEL, | 912 | AC_VERB_SET_CONNECT_SEL, |
914 | mux_idx); | 913 | mux_idx); |
915 | pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, | ||
916 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
917 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, | ||
918 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
919 | pinctl | PIN_OUT); | ||
920 | snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); | 914 | snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); |
921 | 915 | ||
922 | /* Initially set the converter's capabilities */ | 916 | /* Initially set the converter's capabilities */ |
@@ -1153,11 +1147,17 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
1153 | struct hdmi_spec *spec = codec->spec; | 1147 | struct hdmi_spec *spec = codec->spec; |
1154 | int pin_idx = hinfo_to_pin_index(spec, hinfo); | 1148 | int pin_idx = hinfo_to_pin_index(spec, hinfo); |
1155 | hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; | 1149 | hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; |
1150 | int pinctl; | ||
1156 | 1151 | ||
1157 | hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); | 1152 | hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); |
1158 | 1153 | ||
1159 | hdmi_setup_audio_infoframe(codec, pin_idx, substream); | 1154 | hdmi_setup_audio_infoframe(codec, pin_idx, substream); |
1160 | 1155 | ||
1156 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, | ||
1157 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
1158 | snd_hda_codec_write(codec, pin_nid, 0, | ||
1159 | AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl | PIN_OUT); | ||
1160 | |||
1161 | return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); | 1161 | return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); |
1162 | } | 1162 | } |
1163 | 1163 | ||
@@ -1277,23 +1277,34 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) | |||
1277 | return 0; | 1277 | return 0; |
1278 | } | 1278 | } |
1279 | 1279 | ||
1280 | static int generic_hdmi_init(struct hda_codec *codec) | 1280 | static int generic_hdmi_init_per_pins(struct hda_codec *codec) |
1281 | { | 1281 | { |
1282 | struct hdmi_spec *spec = codec->spec; | 1282 | struct hdmi_spec *spec = codec->spec; |
1283 | int pin_idx; | 1283 | int pin_idx; |
1284 | 1284 | ||
1285 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1285 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1286 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1286 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
1287 | hda_nid_t pin_nid = per_pin->pin_nid; | ||
1288 | struct hdmi_eld *eld = &per_pin->sink_eld; | 1287 | struct hdmi_eld *eld = &per_pin->sink_eld; |
1289 | 1288 | ||
1290 | hdmi_init_pin(codec, pin_nid); | ||
1291 | snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); | ||
1292 | |||
1293 | per_pin->codec = codec; | 1289 | per_pin->codec = codec; |
1294 | INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); | 1290 | INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); |
1295 | snd_hda_eld_proc_new(codec, eld, pin_idx); | 1291 | snd_hda_eld_proc_new(codec, eld, pin_idx); |
1296 | } | 1292 | } |
1293 | return 0; | ||
1294 | } | ||
1295 | |||
1296 | static int generic_hdmi_init(struct hda_codec *codec) | ||
1297 | { | ||
1298 | struct hdmi_spec *spec = codec->spec; | ||
1299 | int pin_idx; | ||
1300 | |||
1301 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | ||
1302 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | ||
1303 | hda_nid_t pin_nid = per_pin->pin_nid; | ||
1304 | |||
1305 | hdmi_init_pin(codec, pin_nid); | ||
1306 | snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); | ||
1307 | } | ||
1297 | snd_hda_jack_report_sync(codec); | 1308 | snd_hda_jack_report_sync(codec); |
1298 | return 0; | 1309 | return 0; |
1299 | } | 1310 | } |
@@ -1338,6 +1349,7 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
1338 | return -EINVAL; | 1349 | return -EINVAL; |
1339 | } | 1350 | } |
1340 | codec->patch_ops = generic_hdmi_patch_ops; | 1351 | codec->patch_ops = generic_hdmi_patch_ops; |
1352 | generic_hdmi_init_per_pins(codec); | ||
1341 | 1353 | ||
1342 | init_channel_allocations(); | 1354 | init_channel_allocations(); |
1343 | 1355 | ||
@@ -1352,45 +1364,65 @@ static int simple_playback_build_pcms(struct hda_codec *codec) | |||
1352 | { | 1364 | { |
1353 | struct hdmi_spec *spec = codec->spec; | 1365 | struct hdmi_spec *spec = codec->spec; |
1354 | struct hda_pcm *info = spec->pcm_rec; | 1366 | struct hda_pcm *info = spec->pcm_rec; |
1355 | int i; | 1367 | unsigned int chans; |
1368 | struct hda_pcm_stream *pstr; | ||
1356 | 1369 | ||
1357 | codec->num_pcms = spec->num_cvts; | 1370 | codec->num_pcms = 1; |
1358 | codec->pcm_info = info; | 1371 | codec->pcm_info = info; |
1359 | 1372 | ||
1360 | for (i = 0; i < codec->num_pcms; i++, info++) { | 1373 | chans = get_wcaps(codec, spec->cvts[0].cvt_nid); |
1361 | unsigned int chans; | 1374 | chans = get_wcaps_channels(chans); |
1362 | struct hda_pcm_stream *pstr; | ||
1363 | |||
1364 | chans = get_wcaps(codec, spec->cvts[i].cvt_nid); | ||
1365 | chans = get_wcaps_channels(chans); | ||
1366 | 1375 | ||
1367 | info->name = get_hdmi_pcm_name(i); | 1376 | info->name = get_hdmi_pcm_name(0); |
1368 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 1377 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
1369 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | 1378 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; |
1370 | snd_BUG_ON(!spec->pcm_playback); | 1379 | *pstr = spec->pcm_playback; |
1371 | *pstr = *spec->pcm_playback; | 1380 | pstr->nid = spec->cvts[0].cvt_nid; |
1372 | pstr->nid = spec->cvts[i].cvt_nid; | 1381 | if (pstr->channels_max <= 2 && chans && chans <= 16) |
1373 | if (pstr->channels_max <= 2 && chans && chans <= 16) | 1382 | pstr->channels_max = chans; |
1374 | pstr->channels_max = chans; | ||
1375 | } | ||
1376 | 1383 | ||
1377 | return 0; | 1384 | return 0; |
1378 | } | 1385 | } |
1379 | 1386 | ||
1387 | /* unsolicited event for jack sensing */ | ||
1388 | static void simple_hdmi_unsol_event(struct hda_codec *codec, | ||
1389 | unsigned int res) | ||
1390 | { | ||
1391 | snd_hda_jack_set_dirty_all(codec); | ||
1392 | snd_hda_jack_report_sync(codec); | ||
1393 | } | ||
1394 | |||
1395 | /* generic_hdmi_build_jack can be used for simple_hdmi, too, | ||
1396 | * as long as spec->pins[] is set correctly | ||
1397 | */ | ||
1398 | #define simple_hdmi_build_jack generic_hdmi_build_jack | ||
1399 | |||
1380 | static int simple_playback_build_controls(struct hda_codec *codec) | 1400 | static int simple_playback_build_controls(struct hda_codec *codec) |
1381 | { | 1401 | { |
1382 | struct hdmi_spec *spec = codec->spec; | 1402 | struct hdmi_spec *spec = codec->spec; |
1383 | int err; | 1403 | int err; |
1384 | int i; | ||
1385 | 1404 | ||
1386 | for (i = 0; i < codec->num_pcms; i++) { | 1405 | err = snd_hda_create_spdif_out_ctls(codec, |
1387 | err = snd_hda_create_spdif_out_ctls(codec, | 1406 | spec->cvts[0].cvt_nid, |
1388 | spec->cvts[i].cvt_nid, | 1407 | spec->cvts[0].cvt_nid); |
1389 | spec->cvts[i].cvt_nid); | 1408 | if (err < 0) |
1390 | if (err < 0) | 1409 | return err; |
1391 | return err; | 1410 | return simple_hdmi_build_jack(codec, 0); |
1392 | } | 1411 | } |
1393 | 1412 | ||
1413 | static int simple_playback_init(struct hda_codec *codec) | ||
1414 | { | ||
1415 | struct hdmi_spec *spec = codec->spec; | ||
1416 | hda_nid_t pin = spec->pins[0].pin_nid; | ||
1417 | |||
1418 | snd_hda_codec_write(codec, pin, 0, | ||
1419 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
1420 | /* some codecs require to unmute the pin */ | ||
1421 | if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) | ||
1422 | snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1423 | AMP_OUT_UNMUTE); | ||
1424 | snd_hda_jack_detect_enable(codec, pin, pin); | ||
1425 | snd_hda_jack_report_sync(codec); | ||
1394 | return 0; | 1426 | return 0; |
1395 | } | 1427 | } |
1396 | 1428 | ||
@@ -1418,7 +1450,15 @@ static const hda_nid_t nvhdmi_con_nids_7x[4] = { | |||
1418 | 0x6, 0x8, 0xa, 0xc, | 1450 | 0x6, 0x8, 0xa, 0xc, |
1419 | }; | 1451 | }; |
1420 | 1452 | ||
1421 | static const struct hda_verb nvhdmi_basic_init_7x[] = { | 1453 | static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = { |
1454 | /* set audio protect on */ | ||
1455 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | ||
1456 | /* enable digital output on pin widget */ | ||
1457 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1458 | {} /* terminator */ | ||
1459 | }; | ||
1460 | |||
1461 | static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = { | ||
1422 | /* set audio protect on */ | 1462 | /* set audio protect on */ |
1423 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | 1463 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, |
1424 | /* enable digital output on pin widget */ | 1464 | /* enable digital output on pin widget */ |
@@ -1446,9 +1486,15 @@ static const struct hda_verb nvhdmi_basic_init_7x[] = { | |||
1446 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | 1486 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) |
1447 | #endif | 1487 | #endif |
1448 | 1488 | ||
1449 | static int nvhdmi_7x_init(struct hda_codec *codec) | 1489 | static int nvhdmi_7x_init_2ch(struct hda_codec *codec) |
1450 | { | 1490 | { |
1451 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | 1491 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch); |
1492 | return 0; | ||
1493 | } | ||
1494 | |||
1495 | static int nvhdmi_7x_init_8ch(struct hda_codec *codec) | ||
1496 | { | ||
1497 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch); | ||
1452 | return 0; | 1498 | return 0; |
1453 | } | 1499 | } |
1454 | 1500 | ||
@@ -1524,6 +1570,50 @@ static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
1524 | stream_tag, format, substream); | 1570 | stream_tag, format, substream); |
1525 | } | 1571 | } |
1526 | 1572 | ||
1573 | static const struct hda_pcm_stream simple_pcm_playback = { | ||
1574 | .substreams = 1, | ||
1575 | .channels_min = 2, | ||
1576 | .channels_max = 2, | ||
1577 | .ops = { | ||
1578 | .open = simple_playback_pcm_open, | ||
1579 | .close = simple_playback_pcm_close, | ||
1580 | .prepare = simple_playback_pcm_prepare | ||
1581 | }, | ||
1582 | }; | ||
1583 | |||
1584 | static const struct hda_codec_ops simple_hdmi_patch_ops = { | ||
1585 | .build_controls = simple_playback_build_controls, | ||
1586 | .build_pcms = simple_playback_build_pcms, | ||
1587 | .init = simple_playback_init, | ||
1588 | .free = simple_playback_free, | ||
1589 | .unsol_event = simple_hdmi_unsol_event, | ||
1590 | }; | ||
1591 | |||
1592 | static int patch_simple_hdmi(struct hda_codec *codec, | ||
1593 | hda_nid_t cvt_nid, hda_nid_t pin_nid) | ||
1594 | { | ||
1595 | struct hdmi_spec *spec; | ||
1596 | |||
1597 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1598 | if (!spec) | ||
1599 | return -ENOMEM; | ||
1600 | |||
1601 | codec->spec = spec; | ||
1602 | |||
1603 | spec->multiout.num_dacs = 0; /* no analog */ | ||
1604 | spec->multiout.max_channels = 2; | ||
1605 | spec->multiout.dig_out_nid = cvt_nid; | ||
1606 | spec->num_cvts = 1; | ||
1607 | spec->num_pins = 1; | ||
1608 | spec->cvts[0].cvt_nid = cvt_nid; | ||
1609 | spec->pins[0].pin_nid = pin_nid; | ||
1610 | spec->pcm_playback = simple_pcm_playback; | ||
1611 | |||
1612 | codec->patch_ops = simple_hdmi_patch_ops; | ||
1613 | |||
1614 | return 0; | ||
1615 | } | ||
1616 | |||
1527 | static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, | 1617 | static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, |
1528 | int channels) | 1618 | int channels) |
1529 | { | 1619 | { |
@@ -1696,54 +1786,20 @@ static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { | |||
1696 | }, | 1786 | }, |
1697 | }; | 1787 | }; |
1698 | 1788 | ||
1699 | static const struct hda_pcm_stream nvhdmi_pcm_playback_2ch = { | ||
1700 | .substreams = 1, | ||
1701 | .channels_min = 2, | ||
1702 | .channels_max = 2, | ||
1703 | .nid = nvhdmi_master_con_nid_7x, | ||
1704 | .rates = SUPPORTED_RATES, | ||
1705 | .maxbps = SUPPORTED_MAXBPS, | ||
1706 | .formats = SUPPORTED_FORMATS, | ||
1707 | .ops = { | ||
1708 | .open = simple_playback_pcm_open, | ||
1709 | .close = simple_playback_pcm_close, | ||
1710 | .prepare = simple_playback_pcm_prepare | ||
1711 | }, | ||
1712 | }; | ||
1713 | |||
1714 | static const struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { | ||
1715 | .build_controls = simple_playback_build_controls, | ||
1716 | .build_pcms = simple_playback_build_pcms, | ||
1717 | .init = nvhdmi_7x_init, | ||
1718 | .free = simple_playback_free, | ||
1719 | }; | ||
1720 | |||
1721 | static const struct hda_codec_ops nvhdmi_patch_ops_2ch = { | ||
1722 | .build_controls = simple_playback_build_controls, | ||
1723 | .build_pcms = simple_playback_build_pcms, | ||
1724 | .init = nvhdmi_7x_init, | ||
1725 | .free = simple_playback_free, | ||
1726 | }; | ||
1727 | |||
1728 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | 1789 | static int patch_nvhdmi_2ch(struct hda_codec *codec) |
1729 | { | 1790 | { |
1730 | struct hdmi_spec *spec; | 1791 | struct hdmi_spec *spec; |
1792 | int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x, | ||
1793 | nvhdmi_master_pin_nid_7x); | ||
1794 | if (err < 0) | ||
1795 | return err; | ||
1731 | 1796 | ||
1732 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1797 | codec->patch_ops.init = nvhdmi_7x_init_2ch; |
1733 | if (spec == NULL) | 1798 | /* override the PCM rates, etc, as the codec doesn't give full list */ |
1734 | return -ENOMEM; | 1799 | spec = codec->spec; |
1735 | 1800 | spec->pcm_playback.rates = SUPPORTED_RATES; | |
1736 | codec->spec = spec; | 1801 | spec->pcm_playback.maxbps = SUPPORTED_MAXBPS; |
1737 | 1802 | spec->pcm_playback.formats = SUPPORTED_FORMATS; | |
1738 | spec->multiout.num_dacs = 0; /* no analog */ | ||
1739 | spec->multiout.max_channels = 2; | ||
1740 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | ||
1741 | spec->num_cvts = 1; | ||
1742 | spec->cvts[0].cvt_nid = nvhdmi_master_con_nid_7x; | ||
1743 | spec->pcm_playback = &nvhdmi_pcm_playback_2ch; | ||
1744 | |||
1745 | codec->patch_ops = nvhdmi_patch_ops_2ch; | ||
1746 | |||
1747 | return 0; | 1803 | return 0; |
1748 | } | 1804 | } |
1749 | 1805 | ||
@@ -1751,13 +1807,12 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | |||
1751 | { | 1807 | { |
1752 | struct hdmi_spec *spec; | 1808 | struct hdmi_spec *spec; |
1753 | int err = patch_nvhdmi_2ch(codec); | 1809 | int err = patch_nvhdmi_2ch(codec); |
1754 | |||
1755 | if (err < 0) | 1810 | if (err < 0) |
1756 | return err; | 1811 | return err; |
1757 | spec = codec->spec; | 1812 | spec = codec->spec; |
1758 | spec->multiout.max_channels = 8; | 1813 | spec->multiout.max_channels = 8; |
1759 | spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x; | 1814 | spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; |
1760 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; | 1815 | codec->patch_ops.init = nvhdmi_7x_init_8ch; |
1761 | 1816 | ||
1762 | /* Initialize the audio infoframe channel mask and checksum to something | 1817 | /* Initialize the audio infoframe channel mask and checksum to something |
1763 | * valid */ | 1818 | * valid */ |
@@ -1801,69 +1856,26 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
1801 | return 0; | 1856 | return 0; |
1802 | } | 1857 | } |
1803 | 1858 | ||
1804 | static const struct hda_pcm_stream atihdmi_pcm_digital_playback = { | 1859 | static int patch_atihdmi(struct hda_codec *codec) |
1805 | .substreams = 1, | ||
1806 | .channels_min = 2, | ||
1807 | .channels_max = 2, | ||
1808 | .nid = ATIHDMI_CVT_NID, | ||
1809 | .ops = { | ||
1810 | .open = simple_playback_pcm_open, | ||
1811 | .close = simple_playback_pcm_close, | ||
1812 | .prepare = atihdmi_playback_pcm_prepare | ||
1813 | }, | ||
1814 | }; | ||
1815 | |||
1816 | static const struct hda_verb atihdmi_basic_init[] = { | ||
1817 | /* enable digital output on pin widget */ | ||
1818 | { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
1819 | {} /* terminator */ | ||
1820 | }; | ||
1821 | |||
1822 | static int atihdmi_init(struct hda_codec *codec) | ||
1823 | { | 1860 | { |
1824 | struct hdmi_spec *spec = codec->spec; | 1861 | struct hdmi_spec *spec; |
1825 | 1862 | int err = patch_simple_hdmi(codec, ATIHDMI_CVT_NID, ATIHDMI_PIN_NID); | |
1826 | snd_hda_sequence_write(codec, atihdmi_basic_init); | 1863 | if (err < 0) |
1827 | /* SI codec requires to unmute the pin */ | 1864 | return err; |
1828 | if (get_wcaps(codec, spec->pins[0].pin_nid) & AC_WCAP_OUT_AMP) | 1865 | spec = codec->spec; |
1829 | snd_hda_codec_write(codec, spec->pins[0].pin_nid, 0, | 1866 | spec->pcm_playback.ops.prepare = atihdmi_playback_pcm_prepare; |
1830 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1831 | AMP_OUT_UNMUTE); | ||
1832 | return 0; | 1867 | return 0; |
1833 | } | 1868 | } |
1834 | 1869 | ||
1835 | static const struct hda_codec_ops atihdmi_patch_ops = { | 1870 | /* VIA HDMI Implementation */ |
1836 | .build_controls = simple_playback_build_controls, | 1871 | #define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ |
1837 | .build_pcms = simple_playback_build_pcms, | 1872 | #define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ |
1838 | .init = atihdmi_init, | ||
1839 | .free = simple_playback_free, | ||
1840 | }; | ||
1841 | 1873 | ||
1842 | 1874 | static int patch_via_hdmi(struct hda_codec *codec) | |
1843 | static int patch_atihdmi(struct hda_codec *codec) | ||
1844 | { | 1875 | { |
1845 | struct hdmi_spec *spec; | 1876 | return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); |
1846 | |||
1847 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1848 | if (spec == NULL) | ||
1849 | return -ENOMEM; | ||
1850 | |||
1851 | codec->spec = spec; | ||
1852 | |||
1853 | spec->multiout.num_dacs = 0; /* no analog */ | ||
1854 | spec->multiout.max_channels = 2; | ||
1855 | spec->multiout.dig_out_nid = ATIHDMI_CVT_NID; | ||
1856 | spec->num_cvts = 1; | ||
1857 | spec->cvts[0].cvt_nid = ATIHDMI_CVT_NID; | ||
1858 | spec->pins[0].pin_nid = ATIHDMI_PIN_NID; | ||
1859 | spec->pcm_playback = &atihdmi_pcm_digital_playback; | ||
1860 | |||
1861 | codec->patch_ops = atihdmi_patch_ops; | ||
1862 | |||
1863 | return 0; | ||
1864 | } | 1877 | } |
1865 | 1878 | ||
1866 | |||
1867 | /* | 1879 | /* |
1868 | * patch entries | 1880 | * patch entries |
1869 | */ | 1881 | */ |
@@ -1902,8 +1914,13 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | |||
1902 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_generic_hdmi }, | 1914 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_generic_hdmi }, |
1903 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_generic_hdmi }, | 1915 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_generic_hdmi }, |
1904 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, | 1916 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, |
1917 | { .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1905 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | 1918 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, |
1906 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | 1919 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, |
1920 | { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | ||
1921 | { .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | ||
1922 | { .id = 0x11069f84, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1923 | { .id = 0x11069f85, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, | ||
1907 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | 1924 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, |
1908 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, | 1925 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, |
1909 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, | 1926 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, |
@@ -1911,6 +1928,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | |||
1911 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | 1928 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, |
1912 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, | 1929 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, |
1913 | { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, | 1930 | { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, |
1931 | { .id = 0x80862807, .name = "Haswell HDMI", .patch = patch_generic_hdmi }, | ||
1914 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, | 1932 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, |
1915 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, | 1933 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, |
1916 | {} /* terminator */ | 1934 | {} /* terminator */ |
@@ -1948,8 +1966,13 @@ MODULE_ALIAS("snd-hda-codec-id:10de0041"); | |||
1948 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); | 1966 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); |
1949 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); | 1967 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); |
1950 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); | 1968 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); |
1969 | MODULE_ALIAS("snd-hda-codec-id:10de0051"); | ||
1951 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | 1970 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
1952 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | 1971 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
1972 | MODULE_ALIAS("snd-hda-codec-id:11069f80"); | ||
1973 | MODULE_ALIAS("snd-hda-codec-id:11069f81"); | ||
1974 | MODULE_ALIAS("snd-hda-codec-id:11069f84"); | ||
1975 | MODULE_ALIAS("snd-hda-codec-id:11069f85"); | ||
1953 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); | 1976 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); |
1954 | MODULE_ALIAS("snd-hda-codec-id:80860054"); | 1977 | MODULE_ALIAS("snd-hda-codec-id:80860054"); |
1955 | MODULE_ALIAS("snd-hda-codec-id:80862801"); | 1978 | MODULE_ALIAS("snd-hda-codec-id:80862801"); |
@@ -1958,6 +1981,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862803"); | |||
1958 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | 1981 | MODULE_ALIAS("snd-hda-codec-id:80862804"); |
1959 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | 1982 | MODULE_ALIAS("snd-hda-codec-id:80862805"); |
1960 | MODULE_ALIAS("snd-hda-codec-id:80862806"); | 1983 | MODULE_ALIAS("snd-hda-codec-id:80862806"); |
1984 | MODULE_ALIAS("snd-hda-codec-id:80862807"); | ||
1961 | MODULE_ALIAS("snd-hda-codec-id:80862880"); | 1985 | MODULE_ALIAS("snd-hda-codec-id:80862880"); |
1962 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | 1986 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); |
1963 | 1987 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index aa4c25e0f327..f141395dfee6 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -170,10 +170,10 @@ struct alc_spec { | |||
170 | hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; | 170 | hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; |
171 | unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; | 171 | unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; |
172 | int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */ | 172 | int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */ |
173 | hda_nid_t inv_dmic_pin; | ||
173 | 174 | ||
174 | /* hooks */ | 175 | /* hooks */ |
175 | void (*init_hook)(struct hda_codec *codec); | 176 | void (*init_hook)(struct hda_codec *codec); |
176 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); | ||
177 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 177 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
178 | void (*power_hook)(struct hda_codec *codec); | 178 | void (*power_hook)(struct hda_codec *codec); |
179 | #endif | 179 | #endif |
@@ -201,6 +201,8 @@ struct alc_spec { | |||
201 | unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ | 201 | unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ |
202 | unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ | 202 | unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ |
203 | unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ | 203 | unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ |
204 | unsigned int inv_dmic_fixup:1; /* has inverted digital-mic workaround */ | ||
205 | unsigned int inv_dmic_muted:1; /* R-ch of inv d-mic is muted? */ | ||
204 | 206 | ||
205 | /* auto-mute control */ | 207 | /* auto-mute control */ |
206 | int automute_mode; | 208 | int automute_mode; |
@@ -298,6 +300,39 @@ static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx) | |||
298 | } | 300 | } |
299 | 301 | ||
300 | static void call_update_outputs(struct hda_codec *codec); | 302 | static void call_update_outputs(struct hda_codec *codec); |
303 | static void alc_inv_dmic_sync(struct hda_codec *codec, bool force); | ||
304 | |||
305 | /* for shared I/O, change the pin-control accordingly */ | ||
306 | static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic) | ||
307 | { | ||
308 | struct alc_spec *spec = codec->spec; | ||
309 | unsigned int val; | ||
310 | hda_nid_t pin = spec->autocfg.inputs[1].pin; | ||
311 | /* NOTE: this assumes that there are only two inputs, the | ||
312 | * first is the real internal mic and the second is HP/mic jack. | ||
313 | */ | ||
314 | |||
315 | val = snd_hda_get_default_vref(codec, pin); | ||
316 | |||
317 | /* This pin does not have vref caps - let's enable vref on pin 0x18 | ||
318 | instead, as suggested by Realtek */ | ||
319 | if (val == AC_PINCTL_VREF_HIZ) { | ||
320 | const hda_nid_t vref_pin = 0x18; | ||
321 | /* Sanity check pin 0x18 */ | ||
322 | if (get_wcaps_type(get_wcaps(codec, vref_pin)) == AC_WID_PIN && | ||
323 | get_defcfg_connect(snd_hda_codec_get_pincfg(codec, vref_pin)) == AC_JACK_PORT_NONE) { | ||
324 | unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin); | ||
325 | if (vref_val != AC_PINCTL_VREF_HIZ) | ||
326 | snd_hda_set_pin_ctl(codec, vref_pin, PIN_IN | (set_as_mic ? vref_val : 0)); | ||
327 | } | ||
328 | } | ||
329 | |||
330 | val = set_as_mic ? val | PIN_IN : PIN_HP; | ||
331 | snd_hda_set_pin_ctl(codec, pin, val); | ||
332 | |||
333 | spec->automute_speaker = !set_as_mic; | ||
334 | call_update_outputs(codec); | ||
335 | } | ||
301 | 336 | ||
302 | /* select the given imux item; either unmute exclusively or select the route */ | 337 | /* select the given imux item; either unmute exclusively or select the route */ |
303 | static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, | 338 | static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, |
@@ -325,21 +360,8 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, | |||
325 | return 0; | 360 | return 0; |
326 | spec->cur_mux[adc_idx] = idx; | 361 | spec->cur_mux[adc_idx] = idx; |
327 | 362 | ||
328 | /* for shared I/O, change the pin-control accordingly */ | 363 | if (spec->shared_mic_hp) |
329 | if (spec->shared_mic_hp) { | 364 | update_shared_mic_hp(codec, spec->cur_mux[adc_idx]); |
330 | unsigned int val; | ||
331 | hda_nid_t pin = spec->autocfg.inputs[1].pin; | ||
332 | /* NOTE: this assumes that there are only two inputs, the | ||
333 | * first is the real internal mic and the second is HP jack. | ||
334 | */ | ||
335 | if (spec->cur_mux[adc_idx]) | ||
336 | val = snd_hda_get_default_vref(codec, pin) | PIN_IN; | ||
337 | else | ||
338 | val = PIN_HP; | ||
339 | snd_hda_set_pin_ctl(codec, pin, val); | ||
340 | spec->automute_speaker = !spec->cur_mux[adc_idx]; | ||
341 | call_update_outputs(codec); | ||
342 | } | ||
343 | 365 | ||
344 | if (spec->dyn_adc_switch) { | 366 | if (spec->dyn_adc_switch) { |
345 | alc_dyn_adc_pcm_resetup(codec, idx); | 367 | alc_dyn_adc_pcm_resetup(codec, idx); |
@@ -368,6 +390,7 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, | |||
368 | AC_VERB_SET_CONNECT_SEL, | 390 | AC_VERB_SET_CONNECT_SEL, |
369 | imux->items[idx].index); | 391 | imux->items[idx].index); |
370 | } | 392 | } |
393 | alc_inv_dmic_sync(codec, true); | ||
371 | return 1; | 394 | return 1; |
372 | } | 395 | } |
373 | 396 | ||
@@ -664,7 +687,7 @@ static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid) | |||
664 | } | 687 | } |
665 | 688 | ||
666 | /* unsolicited event for HP jack sensing */ | 689 | /* unsolicited event for HP jack sensing */ |
667 | static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) | 690 | static void alc_unsol_event(struct hda_codec *codec, unsigned int res) |
668 | { | 691 | { |
669 | int action; | 692 | int action; |
670 | 693 | ||
@@ -1000,11 +1023,9 @@ static void alc_init_automute(struct hda_codec *codec) | |||
1000 | spec->automute_lo = spec->automute_lo_possible; | 1023 | spec->automute_lo = spec->automute_lo_possible; |
1001 | spec->automute_speaker = spec->automute_speaker_possible; | 1024 | spec->automute_speaker = spec->automute_speaker_possible; |
1002 | 1025 | ||
1003 | if (spec->automute_speaker_possible || spec->automute_lo_possible) { | 1026 | if (spec->automute_speaker_possible || spec->automute_lo_possible) |
1004 | /* create a control for automute mode */ | 1027 | /* create a control for automute mode */ |
1005 | alc_add_automute_mode_enum(codec); | 1028 | alc_add_automute_mode_enum(codec); |
1006 | spec->unsol_event = alc_sku_unsol_event; | ||
1007 | } | ||
1008 | } | 1029 | } |
1009 | 1030 | ||
1010 | /* return the position of NID in the list, or -1 if not found */ | 1031 | /* return the position of NID in the list, or -1 if not found */ |
@@ -1167,7 +1188,6 @@ static void alc_init_auto_mic(struct hda_codec *codec) | |||
1167 | 1188 | ||
1168 | snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n", | 1189 | snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n", |
1169 | ext, fixed, dock); | 1190 | ext, fixed, dock); |
1170 | spec->unsol_event = alc_sku_unsol_event; | ||
1171 | } | 1191 | } |
1172 | 1192 | ||
1173 | /* check the availabilities of auto-mute and auto-mic switches */ | 1193 | /* check the availabilities of auto-mute and auto-mic switches */ |
@@ -1556,14 +1576,14 @@ typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol, | |||
1556 | 1576 | ||
1557 | static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, | 1577 | static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, |
1558 | struct snd_ctl_elem_value *ucontrol, | 1578 | struct snd_ctl_elem_value *ucontrol, |
1559 | getput_call_t func, bool check_adc_switch) | 1579 | getput_call_t func, bool is_put) |
1560 | { | 1580 | { |
1561 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1581 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1562 | struct alc_spec *spec = codec->spec; | 1582 | struct alc_spec *spec = codec->spec; |
1563 | int i, err = 0; | 1583 | int i, err = 0; |
1564 | 1584 | ||
1565 | mutex_lock(&codec->control_mutex); | 1585 | mutex_lock(&codec->control_mutex); |
1566 | if (check_adc_switch && spec->dyn_adc_switch) { | 1586 | if (is_put && spec->dyn_adc_switch) { |
1567 | for (i = 0; i < spec->num_adc_nids; i++) { | 1587 | for (i = 0; i < spec->num_adc_nids; i++) { |
1568 | kcontrol->private_value = | 1588 | kcontrol->private_value = |
1569 | HDA_COMPOSE_AMP_VAL(spec->adc_nids[i], | 1589 | HDA_COMPOSE_AMP_VAL(spec->adc_nids[i], |
@@ -1584,6 +1604,8 @@ static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, | |||
1584 | 3, 0, HDA_INPUT); | 1604 | 3, 0, HDA_INPUT); |
1585 | err = func(kcontrol, ucontrol); | 1605 | err = func(kcontrol, ucontrol); |
1586 | } | 1606 | } |
1607 | if (err >= 0 && is_put) | ||
1608 | alc_inv_dmic_sync(codec, false); | ||
1587 | error: | 1609 | error: |
1588 | mutex_unlock(&codec->control_mutex); | 1610 | mutex_unlock(&codec->control_mutex); |
1589 | return err; | 1611 | return err; |
@@ -1676,6 +1698,116 @@ DEFINE_CAPMIX_NOSRC(2); | |||
1676 | DEFINE_CAPMIX_NOSRC(3); | 1698 | DEFINE_CAPMIX_NOSRC(3); |
1677 | 1699 | ||
1678 | /* | 1700 | /* |
1701 | * Inverted digital-mic handling | ||
1702 | * | ||
1703 | * First off, it's a bit tricky. The "Inverted Internal Mic Capture Switch" | ||
1704 | * gives the additional mute only to the right channel of the digital mic | ||
1705 | * capture stream. This is a workaround for avoiding the almost silence | ||
1706 | * by summing the stereo stream from some (known to be ForteMedia) | ||
1707 | * digital mic unit. | ||
1708 | * | ||
1709 | * The logic is to call alc_inv_dmic_sync() after each action (possibly) | ||
1710 | * modifying ADC amp. When the mute flag is set, it mutes the R-channel | ||
1711 | * without caching so that the cache can still keep the original value. | ||
1712 | * The cached value is then restored when the flag is set off or any other | ||
1713 | * than d-mic is used as the current input source. | ||
1714 | */ | ||
1715 | static void alc_inv_dmic_sync(struct hda_codec *codec, bool force) | ||
1716 | { | ||
1717 | struct alc_spec *spec = codec->spec; | ||
1718 | int i; | ||
1719 | |||
1720 | if (!spec->inv_dmic_fixup) | ||
1721 | return; | ||
1722 | if (!spec->inv_dmic_muted && !force) | ||
1723 | return; | ||
1724 | for (i = 0; i < spec->num_adc_nids; i++) { | ||
1725 | int src = spec->dyn_adc_switch ? 0 : i; | ||
1726 | bool dmic_fixup = false; | ||
1727 | hda_nid_t nid; | ||
1728 | int parm, dir, v; | ||
1729 | |||
1730 | if (spec->inv_dmic_muted && | ||
1731 | spec->imux_pins[spec->cur_mux[src]] == spec->inv_dmic_pin) | ||
1732 | dmic_fixup = true; | ||
1733 | if (!dmic_fixup && !force) | ||
1734 | continue; | ||
1735 | if (spec->vol_in_capsrc) { | ||
1736 | nid = spec->capsrc_nids[i]; | ||
1737 | parm = AC_AMP_SET_RIGHT | AC_AMP_SET_OUTPUT; | ||
1738 | dir = HDA_OUTPUT; | ||
1739 | } else { | ||
1740 | nid = spec->adc_nids[i]; | ||
1741 | parm = AC_AMP_SET_RIGHT | AC_AMP_SET_INPUT; | ||
1742 | dir = HDA_INPUT; | ||
1743 | } | ||
1744 | /* we care only right channel */ | ||
1745 | v = snd_hda_codec_amp_read(codec, nid, 1, dir, 0); | ||
1746 | if (v & 0x80) /* if already muted, we don't need to touch */ | ||
1747 | continue; | ||
1748 | if (dmic_fixup) /* add mute for d-mic */ | ||
1749 | v |= 0x80; | ||
1750 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1751 | parm | v); | ||
1752 | } | ||
1753 | } | ||
1754 | |||
1755 | static int alc_inv_dmic_sw_get(struct snd_kcontrol *kcontrol, | ||
1756 | struct snd_ctl_elem_value *ucontrol) | ||
1757 | { | ||
1758 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1759 | struct alc_spec *spec = codec->spec; | ||
1760 | |||
1761 | ucontrol->value.integer.value[0] = !spec->inv_dmic_muted; | ||
1762 | return 0; | ||
1763 | } | ||
1764 | |||
1765 | static int alc_inv_dmic_sw_put(struct snd_kcontrol *kcontrol, | ||
1766 | struct snd_ctl_elem_value *ucontrol) | ||
1767 | { | ||
1768 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1769 | struct alc_spec *spec = codec->spec; | ||
1770 | unsigned int val = !ucontrol->value.integer.value[0]; | ||
1771 | |||
1772 | if (val == spec->inv_dmic_muted) | ||
1773 | return 0; | ||
1774 | spec->inv_dmic_muted = val; | ||
1775 | alc_inv_dmic_sync(codec, true); | ||
1776 | return 0; | ||
1777 | } | ||
1778 | |||
1779 | static const struct snd_kcontrol_new alc_inv_dmic_sw = { | ||
1780 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1781 | .info = snd_ctl_boolean_mono_info, | ||
1782 | .get = alc_inv_dmic_sw_get, | ||
1783 | .put = alc_inv_dmic_sw_put, | ||
1784 | }; | ||
1785 | |||
1786 | static int alc_add_inv_dmic_mixer(struct hda_codec *codec, hda_nid_t nid) | ||
1787 | { | ||
1788 | struct alc_spec *spec = codec->spec; | ||
1789 | struct snd_kcontrol_new *knew = alc_kcontrol_new(spec); | ||
1790 | if (!knew) | ||
1791 | return -ENOMEM; | ||
1792 | *knew = alc_inv_dmic_sw; | ||
1793 | knew->name = kstrdup("Inverted Internal Mic Capture Switch", GFP_KERNEL); | ||
1794 | if (!knew->name) | ||
1795 | return -ENOMEM; | ||
1796 | spec->inv_dmic_fixup = 1; | ||
1797 | spec->inv_dmic_muted = 0; | ||
1798 | spec->inv_dmic_pin = nid; | ||
1799 | return 0; | ||
1800 | } | ||
1801 | |||
1802 | /* typically the digital mic is put at node 0x12 */ | ||
1803 | static void alc_fixup_inv_dmic_0x12(struct hda_codec *codec, | ||
1804 | const struct alc_fixup *fix, int action) | ||
1805 | { | ||
1806 | if (action == ALC_FIXUP_ACT_PROBE) | ||
1807 | alc_add_inv_dmic_mixer(codec, 0x12); | ||
1808 | } | ||
1809 | |||
1810 | /* | ||
1679 | * virtual master controls | 1811 | * virtual master controls |
1680 | */ | 1812 | */ |
1681 | 1813 | ||
@@ -1865,13 +1997,31 @@ static int __alc_build_controls(struct hda_codec *codec) | |||
1865 | return 0; | 1997 | return 0; |
1866 | } | 1998 | } |
1867 | 1999 | ||
1868 | static int alc_build_controls(struct hda_codec *codec) | 2000 | static int alc_build_jacks(struct hda_codec *codec) |
1869 | { | 2001 | { |
1870 | struct alc_spec *spec = codec->spec; | 2002 | struct alc_spec *spec = codec->spec; |
2003 | |||
2004 | if (spec->shared_mic_hp) { | ||
2005 | int err; | ||
2006 | int nid = spec->autocfg.inputs[1].pin; | ||
2007 | err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0); | ||
2008 | if (err < 0) | ||
2009 | return err; | ||
2010 | err = snd_hda_jack_detect_enable(codec, nid, 0); | ||
2011 | if (err < 0) | ||
2012 | return err; | ||
2013 | } | ||
2014 | |||
2015 | return snd_hda_jack_add_kctls(codec, &spec->autocfg); | ||
2016 | } | ||
2017 | |||
2018 | static int alc_build_controls(struct hda_codec *codec) | ||
2019 | { | ||
1871 | int err = __alc_build_controls(codec); | 2020 | int err = __alc_build_controls(codec); |
1872 | if (err < 0) | 2021 | if (err < 0) |
1873 | return err; | 2022 | return err; |
1874 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); | 2023 | |
2024 | err = alc_build_jacks(codec); | ||
1875 | if (err < 0) | 2025 | if (err < 0) |
1876 | return err; | 2026 | return err; |
1877 | alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD); | 2027 | alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD); |
@@ -1908,14 +2058,6 @@ static int alc_init(struct hda_codec *codec) | |||
1908 | return 0; | 2058 | return 0; |
1909 | } | 2059 | } |
1910 | 2060 | ||
1911 | static void alc_unsol_event(struct hda_codec *codec, unsigned int res) | ||
1912 | { | ||
1913 | struct alc_spec *spec = codec->spec; | ||
1914 | |||
1915 | if (spec->unsol_event) | ||
1916 | spec->unsol_event(codec, res); | ||
1917 | } | ||
1918 | |||
1919 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2061 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
1920 | static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid) | 2062 | static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid) |
1921 | { | 2063 | { |
@@ -2300,7 +2442,7 @@ static void alc_power_eapd(struct hda_codec *codec) | |||
2300 | alc_auto_setup_eapd(codec, false); | 2442 | alc_auto_setup_eapd(codec, false); |
2301 | } | 2443 | } |
2302 | 2444 | ||
2303 | static int alc_suspend(struct hda_codec *codec, pm_message_t state) | 2445 | static int alc_suspend(struct hda_codec *codec) |
2304 | { | 2446 | { |
2305 | struct alc_spec *spec = codec->spec; | 2447 | struct alc_spec *spec = codec->spec; |
2306 | alc_shutup(codec); | 2448 | alc_shutup(codec); |
@@ -2317,6 +2459,7 @@ static int alc_resume(struct hda_codec *codec) | |||
2317 | codec->patch_ops.init(codec); | 2459 | codec->patch_ops.init(codec); |
2318 | snd_hda_codec_resume_amp(codec); | 2460 | snd_hda_codec_resume_amp(codec); |
2319 | snd_hda_codec_resume_cache(codec); | 2461 | snd_hda_codec_resume_cache(codec); |
2462 | alc_inv_dmic_sync(codec, true); | ||
2320 | hda_call_check_power_status(codec, 0x01); | 2463 | hda_call_check_power_status(codec, 0x01); |
2321 | return 0; | 2464 | return 0; |
2322 | } | 2465 | } |
@@ -4116,14 +4259,12 @@ static void set_capture_mixer(struct hda_codec *codec) | |||
4116 | */ | 4259 | */ |
4117 | static void alc_auto_init_std(struct hda_codec *codec) | 4260 | static void alc_auto_init_std(struct hda_codec *codec) |
4118 | { | 4261 | { |
4119 | struct alc_spec *spec = codec->spec; | ||
4120 | alc_auto_init_multi_out(codec); | 4262 | alc_auto_init_multi_out(codec); |
4121 | alc_auto_init_extra_out(codec); | 4263 | alc_auto_init_extra_out(codec); |
4122 | alc_auto_init_analog_input(codec); | 4264 | alc_auto_init_analog_input(codec); |
4123 | alc_auto_init_input_src(codec); | 4265 | alc_auto_init_input_src(codec); |
4124 | alc_auto_init_digital(codec); | 4266 | alc_auto_init_digital(codec); |
4125 | if (spec->unsol_event) | 4267 | alc_inithook(codec); |
4126 | alc_inithook(codec); | ||
4127 | } | 4268 | } |
4128 | 4269 | ||
4129 | /* | 4270 | /* |
@@ -4724,7 +4865,6 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, | |||
4724 | spec->automute_speaker = 1; | 4865 | spec->automute_speaker = 1; |
4725 | spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ | 4866 | spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ |
4726 | snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT); | 4867 | snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT); |
4727 | spec->unsol_event = alc_sku_unsol_event; | ||
4728 | snd_hda_gen_add_verbs(&spec->gen, alc_gpio1_init_verbs); | 4868 | snd_hda_gen_add_verbs(&spec->gen, alc_gpio1_init_verbs); |
4729 | } | 4869 | } |
4730 | } | 4870 | } |
@@ -4909,6 +5049,7 @@ enum { | |||
4909 | ALC889_FIXUP_DAC_ROUTE, | 5049 | ALC889_FIXUP_DAC_ROUTE, |
4910 | ALC889_FIXUP_MBP_VREF, | 5050 | ALC889_FIXUP_MBP_VREF, |
4911 | ALC889_FIXUP_IMAC91_VREF, | 5051 | ALC889_FIXUP_IMAC91_VREF, |
5052 | ALC882_FIXUP_INV_DMIC, | ||
4912 | }; | 5053 | }; |
4913 | 5054 | ||
4914 | static void alc889_fixup_coef(struct hda_codec *codec, | 5055 | static void alc889_fixup_coef(struct hda_codec *codec, |
@@ -5212,6 +5353,10 @@ static const struct alc_fixup alc882_fixups[] = { | |||
5212 | .chained = true, | 5353 | .chained = true, |
5213 | .chain_id = ALC882_FIXUP_GPIO1, | 5354 | .chain_id = ALC882_FIXUP_GPIO1, |
5214 | }, | 5355 | }, |
5356 | [ALC882_FIXUP_INV_DMIC] = { | ||
5357 | .type = ALC_FIXUP_FUNC, | ||
5358 | .v.func = alc_fixup_inv_dmic_0x12, | ||
5359 | }, | ||
5215 | }; | 5360 | }; |
5216 | 5361 | ||
5217 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { | 5362 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { |
@@ -5286,6 +5431,7 @@ static const struct alc_model_fixup alc882_fixup_models[] = { | |||
5286 | {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"}, | 5431 | {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"}, |
5287 | {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"}, | 5432 | {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"}, |
5288 | {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"}, | 5433 | {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"}, |
5434 | {.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"}, | ||
5289 | {} | 5435 | {} |
5290 | }; | 5436 | }; |
5291 | 5437 | ||
@@ -5373,6 +5519,7 @@ enum { | |||
5373 | ALC262_FIXUP_LENOVO_3000, | 5519 | ALC262_FIXUP_LENOVO_3000, |
5374 | ALC262_FIXUP_BENQ, | 5520 | ALC262_FIXUP_BENQ, |
5375 | ALC262_FIXUP_BENQ_T31, | 5521 | ALC262_FIXUP_BENQ_T31, |
5522 | ALC262_FIXUP_INV_DMIC, | ||
5376 | }; | 5523 | }; |
5377 | 5524 | ||
5378 | static const struct alc_fixup alc262_fixups[] = { | 5525 | static const struct alc_fixup alc262_fixups[] = { |
@@ -5424,6 +5571,10 @@ static const struct alc_fixup alc262_fixups[] = { | |||
5424 | {} | 5571 | {} |
5425 | } | 5572 | } |
5426 | }, | 5573 | }, |
5574 | [ALC262_FIXUP_INV_DMIC] = { | ||
5575 | .type = ALC_FIXUP_FUNC, | ||
5576 | .v.func = alc_fixup_inv_dmic_0x12, | ||
5577 | }, | ||
5427 | }; | 5578 | }; |
5428 | 5579 | ||
5429 | static const struct snd_pci_quirk alc262_fixup_tbl[] = { | 5580 | static const struct snd_pci_quirk alc262_fixup_tbl[] = { |
@@ -5438,6 +5589,10 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = { | |||
5438 | {} | 5589 | {} |
5439 | }; | 5590 | }; |
5440 | 5591 | ||
5592 | static const struct alc_model_fixup alc262_fixup_models[] = { | ||
5593 | {.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"}, | ||
5594 | {} | ||
5595 | }; | ||
5441 | 5596 | ||
5442 | /* | 5597 | /* |
5443 | */ | 5598 | */ |
@@ -5466,7 +5621,8 @@ static int patch_alc262(struct hda_codec *codec) | |||
5466 | #endif | 5621 | #endif |
5467 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); | 5622 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); |
5468 | 5623 | ||
5469 | alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups); | 5624 | alc_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl, |
5625 | alc262_fixups); | ||
5470 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | 5626 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); |
5471 | 5627 | ||
5472 | alc_auto_parse_customize_define(codec); | 5628 | alc_auto_parse_customize_define(codec); |
@@ -5522,6 +5678,22 @@ static const struct hda_verb alc268_beep_init_verbs[] = { | |||
5522 | { } | 5678 | { } |
5523 | }; | 5679 | }; |
5524 | 5680 | ||
5681 | enum { | ||
5682 | ALC268_FIXUP_INV_DMIC, | ||
5683 | }; | ||
5684 | |||
5685 | static const struct alc_fixup alc268_fixups[] = { | ||
5686 | [ALC268_FIXUP_INV_DMIC] = { | ||
5687 | .type = ALC_FIXUP_FUNC, | ||
5688 | .v.func = alc_fixup_inv_dmic_0x12, | ||
5689 | }, | ||
5690 | }; | ||
5691 | |||
5692 | static const struct alc_model_fixup alc268_fixup_models[] = { | ||
5693 | {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"}, | ||
5694 | {} | ||
5695 | }; | ||
5696 | |||
5525 | /* | 5697 | /* |
5526 | * BIOS auto configuration | 5698 | * BIOS auto configuration |
5527 | */ | 5699 | */ |
@@ -5553,6 +5725,9 @@ static int patch_alc268(struct hda_codec *codec) | |||
5553 | 5725 | ||
5554 | spec = codec->spec; | 5726 | spec = codec->spec; |
5555 | 5727 | ||
5728 | alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups); | ||
5729 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | ||
5730 | |||
5556 | /* automatic parse from the BIOS config */ | 5731 | /* automatic parse from the BIOS config */ |
5557 | err = alc268_parse_auto_config(codec); | 5732 | err = alc268_parse_auto_config(codec); |
5558 | if (err < 0) | 5733 | if (err < 0) |
@@ -5582,6 +5757,8 @@ static int patch_alc268(struct hda_codec *codec) | |||
5582 | codec->patch_ops = alc_patch_ops; | 5757 | codec->patch_ops = alc_patch_ops; |
5583 | spec->shutup = alc_eapd_shutup; | 5758 | spec->shutup = alc_eapd_shutup; |
5584 | 5759 | ||
5760 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
5761 | |||
5585 | return 0; | 5762 | return 0; |
5586 | 5763 | ||
5587 | error: | 5764 | error: |
@@ -5704,6 +5881,15 @@ static int alc269_resume(struct hda_codec *codec) | |||
5704 | } | 5881 | } |
5705 | #endif /* CONFIG_PM */ | 5882 | #endif /* CONFIG_PM */ |
5706 | 5883 | ||
5884 | static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec, | ||
5885 | const struct alc_fixup *fix, int action) | ||
5886 | { | ||
5887 | struct alc_spec *spec = codec->spec; | ||
5888 | |||
5889 | if (action == ALC_FIXUP_ACT_PRE_PROBE) | ||
5890 | spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; | ||
5891 | } | ||
5892 | |||
5707 | static void alc269_fixup_hweq(struct hda_codec *codec, | 5893 | static void alc269_fixup_hweq(struct hda_codec *codec, |
5708 | const struct alc_fixup *fix, int action) | 5894 | const struct alc_fixup *fix, int action) |
5709 | { | 5895 | { |
@@ -5810,6 +5996,7 @@ static void alc269_fixup_mic2_mute(struct hda_codec *codec, | |||
5810 | } | 5996 | } |
5811 | } | 5997 | } |
5812 | 5998 | ||
5999 | |||
5813 | enum { | 6000 | enum { |
5814 | ALC269_FIXUP_SONY_VAIO, | 6001 | ALC269_FIXUP_SONY_VAIO, |
5815 | ALC275_FIXUP_SONY_VAIO_GPIO2, | 6002 | ALC275_FIXUP_SONY_VAIO_GPIO2, |
@@ -5828,6 +6015,9 @@ enum { | |||
5828 | ALC269VB_FIXUP_AMIC, | 6015 | ALC269VB_FIXUP_AMIC, |
5829 | ALC269VB_FIXUP_DMIC, | 6016 | ALC269VB_FIXUP_DMIC, |
5830 | ALC269_FIXUP_MIC2_MUTE_LED, | 6017 | ALC269_FIXUP_MIC2_MUTE_LED, |
6018 | ALC269_FIXUP_INV_DMIC, | ||
6019 | ALC269_FIXUP_LENOVO_DOCK, | ||
6020 | ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT, | ||
5831 | }; | 6021 | }; |
5832 | 6022 | ||
5833 | static const struct alc_fixup alc269_fixups[] = { | 6023 | static const struct alc_fixup alc269_fixups[] = { |
@@ -5952,12 +6142,33 @@ static const struct alc_fixup alc269_fixups[] = { | |||
5952 | .type = ALC_FIXUP_FUNC, | 6142 | .type = ALC_FIXUP_FUNC, |
5953 | .v.func = alc269_fixup_mic2_mute, | 6143 | .v.func = alc269_fixup_mic2_mute, |
5954 | }, | 6144 | }, |
6145 | [ALC269_FIXUP_INV_DMIC] = { | ||
6146 | .type = ALC_FIXUP_FUNC, | ||
6147 | .v.func = alc_fixup_inv_dmic_0x12, | ||
6148 | }, | ||
6149 | [ALC269_FIXUP_LENOVO_DOCK] = { | ||
6150 | .type = ALC_FIXUP_PINS, | ||
6151 | .v.pins = (const struct alc_pincfg[]) { | ||
6152 | { 0x19, 0x23a11040 }, /* dock mic */ | ||
6153 | { 0x1b, 0x2121103f }, /* dock headphone */ | ||
6154 | { } | ||
6155 | }, | ||
6156 | .chained = true, | ||
6157 | .chain_id = ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT | ||
6158 | }, | ||
6159 | [ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT] = { | ||
6160 | .type = ALC_FIXUP_FUNC, | ||
6161 | .v.func = alc269_fixup_pincfg_no_hp_to_lineout, | ||
6162 | }, | ||
5955 | }; | 6163 | }; |
5956 | 6164 | ||
5957 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 6165 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
6166 | SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), | ||
6167 | SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), | ||
5958 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), | 6168 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), |
5959 | SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), | 6169 | SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), |
5960 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), | 6170 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), |
6171 | SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), | ||
5961 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), | 6172 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), |
5962 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), | 6173 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), |
5963 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), | 6174 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), |
@@ -5975,6 +6186,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5975 | SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), | 6186 | SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), |
5976 | SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), | 6187 | SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), |
5977 | SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), | 6188 | SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), |
6189 | SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), | ||
5978 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), | 6190 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), |
5979 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), | 6191 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), |
5980 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), | 6192 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), |
@@ -6033,6 +6245,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
6033 | static const struct alc_model_fixup alc269_fixup_models[] = { | 6245 | static const struct alc_model_fixup alc269_fixup_models[] = { |
6034 | {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, | 6246 | {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, |
6035 | {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, | 6247 | {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, |
6248 | {.id = ALC269_FIXUP_STEREO_DMIC, .name = "alc269-dmic"}, | ||
6249 | {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"}, | ||
6250 | {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"}, | ||
6251 | {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"}, | ||
6036 | {} | 6252 | {} |
6037 | }; | 6253 | }; |
6038 | 6254 | ||
@@ -6329,12 +6545,6 @@ static const struct snd_pci_quirk alc861vd_fixup_tbl[] = { | |||
6329 | {} | 6545 | {} |
6330 | }; | 6546 | }; |
6331 | 6547 | ||
6332 | static const struct hda_verb alc660vd_eapd_verbs[] = { | ||
6333 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
6334 | {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
6335 | { } | ||
6336 | }; | ||
6337 | |||
6338 | /* | 6548 | /* |
6339 | */ | 6549 | */ |
6340 | static int patch_alc861vd(struct hda_codec *codec) | 6550 | static int patch_alc861vd(struct hda_codec *codec) |
@@ -6356,11 +6566,6 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
6356 | if (err < 0) | 6566 | if (err < 0) |
6357 | goto error; | 6567 | goto error; |
6358 | 6568 | ||
6359 | if (codec->vendor_id == 0x10ec0660) { | ||
6360 | /* always turn on EAPD */ | ||
6361 | snd_hda_gen_add_verbs(&spec->gen, alc660vd_eapd_verbs); | ||
6362 | } | ||
6363 | |||
6364 | if (!spec->no_analog) { | 6569 | if (!spec->no_analog) { |
6365 | err = snd_hda_attach_beep_device(codec, 0x23); | 6570 | err = snd_hda_attach_beep_device(codec, 0x23); |
6366 | if (err < 0) | 6571 | if (err < 0) |
@@ -6443,6 +6648,7 @@ enum { | |||
6443 | ALC662_FIXUP_ASUS_MODE8, | 6648 | ALC662_FIXUP_ASUS_MODE8, |
6444 | ALC662_FIXUP_NO_JACK_DETECT, | 6649 | ALC662_FIXUP_NO_JACK_DETECT, |
6445 | ALC662_FIXUP_ZOTAC_Z68, | 6650 | ALC662_FIXUP_ZOTAC_Z68, |
6651 | ALC662_FIXUP_INV_DMIC, | ||
6446 | }; | 6652 | }; |
6447 | 6653 | ||
6448 | static const struct alc_fixup alc662_fixups[] = { | 6654 | static const struct alc_fixup alc662_fixups[] = { |
@@ -6599,12 +6805,17 @@ static const struct alc_fixup alc662_fixups[] = { | |||
6599 | { } | 6805 | { } |
6600 | } | 6806 | } |
6601 | }, | 6807 | }, |
6808 | [ALC662_FIXUP_INV_DMIC] = { | ||
6809 | .type = ALC_FIXUP_FUNC, | ||
6810 | .v.func = alc_fixup_inv_dmic_0x12, | ||
6811 | }, | ||
6602 | }; | 6812 | }; |
6603 | 6813 | ||
6604 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { | 6814 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { |
6605 | SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2), | 6815 | SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2), |
6606 | SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), | 6816 | SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), |
6607 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), | 6817 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), |
6818 | SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), | ||
6608 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), | 6819 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), |
6609 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), | 6820 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), |
6610 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), | 6821 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), |
@@ -6685,6 +6896,7 @@ static const struct alc_model_fixup alc662_fixup_models[] = { | |||
6685 | {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"}, | 6896 | {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"}, |
6686 | {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"}, | 6897 | {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"}, |
6687 | {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"}, | 6898 | {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"}, |
6899 | {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"}, | ||
6688 | {} | 6900 | {} |
6689 | }; | 6901 | }; |
6690 | 6902 | ||
@@ -6831,6 +7043,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
6831 | { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 }, | 7043 | { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 }, |
6832 | { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 }, | 7044 | { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 }, |
6833 | { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, | 7045 | { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, |
7046 | { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, | ||
6834 | { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", | 7047 | { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", |
6835 | .patch = patch_alc861 }, | 7048 | .patch = patch_alc861 }, |
6836 | { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, | 7049 | { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 07675282015a..a1596a3b171c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -4997,7 +4997,7 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
4997 | return 0; | 4997 | return 0; |
4998 | } | 4998 | } |
4999 | 4999 | ||
5000 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | 5000 | static int stac92xx_suspend(struct hda_codec *codec) |
5001 | { | 5001 | { |
5002 | stac92xx_shutup(codec); | 5002 | stac92xx_shutup(codec); |
5003 | return 0; | 5003 | return 0; |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 82b368068e08..90645560ed39 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -1748,7 +1748,7 @@ static void via_unsol_event(struct hda_codec *codec, | |||
1748 | } | 1748 | } |
1749 | 1749 | ||
1750 | #ifdef CONFIG_PM | 1750 | #ifdef CONFIG_PM |
1751 | static int via_suspend(struct hda_codec *codec, pm_message_t state) | 1751 | static int via_suspend(struct hda_codec *codec) |
1752 | { | 1752 | { |
1753 | struct via_spec *spec = codec->spec; | 1753 | struct via_spec *spec = codec->spec; |
1754 | vt1708_stop_hp_work(spec); | 1754 | vt1708_stop_hp_work(spec); |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index a01a00d1cf4d..bed9f34f4efe 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -2793,9 +2793,10 @@ static void __devexit snd_vt1724_remove(struct pci_dev *pci) | |||
2793 | } | 2793 | } |
2794 | 2794 | ||
2795 | #ifdef CONFIG_PM | 2795 | #ifdef CONFIG_PM |
2796 | static int snd_vt1724_suspend(struct pci_dev *pci, pm_message_t state) | 2796 | static int snd_vt1724_suspend(struct device *dev) |
2797 | { | 2797 | { |
2798 | struct snd_card *card = pci_get_drvdata(pci); | 2798 | struct pci_dev *pci = to_pci_dev(dev); |
2799 | struct snd_card *card = dev_get_drvdata(dev); | ||
2799 | struct snd_ice1712 *ice = card->private_data; | 2800 | struct snd_ice1712 *ice = card->private_data; |
2800 | 2801 | ||
2801 | if (!ice->pm_suspend_enabled) | 2802 | if (!ice->pm_suspend_enabled) |
@@ -2820,13 +2821,14 @@ static int snd_vt1724_suspend(struct pci_dev *pci, pm_message_t state) | |||
2820 | 2821 | ||
2821 | pci_disable_device(pci); | 2822 | pci_disable_device(pci); |
2822 | pci_save_state(pci); | 2823 | pci_save_state(pci); |
2823 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 2824 | pci_set_power_state(pci, PCI_D3hot); |
2824 | return 0; | 2825 | return 0; |
2825 | } | 2826 | } |
2826 | 2827 | ||
2827 | static int snd_vt1724_resume(struct pci_dev *pci) | 2828 | static int snd_vt1724_resume(struct device *dev) |
2828 | { | 2829 | { |
2829 | struct snd_card *card = pci_get_drvdata(pci); | 2830 | struct pci_dev *pci = to_pci_dev(dev); |
2831 | struct snd_card *card = dev_get_drvdata(dev); | ||
2830 | struct snd_ice1712 *ice = card->private_data; | 2832 | struct snd_ice1712 *ice = card->private_data; |
2831 | 2833 | ||
2832 | if (!ice->pm_suspend_enabled) | 2834 | if (!ice->pm_suspend_enabled) |
@@ -2871,17 +2873,21 @@ static int snd_vt1724_resume(struct pci_dev *pci) | |||
2871 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2873 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
2872 | return 0; | 2874 | return 0; |
2873 | } | 2875 | } |
2874 | #endif | 2876 | |
2877 | static SIMPLE_DEV_PM_OPS(snd_vt1724_pm, snd_vt1724_suspend, snd_vt1724_resume); | ||
2878 | #define SND_VT1724_PM_OPS &snd_vt1724_pm | ||
2879 | #else | ||
2880 | #define SND_VT1724_PM_OPS NULL | ||
2881 | #endif /* CONFIG_PM */ | ||
2875 | 2882 | ||
2876 | static struct pci_driver vt1724_driver = { | 2883 | static struct pci_driver vt1724_driver = { |
2877 | .name = KBUILD_MODNAME, | 2884 | .name = KBUILD_MODNAME, |
2878 | .id_table = snd_vt1724_ids, | 2885 | .id_table = snd_vt1724_ids, |
2879 | .probe = snd_vt1724_probe, | 2886 | .probe = snd_vt1724_probe, |
2880 | .remove = __devexit_p(snd_vt1724_remove), | 2887 | .remove = __devexit_p(snd_vt1724_remove), |
2881 | #ifdef CONFIG_PM | 2888 | .driver = { |
2882 | .suspend = snd_vt1724_suspend, | 2889 | .pm = SND_VT1724_PM_OPS, |
2883 | .resume = snd_vt1724_resume, | 2890 | }, |
2884 | #endif | ||
2885 | }; | 2891 | }; |
2886 | 2892 | ||
2887 | module_pci_driver(vt1724_driver); | 2893 | module_pci_driver(vt1724_driver); |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index f4e2dd4da8cf..cd553f592e2d 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -2624,9 +2624,10 @@ static int snd_intel8x0_free(struct intel8x0 *chip) | |||
2624 | /* | 2624 | /* |
2625 | * power management | 2625 | * power management |
2626 | */ | 2626 | */ |
2627 | static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) | 2627 | static int intel8x0_suspend(struct device *dev) |
2628 | { | 2628 | { |
2629 | struct snd_card *card = pci_get_drvdata(pci); | 2629 | struct pci_dev *pci = to_pci_dev(dev); |
2630 | struct snd_card *card = dev_get_drvdata(dev); | ||
2630 | struct intel8x0 *chip = card->private_data; | 2631 | struct intel8x0 *chip = card->private_data; |
2631 | int i; | 2632 | int i; |
2632 | 2633 | ||
@@ -2658,13 +2659,14 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) | |||
2658 | /* The call below may disable built-in speaker on some laptops | 2659 | /* The call below may disable built-in speaker on some laptops |
2659 | * after S2RAM. So, don't touch it. | 2660 | * after S2RAM. So, don't touch it. |
2660 | */ | 2661 | */ |
2661 | /* pci_set_power_state(pci, pci_choose_state(pci, state)); */ | 2662 | /* pci_set_power_state(pci, PCI_D3hot); */ |
2662 | return 0; | 2663 | return 0; |
2663 | } | 2664 | } |
2664 | 2665 | ||
2665 | static int intel8x0_resume(struct pci_dev *pci) | 2666 | static int intel8x0_resume(struct device *dev) |
2666 | { | 2667 | { |
2667 | struct snd_card *card = pci_get_drvdata(pci); | 2668 | struct pci_dev *pci = to_pci_dev(dev); |
2669 | struct snd_card *card = dev_get_drvdata(dev); | ||
2668 | struct intel8x0 *chip = card->private_data; | 2670 | struct intel8x0 *chip = card->private_data; |
2669 | int i; | 2671 | int i; |
2670 | 2672 | ||
@@ -2734,6 +2736,11 @@ static int intel8x0_resume(struct pci_dev *pci) | |||
2734 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2736 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
2735 | return 0; | 2737 | return 0; |
2736 | } | 2738 | } |
2739 | |||
2740 | static SIMPLE_DEV_PM_OPS(intel8x0_pm, intel8x0_suspend, intel8x0_resume); | ||
2741 | #define INTEL8X0_PM_OPS &intel8x0_pm | ||
2742 | #else | ||
2743 | #define INTEL8X0_PM_OPS NULL | ||
2737 | #endif /* CONFIG_PM */ | 2744 | #endif /* CONFIG_PM */ |
2738 | 2745 | ||
2739 | #define INTEL8X0_TESTBUF_SIZE 32768 /* enough large for one shot */ | 2746 | #define INTEL8X0_TESTBUF_SIZE 32768 /* enough large for one shot */ |
@@ -3343,10 +3350,9 @@ static struct pci_driver intel8x0_driver = { | |||
3343 | .id_table = snd_intel8x0_ids, | 3350 | .id_table = snd_intel8x0_ids, |
3344 | .probe = snd_intel8x0_probe, | 3351 | .probe = snd_intel8x0_probe, |
3345 | .remove = __devexit_p(snd_intel8x0_remove), | 3352 | .remove = __devexit_p(snd_intel8x0_remove), |
3346 | #ifdef CONFIG_PM | 3353 | .driver = { |
3347 | .suspend = intel8x0_suspend, | 3354 | .pm = INTEL8X0_PM_OPS, |
3348 | .resume = intel8x0_resume, | 3355 | }, |
3349 | #endif | ||
3350 | }; | 3356 | }; |
3351 | 3357 | ||
3352 | module_pci_driver(intel8x0_driver); | 3358 | module_pci_driver(intel8x0_driver); |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index fc27a6a69e77..da44bb3f8e7a 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -1012,9 +1012,10 @@ static int snd_intel8x0m_free(struct intel8x0m *chip) | |||
1012 | /* | 1012 | /* |
1013 | * power management | 1013 | * power management |
1014 | */ | 1014 | */ |
1015 | static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state) | 1015 | static int intel8x0m_suspend(struct device *dev) |
1016 | { | 1016 | { |
1017 | struct snd_card *card = pci_get_drvdata(pci); | 1017 | struct pci_dev *pci = to_pci_dev(dev); |
1018 | struct snd_card *card = dev_get_drvdata(dev); | ||
1018 | struct intel8x0m *chip = card->private_data; | 1019 | struct intel8x0m *chip = card->private_data; |
1019 | int i; | 1020 | int i; |
1020 | 1021 | ||
@@ -1028,13 +1029,14 @@ static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state) | |||
1028 | } | 1029 | } |
1029 | pci_disable_device(pci); | 1030 | pci_disable_device(pci); |
1030 | pci_save_state(pci); | 1031 | pci_save_state(pci); |
1031 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 1032 | pci_set_power_state(pci, PCI_D3hot); |
1032 | return 0; | 1033 | return 0; |
1033 | } | 1034 | } |
1034 | 1035 | ||
1035 | static int intel8x0m_resume(struct pci_dev *pci) | 1036 | static int intel8x0m_resume(struct device *dev) |
1036 | { | 1037 | { |
1037 | struct snd_card *card = pci_get_drvdata(pci); | 1038 | struct pci_dev *pci = to_pci_dev(dev); |
1039 | struct snd_card *card = dev_get_drvdata(dev); | ||
1038 | struct intel8x0m *chip = card->private_data; | 1040 | struct intel8x0m *chip = card->private_data; |
1039 | 1041 | ||
1040 | pci_set_power_state(pci, PCI_D0); | 1042 | pci_set_power_state(pci, PCI_D0); |
@@ -1060,6 +1062,11 @@ static int intel8x0m_resume(struct pci_dev *pci) | |||
1060 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1062 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1061 | return 0; | 1063 | return 0; |
1062 | } | 1064 | } |
1065 | |||
1066 | static SIMPLE_DEV_PM_OPS(intel8x0m_pm, intel8x0m_suspend, intel8x0m_resume); | ||
1067 | #define INTEL8X0M_PM_OPS &intel8x0m_pm | ||
1068 | #else | ||
1069 | #define INTEL8X0M_PM_OPS NULL | ||
1063 | #endif /* CONFIG_PM */ | 1070 | #endif /* CONFIG_PM */ |
1064 | 1071 | ||
1065 | #ifdef CONFIG_PROC_FS | 1072 | #ifdef CONFIG_PROC_FS |
@@ -1329,10 +1336,9 @@ static struct pci_driver intel8x0m_driver = { | |||
1329 | .id_table = snd_intel8x0m_ids, | 1336 | .id_table = snd_intel8x0m_ids, |
1330 | .probe = snd_intel8x0m_probe, | 1337 | .probe = snd_intel8x0m_probe, |
1331 | .remove = __devexit_p(snd_intel8x0m_remove), | 1338 | .remove = __devexit_p(snd_intel8x0m_remove), |
1332 | #ifdef CONFIG_PM | 1339 | .driver = { |
1333 | .suspend = intel8x0m_suspend, | 1340 | .pm = INTEL8X0M_PM_OPS, |
1334 | .resume = intel8x0m_resume, | 1341 | }, |
1335 | #endif | ||
1336 | }; | 1342 | }; |
1337 | 1343 | ||
1338 | module_pci_driver(intel8x0m_driver); | 1344 | module_pci_driver(intel8x0m_driver); |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index deef21399586..c85d1ffcc955 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -361,74 +361,6 @@ MODULE_PARM_DESC(amp_gpio, "GPIO pin number for external amp. (default = -1)"); | |||
361 | #define DSP2HOST_REQ_I2SRATE 0x02 | 361 | #define DSP2HOST_REQ_I2SRATE 0x02 |
362 | #define DSP2HOST_REQ_TIMER 0x04 | 362 | #define DSP2HOST_REQ_TIMER 0x04 |
363 | 363 | ||
364 | /* AC97 registers */ | ||
365 | /* XXX fix this crap up */ | ||
366 | /*#define AC97_RESET 0x00*/ | ||
367 | |||
368 | #define AC97_VOL_MUTE_B 0x8000 | ||
369 | #define AC97_VOL_M 0x1F | ||
370 | #define AC97_LEFT_VOL_S 8 | ||
371 | |||
372 | #define AC97_MASTER_VOL 0x02 | ||
373 | #define AC97_LINE_LEVEL_VOL 0x04 | ||
374 | #define AC97_MASTER_MONO_VOL 0x06 | ||
375 | #define AC97_PC_BEEP_VOL 0x0A | ||
376 | #define AC97_PC_BEEP_VOL_M 0x0F | ||
377 | #define AC97_SROUND_MASTER_VOL 0x38 | ||
378 | #define AC97_PC_BEEP_VOL_S 1 | ||
379 | |||
380 | /*#define AC97_PHONE_VOL 0x0C | ||
381 | #define AC97_MIC_VOL 0x0E*/ | ||
382 | #define AC97_MIC_20DB_ENABLE 0x40 | ||
383 | |||
384 | /*#define AC97_LINEIN_VOL 0x10 | ||
385 | #define AC97_CD_VOL 0x12 | ||
386 | #define AC97_VIDEO_VOL 0x14 | ||
387 | #define AC97_AUX_VOL 0x16*/ | ||
388 | #define AC97_PCM_OUT_VOL 0x18 | ||
389 | /*#define AC97_RECORD_SELECT 0x1A*/ | ||
390 | #define AC97_RECORD_MIC 0x00 | ||
391 | #define AC97_RECORD_CD 0x01 | ||
392 | #define AC97_RECORD_VIDEO 0x02 | ||
393 | #define AC97_RECORD_AUX 0x03 | ||
394 | #define AC97_RECORD_MONO_MUX 0x02 | ||
395 | #define AC97_RECORD_DIGITAL 0x03 | ||
396 | #define AC97_RECORD_LINE 0x04 | ||
397 | #define AC97_RECORD_STEREO 0x05 | ||
398 | #define AC97_RECORD_MONO 0x06 | ||
399 | #define AC97_RECORD_PHONE 0x07 | ||
400 | |||
401 | /*#define AC97_RECORD_GAIN 0x1C*/ | ||
402 | #define AC97_RECORD_VOL_M 0x0F | ||
403 | |||
404 | /*#define AC97_GENERAL_PURPOSE 0x20*/ | ||
405 | #define AC97_POWER_DOWN_CTRL 0x26 | ||
406 | #define AC97_ADC_READY 0x0001 | ||
407 | #define AC97_DAC_READY 0x0002 | ||
408 | #define AC97_ANALOG_READY 0x0004 | ||
409 | #define AC97_VREF_ON 0x0008 | ||
410 | #define AC97_PR0 0x0100 | ||
411 | #define AC97_PR1 0x0200 | ||
412 | #define AC97_PR2 0x0400 | ||
413 | #define AC97_PR3 0x0800 | ||
414 | #define AC97_PR4 0x1000 | ||
415 | |||
416 | #define AC97_RESERVED1 0x28 | ||
417 | |||
418 | #define AC97_VENDOR_TEST 0x5A | ||
419 | |||
420 | #define AC97_CLOCK_DELAY 0x5C | ||
421 | #define AC97_LINEOUT_MUX_SEL 0x0001 | ||
422 | #define AC97_MONO_MUX_SEL 0x0002 | ||
423 | #define AC97_CLOCK_DELAY_SEL 0x1F | ||
424 | #define AC97_DAC_CDS_SHIFT 6 | ||
425 | #define AC97_ADC_CDS_SHIFT 11 | ||
426 | |||
427 | #define AC97_MULTI_CHANNEL_SEL 0x74 | ||
428 | |||
429 | /*#define AC97_VENDOR_ID1 0x7C | ||
430 | #define AC97_VENDOR_ID2 0x7E*/ | ||
431 | |||
432 | /* | 364 | /* |
433 | * ASSP control regs | 365 | * ASSP control regs |
434 | */ | 366 | */ |
@@ -2459,9 +2391,10 @@ static int snd_m3_free(struct snd_m3 *chip) | |||
2459 | * APM support | 2391 | * APM support |
2460 | */ | 2392 | */ |
2461 | #ifdef CONFIG_PM | 2393 | #ifdef CONFIG_PM |
2462 | static int m3_suspend(struct pci_dev *pci, pm_message_t state) | 2394 | static int m3_suspend(struct device *dev) |
2463 | { | 2395 | { |
2464 | struct snd_card *card = pci_get_drvdata(pci); | 2396 | struct pci_dev *pci = to_pci_dev(dev); |
2397 | struct snd_card *card = dev_get_drvdata(dev); | ||
2465 | struct snd_m3 *chip = card->private_data; | 2398 | struct snd_m3 *chip = card->private_data; |
2466 | int i, dsp_index; | 2399 | int i, dsp_index; |
2467 | 2400 | ||
@@ -2489,13 +2422,14 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state) | |||
2489 | 2422 | ||
2490 | pci_disable_device(pci); | 2423 | pci_disable_device(pci); |
2491 | pci_save_state(pci); | 2424 | pci_save_state(pci); |
2492 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 2425 | pci_set_power_state(pci, PCI_D3hot); |
2493 | return 0; | 2426 | return 0; |
2494 | } | 2427 | } |
2495 | 2428 | ||
2496 | static int m3_resume(struct pci_dev *pci) | 2429 | static int m3_resume(struct device *dev) |
2497 | { | 2430 | { |
2498 | struct snd_card *card = pci_get_drvdata(pci); | 2431 | struct pci_dev *pci = to_pci_dev(dev); |
2432 | struct snd_card *card = dev_get_drvdata(dev); | ||
2499 | struct snd_m3 *chip = card->private_data; | 2433 | struct snd_m3 *chip = card->private_data; |
2500 | int i, dsp_index; | 2434 | int i, dsp_index; |
2501 | 2435 | ||
@@ -2546,6 +2480,11 @@ static int m3_resume(struct pci_dev *pci) | |||
2546 | chip->in_suspend = 0; | 2480 | chip->in_suspend = 0; |
2547 | return 0; | 2481 | return 0; |
2548 | } | 2482 | } |
2483 | |||
2484 | static SIMPLE_DEV_PM_OPS(m3_pm, m3_suspend, m3_resume); | ||
2485 | #define M3_PM_OPS &m3_pm | ||
2486 | #else | ||
2487 | #define M3_PM_OPS NULL | ||
2549 | #endif /* CONFIG_PM */ | 2488 | #endif /* CONFIG_PM */ |
2550 | 2489 | ||
2551 | #ifdef CONFIG_SND_MAESTRO3_INPUT | 2490 | #ifdef CONFIG_SND_MAESTRO3_INPUT |
@@ -2842,10 +2781,9 @@ static struct pci_driver m3_driver = { | |||
2842 | .id_table = snd_m3_ids, | 2781 | .id_table = snd_m3_ids, |
2843 | .probe = snd_m3_probe, | 2782 | .probe = snd_m3_probe, |
2844 | .remove = __devexit_p(snd_m3_remove), | 2783 | .remove = __devexit_p(snd_m3_remove), |
2845 | #ifdef CONFIG_PM | 2784 | .driver = { |
2846 | .suspend = m3_suspend, | 2785 | .pm = M3_PM_OPS, |
2847 | .resume = m3_resume, | 2786 | }, |
2848 | #endif | ||
2849 | }; | 2787 | }; |
2850 | 2788 | ||
2851 | module_pci_driver(m3_driver); | 2789 | module_pci_driver(m3_driver); |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 8159b05ee94d..465cff25b146 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -1382,9 +1382,10 @@ snd_nm256_peek_for_sig(struct nm256 *chip) | |||
1382 | * APM event handler, so the card is properly reinitialized after a power | 1382 | * APM event handler, so the card is properly reinitialized after a power |
1383 | * event. | 1383 | * event. |
1384 | */ | 1384 | */ |
1385 | static int nm256_suspend(struct pci_dev *pci, pm_message_t state) | 1385 | static int nm256_suspend(struct device *dev) |
1386 | { | 1386 | { |
1387 | struct snd_card *card = pci_get_drvdata(pci); | 1387 | struct pci_dev *pci = to_pci_dev(dev); |
1388 | struct snd_card *card = dev_get_drvdata(dev); | ||
1388 | struct nm256 *chip = card->private_data; | 1389 | struct nm256 *chip = card->private_data; |
1389 | 1390 | ||
1390 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 1391 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
@@ -1393,13 +1394,14 @@ static int nm256_suspend(struct pci_dev *pci, pm_message_t state) | |||
1393 | chip->coeffs_current = 0; | 1394 | chip->coeffs_current = 0; |
1394 | pci_disable_device(pci); | 1395 | pci_disable_device(pci); |
1395 | pci_save_state(pci); | 1396 | pci_save_state(pci); |
1396 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 1397 | pci_set_power_state(pci, PCI_D3hot); |
1397 | return 0; | 1398 | return 0; |
1398 | } | 1399 | } |
1399 | 1400 | ||
1400 | static int nm256_resume(struct pci_dev *pci) | 1401 | static int nm256_resume(struct device *dev) |
1401 | { | 1402 | { |
1402 | struct snd_card *card = pci_get_drvdata(pci); | 1403 | struct pci_dev *pci = to_pci_dev(dev); |
1404 | struct snd_card *card = dev_get_drvdata(dev); | ||
1403 | struct nm256 *chip = card->private_data; | 1405 | struct nm256 *chip = card->private_data; |
1404 | int i; | 1406 | int i; |
1405 | 1407 | ||
@@ -1434,6 +1436,11 @@ static int nm256_resume(struct pci_dev *pci) | |||
1434 | chip->in_resume = 0; | 1436 | chip->in_resume = 0; |
1435 | return 0; | 1437 | return 0; |
1436 | } | 1438 | } |
1439 | |||
1440 | static SIMPLE_DEV_PM_OPS(nm256_pm, nm256_suspend, nm256_resume); | ||
1441 | #define NM256_PM_OPS &nm256_pm | ||
1442 | #else | ||
1443 | #define NM256_PM_OPS NULL | ||
1437 | #endif /* CONFIG_PM */ | 1444 | #endif /* CONFIG_PM */ |
1438 | 1445 | ||
1439 | static int snd_nm256_free(struct nm256 *chip) | 1446 | static int snd_nm256_free(struct nm256 *chip) |
@@ -1747,10 +1754,9 @@ static struct pci_driver nm256_driver = { | |||
1747 | .id_table = snd_nm256_ids, | 1754 | .id_table = snd_nm256_ids, |
1748 | .probe = snd_nm256_probe, | 1755 | .probe = snd_nm256_probe, |
1749 | .remove = __devexit_p(snd_nm256_remove), | 1756 | .remove = __devexit_p(snd_nm256_remove), |
1750 | #ifdef CONFIG_PM | 1757 | .driver = { |
1751 | .suspend = nm256_suspend, | 1758 | .pm = NM256_PM_OPS, |
1752 | .resume = nm256_resume, | 1759 | }, |
1753 | #endif | ||
1754 | }; | 1760 | }; |
1755 | 1761 | ||
1756 | module_pci_driver(nm256_driver); | 1762 | module_pci_driver(nm256_driver); |
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index 610275bfbaeb..37520a2b4dcf 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
@@ -873,8 +873,9 @@ static struct pci_driver oxygen_driver = { | |||
873 | .probe = generic_oxygen_probe, | 873 | .probe = generic_oxygen_probe, |
874 | .remove = __devexit_p(oxygen_pci_remove), | 874 | .remove = __devexit_p(oxygen_pci_remove), |
875 | #ifdef CONFIG_PM | 875 | #ifdef CONFIG_PM |
876 | .suspend = oxygen_pci_suspend, | 876 | .driver = { |
877 | .resume = oxygen_pci_resume, | 877 | .pm = &oxygen_pci_pm, |
878 | }, | ||
878 | #endif | 879 | #endif |
879 | }; | 880 | }; |
880 | 881 | ||
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index f53897a708b4..7112a89fb8bd 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
@@ -162,8 +162,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
162 | ); | 162 | ); |
163 | void oxygen_pci_remove(struct pci_dev *pci); | 163 | void oxygen_pci_remove(struct pci_dev *pci); |
164 | #ifdef CONFIG_PM | 164 | #ifdef CONFIG_PM |
165 | int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); | 165 | extern const struct dev_pm_ops oxygen_pci_pm; |
166 | int oxygen_pci_resume(struct pci_dev *pci); | ||
167 | #endif | 166 | #endif |
168 | void oxygen_pci_shutdown(struct pci_dev *pci); | 167 | void oxygen_pci_shutdown(struct pci_dev *pci); |
169 | 168 | ||
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 92e2d67f16a1..ab8738e21ad1 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -727,9 +727,10 @@ void oxygen_pci_remove(struct pci_dev *pci) | |||
727 | EXPORT_SYMBOL(oxygen_pci_remove); | 727 | EXPORT_SYMBOL(oxygen_pci_remove); |
728 | 728 | ||
729 | #ifdef CONFIG_PM | 729 | #ifdef CONFIG_PM |
730 | int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state) | 730 | static int oxygen_pci_suspend(struct device *dev) |
731 | { | 731 | { |
732 | struct snd_card *card = pci_get_drvdata(pci); | 732 | struct pci_dev *pci = to_pci_dev(dev); |
733 | struct snd_card *card = dev_get_drvdata(dev); | ||
733 | struct oxygen *chip = card->private_data; | 734 | struct oxygen *chip = card->private_data; |
734 | unsigned int i, saved_interrupt_mask; | 735 | unsigned int i, saved_interrupt_mask; |
735 | 736 | ||
@@ -756,10 +757,9 @@ int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state) | |||
756 | 757 | ||
757 | pci_disable_device(pci); | 758 | pci_disable_device(pci); |
758 | pci_save_state(pci); | 759 | pci_save_state(pci); |
759 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 760 | pci_set_power_state(pci, PCI_D3hot); |
760 | return 0; | 761 | return 0; |
761 | } | 762 | } |
762 | EXPORT_SYMBOL(oxygen_pci_suspend); | ||
763 | 763 | ||
764 | static const u32 registers_to_restore[OXYGEN_IO_SIZE / 32] = { | 764 | static const u32 registers_to_restore[OXYGEN_IO_SIZE / 32] = { |
765 | 0xffffffff, 0x00ff077f, 0x00011d08, 0x007f00ff, | 765 | 0xffffffff, 0x00ff077f, 0x00011d08, 0x007f00ff, |
@@ -787,9 +787,10 @@ static void oxygen_restore_ac97(struct oxygen *chip, unsigned int codec) | |||
787 | chip->saved_ac97_registers[codec][i]); | 787 | chip->saved_ac97_registers[codec][i]); |
788 | } | 788 | } |
789 | 789 | ||
790 | int oxygen_pci_resume(struct pci_dev *pci) | 790 | static int oxygen_pci_resume(struct device *dev) |
791 | { | 791 | { |
792 | struct snd_card *card = pci_get_drvdata(pci); | 792 | struct pci_dev *pci = to_pci_dev(dev); |
793 | struct snd_card *card = dev_get_drvdata(dev); | ||
793 | struct oxygen *chip = card->private_data; | 794 | struct oxygen *chip = card->private_data; |
794 | unsigned int i; | 795 | unsigned int i; |
795 | 796 | ||
@@ -820,7 +821,9 @@ int oxygen_pci_resume(struct pci_dev *pci) | |||
820 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 821 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
821 | return 0; | 822 | return 0; |
822 | } | 823 | } |
823 | EXPORT_SYMBOL(oxygen_pci_resume); | 824 | |
825 | SIMPLE_DEV_PM_OPS(oxygen_pci_pm, oxygen_pci_suspend, oxygen_pci_resume); | ||
826 | EXPORT_SYMBOL(oxygen_pci_pm); | ||
824 | #endif /* CONFIG_PM */ | 827 | #endif /* CONFIG_PM */ |
825 | 828 | ||
826 | void oxygen_pci_shutdown(struct pci_dev *pci) | 829 | void oxygen_pci_shutdown(struct pci_dev *pci) |
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 19962c6d38c3..d3b606b69f3b 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
@@ -94,8 +94,9 @@ static struct pci_driver xonar_driver = { | |||
94 | .probe = xonar_probe, | 94 | .probe = xonar_probe, |
95 | .remove = __devexit_p(oxygen_pci_remove), | 95 | .remove = __devexit_p(oxygen_pci_remove), |
96 | #ifdef CONFIG_PM | 96 | #ifdef CONFIG_PM |
97 | .suspend = oxygen_pci_suspend, | 97 | .driver = { |
98 | .resume = oxygen_pci_resume, | 98 | .pm = &oxygen_pci_pm, |
99 | }, | ||
99 | #endif | 100 | #endif |
100 | .shutdown = oxygen_pci_shutdown, | 101 | .shutdown = oxygen_pci_shutdown, |
101 | }; | 102 | }; |
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 0435f45e9513..e3ac1f768ff6 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
@@ -1368,6 +1368,67 @@ static void pcxhr_proc_gpo_write(struct snd_info_entry *entry, | |||
1368 | } | 1368 | } |
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | /* Access to the results of the CMD_GET_TIME_CODE RMH */ | ||
1372 | #define TIME_CODE_VALID_MASK 0x00800000 | ||
1373 | #define TIME_CODE_NEW_MASK 0x00400000 | ||
1374 | #define TIME_CODE_BACK_MASK 0x00200000 | ||
1375 | #define TIME_CODE_WAIT_MASK 0x00100000 | ||
1376 | |||
1377 | /* Values for the CMD_MANAGE_SIGNAL RMH */ | ||
1378 | #define MANAGE_SIGNAL_TIME_CODE 0x01 | ||
1379 | #define MANAGE_SIGNAL_MIDI 0x02 | ||
1380 | |||
1381 | /* linear time code read proc*/ | ||
1382 | static void pcxhr_proc_ltc(struct snd_info_entry *entry, | ||
1383 | struct snd_info_buffer *buffer) | ||
1384 | { | ||
1385 | struct snd_pcxhr *chip = entry->private_data; | ||
1386 | struct pcxhr_mgr *mgr = chip->mgr; | ||
1387 | struct pcxhr_rmh rmh; | ||
1388 | unsigned int ltcHrs, ltcMin, ltcSec, ltcFrm; | ||
1389 | int err; | ||
1390 | /* commands available when embedded DSP is running */ | ||
1391 | if (!(mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))) { | ||
1392 | snd_iprintf(buffer, "no firmware loaded\n"); | ||
1393 | return; | ||
1394 | } | ||
1395 | if (!mgr->capture_ltc) { | ||
1396 | pcxhr_init_rmh(&rmh, CMD_MANAGE_SIGNAL); | ||
1397 | rmh.cmd[0] |= MANAGE_SIGNAL_TIME_CODE; | ||
1398 | err = pcxhr_send_msg(mgr, &rmh); | ||
1399 | if (err) { | ||
1400 | snd_iprintf(buffer, "ltc not activated (%d)\n", err); | ||
1401 | return; | ||
1402 | } | ||
1403 | if (mgr->is_hr_stereo) | ||
1404 | hr222_manage_timecode(mgr, 1); | ||
1405 | else | ||
1406 | pcxhr_write_io_num_reg_cont(mgr, REG_CONT_VALSMPTE, | ||
1407 | REG_CONT_VALSMPTE, NULL); | ||
1408 | mgr->capture_ltc = 1; | ||
1409 | } | ||
1410 | pcxhr_init_rmh(&rmh, CMD_GET_TIME_CODE); | ||
1411 | err = pcxhr_send_msg(mgr, &rmh); | ||
1412 | if (err) { | ||
1413 | snd_iprintf(buffer, "ltc read error (err=%d)\n", err); | ||
1414 | return ; | ||
1415 | } | ||
1416 | ltcHrs = 10*((rmh.stat[0] >> 8) & 0x3) + (rmh.stat[0] & 0xf); | ||
1417 | ltcMin = 10*((rmh.stat[1] >> 16) & 0x7) + ((rmh.stat[1] >> 8) & 0xf); | ||
1418 | ltcSec = 10*(rmh.stat[1] & 0x7) + ((rmh.stat[2] >> 16) & 0xf); | ||
1419 | ltcFrm = 10*((rmh.stat[2] >> 8) & 0x3) + (rmh.stat[2] & 0xf); | ||
1420 | |||
1421 | snd_iprintf(buffer, "timecode: %02u:%02u:%02u-%02u\n", | ||
1422 | ltcHrs, ltcMin, ltcSec, ltcFrm); | ||
1423 | snd_iprintf(buffer, "raw: 0x%04x%06x%06x\n", rmh.stat[0] & 0x00ffff, | ||
1424 | rmh.stat[1] & 0xffffff, rmh.stat[2] & 0xffffff); | ||
1425 | /*snd_iprintf(buffer, "dsp ref time: 0x%06x%06x\n", | ||
1426 | rmh.stat[3] & 0xffffff, rmh.stat[4] & 0xffffff);*/ | ||
1427 | if (!(rmh.stat[0] & TIME_CODE_VALID_MASK)) { | ||
1428 | snd_iprintf(buffer, "warning: linear timecode not valid\n"); | ||
1429 | } | ||
1430 | } | ||
1431 | |||
1371 | static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) | 1432 | static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) |
1372 | { | 1433 | { |
1373 | struct snd_info_entry *entry; | 1434 | struct snd_info_entry *entry; |
@@ -1383,6 +1444,8 @@ static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) | |||
1383 | entry->c.text.write = pcxhr_proc_gpo_write; | 1444 | entry->c.text.write = pcxhr_proc_gpo_write; |
1384 | entry->mode |= S_IWUSR; | 1445 | entry->mode |= S_IWUSR; |
1385 | } | 1446 | } |
1447 | if (!snd_card_proc_new(chip->card, "ltc", &entry)) | ||
1448 | snd_info_set_text_ops(entry, chip, pcxhr_proc_ltc); | ||
1386 | } | 1449 | } |
1387 | /* end of proc interface */ | 1450 | /* end of proc interface */ |
1388 | 1451 | ||
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h index bda776c49884..a4c602c45173 100644 --- a/sound/pci/pcxhr/pcxhr.h +++ b/sound/pci/pcxhr/pcxhr.h | |||
@@ -103,6 +103,7 @@ struct pcxhr_mgr { | |||
103 | unsigned int board_has_mic:1; /* if 1 the board has microphone input */ | 103 | unsigned int board_has_mic:1; /* if 1 the board has microphone input */ |
104 | unsigned int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */ | 104 | unsigned int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */ |
105 | unsigned int mono_capture:1; /* if 1 the board does mono capture */ | 105 | unsigned int mono_capture:1; /* if 1 the board does mono capture */ |
106 | unsigned int capture_ltc:1; /* if 1 the board captures LTC input */ | ||
106 | 107 | ||
107 | struct snd_dma_buffer hostport; | 108 | struct snd_dma_buffer hostport; |
108 | 109 | ||
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index 304411c1fe4b..b33db1e006e7 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c | |||
@@ -504,6 +504,8 @@ static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = { | |||
504 | [CMD_FORMAT_STREAM_IN] = { 0x870000, 0, RMH_SSIZE_FIXED }, | 504 | [CMD_FORMAT_STREAM_IN] = { 0x870000, 0, RMH_SSIZE_FIXED }, |
505 | [CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED }, | 505 | [CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED }, |
506 | [CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED }, | 506 | [CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED }, |
507 | [CMD_GET_TIME_CODE] = { 0x060000, 5, RMH_SSIZE_FIXED }, | ||
508 | [CMD_MANAGE_SIGNAL] = { 0x0f0000, 0, RMH_SSIZE_FIXED }, | ||
507 | }; | 509 | }; |
508 | 510 | ||
509 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 511 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
@@ -533,6 +535,8 @@ static char* cmd_names[] = { | |||
533 | [CMD_FORMAT_STREAM_IN] = "CMD_FORMAT_STREAM_IN", | 535 | [CMD_FORMAT_STREAM_IN] = "CMD_FORMAT_STREAM_IN", |
534 | [CMD_STREAM_SAMPLE_COUNT] = "CMD_STREAM_SAMPLE_COUNT", | 536 | [CMD_STREAM_SAMPLE_COUNT] = "CMD_STREAM_SAMPLE_COUNT", |
535 | [CMD_AUDIO_LEVEL_ADJUST] = "CMD_AUDIO_LEVEL_ADJUST", | 537 | [CMD_AUDIO_LEVEL_ADJUST] = "CMD_AUDIO_LEVEL_ADJUST", |
538 | [CMD_GET_TIME_CODE] = "CMD_GET_TIME_CODE", | ||
539 | [CMD_MANAGE_SIGNAL] = "CMD_MANAGE_SIGNAL", | ||
536 | }; | 540 | }; |
537 | #endif | 541 | #endif |
538 | 542 | ||
@@ -1133,13 +1137,12 @@ static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr, | |||
1133 | hw_sample_count = ((u_int64_t)rmh.stat[0]) << 24; | 1137 | hw_sample_count = ((u_int64_t)rmh.stat[0]) << 24; |
1134 | hw_sample_count += (u_int64_t)rmh.stat[1]; | 1138 | hw_sample_count += (u_int64_t)rmh.stat[1]; |
1135 | 1139 | ||
1136 | snd_printdd("stream %c%d : abs samples real(%ld) timer(%ld)\n", | 1140 | snd_printdd("stream %c%d : abs samples real(%llu) timer(%llu)\n", |
1137 | stream->pipe->is_capture ? 'C' : 'P', | 1141 | stream->pipe->is_capture ? 'C' : 'P', |
1138 | stream->substream->number, | 1142 | stream->substream->number, |
1139 | (long unsigned int)hw_sample_count, | 1143 | hw_sample_count, |
1140 | (long unsigned int)(stream->timer_abs_periods + | 1144 | stream->timer_abs_periods + stream->timer_period_frag + |
1141 | stream->timer_period_frag + | 1145 | mgr->granularity); |
1142 | mgr->granularity)); | ||
1143 | return hw_sample_count; | 1146 | return hw_sample_count; |
1144 | } | 1147 | } |
1145 | 1148 | ||
@@ -1243,10 +1246,18 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id) | |||
1243 | 1246 | ||
1244 | if ((dsp_time_diff < 0) && | 1247 | if ((dsp_time_diff < 0) && |
1245 | (mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID)) { | 1248 | (mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID)) { |
1246 | snd_printdd("ERROR DSP TIME old(%d) new(%d) -> " | 1249 | /* handle dsp counter wraparound without resync */ |
1247 | "resynchronize all streams\n", | 1250 | int tmp_diff = dsp_time_diff + PCXHR_DSP_TIME_MASK + 1; |
1251 | snd_printdd("WARNING DSP timestamp old(%d) new(%d)", | ||
1248 | mgr->dsp_time_last, dsp_time_new); | 1252 | mgr->dsp_time_last, dsp_time_new); |
1249 | mgr->dsp_time_err++; | 1253 | if (tmp_diff > 0 && tmp_diff <= (2*mgr->granularity)) { |
1254 | snd_printdd("-> timestamp wraparound OK: " | ||
1255 | "diff=%d\n", tmp_diff); | ||
1256 | dsp_time_diff = tmp_diff; | ||
1257 | } else { | ||
1258 | snd_printdd("-> resynchronize all streams\n"); | ||
1259 | mgr->dsp_time_err++; | ||
1260 | } | ||
1250 | } | 1261 | } |
1251 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 1262 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
1252 | if (dsp_time_diff == 0) | 1263 | if (dsp_time_diff == 0) |
diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h index be0173796cdb..a81ab6b811e7 100644 --- a/sound/pci/pcxhr/pcxhr_core.h +++ b/sound/pci/pcxhr/pcxhr_core.h | |||
@@ -79,6 +79,8 @@ enum { | |||
79 | CMD_FORMAT_STREAM_IN, /* cmd_len >= 4 stat_len = 0 */ | 79 | CMD_FORMAT_STREAM_IN, /* cmd_len >= 4 stat_len = 0 */ |
80 | CMD_STREAM_SAMPLE_COUNT, /* cmd_len = 2 stat_len = (2 * nb_stream) */ | 80 | CMD_STREAM_SAMPLE_COUNT, /* cmd_len = 2 stat_len = (2 * nb_stream) */ |
81 | CMD_AUDIO_LEVEL_ADJUST, /* cmd_len = 3 stat_len = 0 */ | 81 | CMD_AUDIO_LEVEL_ADJUST, /* cmd_len = 3 stat_len = 0 */ |
82 | CMD_GET_TIME_CODE, /* cmd_len = 1 stat_len = 5 */ | ||
83 | CMD_MANAGE_SIGNAL, /* cmd_len = 1 stat_len = 0 */ | ||
82 | CMD_LAST_INDEX | 84 | CMD_LAST_INDEX |
83 | }; | 85 | }; |
84 | 86 | ||
@@ -116,7 +118,7 @@ int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh); | |||
116 | #define IO_NUM_REG_OUT_ANA_LEVEL 20 | 118 | #define IO_NUM_REG_OUT_ANA_LEVEL 20 |
117 | #define IO_NUM_REG_IN_ANA_LEVEL 21 | 119 | #define IO_NUM_REG_IN_ANA_LEVEL 21 |
118 | 120 | ||
119 | 121 | #define REG_CONT_VALSMPTE 0x000800 | |
120 | #define REG_CONT_UNMUTE_INPUTS 0x020000 | 122 | #define REG_CONT_UNMUTE_INPUTS 0x020000 |
121 | 123 | ||
122 | /* parameters used with register IO_NUM_REG_STATUS */ | 124 | /* parameters used with register IO_NUM_REG_STATUS */ |
diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c index 1cb82c0a9cb3..84fe57626eba 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.c +++ b/sound/pci/pcxhr/pcxhr_mix22.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #define PCXHR_DSP_RESET_DSP 0x01 | 53 | #define PCXHR_DSP_RESET_DSP 0x01 |
54 | #define PCXHR_DSP_RESET_MUTE 0x02 | 54 | #define PCXHR_DSP_RESET_MUTE 0x02 |
55 | #define PCXHR_DSP_RESET_CODEC 0x08 | 55 | #define PCXHR_DSP_RESET_CODEC 0x08 |
56 | #define PCXHR_DSP_RESET_SMPTE 0x10 | ||
56 | #define PCXHR_DSP_RESET_GPO_OFFSET 5 | 57 | #define PCXHR_DSP_RESET_GPO_OFFSET 5 |
57 | #define PCXHR_DSP_RESET_GPO_MASK 0x60 | 58 | #define PCXHR_DSP_RESET_GPO_MASK 0x60 |
58 | 59 | ||
@@ -527,6 +528,16 @@ int hr222_write_gpo(struct pcxhr_mgr *mgr, int value) | |||
527 | return 0; | 528 | return 0; |
528 | } | 529 | } |
529 | 530 | ||
531 | int hr222_manage_timecode(struct pcxhr_mgr *mgr, int enable) | ||
532 | { | ||
533 | if (enable) | ||
534 | mgr->dsp_reset |= PCXHR_DSP_RESET_SMPTE; | ||
535 | else | ||
536 | mgr->dsp_reset &= ~PCXHR_DSP_RESET_SMPTE; | ||
537 | |||
538 | PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset); | ||
539 | return 0; | ||
540 | } | ||
530 | 541 | ||
531 | int hr222_update_analog_audio_level(struct snd_pcxhr *chip, | 542 | int hr222_update_analog_audio_level(struct snd_pcxhr *chip, |
532 | int is_capture, int channel) | 543 | int is_capture, int channel) |
diff --git a/sound/pci/pcxhr/pcxhr_mix22.h b/sound/pci/pcxhr/pcxhr_mix22.h index 5a37a0007e8f..5971b9933f41 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.h +++ b/sound/pci/pcxhr/pcxhr_mix22.h | |||
@@ -34,6 +34,7 @@ int hr222_get_external_clock(struct pcxhr_mgr *mgr, | |||
34 | 34 | ||
35 | int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value); | 35 | int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value); |
36 | int hr222_write_gpo(struct pcxhr_mgr *mgr, int value); | 36 | int hr222_write_gpo(struct pcxhr_mgr *mgr, int value); |
37 | int hr222_manage_timecode(struct pcxhr_mgr *mgr, int enable); | ||
37 | 38 | ||
38 | #define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */ | 39 | #define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */ |
39 | #define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */ | 40 | #define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */ |
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index cbeb3f77350c..760ee467cd9a 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c | |||
@@ -1151,9 +1151,10 @@ static void riptide_handleirq(unsigned long dev_id) | |||
1151 | } | 1151 | } |
1152 | 1152 | ||
1153 | #ifdef CONFIG_PM | 1153 | #ifdef CONFIG_PM |
1154 | static int riptide_suspend(struct pci_dev *pci, pm_message_t state) | 1154 | static int riptide_suspend(struct device *dev) |
1155 | { | 1155 | { |
1156 | struct snd_card *card = pci_get_drvdata(pci); | 1156 | struct pci_dev *pci = to_pci_dev(dev); |
1157 | struct snd_card *card = dev_get_drvdata(dev); | ||
1157 | struct snd_riptide *chip = card->private_data; | 1158 | struct snd_riptide *chip = card->private_data; |
1158 | 1159 | ||
1159 | chip->in_suspend = 1; | 1160 | chip->in_suspend = 1; |
@@ -1162,13 +1163,14 @@ static int riptide_suspend(struct pci_dev *pci, pm_message_t state) | |||
1162 | snd_ac97_suspend(chip->ac97); | 1163 | snd_ac97_suspend(chip->ac97); |
1163 | pci_disable_device(pci); | 1164 | pci_disable_device(pci); |
1164 | pci_save_state(pci); | 1165 | pci_save_state(pci); |
1165 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 1166 | pci_set_power_state(pci, PCI_D3hot); |
1166 | return 0; | 1167 | return 0; |
1167 | } | 1168 | } |
1168 | 1169 | ||
1169 | static int riptide_resume(struct pci_dev *pci) | 1170 | static int riptide_resume(struct device *dev) |
1170 | { | 1171 | { |
1171 | struct snd_card *card = pci_get_drvdata(pci); | 1172 | struct pci_dev *pci = to_pci_dev(dev); |
1173 | struct snd_card *card = dev_get_drvdata(dev); | ||
1172 | struct snd_riptide *chip = card->private_data; | 1174 | struct snd_riptide *chip = card->private_data; |
1173 | 1175 | ||
1174 | pci_set_power_state(pci, PCI_D0); | 1176 | pci_set_power_state(pci, PCI_D0); |
@@ -1186,7 +1188,12 @@ static int riptide_resume(struct pci_dev *pci) | |||
1186 | chip->in_suspend = 0; | 1188 | chip->in_suspend = 0; |
1187 | return 0; | 1189 | return 0; |
1188 | } | 1190 | } |
1189 | #endif | 1191 | |
1192 | static SIMPLE_DEV_PM_OPS(riptide_pm, riptide_suspend, riptide_resume); | ||
1193 | #define RIPTIDE_PM_OPS &riptide_pm | ||
1194 | #else | ||
1195 | #define RIPTIDE_PM_OPS NULL | ||
1196 | #endif /* CONFIG_PM */ | ||
1190 | 1197 | ||
1191 | static int try_to_load_firmware(struct cmdif *cif, struct snd_riptide *chip) | 1198 | static int try_to_load_firmware(struct cmdif *cif, struct snd_riptide *chip) |
1192 | { | 1199 | { |
@@ -2180,10 +2187,9 @@ static struct pci_driver driver = { | |||
2180 | .id_table = snd_riptide_ids, | 2187 | .id_table = snd_riptide_ids, |
2181 | .probe = snd_card_riptide_probe, | 2188 | .probe = snd_card_riptide_probe, |
2182 | .remove = __devexit_p(snd_card_riptide_remove), | 2189 | .remove = __devexit_p(snd_card_riptide_remove), |
2183 | #ifdef CONFIG_PM | 2190 | .driver = { |
2184 | .suspend = riptide_suspend, | 2191 | .pm = RIPTIDE_PM_OPS, |
2185 | .resume = riptide_resume, | 2192 | }, |
2186 | #endif | ||
2187 | }; | 2193 | }; |
2188 | 2194 | ||
2189 | #ifdef SUPPORT_JOYSTICK | 2195 | #ifdef SUPPORT_JOYSTICK |
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index 1552642765d6..512434efcc31 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c | |||
@@ -1209,9 +1209,10 @@ static int sis_chip_init(struct sis7019 *sis) | |||
1209 | } | 1209 | } |
1210 | 1210 | ||
1211 | #ifdef CONFIG_PM | 1211 | #ifdef CONFIG_PM |
1212 | static int sis_suspend(struct pci_dev *pci, pm_message_t state) | 1212 | static int sis_suspend(struct device *dev) |
1213 | { | 1213 | { |
1214 | struct snd_card *card = pci_get_drvdata(pci); | 1214 | struct pci_dev *pci = to_pci_dev(dev); |
1215 | struct snd_card *card = dev_get_drvdata(dev); | ||
1215 | struct sis7019 *sis = card->private_data; | 1216 | struct sis7019 *sis = card->private_data; |
1216 | void __iomem *ioaddr = sis->ioaddr; | 1217 | void __iomem *ioaddr = sis->ioaddr; |
1217 | int i; | 1218 | int i; |
@@ -1241,13 +1242,14 @@ static int sis_suspend(struct pci_dev *pci, pm_message_t state) | |||
1241 | 1242 | ||
1242 | pci_disable_device(pci); | 1243 | pci_disable_device(pci); |
1243 | pci_save_state(pci); | 1244 | pci_save_state(pci); |
1244 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 1245 | pci_set_power_state(pci, PCI_D3hot); |
1245 | return 0; | 1246 | return 0; |
1246 | } | 1247 | } |
1247 | 1248 | ||
1248 | static int sis_resume(struct pci_dev *pci) | 1249 | static int sis_resume(struct device *dev) |
1249 | { | 1250 | { |
1250 | struct snd_card *card = pci_get_drvdata(pci); | 1251 | struct pci_dev *pci = to_pci_dev(dev); |
1252 | struct snd_card *card = dev_get_drvdata(dev); | ||
1251 | struct sis7019 *sis = card->private_data; | 1253 | struct sis7019 *sis = card->private_data; |
1252 | void __iomem *ioaddr = sis->ioaddr; | 1254 | void __iomem *ioaddr = sis->ioaddr; |
1253 | int i; | 1255 | int i; |
@@ -1298,6 +1300,11 @@ error: | |||
1298 | snd_card_disconnect(card); | 1300 | snd_card_disconnect(card); |
1299 | return -EIO; | 1301 | return -EIO; |
1300 | } | 1302 | } |
1303 | |||
1304 | static SIMPLE_DEV_PM_OPS(sis_pm, sis_suspend, sis_resume); | ||
1305 | #define SIS_PM_OPS &sis_pm | ||
1306 | #else | ||
1307 | #define SIS_PM_OPS NULL | ||
1301 | #endif /* CONFIG_PM */ | 1308 | #endif /* CONFIG_PM */ |
1302 | 1309 | ||
1303 | static int sis_alloc_suspend(struct sis7019 *sis) | 1310 | static int sis_alloc_suspend(struct sis7019 *sis) |
@@ -1481,11 +1488,9 @@ static struct pci_driver sis7019_driver = { | |||
1481 | .id_table = snd_sis7019_ids, | 1488 | .id_table = snd_sis7019_ids, |
1482 | .probe = snd_sis7019_probe, | 1489 | .probe = snd_sis7019_probe, |
1483 | .remove = __devexit_p(snd_sis7019_remove), | 1490 | .remove = __devexit_p(snd_sis7019_remove), |
1484 | 1491 | .driver = { | |
1485 | #ifdef CONFIG_PM | 1492 | .pm = SIS_PM_OPS, |
1486 | .suspend = sis_suspend, | 1493 | }, |
1487 | .resume = sis_resume, | ||
1488 | #endif | ||
1489 | }; | 1494 | }; |
1490 | 1495 | ||
1491 | module_pci_driver(sis7019_driver); | 1496 | module_pci_driver(sis7019_driver); |
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index 611983ec7321..d36e6ca147e1 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/time.h> | 26 | #include <linux/time.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <sound/core.h> | 28 | #include <sound/core.h> |
29 | #include <sound/trident.h> | 29 | #include "trident.h" |
30 | #include <sound/initval.h> | 30 | #include <sound/initval.h> |
31 | 31 | ||
32 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, <audio@tridentmicro.com>"); | 32 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, <audio@tridentmicro.com>"); |
@@ -178,8 +178,9 @@ static struct pci_driver trident_driver = { | |||
178 | .probe = snd_trident_probe, | 178 | .probe = snd_trident_probe, |
179 | .remove = __devexit_p(snd_trident_remove), | 179 | .remove = __devexit_p(snd_trident_remove), |
180 | #ifdef CONFIG_PM | 180 | #ifdef CONFIG_PM |
181 | .suspend = snd_trident_suspend, | 181 | .driver = { |
182 | .resume = snd_trident_resume, | 182 | .pm = &snd_trident_pm, |
183 | }, | ||
183 | #endif | 184 | #endif |
184 | }; | 185 | }; |
185 | 186 | ||
diff --git a/sound/pci/trident/trident.h b/sound/pci/trident/trident.h new file mode 100644 index 000000000000..5f110eb56e47 --- /dev/null +++ b/sound/pci/trident/trident.h | |||
@@ -0,0 +1,444 @@ | |||
1 | #ifndef __SOUND_TRIDENT_H | ||
2 | #define __SOUND_TRIDENT_H | ||
3 | |||
4 | /* | ||
5 | * audio@tridentmicro.com | ||
6 | * Fri Feb 19 15:55:28 MST 1999 | ||
7 | * Definitions for Trident 4DWave DX/NX chips | ||
8 | * | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/mpu401.h> | ||
28 | #include <sound/ac97_codec.h> | ||
29 | #include <sound/util_mem.h> | ||
30 | |||
31 | #define TRIDENT_DEVICE_ID_DX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_DX) | ||
32 | #define TRIDENT_DEVICE_ID_NX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) | ||
33 | #define TRIDENT_DEVICE_ID_SI7018 ((PCI_VENDOR_ID_SI<<16)|PCI_DEVICE_ID_SI_7018) | ||
34 | |||
35 | #define SNDRV_TRIDENT_VOICE_TYPE_PCM 0 | ||
36 | #define SNDRV_TRIDENT_VOICE_TYPE_SYNTH 1 | ||
37 | #define SNDRV_TRIDENT_VOICE_TYPE_MIDI 2 | ||
38 | |||
39 | #define SNDRV_TRIDENT_VFLG_RUNNING (1<<0) | ||
40 | |||
41 | /* TLB code constants */ | ||
42 | #define SNDRV_TRIDENT_PAGE_SIZE 4096 | ||
43 | #define SNDRV_TRIDENT_PAGE_SHIFT 12 | ||
44 | #define SNDRV_TRIDENT_PAGE_MASK ((1<<SNDRV_TRIDENT_PAGE_SHIFT)-1) | ||
45 | #define SNDRV_TRIDENT_MAX_PAGES 4096 | ||
46 | |||
47 | /* | ||
48 | * Direct registers | ||
49 | */ | ||
50 | |||
51 | #define TRID_REG(trident, x) ((trident)->port + (x)) | ||
52 | |||
53 | #define ID_4DWAVE_DX 0x2000 | ||
54 | #define ID_4DWAVE_NX 0x2001 | ||
55 | |||
56 | /* Bank definitions */ | ||
57 | |||
58 | #define T4D_BANK_A 0 | ||
59 | #define T4D_BANK_B 1 | ||
60 | #define T4D_NUM_BANKS 2 | ||
61 | |||
62 | /* Register definitions */ | ||
63 | |||
64 | /* Global registers */ | ||
65 | |||
66 | enum global_control_bits { | ||
67 | CHANNEL_IDX = 0x0000003f, | ||
68 | OVERRUN_IE = 0x00000400, /* interrupt enable: capture overrun */ | ||
69 | UNDERRUN_IE = 0x00000800, /* interrupt enable: playback underrun */ | ||
70 | ENDLP_IE = 0x00001000, /* interrupt enable: end of buffer */ | ||
71 | MIDLP_IE = 0x00002000, /* interrupt enable: middle buffer */ | ||
72 | ETOG_IE = 0x00004000, /* interrupt enable: envelope toggling */ | ||
73 | EDROP_IE = 0x00008000, /* interrupt enable: envelope drop */ | ||
74 | BANK_B_EN = 0x00010000, /* SiS: enable bank B (64 channels) */ | ||
75 | PCMIN_B_MIX = 0x00020000, /* SiS: PCM IN B mixing enable */ | ||
76 | I2S_OUT_ASSIGN = 0x00040000, /* SiS: I2S Out contains surround PCM */ | ||
77 | SPDIF_OUT_ASSIGN= 0x00080000, /* SiS: 0=S/PDIF L/R | 1=PCM Out FIFO */ | ||
78 | MAIN_OUT_ASSIGN = 0x00100000, /* SiS: 0=PCM Out FIFO | 1=MMC Out buffer */ | ||
79 | }; | ||
80 | |||
81 | enum miscint_bits { | ||
82 | PB_UNDERRUN_IRQ = 0x00000001, REC_OVERRUN_IRQ = 0x00000002, | ||
83 | SB_IRQ = 0x00000004, MPU401_IRQ = 0x00000008, | ||
84 | OPL3_IRQ = 0x00000010, ADDRESS_IRQ = 0x00000020, | ||
85 | ENVELOPE_IRQ = 0x00000040, PB_UNDERRUN = 0x00000100, | ||
86 | REC_OVERRUN = 0x00000200, MIXER_UNDERFLOW = 0x00000400, | ||
87 | MIXER_OVERFLOW = 0x00000800, NX_SB_IRQ_DISABLE = 0x00001000, | ||
88 | ST_TARGET_REACHED = 0x00008000, | ||
89 | PB_24K_MODE = 0x00010000, ST_IRQ_EN = 0x00800000, | ||
90 | ACGPIO_IRQ = 0x01000000 | ||
91 | }; | ||
92 | |||
93 | /* T2 legacy dma control registers. */ | ||
94 | #define LEGACY_DMAR0 0x00 // ADR0 | ||
95 | #define LEGACY_DMAR4 0x04 // CNT0 | ||
96 | #define LEGACY_DMAR6 0x06 // CNT0 - High bits | ||
97 | #define LEGACY_DMAR11 0x0b // MOD | ||
98 | #define LEGACY_DMAR15 0x0f // MMR | ||
99 | |||
100 | #define T4D_START_A 0x80 | ||
101 | #define T4D_STOP_A 0x84 | ||
102 | #define T4D_DLY_A 0x88 | ||
103 | #define T4D_SIGN_CSO_A 0x8c | ||
104 | #define T4D_CSPF_A 0x90 | ||
105 | #define T4D_CSPF_B 0xbc | ||
106 | #define T4D_CEBC_A 0x94 | ||
107 | #define T4D_AINT_A 0x98 | ||
108 | #define T4D_AINTEN_A 0x9c | ||
109 | #define T4D_LFO_GC_CIR 0xa0 | ||
110 | #define T4D_MUSICVOL_WAVEVOL 0xa8 | ||
111 | #define T4D_SBDELTA_DELTA_R 0xac | ||
112 | #define T4D_MISCINT 0xb0 | ||
113 | #define T4D_START_B 0xb4 | ||
114 | #define T4D_STOP_B 0xb8 | ||
115 | #define T4D_SBBL_SBCL 0xc0 | ||
116 | #define T4D_SBCTRL_SBE2R_SBDD 0xc4 | ||
117 | #define T4D_STIMER 0xc8 | ||
118 | #define T4D_AINT_B 0xd8 | ||
119 | #define T4D_AINTEN_B 0xdc | ||
120 | #define T4D_RCI 0x70 | ||
121 | |||
122 | /* MPU-401 UART */ | ||
123 | #define T4D_MPU401_BASE 0x20 | ||
124 | #define T4D_MPUR0 0x20 | ||
125 | #define T4D_MPUR1 0x21 | ||
126 | #define T4D_MPUR2 0x22 | ||
127 | #define T4D_MPUR3 0x23 | ||
128 | |||
129 | /* S/PDIF Registers */ | ||
130 | #define NX_SPCTRL_SPCSO 0x24 | ||
131 | #define NX_SPLBA 0x28 | ||
132 | #define NX_SPESO 0x2c | ||
133 | #define NX_SPCSTATUS 0x64 | ||
134 | |||
135 | /* Joystick */ | ||
136 | #define GAMEPORT_GCR 0x30 | ||
137 | #define GAMEPORT_MODE_ADC 0x80 | ||
138 | #define GAMEPORT_LEGACY 0x31 | ||
139 | #define GAMEPORT_AXES 0x34 | ||
140 | |||
141 | /* NX Specific Registers */ | ||
142 | #define NX_TLBC 0x6c | ||
143 | |||
144 | /* Channel Registers */ | ||
145 | |||
146 | #define CH_START 0xe0 | ||
147 | |||
148 | #define CH_DX_CSO_ALPHA_FMS 0xe0 | ||
149 | #define CH_DX_ESO_DELTA 0xe8 | ||
150 | #define CH_DX_FMC_RVOL_CVOL 0xec | ||
151 | |||
152 | #define CH_NX_DELTA_CSO 0xe0 | ||
153 | #define CH_NX_DELTA_ESO 0xe8 | ||
154 | #define CH_NX_ALPHA_FMS_FMC_RVOL_CVOL 0xec | ||
155 | |||
156 | #define CH_LBA 0xe4 | ||
157 | #define CH_GVSEL_PAN_VOL_CTRL_EC 0xf0 | ||
158 | #define CH_EBUF1 0xf4 | ||
159 | #define CH_EBUF2 0xf8 | ||
160 | |||
161 | /* AC-97 Registers */ | ||
162 | |||
163 | #define DX_ACR0_AC97_W 0x40 | ||
164 | #define DX_ACR1_AC97_R 0x44 | ||
165 | #define DX_ACR2_AC97_COM_STAT 0x48 | ||
166 | |||
167 | #define NX_ACR0_AC97_COM_STAT 0x40 | ||
168 | #define NX_ACR1_AC97_W 0x44 | ||
169 | #define NX_ACR2_AC97_R_PRIMARY 0x48 | ||
170 | #define NX_ACR3_AC97_R_SECONDARY 0x4c | ||
171 | |||
172 | #define SI_AC97_WRITE 0x40 | ||
173 | #define SI_AC97_READ 0x44 | ||
174 | #define SI_SERIAL_INTF_CTRL 0x48 | ||
175 | #define SI_AC97_GPIO 0x4c | ||
176 | #define SI_ASR0 0x50 | ||
177 | #define SI_SPDIF_CS 0x70 | ||
178 | #define SI_GPIO 0x7c | ||
179 | |||
180 | enum trident_nx_ac97_bits { | ||
181 | /* ACR1-3 */ | ||
182 | NX_AC97_BUSY_WRITE = 0x0800, | ||
183 | NX_AC97_BUSY_READ = 0x0800, | ||
184 | NX_AC97_BUSY_DATA = 0x0400, | ||
185 | NX_AC97_WRITE_SECONDARY = 0x0100, | ||
186 | /* ACR0 */ | ||
187 | NX_AC97_SECONDARY_READY = 0x0040, | ||
188 | NX_AC97_SECONDARY_RECORD = 0x0020, | ||
189 | NX_AC97_SURROUND_OUTPUT = 0x0010, | ||
190 | NX_AC97_PRIMARY_READY = 0x0008, | ||
191 | NX_AC97_PRIMARY_RECORD = 0x0004, | ||
192 | NX_AC97_PCM_OUTPUT = 0x0002, | ||
193 | NX_AC97_WARM_RESET = 0x0001 | ||
194 | }; | ||
195 | |||
196 | enum trident_dx_ac97_bits { | ||
197 | DX_AC97_BUSY_WRITE = 0x8000, | ||
198 | DX_AC97_BUSY_READ = 0x8000, | ||
199 | DX_AC97_READY = 0x0010, | ||
200 | DX_AC97_RECORD = 0x0008, | ||
201 | DX_AC97_PLAYBACK = 0x0002 | ||
202 | }; | ||
203 | |||
204 | enum sis7018_ac97_bits { | ||
205 | SI_AC97_BUSY_WRITE = 0x00008000, | ||
206 | SI_AC97_AUDIO_BUSY = 0x00004000, | ||
207 | SI_AC97_MODEM_BUSY = 0x00002000, | ||
208 | SI_AC97_BUSY_READ = 0x00008000, | ||
209 | SI_AC97_SECONDARY = 0x00000080, | ||
210 | }; | ||
211 | |||
212 | enum serial_intf_ctrl_bits { | ||
213 | WARM_RESET = 0x00000001, | ||
214 | COLD_RESET = 0x00000002, | ||
215 | I2S_CLOCK = 0x00000004, | ||
216 | PCM_SEC_AC97 = 0x00000008, | ||
217 | AC97_DBL_RATE = 0x00000010, | ||
218 | SPDIF_EN = 0x00000020, | ||
219 | I2S_OUTPUT_EN = 0x00000040, | ||
220 | I2S_INPUT_EN = 0x00000080, | ||
221 | PCMIN = 0x00000100, | ||
222 | LINE1IN = 0x00000200, | ||
223 | MICIN = 0x00000400, | ||
224 | LINE2IN = 0x00000800, | ||
225 | HEAD_SET_IN = 0x00001000, | ||
226 | GPIOIN = 0x00002000, | ||
227 | /* 7018 spec says id = 01 but the demo board routed to 10 | ||
228 | SECONDARY_ID= 0x00004000, */ | ||
229 | SECONDARY_ID = 0x00004000, | ||
230 | PCMOUT = 0x00010000, | ||
231 | SURROUT = 0x00020000, | ||
232 | CENTEROUT = 0x00040000, | ||
233 | LFEOUT = 0x00080000, | ||
234 | LINE1OUT = 0x00100000, | ||
235 | LINE2OUT = 0x00200000, | ||
236 | GPIOOUT = 0x00400000, | ||
237 | SI_AC97_PRIMARY_READY = 0x01000000, | ||
238 | SI_AC97_SECONDARY_READY = 0x02000000, | ||
239 | SI_AC97_POWERDOWN = 0x04000000, | ||
240 | }; | ||
241 | |||
242 | /* PCM defaults */ | ||
243 | |||
244 | #define T4D_DEFAULT_PCM_VOL 10 /* 0 - 255 */ | ||
245 | #define T4D_DEFAULT_PCM_PAN 0 /* 0 - 127 */ | ||
246 | #define T4D_DEFAULT_PCM_RVOL 127 /* 0 - 127 */ | ||
247 | #define T4D_DEFAULT_PCM_CVOL 127 /* 0 - 127 */ | ||
248 | |||
249 | struct snd_trident; | ||
250 | struct snd_trident_voice; | ||
251 | struct snd_trident_pcm_mixer; | ||
252 | |||
253 | struct snd_trident_port { | ||
254 | struct snd_midi_channel_set * chset; | ||
255 | struct snd_trident * trident; | ||
256 | int mode; /* operation mode */ | ||
257 | int client; /* sequencer client number */ | ||
258 | int port; /* sequencer port number */ | ||
259 | unsigned int midi_has_voices: 1; | ||
260 | }; | ||
261 | |||
262 | struct snd_trident_memblk_arg { | ||
263 | short first_page, last_page; | ||
264 | }; | ||
265 | |||
266 | struct snd_trident_tlb { | ||
267 | unsigned int * entries; /* 16k-aligned TLB table */ | ||
268 | dma_addr_t entries_dmaaddr; /* 16k-aligned PCI address to TLB table */ | ||
269 | unsigned long * shadow_entries; /* shadow entries with virtual addresses */ | ||
270 | struct snd_dma_buffer buffer; | ||
271 | struct snd_util_memhdr * memhdr; /* page allocation list */ | ||
272 | struct snd_dma_buffer silent_page; | ||
273 | }; | ||
274 | |||
275 | struct snd_trident_voice { | ||
276 | unsigned int number; | ||
277 | unsigned int use: 1, | ||
278 | pcm: 1, | ||
279 | synth:1, | ||
280 | midi: 1; | ||
281 | unsigned int flags; | ||
282 | unsigned char client; | ||
283 | unsigned char port; | ||
284 | unsigned char index; | ||
285 | |||
286 | struct snd_trident_sample_ops *sample_ops; | ||
287 | |||
288 | /* channel parameters */ | ||
289 | unsigned int CSO; /* 24 bits (16 on DX) */ | ||
290 | unsigned int ESO; /* 24 bits (16 on DX) */ | ||
291 | unsigned int LBA; /* 30 bits */ | ||
292 | unsigned short EC; /* 12 bits */ | ||
293 | unsigned short Alpha; /* 12 bits */ | ||
294 | unsigned short Delta; /* 16 bits */ | ||
295 | unsigned short Attribute; /* 16 bits - SiS 7018 */ | ||
296 | unsigned short Vol; /* 12 bits (6.6) */ | ||
297 | unsigned char Pan; /* 7 bits (1.4.2) */ | ||
298 | unsigned char GVSel; /* 1 bit */ | ||
299 | unsigned char RVol; /* 7 bits (5.2) */ | ||
300 | unsigned char CVol; /* 7 bits (5.2) */ | ||
301 | unsigned char FMC; /* 2 bits */ | ||
302 | unsigned char CTRL; /* 4 bits */ | ||
303 | unsigned char FMS; /* 4 bits */ | ||
304 | unsigned char LFO; /* 8 bits */ | ||
305 | |||
306 | unsigned int negCSO; /* nonzero - use negative CSO */ | ||
307 | |||
308 | struct snd_util_memblk *memblk; /* memory block if TLB enabled */ | ||
309 | |||
310 | /* PCM data */ | ||
311 | |||
312 | struct snd_trident *trident; | ||
313 | struct snd_pcm_substream *substream; | ||
314 | struct snd_trident_voice *extra; /* extra PCM voice (acts as interrupt generator) */ | ||
315 | unsigned int running: 1, | ||
316 | capture: 1, | ||
317 | spdif: 1, | ||
318 | foldback: 1, | ||
319 | isync: 1, | ||
320 | isync2: 1, | ||
321 | isync3: 1; | ||
322 | int foldback_chan; /* foldback subdevice number */ | ||
323 | unsigned int stimer; /* global sample timer (to detect spurious interrupts) */ | ||
324 | unsigned int spurious_threshold; /* spurious threshold */ | ||
325 | unsigned int isync_mark; | ||
326 | unsigned int isync_max; | ||
327 | unsigned int isync_ESO; | ||
328 | |||
329 | /* --- */ | ||
330 | |||
331 | void *private_data; | ||
332 | void (*private_free)(struct snd_trident_voice *voice); | ||
333 | }; | ||
334 | |||
335 | struct snd_4dwave { | ||
336 | int seq_client; | ||
337 | |||
338 | struct snd_trident_port seq_ports[4]; | ||
339 | struct snd_trident_voice voices[64]; | ||
340 | |||
341 | int ChanSynthCount; /* number of allocated synth channels */ | ||
342 | int max_size; /* maximum synth memory size in bytes */ | ||
343 | int current_size; /* current allocated synth mem in bytes */ | ||
344 | }; | ||
345 | |||
346 | struct snd_trident_pcm_mixer { | ||
347 | struct snd_trident_voice *voice; /* active voice */ | ||
348 | unsigned short vol; /* front volume */ | ||
349 | unsigned char pan; /* pan control */ | ||
350 | unsigned char rvol; /* rear volume */ | ||
351 | unsigned char cvol; /* center volume */ | ||
352 | unsigned char pad; | ||
353 | }; | ||
354 | |||
355 | struct snd_trident { | ||
356 | int irq; | ||
357 | |||
358 | unsigned int device; /* device ID */ | ||
359 | |||
360 | unsigned char bDMAStart; | ||
361 | |||
362 | unsigned long port; | ||
363 | unsigned long midi_port; | ||
364 | |||
365 | unsigned int spurious_irq_count; | ||
366 | unsigned int spurious_irq_max_delta; | ||
367 | |||
368 | struct snd_trident_tlb tlb; /* TLB entries for NX cards */ | ||
369 | |||
370 | unsigned char spdif_ctrl; | ||
371 | unsigned char spdif_pcm_ctrl; | ||
372 | unsigned int spdif_bits; | ||
373 | unsigned int spdif_pcm_bits; | ||
374 | struct snd_kcontrol *spdif_pcm_ctl; /* S/PDIF settings */ | ||
375 | unsigned int ac97_ctrl; | ||
376 | |||
377 | unsigned int ChanMap[2]; /* allocation map for hardware channels */ | ||
378 | |||
379 | int ChanPCM; /* max number of PCM channels */ | ||
380 | int ChanPCMcnt; /* actual number of PCM channels */ | ||
381 | |||
382 | unsigned int ac97_detect: 1; /* 1 = AC97 in detection phase */ | ||
383 | unsigned int in_suspend: 1; /* 1 during suspend/resume */ | ||
384 | |||
385 | struct snd_4dwave synth; /* synth specific variables */ | ||
386 | |||
387 | spinlock_t event_lock; | ||
388 | spinlock_t voice_alloc; | ||
389 | |||
390 | struct snd_dma_device dma_dev; | ||
391 | |||
392 | struct pci_dev *pci; | ||
393 | struct snd_card *card; | ||
394 | struct snd_pcm *pcm; /* ADC/DAC PCM */ | ||
395 | struct snd_pcm *foldback; /* Foldback PCM */ | ||
396 | struct snd_pcm *spdif; /* SPDIF PCM */ | ||
397 | struct snd_rawmidi *rmidi; | ||
398 | |||
399 | struct snd_ac97_bus *ac97_bus; | ||
400 | struct snd_ac97 *ac97; | ||
401 | struct snd_ac97 *ac97_sec; | ||
402 | |||
403 | unsigned int musicvol_wavevol; | ||
404 | struct snd_trident_pcm_mixer pcm_mixer[32]; | ||
405 | struct snd_kcontrol *ctl_vol; /* front volume */ | ||
406 | struct snd_kcontrol *ctl_pan; /* pan */ | ||
407 | struct snd_kcontrol *ctl_rvol; /* rear volume */ | ||
408 | struct snd_kcontrol *ctl_cvol; /* center volume */ | ||
409 | |||
410 | spinlock_t reg_lock; | ||
411 | |||
412 | struct gameport *gameport; | ||
413 | }; | ||
414 | |||
415 | int snd_trident_create(struct snd_card *card, | ||
416 | struct pci_dev *pci, | ||
417 | int pcm_streams, | ||
418 | int pcm_spdif_device, | ||
419 | int max_wavetable_size, | ||
420 | struct snd_trident ** rtrident); | ||
421 | int snd_trident_create_gameport(struct snd_trident *trident); | ||
422 | |||
423 | int snd_trident_pcm(struct snd_trident * trident, int device, struct snd_pcm **rpcm); | ||
424 | int snd_trident_foldback_pcm(struct snd_trident * trident, int device, struct snd_pcm **rpcm); | ||
425 | int snd_trident_spdif_pcm(struct snd_trident * trident, int device, struct snd_pcm **rpcm); | ||
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, | ||
428 | int client, int port); | ||
429 | void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice); | ||
430 | void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice); | ||
431 | void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice); | ||
432 | void snd_trident_write_voice_regs(struct snd_trident * trident, struct snd_trident_voice *voice); | ||
433 | extern const struct dev_pm_ops snd_trident_pm; | ||
434 | |||
435 | /* TLB memory allocation */ | ||
436 | struct snd_util_memblk *snd_trident_alloc_pages(struct snd_trident *trident, | ||
437 | struct snd_pcm_substream *substream); | ||
438 | int snd_trident_free_pages(struct snd_trident *trident, struct snd_util_memblk *blk); | ||
439 | struct snd_util_memblk *snd_trident_synth_alloc(struct snd_trident *trident, unsigned int size); | ||
440 | int snd_trident_synth_free(struct snd_trident *trident, struct snd_util_memblk *blk); | ||
441 | int snd_trident_synth_copy_from_user(struct snd_trident *trident, struct snd_util_memblk *blk, | ||
442 | int offset, const char __user *data, int size); | ||
443 | |||
444 | #endif /* __SOUND_TRIDENT_H */ | ||
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 61d3c0e8d4ce..94011dcae731 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -41,7 +41,7 @@ | |||
41 | #include <sound/info.h> | 41 | #include <sound/info.h> |
42 | #include <sound/control.h> | 42 | #include <sound/control.h> |
43 | #include <sound/tlv.h> | 43 | #include <sound/tlv.h> |
44 | #include <sound/trident.h> | 44 | #include "trident.h" |
45 | #include <sound/asoundef.h> | 45 | #include <sound/asoundef.h> |
46 | 46 | ||
47 | #include <asm/io.h> | 47 | #include <asm/io.h> |
@@ -3920,9 +3920,10 @@ static void snd_trident_clear_voices(struct snd_trident * trident, unsigned shor | |||
3920 | } | 3920 | } |
3921 | 3921 | ||
3922 | #ifdef CONFIG_PM | 3922 | #ifdef CONFIG_PM |
3923 | int snd_trident_suspend(struct pci_dev *pci, pm_message_t state) | 3923 | static int snd_trident_suspend(struct device *dev) |
3924 | { | 3924 | { |
3925 | struct snd_card *card = pci_get_drvdata(pci); | 3925 | struct pci_dev *pci = to_pci_dev(dev); |
3926 | struct snd_card *card = dev_get_drvdata(dev); | ||
3926 | struct snd_trident *trident = card->private_data; | 3927 | struct snd_trident *trident = card->private_data; |
3927 | 3928 | ||
3928 | trident->in_suspend = 1; | 3929 | trident->in_suspend = 1; |
@@ -3936,13 +3937,14 @@ int snd_trident_suspend(struct pci_dev *pci, pm_message_t state) | |||
3936 | 3937 | ||
3937 | pci_disable_device(pci); | 3938 | pci_disable_device(pci); |
3938 | pci_save_state(pci); | 3939 | pci_save_state(pci); |
3939 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 3940 | pci_set_power_state(pci, PCI_D3hot); |
3940 | return 0; | 3941 | return 0; |
3941 | } | 3942 | } |
3942 | 3943 | ||
3943 | int snd_trident_resume(struct pci_dev *pci) | 3944 | static int snd_trident_resume(struct device *dev) |
3944 | { | 3945 | { |
3945 | struct snd_card *card = pci_get_drvdata(pci); | 3946 | struct pci_dev *pci = to_pci_dev(dev); |
3947 | struct snd_card *card = dev_get_drvdata(dev); | ||
3946 | struct snd_trident *trident = card->private_data; | 3948 | struct snd_trident *trident = card->private_data; |
3947 | 3949 | ||
3948 | pci_set_power_state(pci, PCI_D0); | 3950 | pci_set_power_state(pci, PCI_D0); |
@@ -3979,4 +3981,6 @@ int snd_trident_resume(struct pci_dev *pci) | |||
3979 | trident->in_suspend = 0; | 3981 | trident->in_suspend = 0; |
3980 | return 0; | 3982 | return 0; |
3981 | } | 3983 | } |
3984 | |||
3985 | SIMPLE_DEV_PM_OPS(snd_trident_pm, snd_trident_suspend, snd_trident_resume); | ||
3982 | #endif /* CONFIG_PM */ | 3986 | #endif /* CONFIG_PM */ |
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index f9779e23fe57..3102a579660b 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
30 | 30 | ||
31 | #include <sound/core.h> | 31 | #include <sound/core.h> |
32 | #include <sound/trident.h> | 32 | #include "trident.h" |
33 | 33 | ||
34 | /* page arguments of these two macros are Trident page (4096 bytes), not like | 34 | /* page arguments of these two macros are Trident page (4096 bytes), not like |
35 | * aligned pages in others | 35 | * aligned pages in others |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index b5afab48943e..0eb7245dd362 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -2242,9 +2242,10 @@ static int snd_via82xx_chip_init(struct via82xx *chip) | |||
2242 | /* | 2242 | /* |
2243 | * power management | 2243 | * power management |
2244 | */ | 2244 | */ |
2245 | static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) | 2245 | static int snd_via82xx_suspend(struct device *dev) |
2246 | { | 2246 | { |
2247 | struct snd_card *card = pci_get_drvdata(pci); | 2247 | struct pci_dev *pci = to_pci_dev(dev); |
2248 | struct snd_card *card = dev_get_drvdata(dev); | ||
2248 | struct via82xx *chip = card->private_data; | 2249 | struct via82xx *chip = card->private_data; |
2249 | int i; | 2250 | int i; |
2250 | 2251 | ||
@@ -2265,13 +2266,14 @@ static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) | |||
2265 | 2266 | ||
2266 | pci_disable_device(pci); | 2267 | pci_disable_device(pci); |
2267 | pci_save_state(pci); | 2268 | pci_save_state(pci); |
2268 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 2269 | pci_set_power_state(pci, PCI_D3hot); |
2269 | return 0; | 2270 | return 0; |
2270 | } | 2271 | } |
2271 | 2272 | ||
2272 | static int snd_via82xx_resume(struct pci_dev *pci) | 2273 | static int snd_via82xx_resume(struct device *dev) |
2273 | { | 2274 | { |
2274 | struct snd_card *card = pci_get_drvdata(pci); | 2275 | struct pci_dev *pci = to_pci_dev(dev); |
2276 | struct snd_card *card = dev_get_drvdata(dev); | ||
2275 | struct via82xx *chip = card->private_data; | 2277 | struct via82xx *chip = card->private_data; |
2276 | int i; | 2278 | int i; |
2277 | 2279 | ||
@@ -2306,6 +2308,11 @@ static int snd_via82xx_resume(struct pci_dev *pci) | |||
2306 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2308 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
2307 | return 0; | 2309 | return 0; |
2308 | } | 2310 | } |
2311 | |||
2312 | static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume); | ||
2313 | #define SND_VIA82XX_PM_OPS &snd_via82xx_pm | ||
2314 | #else | ||
2315 | #define SND_VIA82XX_PM_OPS NULL | ||
2309 | #endif /* CONFIG_PM */ | 2316 | #endif /* CONFIG_PM */ |
2310 | 2317 | ||
2311 | static int snd_via82xx_free(struct via82xx *chip) | 2318 | static int snd_via82xx_free(struct via82xx *chip) |
@@ -2624,10 +2631,9 @@ static struct pci_driver via82xx_driver = { | |||
2624 | .id_table = snd_via82xx_ids, | 2631 | .id_table = snd_via82xx_ids, |
2625 | .probe = snd_via82xx_probe, | 2632 | .probe = snd_via82xx_probe, |
2626 | .remove = __devexit_p(snd_via82xx_remove), | 2633 | .remove = __devexit_p(snd_via82xx_remove), |
2627 | #ifdef CONFIG_PM | 2634 | .driver = { |
2628 | .suspend = snd_via82xx_suspend, | 2635 | .pm = SND_VIA82XX_PM_OPS, |
2629 | .resume = snd_via82xx_resume, | 2636 | }, |
2630 | #endif | ||
2631 | }; | 2637 | }; |
2632 | 2638 | ||
2633 | module_pci_driver(via82xx_driver); | 2639 | module_pci_driver(via82xx_driver); |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 59fd47ed0a31..e886bc16999d 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -1023,9 +1023,10 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) | |||
1023 | /* | 1023 | /* |
1024 | * power management | 1024 | * power management |
1025 | */ | 1025 | */ |
1026 | static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) | 1026 | static int snd_via82xx_suspend(struct device *dev) |
1027 | { | 1027 | { |
1028 | struct snd_card *card = pci_get_drvdata(pci); | 1028 | struct pci_dev *pci = to_pci_dev(dev); |
1029 | struct snd_card *card = dev_get_drvdata(dev); | ||
1029 | struct via82xx_modem *chip = card->private_data; | 1030 | struct via82xx_modem *chip = card->private_data; |
1030 | int i; | 1031 | int i; |
1031 | 1032 | ||
@@ -1039,13 +1040,14 @@ static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) | |||
1039 | 1040 | ||
1040 | pci_disable_device(pci); | 1041 | pci_disable_device(pci); |
1041 | pci_save_state(pci); | 1042 | pci_save_state(pci); |
1042 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 1043 | pci_set_power_state(pci, PCI_D3hot); |
1043 | return 0; | 1044 | return 0; |
1044 | } | 1045 | } |
1045 | 1046 | ||
1046 | static int snd_via82xx_resume(struct pci_dev *pci) | 1047 | static int snd_via82xx_resume(struct device *dev) |
1047 | { | 1048 | { |
1048 | struct snd_card *card = pci_get_drvdata(pci); | 1049 | struct pci_dev *pci = to_pci_dev(dev); |
1050 | struct snd_card *card = dev_get_drvdata(dev); | ||
1049 | struct via82xx_modem *chip = card->private_data; | 1051 | struct via82xx_modem *chip = card->private_data; |
1050 | int i; | 1052 | int i; |
1051 | 1053 | ||
@@ -1069,6 +1071,11 @@ static int snd_via82xx_resume(struct pci_dev *pci) | |||
1069 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1071 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1070 | return 0; | 1072 | return 0; |
1071 | } | 1073 | } |
1074 | |||
1075 | static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume); | ||
1076 | #define SND_VIA82XX_PM_OPS &snd_via82xx_pm | ||
1077 | #else | ||
1078 | #define SND_VIA82XX_PM_OPS NULL | ||
1072 | #endif /* CONFIG_PM */ | 1079 | #endif /* CONFIG_PM */ |
1073 | 1080 | ||
1074 | static int snd_via82xx_free(struct via82xx_modem *chip) | 1081 | static int snd_via82xx_free(struct via82xx_modem *chip) |
@@ -1228,10 +1235,9 @@ static struct pci_driver via82xx_modem_driver = { | |||
1228 | .id_table = snd_via82xx_modem_ids, | 1235 | .id_table = snd_via82xx_modem_ids, |
1229 | .probe = snd_via82xx_probe, | 1236 | .probe = snd_via82xx_probe, |
1230 | .remove = __devexit_p(snd_via82xx_remove), | 1237 | .remove = __devexit_p(snd_via82xx_remove), |
1231 | #ifdef CONFIG_PM | 1238 | .driver = { |
1232 | .suspend = snd_via82xx_suspend, | 1239 | .pm = SND_VIA82XX_PM_OPS, |
1233 | .resume = snd_via82xx_resume, | 1240 | }, |
1234 | #endif | ||
1235 | }; | 1241 | }; |
1236 | 1242 | ||
1237 | module_pci_driver(via82xx_modem_driver); | 1243 | module_pci_driver(via82xx_modem_driver); |
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index 1ea1f656a5dc..b89e7a86e9d8 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c | |||
@@ -258,22 +258,24 @@ static void __devexit snd_vx222_remove(struct pci_dev *pci) | |||
258 | } | 258 | } |
259 | 259 | ||
260 | #ifdef CONFIG_PM | 260 | #ifdef CONFIG_PM |
261 | static int snd_vx222_suspend(struct pci_dev *pci, pm_message_t state) | 261 | static int snd_vx222_suspend(struct device *dev) |
262 | { | 262 | { |
263 | struct snd_card *card = pci_get_drvdata(pci); | 263 | struct pci_dev *pci = to_pci_dev(dev); |
264 | struct snd_card *card = dev_get_drvdata(dev); | ||
264 | struct snd_vx222 *vx = card->private_data; | 265 | struct snd_vx222 *vx = card->private_data; |
265 | int err; | 266 | int err; |
266 | 267 | ||
267 | err = snd_vx_suspend(&vx->core, state); | 268 | err = snd_vx_suspend(&vx->core); |
268 | pci_disable_device(pci); | 269 | pci_disable_device(pci); |
269 | pci_save_state(pci); | 270 | pci_save_state(pci); |
270 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 271 | pci_set_power_state(pci, PCI_D3hot); |
271 | return err; | 272 | return err; |
272 | } | 273 | } |
273 | 274 | ||
274 | static int snd_vx222_resume(struct pci_dev *pci) | 275 | static int snd_vx222_resume(struct device *dev) |
275 | { | 276 | { |
276 | struct snd_card *card = pci_get_drvdata(pci); | 277 | struct pci_dev *pci = to_pci_dev(dev); |
278 | struct snd_card *card = dev_get_drvdata(dev); | ||
277 | struct snd_vx222 *vx = card->private_data; | 279 | struct snd_vx222 *vx = card->private_data; |
278 | 280 | ||
279 | pci_set_power_state(pci, PCI_D0); | 281 | pci_set_power_state(pci, PCI_D0); |
@@ -287,6 +289,11 @@ static int snd_vx222_resume(struct pci_dev *pci) | |||
287 | pci_set_master(pci); | 289 | pci_set_master(pci); |
288 | return snd_vx_resume(&vx->core); | 290 | return snd_vx_resume(&vx->core); |
289 | } | 291 | } |
292 | |||
293 | static SIMPLE_DEV_PM_OPS(snd_vx222_pm, snd_vx222_suspend, snd_vx222_resume); | ||
294 | #define SND_VX222_PM_OPS &snd_vx222_pm | ||
295 | #else | ||
296 | #define SND_VX222_PM_OPS NULL | ||
290 | #endif | 297 | #endif |
291 | 298 | ||
292 | static struct pci_driver vx222_driver = { | 299 | static struct pci_driver vx222_driver = { |
@@ -294,10 +301,9 @@ static struct pci_driver vx222_driver = { | |||
294 | .id_table = snd_vx222_ids, | 301 | .id_table = snd_vx222_ids, |
295 | .probe = snd_vx222_probe, | 302 | .probe = snd_vx222_probe, |
296 | .remove = __devexit_p(snd_vx222_remove), | 303 | .remove = __devexit_p(snd_vx222_remove), |
297 | #ifdef CONFIG_PM | 304 | .driver = { |
298 | .suspend = snd_vx222_suspend, | 305 | .pm = SND_VX222_PM_OPS, |
299 | .resume = snd_vx222_resume, | 306 | }, |
300 | #endif | ||
301 | }; | 307 | }; |
302 | 308 | ||
303 | module_pci_driver(vx222_driver); | 309 | module_pci_driver(vx222_driver); |
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 9a1d01d653a7..4810356b97ba 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/time.h> | 24 | #include <linux/time.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <sound/core.h> | 26 | #include <sound/core.h> |
27 | #include <sound/ymfpci.h> | 27 | #include "ymfpci.h" |
28 | #include <sound/mpu401.h> | 28 | #include <sound/mpu401.h> |
29 | #include <sound/opl3.h> | 29 | #include <sound/opl3.h> |
30 | #include <sound/initval.h> | 30 | #include <sound/initval.h> |
@@ -356,8 +356,9 @@ static struct pci_driver ymfpci_driver = { | |||
356 | .probe = snd_card_ymfpci_probe, | 356 | .probe = snd_card_ymfpci_probe, |
357 | .remove = __devexit_p(snd_card_ymfpci_remove), | 357 | .remove = __devexit_p(snd_card_ymfpci_remove), |
358 | #ifdef CONFIG_PM | 358 | #ifdef CONFIG_PM |
359 | .suspend = snd_ymfpci_suspend, | 359 | .driver = { |
360 | .resume = snd_ymfpci_resume, | 360 | .pm = &snd_ymfpci_pm, |
361 | }, | ||
361 | #endif | 362 | #endif |
362 | }; | 363 | }; |
363 | 364 | ||
diff --git a/sound/pci/ymfpci/ymfpci.h b/sound/pci/ymfpci/ymfpci.h new file mode 100644 index 000000000000..bddc4052286b --- /dev/null +++ b/sound/pci/ymfpci/ymfpci.h | |||
@@ -0,0 +1,389 @@ | |||
1 | #ifndef __SOUND_YMFPCI_H | ||
2 | #define __SOUND_YMFPCI_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | ||
6 | * Definitions for Yahama YMF724/740/744/754 chips | ||
7 | * | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/rawmidi.h> | ||
27 | #include <sound/ac97_codec.h> | ||
28 | #include <sound/timer.h> | ||
29 | #include <linux/gameport.h> | ||
30 | |||
31 | /* | ||
32 | * Direct registers | ||
33 | */ | ||
34 | |||
35 | #define YMFREG(chip, reg) (chip->port + YDSXGR_##reg) | ||
36 | |||
37 | #define YDSXGR_INTFLAG 0x0004 | ||
38 | #define YDSXGR_ACTIVITY 0x0006 | ||
39 | #define YDSXGR_GLOBALCTRL 0x0008 | ||
40 | #define YDSXGR_ZVCTRL 0x000A | ||
41 | #define YDSXGR_TIMERCTRL 0x0010 | ||
42 | #define YDSXGR_TIMERCOUNT 0x0012 | ||
43 | #define YDSXGR_SPDIFOUTCTRL 0x0018 | ||
44 | #define YDSXGR_SPDIFOUTSTATUS 0x001C | ||
45 | #define YDSXGR_EEPROMCTRL 0x0020 | ||
46 | #define YDSXGR_SPDIFINCTRL 0x0034 | ||
47 | #define YDSXGR_SPDIFINSTATUS 0x0038 | ||
48 | #define YDSXGR_DSPPROGRAMDL 0x0048 | ||
49 | #define YDSXGR_DLCNTRL 0x004C | ||
50 | #define YDSXGR_GPIOININTFLAG 0x0050 | ||
51 | #define YDSXGR_GPIOININTENABLE 0x0052 | ||
52 | #define YDSXGR_GPIOINSTATUS 0x0054 | ||
53 | #define YDSXGR_GPIOOUTCTRL 0x0056 | ||
54 | #define YDSXGR_GPIOFUNCENABLE 0x0058 | ||
55 | #define YDSXGR_GPIOTYPECONFIG 0x005A | ||
56 | #define YDSXGR_AC97CMDDATA 0x0060 | ||
57 | #define YDSXGR_AC97CMDADR 0x0062 | ||
58 | #define YDSXGR_PRISTATUSDATA 0x0064 | ||
59 | #define YDSXGR_PRISTATUSADR 0x0066 | ||
60 | #define YDSXGR_SECSTATUSDATA 0x0068 | ||
61 | #define YDSXGR_SECSTATUSADR 0x006A | ||
62 | #define YDSXGR_SECCONFIG 0x0070 | ||
63 | #define YDSXGR_LEGACYOUTVOL 0x0080 | ||
64 | #define YDSXGR_LEGACYOUTVOLL 0x0080 | ||
65 | #define YDSXGR_LEGACYOUTVOLR 0x0082 | ||
66 | #define YDSXGR_NATIVEDACOUTVOL 0x0084 | ||
67 | #define YDSXGR_NATIVEDACOUTVOLL 0x0084 | ||
68 | #define YDSXGR_NATIVEDACOUTVOLR 0x0086 | ||
69 | #define YDSXGR_ZVOUTVOL 0x0088 | ||
70 | #define YDSXGR_ZVOUTVOLL 0x0088 | ||
71 | #define YDSXGR_ZVOUTVOLR 0x008A | ||
72 | #define YDSXGR_SECADCOUTVOL 0x008C | ||
73 | #define YDSXGR_SECADCOUTVOLL 0x008C | ||
74 | #define YDSXGR_SECADCOUTVOLR 0x008E | ||
75 | #define YDSXGR_PRIADCOUTVOL 0x0090 | ||
76 | #define YDSXGR_PRIADCOUTVOLL 0x0090 | ||
77 | #define YDSXGR_PRIADCOUTVOLR 0x0092 | ||
78 | #define YDSXGR_LEGACYLOOPVOL 0x0094 | ||
79 | #define YDSXGR_LEGACYLOOPVOLL 0x0094 | ||
80 | #define YDSXGR_LEGACYLOOPVOLR 0x0096 | ||
81 | #define YDSXGR_NATIVEDACLOOPVOL 0x0098 | ||
82 | #define YDSXGR_NATIVEDACLOOPVOLL 0x0098 | ||
83 | #define YDSXGR_NATIVEDACLOOPVOLR 0x009A | ||
84 | #define YDSXGR_ZVLOOPVOL 0x009C | ||
85 | #define YDSXGR_ZVLOOPVOLL 0x009E | ||
86 | #define YDSXGR_ZVLOOPVOLR 0x009E | ||
87 | #define YDSXGR_SECADCLOOPVOL 0x00A0 | ||
88 | #define YDSXGR_SECADCLOOPVOLL 0x00A0 | ||
89 | #define YDSXGR_SECADCLOOPVOLR 0x00A2 | ||
90 | #define YDSXGR_PRIADCLOOPVOL 0x00A4 | ||
91 | #define YDSXGR_PRIADCLOOPVOLL 0x00A4 | ||
92 | #define YDSXGR_PRIADCLOOPVOLR 0x00A6 | ||
93 | #define YDSXGR_NATIVEADCINVOL 0x00A8 | ||
94 | #define YDSXGR_NATIVEADCINVOLL 0x00A8 | ||
95 | #define YDSXGR_NATIVEADCINVOLR 0x00AA | ||
96 | #define YDSXGR_NATIVEDACINVOL 0x00AC | ||
97 | #define YDSXGR_NATIVEDACINVOLL 0x00AC | ||
98 | #define YDSXGR_NATIVEDACINVOLR 0x00AE | ||
99 | #define YDSXGR_BUF441OUTVOL 0x00B0 | ||
100 | #define YDSXGR_BUF441OUTVOLL 0x00B0 | ||
101 | #define YDSXGR_BUF441OUTVOLR 0x00B2 | ||
102 | #define YDSXGR_BUF441LOOPVOL 0x00B4 | ||
103 | #define YDSXGR_BUF441LOOPVOLL 0x00B4 | ||
104 | #define YDSXGR_BUF441LOOPVOLR 0x00B6 | ||
105 | #define YDSXGR_SPDIFOUTVOL 0x00B8 | ||
106 | #define YDSXGR_SPDIFOUTVOLL 0x00B8 | ||
107 | #define YDSXGR_SPDIFOUTVOLR 0x00BA | ||
108 | #define YDSXGR_SPDIFLOOPVOL 0x00BC | ||
109 | #define YDSXGR_SPDIFLOOPVOLL 0x00BC | ||
110 | #define YDSXGR_SPDIFLOOPVOLR 0x00BE | ||
111 | #define YDSXGR_ADCSLOTSR 0x00C0 | ||
112 | #define YDSXGR_RECSLOTSR 0x00C4 | ||
113 | #define YDSXGR_ADCFORMAT 0x00C8 | ||
114 | #define YDSXGR_RECFORMAT 0x00CC | ||
115 | #define YDSXGR_P44SLOTSR 0x00D0 | ||
116 | #define YDSXGR_STATUS 0x0100 | ||
117 | #define YDSXGR_CTRLSELECT 0x0104 | ||
118 | #define YDSXGR_MODE 0x0108 | ||
119 | #define YDSXGR_SAMPLECOUNT 0x010C | ||
120 | #define YDSXGR_NUMOFSAMPLES 0x0110 | ||
121 | #define YDSXGR_CONFIG 0x0114 | ||
122 | #define YDSXGR_PLAYCTRLSIZE 0x0140 | ||
123 | #define YDSXGR_RECCTRLSIZE 0x0144 | ||
124 | #define YDSXGR_EFFCTRLSIZE 0x0148 | ||
125 | #define YDSXGR_WORKSIZE 0x014C | ||
126 | #define YDSXGR_MAPOFREC 0x0150 | ||
127 | #define YDSXGR_MAPOFEFFECT 0x0154 | ||
128 | #define YDSXGR_PLAYCTRLBASE 0x0158 | ||
129 | #define YDSXGR_RECCTRLBASE 0x015C | ||
130 | #define YDSXGR_EFFCTRLBASE 0x0160 | ||
131 | #define YDSXGR_WORKBASE 0x0164 | ||
132 | #define YDSXGR_DSPINSTRAM 0x1000 | ||
133 | #define YDSXGR_CTRLINSTRAM 0x4000 | ||
134 | |||
135 | #define YDSXG_AC97READCMD 0x8000 | ||
136 | #define YDSXG_AC97WRITECMD 0x0000 | ||
137 | |||
138 | #define PCIR_DSXG_LEGACY 0x40 | ||
139 | #define PCIR_DSXG_ELEGACY 0x42 | ||
140 | #define PCIR_DSXG_CTRL 0x48 | ||
141 | #define PCIR_DSXG_PWRCTRL1 0x4a | ||
142 | #define PCIR_DSXG_PWRCTRL2 0x4e | ||
143 | #define PCIR_DSXG_FMBASE 0x60 | ||
144 | #define PCIR_DSXG_SBBASE 0x62 | ||
145 | #define PCIR_DSXG_MPU401BASE 0x64 | ||
146 | #define PCIR_DSXG_JOYBASE 0x66 | ||
147 | |||
148 | #define YDSXG_DSPLENGTH 0x0080 | ||
149 | #define YDSXG_CTRLLENGTH 0x3000 | ||
150 | |||
151 | #define YDSXG_DEFAULT_WORK_SIZE 0x0400 | ||
152 | |||
153 | #define YDSXG_PLAYBACK_VOICES 64 | ||
154 | #define YDSXG_CAPTURE_VOICES 2 | ||
155 | #define YDSXG_EFFECT_VOICES 5 | ||
156 | |||
157 | #define YMFPCI_LEGACY_SBEN (1 << 0) /* soundblaster enable */ | ||
158 | #define YMFPCI_LEGACY_FMEN (1 << 1) /* OPL3 enable */ | ||
159 | #define YMFPCI_LEGACY_JPEN (1 << 2) /* joystick enable */ | ||
160 | #define YMFPCI_LEGACY_MEN (1 << 3) /* MPU401 enable */ | ||
161 | #define YMFPCI_LEGACY_MIEN (1 << 4) /* MPU RX irq enable */ | ||
162 | #define YMFPCI_LEGACY_IOBITS (1 << 5) /* i/o bits range, 0 = 16bit, 1 =10bit */ | ||
163 | #define YMFPCI_LEGACY_SDMA (3 << 6) /* SB DMA select */ | ||
164 | #define YMFPCI_LEGACY_SBIRQ (7 << 8) /* SB IRQ select */ | ||
165 | #define YMFPCI_LEGACY_MPUIRQ (7 << 11) /* MPU IRQ select */ | ||
166 | #define YMFPCI_LEGACY_SIEN (1 << 14) /* serialized IRQ */ | ||
167 | #define YMFPCI_LEGACY_LAD (1 << 15) /* legacy audio disable */ | ||
168 | |||
169 | #define YMFPCI_LEGACY2_FMIO (3 << 0) /* OPL3 i/o address (724/740) */ | ||
170 | #define YMFPCI_LEGACY2_SBIO (3 << 2) /* SB i/o address (724/740) */ | ||
171 | #define YMFPCI_LEGACY2_MPUIO (3 << 4) /* MPU401 i/o address (724/740) */ | ||
172 | #define YMFPCI_LEGACY2_JSIO (3 << 6) /* joystick i/o address (724/740) */ | ||
173 | #define YMFPCI_LEGACY2_MAIM (1 << 8) /* MPU401 ack intr mask */ | ||
174 | #define YMFPCI_LEGACY2_SMOD (3 << 11) /* SB DMA mode */ | ||
175 | #define YMFPCI_LEGACY2_SBVER (3 << 13) /* SB version select */ | ||
176 | #define YMFPCI_LEGACY2_IMOD (1 << 15) /* legacy IRQ mode */ | ||
177 | /* SIEN:IMOD 0:0 = legacy irq, 0:1 = INTA, 1:0 = serialized IRQ */ | ||
178 | |||
179 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
180 | #define SUPPORT_JOYSTICK | ||
181 | #endif | ||
182 | |||
183 | /* | ||
184 | * | ||
185 | */ | ||
186 | |||
187 | struct snd_ymfpci_playback_bank { | ||
188 | u32 format; | ||
189 | u32 loop_default; | ||
190 | u32 base; /* 32-bit address */ | ||
191 | u32 loop_start; /* 32-bit offset */ | ||
192 | u32 loop_end; /* 32-bit offset */ | ||
193 | u32 loop_frac; /* 8-bit fraction - loop_start */ | ||
194 | u32 delta_end; /* pitch delta end */ | ||
195 | u32 lpfK_end; | ||
196 | u32 eg_gain_end; | ||
197 | u32 left_gain_end; | ||
198 | u32 right_gain_end; | ||
199 | u32 eff1_gain_end; | ||
200 | u32 eff2_gain_end; | ||
201 | u32 eff3_gain_end; | ||
202 | u32 lpfQ; | ||
203 | u32 status; | ||
204 | u32 num_of_frames; | ||
205 | u32 loop_count; | ||
206 | u32 start; | ||
207 | u32 start_frac; | ||
208 | u32 delta; | ||
209 | u32 lpfK; | ||
210 | u32 eg_gain; | ||
211 | u32 left_gain; | ||
212 | u32 right_gain; | ||
213 | u32 eff1_gain; | ||
214 | u32 eff2_gain; | ||
215 | u32 eff3_gain; | ||
216 | u32 lpfD1; | ||
217 | u32 lpfD2; | ||
218 | }; | ||
219 | |||
220 | struct snd_ymfpci_capture_bank { | ||
221 | u32 base; /* 32-bit address */ | ||
222 | u32 loop_end; /* 32-bit offset */ | ||
223 | u32 start; /* 32-bit offset */ | ||
224 | u32 num_of_loops; /* counter */ | ||
225 | }; | ||
226 | |||
227 | struct snd_ymfpci_effect_bank { | ||
228 | u32 base; /* 32-bit address */ | ||
229 | u32 loop_end; /* 32-bit offset */ | ||
230 | u32 start; /* 32-bit offset */ | ||
231 | u32 temp; | ||
232 | }; | ||
233 | |||
234 | struct snd_ymfpci_pcm; | ||
235 | struct snd_ymfpci; | ||
236 | |||
237 | enum snd_ymfpci_voice_type { | ||
238 | YMFPCI_PCM, | ||
239 | YMFPCI_SYNTH, | ||
240 | YMFPCI_MIDI | ||
241 | }; | ||
242 | |||
243 | struct snd_ymfpci_voice { | ||
244 | struct snd_ymfpci *chip; | ||
245 | int number; | ||
246 | unsigned int use: 1, | ||
247 | pcm: 1, | ||
248 | synth: 1, | ||
249 | midi: 1; | ||
250 | struct snd_ymfpci_playback_bank *bank; | ||
251 | dma_addr_t bank_addr; | ||
252 | void (*interrupt)(struct snd_ymfpci *chip, struct snd_ymfpci_voice *voice); | ||
253 | struct snd_ymfpci_pcm *ypcm; | ||
254 | }; | ||
255 | |||
256 | enum snd_ymfpci_pcm_type { | ||
257 | PLAYBACK_VOICE, | ||
258 | CAPTURE_REC, | ||
259 | CAPTURE_AC97, | ||
260 | EFFECT_DRY_LEFT, | ||
261 | EFFECT_DRY_RIGHT, | ||
262 | EFFECT_EFF1, | ||
263 | EFFECT_EFF2, | ||
264 | EFFECT_EFF3 | ||
265 | }; | ||
266 | |||
267 | struct snd_ymfpci_pcm { | ||
268 | struct snd_ymfpci *chip; | ||
269 | enum snd_ymfpci_pcm_type type; | ||
270 | struct snd_pcm_substream *substream; | ||
271 | struct snd_ymfpci_voice *voices[2]; /* playback only */ | ||
272 | unsigned int running: 1, | ||
273 | use_441_slot: 1, | ||
274 | output_front: 1, | ||
275 | output_rear: 1, | ||
276 | swap_rear: 1; | ||
277 | unsigned int update_pcm_vol; | ||
278 | u32 period_size; /* cached from runtime->period_size */ | ||
279 | u32 buffer_size; /* cached from runtime->buffer_size */ | ||
280 | u32 period_pos; | ||
281 | u32 last_pos; | ||
282 | u32 capture_bank_number; | ||
283 | u32 shift; | ||
284 | }; | ||
285 | |||
286 | struct snd_ymfpci { | ||
287 | int irq; | ||
288 | |||
289 | unsigned int device_id; /* PCI device ID */ | ||
290 | unsigned char rev; /* PCI revision */ | ||
291 | unsigned long reg_area_phys; | ||
292 | void __iomem *reg_area_virt; | ||
293 | struct resource *res_reg_area; | ||
294 | struct resource *fm_res; | ||
295 | struct resource *mpu_res; | ||
296 | |||
297 | unsigned short old_legacy_ctrl; | ||
298 | #ifdef SUPPORT_JOYSTICK | ||
299 | struct gameport *gameport; | ||
300 | #endif | ||
301 | |||
302 | struct snd_dma_buffer work_ptr; | ||
303 | |||
304 | unsigned int bank_size_playback; | ||
305 | unsigned int bank_size_capture; | ||
306 | unsigned int bank_size_effect; | ||
307 | unsigned int work_size; | ||
308 | |||
309 | void *bank_base_playback; | ||
310 | void *bank_base_capture; | ||
311 | void *bank_base_effect; | ||
312 | void *work_base; | ||
313 | dma_addr_t bank_base_playback_addr; | ||
314 | dma_addr_t bank_base_capture_addr; | ||
315 | dma_addr_t bank_base_effect_addr; | ||
316 | dma_addr_t work_base_addr; | ||
317 | struct snd_dma_buffer ac3_tmp_base; | ||
318 | |||
319 | u32 *ctrl_playback; | ||
320 | struct snd_ymfpci_playback_bank *bank_playback[YDSXG_PLAYBACK_VOICES][2]; | ||
321 | struct snd_ymfpci_capture_bank *bank_capture[YDSXG_CAPTURE_VOICES][2]; | ||
322 | struct snd_ymfpci_effect_bank *bank_effect[YDSXG_EFFECT_VOICES][2]; | ||
323 | |||
324 | int start_count; | ||
325 | |||
326 | u32 active_bank; | ||
327 | struct snd_ymfpci_voice voices[64]; | ||
328 | int src441_used; | ||
329 | |||
330 | struct snd_ac97_bus *ac97_bus; | ||
331 | struct snd_ac97 *ac97; | ||
332 | struct snd_rawmidi *rawmidi; | ||
333 | struct snd_timer *timer; | ||
334 | unsigned int timer_ticks; | ||
335 | |||
336 | struct pci_dev *pci; | ||
337 | struct snd_card *card; | ||
338 | struct snd_pcm *pcm; | ||
339 | struct snd_pcm *pcm2; | ||
340 | struct snd_pcm *pcm_spdif; | ||
341 | struct snd_pcm *pcm_4ch; | ||
342 | struct snd_pcm_substream *capture_substream[YDSXG_CAPTURE_VOICES]; | ||
343 | struct snd_pcm_substream *effect_substream[YDSXG_EFFECT_VOICES]; | ||
344 | struct snd_kcontrol *ctl_vol_recsrc; | ||
345 | struct snd_kcontrol *ctl_vol_adcrec; | ||
346 | struct snd_kcontrol *ctl_vol_spdifrec; | ||
347 | unsigned short spdif_bits, spdif_pcm_bits; | ||
348 | struct snd_kcontrol *spdif_pcm_ctl; | ||
349 | int mode_dup4ch; | ||
350 | int rear_opened; | ||
351 | int spdif_opened; | ||
352 | struct snd_ymfpci_pcm_mixer { | ||
353 | u16 left; | ||
354 | u16 right; | ||
355 | struct snd_kcontrol *ctl; | ||
356 | } pcm_mixer[32]; | ||
357 | |||
358 | spinlock_t reg_lock; | ||
359 | spinlock_t voice_lock; | ||
360 | wait_queue_head_t interrupt_sleep; | ||
361 | atomic_t interrupt_sleep_count; | ||
362 | struct snd_info_entry *proc_entry; | ||
363 | const struct firmware *dsp_microcode; | ||
364 | const struct firmware *controller_microcode; | ||
365 | |||
366 | #ifdef CONFIG_PM | ||
367 | u32 *saved_regs; | ||
368 | u32 saved_ydsxgr_mode; | ||
369 | u16 saved_dsxg_legacy; | ||
370 | u16 saved_dsxg_elegacy; | ||
371 | #endif | ||
372 | }; | ||
373 | |||
374 | int snd_ymfpci_create(struct snd_card *card, | ||
375 | struct pci_dev *pci, | ||
376 | unsigned short old_legacy_ctrl, | ||
377 | struct snd_ymfpci ** rcodec); | ||
378 | void snd_ymfpci_free_gameport(struct snd_ymfpci *chip); | ||
379 | |||
380 | extern const struct dev_pm_ops snd_ymfpci_pm; | ||
381 | |||
382 | int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); | ||
383 | int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); | ||
384 | int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); | ||
385 | int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm); | ||
386 | int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch); | ||
387 | int snd_ymfpci_timer(struct snd_ymfpci *chip, int device); | ||
388 | |||
389 | #endif /* __SOUND_YMFPCI_H */ | ||
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index a8159b81e9c4..62b23635b754 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <sound/control.h> | 33 | #include <sound/control.h> |
34 | #include <sound/info.h> | 34 | #include <sound/info.h> |
35 | #include <sound/tlv.h> | 35 | #include <sound/tlv.h> |
36 | #include <sound/ymfpci.h> | 36 | #include "ymfpci.h" |
37 | #include <sound/asoundef.h> | 37 | #include <sound/asoundef.h> |
38 | #include <sound/mpu401.h> | 38 | #include <sound/mpu401.h> |
39 | 39 | ||
@@ -2302,9 +2302,10 @@ static int saved_regs_index[] = { | |||
2302 | }; | 2302 | }; |
2303 | #define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index) | 2303 | #define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index) |
2304 | 2304 | ||
2305 | int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state) | 2305 | static int snd_ymfpci_suspend(struct device *dev) |
2306 | { | 2306 | { |
2307 | struct snd_card *card = pci_get_drvdata(pci); | 2307 | struct pci_dev *pci = to_pci_dev(dev); |
2308 | struct snd_card *card = dev_get_drvdata(dev); | ||
2308 | struct snd_ymfpci *chip = card->private_data; | 2309 | struct snd_ymfpci *chip = card->private_data; |
2309 | unsigned int i; | 2310 | unsigned int i; |
2310 | 2311 | ||
@@ -2326,13 +2327,14 @@ int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state) | |||
2326 | snd_ymfpci_disable_dsp(chip); | 2327 | snd_ymfpci_disable_dsp(chip); |
2327 | pci_disable_device(pci); | 2328 | pci_disable_device(pci); |
2328 | pci_save_state(pci); | 2329 | pci_save_state(pci); |
2329 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 2330 | pci_set_power_state(pci, PCI_D3hot); |
2330 | return 0; | 2331 | return 0; |
2331 | } | 2332 | } |
2332 | 2333 | ||
2333 | int snd_ymfpci_resume(struct pci_dev *pci) | 2334 | static int snd_ymfpci_resume(struct device *dev) |
2334 | { | 2335 | { |
2335 | struct snd_card *card = pci_get_drvdata(pci); | 2336 | struct pci_dev *pci = to_pci_dev(dev); |
2337 | struct snd_card *card = dev_get_drvdata(dev); | ||
2336 | struct snd_ymfpci *chip = card->private_data; | 2338 | struct snd_ymfpci *chip = card->private_data; |
2337 | unsigned int i; | 2339 | unsigned int i; |
2338 | 2340 | ||
@@ -2370,6 +2372,8 @@ int snd_ymfpci_resume(struct pci_dev *pci) | |||
2370 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2372 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
2371 | return 0; | 2373 | return 0; |
2372 | } | 2374 | } |
2375 | |||
2376 | SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume); | ||
2373 | #endif /* CONFIG_PM */ | 2377 | #endif /* CONFIG_PM */ |
2374 | 2378 | ||
2375 | int __devinit snd_ymfpci_create(struct snd_card *card, | 2379 | int __devinit snd_ymfpci_create(struct snd_card *card, |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 830839a874b6..f9b5229b2723 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c | |||
@@ -251,7 +251,7 @@ static int pdacf_suspend(struct pcmcia_device *link) | |||
251 | snd_printdd(KERN_DEBUG "SUSPEND\n"); | 251 | snd_printdd(KERN_DEBUG "SUSPEND\n"); |
252 | if (chip) { | 252 | if (chip) { |
253 | snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n"); | 253 | snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n"); |
254 | snd_pdacf_suspend(chip, PMSG_SUSPEND); | 254 | snd_pdacf_suspend(chip); |
255 | } | 255 | } |
256 | 256 | ||
257 | return 0; | 257 | return 0; |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h index 6ce9ad700290..ea41e57d7179 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.h +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h | |||
@@ -131,7 +131,7 @@ struct snd_pdacf *snd_pdacf_create(struct snd_card *card); | |||
131 | int snd_pdacf_ak4117_create(struct snd_pdacf *pdacf); | 131 | int snd_pdacf_ak4117_create(struct snd_pdacf *pdacf); |
132 | void snd_pdacf_powerdown(struct snd_pdacf *chip); | 132 | void snd_pdacf_powerdown(struct snd_pdacf *chip); |
133 | #ifdef CONFIG_PM | 133 | #ifdef CONFIG_PM |
134 | int snd_pdacf_suspend(struct snd_pdacf *chip, pm_message_t state); | 134 | int snd_pdacf_suspend(struct snd_pdacf *chip); |
135 | int snd_pdacf_resume(struct snd_pdacf *chip); | 135 | int snd_pdacf_resume(struct snd_pdacf *chip); |
136 | #endif | 136 | #endif |
137 | int snd_pdacf_pcm_new(struct snd_pdacf *chip); | 137 | int snd_pdacf_pcm_new(struct snd_pdacf *chip); |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c index 9dce0bde5c05..ea0adfb984ad 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c | |||
@@ -262,7 +262,7 @@ void snd_pdacf_powerdown(struct snd_pdacf *chip) | |||
262 | 262 | ||
263 | #ifdef CONFIG_PM | 263 | #ifdef CONFIG_PM |
264 | 264 | ||
265 | int snd_pdacf_suspend(struct snd_pdacf *chip, pm_message_t state) | 265 | int snd_pdacf_suspend(struct snd_pdacf *chip) |
266 | { | 266 | { |
267 | u16 val; | 267 | u16 val; |
268 | 268 | ||
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 512f0b472375..8f9350475c7b 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c | |||
@@ -260,7 +260,7 @@ static int vxp_suspend(struct pcmcia_device *link) | |||
260 | snd_printdd(KERN_DEBUG "SUSPEND\n"); | 260 | snd_printdd(KERN_DEBUG "SUSPEND\n"); |
261 | if (chip) { | 261 | if (chip) { |
262 | snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n"); | 262 | snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n"); |
263 | snd_vx_suspend(chip, PMSG_SUSPEND); | 263 | snd_vx_suspend(chip); |
264 | } | 264 | } |
265 | 265 | ||
266 | return 0; | 266 | return 0; |
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index 5a4e263b5b0f..f5ceb6f282de 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c | |||
@@ -144,19 +144,24 @@ static int __devexit snd_pmac_remove(struct platform_device *devptr) | |||
144 | } | 144 | } |
145 | 145 | ||
146 | #ifdef CONFIG_PM | 146 | #ifdef CONFIG_PM |
147 | static int snd_pmac_driver_suspend(struct platform_device *devptr, pm_message_t state) | 147 | static int snd_pmac_driver_suspend(struct device *dev) |
148 | { | 148 | { |
149 | struct snd_card *card = platform_get_drvdata(devptr); | 149 | struct snd_card *card = dev_get_drvdata(dev); |
150 | snd_pmac_suspend(card->private_data); | 150 | snd_pmac_suspend(card->private_data); |
151 | return 0; | 151 | return 0; |
152 | } | 152 | } |
153 | 153 | ||
154 | static int snd_pmac_driver_resume(struct platform_device *devptr) | 154 | static int snd_pmac_driver_resume(struct device *dev) |
155 | { | 155 | { |
156 | struct snd_card *card = platform_get_drvdata(devptr); | 156 | struct snd_card *card = dev_get_drvdata(dev); |
157 | snd_pmac_resume(card->private_data); | 157 | snd_pmac_resume(card->private_data); |
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
160 | |||
161 | static SIMPLE_DEV_PM_OPS(snd_pmac_pm, snd_pmac_driver_suspend, snd_pmac_driver_resume); | ||
162 | #define SND_PMAC_PM_OPS &snd_pmac_pm | ||
163 | #else | ||
164 | #define SND_PMAC_PM_OPS NULL | ||
160 | #endif | 165 | #endif |
161 | 166 | ||
162 | #define SND_PMAC_DRIVER "snd_powermac" | 167 | #define SND_PMAC_DRIVER "snd_powermac" |
@@ -164,12 +169,10 @@ static int snd_pmac_driver_resume(struct platform_device *devptr) | |||
164 | static struct platform_driver snd_pmac_driver = { | 169 | static struct platform_driver snd_pmac_driver = { |
165 | .probe = snd_pmac_probe, | 170 | .probe = snd_pmac_probe, |
166 | .remove = __devexit_p(snd_pmac_remove), | 171 | .remove = __devexit_p(snd_pmac_remove), |
167 | #ifdef CONFIG_PM | ||
168 | .suspend = snd_pmac_driver_suspend, | ||
169 | .resume = snd_pmac_driver_resume, | ||
170 | #endif | ||
171 | .driver = { | 172 | .driver = { |
172 | .name = SND_PMAC_DRIVER | 173 | .name = SND_PMAC_DRIVER, |
174 | .owner = THIS_MODULE, | ||
175 | .pm = SND_PMAC_PM_OPS, | ||
173 | }, | 176 | }, |
174 | }; | 177 | }; |
175 | 178 | ||
diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 391a38ca58bc..d48b523207eb 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c | |||
@@ -654,7 +654,9 @@ static struct platform_driver snd_aica_driver = { | |||
654 | .probe = snd_aica_probe, | 654 | .probe = snd_aica_probe, |
655 | .remove = __devexit_p(snd_aica_remove), | 655 | .remove = __devexit_p(snd_aica_remove), |
656 | .driver = { | 656 | .driver = { |
657 | .name = SND_AICA_DRIVER}, | 657 | .name = SND_AICA_DRIVER, |
658 | .owner = THIS_MODULE, | ||
659 | }, | ||
658 | }; | 660 | }; |
659 | 661 | ||
660 | static int __init aica_init(void) | 662 | static int __init aica_init(void) |
diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c index f8b01c77b298..0a3394751ed2 100644 --- a/sound/sh/sh_dac_audio.c +++ b/sound/sh/sh_dac_audio.c | |||
@@ -438,6 +438,7 @@ static struct platform_driver sh_dac_driver = { | |||
438 | .remove = snd_sh_dac_remove, | 438 | .remove = snd_sh_dac_remove, |
439 | .driver = { | 439 | .driver = { |
440 | .name = "dac_audio", | 440 | .name = "dac_audio", |
441 | .owner = THIS_MODULE, | ||
441 | }, | 442 | }, |
442 | }; | 443 | }; |
443 | 444 | ||
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 40b2ad1bb1cd..c5de0a84566f 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -33,6 +33,7 @@ source "sound/soc/atmel/Kconfig" | |||
33 | source "sound/soc/au1x/Kconfig" | 33 | source "sound/soc/au1x/Kconfig" |
34 | source "sound/soc/blackfin/Kconfig" | 34 | source "sound/soc/blackfin/Kconfig" |
35 | source "sound/soc/davinci/Kconfig" | 35 | source "sound/soc/davinci/Kconfig" |
36 | source "sound/soc/dwc/Kconfig" | ||
36 | source "sound/soc/ep93xx/Kconfig" | 37 | source "sound/soc/ep93xx/Kconfig" |
37 | source "sound/soc/fsl/Kconfig" | 38 | source "sound/soc/fsl/Kconfig" |
38 | source "sound/soc/jz4740/Kconfig" | 39 | source "sound/soc/jz4740/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 70990f4017f4..00a555a743b6 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -11,6 +11,7 @@ obj-$(CONFIG_SND_SOC) += atmel/ | |||
11 | obj-$(CONFIG_SND_SOC) += au1x/ | 11 | obj-$(CONFIG_SND_SOC) += au1x/ |
12 | obj-$(CONFIG_SND_SOC) += blackfin/ | 12 | obj-$(CONFIG_SND_SOC) += blackfin/ |
13 | obj-$(CONFIG_SND_SOC) += davinci/ | 13 | obj-$(CONFIG_SND_SOC) += davinci/ |
14 | obj-$(CONFIG_SND_SOC) += dwc/ | ||
14 | obj-$(CONFIG_SND_SOC) += ep93xx/ | 15 | obj-$(CONFIG_SND_SOC) += ep93xx/ |
15 | obj-$(CONFIG_SND_SOC) += fsl/ | 16 | obj-$(CONFIG_SND_SOC) += fsl/ |
16 | obj-$(CONFIG_SND_SOC) += jz4740/ | 17 | obj-$(CONFIG_SND_SOC) += jz4740/ |
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 9f6bc55fc399..16b88f5c26e2 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig | |||
@@ -1,7 +1,8 @@ | |||
1 | config SND_BF5XX_I2S | 1 | config SND_BF5XX_I2S |
2 | tristate "SoC I2S Audio for the ADI BF5xx chip" | 2 | tristate "SoC I2S Audio for the ADI Blackfin chip" |
3 | depends on BLACKFIN | 3 | depends on BLACKFIN |
4 | select SND_BF5XX_SOC_SPORT | 4 | select SND_BF5XX_SOC_SPORT if !BF60x |
5 | select SND_BF6XX_SOC_SPORT if BF60x | ||
5 | help | 6 | help |
6 | Say Y or M if you want to add support for codecs attached to | 7 | Say Y or M if you want to add support for codecs attached to |
7 | the Blackfin SPORT (synchronous serial ports) interface in I2S | 8 | the Blackfin SPORT (synchronous serial ports) interface in I2S |
@@ -9,12 +10,14 @@ config SND_BF5XX_I2S | |||
9 | You will also need to select the audio interfaces to support below. | 10 | You will also need to select the audio interfaces to support below. |
10 | 11 | ||
11 | config SND_BF5XX_SOC_SSM2602 | 12 | config SND_BF5XX_SOC_SSM2602 |
12 | tristate "SoC SSM2602 Audio support for BF52x ezkit" | 13 | tristate "SoC SSM2602 Audio Codec Add-On Card support" |
13 | depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) | 14 | depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) |
14 | select SND_BF5XX_SOC_I2S | 15 | select SND_BF5XX_SOC_I2S if !BF60x |
16 | select SND_BF6XX_SOC_I2S if BF60x | ||
15 | select SND_SOC_SSM2602 | 17 | select SND_SOC_SSM2602 |
16 | help | 18 | help |
17 | Say Y if you want to add support for SoC audio on BF527-EZKIT. | 19 | Say Y if you want to add support for the Analog Devices |
20 | SSM2602 Audio Codec Add-On Card. | ||
18 | 21 | ||
19 | config SND_SOC_BFIN_EVAL_ADAU1701 | 22 | config SND_SOC_BFIN_EVAL_ADAU1701 |
20 | tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards" | 23 | tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards" |
@@ -162,9 +165,15 @@ config SND_BF5XX_SOC_AD1980 | |||
162 | config SND_BF5XX_SOC_SPORT | 165 | config SND_BF5XX_SOC_SPORT |
163 | tristate | 166 | tristate |
164 | 167 | ||
168 | config SND_BF6XX_SOC_SPORT | ||
169 | tristate | ||
170 | |||
165 | config SND_BF5XX_SOC_I2S | 171 | config SND_BF5XX_SOC_I2S |
166 | tristate | 172 | tristate |
167 | 173 | ||
174 | config SND_BF6XX_SOC_I2S | ||
175 | tristate | ||
176 | |||
168 | config SND_BF5XX_SOC_TDM | 177 | config SND_BF5XX_SOC_TDM |
169 | tristate | 178 | tristate |
170 | 179 | ||
@@ -173,7 +182,7 @@ config SND_BF5XX_SOC_AC97 | |||
173 | 182 | ||
174 | config SND_BF5XX_SPORT_NUM | 183 | config SND_BF5XX_SPORT_NUM |
175 | int "Set a SPORT for Sound chip" | 184 | int "Set a SPORT for Sound chip" |
176 | depends on (SND_BF5XX_I2S || SND_BF5XX_AC97 || SND_BF5XX_TDM) | 185 | depends on (SND_BF5XX_SOC_SPORT || SND_BF6XX_SOC_SPORT) |
177 | range 0 3 if BF54x | 186 | range 0 3 if BF54x |
178 | range 0 1 if !BF54x | 187 | range 0 1 if !BF54x |
179 | default 0 | 188 | default 0 |
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile index 1bf86ccaa8de..6fea1f4cbee2 100644 --- a/sound/soc/blackfin/Makefile +++ b/sound/soc/blackfin/Makefile | |||
@@ -3,16 +3,20 @@ snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o | |||
3 | snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o | 3 | snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o |
4 | snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o | 4 | snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o |
5 | snd-soc-bf5xx-sport-objs := bf5xx-sport.o | 5 | snd-soc-bf5xx-sport-objs := bf5xx-sport.o |
6 | snd-soc-bf6xx-sport-objs := bf6xx-sport.o | ||
6 | snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o | 7 | snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o |
7 | snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o | 8 | snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o |
9 | snd-soc-bf6xx-i2s-objs := bf6xx-i2s.o | ||
8 | snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o | 10 | snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o |
9 | 11 | ||
10 | obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o | 12 | obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o |
11 | obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o | 13 | obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o |
12 | obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o | 14 | obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o |
13 | obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o | 15 | obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o |
16 | obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o | ||
14 | obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o | 17 | obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o |
15 | obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o | 18 | obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o |
19 | obj-$(CONFIG_SND_BF6XX_SOC_I2S) += snd-soc-bf6xx-i2s.o | ||
16 | obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o | 20 | obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o |
17 | 21 | ||
18 | # Blackfin Machine Support | 22 | # Blackfin Machine Support |
diff --git a/sound/soc/blackfin/bf6xx-i2s.c b/sound/soc/blackfin/bf6xx-i2s.c new file mode 100644 index 000000000000..c3c2466d3a42 --- /dev/null +++ b/sound/soc/blackfin/bf6xx-i2s.c | |||
@@ -0,0 +1,234 @@ | |||
1 | /* | ||
2 | * bf6xx-i2s.c - Analog Devices BF6XX i2s interface driver | ||
3 | * | ||
4 | * Copyright (c) 2012 Analog Devices 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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/device.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/soc-dai.h> | ||
28 | |||
29 | #include "bf6xx-sport.h" | ||
30 | |||
31 | struct sport_params param; | ||
32 | |||
33 | static int bfin_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | ||
34 | unsigned int fmt) | ||
35 | { | ||
36 | struct sport_device *sport = snd_soc_dai_get_drvdata(cpu_dai); | ||
37 | struct device *dev = &sport->pdev->dev; | ||
38 | int ret = 0; | ||
39 | |||
40 | param.spctl &= ~(SPORT_CTL_OPMODE | SPORT_CTL_CKRE | SPORT_CTL_FSR | ||
41 | | SPORT_CTL_LFS | SPORT_CTL_LAFS); | ||
42 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
43 | case SND_SOC_DAIFMT_I2S: | ||
44 | param.spctl |= SPORT_CTL_OPMODE | SPORT_CTL_CKRE | ||
45 | | SPORT_CTL_LFS; | ||
46 | break; | ||
47 | case SND_SOC_DAIFMT_DSP_A: | ||
48 | param.spctl |= SPORT_CTL_FSR; | ||
49 | break; | ||
50 | case SND_SOC_DAIFMT_LEFT_J: | ||
51 | param.spctl |= SPORT_CTL_OPMODE | SPORT_CTL_LFS | ||
52 | | SPORT_CTL_LAFS; | ||
53 | break; | ||
54 | default: | ||
55 | dev_err(dev, "%s: Unknown DAI format type\n", __func__); | ||
56 | ret = -EINVAL; | ||
57 | break; | ||
58 | } | ||
59 | |||
60 | param.spctl &= ~(SPORT_CTL_ICLK | SPORT_CTL_IFS); | ||
61 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
62 | case SND_SOC_DAIFMT_CBM_CFM: | ||
63 | break; | ||
64 | case SND_SOC_DAIFMT_CBS_CFS: | ||
65 | case SND_SOC_DAIFMT_CBM_CFS: | ||
66 | case SND_SOC_DAIFMT_CBS_CFM: | ||
67 | ret = -EINVAL; | ||
68 | break; | ||
69 | default: | ||
70 | dev_err(dev, "%s: Unknown DAI master type\n", __func__); | ||
71 | ret = -EINVAL; | ||
72 | break; | ||
73 | } | ||
74 | |||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | static int bfin_i2s_hw_params(struct snd_pcm_substream *substream, | ||
79 | struct snd_pcm_hw_params *params, | ||
80 | struct snd_soc_dai *dai) | ||
81 | { | ||
82 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); | ||
83 | struct device *dev = &sport->pdev->dev; | ||
84 | int ret = 0; | ||
85 | |||
86 | param.spctl &= ~SPORT_CTL_SLEN; | ||
87 | switch (params_format(params)) { | ||
88 | case SNDRV_PCM_FORMAT_S8: | ||
89 | param.spctl |= 0x70; | ||
90 | sport->wdsize = 1; | ||
91 | case SNDRV_PCM_FORMAT_S16_LE: | ||
92 | param.spctl |= 0xf0; | ||
93 | sport->wdsize = 2; | ||
94 | break; | ||
95 | case SNDRV_PCM_FORMAT_S24_LE: | ||
96 | param.spctl |= 0x170; | ||
97 | sport->wdsize = 3; | ||
98 | break; | ||
99 | case SNDRV_PCM_FORMAT_S32_LE: | ||
100 | param.spctl |= 0x1f0; | ||
101 | sport->wdsize = 4; | ||
102 | break; | ||
103 | } | ||
104 | |||
105 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
106 | ret = sport_set_tx_params(sport, ¶m); | ||
107 | if (ret) { | ||
108 | dev_err(dev, "SPORT tx is busy!\n"); | ||
109 | return ret; | ||
110 | } | ||
111 | } else { | ||
112 | ret = sport_set_rx_params(sport, ¶m); | ||
113 | if (ret) { | ||
114 | dev_err(dev, "SPORT rx is busy!\n"); | ||
115 | return ret; | ||
116 | } | ||
117 | } | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | #ifdef CONFIG_PM | ||
122 | static int bfin_i2s_suspend(struct snd_soc_dai *dai) | ||
123 | { | ||
124 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); | ||
125 | |||
126 | if (dai->capture_active) | ||
127 | sport_rx_stop(sport); | ||
128 | if (dai->playback_active) | ||
129 | sport_tx_stop(sport); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static int bfin_i2s_resume(struct snd_soc_dai *dai) | ||
134 | { | ||
135 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); | ||
136 | struct device *dev = &sport->pdev->dev; | ||
137 | int ret; | ||
138 | |||
139 | ret = sport_set_tx_params(sport, ¶m); | ||
140 | if (ret) { | ||
141 | dev_err(dev, "SPORT tx is busy!\n"); | ||
142 | return ret; | ||
143 | } | ||
144 | ret = sport_set_rx_params(sport, ¶m); | ||
145 | if (ret) { | ||
146 | dev_err(dev, "SPORT rx is busy!\n"); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | #else | ||
154 | #define bfin_i2s_suspend NULL | ||
155 | #define bfin_i2s_resume NULL | ||
156 | #endif | ||
157 | |||
158 | #define BFIN_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | ||
159 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ | ||
160 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ | ||
161 | SNDRV_PCM_RATE_96000) | ||
162 | |||
163 | #define BFIN_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
164 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
165 | |||
166 | static struct snd_soc_dai_ops bfin_i2s_dai_ops = { | ||
167 | .hw_params = bfin_i2s_hw_params, | ||
168 | .set_fmt = bfin_i2s_set_dai_fmt, | ||
169 | }; | ||
170 | |||
171 | static struct snd_soc_dai_driver bfin_i2s_dai = { | ||
172 | .suspend = bfin_i2s_suspend, | ||
173 | .resume = bfin_i2s_resume, | ||
174 | .playback = { | ||
175 | .channels_min = 1, | ||
176 | .channels_max = 2, | ||
177 | .rates = BFIN_I2S_RATES, | ||
178 | .formats = BFIN_I2S_FORMATS, | ||
179 | }, | ||
180 | .capture = { | ||
181 | .channels_min = 1, | ||
182 | .channels_max = 2, | ||
183 | .rates = BFIN_I2S_RATES, | ||
184 | .formats = BFIN_I2S_FORMATS, | ||
185 | }, | ||
186 | .ops = &bfin_i2s_dai_ops, | ||
187 | }; | ||
188 | |||
189 | static int __devinit bfin_i2s_probe(struct platform_device *pdev) | ||
190 | { | ||
191 | struct sport_device *sport; | ||
192 | struct device *dev = &pdev->dev; | ||
193 | int ret; | ||
194 | |||
195 | sport = sport_create(pdev); | ||
196 | if (!sport) | ||
197 | return -ENODEV; | ||
198 | |||
199 | /* register with the ASoC layers */ | ||
200 | ret = snd_soc_register_dai(dev, &bfin_i2s_dai); | ||
201 | if (ret) { | ||
202 | dev_err(dev, "Failed to register DAI: %d\n", ret); | ||
203 | sport_delete(sport); | ||
204 | return ret; | ||
205 | } | ||
206 | platform_set_drvdata(pdev, sport); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static int __devexit bfin_i2s_remove(struct platform_device *pdev) | ||
212 | { | ||
213 | struct sport_device *sport = platform_get_drvdata(pdev); | ||
214 | |||
215 | snd_soc_unregister_dai(&pdev->dev); | ||
216 | sport_delete(sport); | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static struct platform_driver bfin_i2s_driver = { | ||
222 | .probe = bfin_i2s_probe, | ||
223 | .remove = __devexit_p(bfin_i2s_remove), | ||
224 | .driver = { | ||
225 | .name = "bfin-i2s", | ||
226 | .owner = THIS_MODULE, | ||
227 | }, | ||
228 | }; | ||
229 | |||
230 | module_platform_driver(bfin_i2s_driver); | ||
231 | |||
232 | MODULE_DESCRIPTION("Analog Devices BF6XX i2s interface driver"); | ||
233 | MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | ||
234 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/blackfin/bf6xx-sport.c b/sound/soc/blackfin/bf6xx-sport.c new file mode 100644 index 000000000000..318c5ba5360f --- /dev/null +++ b/sound/soc/blackfin/bf6xx-sport.c | |||
@@ -0,0 +1,422 @@ | |||
1 | /* | ||
2 | * bf6xx_sport.c Analog Devices BF6XX SPORT driver | ||
3 | * | ||
4 | * Copyright (c) 2012 Analog Devices 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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/device.h> | ||
21 | #include <linux/dma-mapping.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | #include <asm/blackfin.h> | ||
28 | #include <asm/dma.h> | ||
29 | #include <asm/portmux.h> | ||
30 | |||
31 | #include "bf6xx-sport.h" | ||
32 | |||
33 | int sport_set_tx_params(struct sport_device *sport, | ||
34 | struct sport_params *params) | ||
35 | { | ||
36 | if (sport->tx_regs->spctl & SPORT_CTL_SPENPRI) | ||
37 | return -EBUSY; | ||
38 | sport->tx_regs->spctl = params->spctl | SPORT_CTL_SPTRAN; | ||
39 | sport->tx_regs->div = params->div; | ||
40 | SSYNC(); | ||
41 | return 0; | ||
42 | } | ||
43 | EXPORT_SYMBOL(sport_set_tx_params); | ||
44 | |||
45 | int sport_set_rx_params(struct sport_device *sport, | ||
46 | struct sport_params *params) | ||
47 | { | ||
48 | if (sport->rx_regs->spctl & SPORT_CTL_SPENPRI) | ||
49 | return -EBUSY; | ||
50 | sport->rx_regs->spctl = params->spctl & ~SPORT_CTL_SPTRAN; | ||
51 | sport->rx_regs->div = params->div; | ||
52 | SSYNC(); | ||
53 | return 0; | ||
54 | } | ||
55 | EXPORT_SYMBOL(sport_set_rx_params); | ||
56 | |||
57 | static int compute_wdsize(size_t wdsize) | ||
58 | { | ||
59 | switch (wdsize) { | ||
60 | case 1: | ||
61 | return WDSIZE_8 | PSIZE_8; | ||
62 | case 2: | ||
63 | return WDSIZE_16 | PSIZE_16; | ||
64 | default: | ||
65 | return WDSIZE_32 | PSIZE_32; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | void sport_tx_start(struct sport_device *sport) | ||
70 | { | ||
71 | set_dma_next_desc_addr(sport->tx_dma_chan, sport->tx_desc); | ||
72 | set_dma_config(sport->tx_dma_chan, DMAFLOW_LIST | DI_EN | ||
73 | | compute_wdsize(sport->wdsize) | NDSIZE_6); | ||
74 | enable_dma(sport->tx_dma_chan); | ||
75 | sport->tx_regs->spctl |= SPORT_CTL_SPENPRI; | ||
76 | SSYNC(); | ||
77 | } | ||
78 | EXPORT_SYMBOL(sport_tx_start); | ||
79 | |||
80 | void sport_rx_start(struct sport_device *sport) | ||
81 | { | ||
82 | set_dma_next_desc_addr(sport->rx_dma_chan, sport->rx_desc); | ||
83 | set_dma_config(sport->rx_dma_chan, DMAFLOW_LIST | DI_EN | WNR | ||
84 | | compute_wdsize(sport->wdsize) | NDSIZE_6); | ||
85 | enable_dma(sport->rx_dma_chan); | ||
86 | sport->rx_regs->spctl |= SPORT_CTL_SPENPRI; | ||
87 | SSYNC(); | ||
88 | } | ||
89 | EXPORT_SYMBOL(sport_rx_start); | ||
90 | |||
91 | void sport_tx_stop(struct sport_device *sport) | ||
92 | { | ||
93 | sport->tx_regs->spctl &= ~SPORT_CTL_SPENPRI; | ||
94 | SSYNC(); | ||
95 | disable_dma(sport->tx_dma_chan); | ||
96 | } | ||
97 | EXPORT_SYMBOL(sport_tx_stop); | ||
98 | |||
99 | void sport_rx_stop(struct sport_device *sport) | ||
100 | { | ||
101 | sport->rx_regs->spctl &= ~SPORT_CTL_SPENPRI; | ||
102 | SSYNC(); | ||
103 | disable_dma(sport->rx_dma_chan); | ||
104 | } | ||
105 | EXPORT_SYMBOL(sport_rx_stop); | ||
106 | |||
107 | void sport_set_tx_callback(struct sport_device *sport, | ||
108 | void (*tx_callback)(void *), void *tx_data) | ||
109 | { | ||
110 | sport->tx_callback = tx_callback; | ||
111 | sport->tx_data = tx_data; | ||
112 | } | ||
113 | EXPORT_SYMBOL(sport_set_tx_callback); | ||
114 | |||
115 | void sport_set_rx_callback(struct sport_device *sport, | ||
116 | void (*rx_callback)(void *), void *rx_data) | ||
117 | { | ||
118 | sport->rx_callback = rx_callback; | ||
119 | sport->rx_data = rx_data; | ||
120 | } | ||
121 | EXPORT_SYMBOL(sport_set_rx_callback); | ||
122 | |||
123 | static void setup_desc(struct dmasg *desc, void *buf, int fragcount, | ||
124 | size_t fragsize, unsigned int cfg, | ||
125 | unsigned int count, size_t wdsize) | ||
126 | { | ||
127 | |||
128 | int i; | ||
129 | |||
130 | for (i = 0; i < fragcount; ++i) { | ||
131 | desc[i].next_desc_addr = &(desc[i + 1]); | ||
132 | desc[i].start_addr = (unsigned long)buf + i*fragsize; | ||
133 | desc[i].cfg = cfg; | ||
134 | desc[i].x_count = count; | ||
135 | desc[i].x_modify = wdsize; | ||
136 | desc[i].y_count = 0; | ||
137 | desc[i].y_modify = 0; | ||
138 | } | ||
139 | |||
140 | /* make circular */ | ||
141 | desc[fragcount-1].next_desc_addr = desc; | ||
142 | } | ||
143 | |||
144 | int sport_config_tx_dma(struct sport_device *sport, void *buf, | ||
145 | int fragcount, size_t fragsize) | ||
146 | { | ||
147 | unsigned int count; | ||
148 | unsigned int cfg; | ||
149 | dma_addr_t addr; | ||
150 | |||
151 | count = fragsize/sport->wdsize; | ||
152 | |||
153 | if (sport->tx_desc) | ||
154 | dma_free_coherent(NULL, sport->tx_desc_size, | ||
155 | sport->tx_desc, 0); | ||
156 | |||
157 | sport->tx_desc = dma_alloc_coherent(NULL, | ||
158 | fragcount * sizeof(struct dmasg), &addr, 0); | ||
159 | sport->tx_desc_size = fragcount * sizeof(struct dmasg); | ||
160 | if (!sport->tx_desc) | ||
161 | return -ENOMEM; | ||
162 | |||
163 | sport->tx_buf = buf; | ||
164 | sport->tx_fragsize = fragsize; | ||
165 | sport->tx_frags = fragcount; | ||
166 | cfg = DMAFLOW_LIST | DI_EN | compute_wdsize(sport->wdsize) | NDSIZE_6; | ||
167 | |||
168 | setup_desc(sport->tx_desc, buf, fragcount, fragsize, | ||
169 | cfg|DMAEN, count, sport->wdsize); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | EXPORT_SYMBOL(sport_config_tx_dma); | ||
174 | |||
175 | int sport_config_rx_dma(struct sport_device *sport, void *buf, | ||
176 | int fragcount, size_t fragsize) | ||
177 | { | ||
178 | unsigned int count; | ||
179 | unsigned int cfg; | ||
180 | dma_addr_t addr; | ||
181 | |||
182 | count = fragsize/sport->wdsize; | ||
183 | |||
184 | if (sport->rx_desc) | ||
185 | dma_free_coherent(NULL, sport->rx_desc_size, | ||
186 | sport->rx_desc, 0); | ||
187 | |||
188 | sport->rx_desc = dma_alloc_coherent(NULL, | ||
189 | fragcount * sizeof(struct dmasg), &addr, 0); | ||
190 | sport->rx_desc_size = fragcount * sizeof(struct dmasg); | ||
191 | if (!sport->rx_desc) | ||
192 | return -ENOMEM; | ||
193 | |||
194 | sport->rx_buf = buf; | ||
195 | sport->rx_fragsize = fragsize; | ||
196 | sport->rx_frags = fragcount; | ||
197 | cfg = DMAFLOW_LIST | DI_EN | compute_wdsize(sport->wdsize) | ||
198 | | WNR | NDSIZE_6; | ||
199 | |||
200 | setup_desc(sport->rx_desc, buf, fragcount, fragsize, | ||
201 | cfg|DMAEN, count, sport->wdsize); | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | EXPORT_SYMBOL(sport_config_rx_dma); | ||
206 | |||
207 | unsigned long sport_curr_offset_tx(struct sport_device *sport) | ||
208 | { | ||
209 | unsigned long curr = get_dma_curr_addr(sport->tx_dma_chan); | ||
210 | |||
211 | return (unsigned char *)curr - sport->tx_buf; | ||
212 | } | ||
213 | EXPORT_SYMBOL(sport_curr_offset_tx); | ||
214 | |||
215 | unsigned long sport_curr_offset_rx(struct sport_device *sport) | ||
216 | { | ||
217 | unsigned long curr = get_dma_curr_addr(sport->rx_dma_chan); | ||
218 | |||
219 | return (unsigned char *)curr - sport->rx_buf; | ||
220 | } | ||
221 | EXPORT_SYMBOL(sport_curr_offset_rx); | ||
222 | |||
223 | static irqreturn_t sport_tx_irq(int irq, void *dev_id) | ||
224 | { | ||
225 | struct sport_device *sport = dev_id; | ||
226 | static unsigned long status; | ||
227 | |||
228 | status = get_dma_curr_irqstat(sport->tx_dma_chan); | ||
229 | if (status & (DMA_DONE|DMA_ERR)) { | ||
230 | clear_dma_irqstat(sport->tx_dma_chan); | ||
231 | SSYNC(); | ||
232 | } | ||
233 | if (sport->tx_callback) | ||
234 | sport->tx_callback(sport->tx_data); | ||
235 | return IRQ_HANDLED; | ||
236 | } | ||
237 | |||
238 | static irqreturn_t sport_rx_irq(int irq, void *dev_id) | ||
239 | { | ||
240 | struct sport_device *sport = dev_id; | ||
241 | unsigned long status; | ||
242 | |||
243 | status = get_dma_curr_irqstat(sport->rx_dma_chan); | ||
244 | if (status & (DMA_DONE|DMA_ERR)) { | ||
245 | clear_dma_irqstat(sport->rx_dma_chan); | ||
246 | SSYNC(); | ||
247 | } | ||
248 | if (sport->rx_callback) | ||
249 | sport->rx_callback(sport->rx_data); | ||
250 | return IRQ_HANDLED; | ||
251 | } | ||
252 | |||
253 | static irqreturn_t sport_err_irq(int irq, void *dev_id) | ||
254 | { | ||
255 | struct sport_device *sport = dev_id; | ||
256 | struct device *dev = &sport->pdev->dev; | ||
257 | |||
258 | if (sport->tx_regs->spctl & SPORT_CTL_DERRPRI) | ||
259 | dev_err(dev, "sport error: TUVF\n"); | ||
260 | if (sport->rx_regs->spctl & SPORT_CTL_DERRPRI) | ||
261 | dev_err(dev, "sport error: ROVF\n"); | ||
262 | |||
263 | return IRQ_HANDLED; | ||
264 | } | ||
265 | |||
266 | static int sport_get_resource(struct sport_device *sport) | ||
267 | { | ||
268 | struct platform_device *pdev = sport->pdev; | ||
269 | struct device *dev = &pdev->dev; | ||
270 | struct bfin_snd_platform_data *pdata = dev->platform_data; | ||
271 | struct resource *res; | ||
272 | |||
273 | if (!pdata) { | ||
274 | dev_err(dev, "No platform data\n"); | ||
275 | return -ENODEV; | ||
276 | } | ||
277 | sport->pin_req = pdata->pin_req; | ||
278 | |||
279 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
280 | if (!res) { | ||
281 | dev_err(dev, "No tx MEM resource\n"); | ||
282 | return -ENODEV; | ||
283 | } | ||
284 | sport->tx_regs = (struct sport_register *)res->start; | ||
285 | |||
286 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
287 | if (!res) { | ||
288 | dev_err(dev, "No rx MEM resource\n"); | ||
289 | return -ENODEV; | ||
290 | } | ||
291 | sport->rx_regs = (struct sport_register *)res->start; | ||
292 | |||
293 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
294 | if (!res) { | ||
295 | dev_err(dev, "No tx DMA resource\n"); | ||
296 | return -ENODEV; | ||
297 | } | ||
298 | sport->tx_dma_chan = res->start; | ||
299 | |||
300 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
301 | if (!res) { | ||
302 | dev_err(dev, "No rx DMA resource\n"); | ||
303 | return -ENODEV; | ||
304 | } | ||
305 | sport->rx_dma_chan = res->start; | ||
306 | |||
307 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
308 | if (!res) { | ||
309 | dev_err(dev, "No tx error irq resource\n"); | ||
310 | return -ENODEV; | ||
311 | } | ||
312 | sport->tx_err_irq = res->start; | ||
313 | |||
314 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | ||
315 | if (!res) { | ||
316 | dev_err(dev, "No rx error irq resource\n"); | ||
317 | return -ENODEV; | ||
318 | } | ||
319 | sport->rx_err_irq = res->start; | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int sport_request_resource(struct sport_device *sport) | ||
325 | { | ||
326 | struct device *dev = &sport->pdev->dev; | ||
327 | int ret; | ||
328 | |||
329 | ret = peripheral_request_list(sport->pin_req, "soc-audio"); | ||
330 | if (ret) { | ||
331 | dev_err(dev, "Unable to request sport pin\n"); | ||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | ret = request_dma(sport->tx_dma_chan, "SPORT TX Data"); | ||
336 | if (ret) { | ||
337 | dev_err(dev, "Unable to allocate DMA channel for sport tx\n"); | ||
338 | goto err_tx_dma; | ||
339 | } | ||
340 | set_dma_callback(sport->tx_dma_chan, sport_tx_irq, sport); | ||
341 | |||
342 | ret = request_dma(sport->rx_dma_chan, "SPORT RX Data"); | ||
343 | if (ret) { | ||
344 | dev_err(dev, "Unable to allocate DMA channel for sport rx\n"); | ||
345 | goto err_rx_dma; | ||
346 | } | ||
347 | set_dma_callback(sport->rx_dma_chan, sport_rx_irq, sport); | ||
348 | |||
349 | ret = request_irq(sport->tx_err_irq, sport_err_irq, | ||
350 | 0, "SPORT TX ERROR", sport); | ||
351 | if (ret) { | ||
352 | dev_err(dev, "Unable to allocate tx error IRQ for sport\n"); | ||
353 | goto err_tx_irq; | ||
354 | } | ||
355 | |||
356 | ret = request_irq(sport->rx_err_irq, sport_err_irq, | ||
357 | 0, "SPORT RX ERROR", sport); | ||
358 | if (ret) { | ||
359 | dev_err(dev, "Unable to allocate rx error IRQ for sport\n"); | ||
360 | goto err_rx_irq; | ||
361 | } | ||
362 | |||
363 | return 0; | ||
364 | err_rx_irq: | ||
365 | free_irq(sport->tx_err_irq, sport); | ||
366 | err_tx_irq: | ||
367 | free_dma(sport->rx_dma_chan); | ||
368 | err_rx_dma: | ||
369 | free_dma(sport->tx_dma_chan); | ||
370 | err_tx_dma: | ||
371 | peripheral_free_list(sport->pin_req); | ||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | static void sport_free_resource(struct sport_device *sport) | ||
376 | { | ||
377 | free_irq(sport->rx_err_irq, sport); | ||
378 | free_irq(sport->tx_err_irq, sport); | ||
379 | free_dma(sport->rx_dma_chan); | ||
380 | free_dma(sport->tx_dma_chan); | ||
381 | peripheral_free_list(sport->pin_req); | ||
382 | } | ||
383 | |||
384 | struct sport_device *sport_create(struct platform_device *pdev) | ||
385 | { | ||
386 | struct device *dev = &pdev->dev; | ||
387 | struct sport_device *sport; | ||
388 | int ret; | ||
389 | |||
390 | sport = kzalloc(sizeof(*sport), GFP_KERNEL); | ||
391 | if (!sport) { | ||
392 | dev_err(dev, "Unable to allocate memory for sport device\n"); | ||
393 | return NULL; | ||
394 | } | ||
395 | sport->pdev = pdev; | ||
396 | |||
397 | ret = sport_get_resource(sport); | ||
398 | if (ret) { | ||
399 | kfree(sport); | ||
400 | return NULL; | ||
401 | } | ||
402 | |||
403 | ret = sport_request_resource(sport); | ||
404 | if (ret) { | ||
405 | kfree(sport); | ||
406 | return NULL; | ||
407 | } | ||
408 | |||
409 | dev_dbg(dev, "SPORT create success\n"); | ||
410 | return sport; | ||
411 | } | ||
412 | EXPORT_SYMBOL(sport_create); | ||
413 | |||
414 | void sport_delete(struct sport_device *sport) | ||
415 | { | ||
416 | sport_free_resource(sport); | ||
417 | } | ||
418 | EXPORT_SYMBOL(sport_delete); | ||
419 | |||
420 | MODULE_DESCRIPTION("Analog Devices BF6XX SPORT driver"); | ||
421 | MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | ||
422 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/blackfin/bf6xx-sport.h b/sound/soc/blackfin/bf6xx-sport.h new file mode 100644 index 000000000000..307d193cfcef --- /dev/null +++ b/sound/soc/blackfin/bf6xx-sport.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * bf6xx_sport - Analog Devices BF6XX SPORT driver | ||
3 | * | ||
4 | * Copyright (c) 2012 Analog Devices 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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef _BF6XX_SPORT_H_ | ||
21 | #define _BF6XX_SPORT_H_ | ||
22 | |||
23 | #include <linux/platform_device.h> | ||
24 | #include <asm/bfin_sport3.h> | ||
25 | |||
26 | struct sport_device { | ||
27 | struct platform_device *pdev; | ||
28 | const unsigned short *pin_req; | ||
29 | struct sport_register *tx_regs; | ||
30 | struct sport_register *rx_regs; | ||
31 | int tx_dma_chan; | ||
32 | int rx_dma_chan; | ||
33 | int tx_err_irq; | ||
34 | int rx_err_irq; | ||
35 | |||
36 | void (*tx_callback)(void *data); | ||
37 | void *tx_data; | ||
38 | void (*rx_callback)(void *data); | ||
39 | void *rx_data; | ||
40 | |||
41 | struct dmasg *tx_desc; | ||
42 | struct dmasg *rx_desc; | ||
43 | unsigned int tx_desc_size; | ||
44 | unsigned int rx_desc_size; | ||
45 | unsigned char *tx_buf; | ||
46 | unsigned char *rx_buf; | ||
47 | unsigned int tx_fragsize; | ||
48 | unsigned int rx_fragsize; | ||
49 | unsigned int tx_frags; | ||
50 | unsigned int rx_frags; | ||
51 | unsigned int wdsize; | ||
52 | }; | ||
53 | |||
54 | struct sport_params { | ||
55 | u32 spctl; | ||
56 | u32 div; | ||
57 | }; | ||
58 | |||
59 | struct sport_device *sport_create(struct platform_device *pdev); | ||
60 | void sport_delete(struct sport_device *sport); | ||
61 | int sport_set_tx_params(struct sport_device *sport, | ||
62 | struct sport_params *params); | ||
63 | int sport_set_rx_params(struct sport_device *sport, | ||
64 | struct sport_params *params); | ||
65 | void sport_tx_start(struct sport_device *sport); | ||
66 | void sport_rx_start(struct sport_device *sport); | ||
67 | void sport_tx_stop(struct sport_device *sport); | ||
68 | void sport_rx_stop(struct sport_device *sport); | ||
69 | void sport_set_tx_callback(struct sport_device *sport, | ||
70 | void (*tx_callback)(void *), void *tx_data); | ||
71 | void sport_set_rx_callback(struct sport_device *sport, | ||
72 | void (*rx_callback)(void *), void *rx_data); | ||
73 | int sport_config_tx_dma(struct sport_device *sport, void *buf, | ||
74 | int fragcount, size_t fragsize); | ||
75 | int sport_config_rx_dma(struct sport_device *sport, void *buf, | ||
76 | int fragcount, size_t fragsize); | ||
77 | unsigned long sport_curr_offset_tx(struct sport_device *sport); | ||
78 | unsigned long sport_curr_offset_rx(struct sport_device *sport); | ||
79 | |||
80 | |||
81 | |||
82 | #endif | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1e1613a438dd..9f8e8594aeb9 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -12,6 +12,7 @@ config SND_SOC_ALL_CODECS | |||
12 | tristate "Build all ASoC CODEC drivers" | 12 | tristate "Build all ASoC CODEC drivers" |
13 | select SND_SOC_88PM860X if MFD_88PM860X | 13 | select SND_SOC_88PM860X if MFD_88PM860X |
14 | select SND_SOC_L3 | 14 | select SND_SOC_L3 |
15 | select SND_SOC_AB8500_CODEC if ABX500_CORE | ||
15 | select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS | 16 | select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS |
16 | select SND_SOC_AD1836 if SPI_MASTER | 17 | select SND_SOC_AD1836 if SPI_MASTER |
17 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI | 18 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI |
@@ -35,7 +36,9 @@ config SND_SOC_ALL_CODECS | |||
35 | select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI | 36 | select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI |
36 | select SND_SOC_CX20442 | 37 | select SND_SOC_CX20442 |
37 | select SND_SOC_DA7210 if I2C | 38 | select SND_SOC_DA7210 if I2C |
39 | select SND_SOC_DA732X if I2C | ||
38 | select SND_SOC_DFBMCS320 | 40 | select SND_SOC_DFBMCS320 |
41 | select SND_SOC_ISABELLE if I2C | ||
39 | select SND_SOC_JZ4740_CODEC | 42 | select SND_SOC_JZ4740_CODEC |
40 | select SND_SOC_LM4857 if I2C | 43 | select SND_SOC_LM4857 if I2C |
41 | select SND_SOC_LM49453 if I2C | 44 | select SND_SOC_LM49453 if I2C |
@@ -54,6 +57,7 @@ config SND_SOC_ALL_CODECS | |||
54 | select SND_SOC_SPDIF | 57 | select SND_SOC_SPDIF |
55 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI | 58 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI |
56 | select SND_SOC_STA32X if I2C | 59 | select SND_SOC_STA32X if I2C |
60 | select SND_SOC_STA529 if I2C | ||
57 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS | 61 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
58 | select SND_SOC_TLV320AIC23 if I2C | 62 | select SND_SOC_TLV320AIC23 if I2C |
59 | select SND_SOC_TLV320AIC26 if SPI_MASTER | 63 | select SND_SOC_TLV320AIC26 if SPI_MASTER |
@@ -70,6 +74,8 @@ config SND_SOC_ALL_CODECS | |||
70 | select SND_SOC_WM2000 if I2C | 74 | select SND_SOC_WM2000 if I2C |
71 | select SND_SOC_WM2200 if I2C | 75 | select SND_SOC_WM2200 if I2C |
72 | select SND_SOC_WM5100 if I2C | 76 | select SND_SOC_WM5100 if I2C |
77 | select SND_SOC_WM5102 if MFD_WM5102 | ||
78 | select SND_SOC_WM5110 if MFD_WM5110 | ||
73 | select SND_SOC_WM8350 if MFD_WM8350 | 79 | select SND_SOC_WM8350 if MFD_WM8350 |
74 | select SND_SOC_WM8400 if MFD_WM8400 | 80 | select SND_SOC_WM8400 if MFD_WM8400 |
75 | select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI | 81 | select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI |
@@ -126,11 +132,21 @@ config SND_SOC_ALL_CODECS | |||
126 | config SND_SOC_88PM860X | 132 | config SND_SOC_88PM860X |
127 | tristate | 133 | tristate |
128 | 134 | ||
135 | config SND_SOC_ARIZONA | ||
136 | tristate | ||
137 | default y if SND_SOC_WM5102=y | ||
138 | default y if SND_SOC_WM5110=y | ||
139 | default m if SND_SOC_WM5102=m | ||
140 | default m if SND_SOC_WM5110=m | ||
141 | |||
129 | config SND_SOC_WM_HUBS | 142 | config SND_SOC_WM_HUBS |
130 | tristate | 143 | tristate |
131 | default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y | 144 | default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y |
132 | default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m | 145 | default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m |
133 | 146 | ||
147 | config SND_SOC_AB8500_CODEC | ||
148 | tristate | ||
149 | |||
134 | config SND_SOC_AC97_CODEC | 150 | config SND_SOC_AC97_CODEC |
135 | tristate | 151 | tristate |
136 | select SND_AC97_CODEC | 152 | select SND_AC97_CODEC |
@@ -219,12 +235,18 @@ config SND_SOC_L3 | |||
219 | config SND_SOC_DA7210 | 235 | config SND_SOC_DA7210 |
220 | tristate | 236 | tristate |
221 | 237 | ||
238 | config SND_SOC_DA732X | ||
239 | tristate | ||
240 | |||
222 | config SND_SOC_DFBMCS320 | 241 | config SND_SOC_DFBMCS320 |
223 | tristate | 242 | tristate |
224 | 243 | ||
225 | config SND_SOC_DMIC | 244 | config SND_SOC_DMIC |
226 | tristate | 245 | tristate |
227 | 246 | ||
247 | config SND_SOC_ISABELLE | ||
248 | tristate | ||
249 | |||
228 | config SND_SOC_LM49453 | 250 | config SND_SOC_LM49453 |
229 | tristate | 251 | tristate |
230 | 252 | ||
@@ -266,6 +288,9 @@ config SND_SOC_SSM2602 | |||
266 | config SND_SOC_STA32X | 288 | config SND_SOC_STA32X |
267 | tristate | 289 | tristate |
268 | 290 | ||
291 | config SND_SOC_STA529 | ||
292 | tristate | ||
293 | |||
269 | config SND_SOC_STAC9766 | 294 | config SND_SOC_STAC9766 |
270 | tristate | 295 | tristate |
271 | 296 | ||
@@ -313,6 +338,12 @@ config SND_SOC_WM2200 | |||
313 | config SND_SOC_WM5100 | 338 | config SND_SOC_WM5100 |
314 | tristate | 339 | tristate |
315 | 340 | ||
341 | config SND_SOC_WM5102 | ||
342 | tristate | ||
343 | |||
344 | config SND_SOC_WM5110 | ||
345 | tristate | ||
346 | |||
316 | config SND_SOC_WM8350 | 347 | config SND_SOC_WM8350 |
317 | tristate | 348 | tristate |
318 | 349 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index fc27fec39487..34148bb59c68 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | snd-soc-88pm860x-objs := 88pm860x-codec.o | 1 | snd-soc-88pm860x-objs := 88pm860x-codec.o |
2 | snd-soc-ab8500-codec-objs := ab8500-codec.o | ||
2 | snd-soc-ac97-objs := ac97.o | 3 | snd-soc-ac97-objs := ac97.o |
3 | snd-soc-ad1836-objs := ad1836.o | 4 | snd-soc-ad1836-objs := ad1836.o |
4 | snd-soc-ad193x-objs := ad193x.o | 5 | snd-soc-ad193x-objs := ad193x.o |
@@ -13,6 +14,7 @@ snd-soc-ak4535-objs := ak4535.o | |||
13 | snd-soc-ak4641-objs := ak4641.o | 14 | snd-soc-ak4641-objs := ak4641.o |
14 | snd-soc-ak4642-objs := ak4642.o | 15 | snd-soc-ak4642-objs := ak4642.o |
15 | snd-soc-ak4671-objs := ak4671.o | 16 | snd-soc-ak4671-objs := ak4671.o |
17 | snd-soc-arizona-objs := arizona.o | ||
16 | snd-soc-cq93vc-objs := cq93vc.o | 18 | snd-soc-cq93vc-objs := cq93vc.o |
17 | snd-soc-cs42l51-objs := cs42l51.o | 19 | snd-soc-cs42l51-objs := cs42l51.o |
18 | snd-soc-cs42l52-objs := cs42l52.o | 20 | snd-soc-cs42l52-objs := cs42l52.o |
@@ -21,8 +23,10 @@ snd-soc-cs4270-objs := cs4270.o | |||
21 | snd-soc-cs4271-objs := cs4271.o | 23 | snd-soc-cs4271-objs := cs4271.o |
22 | snd-soc-cx20442-objs := cx20442.o | 24 | snd-soc-cx20442-objs := cx20442.o |
23 | snd-soc-da7210-objs := da7210.o | 25 | snd-soc-da7210-objs := da7210.o |
26 | snd-soc-da732x-objs := da732x.o | ||
24 | snd-soc-dfbmcs320-objs := dfbmcs320.o | 27 | snd-soc-dfbmcs320-objs := dfbmcs320.o |
25 | snd-soc-dmic-objs := dmic.o | 28 | snd-soc-dmic-objs := dmic.o |
29 | snd-soc-isabelle-objs := isabelle.o | ||
26 | snd-soc-jz4740-codec-objs := jz4740.o | 30 | snd-soc-jz4740-codec-objs := jz4740.o |
27 | snd-soc-l3-objs := l3.o | 31 | snd-soc-l3-objs := l3.o |
28 | snd-soc-lm4857-objs := lm4857.o | 32 | snd-soc-lm4857-objs := lm4857.o |
@@ -41,9 +45,11 @@ snd-soc-alc5623-objs := alc5623.o | |||
41 | snd-soc-alc5632-objs := alc5632.o | 45 | snd-soc-alc5632-objs := alc5632.o |
42 | snd-soc-sigmadsp-objs := sigmadsp.o | 46 | snd-soc-sigmadsp-objs := sigmadsp.o |
43 | snd-soc-sn95031-objs := sn95031.o | 47 | snd-soc-sn95031-objs := sn95031.o |
44 | snd-soc-spdif-objs := spdif_transciever.o | 48 | snd-soc-spdif-tx-objs := spdif_transciever.o |
49 | snd-soc-spdif-rx-objs := spdif_receiver.o | ||
45 | snd-soc-ssm2602-objs := ssm2602.o | 50 | snd-soc-ssm2602-objs := ssm2602.o |
46 | snd-soc-sta32x-objs := sta32x.o | 51 | snd-soc-sta32x-objs := sta32x.o |
52 | snd-soc-sta529-objs := sta529.o | ||
47 | snd-soc-stac9766-objs := stac9766.o | 53 | snd-soc-stac9766-objs := stac9766.o |
48 | snd-soc-tlv320aic23-objs := tlv320aic23.o | 54 | snd-soc-tlv320aic23-objs := tlv320aic23.o |
49 | snd-soc-tlv320aic26-objs := tlv320aic26.o | 55 | snd-soc-tlv320aic26-objs := tlv320aic26.o |
@@ -59,6 +65,8 @@ snd-soc-wm1250-ev1-objs := wm1250-ev1.o | |||
59 | snd-soc-wm2000-objs := wm2000.o | 65 | snd-soc-wm2000-objs := wm2000.o |
60 | snd-soc-wm2200-objs := wm2200.o | 66 | snd-soc-wm2200-objs := wm2200.o |
61 | snd-soc-wm5100-objs := wm5100.o wm5100-tables.o | 67 | snd-soc-wm5100-objs := wm5100.o wm5100-tables.o |
68 | snd-soc-wm5102-objs := wm5102.o | ||
69 | snd-soc-wm5110-objs := wm5110.o | ||
62 | snd-soc-wm8350-objs := wm8350.o | 70 | snd-soc-wm8350-objs := wm8350.o |
63 | snd-soc-wm8400-objs := wm8400.o | 71 | snd-soc-wm8400-objs := wm8400.o |
64 | snd-soc-wm8510-objs := wm8510.o | 72 | snd-soc-wm8510-objs := wm8510.o |
@@ -108,6 +116,7 @@ snd-soc-max9877-objs := max9877.o | |||
108 | snd-soc-tpa6130a2-objs := tpa6130a2.o | 116 | snd-soc-tpa6130a2-objs := tpa6130a2.o |
109 | 117 | ||
110 | obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o | 118 | obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o |
119 | obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o | ||
111 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o | 120 | obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o |
112 | obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o | 121 | obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o |
113 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o | 122 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o |
@@ -124,6 +133,7 @@ obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o | |||
124 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o | 133 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o |
125 | obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o | 134 | obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o |
126 | obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o | 135 | obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o |
136 | obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o | ||
127 | obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o | 137 | obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o |
128 | obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o | 138 | obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o |
129 | obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o | 139 | obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o |
@@ -132,8 +142,10 @@ obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | |||
132 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o | 142 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o |
133 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 143 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
134 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o | 144 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o |
145 | obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o | ||
135 | obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o | 146 | obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o |
136 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o | 147 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o |
148 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o | ||
137 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o | 149 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o |
138 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o | 150 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o |
139 | obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o | 151 | obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o |
@@ -150,9 +162,10 @@ obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o | |||
150 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o | 162 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o |
151 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o | 163 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o |
152 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o | 164 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o |
153 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o | 165 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o |
154 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | 166 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
155 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o | 167 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o |
168 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | ||
156 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o | 169 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o |
157 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o | 170 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
158 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o | 171 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o |
@@ -168,6 +181,8 @@ obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o | |||
168 | obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o | 181 | obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o |
169 | obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o | 182 | obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o |
170 | obj-$(CONFIG_SND_SOC_WM5100) += snd-soc-wm5100.o | 183 | obj-$(CONFIG_SND_SOC_WM5100) += snd-soc-wm5100.o |
184 | obj-$(CONFIG_SND_SOC_WM5102) += snd-soc-wm5102.o | ||
185 | obj-$(CONFIG_SND_SOC_WM5110) += snd-soc-wm5110.o | ||
171 | obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o | 186 | obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o |
172 | obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o | 187 | obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o |
173 | obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o | 188 | obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o |
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c new file mode 100644 index 000000000000..3c795921c5f6 --- /dev/null +++ b/sound/soc/codecs/ab8500-codec.c | |||
@@ -0,0 +1,2522 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2012 | ||
3 | * | ||
4 | * Author: Ola Lilja <ola.o.lilja@stericsson.com>, | ||
5 | * Kristoffer Karlsson <kristoffer.karlsson@stericsson.com>, | ||
6 | * Roger Nilsson <roger.xr.nilsson@stericsson.com>, | ||
7 | * for ST-Ericsson. | ||
8 | * | ||
9 | * Based on the early work done by: | ||
10 | * Mikko J. Lehto <mikko.lehto@symbio.com>, | ||
11 | * Mikko Sarmanne <mikko.sarmanne@symbio.com>, | ||
12 | * Jarmo K. Kuronen <jarmo.kuronen@symbio.com>, | ||
13 | * for ST-Ericsson. | ||
14 | * | ||
15 | * License terms: | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify it | ||
18 | * under the terms of the GNU General Public License version 2 as published | ||
19 | * by the Free Software Foundation. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/device.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/pm.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/mutex.h> | ||
32 | #include <linux/mfd/abx500/ab8500.h> | ||
33 | #include <linux/mfd/abx500.h> | ||
34 | #include <linux/mfd/abx500/ab8500-sysctrl.h> | ||
35 | #include <linux/mfd/abx500/ab8500-codec.h> | ||
36 | #include <linux/regulator/consumer.h> | ||
37 | |||
38 | #include <sound/core.h> | ||
39 | #include <sound/pcm.h> | ||
40 | #include <sound/pcm_params.h> | ||
41 | #include <sound/initval.h> | ||
42 | #include <sound/soc.h> | ||
43 | #include <sound/soc-dapm.h> | ||
44 | #include <sound/tlv.h> | ||
45 | |||
46 | #include "ab8500-codec.h" | ||
47 | |||
48 | /* Macrocell value definitions */ | ||
49 | #define CLK_32K_OUT2_DISABLE 0x01 | ||
50 | #define INACTIVE_RESET_AUDIO 0x02 | ||
51 | #define ENABLE_AUDIO_CLK_TO_AUDIO_BLK 0x10 | ||
52 | #define ENABLE_VINTCORE12_SUPPLY 0x04 | ||
53 | #define GPIO27_DIR_OUTPUT 0x04 | ||
54 | #define GPIO29_DIR_OUTPUT 0x10 | ||
55 | #define GPIO31_DIR_OUTPUT 0x40 | ||
56 | |||
57 | /* Macrocell register definitions */ | ||
58 | #define AB8500_CTRL3_REG 0x0200 | ||
59 | #define AB8500_GPIO_DIR4_REG 0x1013 | ||
60 | |||
61 | /* Nr of FIR/IIR-coeff banks in ANC-block */ | ||
62 | #define AB8500_NR_OF_ANC_COEFF_BANKS 2 | ||
63 | |||
64 | /* Minimum duration to keep ANC IIR Init bit high or | ||
65 | low before proceeding with the configuration sequence */ | ||
66 | #define AB8500_ANC_SM_DELAY 2000 | ||
67 | |||
68 | #define AB8500_FILTER_CONTROL(xname, xcount, xmin, xmax) \ | ||
69 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
70 | .info = filter_control_info, \ | ||
71 | .get = filter_control_get, .put = filter_control_put, \ | ||
72 | .private_value = (unsigned long)&(struct filter_control) \ | ||
73 | {.count = xcount, .min = xmin, .max = xmax} } | ||
74 | |||
75 | struct filter_control { | ||
76 | long min, max; | ||
77 | unsigned int count; | ||
78 | long value[128]; | ||
79 | }; | ||
80 | |||
81 | /* Sidetone states */ | ||
82 | static const char * const enum_sid_state[] = { | ||
83 | "Unconfigured", | ||
84 | "Apply FIR", | ||
85 | "FIR is configured", | ||
86 | }; | ||
87 | enum sid_state { | ||
88 | SID_UNCONFIGURED = 0, | ||
89 | SID_APPLY_FIR = 1, | ||
90 | SID_FIR_CONFIGURED = 2, | ||
91 | }; | ||
92 | |||
93 | static const char * const enum_anc_state[] = { | ||
94 | "Unconfigured", | ||
95 | "Apply FIR and IIR", | ||
96 | "FIR and IIR are configured", | ||
97 | "Apply FIR", | ||
98 | "FIR is configured", | ||
99 | "Apply IIR", | ||
100 | "IIR is configured" | ||
101 | }; | ||
102 | enum anc_state { | ||
103 | ANC_UNCONFIGURED = 0, | ||
104 | ANC_APPLY_FIR_IIR = 1, | ||
105 | ANC_FIR_IIR_CONFIGURED = 2, | ||
106 | ANC_APPLY_FIR = 3, | ||
107 | ANC_FIR_CONFIGURED = 4, | ||
108 | ANC_APPLY_IIR = 5, | ||
109 | ANC_IIR_CONFIGURED = 6 | ||
110 | }; | ||
111 | |||
112 | /* Analog microphones */ | ||
113 | enum amic_idx { | ||
114 | AMIC_IDX_1A, | ||
115 | AMIC_IDX_1B, | ||
116 | AMIC_IDX_2 | ||
117 | }; | ||
118 | |||
119 | struct ab8500_codec_drvdata_dbg { | ||
120 | struct regulator *vaud; | ||
121 | struct regulator *vamic1; | ||
122 | struct regulator *vamic2; | ||
123 | struct regulator *vdmic; | ||
124 | }; | ||
125 | |||
126 | /* Private data for AB8500 device-driver */ | ||
127 | struct ab8500_codec_drvdata { | ||
128 | /* Sidetone */ | ||
129 | long *sid_fir_values; | ||
130 | enum sid_state sid_status; | ||
131 | |||
132 | /* ANC */ | ||
133 | struct mutex anc_lock; | ||
134 | long *anc_fir_values; | ||
135 | long *anc_iir_values; | ||
136 | enum anc_state anc_status; | ||
137 | }; | ||
138 | |||
139 | static inline const char *amic_micbias_str(enum amic_micbias micbias) | ||
140 | { | ||
141 | switch (micbias) { | ||
142 | case AMIC_MICBIAS_VAMIC1: | ||
143 | return "VAMIC1"; | ||
144 | case AMIC_MICBIAS_VAMIC2: | ||
145 | return "VAMIC2"; | ||
146 | default: | ||
147 | return "Unknown"; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | static inline const char *amic_type_str(enum amic_type type) | ||
152 | { | ||
153 | switch (type) { | ||
154 | case AMIC_TYPE_DIFFERENTIAL: | ||
155 | return "DIFFERENTIAL"; | ||
156 | case AMIC_TYPE_SINGLE_ENDED: | ||
157 | return "SINGLE ENDED"; | ||
158 | default: | ||
159 | return "Unknown"; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * Read'n'write functions | ||
165 | */ | ||
166 | |||
167 | /* Read a register from the audio-bank of AB8500 */ | ||
168 | static unsigned int ab8500_codec_read_reg(struct snd_soc_codec *codec, | ||
169 | unsigned int reg) | ||
170 | { | ||
171 | int status; | ||
172 | unsigned int value = 0; | ||
173 | |||
174 | u8 value8; | ||
175 | status = abx500_get_register_interruptible(codec->dev, AB8500_AUDIO, | ||
176 | reg, &value8); | ||
177 | if (status < 0) { | ||
178 | dev_err(codec->dev, | ||
179 | "%s: ERROR: Register (0x%02x:0x%02x) read failed (%d).\n", | ||
180 | __func__, (u8)AB8500_AUDIO, (u8)reg, status); | ||
181 | } else { | ||
182 | dev_dbg(codec->dev, | ||
183 | "%s: Read 0x%02x from register 0x%02x:0x%02x\n", | ||
184 | __func__, value8, (u8)AB8500_AUDIO, (u8)reg); | ||
185 | value = (unsigned int)value8; | ||
186 | } | ||
187 | |||
188 | return value; | ||
189 | } | ||
190 | |||
191 | /* Write to a register in the audio-bank of AB8500 */ | ||
192 | static int ab8500_codec_write_reg(struct snd_soc_codec *codec, | ||
193 | unsigned int reg, unsigned int value) | ||
194 | { | ||
195 | int status; | ||
196 | |||
197 | status = abx500_set_register_interruptible(codec->dev, AB8500_AUDIO, | ||
198 | reg, value); | ||
199 | if (status < 0) | ||
200 | dev_err(codec->dev, | ||
201 | "%s: ERROR: Register (%02x:%02x) write failed (%d).\n", | ||
202 | __func__, (u8)AB8500_AUDIO, (u8)reg, status); | ||
203 | else | ||
204 | dev_dbg(codec->dev, | ||
205 | "%s: Wrote 0x%02x into register %02x:%02x\n", | ||
206 | __func__, (u8)value, (u8)AB8500_AUDIO, (u8)reg); | ||
207 | |||
208 | return status; | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * Controls - DAPM | ||
213 | */ | ||
214 | |||
215 | /* Earpiece */ | ||
216 | |||
217 | /* Earpiece source selector */ | ||
218 | static const char * const enum_ear_lineout_source[] = {"Headset Left", | ||
219 | "Speaker Left"}; | ||
220 | static SOC_ENUM_SINGLE_DECL(dapm_enum_ear_lineout_source, AB8500_DMICFILTCONF, | ||
221 | AB8500_DMICFILTCONF_DA3TOEAR, enum_ear_lineout_source); | ||
222 | static const struct snd_kcontrol_new dapm_ear_lineout_source = | ||
223 | SOC_DAPM_ENUM("Earpiece or LineOut Mono Source", | ||
224 | dapm_enum_ear_lineout_source); | ||
225 | |||
226 | /* LineOut */ | ||
227 | |||
228 | /* LineOut source selector */ | ||
229 | static const char * const enum_lineout_source[] = {"Mono Path", "Stereo Path"}; | ||
230 | static SOC_ENUM_DOUBLE_DECL(dapm_enum_lineout_source, AB8500_ANACONF5, | ||
231 | AB8500_ANACONF5_HSLDACTOLOL, | ||
232 | AB8500_ANACONF5_HSRDACTOLOR, enum_lineout_source); | ||
233 | static const struct snd_kcontrol_new dapm_lineout_source[] = { | ||
234 | SOC_DAPM_ENUM("LineOut Source", dapm_enum_lineout_source), | ||
235 | }; | ||
236 | |||
237 | /* Handsfree */ | ||
238 | |||
239 | /* Speaker Left - ANC selector */ | ||
240 | static const char * const enum_HFx_sel[] = {"Audio Path", "ANC"}; | ||
241 | static SOC_ENUM_SINGLE_DECL(dapm_enum_HFl_sel, AB8500_DIGMULTCONF2, | ||
242 | AB8500_DIGMULTCONF2_HFLSEL, enum_HFx_sel); | ||
243 | static const struct snd_kcontrol_new dapm_HFl_select[] = { | ||
244 | SOC_DAPM_ENUM("Speaker Left Source", dapm_enum_HFl_sel), | ||
245 | }; | ||
246 | |||
247 | /* Speaker Right - ANC selector */ | ||
248 | static SOC_ENUM_SINGLE_DECL(dapm_enum_HFr_sel, AB8500_DIGMULTCONF2, | ||
249 | AB8500_DIGMULTCONF2_HFRSEL, enum_HFx_sel); | ||
250 | static const struct snd_kcontrol_new dapm_HFr_select[] = { | ||
251 | SOC_DAPM_ENUM("Speaker Right Source", dapm_enum_HFr_sel), | ||
252 | }; | ||
253 | |||
254 | /* Mic 1 */ | ||
255 | |||
256 | /* Mic 1 - Mic 1a or 1b selector */ | ||
257 | static const char * const enum_mic1ab_sel[] = {"Mic 1b", "Mic 1a"}; | ||
258 | static SOC_ENUM_SINGLE_DECL(dapm_enum_mic1ab_sel, AB8500_ANACONF3, | ||
259 | AB8500_ANACONF3_MIC1SEL, enum_mic1ab_sel); | ||
260 | static const struct snd_kcontrol_new dapm_mic1ab_mux[] = { | ||
261 | SOC_DAPM_ENUM("Mic 1a or 1b Select", dapm_enum_mic1ab_sel), | ||
262 | }; | ||
263 | |||
264 | /* Mic 1 - AD3 - Mic 1 or DMic 3 selector */ | ||
265 | static const char * const enum_ad3_sel[] = {"Mic 1", "DMic 3"}; | ||
266 | static SOC_ENUM_SINGLE_DECL(dapm_enum_ad3_sel, AB8500_DIGMULTCONF1, | ||
267 | AB8500_DIGMULTCONF1_AD3SEL, enum_ad3_sel); | ||
268 | static const struct snd_kcontrol_new dapm_ad3_select[] = { | ||
269 | SOC_DAPM_ENUM("AD3 Source Select", dapm_enum_ad3_sel), | ||
270 | }; | ||
271 | |||
272 | /* Mic 1 - AD6 - Mic 1 or DMic 6 selector */ | ||
273 | static const char * const enum_ad6_sel[] = {"Mic 1", "DMic 6"}; | ||
274 | static SOC_ENUM_SINGLE_DECL(dapm_enum_ad6_sel, AB8500_DIGMULTCONF1, | ||
275 | AB8500_DIGMULTCONF1_AD6SEL, enum_ad6_sel); | ||
276 | static const struct snd_kcontrol_new dapm_ad6_select[] = { | ||
277 | SOC_DAPM_ENUM("AD6 Source Select", dapm_enum_ad6_sel), | ||
278 | }; | ||
279 | |||
280 | /* Mic 2 */ | ||
281 | |||
282 | /* Mic 2 - AD5 - Mic 2 or DMic 5 selector */ | ||
283 | static const char * const enum_ad5_sel[] = {"Mic 2", "DMic 5"}; | ||
284 | static SOC_ENUM_SINGLE_DECL(dapm_enum_ad5_sel, AB8500_DIGMULTCONF1, | ||
285 | AB8500_DIGMULTCONF1_AD5SEL, enum_ad5_sel); | ||
286 | static const struct snd_kcontrol_new dapm_ad5_select[] = { | ||
287 | SOC_DAPM_ENUM("AD5 Source Select", dapm_enum_ad5_sel), | ||
288 | }; | ||
289 | |||
290 | /* LineIn */ | ||
291 | |||
292 | /* LineIn left - AD1 - LineIn Left or DMic 1 selector */ | ||
293 | static const char * const enum_ad1_sel[] = {"LineIn Left", "DMic 1"}; | ||
294 | static SOC_ENUM_SINGLE_DECL(dapm_enum_ad1_sel, AB8500_DIGMULTCONF1, | ||
295 | AB8500_DIGMULTCONF1_AD1SEL, enum_ad1_sel); | ||
296 | static const struct snd_kcontrol_new dapm_ad1_select[] = { | ||
297 | SOC_DAPM_ENUM("AD1 Source Select", dapm_enum_ad1_sel), | ||
298 | }; | ||
299 | |||
300 | /* LineIn right - Mic 2 or LineIn Right selector */ | ||
301 | static const char * const enum_mic2lr_sel[] = {"Mic 2", "LineIn Right"}; | ||
302 | static SOC_ENUM_SINGLE_DECL(dapm_enum_mic2lr_sel, AB8500_ANACONF3, | ||
303 | AB8500_ANACONF3_LINRSEL, enum_mic2lr_sel); | ||
304 | static const struct snd_kcontrol_new dapm_mic2lr_select[] = { | ||
305 | SOC_DAPM_ENUM("Mic 2 or LINR Select", dapm_enum_mic2lr_sel), | ||
306 | }; | ||
307 | |||
308 | /* LineIn right - AD2 - LineIn Right or DMic2 selector */ | ||
309 | static const char * const enum_ad2_sel[] = {"LineIn Right", "DMic 2"}; | ||
310 | static SOC_ENUM_SINGLE_DECL(dapm_enum_ad2_sel, AB8500_DIGMULTCONF1, | ||
311 | AB8500_DIGMULTCONF1_AD2SEL, enum_ad2_sel); | ||
312 | static const struct snd_kcontrol_new dapm_ad2_select[] = { | ||
313 | SOC_DAPM_ENUM("AD2 Source Select", dapm_enum_ad2_sel), | ||
314 | }; | ||
315 | |||
316 | |||
317 | /* ANC */ | ||
318 | |||
319 | static const char * const enum_anc_in_sel[] = {"Mic 1 / DMic 6", | ||
320 | "Mic 2 / DMic 5"}; | ||
321 | static SOC_ENUM_SINGLE_DECL(dapm_enum_anc_in_sel, AB8500_DMICFILTCONF, | ||
322 | AB8500_DMICFILTCONF_ANCINSEL, enum_anc_in_sel); | ||
323 | static const struct snd_kcontrol_new dapm_anc_in_select[] = { | ||
324 | SOC_DAPM_ENUM("ANC Source", dapm_enum_anc_in_sel), | ||
325 | }; | ||
326 | |||
327 | /* ANC - Enable/Disable */ | ||
328 | static const struct snd_kcontrol_new dapm_anc_enable[] = { | ||
329 | SOC_DAPM_SINGLE("Switch", AB8500_ANCCONF1, | ||
330 | AB8500_ANCCONF1_ENANC, 0, 0), | ||
331 | }; | ||
332 | |||
333 | /* ANC to Earpiece - Mute */ | ||
334 | static const struct snd_kcontrol_new dapm_anc_ear_mute[] = { | ||
335 | SOC_DAPM_SINGLE("Switch", AB8500_DIGMULTCONF1, | ||
336 | AB8500_DIGMULTCONF1_ANCSEL, 1, 0), | ||
337 | }; | ||
338 | |||
339 | |||
340 | |||
341 | /* Sidetone left */ | ||
342 | |||
343 | /* Sidetone left - Input selector */ | ||
344 | static const char * const enum_stfir1_in_sel[] = { | ||
345 | "LineIn Left", "LineIn Right", "Mic 1", "Headset Left" | ||
346 | }; | ||
347 | static SOC_ENUM_SINGLE_DECL(dapm_enum_stfir1_in_sel, AB8500_DIGMULTCONF2, | ||
348 | AB8500_DIGMULTCONF2_FIRSID1SEL, enum_stfir1_in_sel); | ||
349 | static const struct snd_kcontrol_new dapm_stfir1_in_select[] = { | ||
350 | SOC_DAPM_ENUM("Sidetone Left Source", dapm_enum_stfir1_in_sel), | ||
351 | }; | ||
352 | |||
353 | /* Sidetone right path */ | ||
354 | |||
355 | /* Sidetone right - Input selector */ | ||
356 | static const char * const enum_stfir2_in_sel[] = { | ||
357 | "LineIn Right", "Mic 1", "DMic 4", "Headset Right" | ||
358 | }; | ||
359 | static SOC_ENUM_SINGLE_DECL(dapm_enum_stfir2_in_sel, AB8500_DIGMULTCONF2, | ||
360 | AB8500_DIGMULTCONF2_FIRSID2SEL, enum_stfir2_in_sel); | ||
361 | static const struct snd_kcontrol_new dapm_stfir2_in_select[] = { | ||
362 | SOC_DAPM_ENUM("Sidetone Right Source", dapm_enum_stfir2_in_sel), | ||
363 | }; | ||
364 | |||
365 | /* Vibra */ | ||
366 | |||
367 | static const char * const enum_pwm2vibx[] = {"Audio Path", "PWM Generator"}; | ||
368 | |||
369 | static SOC_ENUM_SINGLE_DECL(dapm_enum_pwm2vib1, AB8500_PWMGENCONF1, | ||
370 | AB8500_PWMGENCONF1_PWMTOVIB1, enum_pwm2vibx); | ||
371 | |||
372 | static const struct snd_kcontrol_new dapm_pwm2vib1[] = { | ||
373 | SOC_DAPM_ENUM("Vibra 1 Controller", dapm_enum_pwm2vib1), | ||
374 | }; | ||
375 | |||
376 | static SOC_ENUM_SINGLE_DECL(dapm_enum_pwm2vib2, AB8500_PWMGENCONF1, | ||
377 | AB8500_PWMGENCONF1_PWMTOVIB2, enum_pwm2vibx); | ||
378 | |||
379 | static const struct snd_kcontrol_new dapm_pwm2vib2[] = { | ||
380 | SOC_DAPM_ENUM("Vibra 2 Controller", dapm_enum_pwm2vib2), | ||
381 | }; | ||
382 | |||
383 | /* | ||
384 | * DAPM-widgets | ||
385 | */ | ||
386 | |||
387 | static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = { | ||
388 | |||
389 | /* Clocks */ | ||
390 | SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"), | ||
391 | |||
392 | /* Regulators */ | ||
393 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0), | ||
394 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0), | ||
395 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0), | ||
396 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0), | ||
397 | |||
398 | /* Power */ | ||
399 | SND_SOC_DAPM_SUPPLY("Audio Power", | ||
400 | AB8500_POWERUP, AB8500_POWERUP_POWERUP, 0, | ||
401 | NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
402 | SND_SOC_DAPM_SUPPLY("Audio Analog Power", | ||
403 | AB8500_POWERUP, AB8500_POWERUP_ENANA, 0, | ||
404 | NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
405 | |||
406 | /* Main supply node */ | ||
407 | SND_SOC_DAPM_SUPPLY("Main Supply", SND_SOC_NOPM, 0, 0, | ||
408 | NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
409 | |||
410 | /* DA/AD */ | ||
411 | |||
412 | SND_SOC_DAPM_INPUT("ADC Input"), | ||
413 | SND_SOC_DAPM_ADC("ADC", "ab8500_0c", SND_SOC_NOPM, 0, 0), | ||
414 | |||
415 | SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), | ||
416 | SND_SOC_DAPM_OUTPUT("DAC Output"), | ||
417 | |||
418 | SND_SOC_DAPM_AIF_IN("DA_IN1", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
419 | SND_SOC_DAPM_AIF_IN("DA_IN2", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
420 | SND_SOC_DAPM_AIF_IN("DA_IN3", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
421 | SND_SOC_DAPM_AIF_IN("DA_IN4", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
422 | SND_SOC_DAPM_AIF_IN("DA_IN5", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
423 | SND_SOC_DAPM_AIF_IN("DA_IN6", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
424 | SND_SOC_DAPM_AIF_OUT("AD_OUT1", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
425 | SND_SOC_DAPM_AIF_OUT("AD_OUT2", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
426 | SND_SOC_DAPM_AIF_OUT("AD_OUT3", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
427 | SND_SOC_DAPM_AIF_OUT("AD_OUT4", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
428 | SND_SOC_DAPM_AIF_OUT("AD_OUT57", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
429 | SND_SOC_DAPM_AIF_OUT("AD_OUT68", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
430 | |||
431 | /* Headset path */ | ||
432 | |||
433 | SND_SOC_DAPM_SUPPLY("Charge Pump", AB8500_ANACONF5, | ||
434 | AB8500_ANACONF5_ENCPHS, 0, NULL, 0), | ||
435 | |||
436 | SND_SOC_DAPM_DAC("DA1 Enable", "ab8500_0p", | ||
437 | AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA1, 0), | ||
438 | SND_SOC_DAPM_DAC("DA2 Enable", "ab8500_0p", | ||
439 | AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA2, 0), | ||
440 | |||
441 | SND_SOC_DAPM_PGA("HSL Digital Volume", SND_SOC_NOPM, 0, 0, | ||
442 | NULL, 0), | ||
443 | SND_SOC_DAPM_PGA("HSR Digital Volume", SND_SOC_NOPM, 0, 0, | ||
444 | NULL, 0), | ||
445 | |||
446 | SND_SOC_DAPM_DAC("HSL DAC", "ab8500_0p", | ||
447 | AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHSL, 0), | ||
448 | SND_SOC_DAPM_DAC("HSR DAC", "ab8500_0p", | ||
449 | AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHSR, 0), | ||
450 | SND_SOC_DAPM_MIXER("HSL DAC Mute", AB8500_MUTECONF, | ||
451 | AB8500_MUTECONF_MUTDACHSL, 1, | ||
452 | NULL, 0), | ||
453 | SND_SOC_DAPM_MIXER("HSR DAC Mute", AB8500_MUTECONF, | ||
454 | AB8500_MUTECONF_MUTDACHSR, 1, | ||
455 | NULL, 0), | ||
456 | SND_SOC_DAPM_DAC("HSL DAC Driver", "ab8500_0p", | ||
457 | AB8500_ANACONF3, AB8500_ANACONF3_ENDRVHSL, 0), | ||
458 | SND_SOC_DAPM_DAC("HSR DAC Driver", "ab8500_0p", | ||
459 | AB8500_ANACONF3, AB8500_ANACONF3_ENDRVHSR, 0), | ||
460 | |||
461 | SND_SOC_DAPM_MIXER("HSL Mute", | ||
462 | AB8500_MUTECONF, AB8500_MUTECONF_MUTHSL, 1, | ||
463 | NULL, 0), | ||
464 | SND_SOC_DAPM_MIXER("HSR Mute", | ||
465 | AB8500_MUTECONF, AB8500_MUTECONF_MUTHSR, 1, | ||
466 | NULL, 0), | ||
467 | SND_SOC_DAPM_MIXER("HSL Enable", | ||
468 | AB8500_ANACONF4, AB8500_ANACONF4_ENHSL, 0, | ||
469 | NULL, 0), | ||
470 | SND_SOC_DAPM_MIXER("HSR Enable", | ||
471 | AB8500_ANACONF4, AB8500_ANACONF4_ENHSR, 0, | ||
472 | NULL, 0), | ||
473 | SND_SOC_DAPM_PGA("HSL Volume", | ||
474 | SND_SOC_NOPM, 0, 0, | ||
475 | NULL, 0), | ||
476 | SND_SOC_DAPM_PGA("HSR Volume", | ||
477 | SND_SOC_NOPM, 0, 0, | ||
478 | NULL, 0), | ||
479 | |||
480 | SND_SOC_DAPM_OUTPUT("Headset Left"), | ||
481 | SND_SOC_DAPM_OUTPUT("Headset Right"), | ||
482 | |||
483 | /* LineOut path */ | ||
484 | |||
485 | SND_SOC_DAPM_MUX("LineOut Source", | ||
486 | SND_SOC_NOPM, 0, 0, dapm_lineout_source), | ||
487 | |||
488 | SND_SOC_DAPM_MIXER("LOL Disable HFL", | ||
489 | AB8500_ANACONF4, AB8500_ANACONF4_ENHFL, 1, | ||
490 | NULL, 0), | ||
491 | SND_SOC_DAPM_MIXER("LOR Disable HFR", | ||
492 | AB8500_ANACONF4, AB8500_ANACONF4_ENHFR, 1, | ||
493 | NULL, 0), | ||
494 | |||
495 | SND_SOC_DAPM_MIXER("LOL Enable", | ||
496 | AB8500_ANACONF5, AB8500_ANACONF5_ENLOL, 0, | ||
497 | NULL, 0), | ||
498 | SND_SOC_DAPM_MIXER("LOR Enable", | ||
499 | AB8500_ANACONF5, AB8500_ANACONF5_ENLOR, 0, | ||
500 | NULL, 0), | ||
501 | |||
502 | SND_SOC_DAPM_OUTPUT("LineOut Left"), | ||
503 | SND_SOC_DAPM_OUTPUT("LineOut Right"), | ||
504 | |||
505 | /* Earpiece path */ | ||
506 | |||
507 | SND_SOC_DAPM_MUX("Earpiece or LineOut Mono Source", | ||
508 | SND_SOC_NOPM, 0, 0, &dapm_ear_lineout_source), | ||
509 | SND_SOC_DAPM_MIXER("EAR DAC", | ||
510 | AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACEAR, 0, | ||
511 | NULL, 0), | ||
512 | SND_SOC_DAPM_MIXER("EAR Mute", | ||
513 | AB8500_MUTECONF, AB8500_MUTECONF_MUTEAR, 1, | ||
514 | NULL, 0), | ||
515 | SND_SOC_DAPM_MIXER("EAR Enable", | ||
516 | AB8500_ANACONF4, AB8500_ANACONF4_ENEAR, 0, | ||
517 | NULL, 0), | ||
518 | |||
519 | SND_SOC_DAPM_OUTPUT("Earpiece"), | ||
520 | |||
521 | /* Handsfree path */ | ||
522 | |||
523 | SND_SOC_DAPM_MIXER("DA3 Channel Volume", | ||
524 | AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA3, 0, | ||
525 | NULL, 0), | ||
526 | SND_SOC_DAPM_MIXER("DA4 Channel Volume", | ||
527 | AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA4, 0, | ||
528 | NULL, 0), | ||
529 | SND_SOC_DAPM_MUX("Speaker Left Source", | ||
530 | SND_SOC_NOPM, 0, 0, dapm_HFl_select), | ||
531 | SND_SOC_DAPM_MUX("Speaker Right Source", | ||
532 | SND_SOC_NOPM, 0, 0, dapm_HFr_select), | ||
533 | SND_SOC_DAPM_MIXER("HFL DAC", AB8500_DAPATHCONF, | ||
534 | AB8500_DAPATHCONF_ENDACHFL, 0, | ||
535 | NULL, 0), | ||
536 | SND_SOC_DAPM_MIXER("HFR DAC", | ||
537 | AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHFR, 0, | ||
538 | NULL, 0), | ||
539 | SND_SOC_DAPM_MIXER("DA4 or ANC path to HfR", | ||
540 | AB8500_DIGMULTCONF2, AB8500_DIGMULTCONF2_DATOHFREN, 0, | ||
541 | NULL, 0), | ||
542 | SND_SOC_DAPM_MIXER("DA3 or ANC path to HfL", | ||
543 | AB8500_DIGMULTCONF2, AB8500_DIGMULTCONF2_DATOHFLEN, 0, | ||
544 | NULL, 0), | ||
545 | SND_SOC_DAPM_MIXER("HFL Enable", | ||
546 | AB8500_ANACONF4, AB8500_ANACONF4_ENHFL, 0, | ||
547 | NULL, 0), | ||
548 | SND_SOC_DAPM_MIXER("HFR Enable", | ||
549 | AB8500_ANACONF4, AB8500_ANACONF4_ENHFR, 0, | ||
550 | NULL, 0), | ||
551 | |||
552 | SND_SOC_DAPM_OUTPUT("Speaker Left"), | ||
553 | SND_SOC_DAPM_OUTPUT("Speaker Right"), | ||
554 | |||
555 | /* Vibrator path */ | ||
556 | |||
557 | SND_SOC_DAPM_INPUT("PWMGEN1"), | ||
558 | SND_SOC_DAPM_INPUT("PWMGEN2"), | ||
559 | |||
560 | SND_SOC_DAPM_MIXER("DA5 Channel Volume", | ||
561 | AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA5, 0, | ||
562 | NULL, 0), | ||
563 | SND_SOC_DAPM_MIXER("DA6 Channel Volume", | ||
564 | AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA6, 0, | ||
565 | NULL, 0), | ||
566 | SND_SOC_DAPM_MIXER("VIB1 DAC", | ||
567 | AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACVIB1, 0, | ||
568 | NULL, 0), | ||
569 | SND_SOC_DAPM_MIXER("VIB2 DAC", | ||
570 | AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACVIB2, 0, | ||
571 | NULL, 0), | ||
572 | SND_SOC_DAPM_MUX("Vibra 1 Controller", | ||
573 | SND_SOC_NOPM, 0, 0, dapm_pwm2vib1), | ||
574 | SND_SOC_DAPM_MUX("Vibra 2 Controller", | ||
575 | SND_SOC_NOPM, 0, 0, dapm_pwm2vib2), | ||
576 | SND_SOC_DAPM_MIXER("VIB1 Enable", | ||
577 | AB8500_ANACONF4, AB8500_ANACONF4_ENVIB1, 0, | ||
578 | NULL, 0), | ||
579 | SND_SOC_DAPM_MIXER("VIB2 Enable", | ||
580 | AB8500_ANACONF4, AB8500_ANACONF4_ENVIB2, 0, | ||
581 | NULL, 0), | ||
582 | |||
583 | SND_SOC_DAPM_OUTPUT("Vibra 1"), | ||
584 | SND_SOC_DAPM_OUTPUT("Vibra 2"), | ||
585 | |||
586 | /* Mic 1 */ | ||
587 | |||
588 | SND_SOC_DAPM_INPUT("Mic 1"), | ||
589 | |||
590 | SND_SOC_DAPM_MUX("Mic 1a or 1b Select", | ||
591 | SND_SOC_NOPM, 0, 0, dapm_mic1ab_mux), | ||
592 | SND_SOC_DAPM_MIXER("MIC1 Mute", | ||
593 | AB8500_ANACONF2, AB8500_ANACONF2_MUTMIC1, 1, | ||
594 | NULL, 0), | ||
595 | SND_SOC_DAPM_MIXER("MIC1A V-AMICx Enable", | ||
596 | AB8500_ANACONF2, AB8500_ANACONF2_ENMIC1, 0, | ||
597 | NULL, 0), | ||
598 | SND_SOC_DAPM_MIXER("MIC1B V-AMICx Enable", | ||
599 | AB8500_ANACONF2, AB8500_ANACONF2_ENMIC1, 0, | ||
600 | NULL, 0), | ||
601 | SND_SOC_DAPM_MIXER("MIC1 ADC", | ||
602 | AB8500_ANACONF3, AB8500_ANACONF3_ENADCMIC, 0, | ||
603 | NULL, 0), | ||
604 | SND_SOC_DAPM_MUX("AD3 Source Select", | ||
605 | SND_SOC_NOPM, 0, 0, dapm_ad3_select), | ||
606 | SND_SOC_DAPM_MIXER("AD3 Channel Volume", | ||
607 | SND_SOC_NOPM, 0, 0, | ||
608 | NULL, 0), | ||
609 | SND_SOC_DAPM_MIXER("AD3 Enable", | ||
610 | AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD34, 0, | ||
611 | NULL, 0), | ||
612 | |||
613 | /* Mic 2 */ | ||
614 | |||
615 | SND_SOC_DAPM_INPUT("Mic 2"), | ||
616 | |||
617 | SND_SOC_DAPM_MIXER("MIC2 Mute", | ||
618 | AB8500_ANACONF2, AB8500_ANACONF2_MUTMIC2, 1, | ||
619 | NULL, 0), | ||
620 | SND_SOC_DAPM_MIXER("MIC2 V-AMICx Enable", AB8500_ANACONF2, | ||
621 | AB8500_ANACONF2_ENMIC2, 0, | ||
622 | NULL, 0), | ||
623 | |||
624 | /* LineIn */ | ||
625 | |||
626 | SND_SOC_DAPM_INPUT("LineIn Left"), | ||
627 | SND_SOC_DAPM_INPUT("LineIn Right"), | ||
628 | |||
629 | SND_SOC_DAPM_MIXER("LINL Mute", | ||
630 | AB8500_ANACONF2, AB8500_ANACONF2_MUTLINL, 1, | ||
631 | NULL, 0), | ||
632 | SND_SOC_DAPM_MIXER("LINR Mute", | ||
633 | AB8500_ANACONF2, AB8500_ANACONF2_MUTLINR, 1, | ||
634 | NULL, 0), | ||
635 | SND_SOC_DAPM_MIXER("LINL Enable", AB8500_ANACONF2, | ||
636 | AB8500_ANACONF2_ENLINL, 0, | ||
637 | NULL, 0), | ||
638 | SND_SOC_DAPM_MIXER("LINR Enable", AB8500_ANACONF2, | ||
639 | AB8500_ANACONF2_ENLINR, 0, | ||
640 | NULL, 0), | ||
641 | |||
642 | /* LineIn Bypass path */ | ||
643 | SND_SOC_DAPM_MIXER("LINL to HSL Volume", | ||
644 | SND_SOC_NOPM, 0, 0, | ||
645 | NULL, 0), | ||
646 | SND_SOC_DAPM_MIXER("LINR to HSR Volume", | ||
647 | SND_SOC_NOPM, 0, 0, | ||
648 | NULL, 0), | ||
649 | |||
650 | /* LineIn, Mic 2 */ | ||
651 | SND_SOC_DAPM_MUX("Mic 2 or LINR Select", | ||
652 | SND_SOC_NOPM, 0, 0, dapm_mic2lr_select), | ||
653 | SND_SOC_DAPM_MIXER("LINL ADC", AB8500_ANACONF3, | ||
654 | AB8500_ANACONF3_ENADCLINL, 0, | ||
655 | NULL, 0), | ||
656 | SND_SOC_DAPM_MIXER("LINR ADC", AB8500_ANACONF3, | ||
657 | AB8500_ANACONF3_ENADCLINR, 0, | ||
658 | NULL, 0), | ||
659 | SND_SOC_DAPM_MUX("AD1 Source Select", | ||
660 | SND_SOC_NOPM, 0, 0, dapm_ad1_select), | ||
661 | SND_SOC_DAPM_MUX("AD2 Source Select", | ||
662 | SND_SOC_NOPM, 0, 0, dapm_ad2_select), | ||
663 | SND_SOC_DAPM_MIXER("AD1 Channel Volume", | ||
664 | SND_SOC_NOPM, 0, 0, | ||
665 | NULL, 0), | ||
666 | SND_SOC_DAPM_MIXER("AD2 Channel Volume", | ||
667 | SND_SOC_NOPM, 0, 0, | ||
668 | NULL, 0), | ||
669 | |||
670 | SND_SOC_DAPM_MIXER("AD12 Enable", | ||
671 | AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD12, 0, | ||
672 | NULL, 0), | ||
673 | |||
674 | /* HD Capture path */ | ||
675 | |||
676 | SND_SOC_DAPM_MUX("AD5 Source Select", | ||
677 | SND_SOC_NOPM, 0, 0, dapm_ad5_select), | ||
678 | SND_SOC_DAPM_MUX("AD6 Source Select", | ||
679 | SND_SOC_NOPM, 0, 0, dapm_ad6_select), | ||
680 | SND_SOC_DAPM_MIXER("AD5 Channel Volume", | ||
681 | SND_SOC_NOPM, 0, 0, | ||
682 | NULL, 0), | ||
683 | SND_SOC_DAPM_MIXER("AD6 Channel Volume", | ||
684 | SND_SOC_NOPM, 0, 0, | ||
685 | NULL, 0), | ||
686 | SND_SOC_DAPM_MIXER("AD57 Enable", | ||
687 | AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD5768, 0, | ||
688 | NULL, 0), | ||
689 | SND_SOC_DAPM_MIXER("AD68 Enable", | ||
690 | AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD5768, 0, | ||
691 | NULL, 0), | ||
692 | |||
693 | /* Digital Microphone path */ | ||
694 | |||
695 | SND_SOC_DAPM_INPUT("DMic 1"), | ||
696 | SND_SOC_DAPM_INPUT("DMic 2"), | ||
697 | SND_SOC_DAPM_INPUT("DMic 3"), | ||
698 | SND_SOC_DAPM_INPUT("DMic 4"), | ||
699 | SND_SOC_DAPM_INPUT("DMic 5"), | ||
700 | SND_SOC_DAPM_INPUT("DMic 6"), | ||
701 | |||
702 | SND_SOC_DAPM_MIXER("DMIC1", | ||
703 | AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC1, 0, | ||
704 | NULL, 0), | ||
705 | SND_SOC_DAPM_MIXER("DMIC2", | ||
706 | AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC2, 0, | ||
707 | NULL, 0), | ||
708 | SND_SOC_DAPM_MIXER("DMIC3", | ||
709 | AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC3, 0, | ||
710 | NULL, 0), | ||
711 | SND_SOC_DAPM_MIXER("DMIC4", | ||
712 | AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC4, 0, | ||
713 | NULL, 0), | ||
714 | SND_SOC_DAPM_MIXER("DMIC5", | ||
715 | AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC5, 0, | ||
716 | NULL, 0), | ||
717 | SND_SOC_DAPM_MIXER("DMIC6", | ||
718 | AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC6, 0, | ||
719 | NULL, 0), | ||
720 | SND_SOC_DAPM_MIXER("AD4 Channel Volume", | ||
721 | SND_SOC_NOPM, 0, 0, | ||
722 | NULL, 0), | ||
723 | SND_SOC_DAPM_MIXER("AD4 Enable", | ||
724 | AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD34, | ||
725 | 0, NULL, 0), | ||
726 | |||
727 | /* Acoustical Noise Cancellation path */ | ||
728 | |||
729 | SND_SOC_DAPM_INPUT("ANC Configure Input"), | ||
730 | SND_SOC_DAPM_OUTPUT("ANC Configure Output"), | ||
731 | |||
732 | SND_SOC_DAPM_MUX("ANC Source", | ||
733 | SND_SOC_NOPM, 0, 0, | ||
734 | dapm_anc_in_select), | ||
735 | SND_SOC_DAPM_SWITCH("ANC", | ||
736 | SND_SOC_NOPM, 0, 0, | ||
737 | dapm_anc_enable), | ||
738 | SND_SOC_DAPM_SWITCH("ANC to Earpiece", | ||
739 | SND_SOC_NOPM, 0, 0, | ||
740 | dapm_anc_ear_mute), | ||
741 | |||
742 | /* Sidetone Filter path */ | ||
743 | |||
744 | SND_SOC_DAPM_MUX("Sidetone Left Source", | ||
745 | SND_SOC_NOPM, 0, 0, | ||
746 | dapm_stfir1_in_select), | ||
747 | SND_SOC_DAPM_MUX("Sidetone Right Source", | ||
748 | SND_SOC_NOPM, 0, 0, | ||
749 | dapm_stfir2_in_select), | ||
750 | SND_SOC_DAPM_MIXER("STFIR1 Control", | ||
751 | SND_SOC_NOPM, 0, 0, | ||
752 | NULL, 0), | ||
753 | SND_SOC_DAPM_MIXER("STFIR2 Control", | ||
754 | SND_SOC_NOPM, 0, 0, | ||
755 | NULL, 0), | ||
756 | SND_SOC_DAPM_MIXER("STFIR1 Volume", | ||
757 | SND_SOC_NOPM, 0, 0, | ||
758 | NULL, 0), | ||
759 | SND_SOC_DAPM_MIXER("STFIR2 Volume", | ||
760 | SND_SOC_NOPM, 0, 0, | ||
761 | NULL, 0), | ||
762 | }; | ||
763 | |||
764 | /* | ||
765 | * DAPM-routes | ||
766 | */ | ||
767 | static const struct snd_soc_dapm_route ab8500_dapm_routes[] = { | ||
768 | /* Power AB8500 audio-block when AD/DA is active */ | ||
769 | {"Main Supply", NULL, "V-AUD"}, | ||
770 | {"Main Supply", NULL, "audioclk"}, | ||
771 | {"Main Supply", NULL, "Audio Power"}, | ||
772 | {"Main Supply", NULL, "Audio Analog Power"}, | ||
773 | |||
774 | {"DAC", NULL, "ab8500_0p"}, | ||
775 | {"DAC", NULL, "Main Supply"}, | ||
776 | {"ADC", NULL, "ab8500_0c"}, | ||
777 | {"ADC", NULL, "Main Supply"}, | ||
778 | |||
779 | /* ANC Configure */ | ||
780 | {"ANC Configure Input", NULL, "Main Supply"}, | ||
781 | {"ANC Configure Output", NULL, "ANC Configure Input"}, | ||
782 | |||
783 | /* AD/DA */ | ||
784 | {"ADC", NULL, "ADC Input"}, | ||
785 | {"DAC Output", NULL, "DAC"}, | ||
786 | |||
787 | /* Powerup charge pump if DA1/2 is in use */ | ||
788 | |||
789 | {"DA_IN1", NULL, "ab8500_0p"}, | ||
790 | {"DA_IN1", NULL, "Charge Pump"}, | ||
791 | {"DA_IN2", NULL, "ab8500_0p"}, | ||
792 | {"DA_IN2", NULL, "Charge Pump"}, | ||
793 | |||
794 | /* Headset path */ | ||
795 | |||
796 | {"DA1 Enable", NULL, "DA_IN1"}, | ||
797 | {"DA2 Enable", NULL, "DA_IN2"}, | ||
798 | |||
799 | {"HSL Digital Volume", NULL, "DA1 Enable"}, | ||
800 | {"HSR Digital Volume", NULL, "DA2 Enable"}, | ||
801 | |||
802 | {"HSL DAC", NULL, "HSL Digital Volume"}, | ||
803 | {"HSR DAC", NULL, "HSR Digital Volume"}, | ||
804 | |||
805 | {"HSL DAC Mute", NULL, "HSL DAC"}, | ||
806 | {"HSR DAC Mute", NULL, "HSR DAC"}, | ||
807 | |||
808 | {"HSL DAC Driver", NULL, "HSL DAC Mute"}, | ||
809 | {"HSR DAC Driver", NULL, "HSR DAC Mute"}, | ||
810 | |||
811 | {"HSL Mute", NULL, "HSL DAC Driver"}, | ||
812 | {"HSR Mute", NULL, "HSR DAC Driver"}, | ||
813 | |||
814 | {"HSL Enable", NULL, "HSL Mute"}, | ||
815 | {"HSR Enable", NULL, "HSR Mute"}, | ||
816 | |||
817 | {"HSL Volume", NULL, "HSL Enable"}, | ||
818 | {"HSR Volume", NULL, "HSR Enable"}, | ||
819 | |||
820 | {"Headset Left", NULL, "HSL Volume"}, | ||
821 | {"Headset Right", NULL, "HSR Volume"}, | ||
822 | |||
823 | /* HF or LineOut path */ | ||
824 | |||
825 | {"DA_IN3", NULL, "ab8500_0p"}, | ||
826 | {"DA3 Channel Volume", NULL, "DA_IN3"}, | ||
827 | {"DA_IN4", NULL, "ab8500_0p"}, | ||
828 | {"DA4 Channel Volume", NULL, "DA_IN4"}, | ||
829 | |||
830 | {"Speaker Left Source", "Audio Path", "DA3 Channel Volume"}, | ||
831 | {"Speaker Right Source", "Audio Path", "DA4 Channel Volume"}, | ||
832 | |||
833 | {"DA3 or ANC path to HfL", NULL, "Speaker Left Source"}, | ||
834 | {"DA4 or ANC path to HfR", NULL, "Speaker Right Source"}, | ||
835 | |||
836 | /* HF path */ | ||
837 | |||
838 | {"HFL DAC", NULL, "DA3 or ANC path to HfL"}, | ||
839 | {"HFR DAC", NULL, "DA4 or ANC path to HfR"}, | ||
840 | |||
841 | {"HFL Enable", NULL, "HFL DAC"}, | ||
842 | {"HFR Enable", NULL, "HFR DAC"}, | ||
843 | |||
844 | {"Speaker Left", NULL, "HFL Enable"}, | ||
845 | {"Speaker Right", NULL, "HFR Enable"}, | ||
846 | |||
847 | /* Earpiece path */ | ||
848 | |||
849 | {"Earpiece or LineOut Mono Source", "Headset Left", | ||
850 | "HSL Digital Volume"}, | ||
851 | {"Earpiece or LineOut Mono Source", "Speaker Left", | ||
852 | "DA3 or ANC path to HfL"}, | ||
853 | |||
854 | {"EAR DAC", NULL, "Earpiece or LineOut Mono Source"}, | ||
855 | |||
856 | {"EAR Mute", NULL, "EAR DAC"}, | ||
857 | |||
858 | {"EAR Enable", NULL, "EAR Mute"}, | ||
859 | |||
860 | {"Earpiece", NULL, "EAR Enable"}, | ||
861 | |||
862 | /* LineOut path stereo */ | ||
863 | |||
864 | {"LineOut Source", "Stereo Path", "HSL DAC Driver"}, | ||
865 | {"LineOut Source", "Stereo Path", "HSR DAC Driver"}, | ||
866 | |||
867 | /* LineOut path mono */ | ||
868 | |||
869 | {"LineOut Source", "Mono Path", "EAR DAC"}, | ||
870 | |||
871 | /* LineOut path */ | ||
872 | |||
873 | {"LOL Disable HFL", NULL, "LineOut Source"}, | ||
874 | {"LOR Disable HFR", NULL, "LineOut Source"}, | ||
875 | |||
876 | {"LOL Enable", NULL, "LOL Disable HFL"}, | ||
877 | {"LOR Enable", NULL, "LOR Disable HFR"}, | ||
878 | |||
879 | {"LineOut Left", NULL, "LOL Enable"}, | ||
880 | {"LineOut Right", NULL, "LOR Enable"}, | ||
881 | |||
882 | /* Vibrator path */ | ||
883 | |||
884 | {"DA_IN5", NULL, "ab8500_0p"}, | ||
885 | {"DA5 Channel Volume", NULL, "DA_IN5"}, | ||
886 | {"DA_IN6", NULL, "ab8500_0p"}, | ||
887 | {"DA6 Channel Volume", NULL, "DA_IN6"}, | ||
888 | |||
889 | {"VIB1 DAC", NULL, "DA5 Channel Volume"}, | ||
890 | {"VIB2 DAC", NULL, "DA6 Channel Volume"}, | ||
891 | |||
892 | {"Vibra 1 Controller", "Audio Path", "VIB1 DAC"}, | ||
893 | {"Vibra 2 Controller", "Audio Path", "VIB2 DAC"}, | ||
894 | {"Vibra 1 Controller", "PWM Generator", "PWMGEN1"}, | ||
895 | {"Vibra 2 Controller", "PWM Generator", "PWMGEN2"}, | ||
896 | |||
897 | {"VIB1 Enable", NULL, "Vibra 1 Controller"}, | ||
898 | {"VIB2 Enable", NULL, "Vibra 2 Controller"}, | ||
899 | |||
900 | {"Vibra 1", NULL, "VIB1 Enable"}, | ||
901 | {"Vibra 2", NULL, "VIB2 Enable"}, | ||
902 | |||
903 | |||
904 | /* Mic 2 */ | ||
905 | |||
906 | {"MIC2 V-AMICx Enable", NULL, "Mic 2"}, | ||
907 | |||
908 | /* LineIn */ | ||
909 | {"LINL Mute", NULL, "LineIn Left"}, | ||
910 | {"LINR Mute", NULL, "LineIn Right"}, | ||
911 | |||
912 | {"LINL Enable", NULL, "LINL Mute"}, | ||
913 | {"LINR Enable", NULL, "LINR Mute"}, | ||
914 | |||
915 | /* LineIn, Mic 2 */ | ||
916 | {"Mic 2 or LINR Select", "LineIn Right", "LINR Enable"}, | ||
917 | {"Mic 2 or LINR Select", "Mic 2", "MIC2 V-AMICx Enable"}, | ||
918 | |||
919 | {"LINL ADC", NULL, "LINL Enable"}, | ||
920 | {"LINR ADC", NULL, "Mic 2 or LINR Select"}, | ||
921 | |||
922 | {"AD1 Source Select", "LineIn Left", "LINL ADC"}, | ||
923 | {"AD2 Source Select", "LineIn Right", "LINR ADC"}, | ||
924 | |||
925 | {"AD1 Channel Volume", NULL, "AD1 Source Select"}, | ||
926 | {"AD2 Channel Volume", NULL, "AD2 Source Select"}, | ||
927 | |||
928 | {"AD12 Enable", NULL, "AD1 Channel Volume"}, | ||
929 | {"AD12 Enable", NULL, "AD2 Channel Volume"}, | ||
930 | |||
931 | {"AD_OUT1", NULL, "ab8500_0c"}, | ||
932 | {"AD_OUT1", NULL, "AD12 Enable"}, | ||
933 | {"AD_OUT2", NULL, "ab8500_0c"}, | ||
934 | {"AD_OUT2", NULL, "AD12 Enable"}, | ||
935 | |||
936 | /* Mic 1 */ | ||
937 | |||
938 | {"MIC1 Mute", NULL, "Mic 1"}, | ||
939 | |||
940 | {"MIC1A V-AMICx Enable", NULL, "MIC1 Mute"}, | ||
941 | {"MIC1B V-AMICx Enable", NULL, "MIC1 Mute"}, | ||
942 | |||
943 | {"Mic 1a or 1b Select", "Mic 1a", "MIC1A V-AMICx Enable"}, | ||
944 | {"Mic 1a or 1b Select", "Mic 1b", "MIC1B V-AMICx Enable"}, | ||
945 | |||
946 | {"MIC1 ADC", NULL, "Mic 1a or 1b Select"}, | ||
947 | |||
948 | {"AD3 Source Select", "Mic 1", "MIC1 ADC"}, | ||
949 | |||
950 | {"AD3 Channel Volume", NULL, "AD3 Source Select"}, | ||
951 | |||
952 | {"AD3 Enable", NULL, "AD3 Channel Volume"}, | ||
953 | |||
954 | {"AD_OUT3", NULL, "ab8500_0c"}, | ||
955 | {"AD_OUT3", NULL, "AD3 Enable"}, | ||
956 | |||
957 | /* HD Capture path */ | ||
958 | |||
959 | {"AD5 Source Select", "Mic 2", "LINR ADC"}, | ||
960 | {"AD6 Source Select", "Mic 1", "MIC1 ADC"}, | ||
961 | |||
962 | {"AD5 Channel Volume", NULL, "AD5 Source Select"}, | ||
963 | {"AD6 Channel Volume", NULL, "AD6 Source Select"}, | ||
964 | |||
965 | {"AD57 Enable", NULL, "AD5 Channel Volume"}, | ||
966 | {"AD68 Enable", NULL, "AD6 Channel Volume"}, | ||
967 | |||
968 | {"AD_OUT57", NULL, "ab8500_0c"}, | ||
969 | {"AD_OUT57", NULL, "AD57 Enable"}, | ||
970 | {"AD_OUT68", NULL, "ab8500_0c"}, | ||
971 | {"AD_OUT68", NULL, "AD68 Enable"}, | ||
972 | |||
973 | /* Digital Microphone path */ | ||
974 | |||
975 | {"DMic 1", NULL, "V-DMIC"}, | ||
976 | {"DMic 2", NULL, "V-DMIC"}, | ||
977 | {"DMic 3", NULL, "V-DMIC"}, | ||
978 | {"DMic 4", NULL, "V-DMIC"}, | ||
979 | {"DMic 5", NULL, "V-DMIC"}, | ||
980 | {"DMic 6", NULL, "V-DMIC"}, | ||
981 | |||
982 | {"AD1 Source Select", NULL, "DMic 1"}, | ||
983 | {"AD2 Source Select", NULL, "DMic 2"}, | ||
984 | {"AD3 Source Select", NULL, "DMic 3"}, | ||
985 | {"AD5 Source Select", NULL, "DMic 5"}, | ||
986 | {"AD6 Source Select", NULL, "DMic 6"}, | ||
987 | |||
988 | {"AD4 Channel Volume", NULL, "DMic 4"}, | ||
989 | {"AD4 Enable", NULL, "AD4 Channel Volume"}, | ||
990 | |||
991 | {"AD_OUT4", NULL, "ab8500_0c"}, | ||
992 | {"AD_OUT4", NULL, "AD4 Enable"}, | ||
993 | |||
994 | /* LineIn Bypass path */ | ||
995 | |||
996 | {"LINL to HSL Volume", NULL, "LINL Enable"}, | ||
997 | {"LINR to HSR Volume", NULL, "LINR Enable"}, | ||
998 | |||
999 | {"HSL DAC Driver", NULL, "LINL to HSL Volume"}, | ||
1000 | {"HSR DAC Driver", NULL, "LINR to HSR Volume"}, | ||
1001 | |||
1002 | /* ANC path (Acoustic Noise Cancellation) */ | ||
1003 | |||
1004 | {"ANC Source", "Mic 2 / DMic 5", "AD5 Channel Volume"}, | ||
1005 | {"ANC Source", "Mic 1 / DMic 6", "AD6 Channel Volume"}, | ||
1006 | |||
1007 | {"ANC", "Switch", "ANC Source"}, | ||
1008 | |||
1009 | {"Speaker Left Source", "ANC", "ANC"}, | ||
1010 | {"Speaker Right Source", "ANC", "ANC"}, | ||
1011 | {"ANC to Earpiece", "Switch", "ANC"}, | ||
1012 | |||
1013 | {"HSL Digital Volume", NULL, "ANC to Earpiece"}, | ||
1014 | |||
1015 | /* Sidetone Filter path */ | ||
1016 | |||
1017 | {"Sidetone Left Source", "LineIn Left", "AD12 Enable"}, | ||
1018 | {"Sidetone Left Source", "LineIn Right", "AD12 Enable"}, | ||
1019 | {"Sidetone Left Source", "Mic 1", "AD3 Enable"}, | ||
1020 | {"Sidetone Left Source", "Headset Left", "DA_IN1"}, | ||
1021 | {"Sidetone Right Source", "LineIn Right", "AD12 Enable"}, | ||
1022 | {"Sidetone Right Source", "Mic 1", "AD3 Enable"}, | ||
1023 | {"Sidetone Right Source", "DMic 4", "AD4 Enable"}, | ||
1024 | {"Sidetone Right Source", "Headset Right", "DA_IN2"}, | ||
1025 | |||
1026 | {"STFIR1 Control", NULL, "Sidetone Left Source"}, | ||
1027 | {"STFIR2 Control", NULL, "Sidetone Right Source"}, | ||
1028 | |||
1029 | {"STFIR1 Volume", NULL, "STFIR1 Control"}, | ||
1030 | {"STFIR2 Volume", NULL, "STFIR2 Control"}, | ||
1031 | |||
1032 | {"DA1 Enable", NULL, "STFIR1 Volume"}, | ||
1033 | {"DA2 Enable", NULL, "STFIR2 Volume"}, | ||
1034 | }; | ||
1035 | |||
1036 | static const struct snd_soc_dapm_route ab8500_dapm_routes_mic1a_vamicx[] = { | ||
1037 | {"MIC1A V-AMICx Enable", NULL, "V-AMIC1"}, | ||
1038 | {"MIC1A V-AMICx Enable", NULL, "V-AMIC2"}, | ||
1039 | }; | ||
1040 | |||
1041 | static const struct snd_soc_dapm_route ab8500_dapm_routes_mic1b_vamicx[] = { | ||
1042 | {"MIC1B V-AMICx Enable", NULL, "V-AMIC1"}, | ||
1043 | {"MIC1B V-AMICx Enable", NULL, "V-AMIC2"}, | ||
1044 | }; | ||
1045 | |||
1046 | static const struct snd_soc_dapm_route ab8500_dapm_routes_mic2_vamicx[] = { | ||
1047 | {"MIC2 V-AMICx Enable", NULL, "V-AMIC1"}, | ||
1048 | {"MIC2 V-AMICx Enable", NULL, "V-AMIC2"}, | ||
1049 | }; | ||
1050 | |||
1051 | /* ANC FIR-coefficients configuration sequence */ | ||
1052 | static void anc_fir(struct snd_soc_codec *codec, | ||
1053 | unsigned int bnk, unsigned int par, unsigned int val) | ||
1054 | { | ||
1055 | if (par == 0 && bnk == 0) | ||
1056 | snd_soc_update_bits(codec, AB8500_ANCCONF1, | ||
1057 | BIT(AB8500_ANCCONF1_ANCFIRUPDATE), | ||
1058 | BIT(AB8500_ANCCONF1_ANCFIRUPDATE)); | ||
1059 | |||
1060 | snd_soc_write(codec, AB8500_ANCCONF5, val >> 8 & 0xff); | ||
1061 | snd_soc_write(codec, AB8500_ANCCONF6, val & 0xff); | ||
1062 | |||
1063 | if (par == AB8500_ANC_FIR_COEFFS - 1 && bnk == 1) | ||
1064 | snd_soc_update_bits(codec, AB8500_ANCCONF1, | ||
1065 | BIT(AB8500_ANCCONF1_ANCFIRUPDATE), 0); | ||
1066 | } | ||
1067 | |||
1068 | /* ANC IIR-coefficients configuration sequence */ | ||
1069 | static void anc_iir(struct snd_soc_codec *codec, unsigned int bnk, | ||
1070 | unsigned int par, unsigned int val) | ||
1071 | { | ||
1072 | if (par == 0) { | ||
1073 | if (bnk == 0) { | ||
1074 | snd_soc_update_bits(codec, AB8500_ANCCONF1, | ||
1075 | BIT(AB8500_ANCCONF1_ANCIIRINIT), | ||
1076 | BIT(AB8500_ANCCONF1_ANCIIRINIT)); | ||
1077 | usleep_range(AB8500_ANC_SM_DELAY, AB8500_ANC_SM_DELAY); | ||
1078 | snd_soc_update_bits(codec, AB8500_ANCCONF1, | ||
1079 | BIT(AB8500_ANCCONF1_ANCIIRINIT), 0); | ||
1080 | usleep_range(AB8500_ANC_SM_DELAY, AB8500_ANC_SM_DELAY); | ||
1081 | } else { | ||
1082 | snd_soc_update_bits(codec, AB8500_ANCCONF1, | ||
1083 | BIT(AB8500_ANCCONF1_ANCIIRUPDATE), | ||
1084 | BIT(AB8500_ANCCONF1_ANCIIRUPDATE)); | ||
1085 | } | ||
1086 | } else if (par > 3) { | ||
1087 | snd_soc_write(codec, AB8500_ANCCONF7, 0); | ||
1088 | snd_soc_write(codec, AB8500_ANCCONF8, val >> 16 & 0xff); | ||
1089 | } | ||
1090 | |||
1091 | snd_soc_write(codec, AB8500_ANCCONF7, val >> 8 & 0xff); | ||
1092 | snd_soc_write(codec, AB8500_ANCCONF8, val & 0xff); | ||
1093 | |||
1094 | if (par == AB8500_ANC_IIR_COEFFS - 1 && bnk == 1) | ||
1095 | snd_soc_update_bits(codec, AB8500_ANCCONF1, | ||
1096 | BIT(AB8500_ANCCONF1_ANCIIRUPDATE), 0); | ||
1097 | } | ||
1098 | |||
1099 | /* ANC IIR-/FIR-coefficients configuration sequence */ | ||
1100 | static void anc_configure(struct snd_soc_codec *codec, | ||
1101 | bool apply_fir, bool apply_iir) | ||
1102 | { | ||
1103 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | ||
1104 | unsigned int bnk, par, val; | ||
1105 | |||
1106 | dev_dbg(codec->dev, "%s: Enter.\n", __func__); | ||
1107 | |||
1108 | if (apply_fir) | ||
1109 | snd_soc_update_bits(codec, AB8500_ANCCONF1, | ||
1110 | BIT(AB8500_ANCCONF1_ENANC), 0); | ||
1111 | |||
1112 | snd_soc_update_bits(codec, AB8500_ANCCONF1, | ||
1113 | BIT(AB8500_ANCCONF1_ENANC), BIT(AB8500_ANCCONF1_ENANC)); | ||
1114 | |||
1115 | if (apply_fir) | ||
1116 | for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++) | ||
1117 | for (par = 0; par < AB8500_ANC_FIR_COEFFS; par++) { | ||
1118 | val = snd_soc_read(codec, | ||
1119 | drvdata->anc_fir_values[par]); | ||
1120 | anc_fir(codec, bnk, par, val); | ||
1121 | } | ||
1122 | |||
1123 | if (apply_iir) | ||
1124 | for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++) | ||
1125 | for (par = 0; par < AB8500_ANC_IIR_COEFFS; par++) { | ||
1126 | val = snd_soc_read(codec, | ||
1127 | drvdata->anc_iir_values[par]); | ||
1128 | anc_iir(codec, bnk, par, val); | ||
1129 | } | ||
1130 | |||
1131 | dev_dbg(codec->dev, "%s: Exit.\n", __func__); | ||
1132 | } | ||
1133 | |||
1134 | /* | ||
1135 | * Control-events | ||
1136 | */ | ||
1137 | |||
1138 | static int sid_status_control_get(struct snd_kcontrol *kcontrol, | ||
1139 | struct snd_ctl_elem_value *ucontrol) | ||
1140 | { | ||
1141 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1142 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | ||
1143 | |||
1144 | mutex_lock(&codec->mutex); | ||
1145 | ucontrol->value.integer.value[0] = drvdata->sid_status; | ||
1146 | mutex_unlock(&codec->mutex); | ||
1147 | |||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | /* Write sidetone FIR-coefficients configuration sequence */ | ||
1152 | static int sid_status_control_put(struct snd_kcontrol *kcontrol, | ||
1153 | struct snd_ctl_elem_value *ucontrol) | ||
1154 | { | ||
1155 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1156 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | ||
1157 | unsigned int param, sidconf, val; | ||
1158 | int status = 1; | ||
1159 | |||
1160 | dev_dbg(codec->dev, "%s: Enter\n", __func__); | ||
1161 | |||
1162 | if (ucontrol->value.integer.value[0] != SID_APPLY_FIR) { | ||
1163 | dev_err(codec->dev, | ||
1164 | "%s: ERROR: This control supports '%s' only!\n", | ||
1165 | __func__, enum_sid_state[SID_APPLY_FIR]); | ||
1166 | return -EIO; | ||
1167 | } | ||
1168 | |||
1169 | mutex_lock(&codec->mutex); | ||
1170 | |||
1171 | sidconf = snd_soc_read(codec, AB8500_SIDFIRCONF); | ||
1172 | if (((sidconf & BIT(AB8500_SIDFIRCONF_FIRSIDBUSY)) != 0)) { | ||
1173 | if ((sidconf & BIT(AB8500_SIDFIRCONF_ENFIRSIDS)) == 0) { | ||
1174 | dev_err(codec->dev, "%s: Sidetone busy while off!\n", | ||
1175 | __func__); | ||
1176 | status = -EPERM; | ||
1177 | } else { | ||
1178 | status = -EBUSY; | ||
1179 | } | ||
1180 | goto out; | ||
1181 | } | ||
1182 | |||
1183 | snd_soc_write(codec, AB8500_SIDFIRADR, 0); | ||
1184 | |||
1185 | for (param = 0; param < AB8500_SID_FIR_COEFFS; param++) { | ||
1186 | val = snd_soc_read(codec, drvdata->sid_fir_values[param]); | ||
1187 | snd_soc_write(codec, AB8500_SIDFIRCOEF1, val >> 8 & 0xff); | ||
1188 | snd_soc_write(codec, AB8500_SIDFIRCOEF2, val & 0xff); | ||
1189 | } | ||
1190 | |||
1191 | snd_soc_update_bits(codec, AB8500_SIDFIRADR, | ||
1192 | BIT(AB8500_SIDFIRADR_FIRSIDSET), | ||
1193 | BIT(AB8500_SIDFIRADR_FIRSIDSET)); | ||
1194 | snd_soc_update_bits(codec, AB8500_SIDFIRADR, | ||
1195 | BIT(AB8500_SIDFIRADR_FIRSIDSET), 0); | ||
1196 | |||
1197 | drvdata->sid_status = SID_FIR_CONFIGURED; | ||
1198 | |||
1199 | out: | ||
1200 | mutex_unlock(&codec->mutex); | ||
1201 | |||
1202 | dev_dbg(codec->dev, "%s: Exit\n", __func__); | ||
1203 | |||
1204 | return status; | ||
1205 | } | ||
1206 | |||
1207 | static int anc_status_control_get(struct snd_kcontrol *kcontrol, | ||
1208 | struct snd_ctl_elem_value *ucontrol) | ||
1209 | { | ||
1210 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1211 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | ||
1212 | |||
1213 | mutex_lock(&codec->mutex); | ||
1214 | ucontrol->value.integer.value[0] = drvdata->anc_status; | ||
1215 | mutex_unlock(&codec->mutex); | ||
1216 | |||
1217 | return 0; | ||
1218 | } | ||
1219 | |||
1220 | static int anc_status_control_put(struct snd_kcontrol *kcontrol, | ||
1221 | struct snd_ctl_elem_value *ucontrol) | ||
1222 | { | ||
1223 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1224 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | ||
1225 | struct device *dev = codec->dev; | ||
1226 | bool apply_fir, apply_iir; | ||
1227 | int req, status; | ||
1228 | |||
1229 | dev_dbg(dev, "%s: Enter.\n", __func__); | ||
1230 | |||
1231 | mutex_lock(&drvdata->anc_lock); | ||
1232 | |||
1233 | req = ucontrol->value.integer.value[0]; | ||
1234 | if (req != ANC_APPLY_FIR_IIR && req != ANC_APPLY_FIR && | ||
1235 | req != ANC_APPLY_IIR) { | ||
1236 | dev_err(dev, "%s: ERROR: Unsupported status to set '%s'!\n", | ||
1237 | __func__, enum_anc_state[req]); | ||
1238 | status = -EINVAL; | ||
1239 | goto cleanup; | ||
1240 | } | ||
1241 | apply_fir = req == ANC_APPLY_FIR || req == ANC_APPLY_FIR_IIR; | ||
1242 | apply_iir = req == ANC_APPLY_IIR || req == ANC_APPLY_FIR_IIR; | ||
1243 | |||
1244 | status = snd_soc_dapm_force_enable_pin(&codec->dapm, | ||
1245 | "ANC Configure Input"); | ||
1246 | if (status < 0) { | ||
1247 | dev_err(dev, | ||
1248 | "%s: ERROR: Failed to enable power (status = %d)!\n", | ||
1249 | __func__, status); | ||
1250 | goto cleanup; | ||
1251 | } | ||
1252 | snd_soc_dapm_sync(&codec->dapm); | ||
1253 | |||
1254 | mutex_lock(&codec->mutex); | ||
1255 | anc_configure(codec, apply_fir, apply_iir); | ||
1256 | mutex_unlock(&codec->mutex); | ||
1257 | |||
1258 | if (apply_fir) { | ||
1259 | if (drvdata->anc_status == ANC_IIR_CONFIGURED) | ||
1260 | drvdata->anc_status = ANC_FIR_IIR_CONFIGURED; | ||
1261 | else if (drvdata->anc_status != ANC_FIR_IIR_CONFIGURED) | ||
1262 | drvdata->anc_status = ANC_FIR_CONFIGURED; | ||
1263 | } | ||
1264 | if (apply_iir) { | ||
1265 | if (drvdata->anc_status == ANC_FIR_CONFIGURED) | ||
1266 | drvdata->anc_status = ANC_FIR_IIR_CONFIGURED; | ||
1267 | else if (drvdata->anc_status != ANC_FIR_IIR_CONFIGURED) | ||
1268 | drvdata->anc_status = ANC_IIR_CONFIGURED; | ||
1269 | } | ||
1270 | |||
1271 | status = snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input"); | ||
1272 | snd_soc_dapm_sync(&codec->dapm); | ||
1273 | |||
1274 | cleanup: | ||
1275 | mutex_unlock(&drvdata->anc_lock); | ||
1276 | |||
1277 | if (status < 0) | ||
1278 | dev_err(dev, "%s: Unable to configure ANC! (status = %d)\n", | ||
1279 | __func__, status); | ||
1280 | |||
1281 | dev_dbg(dev, "%s: Exit.\n", __func__); | ||
1282 | |||
1283 | return (status < 0) ? status : 1; | ||
1284 | } | ||
1285 | |||
1286 | static int filter_control_info(struct snd_kcontrol *kcontrol, | ||
1287 | struct snd_ctl_elem_info *uinfo) | ||
1288 | { | ||
1289 | struct filter_control *fc = | ||
1290 | (struct filter_control *)kcontrol->private_value; | ||
1291 | |||
1292 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1293 | uinfo->count = fc->count; | ||
1294 | uinfo->value.integer.min = fc->min; | ||
1295 | uinfo->value.integer.max = fc->max; | ||
1296 | |||
1297 | return 0; | ||
1298 | } | ||
1299 | |||
1300 | static int filter_control_get(struct snd_kcontrol *kcontrol, | ||
1301 | struct snd_ctl_elem_value *ucontrol) | ||
1302 | { | ||
1303 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1304 | struct filter_control *fc = | ||
1305 | (struct filter_control *)kcontrol->private_value; | ||
1306 | unsigned int i; | ||
1307 | |||
1308 | mutex_lock(&codec->mutex); | ||
1309 | for (i = 0; i < fc->count; i++) | ||
1310 | ucontrol->value.integer.value[i] = fc->value[i]; | ||
1311 | mutex_unlock(&codec->mutex); | ||
1312 | |||
1313 | return 0; | ||
1314 | } | ||
1315 | |||
1316 | static int filter_control_put(struct snd_kcontrol *kcontrol, | ||
1317 | struct snd_ctl_elem_value *ucontrol) | ||
1318 | { | ||
1319 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1320 | struct filter_control *fc = | ||
1321 | (struct filter_control *)kcontrol->private_value; | ||
1322 | unsigned int i; | ||
1323 | |||
1324 | mutex_lock(&codec->mutex); | ||
1325 | for (i = 0; i < fc->count; i++) | ||
1326 | fc->value[i] = ucontrol->value.integer.value[i]; | ||
1327 | mutex_unlock(&codec->mutex); | ||
1328 | |||
1329 | return 0; | ||
1330 | } | ||
1331 | |||
1332 | /* | ||
1333 | * Controls - Non-DAPM ASoC | ||
1334 | */ | ||
1335 | |||
1336 | static DECLARE_TLV_DB_SCALE(adx_dig_gain_tlv, -3200, 100, 1); | ||
1337 | /* -32dB = Mute */ | ||
1338 | |||
1339 | static DECLARE_TLV_DB_SCALE(dax_dig_gain_tlv, -6300, 100, 1); | ||
1340 | /* -63dB = Mute */ | ||
1341 | |||
1342 | static DECLARE_TLV_DB_SCALE(hs_ear_dig_gain_tlv, -100, 100, 1); | ||
1343 | /* -1dB = Mute */ | ||
1344 | |||
1345 | static const unsigned int hs_gain_tlv[] = { | ||
1346 | TLV_DB_RANGE_HEAD(2), | ||
1347 | 0, 3, TLV_DB_SCALE_ITEM(-3200, 400, 0), | ||
1348 | 4, 15, TLV_DB_SCALE_ITEM(-1800, 200, 0), | ||
1349 | }; | ||
1350 | |||
1351 | static DECLARE_TLV_DB_SCALE(mic_gain_tlv, 0, 100, 0); | ||
1352 | |||
1353 | static DECLARE_TLV_DB_SCALE(lin_gain_tlv, -1000, 200, 0); | ||
1354 | |||
1355 | static DECLARE_TLV_DB_SCALE(lin2hs_gain_tlv, -3800, 200, 1); | ||
1356 | /* -38dB = Mute */ | ||
1357 | |||
1358 | static const char * const enum_hsfadspeed[] = {"2ms", "0.5ms", "10.6ms", | ||
1359 | "5ms"}; | ||
1360 | static SOC_ENUM_SINGLE_DECL(soc_enum_hsfadspeed, | ||
1361 | AB8500_DIGMICCONF, AB8500_DIGMICCONF_HSFADSPEED, enum_hsfadspeed); | ||
1362 | |||
1363 | static const char * const enum_envdetthre[] = { | ||
1364 | "250mV", "300mV", "350mV", "400mV", | ||
1365 | "450mV", "500mV", "550mV", "600mV", | ||
1366 | "650mV", "700mV", "750mV", "800mV", | ||
1367 | "850mV", "900mV", "950mV", "1.00V" }; | ||
1368 | static SOC_ENUM_SINGLE_DECL(soc_enum_envdeththre, | ||
1369 | AB8500_ENVCPCONF, AB8500_ENVCPCONF_ENVDETHTHRE, enum_envdetthre); | ||
1370 | static SOC_ENUM_SINGLE_DECL(soc_enum_envdetlthre, | ||
1371 | AB8500_ENVCPCONF, AB8500_ENVCPCONF_ENVDETLTHRE, enum_envdetthre); | ||
1372 | static const char * const enum_envdettime[] = { | ||
1373 | "26.6us", "53.2us", "106us", "213us", | ||
1374 | "426us", "851us", "1.70ms", "3.40ms", | ||
1375 | "6.81ms", "13.6ms", "27.2ms", "54.5ms", | ||
1376 | "109ms", "218ms", "436ms", "872ms" }; | ||
1377 | static SOC_ENUM_SINGLE_DECL(soc_enum_envdettime, | ||
1378 | AB8500_SIGENVCONF, AB8500_SIGENVCONF_ENVDETTIME, enum_envdettime); | ||
1379 | |||
1380 | static const char * const enum_sinc31[] = {"Sinc 3", "Sinc 1"}; | ||
1381 | static SOC_ENUM_SINGLE_DECL(soc_enum_hsesinc, AB8500_HSLEARDIGGAIN, | ||
1382 | AB8500_HSLEARDIGGAIN_HSSINC1, enum_sinc31); | ||
1383 | |||
1384 | static const char * const enum_fadespeed[] = {"1ms", "4ms", "8ms", "16ms"}; | ||
1385 | static SOC_ENUM_SINGLE_DECL(soc_enum_fadespeed, AB8500_HSRDIGGAIN, | ||
1386 | AB8500_HSRDIGGAIN_FADESPEED, enum_fadespeed); | ||
1387 | |||
1388 | /* Earpiece */ | ||
1389 | |||
1390 | static const char * const enum_lowpow[] = {"Normal", "Low Power"}; | ||
1391 | static SOC_ENUM_SINGLE_DECL(soc_enum_eardaclowpow, AB8500_ANACONF1, | ||
1392 | AB8500_ANACONF1_EARDACLOWPOW, enum_lowpow); | ||
1393 | static SOC_ENUM_SINGLE_DECL(soc_enum_eardrvlowpow, AB8500_ANACONF1, | ||
1394 | AB8500_ANACONF1_EARDRVLOWPOW, enum_lowpow); | ||
1395 | |||
1396 | static const char * const enum_av_mode[] = {"Audio", "Voice"}; | ||
1397 | static SOC_ENUM_DOUBLE_DECL(soc_enum_ad12voice, AB8500_ADFILTCONF, | ||
1398 | AB8500_ADFILTCONF_AD1VOICE, AB8500_ADFILTCONF_AD2VOICE, enum_av_mode); | ||
1399 | static SOC_ENUM_DOUBLE_DECL(soc_enum_ad34voice, AB8500_ADFILTCONF, | ||
1400 | AB8500_ADFILTCONF_AD3VOICE, AB8500_ADFILTCONF_AD4VOICE, enum_av_mode); | ||
1401 | |||
1402 | /* DA */ | ||
1403 | |||
1404 | static SOC_ENUM_SINGLE_DECL(soc_enum_da12voice, | ||
1405 | AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_DA12VOICE, | ||
1406 | enum_av_mode); | ||
1407 | static SOC_ENUM_SINGLE_DECL(soc_enum_da34voice, | ||
1408 | AB8500_DASLOTCONF3, AB8500_DASLOTCONF3_DA34VOICE, | ||
1409 | enum_av_mode); | ||
1410 | static SOC_ENUM_SINGLE_DECL(soc_enum_da56voice, | ||
1411 | AB8500_DASLOTCONF5, AB8500_DASLOTCONF5_DA56VOICE, | ||
1412 | enum_av_mode); | ||
1413 | |||
1414 | static const char * const enum_da2hslr[] = {"Sidetone", "Audio Path"}; | ||
1415 | static SOC_ENUM_DOUBLE_DECL(soc_enum_da2hslr, AB8500_DIGMULTCONF1, | ||
1416 | AB8500_DIGMULTCONF1_DATOHSLEN, | ||
1417 | AB8500_DIGMULTCONF1_DATOHSREN, enum_da2hslr); | ||
1418 | |||
1419 | static const char * const enum_sinc53[] = {"Sinc 5", "Sinc 3"}; | ||
1420 | static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic12sinc, AB8500_DMICFILTCONF, | ||
1421 | AB8500_DMICFILTCONF_DMIC1SINC3, | ||
1422 | AB8500_DMICFILTCONF_DMIC2SINC3, enum_sinc53); | ||
1423 | static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic34sinc, AB8500_DMICFILTCONF, | ||
1424 | AB8500_DMICFILTCONF_DMIC3SINC3, | ||
1425 | AB8500_DMICFILTCONF_DMIC4SINC3, enum_sinc53); | ||
1426 | static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic56sinc, AB8500_DMICFILTCONF, | ||
1427 | AB8500_DMICFILTCONF_DMIC5SINC3, | ||
1428 | AB8500_DMICFILTCONF_DMIC6SINC3, enum_sinc53); | ||
1429 | |||
1430 | /* Digital interface - DA from slot mapping */ | ||
1431 | static const char * const enum_da_from_slot_map[] = {"SLOT0", | ||
1432 | "SLOT1", | ||
1433 | "SLOT2", | ||
1434 | "SLOT3", | ||
1435 | "SLOT4", | ||
1436 | "SLOT5", | ||
1437 | "SLOT6", | ||
1438 | "SLOT7", | ||
1439 | "SLOT8", | ||
1440 | "SLOT9", | ||
1441 | "SLOT10", | ||
1442 | "SLOT11", | ||
1443 | "SLOT12", | ||
1444 | "SLOT13", | ||
1445 | "SLOT14", | ||
1446 | "SLOT15", | ||
1447 | "SLOT16", | ||
1448 | "SLOT17", | ||
1449 | "SLOT18", | ||
1450 | "SLOT19", | ||
1451 | "SLOT20", | ||
1452 | "SLOT21", | ||
1453 | "SLOT22", | ||
1454 | "SLOT23", | ||
1455 | "SLOT24", | ||
1456 | "SLOT25", | ||
1457 | "SLOT26", | ||
1458 | "SLOT27", | ||
1459 | "SLOT28", | ||
1460 | "SLOT29", | ||
1461 | "SLOT30", | ||
1462 | "SLOT31"}; | ||
1463 | static SOC_ENUM_SINGLE_DECL(soc_enum_da1slotmap, | ||
1464 | AB8500_DASLOTCONF1, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | ||
1465 | enum_da_from_slot_map); | ||
1466 | static SOC_ENUM_SINGLE_DECL(soc_enum_da2slotmap, | ||
1467 | AB8500_DASLOTCONF2, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | ||
1468 | enum_da_from_slot_map); | ||
1469 | static SOC_ENUM_SINGLE_DECL(soc_enum_da3slotmap, | ||
1470 | AB8500_DASLOTCONF3, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | ||
1471 | enum_da_from_slot_map); | ||
1472 | static SOC_ENUM_SINGLE_DECL(soc_enum_da4slotmap, | ||
1473 | AB8500_DASLOTCONF4, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | ||
1474 | enum_da_from_slot_map); | ||
1475 | static SOC_ENUM_SINGLE_DECL(soc_enum_da5slotmap, | ||
1476 | AB8500_DASLOTCONF5, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | ||
1477 | enum_da_from_slot_map); | ||
1478 | static SOC_ENUM_SINGLE_DECL(soc_enum_da6slotmap, | ||
1479 | AB8500_DASLOTCONF6, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | ||
1480 | enum_da_from_slot_map); | ||
1481 | static SOC_ENUM_SINGLE_DECL(soc_enum_da7slotmap, | ||
1482 | AB8500_DASLOTCONF7, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | ||
1483 | enum_da_from_slot_map); | ||
1484 | static SOC_ENUM_SINGLE_DECL(soc_enum_da8slotmap, | ||
1485 | AB8500_DASLOTCONF8, AB8500_DASLOTCONFX_SLTODAX_SHIFT, | ||
1486 | enum_da_from_slot_map); | ||
1487 | |||
1488 | /* Digital interface - AD to slot mapping */ | ||
1489 | static const char * const enum_ad_to_slot_map[] = {"AD_OUT1", | ||
1490 | "AD_OUT2", | ||
1491 | "AD_OUT3", | ||
1492 | "AD_OUT4", | ||
1493 | "AD_OUT5", | ||
1494 | "AD_OUT6", | ||
1495 | "AD_OUT7", | ||
1496 | "AD_OUT8", | ||
1497 | "zeroes", | ||
1498 | "tristate"}; | ||
1499 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot0map, | ||
1500 | AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1501 | enum_ad_to_slot_map); | ||
1502 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot1map, | ||
1503 | AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1504 | enum_ad_to_slot_map); | ||
1505 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot2map, | ||
1506 | AB8500_ADSLOTSEL2, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1507 | enum_ad_to_slot_map); | ||
1508 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot3map, | ||
1509 | AB8500_ADSLOTSEL2, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1510 | enum_ad_to_slot_map); | ||
1511 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot4map, | ||
1512 | AB8500_ADSLOTSEL3, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1513 | enum_ad_to_slot_map); | ||
1514 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot5map, | ||
1515 | AB8500_ADSLOTSEL3, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1516 | enum_ad_to_slot_map); | ||
1517 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot6map, | ||
1518 | AB8500_ADSLOTSEL4, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1519 | enum_ad_to_slot_map); | ||
1520 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot7map, | ||
1521 | AB8500_ADSLOTSEL4, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1522 | enum_ad_to_slot_map); | ||
1523 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot8map, | ||
1524 | AB8500_ADSLOTSEL5, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1525 | enum_ad_to_slot_map); | ||
1526 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot9map, | ||
1527 | AB8500_ADSLOTSEL5, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1528 | enum_ad_to_slot_map); | ||
1529 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot10map, | ||
1530 | AB8500_ADSLOTSEL6, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1531 | enum_ad_to_slot_map); | ||
1532 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot11map, | ||
1533 | AB8500_ADSLOTSEL6, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1534 | enum_ad_to_slot_map); | ||
1535 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot12map, | ||
1536 | AB8500_ADSLOTSEL7, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1537 | enum_ad_to_slot_map); | ||
1538 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot13map, | ||
1539 | AB8500_ADSLOTSEL7, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1540 | enum_ad_to_slot_map); | ||
1541 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot14map, | ||
1542 | AB8500_ADSLOTSEL8, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1543 | enum_ad_to_slot_map); | ||
1544 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot15map, | ||
1545 | AB8500_ADSLOTSEL8, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1546 | enum_ad_to_slot_map); | ||
1547 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot16map, | ||
1548 | AB8500_ADSLOTSEL9, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1549 | enum_ad_to_slot_map); | ||
1550 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot17map, | ||
1551 | AB8500_ADSLOTSEL9, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1552 | enum_ad_to_slot_map); | ||
1553 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot18map, | ||
1554 | AB8500_ADSLOTSEL10, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1555 | enum_ad_to_slot_map); | ||
1556 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot19map, | ||
1557 | AB8500_ADSLOTSEL10, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1558 | enum_ad_to_slot_map); | ||
1559 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot20map, | ||
1560 | AB8500_ADSLOTSEL11, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1561 | enum_ad_to_slot_map); | ||
1562 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot21map, | ||
1563 | AB8500_ADSLOTSEL11, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1564 | enum_ad_to_slot_map); | ||
1565 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot22map, | ||
1566 | AB8500_ADSLOTSEL12, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1567 | enum_ad_to_slot_map); | ||
1568 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot23map, | ||
1569 | AB8500_ADSLOTSEL12, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1570 | enum_ad_to_slot_map); | ||
1571 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot24map, | ||
1572 | AB8500_ADSLOTSEL13, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1573 | enum_ad_to_slot_map); | ||
1574 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot25map, | ||
1575 | AB8500_ADSLOTSEL13, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1576 | enum_ad_to_slot_map); | ||
1577 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot26map, | ||
1578 | AB8500_ADSLOTSEL14, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1579 | enum_ad_to_slot_map); | ||
1580 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot27map, | ||
1581 | AB8500_ADSLOTSEL14, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1582 | enum_ad_to_slot_map); | ||
1583 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot28map, | ||
1584 | AB8500_ADSLOTSEL15, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1585 | enum_ad_to_slot_map); | ||
1586 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot29map, | ||
1587 | AB8500_ADSLOTSEL15, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1588 | enum_ad_to_slot_map); | ||
1589 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot30map, | ||
1590 | AB8500_ADSLOTSEL16, AB8500_ADSLOTSELX_EVEN_SHIFT, | ||
1591 | enum_ad_to_slot_map); | ||
1592 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot31map, | ||
1593 | AB8500_ADSLOTSEL16, AB8500_ADSLOTSELX_ODD_SHIFT, | ||
1594 | enum_ad_to_slot_map); | ||
1595 | |||
1596 | /* Digital interface - Burst mode */ | ||
1597 | static const char * const enum_mask[] = {"Unmasked", "Masked"}; | ||
1598 | static SOC_ENUM_SINGLE_DECL(soc_enum_bfifomask, | ||
1599 | AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFOMASK, | ||
1600 | enum_mask); | ||
1601 | static const char * const enum_bitclk0[] = {"19_2_MHz", "38_4_MHz"}; | ||
1602 | static SOC_ENUM_SINGLE_DECL(soc_enum_bfifo19m2, | ||
1603 | AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFO19M2, | ||
1604 | enum_bitclk0); | ||
1605 | static const char * const enum_slavemaster[] = {"Slave", "Master"}; | ||
1606 | static SOC_ENUM_SINGLE_DECL(soc_enum_bfifomast, | ||
1607 | AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFOMAST_SHIFT, | ||
1608 | enum_slavemaster); | ||
1609 | |||
1610 | /* Sidetone */ | ||
1611 | static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_sidstate, enum_sid_state); | ||
1612 | |||
1613 | /* ANC */ | ||
1614 | static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_ancstate, enum_anc_state); | ||
1615 | |||
1616 | static struct snd_kcontrol_new ab8500_ctrls[] = { | ||
1617 | /* Charge pump */ | ||
1618 | SOC_ENUM("Charge Pump High Threshold For Low Voltage", | ||
1619 | soc_enum_envdeththre), | ||
1620 | SOC_ENUM("Charge Pump Low Threshold For Low Voltage", | ||
1621 | soc_enum_envdetlthre), | ||
1622 | SOC_SINGLE("Charge Pump Envelope Detection Switch", | ||
1623 | AB8500_SIGENVCONF, AB8500_SIGENVCONF_ENVDETCPEN, | ||
1624 | 1, 0), | ||
1625 | SOC_ENUM("Charge Pump Envelope Detection Decay Time", | ||
1626 | soc_enum_envdettime), | ||
1627 | |||
1628 | /* Headset */ | ||
1629 | SOC_ENUM("Headset Mode", soc_enum_da12voice), | ||
1630 | SOC_SINGLE("Headset High Pass Switch", | ||
1631 | AB8500_ANACONF1, AB8500_ANACONF1_HSHPEN, | ||
1632 | 1, 0), | ||
1633 | SOC_SINGLE("Headset Low Power Switch", | ||
1634 | AB8500_ANACONF1, AB8500_ANACONF1_HSLOWPOW, | ||
1635 | 1, 0), | ||
1636 | SOC_SINGLE("Headset DAC Low Power Switch", | ||
1637 | AB8500_ANACONF1, AB8500_ANACONF1_DACLOWPOW1, | ||
1638 | 1, 0), | ||
1639 | SOC_SINGLE("Headset DAC Drv Low Power Switch", | ||
1640 | AB8500_ANACONF1, AB8500_ANACONF1_DACLOWPOW0, | ||
1641 | 1, 0), | ||
1642 | SOC_ENUM("Headset Fade Speed", soc_enum_hsfadspeed), | ||
1643 | SOC_ENUM("Headset Source", soc_enum_da2hslr), | ||
1644 | SOC_ENUM("Headset Filter", soc_enum_hsesinc), | ||
1645 | SOC_DOUBLE_R_TLV("Headset Master Volume", | ||
1646 | AB8500_DADIGGAIN1, AB8500_DADIGGAIN2, | ||
1647 | 0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv), | ||
1648 | SOC_DOUBLE_R_TLV("Headset Digital Volume", | ||
1649 | AB8500_HSLEARDIGGAIN, AB8500_HSRDIGGAIN, | ||
1650 | 0, AB8500_HSLEARDIGGAIN_HSLDGAIN_MAX, 1, hs_ear_dig_gain_tlv), | ||
1651 | SOC_DOUBLE_TLV("Headset Volume", | ||
1652 | AB8500_ANAGAIN3, | ||
1653 | AB8500_ANAGAIN3_HSLGAIN, AB8500_ANAGAIN3_HSRGAIN, | ||
1654 | AB8500_ANAGAIN3_HSXGAIN_MAX, 1, hs_gain_tlv), | ||
1655 | |||
1656 | /* Earpiece */ | ||
1657 | SOC_ENUM("Earpiece DAC Mode", | ||
1658 | soc_enum_eardaclowpow), | ||
1659 | SOC_ENUM("Earpiece DAC Drv Mode", | ||
1660 | soc_enum_eardrvlowpow), | ||
1661 | |||
1662 | /* HandsFree */ | ||
1663 | SOC_ENUM("HF Mode", soc_enum_da34voice), | ||
1664 | SOC_SINGLE("HF and Headset Swap Switch", | ||
1665 | AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_SWAPDA12_34, | ||
1666 | 1, 0), | ||
1667 | SOC_DOUBLE("HF Low EMI Mode Switch", | ||
1668 | AB8500_CLASSDCONF1, | ||
1669 | AB8500_CLASSDCONF1_HFLSWAPEN, AB8500_CLASSDCONF1_HFRSWAPEN, | ||
1670 | 1, 0), | ||
1671 | SOC_DOUBLE("HF FIR Bypass Switch", | ||
1672 | AB8500_CLASSDCONF2, | ||
1673 | AB8500_CLASSDCONF2_FIRBYP0, AB8500_CLASSDCONF2_FIRBYP1, | ||
1674 | 1, 0), | ||
1675 | SOC_DOUBLE("HF High Volume Switch", | ||
1676 | AB8500_CLASSDCONF2, | ||
1677 | AB8500_CLASSDCONF2_HIGHVOLEN0, AB8500_CLASSDCONF2_HIGHVOLEN1, | ||
1678 | 1, 0), | ||
1679 | SOC_SINGLE("HF L and R Bridge Switch", | ||
1680 | AB8500_CLASSDCONF1, AB8500_CLASSDCONF1_PARLHF, | ||
1681 | 1, 0), | ||
1682 | SOC_DOUBLE_R_TLV("HF Master Volume", | ||
1683 | AB8500_DADIGGAIN3, AB8500_DADIGGAIN4, | ||
1684 | 0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv), | ||
1685 | |||
1686 | /* Vibra */ | ||
1687 | SOC_DOUBLE("Vibra High Volume Switch", | ||
1688 | AB8500_CLASSDCONF2, | ||
1689 | AB8500_CLASSDCONF2_HIGHVOLEN2, AB8500_CLASSDCONF2_HIGHVOLEN3, | ||
1690 | 1, 0), | ||
1691 | SOC_DOUBLE("Vibra Low EMI Mode Switch", | ||
1692 | AB8500_CLASSDCONF1, | ||
1693 | AB8500_CLASSDCONF1_VIB1SWAPEN, AB8500_CLASSDCONF1_VIB2SWAPEN, | ||
1694 | 1, 0), | ||
1695 | SOC_DOUBLE("Vibra FIR Bypass Switch", | ||
1696 | AB8500_CLASSDCONF2, | ||
1697 | AB8500_CLASSDCONF2_FIRBYP2, AB8500_CLASSDCONF2_FIRBYP3, | ||
1698 | 1, 0), | ||
1699 | SOC_ENUM("Vibra Mode", soc_enum_da56voice), | ||
1700 | SOC_DOUBLE_R("Vibra PWM Duty Cycle N", | ||
1701 | AB8500_PWMGENCONF3, AB8500_PWMGENCONF5, | ||
1702 | AB8500_PWMGENCONFX_PWMVIBXDUTCYC, | ||
1703 | AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX, 0), | ||
1704 | SOC_DOUBLE_R("Vibra PWM Duty Cycle P", | ||
1705 | AB8500_PWMGENCONF2, AB8500_PWMGENCONF4, | ||
1706 | AB8500_PWMGENCONFX_PWMVIBXDUTCYC, | ||
1707 | AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX, 0), | ||
1708 | SOC_SINGLE("Vibra 1 and 2 Bridge Switch", | ||
1709 | AB8500_CLASSDCONF1, AB8500_CLASSDCONF1_PARLVIB, | ||
1710 | 1, 0), | ||
1711 | SOC_DOUBLE_R_TLV("Vibra Master Volume", | ||
1712 | AB8500_DADIGGAIN5, AB8500_DADIGGAIN6, | ||
1713 | 0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv), | ||
1714 | |||
1715 | /* HandsFree, Vibra */ | ||
1716 | SOC_SINGLE("ClassD High Pass Volume", | ||
1717 | AB8500_CLASSDCONF3, AB8500_CLASSDCONF3_DITHHPGAIN, | ||
1718 | AB8500_CLASSDCONF3_DITHHPGAIN_MAX, 0), | ||
1719 | SOC_SINGLE("ClassD White Volume", | ||
1720 | AB8500_CLASSDCONF3, AB8500_CLASSDCONF3_DITHWGAIN, | ||
1721 | AB8500_CLASSDCONF3_DITHWGAIN_MAX, 0), | ||
1722 | |||
1723 | /* Mic 1, Mic 2, LineIn */ | ||
1724 | SOC_DOUBLE_R_TLV("Mic Master Volume", | ||
1725 | AB8500_ADDIGGAIN3, AB8500_ADDIGGAIN4, | ||
1726 | 0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv), | ||
1727 | |||
1728 | /* Mic 1 */ | ||
1729 | SOC_SINGLE_TLV("Mic 1", | ||
1730 | AB8500_ANAGAIN1, | ||
1731 | AB8500_ANAGAINX_MICXGAIN, | ||
1732 | AB8500_ANAGAINX_MICXGAIN_MAX, 0, mic_gain_tlv), | ||
1733 | SOC_SINGLE("Mic 1 Low Power Switch", | ||
1734 | AB8500_ANAGAIN1, AB8500_ANAGAINX_LOWPOWMICX, | ||
1735 | 1, 0), | ||
1736 | |||
1737 | /* Mic 2 */ | ||
1738 | SOC_DOUBLE("Mic High Pass Switch", | ||
1739 | AB8500_ADFILTCONF, | ||
1740 | AB8500_ADFILTCONF_AD3NH, AB8500_ADFILTCONF_AD4NH, | ||
1741 | 1, 1), | ||
1742 | SOC_ENUM("Mic Mode", soc_enum_ad34voice), | ||
1743 | SOC_ENUM("Mic Filter", soc_enum_dmic34sinc), | ||
1744 | SOC_SINGLE_TLV("Mic 2", | ||
1745 | AB8500_ANAGAIN2, | ||
1746 | AB8500_ANAGAINX_MICXGAIN, | ||
1747 | AB8500_ANAGAINX_MICXGAIN_MAX, 0, mic_gain_tlv), | ||
1748 | SOC_SINGLE("Mic 2 Low Power Switch", | ||
1749 | AB8500_ANAGAIN2, AB8500_ANAGAINX_LOWPOWMICX, | ||
1750 | 1, 0), | ||
1751 | |||
1752 | /* LineIn */ | ||
1753 | SOC_DOUBLE("LineIn High Pass Switch", | ||
1754 | AB8500_ADFILTCONF, | ||
1755 | AB8500_ADFILTCONF_AD1NH, AB8500_ADFILTCONF_AD2NH, | ||
1756 | 1, 1), | ||
1757 | SOC_ENUM("LineIn Filter", soc_enum_dmic12sinc), | ||
1758 | SOC_ENUM("LineIn Mode", soc_enum_ad12voice), | ||
1759 | SOC_DOUBLE_R_TLV("LineIn Master Volume", | ||
1760 | AB8500_ADDIGGAIN1, AB8500_ADDIGGAIN2, | ||
1761 | 0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv), | ||
1762 | SOC_DOUBLE_TLV("LineIn", | ||
1763 | AB8500_ANAGAIN4, | ||
1764 | AB8500_ANAGAIN4_LINLGAIN, AB8500_ANAGAIN4_LINRGAIN, | ||
1765 | AB8500_ANAGAIN4_LINXGAIN_MAX, 0, lin_gain_tlv), | ||
1766 | SOC_DOUBLE_R_TLV("LineIn to Headset Volume", | ||
1767 | AB8500_DIGLINHSLGAIN, AB8500_DIGLINHSRGAIN, | ||
1768 | AB8500_DIGLINHSXGAIN_LINTOHSXGAIN, | ||
1769 | AB8500_DIGLINHSXGAIN_LINTOHSXGAIN_MAX, | ||
1770 | 1, lin2hs_gain_tlv), | ||
1771 | |||
1772 | /* DMic */ | ||
1773 | SOC_ENUM("DMic Filter", soc_enum_dmic56sinc), | ||
1774 | SOC_DOUBLE_R_TLV("DMic Master Volume", | ||
1775 | AB8500_ADDIGGAIN5, AB8500_ADDIGGAIN6, | ||
1776 | 0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv), | ||
1777 | |||
1778 | /* Digital gains */ | ||
1779 | SOC_ENUM("Digital Gain Fade Speed", soc_enum_fadespeed), | ||
1780 | |||
1781 | /* Analog loopback */ | ||
1782 | SOC_DOUBLE_R_TLV("Analog Loopback Volume", | ||
1783 | AB8500_ADDIGLOOPGAIN1, AB8500_ADDIGLOOPGAIN2, | ||
1784 | 0, AB8500_ADDIGLOOPGAINX_ADXLBGAIN_MAX, 1, dax_dig_gain_tlv), | ||
1785 | |||
1786 | /* Digital interface - DA from slot mapping */ | ||
1787 | SOC_ENUM("Digital Interface DA 1 From Slot Map", soc_enum_da1slotmap), | ||
1788 | SOC_ENUM("Digital Interface DA 2 From Slot Map", soc_enum_da2slotmap), | ||
1789 | SOC_ENUM("Digital Interface DA 3 From Slot Map", soc_enum_da3slotmap), | ||
1790 | SOC_ENUM("Digital Interface DA 4 From Slot Map", soc_enum_da4slotmap), | ||
1791 | SOC_ENUM("Digital Interface DA 5 From Slot Map", soc_enum_da5slotmap), | ||
1792 | SOC_ENUM("Digital Interface DA 6 From Slot Map", soc_enum_da6slotmap), | ||
1793 | SOC_ENUM("Digital Interface DA 7 From Slot Map", soc_enum_da7slotmap), | ||
1794 | SOC_ENUM("Digital Interface DA 8 From Slot Map", soc_enum_da8slotmap), | ||
1795 | |||
1796 | /* Digital interface - AD to slot mapping */ | ||
1797 | SOC_ENUM("Digital Interface AD To Slot 0 Map", soc_enum_adslot0map), | ||
1798 | SOC_ENUM("Digital Interface AD To Slot 1 Map", soc_enum_adslot1map), | ||
1799 | SOC_ENUM("Digital Interface AD To Slot 2 Map", soc_enum_adslot2map), | ||
1800 | SOC_ENUM("Digital Interface AD To Slot 3 Map", soc_enum_adslot3map), | ||
1801 | SOC_ENUM("Digital Interface AD To Slot 4 Map", soc_enum_adslot4map), | ||
1802 | SOC_ENUM("Digital Interface AD To Slot 5 Map", soc_enum_adslot5map), | ||
1803 | SOC_ENUM("Digital Interface AD To Slot 6 Map", soc_enum_adslot6map), | ||
1804 | SOC_ENUM("Digital Interface AD To Slot 7 Map", soc_enum_adslot7map), | ||
1805 | SOC_ENUM("Digital Interface AD To Slot 8 Map", soc_enum_adslot8map), | ||
1806 | SOC_ENUM("Digital Interface AD To Slot 9 Map", soc_enum_adslot9map), | ||
1807 | SOC_ENUM("Digital Interface AD To Slot 10 Map", soc_enum_adslot10map), | ||
1808 | SOC_ENUM("Digital Interface AD To Slot 11 Map", soc_enum_adslot11map), | ||
1809 | SOC_ENUM("Digital Interface AD To Slot 12 Map", soc_enum_adslot12map), | ||
1810 | SOC_ENUM("Digital Interface AD To Slot 13 Map", soc_enum_adslot13map), | ||
1811 | SOC_ENUM("Digital Interface AD To Slot 14 Map", soc_enum_adslot14map), | ||
1812 | SOC_ENUM("Digital Interface AD To Slot 15 Map", soc_enum_adslot15map), | ||
1813 | SOC_ENUM("Digital Interface AD To Slot 16 Map", soc_enum_adslot16map), | ||
1814 | SOC_ENUM("Digital Interface AD To Slot 17 Map", soc_enum_adslot17map), | ||
1815 | SOC_ENUM("Digital Interface AD To Slot 18 Map", soc_enum_adslot18map), | ||
1816 | SOC_ENUM("Digital Interface AD To Slot 19 Map", soc_enum_adslot19map), | ||
1817 | SOC_ENUM("Digital Interface AD To Slot 20 Map", soc_enum_adslot20map), | ||
1818 | SOC_ENUM("Digital Interface AD To Slot 21 Map", soc_enum_adslot21map), | ||
1819 | SOC_ENUM("Digital Interface AD To Slot 22 Map", soc_enum_adslot22map), | ||
1820 | SOC_ENUM("Digital Interface AD To Slot 23 Map", soc_enum_adslot23map), | ||
1821 | SOC_ENUM("Digital Interface AD To Slot 24 Map", soc_enum_adslot24map), | ||
1822 | SOC_ENUM("Digital Interface AD To Slot 25 Map", soc_enum_adslot25map), | ||
1823 | SOC_ENUM("Digital Interface AD To Slot 26 Map", soc_enum_adslot26map), | ||
1824 | SOC_ENUM("Digital Interface AD To Slot 27 Map", soc_enum_adslot27map), | ||
1825 | SOC_ENUM("Digital Interface AD To Slot 28 Map", soc_enum_adslot28map), | ||
1826 | SOC_ENUM("Digital Interface AD To Slot 29 Map", soc_enum_adslot29map), | ||
1827 | SOC_ENUM("Digital Interface AD To Slot 30 Map", soc_enum_adslot30map), | ||
1828 | SOC_ENUM("Digital Interface AD To Slot 31 Map", soc_enum_adslot31map), | ||
1829 | |||
1830 | /* Digital interface - Loopback */ | ||
1831 | SOC_SINGLE("Digital Interface AD 1 Loopback Switch", | ||
1832 | AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_DAI7TOADO1, | ||
1833 | 1, 0), | ||
1834 | SOC_SINGLE("Digital Interface AD 2 Loopback Switch", | ||
1835 | AB8500_DASLOTCONF2, AB8500_DASLOTCONF2_DAI8TOADO2, | ||
1836 | 1, 0), | ||
1837 | SOC_SINGLE("Digital Interface AD 3 Loopback Switch", | ||
1838 | AB8500_DASLOTCONF3, AB8500_DASLOTCONF3_DAI7TOADO3, | ||
1839 | 1, 0), | ||
1840 | SOC_SINGLE("Digital Interface AD 4 Loopback Switch", | ||
1841 | AB8500_DASLOTCONF4, AB8500_DASLOTCONF4_DAI8TOADO4, | ||
1842 | 1, 0), | ||
1843 | SOC_SINGLE("Digital Interface AD 5 Loopback Switch", | ||
1844 | AB8500_DASLOTCONF5, AB8500_DASLOTCONF5_DAI7TOADO5, | ||
1845 | 1, 0), | ||
1846 | SOC_SINGLE("Digital Interface AD 6 Loopback Switch", | ||
1847 | AB8500_DASLOTCONF6, AB8500_DASLOTCONF6_DAI8TOADO6, | ||
1848 | 1, 0), | ||
1849 | SOC_SINGLE("Digital Interface AD 7 Loopback Switch", | ||
1850 | AB8500_DASLOTCONF7, AB8500_DASLOTCONF7_DAI8TOADO7, | ||
1851 | 1, 0), | ||
1852 | SOC_SINGLE("Digital Interface AD 8 Loopback Switch", | ||
1853 | AB8500_DASLOTCONF8, AB8500_DASLOTCONF8_DAI7TOADO8, | ||
1854 | 1, 0), | ||
1855 | |||
1856 | /* Digital interface - Burst FIFO */ | ||
1857 | SOC_SINGLE("Digital Interface 0 FIFO Enable Switch", | ||
1858 | AB8500_DIGIFCONF3, AB8500_DIGIFCONF3_IF0BFIFOEN, | ||
1859 | 1, 0), | ||
1860 | SOC_ENUM("Burst FIFO Mask", soc_enum_bfifomask), | ||
1861 | SOC_ENUM("Burst FIFO Bit-clock Frequency", soc_enum_bfifo19m2), | ||
1862 | SOC_SINGLE("Burst FIFO Threshold", | ||
1863 | AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFOINT_SHIFT, | ||
1864 | AB8500_FIFOCONF1_BFIFOINT_MAX, 0), | ||
1865 | SOC_SINGLE("Burst FIFO Length", | ||
1866 | AB8500_FIFOCONF2, AB8500_FIFOCONF2_BFIFOTX_SHIFT, | ||
1867 | AB8500_FIFOCONF2_BFIFOTX_MAX, 0), | ||
1868 | SOC_SINGLE("Burst FIFO EOS Extra Slots", | ||
1869 | AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFOEXSL_SHIFT, | ||
1870 | AB8500_FIFOCONF3_BFIFOEXSL_MAX, 0), | ||
1871 | SOC_SINGLE("Burst FIFO FS Extra Bit-clocks", | ||
1872 | AB8500_FIFOCONF3, AB8500_FIFOCONF3_PREBITCLK0_SHIFT, | ||
1873 | AB8500_FIFOCONF3_PREBITCLK0_MAX, 0), | ||
1874 | SOC_ENUM("Burst FIFO Interface Mode", soc_enum_bfifomast), | ||
1875 | |||
1876 | SOC_SINGLE("Burst FIFO Interface Switch", | ||
1877 | AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFORUN_SHIFT, | ||
1878 | 1, 0), | ||
1879 | SOC_SINGLE("Burst FIFO Switch Frame Number", | ||
1880 | AB8500_FIFOCONF4, AB8500_FIFOCONF4_BFIFOFRAMSW_SHIFT, | ||
1881 | AB8500_FIFOCONF4_BFIFOFRAMSW_MAX, 0), | ||
1882 | SOC_SINGLE("Burst FIFO Wake Up Delay", | ||
1883 | AB8500_FIFOCONF5, AB8500_FIFOCONF5_BFIFOWAKEUP_SHIFT, | ||
1884 | AB8500_FIFOCONF5_BFIFOWAKEUP_MAX, 0), | ||
1885 | SOC_SINGLE("Burst FIFO Samples In FIFO", | ||
1886 | AB8500_FIFOCONF6, AB8500_FIFOCONF6_BFIFOSAMPLE_SHIFT, | ||
1887 | AB8500_FIFOCONF6_BFIFOSAMPLE_MAX, 0), | ||
1888 | |||
1889 | /* ANC */ | ||
1890 | SOC_ENUM_EXT("ANC Status", soc_enum_ancstate, | ||
1891 | anc_status_control_get, anc_status_control_put), | ||
1892 | SOC_SINGLE_XR_SX("ANC Warp Delay Shift", | ||
1893 | AB8500_ANCCONF2, 1, AB8500_ANCCONF2_SHIFT, | ||
1894 | AB8500_ANCCONF2_MIN, AB8500_ANCCONF2_MAX, 0), | ||
1895 | SOC_SINGLE_XR_SX("ANC FIR Output Shift", | ||
1896 | AB8500_ANCCONF3, 1, AB8500_ANCCONF3_SHIFT, | ||
1897 | AB8500_ANCCONF3_MIN, AB8500_ANCCONF3_MAX, 0), | ||
1898 | SOC_SINGLE_XR_SX("ANC IIR Output Shift", | ||
1899 | AB8500_ANCCONF4, 1, AB8500_ANCCONF4_SHIFT, | ||
1900 | AB8500_ANCCONF4_MIN, AB8500_ANCCONF4_MAX, 0), | ||
1901 | SOC_SINGLE_XR_SX("ANC Warp Delay", | ||
1902 | AB8500_ANCCONF9, 2, AB8500_ANC_WARP_DELAY_SHIFT, | ||
1903 | AB8500_ANC_WARP_DELAY_MIN, AB8500_ANC_WARP_DELAY_MAX, 0), | ||
1904 | |||
1905 | /* Sidetone */ | ||
1906 | SOC_ENUM_EXT("Sidetone Status", soc_enum_sidstate, | ||
1907 | sid_status_control_get, sid_status_control_put), | ||
1908 | SOC_SINGLE_STROBE("Sidetone Reset", | ||
1909 | AB8500_SIDFIRADR, AB8500_SIDFIRADR_FIRSIDSET, 0), | ||
1910 | }; | ||
1911 | |||
1912 | static struct snd_kcontrol_new ab8500_filter_controls[] = { | ||
1913 | AB8500_FILTER_CONTROL("ANC FIR Coefficients", AB8500_ANC_FIR_COEFFS, | ||
1914 | AB8500_ANC_FIR_COEFF_MIN, AB8500_ANC_FIR_COEFF_MAX), | ||
1915 | AB8500_FILTER_CONTROL("ANC IIR Coefficients", AB8500_ANC_IIR_COEFFS, | ||
1916 | AB8500_ANC_IIR_COEFF_MIN, AB8500_ANC_IIR_COEFF_MAX), | ||
1917 | AB8500_FILTER_CONTROL("Sidetone FIR Coefficients", | ||
1918 | AB8500_SID_FIR_COEFFS, AB8500_SID_FIR_COEFF_MIN, | ||
1919 | AB8500_SID_FIR_COEFF_MAX) | ||
1920 | }; | ||
1921 | enum ab8500_filter { | ||
1922 | AB8500_FILTER_ANC_FIR = 0, | ||
1923 | AB8500_FILTER_ANC_IIR = 1, | ||
1924 | AB8500_FILTER_SID_FIR = 2, | ||
1925 | }; | ||
1926 | |||
1927 | /* | ||
1928 | * Extended interface for codec-driver | ||
1929 | */ | ||
1930 | |||
1931 | static int ab8500_audio_init_audioblock(struct snd_soc_codec *codec) | ||
1932 | { | ||
1933 | int status; | ||
1934 | |||
1935 | dev_dbg(codec->dev, "%s: Enter.\n", __func__); | ||
1936 | |||
1937 | /* Reset audio-registers and disable 32kHz-clock output 2 */ | ||
1938 | status = ab8500_sysctrl_write(AB8500_STW4500CTRL3, | ||
1939 | AB8500_STW4500CTRL3_CLK32KOUT2DIS | | ||
1940 | AB8500_STW4500CTRL3_RESETAUDN, | ||
1941 | AB8500_STW4500CTRL3_RESETAUDN); | ||
1942 | if (status < 0) | ||
1943 | return status; | ||
1944 | |||
1945 | return 0; | ||
1946 | } | ||
1947 | |||
1948 | static int ab8500_audio_setup_mics(struct snd_soc_codec *codec, | ||
1949 | struct amic_settings *amics) | ||
1950 | { | ||
1951 | u8 value8; | ||
1952 | unsigned int value; | ||
1953 | int status; | ||
1954 | const struct snd_soc_dapm_route *route; | ||
1955 | |||
1956 | dev_dbg(codec->dev, "%s: Enter.\n", __func__); | ||
1957 | |||
1958 | /* Set DMic-clocks to outputs */ | ||
1959 | status = abx500_get_register_interruptible(codec->dev, (u8)AB8500_MISC, | ||
1960 | (u8)AB8500_GPIO_DIR4_REG, | ||
1961 | &value8); | ||
1962 | if (status < 0) | ||
1963 | return status; | ||
1964 | value = value8 | GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT | | ||
1965 | GPIO31_DIR_OUTPUT; | ||
1966 | status = abx500_set_register_interruptible(codec->dev, | ||
1967 | (u8)AB8500_MISC, | ||
1968 | (u8)AB8500_GPIO_DIR4_REG, | ||
1969 | value); | ||
1970 | if (status < 0) | ||
1971 | return status; | ||
1972 | |||
1973 | /* Attach regulators to AMic DAPM-paths */ | ||
1974 | dev_dbg(codec->dev, "%s: Mic 1a regulator: %s\n", __func__, | ||
1975 | amic_micbias_str(amics->mic1a_micbias)); | ||
1976 | route = &ab8500_dapm_routes_mic1a_vamicx[amics->mic1a_micbias]; | ||
1977 | status = snd_soc_dapm_add_routes(&codec->dapm, route, 1); | ||
1978 | dev_dbg(codec->dev, "%s: Mic 1b regulator: %s\n", __func__, | ||
1979 | amic_micbias_str(amics->mic1b_micbias)); | ||
1980 | route = &ab8500_dapm_routes_mic1b_vamicx[amics->mic1b_micbias]; | ||
1981 | status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1); | ||
1982 | dev_dbg(codec->dev, "%s: Mic 2 regulator: %s\n", __func__, | ||
1983 | amic_micbias_str(amics->mic2_micbias)); | ||
1984 | route = &ab8500_dapm_routes_mic2_vamicx[amics->mic2_micbias]; | ||
1985 | status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1); | ||
1986 | if (status < 0) { | ||
1987 | dev_err(codec->dev, | ||
1988 | "%s: Failed to add AMic-regulator DAPM-routes (%d).\n", | ||
1989 | __func__, status); | ||
1990 | return status; | ||
1991 | } | ||
1992 | |||
1993 | /* Set AMic-configuration */ | ||
1994 | dev_dbg(codec->dev, "%s: Mic 1 mic-type: %s\n", __func__, | ||
1995 | amic_type_str(amics->mic1_type)); | ||
1996 | snd_soc_update_bits(codec, AB8500_ANAGAIN1, AB8500_ANAGAINX_ENSEMICX, | ||
1997 | amics->mic1_type == AMIC_TYPE_DIFFERENTIAL ? | ||
1998 | 0 : AB8500_ANAGAINX_ENSEMICX); | ||
1999 | dev_dbg(codec->dev, "%s: Mic 2 mic-type: %s\n", __func__, | ||
2000 | amic_type_str(amics->mic2_type)); | ||
2001 | snd_soc_update_bits(codec, AB8500_ANAGAIN2, AB8500_ANAGAINX_ENSEMICX, | ||
2002 | amics->mic2_type == AMIC_TYPE_DIFFERENTIAL ? | ||
2003 | 0 : AB8500_ANAGAINX_ENSEMICX); | ||
2004 | |||
2005 | return 0; | ||
2006 | } | ||
2007 | EXPORT_SYMBOL_GPL(ab8500_audio_setup_mics); | ||
2008 | |||
2009 | static int ab8500_audio_set_ear_cmv(struct snd_soc_codec *codec, | ||
2010 | enum ear_cm_voltage ear_cmv) | ||
2011 | { | ||
2012 | char *cmv_str; | ||
2013 | |||
2014 | switch (ear_cmv) { | ||
2015 | case EAR_CMV_0_95V: | ||
2016 | cmv_str = "0.95V"; | ||
2017 | break; | ||
2018 | case EAR_CMV_1_10V: | ||
2019 | cmv_str = "1.10V"; | ||
2020 | break; | ||
2021 | case EAR_CMV_1_27V: | ||
2022 | cmv_str = "1.27V"; | ||
2023 | break; | ||
2024 | case EAR_CMV_1_58V: | ||
2025 | cmv_str = "1.58V"; | ||
2026 | break; | ||
2027 | default: | ||
2028 | dev_err(codec->dev, | ||
2029 | "%s: Unknown earpiece CM-voltage (%d)!\n", | ||
2030 | __func__, (int)ear_cmv); | ||
2031 | return -EINVAL; | ||
2032 | } | ||
2033 | dev_dbg(codec->dev, "%s: Earpiece CM-voltage: %s\n", __func__, | ||
2034 | cmv_str); | ||
2035 | snd_soc_update_bits(codec, AB8500_ANACONF1, AB8500_ANACONF1_EARSELCM, | ||
2036 | ear_cmv); | ||
2037 | |||
2038 | return 0; | ||
2039 | } | ||
2040 | EXPORT_SYMBOL_GPL(ab8500_audio_set_ear_cmv); | ||
2041 | |||
2042 | static int ab8500_audio_set_bit_delay(struct snd_soc_dai *dai, | ||
2043 | unsigned int delay) | ||
2044 | { | ||
2045 | unsigned int mask, val; | ||
2046 | struct snd_soc_codec *codec = dai->codec; | ||
2047 | |||
2048 | mask = BIT(AB8500_DIGIFCONF2_IF0DEL); | ||
2049 | val = 0; | ||
2050 | |||
2051 | switch (delay) { | ||
2052 | case 0: | ||
2053 | break; | ||
2054 | case 1: | ||
2055 | val |= BIT(AB8500_DIGIFCONF2_IF0DEL); | ||
2056 | break; | ||
2057 | default: | ||
2058 | dev_err(dai->codec->dev, | ||
2059 | "%s: ERROR: Unsupported bit-delay (0x%x)!\n", | ||
2060 | __func__, delay); | ||
2061 | return -EINVAL; | ||
2062 | } | ||
2063 | |||
2064 | dev_dbg(dai->codec->dev, "%s: IF0 Bit-delay: %d bits.\n", | ||
2065 | __func__, delay); | ||
2066 | snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val); | ||
2067 | |||
2068 | return 0; | ||
2069 | } | ||
2070 | |||
2071 | /* Gates clocking according format mask */ | ||
2072 | static int ab8500_codec_set_dai_clock_gate(struct snd_soc_codec *codec, | ||
2073 | unsigned int fmt) | ||
2074 | { | ||
2075 | unsigned int mask; | ||
2076 | unsigned int val; | ||
2077 | |||
2078 | mask = BIT(AB8500_DIGIFCONF1_ENMASTGEN) | | ||
2079 | BIT(AB8500_DIGIFCONF1_ENFSBITCLK0); | ||
2080 | |||
2081 | val = BIT(AB8500_DIGIFCONF1_ENMASTGEN); | ||
2082 | |||
2083 | switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) { | ||
2084 | case SND_SOC_DAIFMT_CONT: /* continuous clock */ | ||
2085 | dev_dbg(codec->dev, "%s: IF0 Clock is continuous.\n", | ||
2086 | __func__); | ||
2087 | val |= BIT(AB8500_DIGIFCONF1_ENFSBITCLK0); | ||
2088 | break; | ||
2089 | case SND_SOC_DAIFMT_GATED: /* clock is gated */ | ||
2090 | dev_dbg(codec->dev, "%s: IF0 Clock is gated.\n", | ||
2091 | __func__); | ||
2092 | break; | ||
2093 | default: | ||
2094 | dev_err(codec->dev, | ||
2095 | "%s: ERROR: Unsupported clock mask (0x%x)!\n", | ||
2096 | __func__, fmt & SND_SOC_DAIFMT_CLOCK_MASK); | ||
2097 | return -EINVAL; | ||
2098 | } | ||
2099 | |||
2100 | snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val); | ||
2101 | |||
2102 | return 0; | ||
2103 | } | ||
2104 | |||
2105 | static int ab8500_codec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
2106 | { | ||
2107 | unsigned int mask; | ||
2108 | unsigned int val; | ||
2109 | struct snd_soc_codec *codec = dai->codec; | ||
2110 | int status; | ||
2111 | |||
2112 | dev_dbg(codec->dev, "%s: Enter (fmt = 0x%x)\n", __func__, fmt); | ||
2113 | |||
2114 | mask = BIT(AB8500_DIGIFCONF3_IF1DATOIF0AD) | | ||
2115 | BIT(AB8500_DIGIFCONF3_IF1CLKTOIF0CLK) | | ||
2116 | BIT(AB8500_DIGIFCONF3_IF0BFIFOEN) | | ||
2117 | BIT(AB8500_DIGIFCONF3_IF0MASTER); | ||
2118 | val = 0; | ||
2119 | |||
2120 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
2121 | case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & FRM master */ | ||
2122 | dev_dbg(dai->codec->dev, | ||
2123 | "%s: IF0 Master-mode: AB8500 master.\n", __func__); | ||
2124 | val |= BIT(AB8500_DIGIFCONF3_IF0MASTER); | ||
2125 | break; | ||
2126 | case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & FRM slave */ | ||
2127 | dev_dbg(dai->codec->dev, | ||
2128 | "%s: IF0 Master-mode: AB8500 slave.\n", __func__); | ||
2129 | break; | ||
2130 | case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & FRM master */ | ||
2131 | case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */ | ||
2132 | dev_err(dai->codec->dev, | ||
2133 | "%s: ERROR: The device is either a master or a slave.\n", | ||
2134 | __func__); | ||
2135 | default: | ||
2136 | dev_err(dai->codec->dev, | ||
2137 | "%s: ERROR: Unsupporter master mask 0x%x\n", | ||
2138 | __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK); | ||
2139 | return -EINVAL; | ||
2140 | break; | ||
2141 | } | ||
2142 | |||
2143 | snd_soc_update_bits(codec, AB8500_DIGIFCONF3, mask, val); | ||
2144 | |||
2145 | /* Set clock gating */ | ||
2146 | status = ab8500_codec_set_dai_clock_gate(codec, fmt); | ||
2147 | if (status) { | ||
2148 | dev_err(dai->codec->dev, | ||
2149 | "%s: ERRROR: Failed to set clock gate (%d).\n", | ||
2150 | __func__, status); | ||
2151 | return status; | ||
2152 | } | ||
2153 | |||
2154 | /* Setting data transfer format */ | ||
2155 | |||
2156 | mask = BIT(AB8500_DIGIFCONF2_IF0FORMAT0) | | ||
2157 | BIT(AB8500_DIGIFCONF2_IF0FORMAT1) | | ||
2158 | BIT(AB8500_DIGIFCONF2_FSYNC0P) | | ||
2159 | BIT(AB8500_DIGIFCONF2_BITCLK0P); | ||
2160 | val = 0; | ||
2161 | |||
2162 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
2163 | case SND_SOC_DAIFMT_I2S: /* I2S mode */ | ||
2164 | dev_dbg(dai->codec->dev, "%s: IF0 Protocol: I2S\n", __func__); | ||
2165 | val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT1); | ||
2166 | ab8500_audio_set_bit_delay(dai, 0); | ||
2167 | break; | ||
2168 | |||
2169 | case SND_SOC_DAIFMT_DSP_A: /* L data MSB after FRM LRC */ | ||
2170 | dev_dbg(dai->codec->dev, | ||
2171 | "%s: IF0 Protocol: DSP A (TDM)\n", __func__); | ||
2172 | val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT0); | ||
2173 | ab8500_audio_set_bit_delay(dai, 1); | ||
2174 | break; | ||
2175 | |||
2176 | case SND_SOC_DAIFMT_DSP_B: /* L data MSB during FRM LRC */ | ||
2177 | dev_dbg(dai->codec->dev, | ||
2178 | "%s: IF0 Protocol: DSP B (TDM)\n", __func__); | ||
2179 | val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT0); | ||
2180 | ab8500_audio_set_bit_delay(dai, 0); | ||
2181 | break; | ||
2182 | |||
2183 | default: | ||
2184 | dev_err(dai->codec->dev, | ||
2185 | "%s: ERROR: Unsupported format (0x%x)!\n", | ||
2186 | __func__, fmt & SND_SOC_DAIFMT_FORMAT_MASK); | ||
2187 | return -EINVAL; | ||
2188 | } | ||
2189 | |||
2190 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
2191 | case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ | ||
2192 | dev_dbg(dai->codec->dev, | ||
2193 | "%s: IF0: Normal bit clock, normal frame\n", | ||
2194 | __func__); | ||
2195 | break; | ||
2196 | case SND_SOC_DAIFMT_NB_IF: /* normal BCLK + inv FRM */ | ||
2197 | dev_dbg(dai->codec->dev, | ||
2198 | "%s: IF0: Normal bit clock, inverted frame\n", | ||
2199 | __func__); | ||
2200 | val |= BIT(AB8500_DIGIFCONF2_FSYNC0P); | ||
2201 | break; | ||
2202 | case SND_SOC_DAIFMT_IB_NF: /* invert BCLK + nor FRM */ | ||
2203 | dev_dbg(dai->codec->dev, | ||
2204 | "%s: IF0: Inverted bit clock, normal frame\n", | ||
2205 | __func__); | ||
2206 | val |= BIT(AB8500_DIGIFCONF2_BITCLK0P); | ||
2207 | break; | ||
2208 | case SND_SOC_DAIFMT_IB_IF: /* invert BCLK + FRM */ | ||
2209 | dev_dbg(dai->codec->dev, | ||
2210 | "%s: IF0: Inverted bit clock, inverted frame\n", | ||
2211 | __func__); | ||
2212 | val |= BIT(AB8500_DIGIFCONF2_FSYNC0P); | ||
2213 | val |= BIT(AB8500_DIGIFCONF2_BITCLK0P); | ||
2214 | break; | ||
2215 | default: | ||
2216 | dev_err(dai->codec->dev, | ||
2217 | "%s: ERROR: Unsupported INV mask 0x%x\n", | ||
2218 | __func__, fmt & SND_SOC_DAIFMT_INV_MASK); | ||
2219 | return -EINVAL; | ||
2220 | } | ||
2221 | |||
2222 | snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val); | ||
2223 | |||
2224 | return 0; | ||
2225 | } | ||
2226 | |||
2227 | static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai, | ||
2228 | unsigned int tx_mask, unsigned int rx_mask, | ||
2229 | int slots, int slot_width) | ||
2230 | { | ||
2231 | struct snd_soc_codec *codec = dai->codec; | ||
2232 | unsigned int val, mask, slots_active; | ||
2233 | |||
2234 | mask = BIT(AB8500_DIGIFCONF2_IF0WL0) | | ||
2235 | BIT(AB8500_DIGIFCONF2_IF0WL1); | ||
2236 | val = 0; | ||
2237 | |||
2238 | switch (slot_width) { | ||
2239 | case 16: | ||
2240 | break; | ||
2241 | case 20: | ||
2242 | val |= BIT(AB8500_DIGIFCONF2_IF0WL0); | ||
2243 | break; | ||
2244 | case 24: | ||
2245 | val |= BIT(AB8500_DIGIFCONF2_IF0WL1); | ||
2246 | break; | ||
2247 | case 32: | ||
2248 | val |= BIT(AB8500_DIGIFCONF2_IF0WL1) | | ||
2249 | BIT(AB8500_DIGIFCONF2_IF0WL0); | ||
2250 | break; | ||
2251 | default: | ||
2252 | dev_err(dai->codec->dev, "%s: Unsupported slot-width 0x%x\n", | ||
2253 | __func__, slot_width); | ||
2254 | return -EINVAL; | ||
2255 | } | ||
2256 | |||
2257 | dev_dbg(dai->codec->dev, "%s: IF0 slot-width: %d bits.\n", | ||
2258 | __func__, slot_width); | ||
2259 | snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val); | ||
2260 | |||
2261 | /* Setup TDM clocking according to slot count */ | ||
2262 | dev_dbg(dai->codec->dev, "%s: Slots, total: %d\n", __func__, slots); | ||
2263 | mask = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0) | | ||
2264 | BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1); | ||
2265 | switch (slots) { | ||
2266 | case 2: | ||
2267 | val = AB8500_MASK_NONE; | ||
2268 | break; | ||
2269 | case 4: | ||
2270 | val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0); | ||
2271 | break; | ||
2272 | case 8: | ||
2273 | val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1); | ||
2274 | break; | ||
2275 | case 16: | ||
2276 | val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0) | | ||
2277 | BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1); | ||
2278 | break; | ||
2279 | default: | ||
2280 | dev_err(dai->codec->dev, | ||
2281 | "%s: ERROR: Unsupported number of slots (%d)!\n", | ||
2282 | __func__, slots); | ||
2283 | return -EINVAL; | ||
2284 | } | ||
2285 | snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val); | ||
2286 | |||
2287 | /* Setup TDM DA according to active tx slots */ | ||
2288 | mask = AB8500_DASLOTCONFX_SLTODAX_MASK; | ||
2289 | slots_active = hweight32(tx_mask); | ||
2290 | dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__, | ||
2291 | slots_active); | ||
2292 | switch (slots_active) { | ||
2293 | case 0: | ||
2294 | break; | ||
2295 | case 1: | ||
2296 | /* Slot 9 -> DA_IN1 & DA_IN3 */ | ||
2297 | snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 11); | ||
2298 | snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 11); | ||
2299 | snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11); | ||
2300 | snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11); | ||
2301 | break; | ||
2302 | case 2: | ||
2303 | /* Slot 9 -> DA_IN1 & DA_IN3, Slot 11 -> DA_IN2 & DA_IN4 */ | ||
2304 | snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 9); | ||
2305 | snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 9); | ||
2306 | snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11); | ||
2307 | snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11); | ||
2308 | |||
2309 | break; | ||
2310 | case 8: | ||
2311 | dev_dbg(dai->codec->dev, | ||
2312 | "%s: In 8-channel mode DA-from-slot mapping is set manually.", | ||
2313 | __func__); | ||
2314 | break; | ||
2315 | default: | ||
2316 | dev_err(dai->codec->dev, | ||
2317 | "%s: Unsupported number of active TX-slots (%d)!\n", | ||
2318 | __func__, slots_active); | ||
2319 | return -EINVAL; | ||
2320 | } | ||
2321 | |||
2322 | /* Setup TDM AD according to active RX-slots */ | ||
2323 | slots_active = hweight32(rx_mask); | ||
2324 | dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__, | ||
2325 | slots_active); | ||
2326 | switch (slots_active) { | ||
2327 | case 0: | ||
2328 | break; | ||
2329 | case 1: | ||
2330 | /* AD_OUT3 -> slot 0 & 1 */ | ||
2331 | snd_soc_update_bits(codec, AB8500_ADSLOTSEL1, AB8500_MASK_ALL, | ||
2332 | AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN | | ||
2333 | AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD); | ||
2334 | break; | ||
2335 | case 2: | ||
2336 | /* AD_OUT3 -> slot 0, AD_OUT2 -> slot 1 */ | ||
2337 | snd_soc_update_bits(codec, | ||
2338 | AB8500_ADSLOTSEL1, | ||
2339 | AB8500_MASK_ALL, | ||
2340 | AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN | | ||
2341 | AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD); | ||
2342 | break; | ||
2343 | case 8: | ||
2344 | dev_dbg(dai->codec->dev, | ||
2345 | "%s: In 8-channel mode AD-to-slot mapping is set manually.", | ||
2346 | __func__); | ||
2347 | break; | ||
2348 | default: | ||
2349 | dev_err(dai->codec->dev, | ||
2350 | "%s: Unsupported number of active RX-slots (%d)!\n", | ||
2351 | __func__, slots_active); | ||
2352 | return -EINVAL; | ||
2353 | } | ||
2354 | |||
2355 | return 0; | ||
2356 | } | ||
2357 | |||
2358 | struct snd_soc_dai_driver ab8500_codec_dai[] = { | ||
2359 | { | ||
2360 | .name = "ab8500-codec-dai.0", | ||
2361 | .id = 0, | ||
2362 | .playback = { | ||
2363 | .stream_name = "ab8500_0p", | ||
2364 | .channels_min = 1, | ||
2365 | .channels_max = 8, | ||
2366 | .rates = AB8500_SUPPORTED_RATE, | ||
2367 | .formats = AB8500_SUPPORTED_FMT, | ||
2368 | }, | ||
2369 | .ops = (struct snd_soc_dai_ops[]) { | ||
2370 | { | ||
2371 | .set_tdm_slot = ab8500_codec_set_dai_tdm_slot, | ||
2372 | .set_fmt = ab8500_codec_set_dai_fmt, | ||
2373 | } | ||
2374 | }, | ||
2375 | .symmetric_rates = 1 | ||
2376 | }, | ||
2377 | { | ||
2378 | .name = "ab8500-codec-dai.1", | ||
2379 | .id = 1, | ||
2380 | .capture = { | ||
2381 | .stream_name = "ab8500_0c", | ||
2382 | .channels_min = 1, | ||
2383 | .channels_max = 8, | ||
2384 | .rates = AB8500_SUPPORTED_RATE, | ||
2385 | .formats = AB8500_SUPPORTED_FMT, | ||
2386 | }, | ||
2387 | .ops = (struct snd_soc_dai_ops[]) { | ||
2388 | { | ||
2389 | .set_tdm_slot = ab8500_codec_set_dai_tdm_slot, | ||
2390 | .set_fmt = ab8500_codec_set_dai_fmt, | ||
2391 | } | ||
2392 | }, | ||
2393 | .symmetric_rates = 1 | ||
2394 | } | ||
2395 | }; | ||
2396 | |||
2397 | static int ab8500_codec_probe(struct snd_soc_codec *codec) | ||
2398 | { | ||
2399 | struct device *dev = codec->dev; | ||
2400 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev); | ||
2401 | struct ab8500_platform_data *pdata; | ||
2402 | struct filter_control *fc; | ||
2403 | int status; | ||
2404 | |||
2405 | dev_dbg(dev, "%s: Enter.\n", __func__); | ||
2406 | |||
2407 | /* Setup AB8500 according to board-settings */ | ||
2408 | pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent); | ||
2409 | status = ab8500_audio_setup_mics(codec, &pdata->codec->amics); | ||
2410 | if (status < 0) { | ||
2411 | pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); | ||
2412 | return status; | ||
2413 | } | ||
2414 | status = ab8500_audio_set_ear_cmv(codec, pdata->codec->ear_cmv); | ||
2415 | if (status < 0) { | ||
2416 | pr_err("%s: Failed to set earpiece CM-voltage (%d)!\n", | ||
2417 | __func__, status); | ||
2418 | return status; | ||
2419 | } | ||
2420 | |||
2421 | status = ab8500_audio_init_audioblock(codec); | ||
2422 | if (status < 0) { | ||
2423 | dev_err(dev, "%s: failed to init audio-block (%d)!\n", | ||
2424 | __func__, status); | ||
2425 | return status; | ||
2426 | } | ||
2427 | |||
2428 | /* Override HW-defaults */ | ||
2429 | ab8500_codec_write_reg(codec, | ||
2430 | AB8500_ANACONF5, | ||
2431 | BIT(AB8500_ANACONF5_HSAUTOEN)); | ||
2432 | ab8500_codec_write_reg(codec, | ||
2433 | AB8500_SHORTCIRCONF, | ||
2434 | BIT(AB8500_SHORTCIRCONF_HSZCDDIS)); | ||
2435 | |||
2436 | /* Add filter controls */ | ||
2437 | status = snd_soc_add_codec_controls(codec, ab8500_filter_controls, | ||
2438 | ARRAY_SIZE(ab8500_filter_controls)); | ||
2439 | if (status < 0) { | ||
2440 | dev_err(dev, | ||
2441 | "%s: failed to add ab8500 filter controls (%d).\n", | ||
2442 | __func__, status); | ||
2443 | return status; | ||
2444 | } | ||
2445 | fc = (struct filter_control *) | ||
2446 | &ab8500_filter_controls[AB8500_FILTER_ANC_FIR].private_value; | ||
2447 | drvdata->anc_fir_values = (long *)fc->value; | ||
2448 | fc = (struct filter_control *) | ||
2449 | &ab8500_filter_controls[AB8500_FILTER_ANC_IIR].private_value; | ||
2450 | drvdata->anc_iir_values = (long *)fc->value; | ||
2451 | fc = (struct filter_control *) | ||
2452 | &ab8500_filter_controls[AB8500_FILTER_SID_FIR].private_value; | ||
2453 | drvdata->sid_fir_values = (long *)fc->value; | ||
2454 | |||
2455 | (void)snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input"); | ||
2456 | |||
2457 | mutex_init(&drvdata->anc_lock); | ||
2458 | |||
2459 | return status; | ||
2460 | } | ||
2461 | |||
2462 | static struct snd_soc_codec_driver ab8500_codec_driver = { | ||
2463 | .probe = ab8500_codec_probe, | ||
2464 | .read = ab8500_codec_read_reg, | ||
2465 | .write = ab8500_codec_write_reg, | ||
2466 | .reg_word_size = sizeof(u8), | ||
2467 | .controls = ab8500_ctrls, | ||
2468 | .num_controls = ARRAY_SIZE(ab8500_ctrls), | ||
2469 | .dapm_widgets = ab8500_dapm_widgets, | ||
2470 | .num_dapm_widgets = ARRAY_SIZE(ab8500_dapm_widgets), | ||
2471 | .dapm_routes = ab8500_dapm_routes, | ||
2472 | .num_dapm_routes = ARRAY_SIZE(ab8500_dapm_routes), | ||
2473 | }; | ||
2474 | |||
2475 | static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev) | ||
2476 | { | ||
2477 | int status; | ||
2478 | struct ab8500_codec_drvdata *drvdata; | ||
2479 | |||
2480 | dev_dbg(&pdev->dev, "%s: Enter.\n", __func__); | ||
2481 | |||
2482 | /* Create driver private-data struct */ | ||
2483 | drvdata = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_codec_drvdata), | ||
2484 | GFP_KERNEL); | ||
2485 | drvdata->sid_status = SID_UNCONFIGURED; | ||
2486 | drvdata->anc_status = ANC_UNCONFIGURED; | ||
2487 | dev_set_drvdata(&pdev->dev, drvdata); | ||
2488 | |||
2489 | dev_dbg(&pdev->dev, "%s: Register codec.\n", __func__); | ||
2490 | status = snd_soc_register_codec(&pdev->dev, &ab8500_codec_driver, | ||
2491 | ab8500_codec_dai, | ||
2492 | ARRAY_SIZE(ab8500_codec_dai)); | ||
2493 | if (status < 0) | ||
2494 | dev_err(&pdev->dev, | ||
2495 | "%s: Error: Failed to register codec (%d).\n", | ||
2496 | __func__, status); | ||
2497 | |||
2498 | return status; | ||
2499 | } | ||
2500 | |||
2501 | static int __devexit ab8500_codec_driver_remove(struct platform_device *pdev) | ||
2502 | { | ||
2503 | dev_info(&pdev->dev, "%s Enter.\n", __func__); | ||
2504 | |||
2505 | snd_soc_unregister_codec(&pdev->dev); | ||
2506 | |||
2507 | return 0; | ||
2508 | } | ||
2509 | |||
2510 | static struct platform_driver ab8500_codec_platform_driver = { | ||
2511 | .driver = { | ||
2512 | .name = "ab8500-codec", | ||
2513 | .owner = THIS_MODULE, | ||
2514 | }, | ||
2515 | .probe = ab8500_codec_driver_probe, | ||
2516 | .remove = __devexit_p(ab8500_codec_driver_remove), | ||
2517 | .suspend = NULL, | ||
2518 | .resume = NULL, | ||
2519 | }; | ||
2520 | module_platform_driver(ab8500_codec_platform_driver); | ||
2521 | |||
2522 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/ab8500-codec.h b/sound/soc/codecs/ab8500-codec.h new file mode 100644 index 000000000000..114f69a0c629 --- /dev/null +++ b/sound/soc/codecs/ab8500-codec.h | |||
@@ -0,0 +1,590 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2012 | ||
3 | * | ||
4 | * Author: Ola Lilja <ola.o.lilja@stericsson.com>, | ||
5 | * Kristoffer Karlsson <kristoffer.karlsson@stericsson.com>, | ||
6 | * Roger Nilsson <roger.xr.nilsson@stericsson.com>, | ||
7 | * for ST-Ericsson. | ||
8 | * | ||
9 | * Based on the early work done by: | ||
10 | * Mikko J. Lehto <mikko.lehto@symbio.com>, | ||
11 | * Mikko Sarmanne <mikko.sarmanne@symbio.com>, | ||
12 | * for ST-Ericsson. | ||
13 | * | ||
14 | * License terms: | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify it | ||
17 | * under the terms of the GNU General Public License version 2 as published | ||
18 | * by the Free Software Foundation. | ||
19 | */ | ||
20 | |||
21 | #ifndef AB8500_CODEC_REGISTERS_H | ||
22 | #define AB8500_CODEC_REGISTERS_H | ||
23 | |||
24 | #define AB8500_SUPPORTED_RATE (SNDRV_PCM_RATE_48000) | ||
25 | #define AB8500_SUPPORTED_FMT (SNDRV_PCM_FMTBIT_S16_LE) | ||
26 | |||
27 | /* AB8500 audio bank (0x0d) register definitions */ | ||
28 | |||
29 | #define AB8500_POWERUP 0x00 | ||
30 | #define AB8500_AUDSWRESET 0x01 | ||
31 | #define AB8500_ADPATHENA 0x02 | ||
32 | #define AB8500_DAPATHENA 0x03 | ||
33 | #define AB8500_ANACONF1 0x04 | ||
34 | #define AB8500_ANACONF2 0x05 | ||
35 | #define AB8500_DIGMICCONF 0x06 | ||
36 | #define AB8500_ANACONF3 0x07 | ||
37 | #define AB8500_ANACONF4 0x08 | ||
38 | #define AB8500_DAPATHCONF 0x09 | ||
39 | #define AB8500_MUTECONF 0x0A | ||
40 | #define AB8500_SHORTCIRCONF 0x0B | ||
41 | #define AB8500_ANACONF5 0x0C | ||
42 | #define AB8500_ENVCPCONF 0x0D | ||
43 | #define AB8500_SIGENVCONF 0x0E | ||
44 | #define AB8500_PWMGENCONF1 0x0F | ||
45 | #define AB8500_PWMGENCONF2 0x10 | ||
46 | #define AB8500_PWMGENCONF3 0x11 | ||
47 | #define AB8500_PWMGENCONF4 0x12 | ||
48 | #define AB8500_PWMGENCONF5 0x13 | ||
49 | #define AB8500_ANAGAIN1 0x14 | ||
50 | #define AB8500_ANAGAIN2 0x15 | ||
51 | #define AB8500_ANAGAIN3 0x16 | ||
52 | #define AB8500_ANAGAIN4 0x17 | ||
53 | #define AB8500_DIGLINHSLGAIN 0x18 | ||
54 | #define AB8500_DIGLINHSRGAIN 0x19 | ||
55 | #define AB8500_ADFILTCONF 0x1A | ||
56 | #define AB8500_DIGIFCONF1 0x1B | ||
57 | #define AB8500_DIGIFCONF2 0x1C | ||
58 | #define AB8500_DIGIFCONF3 0x1D | ||
59 | #define AB8500_DIGIFCONF4 0x1E | ||
60 | #define AB8500_ADSLOTSEL1 0x1F | ||
61 | #define AB8500_ADSLOTSEL2 0x20 | ||
62 | #define AB8500_ADSLOTSEL3 0x21 | ||
63 | #define AB8500_ADSLOTSEL4 0x22 | ||
64 | #define AB8500_ADSLOTSEL5 0x23 | ||
65 | #define AB8500_ADSLOTSEL6 0x24 | ||
66 | #define AB8500_ADSLOTSEL7 0x25 | ||
67 | #define AB8500_ADSLOTSEL8 0x26 | ||
68 | #define AB8500_ADSLOTSEL9 0x27 | ||
69 | #define AB8500_ADSLOTSEL10 0x28 | ||
70 | #define AB8500_ADSLOTSEL11 0x29 | ||
71 | #define AB8500_ADSLOTSEL12 0x2A | ||
72 | #define AB8500_ADSLOTSEL13 0x2B | ||
73 | #define AB8500_ADSLOTSEL14 0x2C | ||
74 | #define AB8500_ADSLOTSEL15 0x2D | ||
75 | #define AB8500_ADSLOTSEL16 0x2E | ||
76 | #define AB8500_ADSLOTHIZCTRL1 0x2F | ||
77 | #define AB8500_ADSLOTHIZCTRL2 0x30 | ||
78 | #define AB8500_ADSLOTHIZCTRL3 0x31 | ||
79 | #define AB8500_ADSLOTHIZCTRL4 0x32 | ||
80 | #define AB8500_DASLOTCONF1 0x33 | ||
81 | #define AB8500_DASLOTCONF2 0x34 | ||
82 | #define AB8500_DASLOTCONF3 0x35 | ||
83 | #define AB8500_DASLOTCONF4 0x36 | ||
84 | #define AB8500_DASLOTCONF5 0x37 | ||
85 | #define AB8500_DASLOTCONF6 0x38 | ||
86 | #define AB8500_DASLOTCONF7 0x39 | ||
87 | #define AB8500_DASLOTCONF8 0x3A | ||
88 | #define AB8500_CLASSDCONF1 0x3B | ||
89 | #define AB8500_CLASSDCONF2 0x3C | ||
90 | #define AB8500_CLASSDCONF3 0x3D | ||
91 | #define AB8500_DMICFILTCONF 0x3E | ||
92 | #define AB8500_DIGMULTCONF1 0x3F | ||
93 | #define AB8500_DIGMULTCONF2 0x40 | ||
94 | #define AB8500_ADDIGGAIN1 0x41 | ||
95 | #define AB8500_ADDIGGAIN2 0x42 | ||
96 | #define AB8500_ADDIGGAIN3 0x43 | ||
97 | #define AB8500_ADDIGGAIN4 0x44 | ||
98 | #define AB8500_ADDIGGAIN5 0x45 | ||
99 | #define AB8500_ADDIGGAIN6 0x46 | ||
100 | #define AB8500_DADIGGAIN1 0x47 | ||
101 | #define AB8500_DADIGGAIN2 0x48 | ||
102 | #define AB8500_DADIGGAIN3 0x49 | ||
103 | #define AB8500_DADIGGAIN4 0x4A | ||
104 | #define AB8500_DADIGGAIN5 0x4B | ||
105 | #define AB8500_DADIGGAIN6 0x4C | ||
106 | #define AB8500_ADDIGLOOPGAIN1 0x4D | ||
107 | #define AB8500_ADDIGLOOPGAIN2 0x4E | ||
108 | #define AB8500_HSLEARDIGGAIN 0x4F | ||
109 | #define AB8500_HSRDIGGAIN 0x50 | ||
110 | #define AB8500_SIDFIRGAIN1 0x51 | ||
111 | #define AB8500_SIDFIRGAIN2 0x52 | ||
112 | #define AB8500_ANCCONF1 0x53 | ||
113 | #define AB8500_ANCCONF2 0x54 | ||
114 | #define AB8500_ANCCONF3 0x55 | ||
115 | #define AB8500_ANCCONF4 0x56 | ||
116 | #define AB8500_ANCCONF5 0x57 | ||
117 | #define AB8500_ANCCONF6 0x58 | ||
118 | #define AB8500_ANCCONF7 0x59 | ||
119 | #define AB8500_ANCCONF8 0x5A | ||
120 | #define AB8500_ANCCONF9 0x5B | ||
121 | #define AB8500_ANCCONF10 0x5C | ||
122 | #define AB8500_ANCCONF11 0x5D | ||
123 | #define AB8500_ANCCONF12 0x5E | ||
124 | #define AB8500_ANCCONF13 0x5F | ||
125 | #define AB8500_ANCCONF14 0x60 | ||
126 | #define AB8500_SIDFIRADR 0x61 | ||
127 | #define AB8500_SIDFIRCOEF1 0x62 | ||
128 | #define AB8500_SIDFIRCOEF2 0x63 | ||
129 | #define AB8500_SIDFIRCONF 0x64 | ||
130 | #define AB8500_AUDINTMASK1 0x65 | ||
131 | #define AB8500_AUDINTSOURCE1 0x66 | ||
132 | #define AB8500_AUDINTMASK2 0x67 | ||
133 | #define AB8500_AUDINTSOURCE2 0x68 | ||
134 | #define AB8500_FIFOCONF1 0x69 | ||
135 | #define AB8500_FIFOCONF2 0x6A | ||
136 | #define AB8500_FIFOCONF3 0x6B | ||
137 | #define AB8500_FIFOCONF4 0x6C | ||
138 | #define AB8500_FIFOCONF5 0x6D | ||
139 | #define AB8500_FIFOCONF6 0x6E | ||
140 | #define AB8500_AUDREV 0x6F | ||
141 | |||
142 | #define AB8500_FIRST_REG AB8500_POWERUP | ||
143 | #define AB8500_LAST_REG AB8500_AUDREV | ||
144 | #define AB8500_CACHEREGNUM (AB8500_LAST_REG + 1) | ||
145 | |||
146 | #define AB8500_MASK_ALL 0xFF | ||
147 | #define AB8500_MASK_NONE 0x00 | ||
148 | |||
149 | /* AB8500_POWERUP */ | ||
150 | #define AB8500_POWERUP_POWERUP 7 | ||
151 | #define AB8500_POWERUP_ENANA 3 | ||
152 | |||
153 | /* AB8500_AUDSWRESET */ | ||
154 | #define AB8500_AUDSWRESET_SWRESET 7 | ||
155 | |||
156 | /* AB8500_ADPATHENA */ | ||
157 | #define AB8500_ADPATHENA_ENAD12 7 | ||
158 | #define AB8500_ADPATHENA_ENAD34 5 | ||
159 | #define AB8500_ADPATHENA_ENAD5768 3 | ||
160 | |||
161 | /* AB8500_DAPATHENA */ | ||
162 | #define AB8500_DAPATHENA_ENDA1 7 | ||
163 | #define AB8500_DAPATHENA_ENDA2 6 | ||
164 | #define AB8500_DAPATHENA_ENDA3 5 | ||
165 | #define AB8500_DAPATHENA_ENDA4 4 | ||
166 | #define AB8500_DAPATHENA_ENDA5 3 | ||
167 | #define AB8500_DAPATHENA_ENDA6 2 | ||
168 | |||
169 | /* AB8500_ANACONF1 */ | ||
170 | #define AB8500_ANACONF1_HSLOWPOW 7 | ||
171 | #define AB8500_ANACONF1_DACLOWPOW1 6 | ||
172 | #define AB8500_ANACONF1_DACLOWPOW0 5 | ||
173 | #define AB8500_ANACONF1_EARDACLOWPOW 4 | ||
174 | #define AB8500_ANACONF1_EARSELCM 2 | ||
175 | #define AB8500_ANACONF1_HSHPEN 1 | ||
176 | #define AB8500_ANACONF1_EARDRVLOWPOW 0 | ||
177 | |||
178 | /* AB8500_ANACONF2 */ | ||
179 | #define AB8500_ANACONF2_ENMIC1 7 | ||
180 | #define AB8500_ANACONF2_ENMIC2 6 | ||
181 | #define AB8500_ANACONF2_ENLINL 5 | ||
182 | #define AB8500_ANACONF2_ENLINR 4 | ||
183 | #define AB8500_ANACONF2_MUTMIC1 3 | ||
184 | #define AB8500_ANACONF2_MUTMIC2 2 | ||
185 | #define AB8500_ANACONF2_MUTLINL 1 | ||
186 | #define AB8500_ANACONF2_MUTLINR 0 | ||
187 | |||
188 | /* AB8500_DIGMICCONF */ | ||
189 | #define AB8500_DIGMICCONF_ENDMIC1 7 | ||
190 | #define AB8500_DIGMICCONF_ENDMIC2 6 | ||
191 | #define AB8500_DIGMICCONF_ENDMIC3 5 | ||
192 | #define AB8500_DIGMICCONF_ENDMIC4 4 | ||
193 | #define AB8500_DIGMICCONF_ENDMIC5 3 | ||
194 | #define AB8500_DIGMICCONF_ENDMIC6 2 | ||
195 | #define AB8500_DIGMICCONF_HSFADSPEED 0 | ||
196 | |||
197 | /* AB8500_ANACONF3 */ | ||
198 | #define AB8500_ANACONF3_MIC1SEL 7 | ||
199 | #define AB8500_ANACONF3_LINRSEL 6 | ||
200 | #define AB8500_ANACONF3_ENDRVHSL 5 | ||
201 | #define AB8500_ANACONF3_ENDRVHSR 4 | ||
202 | #define AB8500_ANACONF3_ENADCMIC 2 | ||
203 | #define AB8500_ANACONF3_ENADCLINL 1 | ||
204 | #define AB8500_ANACONF3_ENADCLINR 0 | ||
205 | |||
206 | /* AB8500_ANACONF4 */ | ||
207 | #define AB8500_ANACONF4_DISPDVSS 7 | ||
208 | #define AB8500_ANACONF4_ENEAR 6 | ||
209 | #define AB8500_ANACONF4_ENHSL 5 | ||
210 | #define AB8500_ANACONF4_ENHSR 4 | ||
211 | #define AB8500_ANACONF4_ENHFL 3 | ||
212 | #define AB8500_ANACONF4_ENHFR 2 | ||
213 | #define AB8500_ANACONF4_ENVIB1 1 | ||
214 | #define AB8500_ANACONF4_ENVIB2 0 | ||
215 | |||
216 | /* AB8500_DAPATHCONF */ | ||
217 | #define AB8500_DAPATHCONF_ENDACEAR 6 | ||
218 | #define AB8500_DAPATHCONF_ENDACHSL 5 | ||
219 | #define AB8500_DAPATHCONF_ENDACHSR 4 | ||
220 | #define AB8500_DAPATHCONF_ENDACHFL 3 | ||
221 | #define AB8500_DAPATHCONF_ENDACHFR 2 | ||
222 | #define AB8500_DAPATHCONF_ENDACVIB1 1 | ||
223 | #define AB8500_DAPATHCONF_ENDACVIB2 0 | ||
224 | |||
225 | /* AB8500_MUTECONF */ | ||
226 | #define AB8500_MUTECONF_MUTEAR 6 | ||
227 | #define AB8500_MUTECONF_MUTHSL 5 | ||
228 | #define AB8500_MUTECONF_MUTHSR 4 | ||
229 | #define AB8500_MUTECONF_MUTDACEAR 2 | ||
230 | #define AB8500_MUTECONF_MUTDACHSL 1 | ||
231 | #define AB8500_MUTECONF_MUTDACHSR 0 | ||
232 | |||
233 | /* AB8500_SHORTCIRCONF */ | ||
234 | #define AB8500_SHORTCIRCONF_ENSHORTPWD 7 | ||
235 | #define AB8500_SHORTCIRCONF_EARSHORTDIS 6 | ||
236 | #define AB8500_SHORTCIRCONF_HSSHORTDIS 5 | ||
237 | #define AB8500_SHORTCIRCONF_HSPULLDEN 4 | ||
238 | #define AB8500_SHORTCIRCONF_HSOSCEN 2 | ||
239 | #define AB8500_SHORTCIRCONF_HSFADDIS 1 | ||
240 | #define AB8500_SHORTCIRCONF_HSZCDDIS 0 | ||
241 | /* Zero cross should be disabled */ | ||
242 | |||
243 | /* AB8500_ANACONF5 */ | ||
244 | #define AB8500_ANACONF5_ENCPHS 7 | ||
245 | #define AB8500_ANACONF5_HSLDACTOLOL 5 | ||
246 | #define AB8500_ANACONF5_HSRDACTOLOR 4 | ||
247 | #define AB8500_ANACONF5_ENLOL 3 | ||
248 | #define AB8500_ANACONF5_ENLOR 2 | ||
249 | #define AB8500_ANACONF5_HSAUTOEN 0 | ||
250 | |||
251 | /* AB8500_ENVCPCONF */ | ||
252 | #define AB8500_ENVCPCONF_ENVDETHTHRE 4 | ||
253 | #define AB8500_ENVCPCONF_ENVDETLTHRE 0 | ||
254 | #define AB8500_ENVCPCONF_ENVDETHTHRE_MAX 0x0F | ||
255 | #define AB8500_ENVCPCONF_ENVDETLTHRE_MAX 0x0F | ||
256 | |||
257 | /* AB8500_SIGENVCONF */ | ||
258 | #define AB8500_SIGENVCONF_CPLVEN 5 | ||
259 | #define AB8500_SIGENVCONF_ENVDETCPEN 4 | ||
260 | #define AB8500_SIGENVCONF_ENVDETTIME 0 | ||
261 | #define AB8500_SIGENVCONF_ENVDETTIME_MAX 0x0F | ||
262 | |||
263 | /* AB8500_PWMGENCONF1 */ | ||
264 | #define AB8500_PWMGENCONF1_PWMTOVIB1 7 | ||
265 | #define AB8500_PWMGENCONF1_PWMTOVIB2 6 | ||
266 | #define AB8500_PWMGENCONF1_PWM1CTRL 5 | ||
267 | #define AB8500_PWMGENCONF1_PWM2CTRL 4 | ||
268 | #define AB8500_PWMGENCONF1_PWM1NCTRL 3 | ||
269 | #define AB8500_PWMGENCONF1_PWM1PCTRL 2 | ||
270 | #define AB8500_PWMGENCONF1_PWM2NCTRL 1 | ||
271 | #define AB8500_PWMGENCONF1_PWM2PCTRL 0 | ||
272 | |||
273 | /* AB8500_PWMGENCONF2 */ | ||
274 | /* AB8500_PWMGENCONF3 */ | ||
275 | /* AB8500_PWMGENCONF4 */ | ||
276 | /* AB8500_PWMGENCONF5 */ | ||
277 | #define AB8500_PWMGENCONFX_PWMVIBXPOL 7 | ||
278 | #define AB8500_PWMGENCONFX_PWMVIBXDUTCYC 0 | ||
279 | #define AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX 0x64 | ||
280 | |||
281 | /* AB8500_ANAGAIN1 */ | ||
282 | /* AB8500_ANAGAIN2 */ | ||
283 | #define AB8500_ANAGAINX_ENSEMICX 7 | ||
284 | #define AB8500_ANAGAINX_LOWPOWMICX 6 | ||
285 | #define AB8500_ANAGAINX_MICXGAIN 0 | ||
286 | #define AB8500_ANAGAINX_MICXGAIN_MAX 0x1F | ||
287 | |||
288 | /* AB8500_ANAGAIN3 */ | ||
289 | #define AB8500_ANAGAIN3_HSLGAIN 4 | ||
290 | #define AB8500_ANAGAIN3_HSRGAIN 0 | ||
291 | #define AB8500_ANAGAIN3_HSXGAIN_MAX 0x0F | ||
292 | |||
293 | /* AB8500_ANAGAIN4 */ | ||
294 | #define AB8500_ANAGAIN4_LINLGAIN 4 | ||
295 | #define AB8500_ANAGAIN4_LINRGAIN 0 | ||
296 | #define AB8500_ANAGAIN4_LINXGAIN_MAX 0x0F | ||
297 | |||
298 | /* AB8500_DIGLINHSLGAIN */ | ||
299 | /* AB8500_DIGLINHSRGAIN */ | ||
300 | #define AB8500_DIGLINHSXGAIN_LINTOHSXGAIN 0 | ||
301 | #define AB8500_DIGLINHSXGAIN_LINTOHSXGAIN_MAX 0x13 | ||
302 | |||
303 | /* AB8500_ADFILTCONF */ | ||
304 | #define AB8500_ADFILTCONF_AD1NH 7 | ||
305 | #define AB8500_ADFILTCONF_AD2NH 6 | ||
306 | #define AB8500_ADFILTCONF_AD3NH 5 | ||
307 | #define AB8500_ADFILTCONF_AD4NH 4 | ||
308 | #define AB8500_ADFILTCONF_AD1VOICE 3 | ||
309 | #define AB8500_ADFILTCONF_AD2VOICE 2 | ||
310 | #define AB8500_ADFILTCONF_AD3VOICE 1 | ||
311 | #define AB8500_ADFILTCONF_AD4VOICE 0 | ||
312 | |||
313 | /* AB8500_DIGIFCONF1 */ | ||
314 | #define AB8500_DIGIFCONF1_ENMASTGEN 7 | ||
315 | #define AB8500_DIGIFCONF1_IF1BITCLKOS1 6 | ||
316 | #define AB8500_DIGIFCONF1_IF1BITCLKOS0 5 | ||
317 | #define AB8500_DIGIFCONF1_ENFSBITCLK1 4 | ||
318 | #define AB8500_DIGIFCONF1_IF0BITCLKOS1 2 | ||
319 | #define AB8500_DIGIFCONF1_IF0BITCLKOS0 1 | ||
320 | #define AB8500_DIGIFCONF1_ENFSBITCLK0 0 | ||
321 | |||
322 | /* AB8500_DIGIFCONF2 */ | ||
323 | #define AB8500_DIGIFCONF2_FSYNC0P 6 | ||
324 | #define AB8500_DIGIFCONF2_BITCLK0P 5 | ||
325 | #define AB8500_DIGIFCONF2_IF0DEL 4 | ||
326 | #define AB8500_DIGIFCONF2_IF0FORMAT1 3 | ||
327 | #define AB8500_DIGIFCONF2_IF0FORMAT0 2 | ||
328 | #define AB8500_DIGIFCONF2_IF0WL1 1 | ||
329 | #define AB8500_DIGIFCONF2_IF0WL0 0 | ||
330 | |||
331 | /* AB8500_DIGIFCONF3 */ | ||
332 | #define AB8500_DIGIFCONF3_IF0DATOIF1AD 7 | ||
333 | #define AB8500_DIGIFCONF3_IF0CLKTOIF1CLK 6 | ||
334 | #define AB8500_DIGIFCONF3_IF1MASTER 5 | ||
335 | #define AB8500_DIGIFCONF3_IF1DATOIF0AD 3 | ||
336 | #define AB8500_DIGIFCONF3_IF1CLKTOIF0CLK 2 | ||
337 | #define AB8500_DIGIFCONF3_IF0MASTER 1 | ||
338 | #define AB8500_DIGIFCONF3_IF0BFIFOEN 0 | ||
339 | |||
340 | /* AB8500_DIGIFCONF4 */ | ||
341 | #define AB8500_DIGIFCONF4_FSYNC1P 6 | ||
342 | #define AB8500_DIGIFCONF4_BITCLK1P 5 | ||
343 | #define AB8500_DIGIFCONF4_IF1DEL 4 | ||
344 | #define AB8500_DIGIFCONF4_IF1FORMAT1 3 | ||
345 | #define AB8500_DIGIFCONF4_IF1FORMAT0 2 | ||
346 | #define AB8500_DIGIFCONF4_IF1WL1 1 | ||
347 | #define AB8500_DIGIFCONF4_IF1WL0 0 | ||
348 | |||
349 | /* AB8500_ADSLOTSELX */ | ||
350 | #define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_ODD 0x00 | ||
351 | #define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD 0x01 | ||
352 | #define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD 0x02 | ||
353 | #define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_ODD 0x03 | ||
354 | #define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_ODD 0x04 | ||
355 | #define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD 0x05 | ||
356 | #define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_ODD 0x06 | ||
357 | #define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_ODD 0x07 | ||
358 | #define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_ODD 0x08 | ||
359 | #define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_ODD 0x0F | ||
360 | #define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_EVEN 0x00 | ||
361 | #define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_EVEN 0x10 | ||
362 | #define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN 0x20 | ||
363 | #define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_EVEN 0x30 | ||
364 | #define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN 0x40 | ||
365 | #define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_EVEN 0x50 | ||
366 | #define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_EVEN 0x60 | ||
367 | #define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_EVEN 0x70 | ||
368 | #define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_EVEN 0x80 | ||
369 | #define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_EVEN 0xF0 | ||
370 | #define AB8500_ADSLOTSELX_EVEN_SHIFT 0 | ||
371 | #define AB8500_ADSLOTSELX_ODD_SHIFT 4 | ||
372 | |||
373 | /* AB8500_ADSLOTHIZCTRL1 */ | ||
374 | /* AB8500_ADSLOTHIZCTRL2 */ | ||
375 | /* AB8500_ADSLOTHIZCTRL3 */ | ||
376 | /* AB8500_ADSLOTHIZCTRL4 */ | ||
377 | /* AB8500_DASLOTCONF1 */ | ||
378 | #define AB8500_DASLOTCONF1_DA12VOICE 7 | ||
379 | #define AB8500_DASLOTCONF1_SWAPDA12_34 6 | ||
380 | #define AB8500_DASLOTCONF1_DAI7TOADO1 5 | ||
381 | |||
382 | /* AB8500_DASLOTCONF2 */ | ||
383 | #define AB8500_DASLOTCONF2_DAI8TOADO2 5 | ||
384 | |||
385 | /* AB8500_DASLOTCONF3 */ | ||
386 | #define AB8500_DASLOTCONF3_DA34VOICE 7 | ||
387 | #define AB8500_DASLOTCONF3_DAI7TOADO3 5 | ||
388 | |||
389 | /* AB8500_DASLOTCONF4 */ | ||
390 | #define AB8500_DASLOTCONF4_DAI8TOADO4 5 | ||
391 | |||
392 | /* AB8500_DASLOTCONF5 */ | ||
393 | #define AB8500_DASLOTCONF5_DA56VOICE 7 | ||
394 | #define AB8500_DASLOTCONF5_DAI7TOADO5 5 | ||
395 | |||
396 | /* AB8500_DASLOTCONF6 */ | ||
397 | #define AB8500_DASLOTCONF6_DAI8TOADO6 5 | ||
398 | |||
399 | /* AB8500_DASLOTCONF7 */ | ||
400 | #define AB8500_DASLOTCONF7_DAI8TOADO7 5 | ||
401 | |||
402 | /* AB8500_DASLOTCONF8 */ | ||
403 | #define AB8500_DASLOTCONF8_DAI7TOADO8 5 | ||
404 | |||
405 | #define AB8500_DASLOTCONFX_SLTODAX_SHIFT 0 | ||
406 | #define AB8500_DASLOTCONFX_SLTODAX_MASK 0x1F | ||
407 | |||
408 | /* AB8500_CLASSDCONF1 */ | ||
409 | #define AB8500_CLASSDCONF1_PARLHF 7 | ||
410 | #define AB8500_CLASSDCONF1_PARLVIB 6 | ||
411 | #define AB8500_CLASSDCONF1_VIB1SWAPEN 3 | ||
412 | #define AB8500_CLASSDCONF1_VIB2SWAPEN 2 | ||
413 | #define AB8500_CLASSDCONF1_HFLSWAPEN 1 | ||
414 | #define AB8500_CLASSDCONF1_HFRSWAPEN 0 | ||
415 | |||
416 | /* AB8500_CLASSDCONF2 */ | ||
417 | #define AB8500_CLASSDCONF2_FIRBYP3 7 | ||
418 | #define AB8500_CLASSDCONF2_FIRBYP2 6 | ||
419 | #define AB8500_CLASSDCONF2_FIRBYP1 5 | ||
420 | #define AB8500_CLASSDCONF2_FIRBYP0 4 | ||
421 | #define AB8500_CLASSDCONF2_HIGHVOLEN3 3 | ||
422 | #define AB8500_CLASSDCONF2_HIGHVOLEN2 2 | ||
423 | #define AB8500_CLASSDCONF2_HIGHVOLEN1 1 | ||
424 | #define AB8500_CLASSDCONF2_HIGHVOLEN0 0 | ||
425 | |||
426 | /* AB8500_CLASSDCONF3 */ | ||
427 | #define AB8500_CLASSDCONF3_DITHHPGAIN 4 | ||
428 | #define AB8500_CLASSDCONF3_DITHHPGAIN_MAX 0x0A | ||
429 | #define AB8500_CLASSDCONF3_DITHWGAIN 0 | ||
430 | #define AB8500_CLASSDCONF3_DITHWGAIN_MAX 0x0A | ||
431 | |||
432 | /* AB8500_DMICFILTCONF */ | ||
433 | #define AB8500_DMICFILTCONF_ANCINSEL 7 | ||
434 | #define AB8500_DMICFILTCONF_DA3TOEAR 6 | ||
435 | #define AB8500_DMICFILTCONF_DMIC1SINC3 5 | ||
436 | #define AB8500_DMICFILTCONF_DMIC2SINC3 4 | ||
437 | #define AB8500_DMICFILTCONF_DMIC3SINC3 3 | ||
438 | #define AB8500_DMICFILTCONF_DMIC4SINC3 2 | ||
439 | #define AB8500_DMICFILTCONF_DMIC5SINC3 1 | ||
440 | #define AB8500_DMICFILTCONF_DMIC6SINC3 0 | ||
441 | |||
442 | /* AB8500_DIGMULTCONF1 */ | ||
443 | #define AB8500_DIGMULTCONF1_DATOHSLEN 7 | ||
444 | #define AB8500_DIGMULTCONF1_DATOHSREN 6 | ||
445 | #define AB8500_DIGMULTCONF1_AD1SEL 5 | ||
446 | #define AB8500_DIGMULTCONF1_AD2SEL 4 | ||
447 | #define AB8500_DIGMULTCONF1_AD3SEL 3 | ||
448 | #define AB8500_DIGMULTCONF1_AD5SEL 2 | ||
449 | #define AB8500_DIGMULTCONF1_AD6SEL 1 | ||
450 | #define AB8500_DIGMULTCONF1_ANCSEL 0 | ||
451 | |||
452 | /* AB8500_DIGMULTCONF2 */ | ||
453 | #define AB8500_DIGMULTCONF2_DATOHFREN 7 | ||
454 | #define AB8500_DIGMULTCONF2_DATOHFLEN 6 | ||
455 | #define AB8500_DIGMULTCONF2_HFRSEL 5 | ||
456 | #define AB8500_DIGMULTCONF2_HFLSEL 4 | ||
457 | #define AB8500_DIGMULTCONF2_FIRSID1SEL 2 | ||
458 | #define AB8500_DIGMULTCONF2_FIRSID2SEL 0 | ||
459 | |||
460 | /* AB8500_ADDIGGAIN1 */ | ||
461 | /* AB8500_ADDIGGAIN2 */ | ||
462 | /* AB8500_ADDIGGAIN3 */ | ||
463 | /* AB8500_ADDIGGAIN4 */ | ||
464 | /* AB8500_ADDIGGAIN5 */ | ||
465 | /* AB8500_ADDIGGAIN6 */ | ||
466 | #define AB8500_ADDIGGAINX_FADEDISADX 6 | ||
467 | #define AB8500_ADDIGGAINX_ADXGAIN_MAX 0x3F | ||
468 | |||
469 | /* AB8500_DADIGGAIN1 */ | ||
470 | /* AB8500_DADIGGAIN2 */ | ||
471 | /* AB8500_DADIGGAIN3 */ | ||
472 | /* AB8500_DADIGGAIN4 */ | ||
473 | /* AB8500_DADIGGAIN5 */ | ||
474 | /* AB8500_DADIGGAIN6 */ | ||
475 | #define AB8500_DADIGGAINX_FADEDISDAX 6 | ||
476 | #define AB8500_DADIGGAINX_DAXGAIN_MAX 0x3F | ||
477 | |||
478 | /* AB8500_ADDIGLOOPGAIN1 */ | ||
479 | /* AB8500_ADDIGLOOPGAIN2 */ | ||
480 | #define AB8500_ADDIGLOOPGAINX_FADEDISADXL 6 | ||
481 | #define AB8500_ADDIGLOOPGAINX_ADXLBGAIN_MAX 0x3F | ||
482 | |||
483 | /* AB8500_HSLEARDIGGAIN */ | ||
484 | #define AB8500_HSLEARDIGGAIN_HSSINC1 7 | ||
485 | #define AB8500_HSLEARDIGGAIN_FADEDISHSL 4 | ||
486 | #define AB8500_HSLEARDIGGAIN_HSLDGAIN_MAX 0x09 | ||
487 | |||
488 | /* AB8500_HSRDIGGAIN */ | ||
489 | #define AB8500_HSRDIGGAIN_FADESPEED 6 | ||
490 | #define AB8500_HSRDIGGAIN_FADEDISHSR 4 | ||
491 | #define AB8500_HSRDIGGAIN_HSRDGAIN_MAX 0x09 | ||
492 | |||
493 | /* AB8500_SIDFIRGAIN1 */ | ||
494 | /* AB8500_SIDFIRGAIN2 */ | ||
495 | #define AB8500_SIDFIRGAINX_FIRSIDXGAIN_MAX 0x1F | ||
496 | |||
497 | /* AB8500_ANCCONF1 */ | ||
498 | #define AB8500_ANCCONF1_ANCIIRUPDATE 3 | ||
499 | #define AB8500_ANCCONF1_ENANC 2 | ||
500 | #define AB8500_ANCCONF1_ANCIIRINIT 1 | ||
501 | #define AB8500_ANCCONF1_ANCFIRUPDATE 0 | ||
502 | |||
503 | /* AB8500_ANCCONF2 */ | ||
504 | #define AB8500_ANCCONF2_SHIFT 5 | ||
505 | #define AB8500_ANCCONF2_MIN -0x10 | ||
506 | #define AB8500_ANCCONF2_MAX 0xF | ||
507 | |||
508 | /* AB8500_ANCCONF3 */ | ||
509 | #define AB8500_ANCCONF3_SHIFT 5 | ||
510 | #define AB8500_ANCCONF3_MIN -0x10 | ||
511 | #define AB8500_ANCCONF3_MAX 0xF | ||
512 | |||
513 | /* AB8500_ANCCONF4 */ | ||
514 | #define AB8500_ANCCONF4_SHIFT 5 | ||
515 | #define AB8500_ANCCONF4_MIN -0x10 | ||
516 | #define AB8500_ANCCONF4_MAX 0xF | ||
517 | |||
518 | /* AB8500_ANC_FIR_COEFFS */ | ||
519 | #define AB8500_ANC_FIR_COEFF_MIN -0x8000 | ||
520 | #define AB8500_ANC_FIR_COEFF_MAX 0x7FFF | ||
521 | #define AB8500_ANC_FIR_COEFFS 15 | ||
522 | |||
523 | /* AB8500_ANC_IIR_COEFFS */ | ||
524 | #define AB8500_ANC_IIR_COEFF_MIN -0x800000 | ||
525 | #define AB8500_ANC_IIR_COEFF_MAX 0x7FFFFF | ||
526 | #define AB8500_ANC_IIR_COEFFS 24 | ||
527 | /* AB8500_ANC_WARP_DELAY */ | ||
528 | #define AB8500_ANC_WARP_DELAY_SHIFT 16 | ||
529 | #define AB8500_ANC_WARP_DELAY_MIN 0x0000 | ||
530 | #define AB8500_ANC_WARP_DELAY_MAX 0xFFFF | ||
531 | |||
532 | /* AB8500_ANCCONF11 */ | ||
533 | /* AB8500_ANCCONF12 */ | ||
534 | /* AB8500_ANCCONF13 */ | ||
535 | /* AB8500_ANCCONF14 */ | ||
536 | |||
537 | /* AB8500_SIDFIRADR */ | ||
538 | #define AB8500_SIDFIRADR_FIRSIDSET 7 | ||
539 | #define AB8500_SIDFIRADR_ADDRESS_SHIFT 0 | ||
540 | #define AB8500_SIDFIRADR_ADDRESS_MAX 0x7F | ||
541 | |||
542 | /* AB8500_SIDFIRCOEF1 */ | ||
543 | /* AB8500_SIDFIRCOEF2 */ | ||
544 | #define AB8500_SID_FIR_COEFF_MIN 0 | ||
545 | #define AB8500_SID_FIR_COEFF_MAX 0xFFFF | ||
546 | #define AB8500_SID_FIR_COEFFS 128 | ||
547 | |||
548 | /* AB8500_SIDFIRCONF */ | ||
549 | #define AB8500_SIDFIRCONF_ENFIRSIDS 2 | ||
550 | #define AB8500_SIDFIRCONF_FIRSIDSTOIF1 1 | ||
551 | #define AB8500_SIDFIRCONF_FIRSIDBUSY 0 | ||
552 | |||
553 | /* AB8500_AUDINTMASK1 */ | ||
554 | /* AB8500_AUDINTSOURCE1 */ | ||
555 | /* AB8500_AUDINTMASK2 */ | ||
556 | /* AB8500_AUDINTSOURCE2 */ | ||
557 | |||
558 | /* AB8500_FIFOCONF1 */ | ||
559 | #define AB8500_FIFOCONF1_BFIFOMASK 0x80 | ||
560 | #define AB8500_FIFOCONF1_BFIFO19M2 0x40 | ||
561 | #define AB8500_FIFOCONF1_BFIFOINT_SHIFT 0 | ||
562 | #define AB8500_FIFOCONF1_BFIFOINT_MAX 0x3F | ||
563 | |||
564 | /* AB8500_FIFOCONF2 */ | ||
565 | #define AB8500_FIFOCONF2_BFIFOTX_SHIFT 0 | ||
566 | #define AB8500_FIFOCONF2_BFIFOTX_MAX 0xFF | ||
567 | |||
568 | /* AB8500_FIFOCONF3 */ | ||
569 | #define AB8500_FIFOCONF3_BFIFOEXSL_SHIFT 5 | ||
570 | #define AB8500_FIFOCONF3_BFIFOEXSL_MAX 0x5 | ||
571 | #define AB8500_FIFOCONF3_PREBITCLK0_SHIFT 2 | ||
572 | #define AB8500_FIFOCONF3_PREBITCLK0_MAX 0x7 | ||
573 | #define AB8500_FIFOCONF3_BFIFOMAST_SHIFT 1 | ||
574 | #define AB8500_FIFOCONF3_BFIFORUN_SHIFT 0 | ||
575 | |||
576 | /* AB8500_FIFOCONF4 */ | ||
577 | #define AB8500_FIFOCONF4_BFIFOFRAMSW_SHIFT 0 | ||
578 | #define AB8500_FIFOCONF4_BFIFOFRAMSW_MAX 0xFF | ||
579 | |||
580 | /* AB8500_FIFOCONF5 */ | ||
581 | #define AB8500_FIFOCONF5_BFIFOWAKEUP_SHIFT 0 | ||
582 | #define AB8500_FIFOCONF5_BFIFOWAKEUP_MAX 0xFF | ||
583 | |||
584 | /* AB8500_FIFOCONF6 */ | ||
585 | #define AB8500_FIFOCONF6_BFIFOSAMPLE_SHIFT 0 | ||
586 | #define AB8500_FIFOCONF6_BFIFOSAMPLE_MAX 0xFF | ||
587 | |||
588 | /* AB8500_AUDREV */ | ||
589 | |||
590 | #endif | ||
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 2023c749f232..ea06b834a7de 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -91,11 +91,6 @@ static int ac97_soc_probe(struct snd_soc_codec *codec) | |||
91 | return 0; | 91 | return 0; |
92 | } | 92 | } |
93 | 93 | ||
94 | static int ac97_soc_remove(struct snd_soc_codec *codec) | ||
95 | { | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | #ifdef CONFIG_PM | 94 | #ifdef CONFIG_PM |
100 | static int ac97_soc_suspend(struct snd_soc_codec *codec) | 95 | static int ac97_soc_suspend(struct snd_soc_codec *codec) |
101 | { | 96 | { |
@@ -119,7 +114,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = { | |||
119 | .write = ac97_write, | 114 | .write = ac97_write, |
120 | .read = ac97_read, | 115 | .read = ac97_read, |
121 | .probe = ac97_soc_probe, | 116 | .probe = ac97_soc_probe, |
122 | .remove = ac97_soc_remove, | ||
123 | .suspend = ac97_soc_suspend, | 117 | .suspend = ac97_soc_suspend, |
124 | .resume = ac97_soc_resume, | 118 | .resume = ac97_soc_resume, |
125 | }; | 119 | }; |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c new file mode 100644 index 000000000000..5c9cacaf2d52 --- /dev/null +++ b/sound/soc/codecs/arizona.c | |||
@@ -0,0 +1,937 @@ | |||
1 | /* | ||
2 | * arizona.c - Wolfson Arizona class device shared support | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/gcd.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/pm_runtime.h> | ||
16 | #include <sound/pcm.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | #include <sound/tlv.h> | ||
19 | |||
20 | #include <linux/mfd/arizona/core.h> | ||
21 | #include <linux/mfd/arizona/registers.h> | ||
22 | |||
23 | #include "arizona.h" | ||
24 | |||
25 | #define ARIZONA_AIF_BCLK_CTRL 0x00 | ||
26 | #define ARIZONA_AIF_TX_PIN_CTRL 0x01 | ||
27 | #define ARIZONA_AIF_RX_PIN_CTRL 0x02 | ||
28 | #define ARIZONA_AIF_RATE_CTRL 0x03 | ||
29 | #define ARIZONA_AIF_FORMAT 0x04 | ||
30 | #define ARIZONA_AIF_TX_BCLK_RATE 0x05 | ||
31 | #define ARIZONA_AIF_RX_BCLK_RATE 0x06 | ||
32 | #define ARIZONA_AIF_FRAME_CTRL_1 0x07 | ||
33 | #define ARIZONA_AIF_FRAME_CTRL_2 0x08 | ||
34 | #define ARIZONA_AIF_FRAME_CTRL_3 0x09 | ||
35 | #define ARIZONA_AIF_FRAME_CTRL_4 0x0A | ||
36 | #define ARIZONA_AIF_FRAME_CTRL_5 0x0B | ||
37 | #define ARIZONA_AIF_FRAME_CTRL_6 0x0C | ||
38 | #define ARIZONA_AIF_FRAME_CTRL_7 0x0D | ||
39 | #define ARIZONA_AIF_FRAME_CTRL_8 0x0E | ||
40 | #define ARIZONA_AIF_FRAME_CTRL_9 0x0F | ||
41 | #define ARIZONA_AIF_FRAME_CTRL_10 0x10 | ||
42 | #define ARIZONA_AIF_FRAME_CTRL_11 0x11 | ||
43 | #define ARIZONA_AIF_FRAME_CTRL_12 0x12 | ||
44 | #define ARIZONA_AIF_FRAME_CTRL_13 0x13 | ||
45 | #define ARIZONA_AIF_FRAME_CTRL_14 0x14 | ||
46 | #define ARIZONA_AIF_FRAME_CTRL_15 0x15 | ||
47 | #define ARIZONA_AIF_FRAME_CTRL_16 0x16 | ||
48 | #define ARIZONA_AIF_FRAME_CTRL_17 0x17 | ||
49 | #define ARIZONA_AIF_FRAME_CTRL_18 0x18 | ||
50 | #define ARIZONA_AIF_TX_ENABLES 0x19 | ||
51 | #define ARIZONA_AIF_RX_ENABLES 0x1A | ||
52 | #define ARIZONA_AIF_FORCE_WRITE 0x1B | ||
53 | |||
54 | #define arizona_fll_err(_fll, fmt, ...) \ | ||
55 | dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) | ||
56 | #define arizona_fll_warn(_fll, fmt, ...) \ | ||
57 | dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) | ||
58 | #define arizona_fll_dbg(_fll, fmt, ...) \ | ||
59 | dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) | ||
60 | |||
61 | #define arizona_aif_err(_dai, fmt, ...) \ | ||
62 | dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) | ||
63 | #define arizona_aif_warn(_dai, fmt, ...) \ | ||
64 | dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) | ||
65 | #define arizona_aif_dbg(_dai, fmt, ...) \ | ||
66 | dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__) | ||
67 | |||
68 | const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { | ||
69 | "None", | ||
70 | "Tone Generator 1", | ||
71 | "Tone Generator 2", | ||
72 | "Haptics", | ||
73 | "AEC", | ||
74 | "Mic Mute Mixer", | ||
75 | "Noise Generator", | ||
76 | "IN1L", | ||
77 | "IN1R", | ||
78 | "IN2L", | ||
79 | "IN2R", | ||
80 | "IN3L", | ||
81 | "IN3R", | ||
82 | "IN4L", | ||
83 | "IN4R", | ||
84 | "AIF1RX1", | ||
85 | "AIF1RX2", | ||
86 | "AIF1RX3", | ||
87 | "AIF1RX4", | ||
88 | "AIF1RX5", | ||
89 | "AIF1RX6", | ||
90 | "AIF1RX7", | ||
91 | "AIF1RX8", | ||
92 | "AIF2RX1", | ||
93 | "AIF2RX2", | ||
94 | "AIF3RX1", | ||
95 | "AIF3RX2", | ||
96 | "SLIMRX1", | ||
97 | "SLIMRX2", | ||
98 | "SLIMRX3", | ||
99 | "SLIMRX4", | ||
100 | "SLIMRX5", | ||
101 | "SLIMRX6", | ||
102 | "SLIMRX7", | ||
103 | "SLIMRX8", | ||
104 | "EQ1", | ||
105 | "EQ2", | ||
106 | "EQ3", | ||
107 | "EQ4", | ||
108 | "DRC1L", | ||
109 | "DRC1R", | ||
110 | "DRC2L", | ||
111 | "DRC2R", | ||
112 | "LHPF1", | ||
113 | "LHPF2", | ||
114 | "LHPF3", | ||
115 | "LHPF4", | ||
116 | "DSP1.1", | ||
117 | "DSP1.2", | ||
118 | "DSP1.3", | ||
119 | "DSP1.4", | ||
120 | "DSP1.5", | ||
121 | "DSP1.6", | ||
122 | "ASRC1L", | ||
123 | "ASRC1R", | ||
124 | "ASRC2L", | ||
125 | "ASRC2R", | ||
126 | }; | ||
127 | EXPORT_SYMBOL_GPL(arizona_mixer_texts); | ||
128 | |||
129 | int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = { | ||
130 | 0x00, /* None */ | ||
131 | 0x04, /* Tone */ | ||
132 | 0x05, | ||
133 | 0x06, /* Haptics */ | ||
134 | 0x08, /* AEC */ | ||
135 | 0x0c, /* Noise mixer */ | ||
136 | 0x0d, /* Comfort noise */ | ||
137 | 0x10, /* IN1L */ | ||
138 | 0x11, | ||
139 | 0x12, | ||
140 | 0x13, | ||
141 | 0x14, | ||
142 | 0x15, | ||
143 | 0x16, | ||
144 | 0x17, | ||
145 | 0x20, /* AIF1RX1 */ | ||
146 | 0x21, | ||
147 | 0x22, | ||
148 | 0x23, | ||
149 | 0x24, | ||
150 | 0x25, | ||
151 | 0x26, | ||
152 | 0x27, | ||
153 | 0x28, /* AIF2RX1 */ | ||
154 | 0x29, | ||
155 | 0x30, /* AIF3RX1 */ | ||
156 | 0x31, | ||
157 | 0x38, /* SLIMRX1 */ | ||
158 | 0x39, | ||
159 | 0x3a, | ||
160 | 0x3b, | ||
161 | 0x3c, | ||
162 | 0x3d, | ||
163 | 0x3e, | ||
164 | 0x3f, | ||
165 | 0x50, /* EQ1 */ | ||
166 | 0x51, | ||
167 | 0x52, | ||
168 | 0x53, | ||
169 | 0x58, /* DRC1L */ | ||
170 | 0x59, | ||
171 | 0x5a, | ||
172 | 0x5b, | ||
173 | 0x60, /* LHPF1 */ | ||
174 | 0x61, | ||
175 | 0x62, | ||
176 | 0x63, | ||
177 | 0x68, /* DSP1.1 */ | ||
178 | 0x69, | ||
179 | 0x6a, | ||
180 | 0x6b, | ||
181 | 0x6c, | ||
182 | 0x6d, | ||
183 | 0x90, /* ASRC1L */ | ||
184 | 0x91, | ||
185 | 0x92, | ||
186 | 0x93, | ||
187 | }; | ||
188 | EXPORT_SYMBOL_GPL(arizona_mixer_values); | ||
189 | |||
190 | const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0); | ||
191 | EXPORT_SYMBOL_GPL(arizona_mixer_tlv); | ||
192 | |||
193 | static const char *arizona_lhpf_mode_text[] = { | ||
194 | "Low-pass", "High-pass" | ||
195 | }; | ||
196 | |||
197 | const struct soc_enum arizona_lhpf1_mode = | ||
198 | SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2, | ||
199 | arizona_lhpf_mode_text); | ||
200 | EXPORT_SYMBOL_GPL(arizona_lhpf1_mode); | ||
201 | |||
202 | const struct soc_enum arizona_lhpf2_mode = | ||
203 | SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2, | ||
204 | arizona_lhpf_mode_text); | ||
205 | EXPORT_SYMBOL_GPL(arizona_lhpf2_mode); | ||
206 | |||
207 | const struct soc_enum arizona_lhpf3_mode = | ||
208 | SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2, | ||
209 | arizona_lhpf_mode_text); | ||
210 | EXPORT_SYMBOL_GPL(arizona_lhpf3_mode); | ||
211 | |||
212 | const struct soc_enum arizona_lhpf4_mode = | ||
213 | SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2, | ||
214 | arizona_lhpf_mode_text); | ||
215 | EXPORT_SYMBOL_GPL(arizona_lhpf4_mode); | ||
216 | |||
217 | int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, | ||
218 | int event) | ||
219 | { | ||
220 | return 0; | ||
221 | } | ||
222 | EXPORT_SYMBOL_GPL(arizona_in_ev); | ||
223 | |||
224 | int arizona_out_ev(struct snd_soc_dapm_widget *w, | ||
225 | struct snd_kcontrol *kcontrol, | ||
226 | int event) | ||
227 | { | ||
228 | return 0; | ||
229 | } | ||
230 | EXPORT_SYMBOL_GPL(arizona_out_ev); | ||
231 | |||
232 | int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | ||
233 | int source, unsigned int freq, int dir) | ||
234 | { | ||
235 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
236 | struct arizona *arizona = priv->arizona; | ||
237 | char *name; | ||
238 | unsigned int reg; | ||
239 | unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK; | ||
240 | unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT; | ||
241 | unsigned int *clk; | ||
242 | |||
243 | switch (clk_id) { | ||
244 | case ARIZONA_CLK_SYSCLK: | ||
245 | name = "SYSCLK"; | ||
246 | reg = ARIZONA_SYSTEM_CLOCK_1; | ||
247 | clk = &priv->sysclk; | ||
248 | mask |= ARIZONA_SYSCLK_FRAC; | ||
249 | break; | ||
250 | case ARIZONA_CLK_ASYNCCLK: | ||
251 | name = "ASYNCCLK"; | ||
252 | reg = ARIZONA_ASYNC_CLOCK_1; | ||
253 | clk = &priv->asyncclk; | ||
254 | break; | ||
255 | default: | ||
256 | return -EINVAL; | ||
257 | } | ||
258 | |||
259 | switch (freq) { | ||
260 | case 5644800: | ||
261 | case 6144000: | ||
262 | break; | ||
263 | case 11289600: | ||
264 | case 12288000: | ||
265 | val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT; | ||
266 | break; | ||
267 | case 22579200: | ||
268 | case 24576000: | ||
269 | val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT; | ||
270 | break; | ||
271 | case 45158400: | ||
272 | case 49152000: | ||
273 | val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT; | ||
274 | break; | ||
275 | default: | ||
276 | return -EINVAL; | ||
277 | } | ||
278 | |||
279 | *clk = freq; | ||
280 | |||
281 | if (freq % 6144000) | ||
282 | val |= ARIZONA_SYSCLK_FRAC; | ||
283 | |||
284 | dev_dbg(arizona->dev, "%s set to %uHz", name, freq); | ||
285 | |||
286 | return regmap_update_bits(arizona->regmap, reg, mask, val); | ||
287 | } | ||
288 | EXPORT_SYMBOL_GPL(arizona_set_sysclk); | ||
289 | |||
290 | static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
291 | { | ||
292 | struct snd_soc_codec *codec = dai->codec; | ||
293 | int lrclk, bclk, mode, base; | ||
294 | |||
295 | base = dai->driver->base; | ||
296 | |||
297 | lrclk = 0; | ||
298 | bclk = 0; | ||
299 | |||
300 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
301 | case SND_SOC_DAIFMT_DSP_A: | ||
302 | mode = 0; | ||
303 | break; | ||
304 | case SND_SOC_DAIFMT_DSP_B: | ||
305 | mode = 1; | ||
306 | break; | ||
307 | case SND_SOC_DAIFMT_I2S: | ||
308 | mode = 2; | ||
309 | break; | ||
310 | case SND_SOC_DAIFMT_LEFT_J: | ||
311 | mode = 3; | ||
312 | break; | ||
313 | default: | ||
314 | arizona_aif_err(dai, "Unsupported DAI format %d\n", | ||
315 | fmt & SND_SOC_DAIFMT_FORMAT_MASK); | ||
316 | return -EINVAL; | ||
317 | } | ||
318 | |||
319 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
320 | case SND_SOC_DAIFMT_CBS_CFS: | ||
321 | break; | ||
322 | case SND_SOC_DAIFMT_CBS_CFM: | ||
323 | lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR; | ||
324 | break; | ||
325 | case SND_SOC_DAIFMT_CBM_CFS: | ||
326 | bclk |= ARIZONA_AIF1_BCLK_MSTR; | ||
327 | break; | ||
328 | case SND_SOC_DAIFMT_CBM_CFM: | ||
329 | bclk |= ARIZONA_AIF1_BCLK_MSTR; | ||
330 | lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR; | ||
331 | break; | ||
332 | default: | ||
333 | arizona_aif_err(dai, "Unsupported master mode %d\n", | ||
334 | fmt & SND_SOC_DAIFMT_MASTER_MASK); | ||
335 | return -EINVAL; | ||
336 | } | ||
337 | |||
338 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
339 | case SND_SOC_DAIFMT_NB_NF: | ||
340 | break; | ||
341 | case SND_SOC_DAIFMT_IB_IF: | ||
342 | bclk |= ARIZONA_AIF1_BCLK_INV; | ||
343 | lrclk |= ARIZONA_AIF1TX_LRCLK_INV; | ||
344 | break; | ||
345 | case SND_SOC_DAIFMT_IB_NF: | ||
346 | bclk |= ARIZONA_AIF1_BCLK_INV; | ||
347 | break; | ||
348 | case SND_SOC_DAIFMT_NB_IF: | ||
349 | lrclk |= ARIZONA_AIF1TX_LRCLK_INV; | ||
350 | break; | ||
351 | default: | ||
352 | return -EINVAL; | ||
353 | } | ||
354 | |||
355 | snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, | ||
356 | ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR, | ||
357 | bclk); | ||
358 | snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL, | ||
359 | ARIZONA_AIF1TX_LRCLK_INV | | ||
360 | ARIZONA_AIF1TX_LRCLK_MSTR, lrclk); | ||
361 | snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL, | ||
362 | ARIZONA_AIF1RX_LRCLK_INV | | ||
363 | ARIZONA_AIF1RX_LRCLK_MSTR, lrclk); | ||
364 | snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT, | ||
365 | ARIZONA_AIF1_FMT_MASK, mode); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static const int arizona_48k_bclk_rates[] = { | ||
371 | -1, | ||
372 | 48000, | ||
373 | 64000, | ||
374 | 96000, | ||
375 | 128000, | ||
376 | 192000, | ||
377 | 256000, | ||
378 | 384000, | ||
379 | 512000, | ||
380 | 768000, | ||
381 | 1024000, | ||
382 | 1536000, | ||
383 | 2048000, | ||
384 | 3072000, | ||
385 | 4096000, | ||
386 | 6144000, | ||
387 | 8192000, | ||
388 | 12288000, | ||
389 | 24576000, | ||
390 | }; | ||
391 | |||
392 | static const unsigned int arizona_48k_rates[] = { | ||
393 | 12000, | ||
394 | 24000, | ||
395 | 48000, | ||
396 | 96000, | ||
397 | 192000, | ||
398 | 384000, | ||
399 | 768000, | ||
400 | 4000, | ||
401 | 8000, | ||
402 | 16000, | ||
403 | 32000, | ||
404 | 64000, | ||
405 | 128000, | ||
406 | 256000, | ||
407 | 512000, | ||
408 | }; | ||
409 | |||
410 | static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = { | ||
411 | .count = ARRAY_SIZE(arizona_48k_rates), | ||
412 | .list = arizona_48k_rates, | ||
413 | }; | ||
414 | |||
415 | static const int arizona_44k1_bclk_rates[] = { | ||
416 | -1, | ||
417 | 44100, | ||
418 | 58800, | ||
419 | 88200, | ||
420 | 117600, | ||
421 | 177640, | ||
422 | 235200, | ||
423 | 352800, | ||
424 | 470400, | ||
425 | 705600, | ||
426 | 940800, | ||
427 | 1411200, | ||
428 | 1881600, | ||
429 | 2882400, | ||
430 | 3763200, | ||
431 | 5644800, | ||
432 | 7526400, | ||
433 | 11289600, | ||
434 | 22579200, | ||
435 | }; | ||
436 | |||
437 | static const unsigned int arizona_44k1_rates[] = { | ||
438 | 11025, | ||
439 | 22050, | ||
440 | 44100, | ||
441 | 88200, | ||
442 | 176400, | ||
443 | 352800, | ||
444 | 705600, | ||
445 | }; | ||
446 | |||
447 | static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = { | ||
448 | .count = ARRAY_SIZE(arizona_44k1_rates), | ||
449 | .list = arizona_44k1_rates, | ||
450 | }; | ||
451 | |||
452 | static int arizona_sr_vals[] = { | ||
453 | 0, | ||
454 | 12000, | ||
455 | 24000, | ||
456 | 48000, | ||
457 | 96000, | ||
458 | 192000, | ||
459 | 384000, | ||
460 | 768000, | ||
461 | 0, | ||
462 | 11025, | ||
463 | 22050, | ||
464 | 44100, | ||
465 | 88200, | ||
466 | 176400, | ||
467 | 352800, | ||
468 | 705600, | ||
469 | 4000, | ||
470 | 8000, | ||
471 | 16000, | ||
472 | 32000, | ||
473 | 64000, | ||
474 | 128000, | ||
475 | 256000, | ||
476 | 512000, | ||
477 | }; | ||
478 | |||
479 | static int arizona_startup(struct snd_pcm_substream *substream, | ||
480 | struct snd_soc_dai *dai) | ||
481 | { | ||
482 | struct snd_soc_codec *codec = dai->codec; | ||
483 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
484 | struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; | ||
485 | const struct snd_pcm_hw_constraint_list *constraint; | ||
486 | unsigned int base_rate; | ||
487 | |||
488 | switch (dai_priv->clk) { | ||
489 | case ARIZONA_CLK_SYSCLK: | ||
490 | base_rate = priv->sysclk; | ||
491 | break; | ||
492 | case ARIZONA_CLK_ASYNCCLK: | ||
493 | base_rate = priv->asyncclk; | ||
494 | break; | ||
495 | default: | ||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | if (base_rate % 8000) | ||
500 | constraint = &arizona_44k1_constraint; | ||
501 | else | ||
502 | constraint = &arizona_48k_constraint; | ||
503 | |||
504 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
505 | SNDRV_PCM_HW_PARAM_RATE, | ||
506 | constraint); | ||
507 | } | ||
508 | |||
509 | static int arizona_hw_params(struct snd_pcm_substream *substream, | ||
510 | struct snd_pcm_hw_params *params, | ||
511 | struct snd_soc_dai *dai) | ||
512 | { | ||
513 | struct snd_soc_codec *codec = dai->codec; | ||
514 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
515 | struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; | ||
516 | int base = dai->driver->base; | ||
517 | const int *rates; | ||
518 | int i; | ||
519 | int bclk, lrclk, wl, frame, sr_val; | ||
520 | |||
521 | if (params_rate(params) % 8000) | ||
522 | rates = &arizona_44k1_bclk_rates[0]; | ||
523 | else | ||
524 | rates = &arizona_48k_bclk_rates[0]; | ||
525 | |||
526 | for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { | ||
527 | if (rates[i] >= snd_soc_params_to_bclk(params) && | ||
528 | rates[i] % params_rate(params) == 0) { | ||
529 | bclk = i; | ||
530 | break; | ||
531 | } | ||
532 | } | ||
533 | if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) { | ||
534 | arizona_aif_err(dai, "Unsupported sample rate %dHz\n", | ||
535 | params_rate(params)); | ||
536 | return -EINVAL; | ||
537 | } | ||
538 | |||
539 | for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++) | ||
540 | if (arizona_sr_vals[i] == params_rate(params)) | ||
541 | break; | ||
542 | if (i == ARRAY_SIZE(arizona_sr_vals)) { | ||
543 | arizona_aif_err(dai, "Unsupported sample rate %dHz\n", | ||
544 | params_rate(params)); | ||
545 | return -EINVAL; | ||
546 | } | ||
547 | sr_val = i; | ||
548 | |||
549 | lrclk = snd_soc_params_to_bclk(params) / params_rate(params); | ||
550 | |||
551 | arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", | ||
552 | rates[bclk], rates[bclk] / lrclk); | ||
553 | |||
554 | wl = snd_pcm_format_width(params_format(params)); | ||
555 | frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; | ||
556 | |||
557 | /* | ||
558 | * We will need to be more flexible than this in future, | ||
559 | * currently we use a single sample rate for SYSCLK. | ||
560 | */ | ||
561 | switch (dai_priv->clk) { | ||
562 | case ARIZONA_CLK_SYSCLK: | ||
563 | snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1, | ||
564 | ARIZONA_SAMPLE_RATE_1_MASK, sr_val); | ||
565 | snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, | ||
566 | ARIZONA_AIF1_RATE_MASK, 0); | ||
567 | break; | ||
568 | case ARIZONA_CLK_ASYNCCLK: | ||
569 | snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, | ||
570 | ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); | ||
571 | snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, | ||
572 | ARIZONA_AIF1_RATE_MASK, 8); | ||
573 | break; | ||
574 | default: | ||
575 | arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); | ||
576 | return -EINVAL; | ||
577 | } | ||
578 | |||
579 | snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, | ||
580 | ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); | ||
581 | snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE, | ||
582 | ARIZONA_AIF1TX_BCPF_MASK, lrclk); | ||
583 | snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE, | ||
584 | ARIZONA_AIF1RX_BCPF_MASK, lrclk); | ||
585 | snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1, | ||
586 | ARIZONA_AIF1TX_WL_MASK | | ||
587 | ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); | ||
588 | snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2, | ||
589 | ARIZONA_AIF1RX_WL_MASK | | ||
590 | ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); | ||
591 | |||
592 | return 0; | ||
593 | } | ||
594 | |||
595 | static const char *arizona_dai_clk_str(int clk_id) | ||
596 | { | ||
597 | switch (clk_id) { | ||
598 | case ARIZONA_CLK_SYSCLK: | ||
599 | return "SYSCLK"; | ||
600 | case ARIZONA_CLK_ASYNCCLK: | ||
601 | return "ASYNCCLK"; | ||
602 | default: | ||
603 | return "Unknown clock"; | ||
604 | } | ||
605 | } | ||
606 | |||
607 | static int arizona_dai_set_sysclk(struct snd_soc_dai *dai, | ||
608 | int clk_id, unsigned int freq, int dir) | ||
609 | { | ||
610 | struct snd_soc_codec *codec = dai->codec; | ||
611 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
612 | struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; | ||
613 | struct snd_soc_dapm_route routes[2]; | ||
614 | |||
615 | switch (clk_id) { | ||
616 | case ARIZONA_CLK_SYSCLK: | ||
617 | case ARIZONA_CLK_ASYNCCLK: | ||
618 | break; | ||
619 | default: | ||
620 | return -EINVAL; | ||
621 | } | ||
622 | |||
623 | if (clk_id == dai_priv->clk) | ||
624 | return 0; | ||
625 | |||
626 | if (dai->active) { | ||
627 | dev_err(codec->dev, "Can't change clock on active DAI %d\n", | ||
628 | dai->id); | ||
629 | return -EBUSY; | ||
630 | } | ||
631 | |||
632 | memset(&routes, 0, sizeof(routes)); | ||
633 | routes[0].sink = dai->driver->capture.stream_name; | ||
634 | routes[1].sink = dai->driver->playback.stream_name; | ||
635 | |||
636 | routes[0].source = arizona_dai_clk_str(dai_priv->clk); | ||
637 | routes[1].source = arizona_dai_clk_str(dai_priv->clk); | ||
638 | snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes)); | ||
639 | |||
640 | routes[0].source = arizona_dai_clk_str(clk_id); | ||
641 | routes[1].source = arizona_dai_clk_str(clk_id); | ||
642 | snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes)); | ||
643 | |||
644 | return snd_soc_dapm_sync(&codec->dapm); | ||
645 | } | ||
646 | |||
647 | const struct snd_soc_dai_ops arizona_dai_ops = { | ||
648 | .startup = arizona_startup, | ||
649 | .set_fmt = arizona_set_fmt, | ||
650 | .hw_params = arizona_hw_params, | ||
651 | .set_sysclk = arizona_dai_set_sysclk, | ||
652 | }; | ||
653 | EXPORT_SYMBOL_GPL(arizona_dai_ops); | ||
654 | |||
655 | int arizona_init_dai(struct arizona_priv *priv, int id) | ||
656 | { | ||
657 | struct arizona_dai_priv *dai_priv = &priv->dai[id]; | ||
658 | |||
659 | dai_priv->clk = ARIZONA_CLK_SYSCLK; | ||
660 | |||
661 | return 0; | ||
662 | } | ||
663 | EXPORT_SYMBOL_GPL(arizona_init_dai); | ||
664 | |||
665 | static irqreturn_t arizona_fll_lock(int irq, void *data) | ||
666 | { | ||
667 | struct arizona_fll *fll = data; | ||
668 | |||
669 | arizona_fll_dbg(fll, "Locked\n"); | ||
670 | |||
671 | complete(&fll->lock); | ||
672 | |||
673 | return IRQ_HANDLED; | ||
674 | } | ||
675 | |||
676 | static irqreturn_t arizona_fll_clock_ok(int irq, void *data) | ||
677 | { | ||
678 | struct arizona_fll *fll = data; | ||
679 | |||
680 | arizona_fll_dbg(fll, "clock OK\n"); | ||
681 | |||
682 | complete(&fll->ok); | ||
683 | |||
684 | return IRQ_HANDLED; | ||
685 | } | ||
686 | |||
687 | static struct { | ||
688 | unsigned int min; | ||
689 | unsigned int max; | ||
690 | u16 fratio; | ||
691 | int ratio; | ||
692 | } fll_fratios[] = { | ||
693 | { 0, 64000, 4, 16 }, | ||
694 | { 64000, 128000, 3, 8 }, | ||
695 | { 128000, 256000, 2, 4 }, | ||
696 | { 256000, 1000000, 1, 2 }, | ||
697 | { 1000000, 13500000, 0, 1 }, | ||
698 | }; | ||
699 | |||
700 | struct arizona_fll_cfg { | ||
701 | int n; | ||
702 | int theta; | ||
703 | int lambda; | ||
704 | int refdiv; | ||
705 | int outdiv; | ||
706 | int fratio; | ||
707 | }; | ||
708 | |||
709 | static int arizona_calc_fll(struct arizona_fll *fll, | ||
710 | struct arizona_fll_cfg *cfg, | ||
711 | unsigned int Fref, | ||
712 | unsigned int Fout) | ||
713 | { | ||
714 | unsigned int target, div, gcd_fll; | ||
715 | int i, ratio; | ||
716 | |||
717 | arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout); | ||
718 | |||
719 | /* Fref must be <=13.5MHz */ | ||
720 | div = 1; | ||
721 | cfg->refdiv = 0; | ||
722 | while ((Fref / div) > 13500000) { | ||
723 | div *= 2; | ||
724 | cfg->refdiv++; | ||
725 | |||
726 | if (div > 8) { | ||
727 | arizona_fll_err(fll, | ||
728 | "Can't scale %dMHz in to <=13.5MHz\n", | ||
729 | Fref); | ||
730 | return -EINVAL; | ||
731 | } | ||
732 | } | ||
733 | |||
734 | /* Apply the division for our remaining calculations */ | ||
735 | Fref /= div; | ||
736 | |||
737 | /* Fvco should be over the targt; don't check the upper bound */ | ||
738 | div = 1; | ||
739 | while (Fout * div < 90000000 * fll->vco_mult) { | ||
740 | div++; | ||
741 | if (div > 7) { | ||
742 | arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", | ||
743 | Fout); | ||
744 | return -EINVAL; | ||
745 | } | ||
746 | } | ||
747 | target = Fout * div / fll->vco_mult; | ||
748 | cfg->outdiv = div; | ||
749 | |||
750 | arizona_fll_dbg(fll, "Fvco=%dHz\n", target); | ||
751 | |||
752 | /* Find an appropraite FLL_FRATIO and factor it out of the target */ | ||
753 | for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { | ||
754 | if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { | ||
755 | cfg->fratio = fll_fratios[i].fratio; | ||
756 | ratio = fll_fratios[i].ratio; | ||
757 | break; | ||
758 | } | ||
759 | } | ||
760 | if (i == ARRAY_SIZE(fll_fratios)) { | ||
761 | arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n", | ||
762 | Fref); | ||
763 | return -EINVAL; | ||
764 | } | ||
765 | |||
766 | cfg->n = target / (ratio * Fref); | ||
767 | |||
768 | if (target % Fref) { | ||
769 | gcd_fll = gcd(target, ratio * Fref); | ||
770 | arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll); | ||
771 | |||
772 | cfg->theta = (target - (cfg->n * ratio * Fref)) | ||
773 | / gcd_fll; | ||
774 | cfg->lambda = (ratio * Fref) / gcd_fll; | ||
775 | } else { | ||
776 | cfg->theta = 0; | ||
777 | cfg->lambda = 0; | ||
778 | } | ||
779 | |||
780 | arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n", | ||
781 | cfg->n, cfg->theta, cfg->lambda); | ||
782 | arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", | ||
783 | cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv); | ||
784 | |||
785 | return 0; | ||
786 | |||
787 | } | ||
788 | |||
789 | static void arizona_apply_fll(struct arizona *arizona, unsigned int base, | ||
790 | struct arizona_fll_cfg *cfg, int source) | ||
791 | { | ||
792 | regmap_update_bits(arizona->regmap, base + 3, | ||
793 | ARIZONA_FLL1_THETA_MASK, cfg->theta); | ||
794 | regmap_update_bits(arizona->regmap, base + 4, | ||
795 | ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda); | ||
796 | regmap_update_bits(arizona->regmap, base + 5, | ||
797 | ARIZONA_FLL1_FRATIO_MASK, | ||
798 | cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT); | ||
799 | regmap_update_bits(arizona->regmap, base + 6, | ||
800 | ARIZONA_FLL1_CLK_REF_DIV_MASK | | ||
801 | ARIZONA_FLL1_CLK_REF_SRC_MASK, | ||
802 | cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | | ||
803 | source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); | ||
804 | |||
805 | regmap_update_bits(arizona->regmap, base + 2, | ||
806 | ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, | ||
807 | ARIZONA_FLL1_CTRL_UPD | cfg->n); | ||
808 | } | ||
809 | |||
810 | int arizona_set_fll(struct arizona_fll *fll, int source, | ||
811 | unsigned int Fref, unsigned int Fout) | ||
812 | { | ||
813 | struct arizona *arizona = fll->arizona; | ||
814 | struct arizona_fll_cfg cfg, sync; | ||
815 | unsigned int reg, val; | ||
816 | int syncsrc; | ||
817 | bool ena; | ||
818 | int ret; | ||
819 | |||
820 | ret = regmap_read(arizona->regmap, fll->base + 1, ®); | ||
821 | if (ret != 0) { | ||
822 | arizona_fll_err(fll, "Failed to read current state: %d\n", | ||
823 | ret); | ||
824 | return ret; | ||
825 | } | ||
826 | ena = reg & ARIZONA_FLL1_ENA; | ||
827 | |||
828 | if (Fout) { | ||
829 | /* Do we have a 32kHz reference? */ | ||
830 | regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val); | ||
831 | switch (val & ARIZONA_CLK_32K_SRC_MASK) { | ||
832 | case ARIZONA_CLK_SRC_MCLK1: | ||
833 | case ARIZONA_CLK_SRC_MCLK2: | ||
834 | syncsrc = val & ARIZONA_CLK_32K_SRC_MASK; | ||
835 | break; | ||
836 | default: | ||
837 | syncsrc = -1; | ||
838 | } | ||
839 | |||
840 | if (source == syncsrc) | ||
841 | syncsrc = -1; | ||
842 | |||
843 | if (syncsrc >= 0) { | ||
844 | ret = arizona_calc_fll(fll, &sync, Fref, Fout); | ||
845 | if (ret != 0) | ||
846 | return ret; | ||
847 | |||
848 | ret = arizona_calc_fll(fll, &cfg, 32768, Fout); | ||
849 | if (ret != 0) | ||
850 | return ret; | ||
851 | } else { | ||
852 | ret = arizona_calc_fll(fll, &cfg, Fref, Fout); | ||
853 | if (ret != 0) | ||
854 | return ret; | ||
855 | } | ||
856 | } else { | ||
857 | regmap_update_bits(arizona->regmap, fll->base + 1, | ||
858 | ARIZONA_FLL1_ENA, 0); | ||
859 | regmap_update_bits(arizona->regmap, fll->base + 0x11, | ||
860 | ARIZONA_FLL1_SYNC_ENA, 0); | ||
861 | |||
862 | if (ena) | ||
863 | pm_runtime_put_autosuspend(arizona->dev); | ||
864 | |||
865 | return 0; | ||
866 | } | ||
867 | |||
868 | regmap_update_bits(arizona->regmap, fll->base + 5, | ||
869 | ARIZONA_FLL1_OUTDIV_MASK, | ||
870 | cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); | ||
871 | |||
872 | if (syncsrc >= 0) { | ||
873 | arizona_apply_fll(arizona, fll->base, &cfg, syncsrc); | ||
874 | arizona_apply_fll(arizona, fll->base + 0x10, &sync, source); | ||
875 | } else { | ||
876 | arizona_apply_fll(arizona, fll->base, &cfg, source); | ||
877 | } | ||
878 | |||
879 | if (!ena) | ||
880 | pm_runtime_get(arizona->dev); | ||
881 | |||
882 | /* Clear any pending completions */ | ||
883 | try_wait_for_completion(&fll->ok); | ||
884 | |||
885 | regmap_update_bits(arizona->regmap, fll->base + 1, | ||
886 | ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); | ||
887 | if (syncsrc >= 0) | ||
888 | regmap_update_bits(arizona->regmap, fll->base + 0x11, | ||
889 | ARIZONA_FLL1_SYNC_ENA, | ||
890 | ARIZONA_FLL1_SYNC_ENA); | ||
891 | |||
892 | ret = wait_for_completion_timeout(&fll->ok, | ||
893 | msecs_to_jiffies(25)); | ||
894 | if (ret == 0) | ||
895 | arizona_fll_warn(fll, "Timed out waiting for lock\n"); | ||
896 | |||
897 | return 0; | ||
898 | } | ||
899 | EXPORT_SYMBOL_GPL(arizona_set_fll); | ||
900 | |||
901 | int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, | ||
902 | int ok_irq, struct arizona_fll *fll) | ||
903 | { | ||
904 | int ret; | ||
905 | |||
906 | init_completion(&fll->lock); | ||
907 | init_completion(&fll->ok); | ||
908 | |||
909 | fll->id = id; | ||
910 | fll->base = base; | ||
911 | fll->arizona = arizona; | ||
912 | |||
913 | snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id); | ||
914 | snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name), | ||
915 | "FLL%d clock OK", id); | ||
916 | |||
917 | ret = arizona_request_irq(arizona, lock_irq, fll->lock_name, | ||
918 | arizona_fll_lock, fll); | ||
919 | if (ret != 0) { | ||
920 | dev_err(arizona->dev, "Failed to get FLL%d lock IRQ: %d\n", | ||
921 | id, ret); | ||
922 | } | ||
923 | |||
924 | ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name, | ||
925 | arizona_fll_clock_ok, fll); | ||
926 | if (ret != 0) { | ||
927 | dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n", | ||
928 | id, ret); | ||
929 | } | ||
930 | |||
931 | return 0; | ||
932 | } | ||
933 | EXPORT_SYMBOL_GPL(arizona_init_fll); | ||
934 | |||
935 | MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support"); | ||
936 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
937 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h new file mode 100644 index 000000000000..59caca8865e8 --- /dev/null +++ b/sound/soc/codecs/arizona.h | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * arizona.h - Wolfson Arizona class device shared support | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef _ASOC_ARIZONA_H | ||
14 | #define _ASOC_ARIZONA_H | ||
15 | |||
16 | #include <linux/completion.h> | ||
17 | |||
18 | #include <sound/soc.h> | ||
19 | |||
20 | #define ARIZONA_CLK_SYSCLK 1 | ||
21 | #define ARIZONA_CLK_ASYNCCLK 2 | ||
22 | |||
23 | #define ARIZONA_CLK_SRC_MCLK1 0x0 | ||
24 | #define ARIZONA_CLK_SRC_MCLK2 0x1 | ||
25 | #define ARIZONA_CLK_SRC_FLL1 0x4 | ||
26 | #define ARIZONA_CLK_SRC_FLL2 0x5 | ||
27 | #define ARIZONA_CLK_SRC_AIF1BCLK 0x8 | ||
28 | #define ARIZONA_CLK_SRC_AIF2BCLK 0x9 | ||
29 | #define ARIZONA_CLK_SRC_AIF3BCLK 0xa | ||
30 | |||
31 | #define ARIZONA_FLL_SRC_MCLK1 0 | ||
32 | #define ARIZONA_FLL_SRC_MCLK2 1 | ||
33 | #define ARIZONA_FLL_SRC_SLIMCLK 2 | ||
34 | #define ARIZONA_FLL_SRC_FLL1 3 | ||
35 | #define ARIZONA_FLL_SRC_FLL2 4 | ||
36 | #define ARIZONA_FLL_SRC_AIF1BCLK 5 | ||
37 | #define ARIZONA_FLL_SRC_AIF2BCLK 6 | ||
38 | #define ARIZONA_FLL_SRC_AIF3BCLK 7 | ||
39 | #define ARIZONA_FLL_SRC_AIF1LRCLK 8 | ||
40 | #define ARIZONA_FLL_SRC_AIF2LRCLK 9 | ||
41 | #define ARIZONA_FLL_SRC_AIF3LRCLK 10 | ||
42 | |||
43 | #define ARIZONA_MIXER_VOL_MASK 0x00FE | ||
44 | #define ARIZONA_MIXER_VOL_SHIFT 1 | ||
45 | #define ARIZONA_MIXER_VOL_WIDTH 7 | ||
46 | |||
47 | #define ARIZONA_MAX_DAI 3 | ||
48 | |||
49 | struct arizona; | ||
50 | |||
51 | struct arizona_dai_priv { | ||
52 | int clk; | ||
53 | }; | ||
54 | |||
55 | struct arizona_priv { | ||
56 | struct arizona *arizona; | ||
57 | int sysclk; | ||
58 | int asyncclk; | ||
59 | struct arizona_dai_priv dai[ARIZONA_MAX_DAI]; | ||
60 | }; | ||
61 | |||
62 | #define ARIZONA_NUM_MIXER_INPUTS 57 | ||
63 | |||
64 | extern const unsigned int arizona_mixer_tlv[]; | ||
65 | extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; | ||
66 | extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; | ||
67 | |||
68 | #define ARIZONA_MIXER_CONTROLS(name, base) \ | ||
69 | SOC_SINGLE_RANGE_TLV(name " Input 1 Volume", base + 1, \ | ||
70 | ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ | ||
71 | arizona_mixer_tlv), \ | ||
72 | SOC_SINGLE_RANGE_TLV(name " Input 2 Volume", base + 3, \ | ||
73 | ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ | ||
74 | arizona_mixer_tlv), \ | ||
75 | SOC_SINGLE_RANGE_TLV(name " Input 3 Volume", base + 5, \ | ||
76 | ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ | ||
77 | arizona_mixer_tlv), \ | ||
78 | SOC_SINGLE_RANGE_TLV(name " Input 4 Volume", base + 7, \ | ||
79 | ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ | ||
80 | arizona_mixer_tlv) | ||
81 | |||
82 | #define ARIZONA_MUX_ENUM_DECL(name, reg) \ | ||
83 | SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \ | ||
84 | arizona_mixer_texts, arizona_mixer_values) | ||
85 | |||
86 | #define ARIZONA_MUX_CTL_DECL(name) \ | ||
87 | const struct snd_kcontrol_new name##_mux = \ | ||
88 | SOC_DAPM_VALUE_ENUM("Route", name##_enum) | ||
89 | |||
90 | #define ARIZONA_MIXER_ENUMS(name, base_reg) \ | ||
91 | static ARIZONA_MUX_ENUM_DECL(name##_in1_enum, base_reg); \ | ||
92 | static ARIZONA_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \ | ||
93 | static ARIZONA_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \ | ||
94 | static ARIZONA_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \ | ||
95 | static ARIZONA_MUX_CTL_DECL(name##_in1); \ | ||
96 | static ARIZONA_MUX_CTL_DECL(name##_in2); \ | ||
97 | static ARIZONA_MUX_CTL_DECL(name##_in3); \ | ||
98 | static ARIZONA_MUX_CTL_DECL(name##_in4) | ||
99 | |||
100 | #define ARIZONA_MUX(name, ctrl) \ | ||
101 | SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) | ||
102 | |||
103 | #define ARIZONA_MIXER_WIDGETS(name, name_str) \ | ||
104 | ARIZONA_MUX(name_str " Input 1", &name##_in1_mux), \ | ||
105 | ARIZONA_MUX(name_str " Input 2", &name##_in2_mux), \ | ||
106 | ARIZONA_MUX(name_str " Input 3", &name##_in3_mux), \ | ||
107 | ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \ | ||
108 | SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) | ||
109 | |||
110 | #define ARIZONA_MIXER_ROUTES(widget, name) \ | ||
111 | { widget, NULL, name " Mixer" }, \ | ||
112 | { name " Mixer", NULL, name " Input 1" }, \ | ||
113 | { name " Mixer", NULL, name " Input 2" }, \ | ||
114 | { name " Mixer", NULL, name " Input 3" }, \ | ||
115 | { name " Mixer", NULL, name " Input 4" }, \ | ||
116 | ARIZONA_MIXER_INPUT_ROUTES(name " Input 1"), \ | ||
117 | ARIZONA_MIXER_INPUT_ROUTES(name " Input 2"), \ | ||
118 | ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \ | ||
119 | ARIZONA_MIXER_INPUT_ROUTES(name " Input 4") | ||
120 | |||
121 | extern const struct soc_enum arizona_lhpf1_mode; | ||
122 | extern const struct soc_enum arizona_lhpf2_mode; | ||
123 | extern const struct soc_enum arizona_lhpf3_mode; | ||
124 | extern const struct soc_enum arizona_lhpf4_mode; | ||
125 | |||
126 | extern int arizona_in_ev(struct snd_soc_dapm_widget *w, | ||
127 | struct snd_kcontrol *kcontrol, | ||
128 | int event); | ||
129 | extern int arizona_out_ev(struct snd_soc_dapm_widget *w, | ||
130 | struct snd_kcontrol *kcontrol, | ||
131 | int event); | ||
132 | |||
133 | extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | ||
134 | int source, unsigned int freq, int dir); | ||
135 | |||
136 | extern const struct snd_soc_dai_ops arizona_dai_ops; | ||
137 | |||
138 | #define ARIZONA_FLL_NAME_LEN 20 | ||
139 | |||
140 | struct arizona_fll { | ||
141 | struct arizona *arizona; | ||
142 | int id; | ||
143 | unsigned int base; | ||
144 | unsigned int vco_mult; | ||
145 | struct completion lock; | ||
146 | struct completion ok; | ||
147 | |||
148 | char lock_name[ARIZONA_FLL_NAME_LEN]; | ||
149 | char clock_ok_name[ARIZONA_FLL_NAME_LEN]; | ||
150 | }; | ||
151 | |||
152 | extern int arizona_init_fll(struct arizona *arizona, int id, int base, | ||
153 | int lock_irq, int ok_irq, struct arizona_fll *fll); | ||
154 | extern int arizona_set_fll(struct arizona_fll *fll, int source, | ||
155 | unsigned int Fref, unsigned int Fout); | ||
156 | |||
157 | extern int arizona_init_dai(struct arizona_priv *priv, int dai); | ||
158 | |||
159 | #endif | ||
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index a7109413aef1..628daf6a1d97 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/moduleparam.h> | 16 | #include <linux/moduleparam.h> |
17 | #include <linux/version.h> | ||
18 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
19 | #include <linux/init.h> | 18 | #include <linux/init.h> |
20 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
@@ -1217,11 +1216,11 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, | |||
1217 | return -ENOMEM; | 1216 | return -ENOMEM; |
1218 | cs42l52->dev = &i2c_client->dev; | 1217 | cs42l52->dev = &i2c_client->dev; |
1219 | 1218 | ||
1220 | cs42l52->regmap = regmap_init_i2c(i2c_client, &cs42l52_regmap); | 1219 | cs42l52->regmap = devm_regmap_init_i2c(i2c_client, &cs42l52_regmap); |
1221 | if (IS_ERR(cs42l52->regmap)) { | 1220 | if (IS_ERR(cs42l52->regmap)) { |
1222 | ret = PTR_ERR(cs42l52->regmap); | 1221 | ret = PTR_ERR(cs42l52->regmap); |
1223 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); | 1222 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); |
1224 | goto err; | 1223 | return ret; |
1225 | } | 1224 | } |
1226 | 1225 | ||
1227 | i2c_set_clientdata(i2c_client, cs42l52); | 1226 | i2c_set_clientdata(i2c_client, cs42l52); |
@@ -1243,7 +1242,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, | |||
1243 | dev_err(&i2c_client->dev, | 1242 | dev_err(&i2c_client->dev, |
1244 | "CS42L52 Device ID (%X). Expected %X\n", | 1243 | "CS42L52 Device ID (%X). Expected %X\n", |
1245 | devid, CS42L52_CHIP_ID); | 1244 | devid, CS42L52_CHIP_ID); |
1246 | goto err_regmap; | 1245 | return ret; |
1247 | } | 1246 | } |
1248 | 1247 | ||
1249 | regcache_cache_only(cs42l52->regmap, true); | 1248 | regcache_cache_only(cs42l52->regmap, true); |
@@ -1251,23 +1250,13 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, | |||
1251 | ret = snd_soc_register_codec(&i2c_client->dev, | 1250 | ret = snd_soc_register_codec(&i2c_client->dev, |
1252 | &soc_codec_dev_cs42l52, &cs42l52_dai, 1); | 1251 | &soc_codec_dev_cs42l52, &cs42l52_dai, 1); |
1253 | if (ret < 0) | 1252 | if (ret < 0) |
1254 | goto err_regmap; | 1253 | return ret; |
1255 | return 0; | 1254 | return 0; |
1256 | |||
1257 | err_regmap: | ||
1258 | regmap_exit(cs42l52->regmap); | ||
1259 | |||
1260 | err: | ||
1261 | return ret; | ||
1262 | } | 1255 | } |
1263 | 1256 | ||
1264 | static int cs42l52_i2c_remove(struct i2c_client *client) | 1257 | static int cs42l52_i2c_remove(struct i2c_client *client) |
1265 | { | 1258 | { |
1266 | struct cs42l52_private *cs42l52 = i2c_get_clientdata(client); | ||
1267 | |||
1268 | snd_soc_unregister_codec(&client->dev); | 1259 | snd_soc_unregister_codec(&client->dev); |
1269 | regmap_exit(cs42l52->regmap); | ||
1270 | |||
1271 | return 0; | 1260 | return 0; |
1272 | } | 1261 | } |
1273 | 1262 | ||
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index e0d45fdaa750..2c08c4cb465a 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -1362,11 +1362,11 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client, | |||
1362 | 1362 | ||
1363 | i2c_set_clientdata(i2c_client, cs42l73); | 1363 | i2c_set_clientdata(i2c_client, cs42l73); |
1364 | 1364 | ||
1365 | cs42l73->regmap = regmap_init_i2c(i2c_client, &cs42l73_regmap); | 1365 | cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap); |
1366 | if (IS_ERR(cs42l73->regmap)) { | 1366 | if (IS_ERR(cs42l73->regmap)) { |
1367 | ret = PTR_ERR(cs42l73->regmap); | 1367 | ret = PTR_ERR(cs42l73->regmap); |
1368 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); | 1368 | dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); |
1369 | goto err; | 1369 | return ret; |
1370 | } | 1370 | } |
1371 | /* initialize codec */ | 1371 | /* initialize codec */ |
1372 | ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, ®); | 1372 | ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, ®); |
@@ -1384,13 +1384,13 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client, | |||
1384 | dev_err(&i2c_client->dev, | 1384 | dev_err(&i2c_client->dev, |
1385 | "CS42L73 Device ID (%X). Expected %X\n", | 1385 | "CS42L73 Device ID (%X). Expected %X\n", |
1386 | devid, CS42L73_DEVID); | 1386 | devid, CS42L73_DEVID); |
1387 | goto err_regmap; | 1387 | return ret; |
1388 | } | 1388 | } |
1389 | 1389 | ||
1390 | ret = regmap_read(cs42l73->regmap, CS42L73_REVID, ®); | 1390 | ret = regmap_read(cs42l73->regmap, CS42L73_REVID, ®); |
1391 | if (ret < 0) { | 1391 | if (ret < 0) { |
1392 | dev_err(&i2c_client->dev, "Get Revision ID failed\n"); | 1392 | dev_err(&i2c_client->dev, "Get Revision ID failed\n"); |
1393 | goto err_regmap; | 1393 | return ret;; |
1394 | } | 1394 | } |
1395 | 1395 | ||
1396 | dev_info(&i2c_client->dev, | 1396 | dev_info(&i2c_client->dev, |
@@ -1402,23 +1402,13 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client, | |||
1402 | &soc_codec_dev_cs42l73, cs42l73_dai, | 1402 | &soc_codec_dev_cs42l73, cs42l73_dai, |
1403 | ARRAY_SIZE(cs42l73_dai)); | 1403 | ARRAY_SIZE(cs42l73_dai)); |
1404 | if (ret < 0) | 1404 | if (ret < 0) |
1405 | goto err_regmap; | 1405 | return ret; |
1406 | return 0; | 1406 | return 0; |
1407 | |||
1408 | err_regmap: | ||
1409 | regmap_exit(cs42l73->regmap); | ||
1410 | |||
1411 | err: | ||
1412 | return ret; | ||
1413 | } | 1407 | } |
1414 | 1408 | ||
1415 | static __devexit int cs42l73_i2c_remove(struct i2c_client *client) | 1409 | static __devexit int cs42l73_i2c_remove(struct i2c_client *client) |
1416 | { | 1410 | { |
1417 | struct cs42l73_private *cs42l73 = i2c_get_clientdata(client); | ||
1418 | |||
1419 | snd_soc_unregister_codec(&client->dev); | 1411 | snd_soc_unregister_codec(&client->dev); |
1420 | regmap_exit(cs42l73->regmap); | ||
1421 | |||
1422 | return 0; | 1412 | return 0; |
1423 | } | 1413 | } |
1424 | 1414 | ||
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c new file mode 100644 index 000000000000..01be2a320e21 --- /dev/null +++ b/sound/soc/codecs/da732x.c | |||
@@ -0,0 +1,1627 @@ | |||
1 | /* | ||
2 | * da732x.c --- Dialog DA732X ALSA SoC Audio Driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Dialog Semiconductor GmbH | ||
5 | * | ||
6 | * Author: Michal Hajduk <Michal.Hajduk@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/sysfs.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/soc-dapm.h> | ||
28 | #include <sound/initval.h> | ||
29 | #include <sound/tlv.h> | ||
30 | #include <asm/div64.h> | ||
31 | |||
32 | #include "da732x.h" | ||
33 | #include "da732x_reg.h" | ||
34 | |||
35 | |||
36 | struct da732x_priv { | ||
37 | struct regmap *regmap; | ||
38 | struct snd_soc_codec *codec; | ||
39 | |||
40 | unsigned int sysclk; | ||
41 | bool pll_en; | ||
42 | }; | ||
43 | |||
44 | /* | ||
45 | * da732x register cache - default settings | ||
46 | */ | ||
47 | static struct reg_default da732x_reg_cache[] = { | ||
48 | { DA732X_REG_REF1 , 0x02 }, | ||
49 | { DA732X_REG_BIAS_EN , 0x80 }, | ||
50 | { DA732X_REG_BIAS1 , 0x00 }, | ||
51 | { DA732X_REG_BIAS2 , 0x00 }, | ||
52 | { DA732X_REG_BIAS3 , 0x00 }, | ||
53 | { DA732X_REG_BIAS4 , 0x00 }, | ||
54 | { DA732X_REG_MICBIAS2 , 0x00 }, | ||
55 | { DA732X_REG_MICBIAS1 , 0x00 }, | ||
56 | { DA732X_REG_MICDET , 0x00 }, | ||
57 | { DA732X_REG_MIC1_PRE , 0x01 }, | ||
58 | { DA732X_REG_MIC1 , 0x40 }, | ||
59 | { DA732X_REG_MIC2_PRE , 0x01 }, | ||
60 | { DA732X_REG_MIC2 , 0x40 }, | ||
61 | { DA732X_REG_AUX1L , 0x75 }, | ||
62 | { DA732X_REG_AUX1R , 0x75 }, | ||
63 | { DA732X_REG_MIC3_PRE , 0x01 }, | ||
64 | { DA732X_REG_MIC3 , 0x40 }, | ||
65 | { DA732X_REG_INP_PINBIAS , 0x00 }, | ||
66 | { DA732X_REG_INP_ZC_EN , 0x00 }, | ||
67 | { DA732X_REG_INP_MUX , 0x50 }, | ||
68 | { DA732X_REG_HP_DET , 0x00 }, | ||
69 | { DA732X_REG_HPL_DAC_OFFSET , 0x00 }, | ||
70 | { DA732X_REG_HPL_DAC_OFF_CNTL , 0x00 }, | ||
71 | { DA732X_REG_HPL_OUT_OFFSET , 0x00 }, | ||
72 | { DA732X_REG_HPL , 0x40 }, | ||
73 | { DA732X_REG_HPL_VOL , 0x0F }, | ||
74 | { DA732X_REG_HPR_DAC_OFFSET , 0x00 }, | ||
75 | { DA732X_REG_HPR_DAC_OFF_CNTL , 0x00 }, | ||
76 | { DA732X_REG_HPR_OUT_OFFSET , 0x00 }, | ||
77 | { DA732X_REG_HPR , 0x40 }, | ||
78 | { DA732X_REG_HPR_VOL , 0x0F }, | ||
79 | { DA732X_REG_LIN2 , 0x4F }, | ||
80 | { DA732X_REG_LIN3 , 0x4F }, | ||
81 | { DA732X_REG_LIN4 , 0x4F }, | ||
82 | { DA732X_REG_OUT_ZC_EN , 0x00 }, | ||
83 | { DA732X_REG_HP_LIN1_GNDSEL , 0x00 }, | ||
84 | { DA732X_REG_CP_HP1 , 0x0C }, | ||
85 | { DA732X_REG_CP_HP2 , 0x03 }, | ||
86 | { DA732X_REG_CP_CTRL1 , 0x00 }, | ||
87 | { DA732X_REG_CP_CTRL2 , 0x99 }, | ||
88 | { DA732X_REG_CP_CTRL3 , 0x25 }, | ||
89 | { DA732X_REG_CP_LEVEL_MASK , 0x3F }, | ||
90 | { DA732X_REG_CP_DET , 0x00 }, | ||
91 | { DA732X_REG_CP_STATUS , 0x00 }, | ||
92 | { DA732X_REG_CP_THRESH1 , 0x00 }, | ||
93 | { DA732X_REG_CP_THRESH2 , 0x00 }, | ||
94 | { DA732X_REG_CP_THRESH3 , 0x00 }, | ||
95 | { DA732X_REG_CP_THRESH4 , 0x00 }, | ||
96 | { DA732X_REG_CP_THRESH5 , 0x00 }, | ||
97 | { DA732X_REG_CP_THRESH6 , 0x00 }, | ||
98 | { DA732X_REG_CP_THRESH7 , 0x00 }, | ||
99 | { DA732X_REG_CP_THRESH8 , 0x00 }, | ||
100 | { DA732X_REG_PLL_DIV_LO , 0x00 }, | ||
101 | { DA732X_REG_PLL_DIV_MID , 0x00 }, | ||
102 | { DA732X_REG_PLL_DIV_HI , 0x00 }, | ||
103 | { DA732X_REG_PLL_CTRL , 0x02 }, | ||
104 | { DA732X_REG_CLK_CTRL , 0xaa }, | ||
105 | { DA732X_REG_CLK_DSP , 0x07 }, | ||
106 | { DA732X_REG_CLK_EN1 , 0x00 }, | ||
107 | { DA732X_REG_CLK_EN2 , 0x00 }, | ||
108 | { DA732X_REG_CLK_EN3 , 0x00 }, | ||
109 | { DA732X_REG_CLK_EN4 , 0x00 }, | ||
110 | { DA732X_REG_CLK_EN5 , 0x00 }, | ||
111 | { DA732X_REG_AIF_MCLK , 0x00 }, | ||
112 | { DA732X_REG_AIFA1 , 0x02 }, | ||
113 | { DA732X_REG_AIFA2 , 0x00 }, | ||
114 | { DA732X_REG_AIFA3 , 0x08 }, | ||
115 | { DA732X_REG_AIFB1 , 0x02 }, | ||
116 | { DA732X_REG_AIFB2 , 0x00 }, | ||
117 | { DA732X_REG_AIFB3 , 0x08 }, | ||
118 | { DA732X_REG_PC_CTRL , 0xC0 }, | ||
119 | { DA732X_REG_DATA_ROUTE , 0x00 }, | ||
120 | { DA732X_REG_DSP_CTRL , 0x00 }, | ||
121 | { DA732X_REG_CIF_CTRL2 , 0x00 }, | ||
122 | { DA732X_REG_HANDSHAKE , 0x00 }, | ||
123 | { DA732X_REG_SPARE1_OUT , 0x00 }, | ||
124 | { DA732X_REG_SPARE2_OUT , 0x00 }, | ||
125 | { DA732X_REG_SPARE1_IN , 0x00 }, | ||
126 | { DA732X_REG_ADC1_PD , 0x00 }, | ||
127 | { DA732X_REG_ADC1_HPF , 0x00 }, | ||
128 | { DA732X_REG_ADC1_SEL , 0x00 }, | ||
129 | { DA732X_REG_ADC1_EQ12 , 0x00 }, | ||
130 | { DA732X_REG_ADC1_EQ34 , 0x00 }, | ||
131 | { DA732X_REG_ADC1_EQ5 , 0x00 }, | ||
132 | { DA732X_REG_ADC2_PD , 0x00 }, | ||
133 | { DA732X_REG_ADC2_HPF , 0x00 }, | ||
134 | { DA732X_REG_ADC2_SEL , 0x00 }, | ||
135 | { DA732X_REG_ADC2_EQ12 , 0x00 }, | ||
136 | { DA732X_REG_ADC2_EQ34 , 0x00 }, | ||
137 | { DA732X_REG_ADC2_EQ5 , 0x00 }, | ||
138 | { DA732X_REG_DAC1_HPF , 0x00 }, | ||
139 | { DA732X_REG_DAC1_L_VOL , 0x00 }, | ||
140 | { DA732X_REG_DAC1_R_VOL , 0x00 }, | ||
141 | { DA732X_REG_DAC1_SEL , 0x00 }, | ||
142 | { DA732X_REG_DAC1_SOFTMUTE , 0x00 }, | ||
143 | { DA732X_REG_DAC1_EQ12 , 0x00 }, | ||
144 | { DA732X_REG_DAC1_EQ34 , 0x00 }, | ||
145 | { DA732X_REG_DAC1_EQ5 , 0x00 }, | ||
146 | { DA732X_REG_DAC2_HPF , 0x00 }, | ||
147 | { DA732X_REG_DAC2_L_VOL , 0x00 }, | ||
148 | { DA732X_REG_DAC2_R_VOL , 0x00 }, | ||
149 | { DA732X_REG_DAC2_SEL , 0x00 }, | ||
150 | { DA732X_REG_DAC2_SOFTMUTE , 0x00 }, | ||
151 | { DA732X_REG_DAC2_EQ12 , 0x00 }, | ||
152 | { DA732X_REG_DAC2_EQ34 , 0x00 }, | ||
153 | { DA732X_REG_DAC2_EQ5 , 0x00 }, | ||
154 | { DA732X_REG_DAC3_HPF , 0x00 }, | ||
155 | { DA732X_REG_DAC3_VOL , 0x00 }, | ||
156 | { DA732X_REG_DAC3_SEL , 0x00 }, | ||
157 | { DA732X_REG_DAC3_SOFTMUTE , 0x00 }, | ||
158 | { DA732X_REG_DAC3_EQ12 , 0x00 }, | ||
159 | { DA732X_REG_DAC3_EQ34 , 0x00 }, | ||
160 | { DA732X_REG_DAC3_EQ5 , 0x00 }, | ||
161 | { DA732X_REG_BIQ_BYP , 0x00 }, | ||
162 | { DA732X_REG_DMA_CMD , 0x00 }, | ||
163 | { DA732X_REG_DMA_ADDR0 , 0x00 }, | ||
164 | { DA732X_REG_DMA_ADDR1 , 0x00 }, | ||
165 | { DA732X_REG_DMA_DATA0 , 0x00 }, | ||
166 | { DA732X_REG_DMA_DATA1 , 0x00 }, | ||
167 | { DA732X_REG_DMA_DATA2 , 0x00 }, | ||
168 | { DA732X_REG_DMA_DATA3 , 0x00 }, | ||
169 | { DA732X_REG_UNLOCK , 0x00 }, | ||
170 | }; | ||
171 | |||
172 | static inline int da732x_get_input_div(struct snd_soc_codec *codec, int sysclk) | ||
173 | { | ||
174 | int val; | ||
175 | int ret; | ||
176 | |||
177 | if (sysclk < DA732X_MCLK_10MHZ) { | ||
178 | val = DA732X_MCLK_RET_0_10MHZ; | ||
179 | ret = DA732X_MCLK_VAL_0_10MHZ; | ||
180 | } else if ((sysclk >= DA732X_MCLK_10MHZ) && | ||
181 | (sysclk < DA732X_MCLK_20MHZ)) { | ||
182 | val = DA732X_MCLK_RET_10_20MHZ; | ||
183 | ret = DA732X_MCLK_VAL_10_20MHZ; | ||
184 | } else if ((sysclk >= DA732X_MCLK_20MHZ) && | ||
185 | (sysclk < DA732X_MCLK_40MHZ)) { | ||
186 | val = DA732X_MCLK_RET_20_40MHZ; | ||
187 | ret = DA732X_MCLK_VAL_20_40MHZ; | ||
188 | } else if ((sysclk >= DA732X_MCLK_40MHZ) && | ||
189 | (sysclk <= DA732X_MCLK_54MHZ)) { | ||
190 | val = DA732X_MCLK_RET_40_54MHZ; | ||
191 | ret = DA732X_MCLK_VAL_40_54MHZ; | ||
192 | } else { | ||
193 | return -EINVAL; | ||
194 | } | ||
195 | |||
196 | snd_soc_write(codec, DA732X_REG_PLL_CTRL, val); | ||
197 | |||
198 | return ret; | ||
199 | } | ||
200 | |||
201 | static void da732x_set_charge_pump(struct snd_soc_codec *codec, int state) | ||
202 | { | ||
203 | switch (state) { | ||
204 | case DA732X_ENABLE_CP: | ||
205 | snd_soc_write(codec, DA732X_REG_CLK_EN2, DA732X_CP_CLK_EN); | ||
206 | snd_soc_write(codec, DA732X_REG_CP_HP2, DA732X_HP_CP_EN | | ||
207 | DA732X_HP_CP_REG | DA732X_HP_CP_PULSESKIP); | ||
208 | snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA732X_CP_EN | | ||
209 | DA732X_CP_CTRL_CPVDD1); | ||
210 | snd_soc_write(codec, DA732X_REG_CP_CTRL2, | ||
211 | DA732X_CP_MANAGE_MAGNITUDE | DA732X_CP_BOOST); | ||
212 | snd_soc_write(codec, DA732X_REG_CP_CTRL3, DA732X_CP_1MHZ); | ||
213 | break; | ||
214 | case DA732X_DISABLE_CP: | ||
215 | snd_soc_write(codec, DA732X_REG_CLK_EN2, DA732X_CP_CLK_DIS); | ||
216 | snd_soc_write(codec, DA732X_REG_CP_HP2, DA732X_HP_CP_DIS); | ||
217 | snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA723X_CP_DIS); | ||
218 | break; | ||
219 | default: | ||
220 | pr_err(KERN_ERR "Wrong charge pump state\n"); | ||
221 | break; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | static const DECLARE_TLV_DB_SCALE(mic_boost_tlv, DA732X_MIC_PRE_VOL_DB_MIN, | ||
226 | DA732X_MIC_PRE_VOL_DB_INC, 0); | ||
227 | |||
228 | static const DECLARE_TLV_DB_SCALE(mic_pga_tlv, DA732X_MIC_VOL_DB_MIN, | ||
229 | DA732X_MIC_VOL_DB_INC, 0); | ||
230 | |||
231 | static const DECLARE_TLV_DB_SCALE(aux_pga_tlv, DA732X_AUX_VOL_DB_MIN, | ||
232 | DA732X_AUX_VOL_DB_INC, 0); | ||
233 | |||
234 | static const DECLARE_TLV_DB_SCALE(hp_pga_tlv, DA732X_HP_VOL_DB_MIN, | ||
235 | DA732X_AUX_VOL_DB_INC, 0); | ||
236 | |||
237 | static const DECLARE_TLV_DB_SCALE(lin2_pga_tlv, DA732X_LIN2_VOL_DB_MIN, | ||
238 | DA732X_LIN2_VOL_DB_INC, 0); | ||
239 | |||
240 | static const DECLARE_TLV_DB_SCALE(lin3_pga_tlv, DA732X_LIN3_VOL_DB_MIN, | ||
241 | DA732X_LIN3_VOL_DB_INC, 0); | ||
242 | |||
243 | static const DECLARE_TLV_DB_SCALE(lin4_pga_tlv, DA732X_LIN4_VOL_DB_MIN, | ||
244 | DA732X_LIN4_VOL_DB_INC, 0); | ||
245 | |||
246 | static const DECLARE_TLV_DB_SCALE(adc_pga_tlv, DA732X_ADC_VOL_DB_MIN, | ||
247 | DA732X_ADC_VOL_DB_INC, 0); | ||
248 | |||
249 | static const DECLARE_TLV_DB_SCALE(dac_pga_tlv, DA732X_DAC_VOL_DB_MIN, | ||
250 | DA732X_DAC_VOL_DB_INC, 0); | ||
251 | |||
252 | static const DECLARE_TLV_DB_SCALE(eq_band_pga_tlv, DA732X_EQ_BAND_VOL_DB_MIN, | ||
253 | DA732X_EQ_BAND_VOL_DB_INC, 0); | ||
254 | |||
255 | static const DECLARE_TLV_DB_SCALE(eq_overall_tlv, DA732X_EQ_OVERALL_VOL_DB_MIN, | ||
256 | DA732X_EQ_OVERALL_VOL_DB_INC, 0); | ||
257 | |||
258 | /* High Pass Filter */ | ||
259 | static const char *da732x_hpf_mode[] = { | ||
260 | "Disable", "Music", "Voice", | ||
261 | }; | ||
262 | |||
263 | static const char *da732x_hpf_music[] = { | ||
264 | "1.8Hz", "3.75Hz", "7.5Hz", "15Hz", | ||
265 | }; | ||
266 | |||
267 | static const char *da732x_hpf_voice[] = { | ||
268 | "2.5Hz", "25Hz", "50Hz", "100Hz", | ||
269 | "150Hz", "200Hz", "300Hz", "400Hz" | ||
270 | }; | ||
271 | |||
272 | static const struct soc_enum da732x_dac1_hpf_mode_enum[] = { | ||
273 | SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT, | ||
274 | DA732X_HPF_MODE_MAX, da732x_hpf_mode) | ||
275 | }; | ||
276 | |||
277 | static const struct soc_enum da732x_dac2_hpf_mode_enum[] = { | ||
278 | SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT, | ||
279 | DA732X_HPF_MODE_MAX, da732x_hpf_mode) | ||
280 | }; | ||
281 | |||
282 | static const struct soc_enum da732x_dac3_hpf_mode_enum[] = { | ||
283 | SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT, | ||
284 | DA732X_HPF_MODE_MAX, da732x_hpf_mode) | ||
285 | }; | ||
286 | |||
287 | static const struct soc_enum da732x_adc1_hpf_mode_enum[] = { | ||
288 | SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT, | ||
289 | DA732X_HPF_MODE_MAX, da732x_hpf_mode) | ||
290 | }; | ||
291 | |||
292 | static const struct soc_enum da732x_adc2_hpf_mode_enum[] = { | ||
293 | SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT, | ||
294 | DA732X_HPF_MODE_MAX, da732x_hpf_mode) | ||
295 | }; | ||
296 | |||
297 | static const struct soc_enum da732x_dac1_hp_filter_enum[] = { | ||
298 | SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT, | ||
299 | DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | ||
300 | }; | ||
301 | |||
302 | static const struct soc_enum da732x_dac2_hp_filter_enum[] = { | ||
303 | SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT, | ||
304 | DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | ||
305 | }; | ||
306 | |||
307 | static const struct soc_enum da732x_dac3_hp_filter_enum[] = { | ||
308 | SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT, | ||
309 | DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | ||
310 | }; | ||
311 | |||
312 | static const struct soc_enum da732x_adc1_hp_filter_enum[] = { | ||
313 | SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT, | ||
314 | DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | ||
315 | }; | ||
316 | |||
317 | static const struct soc_enum da732x_adc2_hp_filter_enum[] = { | ||
318 | SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT, | ||
319 | DA732X_HPF_MUSIC_MAX, da732x_hpf_music) | ||
320 | }; | ||
321 | |||
322 | static const struct soc_enum da732x_dac1_voice_filter_enum[] = { | ||
323 | SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT, | ||
324 | DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | ||
325 | }; | ||
326 | |||
327 | static const struct soc_enum da732x_dac2_voice_filter_enum[] = { | ||
328 | SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT, | ||
329 | DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | ||
330 | }; | ||
331 | |||
332 | static const struct soc_enum da732x_dac3_voice_filter_enum[] = { | ||
333 | SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT, | ||
334 | DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | ||
335 | }; | ||
336 | |||
337 | static const struct soc_enum da732x_adc1_voice_filter_enum[] = { | ||
338 | SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT, | ||
339 | DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | ||
340 | }; | ||
341 | |||
342 | static const struct soc_enum da732x_adc2_voice_filter_enum[] = { | ||
343 | SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT, | ||
344 | DA732X_HPF_VOICE_MAX, da732x_hpf_voice) | ||
345 | }; | ||
346 | |||
347 | |||
348 | static int da732x_hpf_set(struct snd_kcontrol *kcontrol, | ||
349 | struct snd_ctl_elem_value *ucontrol) | ||
350 | { | ||
351 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
352 | struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value; | ||
353 | unsigned int reg = enum_ctrl->reg; | ||
354 | unsigned int sel = ucontrol->value.integer.value[0]; | ||
355 | unsigned int bits; | ||
356 | |||
357 | switch (sel) { | ||
358 | case DA732X_HPF_DISABLED: | ||
359 | bits = DA732X_HPF_DIS; | ||
360 | break; | ||
361 | case DA732X_HPF_VOICE: | ||
362 | bits = DA732X_HPF_VOICE_EN; | ||
363 | break; | ||
364 | case DA732X_HPF_MUSIC: | ||
365 | bits = DA732X_HPF_MUSIC_EN; | ||
366 | break; | ||
367 | default: | ||
368 | return -EINVAL; | ||
369 | } | ||
370 | |||
371 | snd_soc_update_bits(codec, reg, DA732X_HPF_MASK, bits); | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static int da732x_hpf_get(struct snd_kcontrol *kcontrol, | ||
377 | struct snd_ctl_elem_value *ucontrol) | ||
378 | { | ||
379 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
380 | struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value; | ||
381 | unsigned int reg = enum_ctrl->reg; | ||
382 | int val; | ||
383 | |||
384 | val = snd_soc_read(codec, reg) & DA732X_HPF_MASK; | ||
385 | |||
386 | switch (val) { | ||
387 | case DA732X_HPF_VOICE_EN: | ||
388 | ucontrol->value.integer.value[0] = DA732X_HPF_VOICE; | ||
389 | break; | ||
390 | case DA732X_HPF_MUSIC_EN: | ||
391 | ucontrol->value.integer.value[0] = DA732X_HPF_MUSIC; | ||
392 | break; | ||
393 | default: | ||
394 | ucontrol->value.integer.value[0] = DA732X_HPF_DISABLED; | ||
395 | break; | ||
396 | } | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static const struct snd_kcontrol_new da732x_snd_controls[] = { | ||
402 | /* Input PGAs */ | ||
403 | SOC_SINGLE_RANGE_TLV("MIC1 Boost Volume", DA732X_REG_MIC1_PRE, | ||
404 | DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN, | ||
405 | DA732X_MICBOOST_MAX, 0, mic_boost_tlv), | ||
406 | SOC_SINGLE_RANGE_TLV("MIC2 Boost Volume", DA732X_REG_MIC2_PRE, | ||
407 | DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN, | ||
408 | DA732X_MICBOOST_MAX, 0, mic_boost_tlv), | ||
409 | SOC_SINGLE_RANGE_TLV("MIC3 Boost Volume", DA732X_REG_MIC3_PRE, | ||
410 | DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN, | ||
411 | DA732X_MICBOOST_MAX, 0, mic_boost_tlv), | ||
412 | |||
413 | /* MICs */ | ||
414 | SOC_SINGLE("MIC1 Switch", DA732X_REG_MIC1, DA732X_MIC_MUTE_SHIFT, | ||
415 | DA732X_SWITCH_MAX, DA732X_INVERT), | ||
416 | SOC_SINGLE_RANGE_TLV("MIC1 Volume", DA732X_REG_MIC1, | ||
417 | DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN, | ||
418 | DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv), | ||
419 | SOC_SINGLE("MIC2 Switch", DA732X_REG_MIC2, DA732X_MIC_MUTE_SHIFT, | ||
420 | DA732X_SWITCH_MAX, DA732X_INVERT), | ||
421 | SOC_SINGLE_RANGE_TLV("MIC2 Volume", DA732X_REG_MIC2, | ||
422 | DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN, | ||
423 | DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv), | ||
424 | SOC_SINGLE("MIC3 Switch", DA732X_REG_MIC3, DA732X_MIC_MUTE_SHIFT, | ||
425 | DA732X_SWITCH_MAX, DA732X_INVERT), | ||
426 | SOC_SINGLE_RANGE_TLV("MIC3 Volume", DA732X_REG_MIC3, | ||
427 | DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN, | ||
428 | DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv), | ||
429 | |||
430 | /* AUXs */ | ||
431 | SOC_SINGLE("AUX1L Switch", DA732X_REG_AUX1L, DA732X_AUX_MUTE_SHIFT, | ||
432 | DA732X_SWITCH_MAX, DA732X_INVERT), | ||
433 | SOC_SINGLE_TLV("AUX1L Volume", DA732X_REG_AUX1L, | ||
434 | DA732X_AUX_VOL_SHIFT, DA732X_AUX_VOL_VAL_MAX, | ||
435 | DA732X_NO_INVERT, aux_pga_tlv), | ||
436 | SOC_SINGLE("AUX1R Switch", DA732X_REG_AUX1R, DA732X_AUX_MUTE_SHIFT, | ||
437 | DA732X_SWITCH_MAX, DA732X_INVERT), | ||
438 | SOC_SINGLE_TLV("AUX1R Volume", DA732X_REG_AUX1R, | ||
439 | DA732X_AUX_VOL_SHIFT, DA732X_AUX_VOL_VAL_MAX, | ||
440 | DA732X_NO_INVERT, aux_pga_tlv), | ||
441 | |||
442 | /* ADCs */ | ||
443 | SOC_DOUBLE_TLV("ADC1 Volume", DA732X_REG_ADC1_SEL, | ||
444 | DA732X_ADCL_VOL_SHIFT, DA732X_ADCR_VOL_SHIFT, | ||
445 | DA732X_ADC_VOL_VAL_MAX, DA732X_INVERT, adc_pga_tlv), | ||
446 | |||
447 | SOC_DOUBLE_TLV("ADC2 Volume", DA732X_REG_ADC2_SEL, | ||
448 | DA732X_ADCL_VOL_SHIFT, DA732X_ADCR_VOL_SHIFT, | ||
449 | DA732X_ADC_VOL_VAL_MAX, DA732X_INVERT, adc_pga_tlv), | ||
450 | |||
451 | /* DACs */ | ||
452 | SOC_DOUBLE("Digital Playback DAC12 Switch", DA732X_REG_DAC1_SEL, | ||
453 | DA732X_DACL_MUTE_SHIFT, DA732X_DACR_MUTE_SHIFT, | ||
454 | DA732X_SWITCH_MAX, DA732X_INVERT), | ||
455 | SOC_DOUBLE_R_TLV("Digital Playback DAC12 Volume", DA732X_REG_DAC1_L_VOL, | ||
456 | DA732X_REG_DAC1_R_VOL, DA732X_DAC_VOL_SHIFT, | ||
457 | DA732X_DAC_VOL_VAL_MAX, DA732X_INVERT, dac_pga_tlv), | ||
458 | SOC_SINGLE("Digital Playback DAC3 Switch", DA732X_REG_DAC2_SEL, | ||
459 | DA732X_DACL_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT), | ||
460 | SOC_SINGLE_TLV("Digital Playback DAC3 Volume", DA732X_REG_DAC2_L_VOL, | ||
461 | DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX, | ||
462 | DA732X_INVERT, dac_pga_tlv), | ||
463 | SOC_SINGLE("Digital Playback DAC4 Switch", DA732X_REG_DAC2_SEL, | ||
464 | DA732X_DACR_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT), | ||
465 | SOC_SINGLE_TLV("Digital Playback DAC4 Volume", DA732X_REG_DAC2_R_VOL, | ||
466 | DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX, | ||
467 | DA732X_INVERT, dac_pga_tlv), | ||
468 | SOC_SINGLE("Digital Playback DAC5 Switch", DA732X_REG_DAC3_SEL, | ||
469 | DA732X_DACL_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT), | ||
470 | SOC_SINGLE_TLV("Digital Playback DAC5 Volume", DA732X_REG_DAC3_VOL, | ||
471 | DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX, | ||
472 | DA732X_INVERT, dac_pga_tlv), | ||
473 | |||
474 | /* High Pass Filters */ | ||
475 | SOC_ENUM_EXT("DAC1 High Pass Filter Mode", | ||
476 | da732x_dac1_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), | ||
477 | SOC_ENUM("DAC1 High Pass Filter", da732x_dac1_hp_filter_enum), | ||
478 | SOC_ENUM("DAC1 Voice Filter", da732x_dac1_voice_filter_enum), | ||
479 | |||
480 | SOC_ENUM_EXT("DAC2 High Pass Filter Mode", | ||
481 | da732x_dac2_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), | ||
482 | SOC_ENUM("DAC2 High Pass Filter", da732x_dac2_hp_filter_enum), | ||
483 | SOC_ENUM("DAC2 Voice Filter", da732x_dac2_voice_filter_enum), | ||
484 | |||
485 | SOC_ENUM_EXT("DAC3 High Pass Filter Mode", | ||
486 | da732x_dac3_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), | ||
487 | SOC_ENUM("DAC3 High Pass Filter", da732x_dac3_hp_filter_enum), | ||
488 | SOC_ENUM("DAC3 Filter Mode", da732x_dac3_voice_filter_enum), | ||
489 | |||
490 | SOC_ENUM_EXT("ADC1 High Pass Filter Mode", | ||
491 | da732x_adc1_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), | ||
492 | SOC_ENUM("ADC1 High Pass Filter", da732x_adc1_hp_filter_enum), | ||
493 | SOC_ENUM("ADC1 Voice Filter", da732x_adc1_voice_filter_enum), | ||
494 | |||
495 | SOC_ENUM_EXT("ADC2 High Pass Filter Mode", | ||
496 | da732x_adc2_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set), | ||
497 | SOC_ENUM("ADC2 High Pass Filter", da732x_adc2_hp_filter_enum), | ||
498 | SOC_ENUM("ADC2 Voice Filter", da732x_adc2_voice_filter_enum), | ||
499 | |||
500 | /* Equalizers */ | ||
501 | SOC_SINGLE("ADC1 EQ Switch", DA732X_REG_ADC1_EQ5, | ||
502 | DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), | ||
503 | SOC_SINGLE_TLV("ADC1 EQ Band 1 Volume", DA732X_REG_ADC1_EQ12, | ||
504 | DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
505 | DA732X_INVERT, eq_band_pga_tlv), | ||
506 | SOC_SINGLE_TLV("ADC1 EQ Band 2 Volume", DA732X_REG_ADC1_EQ12, | ||
507 | DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
508 | DA732X_INVERT, eq_band_pga_tlv), | ||
509 | SOC_SINGLE_TLV("ADC1 EQ Band 3 Volume", DA732X_REG_ADC1_EQ34, | ||
510 | DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
511 | DA732X_INVERT, eq_band_pga_tlv), | ||
512 | SOC_SINGLE_TLV("ADC1 EQ Band 4 Volume", DA732X_REG_ADC1_EQ34, | ||
513 | DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
514 | DA732X_INVERT, eq_band_pga_tlv), | ||
515 | SOC_SINGLE_TLV("ADC1 EQ Band 5 Volume", DA732X_REG_ADC1_EQ5, | ||
516 | DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
517 | DA732X_INVERT, eq_band_pga_tlv), | ||
518 | SOC_SINGLE_TLV("ADC1 EQ Overall Volume", DA732X_REG_ADC1_EQ5, | ||
519 | DA732X_EQ_OVERALL_SHIFT, DA732X_EQ_OVERALL_VOL_VAL_MAX, | ||
520 | DA732X_INVERT, eq_overall_tlv), | ||
521 | |||
522 | SOC_SINGLE("ADC2 EQ Switch", DA732X_REG_ADC2_EQ5, | ||
523 | DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), | ||
524 | SOC_SINGLE_TLV("ADC2 EQ Band 1 Volume", DA732X_REG_ADC2_EQ12, | ||
525 | DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
526 | DA732X_INVERT, eq_band_pga_tlv), | ||
527 | SOC_SINGLE_TLV("ADC2 EQ Band 2 Volume", DA732X_REG_ADC2_EQ12, | ||
528 | DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
529 | DA732X_INVERT, eq_band_pga_tlv), | ||
530 | SOC_SINGLE_TLV("ADC2 EQ Band 3 Volume", DA732X_REG_ADC2_EQ34, | ||
531 | DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
532 | DA732X_INVERT, eq_band_pga_tlv), | ||
533 | SOC_SINGLE_TLV("ACD2 EQ Band 4 Volume", DA732X_REG_ADC2_EQ34, | ||
534 | DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
535 | DA732X_INVERT, eq_band_pga_tlv), | ||
536 | SOC_SINGLE_TLV("ACD2 EQ Band 5 Volume", DA732X_REG_ADC2_EQ5, | ||
537 | DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
538 | DA732X_INVERT, eq_band_pga_tlv), | ||
539 | SOC_SINGLE_TLV("ADC2 EQ Overall Volume", DA732X_REG_ADC1_EQ5, | ||
540 | DA732X_EQ_OVERALL_SHIFT, DA732X_EQ_OVERALL_VOL_VAL_MAX, | ||
541 | DA732X_INVERT, eq_overall_tlv), | ||
542 | |||
543 | SOC_SINGLE("DAC1 EQ Switch", DA732X_REG_DAC1_EQ5, | ||
544 | DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), | ||
545 | SOC_SINGLE_TLV("DAC1 EQ Band 1 Volume", DA732X_REG_DAC1_EQ12, | ||
546 | DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
547 | DA732X_INVERT, eq_band_pga_tlv), | ||
548 | SOC_SINGLE_TLV("DAC1 EQ Band 2 Volume", DA732X_REG_DAC1_EQ12, | ||
549 | DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
550 | DA732X_INVERT, eq_band_pga_tlv), | ||
551 | SOC_SINGLE_TLV("DAC1 EQ Band 3 Volume", DA732X_REG_DAC1_EQ34, | ||
552 | DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
553 | DA732X_INVERT, eq_band_pga_tlv), | ||
554 | SOC_SINGLE_TLV("DAC1 EQ Band 4 Volume", DA732X_REG_DAC1_EQ34, | ||
555 | DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
556 | DA732X_INVERT, eq_band_pga_tlv), | ||
557 | SOC_SINGLE_TLV("DAC1 EQ Band 5 Volume", DA732X_REG_DAC1_EQ5, | ||
558 | DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
559 | DA732X_INVERT, eq_band_pga_tlv), | ||
560 | |||
561 | SOC_SINGLE("DAC2 EQ Switch", DA732X_REG_DAC2_EQ5, | ||
562 | DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), | ||
563 | SOC_SINGLE_TLV("DAC2 EQ Band 1 Volume", DA732X_REG_DAC2_EQ12, | ||
564 | DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
565 | DA732X_INVERT, eq_band_pga_tlv), | ||
566 | SOC_SINGLE_TLV("DAC2 EQ Band 2 Volume", DA732X_REG_DAC2_EQ12, | ||
567 | DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
568 | DA732X_INVERT, eq_band_pga_tlv), | ||
569 | SOC_SINGLE_TLV("DAC2 EQ Band 3 Volume", DA732X_REG_DAC2_EQ34, | ||
570 | DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
571 | DA732X_INVERT, eq_band_pga_tlv), | ||
572 | SOC_SINGLE_TLV("DAC2 EQ Band 4 Volume", DA732X_REG_DAC2_EQ34, | ||
573 | DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
574 | DA732X_INVERT, eq_band_pga_tlv), | ||
575 | SOC_SINGLE_TLV("DAC2 EQ Band 5 Volume", DA732X_REG_DAC2_EQ5, | ||
576 | DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
577 | DA732X_INVERT, eq_band_pga_tlv), | ||
578 | |||
579 | SOC_SINGLE("DAC3 EQ Switch", DA732X_REG_DAC3_EQ5, | ||
580 | DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT), | ||
581 | SOC_SINGLE_TLV("DAC3 EQ Band 1 Volume", DA732X_REG_DAC3_EQ12, | ||
582 | DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
583 | DA732X_INVERT, eq_band_pga_tlv), | ||
584 | SOC_SINGLE_TLV("DAC3 EQ Band 2 Volume", DA732X_REG_DAC3_EQ12, | ||
585 | DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
586 | DA732X_INVERT, eq_band_pga_tlv), | ||
587 | SOC_SINGLE_TLV("DAC3 EQ Band 3 Volume", DA732X_REG_DAC3_EQ34, | ||
588 | DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
589 | DA732X_INVERT, eq_band_pga_tlv), | ||
590 | SOC_SINGLE_TLV("DAC3 EQ Band 4 Volume", DA732X_REG_DAC3_EQ34, | ||
591 | DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
592 | DA732X_INVERT, eq_band_pga_tlv), | ||
593 | SOC_SINGLE_TLV("DAC3 EQ Band 5 Volume", DA732X_REG_DAC3_EQ5, | ||
594 | DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX, | ||
595 | DA732X_INVERT, eq_band_pga_tlv), | ||
596 | |||
597 | /* Lineout 2 Reciever*/ | ||
598 | SOC_SINGLE("Lineout 2 Switch", DA732X_REG_LIN2, DA732X_LOUT_MUTE_SHIFT, | ||
599 | DA732X_SWITCH_MAX, DA732X_INVERT), | ||
600 | SOC_SINGLE_TLV("Lineout 2 Volume", DA732X_REG_LIN2, | ||
601 | DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX, | ||
602 | DA732X_NO_INVERT, lin2_pga_tlv), | ||
603 | |||
604 | /* Lineout 3 SPEAKER*/ | ||
605 | SOC_SINGLE("Lineout 3 Switch", DA732X_REG_LIN3, DA732X_LOUT_MUTE_SHIFT, | ||
606 | DA732X_SWITCH_MAX, DA732X_INVERT), | ||
607 | SOC_SINGLE_TLV("Lineout 3 Volume", DA732X_REG_LIN3, | ||
608 | DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX, | ||
609 | DA732X_NO_INVERT, lin3_pga_tlv), | ||
610 | |||
611 | /* Lineout 4 */ | ||
612 | SOC_SINGLE("Lineout 4 Switch", DA732X_REG_LIN4, DA732X_LOUT_MUTE_SHIFT, | ||
613 | DA732X_SWITCH_MAX, DA732X_INVERT), | ||
614 | SOC_SINGLE_TLV("Lineout 4 Volume", DA732X_REG_LIN4, | ||
615 | DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX, | ||
616 | DA732X_NO_INVERT, lin4_pga_tlv), | ||
617 | |||
618 | /* Headphones */ | ||
619 | SOC_DOUBLE_R("Headphone Switch", DA732X_REG_HPR, DA732X_REG_HPL, | ||
620 | DA732X_HP_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT), | ||
621 | SOC_DOUBLE_R_TLV("Headphone Volume", DA732X_REG_HPL_VOL, | ||
622 | DA732X_REG_HPR_VOL, DA732X_HP_VOL_SHIFT, | ||
623 | DA732X_HP_VOL_VAL_MAX, DA732X_NO_INVERT, hp_pga_tlv), | ||
624 | }; | ||
625 | |||
626 | static int da732x_adc_event(struct snd_soc_dapm_widget *w, | ||
627 | struct snd_kcontrol *kcontrol, int event) | ||
628 | { | ||
629 | struct snd_soc_codec *codec = w->codec; | ||
630 | |||
631 | switch (event) { | ||
632 | case SND_SOC_DAPM_POST_PMU: | ||
633 | switch (w->reg) { | ||
634 | case DA732X_REG_ADC1_PD: | ||
635 | snd_soc_update_bits(codec, DA732X_REG_CLK_EN3, | ||
636 | DA732X_ADCA_BB_CLK_EN, | ||
637 | DA732X_ADCA_BB_CLK_EN); | ||
638 | break; | ||
639 | case DA732X_REG_ADC2_PD: | ||
640 | snd_soc_update_bits(codec, DA732X_REG_CLK_EN3, | ||
641 | DA732X_ADCC_BB_CLK_EN, | ||
642 | DA732X_ADCC_BB_CLK_EN); | ||
643 | break; | ||
644 | default: | ||
645 | return -EINVAL; | ||
646 | } | ||
647 | |||
648 | snd_soc_update_bits(codec, w->reg, DA732X_ADC_RST_MASK, | ||
649 | DA732X_ADC_SET_ACT); | ||
650 | snd_soc_update_bits(codec, w->reg, DA732X_ADC_PD_MASK, | ||
651 | DA732X_ADC_ON); | ||
652 | break; | ||
653 | case SND_SOC_DAPM_POST_PMD: | ||
654 | snd_soc_update_bits(codec, w->reg, DA732X_ADC_PD_MASK, | ||
655 | DA732X_ADC_OFF); | ||
656 | snd_soc_update_bits(codec, w->reg, DA732X_ADC_RST_MASK, | ||
657 | DA732X_ADC_SET_RST); | ||
658 | |||
659 | switch (w->reg) { | ||
660 | case DA732X_REG_ADC1_PD: | ||
661 | snd_soc_update_bits(codec, DA732X_REG_CLK_EN3, | ||
662 | DA732X_ADCA_BB_CLK_EN, 0); | ||
663 | break; | ||
664 | case DA732X_REG_ADC2_PD: | ||
665 | snd_soc_update_bits(codec, DA732X_REG_CLK_EN3, | ||
666 | DA732X_ADCC_BB_CLK_EN, 0); | ||
667 | break; | ||
668 | default: | ||
669 | return -EINVAL; | ||
670 | } | ||
671 | |||
672 | break; | ||
673 | default: | ||
674 | return -EINVAL; | ||
675 | } | ||
676 | |||
677 | return 0; | ||
678 | } | ||
679 | |||
680 | static int da732x_out_pga_event(struct snd_soc_dapm_widget *w, | ||
681 | struct snd_kcontrol *kcontrol, int event) | ||
682 | { | ||
683 | struct snd_soc_codec *codec = w->codec; | ||
684 | |||
685 | switch (event) { | ||
686 | case SND_SOC_DAPM_POST_PMU: | ||
687 | snd_soc_update_bits(codec, w->reg, | ||
688 | (1 << w->shift) | DA732X_OUT_HIZ_EN, | ||
689 | (1 << w->shift) | DA732X_OUT_HIZ_EN); | ||
690 | break; | ||
691 | case SND_SOC_DAPM_POST_PMD: | ||
692 | snd_soc_update_bits(codec, w->reg, | ||
693 | (1 << w->shift) | DA732X_OUT_HIZ_EN, | ||
694 | (1 << w->shift) | DA732X_OUT_HIZ_DIS); | ||
695 | break; | ||
696 | default: | ||
697 | return -EINVAL; | ||
698 | } | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | static const char *adcl_text[] = { | ||
704 | "AUX1L", "MIC1" | ||
705 | }; | ||
706 | |||
707 | static const char *adcr_text[] = { | ||
708 | "AUX1R", "MIC2", "MIC3" | ||
709 | }; | ||
710 | |||
711 | static const char *enable_text[] = { | ||
712 | "Disabled", | ||
713 | "Enabled" | ||
714 | }; | ||
715 | |||
716 | /* ADC1LMUX */ | ||
717 | static const struct soc_enum adc1l_enum = | ||
718 | SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT, | ||
719 | DA732X_ADCL_MUX_MAX, adcl_text); | ||
720 | static const struct snd_kcontrol_new adc1l_mux = | ||
721 | SOC_DAPM_ENUM("ADC Route", adc1l_enum); | ||
722 | |||
723 | /* ADC1RMUX */ | ||
724 | static const struct soc_enum adc1r_enum = | ||
725 | SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT, | ||
726 | DA732X_ADCR_MUX_MAX, adcr_text); | ||
727 | static const struct snd_kcontrol_new adc1r_mux = | ||
728 | SOC_DAPM_ENUM("ADC Route", adc1r_enum); | ||
729 | |||
730 | /* ADC2LMUX */ | ||
731 | static const struct soc_enum adc2l_enum = | ||
732 | SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT, | ||
733 | DA732X_ADCL_MUX_MAX, adcl_text); | ||
734 | static const struct snd_kcontrol_new adc2l_mux = | ||
735 | SOC_DAPM_ENUM("ADC Route", adc2l_enum); | ||
736 | |||
737 | /* ADC2RMUX */ | ||
738 | static const struct soc_enum adc2r_enum = | ||
739 | SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT, | ||
740 | DA732X_ADCR_MUX_MAX, adcr_text); | ||
741 | |||
742 | static const struct snd_kcontrol_new adc2r_mux = | ||
743 | SOC_DAPM_ENUM("ADC Route", adc2r_enum); | ||
744 | |||
745 | static const struct soc_enum da732x_hp_left_output = | ||
746 | SOC_ENUM_SINGLE(DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT, | ||
747 | DA732X_DAC_EN_MAX, enable_text); | ||
748 | |||
749 | static const struct snd_kcontrol_new hpl_mux = | ||
750 | SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output); | ||
751 | |||
752 | static const struct soc_enum da732x_hp_right_output = | ||
753 | SOC_ENUM_SINGLE(DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT, | ||
754 | DA732X_DAC_EN_MAX, enable_text); | ||
755 | |||
756 | static const struct snd_kcontrol_new hpr_mux = | ||
757 | SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output); | ||
758 | |||
759 | static const struct soc_enum da732x_speaker_output = | ||
760 | SOC_ENUM_SINGLE(DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT, | ||
761 | DA732X_DAC_EN_MAX, enable_text); | ||
762 | |||
763 | static const struct snd_kcontrol_new spk_mux = | ||
764 | SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output); | ||
765 | |||
766 | static const struct soc_enum da732x_lout4_output = | ||
767 | SOC_ENUM_SINGLE(DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT, | ||
768 | DA732X_DAC_EN_MAX, enable_text); | ||
769 | |||
770 | static const struct snd_kcontrol_new lout4_mux = | ||
771 | SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output); | ||
772 | |||
773 | static const struct soc_enum da732x_lout2_output = | ||
774 | SOC_ENUM_SINGLE(DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT, | ||
775 | DA732X_DAC_EN_MAX, enable_text); | ||
776 | |||
777 | static const struct snd_kcontrol_new lout2_mux = | ||
778 | SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output); | ||
779 | |||
780 | static const struct snd_soc_dapm_widget da732x_dapm_widgets[] = { | ||
781 | /* Supplies */ | ||
782 | SND_SOC_DAPM_SUPPLY("ADC1 Supply", DA732X_REG_ADC1_PD, 0, | ||
783 | DA732X_NO_INVERT, da732x_adc_event, | ||
784 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
785 | SND_SOC_DAPM_SUPPLY("ADC2 Supply", DA732X_REG_ADC2_PD, 0, | ||
786 | DA732X_NO_INVERT, da732x_adc_event, | ||
787 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
788 | SND_SOC_DAPM_SUPPLY("DAC1 CLK", DA732X_REG_CLK_EN4, | ||
789 | DA732X_DACA_BB_CLK_SHIFT, DA732X_NO_INVERT, | ||
790 | NULL, 0), | ||
791 | SND_SOC_DAPM_SUPPLY("DAC2 CLK", DA732X_REG_CLK_EN4, | ||
792 | DA732X_DACC_BB_CLK_SHIFT, DA732X_NO_INVERT, | ||
793 | NULL, 0), | ||
794 | SND_SOC_DAPM_SUPPLY("DAC3 CLK", DA732X_REG_CLK_EN5, | ||
795 | DA732X_DACE_BB_CLK_SHIFT, DA732X_NO_INVERT, | ||
796 | NULL, 0), | ||
797 | |||
798 | /* Micbias */ | ||
799 | SND_SOC_DAPM_SUPPLY("MICBIAS1", DA732X_REG_MICBIAS1, | ||
800 | DA732X_MICBIAS_EN_SHIFT, | ||
801 | DA732X_NO_INVERT, NULL, 0), | ||
802 | SND_SOC_DAPM_SUPPLY("MICBIAS2", DA732X_REG_MICBIAS2, | ||
803 | DA732X_MICBIAS_EN_SHIFT, | ||
804 | DA732X_NO_INVERT, NULL, 0), | ||
805 | |||
806 | /* Inputs */ | ||
807 | SND_SOC_DAPM_INPUT("MIC1"), | ||
808 | SND_SOC_DAPM_INPUT("MIC2"), | ||
809 | SND_SOC_DAPM_INPUT("MIC3"), | ||
810 | SND_SOC_DAPM_INPUT("AUX1L"), | ||
811 | SND_SOC_DAPM_INPUT("AUX1R"), | ||
812 | |||
813 | /* Outputs */ | ||
814 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
815 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
816 | SND_SOC_DAPM_OUTPUT("LOUTL"), | ||
817 | SND_SOC_DAPM_OUTPUT("LOUTR"), | ||
818 | SND_SOC_DAPM_OUTPUT("ClassD"), | ||
819 | |||
820 | /* ADCs */ | ||
821 | SND_SOC_DAPM_ADC("ADC1L", NULL, DA732X_REG_ADC1_SEL, | ||
822 | DA732X_ADCL_EN_SHIFT, DA732X_NO_INVERT), | ||
823 | SND_SOC_DAPM_ADC("ADC1R", NULL, DA732X_REG_ADC1_SEL, | ||
824 | DA732X_ADCR_EN_SHIFT, DA732X_NO_INVERT), | ||
825 | SND_SOC_DAPM_ADC("ADC2L", NULL, DA732X_REG_ADC2_SEL, | ||
826 | DA732X_ADCL_EN_SHIFT, DA732X_NO_INVERT), | ||
827 | SND_SOC_DAPM_ADC("ADC2R", NULL, DA732X_REG_ADC2_SEL, | ||
828 | DA732X_ADCR_EN_SHIFT, DA732X_NO_INVERT), | ||
829 | |||
830 | /* DACs */ | ||
831 | SND_SOC_DAPM_DAC("DAC1L", NULL, DA732X_REG_DAC1_SEL, | ||
832 | DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT), | ||
833 | SND_SOC_DAPM_DAC("DAC1R", NULL, DA732X_REG_DAC1_SEL, | ||
834 | DA732X_DACR_EN_SHIFT, DA732X_NO_INVERT), | ||
835 | SND_SOC_DAPM_DAC("DAC2L", NULL, DA732X_REG_DAC2_SEL, | ||
836 | DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT), | ||
837 | SND_SOC_DAPM_DAC("DAC2R", NULL, DA732X_REG_DAC2_SEL, | ||
838 | DA732X_DACR_EN_SHIFT, DA732X_NO_INVERT), | ||
839 | SND_SOC_DAPM_DAC("DAC3", NULL, DA732X_REG_DAC3_SEL, | ||
840 | DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT), | ||
841 | |||
842 | /* Input Pgas */ | ||
843 | SND_SOC_DAPM_PGA("MIC1 PGA", DA732X_REG_MIC1, DA732X_MIC_EN_SHIFT, | ||
844 | 0, NULL, 0), | ||
845 | SND_SOC_DAPM_PGA("MIC2 PGA", DA732X_REG_MIC2, DA732X_MIC_EN_SHIFT, | ||
846 | 0, NULL, 0), | ||
847 | SND_SOC_DAPM_PGA("MIC3 PGA", DA732X_REG_MIC3, DA732X_MIC_EN_SHIFT, | ||
848 | 0, NULL, 0), | ||
849 | SND_SOC_DAPM_PGA("AUX1L PGA", DA732X_REG_AUX1L, DA732X_AUX_EN_SHIFT, | ||
850 | 0, NULL, 0), | ||
851 | SND_SOC_DAPM_PGA("AUX1R PGA", DA732X_REG_AUX1R, DA732X_AUX_EN_SHIFT, | ||
852 | 0, NULL, 0), | ||
853 | |||
854 | SND_SOC_DAPM_PGA_E("HP Left", DA732X_REG_HPL, DA732X_HP_OUT_EN_SHIFT, | ||
855 | 0, NULL, 0, da732x_out_pga_event, | ||
856 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
857 | SND_SOC_DAPM_PGA_E("HP Right", DA732X_REG_HPR, DA732X_HP_OUT_EN_SHIFT, | ||
858 | 0, NULL, 0, da732x_out_pga_event, | ||
859 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
860 | SND_SOC_DAPM_PGA_E("LIN2", DA732X_REG_LIN2, DA732X_LIN_OUT_EN_SHIFT, | ||
861 | 0, NULL, 0, da732x_out_pga_event, | ||
862 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
863 | SND_SOC_DAPM_PGA_E("LIN3", DA732X_REG_LIN3, DA732X_LIN_OUT_EN_SHIFT, | ||
864 | 0, NULL, 0, da732x_out_pga_event, | ||
865 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
866 | SND_SOC_DAPM_PGA_E("LIN4", DA732X_REG_LIN4, DA732X_LIN_OUT_EN_SHIFT, | ||
867 | 0, NULL, 0, da732x_out_pga_event, | ||
868 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
869 | |||
870 | /* MUXs */ | ||
871 | SND_SOC_DAPM_MUX("ADC1 Left MUX", SND_SOC_NOPM, 0, 0, &adc1l_mux), | ||
872 | SND_SOC_DAPM_MUX("ADC1 Right MUX", SND_SOC_NOPM, 0, 0, &adc1r_mux), | ||
873 | SND_SOC_DAPM_MUX("ADC2 Left MUX", SND_SOC_NOPM, 0, 0, &adc2l_mux), | ||
874 | SND_SOC_DAPM_MUX("ADC2 Right MUX", SND_SOC_NOPM, 0, 0, &adc2r_mux), | ||
875 | |||
876 | SND_SOC_DAPM_MUX("HP Left MUX", SND_SOC_NOPM, 0, 0, &hpl_mux), | ||
877 | SND_SOC_DAPM_MUX("HP Right MUX", SND_SOC_NOPM, 0, 0, &hpr_mux), | ||
878 | SND_SOC_DAPM_MUX("Speaker MUX", SND_SOC_NOPM, 0, 0, &spk_mux), | ||
879 | SND_SOC_DAPM_MUX("LOUT2 MUX", SND_SOC_NOPM, 0, 0, &lout2_mux), | ||
880 | SND_SOC_DAPM_MUX("LOUT4 MUX", SND_SOC_NOPM, 0, 0, &lout4_mux), | ||
881 | |||
882 | /* AIF interfaces */ | ||
883 | SND_SOC_DAPM_AIF_OUT("AIFA Output", "AIFA Capture", 0, DA732X_REG_AIFA3, | ||
884 | DA732X_AIF_EN_SHIFT, 0), | ||
885 | SND_SOC_DAPM_AIF_IN("AIFA Input", "AIFA Playback", 0, DA732X_REG_AIFA3, | ||
886 | DA732X_AIF_EN_SHIFT, 0), | ||
887 | |||
888 | SND_SOC_DAPM_AIF_OUT("AIFB Output", "AIFB Capture", 0, DA732X_REG_AIFB3, | ||
889 | DA732X_AIF_EN_SHIFT, 0), | ||
890 | SND_SOC_DAPM_AIF_IN("AIFB Input", "AIFB Playback", 0, DA732X_REG_AIFB3, | ||
891 | DA732X_AIF_EN_SHIFT, 0), | ||
892 | }; | ||
893 | |||
894 | static const struct snd_soc_dapm_route da732x_dapm_routes[] = { | ||
895 | /* Inputs */ | ||
896 | {"AUX1L PGA", "NULL", "AUX1L"}, | ||
897 | {"AUX1R PGA", "NULL", "AUX1R"}, | ||
898 | {"MIC1 PGA", NULL, "MIC1"}, | ||
899 | {"MIC2 PGA", "NULL", "MIC2"}, | ||
900 | {"MIC3 PGA", "NULL", "MIC3"}, | ||
901 | |||
902 | /* Capture Path */ | ||
903 | {"ADC1 Left MUX", "MIC1", "MIC1 PGA"}, | ||
904 | {"ADC1 Left MUX", "AUX1L", "AUX1L PGA"}, | ||
905 | |||
906 | {"ADC1 Right MUX", "AUX1R", "AUX1R PGA"}, | ||
907 | {"ADC1 Right MUX", "MIC2", "MIC2 PGA"}, | ||
908 | {"ADC1 Right MUX", "MIC3", "MIC3 PGA"}, | ||
909 | |||
910 | {"ADC2 Left MUX", "AUX1L", "AUX1L PGA"}, | ||
911 | {"ADC2 Left MUX", "MIC1", "MIC1 PGA"}, | ||
912 | |||
913 | {"ADC2 Right MUX", "AUX1R", "AUX1R PGA"}, | ||
914 | {"ADC2 Right MUX", "MIC2", "MIC2 PGA"}, | ||
915 | {"ADC2 Right MUX", "MIC3", "MIC3 PGA"}, | ||
916 | |||
917 | {"ADC1L", NULL, "ADC1 Supply"}, | ||
918 | {"ADC1R", NULL, "ADC1 Supply"}, | ||
919 | {"ADC2L", NULL, "ADC2 Supply"}, | ||
920 | {"ADC2R", NULL, "ADC2 Supply"}, | ||
921 | |||
922 | {"ADC1L", NULL, "ADC1 Left MUX"}, | ||
923 | {"ADC1R", NULL, "ADC1 Right MUX"}, | ||
924 | {"ADC2L", NULL, "ADC2 Left MUX"}, | ||
925 | {"ADC2R", NULL, "ADC2 Right MUX"}, | ||
926 | |||
927 | {"AIFA Output", NULL, "ADC1L"}, | ||
928 | {"AIFA Output", NULL, "ADC1R"}, | ||
929 | {"AIFB Output", NULL, "ADC2L"}, | ||
930 | {"AIFB Output", NULL, "ADC2R"}, | ||
931 | |||
932 | {"HP Left MUX", "Enabled", "AIFA Input"}, | ||
933 | {"HP Right MUX", "Enabled", "AIFA Input"}, | ||
934 | {"Speaker MUX", "Enabled", "AIFB Input"}, | ||
935 | {"LOUT2 MUX", "Enabled", "AIFB Input"}, | ||
936 | {"LOUT4 MUX", "Enabled", "AIFB Input"}, | ||
937 | |||
938 | {"DAC1L", NULL, "DAC1 CLK"}, | ||
939 | {"DAC1R", NULL, "DAC1 CLK"}, | ||
940 | {"DAC2L", NULL, "DAC2 CLK"}, | ||
941 | {"DAC2R", NULL, "DAC2 CLK"}, | ||
942 | {"DAC3", NULL, "DAC3 CLK"}, | ||
943 | |||
944 | {"DAC1L", NULL, "HP Left MUX"}, | ||
945 | {"DAC1R", NULL, "HP Right MUX"}, | ||
946 | {"DAC2L", NULL, "Speaker MUX"}, | ||
947 | {"DAC2R", NULL, "LOUT4 MUX"}, | ||
948 | {"DAC3", NULL, "LOUT2 MUX"}, | ||
949 | |||
950 | /* Output Pgas */ | ||
951 | {"HP Left", NULL, "DAC1L"}, | ||
952 | {"HP Right", NULL, "DAC1R"}, | ||
953 | {"LIN3", NULL, "DAC2L"}, | ||
954 | {"LIN4", NULL, "DAC2R"}, | ||
955 | {"LIN2", NULL, "DAC3"}, | ||
956 | |||
957 | /* Outputs */ | ||
958 | {"ClassD", NULL, "LIN3"}, | ||
959 | {"LOUTL", NULL, "LIN2"}, | ||
960 | {"LOUTR", NULL, "LIN4"}, | ||
961 | {"HPL", NULL, "HP Left"}, | ||
962 | {"HPR", NULL, "HP Right"}, | ||
963 | }; | ||
964 | |||
965 | static int da732x_hw_params(struct snd_pcm_substream *substream, | ||
966 | struct snd_pcm_hw_params *params, | ||
967 | struct snd_soc_dai *dai) | ||
968 | { | ||
969 | struct snd_soc_codec *codec = dai->codec; | ||
970 | u32 aif = 0; | ||
971 | u32 reg_aif; | ||
972 | u32 fs; | ||
973 | |||
974 | reg_aif = dai->driver->base; | ||
975 | |||
976 | switch (params_format(params)) { | ||
977 | case SNDRV_PCM_FORMAT_S16_LE: | ||
978 | aif |= DA732X_AIF_WORD_16; | ||
979 | break; | ||
980 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
981 | aif |= DA732X_AIF_WORD_20; | ||
982 | break; | ||
983 | case SNDRV_PCM_FORMAT_S24_LE: | ||
984 | aif |= DA732X_AIF_WORD_24; | ||
985 | break; | ||
986 | case SNDRV_PCM_FORMAT_S32_LE: | ||
987 | aif |= DA732X_AIF_WORD_32; | ||
988 | break; | ||
989 | default: | ||
990 | return -EINVAL; | ||
991 | } | ||
992 | |||
993 | switch (params_rate(params)) { | ||
994 | case 8000: | ||
995 | fs = DA732X_SR_8KHZ; | ||
996 | break; | ||
997 | case 11025: | ||
998 | fs = DA732X_SR_11_025KHZ; | ||
999 | break; | ||
1000 | case 12000: | ||
1001 | fs = DA732X_SR_12KHZ; | ||
1002 | break; | ||
1003 | case 16000: | ||
1004 | fs = DA732X_SR_16KHZ; | ||
1005 | break; | ||
1006 | case 22050: | ||
1007 | fs = DA732X_SR_22_05KHZ; | ||
1008 | break; | ||
1009 | case 24000: | ||
1010 | fs = DA732X_SR_24KHZ; | ||
1011 | break; | ||
1012 | case 32000: | ||
1013 | fs = DA732X_SR_32KHZ; | ||
1014 | break; | ||
1015 | case 44100: | ||
1016 | fs = DA732X_SR_44_1KHZ; | ||
1017 | break; | ||
1018 | case 48000: | ||
1019 | fs = DA732X_SR_48KHZ; | ||
1020 | break; | ||
1021 | case 88100: | ||
1022 | fs = DA732X_SR_88_1KHZ; | ||
1023 | break; | ||
1024 | case 96000: | ||
1025 | fs = DA732X_SR_96KHZ; | ||
1026 | break; | ||
1027 | default: | ||
1028 | return -EINVAL; | ||
1029 | } | ||
1030 | |||
1031 | snd_soc_update_bits(codec, reg_aif, DA732X_AIF_WORD_MASK, aif); | ||
1032 | snd_soc_update_bits(codec, DA732X_REG_CLK_CTRL, DA732X_SR1_MASK, fs); | ||
1033 | |||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | static int da732x_set_dai_fmt(struct snd_soc_dai *dai, u32 fmt) | ||
1038 | { | ||
1039 | struct snd_soc_codec *codec = dai->codec; | ||
1040 | u32 aif_mclk, pc_count; | ||
1041 | u32 reg_aif1, aif1; | ||
1042 | u32 reg_aif3, aif3; | ||
1043 | |||
1044 | switch (dai->id) { | ||
1045 | case DA732X_DAI_ID1: | ||
1046 | reg_aif1 = DA732X_REG_AIFA1; | ||
1047 | reg_aif3 = DA732X_REG_AIFA3; | ||
1048 | pc_count = DA732X_PC_PULSE_AIFA | DA732X_PC_RESYNC_NOT_AUT | | ||
1049 | DA732X_PC_SAME; | ||
1050 | break; | ||
1051 | case DA732X_DAI_ID2: | ||
1052 | reg_aif1 = DA732X_REG_AIFB1; | ||
1053 | reg_aif3 = DA732X_REG_AIFB3; | ||
1054 | pc_count = DA732X_PC_PULSE_AIFB | DA732X_PC_RESYNC_NOT_AUT | | ||
1055 | DA732X_PC_SAME; | ||
1056 | break; | ||
1057 | default: | ||
1058 | return -EINVAL; | ||
1059 | } | ||
1060 | |||
1061 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1062 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1063 | aif1 = DA732X_AIF_SLAVE; | ||
1064 | aif_mclk = DA732X_AIFM_FRAME_64 | DA732X_AIFM_SRC_SEL_AIFA; | ||
1065 | break; | ||
1066 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1067 | aif1 = DA732X_AIF_CLK_FROM_SRC; | ||
1068 | aif_mclk = DA732X_CLK_GENERATION_AIF_A; | ||
1069 | break; | ||
1070 | default: | ||
1071 | return -EINVAL; | ||
1072 | } | ||
1073 | |||
1074 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1075 | case SND_SOC_DAIFMT_I2S: | ||
1076 | aif3 = DA732X_AIF_I2S_MODE; | ||
1077 | break; | ||
1078 | case SND_SOC_DAIFMT_RIGHT_J: | ||
1079 | aif3 = DA732X_AIF_RIGHT_J_MODE; | ||
1080 | break; | ||
1081 | case SND_SOC_DAIFMT_LEFT_J: | ||
1082 | aif3 = DA732X_AIF_LEFT_J_MODE; | ||
1083 | break; | ||
1084 | case SND_SOC_DAIFMT_DSP_B: | ||
1085 | aif3 = DA732X_AIF_DSP_MODE; | ||
1086 | break; | ||
1087 | default: | ||
1088 | return -EINVAL; | ||
1089 | } | ||
1090 | |||
1091 | /* Clock inversion */ | ||
1092 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1093 | case SND_SOC_DAIFMT_DSP_B: | ||
1094 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1095 | case SND_SOC_DAIFMT_NB_NF: | ||
1096 | break; | ||
1097 | case SND_SOC_DAIFMT_IB_NF: | ||
1098 | aif3 |= DA732X_AIF_BCLK_INV; | ||
1099 | break; | ||
1100 | default: | ||
1101 | return -EINVAL; | ||
1102 | } | ||
1103 | break; | ||
1104 | case SND_SOC_DAIFMT_I2S: | ||
1105 | case SND_SOC_DAIFMT_RIGHT_J: | ||
1106 | case SND_SOC_DAIFMT_LEFT_J: | ||
1107 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1108 | case SND_SOC_DAIFMT_NB_NF: | ||
1109 | break; | ||
1110 | case SND_SOC_DAIFMT_IB_IF: | ||
1111 | aif3 |= DA732X_AIF_BCLK_INV | DA732X_AIF_WCLK_INV; | ||
1112 | break; | ||
1113 | case SND_SOC_DAIFMT_IB_NF: | ||
1114 | aif3 |= DA732X_AIF_BCLK_INV; | ||
1115 | break; | ||
1116 | case SND_SOC_DAIFMT_NB_IF: | ||
1117 | aif3 |= DA732X_AIF_WCLK_INV; | ||
1118 | break; | ||
1119 | default: | ||
1120 | return -EINVAL; | ||
1121 | } | ||
1122 | break; | ||
1123 | default: | ||
1124 | return -EINVAL; | ||
1125 | } | ||
1126 | |||
1127 | snd_soc_write(codec, DA732X_REG_AIF_MCLK, aif_mclk); | ||
1128 | snd_soc_update_bits(codec, reg_aif1, DA732X_AIF1_CLK_MASK, aif1); | ||
1129 | snd_soc_update_bits(codec, reg_aif3, DA732X_AIF_BCLK_INV | | ||
1130 | DA732X_AIF_WCLK_INV | DA732X_AIF_MODE_MASK, aif3); | ||
1131 | snd_soc_write(codec, DA732X_REG_PC_CTRL, pc_count); | ||
1132 | |||
1133 | return 0; | ||
1134 | } | ||
1135 | |||
1136 | |||
1137 | |||
1138 | static int da732x_set_dai_pll(struct snd_soc_codec *codec, int pll_id, | ||
1139 | int source, unsigned int freq_in, | ||
1140 | unsigned int freq_out) | ||
1141 | { | ||
1142 | struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); | ||
1143 | int fref, indiv; | ||
1144 | u8 div_lo, div_mid, div_hi; | ||
1145 | u64 frac_div; | ||
1146 | |||
1147 | /* Disable PLL */ | ||
1148 | if (freq_out == 0) { | ||
1149 | snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL, | ||
1150 | DA732X_PLL_EN, 0); | ||
1151 | da732x->pll_en = false; | ||
1152 | return 0; | ||
1153 | } | ||
1154 | |||
1155 | if (da732x->pll_en) | ||
1156 | return -EBUSY; | ||
1157 | |||
1158 | if (source == DA732X_SRCCLK_MCLK) { | ||
1159 | /* Validate Sysclk rate */ | ||
1160 | switch (da732x->sysclk) { | ||
1161 | case 11290000: | ||
1162 | case 12288000: | ||
1163 | case 22580000: | ||
1164 | case 24576000: | ||
1165 | case 45160000: | ||
1166 | case 49152000: | ||
1167 | snd_soc_write(codec, DA732X_REG_PLL_CTRL, | ||
1168 | DA732X_PLL_BYPASS); | ||
1169 | return 0; | ||
1170 | default: | ||
1171 | dev_err(codec->dev, | ||
1172 | "Cannot use PLL Bypass, invalid SYSCLK rate\n"); | ||
1173 | return -EINVAL; | ||
1174 | } | ||
1175 | } | ||
1176 | |||
1177 | indiv = da732x_get_input_div(codec, da732x->sysclk); | ||
1178 | if (indiv < 0) | ||
1179 | return indiv; | ||
1180 | |||
1181 | fref = (da732x->sysclk / indiv); | ||
1182 | div_hi = freq_out / fref; | ||
1183 | frac_div = (u64)(freq_out % fref) * 8192ULL; | ||
1184 | do_div(frac_div, fref); | ||
1185 | div_mid = (frac_div >> DA732X_1BYTE_SHIFT) & DA732X_U8_MASK; | ||
1186 | div_lo = (frac_div) & DA732X_U8_MASK; | ||
1187 | |||
1188 | snd_soc_write(codec, DA732X_REG_PLL_DIV_LO, div_lo); | ||
1189 | snd_soc_write(codec, DA732X_REG_PLL_DIV_MID, div_mid); | ||
1190 | snd_soc_write(codec, DA732X_REG_PLL_DIV_HI, div_hi); | ||
1191 | |||
1192 | snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL, DA732X_PLL_EN, | ||
1193 | DA732X_PLL_EN); | ||
1194 | |||
1195 | da732x->pll_en = true; | ||
1196 | |||
1197 | return 0; | ||
1198 | } | ||
1199 | |||
1200 | static int da732x_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
1201 | unsigned int freq, int dir) | ||
1202 | { | ||
1203 | struct snd_soc_codec *codec = dai->codec; | ||
1204 | struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); | ||
1205 | |||
1206 | da732x->sysclk = freq; | ||
1207 | |||
1208 | return 0; | ||
1209 | } | ||
1210 | |||
1211 | #define DA732X_RATES SNDRV_PCM_RATE_8000_96000 | ||
1212 | |||
1213 | #define DA732X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
1214 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
1215 | |||
1216 | static struct snd_soc_dai_ops da732x_dai1_ops = { | ||
1217 | .hw_params = da732x_hw_params, | ||
1218 | .set_fmt = da732x_set_dai_fmt, | ||
1219 | .set_sysclk = da732x_set_dai_sysclk, | ||
1220 | }; | ||
1221 | |||
1222 | static struct snd_soc_dai_ops da732x_dai2_ops = { | ||
1223 | .hw_params = da732x_hw_params, | ||
1224 | .set_fmt = da732x_set_dai_fmt, | ||
1225 | .set_sysclk = da732x_set_dai_sysclk, | ||
1226 | }; | ||
1227 | |||
1228 | static struct snd_soc_dai_driver da732x_dai[] = { | ||
1229 | { | ||
1230 | .name = "DA732X_AIFA", | ||
1231 | .id = DA732X_DAI_ID1, | ||
1232 | .base = DA732X_REG_AIFA1, | ||
1233 | .playback = { | ||
1234 | .stream_name = "AIFA Playback", | ||
1235 | .channels_min = 1, | ||
1236 | .channels_max = 2, | ||
1237 | .rates = DA732X_RATES, | ||
1238 | .formats = DA732X_FORMATS, | ||
1239 | }, | ||
1240 | .capture = { | ||
1241 | .stream_name = "AIFA Capture", | ||
1242 | .channels_min = 1, | ||
1243 | .channels_max = 2, | ||
1244 | .rates = DA732X_RATES, | ||
1245 | .formats = DA732X_FORMATS, | ||
1246 | }, | ||
1247 | .ops = &da732x_dai1_ops, | ||
1248 | }, | ||
1249 | { | ||
1250 | .name = "DA732X_AIFB", | ||
1251 | .id = DA732X_DAI_ID2, | ||
1252 | .base = DA732X_REG_AIFB1, | ||
1253 | .playback = { | ||
1254 | .stream_name = "AIFB Playback", | ||
1255 | .channels_min = 1, | ||
1256 | .channels_max = 2, | ||
1257 | .rates = DA732X_RATES, | ||
1258 | .formats = DA732X_FORMATS, | ||
1259 | }, | ||
1260 | .capture = { | ||
1261 | .stream_name = "AIFB Capture", | ||
1262 | .channels_min = 1, | ||
1263 | .channels_max = 2, | ||
1264 | .rates = DA732X_RATES, | ||
1265 | .formats = DA732X_FORMATS, | ||
1266 | }, | ||
1267 | .ops = &da732x_dai2_ops, | ||
1268 | }, | ||
1269 | }; | ||
1270 | |||
1271 | static const struct regmap_config da732x_regmap = { | ||
1272 | .reg_bits = 8, | ||
1273 | .val_bits = 8, | ||
1274 | |||
1275 | .max_register = DA732X_MAX_REG, | ||
1276 | .reg_defaults = da732x_reg_cache, | ||
1277 | .num_reg_defaults = ARRAY_SIZE(da732x_reg_cache), | ||
1278 | .cache_type = REGCACHE_RBTREE, | ||
1279 | }; | ||
1280 | |||
1281 | |||
1282 | static void da732x_dac_offset_adjust(struct snd_soc_codec *codec) | ||
1283 | { | ||
1284 | u8 offset[DA732X_HP_DACS]; | ||
1285 | u8 sign[DA732X_HP_DACS]; | ||
1286 | u8 step = DA732X_DAC_OFFSET_STEP; | ||
1287 | |||
1288 | /* Initialize DAC offset calibration circuits and registers */ | ||
1289 | snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET, | ||
1290 | DA732X_HP_DAC_OFFSET_TRIM_VAL); | ||
1291 | snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET, | ||
1292 | DA732X_HP_DAC_OFFSET_TRIM_VAL); | ||
1293 | snd_soc_write(codec, DA732X_REG_HPL_DAC_OFF_CNTL, | ||
1294 | DA732X_HP_DAC_OFF_CALIBRATION | | ||
1295 | DA732X_HP_DAC_OFF_SCALE_STEPS); | ||
1296 | snd_soc_write(codec, DA732X_REG_HPR_DAC_OFF_CNTL, | ||
1297 | DA732X_HP_DAC_OFF_CALIBRATION | | ||
1298 | DA732X_HP_DAC_OFF_SCALE_STEPS); | ||
1299 | |||
1300 | /* Wait for voltage stabilization */ | ||
1301 | msleep(DA732X_WAIT_FOR_STABILIZATION); | ||
1302 | |||
1303 | /* Check DAC offset sign */ | ||
1304 | sign[DA732X_HPL_DAC] = (codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & | ||
1305 | DA732X_HP_DAC_OFF_CNTL_COMPO); | ||
1306 | sign[DA732X_HPR_DAC] = (codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & | ||
1307 | DA732X_HP_DAC_OFF_CNTL_COMPO); | ||
1308 | |||
1309 | /* Binary search DAC offset values (both channels at once) */ | ||
1310 | offset[DA732X_HPL_DAC] = sign[DA732X_HPL_DAC] << DA732X_HP_DAC_COMPO_SHIFT; | ||
1311 | offset[DA732X_HPR_DAC] = sign[DA732X_HPR_DAC] << DA732X_HP_DAC_COMPO_SHIFT; | ||
1312 | |||
1313 | do { | ||
1314 | offset[DA732X_HPL_DAC] |= step; | ||
1315 | offset[DA732X_HPR_DAC] |= step; | ||
1316 | snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET, | ||
1317 | ~offset[DA732X_HPL_DAC] & DA732X_HP_DAC_OFF_MASK); | ||
1318 | snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET, | ||
1319 | ~offset[DA732X_HPR_DAC] & DA732X_HP_DAC_OFF_MASK); | ||
1320 | |||
1321 | msleep(DA732X_WAIT_FOR_STABILIZATION); | ||
1322 | |||
1323 | if ((codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & | ||
1324 | DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC]) | ||
1325 | offset[DA732X_HPL_DAC] &= ~step; | ||
1326 | if ((codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & | ||
1327 | DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC]) | ||
1328 | offset[DA732X_HPR_DAC] &= ~step; | ||
1329 | |||
1330 | step >>= 1; | ||
1331 | } while (step); | ||
1332 | |||
1333 | /* Write final DAC offsets to registers */ | ||
1334 | snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET, | ||
1335 | ~offset[DA732X_HPL_DAC] & DA732X_HP_DAC_OFF_MASK); | ||
1336 | snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET, | ||
1337 | ~offset[DA732X_HPR_DAC] & DA732X_HP_DAC_OFF_MASK); | ||
1338 | |||
1339 | /* End DAC calibration mode */ | ||
1340 | snd_soc_write(codec, DA732X_REG_HPL_DAC_OFF_CNTL, | ||
1341 | DA732X_HP_DAC_OFF_SCALE_STEPS); | ||
1342 | snd_soc_write(codec, DA732X_REG_HPR_DAC_OFF_CNTL, | ||
1343 | DA732X_HP_DAC_OFF_SCALE_STEPS); | ||
1344 | } | ||
1345 | |||
1346 | static void da732x_output_offset_adjust(struct snd_soc_codec *codec) | ||
1347 | { | ||
1348 | u8 offset[DA732X_HP_AMPS]; | ||
1349 | u8 sign[DA732X_HP_AMPS]; | ||
1350 | u8 step = DA732X_OUTPUT_OFFSET_STEP; | ||
1351 | |||
1352 | offset[DA732X_HPL_AMP] = DA732X_HP_OUT_TRIM_VAL; | ||
1353 | offset[DA732X_HPR_AMP] = DA732X_HP_OUT_TRIM_VAL; | ||
1354 | |||
1355 | /* Initialize output offset calibration circuits and registers */ | ||
1356 | snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, DA732X_HP_OUT_TRIM_VAL); | ||
1357 | snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, DA732X_HP_OUT_TRIM_VAL); | ||
1358 | snd_soc_write(codec, DA732X_REG_HPL, | ||
1359 | DA732X_HP_OUT_COMP | DA732X_HP_OUT_EN); | ||
1360 | snd_soc_write(codec, DA732X_REG_HPR, | ||
1361 | DA732X_HP_OUT_COMP | DA732X_HP_OUT_EN); | ||
1362 | |||
1363 | /* Wait for voltage stabilization */ | ||
1364 | msleep(DA732X_WAIT_FOR_STABILIZATION); | ||
1365 | |||
1366 | /* Check output offset sign */ | ||
1367 | sign[DA732X_HPL_AMP] = codec->hw_read(codec, DA732X_REG_HPL) & | ||
1368 | DA732X_HP_OUT_COMPO; | ||
1369 | sign[DA732X_HPR_AMP] = codec->hw_read(codec, DA732X_REG_HPR) & | ||
1370 | DA732X_HP_OUT_COMPO; | ||
1371 | |||
1372 | snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_COMP | | ||
1373 | (sign[DA732X_HPL_AMP] >> DA732X_HP_OUT_COMPO_SHIFT) | | ||
1374 | DA732X_HP_OUT_EN); | ||
1375 | snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_OUT_COMP | | ||
1376 | (sign[DA732X_HPR_AMP] >> DA732X_HP_OUT_COMPO_SHIFT) | | ||
1377 | DA732X_HP_OUT_EN); | ||
1378 | |||
1379 | /* Binary search output offset values (both channels at once) */ | ||
1380 | do { | ||
1381 | offset[DA732X_HPL_AMP] |= step; | ||
1382 | offset[DA732X_HPR_AMP] |= step; | ||
1383 | snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, | ||
1384 | offset[DA732X_HPL_AMP]); | ||
1385 | snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, | ||
1386 | offset[DA732X_HPR_AMP]); | ||
1387 | |||
1388 | msleep(DA732X_WAIT_FOR_STABILIZATION); | ||
1389 | |||
1390 | if ((codec->hw_read(codec, DA732X_REG_HPL) & | ||
1391 | DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP]) | ||
1392 | offset[DA732X_HPL_AMP] &= ~step; | ||
1393 | if ((codec->hw_read(codec, DA732X_REG_HPR) & | ||
1394 | DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP]) | ||
1395 | offset[DA732X_HPR_AMP] &= ~step; | ||
1396 | |||
1397 | step >>= 1; | ||
1398 | } while (step); | ||
1399 | |||
1400 | /* Write final DAC offsets to registers */ | ||
1401 | snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, offset[DA732X_HPL_AMP]); | ||
1402 | snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, offset[DA732X_HPR_AMP]); | ||
1403 | } | ||
1404 | |||
1405 | static void da732x_hp_dc_offset_cancellation(struct snd_soc_codec *codec) | ||
1406 | { | ||
1407 | /* Make sure that we have Soft Mute enabled */ | ||
1408 | snd_soc_write(codec, DA732X_REG_DAC1_SOFTMUTE, DA732X_SOFTMUTE_EN | | ||
1409 | DA732X_GAIN_RAMPED | DA732X_16_SAMPLES); | ||
1410 | snd_soc_write(codec, DA732X_REG_DAC1_SEL, DA732X_DACL_EN | | ||
1411 | DA732X_DACR_EN | DA732X_DACL_SDM | DA732X_DACR_SDM | | ||
1412 | DA732X_DACL_MUTE | DA732X_DACR_MUTE); | ||
1413 | snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN | | ||
1414 | DA732X_HP_OUT_MUTE | DA732X_HP_OUT_EN); | ||
1415 | snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_OUT_EN | | ||
1416 | DA732X_HP_OUT_MUTE | DA732X_HP_OUT_DAC_EN); | ||
1417 | |||
1418 | da732x_dac_offset_adjust(codec); | ||
1419 | da732x_output_offset_adjust(codec); | ||
1420 | |||
1421 | snd_soc_write(codec, DA732X_REG_DAC1_SEL, DA732X_DACS_DIS); | ||
1422 | snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_DIS); | ||
1423 | snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_DIS); | ||
1424 | } | ||
1425 | |||
1426 | static int da732x_set_bias_level(struct snd_soc_codec *codec, | ||
1427 | enum snd_soc_bias_level level) | ||
1428 | { | ||
1429 | struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); | ||
1430 | |||
1431 | switch (level) { | ||
1432 | case SND_SOC_BIAS_ON: | ||
1433 | snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, | ||
1434 | DA732X_BIAS_BOOST_MASK, | ||
1435 | DA732X_BIAS_BOOST_100PC); | ||
1436 | break; | ||
1437 | case SND_SOC_BIAS_PREPARE: | ||
1438 | break; | ||
1439 | case SND_SOC_BIAS_STANDBY: | ||
1440 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
1441 | /* Init Codec */ | ||
1442 | snd_soc_write(codec, DA732X_REG_REF1, | ||
1443 | DA732X_VMID_FASTCHG); | ||
1444 | snd_soc_write(codec, DA732X_REG_BIAS_EN, | ||
1445 | DA732X_BIAS_EN); | ||
1446 | |||
1447 | mdelay(DA732X_STARTUP_DELAY); | ||
1448 | |||
1449 | /* Disable Fast Charge and enable DAC ref voltage */ | ||
1450 | snd_soc_write(codec, DA732X_REG_REF1, | ||
1451 | DA732X_REFBUFX2_EN); | ||
1452 | |||
1453 | /* Enable bypass DSP routing */ | ||
1454 | snd_soc_write(codec, DA732X_REG_DATA_ROUTE, | ||
1455 | DA732X_BYPASS_DSP); | ||
1456 | |||
1457 | /* Enable Digital subsystem */ | ||
1458 | snd_soc_write(codec, DA732X_REG_DSP_CTRL, | ||
1459 | DA732X_DIGITAL_EN); | ||
1460 | |||
1461 | snd_soc_write(codec, DA732X_REG_SPARE1_OUT, | ||
1462 | DA732X_HP_DRIVER_EN | | ||
1463 | DA732X_HP_GATE_LOW | | ||
1464 | DA732X_HP_LOOP_GAIN_CTRL); | ||
1465 | snd_soc_write(codec, DA732X_REG_HP_LIN1_GNDSEL, | ||
1466 | DA732X_HP_OUT_GNDSEL); | ||
1467 | |||
1468 | da732x_set_charge_pump(codec, DA732X_ENABLE_CP); | ||
1469 | |||
1470 | snd_soc_write(codec, DA732X_REG_CLK_EN1, | ||
1471 | DA732X_SYS3_CLK_EN | DA732X_PC_CLK_EN); | ||
1472 | |||
1473 | /* Enable Zero Crossing */ | ||
1474 | snd_soc_write(codec, DA732X_REG_INP_ZC_EN, | ||
1475 | DA732X_MIC1_PRE_ZC_EN | | ||
1476 | DA732X_MIC1_ZC_EN | | ||
1477 | DA732X_MIC2_PRE_ZC_EN | | ||
1478 | DA732X_MIC2_ZC_EN | | ||
1479 | DA732X_AUXL_ZC_EN | | ||
1480 | DA732X_AUXR_ZC_EN | | ||
1481 | DA732X_MIC3_PRE_ZC_EN | | ||
1482 | DA732X_MIC3_ZC_EN); | ||
1483 | snd_soc_write(codec, DA732X_REG_OUT_ZC_EN, | ||
1484 | DA732X_HPL_ZC_EN | DA732X_HPR_ZC_EN | | ||
1485 | DA732X_LIN2_ZC_EN | DA732X_LIN3_ZC_EN | | ||
1486 | DA732X_LIN4_ZC_EN); | ||
1487 | |||
1488 | da732x_hp_dc_offset_cancellation(codec); | ||
1489 | |||
1490 | regcache_cache_only(codec->control_data, false); | ||
1491 | regcache_sync(codec->control_data); | ||
1492 | } else { | ||
1493 | snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, | ||
1494 | DA732X_BIAS_BOOST_MASK, | ||
1495 | DA732X_BIAS_BOOST_50PC); | ||
1496 | snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL, | ||
1497 | DA732X_PLL_EN, 0); | ||
1498 | da732x->pll_en = false; | ||
1499 | } | ||
1500 | break; | ||
1501 | case SND_SOC_BIAS_OFF: | ||
1502 | regcache_cache_only(codec->control_data, true); | ||
1503 | da732x_set_charge_pump(codec, DA732X_DISABLE_CP); | ||
1504 | snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN, | ||
1505 | DA732X_BIAS_DIS); | ||
1506 | da732x->pll_en = false; | ||
1507 | break; | ||
1508 | } | ||
1509 | |||
1510 | codec->dapm.bias_level = level; | ||
1511 | |||
1512 | return 0; | ||
1513 | } | ||
1514 | |||
1515 | static int da732x_probe(struct snd_soc_codec *codec) | ||
1516 | { | ||
1517 | struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); | ||
1518 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
1519 | int ret = 0; | ||
1520 | |||
1521 | da732x->codec = codec; | ||
1522 | |||
1523 | dapm->idle_bias_off = false; | ||
1524 | |||
1525 | codec->control_data = da732x->regmap; | ||
1526 | |||
1527 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
1528 | if (ret != 0) { | ||
1529 | dev_err(codec->dev, "Failed to register codec.\n"); | ||
1530 | goto err; | ||
1531 | } | ||
1532 | |||
1533 | da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1534 | err: | ||
1535 | return ret; | ||
1536 | } | ||
1537 | |||
1538 | static int da732x_remove(struct snd_soc_codec *codec) | ||
1539 | { | ||
1540 | |||
1541 | da732x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1542 | |||
1543 | return 0; | ||
1544 | } | ||
1545 | |||
1546 | static struct snd_soc_codec_driver soc_codec_dev_da732x = { | ||
1547 | .probe = da732x_probe, | ||
1548 | .remove = da732x_remove, | ||
1549 | .set_bias_level = da732x_set_bias_level, | ||
1550 | .controls = da732x_snd_controls, | ||
1551 | .num_controls = ARRAY_SIZE(da732x_snd_controls), | ||
1552 | .dapm_widgets = da732x_dapm_widgets, | ||
1553 | .num_dapm_widgets = ARRAY_SIZE(da732x_dapm_widgets), | ||
1554 | .dapm_routes = da732x_dapm_routes, | ||
1555 | .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes), | ||
1556 | .set_pll = da732x_set_dai_pll, | ||
1557 | .reg_cache_size = ARRAY_SIZE(da732x_reg_cache), | ||
1558 | }; | ||
1559 | |||
1560 | static __devinit int da732x_i2c_probe(struct i2c_client *i2c, | ||
1561 | const struct i2c_device_id *id) | ||
1562 | { | ||
1563 | struct da732x_priv *da732x; | ||
1564 | unsigned int reg; | ||
1565 | int ret; | ||
1566 | |||
1567 | da732x = devm_kzalloc(&i2c->dev, sizeof(struct da732x_priv), | ||
1568 | GFP_KERNEL); | ||
1569 | if (!da732x) | ||
1570 | return -ENOMEM; | ||
1571 | |||
1572 | i2c_set_clientdata(i2c, da732x); | ||
1573 | |||
1574 | da732x->regmap = devm_regmap_init_i2c(i2c, &da732x_regmap); | ||
1575 | if (IS_ERR(da732x->regmap)) { | ||
1576 | ret = PTR_ERR(da732x->regmap); | ||
1577 | dev_err(&i2c->dev, "Failed to initialize regmap\n"); | ||
1578 | goto err; | ||
1579 | } | ||
1580 | |||
1581 | ret = regmap_read(da732x->regmap, DA732X_REG_ID, ®); | ||
1582 | if (ret < 0) { | ||
1583 | dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret); | ||
1584 | goto err; | ||
1585 | } | ||
1586 | |||
1587 | dev_info(&i2c->dev, "Revision: %d.%d\n", | ||
1588 | (reg & DA732X_ID_MAJOR_MASK), (reg & DA732X_ID_MINOR_MASK)); | ||
1589 | |||
1590 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da732x, | ||
1591 | da732x_dai, ARRAY_SIZE(da732x_dai)); | ||
1592 | if (ret != 0) | ||
1593 | dev_err(&i2c->dev, "Failed to register codec.\n"); | ||
1594 | |||
1595 | err: | ||
1596 | return ret; | ||
1597 | } | ||
1598 | |||
1599 | static __devexit int da732x_i2c_remove(struct i2c_client *client) | ||
1600 | { | ||
1601 | snd_soc_unregister_codec(&client->dev); | ||
1602 | |||
1603 | return 0; | ||
1604 | } | ||
1605 | |||
1606 | static const struct i2c_device_id da732x_i2c_id[] = { | ||
1607 | { "da7320", 0}, | ||
1608 | { } | ||
1609 | }; | ||
1610 | MODULE_DEVICE_TABLE(i2c, da732x_i2c_id); | ||
1611 | |||
1612 | static struct i2c_driver da732x_i2c_driver = { | ||
1613 | .driver = { | ||
1614 | .name = "da7320", | ||
1615 | .owner = THIS_MODULE, | ||
1616 | }, | ||
1617 | .probe = da732x_i2c_probe, | ||
1618 | .remove = __devexit_p(da732x_i2c_remove), | ||
1619 | .id_table = da732x_i2c_id, | ||
1620 | }; | ||
1621 | |||
1622 | module_i2c_driver(da732x_i2c_driver); | ||
1623 | |||
1624 | |||
1625 | MODULE_DESCRIPTION("ASoC DA732X driver"); | ||
1626 | MODULE_AUTHOR("Michal Hajduk <michal.hajduk@diasemi.com>"); | ||
1627 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/da732x.h b/sound/soc/codecs/da732x.h new file mode 100644 index 000000000000..c8ce5475de22 --- /dev/null +++ b/sound/soc/codecs/da732x.h | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * da732x.h -- Dialog DA732X ALSA SoC Audio Driver Header File | ||
3 | * | ||
4 | * Copyright (C) 2012 Dialog Semiconductor GmbH | ||
5 | * | ||
6 | * Author: Michal Hajduk <Michal.Hajduk@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __DA732X_H_ | ||
14 | #define __DA732X_H | ||
15 | |||
16 | #include <sound/soc.h> | ||
17 | |||
18 | /* General */ | ||
19 | #define DA732X_U8_MASK 0xFF | ||
20 | #define DA732X_4BYTES 4 | ||
21 | #define DA732X_3BYTES 3 | ||
22 | #define DA732X_2BYTES 2 | ||
23 | #define DA732X_1BYTE 1 | ||
24 | #define DA732X_1BYTE_SHIFT 8 | ||
25 | #define DA732X_2BYTES_SHIFT 16 | ||
26 | #define DA732X_3BYTES_SHIFT 24 | ||
27 | #define DA732X_4BYTES_SHIFT 32 | ||
28 | |||
29 | #define DA732X_DACS_DIS 0x0 | ||
30 | #define DA732X_HP_DIS 0x0 | ||
31 | #define DA732X_CLEAR_REG 0x0 | ||
32 | |||
33 | /* Calibration */ | ||
34 | #define DA732X_DAC_OFFSET_STEP 0x20 | ||
35 | #define DA732X_OUTPUT_OFFSET_STEP 0x80 | ||
36 | #define DA732X_HP_OUT_TRIM_VAL 0x0 | ||
37 | #define DA732X_WAIT_FOR_STABILIZATION 1 | ||
38 | #define DA732X_HPL_DAC 0 | ||
39 | #define DA732X_HPR_DAC 1 | ||
40 | #define DA732X_HP_DACS 2 | ||
41 | #define DA732X_HPL_AMP 0 | ||
42 | #define DA732X_HPR_AMP 1 | ||
43 | #define DA732X_HP_AMPS 2 | ||
44 | |||
45 | /* Clock settings */ | ||
46 | #define DA732X_STARTUP_DELAY 100 | ||
47 | #define DA732X_PLL_OUT_196608 196608000 | ||
48 | #define DA732X_PLL_OUT_180634 180633600 | ||
49 | #define DA732X_PLL_OUT_SRM 188620800 | ||
50 | #define DA732X_MCLK_10MHZ 10000000 | ||
51 | #define DA732X_MCLK_20MHZ 20000000 | ||
52 | #define DA732X_MCLK_40MHZ 40000000 | ||
53 | #define DA732X_MCLK_54MHZ 54000000 | ||
54 | #define DA732X_MCLK_RET_0_10MHZ 0 | ||
55 | #define DA732X_MCLK_VAL_0_10MHZ 1 | ||
56 | #define DA732X_MCLK_RET_10_20MHZ 1 | ||
57 | #define DA732X_MCLK_VAL_10_20MHZ 2 | ||
58 | #define DA732X_MCLK_RET_20_40MHZ 2 | ||
59 | #define DA732X_MCLK_VAL_20_40MHZ 4 | ||
60 | #define DA732X_MCLK_RET_40_54MHZ 3 | ||
61 | #define DA732X_MCLK_VAL_40_54MHZ 8 | ||
62 | #define DA732X_DAI_ID1 0 | ||
63 | #define DA732X_DAI_ID2 1 | ||
64 | #define DA732X_SRCCLK_PLL 0 | ||
65 | #define DA732X_SRCCLK_MCLK 1 | ||
66 | |||
67 | #define DA732X_LIN_LP_VOL 0x4F | ||
68 | #define DA732X_LP_VOL 0x40 | ||
69 | |||
70 | /* Kcontrols */ | ||
71 | #define DA732X_DAC_EN_MAX 2 | ||
72 | #define DA732X_ADCL_MUX_MAX 2 | ||
73 | #define DA732X_ADCR_MUX_MAX 3 | ||
74 | #define DA732X_HPF_MODE_MAX 3 | ||
75 | #define DA732X_HPF_MODE_SHIFT 4 | ||
76 | #define DA732X_HPF_MUSIC_SHIFT 0 | ||
77 | #define DA732X_HPF_MUSIC_MAX 4 | ||
78 | #define DA732X_HPF_VOICE_SHIFT 4 | ||
79 | #define DA732X_HPF_VOICE_MAX 8 | ||
80 | #define DA732X_EQ_EN_MAX 1 | ||
81 | #define DA732X_HPF_VOICE 1 | ||
82 | #define DA732X_HPF_MUSIC 2 | ||
83 | #define DA732X_HPF_DISABLED 0 | ||
84 | #define DA732X_NO_INVERT 0 | ||
85 | #define DA732X_INVERT 1 | ||
86 | #define DA732X_SWITCH_MAX 1 | ||
87 | #define DA732X_ENABLE_CP 1 | ||
88 | #define DA732X_DISABLE_CP 0 | ||
89 | #define DA732X_DISABLE_ALL_CLKS 0 | ||
90 | #define DA732X_RESET_ADCS 0 | ||
91 | |||
92 | /* dB values */ | ||
93 | #define DA732X_MIC_VOL_DB_MIN 0 | ||
94 | #define DA732X_MIC_VOL_DB_INC 50 | ||
95 | #define DA732X_MIC_PRE_VOL_DB_MIN 0 | ||
96 | #define DA732X_MIC_PRE_VOL_DB_INC 600 | ||
97 | #define DA732X_AUX_VOL_DB_MIN -6000 | ||
98 | #define DA732X_AUX_VOL_DB_INC 150 | ||
99 | #define DA732X_HP_VOL_DB_MIN -2250 | ||
100 | #define DA732X_HP_VOL_DB_INC 150 | ||
101 | #define DA732X_LIN2_VOL_DB_MIN -1650 | ||
102 | #define DA732X_LIN2_VOL_DB_INC 150 | ||
103 | #define DA732X_LIN3_VOL_DB_MIN -1650 | ||
104 | #define DA732X_LIN3_VOL_DB_INC 150 | ||
105 | #define DA732X_LIN4_VOL_DB_MIN -2250 | ||
106 | #define DA732X_LIN4_VOL_DB_INC 150 | ||
107 | #define DA732X_EQ_BAND_VOL_DB_MIN -1050 | ||
108 | #define DA732X_EQ_BAND_VOL_DB_INC 150 | ||
109 | #define DA732X_DAC_VOL_DB_MIN -7725 | ||
110 | #define DA732X_DAC_VOL_DB_INC 75 | ||
111 | #define DA732X_ADC_VOL_DB_MIN 0 | ||
112 | #define DA732X_ADC_VOL_DB_INC -1 | ||
113 | #define DA732X_EQ_OVERALL_VOL_DB_MIN -1800 | ||
114 | #define DA732X_EQ_OVERALL_VOL_DB_INC 600 | ||
115 | |||
116 | #define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \ | ||
117 | {.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext} | ||
118 | |||
119 | enum da732x_sysctl { | ||
120 | DA732X_SR_8KHZ = 0x1, | ||
121 | DA732X_SR_11_025KHZ = 0x2, | ||
122 | DA732X_SR_12KHZ = 0x3, | ||
123 | DA732X_SR_16KHZ = 0x5, | ||
124 | DA732X_SR_22_05KHZ = 0x6, | ||
125 | DA732X_SR_24KHZ = 0x7, | ||
126 | DA732X_SR_32KHZ = 0x9, | ||
127 | DA732X_SR_44_1KHZ = 0xA, | ||
128 | DA732X_SR_48KHZ = 0xB, | ||
129 | DA732X_SR_88_1KHZ = 0xE, | ||
130 | DA732X_SR_96KHZ = 0xF, | ||
131 | }; | ||
132 | |||
133 | #endif /* __DA732X_H_ */ | ||
diff --git a/sound/soc/codecs/da732x_reg.h b/sound/soc/codecs/da732x_reg.h new file mode 100644 index 000000000000..bdd03ca4b2de --- /dev/null +++ b/sound/soc/codecs/da732x_reg.h | |||
@@ -0,0 +1,654 @@ | |||
1 | /* | ||
2 | * da732x_reg.h --- Dialog DA732X ALSA SoC Audio Registers Header File | ||
3 | * | ||
4 | * Copyright (C) 2012 Dialog Semiconductor GmbH | ||
5 | * | ||
6 | * Author: Michal Hajduk <Michal.Hajduk@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __DA732X_REG_H_ | ||
14 | #define __DA732X_REG_H_ | ||
15 | |||
16 | /* DA732X registers */ | ||
17 | #define DA732X_REG_STATUS_EXT 0x00 | ||
18 | #define DA732X_REG_STATUS 0x01 | ||
19 | #define DA732X_REG_REF1 0x02 | ||
20 | #define DA732X_REG_BIAS_EN 0x03 | ||
21 | #define DA732X_REG_BIAS1 0x04 | ||
22 | #define DA732X_REG_BIAS2 0x05 | ||
23 | #define DA732X_REG_BIAS3 0x06 | ||
24 | #define DA732X_REG_BIAS4 0x07 | ||
25 | #define DA732X_REG_MICBIAS2 0x0F | ||
26 | #define DA732X_REG_MICBIAS1 0x10 | ||
27 | #define DA732X_REG_MICDET 0x11 | ||
28 | #define DA732X_REG_MIC1_PRE 0x12 | ||
29 | #define DA732X_REG_MIC1 0x13 | ||
30 | #define DA732X_REG_MIC2_PRE 0x14 | ||
31 | #define DA732X_REG_MIC2 0x15 | ||
32 | #define DA732X_REG_AUX1L 0x16 | ||
33 | #define DA732X_REG_AUX1R 0x17 | ||
34 | #define DA732X_REG_MIC3_PRE 0x18 | ||
35 | #define DA732X_REG_MIC3 0x19 | ||
36 | #define DA732X_REG_INP_PINBIAS 0x1A | ||
37 | #define DA732X_REG_INP_ZC_EN 0x1B | ||
38 | #define DA732X_REG_INP_MUX 0x1D | ||
39 | #define DA732X_REG_HP_DET 0x20 | ||
40 | #define DA732X_REG_HPL_DAC_OFFSET 0x21 | ||
41 | #define DA732X_REG_HPL_DAC_OFF_CNTL 0x22 | ||
42 | #define DA732X_REG_HPL_OUT_OFFSET 0x23 | ||
43 | #define DA732X_REG_HPL 0x24 | ||
44 | #define DA732X_REG_HPL_VOL 0x25 | ||
45 | #define DA732X_REG_HPR_DAC_OFFSET 0x26 | ||
46 | #define DA732X_REG_HPR_DAC_OFF_CNTL 0x27 | ||
47 | #define DA732X_REG_HPR_OUT_OFFSET 0x28 | ||
48 | #define DA732X_REG_HPR 0x29 | ||
49 | #define DA732X_REG_HPR_VOL 0x2A | ||
50 | #define DA732X_REG_LIN2 0x2B | ||
51 | #define DA732X_REG_LIN3 0x2C | ||
52 | #define DA732X_REG_LIN4 0x2D | ||
53 | #define DA732X_REG_OUT_ZC_EN 0x2E | ||
54 | #define DA732X_REG_HP_LIN1_GNDSEL 0x37 | ||
55 | #define DA732X_REG_CP_HP1 0x3A | ||
56 | #define DA732X_REG_CP_HP2 0x3B | ||
57 | #define DA732X_REG_CP_CTRL1 0x40 | ||
58 | #define DA732X_REG_CP_CTRL2 0x41 | ||
59 | #define DA732X_REG_CP_CTRL3 0x42 | ||
60 | #define DA732X_REG_CP_LEVEL_MASK 0x43 | ||
61 | #define DA732X_REG_CP_DET 0x44 | ||
62 | #define DA732X_REG_CP_STATUS 0x45 | ||
63 | #define DA732X_REG_CP_THRESH1 0x46 | ||
64 | #define DA732X_REG_CP_THRESH2 0x47 | ||
65 | #define DA732X_REG_CP_THRESH3 0x48 | ||
66 | #define DA732X_REG_CP_THRESH4 0x49 | ||
67 | #define DA732X_REG_CP_THRESH5 0x4A | ||
68 | #define DA732X_REG_CP_THRESH6 0x4B | ||
69 | #define DA732X_REG_CP_THRESH7 0x4C | ||
70 | #define DA732X_REG_CP_THRESH8 0x4D | ||
71 | #define DA732X_REG_PLL_DIV_LO 0x50 | ||
72 | #define DA732X_REG_PLL_DIV_MID 0x51 | ||
73 | #define DA732X_REG_PLL_DIV_HI 0x52 | ||
74 | #define DA732X_REG_PLL_CTRL 0x53 | ||
75 | #define DA732X_REG_CLK_CTRL 0x54 | ||
76 | #define DA732X_REG_CLK_DSP 0x5A | ||
77 | #define DA732X_REG_CLK_EN1 0x5B | ||
78 | #define DA732X_REG_CLK_EN2 0x5C | ||
79 | #define DA732X_REG_CLK_EN3 0x5D | ||
80 | #define DA732X_REG_CLK_EN4 0x5E | ||
81 | #define DA732X_REG_CLK_EN5 0x5F | ||
82 | #define DA732X_REG_AIF_MCLK 0x60 | ||
83 | #define DA732X_REG_AIFA1 0x61 | ||
84 | #define DA732X_REG_AIFA2 0x62 | ||
85 | #define DA732X_REG_AIFA3 0x63 | ||
86 | #define DA732X_REG_AIFB1 0x64 | ||
87 | #define DA732X_REG_AIFB2 0x65 | ||
88 | #define DA732X_REG_AIFB3 0x66 | ||
89 | #define DA732X_REG_PC_CTRL 0x6A | ||
90 | #define DA732X_REG_DATA_ROUTE 0x70 | ||
91 | #define DA732X_REG_DSP_CTRL 0x71 | ||
92 | #define DA732X_REG_CIF_CTRL2 0x74 | ||
93 | #define DA732X_REG_HANDSHAKE 0x75 | ||
94 | #define DA732X_REG_MBOX0 0x76 | ||
95 | #define DA732X_REG_MBOX1 0x77 | ||
96 | #define DA732X_REG_MBOX2 0x78 | ||
97 | #define DA732X_REG_MBOX_STATUS 0x79 | ||
98 | #define DA732X_REG_SPARE1_OUT 0x7D | ||
99 | #define DA732X_REG_SPARE2_OUT 0x7E | ||
100 | #define DA732X_REG_SPARE1_IN 0x7F | ||
101 | #define DA732X_REG_ID 0x81 | ||
102 | #define DA732X_REG_ADC1_PD 0x90 | ||
103 | #define DA732X_REG_ADC1_HPF 0x93 | ||
104 | #define DA732X_REG_ADC1_SEL 0x94 | ||
105 | #define DA732X_REG_ADC1_EQ12 0x95 | ||
106 | #define DA732X_REG_ADC1_EQ34 0x96 | ||
107 | #define DA732X_REG_ADC1_EQ5 0x97 | ||
108 | #define DA732X_REG_ADC2_PD 0x98 | ||
109 | #define DA732X_REG_ADC2_HPF 0x9B | ||
110 | #define DA732X_REG_ADC2_SEL 0x9C | ||
111 | #define DA732X_REG_ADC2_EQ12 0x9D | ||
112 | #define DA732X_REG_ADC2_EQ34 0x9E | ||
113 | #define DA732X_REG_ADC2_EQ5 0x9F | ||
114 | #define DA732X_REG_DAC1_HPF 0xA0 | ||
115 | #define DA732X_REG_DAC1_L_VOL 0xA1 | ||
116 | #define DA732X_REG_DAC1_R_VOL 0xA2 | ||
117 | #define DA732X_REG_DAC1_SEL 0xA3 | ||
118 | #define DA732X_REG_DAC1_SOFTMUTE 0xA4 | ||
119 | #define DA732X_REG_DAC1_EQ12 0xA5 | ||
120 | #define DA732X_REG_DAC1_EQ34 0xA6 | ||
121 | #define DA732X_REG_DAC1_EQ5 0xA7 | ||
122 | #define DA732X_REG_DAC2_HPF 0xB0 | ||
123 | #define DA732X_REG_DAC2_L_VOL 0xB1 | ||
124 | #define DA732X_REG_DAC2_R_VOL 0xB2 | ||
125 | #define DA732X_REG_DAC2_SEL 0xB3 | ||
126 | #define DA732X_REG_DAC2_SOFTMUTE 0xB4 | ||
127 | #define DA732X_REG_DAC2_EQ12 0xB5 | ||
128 | #define DA732X_REG_DAC2_EQ34 0xB6 | ||
129 | #define DA732X_REG_DAC2_EQ5 0xB7 | ||
130 | #define DA732X_REG_DAC3_HPF 0xC0 | ||
131 | #define DA732X_REG_DAC3_VOL 0xC1 | ||
132 | #define DA732X_REG_DAC3_SEL 0xC3 | ||
133 | #define DA732X_REG_DAC3_SOFTMUTE 0xC4 | ||
134 | #define DA732X_REG_DAC3_EQ12 0xC5 | ||
135 | #define DA732X_REG_DAC3_EQ34 0xC6 | ||
136 | #define DA732X_REG_DAC3_EQ5 0xC7 | ||
137 | #define DA732X_REG_BIQ_BYP 0xD2 | ||
138 | #define DA732X_REG_DMA_CMD 0xD3 | ||
139 | #define DA732X_REG_DMA_ADDR0 0xD4 | ||
140 | #define DA732X_REG_DMA_ADDR1 0xD5 | ||
141 | #define DA732X_REG_DMA_DATA0 0xD6 | ||
142 | #define DA732X_REG_DMA_DATA1 0xD7 | ||
143 | #define DA732X_REG_DMA_DATA2 0xD8 | ||
144 | #define DA732X_REG_DMA_DATA3 0xD9 | ||
145 | #define DA732X_REG_DMA_STATUS 0xDA | ||
146 | #define DA732X_REG_BROWNOUT 0xDF | ||
147 | #define DA732X_REG_UNLOCK 0xE0 | ||
148 | |||
149 | #define DA732X_MAX_REG DA732X_REG_UNLOCK | ||
150 | /* | ||
151 | * Bits | ||
152 | */ | ||
153 | |||
154 | /* DA732X_REG_STATUS_EXT (addr=0x00) */ | ||
155 | #define DA732X_STATUS_EXT_DSP (1 << 4) | ||
156 | #define DA732X_STATUS_EXT_CLEAR (0 << 0) | ||
157 | |||
158 | /* DA732X_REG_STATUS (addr=0x01) */ | ||
159 | #define DA732X_STATUS_PLL_LOCK (1 << 0) | ||
160 | #define DA732X_STATUS_PLL_MCLK_DET (1 << 1) | ||
161 | #define DA732X_STATUS_HPDET_OUT (1 << 2) | ||
162 | #define DA732X_STATUS_INP_MIXDET_1 (1 << 3) | ||
163 | #define DA732X_STATUS_INP_MIXDET_2 (1 << 4) | ||
164 | #define DA732X_STATUS_BO_STATUS (1 << 5) | ||
165 | |||
166 | /* DA732X_REG_REF1 (addr=0x02) */ | ||
167 | #define DA732X_VMID_FASTCHG (1 << 1) | ||
168 | #define DA732X_VMID_FASTDISCHG (1 << 2) | ||
169 | #define DA732X_REFBUFX2_EN (1 << 6) | ||
170 | #define DA732X_REFBUFX2_DIS (0 << 6) | ||
171 | |||
172 | /* DA732X_REG_BIAS_EN (addr=0x03) */ | ||
173 | #define DA732X_BIAS_BOOST_MASK (3 << 0) | ||
174 | #define DA732X_BIAS_BOOST_100PC (0 << 0) | ||
175 | #define DA732X_BIAS_BOOST_133PC (1 << 0) | ||
176 | #define DA732X_BIAS_BOOST_88PC (2 << 0) | ||
177 | #define DA732X_BIAS_BOOST_50PC (3 << 0) | ||
178 | #define DA732X_BIAS_EN (1 << 7) | ||
179 | #define DA732X_BIAS_DIS (0 << 7) | ||
180 | |||
181 | /* DA732X_REG_BIAS1 (addr=0x04) */ | ||
182 | #define DA732X_BIAS1_HP_DAC_BIAS_MASK (3 << 0) | ||
183 | #define DA732X_BIAS1_HP_DAC_BIAS_100PC (0 << 0) | ||
184 | #define DA732X_BIAS1_HP_DAC_BIAS_150PC (1 << 0) | ||
185 | #define DA732X_BIAS1_HP_DAC_BIAS_50PC (2 << 0) | ||
186 | #define DA732X_BIAS1_HP_DAC_BIAS_75PC (3 << 0) | ||
187 | #define DA732X_BIAS1_HP_OUT_BIAS_MASK (7 << 4) | ||
188 | #define DA732X_BIAS1_HP_OUT_BIAS_100PC (0 << 4) | ||
189 | #define DA732X_BIAS1_HP_OUT_BIAS_125PC (1 << 4) | ||
190 | #define DA732X_BIAS1_HP_OUT_BIAS_150PC (2 << 4) | ||
191 | #define DA732X_BIAS1_HP_OUT_BIAS_175PC (3 << 4) | ||
192 | #define DA732X_BIAS1_HP_OUT_BIAS_200PC (4 << 4) | ||
193 | #define DA732X_BIAS1_HP_OUT_BIAS_250PC (5 << 4) | ||
194 | #define DA732X_BIAS1_HP_OUT_BIAS_300PC (6 << 4) | ||
195 | #define DA732X_BIAS1_HP_OUT_BIAS_350PC (7 << 4) | ||
196 | |||
197 | /* DA732X_REG_BIAS2 (addr=0x05) */ | ||
198 | #define DA732X_BIAS2_LINE2_DAC_BIAS_MASK (3 << 0) | ||
199 | #define DA732X_BIAS2_LINE2_DAC_BIAS_100PC (0 << 0) | ||
200 | #define DA732X_BIAS2_LINE2_DAC_BIAS_150PC (1 << 0) | ||
201 | #define DA732X_BIAS2_LINE2_DAC_BIAS_50PC (2 << 0) | ||
202 | #define DA732X_BIAS2_LINE2_DAC_BIAS_75PC (3 << 0) | ||
203 | #define DA732X_BIAS2_LINE2_OUT_BIAS_MASK (7 << 4) | ||
204 | #define DA732X_BIAS2_LINE2_OUT_BIAS_100PC (0 << 4) | ||
205 | #define DA732X_BIAS2_LINE2_OUT_BIAS_125PC (1 << 4) | ||
206 | #define DA732X_BIAS2_LINE2_OUT_BIAS_150PC (2 << 4) | ||
207 | #define DA732X_BIAS2_LINE2_OUT_BIAS_175PC (3 << 4) | ||
208 | #define DA732X_BIAS2_LINE2_OUT_BIAS_200PC (4 << 4) | ||
209 | #define DA732X_BIAS2_LINE2_OUT_BIAS_250PC (5 << 4) | ||
210 | #define DA732X_BIAS2_LINE2_OUT_BIAS_300PC (6 << 4) | ||
211 | #define DA732X_BIAS2_LINE2_OUT_BIAS_350PC (7 << 4) | ||
212 | |||
213 | /* DA732X_REG_BIAS3 (addr=0x06) */ | ||
214 | #define DA732X_BIAS3_LINE3_DAC_BIAS_MASK (3 << 0) | ||
215 | #define DA732X_BIAS3_LINE3_DAC_BIAS_100PC (0 << 0) | ||
216 | #define DA732X_BIAS3_LINE3_DAC_BIAS_150PC (1 << 0) | ||
217 | #define DA732X_BIAS3_LINE3_DAC_BIAS_50PC (2 << 0) | ||
218 | #define DA732X_BIAS3_LINE3_DAC_BIAS_75PC (3 << 0) | ||
219 | #define DA732X_BIAS3_LINE3_OUT_BIAS_MASK (7 << 4) | ||
220 | #define DA732X_BIAS3_LINE3_OUT_BIAS_100PC (0 << 4) | ||
221 | #define DA732X_BIAS3_LINE3_OUT_BIAS_125PC (1 << 4) | ||
222 | #define DA732X_BIAS3_LINE3_OUT_BIAS_150PC (2 << 4) | ||
223 | #define DA732X_BIAS3_LINE3_OUT_BIAS_175PC (3 << 4) | ||
224 | #define DA732X_BIAS3_LINE3_OUT_BIAS_200PC (4 << 4) | ||
225 | #define DA732X_BIAS3_LINE3_OUT_BIAS_250PC (5 << 4) | ||
226 | #define DA732X_BIAS3_LINE3_OUT_BIAS_300PC (6 << 4) | ||
227 | #define DA732X_BIAS3_LINE3_OUT_BIAS_350PC (7 << 4) | ||
228 | |||
229 | /* DA732X_REG_BIAS4 (addr=0x07) */ | ||
230 | #define DA732X_BIAS4_LINE4_DAC_BIAS_MASK (3 << 0) | ||
231 | #define DA732X_BIAS4_LINE4_DAC_BIAS_100PC (0 << 0) | ||
232 | #define DA732X_BIAS4_LINE4_DAC_BIAS_150PC (1 << 0) | ||
233 | #define DA732X_BIAS4_LINE4_DAC_BIAS_50PC (2 << 0) | ||
234 | #define DA732X_BIAS4_LINE4_DAC_BIAS_75PC (3 << 0) | ||
235 | #define DA732X_BIAS4_LINE4_OUT_BIAS_MASK (7 << 4) | ||
236 | #define DA732X_BIAS4_LINE4_OUT_BIAS_100PC (0 << 4) | ||
237 | #define DA732X_BIAS4_LINE4_OUT_BIAS_125PC (1 << 4) | ||
238 | #define DA732X_BIAS4_LINE4_OUT_BIAS_150PC (2 << 4) | ||
239 | #define DA732X_BIAS4_LINE4_OUT_BIAS_175PC (3 << 4) | ||
240 | #define DA732X_BIAS4_LINE4_OUT_BIAS_200PC (4 << 4) | ||
241 | #define DA732X_BIAS4_LINE4_OUT_BIAS_250PC (5 << 4) | ||
242 | #define DA732X_BIAS4_LINE4_OUT_BIAS_300PC (6 << 4) | ||
243 | #define DA732X_BIAS4_LINE4_OUT_BIAS_350PC (7 << 4) | ||
244 | |||
245 | /* DA732X_REG_SIF_VDD_SEL (addr=0x08) */ | ||
246 | #define DA732X_SIF_VDD_SEL_AIFA_VDD2 (1 << 0) | ||
247 | #define DA732X_SIF_VDD_SEL_AIFB_VDD2 (1 << 1) | ||
248 | #define DA732X_SIF_VDD_SEL_CIFA_VDD2 (1 << 4) | ||
249 | |||
250 | /* DA732X_REG_MICBIAS2/1 (addr=0x0F/0x10) */ | ||
251 | #define DA732X_MICBIAS_VOLTAGE_MASK (0x0F << 0) | ||
252 | #define DA732X_MICBIAS_VOLTAGE_2V (0x00 << 0) | ||
253 | #define DA732X_MICBIAS_VOLTAGE_2V05 (0x01 << 0) | ||
254 | #define DA732X_MICBIAS_VOLTAGE_2V1 (0x02 << 0) | ||
255 | #define DA732X_MICBIAS_VOLTAGE_2V15 (0x03 << 0) | ||
256 | #define DA732X_MICBIAS_VOLTAGE_2V2 (0x04 << 0) | ||
257 | #define DA732X_MICBIAS_VOLTAGE_2V25 (0x05 << 0) | ||
258 | #define DA732X_MICBIAS_VOLTAGE_2V3 (0x06 << 0) | ||
259 | #define DA732X_MICBIAS_VOLTAGE_2V35 (0x07 << 0) | ||
260 | #define DA732X_MICBIAS_VOLTAGE_2V4 (0x08 << 0) | ||
261 | #define DA732X_MICBIAS_VOLTAGE_2V45 (0x09 << 0) | ||
262 | #define DA732X_MICBIAS_VOLTAGE_2V5 (0x0A << 0) | ||
263 | #define DA732X_MICBIAS_EN (1 << 7) | ||
264 | #define DA732X_MICBIAS_EN_SHIFT 7 | ||
265 | #define DA732X_MICBIAS_VOLTAGE_SHIFT 0 | ||
266 | #define DA732X_MICBIAS_VOLTAGE_MAX 0x0B | ||
267 | |||
268 | /* DA732X_REG_MICDET (addr=0x11) */ | ||
269 | #define DA732X_MICDET_INP_MICRES (1 << 0) | ||
270 | #define DA732X_MICDET_INP_MICHOOK (1 << 1) | ||
271 | #define DA732X_MICDET_INP_DEBOUNCE_PRD_8MS (0 << 0) | ||
272 | #define DA732X_MICDET_INP_DEBOUNCE_PRD_16MS (1 << 0) | ||
273 | #define DA732X_MICDET_INP_DEBOUNCE_PRD_32MS (2 << 0) | ||
274 | #define DA732X_MICDET_INP_DEBOUNCE_PRD_64MS (3 << 0) | ||
275 | #define DA732X_MICDET_INP_MICDET_EN (1 << 7) | ||
276 | |||
277 | /* DA732X_REG_MIC1/2/3_PRE (addr=0x11/0x14/0x18) */ | ||
278 | #define DA732X_MICBOOST_MASK 0x7 | ||
279 | #define DA732X_MICBOOST_SHIFT 0 | ||
280 | #define DA732X_MICBOOST_MIN 0x1 | ||
281 | #define DA732X_MICBOOST_MAX DA732X_MICBOOST_MASK | ||
282 | |||
283 | /* DA732X_REG_MIC1/2/3 (addr=0x13/0x15/0x19) */ | ||
284 | #define DA732X_MIC_VOL_SHIFT 0 | ||
285 | #define DA732X_MIC_VOL_VAL_MASK 0x1F | ||
286 | #define DA732X_MIC_MUTE_SHIFT 6 | ||
287 | #define DA732X_MIC_EN_SHIFT 7 | ||
288 | #define DA732X_MIC_VOL_VAL_MIN 0x7 | ||
289 | #define DA732X_MIC_VOL_VAL_MAX DA732X_MIC_VOL_VAL_MASK | ||
290 | |||
291 | /* DA732X_REG_AUX1L/R (addr=0x16/0x17) */ | ||
292 | #define DA732X_AUX_VOL_SHIFT 0 | ||
293 | #define DA732X_AUX_VOL_MASK 0x7 | ||
294 | #define DA732X_AUX_MUTE_SHIFT 6 | ||
295 | #define DA732X_AUX_EN_SHIFT 7 | ||
296 | #define DA732X_AUX_VOL_VAL_MAX DA732X_AUX_VOL_MASK | ||
297 | |||
298 | /* DA732X_REG_INP_PINBIAS (addr=0x1A) */ | ||
299 | #define DA732X_INP_MICL_PINBIAS_EN (1 << 0) | ||
300 | #define DA732X_INP_MICR_PINBIAS_EN (1 << 1) | ||
301 | #define DA732X_INP_AUX1L_PINBIAS_EN (1 << 2) | ||
302 | #define DA732X_INP_AUX1R_PINBIAS_EN (1 << 3) | ||
303 | #define DA732X_INP_AUX2_PINBIAS_EN (1 << 4) | ||
304 | |||
305 | /* DA732X_REG_INP_ZC_EN (addr=0x1B) */ | ||
306 | #define DA732X_MIC1_PRE_ZC_EN (1 << 0) | ||
307 | #define DA732X_MIC1_ZC_EN (1 << 1) | ||
308 | #define DA732X_MIC2_PRE_ZC_EN (1 << 2) | ||
309 | #define DA732X_MIC2_ZC_EN (1 << 3) | ||
310 | #define DA732X_AUXL_ZC_EN (1 << 4) | ||
311 | #define DA732X_AUXR_ZC_EN (1 << 5) | ||
312 | #define DA732X_MIC3_PRE_ZC_EN (1 << 6) | ||
313 | #define DA732X_MIC3_ZC_EN (1 << 7) | ||
314 | |||
315 | /* DA732X_REG_INP_MUX (addr=0x1D) */ | ||
316 | #define DA732X_INP_ADC1L_MUX_SEL_AUX1L (0 << 0) | ||
317 | #define DA732X_INP_ADC1L_MUX_SEL_MIC1 (1 << 0) | ||
318 | #define DA732X_INP_ADC1R_MUX_SEL_MASK (3 << 2) | ||
319 | #define DA732X_INP_ADC1R_MUX_SEL_AUX1R (0 << 2) | ||
320 | #define DA732X_INP_ADC1R_MUX_SEL_MIC2 (1 << 2) | ||
321 | #define DA732X_INP_ADC1R_MUX_SEL_MIC3 (2 << 2) | ||
322 | #define DA732X_INP_ADC2L_MUX_SEL_AUX1L (0 << 4) | ||
323 | #define DA732X_INP_ADC2L_MUX_SEL_MICL (1 << 4) | ||
324 | #define DA732X_INP_ADC2R_MUX_SEL_MASK (3 << 6) | ||
325 | #define DA732X_INP_ADC2R_MUX_SEL_AUX1R (0 << 6) | ||
326 | #define DA732X_INP_ADC2R_MUX_SEL_MICR (1 << 6) | ||
327 | #define DA732X_INP_ADC2R_MUX_SEL_AUX2 (2 << 6) | ||
328 | #define DA732X_ADC1L_MUX_SEL_SHIFT 0 | ||
329 | #define DA732X_ADC1R_MUX_SEL_SHIFT 2 | ||
330 | #define DA732X_ADC2L_MUX_SEL_SHIFT 4 | ||
331 | #define DA732X_ADC2R_MUX_SEL_SHIFT 6 | ||
332 | |||
333 | /* DA732X_REG_HP_DET (addr=0x20) */ | ||
334 | #define DA732X_HP_DET_AZ (1 << 0) | ||
335 | #define DA732X_HP_DET_SEL1 (1 << 1) | ||
336 | #define DA732X_HP_DET_IS_MASK (3 << 2) | ||
337 | #define DA732X_HP_DET_IS_0_5UA (0 << 2) | ||
338 | #define DA732X_HP_DET_IS_1UA (1 << 2) | ||
339 | #define DA732X_HP_DET_IS_2UA (2 << 2) | ||
340 | #define DA732X_HP_DET_IS_4UA (3 << 2) | ||
341 | #define DA732X_HP_DET_RS_MASK (3 << 4) | ||
342 | #define DA732X_HP_DET_RS_INFINITE (0 << 4) | ||
343 | #define DA732X_HP_DET_RS_100KOHM (1 << 4) | ||
344 | #define DA732X_HP_DET_RS_10KOHM (2 << 4) | ||
345 | #define DA732X_HP_DET_RS_1KOHM (3 << 4) | ||
346 | #define DA732X_HP_DET_EN (1 << 7) | ||
347 | |||
348 | /* DA732X_REG_HPL_DAC_OFFSET (addr=0x21/0x26) */ | ||
349 | #define DA732X_HP_DAC_OFFSET_TRIM_MASK (0x3F << 0) | ||
350 | #define DA732X_HP_DAC_OFFSET_DAC_SIGN (1 << 6) | ||
351 | |||
352 | /* DA732X_REG_HPL_DAC_OFF_CNTL (addr=0x22/0x27) */ | ||
353 | #define DA732X_HP_DAC_OFF_CNTL_CONT_MASK (7 << 0) | ||
354 | #define DA732X_HP_DAC_OFF_CNTL_COMPO (1 << 3) | ||
355 | #define DA732X_HP_DAC_OFF_CALIBRATION (1 << 0) | ||
356 | #define DA732X_HP_DAC_OFF_SCALE_STEPS (1 << 1) | ||
357 | #define DA732X_HP_DAC_OFF_MASK 0x7F | ||
358 | #define DA732X_HP_DAC_COMPO_SHIFT 3 | ||
359 | |||
360 | /* DA732X_REG_HPL_OUT_OFFSET (addr=0x23/0x28) */ | ||
361 | #define DA732X_HP_OUT_OFFSET_MASK (0xFF << 0) | ||
362 | #define DA732X_HP_DAC_OFFSET_TRIM_VAL 0x7F | ||
363 | |||
364 | /* DA732X_REG_HPL/R (addr=0x24/0x29) */ | ||
365 | #define DA732X_HP_OUT_SIGN (1 << 0) | ||
366 | #define DA732X_HP_OUT_COMP (1 << 1) | ||
367 | #define DA732X_HP_OUT_RESERVED (1 << 2) | ||
368 | #define DA732X_HP_OUT_COMPO (1 << 3) | ||
369 | #define DA732X_HP_OUT_DAC_EN (1 << 4) | ||
370 | #define DA732X_HP_OUT_HIZ_EN (1 << 5) | ||
371 | #define DA732X_HP_OUT_HIZ_DIS (0 << 5) | ||
372 | #define DA732X_HP_OUT_MUTE (1 << 6) | ||
373 | #define DA732X_HP_OUT_EN (1 << 7) | ||
374 | #define DA732X_HP_OUT_COMPO_SHIFT 3 | ||
375 | #define DA732X_HP_OUT_DAC_EN_SHIFT 4 | ||
376 | #define DA732X_HP_HIZ_SHIFT 5 | ||
377 | #define DA732X_HP_MUTE_SHIFT 6 | ||
378 | #define DA732X_HP_OUT_EN_SHIFT 7 | ||
379 | |||
380 | #define DA732X_OUT_HIZ_EN (1 << 5) | ||
381 | #define DA732X_OUT_HIZ_DIS (0 << 5) | ||
382 | |||
383 | /* DA732X_REG_HPL/R_VOL (addr=0x25/0x2A) */ | ||
384 | #define DA732X_HP_VOL_VAL_MASK 0xF | ||
385 | #define DA732X_HP_VOL_SHIFT 0 | ||
386 | #define DA732X_HP_VOL_VAL_MAX DA732X_HP_VOL_VAL_MASK | ||
387 | |||
388 | /* DA732X_REG_LIN2/3/4 (addr=0x2B/0x2C/0x2D) */ | ||
389 | #define DA732X_LOUT_VOL_SHIFT 0 | ||
390 | #define DA732X_LOUT_VOL_MASK 0x0F | ||
391 | #define DA732X_LOUT_DAC_OFF (0 << 4) | ||
392 | #define DA732X_LOUT_DAC_EN (1 << 4) | ||
393 | #define DA732X_LOUT_HIZ_N_DIS (0 << 5) | ||
394 | #define DA732X_LOUT_HIZ_N_EN (1 << 5) | ||
395 | #define DA732X_LOUT_UNMUTED (0 << 6) | ||
396 | #define DA732X_LOUT_MUTED (1 << 6) | ||
397 | #define DA732X_LOUT_EN (0 << 7) | ||
398 | #define DA732X_LOUT_DIS (1 << 7) | ||
399 | #define DA732X_LOUT_DAC_EN_SHIFT 4 | ||
400 | #define DA732X_LOUT_MUTE_SHIFT 6 | ||
401 | #define DA732X_LIN_OUT_EN_SHIFT 7 | ||
402 | #define DA732X_LOUT_VOL_VAL_MAX DA732X_LOUT_VOL_MASK | ||
403 | |||
404 | /* DA732X_REG_OUT_ZC_EN (addr=0x2E) */ | ||
405 | #define DA732X_HPL_ZC_EN_SHIFT 0 | ||
406 | #define DA732X_HPR_ZC_EN_SHIFT 1 | ||
407 | #define DA732X_HPL_ZC_EN (1 << 0) | ||
408 | #define DA732X_HPL_ZC_DIS (0 << 0) | ||
409 | #define DA732X_HPR_ZC_EN (1 << 1) | ||
410 | #define DA732X_HPR_ZC_DIS (0 << 1) | ||
411 | #define DA732X_LIN2_ZC_EN (1 << 2) | ||
412 | #define DA732X_LIN2_ZC_DIS (0 << 2) | ||
413 | #define DA732X_LIN3_ZC_EN (1 << 3) | ||
414 | #define DA732X_LIN3_ZC_DIS (0 << 3) | ||
415 | #define DA732X_LIN4_ZC_EN (1 << 4) | ||
416 | #define DA732X_LIN4_ZC_DIS (0 << 4) | ||
417 | |||
418 | /* DA732X_REG_HP_LIN1_GNDSEL (addr=0x37) */ | ||
419 | #define DA732X_HP_OUT_GNDSEL (1 << 0) | ||
420 | |||
421 | /* DA732X_REG_CP_HP2 (addr=0x3a) */ | ||
422 | #define DA732X_HP_CP_PULSESKIP (1 << 0) | ||
423 | #define DA732X_HP_CP_REG (1 << 1) | ||
424 | #define DA732X_HP_CP_EN (1 << 3) | ||
425 | #define DA732X_HP_CP_DIS (0 << 3) | ||
426 | |||
427 | /* DA732X_REG_CP_CTRL1 (addr=0x40) */ | ||
428 | #define DA732X_CP_MODE_MASK (7 << 1) | ||
429 | #define DA732X_CP_CTRL_STANDBY (0 << 1) | ||
430 | #define DA732X_CP_CTRL_CPVDD6 (2 << 1) | ||
431 | #define DA732X_CP_CTRL_CPVDD5 (3 << 1) | ||
432 | #define DA732X_CP_CTRL_CPVDD4 (4 << 1) | ||
433 | #define DA732X_CP_CTRL_CPVDD3 (5 << 1) | ||
434 | #define DA732X_CP_CTRL_CPVDD2 (6 << 1) | ||
435 | #define DA732X_CP_CTRL_CPVDD1 (7 << 1) | ||
436 | #define DA723X_CP_DIS (0 << 7) | ||
437 | #define DA732X_CP_EN (1 << 7) | ||
438 | |||
439 | /* DA732X_REG_CP_CTRL2 (addr=0x41) */ | ||
440 | #define DA732X_CP_BOOST (1 << 0) | ||
441 | #define DA732X_CP_MANAGE_MAGNITUDE (2 << 2) | ||
442 | |||
443 | /* DA732X_REG_CP_CTRL3 (addr=0x42) */ | ||
444 | #define DA732X_CP_1MHZ (0 << 0) | ||
445 | #define DA732X_CP_500KHZ (1 << 0) | ||
446 | #define DA732X_CP_250KHZ (2 << 0) | ||
447 | #define DA732X_CP_125KHZ (3 << 0) | ||
448 | #define DA732X_CP_63KHZ (4 << 0) | ||
449 | #define DA732X_CP_0KHZ (5 << 0) | ||
450 | |||
451 | /* DA732X_REG_PLL_CTRL (addr=0x53) */ | ||
452 | #define DA732X_PLL_INDIV_MASK (3 << 0) | ||
453 | #define DA732X_PLL_SRM_EN (1 << 2) | ||
454 | #define DA732X_PLL_EN (1 << 7) | ||
455 | #define DA732X_PLL_BYPASS (0 << 0) | ||
456 | |||
457 | /* DA732X_REG_CLK_CTRL (addr=0x54) */ | ||
458 | #define DA732X_SR1_MASK (0xF) | ||
459 | #define DA732X_SR2_MASK (0xF0) | ||
460 | |||
461 | /* DA732X_REG_CLK_DSP (addr=0x5A) */ | ||
462 | #define DA732X_DSP_FREQ_MASK (7 << 0) | ||
463 | #define DA732X_DSP_FREQ_12MHZ (0 << 0) | ||
464 | #define DA732X_DSP_FREQ_24MHZ (1 << 0) | ||
465 | #define DA732X_DSP_FREQ_36MHZ (2 << 0) | ||
466 | #define DA732X_DSP_FREQ_48MHZ (3 << 0) | ||
467 | #define DA732X_DSP_FREQ_60MHZ (4 << 0) | ||
468 | #define DA732X_DSP_FREQ_72MHZ (5 << 0) | ||
469 | #define DA732X_DSP_FREQ_84MHZ (6 << 0) | ||
470 | #define DA732X_DSP_FREQ_96MHZ (7 << 0) | ||
471 | |||
472 | /* DA732X_REG_CLK_EN1 (addr=0x5B) */ | ||
473 | #define DA732X_DSP_CLK_EN (1 << 0) | ||
474 | #define DA732X_SYS3_CLK_EN (1 << 1) | ||
475 | #define DA732X_DSP12_CLK_EN (1 << 2) | ||
476 | #define DA732X_PC_CLK_EN (1 << 3) | ||
477 | #define DA732X_MCLK_SQR_EN (1 << 7) | ||
478 | |||
479 | /* DA732X_REG_CLK_EN2 (addr=0x5C) */ | ||
480 | #define DA732X_UART_CLK_EN (1 << 1) | ||
481 | #define DA732X_CP_CLK_EN (1 << 2) | ||
482 | #define DA732X_CP_CLK_DIS (0 << 2) | ||
483 | |||
484 | /* DA732X_REG_CLK_EN3 (addr=0x5D) */ | ||
485 | #define DA732X_ADCA_BB_CLK_EN (1 << 0) | ||
486 | #define DA732X_ADCC_BB_CLK_EN (1 << 4) | ||
487 | |||
488 | /* DA732X_REG_CLK_EN4 (addr=0x5E) */ | ||
489 | #define DA732X_DACA_BB_CLK_EN (1 << 0) | ||
490 | #define DA732X_DACC_BB_CLK_EN (1 << 4) | ||
491 | #define DA732X_DACA_BB_CLK_SHIFT 0 | ||
492 | #define DA732X_DACC_BB_CLK_SHIFT 4 | ||
493 | |||
494 | /* DA732X_REG_CLK_EN5 (addr=0x5F) */ | ||
495 | #define DA732X_DACE_BB_CLK_EN (1 << 0) | ||
496 | #define DA732X_DACE_BB_CLK_SHIFT 0 | ||
497 | |||
498 | /* DA732X_REG_AIF_MCLK (addr=0x60) */ | ||
499 | #define DA732X_AIFM_FRAME_64 (1 << 2) | ||
500 | #define DA732X_AIFM_SRC_SEL_AIFA (1 << 6) | ||
501 | #define DA732X_CLK_GENERATION_AIF_A (1 << 4) | ||
502 | #define DA732X_NO_CLK_GENERATION 0x0 | ||
503 | |||
504 | /* DA732X_REG_AIFA1 (addr=0x61) */ | ||
505 | #define DA732X_AIF_WORD_MASK (0x3 << 0) | ||
506 | #define DA732X_AIF_WORD_16 (0 << 0) | ||
507 | #define DA732X_AIF_WORD_20 (1 << 0) | ||
508 | #define DA732X_AIF_WORD_24 (2 << 0) | ||
509 | #define DA732X_AIF_WORD_32 (3 << 0) | ||
510 | #define DA732X_AIF_TDM_MONO_SHIFT (1 << 6) | ||
511 | #define DA732X_AIF1_CLK_MASK (1 << 7) | ||
512 | #define DA732X_AIF_SLAVE (0 << 7) | ||
513 | #define DA732X_AIF_CLK_FROM_SRC (1 << 7) | ||
514 | |||
515 | /* DA732X_REG_AIFA3 (addr=0x63) */ | ||
516 | #define DA732X_AIF_MODE_SHIFT 0 | ||
517 | #define DA732X_AIF_MODE_MASK 0x3 | ||
518 | #define DA732X_AIF_I2S_MODE (0 << 0) | ||
519 | #define DA732X_AIF_LEFT_J_MODE (1 << 0) | ||
520 | #define DA732X_AIF_RIGHT_J_MODE (2 << 0) | ||
521 | #define DA732X_AIF_DSP_MODE (3 << 0) | ||
522 | #define DA732X_AIF_WCLK_INV (1 << 4) | ||
523 | #define DA732X_AIF_BCLK_INV (1 << 5) | ||
524 | #define DA732X_AIF_EN (1 << 7) | ||
525 | #define DA732X_AIF_EN_SHIFT 7 | ||
526 | |||
527 | /* DA732X_REG_PC_CTRL (addr=0x6a) */ | ||
528 | #define DA732X_PC_PULSE_AIFA (0 << 0) | ||
529 | #define DA732X_PC_PULSE_AIFB (1 << 0) | ||
530 | #define DA732X_PC_RESYNC_AUT (1 << 6) | ||
531 | #define DA732X_PC_RESYNC_NOT_AUT (0 << 6) | ||
532 | #define DA732X_PC_SAME (1 << 7) | ||
533 | |||
534 | /* DA732X_REG_DATA_ROUTE (addr=0x70) */ | ||
535 | #define DA732X_ADC1_TO_AIFA (0 << 0) | ||
536 | #define DA732X_DSP_TO_AIFA (1 << 0) | ||
537 | #define DA732X_ADC2_TO_AIFB (0 << 1) | ||
538 | #define DA732X_DSP_TO_AIFB (1 << 1) | ||
539 | #define DA732X_AIFA_TO_DAC1L (0 << 2) | ||
540 | #define DA732X_DSP_TO_DAC1L (1 << 2) | ||
541 | #define DA732X_AIFA_TO_DAC1R (0 << 3) | ||
542 | #define DA732X_DSP_TO_DAC1R (1 << 3) | ||
543 | #define DA732X_AIFB_TO_DAC2L (0 << 4) | ||
544 | #define DA732X_DSP_TO_DAC2L (1 << 4) | ||
545 | #define DA732X_AIFB_TO_DAC2R (0 << 5) | ||
546 | #define DA732X_DSP_TO_DAC2R (1 << 5) | ||
547 | #define DA732X_AIFB_TO_DAC3 (0 << 6) | ||
548 | #define DA732X_DSP_TO_DAC3 (1 << 6) | ||
549 | #define DA732X_BYPASS_DSP (0 << 0) | ||
550 | #define DA732X_ALL_TO_DSP (0x7F << 0) | ||
551 | |||
552 | /* DA732X_REG_DSP_CTRL (addr=0x71) */ | ||
553 | #define DA732X_DIGITAL_EN (1 << 0) | ||
554 | #define DA732X_DIGITAL_RESET (0 << 0) | ||
555 | #define DA732X_DSP_CORE_EN (1 << 1) | ||
556 | #define DA732X_DSP_CORE_RESET (0 << 1) | ||
557 | |||
558 | /* DA732X_REG_SPARE1_OUT (addr=0x7D)*/ | ||
559 | #define DA732X_HP_DRIVER_EN (1 << 0) | ||
560 | #define DA732X_HP_GATE_LOW (1 << 2) | ||
561 | #define DA732X_HP_LOOP_GAIN_CTRL (1 << 3) | ||
562 | |||
563 | /* DA732X_REG_ID (addr=0x81)*/ | ||
564 | #define DA732X_ID_MINOR_MASK (0xF << 0) | ||
565 | #define DA732X_ID_MAJOR_MASK (0xF << 4) | ||
566 | |||
567 | /* DA732X_REG_ADC1/2_PD (addr=0x90/0x98) */ | ||
568 | #define DA732X_ADC_RST_MASK (0x3 << 0) | ||
569 | #define DA732X_ADC_PD_MASK (0x3 << 2) | ||
570 | #define DA732X_ADC_SET_ACT (0x3 << 0) | ||
571 | #define DA732X_ADC_SET_RST (0x0 << 0) | ||
572 | #define DA732X_ADC_ON (0x3 << 2) | ||
573 | #define DA732X_ADC_OFF (0x0 << 2) | ||
574 | |||
575 | /* DA732X_REG_ADC1/2_SEL (addr=0x94/0x9C) */ | ||
576 | #define DA732X_ADC_VOL_VAL_MASK 0x7 | ||
577 | #define DA732X_ADCL_VOL_SHIFT 0 | ||
578 | #define DA732X_ADCR_VOL_SHIFT 4 | ||
579 | #define DA732X_ADCL_EN_SHIFT 2 | ||
580 | #define DA732X_ADCR_EN_SHIFT 3 | ||
581 | #define DA732X_ADCL_EN (1 << 2) | ||
582 | #define DA732X_ADCR_EN (1 << 3) | ||
583 | #define DA732X_ADC_VOL_VAL_MAX DA732X_ADC_VOL_VAL_MASK | ||
584 | |||
585 | /* | ||
586 | * DA732X_REG_ADC1/2_HPF (addr=0x93/0x9b) | ||
587 | * DA732x_REG_DAC1/2/3_HPG (addr=0xA5/0xB5/0xC5) | ||
588 | */ | ||
589 | #define DA732X_HPF_MUSIC_EN (1 << 3) | ||
590 | #define DA732X_HPF_VOICE_EN ((1 << 3) | (1 << 7)) | ||
591 | #define DA732X_HPF_MASK ((1 << 3) | (1 << 7)) | ||
592 | #define DA732X_HPF_DIS ((0 << 3) | (0 << 7)) | ||
593 | |||
594 | /* DA732X_REG_DAC1/2/3_VOL */ | ||
595 | #define DA732X_DAC_VOL_VAL_MASK 0x7F | ||
596 | #define DA732X_DAC_VOL_SHIFT 0 | ||
597 | #define DA732X_DAC_VOL_VAL_MAX DA732X_DAC_VOL_VAL_MASK | ||
598 | |||
599 | /* DA732X_REG_DAC1/2/3_SEL (addr=0xA3/0xB3/0xC3) */ | ||
600 | #define DA732X_DACL_EN_SHIFT 3 | ||
601 | #define DA732X_DACR_EN_SHIFT 7 | ||
602 | #define DA732X_DACL_MUTE_SHIFT 2 | ||
603 | #define DA732X_DACR_MUTE_SHIFT 6 | ||
604 | #define DA732X_DACL_EN (1 << 3) | ||
605 | #define DA732X_DACR_EN (1 << 7) | ||
606 | #define DA732X_DACL_SDM (1 << 0) | ||
607 | #define DA732X_DACR_SDM (1 << 4) | ||
608 | #define DA732X_DACL_MUTE (1 << 2) | ||
609 | #define DA732X_DACR_MUTE (1 << 6) | ||
610 | |||
611 | /* DA732X_REG_DAC_SOFTMUTE (addr=0xA4/0xB4/0xC4) */ | ||
612 | #define DA732X_SOFTMUTE_EN (1 << 7) | ||
613 | #define DA732X_GAIN_RAMPED (1 << 6) | ||
614 | #define DA732X_16_SAMPLES (4 << 0) | ||
615 | #define DA732X_SOFTMUTE_MASK (1 << 7) | ||
616 | #define DA732X_SOFTMUTE_SHIFT 7 | ||
617 | |||
618 | /* | ||
619 | * DA732x_REG_ADC1/2_EQ12 (addr=0x95/0x9D) | ||
620 | * DA732x_REG_ADC1/2_EQ34 (addr=0x96/0x9E) | ||
621 | * DA732x_REG_ADC1/2_EQ5 (addr=0x97/0x9F) | ||
622 | * DA732x_REG_DAC1/2/3_EQ12 (addr=0xA5/0xB5/0xC5) | ||
623 | * DA732x_REG_DAC1/2/3_EQ34 (addr=0xA6/0xB6/0xC6) | ||
624 | * DA732x_REG_DAC1/2/3_EQ5 (addr=0xA7/0xB7/0xB7) | ||
625 | */ | ||
626 | #define DA732X_EQ_VOL_VAL_MASK 0xF | ||
627 | #define DA732X_EQ_BAND1_SHIFT 0 | ||
628 | #define DA732X_EQ_BAND2_SHIFT 4 | ||
629 | #define DA732X_EQ_BAND3_SHIFT 0 | ||
630 | #define DA732X_EQ_BAND4_SHIFT 4 | ||
631 | #define DA732X_EQ_BAND5_SHIFT 0 | ||
632 | #define DA732X_EQ_OVERALL_SHIFT 4 | ||
633 | #define DA732X_EQ_OVERALL_VOL_VAL_MASK 0x3 | ||
634 | #define DA732X_EQ_DIS (0 << 7) | ||
635 | #define DA732X_EQ_EN (1 << 7) | ||
636 | #define DA732X_EQ_EN_SHIFT 7 | ||
637 | #define DA732X_EQ_VOL_VAL_MAX DA732X_EQ_VOL_VAL_MASK | ||
638 | #define DA732X_EQ_OVERALL_VOL_VAL_MAX DA732X_EQ_OVERALL_VOL_VAL_MASK | ||
639 | |||
640 | /* DA732X_REG_DMA_CMD (addr=0xD3) */ | ||
641 | #define DA732X_SEL_DSP_DMA_MASK (3 << 0) | ||
642 | #define DA732X_SEL_DSP_DMA_DIS (0 << 0) | ||
643 | #define DA732X_SEL_DSP_DMA_PMEM (1 << 0) | ||
644 | #define DA732X_SEL_DSP_DMA_XMEM (2 << 0) | ||
645 | #define DA732X_SEL_DSP_DMA_YMEM (3 << 0) | ||
646 | #define DA732X_DSP_RW_MASK (1 << 4) | ||
647 | #define DA732X_DSP_DMA_WRITE (0 << 4) | ||
648 | #define DA732X_DSP_DMA_READ (1 << 4) | ||
649 | |||
650 | /* DA732X_REG_DMA_STATUS (addr=0xDA) */ | ||
651 | #define DA732X_DSP_DMA_FREE (0 << 0) | ||
652 | #define DA732X_DSP_DMA_BUSY (1 << 0) | ||
653 | |||
654 | #endif /* __DA732X_REG_H_ */ | ||
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c new file mode 100644 index 000000000000..5d8f39e32978 --- /dev/null +++ b/sound/soc/codecs/isabelle.c | |||
@@ -0,0 +1,1176 @@ | |||
1 | /* | ||
2 | * isabelle.c - Low power high fidelity audio codec driver | ||
3 | * | ||
4 | * Copyright (c) 2012 Texas Instruments, 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 as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * | ||
11 | * Initially based on sound/soc/codecs/twl6040.c | ||
12 | * | ||
13 | */ | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/version.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/pm.h> | ||
21 | #include <linux/regmap.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/soc.h> | ||
28 | #include <sound/soc-dapm.h> | ||
29 | #include <sound/tlv.h> | ||
30 | #include <sound/jack.h> | ||
31 | #include <sound/initval.h> | ||
32 | #include <asm/div64.h> | ||
33 | #include "isabelle.h" | ||
34 | |||
35 | |||
36 | /* Register default values for ISABELLE driver. */ | ||
37 | static struct reg_default isabelle_reg_defs[] = { | ||
38 | { 0, 0x00 }, | ||
39 | { 1, 0x00 }, | ||
40 | { 2, 0x00 }, | ||
41 | { 3, 0x00 }, | ||
42 | { 4, 0x00 }, | ||
43 | { 5, 0x00 }, | ||
44 | { 6, 0x00 }, | ||
45 | { 7, 0x00 }, | ||
46 | { 8, 0x00 }, | ||
47 | { 9, 0x00 }, | ||
48 | { 10, 0x00 }, | ||
49 | { 11, 0x00 }, | ||
50 | { 12, 0x00 }, | ||
51 | { 13, 0x00 }, | ||
52 | { 14, 0x00 }, | ||
53 | { 15, 0x00 }, | ||
54 | { 16, 0x00 }, | ||
55 | { 17, 0x00 }, | ||
56 | { 18, 0x00 }, | ||
57 | { 19, 0x00 }, | ||
58 | { 20, 0x00 }, | ||
59 | { 21, 0x02 }, | ||
60 | { 22, 0x02 }, | ||
61 | { 23, 0x02 }, | ||
62 | { 24, 0x02 }, | ||
63 | { 25, 0x0F }, | ||
64 | { 26, 0x8F }, | ||
65 | { 27, 0x0F }, | ||
66 | { 28, 0x8F }, | ||
67 | { 29, 0x00 }, | ||
68 | { 30, 0x00 }, | ||
69 | { 31, 0x00 }, | ||
70 | { 32, 0x00 }, | ||
71 | { 33, 0x00 }, | ||
72 | { 34, 0x00 }, | ||
73 | { 35, 0x00 }, | ||
74 | { 36, 0x00 }, | ||
75 | { 37, 0x00 }, | ||
76 | { 38, 0x00 }, | ||
77 | { 39, 0x00 }, | ||
78 | { 40, 0x00 }, | ||
79 | { 41, 0x00 }, | ||
80 | { 42, 0x00 }, | ||
81 | { 43, 0x00 }, | ||
82 | { 44, 0x00 }, | ||
83 | { 45, 0x00 }, | ||
84 | { 46, 0x00 }, | ||
85 | { 47, 0x00 }, | ||
86 | { 48, 0x00 }, | ||
87 | { 49, 0x00 }, | ||
88 | { 50, 0x00 }, | ||
89 | { 51, 0x00 }, | ||
90 | { 52, 0x00 }, | ||
91 | { 53, 0x00 }, | ||
92 | { 54, 0x00 }, | ||
93 | { 55, 0x00 }, | ||
94 | { 56, 0x00 }, | ||
95 | { 57, 0x00 }, | ||
96 | { 58, 0x00 }, | ||
97 | { 59, 0x00 }, | ||
98 | { 60, 0x00 }, | ||
99 | { 61, 0x00 }, | ||
100 | { 62, 0x00 }, | ||
101 | { 63, 0x00 }, | ||
102 | { 64, 0x00 }, | ||
103 | { 65, 0x00 }, | ||
104 | { 66, 0x00 }, | ||
105 | { 67, 0x00 }, | ||
106 | { 68, 0x00 }, | ||
107 | { 69, 0x90 }, | ||
108 | { 70, 0x90 }, | ||
109 | { 71, 0x90 }, | ||
110 | { 72, 0x00 }, | ||
111 | { 73, 0x00 }, | ||
112 | { 74, 0x00 }, | ||
113 | { 75, 0x00 }, | ||
114 | { 76, 0x00 }, | ||
115 | { 77, 0x00 }, | ||
116 | { 78, 0x00 }, | ||
117 | { 79, 0x00 }, | ||
118 | { 80, 0x00 }, | ||
119 | { 81, 0x00 }, | ||
120 | { 82, 0x00 }, | ||
121 | { 83, 0x00 }, | ||
122 | { 84, 0x00 }, | ||
123 | { 85, 0x07 }, | ||
124 | { 86, 0x00 }, | ||
125 | { 87, 0x00 }, | ||
126 | { 88, 0x00 }, | ||
127 | { 89, 0x07 }, | ||
128 | { 90, 0x80 }, | ||
129 | { 91, 0x07 }, | ||
130 | { 92, 0x07 }, | ||
131 | { 93, 0x00 }, | ||
132 | { 94, 0x00 }, | ||
133 | { 95, 0x00 }, | ||
134 | { 96, 0x00 }, | ||
135 | { 97, 0x00 }, | ||
136 | { 98, 0x00 }, | ||
137 | { 99, 0x00 }, | ||
138 | }; | ||
139 | |||
140 | static const char *isabelle_rx1_texts[] = {"VRX1", "ARX1"}; | ||
141 | static const char *isabelle_rx2_texts[] = {"VRX2", "ARX2"}; | ||
142 | |||
143 | static const struct soc_enum isabelle_rx1_enum[] = { | ||
144 | SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, 1, isabelle_rx1_texts), | ||
145 | SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, 1, isabelle_rx1_texts), | ||
146 | }; | ||
147 | |||
148 | static const struct soc_enum isabelle_rx2_enum[] = { | ||
149 | SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, 1, isabelle_rx2_texts), | ||
150 | SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, 1, isabelle_rx2_texts), | ||
151 | }; | ||
152 | |||
153 | /* Headset DAC playback switches */ | ||
154 | static const struct snd_kcontrol_new rx1_mux_controls = | ||
155 | SOC_DAPM_ENUM("Route", isabelle_rx1_enum); | ||
156 | |||
157 | static const struct snd_kcontrol_new rx2_mux_controls = | ||
158 | SOC_DAPM_ENUM("Route", isabelle_rx2_enum); | ||
159 | |||
160 | /* TX input selection */ | ||
161 | static const char *isabelle_atx_texts[] = {"AMIC1", "DMIC"}; | ||
162 | static const char *isabelle_vtx_texts[] = {"AMIC2", "DMIC"}; | ||
163 | |||
164 | static const struct soc_enum isabelle_atx_enum[] = { | ||
165 | SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, 1, isabelle_atx_texts), | ||
166 | SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_atx_texts), | ||
167 | }; | ||
168 | |||
169 | static const struct soc_enum isabelle_vtx_enum[] = { | ||
170 | SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, 1, isabelle_vtx_texts), | ||
171 | SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_vtx_texts), | ||
172 | }; | ||
173 | |||
174 | static const struct snd_kcontrol_new atx_mux_controls = | ||
175 | SOC_DAPM_ENUM("Route", isabelle_atx_enum); | ||
176 | |||
177 | static const struct snd_kcontrol_new vtx_mux_controls = | ||
178 | SOC_DAPM_ENUM("Route", isabelle_vtx_enum); | ||
179 | |||
180 | /* Left analog microphone selection */ | ||
181 | static const char *isabelle_amic1_texts[] = { | ||
182 | "Main Mic", "Headset Mic", "Aux/FM Left"}; | ||
183 | |||
184 | /* Left analog microphone selection */ | ||
185 | static const char *isabelle_amic2_texts[] = {"Sub Mic", "Aux/FM Right"}; | ||
186 | |||
187 | static const struct soc_enum isabelle_amic1_enum[] = { | ||
188 | SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 5, | ||
189 | ARRAY_SIZE(isabelle_amic1_texts), | ||
190 | isabelle_amic1_texts), | ||
191 | }; | ||
192 | |||
193 | static const struct soc_enum isabelle_amic2_enum[] = { | ||
194 | SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 4, | ||
195 | ARRAY_SIZE(isabelle_amic2_texts), | ||
196 | isabelle_amic2_texts), | ||
197 | }; | ||
198 | |||
199 | static const struct snd_kcontrol_new amic1_control = | ||
200 | SOC_DAPM_ENUM("Route", isabelle_amic1_enum); | ||
201 | |||
202 | static const struct snd_kcontrol_new amic2_control = | ||
203 | SOC_DAPM_ENUM("Route", isabelle_amic2_enum); | ||
204 | |||
205 | static const char *isabelle_st_audio_texts[] = {"ATX1", "ATX2"}; | ||
206 | |||
207 | static const char *isabelle_st_voice_texts[] = {"VTX1", "VTX2"}; | ||
208 | |||
209 | static const struct soc_enum isabelle_st_audio_enum[] = { | ||
210 | SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, 1, | ||
211 | isabelle_st_audio_texts), | ||
212 | SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, 1, | ||
213 | isabelle_st_audio_texts), | ||
214 | }; | ||
215 | |||
216 | static const struct soc_enum isabelle_st_voice_enum[] = { | ||
217 | SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, 1, | ||
218 | isabelle_st_voice_texts), | ||
219 | SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, 1, | ||
220 | isabelle_st_voice_texts), | ||
221 | }; | ||
222 | |||
223 | static const struct snd_kcontrol_new st_audio_control = | ||
224 | SOC_DAPM_ENUM("Route", isabelle_st_audio_enum); | ||
225 | |||
226 | static const struct snd_kcontrol_new st_voice_control = | ||
227 | SOC_DAPM_ENUM("Route", isabelle_st_voice_enum); | ||
228 | |||
229 | /* Mixer controls */ | ||
230 | static const struct snd_kcontrol_new isabelle_hs_left_mixer_controls[] = { | ||
231 | SOC_DAPM_SINGLE("DAC1L Playback Switch", ISABELLE_HSDRV_CFG1_REG, 7, 1, 0), | ||
232 | SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_HSDRV_CFG1_REG, 6, 1, 0), | ||
233 | }; | ||
234 | |||
235 | static const struct snd_kcontrol_new isabelle_hs_right_mixer_controls[] = { | ||
236 | SOC_DAPM_SINGLE("DAC1R Playback Switch", ISABELLE_HSDRV_CFG1_REG, 5, 1, 0), | ||
237 | SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_HSDRV_CFG1_REG, 4, 1, 0), | ||
238 | }; | ||
239 | |||
240 | static const struct snd_kcontrol_new isabelle_hf_left_mixer_controls[] = { | ||
241 | SOC_DAPM_SINGLE("DAC2L Playback Switch", ISABELLE_HFLPGA_CFG_REG, 7, 1, 0), | ||
242 | SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_HFLPGA_CFG_REG, 6, 1, 0), | ||
243 | }; | ||
244 | |||
245 | static const struct snd_kcontrol_new isabelle_hf_right_mixer_controls[] = { | ||
246 | SOC_DAPM_SINGLE("DAC2R Playback Switch", ISABELLE_HFRPGA_CFG_REG, 7, 1, 0), | ||
247 | SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_HFRPGA_CFG_REG, 6, 1, 0), | ||
248 | }; | ||
249 | |||
250 | static const struct snd_kcontrol_new isabelle_ep_mixer_controls[] = { | ||
251 | SOC_DAPM_SINGLE("DAC2L Playback Switch", ISABELLE_EARDRV_CFG1_REG, 7, 1, 0), | ||
252 | SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_EARDRV_CFG1_REG, 6, 1, 0), | ||
253 | }; | ||
254 | |||
255 | static const struct snd_kcontrol_new isabelle_aux_left_mixer_controls[] = { | ||
256 | SOC_DAPM_SINGLE("DAC3L Playback Switch", ISABELLE_LINEAMP_CFG_REG, 7, 1, 0), | ||
257 | SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_LINEAMP_CFG_REG, 6, 1, 0), | ||
258 | }; | ||
259 | |||
260 | static const struct snd_kcontrol_new isabelle_aux_right_mixer_controls[] = { | ||
261 | SOC_DAPM_SINGLE("DAC3R Playback Switch", ISABELLE_LINEAMP_CFG_REG, 5, 1, 0), | ||
262 | SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_LINEAMP_CFG_REG, 4, 1, 0), | ||
263 | }; | ||
264 | |||
265 | static const struct snd_kcontrol_new isabelle_dpga1_left_mixer_controls[] = { | ||
266 | SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 7, 1, 0), | ||
267 | SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 6, 1, 0), | ||
268 | SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 5, 1, 0), | ||
269 | }; | ||
270 | |||
271 | static const struct snd_kcontrol_new isabelle_dpga1_right_mixer_controls[] = { | ||
272 | SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 3, 1, 0), | ||
273 | SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 2, 1, 0), | ||
274 | SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 1, 1, 0), | ||
275 | }; | ||
276 | |||
277 | static const struct snd_kcontrol_new isabelle_dpga2_left_mixer_controls[] = { | ||
278 | SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 7, 1, 0), | ||
279 | SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 6, 1, 0), | ||
280 | SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 5, 1, 0), | ||
281 | SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 4, 1, 0), | ||
282 | SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 3, 1, 0), | ||
283 | SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 2, 1, 0), | ||
284 | }; | ||
285 | |||
286 | static const struct snd_kcontrol_new isabelle_dpga2_right_mixer_controls[] = { | ||
287 | SOC_DAPM_SINGLE("USNC Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 7, 1, 0), | ||
288 | SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 3, 1, 0), | ||
289 | SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 2, 1, 0), | ||
290 | SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 1, 1, 0), | ||
291 | }; | ||
292 | |||
293 | static const struct snd_kcontrol_new isabelle_dpga3_left_mixer_controls[] = { | ||
294 | SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 7, 1, 0), | ||
295 | SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 6, 1, 0), | ||
296 | SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 5, 1, 0), | ||
297 | }; | ||
298 | |||
299 | static const struct snd_kcontrol_new isabelle_dpga3_right_mixer_controls[] = { | ||
300 | SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 3, 1, 0), | ||
301 | SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 2, 1, 0), | ||
302 | SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 1, 1, 0), | ||
303 | }; | ||
304 | |||
305 | static const struct snd_kcontrol_new isabelle_rx1_mixer_controls[] = { | ||
306 | SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 7, 1, 0), | ||
307 | SOC_DAPM_SINGLE("DL1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 6, 1, 0), | ||
308 | }; | ||
309 | |||
310 | static const struct snd_kcontrol_new isabelle_rx2_mixer_controls[] = { | ||
311 | SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 5, 1, 0), | ||
312 | SOC_DAPM_SINGLE("DL2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 4, 1, 0), | ||
313 | }; | ||
314 | |||
315 | static const struct snd_kcontrol_new isabelle_rx3_mixer_controls[] = { | ||
316 | SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 3, 1, 0), | ||
317 | SOC_DAPM_SINGLE("DL3 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 2, 1, 0), | ||
318 | }; | ||
319 | |||
320 | static const struct snd_kcontrol_new isabelle_rx4_mixer_controls[] = { | ||
321 | SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 1, 1, 0), | ||
322 | SOC_DAPM_SINGLE("DL4 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 0, 1, 0), | ||
323 | }; | ||
324 | |||
325 | static const struct snd_kcontrol_new isabelle_rx5_mixer_controls[] = { | ||
326 | SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 7, 1, 0), | ||
327 | SOC_DAPM_SINGLE("DL5 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 6, 1, 0), | ||
328 | }; | ||
329 | |||
330 | static const struct snd_kcontrol_new isabelle_rx6_mixer_controls[] = { | ||
331 | SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 5, 1, 0), | ||
332 | SOC_DAPM_SINGLE("DL6 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 4, 1, 0), | ||
333 | }; | ||
334 | |||
335 | static const struct snd_kcontrol_new ep_path_enable_control = | ||
336 | SOC_DAPM_SINGLE("Switch", ISABELLE_EARDRV_CFG2_REG, 0, 1, 0); | ||
337 | |||
338 | /* TLV Declarations */ | ||
339 | static const DECLARE_TLV_DB_SCALE(mic_amp_tlv, 0, 100, 0); | ||
340 | static const DECLARE_TLV_DB_SCALE(afm_amp_tlv, -3300, 300, 0); | ||
341 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -1200, 200, 0); | ||
342 | static const DECLARE_TLV_DB_SCALE(hf_tlv, -5000, 200, 0); | ||
343 | |||
344 | /* from -63 to 0 dB in 1 dB steps */ | ||
345 | static const DECLARE_TLV_DB_SCALE(dpga_tlv, -6300, 100, 1); | ||
346 | |||
347 | /* from -63 to 9 dB in 1 dB steps */ | ||
348 | static const DECLARE_TLV_DB_SCALE(rx_tlv, -6300, 100, 1); | ||
349 | |||
350 | static const DECLARE_TLV_DB_SCALE(st_tlv, -2700, 300, 1); | ||
351 | static const DECLARE_TLV_DB_SCALE(tx_tlv, -600, 100, 0); | ||
352 | |||
353 | static const struct snd_kcontrol_new isabelle_snd_controls[] = { | ||
354 | SOC_DOUBLE_TLV("Headset Playback Volume", ISABELLE_HSDRV_GAIN_REG, | ||
355 | 4, 0, 0xF, 0, dac_tlv), | ||
356 | SOC_DOUBLE_R_TLV("Handsfree Playback Volume", | ||
357 | ISABELLE_HFLPGA_CFG_REG, ISABELLE_HFRPGA_CFG_REG, | ||
358 | 0, 0x1F, 0, hf_tlv), | ||
359 | SOC_DOUBLE_TLV("Aux Playback Volume", ISABELLE_LINEAMP_GAIN_REG, | ||
360 | 4, 0, 0xF, 0, dac_tlv), | ||
361 | SOC_SINGLE_TLV("Earpiece Playback Volume", ISABELLE_EARDRV_CFG1_REG, | ||
362 | 0, 0xF, 0, dac_tlv), | ||
363 | |||
364 | SOC_DOUBLE_TLV("Aux FM Volume", ISABELLE_APGA_GAIN_REG, 4, 0, 0xF, 0, | ||
365 | afm_amp_tlv), | ||
366 | SOC_SINGLE_TLV("Mic1 Capture Volume", ISABELLE_MIC1_GAIN_REG, 3, 0x1F, | ||
367 | 0, mic_amp_tlv), | ||
368 | SOC_SINGLE_TLV("Mic2 Capture Volume", ISABELLE_MIC2_GAIN_REG, 3, 0x1F, | ||
369 | 0, mic_amp_tlv), | ||
370 | |||
371 | SOC_DOUBLE_R_TLV("DPGA1 Volume", ISABELLE_DPGA1L_GAIN_REG, | ||
372 | ISABELLE_DPGA1R_GAIN_REG, 0, 0x3F, 0, dpga_tlv), | ||
373 | SOC_DOUBLE_R_TLV("DPGA2 Volume", ISABELLE_DPGA2L_GAIN_REG, | ||
374 | ISABELLE_DPGA2R_GAIN_REG, 0, 0x3F, 0, dpga_tlv), | ||
375 | SOC_DOUBLE_R_TLV("DPGA3 Volume", ISABELLE_DPGA3L_GAIN_REG, | ||
376 | ISABELLE_DPGA3R_GAIN_REG, 0, 0x3F, 0, dpga_tlv), | ||
377 | |||
378 | SOC_SINGLE_TLV("Sidetone Audio TX1 Volume", | ||
379 | ISABELLE_ATX_STPGA1_CFG_REG, 0, 0xF, 0, st_tlv), | ||
380 | SOC_SINGLE_TLV("Sidetone Audio TX2 Volume", | ||
381 | ISABELLE_ATX_STPGA2_CFG_REG, 0, 0xF, 0, st_tlv), | ||
382 | SOC_SINGLE_TLV("Sidetone Voice TX1 Volume", | ||
383 | ISABELLE_VTX_STPGA1_CFG_REG, 0, 0xF, 0, st_tlv), | ||
384 | SOC_SINGLE_TLV("Sidetone Voice TX2 Volume", | ||
385 | ISABELLE_VTX2_STPGA2_CFG_REG, 0, 0xF, 0, st_tlv), | ||
386 | |||
387 | SOC_SINGLE_TLV("Audio TX1 Volume", ISABELLE_ATX1_DPGA_REG, 4, 0xF, 0, | ||
388 | tx_tlv), | ||
389 | SOC_SINGLE_TLV("Audio TX2 Volume", ISABELLE_ATX2_DPGA_REG, 4, 0xF, 0, | ||
390 | tx_tlv), | ||
391 | SOC_SINGLE_TLV("Voice TX1 Volume", ISABELLE_VTX1_DPGA_REG, 4, 0xF, 0, | ||
392 | tx_tlv), | ||
393 | SOC_SINGLE_TLV("Voice TX2 Volume", ISABELLE_VTX2_DPGA_REG, 4, 0xF, 0, | ||
394 | tx_tlv), | ||
395 | |||
396 | SOC_SINGLE_TLV("RX1 DPGA Volume", ISABELLE_RX1_DPGA_REG, 0, 0x3F, 0, | ||
397 | rx_tlv), | ||
398 | SOC_SINGLE_TLV("RX2 DPGA Volume", ISABELLE_RX2_DPGA_REG, 0, 0x3F, 0, | ||
399 | rx_tlv), | ||
400 | SOC_SINGLE_TLV("RX3 DPGA Volume", ISABELLE_RX3_DPGA_REG, 0, 0x3F, 0, | ||
401 | rx_tlv), | ||
402 | SOC_SINGLE_TLV("RX4 DPGA Volume", ISABELLE_RX4_DPGA_REG, 0, 0x3F, 0, | ||
403 | rx_tlv), | ||
404 | SOC_SINGLE_TLV("RX5 DPGA Volume", ISABELLE_RX5_DPGA_REG, 0, 0x3F, 0, | ||
405 | rx_tlv), | ||
406 | SOC_SINGLE_TLV("RX6 DPGA Volume", ISABELLE_RX6_DPGA_REG, 0, 0x3F, 0, | ||
407 | rx_tlv), | ||
408 | |||
409 | SOC_SINGLE("Headset Noise Gate", ISABELLE_HS_NG_CFG1_REG, 7, 1, 0), | ||
410 | SOC_SINGLE("Handsfree Noise Gate", ISABELLE_HF_NG_CFG1_REG, 7, 1, 0), | ||
411 | |||
412 | SOC_SINGLE("ATX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | ||
413 | 7, 1, 0), | ||
414 | SOC_SINGLE("ATX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | ||
415 | 6, 1, 0), | ||
416 | SOC_SINGLE("ARX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | ||
417 | 5, 1, 0), | ||
418 | SOC_SINGLE("ARX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | ||
419 | 4, 1, 0), | ||
420 | SOC_SINGLE("ARX3 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | ||
421 | 3, 1, 0), | ||
422 | SOC_SINGLE("ARX4 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | ||
423 | 2, 1, 0), | ||
424 | SOC_SINGLE("ARX5 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | ||
425 | 1, 1, 0), | ||
426 | SOC_SINGLE("ARX6 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | ||
427 | 0, 1, 0), | ||
428 | SOC_SINGLE("VRX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | ||
429 | 3, 1, 0), | ||
430 | SOC_SINGLE("VRX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG, | ||
431 | 2, 1, 0), | ||
432 | |||
433 | SOC_SINGLE("ATX1 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG, | ||
434 | 7, 1, 0), | ||
435 | SOC_SINGLE("ATX2 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG, | ||
436 | 6, 1, 0), | ||
437 | SOC_SINGLE("VTX1 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG, | ||
438 | 5, 1, 0), | ||
439 | SOC_SINGLE("VTX2 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG, | ||
440 | 4, 1, 0), | ||
441 | SOC_SINGLE("RX1 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, | ||
442 | 5, 1, 0), | ||
443 | SOC_SINGLE("RX2 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, | ||
444 | 4, 1, 0), | ||
445 | SOC_SINGLE("RX3 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, | ||
446 | 3, 1, 0), | ||
447 | SOC_SINGLE("RX4 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, | ||
448 | 2, 1, 0), | ||
449 | SOC_SINGLE("RX5 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, | ||
450 | 1, 1, 0), | ||
451 | SOC_SINGLE("RX6 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG, | ||
452 | 0, 1, 0), | ||
453 | |||
454 | SOC_SINGLE("ULATX12 Capture Switch", ISABELLE_ULATX12_INTF_CFG_REG, | ||
455 | 7, 1, 0), | ||
456 | |||
457 | SOC_SINGLE("DL12 Playback Switch", ISABELLE_DL12_INTF_CFG_REG, | ||
458 | 7, 1, 0), | ||
459 | SOC_SINGLE("DL34 Playback Switch", ISABELLE_DL34_INTF_CFG_REG, | ||
460 | 7, 1, 0), | ||
461 | SOC_SINGLE("DL56 Playback Switch", ISABELLE_DL56_INTF_CFG_REG, | ||
462 | 7, 1, 0), | ||
463 | |||
464 | /* DMIC Switch */ | ||
465 | SOC_SINGLE("DMIC Switch", ISABELLE_DMIC_CFG_REG, 0, 1, 0), | ||
466 | }; | ||
467 | |||
468 | static const struct snd_soc_dapm_widget isabelle_dapm_widgets[] = { | ||
469 | /* Inputs */ | ||
470 | SND_SOC_DAPM_INPUT("MAINMIC"), | ||
471 | SND_SOC_DAPM_INPUT("HSMIC"), | ||
472 | SND_SOC_DAPM_INPUT("SUBMIC"), | ||
473 | SND_SOC_DAPM_INPUT("LINEIN1"), | ||
474 | SND_SOC_DAPM_INPUT("LINEIN2"), | ||
475 | SND_SOC_DAPM_INPUT("DMICDAT"), | ||
476 | |||
477 | /* Outputs */ | ||
478 | SND_SOC_DAPM_OUTPUT("HSOL"), | ||
479 | SND_SOC_DAPM_OUTPUT("HSOR"), | ||
480 | SND_SOC_DAPM_OUTPUT("HFL"), | ||
481 | SND_SOC_DAPM_OUTPUT("HFR"), | ||
482 | SND_SOC_DAPM_OUTPUT("EP"), | ||
483 | SND_SOC_DAPM_OUTPUT("LINEOUT1"), | ||
484 | SND_SOC_DAPM_OUTPUT("LINEOUT2"), | ||
485 | |||
486 | SND_SOC_DAPM_PGA("DL1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
487 | SND_SOC_DAPM_PGA("DL2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
488 | SND_SOC_DAPM_PGA("DL3", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
489 | SND_SOC_DAPM_PGA("DL4", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
490 | SND_SOC_DAPM_PGA("DL5", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
491 | SND_SOC_DAPM_PGA("DL6", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
492 | |||
493 | /* Analog input muxes for the capture amplifiers */ | ||
494 | SND_SOC_DAPM_MUX("Analog Left Capture Route", | ||
495 | SND_SOC_NOPM, 0, 0, &amic1_control), | ||
496 | SND_SOC_DAPM_MUX("Analog Right Capture Route", | ||
497 | SND_SOC_NOPM, 0, 0, &amic2_control), | ||
498 | |||
499 | SND_SOC_DAPM_MUX("Sidetone Audio Playback", SND_SOC_NOPM, 0, 0, | ||
500 | &st_audio_control), | ||
501 | SND_SOC_DAPM_MUX("Sidetone Voice Playback", SND_SOC_NOPM, 0, 0, | ||
502 | &st_voice_control), | ||
503 | |||
504 | /* AIF */ | ||
505 | SND_SOC_DAPM_AIF_IN("INTF1_SDI", NULL, 0, ISABELLE_INTF_EN_REG, 7, 0), | ||
506 | SND_SOC_DAPM_AIF_IN("INTF2_SDI", NULL, 0, ISABELLE_INTF_EN_REG, 6, 0), | ||
507 | |||
508 | SND_SOC_DAPM_AIF_OUT("INTF1_SDO", NULL, 0, ISABELLE_INTF_EN_REG, 5, 0), | ||
509 | SND_SOC_DAPM_AIF_OUT("INTF2_SDO", NULL, 0, ISABELLE_INTF_EN_REG, 4, 0), | ||
510 | |||
511 | SND_SOC_DAPM_OUT_DRV("ULATX1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
512 | SND_SOC_DAPM_OUT_DRV("ULATX2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
513 | SND_SOC_DAPM_OUT_DRV("ULVTX1", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
514 | SND_SOC_DAPM_OUT_DRV("ULVTX2", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
515 | |||
516 | /* Analog Capture PGAs */ | ||
517 | SND_SOC_DAPM_PGA("MicAmp1", ISABELLE_AMIC_CFG_REG, 5, 0, NULL, 0), | ||
518 | SND_SOC_DAPM_PGA("MicAmp2", ISABELLE_AMIC_CFG_REG, 4, 0, NULL, 0), | ||
519 | |||
520 | /* Auxiliary FM PGAs */ | ||
521 | SND_SOC_DAPM_PGA("APGA1", ISABELLE_APGA_CFG_REG, 7, 0, NULL, 0), | ||
522 | SND_SOC_DAPM_PGA("APGA2", ISABELLE_APGA_CFG_REG, 6, 0, NULL, 0), | ||
523 | |||
524 | /* ADCs */ | ||
525 | SND_SOC_DAPM_ADC("ADC1", "Left Front Capture", | ||
526 | ISABELLE_AMIC_CFG_REG, 7, 0), | ||
527 | SND_SOC_DAPM_ADC("ADC2", "Right Front Capture", | ||
528 | ISABELLE_AMIC_CFG_REG, 6, 0), | ||
529 | |||
530 | /* Microphone Bias */ | ||
531 | SND_SOC_DAPM_SUPPLY("Headset Mic Bias", ISABELLE_ABIAS_CFG_REG, | ||
532 | 3, 0, NULL, 0), | ||
533 | SND_SOC_DAPM_SUPPLY("Main Mic Bias", ISABELLE_ABIAS_CFG_REG, | ||
534 | 2, 0, NULL, 0), | ||
535 | SND_SOC_DAPM_SUPPLY("Digital Mic1 Bias", | ||
536 | ISABELLE_DBIAS_CFG_REG, 3, 0, NULL, 0), | ||
537 | SND_SOC_DAPM_SUPPLY("Digital Mic2 Bias", | ||
538 | ISABELLE_DBIAS_CFG_REG, 2, 0, NULL, 0), | ||
539 | |||
540 | /* Mixers */ | ||
541 | SND_SOC_DAPM_MIXER("Headset Left Mixer", SND_SOC_NOPM, 0, 0, | ||
542 | isabelle_hs_left_mixer_controls, | ||
543 | ARRAY_SIZE(isabelle_hs_left_mixer_controls)), | ||
544 | SND_SOC_DAPM_MIXER("Headset Right Mixer", SND_SOC_NOPM, 0, 0, | ||
545 | isabelle_hs_right_mixer_controls, | ||
546 | ARRAY_SIZE(isabelle_hs_right_mixer_controls)), | ||
547 | SND_SOC_DAPM_MIXER("Handsfree Left Mixer", SND_SOC_NOPM, 0, 0, | ||
548 | isabelle_hf_left_mixer_controls, | ||
549 | ARRAY_SIZE(isabelle_hf_left_mixer_controls)), | ||
550 | SND_SOC_DAPM_MIXER("Handsfree Right Mixer", SND_SOC_NOPM, 0, 0, | ||
551 | isabelle_hf_right_mixer_controls, | ||
552 | ARRAY_SIZE(isabelle_hf_right_mixer_controls)), | ||
553 | SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0, | ||
554 | isabelle_aux_left_mixer_controls, | ||
555 | ARRAY_SIZE(isabelle_aux_left_mixer_controls)), | ||
556 | SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0, | ||
557 | isabelle_aux_right_mixer_controls, | ||
558 | ARRAY_SIZE(isabelle_aux_right_mixer_controls)), | ||
559 | SND_SOC_DAPM_MIXER("Earphone Mixer", SND_SOC_NOPM, 0, 0, | ||
560 | isabelle_ep_mixer_controls, | ||
561 | ARRAY_SIZE(isabelle_ep_mixer_controls)), | ||
562 | |||
563 | SND_SOC_DAPM_MIXER("DPGA1L Mixer", SND_SOC_NOPM, 0, 0, | ||
564 | isabelle_dpga1_left_mixer_controls, | ||
565 | ARRAY_SIZE(isabelle_dpga1_left_mixer_controls)), | ||
566 | SND_SOC_DAPM_MIXER("DPGA1R Mixer", SND_SOC_NOPM, 0, 0, | ||
567 | isabelle_dpga1_right_mixer_controls, | ||
568 | ARRAY_SIZE(isabelle_dpga1_right_mixer_controls)), | ||
569 | SND_SOC_DAPM_MIXER("DPGA2L Mixer", SND_SOC_NOPM, 0, 0, | ||
570 | isabelle_dpga2_left_mixer_controls, | ||
571 | ARRAY_SIZE(isabelle_dpga2_left_mixer_controls)), | ||
572 | SND_SOC_DAPM_MIXER("DPGA2R Mixer", SND_SOC_NOPM, 0, 0, | ||
573 | isabelle_dpga2_right_mixer_controls, | ||
574 | ARRAY_SIZE(isabelle_dpga2_right_mixer_controls)), | ||
575 | SND_SOC_DAPM_MIXER("DPGA3L Mixer", SND_SOC_NOPM, 0, 0, | ||
576 | isabelle_dpga3_left_mixer_controls, | ||
577 | ARRAY_SIZE(isabelle_dpga3_left_mixer_controls)), | ||
578 | SND_SOC_DAPM_MIXER("DPGA3R Mixer", SND_SOC_NOPM, 0, 0, | ||
579 | isabelle_dpga3_right_mixer_controls, | ||
580 | ARRAY_SIZE(isabelle_dpga3_right_mixer_controls)), | ||
581 | |||
582 | SND_SOC_DAPM_MIXER("RX1 Mixer", SND_SOC_NOPM, 0, 0, | ||
583 | isabelle_rx1_mixer_controls, | ||
584 | ARRAY_SIZE(isabelle_rx1_mixer_controls)), | ||
585 | SND_SOC_DAPM_MIXER("RX2 Mixer", SND_SOC_NOPM, 0, 0, | ||
586 | isabelle_rx2_mixer_controls, | ||
587 | ARRAY_SIZE(isabelle_rx2_mixer_controls)), | ||
588 | SND_SOC_DAPM_MIXER("RX3 Mixer", SND_SOC_NOPM, 0, 0, | ||
589 | isabelle_rx3_mixer_controls, | ||
590 | ARRAY_SIZE(isabelle_rx3_mixer_controls)), | ||
591 | SND_SOC_DAPM_MIXER("RX4 Mixer", SND_SOC_NOPM, 0, 0, | ||
592 | isabelle_rx4_mixer_controls, | ||
593 | ARRAY_SIZE(isabelle_rx4_mixer_controls)), | ||
594 | SND_SOC_DAPM_MIXER("RX5 Mixer", SND_SOC_NOPM, 0, 0, | ||
595 | isabelle_rx5_mixer_controls, | ||
596 | ARRAY_SIZE(isabelle_rx5_mixer_controls)), | ||
597 | SND_SOC_DAPM_MIXER("RX6 Mixer", SND_SOC_NOPM, 0, 0, | ||
598 | isabelle_rx6_mixer_controls, | ||
599 | ARRAY_SIZE(isabelle_rx6_mixer_controls)), | ||
600 | |||
601 | /* DACs */ | ||
602 | SND_SOC_DAPM_DAC("DAC1L", "Headset Playback", ISABELLE_DAC_CFG_REG, | ||
603 | 5, 0), | ||
604 | SND_SOC_DAPM_DAC("DAC1R", "Headset Playback", ISABELLE_DAC_CFG_REG, | ||
605 | 4, 0), | ||
606 | SND_SOC_DAPM_DAC("DAC2L", "Handsfree Playback", ISABELLE_DAC_CFG_REG, | ||
607 | 3, 0), | ||
608 | SND_SOC_DAPM_DAC("DAC2R", "Handsfree Playback", ISABELLE_DAC_CFG_REG, | ||
609 | 2, 0), | ||
610 | SND_SOC_DAPM_DAC("DAC3L", "Lineout Playback", ISABELLE_DAC_CFG_REG, | ||
611 | 1, 0), | ||
612 | SND_SOC_DAPM_DAC("DAC3R", "Lineout Playback", ISABELLE_DAC_CFG_REG, | ||
613 | 0, 0), | ||
614 | |||
615 | /* Analog Playback PGAs */ | ||
616 | SND_SOC_DAPM_PGA("Sidetone Audio PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
617 | SND_SOC_DAPM_PGA("Sidetone Voice PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
618 | SND_SOC_DAPM_PGA("HF Left PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
619 | SND_SOC_DAPM_PGA("HF Right PGA", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
620 | SND_SOC_DAPM_PGA("DPGA1L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
621 | SND_SOC_DAPM_PGA("DPGA1R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
622 | SND_SOC_DAPM_PGA("DPGA2L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
623 | SND_SOC_DAPM_PGA("DPGA2R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
624 | SND_SOC_DAPM_PGA("DPGA3L", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
625 | SND_SOC_DAPM_PGA("DPGA3R", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
626 | |||
627 | /* Analog Playback Mux */ | ||
628 | SND_SOC_DAPM_MUX("RX1 Playback", ISABELLE_ALU_RX_EN_REG, 5, 0, | ||
629 | &rx1_mux_controls), | ||
630 | SND_SOC_DAPM_MUX("RX2 Playback", ISABELLE_ALU_RX_EN_REG, 4, 0, | ||
631 | &rx2_mux_controls), | ||
632 | |||
633 | /* TX Select */ | ||
634 | SND_SOC_DAPM_MUX("ATX Select", ISABELLE_TX_INPUT_CFG_REG, | ||
635 | 7, 0, &atx_mux_controls), | ||
636 | SND_SOC_DAPM_MUX("VTX Select", ISABELLE_TX_INPUT_CFG_REG, | ||
637 | 6, 0, &vtx_mux_controls), | ||
638 | |||
639 | SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0, | ||
640 | &ep_path_enable_control), | ||
641 | |||
642 | /* Output Drivers */ | ||
643 | SND_SOC_DAPM_OUT_DRV("HS Left Driver", ISABELLE_HSDRV_CFG2_REG, | ||
644 | 1, 0, NULL, 0), | ||
645 | SND_SOC_DAPM_OUT_DRV("HS Right Driver", ISABELLE_HSDRV_CFG2_REG, | ||
646 | 0, 0, NULL, 0), | ||
647 | SND_SOC_DAPM_OUT_DRV("LINEOUT1 Left Driver", ISABELLE_LINEAMP_CFG_REG, | ||
648 | 1, 0, NULL, 0), | ||
649 | SND_SOC_DAPM_OUT_DRV("LINEOUT2 Right Driver", ISABELLE_LINEAMP_CFG_REG, | ||
650 | 0, 0, NULL, 0), | ||
651 | SND_SOC_DAPM_OUT_DRV("Earphone Driver", ISABELLE_EARDRV_CFG2_REG, | ||
652 | 1, 0, NULL, 0), | ||
653 | |||
654 | SND_SOC_DAPM_OUT_DRV("HF Left Driver", ISABELLE_HFDRV_CFG_REG, | ||
655 | 1, 0, NULL, 0), | ||
656 | SND_SOC_DAPM_OUT_DRV("HF Right Driver", ISABELLE_HFDRV_CFG_REG, | ||
657 | 0, 0, NULL, 0), | ||
658 | }; | ||
659 | |||
660 | static const struct snd_soc_dapm_route isabelle_intercon[] = { | ||
661 | /* Interface mapping */ | ||
662 | { "DL1", "DL12 Playback Switch", "INTF1_SDI" }, | ||
663 | { "DL2", "DL12 Playback Switch", "INTF1_SDI" }, | ||
664 | { "DL3", "DL34 Playback Switch", "INTF1_SDI" }, | ||
665 | { "DL4", "DL34 Playback Switch", "INTF1_SDI" }, | ||
666 | { "DL5", "DL56 Playback Switch", "INTF1_SDI" }, | ||
667 | { "DL6", "DL56 Playback Switch", "INTF1_SDI" }, | ||
668 | |||
669 | { "DL1", "DL12 Playback Switch", "INTF2_SDI" }, | ||
670 | { "DL2", "DL12 Playback Switch", "INTF2_SDI" }, | ||
671 | { "DL3", "DL34 Playback Switch", "INTF2_SDI" }, | ||
672 | { "DL4", "DL34 Playback Switch", "INTF2_SDI" }, | ||
673 | { "DL5", "DL56 Playback Switch", "INTF2_SDI" }, | ||
674 | { "DL6", "DL56 Playback Switch", "INTF2_SDI" }, | ||
675 | |||
676 | /* Input side mapping */ | ||
677 | { "Sidetone Audio PGA", NULL, "Sidetone Audio Playback" }, | ||
678 | { "Sidetone Voice PGA", NULL, "Sidetone Voice Playback" }, | ||
679 | |||
680 | { "RX1 Mixer", "ST1 Playback Switch", "Sidetone Audio PGA" }, | ||
681 | |||
682 | { "RX1 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" }, | ||
683 | { "RX1 Mixer", "DL1 Playback Switch", "DL1" }, | ||
684 | |||
685 | { "RX2 Mixer", "ST2 Playback Switch", "Sidetone Audio PGA" }, | ||
686 | |||
687 | { "RX2 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" }, | ||
688 | { "RX2 Mixer", "DL2 Playback Switch", "DL2" }, | ||
689 | |||
690 | { "RX3 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" }, | ||
691 | { "RX3 Mixer", "DL3 Playback Switch", "DL3" }, | ||
692 | |||
693 | { "RX4 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" }, | ||
694 | { "RX4 Mixer", "DL4 Playback Switch", "DL4" }, | ||
695 | |||
696 | { "RX5 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" }, | ||
697 | { "RX5 Mixer", "DL5 Playback Switch", "DL5" }, | ||
698 | |||
699 | { "RX6 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" }, | ||
700 | { "RX6 Mixer", "DL6 Playback Switch", "DL6" }, | ||
701 | |||
702 | /* Capture path */ | ||
703 | { "Analog Left Capture Route", "Headset Mic", "HSMIC" }, | ||
704 | { "Analog Left Capture Route", "Main Mic", "MAINMIC" }, | ||
705 | { "Analog Left Capture Route", "Aux/FM Left", "LINEIN1" }, | ||
706 | |||
707 | { "Analog Right Capture Route", "Sub Mic", "SUBMIC" }, | ||
708 | { "Analog Right Capture Route", "Aux/FM Right", "LINEIN2" }, | ||
709 | |||
710 | { "MicAmp1", NULL, "Analog Left Capture Route" }, | ||
711 | { "MicAmp2", NULL, "Analog Right Capture Route" }, | ||
712 | |||
713 | { "ADC1", NULL, "MicAmp1" }, | ||
714 | { "ADC2", NULL, "MicAmp2" }, | ||
715 | |||
716 | { "ATX Select", "AMIC1", "ADC1" }, | ||
717 | { "ATX Select", "DMIC", "DMICDAT" }, | ||
718 | { "ATX Select", "AMIC2", "ADC2" }, | ||
719 | |||
720 | { "VTX Select", "AMIC1", "ADC1" }, | ||
721 | { "VTX Select", "DMIC", "DMICDAT" }, | ||
722 | { "VTX Select", "AMIC2", "ADC2" }, | ||
723 | |||
724 | { "ULATX1", "ATX1 Filter Enable Switch", "ATX Select" }, | ||
725 | { "ULATX1", "ATX1 Filter Bypass Switch", "ATX Select" }, | ||
726 | { "ULATX2", "ATX2 Filter Enable Switch", "ATX Select" }, | ||
727 | { "ULATX2", "ATX2 Filter Bypass Switch", "ATX Select" }, | ||
728 | |||
729 | { "ULVTX1", "VTX1 Filter Enable Switch", "VTX Select" }, | ||
730 | { "ULVTX1", "VTX1 Filter Bypass Switch", "VTX Select" }, | ||
731 | { "ULVTX2", "VTX2 Filter Enable Switch", "VTX Select" }, | ||
732 | { "ULVTX2", "VTX2 Filter Bypass Switch", "VTX Select" }, | ||
733 | |||
734 | { "INTF1_SDO", "ULATX12 Capture Switch", "ULATX1" }, | ||
735 | { "INTF1_SDO", "ULATX12 Capture Switch", "ULATX2" }, | ||
736 | { "INTF2_SDO", "ULATX12 Capture Switch", "ULATX1" }, | ||
737 | { "INTF2_SDO", "ULATX12 Capture Switch", "ULATX2" }, | ||
738 | |||
739 | { "INTF1_SDO", NULL, "ULVTX1" }, | ||
740 | { "INTF1_SDO", NULL, "ULVTX2" }, | ||
741 | { "INTF2_SDO", NULL, "ULVTX1" }, | ||
742 | { "INTF2_SDO", NULL, "ULVTX2" }, | ||
743 | |||
744 | /* AFM Path */ | ||
745 | { "APGA1", NULL, "LINEIN1" }, | ||
746 | { "APGA2", NULL, "LINEIN2" }, | ||
747 | |||
748 | { "RX1 Playback", "VRX1 Filter Bypass Switch", "RX1 Mixer" }, | ||
749 | { "RX1 Playback", "ARX1 Filter Bypass Switch", "RX1 Mixer" }, | ||
750 | { "RX1 Playback", "RX1 Filter Enable Switch", "RX1 Mixer" }, | ||
751 | |||
752 | { "RX2 Playback", "VRX2 Filter Bypass Switch", "RX2 Mixer" }, | ||
753 | { "RX2 Playback", "ARX2 Filter Bypass Switch", "RX2 Mixer" }, | ||
754 | { "RX2 Playback", "RX2 Filter Enable Switch", "RX2 Mixer" }, | ||
755 | |||
756 | { "RX3 Playback", "ARX3 Filter Bypass Switch", "RX3 Mixer" }, | ||
757 | { "RX3 Playback", "RX3 Filter Enable Switch", "RX3 Mixer" }, | ||
758 | |||
759 | { "RX4 Playback", "ARX4 Filter Bypass Switch", "RX4 Mixer" }, | ||
760 | { "RX4 Playback", "RX4 Filter Enable Switch", "RX4 Mixer" }, | ||
761 | |||
762 | { "RX5 Playback", "ARX5 Filter Bypass Switch", "RX5 Mixer" }, | ||
763 | { "RX5 Playback", "RX5 Filter Enable Switch", "RX5 Mixer" }, | ||
764 | |||
765 | { "RX6 Playback", "ARX6 Filter Bypass Switch", "RX6 Mixer" }, | ||
766 | { "RX6 Playback", "RX6 Filter Enable Switch", "RX6 Mixer" }, | ||
767 | |||
768 | { "DPGA1L Mixer", "RX1 Playback Switch", "RX1 Playback" }, | ||
769 | { "DPGA1L Mixer", "RX3 Playback Switch", "RX3 Playback" }, | ||
770 | { "DPGA1L Mixer", "RX5 Playback Switch", "RX5 Playback" }, | ||
771 | |||
772 | { "DPGA1R Mixer", "RX2 Playback Switch", "RX2 Playback" }, | ||
773 | { "DPGA1R Mixer", "RX4 Playback Switch", "RX4 Playback" }, | ||
774 | { "DPGA1R Mixer", "RX6 Playback Switch", "RX6 Playback" }, | ||
775 | |||
776 | { "DPGA1L", NULL, "DPGA1L Mixer" }, | ||
777 | { "DPGA1R", NULL, "DPGA1R Mixer" }, | ||
778 | |||
779 | { "DAC1L", NULL, "DPGA1L" }, | ||
780 | { "DAC1R", NULL, "DPGA1R" }, | ||
781 | |||
782 | { "DPGA2L Mixer", "RX1 Playback Switch", "RX1 Playback" }, | ||
783 | { "DPGA2L Mixer", "RX2 Playback Switch", "RX2 Playback" }, | ||
784 | { "DPGA2L Mixer", "RX3 Playback Switch", "RX3 Playback" }, | ||
785 | { "DPGA2L Mixer", "RX4 Playback Switch", "RX4 Playback" }, | ||
786 | { "DPGA2L Mixer", "RX5 Playback Switch", "RX5 Playback" }, | ||
787 | { "DPGA2L Mixer", "RX6 Playback Switch", "RX6 Playback" }, | ||
788 | |||
789 | { "DPGA2R Mixer", "RX2 Playback Switch", "RX2 Playback" }, | ||
790 | { "DPGA2R Mixer", "RX4 Playback Switch", "RX4 Playback" }, | ||
791 | { "DPGA2R Mixer", "RX6 Playback Switch", "RX6 Playback" }, | ||
792 | |||
793 | { "DPGA2L", NULL, "DPGA2L Mixer" }, | ||
794 | { "DPGA2R", NULL, "DPGA2R Mixer" }, | ||
795 | |||
796 | { "DAC2L", NULL, "DPGA2L" }, | ||
797 | { "DAC2R", NULL, "DPGA2R" }, | ||
798 | |||
799 | { "DPGA3L Mixer", "RX1 Playback Switch", "RX1 Playback" }, | ||
800 | { "DPGA3L Mixer", "RX3 Playback Switch", "RX3 Playback" }, | ||
801 | { "DPGA3L Mixer", "RX5 Playback Switch", "RX5 Playback" }, | ||
802 | |||
803 | { "DPGA3R Mixer", "RX2 Playback Switch", "RX2 Playback" }, | ||
804 | { "DPGA3R Mixer", "RX4 Playback Switch", "RX4 Playback" }, | ||
805 | { "DPGA3R Mixer", "RX6 Playback Switch", "RX6 Playback" }, | ||
806 | |||
807 | { "DPGA3L", NULL, "DPGA3L Mixer" }, | ||
808 | { "DPGA3R", NULL, "DPGA3R Mixer" }, | ||
809 | |||
810 | { "DAC3L", NULL, "DPGA3L" }, | ||
811 | { "DAC3R", NULL, "DPGA3R" }, | ||
812 | |||
813 | { "Headset Left Mixer", "DAC1L Playback Switch", "DAC1L" }, | ||
814 | { "Headset Left Mixer", "APGA1 Playback Switch", "APGA1" }, | ||
815 | |||
816 | { "Headset Right Mixer", "DAC1R Playback Switch", "DAC1R" }, | ||
817 | { "Headset Right Mixer", "APGA2 Playback Switch", "APGA2" }, | ||
818 | |||
819 | { "HS Left Driver", NULL, "Headset Left Mixer" }, | ||
820 | { "HS Right Driver", NULL, "Headset Right Mixer" }, | ||
821 | |||
822 | { "HSOL", NULL, "HS Left Driver" }, | ||
823 | { "HSOR", NULL, "HS Right Driver" }, | ||
824 | |||
825 | /* Earphone playback path */ | ||
826 | { "Earphone Mixer", "DAC2L Playback Switch", "DAC2L" }, | ||
827 | { "Earphone Mixer", "APGA1 Playback Switch", "APGA1" }, | ||
828 | |||
829 | { "Earphone Playback", "Switch", "Earphone Mixer" }, | ||
830 | { "Earphone Driver", NULL, "Earphone Playback" }, | ||
831 | { "EP", NULL, "Earphone Driver" }, | ||
832 | |||
833 | { "Handsfree Left Mixer", "DAC2L Playback Switch", "DAC2L" }, | ||
834 | { "Handsfree Left Mixer", "APGA1 Playback Switch", "APGA1" }, | ||
835 | |||
836 | { "Handsfree Right Mixer", "DAC2R Playback Switch", "DAC2R" }, | ||
837 | { "Handsfree Right Mixer", "APGA2 Playback Switch", "APGA2" }, | ||
838 | |||
839 | { "HF Left PGA", NULL, "Handsfree Left Mixer" }, | ||
840 | { "HF Right PGA", NULL, "Handsfree Right Mixer" }, | ||
841 | |||
842 | { "HF Left Driver", NULL, "HF Left PGA" }, | ||
843 | { "HF Right Driver", NULL, "HF Right PGA" }, | ||
844 | |||
845 | { "HFL", NULL, "HF Left Driver" }, | ||
846 | { "HFR", NULL, "HF Right Driver" }, | ||
847 | |||
848 | { "LINEOUT1 Mixer", "DAC3L Playback Switch", "DAC3L" }, | ||
849 | { "LINEOUT1 Mixer", "APGA1 Playback Switch", "APGA1" }, | ||
850 | |||
851 | { "LINEOUT2 Mixer", "DAC3R Playback Switch", "DAC3R" }, | ||
852 | { "LINEOUT2 Mixer", "APGA2 Playback Switch", "APGA2" }, | ||
853 | |||
854 | { "LINEOUT1 Driver", NULL, "LINEOUT1 Mixer" }, | ||
855 | { "LINEOUT2 Driver", NULL, "LINEOUT2 Mixer" }, | ||
856 | |||
857 | { "LINEOUT1", NULL, "LINEOUT1 Driver" }, | ||
858 | { "LINEOUT2", NULL, "LINEOUT2 Driver" }, | ||
859 | }; | ||
860 | |||
861 | static int isabelle_hs_mute(struct snd_soc_dai *dai, int mute) | ||
862 | { | ||
863 | snd_soc_update_bits(dai->codec, ISABELLE_DAC1_SOFTRAMP_REG, | ||
864 | BIT(4), (mute ? BIT(4) : 0)); | ||
865 | |||
866 | return 0; | ||
867 | } | ||
868 | |||
869 | static int isabelle_hf_mute(struct snd_soc_dai *dai, int mute) | ||
870 | { | ||
871 | snd_soc_update_bits(dai->codec, ISABELLE_DAC2_SOFTRAMP_REG, | ||
872 | BIT(4), (mute ? BIT(4) : 0)); | ||
873 | |||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | static int isabelle_line_mute(struct snd_soc_dai *dai, int mute) | ||
878 | { | ||
879 | snd_soc_update_bits(dai->codec, ISABELLE_DAC3_SOFTRAMP_REG, | ||
880 | BIT(4), (mute ? BIT(4) : 0)); | ||
881 | |||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | static int isabelle_set_bias_level(struct snd_soc_codec *codec, | ||
886 | enum snd_soc_bias_level level) | ||
887 | { | ||
888 | switch (level) { | ||
889 | case SND_SOC_BIAS_ON: | ||
890 | break; | ||
891 | case SND_SOC_BIAS_PREPARE: | ||
892 | break; | ||
893 | |||
894 | case SND_SOC_BIAS_STANDBY: | ||
895 | snd_soc_update_bits(codec, ISABELLE_PWR_EN_REG, | ||
896 | ISABELLE_CHIP_EN, BIT(0)); | ||
897 | break; | ||
898 | |||
899 | case SND_SOC_BIAS_OFF: | ||
900 | snd_soc_update_bits(codec, ISABELLE_PWR_EN_REG, | ||
901 | ISABELLE_CHIP_EN, 0); | ||
902 | break; | ||
903 | } | ||
904 | |||
905 | codec->dapm.bias_level = level; | ||
906 | |||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | static int isabelle_hw_params(struct snd_pcm_substream *substream, | ||
911 | struct snd_pcm_hw_params *params, | ||
912 | struct snd_soc_dai *dai) | ||
913 | { | ||
914 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
915 | struct snd_soc_codec *codec = rtd->codec; | ||
916 | u16 aif = 0; | ||
917 | unsigned int fs_val = 0; | ||
918 | |||
919 | switch (params_rate(params)) { | ||
920 | case 8000: | ||
921 | fs_val = ISABELLE_FS_RATE_8; | ||
922 | break; | ||
923 | case 11025: | ||
924 | fs_val = ISABELLE_FS_RATE_11; | ||
925 | break; | ||
926 | case 12000: | ||
927 | fs_val = ISABELLE_FS_RATE_12; | ||
928 | break; | ||
929 | case 16000: | ||
930 | fs_val = ISABELLE_FS_RATE_16; | ||
931 | break; | ||
932 | case 22050: | ||
933 | fs_val = ISABELLE_FS_RATE_22; | ||
934 | break; | ||
935 | case 24000: | ||
936 | fs_val = ISABELLE_FS_RATE_24; | ||
937 | break; | ||
938 | case 32000: | ||
939 | fs_val = ISABELLE_FS_RATE_32; | ||
940 | break; | ||
941 | case 44100: | ||
942 | fs_val = ISABELLE_FS_RATE_44; | ||
943 | break; | ||
944 | case 48000: | ||
945 | fs_val = ISABELLE_FS_RATE_48; | ||
946 | break; | ||
947 | default: | ||
948 | return -EINVAL; | ||
949 | } | ||
950 | |||
951 | snd_soc_update_bits(codec, ISABELLE_FS_RATE_CFG_REG, | ||
952 | ISABELLE_FS_RATE_MASK, fs_val); | ||
953 | |||
954 | /* bit size */ | ||
955 | switch (params_format(params)) { | ||
956 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
957 | aif |= ISABELLE_AIF_LENGTH_20; | ||
958 | break; | ||
959 | case SNDRV_PCM_FORMAT_S32_LE: | ||
960 | aif |= ISABELLE_AIF_LENGTH_32; | ||
961 | break; | ||
962 | default: | ||
963 | return -EINVAL; | ||
964 | } | ||
965 | |||
966 | snd_soc_update_bits(codec, ISABELLE_INTF_CFG_REG, | ||
967 | ISABELLE_AIF_LENGTH_MASK, aif); | ||
968 | |||
969 | return 0; | ||
970 | } | ||
971 | |||
972 | static int isabelle_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
973 | { | ||
974 | struct snd_soc_codec *codec = codec_dai->codec; | ||
975 | unsigned int aif_val = 0; | ||
976 | |||
977 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
978 | case SND_SOC_DAIFMT_CBS_CFS: | ||
979 | aif_val &= ~ISABELLE_AIF_MS; | ||
980 | break; | ||
981 | case SND_SOC_DAIFMT_CBM_CFM: | ||
982 | aif_val |= ISABELLE_AIF_MS; | ||
983 | break; | ||
984 | default: | ||
985 | return -EINVAL; | ||
986 | } | ||
987 | |||
988 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
989 | case SND_SOC_DAIFMT_I2S: | ||
990 | aif_val |= ISABELLE_I2S_MODE; | ||
991 | break; | ||
992 | case SND_SOC_DAIFMT_LEFT_J: | ||
993 | aif_val |= ISABELLE_LEFT_J_MODE; | ||
994 | break; | ||
995 | case SND_SOC_DAIFMT_PDM: | ||
996 | aif_val |= ISABELLE_PDM_MODE; | ||
997 | break; | ||
998 | default: | ||
999 | return -EINVAL; | ||
1000 | } | ||
1001 | |||
1002 | snd_soc_update_bits(codec, ISABELLE_INTF_CFG_REG, | ||
1003 | (ISABELLE_AIF_MS | ISABELLE_AIF_FMT_MASK), aif_val); | ||
1004 | |||
1005 | return 0; | ||
1006 | } | ||
1007 | |||
1008 | /* Rates supported by Isabelle driver */ | ||
1009 | #define ISABELLE_RATES SNDRV_PCM_RATE_8000_48000 | ||
1010 | |||
1011 | /* Formates supported by Isabelle driver. */ | ||
1012 | #define ISABELLE_FORMATS (SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
1013 | SNDRV_PCM_FMTBIT_S32_LE) | ||
1014 | |||
1015 | static struct snd_soc_dai_ops isabelle_hs_dai_ops = { | ||
1016 | .hw_params = isabelle_hw_params, | ||
1017 | .set_fmt = isabelle_set_dai_fmt, | ||
1018 | .digital_mute = isabelle_hs_mute, | ||
1019 | }; | ||
1020 | |||
1021 | static struct snd_soc_dai_ops isabelle_hf_dai_ops = { | ||
1022 | .hw_params = isabelle_hw_params, | ||
1023 | .set_fmt = isabelle_set_dai_fmt, | ||
1024 | .digital_mute = isabelle_hf_mute, | ||
1025 | }; | ||
1026 | |||
1027 | static struct snd_soc_dai_ops isabelle_line_dai_ops = { | ||
1028 | .hw_params = isabelle_hw_params, | ||
1029 | .set_fmt = isabelle_set_dai_fmt, | ||
1030 | .digital_mute = isabelle_line_mute, | ||
1031 | }; | ||
1032 | |||
1033 | static struct snd_soc_dai_ops isabelle_ul_dai_ops = { | ||
1034 | .hw_params = isabelle_hw_params, | ||
1035 | .set_fmt = isabelle_set_dai_fmt, | ||
1036 | }; | ||
1037 | |||
1038 | /* ISABELLE dai structure */ | ||
1039 | static struct snd_soc_dai_driver isabelle_dai[] = { | ||
1040 | { | ||
1041 | .name = "isabelle-dl1", | ||
1042 | .playback = { | ||
1043 | .stream_name = "Headset Playback", | ||
1044 | .channels_min = 1, | ||
1045 | .channels_max = 2, | ||
1046 | .rates = ISABELLE_RATES, | ||
1047 | .formats = ISABELLE_FORMATS, | ||
1048 | }, | ||
1049 | .ops = &isabelle_hs_dai_ops, | ||
1050 | }, | ||
1051 | { | ||
1052 | .name = "isabelle-dl2", | ||
1053 | .playback = { | ||
1054 | .stream_name = "Handsfree Playback", | ||
1055 | .channels_min = 1, | ||
1056 | .channels_max = 2, | ||
1057 | .rates = ISABELLE_RATES, | ||
1058 | .formats = ISABELLE_FORMATS, | ||
1059 | }, | ||
1060 | .ops = &isabelle_hf_dai_ops, | ||
1061 | }, | ||
1062 | { | ||
1063 | .name = "isabelle-lineout", | ||
1064 | .playback = { | ||
1065 | .stream_name = "Lineout Playback", | ||
1066 | .channels_min = 1, | ||
1067 | .channels_max = 2, | ||
1068 | .rates = ISABELLE_RATES, | ||
1069 | .formats = ISABELLE_FORMATS, | ||
1070 | }, | ||
1071 | .ops = &isabelle_line_dai_ops, | ||
1072 | }, | ||
1073 | { | ||
1074 | .name = "isabelle-ul", | ||
1075 | .capture = { | ||
1076 | .stream_name = "Capture", | ||
1077 | .channels_min = 1, | ||
1078 | .channels_max = 2, | ||
1079 | .rates = ISABELLE_RATES, | ||
1080 | .formats = ISABELLE_FORMATS, | ||
1081 | }, | ||
1082 | .ops = &isabelle_ul_dai_ops, | ||
1083 | }, | ||
1084 | }; | ||
1085 | |||
1086 | static int isabelle_probe(struct snd_soc_codec *codec) | ||
1087 | { | ||
1088 | int ret = 0; | ||
1089 | |||
1090 | codec->control_data = dev_get_regmap(codec->dev, NULL); | ||
1091 | |||
1092 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
1093 | if (ret < 0) { | ||
1094 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1095 | return ret; | ||
1096 | } | ||
1097 | |||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | static struct snd_soc_codec_driver soc_codec_dev_isabelle = { | ||
1102 | .probe = isabelle_probe, | ||
1103 | .set_bias_level = isabelle_set_bias_level, | ||
1104 | .controls = isabelle_snd_controls, | ||
1105 | .num_controls = ARRAY_SIZE(isabelle_snd_controls), | ||
1106 | .dapm_widgets = isabelle_dapm_widgets, | ||
1107 | .num_dapm_widgets = ARRAY_SIZE(isabelle_dapm_widgets), | ||
1108 | .dapm_routes = isabelle_intercon, | ||
1109 | .num_dapm_routes = ARRAY_SIZE(isabelle_intercon), | ||
1110 | .idle_bias_off = true, | ||
1111 | }; | ||
1112 | |||
1113 | static const struct regmap_config isabelle_regmap_config = { | ||
1114 | .reg_bits = 8, | ||
1115 | .val_bits = 8, | ||
1116 | |||
1117 | .max_register = ISABELLE_MAX_REGISTER, | ||
1118 | .reg_defaults = isabelle_reg_defs, | ||
1119 | .num_reg_defaults = ARRAY_SIZE(isabelle_reg_defs), | ||
1120 | .cache_type = REGCACHE_RBTREE, | ||
1121 | }; | ||
1122 | |||
1123 | static int __devinit isabelle_i2c_probe(struct i2c_client *i2c, | ||
1124 | const struct i2c_device_id *id) | ||
1125 | { | ||
1126 | struct regmap *isabelle_regmap; | ||
1127 | int ret = 0; | ||
1128 | |||
1129 | isabelle_regmap = devm_regmap_init_i2c(i2c, &isabelle_regmap_config); | ||
1130 | if (IS_ERR(isabelle_regmap)) { | ||
1131 | ret = PTR_ERR(isabelle_regmap); | ||
1132 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
1133 | ret); | ||
1134 | return ret; | ||
1135 | } | ||
1136 | i2c_set_clientdata(i2c, isabelle_regmap); | ||
1137 | |||
1138 | ret = snd_soc_register_codec(&i2c->dev, | ||
1139 | &soc_codec_dev_isabelle, isabelle_dai, | ||
1140 | ARRAY_SIZE(isabelle_dai)); | ||
1141 | if (ret < 0) { | ||
1142 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); | ||
1143 | return ret; | ||
1144 | } | ||
1145 | |||
1146 | return ret; | ||
1147 | } | ||
1148 | |||
1149 | static int __devexit isabelle_i2c_remove(struct i2c_client *client) | ||
1150 | { | ||
1151 | snd_soc_unregister_codec(&client->dev); | ||
1152 | return 0; | ||
1153 | } | ||
1154 | |||
1155 | static const struct i2c_device_id isabelle_i2c_id[] = { | ||
1156 | { "isabelle", 0 }, | ||
1157 | { } | ||
1158 | }; | ||
1159 | MODULE_DEVICE_TABLE(i2c, isabelle_i2c_id); | ||
1160 | |||
1161 | static struct i2c_driver isabelle_i2c_driver = { | ||
1162 | .driver = { | ||
1163 | .name = "isabelle", | ||
1164 | .owner = THIS_MODULE, | ||
1165 | }, | ||
1166 | .probe = isabelle_i2c_probe, | ||
1167 | .remove = __devexit_p(isabelle_i2c_remove), | ||
1168 | .id_table = isabelle_i2c_id, | ||
1169 | }; | ||
1170 | |||
1171 | module_i2c_driver(isabelle_i2c_driver); | ||
1172 | |||
1173 | MODULE_DESCRIPTION("ASoC ISABELLE driver"); | ||
1174 | MODULE_AUTHOR("Vishwas A Deshpande <vishwas.a.deshpande@ti.com>"); | ||
1175 | MODULE_AUTHOR("M R Swami Reddy <MR.Swami.Reddy@ti.com>"); | ||
1176 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/isabelle.h b/sound/soc/codecs/isabelle.h new file mode 100644 index 000000000000..96d839a8c956 --- /dev/null +++ b/sound/soc/codecs/isabelle.h | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * isabelle.h - Low power high fidelity audio codec driver header file | ||
3 | * | ||
4 | * Copyright (c) 2012 Texas Instruments, 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 as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef _ISABELLE_H | ||
13 | #define _ISABELLE_H | ||
14 | |||
15 | #include <linux/bitops.h> | ||
16 | |||
17 | /* ISABELLE REGISTERS */ | ||
18 | |||
19 | #define ISABELLE_PWR_CFG_REG 0x01 | ||
20 | #define ISABELLE_PWR_EN_REG 0x02 | ||
21 | #define ISABELLE_PS_EN1_REG 0x03 | ||
22 | #define ISABELLE_INT1_STATUS_REG 0x04 | ||
23 | #define ISABELLE_INT1_MASK_REG 0x05 | ||
24 | #define ISABELLE_INT2_STATUS_REG 0x06 | ||
25 | #define ISABELLE_INT2_MASK_REG 0x07 | ||
26 | #define ISABELLE_HKCTL1_REG 0x08 | ||
27 | #define ISABELLE_HKCTL2_REG 0x09 | ||
28 | #define ISABELLE_HKCTL3_REG 0x0A | ||
29 | #define ISABELLE_ACCDET_STATUS_REG 0x0B | ||
30 | #define ISABELLE_BUTTON_ID_REG 0x0C | ||
31 | #define ISABELLE_PLL_CFG_REG 0x10 | ||
32 | #define ISABELLE_PLL_EN_REG 0x11 | ||
33 | #define ISABELLE_FS_RATE_CFG_REG 0x12 | ||
34 | #define ISABELLE_INTF_CFG_REG 0x13 | ||
35 | #define ISABELLE_INTF_EN_REG 0x14 | ||
36 | #define ISABELLE_ULATX12_INTF_CFG_REG 0x15 | ||
37 | #define ISABELLE_DL12_INTF_CFG_REG 0x16 | ||
38 | #define ISABELLE_DL34_INTF_CFG_REG 0x17 | ||
39 | #define ISABELLE_DL56_INTF_CFG_REG 0x18 | ||
40 | #define ISABELLE_ATX_STPGA1_CFG_REG 0x19 | ||
41 | #define ISABELLE_ATX_STPGA2_CFG_REG 0x1A | ||
42 | #define ISABELLE_VTX_STPGA1_CFG_REG 0x1B | ||
43 | #define ISABELLE_VTX2_STPGA2_CFG_REG 0x1C | ||
44 | #define ISABELLE_ATX1_DPGA_REG 0x1D | ||
45 | #define ISABELLE_ATX2_DPGA_REG 0x1E | ||
46 | #define ISABELLE_VTX1_DPGA_REG 0x1F | ||
47 | #define ISABELLE_VTX2_DPGA_REG 0x20 | ||
48 | #define ISABELLE_TX_INPUT_CFG_REG 0x21 | ||
49 | #define ISABELLE_RX_INPUT_CFG_REG 0x22 | ||
50 | #define ISABELLE_RX_INPUT_CFG2_REG 0x23 | ||
51 | #define ISABELLE_VOICE_HPF_CFG_REG 0x24 | ||
52 | #define ISABELLE_AUDIO_HPF_CFG_REG 0x25 | ||
53 | #define ISABELLE_RX1_DPGA_REG 0x26 | ||
54 | #define ISABELLE_RX2_DPGA_REG 0x27 | ||
55 | #define ISABELLE_RX3_DPGA_REG 0x28 | ||
56 | #define ISABELLE_RX4_DPGA_REG 0x29 | ||
57 | #define ISABELLE_RX5_DPGA_REG 0x2A | ||
58 | #define ISABELLE_RX6_DPGA_REG 0x2B | ||
59 | #define ISABELLE_ALU_TX_EN_REG 0x2C | ||
60 | #define ISABELLE_ALU_RX_EN_REG 0x2D | ||
61 | #define ISABELLE_IIR_RESYNC_REG 0x2E | ||
62 | #define ISABELLE_ABIAS_CFG_REG 0x30 | ||
63 | #define ISABELLE_DBIAS_CFG_REG 0x31 | ||
64 | #define ISABELLE_MIC1_GAIN_REG 0x32 | ||
65 | #define ISABELLE_MIC2_GAIN_REG 0x33 | ||
66 | #define ISABELLE_AMIC_CFG_REG 0x34 | ||
67 | #define ISABELLE_DMIC_CFG_REG 0x35 | ||
68 | #define ISABELLE_APGA_GAIN_REG 0x36 | ||
69 | #define ISABELLE_APGA_CFG_REG 0x37 | ||
70 | #define ISABELLE_TX_GAIN_DLY_REG 0x38 | ||
71 | #define ISABELLE_RX_GAIN_DLY_REG 0x39 | ||
72 | #define ISABELLE_RX_PWR_CTRL_REG 0x3A | ||
73 | #define ISABELLE_DPGA1LR_IN_SEL_REG 0x3B | ||
74 | #define ISABELLE_DPGA1L_GAIN_REG 0x3C | ||
75 | #define ISABELLE_DPGA1R_GAIN_REG 0x3D | ||
76 | #define ISABELLE_DPGA2L_IN_SEL_REG 0x3E | ||
77 | #define ISABELLE_DPGA2R_IN_SEL_REG 0x3F | ||
78 | #define ISABELLE_DPGA2L_GAIN_REG 0x40 | ||
79 | #define ISABELLE_DPGA2R_GAIN_REG 0x41 | ||
80 | #define ISABELLE_DPGA3LR_IN_SEL_REG 0x42 | ||
81 | #define ISABELLE_DPGA3L_GAIN_REG 0x43 | ||
82 | #define ISABELLE_DPGA3R_GAIN_REG 0x44 | ||
83 | #define ISABELLE_DAC1_SOFTRAMP_REG 0x45 | ||
84 | #define ISABELLE_DAC2_SOFTRAMP_REG 0x46 | ||
85 | #define ISABELLE_DAC3_SOFTRAMP_REG 0x47 | ||
86 | #define ISABELLE_DAC_CFG_REG 0x48 | ||
87 | #define ISABELLE_EARDRV_CFG1_REG 0x49 | ||
88 | #define ISABELLE_EARDRV_CFG2_REG 0x4A | ||
89 | #define ISABELLE_HSDRV_GAIN_REG 0x4B | ||
90 | #define ISABELLE_HSDRV_CFG1_REG 0x4C | ||
91 | #define ISABELLE_HSDRV_CFG2_REG 0x4D | ||
92 | #define ISABELLE_HS_NG_CFG1_REG 0x4E | ||
93 | #define ISABELLE_HS_NG_CFG2_REG 0x4F | ||
94 | #define ISABELLE_LINEAMP_GAIN_REG 0x50 | ||
95 | #define ISABELLE_LINEAMP_CFG_REG 0x51 | ||
96 | #define ISABELLE_HFL_VOL_CTRL_REG 0x52 | ||
97 | #define ISABELLE_HFL_SFTVOL_CTRL_REG 0x53 | ||
98 | #define ISABELLE_HFL_LIM_CTRL_1_REG 0x54 | ||
99 | #define ISABELLE_HFL_LIM_CTRL_2_REG 0x55 | ||
100 | #define ISABELLE_HFR_VOL_CTRL_REG 0x56 | ||
101 | #define ISABELLE_HFR_SFTVOL_CTRL_REG 0x57 | ||
102 | #define ISABELLE_HFR_LIM_CTRL_1_REG 0x58 | ||
103 | #define ISABELLE_HFR_LIM_CTRL_2_REG 0x59 | ||
104 | #define ISABELLE_HF_MODE_REG 0x5A | ||
105 | #define ISABELLE_HFLPGA_CFG_REG 0x5B | ||
106 | #define ISABELLE_HFRPGA_CFG_REG 0x5C | ||
107 | #define ISABELLE_HFDRV_CFG_REG 0x5D | ||
108 | #define ISABELLE_PDMOUT_CFG1_REG 0x5E | ||
109 | #define ISABELLE_PDMOUT_CFG2_REG 0x5F | ||
110 | #define ISABELLE_PDMOUT_L_WM_REG 0x60 | ||
111 | #define ISABELLE_PDMOUT_R_WM_REG 0x61 | ||
112 | #define ISABELLE_HF_NG_CFG1_REG 0x62 | ||
113 | #define ISABELLE_HF_NG_CFG2_REG 0x63 | ||
114 | |||
115 | /* ISABELLE_PWR_EN_REG (0x02h) */ | ||
116 | #define ISABELLE_CHIP_EN BIT(0) | ||
117 | |||
118 | /* ISABELLE DAI FORMATS */ | ||
119 | #define ISABELLE_AIF_FMT_MASK 0x70 | ||
120 | #define ISABELLE_I2S_MODE 0x0 | ||
121 | #define ISABELLE_LEFT_J_MODE 0x1 | ||
122 | #define ISABELLE_PDM_MODE 0x2 | ||
123 | |||
124 | #define ISABELLE_AIF_LENGTH_MASK 0x30 | ||
125 | #define ISABELLE_AIF_LENGTH_20 0x00 | ||
126 | #define ISABELLE_AIF_LENGTH_32 0x10 | ||
127 | |||
128 | #define ISABELLE_AIF_MS 0x80 | ||
129 | |||
130 | #define ISABELLE_FS_RATE_MASK 0xF | ||
131 | #define ISABELLE_FS_RATE_8 0x0 | ||
132 | #define ISABELLE_FS_RATE_11 0x1 | ||
133 | #define ISABELLE_FS_RATE_12 0x2 | ||
134 | #define ISABELLE_FS_RATE_16 0x4 | ||
135 | #define ISABELLE_FS_RATE_22 0x5 | ||
136 | #define ISABELLE_FS_RATE_24 0x6 | ||
137 | #define ISABELLE_FS_RATE_32 0x8 | ||
138 | #define ISABELLE_FS_RATE_44 0x9 | ||
139 | #define ISABELLE_FS_RATE_48 0xA | ||
140 | |||
141 | #define ISABELLE_MAX_REGISTER 0xFF | ||
142 | |||
143 | #endif | ||
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index 802b9f176b16..99b0a9dcff34 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c | |||
@@ -12,7 +12,6 @@ | |||
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/moduleparam.h> | 14 | #include <linux/moduleparam.h> |
15 | #include <linux/version.h> | ||
16 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
17 | #include <linux/init.h> | 16 | #include <linux/init.h> |
18 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
@@ -1358,7 +1357,7 @@ static struct snd_soc_dai_ops lm49453_lineout_dai_ops = { | |||
1358 | }; | 1357 | }; |
1359 | 1358 | ||
1360 | /* LM49453 dai structure. */ | 1359 | /* LM49453 dai structure. */ |
1361 | static const struct snd_soc_dai_driver lm49453_dai[] = { | 1360 | static struct snd_soc_dai_driver lm49453_dai[] = { |
1362 | { | 1361 | { |
1363 | .name = "LM49453 Headset", | 1362 | .name = "LM49453 Headset", |
1364 | .playback = { | 1363 | .playback = { |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 35179e2c23c9..7cd508e16a5c 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c | |||
@@ -2216,7 +2216,7 @@ static irqreturn_t max98095_report_jack(int irq, void *data) | |||
2216 | return IRQ_HANDLED; | 2216 | return IRQ_HANDLED; |
2217 | } | 2217 | } |
2218 | 2218 | ||
2219 | int max98095_jack_detect_enable(struct snd_soc_codec *codec) | 2219 | static int max98095_jack_detect_enable(struct snd_soc_codec *codec) |
2220 | { | 2220 | { |
2221 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); | 2221 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); |
2222 | int ret = 0; | 2222 | int ret = 0; |
@@ -2245,7 +2245,7 @@ int max98095_jack_detect_enable(struct snd_soc_codec *codec) | |||
2245 | return ret; | 2245 | return ret; |
2246 | } | 2246 | } |
2247 | 2247 | ||
2248 | int max98095_jack_detect_disable(struct snd_soc_codec *codec) | 2248 | static int max98095_jack_detect_disable(struct snd_soc_codec *codec) |
2249 | { | 2249 | { |
2250 | int ret = 0; | 2250 | int ret = 0; |
2251 | 2251 | ||
@@ -2286,6 +2286,7 @@ int max98095_jack_detect(struct snd_soc_codec *codec, | |||
2286 | max98095_report_jack(client->irq, codec); | 2286 | max98095_report_jack(client->irq, codec); |
2287 | return 0; | 2287 | return 0; |
2288 | } | 2288 | } |
2289 | EXPORT_SYMBOL_GPL(max98095_jack_detect); | ||
2289 | 2290 | ||
2290 | #ifdef CONFIG_PM | 2291 | #ifdef CONFIG_PM |
2291 | static int max98095_suspend(struct snd_soc_codec *codec) | 2292 | static int max98095_suspend(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 22cb5bf59273..96aa5fa05160 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c | |||
@@ -638,7 +638,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c, | |||
638 | 638 | ||
639 | i2c_set_clientdata(i2c, priv); | 639 | i2c_set_clientdata(i2c, priv); |
640 | 640 | ||
641 | priv->regmap = regmap_init_i2c(i2c, &ml26124_i2c_regmap); | 641 | priv->regmap = devm_regmap_init_i2c(i2c, &ml26124_i2c_regmap); |
642 | if (IS_ERR(priv->regmap)) { | 642 | if (IS_ERR(priv->regmap)) { |
643 | ret = PTR_ERR(priv->regmap); | 643 | ret = PTR_ERR(priv->regmap); |
644 | dev_err(&i2c->dev, "regmap_init_i2c() failed: %d\n", ret); | 644 | dev_err(&i2c->dev, "regmap_init_i2c() failed: %d\n", ret); |
@@ -651,10 +651,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c, | |||
651 | 651 | ||
652 | static __devexit int ml26124_i2c_remove(struct i2c_client *client) | 652 | static __devexit int ml26124_i2c_remove(struct i2c_client *client) |
653 | { | 653 | { |
654 | struct ml26124_priv *priv = i2c_get_clientdata(client); | ||
655 | |||
656 | snd_soc_unregister_codec(&client->dev); | 654 | snd_soc_unregister_codec(&client->dev); |
657 | regmap_exit(priv->regmap); | ||
658 | return 0; | 655 | return 0; |
659 | } | 656 | } |
660 | 657 | ||
diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c new file mode 100644 index 000000000000..dd8d856053fc --- /dev/null +++ b/sound/soc/codecs/spdif_receiver.c | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * ALSA SoC SPDIF DIR (Digital Interface Reciever) driver | ||
3 | * | ||
4 | * Based on ALSA SoC SPDIF DIT driver | ||
5 | * | ||
6 | * This driver is used by controllers which can operate in DIR (SPDI/F) where | ||
7 | * no codec is needed. This file provides stub codec that can be used | ||
8 | * in these configurations. SPEAr SPDIF IN Audio controller uses this driver. | ||
9 | * | ||
10 | * Author: Vipin Kumar, <vipin.kumar@st.com> | ||
11 | * Copyright: (C) 2012 ST Microelectronics | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/initval.h> | ||
24 | |||
25 | #define STUB_RATES SNDRV_PCM_RATE_8000_192000 | ||
26 | #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
27 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) | ||
28 | |||
29 | static struct snd_soc_codec_driver soc_codec_spdif_dir; | ||
30 | |||
31 | static struct snd_soc_dai_driver dir_stub_dai = { | ||
32 | .name = "dir-hifi", | ||
33 | .capture = { | ||
34 | .stream_name = "Capture", | ||
35 | .channels_min = 1, | ||
36 | .channels_max = 384, | ||
37 | .rates = STUB_RATES, | ||
38 | .formats = STUB_FORMATS, | ||
39 | }, | ||
40 | }; | ||
41 | |||
42 | static int spdif_dir_probe(struct platform_device *pdev) | ||
43 | { | ||
44 | return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dir, | ||
45 | &dir_stub_dai, 1); | ||
46 | } | ||
47 | |||
48 | static int spdif_dir_remove(struct platform_device *pdev) | ||
49 | { | ||
50 | snd_soc_unregister_codec(&pdev->dev); | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | static struct platform_driver spdif_dir_driver = { | ||
55 | .probe = spdif_dir_probe, | ||
56 | .remove = spdif_dir_remove, | ||
57 | .driver = { | ||
58 | .name = "spdif-dir", | ||
59 | .owner = THIS_MODULE, | ||
60 | }, | ||
61 | }; | ||
62 | |||
63 | module_platform_driver(spdif_dir_driver); | ||
64 | |||
65 | MODULE_DESCRIPTION("ASoC SPDIF DIR driver"); | ||
66 | MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>"); | ||
67 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c new file mode 100644 index 000000000000..0c225cd569d2 --- /dev/null +++ b/sound/soc/codecs/sta529.c | |||
@@ -0,0 +1,442 @@ | |||
1 | /* | ||
2 | * ASoC codec driver for spear platform | ||
3 | * | ||
4 | * sound/soc/codecs/sta529.c -- spear ALSA Soc codec driver | ||
5 | * | ||
6 | * Copyright (C) 2012 ST Microelectronics | ||
7 | * Rajeev Kumar <rajeev-dlh.kumar@st.com> | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public | ||
10 | * License version 2. This program is licensed "as is" without any | ||
11 | * warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/clk.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/pm.h> | ||
21 | #include <linux/regmap.h> | ||
22 | #include <linux/slab.h> | ||
23 | |||
24 | #include <sound/core.h> | ||
25 | #include <sound/initval.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/pcm_params.h> | ||
28 | #include <sound/soc.h> | ||
29 | #include <sound/soc-dapm.h> | ||
30 | #include <sound/tlv.h> | ||
31 | |||
32 | /* STA529 Register offsets */ | ||
33 | #define STA529_FFXCFG0 0x00 | ||
34 | #define STA529_FFXCFG1 0x01 | ||
35 | #define STA529_MVOL 0x02 | ||
36 | #define STA529_LVOL 0x03 | ||
37 | #define STA529_RVOL 0x04 | ||
38 | #define STA529_TTF0 0x05 | ||
39 | #define STA529_TTF1 0x06 | ||
40 | #define STA529_TTP0 0x07 | ||
41 | #define STA529_TTP1 0x08 | ||
42 | #define STA529_S2PCFG0 0x0A | ||
43 | #define STA529_S2PCFG1 0x0B | ||
44 | #define STA529_P2SCFG0 0x0C | ||
45 | #define STA529_P2SCFG1 0x0D | ||
46 | #define STA529_PLLCFG0 0x14 | ||
47 | #define STA529_PLLCFG1 0x15 | ||
48 | #define STA529_PLLCFG2 0x16 | ||
49 | #define STA529_PLLCFG3 0x17 | ||
50 | #define STA529_PLLPFE 0x18 | ||
51 | #define STA529_PLLST 0x19 | ||
52 | #define STA529_ADCCFG 0x1E /*mic_select*/ | ||
53 | #define STA529_CKOCFG 0x1F | ||
54 | #define STA529_MISC 0x20 | ||
55 | #define STA529_PADST0 0x21 | ||
56 | #define STA529_PADST1 0x22 | ||
57 | #define STA529_FFXST 0x23 | ||
58 | #define STA529_PWMIN1 0x2D | ||
59 | #define STA529_PWMIN2 0x2E | ||
60 | #define STA529_POWST 0x32 | ||
61 | |||
62 | #define STA529_MAX_REGISTER 0x32 | ||
63 | |||
64 | #define STA529_RATES (SNDRV_PCM_RATE_8000 | \ | ||
65 | SNDRV_PCM_RATE_11025 | \ | ||
66 | SNDRV_PCM_RATE_16000 | \ | ||
67 | SNDRV_PCM_RATE_22050 | \ | ||
68 | SNDRV_PCM_RATE_32000 | \ | ||
69 | SNDRV_PCM_RATE_44100 | \ | ||
70 | SNDRV_PCM_RATE_48000) | ||
71 | |||
72 | #define STA529_FORMAT (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
73 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
74 | SNDRV_PCM_FMTBIT_S32_LE) | ||
75 | #define S2PC_VALUE 0x98 | ||
76 | #define CLOCK_OUT 0x60 | ||
77 | #define LEFT_J_DATA_FORMAT 0x10 | ||
78 | #define I2S_DATA_FORMAT 0x12 | ||
79 | #define RIGHT_J_DATA_FORMAT 0x14 | ||
80 | #define CODEC_MUTE_VAL 0x80 | ||
81 | |||
82 | #define POWER_CNTLMSAK 0x40 | ||
83 | #define POWER_STDBY 0x40 | ||
84 | #define FFX_MASK 0x80 | ||
85 | #define FFX_OFF 0x80 | ||
86 | #define POWER_UP 0x00 | ||
87 | #define FFX_CLK_ENB 0x01 | ||
88 | #define FFX_CLK_DIS 0x00 | ||
89 | #define FFX_CLK_MSK 0x01 | ||
90 | #define PLAY_FREQ_RANGE_MSK 0x70 | ||
91 | #define CAP_FREQ_RANGE_MSK 0x0C | ||
92 | #define PDATA_LEN_MSK 0xC0 | ||
93 | #define BCLK_TO_FS_MSK 0x30 | ||
94 | #define AUDIO_MUTE_MSK 0x80 | ||
95 | |||
96 | static const struct reg_default sta529_reg_defaults[] = { | ||
97 | { 0, 0x35 }, /* R0 - FFX Configuration reg 0 */ | ||
98 | { 1, 0xc8 }, /* R1 - FFX Configuration reg 1 */ | ||
99 | { 2, 0x50 }, /* R2 - Master Volume */ | ||
100 | { 3, 0x00 }, /* R3 - Left Volume */ | ||
101 | { 4, 0x00 }, /* R4 - Right Volume */ | ||
102 | { 10, 0xb2 }, /* R10 - S2P Config Reg 0 */ | ||
103 | { 11, 0x41 }, /* R11 - S2P Config Reg 1 */ | ||
104 | { 12, 0x92 }, /* R12 - P2S Config Reg 0 */ | ||
105 | { 13, 0x41 }, /* R13 - P2S Config Reg 1 */ | ||
106 | { 30, 0xd2 }, /* R30 - ADC Config Reg */ | ||
107 | { 31, 0x40 }, /* R31 - clock Out Reg */ | ||
108 | { 32, 0x21 }, /* R32 - Misc Register */ | ||
109 | }; | ||
110 | |||
111 | struct sta529 { | ||
112 | struct regmap *regmap; | ||
113 | }; | ||
114 | |||
115 | static bool sta529_readable(struct device *dev, unsigned int reg) | ||
116 | { | ||
117 | switch (reg) { | ||
118 | |||
119 | case STA529_FFXCFG0: | ||
120 | case STA529_FFXCFG1: | ||
121 | case STA529_MVOL: | ||
122 | case STA529_LVOL: | ||
123 | case STA529_RVOL: | ||
124 | case STA529_S2PCFG0: | ||
125 | case STA529_S2PCFG1: | ||
126 | case STA529_P2SCFG0: | ||
127 | case STA529_P2SCFG1: | ||
128 | case STA529_ADCCFG: | ||
129 | case STA529_CKOCFG: | ||
130 | case STA529_MISC: | ||
131 | return true; | ||
132 | default: | ||
133 | return false; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | |||
138 | static const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary", | ||
139 | "Phase-shift"}; | ||
140 | |||
141 | static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0); | ||
142 | static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0); | ||
143 | static const SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text); | ||
144 | |||
145 | static const struct snd_kcontrol_new sta529_snd_controls[] = { | ||
146 | SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0, | ||
147 | 127, 0, out_gain_tlv), | ||
148 | SOC_SINGLE_TLV("Master Playback Volume", STA529_MVOL, 0, 127, 1, | ||
149 | master_vol_tlv), | ||
150 | SOC_ENUM("PWM Select", pwm_src), | ||
151 | }; | ||
152 | |||
153 | static int sta529_set_bias_level(struct snd_soc_codec *codec, enum | ||
154 | snd_soc_bias_level level) | ||
155 | { | ||
156 | struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec); | ||
157 | |||
158 | switch (level) { | ||
159 | case SND_SOC_BIAS_ON: | ||
160 | case SND_SOC_BIAS_PREPARE: | ||
161 | snd_soc_update_bits(codec, STA529_FFXCFG0, POWER_CNTLMSAK, | ||
162 | POWER_UP); | ||
163 | snd_soc_update_bits(codec, STA529_MISC, FFX_CLK_MSK, | ||
164 | FFX_CLK_ENB); | ||
165 | break; | ||
166 | case SND_SOC_BIAS_STANDBY: | ||
167 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | ||
168 | regcache_sync(sta529->regmap); | ||
169 | snd_soc_update_bits(codec, STA529_FFXCFG0, | ||
170 | POWER_CNTLMSAK, POWER_STDBY); | ||
171 | /* Making FFX output to zero */ | ||
172 | snd_soc_update_bits(codec, STA529_FFXCFG0, FFX_MASK, | ||
173 | FFX_OFF); | ||
174 | snd_soc_update_bits(codec, STA529_MISC, FFX_CLK_MSK, | ||
175 | FFX_CLK_DIS); | ||
176 | break; | ||
177 | case SND_SOC_BIAS_OFF: | ||
178 | break; | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * store the label for powers down audio subsystem for suspend.This is | ||
183 | * used by soc core layer | ||
184 | */ | ||
185 | codec->dapm.bias_level = level; | ||
186 | |||
187 | return 0; | ||
188 | |||
189 | } | ||
190 | |||
191 | static int sta529_hw_params(struct snd_pcm_substream *substream, | ||
192 | struct snd_pcm_hw_params *params, | ||
193 | struct snd_soc_dai *dai) | ||
194 | { | ||
195 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
196 | struct snd_soc_codec *codec = rtd->codec; | ||
197 | int pdata, play_freq_val, record_freq_val; | ||
198 | int bclk_to_fs_ratio; | ||
199 | |||
200 | switch (params_format(params)) { | ||
201 | case SNDRV_PCM_FORMAT_S16_LE: | ||
202 | pdata = 1; | ||
203 | bclk_to_fs_ratio = 0; | ||
204 | break; | ||
205 | case SNDRV_PCM_FORMAT_S24_LE: | ||
206 | pdata = 2; | ||
207 | bclk_to_fs_ratio = 1; | ||
208 | break; | ||
209 | case SNDRV_PCM_FORMAT_S32_LE: | ||
210 | pdata = 3; | ||
211 | bclk_to_fs_ratio = 2; | ||
212 | break; | ||
213 | default: | ||
214 | dev_err(codec->dev, "Unsupported format\n"); | ||
215 | return -EINVAL; | ||
216 | } | ||
217 | |||
218 | switch (params_rate(params)) { | ||
219 | case 8000: | ||
220 | case 11025: | ||
221 | play_freq_val = 0; | ||
222 | record_freq_val = 2; | ||
223 | break; | ||
224 | case 16000: | ||
225 | case 22050: | ||
226 | play_freq_val = 1; | ||
227 | record_freq_val = 0; | ||
228 | break; | ||
229 | |||
230 | case 32000: | ||
231 | case 44100: | ||
232 | case 48000: | ||
233 | play_freq_val = 2; | ||
234 | record_freq_val = 0; | ||
235 | break; | ||
236 | default: | ||
237 | dev_err(codec->dev, "Unsupported rate\n"); | ||
238 | return -EINVAL; | ||
239 | } | ||
240 | |||
241 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
242 | snd_soc_update_bits(codec, STA529_S2PCFG1, PDATA_LEN_MSK, | ||
243 | pdata << 6); | ||
244 | snd_soc_update_bits(codec, STA529_S2PCFG1, BCLK_TO_FS_MSK, | ||
245 | bclk_to_fs_ratio << 4); | ||
246 | snd_soc_update_bits(codec, STA529_MISC, PLAY_FREQ_RANGE_MSK, | ||
247 | play_freq_val << 4); | ||
248 | } else { | ||
249 | snd_soc_update_bits(codec, STA529_P2SCFG1, PDATA_LEN_MSK, | ||
250 | pdata << 6); | ||
251 | snd_soc_update_bits(codec, STA529_P2SCFG1, BCLK_TO_FS_MSK, | ||
252 | bclk_to_fs_ratio << 4); | ||
253 | snd_soc_update_bits(codec, STA529_MISC, CAP_FREQ_RANGE_MSK, | ||
254 | record_freq_val << 2); | ||
255 | } | ||
256 | |||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int sta529_mute(struct snd_soc_dai *dai, int mute) | ||
261 | { | ||
262 | u8 val = 0; | ||
263 | |||
264 | if (mute) | ||
265 | val |= CODEC_MUTE_VAL; | ||
266 | |||
267 | snd_soc_update_bits(dai->codec, STA529_FFXCFG0, AUDIO_MUTE_MSK, val); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) | ||
273 | { | ||
274 | struct snd_soc_codec *codec = codec_dai->codec; | ||
275 | u8 mode = 0; | ||
276 | |||
277 | /* interface format */ | ||
278 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
279 | case SND_SOC_DAIFMT_LEFT_J: | ||
280 | mode = LEFT_J_DATA_FORMAT; | ||
281 | break; | ||
282 | case SND_SOC_DAIFMT_I2S: | ||
283 | mode = I2S_DATA_FORMAT; | ||
284 | break; | ||
285 | case SND_SOC_DAIFMT_RIGHT_J: | ||
286 | mode = RIGHT_J_DATA_FORMAT; | ||
287 | break; | ||
288 | default: | ||
289 | return -EINVAL; | ||
290 | } | ||
291 | |||
292 | snd_soc_update_bits(codec, STA529_S2PCFG0, 0x0D, mode); | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static const struct snd_soc_dai_ops sta529_dai_ops = { | ||
298 | .hw_params = sta529_hw_params, | ||
299 | .set_fmt = sta529_set_dai_fmt, | ||
300 | .digital_mute = sta529_mute, | ||
301 | }; | ||
302 | |||
303 | static struct snd_soc_dai_driver sta529_dai = { | ||
304 | .name = "sta529-audio", | ||
305 | .playback = { | ||
306 | .stream_name = "Playback", | ||
307 | .channels_min = 2, | ||
308 | .channels_max = 2, | ||
309 | .rates = STA529_RATES, | ||
310 | .formats = STA529_FORMAT, | ||
311 | }, | ||
312 | .capture = { | ||
313 | .stream_name = "Capture", | ||
314 | .channels_min = 2, | ||
315 | .channels_max = 2, | ||
316 | .rates = STA529_RATES, | ||
317 | .formats = STA529_FORMAT, | ||
318 | }, | ||
319 | .ops = &sta529_dai_ops, | ||
320 | }; | ||
321 | |||
322 | static int sta529_probe(struct snd_soc_codec *codec) | ||
323 | { | ||
324 | struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec); | ||
325 | int ret; | ||
326 | |||
327 | codec->control_data = sta529->regmap; | ||
328 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
329 | |||
330 | if (ret < 0) { | ||
331 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
332 | return ret; | ||
333 | } | ||
334 | sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | /* power down chip */ | ||
340 | static int sta529_remove(struct snd_soc_codec *codec) | ||
341 | { | ||
342 | sta529_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static int sta529_suspend(struct snd_soc_codec *codec) | ||
348 | { | ||
349 | sta529_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static int sta529_resume(struct snd_soc_codec *codec) | ||
355 | { | ||
356 | sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | struct snd_soc_codec_driver sta529_codec_driver = { | ||
362 | .probe = sta529_probe, | ||
363 | .remove = sta529_remove, | ||
364 | .set_bias_level = sta529_set_bias_level, | ||
365 | .suspend = sta529_suspend, | ||
366 | .resume = sta529_resume, | ||
367 | .controls = sta529_snd_controls, | ||
368 | .num_controls = ARRAY_SIZE(sta529_snd_controls), | ||
369 | }; | ||
370 | |||
371 | static const struct regmap_config sta529_regmap = { | ||
372 | .reg_bits = 8, | ||
373 | .val_bits = 8, | ||
374 | |||
375 | .max_register = STA529_MAX_REGISTER, | ||
376 | .readable_reg = sta529_readable, | ||
377 | |||
378 | .cache_type = REGCACHE_RBTREE, | ||
379 | .reg_defaults = sta529_reg_defaults, | ||
380 | .num_reg_defaults = ARRAY_SIZE(sta529_reg_defaults), | ||
381 | }; | ||
382 | |||
383 | static __devinit int sta529_i2c_probe(struct i2c_client *i2c, | ||
384 | const struct i2c_device_id *id) | ||
385 | { | ||
386 | struct sta529 *sta529; | ||
387 | int ret; | ||
388 | |||
389 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
390 | return -EINVAL; | ||
391 | |||
392 | sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL); | ||
393 | if (sta529 == NULL) { | ||
394 | dev_err(&i2c->dev, "Can not allocate memory\n"); | ||
395 | return -ENOMEM; | ||
396 | } | ||
397 | |||
398 | sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap); | ||
399 | if (IS_ERR(sta529->regmap)) { | ||
400 | ret = PTR_ERR(sta529->regmap); | ||
401 | dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); | ||
402 | return ret; | ||
403 | } | ||
404 | |||
405 | i2c_set_clientdata(i2c, sta529); | ||
406 | |||
407 | ret = snd_soc_register_codec(&i2c->dev, | ||
408 | &sta529_codec_driver, &sta529_dai, 1); | ||
409 | if (ret != 0) | ||
410 | dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); | ||
411 | |||
412 | return ret; | ||
413 | } | ||
414 | |||
415 | static int __devexit sta529_i2c_remove(struct i2c_client *client) | ||
416 | { | ||
417 | snd_soc_unregister_codec(&client->dev); | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static const struct i2c_device_id sta529_i2c_id[] = { | ||
423 | { "sta529", 0 }, | ||
424 | { } | ||
425 | }; | ||
426 | MODULE_DEVICE_TABLE(i2c, sta529_i2c_id); | ||
427 | |||
428 | static struct i2c_driver sta529_i2c_driver = { | ||
429 | .driver = { | ||
430 | .name = "sta529", | ||
431 | .owner = THIS_MODULE, | ||
432 | }, | ||
433 | .probe = sta529_i2c_probe, | ||
434 | .remove = __devexit_p(sta529_i2c_remove), | ||
435 | .id_table = sta529_i2c_id, | ||
436 | }; | ||
437 | |||
438 | module_i2c_driver(sta529_i2c_driver); | ||
439 | |||
440 | MODULE_DESCRIPTION("ASoC STA529 codec driver"); | ||
441 | MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>"); | ||
442 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index e9b62b5ea637..dc78f5a4bcbf 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -118,7 +118,9 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = { | |||
118 | 0x00, 0x00, 0x00, 0x00, /* 88 */ | 118 | 0x00, 0x00, 0x00, 0x00, /* 88 */ |
119 | 0x00, 0x00, 0x00, 0x00, /* 92 */ | 119 | 0x00, 0x00, 0x00, 0x00, /* 92 */ |
120 | 0x00, 0x00, 0x00, 0x00, /* 96 */ | 120 | 0x00, 0x00, 0x00, 0x00, /* 96 */ |
121 | 0x00, 0x00, 0x02, /* 100 */ | 121 | 0x00, 0x00, 0x02, 0x00, /* 100 */ |
122 | 0x00, 0x00, 0x00, 0x00, /* 104 */ | ||
123 | 0x00, 0x00, /* 108 */ | ||
122 | }; | 124 | }; |
123 | 125 | ||
124 | #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ | 126 | #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ |
@@ -229,6 +231,25 @@ static const struct soc_enum aic3x_enum[] = { | |||
229 | SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf), | 231 | SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf), |
230 | }; | 232 | }; |
231 | 233 | ||
234 | static const char *aic3x_agc_level[] = | ||
235 | { "-5.5dB", "-8dB", "-10dB", "-12dB", "-14dB", "-17dB", "-20dB", "-24dB" }; | ||
236 | static const struct soc_enum aic3x_agc_level_enum[] = { | ||
237 | SOC_ENUM_SINGLE(LAGC_CTRL_A, 4, 8, aic3x_agc_level), | ||
238 | SOC_ENUM_SINGLE(RAGC_CTRL_A, 4, 8, aic3x_agc_level), | ||
239 | }; | ||
240 | |||
241 | static const char *aic3x_agc_attack[] = { "8ms", "11ms", "16ms", "20ms" }; | ||
242 | static const struct soc_enum aic3x_agc_attack_enum[] = { | ||
243 | SOC_ENUM_SINGLE(LAGC_CTRL_A, 2, 4, aic3x_agc_attack), | ||
244 | SOC_ENUM_SINGLE(RAGC_CTRL_A, 2, 4, aic3x_agc_attack), | ||
245 | }; | ||
246 | |||
247 | static const char *aic3x_agc_decay[] = { "100ms", "200ms", "400ms", "500ms" }; | ||
248 | static const struct soc_enum aic3x_agc_decay_enum[] = { | ||
249 | SOC_ENUM_SINGLE(LAGC_CTRL_A, 0, 4, aic3x_agc_decay), | ||
250 | SOC_ENUM_SINGLE(RAGC_CTRL_A, 0, 4, aic3x_agc_decay), | ||
251 | }; | ||
252 | |||
232 | /* | 253 | /* |
233 | * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps | 254 | * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps |
234 | */ | 255 | */ |
@@ -353,6 +374,15 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
353 | * adjust PGA to max value when ADC is on and will never go back. | 374 | * adjust PGA to max value when ADC is on and will never go back. |
354 | */ | 375 | */ |
355 | SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), | 376 | SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), |
377 | SOC_ENUM("Left AGC Target level", aic3x_agc_level_enum[0]), | ||
378 | SOC_ENUM("Right AGC Target level", aic3x_agc_level_enum[1]), | ||
379 | SOC_ENUM("Left AGC Attack time", aic3x_agc_attack_enum[0]), | ||
380 | SOC_ENUM("Right AGC Attack time", aic3x_agc_attack_enum[1]), | ||
381 | SOC_ENUM("Left AGC Decay time", aic3x_agc_decay_enum[0]), | ||
382 | SOC_ENUM("Right AGC Decay time", aic3x_agc_decay_enum[1]), | ||
383 | |||
384 | /* De-emphasis */ | ||
385 | SOC_DOUBLE("De-emphasis Switch", AIC3X_CODEC_DFILT_CTRL, 2, 0, 0x01, 0), | ||
356 | 386 | ||
357 | /* Input */ | 387 | /* Input */ |
358 | SOC_DOUBLE_R_TLV("PGA Capture Volume", LADC_VOL, RADC_VOL, | 388 | SOC_DOUBLE_R_TLV("PGA Capture Volume", LADC_VOL, RADC_VOL, |
@@ -368,7 +398,7 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
368 | static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0); | 398 | static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0); |
369 | 399 | ||
370 | static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl = | 400 | static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl = |
371 | SOC_DOUBLE_TLV("Class-D Amplifier Gain", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv); | 401 | SOC_DOUBLE_TLV("Class-D Playback Volume", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv); |
372 | 402 | ||
373 | /* Left DAC Mux */ | 403 | /* Left DAC Mux */ |
374 | static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = | 404 | static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = |
@@ -970,6 +1000,12 @@ static int aic3x_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
970 | struct snd_soc_codec *codec = codec_dai->codec; | 1000 | struct snd_soc_codec *codec = codec_dai->codec; |
971 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | 1001 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
972 | 1002 | ||
1003 | /* set clock on MCLK or GPIO2 or BCLK */ | ||
1004 | snd_soc_update_bits(codec, AIC3X_CLKGEN_CTRL_REG, PLLCLK_IN_MASK, | ||
1005 | clk_id << PLLCLK_IN_SHIFT); | ||
1006 | snd_soc_update_bits(codec, AIC3X_CLKGEN_CTRL_REG, CLKDIV_IN_MASK, | ||
1007 | clk_id << CLKDIV_IN_SHIFT); | ||
1008 | |||
973 | aic3x->sysclk = freq; | 1009 | aic3x->sysclk = freq; |
974 | return 0; | 1010 | return 0; |
975 | } | 1011 | } |
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 08c7f6685ff0..6db3c41b0163 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h | |||
@@ -13,7 +13,7 @@ | |||
13 | #define _AIC3X_H | 13 | #define _AIC3X_H |
14 | 14 | ||
15 | /* AIC3X register space */ | 15 | /* AIC3X register space */ |
16 | #define AIC3X_CACHEREGNUM 103 | 16 | #define AIC3X_CACHEREGNUM 110 |
17 | 17 | ||
18 | /* Page select register */ | 18 | /* Page select register */ |
19 | #define AIC3X_PAGE_SELECT 0 | 19 | #define AIC3X_PAGE_SELECT 0 |
@@ -74,6 +74,8 @@ | |||
74 | #define HPLCOM_CFG 37 | 74 | #define HPLCOM_CFG 37 |
75 | /* Right High Power Output control registers */ | 75 | /* Right High Power Output control registers */ |
76 | #define HPRCOM_CFG 38 | 76 | #define HPRCOM_CFG 38 |
77 | /* High Power Output Stage Control Register */ | ||
78 | #define HPOUT_SC 40 | ||
77 | /* DAC Output Switching control registers */ | 79 | /* DAC Output Switching control registers */ |
78 | #define DAC_LINE_MUX 41 | 80 | #define DAC_LINE_MUX 41 |
79 | /* High Power Output Driver Pop Reduction registers */ | 81 | /* High Power Output Driver Pop Reduction registers */ |
@@ -148,6 +150,17 @@ | |||
148 | #define AIC3X_GPIOB_REG 101 | 150 | #define AIC3X_GPIOB_REG 101 |
149 | /* Clock generation control register */ | 151 | /* Clock generation control register */ |
150 | #define AIC3X_CLKGEN_CTRL_REG 102 | 152 | #define AIC3X_CLKGEN_CTRL_REG 102 |
153 | /* New AGC registers */ | ||
154 | #define LAGCN_ATTACK 103 | ||
155 | #define LAGCN_DECAY 104 | ||
156 | #define RAGCN_ATTACK 105 | ||
157 | #define RAGCN_DECAY 106 | ||
158 | /* New Programmable ADC Digital Path and I2C Bus Condition Register */ | ||
159 | #define NEW_ADC_DIGITALPATH 107 | ||
160 | /* Passive Analog Signal Bypass Selection During Powerdown Register */ | ||
161 | #define PASSIVE_BYPASS 108 | ||
162 | /* DAC Quiescent Current Adjustment Register */ | ||
163 | #define DAC_ICC_ADJ 109 | ||
151 | 164 | ||
152 | /* Page select register bits */ | 165 | /* Page select register bits */ |
153 | #define PAGE0_SELECT 0 | 166 | #define PAGE0_SELECT 0 |
@@ -163,6 +176,10 @@ | |||
163 | #define DUAL_RATE_MODE ((1 << 5) | (1 << 6)) | 176 | #define DUAL_RATE_MODE ((1 << 5) | (1 << 6)) |
164 | #define LDAC2LCH (0x1 << 3) | 177 | #define LDAC2LCH (0x1 << 3) |
165 | #define RDAC2RCH (0x1 << 1) | 178 | #define RDAC2RCH (0x1 << 1) |
179 | #define LDAC2RCH (0x2 << 3) | ||
180 | #define RDAC2LCH (0x2 << 1) | ||
181 | #define LDAC2MONOMIX (0x3 << 3) | ||
182 | #define RDAC2MONOMIX (0x3 << 1) | ||
166 | 183 | ||
167 | /* PLL registers bitfields */ | 184 | /* PLL registers bitfields */ |
168 | #define PLLP_SHIFT 0 | 185 | #define PLLP_SHIFT 0 |
@@ -179,6 +196,14 @@ | |||
179 | #define PLL_CLKIN_SHIFT 4 | 196 | #define PLL_CLKIN_SHIFT 4 |
180 | #define MCLK_SOURCE 0x0 | 197 | #define MCLK_SOURCE 0x0 |
181 | #define PLL_CLKDIV_SHIFT 0 | 198 | #define PLL_CLKDIV_SHIFT 0 |
199 | #define PLLCLK_IN_MASK 0x30 | ||
200 | #define PLLCLK_IN_SHIFT 4 | ||
201 | #define CLKDIV_IN_MASK 0xc0 | ||
202 | #define CLKDIV_IN_SHIFT 6 | ||
203 | /* clock in source */ | ||
204 | #define CLKIN_MCLK 0 | ||
205 | #define CLKIN_GPIO2 1 | ||
206 | #define CLKIN_BCLK 2 | ||
182 | 207 | ||
183 | /* Software reset register bits */ | 208 | /* Software reset register bits */ |
184 | #define SOFT_RESET 0x80 | 209 | #define SOFT_RESET 0x80 |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index a36e9fcdf184..0ff1e70b7770 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -553,7 +553,7 @@ static const struct snd_kcontrol_new vibrar_mux_controls = | |||
553 | 553 | ||
554 | /* Headset power mode */ | 554 | /* Headset power mode */ |
555 | static const char *twl6040_power_mode_texts[] = { | 555 | static const char *twl6040_power_mode_texts[] = { |
556 | "Low-Power", "High-Perfomance", | 556 | "Low-Power", "High-Performance", |
557 | }; | 557 | }; |
558 | 558 | ||
559 | static const struct soc_enum twl6040_power_mode_enum = | 559 | static const struct soc_enum twl6040_power_mode_enum = |
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index e0b51e9f8b12..951d7b49476a 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c | |||
@@ -121,20 +121,23 @@ static const struct snd_soc_dai_ops wm1250_ev1_ops = { | |||
121 | .hw_params = wm1250_ev1_hw_params, | 121 | .hw_params = wm1250_ev1_hw_params, |
122 | }; | 122 | }; |
123 | 123 | ||
124 | #define WM1250_EV1_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ | ||
125 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_64000) | ||
126 | |||
124 | static struct snd_soc_dai_driver wm1250_ev1_dai = { | 127 | static struct snd_soc_dai_driver wm1250_ev1_dai = { |
125 | .name = "wm1250-ev1", | 128 | .name = "wm1250-ev1", |
126 | .playback = { | 129 | .playback = { |
127 | .stream_name = "Playback", | 130 | .stream_name = "Playback", |
128 | .channels_min = 1, | 131 | .channels_min = 1, |
129 | .channels_max = 2, | 132 | .channels_max = 2, |
130 | .rates = SNDRV_PCM_RATE_8000, | 133 | .rates = WM1250_EV1_RATES, |
131 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 134 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
132 | }, | 135 | }, |
133 | .capture = { | 136 | .capture = { |
134 | .stream_name = "Capture", | 137 | .stream_name = "Capture", |
135 | .channels_min = 1, | 138 | .channels_min = 1, |
136 | .channels_max = 2, | 139 | .channels_max = 2, |
137 | .rates = SNDRV_PCM_RATE_8000, | 140 | .rates = WM1250_EV1_RATES, |
138 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 141 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
139 | }, | 142 | }, |
140 | .ops = &wm1250_ev1_ops, | 143 | .ops = &wm1250_ev1_ops, |
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 0418fa11e6bd..3fd5b29dc933 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm2000.c -- WM2000 ALSA Soc Audio driver | 2 | * wm2000.c -- WM2000 ALSA Soc Audio driver |
3 | * | 3 | * |
4 | * Copyright 2008-2010 Wolfson Microelectronics PLC. | 4 | * Copyright 2008-2011 Wolfson Microelectronics PLC. |
5 | * | 5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
@@ -674,9 +674,39 @@ static int wm2000_resume(struct snd_soc_codec *codec) | |||
674 | #define wm2000_resume NULL | 674 | #define wm2000_resume NULL |
675 | #endif | 675 | #endif |
676 | 676 | ||
677 | static bool wm2000_readable_reg(struct device *dev, unsigned int reg) | ||
678 | { | ||
679 | switch (reg) { | ||
680 | case WM2000_REG_SYS_START: | ||
681 | case WM2000_REG_SPEECH_CLARITY: | ||
682 | case WM2000_REG_SYS_WATCHDOG: | ||
683 | case WM2000_REG_ANA_VMID_PD_TIME: | ||
684 | case WM2000_REG_ANA_VMID_PU_TIME: | ||
685 | case WM2000_REG_CAT_FLTR_INDX: | ||
686 | case WM2000_REG_CAT_GAIN_0: | ||
687 | case WM2000_REG_SYS_STATUS: | ||
688 | case WM2000_REG_SYS_MODE_CNTRL: | ||
689 | case WM2000_REG_SYS_START0: | ||
690 | case WM2000_REG_SYS_START1: | ||
691 | case WM2000_REG_ID1: | ||
692 | case WM2000_REG_ID2: | ||
693 | case WM2000_REG_REVISON: | ||
694 | case WM2000_REG_SYS_CTL1: | ||
695 | case WM2000_REG_SYS_CTL2: | ||
696 | case WM2000_REG_ANC_STAT: | ||
697 | case WM2000_REG_IF_CTL: | ||
698 | return true; | ||
699 | default: | ||
700 | return false; | ||
701 | } | ||
702 | } | ||
703 | |||
677 | static const struct regmap_config wm2000_regmap = { | 704 | static const struct regmap_config wm2000_regmap = { |
678 | .reg_bits = 8, | 705 | .reg_bits = 8, |
679 | .val_bits = 8, | 706 | .val_bits = 8, |
707 | |||
708 | .max_register = WM2000_REG_IF_CTL, | ||
709 | .readable_reg = wm2000_readable_reg, | ||
680 | }; | 710 | }; |
681 | 711 | ||
682 | static int wm2000_probe(struct snd_soc_codec *codec) | 712 | static int wm2000_probe(struct snd_soc_codec *codec) |
diff --git a/sound/soc/codecs/wm5100-tables.c b/sound/soc/codecs/wm5100-tables.c index e167207a19cc..e239f4bf2460 100644 --- a/sound/soc/codecs/wm5100-tables.c +++ b/sound/soc/codecs/wm5100-tables.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm5100-tables.c -- WM5100 ALSA SoC Audio driver data | 2 | * wm5100-tables.c -- WM5100 ALSA SoC Audio driver data |
3 | * | 3 | * |
4 | * Copyright 2011 Wolfson Microelectronics plc | 4 | * Copyright 2011-2 Wolfson Microelectronics plc |
5 | * | 5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index cb6d5372103a..f4817292ef45 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm5100.c -- WM5100 ALSA SoC Audio driver | 2 | * wm5100.c -- WM5100 ALSA SoC Audio driver |
3 | * | 3 | * |
4 | * Copyright 2011 Wolfson Microelectronics plc | 4 | * Copyright 2011-2 Wolfson Microelectronics plc |
5 | * | 5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
@@ -2378,13 +2378,6 @@ static int wm5100_remove(struct snd_soc_codec *codec) | |||
2378 | return 0; | 2378 | return 0; |
2379 | } | 2379 | } |
2380 | 2380 | ||
2381 | static int wm5100_soc_volatile(struct snd_soc_codec *codec, | ||
2382 | unsigned int reg) | ||
2383 | { | ||
2384 | return true; | ||
2385 | } | ||
2386 | |||
2387 | |||
2388 | static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { | 2381 | static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { |
2389 | .probe = wm5100_probe, | 2382 | .probe = wm5100_probe, |
2390 | .remove = wm5100_remove, | 2383 | .remove = wm5100_remove, |
@@ -2392,8 +2385,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { | |||
2392 | .set_sysclk = wm5100_set_sysclk, | 2385 | .set_sysclk = wm5100_set_sysclk, |
2393 | .set_pll = wm5100_set_fll, | 2386 | .set_pll = wm5100_set_fll, |
2394 | .idle_bias_off = 1, | 2387 | .idle_bias_off = 1, |
2395 | .reg_cache_size = WM5100_MAX_REGISTER, | ||
2396 | .volatile_register = wm5100_soc_volatile, | ||
2397 | 2388 | ||
2398 | .seq_notifier = wm5100_seq_notifier, | 2389 | .seq_notifier = wm5100_seq_notifier, |
2399 | .controls = wm5100_snd_controls, | 2390 | .controls = wm5100_snd_controls, |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c new file mode 100644 index 000000000000..6537f16d383e --- /dev/null +++ b/sound/soc/codecs/wm5102.c | |||
@@ -0,0 +1,903 @@ | |||
1 | /* | ||
2 | * wm5102.c -- WM5102 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/pm_runtime.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/jack.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/tlv.h> | ||
28 | |||
29 | #include <linux/mfd/arizona/core.h> | ||
30 | #include <linux/mfd/arizona/registers.h> | ||
31 | |||
32 | #include "arizona.h" | ||
33 | #include "wm5102.h" | ||
34 | |||
35 | struct wm5102_priv { | ||
36 | struct arizona_priv core; | ||
37 | struct arizona_fll fll[2]; | ||
38 | }; | ||
39 | |||
40 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); | ||
41 | static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | ||
42 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); | ||
43 | static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); | ||
44 | |||
45 | static const struct snd_kcontrol_new wm5102_snd_controls[] = { | ||
46 | SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL, | ||
47 | ARIZONA_IN1_OSR_SHIFT, 1, 0), | ||
48 | SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL, | ||
49 | ARIZONA_IN2_OSR_SHIFT, 1, 0), | ||
50 | SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL, | ||
51 | ARIZONA_IN3_OSR_SHIFT, 1, 0), | ||
52 | |||
53 | SOC_DOUBLE_R_RANGE_TLV("IN1 Volume", ARIZONA_IN1L_CONTROL, | ||
54 | ARIZONA_IN1R_CONTROL, | ||
55 | ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | ||
56 | SOC_DOUBLE_R_RANGE_TLV("IN2 Volume", ARIZONA_IN2L_CONTROL, | ||
57 | ARIZONA_IN2R_CONTROL, | ||
58 | ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | ||
59 | SOC_DOUBLE_R_RANGE_TLV("IN3 Volume", ARIZONA_IN3L_CONTROL, | ||
60 | ARIZONA_IN3R_CONTROL, | ||
61 | ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | ||
62 | |||
63 | SOC_DOUBLE_R("IN1 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_1L, | ||
64 | ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_MUTE_SHIFT, 1, 1), | ||
65 | SOC_DOUBLE_R("IN2 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_2L, | ||
66 | ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_MUTE_SHIFT, 1, 1), | ||
67 | SOC_DOUBLE_R("IN3 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_3L, | ||
68 | ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_MUTE_SHIFT, 1, 1), | ||
69 | |||
70 | SOC_DOUBLE_R_TLV("IN1 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L, | ||
71 | ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_DIG_VOL_SHIFT, | ||
72 | 0xbf, 0, digital_tlv), | ||
73 | SOC_DOUBLE_R_TLV("IN2 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L, | ||
74 | ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_DIG_VOL_SHIFT, | ||
75 | 0xbf, 0, digital_tlv), | ||
76 | SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L, | ||
77 | ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT, | ||
78 | 0xbf, 0, digital_tlv), | ||
79 | |||
80 | ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), | ||
81 | ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | ||
82 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | ||
83 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | ||
84 | |||
85 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | ||
86 | 24, 0, eq_tlv), | ||
87 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | ||
88 | 24, 0, eq_tlv), | ||
89 | SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT, | ||
90 | 24, 0, eq_tlv), | ||
91 | SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, | ||
92 | 24, 0, eq_tlv), | ||
93 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, | ||
94 | 24, 0, eq_tlv), | ||
95 | |||
96 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, | ||
97 | 24, 0, eq_tlv), | ||
98 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, | ||
99 | 24, 0, eq_tlv), | ||
100 | SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT, | ||
101 | 24, 0, eq_tlv), | ||
102 | SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, | ||
103 | 24, 0, eq_tlv), | ||
104 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, | ||
105 | 24, 0, eq_tlv), | ||
106 | |||
107 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, | ||
108 | 24, 0, eq_tlv), | ||
109 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, | ||
110 | 24, 0, eq_tlv), | ||
111 | SOC_SINGLE_TLV("EQ3 B3 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B3_GAIN_SHIFT, | ||
112 | 24, 0, eq_tlv), | ||
113 | SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, | ||
114 | 24, 0, eq_tlv), | ||
115 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, | ||
116 | 24, 0, eq_tlv), | ||
117 | |||
118 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, | ||
119 | 24, 0, eq_tlv), | ||
120 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, | ||
121 | 24, 0, eq_tlv), | ||
122 | SOC_SINGLE_TLV("EQ4 B3 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B3_GAIN_SHIFT, | ||
123 | 24, 0, eq_tlv), | ||
124 | SOC_SINGLE_TLV("EQ4 B4 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B4_GAIN_SHIFT, | ||
125 | 24, 0, eq_tlv), | ||
126 | SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT, | ||
127 | 24, 0, eq_tlv), | ||
128 | |||
129 | ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE), | ||
130 | ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE), | ||
131 | ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE), | ||
132 | ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE), | ||
133 | |||
134 | SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5, | ||
135 | ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA), | ||
136 | SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5, | ||
137 | ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA), | ||
138 | |||
139 | ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE), | ||
140 | ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), | ||
141 | ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), | ||
142 | ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), | ||
143 | |||
144 | SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), | ||
145 | SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | ||
146 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), | ||
147 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), | ||
148 | |||
149 | ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), | ||
150 | ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), | ||
151 | |||
152 | SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR, | ||
153 | ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv), | ||
154 | |||
155 | ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE), | ||
156 | ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE), | ||
157 | ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE), | ||
158 | ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE), | ||
159 | ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE), | ||
160 | ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE), | ||
161 | ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), | ||
162 | ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), | ||
163 | ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), | ||
164 | |||
165 | SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L, | ||
166 | ARIZONA_OUT1_OSR_SHIFT, 1, 0), | ||
167 | SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L, | ||
168 | ARIZONA_OUT2_OSR_SHIFT, 1, 0), | ||
169 | SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L, | ||
170 | ARIZONA_OUT3_OSR_SHIFT, 1, 0), | ||
171 | SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, | ||
172 | ARIZONA_OUT4_OSR_SHIFT, 1, 0), | ||
173 | SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, | ||
174 | ARIZONA_OUT5_OSR_SHIFT, 1, 0), | ||
175 | |||
176 | SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, | ||
177 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), | ||
178 | SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, | ||
179 | ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1), | ||
180 | SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L, | ||
181 | ARIZONA_OUT3L_MUTE_SHIFT, 1, 1), | ||
182 | SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L, | ||
183 | ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1), | ||
184 | SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L, | ||
185 | ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_MUTE_SHIFT, 1, 1), | ||
186 | |||
187 | SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L, | ||
188 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT, | ||
189 | 0xbf, 0, digital_tlv), | ||
190 | SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L, | ||
191 | ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT, | ||
192 | 0xbf, 0, digital_tlv), | ||
193 | SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L, | ||
194 | ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv), | ||
195 | SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L, | ||
196 | ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT, | ||
197 | 0xbf, 0, digital_tlv), | ||
198 | SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L, | ||
199 | ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, | ||
200 | 0xbf, 0, digital_tlv), | ||
201 | |||
202 | SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L, | ||
203 | ARIZONA_OUTPUT_PATH_CONFIG_1R, | ||
204 | ARIZONA_OUT1L_PGA_VOL_SHIFT, | ||
205 | 0x34, 0x40, 0, ana_tlv), | ||
206 | SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L, | ||
207 | ARIZONA_OUTPUT_PATH_CONFIG_2R, | ||
208 | ARIZONA_OUT2L_PGA_VOL_SHIFT, | ||
209 | 0x34, 0x40, 0, ana_tlv), | ||
210 | SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L, | ||
211 | ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv), | ||
212 | |||
213 | SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, | ||
214 | ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), | ||
215 | |||
216 | ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE), | ||
217 | ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE), | ||
218 | ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE), | ||
219 | ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE), | ||
220 | ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE), | ||
221 | ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE), | ||
222 | ARIZONA_MIXER_CONTROLS("AIF1TX7", ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE), | ||
223 | ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE), | ||
224 | |||
225 | ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE), | ||
226 | ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), | ||
227 | |||
228 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), | ||
229 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), | ||
230 | }; | ||
231 | |||
232 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); | ||
233 | ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); | ||
234 | ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); | ||
235 | ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE); | ||
236 | |||
237 | ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE); | ||
238 | ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE); | ||
239 | ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE); | ||
240 | ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE); | ||
241 | |||
242 | ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE); | ||
243 | ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE); | ||
244 | ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE); | ||
245 | ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE); | ||
246 | |||
247 | ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE); | ||
248 | ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE); | ||
249 | |||
250 | ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE); | ||
251 | ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE); | ||
252 | |||
253 | ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE); | ||
254 | ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE); | ||
255 | ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE); | ||
256 | ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE); | ||
257 | ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE); | ||
258 | ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE); | ||
259 | ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE); | ||
260 | ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE); | ||
261 | ARIZONA_MIXER_ENUMS(SPKDAT1R, ARIZONA_OUT5RMIX_INPUT_1_SOURCE); | ||
262 | |||
263 | ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE); | ||
264 | ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE); | ||
265 | ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE); | ||
266 | ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE); | ||
267 | ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE); | ||
268 | ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE); | ||
269 | ARIZONA_MIXER_ENUMS(AIF1TX7, ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE); | ||
270 | ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE); | ||
271 | |||
272 | ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE); | ||
273 | ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | ||
274 | |||
275 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); | ||
276 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); | ||
277 | |||
278 | ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); | ||
279 | ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | ||
280 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | ||
281 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | ||
282 | |||
283 | static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { | ||
284 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | ||
285 | 0, NULL, 0), | ||
286 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | ||
287 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | ||
288 | |||
289 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | ||
290 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | ||
291 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | ||
292 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), | ||
293 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), | ||
294 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), | ||
295 | |||
296 | SND_SOC_DAPM_SIGGEN("TONE"), | ||
297 | SND_SOC_DAPM_SIGGEN("NOISE"), | ||
298 | |||
299 | SND_SOC_DAPM_INPUT("IN1L"), | ||
300 | SND_SOC_DAPM_INPUT("IN1R"), | ||
301 | SND_SOC_DAPM_INPUT("IN2L"), | ||
302 | SND_SOC_DAPM_INPUT("IN2R"), | ||
303 | SND_SOC_DAPM_INPUT("IN3L"), | ||
304 | SND_SOC_DAPM_INPUT("IN3R"), | ||
305 | |||
306 | SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, | ||
307 | 0, NULL, 0, arizona_in_ev, | ||
308 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
309 | SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, | ||
310 | 0, NULL, 0, arizona_in_ev, | ||
311 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
312 | SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, | ||
313 | 0, NULL, 0, arizona_in_ev, | ||
314 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
315 | SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, | ||
316 | 0, NULL, 0, arizona_in_ev, | ||
317 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
318 | SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, | ||
319 | 0, NULL, 0, arizona_in_ev, | ||
320 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
321 | SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, | ||
322 | 0, NULL, 0, arizona_in_ev, | ||
323 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
324 | |||
325 | SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, | ||
326 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | ||
327 | SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2, | ||
328 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | ||
329 | SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3, | ||
330 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | ||
331 | |||
332 | SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR, | ||
333 | ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), | ||
334 | |||
335 | SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1, | ||
336 | ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0), | ||
337 | SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1, | ||
338 | ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0), | ||
339 | |||
340 | SND_SOC_DAPM_PGA("Mic Mute Mixer", ARIZONA_MIC_NOISE_MIX_CONTROL_1, | ||
341 | ARIZONA_MICMUTE_MIX_ENA_SHIFT, 0, NULL, 0), | ||
342 | |||
343 | SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0), | ||
344 | SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0), | ||
345 | SND_SOC_DAPM_PGA("EQ3", ARIZONA_EQ3_1, ARIZONA_EQ3_ENA_SHIFT, 0, NULL, 0), | ||
346 | SND_SOC_DAPM_PGA("EQ4", ARIZONA_EQ4_1, ARIZONA_EQ4_ENA_SHIFT, 0, NULL, 0), | ||
347 | |||
348 | SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0, | ||
349 | NULL, 0), | ||
350 | SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0, | ||
351 | NULL, 0), | ||
352 | SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0, | ||
353 | NULL, 0), | ||
354 | SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0, | ||
355 | NULL, 0), | ||
356 | |||
357 | SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0, | ||
358 | NULL, 0), | ||
359 | SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0, | ||
360 | NULL, 0), | ||
361 | SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0, | ||
362 | NULL, 0), | ||
363 | SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0, | ||
364 | NULL, 0), | ||
365 | |||
366 | SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT, | ||
367 | 0, NULL, 0), | ||
368 | SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT, | ||
369 | 0, NULL, 0), | ||
370 | |||
371 | SND_SOC_DAPM_PGA("ASRC1L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1L_ENA_SHIFT, 0, | ||
372 | NULL, 0), | ||
373 | SND_SOC_DAPM_PGA("ASRC1R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1R_ENA_SHIFT, 0, | ||
374 | NULL, 0), | ||
375 | SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, | ||
376 | NULL, 0), | ||
377 | SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, | ||
378 | NULL, 0), | ||
379 | |||
380 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, | ||
381 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), | ||
382 | SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, | ||
383 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0), | ||
384 | SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, | ||
385 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0), | ||
386 | SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, | ||
387 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0), | ||
388 | SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, | ||
389 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0), | ||
390 | SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, | ||
391 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0), | ||
392 | SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, | ||
393 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0), | ||
394 | SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, | ||
395 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0), | ||
396 | |||
397 | SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, | ||
398 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0), | ||
399 | SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, | ||
400 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0), | ||
401 | SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, | ||
402 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0), | ||
403 | SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, | ||
404 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0), | ||
405 | SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, | ||
406 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0), | ||
407 | SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, | ||
408 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0), | ||
409 | SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, | ||
410 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0), | ||
411 | SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, | ||
412 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0), | ||
413 | |||
414 | SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, | ||
415 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0), | ||
416 | SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, | ||
417 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0), | ||
418 | |||
419 | SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, | ||
420 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0), | ||
421 | SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, | ||
422 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), | ||
423 | |||
424 | SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, | ||
425 | ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0), | ||
426 | SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, | ||
427 | ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0), | ||
428 | |||
429 | SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, | ||
430 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0), | ||
431 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | ||
432 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), | ||
433 | |||
434 | SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, | ||
435 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
436 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
437 | SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1, | ||
438 | ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
439 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
440 | SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, | ||
441 | ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
442 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
443 | SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, | ||
444 | ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
445 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
446 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, | ||
447 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
448 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
449 | SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, | ||
450 | ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
451 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
452 | SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1, | ||
453 | ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
454 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
455 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, | ||
456 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
457 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
458 | SND_SOC_DAPM_PGA_E("OUT5R", ARIZONA_OUTPUT_ENABLES_1, | ||
459 | ARIZONA_OUT5R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
460 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
461 | |||
462 | ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"), | ||
463 | ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"), | ||
464 | ARIZONA_MIXER_WIDGETS(EQ3, "EQ3"), | ||
465 | ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"), | ||
466 | |||
467 | ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"), | ||
468 | ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"), | ||
469 | ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"), | ||
470 | ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"), | ||
471 | |||
472 | ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"), | ||
473 | ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"), | ||
474 | ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"), | ||
475 | ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"), | ||
476 | |||
477 | ARIZONA_MIXER_WIDGETS(Mic, "Mic"), | ||
478 | ARIZONA_MIXER_WIDGETS(Noise, "Noise"), | ||
479 | |||
480 | ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"), | ||
481 | ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"), | ||
482 | |||
483 | ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), | ||
484 | ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), | ||
485 | ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), | ||
486 | ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), | ||
487 | ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"), | ||
488 | ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), | ||
489 | ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), | ||
490 | ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), | ||
491 | ARIZONA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), | ||
492 | |||
493 | ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), | ||
494 | ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), | ||
495 | ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), | ||
496 | ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), | ||
497 | ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), | ||
498 | ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), | ||
499 | ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"), | ||
500 | ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), | ||
501 | |||
502 | ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), | ||
503 | ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | ||
504 | |||
505 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | ||
506 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | ||
507 | |||
508 | ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"), | ||
509 | ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"), | ||
510 | ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"), | ||
511 | ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"), | ||
512 | |||
513 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), | ||
514 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), | ||
515 | SND_SOC_DAPM_OUTPUT("HPOUT2L"), | ||
516 | SND_SOC_DAPM_OUTPUT("HPOUT2R"), | ||
517 | SND_SOC_DAPM_OUTPUT("EPOUTN"), | ||
518 | SND_SOC_DAPM_OUTPUT("EPOUTP"), | ||
519 | SND_SOC_DAPM_OUTPUT("SPKOUTLN"), | ||
520 | SND_SOC_DAPM_OUTPUT("SPKOUTLP"), | ||
521 | SND_SOC_DAPM_OUTPUT("SPKOUTRN"), | ||
522 | SND_SOC_DAPM_OUTPUT("SPKOUTRP"), | ||
523 | SND_SOC_DAPM_OUTPUT("SPKDAT1L"), | ||
524 | SND_SOC_DAPM_OUTPUT("SPKDAT1R"), | ||
525 | }; | ||
526 | |||
527 | #define ARIZONA_MIXER_INPUT_ROUTES(name) \ | ||
528 | { name, "Noise Generator", "Noise Generator" }, \ | ||
529 | { name, "Tone Generator 1", "Tone Generator 1" }, \ | ||
530 | { name, "Tone Generator 2", "Tone Generator 2" }, \ | ||
531 | { name, "IN1L", "IN1L PGA" }, \ | ||
532 | { name, "IN1R", "IN1R PGA" }, \ | ||
533 | { name, "IN2L", "IN2L PGA" }, \ | ||
534 | { name, "IN2R", "IN2R PGA" }, \ | ||
535 | { name, "IN3L", "IN3L PGA" }, \ | ||
536 | { name, "IN3R", "IN3R PGA" }, \ | ||
537 | { name, "Mic Mute Mixer", "Mic Mute Mixer" }, \ | ||
538 | { name, "AIF1RX1", "AIF1RX1" }, \ | ||
539 | { name, "AIF1RX2", "AIF1RX2" }, \ | ||
540 | { name, "AIF1RX3", "AIF1RX3" }, \ | ||
541 | { name, "AIF1RX4", "AIF1RX4" }, \ | ||
542 | { name, "AIF1RX5", "AIF1RX5" }, \ | ||
543 | { name, "AIF1RX6", "AIF1RX6" }, \ | ||
544 | { name, "AIF1RX7", "AIF1RX7" }, \ | ||
545 | { name, "AIF1RX8", "AIF1RX8" }, \ | ||
546 | { name, "AIF2RX1", "AIF2RX1" }, \ | ||
547 | { name, "AIF2RX2", "AIF2RX2" }, \ | ||
548 | { name, "AIF3RX1", "AIF3RX1" }, \ | ||
549 | { name, "AIF3RX2", "AIF3RX2" }, \ | ||
550 | { name, "EQ1", "EQ1" }, \ | ||
551 | { name, "EQ2", "EQ2" }, \ | ||
552 | { name, "EQ3", "EQ3" }, \ | ||
553 | { name, "EQ4", "EQ4" }, \ | ||
554 | { name, "DRC1L", "DRC1L" }, \ | ||
555 | { name, "DRC1R", "DRC1R" }, \ | ||
556 | { name, "DRC2L", "DRC2L" }, \ | ||
557 | { name, "DRC2R", "DRC2R" }, \ | ||
558 | { name, "LHPF1", "LHPF1" }, \ | ||
559 | { name, "LHPF2", "LHPF2" }, \ | ||
560 | { name, "LHPF3", "LHPF3" }, \ | ||
561 | { name, "LHPF4", "LHPF4" }, \ | ||
562 | { name, "ASRC1L", "ASRC1L" }, \ | ||
563 | { name, "ASRC1R", "ASRC1R" }, \ | ||
564 | { name, "ASRC2L", "ASRC2L" }, \ | ||
565 | { name, "ASRC2R", "ASRC2R" } | ||
566 | |||
567 | static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | ||
568 | { "AIF2 Capture", NULL, "DBVDD2" }, | ||
569 | { "AIF2 Playback", NULL, "DBVDD2" }, | ||
570 | |||
571 | { "AIF3 Capture", NULL, "DBVDD3" }, | ||
572 | { "AIF3 Playback", NULL, "DBVDD3" }, | ||
573 | |||
574 | { "OUT1L", NULL, "CPVDD" }, | ||
575 | { "OUT1R", NULL, "CPVDD" }, | ||
576 | { "OUT2L", NULL, "CPVDD" }, | ||
577 | { "OUT2R", NULL, "CPVDD" }, | ||
578 | { "OUT3L", NULL, "CPVDD" }, | ||
579 | |||
580 | { "OUT4L", NULL, "SPKVDDL" }, | ||
581 | { "OUT4R", NULL, "SPKVDDR" }, | ||
582 | |||
583 | { "OUT1L", NULL, "SYSCLK" }, | ||
584 | { "OUT1R", NULL, "SYSCLK" }, | ||
585 | { "OUT2L", NULL, "SYSCLK" }, | ||
586 | { "OUT2R", NULL, "SYSCLK" }, | ||
587 | { "OUT3L", NULL, "SYSCLK" }, | ||
588 | { "OUT4L", NULL, "SYSCLK" }, | ||
589 | { "OUT4R", NULL, "SYSCLK" }, | ||
590 | { "OUT5L", NULL, "SYSCLK" }, | ||
591 | { "OUT5R", NULL, "SYSCLK" }, | ||
592 | |||
593 | { "MICBIAS1", NULL, "MICVDD" }, | ||
594 | { "MICBIAS2", NULL, "MICVDD" }, | ||
595 | { "MICBIAS3", NULL, "MICVDD" }, | ||
596 | |||
597 | { "Noise Generator", NULL, "NOISE" }, | ||
598 | { "Tone Generator 1", NULL, "TONE" }, | ||
599 | { "Tone Generator 2", NULL, "TONE" }, | ||
600 | |||
601 | { "Mic Mute Mixer", NULL, "Noise Mixer" }, | ||
602 | { "Mic Mute Mixer", NULL, "Mic Mixer" }, | ||
603 | |||
604 | { "AIF1 Capture", NULL, "AIF1TX1" }, | ||
605 | { "AIF1 Capture", NULL, "AIF1TX2" }, | ||
606 | { "AIF1 Capture", NULL, "AIF1TX3" }, | ||
607 | { "AIF1 Capture", NULL, "AIF1TX4" }, | ||
608 | { "AIF1 Capture", NULL, "AIF1TX5" }, | ||
609 | { "AIF1 Capture", NULL, "AIF1TX6" }, | ||
610 | { "AIF1 Capture", NULL, "AIF1TX7" }, | ||
611 | { "AIF1 Capture", NULL, "AIF1TX8" }, | ||
612 | |||
613 | { "AIF1RX1", NULL, "AIF1 Playback" }, | ||
614 | { "AIF1RX2", NULL, "AIF1 Playback" }, | ||
615 | { "AIF1RX3", NULL, "AIF1 Playback" }, | ||
616 | { "AIF1RX4", NULL, "AIF1 Playback" }, | ||
617 | { "AIF1RX5", NULL, "AIF1 Playback" }, | ||
618 | { "AIF1RX6", NULL, "AIF1 Playback" }, | ||
619 | { "AIF1RX7", NULL, "AIF1 Playback" }, | ||
620 | { "AIF1RX8", NULL, "AIF1 Playback" }, | ||
621 | |||
622 | { "AIF2 Capture", NULL, "AIF2TX1" }, | ||
623 | { "AIF2 Capture", NULL, "AIF2TX2" }, | ||
624 | |||
625 | { "AIF2RX1", NULL, "AIF2 Playback" }, | ||
626 | { "AIF2RX2", NULL, "AIF2 Playback" }, | ||
627 | |||
628 | { "AIF3 Capture", NULL, "AIF3TX1" }, | ||
629 | { "AIF3 Capture", NULL, "AIF3TX2" }, | ||
630 | |||
631 | { "AIF3RX1", NULL, "AIF3 Playback" }, | ||
632 | { "AIF3RX2", NULL, "AIF3 Playback" }, | ||
633 | |||
634 | { "AIF1 Playback", NULL, "SYSCLK" }, | ||
635 | { "AIF2 Playback", NULL, "SYSCLK" }, | ||
636 | { "AIF3 Playback", NULL, "SYSCLK" }, | ||
637 | |||
638 | { "AIF1 Capture", NULL, "SYSCLK" }, | ||
639 | { "AIF2 Capture", NULL, "SYSCLK" }, | ||
640 | { "AIF3 Capture", NULL, "SYSCLK" }, | ||
641 | |||
642 | ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), | ||
643 | ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), | ||
644 | ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), | ||
645 | ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"), | ||
646 | ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"), | ||
647 | |||
648 | ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"), | ||
649 | ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"), | ||
650 | ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), | ||
651 | ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), | ||
652 | |||
653 | ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"), | ||
654 | ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"), | ||
655 | |||
656 | ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), | ||
657 | ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), | ||
658 | ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), | ||
659 | ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), | ||
660 | ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), | ||
661 | ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), | ||
662 | ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), | ||
663 | ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), | ||
664 | |||
665 | ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), | ||
666 | ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), | ||
667 | |||
668 | ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), | ||
669 | ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), | ||
670 | |||
671 | ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), | ||
672 | ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), | ||
673 | ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), | ||
674 | ARIZONA_MIXER_ROUTES("EQ4", "EQ4"), | ||
675 | |||
676 | ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"), | ||
677 | ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"), | ||
678 | ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"), | ||
679 | ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"), | ||
680 | |||
681 | ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"), | ||
682 | ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"), | ||
683 | ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), | ||
684 | ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), | ||
685 | |||
686 | ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"), | ||
687 | ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"), | ||
688 | ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), | ||
689 | ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), | ||
690 | |||
691 | { "HPOUT1L", NULL, "OUT1L" }, | ||
692 | { "HPOUT1R", NULL, "OUT1R" }, | ||
693 | |||
694 | { "HPOUT2L", NULL, "OUT2L" }, | ||
695 | { "HPOUT2R", NULL, "OUT2R" }, | ||
696 | |||
697 | { "EPOUTN", NULL, "OUT3L" }, | ||
698 | { "EPOUTP", NULL, "OUT3L" }, | ||
699 | |||
700 | { "SPKOUTLN", NULL, "OUT4L" }, | ||
701 | { "SPKOUTLP", NULL, "OUT4L" }, | ||
702 | |||
703 | { "SPKOUTRN", NULL, "OUT4R" }, | ||
704 | { "SPKOUTRP", NULL, "OUT4R" }, | ||
705 | |||
706 | { "SPKDAT1L", NULL, "OUT5L" }, | ||
707 | { "SPKDAT1R", NULL, "OUT5R" }, | ||
708 | }; | ||
709 | |||
710 | static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | ||
711 | unsigned int Fref, unsigned int Fout) | ||
712 | { | ||
713 | struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec); | ||
714 | |||
715 | switch (fll_id) { | ||
716 | case WM5102_FLL1: | ||
717 | return arizona_set_fll(&wm5102->fll[0], source, Fref, Fout); | ||
718 | case WM5102_FLL2: | ||
719 | return arizona_set_fll(&wm5102->fll[1], source, Fref, Fout); | ||
720 | default: | ||
721 | return -EINVAL; | ||
722 | } | ||
723 | } | ||
724 | |||
725 | #define WM5102_RATES SNDRV_PCM_RATE_8000_192000 | ||
726 | |||
727 | #define WM5102_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
728 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
729 | |||
730 | static struct snd_soc_dai_driver wm5102_dai[] = { | ||
731 | { | ||
732 | .name = "wm5102-aif1", | ||
733 | .id = 1, | ||
734 | .base = ARIZONA_AIF1_BCLK_CTRL, | ||
735 | .playback = { | ||
736 | .stream_name = "AIF1 Playback", | ||
737 | .channels_min = 1, | ||
738 | .channels_max = 8, | ||
739 | .rates = WM5102_RATES, | ||
740 | .formats = WM5102_FORMATS, | ||
741 | }, | ||
742 | .capture = { | ||
743 | .stream_name = "AIF1 Capture", | ||
744 | .channels_min = 1, | ||
745 | .channels_max = 8, | ||
746 | .rates = WM5102_RATES, | ||
747 | .formats = WM5102_FORMATS, | ||
748 | }, | ||
749 | .ops = &arizona_dai_ops, | ||
750 | .symmetric_rates = 1, | ||
751 | }, | ||
752 | { | ||
753 | .name = "wm5102-aif2", | ||
754 | .id = 2, | ||
755 | .base = ARIZONA_AIF2_BCLK_CTRL, | ||
756 | .playback = { | ||
757 | .stream_name = "AIF2 Playback", | ||
758 | .channels_min = 1, | ||
759 | .channels_max = 2, | ||
760 | .rates = WM5102_RATES, | ||
761 | .formats = WM5102_FORMATS, | ||
762 | }, | ||
763 | .capture = { | ||
764 | .stream_name = "AIF2 Capture", | ||
765 | .channels_min = 1, | ||
766 | .channels_max = 2, | ||
767 | .rates = WM5102_RATES, | ||
768 | .formats = WM5102_FORMATS, | ||
769 | }, | ||
770 | .ops = &arizona_dai_ops, | ||
771 | .symmetric_rates = 1, | ||
772 | }, | ||
773 | { | ||
774 | .name = "wm5102-aif3", | ||
775 | .id = 3, | ||
776 | .base = ARIZONA_AIF3_BCLK_CTRL, | ||
777 | .playback = { | ||
778 | .stream_name = "AIF3 Playback", | ||
779 | .channels_min = 1, | ||
780 | .channels_max = 2, | ||
781 | .rates = WM5102_RATES, | ||
782 | .formats = WM5102_FORMATS, | ||
783 | }, | ||
784 | .capture = { | ||
785 | .stream_name = "AIF3 Capture", | ||
786 | .channels_min = 1, | ||
787 | .channels_max = 2, | ||
788 | .rates = WM5102_RATES, | ||
789 | .formats = WM5102_FORMATS, | ||
790 | }, | ||
791 | .ops = &arizona_dai_ops, | ||
792 | .symmetric_rates = 1, | ||
793 | }, | ||
794 | }; | ||
795 | |||
796 | static int wm5102_codec_probe(struct snd_soc_codec *codec) | ||
797 | { | ||
798 | struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
799 | |||
800 | codec->control_data = priv->core.arizona->regmap; | ||
801 | return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); | ||
802 | } | ||
803 | |||
804 | #define WM5102_DIG_VU 0x0200 | ||
805 | |||
806 | static unsigned int wm5102_digital_vu[] = { | ||
807 | ARIZONA_ADC_DIGITAL_VOLUME_1L, | ||
808 | ARIZONA_ADC_DIGITAL_VOLUME_1R, | ||
809 | ARIZONA_ADC_DIGITAL_VOLUME_2L, | ||
810 | ARIZONA_ADC_DIGITAL_VOLUME_2R, | ||
811 | ARIZONA_ADC_DIGITAL_VOLUME_3L, | ||
812 | ARIZONA_ADC_DIGITAL_VOLUME_3R, | ||
813 | |||
814 | ARIZONA_DAC_DIGITAL_VOLUME_1L, | ||
815 | ARIZONA_DAC_DIGITAL_VOLUME_1R, | ||
816 | ARIZONA_DAC_DIGITAL_VOLUME_2L, | ||
817 | ARIZONA_DAC_DIGITAL_VOLUME_2R, | ||
818 | ARIZONA_DAC_DIGITAL_VOLUME_3L, | ||
819 | ARIZONA_DAC_DIGITAL_VOLUME_3R, | ||
820 | ARIZONA_DAC_DIGITAL_VOLUME_4L, | ||
821 | ARIZONA_DAC_DIGITAL_VOLUME_4R, | ||
822 | ARIZONA_DAC_DIGITAL_VOLUME_5L, | ||
823 | ARIZONA_DAC_DIGITAL_VOLUME_5R, | ||
824 | }; | ||
825 | |||
826 | static struct snd_soc_codec_driver soc_codec_dev_wm5102 = { | ||
827 | .probe = wm5102_codec_probe, | ||
828 | |||
829 | .idle_bias_off = true, | ||
830 | |||
831 | .set_sysclk = arizona_set_sysclk, | ||
832 | .set_pll = wm5102_set_fll, | ||
833 | |||
834 | .controls = wm5102_snd_controls, | ||
835 | .num_controls = ARRAY_SIZE(wm5102_snd_controls), | ||
836 | .dapm_widgets = wm5102_dapm_widgets, | ||
837 | .num_dapm_widgets = ARRAY_SIZE(wm5102_dapm_widgets), | ||
838 | .dapm_routes = wm5102_dapm_routes, | ||
839 | .num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes), | ||
840 | }; | ||
841 | |||
842 | static int __devinit wm5102_probe(struct platform_device *pdev) | ||
843 | { | ||
844 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | ||
845 | struct wm5102_priv *wm5102; | ||
846 | int i; | ||
847 | |||
848 | wm5102 = devm_kzalloc(&pdev->dev, sizeof(struct wm5102_priv), | ||
849 | GFP_KERNEL); | ||
850 | if (wm5102 == NULL) | ||
851 | return -ENOMEM; | ||
852 | platform_set_drvdata(pdev, wm5102); | ||
853 | |||
854 | wm5102->core.arizona = arizona; | ||
855 | |||
856 | for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++) | ||
857 | wm5102->fll[i].vco_mult = 1; | ||
858 | |||
859 | arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1, | ||
860 | ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK, | ||
861 | &wm5102->fll[0]); | ||
862 | arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1, | ||
863 | ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, | ||
864 | &wm5102->fll[1]); | ||
865 | |||
866 | for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++) | ||
867 | arizona_init_dai(&wm5102->core, i); | ||
868 | |||
869 | /* Latch volume update bits */ | ||
870 | for (i = 0; i < ARRAY_SIZE(wm5102_digital_vu); i++) | ||
871 | regmap_update_bits(arizona->regmap, wm5102_digital_vu[i], | ||
872 | WM5102_DIG_VU, WM5102_DIG_VU); | ||
873 | |||
874 | pm_runtime_enable(&pdev->dev); | ||
875 | pm_runtime_idle(&pdev->dev); | ||
876 | |||
877 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5102, | ||
878 | wm5102_dai, ARRAY_SIZE(wm5102_dai)); | ||
879 | } | ||
880 | |||
881 | static int __devexit wm5102_remove(struct platform_device *pdev) | ||
882 | { | ||
883 | snd_soc_unregister_codec(&pdev->dev); | ||
884 | pm_runtime_disable(&pdev->dev); | ||
885 | |||
886 | return 0; | ||
887 | } | ||
888 | |||
889 | static struct platform_driver wm5102_codec_driver = { | ||
890 | .driver = { | ||
891 | .name = "wm5102-codec", | ||
892 | .owner = THIS_MODULE, | ||
893 | }, | ||
894 | .probe = wm5102_probe, | ||
895 | .remove = __devexit_p(wm5102_remove), | ||
896 | }; | ||
897 | |||
898 | module_platform_driver(wm5102_codec_driver); | ||
899 | |||
900 | MODULE_DESCRIPTION("ASoC WM5102 driver"); | ||
901 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
902 | MODULE_LICENSE("GPL"); | ||
903 | MODULE_ALIAS("platform:wm5102-codec"); | ||
diff --git a/sound/soc/codecs/wm5102.h b/sound/soc/codecs/wm5102.h new file mode 100644 index 000000000000..d30477f3070c --- /dev/null +++ b/sound/soc/codecs/wm5102.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * wm5102.h -- WM5102 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef _WM5102_H | ||
14 | #define _WM5102_H | ||
15 | |||
16 | #include "arizona.h" | ||
17 | |||
18 | #define WM5102_FLL1 1 | ||
19 | #define WM5102_FLL2 2 | ||
20 | |||
21 | #endif | ||
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c new file mode 100644 index 000000000000..8033f7065189 --- /dev/null +++ b/sound/soc/codecs/wm5110.c | |||
@@ -0,0 +1,950 @@ | |||
1 | /* | ||
2 | * wm5110.c -- WM5110 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/pm_runtime.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/jack.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/tlv.h> | ||
28 | |||
29 | #include <linux/mfd/arizona/core.h> | ||
30 | #include <linux/mfd/arizona/registers.h> | ||
31 | |||
32 | #include "arizona.h" | ||
33 | #include "wm5110.h" | ||
34 | |||
35 | struct wm5110_priv { | ||
36 | struct arizona_priv core; | ||
37 | struct arizona_fll fll[2]; | ||
38 | }; | ||
39 | |||
40 | static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); | ||
41 | static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | ||
42 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); | ||
43 | static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); | ||
44 | |||
45 | static const struct snd_kcontrol_new wm5110_snd_controls[] = { | ||
46 | SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL, | ||
47 | ARIZONA_IN1_OSR_SHIFT, 1, 0), | ||
48 | SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL, | ||
49 | ARIZONA_IN2_OSR_SHIFT, 1, 0), | ||
50 | SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL, | ||
51 | ARIZONA_IN3_OSR_SHIFT, 1, 0), | ||
52 | SOC_SINGLE("IN4 High Performance Switch", ARIZONA_IN4L_CONTROL, | ||
53 | ARIZONA_IN4_OSR_SHIFT, 1, 0), | ||
54 | |||
55 | SOC_DOUBLE_R_RANGE_TLV("IN1 Volume", ARIZONA_IN1L_CONTROL, | ||
56 | ARIZONA_IN1R_CONTROL, | ||
57 | ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | ||
58 | SOC_DOUBLE_R_RANGE_TLV("IN2 Volume", ARIZONA_IN2L_CONTROL, | ||
59 | ARIZONA_IN2R_CONTROL, | ||
60 | ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | ||
61 | SOC_DOUBLE_R_RANGE_TLV("IN3 Volume", ARIZONA_IN3L_CONTROL, | ||
62 | ARIZONA_IN3R_CONTROL, | ||
63 | ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv), | ||
64 | |||
65 | SOC_DOUBLE_R("IN1 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_1L, | ||
66 | ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_MUTE_SHIFT, 1, 1), | ||
67 | SOC_DOUBLE_R("IN2 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_2L, | ||
68 | ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_MUTE_SHIFT, 1, 1), | ||
69 | SOC_DOUBLE_R("IN3 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_3L, | ||
70 | ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_MUTE_SHIFT, 1, 1), | ||
71 | SOC_DOUBLE_R("IN4 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_4L, | ||
72 | ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_MUTE_SHIFT, 1, 1), | ||
73 | |||
74 | SOC_DOUBLE_R_TLV("IN1 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L, | ||
75 | ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_DIG_VOL_SHIFT, | ||
76 | 0xbf, 0, digital_tlv), | ||
77 | SOC_DOUBLE_R_TLV("IN2 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L, | ||
78 | ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_DIG_VOL_SHIFT, | ||
79 | 0xbf, 0, digital_tlv), | ||
80 | SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L, | ||
81 | ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT, | ||
82 | 0xbf, 0, digital_tlv), | ||
83 | SOC_DOUBLE_R_TLV("IN4 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4L, | ||
84 | ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT, | ||
85 | 0xbf, 0, digital_tlv), | ||
86 | |||
87 | ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), | ||
88 | ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | ||
89 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | ||
90 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | ||
91 | |||
92 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | ||
93 | 24, 0, eq_tlv), | ||
94 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | ||
95 | 24, 0, eq_tlv), | ||
96 | SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT, | ||
97 | 24, 0, eq_tlv), | ||
98 | SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, | ||
99 | 24, 0, eq_tlv), | ||
100 | SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, | ||
101 | 24, 0, eq_tlv), | ||
102 | |||
103 | SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, | ||
104 | 24, 0, eq_tlv), | ||
105 | SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, | ||
106 | 24, 0, eq_tlv), | ||
107 | SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT, | ||
108 | 24, 0, eq_tlv), | ||
109 | SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, | ||
110 | 24, 0, eq_tlv), | ||
111 | SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, | ||
112 | 24, 0, eq_tlv), | ||
113 | |||
114 | SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, | ||
115 | 24, 0, eq_tlv), | ||
116 | SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, | ||
117 | 24, 0, eq_tlv), | ||
118 | SOC_SINGLE_TLV("EQ3 B3 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B3_GAIN_SHIFT, | ||
119 | 24, 0, eq_tlv), | ||
120 | SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, | ||
121 | 24, 0, eq_tlv), | ||
122 | SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, | ||
123 | 24, 0, eq_tlv), | ||
124 | |||
125 | SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, | ||
126 | 24, 0, eq_tlv), | ||
127 | SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, | ||
128 | 24, 0, eq_tlv), | ||
129 | SOC_SINGLE_TLV("EQ4 B3 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B3_GAIN_SHIFT, | ||
130 | 24, 0, eq_tlv), | ||
131 | SOC_SINGLE_TLV("EQ4 B4 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B4_GAIN_SHIFT, | ||
132 | 24, 0, eq_tlv), | ||
133 | SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT, | ||
134 | 24, 0, eq_tlv), | ||
135 | |||
136 | ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE), | ||
137 | ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE), | ||
138 | ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE), | ||
139 | ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE), | ||
140 | |||
141 | SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5, | ||
142 | ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA), | ||
143 | SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5, | ||
144 | ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA), | ||
145 | |||
146 | ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE), | ||
147 | ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), | ||
148 | ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), | ||
149 | ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), | ||
150 | |||
151 | SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), | ||
152 | SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | ||
153 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), | ||
154 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), | ||
155 | |||
156 | ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), | ||
157 | ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), | ||
158 | |||
159 | SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR, | ||
160 | ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv), | ||
161 | |||
162 | ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE), | ||
163 | ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE), | ||
164 | ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE), | ||
165 | ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE), | ||
166 | ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE), | ||
167 | ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE), | ||
168 | ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), | ||
169 | ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), | ||
170 | ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), | ||
171 | ARIZONA_MIXER_CONTROLS("SPKDAT2L", ARIZONA_OUT6LMIX_INPUT_1_SOURCE), | ||
172 | ARIZONA_MIXER_CONTROLS("SPKDAT2R", ARIZONA_OUT6RMIX_INPUT_1_SOURCE), | ||
173 | |||
174 | SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L, | ||
175 | ARIZONA_OUT1_OSR_SHIFT, 1, 0), | ||
176 | SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L, | ||
177 | ARIZONA_OUT2_OSR_SHIFT, 1, 0), | ||
178 | SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L, | ||
179 | ARIZONA_OUT3_OSR_SHIFT, 1, 0), | ||
180 | SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, | ||
181 | ARIZONA_OUT4_OSR_SHIFT, 1, 0), | ||
182 | SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, | ||
183 | ARIZONA_OUT5_OSR_SHIFT, 1, 0), | ||
184 | SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L, | ||
185 | ARIZONA_OUT6_OSR_SHIFT, 1, 0), | ||
186 | |||
187 | SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, | ||
188 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), | ||
189 | SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, | ||
190 | ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1), | ||
191 | SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L, | ||
192 | ARIZONA_OUT3L_MUTE_SHIFT, 1, 1), | ||
193 | SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L, | ||
194 | ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1), | ||
195 | SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L, | ||
196 | ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_MUTE_SHIFT, 1, 1), | ||
197 | SOC_DOUBLE_R("SPKDAT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_6L, | ||
198 | ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_MUTE_SHIFT, 1, 1), | ||
199 | |||
200 | SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L, | ||
201 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT, | ||
202 | 0xbf, 0, digital_tlv), | ||
203 | SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L, | ||
204 | ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT, | ||
205 | 0xbf, 0, digital_tlv), | ||
206 | SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L, | ||
207 | ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv), | ||
208 | SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L, | ||
209 | ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT, | ||
210 | 0xbf, 0, digital_tlv), | ||
211 | SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L, | ||
212 | ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, | ||
213 | 0xbf, 0, digital_tlv), | ||
214 | SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_6L, | ||
215 | ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_VOL_SHIFT, | ||
216 | 0xbf, 0, digital_tlv), | ||
217 | |||
218 | SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L, | ||
219 | ARIZONA_OUTPUT_PATH_CONFIG_1R, | ||
220 | ARIZONA_OUT1L_PGA_VOL_SHIFT, | ||
221 | 0x34, 0x40, 0, ana_tlv), | ||
222 | SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L, | ||
223 | ARIZONA_OUTPUT_PATH_CONFIG_2R, | ||
224 | ARIZONA_OUT2L_PGA_VOL_SHIFT, | ||
225 | 0x34, 0x40, 0, ana_tlv), | ||
226 | SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L, | ||
227 | ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv), | ||
228 | |||
229 | SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, | ||
230 | ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), | ||
231 | SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT, | ||
232 | ARIZONA_SPK2R_MUTE_SHIFT, 1, 1), | ||
233 | |||
234 | ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE), | ||
235 | ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE), | ||
236 | ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE), | ||
237 | ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE), | ||
238 | ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE), | ||
239 | ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE), | ||
240 | ARIZONA_MIXER_CONTROLS("AIF1TX7", ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE), | ||
241 | ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE), | ||
242 | |||
243 | ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE), | ||
244 | ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), | ||
245 | |||
246 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), | ||
247 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), | ||
248 | }; | ||
249 | |||
250 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); | ||
251 | ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE); | ||
252 | ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE); | ||
253 | ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE); | ||
254 | |||
255 | ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE); | ||
256 | ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE); | ||
257 | ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE); | ||
258 | ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE); | ||
259 | |||
260 | ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE); | ||
261 | ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE); | ||
262 | ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE); | ||
263 | ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE); | ||
264 | |||
265 | ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE); | ||
266 | ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE); | ||
267 | |||
268 | ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE); | ||
269 | ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE); | ||
270 | |||
271 | ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE); | ||
272 | ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE); | ||
273 | ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE); | ||
274 | ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE); | ||
275 | ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE); | ||
276 | ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE); | ||
277 | ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE); | ||
278 | ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE); | ||
279 | ARIZONA_MIXER_ENUMS(SPKDAT1R, ARIZONA_OUT5RMIX_INPUT_1_SOURCE); | ||
280 | ARIZONA_MIXER_ENUMS(SPKDAT2L, ARIZONA_OUT6LMIX_INPUT_1_SOURCE); | ||
281 | ARIZONA_MIXER_ENUMS(SPKDAT2R, ARIZONA_OUT6RMIX_INPUT_1_SOURCE); | ||
282 | |||
283 | ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE); | ||
284 | ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE); | ||
285 | ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE); | ||
286 | ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE); | ||
287 | ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE); | ||
288 | ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE); | ||
289 | ARIZONA_MIXER_ENUMS(AIF1TX7, ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE); | ||
290 | ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE); | ||
291 | |||
292 | ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE); | ||
293 | ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | ||
294 | |||
295 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); | ||
296 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); | ||
297 | |||
298 | ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); | ||
299 | ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | ||
300 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | ||
301 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | ||
302 | |||
303 | static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = { | ||
304 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | ||
305 | 0, NULL, 0), | ||
306 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | ||
307 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | ||
308 | |||
309 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | ||
310 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | ||
311 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | ||
312 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), | ||
313 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), | ||
314 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), | ||
315 | |||
316 | SND_SOC_DAPM_SIGGEN("TONE"), | ||
317 | SND_SOC_DAPM_SIGGEN("NOISE"), | ||
318 | |||
319 | SND_SOC_DAPM_INPUT("IN1L"), | ||
320 | SND_SOC_DAPM_INPUT("IN1R"), | ||
321 | SND_SOC_DAPM_INPUT("IN2L"), | ||
322 | SND_SOC_DAPM_INPUT("IN2R"), | ||
323 | SND_SOC_DAPM_INPUT("IN3L"), | ||
324 | SND_SOC_DAPM_INPUT("IN3R"), | ||
325 | SND_SOC_DAPM_INPUT("IN4L"), | ||
326 | SND_SOC_DAPM_INPUT("IN4R"), | ||
327 | |||
328 | SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT, | ||
329 | 0, NULL, 0, arizona_in_ev, | ||
330 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
331 | SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT, | ||
332 | 0, NULL, 0, arizona_in_ev, | ||
333 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
334 | SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT, | ||
335 | 0, NULL, 0, arizona_in_ev, | ||
336 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
337 | SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT, | ||
338 | 0, NULL, 0, arizona_in_ev, | ||
339 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
340 | SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT, | ||
341 | 0, NULL, 0, arizona_in_ev, | ||
342 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
343 | SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, | ||
344 | 0, NULL, 0, arizona_in_ev, | ||
345 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
346 | SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT, | ||
347 | 0, NULL, 0, arizona_in_ev, | ||
348 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
349 | SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT, | ||
350 | 0, NULL, 0, arizona_in_ev, | ||
351 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
352 | |||
353 | SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, | ||
354 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | ||
355 | SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2, | ||
356 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | ||
357 | SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3, | ||
358 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | ||
359 | |||
360 | SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR, | ||
361 | ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), | ||
362 | |||
363 | SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1, | ||
364 | ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0), | ||
365 | SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1, | ||
366 | ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0), | ||
367 | |||
368 | SND_SOC_DAPM_PGA("Mic Mute Mixer", ARIZONA_MIC_NOISE_MIX_CONTROL_1, | ||
369 | ARIZONA_MICMUTE_MIX_ENA_SHIFT, 0, NULL, 0), | ||
370 | |||
371 | SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0), | ||
372 | SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0), | ||
373 | SND_SOC_DAPM_PGA("EQ3", ARIZONA_EQ3_1, ARIZONA_EQ3_ENA_SHIFT, 0, NULL, 0), | ||
374 | SND_SOC_DAPM_PGA("EQ4", ARIZONA_EQ4_1, ARIZONA_EQ4_ENA_SHIFT, 0, NULL, 0), | ||
375 | |||
376 | SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0, | ||
377 | NULL, 0), | ||
378 | SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0, | ||
379 | NULL, 0), | ||
380 | SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0, | ||
381 | NULL, 0), | ||
382 | SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0, | ||
383 | NULL, 0), | ||
384 | |||
385 | SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0, | ||
386 | NULL, 0), | ||
387 | SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0, | ||
388 | NULL, 0), | ||
389 | SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0, | ||
390 | NULL, 0), | ||
391 | SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0, | ||
392 | NULL, 0), | ||
393 | |||
394 | SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT, | ||
395 | 0, NULL, 0), | ||
396 | SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT, | ||
397 | 0, NULL, 0), | ||
398 | |||
399 | SND_SOC_DAPM_PGA("ASRC1L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1L_ENA_SHIFT, 0, | ||
400 | NULL, 0), | ||
401 | SND_SOC_DAPM_PGA("ASRC1R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1R_ENA_SHIFT, 0, | ||
402 | NULL, 0), | ||
403 | SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, | ||
404 | NULL, 0), | ||
405 | SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, | ||
406 | NULL, 0), | ||
407 | |||
408 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, | ||
409 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), | ||
410 | SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, | ||
411 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0), | ||
412 | SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0, | ||
413 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0), | ||
414 | SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0, | ||
415 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0), | ||
416 | SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0, | ||
417 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0), | ||
418 | SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0, | ||
419 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0), | ||
420 | SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0, | ||
421 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0), | ||
422 | SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0, | ||
423 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0), | ||
424 | |||
425 | SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0, | ||
426 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0), | ||
427 | SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0, | ||
428 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0), | ||
429 | SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0, | ||
430 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0), | ||
431 | SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0, | ||
432 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0), | ||
433 | SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0, | ||
434 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0), | ||
435 | SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0, | ||
436 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0), | ||
437 | SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0, | ||
438 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0), | ||
439 | SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0, | ||
440 | ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0), | ||
441 | |||
442 | SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, | ||
443 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0), | ||
444 | SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0, | ||
445 | ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0), | ||
446 | |||
447 | SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, | ||
448 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0), | ||
449 | SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, | ||
450 | ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), | ||
451 | |||
452 | SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, | ||
453 | ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0), | ||
454 | SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, | ||
455 | ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0), | ||
456 | |||
457 | SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, | ||
458 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0), | ||
459 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | ||
460 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), | ||
461 | |||
462 | SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, | ||
463 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
464 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
465 | SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1, | ||
466 | ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
467 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
468 | SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1, | ||
469 | ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
470 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
471 | SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, | ||
472 | ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
473 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
474 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, | ||
475 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
476 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
477 | SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, | ||
478 | ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
479 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
480 | SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1, | ||
481 | ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
482 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
483 | SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1, | ||
484 | ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
485 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
486 | SND_SOC_DAPM_PGA_E("OUT5R", ARIZONA_OUTPUT_ENABLES_1, | ||
487 | ARIZONA_OUT5R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
488 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
489 | SND_SOC_DAPM_PGA_E("OUT6L", ARIZONA_OUTPUT_ENABLES_1, | ||
490 | ARIZONA_OUT6L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
491 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
492 | SND_SOC_DAPM_PGA_E("OUT6R", ARIZONA_OUTPUT_ENABLES_1, | ||
493 | ARIZONA_OUT6R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
494 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
495 | |||
496 | ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"), | ||
497 | ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"), | ||
498 | ARIZONA_MIXER_WIDGETS(EQ3, "EQ3"), | ||
499 | ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"), | ||
500 | |||
501 | ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"), | ||
502 | ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"), | ||
503 | ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"), | ||
504 | ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"), | ||
505 | |||
506 | ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"), | ||
507 | ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"), | ||
508 | ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"), | ||
509 | ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"), | ||
510 | |||
511 | ARIZONA_MIXER_WIDGETS(Mic, "Mic"), | ||
512 | ARIZONA_MIXER_WIDGETS(Noise, "Noise"), | ||
513 | |||
514 | ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"), | ||
515 | ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"), | ||
516 | |||
517 | ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), | ||
518 | ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), | ||
519 | ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), | ||
520 | ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), | ||
521 | ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"), | ||
522 | ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), | ||
523 | ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), | ||
524 | ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), | ||
525 | ARIZONA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), | ||
526 | ARIZONA_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"), | ||
527 | ARIZONA_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"), | ||
528 | |||
529 | ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), | ||
530 | ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), | ||
531 | ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), | ||
532 | ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), | ||
533 | ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), | ||
534 | ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), | ||
535 | ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"), | ||
536 | ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), | ||
537 | |||
538 | ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), | ||
539 | ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | ||
540 | |||
541 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | ||
542 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | ||
543 | |||
544 | ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"), | ||
545 | ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"), | ||
546 | ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"), | ||
547 | ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"), | ||
548 | |||
549 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), | ||
550 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), | ||
551 | SND_SOC_DAPM_OUTPUT("HPOUT2L"), | ||
552 | SND_SOC_DAPM_OUTPUT("HPOUT2R"), | ||
553 | SND_SOC_DAPM_OUTPUT("EPOUTN"), | ||
554 | SND_SOC_DAPM_OUTPUT("EPOUTP"), | ||
555 | SND_SOC_DAPM_OUTPUT("SPKOUTLN"), | ||
556 | SND_SOC_DAPM_OUTPUT("SPKOUTLP"), | ||
557 | SND_SOC_DAPM_OUTPUT("SPKOUTRN"), | ||
558 | SND_SOC_DAPM_OUTPUT("SPKOUTRP"), | ||
559 | SND_SOC_DAPM_OUTPUT("SPKDAT1L"), | ||
560 | SND_SOC_DAPM_OUTPUT("SPKDAT1R"), | ||
561 | SND_SOC_DAPM_OUTPUT("SPKDAT2L"), | ||
562 | SND_SOC_DAPM_OUTPUT("SPKDAT2R"), | ||
563 | }; | ||
564 | |||
565 | #define ARIZONA_MIXER_INPUT_ROUTES(name) \ | ||
566 | { name, "Noise Generator", "Noise Generator" }, \ | ||
567 | { name, "Tone Generator 1", "Tone Generator 1" }, \ | ||
568 | { name, "Tone Generator 2", "Tone Generator 2" }, \ | ||
569 | { name, "IN1L", "IN1L PGA" }, \ | ||
570 | { name, "IN1R", "IN1R PGA" }, \ | ||
571 | { name, "IN2L", "IN2L PGA" }, \ | ||
572 | { name, "IN2R", "IN2R PGA" }, \ | ||
573 | { name, "IN3L", "IN3L PGA" }, \ | ||
574 | { name, "IN3R", "IN3R PGA" }, \ | ||
575 | { name, "IN4L", "IN4L PGA" }, \ | ||
576 | { name, "IN4R", "IN4R PGA" }, \ | ||
577 | { name, "Mic Mute Mixer", "Mic Mute Mixer" }, \ | ||
578 | { name, "AIF1RX1", "AIF1RX1" }, \ | ||
579 | { name, "AIF1RX2", "AIF1RX2" }, \ | ||
580 | { name, "AIF1RX3", "AIF1RX3" }, \ | ||
581 | { name, "AIF1RX4", "AIF1RX4" }, \ | ||
582 | { name, "AIF1RX5", "AIF1RX5" }, \ | ||
583 | { name, "AIF1RX6", "AIF1RX6" }, \ | ||
584 | { name, "AIF1RX7", "AIF1RX7" }, \ | ||
585 | { name, "AIF1RX8", "AIF1RX8" }, \ | ||
586 | { name, "AIF2RX1", "AIF2RX1" }, \ | ||
587 | { name, "AIF2RX2", "AIF2RX2" }, \ | ||
588 | { name, "AIF3RX1", "AIF3RX1" }, \ | ||
589 | { name, "AIF3RX2", "AIF3RX2" }, \ | ||
590 | { name, "EQ1", "EQ1" }, \ | ||
591 | { name, "EQ2", "EQ2" }, \ | ||
592 | { name, "EQ3", "EQ3" }, \ | ||
593 | { name, "EQ4", "EQ4" }, \ | ||
594 | { name, "DRC1L", "DRC1L" }, \ | ||
595 | { name, "DRC1R", "DRC1R" }, \ | ||
596 | { name, "DRC2L", "DRC2L" }, \ | ||
597 | { name, "DRC2R", "DRC2R" }, \ | ||
598 | { name, "LHPF1", "LHPF1" }, \ | ||
599 | { name, "LHPF2", "LHPF2" }, \ | ||
600 | { name, "LHPF3", "LHPF3" }, \ | ||
601 | { name, "LHPF4", "LHPF4" }, \ | ||
602 | { name, "ASRC1L", "ASRC1L" }, \ | ||
603 | { name, "ASRC1R", "ASRC1R" }, \ | ||
604 | { name, "ASRC2L", "ASRC2L" }, \ | ||
605 | { name, "ASRC2R", "ASRC2R" } | ||
606 | |||
607 | static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | ||
608 | { "AIF2 Capture", NULL, "DBVDD2" }, | ||
609 | { "AIF2 Playback", NULL, "DBVDD2" }, | ||
610 | |||
611 | { "AIF3 Capture", NULL, "DBVDD3" }, | ||
612 | { "AIF3 Playback", NULL, "DBVDD3" }, | ||
613 | |||
614 | { "OUT1L", NULL, "CPVDD" }, | ||
615 | { "OUT1R", NULL, "CPVDD" }, | ||
616 | { "OUT2L", NULL, "CPVDD" }, | ||
617 | { "OUT2R", NULL, "CPVDD" }, | ||
618 | { "OUT3L", NULL, "CPVDD" }, | ||
619 | |||
620 | { "OUT4L", NULL, "SPKVDDL" }, | ||
621 | { "OUT4R", NULL, "SPKVDDR" }, | ||
622 | |||
623 | { "OUT1L", NULL, "SYSCLK" }, | ||
624 | { "OUT1R", NULL, "SYSCLK" }, | ||
625 | { "OUT2L", NULL, "SYSCLK" }, | ||
626 | { "OUT2R", NULL, "SYSCLK" }, | ||
627 | { "OUT3L", NULL, "SYSCLK" }, | ||
628 | { "OUT4L", NULL, "SYSCLK" }, | ||
629 | { "OUT4R", NULL, "SYSCLK" }, | ||
630 | { "OUT5L", NULL, "SYSCLK" }, | ||
631 | { "OUT5R", NULL, "SYSCLK" }, | ||
632 | { "OUT6L", NULL, "SYSCLK" }, | ||
633 | { "OUT6R", NULL, "SYSCLK" }, | ||
634 | |||
635 | { "MICBIAS1", NULL, "MICVDD" }, | ||
636 | { "MICBIAS2", NULL, "MICVDD" }, | ||
637 | { "MICBIAS3", NULL, "MICVDD" }, | ||
638 | |||
639 | { "Noise Generator", NULL, "NOISE" }, | ||
640 | { "Tone Generator 1", NULL, "TONE" }, | ||
641 | { "Tone Generator 2", NULL, "TONE" }, | ||
642 | |||
643 | { "Mic Mute Mixer", NULL, "Noise Mixer" }, | ||
644 | { "Mic Mute Mixer", NULL, "Mic Mixer" }, | ||
645 | |||
646 | { "AIF1 Capture", NULL, "AIF1TX1" }, | ||
647 | { "AIF1 Capture", NULL, "AIF1TX2" }, | ||
648 | { "AIF1 Capture", NULL, "AIF1TX3" }, | ||
649 | { "AIF1 Capture", NULL, "AIF1TX4" }, | ||
650 | { "AIF1 Capture", NULL, "AIF1TX5" }, | ||
651 | { "AIF1 Capture", NULL, "AIF1TX6" }, | ||
652 | { "AIF1 Capture", NULL, "AIF1TX7" }, | ||
653 | { "AIF1 Capture", NULL, "AIF1TX8" }, | ||
654 | |||
655 | { "AIF1RX1", NULL, "AIF1 Playback" }, | ||
656 | { "AIF1RX2", NULL, "AIF1 Playback" }, | ||
657 | { "AIF1RX3", NULL, "AIF1 Playback" }, | ||
658 | { "AIF1RX4", NULL, "AIF1 Playback" }, | ||
659 | { "AIF1RX5", NULL, "AIF1 Playback" }, | ||
660 | { "AIF1RX6", NULL, "AIF1 Playback" }, | ||
661 | { "AIF1RX7", NULL, "AIF1 Playback" }, | ||
662 | { "AIF1RX8", NULL, "AIF1 Playback" }, | ||
663 | |||
664 | { "AIF2 Capture", NULL, "AIF2TX1" }, | ||
665 | { "AIF2 Capture", NULL, "AIF2TX2" }, | ||
666 | |||
667 | { "AIF2RX1", NULL, "AIF2 Playback" }, | ||
668 | { "AIF2RX2", NULL, "AIF2 Playback" }, | ||
669 | |||
670 | { "AIF3 Capture", NULL, "AIF3TX1" }, | ||
671 | { "AIF3 Capture", NULL, "AIF3TX2" }, | ||
672 | |||
673 | { "AIF3RX1", NULL, "AIF3 Playback" }, | ||
674 | { "AIF3RX2", NULL, "AIF3 Playback" }, | ||
675 | |||
676 | { "AIF1 Playback", NULL, "SYSCLK" }, | ||
677 | { "AIF2 Playback", NULL, "SYSCLK" }, | ||
678 | { "AIF3 Playback", NULL, "SYSCLK" }, | ||
679 | |||
680 | { "AIF1 Capture", NULL, "SYSCLK" }, | ||
681 | { "AIF2 Capture", NULL, "SYSCLK" }, | ||
682 | { "AIF3 Capture", NULL, "SYSCLK" }, | ||
683 | |||
684 | ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), | ||
685 | ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), | ||
686 | ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), | ||
687 | ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"), | ||
688 | ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"), | ||
689 | |||
690 | ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"), | ||
691 | ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"), | ||
692 | ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"), | ||
693 | ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"), | ||
694 | ARIZONA_MIXER_ROUTES("OUT6L", "SPKDAT2L"), | ||
695 | ARIZONA_MIXER_ROUTES("OUT6R", "SPKDAT2R"), | ||
696 | |||
697 | ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"), | ||
698 | ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"), | ||
699 | |||
700 | ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), | ||
701 | ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), | ||
702 | ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), | ||
703 | ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), | ||
704 | ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), | ||
705 | ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), | ||
706 | ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), | ||
707 | ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), | ||
708 | |||
709 | ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), | ||
710 | ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), | ||
711 | |||
712 | ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), | ||
713 | ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), | ||
714 | |||
715 | ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), | ||
716 | ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), | ||
717 | ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), | ||
718 | ARIZONA_MIXER_ROUTES("EQ4", "EQ4"), | ||
719 | |||
720 | ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"), | ||
721 | ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"), | ||
722 | ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"), | ||
723 | ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"), | ||
724 | |||
725 | ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"), | ||
726 | ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"), | ||
727 | ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), | ||
728 | ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), | ||
729 | |||
730 | ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"), | ||
731 | ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"), | ||
732 | ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), | ||
733 | ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), | ||
734 | |||
735 | { "HPOUT1L", NULL, "OUT1L" }, | ||
736 | { "HPOUT1R", NULL, "OUT1R" }, | ||
737 | |||
738 | { "HPOUT2L", NULL, "OUT2L" }, | ||
739 | { "HPOUT2R", NULL, "OUT2R" }, | ||
740 | |||
741 | { "EPOUTN", NULL, "OUT3L" }, | ||
742 | { "EPOUTP", NULL, "OUT3L" }, | ||
743 | |||
744 | { "SPKOUTLN", NULL, "OUT4L" }, | ||
745 | { "SPKOUTLP", NULL, "OUT4L" }, | ||
746 | |||
747 | { "SPKOUTRN", NULL, "OUT4R" }, | ||
748 | { "SPKOUTRP", NULL, "OUT4R" }, | ||
749 | |||
750 | { "SPKDAT1L", NULL, "OUT5L" }, | ||
751 | { "SPKDAT1R", NULL, "OUT5R" }, | ||
752 | |||
753 | { "SPKDAT2L", NULL, "OUT6L" }, | ||
754 | { "SPKDAT2R", NULL, "OUT6R" }, | ||
755 | }; | ||
756 | |||
757 | static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | ||
758 | unsigned int Fref, unsigned int Fout) | ||
759 | { | ||
760 | struct wm5110_priv *wm5110 = snd_soc_codec_get_drvdata(codec); | ||
761 | |||
762 | switch (fll_id) { | ||
763 | case WM5110_FLL1: | ||
764 | return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout); | ||
765 | case WM5110_FLL2: | ||
766 | return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout); | ||
767 | default: | ||
768 | return -EINVAL; | ||
769 | } | ||
770 | } | ||
771 | |||
772 | #define WM5110_RATES SNDRV_PCM_RATE_8000_192000 | ||
773 | |||
774 | #define WM5110_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
775 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
776 | |||
777 | static struct snd_soc_dai_driver wm5110_dai[] = { | ||
778 | { | ||
779 | .name = "wm5110-aif1", | ||
780 | .id = 1, | ||
781 | .base = ARIZONA_AIF1_BCLK_CTRL, | ||
782 | .playback = { | ||
783 | .stream_name = "AIF1 Playback", | ||
784 | .channels_min = 1, | ||
785 | .channels_max = 8, | ||
786 | .rates = WM5110_RATES, | ||
787 | .formats = WM5110_FORMATS, | ||
788 | }, | ||
789 | .capture = { | ||
790 | .stream_name = "AIF1 Capture", | ||
791 | .channels_min = 1, | ||
792 | .channels_max = 8, | ||
793 | .rates = WM5110_RATES, | ||
794 | .formats = WM5110_FORMATS, | ||
795 | }, | ||
796 | .ops = &arizona_dai_ops, | ||
797 | .symmetric_rates = 1, | ||
798 | }, | ||
799 | { | ||
800 | .name = "wm5110-aif2", | ||
801 | .id = 2, | ||
802 | .base = ARIZONA_AIF2_BCLK_CTRL, | ||
803 | .playback = { | ||
804 | .stream_name = "AIF2 Playback", | ||
805 | .channels_min = 1, | ||
806 | .channels_max = 2, | ||
807 | .rates = WM5110_RATES, | ||
808 | .formats = WM5110_FORMATS, | ||
809 | }, | ||
810 | .capture = { | ||
811 | .stream_name = "AIF2 Capture", | ||
812 | .channels_min = 1, | ||
813 | .channels_max = 2, | ||
814 | .rates = WM5110_RATES, | ||
815 | .formats = WM5110_FORMATS, | ||
816 | }, | ||
817 | .ops = &arizona_dai_ops, | ||
818 | .symmetric_rates = 1, | ||
819 | }, | ||
820 | { | ||
821 | .name = "wm5110-aif3", | ||
822 | .id = 3, | ||
823 | .base = ARIZONA_AIF3_BCLK_CTRL, | ||
824 | .playback = { | ||
825 | .stream_name = "AIF3 Playback", | ||
826 | .channels_min = 1, | ||
827 | .channels_max = 2, | ||
828 | .rates = WM5110_RATES, | ||
829 | .formats = WM5110_FORMATS, | ||
830 | }, | ||
831 | .capture = { | ||
832 | .stream_name = "AIF3 Capture", | ||
833 | .channels_min = 1, | ||
834 | .channels_max = 2, | ||
835 | .rates = WM5110_RATES, | ||
836 | .formats = WM5110_FORMATS, | ||
837 | }, | ||
838 | .ops = &arizona_dai_ops, | ||
839 | .symmetric_rates = 1, | ||
840 | }, | ||
841 | }; | ||
842 | |||
843 | static int wm5110_codec_probe(struct snd_soc_codec *codec) | ||
844 | { | ||
845 | struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
846 | |||
847 | codec->control_data = priv->core.arizona->regmap; | ||
848 | return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); | ||
849 | } | ||
850 | |||
851 | #define WM5110_DIG_VU 0x0200 | ||
852 | |||
853 | static unsigned int wm5110_digital_vu[] = { | ||
854 | ARIZONA_ADC_DIGITAL_VOLUME_1L, | ||
855 | ARIZONA_ADC_DIGITAL_VOLUME_1R, | ||
856 | ARIZONA_ADC_DIGITAL_VOLUME_2L, | ||
857 | ARIZONA_ADC_DIGITAL_VOLUME_2R, | ||
858 | ARIZONA_ADC_DIGITAL_VOLUME_3L, | ||
859 | ARIZONA_ADC_DIGITAL_VOLUME_3R, | ||
860 | |||
861 | ARIZONA_DAC_DIGITAL_VOLUME_1L, | ||
862 | ARIZONA_DAC_DIGITAL_VOLUME_1R, | ||
863 | ARIZONA_DAC_DIGITAL_VOLUME_2L, | ||
864 | ARIZONA_DAC_DIGITAL_VOLUME_2R, | ||
865 | ARIZONA_DAC_DIGITAL_VOLUME_3L, | ||
866 | ARIZONA_DAC_DIGITAL_VOLUME_3R, | ||
867 | ARIZONA_DAC_DIGITAL_VOLUME_4L, | ||
868 | ARIZONA_DAC_DIGITAL_VOLUME_4R, | ||
869 | ARIZONA_DAC_DIGITAL_VOLUME_5L, | ||
870 | ARIZONA_DAC_DIGITAL_VOLUME_5R, | ||
871 | }; | ||
872 | |||
873 | static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { | ||
874 | .probe = wm5110_codec_probe, | ||
875 | |||
876 | .idle_bias_off = true, | ||
877 | |||
878 | .set_sysclk = arizona_set_sysclk, | ||
879 | .set_pll = wm5110_set_fll, | ||
880 | |||
881 | .controls = wm5110_snd_controls, | ||
882 | .num_controls = ARRAY_SIZE(wm5110_snd_controls), | ||
883 | .dapm_widgets = wm5110_dapm_widgets, | ||
884 | .num_dapm_widgets = ARRAY_SIZE(wm5110_dapm_widgets), | ||
885 | .dapm_routes = wm5110_dapm_routes, | ||
886 | .num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes), | ||
887 | }; | ||
888 | |||
889 | static int __devinit wm5110_probe(struct platform_device *pdev) | ||
890 | { | ||
891 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | ||
892 | struct wm5110_priv *wm5110; | ||
893 | int i; | ||
894 | |||
895 | wm5110 = devm_kzalloc(&pdev->dev, sizeof(struct wm5110_priv), | ||
896 | GFP_KERNEL); | ||
897 | if (wm5110 == NULL) | ||
898 | return -ENOMEM; | ||
899 | platform_set_drvdata(pdev, wm5110); | ||
900 | |||
901 | wm5110->core.arizona = arizona; | ||
902 | |||
903 | for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++) | ||
904 | wm5110->fll[i].vco_mult = 3; | ||
905 | |||
906 | arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1, | ||
907 | ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK, | ||
908 | &wm5110->fll[0]); | ||
909 | arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1, | ||
910 | ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK, | ||
911 | &wm5110->fll[1]); | ||
912 | |||
913 | for (i = 0; i < ARRAY_SIZE(wm5110_dai); i++) | ||
914 | arizona_init_dai(&wm5110->core, i); | ||
915 | |||
916 | /* Latch volume update bits */ | ||
917 | for (i = 0; i < ARRAY_SIZE(wm5110_digital_vu); i++) | ||
918 | regmap_update_bits(arizona->regmap, wm5110_digital_vu[i], | ||
919 | WM5110_DIG_VU, WM5110_DIG_VU); | ||
920 | |||
921 | pm_runtime_enable(&pdev->dev); | ||
922 | pm_runtime_idle(&pdev->dev); | ||
923 | |||
924 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110, | ||
925 | wm5110_dai, ARRAY_SIZE(wm5110_dai)); | ||
926 | } | ||
927 | |||
928 | static int __devexit wm5110_remove(struct platform_device *pdev) | ||
929 | { | ||
930 | snd_soc_unregister_codec(&pdev->dev); | ||
931 | pm_runtime_disable(&pdev->dev); | ||
932 | |||
933 | return 0; | ||
934 | } | ||
935 | |||
936 | static struct platform_driver wm5110_codec_driver = { | ||
937 | .driver = { | ||
938 | .name = "wm5110-codec", | ||
939 | .owner = THIS_MODULE, | ||
940 | }, | ||
941 | .probe = wm5110_probe, | ||
942 | .remove = __devexit_p(wm5110_remove), | ||
943 | }; | ||
944 | |||
945 | module_platform_driver(wm5110_codec_driver); | ||
946 | |||
947 | MODULE_DESCRIPTION("ASoC WM5110 driver"); | ||
948 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
949 | MODULE_LICENSE("GPL"); | ||
950 | MODULE_ALIAS("platform:wm5110-codec"); | ||
diff --git a/sound/soc/codecs/wm5110.h b/sound/soc/codecs/wm5110.h new file mode 100644 index 000000000000..75e9351ccab0 --- /dev/null +++ b/sound/soc/codecs/wm5110.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * wm5110.h -- WM5110 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef _WM5110_H | ||
14 | #define _WM5110_H | ||
15 | |||
16 | #include "arizona.h" | ||
17 | |||
18 | #define WM5110_FLL1 1 | ||
19 | #define WM5110_FLL2 2 | ||
20 | |||
21 | #endif | ||
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 555ee146ae0d..d26c8ae4e6d9 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8350.c -- WM8350 ALSA SoC audio driver | 2 | * wm8350.c -- WM8350 ALSA SoC audio driver |
3 | * | 3 | * |
4 | * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC. | 4 | * Copyright (C) 2007-12 Wolfson Microelectronics PLC. |
5 | * | 5 | * |
6 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> | 6 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
7 | * | 7 | * |
@@ -71,20 +71,6 @@ struct wm8350_data { | |||
71 | int fll_freq_in; | 71 | int fll_freq_in; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static unsigned int wm8350_codec_read(struct snd_soc_codec *codec, | ||
75 | unsigned int reg) | ||
76 | { | ||
77 | struct wm8350 *wm8350 = codec->control_data; | ||
78 | return wm8350_reg_read(wm8350, reg); | ||
79 | } | ||
80 | |||
81 | static int wm8350_codec_write(struct snd_soc_codec *codec, unsigned int reg, | ||
82 | unsigned int value) | ||
83 | { | ||
84 | struct wm8350 *wm8350 = codec->control_data; | ||
85 | return wm8350_reg_write(wm8350, reg, value); | ||
86 | } | ||
87 | |||
88 | /* | 74 | /* |
89 | * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown. | 75 | * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown. |
90 | */ | 76 | */ |
@@ -1519,7 +1505,9 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) | |||
1519 | if (ret != 0) | 1505 | if (ret != 0) |
1520 | return ret; | 1506 | return ret; |
1521 | 1507 | ||
1522 | codec->control_data = wm8350; | 1508 | codec->control_data = wm8350->regmap; |
1509 | |||
1510 | snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); | ||
1523 | 1511 | ||
1524 | /* Put the codec into reset if it wasn't already */ | 1512 | /* Put the codec into reset if it wasn't already */ |
1525 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1513 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
@@ -1629,8 +1617,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { | |||
1629 | .remove = wm8350_codec_remove, | 1617 | .remove = wm8350_codec_remove, |
1630 | .suspend = wm8350_suspend, | 1618 | .suspend = wm8350_suspend, |
1631 | .resume = wm8350_resume, | 1619 | .resume = wm8350_resume, |
1632 | .read = wm8350_codec_read, | ||
1633 | .write = wm8350_codec_write, | ||
1634 | .set_bias_level = wm8350_set_bias_level, | 1620 | .set_bias_level = wm8350_set_bias_level, |
1635 | 1621 | ||
1636 | .controls = wm8350_snd_controls, | 1622 | .controls = wm8350_snd_controls, |
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 5dc31ebcd0e7..5d277a915f81 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8400.c -- WM8400 ALSA Soc Audio driver | 2 | * wm8400.c -- WM8400 ALSA Soc Audio driver |
3 | * | 3 | * |
4 | * Copyright 2008, 2009 Wolfson Microelectronics PLC. | 4 | * Copyright 2008-11 Wolfson Microelectronics PLC. |
5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 211285164d70..7c68226376e4 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8580.c -- WM8580 ALSA Soc Audio driver | 2 | * wm8580.c -- WM8580 ALSA Soc Audio driver |
3 | * | 3 | * |
4 | * Copyright 2008, 2009 Wolfson Microelectronics PLC. | 4 | * Copyright 2008-11 Wolfson Microelectronics PLC. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 7 | * under the terms of the GNU General Public License as published by the |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 9d1b9b0271f1..bb1d26919b10 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * wm8731.c -- WM8731 ALSA SoC Audio driver | 2 | * wm8731.c -- WM8731 ALSA SoC Audio driver |
3 | * | 3 | * |
4 | * Copyright 2005 Openedhand Ltd. | 4 | * Copyright 2005 Openedhand Ltd. |
5 | * Copyright 2006-12 Wolfson Microelectronics, plc | ||
5 | * | 6 | * |
6 | * Author: Richard Purdie <richard@openedhand.com> | 7 | * Author: Richard Purdie <richard@openedhand.com> |
7 | * | 8 | * |
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 6e849cb04243..35f3d23200e0 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8741.c -- WM8741 ALSA SoC Audio driver | 2 | * wm8741.c -- WM8741 ALSA SoC Audio driver |
3 | * | 3 | * |
4 | * Copyright 2010 Wolfson Microelectronics plc | 4 | * Copyright 2010-1 Wolfson Microelectronics plc |
5 | * | 5 | * |
6 | * Author: Ian Lartey <ian@opensource.wolfsonmicro.com> | 6 | * Author: Ian Lartey <ian@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index a26482cd7654..13bff87ddcf5 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8753.c -- WM8753 ALSA Soc Audio driver | 2 | * wm8753.c -- WM8753 ALSA Soc Audio driver |
3 | * | 3 | * |
4 | * Copyright 2003 Wolfson Microelectronics PLC. | 4 | * Copyright 2003-11 Wolfson Microelectronics PLC. |
5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> | 5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index a19db5a0a17a..879c356a9045 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8776.c -- WM8776 ALSA SoC Audio driver | 2 | * wm8776.c -- WM8776 ALSA SoC Audio driver |
3 | * | 3 | * |
4 | * Copyright 2009 Wolfson Microelectronics plc | 4 | * Copyright 2009-12 Wolfson Microelectronics plc |
5 | * | 5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 6bd1b767b138..c088020172ab 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8804.c -- WM8804 S/PDIF transceiver driver | 2 | * wm8804.c -- WM8804 S/PDIF transceiver driver |
3 | * | 3 | * |
4 | * Copyright 2010 Wolfson Microelectronics plc | 4 | * Copyright 2010-11 Wolfson Microelectronics plc |
5 | * | 5 | * |
6 | * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> | 6 | * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 86b8a2926591..73f1c8d7bafb 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * wm8903.c -- WM8903 ALSA SoC Audio driver | 2 | * wm8903.c -- WM8903 ALSA SoC Audio driver |
3 | * | 3 | * |
4 | * Copyright 2008 Wolfson Microelectronics | 4 | * Copyright 2008-12 Wolfson Microelectronics |
5 | * Copyright 2011 NVIDIA, Inc. | 5 | * Copyright 2011-2012 NVIDIA, Inc. |
6 | * | 6 | * |
7 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 7 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
8 | * | 8 | * |
@@ -116,6 +116,7 @@ static const struct reg_default wm8903_reg_defaults[] = { | |||
116 | 116 | ||
117 | struct wm8903_priv { | 117 | struct wm8903_priv { |
118 | struct wm8903_platform_data *pdata; | 118 | struct wm8903_platform_data *pdata; |
119 | struct device *dev; | ||
119 | struct snd_soc_codec *codec; | 120 | struct snd_soc_codec *codec; |
120 | struct regmap *regmap; | 121 | struct regmap *regmap; |
121 | 122 | ||
@@ -1635,17 +1636,27 @@ EXPORT_SYMBOL_GPL(wm8903_mic_detect); | |||
1635 | 1636 | ||
1636 | static irqreturn_t wm8903_irq(int irq, void *data) | 1637 | static irqreturn_t wm8903_irq(int irq, void *data) |
1637 | { | 1638 | { |
1638 | struct snd_soc_codec *codec = data; | 1639 | struct wm8903_priv *wm8903 = data; |
1639 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 1640 | int mic_report, ret; |
1640 | int mic_report; | 1641 | unsigned int int_val, mask, int_pol; |
1641 | int int_pol; | ||
1642 | int int_val = 0; | ||
1643 | int mask = ~snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1_MASK); | ||
1644 | 1642 | ||
1645 | int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask; | 1643 | ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_STATUS_1_MASK, |
1644 | &mask); | ||
1645 | if (ret != 0) { | ||
1646 | dev_err(wm8903->dev, "Failed to read IRQ mask: %d\n", ret); | ||
1647 | return IRQ_NONE; | ||
1648 | } | ||
1649 | |||
1650 | ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_STATUS_1, &int_val); | ||
1651 | if (ret != 0) { | ||
1652 | dev_err(wm8903->dev, "Failed to read IRQ status: %d\n", ret); | ||
1653 | return IRQ_NONE; | ||
1654 | } | ||
1655 | |||
1656 | int_val &= ~mask; | ||
1646 | 1657 | ||
1647 | if (int_val & WM8903_WSEQ_BUSY_EINT) { | 1658 | if (int_val & WM8903_WSEQ_BUSY_EINT) { |
1648 | dev_warn(codec->dev, "Write sequencer done\n"); | 1659 | dev_warn(wm8903->dev, "Write sequencer done\n"); |
1649 | } | 1660 | } |
1650 | 1661 | ||
1651 | /* | 1662 | /* |
@@ -1656,22 +1667,28 @@ static irqreturn_t wm8903_irq(int irq, void *data) | |||
1656 | * the polarity register. | 1667 | * the polarity register. |
1657 | */ | 1668 | */ |
1658 | mic_report = wm8903->mic_last_report; | 1669 | mic_report = wm8903->mic_last_report; |
1659 | int_pol = snd_soc_read(codec, WM8903_INTERRUPT_POLARITY_1); | 1670 | ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_POLARITY_1, |
1671 | &int_pol); | ||
1672 | if (ret != 0) { | ||
1673 | dev_err(wm8903->dev, "Failed to read interrupt polarity: %d\n", | ||
1674 | ret); | ||
1675 | return IRQ_HANDLED; | ||
1676 | } | ||
1660 | 1677 | ||
1661 | #ifndef CONFIG_SND_SOC_WM8903_MODULE | 1678 | #ifndef CONFIG_SND_SOC_WM8903_MODULE |
1662 | if (int_val & (WM8903_MICSHRT_EINT | WM8903_MICDET_EINT)) | 1679 | if (int_val & (WM8903_MICSHRT_EINT | WM8903_MICDET_EINT)) |
1663 | trace_snd_soc_jack_irq(dev_name(codec->dev)); | 1680 | trace_snd_soc_jack_irq(dev_name(wm8903->dev)); |
1664 | #endif | 1681 | #endif |
1665 | 1682 | ||
1666 | if (int_val & WM8903_MICSHRT_EINT) { | 1683 | if (int_val & WM8903_MICSHRT_EINT) { |
1667 | dev_dbg(codec->dev, "Microphone short (pol=%x)\n", int_pol); | 1684 | dev_dbg(wm8903->dev, "Microphone short (pol=%x)\n", int_pol); |
1668 | 1685 | ||
1669 | mic_report ^= wm8903->mic_short; | 1686 | mic_report ^= wm8903->mic_short; |
1670 | int_pol ^= WM8903_MICSHRT_INV; | 1687 | int_pol ^= WM8903_MICSHRT_INV; |
1671 | } | 1688 | } |
1672 | 1689 | ||
1673 | if (int_val & WM8903_MICDET_EINT) { | 1690 | if (int_val & WM8903_MICDET_EINT) { |
1674 | dev_dbg(codec->dev, "Microphone detect (pol=%x)\n", int_pol); | 1691 | dev_dbg(wm8903->dev, "Microphone detect (pol=%x)\n", int_pol); |
1675 | 1692 | ||
1676 | mic_report ^= wm8903->mic_det; | 1693 | mic_report ^= wm8903->mic_det; |
1677 | int_pol ^= WM8903_MICDET_INV; | 1694 | int_pol ^= WM8903_MICDET_INV; |
@@ -1679,8 +1696,8 @@ static irqreturn_t wm8903_irq(int irq, void *data) | |||
1679 | msleep(wm8903->mic_delay); | 1696 | msleep(wm8903->mic_delay); |
1680 | } | 1697 | } |
1681 | 1698 | ||
1682 | snd_soc_update_bits(codec, WM8903_INTERRUPT_POLARITY_1, | 1699 | regmap_update_bits(wm8903->regmap, WM8903_INTERRUPT_POLARITY_1, |
1683 | WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol); | 1700 | WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol); |
1684 | 1701 | ||
1685 | snd_soc_jack_report(wm8903->mic_jack, mic_report, | 1702 | snd_soc_jack_report(wm8903->mic_jack, mic_report, |
1686 | wm8903->mic_short | wm8903->mic_det); | 1703 | wm8903->mic_short | wm8903->mic_det); |
@@ -1774,7 +1791,6 @@ static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset) | |||
1774 | static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) | 1791 | static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) |
1775 | { | 1792 | { |
1776 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); | 1793 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); |
1777 | struct snd_soc_codec *codec = wm8903->codec; | ||
1778 | unsigned int mask, val; | 1794 | unsigned int mask, val; |
1779 | int ret; | 1795 | int ret; |
1780 | 1796 | ||
@@ -1782,8 +1798,8 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) | |||
1782 | val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) | | 1798 | val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) | |
1783 | WM8903_GP1_DIR; | 1799 | WM8903_GP1_DIR; |
1784 | 1800 | ||
1785 | ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, | 1801 | ret = regmap_update_bits(wm8903->regmap, |
1786 | mask, val); | 1802 | WM8903_GPIO_CONTROL_1 + offset, mask, val); |
1787 | if (ret < 0) | 1803 | if (ret < 0) |
1788 | return ret; | 1804 | return ret; |
1789 | 1805 | ||
@@ -1793,10 +1809,9 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) | |||
1793 | static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) | 1809 | static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) |
1794 | { | 1810 | { |
1795 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); | 1811 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); |
1796 | struct snd_soc_codec *codec = wm8903->codec; | 1812 | unsigned int reg; |
1797 | int reg; | ||
1798 | 1813 | ||
1799 | reg = snd_soc_read(codec, WM8903_GPIO_CONTROL_1 + offset); | 1814 | regmap_read(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, ®); |
1800 | 1815 | ||
1801 | return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT; | 1816 | return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT; |
1802 | } | 1817 | } |
@@ -1805,7 +1820,6 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip, | |||
1805 | unsigned offset, int value) | 1820 | unsigned offset, int value) |
1806 | { | 1821 | { |
1807 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); | 1822 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); |
1808 | struct snd_soc_codec *codec = wm8903->codec; | ||
1809 | unsigned int mask, val; | 1823 | unsigned int mask, val; |
1810 | int ret; | 1824 | int ret; |
1811 | 1825 | ||
@@ -1813,8 +1827,8 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip, | |||
1813 | val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) | | 1827 | val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) | |
1814 | (value << WM8903_GP2_LVL_SHIFT); | 1828 | (value << WM8903_GP2_LVL_SHIFT); |
1815 | 1829 | ||
1816 | ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, | 1830 | ret = regmap_update_bits(wm8903->regmap, |
1817 | mask, val); | 1831 | WM8903_GPIO_CONTROL_1 + offset, mask, val); |
1818 | if (ret < 0) | 1832 | if (ret < 0) |
1819 | return ret; | 1833 | return ret; |
1820 | 1834 | ||
@@ -1824,11 +1838,10 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip, | |||
1824 | static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | 1838 | static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) |
1825 | { | 1839 | { |
1826 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); | 1840 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); |
1827 | struct snd_soc_codec *codec = wm8903->codec; | ||
1828 | 1841 | ||
1829 | snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, | 1842 | regmap_update_bits(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, |
1830 | WM8903_GP1_LVL_MASK, | 1843 | WM8903_GP1_LVL_MASK, |
1831 | !!value << WM8903_GP1_LVL_SHIFT); | 1844 | !!value << WM8903_GP1_LVL_SHIFT); |
1832 | } | 1845 | } |
1833 | 1846 | ||
1834 | static struct gpio_chip wm8903_template_chip = { | 1847 | static struct gpio_chip wm8903_template_chip = { |
@@ -1842,15 +1855,14 @@ static struct gpio_chip wm8903_template_chip = { | |||
1842 | .can_sleep = 1, | 1855 | .can_sleep = 1, |
1843 | }; | 1856 | }; |
1844 | 1857 | ||
1845 | static void wm8903_init_gpio(struct snd_soc_codec *codec) | 1858 | static void wm8903_init_gpio(struct wm8903_priv *wm8903) |
1846 | { | 1859 | { |
1847 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
1848 | struct wm8903_platform_data *pdata = wm8903->pdata; | 1860 | struct wm8903_platform_data *pdata = wm8903->pdata; |
1849 | int ret; | 1861 | int ret; |
1850 | 1862 | ||
1851 | wm8903->gpio_chip = wm8903_template_chip; | 1863 | wm8903->gpio_chip = wm8903_template_chip; |
1852 | wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO; | 1864 | wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO; |
1853 | wm8903->gpio_chip.dev = codec->dev; | 1865 | wm8903->gpio_chip.dev = wm8903->dev; |
1854 | 1866 | ||
1855 | if (pdata->gpio_base) | 1867 | if (pdata->gpio_base) |
1856 | wm8903->gpio_chip.base = pdata->gpio_base; | 1868 | wm8903->gpio_chip.base = pdata->gpio_base; |
@@ -1859,24 +1871,23 @@ static void wm8903_init_gpio(struct snd_soc_codec *codec) | |||
1859 | 1871 | ||
1860 | ret = gpiochip_add(&wm8903->gpio_chip); | 1872 | ret = gpiochip_add(&wm8903->gpio_chip); |
1861 | if (ret != 0) | 1873 | if (ret != 0) |
1862 | dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); | 1874 | dev_err(wm8903->dev, "Failed to add GPIOs: %d\n", ret); |
1863 | } | 1875 | } |
1864 | 1876 | ||
1865 | static void wm8903_free_gpio(struct snd_soc_codec *codec) | 1877 | static void wm8903_free_gpio(struct wm8903_priv *wm8903) |
1866 | { | 1878 | { |
1867 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
1868 | int ret; | 1879 | int ret; |
1869 | 1880 | ||
1870 | ret = gpiochip_remove(&wm8903->gpio_chip); | 1881 | ret = gpiochip_remove(&wm8903->gpio_chip); |
1871 | if (ret != 0) | 1882 | if (ret != 0) |
1872 | dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); | 1883 | dev_err(wm8903->dev, "Failed to remove GPIOs: %d\n", ret); |
1873 | } | 1884 | } |
1874 | #else | 1885 | #else |
1875 | static void wm8903_init_gpio(struct snd_soc_codec *codec) | 1886 | static void wm8903_init_gpio(struct wm8903_priv *wm8903) |
1876 | { | 1887 | { |
1877 | } | 1888 | } |
1878 | 1889 | ||
1879 | static void wm8903_free_gpio(struct snd_soc_codec *codec) | 1890 | static void wm8903_free_gpio(struct wm8903_priv *wm8903) |
1880 | { | 1891 | { |
1881 | } | 1892 | } |
1882 | #endif | 1893 | #endif |
@@ -1884,11 +1895,7 @@ static void wm8903_free_gpio(struct snd_soc_codec *codec) | |||
1884 | static int wm8903_probe(struct snd_soc_codec *codec) | 1895 | static int wm8903_probe(struct snd_soc_codec *codec) |
1885 | { | 1896 | { |
1886 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 1897 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1887 | struct wm8903_platform_data *pdata = wm8903->pdata; | 1898 | int ret; |
1888 | int ret, i; | ||
1889 | int trigger, irq_pol; | ||
1890 | u16 val; | ||
1891 | bool mic_gpio = false; | ||
1892 | 1899 | ||
1893 | wm8903->codec = codec; | 1900 | wm8903->codec = codec; |
1894 | codec->control_data = wm8903->regmap; | 1901 | codec->control_data = wm8903->regmap; |
@@ -1899,121 +1906,16 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
1899 | return ret; | 1906 | return ret; |
1900 | } | 1907 | } |
1901 | 1908 | ||
1902 | /* Set up GPIOs, detect if any are MIC detect outputs */ | ||
1903 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { | ||
1904 | if ((!pdata->gpio_cfg[i]) || | ||
1905 | (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO)) | ||
1906 | continue; | ||
1907 | |||
1908 | snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i, | ||
1909 | pdata->gpio_cfg[i] & 0x7fff); | ||
1910 | |||
1911 | val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK) | ||
1912 | >> WM8903_GP1_FN_SHIFT; | ||
1913 | |||
1914 | switch (val) { | ||
1915 | case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT: | ||
1916 | case WM8903_GPn_FN_MICBIAS_SHORT_DETECT: | ||
1917 | mic_gpio = true; | ||
1918 | break; | ||
1919 | default: | ||
1920 | break; | ||
1921 | } | ||
1922 | } | ||
1923 | |||
1924 | /* Set up microphone detection */ | ||
1925 | snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, | ||
1926 | pdata->micdet_cfg); | ||
1927 | |||
1928 | /* Microphone detection needs the WSEQ clock */ | ||
1929 | if (pdata->micdet_cfg) | ||
1930 | snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, | ||
1931 | WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); | ||
1932 | |||
1933 | /* If microphone detection is enabled by pdata but | ||
1934 | * detected via IRQ then interrupts can be lost before | ||
1935 | * the machine driver has set up microphone detection | ||
1936 | * IRQs as the IRQs are clear on read. The detection | ||
1937 | * will be enabled when the machine driver configures. | ||
1938 | */ | ||
1939 | WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA)); | ||
1940 | |||
1941 | wm8903->mic_delay = pdata->micdet_delay; | ||
1942 | |||
1943 | if (wm8903->irq) { | ||
1944 | if (pdata->irq_active_low) { | ||
1945 | trigger = IRQF_TRIGGER_LOW; | ||
1946 | irq_pol = WM8903_IRQ_POL; | ||
1947 | } else { | ||
1948 | trigger = IRQF_TRIGGER_HIGH; | ||
1949 | irq_pol = 0; | ||
1950 | } | ||
1951 | |||
1952 | snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL, | ||
1953 | WM8903_IRQ_POL, irq_pol); | ||
1954 | |||
1955 | ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq, | ||
1956 | trigger | IRQF_ONESHOT, | ||
1957 | "wm8903", codec); | ||
1958 | if (ret != 0) { | ||
1959 | dev_err(codec->dev, "Failed to request IRQ: %d\n", | ||
1960 | ret); | ||
1961 | return ret; | ||
1962 | } | ||
1963 | |||
1964 | /* Enable write sequencer interrupts */ | ||
1965 | snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK, | ||
1966 | WM8903_IM_WSEQ_BUSY_EINT, 0); | ||
1967 | } | ||
1968 | |||
1969 | /* power on device */ | 1909 | /* power on device */ |
1970 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1910 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1971 | 1911 | ||
1972 | /* Latch volume update bits */ | ||
1973 | val = snd_soc_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT); | ||
1974 | val |= WM8903_ADCVU; | ||
1975 | snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val); | ||
1976 | snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val); | ||
1977 | |||
1978 | val = snd_soc_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT); | ||
1979 | val |= WM8903_DACVU; | ||
1980 | snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val); | ||
1981 | snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val); | ||
1982 | |||
1983 | val = snd_soc_read(codec, WM8903_ANALOGUE_OUT1_LEFT); | ||
1984 | val |= WM8903_HPOUTVU; | ||
1985 | snd_soc_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val); | ||
1986 | snd_soc_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val); | ||
1987 | |||
1988 | val = snd_soc_read(codec, WM8903_ANALOGUE_OUT2_LEFT); | ||
1989 | val |= WM8903_LINEOUTVU; | ||
1990 | snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val); | ||
1991 | snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val); | ||
1992 | |||
1993 | val = snd_soc_read(codec, WM8903_ANALOGUE_OUT3_LEFT); | ||
1994 | val |= WM8903_SPKVU; | ||
1995 | snd_soc_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val); | ||
1996 | snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); | ||
1997 | |||
1998 | /* Enable DAC soft mute by default */ | ||
1999 | snd_soc_update_bits(codec, WM8903_DAC_DIGITAL_1, | ||
2000 | WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE, | ||
2001 | WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE); | ||
2002 | |||
2003 | wm8903_init_gpio(codec); | ||
2004 | |||
2005 | return ret; | 1912 | return ret; |
2006 | } | 1913 | } |
2007 | 1914 | ||
2008 | /* power down chip */ | 1915 | /* power down chip */ |
2009 | static int wm8903_remove(struct snd_soc_codec *codec) | 1916 | static int wm8903_remove(struct snd_soc_codec *codec) |
2010 | { | 1917 | { |
2011 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
2012 | |||
2013 | wm8903_free_gpio(codec); | ||
2014 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1918 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2015 | if (wm8903->irq) | ||
2016 | free_irq(wm8903->irq, codec); | ||
2017 | 1919 | ||
2018 | return 0; | 1920 | return 0; |
2019 | } | 1921 | } |
@@ -2123,15 +2025,18 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
2123 | { | 2025 | { |
2124 | struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); | 2026 | struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); |
2125 | struct wm8903_priv *wm8903; | 2027 | struct wm8903_priv *wm8903; |
2126 | unsigned int val; | 2028 | int trigger; |
2127 | int ret; | 2029 | bool mic_gpio = false; |
2030 | unsigned int val, irq_pol; | ||
2031 | int ret, i; | ||
2128 | 2032 | ||
2129 | wm8903 = devm_kzalloc(&i2c->dev, sizeof(struct wm8903_priv), | 2033 | wm8903 = devm_kzalloc(&i2c->dev, sizeof(struct wm8903_priv), |
2130 | GFP_KERNEL); | 2034 | GFP_KERNEL); |
2131 | if (wm8903 == NULL) | 2035 | if (wm8903 == NULL) |
2132 | return -ENOMEM; | 2036 | return -ENOMEM; |
2037 | wm8903->dev = &i2c->dev; | ||
2133 | 2038 | ||
2134 | wm8903->regmap = regmap_init_i2c(i2c, &wm8903_regmap); | 2039 | wm8903->regmap = devm_regmap_init_i2c(i2c, &wm8903_regmap); |
2135 | if (IS_ERR(wm8903->regmap)) { | 2040 | if (IS_ERR(wm8903->regmap)) { |
2136 | ret = PTR_ERR(wm8903->regmap); | 2041 | ret = PTR_ERR(wm8903->regmap); |
2137 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 2042 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
@@ -2140,7 +2045,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
2140 | } | 2045 | } |
2141 | 2046 | ||
2142 | i2c_set_clientdata(i2c, wm8903); | 2047 | i2c_set_clientdata(i2c, wm8903); |
2143 | wm8903->irq = i2c->irq; | ||
2144 | 2048 | ||
2145 | /* If no platform data was supplied, create storage for defaults */ | 2049 | /* If no platform data was supplied, create storage for defaults */ |
2146 | if (pdata) { | 2050 | if (pdata) { |
@@ -2167,6 +2071,8 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
2167 | } | 2071 | } |
2168 | } | 2072 | } |
2169 | 2073 | ||
2074 | pdata = wm8903->pdata; | ||
2075 | |||
2170 | ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val); | 2076 | ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val); |
2171 | if (ret != 0) { | 2077 | if (ret != 0) { |
2172 | dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); | 2078 | dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); |
@@ -2189,6 +2095,107 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
2189 | /* Reset the device */ | 2095 | /* Reset the device */ |
2190 | regmap_write(wm8903->regmap, WM8903_SW_RESET_AND_ID, 0x8903); | 2096 | regmap_write(wm8903->regmap, WM8903_SW_RESET_AND_ID, 0x8903); |
2191 | 2097 | ||
2098 | wm8903_init_gpio(wm8903); | ||
2099 | |||
2100 | /* Set up GPIO pin state, detect if any are MIC detect outputs */ | ||
2101 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { | ||
2102 | if ((!pdata->gpio_cfg[i]) || | ||
2103 | (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO)) | ||
2104 | continue; | ||
2105 | |||
2106 | regmap_write(wm8903->regmap, WM8903_GPIO_CONTROL_1 + i, | ||
2107 | pdata->gpio_cfg[i] & 0x7fff); | ||
2108 | |||
2109 | val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK) | ||
2110 | >> WM8903_GP1_FN_SHIFT; | ||
2111 | |||
2112 | switch (val) { | ||
2113 | case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT: | ||
2114 | case WM8903_GPn_FN_MICBIAS_SHORT_DETECT: | ||
2115 | mic_gpio = true; | ||
2116 | break; | ||
2117 | default: | ||
2118 | break; | ||
2119 | } | ||
2120 | } | ||
2121 | |||
2122 | /* Set up microphone detection */ | ||
2123 | regmap_write(wm8903->regmap, WM8903_MIC_BIAS_CONTROL_0, | ||
2124 | pdata->micdet_cfg); | ||
2125 | |||
2126 | /* Microphone detection needs the WSEQ clock */ | ||
2127 | if (pdata->micdet_cfg) | ||
2128 | regmap_update_bits(wm8903->regmap, WM8903_WRITE_SEQUENCER_0, | ||
2129 | WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); | ||
2130 | |||
2131 | /* If microphone detection is enabled by pdata but | ||
2132 | * detected via IRQ then interrupts can be lost before | ||
2133 | * the machine driver has set up microphone detection | ||
2134 | * IRQs as the IRQs are clear on read. The detection | ||
2135 | * will be enabled when the machine driver configures. | ||
2136 | */ | ||
2137 | WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA)); | ||
2138 | |||
2139 | wm8903->mic_delay = pdata->micdet_delay; | ||
2140 | |||
2141 | if (i2c->irq) { | ||
2142 | if (pdata->irq_active_low) { | ||
2143 | trigger = IRQF_TRIGGER_LOW; | ||
2144 | irq_pol = WM8903_IRQ_POL; | ||
2145 | } else { | ||
2146 | trigger = IRQF_TRIGGER_HIGH; | ||
2147 | irq_pol = 0; | ||
2148 | } | ||
2149 | |||
2150 | regmap_update_bits(wm8903->regmap, WM8903_INTERRUPT_CONTROL, | ||
2151 | WM8903_IRQ_POL, irq_pol); | ||
2152 | |||
2153 | ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq, | ||
2154 | trigger | IRQF_ONESHOT, | ||
2155 | "wm8903", wm8903); | ||
2156 | if (ret != 0) { | ||
2157 | dev_err(wm8903->dev, "Failed to request IRQ: %d\n", | ||
2158 | ret); | ||
2159 | return ret; | ||
2160 | } | ||
2161 | |||
2162 | /* Enable write sequencer interrupts */ | ||
2163 | regmap_update_bits(wm8903->regmap, | ||
2164 | WM8903_INTERRUPT_STATUS_1_MASK, | ||
2165 | WM8903_IM_WSEQ_BUSY_EINT, 0); | ||
2166 | } | ||
2167 | |||
2168 | /* Latch volume update bits */ | ||
2169 | regmap_update_bits(wm8903->regmap, WM8903_ADC_DIGITAL_VOLUME_LEFT, | ||
2170 | WM8903_ADCVU, WM8903_ADCVU); | ||
2171 | regmap_update_bits(wm8903->regmap, WM8903_ADC_DIGITAL_VOLUME_RIGHT, | ||
2172 | WM8903_ADCVU, WM8903_ADCVU); | ||
2173 | |||
2174 | regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_VOLUME_LEFT, | ||
2175 | WM8903_DACVU, WM8903_DACVU); | ||
2176 | regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_VOLUME_RIGHT, | ||
2177 | WM8903_DACVU, WM8903_DACVU); | ||
2178 | |||
2179 | regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT1_LEFT, | ||
2180 | WM8903_HPOUTVU, WM8903_HPOUTVU); | ||
2181 | regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT1_RIGHT, | ||
2182 | WM8903_HPOUTVU, WM8903_HPOUTVU); | ||
2183 | |||
2184 | regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT2_LEFT, | ||
2185 | WM8903_LINEOUTVU, WM8903_LINEOUTVU); | ||
2186 | regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT2_RIGHT, | ||
2187 | WM8903_LINEOUTVU, WM8903_LINEOUTVU); | ||
2188 | |||
2189 | regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT3_LEFT, | ||
2190 | WM8903_SPKVU, WM8903_SPKVU); | ||
2191 | regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT3_RIGHT, | ||
2192 | WM8903_SPKVU, WM8903_SPKVU); | ||
2193 | |||
2194 | /* Enable DAC soft mute by default */ | ||
2195 | regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_1, | ||
2196 | WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE, | ||
2197 | WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE); | ||
2198 | |||
2192 | ret = snd_soc_register_codec(&i2c->dev, | 2199 | ret = snd_soc_register_codec(&i2c->dev, |
2193 | &soc_codec_dev_wm8903, &wm8903_dai, 1); | 2200 | &soc_codec_dev_wm8903, &wm8903_dai, 1); |
2194 | if (ret != 0) | 2201 | if (ret != 0) |
@@ -2196,7 +2203,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
2196 | 2203 | ||
2197 | return 0; | 2204 | return 0; |
2198 | err: | 2205 | err: |
2199 | regmap_exit(wm8903->regmap); | ||
2200 | return ret; | 2206 | return ret; |
2201 | } | 2207 | } |
2202 | 2208 | ||
@@ -2204,7 +2210,9 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client) | |||
2204 | { | 2210 | { |
2205 | struct wm8903_priv *wm8903 = i2c_get_clientdata(client); | 2211 | struct wm8903_priv *wm8903 = i2c_get_clientdata(client); |
2206 | 2212 | ||
2207 | regmap_exit(wm8903->regmap); | 2213 | if (client->irq) |
2214 | free_irq(client->irq, wm8903); | ||
2215 | wm8903_free_gpio(wm8903); | ||
2208 | snd_soc_unregister_codec(&client->dev); | 2216 | snd_soc_unregister_codec(&client->dev); |
2209 | 2217 | ||
2210 | return 0; | 2218 | return 0; |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 812acd83fb48..0013afe48e66 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8904.c -- WM8904 ALSA SoC Audio driver | 2 | * wm8904.c -- WM8904 ALSA SoC Audio driver |
3 | * | 3 | * |
4 | * Copyright 2009 Wolfson Microelectronics plc | 4 | * Copyright 2009-12 Wolfson Microelectronics plc |
5 | * | 5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
@@ -314,11 +314,6 @@ static bool wm8904_readable_register(struct device *dev, unsigned int reg) | |||
314 | } | 314 | } |
315 | } | 315 | } |
316 | 316 | ||
317 | static int wm8904_reset(struct snd_soc_codec *codec) | ||
318 | { | ||
319 | return snd_soc_write(codec, WM8904_SW_RESET_AND_ID, 0); | ||
320 | } | ||
321 | |||
322 | static int wm8904_configure_clocking(struct snd_soc_codec *codec) | 317 | static int wm8904_configure_clocking(struct snd_soc_codec *codec) |
323 | { | 318 | { |
324 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | 319 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
@@ -1945,25 +1940,6 @@ static struct snd_soc_dai_driver wm8904_dai = { | |||
1945 | .symmetric_rates = 1, | 1940 | .symmetric_rates = 1, |
1946 | }; | 1941 | }; |
1947 | 1942 | ||
1948 | #ifdef CONFIG_PM | ||
1949 | static int wm8904_suspend(struct snd_soc_codec *codec) | ||
1950 | { | ||
1951 | wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1952 | |||
1953 | return 0; | ||
1954 | } | ||
1955 | |||
1956 | static int wm8904_resume(struct snd_soc_codec *codec) | ||
1957 | { | ||
1958 | wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1959 | |||
1960 | return 0; | ||
1961 | } | ||
1962 | #else | ||
1963 | #define wm8904_suspend NULL | ||
1964 | #define wm8904_resume NULL | ||
1965 | #endif | ||
1966 | |||
1967 | static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec) | 1943 | static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec) |
1968 | { | 1944 | { |
1969 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | 1945 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
@@ -2078,8 +2054,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) | |||
2078 | static int wm8904_probe(struct snd_soc_codec *codec) | 2054 | static int wm8904_probe(struct snd_soc_codec *codec) |
2079 | { | 2055 | { |
2080 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | 2056 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
2081 | struct wm8904_pdata *pdata = wm8904->pdata; | 2057 | int ret; |
2082 | int ret, i; | ||
2083 | 2058 | ||
2084 | codec->control_data = wm8904->regmap; | 2059 | codec->control_data = wm8904->regmap; |
2085 | 2060 | ||
@@ -2101,127 +2076,17 @@ static int wm8904_probe(struct snd_soc_codec *codec) | |||
2101 | return ret; | 2076 | return ret; |
2102 | } | 2077 | } |
2103 | 2078 | ||
2104 | for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) | ||
2105 | wm8904->supplies[i].supply = wm8904_supply_names[i]; | ||
2106 | |||
2107 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8904->supplies), | ||
2108 | wm8904->supplies); | ||
2109 | if (ret != 0) { | ||
2110 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
2111 | return ret; | ||
2112 | } | ||
2113 | |||
2114 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), | ||
2115 | wm8904->supplies); | ||
2116 | if (ret != 0) { | ||
2117 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
2118 | goto err_get; | ||
2119 | } | ||
2120 | |||
2121 | ret = snd_soc_read(codec, WM8904_SW_RESET_AND_ID); | ||
2122 | if (ret < 0) { | ||
2123 | dev_err(codec->dev, "Failed to read ID register\n"); | ||
2124 | goto err_enable; | ||
2125 | } | ||
2126 | if (ret != 0x8904) { | ||
2127 | dev_err(codec->dev, "Device is not a WM8904, ID is %x\n", ret); | ||
2128 | ret = -EINVAL; | ||
2129 | goto err_enable; | ||
2130 | } | ||
2131 | |||
2132 | ret = snd_soc_read(codec, WM8904_REVISION); | ||
2133 | if (ret < 0) { | ||
2134 | dev_err(codec->dev, "Failed to read device revision: %d\n", | ||
2135 | ret); | ||
2136 | goto err_enable; | ||
2137 | } | ||
2138 | dev_info(codec->dev, "revision %c\n", ret + 'A'); | ||
2139 | |||
2140 | ret = wm8904_reset(codec); | ||
2141 | if (ret < 0) { | ||
2142 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
2143 | goto err_enable; | ||
2144 | } | ||
2145 | |||
2146 | regcache_cache_only(wm8904->regmap, true); | ||
2147 | /* Change some default settings - latch VU and enable ZC */ | ||
2148 | snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_LEFT, | ||
2149 | WM8904_ADC_VU, WM8904_ADC_VU); | ||
2150 | snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_RIGHT, | ||
2151 | WM8904_ADC_VU, WM8904_ADC_VU); | ||
2152 | snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_LEFT, | ||
2153 | WM8904_DAC_VU, WM8904_DAC_VU); | ||
2154 | snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_RIGHT, | ||
2155 | WM8904_DAC_VU, WM8904_DAC_VU); | ||
2156 | snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_LEFT, | ||
2157 | WM8904_HPOUT_VU | WM8904_HPOUTLZC, | ||
2158 | WM8904_HPOUT_VU | WM8904_HPOUTLZC); | ||
2159 | snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_RIGHT, | ||
2160 | WM8904_HPOUT_VU | WM8904_HPOUTRZC, | ||
2161 | WM8904_HPOUT_VU | WM8904_HPOUTRZC); | ||
2162 | snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_LEFT, | ||
2163 | WM8904_LINEOUT_VU | WM8904_LINEOUTLZC, | ||
2164 | WM8904_LINEOUT_VU | WM8904_LINEOUTLZC); | ||
2165 | snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_RIGHT, | ||
2166 | WM8904_LINEOUT_VU | WM8904_LINEOUTRZC, | ||
2167 | WM8904_LINEOUT_VU | WM8904_LINEOUTRZC); | ||
2168 | snd_soc_update_bits(codec, WM8904_CLOCK_RATES_0, | ||
2169 | WM8904_SR_MODE, 0); | ||
2170 | |||
2171 | /* Apply configuration from the platform data. */ | ||
2172 | if (wm8904->pdata) { | ||
2173 | for (i = 0; i < WM8904_GPIO_REGS; i++) { | ||
2174 | if (!pdata->gpio_cfg[i]) | ||
2175 | continue; | ||
2176 | |||
2177 | regmap_update_bits(wm8904->regmap, | ||
2178 | WM8904_GPIO_CONTROL_1 + i, | ||
2179 | 0xffff, | ||
2180 | pdata->gpio_cfg[i]); | ||
2181 | } | ||
2182 | |||
2183 | /* Zero is the default value for these anyway */ | ||
2184 | for (i = 0; i < WM8904_MIC_REGS; i++) | ||
2185 | regmap_update_bits(wm8904->regmap, | ||
2186 | WM8904_MIC_BIAS_CONTROL_0 + i, | ||
2187 | 0xffff, | ||
2188 | pdata->mic_cfg[i]); | ||
2189 | } | ||
2190 | |||
2191 | /* Set Class W by default - this will be managed by the Class | ||
2192 | * G widget at runtime where bypass paths are available. | ||
2193 | */ | ||
2194 | snd_soc_update_bits(codec, WM8904_CLASS_W_0, | ||
2195 | WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR); | ||
2196 | |||
2197 | /* Use normal bias source */ | ||
2198 | snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0, | ||
2199 | WM8904_POBCTRL, 0); | ||
2200 | |||
2201 | wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
2202 | |||
2203 | /* Bias level configuration will have done an extra enable */ | ||
2204 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | ||
2205 | |||
2206 | wm8904_handle_pdata(codec); | 2079 | wm8904_handle_pdata(codec); |
2207 | 2080 | ||
2208 | wm8904_add_widgets(codec); | 2081 | wm8904_add_widgets(codec); |
2209 | 2082 | ||
2210 | return 0; | 2083 | return 0; |
2211 | |||
2212 | err_enable: | ||
2213 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | ||
2214 | err_get: | ||
2215 | regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | ||
2216 | return ret; | ||
2217 | } | 2084 | } |
2218 | 2085 | ||
2219 | static int wm8904_remove(struct snd_soc_codec *codec) | 2086 | static int wm8904_remove(struct snd_soc_codec *codec) |
2220 | { | 2087 | { |
2221 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | 2088 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
2222 | 2089 | ||
2223 | wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
2224 | regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | ||
2225 | kfree(wm8904->retune_mobile_texts); | 2090 | kfree(wm8904->retune_mobile_texts); |
2226 | kfree(wm8904->drc_texts); | 2091 | kfree(wm8904->drc_texts); |
2227 | 2092 | ||
@@ -2231,8 +2096,6 @@ static int wm8904_remove(struct snd_soc_codec *codec) | |||
2231 | static struct snd_soc_codec_driver soc_codec_dev_wm8904 = { | 2096 | static struct snd_soc_codec_driver soc_codec_dev_wm8904 = { |
2232 | .probe = wm8904_probe, | 2097 | .probe = wm8904_probe, |
2233 | .remove = wm8904_remove, | 2098 | .remove = wm8904_remove, |
2234 | .suspend = wm8904_suspend, | ||
2235 | .resume = wm8904_resume, | ||
2236 | .set_bias_level = wm8904_set_bias_level, | 2099 | .set_bias_level = wm8904_set_bias_level, |
2237 | .idle_bias_off = true, | 2100 | .idle_bias_off = true, |
2238 | }; | 2101 | }; |
@@ -2254,14 +2117,15 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, | |||
2254 | const struct i2c_device_id *id) | 2117 | const struct i2c_device_id *id) |
2255 | { | 2118 | { |
2256 | struct wm8904_priv *wm8904; | 2119 | struct wm8904_priv *wm8904; |
2257 | int ret; | 2120 | unsigned int val; |
2121 | int ret, i; | ||
2258 | 2122 | ||
2259 | wm8904 = devm_kzalloc(&i2c->dev, sizeof(struct wm8904_priv), | 2123 | wm8904 = devm_kzalloc(&i2c->dev, sizeof(struct wm8904_priv), |
2260 | GFP_KERNEL); | 2124 | GFP_KERNEL); |
2261 | if (wm8904 == NULL) | 2125 | if (wm8904 == NULL) |
2262 | return -ENOMEM; | 2126 | return -ENOMEM; |
2263 | 2127 | ||
2264 | wm8904->regmap = regmap_init_i2c(i2c, &wm8904_regmap); | 2128 | wm8904->regmap = devm_regmap_init_i2c(i2c, &wm8904_regmap); |
2265 | if (IS_ERR(wm8904->regmap)) { | 2129 | if (IS_ERR(wm8904->regmap)) { |
2266 | ret = PTR_ERR(wm8904->regmap); | 2130 | ret = PTR_ERR(wm8904->regmap); |
2267 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 2131 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
@@ -2273,23 +2137,121 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, | |||
2273 | i2c_set_clientdata(i2c, wm8904); | 2137 | i2c_set_clientdata(i2c, wm8904); |
2274 | wm8904->pdata = i2c->dev.platform_data; | 2138 | wm8904->pdata = i2c->dev.platform_data; |
2275 | 2139 | ||
2140 | for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) | ||
2141 | wm8904->supplies[i].supply = wm8904_supply_names[i]; | ||
2142 | |||
2143 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8904->supplies), | ||
2144 | wm8904->supplies); | ||
2145 | if (ret != 0) { | ||
2146 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
2147 | return ret; | ||
2148 | } | ||
2149 | |||
2150 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), | ||
2151 | wm8904->supplies); | ||
2152 | if (ret != 0) { | ||
2153 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | ||
2154 | return ret; | ||
2155 | } | ||
2156 | |||
2157 | ret = regmap_read(wm8904->regmap, WM8904_SW_RESET_AND_ID, &val); | ||
2158 | if (ret < 0) { | ||
2159 | dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret); | ||
2160 | goto err_enable; | ||
2161 | } | ||
2162 | if (val != 0x8904) { | ||
2163 | dev_err(&i2c->dev, "Device is not a WM8904, ID is %x\n", val); | ||
2164 | ret = -EINVAL; | ||
2165 | goto err_enable; | ||
2166 | } | ||
2167 | |||
2168 | ret = regmap_read(wm8904->regmap, WM8904_REVISION, &val); | ||
2169 | if (ret < 0) { | ||
2170 | dev_err(&i2c->dev, "Failed to read device revision: %d\n", | ||
2171 | ret); | ||
2172 | goto err_enable; | ||
2173 | } | ||
2174 | dev_info(&i2c->dev, "revision %c\n", val + 'A'); | ||
2175 | |||
2176 | ret = regmap_write(wm8904->regmap, WM8904_SW_RESET_AND_ID, 0); | ||
2177 | if (ret < 0) { | ||
2178 | dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); | ||
2179 | goto err_enable; | ||
2180 | } | ||
2181 | |||
2182 | /* Change some default settings - latch VU and enable ZC */ | ||
2183 | regmap_update_bits(wm8904->regmap, WM8904_ADC_DIGITAL_VOLUME_LEFT, | ||
2184 | WM8904_ADC_VU, WM8904_ADC_VU); | ||
2185 | regmap_update_bits(wm8904->regmap, WM8904_ADC_DIGITAL_VOLUME_RIGHT, | ||
2186 | WM8904_ADC_VU, WM8904_ADC_VU); | ||
2187 | regmap_update_bits(wm8904->regmap, WM8904_DAC_DIGITAL_VOLUME_LEFT, | ||
2188 | WM8904_DAC_VU, WM8904_DAC_VU); | ||
2189 | regmap_update_bits(wm8904->regmap, WM8904_DAC_DIGITAL_VOLUME_RIGHT, | ||
2190 | WM8904_DAC_VU, WM8904_DAC_VU); | ||
2191 | regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT1_LEFT, | ||
2192 | WM8904_HPOUT_VU | WM8904_HPOUTLZC, | ||
2193 | WM8904_HPOUT_VU | WM8904_HPOUTLZC); | ||
2194 | regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT1_RIGHT, | ||
2195 | WM8904_HPOUT_VU | WM8904_HPOUTRZC, | ||
2196 | WM8904_HPOUT_VU | WM8904_HPOUTRZC); | ||
2197 | regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT2_LEFT, | ||
2198 | WM8904_LINEOUT_VU | WM8904_LINEOUTLZC, | ||
2199 | WM8904_LINEOUT_VU | WM8904_LINEOUTLZC); | ||
2200 | regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT2_RIGHT, | ||
2201 | WM8904_LINEOUT_VU | WM8904_LINEOUTRZC, | ||
2202 | WM8904_LINEOUT_VU | WM8904_LINEOUTRZC); | ||
2203 | regmap_update_bits(wm8904->regmap, WM8904_CLOCK_RATES_0, | ||
2204 | WM8904_SR_MODE, 0); | ||
2205 | |||
2206 | /* Apply configuration from the platform data. */ | ||
2207 | if (wm8904->pdata) { | ||
2208 | for (i = 0; i < WM8904_GPIO_REGS; i++) { | ||
2209 | if (!wm8904->pdata->gpio_cfg[i]) | ||
2210 | continue; | ||
2211 | |||
2212 | regmap_update_bits(wm8904->regmap, | ||
2213 | WM8904_GPIO_CONTROL_1 + i, | ||
2214 | 0xffff, | ||
2215 | wm8904->pdata->gpio_cfg[i]); | ||
2216 | } | ||
2217 | |||
2218 | /* Zero is the default value for these anyway */ | ||
2219 | for (i = 0; i < WM8904_MIC_REGS; i++) | ||
2220 | regmap_update_bits(wm8904->regmap, | ||
2221 | WM8904_MIC_BIAS_CONTROL_0 + i, | ||
2222 | 0xffff, | ||
2223 | wm8904->pdata->mic_cfg[i]); | ||
2224 | } | ||
2225 | |||
2226 | /* Set Class W by default - this will be managed by the Class | ||
2227 | * G widget at runtime where bypass paths are available. | ||
2228 | */ | ||
2229 | regmap_update_bits(wm8904->regmap, WM8904_CLASS_W_0, | ||
2230 | WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR); | ||
2231 | |||
2232 | /* Use normal bias source */ | ||
2233 | regmap_update_bits(wm8904->regmap, WM8904_BIAS_CONTROL_0, | ||
2234 | WM8904_POBCTRL, 0); | ||
2235 | |||
2236 | /* Can leave the device powered off until we need it */ | ||
2237 | regcache_cache_only(wm8904->regmap, true); | ||
2238 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | ||
2239 | |||
2276 | ret = snd_soc_register_codec(&i2c->dev, | 2240 | ret = snd_soc_register_codec(&i2c->dev, |
2277 | &soc_codec_dev_wm8904, &wm8904_dai, 1); | 2241 | &soc_codec_dev_wm8904, &wm8904_dai, 1); |
2278 | if (ret != 0) | 2242 | if (ret != 0) |
2279 | goto err; | 2243 | return ret; |
2280 | 2244 | ||
2281 | return 0; | 2245 | return 0; |
2282 | 2246 | ||
2283 | err: | 2247 | err_enable: |
2284 | regmap_exit(wm8904->regmap); | 2248 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); |
2285 | return ret; | 2249 | return ret; |
2286 | } | 2250 | } |
2287 | 2251 | ||
2288 | static __devexit int wm8904_i2c_remove(struct i2c_client *client) | 2252 | static __devexit int wm8904_i2c_remove(struct i2c_client *client) |
2289 | { | 2253 | { |
2290 | struct wm8904_priv *wm8904 = i2c_get_clientdata(client); | ||
2291 | snd_soc_unregister_codec(&client->dev); | 2254 | snd_soc_unregister_codec(&client->dev); |
2292 | regmap_exit(wm8904->regmap); | ||
2293 | return 0; | 2255 | return 0; |
2294 | } | 2256 | } |
2295 | 2257 | ||
@@ -2311,23 +2273,7 @@ static struct i2c_driver wm8904_i2c_driver = { | |||
2311 | .id_table = wm8904_i2c_id, | 2273 | .id_table = wm8904_i2c_id, |
2312 | }; | 2274 | }; |
2313 | 2275 | ||
2314 | static int __init wm8904_modinit(void) | 2276 | module_i2c_driver(wm8904_i2c_driver); |
2315 | { | ||
2316 | int ret = 0; | ||
2317 | ret = i2c_add_driver(&wm8904_i2c_driver); | ||
2318 | if (ret != 0) { | ||
2319 | printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n", | ||
2320 | ret); | ||
2321 | } | ||
2322 | return ret; | ||
2323 | } | ||
2324 | module_init(wm8904_modinit); | ||
2325 | |||
2326 | static void __exit wm8904_exit(void) | ||
2327 | { | ||
2328 | i2c_del_driver(&wm8904_i2c_driver); | ||
2329 | } | ||
2330 | module_exit(wm8904_exit); | ||
2331 | 2277 | ||
2332 | MODULE_DESCRIPTION("ASoC WM8904 driver"); | 2278 | MODULE_DESCRIPTION("ASoC WM8904 driver"); |
2333 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 2279 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 8bc659d8dd2e..96518ac8e24c 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -1,6 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * wm8960.c -- WM8960 ALSA SoC Audio driver | 2 | * wm8960.c -- WM8960 ALSA SoC Audio driver |
3 | * | 3 | * |
4 | * Copyright 2007-11 Wolfson Microelectronics, plc | ||
5 | * | ||
4 | * Author: Liam Girdwood | 6 | * Author: Liam Girdwood |
5 | * | 7 | * |
6 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 05ea7c274093..01edbcc754d2 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -1,6 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * wm8961.c -- WM8961 ALSA SoC Audio driver | 2 | * wm8961.c -- WM8961 ALSA SoC Audio driver |
3 | * | 3 | * |
4 | * Copyright 2009-10 Wolfson Microelectronics, plc | ||
5 | * | ||
4 | * Author: Mark Brown | 6 | * Author: Mark Brown |
5 | * | 7 | * |
6 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 0cfce9999c89..eaf65863ec21 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8962.c -- WM8962 ALSA SoC Audio driver | 2 | * wm8962.c -- WM8962 ALSA SoC Audio driver |
3 | * | 3 | * |
4 | * Copyright 2010 Wolfson Microelectronics plc | 4 | * Copyright 2010-2 Wolfson Microelectronics plc |
5 | * | 5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
@@ -2580,6 +2580,9 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream, | |||
2580 | WM8962_SAMPLE_RATE_INT_MODE | | 2580 | WM8962_SAMPLE_RATE_INT_MODE | |
2581 | WM8962_SAMPLE_RATE_MASK, adctl3); | 2581 | WM8962_SAMPLE_RATE_MASK, adctl3); |
2582 | 2582 | ||
2583 | dev_dbg(codec->dev, "hw_params set BCLK %dHz LRCLK %dHz\n", | ||
2584 | wm8962->bclk, wm8962->lrclk); | ||
2585 | |||
2583 | if (codec->dapm.bias_level == SND_SOC_BIAS_ON) | 2586 | if (codec->dapm.bias_level == SND_SOC_BIAS_ON) |
2584 | wm8962_configure_bclk(codec); | 2587 | wm8962_configure_bclk(codec); |
2585 | 2588 | ||
@@ -3722,6 +3725,9 @@ static int wm8962_runtime_resume(struct device *dev) | |||
3722 | } | 3725 | } |
3723 | 3726 | ||
3724 | regcache_cache_only(wm8962->regmap, false); | 3727 | regcache_cache_only(wm8962->regmap, false); |
3728 | |||
3729 | wm8962_reset(wm8962); | ||
3730 | |||
3725 | regcache_sync(wm8962->regmap); | 3731 | regcache_sync(wm8962->regmap); |
3726 | 3732 | ||
3727 | regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, | 3733 | regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 36acfccab999..9fd80d688979 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8993.c -- WM8993 ALSA SoC audio driver | 2 | * wm8993.c -- WM8993 ALSA SoC audio driver |
3 | * | 3 | * |
4 | * Copyright 2009, 2010 Wolfson Microelectronics plc | 4 | * Copyright 2009-12 Wolfson Microelectronics plc |
5 | * | 5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 1436b6ce74d1..bb62f4b3d563 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8994.c -- WM8994 ALSA SoC Audio driver | 2 | * wm8994.c -- WM8994 ALSA SoC Audio driver |
3 | * | 3 | * |
4 | * Copyright 2009 Wolfson Microelectronics plc | 4 | * Copyright 2009-12 Wolfson Microelectronics plc |
5 | * | 5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
@@ -2967,23 +2967,8 @@ static struct snd_soc_dai_driver wm8994_dai[] = { | |||
2967 | static int wm8994_codec_suspend(struct snd_soc_codec *codec) | 2967 | static int wm8994_codec_suspend(struct snd_soc_codec *codec) |
2968 | { | 2968 | { |
2969 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2969 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2970 | struct wm8994 *control = wm8994->wm8994; | ||
2971 | int i, ret; | 2970 | int i, ret; |
2972 | 2971 | ||
2973 | switch (control->type) { | ||
2974 | case WM8994: | ||
2975 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0); | ||
2976 | break; | ||
2977 | case WM1811: | ||
2978 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
2979 | WM1811_JACKDET_MODE_MASK, 0); | ||
2980 | /* Fall through */ | ||
2981 | case WM8958: | ||
2982 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | ||
2983 | WM8958_MICD_ENA, 0); | ||
2984 | break; | ||
2985 | } | ||
2986 | |||
2987 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { | 2972 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { |
2988 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], | 2973 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], |
2989 | sizeof(struct wm8994_fll_config)); | 2974 | sizeof(struct wm8994_fll_config)); |
@@ -3033,28 +3018,6 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec) | |||
3033 | i + 1, ret); | 3018 | i + 1, ret); |
3034 | } | 3019 | } |
3035 | 3020 | ||
3036 | switch (control->type) { | ||
3037 | case WM8994: | ||
3038 | if (wm8994->micdet[0].jack || wm8994->micdet[1].jack) | ||
3039 | snd_soc_update_bits(codec, WM8994_MICBIAS, | ||
3040 | WM8994_MICD_ENA, WM8994_MICD_ENA); | ||
3041 | break; | ||
3042 | case WM1811: | ||
3043 | if (wm8994->jackdet && wm8994->jack_cb) { | ||
3044 | /* Restart from idle */ | ||
3045 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
3046 | WM1811_JACKDET_MODE_MASK, | ||
3047 | WM1811_JACKDET_MODE_JACK); | ||
3048 | break; | ||
3049 | } | ||
3050 | break; | ||
3051 | case WM8958: | ||
3052 | if (wm8994->jack_cb) | ||
3053 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | ||
3054 | WM8958_MICD_ENA, WM8958_MICD_ENA); | ||
3055 | break; | ||
3056 | } | ||
3057 | |||
3058 | return 0; | 3021 | return 0; |
3059 | } | 3022 | } |
3060 | #else | 3023 | #else |
@@ -3729,9 +3692,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3729 | 3692 | ||
3730 | if (wm8994->pdata && wm8994->pdata->micdet_irq) | 3693 | if (wm8994->pdata && wm8994->pdata->micdet_irq) |
3731 | wm8994->micdet_irq = wm8994->pdata->micdet_irq; | 3694 | wm8994->micdet_irq = wm8994->pdata->micdet_irq; |
3732 | else if (wm8994->pdata && wm8994->pdata->irq_base) | ||
3733 | wm8994->micdet_irq = wm8994->pdata->irq_base + | ||
3734 | WM8994_IRQ_MIC1_DET; | ||
3735 | 3695 | ||
3736 | pm_runtime_enable(codec->dev); | 3696 | pm_runtime_enable(codec->dev); |
3737 | pm_runtime_idle(codec->dev); | 3697 | pm_runtime_idle(codec->dev); |
@@ -3870,6 +3830,10 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3870 | dev_warn(codec->dev, | 3830 | dev_warn(codec->dev, |
3871 | "Failed to request Mic detect IRQ: %d\n", | 3831 | "Failed to request Mic detect IRQ: %d\n", |
3872 | ret); | 3832 | ret); |
3833 | } else { | ||
3834 | wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_MIC1_DET, | ||
3835 | wm8958_mic_irq, "Mic detect", | ||
3836 | wm8994); | ||
3873 | } | 3837 | } |
3874 | } | 3838 | } |
3875 | 3839 | ||
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index dc9b42b7fc4d..00f183dfa454 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8996.c - WM8996 audio codec interface | 2 | * wm8996.c - WM8996 audio codec interface |
3 | * | 3 | * |
4 | * Copyright 2011 Wolfson Microelectronics PLC. | 4 | * Copyright 2011-2 Wolfson Microelectronics PLC. |
5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
@@ -296,184 +296,6 @@ static struct reg_default wm8996_reg[] = { | |||
296 | { WM8996_RIGHT_PDM_SPEAKER, 0x1 }, | 296 | { WM8996_RIGHT_PDM_SPEAKER, 0x1 }, |
297 | { WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 }, | 297 | { WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 }, |
298 | { WM8996_PDM_SPEAKER_VOLUME, 0x66 }, | 298 | { WM8996_PDM_SPEAKER_VOLUME, 0x66 }, |
299 | { WM8996_WRITE_SEQUENCER_0, 0x1 }, | ||
300 | { WM8996_WRITE_SEQUENCER_1, 0x1 }, | ||
301 | { WM8996_WRITE_SEQUENCER_3, 0x6 }, | ||
302 | { WM8996_WRITE_SEQUENCER_4, 0x40 }, | ||
303 | { WM8996_WRITE_SEQUENCER_5, 0x1 }, | ||
304 | { WM8996_WRITE_SEQUENCER_6, 0xf }, | ||
305 | { WM8996_WRITE_SEQUENCER_7, 0x6 }, | ||
306 | { WM8996_WRITE_SEQUENCER_8, 0x1 }, | ||
307 | { WM8996_WRITE_SEQUENCER_9, 0x3 }, | ||
308 | { WM8996_WRITE_SEQUENCER_10, 0x104 }, | ||
309 | { WM8996_WRITE_SEQUENCER_12, 0x60 }, | ||
310 | { WM8996_WRITE_SEQUENCER_13, 0x11 }, | ||
311 | { WM8996_WRITE_SEQUENCER_14, 0x401 }, | ||
312 | { WM8996_WRITE_SEQUENCER_16, 0x50 }, | ||
313 | { WM8996_WRITE_SEQUENCER_17, 0x3 }, | ||
314 | { WM8996_WRITE_SEQUENCER_18, 0x100 }, | ||
315 | { WM8996_WRITE_SEQUENCER_20, 0x51 }, | ||
316 | { WM8996_WRITE_SEQUENCER_21, 0x3 }, | ||
317 | { WM8996_WRITE_SEQUENCER_22, 0x104 }, | ||
318 | { WM8996_WRITE_SEQUENCER_23, 0xa }, | ||
319 | { WM8996_WRITE_SEQUENCER_24, 0x60 }, | ||
320 | { WM8996_WRITE_SEQUENCER_25, 0x3b }, | ||
321 | { WM8996_WRITE_SEQUENCER_26, 0x502 }, | ||
322 | { WM8996_WRITE_SEQUENCER_27, 0x100 }, | ||
323 | { WM8996_WRITE_SEQUENCER_28, 0x2fff }, | ||
324 | { WM8996_WRITE_SEQUENCER_32, 0x2fff }, | ||
325 | { WM8996_WRITE_SEQUENCER_36, 0x2fff }, | ||
326 | { WM8996_WRITE_SEQUENCER_40, 0x2fff }, | ||
327 | { WM8996_WRITE_SEQUENCER_44, 0x2fff }, | ||
328 | { WM8996_WRITE_SEQUENCER_48, 0x2fff }, | ||
329 | { WM8996_WRITE_SEQUENCER_52, 0x2fff }, | ||
330 | { WM8996_WRITE_SEQUENCER_56, 0x2fff }, | ||
331 | { WM8996_WRITE_SEQUENCER_60, 0x2fff }, | ||
332 | { WM8996_WRITE_SEQUENCER_64, 0x1 }, | ||
333 | { WM8996_WRITE_SEQUENCER_65, 0x1 }, | ||
334 | { WM8996_WRITE_SEQUENCER_67, 0x6 }, | ||
335 | { WM8996_WRITE_SEQUENCER_68, 0x40 }, | ||
336 | { WM8996_WRITE_SEQUENCER_69, 0x1 }, | ||
337 | { WM8996_WRITE_SEQUENCER_70, 0xf }, | ||
338 | { WM8996_WRITE_SEQUENCER_71, 0x6 }, | ||
339 | { WM8996_WRITE_SEQUENCER_72, 0x1 }, | ||
340 | { WM8996_WRITE_SEQUENCER_73, 0x3 }, | ||
341 | { WM8996_WRITE_SEQUENCER_74, 0x104 }, | ||
342 | { WM8996_WRITE_SEQUENCER_76, 0x60 }, | ||
343 | { WM8996_WRITE_SEQUENCER_77, 0x11 }, | ||
344 | { WM8996_WRITE_SEQUENCER_78, 0x401 }, | ||
345 | { WM8996_WRITE_SEQUENCER_80, 0x50 }, | ||
346 | { WM8996_WRITE_SEQUENCER_81, 0x3 }, | ||
347 | { WM8996_WRITE_SEQUENCER_82, 0x100 }, | ||
348 | { WM8996_WRITE_SEQUENCER_84, 0x60 }, | ||
349 | { WM8996_WRITE_SEQUENCER_85, 0x3b }, | ||
350 | { WM8996_WRITE_SEQUENCER_86, 0x502 }, | ||
351 | { WM8996_WRITE_SEQUENCER_87, 0x100 }, | ||
352 | { WM8996_WRITE_SEQUENCER_88, 0x2fff }, | ||
353 | { WM8996_WRITE_SEQUENCER_92, 0x2fff }, | ||
354 | { WM8996_WRITE_SEQUENCER_96, 0x2fff }, | ||
355 | { WM8996_WRITE_SEQUENCER_100, 0x2fff }, | ||
356 | { WM8996_WRITE_SEQUENCER_104, 0x2fff }, | ||
357 | { WM8996_WRITE_SEQUENCER_108, 0x2fff }, | ||
358 | { WM8996_WRITE_SEQUENCER_112, 0x2fff }, | ||
359 | { WM8996_WRITE_SEQUENCER_116, 0x2fff }, | ||
360 | { WM8996_WRITE_SEQUENCER_120, 0x2fff }, | ||
361 | { WM8996_WRITE_SEQUENCER_124, 0x2fff }, | ||
362 | { WM8996_WRITE_SEQUENCER_128, 0x1 }, | ||
363 | { WM8996_WRITE_SEQUENCER_129, 0x1 }, | ||
364 | { WM8996_WRITE_SEQUENCER_131, 0x6 }, | ||
365 | { WM8996_WRITE_SEQUENCER_132, 0x40 }, | ||
366 | { WM8996_WRITE_SEQUENCER_133, 0x1 }, | ||
367 | { WM8996_WRITE_SEQUENCER_134, 0xf }, | ||
368 | { WM8996_WRITE_SEQUENCER_135, 0x6 }, | ||
369 | { WM8996_WRITE_SEQUENCER_136, 0x1 }, | ||
370 | { WM8996_WRITE_SEQUENCER_137, 0x3 }, | ||
371 | { WM8996_WRITE_SEQUENCER_138, 0x106 }, | ||
372 | { WM8996_WRITE_SEQUENCER_140, 0x61 }, | ||
373 | { WM8996_WRITE_SEQUENCER_141, 0x11 }, | ||
374 | { WM8996_WRITE_SEQUENCER_142, 0x401 }, | ||
375 | { WM8996_WRITE_SEQUENCER_144, 0x50 }, | ||
376 | { WM8996_WRITE_SEQUENCER_145, 0x3 }, | ||
377 | { WM8996_WRITE_SEQUENCER_146, 0x102 }, | ||
378 | { WM8996_WRITE_SEQUENCER_148, 0x51 }, | ||
379 | { WM8996_WRITE_SEQUENCER_149, 0x3 }, | ||
380 | { WM8996_WRITE_SEQUENCER_150, 0x106 }, | ||
381 | { WM8996_WRITE_SEQUENCER_151, 0xa }, | ||
382 | { WM8996_WRITE_SEQUENCER_152, 0x61 }, | ||
383 | { WM8996_WRITE_SEQUENCER_153, 0x3b }, | ||
384 | { WM8996_WRITE_SEQUENCER_154, 0x502 }, | ||
385 | { WM8996_WRITE_SEQUENCER_155, 0x100 }, | ||
386 | { WM8996_WRITE_SEQUENCER_156, 0x2fff }, | ||
387 | { WM8996_WRITE_SEQUENCER_160, 0x2fff }, | ||
388 | { WM8996_WRITE_SEQUENCER_164, 0x2fff }, | ||
389 | { WM8996_WRITE_SEQUENCER_168, 0x2fff }, | ||
390 | { WM8996_WRITE_SEQUENCER_172, 0x2fff }, | ||
391 | { WM8996_WRITE_SEQUENCER_176, 0x2fff }, | ||
392 | { WM8996_WRITE_SEQUENCER_180, 0x2fff }, | ||
393 | { WM8996_WRITE_SEQUENCER_184, 0x2fff }, | ||
394 | { WM8996_WRITE_SEQUENCER_188, 0x2fff }, | ||
395 | { WM8996_WRITE_SEQUENCER_192, 0x1 }, | ||
396 | { WM8996_WRITE_SEQUENCER_193, 0x1 }, | ||
397 | { WM8996_WRITE_SEQUENCER_195, 0x6 }, | ||
398 | { WM8996_WRITE_SEQUENCER_196, 0x40 }, | ||
399 | { WM8996_WRITE_SEQUENCER_197, 0x1 }, | ||
400 | { WM8996_WRITE_SEQUENCER_198, 0xf }, | ||
401 | { WM8996_WRITE_SEQUENCER_199, 0x6 }, | ||
402 | { WM8996_WRITE_SEQUENCER_200, 0x1 }, | ||
403 | { WM8996_WRITE_SEQUENCER_201, 0x3 }, | ||
404 | { WM8996_WRITE_SEQUENCER_202, 0x106 }, | ||
405 | { WM8996_WRITE_SEQUENCER_204, 0x61 }, | ||
406 | { WM8996_WRITE_SEQUENCER_205, 0x11 }, | ||
407 | { WM8996_WRITE_SEQUENCER_206, 0x401 }, | ||
408 | { WM8996_WRITE_SEQUENCER_208, 0x50 }, | ||
409 | { WM8996_WRITE_SEQUENCER_209, 0x3 }, | ||
410 | { WM8996_WRITE_SEQUENCER_210, 0x102 }, | ||
411 | { WM8996_WRITE_SEQUENCER_212, 0x61 }, | ||
412 | { WM8996_WRITE_SEQUENCER_213, 0x3b }, | ||
413 | { WM8996_WRITE_SEQUENCER_214, 0x502 }, | ||
414 | { WM8996_WRITE_SEQUENCER_215, 0x100 }, | ||
415 | { WM8996_WRITE_SEQUENCER_216, 0x2fff }, | ||
416 | { WM8996_WRITE_SEQUENCER_220, 0x2fff }, | ||
417 | { WM8996_WRITE_SEQUENCER_224, 0x2fff }, | ||
418 | { WM8996_WRITE_SEQUENCER_228, 0x2fff }, | ||
419 | { WM8996_WRITE_SEQUENCER_232, 0x2fff }, | ||
420 | { WM8996_WRITE_SEQUENCER_236, 0x2fff }, | ||
421 | { WM8996_WRITE_SEQUENCER_240, 0x2fff }, | ||
422 | { WM8996_WRITE_SEQUENCER_244, 0x2fff }, | ||
423 | { WM8996_WRITE_SEQUENCER_248, 0x2fff }, | ||
424 | { WM8996_WRITE_SEQUENCER_252, 0x2fff }, | ||
425 | { WM8996_WRITE_SEQUENCER_256, 0x60 }, | ||
426 | { WM8996_WRITE_SEQUENCER_258, 0x601 }, | ||
427 | { WM8996_WRITE_SEQUENCER_260, 0x50 }, | ||
428 | { WM8996_WRITE_SEQUENCER_262, 0x100 }, | ||
429 | { WM8996_WRITE_SEQUENCER_264, 0x1 }, | ||
430 | { WM8996_WRITE_SEQUENCER_266, 0x104 }, | ||
431 | { WM8996_WRITE_SEQUENCER_267, 0x100 }, | ||
432 | { WM8996_WRITE_SEQUENCER_268, 0x2fff }, | ||
433 | { WM8996_WRITE_SEQUENCER_272, 0x2fff }, | ||
434 | { WM8996_WRITE_SEQUENCER_276, 0x2fff }, | ||
435 | { WM8996_WRITE_SEQUENCER_280, 0x2fff }, | ||
436 | { WM8996_WRITE_SEQUENCER_284, 0x2fff }, | ||
437 | { WM8996_WRITE_SEQUENCER_288, 0x2fff }, | ||
438 | { WM8996_WRITE_SEQUENCER_292, 0x2fff }, | ||
439 | { WM8996_WRITE_SEQUENCER_296, 0x2fff }, | ||
440 | { WM8996_WRITE_SEQUENCER_300, 0x2fff }, | ||
441 | { WM8996_WRITE_SEQUENCER_304, 0x2fff }, | ||
442 | { WM8996_WRITE_SEQUENCER_308, 0x2fff }, | ||
443 | { WM8996_WRITE_SEQUENCER_312, 0x2fff }, | ||
444 | { WM8996_WRITE_SEQUENCER_316, 0x2fff }, | ||
445 | { WM8996_WRITE_SEQUENCER_320, 0x61 }, | ||
446 | { WM8996_WRITE_SEQUENCER_322, 0x601 }, | ||
447 | { WM8996_WRITE_SEQUENCER_324, 0x50 }, | ||
448 | { WM8996_WRITE_SEQUENCER_326, 0x102 }, | ||
449 | { WM8996_WRITE_SEQUENCER_328, 0x1 }, | ||
450 | { WM8996_WRITE_SEQUENCER_330, 0x106 }, | ||
451 | { WM8996_WRITE_SEQUENCER_331, 0x100 }, | ||
452 | { WM8996_WRITE_SEQUENCER_332, 0x2fff }, | ||
453 | { WM8996_WRITE_SEQUENCER_336, 0x2fff }, | ||
454 | { WM8996_WRITE_SEQUENCER_340, 0x2fff }, | ||
455 | { WM8996_WRITE_SEQUENCER_344, 0x2fff }, | ||
456 | { WM8996_WRITE_SEQUENCER_348, 0x2fff }, | ||
457 | { WM8996_WRITE_SEQUENCER_352, 0x2fff }, | ||
458 | { WM8996_WRITE_SEQUENCER_356, 0x2fff }, | ||
459 | { WM8996_WRITE_SEQUENCER_360, 0x2fff }, | ||
460 | { WM8996_WRITE_SEQUENCER_364, 0x2fff }, | ||
461 | { WM8996_WRITE_SEQUENCER_368, 0x2fff }, | ||
462 | { WM8996_WRITE_SEQUENCER_372, 0x2fff }, | ||
463 | { WM8996_WRITE_SEQUENCER_376, 0x2fff }, | ||
464 | { WM8996_WRITE_SEQUENCER_380, 0x2fff }, | ||
465 | { WM8996_WRITE_SEQUENCER_384, 0x60 }, | ||
466 | { WM8996_WRITE_SEQUENCER_386, 0x601 }, | ||
467 | { WM8996_WRITE_SEQUENCER_388, 0x61 }, | ||
468 | { WM8996_WRITE_SEQUENCER_390, 0x601 }, | ||
469 | { WM8996_WRITE_SEQUENCER_392, 0x50 }, | ||
470 | { WM8996_WRITE_SEQUENCER_394, 0x300 }, | ||
471 | { WM8996_WRITE_SEQUENCER_396, 0x1 }, | ||
472 | { WM8996_WRITE_SEQUENCER_398, 0x304 }, | ||
473 | { WM8996_WRITE_SEQUENCER_400, 0x40 }, | ||
474 | { WM8996_WRITE_SEQUENCER_402, 0xf }, | ||
475 | { WM8996_WRITE_SEQUENCER_404, 0x1 }, | ||
476 | { WM8996_WRITE_SEQUENCER_407, 0x100 }, | ||
477 | }; | 299 | }; |
478 | 300 | ||
479 | static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0); | 301 | static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0); |
@@ -1706,18 +1528,6 @@ static bool wm8996_volatile_register(struct device *dev, unsigned int reg) | |||
1706 | } | 1528 | } |
1707 | } | 1529 | } |
1708 | 1530 | ||
1709 | static int wm8996_reset(struct wm8996_priv *wm8996) | ||
1710 | { | ||
1711 | if (wm8996->pdata.ldo_ena > 0) { | ||
1712 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | ||
1713 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1); | ||
1714 | return 0; | ||
1715 | } else { | ||
1716 | return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET, | ||
1717 | 0x8915); | ||
1718 | } | ||
1719 | } | ||
1720 | |||
1721 | static const int bclk_divs[] = { | 1531 | static const int bclk_divs[] = { |
1722 | 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96 | 1532 | 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96 |
1723 | }; | 1533 | }; |
@@ -1809,8 +1619,10 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, | |||
1809 | 1619 | ||
1810 | case SND_SOC_BIAS_OFF: | 1620 | case SND_SOC_BIAS_OFF: |
1811 | regcache_cache_only(codec->control_data, true); | 1621 | regcache_cache_only(codec->control_data, true); |
1812 | if (wm8996->pdata.ldo_ena >= 0) | 1622 | if (wm8996->pdata.ldo_ena >= 0) { |
1813 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | 1623 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
1624 | regcache_cache_only(codec->control_data, true); | ||
1625 | } | ||
1814 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), | 1626 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), |
1815 | wm8996->supplies); | 1627 | wm8996->supplies); |
1816 | break; | 1628 | break; |
@@ -2807,7 +2619,7 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2807 | int ret; | 2619 | int ret; |
2808 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 2620 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
2809 | struct i2c_client *i2c = to_i2c_client(codec->dev); | 2621 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
2810 | int i, irq_flags; | 2622 | int irq_flags; |
2811 | 2623 | ||
2812 | wm8996->codec = codec; | 2624 | wm8996->codec = codec; |
2813 | 2625 | ||
@@ -2822,177 +2634,12 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2822 | goto err; | 2634 | goto err; |
2823 | } | 2635 | } |
2824 | 2636 | ||
2825 | wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0; | ||
2826 | wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1; | ||
2827 | wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2; | ||
2828 | |||
2829 | /* This should really be moved into the regulator core */ | ||
2830 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) { | ||
2831 | ret = regulator_register_notifier(wm8996->supplies[i].consumer, | ||
2832 | &wm8996->disable_nb[i]); | ||
2833 | if (ret != 0) { | ||
2834 | dev_err(codec->dev, | ||
2835 | "Failed to register regulator notifier: %d\n", | ||
2836 | ret); | ||
2837 | } | ||
2838 | } | ||
2839 | |||
2840 | /* Apply platform data settings */ | ||
2841 | snd_soc_update_bits(codec, WM8996_LINE_INPUT_CONTROL, | ||
2842 | WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK, | ||
2843 | wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT | | ||
2844 | wm8996->pdata.inr_mode); | ||
2845 | |||
2846 | for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) { | ||
2847 | if (!wm8996->pdata.gpio_default[i]) | ||
2848 | continue; | ||
2849 | |||
2850 | snd_soc_write(codec, WM8996_GPIO_1 + i, | ||
2851 | wm8996->pdata.gpio_default[i] & 0xffff); | ||
2852 | } | ||
2853 | |||
2854 | if (wm8996->pdata.spkmute_seq) | ||
2855 | snd_soc_update_bits(codec, WM8996_PDM_SPEAKER_MUTE_SEQUENCE, | ||
2856 | WM8996_SPK_MUTE_ENDIAN | | ||
2857 | WM8996_SPK_MUTE_SEQ1_MASK, | ||
2858 | wm8996->pdata.spkmute_seq); | ||
2859 | |||
2860 | snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_2, | ||
2861 | WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC | | ||
2862 | WM8996_MICD_SRC, wm8996->pdata.micdet_def); | ||
2863 | |||
2864 | /* Latch volume update bits */ | ||
2865 | snd_soc_update_bits(codec, WM8996_LEFT_LINE_INPUT_VOLUME, | ||
2866 | WM8996_IN1_VU, WM8996_IN1_VU); | ||
2867 | snd_soc_update_bits(codec, WM8996_RIGHT_LINE_INPUT_VOLUME, | ||
2868 | WM8996_IN1_VU, WM8996_IN1_VU); | ||
2869 | |||
2870 | snd_soc_update_bits(codec, WM8996_DAC1_LEFT_VOLUME, | ||
2871 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2872 | snd_soc_update_bits(codec, WM8996_DAC1_RIGHT_VOLUME, | ||
2873 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2874 | snd_soc_update_bits(codec, WM8996_DAC2_LEFT_VOLUME, | ||
2875 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2876 | snd_soc_update_bits(codec, WM8996_DAC2_RIGHT_VOLUME, | ||
2877 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2878 | |||
2879 | snd_soc_update_bits(codec, WM8996_OUTPUT1_LEFT_VOLUME, | ||
2880 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2881 | snd_soc_update_bits(codec, WM8996_OUTPUT1_RIGHT_VOLUME, | ||
2882 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2883 | snd_soc_update_bits(codec, WM8996_OUTPUT2_LEFT_VOLUME, | ||
2884 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2885 | snd_soc_update_bits(codec, WM8996_OUTPUT2_RIGHT_VOLUME, | ||
2886 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2887 | |||
2888 | snd_soc_update_bits(codec, WM8996_DSP1_TX_LEFT_VOLUME, | ||
2889 | WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); | ||
2890 | snd_soc_update_bits(codec, WM8996_DSP1_TX_RIGHT_VOLUME, | ||
2891 | WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); | ||
2892 | snd_soc_update_bits(codec, WM8996_DSP2_TX_LEFT_VOLUME, | ||
2893 | WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); | ||
2894 | snd_soc_update_bits(codec, WM8996_DSP2_TX_RIGHT_VOLUME, | ||
2895 | WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); | ||
2896 | |||
2897 | snd_soc_update_bits(codec, WM8996_DSP1_RX_LEFT_VOLUME, | ||
2898 | WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); | ||
2899 | snd_soc_update_bits(codec, WM8996_DSP1_RX_RIGHT_VOLUME, | ||
2900 | WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); | ||
2901 | snd_soc_update_bits(codec, WM8996_DSP2_RX_LEFT_VOLUME, | ||
2902 | WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); | ||
2903 | snd_soc_update_bits(codec, WM8996_DSP2_RX_RIGHT_VOLUME, | ||
2904 | WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); | ||
2905 | |||
2906 | /* No support currently for the underclocked TDM modes and | ||
2907 | * pick a default TDM layout with each channel pair working with | ||
2908 | * slots 0 and 1. */ | ||
2909 | snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_0_CONFIGURATION, | ||
2910 | WM8996_AIF1RX_CHAN0_SLOTS_MASK | | ||
2911 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2912 | 1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0); | ||
2913 | snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_1_CONFIGURATION, | ||
2914 | WM8996_AIF1RX_CHAN1_SLOTS_MASK | | ||
2915 | WM8996_AIF1RX_CHAN1_START_SLOT_MASK, | ||
2916 | 1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1); | ||
2917 | snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_2_CONFIGURATION, | ||
2918 | WM8996_AIF1RX_CHAN2_SLOTS_MASK | | ||
2919 | WM8996_AIF1RX_CHAN2_START_SLOT_MASK, | ||
2920 | 1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0); | ||
2921 | snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_3_CONFIGURATION, | ||
2922 | WM8996_AIF1RX_CHAN3_SLOTS_MASK | | ||
2923 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2924 | 1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1); | ||
2925 | snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_4_CONFIGURATION, | ||
2926 | WM8996_AIF1RX_CHAN4_SLOTS_MASK | | ||
2927 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2928 | 1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0); | ||
2929 | snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_5_CONFIGURATION, | ||
2930 | WM8996_AIF1RX_CHAN5_SLOTS_MASK | | ||
2931 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2932 | 1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1); | ||
2933 | |||
2934 | snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_0_CONFIGURATION, | ||
2935 | WM8996_AIF2RX_CHAN0_SLOTS_MASK | | ||
2936 | WM8996_AIF2RX_CHAN0_START_SLOT_MASK, | ||
2937 | 1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0); | ||
2938 | snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_1_CONFIGURATION, | ||
2939 | WM8996_AIF2RX_CHAN1_SLOTS_MASK | | ||
2940 | WM8996_AIF2RX_CHAN1_START_SLOT_MASK, | ||
2941 | 1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1); | ||
2942 | |||
2943 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_0_CONFIGURATION, | ||
2944 | WM8996_AIF1TX_CHAN0_SLOTS_MASK | | ||
2945 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2946 | 1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0); | ||
2947 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, | ||
2948 | WM8996_AIF1TX_CHAN1_SLOTS_MASK | | ||
2949 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2950 | 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | ||
2951 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_2_CONFIGURATION, | ||
2952 | WM8996_AIF1TX_CHAN2_SLOTS_MASK | | ||
2953 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2954 | 1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0); | ||
2955 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_3_CONFIGURATION, | ||
2956 | WM8996_AIF1TX_CHAN3_SLOTS_MASK | | ||
2957 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2958 | 1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1); | ||
2959 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_4_CONFIGURATION, | ||
2960 | WM8996_AIF1TX_CHAN4_SLOTS_MASK | | ||
2961 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2962 | 1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0); | ||
2963 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_5_CONFIGURATION, | ||
2964 | WM8996_AIF1TX_CHAN5_SLOTS_MASK | | ||
2965 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2966 | 1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1); | ||
2967 | |||
2968 | snd_soc_update_bits(codec, WM8996_AIF2TX_CHANNEL_0_CONFIGURATION, | ||
2969 | WM8996_AIF2TX_CHAN0_SLOTS_MASK | | ||
2970 | WM8996_AIF2TX_CHAN0_START_SLOT_MASK, | ||
2971 | 1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0); | ||
2972 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, | ||
2973 | WM8996_AIF2TX_CHAN1_SLOTS_MASK | | ||
2974 | WM8996_AIF2TX_CHAN1_START_SLOT_MASK, | ||
2975 | 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | ||
2976 | |||
2977 | if (wm8996->pdata.num_retune_mobile_cfgs) | 2637 | if (wm8996->pdata.num_retune_mobile_cfgs) |
2978 | wm8996_retune_mobile_pdata(codec); | 2638 | wm8996_retune_mobile_pdata(codec); |
2979 | else | 2639 | else |
2980 | snd_soc_add_codec_controls(codec, wm8996_eq_controls, | 2640 | snd_soc_add_codec_controls(codec, wm8996_eq_controls, |
2981 | ARRAY_SIZE(wm8996_eq_controls)); | 2641 | ARRAY_SIZE(wm8996_eq_controls)); |
2982 | 2642 | ||
2983 | /* If the TX LRCLK pins are not in LRCLK mode configure the | ||
2984 | * AIFs to source their clocks from the RX LRCLKs. | ||
2985 | */ | ||
2986 | if ((snd_soc_read(codec, WM8996_GPIO_1))) | ||
2987 | snd_soc_update_bits(codec, WM8996_AIF1_TX_LRCLK_2, | ||
2988 | WM8996_AIF1TX_LRCLK_MODE, | ||
2989 | WM8996_AIF1TX_LRCLK_MODE); | ||
2990 | |||
2991 | if ((snd_soc_read(codec, WM8996_GPIO_2))) | ||
2992 | snd_soc_update_bits(codec, WM8996_AIF2_TX_LRCLK_2, | ||
2993 | WM8996_AIF2TX_LRCLK_MODE, | ||
2994 | WM8996_AIF2TX_LRCLK_MODE); | ||
2995 | |||
2996 | if (i2c->irq) { | 2643 | if (i2c->irq) { |
2997 | if (wm8996->pdata.irq_flags) | 2644 | if (wm8996->pdata.irq_flags) |
2998 | irq_flags = wm8996->pdata.irq_flags; | 2645 | irq_flags = wm8996->pdata.irq_flags; |
@@ -3036,9 +2683,7 @@ err: | |||
3036 | 2683 | ||
3037 | static int wm8996_remove(struct snd_soc_codec *codec) | 2684 | static int wm8996_remove(struct snd_soc_codec *codec) |
3038 | { | 2685 | { |
3039 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
3040 | struct i2c_client *i2c = to_i2c_client(codec->dev); | 2686 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
3041 | int i; | ||
3042 | 2687 | ||
3043 | snd_soc_update_bits(codec, WM8996_INTERRUPT_CONTROL, | 2688 | snd_soc_update_bits(codec, WM8996_INTERRUPT_CONTROL, |
3044 | WM8996_IM_IRQ, WM8996_IM_IRQ); | 2689 | WM8996_IM_IRQ, WM8996_IM_IRQ); |
@@ -3046,10 +2691,6 @@ static int wm8996_remove(struct snd_soc_codec *codec) | |||
3046 | if (i2c->irq) | 2691 | if (i2c->irq) |
3047 | free_irq(i2c->irq, codec); | 2692 | free_irq(i2c->irq, codec); |
3048 | 2693 | ||
3049 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) | ||
3050 | regulator_unregister_notifier(wm8996->supplies[i].consumer, | ||
3051 | &wm8996->disable_nb[i]); | ||
3052 | |||
3053 | return 0; | 2694 | return 0; |
3054 | } | 2695 | } |
3055 | 2696 | ||
@@ -3163,6 +2804,21 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, | |||
3163 | goto err_gpio; | 2804 | goto err_gpio; |
3164 | } | 2805 | } |
3165 | 2806 | ||
2807 | wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0; | ||
2808 | wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1; | ||
2809 | wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2; | ||
2810 | |||
2811 | /* This should really be moved into the regulator core */ | ||
2812 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) { | ||
2813 | ret = regulator_register_notifier(wm8996->supplies[i].consumer, | ||
2814 | &wm8996->disable_nb[i]); | ||
2815 | if (ret != 0) { | ||
2816 | dev_err(&i2c->dev, | ||
2817 | "Failed to register regulator notifier: %d\n", | ||
2818 | ret); | ||
2819 | } | ||
2820 | } | ||
2821 | |||
3166 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies), | 2822 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies), |
3167 | wm8996->supplies); | 2823 | wm8996->supplies); |
3168 | if (ret != 0) { | 2824 | if (ret != 0) { |
@@ -3175,7 +2831,7 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, | |||
3175 | msleep(5); | 2831 | msleep(5); |
3176 | } | 2832 | } |
3177 | 2833 | ||
3178 | wm8996->regmap = regmap_init_i2c(i2c, &wm8996_regmap); | 2834 | wm8996->regmap = devm_regmap_init_i2c(i2c, &wm8996_regmap); |
3179 | if (IS_ERR(wm8996->regmap)) { | 2835 | if (IS_ERR(wm8996->regmap)) { |
3180 | ret = PTR_ERR(wm8996->regmap); | 2836 | ret = PTR_ERR(wm8996->regmap); |
3181 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); | 2837 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); |
@@ -3203,15 +2859,199 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, | |||
3203 | dev_info(&i2c->dev, "revision %c\n", | 2859 | dev_info(&i2c->dev, "revision %c\n", |
3204 | (reg & WM8996_CHIP_REV_MASK) + 'A'); | 2860 | (reg & WM8996_CHIP_REV_MASK) + 'A'); |
3205 | 2861 | ||
3206 | ret = wm8996_reset(wm8996); | 2862 | if (wm8996->pdata.ldo_ena > 0) { |
3207 | if (ret < 0) { | 2863 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
3208 | dev_err(&i2c->dev, "Failed to issue reset\n"); | 2864 | regcache_cache_only(wm8996->regmap, true); |
3209 | goto err_regmap; | 2865 | } else { |
2866 | ret = regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET, | ||
2867 | 0x8915); | ||
2868 | if (ret != 0) { | ||
2869 | dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); | ||
2870 | goto err_regmap; | ||
2871 | } | ||
3210 | } | 2872 | } |
3211 | 2873 | ||
3212 | regcache_cache_only(wm8996->regmap, true); | ||
3213 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); | 2874 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); |
3214 | 2875 | ||
2876 | /* Apply platform data settings */ | ||
2877 | regmap_update_bits(wm8996->regmap, WM8996_LINE_INPUT_CONTROL, | ||
2878 | WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK, | ||
2879 | wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT | | ||
2880 | wm8996->pdata.inr_mode); | ||
2881 | |||
2882 | for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) { | ||
2883 | if (!wm8996->pdata.gpio_default[i]) | ||
2884 | continue; | ||
2885 | |||
2886 | regmap_write(wm8996->regmap, WM8996_GPIO_1 + i, | ||
2887 | wm8996->pdata.gpio_default[i] & 0xffff); | ||
2888 | } | ||
2889 | |||
2890 | if (wm8996->pdata.spkmute_seq) | ||
2891 | regmap_update_bits(wm8996->regmap, | ||
2892 | WM8996_PDM_SPEAKER_MUTE_SEQUENCE, | ||
2893 | WM8996_SPK_MUTE_ENDIAN | | ||
2894 | WM8996_SPK_MUTE_SEQ1_MASK, | ||
2895 | wm8996->pdata.spkmute_seq); | ||
2896 | |||
2897 | regmap_update_bits(wm8996->regmap, WM8996_ACCESSORY_DETECT_MODE_2, | ||
2898 | WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC | | ||
2899 | WM8996_MICD_SRC, wm8996->pdata.micdet_def); | ||
2900 | |||
2901 | /* Latch volume update bits */ | ||
2902 | regmap_update_bits(wm8996->regmap, WM8996_LEFT_LINE_INPUT_VOLUME, | ||
2903 | WM8996_IN1_VU, WM8996_IN1_VU); | ||
2904 | regmap_update_bits(wm8996->regmap, WM8996_RIGHT_LINE_INPUT_VOLUME, | ||
2905 | WM8996_IN1_VU, WM8996_IN1_VU); | ||
2906 | |||
2907 | regmap_update_bits(wm8996->regmap, WM8996_DAC1_LEFT_VOLUME, | ||
2908 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2909 | regmap_update_bits(wm8996->regmap, WM8996_DAC1_RIGHT_VOLUME, | ||
2910 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2911 | regmap_update_bits(wm8996->regmap, WM8996_DAC2_LEFT_VOLUME, | ||
2912 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2913 | regmap_update_bits(wm8996->regmap, WM8996_DAC2_RIGHT_VOLUME, | ||
2914 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2915 | |||
2916 | regmap_update_bits(wm8996->regmap, WM8996_OUTPUT1_LEFT_VOLUME, | ||
2917 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2918 | regmap_update_bits(wm8996->regmap, WM8996_OUTPUT1_RIGHT_VOLUME, | ||
2919 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2920 | regmap_update_bits(wm8996->regmap, WM8996_OUTPUT2_LEFT_VOLUME, | ||
2921 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2922 | regmap_update_bits(wm8996->regmap, WM8996_OUTPUT2_RIGHT_VOLUME, | ||
2923 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2924 | |||
2925 | regmap_update_bits(wm8996->regmap, WM8996_DSP1_TX_LEFT_VOLUME, | ||
2926 | WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); | ||
2927 | regmap_update_bits(wm8996->regmap, WM8996_DSP1_TX_RIGHT_VOLUME, | ||
2928 | WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); | ||
2929 | regmap_update_bits(wm8996->regmap, WM8996_DSP2_TX_LEFT_VOLUME, | ||
2930 | WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); | ||
2931 | regmap_update_bits(wm8996->regmap, WM8996_DSP2_TX_RIGHT_VOLUME, | ||
2932 | WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); | ||
2933 | |||
2934 | regmap_update_bits(wm8996->regmap, WM8996_DSP1_RX_LEFT_VOLUME, | ||
2935 | WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); | ||
2936 | regmap_update_bits(wm8996->regmap, WM8996_DSP1_RX_RIGHT_VOLUME, | ||
2937 | WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); | ||
2938 | regmap_update_bits(wm8996->regmap, WM8996_DSP2_RX_LEFT_VOLUME, | ||
2939 | WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); | ||
2940 | regmap_update_bits(wm8996->regmap, WM8996_DSP2_RX_RIGHT_VOLUME, | ||
2941 | WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); | ||
2942 | |||
2943 | /* No support currently for the underclocked TDM modes and | ||
2944 | * pick a default TDM layout with each channel pair working with | ||
2945 | * slots 0 and 1. */ | ||
2946 | regmap_update_bits(wm8996->regmap, | ||
2947 | WM8996_AIF1RX_CHANNEL_0_CONFIGURATION, | ||
2948 | WM8996_AIF1RX_CHAN0_SLOTS_MASK | | ||
2949 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2950 | 1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0); | ||
2951 | regmap_update_bits(wm8996->regmap, | ||
2952 | WM8996_AIF1RX_CHANNEL_1_CONFIGURATION, | ||
2953 | WM8996_AIF1RX_CHAN1_SLOTS_MASK | | ||
2954 | WM8996_AIF1RX_CHAN1_START_SLOT_MASK, | ||
2955 | 1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1); | ||
2956 | regmap_update_bits(wm8996->regmap, | ||
2957 | WM8996_AIF1RX_CHANNEL_2_CONFIGURATION, | ||
2958 | WM8996_AIF1RX_CHAN2_SLOTS_MASK | | ||
2959 | WM8996_AIF1RX_CHAN2_START_SLOT_MASK, | ||
2960 | 1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0); | ||
2961 | regmap_update_bits(wm8996->regmap, | ||
2962 | WM8996_AIF1RX_CHANNEL_3_CONFIGURATION, | ||
2963 | WM8996_AIF1RX_CHAN3_SLOTS_MASK | | ||
2964 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2965 | 1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1); | ||
2966 | regmap_update_bits(wm8996->regmap, | ||
2967 | WM8996_AIF1RX_CHANNEL_4_CONFIGURATION, | ||
2968 | WM8996_AIF1RX_CHAN4_SLOTS_MASK | | ||
2969 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2970 | 1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0); | ||
2971 | regmap_update_bits(wm8996->regmap, | ||
2972 | WM8996_AIF1RX_CHANNEL_5_CONFIGURATION, | ||
2973 | WM8996_AIF1RX_CHAN5_SLOTS_MASK | | ||
2974 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2975 | 1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1); | ||
2976 | |||
2977 | regmap_update_bits(wm8996->regmap, | ||
2978 | WM8996_AIF2RX_CHANNEL_0_CONFIGURATION, | ||
2979 | WM8996_AIF2RX_CHAN0_SLOTS_MASK | | ||
2980 | WM8996_AIF2RX_CHAN0_START_SLOT_MASK, | ||
2981 | 1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0); | ||
2982 | regmap_update_bits(wm8996->regmap, | ||
2983 | WM8996_AIF2RX_CHANNEL_1_CONFIGURATION, | ||
2984 | WM8996_AIF2RX_CHAN1_SLOTS_MASK | | ||
2985 | WM8996_AIF2RX_CHAN1_START_SLOT_MASK, | ||
2986 | 1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1); | ||
2987 | |||
2988 | regmap_update_bits(wm8996->regmap, | ||
2989 | WM8996_AIF1TX_CHANNEL_0_CONFIGURATION, | ||
2990 | WM8996_AIF1TX_CHAN0_SLOTS_MASK | | ||
2991 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2992 | 1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0); | ||
2993 | regmap_update_bits(wm8996->regmap, | ||
2994 | WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, | ||
2995 | WM8996_AIF1TX_CHAN1_SLOTS_MASK | | ||
2996 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2997 | 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | ||
2998 | regmap_update_bits(wm8996->regmap, | ||
2999 | WM8996_AIF1TX_CHANNEL_2_CONFIGURATION, | ||
3000 | WM8996_AIF1TX_CHAN2_SLOTS_MASK | | ||
3001 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
3002 | 1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0); | ||
3003 | regmap_update_bits(wm8996->regmap, | ||
3004 | WM8996_AIF1TX_CHANNEL_3_CONFIGURATION, | ||
3005 | WM8996_AIF1TX_CHAN3_SLOTS_MASK | | ||
3006 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
3007 | 1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1); | ||
3008 | regmap_update_bits(wm8996->regmap, | ||
3009 | WM8996_AIF1TX_CHANNEL_4_CONFIGURATION, | ||
3010 | WM8996_AIF1TX_CHAN4_SLOTS_MASK | | ||
3011 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
3012 | 1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0); | ||
3013 | regmap_update_bits(wm8996->regmap, | ||
3014 | WM8996_AIF1TX_CHANNEL_5_CONFIGURATION, | ||
3015 | WM8996_AIF1TX_CHAN5_SLOTS_MASK | | ||
3016 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
3017 | 1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1); | ||
3018 | |||
3019 | regmap_update_bits(wm8996->regmap, | ||
3020 | WM8996_AIF2TX_CHANNEL_0_CONFIGURATION, | ||
3021 | WM8996_AIF2TX_CHAN0_SLOTS_MASK | | ||
3022 | WM8996_AIF2TX_CHAN0_START_SLOT_MASK, | ||
3023 | 1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0); | ||
3024 | regmap_update_bits(wm8996->regmap, | ||
3025 | WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, | ||
3026 | WM8996_AIF2TX_CHAN1_SLOTS_MASK | | ||
3027 | WM8996_AIF2TX_CHAN1_START_SLOT_MASK, | ||
3028 | 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | ||
3029 | |||
3030 | /* If the TX LRCLK pins are not in LRCLK mode configure the | ||
3031 | * AIFs to source their clocks from the RX LRCLKs. | ||
3032 | */ | ||
3033 | ret = regmap_read(wm8996->regmap, WM8996_GPIO_1, ®); | ||
3034 | if (ret != 0) { | ||
3035 | dev_err(&i2c->dev, "Failed to read GPIO1: %d\n", ret); | ||
3036 | goto err_regmap; | ||
3037 | } | ||
3038 | |||
3039 | if (reg & WM8996_GP1_FN_MASK) | ||
3040 | regmap_update_bits(wm8996->regmap, WM8996_AIF1_TX_LRCLK_2, | ||
3041 | WM8996_AIF1TX_LRCLK_MODE, | ||
3042 | WM8996_AIF1TX_LRCLK_MODE); | ||
3043 | |||
3044 | ret = regmap_read(wm8996->regmap, WM8996_GPIO_2, ®); | ||
3045 | if (ret != 0) { | ||
3046 | dev_err(&i2c->dev, "Failed to read GPIO2: %d\n", ret); | ||
3047 | goto err_regmap; | ||
3048 | } | ||
3049 | |||
3050 | if (reg & WM8996_GP2_FN_MASK) | ||
3051 | regmap_update_bits(wm8996->regmap, WM8996_AIF2_TX_LRCLK_2, | ||
3052 | WM8996_AIF2TX_LRCLK_MODE, | ||
3053 | WM8996_AIF2TX_LRCLK_MODE); | ||
3054 | |||
3215 | wm8996_init_gpio(wm8996); | 3055 | wm8996_init_gpio(wm8996); |
3216 | 3056 | ||
3217 | ret = snd_soc_register_codec(&i2c->dev, | 3057 | ret = snd_soc_register_codec(&i2c->dev, |
@@ -3225,7 +3065,6 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, | |||
3225 | err_gpiolib: | 3065 | err_gpiolib: |
3226 | wm8996_free_gpio(wm8996); | 3066 | wm8996_free_gpio(wm8996); |
3227 | err_regmap: | 3067 | err_regmap: |
3228 | regmap_exit(wm8996->regmap); | ||
3229 | err_enable: | 3068 | err_enable: |
3230 | if (wm8996->pdata.ldo_ena > 0) | 3069 | if (wm8996->pdata.ldo_ena > 0) |
3231 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | 3070 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
@@ -3241,14 +3080,18 @@ err: | |||
3241 | static __devexit int wm8996_i2c_remove(struct i2c_client *client) | 3080 | static __devexit int wm8996_i2c_remove(struct i2c_client *client) |
3242 | { | 3081 | { |
3243 | struct wm8996_priv *wm8996 = i2c_get_clientdata(client); | 3082 | struct wm8996_priv *wm8996 = i2c_get_clientdata(client); |
3083 | int i; | ||
3244 | 3084 | ||
3245 | snd_soc_unregister_codec(&client->dev); | 3085 | snd_soc_unregister_codec(&client->dev); |
3246 | wm8996_free_gpio(wm8996); | 3086 | wm8996_free_gpio(wm8996); |
3247 | regmap_exit(wm8996->regmap); | ||
3248 | if (wm8996->pdata.ldo_ena > 0) { | 3087 | if (wm8996->pdata.ldo_ena > 0) { |
3249 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | 3088 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
3250 | gpio_free(wm8996->pdata.ldo_ena); | 3089 | gpio_free(wm8996->pdata.ldo_ena); |
3251 | } | 3090 | } |
3091 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) | ||
3092 | regulator_unregister_notifier(wm8996->supplies[i].consumer, | ||
3093 | &wm8996->disable_nb[i]); | ||
3094 | |||
3252 | return 0; | 3095 | return 0; |
3253 | } | 3096 | } |
3254 | 3097 | ||
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 9328270df16c..2de74e1ea225 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Author: Mark Brown | 4 | * Author: Mark Brown |
5 | * | 5 | * |
6 | * Copyright 2009 Wolfson Microelectronics plc | 6 | * Copyright 2009-12 Wolfson Microelectronics plc |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 4b263b6edf13..2c2346fdd637 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA SoC WM9090 driver | 2 | * ALSA SoC WM9090 driver |
3 | * | 3 | * |
4 | * Copyright 2009, 2010 Wolfson Microelectronics | 4 | * Copyright 2009-12 Wolfson Microelectronics |
5 | * | 5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index a1541414d904..099e6ec32125 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm9712.c -- ALSA Soc WM9712 codec support | 2 | * wm9712.c -- ALSA Soc WM9712 codec support |
3 | * | 3 | * |
4 | * Copyright 2006 Wolfson Microelectronics PLC. | 4 | * Copyright 2006-12 Wolfson Microelectronics PLC. |
5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> | 5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 2d22cc70d536..3eb19fb71d17 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm9713.c -- ALSA Soc WM9713 codec support | 2 | * wm9713.c -- ALSA Soc WM9713 codec support |
3 | * | 3 | * |
4 | * Copyright 2006 Wolfson Microelectronics PLC. | 4 | * Copyright 2006-10 Wolfson Microelectronics PLC. |
5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> | 5 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index dfe957a47f29..61baa48823cb 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm_hubs.c -- WM8993/4 common code | 2 | * wm_hubs.c -- WM8993/4 common code |
3 | * | 3 | * |
4 | * Copyright 2009 Wolfson Microelectronics plc | 4 | * Copyright 2009-12 Wolfson Microelectronics plc |
5 | * | 5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
diff --git a/sound/soc/dwc/Kconfig b/sound/soc/dwc/Kconfig new file mode 100644 index 000000000000..e334900cf0b8 --- /dev/null +++ b/sound/soc/dwc/Kconfig | |||
@@ -0,0 +1,9 @@ | |||
1 | config SND_DESIGNWARE_I2S | ||
2 | tristate "Synopsys I2S Device Driver" | ||
3 | depends on CLKDEV_LOOKUP | ||
4 | help | ||
5 | Say Y or M if you want to add support for I2S driver for | ||
6 | Synopsys desigwnware I2S device. The device supports upto | ||
7 | maximum of 8 channels each for play and record. | ||
8 | |||
9 | |||
diff --git a/sound/soc/dwc/Makefile b/sound/soc/dwc/Makefile new file mode 100644 index 000000000000..319371f690f4 --- /dev/null +++ b/sound/soc/dwc/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | # SYNOPSYS Platform Support | ||
2 | obj-$(CONFIG_SND_DESIGNWARE_I2S) += designware_i2s.o | ||
3 | |||
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c new file mode 100644 index 000000000000..1aa51300c564 --- /dev/null +++ b/sound/soc/dwc/designware_i2s.c | |||
@@ -0,0 +1,455 @@ | |||
1 | /* | ||
2 | * ALSA SoC Synopsys I2S Audio Layer | ||
3 | * | ||
4 | * sound/soc/spear/designware_i2s.c | ||
5 | * | ||
6 | * Copyright (C) 2010 ST Microelectronics | ||
7 | * Rajeev Kumar <rajeev-dlh.kumar@st.com> | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public | ||
10 | * License version 2. This program is licensed "as is" without any | ||
11 | * warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/clk.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <sound/designware_i2s.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | |||
26 | /* common register for all channel */ | ||
27 | #define IER 0x000 | ||
28 | #define IRER 0x004 | ||
29 | #define ITER 0x008 | ||
30 | #define CER 0x00C | ||
31 | #define CCR 0x010 | ||
32 | #define RXFFR 0x014 | ||
33 | #define TXFFR 0x018 | ||
34 | |||
35 | /* I2STxRxRegisters for all channels */ | ||
36 | #define LRBR_LTHR(x) (0x40 * x + 0x020) | ||
37 | #define RRBR_RTHR(x) (0x40 * x + 0x024) | ||
38 | #define RER(x) (0x40 * x + 0x028) | ||
39 | #define TER(x) (0x40 * x + 0x02C) | ||
40 | #define RCR(x) (0x40 * x + 0x030) | ||
41 | #define TCR(x) (0x40 * x + 0x034) | ||
42 | #define ISR(x) (0x40 * x + 0x038) | ||
43 | #define IMR(x) (0x40 * x + 0x03C) | ||
44 | #define ROR(x) (0x40 * x + 0x040) | ||
45 | #define TOR(x) (0x40 * x + 0x044) | ||
46 | #define RFCR(x) (0x40 * x + 0x048) | ||
47 | #define TFCR(x) (0x40 * x + 0x04C) | ||
48 | #define RFF(x) (0x40 * x + 0x050) | ||
49 | #define TFF(x) (0x40 * x + 0x054) | ||
50 | |||
51 | /* I2SCOMPRegisters */ | ||
52 | #define I2S_COMP_PARAM_2 0x01F0 | ||
53 | #define I2S_COMP_PARAM_1 0x01F4 | ||
54 | #define I2S_COMP_VERSION 0x01F8 | ||
55 | #define I2S_COMP_TYPE 0x01FC | ||
56 | |||
57 | #define MAX_CHANNEL_NUM 8 | ||
58 | #define MIN_CHANNEL_NUM 2 | ||
59 | |||
60 | struct dw_i2s_dev { | ||
61 | void __iomem *i2s_base; | ||
62 | struct clk *clk; | ||
63 | int active; | ||
64 | unsigned int capability; | ||
65 | struct device *dev; | ||
66 | |||
67 | /* data related to DMA transfers b/w i2s and DMAC */ | ||
68 | struct i2s_dma_data play_dma_data; | ||
69 | struct i2s_dma_data capture_dma_data; | ||
70 | struct i2s_clk_config_data config; | ||
71 | int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); | ||
72 | }; | ||
73 | |||
74 | static inline void i2s_write_reg(void __iomem *io_base, int reg, u32 val) | ||
75 | { | ||
76 | writel(val, io_base + reg); | ||
77 | } | ||
78 | |||
79 | static inline u32 i2s_read_reg(void __iomem *io_base, int reg) | ||
80 | { | ||
81 | return readl(io_base + reg); | ||
82 | } | ||
83 | |||
84 | static inline void i2s_disable_channels(struct dw_i2s_dev *dev, u32 stream) | ||
85 | { | ||
86 | u32 i = 0; | ||
87 | |||
88 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
89 | for (i = 0; i < 4; i++) | ||
90 | i2s_write_reg(dev->i2s_base, TER(i), 0); | ||
91 | } else { | ||
92 | for (i = 0; i < 4; i++) | ||
93 | i2s_write_reg(dev->i2s_base, RER(i), 0); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, u32 stream) | ||
98 | { | ||
99 | u32 i = 0; | ||
100 | |||
101 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
102 | for (i = 0; i < 4; i++) | ||
103 | i2s_write_reg(dev->i2s_base, TOR(i), 0); | ||
104 | } else { | ||
105 | for (i = 0; i < 4; i++) | ||
106 | i2s_write_reg(dev->i2s_base, ROR(i), 0); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | static void i2s_start(struct dw_i2s_dev *dev, | ||
111 | struct snd_pcm_substream *substream) | ||
112 | { | ||
113 | |||
114 | i2s_write_reg(dev->i2s_base, IER, 1); | ||
115 | |||
116 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
117 | i2s_write_reg(dev->i2s_base, ITER, 1); | ||
118 | else | ||
119 | i2s_write_reg(dev->i2s_base, IRER, 1); | ||
120 | |||
121 | i2s_write_reg(dev->i2s_base, CER, 1); | ||
122 | } | ||
123 | |||
124 | static void i2s_stop(struct dw_i2s_dev *dev, | ||
125 | struct snd_pcm_substream *substream) | ||
126 | { | ||
127 | u32 i = 0, irq; | ||
128 | |||
129 | i2s_clear_irqs(dev, substream->stream); | ||
130 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
131 | i2s_write_reg(dev->i2s_base, ITER, 0); | ||
132 | |||
133 | for (i = 0; i < 4; i++) { | ||
134 | irq = i2s_read_reg(dev->i2s_base, IMR(i)); | ||
135 | i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x30); | ||
136 | } | ||
137 | } else { | ||
138 | i2s_write_reg(dev->i2s_base, IRER, 0); | ||
139 | |||
140 | for (i = 0; i < 4; i++) { | ||
141 | irq = i2s_read_reg(dev->i2s_base, IMR(i)); | ||
142 | i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x03); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | if (!dev->active) { | ||
147 | i2s_write_reg(dev->i2s_base, CER, 0); | ||
148 | i2s_write_reg(dev->i2s_base, IER, 0); | ||
149 | } | ||
150 | } | ||
151 | |||
152 | static int dw_i2s_startup(struct snd_pcm_substream *substream, | ||
153 | struct snd_soc_dai *cpu_dai) | ||
154 | { | ||
155 | struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); | ||
156 | struct i2s_dma_data *dma_data = NULL; | ||
157 | |||
158 | if (!(dev->capability & DWC_I2S_RECORD) && | ||
159 | (substream->stream == SNDRV_PCM_STREAM_CAPTURE)) | ||
160 | return -EINVAL; | ||
161 | |||
162 | if (!(dev->capability & DWC_I2S_PLAY) && | ||
163 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) | ||
164 | return -EINVAL; | ||
165 | |||
166 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
167 | dma_data = &dev->play_dma_data; | ||
168 | else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
169 | dma_data = &dev->capture_dma_data; | ||
170 | |||
171 | snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data); | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int dw_i2s_hw_params(struct snd_pcm_substream *substream, | ||
177 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
178 | { | ||
179 | struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
180 | struct i2s_clk_config_data *config = &dev->config; | ||
181 | u32 ccr, xfer_resolution, ch_reg, irq; | ||
182 | int ret; | ||
183 | |||
184 | switch (params_format(params)) { | ||
185 | case SNDRV_PCM_FORMAT_S16_LE: | ||
186 | config->data_width = 16; | ||
187 | ccr = 0x00; | ||
188 | xfer_resolution = 0x02; | ||
189 | break; | ||
190 | |||
191 | case SNDRV_PCM_FORMAT_S24_LE: | ||
192 | config->data_width = 24; | ||
193 | ccr = 0x08; | ||
194 | xfer_resolution = 0x04; | ||
195 | break; | ||
196 | |||
197 | case SNDRV_PCM_FORMAT_S32_LE: | ||
198 | config->data_width = 32; | ||
199 | ccr = 0x10; | ||
200 | xfer_resolution = 0x05; | ||
201 | break; | ||
202 | |||
203 | default: | ||
204 | dev_err(dev->dev, "designware-i2s: unsuppted PCM fmt"); | ||
205 | return -EINVAL; | ||
206 | } | ||
207 | |||
208 | config->chan_nr = params_channels(params); | ||
209 | |||
210 | switch (config->chan_nr) { | ||
211 | case EIGHT_CHANNEL_SUPPORT: | ||
212 | ch_reg = 3; | ||
213 | case SIX_CHANNEL_SUPPORT: | ||
214 | ch_reg = 2; | ||
215 | case FOUR_CHANNEL_SUPPORT: | ||
216 | ch_reg = 1; | ||
217 | case TWO_CHANNEL_SUPPORT: | ||
218 | ch_reg = 0; | ||
219 | break; | ||
220 | default: | ||
221 | dev_err(dev->dev, "channel not supported\n"); | ||
222 | } | ||
223 | |||
224 | i2s_disable_channels(dev, substream->stream); | ||
225 | |||
226 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
227 | i2s_write_reg(dev->i2s_base, TCR(ch_reg), xfer_resolution); | ||
228 | i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02); | ||
229 | irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); | ||
230 | i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30); | ||
231 | i2s_write_reg(dev->i2s_base, TER(ch_reg), 1); | ||
232 | } else { | ||
233 | i2s_write_reg(dev->i2s_base, RCR(ch_reg), xfer_resolution); | ||
234 | i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07); | ||
235 | irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); | ||
236 | i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03); | ||
237 | i2s_write_reg(dev->i2s_base, RER(ch_reg), 1); | ||
238 | } | ||
239 | |||
240 | i2s_write_reg(dev->i2s_base, CCR, ccr); | ||
241 | |||
242 | config->sample_rate = params_rate(params); | ||
243 | |||
244 | if (!dev->i2s_clk_cfg) | ||
245 | return -EINVAL; | ||
246 | |||
247 | ret = dev->i2s_clk_cfg(config); | ||
248 | if (ret < 0) { | ||
249 | dev_err(dev->dev, "runtime audio clk config fail\n"); | ||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static void dw_i2s_shutdown(struct snd_pcm_substream *substream, | ||
257 | struct snd_soc_dai *dai) | ||
258 | { | ||
259 | snd_soc_dai_set_dma_data(dai, substream, NULL); | ||
260 | } | ||
261 | |||
262 | static int dw_i2s_trigger(struct snd_pcm_substream *substream, | ||
263 | int cmd, struct snd_soc_dai *dai) | ||
264 | { | ||
265 | struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
266 | int ret = 0; | ||
267 | |||
268 | switch (cmd) { | ||
269 | case SNDRV_PCM_TRIGGER_START: | ||
270 | case SNDRV_PCM_TRIGGER_RESUME: | ||
271 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
272 | dev->active++; | ||
273 | i2s_start(dev, substream); | ||
274 | break; | ||
275 | |||
276 | case SNDRV_PCM_TRIGGER_STOP: | ||
277 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
278 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
279 | dev->active--; | ||
280 | i2s_stop(dev, substream); | ||
281 | break; | ||
282 | default: | ||
283 | ret = -EINVAL; | ||
284 | break; | ||
285 | } | ||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | static struct snd_soc_dai_ops dw_i2s_dai_ops = { | ||
290 | .startup = dw_i2s_startup, | ||
291 | .shutdown = dw_i2s_shutdown, | ||
292 | .hw_params = dw_i2s_hw_params, | ||
293 | .trigger = dw_i2s_trigger, | ||
294 | }; | ||
295 | |||
296 | #ifdef CONFIG_PM | ||
297 | |||
298 | static int dw_i2s_suspend(struct snd_soc_dai *dai) | ||
299 | { | ||
300 | struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
301 | |||
302 | clk_disable(dev->clk); | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int dw_i2s_resume(struct snd_soc_dai *dai) | ||
307 | { | ||
308 | struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
309 | |||
310 | clk_enable(dev->clk); | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | #else | ||
315 | #define dw_i2s_suspend NULL | ||
316 | #define dw_i2s_resume NULL | ||
317 | #endif | ||
318 | |||
319 | static int dw_i2s_probe(struct platform_device *pdev) | ||
320 | { | ||
321 | const struct i2s_platform_data *pdata = pdev->dev.platform_data; | ||
322 | struct dw_i2s_dev *dev; | ||
323 | struct resource *res; | ||
324 | int ret; | ||
325 | unsigned int cap; | ||
326 | struct snd_soc_dai_driver *dw_i2s_dai; | ||
327 | |||
328 | if (!pdata) { | ||
329 | dev_err(&pdev->dev, "Invalid platform data\n"); | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | |||
333 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
334 | if (!res) { | ||
335 | dev_err(&pdev->dev, "no i2s resource defined\n"); | ||
336 | return -ENODEV; | ||
337 | } | ||
338 | |||
339 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
340 | resource_size(res), pdev->name)) { | ||
341 | dev_err(&pdev->dev, "i2s region already claimed\n"); | ||
342 | return -EBUSY; | ||
343 | } | ||
344 | |||
345 | dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); | ||
346 | if (!dev) { | ||
347 | dev_warn(&pdev->dev, "kzalloc fail\n"); | ||
348 | return -ENOMEM; | ||
349 | } | ||
350 | |||
351 | dev->i2s_base = devm_ioremap(&pdev->dev, res->start, | ||
352 | resource_size(res)); | ||
353 | if (!dev->i2s_base) { | ||
354 | dev_err(&pdev->dev, "ioremap fail for i2s_region\n"); | ||
355 | return -ENOMEM; | ||
356 | } | ||
357 | |||
358 | cap = pdata->cap; | ||
359 | dev->capability = cap; | ||
360 | dev->i2s_clk_cfg = pdata->i2s_clk_cfg; | ||
361 | |||
362 | /* Set DMA slaves info */ | ||
363 | |||
364 | dev->play_dma_data.data = pdata->play_dma_data; | ||
365 | dev->capture_dma_data.data = pdata->capture_dma_data; | ||
366 | dev->play_dma_data.addr = res->start + I2S_TXDMA; | ||
367 | dev->capture_dma_data.addr = res->start + I2S_RXDMA; | ||
368 | dev->play_dma_data.max_burst = 16; | ||
369 | dev->capture_dma_data.max_burst = 16; | ||
370 | dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
371 | dev->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
372 | dev->play_dma_data.filter = pdata->filter; | ||
373 | dev->capture_dma_data.filter = pdata->filter; | ||
374 | |||
375 | dev->clk = clk_get(&pdev->dev, NULL); | ||
376 | if (IS_ERR(dev->clk)) | ||
377 | return PTR_ERR(dev->clk); | ||
378 | |||
379 | ret = clk_enable(dev->clk); | ||
380 | if (ret < 0) | ||
381 | goto err_clk_put; | ||
382 | |||
383 | dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL); | ||
384 | if (!dw_i2s_dai) { | ||
385 | dev_err(&pdev->dev, "mem allocation failed for dai driver\n"); | ||
386 | ret = -ENOMEM; | ||
387 | goto err_clk_disable; | ||
388 | } | ||
389 | |||
390 | if (cap & DWC_I2S_PLAY) { | ||
391 | dev_dbg(&pdev->dev, " SPEAr: play supported\n"); | ||
392 | dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM; | ||
393 | dw_i2s_dai->playback.channels_max = pdata->channel; | ||
394 | dw_i2s_dai->playback.formats = pdata->snd_fmts; | ||
395 | dw_i2s_dai->playback.rates = pdata->snd_rates; | ||
396 | } | ||
397 | |||
398 | if (cap & DWC_I2S_RECORD) { | ||
399 | dev_dbg(&pdev->dev, "SPEAr: record supported\n"); | ||
400 | dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; | ||
401 | dw_i2s_dai->capture.channels_max = pdata->channel; | ||
402 | dw_i2s_dai->capture.formats = pdata->snd_fmts; | ||
403 | dw_i2s_dai->capture.rates = pdata->snd_rates; | ||
404 | } | ||
405 | |||
406 | dw_i2s_dai->ops = &dw_i2s_dai_ops; | ||
407 | dw_i2s_dai->suspend = dw_i2s_suspend; | ||
408 | dw_i2s_dai->resume = dw_i2s_resume; | ||
409 | |||
410 | dev->dev = &pdev->dev; | ||
411 | dev_set_drvdata(&pdev->dev, dev); | ||
412 | ret = snd_soc_register_dai(&pdev->dev, dw_i2s_dai); | ||
413 | if (ret != 0) { | ||
414 | dev_err(&pdev->dev, "not able to register dai\n"); | ||
415 | goto err_set_drvdata; | ||
416 | } | ||
417 | |||
418 | return 0; | ||
419 | |||
420 | err_set_drvdata: | ||
421 | dev_set_drvdata(&pdev->dev, NULL); | ||
422 | err_clk_disable: | ||
423 | clk_disable(dev->clk); | ||
424 | err_clk_put: | ||
425 | clk_put(dev->clk); | ||
426 | return ret; | ||
427 | } | ||
428 | |||
429 | static int dw_i2s_remove(struct platform_device *pdev) | ||
430 | { | ||
431 | struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev); | ||
432 | |||
433 | snd_soc_unregister_dai(&pdev->dev); | ||
434 | dev_set_drvdata(&pdev->dev, NULL); | ||
435 | |||
436 | clk_put(dev->clk); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static struct platform_driver dw_i2s_driver = { | ||
442 | .probe = dw_i2s_probe, | ||
443 | .remove = dw_i2s_remove, | ||
444 | .driver = { | ||
445 | .name = "designware-i2s", | ||
446 | .owner = THIS_MODULE, | ||
447 | }, | ||
448 | }; | ||
449 | |||
450 | module_platform_driver(dw_i2s_driver); | ||
451 | |||
452 | MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>"); | ||
453 | MODULE_DESCRIPTION("DESIGNWARE I2S SoC Interface"); | ||
454 | MODULE_LICENSE("GPL"); | ||
455 | MODULE_ALIAS("platform:designware_i2s"); | ||
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c index 162dbb74f4cc..4eea98b42bc8 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/ep93xx/ep93xx-pcm.c | |||
@@ -136,7 +136,7 @@ static struct snd_pcm_ops ep93xx_pcm_ops = { | |||
136 | .hw_params = ep93xx_pcm_hw_params, | 136 | .hw_params = ep93xx_pcm_hw_params, |
137 | .hw_free = ep93xx_pcm_hw_free, | 137 | .hw_free = ep93xx_pcm_hw_free, |
138 | .trigger = snd_dmaengine_pcm_trigger, | 138 | .trigger = snd_dmaengine_pcm_trigger, |
139 | .pointer = snd_dmaengine_pcm_pointer, | 139 | .pointer = snd_dmaengine_pcm_pointer_no_residue, |
140 | .mmap = ep93xx_pcm_mmap, | 140 | .mmap = ep93xx_pcm_mmap, |
141 | }; | 141 | }; |
142 | 142 | ||
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 080327414c6b..e7c800ebbd75 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c | |||
@@ -156,7 +156,7 @@ static void __init audmux_debugfs_init(void) | |||
156 | return; | 156 | return; |
157 | } | 157 | } |
158 | 158 | ||
159 | for (i = 0; i < MX31_AUDMUX_PORT6_SSI_PINS_6 + 1; i++) { | 159 | for (i = 0; i < MX31_AUDMUX_PORT7_SSI_PINS_7 + 1; i++) { |
160 | snprintf(buf, sizeof(buf), "ssi%d", i); | 160 | snprintf(buf, sizeof(buf), "ssi%d", i); |
161 | if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, | 161 | if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, |
162 | (void *)i, &audmux_debugfs_fops)) | 162 | (void *)i, &audmux_debugfs_fops)) |
diff --git a/sound/soc/fsl/imx-audmux.h b/sound/soc/fsl/imx-audmux.h index 04ebbab8d7b9..b8ff44b9dafa 100644 --- a/sound/soc/fsl/imx-audmux.h +++ b/sound/soc/fsl/imx-audmux.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #define MX31_AUDMUX_PORT4_SSI_PINS_4 3 | 14 | #define MX31_AUDMUX_PORT4_SSI_PINS_4 3 |
15 | #define MX31_AUDMUX_PORT5_SSI_PINS_5 4 | 15 | #define MX31_AUDMUX_PORT5_SSI_PINS_5 4 |
16 | #define MX31_AUDMUX_PORT6_SSI_PINS_6 5 | 16 | #define MX31_AUDMUX_PORT6_SSI_PINS_6 5 |
17 | #define MX31_AUDMUX_PORT7_SSI_PINS_7 6 | ||
17 | 18 | ||
18 | #define MX51_AUDMUX_PORT1_SSI0 0 | 19 | #define MX51_AUDMUX_PORT1_SSI0 0 |
19 | #define MX51_AUDMUX_PORT2_SSI1 1 | 20 | #define MX51_AUDMUX_PORT2_SSI1 1 |
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c index f59c34943662..549b31fdc9dd 100644 --- a/sound/soc/fsl/imx-mc13783.c +++ b/sound/soc/fsl/imx-mc13783.c | |||
@@ -111,22 +111,39 @@ static int __devinit imx_mc13783_probe(struct platform_device *pdev) | |||
111 | return ret; | 111 | return ret; |
112 | } | 112 | } |
113 | 113 | ||
114 | imx_audmux_v2_configure_port(MX31_AUDMUX_PORT4_SSI_PINS_4, | 114 | if (machine_is_mx31_3ds()) { |
115 | IMX_AUDMUX_V2_PTCR_SYN, | 115 | imx_audmux_v2_configure_port(MX31_AUDMUX_PORT4_SSI_PINS_4, |
116 | IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0) | | 116 | IMX_AUDMUX_V2_PTCR_SYN, |
117 | IMX_AUDMUX_V2_PDCR_MODE(1) | | 117 | IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0) | |
118 | IMX_AUDMUX_V2_PDCR_INMMASK(0xfc)); | 118 | IMX_AUDMUX_V2_PDCR_MODE(1) | |
119 | imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, | 119 | IMX_AUDMUX_V2_PDCR_INMMASK(0xfc)); |
120 | IMX_AUDMUX_V2_PTCR_SYN | | 120 | imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, |
121 | IMX_AUDMUX_V2_PTCR_TFSDIR | | 121 | IMX_AUDMUX_V2_PTCR_SYN | |
122 | IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) | | 122 | IMX_AUDMUX_V2_PTCR_TFSDIR | |
123 | IMX_AUDMUX_V2_PTCR_TCLKDIR | | 123 | IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) | |
124 | IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) | | 124 | IMX_AUDMUX_V2_PTCR_TCLKDIR | |
125 | IMX_AUDMUX_V2_PTCR_RFSDIR | | 125 | IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) | |
126 | IMX_AUDMUX_V2_PTCR_RFSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) | | 126 | IMX_AUDMUX_V2_PTCR_RFSDIR | |
127 | IMX_AUDMUX_V2_PTCR_RCLKDIR | | 127 | IMX_AUDMUX_V2_PTCR_RFSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) | |
128 | IMX_AUDMUX_V2_PTCR_RCSEL(MX31_AUDMUX_PORT4_SSI_PINS_4), | 128 | IMX_AUDMUX_V2_PTCR_RCLKDIR | |
129 | IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT4_SSI_PINS_4)); | 129 | IMX_AUDMUX_V2_PTCR_RCSEL(MX31_AUDMUX_PORT4_SSI_PINS_4), |
130 | IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT4_SSI_PINS_4)); | ||
131 | } else if (machine_is_mx27_3ds()) { | ||
132 | imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, | ||
133 | IMX_AUDMUX_V1_PCR_SYN | | ||
134 | IMX_AUDMUX_V1_PCR_TFSDIR | | ||
135 | IMX_AUDMUX_V1_PCR_TCLKDIR | | ||
136 | IMX_AUDMUX_V1_PCR_RFSDIR | | ||
137 | IMX_AUDMUX_V1_PCR_RCLKDIR | | ||
138 | IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | | ||
139 | IMX_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | | ||
140 | IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | ||
141 | ); | ||
142 | imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4, | ||
143 | IMX_AUDMUX_V1_PCR_SYN | | ||
144 | IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) | ||
145 | ); | ||
146 | } | ||
130 | 147 | ||
131 | return ret; | 148 | return ret; |
132 | } | 149 | } |
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index f3c0a5ef35c8..48f9d886f020 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c | |||
@@ -141,7 +141,7 @@ static struct snd_pcm_ops imx_pcm_ops = { | |||
141 | .ioctl = snd_pcm_lib_ioctl, | 141 | .ioctl = snd_pcm_lib_ioctl, |
142 | .hw_params = snd_imx_pcm_hw_params, | 142 | .hw_params = snd_imx_pcm_hw_params, |
143 | .trigger = snd_dmaengine_pcm_trigger, | 143 | .trigger = snd_dmaengine_pcm_trigger, |
144 | .pointer = snd_dmaengine_pcm_pointer, | 144 | .pointer = snd_dmaengine_pcm_pointer_no_residue, |
145 | .mmap = snd_imx_pcm_mmap, | 145 | .mmap = snd_imx_pcm_mmap, |
146 | }; | 146 | }; |
147 | 147 | ||
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index 456b7d723d66..ee27ba3933bd 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <asm/fiq.h> | 30 | #include <asm/fiq.h> |
31 | 31 | ||
32 | #include <mach/irqs.h> | ||
32 | #include <mach/ssi.h> | 33 | #include <mach/ssi.h> |
33 | 34 | ||
34 | #include "imx-ssi.h" | 35 | #include "imx-ssi.h" |
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 3a729caeb8c8..fb21b17f17f5 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c | |||
@@ -95,8 +95,7 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) | |||
95 | return ret; | 95 | return ret; |
96 | } | 96 | } |
97 | imx_audmux_v2_configure_port(ext_port, | 97 | imx_audmux_v2_configure_port(ext_port, |
98 | IMX_AUDMUX_V2_PTCR_SYN | | 98 | IMX_AUDMUX_V2_PTCR_SYN, |
99 | IMX_AUDMUX_V2_PTCR_TCSEL(int_port), | ||
100 | IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); | 99 | IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); |
101 | if (ret) { | 100 | if (ret) { |
102 | dev_err(&pdev->dev, "audmux external port setup failed\n"); | 101 | dev_err(&pdev->dev, "audmux external port setup failed\n"); |
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index 373dec90579f..f82d766cbf9e 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c | |||
@@ -141,7 +141,7 @@ static struct snd_pcm_ops mxs_pcm_ops = { | |||
141 | .ioctl = snd_pcm_lib_ioctl, | 141 | .ioctl = snd_pcm_lib_ioctl, |
142 | .hw_params = snd_mxs_pcm_hw_params, | 142 | .hw_params = snd_mxs_pcm_hw_params, |
143 | .trigger = snd_dmaengine_pcm_trigger, | 143 | .trigger = snd_dmaengine_pcm_trigger, |
144 | .pointer = snd_dmaengine_pcm_pointer, | 144 | .pointer = snd_dmaengine_pcm_pointer_no_residue, |
145 | .mmap = snd_mxs_pcm_mmap, | 145 | .mmap = snd_mxs_pcm_mmap, |
146 | }; | 146 | }; |
147 | 147 | ||
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 3e6e8764b2e6..215113b05f7d 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c | |||
@@ -133,7 +133,7 @@ static int __devinit mxs_sgtl5000_probe_dt(struct platform_device *pdev) | |||
133 | mxs_sgtl5000_dai[i].codec_name = NULL; | 133 | mxs_sgtl5000_dai[i].codec_name = NULL; |
134 | mxs_sgtl5000_dai[i].codec_of_node = codec_np; | 134 | mxs_sgtl5000_dai[i].codec_of_node = codec_np; |
135 | mxs_sgtl5000_dai[i].cpu_dai_name = NULL; | 135 | mxs_sgtl5000_dai[i].cpu_dai_name = NULL; |
136 | mxs_sgtl5000_dai[i].cpu_dai_of_node = saif_np[i]; | 136 | mxs_sgtl5000_dai[i].cpu_of_node = saif_np[i]; |
137 | mxs_sgtl5000_dai[i].platform_name = NULL; | 137 | mxs_sgtl5000_dai[i].platform_name = NULL; |
138 | mxs_sgtl5000_dai[i].platform_of_node = saif_np[i]; | 138 | mxs_sgtl5000_dai[i].platform_of_node = saif_np[i]; |
139 | } | 139 | } |
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 59d47ab5b15d..2c66e2498a45 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c | |||
@@ -527,6 +527,7 @@ static struct platform_driver asoc_mcpdm_driver = { | |||
527 | 527 | ||
528 | module_platform_driver(asoc_mcpdm_driver); | 528 | module_platform_driver(asoc_mcpdm_driver); |
529 | 529 | ||
530 | MODULE_ALIAS("platform:omap-mcpdm"); | ||
530 | MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>"); | 531 | MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>"); |
531 | MODULE_DESCRIPTION("OMAP PDM SoC Interface"); | 532 | MODULE_DESCRIPTION("OMAP PDM SoC Interface"); |
532 | MODULE_LICENSE("GPL"); | 533 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index a0f7d3cfa470..4d2e46fae77c 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
@@ -8,6 +8,15 @@ config SND_PXA2XX_SOC | |||
8 | the PXA2xx AC97, I2S or SSP interface. You will also need | 8 | the PXA2xx AC97, I2S or SSP interface. You will also need |
9 | to select the audio interfaces to support below. | 9 | to select the audio interfaces to support below. |
10 | 10 | ||
11 | config SND_MMP_SOC | ||
12 | bool "Soc Audio for Marvell MMP chips" | ||
13 | depends on ARCH_MMP | ||
14 | select SND_SOC_DMAENGINE_PCM | ||
15 | select SND_ARM | ||
16 | help | ||
17 | Say Y if you want to add support for codecs attached to | ||
18 | the MMP SSPA interface. | ||
19 | |||
11 | config SND_PXA2XX_AC97 | 20 | config SND_PXA2XX_AC97 |
12 | tristate | 21 | tristate |
13 | select SND_AC97_CODEC | 22 | select SND_AC97_CODEC |
@@ -26,6 +35,9 @@ config SND_PXA_SOC_SSP | |||
26 | tristate | 35 | tristate |
27 | select PXA_SSP | 36 | select PXA_SSP |
28 | 37 | ||
38 | config SND_MMP_SOC_SSPA | ||
39 | tristate | ||
40 | |||
29 | config SND_PXA2XX_SOC_CORGI | 41 | config SND_PXA2XX_SOC_CORGI |
30 | tristate "SoC Audio support for Sharp Zaurus SL-C7x0" | 42 | tristate "SoC Audio support for Sharp Zaurus SL-C7x0" |
31 | depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx | 43 | depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx |
@@ -138,6 +150,26 @@ config SND_SOC_TAVOREVB3 | |||
138 | Say Y if you want to add support for SoC audio on the | 150 | Say Y if you want to add support for SoC audio on the |
139 | Marvell Saarb reference platform. | 151 | Marvell Saarb reference platform. |
140 | 152 | ||
153 | config SND_PXA910_SOC | ||
154 | tristate "SoC Audio for Marvell PXA910 chip" | ||
155 | depends on ARCH_MMP && SND | ||
156 | select SND_PCM | ||
157 | help | ||
158 | Say Y if you want to add support for SoC audio on the | ||
159 | Marvell PXA910 reference platform. | ||
160 | |||
161 | config SND_SOC_TTC_DKB | ||
162 | bool "SoC Audio support for TTC DKB" | ||
163 | depends on SND_PXA910_SOC && MACH_TTC_DKB | ||
164 | select PXA_SSP | ||
165 | select SND_PXA_SOC_SSP | ||
166 | select SND_MMP_SOC | ||
167 | select MFD_88PM860X | ||
168 | select SND_SOC_88PM860X | ||
169 | help | ||
170 | Say Y if you want to add support for SoC audio on TTC DKB | ||
171 | |||
172 | |||
141 | config SND_SOC_ZYLONITE | 173 | config SND_SOC_ZYLONITE |
142 | tristate "SoC Audio support for Marvell Zylonite" | 174 | tristate "SoC Audio support for Marvell Zylonite" |
143 | depends on SND_PXA2XX_SOC && MACH_ZYLONITE | 175 | depends on SND_PXA2XX_SOC && MACH_ZYLONITE |
@@ -194,3 +226,13 @@ config SND_PXA2XX_SOC_IMOTE2 | |||
194 | help | 226 | help |
195 | Say Y if you want to add support for SoC audio on the | 227 | Say Y if you want to add support for SoC audio on the |
196 | IMote 2. | 228 | IMote 2. |
229 | |||
230 | config SND_MMP_SOC_BROWNSTONE | ||
231 | tristate "SoC Audio support for Marvell Brownstone" | ||
232 | depends on SND_MMP_SOC && MACH_BROWNSTONE | ||
233 | select SND_MMP_SOC_SSPA | ||
234 | select MFD_WM8994 | ||
235 | select SND_SOC_WM8994 | ||
236 | help | ||
237 | Say Y if you want to add support for SoC audio on the | ||
238 | Marvell Brownstone reference platform. | ||
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index af357623be9d..d8a265d2d5d7 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile | |||
@@ -3,11 +3,15 @@ snd-soc-pxa2xx-objs := pxa2xx-pcm.o | |||
3 | snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o | 3 | snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o |
4 | snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o | 4 | snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o |
5 | snd-soc-pxa-ssp-objs := pxa-ssp.o | 5 | snd-soc-pxa-ssp-objs := pxa-ssp.o |
6 | snd-soc-mmp-objs := mmp-pcm.o | ||
7 | snd-soc-mmp-sspa-objs := mmp-sspa.o | ||
6 | 8 | ||
7 | obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o | 9 | obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o |
8 | obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o | 10 | obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o |
9 | obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o | 11 | obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o |
10 | obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o | 12 | obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o |
13 | obj-$(CONFIG_SND_MMP_SOC) += snd-soc-mmp.o | ||
14 | obj-$(CONFIG_SND_MMP_SOC_SSPA) += snd-soc-mmp-sspa.o | ||
11 | 15 | ||
12 | # PXA Machine Support | 16 | # PXA Machine Support |
13 | snd-soc-corgi-objs := corgi.o | 17 | snd-soc-corgi-objs := corgi.o |
@@ -28,6 +32,8 @@ snd-soc-mioa701-objs := mioa701_wm9713.o | |||
28 | snd-soc-z2-objs := z2.o | 32 | snd-soc-z2-objs := z2.o |
29 | snd-soc-imote2-objs := imote2.o | 33 | snd-soc-imote2-objs := imote2.o |
30 | snd-soc-raumfeld-objs := raumfeld.o | 34 | snd-soc-raumfeld-objs := raumfeld.o |
35 | snd-soc-brownstone-objs := brownstone.o | ||
36 | snd-soc-ttc-dkb-objs := ttc-dkb.o | ||
31 | 37 | ||
32 | obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o | 38 | obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o |
33 | obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o | 39 | obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o |
@@ -47,3 +53,5 @@ obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o | |||
47 | obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o | 53 | obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o |
48 | obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o | 54 | obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o |
49 | obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o | 55 | obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o |
56 | obj-$(CONFIG_SND_MMP_SOC_BROWNSTONE) += snd-soc-brownstone.o | ||
57 | obj-$(CONFIG_SND_SOC_TTC_DKB) += snd-soc-ttc-dkb.o | ||
diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c new file mode 100644 index 000000000000..5e666e03d333 --- /dev/null +++ b/sound/soc/pxa/brownstone.c | |||
@@ -0,0 +1,174 @@ | |||
1 | /* | ||
2 | * linux/sound/soc/pxa/brownstone.c | ||
3 | * | ||
4 | * Copyright (C) 2011 Marvell International Ltd. | ||
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 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <sound/core.h> | ||
15 | #include <sound/pcm.h> | ||
16 | #include <sound/soc.h> | ||
17 | #include <sound/jack.h> | ||
18 | |||
19 | #include "../codecs/wm8994.h" | ||
20 | #include "mmp-sspa.h" | ||
21 | |||
22 | static const struct snd_kcontrol_new brownstone_dapm_control[] = { | ||
23 | SOC_DAPM_PIN_SWITCH("Ext Spk"), | ||
24 | }; | ||
25 | |||
26 | static const struct snd_soc_dapm_widget brownstone_dapm_widgets[] = { | ||
27 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | ||
28 | SND_SOC_DAPM_HP("Headset Stereophone", NULL), | ||
29 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
30 | SND_SOC_DAPM_MIC("Main Mic", NULL), | ||
31 | }; | ||
32 | |||
33 | static const struct snd_soc_dapm_route brownstone_audio_map[] = { | ||
34 | {"Ext Spk", NULL, "SPKOUTLP"}, | ||
35 | {"Ext Spk", NULL, "SPKOUTLN"}, | ||
36 | {"Ext Spk", NULL, "SPKOUTRP"}, | ||
37 | {"Ext Spk", NULL, "SPKOUTRN"}, | ||
38 | |||
39 | {"Headset Stereophone", NULL, "HPOUT1L"}, | ||
40 | {"Headset Stereophone", NULL, "HPOUT1R"}, | ||
41 | |||
42 | {"IN1RN", NULL, "Headset Mic"}, | ||
43 | |||
44 | {"DMIC1DAT", NULL, "MICBIAS1"}, | ||
45 | {"MICBIAS1", NULL, "Main Mic"}, | ||
46 | }; | ||
47 | |||
48 | static int brownstone_wm8994_init(struct snd_soc_pcm_runtime *rtd) | ||
49 | { | ||
50 | struct snd_soc_codec *codec = rtd->codec; | ||
51 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
52 | |||
53 | snd_soc_dapm_enable_pin(dapm, "Ext Spk"); | ||
54 | snd_soc_dapm_enable_pin(dapm, "Headset Stereophone"); | ||
55 | snd_soc_dapm_enable_pin(dapm, "Headset Mic"); | ||
56 | snd_soc_dapm_enable_pin(dapm, "Main Mic"); | ||
57 | |||
58 | /* set endpoints to not connected */ | ||
59 | snd_soc_dapm_nc_pin(dapm, "HPOUT2P"); | ||
60 | snd_soc_dapm_nc_pin(dapm, "HPOUT2N"); | ||
61 | snd_soc_dapm_nc_pin(dapm, "LINEOUT1N"); | ||
62 | snd_soc_dapm_nc_pin(dapm, "LINEOUT1P"); | ||
63 | snd_soc_dapm_nc_pin(dapm, "LINEOUT2N"); | ||
64 | snd_soc_dapm_nc_pin(dapm, "LINEOUT2P"); | ||
65 | snd_soc_dapm_nc_pin(dapm, "IN1LN"); | ||
66 | snd_soc_dapm_nc_pin(dapm, "IN1LP"); | ||
67 | snd_soc_dapm_nc_pin(dapm, "IN1RP"); | ||
68 | snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN"); | ||
69 | snd_soc_dapm_nc_pin(dapm, "IN2RN"); | ||
70 | snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP"); | ||
71 | snd_soc_dapm_nc_pin(dapm, "IN2LN"); | ||
72 | |||
73 | snd_soc_dapm_sync(dapm); | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream, | ||
79 | struct snd_pcm_hw_params *params) | ||
80 | { | ||
81 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
82 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
83 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
84 | int freq_out, sspa_mclk, sysclk; | ||
85 | int sspa_div; | ||
86 | |||
87 | if (params_rate(params) > 11025) { | ||
88 | freq_out = params_rate(params) * 512; | ||
89 | sysclk = params_rate(params) * 256; | ||
90 | sspa_mclk = params_rate(params) * 64; | ||
91 | } else { | ||
92 | freq_out = params_rate(params) * 1024; | ||
93 | sysclk = params_rate(params) * 512; | ||
94 | sspa_mclk = params_rate(params) * 64; | ||
95 | } | ||
96 | sspa_div = freq_out; | ||
97 | do_div(sspa_div, sspa_mclk); | ||
98 | |||
99 | snd_soc_dai_set_sysclk(cpu_dai, MMP_SSPA_CLK_AUDIO, freq_out, 0); | ||
100 | snd_soc_dai_set_pll(cpu_dai, MMP_SYSCLK, 0, freq_out, sysclk); | ||
101 | snd_soc_dai_set_pll(cpu_dai, MMP_SSPA_CLK, 0, freq_out, sspa_mclk); | ||
102 | |||
103 | /* set wm8994 sysclk */ | ||
104 | snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1, sysclk, 0); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | /* machine stream operations */ | ||
110 | static struct snd_soc_ops brownstone_ops = { | ||
111 | .hw_params = brownstone_wm8994_hw_params, | ||
112 | }; | ||
113 | |||
114 | static struct snd_soc_dai_link brownstone_wm8994_dai[] = { | ||
115 | { | ||
116 | .name = "WM8994", | ||
117 | .stream_name = "WM8994 HiFi", | ||
118 | .cpu_dai_name = "mmp-sspa-dai.0", | ||
119 | .codec_dai_name = "wm8994-aif1", | ||
120 | .platform_name = "mmp-pcm-audio", | ||
121 | .codec_name = "wm8994-codec", | ||
122 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
123 | SND_SOC_DAIFMT_CBS_CFS, | ||
124 | .ops = &brownstone_ops, | ||
125 | .init = brownstone_wm8994_init, | ||
126 | }, | ||
127 | }; | ||
128 | |||
129 | /* audio machine driver */ | ||
130 | static struct snd_soc_card brownstone = { | ||
131 | .name = "brownstone", | ||
132 | .dai_link = brownstone_wm8994_dai, | ||
133 | .num_links = ARRAY_SIZE(brownstone_wm8994_dai), | ||
134 | |||
135 | .controls = brownstone_dapm_control, | ||
136 | .num_controls = ARRAY_SIZE(brownstone_dapm_control), | ||
137 | .dapm_widgets = brownstone_dapm_widgets, | ||
138 | .num_dapm_widgets = ARRAY_SIZE(brownstone_dapm_widgets), | ||
139 | .dapm_routes = brownstone_audio_map, | ||
140 | .num_dapm_routes = ARRAY_SIZE(brownstone_audio_map), | ||
141 | }; | ||
142 | |||
143 | static int __devinit brownstone_probe(struct platform_device *pdev) | ||
144 | { | ||
145 | int ret; | ||
146 | |||
147 | brownstone.dev = &pdev->dev; | ||
148 | ret = snd_soc_register_card(&brownstone); | ||
149 | if (ret) | ||
150 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
151 | ret); | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | static int __devexit brownstone_remove(struct platform_device *pdev) | ||
156 | { | ||
157 | snd_soc_unregister_card(&brownstone); | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static struct platform_driver mmp_driver = { | ||
162 | .driver = { | ||
163 | .name = "brownstone-audio", | ||
164 | .owner = THIS_MODULE, | ||
165 | }, | ||
166 | .probe = brownstone_probe, | ||
167 | .remove = __devexit_p(brownstone_remove), | ||
168 | }; | ||
169 | |||
170 | module_platform_driver(mmp_driver); | ||
171 | |||
172 | MODULE_AUTHOR("Leo Yan <leoy@marvell.com>"); | ||
173 | MODULE_DESCRIPTION("ALSA SoC Brownstone"); | ||
174 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 9c585af59b5f..8687c1c65d29 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c | |||
@@ -186,36 +186,27 @@ static struct snd_soc_card mioa701 = { | |||
186 | .num_links = ARRAY_SIZE(mioa701_dai), | 186 | .num_links = ARRAY_SIZE(mioa701_dai), |
187 | }; | 187 | }; |
188 | 188 | ||
189 | static struct platform_device *mioa701_snd_device; | 189 | static int __devinit mioa701_wm9713_probe(struct platform_device *pdev) |
190 | |||
191 | static int mioa701_wm9713_probe(struct platform_device *pdev) | ||
192 | { | 190 | { |
193 | int ret; | 191 | int rc; |
194 | 192 | ||
195 | if (!machine_is_mioa701()) | 193 | if (!machine_is_mioa701()) |
196 | return -ENODEV; | 194 | return -ENODEV; |
197 | 195 | ||
198 | dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will" | 196 | mioa701.dev = &pdev->dev; |
199 | "lead to overheating and possible destruction of your device." | 197 | rc = snd_soc_register_card(&mioa701); |
200 | "Do not use without a good knowledge of mio's board design!\n"); | 198 | if (!rc) |
201 | 199 | dev_warn(&pdev->dev, "Be warned that incorrect mixers/muxes setup will" | |
202 | mioa701_snd_device = platform_device_alloc("soc-audio", -1); | 200 | "lead to overheating and possible destruction of your device." |
203 | if (!mioa701_snd_device) | 201 | " Do not use without a good knowledge of mio's board design!\n"); |
204 | return -ENOMEM; | 202 | return rc; |
205 | |||
206 | platform_set_drvdata(mioa701_snd_device, &mioa701); | ||
207 | |||
208 | ret = platform_device_add(mioa701_snd_device); | ||
209 | if (!ret) | ||
210 | return 0; | ||
211 | |||
212 | platform_device_put(mioa701_snd_device); | ||
213 | return ret; | ||
214 | } | 203 | } |
215 | 204 | ||
216 | static int __devexit mioa701_wm9713_remove(struct platform_device *pdev) | 205 | static int __devexit mioa701_wm9713_remove(struct platform_device *pdev) |
217 | { | 206 | { |
218 | platform_device_unregister(mioa701_snd_device); | 207 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
208 | |||
209 | snd_soc_unregister_card(card); | ||
219 | return 0; | 210 | return 0; |
220 | } | 211 | } |
221 | 212 | ||
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c new file mode 100644 index 000000000000..73ac5463c9e4 --- /dev/null +++ b/sound/soc/pxa/mmp-pcm.c | |||
@@ -0,0 +1,297 @@ | |||
1 | /* | ||
2 | * linux/sound/soc/pxa/mmp-pcm.c | ||
3 | * | ||
4 | * Copyright (C) 2011 Marvell International Ltd. | ||
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 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/dmaengine.h> | ||
18 | #include <linux/platform_data/mmp_audio.h> | ||
19 | #include <sound/pxa2xx-lib.h> | ||
20 | #include <sound/core.h> | ||
21 | #include <sound/pcm.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | #include <sound/soc.h> | ||
24 | #include <mach/sram.h> | ||
25 | #include <sound/dmaengine_pcm.h> | ||
26 | |||
27 | struct mmp_dma_data { | ||
28 | int ssp_id; | ||
29 | struct resource *dma_res; | ||
30 | }; | ||
31 | |||
32 | #define MMP_PCM_INFO (SNDRV_PCM_INFO_MMAP | \ | ||
33 | SNDRV_PCM_INFO_MMAP_VALID | \ | ||
34 | SNDRV_PCM_INFO_INTERLEAVED | \ | ||
35 | SNDRV_PCM_INFO_PAUSE | \ | ||
36 | SNDRV_PCM_INFO_RESUME) | ||
37 | |||
38 | #define MMP_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
39 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
40 | SNDRV_PCM_FMTBIT_S32_LE) | ||
41 | |||
42 | static struct snd_pcm_hardware mmp_pcm_hardware[] = { | ||
43 | { | ||
44 | .info = MMP_PCM_INFO, | ||
45 | .formats = MMP_PCM_FORMATS, | ||
46 | .period_bytes_min = 1024, | ||
47 | .period_bytes_max = 2048, | ||
48 | .periods_min = 2, | ||
49 | .periods_max = 32, | ||
50 | .buffer_bytes_max = 4096, | ||
51 | .fifo_size = 32, | ||
52 | }, | ||
53 | { | ||
54 | .info = MMP_PCM_INFO, | ||
55 | .formats = MMP_PCM_FORMATS, | ||
56 | .period_bytes_min = 1024, | ||
57 | .period_bytes_max = 2048, | ||
58 | .periods_min = 2, | ||
59 | .periods_max = 32, | ||
60 | .buffer_bytes_max = 4096, | ||
61 | .fifo_size = 32, | ||
62 | }, | ||
63 | }; | ||
64 | |||
65 | static int mmp_pcm_hw_params(struct snd_pcm_substream *substream, | ||
66 | struct snd_pcm_hw_params *params) | ||
67 | { | ||
68 | struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); | ||
69 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
70 | struct pxa2xx_pcm_dma_params *dma_params; | ||
71 | struct dma_slave_config slave_config; | ||
72 | int ret; | ||
73 | |||
74 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
75 | if (!dma_params) | ||
76 | return 0; | ||
77 | |||
78 | ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config); | ||
79 | if (ret) | ||
80 | return ret; | ||
81 | |||
82 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
83 | slave_config.dst_addr = dma_params->dev_addr; | ||
84 | slave_config.dst_maxburst = 4; | ||
85 | } else { | ||
86 | slave_config.src_addr = dma_params->dev_addr; | ||
87 | slave_config.src_maxburst = 4; | ||
88 | } | ||
89 | |||
90 | ret = dmaengine_slave_config(chan, &slave_config); | ||
91 | if (ret) | ||
92 | return ret; | ||
93 | |||
94 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static bool filter(struct dma_chan *chan, void *param) | ||
100 | { | ||
101 | struct mmp_dma_data *dma_data = param; | ||
102 | bool found = false; | ||
103 | char *devname; | ||
104 | |||
105 | devname = kasprintf(GFP_KERNEL, "%s.%d", dma_data->dma_res->name, | ||
106 | dma_data->ssp_id); | ||
107 | if ((strcmp(dev_name(chan->device->dev), devname) == 0) && | ||
108 | (chan->chan_id == dma_data->dma_res->start)) { | ||
109 | found = true; | ||
110 | } | ||
111 | |||
112 | kfree(devname); | ||
113 | return found; | ||
114 | } | ||
115 | |||
116 | static int mmp_pcm_open(struct snd_pcm_substream *substream) | ||
117 | { | ||
118 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
119 | struct platform_device *pdev = to_platform_device(rtd->platform->dev); | ||
120 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
121 | struct mmp_dma_data *dma_data; | ||
122 | struct resource *r; | ||
123 | int ret; | ||
124 | |||
125 | r = platform_get_resource(pdev, IORESOURCE_DMA, substream->stream); | ||
126 | if (!r) | ||
127 | return -EBUSY; | ||
128 | |||
129 | snd_soc_set_runtime_hwparams(substream, | ||
130 | &mmp_pcm_hardware[substream->stream]); | ||
131 | dma_data = devm_kzalloc(&pdev->dev, | ||
132 | sizeof(struct mmp_dma_data), GFP_KERNEL); | ||
133 | if (dma_data == NULL) | ||
134 | return -ENOMEM; | ||
135 | |||
136 | dma_data->dma_res = r; | ||
137 | dma_data->ssp_id = cpu_dai->id; | ||
138 | |||
139 | ret = snd_dmaengine_pcm_open(substream, filter, dma_data); | ||
140 | if (ret) { | ||
141 | devm_kfree(&pdev->dev, dma_data); | ||
142 | return ret; | ||
143 | } | ||
144 | |||
145 | snd_dmaengine_pcm_set_data(substream, dma_data); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int mmp_pcm_close(struct snd_pcm_substream *substream) | ||
150 | { | ||
151 | struct mmp_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream); | ||
152 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
153 | struct platform_device *pdev = to_platform_device(rtd->platform->dev); | ||
154 | |||
155 | snd_dmaengine_pcm_close(substream); | ||
156 | devm_kfree(&pdev->dev, dma_data); | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int mmp_pcm_mmap(struct snd_pcm_substream *substream, | ||
161 | struct vm_area_struct *vma) | ||
162 | { | ||
163 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
164 | unsigned long off = vma->vm_pgoff; | ||
165 | |||
166 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
167 | return remap_pfn_range(vma, vma->vm_start, | ||
168 | __phys_to_pfn(runtime->dma_addr) + off, | ||
169 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
170 | } | ||
171 | |||
172 | struct snd_pcm_ops mmp_pcm_ops = { | ||
173 | .open = mmp_pcm_open, | ||
174 | .close = mmp_pcm_close, | ||
175 | .ioctl = snd_pcm_lib_ioctl, | ||
176 | .hw_params = mmp_pcm_hw_params, | ||
177 | .trigger = snd_dmaengine_pcm_trigger, | ||
178 | .pointer = snd_dmaengine_pcm_pointer, | ||
179 | .mmap = mmp_pcm_mmap, | ||
180 | }; | ||
181 | |||
182 | static void mmp_pcm_free_dma_buffers(struct snd_pcm *pcm) | ||
183 | { | ||
184 | struct snd_pcm_substream *substream; | ||
185 | struct snd_dma_buffer *buf; | ||
186 | int stream; | ||
187 | struct gen_pool *gpool; | ||
188 | |||
189 | gpool = sram_get_gpool("asram"); | ||
190 | if (!gpool) | ||
191 | return; | ||
192 | |||
193 | for (stream = 0; stream < 2; stream++) { | ||
194 | size_t size = mmp_pcm_hardware[stream].buffer_bytes_max; | ||
195 | |||
196 | substream = pcm->streams[stream].substream; | ||
197 | if (!substream) | ||
198 | continue; | ||
199 | |||
200 | buf = &substream->dma_buffer; | ||
201 | if (!buf->area) | ||
202 | continue; | ||
203 | gen_pool_free(gpool, (unsigned long)buf->area, size); | ||
204 | buf->area = NULL; | ||
205 | } | ||
206 | |||
207 | return; | ||
208 | } | ||
209 | |||
210 | static int mmp_pcm_preallocate_dma_buffer(struct snd_pcm_substream *substream, | ||
211 | int stream) | ||
212 | { | ||
213 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
214 | size_t size = mmp_pcm_hardware[stream].buffer_bytes_max; | ||
215 | struct gen_pool *gpool; | ||
216 | |||
217 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
218 | buf->dev.dev = substream->pcm->card->dev; | ||
219 | buf->private_data = NULL; | ||
220 | |||
221 | gpool = sram_get_gpool("asram"); | ||
222 | if (!gpool) | ||
223 | return -ENOMEM; | ||
224 | |||
225 | buf->area = (unsigned char *)gen_pool_alloc(gpool, size); | ||
226 | if (!buf->area) | ||
227 | return -ENOMEM; | ||
228 | buf->addr = gen_pool_virt_to_phys(gpool, (unsigned long)buf->area); | ||
229 | buf->bytes = size; | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | int mmp_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
234 | { | ||
235 | struct snd_pcm_substream *substream; | ||
236 | struct snd_pcm *pcm = rtd->pcm; | ||
237 | int ret = 0, stream; | ||
238 | |||
239 | for (stream = 0; stream < 2; stream++) { | ||
240 | substream = pcm->streams[stream].substream; | ||
241 | |||
242 | ret = mmp_pcm_preallocate_dma_buffer(substream, stream); | ||
243 | if (ret) | ||
244 | goto err; | ||
245 | } | ||
246 | |||
247 | return 0; | ||
248 | |||
249 | err: | ||
250 | mmp_pcm_free_dma_buffers(pcm); | ||
251 | return ret; | ||
252 | } | ||
253 | |||
254 | struct snd_soc_platform_driver mmp_soc_platform = { | ||
255 | .ops = &mmp_pcm_ops, | ||
256 | .pcm_new = mmp_pcm_new, | ||
257 | .pcm_free = mmp_pcm_free_dma_buffers, | ||
258 | }; | ||
259 | |||
260 | static __devinit int mmp_pcm_probe(struct platform_device *pdev) | ||
261 | { | ||
262 | struct mmp_audio_platdata *pdata = pdev->dev.platform_data; | ||
263 | |||
264 | if (pdata) { | ||
265 | mmp_pcm_hardware[SNDRV_PCM_STREAM_PLAYBACK].buffer_bytes_max = | ||
266 | pdata->buffer_max_playback; | ||
267 | mmp_pcm_hardware[SNDRV_PCM_STREAM_PLAYBACK].period_bytes_max = | ||
268 | pdata->period_max_playback; | ||
269 | mmp_pcm_hardware[SNDRV_PCM_STREAM_CAPTURE].buffer_bytes_max = | ||
270 | pdata->buffer_max_capture; | ||
271 | mmp_pcm_hardware[SNDRV_PCM_STREAM_CAPTURE].period_bytes_max = | ||
272 | pdata->period_max_capture; | ||
273 | } | ||
274 | return snd_soc_register_platform(&pdev->dev, &mmp_soc_platform); | ||
275 | } | ||
276 | |||
277 | static int __devexit mmp_pcm_remove(struct platform_device *pdev) | ||
278 | { | ||
279 | snd_soc_unregister_platform(&pdev->dev); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static struct platform_driver mmp_pcm_driver = { | ||
284 | .driver = { | ||
285 | .name = "mmp-pcm-audio", | ||
286 | .owner = THIS_MODULE, | ||
287 | }, | ||
288 | |||
289 | .probe = mmp_pcm_probe, | ||
290 | .remove = __devexit_p(mmp_pcm_remove), | ||
291 | }; | ||
292 | |||
293 | module_platform_driver(mmp_pcm_driver); | ||
294 | |||
295 | MODULE_AUTHOR("Leo Yan <leoy@marvell.com>"); | ||
296 | MODULE_DESCRIPTION("MMP Soc Audio DMA module"); | ||
297 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c new file mode 100644 index 000000000000..4d6cb8a30fc8 --- /dev/null +++ b/sound/soc/pxa/mmp-sspa.c | |||
@@ -0,0 +1,480 @@ | |||
1 | /* | ||
2 | * linux/sound/soc/pxa/mmp-sspa.c | ||
3 | * Base on pxa2xx-ssp.c | ||
4 | * | ||
5 | * Copyright (C) 2011 Marvell International Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/pxa2xx_ssp.h> | ||
29 | #include <linux/io.h> | ||
30 | #include <sound/core.h> | ||
31 | #include <sound/pcm.h> | ||
32 | #include <sound/initval.h> | ||
33 | #include <sound/pcm_params.h> | ||
34 | #include <sound/soc.h> | ||
35 | #include <sound/pxa2xx-lib.h> | ||
36 | #include "mmp-sspa.h" | ||
37 | |||
38 | /* | ||
39 | * SSPA audio private data | ||
40 | */ | ||
41 | struct sspa_priv { | ||
42 | struct ssp_device *sspa; | ||
43 | struct pxa2xx_pcm_dma_params *dma_params; | ||
44 | struct clk *audio_clk; | ||
45 | struct clk *sysclk; | ||
46 | int dai_fmt; | ||
47 | int running_cnt; | ||
48 | }; | ||
49 | |||
50 | static void mmp_sspa_write_reg(struct ssp_device *sspa, u32 reg, u32 val) | ||
51 | { | ||
52 | __raw_writel(val, sspa->mmio_base + reg); | ||
53 | } | ||
54 | |||
55 | static u32 mmp_sspa_read_reg(struct ssp_device *sspa, u32 reg) | ||
56 | { | ||
57 | return __raw_readl(sspa->mmio_base + reg); | ||
58 | } | ||
59 | |||
60 | static void mmp_sspa_tx_enable(struct ssp_device *sspa) | ||
61 | { | ||
62 | unsigned int sspa_sp; | ||
63 | |||
64 | sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP); | ||
65 | sspa_sp |= SSPA_SP_S_EN; | ||
66 | sspa_sp |= SSPA_SP_WEN; | ||
67 | mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); | ||
68 | } | ||
69 | |||
70 | static void mmp_sspa_tx_disable(struct ssp_device *sspa) | ||
71 | { | ||
72 | unsigned int sspa_sp; | ||
73 | |||
74 | sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP); | ||
75 | sspa_sp &= ~SSPA_SP_S_EN; | ||
76 | sspa_sp |= SSPA_SP_WEN; | ||
77 | mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); | ||
78 | } | ||
79 | |||
80 | static void mmp_sspa_rx_enable(struct ssp_device *sspa) | ||
81 | { | ||
82 | unsigned int sspa_sp; | ||
83 | |||
84 | sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP); | ||
85 | sspa_sp |= SSPA_SP_S_EN; | ||
86 | sspa_sp |= SSPA_SP_WEN; | ||
87 | mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); | ||
88 | } | ||
89 | |||
90 | static void mmp_sspa_rx_disable(struct ssp_device *sspa) | ||
91 | { | ||
92 | unsigned int sspa_sp; | ||
93 | |||
94 | sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP); | ||
95 | sspa_sp &= ~SSPA_SP_S_EN; | ||
96 | sspa_sp |= SSPA_SP_WEN; | ||
97 | mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); | ||
98 | } | ||
99 | |||
100 | static int mmp_sspa_startup(struct snd_pcm_substream *substream, | ||
101 | struct snd_soc_dai *dai) | ||
102 | { | ||
103 | struct sspa_priv *priv = snd_soc_dai_get_drvdata(dai); | ||
104 | |||
105 | clk_enable(priv->sysclk); | ||
106 | clk_enable(priv->sspa->clk); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static void mmp_sspa_shutdown(struct snd_pcm_substream *substream, | ||
112 | struct snd_soc_dai *dai) | ||
113 | { | ||
114 | struct sspa_priv *priv = snd_soc_dai_get_drvdata(dai); | ||
115 | |||
116 | clk_disable(priv->sspa->clk); | ||
117 | clk_disable(priv->sysclk); | ||
118 | |||
119 | return; | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * Set the SSP ports SYSCLK. | ||
124 | */ | ||
125 | static int mmp_sspa_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | ||
126 | int clk_id, unsigned int freq, int dir) | ||
127 | { | ||
128 | struct sspa_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
129 | int ret = 0; | ||
130 | |||
131 | switch (clk_id) { | ||
132 | case MMP_SSPA_CLK_AUDIO: | ||
133 | ret = clk_set_rate(priv->audio_clk, freq); | ||
134 | if (ret) | ||
135 | return ret; | ||
136 | break; | ||
137 | case MMP_SSPA_CLK_PLL: | ||
138 | case MMP_SSPA_CLK_VCXO: | ||
139 | /* not support yet */ | ||
140 | return -EINVAL; | ||
141 | default: | ||
142 | return -EINVAL; | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int mmp_sspa_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, | ||
149 | int source, unsigned int freq_in, | ||
150 | unsigned int freq_out) | ||
151 | { | ||
152 | struct sspa_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
153 | int ret = 0; | ||
154 | |||
155 | switch (pll_id) { | ||
156 | case MMP_SYSCLK: | ||
157 | ret = clk_set_rate(priv->sysclk, freq_out); | ||
158 | if (ret) | ||
159 | return ret; | ||
160 | break; | ||
161 | case MMP_SSPA_CLK: | ||
162 | ret = clk_set_rate(priv->sspa->clk, freq_out); | ||
163 | if (ret) | ||
164 | return ret; | ||
165 | break; | ||
166 | default: | ||
167 | return -ENODEV; | ||
168 | } | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * Set up the sspa dai format. The sspa port must be inactive | ||
175 | * before calling this function as the physical | ||
176 | * interface format is changed. | ||
177 | */ | ||
178 | static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai, | ||
179 | unsigned int fmt) | ||
180 | { | ||
181 | struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(cpu_dai); | ||
182 | struct ssp_device *sspa = sspa_priv->sspa; | ||
183 | u32 sspa_sp, sspa_ctrl; | ||
184 | |||
185 | /* check if we need to change anything at all */ | ||
186 | if (sspa_priv->dai_fmt == fmt) | ||
187 | return 0; | ||
188 | |||
189 | /* we can only change the settings if the port is not in use */ | ||
190 | if ((mmp_sspa_read_reg(sspa, SSPA_TXSP) & SSPA_SP_S_EN) || | ||
191 | (mmp_sspa_read_reg(sspa, SSPA_RXSP) & SSPA_SP_S_EN)) { | ||
192 | dev_err(&sspa->pdev->dev, | ||
193 | "can't change hardware dai format: stream is in use\n"); | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | /* reset port settings */ | ||
198 | sspa_sp = SSPA_SP_WEN | SSPA_SP_S_RST | SSPA_SP_FFLUSH; | ||
199 | sspa_ctrl = 0; | ||
200 | |||
201 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
202 | case SND_SOC_DAIFMT_CBS_CFS: | ||
203 | sspa_sp |= SSPA_SP_MSL; | ||
204 | break; | ||
205 | case SND_SOC_DAIFMT_CBM_CFM: | ||
206 | break; | ||
207 | default: | ||
208 | return -EINVAL; | ||
209 | } | ||
210 | |||
211 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
212 | case SND_SOC_DAIFMT_NB_NF: | ||
213 | sspa_sp |= SSPA_SP_FSP; | ||
214 | break; | ||
215 | default: | ||
216 | return -EINVAL; | ||
217 | } | ||
218 | |||
219 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
220 | case SND_SOC_DAIFMT_I2S: | ||
221 | sspa_sp |= SSPA_TXSP_FPER(63); | ||
222 | sspa_sp |= SSPA_SP_FWID(31); | ||
223 | sspa_ctrl |= SSPA_CTL_XDATDLY(1); | ||
224 | break; | ||
225 | default: | ||
226 | return -EINVAL; | ||
227 | } | ||
228 | |||
229 | mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); | ||
230 | mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); | ||
231 | |||
232 | sspa_sp &= ~(SSPA_SP_S_RST | SSPA_SP_FFLUSH); | ||
233 | mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); | ||
234 | mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp); | ||
235 | |||
236 | /* | ||
237 | * FIXME: hw issue, for the tx serial port, | ||
238 | * can not config the master/slave mode; | ||
239 | * so must clean this bit. | ||
240 | * The master/slave mode has been set in the | ||
241 | * rx port. | ||
242 | */ | ||
243 | sspa_sp &= ~SSPA_SP_MSL; | ||
244 | mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp); | ||
245 | |||
246 | mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl); | ||
247 | mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl); | ||
248 | |||
249 | /* Since we are configuring the timings for the format by hand | ||
250 | * we have to defer some things until hw_params() where we | ||
251 | * know parameters like the sample size. | ||
252 | */ | ||
253 | sspa_priv->dai_fmt = fmt; | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | /* | ||
258 | * Set the SSPA audio DMA parameters and sample size. | ||
259 | * Can be called multiple times by oss emulation. | ||
260 | */ | ||
261 | static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, | ||
262 | struct snd_pcm_hw_params *params, | ||
263 | struct snd_soc_dai *dai) | ||
264 | { | ||
265 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
266 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
267 | struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai); | ||
268 | struct ssp_device *sspa = sspa_priv->sspa; | ||
269 | struct pxa2xx_pcm_dma_params *dma_params; | ||
270 | u32 sspa_ctrl; | ||
271 | |||
272 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
273 | sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_TXCTL); | ||
274 | else | ||
275 | sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_RXCTL); | ||
276 | |||
277 | sspa_ctrl &= ~SSPA_CTL_XFRLEN1_MASK; | ||
278 | sspa_ctrl |= SSPA_CTL_XFRLEN1(params_channels(params) - 1); | ||
279 | sspa_ctrl &= ~SSPA_CTL_XWDLEN1_MASK; | ||
280 | sspa_ctrl |= SSPA_CTL_XWDLEN1(SSPA_CTL_32_BITS); | ||
281 | sspa_ctrl &= ~SSPA_CTL_XSSZ1_MASK; | ||
282 | |||
283 | switch (params_format(params)) { | ||
284 | case SNDRV_PCM_FORMAT_S8: | ||
285 | sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_8_BITS); | ||
286 | break; | ||
287 | case SNDRV_PCM_FORMAT_S16_LE: | ||
288 | sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_16_BITS); | ||
289 | break; | ||
290 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
291 | sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_20_BITS); | ||
292 | break; | ||
293 | case SNDRV_PCM_FORMAT_S24_3LE: | ||
294 | sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_24_BITS); | ||
295 | break; | ||
296 | case SNDRV_PCM_FORMAT_S32_LE: | ||
297 | sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_32_BITS); | ||
298 | break; | ||
299 | default: | ||
300 | return -EINVAL; | ||
301 | } | ||
302 | |||
303 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
304 | mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl); | ||
305 | mmp_sspa_write_reg(sspa, SSPA_TXFIFO_LL, 0x1); | ||
306 | } else { | ||
307 | mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl); | ||
308 | mmp_sspa_write_reg(sspa, SSPA_RXFIFO_UL, 0x0); | ||
309 | } | ||
310 | |||
311 | dma_params = &sspa_priv->dma_params[substream->stream]; | ||
312 | dma_params->dev_addr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? | ||
313 | (sspa->phys_base + SSPA_TXD) : | ||
314 | (sspa->phys_base + SSPA_RXD); | ||
315 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params); | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int mmp_sspa_trigger(struct snd_pcm_substream *substream, int cmd, | ||
320 | struct snd_soc_dai *dai) | ||
321 | { | ||
322 | struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai); | ||
323 | struct ssp_device *sspa = sspa_priv->sspa; | ||
324 | int ret = 0; | ||
325 | |||
326 | switch (cmd) { | ||
327 | case SNDRV_PCM_TRIGGER_START: | ||
328 | case SNDRV_PCM_TRIGGER_RESUME: | ||
329 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
330 | /* | ||
331 | * whatever playback or capture, must enable rx. | ||
332 | * this is a hw issue, so need check if rx has been | ||
333 | * enabled or not; if has been enabled by another | ||
334 | * stream, do not enable again. | ||
335 | */ | ||
336 | if (!sspa_priv->running_cnt) | ||
337 | mmp_sspa_rx_enable(sspa); | ||
338 | |||
339 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
340 | mmp_sspa_tx_enable(sspa); | ||
341 | |||
342 | sspa_priv->running_cnt++; | ||
343 | break; | ||
344 | |||
345 | case SNDRV_PCM_TRIGGER_STOP: | ||
346 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
347 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
348 | sspa_priv->running_cnt--; | ||
349 | |||
350 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
351 | mmp_sspa_tx_disable(sspa); | ||
352 | |||
353 | /* have no capture stream, disable rx port */ | ||
354 | if (!sspa_priv->running_cnt) | ||
355 | mmp_sspa_rx_disable(sspa); | ||
356 | break; | ||
357 | |||
358 | default: | ||
359 | ret = -EINVAL; | ||
360 | } | ||
361 | |||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | static int mmp_sspa_probe(struct snd_soc_dai *dai) | ||
366 | { | ||
367 | struct sspa_priv *priv = dev_get_drvdata(dai->dev); | ||
368 | |||
369 | snd_soc_dai_set_drvdata(dai, priv); | ||
370 | return 0; | ||
371 | |||
372 | } | ||
373 | |||
374 | #define MMP_SSPA_RATES SNDRV_PCM_RATE_8000_192000 | ||
375 | #define MMP_SSPA_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ | ||
376 | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
377 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
378 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
379 | SNDRV_PCM_FMTBIT_S32_LE) | ||
380 | |||
381 | static struct snd_soc_dai_ops mmp_sspa_dai_ops = { | ||
382 | .startup = mmp_sspa_startup, | ||
383 | .shutdown = mmp_sspa_shutdown, | ||
384 | .trigger = mmp_sspa_trigger, | ||
385 | .hw_params = mmp_sspa_hw_params, | ||
386 | .set_sysclk = mmp_sspa_set_dai_sysclk, | ||
387 | .set_pll = mmp_sspa_set_dai_pll, | ||
388 | .set_fmt = mmp_sspa_set_dai_fmt, | ||
389 | }; | ||
390 | |||
391 | struct snd_soc_dai_driver mmp_sspa_dai = { | ||
392 | .probe = mmp_sspa_probe, | ||
393 | .playback = { | ||
394 | .channels_min = 1, | ||
395 | .channels_max = 128, | ||
396 | .rates = MMP_SSPA_RATES, | ||
397 | .formats = MMP_SSPA_FORMATS, | ||
398 | }, | ||
399 | .capture = { | ||
400 | .channels_min = 1, | ||
401 | .channels_max = 2, | ||
402 | .rates = MMP_SSPA_RATES, | ||
403 | .formats = MMP_SSPA_FORMATS, | ||
404 | }, | ||
405 | .ops = &mmp_sspa_dai_ops, | ||
406 | }; | ||
407 | |||
408 | static __devinit int asoc_mmp_sspa_probe(struct platform_device *pdev) | ||
409 | { | ||
410 | struct sspa_priv *priv; | ||
411 | struct resource *res; | ||
412 | |||
413 | priv = devm_kzalloc(&pdev->dev, | ||
414 | sizeof(struct sspa_priv), GFP_KERNEL); | ||
415 | if (!priv) | ||
416 | return -ENOMEM; | ||
417 | |||
418 | priv->sspa = devm_kzalloc(&pdev->dev, | ||
419 | sizeof(struct ssp_device), GFP_KERNEL); | ||
420 | if (priv->sspa == NULL) | ||
421 | return -ENOMEM; | ||
422 | |||
423 | priv->dma_params = devm_kzalloc(&pdev->dev, | ||
424 | 2 * sizeof(struct pxa2xx_pcm_dma_params), GFP_KERNEL); | ||
425 | if (priv->dma_params == NULL) | ||
426 | return -ENOMEM; | ||
427 | |||
428 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
429 | if (res == NULL) | ||
430 | return -ENOMEM; | ||
431 | |||
432 | priv->sspa->mmio_base = devm_request_and_ioremap(&pdev->dev, res); | ||
433 | if (priv->sspa->mmio_base == NULL) | ||
434 | return -ENODEV; | ||
435 | |||
436 | priv->sspa->clk = devm_clk_get(&pdev->dev, NULL); | ||
437 | if (IS_ERR(priv->sspa->clk)) | ||
438 | return PTR_ERR(priv->sspa->clk); | ||
439 | |||
440 | priv->audio_clk = clk_get(NULL, "mmp-audio"); | ||
441 | if (IS_ERR(priv->audio_clk)) | ||
442 | return PTR_ERR(priv->audio_clk); | ||
443 | |||
444 | priv->sysclk = clk_get(NULL, "mmp-sysclk"); | ||
445 | if (IS_ERR(priv->sysclk)) { | ||
446 | clk_put(priv->audio_clk); | ||
447 | return PTR_ERR(priv->sysclk); | ||
448 | } | ||
449 | clk_enable(priv->audio_clk); | ||
450 | priv->dai_fmt = (unsigned int) -1; | ||
451 | platform_set_drvdata(pdev, priv); | ||
452 | |||
453 | return snd_soc_register_dai(&pdev->dev, &mmp_sspa_dai); | ||
454 | } | ||
455 | |||
456 | static int __devexit asoc_mmp_sspa_remove(struct platform_device *pdev) | ||
457 | { | ||
458 | struct sspa_priv *priv = platform_get_drvdata(pdev); | ||
459 | |||
460 | clk_disable(priv->audio_clk); | ||
461 | clk_put(priv->audio_clk); | ||
462 | clk_put(priv->sysclk); | ||
463 | snd_soc_unregister_dai(&pdev->dev); | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | static struct platform_driver asoc_mmp_sspa_driver = { | ||
468 | .driver = { | ||
469 | .name = "mmp-sspa-dai", | ||
470 | .owner = THIS_MODULE, | ||
471 | }, | ||
472 | .probe = asoc_mmp_sspa_probe, | ||
473 | .remove = __devexit_p(asoc_mmp_sspa_remove), | ||
474 | }; | ||
475 | |||
476 | module_platform_driver(asoc_mmp_sspa_driver); | ||
477 | |||
478 | MODULE_AUTHOR("Leo Yan <leoy@marvell.com>"); | ||
479 | MODULE_DESCRIPTION("MMP SSPA SoC Interface"); | ||
480 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/pxa/mmp-sspa.h b/sound/soc/pxa/mmp-sspa.h new file mode 100644 index 000000000000..ea365cb9e784 --- /dev/null +++ b/sound/soc/pxa/mmp-sspa.h | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * linux/sound/soc/pxa/mmp-sspa.h | ||
3 | * | ||
4 | * Copyright (C) 2011 Marvell International Ltd. | ||
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 | #ifndef _MMP_SSPA_H | ||
22 | #define _MMP_SSPA_H | ||
23 | |||
24 | /* | ||
25 | * SSPA Registers | ||
26 | */ | ||
27 | #define SSPA_RXD (0x00) | ||
28 | #define SSPA_RXID (0x04) | ||
29 | #define SSPA_RXCTL (0x08) | ||
30 | #define SSPA_RXSP (0x0c) | ||
31 | #define SSPA_RXFIFO_UL (0x10) | ||
32 | #define SSPA_RXINT_MASK (0x14) | ||
33 | #define SSPA_RXC (0x18) | ||
34 | #define SSPA_RXFIFO_NOFS (0x1c) | ||
35 | #define SSPA_RXFIFO_SIZE (0x20) | ||
36 | |||
37 | #define SSPA_TXD (0x80) | ||
38 | #define SSPA_TXID (0x84) | ||
39 | #define SSPA_TXCTL (0x88) | ||
40 | #define SSPA_TXSP (0x8c) | ||
41 | #define SSPA_TXFIFO_LL (0x90) | ||
42 | #define SSPA_TXINT_MASK (0x94) | ||
43 | #define SSPA_TXC (0x98) | ||
44 | #define SSPA_TXFIFO_NOFS (0x9c) | ||
45 | #define SSPA_TXFIFO_SIZE (0xa0) | ||
46 | |||
47 | /* SSPA Control Register */ | ||
48 | #define SSPA_CTL_XPH (1 << 31) /* Read Phase */ | ||
49 | #define SSPA_CTL_XFIG (1 << 15) /* Transmit Zeros when FIFO Empty */ | ||
50 | #define SSPA_CTL_JST (1 << 3) /* Audio Sample Justification */ | ||
51 | #define SSPA_CTL_XFRLEN2_MASK (7 << 24) | ||
52 | #define SSPA_CTL_XFRLEN2(x) ((x) << 24) /* Transmit Frame Length in Phase 2 */ | ||
53 | #define SSPA_CTL_XWDLEN2_MASK (7 << 21) | ||
54 | #define SSPA_CTL_XWDLEN2(x) ((x) << 21) /* Transmit Word Length in Phase 2 */ | ||
55 | #define SSPA_CTL_XDATDLY(x) ((x) << 19) /* Tansmit Data Delay */ | ||
56 | #define SSPA_CTL_XSSZ2_MASK (7 << 16) | ||
57 | #define SSPA_CTL_XSSZ2(x) ((x) << 16) /* Transmit Sample Audio Size */ | ||
58 | #define SSPA_CTL_XFRLEN1_MASK (7 << 8) | ||
59 | #define SSPA_CTL_XFRLEN1(x) ((x) << 8) /* Transmit Frame Length in Phase 1 */ | ||
60 | #define SSPA_CTL_XWDLEN1_MASK (7 << 5) | ||
61 | #define SSPA_CTL_XWDLEN1(x) ((x) << 5) /* Transmit Word Length in Phase 1 */ | ||
62 | #define SSPA_CTL_XSSZ1_MASK (7 << 0) | ||
63 | #define SSPA_CTL_XSSZ1(x) ((x) << 0) /* XSSZ1 */ | ||
64 | |||
65 | #define SSPA_CTL_8_BITS (0x0) /* Sample Size */ | ||
66 | #define SSPA_CTL_12_BITS (0x1) | ||
67 | #define SSPA_CTL_16_BITS (0x2) | ||
68 | #define SSPA_CTL_20_BITS (0x3) | ||
69 | #define SSPA_CTL_24_BITS (0x4) | ||
70 | #define SSPA_CTL_32_BITS (0x5) | ||
71 | |||
72 | /* SSPA Serial Port Register */ | ||
73 | #define SSPA_SP_WEN (1 << 31) /* Write Configuration Enable */ | ||
74 | #define SSPA_SP_MSL (1 << 18) /* Master Slave Configuration */ | ||
75 | #define SSPA_SP_CLKP (1 << 17) /* CLKP Polarity Clock Edge Select */ | ||
76 | #define SSPA_SP_FSP (1 << 16) /* FSP Polarity Clock Edge Select */ | ||
77 | #define SSPA_SP_FFLUSH (1 << 2) /* FIFO Flush */ | ||
78 | #define SSPA_SP_S_RST (1 << 1) /* Active High Reset Signal */ | ||
79 | #define SSPA_SP_S_EN (1 << 0) /* Serial Clock Domain Enable */ | ||
80 | #define SSPA_SP_FWID(x) ((x) << 20) /* Frame-Sync Width */ | ||
81 | #define SSPA_TXSP_FPER(x) ((x) << 4) /* Frame-Sync Active */ | ||
82 | |||
83 | /* sspa clock sources */ | ||
84 | #define MMP_SSPA_CLK_PLL 0 | ||
85 | #define MMP_SSPA_CLK_VCXO 1 | ||
86 | #define MMP_SSPA_CLK_AUDIO 3 | ||
87 | |||
88 | /* sspa pll id */ | ||
89 | #define MMP_SYSCLK 0 | ||
90 | #define MMP_SSPA_CLK 1 | ||
91 | |||
92 | #endif /* _MMP_SSPA_H */ | ||
diff --git a/sound/soc/pxa/ttc-dkb.c b/sound/soc/pxa/ttc-dkb.c new file mode 100644 index 000000000000..935491a8a770 --- /dev/null +++ b/sound/soc/pxa/ttc-dkb.c | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | * linux/sound/soc/pxa/ttc_dkb.c | ||
3 | * | ||
4 | * Copyright (C) 2012 Marvell International Ltd. | ||
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 | #include <linux/module.h> | ||
22 | #include <linux/moduleparam.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/jack.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | #include <sound/pcm_params.h> | ||
29 | #include "../codecs/88pm860x-codec.h" | ||
30 | |||
31 | static struct snd_soc_jack hs_jack, mic_jack; | ||
32 | |||
33 | static struct snd_soc_jack_pin hs_jack_pins[] = { | ||
34 | { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, }, | ||
35 | }; | ||
36 | |||
37 | static struct snd_soc_jack_pin mic_jack_pins[] = { | ||
38 | { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, }, | ||
39 | }; | ||
40 | |||
41 | /* ttc machine dapm widgets */ | ||
42 | static const struct snd_soc_dapm_widget ttc_dapm_widgets[] = { | ||
43 | SND_SOC_DAPM_HP("Headset Stereophone", NULL), | ||
44 | SND_SOC_DAPM_LINE("Lineout Out 1", NULL), | ||
45 | SND_SOC_DAPM_LINE("Lineout Out 2", NULL), | ||
46 | SND_SOC_DAPM_SPK("Ext Speaker", NULL), | ||
47 | SND_SOC_DAPM_MIC("Ext Mic 1", NULL), | ||
48 | SND_SOC_DAPM_MIC("Headset Mic 2", NULL), | ||
49 | SND_SOC_DAPM_MIC("Ext Mic 3", NULL), | ||
50 | }; | ||
51 | |||
52 | /* ttc machine audio map */ | ||
53 | static const struct snd_soc_dapm_route ttc_audio_map[] = { | ||
54 | {"Headset Stereophone", NULL, "HS1"}, | ||
55 | {"Headset Stereophone", NULL, "HS2"}, | ||
56 | |||
57 | {"Ext Speaker", NULL, "LSP"}, | ||
58 | {"Ext Speaker", NULL, "LSN"}, | ||
59 | |||
60 | {"Lineout Out 1", NULL, "LINEOUT1"}, | ||
61 | {"Lineout Out 2", NULL, "LINEOUT2"}, | ||
62 | |||
63 | {"MIC1P", NULL, "Mic1 Bias"}, | ||
64 | {"MIC1N", NULL, "Mic1 Bias"}, | ||
65 | {"Mic1 Bias", NULL, "Ext Mic 1"}, | ||
66 | |||
67 | {"MIC2P", NULL, "Mic1 Bias"}, | ||
68 | {"MIC2N", NULL, "Mic1 Bias"}, | ||
69 | {"Mic1 Bias", NULL, "Headset Mic 2"}, | ||
70 | |||
71 | {"MIC3P", NULL, "Mic3 Bias"}, | ||
72 | {"MIC3N", NULL, "Mic3 Bias"}, | ||
73 | {"Mic3 Bias", NULL, "Ext Mic 3"}, | ||
74 | }; | ||
75 | |||
76 | static int ttc_pm860x_init(struct snd_soc_pcm_runtime *rtd) | ||
77 | { | ||
78 | struct snd_soc_codec *codec = rtd->codec; | ||
79 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
80 | |||
81 | /* connected pins */ | ||
82 | snd_soc_dapm_enable_pin(dapm, "Ext Speaker"); | ||
83 | snd_soc_dapm_enable_pin(dapm, "Ext Mic 1"); | ||
84 | snd_soc_dapm_enable_pin(dapm, "Ext Mic 3"); | ||
85 | snd_soc_dapm_disable_pin(dapm, "Headset Mic 2"); | ||
86 | snd_soc_dapm_disable_pin(dapm, "Headset Stereophone"); | ||
87 | |||
88 | /* Headset jack detection */ | ||
89 | snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE | ||
90 | | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, | ||
91 | &hs_jack); | ||
92 | snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), | ||
93 | hs_jack_pins); | ||
94 | snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE, | ||
95 | &mic_jack); | ||
96 | snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), | ||
97 | mic_jack_pins); | ||
98 | |||
99 | /* headphone, microphone detection & headset short detection */ | ||
100 | pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE, | ||
101 | SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2); | ||
102 | pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | /* ttc/td-dkb digital audio interface glue - connects codec <--> CPU */ | ||
108 | static struct snd_soc_dai_link ttc_pm860x_hifi_dai[] = { | ||
109 | { | ||
110 | .name = "88pm860x i2s", | ||
111 | .stream_name = "audio playback", | ||
112 | .codec_name = "88pm860x-codec", | ||
113 | .platform_name = "mmp-pcm-audio", | ||
114 | .cpu_dai_name = "pxa-ssp-dai.1", | ||
115 | .codec_dai_name = "88pm860x-i2s", | ||
116 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
117 | SND_SOC_DAIFMT_CBM_CFM, | ||
118 | .init = ttc_pm860x_init, | ||
119 | }, | ||
120 | }; | ||
121 | |||
122 | /* ttc/td audio machine driver */ | ||
123 | static struct snd_soc_card ttc_dkb_card = { | ||
124 | .name = "ttc-dkb-hifi", | ||
125 | .dai_link = ttc_pm860x_hifi_dai, | ||
126 | .num_links = ARRAY_SIZE(ttc_pm860x_hifi_dai), | ||
127 | |||
128 | .dapm_widgets = ttc_dapm_widgets, | ||
129 | .num_dapm_widgets = ARRAY_SIZE(ttc_dapm_widgets), | ||
130 | .dapm_routes = ttc_audio_map, | ||
131 | .num_dapm_routes = ARRAY_SIZE(ttc_audio_map), | ||
132 | }; | ||
133 | |||
134 | static int __devinit ttc_dkb_probe(struct platform_device *pdev) | ||
135 | { | ||
136 | struct snd_soc_card *card = &ttc_dkb_card; | ||
137 | int ret; | ||
138 | |||
139 | card->dev = &pdev->dev; | ||
140 | |||
141 | ret = snd_soc_register_card(card); | ||
142 | if (ret) | ||
143 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
144 | ret); | ||
145 | |||
146 | return ret; | ||
147 | } | ||
148 | |||
149 | static int __devexit ttc_dkb_remove(struct platform_device *pdev) | ||
150 | { | ||
151 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
152 | |||
153 | snd_soc_unregister_card(card); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static struct platform_driver ttc_dkb_driver = { | ||
159 | .driver = { | ||
160 | .name = "ttc-dkb-audio", | ||
161 | .owner = THIS_MODULE, | ||
162 | }, | ||
163 | .probe = ttc_dkb_probe, | ||
164 | .remove = __devexit_p(ttc_dkb_remove), | ||
165 | }; | ||
166 | |||
167 | module_platform_driver(ttc_dkb_driver); | ||
168 | |||
169 | /* Module information */ | ||
170 | MODULE_AUTHOR("Qiao Zhou, <zhouqiao@marvell.com>"); | ||
171 | MODULE_DESCRIPTION("ALSA SoC TTC DKB"); | ||
172 | MODULE_LICENSE("GPL"); | ||
173 | MODULE_ALIAS("platform:ttc-dkb-audio"); | ||
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index ddc6cde14e2a..f3ebc38c10fe 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c | |||
@@ -74,7 +74,7 @@ static void dma_enqueue(struct snd_pcm_substream *substream) | |||
74 | struct runtime_data *prtd = substream->runtime->private_data; | 74 | struct runtime_data *prtd = substream->runtime->private_data; |
75 | dma_addr_t pos = prtd->dma_pos; | 75 | dma_addr_t pos = prtd->dma_pos; |
76 | unsigned int limit; | 76 | unsigned int limit; |
77 | struct samsung_dma_prep_info dma_info; | 77 | struct samsung_dma_prep dma_info; |
78 | 78 | ||
79 | pr_debug("Entered %s\n", __func__); | 79 | pr_debug("Entered %s\n", __func__); |
80 | 80 | ||
@@ -146,7 +146,8 @@ static int dma_hw_params(struct snd_pcm_substream *substream, | |||
146 | unsigned long totbytes = params_buffer_bytes(params); | 146 | unsigned long totbytes = params_buffer_bytes(params); |
147 | struct s3c_dma_params *dma = | 147 | struct s3c_dma_params *dma = |
148 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 148 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
149 | struct samsung_dma_info dma_info; | 149 | struct samsung_dma_req req; |
150 | struct samsung_dma_config config; | ||
150 | 151 | ||
151 | pr_debug("Entered %s\n", __func__); | 152 | pr_debug("Entered %s\n", __func__); |
152 | 153 | ||
@@ -166,16 +167,17 @@ static int dma_hw_params(struct snd_pcm_substream *substream, | |||
166 | 167 | ||
167 | prtd->params->ops = samsung_dma_get_ops(); | 168 | prtd->params->ops = samsung_dma_get_ops(); |
168 | 169 | ||
169 | dma_info.cap = (samsung_dma_has_circular() ? | 170 | req.cap = (samsung_dma_has_circular() ? |
170 | DMA_CYCLIC : DMA_SLAVE); | 171 | DMA_CYCLIC : DMA_SLAVE); |
171 | dma_info.client = prtd->params->client; | 172 | req.client = prtd->params->client; |
172 | dma_info.direction = | 173 | config.direction = |
173 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK | 174 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK |
174 | ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); | 175 | ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); |
175 | dma_info.width = prtd->params->dma_size; | 176 | config.width = prtd->params->dma_size; |
176 | dma_info.fifo = prtd->params->dma_addr; | 177 | config.fifo = prtd->params->dma_addr; |
177 | prtd->params->ch = prtd->params->ops->request( | 178 | prtd->params->ch = prtd->params->ops->request( |
178 | prtd->params->channel, &dma_info); | 179 | prtd->params->channel, &req); |
180 | prtd->params->ops->config(prtd->params->ch, &config); | ||
179 | } | 181 | } |
180 | 182 | ||
181 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 183 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); |
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index c82c646b8a08..ee52c8a00779 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c | |||
@@ -211,6 +211,11 @@ static int bbclk_ev(struct snd_soc_dapm_widget *w, | |||
211 | return 0; | 211 | return 0; |
212 | } | 212 | } |
213 | 213 | ||
214 | static const struct snd_kcontrol_new controls[] = { | ||
215 | SOC_DAPM_PIN_SWITCH("WM1250 Input"), | ||
216 | SOC_DAPM_PIN_SWITCH("WM1250 Output"), | ||
217 | }; | ||
218 | |||
214 | static struct snd_soc_dapm_widget widgets[] = { | 219 | static struct snd_soc_dapm_widget widgets[] = { |
215 | SND_SOC_DAPM_HP("Headphone", NULL), | 220 | SND_SOC_DAPM_HP("Headphone", NULL), |
216 | 221 | ||
@@ -282,6 +287,8 @@ static struct snd_soc_card littlemill = { | |||
282 | .set_bias_level = littlemill_set_bias_level, | 287 | .set_bias_level = littlemill_set_bias_level, |
283 | .set_bias_level_post = littlemill_set_bias_level_post, | 288 | .set_bias_level_post = littlemill_set_bias_level_post, |
284 | 289 | ||
290 | .controls = controls, | ||
291 | .num_controls = ARRAY_SIZE(controls), | ||
285 | .dapm_widgets = widgets, | 292 | .dapm_widgets = widgets, |
286 | .num_dapm_widgets = ARRAY_SIZE(widgets), | 293 | .num_dapm_widgets = ARRAY_SIZE(widgets), |
287 | .dapm_routes = audio_paths, | 294 | .dapm_routes = audio_paths, |
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index 79fbeea99d46..ac7701b3c5dc 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
26 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
27 | 27 | ||
28 | #include <mach/regs-gpio.h> | ||
29 | #include <mach/dma.h> | 28 | #include <mach/dma.h> |
30 | 29 | ||
31 | #include "dma.h" | 30 | #include "dma.h" |
@@ -83,12 +82,9 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) | |||
83 | 82 | ||
84 | s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk; | 83 | s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk; |
85 | 84 | ||
86 | /* Configure the I2S pins in correct mode */ | 85 | /* Configure the I2S pins (GPE0...GPE4) in correct mode */ |
87 | s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK); | 86 | s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), |
88 | s3c2410_gpio_cfgpin(S3C2410_GPE1, S3C2410_GPE1_I2SSCLK); | 87 | S3C_GPIO_PULL_NONE); |
89 | s3c2410_gpio_cfgpin(S3C2410_GPE2, S3C2410_GPE2_CDCLK); | ||
90 | s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI); | ||
91 | s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO); | ||
92 | 88 | ||
93 | return 0; | 89 | return 0; |
94 | } | 90 | } |
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index c4aa4d412fbf..0aae3a3883dc 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
24 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
25 | 25 | ||
26 | #include <mach/regs-gpio.h> | ||
27 | #include <mach/dma.h> | 26 | #include <mach/dma.h> |
28 | #include <plat/regs-iis.h> | 27 | #include <plat/regs-iis.h> |
29 | 28 | ||
@@ -391,12 +390,9 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) | |||
391 | } | 390 | } |
392 | clk_enable(s3c24xx_i2s.iis_clk); | 391 | clk_enable(s3c24xx_i2s.iis_clk); |
393 | 392 | ||
394 | /* Configure the I2S pins in correct mode */ | 393 | /* Configure the I2S pins (GPE0...GPE4) in correct mode */ |
395 | s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK); | 394 | s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), |
396 | s3c2410_gpio_cfgpin(S3C2410_GPE1, S3C2410_GPE1_I2SSCLK); | 395 | S3C_GPIO_PULL_NONE); |
397 | s3c2410_gpio_cfgpin(S3C2410_GPE2, S3C2410_GPE2_CDCLK); | ||
398 | s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI); | ||
399 | s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO); | ||
400 | 396 | ||
401 | writel(S3C2410_IISCON_IISEN, s3c24xx_i2s.regs + S3C2410_IISCON); | 397 | writel(S3C2410_IISCON_IISEN, s3c24xx_i2s.regs + S3C2410_IISCON); |
402 | 398 | ||
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index 8eb309f23d18..48dd4dd9ee08 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c | |||
@@ -149,31 +149,41 @@ static struct snd_soc_card smdk = { | |||
149 | .num_links = ARRAY_SIZE(smdk_dai), | 149 | .num_links = ARRAY_SIZE(smdk_dai), |
150 | }; | 150 | }; |
151 | 151 | ||
152 | static struct platform_device *smdk_snd_device; | ||
153 | 152 | ||
154 | static int __init smdk_audio_init(void) | 153 | static int __devinit smdk_audio_probe(struct platform_device *pdev) |
155 | { | 154 | { |
156 | int ret; | 155 | int ret; |
156 | struct snd_soc_card *card = &smdk; | ||
157 | 157 | ||
158 | smdk_snd_device = platform_device_alloc("soc-audio", -1); | 158 | card->dev = &pdev->dev; |
159 | if (!smdk_snd_device) | 159 | ret = snd_soc_register_card(card); |
160 | return -ENOMEM; | ||
161 | 160 | ||
162 | platform_set_drvdata(smdk_snd_device, &smdk); | ||
163 | |||
164 | ret = platform_device_add(smdk_snd_device); | ||
165 | if (ret) | 161 | if (ret) |
166 | platform_device_put(smdk_snd_device); | 162 | dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret); |
167 | 163 | ||
168 | return ret; | 164 | return ret; |
169 | } | 165 | } |
170 | module_init(smdk_audio_init); | ||
171 | 166 | ||
172 | static void __exit smdk_audio_exit(void) | 167 | static int __devexit smdk_audio_remove(struct platform_device *pdev) |
173 | { | 168 | { |
174 | platform_device_unregister(smdk_snd_device); | 169 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
170 | |||
171 | snd_soc_unregister_card(card); | ||
172 | |||
173 | return 0; | ||
175 | } | 174 | } |
176 | module_exit(smdk_audio_exit); | 175 | |
176 | static struct platform_driver smdk_audio_driver = { | ||
177 | .driver = { | ||
178 | .name = "smdk-audio", | ||
179 | .owner = THIS_MODULE, | ||
180 | }, | ||
181 | .probe = smdk_audio_probe, | ||
182 | .remove = __devexit_p(smdk_audio_remove), | ||
183 | }; | ||
184 | |||
185 | module_platform_driver(smdk_audio_driver); | ||
177 | 186 | ||
178 | MODULE_DESCRIPTION("ALSA SoC SMDK WM8994"); | 187 | MODULE_DESCRIPTION("ALSA SoC SMDK WM8994"); |
179 | MODULE_LICENSE("GPL"); | 188 | MODULE_LICENSE("GPL"); |
189 | MODULE_ALIAS("platform:smdk-audio"); | ||
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 2ef98536f1da..0540408a9fa9 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -247,7 +247,7 @@ struct fsi_priv { | |||
247 | struct fsi_stream_handler { | 247 | struct fsi_stream_handler { |
248 | int (*init)(struct fsi_priv *fsi, struct fsi_stream *io); | 248 | int (*init)(struct fsi_priv *fsi, struct fsi_stream *io); |
249 | int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io); | 249 | int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io); |
250 | int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io); | 250 | int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev); |
251 | int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io); | 251 | int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io); |
252 | int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io); | 252 | int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io); |
253 | void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io, | 253 | void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io, |
@@ -571,16 +571,16 @@ static int fsi_stream_transfer(struct fsi_stream *io) | |||
571 | #define fsi_stream_stop(fsi, io)\ | 571 | #define fsi_stream_stop(fsi, io)\ |
572 | fsi_stream_handler_call(io, start_stop, fsi, io, 0) | 572 | fsi_stream_handler_call(io, start_stop, fsi, io, 0) |
573 | 573 | ||
574 | static int fsi_stream_probe(struct fsi_priv *fsi) | 574 | static int fsi_stream_probe(struct fsi_priv *fsi, struct device *dev) |
575 | { | 575 | { |
576 | struct fsi_stream *io; | 576 | struct fsi_stream *io; |
577 | int ret1, ret2; | 577 | int ret1, ret2; |
578 | 578 | ||
579 | io = &fsi->playback; | 579 | io = &fsi->playback; |
580 | ret1 = fsi_stream_handler_call(io, probe, fsi, io); | 580 | ret1 = fsi_stream_handler_call(io, probe, fsi, io, dev); |
581 | 581 | ||
582 | io = &fsi->capture; | 582 | io = &fsi->capture; |
583 | ret2 = fsi_stream_handler_call(io, probe, fsi, io); | 583 | ret2 = fsi_stream_handler_call(io, probe, fsi, io, dev); |
584 | 584 | ||
585 | if (ret1 < 0) | 585 | if (ret1 < 0) |
586 | return ret1; | 586 | return ret1; |
@@ -1089,13 +1089,10 @@ static void fsi_dma_do_tasklet(unsigned long data) | |||
1089 | { | 1089 | { |
1090 | struct fsi_stream *io = (struct fsi_stream *)data; | 1090 | struct fsi_stream *io = (struct fsi_stream *)data; |
1091 | struct fsi_priv *fsi = fsi_stream_to_priv(io); | 1091 | struct fsi_priv *fsi = fsi_stream_to_priv(io); |
1092 | struct dma_chan *chan; | ||
1093 | struct snd_soc_dai *dai; | 1092 | struct snd_soc_dai *dai; |
1094 | struct dma_async_tx_descriptor *desc; | 1093 | struct dma_async_tx_descriptor *desc; |
1095 | struct scatterlist sg; | ||
1096 | struct snd_pcm_runtime *runtime; | 1094 | struct snd_pcm_runtime *runtime; |
1097 | enum dma_data_direction dir; | 1095 | enum dma_data_direction dir; |
1098 | dma_cookie_t cookie; | ||
1099 | int is_play = fsi_stream_is_play(fsi, io); | 1096 | int is_play = fsi_stream_is_play(fsi, io); |
1100 | int len; | 1097 | int len; |
1101 | dma_addr_t buf; | 1098 | dma_addr_t buf; |
@@ -1104,7 +1101,6 @@ static void fsi_dma_do_tasklet(unsigned long data) | |||
1104 | return; | 1101 | return; |
1105 | 1102 | ||
1106 | dai = fsi_get_dai(io->substream); | 1103 | dai = fsi_get_dai(io->substream); |
1107 | chan = io->chan; | ||
1108 | runtime = io->substream->runtime; | 1104 | runtime = io->substream->runtime; |
1109 | dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 1105 | dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; |
1110 | len = samples_to_bytes(runtime, io->period_samples); | 1106 | len = samples_to_bytes(runtime, io->period_samples); |
@@ -1112,14 +1108,8 @@ static void fsi_dma_do_tasklet(unsigned long data) | |||
1112 | 1108 | ||
1113 | dma_sync_single_for_device(dai->dev, buf, len, dir); | 1109 | dma_sync_single_for_device(dai->dev, buf, len, dir); |
1114 | 1110 | ||
1115 | sg_init_table(&sg, 1); | 1111 | desc = dmaengine_prep_slave_single(io->chan, buf, len, dir, |
1116 | sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)), | 1112 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
1117 | len , offset_in_page(buf)); | ||
1118 | sg_dma_address(&sg) = buf; | ||
1119 | sg_dma_len(&sg) = len; | ||
1120 | |||
1121 | desc = dmaengine_prep_slave_sg(chan, &sg, 1, dir, | ||
1122 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
1123 | if (!desc) { | 1113 | if (!desc) { |
1124 | dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n"); | 1114 | dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n"); |
1125 | return; | 1115 | return; |
@@ -1128,13 +1118,12 @@ static void fsi_dma_do_tasklet(unsigned long data) | |||
1128 | desc->callback = fsi_dma_complete; | 1118 | desc->callback = fsi_dma_complete; |
1129 | desc->callback_param = io; | 1119 | desc->callback_param = io; |
1130 | 1120 | ||
1131 | cookie = desc->tx_submit(desc); | 1121 | if (dmaengine_submit(desc) < 0) { |
1132 | if (cookie < 0) { | ||
1133 | dev_err(dai->dev, "tx_submit() fail\n"); | 1122 | dev_err(dai->dev, "tx_submit() fail\n"); |
1134 | return; | 1123 | return; |
1135 | } | 1124 | } |
1136 | 1125 | ||
1137 | dma_async_issue_pending(chan); | 1126 | dma_async_issue_pending(io->chan); |
1138 | 1127 | ||
1139 | /* | 1128 | /* |
1140 | * FIXME | 1129 | * FIXME |
@@ -1184,7 +1173,7 @@ static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | |||
1184 | fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); | 1173 | fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); |
1185 | } | 1174 | } |
1186 | 1175 | ||
1187 | static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) | 1176 | static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev) |
1188 | { | 1177 | { |
1189 | dma_cap_mask_t mask; | 1178 | dma_cap_mask_t mask; |
1190 | 1179 | ||
@@ -1192,8 +1181,19 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) | |||
1192 | dma_cap_set(DMA_SLAVE, mask); | 1181 | dma_cap_set(DMA_SLAVE, mask); |
1193 | 1182 | ||
1194 | io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave); | 1183 | io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave); |
1195 | if (!io->chan) | 1184 | if (!io->chan) { |
1196 | return -EIO; | 1185 | |
1186 | /* switch to PIO handler */ | ||
1187 | if (fsi_stream_is_play(fsi, io)) | ||
1188 | fsi->playback.handler = &fsi_pio_push_handler; | ||
1189 | else | ||
1190 | fsi->capture.handler = &fsi_pio_pop_handler; | ||
1191 | |||
1192 | dev_info(dev, "switch handler (dma => pio)\n"); | ||
1193 | |||
1194 | /* probe again */ | ||
1195 | return fsi_stream_probe(fsi, dev); | ||
1196 | } | ||
1197 | 1197 | ||
1198 | tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io); | 1198 | tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io); |
1199 | 1199 | ||
@@ -1631,8 +1631,8 @@ static void fsi_handler_init(struct fsi_priv *fsi) | |||
1631 | fsi->capture.priv = fsi; | 1631 | fsi->capture.priv = fsi; |
1632 | 1632 | ||
1633 | if (fsi->info->tx_id) { | 1633 | if (fsi->info->tx_id) { |
1634 | fsi->playback.slave.slave_id = fsi->info->tx_id; | 1634 | fsi->playback.slave.shdma_slave.slave_id = fsi->info->tx_id; |
1635 | fsi->playback.handler = &fsi_dma_push_handler; | 1635 | fsi->playback.handler = &fsi_dma_push_handler; |
1636 | } | 1636 | } |
1637 | } | 1637 | } |
1638 | 1638 | ||
@@ -1683,7 +1683,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
1683 | master->fsia.master = master; | 1683 | master->fsia.master = master; |
1684 | master->fsia.info = &info->port_a; | 1684 | master->fsia.info = &info->port_a; |
1685 | fsi_handler_init(&master->fsia); | 1685 | fsi_handler_init(&master->fsia); |
1686 | ret = fsi_stream_probe(&master->fsia); | 1686 | ret = fsi_stream_probe(&master->fsia, &pdev->dev); |
1687 | if (ret < 0) { | 1687 | if (ret < 0) { |
1688 | dev_err(&pdev->dev, "FSIA stream probe failed\n"); | 1688 | dev_err(&pdev->dev, "FSIA stream probe failed\n"); |
1689 | goto exit_iounmap; | 1689 | goto exit_iounmap; |
@@ -1694,7 +1694,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
1694 | master->fsib.master = master; | 1694 | master->fsib.master = master; |
1695 | master->fsib.info = &info->port_b; | 1695 | master->fsib.info = &info->port_b; |
1696 | fsi_handler_init(&master->fsib); | 1696 | fsi_handler_init(&master->fsib); |
1697 | ret = fsi_stream_probe(&master->fsib); | 1697 | ret = fsi_stream_probe(&master->fsib, &pdev->dev); |
1698 | if (ret < 0) { | 1698 | if (ret < 0) { |
1699 | dev_err(&pdev->dev, "FSIB stream probe failed\n"); | 1699 | dev_err(&pdev->dev, "FSIB stream probe failed\n"); |
1700 | goto exit_fsia; | 1700 | goto exit_fsia; |
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index 5cfcc655e95f..488f9becb44f 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c | |||
@@ -330,12 +330,9 @@ static bool filter(struct dma_chan *chan, void *slave) | |||
330 | { | 330 | { |
331 | struct sh_dmae_slave *param = slave; | 331 | struct sh_dmae_slave *param = slave; |
332 | 332 | ||
333 | pr_debug("%s: slave ID %d\n", __func__, param->slave_id); | 333 | pr_debug("%s: slave ID %d\n", __func__, param->shdma_slave.slave_id); |
334 | 334 | ||
335 | if (unlikely(param->dma_dev != chan->device->dev)) | 335 | chan->private = ¶m->shdma_slave; |
336 | return false; | ||
337 | |||
338 | chan->private = param; | ||
339 | return true; | 336 | return true; |
340 | } | 337 | } |
341 | 338 | ||
@@ -360,16 +357,15 @@ static int siu_pcm_open(struct snd_pcm_substream *ss) | |||
360 | if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 357 | if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
361 | siu_stream = &port_info->playback; | 358 | siu_stream = &port_info->playback; |
362 | param = &siu_stream->param; | 359 | param = &siu_stream->param; |
363 | param->slave_id = port ? pdata->dma_slave_tx_b : | 360 | param->shdma_slave.slave_id = port ? pdata->dma_slave_tx_b : |
364 | pdata->dma_slave_tx_a; | 361 | pdata->dma_slave_tx_a; |
365 | } else { | 362 | } else { |
366 | siu_stream = &port_info->capture; | 363 | siu_stream = &port_info->capture; |
367 | param = &siu_stream->param; | 364 | param = &siu_stream->param; |
368 | param->slave_id = port ? pdata->dma_slave_rx_b : | 365 | param->shdma_slave.slave_id = port ? pdata->dma_slave_rx_b : |
369 | pdata->dma_slave_rx_a; | 366 | pdata->dma_slave_rx_a; |
370 | } | 367 | } |
371 | 368 | ||
372 | param->dma_dev = pdata->dma_dev; | ||
373 | /* Get DMA channel */ | 369 | /* Get DMA channel */ |
374 | siu_stream->chan = dma_request_channel(mask, filter, param); | 370 | siu_stream->chan = dma_request_channel(mask, filter, param); |
375 | if (!siu_stream->chan) { | 371 | if (!siu_stream->chan) { |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b37ee8077ed1..f219b2f7ee68 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -812,13 +812,15 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
812 | 812 | ||
813 | /* Find CPU DAI from registered DAIs*/ | 813 | /* Find CPU DAI from registered DAIs*/ |
814 | list_for_each_entry(cpu_dai, &dai_list, list) { | 814 | list_for_each_entry(cpu_dai, &dai_list, list) { |
815 | if (dai_link->cpu_dai_of_node) { | 815 | if (dai_link->cpu_of_node && |
816 | if (cpu_dai->dev->of_node != dai_link->cpu_dai_of_node) | 816 | (cpu_dai->dev->of_node != dai_link->cpu_of_node)) |
817 | continue; | 817 | continue; |
818 | } else { | 818 | if (dai_link->cpu_name && |
819 | if (strcmp(cpu_dai->name, dai_link->cpu_dai_name)) | 819 | strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name)) |
820 | continue; | 820 | continue; |
821 | } | 821 | if (dai_link->cpu_dai_name && |
822 | strcmp(cpu_dai->name, dai_link->cpu_dai_name)) | ||
823 | continue; | ||
822 | 824 | ||
823 | rtd->cpu_dai = cpu_dai; | 825 | rtd->cpu_dai = cpu_dai; |
824 | } | 826 | } |
@@ -896,6 +898,28 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
896 | return 0; | 898 | return 0; |
897 | } | 899 | } |
898 | 900 | ||
901 | static int soc_remove_platform(struct snd_soc_platform *platform) | ||
902 | { | ||
903 | int ret; | ||
904 | |||
905 | if (platform->driver->remove) { | ||
906 | ret = platform->driver->remove(platform); | ||
907 | if (ret < 0) | ||
908 | pr_err("asoc: failed to remove %s: %d\n", | ||
909 | platform->name, ret); | ||
910 | } | ||
911 | |||
912 | /* Make sure all DAPM widgets are freed */ | ||
913 | snd_soc_dapm_free(&platform->dapm); | ||
914 | |||
915 | soc_cleanup_platform_debugfs(platform); | ||
916 | platform->probed = 0; | ||
917 | list_del(&platform->card_list); | ||
918 | module_put(platform->dev->driver->owner); | ||
919 | |||
920 | return 0; | ||
921 | } | ||
922 | |||
899 | static void soc_remove_codec(struct snd_soc_codec *codec) | 923 | static void soc_remove_codec(struct snd_soc_codec *codec) |
900 | { | 924 | { |
901 | int err; | 925 | int err; |
@@ -917,11 +941,9 @@ static void soc_remove_codec(struct snd_soc_codec *codec) | |||
917 | module_put(codec->dev->driver->owner); | 941 | module_put(codec->dev->driver->owner); |
918 | } | 942 | } |
919 | 943 | ||
920 | static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) | 944 | static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) |
921 | { | 945 | { |
922 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 946 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
923 | struct snd_soc_codec *codec = rtd->codec; | ||
924 | struct snd_soc_platform *platform = rtd->platform; | ||
925 | struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; | 947 | struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; |
926 | int err; | 948 | int err; |
927 | 949 | ||
@@ -946,30 +968,6 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) | |||
946 | list_del(&codec_dai->card_list); | 968 | list_del(&codec_dai->card_list); |
947 | } | 969 | } |
948 | 970 | ||
949 | /* remove the platform */ | ||
950 | if (platform && platform->probed && | ||
951 | platform->driver->remove_order == order) { | ||
952 | if (platform->driver->remove) { | ||
953 | err = platform->driver->remove(platform); | ||
954 | if (err < 0) | ||
955 | pr_err("asoc: failed to remove %s: %d\n", | ||
956 | platform->name, err); | ||
957 | } | ||
958 | |||
959 | /* Make sure all DAPM widgets are freed */ | ||
960 | snd_soc_dapm_free(&platform->dapm); | ||
961 | |||
962 | soc_cleanup_platform_debugfs(platform); | ||
963 | platform->probed = 0; | ||
964 | list_del(&platform->card_list); | ||
965 | module_put(platform->dev->driver->owner); | ||
966 | } | ||
967 | |||
968 | /* remove the CODEC */ | ||
969 | if (codec && codec->probed && | ||
970 | codec->driver->remove_order == order) | ||
971 | soc_remove_codec(codec); | ||
972 | |||
973 | /* remove the cpu_dai */ | 971 | /* remove the cpu_dai */ |
974 | if (cpu_dai && cpu_dai->probed && | 972 | if (cpu_dai && cpu_dai->probed && |
975 | cpu_dai->driver->remove_order == order) { | 973 | cpu_dai->driver->remove_order == order) { |
@@ -981,7 +979,43 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) | |||
981 | } | 979 | } |
982 | cpu_dai->probed = 0; | 980 | cpu_dai->probed = 0; |
983 | list_del(&cpu_dai->card_list); | 981 | list_del(&cpu_dai->card_list); |
984 | module_put(cpu_dai->dev->driver->owner); | 982 | |
983 | if (!cpu_dai->codec) { | ||
984 | snd_soc_dapm_free(&cpu_dai->dapm); | ||
985 | module_put(cpu_dai->dev->driver->owner); | ||
986 | } | ||
987 | } | ||
988 | } | ||
989 | |||
990 | static void soc_remove_link_components(struct snd_soc_card *card, int num, | ||
991 | int order) | ||
992 | { | ||
993 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | ||
994 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
995 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
996 | struct snd_soc_platform *platform = rtd->platform; | ||
997 | struct snd_soc_codec *codec; | ||
998 | |||
999 | /* remove the platform */ | ||
1000 | if (platform && platform->probed && | ||
1001 | platform->driver->remove_order == order) { | ||
1002 | soc_remove_platform(platform); | ||
1003 | } | ||
1004 | |||
1005 | /* remove the CODEC-side CODEC */ | ||
1006 | if (codec_dai) { | ||
1007 | codec = codec_dai->codec; | ||
1008 | if (codec && codec->probed && | ||
1009 | codec->driver->remove_order == order) | ||
1010 | soc_remove_codec(codec); | ||
1011 | } | ||
1012 | |||
1013 | /* remove any CPU-side CODEC */ | ||
1014 | if (cpu_dai) { | ||
1015 | codec = cpu_dai->codec; | ||
1016 | if (codec && codec->probed && | ||
1017 | codec->driver->remove_order == order) | ||
1018 | soc_remove_codec(codec); | ||
985 | } | 1019 | } |
986 | } | 1020 | } |
987 | 1021 | ||
@@ -992,8 +1026,15 @@ static void soc_remove_dai_links(struct snd_soc_card *card) | |||
992 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 1026 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; |
993 | order++) { | 1027 | order++) { |
994 | for (dai = 0; dai < card->num_rtd; dai++) | 1028 | for (dai = 0; dai < card->num_rtd; dai++) |
995 | soc_remove_dai_link(card, dai, order); | 1029 | soc_remove_link_dais(card, dai, order); |
996 | } | 1030 | } |
1031 | |||
1032 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | ||
1033 | order++) { | ||
1034 | for (dai = 0; dai < card->num_rtd; dai++) | ||
1035 | soc_remove_link_components(card, dai, order); | ||
1036 | } | ||
1037 | |||
997 | card->num_rtd = 0; | 1038 | card->num_rtd = 0; |
998 | } | 1039 | } |
999 | 1040 | ||
@@ -1054,6 +1095,10 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1054 | } | 1095 | } |
1055 | } | 1096 | } |
1056 | 1097 | ||
1098 | /* If the driver didn't set I/O up try regmap */ | ||
1099 | if (!codec->control_data) | ||
1100 | snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); | ||
1101 | |||
1057 | if (driver->controls) | 1102 | if (driver->controls) |
1058 | snd_soc_add_codec_controls(codec, driver->controls, | 1103 | snd_soc_add_codec_controls(codec, driver->controls, |
1059 | driver->num_controls); | 1104 | driver->num_controls); |
@@ -1230,7 +1275,44 @@ out: | |||
1230 | return 0; | 1275 | return 0; |
1231 | } | 1276 | } |
1232 | 1277 | ||
1233 | static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) | 1278 | static int soc_probe_link_components(struct snd_soc_card *card, int num, |
1279 | int order) | ||
1280 | { | ||
1281 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | ||
1282 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
1283 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
1284 | struct snd_soc_platform *platform = rtd->platform; | ||
1285 | int ret; | ||
1286 | |||
1287 | /* probe the CPU-side component, if it is a CODEC */ | ||
1288 | if (cpu_dai->codec && | ||
1289 | !cpu_dai->codec->probed && | ||
1290 | cpu_dai->codec->driver->probe_order == order) { | ||
1291 | ret = soc_probe_codec(card, cpu_dai->codec); | ||
1292 | if (ret < 0) | ||
1293 | return ret; | ||
1294 | } | ||
1295 | |||
1296 | /* probe the CODEC-side component */ | ||
1297 | if (!codec_dai->codec->probed && | ||
1298 | codec_dai->codec->driver->probe_order == order) { | ||
1299 | ret = soc_probe_codec(card, codec_dai->codec); | ||
1300 | if (ret < 0) | ||
1301 | return ret; | ||
1302 | } | ||
1303 | |||
1304 | /* probe the platform */ | ||
1305 | if (!platform->probed && | ||
1306 | platform->driver->probe_order == order) { | ||
1307 | ret = soc_probe_platform(card, platform); | ||
1308 | if (ret < 0) | ||
1309 | return ret; | ||
1310 | } | ||
1311 | |||
1312 | return 0; | ||
1313 | } | ||
1314 | |||
1315 | static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | ||
1234 | { | 1316 | { |
1235 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 1317 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
1236 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1318 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
@@ -1255,11 +1337,14 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) | |||
1255 | /* probe the cpu_dai */ | 1337 | /* probe the cpu_dai */ |
1256 | if (!cpu_dai->probed && | 1338 | if (!cpu_dai->probed && |
1257 | cpu_dai->driver->probe_order == order) { | 1339 | cpu_dai->driver->probe_order == order) { |
1258 | cpu_dai->dapm.card = card; | 1340 | if (!cpu_dai->codec) { |
1259 | if (!try_module_get(cpu_dai->dev->driver->owner)) | 1341 | cpu_dai->dapm.card = card; |
1260 | return -ENODEV; | 1342 | if (!try_module_get(cpu_dai->dev->driver->owner)) |
1343 | return -ENODEV; | ||
1261 | 1344 | ||
1262 | snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai); | 1345 | list_add(&cpu_dai->dapm.list, &card->dapm_list); |
1346 | snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai); | ||
1347 | } | ||
1263 | 1348 | ||
1264 | if (cpu_dai->driver->probe) { | 1349 | if (cpu_dai->driver->probe) { |
1265 | ret = cpu_dai->driver->probe(cpu_dai); | 1350 | ret = cpu_dai->driver->probe(cpu_dai); |
@@ -1275,22 +1360,6 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) | |||
1275 | list_add(&cpu_dai->card_list, &card->dai_dev_list); | 1360 | list_add(&cpu_dai->card_list, &card->dai_dev_list); |
1276 | } | 1361 | } |
1277 | 1362 | ||
1278 | /* probe the CODEC */ | ||
1279 | if (!codec->probed && | ||
1280 | codec->driver->probe_order == order) { | ||
1281 | ret = soc_probe_codec(card, codec); | ||
1282 | if (ret < 0) | ||
1283 | return ret; | ||
1284 | } | ||
1285 | |||
1286 | /* probe the platform */ | ||
1287 | if (!platform->probed && | ||
1288 | platform->driver->probe_order == order) { | ||
1289 | ret = soc_probe_platform(card, platform); | ||
1290 | if (ret < 0) | ||
1291 | return ret; | ||
1292 | } | ||
1293 | |||
1294 | /* probe the CODEC DAI */ | 1363 | /* probe the CODEC DAI */ |
1295 | if (!codec_dai->probed && codec_dai->driver->probe_order == order) { | 1364 | if (!codec_dai->probed && codec_dai->driver->probe_order == order) { |
1296 | if (codec_dai->driver->probe) { | 1365 | if (codec_dai->driver->probe) { |
@@ -1565,14 +1634,27 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1565 | goto card_probe_error; | 1634 | goto card_probe_error; |
1566 | } | 1635 | } |
1567 | 1636 | ||
1568 | /* early DAI link probe */ | 1637 | /* probe all components used by DAI links on this card */ |
1569 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 1638 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; |
1570 | order++) { | 1639 | order++) { |
1571 | for (i = 0; i < card->num_links; i++) { | 1640 | for (i = 0; i < card->num_links; i++) { |
1572 | ret = soc_probe_dai_link(card, i, order); | 1641 | ret = soc_probe_link_components(card, i, order); |
1573 | if (ret < 0) { | 1642 | if (ret < 0) { |
1574 | pr_err("asoc: failed to instantiate card %s: %d\n", | 1643 | pr_err("asoc: failed to instantiate card %s: %d\n", |
1575 | card->name, ret); | 1644 | card->name, ret); |
1645 | goto probe_dai_err; | ||
1646 | } | ||
1647 | } | ||
1648 | } | ||
1649 | |||
1650 | /* probe all DAI links on this card */ | ||
1651 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | ||
1652 | order++) { | ||
1653 | for (i = 0; i < card->num_links; i++) { | ||
1654 | ret = soc_probe_link_dais(card, i, order); | ||
1655 | if (ret < 0) { | ||
1656 | pr_err("asoc: failed to instantiate card %s: %d\n", | ||
1657 | card->name, ret); | ||
1576 | goto probe_dai_err; | 1658 | goto probe_dai_err; |
1577 | } | 1659 | } |
1578 | } | 1660 | } |
@@ -2790,6 +2872,104 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, | |||
2790 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); | 2872 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); |
2791 | 2873 | ||
2792 | /** | 2874 | /** |
2875 | * snd_soc_info_volsw_range - single mixer info callback with range. | ||
2876 | * @kcontrol: mixer control | ||
2877 | * @uinfo: control element information | ||
2878 | * | ||
2879 | * Callback to provide information, within a range, about a single | ||
2880 | * mixer control. | ||
2881 | * | ||
2882 | * returns 0 for success. | ||
2883 | */ | ||
2884 | int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, | ||
2885 | struct snd_ctl_elem_info *uinfo) | ||
2886 | { | ||
2887 | struct soc_mixer_control *mc = | ||
2888 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2889 | int platform_max; | ||
2890 | int min = mc->min; | ||
2891 | |||
2892 | if (!mc->platform_max) | ||
2893 | mc->platform_max = mc->max; | ||
2894 | platform_max = mc->platform_max; | ||
2895 | |||
2896 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2897 | uinfo->count = 1; | ||
2898 | uinfo->value.integer.min = 0; | ||
2899 | uinfo->value.integer.max = platform_max - min; | ||
2900 | |||
2901 | return 0; | ||
2902 | } | ||
2903 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); | ||
2904 | |||
2905 | /** | ||
2906 | * snd_soc_put_volsw_range - single mixer put value callback with range. | ||
2907 | * @kcontrol: mixer control | ||
2908 | * @ucontrol: control element information | ||
2909 | * | ||
2910 | * Callback to set the value, within a range, for a single mixer control. | ||
2911 | * | ||
2912 | * Returns 0 for success. | ||
2913 | */ | ||
2914 | int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | ||
2915 | struct snd_ctl_elem_value *ucontrol) | ||
2916 | { | ||
2917 | struct soc_mixer_control *mc = | ||
2918 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2919 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2920 | unsigned int reg = mc->reg; | ||
2921 | unsigned int shift = mc->shift; | ||
2922 | int min = mc->min; | ||
2923 | int max = mc->max; | ||
2924 | unsigned int mask = (1 << fls(max)) - 1; | ||
2925 | unsigned int invert = mc->invert; | ||
2926 | unsigned int val, val_mask; | ||
2927 | |||
2928 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
2929 | if (invert) | ||
2930 | val = max - val; | ||
2931 | val_mask = mask << shift; | ||
2932 | val = val << shift; | ||
2933 | |||
2934 | return snd_soc_update_bits_locked(codec, reg, val_mask, val); | ||
2935 | } | ||
2936 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); | ||
2937 | |||
2938 | /** | ||
2939 | * snd_soc_get_volsw_range - single mixer get callback with range | ||
2940 | * @kcontrol: mixer control | ||
2941 | * @ucontrol: control element information | ||
2942 | * | ||
2943 | * Callback to get the value, within a range, of a single mixer control. | ||
2944 | * | ||
2945 | * Returns 0 for success. | ||
2946 | */ | ||
2947 | int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, | ||
2948 | struct snd_ctl_elem_value *ucontrol) | ||
2949 | { | ||
2950 | struct soc_mixer_control *mc = | ||
2951 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2952 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2953 | unsigned int reg = mc->reg; | ||
2954 | unsigned int shift = mc->shift; | ||
2955 | int min = mc->min; | ||
2956 | int max = mc->max; | ||
2957 | unsigned int mask = (1 << fls(max)) - 1; | ||
2958 | unsigned int invert = mc->invert; | ||
2959 | |||
2960 | ucontrol->value.integer.value[0] = | ||
2961 | (snd_soc_read(codec, reg) >> shift) & mask; | ||
2962 | if (invert) | ||
2963 | ucontrol->value.integer.value[0] = | ||
2964 | max - ucontrol->value.integer.value[0]; | ||
2965 | ucontrol->value.integer.value[0] = | ||
2966 | ucontrol->value.integer.value[0] - min; | ||
2967 | |||
2968 | return 0; | ||
2969 | } | ||
2970 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); | ||
2971 | |||
2972 | /** | ||
2793 | * snd_soc_limit_volume - Set new limit to an existing volume control. | 2973 | * snd_soc_limit_volume - Set new limit to an existing volume control. |
2794 | * | 2974 | * |
2795 | * @codec: where to look for the control | 2975 | * @codec: where to look for the control |
@@ -3346,6 +3526,12 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3346 | link->name); | 3526 | link->name); |
3347 | return -EINVAL; | 3527 | return -EINVAL; |
3348 | } | 3528 | } |
3529 | /* Codec DAI name must be specified */ | ||
3530 | if (!link->codec_dai_name) { | ||
3531 | dev_err(card->dev, "codec_dai_name not set for %s\n", | ||
3532 | link->name); | ||
3533 | return -EINVAL; | ||
3534 | } | ||
3349 | 3535 | ||
3350 | /* | 3536 | /* |
3351 | * Platform may be specified by either name or OF node, but | 3537 | * Platform may be specified by either name or OF node, but |
@@ -3358,12 +3544,24 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
3358 | } | 3544 | } |
3359 | 3545 | ||
3360 | /* | 3546 | /* |
3361 | * CPU DAI must be specified by 1 of name or OF node, | 3547 | * CPU device may be specified by either name or OF node, but |
3362 | * not both or neither. | 3548 | * can be left unspecified, and will be matched based on DAI |
3549 | * name alone.. | ||
3550 | */ | ||
3551 | if (link->cpu_name && link->cpu_of_node) { | ||
3552 | dev_err(card->dev, | ||
3553 | "Neither/both cpu name/of_node are set for %s\n", | ||
3554 | link->name); | ||
3555 | return -EINVAL; | ||
3556 | } | ||
3557 | /* | ||
3558 | * At least one of CPU DAI name or CPU device name/node must be | ||
3559 | * specified | ||
3363 | */ | 3560 | */ |
3364 | if (!!link->cpu_dai_name == !!link->cpu_dai_of_node) { | 3561 | if (!link->cpu_dai_name && |
3562 | !(link->cpu_name || link->cpu_of_node)) { | ||
3365 | dev_err(card->dev, | 3563 | dev_err(card->dev, |
3366 | "Neither/both cpu_dai name/of_node are set for %s\n", | 3564 | "Neither cpu_dai_name nor cpu_name/of_node are set for %s\n", |
3367 | link->name); | 3565 | link->name); |
3368 | return -EINVAL; | 3566 | return -EINVAL; |
3369 | } | 3567 | } |
@@ -3938,6 +4136,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
3938 | dev_err(card->dev, | 4136 | dev_err(card->dev, |
3939 | "Property '%s' index %d could not be read: %d\n", | 4137 | "Property '%s' index %d could not be read: %d\n", |
3940 | propname, 2 * i, ret); | 4138 | propname, 2 * i, ret); |
4139 | kfree(routes); | ||
3941 | return -EINVAL; | 4140 | return -EINVAL; |
3942 | } | 4141 | } |
3943 | ret = of_property_read_string_index(np, propname, | 4142 | ret = of_property_read_string_index(np, propname, |
@@ -3946,6 +4145,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
3946 | dev_err(card->dev, | 4145 | dev_err(card->dev, |
3947 | "Property '%s' index %d could not be read: %d\n", | 4146 | "Property '%s' index %d could not be read: %d\n", |
3948 | propname, (2 * i) + 1, ret); | 4147 | propname, (2 * i) + 1, ret); |
4148 | kfree(routes); | ||
3949 | return -EINVAL; | 4149 | return -EINVAL; |
3950 | } | 4150 | } |
3951 | } | 4151 | } |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index fa1e31206892..dd7c49fafd75 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/debugfs.h> | 35 | #include <linux/debugfs.h> |
36 | #include <linux/pm_runtime.h> | 36 | #include <linux/pm_runtime.h> |
37 | #include <linux/regulator/consumer.h> | 37 | #include <linux/regulator/consumer.h> |
38 | #include <linux/clk.h> | ||
38 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
39 | #include <sound/core.h> | 40 | #include <sound/core.h> |
40 | #include <sound/pcm.h> | 41 | #include <sound/pcm.h> |
@@ -51,6 +52,7 @@ static int dapm_up_seq[] = { | |||
51 | [snd_soc_dapm_pre] = 0, | 52 | [snd_soc_dapm_pre] = 0, |
52 | [snd_soc_dapm_supply] = 1, | 53 | [snd_soc_dapm_supply] = 1, |
53 | [snd_soc_dapm_regulator_supply] = 1, | 54 | [snd_soc_dapm_regulator_supply] = 1, |
55 | [snd_soc_dapm_clock_supply] = 1, | ||
54 | [snd_soc_dapm_micbias] = 2, | 56 | [snd_soc_dapm_micbias] = 2, |
55 | [snd_soc_dapm_dai_link] = 2, | 57 | [snd_soc_dapm_dai_link] = 2, |
56 | [snd_soc_dapm_dai] = 3, | 58 | [snd_soc_dapm_dai] = 3, |
@@ -92,6 +94,7 @@ static int dapm_down_seq[] = { | |||
92 | [snd_soc_dapm_aif_out] = 10, | 94 | [snd_soc_dapm_aif_out] = 10, |
93 | [snd_soc_dapm_dai] = 10, | 95 | [snd_soc_dapm_dai] = 10, |
94 | [snd_soc_dapm_dai_link] = 11, | 96 | [snd_soc_dapm_dai_link] = 11, |
97 | [snd_soc_dapm_clock_supply] = 12, | ||
95 | [snd_soc_dapm_regulator_supply] = 12, | 98 | [snd_soc_dapm_regulator_supply] = 12, |
96 | [snd_soc_dapm_supply] = 12, | 99 | [snd_soc_dapm_supply] = 12, |
97 | [snd_soc_dapm_post] = 13, | 100 | [snd_soc_dapm_post] = 13, |
@@ -288,9 +291,9 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, | |||
288 | if (dapm->codec->driver->set_bias_level) | 291 | if (dapm->codec->driver->set_bias_level) |
289 | ret = dapm->codec->driver->set_bias_level(dapm->codec, | 292 | ret = dapm->codec->driver->set_bias_level(dapm->codec, |
290 | level); | 293 | level); |
291 | else | 294 | } else |
292 | dapm->bias_level = level; | 295 | dapm->bias_level = level; |
293 | } | 296 | |
294 | if (ret != 0) | 297 | if (ret != 0) |
295 | goto out; | 298 | goto out; |
296 | 299 | ||
@@ -321,11 +324,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
321 | 324 | ||
322 | val = soc_widget_read(w, reg); | 325 | val = soc_widget_read(w, reg); |
323 | val = (val >> shift) & mask; | 326 | val = (val >> shift) & mask; |
327 | if (invert) | ||
328 | val = max - val; | ||
324 | 329 | ||
325 | if ((invert && !val) || (!invert && val)) | 330 | p->connect = !!val; |
326 | p->connect = 1; | ||
327 | else | ||
328 | p->connect = 0; | ||
329 | } | 331 | } |
330 | break; | 332 | break; |
331 | case snd_soc_dapm_mux: { | 333 | case snd_soc_dapm_mux: { |
@@ -391,6 +393,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
391 | case snd_soc_dapm_vmid: | 393 | case snd_soc_dapm_vmid: |
392 | case snd_soc_dapm_supply: | 394 | case snd_soc_dapm_supply: |
393 | case snd_soc_dapm_regulator_supply: | 395 | case snd_soc_dapm_regulator_supply: |
396 | case snd_soc_dapm_clock_supply: | ||
394 | case snd_soc_dapm_aif_in: | 397 | case snd_soc_dapm_aif_in: |
395 | case snd_soc_dapm_aif_out: | 398 | case snd_soc_dapm_aif_out: |
396 | case snd_soc_dapm_dai: | 399 | case snd_soc_dapm_dai: |
@@ -764,6 +767,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget, | |||
764 | switch (widget->id) { | 767 | switch (widget->id) { |
765 | case snd_soc_dapm_supply: | 768 | case snd_soc_dapm_supply: |
766 | case snd_soc_dapm_regulator_supply: | 769 | case snd_soc_dapm_regulator_supply: |
770 | case snd_soc_dapm_clock_supply: | ||
767 | return 0; | 771 | return 0; |
768 | default: | 772 | default: |
769 | break; | 773 | break; |
@@ -850,6 +854,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, | |||
850 | switch (widget->id) { | 854 | switch (widget->id) { |
851 | case snd_soc_dapm_supply: | 855 | case snd_soc_dapm_supply: |
852 | case snd_soc_dapm_regulator_supply: | 856 | case snd_soc_dapm_regulator_supply: |
857 | case snd_soc_dapm_clock_supply: | ||
853 | return 0; | 858 | return 0; |
854 | default: | 859 | default: |
855 | break; | 860 | break; |
@@ -996,6 +1001,27 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, | |||
996 | } | 1001 | } |
997 | EXPORT_SYMBOL_GPL(dapm_regulator_event); | 1002 | EXPORT_SYMBOL_GPL(dapm_regulator_event); |
998 | 1003 | ||
1004 | /* | ||
1005 | * Handler for clock supply widget. | ||
1006 | */ | ||
1007 | int dapm_clock_event(struct snd_soc_dapm_widget *w, | ||
1008 | struct snd_kcontrol *kcontrol, int event) | ||
1009 | { | ||
1010 | if (!w->clk) | ||
1011 | return -EIO; | ||
1012 | |||
1013 | #ifdef CONFIG_HAVE_CLK | ||
1014 | if (SND_SOC_DAPM_EVENT_ON(event)) { | ||
1015 | return clk_enable(w->clk); | ||
1016 | } else { | ||
1017 | clk_disable(w->clk); | ||
1018 | return 0; | ||
1019 | } | ||
1020 | #endif | ||
1021 | return 0; | ||
1022 | } | ||
1023 | EXPORT_SYMBOL_GPL(dapm_clock_event); | ||
1024 | |||
999 | static int dapm_widget_power_check(struct snd_soc_dapm_widget *w) | 1025 | static int dapm_widget_power_check(struct snd_soc_dapm_widget *w) |
1000 | { | 1026 | { |
1001 | if (w->power_checked) | 1027 | if (w->power_checked) |
@@ -1487,6 +1513,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power, | |||
1487 | switch (w->id) { | 1513 | switch (w->id) { |
1488 | case snd_soc_dapm_supply: | 1514 | case snd_soc_dapm_supply: |
1489 | case snd_soc_dapm_regulator_supply: | 1515 | case snd_soc_dapm_regulator_supply: |
1516 | case snd_soc_dapm_clock_supply: | ||
1490 | /* Supplies can't affect their outputs, only their inputs */ | 1517 | /* Supplies can't affect their outputs, only their inputs */ |
1491 | break; | 1518 | break; |
1492 | default: | 1519 | default: |
@@ -1570,7 +1597,15 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1570 | } | 1597 | } |
1571 | 1598 | ||
1572 | list_for_each_entry(w, &card->widgets, list) { | 1599 | list_for_each_entry(w, &card->widgets, list) { |
1573 | list_del_init(&w->dirty); | 1600 | switch (w->id) { |
1601 | case snd_soc_dapm_pre: | ||
1602 | case snd_soc_dapm_post: | ||
1603 | /* These widgets always need to be powered */ | ||
1604 | break; | ||
1605 | default: | ||
1606 | list_del_init(&w->dirty); | ||
1607 | break; | ||
1608 | } | ||
1574 | 1609 | ||
1575 | if (w->power) { | 1610 | if (w->power) { |
1576 | d = w->dapm; | 1611 | d = w->dapm; |
@@ -1587,6 +1622,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1587 | break; | 1622 | break; |
1588 | case snd_soc_dapm_supply: | 1623 | case snd_soc_dapm_supply: |
1589 | case snd_soc_dapm_regulator_supply: | 1624 | case snd_soc_dapm_regulator_supply: |
1625 | case snd_soc_dapm_clock_supply: | ||
1590 | case snd_soc_dapm_micbias: | 1626 | case snd_soc_dapm_micbias: |
1591 | if (d->target_bias_level < SND_SOC_BIAS_STANDBY) | 1627 | if (d->target_bias_level < SND_SOC_BIAS_STANDBY) |
1592 | d->target_bias_level = SND_SOC_BIAS_STANDBY; | 1628 | d->target_bias_level = SND_SOC_BIAS_STANDBY; |
@@ -1941,6 +1977,7 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
1941 | case snd_soc_dapm_mixer_named_ctl: | 1977 | case snd_soc_dapm_mixer_named_ctl: |
1942 | case snd_soc_dapm_supply: | 1978 | case snd_soc_dapm_supply: |
1943 | case snd_soc_dapm_regulator_supply: | 1979 | case snd_soc_dapm_regulator_supply: |
1980 | case snd_soc_dapm_clock_supply: | ||
1944 | if (w->name) | 1981 | if (w->name) |
1945 | count += sprintf(buf + count, "%s: %s\n", | 1982 | count += sprintf(buf + count, "%s: %s\n", |
1946 | w->name, w->power ? "On":"Off"); | 1983 | w->name, w->power ? "On":"Off"); |
@@ -2187,6 +2224,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
2187 | case snd_soc_dapm_post: | 2224 | case snd_soc_dapm_post: |
2188 | case snd_soc_dapm_supply: | 2225 | case snd_soc_dapm_supply: |
2189 | case snd_soc_dapm_regulator_supply: | 2226 | case snd_soc_dapm_regulator_supply: |
2227 | case snd_soc_dapm_clock_supply: | ||
2190 | case snd_soc_dapm_aif_in: | 2228 | case snd_soc_dapm_aif_in: |
2191 | case snd_soc_dapm_aif_out: | 2229 | case snd_soc_dapm_aif_out: |
2192 | case snd_soc_dapm_dai: | 2230 | case snd_soc_dapm_dai: |
@@ -2221,6 +2259,10 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
2221 | path->connect = 0; | 2259 | path->connect = 0; |
2222 | return 0; | 2260 | return 0; |
2223 | } | 2261 | } |
2262 | |||
2263 | dapm_mark_dirty(wsource, "Route added"); | ||
2264 | dapm_mark_dirty(wsink, "Route added"); | ||
2265 | |||
2224 | return 0; | 2266 | return 0; |
2225 | 2267 | ||
2226 | err: | 2268 | err: |
@@ -2230,6 +2272,59 @@ err: | |||
2230 | return ret; | 2272 | return ret; |
2231 | } | 2273 | } |
2232 | 2274 | ||
2275 | static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, | ||
2276 | const struct snd_soc_dapm_route *route) | ||
2277 | { | ||
2278 | struct snd_soc_dapm_path *path, *p; | ||
2279 | const char *sink; | ||
2280 | const char *source; | ||
2281 | char prefixed_sink[80]; | ||
2282 | char prefixed_source[80]; | ||
2283 | |||
2284 | if (route->control) { | ||
2285 | dev_err(dapm->dev, | ||
2286 | "Removal of routes with controls not supported\n"); | ||
2287 | return -EINVAL; | ||
2288 | } | ||
2289 | |||
2290 | if (dapm->codec && dapm->codec->name_prefix) { | ||
2291 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", | ||
2292 | dapm->codec->name_prefix, route->sink); | ||
2293 | sink = prefixed_sink; | ||
2294 | snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", | ||
2295 | dapm->codec->name_prefix, route->source); | ||
2296 | source = prefixed_source; | ||
2297 | } else { | ||
2298 | sink = route->sink; | ||
2299 | source = route->source; | ||
2300 | } | ||
2301 | |||
2302 | path = NULL; | ||
2303 | list_for_each_entry(p, &dapm->card->paths, list) { | ||
2304 | if (strcmp(p->source->name, source) != 0) | ||
2305 | continue; | ||
2306 | if (strcmp(p->sink->name, sink) != 0) | ||
2307 | continue; | ||
2308 | path = p; | ||
2309 | break; | ||
2310 | } | ||
2311 | |||
2312 | if (path) { | ||
2313 | dapm_mark_dirty(path->source, "Route removed"); | ||
2314 | dapm_mark_dirty(path->sink, "Route removed"); | ||
2315 | |||
2316 | list_del(&path->list); | ||
2317 | list_del(&path->list_sink); | ||
2318 | list_del(&path->list_source); | ||
2319 | kfree(path); | ||
2320 | } else { | ||
2321 | dev_warn(dapm->dev, "Route %s->%s does not exist\n", | ||
2322 | source, sink); | ||
2323 | } | ||
2324 | |||
2325 | return 0; | ||
2326 | } | ||
2327 | |||
2233 | /** | 2328 | /** |
2234 | * snd_soc_dapm_add_routes - Add routes between DAPM widgets | 2329 | * snd_soc_dapm_add_routes - Add routes between DAPM widgets |
2235 | * @dapm: DAPM context | 2330 | * @dapm: DAPM context |
@@ -2246,15 +2341,15 @@ err: | |||
2246 | int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, | 2341 | int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, |
2247 | const struct snd_soc_dapm_route *route, int num) | 2342 | const struct snd_soc_dapm_route *route, int num) |
2248 | { | 2343 | { |
2249 | int i, ret = 0; | 2344 | int i, r, ret = 0; |
2250 | 2345 | ||
2251 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); | 2346 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); |
2252 | for (i = 0; i < num; i++) { | 2347 | for (i = 0; i < num; i++) { |
2253 | ret = snd_soc_dapm_add_route(dapm, route); | 2348 | r = snd_soc_dapm_add_route(dapm, route); |
2254 | if (ret < 0) { | 2349 | if (r < 0) { |
2255 | dev_err(dapm->dev, "Failed to add route %s->%s\n", | 2350 | dev_err(dapm->dev, "Failed to add route %s->%s\n", |
2256 | route->source, route->sink); | 2351 | route->source, route->sink); |
2257 | break; | 2352 | ret = r; |
2258 | } | 2353 | } |
2259 | route++; | 2354 | route++; |
2260 | } | 2355 | } |
@@ -2264,6 +2359,30 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, | |||
2264 | } | 2359 | } |
2265 | EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); | 2360 | EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); |
2266 | 2361 | ||
2362 | /** | ||
2363 | * snd_soc_dapm_del_routes - Remove routes between DAPM widgets | ||
2364 | * @dapm: DAPM context | ||
2365 | * @route: audio routes | ||
2366 | * @num: number of routes | ||
2367 | * | ||
2368 | * Removes routes from the DAPM context. | ||
2369 | */ | ||
2370 | int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, | ||
2371 | const struct snd_soc_dapm_route *route, int num) | ||
2372 | { | ||
2373 | int i, ret = 0; | ||
2374 | |||
2375 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); | ||
2376 | for (i = 0; i < num; i++) { | ||
2377 | snd_soc_dapm_del_route(dapm, route); | ||
2378 | route++; | ||
2379 | } | ||
2380 | mutex_unlock(&dapm->card->dapm_mutex); | ||
2381 | |||
2382 | return ret; | ||
2383 | } | ||
2384 | EXPORT_SYMBOL_GPL(snd_soc_dapm_del_routes); | ||
2385 | |||
2267 | static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm, | 2386 | static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm, |
2268 | const struct snd_soc_dapm_route *route) | 2387 | const struct snd_soc_dapm_route *route) |
2269 | { | 2388 | { |
@@ -2434,23 +2553,20 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
2434 | (struct soc_mixer_control *)kcontrol->private_value; | 2553 | (struct soc_mixer_control *)kcontrol->private_value; |
2435 | unsigned int reg = mc->reg; | 2554 | unsigned int reg = mc->reg; |
2436 | unsigned int shift = mc->shift; | 2555 | unsigned int shift = mc->shift; |
2437 | unsigned int rshift = mc->rshift; | ||
2438 | int max = mc->max; | 2556 | int max = mc->max; |
2439 | unsigned int invert = mc->invert; | ||
2440 | unsigned int mask = (1 << fls(max)) - 1; | 2557 | unsigned int mask = (1 << fls(max)) - 1; |
2558 | unsigned int invert = mc->invert; | ||
2559 | |||
2560 | if (snd_soc_volsw_is_stereo(mc)) | ||
2561 | dev_warn(widget->dapm->dev, | ||
2562 | "Control '%s' is stereo, which is not supported\n", | ||
2563 | kcontrol->id.name); | ||
2441 | 2564 | ||
2442 | ucontrol->value.integer.value[0] = | 2565 | ucontrol->value.integer.value[0] = |
2443 | (snd_soc_read(widget->codec, reg) >> shift) & mask; | 2566 | (snd_soc_read(widget->codec, reg) >> shift) & mask; |
2444 | if (shift != rshift) | 2567 | if (invert) |
2445 | ucontrol->value.integer.value[1] = | ||
2446 | (snd_soc_read(widget->codec, reg) >> rshift) & mask; | ||
2447 | if (invert) { | ||
2448 | ucontrol->value.integer.value[0] = | 2568 | ucontrol->value.integer.value[0] = |
2449 | max - ucontrol->value.integer.value[0]; | 2569 | max - ucontrol->value.integer.value[0]; |
2450 | if (shift != rshift) | ||
2451 | ucontrol->value.integer.value[1] = | ||
2452 | max - ucontrol->value.integer.value[1]; | ||
2453 | } | ||
2454 | 2570 | ||
2455 | return 0; | 2571 | return 0; |
2456 | } | 2572 | } |
@@ -2484,20 +2600,19 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
2484 | struct snd_soc_dapm_update update; | 2600 | struct snd_soc_dapm_update update; |
2485 | int wi; | 2601 | int wi; |
2486 | 2602 | ||
2603 | if (snd_soc_volsw_is_stereo(mc)) | ||
2604 | dev_warn(widget->dapm->dev, | ||
2605 | "Control '%s' is stereo, which is not supported\n", | ||
2606 | kcontrol->id.name); | ||
2607 | |||
2487 | val = (ucontrol->value.integer.value[0] & mask); | 2608 | val = (ucontrol->value.integer.value[0] & mask); |
2609 | connect = !!val; | ||
2488 | 2610 | ||
2489 | if (invert) | 2611 | if (invert) |
2490 | val = max - val; | 2612 | val = max - val; |
2491 | mask = mask << shift; | 2613 | mask = mask << shift; |
2492 | val = val << shift; | 2614 | val = val << shift; |
2493 | 2615 | ||
2494 | if (val) | ||
2495 | /* new connection */ | ||
2496 | connect = invert ? 0 : 1; | ||
2497 | else | ||
2498 | /* old connection must be powered down */ | ||
2499 | connect = invert ? 1 : 0; | ||
2500 | |||
2501 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2616 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
2502 | 2617 | ||
2503 | change = snd_soc_test_bits(widget->codec, reg, mask, val); | 2618 | change = snd_soc_test_bits(widget->codec, reg, mask, val); |
@@ -2873,6 +2988,19 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
2873 | return NULL; | 2988 | return NULL; |
2874 | } | 2989 | } |
2875 | break; | 2990 | break; |
2991 | case snd_soc_dapm_clock_supply: | ||
2992 | #ifdef CONFIG_CLKDEV_LOOKUP | ||
2993 | w->clk = devm_clk_get(dapm->dev, w->name); | ||
2994 | if (IS_ERR(w->clk)) { | ||
2995 | ret = PTR_ERR(w->clk); | ||
2996 | dev_err(dapm->dev, "Failed to request %s: %d\n", | ||
2997 | w->name, ret); | ||
2998 | return NULL; | ||
2999 | } | ||
3000 | #else | ||
3001 | return NULL; | ||
3002 | #endif | ||
3003 | break; | ||
2876 | default: | 3004 | default: |
2877 | break; | 3005 | break; |
2878 | } | 3006 | } |
@@ -2924,6 +3052,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
2924 | break; | 3052 | break; |
2925 | case snd_soc_dapm_supply: | 3053 | case snd_soc_dapm_supply: |
2926 | case snd_soc_dapm_regulator_supply: | 3054 | case snd_soc_dapm_regulator_supply: |
3055 | case snd_soc_dapm_clock_supply: | ||
2927 | w->power_check = dapm_supply_check_power; | 3056 | w->power_check = dapm_supply_check_power; |
2928 | break; | 3057 | break; |
2929 | case snd_soc_dapm_dai: | 3058 | case snd_soc_dapm_dai: |
@@ -3538,10 +3667,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_free); | |||
3538 | 3667 | ||
3539 | static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) | 3668 | static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) |
3540 | { | 3669 | { |
3670 | struct snd_soc_card *card = dapm->card; | ||
3541 | struct snd_soc_dapm_widget *w; | 3671 | struct snd_soc_dapm_widget *w; |
3542 | LIST_HEAD(down_list); | 3672 | LIST_HEAD(down_list); |
3543 | int powerdown = 0; | 3673 | int powerdown = 0; |
3544 | 3674 | ||
3675 | mutex_lock(&card->dapm_mutex); | ||
3676 | |||
3545 | list_for_each_entry(w, &dapm->card->widgets, list) { | 3677 | list_for_each_entry(w, &dapm->card->widgets, list) { |
3546 | if (w->dapm != dapm) | 3678 | if (w->dapm != dapm) |
3547 | continue; | 3679 | continue; |
@@ -3564,6 +3696,8 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) | |||
3564 | snd_soc_dapm_set_bias_level(dapm, | 3696 | snd_soc_dapm_set_bias_level(dapm, |
3565 | SND_SOC_BIAS_STANDBY); | 3697 | SND_SOC_BIAS_STANDBY); |
3566 | } | 3698 | } |
3699 | |||
3700 | mutex_unlock(&card->dapm_mutex); | ||
3567 | } | 3701 | } |
3568 | 3702 | ||
3569 | /* | 3703 | /* |
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c index 475695234b3d..5df529eda251 100644 --- a/sound/soc/soc-dmaengine-pcm.c +++ b/sound/soc/soc-dmaengine-pcm.c | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | struct dmaengine_pcm_runtime_data { | 31 | struct dmaengine_pcm_runtime_data { |
32 | struct dma_chan *dma_chan; | 32 | struct dma_chan *dma_chan; |
33 | dma_cookie_t cookie; | ||
33 | 34 | ||
34 | unsigned int pos; | 35 | unsigned int pos; |
35 | 36 | ||
@@ -153,7 +154,7 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) | |||
153 | 154 | ||
154 | desc->callback = dmaengine_pcm_dma_complete; | 155 | desc->callback = dmaengine_pcm_dma_complete; |
155 | desc->callback_param = substream; | 156 | desc->callback_param = substream; |
156 | dmaengine_submit(desc); | 157 | prtd->cookie = dmaengine_submit(desc); |
157 | 158 | ||
158 | return 0; | 159 | return 0; |
159 | } | 160 | } |
@@ -200,6 +201,20 @@ int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
200 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); | 201 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); |
201 | 202 | ||
202 | /** | 203 | /** |
204 | * snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation | ||
205 | * @substream: PCM substream | ||
206 | * | ||
207 | * This function is deprecated and should not be used by new drivers, as its | ||
208 | * results may be unreliable. | ||
209 | */ | ||
210 | snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream) | ||
211 | { | ||
212 | struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); | ||
213 | return bytes_to_frames(substream->runtime, prtd->pos); | ||
214 | } | ||
215 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); | ||
216 | |||
217 | /** | ||
203 | * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation | 218 | * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation |
204 | * @substream: PCM substream | 219 | * @substream: PCM substream |
205 | * | 220 | * |
@@ -209,7 +224,19 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); | |||
209 | snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) | 224 | snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) |
210 | { | 225 | { |
211 | struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); | 226 | struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); |
212 | return bytes_to_frames(substream->runtime, prtd->pos); | 227 | struct dma_tx_state state; |
228 | enum dma_status status; | ||
229 | unsigned int buf_size; | ||
230 | unsigned int pos = 0; | ||
231 | |||
232 | status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); | ||
233 | if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { | ||
234 | buf_size = snd_pcm_lib_buffer_bytes(substream); | ||
235 | if (state.residue > 0 && state.residue <= buf_size) | ||
236 | pos = buf_size - state.residue; | ||
237 | } | ||
238 | |||
239 | return bytes_to_frames(substream->runtime, pos); | ||
213 | } | 240 | } |
214 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); | 241 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); |
215 | 242 | ||
@@ -243,7 +270,7 @@ static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd | |||
243 | * Note that this function will use private_data field of the substream's | 270 | * Note that this function will use private_data field of the substream's |
244 | * runtime. So it is not availabe to your pcm driver implementation. If you need | 271 | * runtime. So it is not availabe to your pcm driver implementation. If you need |
245 | * to keep additional data attached to a substream use | 272 | * to keep additional data attached to a substream use |
246 | * snd_dmaeinge_pcm_{set,get}_data. | 273 | * snd_dmaengine_pcm_{set,get}_data. |
247 | */ | 274 | */ |
248 | int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, | 275 | int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, |
249 | dma_filter_fn filter_fn, void *filter_data) | 276 | dma_filter_fn filter_fn, void *filter_data) |
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index 4d8dc6a27d4d..29183ef2b93d 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c | |||
@@ -142,11 +142,16 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | |||
142 | case SND_SOC_REGMAP: | 142 | case SND_SOC_REGMAP: |
143 | /* Device has made its own regmap arrangements */ | 143 | /* Device has made its own regmap arrangements */ |
144 | codec->using_regmap = true; | 144 | codec->using_regmap = true; |
145 | 145 | if (!codec->control_data) | |
146 | ret = regmap_get_val_bytes(codec->control_data); | 146 | codec->control_data = dev_get_regmap(codec->dev, NULL); |
147 | /* Errors are legitimate for non-integer byte multiples */ | 147 | |
148 | if (ret > 0) | 148 | if (codec->control_data) { |
149 | codec->val_bytes = ret; | 149 | ret = regmap_get_val_bytes(codec->control_data); |
150 | /* Errors are legitimate for non-integer byte | ||
151 | * multiples */ | ||
152 | if (ret > 0) | ||
153 | codec->val_bytes = ret; | ||
154 | } | ||
150 | break; | 155 | break; |
151 | 156 | ||
152 | default: | 157 | default: |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 48fd15b312c1..ef22d0bd9e9e 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -1955,10 +1955,8 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) | |||
1955 | fe->dpcm[stream].runtime = fe_substream->runtime; | 1955 | fe->dpcm[stream].runtime = fe_substream->runtime; |
1956 | 1956 | ||
1957 | if (dpcm_path_get(fe, stream, &list) <= 0) { | 1957 | if (dpcm_path_get(fe, stream, &list) <= 0) { |
1958 | dev_warn(fe->dev, "asoc: %s no valid %s route\n", | 1958 | dev_dbg(fe->dev, "asoc: %s no valid %s route\n", |
1959 | fe->dai_link->name, stream ? "capture" : "playback"); | 1959 | fe->dai_link->name, stream ? "capture" : "playback"); |
1960 | mutex_unlock(&fe->card->mutex); | ||
1961 | return -EINVAL; | ||
1962 | } | 1960 | } |
1963 | 1961 | ||
1964 | /* calculate valid and active FE <-> BE dpcms */ | 1962 | /* calculate valid and active FE <-> BE dpcms */ |
@@ -2003,7 +2001,6 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) | |||
2003 | /* create a new pcm */ | 2001 | /* create a new pcm */ |
2004 | int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | 2002 | int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) |
2005 | { | 2003 | { |
2006 | struct snd_soc_codec *codec = rtd->codec; | ||
2007 | struct snd_soc_platform *platform = rtd->platform; | 2004 | struct snd_soc_platform *platform = rtd->platform; |
2008 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 2005 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
2009 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 2006 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
@@ -2042,7 +2039,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2042 | capture, &pcm); | 2039 | capture, &pcm); |
2043 | } | 2040 | } |
2044 | if (ret < 0) { | 2041 | if (ret < 0) { |
2045 | printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name); | 2042 | dev_err(rtd->card->dev, "can't create pcm for %s\n", |
2043 | rtd->dai_link->name); | ||
2046 | return ret; | 2044 | return ret; |
2047 | } | 2045 | } |
2048 | dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name); | 2046 | dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name); |
@@ -2099,14 +2097,14 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2099 | if (platform->driver->pcm_new) { | 2097 | if (platform->driver->pcm_new) { |
2100 | ret = platform->driver->pcm_new(rtd); | 2098 | ret = platform->driver->pcm_new(rtd); |
2101 | if (ret < 0) { | 2099 | if (ret < 0) { |
2102 | pr_err("asoc: platform pcm constructor failed\n"); | 2100 | dev_err(platform->dev, "pcm constructor failed\n"); |
2103 | return ret; | 2101 | return ret; |
2104 | } | 2102 | } |
2105 | } | 2103 | } |
2106 | 2104 | ||
2107 | pcm->private_free = platform->driver->pcm_free; | 2105 | pcm->private_free = platform->driver->pcm_free; |
2108 | out: | 2106 | out: |
2109 | printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, | 2107 | dev_info(rtd->card->dev, " %s <-> %s mapping ok\n", codec_dai->name, |
2110 | cpu_dai->name); | 2108 | cpu_dai->name); |
2111 | return ret; | 2109 | return ret; |
2112 | } | 2110 | } |
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c new file mode 100644 index 000000000000..c7c4b20395bb --- /dev/null +++ b/sound/soc/spear/spdif_in.c | |||
@@ -0,0 +1,297 @@ | |||
1 | /* | ||
2 | * ALSA SoC SPDIF In Audio Layer for spear processors | ||
3 | * | ||
4 | * Copyright (C) 2012 ST Microelectronics | ||
5 | * Vipin Kumar <vipin.kumar@st.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/ioport.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <sound/pcm.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | #include <sound/soc.h> | ||
24 | #include <sound/spear_dma.h> | ||
25 | #include <sound/spear_spdif.h> | ||
26 | #include "spdif_in_regs.h" | ||
27 | |||
28 | struct spdif_in_params { | ||
29 | u32 format; | ||
30 | }; | ||
31 | |||
32 | struct spdif_in_dev { | ||
33 | struct clk *clk; | ||
34 | struct spear_dma_data dma_params; | ||
35 | struct spdif_in_params saved_params; | ||
36 | void *io_base; | ||
37 | struct device *dev; | ||
38 | void (*reset_perip)(void); | ||
39 | int irq; | ||
40 | }; | ||
41 | |||
42 | static void spdif_in_configure(struct spdif_in_dev *host) | ||
43 | { | ||
44 | u32 ctrl = SPDIF_IN_PRTYEN | SPDIF_IN_STATEN | SPDIF_IN_USREN | | ||
45 | SPDIF_IN_VALEN | SPDIF_IN_BLKEN; | ||
46 | ctrl |= SPDIF_MODE_16BIT | SPDIF_FIFO_THRES_16; | ||
47 | |||
48 | writel(ctrl, host->io_base + SPDIF_IN_CTRL); | ||
49 | writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK); | ||
50 | } | ||
51 | |||
52 | static int spdif_in_startup(struct snd_pcm_substream *substream, | ||
53 | struct snd_soc_dai *cpu_dai) | ||
54 | { | ||
55 | struct spdif_in_dev *host = snd_soc_dai_get_drvdata(cpu_dai); | ||
56 | |||
57 | if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) | ||
58 | return -EINVAL; | ||
59 | |||
60 | snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params); | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static void spdif_in_shutdown(struct snd_pcm_substream *substream, | ||
65 | struct snd_soc_dai *dai) | ||
66 | { | ||
67 | struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai); | ||
68 | |||
69 | if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) | ||
70 | return; | ||
71 | |||
72 | writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK); | ||
73 | snd_soc_dai_set_dma_data(dai, substream, NULL); | ||
74 | } | ||
75 | |||
76 | static void spdif_in_format(struct spdif_in_dev *host, u32 format) | ||
77 | { | ||
78 | u32 ctrl = readl(host->io_base + SPDIF_IN_CTRL); | ||
79 | |||
80 | switch (format) { | ||
81 | case SNDRV_PCM_FORMAT_S16_LE: | ||
82 | ctrl |= SPDIF_XTRACT_16BIT; | ||
83 | break; | ||
84 | |||
85 | case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: | ||
86 | ctrl &= ~SPDIF_XTRACT_16BIT; | ||
87 | break; | ||
88 | } | ||
89 | |||
90 | writel(ctrl, host->io_base + SPDIF_IN_CTRL); | ||
91 | } | ||
92 | |||
93 | static int spdif_in_hw_params(struct snd_pcm_substream *substream, | ||
94 | struct snd_pcm_hw_params *params, | ||
95 | struct snd_soc_dai *dai) | ||
96 | { | ||
97 | struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai); | ||
98 | u32 format; | ||
99 | |||
100 | if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) | ||
101 | return -EINVAL; | ||
102 | |||
103 | format = params_format(params); | ||
104 | host->saved_params.format = format; | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int spdif_in_trigger(struct snd_pcm_substream *substream, int cmd, | ||
110 | struct snd_soc_dai *dai) | ||
111 | { | ||
112 | struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai); | ||
113 | u32 ctrl; | ||
114 | int ret = 0; | ||
115 | |||
116 | if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) | ||
117 | return -EINVAL; | ||
118 | |||
119 | switch (cmd) { | ||
120 | case SNDRV_PCM_TRIGGER_START: | ||
121 | case SNDRV_PCM_TRIGGER_RESUME: | ||
122 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
123 | clk_enable(host->clk); | ||
124 | spdif_in_configure(host); | ||
125 | spdif_in_format(host, host->saved_params.format); | ||
126 | |||
127 | ctrl = readl(host->io_base + SPDIF_IN_CTRL); | ||
128 | ctrl |= SPDIF_IN_SAMPLE | SPDIF_IN_ENB; | ||
129 | writel(ctrl, host->io_base + SPDIF_IN_CTRL); | ||
130 | writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK); | ||
131 | break; | ||
132 | |||
133 | case SNDRV_PCM_TRIGGER_STOP: | ||
134 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
135 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
136 | ctrl = readl(host->io_base + SPDIF_IN_CTRL); | ||
137 | ctrl &= ~(SPDIF_IN_SAMPLE | SPDIF_IN_ENB); | ||
138 | writel(ctrl, host->io_base + SPDIF_IN_CTRL); | ||
139 | writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK); | ||
140 | |||
141 | if (host->reset_perip) | ||
142 | host->reset_perip(); | ||
143 | clk_disable(host->clk); | ||
144 | break; | ||
145 | |||
146 | default: | ||
147 | ret = -EINVAL; | ||
148 | break; | ||
149 | } | ||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | static struct snd_soc_dai_ops spdif_in_dai_ops = { | ||
154 | .startup = spdif_in_startup, | ||
155 | .shutdown = spdif_in_shutdown, | ||
156 | .trigger = spdif_in_trigger, | ||
157 | .hw_params = spdif_in_hw_params, | ||
158 | }; | ||
159 | |||
160 | struct snd_soc_dai_driver spdif_in_dai = { | ||
161 | .capture = { | ||
162 | .channels_min = 2, | ||
163 | .channels_max = 2, | ||
164 | .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
165 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \ | ||
166 | SNDRV_PCM_RATE_192000), | ||
167 | .formats = SNDRV_PCM_FMTBIT_S16_LE | \ | ||
168 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE, | ||
169 | }, | ||
170 | .ops = &spdif_in_dai_ops, | ||
171 | }; | ||
172 | |||
173 | static irqreturn_t spdif_in_irq(int irq, void *arg) | ||
174 | { | ||
175 | struct spdif_in_dev *host = (struct spdif_in_dev *)arg; | ||
176 | |||
177 | u32 irq_status = readl(host->io_base + SPDIF_IN_IRQ); | ||
178 | |||
179 | if (!irq_status) | ||
180 | return IRQ_NONE; | ||
181 | |||
182 | if (irq_status & SPDIF_IRQ_FIFOWRITE) | ||
183 | dev_err(host->dev, "spdif in: fifo write error"); | ||
184 | if (irq_status & SPDIF_IRQ_EMPTYFIFOREAD) | ||
185 | dev_err(host->dev, "spdif in: empty fifo read error"); | ||
186 | if (irq_status & SPDIF_IRQ_FIFOFULL) | ||
187 | dev_err(host->dev, "spdif in: fifo full error"); | ||
188 | if (irq_status & SPDIF_IRQ_OUTOFRANGE) | ||
189 | dev_err(host->dev, "spdif in: out of range error"); | ||
190 | |||
191 | writel(0, host->io_base + SPDIF_IN_IRQ); | ||
192 | |||
193 | return IRQ_HANDLED; | ||
194 | } | ||
195 | |||
196 | static int spdif_in_probe(struct platform_device *pdev) | ||
197 | { | ||
198 | struct spdif_in_dev *host; | ||
199 | struct spear_spdif_platform_data *pdata; | ||
200 | struct resource *res, *res_fifo; | ||
201 | int ret; | ||
202 | |||
203 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
204 | if (!res) | ||
205 | return -EINVAL; | ||
206 | |||
207 | res_fifo = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
208 | if (!res_fifo) | ||
209 | return -EINVAL; | ||
210 | |||
211 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
212 | resource_size(res), pdev->name)) { | ||
213 | dev_warn(&pdev->dev, "Failed to get memory resourse\n"); | ||
214 | return -ENOENT; | ||
215 | } | ||
216 | |||
217 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); | ||
218 | if (!host) { | ||
219 | dev_warn(&pdev->dev, "kzalloc fail\n"); | ||
220 | return -ENOMEM; | ||
221 | } | ||
222 | |||
223 | host->io_base = devm_ioremap(&pdev->dev, res->start, | ||
224 | resource_size(res)); | ||
225 | if (!host->io_base) { | ||
226 | dev_warn(&pdev->dev, "ioremap failed\n"); | ||
227 | return -ENOMEM; | ||
228 | } | ||
229 | |||
230 | host->irq = platform_get_irq(pdev, 0); | ||
231 | if (host->irq < 0) | ||
232 | return -EINVAL; | ||
233 | |||
234 | host->clk = clk_get(&pdev->dev, NULL); | ||
235 | if (IS_ERR(host->clk)) | ||
236 | return PTR_ERR(host->clk); | ||
237 | |||
238 | pdata = dev_get_platdata(&pdev->dev); | ||
239 | |||
240 | if (!pdata) | ||
241 | return -EINVAL; | ||
242 | |||
243 | host->dma_params.data = pdata->dma_params; | ||
244 | host->dma_params.addr = res_fifo->start; | ||
245 | host->dma_params.max_burst = 16; | ||
246 | host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
247 | host->dma_params.filter = pdata->filter; | ||
248 | host->reset_perip = pdata->reset_perip; | ||
249 | |||
250 | host->dev = &pdev->dev; | ||
251 | dev_set_drvdata(&pdev->dev, host); | ||
252 | |||
253 | ret = devm_request_irq(&pdev->dev, host->irq, spdif_in_irq, 0, | ||
254 | "spdif-in", host); | ||
255 | if (ret) { | ||
256 | clk_put(host->clk); | ||
257 | dev_warn(&pdev->dev, "request_irq failed\n"); | ||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | ret = snd_soc_register_dai(&pdev->dev, &spdif_in_dai); | ||
262 | if (ret != 0) { | ||
263 | clk_put(host->clk); | ||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int spdif_in_remove(struct platform_device *pdev) | ||
271 | { | ||
272 | struct spdif_in_dev *host = dev_get_drvdata(&pdev->dev); | ||
273 | |||
274 | snd_soc_unregister_dai(&pdev->dev); | ||
275 | dev_set_drvdata(&pdev->dev, NULL); | ||
276 | |||
277 | clk_put(host->clk); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | |||
283 | static struct platform_driver spdif_in_driver = { | ||
284 | .probe = spdif_in_probe, | ||
285 | .remove = spdif_in_remove, | ||
286 | .driver = { | ||
287 | .name = "spdif-in", | ||
288 | .owner = THIS_MODULE, | ||
289 | }, | ||
290 | }; | ||
291 | |||
292 | module_platform_driver(spdif_in_driver); | ||
293 | |||
294 | MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>"); | ||
295 | MODULE_DESCRIPTION("SPEAr SPDIF IN SoC Interface"); | ||
296 | MODULE_LICENSE("GPL"); | ||
297 | MODULE_ALIAS("platform:spdif_in"); | ||
diff --git a/sound/soc/spear/spdif_in_regs.h b/sound/soc/spear/spdif_in_regs.h new file mode 100644 index 000000000000..37af7bc66b7f --- /dev/null +++ b/sound/soc/spear/spdif_in_regs.h | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * SPEAr SPDIF IN controller header file | ||
3 | * | ||
4 | * Copyright (ST) 2011 Vipin Kumar (vipin.kumar@st.com) | ||
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 | #ifndef SPDIF_IN_REGS_H | ||
22 | #define SPDIF_IN_REGS_H | ||
23 | |||
24 | #define SPDIF_IN_CTRL 0x00 | ||
25 | #define SPDIF_IN_PRTYEN (1 << 20) | ||
26 | #define SPDIF_IN_STATEN (1 << 19) | ||
27 | #define SPDIF_IN_USREN (1 << 18) | ||
28 | #define SPDIF_IN_VALEN (1 << 17) | ||
29 | #define SPDIF_IN_BLKEN (1 << 16) | ||
30 | |||
31 | #define SPDIF_MODE_24BIT (8 << 12) | ||
32 | #define SPDIF_MODE_23BIT (7 << 12) | ||
33 | #define SPDIF_MODE_22BIT (6 << 12) | ||
34 | #define SPDIF_MODE_21BIT (5 << 12) | ||
35 | #define SPDIF_MODE_20BIT (4 << 12) | ||
36 | #define SPDIF_MODE_19BIT (3 << 12) | ||
37 | #define SPDIF_MODE_18BIT (2 << 12) | ||
38 | #define SPDIF_MODE_17BIT (1 << 12) | ||
39 | #define SPDIF_MODE_16BIT (0 << 12) | ||
40 | #define SPDIF_MODE_MASK (0x0F << 12) | ||
41 | |||
42 | #define SPDIF_IN_VALID (1 << 11) | ||
43 | #define SPDIF_IN_SAMPLE (1 << 10) | ||
44 | #define SPDIF_DATA_SWAP (1 << 9) | ||
45 | #define SPDIF_IN_ENB (1 << 8) | ||
46 | #define SPDIF_DATA_REVERT (1 << 7) | ||
47 | #define SPDIF_XTRACT_16BIT (1 << 6) | ||
48 | #define SPDIF_FIFO_THRES_16 (16 << 0) | ||
49 | |||
50 | #define SPDIF_IN_IRQ_MASK 0x04 | ||
51 | #define SPDIF_IN_IRQ 0x08 | ||
52 | #define SPDIF_IRQ_FIFOWRITE (1 << 0) | ||
53 | #define SPDIF_IRQ_EMPTYFIFOREAD (1 << 1) | ||
54 | #define SPDIF_IRQ_FIFOFULL (1 << 2) | ||
55 | #define SPDIF_IRQ_OUTOFRANGE (1 << 3) | ||
56 | |||
57 | #define SPDIF_IN_STA 0x0C | ||
58 | #define SPDIF_IN_LOCK (0x1 << 0) | ||
59 | |||
60 | #endif /* SPDIF_IN_REGS_H */ | ||
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c new file mode 100644 index 000000000000..5eac4cda2fd7 --- /dev/null +++ b/sound/soc/spear/spdif_out.c | |||
@@ -0,0 +1,389 @@ | |||
1 | /* | ||
2 | * ALSA SoC SPDIF Out Audio Layer for spear processors | ||
3 | * | ||
4 | * Copyright (C) 2012 ST Microelectronics | ||
5 | * Vipin Kumar <vipin.kumar@st.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/ioport.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/spear_dma.h> | ||
23 | #include <sound/spear_spdif.h> | ||
24 | #include "spdif_out_regs.h" | ||
25 | |||
26 | struct spdif_out_params { | ||
27 | u32 rate; | ||
28 | u32 core_freq; | ||
29 | u32 mute; | ||
30 | }; | ||
31 | |||
32 | struct spdif_out_dev { | ||
33 | struct clk *clk; | ||
34 | struct spear_dma_data dma_params; | ||
35 | struct spdif_out_params saved_params; | ||
36 | u32 running; | ||
37 | void __iomem *io_base; | ||
38 | }; | ||
39 | |||
40 | static void spdif_out_configure(struct spdif_out_dev *host) | ||
41 | { | ||
42 | writel(SPDIF_OUT_RESET, host->io_base + SPDIF_OUT_SOFT_RST); | ||
43 | mdelay(1); | ||
44 | writel(readl(host->io_base + SPDIF_OUT_SOFT_RST) & ~SPDIF_OUT_RESET, | ||
45 | host->io_base + SPDIF_OUT_SOFT_RST); | ||
46 | |||
47 | writel(SPDIF_OUT_FDMA_TRIG_16 | SPDIF_OUT_MEMFMT_16_16 | | ||
48 | SPDIF_OUT_VALID_HW | SPDIF_OUT_USER_HW | | ||
49 | SPDIF_OUT_CHNLSTA_HW | SPDIF_OUT_PARITY_HW, | ||
50 | host->io_base + SPDIF_OUT_CFG); | ||
51 | |||
52 | writel(0x7F, host->io_base + SPDIF_OUT_INT_STA_CLR); | ||
53 | writel(0x7F, host->io_base + SPDIF_OUT_INT_EN_CLR); | ||
54 | } | ||
55 | |||
56 | static int spdif_out_startup(struct snd_pcm_substream *substream, | ||
57 | struct snd_soc_dai *cpu_dai) | ||
58 | { | ||
59 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); | ||
60 | int ret; | ||
61 | |||
62 | if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
63 | return -EINVAL; | ||
64 | |||
65 | snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params); | ||
66 | |||
67 | ret = clk_enable(host->clk); | ||
68 | if (ret) | ||
69 | return ret; | ||
70 | |||
71 | host->running = true; | ||
72 | spdif_out_configure(host); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static void spdif_out_shutdown(struct snd_pcm_substream *substream, | ||
78 | struct snd_soc_dai *dai) | ||
79 | { | ||
80 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai); | ||
81 | |||
82 | if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
83 | return; | ||
84 | |||
85 | clk_disable(host->clk); | ||
86 | host->running = false; | ||
87 | snd_soc_dai_set_dma_data(dai, substream, NULL); | ||
88 | } | ||
89 | |||
90 | static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq, | ||
91 | u32 rate) | ||
92 | { | ||
93 | u32 divider, ctrl; | ||
94 | |||
95 | clk_set_rate(host->clk, core_freq); | ||
96 | divider = DIV_ROUND_CLOSEST(clk_get_rate(host->clk), (rate * 128)); | ||
97 | |||
98 | ctrl = readl(host->io_base + SPDIF_OUT_CTRL); | ||
99 | ctrl &= ~SPDIF_DIVIDER_MASK; | ||
100 | ctrl |= (divider << SPDIF_DIVIDER_SHIFT) & SPDIF_DIVIDER_MASK; | ||
101 | writel(ctrl, host->io_base + SPDIF_OUT_CTRL); | ||
102 | } | ||
103 | |||
104 | static int spdif_out_hw_params(struct snd_pcm_substream *substream, | ||
105 | struct snd_pcm_hw_params *params, | ||
106 | struct snd_soc_dai *dai) | ||
107 | { | ||
108 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai); | ||
109 | u32 rate, core_freq; | ||
110 | |||
111 | if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
112 | return -EINVAL; | ||
113 | |||
114 | rate = params_rate(params); | ||
115 | |||
116 | switch (rate) { | ||
117 | case 8000: | ||
118 | case 16000: | ||
119 | case 32000: | ||
120 | case 64000: | ||
121 | /* | ||
122 | * The clock is multiplied by 10 to bring it to feasible range | ||
123 | * of frequencies for sscg | ||
124 | */ | ||
125 | core_freq = 64000 * 128 * 10; /* 81.92 MHz */ | ||
126 | break; | ||
127 | case 5512: | ||
128 | case 11025: | ||
129 | case 22050: | ||
130 | case 44100: | ||
131 | case 88200: | ||
132 | case 176400: | ||
133 | core_freq = 176400 * 128; /* 22.5792 MHz */ | ||
134 | break; | ||
135 | case 48000: | ||
136 | case 96000: | ||
137 | case 192000: | ||
138 | default: | ||
139 | core_freq = 192000 * 128; /* 24.576 MHz */ | ||
140 | break; | ||
141 | } | ||
142 | |||
143 | spdif_out_clock(host, core_freq, rate); | ||
144 | host->saved_params.core_freq = core_freq; | ||
145 | host->saved_params.rate = rate; | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static int spdif_out_trigger(struct snd_pcm_substream *substream, int cmd, | ||
151 | struct snd_soc_dai *dai) | ||
152 | { | ||
153 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai); | ||
154 | u32 ctrl; | ||
155 | int ret = 0; | ||
156 | |||
157 | if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
158 | return -EINVAL; | ||
159 | |||
160 | switch (cmd) { | ||
161 | case SNDRV_PCM_TRIGGER_START: | ||
162 | case SNDRV_PCM_TRIGGER_RESUME: | ||
163 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
164 | ctrl = readl(host->io_base + SPDIF_OUT_CTRL); | ||
165 | ctrl &= ~SPDIF_OPMODE_MASK; | ||
166 | if (!host->saved_params.mute) | ||
167 | ctrl |= SPDIF_OPMODE_AUD_DATA | | ||
168 | SPDIF_STATE_NORMAL; | ||
169 | else | ||
170 | ctrl |= SPDIF_OPMODE_MUTE_PCM; | ||
171 | writel(ctrl, host->io_base + SPDIF_OUT_CTRL); | ||
172 | break; | ||
173 | |||
174 | case SNDRV_PCM_TRIGGER_STOP: | ||
175 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
176 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
177 | ctrl = readl(host->io_base + SPDIF_OUT_CTRL); | ||
178 | ctrl &= ~SPDIF_OPMODE_MASK; | ||
179 | ctrl |= SPDIF_OPMODE_OFF; | ||
180 | writel(ctrl, host->io_base + SPDIF_OUT_CTRL); | ||
181 | break; | ||
182 | |||
183 | default: | ||
184 | ret = -EINVAL; | ||
185 | break; | ||
186 | } | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | static int spdif_digital_mute(struct snd_soc_dai *dai, int mute) | ||
191 | { | ||
192 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai); | ||
193 | u32 val; | ||
194 | |||
195 | host->saved_params.mute = mute; | ||
196 | val = readl(host->io_base + SPDIF_OUT_CTRL); | ||
197 | val &= ~SPDIF_OPMODE_MASK; | ||
198 | |||
199 | if (mute) | ||
200 | val |= SPDIF_OPMODE_MUTE_PCM; | ||
201 | else { | ||
202 | if (host->running) | ||
203 | val |= SPDIF_OPMODE_AUD_DATA | SPDIF_STATE_NORMAL; | ||
204 | else | ||
205 | val |= SPDIF_OPMODE_OFF; | ||
206 | } | ||
207 | |||
208 | writel(val, host->io_base + SPDIF_OUT_CTRL); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int spdif_mute_get(struct snd_kcontrol *kcontrol, | ||
213 | struct snd_ctl_elem_value *ucontrol) | ||
214 | { | ||
215 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
216 | struct snd_soc_card *card = codec->card; | ||
217 | struct snd_soc_pcm_runtime *rtd = card->rtd; | ||
218 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
219 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); | ||
220 | |||
221 | ucontrol->value.integer.value[0] = host->saved_params.mute; | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static int spdif_mute_put(struct snd_kcontrol *kcontrol, | ||
226 | struct snd_ctl_elem_value *ucontrol) | ||
227 | { | ||
228 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
229 | struct snd_soc_card *card = codec->card; | ||
230 | struct snd_soc_pcm_runtime *rtd = card->rtd; | ||
231 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
232 | struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); | ||
233 | |||
234 | if (host->saved_params.mute == ucontrol->value.integer.value[0]) | ||
235 | return 0; | ||
236 | |||
237 | spdif_digital_mute(cpu_dai, ucontrol->value.integer.value[0]); | ||
238 | |||
239 | return 1; | ||
240 | } | ||
241 | static const struct snd_kcontrol_new spdif_out_controls[] = { | ||
242 | SOC_SINGLE_BOOL_EXT("IEC958 Playback Switch", 0, | ||
243 | spdif_mute_get, spdif_mute_put), | ||
244 | }; | ||
245 | |||
246 | int spdif_soc_dai_probe(struct snd_soc_dai *dai) | ||
247 | { | ||
248 | return snd_soc_add_dai_controls(dai, spdif_out_controls, | ||
249 | ARRAY_SIZE(spdif_out_controls)); | ||
250 | } | ||
251 | |||
252 | static const struct snd_soc_dai_ops spdif_out_dai_ops = { | ||
253 | .digital_mute = spdif_digital_mute, | ||
254 | .startup = spdif_out_startup, | ||
255 | .shutdown = spdif_out_shutdown, | ||
256 | .trigger = spdif_out_trigger, | ||
257 | .hw_params = spdif_out_hw_params, | ||
258 | }; | ||
259 | |||
260 | static struct snd_soc_dai_driver spdif_out_dai = { | ||
261 | .playback = { | ||
262 | .channels_min = 2, | ||
263 | .channels_max = 2, | ||
264 | .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
265 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \ | ||
266 | SNDRV_PCM_RATE_192000), | ||
267 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
268 | }, | ||
269 | .probe = spdif_soc_dai_probe, | ||
270 | .ops = &spdif_out_dai_ops, | ||
271 | }; | ||
272 | |||
273 | static int spdif_out_probe(struct platform_device *pdev) | ||
274 | { | ||
275 | struct spdif_out_dev *host; | ||
276 | struct spear_spdif_platform_data *pdata; | ||
277 | struct resource *res; | ||
278 | int ret; | ||
279 | |||
280 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
281 | if (!res) | ||
282 | return -EINVAL; | ||
283 | |||
284 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
285 | resource_size(res), pdev->name)) { | ||
286 | dev_warn(&pdev->dev, "Failed to get memory resourse\n"); | ||
287 | return -ENOENT; | ||
288 | } | ||
289 | |||
290 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); | ||
291 | if (!host) { | ||
292 | dev_warn(&pdev->dev, "kzalloc fail\n"); | ||
293 | return -ENOMEM; | ||
294 | } | ||
295 | |||
296 | host->io_base = devm_ioremap(&pdev->dev, res->start, | ||
297 | resource_size(res)); | ||
298 | if (!host->io_base) { | ||
299 | dev_warn(&pdev->dev, "ioremap failed\n"); | ||
300 | return -ENOMEM; | ||
301 | } | ||
302 | |||
303 | host->clk = clk_get(&pdev->dev, NULL); | ||
304 | if (IS_ERR(host->clk)) | ||
305 | return PTR_ERR(host->clk); | ||
306 | |||
307 | pdata = dev_get_platdata(&pdev->dev); | ||
308 | |||
309 | host->dma_params.data = pdata->dma_params; | ||
310 | host->dma_params.addr = res->start + SPDIF_OUT_FIFO_DATA; | ||
311 | host->dma_params.max_burst = 16; | ||
312 | host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
313 | host->dma_params.filter = pdata->filter; | ||
314 | |||
315 | dev_set_drvdata(&pdev->dev, host); | ||
316 | |||
317 | ret = snd_soc_register_dai(&pdev->dev, &spdif_out_dai); | ||
318 | if (ret != 0) { | ||
319 | clk_put(host->clk); | ||
320 | return ret; | ||
321 | } | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static int spdif_out_remove(struct platform_device *pdev) | ||
327 | { | ||
328 | struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev); | ||
329 | |||
330 | snd_soc_unregister_dai(&pdev->dev); | ||
331 | dev_set_drvdata(&pdev->dev, NULL); | ||
332 | |||
333 | clk_put(host->clk); | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | #ifdef CONFIG_PM | ||
339 | static int spdif_out_suspend(struct device *dev) | ||
340 | { | ||
341 | struct platform_device *pdev = to_platform_device(dev); | ||
342 | struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev); | ||
343 | |||
344 | if (host->running) | ||
345 | clk_disable(host->clk); | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static int spdif_out_resume(struct device *dev) | ||
351 | { | ||
352 | struct platform_device *pdev = to_platform_device(dev); | ||
353 | struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev); | ||
354 | |||
355 | if (host->running) { | ||
356 | clk_enable(host->clk); | ||
357 | spdif_out_configure(host); | ||
358 | spdif_out_clock(host, host->saved_params.core_freq, | ||
359 | host->saved_params.rate); | ||
360 | } | ||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static SIMPLE_DEV_PM_OPS(spdif_out_dev_pm_ops, spdif_out_suspend, \ | ||
365 | spdif_out_resume); | ||
366 | |||
367 | #define SPDIF_OUT_DEV_PM_OPS (&spdif_out_dev_pm_ops) | ||
368 | |||
369 | #else | ||
370 | #define SPDIF_OUT_DEV_PM_OPS NULL | ||
371 | |||
372 | #endif | ||
373 | |||
374 | static struct platform_driver spdif_out_driver = { | ||
375 | .probe = spdif_out_probe, | ||
376 | .remove = spdif_out_remove, | ||
377 | .driver = { | ||
378 | .name = "spdif-out", | ||
379 | .owner = THIS_MODULE, | ||
380 | .pm = SPDIF_OUT_DEV_PM_OPS, | ||
381 | }, | ||
382 | }; | ||
383 | |||
384 | module_platform_driver(spdif_out_driver); | ||
385 | |||
386 | MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>"); | ||
387 | MODULE_DESCRIPTION("SPEAr SPDIF OUT SoC Interface"); | ||
388 | MODULE_LICENSE("GPL"); | ||
389 | MODULE_ALIAS("platform:spdif_out"); | ||
diff --git a/sound/soc/spear/spdif_out_regs.h b/sound/soc/spear/spdif_out_regs.h new file mode 100644 index 000000000000..a5e53324b452 --- /dev/null +++ b/sound/soc/spear/spdif_out_regs.h | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * SPEAr SPDIF OUT controller header file | ||
3 | * | ||
4 | * Copyright (ST) 2011 Vipin Kumar (vipin.kumar@st.com) | ||
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 | #ifndef SPDIF_OUT_REGS_H | ||
22 | #define SPDIF_OUT_REGS_H | ||
23 | |||
24 | #define SPDIF_OUT_SOFT_RST 0x00 | ||
25 | #define SPDIF_OUT_RESET (1 << 0) | ||
26 | #define SPDIF_OUT_FIFO_DATA 0x04 | ||
27 | #define SPDIF_OUT_INT_STA 0x08 | ||
28 | #define SPDIF_OUT_INT_STA_CLR 0x0C | ||
29 | #define SPDIF_INT_UNDERFLOW (1 << 0) | ||
30 | #define SPDIF_INT_EODATA (1 << 1) | ||
31 | #define SPDIF_INT_EOBLOCK (1 << 2) | ||
32 | #define SPDIF_INT_EOLATENCY (1 << 3) | ||
33 | #define SPDIF_INT_EOPD_DATA (1 << 4) | ||
34 | #define SPDIF_INT_MEMFULLREAD (1 << 5) | ||
35 | #define SPDIF_INT_EOPD_PAUSE (1 << 6) | ||
36 | |||
37 | #define SPDIF_OUT_INT_EN 0x10 | ||
38 | #define SPDIF_OUT_INT_EN_SET 0x14 | ||
39 | #define SPDIF_OUT_INT_EN_CLR 0x18 | ||
40 | #define SPDIF_OUT_CTRL 0x1C | ||
41 | #define SPDIF_OPMODE_MASK (7 << 0) | ||
42 | #define SPDIF_OPMODE_OFF (0 << 0) | ||
43 | #define SPDIF_OPMODE_MUTE_PCM (1 << 0) | ||
44 | #define SPDIF_OPMODE_MUTE_PAUSE (2 << 0) | ||
45 | #define SPDIF_OPMODE_AUD_DATA (3 << 0) | ||
46 | #define SPDIF_OPMODE_ENCODE (4 << 0) | ||
47 | #define SPDIF_STATE_NORMAL (1 << 3) | ||
48 | #define SPDIF_DIVIDER_MASK (0xff << 5) | ||
49 | #define SPDIF_DIVIDER_SHIFT (5) | ||
50 | #define SPDIF_SAMPLEREAD_MASK (0x1ffff << 15) | ||
51 | #define SPDIF_SAMPLEREAD_SHIFT (15) | ||
52 | #define SPDIF_OUT_STA 0x20 | ||
53 | #define SPDIF_OUT_PA_PB 0x24 | ||
54 | #define SPDIF_OUT_PC_PD 0x28 | ||
55 | #define SPDIF_OUT_CL1 0x2C | ||
56 | #define SPDIF_OUT_CR1 0x30 | ||
57 | #define SPDIF_OUT_CL2_CR2_UV 0x34 | ||
58 | #define SPDIF_OUT_PAUSE_LAT 0x38 | ||
59 | #define SPDIF_OUT_FRMLEN_BRST 0x3C | ||
60 | #define SPDIF_OUT_CFG 0x40 | ||
61 | #define SPDIF_OUT_MEMFMT_16_0 (0 << 5) | ||
62 | #define SPDIF_OUT_MEMFMT_16_16 (1 << 5) | ||
63 | #define SPDIF_OUT_VALID_DMA (0 << 3) | ||
64 | #define SPDIF_OUT_VALID_HW (1 << 3) | ||
65 | #define SPDIF_OUT_USER_DMA (0 << 2) | ||
66 | #define SPDIF_OUT_USER_HW (1 << 2) | ||
67 | #define SPDIF_OUT_CHNLSTA_DMA (0 << 1) | ||
68 | #define SPDIF_OUT_CHNLSTA_HW (1 << 1) | ||
69 | #define SPDIF_OUT_PARITY_HW (0 << 0) | ||
70 | #define SPDIF_OUT_PARITY_DMA (1 << 0) | ||
71 | #define SPDIF_OUT_FDMA_TRIG_2 (2 << 8) | ||
72 | #define SPDIF_OUT_FDMA_TRIG_6 (6 << 8) | ||
73 | #define SPDIF_OUT_FDMA_TRIG_8 (8 << 8) | ||
74 | #define SPDIF_OUT_FDMA_TRIG_10 (10 << 8) | ||
75 | #define SPDIF_OUT_FDMA_TRIG_12 (12 << 8) | ||
76 | #define SPDIF_OUT_FDMA_TRIG_16 (16 << 8) | ||
77 | #define SPDIF_OUT_FDMA_TRIG_18 (18 << 8) | ||
78 | |||
79 | #endif /* SPDIF_OUT_REGS_H */ | ||
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c new file mode 100644 index 000000000000..97c2cac8e92c --- /dev/null +++ b/sound/soc/spear/spear_pcm.c | |||
@@ -0,0 +1,214 @@ | |||
1 | /* | ||
2 | * ALSA PCM interface for ST SPEAr Processors | ||
3 | * | ||
4 | * sound/soc/spear/spear_pcm.c | ||
5 | * | ||
6 | * Copyright (C) 2012 ST Microelectronics | ||
7 | * Rajeev Kumar<rajeev-dlh.kumar@st.com> | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public | ||
10 | * License version 2. This program is licensed "as is" without any | ||
11 | * warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/dmaengine.h> | ||
16 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/scatterlist.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/dmaengine_pcm.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/spear_dma.h> | ||
27 | |||
28 | struct snd_pcm_hardware spear_pcm_hardware = { | ||
29 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
30 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | ||
31 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), | ||
32 | .buffer_bytes_max = 16 * 1024, /* max buffer size */ | ||
33 | .period_bytes_min = 2 * 1024, /* 1 msec data minimum period size */ | ||
34 | .period_bytes_max = 2 * 1024, /* maximum period size */ | ||
35 | .periods_min = 1, /* min # periods */ | ||
36 | .periods_max = 8, /* max # of periods */ | ||
37 | .fifo_size = 0, /* fifo size in bytes */ | ||
38 | }; | ||
39 | |||
40 | static int spear_pcm_hw_params(struct snd_pcm_substream *substream, | ||
41 | struct snd_pcm_hw_params *params) | ||
42 | { | ||
43 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static int spear_pcm_hw_free(struct snd_pcm_substream *substream) | ||
49 | { | ||
50 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int spear_pcm_open(struct snd_pcm_substream *substream) | ||
56 | { | ||
57 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
58 | |||
59 | struct spear_dma_data *dma_data = (struct spear_dma_data *) | ||
60 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
61 | int ret; | ||
62 | |||
63 | ret = snd_soc_set_runtime_hwparams(substream, &spear_pcm_hardware); | ||
64 | if (ret) | ||
65 | return ret; | ||
66 | |||
67 | ret = snd_dmaengine_pcm_open(substream, dma_data->filter, dma_data); | ||
68 | if (ret) | ||
69 | return ret; | ||
70 | |||
71 | snd_dmaengine_pcm_set_data(substream, dma_data); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int spear_pcm_close(struct snd_pcm_substream *substream) | ||
77 | { | ||
78 | |||
79 | snd_dmaengine_pcm_close(substream); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int spear_pcm_mmap(struct snd_pcm_substream *substream, | ||
85 | struct vm_area_struct *vma) | ||
86 | { | ||
87 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
88 | |||
89 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
90 | runtime->dma_area, runtime->dma_addr, | ||
91 | runtime->dma_bytes); | ||
92 | } | ||
93 | |||
94 | static struct snd_pcm_ops spear_pcm_ops = { | ||
95 | .open = spear_pcm_open, | ||
96 | .close = spear_pcm_close, | ||
97 | .ioctl = snd_pcm_lib_ioctl, | ||
98 | .hw_params = spear_pcm_hw_params, | ||
99 | .hw_free = spear_pcm_hw_free, | ||
100 | .trigger = snd_dmaengine_pcm_trigger, | ||
101 | .pointer = snd_dmaengine_pcm_pointer, | ||
102 | .mmap = spear_pcm_mmap, | ||
103 | }; | ||
104 | |||
105 | static int | ||
106 | spear_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream, | ||
107 | size_t size) | ||
108 | { | ||
109 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
110 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
111 | |||
112 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
113 | buf->dev.dev = pcm->card->dev; | ||
114 | buf->private_data = NULL; | ||
115 | |||
116 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
117 | &buf->addr, GFP_KERNEL); | ||
118 | if (!buf->area) | ||
119 | return -ENOMEM; | ||
120 | |||
121 | dev_info(buf->dev.dev, | ||
122 | " preallocate_dma_buffer: area=%p, addr=%p, size=%d\n", | ||
123 | (void *)buf->area, (void *)buf->addr, size); | ||
124 | |||
125 | buf->bytes = size; | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static void spear_pcm_free(struct snd_pcm *pcm) | ||
130 | { | ||
131 | struct snd_pcm_substream *substream; | ||
132 | struct snd_dma_buffer *buf; | ||
133 | int stream; | ||
134 | |||
135 | for (stream = 0; stream < 2; stream++) { | ||
136 | substream = pcm->streams[stream].substream; | ||
137 | if (!substream) | ||
138 | continue; | ||
139 | |||
140 | buf = &substream->dma_buffer; | ||
141 | if (!buf && !buf->area) | ||
142 | continue; | ||
143 | |||
144 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
145 | buf->area, buf->addr); | ||
146 | buf->area = NULL; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static u64 spear_pcm_dmamask = DMA_BIT_MASK(32); | ||
151 | |||
152 | static int spear_pcm_new(struct snd_card *card, | ||
153 | struct snd_soc_dai *dai, struct snd_pcm *pcm) | ||
154 | { | ||
155 | int ret; | ||
156 | |||
157 | if (!card->dev->dma_mask) | ||
158 | card->dev->dma_mask = &spear_pcm_dmamask; | ||
159 | if (!card->dev->coherent_dma_mask) | ||
160 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
161 | |||
162 | if (dai->driver->playback.channels_min) { | ||
163 | ret = spear_pcm_preallocate_dma_buffer(pcm, | ||
164 | SNDRV_PCM_STREAM_PLAYBACK, | ||
165 | spear_pcm_hardware.buffer_bytes_max); | ||
166 | if (ret) | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | if (dai->driver->capture.channels_min) { | ||
171 | ret = spear_pcm_preallocate_dma_buffer(pcm, | ||
172 | SNDRV_PCM_STREAM_CAPTURE, | ||
173 | spear_pcm_hardware.buffer_bytes_max); | ||
174 | if (ret) | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | struct snd_soc_platform_driver spear_soc_platform = { | ||
182 | .ops = &spear_pcm_ops, | ||
183 | .pcm_new = spear_pcm_new, | ||
184 | .pcm_free = spear_pcm_free, | ||
185 | }; | ||
186 | |||
187 | static int __devinit spear_soc_platform_probe(struct platform_device *pdev) | ||
188 | { | ||
189 | return snd_soc_register_platform(&pdev->dev, &spear_soc_platform); | ||
190 | } | ||
191 | |||
192 | static int __devexit spear_soc_platform_remove(struct platform_device *pdev) | ||
193 | { | ||
194 | snd_soc_unregister_platform(&pdev->dev); | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static struct platform_driver spear_pcm_driver = { | ||
200 | .driver = { | ||
201 | .name = "spear-pcm-audio", | ||
202 | .owner = THIS_MODULE, | ||
203 | }, | ||
204 | |||
205 | .probe = spear_soc_platform_probe, | ||
206 | .remove = __devexit_p(spear_soc_platform_remove), | ||
207 | }; | ||
208 | |||
209 | module_platform_driver(spear_pcm_driver); | ||
210 | |||
211 | MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>"); | ||
212 | MODULE_DESCRIPTION("SPEAr PCM DMA module"); | ||
213 | MODULE_LICENSE("GPL"); | ||
214 | MODULE_ALIAS("platform:spear-pcm-audio"); | ||
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index c1c8e955f4d3..02bcd308c189 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig | |||
@@ -1,7 +1,8 @@ | |||
1 | config SND_SOC_TEGRA | 1 | config SND_SOC_TEGRA |
2 | tristate "SoC Audio for the Tegra System-on-Chip" | 2 | tristate "SoC Audio for the Tegra System-on-Chip" |
3 | depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA | 3 | depends on ARCH_TEGRA && (TEGRA_SYSTEM_DMA || TEGRA20_APB_DMA) |
4 | select REGMAP_MMIO | 4 | select REGMAP_MMIO |
5 | select SND_SOC_DMAENGINE_PCM if TEGRA20_APB_DMA | ||
5 | help | 6 | help |
6 | Say Y or M here if you want support for SoC audio on Tegra. | 7 | Say Y or M here if you want support for SoC audio on Tegra. |
7 | 8 | ||
@@ -58,17 +59,9 @@ config SND_SOC_TEGRA_WM8753 | |||
58 | Say Y or M here if you want to add support for SoC audio on Tegra | 59 | Say Y or M here if you want to add support for SoC audio on Tegra |
59 | boards using the WM8753 codec, such as Whistler. | 60 | boards using the WM8753 codec, such as Whistler. |
60 | 61 | ||
61 | config MACH_HAS_SND_SOC_TEGRA_WM8903 | ||
62 | bool | ||
63 | help | ||
64 | Machines that use the SND_SOC_TEGRA_WM8903 driver should select | ||
65 | this config option, in order to allow the user to enable | ||
66 | SND_SOC_TEGRA_WM8903. | ||
67 | |||
68 | config SND_SOC_TEGRA_WM8903 | 62 | config SND_SOC_TEGRA_WM8903 |
69 | tristate "SoC Audio support for Tegra boards using a WM8903 codec" | 63 | tristate "SoC Audio support for Tegra boards using a WM8903 codec" |
70 | depends on SND_SOC_TEGRA && I2C | 64 | depends on SND_SOC_TEGRA && I2C |
71 | depends on MACH_HAS_SND_SOC_TEGRA_WM8903 | ||
72 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC | 65 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC |
73 | select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC | 66 | select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC |
74 | select SND_SOC_WM8903 | 67 | select SND_SOC_WM8903 |
@@ -79,7 +72,7 @@ config SND_SOC_TEGRA_WM8903 | |||
79 | 72 | ||
80 | config SND_SOC_TEGRA_TRIMSLICE | 73 | config SND_SOC_TEGRA_TRIMSLICE |
81 | tristate "SoC Audio support for TrimSlice board" | 74 | tristate "SoC Audio support for TrimSlice board" |
82 | depends on SND_SOC_TEGRA && MACH_TRIMSLICE && I2C | 75 | depends on SND_SOC_TEGRA && I2C |
83 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC | 76 | select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC |
84 | select SND_SOC_TLV320AIC23 | 77 | select SND_SOC_TLV320AIC23 |
85 | help | 78 | help |
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 0c7af63d444b..0832e8afd73c 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c | |||
@@ -46,23 +46,11 @@ | |||
46 | 46 | ||
47 | #define DRV_NAME "tegra20-i2s" | 47 | #define DRV_NAME "tegra20-i2s" |
48 | 48 | ||
49 | static inline void tegra20_i2s_write(struct tegra20_i2s *i2s, u32 reg, u32 val) | ||
50 | { | ||
51 | regmap_write(i2s->regmap, reg, val); | ||
52 | } | ||
53 | |||
54 | static inline u32 tegra20_i2s_read(struct tegra20_i2s *i2s, u32 reg) | ||
55 | { | ||
56 | u32 val; | ||
57 | regmap_read(i2s->regmap, reg, &val); | ||
58 | return val; | ||
59 | } | ||
60 | |||
61 | static int tegra20_i2s_runtime_suspend(struct device *dev) | 49 | static int tegra20_i2s_runtime_suspend(struct device *dev) |
62 | { | 50 | { |
63 | struct tegra20_i2s *i2s = dev_get_drvdata(dev); | 51 | struct tegra20_i2s *i2s = dev_get_drvdata(dev); |
64 | 52 | ||
65 | clk_disable(i2s->clk_i2s); | 53 | clk_disable_unprepare(i2s->clk_i2s); |
66 | 54 | ||
67 | return 0; | 55 | return 0; |
68 | } | 56 | } |
@@ -72,7 +60,7 @@ static int tegra20_i2s_runtime_resume(struct device *dev) | |||
72 | struct tegra20_i2s *i2s = dev_get_drvdata(dev); | 60 | struct tegra20_i2s *i2s = dev_get_drvdata(dev); |
73 | int ret; | 61 | int ret; |
74 | 62 | ||
75 | ret = clk_enable(i2s->clk_i2s); | 63 | ret = clk_prepare_enable(i2s->clk_i2s); |
76 | if (ret) { | 64 | if (ret) { |
77 | dev_err(dev, "clk_enable failed: %d\n", ret); | 65 | dev_err(dev, "clk_enable failed: %d\n", ret); |
78 | return ret; | 66 | return ret; |
@@ -85,6 +73,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, | |||
85 | unsigned int fmt) | 73 | unsigned int fmt) |
86 | { | 74 | { |
87 | struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 75 | struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
76 | unsigned int mask, val; | ||
88 | 77 | ||
89 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 78 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
90 | case SND_SOC_DAIFMT_NB_NF: | 79 | case SND_SOC_DAIFMT_NB_NF: |
@@ -93,10 +82,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, | |||
93 | return -EINVAL; | 82 | return -EINVAL; |
94 | } | 83 | } |
95 | 84 | ||
96 | i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_MASTER_ENABLE; | 85 | mask = TEGRA20_I2S_CTRL_MASTER_ENABLE; |
97 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 86 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
98 | case SND_SOC_DAIFMT_CBS_CFS: | 87 | case SND_SOC_DAIFMT_CBS_CFS: |
99 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_MASTER_ENABLE; | 88 | val = TEGRA20_I2S_CTRL_MASTER_ENABLE; |
100 | break; | 89 | break; |
101 | case SND_SOC_DAIFMT_CBM_CFM: | 90 | case SND_SOC_DAIFMT_CBM_CFM: |
102 | break; | 91 | break; |
@@ -104,33 +93,35 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, | |||
104 | return -EINVAL; | 93 | return -EINVAL; |
105 | } | 94 | } |
106 | 95 | ||
107 | i2s->reg_ctrl &= ~(TEGRA20_I2S_CTRL_BIT_FORMAT_MASK | | 96 | mask |= TEGRA20_I2S_CTRL_BIT_FORMAT_MASK | |
108 | TEGRA20_I2S_CTRL_LRCK_MASK); | 97 | TEGRA20_I2S_CTRL_LRCK_MASK; |
109 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 98 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
110 | case SND_SOC_DAIFMT_DSP_A: | 99 | case SND_SOC_DAIFMT_DSP_A: |
111 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; | 100 | val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; |
112 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; | 101 | val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; |
113 | break; | 102 | break; |
114 | case SND_SOC_DAIFMT_DSP_B: | 103 | case SND_SOC_DAIFMT_DSP_B: |
115 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; | 104 | val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; |
116 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_R_LOW; | 105 | val |= TEGRA20_I2S_CTRL_LRCK_R_LOW; |
117 | break; | 106 | break; |
118 | case SND_SOC_DAIFMT_I2S: | 107 | case SND_SOC_DAIFMT_I2S: |
119 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S; | 108 | val |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S; |
120 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; | 109 | val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; |
121 | break; | 110 | break; |
122 | case SND_SOC_DAIFMT_RIGHT_J: | 111 | case SND_SOC_DAIFMT_RIGHT_J: |
123 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM; | 112 | val |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM; |
124 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; | 113 | val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; |
125 | break; | 114 | break; |
126 | case SND_SOC_DAIFMT_LEFT_J: | 115 | case SND_SOC_DAIFMT_LEFT_J: |
127 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM; | 116 | val |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM; |
128 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; | 117 | val |= TEGRA20_I2S_CTRL_LRCK_L_LOW; |
129 | break; | 118 | break; |
130 | default: | 119 | default: |
131 | return -EINVAL; | 120 | return -EINVAL; |
132 | } | 121 | } |
133 | 122 | ||
123 | regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val); | ||
124 | |||
134 | return 0; | 125 | return 0; |
135 | } | 126 | } |
136 | 127 | ||
@@ -138,29 +129,34 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream, | |||
138 | struct snd_pcm_hw_params *params, | 129 | struct snd_pcm_hw_params *params, |
139 | struct snd_soc_dai *dai) | 130 | struct snd_soc_dai *dai) |
140 | { | 131 | { |
141 | struct device *dev = substream->pcm->card->dev; | 132 | struct device *dev = dai->dev; |
142 | struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 133 | struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
143 | u32 reg; | 134 | unsigned int mask, val; |
144 | int ret, sample_size, srate, i2sclock, bitcnt; | 135 | int ret, sample_size, srate, i2sclock, bitcnt; |
145 | 136 | ||
146 | i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_BIT_SIZE_MASK; | 137 | mask = TEGRA20_I2S_CTRL_BIT_SIZE_MASK; |
147 | switch (params_format(params)) { | 138 | switch (params_format(params)) { |
148 | case SNDRV_PCM_FORMAT_S16_LE: | 139 | case SNDRV_PCM_FORMAT_S16_LE: |
149 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_16; | 140 | val = TEGRA20_I2S_CTRL_BIT_SIZE_16; |
150 | sample_size = 16; | 141 | sample_size = 16; |
151 | break; | 142 | break; |
152 | case SNDRV_PCM_FORMAT_S24_LE: | 143 | case SNDRV_PCM_FORMAT_S24_LE: |
153 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_24; | 144 | val = TEGRA20_I2S_CTRL_BIT_SIZE_24; |
154 | sample_size = 24; | 145 | sample_size = 24; |
155 | break; | 146 | break; |
156 | case SNDRV_PCM_FORMAT_S32_LE: | 147 | case SNDRV_PCM_FORMAT_S32_LE: |
157 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_32; | 148 | val = TEGRA20_I2S_CTRL_BIT_SIZE_32; |
158 | sample_size = 32; | 149 | sample_size = 32; |
159 | break; | 150 | break; |
160 | default: | 151 | default: |
161 | return -EINVAL; | 152 | return -EINVAL; |
162 | } | 153 | } |
163 | 154 | ||
155 | mask |= TEGRA20_I2S_CTRL_FIFO_FORMAT_MASK; | ||
156 | val |= TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED; | ||
157 | |||
158 | regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val); | ||
159 | |||
164 | srate = params_rate(params); | 160 | srate = params_rate(params); |
165 | 161 | ||
166 | /* Final "* 2" required by Tegra hardware */ | 162 | /* Final "* 2" required by Tegra hardware */ |
@@ -175,42 +171,44 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream, | |||
175 | bitcnt = (i2sclock / (2 * srate)) - 1; | 171 | bitcnt = (i2sclock / (2 * srate)) - 1; |
176 | if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US) | 172 | if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US) |
177 | return -EINVAL; | 173 | return -EINVAL; |
178 | reg = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; | 174 | val = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; |
179 | 175 | ||
180 | if (i2sclock % (2 * srate)) | 176 | if (i2sclock % (2 * srate)) |
181 | reg |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE; | 177 | val |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE; |
182 | 178 | ||
183 | tegra20_i2s_write(i2s, TEGRA20_I2S_TIMING, reg); | 179 | regmap_write(i2s->regmap, TEGRA20_I2S_TIMING, val); |
184 | 180 | ||
185 | tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR, | 181 | regmap_write(i2s->regmap, TEGRA20_I2S_FIFO_SCR, |
186 | TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | | 182 | TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | |
187 | TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); | 183 | TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); |
188 | 184 | ||
189 | return 0; | 185 | return 0; |
190 | } | 186 | } |
191 | 187 | ||
192 | static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s) | 188 | static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s) |
193 | { | 189 | { |
194 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO1_ENABLE; | 190 | regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, |
195 | tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); | 191 | TEGRA20_I2S_CTRL_FIFO1_ENABLE, |
192 | TEGRA20_I2S_CTRL_FIFO1_ENABLE); | ||
196 | } | 193 | } |
197 | 194 | ||
198 | static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s) | 195 | static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s) |
199 | { | 196 | { |
200 | i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO1_ENABLE; | 197 | regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, |
201 | tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); | 198 | TEGRA20_I2S_CTRL_FIFO1_ENABLE, 0); |
202 | } | 199 | } |
203 | 200 | ||
204 | static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s) | 201 | static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s) |
205 | { | 202 | { |
206 | i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO2_ENABLE; | 203 | regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, |
207 | tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); | 204 | TEGRA20_I2S_CTRL_FIFO2_ENABLE, |
205 | TEGRA20_I2S_CTRL_FIFO2_ENABLE); | ||
208 | } | 206 | } |
209 | 207 | ||
210 | static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s) | 208 | static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s) |
211 | { | 209 | { |
212 | i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO2_ENABLE; | 210 | regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, |
213 | tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); | 211 | TEGRA20_I2S_CTRL_FIFO2_ENABLE, 0); |
214 | } | 212 | } |
215 | 213 | ||
216 | static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | 214 | static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd, |
@@ -261,12 +259,14 @@ static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = { | |||
261 | static const struct snd_soc_dai_driver tegra20_i2s_dai_template = { | 259 | static const struct snd_soc_dai_driver tegra20_i2s_dai_template = { |
262 | .probe = tegra20_i2s_probe, | 260 | .probe = tegra20_i2s_probe, |
263 | .playback = { | 261 | .playback = { |
262 | .stream_name = "Playback", | ||
264 | .channels_min = 2, | 263 | .channels_min = 2, |
265 | .channels_max = 2, | 264 | .channels_max = 2, |
266 | .rates = SNDRV_PCM_RATE_8000_96000, | 265 | .rates = SNDRV_PCM_RATE_8000_96000, |
267 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 266 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
268 | }, | 267 | }, |
269 | .capture = { | 268 | .capture = { |
269 | .stream_name = "Capture", | ||
270 | .channels_min = 2, | 270 | .channels_min = 2, |
271 | .channels_max = 2, | 271 | .channels_max = 2, |
272 | .rates = SNDRV_PCM_RATE_8000_96000, | 272 | .rates = SNDRV_PCM_RATE_8000_96000, |
@@ -412,8 +412,6 @@ static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev) | |||
412 | i2s->playback_dma_data.width = 32; | 412 | i2s->playback_dma_data.width = 32; |
413 | i2s->playback_dma_data.req_sel = dma_ch; | 413 | i2s->playback_dma_data.req_sel = dma_ch; |
414 | 414 | ||
415 | i2s->reg_ctrl = TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED; | ||
416 | |||
417 | pm_runtime_enable(&pdev->dev); | 415 | pm_runtime_enable(&pdev->dev); |
418 | if (!pm_runtime_enabled(&pdev->dev)) { | 416 | if (!pm_runtime_enabled(&pdev->dev)) { |
419 | ret = tegra20_i2s_runtime_resume(&pdev->dev); | 417 | ret = tegra20_i2s_runtime_resume(&pdev->dev); |
diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h index a57efc6a597e..c27069d24d77 100644 --- a/sound/soc/tegra/tegra20_i2s.h +++ b/sound/soc/tegra/tegra20_i2s.h | |||
@@ -158,7 +158,6 @@ struct tegra20_i2s { | |||
158 | struct tegra_pcm_dma_params capture_dma_data; | 158 | struct tegra_pcm_dma_params capture_dma_data; |
159 | struct tegra_pcm_dma_params playback_dma_data; | 159 | struct tegra_pcm_dma_params playback_dma_data; |
160 | struct regmap *regmap; | 160 | struct regmap *regmap; |
161 | u32 reg_ctrl; | ||
162 | }; | 161 | }; |
163 | 162 | ||
164 | #endif | 163 | #endif |
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index f9b57418bd08..3ebc8670ba00 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c | |||
@@ -37,24 +37,11 @@ | |||
37 | 37 | ||
38 | #define DRV_NAME "tegra20-spdif" | 38 | #define DRV_NAME "tegra20-spdif" |
39 | 39 | ||
40 | static inline void tegra20_spdif_write(struct tegra20_spdif *spdif, u32 reg, | ||
41 | u32 val) | ||
42 | { | ||
43 | regmap_write(spdif->regmap, reg, val); | ||
44 | } | ||
45 | |||
46 | static inline u32 tegra20_spdif_read(struct tegra20_spdif *spdif, u32 reg) | ||
47 | { | ||
48 | u32 val; | ||
49 | regmap_read(spdif->regmap, reg, &val); | ||
50 | return val; | ||
51 | } | ||
52 | |||
53 | static int tegra20_spdif_runtime_suspend(struct device *dev) | 40 | static int tegra20_spdif_runtime_suspend(struct device *dev) |
54 | { | 41 | { |
55 | struct tegra20_spdif *spdif = dev_get_drvdata(dev); | 42 | struct tegra20_spdif *spdif = dev_get_drvdata(dev); |
56 | 43 | ||
57 | clk_disable(spdif->clk_spdif_out); | 44 | clk_disable_unprepare(spdif->clk_spdif_out); |
58 | 45 | ||
59 | return 0; | 46 | return 0; |
60 | } | 47 | } |
@@ -64,7 +51,7 @@ static int tegra20_spdif_runtime_resume(struct device *dev) | |||
64 | struct tegra20_spdif *spdif = dev_get_drvdata(dev); | 51 | struct tegra20_spdif *spdif = dev_get_drvdata(dev); |
65 | int ret; | 52 | int ret; |
66 | 53 | ||
67 | ret = clk_enable(spdif->clk_spdif_out); | 54 | ret = clk_prepare_enable(spdif->clk_spdif_out); |
68 | if (ret) { | 55 | if (ret) { |
69 | dev_err(dev, "clk_enable failed: %d\n", ret); | 56 | dev_err(dev, "clk_enable failed: %d\n", ret); |
70 | return ret; | 57 | return ret; |
@@ -77,21 +64,24 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, | |||
77 | struct snd_pcm_hw_params *params, | 64 | struct snd_pcm_hw_params *params, |
78 | struct snd_soc_dai *dai) | 65 | struct snd_soc_dai *dai) |
79 | { | 66 | { |
80 | struct device *dev = substream->pcm->card->dev; | 67 | struct device *dev = dai->dev; |
81 | struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); | 68 | struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); |
69 | unsigned int mask, val; | ||
82 | int ret, spdifclock; | 70 | int ret, spdifclock; |
83 | 71 | ||
84 | spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_PACK; | 72 | mask = TEGRA20_SPDIF_CTRL_PACK | |
85 | spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; | 73 | TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; |
86 | switch (params_format(params)) { | 74 | switch (params_format(params)) { |
87 | case SNDRV_PCM_FORMAT_S16_LE: | 75 | case SNDRV_PCM_FORMAT_S16_LE: |
88 | spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_PACK; | 76 | val = TEGRA20_SPDIF_CTRL_PACK | |
89 | spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; | 77 | TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; |
90 | break; | 78 | break; |
91 | default: | 79 | default: |
92 | return -EINVAL; | 80 | return -EINVAL; |
93 | } | 81 | } |
94 | 82 | ||
83 | regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, mask, val); | ||
84 | |||
95 | switch (params_rate(params)) { | 85 | switch (params_rate(params)) { |
96 | case 32000: | 86 | case 32000: |
97 | spdifclock = 4096000; | 87 | spdifclock = 4096000; |
@@ -129,14 +119,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream, | |||
129 | 119 | ||
130 | static void tegra20_spdif_start_playback(struct tegra20_spdif *spdif) | 120 | static void tegra20_spdif_start_playback(struct tegra20_spdif *spdif) |
131 | { | 121 | { |
132 | spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_TX_EN; | 122 | regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, |
133 | tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl); | 123 | TEGRA20_SPDIF_CTRL_TX_EN, |
124 | TEGRA20_SPDIF_CTRL_TX_EN); | ||
134 | } | 125 | } |
135 | 126 | ||
136 | static void tegra20_spdif_stop_playback(struct tegra20_spdif *spdif) | 127 | static void tegra20_spdif_stop_playback(struct tegra20_spdif *spdif) |
137 | { | 128 | { |
138 | spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_TX_EN; | 129 | regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, |
139 | tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl); | 130 | TEGRA20_SPDIF_CTRL_TX_EN, 0); |
140 | } | 131 | } |
141 | 132 | ||
142 | static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd, | 133 | static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd, |
@@ -181,6 +172,7 @@ static struct snd_soc_dai_driver tegra20_spdif_dai = { | |||
181 | .name = DRV_NAME, | 172 | .name = DRV_NAME, |
182 | .probe = tegra20_spdif_probe, | 173 | .probe = tegra20_spdif_probe, |
183 | .playback = { | 174 | .playback = { |
175 | .stream_name = "Playback", | ||
184 | .channels_min = 2, | 176 | .channels_min = 2, |
185 | .channels_max = 2, | 177 | .channels_max = 2, |
186 | .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | | 178 | .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | |
diff --git a/sound/soc/tegra/tegra20_spdif.h b/sound/soc/tegra/tegra20_spdif.h index ed756527efea..b48d699fd583 100644 --- a/sound/soc/tegra/tegra20_spdif.h +++ b/sound/soc/tegra/tegra20_spdif.h | |||
@@ -465,7 +465,6 @@ struct tegra20_spdif { | |||
465 | struct tegra_pcm_dma_params capture_dma_data; | 465 | struct tegra_pcm_dma_params capture_dma_data; |
466 | struct tegra_pcm_dma_params playback_dma_data; | 466 | struct tegra_pcm_dma_params playback_dma_data; |
467 | struct regmap *regmap; | 467 | struct regmap *regmap; |
468 | u32 reg_ctrl; | ||
469 | }; | 468 | }; |
470 | 469 | ||
471 | #endif | 470 | #endif |
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index f43edb364a18..bf5610122c76 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c | |||
@@ -56,8 +56,8 @@ static int tegra30_ahub_runtime_suspend(struct device *dev) | |||
56 | regcache_cache_only(ahub->regmap_apbif, true); | 56 | regcache_cache_only(ahub->regmap_apbif, true); |
57 | regcache_cache_only(ahub->regmap_ahub, true); | 57 | regcache_cache_only(ahub->regmap_ahub, true); |
58 | 58 | ||
59 | clk_disable(ahub->clk_apbif); | 59 | clk_disable_unprepare(ahub->clk_apbif); |
60 | clk_disable(ahub->clk_d_audio); | 60 | clk_disable_unprepare(ahub->clk_d_audio); |
61 | 61 | ||
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
@@ -77,12 +77,12 @@ static int tegra30_ahub_runtime_resume(struct device *dev) | |||
77 | { | 77 | { |
78 | int ret; | 78 | int ret; |
79 | 79 | ||
80 | ret = clk_enable(ahub->clk_d_audio); | 80 | ret = clk_prepare_enable(ahub->clk_d_audio); |
81 | if (ret) { | 81 | if (ret) { |
82 | dev_err(dev, "clk_enable d_audio failed: %d\n", ret); | 82 | dev_err(dev, "clk_enable d_audio failed: %d\n", ret); |
83 | return ret; | 83 | return ret; |
84 | } | 84 | } |
85 | ret = clk_enable(ahub->clk_apbif); | 85 | ret = clk_prepare_enable(ahub->clk_apbif); |
86 | if (ret) { | 86 | if (ret) { |
87 | dev_err(dev, "clk_enable apbif failed: %d\n", ret); | 87 | dev_err(dev, "clk_enable apbif failed: %d\n", ret); |
88 | clk_disable(ahub->clk_d_audio); | 88 | clk_disable(ahub->clk_d_audio); |
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 8596032985dc..44184228d1f0 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c | |||
@@ -44,25 +44,13 @@ | |||
44 | 44 | ||
45 | #define DRV_NAME "tegra30-i2s" | 45 | #define DRV_NAME "tegra30-i2s" |
46 | 46 | ||
47 | static inline void tegra30_i2s_write(struct tegra30_i2s *i2s, u32 reg, u32 val) | ||
48 | { | ||
49 | regmap_write(i2s->regmap, reg, val); | ||
50 | } | ||
51 | |||
52 | static inline u32 tegra30_i2s_read(struct tegra30_i2s *i2s, u32 reg) | ||
53 | { | ||
54 | u32 val; | ||
55 | regmap_read(i2s->regmap, reg, &val); | ||
56 | return val; | ||
57 | } | ||
58 | |||
59 | static int tegra30_i2s_runtime_suspend(struct device *dev) | 47 | static int tegra30_i2s_runtime_suspend(struct device *dev) |
60 | { | 48 | { |
61 | struct tegra30_i2s *i2s = dev_get_drvdata(dev); | 49 | struct tegra30_i2s *i2s = dev_get_drvdata(dev); |
62 | 50 | ||
63 | regcache_cache_only(i2s->regmap, true); | 51 | regcache_cache_only(i2s->regmap, true); |
64 | 52 | ||
65 | clk_disable(i2s->clk_i2s); | 53 | clk_disable_unprepare(i2s->clk_i2s); |
66 | 54 | ||
67 | return 0; | 55 | return 0; |
68 | } | 56 | } |
@@ -72,7 +60,7 @@ static int tegra30_i2s_runtime_resume(struct device *dev) | |||
72 | struct tegra30_i2s *i2s = dev_get_drvdata(dev); | 60 | struct tegra30_i2s *i2s = dev_get_drvdata(dev); |
73 | int ret; | 61 | int ret; |
74 | 62 | ||
75 | ret = clk_enable(i2s->clk_i2s); | 63 | ret = clk_prepare_enable(i2s->clk_i2s); |
76 | if (ret) { | 64 | if (ret) { |
77 | dev_err(dev, "clk_enable failed: %d\n", ret); | 65 | dev_err(dev, "clk_enable failed: %d\n", ret); |
78 | return ret; | 66 | return ret; |
@@ -128,6 +116,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, | |||
128 | unsigned int fmt) | 116 | unsigned int fmt) |
129 | { | 117 | { |
130 | struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 118 | struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
119 | unsigned int mask, val; | ||
131 | 120 | ||
132 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 121 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
133 | case SND_SOC_DAIFMT_NB_NF: | 122 | case SND_SOC_DAIFMT_NB_NF: |
@@ -136,10 +125,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, | |||
136 | return -EINVAL; | 125 | return -EINVAL; |
137 | } | 126 | } |
138 | 127 | ||
139 | i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_MASTER_ENABLE; | 128 | mask = TEGRA30_I2S_CTRL_MASTER_ENABLE; |
140 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 129 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
141 | case SND_SOC_DAIFMT_CBS_CFS: | 130 | case SND_SOC_DAIFMT_CBS_CFS: |
142 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_MASTER_ENABLE; | 131 | val = TEGRA30_I2S_CTRL_MASTER_ENABLE; |
143 | break; | 132 | break; |
144 | case SND_SOC_DAIFMT_CBM_CFM: | 133 | case SND_SOC_DAIFMT_CBM_CFM: |
145 | break; | 134 | break; |
@@ -147,33 +136,37 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, | |||
147 | return -EINVAL; | 136 | return -EINVAL; |
148 | } | 137 | } |
149 | 138 | ||
150 | i2s->reg_ctrl &= ~(TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK | | 139 | mask |= TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK | |
151 | TEGRA30_I2S_CTRL_LRCK_MASK); | 140 | TEGRA30_I2S_CTRL_LRCK_MASK; |
152 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 141 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
153 | case SND_SOC_DAIFMT_DSP_A: | 142 | case SND_SOC_DAIFMT_DSP_A: |
154 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; | 143 | val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; |
155 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; | 144 | val |= TEGRA30_I2S_CTRL_LRCK_L_LOW; |
156 | break; | 145 | break; |
157 | case SND_SOC_DAIFMT_DSP_B: | 146 | case SND_SOC_DAIFMT_DSP_B: |
158 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; | 147 | val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; |
159 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW; | 148 | val |= TEGRA30_I2S_CTRL_LRCK_R_LOW; |
160 | break; | 149 | break; |
161 | case SND_SOC_DAIFMT_I2S: | 150 | case SND_SOC_DAIFMT_I2S: |
162 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; | 151 | val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; |
163 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; | 152 | val |= TEGRA30_I2S_CTRL_LRCK_L_LOW; |
164 | break; | 153 | break; |
165 | case SND_SOC_DAIFMT_RIGHT_J: | 154 | case SND_SOC_DAIFMT_RIGHT_J: |
166 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; | 155 | val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; |
167 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; | 156 | val |= TEGRA30_I2S_CTRL_LRCK_L_LOW; |
168 | break; | 157 | break; |
169 | case SND_SOC_DAIFMT_LEFT_J: | 158 | case SND_SOC_DAIFMT_LEFT_J: |
170 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; | 159 | val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; |
171 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; | 160 | val |= TEGRA30_I2S_CTRL_LRCK_L_LOW; |
172 | break; | 161 | break; |
173 | default: | 162 | default: |
174 | return -EINVAL; | 163 | return -EINVAL; |
175 | } | 164 | } |
176 | 165 | ||
166 | pm_runtime_get_sync(dai->dev); | ||
167 | regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val); | ||
168 | pm_runtime_put(dai->dev); | ||
169 | |||
177 | return 0; | 170 | return 0; |
178 | } | 171 | } |
179 | 172 | ||
@@ -181,24 +174,26 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, | |||
181 | struct snd_pcm_hw_params *params, | 174 | struct snd_pcm_hw_params *params, |
182 | struct snd_soc_dai *dai) | 175 | struct snd_soc_dai *dai) |
183 | { | 176 | { |
184 | struct device *dev = substream->pcm->card->dev; | 177 | struct device *dev = dai->dev; |
185 | struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); | 178 | struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
186 | u32 val; | 179 | unsigned int mask, val, reg; |
187 | int ret, sample_size, srate, i2sclock, bitcnt; | 180 | int ret, sample_size, srate, i2sclock, bitcnt; |
188 | 181 | ||
189 | if (params_channels(params) != 2) | 182 | if (params_channels(params) != 2) |
190 | return -EINVAL; | 183 | return -EINVAL; |
191 | 184 | ||
192 | i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_BIT_SIZE_MASK; | 185 | mask = TEGRA30_I2S_CTRL_BIT_SIZE_MASK; |
193 | switch (params_format(params)) { | 186 | switch (params_format(params)) { |
194 | case SNDRV_PCM_FORMAT_S16_LE: | 187 | case SNDRV_PCM_FORMAT_S16_LE: |
195 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16; | 188 | val = TEGRA30_I2S_CTRL_BIT_SIZE_16; |
196 | sample_size = 16; | 189 | sample_size = 16; |
197 | break; | 190 | break; |
198 | default: | 191 | default: |
199 | return -EINVAL; | 192 | return -EINVAL; |
200 | } | 193 | } |
201 | 194 | ||
195 | regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val); | ||
196 | |||
202 | srate = params_rate(params); | 197 | srate = params_rate(params); |
203 | 198 | ||
204 | /* Final "* 2" required by Tegra hardware */ | 199 | /* Final "* 2" required by Tegra hardware */ |
@@ -219,7 +214,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, | |||
219 | if (i2sclock % (2 * srate)) | 214 | if (i2sclock % (2 * srate)) |
220 | val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE; | 215 | val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE; |
221 | 216 | ||
222 | tegra30_i2s_write(i2s, TEGRA30_I2S_TIMING, val); | 217 | regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val); |
223 | 218 | ||
224 | val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | | 219 | val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | |
225 | (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | | 220 | (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | |
@@ -229,15 +224,17 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, | |||
229 | 224 | ||
230 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 225 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
231 | val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX; | 226 | val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX; |
232 | tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val); | 227 | reg = TEGRA30_I2S_CIF_RX_CTRL; |
233 | } else { | 228 | } else { |
234 | val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; | 229 | val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; |
235 | tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val); | 230 | reg = TEGRA30_I2S_CIF_RX_CTRL; |
236 | } | 231 | } |
237 | 232 | ||
233 | regmap_write(i2s->regmap, reg, val); | ||
234 | |||
238 | val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) | | 235 | val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) | |
239 | (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT); | 236 | (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT); |
240 | tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val); | 237 | regmap_write(i2s->regmap, TEGRA30_I2S_OFFSET, val); |
241 | 238 | ||
242 | return 0; | 239 | return 0; |
243 | } | 240 | } |
@@ -245,29 +242,31 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream, | |||
245 | static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s) | 242 | static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s) |
246 | { | 243 | { |
247 | tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif); | 244 | tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif); |
248 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX; | 245 | regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, |
249 | tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); | 246 | TEGRA30_I2S_CTRL_XFER_EN_TX, |
247 | TEGRA30_I2S_CTRL_XFER_EN_TX); | ||
250 | } | 248 | } |
251 | 249 | ||
252 | static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s) | 250 | static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s) |
253 | { | 251 | { |
254 | tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif); | 252 | tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif); |
255 | i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX; | 253 | regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, |
256 | tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); | 254 | TEGRA30_I2S_CTRL_XFER_EN_TX, 0); |
257 | } | 255 | } |
258 | 256 | ||
259 | static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s) | 257 | static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s) |
260 | { | 258 | { |
261 | tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif); | 259 | tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif); |
262 | i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX; | 260 | regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, |
263 | tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); | 261 | TEGRA30_I2S_CTRL_XFER_EN_RX, |
262 | TEGRA30_I2S_CTRL_XFER_EN_RX); | ||
264 | } | 263 | } |
265 | 264 | ||
266 | static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s) | 265 | static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s) |
267 | { | 266 | { |
268 | tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif); | 267 | tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif); |
269 | i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX; | 268 | regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, |
270 | tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); | 269 | TEGRA30_I2S_CTRL_XFER_EN_RX, 0); |
271 | } | 270 | } |
272 | 271 | ||
273 | static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | 272 | static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd, |
@@ -320,12 +319,14 @@ static struct snd_soc_dai_ops tegra30_i2s_dai_ops = { | |||
320 | static const struct snd_soc_dai_driver tegra30_i2s_dai_template = { | 319 | static const struct snd_soc_dai_driver tegra30_i2s_dai_template = { |
321 | .probe = tegra30_i2s_probe, | 320 | .probe = tegra30_i2s_probe, |
322 | .playback = { | 321 | .playback = { |
322 | .stream_name = "Playback", | ||
323 | .channels_min = 2, | 323 | .channels_min = 2, |
324 | .channels_max = 2, | 324 | .channels_max = 2, |
325 | .rates = SNDRV_PCM_RATE_8000_96000, | 325 | .rates = SNDRV_PCM_RATE_8000_96000, |
326 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 326 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
327 | }, | 327 | }, |
328 | .capture = { | 328 | .capture = { |
329 | .stream_name = "Capture", | ||
329 | .channels_min = 2, | 330 | .channels_min = 2, |
330 | .channels_max = 2, | 331 | .channels_max = 2, |
331 | .rates = SNDRV_PCM_RATE_8000_96000, | 332 | .rates = SNDRV_PCM_RATE_8000_96000, |
diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h index 91adf29c7a87..34dc47b9581c 100644 --- a/sound/soc/tegra/tegra30_i2s.h +++ b/sound/soc/tegra/tegra30_i2s.h | |||
@@ -236,7 +236,6 @@ struct tegra30_i2s { | |||
236 | enum tegra30_ahub_txcif playback_fifo_cif; | 236 | enum tegra30_ahub_txcif playback_fifo_cif; |
237 | struct tegra_pcm_dma_params playback_dma_data; | 237 | struct tegra_pcm_dma_params playback_dma_data; |
238 | struct regmap *regmap; | 238 | struct regmap *regmap; |
239 | u32 reg_ctrl; | ||
240 | }; | 239 | }; |
241 | 240 | ||
242 | #endif | 241 | #endif |
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 32de7006daf0..d684df294c0c 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver | 2 | * tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver |
3 | * | 3 | * |
4 | * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net> | 4 | * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net> |
5 | * Copyright (C) 2012 - NVIDIA, Inc. | 5 | * Copyright (C) 2012 - NVIDIA, Inc. |
@@ -33,11 +33,8 @@ | |||
33 | 33 | ||
34 | #define DRV_NAME "tegra-alc5632" | 34 | #define DRV_NAME "tegra-alc5632" |
35 | 35 | ||
36 | #define GPIO_HP_DET BIT(0) | ||
37 | |||
38 | struct tegra_alc5632 { | 36 | struct tegra_alc5632 { |
39 | struct tegra_asoc_utils_data util_data; | 37 | struct tegra_asoc_utils_data util_data; |
40 | int gpio_requested; | ||
41 | int gpio_hp_det; | 38 | int gpio_hp_det; |
42 | }; | 39 | }; |
43 | 40 | ||
@@ -46,7 +43,7 @@ static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream, | |||
46 | { | 43 | { |
47 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 44 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
48 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 45 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
49 | struct snd_soc_codec *codec = rtd->codec; | 46 | struct snd_soc_codec *codec = codec_dai->codec; |
50 | struct snd_soc_card *card = codec->card; | 47 | struct snd_soc_card *card = codec->card; |
51 | struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card); | 48 | struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card); |
52 | int srate, mclk; | 49 | int srate, mclk; |
@@ -108,9 +105,9 @@ static const struct snd_kcontrol_new tegra_alc5632_controls[] = { | |||
108 | 105 | ||
109 | static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) | 106 | static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) |
110 | { | 107 | { |
111 | struct snd_soc_codec *codec = rtd->codec; | 108 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
109 | struct snd_soc_codec *codec = codec_dai->codec; | ||
112 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 110 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
113 | struct device_node *np = codec->card->dev->of_node; | ||
114 | struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card); | 111 | struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card); |
115 | 112 | ||
116 | snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, | 113 | snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, |
@@ -119,14 +116,11 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) | |||
119 | ARRAY_SIZE(tegra_alc5632_hs_jack_pins), | 116 | ARRAY_SIZE(tegra_alc5632_hs_jack_pins), |
120 | tegra_alc5632_hs_jack_pins); | 117 | tegra_alc5632_hs_jack_pins); |
121 | 118 | ||
122 | machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); | ||
123 | |||
124 | if (gpio_is_valid(machine->gpio_hp_det)) { | 119 | if (gpio_is_valid(machine->gpio_hp_det)) { |
125 | tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det; | 120 | tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det; |
126 | snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack, | 121 | snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack, |
127 | 1, | 122 | 1, |
128 | &tegra_alc5632_hp_jack_gpio); | 123 | &tegra_alc5632_hp_jack_gpio); |
129 | machine->gpio_requested |= GPIO_HP_DET; | ||
130 | } | 124 | } |
131 | 125 | ||
132 | snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); | 126 | snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); |
@@ -159,6 +153,7 @@ static struct snd_soc_card snd_soc_tegra_alc5632 = { | |||
159 | 153 | ||
160 | static __devinit int tegra_alc5632_probe(struct platform_device *pdev) | 154 | static __devinit int tegra_alc5632_probe(struct platform_device *pdev) |
161 | { | 155 | { |
156 | struct device_node *np = pdev->dev.of_node; | ||
162 | struct snd_soc_card *card = &snd_soc_tegra_alc5632; | 157 | struct snd_soc_card *card = &snd_soc_tegra_alc5632; |
163 | struct tegra_alc5632 *alc5632; | 158 | struct tegra_alc5632 *alc5632; |
164 | int ret; | 159 | int ret; |
@@ -181,6 +176,10 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev) | |||
181 | goto err; | 176 | goto err; |
182 | } | 177 | } |
183 | 178 | ||
179 | alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); | ||
180 | if (alc5632->gpio_hp_det == -ENODEV) | ||
181 | return -EPROBE_DEFER; | ||
182 | |||
184 | ret = snd_soc_of_parse_card_name(card, "nvidia,model"); | 183 | ret = snd_soc_of_parse_card_name(card, "nvidia,model"); |
185 | if (ret) | 184 | if (ret) |
186 | goto err; | 185 | goto err; |
@@ -199,16 +198,16 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev) | |||
199 | goto err; | 198 | goto err; |
200 | } | 199 | } |
201 | 200 | ||
202 | tegra_alc5632_dai.cpu_dai_of_node = of_parse_phandle( | 201 | tegra_alc5632_dai.cpu_of_node = of_parse_phandle( |
203 | pdev->dev.of_node, "nvidia,i2s-controller", 0); | 202 | pdev->dev.of_node, "nvidia,i2s-controller", 0); |
204 | if (!tegra_alc5632_dai.cpu_dai_of_node) { | 203 | if (!tegra_alc5632_dai.cpu_of_node) { |
205 | dev_err(&pdev->dev, | 204 | dev_err(&pdev->dev, |
206 | "Property 'nvidia,i2s-controller' missing or invalid\n"); | 205 | "Property 'nvidia,i2s-controller' missing or invalid\n"); |
207 | ret = -EINVAL; | 206 | ret = -EINVAL; |
208 | goto err; | 207 | goto err; |
209 | } | 208 | } |
210 | 209 | ||
211 | tegra_alc5632_dai.platform_of_node = tegra_alc5632_dai.cpu_dai_of_node; | 210 | tegra_alc5632_dai.platform_of_node = tegra_alc5632_dai.cpu_of_node; |
212 | 211 | ||
213 | ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev); | 212 | ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev); |
214 | if (ret) | 213 | if (ret) |
@@ -234,11 +233,8 @@ static int __devexit tegra_alc5632_remove(struct platform_device *pdev) | |||
234 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 233 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
235 | struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card); | 234 | struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card); |
236 | 235 | ||
237 | if (machine->gpio_requested & GPIO_HP_DET) | 236 | snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack, 1, |
238 | snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack, | 237 | &tegra_alc5632_hp_jack_gpio); |
239 | 1, | ||
240 | &tegra_alc5632_hp_jack_gpio); | ||
241 | machine->gpio_requested = 0; | ||
242 | 238 | ||
243 | snd_soc_unregister_card(card); | 239 | snd_soc_unregister_card(card); |
244 | 240 | ||
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c index 9515ce58ea02..6872c77a1196 100644 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ b/sound/soc/tegra/tegra_asoc_utils.c | |||
@@ -69,9 +69,9 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, | |||
69 | data->set_baseclock = 0; | 69 | data->set_baseclock = 0; |
70 | data->set_mclk = 0; | 70 | data->set_mclk = 0; |
71 | 71 | ||
72 | clk_disable(data->clk_cdev1); | 72 | clk_disable_unprepare(data->clk_cdev1); |
73 | clk_disable(data->clk_pll_a_out0); | 73 | clk_disable_unprepare(data->clk_pll_a_out0); |
74 | clk_disable(data->clk_pll_a); | 74 | clk_disable_unprepare(data->clk_pll_a); |
75 | 75 | ||
76 | err = clk_set_rate(data->clk_pll_a, new_baseclock); | 76 | err = clk_set_rate(data->clk_pll_a, new_baseclock); |
77 | if (err) { | 77 | if (err) { |
@@ -87,19 +87,19 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, | |||
87 | 87 | ||
88 | /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */ | 88 | /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */ |
89 | 89 | ||
90 | err = clk_enable(data->clk_pll_a); | 90 | err = clk_prepare_enable(data->clk_pll_a); |
91 | if (err) { | 91 | if (err) { |
92 | dev_err(data->dev, "Can't enable pll_a: %d\n", err); | 92 | dev_err(data->dev, "Can't enable pll_a: %d\n", err); |
93 | return err; | 93 | return err; |
94 | } | 94 | } |
95 | 95 | ||
96 | err = clk_enable(data->clk_pll_a_out0); | 96 | err = clk_prepare_enable(data->clk_pll_a_out0); |
97 | if (err) { | 97 | if (err) { |
98 | dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); | 98 | dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); |
99 | return err; | 99 | return err; |
100 | } | 100 | } |
101 | 101 | ||
102 | err = clk_enable(data->clk_cdev1); | 102 | err = clk_prepare_enable(data->clk_cdev1); |
103 | if (err) { | 103 | if (err) { |
104 | dev_err(data->dev, "Can't enable cdev1: %d\n", err); | 104 | dev_err(data->dev, "Can't enable cdev1: %d\n", err); |
105 | return err; | 105 | return err; |
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 127348dc09b1..5658bcec1931 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <sound/pcm.h> | 36 | #include <sound/pcm.h> |
37 | #include <sound/pcm_params.h> | 37 | #include <sound/pcm_params.h> |
38 | #include <sound/soc.h> | 38 | #include <sound/soc.h> |
39 | #include <sound/dmaengine_pcm.h> | ||
39 | 40 | ||
40 | #include "tegra_pcm.h" | 41 | #include "tegra_pcm.h" |
41 | 42 | ||
@@ -56,6 +57,7 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = { | |||
56 | .fifo_size = 4, | 57 | .fifo_size = 4, |
57 | }; | 58 | }; |
58 | 59 | ||
60 | #if defined(CONFIG_TEGRA_SYSTEM_DMA) | ||
59 | static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd) | 61 | static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd) |
60 | { | 62 | { |
61 | struct snd_pcm_substream *substream = prtd->substream; | 63 | struct snd_pcm_substream *substream = prtd->substream; |
@@ -285,6 +287,119 @@ static struct snd_pcm_ops tegra_pcm_ops = { | |||
285 | .pointer = tegra_pcm_pointer, | 287 | .pointer = tegra_pcm_pointer, |
286 | .mmap = tegra_pcm_mmap, | 288 | .mmap = tegra_pcm_mmap, |
287 | }; | 289 | }; |
290 | #else | ||
291 | static int tegra_pcm_open(struct snd_pcm_substream *substream) | ||
292 | { | ||
293 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
294 | struct device *dev = rtd->platform->dev; | ||
295 | int ret; | ||
296 | |||
297 | /* Set HW params now that initialization is complete */ | ||
298 | snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware); | ||
299 | |||
300 | ret = snd_dmaengine_pcm_open(substream, NULL, NULL); | ||
301 | if (ret) { | ||
302 | dev_err(dev, "dmaengine pcm open failed with err %d\n", ret); | ||
303 | return ret; | ||
304 | } | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static int tegra_pcm_close(struct snd_pcm_substream *substream) | ||
310 | { | ||
311 | snd_dmaengine_pcm_close(substream); | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, | ||
316 | struct snd_pcm_hw_params *params) | ||
317 | { | ||
318 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
319 | struct device *dev = rtd->platform->dev; | ||
320 | struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); | ||
321 | struct tegra_pcm_dma_params *dmap; | ||
322 | struct dma_slave_config slave_config; | ||
323 | int ret; | ||
324 | |||
325 | dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
326 | |||
327 | ret = snd_hwparams_to_dma_slave_config(substream, params, | ||
328 | &slave_config); | ||
329 | if (ret) { | ||
330 | dev_err(dev, "hw params config failed with err %d\n", ret); | ||
331 | return ret; | ||
332 | } | ||
333 | |||
334 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
335 | slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
336 | slave_config.dst_addr = dmap->addr; | ||
337 | slave_config.src_maxburst = 0; | ||
338 | } else { | ||
339 | slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
340 | slave_config.src_addr = dmap->addr; | ||
341 | slave_config.dst_maxburst = 0; | ||
342 | } | ||
343 | slave_config.slave_id = dmap->req_sel; | ||
344 | |||
345 | ret = dmaengine_slave_config(chan, &slave_config); | ||
346 | if (ret < 0) { | ||
347 | dev_err(dev, "dma slave config failed with err %d\n", ret); | ||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int tegra_pcm_hw_free(struct snd_pcm_substream *substream) | ||
356 | { | ||
357 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
362 | { | ||
363 | switch (cmd) { | ||
364 | case SNDRV_PCM_TRIGGER_START: | ||
365 | case SNDRV_PCM_TRIGGER_RESUME: | ||
366 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
367 | return snd_dmaengine_pcm_trigger(substream, | ||
368 | SNDRV_PCM_TRIGGER_START); | ||
369 | |||
370 | case SNDRV_PCM_TRIGGER_STOP: | ||
371 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
372 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
373 | return snd_dmaengine_pcm_trigger(substream, | ||
374 | SNDRV_PCM_TRIGGER_STOP); | ||
375 | default: | ||
376 | return -EINVAL; | ||
377 | } | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int tegra_pcm_mmap(struct snd_pcm_substream *substream, | ||
382 | struct vm_area_struct *vma) | ||
383 | { | ||
384 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
385 | |||
386 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
387 | runtime->dma_area, | ||
388 | runtime->dma_addr, | ||
389 | runtime->dma_bytes); | ||
390 | } | ||
391 | |||
392 | static struct snd_pcm_ops tegra_pcm_ops = { | ||
393 | .open = tegra_pcm_open, | ||
394 | .close = tegra_pcm_close, | ||
395 | .ioctl = snd_pcm_lib_ioctl, | ||
396 | .hw_params = tegra_pcm_hw_params, | ||
397 | .hw_free = tegra_pcm_hw_free, | ||
398 | .trigger = tegra_pcm_trigger, | ||
399 | .pointer = snd_dmaengine_pcm_pointer, | ||
400 | .mmap = tegra_pcm_mmap, | ||
401 | }; | ||
402 | #endif | ||
288 | 403 | ||
289 | static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | 404 | static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) |
290 | { | 405 | { |
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h index 985d418a35e7..a3a450352dcf 100644 --- a/sound/soc/tegra/tegra_pcm.h +++ b/sound/soc/tegra/tegra_pcm.h | |||
@@ -40,6 +40,7 @@ struct tegra_pcm_dma_params { | |||
40 | unsigned long req_sel; | 40 | unsigned long req_sel; |
41 | }; | 41 | }; |
42 | 42 | ||
43 | #if defined(CONFIG_TEGRA_SYSTEM_DMA) | ||
43 | struct tegra_runtime_data { | 44 | struct tegra_runtime_data { |
44 | struct snd_pcm_substream *substream; | 45 | struct snd_pcm_substream *substream; |
45 | spinlock_t lock; | 46 | spinlock_t lock; |
@@ -51,6 +52,7 @@ struct tegra_runtime_data { | |||
51 | struct tegra_dma_req dma_req[2]; | 52 | struct tegra_dma_req dma_req[2]; |
52 | struct tegra_dma_channel *dma_chan; | 53 | struct tegra_dma_channel *dma_chan; |
53 | }; | 54 | }; |
55 | #endif | ||
54 | 56 | ||
55 | int tegra_pcm_platform_register(struct device *dev); | 57 | int tegra_pcm_platform_register(struct device *dev); |
56 | void tegra_pcm_platform_unregister(struct device *dev); | 58 | void tegra_pcm_platform_unregister(struct device *dev); |
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index 4e77026807a2..ea9166d5c4eb 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c | |||
@@ -57,7 +57,7 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream, | |||
57 | { | 57 | { |
58 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 58 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
59 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 59 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
60 | struct snd_soc_codec *codec = rtd->codec; | 60 | struct snd_soc_codec *codec = codec_dai->codec; |
61 | struct snd_soc_card *card = codec->card; | 61 | struct snd_soc_card *card = codec->card; |
62 | struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); | 62 | struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); |
63 | int srate, mclk; | 63 | int srate, mclk; |
@@ -157,9 +157,9 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev) | |||
157 | goto err; | 157 | goto err; |
158 | } | 158 | } |
159 | 159 | ||
160 | tegra_wm8753_dai.cpu_dai_of_node = of_parse_phandle( | 160 | tegra_wm8753_dai.cpu_of_node = of_parse_phandle( |
161 | pdev->dev.of_node, "nvidia,i2s-controller", 0); | 161 | pdev->dev.of_node, "nvidia,i2s-controller", 0); |
162 | if (!tegra_wm8753_dai.cpu_dai_of_node) { | 162 | if (!tegra_wm8753_dai.cpu_of_node) { |
163 | dev_err(&pdev->dev, | 163 | dev_err(&pdev->dev, |
164 | "Property 'nvidia,i2s-controller' missing or invalid\n"); | 164 | "Property 'nvidia,i2s-controller' missing or invalid\n"); |
165 | ret = -EINVAL; | 165 | ret = -EINVAL; |
@@ -167,7 +167,7 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev) | |||
167 | } | 167 | } |
168 | 168 | ||
169 | tegra_wm8753_dai.platform_of_node = | 169 | tegra_wm8753_dai.platform_of_node = |
170 | tegra_wm8753_dai.cpu_dai_of_node; | 170 | tegra_wm8753_dai.cpu_of_node; |
171 | 171 | ||
172 | ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); | 172 | ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); |
173 | if (ret) | 173 | if (ret) |
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 3b6da91188a9..0c5bb33d258e 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c | |||
@@ -28,8 +28,6 @@ | |||
28 | * | 28 | * |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <asm/mach-types.h> | ||
32 | |||
33 | #include <linux/module.h> | 31 | #include <linux/module.h> |
34 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
35 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
@@ -50,16 +48,9 @@ | |||
50 | 48 | ||
51 | #define DRV_NAME "tegra-snd-wm8903" | 49 | #define DRV_NAME "tegra-snd-wm8903" |
52 | 50 | ||
53 | #define GPIO_SPKR_EN BIT(0) | ||
54 | #define GPIO_HP_MUTE BIT(1) | ||
55 | #define GPIO_INT_MIC_EN BIT(2) | ||
56 | #define GPIO_EXT_MIC_EN BIT(3) | ||
57 | #define GPIO_HP_DET BIT(4) | ||
58 | |||
59 | struct tegra_wm8903 { | 51 | struct tegra_wm8903 { |
60 | struct tegra_wm8903_platform_data pdata; | 52 | struct tegra_wm8903_platform_data pdata; |
61 | struct tegra_asoc_utils_data util_data; | 53 | struct tegra_asoc_utils_data util_data; |
62 | int gpio_requested; | ||
63 | }; | 54 | }; |
64 | 55 | ||
65 | static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, | 56 | static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, |
@@ -67,8 +58,7 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, | |||
67 | { | 58 | { |
68 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 59 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
69 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 60 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
70 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 61 | struct snd_soc_codec *codec = codec_dai->codec; |
71 | struct snd_soc_codec *codec = rtd->codec; | ||
72 | struct snd_soc_card *card = codec->card; | 62 | struct snd_soc_card *card = codec->card; |
73 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | 63 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); |
74 | int srate, mclk; | 64 | int srate, mclk; |
@@ -95,24 +85,6 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, | |||
95 | return err; | 85 | return err; |
96 | } | 86 | } |
97 | 87 | ||
98 | err = snd_soc_dai_set_fmt(codec_dai, | ||
99 | SND_SOC_DAIFMT_I2S | | ||
100 | SND_SOC_DAIFMT_NB_NF | | ||
101 | SND_SOC_DAIFMT_CBS_CFS); | ||
102 | if (err < 0) { | ||
103 | dev_err(card->dev, "codec_dai fmt not set\n"); | ||
104 | return err; | ||
105 | } | ||
106 | |||
107 | err = snd_soc_dai_set_fmt(cpu_dai, | ||
108 | SND_SOC_DAIFMT_I2S | | ||
109 | SND_SOC_DAIFMT_NB_NF | | ||
110 | SND_SOC_DAIFMT_CBS_CFS); | ||
111 | if (err < 0) { | ||
112 | dev_err(card->dev, "cpu_dai fmt not set\n"); | ||
113 | return err; | ||
114 | } | ||
115 | |||
116 | err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | 88 | err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, |
117 | SND_SOC_CLOCK_IN); | 89 | SND_SOC_CLOCK_IN); |
118 | if (err < 0) { | 90 | if (err < 0) { |
@@ -160,7 +132,7 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w, | |||
160 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | 132 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); |
161 | struct tegra_wm8903_platform_data *pdata = &machine->pdata; | 133 | struct tegra_wm8903_platform_data *pdata = &machine->pdata; |
162 | 134 | ||
163 | if (!(machine->gpio_requested & GPIO_SPKR_EN)) | 135 | if (!gpio_is_valid(pdata->gpio_spkr_en)) |
164 | return 0; | 136 | return 0; |
165 | 137 | ||
166 | gpio_set_value_cansleep(pdata->gpio_spkr_en, | 138 | gpio_set_value_cansleep(pdata->gpio_spkr_en, |
@@ -177,7 +149,7 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w, | |||
177 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | 149 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); |
178 | struct tegra_wm8903_platform_data *pdata = &machine->pdata; | 150 | struct tegra_wm8903_platform_data *pdata = &machine->pdata; |
179 | 151 | ||
180 | if (!(machine->gpio_requested & GPIO_HP_MUTE)) | 152 | if (!gpio_is_valid(pdata->gpio_hp_mute)) |
181 | return 0; | 153 | return 0; |
182 | 154 | ||
183 | gpio_set_value_cansleep(pdata->gpio_hp_mute, | 155 | gpio_set_value_cansleep(pdata->gpio_hp_mute, |
@@ -203,122 +175,18 @@ static const struct snd_soc_dapm_route harmony_audio_map[] = { | |||
203 | {"IN1L", NULL, "Mic Jack"}, | 175 | {"IN1L", NULL, "Mic Jack"}, |
204 | }; | 176 | }; |
205 | 177 | ||
206 | static const struct snd_soc_dapm_route seaboard_audio_map[] = { | ||
207 | {"Headphone Jack", NULL, "HPOUTR"}, | ||
208 | {"Headphone Jack", NULL, "HPOUTL"}, | ||
209 | {"Int Spk", NULL, "ROP"}, | ||
210 | {"Int Spk", NULL, "RON"}, | ||
211 | {"Int Spk", NULL, "LOP"}, | ||
212 | {"Int Spk", NULL, "LON"}, | ||
213 | {"Mic Jack", NULL, "MICBIAS"}, | ||
214 | {"IN1R", NULL, "Mic Jack"}, | ||
215 | }; | ||
216 | |||
217 | static const struct snd_soc_dapm_route kaen_audio_map[] = { | ||
218 | {"Headphone Jack", NULL, "HPOUTR"}, | ||
219 | {"Headphone Jack", NULL, "HPOUTL"}, | ||
220 | {"Int Spk", NULL, "ROP"}, | ||
221 | {"Int Spk", NULL, "RON"}, | ||
222 | {"Int Spk", NULL, "LOP"}, | ||
223 | {"Int Spk", NULL, "LON"}, | ||
224 | {"Mic Jack", NULL, "MICBIAS"}, | ||
225 | {"IN2R", NULL, "Mic Jack"}, | ||
226 | }; | ||
227 | |||
228 | static const struct snd_soc_dapm_route aebl_audio_map[] = { | ||
229 | {"Headphone Jack", NULL, "HPOUTR"}, | ||
230 | {"Headphone Jack", NULL, "HPOUTL"}, | ||
231 | {"Int Spk", NULL, "LINEOUTR"}, | ||
232 | {"Int Spk", NULL, "LINEOUTL"}, | ||
233 | {"Mic Jack", NULL, "MICBIAS"}, | ||
234 | {"IN1R", NULL, "Mic Jack"}, | ||
235 | }; | ||
236 | |||
237 | static const struct snd_kcontrol_new tegra_wm8903_controls[] = { | 178 | static const struct snd_kcontrol_new tegra_wm8903_controls[] = { |
238 | SOC_DAPM_PIN_SWITCH("Int Spk"), | 179 | SOC_DAPM_PIN_SWITCH("Int Spk"), |
239 | }; | 180 | }; |
240 | 181 | ||
241 | static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) | 182 | static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) |
242 | { | 183 | { |
243 | struct snd_soc_codec *codec = rtd->codec; | 184 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
185 | struct snd_soc_codec *codec = codec_dai->codec; | ||
244 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 186 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
245 | struct snd_soc_card *card = codec->card; | 187 | struct snd_soc_card *card = codec->card; |
246 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | 188 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); |
247 | struct tegra_wm8903_platform_data *pdata = &machine->pdata; | 189 | struct tegra_wm8903_platform_data *pdata = &machine->pdata; |
248 | struct device_node *np = card->dev->of_node; | ||
249 | int ret; | ||
250 | |||
251 | if (card->dev->platform_data) { | ||
252 | memcpy(pdata, card->dev->platform_data, sizeof(*pdata)); | ||
253 | } else if (np) { | ||
254 | /* | ||
255 | * This part must be in init() rather than probe() in order to | ||
256 | * guarantee that the WM8903 has been probed, and hence its | ||
257 | * GPIO controller registered, which is a pre-condition for | ||
258 | * of_get_named_gpio() to be able to map the phandles in the | ||
259 | * properties to the controller node. Given this, all | ||
260 | * pdata handling is in init() for consistency. | ||
261 | */ | ||
262 | pdata->gpio_spkr_en = of_get_named_gpio(np, | ||
263 | "nvidia,spkr-en-gpios", 0); | ||
264 | pdata->gpio_hp_mute = of_get_named_gpio(np, | ||
265 | "nvidia,hp-mute-gpios", 0); | ||
266 | pdata->gpio_hp_det = of_get_named_gpio(np, | ||
267 | "nvidia,hp-det-gpios", 0); | ||
268 | pdata->gpio_int_mic_en = of_get_named_gpio(np, | ||
269 | "nvidia,int-mic-en-gpios", 0); | ||
270 | pdata->gpio_ext_mic_en = of_get_named_gpio(np, | ||
271 | "nvidia,ext-mic-en-gpios", 0); | ||
272 | } else { | ||
273 | dev_err(card->dev, "No platform data supplied\n"); | ||
274 | return -EINVAL; | ||
275 | } | ||
276 | |||
277 | if (gpio_is_valid(pdata->gpio_spkr_en)) { | ||
278 | ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); | ||
279 | if (ret) { | ||
280 | dev_err(card->dev, "cannot get spkr_en gpio\n"); | ||
281 | return ret; | ||
282 | } | ||
283 | machine->gpio_requested |= GPIO_SPKR_EN; | ||
284 | |||
285 | gpio_direction_output(pdata->gpio_spkr_en, 0); | ||
286 | } | ||
287 | |||
288 | if (gpio_is_valid(pdata->gpio_hp_mute)) { | ||
289 | ret = gpio_request(pdata->gpio_hp_mute, "hp_mute"); | ||
290 | if (ret) { | ||
291 | dev_err(card->dev, "cannot get hp_mute gpio\n"); | ||
292 | return ret; | ||
293 | } | ||
294 | machine->gpio_requested |= GPIO_HP_MUTE; | ||
295 | |||
296 | gpio_direction_output(pdata->gpio_hp_mute, 1); | ||
297 | } | ||
298 | |||
299 | if (gpio_is_valid(pdata->gpio_int_mic_en)) { | ||
300 | ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); | ||
301 | if (ret) { | ||
302 | dev_err(card->dev, "cannot get int_mic_en gpio\n"); | ||
303 | return ret; | ||
304 | } | ||
305 | machine->gpio_requested |= GPIO_INT_MIC_EN; | ||
306 | |||
307 | /* Disable int mic; enable signal is active-high */ | ||
308 | gpio_direction_output(pdata->gpio_int_mic_en, 0); | ||
309 | } | ||
310 | |||
311 | if (gpio_is_valid(pdata->gpio_ext_mic_en)) { | ||
312 | ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); | ||
313 | if (ret) { | ||
314 | dev_err(card->dev, "cannot get ext_mic_en gpio\n"); | ||
315 | return ret; | ||
316 | } | ||
317 | machine->gpio_requested |= GPIO_EXT_MIC_EN; | ||
318 | |||
319 | /* Enable ext mic; enable signal is active-low */ | ||
320 | gpio_direction_output(pdata->gpio_ext_mic_en, 0); | ||
321 | } | ||
322 | 190 | ||
323 | if (gpio_is_valid(pdata->gpio_hp_det)) { | 191 | if (gpio_is_valid(pdata->gpio_hp_det)) { |
324 | tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det; | 192 | tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det; |
@@ -330,7 +198,6 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) | |||
330 | snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, | 198 | snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, |
331 | 1, | 199 | 1, |
332 | &tegra_wm8903_hp_jack_gpio); | 200 | &tegra_wm8903_hp_jack_gpio); |
333 | machine->gpio_requested |= GPIO_HP_DET; | ||
334 | } | 201 | } |
335 | 202 | ||
336 | snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, | 203 | snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, |
@@ -366,6 +233,9 @@ static struct snd_soc_dai_link tegra_wm8903_dai = { | |||
366 | .codec_dai_name = "wm8903-hifi", | 233 | .codec_dai_name = "wm8903-hifi", |
367 | .init = tegra_wm8903_init, | 234 | .init = tegra_wm8903_init, |
368 | .ops = &tegra_wm8903_ops, | 235 | .ops = &tegra_wm8903_ops, |
236 | .dai_fmt = SND_SOC_DAIFMT_I2S | | ||
237 | SND_SOC_DAIFMT_NB_NF | | ||
238 | SND_SOC_DAIFMT_CBS_CFS, | ||
369 | }; | 239 | }; |
370 | 240 | ||
371 | static struct snd_soc_card snd_soc_tegra_wm8903 = { | 241 | static struct snd_soc_card snd_soc_tegra_wm8903 = { |
@@ -385,8 +255,10 @@ static struct snd_soc_card snd_soc_tegra_wm8903 = { | |||
385 | 255 | ||
386 | static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) | 256 | static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) |
387 | { | 257 | { |
258 | struct device_node *np = pdev->dev.of_node; | ||
388 | struct snd_soc_card *card = &snd_soc_tegra_wm8903; | 259 | struct snd_soc_card *card = &snd_soc_tegra_wm8903; |
389 | struct tegra_wm8903 *machine; | 260 | struct tegra_wm8903 *machine; |
261 | struct tegra_wm8903_platform_data *pdata; | ||
390 | int ret; | 262 | int ret; |
391 | 263 | ||
392 | if (!pdev->dev.platform_data && !pdev->dev.of_node) { | 264 | if (!pdev->dev.platform_data && !pdev->dev.of_node) { |
@@ -401,12 +273,42 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) | |||
401 | ret = -ENOMEM; | 273 | ret = -ENOMEM; |
402 | goto err; | 274 | goto err; |
403 | } | 275 | } |
276 | pdata = &machine->pdata; | ||
404 | 277 | ||
405 | card->dev = &pdev->dev; | 278 | card->dev = &pdev->dev; |
406 | platform_set_drvdata(pdev, card); | 279 | platform_set_drvdata(pdev, card); |
407 | snd_soc_card_set_drvdata(card, machine); | 280 | snd_soc_card_set_drvdata(card, machine); |
408 | 281 | ||
409 | if (pdev->dev.of_node) { | 282 | if (pdev->dev.platform_data) { |
283 | memcpy(pdata, card->dev->platform_data, sizeof(*pdata)); | ||
284 | } else if (np) { | ||
285 | pdata->gpio_spkr_en = of_get_named_gpio(np, | ||
286 | "nvidia,spkr-en-gpios", 0); | ||
287 | if (pdata->gpio_spkr_en == -ENODEV) | ||
288 | return -EPROBE_DEFER; | ||
289 | |||
290 | pdata->gpio_hp_mute = of_get_named_gpio(np, | ||
291 | "nvidia,hp-mute-gpios", 0); | ||
292 | if (pdata->gpio_hp_mute == -ENODEV) | ||
293 | return -EPROBE_DEFER; | ||
294 | |||
295 | pdata->gpio_hp_det = of_get_named_gpio(np, | ||
296 | "nvidia,hp-det-gpios", 0); | ||
297 | if (pdata->gpio_hp_det == -ENODEV) | ||
298 | return -EPROBE_DEFER; | ||
299 | |||
300 | pdata->gpio_int_mic_en = of_get_named_gpio(np, | ||
301 | "nvidia,int-mic-en-gpios", 0); | ||
302 | if (pdata->gpio_int_mic_en == -ENODEV) | ||
303 | return -EPROBE_DEFER; | ||
304 | |||
305 | pdata->gpio_ext_mic_en = of_get_named_gpio(np, | ||
306 | "nvidia,ext-mic-en-gpios", 0); | ||
307 | if (pdata->gpio_ext_mic_en == -ENODEV) | ||
308 | return -EPROBE_DEFER; | ||
309 | } | ||
310 | |||
311 | if (np) { | ||
410 | ret = snd_soc_of_parse_card_name(card, "nvidia,model"); | 312 | ret = snd_soc_of_parse_card_name(card, "nvidia,model"); |
411 | if (ret) | 313 | if (ret) |
412 | goto err; | 314 | goto err; |
@@ -417,8 +319,8 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) | |||
417 | goto err; | 319 | goto err; |
418 | 320 | ||
419 | tegra_wm8903_dai.codec_name = NULL; | 321 | tegra_wm8903_dai.codec_name = NULL; |
420 | tegra_wm8903_dai.codec_of_node = of_parse_phandle( | 322 | tegra_wm8903_dai.codec_of_node = of_parse_phandle(np, |
421 | pdev->dev.of_node, "nvidia,audio-codec", 0); | 323 | "nvidia,audio-codec", 0); |
422 | if (!tegra_wm8903_dai.codec_of_node) { | 324 | if (!tegra_wm8903_dai.codec_of_node) { |
423 | dev_err(&pdev->dev, | 325 | dev_err(&pdev->dev, |
424 | "Property 'nvidia,audio-codec' missing or invalid\n"); | 326 | "Property 'nvidia,audio-codec' missing or invalid\n"); |
@@ -427,9 +329,9 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) | |||
427 | } | 329 | } |
428 | 330 | ||
429 | tegra_wm8903_dai.cpu_dai_name = NULL; | 331 | tegra_wm8903_dai.cpu_dai_name = NULL; |
430 | tegra_wm8903_dai.cpu_dai_of_node = of_parse_phandle( | 332 | tegra_wm8903_dai.cpu_of_node = of_parse_phandle(np, |
431 | pdev->dev.of_node, "nvidia,i2s-controller", 0); | 333 | "nvidia,i2s-controller", 0); |
432 | if (!tegra_wm8903_dai.cpu_dai_of_node) { | 334 | if (!tegra_wm8903_dai.cpu_of_node) { |
433 | dev_err(&pdev->dev, | 335 | dev_err(&pdev->dev, |
434 | "Property 'nvidia,i2s-controller' missing or invalid\n"); | 336 | "Property 'nvidia,i2s-controller' missing or invalid\n"); |
435 | ret = -EINVAL; | 337 | ret = -EINVAL; |
@@ -438,20 +340,47 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) | |||
438 | 340 | ||
439 | tegra_wm8903_dai.platform_name = NULL; | 341 | tegra_wm8903_dai.platform_name = NULL; |
440 | tegra_wm8903_dai.platform_of_node = | 342 | tegra_wm8903_dai.platform_of_node = |
441 | tegra_wm8903_dai.cpu_dai_of_node; | 343 | tegra_wm8903_dai.cpu_of_node; |
442 | } else { | 344 | } else { |
443 | if (machine_is_harmony()) { | 345 | card->dapm_routes = harmony_audio_map; |
444 | card->dapm_routes = harmony_audio_map; | 346 | card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); |
445 | card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); | 347 | } |
446 | } else if (machine_is_seaboard()) { | 348 | |
447 | card->dapm_routes = seaboard_audio_map; | 349 | if (gpio_is_valid(pdata->gpio_spkr_en)) { |
448 | card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map); | 350 | ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_spkr_en, |
449 | } else if (machine_is_kaen()) { | 351 | GPIOF_OUT_INIT_LOW, "spkr_en"); |
450 | card->dapm_routes = kaen_audio_map; | 352 | if (ret) { |
451 | card->num_dapm_routes = ARRAY_SIZE(kaen_audio_map); | 353 | dev_err(card->dev, "cannot get spkr_en gpio\n"); |
452 | } else { | 354 | return ret; |
453 | card->dapm_routes = aebl_audio_map; | 355 | } |
454 | card->num_dapm_routes = ARRAY_SIZE(aebl_audio_map); | 356 | } |
357 | |||
358 | if (gpio_is_valid(pdata->gpio_hp_mute)) { | ||
359 | ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_hp_mute, | ||
360 | GPIOF_OUT_INIT_HIGH, "hp_mute"); | ||
361 | if (ret) { | ||
362 | dev_err(card->dev, "cannot get hp_mute gpio\n"); | ||
363 | return ret; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | if (gpio_is_valid(pdata->gpio_int_mic_en)) { | ||
368 | /* Disable int mic; enable signal is active-high */ | ||
369 | ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_int_mic_en, | ||
370 | GPIOF_OUT_INIT_LOW, "int_mic_en"); | ||
371 | if (ret) { | ||
372 | dev_err(card->dev, "cannot get int_mic_en gpio\n"); | ||
373 | return ret; | ||
374 | } | ||
375 | } | ||
376 | |||
377 | if (gpio_is_valid(pdata->gpio_ext_mic_en)) { | ||
378 | /* Enable ext mic; enable signal is active-low */ | ||
379 | ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_ext_mic_en, | ||
380 | GPIOF_OUT_INIT_LOW, "ext_mic_en"); | ||
381 | if (ret) { | ||
382 | dev_err(card->dev, "cannot get ext_mic_en gpio\n"); | ||
383 | return ret; | ||
455 | } | 384 | } |
456 | } | 385 | } |
457 | 386 | ||
@@ -478,21 +407,9 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev) | |||
478 | { | 407 | { |
479 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 408 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
480 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | 409 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); |
481 | struct tegra_wm8903_platform_data *pdata = &machine->pdata; | ||
482 | 410 | ||
483 | if (machine->gpio_requested & GPIO_HP_DET) | 411 | snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, 1, |
484 | snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, | 412 | &tegra_wm8903_hp_jack_gpio); |
485 | 1, | ||
486 | &tegra_wm8903_hp_jack_gpio); | ||
487 | if (machine->gpio_requested & GPIO_EXT_MIC_EN) | ||
488 | gpio_free(pdata->gpio_ext_mic_en); | ||
489 | if (machine->gpio_requested & GPIO_INT_MIC_EN) | ||
490 | gpio_free(pdata->gpio_int_mic_en); | ||
491 | if (machine->gpio_requested & GPIO_HP_MUTE) | ||
492 | gpio_free(pdata->gpio_hp_mute); | ||
493 | if (machine->gpio_requested & GPIO_SPKR_EN) | ||
494 | gpio_free(pdata->gpio_spkr_en); | ||
495 | machine->gpio_requested = 0; | ||
496 | 413 | ||
497 | snd_soc_unregister_card(card); | 414 | snd_soc_unregister_card(card); |
498 | 415 | ||
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index 4a8d5b672c9f..e69a4f7000d6 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c | |||
@@ -52,8 +52,7 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, | |||
52 | { | 52 | { |
53 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 53 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
54 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 54 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
55 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 55 | struct snd_soc_codec *codec = codec_dai->codec; |
56 | struct snd_soc_codec *codec = rtd->codec; | ||
57 | struct snd_soc_card *card = codec->card; | 56 | struct snd_soc_card *card = codec->card; |
58 | struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); | 57 | struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); |
59 | int srate, mclk; | 58 | int srate, mclk; |
@@ -68,24 +67,6 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream, | |||
68 | return err; | 67 | return err; |
69 | } | 68 | } |
70 | 69 | ||
71 | err = snd_soc_dai_set_fmt(codec_dai, | ||
72 | SND_SOC_DAIFMT_I2S | | ||
73 | SND_SOC_DAIFMT_NB_NF | | ||
74 | SND_SOC_DAIFMT_CBS_CFS); | ||
75 | if (err < 0) { | ||
76 | dev_err(card->dev, "codec_dai fmt not set\n"); | ||
77 | return err; | ||
78 | } | ||
79 | |||
80 | err = snd_soc_dai_set_fmt(cpu_dai, | ||
81 | SND_SOC_DAIFMT_I2S | | ||
82 | SND_SOC_DAIFMT_NB_NF | | ||
83 | SND_SOC_DAIFMT_CBS_CFS); | ||
84 | if (err < 0) { | ||
85 | dev_err(card->dev, "cpu_dai fmt not set\n"); | ||
86 | return err; | ||
87 | } | ||
88 | |||
89 | err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | 70 | err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, |
90 | SND_SOC_CLOCK_IN); | 71 | SND_SOC_CLOCK_IN); |
91 | if (err < 0) { | 72 | if (err < 0) { |
@@ -121,6 +102,9 @@ static struct snd_soc_dai_link trimslice_tlv320aic23_dai = { | |||
121 | .cpu_dai_name = "tegra20-i2s.0", | 102 | .cpu_dai_name = "tegra20-i2s.0", |
122 | .codec_dai_name = "tlv320aic23-hifi", | 103 | .codec_dai_name = "tlv320aic23-hifi", |
123 | .ops = &trimslice_asoc_ops, | 104 | .ops = &trimslice_asoc_ops, |
105 | .dai_fmt = SND_SOC_DAIFMT_I2S | | ||
106 | SND_SOC_DAIFMT_NB_NF | | ||
107 | SND_SOC_DAIFMT_CBS_CFS, | ||
124 | }; | 108 | }; |
125 | 109 | ||
126 | static struct snd_soc_card snd_soc_trimslice = { | 110 | static struct snd_soc_card snd_soc_trimslice = { |
@@ -162,9 +146,9 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev) | |||
162 | } | 146 | } |
163 | 147 | ||
164 | trimslice_tlv320aic23_dai.cpu_dai_name = NULL; | 148 | trimslice_tlv320aic23_dai.cpu_dai_name = NULL; |
165 | trimslice_tlv320aic23_dai.cpu_dai_of_node = of_parse_phandle( | 149 | trimslice_tlv320aic23_dai.cpu_of_node = of_parse_phandle( |
166 | pdev->dev.of_node, "nvidia,i2s-controller", 0); | 150 | pdev->dev.of_node, "nvidia,i2s-controller", 0); |
167 | if (!trimslice_tlv320aic23_dai.cpu_dai_of_node) { | 151 | if (!trimslice_tlv320aic23_dai.cpu_of_node) { |
168 | dev_err(&pdev->dev, | 152 | dev_err(&pdev->dev, |
169 | "Property 'nvidia,i2s-controller' missing or invalid\n"); | 153 | "Property 'nvidia,i2s-controller' missing or invalid\n"); |
170 | ret = -EINVAL; | 154 | ret = -EINVAL; |
@@ -173,7 +157,7 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev) | |||
173 | 157 | ||
174 | trimslice_tlv320aic23_dai.platform_name = NULL; | 158 | trimslice_tlv320aic23_dai.platform_name = NULL; |
175 | trimslice_tlv320aic23_dai.platform_of_node = | 159 | trimslice_tlv320aic23_dai.platform_of_node = |
176 | trimslice_tlv320aic23_dai.cpu_dai_of_node; | 160 | trimslice_tlv320aic23_dai.cpu_of_node; |
177 | } | 161 | } |
178 | 162 | ||
179 | ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); | 163 | ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); |
diff --git a/sound/soc/ux500/Kconfig b/sound/soc/ux500/Kconfig index 44cf43404cd9..069330d82be5 100644 --- a/sound/soc/ux500/Kconfig +++ b/sound/soc/ux500/Kconfig | |||
@@ -12,3 +12,21 @@ menuconfig SND_SOC_UX500 | |||
12 | config SND_SOC_UX500_PLAT_MSP_I2S | 12 | config SND_SOC_UX500_PLAT_MSP_I2S |
13 | tristate | 13 | tristate |
14 | depends on SND_SOC_UX500 | 14 | depends on SND_SOC_UX500 |
15 | |||
16 | config SND_SOC_UX500_PLAT_DMA | ||
17 | tristate "Platform - DB8500 (DMA)" | ||
18 | depends on SND_SOC_UX500 | ||
19 | select SND_SOC_DMAENGINE_PCM | ||
20 | help | ||
21 | Say Y if you want to enable the Ux500 platform-driver. | ||
22 | |||
23 | +config SND_SOC_UX500_MACH_MOP500 | ||
24 | + tristate "Machine - MOP500 (Ux500 + AB8500)" | ||
25 | depends on AB8500_CORE && AB8500_GPADC && SND_SOC_UX500 | ||
26 | select SND_SOC_AB8500_CODEC | ||
27 | select SND_SOC_UX500_PLAT_MSP_I2S | ||
28 | select SND_SOC_UX500_PLAT_DMA | ||
29 | help | ||
30 | Select this to enable the MOP500 machine-driver. | ||
31 | This will enable platform-drivers for: Ux500 | ||
32 | This will enable codec-drivers for: AB8500 | ||
diff --git a/sound/soc/ux500/Makefile b/sound/soc/ux500/Makefile index 19974c5a2ea1..cce0c11a4d86 100644 --- a/sound/soc/ux500/Makefile +++ b/sound/soc/ux500/Makefile | |||
@@ -2,3 +2,9 @@ | |||
2 | 2 | ||
3 | snd-soc-ux500-plat-msp-i2s-objs := ux500_msp_dai.o ux500_msp_i2s.o | 3 | snd-soc-ux500-plat-msp-i2s-objs := ux500_msp_dai.o ux500_msp_i2s.o |
4 | obj-$(CONFIG_SND_SOC_UX500_PLAT_MSP_I2S) += snd-soc-ux500-plat-msp-i2s.o | 4 | obj-$(CONFIG_SND_SOC_UX500_PLAT_MSP_I2S) += snd-soc-ux500-plat-msp-i2s.o |
5 | |||
6 | snd-soc-ux500-plat-dma-objs := ux500_pcm.o | ||
7 | obj-$(CONFIG_SND_SOC_UX500_PLAT_DMA) += snd-soc-ux500-plat-dma.o | ||
8 | |||
9 | snd-soc-ux500-mach-mop500-objs := mop500.o mop500_ab8500.o | ||
10 | obj-$(CONFIG_SND_SOC_UX500_MACH_MOP500) += snd-soc-ux500-mach-mop500.o | ||
diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c new file mode 100644 index 000000000000..31c4d26d0359 --- /dev/null +++ b/sound/soc/ux500/mop500.c | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2012 | ||
3 | * | ||
4 | * Author: Ola Lilja (ola.o.lilja@stericsson.com) | ||
5 | * for ST-Ericsson. | ||
6 | * | ||
7 | * License terms: | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as published | ||
11 | * by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <asm/mach-types.h> | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/spi/spi.h> | ||
19 | |||
20 | #include <sound/soc.h> | ||
21 | #include <sound/initval.h> | ||
22 | |||
23 | #include "ux500_pcm.h" | ||
24 | #include "ux500_msp_dai.h" | ||
25 | |||
26 | #include <mop500_ab8500.h> | ||
27 | |||
28 | /* Define the whole MOP500 soundcard, linking platform to the codec-drivers */ | ||
29 | struct snd_soc_dai_link mop500_dai_links[] = { | ||
30 | { | ||
31 | .name = "ab8500_0", | ||
32 | .stream_name = "ab8500_0", | ||
33 | .cpu_dai_name = "ux500-msp-i2s.1", | ||
34 | .codec_dai_name = "ab8500-codec-dai.0", | ||
35 | .platform_name = "ux500-pcm.0", | ||
36 | .codec_name = "ab8500-codec.0", | ||
37 | .init = mop500_ab8500_machine_init, | ||
38 | .ops = mop500_ab8500_ops, | ||
39 | }, | ||
40 | { | ||
41 | .name = "ab8500_1", | ||
42 | .stream_name = "ab8500_1", | ||
43 | .cpu_dai_name = "ux500-msp-i2s.3", | ||
44 | .codec_dai_name = "ab8500-codec-dai.1", | ||
45 | .platform_name = "ux500-pcm.0", | ||
46 | .codec_name = "ab8500-codec.0", | ||
47 | .init = NULL, | ||
48 | .ops = mop500_ab8500_ops, | ||
49 | }, | ||
50 | }; | ||
51 | |||
52 | static struct snd_soc_card mop500_card = { | ||
53 | .name = "MOP500-card", | ||
54 | .probe = NULL, | ||
55 | .dai_link = mop500_dai_links, | ||
56 | .num_links = ARRAY_SIZE(mop500_dai_links), | ||
57 | }; | ||
58 | |||
59 | static int __devinit mop500_probe(struct platform_device *pdev) | ||
60 | { | ||
61 | int ret; | ||
62 | |||
63 | pr_debug("%s: Enter.\n", __func__); | ||
64 | |||
65 | dev_dbg(&pdev->dev, "%s: Enter.\n", __func__); | ||
66 | |||
67 | mop500_card.dev = &pdev->dev; | ||
68 | |||
69 | dev_dbg(&pdev->dev, "%s: Card %s: Set platform drvdata.\n", | ||
70 | __func__, mop500_card.name); | ||
71 | platform_set_drvdata(pdev, &mop500_card); | ||
72 | |||
73 | snd_soc_card_set_drvdata(&mop500_card, NULL); | ||
74 | |||
75 | dev_dbg(&pdev->dev, "%s: Card %s: num_links = %d\n", | ||
76 | __func__, mop500_card.name, mop500_card.num_links); | ||
77 | dev_dbg(&pdev->dev, "%s: Card %s: DAI-link 0: name = %s\n", | ||
78 | __func__, mop500_card.name, mop500_card.dai_link[0].name); | ||
79 | dev_dbg(&pdev->dev, "%s: Card %s: DAI-link 0: stream_name = %s\n", | ||
80 | __func__, mop500_card.name, | ||
81 | mop500_card.dai_link[0].stream_name); | ||
82 | |||
83 | ret = snd_soc_register_card(&mop500_card); | ||
84 | if (ret) | ||
85 | dev_err(&pdev->dev, | ||
86 | "Error: snd_soc_register_card failed (%d)!\n", | ||
87 | ret); | ||
88 | |||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | static int __devexit mop500_remove(struct platform_device *pdev) | ||
93 | { | ||
94 | struct snd_soc_card *mop500_card = platform_get_drvdata(pdev); | ||
95 | |||
96 | pr_debug("%s: Enter.\n", __func__); | ||
97 | |||
98 | snd_soc_unregister_card(mop500_card); | ||
99 | mop500_ab8500_remove(mop500_card); | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static struct platform_driver snd_soc_mop500_driver = { | ||
105 | .driver = { | ||
106 | .owner = THIS_MODULE, | ||
107 | .name = "snd-soc-mop500", | ||
108 | }, | ||
109 | .probe = mop500_probe, | ||
110 | .remove = __devexit_p(mop500_remove), | ||
111 | }; | ||
112 | |||
113 | module_platform_driver(snd_soc_mop500_driver); | ||
diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c new file mode 100644 index 000000000000..78cce236693e --- /dev/null +++ b/sound/soc/ux500/mop500_ab8500.c | |||
@@ -0,0 +1,431 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2012 | ||
3 | * | ||
4 | * Author: Ola Lilja <ola.o.lilja@stericsson.com>, | ||
5 | * Kristoffer Karlsson <kristoffer.karlsson@stericsson.com> | ||
6 | * for ST-Ericsson. | ||
7 | * | ||
8 | * License terms: | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as published | ||
12 | * by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/clk.h> | ||
19 | |||
20 | #include <mach/hardware.h> | ||
21 | |||
22 | #include <sound/soc.h> | ||
23 | #include <sound/soc-dapm.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | |||
27 | #include "ux500_pcm.h" | ||
28 | #include "ux500_msp_dai.h" | ||
29 | #include "../codecs/ab8500-codec.h" | ||
30 | |||
31 | #define TX_SLOT_MONO 0x0008 | ||
32 | #define TX_SLOT_STEREO 0x000a | ||
33 | #define RX_SLOT_MONO 0x0001 | ||
34 | #define RX_SLOT_STEREO 0x0003 | ||
35 | #define TX_SLOT_8CH 0x00FF | ||
36 | #define RX_SLOT_8CH 0x00FF | ||
37 | |||
38 | #define DEF_TX_SLOTS TX_SLOT_STEREO | ||
39 | #define DEF_RX_SLOTS RX_SLOT_MONO | ||
40 | |||
41 | #define DRIVERMODE_NORMAL 0 | ||
42 | #define DRIVERMODE_CODEC_ONLY 1 | ||
43 | |||
44 | /* Slot configuration */ | ||
45 | static unsigned int tx_slots = DEF_TX_SLOTS; | ||
46 | static unsigned int rx_slots = DEF_RX_SLOTS; | ||
47 | |||
48 | /* Clocks */ | ||
49 | static const char * const enum_mclk[] = { | ||
50 | "SYSCLK", | ||
51 | "ULPCLK" | ||
52 | }; | ||
53 | enum mclk { | ||
54 | MCLK_SYSCLK, | ||
55 | MCLK_ULPCLK, | ||
56 | }; | ||
57 | |||
58 | static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_mclk, enum_mclk); | ||
59 | |||
60 | /* Private data for machine-part MOP500<->AB8500 */ | ||
61 | struct mop500_ab8500_drvdata { | ||
62 | /* Clocks */ | ||
63 | enum mclk mclk_sel; | ||
64 | struct clk *clk_ptr_intclk; | ||
65 | struct clk *clk_ptr_sysclk; | ||
66 | struct clk *clk_ptr_ulpclk; | ||
67 | }; | ||
68 | |||
69 | static inline const char *get_mclk_str(enum mclk mclk_sel) | ||
70 | { | ||
71 | switch (mclk_sel) { | ||
72 | case MCLK_SYSCLK: | ||
73 | return "SYSCLK"; | ||
74 | case MCLK_ULPCLK: | ||
75 | return "ULPCLK"; | ||
76 | default: | ||
77 | return "Unknown"; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static int mop500_ab8500_set_mclk(struct device *dev, | ||
82 | struct mop500_ab8500_drvdata *drvdata) | ||
83 | { | ||
84 | int status; | ||
85 | struct clk *clk_ptr; | ||
86 | |||
87 | if (IS_ERR(drvdata->clk_ptr_intclk)) { | ||
88 | dev_err(dev, | ||
89 | "%s: ERROR: intclk not initialized!\n", __func__); | ||
90 | return -EIO; | ||
91 | } | ||
92 | |||
93 | switch (drvdata->mclk_sel) { | ||
94 | case MCLK_SYSCLK: | ||
95 | clk_ptr = drvdata->clk_ptr_sysclk; | ||
96 | break; | ||
97 | case MCLK_ULPCLK: | ||
98 | clk_ptr = drvdata->clk_ptr_ulpclk; | ||
99 | break; | ||
100 | default: | ||
101 | return -EINVAL; | ||
102 | } | ||
103 | |||
104 | if (IS_ERR(clk_ptr)) { | ||
105 | dev_err(dev, "%s: ERROR: %s not initialized!\n", __func__, | ||
106 | get_mclk_str(drvdata->mclk_sel)); | ||
107 | return -EIO; | ||
108 | } | ||
109 | |||
110 | status = clk_set_parent(drvdata->clk_ptr_intclk, clk_ptr); | ||
111 | if (status) | ||
112 | dev_err(dev, | ||
113 | "%s: ERROR: Setting intclk parent to %s failed (ret = %d)!", | ||
114 | __func__, get_mclk_str(drvdata->mclk_sel), status); | ||
115 | else | ||
116 | dev_dbg(dev, | ||
117 | "%s: intclk parent changed to %s.\n", | ||
118 | __func__, get_mclk_str(drvdata->mclk_sel)); | ||
119 | |||
120 | return status; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Control-events | ||
125 | */ | ||
126 | |||
127 | static int mclk_input_control_get(struct snd_kcontrol *kcontrol, | ||
128 | struct snd_ctl_elem_value *ucontrol) | ||
129 | { | ||
130 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
131 | struct mop500_ab8500_drvdata *drvdata = | ||
132 | snd_soc_card_get_drvdata(codec->card); | ||
133 | |||
134 | ucontrol->value.enumerated.item[0] = drvdata->mclk_sel; | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int mclk_input_control_put(struct snd_kcontrol *kcontrol, | ||
140 | struct snd_ctl_elem_value *ucontrol) | ||
141 | { | ||
142 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
143 | struct mop500_ab8500_drvdata *drvdata = | ||
144 | snd_soc_card_get_drvdata(codec->card); | ||
145 | unsigned int val = ucontrol->value.enumerated.item[0]; | ||
146 | |||
147 | if (val > (unsigned int)MCLK_ULPCLK) | ||
148 | return -EINVAL; | ||
149 | if (drvdata->mclk_sel == val) | ||
150 | return 0; | ||
151 | |||
152 | drvdata->mclk_sel = val; | ||
153 | |||
154 | return 1; | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | * Controls | ||
159 | */ | ||
160 | |||
161 | static struct snd_kcontrol_new mop500_ab8500_ctrls[] = { | ||
162 | SOC_ENUM_EXT("Master Clock Select", | ||
163 | soc_enum_mclk, | ||
164 | mclk_input_control_get, mclk_input_control_put), | ||
165 | /* Digital interface - Clocks */ | ||
166 | SOC_SINGLE("Digital Interface Master Generator Switch", | ||
167 | AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENMASTGEN, | ||
168 | 1, 0), | ||
169 | SOC_SINGLE("Digital Interface 0 Bit-clock Switch", | ||
170 | AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK0, | ||
171 | 1, 0), | ||
172 | SOC_SINGLE("Digital Interface 1 Bit-clock Switch", | ||
173 | AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK1, | ||
174 | 1, 0), | ||
175 | SOC_DAPM_PIN_SWITCH("Headset Left"), | ||
176 | SOC_DAPM_PIN_SWITCH("Headset Right"), | ||
177 | SOC_DAPM_PIN_SWITCH("Earpiece"), | ||
178 | SOC_DAPM_PIN_SWITCH("Speaker Left"), | ||
179 | SOC_DAPM_PIN_SWITCH("Speaker Right"), | ||
180 | SOC_DAPM_PIN_SWITCH("LineOut Left"), | ||
181 | SOC_DAPM_PIN_SWITCH("LineOut Right"), | ||
182 | SOC_DAPM_PIN_SWITCH("Vibra 1"), | ||
183 | SOC_DAPM_PIN_SWITCH("Vibra 2"), | ||
184 | SOC_DAPM_PIN_SWITCH("Mic 1"), | ||
185 | SOC_DAPM_PIN_SWITCH("Mic 2"), | ||
186 | SOC_DAPM_PIN_SWITCH("LineIn Left"), | ||
187 | SOC_DAPM_PIN_SWITCH("LineIn Right"), | ||
188 | SOC_DAPM_PIN_SWITCH("DMic 1"), | ||
189 | SOC_DAPM_PIN_SWITCH("DMic 2"), | ||
190 | SOC_DAPM_PIN_SWITCH("DMic 3"), | ||
191 | SOC_DAPM_PIN_SWITCH("DMic 4"), | ||
192 | SOC_DAPM_PIN_SWITCH("DMic 5"), | ||
193 | SOC_DAPM_PIN_SWITCH("DMic 6"), | ||
194 | }; | ||
195 | |||
196 | /* ASoC */ | ||
197 | |||
198 | int mop500_ab8500_startup(struct snd_pcm_substream *substream) | ||
199 | { | ||
200 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
201 | |||
202 | /* Set audio-clock source */ | ||
203 | return mop500_ab8500_set_mclk(rtd->card->dev, | ||
204 | snd_soc_card_get_drvdata(rtd->card)); | ||
205 | } | ||
206 | |||
207 | void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) | ||
208 | { | ||
209 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
210 | struct device *dev = rtd->card->dev; | ||
211 | |||
212 | dev_dbg(dev, "%s: Enter\n", __func__); | ||
213 | |||
214 | /* Reset slots configuration to default(s) */ | ||
215 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
216 | tx_slots = DEF_TX_SLOTS; | ||
217 | else | ||
218 | rx_slots = DEF_RX_SLOTS; | ||
219 | } | ||
220 | |||
221 | int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, | ||
222 | struct snd_pcm_hw_params *params) | ||
223 | { | ||
224 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
225 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
226 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
227 | struct device *dev = rtd->card->dev; | ||
228 | unsigned int fmt; | ||
229 | int channels, ret = 0, driver_mode, slots; | ||
230 | unsigned int sw_codec, sw_cpu; | ||
231 | bool is_playback; | ||
232 | |||
233 | dev_dbg(dev, "%s: Enter\n", __func__); | ||
234 | |||
235 | dev_dbg(dev, "%s: substream->pcm->name = %s\n" | ||
236 | "substream->pcm->id = %s.\n" | ||
237 | "substream->name = %s.\n" | ||
238 | "substream->number = %d.\n", | ||
239 | __func__, | ||
240 | substream->pcm->name, | ||
241 | substream->pcm->id, | ||
242 | substream->name, | ||
243 | substream->number); | ||
244 | |||
245 | channels = params_channels(params); | ||
246 | |||
247 | switch (params_format(params)) { | ||
248 | case SNDRV_PCM_FORMAT_S32_LE: | ||
249 | sw_cpu = 32; | ||
250 | break; | ||
251 | |||
252 | case SNDRV_PCM_FORMAT_S16_LE: | ||
253 | sw_cpu = 16; | ||
254 | break; | ||
255 | |||
256 | default: | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | |||
260 | /* Setup codec depending on driver-mode */ | ||
261 | if (channels == 8) | ||
262 | driver_mode = DRIVERMODE_CODEC_ONLY; | ||
263 | else | ||
264 | driver_mode = DRIVERMODE_NORMAL; | ||
265 | dev_dbg(dev, "%s: Driver-mode: %s.\n", __func__, | ||
266 | (driver_mode == DRIVERMODE_NORMAL) ? "NORMAL" : "CODEC_ONLY"); | ||
267 | |||
268 | /* Setup format */ | ||
269 | |||
270 | if (driver_mode == DRIVERMODE_NORMAL) { | ||
271 | fmt = SND_SOC_DAIFMT_DSP_A | | ||
272 | SND_SOC_DAIFMT_CBM_CFM | | ||
273 | SND_SOC_DAIFMT_NB_NF | | ||
274 | SND_SOC_DAIFMT_CONT; | ||
275 | } else { | ||
276 | fmt = SND_SOC_DAIFMT_DSP_A | | ||
277 | SND_SOC_DAIFMT_CBM_CFM | | ||
278 | SND_SOC_DAIFMT_NB_NF | | ||
279 | SND_SOC_DAIFMT_GATED; | ||
280 | } | ||
281 | |||
282 | ret = snd_soc_dai_set_fmt(codec_dai, fmt); | ||
283 | if (ret < 0) { | ||
284 | dev_err(dev, | ||
285 | "%s: ERROR: snd_soc_dai_set_fmt failed for codec_dai (ret = %d)!\n", | ||
286 | __func__, ret); | ||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | ret = snd_soc_dai_set_fmt(cpu_dai, fmt); | ||
291 | if (ret < 0) { | ||
292 | dev_err(dev, | ||
293 | "%s: ERROR: snd_soc_dai_set_fmt failed for cpu_dai (ret = %d)!\n", | ||
294 | __func__, ret); | ||
295 | return ret; | ||
296 | } | ||
297 | |||
298 | /* Setup TDM-slots */ | ||
299 | |||
300 | is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | ||
301 | switch (channels) { | ||
302 | case 1: | ||
303 | slots = 16; | ||
304 | tx_slots = (is_playback) ? TX_SLOT_MONO : 0; | ||
305 | rx_slots = (is_playback) ? 0 : RX_SLOT_MONO; | ||
306 | break; | ||
307 | case 2: | ||
308 | slots = 16; | ||
309 | tx_slots = (is_playback) ? TX_SLOT_STEREO : 0; | ||
310 | rx_slots = (is_playback) ? 0 : RX_SLOT_STEREO; | ||
311 | break; | ||
312 | case 8: | ||
313 | slots = 16; | ||
314 | tx_slots = (is_playback) ? TX_SLOT_8CH : 0; | ||
315 | rx_slots = (is_playback) ? 0 : RX_SLOT_8CH; | ||
316 | break; | ||
317 | default: | ||
318 | return -EINVAL; | ||
319 | } | ||
320 | |||
321 | if (driver_mode == DRIVERMODE_NORMAL) | ||
322 | sw_codec = sw_cpu; | ||
323 | else | ||
324 | sw_codec = 20; | ||
325 | |||
326 | dev_dbg(dev, "%s: CPU-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, | ||
327 | tx_slots, rx_slots); | ||
328 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_slots, rx_slots, slots, | ||
329 | sw_cpu); | ||
330 | if (ret) | ||
331 | return ret; | ||
332 | |||
333 | dev_dbg(dev, "%s: CODEC-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, | ||
334 | tx_slots, rx_slots); | ||
335 | ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_slots, rx_slots, slots, | ||
336 | sw_codec); | ||
337 | if (ret) | ||
338 | return ret; | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | struct snd_soc_ops mop500_ab8500_ops[] = { | ||
344 | { | ||
345 | .hw_params = mop500_ab8500_hw_params, | ||
346 | .startup = mop500_ab8500_startup, | ||
347 | .shutdown = mop500_ab8500_shutdown, | ||
348 | } | ||
349 | }; | ||
350 | |||
351 | int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd) | ||
352 | { | ||
353 | struct snd_soc_codec *codec = rtd->codec; | ||
354 | struct device *dev = rtd->card->dev; | ||
355 | struct mop500_ab8500_drvdata *drvdata; | ||
356 | int ret; | ||
357 | |||
358 | dev_dbg(dev, "%s Enter.\n", __func__); | ||
359 | |||
360 | /* Create driver private-data struct */ | ||
361 | drvdata = devm_kzalloc(dev, sizeof(struct mop500_ab8500_drvdata), | ||
362 | GFP_KERNEL); | ||
363 | snd_soc_card_set_drvdata(rtd->card, drvdata); | ||
364 | |||
365 | /* Setup clocks */ | ||
366 | |||
367 | drvdata->clk_ptr_sysclk = clk_get(dev, "sysclk"); | ||
368 | if (IS_ERR(drvdata->clk_ptr_sysclk)) | ||
369 | dev_warn(dev, "%s: WARNING: clk_get failed for 'sysclk'!\n", | ||
370 | __func__); | ||
371 | drvdata->clk_ptr_ulpclk = clk_get(dev, "ulpclk"); | ||
372 | if (IS_ERR(drvdata->clk_ptr_ulpclk)) | ||
373 | dev_warn(dev, "%s: WARNING: clk_get failed for 'ulpclk'!\n", | ||
374 | __func__); | ||
375 | drvdata->clk_ptr_intclk = clk_get(dev, "intclk"); | ||
376 | if (IS_ERR(drvdata->clk_ptr_intclk)) | ||
377 | dev_warn(dev, "%s: WARNING: clk_get failed for 'intclk'!\n", | ||
378 | __func__); | ||
379 | |||
380 | /* Set intclk default parent to ulpclk */ | ||
381 | drvdata->mclk_sel = MCLK_ULPCLK; | ||
382 | ret = mop500_ab8500_set_mclk(dev, drvdata); | ||
383 | if (ret < 0) | ||
384 | dev_warn(dev, "%s: WARNING: mop500_ab8500_set_mclk!\n", | ||
385 | __func__); | ||
386 | |||
387 | drvdata->mclk_sel = MCLK_ULPCLK; | ||
388 | |||
389 | /* Add controls */ | ||
390 | ret = snd_soc_add_codec_controls(codec, mop500_ab8500_ctrls, | ||
391 | ARRAY_SIZE(mop500_ab8500_ctrls)); | ||
392 | if (ret < 0) { | ||
393 | pr_err("%s: Failed to add machine-controls (%d)!\n", | ||
394 | __func__, ret); | ||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | ret = snd_soc_dapm_disable_pin(&codec->dapm, "Earpiece"); | ||
399 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Speaker Left"); | ||
400 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Speaker Right"); | ||
401 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineOut Left"); | ||
402 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineOut Right"); | ||
403 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Vibra 1"); | ||
404 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Vibra 2"); | ||
405 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Mic 1"); | ||
406 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Mic 2"); | ||
407 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineIn Left"); | ||
408 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineIn Right"); | ||
409 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 1"); | ||
410 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 2"); | ||
411 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 3"); | ||
412 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 4"); | ||
413 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 5"); | ||
414 | ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 6"); | ||
415 | |||
416 | return ret; | ||
417 | } | ||
418 | |||
419 | void mop500_ab8500_remove(struct snd_soc_card *card) | ||
420 | { | ||
421 | struct mop500_ab8500_drvdata *drvdata = snd_soc_card_get_drvdata(card); | ||
422 | |||
423 | if (drvdata->clk_ptr_sysclk != NULL) | ||
424 | clk_put(drvdata->clk_ptr_sysclk); | ||
425 | if (drvdata->clk_ptr_ulpclk != NULL) | ||
426 | clk_put(drvdata->clk_ptr_ulpclk); | ||
427 | if (drvdata->clk_ptr_intclk != NULL) | ||
428 | clk_put(drvdata->clk_ptr_intclk); | ||
429 | |||
430 | snd_soc_card_set_drvdata(card, drvdata); | ||
431 | } | ||
diff --git a/sound/soc/ux500/mop500_ab8500.h b/sound/soc/ux500/mop500_ab8500.h new file mode 100644 index 000000000000..cca5b33964b6 --- /dev/null +++ b/sound/soc/ux500/mop500_ab8500.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2012 | ||
3 | * | ||
4 | * Author: Ola Lilja <ola.o.lilja@stericsson.com> | ||
5 | * for ST-Ericsson. | ||
6 | * | ||
7 | * License terms: | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as published | ||
11 | * by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #ifndef MOP500_AB8500_H | ||
15 | #define MOP500_AB8500_H | ||
16 | |||
17 | extern struct snd_soc_ops mop500_ab8500_ops[]; | ||
18 | |||
19 | int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *runtime); | ||
20 | void mop500_ab8500_remove(struct snd_soc_card *card); | ||
21 | |||
22 | #endif | ||
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 93c6c40e724c..62ac0285bfaf 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c | |||
@@ -840,4 +840,4 @@ static struct platform_driver msp_i2s_driver = { | |||
840 | }; | 840 | }; |
841 | module_platform_driver(msp_i2s_driver); | 841 | module_platform_driver(msp_i2s_driver); |
842 | 842 | ||
843 | MODULE_LICENSE("GPLv2"); | 843 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 496dec10c96e..ee14d2dac2f5 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c | |||
@@ -739,4 +739,4 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev, | |||
739 | devm_kfree(&pdev->dev, msp); | 739 | devm_kfree(&pdev->dev, msp); |
740 | } | 740 | } |
741 | 741 | ||
742 | MODULE_LICENSE("GPLv2"); | 742 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c new file mode 100644 index 000000000000..1a04e248453c --- /dev/null +++ b/sound/soc/ux500/ux500_pcm.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2012 | ||
3 | * | ||
4 | * Author: Ola Lilja <ola.o.lilja@stericsson.com>, | ||
5 | * Roger Nilsson <roger.xr.nilsson@stericsson.com> | ||
6 | * for ST-Ericsson. | ||
7 | * | ||
8 | * License terms: | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as published | ||
12 | * by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <asm/page.h> | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/dmaengine.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include <plat/ste_dma40.h> | ||
23 | |||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/dmaengine_pcm.h> | ||
28 | |||
29 | #include "ux500_msp_i2s.h" | ||
30 | #include "ux500_pcm.h" | ||
31 | |||
32 | static struct snd_pcm_hardware ux500_pcm_hw_playback = { | ||
33 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
34 | SNDRV_PCM_INFO_MMAP | | ||
35 | SNDRV_PCM_INFO_RESUME | | ||
36 | SNDRV_PCM_INFO_PAUSE, | ||
37 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
38 | SNDRV_PCM_FMTBIT_U16_LE | | ||
39 | SNDRV_PCM_FMTBIT_S16_BE | | ||
40 | SNDRV_PCM_FMTBIT_U16_BE, | ||
41 | .rates = SNDRV_PCM_RATE_KNOT, | ||
42 | .rate_min = UX500_PLATFORM_MIN_RATE_PLAYBACK, | ||
43 | .rate_max = UX500_PLATFORM_MAX_RATE_PLAYBACK, | ||
44 | .channels_min = UX500_PLATFORM_MIN_CHANNELS, | ||
45 | .channels_max = UX500_PLATFORM_MAX_CHANNELS, | ||
46 | .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, | ||
47 | .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN, | ||
48 | .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX, | ||
49 | .periods_min = UX500_PLATFORM_PERIODS_MIN, | ||
50 | .periods_max = UX500_PLATFORM_PERIODS_MAX, | ||
51 | }; | ||
52 | |||
53 | static struct snd_pcm_hardware ux500_pcm_hw_capture = { | ||
54 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
55 | SNDRV_PCM_INFO_MMAP | | ||
56 | SNDRV_PCM_INFO_RESUME | | ||
57 | SNDRV_PCM_INFO_PAUSE, | ||
58 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
59 | SNDRV_PCM_FMTBIT_U16_LE | | ||
60 | SNDRV_PCM_FMTBIT_S16_BE | | ||
61 | SNDRV_PCM_FMTBIT_U16_BE, | ||
62 | .rates = SNDRV_PCM_RATE_KNOT, | ||
63 | .rate_min = UX500_PLATFORM_MIN_RATE_CAPTURE, | ||
64 | .rate_max = UX500_PLATFORM_MAX_RATE_CAPTURE, | ||
65 | .channels_min = UX500_PLATFORM_MIN_CHANNELS, | ||
66 | .channels_max = UX500_PLATFORM_MAX_CHANNELS, | ||
67 | .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, | ||
68 | .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN, | ||
69 | .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX, | ||
70 | .periods_min = UX500_PLATFORM_PERIODS_MIN, | ||
71 | .periods_max = UX500_PLATFORM_PERIODS_MAX, | ||
72 | }; | ||
73 | |||
74 | static void ux500_pcm_dma_hw_free(struct device *dev, | ||
75 | struct snd_pcm_substream *substream) | ||
76 | { | ||
77 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
78 | struct snd_dma_buffer *buf = runtime->dma_buffer_p; | ||
79 | |||
80 | if (runtime->dma_area == NULL) | ||
81 | return; | ||
82 | |||
83 | if (buf != &substream->dma_buffer) { | ||
84 | dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, | ||
85 | buf->addr); | ||
86 | kfree(runtime->dma_buffer_p); | ||
87 | } | ||
88 | |||
89 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
90 | } | ||
91 | |||
92 | static int ux500_pcm_open(struct snd_pcm_substream *substream) | ||
93 | { | ||
94 | int stream_id = substream->pstr->stream; | ||
95 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
96 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
97 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
98 | struct device *dev = dai->dev; | ||
99 | int ret; | ||
100 | struct ux500_msp_dma_params *dma_params; | ||
101 | u16 per_data_width, mem_data_width; | ||
102 | struct stedma40_chan_cfg *dma_cfg; | ||
103 | |||
104 | dev_dbg(dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id, | ||
105 | snd_pcm_stream_str(substream)); | ||
106 | |||
107 | dev_dbg(dev, "%s: Set runtime hwparams.\n", __func__); | ||
108 | if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) | ||
109 | snd_soc_set_runtime_hwparams(substream, | ||
110 | &ux500_pcm_hw_playback); | ||
111 | else | ||
112 | snd_soc_set_runtime_hwparams(substream, | ||
113 | &ux500_pcm_hw_capture); | ||
114 | |||
115 | /* ensure that buffer size is a multiple of period size */ | ||
116 | ret = snd_pcm_hw_constraint_integer(runtime, | ||
117 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
118 | if (ret < 0) { | ||
119 | dev_err(dev, "%s: Error: snd_pcm_hw_constraints failed (%d)\n", | ||
120 | __func__, ret); | ||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | dev_dbg(dev, "%s: Set hw-struct for %s.\n", __func__, | ||
125 | snd_pcm_stream_str(substream)); | ||
126 | runtime->hw = (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
127 | ux500_pcm_hw_playback : ux500_pcm_hw_capture; | ||
128 | |||
129 | mem_data_width = STEDMA40_HALFWORD_WIDTH; | ||
130 | |||
131 | dma_params = snd_soc_dai_get_dma_data(dai, substream); | ||
132 | switch (dma_params->data_size) { | ||
133 | case 32: | ||
134 | per_data_width = STEDMA40_WORD_WIDTH; | ||
135 | break; | ||
136 | case 16: | ||
137 | per_data_width = STEDMA40_HALFWORD_WIDTH; | ||
138 | break; | ||
139 | case 8: | ||
140 | per_data_width = STEDMA40_BYTE_WIDTH; | ||
141 | break; | ||
142 | default: | ||
143 | per_data_width = STEDMA40_WORD_WIDTH; | ||
144 | dev_warn(rtd->platform->dev, | ||
145 | "%s: Unknown data-size (%d)! Assuming 32 bits.\n", | ||
146 | __func__, dma_params->data_size); | ||
147 | } | ||
148 | |||
149 | dma_cfg = dma_params->dma_cfg; | ||
150 | |||
151 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
152 | dma_cfg->src_info.data_width = mem_data_width; | ||
153 | dma_cfg->dst_info.data_width = per_data_width; | ||
154 | } else { | ||
155 | dma_cfg->src_info.data_width = per_data_width; | ||
156 | dma_cfg->dst_info.data_width = mem_data_width; | ||
157 | } | ||
158 | |||
159 | |||
160 | ret = snd_dmaengine_pcm_open(substream, stedma40_filter, dma_cfg); | ||
161 | if (ret) { | ||
162 | dev_dbg(dai->dev, | ||
163 | "%s: ERROR: snd_dmaengine_pcm_open failed (%d)!\n", | ||
164 | __func__, ret); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | snd_dmaengine_pcm_set_data(substream, dma_cfg); | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static int ux500_pcm_close(struct snd_pcm_substream *substream) | ||
174 | { | ||
175 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
176 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
177 | |||
178 | dev_dbg(dai->dev, "%s: Enter\n", __func__); | ||
179 | |||
180 | snd_dmaengine_pcm_close(substream); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int ux500_pcm_hw_params(struct snd_pcm_substream *substream, | ||
186 | struct snd_pcm_hw_params *hw_params) | ||
187 | { | ||
188 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
189 | struct snd_dma_buffer *buf = runtime->dma_buffer_p; | ||
190 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
191 | int ret = 0; | ||
192 | int size; | ||
193 | |||
194 | dev_dbg(rtd->platform->dev, "%s: Enter\n", __func__); | ||
195 | |||
196 | size = params_buffer_bytes(hw_params); | ||
197 | |||
198 | if (buf) { | ||
199 | if (buf->bytes >= size) | ||
200 | goto out; | ||
201 | ux500_pcm_dma_hw_free(NULL, substream); | ||
202 | } | ||
203 | |||
204 | if (substream->dma_buffer.area != NULL && | ||
205 | substream->dma_buffer.bytes >= size) { | ||
206 | buf = &substream->dma_buffer; | ||
207 | } else { | ||
208 | buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); | ||
209 | if (!buf) | ||
210 | goto nomem; | ||
211 | |||
212 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
213 | buf->dev.dev = NULL; | ||
214 | buf->area = dma_alloc_coherent(NULL, size, &buf->addr, | ||
215 | GFP_KERNEL); | ||
216 | buf->bytes = size; | ||
217 | buf->private_data = NULL; | ||
218 | |||
219 | if (!buf->area) | ||
220 | goto free; | ||
221 | } | ||
222 | snd_pcm_set_runtime_buffer(substream, buf); | ||
223 | ret = 1; | ||
224 | out: | ||
225 | runtime->dma_bytes = size; | ||
226 | return ret; | ||
227 | |||
228 | free: | ||
229 | kfree(buf); | ||
230 | nomem: | ||
231 | return -ENOMEM; | ||
232 | } | ||
233 | |||
234 | static int ux500_pcm_hw_free(struct snd_pcm_substream *substream) | ||
235 | { | ||
236 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
237 | |||
238 | dev_dbg(rtd->platform->dev, "%s: Enter\n", __func__); | ||
239 | |||
240 | ux500_pcm_dma_hw_free(NULL, substream); | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int ux500_pcm_mmap(struct snd_pcm_substream *substream, | ||
246 | struct vm_area_struct *vma) | ||
247 | { | ||
248 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
249 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
250 | |||
251 | dev_dbg(rtd->platform->dev, "%s: Enter.\n", __func__); | ||
252 | |||
253 | return dma_mmap_coherent(NULL, vma, runtime->dma_area, | ||
254 | runtime->dma_addr, runtime->dma_bytes); | ||
255 | } | ||
256 | |||
257 | static struct snd_pcm_ops ux500_pcm_ops = { | ||
258 | .open = ux500_pcm_open, | ||
259 | .close = ux500_pcm_close, | ||
260 | .ioctl = snd_pcm_lib_ioctl, | ||
261 | .hw_params = ux500_pcm_hw_params, | ||
262 | .hw_free = ux500_pcm_hw_free, | ||
263 | .trigger = snd_dmaengine_pcm_trigger, | ||
264 | .pointer = snd_dmaengine_pcm_pointer_no_residue, | ||
265 | .mmap = ux500_pcm_mmap | ||
266 | }; | ||
267 | |||
268 | int ux500_pcm_new(struct snd_soc_pcm_runtime *rtd) | ||
269 | { | ||
270 | struct snd_pcm *pcm = rtd->pcm; | ||
271 | |||
272 | dev_dbg(rtd->platform->dev, "%s: Enter (id = '%s').\n", __func__, | ||
273 | pcm->id); | ||
274 | |||
275 | pcm->info_flags = 0; | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static struct snd_soc_platform_driver ux500_pcm_soc_drv = { | ||
281 | .ops = &ux500_pcm_ops, | ||
282 | .pcm_new = ux500_pcm_new, | ||
283 | }; | ||
284 | |||
285 | static int __devexit ux500_pcm_drv_probe(struct platform_device *pdev) | ||
286 | { | ||
287 | int ret; | ||
288 | |||
289 | ret = snd_soc_register_platform(&pdev->dev, &ux500_pcm_soc_drv); | ||
290 | if (ret < 0) { | ||
291 | dev_err(&pdev->dev, | ||
292 | "%s: ERROR: Failed to register platform '%s' (%d)!\n", | ||
293 | __func__, pdev->name, ret); | ||
294 | return ret; | ||
295 | } | ||
296 | |||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int __devinit ux500_pcm_drv_remove(struct platform_device *pdev) | ||
301 | { | ||
302 | snd_soc_unregister_platform(&pdev->dev); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static struct platform_driver ux500_pcm_driver = { | ||
308 | .driver = { | ||
309 | .name = "ux500-pcm", | ||
310 | .owner = THIS_MODULE, | ||
311 | }, | ||
312 | |||
313 | .probe = ux500_pcm_drv_probe, | ||
314 | .remove = __devexit_p(ux500_pcm_drv_remove), | ||
315 | }; | ||
316 | module_platform_driver(ux500_pcm_driver); | ||
317 | |||
318 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/ux500/ux500_pcm.h b/sound/soc/ux500/ux500_pcm.h new file mode 100644 index 000000000000..77ed44d371e9 --- /dev/null +++ b/sound/soc/ux500/ux500_pcm.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2012 | ||
3 | * | ||
4 | * Author: Ola Lilja <ola.o.lilja@stericsson.com>, | ||
5 | * Roger Nilsson <roger.xr.nilsson@stericsson.com> | ||
6 | * for ST-Ericsson. | ||
7 | * | ||
8 | * License terms: | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as published | ||
12 | * by the Free Software Foundation. | ||
13 | */ | ||
14 | #ifndef UX500_PCM_H | ||
15 | #define UX500_PCM_H | ||
16 | |||
17 | #include <asm/page.h> | ||
18 | |||
19 | #include <linux/workqueue.h> | ||
20 | |||
21 | #define UX500_PLATFORM_MIN_RATE_PLAYBACK 8000 | ||
22 | #define UX500_PLATFORM_MAX_RATE_PLAYBACK 48000 | ||
23 | #define UX500_PLATFORM_MIN_RATE_CAPTURE 8000 | ||
24 | #define UX500_PLATFORM_MAX_RATE_CAPTURE 48000 | ||
25 | |||
26 | #define UX500_PLATFORM_MIN_CHANNELS 1 | ||
27 | #define UX500_PLATFORM_MAX_CHANNELS 8 | ||
28 | |||
29 | #define UX500_PLATFORM_PERIODS_BYTES_MIN 128 | ||
30 | #define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE) | ||
31 | #define UX500_PLATFORM_PERIODS_MIN 2 | ||
32 | #define UX500_PLATFORM_PERIODS_MAX 48 | ||
33 | #define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE) | ||
34 | |||
35 | #endif | ||
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 64aed432ae22..7da0d0aa72cb 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c | |||
@@ -485,7 +485,7 @@ static int __devinit snd_probe(struct usb_interface *intf, | |||
485 | const struct usb_device_id *id) | 485 | const struct usb_device_id *id) |
486 | { | 486 | { |
487 | int ret; | 487 | int ret; |
488 | struct snd_card *card; | 488 | struct snd_card *card = NULL; |
489 | struct usb_device *device = interface_to_usbdev(intf); | 489 | struct usb_device *device = interface_to_usbdev(intf); |
490 | 490 | ||
491 | ret = create_card(device, intf, &card); | 491 | ret = create_card(device, intf, &card); |
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 41f4b6911920..690000db0ec0 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -42,6 +42,13 @@ | |||
42 | 42 | ||
43 | extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; | 43 | extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; |
44 | 44 | ||
45 | struct std_mono_table { | ||
46 | unsigned int unitid, control, cmask; | ||
47 | int val_type; | ||
48 | const char *name; | ||
49 | snd_kcontrol_tlv_rw_t *tlv_callback; | ||
50 | }; | ||
51 | |||
45 | /* private_free callback */ | 52 | /* private_free callback */ |
46 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | 53 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) |
47 | { | 54 | { |
@@ -114,6 +121,25 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, | |||
114 | } | 121 | } |
115 | 122 | ||
116 | /* | 123 | /* |
124 | * Create a set of standard UAC controls from a table | ||
125 | */ | ||
126 | static int snd_create_std_mono_table(struct usb_mixer_interface *mixer, | ||
127 | struct std_mono_table *t) | ||
128 | { | ||
129 | int err; | ||
130 | |||
131 | while (t->name != NULL) { | ||
132 | err = snd_create_std_mono_ctl(mixer, t->unitid, t->control, | ||
133 | t->cmask, t->val_type, t->name, t->tlv_callback); | ||
134 | if (err < 0) | ||
135 | return err; | ||
136 | t++; | ||
137 | } | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | /* | ||
117 | * Sound Blaster remote control configuration | 143 | * Sound Blaster remote control configuration |
118 | * | 144 | * |
119 | * format of remote control data: | 145 | * format of remote control data: |
@@ -916,61 +942,6 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) | |||
916 | return 0; | 942 | return 0; |
917 | } | 943 | } |
918 | 944 | ||
919 | |||
920 | /* | ||
921 | * Create mixer for Electrix Ebox-44 | ||
922 | * | ||
923 | * The mixer units from this device are corrupt, and even where they | ||
924 | * are valid they presents mono controls as L and R channels of | ||
925 | * stereo. So we create a good mixer in code. | ||
926 | */ | ||
927 | |||
928 | static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) | ||
929 | { | ||
930 | int err; | ||
931 | |||
932 | err = snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, | ||
933 | "Headphone Playback Switch", NULL); | ||
934 | if (err < 0) | ||
935 | return err; | ||
936 | err = snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16, | ||
937 | "Headphone A Mix Playback Volume", NULL); | ||
938 | if (err < 0) | ||
939 | return err; | ||
940 | err = snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16, | ||
941 | "Headphone B Mix Playback Volume", NULL); | ||
942 | if (err < 0) | ||
943 | return err; | ||
944 | |||
945 | err = snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, | ||
946 | "Output Playback Switch", NULL); | ||
947 | if (err < 0) | ||
948 | return err; | ||
949 | err = snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16, | ||
950 | "Output A Playback Volume", NULL); | ||
951 | if (err < 0) | ||
952 | return err; | ||
953 | err = snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16, | ||
954 | "Output B Playback Volume", NULL); | ||
955 | if (err < 0) | ||
956 | return err; | ||
957 | |||
958 | err = snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, | ||
959 | "Input Capture Switch", NULL); | ||
960 | if (err < 0) | ||
961 | return err; | ||
962 | err = snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16, | ||
963 | "Input A Capture Volume", NULL); | ||
964 | if (err < 0) | ||
965 | return err; | ||
966 | err = snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16, | ||
967 | "Input B Capture Volume", NULL); | ||
968 | if (err < 0) | ||
969 | return err; | ||
970 | |||
971 | return 0; | ||
972 | } | ||
973 | |||
974 | void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | 945 | void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, |
975 | unsigned char samplerate_id) | 946 | unsigned char samplerate_id) |
976 | { | 947 | { |
@@ -990,6 +961,81 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | |||
990 | } | 961 | } |
991 | } | 962 | } |
992 | 963 | ||
964 | /* | ||
965 | * The mixer units for Ebox-44 are corrupt, and even where they | ||
966 | * are valid they presents mono controls as L and R channels of | ||
967 | * stereo. So we provide a good mixer here. | ||
968 | */ | ||
969 | struct std_mono_table ebox44_table[] = { | ||
970 | { | ||
971 | .unitid = 4, | ||
972 | .control = 1, | ||
973 | .cmask = 0x0, | ||
974 | .val_type = USB_MIXER_INV_BOOLEAN, | ||
975 | .name = "Headphone Playback Switch" | ||
976 | }, | ||
977 | { | ||
978 | .unitid = 4, | ||
979 | .control = 2, | ||
980 | .cmask = 0x1, | ||
981 | .val_type = USB_MIXER_S16, | ||
982 | .name = "Headphone A Mix Playback Volume" | ||
983 | }, | ||
984 | { | ||
985 | .unitid = 4, | ||
986 | .control = 2, | ||
987 | .cmask = 0x2, | ||
988 | .val_type = USB_MIXER_S16, | ||
989 | .name = "Headphone B Mix Playback Volume" | ||
990 | }, | ||
991 | |||
992 | { | ||
993 | .unitid = 7, | ||
994 | .control = 1, | ||
995 | .cmask = 0x0, | ||
996 | .val_type = USB_MIXER_INV_BOOLEAN, | ||
997 | .name = "Output Playback Switch" | ||
998 | }, | ||
999 | { | ||
1000 | .unitid = 7, | ||
1001 | .control = 2, | ||
1002 | .cmask = 0x1, | ||
1003 | .val_type = USB_MIXER_S16, | ||
1004 | .name = "Output A Playback Volume" | ||
1005 | }, | ||
1006 | { | ||
1007 | .unitid = 7, | ||
1008 | .control = 2, | ||
1009 | .cmask = 0x2, | ||
1010 | .val_type = USB_MIXER_S16, | ||
1011 | .name = "Output B Playback Volume" | ||
1012 | }, | ||
1013 | |||
1014 | { | ||
1015 | .unitid = 10, | ||
1016 | .control = 1, | ||
1017 | .cmask = 0x0, | ||
1018 | .val_type = USB_MIXER_INV_BOOLEAN, | ||
1019 | .name = "Input Capture Switch" | ||
1020 | }, | ||
1021 | { | ||
1022 | .unitid = 10, | ||
1023 | .control = 2, | ||
1024 | .cmask = 0x1, | ||
1025 | .val_type = USB_MIXER_S16, | ||
1026 | .name = "Input A Capture Volume" | ||
1027 | }, | ||
1028 | { | ||
1029 | .unitid = 10, | ||
1030 | .control = 2, | ||
1031 | .cmask = 0x2, | ||
1032 | .val_type = USB_MIXER_S16, | ||
1033 | .name = "Input B Capture Volume" | ||
1034 | }, | ||
1035 | |||
1036 | {} | ||
1037 | }; | ||
1038 | |||
993 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | 1039 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) |
994 | { | 1040 | { |
995 | int err = 0; | 1041 | int err = 0; |
@@ -1035,7 +1081,8 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | |||
1035 | break; | 1081 | break; |
1036 | 1082 | ||
1037 | case USB_ID(0x200c, 0x1018): /* Electrix Ebox-44 */ | 1083 | case USB_ID(0x200c, 0x1018): /* Electrix Ebox-44 */ |
1038 | err = snd_ebox44_create_mixer(mixer); | 1084 | /* detection is disabled in mixer_maps.c */ |
1085 | err = snd_create_std_mono_table(mixer, ebox44_table); | ||
1039 | break; | 1086 | break; |
1040 | } | 1087 | } |
1041 | 1088 | ||