linux/sound/soc/s3c24xx/jive_wm8750.c
<<
>>
Prefs
   1/* sound/soc/s3c24xx/jive_wm8750.c
   2 *
   3 * Copyright 2007,2008 Simtec Electronics
   4 *
   5 * Based on sound/soc/pxa/spitz.c
   6 *      Copyright 2005 Wolfson Microelectronics PLC.
   7 *      Copyright 2005 Openedhand Ltd.
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12*/
  13
  14#include <linux/module.h>
  15#include <linux/moduleparam.h>
  16#include <linux/timer.h>
  17#include <linux/interrupt.h>
  18#include <linux/platform_device.h>
  19#include <linux/clk.h>
  20
  21#include <sound/core.h>
  22#include <sound/pcm.h>
  23#include <sound/soc.h>
  24#include <sound/soc-dapm.h>
  25
  26#include <asm/mach-types.h>
  27
  28#include "s3c24xx-pcm.h"
  29#include "s3c2412-i2s.h"
  30
  31#include "../codecs/wm8750.h"
  32
  33static const struct snd_soc_dapm_route audio_map[] = {
  34        { "Headphone Jack", NULL, "LOUT1" },
  35        { "Headphone Jack", NULL, "ROUT1" },
  36        { "Internal Speaker", NULL, "LOUT2" },
  37        { "Internal Speaker", NULL, "ROUT2" },
  38        { "LINPUT1", NULL, "Line Input" },
  39        { "RINPUT1", NULL, "Line Input" },
  40};
  41
  42static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
  43        SND_SOC_DAPM_HP("Headphone Jack", NULL),
  44        SND_SOC_DAPM_SPK("Internal Speaker", NULL),
  45        SND_SOC_DAPM_LINE("Line In", NULL),
  46};
  47
  48static int jive_hw_params(struct snd_pcm_substream *substream,
  49                          struct snd_pcm_hw_params *params)
  50{
  51        struct snd_soc_pcm_runtime *rtd = substream->private_data;
  52        struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
  53        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
  54        struct s3c_i2sv2_rate_calc div;
  55        unsigned int clk = 0;
  56        int ret = 0;
  57
  58        switch (params_rate(params)) {
  59        case 8000:
  60        case 16000:
  61        case 48000:
  62        case 96000:
  63                clk = 12288000;
  64                break;
  65        case 11025:
  66        case 22050:
  67        case 44100:
  68                clk = 11289600;
  69                break;
  70        }
  71
  72        s3c_i2sv2_iis_calc_rate(&div, NULL, params_rate(params),
  73                                s3c2412_get_iisclk());
  74
  75        /* set codec DAI configuration */
  76        ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
  77                                  SND_SOC_DAIFMT_NB_NF |
  78                                  SND_SOC_DAIFMT_CBS_CFS);
  79        if (ret < 0)
  80                return ret;
  81
  82        /* set cpu DAI configuration */
  83        ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
  84                                  SND_SOC_DAIFMT_NB_NF |
  85                                  SND_SOC_DAIFMT_CBS_CFS);
  86        if (ret < 0)
  87                return ret;
  88
  89        /* set the codec system clock for DAC and ADC */
  90        ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
  91                                     SND_SOC_CLOCK_IN);
  92        if (ret < 0)
  93                return ret;
  94
  95        ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_RCLK, div.fs_div);
  96        if (ret < 0)
  97                return ret;
  98
  99        ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_PRESCALER,
 100                                     div.clk_div - 1);
 101        if (ret < 0)
 102                return ret;
 103
 104        return 0;
 105}
 106
 107static struct snd_soc_ops jive_ops = {
 108        .hw_params      = jive_hw_params,
 109};
 110
 111static int jive_wm8750_init(struct snd_soc_codec *codec)
 112{
 113        int err;
 114
 115        /* These endpoints are not being used. */
 116        snd_soc_dapm_nc_pin(codec, "LINPUT2");
 117        snd_soc_dapm_nc_pin(codec, "RINPUT2");
 118        snd_soc_dapm_nc_pin(codec, "LINPUT3");
 119        snd_soc_dapm_nc_pin(codec, "RINPUT3");
 120        snd_soc_dapm_nc_pin(codec, "OUT3");
 121        snd_soc_dapm_nc_pin(codec, "MONO");
 122
 123        /* Add jive specific widgets */
 124        err = snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
 125                                        ARRAY_SIZE(wm8750_dapm_widgets));
 126        if (err) {
 127                printk(KERN_ERR "%s: failed to add widgets (%d)\n",
 128                       __func__, err);
 129                return err;
 130        }
 131
 132        snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
 133        snd_soc_dapm_sync(codec);
 134
 135        return 0;
 136}
 137
 138static struct snd_soc_dai_link jive_dai = {
 139        .name           = "wm8750",
 140        .stream_name    = "WM8750",
 141        .cpu_dai        = &s3c2412_i2s_dai,
 142        .codec_dai      = &wm8750_dai,
 143        .init           = jive_wm8750_init,
 144        .ops            = &jive_ops,
 145};
 146
 147/* jive audio machine driver */
 148static struct snd_soc_card snd_soc_machine_jive = {
 149        .name           = "Jive",
 150        .platform       = &s3c24xx_soc_platform,
 151        .dai_link       = &jive_dai,
 152        .num_links      = 1,
 153};
 154
 155/* jive audio private data */
 156static struct wm8750_setup_data jive_wm8750_setup = {
 157};
 158
 159/* jive audio subsystem */
 160static struct snd_soc_device jive_snd_devdata = {
 161        .card           = &snd_soc_machine_jive,
 162        .codec_dev      = &soc_codec_dev_wm8750,
 163        .codec_data     = &jive_wm8750_setup,
 164};
 165
 166static struct platform_device *jive_snd_device;
 167
 168static int __init jive_init(void)
 169{
 170        int ret;
 171
 172        if (!machine_is_jive())
 173                return 0;
 174
 175        printk("JIVE WM8750 Audio support\n");
 176
 177        jive_snd_device = platform_device_alloc("soc-audio", -1);
 178        if (!jive_snd_device)
 179                return -ENOMEM;
 180
 181        platform_set_drvdata(jive_snd_device, &jive_snd_devdata);
 182        jive_snd_devdata.dev = &jive_snd_device->dev;
 183        ret = platform_device_add(jive_snd_device);
 184
 185        if (ret)
 186                platform_device_put(jive_snd_device);
 187
 188        return ret;
 189}
 190
 191static void __exit jive_exit(void)
 192{
 193        platform_device_unregister(jive_snd_device);
 194}
 195
 196module_init(jive_init);
 197module_exit(jive_exit);
 198
 199MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 200MODULE_DESCRIPTION("ALSA SoC Jive Audio support");
 201MODULE_LICENSE("GPL");
 202