2/5
This commit is contained in:
parent
7fd61770fc
commit
c8eb8e1adf
14
us144mkii.c
14
us144mkii.c
|
|
@ -62,7 +62,7 @@ static void tascam_card_private_free(struct snd_card *card) {
|
||||||
* - Checking for the second interface (MIDI) and associating it.
|
* - Checking for the second interface (MIDI) and associating it.
|
||||||
* - Performing a vendor-specific handshake with the device.
|
* - Performing a vendor-specific handshake with the device.
|
||||||
* - Setting alternate settings for USB interfaces.
|
* - Setting alternate settings for USB interfaces.
|
||||||
* - Creating and registering the ALSA sound card.
|
* - Creating and registering the ALSA sound card and PCM device.
|
||||||
*
|
*
|
||||||
* Return: 0 on success, or a negative error code on failure.
|
* Return: 0 on success, or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
|
|
@ -143,6 +143,18 @@ static int tascam_probe(struct usb_interface *intf,
|
||||||
tascam->card = card;
|
tascam->card = card;
|
||||||
tascam->iface0 = intf;
|
tascam->iface0 = intf;
|
||||||
|
|
||||||
|
spin_lock_init(&tascam->lock);
|
||||||
|
|
||||||
|
err = snd_pcm_new(card, "US144MKII PCM", 0, 1, 1, &tascam->pcm);
|
||||||
|
if (err < 0)
|
||||||
|
goto free_card;
|
||||||
|
tascam->pcm->private_data = tascam;
|
||||||
|
strscpy(tascam->pcm->name, "US144MKII PCM", sizeof(tascam->pcm->name));
|
||||||
|
|
||||||
|
err = tascam_init_pcm(tascam->pcm);
|
||||||
|
if (err < 0)
|
||||||
|
goto free_card;
|
||||||
|
|
||||||
strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));
|
strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));
|
||||||
if (dev->descriptor.idProduct == USB_PID_TASCAM_US144) {
|
if (dev->descriptor.idProduct == USB_PID_TASCAM_US144) {
|
||||||
strscpy(card->shortname, "TASCAM US-144", sizeof(card->shortname));
|
strscpy(card->shortname, "TASCAM US-144", sizeof(card->shortname));
|
||||||
|
|
|
||||||
37
us144mkii.h
37
us144mkii.h
|
|
@ -7,6 +7,7 @@
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/initval.h>
|
#include <sound/initval.h>
|
||||||
|
#include <sound/pcm.h>
|
||||||
|
|
||||||
#define DRIVER_NAME "us144mkii"
|
#define DRIVER_NAME "us144mkii"
|
||||||
|
|
||||||
|
|
@ -15,24 +16,60 @@
|
||||||
#define USB_PID_TASCAM_US144 0x800f
|
#define USB_PID_TASCAM_US144 0x800f
|
||||||
#define USB_PID_TASCAM_US144MKII 0x8020
|
#define USB_PID_TASCAM_US144MKII 0x8020
|
||||||
|
|
||||||
|
/* --- Audio Format Configuration --- */
|
||||||
|
#define BYTES_PER_SAMPLE 3
|
||||||
|
#define NUM_CHANNELS 4
|
||||||
|
#define BYTES_PER_FRAME (NUM_CHANNELS * BYTES_PER_SAMPLE)
|
||||||
|
|
||||||
/* --- USB Control Message Protocol --- */
|
/* --- USB Control Message Protocol --- */
|
||||||
#define RT_D2H_VENDOR_DEV (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
|
#define RT_D2H_VENDOR_DEV (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
|
||||||
#define VENDOR_REQ_MODE_CONTROL 0x49
|
#define VENDOR_REQ_MODE_CONTROL 0x49
|
||||||
#define MODE_VAL_HANDSHAKE_READ 0x0000
|
#define MODE_VAL_HANDSHAKE_READ 0x0000
|
||||||
#define USB_CTRL_TIMEOUT_MS 1000
|
#define USB_CTRL_TIMEOUT_MS 1000
|
||||||
|
|
||||||
|
struct tascam_card;
|
||||||
|
|
||||||
|
#include "us144mkii_pcm.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct tascam_card - Main driver data structure for the TASCAM US-144MKII.
|
* struct tascam_card - Main driver data structure for the TASCAM US-144MKII.
|
||||||
* @dev: Pointer to the USB device.
|
* @dev: Pointer to the USB device.
|
||||||
* @iface0: Pointer to USB interface 0 (audio).
|
* @iface0: Pointer to USB interface 0 (audio).
|
||||||
* @iface1: Pointer to USB interface 1 (MIDI).
|
* @iface1: Pointer to USB interface 1 (MIDI).
|
||||||
* @card: Pointer to the ALSA sound card instance.
|
* @card: Pointer to the ALSA sound card instance.
|
||||||
|
* @pcm: Pointer to the ALSA PCM device.
|
||||||
|
* @playback_substream: Pointer to the active playback PCM substream.
|
||||||
|
* @capture_substream: Pointer to the active capture PCM substream.
|
||||||
|
* @playback_active: Atomic flag indicating if playback is active.
|
||||||
|
* @capture_active: Atomic flag indicating if capture is active.
|
||||||
|
* @driver_playback_pos: Current position in the ALSA playback buffer (frames).
|
||||||
|
* @driver_capture_pos: Current position in the ALSA capture buffer (frames).
|
||||||
|
* @playback_frames_consumed: Total frames consumed by playback.
|
||||||
|
* @capture_frames_processed: Total frames processed for capture.
|
||||||
|
* @current_rate: Currently configured sample rate of the device.
|
||||||
|
* @lock: Main spinlock for protecting shared driver state.
|
||||||
*/
|
*/
|
||||||
struct tascam_card {
|
struct tascam_card {
|
||||||
struct usb_device *dev;
|
struct usb_device *dev;
|
||||||
struct usb_interface *iface0;
|
struct usb_interface *iface0;
|
||||||
struct usb_interface *iface1;
|
struct usb_interface *iface1;
|
||||||
struct snd_card *card;
|
struct snd_card *card;
|
||||||
|
struct snd_pcm *pcm;
|
||||||
|
|
||||||
|
struct snd_pcm_substream *playback_substream;
|
||||||
|
struct snd_pcm_substream *capture_substream;
|
||||||
|
|
||||||
|
atomic_t playback_active;
|
||||||
|
atomic_t capture_active;
|
||||||
|
|
||||||
|
snd_pcm_uframes_t driver_playback_pos;
|
||||||
|
snd_pcm_uframes_t driver_capture_pos;
|
||||||
|
|
||||||
|
u64 playback_frames_consumed;
|
||||||
|
u64 capture_frames_processed;
|
||||||
|
|
||||||
|
int current_rate;
|
||||||
|
spinlock_t lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __US144MKII_H */
|
#endif /* __US144MKII_H */
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
// Copyright (c) 2025 Šerif Rami <ramiserifpersia@gmail.com>
|
||||||
|
|
||||||
|
#include "us144mkii.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_capture_open() - Opens the PCM capture substream.
|
||||||
|
* @substream: The ALSA PCM substream to open.
|
||||||
|
*
|
||||||
|
* This function sets the hardware parameters for the capture substream
|
||||||
|
* and stores a reference to the substream in the driver's private data.
|
||||||
|
*
|
||||||
|
* Return: 0 on success.
|
||||||
|
*/
|
||||||
|
static int tascam_capture_open(struct snd_pcm_substream *substream) {
|
||||||
|
struct tascam_card *tascam = snd_pcm_substream_chip(substream);
|
||||||
|
|
||||||
|
substream->runtime->hw = tascam_pcm_hw;
|
||||||
|
tascam->capture_substream = substream;
|
||||||
|
atomic_set(&tascam->capture_active, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_capture_close() - Closes the PCM capture substream.
|
||||||
|
* @substream: The ALSA PCM substream to close.
|
||||||
|
*
|
||||||
|
* This function clears the reference to the capture substream in the
|
||||||
|
* driver's private data.
|
||||||
|
*
|
||||||
|
* Return: 0 on success.
|
||||||
|
*/
|
||||||
|
static int tascam_capture_close(struct snd_pcm_substream *substream) {
|
||||||
|
struct tascam_card *tascam = snd_pcm_substream_chip(substream);
|
||||||
|
|
||||||
|
tascam->capture_substream = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_capture_prepare() - Prepares the PCM capture substream for use.
|
||||||
|
* @substream: The ALSA PCM substream to prepare.
|
||||||
|
*
|
||||||
|
* This function initializes capture-related counters.
|
||||||
|
*
|
||||||
|
* Return: 0 on success.
|
||||||
|
*/
|
||||||
|
static int tascam_capture_prepare(struct snd_pcm_substream *substream) {
|
||||||
|
struct tascam_card *tascam = snd_pcm_substream_chip(substream);
|
||||||
|
|
||||||
|
tascam->driver_capture_pos = 0;
|
||||||
|
tascam->capture_frames_processed = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_capture_pointer() - Returns the current capture pointer position.
|
||||||
|
* @substream: The ALSA PCM substream.
|
||||||
|
*
|
||||||
|
* This function returns the current position of the capture pointer within
|
||||||
|
* the ALSA ring buffer, in frames.
|
||||||
|
*
|
||||||
|
* Return: The current capture pointer position in frames.
|
||||||
|
*/
|
||||||
|
static snd_pcm_uframes_t
|
||||||
|
tascam_capture_pointer(struct snd_pcm_substream *substream) {
|
||||||
|
struct tascam_card *tascam = snd_pcm_substream_chip(substream);
|
||||||
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
u64 pos;
|
||||||
|
|
||||||
|
if (!atomic_read(&tascam->capture_active))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
guard(spinlock_irqsave)(&tascam->lock);
|
||||||
|
pos = tascam->capture_frames_processed;
|
||||||
|
|
||||||
|
if (runtime->buffer_size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
u64 remainder = do_div(pos, runtime->buffer_size);
|
||||||
|
return runtime ? remainder : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_capture_ops - ALSA PCM operations for capture.
|
||||||
|
*
|
||||||
|
* This structure defines the callback functions for capture stream operations,
|
||||||
|
* including open, close, ioctl, hardware parameters, hardware free, prepare,
|
||||||
|
* trigger, and pointer.
|
||||||
|
*/
|
||||||
|
const struct snd_pcm_ops tascam_capture_ops = {
|
||||||
|
.open = tascam_capture_open,
|
||||||
|
.close = tascam_capture_close,
|
||||||
|
.ioctl = snd_pcm_lib_ioctl,
|
||||||
|
.hw_params = tascam_pcm_hw_params,
|
||||||
|
.hw_free = tascam_pcm_hw_free,
|
||||||
|
.prepare = tascam_capture_prepare,
|
||||||
|
.trigger = tascam_pcm_trigger,
|
||||||
|
.pointer = tascam_capture_pointer,
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
// Copyright (c) 2025 Šerif Rami <ramiserifpersia@gmail.com>
|
||||||
|
|
||||||
|
#include "us144mkii.h"
|
||||||
|
|
||||||
|
const struct snd_pcm_hardware tascam_pcm_hw = {
|
||||||
|
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
|
||||||
|
SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID |
|
||||||
|
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
|
||||||
|
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
|
||||||
|
.rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
|
||||||
|
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
|
||||||
|
.rate_min = 44100,
|
||||||
|
.rate_max = 96000,
|
||||||
|
.channels_min = NUM_CHANNELS,
|
||||||
|
.channels_max = NUM_CHANNELS,
|
||||||
|
.buffer_bytes_max = 1024 * 1024,
|
||||||
|
.period_bytes_min = 48 * BYTES_PER_FRAME,
|
||||||
|
.period_bytes_max = 1024 * BYTES_PER_FRAME,
|
||||||
|
.periods_min = 2,
|
||||||
|
.periods_max = 1024,
|
||||||
|
};
|
||||||
|
|
||||||
|
int tascam_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tascam_pcm_hw_free(struct snd_pcm_substream *substream) { return 0; }
|
||||||
|
|
||||||
|
int tascam_pcm_trigger(struct snd_pcm_substream *substream, int cmd) {
|
||||||
|
struct tascam_card *tascam = snd_pcm_substream_chip(substream);
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
guard(spinlock_irqsave)(&tascam->lock);
|
||||||
|
switch (cmd) {
|
||||||
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
|
case SNDRV_PCM_TRIGGER_RESUME:
|
||||||
|
if (!atomic_read(&tascam->playback_active)) {
|
||||||
|
atomic_set(&tascam->playback_active, 1);
|
||||||
|
atomic_set(&tascam->capture_active, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SNDRV_PCM_TRIGGER_STOP:
|
||||||
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||||
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
|
if (atomic_read(&tascam->playback_active)) {
|
||||||
|
atomic_set(&tascam->playback_active, 0);
|
||||||
|
atomic_set(&tascam->capture_active, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tascam_init_pcm(struct snd_pcm *pcm) {
|
||||||
|
struct tascam_card *tascam = pcm->private_data;
|
||||||
|
|
||||||
|
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &tascam_playback_ops);
|
||||||
|
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &tascam_capture_ops);
|
||||||
|
|
||||||
|
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
|
||||||
|
tascam->dev->dev.parent, 64 * 1024,
|
||||||
|
tascam_pcm_hw.buffer_bytes_max);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
// Copyright (c) 2025 Šerif Rami <ramiserifpersia@gmail.com>
|
||||||
|
|
||||||
|
#ifndef __US144MKII_PCM_H
|
||||||
|
#define __US144MKII_PCM_H
|
||||||
|
|
||||||
|
#include "us144mkii.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_pcm_hw - Hardware capabilities for TASCAM US-144MKII PCM.
|
||||||
|
*
|
||||||
|
* Defines the supported PCM formats, rates, channels, and buffer/period sizes
|
||||||
|
* for the TASCAM US-144MKII audio interface.
|
||||||
|
*/
|
||||||
|
extern const struct snd_pcm_hardware tascam_pcm_hw;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_playback_ops - ALSA PCM operations for playback.
|
||||||
|
*
|
||||||
|
* This structure defines the callback functions for playback stream operations.
|
||||||
|
*/
|
||||||
|
extern const struct snd_pcm_ops tascam_playback_ops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_capture_ops - ALSA PCM operations for capture.
|
||||||
|
*
|
||||||
|
* This structure defines the callback functions for capture stream operations.
|
||||||
|
*/
|
||||||
|
extern const struct snd_pcm_ops tascam_capture_ops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_init_pcm() - Initializes the ALSA PCM device.
|
||||||
|
* @pcm: Pointer to the ALSA PCM device to initialize.
|
||||||
|
*
|
||||||
|
* This function sets up the PCM operations and preallocates pages for the
|
||||||
|
* PCM buffer.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, or a negative error code on failure.
|
||||||
|
*/
|
||||||
|
int tascam_init_pcm(struct snd_pcm *pcm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_pcm_hw_params() - Configures hardware parameters for PCM streams.
|
||||||
|
* @substream: The ALSA PCM substream.
|
||||||
|
* @params: The hardware parameters to apply.
|
||||||
|
*
|
||||||
|
* This function is a stub for handling hardware parameter configuration.
|
||||||
|
*
|
||||||
|
* Return: 0 on success.
|
||||||
|
*/
|
||||||
|
int tascam_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_pcm_hw_free() - Frees hardware parameters for PCM streams.
|
||||||
|
* @substream: The ALSA PCM substream.
|
||||||
|
*
|
||||||
|
* This function is a stub for freeing hardware-related resources.
|
||||||
|
*
|
||||||
|
* Return: 0 on success.
|
||||||
|
*/
|
||||||
|
int tascam_pcm_hw_free(struct snd_pcm_substream *substream);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_pcm_trigger() - Triggers the start or stop of PCM streams.
|
||||||
|
* @substream: The ALSA PCM substream.
|
||||||
|
* @cmd: The trigger command (e.g., SNDRV_PCM_TRIGGER_START).
|
||||||
|
*
|
||||||
|
* This function handles starting and stopping of playback and capture streams
|
||||||
|
* by setting atomic flags.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, or a negative error code on failure.
|
||||||
|
*/
|
||||||
|
int tascam_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
|
||||||
|
|
||||||
|
#endif /* __US144MKII_PCM_H */
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
// Copyright (c) 2025 Šerif Rami <ramiserifpersia@gmail.com>
|
||||||
|
|
||||||
|
#include "us144mkii.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_playback_open() - Opens the PCM playback substream.
|
||||||
|
* @substream: The ALSA PCM substream to open.
|
||||||
|
*
|
||||||
|
* This function sets the hardware parameters for the playback substream
|
||||||
|
* and stores a reference to the substream in the driver's private data.
|
||||||
|
*
|
||||||
|
* Return: 0 on success.
|
||||||
|
*/
|
||||||
|
static int tascam_playback_open(struct snd_pcm_substream *substream) {
|
||||||
|
struct tascam_card *tascam = snd_pcm_substream_chip(substream);
|
||||||
|
|
||||||
|
substream->runtime->hw = tascam_pcm_hw;
|
||||||
|
tascam->playback_substream = substream;
|
||||||
|
atomic_set(&tascam->playback_active, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_playback_close() - Closes the PCM playback substream.
|
||||||
|
* @substream: The ALSA PCM substream to close.
|
||||||
|
*
|
||||||
|
* This function clears the reference to the playback substream in the
|
||||||
|
* driver's private data.
|
||||||
|
*
|
||||||
|
* Return: 0 on success.
|
||||||
|
*/
|
||||||
|
static int tascam_playback_close(struct snd_pcm_substream *substream) {
|
||||||
|
struct tascam_card *tascam = snd_pcm_substream_chip(substream);
|
||||||
|
|
||||||
|
tascam->playback_substream = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_playback_prepare() - Prepares the PCM playback substream for use.
|
||||||
|
* @substream: The ALSA PCM substream to prepare.
|
||||||
|
*
|
||||||
|
* This function initializes playback-related counters.
|
||||||
|
*
|
||||||
|
* Return: 0 on success.
|
||||||
|
*/
|
||||||
|
static int tascam_playback_prepare(struct snd_pcm_substream *substream) {
|
||||||
|
struct tascam_card *tascam = snd_pcm_substream_chip(substream);
|
||||||
|
|
||||||
|
tascam->driver_playback_pos = 0;
|
||||||
|
tascam->playback_frames_consumed = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_playback_pointer() - Returns the current playback pointer position.
|
||||||
|
* @substream: The ALSA PCM substream.
|
||||||
|
*
|
||||||
|
* This function returns the current position of the playback pointer within
|
||||||
|
* the ALSA ring buffer, in frames.
|
||||||
|
*
|
||||||
|
* Return: The current playback pointer position in frames.
|
||||||
|
*/
|
||||||
|
static snd_pcm_uframes_t
|
||||||
|
tascam_playback_pointer(struct snd_pcm_substream *substream) {
|
||||||
|
struct tascam_card *tascam = snd_pcm_substream_chip(substream);
|
||||||
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
u64 pos;
|
||||||
|
|
||||||
|
if (!atomic_read(&tascam->playback_active))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
guard(spinlock_irqsave)(&tascam->lock);
|
||||||
|
pos = tascam->playback_frames_consumed;
|
||||||
|
|
||||||
|
if (runtime->buffer_size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
u64 remainder = do_div(pos, runtime->buffer_size);
|
||||||
|
return runtime ? remainder : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tascam_playback_ops - ALSA PCM operations for playback.
|
||||||
|
*
|
||||||
|
* This structure defines the callback functions for playback stream operations,
|
||||||
|
* including open, close, ioctl, hardware parameters, hardware free, prepare,
|
||||||
|
* trigger, and pointer.
|
||||||
|
*/
|
||||||
|
const struct snd_pcm_ops tascam_playback_ops = {
|
||||||
|
.open = tascam_playback_open,
|
||||||
|
.close = tascam_playback_close,
|
||||||
|
.ioctl = snd_pcm_lib_ioctl,
|
||||||
|
.hw_params = tascam_pcm_hw_params,
|
||||||
|
.hw_free = tascam_pcm_hw_free,
|
||||||
|
.prepare = tascam_playback_prepare,
|
||||||
|
.trigger = tascam_pcm_trigger,
|
||||||
|
.pointer = tascam_playback_pointer,
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue