📄 omap2-audio-twl4030.c
字号:
if (ret) { printk(KERN_ERR "Setting Stereo mode failed[0x%x]\n", mode); } FN_OUT(ret); return ret;}/** * @brief twl4030_unconfigure */static void twl4030_unconfigure(void){ FN_IN; if (1 == twl4030_configured) { twl4030_codec_off(); twl4030_disable_output(); twl4030_disable_input(); } if (twl4030_configured > 0) twl4030_configured--; FN_OUT(0);}/** * @brief twl4030_cleanup - clean up the register settings * * @return 0 if successful */static int twl4030_cleanup(void){ int ret = 0; int line = 0; ret = audio_twl4030_write(REG_VRXPGA, 0x0); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_VDL_APGA_CTL, 0x0); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_BTPGA, 0x0); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_DTMF_FREQSEL, 0x0); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_DTMF_TONOFF, 0x0); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_DTMF_PGA_CTL2, 0x0); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_DTMF_PGA_CTL1, 0x0); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_DTMF_WANONOFF, 0x0); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_HS_POPN_SET, 0x0); if (ret) { line = __LINE__; goto cleanup_exit; } /* Shut down the voice and other paths completely */ ret = audio_twl4030_write(REG_ARXR1PGA, 0x0); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_ARXL1PGA, 0x0); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_ARXL1_APGA_CTL, 0x00); /*path1 */ if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_ARXR1_APGA_CTL, 0x00); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_ARXL2_APGA_CTL, 0x00); /*path1 */ if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_ARXR2_APGA_CTL, 0x00); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_ALC_CTL, 0x00); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_ARXL1PGA, 0x00); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_ARXR1PGA, 0x00); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_ARXL2PGA, 0x00); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_ARXR2PGA, 0x00); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_ATXL1PGA, 0x00); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_ATXR1PGA, 0x00); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_AVTXL2PGA, 0x00); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_AVTXR2PGA, 0x00); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_AVDAC_CTL, 0x00); if (ret) { line = __LINE__; goto cleanup_exit; } ret = audio_twl4030_write(REG_OPTION, 0); if (ret) { line = __LINE__; goto cleanup_exit; } cleanup_exit: if (ret) { printk(KERN_ERR "Cleanup Error[%d] Error in line %d\n", ret, line); } FN_OUT(ret); return (ret);}/** * @brief twl4030_configure * *NOTE* should be called with codec off * * @return 0 if successful */static int twl4030_configure(void){ int ret = 0; int line = 0; FN_IN; if (0 == twl4030_configured) { int data = 0; ret = twl4030_ext_mut_conf(); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_ext_mut_on(); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_cleanup(); if (ret) { line = __LINE__; goto configure_exit; } /* set up the codec_mode - use option 1 * - assume no voice path */ data = audio_twl4030_read(REG_CODEC_MODE); if (data < 0) { line = __LINE__; goto configure_exit; } ret = audio_twl4030_write(REG_CODEC_MODE, ((u8) data) | CODEC_OPTION_1 << BIT_CODEC_MODE_OPT_MODE); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_codec_conf_data_path(); if (ret) { line = __LINE__; goto configure_exit; } /* Select Rx path * SDRL1->RxL1 * SDRR1->RxR1 * SDRL2->RxL2 (mono SDRM2) * SDRL2->RxL2 (mono SDRM2) */ ret = audio_twl4030_write(REG_RX_PATH_SEL, ((current_stereomode == STEREO_MODE) ? 0x00 : BIT_RX_PATH_SEL_RXL2_SEL_M | BIT_RX_PATH_SEL_RXR2_SEL_M)); if (ret) { line = __LINE__; goto configure_exit; } /* set the gains - we do not know the defaults * attempt to set the volume of all the devices * only those enabled get set. */ ret = twl4030_setvolume(OUTPUT_VOLUME, READ_LEFT_VOLUME (twl4030_local.play_volume), READ_RIGHT_VOLUME (twl4030_local.play_volume)); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_setvolume(OUTPUT_STEREO_HEADSET, READ_LEFT_VOLUME(twl4030_local.hset), READ_RIGHT_VOLUME(twl4030_local.hset)); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_setvolume(OUTPUT_HANDS_FREE_CLASSD, READ_LEFT_VOLUME(twl4030_local.classd), READ_RIGHT_VOLUME(twl4030_local.classd)); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_setvolume(OUTPUT_MONO_EARPIECE, READ_LEFT_VOLUME(twl4030_local.ear), 0); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_setvolume(OUTPUT_SIDETONE, READ_LEFT_VOLUME (twl4030_local.sidetone), 0); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_setvolume(OUTPUT_CARKIT, READ_LEFT_VOLUME (twl4030_local.carkit_out), READ_RIGHT_VOLUME (twl4030_local.carkit_out)); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_setvolume(INPUT_VOLUME, READ_LEFT_VOLUME (twl4030_local.rec_volume), READ_RIGHT_VOLUME (twl4030_local.rec_volume)); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_setvolume(INPUT_HEADSET_MIC, READ_LEFT_VOLUME(twl4030_local.line), READ_RIGHT_VOLUME(twl4030_local.line)); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_setvolume(INPUT_MAIN_MIC, READ_LEFT_VOLUME(twl4030_local.mic), 0); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_setvolume(INPUT_SUB_MIC, 0, READ_RIGHT_VOLUME(twl4030_local.mic)); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_setvolume(INPUT_AUX, READ_LEFT_VOLUME(twl4030_local.aux), READ_RIGHT_VOLUME(twl4030_local.aux)); if (ret) { line = __LINE__; goto configure_exit; } ret = twl4030_setvolume(INPUT_CARKIT, READ_LEFT_VOLUME (twl4030_local.carkit_in), 0); if (ret) { line = __LINE__; goto configure_exit; } /* Do not bypass the high pass filters */ ret = audio_twl4030_write(REG_MISC_SET_2, 0x0); if (ret) { line = __LINE__; goto configure_exit; } /* switch on the input required */ if (!(twl4030_disable_output())) { ret = twl4030_enable_output(); if (ret) { line = __LINE__; goto configure_exit; } } if (!(twl4030_disable_input())) { ret = twl4030_enable_input(); if (ret) { line = __LINE__; goto configure_exit; } } } twl4030_configured++; configure_exit: if (ret) { printk(KERN_ERR "Configuration Error[%d] Error in line %d\n", ret, line); } FN_OUT(ret); return ret;}/** * @brief twl4030_mcbsp_dma_cb - the mcbsp call back * * @param ch_status - dma channel status value * @param arg - the stream_callback structure */static void twl4030_mcbsp_dma_cb(u16 ch_status, void *arg){ if (ch_status) { printk(KERN_ERR "Error happend[%d 0x%x]!!\n", ch_status, ch_status); return; } audio_period_handler(arg); FN_OUT(0);}/**************** ************** * ***************************** CODEC APIS ****************************** * *//** * @brief omap_twl4030_transfer [hw_transfer] * - Do the transfer to a said stream * @param s - stream for which the transfer occurs * @param buffer_phy - the physical address of the buffer * @param size - num bytes to transfer * * @return 0 if success else return value -EBUSY implies retry later.. */static int omap_twl4030_transfer(int mode, void *buffer_phy, u32 size, void *arg){ int ret = 0; int restart = 0; FN_IN; /* Error Recovery Strategy - * 1. stop codec * 2. stop mcbsp tx/rx * 3. stop dma tx/rx * --- * Restart: * 1. send/recievedata (starts mcbsp,dma) * 2. start codec */ if (mcbsp_interface_acquired > 0) { if (mode == SNDRV_PCM_STREAM_CAPTURE) { DPRINTK("RX-%d", size); /* Capture Path to be implemented */ if (rx_err) { rx_err = 0; } ret = omap2_mcbsp_receive_data(AUDIO_MCBSP, arg, (dma_addr_t) buffer_phy, size); DPRINTK("rx-%d\n", ret); } else { DPRINTK("TX-%d", size); if (tx_err) { tx_err = 0; } ret = omap2_mcbsp_send_data(AUDIO_MCBSP, arg, (dma_addr_t) buffer_phy, size); } if (restart) { twl4030_codec_on(); twl4030_ext_mut_off(); } } FN_OUT(ret); return ret;}/** * @brief omap_twl4030_transfer_stop [hw_transfer_stop] * - Stop Transfers on the current stream * @param s - stream for which the transfer occurs * * @return 0 if success else return value */static int omap_twl4030_transfer_stop(int mode){ int ret = 0; FN_IN; if (mcbsp_interface_acquired > 0) { if (mode == SNDRV_PCM_STREAM_CAPTURE) { ret = omap2_mcbsp_stop_datarx(AUDIO_MCBSP); (void)omap2_mcbsp_set_rrst(AUDIO_MCBSP, OMAP2_MCBSP_RRST_DISABLE); } else { ret = omap2_mcbsp_stop_datatx(AUDIO_MCBSP); (void)omap2_mcbsp_set_xrst(AUDIO_MCBSP, OMAP2_MCBSP_XRST_DISABLE); } } FN_OUT(ret); return ret;}static inline int element_size(int mcbsp_wordlen){ if (mcbsp_wordlen == OMAP2_MCBSP_WORDLEN_32) return 4; if (mcbsp_wordlen == OMAP2_MCBSP_WORDLEN_16) return 2; /* we don't allow any other word lengths */ return -1;}/** * @brief omap_twl4030_transfer_posn [hw_transfer_posn] * - Where am i? * @param s - stream for which the transfer occurs * * @return posn of the transfer */static int omap_twl4030_transfer_posn(int mode){ int ret = 0; int fi, ei; FN_IN; /* we always ask only one frame to transmit/recieve, * variant is the element num */ if (mcbsp_interface_acquired > 0) { if (mode == SNDRV_PCM_STREAM_CAPTURE) { ret = omap2_mcbsp_receiver_index(AUDIO_MCBSP, &ei, &fi); ret = ei * element_size(plat_mcbsp_config.rx_params.word_length1); } else { ret = omap2_mcbsp_transmitter_index(AUDIO_MCBSP, &ei, &fi); ret = ei * element_size(plat_mcbsp_config.tx_params.word_length1); } if (ret < 0) { printk(KERN_ERR "twl4030_transfer_posn: Unable to find index of " "transfer\n"); } } FN_OUT(ret); return ret;}/** * @brief omap_twl4030_transfer_init [hw_transfer_init] * - initialize the current stream * @param state -codec state for which this transfer is to be done * @param s - stream for which the transfer occurs * @param callback - call me back when I am done with the transfer * * @return 0 if success else return value */static int omap_twl4030_transfer_init(int mode){ int ret = 0; FN_IN;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -