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