Deleted Added
sdiff udiff text old ( 71503 ) new ( 74763 )
full compact
1/*
2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/sound/pci/t4dwave.c 71503 2001-01-24 01:20:04Z cg $
27 */
28
29#include <dev/sound/pcm/sound.h>
30#include <dev/sound/pcm/ac97.h>
31#include <dev/sound/pci/t4dwave.h>
32
33#include <pci/pcireg.h>
34#include <pci/pcivar.h>

--- 12 unchanged lines hidden (view full) ---

47/* channel registers */
48struct tr_chinfo {
49 u_int32_t cso, alpha, fms, fmc, ec;
50 u_int32_t lba;
51 u_int32_t eso, delta;
52 u_int32_t rvol, cvol;
53 u_int32_t gvsel, pan, vol, ctrl;
54 int index, bufhalf;
55 snd_dbuf *buffer;
56 pcm_channel *channel;
57 struct tr_info *parent;
58};
59
60struct tr_rchinfo {
61 u_int32_t delta;
62 snd_dbuf *buffer;
63 pcm_channel *channel;
64 struct tr_info *parent;
65};
66
67/* device private data */
68struct tr_info {
69 u_int32_t type;
70
71 bus_space_tag_t st;
72 bus_space_handle_t sh;
73 bus_dma_tag_t parent_dmat;
74
75 struct resource *reg, *irq;
76 int regtype, regid, irqid;
77 void *ih;
78
79 u_int32_t playchns;
80 struct tr_chinfo chinfo[TR_MAXPLAYCH];
81 struct tr_rchinfo recchinfo;
82};
83
84/* -------------------------------------------------------------------- */
85
86static u_int32_t tr_recfmt[] = {
87 AFMT_U8,
88 AFMT_STEREO | AFMT_U8,
89 AFMT_S8,
90 AFMT_STEREO | AFMT_S8,
91 AFMT_S16_LE,
92 AFMT_STEREO | AFMT_S16_LE,
93 AFMT_U16_LE,
94 AFMT_STEREO | AFMT_U16_LE,
95 0
96};
97static pcmchan_caps tr_reccaps = {4000, 48000, tr_recfmt, 0};
98
99static u_int32_t tr_playfmt[] = {
100 AFMT_U8,
101 AFMT_STEREO | AFMT_U8,
102 AFMT_S8,
103 AFMT_STEREO | AFMT_S8,
104 AFMT_S16_LE,
105 AFMT_STEREO | AFMT_S16_LE,
106 AFMT_U16_LE,
107 AFMT_STEREO | AFMT_U16_LE,
108 0
109};
110static pcmchan_caps tr_playcaps = {4000, 48000, tr_playfmt, 0};
111
112/* -------------------------------------------------------------------- */
113
114/* Hardware */
115
116static u_int32_t
117tr_rd(struct tr_info *tr, int regno, int size)
118{

--- 44 unchanged lines hidden (view full) ---

163 trw=TNX_CDC_RWSTAT;
164 break;
165 default:
166 printf("!!! tr_rdcd defaulted !!!\n");
167 return -1;
168 }
169
170 regno &= 0x7f;
171 tr_wr(tr, treg, regno | trw, 4);
172 j=trw;
173 for (i=TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--) j=tr_rd(tr, treg, 4);
174 if (i == 0) printf("codec timeout during read of register %x\n", regno);
175 return (j >> TR_CDC_DATA) & 0xffff;
176}
177
178static int
179tr_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
180{
181 struct tr_info *tr = (struct tr_info *)devinfo;

--- 13 unchanged lines hidden (view full) ---

195 return -1;
196 }
197
198 regno &= 0x7f;
199#if 0
200 printf("tr_wrcd: reg %x was %x", regno, tr_rdcd(devinfo, regno));
201#endif
202 j=trw;
203 for (i=TR_TIMEOUT_CDC; (i>0) && (j & trw); i--) j=tr_rd(tr, treg, 4);
204 tr_wr(tr, treg, (data << TR_CDC_DATA) | regno | trw, 4);
205#if 0
206 printf(" - wrote %x, now %x\n", data, tr_rdcd(devinfo, regno));
207#endif
208 if (i==0) printf("codec timeout writing %x, data %x\n", regno, data);
209 return (i > 0)? 0 : -1;
210}
211
212static kobj_method_t tr_ac97_methods[] = {
213 KOBJMETHOD(ac97_read, tr_rdcd),
214 KOBJMETHOD(ac97_write, tr_wrcd),
215 { 0, 0 }

--- 29 unchanged lines hidden (view full) ---

245
246static void
247tr_enaint(struct tr_chinfo *ch, int enable)
248{
249 struct tr_info *tr = ch->parent;
250 u_int32_t i, reg;
251 int bank, chan;
252
253 bank = (ch->index & 0x20) ? 1 : 0;
254 chan = ch->index & 0x1f;
255 reg = bank? TR_REG_INTENB : TR_REG_INTENA;
256
257 i = tr_rd(tr, reg, 4);
258 i &= ~(1 << chan);
259 i |= (enable? 1 : 0) << chan;
260
261 tr_clrint(ch);
262 tr_wr(tr, reg, i, 4);
263}
264
265/* playback channels */
266
267static void
268tr_selch(struct tr_chinfo *ch)
269{
270 struct tr_info *tr = ch->parent;

--- 60 unchanged lines hidden (view full) ---

331 case TNX_PCI_ID:
332 ch->cso &= 0x00ffffff;
333 ch->eso &= 0x00ffffff;
334 cr[0]=((ch->delta & 0xff)<<24) | (ch->cso);
335 cr[2]=((ch->delta>>16)<<24) | (ch->eso);
336 cr[3]|=(ch->alpha<<20) | (ch->fms<<16) | (ch->fmc<<14);
337 break;
338 }
339 tr_selch(ch);
340 for (i=0; i<TR_CHN_REGS; i++)
341 tr_wr(tr, TR_REG_CHNBASE+(i<<2), cr[i], 4);
342}
343
344static void
345tr_rdch(struct tr_chinfo *ch)
346{
347 struct tr_info *tr = ch->parent;
348 u_int32_t cr[5], i;
349
350 tr_selch(ch);
351 for (i=0; i<5; i++)
352 cr[i]=tr_rd(tr, TR_REG_CHNBASE+(i<<2), 4);
353
354
355 ch->lba= (cr[1] & 0x3fffffff);
356 ch->fmc= (cr[3] & 0x0000c000) >> 14;
357 ch->rvol= (cr[3] & 0x00003f80) >> 7;
358 ch->cvol= (cr[3] & 0x0000007f);
359 ch->gvsel= (cr[4] & 0x80000000) >> 31;
360 ch->pan= (cr[4] & 0x7f000000) >> 24;

--- 30 unchanged lines hidden (view full) ---

391
392 return bits;
393}
394
395/* -------------------------------------------------------------------- */
396/* channel interface */
397
398static void *
399trpchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
400{
401 struct tr_info *tr = devinfo;
402 struct tr_chinfo *ch;
403
404 KASSERT(dir == PCMDIR_PLAY, ("trpchan_init: bad direction"));
405 ch = &tr->chinfo[tr->playchns];
406 ch->index = tr->playchns++;
407 ch->buffer = b;

--- 67 unchanged lines hidden (view full) ---

475trpchan_getptr(kobj_t obj, void *data)
476{
477 struct tr_chinfo *ch = data;
478
479 tr_rdch(ch);
480 return ch->cso * sndbuf_getbps(ch->buffer);
481}
482
483static pcmchan_caps *
484trpchan_getcaps(kobj_t obj, void *data)
485{
486 return &tr_playcaps;
487}
488
489static kobj_method_t trpchan_methods[] = {
490 KOBJMETHOD(channel_init, trpchan_init),
491 KOBJMETHOD(channel_setformat, trpchan_setformat),

--- 5 unchanged lines hidden (view full) ---

497 { 0, 0 }
498};
499CHANNEL_DECLARE(trpchan);
500
501/* -------------------------------------------------------------------- */
502/* rec channel interface */
503
504static void *
505trrchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
506{
507 struct tr_info *tr = devinfo;
508 struct tr_rchinfo *ch;
509
510 KASSERT(dir == PCMDIR_REC, ("trrchan_init: bad direction"));
511 ch = &tr->recchinfo;
512 ch->buffer = b;
513 ch->parent = tr;

--- 81 unchanged lines hidden (view full) ---

595{
596 struct tr_rchinfo *ch = data;
597 struct tr_info *tr = ch->parent;
598
599 /* return current byte offset of channel */
600 return tr_rd(tr, TR_REG_DMAR0, 4) - vtophys(sndbuf_getbuf(ch->buffer));
601}
602
603static pcmchan_caps *
604trrchan_getcaps(kobj_t obj, void *data)
605{
606 return &tr_reccaps;
607}
608
609static kobj_method_t trrchan_methods[] = {
610 KOBJMETHOD(channel_init, trrchan_init),
611 KOBJMETHOD(channel_setformat, trrchan_setformat),

--- 29 unchanged lines hidden (view full) ---

641 if (active & mask) {
642 tmp = (bufhalf & mask)? 1 : 0;
643 if (chnum < tr->playchns) {
644 ch = &tr->chinfo[chnum];
645 /* printf("%d @ %d, ", chnum, trpchan_getptr(NULL, ch)); */
646 if (ch->bufhalf != tmp) {
647 chn_intr(ch->channel);
648 ch->bufhalf = tmp;
649 } else
650 printf("same bufhalf\n");
651
652 }
653 }
654 chnum++;
655 mask <<= 1;
656 } while (chnum & 31);
657 } else
658 chnum += 32;
659

--- 51 unchanged lines hidden (view full) ---

711
712 if ((tr = malloc(sizeof(*tr), M_DEVBUF, M_NOWAIT)) == NULL) {
713 device_printf(dev, "cannot allocate softc\n");
714 return ENXIO;
715 }
716
717 bzero(tr, sizeof(*tr));
718 tr->type = pci_get_devid(dev);
719
720 data = pci_read_config(dev, PCIR_COMMAND, 2);
721 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
722 pci_write_config(dev, PCIR_COMMAND, data, 2);
723 data = pci_read_config(dev, PCIR_COMMAND, 2);
724
725 tr->regid = PCIR_MAPS;
726 tr->regtype = SYS_RES_IOPORT;

--- 13 unchanged lines hidden (view full) ---

740
741 codec = AC97_CREATE(dev, tr, tr_ac97);
742 if (codec == NULL) goto bad;
743 if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
744
745 tr->irqid = 0;
746 tr->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &tr->irqid,
747 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
748 if (!tr->irq ||
749 bus_setup_intr(dev, tr->irq, INTR_TYPE_TTY, tr_intr, tr, &tr->ih)) {
750 device_printf(dev, "unable to map interrupt\n");
751 goto bad;
752 }
753
754 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
755 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
756 /*highaddr*/BUS_SPACE_MAXADDR,
757 /*filter*/NULL, /*filterarg*/NULL,

--- 15 unchanged lines hidden (view full) ---

773 return 0;
774
775bad:
776 if (codec) ac97_destroy(codec);
777 if (tr->reg) bus_release_resource(dev, tr->regtype, tr->regid, tr->reg);
778 if (tr->ih) bus_teardown_intr(dev, tr->irq, tr->ih);
779 if (tr->irq) bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq);
780 if (tr->parent_dmat) bus_dma_tag_destroy(tr->parent_dmat);
781 free(tr, M_DEVBUF);
782 return ENXIO;
783}
784
785static int
786tr_pci_detach(device_t dev)
787{
788 int r;
789 struct tr_info *tr;
790
791 r = pcm_unregister(dev);
792 if (r)
793 return r;
794
795 tr = pcm_getdevinfo(dev);
796 bus_release_resource(dev, tr->regtype, tr->regid, tr->reg);
797 bus_teardown_intr(dev, tr->irq, tr->ih);
798 bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq);
799 bus_dma_tag_destroy(tr->parent_dmat);
800 free(tr, M_DEVBUF);
801
802 return 0;
803}
804
805static device_method_t tr_methods[] = {
806 /* Device interface */
807 DEVMETHOD(device_probe, tr_pci_probe),
808 DEVMETHOD(device_attach, tr_pci_attach),
809 DEVMETHOD(device_detach, tr_pci_detach),
810
811 { 0, 0 }
812};
813
814static driver_t tr_driver = {
815 "pcm",
816 tr_methods,
817 sizeof(snddev_info),
818};
819
820static devclass_t pcm_devclass;
821
822DRIVER_MODULE(snd_t4dwave, pci, tr_driver, pcm_devclass, 0, 0);
823MODULE_DEPEND(snd_t4dwave, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
824MODULE_VERSION(snd_t4dwave, 1);