Commit 94712927 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-3.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "Although the diffstat looks scary, it's just because of the removal of
  the dead code (s6000), thus it must not affect anything serious.

  Other than that, all small fixes.  The only core fix is zero-clear for
  a PCM compat ioctl.  The rest are driver-specific, bebob, sgtl500,
  adau1761, intel-sst, ad1889 and a few HD-audio quirks as usual"

* tag 'sound-3.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda - Add workaround for CMI8888 snoop behavior
  ALSA: pcm: Zero-clear reserved fields of PCM status ioctl in compat mode
  ALSA: bebob: Uninitialized id returned by saffirepro_both_clk_src_get
  ALSA: hda/realtek - New SSID for Headset quirk
  ALSA: ad1889: Fix probable mask then right shift defects
  ALSA: bebob: fix wrong decoding of clock information for Terratec PHASE 88 Rack FW
  ALSA: hda/realtek - Update restore default value for ALC283
  ALSA: hda/realtek - Update restore default value for ALC282
  ASoC: fsl: use strncpy() to prevent copying of over-long names
  ASoC: adau1761: Fix input PGA volume
  ASoC: s6000: remove driver
  ASoC: Intel: HSW/BDW only support S16 and S24 formats.
  ASoC: sgtl500: Document the required supplies
parents a7ca10f2 3b70bdba
......@@ -7,10 +7,20 @@ Required properties:
- clocks : the clock provider of SYS_MCLK
- VDDA-supply : the regulator provider of VDDA
- VDDIO-supply: the regulator provider of VDDIO
Optional properties:
- VDDD-supply : the regulator provider of VDDD
Example:
codec: sgtl5000@0a {
compatible = "fsl,sgtl5000";
reg = <0x0a>;
clocks = <&clks 150>;
VDDA-supply = <&reg_3p3v>;
VDDIO-supply = <&reg_3p3v>;
};
......@@ -210,6 +210,8 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
if (err < 0)
return err;
if (clear_user(src, sizeof(*src)))
return -EFAULT;
if (put_user(status.state, &src->state) ||
compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
compat_put_timespec(&status.tstamp, &src->tstamp) ||
......
......@@ -27,12 +27,14 @@
#define SAFFIRE_CLOCK_SOURCE_INTERNAL 0
#define SAFFIRE_CLOCK_SOURCE_SPDIF 1
/* '1' is absent, why... */
/* clock sources as returned from register of Saffire Pro 10 and 26 */
#define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0
#define SAFFIREPRO_CLOCK_SOURCE_SKIP 1 /* never used on hardware */
#define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2
#define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3
#define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4
#define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 /* not used on s.pro. 10 */
#define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 /* not used on s.pro. 10 */
#define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5
#define SAFFIREPRO_CLOCK_SOURCE_COUNT 6
/* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */
#define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4
......@@ -101,13 +103,34 @@ saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value)
&data, sizeof(__be32), 0);
}
static char *const saffirepro_10_clk_src_labels[] = {
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock"
};
static char *const saffirepro_26_clk_src_labels[] = {
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock"
};
static char *const saffirepro_10_clk_src_labels[] = {
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock"
/* Value maps between registers and labels for SaffirePro 10/26. */
static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = {
/* SaffirePro 10 */
[0] = {
[SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0,
[SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */
[SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1,
[SAFFIREPRO_CLOCK_SOURCE_ADAT1] = -1, /* not supported */
[SAFFIREPRO_CLOCK_SOURCE_ADAT2] = -1, /* not supported */
[SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 2,
},
/* SaffirePro 26 */
[1] = {
[SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0,
[SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */
[SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1,
[SAFFIREPRO_CLOCK_SOURCE_ADAT1] = 2,
[SAFFIREPRO_CLOCK_SOURCE_ADAT2] = 3,
[SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 4,
}
};
static int
saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate)
{
......@@ -138,24 +161,35 @@ saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate)
return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id);
}
/*
* query hardware for current clock source, return our internally
* used clock index in *id, depending on hardware.
*/
static int
saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
{
int err;
u32 value;
u32 value; /* clock source read from hw register */
const signed char *map;
err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value);
if (err < 0)
goto end;
if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) {
if (value == SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK)
*id = 2;
else if (value == SAFFIREPRO_CLOCK_SOURCE_SPDIF)
*id = 1;
} else if (value > 1) {
*id = value - 1;
/* depending on hardware, use a different mapping */
if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels)
map = saffirepro_clk_maps[0];
else
map = saffirepro_clk_maps[1];
/* In a case that this driver cannot handle the value of register. */
if (value >= SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] < 0) {
err = -EIO;
goto end;
}
*id = (unsigned int)map[value];
end:
return err;
}
......
......@@ -129,12 +129,24 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal)
/* 1.The device has its own operation to switch source of clock */
if (clk_spec) {
err = clk_spec->get(bebob, &id);
if (err < 0)
if (err < 0) {
dev_err(&bebob->unit->device,
"fail to get clock source: %d\n", err);
else if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL,
strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0)
goto end;
}
if (id >= clk_spec->num) {
dev_err(&bebob->unit->device,
"clock source %d out of range 0..%d\n",
id, clk_spec->num - 1);
err = -EIO;
goto end;
}
if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL,
strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0)
*internal = true;
goto end;
}
......
......@@ -24,7 +24,12 @@ phase88_rack_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
if (err < 0)
goto end;
*id = (enable_ext & 0x01) | ((enable_word & 0x01) << 1);
if (enable_ext == 0)
*id = 0;
else if (enable_word == 0)
*id = 1;
else
*id = 2;
end:
return err;
}
......
......@@ -681,7 +681,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
/* WARQ is at offset 12 */
tmp = (reg & AD_DS_WSMC_WARQ) ?
(((reg & AD_DS_WSMC_WARQ >> 12) & 0x01) ? 12 : 18) : 4;
((((reg & AD_DS_WSMC_WARQ) >> 12) & 0x01) ? 12 : 18) : 4;
tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
snd_iprintf(buffer, "Wave FIFO: %d %s words\n\n", tmp,
......@@ -693,7 +693,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
/* SYRQ is at offset 4 */
tmp = (reg & AD_DS_WSMC_SYRQ) ?
(((reg & AD_DS_WSMC_SYRQ >> 4) & 0x01) ? 12 : 18) : 4;
((((reg & AD_DS_WSMC_SYRQ) >> 4) & 0x01) ? 12 : 18) : 4;
tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
snd_iprintf(buffer, "Synthesis FIFO: %d %s words\n\n", tmp,
......@@ -709,7 +709,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
/* ACRQ is at offset 4 */
tmp = (reg & AD_DS_RAMC_ACRQ) ?
(((reg & AD_DS_RAMC_ACRQ >> 4) & 0x01) ? 12 : 18) : 4;
((((reg & AD_DS_RAMC_ACRQ) >> 4) & 0x01) ? 12 : 18) : 4;
tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
snd_iprintf(buffer, "ADC FIFO: %d %s words\n\n", tmp,
......@@ -720,7 +720,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
/* RERQ is at offset 12 */
tmp = (reg & AD_DS_RAMC_RERQ) ?
(((reg & AD_DS_RAMC_RERQ >> 12) & 0x01) ? 12 : 18) : 4;
((((reg & AD_DS_RAMC_RERQ) >> 12) & 0x01) ? 12 : 18) : 4;
tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
snd_iprintf(buffer, "Resampler FIFO: %d %s words\n\n", tmp,
......
......@@ -374,6 +374,8 @@ static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool
#ifdef CONFIG_SND_DMA_SGBUF
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) {
struct snd_sg_buf *sgbuf = dmab->private_data;
if (chip->driver_type == AZX_DRIVER_CMEDIA)
return; /* deal with only CORB/RIRB buffers */
if (on)
set_pages_array_wc(sgbuf->page_table, sgbuf->pages);
else
......@@ -1769,7 +1771,7 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
#ifdef CONFIG_X86
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct azx *chip = apcm->chip;
if (!azx_snoop(chip))
if (!azx_snoop(chip) && chip->driver_type != AZX_DRIVER_CMEDIA)
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
#endif
}
......
......@@ -2675,7 +2675,7 @@ static void alc269_shutup(struct hda_codec *codec)
static struct coef_fw alc282_coefs[] = {
WRITE_COEF(0x03, 0x0002), /* Power Down Control */
WRITE_COEF(0x05, 0x0700), /* FIFO and filter clock */
UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
WRITE_COEF(0x07, 0x0200), /* DMIC control */
UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */
UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */
......@@ -2786,7 +2786,7 @@ static void alc282_shutup(struct hda_codec *codec)
static struct coef_fw alc283_coefs[] = {
WRITE_COEF(0x03, 0x0002), /* Power Down Control */
WRITE_COEF(0x05, 0x0700), /* FIFO and filter clock */
UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
WRITE_COEF(0x07, 0x0200), /* DMIC control */
UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */
UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */
......@@ -2817,6 +2817,7 @@ static struct coef_fw alc283_coefs[] = {
UPDATE_COEF(0x40, 0xf800, 0x9800), /* Class D DC enable */
UPDATE_COEF(0x42, 0xf000, 0x2000), /* DC offset */
WRITE_COEF(0x37, 0xfc06), /* Class D amp control */
UPDATE_COEF(0x1b, 0x8000, 0), /* HP JD control */
{}
};
......@@ -5922,6 +5923,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A),
SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
......
......@@ -49,7 +49,6 @@ source "sound/soc/mxs/Kconfig"
source "sound/soc/pxa/Kconfig"
source "sound/soc/rockchip/Kconfig"
source "sound/soc/samsung/Kconfig"
source "sound/soc/s6000/Kconfig"
source "sound/soc/sh/Kconfig"
source "sound/soc/sirf/Kconfig"
source "sound/soc/spear/Kconfig"
......
......@@ -26,7 +26,6 @@ obj-$(CONFIG_SND_SOC) += kirkwood/
obj-$(CONFIG_SND_SOC) += pxa/
obj-$(CONFIG_SND_SOC) += rockchip/
obj-$(CONFIG_SND_SOC) += samsung/
obj-$(CONFIG_SND_SOC) += s6000/
obj-$(CONFIG_SND_SOC) += sh/
obj-$(CONFIG_SND_SOC) += sirf/
obj-$(CONFIG_SND_SOC) += spear/
......
......@@ -405,6 +405,7 @@ static const struct snd_soc_dapm_widget adau1761_dapm_widgets[] = {
2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Slew Clock", ADAU1761_CLK_ENABLE0, 6, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ALC Clock", ADAU1761_CLK_ENABLE0, 5, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("Digital Clock 0", 1, ADAU1761_CLK_ENABLE1,
0, 0, NULL, 0),
......@@ -436,6 +437,9 @@ static const struct snd_soc_dapm_route adau1761_dapm_routes[] = {
{ "Right Playback Mixer", NULL, "Slew Clock" },
{ "Left Playback Mixer", NULL, "Slew Clock" },
{ "Left Input Mixer", NULL, "ALC Clock" },
{ "Right Input Mixer", NULL, "ALC Clock" },
{ "Digital Clock 0", NULL, "SYSCLK" },
{ "Digital Clock 1", NULL, "SYSCLK" },
};
......
......@@ -792,7 +792,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
return -ENOMEM;
asrc_priv->pdev = pdev;
strcpy(asrc_priv->name, np->name);
strncpy(asrc_priv->name, np->name, sizeof(asrc_priv->name) - 1);
/* Get the addresses and IRQ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
......@@ -734,7 +734,7 @@ static int fsl_esai_probe(struct platform_device *pdev)
return -ENOMEM;
esai_priv->pdev = pdev;
strcpy(esai_priv->name, np->name);
strncpy(esai_priv->name, np->name, sizeof(esai_priv->name) - 1);
/* Get the addresses and IRQ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
......@@ -691,9 +691,7 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd)
}
#define HSW_FORMATS \
(SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S8)
(SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
static struct snd_soc_dai_driver hsw_dais[] = {
{
......
config SND_S6000_SOC
tristate "SoC Audio for the Stretch s6000 family"
depends on XTENSA_VARIANT_S6000 || COMPILE_TEST
depends on HAS_IOMEM
select SND_S6000_SOC_PCM if XTENSA_VARIANT_S6000
help
Say Y or M if you want to add support for codecs attached to
s6000 family chips. You will also need to select the platform
to support below.
config SND_S6000_SOC_PCM
tristate
config SND_S6000_SOC_I2S
tristate
config SND_S6000_SOC_S6IPCAM
bool "SoC Audio support for Stretch 6105 IP Camera"
depends on SND_S6000_SOC=y
depends on I2C=y
depends on XTENSA_PLATFORM_S6105 || COMPILE_TEST
select SND_S6000_SOC_I2S
select SND_SOC_TLV320AIC3X
help
Say Y if you want to add support for SoC audio on the
Stretch s6105 IP Camera Reference Design.
# s6000 Platform Support
snd-soc-s6000-objs := s6000-pcm.o
snd-soc-s6000-i2s-objs := s6000-i2s.o
obj-$(CONFIG_SND_S6000_SOC_PCM) += snd-soc-s6000.o
obj-$(CONFIG_SND_S6000_SOC_I2S) += snd-soc-s6000-i2s.o
# s6105 Machine Support
snd-soc-s6ipcam-objs := s6105-ipcam.o
obj-$(CONFIG_SND_S6000_SOC_S6IPCAM) += snd-soc-s6ipcam.o
This diff is collapsed.
/*
* ALSA SoC I2S Audio Layer for the Stretch s6000 family
*
* Author: Daniel Gloeckner, <dg@emlix.com>
* Copyright: (C) 2009 emlix GmbH <info@emlix.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _S6000_I2S_H
#define _S6000_I2S_H
struct s6000_snd_platform_data {
int lines_in;
int lines_out;
int channel_in;
int channel_out;
int wide;
int same_rate;
};
#endif
This diff is collapsed.
/*
* ALSA PCM interface for the Stretch s6000 family
*
* Author: Daniel Gloeckner, <dg@emlix.com>
* Copyright: (C) 2009 emlix GmbH <info@emlix.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _S6000_PCM_H
#define _S6000_PCM_H
struct snd_soc_dai;
struct snd_pcm_substream;
struct s6000_pcm_dma_params {
unsigned int (*check_xrun)(struct snd_soc_dai *cpu_dai);
int (*trigger)(struct snd_pcm_substream *substream, int cmd, int after);
dma_addr_t sif_in;
dma_addr_t sif_out;
u32 dma_in;
u32 dma_out;
int irq;
int same_rate;
spinlock_t lock;
int in_use;
int rate;
};
#endif
/*
* ASoC driver for Stretch s6105 IP camera platform
*
* Author: Daniel Gloeckner, <dg@emlix.com>
* Copyright: (C) 2009 emlix GmbH <info@emlix.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include "s6000-pcm.h"
#include "s6000-i2s.h"
#define S6105_CAM_CODEC_CLOCK 12288000
static int s6105_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret = 0;
/* set codec DAI configuration */
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
/* set cpu DAI configuration */
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM |
SND_SOC_DAIFMT_NB_NF);
if (ret < 0)
return ret;
/* set the codec system clock */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, S6105_CAM_CODEC_CLOCK,
SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;
return 0;
}
static struct snd_soc_ops s6105_ops = {
.hw_params = s6105_hw_params,
};
/* s6105 machine dapm widgets */
static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
SND_SOC_DAPM_LINE("Audio Out Differential", NULL),
SND_SOC_DAPM_LINE("Audio Out Stereo", NULL),
SND_SOC_DAPM_LINE("Audio In", NULL),
};
/* s6105 machine audio_mapnections to the codec pins */
static const struct snd_soc_dapm_route audio_map[] = {
/* Audio Out connected to HPLOUT, HPLCOM, HPROUT */
{"Audio Out Differential", NULL, "HPLOUT"},
{"Audio Out Differential", NULL, "HPLCOM"},
{"Audio Out Stereo", NULL, "HPLOUT"},
{"Audio Out Stereo", NULL, "HPROUT"},
/* Audio In connected to LINE1L, LINE1R */
{"LINE1L", NULL, "Audio In"},
{"LINE1R", NULL, "Audio In"},
};
static int output_type_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = 2;
if (uinfo->value.enumerated.item) {
uinfo->value.enumerated.item = 1;
strcpy(uinfo->value.enumerated.name, "HPLOUT/HPROUT");
} else {
strcpy(uinfo->value.enumerated.name, "HPLOUT/HPLCOM");
}
return 0;
}
static int output_type_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.enumerated.item[0] = kcontrol->private_value;
return 0;
}
static int output_type_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = kcontrol->private_data;
struct snd_soc_dapm_context *dapm = &card->dapm;
unsigned int val = (ucontrol->value.enumerated.item[0] != 0);
char *differential = "Audio Out Differential";
char *stereo = "Audio Out Stereo";
if (kcontrol->private_value == val)
return 0;
kcontrol->private_value = val;
snd_soc_dapm_disable_pin(dapm, val ? differential : stereo);
snd_soc_dapm_sync(dapm);
snd_soc_dapm_enable_pin(dapm, val ? stereo : differential);
snd_soc_dapm_sync(dapm);
return 1;
}
static const struct snd_kcontrol_new audio_out_mux = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Output Mux",
.index = 0,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = output_type_info,
.get = output_type_get,
.put = output_type_put,
.private_value = 1 /* default to stereo */
};
/* Logic for a aic3x as connected on the s6105 ip camera ref design */
static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
/* must correspond to audio_out_mux.private_value initializer */
snd_soc_dapm_disable_pin(&card->dapm, "Audio Out Differential");
snd_ctl_add(card->snd_card, snd_ctl_new1(&audio_out_mux, card));
return 0;
}
/* s6105 digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link s6105_dai = {
.name = "TLV320AIC31",
.stream_name = "AIC31",
.cpu_dai_name = "s6000-i2s",
.codec_dai_name = "tlv320aic3x-hifi",
.platform_name = "s6000-pcm-audio",
.codec_name = "tlv320aic3x-codec.0-001a",
.init = s6105_aic3x_init,
.ops = &s6105_ops,
};
/* s6105 audio machine driver */
static struct snd_soc_card snd_soc_card_s6105 = {
.name = "Stretch IP Camera",
.owner = THIS_MODULE,
.dai_link = &s6105_dai,
.num_links = 1,
.dapm_widgets = aic3x_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets),
.dapm_routes = audio_map,
.num_dapm_routes = ARRAY_SIZE(audio_map),
.fully_routed = true,
};
static struct s6000_snd_platform_data s6105_snd_data __initdata = {
.wide = 0,
.channel_in = 0,
.channel_out = 1,
.lines_in = 1,
.lines_out = 1,
.same_rate = 1,
};
static struct platform_device *s6105_snd_device;
/* temporary i2c device creation until this can be moved into the machine
* support file.
*/
static struct i2c_board_info i2c_device[] = {
{ I2C_BOARD_INFO("tlv320aic33", 0x18), }
};
static int __init s6105_init(void)
{
int ret;
i2c_register_board_info(0, i2c_device, ARRAY_SIZE(i2c_device));
s6105_snd_device = platform_device_alloc("soc-audio", -1);
if (!s6105_snd_device)
return -ENOMEM;
platform_set_drvdata(s6105_snd_device, &snd_soc_card_s6105);
platform_device_add_data(s6105_snd_device, &s6105_snd_data,
sizeof(s6105_snd_data));
ret = platform_device_add(s6105_snd_device);
if (ret)
platform_device_put(s6105_snd_device);
return ret;
}
static void __exit s6105_exit(void)
{
platform_device_unregister(s6105_snd_device);
}
module_init(s6105_init);
module_exit(s6105_exit);
MODULE_AUTHOR("Daniel Gloeckner");
MODULE_DESCRIPTION("Stretch s6105 IP camera ASoC driver");
MODULE_LICENSE("GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment