static void jornada56x_audio_init(void *dummy) { int i = 100; JORNADA_GPIOAFR |= JORNADA_GP_L3; udelay(100); SetPMUPCRRegister(PCR_BIT_SET, JORNADA_L3CLK_EN | JORNADA_I2S_CLK_EN); udelay(100); JORNADA_L3CFR |= JORNADA_L3_EN; /* Enable L3 interface */ GAFR |= (GPIO_SSP_CLK); GPDR &= ~(GPIO_SSP_CLK); Ser4SSCR0 = 0; Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(2); Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk; Ser4SSCR0 |= SSCR0_SSE; Ser4SSDR = 0; JORNADA_GPDPCR = GPIO_GPIO10; uda1341_open(uda1341); jornada56x_set_audio_rate(AUDIO_RATE_DEFAULT); JORNADA_L3CAR = 0x14; mdelay(100); while ((!(JORNADA_L3CFR & JORNADA_L3_ADDR_DONE))&&(i--)); JORNADA_L3CDW = 0xc3; mdelay(100); i=100; while ((!(JORNADA_L3CFR & JORNADA_L3_DATA_DONE))&&(i--)); printk("jornada56x_audi_init() done!"); }
static void ssp_audio_init(void *data) { if (machine_is_lart()) { unsigned long flags; local_irq_save(flags); /* LART has the SSP port rewired to GPIO 10-13, 19 */ /* alternate functions for the GPIOs */ GAFR |= ( GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM | GPIO_SSP_CLK ); /* Set the direction: 10, 12, 13 output; 11, 19 input */ GPDR |= ( GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM ); GPDR &= ~( GPIO_SSP_RXD | GPIO_SSP_CLK ); /* enable SSP pin swap */ PPAR |= PPAR_SPR; local_irq_restore(flags); } /* turn on the SSP */ Ser4SSCR0 = 0; Ser4SSCR0 = (SSCR0_DataSize(16) | SSCR0_TI | SSCR0_SerClkDiv(2) | SSCR0_SSE); Ser4SSCR1 = (SSCR1_SClkIactL | SSCR1_SClk1P | SSCR1_ExtClk); }
static void h3600_audio_init(void *dummy) { unsigned long flags; /* Setup the uarts */ local_irq_save(flags); GAFR |= (GPIO_SSP_CLK); GPDR &= ~(GPIO_SSP_CLK); Ser4SSCR0 = 0; Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(8); Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk; Ser4SSCR0 |= SSCR0_SSE; /* Enable the audio power */ clr_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET); set_h3600_egpio(IPAQ_EGPIO_AUDIO_ON); set_h3600_egpio(IPAQ_EGPIO_QMUTE); local_irq_restore(flags); /* external clock configuration */ h3600_set_samplerate(audio_samplerate); /* Wait for the UDA1341 to wake up */ set_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET); mdelay(1); /* make the left and right channels unswapped (flip the WS latch ) */ Ser4SSDR = 0; /* Initialize the UDA1341 internal state */ l3_open(&uda1341); clr_h3600_egpio(IPAQ_EGPIO_QMUTE); }
static void initKBCTL (void) { char msg[30]; int i; /* set dir for ssp */ GPDR = (GPDR | (0xD<<10) | (1<<23)) & ~(0x2 << 10); GAFR |= (0xf << 10); GPSR = 1<<23; /* deassert the kbctl wakup pin */ PPAR |= 1<<18; /* set alt function for spi interface */ Ser4SSCR0 = 0; Ser4SSCR1 = 0; /* no ints no loopback */ Ser4SSSR = 0; /* remove any rcv overrun errors */ /* turn on SSP */ Ser4SSCR0 = SSCR0_DataSize(8) + SSCR0_SerClkDiv(8) + SSCR0_SSE + SSCR0_Motorola; /* drain any data already there */ while (Ser4SSSR & SSSR_RNE) i = Ser4SSDR; msg[0]=0x1B; /* led on */ msg[1]=0xa7; msg[2]=0; msg[3]=3; msg[4]=lrc(msg, 4); putsToKBCTL(msg, 5); /* clear keyboard buffer */ while (getcFromKBCTL() != KBCTL_NODATA) { ; } }
static int ad_probe(struct platform_device *pdev) { struct ad7877_platform_data *pdata = pdev->dev.platform_data; struct ad7877 *ad; int ret; int i; // Initialize ad data structure. ad = kzalloc(sizeof(*ad), GFP_KERNEL); if (!ad) return -ENOMEM; init_completion(&ad->comp); ret = request_irq(pdata->dav_irq, davirq , IRQF_DISABLED | IRQF_TRIGGER_FALLING , "ad7877-dav", ad); if (ret) { kfree(ad); return ret; } ret = ssp_init(&ad->ssp, 1, 0); if (ret) { printk(KERN_ERR "Unable to register SSP handler!\n"); free_irq(pdata->dav_irq, ad); kfree(ad); return ret; } platform_set_drvdata(pdev, ad); ssp_disable(&ad->ssp); ssp_config(&ad->ssp, SSCR0_DataSize(16), 0, 0, SSCR0_SerClkDiv(6)); ssp_enable(&ad->ssp); initChip(ad); for (i = 0; i < ARRAY_SIZE(acdevs); i++) { acdevs[i].sense = sense; ret = adc_classdev_register(&pdev->dev, &acdevs[i]); if (ret) { printk("ad7877: failed to register adc class " "device %s\n", acdevs[i].name); goto adc_cdev_register_failed; } } return 0; adc_cdev_register_failed: while (--i >= 0) adc_classdev_unregister(&acdevs[i]); return ret; }
/* * calculate_sscr0: Calculate sscr0 register * @settings: config settings * @bps: bits per sample * * Calculate sscr0 register */ static uint32_t calculate_sscr0(const AplI2sSettings *settings, int bps) { uint32_t sscr0 = 0; if (bps > 16) sscr0 = SSCR0_reg(DSS, SSCR0_DataSize(bps - 16)) | SSCR0_reg(EDSS, EDSS_17_32_BITS); else sscr0 = SSCR0_reg(DSS, SSCR0_DataSize(bps)) | SSCR0_reg(EDSS, EDSS_4_16_BITS); sscr0 |= SSCR0_reg(MOD, settings->mode) | SSCR0_reg(FRF, PSP_FORMAT) | SSCR0_reg(SCR, 0x7) | SSCR0_reg(RIM, SSP_FIFO_INT_DISABLE) | SSCR0_reg(TIM, SSP_FIFO_INT_DISABLE) | SSCR0_reg(ECS, DIV_DISABLE) | SSCR0_reg(NCS, NETWORK_CLOCK_DISABLE) | SSCR0_reg(FRDC, SSCR0_SlotsPerFrm(settings->frame_rate_divider_ctrl)); return sscr0; }
/* * calculate_sscr0_psp: separate function that calculate sscr0 register * @ps_settings : pointer of the settings struct * * this function is to simplify/clarify set_ssp_i2s_hw function * * Output parameters * u32 : calculated SSCR0 register */ u32 calculate_sscr0_psp(const struct intel_mid_i2s_settings *ps_settings) { u16 l_ssp_data_size = ps_settings->data_size; u32 sscr0; if (l_ssp_data_size > 16) { sscr0 = SSCR0_reg(DSS, SSCR0_DataSize(l_ssp_data_size - 16)) | SSCR0_reg(EDSS, 1); } else { sscr0 = SSCR0_reg(DSS, SSCR0_DataSize(l_ssp_data_size)) | SSCR0_reg(EDSS, 0); } /* Can be replaced by code below : sscr0 = SSCR0_reg(DSS, (l_ssp_data_size - 1) & 0x0F) | SSCR0_reg(EDSS, ((l_ssp_data_size - 1) & 0x10) >> 8); */ sscr0 |= SSCR0_reg(MOD, ps_settings->mode) |SSCR0_reg(FRF, ps_settings->frame_format) |SSCR0_reg(RIM, SSP_RX_FIFO_OVER_INT_DISABLE) |SSCR0_reg(TIM, SSP_TX_FIFO_UNDER_INT_DISABLE); return sscr0; }
static void pangolin_audio_init(void *dummy) { unsigned long flags; unsigned int mdrefr; local_irq_save(flags); /* * Setup the SSP uart. */ PPAR |= PPAR_SPR; Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(2); Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk; GAFR |= GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_CLK | GPIO_SSP_SFRM; GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM; GPDR &= ~(GPIO_SSP_RXD | GPIO_SSP_CLK); Ser4SSCR0 |= SSCR0_SSE; GAFR &= ~(SpeakerOffPin | QmutePin); GPDR |= (SpeakerOffPin | QmutePin); GPCR = SpeakerOffPin; /* * The assabet board uses the SDRAM clock as the source clock for * audio. This is supplied to the SA11x0 from the CPLD on pin 19. * At 206MHz we need to run the audio clock (SDRAM bank 2) * at half speed. This clock will scale with core frequency so * the audio sample rate will also scale. The CPLD on Assabet * will need to be programmed to match the core frequency. */ mdrefr = MDREFR; if ((mdrefr & (MDREFR_K2DB2 | MDREFR_K2RUN | MDREFR_EAPD | MDREFR_KAPD)) != (MDREFR_K2DB2 | MDREFR_K2RUN)) { mdrefr |= MDREFR_K2DB2 | MDREFR_K2RUN; mdrefr &= ~(MDREFR_EAPD | MDREFR_KAPD); MDREFR = mdrefr; (void) MDREFR; } local_irq_restore(flags); /* Wait for the UDA1341 to wake up */ mdelay(100); l3_open(&uda1341); pangolin_set_samplerate(audio_samplerate); GPCR = QmutePin; }
static u32 pxa2xx_configure_sscr0(const struct driver_data *drv_data, u32 clk_div, u8 bits) { switch (drv_data->ssp_type) { case QUARK_X1000_SSP: return clk_div | QUARK_X1000_SSCR0_Motorola | QUARK_X1000_SSCR0_DataSize(bits > 32 ? 8 : bits) | SSCR0_SSE; default: return clk_div | SSCR0_Motorola | SSCR0_DataSize(bits > 16 ? bits - 16 : bits) | SSCR0_SSE | (bits > 16 ? SSCR0_EDSS : 0); } }
static inline void pfs168_spi_init_dev(void) { Ser4SSCR0 &= ~SSCR0_SSE; GPDR |= (GPIO_GPIO10 | GPIO_GPIO12 | GPIO_GPIO13); GPDR &= ~GPIO_GPIO11; GAFR |= (GPIO_GPIO10 | GPIO_GPIO11 | GPIO_GPIO12 | GPIO_GPIO13); PPAR |= PPAR_SSPGPIO; /* * scr bit rate * --- -------- * 255 7200.0 0xff, works * 169 10842.4 0xa9, works * 128 14288.4 0x80, works * 64 28356.9 0x40, works * 32 55854.5 0x20, works * 16 108424 * 8 204800 * 4 368640 * 2 614400 * 1 921600 */ #define SER_CLK 0x80 Ser4SSCR0 = SSCR0_SerClkDiv(SER_CLK) | SSCR0_Motorola | SSCR0_DataSize(8); Ser4SSSR = SSSR_ROR; // original ---> Ser4SSCR1 = SSCR1_SClkIactL | SSCR1_SClk1P; // Ser4SSCR1 = SSCR1_SClkIactL | SSCR1_SClk1P; // Ser4SSCR1 = SSCR1_SClkIactL | SSCR1_SClk1_2P; // Ser4SSCR1 = SSCR1_SClkIactH | SSCR1_SClk1P; // Ser4SSCR1 = SSCR1_SClkIactH | SSCR1_SClk1_2P; Ser4SSCR1 = SSCR1_SClkIactL | SSCR1_SClk1P /*| SSCR1_LBM*/; Ser4SSCR0 |= SSCR0_SSE; /* Release AT89S53 reset line. */ PFS168_SYSLCDDE &= ~0x4; }
/* * Set the SSP audio DMA parameters and sample size. * Can be called multiple times by oss emulation. */ static int pxa3xx_ssp_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai * dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct ssp_device *ssp = cpu_dai->private_data; struct pxa3xx_pcm_dma_params *pcm; u32 sscr0, sspsp; u32 width; pcm = kmalloc(sizeof(struct pxa3xx_pcm_dma_params), GFP_KERNEL); if (pcm == NULL) return -ENOMEM; /* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: sscr0 = __raw_readl(ssp->mmio_base + SSCR0); sscr0 |= SSCR0_DataSize(16); __raw_writel(sscr0, ssp->mmio_base + SSCR0); if ((sscr0 & SSCR0_FPCKE ) || (sscr0 & SSCR0_EDSS)) width = DCMD_WIDTH4; else width = DCMD_WIDTH2; break; case SNDRV_PCM_FORMAT_S32_LE: sscr0 = __raw_readl(ssp->mmio_base + SSCR0); sscr0 |= SSCR0_EDSS | SSCR0_DataSize(16); __raw_writel(sscr0, ssp->mmio_base + SSCR0); width = DCMD_WIDTH4; break; default: return -EINVAL; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { pcm->name = ssp_names[cpu_dai->id][0]; pcm->dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG; pcm->drcmr = &DRCMR(ssp->drcmr_tx); pcm->dev_addr = ssp->phys_base + SSDR; } else { pcm->name = ssp_names[cpu_dai->id][1]; pcm->dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC; pcm->drcmr = &DRCMR(ssp->drcmr_rx); pcm->dev_addr = ssp->phys_base + SSDR; } pcm->dcmd |= DCMD_BURST16 | width; kfree(snd_soc_dai_get_dma_data(cpu_dai, substream)); snd_soc_dai_set_dma_data(cpu_dai, substream, pcm); if (ssp_clk[cpu_dai->id].dai_fmt == SND_SOC_DAIFMT_I2S) { int sfrmwidth = snd_pcm_format_physical_width(params_format(params)); sspsp = __raw_readl(ssp->mmio_base + SSPSP); sspsp |= SSPSP_SFRMWDTH(sfrmwidth); __raw_writel(sspsp, ssp->mmio_base + SSPSP); } return 0; }
/* * Initialise the Assabet audio driver. * * Note that we have to be careful with the order that we do things here; * there is a D-type flip flop which is clocked from the SFRM line which * indicates whether the same is for the left or right channel to the * UDA1341. * * When you disable the SSP (by clearing SSCR0_SSE) it appears that the * SFRM signal can float high. When you re-enable the SSP, you clock the * flip flop once, and end up swapping the left and right channels. * * The ASSABET_BCR_CODEC_RST line will force this flip flop into a known * state, but this line resets other devices as well! * * In addition to the above, it appears that powering down the UDA1341 on * early Assabets leaves the UDA_WS actively driving a logic '1' into the * chip, wasting power! (you can tell this by D11 being half-on). We * attempt to correct this by kicking the flip flop on init/open/close. * We should probably do this on PM resume as well. * * (Note the ordering of ASSABET_BCR_AUDIO_ON, SFRM and ASSABET_BCR_CODEC_RST * is important). */ static void assabet_audio_init(void *dummy) { unsigned long flags; unsigned int mdrefr; local_irq_save(flags); /* * Enable the power for the UDA1341 before driving any signals. * We leave the audio amp (LM4880) disabled for now. */ ASSABET_BCR_set(ASSABET_BCR_AUDIO_ON); #ifdef FIX_POWER_DRAIN GPSR = GPIO_SSP_SFRM; GPCR = GPIO_SSP_SFRM; #endif ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); ASSABET_BCR_clear(ASSABET_BCR_STEREO_LB); /* * Setup the SSP uart. */ PPAR |= PPAR_SPR; Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(2); Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk; GAFR |= GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_CLK; GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM; GPDR &= ~(GPIO_SSP_RXD | GPIO_SSP_CLK); Ser4SSCR0 |= SSCR0_SSE; /* * Only give SFRM to the SSP after it has been enabled. */ GAFR |= GPIO_SSP_SFRM; /* * The assabet board uses the SDRAM clock as the source clock for * audio. This is supplied to the SA11x0 from the CPLD on pin 19. * At 206MHz we need to run the audio clock (SDRAM bank 2) * at half speed. This clock will scale with core frequency so * the audio sample rate will also scale. The CPLD on Assabet * will need to be programmed to match the core frequency. */ mdrefr = MDREFR; if ((mdrefr & (MDREFR_K2DB2 | MDREFR_K2RUN | MDREFR_EAPD | MDREFR_KAPD)) != (MDREFR_K2DB2 | MDREFR_K2RUN)) { mdrefr |= MDREFR_K2DB2 | MDREFR_K2RUN; mdrefr &= ~(MDREFR_EAPD | MDREFR_KAPD); MDREFR = mdrefr; (void) MDREFR; } local_irq_restore(flags); /* Wait for the UDA1341 to wake up */ mdelay(1); l3_open(&uda1341); assabet_set_samplerate(audio_samplerate); /* Enable the audio power */ ASSABET_BCR_clear(ASSABET_BCR_QMUTE | ASSABET_BCR_SPK_OFF); }
struct input_dev *input; struct device *dev; int gpio; int index; u8 data[1 + HEADER_LENGTH(0xff)]; }; /* * Initialization values for SSCR0_x, SSCR1_x, SSSR_x. */ static const u32 sscr0 = 0 | SSCR0_TUM /* TIM = 1; No TUR interrupts */ | SSCR0_RIM /* RIM = 1; No ROR interrupts */ | SSCR0_SSE /* SSE = 1; SSP enabled */ | SSCR0_Motorola /* FRF = 0; Motorola SPI */ | SSCR0_DataSize(16) /* DSS = 15; Data size = 16-bit */ ; static const u32 sscr1 = 0 | SSCR1_SCFR /* SCFR = 1; SSPSCLK only during transfers */ | SSCR1_SCLKDIR /* SCLKDIR = 1; Slave mode */ | SSCR1_SFRMDIR /* SFRMDIR = 1; Slave mode */ | SSCR1_RWOT /* RWOT = 1; Receive without transmit mode */ | SSCR1_RxTresh(1) /* RFT = 0; Receive FIFO threshold = 1 */ | SSCR1_SPH /* SPH = 1; SSPSCLK inactive 0.5 + 1 cycles */ | SSCR1_RIE /* RIE = 1; Receive FIFO interrupt enabled */ ; static const u32 sssr = 0 | SSSR_BCE /* BCE = 1; Clear BCE */ | SSSR_TUR /* TUR = 1; Clear TUR */ | SSSR_EOC /* EOC = 1; Clear EOC */ | SSSR_TINT /* TINT = 1; Clear TINT */
/* * Set the SSP audio DMA parameters and sample size. * Can be called multiple times by oss emulation. */ static int pxa3xx_ssp_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai * dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct ssp_device *ssp = cpu_dai->private_data; struct pxa3xx_pcm_dma_params *pcm_o, *pcm_i; u32 sscr0, sspsp; u32 width; pcm_o = kmalloc(sizeof(struct pxa3xx_pcm_dma_params), GFP_KERNEL); pcm_i = kmalloc(sizeof(struct pxa3xx_pcm_dma_params), GFP_KERNEL); pcm_o->name = ssp_names[cpu_dai->id][0]; pcm_i->name = ssp_names[cpu_dai->id][1]; //printk("pxa3xx_ssp_hw_params()\n"); /* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: // printk("SNDRV_PCM_FORMAT_S16_LE\n"); sscr0 = __raw_readl(ssp->mmio_base + SSCR0); sscr0 |= SSCR0_DataSize(16); __raw_writel(sscr0, ssp->mmio_base + SSCR0); if ((sscr0 & SSCR0_FPCKE ) || (sscr0 & SSCR0_EDSS)) width = DCMD_WIDTH4; else width = DCMD_WIDTH2; break; case SNDRV_PCM_FORMAT_S32_LE: //printk("SNDRV_PCM_FORMAT_S32_LE\n"); sscr0 = __raw_readl(ssp->mmio_base + SSCR0); sscr0 |= SSCR0_EDSS | SSCR0_DataSize(16); __raw_writel(sscr0, ssp->mmio_base + SSCR0); width = DCMD_WIDTH4; break; default: return -EINVAL; } pcm_o->dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST16 | width; pcm_i->dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST16 | width; pcm_o->drcmr = &DRCMR(ssp->drcmr_tx); pcm_i->drcmr = &DRCMR(ssp->drcmr_rx); pcm_o->dev_addr = ssp->phys_base + SSDR; pcm_i->dev_addr = ssp->phys_base + SSDR; /* select correct DMA params */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) cpu_dai->dma_data = pcm_o; else cpu_dai->dma_data = pcm_i; if (ssp_clk[cpu_dai->id].dai_fmt == SND_SOC_DAIFMT_I2S) { int sfrmwidth = snd_pcm_format_physical_width(params_format(params)); sspsp = __raw_readl(ssp->mmio_base + SSPSP); sspsp |= SSPSP_SFRMWDTH(sfrmwidth); __raw_writel(sspsp, ssp->mmio_base + SSPSP); } /* printk("SSPSP: 0x%08lX\n", __raw_readl(ssp->mmio_base + SSPSP)); printk("SSCR0: 0x%08lX\n", __raw_readl(ssp->mmio_base + SSCR0)); printk("SSCR1: 0x%08lX\n", __raw_readl(ssp->mmio_base + SSCR1)); */ return 0; }