1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright (c) 2025 Šerif Rami <ramiserifpersia@gmail.com> 3 4 #include "us144mkii.h" 5 6 /** 7 * tascam_capture_open() - Opens the PCM capture substream. 8 * @substream: The ALSA PCM substream to open. 9 * 10 * This function sets the hardware parameters for the capture substream 11 * and stores a reference to the substream in the driver's private data. 12 * 13 * Return: 0 on success. 14 */ 15 static int tascam_capture_open(struct snd_pcm_substream *substream) 16 { 17 struct tascam_card *tascam = snd_pcm_substream_chip(substream); 18 19 substream->runtime->hw = tascam_pcm_hw; 20 tascam->capture_substream = substream; 21 atomic_set(&tascam->capture_active, 0); 22 23 return 0; 24 } 25 26 /** 27 * tascam_capture_close() - Closes the PCM capture substream. 28 * @substream: The ALSA PCM substream to close. 29 * 30 * This function clears the reference to the capture substream in the 31 * driver's private data. 32 * 33 * Return: 0 on success. 34 */ 35 static int tascam_capture_close(struct snd_pcm_substream *substream) 36 { 37 struct tascam_card *tascam = snd_pcm_substream_chip(substream); 38 39 tascam->capture_substream = NULL; 40 41 return 0; 42 } 43 44 /** 45 * tascam_capture_prepare() - Prepares the PCM capture substream for use. 46 * @substream: The ALSA PCM substream to prepare. 47 * 48 * This function initializes capture-related counters and ring buffer pointers. 49 * 50 * Return: 0 on success. 51 */ 52 static int tascam_capture_prepare(struct snd_pcm_substream *substream) 53 { 54 struct tascam_card *tascam = snd_pcm_substream_chip(substream); 55 56 tascam->driver_capture_pos = 0; 57 tascam->capture_frames_processed = 0; 58 tascam->last_capture_period_pos = 0; 59 tascam->capture_ring_buffer_read_ptr = 0; 60 tascam->capture_ring_buffer_write_ptr = 0; 61 62 return 0; 63 } 64 65 /** 66 * tascam_capture_pointer() - Returns the current capture pointer position. 67 * @substream: The ALSA PCM substream. 68 * 69 * This function returns the current position of the capture pointer within 70 * the ALSA ring buffer, in frames. 71 * 72 * Return: The current capture pointer position in frames. 73 */ 74 static snd_pcm_uframes_t 75 tascam_capture_pointer(struct snd_pcm_substream *substream) 76 { 77 struct tascam_card *tascam = snd_pcm_substream_chip(substream); 78 struct snd_pcm_runtime *runtime = substream->runtime; 79 u64 pos; 80 81 if (!atomic_read(&tascam->capture_active)) 82 return 0; 83 84 scoped_guard(spinlock_irqsave, &tascam->lock) { 85 pos = tascam->capture_frames_processed; 86 } 87 88 if (runtime->buffer_size == 0) 89 return 0; 90 91 return do_div(pos, runtime->buffer_size); 92 } 93 94 /** 95 * tascam_capture_ops - ALSA PCM operations for capture. 96 * 97 * This structure defines the callback functions for capture stream operations, 98 * including open, close, ioctl, hardware parameters, hardware free, prepare, 99 * trigger, and pointer. 100 */ 101 const struct snd_pcm_ops tascam_capture_ops = { 102 .open = tascam_capture_open, 103 .close = tascam_capture_close, 104 .ioctl = snd_pcm_lib_ioctl, 105 .hw_params = tascam_pcm_hw_params, 106 .hw_free = tascam_pcm_hw_free, 107 .prepare = tascam_capture_prepare, 108 .trigger = tascam_pcm_trigger, 109 .pointer = tascam_capture_pointer, 110 }; 111 112 /** 113 * decode_tascam_capture_block() - Decodes a raw 512-byte block from the device. 114 * @src_block: Pointer to the 512-byte raw source block. 115 * @dst_block: Pointer to the destination buffer for decoded audio frames. 116 * 117 * The device sends audio data in a complex, multiplexed format. This function 118 * demultiplexes the bits from the raw block into 8 frames of 4-channel, 119 * 24-bit audio (stored in 32-bit containers). 120 */ 121 static void decode_tascam_capture_block(const u8 *src_block, s32 *dst_block) 122 { 123 int frame, bit; 124 125 memset(dst_block, 0, 126 FRAMES_PER_DECODE_BLOCK * DECODED_CHANNELS_PER_FRAME * 127 DECODED_SAMPLE_SIZE); 128 129 for (frame = 0; frame < FRAMES_PER_DECODE_BLOCK; ++frame) { 130 const u8 *p_src_frame_base = src_block + frame * 64; 131 s32 *p_dst_frame = dst_block + frame * 4; 132 133 s32 ch[4] = { 0 }; 134 135 for (bit = 0; bit < 24; ++bit) { 136 u8 byte1 = p_src_frame_base[bit]; 137 u8 byte2 = p_src_frame_base[bit + 32]; 138 139 ch[0] = (ch[0] << 1) | (byte1 & 1); 140 ch[2] = (ch[2] << 1) | ((byte1 >> 1) & 1); 141 142 ch[1] = (ch[1] << 1) | (byte2 & 1); 143 ch[3] = (ch[3] << 1) | ((byte2 >> 1) & 1); 144 } 145 146 /* 147 * The result is a 24-bit sample. Shift left by 8 to align it to 148 * the most significant bits of a 32-bit integer (S32_LE format). 149 */ 150 p_dst_frame[0] = ch[0] << 8; 151 p_dst_frame[1] = ch[1] << 8; 152 p_dst_frame[2] = ch[2] << 8; 153 p_dst_frame[3] = ch[3] << 8; 154 } 155 } 156 157 void tascam_capture_work_handler(struct work_struct *work) 158 { 159 struct tascam_card *tascam = 160 container_of(work, struct tascam_card, capture_work); 161 struct snd_pcm_substream *substream = tascam->capture_substream; 162 struct snd_pcm_runtime *runtime; 163 u8 *raw_block = tascam->capture_decode_raw_block; 164 s32 *decoded_block = tascam->capture_decode_dst_block; 165 s32 *routed_block = tascam->capture_routing_buffer; 166 167 if (!substream || !substream->runtime) 168 return; 169 runtime = substream->runtime; 170 171 if (!raw_block || !decoded_block || !routed_block) { 172 dev_err(tascam->card->dev, 173 "Capture decode/routing buffers not allocated!\n"); 174 return; 175 } 176 177 while (atomic_read(&tascam->capture_active)) { 178 size_t write_ptr, read_ptr, available_data; 179 bool can_process; 180 181 scoped_guard(spinlock_irqsave, &tascam->lock) { 182 write_ptr = tascam->capture_ring_buffer_write_ptr; 183 read_ptr = tascam->capture_ring_buffer_read_ptr; 184 available_data = (write_ptr >= read_ptr) ? 185 (write_ptr - read_ptr) : 186 (CAPTURE_RING_BUFFER_SIZE - 187 read_ptr + write_ptr); 188 can_process = 189 (available_data >= RAW_BYTES_PER_DECODE_BLOCK); 190 191 if (can_process) { 192 size_t bytes_to_end = 193 CAPTURE_RING_BUFFER_SIZE - read_ptr; 194 if (bytes_to_end >= 195 RAW_BYTES_PER_DECODE_BLOCK) { 196 memcpy(raw_block, 197 tascam->capture_ring_buffer + 198 read_ptr, 199 RAW_BYTES_PER_DECODE_BLOCK); 200 } else { 201 memcpy(raw_block, 202 tascam->capture_ring_buffer + 203 read_ptr, 204 bytes_to_end); 205 memcpy(raw_block + bytes_to_end, 206 tascam->capture_ring_buffer, 207 RAW_BYTES_PER_DECODE_BLOCK - 208 bytes_to_end); 209 } 210 tascam->capture_ring_buffer_read_ptr = 211 (read_ptr + 212 RAW_BYTES_PER_DECODE_BLOCK) % 213 CAPTURE_RING_BUFFER_SIZE; 214 } 215 } 216 217 if (!can_process) 218 break; 219 220 decode_tascam_capture_block(raw_block, decoded_block); 221 process_capture_routing_us144mkii(tascam, decoded_block, 222 routed_block); 223 224 scoped_guard(spinlock_irqsave, &tascam->lock) { 225 if (atomic_read(&tascam->capture_active)) { 226 int f; 227 228 for (f = 0; f < FRAMES_PER_DECODE_BLOCK; ++f) { 229 u8 *dst_frame_start = 230 runtime->dma_area + 231 frames_to_bytes( 232 runtime, 233 tascam->driver_capture_pos); 234 s32 *routed_frame_start = 235 routed_block + 236 (f * NUM_CHANNELS); 237 int c; 238 239 for (c = 0; c < NUM_CHANNELS; c++) { 240 u8 *dst_channel = 241 dst_frame_start + 242 (c * BYTES_PER_SAMPLE); 243 s32 *src_channel_s32 = 244 routed_frame_start + c; 245 246 memcpy(dst_channel, 247 ((char *)src_channel_s32) + 248 1, 249 3); 250 } 251 252 tascam->driver_capture_pos = 253 (tascam->driver_capture_pos + 254 1) % 255 runtime->buffer_size; 256 } 257 } 258 } 259 } 260 } 261 262 void capture_urb_complete(struct urb *urb) 263 { 264 struct tascam_card *tascam = urb->context; 265 int ret; 266 267 if (urb->status) { 268 if (urb->status != -ENOENT && urb->status != -ECONNRESET && 269 urb->status != -ESHUTDOWN && urb->status != -ENODEV && 270 urb->status != -EPROTO) 271 dev_err_ratelimited(tascam->card->dev, 272 "Capture URB failed: %d\n", 273 urb->status); 274 goto out; 275 } 276 if (!tascam || !atomic_read(&tascam->capture_active)) 277 goto out; 278 279 if (urb->actual_length > 0) { 280 scoped_guard(spinlock_irqsave, &tascam->lock) { 281 size_t write_ptr = tascam->capture_ring_buffer_write_ptr; 282 size_t bytes_to_end = CAPTURE_RING_BUFFER_SIZE - write_ptr; 283 284 if (urb->actual_length > bytes_to_end) { 285 memcpy(tascam->capture_ring_buffer + write_ptr, 286 urb->transfer_buffer, bytes_to_end); 287 memcpy(tascam->capture_ring_buffer, 288 urb->transfer_buffer + bytes_to_end, 289 urb->actual_length - bytes_to_end); 290 } else { 291 memcpy(tascam->capture_ring_buffer + write_ptr, 292 urb->transfer_buffer, 293 urb->actual_length); 294 } 295 296 tascam->capture_ring_buffer_write_ptr = 297 (write_ptr + urb->actual_length) % 298 CAPTURE_RING_BUFFER_SIZE; 299 } 300 301 schedule_work(&tascam->capture_work); 302 } 303 304 usb_get_urb(urb); 305 usb_anchor_urb(urb, &tascam->capture_anchor); 306 ret = usb_submit_urb(urb, GFP_ATOMIC); 307 if (ret < 0) { 308 dev_err_ratelimited(tascam->card->dev, 309 "Failed to resubmit capture URB: %d\n", 310 ret); 311 usb_unanchor_urb(urb); 312 usb_put_urb(urb); 313 atomic_dec( 314 &tascam->active_urbs); /* Decrement on failed resubmission */ 315 } 316 out: 317 usb_put_urb(urb); 318 } 319 320