📄 omap-tsc2101.c
字号:
The source of the clock signal to be used for divide by B circuit is the CODEC Master system clock: CLKS = 0 (deleted). Divide by 4 (MCLK = 11.289 MHz, 64 CSCLK cycle per frame : MCLK must be divided by 4 to achieve a 44.1 kHz frame frequency) : DIVB = 0x3 */ writew(0x3,OMAP24XX_EAC_CPCFR4);#endif /* Codec port enable . RX/TX interrupts are not enabled*/ writew(0x8,OMAP24XX_EAC_CPTCTL); /* only K1 and K5 are closed for playback and record */ writew(0x11,OMAP24XX_EAC_AMSCFR); //w = readw(OMAP24XX_EAC_AGCTR); /* DMA read/write enable */ //w|=0x1800; //w |=0x1000 | 0x8 | 0x2; //writew(w,OMAP24XX_EAC_AGCTR); /* DMA write read volume */ //writew(0xFF&219, OMAP24XX_EAC_AMVCTR);#ifdef TEST_PLAY test_play(dev);#endif return 0;}static int eac_samplerate(struct device *dev, unsigned int rate, struct omap_samplerate_info *sr){ u16 w; int fsint; DPRINTK("EAC_SAMPLERATE"); /* We don't want to mess with clocks when frames are in flight */ /* wait for any frame to complete */ udelay(125); sr->fs_44kHz=1; sr->divisor=0; //division to 1 sr->pll0=0x811C; sr->pll1=0x5240; /* * We have the following clock sources: * 12.000 MHz * * Available sampling rates: * 48kHz, 44.1kHz, 32kHz, 29.4kHz, 24kHz, * 22 kHz, 16 kHz, 14.7kHz, 12kHz, 11kHz, * 9.6kHz, 8.8kHz, 8kHz, (7.3kHz) * Won't bother supporting those in (). *//* fsint values0x0000: 8kHz 0x0001: 11.025kHz 0x0010: 16kHz 0x0011: 22.05kHz 0x0100: 24kHz 0x0101: 32kHz 0x0110: 44.1kHz 0x0111: 48kHz*/ if (rate >= 48000) { fsint = 0x7; rate = 48000; } else if (rate >= 44100) { fsint = 0x6; rate = 44100; } else if (rate >= 32000) { fsint = 0x6; rate = 32000; } else if (rate >= 24000) { fsint = 0x5; rate = 24000; } else if (rate >= 22050) { fsint = 0x4; rate = 22050; } else if (rate >= 16000) { fsint = 0x3; rate = 16000; } else if (rate >= 11025) { fsint = 0x2; rate = 11025; } else { fsint = 0x1; rate = 8000; } /* Audio codec TSC2101 is always set to PCM/stereo/16Bit/Little Endian/44100 */ /* commented for virtio .... need to be debugged for aptix on virtio platform it seems that this disturbs the default settings */ //tsc2101_configure(sr); /* little endian , 16 bit , stereo */ writew(0x0600,OMAP24XX_EAC_AGCFR); w = 0x0; w |= fsint << 9; /* Bluetooth port clock is forced to 12 MHz from CLK12M_INT: BT_CKSRC = 0x1 Modem port clock is forced to 12 MHz from CLK12M_INT: MD_CKSRC = 0x1 MCLK_INT clock is used: AUD_CKSRC = 0x0 The internal 12-MHz clock comes from the 96-MHz clock divided by 8: CLK12M_INT = 0x1 The codec master clock comes from the 96-MHz clock divided by 8.5 (11.28 MHz) MCLKINT_SEL = 0x1. */ w |= 0xA3; writew(w,OMAP24XX_EAC_AGCFR3); return 0;}static void eac_suspend(struct device *dev){}static void eac_resume(struct device *dev){}static struct omap_snd_ops eac_ops = { .name = "eac", .startup = eac_init, .shutdown = eac_shutdown, .setruntime = eac_setruntime, .samplerate = eac_samplerate, .suspend = eac_suspend, .resume = eac_resume,};/*--------------------End --eac specific functions--------------------*/struct ssp_tsc2101 { struct device *dev; struct omap_snd_ops *ops; struct Tsc2101 *tsc; snd_pcm_t *pcm;};#ifdef CONFIG_PMstatic int omap_tsc2101_do_suspend(snd_card_t *card){ struct ssp_tsc2101 *ssp = card->private_data; if (card->power_state != SNDRV_CTL_POWER_D3cold) { snd_pcm_suspend_all(ssp->pcm); tsc2101_suspend(ssp->tsc); if (ssp->ops->suspend) ssp->ops->suspend(card->dev); snd_power_change_state(card, SNDRV_CTL_POWER_D3cold); } return 0;}static int omap_tsc2101_do_resume(snd_card_t *card){ struct ssp_tsc2101 *ssp = card->private_data; if (card->power_state != SNDRV_CTL_POWER_D0) { if (ssp->ops->resume) ssp->ops->resume(card->dev); tsc2101_resume(ssp->tsc); snd_power_change_state(card, SNDRV_CTL_POWER_D0); } return 0;}static int omap_tsc2101_set_power_state(snd_card_t *card, unsigned state){ int ret = -EINVAL; switch (state) { case SNDRV_CTL_POWER_D0: case SNDRV_CTL_POWER_D1: case SNDRV_CTL_POWER_D2: ret =omap_tsc2101_do_resume(card); break; case SNDRV_CTL_POWER_D3hot: case SNDRV_CTL_POWER_D3cold: ret =omap_tsc2101_do_suspend(card); break; } return ret;}#endifstatic int omap_tsc2101_startup(snd_card_t *card){ struct ssp_tsc2101 *ssp = card->private_data; unsigned long flags; int ret; local_irq_save(flags); ret = ssp->ops->startup(card->dev); if (ret) goto out; DPRINTK("McBSP_Init()done, calling tsc2101_open()"); /* * Wait for the TSC2101 to wake up */ mdelay(1); tsc2101_open(ssp->tsc); out: local_irq_restore(flags); return ret;}static int omap_tsc2101_setruntime(snd_card_t *card, snd_pcm_runtime_t *runtime){ struct ssp_tsc2101 *ssp = card->private_data; return ssp->ops->setruntime(card->dev, runtime); DPRINTK("calling McBSP_setruntime()");}static void omap_tsc2101_shutdown(snd_card_t *card){ struct ssp_tsc2101 *ssp = card->private_data; ssp->ops->shutdown(card->dev); DPRINTK("After McBSP_Shutdown, calling tsc2101_close()"); tsc2101_close(ssp->tsc);}static int omap_tsc2101_samplerate(snd_card_t *card, unsigned int rate){ struct ssp_tsc2101 *ssp = card->private_data; struct omap_samplerate_info rateinfo; struct tsc2101_cfg cfg; /* * We don't want to mess with clocks when frames are in flight */ /* * wait for any frame to complete */ udelay(125); ssp->ops->samplerate(card->dev, rate, &rateinfo); //cfg.fs = rateinfo.fs; cfg.format = FMT_WLEN16; tsc2101_write(TSC2101_AUDIO_CTRL_1 , cfg.format); DPRINTK("rate = %u,format = %d", rate,cfg.format); return 0;}static struct omap_pcm_ops omap_tsc2101_ops = { .startup = omap_tsc2101_startup, .shutdown = omap_tsc2101_shutdown, .setruntime = omap_tsc2101_setruntime, .samplerate = omap_tsc2101_samplerate,};static int omap_tsc2101_probe(struct device *dev){ snd_card_t *card; struct ssp_tsc2101 *ssp; int ret; DPRINTK("IN omap_tsc2101_probe()"); //dev->platform_data = &McBSP_ops; dev->platform_data = &eac_ops; card = snd_card_new(0, "OMAP1610_TSC2101", THIS_MODULE, sizeof(struct ssp_tsc2101)); if (card == NULL) { ret = -ENOMEM; goto out; } DPRINTK("exiting snd_card_new"); DPRINTK("card = %u",(unsigned int)card); sprintf(card->longname, "OMAP1610 TSC2101"); card->dev = dev; ssp = card->private_data; ssp->dev = dev; ssp->ops = dev->platform_data; strncpy(card->driver, "omap-tsc2101", sizeof(card->driver)); snprintf(card->shortname, sizeof(card->shortname), "%s-%s", card->driver, ssp->ops->name); strcpy(card->id,"card0"); DPRINTK("card->id=%s",card->id); DPRINTK("card_num=%d,card_id= %s, driver = %s,name = %s,shortname= %s",card->number,card->id,card->driver,ssp->ops->name,card->shortname);#ifdef CONFIG_PM card->set_power_state = omap_tsc2101_set_power_state;#endif ssp->pcm = omap_pcm_create(card, &omap_tsc2101_ops, eAudioTx, eAudioRx); if (IS_ERR(ssp->pcm)) { ret = PTR_ERR(ssp->pcm); goto out; } DPRINTK("Back from omap_pcm_create(),entering tsc2101_create()"); ssp->tsc = tsc2101_create(card); DPRINTK("Done tsc2101_create"); if (IS_ERR(ssp->tsc)) { ret = PTR_ERR(ssp->tsc); DPRINTK("error tsc2101_create not successful"); goto out; } ret = snd_card_register(card); if (ret == 0) { DPRINTK("ret=%d",ret); dev_set_drvdata(dev, card); DPRINTK("Card registered"); return 0; }// DPRINTK("Card registered"); out: if (card) { DPRINTK("freeing snd_card"); snd_card_free(card); } return ret;}static int omap_tsc2101_remove(struct device *dev){ snd_card_t *card = dev_get_drvdata(dev); if (card) snd_card_free(card); DPRINTK("Remove driver"); dev_set_drvdata(dev, NULL); return 0;}#ifdef CONFIG_PMstatic int omap_tsc2101_suspend(struct device *_dev, u32 state, u32 level){ snd_card_t *card = dev_get_drvdata(_dev); int ret = 0; if (card && level == SUSPEND_DISABLE) ret = omap_tsc2101_do_suspend(card); return ret;}static int omap_tsc2101_resume(struct device *_dev, u32 level){ snd_card_t *card = dev_get_drvdata(_dev); int ret = 0; if (card && level == RESUME_ENABLE) ret = omap_tsc2101_do_resume(card); return ret;}#endifstatic struct device_driver omap_tsc2101_driver = { .name = "omap-ssp", .bus = &platform_bus_type, .probe = omap_tsc2101_probe, .remove = omap_tsc2101_remove,#ifdef CONFIG_PM .suspend = omap_tsc2101_suspend, .resume = omap_tsc2101_resume,#endif};static struct device omap_sound_device = { //.name = "OMAP sound device", .bus_id = "McBSP", .driver = &omap_tsc2101_driver,};static struct omap_driver sound_omap_driver = { .drv = { .name = "omap sound driver", }, .devid = 3, .busid = OMAP_BUS_L3, .clocks = 0, .probe = omap_tsc2101_probe, .remove = omap_tsc2101_remove,};static struct omap_dev sound_omap_device = { .name = "OMAP sound device", .devid = 3, .busid = OMAP_BUS_L3,};static int __init omap_tsc2101_init(void){ DPRINTK("In __init");/* driver_register(&omap_tsc2101_driver); return device_register(&omap_sound_device);*/ omap_driver_register(&sound_omap_driver); return omap_device_register(&sound_omap_device);}static void __exit omap_tsc2101_exit(void){ DPRINTK("In __exit"); driver_unregister(&omap_tsc2101_driver);}module_init(omap_tsc2101_init);module_exit(omap_tsc2101_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -