📄 au88x0_a3d.c
字号:
((((a->slice) << 0xb) + i) << 2), 0);}/* Reset Single A3D source. */static void a3dsrc_ZeroState(a3dsrc_t * a){ //printk("vortex: ZeroState slice: %d, source %d\n", a->slice, a->source); a3dsrc_SetAtmosState(a, 0, 0, 0, 0); a3dsrc_SetHrtfState(a, A3dHrirZeros, A3dHrirZeros); a3dsrc_SetItdDline(a, A3dItdDlineZeros); a3dsrc_SetHrtfOutput(a, 0, 0); a3dsrc_SetTimeConsts(a, 0, 0, 0, 0); a3dsrc_SetAtmosCurrent(a, 0, 0, 0, 0, 0); a3dsrc_SetAtmosTarget(a, 0, 0, 0, 0, 0); a3dsrc_SetItdCurrent(a, 0, 0); a3dsrc_SetItdTarget(a, 0, 0); a3dsrc_SetGainCurrent(a, 0, 0); a3dsrc_SetGainTarget(a, 0, 0); a3dsrc_SetHrtfCurrent(a, A3dHrirZeros, A3dHrirZeros); a3dsrc_SetHrtfTarget(a, A3dHrirZeros, A3dHrirZeros);}/* Reset entire A3D engine */static void a3dsrc_ZeroStateA3D(a3dsrc_t * a){ int i, var, var2; if ((a->vortex) == NULL) { printk(KERN_ERR "vortex: ZeroStateA3D: ERROR: a->vortex is NULL\n"); return; } a3dsrc_SetA3DControlReg(a, 0); a3dsrc_SetA3DPointerReg(a, 0); var = a->slice; var2 = a->source; for (i = 0; i < 4; i++) { a->slice = i; a3dsrc_ZeroSliceIO(a); //a3dsrc_ZeroState(a); } a->source = var2; a->slice = var;}/* Program A3D block as pass through */static void a3dsrc_ProgramPipe(a3dsrc_t * a){ a3dsrc_SetTimeConsts(a, 0, 0, 0, 0); a3dsrc_SetAtmosCurrent(a, 0, 0x4000, 0, 0, 0); a3dsrc_SetAtmosTarget(a, 0x4000, 0, 0, 0, 0); a3dsrc_SetItdCurrent(a, 0, 0); a3dsrc_SetItdTarget(a, 0, 0); a3dsrc_SetGainCurrent(a, 0x7fff, 0x7fff); a3dsrc_SetGainTarget(a, 0x7fff, 0x7fff); /* SET HRTF HERE */ /* Single spike leads to identity transfer function. */ a3dsrc_SetHrtfCurrent(a, A3dHrirImpulse, A3dHrirImpulse); a3dsrc_SetHrtfTarget(a, A3dHrirImpulse, A3dHrirImpulse); /* Test: Sounds saturated. */ //a3dsrc_SetHrtfCurrent(a, A3dHrirSatTest, A3dHrirSatTest); //a3dsrc_SetHrtfTarget(a, A3dHrirSatTest, A3dHrirSatTest); }/* VDB = Vortex audio Dataflow Bus */#if 0static void a3dsrc_ClearVDBData(a3dsrc_t * a, unsigned long aa){ vortex_t *vortex = (vortex_t *) (a->vortex); // ((aa >> 2) << 8) - (aa >> 2) hwwrite(vortex->mmio, a3d_addrS(a->slice, A3D_SLICE_VDBDest) + (a->source << 2), 0); hwwrite(vortex->mmio, a3d_addrS(a->slice, A3D_SLICE_VDBDest + 4) + (a->source << 2), 0); /* hwwrite(vortex->mmio, 0x19c00 + (((aa>>2)*255*4)+aa)*8, 0); hwwrite(vortex->mmio, 0x19c04 + (((aa>>2)*255*4)+aa)*8, 0); */}#endif/* A3D HwSource stuff. */static void vortex_A3dSourceHw_Initialize(vortex_t * v, int source, int slice){ a3dsrc_t *a3dsrc = &(v->a3d[source + (slice * 4)]); //a3dsrc_t *a3dsrc = &(v->a3d[source + (slice*4)]); a3dsrc->vortex = (void *)v; a3dsrc->source = source; /* source */ a3dsrc->slice = slice; /* slice */ a3dsrc_ZeroState(a3dsrc); /* Added by me. */ a3dsrc_SetA3DSampleRate(a3dsrc, 0x11);}static int Vort3DRend_Initialize(vortex_t * v, unsigned short mode){ v->xt_mode = mode; /* this_14 */ vortex_XtalkHw_init(v); vortex_XtalkHw_SetGainsAllChan(v); switch (v->xt_mode) { case XT_SPEAKER0: vortex_XtalkHw_ProgramXtalkNarrow(v); break; case XT_SPEAKER1: vortex_XtalkHw_ProgramXtalkWide(v); break; default: case XT_HEADPHONE: vortex_XtalkHw_ProgramPipe(v); break; case XT_DIAMOND: vortex_XtalkHw_ProgramDiamondXtalk(v); break; } vortex_XtalkHw_SetSampleRate(v, 0x11); vortex_XtalkHw_Enable(v); return 0;}/* 3D Sound entry points. */static int vortex_a3d_register_controls(vortex_t * vortex);static void vortex_a3d_unregister_controls(vortex_t * vortex);/* A3D base support init/shudown */static void vortex_Vort3D(vortex_t * v, int en){ int i; if (en) { Vort3DRend_Initialize(v, XT_HEADPHONE); for (i = 0; i < NR_A3D; i++) { vortex_A3dSourceHw_Initialize(v, i % 4, i >> 2); a3dsrc_ZeroStateA3D(&(v->a3d[0])); } } else { vortex_XtalkHw_Disable(v); } /* Register ALSA controls */ if (en) { vortex_a3d_register_controls(v); } else { vortex_a3d_unregister_controls(v); }}/* Make A3D subsystem connections. */static void vortex_Vort3D_connect(vortex_t * v, int en){ int i; // Disable AU8810 routes, since they seem to be wrong (in au8810.h).#ifdef CHIP_AU8810 return;#endif #if 1 /* Alloc Xtalk mixin resources */ v->mixxtlk[0] = vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN); if (v->mixxtlk[0] < 0) { printk ("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n"); return; } v->mixxtlk[1] = vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN); if (v->mixxtlk[1] < 0) { printk ("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n"); return; }#endif /* Connect A3D -> XTALK */ for (i = 0; i < 4; i++) { // 2 outputs per each A3D slice. vortex_route(v, en, 0x11, ADB_A3DOUT(i * 2), ADB_XTALKIN(i)); vortex_route(v, en, 0x11, ADB_A3DOUT(i * 2) + 1, ADB_XTALKIN(5 + i)); }#if 0 vortex_route(v, en, 0x11, ADB_XTALKOUT(0), ADB_EQIN(2)); vortex_route(v, en, 0x11, ADB_XTALKOUT(1), ADB_EQIN(3));#else /* Connect XTalk -> mixer */ vortex_route(v, en, 0x11, ADB_XTALKOUT(0), ADB_MIXIN(v->mixxtlk[0])); vortex_route(v, en, 0x11, ADB_XTALKOUT(1), ADB_MIXIN(v->mixxtlk[1])); vortex_connection_mixin_mix(v, en, v->mixxtlk[0], v->mixplayb[0], 0); vortex_connection_mixin_mix(v, en, v->mixxtlk[1], v->mixplayb[1], 0); vortex_mix_setinputvolumebyte(v, v->mixplayb[0], v->mixxtlk[0], en ? MIX_DEFIGAIN : VOL_MIN); vortex_mix_setinputvolumebyte(v, v->mixplayb[1], v->mixxtlk[1], en ? MIX_DEFIGAIN : VOL_MIN); if (VORTEX_IS_QUAD(v)) { vortex_connection_mixin_mix(v, en, v->mixxtlk[0], v->mixplayb[2], 0); vortex_connection_mixin_mix(v, en, v->mixxtlk[1], v->mixplayb[3], 0); vortex_mix_setinputvolumebyte(v, v->mixplayb[2], v->mixxtlk[0], en ? MIX_DEFIGAIN : VOL_MIN); vortex_mix_setinputvolumebyte(v, v->mixplayb[3], v->mixxtlk[1], en ? MIX_DEFIGAIN : VOL_MIN); }#endif}/* Initialize one single A3D source. */static void vortex_Vort3D_InitializeSource(a3dsrc_t * a, int en){ if (a->vortex == NULL) { printk ("vortex: Vort3D_InitializeSource: A3D source not initialized\n"); return; } if (en) { a3dsrc_ProgramPipe(a); a3dsrc_SetA3DSampleRate(a, 0x11); a3dsrc_SetTimeConsts(a, HrtfTCDefault, ItdTCDefault, GainTCDefault, CoefTCDefault); /* Remark: zero gain is muted. */ //a3dsrc_SetGainTarget(a,0,0); //a3dsrc_SetGainCurrent(a,0,0); a3dsrc_EnableA3D(a); } else { a3dsrc_DisableA3D(a); a3dsrc_ZeroState(a); }}/* Conversion of coordinates into 3D parameters. */static void vortex_a3d_coord2hrtf(a3d_Hrtf_t hrtf, int *coord){ /* FIXME: implement this. */}static void vortex_a3d_coord2itd(a3d_Itd_t itd, int *coord){ /* FIXME: implement this. */}static void vortex_a3d_coord2ild(a3d_LRGains_t ild, int left, int right){ /* FIXME: implement this. */}static void vortex_a3d_translate_filter(a3d_atmos_t filter, int *params){ /* FIXME: implement this. */}/* ALSA control interface. */static intsnd_vortex_a3d_hrtf_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 6; uinfo->value.integer.min = 0x00000000; uinfo->value.integer.max = 0xffffffff; return 0;}static intsnd_vortex_a3d_itd_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0x00000000; uinfo->value.integer.max = 0xffffffff; return 0;}static intsnd_vortex_a3d_ild_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0x00000000; uinfo->value.integer.max = 0xffffffff; return 0;}static intsnd_vortex_a3d_filter_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 4; uinfo->value.integer.min = 0x00000000; uinfo->value.integer.max = 0xffffffff; return 0;}static intsnd_vortex_a3d_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ //a3dsrc_t *a = kcontrol->private_data; /* No read yet. Would this be really useable/needed ? */ return 0;}static intsnd_vortex_a3d_hrtf_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ a3dsrc_t *a = kcontrol->private_data; int changed = 1, i; int coord[6]; for (i = 0; i < 6; i++) coord[i] = ucontrol->value.integer.value[i]; /* Translate orientation coordinates to a3d params. */ vortex_a3d_coord2hrtf(a->hrtf[0], coord); vortex_a3d_coord2hrtf(a->hrtf[1], coord); a3dsrc_SetHrtfTarget(a, a->hrtf[0], a->hrtf[1]); a3dsrc_SetHrtfCurrent(a, a->hrtf[0], a->hrtf[1]); return changed;}static intsnd_vortex_a3d_itd_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ a3dsrc_t *a = kcontrol->private_data; int coord[6]; int i, changed = 1; for (i = 0; i < 6; i++) coord[i] = ucontrol->value.integer.value[i]; /* Translate orientation coordinates to a3d params. */ vortex_a3d_coord2itd(a->hrtf[0], coord); vortex_a3d_coord2itd(a->hrtf[1], coord); /* Inter aural time difference. */ a3dsrc_SetItdTarget(a, a->itd[0], a->itd[1]); a3dsrc_SetItdCurrent(a, a->itd[0], a->itd[1]); a3dsrc_SetItdDline(a, a->dline); return changed;}static intsnd_vortex_a3d_ild_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ a3dsrc_t *a = kcontrol->private_data; int changed = 1; int l, r; /* There may be some scale tranlation needed here. */ l = ucontrol->value.integer.value[0]; r = ucontrol->value.integer.value[1]; vortex_a3d_coord2ild(a->ild, l, r); /* Left Right panning. */ a3dsrc_SetGainTarget(a, l, r); a3dsrc_SetGainCurrent(a, l, r); return changed;}static intsnd_vortex_a3d_filter_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ a3dsrc_t *a = kcontrol->private_data; int i, changed = 1; int params[6]; for (i = 0; i < 6; i++) params[i] = ucontrol->value.integer.value[i]; /* Translate generic filter params to a3d filter params. */ vortex_a3d_translate_filter(a->filter, params); /* Atmospheric absorbtion and filtering. */ a3dsrc_SetAtmosTarget(a, a->filter[0], a->filter[1], a->filter[2], a->filter[3], a->filter[4]); a3dsrc_SetAtmosCurrent(a, a->filter[0], a->filter[1], a->filter[2], a->filter[3], a->filter[4]); return changed;}static snd_kcontrol_new_t vortex_a3d_kcontrol __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = "Playback PCM advanced processing", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = snd_vortex_a3d_hrtf_info, .get = snd_vortex_a3d_get, .put = snd_vortex_a3d_hrtf_put,};/* Control (un)registration. */static int vortex_a3d_register_controls(vortex_t * vortex){ snd_kcontrol_t *kcontrol; int err, i; /* HRTF controls. */ for (i = 0; i < NR_A3D; i++) { if ((kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) return -ENOMEM; kcontrol->id.numid = CTRLID_HRTF; kcontrol->info = snd_vortex_a3d_hrtf_info; kcontrol->put = snd_vortex_a3d_hrtf_put; if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) return err; } /* ITD controls. */ for (i = 0; i < NR_A3D; i++) { if ((kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) return -ENOMEM; kcontrol->id.numid = CTRLID_ITD; kcontrol->info = snd_vortex_a3d_itd_info; kcontrol->put = snd_vortex_a3d_itd_put; if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) return err; } /* ILD (gains) controls. */ for (i = 0; i < NR_A3D; i++) { if ((kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) return -ENOMEM; kcontrol->id.numid = CTRLID_GAINS; kcontrol->info = snd_vortex_a3d_ild_info; kcontrol->put = snd_vortex_a3d_ild_put; if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) return err; } /* Filter controls. */ for (i = 0; i < NR_A3D; i++) { if ((kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) return -ENOMEM; kcontrol->id.numid = CTRLID_FILTER; kcontrol->info = snd_vortex_a3d_filter_info; kcontrol->put = snd_vortex_a3d_filter_put; if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) return err; } return 0;}static void vortex_a3d_unregister_controls(vortex_t * vortex){}/* End of File*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -