Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/sound/soc/ti/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  omap3pandora.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * omap3pandora.c  --  SoC audio for Pandora Handheld Console
 *
 * Author: Gražvydas Ignotas <notasas@gmail.com>
 */


#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>

#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>

#include <asm/mach-types.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>

#include "omap-mcbsp.h"

#define PREFIX "ASoC omap3pandora: "

static struct regulator *omap3pandora_dac_reg;
static struct gpio_desc *dac_power_gpio;
static struct gpio_desc *amp_power_gpio;

static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
 struct snd_pcm_hw_params *params)
{
 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
 int ret;

 /* Set the codec system clock for DAC and ADC */
 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
         SND_SOC_CLOCK_IN);
 if (ret < 0) {
  pr_err(PREFIX "can't set codec system clock\n");
  return ret;
 }

 /* Set McBSP clock to external */
 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT,
         256 * params_rate(params),
         SND_SOC_CLOCK_IN);
 if (ret < 0) {
  pr_err(PREFIX "can't set cpu system clock\n");
  return ret;
 }

 ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, 8);
 if (ret < 0) {
  pr_err(PREFIX "can't set SRG clock divider\n");
  return ret;
 }

 return 0;
}

static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w,
 struct snd_kcontrol *k, int event)
{
 int ret;

 /*
 * The PCM1773 DAC datasheet requires 1ms delay between switching
 * VCC power on/off and /PD pin high/low
 */

 if (SND_SOC_DAPM_EVENT_ON(event)) {
  ret = regulator_enable(omap3pandora_dac_reg);
  if (ret) {
   dev_err(w->dapm->dev, "Failed to power DAC: %d\n", ret);
   return ret;
  }
  mdelay(1);
  gpiod_set_value(dac_power_gpio, 1);
 } else {
  gpiod_set_value(dac_power_gpio, 0);
  mdelay(1);
  regulator_disable(omap3pandora_dac_reg);
 }

 return 0;
}

static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w,
 struct snd_kcontrol *k, int event)
{
 if (SND_SOC_DAPM_EVENT_ON(event))
  gpiod_set_value(amp_power_gpio, 1);
 else
  gpiod_set_value(amp_power_gpio, 0);

 return 0;
}

/*
 * Audio paths on Pandora board:
 *
 *  |O| ---> PCM DAC +-> AMP -> Headphone Jack
 *  |M|         A    +--------> Line Out
 *  |A| <~~clk~~+
 *  |P| <--- TWL4030 <--------- Line In and MICs
 */

static const struct snd_soc_dapm_widget omap3pandora_dapm_widgets[] = {
 SND_SOC_DAPM_DAC_E("PCM DAC""HiFi Playback", SND_SOC_NOPM,
      0, 0, omap3pandora_dac_event,
      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM,
      0, 0, NULL, 0, omap3pandora_hp_event,
      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 SND_SOC_DAPM_HP("Headphone Jack", NULL),
 SND_SOC_DAPM_LINE("Line Out", NULL),

 SND_SOC_DAPM_MIC("Mic (internal)", NULL),
 SND_SOC_DAPM_MIC("Mic (external)", NULL),
 SND_SOC_DAPM_LINE("Line In", NULL),
};

static const struct snd_soc_dapm_route omap3pandora_map[] = {
 {"PCM DAC", NULL, "APLL Enable"},
 {"Headphone Amplifier", NULL, "PCM DAC"},
 {"Line Out", NULL, "PCM DAC"},
 {"Headphone Jack", NULL, "Headphone Amplifier"},

 {"AUXL", NULL, "Line In"},
 {"AUXR", NULL, "Line In"},

 {"MAINMIC", NULL, "Mic (internal)"},
 {"Mic (internal)", NULL, "Mic Bias 1"},

 {"SUBMIC", NULL, "Mic (external)"},
 {"Mic (external)", NULL, "Mic Bias 2"},
};

static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd)
{
 struct snd_soc_dapm_context *dapm = &rtd->card->dapm;

 /* All TWL4030 output pins are floating */
 snd_soc_dapm_nc_pin(dapm, "EARPIECE");
 snd_soc_dapm_nc_pin(dapm, "PREDRIVEL");
 snd_soc_dapm_nc_pin(dapm, "PREDRIVER");
 snd_soc_dapm_nc_pin(dapm, "HSOL");
 snd_soc_dapm_nc_pin(dapm, "HSOR");
 snd_soc_dapm_nc_pin(dapm, "CARKITL");
 snd_soc_dapm_nc_pin(dapm, "CARKITR");
 snd_soc_dapm_nc_pin(dapm, "HFL");
 snd_soc_dapm_nc_pin(dapm, "HFR");
 snd_soc_dapm_nc_pin(dapm, "VIBRA");

 return 0;
}

