Skip to content

Commit

Permalink
Merge tag 'sound-3.5' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/tiwai/sound

Pull sound update from Takashi Iwai:
 "This is the second updates for 3.5-rc1.  It's mainly for OMAP4 HDMI
  updates and the device tree updates for OMAP, in addition to a couple
  of PCM accuray improvement and Realtek ALC269VD codec support."

* tag 'sound-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (21 commits)
  ALSA: hda/realtek - Add new codec support for ALC269VD
  ALSA: core: group read of pointer, tstamp and jiffies
  ASoC: OMAP: HDMI: Rename sound card source file
  ASoC: OMAP: HDMI: Make sound card naming more generic
  ASoC: OMAP: HDMI: Make build config options more generic
  ASoC: OMAP: HDMI: Expand capabilities of the HDMI DAI
  ASoC: OMAP: HDMI: Improve how the display state is verified
  ASoC: OMAP: HDMI: Expand configuration of hw_params
  ASoC: OMAP: HDMI: Use the DSS audio interface
  ASoC: OMAP: HDMI: Create a structure for private data of the CPU DAI
  ASoC: OMAP: HDMI: Change error values in HDMI CPU DAI
  ASoC: OMAP: HDMI: Update the platform device names
  ASoC: omap-abe-twl6040: Introduce driver data for runtime parameters
  ASoC: omap-abe-twl6040: Move Digital Mic widget into dapm table
  ASoC: omap-abe-twl6040: Keep only one snd_soc_dai_link structure
  ASoC: omap-dmic: Add device tree bindings
  ASoC: omap-mcpdm: Add device tree bindings
  ASoC: omap-mcbsp: buffer size constraint only applies to playback stream
  ASoC: omap-mcbsp: Use the common interrupt line if supported by the SoC
  ASoC: omap-mcbsp: Remove unused FRAME dma_op_mode
  ...
  • Loading branch information
Linus Torvalds committed May 25, 2012
2 parents 58823de + adcc70b commit be87cfb
Show file tree
Hide file tree
Showing 16 changed files with 582 additions and 234 deletions.
21 changes: 21 additions & 0 deletions Documentation/devicetree/bindings/sound/omap-dmic.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
* Texas Instruments OMAP4+ Digital Microphone Module

Required properties:
- compatible: "ti,omap4-dmic"
- reg: Register location and size as an array:
<MPU access base address, size>,
<L3 interconnect address, size>;
- interrupts: Interrupt number for DMIC
- interrupt-parent: The parent interrupt controller
- ti,hwmods: Name of the hwmod associated with OMAP dmic IP

Example:

dmic: dmic@4012e000 {
compatible = "ti,omap4-dmic";
reg = <0x4012e000 0x7f>, /* MPU private access */
<0x4902e000 0x7f>; /* L3 Interconnect */
interrupts = <0 114 0x4>;
interrupt-parent = <&gic>;
ti,hwmods = "dmic";
};
21 changes: 21 additions & 0 deletions Documentation/devicetree/bindings/sound/omap-mcpdm.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
* Texas Instruments OMAP4+ McPDM

Required properties:
- compatible: "ti,omap4-mcpdm"
- reg: Register location and size as an array:
<MPU access base address, size>,
<L3 interconnect address, size>;
- interrupts: Interrupt number for McPDM
- interrupt-parent: The parent interrupt controller
- ti,hwmods: Name of the hwmod associated to the McPDM

Example:

mcpdm: mcpdm@40132000 {
compatible = "ti,omap4-mcpdm";
reg = <0x40132000 0x7f>, /* MPU private access */
<0x49032000 0x7f>; /* L3 Interconnect */
interrupts = <0 112 0x4>;
interrupt-parent = <&gic>;
ti,hwmods = "mcpdm";
};
23 changes: 18 additions & 5 deletions sound/core/pcm_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,22 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
snd_pcm_sframes_t hdelta, delta;
unsigned long jdelta;
unsigned long curr_jiffies;
struct timespec curr_tstamp;

old_hw_ptr = runtime->status->hw_ptr;

/*
* group pointer, time and jiffies reads to allow for more
* accurate correlations/corrections.
* The values are stored at the end of this routine after
* corrections for hw_ptr position
*/
pos = substream->ops->pointer(substream);
curr_jiffies = jiffies;
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);

