xref: /openbmc/linux/sound/firewire/isight.c (revision ca79522c)
1 /*
2  * Apple iSight audio driver
3  *
4  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5  * Licensed under the terms of the GNU General Public License, version 2.
6  */
7 
8 #include <asm/byteorder.h>
9 #include <linux/delay.h>
10 #include <linux/device.h>
11 #include <linux/firewire.h>
12 #include <linux/firewire-constants.h>
13 #include <linux/module.h>
14 #include <linux/mod_devicetable.h>
15 #include <linux/mutex.h>
16 #include <linux/string.h>
17 #include <sound/control.h>
18 #include <sound/core.h>
19 #include <sound/initval.h>
20 #include <sound/pcm.h>
21 #include <sound/tlv.h>
22 #include "lib.h"
23 #include "iso-resources.h"
24 #include "packets-buffer.h"
25 
26 #define OUI_APPLE		0x000a27
27 #define MODEL_APPLE_ISIGHT	0x000008
28 #define SW_ISIGHT_AUDIO		0x000010
29 
30 #define REG_AUDIO_ENABLE	0x000
31 #define  AUDIO_ENABLE		0x80000000
32 #define REG_DEF_AUDIO_GAIN	0x204
33 #define REG_GAIN_RAW_START	0x210
34 #define REG_GAIN_RAW_END	0x214
35 #define REG_GAIN_DB_START	0x218
36 #define REG_GAIN_DB_END		0x21c
37 #define REG_SAMPLE_RATE_INQUIRY	0x280
38 #define REG_ISO_TX_CONFIG	0x300
39 #define  SPEED_SHIFT		16
40 #define REG_SAMPLE_RATE		0x400
41 #define  RATE_48000		0x80000000
42 #define REG_GAIN		0x500
43 #define REG_MUTE		0x504
44 
45 #define MAX_FRAMES_PER_PACKET	475
46 
47 #define QUEUE_LENGTH		20
48 
49 struct isight {
50 	struct snd_card *card;
51 	struct fw_unit *unit;
52 	struct fw_device *device;
53 	u64 audio_base;
54 	struct snd_pcm_substream *pcm;
55 	struct mutex mutex;
56 	struct iso_packets_buffer buffer;
57 	struct fw_iso_resources resources;
58 	struct fw_iso_context *context;
59 	bool pcm_active;
60 	bool pcm_running;
61 	bool first_packet;
62 	int packet_index;
63 	u32 total_samples;
64 	unsigned int buffer_pointer;
65 	unsigned int period_counter;
66 	s32 gain_min, gain_max;
67 	unsigned int gain_tlv[4];
68 };
69 
70 struct audio_payload {
71 	__be32 sample_count;
72 	__be32 signature;
73 	__be32 sample_total;
74 	__be32 reserved;
75 	__be16 samples[2 * MAX_FRAMES_PER_PACKET];
76 };
77 
78 MODULE_DESCRIPTION("iSight audio driver");
79 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
80 MODULE_LICENSE("GPL v2");
81 
82 static struct fw_iso_packet audio_packet = {
83 	.payload_length = sizeof(struct audio_payload),
84 	.interrupt = 1,
85 	.header_length = 4,
86 };
87 
88 static void isight_update_pointers(struct isight *isight, unsigned int count)
89 {
90 	struct snd_pcm_runtime *runtime = isight->pcm->runtime;
91 	unsigned int ptr;
92 
93 	smp_wmb(); /* update buffer data before buffer pointer */
94 
95 	ptr = isight->buffer_pointer;
96 	ptr += count;
97 	if (ptr >= runtime->buffer_size)
98 		ptr -= runtime->buffer_size;
99 	ACCESS_ONCE(isight->buffer_pointer) = ptr;
100 
101 	isight->period_counter += count;
102 	if (isight->period_counter >= runtime->period_size) {
103 		isight->period_counter -= runtime->period_size;
104 		snd_pcm_period_elapsed(isight->pcm);
105 	}
106 }
107 
108 static void isight_samples(struct isight *isight,
109 			   const __be16 *samples, unsigned int count)
110 {
111 	struct snd_pcm_runtime *runtime;
112 	unsigned int count1;
113 
114 	if (!ACCESS_ONCE(isight->pcm_running))
115 		return;
116 
117 	runtime = isight->pcm->runtime;
118 	if (isight->buffer_pointer + count <= runtime->buffer_size) {
119 		memcpy(runtime->dma_area + isight->buffer_pointer * 4,
120 		       samples, count * 4);
121 	} else {
122 		count1 = runtime->buffer_size - isight->buffer_pointer;
123 		memcpy(runtime->dma_area + isight->buffer_pointer * 4,
124 		       samples, count1 * 4);
125 		samples += count1 * 2;
126 		memcpy(runtime->dma_area, samples, (count - count1) * 4);
127 	}
128 
129 	isight_update_pointers(isight, count);
130 }
131 
132 static void isight_pcm_abort(struct isight *isight)
133 {
134 	unsigned long flags;
135 
136 	if (ACCESS_ONCE(isight->pcm_active)) {
137 		snd_pcm_stream_lock_irqsave(isight->pcm, flags);
138 		if (snd_pcm_running(isight->pcm))
139 			snd_pcm_stop(isight->pcm, SNDRV_PCM_STATE_XRUN);
140 		snd_pcm_stream_unlock_irqrestore(isight->pcm, flags);
141 	}
142 }
143 
144 static void isight_dropped_samples(struct isight *isight, unsigned int total)
145 {
146 	struct snd_pcm_runtime *runtime;
147 	u32 dropped;
148 	unsigned int count1;
149 
150 	if (!ACCESS_ONCE(isight->pcm_running))
151 		return;
152 
153 	runtime = isight->pcm->runtime;
154 	dropped = total - isight->total_samples;
155 	if (dropped < runtime->buffer_size) {
156 		if (isight->buffer_pointer + dropped <= runtime->buffer_size) {
157 			memset(runtime->dma_area + isight->buffer_pointer * 4,
158 			       0, dropped * 4);
159 		} else {
160 			count1 = runtime->buffer_size - isight->buffer_pointer;
161 			memset(runtime->dma_area + isight->buffer_pointer * 4,
162 			       0, count1 * 4);
163 			memset(runtime->dma_area, 0, (dropped - count1) * 4);
164 		}
165 		isight_update_pointers(isight, dropped);
166 	} else {
167 		isight_pcm_abort(isight);
168 	}
169 }
170 
171 static void isight_packet(struct fw_iso_context *context, u32 cycle,
172 			  size_t header_length, void *header, void *data)
173 {
174 	struct isight *isight = data;
175 	const struct audio_payload *payload;
176 	unsigned int index, length, count, total;
177 	int err;
178 
179 	if (isight->packet_index < 0)
180 		return;
181 	index = isight->packet_index;
182 	payload = isight->buffer.packets[index].buffer;
183 	length = be32_to_cpup(header) >> 16;
184 
185 	if (likely(length >= 16 &&
186 		   payload->signature == cpu_to_be32(0x73676874/*"sght"*/))) {
187 		count = be32_to_cpu(payload->sample_count);
188 		if (likely(count <= (length - 16) / 4)) {
189 			total = be32_to_cpu(payload->sample_total);
190 			if (unlikely(total != isight->total_samples)) {
191 				if (!isight->first_packet)
192 					isight_dropped_samples(isight, total);
193 				isight->first_packet = false;
194 				isight->total_samples = total;
195 			}
196 
197 			isight_samples(isight, payload->samples, count);
198 			isight->total_samples += count;
199 		}
200 	}
201 
202 	err = fw_iso_context_queue(isight->context, &audio_packet,
203 				   &isight->buffer.iso_buffer,
204 				   isight->buffer.packets[index].offset);
205 	if (err < 0) {
206 		dev_err(&isight->unit->device, "queueing error: %d\n", err);
207 		isight_pcm_abort(isight);
208 		isight->packet_index = -1;
209 		return;
210 	}
211 	fw_iso_context_queue_flush(isight->context);
212 
213 	if (++index >= QUEUE_LENGTH)
214 		index = 0;
215 	isight->packet_index = index;
216 }
217 
218 static int isight_connect(struct isight *isight)
219 {
220 	int ch, err, rcode, errors = 0;
221 	__be32 value;
222 
223 retry_after_bus_reset:
224 	ch = fw_iso_resources_allocate(&isight->resources,
225 				       sizeof(struct audio_payload),
226 				       isight->device->max_speed);
227 	if (ch < 0) {
228 		err = ch;
229 		goto error;
230 	}
231 
232 	value = cpu_to_be32(ch | (isight->device->max_speed << SPEED_SHIFT));
233 	for (;;) {
234 		rcode = fw_run_transaction(
235 				isight->device->card,
236 				TCODE_WRITE_QUADLET_REQUEST,
237 				isight->device->node_id,
238 				isight->resources.generation,
239 				isight->device->max_speed,
240 				isight->audio_base + REG_ISO_TX_CONFIG,
241 				&value, 4);
242 		if (rcode == RCODE_COMPLETE) {
243 			return 0;
244 		} else if (rcode == RCODE_GENERATION) {
245 			fw_iso_resources_free(&isight->resources);
246 			goto retry_after_bus_reset;
247 		} else if (rcode_is_permanent_error(rcode) || ++errors >= 3) {
248 			err = -EIO;
249 			goto err_resources;
250 		}
251 		msleep(5);
252 	}
253 
254 err_resources:
255 	fw_iso_resources_free(&isight->resources);
256 error:
257 	return err;
258 }
259 
260 static int isight_open(struct snd_pcm_substream *substream)
261 {
262 	static const struct snd_pcm_hardware hardware = {
263 		.info = SNDRV_PCM_INFO_MMAP |
264 			SNDRV_PCM_INFO_MMAP_VALID |
265 			SNDRV_PCM_INFO_BATCH |
266 			SNDRV_PCM_INFO_INTERLEAVED |
267 			SNDRV_PCM_INFO_BLOCK_TRANSFER,
268 		.formats = SNDRV_PCM_FMTBIT_S16_BE,
269 		.rates = SNDRV_PCM_RATE_48000,
270 		.rate_min = 48000,
271 		.rate_max = 48000,
272 		.channels_min = 2,
273 		.channels_max = 2,
274 		.buffer_bytes_max = 4 * 1024 * 1024,
275 		.period_bytes_min = MAX_FRAMES_PER_PACKET * 4,
276 		.period_bytes_max = 1024 * 1024,
277 		.periods_min = 2,
278 		.periods_max = UINT_MAX,
279 	};
280 	struct isight *isight = substream->private_data;
281 
282 	substream->runtime->hw = hardware;
283 
284 	return iso_packets_buffer_init(&isight->buffer, isight->unit,
285 				       QUEUE_LENGTH,
286 				       sizeof(struct audio_payload),
287 				       DMA_FROM_DEVICE);
288 }
289 
290 static int isight_close(struct snd_pcm_substream *substream)
291 {
292 	struct isight *isight = substream->private_data;
293 
294 	iso_packets_buffer_destroy(&isight->buffer, isight->unit);
295 
296 	return 0;
297 }
298 
299 static int isight_hw_params(struct snd_pcm_substream *substream,
300 			    struct snd_pcm_hw_params *hw_params)
301 {
302 	struct isight *isight = substream->private_data;
303 	int err;
304 
305 	err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
306 					       params_buffer_bytes(hw_params));
307 	if (err < 0)
308 		return err;
309 
310 	ACCESS_ONCE(isight->pcm_active) = true;
311 
312 	return 0;
313 }
314 
315 static int reg_read(struct isight *isight, int offset, __be32 *value)
316 {
317 	return snd_fw_transaction(isight->unit, TCODE_READ_QUADLET_REQUEST,
318 				  isight->audio_base + offset, value, 4);
319 }
320 
321 static int reg_write(struct isight *isight, int offset, __be32 value)
322 {
323 	return snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST,
324 				  isight->audio_base + offset, &value, 4);
325 }
326 
327 static void isight_stop_streaming(struct isight *isight)
328 {
329 	if (!isight->context)
330 		return;
331 
332 	fw_iso_context_stop(isight->context);
333 	fw_iso_context_destroy(isight->context);
334 	isight->context = NULL;
335 	fw_iso_resources_free(&isight->resources);
336 	reg_write(isight, REG_AUDIO_ENABLE, 0);
337 }
338 
339 static int isight_hw_free(struct snd_pcm_substream *substream)
340 {
341 	struct isight *isight = substream->private_data;
342 
343 	ACCESS_ONCE(isight->pcm_active) = false;
344 
345 	mutex_lock(&isight->mutex);
346 	isight_stop_streaming(isight);
347 	mutex_unlock(&isight->mutex);
348 
349 	return snd_pcm_lib_free_vmalloc_buffer(substream);
350 }
351 
352 static int isight_start_streaming(struct isight *isight)
353 {
354 	unsigned int i;
355 	int err;
356 
357 	if (isight->context) {
358 		if (isight->packet_index < 0)
359 			isight_stop_streaming(isight);
360 		else
361 			return 0;
362 	}
363 
364 	err = reg_write(isight, REG_SAMPLE_RATE, cpu_to_be32(RATE_48000));
365 	if (err < 0)
366 		goto error;
367 
368 	err = isight_connect(isight);
369 	if (err < 0)
370 		goto error;
371 
372 	err = reg_write(isight, REG_AUDIO_ENABLE, cpu_to_be32(AUDIO_ENABLE));
373 	if (err < 0)
374 		goto err_resources;
375 
376 	isight->context = fw_iso_context_create(isight->device->card,
377 						FW_ISO_CONTEXT_RECEIVE,
378 						isight->resources.channel,
379 						isight->device->max_speed,
380 						4, isight_packet, isight);
381 	if (IS_ERR(isight->context)) {
382 		err = PTR_ERR(isight->context);
383 		isight->context = NULL;
384 		goto err_resources;
385 	}
386 
387 	for (i = 0; i < QUEUE_LENGTH; ++i) {
388 		err = fw_iso_context_queue(isight->context, &audio_packet,
389 					   &isight->buffer.iso_buffer,
390 					   isight->buffer.packets[i].offset);
391 		if (err < 0)
392 			goto err_context;
393 	}
394 
395 	isight->first_packet = true;
396 	isight->packet_index = 0;
397 
398 	err = fw_iso_context_start(isight->context, -1, 0,
399 				   FW_ISO_CONTEXT_MATCH_ALL_TAGS/*?*/);
400 	if (err < 0)
401 		goto err_context;
402 
403 	return 0;
404 
405 err_context:
406 	fw_iso_context_destroy(isight->context);
407 	isight->context = NULL;
408 err_resources:
409 	fw_iso_resources_free(&isight->resources);
410 	reg_write(isight, REG_AUDIO_ENABLE, 0);
411 error:
412 	return err;
413 }
414 
415 static int isight_prepare(struct snd_pcm_substream *substream)
416 {
417 	struct isight *isight = substream->private_data;
418 	int err;
419 
420 	isight->buffer_pointer = 0;
421 	isight->period_counter = 0;
422 
423 	mutex_lock(&isight->mutex);
424 	err = isight_start_streaming(isight);
425 	mutex_unlock(&isight->mutex);
426 
427 	return err;
428 }
429 
430 static int isight_trigger(struct snd_pcm_substream *substream, int cmd)
431 {
432 	struct isight *isight = substream->private_data;
433 
434 	switch (cmd) {
435 	case SNDRV_PCM_TRIGGER_START:
436 		ACCESS_ONCE(isight->pcm_running) = true;
437 		break;
438 	case SNDRV_PCM_TRIGGER_STOP:
439 		ACCESS_ONCE(isight->pcm_running) = false;
440 		break;
441 	default:
442 		return -EINVAL;
443 	}
444 	return 0;
445 }
446 
447 static snd_pcm_uframes_t isight_pointer(struct snd_pcm_substream *substream)
448 {
449 	struct isight *isight = substream->private_data;
450 
451 	return ACCESS_ONCE(isight->buffer_pointer);
452 }
453 
454 static int isight_create_pcm(struct isight *isight)
455 {
456 	static struct snd_pcm_ops ops = {
457 		.open      = isight_open,
458 		.close     = isight_close,
459 		.ioctl     = snd_pcm_lib_ioctl,
460 		.hw_params = isight_hw_params,
461 		.hw_free   = isight_hw_free,
462 		.prepare   = isight_prepare,
463 		.trigger   = isight_trigger,
464 		.pointer   = isight_pointer,
465 		.page      = snd_pcm_lib_get_vmalloc_page,
466 		.mmap      = snd_pcm_lib_mmap_vmalloc,
467 	};
468 	struct snd_pcm *pcm;
469 	int err;
470 
471 	err = snd_pcm_new(isight->card, "iSight", 0, 0, 1, &pcm);
472 	if (err < 0)
473 		return err;
474 	pcm->private_data = isight;
475 	strcpy(pcm->name, "iSight");
476 	isight->pcm = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
477 	isight->pcm->ops = &ops;
478 
479 	return 0;
480 }
481 
482 static int isight_gain_info(struct snd_kcontrol *ctl,
483 			    struct snd_ctl_elem_info *info)
484 {
485 	struct isight *isight = ctl->private_data;
486 
487 	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
488 	info->count = 1;
489 	info->value.integer.min = isight->gain_min;
490 	info->value.integer.max = isight->gain_max;
491 
492 	return 0;
493 }
494 
495 static int isight_gain_get(struct snd_kcontrol *ctl,
496 			   struct snd_ctl_elem_value *value)
497 {
498 	struct isight *isight = ctl->private_data;
499 	__be32 gain;
500 	int err;
501 
502 	err = reg_read(isight, REG_GAIN, &gain);
503 	if (err < 0)
504 		return err;
505 
506 	value->value.integer.value[0] = (s32)be32_to_cpu(gain);
507 
508 	return 0;
509 }
510 
511 static int isight_gain_put(struct snd_kcontrol *ctl,
512 			   struct snd_ctl_elem_value *value)
513 {
514 	struct isight *isight = ctl->private_data;
515 
516 	if (value->value.integer.value[0] < isight->gain_min ||
517 	    value->value.integer.value[0] > isight->gain_max)
518 		return -EINVAL;
519 
520 	return reg_write(isight, REG_GAIN,
521 			 cpu_to_be32(value->value.integer.value[0]));
522 }
523 
524 static int isight_mute_get(struct snd_kcontrol *ctl,
525 			   struct snd_ctl_elem_value *value)
526 {
527 	struct isight *isight = ctl->private_data;
528 	__be32 mute;
529 	int err;
530 
531 	err = reg_read(isight, REG_MUTE, &mute);
532 	if (err < 0)
533 		return err;
534 
535 	value->value.integer.value[0] = !mute;
536 
537 	return 0;
538 }
539 
540 static int isight_mute_put(struct snd_kcontrol *ctl,
541 			   struct snd_ctl_elem_value *value)
542 {
543 	struct isight *isight = ctl->private_data;
544 
545 	return reg_write(isight, REG_MUTE,
546 			 (__force __be32)!value->value.integer.value[0]);
547 }
548 
549 static int isight_create_mixer(struct isight *isight)
550 {
551 	static const struct snd_kcontrol_new gain_control = {
552 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
553 		.name = "Mic Capture Volume",
554 		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
555 			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
556 		.info = isight_gain_info,
557 		.get = isight_gain_get,
558 		.put = isight_gain_put,
559 	};
560 	static const struct snd_kcontrol_new mute_control = {
561 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
562 		.name = "Mic Capture Switch",
563 		.info = snd_ctl_boolean_mono_info,
564 		.get = isight_mute_get,
565 		.put = isight_mute_put,
566 	};
567 	__be32 value;
568 	struct snd_kcontrol *ctl;
569 	int err;
570 
571 	err = reg_read(isight, REG_GAIN_RAW_START, &value);
572 	if (err < 0)
573 		return err;
574 	isight->gain_min = be32_to_cpu(value);
575 
576 	err = reg_read(isight, REG_GAIN_RAW_END, &value);
577 	if (err < 0)
578 		return err;
579 	isight->gain_max = be32_to_cpu(value);
580 
581 	isight->gain_tlv[0] = SNDRV_CTL_TLVT_DB_MINMAX;
582 	isight->gain_tlv[1] = 2 * sizeof(unsigned int);
583 
584 	err = reg_read(isight, REG_GAIN_DB_START, &value);
585 	if (err < 0)
586 		return err;
587 	isight->gain_tlv[2] = (s32)be32_to_cpu(value) * 100;
588 
589 	err = reg_read(isight, REG_GAIN_DB_END, &value);
590 	if (err < 0)
591 		return err;
592 	isight->gain_tlv[3] = (s32)be32_to_cpu(value) * 100;
593 
594 	ctl = snd_ctl_new1(&gain_control, isight);
595 	if (ctl)
596 		ctl->tlv.p = isight->gain_tlv;
597 	err = snd_ctl_add(isight->card, ctl);
598 	if (err < 0)
599 		return err;
600 
601 	err = snd_ctl_add(isight->card, snd_ctl_new1(&mute_control, isight));
602 	if (err < 0)
603 		return err;
604 
605 	return 0;
606 }
607 
608 static void isight_card_free(struct snd_card *card)
609 {
610 	struct isight *isight = card->private_data;
611 
612 	fw_iso_resources_destroy(&isight->resources);
613 	fw_unit_put(isight->unit);
614 	mutex_destroy(&isight->mutex);
615 }
616 
617 static u64 get_unit_base(struct fw_unit *unit)
618 {
619 	struct fw_csr_iterator i;
620 	int key, value;
621 
622 	fw_csr_iterator_init(&i, unit->directory);
623 	while (fw_csr_iterator_next(&i, &key, &value))
624 		if (key == CSR_OFFSET)
625 			return CSR_REGISTER_BASE + value * 4;
626 	return 0;
627 }
628 
629 static int isight_probe(struct device *unit_dev)
630 {
631 	struct fw_unit *unit = fw_unit(unit_dev);
632 	struct fw_device *fw_dev = fw_parent_device(unit);
633 	struct snd_card *card;
634 	struct isight *isight;
635 	int err;
636 
637 	err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*isight), &card);
638 	if (err < 0)
639 		return err;
640 	snd_card_set_dev(card, unit_dev);
641 
642 	isight = card->private_data;
643 	isight->card = card;
644 	mutex_init(&isight->mutex);
645 	isight->unit = fw_unit_get(unit);
646 	isight->device = fw_dev;
647 	isight->audio_base = get_unit_base(unit);
648 	if (!isight->audio_base) {
649 		dev_err(&unit->device, "audio unit base not found\n");
650 		err = -ENXIO;
651 		goto err_unit;
652 	}
653 	fw_iso_resources_init(&isight->resources, unit);
654 
655 	card->private_free = isight_card_free;
656 
657 	strcpy(card->driver, "iSight");
658 	strcpy(card->shortname, "Apple iSight");
659 	snprintf(card->longname, sizeof(card->longname),
660 		 "Apple iSight (GUID %08x%08x) at %s, S%d",
661 		 fw_dev->config_rom[3], fw_dev->config_rom[4],
662 		 dev_name(&unit->device), 100 << fw_dev->max_speed);
663 	strcpy(card->mixername, "iSight");
664 
665 	err = isight_create_pcm(isight);
666 	if (err < 0)
667 		goto error;
668 
669 	err = isight_create_mixer(isight);
670 	if (err < 0)
671 		goto error;
672 
673 	err = snd_card_register(card);
674 	if (err < 0)
675 		goto error;
676 
677 	dev_set_drvdata(unit_dev, isight);
678 
679 	return 0;
680 
681 err_unit:
682 	fw_unit_put(isight->unit);
683 	mutex_destroy(&isight->mutex);
684 error:
685 	snd_card_free(card);
686 	return err;
687 }
688 
689 static int isight_remove(struct device *dev)
690 {
691 	struct isight *isight = dev_get_drvdata(dev);
692 
693 	isight_pcm_abort(isight);
694 
695 	snd_card_disconnect(isight->card);
696 
697 	mutex_lock(&isight->mutex);
698 	isight_stop_streaming(isight);
699 	mutex_unlock(&isight->mutex);
700 
701 	snd_card_free_when_closed(isight->card);
702 
703 	return 0;
704 }
705 
706 static void isight_bus_reset(struct fw_unit *unit)
707 {
708 	struct isight *isight = dev_get_drvdata(&unit->device);
709 
710 	if (fw_iso_resources_update(&isight->resources) < 0) {
711 		isight_pcm_abort(isight);
712 
713 		mutex_lock(&isight->mutex);
714 		isight_stop_streaming(isight);
715 		mutex_unlock(&isight->mutex);
716 	}
717 }
718 
719 static const struct ieee1394_device_id isight_id_table[] = {
720 	{
721 		.match_flags  = IEEE1394_MATCH_SPECIFIER_ID |
722 				IEEE1394_MATCH_VERSION,
723 		.specifier_id = OUI_APPLE,
724 		.version      = SW_ISIGHT_AUDIO,
725 	},
726 	{ }
727 };
728 MODULE_DEVICE_TABLE(ieee1394, isight_id_table);
729 
730 static struct fw_driver isight_driver = {
731 	.driver   = {
732 		.owner	= THIS_MODULE,
733 		.name	= KBUILD_MODNAME,
734 		.bus	= &fw_bus_type,
735 		.probe	= isight_probe,
736 		.remove	= isight_remove,
737 	},
738 	.update   = isight_bus_reset,
739 	.id_table = isight_id_table,
740 };
741 
742 static int __init alsa_isight_init(void)
743 {
744 	return driver_register(&isight_driver.driver);
745 }
746 
747 static void __exit alsa_isight_exit(void)
748 {
749 	driver_unregister(&isight_driver.driver);
750 }
751 
752 module_init(alsa_isight_init);
753 module_exit(alsa_isight_exit);
754