diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2010-10-12 06:19:28 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-10-15 06:41:25 -0400 |
commit | 93193c2bbcd83bf8bf43433cfb1868d4ca0ac351 (patch) | |
tree | cff90ecf21d26cd2c59cf42f083d1af640a22a59 /sound/soc/sh/fsi.c | |
parent | b67089e4c258a3a4ea8e23ceea4a5b7f8c3099d7 (diff) |
ASoC: fsi: simultaneous playback/recorde support
Current FSI driver had not cared about simultaneous
playback/capture on same port.
This patch add new fsi_stream struct to care it,
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 | 152 |
1 files changed, 94 insertions, 58 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index dfc04bc2809e..507e709f2807 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -113,10 +113,8 @@ | |||
113 | * struct | 113 | * struct |
114 | */ | 114 | */ |
115 | 115 | ||
116 | struct fsi_priv { | 116 | struct fsi_stream { |
117 | void __iomem *base; | ||
118 | struct snd_pcm_substream *substream; | 117 | struct snd_pcm_substream *substream; |
119 | struct fsi_master *master; | ||
120 | 118 | ||
121 | int fifo_max_num; | 119 | int fifo_max_num; |
122 | int chan_num; | 120 | int chan_num; |
@@ -125,6 +123,14 @@ struct fsi_priv { | |||
125 | int buff_len; | 123 | int buff_len; |
126 | int period_len; | 124 | int period_len; |
127 | int period_num; | 125 | int period_num; |
126 | }; | ||
127 | |||
128 | struct fsi_priv { | ||
129 | void __iomem *base; | ||
130 | struct fsi_master *master; | ||
131 | |||
132 | struct fsi_stream playback; | ||
133 | struct fsi_stream capture; | ||
128 | 134 | ||
129 | u32 mst_ctrl; | 135 | u32 mst_ctrl; |
130 | }; | 136 | }; |
@@ -294,9 +300,20 @@ static u32 fsi_get_info_flags(struct fsi_priv *fsi) | |||
294 | master->info->portb_flags; | 300 | master->info->portb_flags; |
295 | } | 301 | } |
296 | 302 | ||
303 | static inline int fsi_stream_is_play(int stream) | ||
304 | { | ||
305 | return stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
306 | } | ||
307 | |||
297 | static inline int fsi_is_play(struct snd_pcm_substream *substream) | 308 | static inline int fsi_is_play(struct snd_pcm_substream *substream) |
298 | { | 309 | { |
299 | return substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 310 | return fsi_stream_is_play(substream->stream); |
311 | } | ||
312 | |||
313 | static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi, | ||
314 | int is_play) | ||
315 | { | ||
316 | return is_play ? &fsi->playback : &fsi->capture; | ||
300 | } | 317 | } |
301 | 318 | ||
302 | static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play) | 319 | static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play) |
@@ -328,35 +345,41 @@ static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) | |||
328 | } | 345 | } |
329 | 346 | ||
330 | static void fsi_stream_push(struct fsi_priv *fsi, | 347 | static void fsi_stream_push(struct fsi_priv *fsi, |
348 | int is_play, | ||
331 | struct snd_pcm_substream *substream, | 349 | struct snd_pcm_substream *substream, |
332 | u32 buffer_len, | 350 | u32 buffer_len, |
333 | u32 period_len) | 351 | u32 period_len) |
334 | { | 352 | { |
335 | fsi->substream = substream; | 353 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); |
336 | fsi->buff_len = buffer_len; | 354 | |
337 | fsi->buff_offset = 0; | 355 | io->substream = substream; |
338 | fsi->period_len = period_len; | 356 | io->buff_len = buffer_len; |
339 | fsi->period_num = 0; | 357 | io->buff_offset = 0; |
358 | io->period_len = period_len; | ||
359 | io->period_num = 0; | ||
340 | } | 360 | } |
341 | 361 | ||
342 | static void fsi_stream_pop(struct fsi_priv *fsi) | 362 | static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) |
343 | { | 363 | { |
344 | fsi->substream = NULL; | 364 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); |
345 | fsi->buff_len = 0; | 365 | |
346 | fsi->buff_offset = 0; | 366 | io->substream = NULL; |
347 | fsi->period_len = 0; | 367 | io->buff_len = 0; |
348 | fsi->period_num = 0; | 368 | io->buff_offset = 0; |
369 | io->period_len = 0; | ||
370 | io->period_num = 0; | ||
349 | } | 371 | } |
350 | 372 | ||
351 | static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) | 373 | static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) |
352 | { | 374 | { |
353 | u32 status; | 375 | u32 status; |
354 | u32 reg = is_play ? DOFF_ST : DIFF_ST; | 376 | u32 reg = is_play ? DOFF_ST : DIFF_ST; |
377 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | ||
355 | int data_num; | 378 | int data_num; |
356 | 379 | ||
357 | status = fsi_reg_read(fsi, reg); | 380 | status = fsi_reg_read(fsi, reg); |
358 | data_num = 0x1ff & (status >> 8); | 381 | data_num = 0x1ff & (status >> 8); |
359 | data_num *= fsi->chan_num; | 382 | data_num *= io->chan_num; |
360 | 383 | ||
361 | return data_num; | 384 | return data_num; |
362 | } | 385 | } |
@@ -372,21 +395,25 @@ static int fsi_num2len(int num, int width) | |||
372 | return num * width; | 395 | return num * width; |
373 | } | 396 | } |
374 | 397 | ||
375 | static int fsi_get_frame_width(struct fsi_priv *fsi) | 398 | static int fsi_get_frame_width(struct fsi_priv *fsi, int is_play) |
376 | { | 399 | { |
377 | struct snd_pcm_substream *substream = fsi->substream; | 400 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); |
401 | struct snd_pcm_substream *substream = io->substream; | ||
378 | struct snd_pcm_runtime *runtime = substream->runtime; | 402 | struct snd_pcm_runtime *runtime = substream->runtime; |
379 | 403 | ||
380 | return frames_to_bytes(runtime, 1) / fsi->chan_num; | 404 | return frames_to_bytes(runtime, 1) / io->chan_num; |
381 | } | 405 | } |
382 | 406 | ||
383 | /* | 407 | /* |
384 | * dma function | 408 | * dma function |
385 | */ | 409 | */ |
386 | 410 | ||
387 | static u8 *fsi_dma_get_area(struct fsi_priv *fsi) | 411 | static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream) |
388 | { | 412 | { |
389 | return fsi->substream->runtime->dma_area + fsi->buff_offset; | 413 | int is_play = fsi_stream_is_play(stream); |
414 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | ||
415 | |||
416 | return io->substream->runtime->dma_area + io->buff_offset; | ||
390 | } | 417 | } |
391 | 418 | ||
392 | static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num) | 419 | static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num) |
@@ -394,7 +421,7 @@ static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num) | |||
394 | u16 *start; | 421 | u16 *start; |
395 | int i; | 422 | int i; |
396 | 423 | ||
397 | start = (u16 *)fsi_dma_get_area(fsi); | 424 | start = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK); |
398 | 425 | ||
399 | for (i = 0; i < num; i++) | 426 | for (i = 0; i < num; i++) |
400 | fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8)); | 427 | fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8)); |
@@ -405,7 +432,8 @@ static void fsi_dma_soft_pop16(struct fsi_priv *fsi, int num) | |||
405 | u16 *start; | 432 | u16 *start; |
406 | int i; | 433 | int i; |
407 | 434 | ||
408 | start = (u16 *)fsi_dma_get_area(fsi); | 435 | start = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE); |
436 | |||
409 | 437 | ||
410 | for (i = 0; i < num; i++) | 438 | for (i = 0; i < num; i++) |
411 | *(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8); | 439 | *(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8); |
@@ -416,7 +444,8 @@ static void fsi_dma_soft_push32(struct fsi_priv *fsi, int num) | |||
416 | u32 *start; | 444 | u32 *start; |
417 | int i; | 445 | int i; |
418 | 446 | ||
419 | start = (u32 *)fsi_dma_get_area(fsi); | 447 | start = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK); |
448 | |||
420 | 449 | ||
421 | for (i = 0; i < num; i++) | 450 | for (i = 0; i < num; i++) |
422 | fsi_reg_write(fsi, DODT, *(start + i)); | 451 | fsi_reg_write(fsi, DODT, *(start + i)); |
@@ -427,7 +456,7 @@ static void fsi_dma_soft_pop32(struct fsi_priv *fsi, int num) | |||
427 | u32 *start; | 456 | u32 *start; |
428 | int i; | 457 | int i; |
429 | 458 | ||
430 | start = (u32 *)fsi_dma_get_area(fsi); | 459 | start = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE); |
431 | 460 | ||
432 | for (i = 0; i < num; i++) | 461 | for (i = 0; i < num; i++) |
433 | *(start + i) = fsi_reg_read(fsi, DIDT); | 462 | *(start + i) = fsi_reg_read(fsi, DIDT); |
@@ -518,14 +547,15 @@ static void fsi_fifo_init(struct fsi_priv *fsi, | |||
518 | struct snd_soc_dai *dai) | 547 | struct snd_soc_dai *dai) |
519 | { | 548 | { |
520 | struct fsi_master *master = fsi_get_master(fsi); | 549 | struct fsi_master *master = fsi_get_master(fsi); |
550 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | ||
521 | u32 ctrl, shift, i; | 551 | u32 ctrl, shift, i; |
522 | 552 | ||
523 | /* get on-chip RAM capacity */ | 553 | /* get on-chip RAM capacity */ |
524 | shift = fsi_master_read(master, FIFO_SZ); | 554 | shift = fsi_master_read(master, FIFO_SZ); |
525 | shift >>= fsi_get_port_shift(fsi, is_play); | 555 | shift >>= fsi_get_port_shift(fsi, is_play); |
526 | shift &= FIFO_SZ_MASK; | 556 | shift &= FIFO_SZ_MASK; |
527 | fsi->fifo_max_num = 256 << shift; | 557 | io->fifo_max_num = 256 << shift; |
528 | dev_dbg(dai->dev, "fifo = %d words\n", fsi->fifo_max_num); | 558 | dev_dbg(dai->dev, "fifo = %d words\n", io->fifo_max_num); |
529 | 559 | ||
530 | /* | 560 | /* |
531 | * The maximum number of sample data varies depending | 561 | * The maximum number of sample data varies depending |
@@ -546,10 +576,10 @@ static void fsi_fifo_init(struct fsi_priv *fsi, | |||
546 | * 7 channels: 32 ( 32 x 7 = 224) | 576 | * 7 channels: 32 ( 32 x 7 = 224) |
547 | * 8 channels: 32 ( 32 x 8 = 256) | 577 | * 8 channels: 32 ( 32 x 8 = 256) |
548 | */ | 578 | */ |
549 | for (i = 1; i < fsi->chan_num; i <<= 1) | 579 | for (i = 1; i < io->chan_num; i <<= 1) |
550 | fsi->fifo_max_num >>= 1; | 580 | io->fifo_max_num >>= 1; |
551 | dev_dbg(dai->dev, "%d channel %d store\n", | 581 | dev_dbg(dai->dev, "%d channel %d store\n", |
552 | fsi->chan_num, fsi->fifo_max_num); | 582 | io->chan_num, io->fifo_max_num); |
553 | 583 | ||
554 | ctrl = is_play ? DOFF_CTL : DIFF_CTL; | 584 | ctrl = is_play ? DOFF_CTL : DIFF_CTL; |
555 | 585 | ||
@@ -572,10 +602,12 @@ static void fsi_soft_all_reset(struct fsi_master *master) | |||
572 | mdelay(10); | 602 | mdelay(10); |
573 | } | 603 | } |
574 | 604 | ||
575 | static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int startup, int is_play) | 605 | static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int startup, int stream) |
576 | { | 606 | { |
577 | struct snd_pcm_runtime *runtime; | 607 | struct snd_pcm_runtime *runtime; |
578 | struct snd_pcm_substream *substream = NULL; | 608 | struct snd_pcm_substream *substream = NULL; |
609 | int is_play = fsi_stream_is_play(stream); | ||
610 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | ||
579 | u32 status_reg = is_play ? DOFF_ST : DIFF_ST; | 611 | u32 status_reg = is_play ? DOFF_ST : DIFF_ST; |
580 | int data_residue_num; | 612 | int data_residue_num; |
581 | int data_num; | 613 | int data_num; |
@@ -585,32 +617,32 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int startup, int is_play) | |||
585 | void (*fn)(struct fsi_priv *fsi, int size); | 617 | void (*fn)(struct fsi_priv *fsi, int size); |
586 | 618 | ||
587 | if (!fsi || | 619 | if (!fsi || |
588 | !fsi->substream || | 620 | !io->substream || |
589 | !fsi->substream->runtime) | 621 | !io->substream->runtime) |
590 | return -EINVAL; | 622 | return -EINVAL; |
591 | 623 | ||
592 | over_period = 0; | 624 | over_period = 0; |
593 | substream = fsi->substream; | 625 | substream = io->substream; |
594 | runtime = substream->runtime; | 626 | runtime = substream->runtime; |
595 | 627 | ||
596 | /* FSI FIFO has limit. | 628 | /* FSI FIFO has limit. |
597 | * So, this driver can not send periods data at a time | 629 | * So, this driver can not send periods data at a time |
598 | */ | 630 | */ |
599 | if (fsi->buff_offset >= | 631 | if (io->buff_offset >= |
600 | fsi_num2offset(fsi->period_num + 1, fsi->period_len)) { | 632 | fsi_num2offset(io->period_num + 1, io->period_len)) { |
601 | 633 | ||
602 | over_period = 1; | 634 | over_period = 1; |
603 | fsi->period_num = (fsi->period_num + 1) % runtime->periods; | 635 | io->period_num = (io->period_num + 1) % runtime->periods; |
604 | 636 | ||
605 | if (0 == fsi->period_num) | 637 | if (0 == io->period_num) |
606 | fsi->buff_offset = 0; | 638 | io->buff_offset = 0; |
607 | } | 639 | } |
608 | 640 | ||
609 | /* get 1 channel data width */ | 641 | /* get 1 channel data width */ |
610 | ch_width = fsi_get_frame_width(fsi); | 642 | ch_width = fsi_get_frame_width(fsi, is_play); |
611 | 643 | ||
612 | /* get residue data number of alsa */ | 644 | /* get residue data number of alsa */ |
613 | data_residue_num = fsi_len2num(fsi->buff_len - fsi->buff_offset, | 645 | data_residue_num = fsi_len2num(io->buff_len - io->buff_offset, |
614 | ch_width); | 646 | ch_width); |
615 | 647 | ||
616 | if (is_play) { | 648 | if (is_play) { |
@@ -620,7 +652,7 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int startup, int is_play) | |||
620 | * data_num_max : number of FSI fifo free space | 652 | * data_num_max : number of FSI fifo free space |
621 | * data_num : number of ALSA residue data | 653 | * data_num : number of ALSA residue data |
622 | */ | 654 | */ |
623 | data_num_max = fsi->fifo_max_num * fsi->chan_num; | 655 | data_num_max = io->fifo_max_num * io->chan_num; |
624 | data_num_max -= fsi_get_fifo_data_num(fsi, is_play); | 656 | data_num_max -= fsi_get_fifo_data_num(fsi, is_play); |
625 | 657 | ||
626 | data_num = data_residue_num; | 658 | data_num = data_residue_num; |
@@ -662,7 +694,7 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int startup, int is_play) | |||
662 | fn(fsi, data_num); | 694 | fn(fsi, data_num); |
663 | 695 | ||
664 | /* update buff_offset */ | 696 | /* update buff_offset */ |
665 | fsi->buff_offset += fsi_num2offset(data_num, ch_width); | 697 | io->buff_offset += fsi_num2offset(data_num, ch_width); |
666 | 698 | ||
667 | /* check fifo status */ | 699 | /* check fifo status */ |
668 | if (!startup) { | 700 | if (!startup) { |
@@ -687,12 +719,12 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int startup, int is_play) | |||
687 | 719 | ||
688 | static int fsi_data_pop(struct fsi_priv *fsi, int startup) | 720 | static int fsi_data_pop(struct fsi_priv *fsi, int startup) |
689 | { | 721 | { |
690 | return fsi_fifo_data_ctrl(fsi, startup, 0); | 722 | return fsi_fifo_data_ctrl(fsi, startup, SNDRV_PCM_STREAM_CAPTURE); |
691 | } | 723 | } |
692 | 724 | ||
693 | static int fsi_data_push(struct fsi_priv *fsi, int startup) | 725 | static int fsi_data_push(struct fsi_priv *fsi, int startup) |
694 | { | 726 | { |
695 | return fsi_fifo_data_ctrl(fsi, startup, 1); | 727 | return fsi_fifo_data_ctrl(fsi, startup, SNDRV_PCM_STREAM_PLAYBACK); |
696 | } | 728 | } |
697 | 729 | ||
698 | static irqreturn_t fsi_interrupt(int irq, void *data) | 730 | static irqreturn_t fsi_interrupt(int irq, void *data) |
@@ -726,14 +758,17 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
726 | struct snd_soc_dai *dai) | 758 | struct snd_soc_dai *dai) |
727 | { | 759 | { |
728 | struct fsi_priv *fsi = fsi_get_priv(substream); | 760 | struct fsi_priv *fsi = fsi_get_priv(substream); |
729 | u32 flags = fsi_get_info_flags(fsi); | ||
730 | struct fsi_master *master = fsi_get_master(fsi); | 761 | struct fsi_master *master = fsi_get_master(fsi); |
762 | struct fsi_stream *io; | ||
763 | u32 flags = fsi_get_info_flags(fsi); | ||
731 | u32 fmt; | 764 | u32 fmt; |
732 | u32 reg; | 765 | u32 reg; |
733 | u32 data; | 766 | u32 data; |
734 | int is_play = fsi_is_play(substream); | 767 | int is_play = fsi_is_play(substream); |
735 | int is_master; | 768 | int is_master; |
736 | 769 | ||
770 | io = fsi_get_stream(fsi, is_play); | ||
771 | |||
737 | pm_runtime_get_sync(dai->dev); | 772 | pm_runtime_get_sync(dai->dev); |
738 | 773 | ||
739 | /* CKG1 */ | 774 | /* CKG1 */ |
@@ -764,29 +799,29 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
764 | switch (fmt) { | 799 | switch (fmt) { |
765 | case SH_FSI_FMT_MONO: | 800 | case SH_FSI_FMT_MONO: |
766 | data = CR_MONO; | 801 | data = CR_MONO; |
767 | fsi->chan_num = 1; | 802 | io->chan_num = 1; |
768 | break; | 803 | break; |
769 | case SH_FSI_FMT_MONO_DELAY: | 804 | case SH_FSI_FMT_MONO_DELAY: |
770 | data = CR_MONO_D; | 805 | data = CR_MONO_D; |
771 | fsi->chan_num = 1; | 806 | io->chan_num = 1; |
772 | break; | 807 | break; |
773 | case SH_FSI_FMT_PCM: | 808 | case SH_FSI_FMT_PCM: |
774 | data = CR_PCM; | 809 | data = CR_PCM; |
775 | fsi->chan_num = 2; | 810 | io->chan_num = 2; |
776 | break; | 811 | break; |
777 | case SH_FSI_FMT_I2S: | 812 | case SH_FSI_FMT_I2S: |
778 | data = CR_I2S; | 813 | data = CR_I2S; |
779 | fsi->chan_num = 2; | 814 | io->chan_num = 2; |
780 | break; | 815 | break; |
781 | case SH_FSI_FMT_TDM: | 816 | case SH_FSI_FMT_TDM: |
782 | fsi->chan_num = is_play ? | 817 | io->chan_num = is_play ? |
783 | SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); | 818 | SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); |
784 | data = CR_TDM | (fsi->chan_num - 1); | 819 | data = CR_TDM | (io->chan_num - 1); |
785 | break; | 820 | break; |
786 | case SH_FSI_FMT_TDM_DELAY: | 821 | case SH_FSI_FMT_TDM_DELAY: |
787 | fsi->chan_num = is_play ? | 822 | io->chan_num = is_play ? |
788 | SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); | 823 | SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); |
789 | data = CR_TDM_D | (fsi->chan_num - 1); | 824 | data = CR_TDM_D | (io->chan_num - 1); |
790 | break; | 825 | break; |
791 | case SH_FSI_FMT_SPDIF: | 826 | case SH_FSI_FMT_SPDIF: |
792 | if (master->core->ver < 2) { | 827 | if (master->core->ver < 2) { |
@@ -794,7 +829,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
794 | return -EINVAL; | 829 | return -EINVAL; |
795 | } | 830 | } |
796 | data = CR_SPDIF; | 831 | data = CR_SPDIF; |
797 | fsi->chan_num = 2; | 832 | io->chan_num = 2; |
798 | fsi_spdif_clk_ctrl(fsi, 1); | 833 | fsi_spdif_clk_ctrl(fsi, 1); |
799 | fsi_reg_mask_set(fsi, OUT_SEL, 0x0010, 0x0010); | 834 | fsi_reg_mask_set(fsi, OUT_SEL, 0x0010, 0x0010); |
800 | break; | 835 | break; |
@@ -836,14 +871,14 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
836 | 871 | ||
837 | switch (cmd) { | 872 | switch (cmd) { |
838 | case SNDRV_PCM_TRIGGER_START: | 873 | case SNDRV_PCM_TRIGGER_START: |
839 | fsi_stream_push(fsi, substream, | 874 | fsi_stream_push(fsi, is_play, substream, |
840 | frames_to_bytes(runtime, runtime->buffer_size), | 875 | frames_to_bytes(runtime, runtime->buffer_size), |
841 | frames_to_bytes(runtime, runtime->period_size)); | 876 | frames_to_bytes(runtime, runtime->period_size)); |
842 | ret = is_play ? fsi_data_push(fsi, 1) : fsi_data_pop(fsi, 1); | 877 | ret = is_play ? fsi_data_push(fsi, 1) : fsi_data_pop(fsi, 1); |
843 | break; | 878 | break; |
844 | case SNDRV_PCM_TRIGGER_STOP: | 879 | case SNDRV_PCM_TRIGGER_STOP: |
845 | fsi_irq_disable(fsi, is_play); | 880 | fsi_irq_disable(fsi, is_play); |
846 | fsi_stream_pop(fsi); | 881 | fsi_stream_pop(fsi, is_play); |
847 | break; | 882 | break; |
848 | } | 883 | } |
849 | 884 | ||
@@ -991,9 +1026,10 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) | |||
991 | { | 1026 | { |
992 | struct snd_pcm_runtime *runtime = substream->runtime; | 1027 | struct snd_pcm_runtime *runtime = substream->runtime; |
993 | struct fsi_priv *fsi = fsi_get_priv(substream); | 1028 | struct fsi_priv *fsi = fsi_get_priv(substream); |
1029 | struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream)); | ||
994 | long location; | 1030 | long location; |
995 | 1031 | ||
996 | location = (fsi->buff_offset - 1); | 1032 | location = (io->buff_offset - 1); |
997 | if (location < 0) | 1033 | if (location < 0) |
998 | location = 0; | 1034 | location = 0; |
999 | 1035 | ||