📄 riptide.c
字号:
int openstreams; int irq; unsigned long port; unsigned short mpuaddr; unsigned short opladdr;#ifdef SUPPORT_JOYSTICK unsigned short gameaddr;#endif struct resource *res_port; unsigned short device_id; union firmware_version firmware; spinlock_t lock; struct tasklet_struct riptide_tq; struct snd_info_entry *proc_entry; unsigned long received_irqs; unsigned long handled_irqs;#ifdef CONFIG_PM int in_suspend;#endif};struct sgd { /* scatter gather desriptor */ u32 dwNextLink; u32 dwSegPtrPhys; u32 dwSegLen; u32 dwStat_Ctl;};struct pcmhw { /* pcm descriptor */ struct lbuspath paths; unsigned char *lbuspath; unsigned char source; unsigned char intdec[2]; unsigned char mixer; unsigned char id; unsigned char state; unsigned int rate; unsigned int channels; snd_pcm_format_t format; struct snd_dma_buffer sgdlist; struct sgd *sgdbuf; unsigned int size; unsigned int pages; unsigned int oldpos; unsigned int pointer;};#define CMDRET_ZERO (union cmdret){{(u32)0, (u32) 0}}static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm, union cmdret *ret);static int getsourcesink(struct cmdif *cif, unsigned char source, unsigned char sink, unsigned char *a, unsigned char *b);static int snd_riptide_initialize(struct snd_riptide *chip);static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip);/* */static struct pci_device_id snd_riptide_ids[] = { { .vendor = 0x127a,.device = 0x4310, .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, }, { .vendor = 0x127a,.device = 0x4320, .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, }, { .vendor = 0x127a,.device = 0x4330, .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, }, { .vendor = 0x127a,.device = 0x4340, .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, }, {0,},};#ifdef SUPPORT_JOYSTICKstatic struct pci_device_id snd_riptide_joystick_ids[] __devinitdata = { { .vendor = 0x127a,.device = 0x4312, .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, }, { .vendor = 0x127a,.device = 0x4322, .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, }, {.vendor = 0x127a,.device = 0x4332, .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, }, {.vendor = 0x127a,.device = 0x4342, .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, }, {0,},};#endifMODULE_DEVICE_TABLE(pci, snd_riptide_ids);/* */static unsigned char lbusin2out[E2SINK_MAX + 1][2] = { {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {INTER0_OUT, LS_SRC_INTERPOLATOR}, {INTER1_OUT, LS_SRC_INTERPOLATOR}, {INTER2_OUT, LS_SRC_INTERPOLATOR}, {INTER3_OUT, LS_SRC_INTERPOLATOR}, {INTER4_OUT, LS_SRC_INTERPOLATOR}, {INTERM0_OUT, LS_SRC_INTERPOLATORM}, {INTERM1_OUT, LS_SRC_INTERPOLATORM}, {INTERM2_OUT, LS_SRC_INTERPOLATORM}, {INTERM3_OUT, LS_SRC_INTERPOLATORM}, {INTERM4_OUT, LS_SRC_INTERPOLATORM}, {INTERM5_OUT, LS_SRC_INTERPOLATORM}, {INTERM6_OUT, LS_SRC_INTERPOLATORM}, {DECIMM0_OUT, LS_SRC_DECIMATORM}, {DECIMM1_OUT, LS_SRC_DECIMATORM}, {DECIMM2_OUT, LS_SRC_DECIMATORM}, {DECIMM3_OUT, LS_SRC_DECIMATORM}, {DECIM0_OUT, LS_SRC_DECIMATOR}, {SR3_4_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {GAINFUNC0_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC1_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC2_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC3_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC4_OUT, LS_MIXER_GAIN_FUNCTION}, {SOFTMODEMTX, LS_NONE1}, {SPLITTER0_OUTL, LS_SRC_SPLITTER}, {SPLITTER1_OUTL, LS_SRC_SPLITTER}, {SPLITTER2_OUTL, LS_SRC_SPLITTER}, {SPLITTER3_OUTL, LS_SRC_SPLITTER}, {MERGER0_OUT, LS_SRC_MERGER}, {MERGER0_OUT, LS_SRC_MERGER}, {MERGER1_OUT, LS_SRC_MERGER}, {MERGER1_OUT, LS_SRC_MERGER}, {MERGER2_OUT, LS_SRC_MERGER}, {MERGER2_OUT, LS_SRC_MERGER}, {MERGER3_OUT, LS_SRC_MERGER}, {MERGER3_OUT, LS_SRC_MERGER}, {NO_OUT, LS_NONE2},};static unsigned char lbus_play_opl3[] = { DIGITAL_MIXER_IN0 + FM_MIXER, 0xff};static unsigned char lbus_play_modem[] = { DIGITAL_MIXER_IN0 + MODEM_MIXER, 0xff};static unsigned char lbus_play_i2s[] = { INTER0_IN + I2S_INTDEC, DIGITAL_MIXER_IN0 + I2S_MIXER, 0xff};static unsigned char lbus_play_out[] = { PDAC2ACLNK, 0xff};static unsigned char lbus_play_outhp[] = { HNDSPK2ACLNK, 0xff};static unsigned char lbus_play_noconv1[] = { DIGITAL_MIXER_IN0, 0xff};static unsigned char lbus_play_stereo1[] = { INTER0_IN, DIGITAL_MIXER_IN0, 0xff};static unsigned char lbus_play_mono1[] = { INTERM0_IN, DIGITAL_MIXER_IN0, 0xff};static unsigned char lbus_play_noconv2[] = { DIGITAL_MIXER_IN1, 0xff};static unsigned char lbus_play_stereo2[] = { INTER1_IN, DIGITAL_MIXER_IN1, 0xff};static unsigned char lbus_play_mono2[] = { INTERM1_IN, DIGITAL_MIXER_IN1, 0xff};static unsigned char lbus_play_noconv3[] = { DIGITAL_MIXER_IN2, 0xff};static unsigned char lbus_play_stereo3[] = { INTER2_IN, DIGITAL_MIXER_IN2, 0xff};static unsigned char lbus_play_mono3[] = { INTERM2_IN, DIGITAL_MIXER_IN2, 0xff};static unsigned char lbus_rec_noconv1[] = { LBUS2ARM_FIFO5, 0xff};static unsigned char lbus_rec_stereo1[] = { DECIM0_IN, LBUS2ARM_FIFO5, 0xff};static unsigned char lbus_rec_mono1[] = { DECIMM3_IN, LBUS2ARM_FIFO5, 0xff};static unsigned char play_ids[] = { 4, 1, 2, };static unsigned char play_sources[] = { ARM2LBUS_FIFO4, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2,};static struct lbuspath lbus_play_paths[] = { { .noconv = lbus_play_noconv1, .stereo = lbus_play_stereo1, .mono = lbus_play_mono1, }, { .noconv = lbus_play_noconv2, .stereo = lbus_play_stereo2, .mono = lbus_play_mono2, }, { .noconv = lbus_play_noconv3, .stereo = lbus_play_stereo3, .mono = lbus_play_mono3, },};static struct lbuspath lbus_rec_path = { .noconv = lbus_rec_noconv1, .stereo = lbus_rec_stereo1, .mono = lbus_rec_mono1,};#define FIRMWARE_VERSIONS 1static union firmware_version firmware_versions[] = { { .firmware = { .ASIC = 3, .CODEC = 2, .AUXDSP = 3, .PROG = 773, }, },};static u32 atoh(unsigned char *in, unsigned int len){ u32 sum = 0; unsigned int mult = 1; unsigned char c; while (len) { c = in[len - 1]; if ((c >= '0') && (c <= '9')) sum += mult * (c - '0'); else if ((c >= 'A') && (c <= 'F')) sum += mult * (c - ('A' - 10)); else if ((c >= 'a') && (c <= 'f')) sum += mult * (c - ('a' - 10)); mult *= 16; --len; } return sum;}static int senddata(struct cmdif *cif, unsigned char *in, u32 offset){ u32 addr; u32 data; u32 i; unsigned char *p; i = atoh(&in[1], 2); addr = offset + atoh(&in[3], 4); if (SEND_SMEM(cif, 0, addr) != 0) return -EACCES; p = in + 9; while (i) { data = atoh(p, 8); if (SEND_WMEM(cif, 2, ((data & 0x0f0f0f0f) << 4) | ((data & 0xf0f0f0f0) >> 4))) return -EACCES; i -= 4; p += 8; } return 0;}static int loadfirmware(struct cmdif *cif, unsigned char *img, unsigned int size){ unsigned char *in; u32 laddr, saddr, t, val; int err = 0; laddr = saddr = 0; while (size > 0 && err == 0) { in = img; if (in[0] == ':') { t = atoh(&in[7], 2); switch (t) { case DATA_REC: err = senddata(cif, in, laddr + saddr); break; case EXT_SEG_ADDR_REC: saddr = atoh(&in[9], 4) << 4; break; case EXT_LIN_ADDR_REC: laddr = atoh(&in[9], 4) << 16; break; case EXT_GOTO_CMD_REC: val = atoh(&in[9], 8); if (SEND_GOTO(cif, val) != 0) err = -EACCES; break; case EXT_END_OF_FILE: size = 0; break; default: break; } while (size > 0) { size--; if (*img++ == '\n') break; } } } snd_printdd("load firmware return %d\n", err); return err;}static voidalloclbuspath(struct cmdif *cif, unsigned char source, unsigned char *path, unsigned char *mixer, unsigned char *s){ while (*path != 0xff) { unsigned char sink, type; sink = *path & (~SPLIT_PATH); if (sink != E2SINK_MAX) { snd_printdd("alloc path 0x%x->0x%x\n", source, sink); SEND_PSEL(cif, source, sink); source = lbusin2out[sink][0]; type = lbusin2out[sink][1]; if (type == LS_MIXER_IN) { if (mixer) *mixer = sink - DIGITAL_MIXER_IN0; } if (type == LS_SRC_DECIMATORM || type == LS_SRC_DECIMATOR || type == LS_SRC_INTERPOLATORM || type == LS_SRC_INTERPOLATOR) { if (s) { if (s[0] != 0xff) s[1] = sink; else s[0] = sink; } } } if (*path++ & SPLIT_PATH) { unsigned char *npath = path; while (*npath != 0xff) npath++; alloclbuspath(cif, source + 1, ++npath, mixer, s); } }}static voidfreelbuspath(struct cmdif *cif, unsigned char source, unsigned char *path){ while (*path != 0xff) { unsigned char sink; sink = *path & (~SPLIT_PATH); if (sink != E2SINK_MAX) { snd_printdd("free path 0x%x->0x%x\n", source, sink); SEND_PCLR(cif, source, sink); source = lbusin2out[sink][0]; } if (*path++ & SPLIT_PATH) { unsigned char *npath = path; while (*npath != 0xff) npath++; freelbuspath(cif, source + 1, ++npath); } }}static int writearm(struct cmdif *cif, u32 addr, u32 data, u32 mask){ union cmdret rptr = CMDRET_ZERO; unsigned int i = MAX_WRITE_RETRY; int flag = 1; SEND_RMEM(cif, 0x02, addr, &rptr); rptr.retlongs[0] &= (~mask); while (--i) { SEND_SMEM(cif, 0x01, addr); SEND_WMEM(cif, 0x02, (rptr.retlongs[0] | data)); SEND_RMEM(cif, 0x02, addr, &rptr); if ((rptr.retlongs[0] & data) == data) { flag = 0; break; } else rptr.retlongs[0] &= ~mask; } snd_printdd("send arm 0x%x 0x%x 0x%x return %d\n", addr, data, mask, flag); return flag;}static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm, union cmdret *ret){ int i, j; int err; unsigned int time = 0; unsigned long irqflags; struct riptideport *hwport; struct cmdport *cmdport = NULL; snd_assert(cif, return -EINVAL); hwport = cif->hwport; if (cif->errcnt > MAX_ERROR_COUNT) { if (cif->is_reset) { snd_printk(KERN_ERR "Riptide: Too many failed cmds, reinitializing\n"); if (riptide_reset(cif, NULL) == 0) { cif->errcnt = 0; return -EIO; } } snd_printk(KERN_ERR "Riptide: Initialization failed.\n"); return -EINVAL; } if (ret) { ret->retlongs[0] = 0; ret->retlongs[1] = 0; } i = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -