Deleted Added
sdiff udiff text old ( 65644 ) new ( 70134 )
full compact
1/*
2 * Copyright (c) 1999 Seigo Tanimura
3 * All rights reserved.
4 *
5 * Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in
6 * cwcealdr1.zip, the sample sources by Crystal Semiconductor.
7 * Copyright (c) 1996-1998 Crystal Semiconductor Corp.
8 *

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

22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $FreeBSD: head/sys/dev/sound/pci/csapcm.c 65644 2000-09-09 19:21:04Z cg $
31 */
32
33#include <sys/soundcard.h>
34#include <dev/sound/pcm/sound.h>
35#include <dev/sound/pcm/ac97.h>
36#include <dev/sound/chip.h>
37#include <dev/sound/pci/csareg.h>
38#include <dev/sound/pci/csavar.h>

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

77static void csa_stopplaydma(struct csa_info *csa);
78static void csa_stopcapturedma(struct csa_info *csa);
79static void csa_powerupadc(csa_res *resp);
80static void csa_powerupdac(csa_res *resp);
81static int csa_startdsp(csa_res *resp);
82static int csa_allocres(struct csa_info *scp, device_t dev);
83static void csa_releaseres(struct csa_info *scp, device_t dev);
84
85/* talk to the codec - called from ac97.c */
86static u_int32_t csa_rdcd(void *, int);
87static void csa_wrcd(void *, int, u_int32_t);
88
89/* channel interface */
90static void *csachan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
91static int csachan_setdir(void *data, int dir);
92static int csachan_setformat(void *data, u_int32_t format);
93static int csachan_setspeed(void *data, u_int32_t speed);
94static int csachan_setblocksize(void *data, u_int32_t blocksize);
95static int csachan_trigger(void *data, int go);
96static int csachan_getptr(void *data);
97static pcmchan_caps *csachan_getcaps(void *data);
98
99static u_int32_t csa_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_S16_BE,

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

