mailman.alsa-project.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

Sound-open-firmware

Thread Start a new thread
Download
Threads by month
  • ----- 2025 -----
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2021 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2020 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2019 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2018 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2017 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2016 -----
  • December
  • November
  • October
sound-open-firmware@alsa-project.org

March 2017

  • 3 participants
  • 6 discussions
[Sound-open-firmware] [PATCH] work: enable/disable workq timer following each timer_set/clear()
by Keyon Jie 16 Mar '17

16 Mar '17
We need enable/disable workq timer also after each calling to set/clear timer, but not only CPU frequency change, so merge them into work_set/clear_timer(). Signed-off-by: Keyon Jie <yang.jie(a)linux.intel.com> --- src/lib/work.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/work.c b/src/lib/work.c index 55a6f90..7da6f68 100644 --- a/src/lib/work.c +++ b/src/lib/work.c @@ -75,11 +75,13 @@ static struct work_queue *queue_; static inline void work_set_timer(struct work_queue *queue, uint32_t ticks) { queue->ts->timer_set(&queue->ts->timer, ticks); + timer_enable(&queue->ts->timer); } static inline void work_clear_timer(struct work_queue *queue) { queue->ts->timer_clear(&queue->ts->timer); + timer_disable(&queue->ts->timer); } static inline uint32_t work_get_timer(struct work_queue *queue) @@ -308,10 +310,8 @@ static void work_notify(int message, void *data, void *event_data) queue->ticks_per_usec * PLATFORM_WORKQ_WINDOW; queue_recalc_timers(queue, clk_data); queue_reschedule(queue); - timer_enable(&queue->ts->timer); } else if (message == CLOCK_NOTIFY_PRE) { /* CPU frequency update pending */ - timer_disable(&queue->ts->timer); } spin_unlock_irq(&queue->lock, flags); -- 2.7.4
2 1
0 0
[Sound-open-firmware] [PATCH] ssp: add handle for default clk type
by Keyon Jie 16 Mar '17

16 Mar '17
Add default clk type SSP_CLK_DEFAULT and the handle for it Signed-off-by: Keyon Jie <yang.jie(a)linux.intel.com> --- src/drivers/ssp.c | 2 ++ src/include/reef/ssp.h | 1 + 2 files changed, 3 insertions(+) diff --git a/src/drivers/ssp.c b/src/drivers/ssp.c index b22e06d..c0d4ef3 100644 --- a/src/drivers/ssp.c +++ b/src/drivers/ssp.c @@ -101,6 +101,8 @@ static inline int ssp_set_config(struct dai *dai, struct dai_config *dai_config) case DAI_FMT_CBS_CFM: sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR | SSCR1_SCFR; break; + case SSP_CLK_DEFAULT: + break; default: return -EINVAL; } diff --git a/src/include/reef/ssp.h b/src/include/reef/ssp.h index b1c1afd..b1f370b 100644 --- a/src/include/reef/ssp.h +++ b/src/include/reef/ssp.h @@ -42,6 +42,7 @@ #define SSP_CLK_NET_PLL 1 #define SSP_CLK_EXT 2 #define SSP_CLK_NET 3 +#define SSP_CLK_DEFAULT 4 /* SSP register offsets */ #define SSCR0 0x00 -- 2.7.4
2 1
0 0
[Sound-open-firmware] [PATCH] work: fix typos for comment message
by Keyon Jie 16 Mar '17

16 Mar '17
Signed-off-by: Keyon Jie <yang.jie(a)linux.intel.com> --- src/lib/work.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/work.c b/src/lib/work.c index f93da31..8062ca5 100644 --- a/src/lib/work.c +++ b/src/lib/work.c @@ -300,7 +300,7 @@ static void work_notify(int message, void *data, void *event_data) spin_lock_irq(&queue->lock, flags); - /* we need to re-caclulate timer when CPU freqency changes */ + /* we need to re-caclulate timer when CPU frequency changes */ if (message == CLOCK_NOTIFY_POST) { /* CPU frequency update complete */ @@ -336,7 +336,7 @@ void work_schedule(struct work_queue *queue, struct work *w, uint32_t timeout) goto out; } - /* convert timeout microsecs to CPU clock ticks */ + /* convert timeout micro seconds to CPU clock ticks */ w->timeout = queue->ticks_per_usec * timeout + work_get_timer(queue); /* insert work into list */ -- 2.7.4
2 1
0 0
[Sound-open-firmware] [PATCH] ssp: move macros and inlines to head file
by Keyon Jie 08 Mar '17

08 Mar '17
Move macros and inline functions to head file, and make the .c file clean. Signed-off-by: Keyon Jie <yang.jie(a)linux.intel.com> --- src/drivers/ssp.c | 113 ---------------------------------------------- src/include/reef/ssp.h | 118 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 113 deletions(-) diff --git a/src/drivers/ssp.c b/src/drivers/ssp.c index 2b5b89e..b22e06d 100644 --- a/src/drivers/ssp.c +++ b/src/drivers/ssp.c @@ -30,129 +30,16 @@ */ #include <errno.h> -#include <reef/dai.h> -#include <reef/io.h> #include <reef/stream.h> #include <reef/ssp.h> #include <reef/alloc.h> #include <reef/interrupt.h> -#include <reef/lock.h> -#include <reef/work.h> -#include <reef/trace.h> -#include <reef/wait.h> - -/* SSCR0 bits */ -#define SSCR0_DSS_MASK (0x0000000f) -#define SSCR0_DSIZE(x) ((x) - 1) -#define SSCR0_FRF (0x00000030) -#define SSCR0_MOT (00 << 4) -#define SSCR0_TI (1 << 4) -#define SSCR0_NAT (2 << 4) -#define SSCR0_PSP (3 << 4) -#define SSCR0_ECS (1 << 6) -#define SSCR0_SSE (1 << 7) -#define SSCR0_SCR(x) ((x) << 8) -#define SSCR0_EDSS (1 << 20) -#define SSCR0_NCS (1 << 21) -#define SSCR0_RIM (1 << 22) -#define SSCR0_TUM (1 << 23) -#define SSCR0_FRDC (0x07000000) -#define SSCR0_ACS (1 << 30) -#define SSCR0_MOD (1 << 31) - -/* SSCR1 bits */ -#define SSCR1_RIE (1 << 0) -#define SSCR1_TIE (1 << 1) -#define SSCR1_LBM (1 << 2) -#define SSCR1_SPO (1 << 3) -#define SSCR1_SPH (1 << 4) -#define SSCR1_MWDS (1 << 5) -#define SSCR1_TFT_MASK (0x000003c0) -#define SSCR1_TX(x) (((x) - 1) << 6) -#define SSCR1_RFT_MASK (0x00003c00) -#define SSCR1_RX(x) (((x) - 1) << 10) -#define SSCR1_EFWR (1 << 14) -#define SSCR1_STRF (1 << 15) -#define SSCR1_IFS (1 << 16) -#define SSCR1_PINTE (1 << 18) -#define SSCR1_TINTE (1 << 19) -#define SSCR1_RSRE (1 << 20) -#define SSCR1_TSRE (1 << 21) -#define SSCR1_TRAIL (1 << 22) -#define SSCR1_RWOT (1 << 23) -#define SSCR1_SFRMDIR (1 << 24) -#define SSCR1_SCLKDIR (1 << 25) -#define SSCR1_ECRB (1 << 26) -#define SSCR1_ECRA (1 << 27) -#define SSCR1_SCFR (1 << 28) -#define SSCR1_EBCEI (1 << 29) -#define SSCR1_TTE (1 << 30) -#define SSCR1_TTELP (1 << 31) - -/* SSR bits */ -#define SSSR_TNF (1 << 2) -#define SSSR_RNE (1 << 3) -#define SSSR_BSY (1 << 4) -#define SSSR_TFS (1 << 5) -#define SSSR_RFS (1 << 6) -#define SSSR_ROR (1 << 7) - -/* SSPSP bits */ -#define SSPSP_SCMODE(x) ((x) << 0) -#define SSPSP_SFRMP (1 << 2) -#define SSPSP_ETDS (1 << 3) -#define SSPSP_STRTDLY(x) ((x) << 4) -#define SSPSP_DMYSTRT(x) ((x) << 7) -#define SSPSP_SFRMDLY(x) ((x) << 9) -#define SSPSP_SFRMWDTH(x) ((x) << 16) -#define SSPSP_DMYSTOP(x) ((x) << 23) -#define SSPSP_FSRT (1 << 25) - -/* SFIFOTT bits */ -#define SFIFOTT_TX(x) (x - 1) -#define SFIFOTT_RX(x) ((x - 1) << 16) - -/* SSP port status */ -#define SSP_STATE_INIT 0 -#define SSP_STATE_IDLE 1 -#define SSP_STATE_RUNNING 2 -#define SSP_STATE_DRAINING 3 -#define SSP_STATE_PAUSING 4 -#define SSP_STATE_PAUSED 5 /* tracing */ #define trace_ssp(__e) trace_event(TRACE_CLASS_SSP, __e) #define trace_ssp_error(__e) trace_error(TRACE_CLASS_SSP, __e) #define tracev_ssp(__e) tracev_event(TRACE_CLASS_SSP, __e) -/* SSP private data */ -struct ssp_pdata { - uint32_t sscr0; - uint32_t sscr1; - uint32_t psp; - struct work work; - spinlock_t lock; - uint32_t state[2]; /* SSP_STATE_ for each direction */ - completion_t drain_complete; - -}; - -static inline void ssp_write(struct dai *dai, uint32_t reg, uint32_t value) -{ - io_reg_write(dai_base(dai) + reg, value); -} - -static inline uint32_t ssp_read(struct dai *dai, uint32_t reg) -{ - return io_reg_read(dai_base(dai) + reg); -} - -static inline void ssp_update_bits(struct dai *dai, uint32_t reg, uint32_t mask, - uint32_t value) -{ - io_reg_update_bits(dai_base(dai) + reg, mask, value); -} - /* save SSP context prior to entering D3 */ static int ssp_context_store(struct dai *dai) { diff --git a/src/include/reef/ssp.h b/src/include/reef/ssp.h index 74f0be6..b1c1afd 100644 --- a/src/include/reef/ssp.h +++ b/src/include/reef/ssp.h @@ -32,6 +32,11 @@ #define __INCLUDE_SSP__ #include <reef/dai.h> +#include <reef/io.h> +#include <reef/lock.h> +#include <reef/work.h> +#include <reef/trace.h> +#include <reef/wait.h> #define SSP_CLK_AUDIO 0 #define SSP_CLK_NET_PLL 1 @@ -53,4 +58,117 @@ extern const struct dai_ops ssp_ops; +/* SSCR0 bits */ +#define SSCR0_DSS_MASK (0x0000000f) +#define SSCR0_DSIZE(x) ((x) - 1) +#define SSCR0_FRF (0x00000030) +#define SSCR0_MOT (00 << 4) +#define SSCR0_TI (1 << 4) +#define SSCR0_NAT (2 << 4) +#define SSCR0_PSP (3 << 4) +#define SSCR0_ECS (1 << 6) +#define SSCR0_SSE (1 << 7) +#define SSCR0_SCR_MASK (0x000fff00) +#define SSCR0_SCR(x) ((x) << 8) +#define SSCR0_EDSS (1 << 20) +#define SSCR0_NCS (1 << 21) +#define SSCR0_RIM (1 << 22) +#define SSCR0_TUM (1 << 23) +#define SSCR0_FRDC (0x07000000) +#define SSCR0_ACS (1 << 30) +#define SSCR0_MOD (1 << 31) + +/* SSCR1 bits */ +#define SSCR1_RIE (1 << 0) +#define SSCR1_TIE (1 << 1) +#define SSCR1_LBM (1 << 2) +#define SSCR1_SPO (1 << 3) +#define SSCR1_SPH (1 << 4) +#define SSCR1_MWDS (1 << 5) +#define SSCR1_TFT_MASK (0x000003c0) +#define SSCR1_TX(x) (((x) - 1) << 6) +#define SSCR1_RFT_MASK (0x00003c00) +#define SSCR1_RX(x) (((x) - 1) << 10) +#define SSCR1_EFWR (1 << 14) +#define SSCR1_STRF (1 << 15) +#define SSCR1_IFS (1 << 16) +#define SSCR1_PINTE (1 << 18) +#define SSCR1_TINTE (1 << 19) +#define SSCR1_RSRE (1 << 20) +#define SSCR1_TSRE (1 << 21) +#define SSCR1_TRAIL (1 << 22) +#define SSCR1_RWOT (1 << 23) +#define SSCR1_SFRMDIR (1 << 24) +#define SSCR1_SCLKDIR (1 << 25) +#define SSCR1_ECRB (1 << 26) +#define SSCR1_ECRA (1 << 27) +#define SSCR1_SCFR (1 << 28) +#define SSCR1_EBCEI (1 << 29) +#define SSCR1_TTE (1 << 30) +#define SSCR1_TTELP (1 << 31) + +/* SSR bits */ +#define SSSR_TNF (1 << 2) +#define SSSR_RNE (1 << 3) +#define SSSR_BSY (1 << 4) +#define SSSR_TFS (1 << 5) +#define SSSR_RFS (1 << 6) +#define SSSR_ROR (1 << 7) + +/* SSPSP bits */ +#define SSPSP_SCMODE(x) ((x) << 0) +#define SSPSP_SFRMP (1 << 2) +#define SSPSP_ETDS (1 << 3) +#define SSPSP_STRTDLY(x) ((x) << 4) +#define SSPSP_DMYSTRT(x) ((x) << 7) +#define SSPSP_SFRMDLY(x) ((x) << 9) +#define SSPSP_SFRMWDTH(x) ((x) << 16) +#define SSPSP_DMYSTOP(x) ((x) << 23) +#define SSPSP_FSRT (1 << 25) + +/* SFIFOTT bits */ +#define SFIFOTT_TX(x) (x - 1) +#define SFIFOTT_RX(x) ((x - 1) << 16) + +/* SSP port status */ +#define SSP_STATE_INIT 0 +#define SSP_STATE_RUNNING 1 +#define SSP_STATE_IDLE 2 +#define SSP_STATE_DRAINING 3 +#define SSP_STATE_PAUSING 4 +#define SSP_STATE_PAUSED 5 + +/* tracing */ +#define trace_ssp(__e) trace_event(TRACE_CLASS_SSP, __e) +#define trace_ssp_error(__e) trace_error(TRACE_CLASS_SSP, __e) +#define tracev_ssp(__e) tracev_event(TRACE_CLASS_SSP, __e) + +/* SSP private data */ +struct ssp_pdata { + uint32_t sscr0; + uint32_t sscr1; + uint32_t psp; + struct work work; + spinlock_t lock; + uint32_t state[2]; /* SSP_STATE_ for each direction */ + completion_t drain_complete; +}; + +static inline void ssp_write(struct dai *dai, uint32_t reg, uint32_t value) +{ + io_reg_write(dai_base(dai) + reg, value); +} + +static inline uint32_t ssp_read(struct dai *dai, uint32_t reg) +{ + return io_reg_read(dai_base(dai) + reg); +} + +static inline void ssp_update_bits(struct dai *dai, uint32_t reg, uint32_t mask, + uint32_t value) +{ + io_reg_update_bits(dai_base(dai) + reg, mask, value); +} + + #endif -- 2.7.4
3 2
0 0
[Sound-open-firmware] [PATCH] host: remove host side buffer check and fix for capture
by Keyon Jie 02 Mar '17

02 Mar '17
We assume that there are always datas/spaces for playback/capture, and then don't need to check the host side buffer pointers, here remove these buffer check related code to save about 0.6KB to the firmware binary size. We also do code cleanup for host in this patch: remove superfluous prefix 'host_' for host_data members, merge host_dma_cb_playback() and host_dma_cb_capture() as they have most common code, and the latter change can save about 0.25KB to firmware binary size. Furthermore, we also fix the capture doesn't work issue at the same time. Signed-off-by: Keyon Jie <yang.jie(a)linux.intel.com> --- src/audio/host.c | 302 +++++++++---------------------------------------------- 1 file changed, 50 insertions(+), 252 deletions(-) diff --git a/src/audio/host.c b/src/audio/host.c index 12aee59..4448af4 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -65,19 +65,16 @@ struct host_data { completion_t complete; struct period_desc *period; struct comp_buffer *dma_buffer; - struct work work; /* local and host DMA buffer info */ struct hc_buf host; struct hc_buf local; uint32_t host_size; - volatile uint32_t *host_pos; /* read pos, update to mailbox for host side */ - uint32_t host_pos_read; /* host buffer read pos in bytes */ - uint32_t host_period_bytes; /* host period size in bytes */ - uint32_t host_period_pos; /* position in current host perid */ - uint32_t host_app_pos; /* host buffer app write pos, points to mailbox */ - uint32_t host_avail; /* host buffer available size */ - uint32_t host_free; /* host buffer free size */ + /* host possition reporting related */ + volatile uint32_t *host_pos; /* read/write pos, update to mailbox for host side */ + uint32_t report_period; /* host_pos report/update to host side period, in bytes */ + uint32_t report_pos; /* position in current report period */ + uint32_t local_pos; /* the host side buffer local read/write possition, in bytes */ /* pointers set during params to host or local above */ struct hc_buf *source; struct hc_buf *sink; @@ -89,30 +86,6 @@ struct host_data { struct comp_position cp; }; -static inline void host_update_buffer_produce(struct host_data *hd) -{ - if (hd->host_pos_read < hd->host_app_pos) - hd->host_avail = hd->host_app_pos - hd->host_pos_read; - else if (hd->host_pos_read == hd->host_app_pos) - hd->host_avail = hd->host_size; /* full */ - else - hd->host_avail = hd->host_size -hd->host_pos_read + - hd->host_app_pos; - hd->host_free = hd->host_size - hd->host_avail; -} - -static inline void host_update_buffer_consume(struct host_data *hd) -{ - if (hd->host_pos_read < hd->host_app_pos) - hd->host_avail = hd->host_app_pos - hd->host_pos_read; - else if (hd->host_pos_read == hd->host_app_pos) - hd->host_avail = 0; /* empty */ - else - hd->host_avail = hd->host_size -hd->host_pos_read + - hd->host_app_pos; - hd->host_free = hd->host_size - hd->host_avail; -} - static inline struct dma_sg_elem *next_buffer(struct hc_buf *hc) { struct dma_sg_elem *elem; @@ -127,16 +100,17 @@ static inline struct dma_sg_elem *next_buffer(struct hc_buf *hc) } /* - * Host period copy to DSP DMA completion. This is called when DMA completes - * its current transfer from host to DSP. The host memory is not guaranteed - * to be continuous and also not guaranteed to have a period/buffer size that - * is a multiple of the DSP period size. This means we must check we do not + * Host period copy between DSP and host DMA completion. + * This is called by DMA driver every time when DMA completes its current + * transfer between host and DSP. The host memory is not guaranteed to be + * continuous and also not guaranteed to have a period/buffer size that is a + * multiple of the DSP period size. This means we must check we do not * overflow host period/buffer/page boundaries on each transfer and split the * DMA transfer if we do overflow. */ -static void host_dma_cb_playback(struct comp_dev *dev, - struct dma_sg_elem *next) +static void host_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) { + struct comp_dev *dev = (struct comp_dev *)data; struct host_data *hd = comp_get_drvdata(dev); struct dma_sg_elem *local_elem, *source_elem, *sink_elem; struct comp_buffer *dma_buffer; @@ -145,42 +119,50 @@ static void host_dma_cb_playback(struct comp_dev *dev, local_elem = list_first_item(&hd->config.elem_list, struct dma_sg_elem, list); - trace_host("Cpp"); + trace_host("CpC"); /* update buffer positions */ dma_buffer = hd->dma_buffer; - dma_buffer->w_ptr += local_elem->size; + if (hd->params.direction == STREAM_DIRECTION_PLAYBACK) { + dma_buffer->w_ptr += local_elem->size; + + if (dma_buffer->w_ptr >= dma_buffer->end_addr) + dma_buffer->w_ptr = dma_buffer->addr; +#if 0 + trace_value((uint32_t)(hd->dma_buffer->w_ptr - hd->dma_buffer->addr)); +#endif - if (dma_buffer->w_ptr >= dma_buffer->end_addr) - dma_buffer->w_ptr = dma_buffer->addr; + /* recalc available buffer space */ + comp_update_buffer_produce(hd->dma_buffer); + } else { + dma_buffer->r_ptr += local_elem->size; + if (dma_buffer->r_ptr >= dma_buffer->end_addr) + dma_buffer->r_ptr = dma_buffer->addr; #if 0 - trace_value((uint32_t)(hd->dma_buffer->w_ptr - hd->dma_buffer->addr)); + trace_value((uint32_t)(hd->dma_buffer->r_ptr - hd->dma_buffer->addr)); #endif - /* recalc available buffer space */ - comp_update_buffer_produce(hd->dma_buffer); + /* recalc available buffer space */ + comp_update_buffer_consume(hd->dma_buffer); + } /* new local period, update host buffer position blks */ - hd->host_pos_read += local_elem->size; + hd->local_pos += local_elem->size; /* buffer overlap ? */ - if (hd->host_pos_read >= hd->host_size) - hd->host_pos_read = 0; - host_update_buffer_consume(hd); + if (hd->local_pos >= hd->host_size) + hd->local_pos = 0; /* send IPC message to driver if needed */ - hd->host_period_pos += local_elem->size; - if (hd->host_period_pos >= hd->host_period_bytes) { - hd->host_period_pos = 0; - /* for the last bytes/period, send notification later */ - if (hd->host_avail) { - /* update for host side */ - if (hd->host_pos) { - *hd->host_pos = hd->host_pos_read; - ipc_stream_send_notification(dev, &hd->cp); - } + hd->report_pos += local_elem->size; + if (hd->report_pos >= hd->report_period) { + hd->report_pos = 0; + /* update for host side */ + if (hd->host_pos) { + *hd->host_pos = hd->local_pos; + ipc_stream_send_notification(dev, &hd->cp); } } @@ -216,29 +198,6 @@ static void host_dma_cb_playback(struct comp_dev *dev, } local_elem->size = next_size; - /* check if avail is enough, otherwise, drain the last bytes and stop */ - if (hd->host_avail < local_elem->size) { - if (hd->host_avail == 0) { - /* end of stream, stop */ - next->size = DMA_RELOAD_END; - need_copy = 0; - - /* will notify host side once dai tell us */ - wait_init(&dev->pipeline->complete); - work_schedule_default(&hd->work, PLATFORM_HOST_FINISH_DELAY); - goto next_copy; - } - - /* end of stream, drain the last bytes */ - local_elem->size = hd->host_avail; - - /* the split_remaining may not be copied anymore, but, let's make it - correct. we have only hd->host_avail data, so the split_remaining - should be (next_size - hd->host_avail) bigger */ - hd->split_remaining += next_size - hd->host_avail; - } - -next_copy: if (need_copy) { next->src = local_elem->src; next->dest = local_elem->dest; @@ -250,148 +209,6 @@ next_copy: wait_completed(&hd->complete); } -/* - * DSP period copy to host DMA completion. This is called when DMA completes - * its current transfer from DSP to host. The host memory is not guaranteed - * to be continuous and also not guaranteed to have a period/buffer size that - * is a multiple of the DSP period size. This means we must check we do not - * overflow host period/buffer/page boundaries on each transfer and split the - * DMA transfer if we do overflow. - */ -static void host_dma_cb_capture(struct comp_dev *dev, - struct dma_sg_elem *next) -{ - struct host_data *hd = comp_get_drvdata(dev); - struct dma_sg_elem *local_elem, *source_elem, *sink_elem; - struct comp_buffer *dma_buffer; - - local_elem = list_first_item(&hd->config.elem_list, - struct dma_sg_elem, list); - - trace_host("Cpc"); - - /* update buffer positions */ - dma_buffer = hd->dma_buffer; - hd->dma_buffer->r_ptr += local_elem->size; - - if (dma_buffer->r_ptr >= dma_buffer->end_addr) - dma_buffer->r_ptr = dma_buffer->addr; -#if 0 - trace_value((uint32_t)(hd->dma_buffer->r_ptr - hd->dma_buffer->addr)); -#endif - - /* new local period, update host buffer position blks */ - hd->host_pos_read += local_elem->size; - - /* buffer overlap ? */ - if (hd->host_pos_read >= hd->host_size) - hd->host_pos_read = 0; - if (hd->host_pos) - *hd->host_pos = hd->host_pos_read; - - /* recalc available buffer space */ - comp_update_buffer_consume(hd->dma_buffer); - - /* send IPC message to driver if needed */ - hd->host_period_pos += local_elem->size; - if (hd->host_period_pos >= hd->host_period_bytes) { - hd->host_period_pos = 0; - ipc_stream_send_notification(dev, &hd->cp); - } - - /* are we dealing with a split transfer */ - if (hd->split_remaining) { - - /* update local elem */ - local_elem->src += local_elem->size; - sink_elem = next_buffer(hd->sink); - hd->sink->current_end = sink_elem->dest + sink_elem->size; - local_elem->dest = sink_elem->dest; - - /* set up next elem */ - local_elem->size = hd->split_remaining; - hd->next_inc = hd->split_remaining; - hd->split_remaining = 0; - - } else { - /* source is always DSP period size */ - source_elem = next_buffer(hd->source); - - local_elem->src = source_elem->src; - local_elem->size = hd->period->size; - local_elem->dest += hd->next_inc; - hd->next_inc = hd->period->size; - - /* are we at end of elem */ - if (local_elem->dest == hd->sink->current_end) { - - /* end of elem, so use next */ - sink_elem = next_buffer(hd->sink); - hd->sink->current_end = sink_elem->dest + sink_elem->size; - local_elem->dest = sink_elem->dest; - - } else if (local_elem->dest + hd->period->size > hd->sink->current_end) { - - /* split copy - split transaction into 2 copies */ - local_elem->size = hd->sink->current_end - local_elem->dest; - hd->split_remaining = hd->period->size - local_elem->size; - - next->src = local_elem->src; - next->dest = local_elem->dest; - next->size = local_elem->size; - return; - } - } - - /* let any waiters know we have completed */ - wait_completed(&hd->complete); -} - -/* this is called by DMA driver every time descriptor has completed */ -static void host_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) -{ - - struct comp_dev *dev = (struct comp_dev *)data; - struct host_data *hd = comp_get_drvdata(dev); - - if (hd->params.direction == STREAM_DIRECTION_PLAYBACK) - host_dma_cb_playback(dev, next); - else - host_dma_cb_capture(dev, next); -} - -/* We need to wait until the last bytes/period is finished in dai, before we - * can notify host side about that, otherwise, host side will trigger stop too - * early, and we will miss rendering them. - * This work should be scheduled once the copy for host component is finished, - * and wait a timeout inside the work for pipeline->complete, which should be - * set in the endpoint(dai) rendering finishing callback. - */ -static uint32_t host_finish_work(void *data, uint32_t udelay) -{ - struct comp_dev *dev = (struct comp_dev *)data; - struct host_data *hd = comp_get_drvdata(dev); - int ret; - - dev->pipeline->complete.timeout = PLATFORM_HOST_FINISH_TIMEOUT; - ret = wait_for_completion_timeout(&dev->pipeline->complete); - if (ret < 0) - trace_comp_error("eHf"); - else { - trace_comp("hFw"); - /* update for host side */ - if (hd->host_pos) { - *hd->host_pos = hd->host_pos_read; - /* send the last notification to host */ - ipc_stream_send_notification(dev, &hd->cp); - } - } - - return 0; -} - - - static struct comp_dev *host_new(uint32_t type, uint32_t index, uint32_t direction) { @@ -421,7 +238,6 @@ static struct comp_dev *host_new(uint32_t type, uint32_t index, hd->dma = dma_get(DMA_ID_DMAC0); if (hd->dma == NULL) goto error; - work_init(&hd->work, host_finish_work, dev, WORK_ASYNC); /* init buffer elems */ list_init(&hd->config.elem_list); @@ -616,25 +432,19 @@ static int host_prepare(struct comp_dev *dev) struct host_data *hd = comp_get_drvdata(dev); struct comp_buffer *dma_buffer; - if (hd->params.direction == STREAM_DIRECTION_PLAYBACK) { + if (hd->params.direction == STREAM_DIRECTION_PLAYBACK) dma_buffer = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); - - dma_buffer->r_ptr = dma_buffer->addr; - dma_buffer->w_ptr = dma_buffer->addr; - } else { + else dma_buffer = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); + dma_buffer->r_ptr = dma_buffer->w_ptr = dma_buffer->addr; - dma_buffer->r_ptr = dma_buffer->addr; - dma_buffer->w_ptr = dma_buffer->addr; - } - + hd->local_pos = 0; if (hd->host_pos) *hd->host_pos = 0; - hd->host_pos_read = 0; - hd->host_period_pos = 0; - hd->host_period_bytes = + hd->report_pos = 0; + hd->report_period = hd->params.period_frames * hd->params.frame_size; hd->split_remaining = 0; @@ -671,11 +481,8 @@ static int host_pointer_reset(struct comp_dev *dev) /* reset buffer pointers */ if (hd->host_pos) *hd->host_pos = 0; - hd->host_app_pos = 0; - hd->host_pos_read = 0; - hd->host_period_pos = 0; - hd->host_size = 0; - hd->host_avail= 0; + hd->local_pos = 0; + hd->report_pos = 0; return 0; } @@ -700,7 +507,6 @@ static int host_cmd(struct comp_dev *dev, int cmd, void *data) { struct host_data *hd = comp_get_drvdata(dev); struct comp_dev *vol_dev = NULL; - struct ipc_intel_ipc_stream_set_position *app_pos; int ret = 0; // TODO: align cmd macros. @@ -729,11 +535,6 @@ static int host_cmd(struct comp_dev *dev, int cmd, void *data) case COMP_CMD_IPC_MMAP_RPOS: hd->host_pos = data; break; - case COMP_CMD_AVAIL_UPDATE: - app_pos = (struct ipc_intel_ipc_stream_set_position *)data; - hd->host_app_pos = app_pos->position; - host_update_buffer_produce(hd); - break; case COMP_CMD_VOLUME: vol_dev = host_volume_component(dev); if (vol_dev != NULL) @@ -789,7 +590,7 @@ static int host_reset(struct comp_dev *dev) host_pointer_reset(dev); hd->host_pos = NULL; - hd->host_period_bytes = 0; + hd->report_period = 0; hd->source = NULL; hd->sink = NULL; dev->state = COMP_STATE_INIT; @@ -807,9 +608,6 @@ static int host_copy(struct comp_dev *dev) if (dev->state != COMP_STATE_RUNNING) return 0; - if (hd->host_avail == 0) - return 0; - /* do DMA transfer */ wait_init(&hd->complete); dma_set_config(hd->dma, hd->chan, &hd->config); -- 2.7.4
2 1
0 0
[Sound-open-firmware] [PATCH v3 0/7] Fix capture doesn't work issue
by Keyon Jie 01 Mar '17

01 Mar '17
This series fix the capture doesn't work after W/R pointer check implemented: 1. Make sure the component .params() works for capture; 2. Fix host side buffer for capture; 3. rename host side buffer pointer to make it more understandable for capture also. 4. integrate produce and consume version host_update_buffer to fix capture issue. 5. make the host buffer pointers check configurable. Changes in v3: 1. remove superfluous prefix 'host_' for members in host_data struct and rename to make them more understandable; 2. make the host buffer pointers check configurable, when disable, will save about 0.6KB in firmware binary size. Changes in v2: 1. change to use w_ptr/r_ptr host buffer pointers to make it easy to understand. Keyon Jie (7): component: set source buffer params for capture component .params() host: only update host_avail and host_free in host_update_buffer_xx() host: host_copy(): add handle for capture host: change host buffer pointer to w_ptr/r_ptr and update comments host: integrate consume and produce to host_update_buffer host: remove 'host_' prefix for host_data struct host: add HOST_SIDE_BUFFER_CHECK to make host side buffer check configurable src/audio/host.c | 173 +++++++++++++++++++++++-------------- src/audio/volume.c | 39 ++++++--- src/include/reef/audio/component.h | 13 +++ 3 files changed, 145 insertions(+), 80 deletions(-) -- 2.7.4
1 7
0 0

HyperKitty Powered by HyperKitty version 1.3.8.