summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2017-01-21 08:09:48 -0500
committerMichael Sevakis <jethead71@rockbox.org>2017-01-21 12:03:23 -0500
commitc6299b268da0599c2bbce3e71efb5398ffd0a808 (patch)
tree6eb097f0d66b27f8524b5471d56e5460cdc4a0a5
parent15e1f592de7d91b208b83425d3c8b12496b30b89 (diff)
downloadrockbox-c6299b268da0599c2bbce3e71efb5398ffd0a808.tar.gz
rockbox-c6299b268da0599c2bbce3e71efb5398ffd0a808.zip
action.c must desist in calling set_cpu_frequency from a tick
The function is neither reentrant nor ISR callable. Instead of using a ticked-based timeout, have the button driver provide the unboost after a delay when waiting for a button. HAVE_GUI_BOOST gets immediate boost after dequeuing any message, otherwise the queue has to have at least three messages waiting for it to trigger a boost-- essentially the behavior that existed but now combined in one place. Change-Id: I1d924702840f56a1a65abe41fa92b4e753c4e75a
-rw-r--r--apps/action.c50
-rw-r--r--firmware/drivers/button.c106
-rw-r--r--firmware/export/config.h5
3 files changed, 72 insertions, 89 deletions
diff --git a/apps/action.c b/apps/action.c
index 286d4f39b3..30277dc3a6 100644
--- a/apps/action.c
+++ b/apps/action.c
@@ -181,38 +181,6 @@ static inline int get_next_context(const struct button_mapping *items, int i)
181 items[i].action_code; 181 items[i].action_code;
182} 182}
183 183
184#if defined(HAVE_GUI_BOOST) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
185
186/* Timeout for gui boost in seconds. */
187#define GUI_BOOST_TIMEOUT (HZ)
188
189/* Helper function which is called to boost / unboost CPU. This function
190 * avoids to increase boost_count with each call of gui_boost(). */
191static void gui_boost(bool want_to_boost)
192{
193 static bool boosted = false;
194
195 if (want_to_boost && !boosted)
196 {
197 cpu_boost(true);
198 boosted = true;
199 }
200 else if (!want_to_boost && boosted)
201 {
202 cpu_boost(false);
203 boosted = false;
204 }
205}
206
207/* gui_unboost_callback() is called GUI_BOOST_TIMEOUT seconds after the
208 * last wheel scrolling event. */
209static int gui_unboost_callback(struct timeout *tmo)
210{
211 (void)tmo;
212 gui_boost(false);
213 return 0;
214}
215#endif
216 184
217/* 185/*
218 * int get_action_worker(int context, int timeout, bool *is_pre_button, 186 * int get_action_worker(int context, int timeout, bool *is_pre_button,
@@ -242,23 +210,7 @@ static int get_action_worker(int context, int timeout, bool *is_pre_button,
242 210
243 send_event(GUI_EVENT_ACTIONUPDATE, NULL); 211 send_event(GUI_EVENT_ACTIONUPDATE, NULL);
244 212
245 if (timeout == TIMEOUT_NOBLOCK) 213 button = button_get_w_tmo(timeout);
246 button = button_get(false);
247 else if (timeout == TIMEOUT_BLOCK)
248 button = button_get(true);
249 else
250 button = button_get_w_tmo(timeout);
251
252#if defined(HAVE_GUI_BOOST) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
253 static struct timeout gui_unboost;
254 /* Boost the CPU in case of wheel scrolling activity in the defined contexts.
255 * Call unboost with a timeout of GUI_BOOST_TIMEOUT. */
256 if (button != BUTTON_NONE)
257 {
258 gui_boost(true);
259 timeout_register(&gui_unboost, gui_unboost_callback, GUI_BOOST_TIMEOUT, 0);
260 }
261#endif
262 214
263 /* Data from sys events can be pulled with button_get_data 215 /* Data from sys events can be pulled with button_get_data
264 * multimedia button presses don't go through the action system */ 216 * multimedia button presses don't go through the action system */
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c
index d47a486b43..fe9040cef8 100644
--- a/firmware/drivers/button.c
+++ b/firmware/drivers/button.c
@@ -371,21 +371,75 @@ static void button_tick(void)
371} 371}
372 372
373#ifdef HAVE_ADJUSTABLE_CPU_FREQ 373#ifdef HAVE_ADJUSTABLE_CPU_FREQ
374static bool button_boosted = false;
375static long button_unboost_tick;
376#define BUTTON_UNBOOST_TMO HZ
377
374static void button_boost(bool state) 378static void button_boost(bool state)
375{ 379{
376 static bool boosted = false; 380 if (state)
377
378 if (state && !boosted)
379 { 381 {
380 cpu_boost(true); 382 button_unboost_tick = current_tick + BUTTON_UNBOOST_TMO;
381 boosted = true; 383
384 if (!button_boosted)
385 {
386 button_boosted = true;
387 cpu_boost(true);
388 }
382 } 389 }
383 else if (!state && boosted) 390 else if (!state && button_boosted)
384 { 391 {
392 button_boosted = false;
385 cpu_boost(false); 393 cpu_boost(false);
386 boosted = false;
387 } 394 }
388} 395}
396
397static void button_queue_wait(struct queue_event *evp, int timeout)
398{
399 /* Loop once after wait time if boosted in order to unboost and wait the
400 full remaining time */
401 do
402 {
403 int ticks = timeout;
404
405 if (ticks == 0) /* TIMEOUT_NOBLOCK */
406 ;
407 else if (ticks > 0)
408 {
409 if (button_boosted && ticks > BUTTON_UNBOOST_TMO)
410 ticks = BUTTON_UNBOOST_TMO;
411
412 timeout -= ticks;
413 }
414 else /* TIMEOUT_BLOCK (ticks < 0) */
415 {
416 if (button_boosted)
417 ticks = BUTTON_UNBOOST_TMO;
418 }
419
420 queue_wait_w_tmo(&button_queue, evp, ticks);
421 if (evp->id != SYS_TIMEOUT)
422 {
423 /* GUI boost build gets immediate kick, otherwise at least 3
424 messages had to be there */
425 #ifndef HAVE_GUI_BOOST
426 if (queue_count(&button_queue) >= 2)
427 #endif
428 button_boost(true);
429
430 break;
431 }
432
433 if (button_boosted && TIME_AFTER(current_tick, button_unboost_tick))
434 button_boost(false);
435 }
436 while (timeout);
437}
438#else /* ndef HAVE_ADJUSTABLE_CPU_FREQ */
439static inline void button_queue_wait(struct queue_event *evp, int timeout)
440{
441 queue_wait_w_timeout(&button_queue, evp, timeout);
442}
389#endif /* HAVE_ADJUSTABLE_CPU_FREQ */ 443#endif /* HAVE_ADJUSTABLE_CPU_FREQ */
390 444
391int button_queue_count( void ) 445int button_queue_count( void )
@@ -396,44 +450,26 @@ int button_queue_count( void )
396long button_get(bool block) 450long button_get(bool block)
397{ 451{
398 struct queue_event ev; 452 struct queue_event ev;
399 int pending_count = queue_count(&button_queue); 453 button_queue_wait(&ev, block ? TIMEOUT_BLOCK : TIMEOUT_NOBLOCK);
400 454
401#ifdef HAVE_ADJUSTABLE_CPU_FREQ 455 if (ev.id == SYS_TIMEOUT)
402 /* Control the CPU boost trying to keep queue empty. */ 456 ev.id = BUTTON_NONE;
403 if (pending_count == 0) 457 else
404 button_boost(false);
405 else if (pending_count > 2)
406 button_boost(true);
407#endif
408
409 if ( block || pending_count )
410 {
411 queue_wait(&button_queue, &ev);
412
413 button_data = ev.data; 458 button_data = ev.data;
414 return ev.id; 459
415 } 460 return ev.id;
416
417 return BUTTON_NONE;
418} 461}
419 462
420long button_get_w_tmo(int ticks) 463long button_get_w_tmo(int ticks)
421{ 464{
422 struct queue_event ev; 465 struct queue_event ev;
423 466 button_queue_wait(&ev, ticks);
424#ifdef HAVE_ADJUSTABLE_CPU_FREQ 467
425 /* Be sure to keep boosted state. */
426 if (!queue_empty(&button_queue))
427 return button_get(true);
428
429 button_boost(false);
430#endif
431
432 queue_wait_w_tmo(&button_queue, &ev, ticks);
433 if (ev.id == SYS_TIMEOUT) 468 if (ev.id == SYS_TIMEOUT)
434 ev.id = BUTTON_NONE; 469 ev.id = BUTTON_NONE;
435 else 470 else
436 button_data = ev.data; 471 button_data = ev.data;
472
437 return ev.id; 473 return ev.id;
438} 474}
439 475
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 73464526a6..e7cfc698df 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -1129,11 +1129,6 @@ Lyre prototype 1 */
1129#define INCLUDE_TIMEOUT_API 1129#define INCLUDE_TIMEOUT_API
1130#endif /* HAVE_USB_CHARGING_ENABLE && HAVE_USBSTACK */ 1130#endif /* HAVE_USB_CHARGING_ENABLE && HAVE_USBSTACK */
1131 1131
1132#if defined(HAVE_GUI_BOOST) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
1133/* Timeout objects required if GUI boost is enabled */
1134#define INCLUDE_TIMEOUT_API
1135#endif /* HAVE_GUI_BOOST && HAVE_ADJUSTABLE_CPU_FREQ */
1136
1137#ifndef SIMULATOR 1132#ifndef SIMULATOR
1138#if defined(HAVE_USBSTACK) || (CONFIG_STORAGE & STORAGE_NAND) 1133#if defined(HAVE_USBSTACK) || (CONFIG_STORAGE & STORAGE_NAND)
1139#define STORAGE_GET_INFO 1134#define STORAGE_GET_INFO