Exemplo n.º 1
0
static void __devexit intel_mid_i2s_remove(struct pci_dev *pdev)
{
	struct intel_mid_i2s_hdl *drv_data;

	pm_runtime_get_noresume(&pdev->dev);
	pm_runtime_forbid(&pdev->dev);

	drv_data = pci_get_drvdata(pdev);
	if (!drv_data) {
		dev_err(&pdev->dev, "no drv_data in pci device to remove!\n");
		goto leave;
	}
	if (test_bit(I2S_PORT_OPENED, &drv_data->flags)) {
		dev_warn(&pdev->dev, "Not closed before removing pci_dev!\n");
		intel_mid_i2s_close(drv_data);
	}
	pci_set_drvdata(pdev, NULL);
	/* Stop DMA is already done during close()  */
	pci_dev_put(drv_data->dmac1);
	/* Disable the SSP at the peripheral and SOC level */
	write_SSCR0(0, drv_data->ioaddr);
	free_irq(drv_data->irq, drv_data);
	iounmap(drv_data->ioaddr);
	pci_release_region(pdev, MRST_SSP_BAR);
	pci_release_region(pdev, MRST_LPE_BAR);
	pci_disable_device(pdev);
	kfree(drv_data);
leave:
	return;
}
Exemplo n.º 2
0
/**
 * intel_mid_i2s_close - release and stop the SSP
 * @drv_data : handle of corresponding ssp i2s (given by i2s_open function)
 *
 * WARNING: This is not -yet- allowed to call close from a read/write callback !
 *
 * Output parameters
 *      none
 */
void intel_mid_i2s_close(struct intel_mid_i2s_hdl *drv_data)
{
	void __iomem *reg;
	struct intel_mid_i2s_settings *ssp_settings =
						&(drv_data->current_settings);
	int s;
	struct dma_chan *channel;

	WARN(!drv_data, "Driver data=NULL\n");
	if (!drv_data)
		return;
	mutex_lock(&drv_data->mutex);
	if (!test_bit(I2S_PORT_OPENED, &drv_data->flags)) {
		dev_err(&drv_data->pdev->dev, "not opened but closing?");
		mutex_unlock(&drv_data->mutex);
		return;
	}

	set_bit(I2S_PORT_CLOSING, &drv_data->flags);
	dev_info(&drv_data->pdev->dev, "Status bit pending write=%d read=%d\n",
			test_bit(I2S_PORT_WRITE_BUSY, &drv_data->flags),
			test_bit(I2S_PORT_READ_BUSY, &drv_data->flags));
	if (test_bit(I2S_PORT_WRITE_BUSY, &drv_data->flags) ||
	     test_bit(I2S_PORT_READ_BUSY, &drv_data->flags)) {
		dev_info(&drv_data->pdev->dev, "Pending callback in close...\n");
	}

	if (ssp_settings->ssp_active_tx_slots_map) {
		channel = drv_data->txchan;
		s = channel->device->device_control(channel,
							DMA_TERMINATE_ALL, 0);
		dev_info(&drv_data->pdev->dev, "DMA_TERMINATE tx=%d\n", s);
	}
	if (ssp_settings->ssp_active_rx_slots_map) {
		channel = drv_data->rxchan;
		s = channel->device->device_control(channel,
							DMA_TERMINATE_ALL, 0);
		dev_info(&drv_data->pdev->dev, "DMA_TERMINATE rx=%d\n", s);
	}

	/* release DMA Channel.. */
	i2s_dma_stop(drv_data);
	reg = drv_data->ioaddr;
	dev_dbg(&drv_data->pdev->dev, "Stopping the SSP\n");
	i2s_ssp_stop(drv_data);
	put_device(&drv_data->pdev->dev);
	write_SSCR0(0, reg);

	dev_dbg(&(drv_data->pdev->dev), "SSP Stopped.\n");
	clear_bit(I2S_PORT_CLOSING, &drv_data->flags);
	clear_bit(I2S_PORT_OPENED, &drv_data->flags);

	/* pm runtime */
	pm_runtime_put(&drv_data->pdev->dev);

	mutex_unlock(&drv_data->mutex);
}
Exemplo n.º 3
0
/*
 * set_ssp_i2s_hw - Configure SSP driver according to settings.
 * @regs: pointer to registers
 * @shim: pointer to shim registers
 * @settings: config settings
 * @bps: bits per sample
 *
 * Configure SSP driver according to settings.
 */
static void set_ssp_i2s_hw(AplI2sRegs *regs, AplI2sRegs *shim,
	const AplI2sSettings *settings, int bps)
{
	uint32_t sscr0;
	uint32_t sscr1;
	uint32_t sscr2;
	uint32_t sscr3;
	uint32_t sstsa;
	uint32_t ssrsa;
	uint32_t sspsp;
	uint32_t sspsp2 = 0;
	uint32_t sssr = 0;
	uint32_t ssioc;

	sscr0 = calculate_sscr0(settings, bps);
	sscr1 = calculate_sscr1(settings);
	sscr2 = calculate_sscr2();
	sscr3 = 0;
	sspsp = calculate_sspsp(settings);
	sstsa = SSTSA_reg(TTSA, settings->ssp_active_tx_slots_map);
	ssrsa = SSRSA_reg(RTSA, settings->ssp_active_rx_slots_map);
	ssioc = calculate_ssioc();

	write_SSCR0(sscr0, regs);
	write_SSCR1(sscr1, regs);
	write_SSCR2(sscr2, regs);
	write_SSCR3(sscr3, regs);
	write_SSPSP(sspsp, regs);
	write_SSPSP2(sspsp2, regs);
	write_SSTSA(sstsa, regs);
	write_SSRSA(ssrsa, regs);
	write_SSIOC(ssioc, regs);

	/* Clear status */
	write_SSSR(sssr, regs);

	/* set the time out for the reception */
	write_SSTO(SSP_TIMEOUT, regs);
}
static void pxa2xx_spi_dma_error_stop(struct driver_data *drv_data,
                                      const char *msg)
{
    void __iomem *reg = drv_data->ioaddr;

    /* Stop and reset */
    DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
    DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
    write_SSSR_CS(drv_data, drv_data->clear_sr);
    write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
    if (!pxa25x_ssp_comp(drv_data))
        write_SSTO(0, reg);
    pxa2xx_spi_flush(drv_data);
    write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);

    pxa2xx_spi_unmap_dma_buffers(drv_data);

    dev_err(&drv_data->pdev->dev, "%s\n", msg);

    drv_data->cur_msg->state = ERROR_STATE;
    tasklet_schedule(&drv_data->pump_transfers);
}
Exemplo n.º 5
0
/**
 * set_ssp_i2s_hw - configure the SSP driver according to the ps_settings
 * @drv_data : structure that contains all details about the SSP Driver
 * @ps_settings : structure that contains SSP Hardware settings
 *
 * it also store ps_settings the drv_data
 *
 * Output parameters
 *      NA
 */
