| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * ALSA driver for Echoaudio soundcards. |
|---|
| 3 | 4 | * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 6 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 7 | | - * the Free Software Foundation; version 2 of the License. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 | | - * GNU General Public License for more details. |
|---|
| 13 | | - * |
|---|
| 14 | | - * You should have received a copy of the GNU General Public License |
|---|
| 15 | | - * along with this program; if not, write to the Free Software |
|---|
| 16 | | - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|---|
| 5 | + * Copyright (C) 2020 Mark Hills <mark@xwax.org> |
|---|
| 17 | 6 | */ |
|---|
| 18 | 7 | |
|---|
| 19 | 8 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 35 | 24 | module_param_array(enable, bool, NULL, 0444); |
|---|
| 36 | 25 | MODULE_PARM_DESC(enable, "Enable " ECHOCARD_NAME " soundcard."); |
|---|
| 37 | 26 | |
|---|
| 38 | | -static unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999}; |
|---|
| 27 | +static const unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999}; |
|---|
| 39 | 28 | static const DECLARE_TLV_DB_SCALE(db_scale_output_gain, -12800, 100, 1); |
|---|
| 40 | 29 | |
|---|
| 41 | 30 | |
|---|
| .. | .. |
|---|
| 257 | 246 | SNDRV_PCM_HW_PARAM_RATE); |
|---|
| 258 | 247 | struct echoaudio *chip = rule->private; |
|---|
| 259 | 248 | struct snd_interval fixed; |
|---|
| 249 | + int err; |
|---|
| 260 | 250 | |
|---|
| 261 | | - if (!chip->can_set_rate) { |
|---|
| 251 | + mutex_lock(&chip->mode_mutex); |
|---|
| 252 | + |
|---|
| 253 | + if (chip->can_set_rate) { |
|---|
| 254 | + err = 0; |
|---|
| 255 | + } else { |
|---|
| 262 | 256 | snd_interval_any(&fixed); |
|---|
| 263 | 257 | fixed.min = fixed.max = chip->sample_rate; |
|---|
| 264 | | - return snd_interval_refine(rate, &fixed); |
|---|
| 258 | + err = snd_interval_refine(rate, &fixed); |
|---|
| 265 | 259 | } |
|---|
| 266 | | - return 0; |
|---|
| 260 | + |
|---|
| 261 | + mutex_unlock(&chip->mode_mutex); |
|---|
| 262 | + return err; |
|---|
| 267 | 263 | } |
|---|
| 268 | 264 | |
|---|
| 269 | 265 | |
|---|
| .. | .. |
|---|
| 334 | 330 | SNDRV_PCM_HW_PARAM_RATE, -1)) < 0) |
|---|
| 335 | 331 | return err; |
|---|
| 336 | 332 | |
|---|
| 337 | | - /* Finally allocate a page for the scatter-gather list */ |
|---|
| 333 | + /* Allocate a page for the scatter-gather list */ |
|---|
| 338 | 334 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, |
|---|
| 339 | | - snd_dma_pci_data(chip->pci), |
|---|
| 335 | + &chip->pci->dev, |
|---|
| 340 | 336 | PAGE_SIZE, &pipe->sgpage)) < 0) { |
|---|
| 341 | 337 | dev_err(chip->card->dev, "s-g list allocation failed\n"); |
|---|
| 342 | 338 | return err; |
|---|
| 343 | 339 | } |
|---|
| 340 | + |
|---|
| 341 | + /* |
|---|
| 342 | + * Sole ownership required to set the rate |
|---|
| 343 | + */ |
|---|
| 344 | + |
|---|
| 345 | + dev_dbg(chip->card->dev, "pcm_open opencount=%d can_set_rate=%d, rate_set=%d", |
|---|
| 346 | + chip->opencount, chip->can_set_rate, chip->rate_set); |
|---|
| 347 | + |
|---|
| 348 | + chip->opencount++; |
|---|
| 349 | + if (chip->opencount > 1 && chip->rate_set) |
|---|
| 350 | + chip->can_set_rate = 0; |
|---|
| 344 | 351 | |
|---|
| 345 | 352 | return 0; |
|---|
| 346 | 353 | } |
|---|
| .. | .. |
|---|
| 365 | 372 | hw_rule_capture_format_by_channels, NULL, |
|---|
| 366 | 373 | SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) |
|---|
| 367 | 374 | return err; |
|---|
| 368 | | - atomic_inc(&chip->opencount); |
|---|
| 369 | | - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) |
|---|
| 370 | | - chip->can_set_rate=0; |
|---|
| 371 | | - dev_dbg(chip->card->dev, "pcm_analog_in_open cs=%d oc=%d r=%d\n", |
|---|
| 372 | | - chip->can_set_rate, atomic_read(&chip->opencount), |
|---|
| 373 | | - chip->sample_rate); |
|---|
| 375 | + |
|---|
| 374 | 376 | return 0; |
|---|
| 375 | 377 | } |
|---|
| 376 | 378 | |
|---|
| .. | .. |
|---|
| 400 | 402 | NULL, |
|---|
| 401 | 403 | SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) |
|---|
| 402 | 404 | return err; |
|---|
| 403 | | - atomic_inc(&chip->opencount); |
|---|
| 404 | | - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) |
|---|
| 405 | | - chip->can_set_rate=0; |
|---|
| 406 | | - dev_dbg(chip->card->dev, "pcm_analog_out_open cs=%d oc=%d r=%d\n", |
|---|
| 407 | | - chip->can_set_rate, atomic_read(&chip->opencount), |
|---|
| 408 | | - chip->sample_rate); |
|---|
| 405 | + |
|---|
| 409 | 406 | return 0; |
|---|
| 410 | 407 | } |
|---|
| 411 | 408 | |
|---|
| .. | .. |
|---|
| 440 | 437 | hw_rule_capture_format_by_channels, NULL, |
|---|
| 441 | 438 | SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) |
|---|
| 442 | 439 | goto din_exit; |
|---|
| 443 | | - |
|---|
| 444 | | - atomic_inc(&chip->opencount); |
|---|
| 445 | | - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) |
|---|
| 446 | | - chip->can_set_rate=0; |
|---|
| 447 | 440 | |
|---|
| 448 | 441 | din_exit: |
|---|
| 449 | 442 | mutex_unlock(&chip->mode_mutex); |
|---|
| .. | .. |
|---|
| 483 | 476 | NULL, SNDRV_PCM_HW_PARAM_CHANNELS, |
|---|
| 484 | 477 | -1)) < 0) |
|---|
| 485 | 478 | goto dout_exit; |
|---|
| 486 | | - atomic_inc(&chip->opencount); |
|---|
| 487 | | - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) |
|---|
| 488 | | - chip->can_set_rate=0; |
|---|
| 479 | + |
|---|
| 489 | 480 | dout_exit: |
|---|
| 490 | 481 | mutex_unlock(&chip->mode_mutex); |
|---|
| 491 | 482 | return err; |
|---|
| .. | .. |
|---|
| 500 | 491 | static int pcm_close(struct snd_pcm_substream *substream) |
|---|
| 501 | 492 | { |
|---|
| 502 | 493 | struct echoaudio *chip = snd_pcm_substream_chip(substream); |
|---|
| 503 | | - int oc; |
|---|
| 504 | 494 | |
|---|
| 505 | 495 | /* Nothing to do here. Audio is already off and pipe will be |
|---|
| 506 | 496 | * freed by its callback |
|---|
| 507 | 497 | */ |
|---|
| 508 | 498 | |
|---|
| 509 | | - atomic_dec(&chip->opencount); |
|---|
| 510 | | - oc = atomic_read(&chip->opencount); |
|---|
| 511 | | - dev_dbg(chip->card->dev, "pcm_close oc=%d cs=%d rs=%d\n", oc, |
|---|
| 512 | | - chip->can_set_rate, chip->rate_set); |
|---|
| 513 | | - if (oc < 2) |
|---|
| 514 | | - chip->can_set_rate = 1; |
|---|
| 515 | | - if (oc == 0) |
|---|
| 516 | | - chip->rate_set = 0; |
|---|
| 517 | | - dev_dbg(chip->card->dev, "pcm_close2 oc=%d cs=%d rs=%d\n", oc, |
|---|
| 518 | | - chip->can_set_rate, chip->rate_set); |
|---|
| 499 | + mutex_lock(&chip->mode_mutex); |
|---|
| 519 | 500 | |
|---|
| 501 | + dev_dbg(chip->card->dev, "pcm_open opencount=%d can_set_rate=%d, rate_set=%d", |
|---|
| 502 | + chip->opencount, chip->can_set_rate, chip->rate_set); |
|---|
| 503 | + |
|---|
| 504 | + chip->opencount--; |
|---|
| 505 | + |
|---|
| 506 | + switch (chip->opencount) { |
|---|
| 507 | + case 1: |
|---|
| 508 | + chip->can_set_rate = 1; |
|---|
| 509 | + break; |
|---|
| 510 | + |
|---|
| 511 | + case 0: |
|---|
| 512 | + chip->rate_set = 0; |
|---|
| 513 | + break; |
|---|
| 514 | + } |
|---|
| 515 | + |
|---|
| 516 | + mutex_unlock(&chip->mode_mutex); |
|---|
| 520 | 517 | return 0; |
|---|
| 521 | 518 | } |
|---|
| 522 | 519 | |
|---|
| .. | .. |
|---|
| 559 | 556 | "pcm_hw_params (bufsize=%dB periods=%d persize=%dB)\n", |
|---|
| 560 | 557 | params_buffer_bytes(hw_params), params_periods(hw_params), |
|---|
| 561 | 558 | params_period_bytes(hw_params)); |
|---|
| 562 | | - err = snd_pcm_lib_malloc_pages(substream, |
|---|
| 563 | | - params_buffer_bytes(hw_params)); |
|---|
| 564 | | - if (err < 0) { |
|---|
| 565 | | - dev_err(chip->card->dev, "malloc_pages err=%d\n", err); |
|---|
| 566 | | - spin_lock_irq(&chip->lock); |
|---|
| 567 | | - free_pipes(chip, pipe); |
|---|
| 568 | | - spin_unlock_irq(&chip->lock); |
|---|
| 569 | | - pipe->index = -1; |
|---|
| 570 | | - return err; |
|---|
| 571 | | - } |
|---|
| 572 | 559 | |
|---|
| 573 | 560 | sglist_init(chip, pipe); |
|---|
| 574 | 561 | edge = PAGE_SIZE; |
|---|
| .. | .. |
|---|
| 604 | 591 | /* This stuff is used by the irq handler, so it must be |
|---|
| 605 | 592 | * initialized before chip->substream |
|---|
| 606 | 593 | */ |
|---|
| 607 | | - chip->last_period[pipe_index] = 0; |
|---|
| 594 | + pipe->last_period = 0; |
|---|
| 608 | 595 | pipe->last_counter = 0; |
|---|
| 609 | 596 | pipe->position = 0; |
|---|
| 610 | 597 | smp_wmb(); |
|---|
| .. | .. |
|---|
| 683 | 670 | } |
|---|
| 684 | 671 | spin_unlock_irq(&chip->lock); |
|---|
| 685 | 672 | |
|---|
| 686 | | - snd_pcm_lib_free_pages(substream); |
|---|
| 687 | 673 | return 0; |
|---|
| 688 | 674 | } |
|---|
| 689 | 675 | |
|---|
| .. | .. |
|---|
| 713 | 699 | break; |
|---|
| 714 | 700 | case SNDRV_PCM_FORMAT_S32_BE: |
|---|
| 715 | 701 | format.data_are_bigendian = 1; |
|---|
| 716 | | - /* fall through */ |
|---|
| 702 | + fallthrough; |
|---|
| 717 | 703 | case SNDRV_PCM_FORMAT_S32_LE: |
|---|
| 718 | 704 | format.bits_per_sample = 32; |
|---|
| 719 | 705 | break; |
|---|
| .. | .. |
|---|
| 726 | 712 | |
|---|
| 727 | 713 | if (snd_BUG_ON(pipe_index >= px_num(chip))) |
|---|
| 728 | 714 | return -EINVAL; |
|---|
| 729 | | - if (snd_BUG_ON(!is_pipe_allocated(chip, pipe_index))) |
|---|
| 715 | + |
|---|
| 716 | + /* |
|---|
| 717 | + * We passed checks we can do independently; now take |
|---|
| 718 | + * exclusive control |
|---|
| 719 | + */ |
|---|
| 720 | + |
|---|
| 721 | + spin_lock_irq(&chip->lock); |
|---|
| 722 | + |
|---|
| 723 | + if (snd_BUG_ON(!is_pipe_allocated(chip, pipe_index))) { |
|---|
| 724 | + spin_unlock_irq(&chip->lock); |
|---|
| 730 | 725 | return -EINVAL; |
|---|
| 726 | + } |
|---|
| 727 | + |
|---|
| 731 | 728 | set_audio_format(chip, pipe_index, &format); |
|---|
| 729 | + spin_unlock_irq(&chip->lock); |
|---|
| 730 | + |
|---|
| 732 | 731 | return 0; |
|---|
| 733 | 732 | } |
|---|
| 734 | 733 | |
|---|
| .. | .. |
|---|
| 761 | 760 | pipe = chip->substream[i]->runtime->private_data; |
|---|
| 762 | 761 | switch (pipe->state) { |
|---|
| 763 | 762 | case PIPE_STATE_STOPPED: |
|---|
| 764 | | - chip->last_period[i] = 0; |
|---|
| 763 | + pipe->last_period = 0; |
|---|
| 765 | 764 | pipe->last_counter = 0; |
|---|
| 766 | 765 | pipe->position = 0; |
|---|
| 767 | 766 | *pipe->dma_counter = 0; |
|---|
| 768 | | - /* fall through */ |
|---|
| 767 | + fallthrough; |
|---|
| 769 | 768 | case PIPE_STATE_PAUSED: |
|---|
| 770 | 769 | pipe->state = PIPE_STATE_STARTED; |
|---|
| 771 | 770 | break; |
|---|
| .. | .. |
|---|
| 809 | 808 | { |
|---|
| 810 | 809 | struct snd_pcm_runtime *runtime = substream->runtime; |
|---|
| 811 | 810 | struct audiopipe *pipe = runtime->private_data; |
|---|
| 812 | | - size_t cnt, bufsize, pos; |
|---|
| 811 | + u32 counter, step; |
|---|
| 813 | 812 | |
|---|
| 814 | | - cnt = le32_to_cpu(*pipe->dma_counter); |
|---|
| 815 | | - pipe->position += cnt - pipe->last_counter; |
|---|
| 816 | | - pipe->last_counter = cnt; |
|---|
| 817 | | - bufsize = substream->runtime->buffer_size; |
|---|
| 818 | | - pos = bytes_to_frames(substream->runtime, pipe->position); |
|---|
| 813 | + /* |
|---|
| 814 | + * IRQ handling runs concurrently. Do not share tracking of |
|---|
| 815 | + * counter with it, which would race or require locking |
|---|
| 816 | + */ |
|---|
| 819 | 817 | |
|---|
| 820 | | - while (pos >= bufsize) { |
|---|
| 821 | | - pipe->position -= frames_to_bytes(substream->runtime, bufsize); |
|---|
| 822 | | - pos -= bufsize; |
|---|
| 823 | | - } |
|---|
| 824 | | - return pos; |
|---|
| 818 | + counter = le32_to_cpu(*pipe->dma_counter); /* presumed atomic */ |
|---|
| 819 | + |
|---|
| 820 | + step = counter - pipe->last_counter; /* handles wrapping */ |
|---|
| 821 | + pipe->last_counter = counter; |
|---|
| 822 | + |
|---|
| 823 | + /* counter doesn't neccessarily wrap on a multiple of |
|---|
| 824 | + * buffer_size, so can't derive the position; must |
|---|
| 825 | + * accumulate */ |
|---|
| 826 | + |
|---|
| 827 | + pipe->position += step; |
|---|
| 828 | + pipe->position %= frames_to_bytes(runtime, runtime->buffer_size); /* wrap */ |
|---|
| 829 | + |
|---|
| 830 | + return bytes_to_frames(runtime, pipe->position); |
|---|
| 825 | 831 | } |
|---|
| 826 | 832 | |
|---|
| 827 | 833 | |
|---|
| .. | .. |
|---|
| 830 | 836 | static const struct snd_pcm_ops analog_playback_ops = { |
|---|
| 831 | 837 | .open = pcm_analog_out_open, |
|---|
| 832 | 838 | .close = pcm_close, |
|---|
| 833 | | - .ioctl = snd_pcm_lib_ioctl, |
|---|
| 834 | 839 | .hw_params = pcm_analog_out_hw_params, |
|---|
| 835 | 840 | .hw_free = pcm_hw_free, |
|---|
| 836 | 841 | .prepare = pcm_prepare, |
|---|
| 837 | 842 | .trigger = pcm_trigger, |
|---|
| 838 | 843 | .pointer = pcm_pointer, |
|---|
| 839 | | - .page = snd_pcm_sgbuf_ops_page, |
|---|
| 840 | 844 | }; |
|---|
| 841 | 845 | static const struct snd_pcm_ops analog_capture_ops = { |
|---|
| 842 | 846 | .open = pcm_analog_in_open, |
|---|
| 843 | 847 | .close = pcm_close, |
|---|
| 844 | | - .ioctl = snd_pcm_lib_ioctl, |
|---|
| 845 | 848 | .hw_params = pcm_analog_in_hw_params, |
|---|
| 846 | 849 | .hw_free = pcm_hw_free, |
|---|
| 847 | 850 | .prepare = pcm_prepare, |
|---|
| 848 | 851 | .trigger = pcm_trigger, |
|---|
| 849 | 852 | .pointer = pcm_pointer, |
|---|
| 850 | | - .page = snd_pcm_sgbuf_ops_page, |
|---|
| 851 | 853 | }; |
|---|
| 852 | 854 | #ifdef ECHOCARD_HAS_DIGITAL_IO |
|---|
| 853 | 855 | #ifndef ECHOCARD_HAS_VMIXER |
|---|
| 854 | 856 | static const struct snd_pcm_ops digital_playback_ops = { |
|---|
| 855 | 857 | .open = pcm_digital_out_open, |
|---|
| 856 | 858 | .close = pcm_close, |
|---|
| 857 | | - .ioctl = snd_pcm_lib_ioctl, |
|---|
| 858 | 859 | .hw_params = pcm_digital_out_hw_params, |
|---|
| 859 | 860 | .hw_free = pcm_hw_free, |
|---|
| 860 | 861 | .prepare = pcm_prepare, |
|---|
| 861 | 862 | .trigger = pcm_trigger, |
|---|
| 862 | 863 | .pointer = pcm_pointer, |
|---|
| 863 | | - .page = snd_pcm_sgbuf_ops_page, |
|---|
| 864 | 864 | }; |
|---|
| 865 | 865 | #endif /* !ECHOCARD_HAS_VMIXER */ |
|---|
| 866 | 866 | static const struct snd_pcm_ops digital_capture_ops = { |
|---|
| 867 | 867 | .open = pcm_digital_in_open, |
|---|
| 868 | 868 | .close = pcm_close, |
|---|
| 869 | | - .ioctl = snd_pcm_lib_ioctl, |
|---|
| 870 | 869 | .hw_params = pcm_digital_in_hw_params, |
|---|
| 871 | 870 | .hw_free = pcm_hw_free, |
|---|
| 872 | 871 | .prepare = pcm_prepare, |
|---|
| 873 | 872 | .trigger = pcm_trigger, |
|---|
| 874 | 873 | .pointer = pcm_pointer, |
|---|
| 875 | | - .page = snd_pcm_sgbuf_ops_page, |
|---|
| 876 | 874 | }; |
|---|
| 877 | 875 | #endif /* ECHOCARD_HAS_DIGITAL_IO */ |
|---|
| 878 | 876 | |
|---|
| .. | .. |
|---|
| 881 | 879 | /* Preallocate memory only for the first substream because it's the most |
|---|
| 882 | 880 | * used one |
|---|
| 883 | 881 | */ |
|---|
| 884 | | -static int snd_echo_preallocate_pages(struct snd_pcm *pcm, struct device *dev) |
|---|
| 882 | +static void snd_echo_preallocate_pages(struct snd_pcm *pcm, struct device *dev) |
|---|
| 885 | 883 | { |
|---|
| 886 | 884 | struct snd_pcm_substream *ss; |
|---|
| 887 | | - int stream, err; |
|---|
| 885 | + int stream; |
|---|
| 888 | 886 | |
|---|
| 889 | 887 | for (stream = 0; stream < 2; stream++) |
|---|
| 890 | | - for (ss = pcm->streams[stream].substream; ss; ss = ss->next) { |
|---|
| 891 | | - err = snd_pcm_lib_preallocate_pages(ss, SNDRV_DMA_TYPE_DEV_SG, |
|---|
| 892 | | - dev, |
|---|
| 893 | | - ss->number ? 0 : 128<<10, |
|---|
| 894 | | - 256<<10); |
|---|
| 895 | | - if (err < 0) |
|---|
| 896 | | - return err; |
|---|
| 897 | | - } |
|---|
| 898 | | - return 0; |
|---|
| 888 | + for (ss = pcm->streams[stream].substream; ss; ss = ss->next) |
|---|
| 889 | + snd_pcm_set_managed_buffer(ss, SNDRV_DMA_TYPE_DEV_SG, |
|---|
| 890 | + dev, |
|---|
| 891 | + ss->number ? 0 : 128<<10, |
|---|
| 892 | + 256<<10); |
|---|
| 899 | 893 | } |
|---|
| 900 | 894 | |
|---|
| 901 | 895 | |
|---|
| .. | .. |
|---|
| 922 | 916 | strcpy(pcm->name, chip->card->shortname); |
|---|
| 923 | 917 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops); |
|---|
| 924 | 918 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops); |
|---|
| 925 | | - if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) |
|---|
| 926 | | - return err; |
|---|
| 919 | + snd_echo_preallocate_pages(pcm, &chip->pci->dev); |
|---|
| 927 | 920 | |
|---|
| 928 | 921 | #ifdef ECHOCARD_HAS_DIGITAL_IO |
|---|
| 929 | 922 | /* PCM#1 Digital inputs, no outputs */ |
|---|
| .. | .. |
|---|
| 934 | 927 | chip->digital_pcm = pcm; |
|---|
| 935 | 928 | strcpy(pcm->name, chip->card->shortname); |
|---|
| 936 | 929 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops); |
|---|
| 937 | | - if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) |
|---|
| 938 | | - return err; |
|---|
| 930 | + snd_echo_preallocate_pages(pcm, &chip->pci->dev); |
|---|
| 939 | 931 | #endif /* ECHOCARD_HAS_DIGITAL_IO */ |
|---|
| 940 | 932 | |
|---|
| 941 | 933 | #else /* ECHOCARD_HAS_VMIXER */ |
|---|
| .. | .. |
|---|
| 955 | 947 | strcpy(pcm->name, chip->card->shortname); |
|---|
| 956 | 948 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops); |
|---|
| 957 | 949 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops); |
|---|
| 958 | | - if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) |
|---|
| 959 | | - return err; |
|---|
| 950 | + snd_echo_preallocate_pages(pcm, &chip->pci->dev); |
|---|
| 960 | 951 | |
|---|
| 961 | 952 | #ifdef ECHOCARD_HAS_DIGITAL_IO |
|---|
| 962 | 953 | /* PCM#1 Digital i/o */ |
|---|
| .. | .. |
|---|
| 969 | 960 | strcpy(pcm->name, chip->card->shortname); |
|---|
| 970 | 961 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &digital_playback_ops); |
|---|
| 971 | 962 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops); |
|---|
| 972 | | - if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) |
|---|
| 973 | | - return err; |
|---|
| 963 | + snd_echo_preallocate_pages(pcm, &chip->pci->dev); |
|---|
| 974 | 964 | #endif /* ECHOCARD_HAS_DIGITAL_IO */ |
|---|
| 975 | 965 | |
|---|
| 976 | 966 | #endif /* ECHOCARD_HAS_VMIXER */ |
|---|
| .. | .. |
|---|
| 1269 | 1259 | static int snd_echo_mixer_info(struct snd_kcontrol *kcontrol, |
|---|
| 1270 | 1260 | struct snd_ctl_elem_info *uinfo) |
|---|
| 1271 | 1261 | { |
|---|
| 1272 | | - struct echoaudio *chip; |
|---|
| 1273 | | - |
|---|
| 1274 | | - chip = snd_kcontrol_chip(kcontrol); |
|---|
| 1275 | 1262 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
|---|
| 1276 | 1263 | uinfo->count = 1; |
|---|
| 1277 | 1264 | uinfo->value.integer.min = ECHOGAIN_MINOUT; |
|---|
| 1278 | 1265 | uinfo->value.integer.max = ECHOGAIN_MAXOUT; |
|---|
| 1279 | | - uinfo->dimen.d[0] = num_busses_out(chip); |
|---|
| 1280 | | - uinfo->dimen.d[1] = num_busses_in(chip); |
|---|
| 1281 | 1266 | return 0; |
|---|
| 1282 | 1267 | } |
|---|
| 1283 | 1268 | |
|---|
| .. | .. |
|---|
| 1341 | 1326 | static int snd_echo_vmixer_info(struct snd_kcontrol *kcontrol, |
|---|
| 1342 | 1327 | struct snd_ctl_elem_info *uinfo) |
|---|
| 1343 | 1328 | { |
|---|
| 1344 | | - struct echoaudio *chip; |
|---|
| 1345 | | - |
|---|
| 1346 | | - chip = snd_kcontrol_chip(kcontrol); |
|---|
| 1347 | 1329 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
|---|
| 1348 | 1330 | uinfo->count = 1; |
|---|
| 1349 | 1331 | uinfo->value.integer.min = ECHOGAIN_MINOUT; |
|---|
| 1350 | 1332 | uinfo->value.integer.max = ECHOGAIN_MAXOUT; |
|---|
| 1351 | | - uinfo->dimen.d[0] = num_busses_out(chip); |
|---|
| 1352 | | - uinfo->dimen.d[1] = num_pipes_out(chip); |
|---|
| 1353 | 1333 | return 0; |
|---|
| 1354 | 1334 | } |
|---|
| 1355 | 1335 | |
|---|
| .. | .. |
|---|
| 1458 | 1438 | /* Do not allow the user to change the digital mode when a pcm |
|---|
| 1459 | 1439 | device is open because it also changes the number of channels |
|---|
| 1460 | 1440 | and the allowed sample rates */ |
|---|
| 1461 | | - if (atomic_read(&chip->opencount)) { |
|---|
| 1441 | + if (chip->opencount) { |
|---|
| 1462 | 1442 | changed = -EAGAIN; |
|---|
| 1463 | 1443 | } else { |
|---|
| 1464 | 1444 | changed = set_digital_mode(chip, dmode); |
|---|
| .. | .. |
|---|
| 1732 | 1712 | uinfo->count = 96; |
|---|
| 1733 | 1713 | uinfo->value.integer.min = ECHOGAIN_MINOUT; |
|---|
| 1734 | 1714 | uinfo->value.integer.max = 0; |
|---|
| 1735 | | -#ifdef ECHOCARD_HAS_VMIXER |
|---|
| 1736 | | - uinfo->dimen.d[0] = 3; /* Out, In, Virt */ |
|---|
| 1737 | | -#else |
|---|
| 1738 | | - uinfo->dimen.d[0] = 2; /* Out, In */ |
|---|
| 1739 | | -#endif |
|---|
| 1740 | | - uinfo->dimen.d[1] = 16; /* 16 channels */ |
|---|
| 1741 | | - uinfo->dimen.d[2] = 2; /* 0=level, 1=peak */ |
|---|
| 1742 | 1715 | return 0; |
|---|
| 1743 | 1716 | } |
|---|
| 1744 | 1717 | |
|---|
| .. | .. |
|---|
| 1817 | 1790 | |
|---|
| 1818 | 1791 | |
|---|
| 1819 | 1792 | /****************************************************************************** |
|---|
| 1820 | | - IRQ Handler |
|---|
| 1793 | + IRQ Handling |
|---|
| 1821 | 1794 | ******************************************************************************/ |
|---|
| 1795 | +/* Check if a period has elapsed since last interrupt |
|---|
| 1796 | + * |
|---|
| 1797 | + * Don't make any updates to state; PCM core handles this with the |
|---|
| 1798 | + * correct locks. |
|---|
| 1799 | + * |
|---|
| 1800 | + * \return true if a period has elapsed, otherwise false |
|---|
| 1801 | + */ |
|---|
| 1802 | +static bool period_has_elapsed(struct snd_pcm_substream *substream) |
|---|
| 1803 | +{ |
|---|
| 1804 | + struct snd_pcm_runtime *runtime = substream->runtime; |
|---|
| 1805 | + struct audiopipe *pipe = runtime->private_data; |
|---|
| 1806 | + u32 counter, step; |
|---|
| 1807 | + size_t period_bytes; |
|---|
| 1808 | + |
|---|
| 1809 | + if (pipe->state != PIPE_STATE_STARTED) |
|---|
| 1810 | + return false; |
|---|
| 1811 | + |
|---|
| 1812 | + period_bytes = frames_to_bytes(runtime, runtime->period_size); |
|---|
| 1813 | + |
|---|
| 1814 | + counter = le32_to_cpu(*pipe->dma_counter); /* presumed atomic */ |
|---|
| 1815 | + |
|---|
| 1816 | + step = counter - pipe->last_period; /* handles wrapping */ |
|---|
| 1817 | + step -= step % period_bytes; /* acknowledge whole periods only */ |
|---|
| 1818 | + |
|---|
| 1819 | + if (step == 0) |
|---|
| 1820 | + return false; /* haven't advanced a whole period yet */ |
|---|
| 1821 | + |
|---|
| 1822 | + pipe->last_period += step; /* used exclusively by us */ |
|---|
| 1823 | + return true; |
|---|
| 1824 | +} |
|---|
| 1822 | 1825 | |
|---|
| 1823 | 1826 | static irqreturn_t snd_echo_interrupt(int irq, void *dev_id) |
|---|
| 1824 | 1827 | { |
|---|
| 1825 | 1828 | struct echoaudio *chip = dev_id; |
|---|
| 1826 | | - struct snd_pcm_substream *substream; |
|---|
| 1827 | | - int period, ss, st; |
|---|
| 1829 | + int ss, st; |
|---|
| 1828 | 1830 | |
|---|
| 1829 | 1831 | spin_lock(&chip->lock); |
|---|
| 1830 | 1832 | st = service_irq(chip); |
|---|
| .. | .. |
|---|
| 1835 | 1837 | /* The hardware doesn't tell us which substream caused the irq, |
|---|
| 1836 | 1838 | thus we have to check all running substreams. */ |
|---|
| 1837 | 1839 | for (ss = 0; ss < DSP_MAXPIPES; ss++) { |
|---|
| 1840 | + struct snd_pcm_substream *substream; |
|---|
| 1841 | + |
|---|
| 1838 | 1842 | substream = chip->substream[ss]; |
|---|
| 1839 | | - if (substream && ((struct audiopipe *)substream->runtime-> |
|---|
| 1840 | | - private_data)->state == PIPE_STATE_STARTED) { |
|---|
| 1841 | | - period = pcm_pointer(substream) / |
|---|
| 1842 | | - substream->runtime->period_size; |
|---|
| 1843 | | - if (period != chip->last_period[ss]) { |
|---|
| 1844 | | - chip->last_period[ss] = period; |
|---|
| 1845 | | - spin_unlock(&chip->lock); |
|---|
| 1846 | | - snd_pcm_period_elapsed(substream); |
|---|
| 1847 | | - spin_lock(&chip->lock); |
|---|
| 1848 | | - } |
|---|
| 1843 | + if (substream && period_has_elapsed(substream)) { |
|---|
| 1844 | + spin_unlock(&chip->lock); |
|---|
| 1845 | + snd_pcm_period_elapsed(substream); |
|---|
| 1846 | + spin_lock(&chip->lock); |
|---|
| 1849 | 1847 | } |
|---|
| 1850 | 1848 | } |
|---|
| 1851 | 1849 | spin_unlock(&chip->lock); |
|---|
| .. | .. |
|---|
| 1906 | 1904 | struct echoaudio *chip; |
|---|
| 1907 | 1905 | int err; |
|---|
| 1908 | 1906 | size_t sz; |
|---|
| 1909 | | - static struct snd_device_ops ops = { |
|---|
| 1907 | + static const struct snd_device_ops ops = { |
|---|
| 1910 | 1908 | .dev_free = snd_echo_dev_free, |
|---|
| 1911 | 1909 | }; |
|---|
| 1912 | 1910 | |
|---|
| .. | .. |
|---|
| 1930 | 1928 | chip->card = card; |
|---|
| 1931 | 1929 | chip->pci = pci; |
|---|
| 1932 | 1930 | chip->irq = -1; |
|---|
| 1933 | | - atomic_set(&chip->opencount, 0); |
|---|
| 1931 | + chip->opencount = 0; |
|---|
| 1934 | 1932 | mutex_init(&chip->mode_mutex); |
|---|
| 1935 | 1933 | chip->can_set_rate = 1; |
|---|
| 1936 | 1934 | } else { |
|---|
| .. | .. |
|---|
| 1952 | 1950 | snd_echo_free(chip); |
|---|
| 1953 | 1951 | return -EBUSY; |
|---|
| 1954 | 1952 | } |
|---|
| 1955 | | - chip->dsp_registers = (volatile u32 __iomem *) |
|---|
| 1956 | | - ioremap_nocache(chip->dsp_registers_phys, sz); |
|---|
| 1953 | + chip->dsp_registers = ioremap(chip->dsp_registers_phys, sz); |
|---|
| 1957 | 1954 | if (!chip->dsp_registers) { |
|---|
| 1958 | 1955 | dev_err(chip->card->dev, "ioremap failed\n"); |
|---|
| 1959 | 1956 | snd_echo_free(chip); |
|---|
| .. | .. |
|---|
| 1967 | 1964 | return -EBUSY; |
|---|
| 1968 | 1965 | } |
|---|
| 1969 | 1966 | chip->irq = pci->irq; |
|---|
| 1967 | + card->sync_irq = chip->irq; |
|---|
| 1970 | 1968 | dev_dbg(card->dev, "pci=%p irq=%d subdev=%04x Init hardware...\n", |
|---|
| 1971 | 1969 | chip->pci, chip->irq, chip->pci->subsystem_device); |
|---|
| 1972 | 1970 | |
|---|
| 1973 | 1971 | /* Create the DSP comm page - this is the area of memory used for most |
|---|
| 1974 | 1972 | of the communication with the DSP, which accesses it via bus mastering */ |
|---|
| 1975 | | - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), |
|---|
| 1973 | + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev, |
|---|
| 1976 | 1974 | sizeof(struct comm_page), |
|---|
| 1977 | 1975 | &chip->commpage_dma_buf) < 0) { |
|---|
| 1978 | 1976 | dev_err(chip->card->dev, "cannot allocate the comm page\n"); |
|---|
| .. | .. |
|---|
| 2010 | 2008 | struct snd_card *card; |
|---|
| 2011 | 2009 | struct echoaudio *chip; |
|---|
| 2012 | 2010 | char *dsp; |
|---|
| 2013 | | - int i, err; |
|---|
| 2011 | + __maybe_unused int i; |
|---|
| 2012 | + int err; |
|---|
| 2014 | 2013 | |
|---|
| 2015 | 2014 | if (dev >= SNDRV_CARDS) |
|---|
| 2016 | 2015 | return -ENODEV; |
|---|
| .. | .. |
|---|
| 2170 | 2169 | { |
|---|
| 2171 | 2170 | struct echoaudio *chip = dev_get_drvdata(dev); |
|---|
| 2172 | 2171 | |
|---|
| 2173 | | - snd_pcm_suspend_all(chip->analog_pcm); |
|---|
| 2174 | | - snd_pcm_suspend_all(chip->digital_pcm); |
|---|
| 2175 | | - |
|---|
| 2176 | 2172 | #ifdef ECHOCARD_HAS_MIDI |
|---|
| 2177 | 2173 | /* This call can sleep */ |
|---|
| 2178 | 2174 | if (chip->midi_out) |
|---|
| .. | .. |
|---|
| 2193 | 2189 | chip->dsp_code = NULL; |
|---|
| 2194 | 2190 | free_irq(chip->irq, chip); |
|---|
| 2195 | 2191 | chip->irq = -1; |
|---|
| 2192 | + chip->card->sync_irq = -1; |
|---|
| 2196 | 2193 | return 0; |
|---|
| 2197 | 2194 | } |
|---|
| 2198 | 2195 | |
|---|
| .. | .. |
|---|
| 2206 | 2203 | u32 pipe_alloc_mask; |
|---|
| 2207 | 2204 | int err; |
|---|
| 2208 | 2205 | |
|---|
| 2209 | | - commpage_bak = kmalloc(sizeof(*commpage), GFP_KERNEL); |
|---|
| 2206 | + commpage = chip->comm_page; |
|---|
| 2207 | + commpage_bak = kmemdup(commpage, sizeof(*commpage), GFP_KERNEL); |
|---|
| 2210 | 2208 | if (commpage_bak == NULL) |
|---|
| 2211 | 2209 | return -ENOMEM; |
|---|
| 2212 | | - commpage = chip->comm_page; |
|---|
| 2213 | | - memcpy(commpage_bak, commpage, sizeof(*commpage)); |
|---|
| 2214 | 2210 | |
|---|
| 2215 | 2211 | err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device); |
|---|
| 2216 | 2212 | if (err < 0) { |
|---|
| .. | .. |
|---|
| 2245 | 2241 | return -EBUSY; |
|---|
| 2246 | 2242 | } |
|---|
| 2247 | 2243 | chip->irq = pci->irq; |
|---|
| 2244 | + chip->card->sync_irq = chip->irq; |
|---|
| 2248 | 2245 | dev_dbg(dev, "resume irq=%d\n", chip->irq); |
|---|
| 2249 | 2246 | |
|---|
| 2250 | 2247 | #ifdef ECHOCARD_HAS_MIDI |
|---|