1/* 2 * File: sound/soc/blackfin/bf5xx-ssm2602.c 3 * Author: Cliff Cai <Cliff.Cai@analog.com> 4 * 5 * Created: Tue June 06 2008 6 * Description: board driver for SSM2602 sound chip 7 * 8 * Modified: 9 * Copyright 2008 Analog Devices Inc. 10 * 11 * Bugs: Enter bugs at http://blackfin.uclinux.org/ 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, see the file COPYING, or write 25 * to the Free Software Foundation, Inc., 26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 27 */ 28 29#include <linux/module.h> 30#include <linux/moduleparam.h> 31#include <linux/device.h> 32 33#include <sound/core.h> 34#include <sound/pcm.h> 35#include <sound/soc.h> 36#include <sound/soc-dapm.h> 37#include <sound/pcm_params.h> 38 39#include <asm/dma.h> 40#include <asm/portmux.h> 41#include <linux/gpio.h> 42#include "../codecs/ssm2602.h" 43#include "bf5xx-sport.h" 44#include "bf5xx-i2s-pcm.h" 45#include "bf5xx-i2s.h" 46 47static struct snd_soc_card bf5xx_ssm2602; 48 49static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) 50{ 51 struct snd_soc_pcm_runtime *rtd = substream->private_data; 52 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 53 54 pr_debug("%s enter\n", __func__); 55 cpu_dai->private_data = sport_handle; 56 return 0; 57} 58 59static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream, 60 struct snd_pcm_hw_params *params) 61{ 62 struct snd_soc_pcm_runtime *rtd = substream->private_data; 63 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 64 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 65 unsigned int clk = 0; 66 int ret = 0; 67 68 pr_debug("%s rate %d format %x\n", __func__, params_rate(params), 69 params_format(params)); 70 /* 71 * If you are using a crystal source which frequency is not 12MHz 72 * then modify the below case statement with frequency of the crystal. 73 * 74 * If you are using the SPORT to generate clocking then this is 75 * where to do it. 76 */ 77 78 switch (params_rate(params)) { 79 case 8000: 80 case 16000: 81 case 48000: 82 case 96000: 83 case 11025: 84 case 22050: 85 case 44100: 86 clk = 12000000; 87 break; 88 } 89 90 /* 91 * CODEC is master for BCLK and LRC in this configuration. 92 */ 93 94 /* set codec DAI configuration */ 95 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 96 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 97 if (ret < 0) 98 return ret; 99 /* set cpu DAI configuration */ 100 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 101 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 102 if (ret < 0) 103 return ret; 104 105 ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk, 106 SND_SOC_CLOCK_IN); 107 if (ret < 0) 108 return ret; 109 110 return 0; 111} 112 113static struct snd_soc_ops bf5xx_ssm2602_ops = { 114 .startup = bf5xx_ssm2602_startup, 115 .hw_params = bf5xx_ssm2602_hw_params, 116}; 117 118static struct snd_soc_dai_link bf5xx_ssm2602_dai = { 119 .name = "ssm2602", 120 .stream_name = "SSM2602", 121 .cpu_dai = &bf5xx_i2s_dai, 122 .codec_dai = &ssm2602_dai, 123 .ops = &bf5xx_ssm2602_ops, 124}; 125 126/* 127 * SSM2602 2 wire address is determined by CSB 128 * state during powerup. 129 * low = 0x1a 130 * high = 0x1b 131 */ 132 133static struct ssm2602_setup_data bf5xx_ssm2602_setup = { 134 .i2c_bus = 0, 135 .i2c_address = 0x1b, 136}; 137 138static struct snd_soc_card bf5xx_ssm2602 = { 139 .name = "bf5xx_ssm2602", 140 .platform = &bf5xx_i2s_soc_platform, 141 .dai_link = &bf5xx_ssm2602_dai, 142 .num_links = 1, 143}; 144 145static struct snd_soc_device bf5xx_ssm2602_snd_devdata = { 146 .card = &bf5xx_ssm2602, 147 .codec_dev = &soc_codec_dev_ssm2602, 148 .codec_data = &bf5xx_ssm2602_setup, 149}; 150 151static struct platform_device *bf5xx_ssm2602_snd_device; 152 153static int __init bf5xx_ssm2602_init(void) 154{ 155 int ret; 156 157 pr_debug("%s enter\n", __func__); 158 bf5xx_ssm2602_snd_device = platform_device_alloc("soc-audio", -1); 159 if (!bf5xx_ssm2602_snd_device) 160 return -ENOMEM; 161 162 platform_set_drvdata(bf5xx_ssm2602_snd_device, 163 &bf5xx_ssm2602_snd_devdata); 164 bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev; 165 ret = platform_device_add(bf5xx_ssm2602_snd_device); 166 167 if (ret) 168 platform_device_put(bf5xx_ssm2602_snd_device); 169 170 return ret; 171} 172 173static void __exit bf5xx_ssm2602_exit(void) 174{ 175 pr_debug("%s enter\n", __func__); 176 platform_device_unregister(bf5xx_ssm2602_snd_device); 177} 178 179module_init(bf5xx_ssm2602_init); 180module_exit(bf5xx_ssm2602_exit); 181 182/* Module information */ 183MODULE_AUTHOR("Cliff Cai"); 184MODULE_DESCRIPTION("ALSA SoC SSM2602 BF527-EZKIT"); 185MODULE_LICENSE("GPL"); 186