Repository navigation
kwd: improvements #1689
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
kwd: improvements #1689
Changes from all commits
3789289
0796604
2e43318
b21dc20
6d1ca1e
79a0548
c031dd8
49eb7c0
13a428c
62e858f
b286510
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,6 +43,7 @@ | |
|
|
||
| /* KPB private data, runtime data */ | ||
| struct comp_data { | ||
| uint64_t state_log; | ||
| enum kpb_state state; /**< current state of KPB component */ | ||
| uint32_t kpb_no_of_clients; /**< number of registered clients */ | ||
| struct kpb_client clients[KPB_MAX_NO_OF_CLIENTS]; | ||
|
|
@@ -81,6 +82,8 @@ static void kpb_drain_samples(void *source, struct comp_buffer *sink, | |
| static void kpb_reset_history_buffer(struct hb *buff); | ||
| static inline bool validate_host_params(size_t host_period_size, | ||
| size_t host_buffer_size); | ||
| static inline void kpb_change_state(struct comp_data *kpb, | ||
| enum kpb_state state); | ||
|
|
||
| /** | ||
| * \brief Create a key phrase buffer component. | ||
|
|
@@ -145,10 +148,11 @@ static struct comp_dev *kpb_new(struct sof_ipc_comp *comp) | |
| /* Init basic component data */ | ||
| kpb->history_buffer = NULL; | ||
| kpb->kpb_no_of_clients = 0; | ||
| kpb->state_log = 0; | ||
|
|
||
| /* Kpb has been created successfully */ | ||
| dev->state = COMP_STATE_READY; | ||
| kpb->state = KPB_STATE_CREATED; | ||
| kpb_change_state(kpb, KPB_STATE_CREATED); | ||
|
|
||
| return dev; | ||
| } | ||
|
|
@@ -340,7 +344,8 @@ static int kpb_prepare(struct comp_dev *dev) | |
| if (kpb->state == KPB_STATE_RESETTING || | ||
| kpb->state == KPB_STATE_RESET_FINISHING) { | ||
| trace_kpb_error("kpb_prepare() error: can not prepare KPB " | ||
| "due to ongoing reset."); | ||
| "due to ongoing reset, state log %d", | ||
| kpb->state_log); | ||
| return -EBUSY; | ||
| } | ||
|
|
||
|
|
@@ -352,13 +357,15 @@ static int kpb_prepare(struct comp_dev *dev) | |
| return PPL_STATUS_PATH_STOP; | ||
|
|
||
| /* Init private data */ | ||
| kpb->state = KPB_STATE_PREPARING; | ||
| kpb_change_state(kpb, KPB_STATE_PREPARING); | ||
| kpb->kpb_no_of_clients = 0; | ||
| kpb->buffered_data = 0; | ||
| kpb->host_buffer_size = dev->params.buffer.size; | ||
| kpb->host_period_size = dev->params.host_period_bytes; | ||
| kpb->config.sampling_width = dev->params.sample_container_bytes * 8; | ||
| kpb->kpb_buffer_size = KPB_MAX_BUFFER_SIZE(kpb->config.sampling_width); | ||
| kpb->sel_sink = NULL; | ||
| kpb->host_sink = NULL; | ||
|
|
||
| if (!kpb->history_buffer) { | ||
| /* Allocate history buffer */ | ||
|
|
@@ -419,7 +426,14 @@ static int kpb_prepare(struct comp_dev *dev) | |
| } | ||
| } | ||
|
|
||
| kpb->state = KPB_STATE_RUN; | ||
| if (!kpb->sel_sink || !kpb->host_sink) { | ||
| trace_kpb("kpb_prepare() error: could not find " | ||
| "sinks: sel_sink %d host_sink %d", | ||
| (uint32_t)kpb->sel_sink, (uint32_t)kpb->host_sink); | ||
|
tlauda marked this conversation as resolved.
Resolved
|
||
| ret = -EIO; | ||
| } | ||
|
|
||
| kpb_change_state(kpb, KPB_STATE_RUN); | ||
|
|
||
| return ret; | ||
| } | ||
|
|
@@ -452,38 +466,46 @@ static void kpb_cache(struct comp_dev *dev, int cmd) | |
| static int kpb_reset(struct comp_dev *dev) | ||
| { | ||
| struct comp_data *kpb = comp_get_drvdata(dev); | ||
| int ret = 0; | ||
|
|
||
| trace_kpb("kpb_reset()"); | ||
|
|
||
| kpb->buffered_data = 0; | ||
| kpb->is_internal_buffer_full = false; | ||
| trace_kpb("kpb_reset(): resetting from state %d, state log %d", | ||
| kpb->state, kpb->state_log); | ||
|
|
||
| /* Change KPB state to RESET. If there is any ongoing job it will | ||
| * shut itself gracefully first. | ||
| */ | ||
| if (kpb->state == KPB_STATE_BUFFERING || | ||
| kpb->state == KPB_STATE_DRAINING) { | ||
| switch (kpb->state) { | ||
| case KPB_STATE_BUFFERING: | ||
| case KPB_STATE_DRAINING: | ||
| /* KPB is performing some task now, | ||
| * terminate it gently. | ||
| */ | ||
| kpb->state = KPB_STATE_RESETTING; | ||
| return -EBUSY; | ||
| } | ||
| kpb_change_state(kpb, KPB_STATE_RESETTING); | ||
| ret = -EBUSY; | ||
| break; | ||
| case KPB_STATE_DISABLED: | ||
| case KPB_STATE_CREATED: | ||
| /* Nothing to reset */ | ||
| ret = comp_set_state(dev, COMP_TRIGGER_RESET); | ||
| break; | ||
| default: | ||
| kpb->buffered_data = 0; | ||
| kpb->is_internal_buffer_full = false; | ||
|
|
||
| if (kpb->history_buffer) { | ||
| /* Reset history buffer - zero its data reset pointers | ||
| * and states. | ||
| */ | ||
| kpb_reset_history_buffer(kpb->history_buffer); | ||
| } | ||
| if (kpb->history_buffer) { | ||
| /* Reset history buffer - zero its data, reset pointers | ||
| * and states. | ||
| */ | ||
| kpb_reset_history_buffer(kpb->history_buffer); | ||
| } | ||
|
|
||
| /* Unregister KPB for async notification */ | ||
| notifier_unregister(&kpb->kpb_events); | ||
| /* Unregister KPB for async notification */ | ||
| notifier_unregister(&kpb->kpb_events); | ||
| /* Finally KPB is ready after reset */ | ||
| kpb_change_state(kpb, KPB_STATE_PREPARING); | ||
|
|
||
| /* Finally KPB is ready after reset */ | ||
| kpb->state = KPB_STATE_PREPARING; | ||
| ret = comp_set_state(dev, COMP_TRIGGER_RESET); | ||
| break; | ||
| } | ||
|
|
||
| return comp_set_state(dev, COMP_TRIGGER_RESET); | ||
| return ret; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -533,6 +555,14 @@ static int kpb_copy(struct comp_dev *dev) | |
| } | ||
|
|
||
| copy_bytes = MIN(sink->free, source->avail); | ||
| if (!copy_bytes) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The last sentence of the commit description seems weird.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, corrected now. |
||
| trace_kpb_error("kpb_copy() error: nothing to copy " | ||
| "sink->free %d source->avail %d", | ||
| sink->free, source->avail); | ||
| ret = PPL_STATUS_PATH_STOP; | ||
| goto out; | ||
| } | ||
|
|
||
| kpb_copy_samples(sink, source, copy_bytes, sample_width); | ||
|
|
||
| /* Buffer source data internally in history buffer for future | ||
|
|
@@ -571,19 +601,27 @@ static int kpb_copy(struct comp_dev *dev) | |
| } | ||
|
|
||
| copy_bytes = MIN(sink->free, source->avail); | ||
| if (!copy_bytes) { | ||
| trace_kpb_error("kpb_copy() error: nothing to copy " | ||
| "sink->free %d source->avail %d", | ||
| sink->free, source->avail); | ||
| ret = PPL_STATUS_PATH_STOP; | ||
| goto out; | ||
| } | ||
|
|
||
| kpb_copy_samples(sink, source, copy_bytes, sample_width); | ||
|
|
||
| comp_update_buffer_produce(sink, copy_bytes); | ||
| comp_update_buffer_consume(source, copy_bytes); | ||
|
|
||
| ret = 0; | ||
| ret = PPL_STATUS_PATH_STOP; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it intentional change?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, during host copy we no longer need selector and detector components. |
||
| break; | ||
| case KPB_STATE_DRAINING: | ||
| /* In draining state we only buffer data in internal, | ||
| * history buffer. | ||
| */ | ||
| if (source->avail <= kpb->kpb_buffer_size) { | ||
| ret = kpb_buffer_data(dev, source, copy_bytes); | ||
| ret = kpb_buffer_data(dev, source, source->avail); | ||
| if (ret) { | ||
| trace_kpb_error("kpb_copy(): internal " | ||
| "buffering failed."); | ||
|
|
@@ -598,7 +636,9 @@ static int kpb_copy(struct comp_dev *dev) | |
| ret = PPL_STATUS_PATH_STOP; | ||
| break; | ||
| default: | ||
| trace_kpb_error("kpb_copy(): wrong state! Copy forbidden."); | ||
| trace_kpb_error("kpb_copy(): wrong state, copy forbidden. " | ||
| "(state %d, state log %d)", | ||
| kpb->state, kpb->state_log); | ||
| ret = -EIO; | ||
| break; | ||
| } | ||
|
|
@@ -624,8 +664,8 @@ static int kpb_buffer_data(struct comp_dev *dev, struct comp_buffer *source, | |
| struct comp_data *kpb = comp_get_drvdata(dev); | ||
| struct hb *buff = kpb->history_buffer; | ||
| void *read_ptr = source->r_ptr; | ||
| size_t timeout = platform_timer_get(platform_timer) + | ||
| clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1); | ||
| uint64_t timeout = 0; | ||
| uint64_t current_time = 0; | ||
| enum kpb_state state_preserved = kpb->state; | ||
| struct dd *draining_data = &kpb->draining_task_data; | ||
|
|
||
|
|
@@ -634,25 +674,31 @@ static int kpb_buffer_data(struct comp_dev *dev, struct comp_buffer *source, | |
| if (kpb->state != KPB_STATE_RUN && kpb->state != KPB_STATE_DRAINING) | ||
| return PPL_STATUS_PATH_STOP; | ||
|
|
||
| kpb->state = KPB_STATE_BUFFERING; | ||
|
|
||
| if (kpb->state == KPB_STATE_DRAINING) | ||
| draining_data->buffered_while_draining += size_to_copy; | ||
|
|
||
| kpb_change_state(kpb, KPB_STATE_BUFFERING); | ||
|
|
||
| timeout = platform_timer_get(platform_timer) + | ||
|
mrajwa marked this conversation as resolved.
Resolved
|
||
| clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1); | ||
| /* Let's store audio stream data in internal history buffer */ | ||
| while (size_to_copy) { | ||
| /* Reset was requested, it's time to stop buffering and finish | ||
| * KPB reset. | ||
| */ | ||
| if (kpb->state == KPB_STATE_RESETTING) { | ||
| kpb->state = KPB_STATE_RESET_FINISHING; | ||
| kpb_change_state(kpb, KPB_STATE_RESET_FINISHING); | ||
| kpb_reset(dev); | ||
| return PPL_STATUS_PATH_STOP; | ||
| } | ||
|
|
||
| /* Are we stuck in buffering? */ | ||
| if (timeout < platform_timer_get(platform_timer)) { | ||
| trace_kpb_error("kpb_buffer_data(): timeout."); | ||
| current_time = platform_timer_get(platform_timer); | ||
| if (timeout < current_time) { | ||
| trace_kpb_error("kpb_buffer_data(): timeout of %d [ms] " | ||
| "(current state %d, state log %d)", | ||
| (current_time - timeout), kpb->state, | ||
| kpb->state_log); | ||
| return -ETIME; | ||
| } | ||
|
|
||
|
|
@@ -711,7 +757,7 @@ static int kpb_buffer_data(struct comp_dev *dev, struct comp_buffer *source, | |
| } | ||
| } | ||
|
|
||
| kpb->state = state_preserved; | ||
| kpb_change_state(kpb, state_preserved); | ||
| return ret; | ||
| } | ||
|
|
||
|
|
@@ -923,7 +969,6 @@ static void kpb_init_draining(struct comp_dev *dev, struct kpb_client *cli) | |
| kpb->draining_task_data.sink = kpb->host_sink; | ||
| kpb->draining_task_data.history_buffer = buff; | ||
| kpb->draining_task_data.history_depth = history_depth; | ||
| kpb->draining_task_data.state = &kpb->state; | ||
| kpb->draining_task_data.sample_width = sample_width; | ||
| kpb->draining_task_data.drain_interval = drain_interval; | ||
| kpb->draining_task_data.pb_limit = period_bytes_limit; | ||
|
|
@@ -974,18 +1019,19 @@ static enum task_state kpb_draining_task(void *arg) | |
| size_t period_copy_start = platform_timer_get(platform_timer); | ||
| size_t time_taken = 0; | ||
| size_t *rt_stream_update = &draining_data->buffered_while_draining; | ||
| struct comp_data *kpb = comp_get_drvdata(draining_data->dev); | ||
|
|
||
| trace_kpb("kpb_draining_task(), start."); | ||
|
|
||
| /* Change KPB internal state to DRAINING */ | ||
| *draining_data->state = KPB_STATE_DRAINING; | ||
| kpb_change_state(kpb, KPB_STATE_DRAINING); | ||
|
|
||
| draining_time_start = platform_timer_get(platform_timer); | ||
|
|
||
| while (history_depth > 0) { | ||
| /* Have we received reset request? */ | ||
| if (*draining_data->state == KPB_STATE_RESETTING) { | ||
| *draining_data->state = KPB_STATE_RESET_FINISHING; | ||
| if (kpb->state == KPB_STATE_RESETTING) { | ||
| kpb_change_state(kpb, KPB_STATE_RESET_FINISHING); | ||
| kpb_reset(draining_data->dev); | ||
| goto out; | ||
| } | ||
|
|
@@ -1059,8 +1105,8 @@ static enum task_state kpb_draining_task(void *arg) | |
| * Note! If KPB state changed during draining due to i.e reset request | ||
| * we should not change that state. | ||
| */ | ||
| *draining_data->state = (*draining_data->state == KPB_STATE_DRAINING) ? | ||
| KPB_STATE_HOST_COPY : *draining_data->state; | ||
| if (kpb->state == KPB_STATE_DRAINING) | ||
| kpb_change_state(kpb, KPB_STATE_HOST_COPY); | ||
|
|
||
| /* Reset host-sink copy mode back to unblocking */ | ||
| comp_set_attribute(sink->sink, COMP_ATTR_COPY_TYPE, ©_type); | ||
|
|
@@ -1247,6 +1293,23 @@ static inline bool validate_host_params(size_t host_period_size, | |
|
|
||
| return (drained_per_interval > host_period_size) ? true : false; | ||
| } | ||
|
|
||
| /** | ||
| * \brief Change KPB state and log this change internally. | ||
| * \param[in] kpb - KPB component data pointer. | ||
| * \param[in] state - current KPB state. | ||
| * | ||
| * \return none. | ||
| */ | ||
| static inline void kpb_change_state(struct comp_data *kpb, | ||
| enum kpb_state state) | ||
| { | ||
| trace_kpb("kpb_change_state(): from %d to %d", | ||
| kpb->state, state); | ||
| kpb->state = state; | ||
| kpb->state_log = (kpb->state_log << 4) | state; | ||
| } | ||
|
|
||
| struct comp_driver comp_kpb = { | ||
| .type = SOF_COMP_KPB, | ||
| .ops = { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need 64 bits?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wider data size gives us the possibility to log more states. So I would keep it as 64 bits.