if (pos == SNDRV_PCM_POS_XRUN) {
xrun(substream);
return -EPIPE;
Expand Down Expand Up @@ -343,7 +356,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
delta = runtime->hw_ptr_interrupt + runtime->period_size;
if (delta > new_hw_ptr) {
/* check for double acknowledged interrupts */
hdelta = jiffies - runtime->hw_ptr_jiffies;
hdelta = curr_jiffies - runtime->hw_ptr_jiffies;
if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
hw_base += runtime->buffer_size;
if (hw_base >= runtime->boundary)
Expand Down Expand Up @@ -388,7 +401,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
* Without regular period interrupts, we have to check
* the elapsed time to detect xruns.
*/
jdelta = jiffies - runtime->hw_ptr_jiffies;
jdelta = curr_jiffies - runtime->hw_ptr_jiffies;
if (jdelta < runtime->hw_ptr_buffer_jiffies / 2)
goto no_delta_check;
hdelta = jdelta - delta * HZ / runtime->rate;
Expand Down Expand Up @@ -430,7 +443,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
if (hdelta < runtime->delay)
goto no_jiffies_check;
hdelta -= runtime->delay;
jdelta = jiffies - runtime->hw_ptr_jiffies;
jdelta = curr_jiffies - runtime->hw_ptr_jiffies;
if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
delta = jdelta /
(((runtime->period_size * HZ) / runtime->rate)
Expand Down Expand Up @@ -492,9 +505,9 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
}
runtime->hw_ptr_base = hw_base;
runtime->status->hw_ptr = new_hw_ptr;
runtime->hw_ptr_jiffies = jiffies;
runtime->hw_ptr_jiffies = curr_jiffies;
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
runtime->status->tstamp = curr_tstamp;

return snd_pcm_update_state(substream, runtime);
}
Expand Down
38 changes: 33 additions & 5 deletions sound/pci/hda/patch_realtek.c
Original file line number Diff line number Diff line change
Expand Up @@ -2368,6 +2368,7 @@ static struct alc_codec_rename_table rename_tbl[] = {
{ 0x10ec0269, 0xffff, 0xa023, "ALC259" },
{ 0x10ec0269, 0xffff, 0x6023, "ALC281X" },
{ 0x10ec0269, 0x00f0, 0x0020, "ALC269VC" },
{ 0x10ec0269, 0x00f0, 0x0030, "ALC269VD" },
{ 0x10ec0887, 0x00f0, 0x0030, "ALC887-VD" },
{ 0x10ec0888, 0x00f0, 0x0030, "ALC888-VD" },
{ 0x10ec0888, 0xf0f0, 0x3020, "ALC886" },
Expand Down Expand Up @@ -5614,6 +5615,7 @@ enum {
ALC269_TYPE_ALC269VA,
ALC269_TYPE_ALC269VB,
ALC269_TYPE_ALC269VC,
ALC269_TYPE_ALC269VD,
};

/*
Expand All @@ -5625,8 +5627,21 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
struct alc_spec *spec = codec->spec;
const hda_nid_t *ssids = spec->codec_variant == ALC269_TYPE_ALC269VA ?
alc269va_ssids : alc269_ssids;
const hda_nid_t *ssids;

switch (spec->codec_variant) {
case ALC269_TYPE_ALC269VA:
case ALC269_TYPE_ALC269VC:
ssids = alc269va_ssids;
break;
case ALC269_TYPE_ALC269VB:
case ALC269_TYPE_ALC269VD:
ssids = alc269_ssids;
break;
default:
ssids = alc269_ssids;
break;
}

return alc_parse_auto_config(codec, alc269_ignore, ssids);
}
Expand All @@ -5643,6 +5658,11 @@ static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)

static void alc269_shutup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;

if (spec->codec_variant != ALC269_TYPE_ALC269VB)
return;

if ((alc_get_coef0(codec) & 0x00ff) == 0x017)
alc269_toggle_power_output(codec, 0);
if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
Expand All @@ -5654,19 +5674,24 @@ static void alc269_shutup(struct hda_codec *codec)
#ifdef CONFIG_PM
static int alc269_resume(struct hda_codec *codec)
{
if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
struct alc_spec *spec = codec->spec;

if (spec->codec_variant == ALC269_TYPE_ALC269VB ||
(alc_get_coef0(codec) & 0x00ff) == 0x018) {
alc269_toggle_power_output(codec, 0);
msleep(150);
}

codec->patch_ops.init(codec);

if ((alc_get_coef0(codec) & 0x00ff) == 0x017) {
if (spec->codec_variant == ALC269_TYPE_ALC269VB ||
(alc_get_coef0(codec) & 0x00ff) == 0x017) {
alc269_toggle_power_output(codec, 1);
msleep(200);
}

if ((alc_get_coef0(codec) & 0x00ff) == 0x018)
if (spec->codec_variant == ALC269_TYPE_ALC269VB ||
(alc_get_coef0(codec) & 0x00ff) == 0x018)
alc269_toggle_power_output(codec, 1);

snd_hda_codec_resume_amp(codec);
Expand Down Expand Up @@ -6081,6 +6106,9 @@ static int patch_alc269(struct hda_codec *codec)
err = alc_codec_rename(codec, "ALC3202");
spec->codec_variant = ALC269_TYPE_ALC269VC;
break;
case 0x0030:
spec->codec_variant = ALC269_TYPE_ALC269VD;
break;
default:
alc_fix_pll_init(codec, 0x20, 0x04, 15);
}
Expand Down
7 changes: 4 additions & 3 deletions sound/soc/omap/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,12 @@ config SND_OMAP_SOC_OMAP_ABE_TWL6040
- PandaBoard (4430)
- PandaBoardES (4460)

config SND_OMAP_SOC_OMAP4_HDMI
tristate "SoC Audio support for Texas Instruments OMAP4 HDMI"
depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS && ARCH_OMAP4
config SND_OMAP_SOC_OMAP_HDMI
tristate "SoC Audio support for Texas Instruments OMAP HDMI"
depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS
select SND_OMAP_SOC_HDMI
select SND_SOC_OMAP_HDMI_CODEC
select OMAP4_DSS_HDMI_AUDIO
help
Say Y if you want to add support for SoC HDMI audio on Texas Instruments
OMAP4 chips
Expand Down
4 changes: 2 additions & 2 deletions sound/soc/omap/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ snd-soc-omap3pandora-objs := omap3pandora.o
snd-soc-omap3beagle-objs := omap3beagle.o
snd-soc-zoom2-objs := zoom2.o
snd-soc-igep0020-objs := igep0020.o
snd-soc-omap4-hdmi-objs := omap4-hdmi-card.o
snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o

obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o
Expand All @@ -41,4 +41,4 @@ obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) += snd-soc-omap4-hdmi.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o
115 changes: 90 additions & 25 deletions sound/soc/omap/mcbsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,47 @@ static void omap_mcbsp_dump_reg(struct omap_mcbsp *mcbsp)
dev_dbg(mcbsp->dev, "***********************\n");
}

static irqreturn_t omap_mcbsp_irq_handler(int irq, void *dev_id)
{
struct omap_mcbsp *mcbsp = dev_id;
u16 irqst;

irqst = MCBSP_READ(mcbsp, IRQST);
dev_dbg(mcbsp->dev, "IRQ callback : 0x%x\n", irqst);

if (irqst & RSYNCERREN)
dev_err(mcbsp->dev, "RX Frame Sync Error!\n");
if (irqst & RFSREN)
dev_dbg(mcbsp->dev, "RX Frame Sync\n");
if (irqst & REOFEN)
dev_dbg(mcbsp->dev, "RX End Of Frame\n");
if (irqst & RRDYEN)
dev_dbg(mcbsp->dev, "RX Buffer Threshold Reached\n");
if (irqst & RUNDFLEN)
dev_err(mcbsp->dev, "RX Buffer Underflow!\n");
if (irqst & ROVFLEN)
dev_err(mcbsp->dev, "RX Buffer Overflow!\n");

if (irqst & XSYNCERREN)
dev_err(mcbsp->dev, "TX Frame Sync Error!\n");
if (irqst & XFSXEN)
dev_dbg(mcbsp->dev, "TX Frame Sync\n");
if (irqst & XEOFEN)
dev_dbg(mcbsp->dev, "TX End Of Frame\n");
if (irqst & XRDYEN)
dev_dbg(mcbsp->dev, "TX Buffer threshold Reached\n");
if (irqst & XUNDFLEN)
dev_err(mcbsp->dev, "TX Buffer Underflow!\n");
if (irqst & XOVFLEN)
dev_err(mcbsp->dev, "TX Buffer Overflow!\n");
if (irqst & XEMPTYEOFEN)
dev_dbg(mcbsp->dev, "TX Buffer empty at end of frame\n");

MCBSP_WRITE(mcbsp, IRQST, irqst);

return IRQ_HANDLED;
}

static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
{
struct omap_mcbsp *mcbsp_tx = dev_id;
Expand Down Expand Up @@ -176,6 +217,10 @@ void omap_mcbsp_config(struct omap_mcbsp *mcbsp,
/* Enable wakeup behavior */
if (mcbsp->pdata->has_wakeup)
MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);

/* Enable TX/RX sync error interrupts by default */
if (mcbsp->irq)
MCBSP_WRITE(mcbsp, IRQEN, RSYNCERREN | XSYNCERREN);
}

/**
Expand Down Expand Up @@ -489,23 +534,25 @@ int omap_mcbsp_request(struct omap_mcbsp *mcbsp)
MCBSP_WRITE(mcbsp, SPCR1, 0);
MCBSP_WRITE(mcbsp, SPCR2, 0);

err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler,
0, "McBSP", (void *)mcbsp);
if (err != 0) {
dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
"for McBSP%d\n", mcbsp->tx_irq,
mcbsp->id);
goto err_clk_disable;
}
if (mcbsp->irq) {
err = request_irq(mcbsp->irq, omap_mcbsp_irq_handler, 0,
"McBSP", (void *)mcbsp);
if (err != 0) {
dev_err(mcbsp->dev, "Unable to request IRQ\n");
goto err_clk_disable;
}
} else {
err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, 0,
"McBSP TX", (void *)mcbsp);
if (err != 0) {
dev_err(mcbsp->dev, "Unable to request TX IRQ\n");
goto err_clk_disable;
}

if (mcbsp->rx_irq) {
err = request_irq(mcbsp->rx_irq,
omap_mcbsp_rx_irq_handler,
0, "McBSP", (void *)mcbsp);
err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, 0,
"McBSP RX", (void *)mcbsp);
if (err != 0) {
dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
"for McBSP%d\n", mcbsp->rx_irq,
mcbsp->id);
dev_err(mcbsp->dev, "Unable to request RX IRQ\n");
goto err_free_irq;
}
}
Expand Down Expand Up @@ -542,9 +589,16 @@ void omap_mcbsp_free(struct omap_mcbsp *mcbsp)
if (mcbsp->pdata->has_wakeup)
MCBSP_WRITE(mcbsp, WAKEUPEN, 0);

if (mcbsp->rx_irq)
/* Disable interrupt requests */
if (mcbsp->irq)
MCBSP_WRITE(mcbsp, IRQEN, 0);

if (mcbsp->irq) {
free_irq(mcbsp->irq, (void *)mcbsp);
} else {
free_irq(mcbsp->rx_irq, (void *)mcbsp);
free_irq(mcbsp->tx_irq, (void *)mcbsp);
free_irq(mcbsp->tx_irq, (void *)mcbsp);
}

reg_cache = mcbsp->reg_cache;

Expand Down Expand Up @@ -754,7 +808,7 @@ THRESHOLD_PROP_BUILDER(max_tx_thres);
THRESHOLD_PROP_BUILDER(max_rx_thres);

static const char *dma_op_modes[] = {
"element", "threshold", "frame",
"element", "threshold",
};

static ssize_t dma_op_mode_show(struct device *dev,
Expand Down Expand Up @@ -949,13 +1003,24 @@ int __devinit omap_mcbsp_init(struct platform_device *pdev)
else
mcbsp->phys_dma_base = res->start;

mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");

/* From OMAP4 there will be a single irq line */
if (mcbsp->tx_irq == -ENXIO) {
mcbsp->tx_irq = platform_get_irq(pdev, 0);
mcbsp->rx_irq = 0;
/*
* OMAP1, 2 uses two interrupt lines: TX, RX
* OMAP2430, OMAP3 SoC have combined IRQ line as well.
* OMAP4 and newer SoC only have the combined IRQ line.
* Use the combined IRQ if available since it gives better debugging
* possibilities.
*/
mcbsp->irq = platform_get_irq_byname(pdev, "common");
if (mcbsp->irq == -ENXIO) {
mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");

if (mcbsp->tx_irq == -ENXIO) {
mcbsp->irq = platform_get_irq(pdev, 0);
mcbsp->tx_irq = 0;
} else {
mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
mcbsp->irq = 0;
}
}

res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
Expand Down
Loading

0 comments on commit be87cfb

Please sign in to comment.