Changeset 615 for GPL/branches/uniaud32-next/alsa-kernel/drivers/dummy.c
- Timestamp:
- Jan 1, 2021, 5:31:48 AM (5 years ago)
- Location:
- GPL/branches/uniaud32-next
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
GPL/branches/uniaud32-next/alsa-kernel/drivers/dummy.c
r612 r615 1 // SPDX-License-Identifier: GPL-2.0-or-later 1 2 /* 2 3 * Dummy soundcard 3 4 * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 4 *5 * This program is free software; you can redistribute it and/or modify6 * it under the terms of the GNU General Public License as published by7 * the Free Software Foundation; either version 2 of the License, or8 * (at your option) any later version.9 *10 * This program is distributed in the hope that it will be useful,11 * but WITHOUT ANY WARRANTY; without even the implied warranty of12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13 * GNU General Public License for more details.14 *15 * You should have received a copy of the GNU General Public License16 * along with this program; if not, write to the Free Software17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA18 *19 5 */ 20 6 … … 61 47 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 62 48 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 63 static intenable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};49 static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; 64 50 static char *model[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = NULL}; 65 51 static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; … … 67 53 //static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; 68 54 #ifdef CONFIG_HIGH_RES_TIMERS 69 static inthrtimer = 1;55 static bool hrtimer = 1; 70 56 #endif 71 static intfake_buffer = 1;57 static bool fake_buffer = 1; 72 58 73 59 module_param_array(index, int, NULL, 0444); … … 138 124 int mixer_volume[MIXER_ADDR_LAST+1][2]; 139 125 int capture_source[MIXER_ADDR_LAST+1][2]; 126 int iobox; 127 struct snd_kcontrol *cd_volume_ctl; 128 struct snd_kcontrol *cd_switch_ctl; 140 129 }; 141 130 … … 156 145 } 157 146 158 st ruct dummy_model model_emu10k1 = {147 static struct dummy_model model_emu10k1 = { 159 148 .name = "emu10k1", 160 149 .playback_constraints = emu10k1_playback_constraints, … … 162 151 }; 163 152 164 st ruct dummy_model model_rme9652 = {153 static struct dummy_model model_rme9652 = { 165 154 .name = "rme9652", 166 155 .buffer_bytes_max = 26 * 64 * 1024, … … 172 161 }; 173 162 174 st ruct dummy_model model_ice1712 = {163 static struct dummy_model model_ice1712 = { 175 164 .name = "ice1712", 176 165 .buffer_bytes_max = 256 * 1024, … … 182 171 }; 183 172 184 st ruct dummy_model model_uda1341 = {173 static struct dummy_model model_uda1341 = { 185 174 .name = "uda1341", 186 175 .buffer_bytes_max = 16380, … … 192 181 }; 193 182 194 st ruct dummy_model model_ac97 = {183 static struct dummy_model model_ac97 = { 195 184 .name = "ac97", 196 185 .formats = SNDRV_PCM_FMTBIT_S16_LE, … … 202 191 }; 203 192 204 st ruct dummy_model model_ca0106 = {193 static struct dummy_model model_ca0106 = { 205 194 .name = "ca0106", 206 195 .formats = SNDRV_PCM_FMTBIT_S16_LE, … … 216 205 }; 217 206 218 st ruct dummy_model *dummy_models[] = {207 static struct dummy_model *dummy_models[] = { 219 208 &model_emu10k1, 220 209 &model_rme9652, … … 247 236 static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm) 248 237 { 249 dpcm->timer.expires = jiffies + 250 (dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate; 251 add_timer(&dpcm->timer); 238 mod_timer(&dpcm->timer, jiffies + 239 (dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate); 252 240 } 253 241 … … 305 293 } 306 294 307 static void dummy_systimer_callback( unsigned long data)308 { 309 struct dummy_systimer_pcm *dpcm = (struct dummy_systimer_pcm *)data;295 static void dummy_systimer_callback(struct timer_list *t) 296 { 297 struct dummy_systimer_pcm *dpcm = from_timer(dpcm, t, timer); 310 298 unsigned long flags; 311 299 int elapsed = 0; … … 342 330 return -ENOMEM; 343 331 substream->runtime->private_data = dpcm; 344 init_timer(&dpcm->timer); 345 dpcm->timer.data = (unsigned long) dpcm; 346 dpcm->timer.function = dummy_systimer_callback; 332 timer_setup(&dpcm->timer, dummy_systimer_callback, 0); 347 333 spin_lock_init(&dpcm->lock); 348 334 dpcm->substream = substream; … … 355 341 } 356 342 357 static struct dummy_timer_ops dummy_systimer_ops = {343 static const struct dummy_timer_ops dummy_systimer_ops = { 358 344 .create = dummy_systimer_create, 359 345 .free = dummy_systimer_free, … … 376 362 atomic_t running; 377 363 struct hrtimer timer; 378 struct tasklet_struct tasklet;379 364 struct snd_pcm_substream *substream; 380 365 }; 381 382 static void dummy_hrtimer_pcm_elapsed(unsigned long priv)383 {384 struct dummy_hrtimer_pcm *dpcm = (struct dummy_hrtimer_pcm *)priv;385 if (atomic_read(&dpcm->running))386 snd_pcm_period_elapsed(dpcm->substream);387 }388 366 389 367 static enum hrtimer_restart dummy_hrtimer_callback(struct hrtimer *timer) … … 394 372 if (!atomic_read(&dpcm->running)) 395 373 return HRTIMER_NORESTART; 396 tasklet_schedule(&dpcm->tasklet); 374 /* 375 * In cases of XRUN and draining, this calls .trigger to stop PCM 376 * substream. 377 */ 378 snd_pcm_period_elapsed(dpcm->substream); 379 if (!atomic_read(&dpcm->running)) 380 return HRTIMER_NORESTART; 381 397 382 hrtimer_forward_now(timer, dpcm->period_time); 398 383 return HRTIMER_RESTART; … … 404 389 405 390 dpcm->base_time = hrtimer_cb_get_time(&dpcm->timer); 406 hrtimer_start(&dpcm->timer, dpcm->period_time, HRTIMER_MODE_REL );391 hrtimer_start(&dpcm->timer, dpcm->period_time, HRTIMER_MODE_REL_SOFT); 407 392 atomic_set(&dpcm->running, 1); 408 393 return 0; … … 414 399 415 400 atomic_set(&dpcm->running, 0); 401 if (!hrtimer_callback_running(&dpcm->timer)) 402 hrtimer_cancel(&dpcm->timer); 403 return 0; 404 } 405 406 static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm) 407 { 416 408 hrtimer_cancel(&dpcm->timer); 417 return 0;418 }419 420 static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm)421 {422 hrtimer_cancel(&dpcm->timer);423 tasklet_kill(&dpcm->tasklet);424 409 } 425 410 … … 466 451 return -ENOMEM; 467 452 substream->runtime->private_data = dpcm; 468 hrtimer_init(&dpcm->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );453 hrtimer_init(&dpcm->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); 469 454 dpcm->timer.function = dummy_hrtimer_callback; 470 455 dpcm->substream = substream; 471 456 atomic_set(&dpcm->running, 0); 472 tasklet_init(&dpcm->tasklet, dummy_hrtimer_pcm_elapsed,473 (unsigned long)dpcm);474 457 return 0; 475 458 } … … 482 465 } 483 466 484 static struct dummy_timer_ops dummy_hrtimer_ops = {467 static const struct dummy_timer_ops dummy_hrtimer_ops = { 485 468 .create = dummy_hrtimer_create, 486 469 .free = dummy_hrtimer_free, … … 520 503 } 521 504 522 static struct snd_pcm_hardware dummy_pcm_hardware = {505 static const struct snd_pcm_hardware dummy_pcm_hardware = { 523 506 .info = (SNDRV_PCM_INFO_MMAP | 524 507 SNDRV_PCM_INFO_INTERLEAVED | … … 644 627 645 628 static int dummy_pcm_copy(struct snd_pcm_substream *substream, 646 int channel, snd_pcm_uframes_tpos,647 void __user *dst, snd_pcm_uframes_t count)629 int channel, unsigned long pos, 630 void __user *dst, unsigned long bytes) 648 631 { 649 632 return 0; /* do nothing */ 650 633 } 651 634 635 static int dummy_pcm_copy_kernel(struct snd_pcm_substream *substream, 636 int channel, unsigned long pos, 637 void *dst, unsigned long bytes) 638 { 639 return 0; /* do nothing */ 640 } 641 652 642 static int dummy_pcm_silence(struct snd_pcm_substream *substream, 653 int channel, snd_pcm_uframes_tpos,654 snd_pcm_uframes_t count)643 int channel, unsigned long pos, 644 unsigned long bytes) 655 645 { 656 646 return 0; /* do nothing */ … … 683 673 .trigger = dummy_pcm_trigger, 684 674 .pointer = dummy_pcm_pointer, 685 .copy = dummy_pcm_copy, 686 .silence = dummy_pcm_silence, 675 .copy_user = dummy_pcm_copy, 676 .copy_kernel = dummy_pcm_copy_kernel, 677 .fill_silence = dummy_pcm_silence, 687 678 .page = dummy_pcm_page, 688 679 }; 689 680 690 static int __devinitsnd_card_dummy_pcm(struct snd_dummy *dummy, int device,691 681 static int snd_card_dummy_pcm(struct snd_dummy *dummy, int device, 682 int substreams) 692 683 { 693 684 struct snd_pcm *pcm; … … 820 811 } 821 812 813 static int snd_dummy_iobox_info(struct snd_kcontrol *kcontrol, 814 struct snd_ctl_elem_info *info) 815 { 816 static const char *const names[] = { "None", "CD Player" }; 817 818 return snd_ctl_enum_info(info, 1, 2, names); 819 } 820 821 static int snd_dummy_iobox_get(struct snd_kcontrol *kcontrol, 822 struct snd_ctl_elem_value *value) 823 { 824 struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); 825 826 value->value.enumerated.item[0] = dummy->iobox; 827 return 0; 828 } 829 830 static int snd_dummy_iobox_put(struct snd_kcontrol *kcontrol, 831 struct snd_ctl_elem_value *value) 832 { 833 struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); 834 int changed; 835 836 if (value->value.enumerated.item[0] > 1) 837 return -EINVAL; 838 839 changed = value->value.enumerated.item[0] != dummy->iobox; 840 if (changed) { 841 dummy->iobox = value->value.enumerated.item[0]; 842 843 if (dummy->iobox) { 844 dummy->cd_volume_ctl->vd[0].access &= 845 ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; 846 dummy->cd_switch_ctl->vd[0].access &= 847 ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; 848 } else { 849 dummy->cd_volume_ctl->vd[0].access |= 850 SNDRV_CTL_ELEM_ACCESS_INACTIVE; 851 dummy->cd_switch_ctl->vd[0].access |= 852 SNDRV_CTL_ELEM_ACCESS_INACTIVE; 853 } 854 855 snd_ctl_notify(dummy->card, SNDRV_CTL_EVENT_MASK_INFO, 856 &dummy->cd_volume_ctl->id); 857 snd_ctl_notify(dummy->card, SNDRV_CTL_EVENT_MASK_INFO, 858 &dummy->cd_switch_ctl->id); 859 } 860 861 return changed; 862 } 863 822 864 static struct snd_kcontrol_new snd_dummy_controls[] = { 823 865 DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER), … … 830 872 DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MIC), 831 873 DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD), 832 DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD) 833 }; 834 835 static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy) 874 DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD), 875 { 876 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 877 .name = "External I/O Box", 878 .info = snd_dummy_iobox_info, 879 .get = snd_dummy_iobox_get, 880 .put = snd_dummy_iobox_put, 881 }, 882 }; 883 884 static int snd_card_dummy_new_mixer(struct snd_dummy *dummy) 836 885 { 837 886 struct snd_card *card = dummy->card; 887 struct snd_kcontrol *kcontrol; 838 888 unsigned int idx; 839 889 int err; … … 841 891 spin_lock_init(&dummy->mixer_lock); 842 892 strcpy(card->mixername, "Dummy Mixer"); 893 dummy->iobox = 1; 843 894 844 895 for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) { 845 err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy)); 896 kcontrol = snd_ctl_new1(&snd_dummy_controls[idx], dummy); 897 err = snd_ctl_add(card, kcontrol); 846 898 if (err < 0) 847 899 return err; 848 } 849 return 0; 850 } 851 852 #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_PROC_FS) 900 if (!strcmp(kcontrol->id.name, "CD Volume")) 901 dummy->cd_volume_ctl = kcontrol; 902 else if (!strcmp(kcontrol->id.name, "CD Capture Switch")) 903 dummy->cd_switch_ctl = kcontrol; 904 905 } 906 return 0; 907 } 908 909 #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_PROC_FS) 853 910 /* 854 911 * proc interface … … 859 916 int i; 860 917 861 for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) {918 for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { 862 919 if (dummy->pcm_hw.formats & (1ULL << i)) 863 920 snd_iprintf(buffer, " %s", snd_pcm_format_name(i)); … … 956 1013 continue; 957 1014 snd_info_get_str(item, ptr, sizeof(item)); 958 if ( strict_strtoull(item, 0, &val))1015 if (kstrtoull(item, 0, &val)) 959 1016 continue; 960 1017 if (fields[i].size == sizeof(int)) … … 965 1022 } 966 1023 967 static void __devinit dummy_proc_init(struct snd_dummy *chip) 968 { 969 struct snd_info_entry *entry; 970 971 if (!snd_card_proc_new(chip->card, "dummy_pcm", &entry)) { 972 snd_info_set_text_ops(entry, chip, dummy_proc_read); 973 entry->c.text.write = dummy_proc_write; 974 entry->mode |= S_IWUSR; 975 entry->private_data = chip; 976 } 1024 static void dummy_proc_init(struct snd_dummy *chip) 1025 { 1026 snd_card_rw_proc_new(chip->card, "dummy_pcm", chip, 1027 dummy_proc_read, dummy_proc_write); 977 1028 } 978 1029 #else 979 1030 #define dummy_proc_init(x) 980 #endif /* CONFIG_SND_DEBUG && CONFIG_ PROC_FS */981 982 static int __devinitsnd_dummy_probe(struct platform_device *devptr)1031 #endif /* CONFIG_SND_DEBUG && CONFIG_SND_PROC_FS */ 1032 1033 static int snd_dummy_probe(struct platform_device *devptr) 983 1034 { 984 1035 struct snd_card *card; … … 988 1039 int dev = devptr->id; 989 1040 990 err = snd_card_ create(index[dev], id[dev], THIS_MODULE,991 1041 err = snd_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE, 1042 sizeof(struct snd_dummy), &card); 992 1043 if (err < 0) 993 1044 return err; … … 1048 1099 dummy_proc_init(dummy); 1049 1100 1050 snd_card_set_dev(card, &devptr->dev);1051 1052 1101 err = snd_card_register(card); 1053 1102 if (err == 0) { … … 1060 1109 } 1061 1110 1062 static int __devexitsnd_dummy_remove(struct platform_device *devptr)1111 static int snd_dummy_remove(struct platform_device *devptr) 1063 1112 { 1064 1113 snd_card_free(platform_get_drvdata(devptr)); 1065 platform_set_drvdata(devptr, NULL); 1066 return 0; 1067 } 1068 1069 #ifdef CONFIG_PM 1070 static int snd_dummy_suspend(struct platform_device *pdev, pm_message_t state) 1071 { 1072 struct snd_card *card = platform_get_drvdata(pdev); 1073 struct snd_dummy *dummy = card->private_data; 1114 return 0; 1115 } 1116 1117 #ifdef CONFIG_PM_SLEEP 1118 static int snd_dummy_suspend(struct device *pdev) 1119 { 1120 struct snd_card *card = dev_get_drvdata(pdev); 1074 1121 1075 1122 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 1076 snd_pcm_suspend_all(dummy->pcm);1077 1123 return 0; 1078 1124 } 1079 1125 1080 static int snd_dummy_resume(struct platform_device *pdev)1081 { 1082 struct snd_card *card = platform_get_drvdata(pdev);1126 static int snd_dummy_resume(struct device *pdev) 1127 { 1128 struct snd_card *card = dev_get_drvdata(pdev); 1083 1129 1084 1130 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 1085 1131 return 0; 1086 1132 } 1133 1134 static SIMPLE_DEV_PM_OPS(snd_dummy_pm, snd_dummy_suspend, snd_dummy_resume); 1135 #define SND_DUMMY_PM_OPS &snd_dummy_pm 1136 #else 1137 #define SND_DUMMY_PM_OPS NULL 1087 1138 #endif 1088 1139 … … 1091 1142 static struct platform_driver snd_dummy_driver = { 1092 1143 .probe = snd_dummy_probe, 1093 .remove = __devexit_p(snd_dummy_remove), 1094 #ifdef CONFIG_PM 1095 .suspend = snd_dummy_suspend, 1096 .resume = snd_dummy_resume, 1097 #endif 1144 .remove = snd_dummy_remove, 1098 1145 .driver = { 1099 .name = SND_DUMMY_DRIVER 1146 .name = SND_DUMMY_DRIVER, 1147 .pm = SND_DUMMY_PM_OPS, 1100 1148 }, 1101 1149 };
Note:
See TracChangeset
for help on using the changeset viewer.