📄 cs4231.c
字号:
READ_IDR(); WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x1c); tmp_bits = READ_IDR(); WRITE_IDR(CHANGE_DFR(tmp_bits, set_bits)); READ_IDR(); READ_IDR(); CHIP_READY(); cs4231_chip->perchip_info.record.sample_rate = value; return 0; } } dprintk(("input rate failed\n")); return -EINVAL;}static int cs4231_get_input_rate(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.record.sample_rate;}/* Generically we support 4 channels. This hardware does 2 */static int cs4231_set_input_channels(struct sparcaudio_driver *drv, int value){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; int tmp_bits; tprintk(("input channels %d\n", value)); WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x1c); tmp_bits = READ_IDR(); switch (value) { case 1: WRITE_IDR(CS4231_MONO_ON(tmp_bits)); break; case 2: WRITE_IDR(CS4231_STEREO_ON(tmp_bits)); break; default: dprintk(("input chan failed\n")); return -EINVAL; }; CHIP_READY(); cs4231_chip->perchip_info.record.channels = value; return 0;}static int cs4231_get_input_channels(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.record.channels;}/* Generically we support 4 channels. This hardware does 2 */static int cs4231_set_output_channels(struct sparcaudio_driver *drv, int value){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; int tmp_bits; tprintk(("output channels %d\n", value)); WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x8); tmp_bits = READ_IDR(); switch (value) { case 1: WRITE_IDR(CS4231_MONO_ON(tmp_bits)); break; case 2: WRITE_IDR(CS4231_STEREO_ON(tmp_bits)); break; default: dprintk(("output chan failed\n")); return -EINVAL; }; CHIP_READY(); cs4231_chip->perchip_info.play.channels = value; return 0;}static int cs4231_get_output_channels(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.play.channels;}static int cs4231_get_input_precision(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.record.precision;}static int cs4231_get_output_precision(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.play.precision;}static int cs4231_set_input_precision(struct sparcaudio_driver *drv, int val){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; cs4231_chip->perchip_info.record.precision = val; return cs4231_chip->perchip_info.record.precision;}static int cs4231_set_output_precision(struct sparcaudio_driver *drv, int val){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; cs4231_chip->perchip_info.play.precision = val; return cs4231_chip->perchip_info.play.precision;}/* Wait until the auto calibration process has finished */static void cs4231_ready(struct sparcaudio_driver *drv) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; unsigned int x; WRITE_IAR(IAR_AUTOCAL_END); x = 0; do { if (READ_IDR() != IAR_NOT_READY) break; x++; } while (x <= CS_TIMEOUT); WRITE_IAR(0x0b); x = 0; do { if (READ_IDR() != AUTOCAL_IN_PROGRESS) break; x++; } while (x <= CS_TIMEOUT);}/* Set output mute */static int cs4231_output_muted(struct sparcaudio_driver *drv, int value){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; tprintk(("in cs4231_output_muted: %d\n", value)); if (!value) { WRITE_IAR(0x7); WRITE_IDR(READ_IDR() & OUTCR_UNMUTE); WRITE_IAR(0x6); WRITE_IDR(READ_IDR() & OUTCR_UNMUTE); cs4231_chip->perchip_info.output_muted = 0; } else { WRITE_IAR(0x7); WRITE_IDR(READ_IDR() | OUTCR_MUTE); WRITE_IAR(0x6); WRITE_IDR(READ_IDR() | OUTCR_MUTE); cs4231_chip->perchip_info.output_muted = 1; } return 0;}static int cs4231_get_output_muted(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.output_muted;}static int cs4231_get_formats(struct sparcaudio_driver *drv){ return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_U8 | AFMT_IMA_ADPCM | AFMT_S16_LE | AFMT_S16_BE);}static int cs4231_get_output_ports(struct sparcaudio_driver *drv){ return (AUDIO_LINE_OUT | AUDIO_SPEAKER | AUDIO_HEADPHONE);}static int cs4231_get_input_ports(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; /* This apparently applies only to APC ultras, not ebus ultras */ if (cs4231_chip->status & CS_STATUS_IS_ULTRA) return (AUDIO_LINE_IN | AUDIO_MICROPHONE | AUDIO_ANALOG_LOOPBACK); else return (AUDIO_INTERNAL_CD_IN | AUDIO_LINE_IN | AUDIO_MICROPHONE | AUDIO_ANALOG_LOOPBACK);}/* Set chip "output" port */static int cs4231_set_output_port(struct sparcaudio_driver *drv, int value){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; int retval = 0; tprintk(("output port: %d\n", value)); /* Aaaaaah! It's all coming so fast! Turn it all off, then selectively * enable things. */ WRITE_IAR(0x1a); WRITE_IDR(READ_IDR() | MONO_IOCR_MUTE); WRITE_IAR(0x0a); WRITE_IDR(READ_IDR() | PINCR_LINE_MUTE); WRITE_IDR(READ_IDR() | PINCR_HDPH_MUTE); if (value & AUDIO_SPEAKER) { WRITE_IAR(0x1a); WRITE_IDR(READ_IDR() & ~MONO_IOCR_MUTE); retval |= AUDIO_SPEAKER; } if (value & AUDIO_HEADPHONE) { WRITE_IAR(0x0a); WRITE_IDR(READ_IDR() & ~PINCR_HDPH_MUTE); retval |= AUDIO_HEADPHONE; } if (value & AUDIO_LINE_OUT) { WRITE_IAR(0x0a); WRITE_IDR(READ_IDR() & ~PINCR_LINE_MUTE); retval |= AUDIO_LINE_OUT; } cs4231_chip->perchip_info.play.port = retval; return (retval);}static int cs4231_get_output_port(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.play.port;}/* Set chip "input" port */static int cs4231_set_input_port(struct sparcaudio_driver *drv, int value){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; int retval = 0; tprintk(("input port: %d\n", value)); /* You can have one and only one. This is probably wrong, but * appears to be how SunOS is doing it. Should be able to mix. * More work to be done. CD input mixable, analog loopback may be. */ /* Ultra systems do not support AUDIO_INTERNAL_CD_IN */ /* This apparently applies only to APC ultras, not ebus ultras */ if (!(cs4231_chip->status & CS_STATUS_IS_ULTRA)) { if (value & AUDIO_INTERNAL_CD_IN) { WRITE_IAR(0x1); WRITE_IDR(CDROM_ENABLE(READ_IDR())); WRITE_IAR(0x0); WRITE_IDR(CDROM_ENABLE(READ_IDR())); retval = AUDIO_INTERNAL_CD_IN; } } if ((value & AUDIO_LINE_IN)) { WRITE_IAR(0x1); WRITE_IDR(LINE_ENABLE(READ_IDR())); WRITE_IAR(0x0); WRITE_IDR(LINE_ENABLE(READ_IDR())); retval = AUDIO_LINE_IN; } else if (value & AUDIO_MICROPHONE) { WRITE_IAR(0x1); WRITE_IDR(MIC_ENABLE(READ_IDR())); WRITE_IAR(0x0); WRITE_IDR(MIC_ENABLE(READ_IDR())); retval = AUDIO_MICROPHONE; } else if (value & AUDIO_ANALOG_LOOPBACK) { WRITE_IAR(0x1); WRITE_IDR(OUTPUTLOOP_ENABLE(READ_IDR())); WRITE_IAR(0x0); WRITE_IDR(OUTPUTLOOP_ENABLE(READ_IDR())); retval = AUDIO_ANALOG_LOOPBACK; } cs4231_chip->perchip_info.record.port = retval; return retval;}static int cs4231_get_input_port(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.record.port;}/* Set chip "monitor" gain */static int cs4231_set_monitor_volume(struct sparcaudio_driver *drv, int value){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; int a = 0; tprintk(("monitor gain: %d\n", value)); /* This interpolation really sucks. The question is, be compatible * with ScumOS/Sloaris or not? */ a = CS4231_MON_MAX_ATEN - (value * (CS4231_MON_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1)); WRITE_IAR(0x0d); if (a >= CS4231_MON_MAX_ATEN) WRITE_IDR(LOOPB_OFF); else WRITE_IDR((a << 2) | LOOPB_ON); if (value == AUDIO_MAX_GAIN) cs4231_chip->perchip_info.monitor_gain = AUDIO_MAX_GAIN; else cs4231_chip->perchip_info.monitor_gain = ((CS4231_MAX_DEV_ATEN - a) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_DEV_ATEN + 1)); return 0;}static int cs4231_get_monitor_volume(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return (int) cs4231_chip->perchip_info.monitor_gain;}static int cs4231_get_output_error(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return (int) cs4231_chip->perchip_info.play.error;}static int cs4231_get_input_error(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return (int) cs4231_chip->perchip_info.record.error;}#ifdef EB4231_SUPPORTstatic int eb4231_get_output_samples(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; u32 dbcr = readl(cs4231_chip->eb2p + EBDMA_COUNT); int count = cs4231_length_to_samplecount(&cs4231_chip->perchip_info.play, dbcr); return (cs4231_chip->perchip_info.play.samples - ((count > cs4231_chip->perchip_info.play.samples) ? 0 : count));}static int eb4231_get_input_samples(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; u32 dbcr = readl(cs4231_chip->eb2c + EBDMA_COUNT); int count = cs4231_length_to_samplecount(&cs4231_chip->perchip_info.record, dbcr); return (cs4231_chip->perchip_info.record.samples - ((count > cs4231_chip->perchip_info.record.samples) ? 0 : count));}#endifstatic int cs4231_get_output_samples(struct sparcaudio_driver *drv){ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; u32 dmapc = sbus_readl(cs4231_chip->regs + APCPC); int count = cs4231_length_to_samplecount(&cs4231_chip->perchip_info.play, dmapc); return (cs4231_chip->perchip_info.play.samples - ((count > cs4231_chip->perchip_info.play.samples) ? 0 : count));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -