linux/sound/soc/s3c24xx/neo1973_wm8753.c
<<
>>
Prefs
   1/*
   2 * neo1973_wm8753.c  --  SoC audio for Neo1973
   3 *
   4 * Copyright 2007 Wolfson Microelectronics PLC.
   5 * Author: Graeme Gregory
   6 *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
   7 *
   8 *  This program is free software; you can redistribute  it and/or modify it
   9 *  under  the terms of  the GNU General  Public License as published by the
  10 *  Free Software Foundation;  either version 2 of the  License, or (at your
  11 *  option) any later version.
  12 *
  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/i2c.h>
  21#include <sound/core.h>
  22#include <sound/pcm.h>
  23#include <sound/soc.h>
  24#include <sound/soc-dapm.h>
  25#include <sound/tlv.h>
  26
  27#include <asm/mach-types.h>
  28#include <asm/hardware/scoop.h>
  29#include <mach/regs-clock.h>
  30#include <mach/regs-gpio.h>
  31#include <mach/hardware.h>
  32#include <mach/audio.h>
  33#include <linux/io.h>
  34#include <mach/spi-gpio.h>
  35
  36#include <asm/plat-s3c24xx/regs-iis.h>
  37
  38#include "../codecs/wm8753.h"
  39#include "lm4857.h"
  40#include "s3c24xx-pcm.h"
  41#include "s3c24xx-i2s.h"
  42
  43/* Debugging stuff */
  44#define S3C24XX_SOC_NEO1973_WM8753_DEBUG 0
  45#if S3C24XX_SOC_NEO1973_WM8753_DEBUG
  46#define DBG(x...) printk(KERN_DEBUG "s3c24xx-soc-neo1973-wm8753: " x)
  47#else
  48#define DBG(x...)
  49#endif
  50
  51/* define the scenarios */
  52#define NEO_AUDIO_OFF                   0
  53#define NEO_GSM_CALL_AUDIO_HANDSET      1
  54#define NEO_GSM_CALL_AUDIO_HEADSET      2
  55#define NEO_GSM_CALL_AUDIO_BLUETOOTH    3
  56#define NEO_STEREO_TO_SPEAKERS          4
  57#define NEO_STEREO_TO_HEADPHONES        5
  58#define NEO_CAPTURE_HANDSET             6
  59#define NEO_CAPTURE_HEADSET             7
  60#define NEO_CAPTURE_BLUETOOTH           8
  61
  62static struct snd_soc_machine neo1973;
  63static struct i2c_client *i2c;
  64
  65static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
  66        struct snd_pcm_hw_params *params)
  67{
  68        struct snd_soc_pcm_runtime *rtd = substream->private_data;
  69        struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
  70        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
  71        unsigned int pll_out = 0, bclk = 0;
  72        int ret = 0;
  73        unsigned long iis_clkrate;
  74
  75        DBG("Entered %s\n", __func__);
  76
  77        iis_clkrate = s3c24xx_i2s_get_clockrate();
  78
  79        switch (params_rate(params)) {
  80        case 8000:
  81        case 16000:
  82                pll_out = 12288000;
  83                break;
  84        case 48000:
  85                bclk = WM8753_BCLK_DIV_4;
  86                pll_out = 12288000;
  87                break;
  88        case 96000:
  89                bclk = WM8753_BCLK_DIV_2;
  90                pll_out = 12288000;
  91                break;
  92        case 11025:
  93                bclk = WM8753_BCLK_DIV_16;
  94                pll_out = 11289600;
  95                break;
  96        case 22050:
  97                bclk = WM8753_BCLK_DIV_8;
  98                pll_out = 11289600;
  99                break;
 100        case 44100:
 101                bclk = WM8753_BCLK_DIV_4;
 102                pll_out = 11289600;
 103                break;
 104        case 88200:
 105                bclk = WM8753_BCLK_DIV_2;
 106                pll_out = 11289600;
 107                break;
 108        }
 109
 110        /* set codec DAI configuration */
 111        ret = snd_soc_dai_set_fmt(codec_dai,
 112                SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 113                SND_SOC_DAIFMT_CBM_CFM);
 114        if (ret < 0)
 115                return ret;
 116
 117        /* set cpu DAI configuration */
 118        ret = snd_soc_dai_set_fmt(cpu_dai,
 119                SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 120                SND_SOC_DAIFMT_CBM_CFM);
 121        if (ret < 0)
 122                return ret;
 123
 124        /* set the codec system clock for DAC and ADC */
 125        ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
 126                SND_SOC_CLOCK_IN);
 127        if (ret < 0)
 128                return ret;
 129
 130        /* set MCLK division for sample rate */
 131        ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
 132                S3C2410_IISMOD_32FS);
 133        if (ret < 0)
 134                return ret;
 135
 136        /* set codec BCLK division for sample rate */
 137        ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
 138        if (ret < 0)
 139                return ret;
 140
 141        /* set prescaler division for sample rate */
 142        ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
 143                S3C24XX_PRESCALE(4, 4));
 144        if (ret < 0)
 145                return ret;
 146
 147        /* codec PLL input is PCLK/4 */
 148        ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1,
 149                iis_clkrate / 4, pll_out);
 150        if (ret < 0)
 151                return ret;
 152
 153        return 0;
 154}
 155
 156static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
 157{
 158        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 159        struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
 160
 161        DBG("Entered %s\n", __func__);
 162
 163        /* disable the PLL */
 164        return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0);
 165}
 166
 167/*
 168 * Neo1973 WM8753 HiFi DAI opserations.
 169 */
 170static struct snd_soc_ops neo1973_hifi_ops = {
 171        .hw_params = neo1973_hifi_hw_params,
 172        .hw_free = neo1973_hifi_hw_free,
 173};
 174
 175static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
 176        struct snd_pcm_hw_params *params)
 177{
 178        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 179        struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
 180        unsigned int pcmdiv = 0;
 181        int ret = 0;
 182        unsigned long iis_clkrate;
 183
 184        DBG("Entered %s\n", __func__);
 185
 186        iis_clkrate = s3c24xx_i2s_get_clockrate();
 187
 188        if (params_rate(params) != 8000)
 189                return -EINVAL;
 190        if (params_channels(params) != 1)
 191                return -EINVAL;
 192
 193        pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
 194
 195        /* todo: gg check mode (DSP_B) against CSR datasheet */
 196        /* set codec DAI configuration */
 197        ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
 198                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
 199        if (ret < 0)
 200                return ret;
 201
 202        /* set the codec system clock for DAC and ADC */
 203        ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, 12288000,
 204                SND_SOC_CLOCK_IN);
 205        if (ret < 0)
 206                return ret;
 207
 208        /* set codec PCM division for sample rate */
 209        ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
 210        if (ret < 0)
 211                return ret;
 212
 213        /* configue and enable PLL for 12.288MHz output */
 214        ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2,
 215                iis_clkrate / 4, 12288000);
 216        if (ret < 0)
 217                return ret;
 218
 219        return 0;
 220}
 221
 222static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
 223{
 224        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 225        struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
 226
 227        DBG("Entered %s\n", __func__);
 228
 229        /* disable the PLL */
 230        return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0);
 231}
 232
 233static struct snd_soc_ops neo1973_voice_ops = {
 234        .hw_params = neo1973_voice_hw_params,
 235        .hw_free = neo1973_voice_hw_free,
 236};
 237
 238static int neo1973_scenario;
 239
 240static int neo1973_get_scenario(struct snd_kcontrol *kcontrol,
 241        struct snd_ctl_elem_value *ucontrol)
 242{
 243        ucontrol->value.integer.value[0] = neo1973_scenario;
 244        return 0;
 245}
 246
 247static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario)
 248{
 249        DBG("Entered %s\n", __func__);
 250
 251        switch (neo1973_scenario) {
 252        case NEO_AUDIO_OFF:
 253                snd_soc_dapm_disable_pin(codec, "Audio Out");
 254                snd_soc_dapm_disable_pin(codec, "GSM Line Out");
 255                snd_soc_dapm_disable_pin(codec, "GSM Line In");
 256                snd_soc_dapm_disable_pin(codec, "Headset Mic");
 257                snd_soc_dapm_disable_pin(codec, "Call Mic");
 258                break;
 259        case NEO_GSM_CALL_AUDIO_HANDSET:
 260                snd_soc_dapm_enable_pin(codec, "Audio Out");
 261                snd_soc_dapm_enable_pin(codec, "GSM Line Out");
 262                snd_soc_dapm_enable_pin(codec, "GSM Line In");
 263                snd_soc_dapm_disable_pin(codec, "Headset Mic");
 264                snd_soc_dapm_enable_pin(codec, "Call Mic");
 265                break;
 266        case NEO_GSM_CALL_AUDIO_HEADSET:
 267                snd_soc_dapm_enable_pin(codec, "Audio Out");
 268                snd_soc_dapm_enable_pin(codec, "GSM Line Out");
 269                snd_soc_dapm_enable_pin(codec, "GSM Line In");
 270                snd_soc_dapm_enable_pin(codec, "Headset Mic");
 271                snd_soc_dapm_disable_pin(codec, "Call Mic");
 272                break;
 273        case NEO_GSM_CALL_AUDIO_BLUETOOTH:
 274                snd_soc_dapm_disable_pin(codec, "Audio Out");
 275                snd_soc_dapm_enable_pin(codec, "GSM Line Out");
 276                snd_soc_dapm_enable_pin(codec, "GSM Line In");
 277                snd_soc_dapm_disable_pin(codec, "Headset Mic");
 278                snd_soc_dapm_disable_pin(codec, "Call Mic");
 279                break;
 280        case NEO_STEREO_TO_SPEAKERS:
 281                snd_soc_dapm_enable_pin(codec, "Audio Out");
 282                snd_soc_dapm_disable_pin(codec, "GSM Line Out");
 283                snd_soc_dapm_disable_pin(codec, "GSM Line In");
 284                snd_soc_dapm_disable_pin(codec, "Headset Mic");
 285                snd_soc_dapm_disable_pin(codec, "Call Mic");
 286                break;
 287        case NEO_STEREO_TO_HEADPHONES:
 288                snd_soc_dapm_enable_pin(codec, "Audio Out");
 289                snd_soc_dapm_disable_pin(codec, "GSM Line Out");
 290                snd_soc_dapm_disable_pin(codec, "GSM Line In");
 291                snd_soc_dapm_disable_pin(codec, "Headset Mic");
 292                snd_soc_dapm_disable_pin(codec, "Call Mic");
 293                break;
 294        case NEO_CAPTURE_HANDSET:
 295                snd_soc_dapm_disable_pin(codec, "Audio Out");
 296                snd_soc_dapm_disable_pin(codec, "GSM Line Out");
 297                snd_soc_dapm_disable_pin(codec, "GSM Line In");
 298                snd_soc_dapm_disable_pin(codec, "Headset Mic");
 299                snd_soc_dapm_enable_pin(codec, "Call Mic");
 300                break;
 301        case NEO_CAPTURE_HEADSET:
 302                snd_soc_dapm_disable_pin(codec, "Audio Out");
 303                snd_soc_dapm_disable_pin(codec, "GSM Line Out");
 304                snd_soc_dapm_disable_pin(codec, "GSM Line In");
 305                snd_soc_dapm_enable_pin(codec, "Headset Mic");
 306                snd_soc_dapm_disable_pin(codec, "Call Mic");
 307                break;
 308        case NEO_CAPTURE_BLUETOOTH:
 309                snd_soc_dapm_disable_pin(codec, "Audio Out");
 310                snd_soc_dapm_disable_pin(codec, "GSM Line Out");
 311                snd_soc_dapm_disable_pin(codec, "GSM Line In");
 312                snd_soc_dapm_disable_pin(codec, "Headset Mic");
 313                snd_soc_dapm_disable_pin(codec, "Call Mic");
 314                break;
 315        default:
 316                snd_soc_dapm_disable_pin(codec, "Audio Out");
 317                snd_soc_dapm_disable_pin(codec, "GSM Line Out");
 318                snd_soc_dapm_disable_pin(codec, "GSM Line In");
 319                snd_soc_dapm_disable_pin(codec, "Headset Mic");
 320                snd_soc_dapm_disable_pin(codec, "Call Mic");
 321        }
 322
 323        snd_soc_dapm_sync(codec);
 324
 325        return 0;
 326}
 327
 328static int neo1973_set_scenario(struct snd_kcontrol *kcontrol,
 329        struct snd_ctl_elem_value *ucontrol)
 330{
 331        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 332
 333        DBG("Entered %s\n", __func__);
 334
 335        if (neo1973_scenario == ucontrol->value.integer.value[0])
 336                return 0;
 337
 338        neo1973_scenario = ucontrol->value.integer.value[0];
 339        set_scenario_endpoints(codec, neo1973_scenario);
 340        return 1;
 341}
 342
 343static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0};
 344
 345static void lm4857_write_regs(void)
 346{
 347        DBG("Entered %s\n", __func__);
 348
 349        if (i2c_master_send(i2c, lm4857_regs, 4) != 4)
 350                printk(KERN_ERR "lm4857: i2c write failed\n");
 351}
 352
 353static int lm4857_get_reg(struct snd_kcontrol *kcontrol,
 354        struct snd_ctl_elem_value *ucontrol)
 355{
 356        int reg = kcontrol->private_value & 0xFF;
 357        int shift = (kcontrol->private_value >> 8) & 0x0F;
 358        int mask = (kcontrol->private_value >> 16) & 0xFF;
 359
 360        DBG("Entered %s\n", __func__);
 361
 362        ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask;
 363        return 0;
 364}
 365
 366static int lm4857_set_reg(struct snd_kcontrol *kcontrol,
 367        struct snd_ctl_elem_value *ucontrol)
 368{
 369        int reg = kcontrol->private_value & 0xFF;
 370        int shift = (kcontrol->private_value >> 8) & 0x0F;
 371        int mask = (kcontrol->private_value >> 16) & 0xFF;
 372
 373        if (((lm4857_regs[reg] >> shift) & mask) ==
 374                ucontrol->value.integer.value[0])
 375                return 0;
 376
 377        lm4857_regs[reg] &= ~(mask << shift);
 378        lm4857_regs[reg] |= ucontrol->value.integer.value[0] << shift;
 379        lm4857_write_regs();
 380        return 1;
 381}
 382
 383static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
 384        struct snd_ctl_elem_value *ucontrol)
 385{
 386        u8 value = lm4857_regs[LM4857_CTRL] & 0x0F;
 387
 388        DBG("Entered %s\n", __func__);
 389
 390        if (value)
 391                value -= 5;
 392
 393        ucontrol->value.integer.value[0] = value;
 394        return 0;
 395}
 396
 397static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
 398        struct snd_ctl_elem_value *ucontrol)
 399{
 400        u8 value = ucontrol->value.integer.value[0];
 401
 402        DBG("Entered %s\n", __func__);
 403
 404        if (value)
 405                value += 5;
 406
 407        if ((lm4857_regs[LM4857_CTRL] & 0x0F) == value)
 408                return 0;
 409
 410        lm4857_regs[LM4857_CTRL] &= 0xF0;
 411        lm4857_regs[LM4857_CTRL] |= value;
 412        lm4857_write_regs();
 413        return 1;
 414}
 415
 416static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
 417        SND_SOC_DAPM_LINE("Audio Out", NULL),
 418        SND_SOC_DAPM_LINE("GSM Line Out", NULL),
 419        SND_SOC_DAPM_LINE("GSM Line In", NULL),
 420        SND_SOC_DAPM_MIC("Headset Mic", NULL),
 421        SND_SOC_DAPM_MIC("Call Mic", NULL),
 422};
 423
 424
 425static const struct snd_soc_dapm_route dapm_routes[] = {
 426
 427        /* Connections to the lm4857 amp */
 428        {"Audio Out", NULL, "LOUT1"},
 429        {"Audio Out", NULL, "ROUT1"},
 430
 431        /* Connections to the GSM Module */
 432        {"GSM Line Out", NULL, "MONO1"},
 433        {"GSM Line Out", NULL, "MONO2"},
 434        {"RXP", NULL, "GSM Line In"},
 435        {"RXN", NULL, "GSM Line In"},
 436
 437        /* Connections to Headset */
 438        {"MIC1", NULL, "Mic Bias"},
 439        {"Mic Bias", NULL, "Headset Mic"},
 440
 441        /* Call Mic */
 442        {"MIC2", NULL, "Mic Bias"},
 443        {"MIC2N", NULL, "Mic Bias"},
 444        {"Mic Bias", NULL, "Call Mic"},
 445
 446        /* Connect the ALC pins */
 447        {"ACIN", NULL, "ACOP"},
 448};
 449
 450static const char *lm4857_mode[] = {
 451        "Off",
 452        "Call Speaker",
 453        "Stereo Speakers",
 454        "Stereo Speakers + Headphones",
 455        "Headphones"
 456};
 457
 458static const struct soc_enum lm4857_mode_enum[] = {
 459        SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode),
 460};
 461
 462static const char *neo_scenarios[] = {
 463        "Off",
 464        "GSM Handset",
 465        "GSM Headset",
 466        "GSM Bluetooth",
 467        "Speakers",
 468        "Headphones",
 469        "Capture Handset",
 470        "Capture Headset",
 471        "Capture Bluetooth"
 472};
 473
 474static const struct soc_enum neo_scenario_enum[] = {
 475        SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios), neo_scenarios),
 476};
 477
 478static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0);
 479static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0);
 480
 481static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
 482        SOC_SINGLE_EXT_TLV("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0,
 483                lm4857_get_reg, lm4857_set_reg, stereo_tlv),
 484        SOC_SINGLE_EXT_TLV("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0,
 485                lm4857_get_reg, lm4857_set_reg, stereo_tlv),
 486        SOC_SINGLE_EXT_TLV("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
 487                lm4857_get_reg, lm4857_set_reg, mono_tlv),
 488        SOC_ENUM_EXT("Amp Mode", lm4857_mode_enum[0],
 489                lm4857_get_mode, lm4857_set_mode),
 490        SOC_ENUM_EXT("Neo Mode", neo_scenario_enum[0],
 491                neo1973_get_scenario, neo1973_set_scenario),
 492        SOC_SINGLE_EXT("Amp Spk 3D Playback Switch", LM4857_LVOL, 5, 1, 0,
 493                lm4857_get_reg, lm4857_set_reg),
 494        SOC_SINGLE_EXT("Amp HP 3d Playback Switch", LM4857_RVOL, 5, 1, 0,
 495                lm4857_get_reg, lm4857_set_reg),
 496        SOC_SINGLE_EXT("Amp Fast Wakeup Playback Switch", LM4857_CTRL, 5, 1, 0,
 497                lm4857_get_reg, lm4857_set_reg),
 498        SOC_SINGLE_EXT("Amp Earpiece 6dB Playback Switch", LM4857_CTRL, 4, 1, 0,
 499                lm4857_get_reg, lm4857_set_reg),
 500};
 501
 502/*
 503 * This is an example machine initialisation for a wm8753 connected to a
 504 * neo1973 II. It is missing logic to detect hp/mic insertions and logic
 505 * to re-route the audio in such an event.
 506 */
 507static int neo1973_wm8753_init(struct snd_soc_codec *codec)
 508{
 509        int i, err;
 510
 511        DBG("Entered %s\n", __func__);
 512
 513        /* set up NC codec pins */
 514        snd_soc_dapm_nc_pin(codec, "LOUT2");
 515        snd_soc_dapm_nc_pin(codec, "ROUT2");
 516        snd_soc_dapm_nc_pin(codec, "OUT3");
 517        snd_soc_dapm_nc_pin(codec, "OUT4");
 518        snd_soc_dapm_nc_pin(codec, "LINE1");
 519        snd_soc_dapm_nc_pin(codec, "LINE2");
 520
 521        /* Add neo1973 specific widgets */
 522        snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
 523                                  ARRAY_SIZE(wm8753_dapm_widgets));
 524
 525        /* set endpoints to default mode */
 526        set_scenario_endpoints(codec, NEO_AUDIO_OFF);
 527
 528        /* add neo1973 specific controls */
 529        for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) {
 530                err = snd_ctl_add(codec->card,
 531                                snd_soc_cnew(&wm8753_neo1973_controls[i],
 532                                codec, NULL));
 533                if (err < 0)
 534                        return err;
 535        }
 536
 537        /* set up neo1973 specific audio routes */
 538        err = snd_soc_dapm_add_routes(codec, dapm_routes,
 539                                      ARRAY_SIZE(dapm_routes));
 540
 541        snd_soc_dapm_sync(codec);
 542        return 0;
 543}
 544
 545/*
 546 * BT Codec DAI
 547 */
 548static struct snd_soc_dai bt_dai = {
 549        .name = "Bluetooth",
 550        .id = 0,
 551        .type = SND_SOC_DAI_PCM,
 552        .playback = {
 553                .channels_min = 1,
 554                .channels_max = 1,
 555                .rates = SNDRV_PCM_RATE_8000,
 556                .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 557        .capture = {
 558                .channels_min = 1,
 559                .channels_max = 1,
 560                .rates = SNDRV_PCM_RATE_8000,
 561                .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 562};
 563
 564static struct snd_soc_dai_link neo1973_dai[] = {
 565{ /* Hifi Playback - for similatious use with voice below */
 566        .name = "WM8753",
 567        .stream_name = "WM8753 HiFi",
 568        .cpu_dai = &s3c24xx_i2s_dai,
 569        .codec_dai = &wm8753_dai[WM8753_DAI_HIFI],
 570        .init = neo1973_wm8753_init,
 571        .ops = &neo1973_hifi_ops,
 572},
 573{ /* Voice via BT */
 574        .name = "Bluetooth",
 575        .stream_name = "Voice",
 576        .cpu_dai = &bt_dai,
 577        .codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
 578        .ops = &neo1973_voice_ops,
 579},
 580};
 581
 582static struct snd_soc_machine neo1973 = {
 583        .name = "neo1973",
 584        .dai_link = neo1973_dai,
 585        .num_links = ARRAY_SIZE(neo1973_dai),
 586};
 587
 588static struct wm8753_setup_data neo1973_wm8753_setup = {
 589        .i2c_bus = 0,
 590        .i2c_address = 0x1a,
 591};
 592
 593static struct snd_soc_device neo1973_snd_devdata = {
 594        .machine = &neo1973,
 595        .platform = &s3c24xx_soc_platform,
 596        .codec_dev = &soc_codec_dev_wm8753,
 597        .codec_data = &neo1973_wm8753_setup,
 598};
 599
 600static int lm4857_i2c_probe(struct i2c_client *client,
 601                            const struct i2c_device_id *id)
 602{
 603        DBG("Entered %s\n", __func__);
 604
 605        i2c = client;
 606
 607        lm4857_write_regs();
 608        return 0;
 609}
 610
 611static int lm4857_i2c_remove(struct i2c_client *client)
 612{
 613        DBG("Entered %s\n", __func__);
 614
 615        i2c = NULL;
 616
 617        return 0;
 618}
 619
 620static u8 lm4857_state;
 621
 622static int lm4857_suspend(struct i2c_client *dev, pm_message_t state)
 623{
 624        DBG("Entered %s\n", __func__);
 625
 626        dev_dbg(&dev->dev, "lm4857_suspend\n");
 627        lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf;
 628        if (lm4857_state) {
 629                lm4857_regs[LM4857_CTRL] &= 0xf0;
 630                lm4857_write_regs();
 631        }
 632        return 0;
 633}
 634
 635static int lm4857_resume(struct i2c_client *dev)
 636{
 637        DBG("Entered %s\n", __func__);
 638
 639        if (lm4857_state) {
 640                lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f);
 641                lm4857_write_regs();
 642        }
 643        return 0;
 644}
 645
 646static void lm4857_shutdown(struct i2c_client *dev)
 647{
 648        DBG("Entered %s\n", __func__);
 649
 650        dev_dbg(&dev->dev, "lm4857_shutdown\n");
 651        lm4857_regs[LM4857_CTRL] &= 0xf0;
 652        lm4857_write_regs();
 653}
 654
 655static const struct i2c_device_id lm4857_i2c_id[] = {
 656        { "neo1973_lm4857", 0 },
 657        { }
 658};
 659
 660static struct i2c_driver lm4857_i2c_driver = {
 661        .driver = {
 662                .name = "LM4857 I2C Amp",
 663                .owner = THIS_MODULE,
 664        },
 665        .suspend =        lm4857_suspend,
 666        .resume =         lm4857_resume,
 667        .shutdown =       lm4857_shutdown,
 668        .probe =          lm4857_i2c_probe,
 669        .remove =         lm4857_i2c_remove,
 670        .id_table =       lm4857_i2c_id,
 671};
 672
 673static struct platform_device *neo1973_snd_device;
 674
 675static int __init neo1973_init(void)
 676{
 677        int ret;
 678
 679        DBG("Entered %s\n", __func__);
 680
 681        if (!machine_is_neo1973_gta01()) {
 682                printk(KERN_INFO
 683                        "Only GTA01 hardware supported by ASoC driver\n");
 684                return -ENODEV;
 685        }
 686
 687        neo1973_snd_device = platform_device_alloc("soc-audio", -1);
 688        if (!neo1973_snd_device)
 689                return -ENOMEM;
 690
 691        platform_set_drvdata(neo1973_snd_device, &neo1973_snd_devdata);
 692        neo1973_snd_devdata.dev = &neo1973_snd_device->dev;
 693        ret = platform_device_add(neo1973_snd_device);
 694
 695        if (ret) {
 696                platform_device_put(neo1973_snd_device);
 697                return ret;
 698        }
 699
 700        ret = i2c_add_driver(&lm4857_i2c_driver);
 701
 702        if (ret != 0)
 703                platform_device_unregister(neo1973_snd_device);
 704
 705        return ret;
 706}
 707
 708static void __exit neo1973_exit(void)
 709{
 710        DBG("Entered %s\n", __func__);
 711
 712        i2c_del_driver(&lm4857_i2c_driver);
 713        platform_device_unregister(neo1973_snd_device);
 714}
 715
 716module_init(neo1973_init);
 717module_exit(neo1973_exit);
 718
 719/* Module information */
 720MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org");
 721MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973");
 722MODULE_LICENSE("GPL");
 723
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.