111
112static u_int32_t csa_recfmt[] = {
113 AFMT_S16_LE,
114 AFMT_STEREO | AFMT_S16_LE,
115 0
116};
117static pcmchan_caps csa_reccaps = {11025, 48000, csa_recfmt, 0};
118
119static pcm_channel csa_chantemplate = {
120 csachan_init,
121 csachan_setdir,
122 csachan_setformat,
123 csachan_setspeed,
124 csachan_setblocksize,
125 csachan_trigger,
126 csachan_getptr,
127 csachan_getcaps,
128 NULL, /* free */
129 NULL, /* nop1 */
130 NULL, /* nop2 */
131 NULL, /* nop3 */
132 NULL, /* nop4 */
133 NULL, /* nop5 */
134 NULL, /* nop6 */
135 NULL, /* nop7 */
136};
137
138/* -------------------------------------------------------------------- */
139
140/* channel interface */
141static void *
142csachan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
143{
144 struct csa_info *csa = devinfo;
145 struct csa_chinfo *ch = (dir == PCMDIR_PLAY)? &csa->pch : &csa->rch;
146
147 ch->parent = csa;
148 ch->channel = c;
149 ch->buffer = b;
150 ch->buffer->bufsize = CS461x_BUFFSIZE;
151 if (chn_allocbuf(ch->buffer, csa->parent_dmat) == -1) return NULL;
152 return ch;
153}
154
155static int
156csachan_setdir(void *data, int dir)
157{
158 struct csa_chinfo *ch = data;
159 struct csa_info *csa = ch->parent;
160 csa_res *resp;
161
162 resp = &csa->res;
163
164 if (dir == PCMDIR_PLAY)
165 csa_writemem(resp, BA1_PBA, vtophys(ch->buffer->buf));
166 else
167 csa_writemem(resp, BA1_CBA, vtophys(ch->buffer->buf));
168 ch->dir = dir;
169 return 0;
170}
171
172static int
173csachan_setformat(void *data, u_int32_t format)
174{
175 struct csa_chinfo *ch = data;
176 struct csa_info *csa = ch->parent;
177 u_long pdtc;
178 csa_res *resp;
179
180 resp = &csa->res;
181
182 if (ch->dir == PCMDIR_REC)
183 csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
184 else {
185 csa->pfie = csa_readmem(resp, BA1_PFIE) & ~0x0000f03f;
186 if (format & AFMT_U8 || format & AFMT_U16_LE || format & AFMT_U16_BE)
187 csa->pfie |= 0x8000;
188 if (format & AFMT_S16_BE || format & AFMT_U16_BE)
189 csa->pfie |= 0x4000;
190 if (!(format & AFMT_STEREO))
191 csa->pfie |= 0x2000;
192 if (format & AFMT_U8 || format & AFMT_S8)
193 csa->pfie |= 0x1000;
194 csa_writemem(resp, BA1_PFIE, csa->pfie);
195 pdtc = csa_readmem(resp, BA1_PDTC) & ~0x000003ff;
196 if ((format & AFMT_S16_BE || format & AFMT_U16_BE || format & AFMT_S16_LE || format & AFMT_U16_LE) && (format & AFMT_STEREO))
197 pdtc |= 0x00f;
198 else if ((format & AFMT_S16_BE || format & AFMT_U16_BE || format & AFMT_S16_LE || format & AFMT_U16_LE) || (format & AFMT_STEREO))
199 pdtc |= 0x007;
200 else
201 pdtc |= 0x003;
202 csa_writemem(resp, BA1_PDTC, pdtc);
203 }
204 ch->fmt = format;
205 return 0;
206}
207
208static int
209csachan_setspeed(void *data, u_int32_t speed)
210{
211 struct csa_chinfo *ch = data;
212 struct csa_info *csa = ch->parent;
213 csa_res *resp;
214
215 resp = &csa->res;
216
217 if (ch->dir == PCMDIR_PLAY)
218 csa_setplaysamplerate(resp, speed);
219 else if (ch->dir == PCMDIR_REC)
220 csa_setcapturesamplerate(resp, speed);
221
222 /* rec/play speeds locked together - should indicate in flags */
223#if 0
224 if (ch->direction == PCMDIR_PLAY) d->rec[0].speed = speed;
225 else d->play[0].speed = speed;
226#endif
227 return speed; /* XXX calc real speed */
228}
229
230static void
231csa_setplaysamplerate(csa_res *resp, u_long ulInRate)
232{
233 u_long ulTemp1, ulTemp2;
234 u_long ulPhiIncr;
235 u_long ulCorrectionPerGOF, ulCorrectionPerSec;
236 u_long ulOutRate;
237

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

382 */
383 csa_writemem(resp, BA1_CFG1, dwFrameGroupLength);
384 csa_writemem(resp, BA1_CFG2, (0x00800000 | dwFrameGroupLength));
385 csa_writemem(resp, BA1_CCST, 0x0000FFFF);
386 csa_writemem(resp, BA1_CSPB, ((65536 * ulOutRate) / 24000));
387 csa_writemem(resp, (BA1_CSPB + 4), 0x0000FFFF);
388}
389
390static int
391csachan_setblocksize(void *data, u_int32_t blocksize)
392{
393#if notdef
394 return blocksize;
395#else
396 struct csa_chinfo *ch = data;
397 return ch->buffer->bufsize / 2;
398#endif /* notdef */
399}
400
401static int
402csachan_trigger(void *data, int go)
403{
404 struct csa_chinfo *ch = data;
405 struct csa_info *csa = ch->parent;
406
407 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
408 return 0;
409
410 if (ch->dir == PCMDIR_PLAY) {
411 if (go == PCMTRIG_START)
412 csa_startplaydma(csa);
413 else
414 csa_stopplaydma(csa);
415 } else {
416 if (go == PCMTRIG_START)
417 csa_startcapturedma(csa);
418 else
419 csa_stopcapturedma(csa);
420 }
421 return 0;
422}
423
424static void
425csa_startplaydma(struct csa_info *csa)
426{
427 csa_res *resp;
428 u_long ul;
429
430 if (!csa->pch.dma) {
431 resp = &csa->res;

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

633 * If the run at frame bit never reset, then return an error.
634 */
635 if((ul & SPCR_RUNFR) != 0)
636 return (EAGAIN);
637
638 return (0);
639}
640
641static int
642csachan_getptr(void *data)
643{
644 struct csa_chinfo *ch = data;
645 struct csa_info *csa = ch->parent;
646 csa_res *resp;
647 int ptr;
648
649 resp = &csa->res;
650
651 if (ch->dir == PCMDIR_PLAY) {
652 ptr = csa_readmem(resp, BA1_PBA) - vtophys(ch->buffer->buf);
653 if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
654 ptr >>= 1;
655 } else {
656 ptr = csa_readmem(resp, BA1_CBA) - vtophys(ch->buffer->buf);
657 if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
658 ptr >>= 1;
659 }
660
661 return (ptr);
662}
663
664static pcmchan_caps *
665csachan_getcaps(void *data)
666{
667 struct csa_chinfo *ch = data;
668 return (ch->dir == PCMDIR_PLAY)? &csa_playcaps : &csa_reccaps;
669}
670
671/* The interrupt handler */
672static void
673csa_intr (void *p)
674{
675 struct csa_info *csa = p;
676
677 if ((csa->binfo->hisr & HISR_VC0) != 0)
678 chn_intr(csa->pch.channel);

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

828 csa_releaseres(csa, dev);
829 return (ENXIO);
830 }
831
832 if (csa_init(csa)) {
833 csa_releaseres(csa, dev);
834 return (ENXIO);
835 }
836 codec = ac97_create(dev, csa, NULL, csa_rdcd, csa_wrcd);
837 if (codec == NULL) {
838 csa_releaseres(csa, dev);
839 return (ENXIO);
840 }
841 if (mixer_init(dev, &ac97_mixer, codec) == -1) {
842 ac97_destroy(codec);
843 csa_releaseres(csa, dev);
844 return (ENXIO);
845 }
846
847 snprintf(status, SND_STATUSLEN, "at irq %ld", rman_get_start(resp->irq));
848
849 /* Enable interrupt. */

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

855 csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
856 csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
857
858 if (pcm_register(dev, csa, 1, 1)) {
859 ac97_destroy(codec);
860 csa_releaseres(csa, dev);
861 return (ENXIO);
862 }
863 pcm_addchan(dev, PCMDIR_REC, &csa_chantemplate, csa);
864 pcm_addchan(dev, PCMDIR_PLAY, &csa_chantemplate, csa);
865 pcm_setstatus(dev, status);
866
867 return (0);
868}
869
870static int
871pcmcsa_detach(device_t dev)
872{

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

878 return r;
879
880 csa = pcm_getdevinfo(dev);
881 csa_releaseres(csa, dev);
882
883 return 0;
884}
885
886/* ac97 codec */
887
888static u_int32_t
889csa_rdcd(void *devinfo, int regno)
890{
891 u_int32_t data;
892 struct csa_info *csa = (struct csa_info *)devinfo;
893
894 if (csa_readcodec(&csa->res, regno + BA0_AC97_RESET, &data))
895 data = 0;
896
897 return data;
898}
899
900static void
901csa_wrcd(void *devinfo, int regno, u_int32_t data)
902{
903 struct csa_info *csa = (struct csa_info *)devinfo;
904
905 csa_writecodec(&csa->res, regno + BA0_AC97_RESET, data);
906}
907
908static device_method_t pcmcsa_methods[] = {
909 /* Device interface */
910 DEVMETHOD(device_probe , pcmcsa_probe ),
911 DEVMETHOD(device_attach, pcmcsa_attach),
912 DEVMETHOD(device_detach, pcmcsa_detach),
913
914 { 0, 0 },
915};

--- 13 unchanged lines hidden ---