summaryrefslogtreecommitdiff
path: root/snd-pcxhr/src/pcxhr_clock_monitoring.c
diff options
context:
space:
mode:
authorChristian Pointner <equinox@helsinki.at>2025-05-08 17:45:06 (GMT)
committerChristian Pointner <equinox@helsinki.at>2025-05-08 17:45:06 (GMT)
commite540c2f827bd7c81915b00000e440d91b450b034 (patch)
treefd0525b5425220413f4a54434b1eeb1a2c7a2f56 /snd-pcxhr/src/pcxhr_clock_monitoring.c
parent829bf65b9d6813528cf83a99503955d8894b5bde (diff)
snd-pcxhr: split package up into dkms source and firmwareHEADmaster
Diffstat (limited to 'snd-pcxhr/src/pcxhr_clock_monitoring.c')
-rw-r--r--snd-pcxhr/src/pcxhr_clock_monitoring.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/snd-pcxhr/src/pcxhr_clock_monitoring.c b/snd-pcxhr/src/pcxhr_clock_monitoring.c
new file mode 100644
index 0000000..74043c0
--- /dev/null
+++ b/snd-pcxhr/src/pcxhr_clock_monitoring.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for Digigram pcxhr compatible soundcards
+ *
+ * Copyright (c) 2004 by Digigram <alsa@digigram.com>
+ */
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h> // for threads
+#include <linux/sched.h> // for task_struct
+#include <linux/time.h> // for using jiffies
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include "pcxhr_clock_monitoring.h"
+#include "pcxhr.h"
+
+/*
+ use case 1
+ on démarre en AES et la clock disparait.
+
+ use case 2
+ La clock aes a disparut à un moment... et elle réapparait.
+
+*/
+void clock_monitoring_treatment(struct pcxhr_mgr *mgr) {
+ int rate = 0;
+
+ if((mgr != NULL) )
+ {
+ mutex_lock(&mgr->timer_mutex);
+ if( mgr->use_clock_type != PCXHR_CLOCK_TYPE_INTERNAL ) { //on est cencé être sur de l AES
+ pcxhr_get_external_clock(mgr,mgr->use_clock_type,&rate);
+ if( rate == 0 ) {
+ dev_err(&mgr->pci->dev, "\tpcxhr_clock_monitoring_tasklet external clock disappears...\n");
+ mgr->expected_clock_type = mgr->use_clock_type;
+ mgr->use_clock_type = PCXHR_CLOCK_TYPE_INTERNAL;
+ pcxhr_set_clock(mgr, mgr->sample_rate_real);
+ }
+ }
+ else { //on est déjà sur l horloge interne on test si l aes est de retour
+ pcxhr_get_external_clock(mgr,mgr->expected_clock_type,&rate);
+ if( rate != 0) {
+ dev_err(&mgr->pci->dev, "\tpcxhr_clock_monitoring_tasklet external clock reappears...\n");
+ mgr->use_clock_type = mgr->expected_clock_type;
+ pcxhr_set_clock(mgr, rate);
+ }
+ }
+ mutex_unlock(&mgr->timer_mutex);
+ }else {
+ dev_err(&mgr->pci->dev, "\tclock_monitoring_treatment mgr pointer null\n");
+ }
+}
+
+int clock_monitoring_thread(void *ptr) {
+ struct pcxhr_mgr *mgr = (struct pcxhr_mgr*) ptr;
+
+ printk(KERN_INFO "In thread %s", mgr->shortname);
+ while (1){
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ clock_monitoring_treatment(mgr);
+ }
+ dev_info(&mgr->pci->dev, "clock_monitoring_thread on sort\n");
+ return 0;
+}
+
+int clock_monitoring_thread_init(struct pcxhr_mgr *mgr) {
+
+ char* our_thread="clockMonitoring thread";
+
+ mgr->thread = kthread_create(clock_monitoring_thread,mgr,our_thread);
+ if(mgr->thread == NULL) {
+ dev_err(&mgr->pci->dev, "clock_monitoring_thread_init kthread_create FAILED\n");
+ return -ENOMEM;
+ }
+ wake_up_process(mgr->thread);
+ return 0;
+}
+
+//void thread_cleanup(void) {
+//}
+
+static void clockMonitor_timedout(unsigned long ptr) {
+ struct pcxhr_mgr *mgr = (struct pcxhr_mgr*) ptr;
+
+ if( (mgr != NULL) && (mgr->timer_state == 1) ) {
+ mod_timer(mgr->clockMonitor_timer, (jiffies + msecs_to_jiffies(1000)));
+ wake_up_process(mgr->thread);
+ }
+
+ if(mgr->timer_state == 0) {
+ dev_info(&mgr->pci->dev, "\tclockMonitor_timedout timer should stop do not reload it\n");
+ }
+}
+
+
+int clockMonitor_stop(struct pcxhr_mgr *mgr){
+ int result = 0;
+ mutex_lock(&mgr->timer_mutex);
+
+ dev_info(&mgr->pci->dev, " clockMonitor_stop %s\n", mgr->shortname);
+ if((mgr->clockMonitor_timer != NULL)&& (mgr->timer_state == 1)) {
+// result = del_timer(mgr->clockMonitor_timer);
+ result = del_timer_sync(mgr->clockMonitor_timer);
+ mgr->timer_state = 0;
+ }
+ mutex_unlock(&mgr->timer_mutex);
+ return 0;
+}
+
+int clockMonitor_start(struct pcxhr_mgr *mgr){
+ mutex_lock(&mgr->timer_mutex);
+ if(mgr->timer_state == 0) { //déjà était démarré...
+ dev_info(&mgr->pci->dev, "clockMonitor_start %s\n", mgr->shortname);
+
+ init_timer(mgr->clockMonitor_timer);
+ mgr->clockMonitor_timer->function = clockMonitor_timedout;
+ mgr->clockMonitor_timer->data = (unsigned long)mgr;
+ mgr->clockMonitor_timer->expires = jiffies + msecs_to_jiffies(2000);
+ add_timer(mgr->clockMonitor_timer);
+ mgr->timer_state = 1;
+ }
+ mutex_unlock(&mgr->timer_mutex);
+ return 0;
+}
+
+
+int clockMonitor_init(struct pcxhr_mgr *mgr){
+ dev_info(&mgr->pci->dev, "clockMonitor_init %s\n", mgr->shortname);
+
+ mutex_init(&mgr->timer_mutex);
+
+ mgr->clockMonitor_timer = (struct timer_list*) kmalloc(sizeof(struct timer_list), GFP_KERNEL);
+ if(mgr->clockMonitor_timer == NULL){
+ dev_info(&mgr->pci->dev, "clockMonitor_init failed mgr->clockMonitor_timer NULL\n");
+ return -ENOMEM;
+ }
+ //init_timer(mgr->clockMonitor_timer);
+
+ mgr->timer_state = 0;
+
+ return clock_monitoring_thread_init(mgr);
+}
+
+int clockMonitor_free(struct pcxhr_mgr *mgr){
+ dev_info(&mgr->pci->dev, "clockMonitor_free %s\n", mgr->shortname);
+
+ if (mgr->clockMonitor_timer != NULL)
+ {
+ kfree(mgr->clockMonitor_timer);
+ }
+ mgr->timer_state = 0;
+
+ return 0;
+}