int i2s_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) #endif { int i ; unsigned long flags, data; i2s_config_type* ptri2s_config; ptri2s_config = filp->private_data; switch (cmd) { case I2S_SRATE: spin_lock_irqsave(&ptri2s_config->lock, flags); { data = *(unsigned long*)(RALINK_SYSCTL_BASE+0x834); data |=(1<<17); *(unsigned long*)(RALINK_SYSCTL_BASE+0x834) = data; data = *(unsigned long*)(RALINK_SYSCTL_BASE+0x834); data &=~(1<<17); *(unsigned long*)(RALINK_SYSCTL_BASE+0x834) = data; audiohw_preinit(); } if((arg>MAX_SRATE_HZ)||(arg<MIN_SRATE_HZ)) { MSG("audio sampling rate %u should be %d ~ %d Hz\n", (u32)arg, MIN_SRATE_HZ, MAX_SRATE_HZ); break; } ptri2s_config->srate = arg; MSG("set audio sampling rate to %d Hz\n", ptri2s_config->srate); spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_TX_VOL: spin_lock_irqsave(&ptri2s_config->lock, flags); if((int)arg > 127) { ptri2s_config->txvol = 127; } else if((int)arg < 96) { ptri2s_config->txvol = 96; } else ptri2s_config->txvol = arg; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_RX_VOL: spin_lock_irqsave(&ptri2s_config->lock, flags); if((int)arg > 63) { ptri2s_config->rxvol = 63; } else if((int)arg < 0) { ptri2s_config->rxvol = 0; } else ptri2s_config->rxvol = arg; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_TX_ENABLE: spin_lock_irqsave(&ptri2s_config->lock, flags); MSG("I2S_TXENABLE\n"); /* allocate tx buffer */ ptri2s_config->pPage0TxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE*2 , &i2s_txdma_addr); if(ptri2s_config->pPage0TxBuf8ptr==NULL) { MSG("Allocate Tx Page Buffer Failed\n"); return -1; } ptri2s_config->pPage1TxBuf8ptr = ptri2s_config->pPage0TxBuf8ptr + I2S_PAGE_SIZE; for( i = 0 ; i < MAX_I2S_PAGE ; i ++ ) { #if defined(CONFIG_I2S_MMAP) ptri2s_config->pMMAPTxBufPtr[i] = ptri2s_config->pMMAPBufPtr[i]; #else if(ptri2s_config->pMMAPTxBufPtr[i]==NULL) ptri2s_config->pMMAPTxBufPtr[i] = kmalloc(I2S_PAGE_SIZE, GFP_KERNEL); #endif } #if defined(I2S_FIFO_MODE) #else GdmaI2sTx((u32)ptri2s_config->pPage0TxBuf8ptr, I2S_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); GdmaI2sTx((u32)ptri2s_config->pPage1TxBuf8ptr, I2S_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); #endif i2s_reset_tx_config(ptri2s_config); ptri2s_config->bTxDMAEnable = 1; i2s_tx_config(ptri2s_config); if(ptri2s_config->bRxDMAEnable==0) i2s_clock_enable(ptri2s_config); audiohw_set_lineout_vol(1, ptri2s_config->txvol, ptri2s_config->txvol); i2s_tx_enable(ptri2s_config); #if defined(I2S_FIFO_MODE) #else GdmaUnMaskChannel(GDMA_I2S_TX0); #endif data = i2s_inw(RALINK_REG_INTENA); data |=0x0400; i2s_outw(RALINK_REG_INTENA, data); MSG("I2S_TXENABLE done\n"); spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_TX_DISABLE: spin_lock_irqsave(&ptri2s_config->lock, flags); MSG("I2S_TXDISABLE\n"); i2s_tx_disable(ptri2s_config); i2s_reset_tx_config(ptri2s_config); if(ptri2s_config->bRxDMAEnable==0) i2s_clock_disable(ptri2s_config); //i2s_tx_disable(ptri2s_config); if(ptri2s_config->bRxDMAEnable==0) { data = i2s_inw(RALINK_REG_INTENA); data &= 0xFFFFFBFF; i2s_outw(RALINK_REG_INTENA, data); } for( i = 0 ; i < MAX_I2S_PAGE ; i ++ ) { if(ptri2s_config->pMMAPTxBufPtr[i] != NULL) { #if defined(CONFIG_I2S_MMAP) dma_unmap_single(NULL, i2s_mmap_addr[i], I2S_PAGE_SIZE, DMA_TO_DEVICE); #endif kfree(ptri2s_config->pMMAPTxBufPtr[i]); ptri2s_config->pMMAPTxBufPtr[i] = NULL; } } pci_free_consistent(NULL, I2S_PAGE_SIZE*2, ptri2s_config->pPage0TxBuf8ptr, i2s_txdma_addr); ptri2s_config->pPage0TxBuf8ptr = NULL; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_RX_ENABLE: spin_lock_irqsave(&ptri2s_config->lock, flags); MSG("I2S_RXENABLE\n"); /* allocate rx buffer */ ptri2s_config->pPage0RxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE*2 , &i2s_rxdma_addr); if(ptri2s_config->pPage0RxBuf8ptr==NULL) { MSG("Allocate Rx Page Buffer Failed\n"); return -1; } ptri2s_config->pPage1RxBuf8ptr = ptri2s_config->pPage0RxBuf8ptr + I2S_PAGE_SIZE; for( i = 0 ; i < MAX_I2S_PAGE ; i ++ ) { if(ptri2s_config->pMMAPRxBufPtr[i]==NULL) ptri2s_config->pMMAPRxBufPtr[i] = kmalloc(I2S_PAGE_SIZE, GFP_KERNEL); } #if defined(I2S_FIFO_MODE) #else GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)ptri2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_unmask_handler); GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)ptri2s_config->pPage1RxBuf8ptr, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_unmask_handler); #endif i2s_reset_rx_config(ptri2s_config); ptri2s_config->bRxDMAEnable = 1; i2s_rx_config(ptri2s_config); #if defined(I2S_FIFO_MODE) #else GdmaUnMaskChannel(GDMA_I2S_RX0); #endif if(ptri2s_config->bTxDMAEnable==0) i2s_clock_enable(ptri2s_config); #if defined(CONFIG_I2S_TXRX) audiohw_set_linein_vol(ptri2s_config->rxvol, ptri2s_config->rxvol); #endif i2s_rx_enable(ptri2s_config); data = i2s_inw(RALINK_REG_INTENA); data |=0x0400; i2s_outw(RALINK_REG_INTENA, data); spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_RX_DISABLE: spin_lock_irqsave(&ptri2s_config->lock, flags); MSG("I2S_RXDISABLE\n"); i2s_reset_rx_config(ptri2s_config); if(ptri2s_config->bTxDMAEnable==0) i2s_clock_disable(ptri2s_config); i2s_rx_disable(ptri2s_config); if(ptri2s_config->bRxDMAEnable==0) { data = i2s_inw(RALINK_REG_INTENA); data &= 0xFFFFFBFF; i2s_outw(RALINK_REG_INTENA, data); } for( i = 0 ; i < MAX_I2S_PAGE ; i ++ ) { if(ptri2s_config->pMMAPRxBufPtr[i] != NULL) kfree(ptri2s_config->pMMAPRxBufPtr[i]); ptri2s_config->pMMAPRxBufPtr[i] = NULL; } pci_free_consistent(NULL, I2S_PAGE_SIZE*2, ptri2s_config->pPage0RxBuf8ptr, i2s_rxdma_addr); ptri2s_config->pPage0RxBuf8ptr = NULL; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_PUT_AUDIO: //MSG("I2S_PUT_AUDIO\n"); #if defined(I2S_FIFO_MODE) { long* pData ; //MSG("I2S_PUT_AUDIO FIFO\n"); copy_from_user(ptri2s_config->pMMAPTxBufPtr[0], (char*)arg, I2S_PAGE_SIZE); pData = ptri2s_config->pMMAPTxBufPtr[0]; for(i = 0 ; i < I2S_PAGE_SIZE>>2 ; i++ ) { int j; unsigned long status = i2s_inw(I2S_FF_STATUS); while((status&0x0F)==0) { for(j = 0 ; j < 50 ; j++); status = i2s_inw(I2S_FF_STATUS); } *((volatile uint32_t *)(I2S_TX_FIFO_WREG)) = cpu_to_le32(*pData); if(i==16) MSG("I2S_PUT_AUDIO FIFO[0x%08X]\n", *pData); pData++; } } break; #else do{ spin_lock_irqsave(&ptri2s_config->lock, flags); if(((ptri2s_config->tx_w_idx+4)%MAX_I2S_PAGE)!=ptri2s_config->tx_r_idx) { ptri2s_config->tx_w_idx = (ptri2s_config->tx_w_idx+1)%MAX_I2S_PAGE; //printk("put TB[%d] for user write\n",ptri2s_config->tx_w_idx); #if defined(CONFIG_I2S_MMAP) put_user(ptri2s_config->tx_w_idx, (int*)arg); #else copy_from_user(ptri2s_config->pMMAPTxBufPtr[ptri2s_config->tx_w_idx], (char*)arg, I2S_PAGE_SIZE); #endif pi2s_status->txbuffer_len++; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; } else { /* Buffer Full */ //printk("TBF tr=%d, tw=%d\n", ptri2s_config->tx_r_idx, ptri2s_config->tx_w_idx); pi2s_status->txbuffer_ovrun++; spin_unlock_irqrestore(&ptri2s_config->lock, flags); interruptible_sleep_on(&(ptri2s_config->i2s_tx_qh)); } }while(1); break; #endif case I2S_GET_AUDIO: #if defined(I2S_FIFO_MODE) { long* pData ; pData = ptri2s_config->pMMAPRxBufPtr[0]; for(i = 0 ; i < I2S_PAGE_SIZE>>2 ; i++ ) { int j; unsigned long status = i2s_inw(I2S_FF_STATUS); while((status&0x0F0)==0) { for(j = 0 ; j < 50 ; j++); status = i2s_inw(I2S_FF_STATUS); } *pData = i2s_inw(I2S_RX_FIFO_RREG); if(i==16) MSG("I2S_GET_AUDIO FIFO[0x%08X]\n", *pData); pData++; } copy_to_user((char*)arg, ptri2s_config->pMMAPRxBufPtr[0], I2S_PAGE_SIZE); } break; #else do{ spin_lock_irqsave(&ptri2s_config->lock, flags); if(ptri2s_config->rx_r_idx!=ptri2s_config->rx_w_idx) { copy_to_user((char*)arg, ptri2s_config->pMMAPRxBufPtr[ptri2s_config->rx_r_idx], I2S_PAGE_SIZE); ptri2s_config->rx_r_idx = (ptri2s_config->rx_r_idx+1)%MAX_I2S_PAGE; pi2s_status->rxbuffer_len--; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; } else { /* Buffer Full */ //printk("RBF rr=%d, rw=%d\n", ptri2s_config->rx_r_idx, ptri2s_config->rx_w_idx); pi2s_status->rxbuffer_ovrun++; spin_unlock_irqrestore(&ptri2s_config->lock, flags); interruptible_sleep_on(&(ptri2s_config->i2s_rx_qh)); } }while(1); break; #endif case I2S_DEBUG_CLKGEN: case I2S_DEBUG_INLBK: case I2S_DEBUG_EXLBK: case I2S_DEBUG_CODECBYPASS: case I2S_DEBUG_FMT: case I2S_DEBUG_RESET: i2s_debug_cmd(cmd, arg); break; default : MSG("i2s_ioctl: command format error\n"); } return 0; }
int tegra_das_set_connection(enum tegra_das_port_con_id new_con_id) { struct am_ch_info *ch1 = NULL, *ch2 = NULL; int dev_id1 = 0, dev_id2 = 0; int damch = 0; struct audio_dev_property dev1_prop, dev2_prop; int break_voicecall = 0, break_voicecallbt = 0; int make_voicecall = 0, make_voicecallbt = 0; AM_DEBUG_PRINT("%s++\n", __func__); if (new_con_id == tegra_das_port_con_id_voicecall_no_bt) { if (aud_manager->cur_conn == tegra_das_port_con_id_voicecall_with_bt) { break_voicecallbt = 1; } make_voicecall = 1; } else if (new_con_id == tegra_das_port_con_id_voicecall_with_bt) { if (aud_manager->cur_conn == tegra_das_port_con_id_voicecall_no_bt) { break_voicecall = 1; } make_voicecallbt = 1; } else if (new_con_id == tegra_das_port_con_id_hifi) { if (aud_manager->cur_conn == tegra_das_port_con_id_voicecall_no_bt) { break_voicecall = 1; } else if (aud_manager->cur_conn == tegra_das_port_con_id_voicecall_with_bt) { break_voicecallbt = 1; } } else if (new_con_id == tegra_das_port_con_id_bt_codec) { if (aud_manager->cur_conn == tegra_das_port_con_id_voicecall_with_bt) { break_voicecallbt = 1; } else if (aud_manager->cur_conn == tegra_das_port_con_id_voicecall_no_bt) { break_voicecall = 1; } } /*break old connections and make new connections*/ if (break_voicecall == 1) { dev_id1 = aud_manager->hifi_port_idx; ch1 = &aud_manager->i2s_ch[dev_id1]; AM_DEBUG_PRINT("devid1 %d\n", dev_id1); dev_id2 = aud_manager->bb_port_idx; ch2 = &aud_manager->i2s_ch[dev_id2]; AM_DEBUG_PRINT("devid2 %d\n", dev_id2); i2s_fifo_enable(dev_id1, AUDIO_TX_MODE, 0); i2s_fifo_enable(dev_id2, AUDIO_TX_MODE, 0); i2s_fifo_enable(dev_id1, AUDIO_RX_MODE, 0); i2s_fifo_enable(dev_id2, AUDIO_RX_MODE, 0); dam_enable(ch1->damch[dam_ch_in0], 0, dam_ch_in0); dam_enable(ch2->damch[dam_ch_in0], 0, dam_ch_in0); audio_switch_clear_rx_port(dev_id2 + ahubrx_i2s0); audio_switch_clear_rx_port(ahubrx0_dam0 + (ch1->damch[dam_ch_in0] << 1)); audio_switch_clear_rx_port(ahubrx0_dam0 + (ch2->damch[dam_ch_in0] << 1)); dam_free_controller(ch1->damch[dam_ch_in0], dam_ch_in0); ch1->damch[dam_ch_in0] = -1; dam_free_controller(ch2->damch[dam_ch_in0], dam_ch_in0); ch2->damch[dam_ch_in0] = -1; i2s_clock_disable(dev_id1, 0); i2s_clock_disable(dev_id2, 0); } else if (break_voicecallbt == 1) { dev_id1 = aud_manager->bt_port_idx; ch1 = &aud_manager->i2s_ch[dev_id1]; AM_DEBUG_PRINT("devid1 %d\n", dev_id1); dev_id2 = aud_manager->bb_port_idx; ch2 = &aud_manager->i2s_ch[dev_id2]; AM_DEBUG_PRINT("devid2 %d\n", dev_id2); i2s_fifo_enable(dev_id1, AUDIO_TX_MODE, 0); i2s_fifo_enable(dev_id2, AUDIO_TX_MODE, 0); i2s_fifo_enable(dev_id1, AUDIO_RX_MODE, 0); i2s_fifo_enable(dev_id2, AUDIO_RX_MODE, 0); dam_enable(ch1->damch[dam_ch_in0], 0, dam_ch_in0); dam_enable(ch2->damch[dam_ch_in0], 0, dam_ch_in0); audio_switch_clear_rx_port(dev_id2 + ahubrx_i2s0); audio_switch_clear_rx_port(ahubrx0_dam0 + (ch1->damch[dam_ch_in0] << 1)); audio_switch_clear_rx_port(ahubrx0_dam0 + (ch2->damch[dam_ch_in0] << 1)); dam_free_controller(ch1->damch[dam_ch_in0], dam_ch_in0); ch1->damch[dam_ch_in0] = -1; dam_free_controller(ch2->damch[dam_ch_in0], dam_ch_in0); ch2->damch[dam_ch_in0] = -1; i2s_clock_disable(dev_id1, 0); i2s_clock_disable(dev_id2, 0); } if (make_voicecall == 1) { AM_DEBUG_PRINT("voice call connection\n"); memset(&dev1_prop, 0, sizeof(struct audio_dev_property)); memset(&dev2_prop, 0, sizeof(struct audio_dev_property)); tegra_das_get_device_property( tegra_audio_codec_type_hifi, &dev1_prop); tegra_das_get_device_property( tegra_audio_codec_type_baseband, &dev2_prop); dev_id1 = aud_manager->hifi_port_idx; dev_id2 = aud_manager->bb_port_idx; i2s_clock_enable(dev_id1, 0); i2s_clock_enable(dev_id2, 0); ch1 = &aud_manager->i2s_ch[dev_id1]; ch2 = &aud_manager->i2s_ch[dev_id2]; AM_DEBUG_PRINT("devid1 %d devid2 %d\n", dev_id1, dev_id2); setup_baseband_connection(dev_id1, &dev1_prop); setup_baseband_connection(dev_id2, &dev2_prop); damch = ch1->damch[dam_ch_in0]; dam_set_samplerate(damch, dam_ch_in0, dev2_prop.rate); /*i2s1_tx (48Khz) -> dam_ch0 rx (8k)*/ audio_switch_set_rx_port(ahubrx0_dam0 + (damch << 1), dev_id2 + ahubtx_i2s0); /*get the properties of i2s and set to i2s and dam*/ dam_set_acif(damch, dam_ch_in0, &ch2->outcif); dam_enable(damch, 1, dam_ch_in0); damch = ch2->damch[dam_ch_in0]; dam_set_samplerate(damch, dam_ch_in0, dev1_prop.rate); /*get the properties of i2s and set to i2s and dam*/ dam_set_acif(damch, dam_ch_in0, &ch1->outcif); audio_switch_set_rx_port(ahubrx0_dam0 + (damch << 1), dev_id1 + ahubtx_i2s0); /*enable the dap and i2s as well*/ dam_enable(damch, 1, dam_ch_in0); i2s_fifo_enable(dev_id1, AUDIO_TX_MODE, 1); i2s_fifo_enable(dev_id2, AUDIO_TX_MODE, 1); i2s_fifo_enable(dev_id1, AUDIO_RX_MODE, 1); i2s_fifo_enable(dev_id2, AUDIO_RX_MODE, 1); } else if (make_voicecallbt == 1) { AM_DEBUG_PRINT("bt voice call connection\n"); memset(&dev1_prop, 0, sizeof(struct audio_dev_property)); memset(&dev2_prop, 0, sizeof(struct audio_dev_property)); tegra_das_get_device_property( tegra_audio_codec_type_bluetooth, &dev1_prop); tegra_das_get_device_property( tegra_audio_codec_type_baseband, &dev2_prop); dev_id1 = aud_manager->bt_port_idx; dev_id2 = aud_manager->bb_port_idx; i2s_clock_enable(dev_id1, 0); i2s_clock_enable(dev_id2, 0); ch1 = &aud_manager->i2s_ch[dev_id1]; ch2 = &aud_manager->i2s_ch[dev_id2]; setup_baseband_connection(dev_id1, &dev1_prop); setup_baseband_connection(dev_id2, &dev2_prop); damch = ch1->damch[dam_ch_in0]; dam_set_samplerate(damch, dam_ch_in0, dev2_prop.rate); /*i2s1_tx (48Khz) -> dam_ch0 rx (8k)*/ audio_switch_set_rx_port(ahubrx0_dam0 + (damch << 1), dev_id2 + ahubtx_i2s0); /*get the properties of i2s and set to i2s and dam*/ dam_set_acif(damch, dam_ch_in0, &ch2->outcif); dam_enable(damch, 1, dam_ch_in0); damch = ch2->damch[dam_ch_in0]; dam_set_samplerate(damch, dam_ch_in0, dev1_prop.rate); /*get the properties of i2s and set to i2s and dam*/ dam_set_acif(damch, dam_ch_in0, &ch1->outcif); audio_switch_set_rx_port(ahubrx0_dam0 + (damch << 1), dev_id1 + ahubtx_i2s0); /* enable the dap and i2s as well */ dam_enable(damch, 1, dam_ch_in0); i2s_fifo_enable(dev_id1, AUDIO_TX_MODE, 1); i2s_fifo_enable(dev_id2, AUDIO_TX_MODE, 1); i2s_fifo_enable(dev_id1, AUDIO_RX_MODE, 1); i2s_fifo_enable(dev_id2, AUDIO_RX_MODE, 1); } aud_manager->cur_conn = new_con_id; AM_DEBUG_PRINT("%s--\n", __func__); return 0; }