162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <linux/kthread.h>
362306a36Sopenharmony_ci#include <linux/wait.h>
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include "spk_types.h"
662306a36Sopenharmony_ci#include "speakup.h"
762306a36Sopenharmony_ci#include "spk_priv.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciDECLARE_WAIT_QUEUE_HEAD(speakup_event);
1062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(speakup_event);
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ciint speakup_thread(void *data)
1362306a36Sopenharmony_ci{
1462306a36Sopenharmony_ci	unsigned long flags;
1562306a36Sopenharmony_ci	int should_break;
1662306a36Sopenharmony_ci	struct bleep our_sound;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	our_sound.active = 0;
1962306a36Sopenharmony_ci	our_sound.freq = 0;
2062306a36Sopenharmony_ci	our_sound.jiffies = 0;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	mutex_lock(&spk_mutex);
2362306a36Sopenharmony_ci	while (1) {
2462306a36Sopenharmony_ci		DEFINE_WAIT(wait);
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci		while (1) {
2762306a36Sopenharmony_ci			spin_lock_irqsave(&speakup_info.spinlock, flags);
2862306a36Sopenharmony_ci			our_sound = spk_unprocessed_sound;
2962306a36Sopenharmony_ci			spk_unprocessed_sound.active = 0;
3062306a36Sopenharmony_ci			prepare_to_wait(&speakup_event, &wait,
3162306a36Sopenharmony_ci					TASK_INTERRUPTIBLE);
3262306a36Sopenharmony_ci			should_break = kthread_should_stop() ||
3362306a36Sopenharmony_ci				our_sound.active ||
3462306a36Sopenharmony_ci				(synth && synth->catch_up && synth->alive &&
3562306a36Sopenharmony_ci					(speakup_info.flushing ||
3662306a36Sopenharmony_ci					!synth_buffer_empty()));
3762306a36Sopenharmony_ci			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
3862306a36Sopenharmony_ci			if (should_break)
3962306a36Sopenharmony_ci				break;
4062306a36Sopenharmony_ci			mutex_unlock(&spk_mutex);
4162306a36Sopenharmony_ci			schedule();
4262306a36Sopenharmony_ci			mutex_lock(&spk_mutex);
4362306a36Sopenharmony_ci		}
4462306a36Sopenharmony_ci		finish_wait(&speakup_event, &wait);
4562306a36Sopenharmony_ci		if (kthread_should_stop())
4662306a36Sopenharmony_ci			break;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci		if (our_sound.active)
4962306a36Sopenharmony_ci			kd_mksound(our_sound.freq, our_sound.jiffies);
5062306a36Sopenharmony_ci		if (synth && synth->catch_up && synth->alive) {
5162306a36Sopenharmony_ci			/*
5262306a36Sopenharmony_ci			 * It is up to the callee to take the lock, so that it
5362306a36Sopenharmony_ci			 * can sleep whenever it likes
5462306a36Sopenharmony_ci			 */
5562306a36Sopenharmony_ci			synth->catch_up(synth);
5662306a36Sopenharmony_ci		}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci		speakup_start_ttys();
5962306a36Sopenharmony_ci	}
6062306a36Sopenharmony_ci	mutex_unlock(&spk_mutex);
6162306a36Sopenharmony_ci	return 0;
6262306a36Sopenharmony_ci}
63