15c8c1079SŠerif Rami /* SPDX-License-Identifier: GPL-2.0-only */ 25c8c1079SŠerif Rami // Copyright (c) 2025 Šerif Rami <ramiserifpersia@gmail.com> 35c8c1079SŠerif Rami 45c8c1079SŠerif Rami #ifndef __US144MKII_PCM_H 55c8c1079SŠerif Rami #define __US144MKII_PCM_H 65c8c1079SŠerif Rami 75c8c1079SŠerif Rami #include "us144mkii.h" 85c8c1079SŠerif Rami 95c8c1079SŠerif Rami /** 105c8c1079SŠerif Rami * tascam_pcm_hw - Hardware capabilities for TASCAM US-144MKII PCM. 115c8c1079SŠerif Rami * 125c8c1079SŠerif Rami * Defines the supported PCM formats, rates, channels, and buffer/period sizes 135c8c1079SŠerif Rami * for the TASCAM US-144MKII audio interface. 145c8c1079SŠerif Rami */ 155c8c1079SŠerif Rami extern const struct snd_pcm_hardware tascam_pcm_hw; 165c8c1079SŠerif Rami 175c8c1079SŠerif Rami /** 185c8c1079SŠerif Rami * tascam_playback_ops - ALSA PCM operations for playback. 195c8c1079SŠerif Rami * 205c8c1079SŠerif Rami * This structure defines the callback functions for playback stream operations. 215c8c1079SŠerif Rami */ 225c8c1079SŠerif Rami extern const struct snd_pcm_ops tascam_playback_ops; 235c8c1079SŠerif Rami 245c8c1079SŠerif Rami /** 255c8c1079SŠerif Rami * tascam_capture_ops - ALSA PCM operations for capture. 265c8c1079SŠerif Rami * 275c8c1079SŠerif Rami * This structure defines the callback functions for capture stream operations. 285c8c1079SŠerif Rami */ 295c8c1079SŠerif Rami extern const struct snd_pcm_ops tascam_capture_ops; 305c8c1079SŠerif Rami 315c8c1079SŠerif Rami /** 32a2a2210fSŠerif Rami * playback_urb_complete() - Completion handler for playback isochronous URBs. 33a2a2210fSŠerif Rami * @urb: the completed URB 34a2a2210fSŠerif Rami * 35a2a2210fSŠerif Rami * This function runs in interrupt context. It calculates the number of bytes 36a2a2210fSŠerif Rami * to send in the next set of packets based on the feedback-driven clock, 37a2a2210fSŠerif Rami * copies the audio data from the ALSA ring buffer, and resubmits the URB. 38a2a2210fSŠerif Rami */ 39a2a2210fSŠerif Rami void playback_urb_complete(struct urb *urb); 40a2a2210fSŠerif Rami 41a2a2210fSŠerif Rami /** 42a2a2210fSŠerif Rami * feedback_urb_complete() - Completion handler for feedback isochronous URBs. 43a2a2210fSŠerif Rami * @urb: the completed URB 44a2a2210fSŠerif Rami * 45a2a2210fSŠerif Rami * This is the master clock for the driver. It runs in interrupt context. 46a2a2210fSŠerif Rami * It reads the feedback value from the device, which indicates how many 47a2a2210fSŠerif Rami * samples the device has consumed. This information is used to adjust the 48a2a2210fSŠerif Rami * playback rate and to advance the capture stream pointer, keeping both 49a2a2210fSŠerif Rami * streams in sync. It then calls snd_pcm_period_elapsed if necessary and 50a2a2210fSŠerif Rami * resubmits itself. 51a2a2210fSŠerif Rami */ 52a2a2210fSŠerif Rami void feedback_urb_complete(struct urb *urb); 53a2a2210fSŠerif Rami 54a2a2210fSŠerif Rami /** 55*c1bb0c13SŠerif Rami * capture_urb_complete() - Completion handler for capture bulk URBs. 56*c1bb0c13SŠerif Rami * @urb: the completed URB 57*c1bb0c13SŠerif Rami * 58*c1bb0c13SŠerif Rami * This function runs in interrupt context. It copies the received raw data 59*c1bb0c13SŠerif Rami * into an intermediate ring buffer and then schedules the workqueue to process 60*c1bb0c13SŠerif Rami * it. It then resubmits the URB to receive more data. 61*c1bb0c13SŠerif Rami */ 62*c1bb0c13SŠerif Rami void capture_urb_complete(struct urb *urb); 63*c1bb0c13SŠerif Rami 64*c1bb0c13SŠerif Rami /** 65a2a2210fSŠerif Rami * tascam_stop_pcm_work_handler() - Work handler to stop PCM streams. 66a2a2210fSŠerif Rami * @work: Pointer to the work_struct. 67a2a2210fSŠerif Rami * 68a2a2210fSŠerif Rami * This function is scheduled to stop PCM streams (playback and capture) 69a2a2210fSŠerif Rami * from a workqueue context, avoiding blocking operations in interrupt context. 70a2a2210fSŠerif Rami */ 71a2a2210fSŠerif Rami void tascam_stop_pcm_work_handler(struct work_struct *work); 72a2a2210fSŠerif Rami 73a2a2210fSŠerif Rami /** 745c8c1079SŠerif Rami * tascam_init_pcm() - Initializes the ALSA PCM device. 755c8c1079SŠerif Rami * @pcm: Pointer to the ALSA PCM device to initialize. 765c8c1079SŠerif Rami * 77*c1bb0c13SŠerif Rami * This function sets up the PCM operations, adds ALSA controls for routing 78*c1bb0c13SŠerif Rami * and sample rate, and preallocates pages for the PCM buffer. 795c8c1079SŠerif Rami * 805c8c1079SŠerif Rami * Return: 0 on success, or a negative error code on failure. 815c8c1079SŠerif Rami */ 825c8c1079SŠerif Rami int tascam_init_pcm(struct snd_pcm *pcm); 835c8c1079SŠerif Rami 845c8c1079SŠerif Rami /** 85a2a2210fSŠerif Rami * us144mkii_configure_device_for_rate() - Set sample rate via USB control msgs 86a2a2210fSŠerif Rami * @tascam: the tascam_card instance 87a2a2210fSŠerif Rami * @rate: the target sample rate (e.g., 44100, 96000) 88a2a2210fSŠerif Rami * 89a2a2210fSŠerif Rami * This function sends a sequence of vendor-specific and UAC control messages 90a2a2210fSŠerif Rami * to configure the device hardware for the specified sample rate. 91a2a2210fSŠerif Rami * 92a2a2210fSŠerif Rami * Return: 0 on success, or a negative error code on failure. 93a2a2210fSŠerif Rami */ 94a2a2210fSŠerif Rami int us144mkii_configure_device_for_rate(struct tascam_card *tascam, int rate); 95a2a2210fSŠerif Rami 96a2a2210fSŠerif Rami /** 97a2a2210fSŠerif Rami * process_playback_routing_us144mkii() - Apply playback routing matrix 98a2a2210fSŠerif Rami * @tascam: The driver instance. 99a2a2210fSŠerif Rami * @src_buffer: Buffer containing 4 channels of S24_3LE audio from ALSA. 100a2a2210fSŠerif Rami * @dst_buffer: Buffer to be filled for the USB device. 101a2a2210fSŠerif Rami * @frames: Number of frames to process. 102a2a2210fSŠerif Rami */ 103a2a2210fSŠerif Rami void process_playback_routing_us144mkii(struct tascam_card *tascam, 104a2a2210fSŠerif Rami const u8 *src_buffer, u8 *dst_buffer, 105a2a2210fSŠerif Rami size_t frames); 106a2a2210fSŠerif Rami 107a2a2210fSŠerif Rami /** 108*c1bb0c13SŠerif Rami * process_capture_routing_us144mkii() - Apply capture routing matrix 109*c1bb0c13SŠerif Rami * @tascam: The driver instance. 110*c1bb0c13SŠerif Rami * @decoded_block: Buffer containing 4 channels of S32LE decoded audio. 111*c1bb0c13SŠerif Rami * @routed_block: Buffer to be filled for ALSA. 112*c1bb0c13SŠerif Rami */ 113*c1bb0c13SŠerif Rami void process_capture_routing_us144mkii(struct tascam_card *tascam, 114*c1bb0c13SŠerif Rami const s32 *decoded_block, 115*c1bb0c13SŠerif Rami s32 *routed_block); 116*c1bb0c13SŠerif Rami 117*c1bb0c13SŠerif Rami /** 1185c8c1079SŠerif Rami * tascam_pcm_hw_params() - Configures hardware parameters for PCM streams. 1195c8c1079SŠerif Rami * @substream: The ALSA PCM substream. 1205c8c1079SŠerif Rami * @params: The hardware parameters to apply. 1215c8c1079SŠerif Rami * 122a2a2210fSŠerif Rami * This function allocates pages for the PCM buffer and, for playback streams, 123a2a2210fSŠerif Rami * selects the appropriate feedback patterns based on the requested sample rate. 124a2a2210fSŠerif Rami * It also configures the device hardware for the selected sample rate if it 125a2a2210fSŠerif Rami * has changed. 1265c8c1079SŠerif Rami * 127a2a2210fSŠerif Rami * Return: 0 on success, or a negative error code on failure. 1285c8c1079SŠerif Rami */ 1295c8c1079SŠerif Rami int tascam_pcm_hw_params(struct snd_pcm_substream *substream, 1305c8c1079SŠerif Rami struct snd_pcm_hw_params *params); 1315c8c1079SŠerif Rami 1325c8c1079SŠerif Rami /** 1335c8c1079SŠerif Rami * tascam_pcm_hw_free() - Frees hardware parameters for PCM streams. 1345c8c1079SŠerif Rami * @substream: The ALSA PCM substream. 1355c8c1079SŠerif Rami * 1365c8c1079SŠerif Rami * This function is a stub for freeing hardware-related resources. 1375c8c1079SŠerif Rami * 1385c8c1079SŠerif Rami * Return: 0 on success. 1395c8c1079SŠerif Rami */ 1405c8c1079SŠerif Rami int tascam_pcm_hw_free(struct snd_pcm_substream *substream); 1415c8c1079SŠerif Rami 1425c8c1079SŠerif Rami /** 1435c8c1079SŠerif Rami * tascam_pcm_trigger() - Triggers the start or stop of PCM streams. 1445c8c1079SŠerif Rami * @substream: The ALSA PCM substream. 1455c8c1079SŠerif Rami * @cmd: The trigger command (e.g., SNDRV_PCM_TRIGGER_START). 1465c8c1079SŠerif Rami * 1475c8c1079SŠerif Rami * This function handles starting and stopping of playback and capture streams 148a2a2210fSŠerif Rami * by submitting or killing the associated URBs. 1495c8c1079SŠerif Rami * 1505c8c1079SŠerif Rami * Return: 0 on success, or a negative error code on failure. 1515c8c1079SŠerif Rami */ 1525c8c1079SŠerif Rami int tascam_pcm_trigger(struct snd_pcm_substream *substream, int cmd); 1535c8c1079SŠerif Rami 154*c1bb0c13SŠerif Rami /** 155*c1bb0c13SŠerif Rami * tascam_capture_work_handler() - Deferred work for processing capture data. 156*c1bb0c13SŠerif Rami * @work: the work_struct instance 157*c1bb0c13SŠerif Rami * 158*c1bb0c13SŠerif Rami * This function runs in a kernel thread context, not an IRQ context. It reads 159*c1bb0c13SŠerif Rami * raw data from the capture ring buffer, decodes it, applies routing, and 160*c1bb0c13SŠerif Rami * copies the final audio data into the ALSA capture ring buffer. This offloads 161*c1bb0c13SŠerif Rami * the CPU-intensive decoding from the time-sensitive URB completion handlers. 162*c1bb0c13SŠerif Rami */ 163*c1bb0c13SŠerif Rami void tascam_capture_work_handler(struct work_struct *work); 164*c1bb0c13SŠerif Rami 1655c8c1079SŠerif Rami #endif /* __US144MKII_PCM_H */ 166