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 -----
  • July
  • June
  • 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

  • 1572 discussions
[Sound-open-firmware] [PATCH] cache: Add cache management API to writeback/invalidate regions
by Liam Girdwood 07 Jun '17

07 Jun '17
Add an API to allow drivers to writeback or invalidate cache contents. This is useful where the DSP firmware runs from cache and needs to writeback/buffer prior to DMA or other peripheral usage. Signed-off-by: Liam Girdwood <liam.r.girdwood(a)linux.intel.com> --- src/audio/dai.c | 7 +++++++ src/audio/host.c | 7 +++++++ src/include/reef/mailbox.h | 9 +++++++-- src/lib/trace.c | 4 ++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/audio/dai.c b/src/audio/dai.c index 8be8776..d02e365 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -43,6 +43,7 @@ #include <reef/audio/component.h> #include <reef/audio/pipeline.h> #include <platform/dma.h> +#include <arch/cache.h> #define DAI_PLAYBACK_STREAM 0 #define DAI_CAPTURE_STREAM 1 @@ -94,6 +95,9 @@ static void dai_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) dd->dai_pos_blks += dma_buffer->ipc_buffer.size; } + /* writeback buffer contents from cache */ + dcache_writeback_region(dma_buffer->r_ptr, dev->period_bytes); + #if 0 // TODO: move this to new trace mechanism trace_value((uint32_t)(dma_buffer->r_ptr - dma_buffer->addr)); @@ -111,6 +115,9 @@ static void dai_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) dma_buffer = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); + /* invalidate buffer contents */ + dcache_writeback_region(dma_buffer->w_ptr, dev->period_bytes); + dma_buffer->w_ptr += dev->period_bytes; /* check for end of buffer */ diff --git a/src/audio/host.c b/src/audio/host.c index 51ece99..9f81a1c 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -44,6 +44,7 @@ #include <reef/audio/component.h> #include <reef/audio/pipeline.h> #include <platform/dma.h> +#include <arch/cache.h> #include <uapi/ipc.h> #define trace_host(__e) trace_event(TRACE_CLASS_HOST, __e) @@ -127,6 +128,9 @@ static void host_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) if (hd->params.pcm->direction == SOF_IPC_STREAM_PLAYBACK) { dma_buffer->w_ptr += local_elem->size; + /* invalidate audio data */ + dcache_invalidate_region(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 @@ -144,6 +148,9 @@ static void host_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) trace_value((uint32_t)(hd->dma_buffer->r_ptr - hd->dma_buffer->addr)); #endif + /* writeback audio data */ + dcache_writeback_region(dma_buffer->r_ptr, local_elem->size); + /* recalc available buffer space */ comp_update_buffer_consume(hd->dma_buffer); } diff --git a/src/include/reef/mailbox.h b/src/include/reef/mailbox.h index d3a7bf6..44366e4 100644 --- a/src/include/reef/mailbox.h +++ b/src/include/reef/mailbox.h @@ -32,6 +32,7 @@ #define __INCLUDE_MAILBOX__ #include <platform/mailbox.h> +#include <arch/cache.h> #include <stdint.h> /* almost 1k should be enough for everyone ..... */ @@ -62,15 +63,19 @@ MAILBOX_DEBUG_SIZE #define mailbox_outbox_write(dest, src, bytes) \ - rmemcpy((void*)(MAILBOX_OUTBOX_BASE + dest), src, bytes); + rmemcpy((void*)(MAILBOX_OUTBOX_BASE + dest), src, bytes); \ + dcache_writeback_region((void*)(MAILBOX_OUTBOX_BASE + dest), bytes); #define mailbox_outbox_read(dest, src, bytes) \ + dcache_invalidate_region((void*)(MAILBOX_OUTBOX_BASE + src), bytes); \ rmemcpy(dest, (void*)(MAILBOX_OUTBOX_BASE + src), bytes); #define mailbox_inbox_write(dest, src, bytes) \ - rmemcpy((void*)(MAILBOX_INBOX_BASE + dest), src, bytes); + rmemcpy((void*)(MAILBOX_INBOX_BASE + dest), src, bytes); \ + dcache_writeback_region((void*)(MAILBOX_INBOX_BASE + dest), bytes); #define mailbox_inbox_read(dest, src, bytes) \ + dcache_invalidate_region((void*)(MAILBOX_INBOX_BASE + src), bytes); \ rmemcpy(dest, (void*)(MAILBOX_INBOX_BASE + src), bytes); #endif diff --git a/src/lib/trace.c b/src/lib/trace.c index 278a59b..79d026e 100644 --- a/src/lib/trace.c +++ b/src/lib/trace.c @@ -29,6 +29,7 @@ */ #include <reef/trace.h> +#include <arch/cache.h> #include <stdint.h> /* trace position */ @@ -47,6 +48,9 @@ void _trace_event(uint32_t event) t[0] = platform_timer_get(0); t[1] = event; + /* writeback trace data */ + dcache_writeback_region((void*)t, sizeof(uint32_t) * 2); + trace_pos += (sizeof(uint32_t) << 1); if (trace_pos >= MAILBOX_TRACE_SIZE) trace_pos = 0; -- 2.11.0
1 0
0 0
[Sound-open-firmware] [PATCH] drivers: dw-dma: move register macros into platform specific header.
by Liam Girdwood 06 Jun '17

06 Jun '17
Clean up the DW-DMA rsgisters so that it can be more easily integrated into other platforms. Signed-off-by: Liam Girdwood <liam.r.girdwood(a)linux.intel.com> --- src/drivers/dw-dma.c | 106 ++++++++++++++++++--------- src/platform/baytrail/include/platform/dma.h | 26 +++++++ 2 files changed, 99 insertions(+), 33 deletions(-) diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index 16f59d1..e851e54 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -62,6 +62,7 @@ #include <errno.h> #include <stdint.h> #include <string.h> +#include <config.h> /* channel registers */ #define DW_MAX_CHAN 8 @@ -108,20 +109,16 @@ #define DW_INTR_STATUS 0x0360 #define DW_DMA_CFG 0x0398 #define DW_DMA_CHAN_EN 0x03A0 -#define DW_FIFO_PART0_LO 0x0400 -#define DW_FIFO_PART0_HI 0x0404 -#define DW_FIFO_PART1_LO 0x0408 -#define DW_FIFO_PART1_HI 0x040C -#define DW_CH_SAI_ERR 0x0410 /* channel bits */ #define INT_MASK(chan) (0x100 << chan) #define INT_UNMASK(chan) (0x101 << chan) +#define INT_MASK_ALL 0xFF00 +#define INT_UNMASK_ALL 0xFFFF #define CHAN_ENABLE(chan) (0x101 << chan) #define CHAN_DISABLE(chan) (0x100 << chan) #define DW_CFG_CH_SUSPEND 0x100 -#define DW_CFG_CH_DRAIN 0x400 #define DW_CFG_CH_FIFO_EMPTY 0x200 /* CTL_LO */ @@ -136,8 +133,6 @@ #define DW_CTLL_SRC_FIX (2 << 9) #define DW_CTLL_DST_MSIZE(x) (x << 11) #define DW_CTLL_SRC_MSIZE(x) (x << 14) -#define DW_CTLL_S_GATH_EN (1 << 17) -#define DW_CTLL_D_SCAT_EN (1 << 18) #define DW_CTLL_FC(x) (x << 20) #define DW_CTLL_FC_M2M (0 << 20) #define DW_CTLL_FC_M2P (1 << 20) @@ -150,16 +145,6 @@ #define DW_CTLL_RELOAD_SRC (1 << 30) #define DW_CTLL_RELOAD_DST (1 << 31) -/* CTL_HI */ -#define DW_CTLH_DONE 0x00020000 -#define DW_CTLH_BLOCK_TS_MASK 0x0001ffff -#define DW_CTLH_CLASS(x) (x << 29) -#define DW_CTLH_WEIGHT(x) (x << 18) - -/* CFG_HI */ -#define DW_CFGH_SRC_PER(x) (x << 0) -#define DW_CFGH_DST_PER(x) (x << 4) - /* tracing */ #define trace_dma(__e) trace_event(TRACE_CLASS_DMA, __e) #define trace_dma_error(__e) trace_error(TRACE_CLASS_DMA, __e) @@ -168,6 +153,9 @@ /* HW Linked list support currently disabled - needs debug for missing IRQs !!! */ #define DW_USE_HW_LLI 0 +/* number of tries to wait for reset */ +#define DW_DMA_CFG_TRIES 10000 + /* data for each DMA channel */ struct dma_chan_data { uint32_t status; @@ -264,7 +252,7 @@ static void dw_dma_channel_put_unlocked(struct dma *dma, int channel) return; } - +#ifdef DW_CFG_CH_DRAIN /* have drain feature */ if (p->chan[channel].status == DMA_STATUS_PAUSED) { dw_update_bits(dma, DW_CFG_LOW(channel), @@ -276,6 +264,7 @@ static void dw_dma_channel_put_unlocked(struct dma *dma, int channel) work_schedule_default(&p->chan[channel].work, 100); return; } +#endif /* mask block, transfer and error interrupts for channel */ dw_write(dma, DW_MASK_TFR, INT_MASK(channel)); @@ -456,8 +445,11 @@ static uint32_t dw_dma_fifo_work(void *data, uint32_t udelay) /* clear suspend */ dw_update_bits(dma, DW_CFG_LOW(cd->channel), +#ifdef DW_CFG_CH_DRAIN /* have drain feature */ DW_CFG_CH_SUSPEND | DW_CFG_CH_DRAIN, 0); - +#else + DW_CFG_CH_SUSPEND, 0); +#endif cd->status = DMA_STATUS_IDLE; goto out; } @@ -470,8 +462,11 @@ static uint32_t dw_dma_fifo_work(void *data, uint32_t udelay) /* clear suspend */ dw_update_bits(dma, DW_CFG_LOW(cd->channel), +#ifdef DW_CFG_CH_DRAIN /* have drain feature */ DW_CFG_CH_SUSPEND | DW_CFG_CH_DRAIN, 0); - +#else + DW_CFG_CH_SUSPEND, 0); +#endif /* do we need to free it ? */ if (cd->status == DMA_STATUS_CLOSING) dw_dma_channel_put_unlocked(dma, cd->channel); @@ -512,15 +507,17 @@ static int dw_dma_stop(struct dma *dma, int channel, int drain) } /* suspend and drain */ + bits = DW_CFG_CH_SUSPEND; + p->chan[channel].drain_count = 3; + p->chan[channel].status = DMA_STATUS_STOPPING; + +#ifdef DW_CFG_CH_DRAIN /* have drain feature, then may drain */ if (drain) { - bits = DW_CFG_CH_SUSPEND | DW_CFG_CH_DRAIN; + bits |= DW_CFG_CH_DRAIN; p->chan[channel].drain_count = 14; p->chan[channel].status = DMA_STATUS_DRAINING; - } else { - bits = DW_CFG_CH_SUSPEND; - p->chan[channel].drain_count = 3; - p->chan[channel].status = DMA_STATUS_STOPPING; } +#endif dw_update_bits(dma, DW_CFG_LOW(channel), bits, bits); schedule = 1; @@ -568,8 +565,8 @@ static int dw_dma_set_config(struct dma *dma, int channel, /* default channel config */ p->chan[channel].direction = config->direction; - p->chan[channel].cfg_lo = 0x00000003; - p->chan[channel].cfg_hi = 0x0; + p->chan[channel].cfg_lo = DW_CFG_LOW_DEF; + p->chan[channel].cfg_hi = DW_CFG_HIGH_DEF; /* get number of SG elems */ list_for_item(plist, &config->elem_list) @@ -666,9 +663,19 @@ static int dw_dma_set_config(struct dma *dma, int channel, break; } + if (sg_elem->size > DW_CTLH_BLOCK_TS_MASK) { + trace_dma_error("eDS"); + return -EINVAL; + } /* set transfer size of element */ +#if defined CONFIG_BAYTRAIL || defined CONFIG_CHERRYTRAIL lli_desc->ctrl_hi = DW_CTLH_CLASS(p->class) | (sg_elem->size & DW_CTLH_BLOCK_TS_MASK); +#else + /* for the unit is transaction--TR_WIDTH. */ + lli_desc->ctrl_hi = (sg_elem->size / (1 << (lli_desc->ctrl_lo >> 4 & 0x7))) + & DW_CTLH_BLOCK_TS_MASK; +#endif /* set next descriptor in list */ lli_desc->llp = (uint32_t)(lli_desc + 1); @@ -768,8 +775,14 @@ static inline void dw_dma_chan_reload_next(struct dma *dma, int channel, dw_write(dma, DW_DAR(channel), next->dest); /* set transfer size of element */ +#if defined CONFIG_BAYTRAIL || defined CONFIG_CHERRYTRAIL lli->ctrl_hi = DW_CTLH_CLASS(p->class) | (next->size & DW_CTLH_BLOCK_TS_MASK); +#else + /* for the unit is transaction--TR_WIDTH. */ + lli->ctrl_hi = (next->size / (1 << (lli->ctrl_lo >> 4 & 0x7))) + & DW_CTLH_BLOCK_TS_MASK; +#endif /* program CTLn */ dw_write(dma, DW_CTRL_LOW(channel), lli->ctrl_lo); @@ -872,16 +885,38 @@ static void dw_dma_setup(struct dma *dma) struct dw_drv_plat_data *dp = dma->plat_data.drv_plat_data; int i; + /* we cannot config DMAC if DMAC has been already enabled by host */ + if (dw_read(dma, DW_DMA_CFG) != 0) + dw_write(dma, DW_DMA_CFG, 0x0); + + /* now check that it's 0 */ + for (i = DW_DMA_CFG_TRIES; i > 0; i--) { + if (dw_read(dma, DW_DMA_CFG) == 0) + goto found; + } + trace_dma_error("eDs"); + return; + +found: + for (i = 0; i < DW_MAX_CHAN; i++) + dw_read(dma, DW_DMA_CHAN_EN); + +#ifdef HAVE_HDDA + /* enable HDDA before DMAC */ + shim_write(SHIM_HMDC, SHIM_HMDC_HDDA_ALLCH); +#endif + /* enable the DMA controller */ dw_write(dma, DW_DMA_CFG, 1); /* mask all interrupts for all 8 channels */ - dw_write(dma, DW_MASK_TFR, 0x0000ff00); - dw_write(dma, DW_MASK_BLOCK, 0x0000ff00); - dw_write(dma, DW_MASK_SRC_TRAN, 0x0000ff00); - dw_write(dma, DW_MASK_DST_TRAN, 0x0000ff00); - dw_write(dma, DW_MASK_ERR, 0x0000ff00); + dw_write(dma, DW_MASK_TFR, INT_MASK_ALL); + dw_write(dma, DW_MASK_BLOCK, INT_MASK_ALL); + dw_write(dma, DW_MASK_SRC_TRAN, INT_MASK_ALL); + dw_write(dma, DW_MASK_DST_TRAN, INT_MASK_ALL); + dw_write(dma, DW_MASK_ERR, INT_MASK_ALL); +#ifdef DW_FIFO_PARTITION /* TODO: we cannot config DMA FIFOs if DMAC has been already */ /* allocate FIFO partitions, 128 bytes for each ch */ dw_write(dma, DW_FIFO_PART1_LO, 0x100080); @@ -889,10 +924,15 @@ static void dw_dma_setup(struct dma *dma) dw_write(dma, DW_FIFO_PART0_HI, 0x100080); dw_write(dma, DW_FIFO_PART0_LO, 0x100080 | (1 << 26)); dw_write(dma, DW_FIFO_PART0_LO, 0x100080); +#endif /* set channel priorities */ for (i = 0; i < DW_MAX_CHAN; i++) { +#if defined CONFIG_BAYTRAIL || defined CONFIG_CHERRYTRAIL dw_write(dma, DW_CTRL_HIGH(i), DW_CTLH_CLASS(dp->chan[i].class)); +#else + dw_write(dma, DW_CFG_LOW(i), DW_CFG_CLASS(dp->chan[i].class)); +#endif } } diff --git a/src/platform/baytrail/include/platform/dma.h b/src/platform/baytrail/include/platform/dma.h index eec501a..5f5c52a 100644 --- a/src/platform/baytrail/include/platform/dma.h +++ b/src/platform/baytrail/include/platform/dma.h @@ -38,6 +38,32 @@ #define DMA_ID_DMAC1 1 #define DMA_ID_DMAC2 2 +/* baytrail specific registers */ +/* CTL_LO */ +#define DW_CTLL_S_GATH_EN (1 << 17) +#define DW_CTLL_D_SCAT_EN (1 << 18) +/* CTL_HI */ +#define DW_CTLH_DONE 0x00020000 +#define DW_CTLH_BLOCK_TS_MASK 0x0001ffff +#define DW_CTLH_CLASS(x) (x << 29) +#define DW_CTLH_WEIGHT(x) (x << 18) +/* CFG_LO */ +#define DW_CFG_CH_DRAIN 0x400 +/* CFG_HI */ +#define DW_CFGH_SRC_PER(x) (x << 0) +#define DW_CFGH_DST_PER(x) (x << 4) +/* FIFO Partition */ +#define DW_FIFO_PARTITION +#define DW_FIFO_PART0_LO 0x0400 +#define DW_FIFO_PART0_HI 0x0404 +#define DW_FIFO_PART1_LO 0x0408 +#define DW_FIFO_PART1_HI 0x040C +#define DW_CH_SAI_ERR 0x0410 + +/* default initial setup register values */ +#define DW_CFG_LOW_DEF 0x00000003 +#define DW_CFG_HIGH_DEF 0x0 + #define DMA_HANDSHAKE_SSP0_RX 0 #define DMA_HANDSHAKE_SSP0_TX 1 #define DMA_HANDSHAKE_SSP1_RX 2 -- 2.11.0
1 4
0 0
[Sound-open-firmware] [PATCH] trace: add more detailed trace vales for init
by Liam Girdwood 06 Jun '17

06 Jun '17
Signed-off-by: Liam Girdwood <liam.r.girdwood(a)linux.intel.com> --- src/include/reef/trace.h | 9 ++++++++- src/init/init.c | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/include/reef/trace.h b/src/include/reef/trace.h index 76908f5..cb861e0 100644 --- a/src/include/reef/trace.h +++ b/src/include/reef/trace.h @@ -48,7 +48,10 @@ /* system specific codes */ #define TRACE_BOOT_SYS_WORK (TRACE_BOOT_SYS + 0x100) -#define TRACE_BOOT_SYS_CPU_FREQ (TRACE_BOOT_SYS + 0x101) +#define TRACE_BOOT_SYS_CPU_FREQ (TRACE_BOOT_SYS + 0x200) +#define TRACE_BOOT_SYS_HEAP (TRACE_BOOT_SYS + 0x300) +#define TRACE_BOOT_SYS_NOTE (TRACE_BOOT_SYS + 0x400) +#define TRACE_BOOT_SYS_SCHED (TRACE_BOOT_SYS + 0x500) /* platform/device specific codes */ #define TRACE_BOOT_PLATFORM_MBOX (TRACE_BOOT_PLATFORM + 0x100) @@ -75,6 +78,10 @@ #define TRACE_CLASS_LOCK (10 << 24) #define TRACE_CLASS_MEM (11 << 24) #define TRACE_CLASS_MIXER (12 << 24) +#define TRACE_CLASS_BUFFER (13 << 24) +#define TRACE_CLASS_VOLUME (14 << 24) +#define TRACE_CLASS_SWITCH (15 << 24) +#define TRACE_CLASS_MUX (16 << 24) /* move to config.h */ #define TRACE 1 diff --git a/src/init/init.c b/src/init/init.c index 1a6b11c..31d727e 100644 --- a/src/init/init.c +++ b/src/init/init.c @@ -55,10 +55,11 @@ int main(int argc, char *argv[]) trace_point(TRACE_BOOT_ARCH); /* initialise system services */ + trace_point(TRACE_BOOT_SYS_HEAP); init_heap(); init_system_notify(); - trace_point(TRACE_BOOT_SYS); + trace_point(TRACE_BOOT_SYS_NOTE); /* init the platform */ err = platform_init(); -- 2.11.0
1 2
0 0
[Sound-open-firmware] [PATCH] build: fix generation of commit ID and build number
by Liam Girdwood 06 Jun '17

