usr/src/uts/common/io/audio/drv/audiosolo/audiosolo.c
changeset 11936 54dc8a89ba0d
parent 11385 ede182582de2
equal deleted inserted replaced
11935:538c866aaac6 11936:54dc8a89ba0d
    22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    23  * SUCH DAMAGE.
    23  * SUCH DAMAGE.
    24  */
    24  */
    25 
    25 
    26 /*
    26 /*
    27  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
    27  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
    28  * Use is subject to license terms.
    28  * Use is subject to license terms.
    29  */
    29  */
    30 
    30 
    31 /*
    31 /*
    32  * Copyright (C) 4Front Technologies 1996-2008.
    32  * Copyright (C) 4Front Technologies 1996-2008.
    99 };
    99 };
   100 
   100 
   101 
   101 
   102 /*
   102 /*
   103  * For the sake of simplicity, this driver fixes a few parameters with
   103  * For the sake of simplicity, this driver fixes a few parameters with
   104  * constants.  If you want these values to be tunable, upgrade to a
   104  * constants.
   105  * nicer and newer device.  This is all tuned for 100 Hz (10
       
   106  * millisecs) latency.
       
   107  */
   105  */
   108 #define	SOLO_RATE	48000
   106 #define	SOLO_RATE	48000
   109 #define	SOLO_INTRS	100
   107 #define	SOLO_FRAGFR	1024
   110 #define	SOLO_FRAGFR	(SOLO_RATE / SOLO_INTRS)
   108 #define	SOLO_NFRAGS	2
   111 #define	SOLO_NFRAGS	8
       
   112 #define	SOLO_NCHAN	2
   109 #define	SOLO_NCHAN	2
   113 #define	SOLO_SAMPSZ	2
   110 #define	SOLO_SAMPSZ	2
   114 #define	SOLO_FRAGSZ	(SOLO_FRAGFR * (SOLO_NCHAN * SOLO_SAMPSZ))
   111 #define	SOLO_FRAGSZ	(SOLO_FRAGFR * (SOLO_NCHAN * SOLO_SAMPSZ))
   115 #define	SOLO_BUFFR	(SOLO_NFRAGS * SOLO_FRAGFR)
   112 #define	SOLO_BUFFR	(SOLO_NFRAGS * SOLO_FRAGFR)
   116 #define	SOLO_BUFSZ	(SOLO_NFRAGS * SOLO_FRAGSZ)
   113 #define	SOLO_BUFSZ	(SOLO_NFRAGS * SOLO_FRAGSZ)
   145 	ddi_acc_handle_t	acch;
   142 	ddi_acc_handle_t	acch;
   146 	caddr_t			kaddr;
   143 	caddr_t			kaddr;
   147 	uint32_t		paddr;
   144 	uint32_t		paddr;
   148 
   145 
   149 	bool			started;
   146 	bool			started;
       
   147 	bool			trigger;
   150 	uint64_t		count;
   148 	uint64_t		count;
   151 	uint16_t		offset;
   149 	uint16_t		offset;
   152 	int			syncdir;
   150 	int			syncdir;
   153 	int			format;
   151 	int			format;
   154 	bool			swapped;
   152 	bool			swapped;
   338 
   336 
   339 static uint_t
   337 static uint_t
   340 solo_intr(caddr_t arg1, caddr_t arg2)
   338 solo_intr(caddr_t arg1, caddr_t arg2)
   341 {
   339 {
   342 	solo_dev_t	*dev = (void *)arg1;
   340 	solo_dev_t	*dev = (void *)arg1;
   343 	audio_engine_t	*prod = NULL;
       
   344 	audio_engine_t	*cons = NULL;
       
   345 	uint8_t		status;
   341 	uint8_t		status;
   346 	uint_t		rv = DDI_INTR_UNCLAIMED;
   342 	uint_t		rv = DDI_INTR_UNCLAIMED;
   347 
   343 
   348 	_NOTE(ARGUNUSED(arg2));
   344 	_NOTE(ARGUNUSED(arg2));
   349 
   345 
   355 	}
   351 	}
   356 
   352 
   357 	status = PORT_RD8(dev->io, 0x7);
   353 	status = PORT_RD8(dev->io, 0x7);
   358 	if (status & 0x20) {
   354 	if (status & 0x20) {
   359 		rv = DDI_INTR_CLAIMED;
   355 		rv = DDI_INTR_CLAIMED;
   360 		cons = dev->play.engine;
       
   361 		/* ack the interrupt */
   356 		/* ack the interrupt */
   362 		solo_setmixer(dev, 0x7a, solo_getmixer(dev, 0x7a) & ~0x80);
   357 		solo_setmixer(dev, 0x7a, solo_getmixer(dev, 0x7a) & ~0x80);
   363 	}
   358 	}
   364 
   359 
   365 	if (status & 0x10) {
   360 	if (status & 0x10) {
   366 		rv = DDI_INTR_CLAIMED;
   361 		rv = DDI_INTR_CLAIMED;
   367 		prod = dev->rec.engine;
       
   368 		/* ack the interrupt */
   362 		/* ack the interrupt */
   369 		(void) PORT_RD8(dev->sb, 0xe);
   363 		(void) PORT_RD8(dev->sb, 0xe);
   370 	}
   364 	}
   371 	mutex_exit(&dev->mutex);
   365 	mutex_exit(&dev->mutex);
   372 
       
   373 	if (cons) {
       
   374 		audio_engine_consume(cons);
       
   375 	}
       
   376 
       
   377 	if (prod) {
       
   378 		audio_engine_produce(prod);
       
   379 	}
       
   380 
   366 
   381 	return (rv);
   367 	return (rv);
   382 }
   368 }
   383 
   369 
   384 static uint8_t
   370 static uint8_t
   486 	if ((val & ~INSRCS) != 0)
   472 	if ((val & ~INSRCS) != 0)
   487 		return (EINVAL);
   473 		return (EINVAL);
   488 
   474 
   489 	mutex_enter(&dev->mutex);
   475 	mutex_enter(&dev->mutex);
   490 	pc->val = val;
   476 	pc->val = val;
   491 	if (!dev->suspended)
   477 	solo_configure_mixer(dev);
   492 		solo_configure_mixer(dev);
       
   493 	mutex_exit(&dev->mutex);
   478 	mutex_exit(&dev->mutex);
   494 	return (0);
   479 	return (0);
   495 }
   480 }
   496 
   481 
   497 static int
   482 static int
   506 
   491 
   507 	val = (val & 0xff) | ((val & 0xff) << 8);
   492 	val = (val & 0xff) | ((val & 0xff) << 8);
   508 
   493 
   509 	mutex_enter(&dev->mutex);
   494 	mutex_enter(&dev->mutex);
   510 	pc->val = val;
   495 	pc->val = val;
   511 	if (!dev->suspended)
   496 	solo_configure_mixer(dev);
   512 		solo_configure_mixer(dev);
       
   513 	mutex_exit(&dev->mutex);
   497 	mutex_exit(&dev->mutex);
   514 	return (0);
   498 	return (0);
   515 }
   499 }
   516 
   500 
   517 static int
   501 static int
   528 	if ((l > 100) || (r > 100))
   512 	if ((l > 100) || (r > 100))
   529 		return (EINVAL);
   513 		return (EINVAL);
   530 
   514 
   531 	mutex_enter(&dev->mutex);
   515 	mutex_enter(&dev->mutex);
   532 	pc->val = val;
   516 	pc->val = val;
   533 	if (!dev->suspended)
   517 	solo_configure_mixer(dev);
   534 		solo_configure_mixer(dev);
       
   535 	mutex_exit(&dev->mutex);
   518 	mutex_exit(&dev->mutex);
   536 	return (0);
   519 	return (0);
   537 }
   520 }
   538 
   521 
   539 static int
   522 static int
   542 	solo_ctrl_t	*pc = arg;
   525 	solo_ctrl_t	*pc = arg;
   543 	solo_dev_t	*dev = pc->dev;
   526 	solo_dev_t	*dev = pc->dev;
   544 
   527 
   545 	mutex_enter(&dev->mutex);
   528 	mutex_enter(&dev->mutex);
   546 	pc->val = val;
   529 	pc->val = val;
   547 	if (!dev->suspended)
   530 	solo_configure_mixer(dev);
   548 		solo_configure_mixer(dev);
       
   549 	mutex_exit(&dev->mutex);
   531 	mutex_exit(&dev->mutex);
   550 	return (0);
   532 	return (0);
   551 }
   533 }
   552 
   534 
   553 static int
   535 static int
   749 	solo_dev_t	*dev = e->dev;
   731 	solo_dev_t	*dev = e->dev;
   750 	uint16_t	offset, n;
   732 	uint16_t	offset, n;
   751 	uint32_t	ptr;
   733 	uint32_t	ptr;
   752 	uint32_t	count;
   734 	uint32_t	count;
   753 	uint32_t	diff;
   735 	uint32_t	diff;
       
   736 	int		tries;
   754 
   737 
   755 	ASSERT(mutex_owned(&dev->mutex));
   738 	ASSERT(mutex_owned(&dev->mutex));
   756 
   739 
   757 	/*
   740 	/*
   758 	 * During recording, this register is known to give back
   741 	 * During recording, this register is known to give back
   759 	 * garbage if it's not quiescent while being read.  This hack
   742 	 * garbage if it's not quiescent while being read.  This hack
   760 	 * attempts to work around it.
   743 	 * attempts to work around it.  We also suspend the DMA
       
   744 	 * while we do this, to minimize record distortion.
   761 	 */
   745 	 */
   762 	ptr = PORT_RD32(dev->vc, 0);
   746 	if (e->trigger) {
   763 	count = PORT_RD16(dev->vc, 4);
   747 		drv_usecwait(20);
   764 	diff = e->paddr + SOLO_BUFSZ - ptr - count;
   748 	}
   765 	if ((diff > 3) || (ptr < e->paddr) ||
   749 	for (tries = 10; tries; tries--) {
   766 	    (ptr >= (e->paddr + SOLO_BUFSZ))) {
   750 		drv_usecwait(10);
   767 		ptr = dev->last_capture;
   751 		ptr = PORT_RD32(dev->vc, 0);
   768 	} else {
   752 		count = PORT_RD16(dev->vc, 4);
   769 		dev->last_capture = ptr;
   753 		diff = e->paddr + SOLO_BUFSZ - ptr - count;
   770 	}
   754 		if ((diff > 3) || (ptr < e->paddr) ||
       
   755 		    (ptr >= (e->paddr + SOLO_BUFSZ))) {
       
   756 			ptr = dev->last_capture;
       
   757 		} else {
       
   758 			break;
       
   759 		}
       
   760 	}
       
   761 	if (e->trigger) {
       
   762 		PORT_WR8(dev->vc, 0xf, 0);	/* restart DMA */
       
   763 	}
       
   764 	if (!tries) {
       
   765 		/*
       
   766 		 * Note, this is a pretty bad situation, because we'll
       
   767 		 * not have an accurate idea of our position.  But its
       
   768 		 * better than making a bad alteration.  If we had FMA
       
   769 		 * for audio devices, this would be a good point to
       
   770 		 * raise a fault.
       
   771 		 */
       
   772 		return;
       
   773 	}
       
   774 	dev->last_capture = ptr;
   771 	offset = ptr - e->paddr;
   775 	offset = ptr - e->paddr;
   772 	offset /= (SOLO_NCHAN * SOLO_SAMPSZ);
   776 	offset /= (SOLO_NCHAN * SOLO_SAMPSZ);
   773 
   777 
   774 	n = offset >= e->offset ?
   778 	n = offset >= e->offset ?
   775 	    offset - e->offset :
   779 	    offset - e->offset :
   829 	/* autoinit, dma dir, go for it */
   833 	/* autoinit, dma dir, go for it */
   830 	solo_write(dev, 0xb8, 0x0f);
   834 	solo_write(dev, 0xb8, 0x0f);
   831 	PORT_WR8(dev->vc, 0xf, 0);	/* start DMA */
   835 	PORT_WR8(dev->vc, 0xf, 0);	/* start DMA */
   832 
   836 
   833 	dev->last_capture = e->paddr;
   837 	dev->last_capture = e->paddr;
       
   838 	e->trigger = true;
   834 }
   839 }
   835 
   840 
   836 static void
   841 static void
   837 solo_aud1_stop(solo_engine_t *e)
   842 solo_aud1_stop(solo_engine_t *e)
   838 {
   843 {
   839 	solo_dev_t	*dev = e->dev;
   844 	solo_dev_t	*dev = e->dev;
   840 
   845 
   841 	/* NB: We might be in quiesce, without a lock held */
   846 	/* NB: We might be in quiesce, without a lock held */
   842 	solo_write(dev, 0xb8, solo_read(dev, 0xb8) & ~0x01);
   847 	solo_write(dev, 0xb8, solo_read(dev, 0xb8) & ~0x01);
       
   848 	e->trigger = false;
   843 }
   849 }
   844 
   850 
   845 static void
   851 static void
   846 solo_aud2_update(solo_engine_t *e)
   852 solo_aud2_update(solo_engine_t *e)
   847 {
   853 {
   898 	PORT_WR8(dev->io, 0x6, 0x0a); /* autoinit, enable */
   904 	PORT_WR8(dev->io, 0x6, 0x0a); /* autoinit, enable */
   899 
   905 
   900 	v = solo_mixer_scale(dev, CTL_VOLUME);
   906 	v = solo_mixer_scale(dev, CTL_VOLUME);
   901 	v = v | (v << 4);
   907 	v = v | (v << 4);
   902 	solo_setmixer(dev, 0x7c, v & 0xff);
   908 	solo_setmixer(dev, 0x7c, v & 0xff);
       
   909 
       
   910 	e->trigger = true;
   903 }
   911 }
   904 
   912 
   905 static void
   913 static void
   906 solo_aud2_stop(solo_engine_t *e)
   914 solo_aud2_stop(solo_engine_t *e)
   907 {
   915 {
   908 	solo_dev_t	*dev = e->dev;
   916 	solo_dev_t	*dev = e->dev;
   909 
   917 
   910 	/* NB: We might be in quiesce, without a lock held */
   918 	/* NB: We might be in quiesce, without a lock held */
   911 	PORT_WR8(dev->io, 0x6, 0);
   919 	PORT_WR8(dev->io, 0x6, 0);
   912 	solo_setmixer(dev, 0x78, solo_getmixer(dev, 0x78) & ~0x03);
   920 	solo_setmixer(dev, 0x78, solo_getmixer(dev, 0x78) & ~0x03);
       
   921 
       
   922 	e->trigger = false;
   913 }
   923 }
   914 
   924 
   915 /*
   925 /*
   916  * Audio entry points.
   926  * Audio entry points.
   917  */
   927  */
   966 	solo_engine_t	*e = arg;
   976 	solo_engine_t	*e = arg;
   967 	solo_dev_t	*dev = e->dev;
   977 	solo_dev_t	*dev = e->dev;
   968 	uint64_t	count;
   978 	uint64_t	count;
   969 
   979 
   970 	mutex_enter(&dev->mutex);
   980 	mutex_enter(&dev->mutex);
   971 	if (!dev->suspended)
   981 	e->update(e);
   972 		e->update(e);
       
   973 	count = e->count;
   982 	count = e->count;
   974 	mutex_exit(&dev->mutex);
   983 	mutex_exit(&dev->mutex);
   975 
   984 
   976 	return (count);
   985 	return (count);
   977 }
   986 }
   978 
   987 
   979 static int
   988 static int
   980 solo_open(void *arg, int f, unsigned *ffr, unsigned *nfr, caddr_t *buf)
   989 solo_open(void *arg, int f, unsigned *nframes, caddr_t *buf)
   981 {
   990 {
   982 	solo_engine_t	*e = arg;
   991 	solo_engine_t	*e = arg;
   983 	solo_dev_t	*dev = e->dev;
   992 	solo_dev_t	*dev = e->dev;
   984 
   993 
   985 	_NOTE(ARGUNUSED(f));
   994 	_NOTE(ARGUNUSED(f));
   986 
   995 
   987 	/* NB: For simplicity, we just fix the interrupt rate at 100 Hz */
   996 	*nframes = SOLO_NFRAGS * SOLO_FRAGFR;
   988 	*ffr = SOLO_FRAGFR;
       
   989 	*nfr = SOLO_NFRAGS;
       
   990 	*buf = e->kaddr;
   997 	*buf = e->kaddr;
   991 
   998 
   992 	mutex_enter(&dev->mutex);
   999 	mutex_enter(&dev->mutex);
   993 	e->started = false;
  1000 	e->started = false;
   994 	e->count = 0;
  1001 	e->count = 0;
  1002 {
  1009 {
  1003 	solo_engine_t	*e = arg;
  1010 	solo_engine_t	*e = arg;
  1004 	solo_dev_t	*dev = e->dev;
  1011 	solo_dev_t	*dev = e->dev;
  1005 
  1012 
  1006 	mutex_enter(&dev->mutex);
  1013 	mutex_enter(&dev->mutex);
  1007 	if (!dev->suspended)
  1014 	e->stop(e);
  1008 		e->stop(e);
       
  1009 	e->started = false;
  1015 	e->started = false;
  1010 	mutex_exit(&dev->mutex);
  1016 	mutex_exit(&dev->mutex);
  1011 }
  1017 }
  1012 
  1018 
  1013 
  1019 
  1017 	solo_engine_t	*e = arg;
  1023 	solo_engine_t	*e = arg;
  1018 	solo_dev_t	*dev = e->dev;
  1024 	solo_dev_t	*dev = e->dev;
  1019 
  1025 
  1020 	mutex_enter(&dev->mutex);
  1026 	mutex_enter(&dev->mutex);
  1021 	if (!e->started) {
  1027 	if (!e->started) {
  1022 		if (!dev->suspended)
  1028 		e->start(e);
  1023 			e->start(e);
       
  1024 		e->started = true;
  1029 		e->started = true;
  1025 	}
  1030 	}
  1026 	mutex_exit(&dev->mutex);
  1031 	mutex_exit(&dev->mutex);
  1027 
  1032 
  1028 	return (0);
  1033 	return (0);
  1034 	solo_engine_t	*e = arg;
  1039 	solo_engine_t	*e = arg;
  1035 	solo_dev_t	*dev = e->dev;
  1040 	solo_dev_t	*dev = e->dev;
  1036 
  1041 
  1037 	mutex_enter(&dev->mutex);
  1042 	mutex_enter(&dev->mutex);
  1038 	if (e->started) {
  1043 	if (e->started) {
  1039 		if (!dev->suspended)
  1044 		e->stop(e);
  1040 			e->stop(e);
       
  1041 		e->started = false;
  1045 		e->started = false;
  1042 	}
  1046 	}
  1043 	mutex_exit(&dev->mutex);
  1047 	mutex_exit(&dev->mutex);
  1044 
  1048 
  1045 }
  1049 }
  1330 
  1334 
  1331 
  1335 
  1332 static int
  1336 static int
  1333 solo_suspend(solo_dev_t *dev)
  1337 solo_suspend(solo_dev_t *dev)
  1334 {
  1338 {
       
  1339 	audio_dev_suspend(dev->adev);
       
  1340 
  1335 	mutex_enter(&dev->mutex);
  1341 	mutex_enter(&dev->mutex);
  1336 	/* play */
       
  1337 	solo_aud2_stop(&dev->play);
       
  1338 	solo_aud2_update(&dev->play);
       
  1339 	/* record */
       
  1340 	solo_aud1_stop(&dev->rec);
       
  1341 	solo_aud1_update(&dev->rec);
       
  1342 
       
  1343 	dev->suspended = true;
  1342 	dev->suspended = true;
  1344 	mutex_exit(&dev->mutex);
  1343 	mutex_exit(&dev->mutex);
  1345 
  1344 
  1346 	return (DDI_SUCCESS);
  1345 	return (DDI_SUCCESS);
  1347 }
  1346 }
  1348 
  1347 
  1349 static int
  1348 static int
  1350 solo_resume(solo_dev_t *dev)
  1349 solo_resume(solo_dev_t *dev)
  1351 {
  1350 {
  1352 	solo_engine_t	*e;
       
  1353 	audio_engine_t	*prod = NULL;
       
  1354 	audio_engine_t	*cons = NULL;
       
  1355 
       
  1356 	audio_engine_reset(dev->rec.engine);
       
  1357 	audio_engine_reset(dev->play.engine);
       
  1358 
       
  1359 	mutex_enter(&dev->mutex);
  1351 	mutex_enter(&dev->mutex);
  1360 	if (!solo_init_hw(dev)) {
  1352 	if (!solo_init_hw(dev)) {
  1361 		/* yikes! */
  1353 		/* yikes! */
  1362 		audio_dev_warn(dev->adev, "unable to resume audio!");
  1354 		audio_dev_warn(dev->adev, "unable to resume audio!");
  1363 		audio_dev_warn(dev->adev, "reboot or reload driver to reset");
  1355 		audio_dev_warn(dev->adev, "reboot or reload driver to reset");
  1364 		mutex_exit(&dev->mutex);
       
  1365 		return (DDI_SUCCESS);
       
  1366 	}
  1356 	}
  1367 	dev->suspended = false;
  1357 	dev->suspended = false;
  1368 
       
  1369 	/* record - audio 1 */
       
  1370 	e = &dev->rec;
       
  1371 	if (e->started) {
       
  1372 		e->start(e);
       
  1373 		prod = e->engine;
       
  1374 	}
       
  1375 
       
  1376 	/* play - audio 2 */
       
  1377 	e = &dev->play;
       
  1378 	if (e->started) {
       
  1379 		e->start(e);
       
  1380 		cons = e->engine;
       
  1381 	}
       
  1382 
       
  1383 	mutex_exit(&dev->mutex);
  1358 	mutex_exit(&dev->mutex);
  1384 
  1359 
  1385 	if (cons)
  1360 	audio_dev_resume(dev->adev);
  1386 		audio_engine_consume(cons);
       
  1387 	if (prod)
       
  1388 		audio_engine_produce(prod);
       
  1389 
  1361 
  1390 	return (DDI_SUCCESS);
  1362 	return (DDI_SUCCESS);
  1391 }
  1363 }
  1392 
  1364 
  1393 static int
  1365 static int