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