static int archos_omap4_twl6040_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct twl6040 *twl6040 = codec->control_data; struct snd_soc_dapm_context *dapm = &codec->dapm; int hsotrim, left_offset, right_offset, mode, ret; /* Add specific controls */ ret = snd_soc_add_controls(codec, archos_omap4_controls, ARRAY_SIZE(archos_omap4_controls)); if (ret) return ret; /* Add specific widgets */ ret = snd_soc_dapm_new_controls(dapm, archos_omap4_twl6040_dapm_widgets, ARRAY_SIZE(archos_omap4_twl6040_dapm_widgets)); if (ret) return ret; /* Set up specific audio path audio_map */ snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); /* Connected pins */ snd_soc_dapm_enable_pin(dapm, "Ext Mic"); snd_soc_dapm_enable_pin(dapm, "Ext Spk"); snd_soc_dapm_enable_pin(dapm, "AFML"); snd_soc_dapm_enable_pin(dapm, "AFMR"); snd_soc_dapm_enable_pin(dapm, "Headset Mic"); snd_soc_dapm_enable_pin(dapm, "Headset Stereophone"); /* allow audio paths from the audio modem to run during suspend */ snd_soc_dapm_ignore_suspend(dapm, "Ext Mic"); snd_soc_dapm_ignore_suspend(dapm, "Ext Spk"); snd_soc_dapm_ignore_suspend(dapm, "AFML"); snd_soc_dapm_ignore_suspend(dapm, "AFMR"); snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); snd_soc_dapm_ignore_suspend(dapm, "Headset Stereophone"); snd_soc_dapm_ignore_suspend(dapm, "Digital Mic 0"); snd_soc_dapm_ignore_suspend(dapm, "Digital Mic 1"); snd_soc_dapm_ignore_suspend(dapm, "Digital Mic 2"); ret = snd_soc_dapm_sync(dapm); if (ret) return ret; /* Headset jack detection */ ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, &hs_jack); if (ret) return ret; ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), hs_jack_pins); twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); /* DC offset cancellation computation */ hsotrim = snd_soc_read(codec, TWL6040_REG_HSOTRIM); right_offset = (hsotrim & TWL6040_HSRO) >> TWL6040_HSRO_OFFSET; left_offset = hsotrim & TWL6040_HSLO; if (twl6040_get_icrev(twl6040) < TWL6040_REV_1_3) /* For ES under ES_1.3 HS step is 2 mV */ mode = 2; else /* For ES_1.3 HS step is 1 mV */ mode = 1; abe_dsp_set_hs_offset(left_offset, right_offset, mode); /* don't wait before switching of HS power */ rtd->pmdown_time = 0; return ret; }
static int __devinit twl6040_probe(struct platform_device *pdev) { struct twl4030_codec_data *pdata = pdev->dev.platform_data; struct twl6040 *twl6040; struct mfd_cell *cell = NULL; unsigned int naudint; int audpwron; int ret, children = 0; u8 accctl; if(!pdata) { dev_err(&pdev->dev, "Platform data is missing\n"); return -EINVAL; } twl6040 = kzalloc(sizeof(struct twl6040), GFP_KERNEL); if (!twl6040) return -ENOMEM; platform_set_drvdata(pdev, twl6040); twl6040->dev = &pdev->dev; mutex_init(&twl6040->mutex); mutex_init(&twl6040->io_mutex); twl6040->icrev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV); if (twl6040->icrev < 0) { ret = twl6040->icrev; goto gpio1_err; } if (pdata && (twl6040_get_icrev(twl6040) > TWL6040_REV_1_0)) audpwron = pdata->audpwron_gpio; else audpwron = -EINVAL; if (pdata) naudint = pdata->naudint_irq; else naudint = 0; twl6040->audpwron = audpwron; twl6040->powered = 0; twl6040->irq = naudint; twl6040->irq_base = pdata->irq_base; init_completion(&twl6040->ready); if (gpio_is_valid(audpwron)) { ret = gpio_request(audpwron, "audpwron"); if (ret) goto gpio1_err; ret = gpio_direction_output(audpwron, 0); if (ret) goto gpio2_err; } if (naudint) { /* codec interrupt */ ret = twl6040_irq_init(twl6040); if (ret) goto gpio2_err; ret = twl6040_request_irq(twl6040, TWL6040_IRQ_READY, twl6040_naudint_handler, "twl6040_irq_ready", twl6040); if (ret) { dev_err(twl6040->dev, "READY IRQ request failed: %d\n", ret); goto irq_err; } } /* dual-access registers controlled by I2C only */ accctl = twl6040_reg_read(twl6040, TWL6040_REG_ACCCTL); twl6040_reg_write(twl6040, TWL6040_REG_ACCCTL, accctl | TWL6040_I2CSEL); if (pdata->get_ext_clk32k) { ret = pdata->get_ext_clk32k(); if (ret) { dev_err(twl6040->dev, "failed to get external 32kHz clock %d\n", ret); goto clk32k_err; } } if (pdata->audio) { cell = &twl6040->cells[children]; cell->name = "twl6040-codec"; cell->platform_data = pdata->audio; cell->pdata_size = sizeof(*pdata->audio); children++; } if (pdata->vibra) { cell = &twl6040->cells[children]; cell->name = "twl6040-vibra"; cell->platform_data = pdata->vibra; cell->pdata_size = sizeof(*pdata->vibra); children++; } if (children) { ret = mfd_add_devices(&pdev->dev, pdev->id, twl6040->cells, children, NULL, 0); if (ret) goto mfd_err; } else { dev_err(&pdev->dev, "No platform data found for children\n"); ret = -ENODEV; goto mfd_err; } return 0; mfd_err: if (pdata->put_ext_clk32k) pdata->put_ext_clk32k(); clk32k_err: if (naudint) twl6040_free_irq(twl6040, TWL6040_IRQ_READY, twl6040); irq_err: if (naudint) twl6040_irq_exit(twl6040); gpio2_err: if (gpio_is_valid(audpwron)) gpio_free(audpwron); gpio1_err: platform_set_drvdata(pdev, NULL); kfree(twl6040); return ret; }