Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.9 181 lines 4.4 kB view raw
1/* 2 * ASoC driver for Lyrtech SFFSDR board. 3 * 4 * Author: Hugo Villeneuve 5 * Copyright (C) 2008 Lyrtech inc 6 * 7 * Based on ASoC driver for TI DAVINCI EVM platform, original copyright follow: 8 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15#include <linux/module.h> 16#include <linux/moduleparam.h> 17#include <linux/timer.h> 18#include <linux/interrupt.h> 19#include <linux/platform_device.h> 20#include <linux/gpio.h> 21#include <sound/core.h> 22#include <sound/pcm.h> 23#include <sound/soc.h> 24 25#include <asm/dma.h> 26#include <asm/mach-types.h> 27#ifdef CONFIG_SFFSDR_FPGA 28#include <asm/plat-sffsdr/sffsdr-fpga.h> 29#endif 30 31#include <mach/edma.h> 32 33#include "../codecs/pcm3008.h" 34#include "davinci-pcm.h" 35#include "davinci-i2s.h" 36 37/* 38 * CLKX and CLKR are the inputs for the Sample Rate Generator. 39 * FSX and FSR are outputs, driven by the sample Rate Generator. 40 */ 41#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ 42 SND_SOC_DAIFMT_CBM_CFS | \ 43 SND_SOC_DAIFMT_IB_NF) 44 45static int sffsdr_hw_params(struct snd_pcm_substream *substream, 46 struct snd_pcm_hw_params *params) 47{ 48 struct snd_soc_pcm_runtime *rtd = substream->private_data; 49 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 50 int fs; 51 int ret = 0; 52 53 /* Fsref can be 32000, 44100 or 48000. */ 54 fs = params_rate(params); 55 56#ifndef CONFIG_SFFSDR_FPGA 57 /* Without the FPGA module, the Fs is fixed at 44100 Hz */ 58 if (fs != 44100) { 59 pr_debug("warning: only 44.1 kHz is supported without SFFSDR FPGA module\n"); 60 return -EINVAL; 61 } 62#endif 63 64 /* set cpu DAI configuration */ 65 ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); 66 if (ret < 0) 67 return ret; 68 69 pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs); 70 71#ifndef CONFIG_SFFSDR_FPGA 72 return 0; 73#else 74 return sffsdr_fpga_set_codec_fs(fs); 75#endif 76} 77 78static struct snd_soc_ops sffsdr_ops = { 79 .hw_params = sffsdr_hw_params, 80}; 81 82/* davinci-sffsdr digital audio interface glue - connects codec <--> CPU */ 83static struct snd_soc_dai_link sffsdr_dai = { 84 .name = "PCM3008", /* Codec name */ 85 .stream_name = "PCM3008 HiFi", 86 .cpu_dai_name = "davinci-mcbsp", 87 .codec_dai_name = "pcm3008-hifi", 88 .codec_name = "pcm3008-codec", 89 .platform_name = "davinci-mcbsp", 90 .ops = &sffsdr_ops, 91}; 92 93/* davinci-sffsdr audio machine driver */ 94static struct snd_soc_card snd_soc_sffsdr = { 95 .name = "DaVinci SFFSDR", 96 .owner = THIS_MODULE, 97 .dai_link = &sffsdr_dai, 98 .num_links = 1, 99}; 100 101/* sffsdr audio private data */ 102static struct pcm3008_setup_data sffsdr_pcm3008_setup = { 103 .dem0_pin = GPIO(45), 104 .dem1_pin = GPIO(46), 105 .pdad_pin = GPIO(47), 106 .pdda_pin = GPIO(38), 107}; 108 109struct platform_device pcm3008_codec = { 110 .name = "pcm3008-codec", 111 .id = 0, 112 .dev = { 113 .platform_data = &sffsdr_pcm3008_setup, 114 }, 115}; 116 117static struct resource sffsdr_snd_resources[] = { 118 { 119 .start = DAVINCI_MCBSP_BASE, 120 .end = DAVINCI_MCBSP_BASE + SZ_8K - 1, 121 .flags = IORESOURCE_MEM, 122 }, 123}; 124 125static struct evm_snd_platform_data sffsdr_snd_data = { 126 .tx_dma_ch = DAVINCI_DMA_MCBSP_TX, 127 .rx_dma_ch = DAVINCI_DMA_MCBSP_RX, 128}; 129 130static struct platform_device *sffsdr_snd_device; 131 132static int __init sffsdr_init(void) 133{ 134 int ret; 135 136 if (!machine_is_sffsdr()) 137 return -EINVAL; 138 139 platform_device_register(&pcm3008_codec); 140 141 sffsdr_snd_device = platform_device_alloc("soc-audio", 0); 142 if (!sffsdr_snd_device) { 143 printk(KERN_ERR "platform device allocation failed\n"); 144 return -ENOMEM; 145 } 146 147 platform_set_drvdata(sffsdr_snd_device, &snd_soc_sffsdr); 148 platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data, 149 sizeof(sffsdr_snd_data)); 150 151 ret = platform_device_add_resources(sffsdr_snd_device, 152 sffsdr_snd_resources, 153 ARRAY_SIZE(sffsdr_snd_resources)); 154 if (ret) { 155 printk(KERN_ERR "platform device add resources failed\n"); 156 goto error; 157 } 158 159 ret = platform_device_add(sffsdr_snd_device); 160 if (ret) 161 goto error; 162 163 return ret; 164 165error: 166 platform_device_put(sffsdr_snd_device); 167 return ret; 168} 169 170static void __exit sffsdr_exit(void) 171{ 172 platform_device_unregister(sffsdr_snd_device); 173 platform_device_unregister(&pcm3008_codec); 174} 175 176module_init(sffsdr_init); 177module_exit(sffsdr_exit); 178 179MODULE_AUTHOR("Hugo Villeneuve"); 180MODULE_DESCRIPTION("Lyrtech SFFSDR ASoC driver"); 181MODULE_LICENSE("GPL");