diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2010-09-17 00:49:05 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-09-20 15:45:04 -0400 |
commit | d8b33534921796825a839cab222a1888c5e7256e (patch) | |
tree | ca85238378e48f89915d4aa1946379ebdd4cbd56 /sound/soc/sh/fsi.c | |
parent | 5bfb9ad0840b15d9c45d25a05e4ff9ae5eb80508 (diff) |
ASoC: fsi: merge fsi_data_push/pop to fsi_fifo_data_ctrl
Current FSI driver had data push/pop functions.
But the main operation of these 2 were very similar.
This mean it is possible to merge these to 1 function.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/sh/fsi.c')
-rw-r--r-- | sound/soc/sh/fsi.c | 162 |
1 files changed, 67 insertions, 95 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 3448170debe4..82c6190b46f3 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -560,16 +560,18 @@ static void fsi_soft_all_reset(struct fsi_master *master) | |||
560 | mdelay(10); | 560 | mdelay(10); |
561 | } | 561 | } |
562 | 562 | ||
563 | /* playback interrupt */ | 563 | static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int startup, int is_play) |
564 | static int fsi_data_push(struct fsi_priv *fsi, int startup) | ||
565 | { | 564 | { |
566 | struct snd_pcm_runtime *runtime; | 565 | struct snd_pcm_runtime *runtime; |
567 | struct snd_pcm_substream *substream = NULL; | 566 | struct snd_pcm_substream *substream = NULL; |
568 | u32 status; | 567 | u32 status; |
569 | int push_num; | 568 | u32 status_reg = is_play ? DOFF_ST : DIFF_ST; |
570 | int push_num_max; | 569 | int data_residue_num; |
570 | int data_num; | ||
571 | int data_num_max; | ||
571 | int ch_width; | 572 | int ch_width; |
572 | int over_period; | 573 | int over_period; |
574 | void (*fn)(struct fsi_priv *fsi, int size); | ||
573 | 575 | ||
574 | if (!fsi || | 576 | if (!fsi || |
575 | !fsi->substream || | 577 | !fsi->substream || |
@@ -596,29 +598,63 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup) | |||
596 | /* get 1 channel data width */ | 598 | /* get 1 channel data width */ |
597 | ch_width = frames_to_bytes(runtime, 1) / fsi->chan_num; | 599 | ch_width = frames_to_bytes(runtime, 1) / fsi->chan_num; |
598 | 600 | ||
599 | /* number of push data */ | 601 | /* get residue data number of alsa */ |
600 | push_num = fsi_len2num(fsi->buff_len - fsi->buff_offset, ch_width); | 602 | data_residue_num = fsi_len2num(fsi->buff_len - fsi->buff_offset, |
601 | 603 | ch_width); | |
602 | /* max number of push data */ | 604 | |
603 | push_num_max = (fsi->fifo_max_num * fsi->chan_num) - | 605 | if (is_play) { |
604 | fsi_get_fifo_data_num(fsi, 1); | 606 | /* |
607 | * for play-back | ||
608 | * | ||
609 | * data_num_max : number of FSI fifo free space | ||
610 | * data_num : number of ALSA residue data | ||
611 | */ | ||
612 | data_num_max = fsi->fifo_max_num * fsi->chan_num; | ||
613 | data_num_max -= fsi_get_fifo_data_num(fsi, is_play); | ||
614 | |||
615 | data_num = data_residue_num; | ||
616 | |||
617 | switch (ch_width) { | ||
618 | case 2: | ||
619 | fn = fsi_dma_soft_push16; | ||
620 | break; | ||
621 | case 4: | ||
622 | fn = fsi_dma_soft_push32; | ||
623 | break; | ||
624 | default: | ||
625 | return -EINVAL; | ||
626 | } | ||
627 | } else { | ||
628 | /* | ||
629 | * for capture | ||
630 | * | ||
631 | * data_num_max : number of ALSA free space | ||
632 | * data_num : number of data in FSI fifo | ||
633 | */ | ||
634 | data_num_max = data_residue_num; | ||
635 | data_num = fsi_get_fifo_data_num(fsi, is_play); | ||
636 | |||
637 | switch (ch_width) { | ||
638 | case 2: | ||
639 | fn = fsi_dma_soft_pop16; | ||
640 | break; | ||
641 | case 4: | ||
642 | fn = fsi_dma_soft_pop32; | ||
643 | break; | ||
644 | default: | ||
645 | return -EINVAL; | ||
646 | } | ||
647 | } | ||
605 | 648 | ||
606 | push_num = min(push_num, push_num_max); | 649 | data_num = min(data_num, data_num_max); |
607 | 650 | ||
608 | switch (ch_width) { | 651 | fn(fsi, data_num); |
609 | case 2: | ||
610 | fsi_dma_soft_push16(fsi, push_num); | ||
611 | break; | ||
612 | case 4: | ||
613 | fsi_dma_soft_push32(fsi, push_num); | ||
614 | break; | ||
615 | default: | ||
616 | return -EINVAL; | ||
617 | } | ||
618 | 652 | ||
619 | fsi->buff_offset += fsi_num2offset(push_num, ch_width); | 653 | /* update buff_offset */ |
654 | fsi->buff_offset += fsi_num2offset(data_num, ch_width); | ||
620 | 655 | ||
621 | status = fsi_reg_read(fsi, DOFF_ST); | 656 | /* check fifo status */ |
657 | status = fsi_reg_read(fsi, status_reg); | ||
622 | if (!startup) { | 658 | if (!startup) { |
623 | struct snd_soc_dai *dai = fsi_get_dai(substream); | 659 | struct snd_soc_dai *dai = fsi_get_dai(substream); |
624 | 660 | ||
@@ -627,9 +663,10 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup) | |||
627 | if (status & ERR_UNDER) | 663 | if (status & ERR_UNDER) |
628 | dev_err(dai->dev, "under run\n"); | 664 | dev_err(dai->dev, "under run\n"); |
629 | } | 665 | } |
630 | fsi_reg_write(fsi, DOFF_ST, 0); | 666 | fsi_reg_write(fsi, status_reg, 0); |
631 | 667 | ||
632 | fsi_irq_enable(fsi, 1); | 668 | /* re-enable irq */ |
669 | fsi_irq_enable(fsi, is_play); | ||
633 | 670 | ||
634 | if (over_period) | 671 | if (over_period) |
635 | snd_pcm_period_elapsed(substream); | 672 | snd_pcm_period_elapsed(substream); |
@@ -639,77 +676,12 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup) | |||
639 | 676 | ||
640 | static int fsi_data_pop(struct fsi_priv *fsi, int startup) | 677 | static int fsi_data_pop(struct fsi_priv *fsi, int startup) |
641 | { | 678 | { |
642 | struct snd_pcm_runtime *runtime; | 679 | return fsi_fifo_data_ctrl(fsi, startup, 0); |
643 | struct snd_pcm_substream *substream = NULL; | 680 | } |
644 | u32 status; | ||
645 | int pop_num; | ||
646 | int pop_num_max; | ||
647 | int ch_width; | ||
648 | int over_period; | ||
649 | |||
650 | if (!fsi || | ||
651 | !fsi->substream || | ||
652 | !fsi->substream->runtime) | ||
653 | return -EINVAL; | ||
654 | |||
655 | over_period = 0; | ||
656 | substream = fsi->substream; | ||
657 | runtime = substream->runtime; | ||
658 | |||
659 | /* FSI FIFO has limit. | ||
660 | * So, this driver can not send periods data at a time | ||
661 | */ | ||
662 | if (fsi->buff_offset >= | ||
663 | fsi_num2offset(fsi->period_num + 1, fsi->period_len)) { | ||
664 | |||
665 | over_period = 1; | ||
666 | fsi->period_num = (fsi->period_num + 1) % runtime->periods; | ||
667 | |||
668 | if (0 == fsi->period_num) | ||
669 | fsi->buff_offset = 0; | ||
670 | } | ||
671 | |||
672 | /* get 1 channel data width */ | ||
673 | ch_width = frames_to_bytes(runtime, 1) / fsi->chan_num; | ||
674 | |||
675 | /* get free space for alsa */ | ||
676 | pop_num_max = fsi_len2num(fsi->buff_len - fsi->buff_offset, ch_width); | ||
677 | |||
678 | /* get recv size */ | ||
679 | pop_num = fsi_get_fifo_data_num(fsi, 0); | ||
680 | |||
681 | pop_num = min(pop_num_max, pop_num); | ||
682 | |||
683 | switch (ch_width) { | ||
684 | case 2: | ||
685 | fsi_dma_soft_pop16(fsi, pop_num); | ||
686 | break; | ||
687 | case 4: | ||
688 | fsi_dma_soft_pop32(fsi, pop_num); | ||
689 | break; | ||
690 | default: | ||
691 | return -EINVAL; | ||
692 | } | ||
693 | |||
694 | fsi->buff_offset += fsi_num2offset(pop_num, ch_width); | ||
695 | |||
696 | status = fsi_reg_read(fsi, DIFF_ST); | ||
697 | if (!startup) { | ||
698 | struct snd_soc_dai *dai = fsi_get_dai(substream); | ||
699 | |||
700 | if (status & ERR_OVER) | ||
701 | dev_err(dai->dev, "over run\n"); | ||
702 | if (status & ERR_UNDER) | ||
703 | dev_err(dai->dev, "under run\n"); | ||
704 | } | ||
705 | fsi_reg_write(fsi, DIFF_ST, 0); | ||
706 | |||
707 | fsi_irq_enable(fsi, 0); | ||
708 | |||
709 | if (over_period) | ||
710 | snd_pcm_period_elapsed(substream); | ||
711 | 681 | ||
712 | return 0; | 682 | static int fsi_data_push(struct fsi_priv *fsi, int startup) |
683 | { | ||
684 | return fsi_fifo_data_ctrl(fsi, startup, 1); | ||
713 | } | 685 | } |
714 | 686 | ||
715 | static irqreturn_t fsi_interrupt(int irq, void *data) | 687 | static irqreturn_t fsi_interrupt(int irq, void *data) |