1/* 2 * SoC audio for BCM94717BU Board 3 * 4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * $Id: bcm94717bu.c,v 1.1 2009/10/30 20:41:44 Exp $ 19 */ 20 21 22#include <linux/module.h> 23#include <linux/moduleparam.h> 24#include <linux/timer.h> 25#include <linux/interrupt.h> 26#include <linux/platform_device.h> 27#include <sound/driver.h> 28#include <sound/core.h> 29#include <sound/pcm.h> 30#include <sound/soc.h> 31#include <sound/soc-dapm.h> 32#include <linux/i2c-gpio.h> 33 34#include <typedefs.h> 35#include <bcmdevs.h> 36#include <pcicfg.h> 37#include <hndsoc.h> 38#include <osl.h> 39#include <bcmutils.h> 40#include <siutils.h> 41#include <sbhnddma.h> 42#include <hnddma.h> 43#include <i2s_core.h> 44 45 46#include "../codecs/wm8750.h" 47#include "bcm947xx-pcm.h" 48#include "bcm947xx-i2s.h" 49 50#define BCM947XX_BU_DEBUG 0 51#if BCM947XX_BU_DEBUG 52#define DBG(x...) printk(KERN_ERR x) 53#else 54#define DBG(x...) 55#endif 56 57 58 /* MCLK in Hz - to bcm94717 & Wolfson 8750 */ 59#define BCM94717BU_MCLK_FREQ 12288000 60 61 62static int bcm94717bu_startup(struct snd_pcm_substream *substream) 63{ 64 //struct snd_soc_pcm_runtime *rtd = substream->private_data; 65 //struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 66 //struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 67 int ret = 0; 68 69 //DBG("%s:\n", __FUNCTION__); 70 71 return ret; 72} 73 74static void bcm94717bu_shutdown(struct snd_pcm_substream *substream) 75{ 76 //DBG("%s\n", __FUNCTION__); 77 return; 78} 79 80static int bcm94717bu_hw_params(struct snd_pcm_substream *substream, 81 struct snd_pcm_hw_params *params) 82{ 83 struct snd_soc_pcm_runtime *rtd = substream->private_data; 84 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; 85 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; 86 unsigned int fmt; 87 88 int ret = 0; 89 90 fmt = SND_SOC_DAIFMT_I2S | /* I2S mode audio */ 91 SND_SOC_DAIFMT_NB_NF | /* BCLK not inverted and normal LRCLK polarity */ 92 SND_SOC_DAIFMT_CBS_CFS; /* BCM947xx is I2S Master / codec is slave */ 93 94 /* set codec DAI configuration */ 95 ret = codec_dai->dai_ops.set_fmt(codec_dai, fmt); 96 if (ret < 0) 97 return ret; 98 99 /* set cpu DAI configuration */ 100 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, fmt); 101 if (ret < 0) 102 return ret; 103 104 /* set the codec system clock for DAC and ADC */ 105 ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8750_SYSCLK, BCM94717BU_MCLK_FREQ, 106 SND_SOC_CLOCK_IN); 107 if (ret < 0) 108 return ret; 109 110 /* set the I2S system clock as input (unused) */ 111 ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, BCM947XX_I2S_SYSCLK, BCM94717BU_MCLK_FREQ, 112 SND_SOC_CLOCK_IN); 113 114 if (ret < 0) 115 return ret; 116 117 return 0; 118} 119 120static struct snd_soc_ops bcm94717bu_ops = { 121 .startup = bcm94717bu_startup, 122 .hw_params = bcm94717bu_hw_params, 123 .shutdown = bcm94717bu_shutdown, 124}; 125 126/* 127 * Logic for a wm8750 128 */ 129static int bcm94717bu_wm8750_init(struct snd_soc_codec *codec) 130{ 131 DBG("%s\n", __FUNCTION__); 132 133 snd_soc_dapm_sync_endpoints(codec); 134 135 return 0; 136} 137 138/* bcm94717bu digital audio interface glue - connects codec <--> CPU */ 139static struct snd_soc_dai_link bcm94717bu_dai = { 140 .name = "WM8750", 141 .stream_name = "WM8750", 142 .cpu_dai = &bcm947xx_i2s_dai, 143 .codec_dai = &wm8750_dai, 144 .init = bcm94717bu_wm8750_init, 145 .ops = &bcm94717bu_ops, 146}; 147 148/* bcm94717bu audio machine driver */ 149static struct snd_soc_machine snd_soc_machine_bcm94717bu = { 150 .name = "Bcm94717bu", 151 .dai_link = &bcm94717bu_dai, 152 .num_links = 1, 153}; 154 155/* bcm94717bu audio private data */ 156static struct wm8750_setup_data bcm94717bu_wm8750_setup = { 157 .i2c_address = 0x1a, /* 2wire / I2C interface */ 158}; 159 160/* bcm94717bu audio subsystem */ 161static struct snd_soc_device bcm94717bu_snd_devdata = { 162 .machine = &snd_soc_machine_bcm94717bu, 163 .platform = &bcm947xx_soc_platform, 164 .codec_dev = &soc_codec_dev_wm8750, 165 .codec_data = &bcm94717bu_wm8750_setup, 166}; 167 168static struct platform_device *bcm94717bu_snd_device; 169 170static int machine_is_bcm94717bu(void) 171{ 172 DBG("%s\n", __FUNCTION__); 173 return 1; 174} 175 176 177 178static struct i2c_gpio_platform_data i2c_gpio_data = { 179 .sda_pin = 1, 180 .scl_pin = 4, 181}; 182 183static struct platform_device i2c_gpio_device = { 184 .name = "i2c-gpio", 185 .id = 0, 186 .dev = { 187 .platform_data = &i2c_gpio_data, 188 }, 189}; 190 191 192static int __init bcm94717bu_init(void) 193{ 194 int ret; 195 196 DBG("%s\n", __FUNCTION__); 197 198 if (!machine_is_bcm94717bu()) 199 return -ENODEV; 200 201 ret = platform_device_register(&i2c_gpio_device); 202 if (ret) { 203 platform_device_put(&i2c_gpio_device); 204 return ret; 205 } 206 207 bcm94717bu_snd_device = platform_device_alloc("soc-audio", -1); 208 if (!bcm94717bu_snd_device) 209 return -ENOMEM; 210 211 platform_set_drvdata(bcm94717bu_snd_device, &bcm94717bu_snd_devdata); 212 bcm94717bu_snd_devdata.dev = &bcm94717bu_snd_device->dev; 213 ret = platform_device_add(bcm94717bu_snd_device); 214 215 if (ret) { 216 platform_device_put(bcm94717bu_snd_device); 217 } 218 219 return ret; 220} 221 222static void __exit bcm94717bu_exit(void) 223{ 224 platform_device_unregister(bcm94717bu_snd_device); 225} 226 227module_init(bcm94717bu_init); 228module_exit(bcm94717bu_exit); 229 230/* Module information */ 231MODULE_DESCRIPTION("ALSA SoC BCM94717BU"); 232MODULE_LICENSE("GPL"); 233