| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Driver for A2 audio system used in SGI machines |
|---|
| 3 | 4 | * Copyright (c) 2008 Thomas Bogendoerfer <tsbogend@alpha.fanken.de> |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * Based on OSS code from Ladislav Michl <ladis@linux-mips.org>, which |
|---|
| 6 | 7 | * was based on code from Ulf Carlsson |
|---|
| 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 | | - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 20 | | - * |
|---|
| 21 | 8 | */ |
|---|
| 22 | 9 | #include <linux/kernel.h> |
|---|
| 23 | 10 | #include <linux/init.h> |
|---|
| .. | .. |
|---|
| 454 | 441 | hal2->adc.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; |
|---|
| 455 | 442 | } |
|---|
| 456 | 443 | |
|---|
| 457 | | -static int hal2_alloc_dmabuf(struct hal2_codec *codec) |
|---|
| 444 | +static int hal2_alloc_dmabuf(struct snd_hal2 *hal2, struct hal2_codec *codec, |
|---|
| 445 | + enum dma_data_direction buffer_dir) |
|---|
| 458 | 446 | { |
|---|
| 447 | + struct device *dev = hal2->card->dev; |
|---|
| 459 | 448 | struct hal2_desc *desc; |
|---|
| 460 | 449 | dma_addr_t desc_dma, buffer_dma; |
|---|
| 461 | 450 | int count = H2_BUF_SIZE / H2_BLOCK_SIZE; |
|---|
| 462 | 451 | int i; |
|---|
| 463 | 452 | |
|---|
| 464 | | - codec->buffer = dma_alloc_attrs(NULL, H2_BUF_SIZE, &buffer_dma, |
|---|
| 465 | | - GFP_KERNEL, DMA_ATTR_NON_CONSISTENT); |
|---|
| 453 | + codec->buffer = dma_alloc_noncoherent(dev, H2_BUF_SIZE, &buffer_dma, |
|---|
| 454 | + buffer_dir, GFP_KERNEL); |
|---|
| 466 | 455 | if (!codec->buffer) |
|---|
| 467 | 456 | return -ENOMEM; |
|---|
| 468 | | - desc = dma_alloc_attrs(NULL, count * sizeof(struct hal2_desc), |
|---|
| 469 | | - &desc_dma, GFP_KERNEL, DMA_ATTR_NON_CONSISTENT); |
|---|
| 457 | + desc = dma_alloc_noncoherent(dev, count * sizeof(struct hal2_desc), |
|---|
| 458 | + &desc_dma, DMA_BIDIRECTIONAL, GFP_KERNEL); |
|---|
| 470 | 459 | if (!desc) { |
|---|
| 471 | | - dma_free_attrs(NULL, H2_BUF_SIZE, codec->buffer, buffer_dma, |
|---|
| 472 | | - DMA_ATTR_NON_CONSISTENT); |
|---|
| 460 | + dma_free_noncoherent(dev, H2_BUF_SIZE, codec->buffer, buffer_dma, |
|---|
| 461 | + buffer_dir); |
|---|
| 473 | 462 | return -ENOMEM; |
|---|
| 474 | 463 | } |
|---|
| 475 | 464 | codec->buffer_dma = buffer_dma; |
|---|
| .. | .. |
|---|
| 482 | 471 | desc_dma : desc_dma + (i + 1) * sizeof(struct hal2_desc); |
|---|
| 483 | 472 | desc++; |
|---|
| 484 | 473 | } |
|---|
| 485 | | - dma_cache_sync(NULL, codec->desc, count * sizeof(struct hal2_desc), |
|---|
| 486 | | - DMA_TO_DEVICE); |
|---|
| 474 | + dma_sync_single_for_device(dev, codec->desc_dma, |
|---|
| 475 | + count * sizeof(struct hal2_desc), |
|---|
| 476 | + DMA_BIDIRECTIONAL); |
|---|
| 487 | 477 | codec->desc_count = count; |
|---|
| 488 | 478 | return 0; |
|---|
| 489 | 479 | } |
|---|
| 490 | 480 | |
|---|
| 491 | | -static void hal2_free_dmabuf(struct hal2_codec *codec) |
|---|
| 481 | +static void hal2_free_dmabuf(struct snd_hal2 *hal2, struct hal2_codec *codec, |
|---|
| 482 | + enum dma_data_direction buffer_dir) |
|---|
| 492 | 483 | { |
|---|
| 493 | | - dma_free_attrs(NULL, codec->desc_count * sizeof(struct hal2_desc), |
|---|
| 494 | | - codec->desc, codec->desc_dma, DMA_ATTR_NON_CONSISTENT); |
|---|
| 495 | | - dma_free_attrs(NULL, H2_BUF_SIZE, codec->buffer, codec->buffer_dma, |
|---|
| 496 | | - DMA_ATTR_NON_CONSISTENT); |
|---|
| 484 | + struct device *dev = hal2->card->dev; |
|---|
| 485 | + |
|---|
| 486 | + dma_free_noncoherent(dev, codec->desc_count * sizeof(struct hal2_desc), |
|---|
| 487 | + codec->desc, codec->desc_dma, DMA_BIDIRECTIONAL); |
|---|
| 488 | + dma_free_noncoherent(dev, H2_BUF_SIZE, codec->buffer, codec->buffer_dma, |
|---|
| 489 | + buffer_dir); |
|---|
| 497 | 490 | } |
|---|
| 498 | 491 | |
|---|
| 499 | 492 | static const struct snd_pcm_hardware hal2_pcm_hw = { |
|---|
| 500 | 493 | .info = (SNDRV_PCM_INFO_MMAP | |
|---|
| 501 | 494 | SNDRV_PCM_INFO_MMAP_VALID | |
|---|
| 502 | 495 | SNDRV_PCM_INFO_INTERLEAVED | |
|---|
| 503 | | - SNDRV_PCM_INFO_BLOCK_TRANSFER), |
|---|
| 496 | + SNDRV_PCM_INFO_BLOCK_TRANSFER | |
|---|
| 497 | + SNDRV_PCM_INFO_SYNC_APPLPTR), |
|---|
| 504 | 498 | .formats = SNDRV_PCM_FMTBIT_S16_BE, |
|---|
| 505 | 499 | .rates = SNDRV_PCM_RATE_8000_48000, |
|---|
| 506 | 500 | .rate_min = 8000, |
|---|
| .. | .. |
|---|
| 514 | 508 | .periods_max = 1024, |
|---|
| 515 | 509 | }; |
|---|
| 516 | 510 | |
|---|
| 517 | | -static int hal2_pcm_hw_params(struct snd_pcm_substream *substream, |
|---|
| 518 | | - struct snd_pcm_hw_params *params) |
|---|
| 519 | | -{ |
|---|
| 520 | | - int err; |
|---|
| 521 | | - |
|---|
| 522 | | - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); |
|---|
| 523 | | - if (err < 0) |
|---|
| 524 | | - return err; |
|---|
| 525 | | - |
|---|
| 526 | | - return 0; |
|---|
| 527 | | -} |
|---|
| 528 | | - |
|---|
| 529 | | -static int hal2_pcm_hw_free(struct snd_pcm_substream *substream) |
|---|
| 530 | | -{ |
|---|
| 531 | | - return snd_pcm_lib_free_pages(substream); |
|---|
| 532 | | -} |
|---|
| 533 | | - |
|---|
| 534 | 511 | static int hal2_playback_open(struct snd_pcm_substream *substream) |
|---|
| 535 | 512 | { |
|---|
| 536 | 513 | struct snd_pcm_runtime *runtime = substream->runtime; |
|---|
| 537 | 514 | struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); |
|---|
| 538 | | - int err; |
|---|
| 539 | 515 | |
|---|
| 540 | 516 | runtime->hw = hal2_pcm_hw; |
|---|
| 541 | | - |
|---|
| 542 | | - err = hal2_alloc_dmabuf(&hal2->dac); |
|---|
| 543 | | - if (err) |
|---|
| 544 | | - return err; |
|---|
| 545 | | - return 0; |
|---|
| 517 | + return hal2_alloc_dmabuf(hal2, &hal2->dac, DMA_TO_DEVICE); |
|---|
| 546 | 518 | } |
|---|
| 547 | 519 | |
|---|
| 548 | 520 | static int hal2_playback_close(struct snd_pcm_substream *substream) |
|---|
| 549 | 521 | { |
|---|
| 550 | 522 | struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); |
|---|
| 551 | 523 | |
|---|
| 552 | | - hal2_free_dmabuf(&hal2->dac); |
|---|
| 524 | + hal2_free_dmabuf(hal2, &hal2->dac, DMA_TO_DEVICE); |
|---|
| 553 | 525 | return 0; |
|---|
| 554 | 526 | } |
|---|
| 555 | 527 | |
|---|
| .. | .. |
|---|
| 563 | 535 | dac->sample_rate = hal2_compute_rate(dac, runtime->rate); |
|---|
| 564 | 536 | memset(&dac->pcm_indirect, 0, sizeof(dac->pcm_indirect)); |
|---|
| 565 | 537 | dac->pcm_indirect.hw_buffer_size = H2_BUF_SIZE; |
|---|
| 538 | + dac->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; |
|---|
| 539 | + dac->pcm_indirect.hw_io = dac->buffer_dma; |
|---|
| 566 | 540 | dac->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); |
|---|
| 567 | 541 | dac->substream = substream; |
|---|
| 568 | 542 | hal2_setup_dac(hal2); |
|---|
| .. | .. |
|---|
| 575 | 549 | |
|---|
| 576 | 550 | switch (cmd) { |
|---|
| 577 | 551 | case SNDRV_PCM_TRIGGER_START: |
|---|
| 578 | | - hal2->dac.pcm_indirect.hw_io = hal2->dac.buffer_dma; |
|---|
| 579 | | - hal2->dac.pcm_indirect.hw_data = 0; |
|---|
| 580 | | - substream->ops->ack(substream); |
|---|
| 581 | 552 | hal2_start_dac(hal2); |
|---|
| 582 | 553 | break; |
|---|
| 583 | 554 | case SNDRV_PCM_TRIGGER_STOP: |
|---|
| .. | .. |
|---|
| 606 | 577 | unsigned char *buf = hal2->dac.buffer + rec->hw_data; |
|---|
| 607 | 578 | |
|---|
| 608 | 579 | memcpy(buf, substream->runtime->dma_area + rec->sw_data, bytes); |
|---|
| 609 | | - dma_cache_sync(NULL, buf, bytes, DMA_TO_DEVICE); |
|---|
| 580 | + dma_sync_single_for_device(hal2->card->dev, |
|---|
| 581 | + hal2->dac.buffer_dma + rec->hw_data, bytes, |
|---|
| 582 | + DMA_TO_DEVICE); |
|---|
| 610 | 583 | |
|---|
| 611 | 584 | } |
|---|
| 612 | 585 | |
|---|
| .. | .. |
|---|
| 615 | 588 | struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); |
|---|
| 616 | 589 | struct hal2_codec *dac = &hal2->dac; |
|---|
| 617 | 590 | |
|---|
| 618 | | - dac->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; |
|---|
| 619 | 591 | return snd_pcm_indirect_playback_transfer(substream, |
|---|
| 620 | 592 | &dac->pcm_indirect, |
|---|
| 621 | 593 | hal2_playback_transfer); |
|---|
| .. | .. |
|---|
| 625 | 597 | { |
|---|
| 626 | 598 | struct snd_pcm_runtime *runtime = substream->runtime; |
|---|
| 627 | 599 | struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); |
|---|
| 628 | | - struct hal2_codec *adc = &hal2->adc; |
|---|
| 629 | | - int err; |
|---|
| 630 | 600 | |
|---|
| 631 | 601 | runtime->hw = hal2_pcm_hw; |
|---|
| 632 | | - |
|---|
| 633 | | - err = hal2_alloc_dmabuf(adc); |
|---|
| 634 | | - if (err) |
|---|
| 635 | | - return err; |
|---|
| 636 | | - return 0; |
|---|
| 602 | + return hal2_alloc_dmabuf(hal2, &hal2->adc, DMA_FROM_DEVICE); |
|---|
| 637 | 603 | } |
|---|
| 638 | 604 | |
|---|
| 639 | 605 | static int hal2_capture_close(struct snd_pcm_substream *substream) |
|---|
| 640 | 606 | { |
|---|
| 641 | 607 | struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); |
|---|
| 642 | 608 | |
|---|
| 643 | | - hal2_free_dmabuf(&hal2->adc); |
|---|
| 609 | + hal2_free_dmabuf(hal2, &hal2->adc, DMA_FROM_DEVICE); |
|---|
| 644 | 610 | return 0; |
|---|
| 645 | 611 | } |
|---|
| 646 | 612 | |
|---|
| .. | .. |
|---|
| 655 | 621 | memset(&adc->pcm_indirect, 0, sizeof(adc->pcm_indirect)); |
|---|
| 656 | 622 | adc->pcm_indirect.hw_buffer_size = H2_BUF_SIZE; |
|---|
| 657 | 623 | adc->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; |
|---|
| 624 | + adc->pcm_indirect.hw_io = adc->buffer_dma; |
|---|
| 658 | 625 | adc->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); |
|---|
| 659 | 626 | adc->substream = substream; |
|---|
| 660 | 627 | hal2_setup_adc(hal2); |
|---|
| .. | .. |
|---|
| 667 | 634 | |
|---|
| 668 | 635 | switch (cmd) { |
|---|
| 669 | 636 | case SNDRV_PCM_TRIGGER_START: |
|---|
| 670 | | - hal2->adc.pcm_indirect.hw_io = hal2->adc.buffer_dma; |
|---|
| 671 | | - hal2->adc.pcm_indirect.hw_data = 0; |
|---|
| 672 | | - printk(KERN_DEBUG "buffer_dma %x\n", hal2->adc.buffer_dma); |
|---|
| 673 | 637 | hal2_start_adc(hal2); |
|---|
| 674 | 638 | break; |
|---|
| 675 | 639 | case SNDRV_PCM_TRIGGER_STOP: |
|---|
| .. | .. |
|---|
| 697 | 661 | struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); |
|---|
| 698 | 662 | unsigned char *buf = hal2->adc.buffer + rec->hw_data; |
|---|
| 699 | 663 | |
|---|
| 700 | | - dma_cache_sync(NULL, buf, bytes, DMA_FROM_DEVICE); |
|---|
| 664 | + dma_sync_single_for_cpu(hal2->card->dev, |
|---|
| 665 | + hal2->adc.buffer_dma + rec->hw_data, bytes, |
|---|
| 666 | + DMA_FROM_DEVICE); |
|---|
| 701 | 667 | memcpy(substream->runtime->dma_area + rec->sw_data, buf, bytes); |
|---|
| 702 | 668 | } |
|---|
| 703 | 669 | |
|---|
| .. | .. |
|---|
| 714 | 680 | static const struct snd_pcm_ops hal2_playback_ops = { |
|---|
| 715 | 681 | .open = hal2_playback_open, |
|---|
| 716 | 682 | .close = hal2_playback_close, |
|---|
| 717 | | - .ioctl = snd_pcm_lib_ioctl, |
|---|
| 718 | | - .hw_params = hal2_pcm_hw_params, |
|---|
| 719 | | - .hw_free = hal2_pcm_hw_free, |
|---|
| 720 | 683 | .prepare = hal2_playback_prepare, |
|---|
| 721 | 684 | .trigger = hal2_playback_trigger, |
|---|
| 722 | 685 | .pointer = hal2_playback_pointer, |
|---|
| .. | .. |
|---|
| 726 | 689 | static const struct snd_pcm_ops hal2_capture_ops = { |
|---|
| 727 | 690 | .open = hal2_capture_open, |
|---|
| 728 | 691 | .close = hal2_capture_close, |
|---|
| 729 | | - .ioctl = snd_pcm_lib_ioctl, |
|---|
| 730 | | - .hw_params = hal2_pcm_hw_params, |
|---|
| 731 | | - .hw_free = hal2_pcm_hw_free, |
|---|
| 732 | 692 | .prepare = hal2_capture_prepare, |
|---|
| 733 | 693 | .trigger = hal2_capture_trigger, |
|---|
| 734 | 694 | .pointer = hal2_capture_pointer, |
|---|
| .. | .. |
|---|
| 753 | 713 | &hal2_playback_ops); |
|---|
| 754 | 714 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, |
|---|
| 755 | 715 | &hal2_capture_ops); |
|---|
| 756 | | - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, |
|---|
| 757 | | - snd_dma_continuous_data(GFP_KERNEL), |
|---|
| 758 | | - 0, 1024 * 1024); |
|---|
| 716 | + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, |
|---|
| 717 | + NULL, 0, 1024 * 1024); |
|---|
| 759 | 718 | |
|---|
| 760 | 719 | return 0; |
|---|
| 761 | 720 | } |
|---|
| .. | .. |
|---|
| 769 | 728 | return 0; |
|---|
| 770 | 729 | } |
|---|
| 771 | 730 | |
|---|
| 772 | | -static struct snd_device_ops hal2_ops = { |
|---|
| 731 | +static const struct snd_device_ops hal2_ops = { |
|---|
| 773 | 732 | .dev_free = hal2_dev_free, |
|---|
| 774 | 733 | }; |
|---|
| 775 | 734 | |
|---|