static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)
{
 struct snd_soc_dapm_context *dapm = &rtd->card->dapm;

 /* Not comnnected */
 snd_soc_dapm_nc_pin(dapm, "HSMIC");
 snd_soc_dapm_nc_pin(dapm, "CARKITMIC");
 snd_soc_dapm_nc_pin(dapm, "DIGIMIC0");
 snd_soc_dapm_nc_pin(dapm, "DIGIMIC1");

 return 0;
}

static const struct snd_soc_ops omap3pandora_ops = {
 .hw_params = omap3pandora_hw_params,
};

/* Digital audio interface glue - connects codec <--> CPU */
SND_SOC_DAILINK_DEFS(out,
 DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.2")),
 DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec""twl4030-hifi")),
 DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.2")));

SND_SOC_DAILINK_DEFS(in,
 DAILINK_COMP_ARRAY(COMP_CPU("omap-mcbsp.4")),
 DAILINK_COMP_ARRAY(COMP_CODEC("twl4030-codec""twl4030-hifi")),
 DAILINK_COMP_ARRAY(COMP_PLATFORM("omap-mcbsp.4")));

static struct snd_soc_dai_link omap3pandora_dai[] = {
 {
  .name = "PCM1773",
  .stream_name = "HiFi Out",
  .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
      SND_SOC_DAIFMT_CBC_CFC,
  .ops = &omap3pandora_ops,
  .init = omap3pandora_out_init,
  SND_SOC_DAILINK_REG(out),
 }, {
  .name = "TWL4030",
  .stream_name = "Line/Mic In",
  .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
      SND_SOC_DAIFMT_CBC_CFC,
  .ops = &omap3pandora_ops,
  .init = omap3pandora_in_init,
  SND_SOC_DAILINK_REG(in),
 }
};

/* SoC card */
static struct snd_soc_card snd_soc_card_omap3pandora = {
 .name = "omap3pandora",
 .owner = THIS_MODULE,
 .dai_link = omap3pandora_dai,
 .num_links = ARRAY_SIZE(omap3pandora_dai),

 .dapm_widgets = omap3pandora_dapm_widgets,
 .num_dapm_widgets = ARRAY_SIZE(omap3pandora_dapm_widgets),
 .dapm_routes = omap3pandora_map,
 .num_dapm_routes = ARRAY_SIZE(omap3pandora_map),
};

static struct platform_device *omap3pandora_snd_device;

static int __init omap3pandora_soc_init(void)
{
 int ret;

 if (!machine_is_omap3_pandora())
  return -ENODEV;

 pr_info("OMAP3 Pandora SoC init\n");

 omap3pandora_snd_device = platform_device_alloc("soc-audio", -1);
 if (omap3pandora_snd_device == NULL) {
  pr_err(PREFIX "Platform device allocation failed\n");
  return -ENOMEM;
 }

 platform_set_drvdata(omap3pandora_snd_device, &snd_soc_card_omap3pandora);

 ret = platform_device_add(omap3pandora_snd_device);
 if (ret) {
  pr_err(PREFIX "Unable to add platform device\n");
  goto fail2;
 }

 dac_power_gpio = devm_gpiod_get(&omap3pandora_snd_device->dev,
     "dac", GPIOD_OUT_LOW);
 if (IS_ERR(dac_power_gpio)) {
  ret = PTR_ERR(dac_power_gpio);
  goto fail3;
 }

 amp_power_gpio = devm_gpiod_get(&omap3pandora_snd_device->dev,
     "amp", GPIOD_OUT_LOW);
 if (IS_ERR(amp_power_gpio)) {
  ret = PTR_ERR(amp_power_gpio);
  goto fail3;
 }

 omap3pandora_dac_reg = regulator_get(&omap3pandora_snd_device->dev, "vcc");
 if (IS_ERR(omap3pandora_dac_reg)) {
  pr_err(PREFIX "Failed to get DAC regulator from %s: %ld\n",
   dev_name(&omap3pandora_snd_device->dev),
   PTR_ERR(omap3pandora_dac_reg));
  ret = PTR_ERR(omap3pandora_dac_reg);
  goto fail3;
 }

 return 0;

fail3:
 platform_device_del(omap3pandora_snd_device);
fail2:
 platform_device_put(omap3pandora_snd_device);

 return ret;
}
module_init(omap3pandora_soc_init);

static void __exit omap3pandora_soc_exit(void)
{
 regulator_put(omap3pandora_dac_reg);
 platform_device_unregister(omap3pandora_snd_device);
}
module_exit(omap3pandora_soc_exit);

MODULE_AUTHOR("Grazvydas Ignotas ");
MODULE_DESCRIPTION("ALSA SoC OMAP3 Pandora");
MODULE_LICENSE("GPL");

Messung V0.5
C=94 H=94 G=93

¤ Dauer der Verarbeitung: 0.0 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.