static void set_ssp_i2s_hw(struct intel_mid_i2s_hdl *drv_data,
			const struct intel_mid_i2s_settings *ps_settings)
{
	u32 sscr0 = 0;
	u32 sscr1 = 0;
	u32 sstsa = 0;
	u32 ssrsa = 0;
	u32 sspsp = 0;
	u32 sssr = 0;
	/* Get the SSP Settings */
	u16 l_ssp_clk_frm_mode = 0xFF;
	void __iomem *reg = drv_data->ioaddr;
	struct device *ddbg = &(drv_data->pdev->dev);
	dev_dbg(ddbg,
		"setup SSP I2S PCM1 configuration\n");
	if ((ps_settings->sspsfrm_direction == SSPSFRM_MASTER_MODE)
	   && (ps_settings->sspslclk_direction == SSPSCLK_MASTER_MODE)) {
		l_ssp_clk_frm_mode = SSP_IN_MASTER_MODE;
	} else if ((ps_settings->sspsfrm_direction == SSPSFRM_SLAVE_MODE)
	   && (ps_settings->sspslclk_direction == SSPSCLK_SLAVE_MODE)) {
		l_ssp_clk_frm_mode = SSP_IN_SLAVE_MODE;
	} else {
		dev_err(ddbg, "Unsupported I2S PCM1 configuration\n");
		goto leave;
	}
	dev_dbg(ddbg, "SSPSFRM_DIRECTION:%d:\n",
		ps_settings->sspsfrm_direction);
	dev_dbg(ddbg, "SSPSCLK_DIRECTION:%d:\n",
		ps_settings->sspslclk_direction);
	if (ps_settings->frame_format != PSP_FORMAT) {
		dev_err(ddbg, "UNSUPPORTED FRAME FORMAT:%d:\n",
						ps_settings->frame_format);
		goto leave;
	}
	if ((ps_settings->ssp_tx_dma != SSP_TX_DMA_ENABLE)
	|| (ps_settings->ssp_rx_dma != SSP_RX_DMA_ENABLE)) {
		dev_err(ddbg, "ONLY DMA MODE IS SUPPORTED");
		goto leave;
	}
	/*********** DMA Transfer Mode ***********/
	dev_dbg(ddbg, "FORMAT :%d:\n", ps_settings->frame_format);
	sscr0 = calculate_sscr0_psp(ps_settings);
	dev_dbg(ddbg, " sscr0 :0x%08X\n", sscr0);
	sscr1 = calculate_sscr1_psp(ps_settings);
	dev_dbg(ddbg, " sscr1 :0x%08X\n", sscr1);
	if (ps_settings->mode == SSP_IN_NETWORK_MODE) {
		dev_dbg(ddbg, "MODE :%d:\n", ps_settings->mode);
		sscr0 |= SSCR0_reg(FRDC,
			SSCR0_SlotsPerFrm(ps_settings->
						frame_rate_divider_control));
		dev_dbg(ddbg, "sscr0 :0x%08X\n", sscr0);
		sspsp = calculate_sspsp_psp(ps_settings);
		dev_dbg(ddbg, "sspsp :0x%08X\n", sspsp);
		/* set the active TX time slot (bitmap) */
		sstsa = SSTSA_reg(TTSA, ps_settings->ssp_active_tx_slots_map);
		/* set the active RX time slot (bitmap) */
		ssrsa = SSRSA_reg(RTSA, ps_settings->ssp_active_rx_slots_map);
		if (l_ssp_clk_frm_mode == SSP_IN_MASTER_MODE) {
			switch (ps_settings->master_mode_clk_selection) {
			case SSP_ONCHIP_CLOCK:
				break;
			case SSP_NETWORK_CLOCK:
				sscr0 |= SSCR0_reg(NCS, 1);
				break;
			case SSP_EXTERNAL_CLOCK:
				sscr0 |= SSCR0_reg(ECS, 1);
				break;
			case SSP_ONCHIP_AUDIO_CLOCK:
				sscr0 |= SSCR0_reg(ACS, 1);
				break;
			default:
				dev_err(ddbg, "Master Mode clk selection UNKNOWN");
				break;
			}
			sspsp |= SSPSP_reg(STRTDLY, ps_settings->ssp_psp_T1)
				|SSPSP_reg(DMYSTRT, ps_settings->ssp_psp_T2);
		} else {	/* Set the Slave Clock Free Running Status */
			sscr1 |= SSCR1_reg(SCFR,
				ps_settings->slave_clk_free_running_status);
		}
	} else {  /* SSP_IN_NORMAL_MODE */
		dev_err(ddbg, "UNSUPPORTED MODE");
		goto leave;
	}

	/* Clear status */
	sssr = (SSSR_BCE_MASK << SSSR_BCE_SHIFT)
	     | (SSSR_TUR_MASK << SSSR_TUR_SHIFT)
	     | (SSSR_TINT_MASK << SSSR_TINT_SHIFT)
	     | (SSSR_PINT_MASK << SSSR_PINT_SHIFT)
	     | (SSSR_ROR_MASK << SSSR_ROR_SHIFT);
	/* disable SSP */
	clear_SSCR0_reg(reg, SSE);
	dev_dbg(ddbg, "WRITE SSCR0 DISABLE\n");
	/* Clear status */
	write_SSSR(sssr, reg);
	dev_dbg(ddbg, "WRITE SSSR: 0x%08X\n", sssr);
	write_SSCR0(sscr0, reg);
	dev_dbg(ddbg, "WRITE SSCR0\n");
	/* first set CR1 without interrupt and service enables */
	write_SSCR1(sscr1, reg);
	write_SSPSP(sspsp, reg);
	write_SSTSA(sstsa, reg);
	write_SSRSA(ssrsa, reg);
	/* set the time out for the reception */
	write_SSTO(0, reg);
	ssp1_dump_registers(drv_data);
leave:
	return;
}