06 Jun '17
Signed-off-by: Liam Girdwood <liam.r.girdwood(a)linux.intel.com> --- .gitignore | 2 ++ Makefile.am | 5 ++++- configure.ac | 2 +- git-version.sh | 16 ++++++++++++++-- src/ipc/intel-ipc.c | 3 +-- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 9223f60..c8a8ab0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ *.man .version .tarball-version +*.x +.build Makefile Makefile.in diff --git a/Makefile.am b/Makefile.am index c47580e..362e2bd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,10 +17,13 @@ export PLATFORM_INCDIR = \ BUILT_SOURCES = $(top_srcdir)/src/include/version.h -$(top_srcdir)/src/include/version.h: +$(top_srcdir)/src/include/version.h: Makefile ./git-version.sh dist-hook: ./git-version.sh cat .version > $(distdir)/.tarball-version cat .version > $(distdir)/.version + +all-local: + rm -f $(top_srcdir)/src/include/version.h diff --git a/configure.ac b/configure.ac index 7c1acf4..f085a73 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.69]) -AC_INIT([Reef],[m4_esyscmd(./git-version.sh)],[sound-open-firmware(a)alsa-project.org]) +AC_INIT([Reef],[m4_esyscmd(./git-version.sh), m4_esyscmd(rm -f .build)],[sound-open-firmware(a)alsa-project.org]) AC_CONFIG_SRCDIR([src/init/init.c]) AC_CONFIG_HEADERS([src/include/config.h]) AC_CONFIG_MACRO_DIRS([m4]) diff --git a/git-version.sh b/git-version.sh index f8f1e58..c6beb40 100755 --- a/git-version.sh +++ b/git-version.sh @@ -1,10 +1,22 @@ # version for configure -echo -n `git describe --abbrev=4` +# echo -n `git describe --abbrev=4` # version for make dist git describe --abbrev=4 > .version git describe --abbrev=4 > .tarball-version # git commit for IPC -echo "#define REEF_BUILD \"`git describe --abbrev=4 | cut -d- -f3`\"" > src/include/version.h +echo "#define REEF_TAG \"`git describe --abbrev=4 | cut -d- -f3`\"" > src/include/version.h + +# build counter +if [ -e .build ]; then + num=$((`cat .build` + 1)) +else + num=0 +fi + +# save and insert build counter +echo $num > .build +echo "#define REEF_BUILD $num" >> src/include/version.h + diff --git a/src/ipc/intel-ipc.c b/src/ipc/intel-ipc.c index 7db4179..e0ab4f7 100644 --- a/src/ipc/intel-ipc.c +++ b/src/ipc/intel-ipc.c @@ -120,11 +120,10 @@ static inline uint32_t msg_get_stage_type(uint32_t msg) /* TODO: add build count */ static const struct ipc_intel_ipc_fw_version fw_version = { - .build = 0, + .build = REEF_BUILD, .minor = REEF_MINOR, .major = REEF_MAJOR, .type = 0, - .fw_build_hash = REEF_BUILD, .fw_log_providers_hash = 0, }; -- 2.11.0
1 4
0 0
[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
  • ← Newer
  • 1
  • ...
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • Older →

HyperKitty Powered by HyperKitty version 1.3.8.