void omap2_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) { struct omap_mcbsp *mcbsp; void __iomem *io_base; mcbsp = id_to_mcbsp_ptr(id); io_base = mcbsp->io_base; OMAP_MCBSP_WRITE(mcbsp, XCCR, config->xccr); OMAP_MCBSP_WRITE(mcbsp, RCCR, config->rccr); }
/* * Stop receving data on a McBSP interface * id : McBSP interface ID */ int omap2_mcbsp_stop_datarx(u32 id) { struct omap_mcbsp *mcbsp = mcbsp_ptr[id]; void __iomem *io_base; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } io_base = mcbsp->io_base; if (mcbsp->dma_rx_lch != -1) { if (omap_stop_dma_chain_transfers(mcbsp->dma_rx_lch) != 0) return -EINVAL; } OMAP_MCBSP_WRITE(mcbsp, SPCR1, OMAP_MCBSP_READ(mcbsp, SPCR1) & (~RRST)); mcbsp->rx_dma_chain_state = 0; if (!mcbsp->tx_dma_chain_state) omap2_mcbsp_set_srg_fsg(id, OMAP_MCBSP_DISABLE_FSG_SRG); return 0; }
/* * Reset Receiver * id : McBSP interface number * state : Disable (0)/ Enable (1) the receiver */ int omap2_mcbsp_set_rrst(unsigned int id, u8 state) { struct omap_mcbsp *mcbsp = mcbsp_ptr[id]; void __iomem *io_base; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } io_base = mcbsp->io_base; if (state == OMAP_MCBSP_RRST_DISABLE) OMAP_MCBSP_WRITE(mcbsp, SPCR1, OMAP_MCBSP_READ(mcbsp, SPCR1) & (~RRST)); else OMAP_MCBSP_WRITE(mcbsp, SPCR1, OMAP_MCBSP_READ(mcbsp, SPCR1) | RRST); udelay(10); return 0; }
/* * Enable/Disable the sample rate generator * id : McBSP interface ID * state : Enable/Disable */ void omap2_mcbsp_set_srg_fsg(unsigned int id, u8 state) { struct omap_mcbsp *mcbsp = mcbsp_ptr[id]; void __iomem *io_base; io_base = mcbsp->io_base; if (state == OMAP_MCBSP_DISABLE_FSG_SRG) { OMAP_MCBSP_WRITE(mcbsp, SPCR2, OMAP_MCBSP_READ(mcbsp, SPCR2) & (~GRST)); OMAP_MCBSP_WRITE(mcbsp, SPCR2, OMAP_MCBSP_READ(mcbsp, SPCR2) & (~FRST)); } else { OMAP_MCBSP_WRITE(mcbsp, SPCR2, OMAP_MCBSP_READ(mcbsp, SPCR2) | GRST); OMAP_MCBSP_WRITE(mcbsp, SPCR2, OMAP_MCBSP_READ(mcbsp, SPCR2) | FRST); } return; }
static void epson_sendbyte(int flag, unsigned char byte) { int i, shifter = 0x80; if (!flag) gpio_set_value(_A_LCD_SSC_A0, 0); mdelay(2); gpio_set_value(A_LCD_SSC_RD, 1); gpio_set_value(A_LCD_SSC_SD, flag); OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200); OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202); for (i = 0; i < 8; i++) { OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200); gpio_set_value(A_LCD_SSC_SD, shifter & byte); OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202); shifter >>= 1; } gpio_set_value(_A_LCD_SSC_A0, 1); }
static void omap2_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data) { struct omap_mcbsp *mcbsp_dma_tx = data; void __iomem *io_base; io_base = mcbsp_dma_tx->io_base; /* If we are at the last transfer, Shut down the Transmitter */ if ((mcbsp_dma_tx->auto_reset & OMAP_MCBSP_AUTO_XRST) && (omap_dma_chain_status(mcbsp_dma_tx->dma_tx_lch) == OMAP_DMA_CHAIN_INACTIVE)) OMAP_MCBSP_WRITE(mcbsp_dma_tx, SPCR2, OMAP_MCBSP_READ(mcbsp_dma_tx, SPCR2) & (~XRST)); if (mcbsp_dma_tx->tx_callback != NULL) mcbsp_dma_tx->tx_callback(ch_status, mcbsp_dma_tx->tx_cb_arg); }
/* * Sample rate changing */ void tsc2101_set_samplerate(long sample_rate) { u8 count = 0; u16 data = 0; int clkgdv = 0; u16 srgr1, srgr2; /* wait for any frame to complete */ udelay(125); ADEBUG(); sample_rate = sample_rate; /* Search for the right sample rate */ while ((rate_reg_info[count].sample_rate != sample_rate) && (count < NUMBER_SAMPLE_RATES_SUPPORTED)) { count++; } if (count == NUMBER_SAMPLE_RATES_SUPPORTED) { printk(KERN_ERR "Invalid Sample Rate %d requested\n", (int) sample_rate); return; // -EPERM; } /* Set AC1 */ data = tsc2101_audio_read(TSC2101_AUDIO_CTRL_1); /* Clear prev settings */ data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07)); data |= AC1_DACFS(rate_reg_info[count].divisor) | AC1_ADCFS(rate_reg_info[count].divisor); tsc2101_audio_write(TSC2101_AUDIO_CTRL_1, data); /* Set the AC3 */ data = tsc2101_audio_read(TSC2101_AUDIO_CTRL_3); /*Clear prev settings */ data &= ~(AC3_REFFS | AC3_SLVMS); data |= (rate_reg_info[count].fs_44kHz) ? AC3_REFFS : 0; #ifdef TSC_MASTER data |= AC3_SLVMS; #endif /* #ifdef TSC_MASTER */ tsc2101_audio_write(TSC2101_AUDIO_CTRL_3, data); /* Program the PLLs. This code assumes that the 12 Mhz MCLK is in use. * If MCLK rate is something else, these values must be changed. * See the tsc2101 specification for the details. */ if (rate_reg_info[count].fs_44kHz) { /* samplerate = (44.1kHZ / x), where x is int. */ tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7)); /* PVAL 1; I_VAL 7 */ tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490)); /* D_VAL 5264 */ } else { /* samplerate = (48.kHZ / x), where x is int. */ tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8)); /* PVAL 1; I_VAL 8 */ tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780)); /* D_VAL 1920 */ } /* Set the sample rate */ #ifndef TSC_MASTER clkgdv = CODEC_CLOCK / (sample_rate * (DEFAULT_BITPERSAMPLE * 2 - 1)); if (clkgdv) srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv)); else return (1); /* Stereo Mode */ srgr2 = (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)); #else srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv)); srgr2 = ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1))); #endif /* end of #ifdef TSC_MASTER */ OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR2, srgr2); OMAP_MCBSP_WRITE(OMAP1610_MCBSP1_BASE, SRGR1, srgr1); }
/* * Start transmitting data through a McBSP interface * id : McBSP interface ID * cbdata : User data to be returned with callback * buf_start_addr : The source address [This should be physical address] * buf_size : Buffer size */ int omap2_mcbsp_send_data(unsigned int id, void *cbdata, dma_addr_t buf_start_addr, u32 buf_size) { struct omap_mcbsp *mcbsp; void __iomem *io_base; u8 enable_tx = 0; int e_count = 0; int f_count = 0; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); io_base = mcbsp->io_base; mcbsp->tx_cb_arg = cbdata; /* Auto RRST handling logic - disable the Reciever before 1st dma */ if ((mcbsp->auto_reset & OMAP_MCBSP_AUTO_XRST) && (omap_dma_chain_status(mcbsp->dma_tx_lch) == OMAP_DMA_CHAIN_INACTIVE)) { OMAP_MCBSP_WRITE(mcbsp, SPCR2, OMAP_MCBSP_READ(mcbsp, SPCR2) & (~XRST)); enable_tx = 1; } /* * for skip_first and second, we need to set e_count =2, and * f_count = number of frames = number of elements/e_count */ e_count = (buf_size / mcbsp->tx_word_length); if (mcbsp->txskip_alt != OMAP_MCBSP_SKIP_NONE) { /* * number of frames = total number of elements/element count, * However, with double indexing for data transfers, double I * the number of elements need to be transmitted */ f_count = e_count; e_count = 2; } else { f_count = 1; } /* * If the DMA is to be configured to skip the first byte, we need * to jump backwards, so we need to move one chunk forward and ask * dma if we dont want the client driver knowing abt this. */ if (mcbsp->txskip_alt == OMAP_MCBSP_SKIP_FIRST) buf_start_addr += mcbsp->tx_word_length; if (omap_dma_chain_a_transfer(mcbsp->dma_tx_lch, buf_start_addr, mcbsp->phys_base + OMAP_MCBSP_REG_DXR, e_count, f_count, mcbsp) < 0) return -EINVAL; if (mcbsp->tx_dma_chain_state == 0) { if (mcbsp->interface_mode == OMAP_MCBSP_MASTER) omap2_mcbsp_set_srg_fsg(id, OMAP_MCBSP_ENABLE_FSG_SRG); if (omap_start_dma_chain_transfers(mcbsp->dma_tx_lch) < 0) return -EINVAL; mcbsp->tx_dma_chain_state = 1; } /* Auto XRST handling logic - Enable the Reciever after 1st dma */ if (enable_tx && (omap_dma_chain_status(mcbsp->dma_tx_lch) == OMAP_DMA_CHAIN_ACTIVE)) OMAP_MCBSP_WRITE(mcbsp, SPCR2, OMAP_MCBSP_READ(mcbsp, SPCR2) | XRST); return 0; }
int omap2_mcbsp_receive_data(unsigned int id, void *cbdata, dma_addr_t buf_start_addr, u32 buf_size) { struct omap_mcbsp *mcbsp; void __iomem *io_base; int enable_rx = 0; int e_count = 0; int f_count = 0; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); io_base = mcbsp->io_base; mcbsp->rx_cb_arg = cbdata; /* Auto RRST handling logic - disable the Reciever before 1st dma */ if ((mcbsp->auto_reset & OMAP_MCBSP_AUTO_RRST) && (omap_dma_chain_status(mcbsp->dma_rx_lch) == OMAP_DMA_CHAIN_INACTIVE)) { OMAP_MCBSP_WRITE(io_base, SPCR1, OMAP_MCBSP_READ(io_base, SPCR1) & (~RRST)); enable_rx = 1; } /* * for skip_first and second, we need to set e_count =2, * and f_count = number of frames = number of elements/e_count */ e_count = (buf_size / mcbsp->rx_word_length); if (mcbsp->rxskip_alt != OMAP_MCBSP_SKIP_NONE) { /* * since the number of frames = total number of elements/element * count, However, with double indexing for data transfers, * double the number of elements need to be transmitted */ f_count = e_count; e_count = 2; } else { f_count = 1; } /* * If the DMA is to be configured to skip the first byte, we need * to jump backwards, so we need to move one chunk forward and * ask dma if we dont want the client driver knowing abt this. */ if (mcbsp->rxskip_alt == OMAP_MCBSP_SKIP_FIRST) buf_start_addr += mcbsp->rx_word_length; if (omap_dma_chain_a_transfer(mcbsp->dma_rx_lch, mcbsp->phys_base + OMAP_MCBSP_REG_DRR, buf_start_addr, e_count, f_count, mcbsp) < 0) { printk(KERN_ERR " Buffer chaining failed \n"); return -EINVAL; } if (mcbsp->rx_dma_chain_state == 0) { if (omap_start_dma_chain_transfers(mcbsp->dma_rx_lch) < 0) return -EINVAL; mcbsp->rx_dma_chain_state = 1; } /* Auto RRST handling logic - Enable the Reciever after 1st dma */ if (enable_rx && (omap_dma_chain_status(mcbsp->dma_rx_lch) == OMAP_DMA_CHAIN_ACTIVE)) OMAP_MCBSP_WRITE(io_base, SPCR1, OMAP_MCBSP_READ(io_base, SPCR1) | RRST); return 0; }