xref: /linux/sound/usb/usx2y/us144mkii_pcm.c (revision 05a54fa773284d1a7923cdfdd8f0c8dabb98bd26)
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  * fpo_init_pattern() - Generates a packet distribution pattern.
8  * @size: The number of elements in the pattern array (e.g., 8).
9  * @pattern_array: Pointer to the array to be populated.
10  * @initial_value: The base value to initialize each element with.
11  * @target_sum: The desired sum of all elements in the final array.
12  *
13  * This function initializes an array with a base value and then iteratively
14  * adjusts the elements to match a target sum, distributing the difference
15  * as evenly as possible.
16  */
17 static void fpo_init_pattern(unsigned int size, unsigned int *pattern_array,
18 	unsigned int initial_value, int target_sum)
19 {
20 	int diff, i;
21 
22 	if (!size)
23 		return;
24 
25 	for (i = 0; i < size; ++i)
26 		pattern_array[i] = initial_value;
27 
28 	diff = target_sum - (size * initial_value);
29 	for (i = 0; i < abs(diff); ++i) {
30 		if (diff > 0)
31 			pattern_array[i]++;
32 		else
33 			pattern_array[i]--;
34 	}
35 }
36 
37 const struct snd_pcm_hardware tascam_pcm_hw = {
38 	.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
39 		 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID |
40 		 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
41 	.formats = SNDRV_PCM_FMTBIT_S24_3LE,
42 	.rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
43 		  SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
44 	.rate_min = 44100,
45 	.rate_max = 96000,
46 	.channels_min = NUM_CHANNELS,
47 	.channels_max = NUM_CHANNELS,
48 	.buffer_bytes_max = 1024 * 1024,
49 	.period_bytes_min = 48 * BYTES_PER_FRAME,
50 	.period_bytes_max = 1024 * BYTES_PER_FRAME,
51 	.periods_min = 2,
52 	.periods_max = 1024,
53 };
54 
55 void process_playback_routing_us144mkii(struct tascam_card *tascam,
56 					const u8 *src_buffer, u8 *dst_buffer,
57 					size_t frames)
58 {
59 	size_t f;
60 	const u8 *src_12, *src_34;
61 	u8 *dst_line, *dst_digital;
62 
63 	for (f = 0; f < frames; ++f) {
64 		src_12 = src_buffer + f * BYTES_PER_FRAME;
65 		src_34 = src_12 + (2 * BYTES_PER_SAMPLE);
66 		dst_line = dst_buffer + f * BYTES_PER_FRAME;
67 		dst_digital = dst_line + (2 * BYTES_PER_SAMPLE);
68 
69 		/* LINE OUTPUTS (ch1/2 on device) */
70 		if (tascam->line_out_source == 0) /* "ch1 and ch2" */
71 			memcpy(dst_line, src_12, 2 * BYTES_PER_SAMPLE);
72 		else /* "ch3 and ch4" */
73 			memcpy(dst_line, src_34, 2 * BYTES_PER_SAMPLE);
74 
75 		/* DIGITAL OUTPUTS (ch3/4 on device) */
76 		if (tascam->digital_out_source == 0) /* "ch1 and ch2" */
77 			memcpy(dst_digital, src_12, 2 * BYTES_PER_SAMPLE);
78 		else /* "ch3 and ch4" */
79 			memcpy(dst_digital, src_34, 2 * BYTES_PER_SAMPLE);
80 	}
81 }
82 
83 void process_capture_routing_us144mkii(struct tascam_card *tascam,
84 				       const s32 *decoded_block,
85 				       s32 *routed_block)
86 {
87 	int f;
88 	const s32 *src_frame;
89 	s32 *dst_frame;
90 
91 	for (f = 0; f < FRAMES_PER_DECODE_BLOCK; f++) {
92 		src_frame = decoded_block + (f * DECODED_CHANNELS_PER_FRAME);
93 		dst_frame = routed_block + (f * DECODED_CHANNELS_PER_FRAME);
94 
95 		/* ch1 and ch2 Source */
96 		if (tascam->capture_12_source == 0) { /* analog inputs */
97 			dst_frame[0] = src_frame[0]; /* Analog L */
98 			dst_frame[1] = src_frame[1]; /* Analog R */
99 		} else { /* digital inputs */
100 			dst_frame[0] = src_frame[2]; /* Digital L */
101 			dst_frame[1] = src_frame[3]; /* Digital R */
102 		}
103 
104 		/* ch3 and ch4 Source */
105 		if (tascam->capture_34_source == 0) { /* analog inputs */
106 			dst_frame[2] = src_frame[0]; /* Analog L (Duplicate) */
107 			dst_frame[3] = src_frame[1]; /* Analog R (Duplicate) */
108 		} else { /* digital inputs */
109 			dst_frame[2] = src_frame[2]; /* Digital L */
110 			dst_frame[3] = src_frame[3]; /* Digital R */
111 		}
112 	}
113 }
114 
115 int us144mkii_configure_device_for_rate(struct tascam_card *tascam, int rate)
116 {
117 	struct usb_device *dev = tascam->dev;
118 	u8 *rate_payload_buf __free(kfree) = NULL;
119 	u16 rate_vendor_wValue;
120 	int err = 0;
121 	const u8 *current_payload_src;
122 
123 	static const u8 payload_44100[] = { 0x44, 0xac, 0x00 };
124 	static const u8 payload_48000[] = { 0x80, 0xbb, 0x00 };
125 	static const u8 payload_88200[] = { 0x88, 0x58, 0x01 };
126 	static const u8 payload_96000[] = { 0x00, 0x77, 0x01 };
127 
128 	switch (rate) {
129 	case 44100:
130 		current_payload_src = payload_44100;
131 		rate_vendor_wValue = REG_ADDR_RATE_44100;
132 		break;
133 	case 48000:
134 		current_payload_src = payload_48000;
135 		rate_vendor_wValue = REG_ADDR_RATE_48000;
136 		break;
137 	case 88200:
138 		current_payload_src = payload_88200;
139 		rate_vendor_wValue = REG_ADDR_RATE_88200;
140 		break;
141 	case 96000:
142 		current_payload_src = payload_96000;
143 		rate_vendor_wValue = REG_ADDR_RATE_96000;
144 		break;
145 	default:
146 		dev_err(&dev->dev,
147 			"Unsupported sample rate %d for configuration\n", rate);
148 		return -EINVAL;
149 	}
150 
151 	rate_payload_buf = kmemdup(current_payload_src, 3, GFP_KERNEL);
152 	if (!rate_payload_buf)
153 		return -ENOMEM;
154 
155 	dev_info(&dev->dev, "Configuring device for %d Hz\n", rate);
156 
157 	err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
158 			      VENDOR_REQ_MODE_CONTROL, RT_H2D_VENDOR_DEV,
159 			      MODE_VAL_CONFIG, 0x0000, NULL, 0,
160 			      USB_CTRL_TIMEOUT_MS);
161 	if (err < 0)
162 		goto fail;
163 	err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
164 			      RT_H2D_CLASS_EP, UAC_SAMPLING_FREQ_CONTROL,
165 			      EP_AUDIO_IN, rate_payload_buf, 3,
166 			      USB_CTRL_TIMEOUT_MS);
167 	if (err < 0)
168 		goto fail;
169 	err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
170 			      RT_H2D_CLASS_EP, UAC_SAMPLING_FREQ_CONTROL,
171 			      EP_AUDIO_OUT, rate_payload_buf, 3,
172 			      USB_CTRL_TIMEOUT_MS);
173 	if (err < 0)
174 		goto fail;
175 	err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
176 			      VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV,
177 			      REG_ADDR_UNKNOWN_0D, REG_VAL_ENABLE, NULL, 0,
178 			      USB_CTRL_TIMEOUT_MS);
179 	if (err < 0)
180 		goto fail;
181 	err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
182 			      VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV,
183 			      REG_ADDR_UNKNOWN_0E, REG_VAL_ENABLE, NULL, 0,
184 			      USB_CTRL_TIMEOUT_MS);
185 	if (err < 0)
186 		goto fail;
187 	err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
188 			      VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV,
189 			      REG_ADDR_UNKNOWN_0F, REG_VAL_ENABLE, NULL, 0,
190 			      USB_CTRL_TIMEOUT_MS);
191 	if (err < 0)
192 		goto fail;
193 	err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
194 			      VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV,
195 			      rate_vendor_wValue, REG_VAL_ENABLE, NULL, 0,
196 			      USB_CTRL_TIMEOUT_MS);
197 	if (err < 0)
198 		goto fail;
199 	err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
200 			      VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV,
201 			      REG_ADDR_UNKNOWN_11, REG_VAL_ENABLE, NULL, 0,
202 			      USB_CTRL_TIMEOUT_MS);
203 	if (err < 0)
204 		goto fail;
205 	err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
206 			      VENDOR_REQ_MODE_CONTROL, RT_H2D_VENDOR_DEV,
207 			      MODE_VAL_STREAM_START, 0x0000, NULL, 0,
208 			      USB_CTRL_TIMEOUT_MS);
209 	if (err < 0)
210 		goto fail;
211 	return 0;
212 
213 fail:
214 	dev_err(&dev->dev,
215 		"Device configuration failed at rate %d with error %d\n", rate,
216 		err);
217 	return err;
218 }
219 
220 int tascam_pcm_hw_params(struct snd_pcm_substream *substream,
221 					 struct snd_pcm_hw_params *params)
222 {
223 	struct tascam_card *tascam = snd_pcm_substream_chip(substream);
224 	int err;
225 	unsigned int rate = params_rate(params);
226 
227 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
228 		tascam->fpo.sample_rate_khz = rate / 1000;
229 		tascam->fpo.base_feedback_value = tascam->fpo.sample_rate_khz;
230 		tascam->fpo.feedback_offset = 2;
231 		tascam->fpo.current_index = 0;
232 		tascam->fpo.previous_index = 0;
233 		tascam->fpo.sync_locked = false;
234 
235 		unsigned int initial_value = tascam->fpo.sample_rate_khz / 8;
236 
237 		for (int i = 0; i < 5; i++) {
238 			int target_sum = tascam->fpo.sample_rate_khz -
239 					 tascam->fpo.feedback_offset + i;
240 			fpo_init_pattern(8, tascam->fpo.full_frame_patterns[i],
241 					       initial_value, target_sum);
242 		}
243 	}
244 
245 	if (tascam->current_rate != rate) {
246 		err = us144mkii_configure_device_for_rate(tascam, rate);
247 		if (err < 0) {
248 			tascam->current_rate = 0;
249 			return err;
250 		}
251 		tascam->current_rate = rate;
252 	}
253 
254 	return 0;
255 }
256 
257 int tascam_pcm_hw_free(struct snd_pcm_substream *substream)
258 {
259 	return 0;
260 }
261 
262 int tascam_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
263 {
264 	struct tascam_card *tascam = snd_pcm_substream_chip(substream);
265 	int err = 0;
266 	int i;
267 	bool do_start = false;
268 	bool do_stop = false;
269 
270 	scoped_guard(spinlock_irqsave, &tascam->lock) {
271 		switch (cmd) {
272 		case SNDRV_PCM_TRIGGER_START:
273 		case SNDRV_PCM_TRIGGER_RESUME:
274 			if (!atomic_read(&tascam->playback_active)) {
275 				atomic_set(&tascam->playback_active, 1);
276 				atomic_set(&tascam->capture_active, 1);
277 				do_start = true;
278 			}
279 			break;
280 		case SNDRV_PCM_TRIGGER_STOP:
281 		case SNDRV_PCM_TRIGGER_SUSPEND:
282 		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
283 			if (atomic_read(&tascam->playback_active)) {
284 				atomic_set(&tascam->playback_active, 0);
285 				atomic_set(&tascam->capture_active, 0);
286 				do_stop = true;
287 			}
288 			break;
289 		default:
290 			err = -EINVAL;
291 			break;
292 		}
293 	}
294 
295 	if (do_start) {
296 		if (atomic_read(&tascam->active_urbs) > 0) {
297 			dev_warn(tascam->card->dev,
298 				 "Cannot start, URBs still active.\n");
299 			return -EAGAIN;
300 		}
301 
302 		for (i = 0; i < NUM_FEEDBACK_URBS; i++) {
303 			usb_get_urb(tascam->feedback_urbs[i]);
304 			usb_anchor_urb(tascam->feedback_urbs[i],
305 					       &tascam->feedback_anchor);
306 			err = usb_submit_urb(tascam->feedback_urbs[i],
307 						     GFP_ATOMIC);
308 			if (err < 0) {
309 				usb_unanchor_urb(tascam->feedback_urbs[i]);
310 				usb_put_urb(tascam->feedback_urbs[i]);
311 				atomic_dec(&tascam->active_urbs);
312 				goto start_rollback;
313 			}
314 			atomic_inc(&tascam->active_urbs);
315 		}
316 		for (i = 0; i < NUM_PLAYBACK_URBS; i++) {
317 			usb_get_urb(tascam->playback_urbs[i]);
318 			usb_anchor_urb(tascam->playback_urbs[i],
319 					       &tascam->playback_anchor);
320 			err = usb_submit_urb(tascam->playback_urbs[i],
321 						     GFP_ATOMIC);
322 			if (err < 0) {
323 				usb_unanchor_urb(tascam->playback_urbs[i]);
324 				usb_put_urb(tascam->playback_urbs[i]);
325 				atomic_dec(&tascam->active_urbs);
326 				goto start_rollback;
327 			}
328 			atomic_inc(&tascam->active_urbs);
329 		}
330 		for (i = 0; i < NUM_CAPTURE_URBS; i++) {
331 			usb_get_urb(tascam->capture_urbs[i]);
332 			usb_anchor_urb(tascam->capture_urbs[i],
333 				       &tascam->capture_anchor);
334 			err = usb_submit_urb(tascam->capture_urbs[i],
335 					     GFP_ATOMIC);
336 			if (err < 0) {
337 				usb_unanchor_urb(tascam->capture_urbs[i]);
338 				usb_put_urb(tascam->capture_urbs[i]);
339 				atomic_dec(&tascam->active_urbs);
340 				goto start_rollback;
341 			}
342 			atomic_inc(&tascam->active_urbs);
343 		}
344 
345 		return 0;
346 start_rollback:
347 		dev_err(tascam->card->dev,
348 			"Failed to submit URBs to start stream: %d\n", err);
349 		do_stop = true;
350 	}
351 
352 	if (do_stop)
353 		schedule_work(&tascam->stop_work);
354 
355 	return err;
356 }
357 
358 int tascam_init_pcm(struct snd_pcm *pcm)
359 {
360 	struct tascam_card *tascam = pcm->private_data;
361 
362 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &tascam_playback_ops);
363 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &tascam_capture_ops);
364 
365 	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
366 				       tascam->dev->dev.parent, 64 * 1024,
367 				       tascam_pcm_hw.buffer_bytes_max);
368 
369 	return 0;
370 }
371