Merge remote-tracking branches 'asoc/topic/intel', 'asoc/topic/kirkwood', 'asoc/topic/max98090' and 'asoc/topic/mc13783' into asoc-next
This commit is contained in:
commit
a6ce305207
31 changed files with 2696 additions and 448 deletions
|
@ -4,7 +4,7 @@ This device supports I2C only.
|
|||
|
||||
Required properties:
|
||||
|
||||
- compatible : "maxim,max98090".
|
||||
- compatible : "maxim,max98090" or "maxim,max98091".
|
||||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
|
|
78
arch/x86/include/asm/platform_sst_audio.h
Normal file
78
arch/x86/include/asm/platform_sst_audio.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* platform_sst_audio.h: sst audio platform data header file
|
||||
*
|
||||
* Copyright (C) 2012-14 Intel Corporation
|
||||
* Author: Jeeja KP <jeeja.kp@intel.com>
|
||||
* Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
|
||||
* Vinod Koul ,vinod.koul@intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; version 2
|
||||
* of the License.
|
||||
*/
|
||||
#ifndef _PLATFORM_SST_AUDIO_H_
|
||||
#define _PLATFORM_SST_AUDIO_H_
|
||||
|
||||
#include <linux/sfi.h>
|
||||
|
||||
enum sst_audio_task_id_mrfld {
|
||||
SST_TASK_ID_NONE = 0,
|
||||
SST_TASK_ID_SBA = 1,
|
||||
SST_TASK_ID_MEDIA = 3,
|
||||
SST_TASK_ID_MAX = SST_TASK_ID_MEDIA,
|
||||
};
|
||||
|
||||
/* Device IDs for Merrifield are Pipe IDs,
|
||||
* ref: DSP spec v0.75 */
|
||||
enum sst_audio_device_id_mrfld {
|
||||
/* Output pipeline IDs */
|
||||
PIPE_ID_OUT_START = 0x0,
|
||||
PIPE_CODEC_OUT0 = 0x2,
|
||||
PIPE_CODEC_OUT1 = 0x3,
|
||||
PIPE_SPROT_LOOP_OUT = 0x4,
|
||||
PIPE_MEDIA_LOOP1_OUT = 0x5,
|
||||
PIPE_MEDIA_LOOP2_OUT = 0x6,
|
||||
PIPE_VOIP_OUT = 0xC,
|
||||
PIPE_PCM0_OUT = 0xD,
|
||||
PIPE_PCM1_OUT = 0xE,
|
||||
PIPE_PCM2_OUT = 0xF,
|
||||
PIPE_MEDIA0_OUT = 0x12,
|
||||
PIPE_MEDIA1_OUT = 0x13,
|
||||
/* Input Pipeline IDs */
|
||||
PIPE_ID_IN_START = 0x80,
|
||||
PIPE_CODEC_IN0 = 0x82,
|
||||
PIPE_CODEC_IN1 = 0x83,
|
||||
PIPE_SPROT_LOOP_IN = 0x84,
|
||||
PIPE_MEDIA_LOOP1_IN = 0x85,
|
||||
PIPE_MEDIA_LOOP2_IN = 0x86,
|
||||
PIPE_VOIP_IN = 0x8C,
|
||||
PIPE_PCM0_IN = 0x8D,
|
||||
PIPE_PCM1_IN = 0x8E,
|
||||
PIPE_MEDIA0_IN = 0x8F,
|
||||
PIPE_MEDIA1_IN = 0x90,
|
||||
PIPE_MEDIA2_IN = 0x91,
|
||||
PIPE_RSVD = 0xFF,
|
||||
};
|
||||
|
||||
/* The stream map for each platform consists of an array of the below
|
||||
* stream map structure.
|
||||
*/
|
||||
struct sst_dev_stream_map {
|
||||
u8 dev_num; /* device id */
|
||||
u8 subdev_num; /* substream */
|
||||
u8 direction;
|
||||
u8 device_id; /* fw id */
|
||||
u8 task_id; /* fw task */
|
||||
u8 status;
|
||||
};
|
||||
|
||||
struct sst_platform_data {
|
||||
/* Intel software platform id*/
|
||||
struct sst_dev_stream_map *pdev_strm_map;
|
||||
unsigned int strm_map_size;
|
||||
};
|
||||
|
||||
int add_sst_platform_device(void);
|
||||
#endif
|
||||
|
19
include/sound/rt286.h
Normal file
19
include/sound/rt286.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* linux/sound/rt286.h -- Platform data for RT286
|
||||
*
|
||||
* Copyright 2013 Realtek Microelectronics
|
||||
*
|
||||
* 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 __LINUX_SND_RT286_H
|
||||
#define __LINUX_SND_RT286_H
|
||||
|
||||
struct rt286_platform_data {
|
||||
bool cbj_en; /*combo jack enable*/
|
||||
bool gpio2_en; /*GPIO2 enable*/
|
||||
};
|
||||
|
||||
#endif
|
|
@ -75,6 +75,7 @@ config SND_SOC_ALL_CODECS
|
|||
select SND_SOC_PCM3008
|
||||
select SND_SOC_PCM512x_I2C if I2C
|
||||
select SND_SOC_PCM512x_SPI if SPI_MASTER
|
||||
select SND_SOC_RT286 if I2C
|
||||
select SND_SOC_RT5631 if I2C
|
||||
select SND_SOC_RT5640 if I2C
|
||||
select SND_SOC_RT5645 if I2C
|
||||
|
@ -455,6 +456,9 @@ config SND_SOC_RL6231
|
|||
default m if SND_SOC_RT5645=m
|
||||
default m if SND_SOC_RT5651=m
|
||||
|
||||
config SND_SOC_RT286
|
||||
tristate
|
||||
|
||||
config SND_SOC_RT5631
|
||||
tristate
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ snd-soc-pcm512x-objs := pcm512x.o
|
|||
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
|
||||
snd-soc-pcm512x-spi-objs := pcm512x-spi.o
|
||||
snd-soc-rl6231-objs := rl6231.o
|
||||
snd-soc-rt286-objs := rt286.o
|
||||
snd-soc-rt5631-objs := rt5631.o
|
||||
snd-soc-rt5640-objs := rt5640.o
|
||||
snd-soc-rt5645-objs := rt5645.o
|
||||
|
@ -237,6 +238,7 @@ obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
|
|||
obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
|
||||
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
|
||||
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
|
||||
obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o
|
||||
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
|
||||
obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
|
||||
obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o
|
||||
|
|
|
@ -26,10 +26,6 @@
|
|||
#include <sound/max98090.h>
|
||||
#include "max98090.h"
|
||||
|
||||
#define DEBUG
|
||||
#define EXTMIC_METHOD
|
||||
#define EXTMIC_METHOD_TEST
|
||||
|
||||
/* Allows for sparsely populated register maps */
|
||||
static struct reg_default max98090_reg[] = {
|
||||
{ 0x00, 0x00 }, /* 00 Software Reset */
|
||||
|
@ -820,7 +816,6 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
|
|||
else
|
||||
val = (val & M98090_MIC_PA2EN_MASK) >> M98090_MIC_PA2EN_SHIFT;
|
||||
|
||||
|
||||
if (val >= 1) {
|
||||
if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) {
|
||||
max98090->pa1en = val - 1; /* Update for volatile */
|
||||
|
@ -1140,7 +1135,6 @@ static const struct snd_kcontrol_new max98090_mixhprsel_mux =
|
|||
SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum);
|
||||
|
||||
static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
|
||||
|
||||
SND_SOC_DAPM_INPUT("MIC1"),
|
||||
SND_SOC_DAPM_INPUT("MIC2"),
|
||||
SND_SOC_DAPM_INPUT("DMICL"),
|
||||
|
@ -1304,7 +1298,6 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
|
|||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
|
||||
|
||||
SND_SOC_DAPM_INPUT("DMIC3"),
|
||||
SND_SOC_DAPM_INPUT("DMIC4"),
|
||||
|
||||
|
@ -1315,7 +1308,6 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
|
|||
};
|
||||
|
||||
static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
|
||||
|
||||
{"MIC1 Input", NULL, "MIC1"},
|
||||
{"MIC2 Input", NULL, "MIC2"},
|
||||
|
||||
|
@ -1493,17 +1485,14 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
|
|||
{"SPKR", NULL, "SPK Right Out"},
|
||||
{"RCVL", NULL, "RCV Left Out"},
|
||||
{"RCVR", NULL, "RCV Right Out"},
|
||||
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route max98091_dapm_routes[] = {
|
||||
|
||||
/* DMIC inputs */
|
||||
{"DMIC3", NULL, "DMIC3_ENA"},
|
||||
{"DMIC4", NULL, "DMIC4_ENA"},
|
||||
{"DMIC3", NULL, "AHPF"},
|
||||
{"DMIC4", NULL, "AHPF"},
|
||||
|
||||
};
|
||||
|
||||
static int max98090_add_widgets(struct snd_soc_codec *codec)
|
||||
|
@ -1531,7 +1520,6 @@ static int max98090_add_widgets(struct snd_soc_codec *codec)
|
|||
|
||||
snd_soc_dapm_add_routes(dapm, max98091_dapm_routes,
|
||||
ARRAY_SIZE(max98091_dapm_routes));
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2212,22 +2200,11 @@ static struct snd_soc_dai_driver max98090_dai[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static void max98090_handle_pdata(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
|
||||
struct max98090_pdata *pdata = max98090->pdata;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(codec->dev, "No platform data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int max98090_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
|
||||
struct max98090_cdata *cdata;
|
||||
enum max98090_type devtype;
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(codec->dev, "max98090_probe\n");
|
||||
|
@ -2263,16 +2240,21 @@ static int max98090_probe(struct snd_soc_codec *codec)
|
|||
}
|
||||
|
||||
if ((ret >= M98090_REVA) && (ret <= M98090_REVA + 0x0f)) {
|
||||
max98090->devtype = MAX98090;
|
||||
devtype = MAX98090;
|
||||
dev_info(codec->dev, "MAX98090 REVID=0x%02x\n", ret);
|
||||
} else if ((ret >= M98091_REVA) && (ret <= M98091_REVA + 0x0f)) {
|
||||
max98090->devtype = MAX98091;
|
||||
devtype = MAX98091;
|
||||
dev_info(codec->dev, "MAX98091 REVID=0x%02x\n", ret);
|
||||
} else {
|
||||
max98090->devtype = MAX98090;
|
||||
devtype = MAX98090;
|
||||
dev_err(codec->dev, "Unrecognized revision 0x%02x\n", ret);
|
||||
}
|
||||
|
||||
if (max98090->devtype != devtype) {
|
||||
dev_warn(codec->dev, "Mismatch in DT specified CODEC type.\n");
|
||||
max98090->devtype = devtype;
|
||||
}
|
||||
|
||||
max98090->jack_state = M98090_JACK_STATE_NO_HEADSET;
|
||||
|
||||
INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work);
|
||||
|
@ -2317,8 +2299,6 @@ static int max98090_probe(struct snd_soc_codec *codec)
|
|||
snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE,
|
||||
M98090_MBVSEL_MASK, M98090_MBVSEL_2V8);
|
||||
|
||||
max98090_handle_pdata(codec);
|
||||
|
||||
max98090_add_widgets(codec);
|
||||
|
||||
err_access:
|
||||
|
@ -2428,7 +2408,7 @@ static int max98090_runtime_suspend(struct device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int max98090_resume(struct device *dev)
|
||||
{
|
||||
struct max98090_priv *max98090 = dev_get_drvdata(dev);
|
||||
|
@ -2460,12 +2440,14 @@ static const struct dev_pm_ops max98090_pm = {
|
|||
|
||||
static const struct i2c_device_id max98090_i2c_id[] = {
|
||||
{ "max98090", MAX98090 },
|
||||
{ "max98091", MAX98091 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max98090_i2c_id);
|
||||
|
||||
static const struct of_device_id max98090_of_match[] = {
|
||||
{ .compatible = "maxim,max98090", },
|
||||
{ .compatible = "maxim,max98091", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, max98090_of_match);
|
||||
|
|
|
@ -766,11 +766,11 @@ static int __init mc13783_codec_probe(struct platform_device *pdev)
|
|||
|
||||
ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pdev->dev, priv);
|
||||
|
@ -783,6 +783,8 @@ static int __init mc13783_codec_probe(struct platform_device *pdev)
|
|||
ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783,
|
||||
mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async));
|
||||
|
||||
out:
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
1224
sound/soc/codecs/rt286.c
Normal file
1224
sound/soc/codecs/rt286.c
Normal file
File diff suppressed because it is too large
Load diff
198
sound/soc/codecs/rt286.h
Normal file
198
sound/soc/codecs/rt286.h
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* rt286.h -- RT286 ALSA SoC audio driver
|
||||
*
|
||||
* Copyright 2011 Realtek Microelectronics
|
||||
* Author: Johnny Hsu <johnnyhsu@realtek.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 __RT286_H__
|
||||
#define __RT286_H__
|
||||
|
||||
#define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D)
|
||||
|
||||
#define RT286_AUDIO_FUNCTION_GROUP 0x01
|
||||
#define RT286_DAC_OUT1 0x02
|
||||
#define RT286_DAC_OUT2 0x03
|
||||
#define RT286_ADC_IN1 0x09
|
||||
#define RT286_ADC_IN2 0x08
|
||||
#define RT286_MIXER_IN 0x0b
|
||||
#define RT286_MIXER_OUT1 0x0c
|
||||
#define RT286_MIXER_OUT2 0x0d
|
||||
#define RT286_DMIC1 0x12
|
||||
#define RT286_DMIC2 0x13
|
||||
#define RT286_SPK_OUT 0x14
|
||||
#define RT286_MIC1 0x18
|
||||
#define RT286_LINE1 0x1a
|
||||
#define RT286_BEEP 0x1d
|
||||
#define RT286_SPDIF 0x1e
|
||||
#define RT286_VENDOR_REGISTERS 0x20
|
||||
#define RT286_HP_OUT 0x21
|
||||
#define RT286_MIXER_IN1 0x22
|
||||
#define RT286_MIXER_IN2 0x23
|
||||
|
||||
#define RT286_SET_PIN_SFT 6
|
||||
#define RT286_SET_PIN_ENABLE 0x40
|
||||
#define RT286_SET_PIN_DISABLE 0
|
||||
#define RT286_SET_EAPD_HIGH 0x2
|
||||
#define RT286_SET_EAPD_LOW 0
|
||||
|
||||
#define RT286_MUTE_SFT 7
|
||||
|
||||
/* Verb commands */
|
||||
#define RT286_GET_PARAM(NID, PARAM) VERB_CMD(AC_VERB_PARAMETERS, NID, PARAM)
|
||||
#define RT286_SET_POWER(NID) VERB_CMD(AC_VERB_SET_POWER_STATE, NID, 0)
|
||||
#define RT286_SET_AUDIO_POWER RT286_SET_POWER(RT286_AUDIO_FUNCTION_GROUP)
|
||||
#define RT286_SET_HPO_POWER RT286_SET_POWER(RT286_HP_OUT)
|
||||
#define RT286_SET_SPK_POWER RT286_SET_POWER(RT286_SPK_OUT)
|
||||
#define RT286_SET_DMIC1_POWER RT286_SET_POWER(RT286_DMIC1)
|
||||
#define RT286_SPK_MUX\
|
||||
VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_SPK_OUT, 0)
|
||||
#define RT286_HPO_MUX\
|
||||
VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_HP_OUT, 0)
|
||||
#define RT286_ADC0_MUX\
|
||||
VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_MIXER_IN1, 0)
|
||||
#define RT286_ADC1_MUX\
|
||||
VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT286_MIXER_IN2, 0)
|
||||
#define RT286_SET_MIC1\
|
||||
VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_MIC1, 0)
|
||||
#define RT286_SET_PIN_HPO\
|
||||
VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_HP_OUT, 0)
|
||||
#define RT286_SET_PIN_SPK\
|
||||
VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_SPK_OUT, 0)
|
||||
#define RT286_SET_PIN_DMIC1\
|
||||
VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT286_DMIC1, 0)
|
||||
#define RT286_SPK_EAPD\
|
||||
VERB_CMD(AC_VERB_SET_EAPD_BTLENABLE, RT286_SPK_OUT, 0)
|
||||
#define RT286_SET_AMP_GAIN_HPO\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0)
|
||||
#define RT286_SET_AMP_GAIN_ADC_IN1\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0)
|
||||
#define RT286_SET_AMP_GAIN_ADC_IN2\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN2, 0)
|
||||
#define RT286_GET_HP_SENSE\
|
||||
VERB_CMD(AC_VERB_GET_PIN_SENSE, RT286_HP_OUT, 0)
|
||||
#define RT286_GET_MIC1_SENSE\
|
||||
VERB_CMD(AC_VERB_GET_PIN_SENSE, RT286_MIC1, 0)
|
||||
#define RT286_SET_DMIC2_DEFAULT\
|
||||
VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT286_DMIC2, 0)
|
||||
#define RT286_DACL_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_DAC_OUT1, 0xa000)
|
||||
#define RT286_DACR_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_DAC_OUT1, 0x9000)
|
||||
#define RT286_ADCL_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0x6000)
|
||||
#define RT286_ADCR_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_ADC_IN1, 0x5000)
|
||||
#define RT286_MIC_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIC1, 0x7000)
|
||||
#define RT286_SPOL_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_SPK_OUT, 0xa000)
|
||||
#define RT286_SPOR_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_SPK_OUT, 0x9000)
|
||||
#define RT286_HPOL_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0xa000)
|
||||
#define RT286_HPOR_GAIN\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_HP_OUT, 0x9000)
|
||||
#define RT286_F_DAC_SWITCH\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_OUT1, 0x7000)
|
||||
#define RT286_F_RECMIX_SWITCH\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_OUT1, 0x7100)
|
||||
#define RT286_REC_MIC_SWITCH\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7000)
|
||||
#define RT286_REC_I2S_SWITCH\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7100)
|
||||
#define RT286_REC_LINE_SWITCH\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7200)
|
||||
#define RT286_REC_BEEP_SWITCH\
|
||||
VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT286_MIXER_IN, 0x7300)
|
||||
#define RT286_DAC_FORMAT\
|
||||
VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT286_DAC_OUT1, 0)
|
||||
#define RT286_ADC_FORMAT\
|
||||
VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT286_ADC_IN1, 0)
|
||||
#define RT286_COEF_INDEX\
|
||||
VERB_CMD(AC_VERB_SET_COEF_INDEX, RT286_VENDOR_REGISTERS, 0)
|
||||
#define RT286_PROC_COEF\
|
||||
VERB_CMD(AC_VERB_SET_PROC_COEF, RT286_VENDOR_REGISTERS, 0)
|
||||
|
||||
/* Index registers */
|
||||
#define RT286_A_BIAS_CTRL1 0x01
|
||||
#define RT286_A_BIAS_CTRL2 0x02
|
||||
#define RT286_POWER_CTRL1 0x03
|
||||
#define RT286_A_BIAS_CTRL3 0x04
|
||||
#define RT286_POWER_CTRL2 0x08
|
||||
#define RT286_I2S_CTRL1 0x09
|
||||
#define RT286_I2S_CTRL2 0x0a
|
||||
#define RT286_CLK_DIV 0x0b
|
||||
#define RT286_DC_GAIN 0x0d
|
||||
#define RT286_POWER_CTRL3 0x0f
|
||||
#define RT286_MIC1_DET_CTRL 0x19
|
||||
#define RT286_MISC_CTRL1 0x20
|
||||
#define RT286_IRQ_CTRL 0x33
|
||||
#define RT286_PLL_CTRL1 0x49
|
||||
#define RT286_CBJ_CTRL1 0x4f
|
||||
#define RT286_CBJ_CTRL2 0x50
|
||||
#define RT286_PLL_CTRL 0x63
|
||||
#define RT286_DEPOP_CTRL1 0x66
|
||||
#define RT286_DEPOP_CTRL2 0x67
|
||||
#define RT286_DEPOP_CTRL3 0x68
|
||||
#define RT286_DEPOP_CTRL4 0x69
|
||||
|
||||
/* SPDIF (0x06) */
|
||||
#define RT286_SPDIF_SEL_SFT 0
|
||||
#define RT286_SPDIF_SEL_PCM0 0
|
||||
#define RT286_SPDIF_SEL_PCM1 1
|
||||
#define RT286_SPDIF_SEL_SPOUT 2
|
||||
#define RT286_SPDIF_SEL_PP 3
|
||||
|
||||
/* RECMIX (0x0b) */
|
||||
#define RT286_M_REC_BEEP_SFT 0
|
||||
#define RT286_M_REC_LINE1_SFT 1
|
||||
#define RT286_M_REC_MIC1_SFT 2
|
||||
#define RT286_M_REC_I2S_SFT 3
|
||||
|
||||
/* Front (0x0c) */
|
||||
#define RT286_M_FRONT_DAC_SFT 0
|
||||
#define RT286_M_FRONT_REC_SFT 1
|
||||
|
||||
/* SPK-OUT (0x14) */
|
||||
#define RT286_M_SPK_MUX_SFT 14
|
||||
#define RT286_SPK_SEL_MASK 0x1
|
||||
#define RT286_SPK_SEL_SFT 0
|
||||
#define RT286_SPK_SEL_F 0
|
||||
#define RT286_SPK_SEL_S 1
|
||||
|
||||
/* HP-OUT (0x21) */
|
||||
#define RT286_M_HP_MUX_SFT 14
|
||||
#define RT286_HP_SEL_MASK 0x1
|
||||
#define RT286_HP_SEL_SFT 0
|
||||
#define RT286_HP_SEL_F 0
|
||||
#define RT286_HP_SEL_S 1
|
||||
|
||||
/* ADC (0x22) (0x23) */
|
||||
#define RT286_ADC_SEL_MASK 0x7
|
||||
#define RT286_ADC_SEL_SFT 0
|
||||
#define RT286_ADC_SEL_SURR 0
|
||||
#define RT286_ADC_SEL_FRONT 1
|
||||
#define RT286_ADC_SEL_DMIC 2
|
||||
#define RT286_ADC_SEL_BEEP 4
|
||||
#define RT286_ADC_SEL_LINE1 5
|
||||
#define RT286_ADC_SEL_I2S 6
|
||||
#define RT286_ADC_SEL_MIC1 7
|
||||
|
||||
#define RT286_SCLK_S_MCLK 0
|
||||
#define RT286_SCLK_S_PLL 1
|
||||
|
||||
enum {
|
||||
RT286_AIF1,
|
||||
RT286_AIF2,
|
||||
RT286_AIFS,
|
||||
};
|
||||
|
||||
int rt286_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
|
||||
|
||||
#endif /* __RT286_H__ */
|
||||
|
|
@ -58,3 +58,15 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH
|
|||
help
|
||||
This adds audio driver for Intel Baytrail platform based boards
|
||||
with the MAX98090 audio codec.
|
||||
|
||||
config SND_SOC_INTEL_BROADWELL_MACH
|
||||
tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint"
|
||||
depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC
|
||||
select SND_SOC_INTEL_HASWELL
|
||||
select SND_COMPRESS_OFFLOAD
|
||||
select SND_SOC_RT286
|
||||
help
|
||||
This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell
|
||||
Ultrabook platforms.
|
||||
Say Y if you have such a device
|
||||
If unsure select "N".
|
||||
|
|
|
@ -24,7 +24,9 @@ obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o
|
|||
snd-soc-sst-haswell-objs := haswell.o
|
||||
snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o
|
||||
snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o
|
||||
snd-soc-sst-broadwell-objs := broadwell.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
|
||||
obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
|
||||
|
|
251
sound/soc/intel/broadwell.c
Normal file
251
sound/soc/intel/broadwell.c
Normal file
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* Intel Broadwell Wildcatpoint SST Audio
|
||||
*
|
||||
* Copyright (C) 2013, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
||||
#include "sst-dsp.h"
|
||||
#include "sst-haswell-ipc.h"
|
||||
|
||||
#include "../codecs/rt286.h"
|
||||
|
||||
static const struct snd_soc_dapm_widget broadwell_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphones", NULL),
|
||||
SND_SOC_DAPM_SPK("Speaker", NULL),
|
||||
SND_SOC_DAPM_MIC("Mic Jack", NULL),
|
||||
SND_SOC_DAPM_MIC("DMIC1", NULL),
|
||||
SND_SOC_DAPM_MIC("DMIC2", NULL),
|
||||
SND_SOC_DAPM_LINE("Line Jack", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route broadwell_rt286_map[] = {
|
||||
|
||||
/* speaker */
|
||||
{"Speaker", NULL, "SPOR"},
|
||||
{"Speaker", NULL, "SPOL"},
|
||||
|
||||
/* HP jack connectors - unknown if we have jack deteck */
|
||||
{"Headphones", NULL, "HPO Pin"},
|
||||
|
||||
/* other jacks */
|
||||
{"MIC1", NULL, "Mic Jack"},
|
||||
{"LINE1", NULL, "Line Jack"},
|
||||
|
||||
/* digital mics */
|
||||
{"DMIC1 Pin", NULL, "DMIC1"},
|
||||
{"DMIC2 Pin", NULL, "DMIC2"},
|
||||
|
||||
/* CODEC BE connections */
|
||||
{"SSP0 CODEC IN", NULL, "AIF1 Capture"},
|
||||
{"AIF1 Playback", NULL, "SSP0 CODEC OUT"},
|
||||
};
|
||||
|
||||
static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_interval *rate = hw_param_interval(params,
|
||||
SNDRV_PCM_HW_PARAM_RATE);
|
||||
struct snd_interval *channels = hw_param_interval(params,
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||
|
||||
/* The ADSP will covert the FE rate to 48k, stereo */
|
||||
rate->min = rate->max = 48000;
|
||||
channels->min = channels->max = 2;
|
||||
|
||||
/* set SSP0 to 16 bit */
|
||||
snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT -
|
||||
SNDRV_PCM_HW_PARAM_FIRST_MASK],
|
||||
SNDRV_PCM_FORMAT_S16_LE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int broadwell_rt286_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;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000,
|
||||
SND_SOC_CLOCK_IN);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "can't set codec sysclk configuration\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct snd_soc_ops broadwell_rt286_ops = {
|
||||
.hw_params = broadwell_rt286_hw_params,
|
||||
};
|
||||
|
||||
static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
||||
struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev);
|
||||
struct sst_hsw *broadwell = pdata->dsp;
|
||||
int ret;
|
||||
|
||||
/* Set ADSP SSP port settings */
|
||||
ret = sst_hsw_device_set_config(broadwell, SST_HSW_DEVICE_SSP_0,
|
||||
SST_HSW_DEVICE_MCLK_FREQ_24_MHZ,
|
||||
SST_HSW_DEVICE_CLOCK_MASTER, 9);
|
||||
if (ret < 0) {
|
||||
dev_err(rtd->dev, "error: failed to set device config\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* always connected - check HP for jack detect */
|
||||
snd_soc_dapm_enable_pin(dapm, "Headphones");
|
||||
snd_soc_dapm_enable_pin(dapm, "Speaker");
|
||||
snd_soc_dapm_enable_pin(dapm, "Mic Jack");
|
||||
snd_soc_dapm_enable_pin(dapm, "Line Jack");
|
||||
snd_soc_dapm_enable_pin(dapm, "DMIC1");
|
||||
snd_soc_dapm_enable_pin(dapm, "DMIC2");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* broadwell digital audio interface glue - connects codec <--> CPU */
|
||||
static struct snd_soc_dai_link broadwell_rt286_dais[] = {
|
||||
/* Front End DAI links */
|
||||
{
|
||||
.name = "System PCM",
|
||||
.stream_name = "System Playback",
|
||||
.cpu_dai_name = "System Pin",
|
||||
.platform_name = "haswell-pcm-audio",
|
||||
.dynamic = 1,
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.init = broadwell_rtd_init,
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
|
||||
.dpcm_playback = 1,
|
||||
},
|
||||
{
|
||||
.name = "Offload0",
|
||||
.stream_name = "Offload0 Playback",
|
||||
.cpu_dai_name = "Offload0 Pin",
|
||||
.platform_name = "haswell-pcm-audio",
|
||||
.dynamic = 1,
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
|
||||
.dpcm_playback = 1,
|
||||
},
|
||||
{
|
||||
.name = "Offload1",
|
||||
.stream_name = "Offload1 Playback",
|
||||
.cpu_dai_name = "Offload1 Pin",
|
||||
.platform_name = "haswell-pcm-audio",
|
||||
.dynamic = 1,
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
|
||||
.dpcm_playback = 1,
|
||||
},
|
||||
{
|
||||
.name = "Loopback PCM",
|
||||
.stream_name = "Loopback",
|
||||
.cpu_dai_name = "Loopback Pin",
|
||||
.platform_name = "haswell-pcm-audio",
|
||||
.dynamic = 0,
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
|
||||
.dpcm_capture = 1,
|
||||
},
|
||||
{
|
||||
.name = "Capture PCM",
|
||||
.stream_name = "Capture",
|
||||
.cpu_dai_name = "Capture Pin",
|
||||
.platform_name = "haswell-pcm-audio",
|
||||
.dynamic = 1,
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
|
||||
.dpcm_capture = 1,
|
||||
},
|
||||
|
||||
/* Back End DAI links */
|
||||
{
|
||||
/* SSP0 - Codec */
|
||||
.name = "Codec",
|
||||
.be_id = 0,
|
||||
.cpu_dai_name = "snd-soc-dummy-dai",
|
||||
.platform_name = "snd-soc-dummy",
|
||||
.no_pcm = 1,
|
||||
.codec_name = "i2c-INT343A:00",
|
||||
.codec_dai_name = "rt286-aif1",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBS_CFS,
|
||||
.ignore_suspend = 1,
|
||||
.ignore_pmdown_time = 1,
|
||||
.be_hw_params_fixup = broadwell_ssp0_fixup,
|
||||
.ops = &broadwell_rt286_ops,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
},
|
||||
};
|
||||
|
||||
/* broadwell audio machine driver for WPT + RT286S */
|
||||
static struct snd_soc_card broadwell_rt286 = {
|
||||
.name = "broadwell-rt286",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = broadwell_rt286_dais,
|
||||
.num_links = ARRAY_SIZE(broadwell_rt286_dais),
|
||||
.dapm_widgets = broadwell_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(broadwell_widgets),
|
||||
.dapm_routes = broadwell_rt286_map,
|
||||
.num_dapm_routes = ARRAY_SIZE(broadwell_rt286_map),
|
||||
.fully_routed = true,
|
||||
};
|
||||
|
||||
static int broadwell_audio_probe(struct platform_device *pdev)
|
||||
{
|
||||
broadwell_rt286.dev = &pdev->dev;
|
||||
|
||||
return snd_soc_register_card(&broadwell_rt286);
|
||||
}
|
||||
|
||||
static int broadwell_audio_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_card(&broadwell_rt286);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver broadwell_audio = {
|
||||
.probe = broadwell_audio_probe,
|
||||
.remove = broadwell_audio_remove,
|
||||
.driver = {
|
||||
.name = "broadwell-audio",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(broadwell_audio)
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("Liam Girdwood, Xingchao Wang");
|
||||
MODULE_DESCRIPTION("Intel SST Audio for WPT/Broadwell");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:broadwell-audio");
|
|
@ -63,14 +63,6 @@ static struct snd_soc_jack_pin hs_jack_pins[] = {
|
|||
.pin = "Headset Mic",
|
||||
.mask = SND_JACK_MICROPHONE,
|
||||
},
|
||||
{
|
||||
.pin = "Ext Spk",
|
||||
.mask = SND_JACK_LINEOUT,
|
||||
},
|
||||
{
|
||||
.pin = "Int Mic",
|
||||
.mask = SND_JACK_LINEIN,
|
||||
},
|
||||
};
|
||||
|
||||
static struct snd_soc_jack_gpio hs_jack_gpios[] = {
|
||||
|
|
|
@ -34,6 +34,7 @@ static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
|
|||
};
|
||||
|
||||
static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
|
||||
{"Headset Mic", NULL, "MICBIAS1"},
|
||||
{"IN2P", NULL, "Headset Mic"},
|
||||
{"IN2N", NULL, "Headset Mic"},
|
||||
{"DMIC1", NULL, "Internal Mic"},
|
||||
|
|
30
sound/soc/intel/sst-atom-controls.h
Normal file
30
sound/soc/intel/sst-atom-controls.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2013-14 Intel Corp
|
||||
* Author: Ramesh Babu <ramesh.babu.koul@intel.com>
|
||||
* Omair M Abdullah <omair.m.abdullah@intel.com>
|
||||
* Samreen Nilofer <samreen.nilofer@intel.com>
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SST_CONTROLS_V2_H__
|
||||
#define __SST_CONTROLS_V2_H__
|
||||
|
||||
enum {
|
||||
MERR_DPCM_AUDIO = 0,
|
||||
MERR_DPCM_COMPR,
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -122,6 +122,26 @@ struct sst_byt_tstamp {
|
|||
u32 channel_peak[8];
|
||||
} __packed;
|
||||
|
||||
struct sst_byt_fw_version {
|
||||
u8 build;
|
||||
u8 minor;
|
||||
u8 major;
|
||||
u8 type;
|
||||
} __packed;
|
||||
|
||||
struct sst_byt_fw_build_info {
|
||||
u8 date[16];
|
||||
u8 time[16];
|
||||
} __packed;
|
||||
|
||||
struct sst_byt_fw_init {
|
||||
struct sst_byt_fw_version fw_version;
|
||||
struct sst_byt_fw_build_info build_info;
|
||||
u16 result;
|
||||
u8 module_id;
|
||||
u8 debug_info;
|
||||
} __packed;
|
||||
|
||||
/* driver internal IPC message structure */
|
||||
struct ipc_message {
|
||||
struct list_head list;
|
||||
|
@ -868,6 +888,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
|
|||
{
|
||||
struct sst_byt *byt;
|
||||
struct sst_fw *byt_sst_fw;
|
||||
struct sst_byt_fw_init init;
|
||||
int err;
|
||||
|
||||
dev_dbg(dev, "initialising Byt DSP IPC\n");
|
||||
|
@ -929,6 +950,15 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
|
|||
goto boot_err;
|
||||
}
|
||||
|
||||
/* show firmware information */
|
||||
sst_dsp_inbox_read(byt->dsp, &init, sizeof(init));
|
||||
dev_info(byt->dev, "FW version: %02x.%02x.%02x.%02x\n",
|
||||
init.fw_version.major, init.fw_version.minor,
|
||||
init.fw_version.build, init.fw_version.type);
|
||||
dev_info(byt->dev, "Build type: %x\n", init.fw_version.type);
|
||||
dev_info(byt->dev, "Build date: %s %s\n",
|
||||
init.build_info.date, init.build_info.time);
|
||||
|
||||
pdata->dsp = byt;
|
||||
byt->fw = byt_sst_fw;
|
||||
|
||||
|
|
|
@ -224,19 +224,23 @@ EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64);
|
|||
|
||||
void sst_dsp_dump(struct sst_dsp *sst)
|
||||
{
|
||||
sst->ops->dump(sst);
|
||||
if (sst->ops->dump)
|
||||
sst->ops->dump(sst);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sst_dsp_dump);
|
||||
|
||||
void sst_dsp_reset(struct sst_dsp *sst)
|
||||
{
|
||||
sst->ops->reset(sst);
|
||||
if (sst->ops->reset)
|
||||
sst->ops->reset(sst);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sst_dsp_reset);
|
||||
|
||||
int sst_dsp_boot(struct sst_dsp *sst)
|
||||
{
|
||||
sst->ops->boot(sst);
|
||||
if (sst->ops->boot)
|
||||
sst->ops->boot(sst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sst_dsp_boot);
|
||||
|
|
|
@ -52,7 +52,11 @@
|
|||
#define SST_CLKCTL 0x78
|
||||
#define SST_CSR2 0x80
|
||||
#define SST_LTRC 0xE0
|
||||
#define SST_HDMC 0xE8
|
||||
#define SST_HMDC 0xE8
|
||||
|
||||
#define SST_SHIM_BEGIN SST_CSR
|
||||
#define SST_SHIM_END SST_HDMC
|
||||
|
||||
#define SST_DBGO 0xF0
|
||||
|
||||
#define SST_SHIM_SIZE 0x100
|
||||
|
@ -73,6 +77,8 @@
|
|||
#define SST_CSR_S0IOCS (0x1 << 21)
|
||||
#define SST_CSR_S1IOCS (0x1 << 23)
|
||||
#define SST_CSR_LPCS (0x1 << 31)
|
||||
#define SST_CSR_24MHZ_LPCS (SST_CSR_SBCS0 | SST_CSR_SBCS1 | SST_CSR_LPCS)
|
||||
#define SST_CSR_24MHZ_NO_LPCS (SST_CSR_SBCS0 | SST_CSR_SBCS1)
|
||||
#define SST_BYT_CSR_RST (0x1 << 0)
|
||||
#define SST_BYT_CSR_VECTOR_SEL (0x1 << 1)
|
||||
#define SST_BYT_CSR_STALL (0x1 << 2)
|
||||
|
@ -92,6 +98,14 @@
|
|||
#define SST_IMRX_DONE (0x1 << 0)
|
||||
#define SST_BYT_IMRX_REQUEST (0x1 << 1)
|
||||
|
||||
/* IMRD / IMD */
|
||||
#define SST_IMRD_DONE (0x1 << 0)
|
||||
#define SST_IMRD_BUSY (0x1 << 1)
|
||||
#define SST_IMRD_SSP0 (0x1 << 16)
|
||||
#define SST_IMRD_DMAC0 (0x1 << 21)
|
||||
#define SST_IMRD_DMAC1 (0x1 << 22)
|
||||
#define SST_IMRD_DMAC (SST_IMRD_DMAC0 | SST_IMRD_DMAC1)
|
||||
|
||||
/* IPCX / IPCC */
|
||||
#define SST_IPCX_DONE (0x1 << 30)
|
||||
#define SST_IPCX_BUSY (0x1 << 31)
|
||||
|
@ -118,9 +132,21 @@
|
|||
/* LTRC */
|
||||
#define SST_LTRC_VAL(x) (x << 0)
|
||||
|
||||
/* HDMC */
|
||||
#define SST_HDMC_HDDA0(x) (x << 0)
|
||||
#define SST_HDMC_HDDA1(x) (x << 7)
|
||||
/* HMDC */
|
||||
#define SST_HMDC_HDDA0(x) (x << 0)
|
||||
#define SST_HMDC_HDDA1(x) (x << 7)
|
||||
#define SST_HMDC_HDDA_E0_CH0 1
|
||||
#define SST_HMDC_HDDA_E0_CH1 2
|
||||
#define SST_HMDC_HDDA_E0_CH2 4
|
||||
#define SST_HMDC_HDDA_E0_CH3 8
|
||||
#define SST_HMDC_HDDA_E1_CH0 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH0)
|
||||
#define SST_HMDC_HDDA_E1_CH1 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH1)
|
||||
#define SST_HMDC_HDDA_E1_CH2 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH2)
|
||||
#define SST_HMDC_HDDA_E1_CH3 SST_HMDC_HDDA1(SST_HMDC_HDDA_E0_CH3)
|
||||
#define SST_HMDC_HDDA_E0_ALLCH (SST_HMDC_HDDA_E0_CH0 | SST_HMDC_HDDA_E0_CH1 | \
|
||||
SST_HMDC_HDDA_E0_CH2 | SST_HMDC_HDDA_E0_CH3)
|
||||
#define SST_HMDC_HDDA_E1_ALLCH (SST_HMDC_HDDA_E1_CH0 | SST_HMDC_HDDA_E1_CH1 | \
|
||||
SST_HMDC_HDDA_E1_CH2 | SST_HMDC_HDDA_E1_CH3)
|
||||
|
||||
|
||||
/* SST Vendor Defined Registers and bits */
|
||||
|
@ -130,11 +156,16 @@
|
|||
#define SST_VDRTCTL3 0xaC
|
||||
|
||||
/* VDRTCTL0 */
|
||||
#define SST_VDRTCL0_APLLSE_MASK 1
|
||||
#define SST_VDRTCL0_DSRAMPGE_SHIFT 16
|
||||
#define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT)
|
||||
#define SST_VDRTCL0_ISRAMPGE_SHIFT 6
|
||||
#define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT)
|
||||
|
||||
/* PMCS */
|
||||
#define SST_PMCS 0x84
|
||||
#define SST_PMCS_PS_MASK 0x3
|
||||
|
||||
struct sst_dsp;
|
||||
|
||||
/*
|
||||
|
|
|
@ -28,9 +28,6 @@
|
|||
#include <linux/firmware.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
|
||||
#include "sst-dsp.h"
|
||||
#include "sst-dsp-priv.h"
|
||||
#include "sst-haswell-ipc.h"
|
||||
|
@ -272,9 +269,9 @@ static void hsw_boot(struct sst_dsp *sst)
|
|||
SST_CSR2_SDFD_SSP1);
|
||||
|
||||
/* enable DMA engine 0,1 all channels to access host memory */
|
||||
sst_dsp_shim_update_bits_unlocked(sst, SST_HDMC,
|
||||
SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff),
|
||||
SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff));
|
||||
sst_dsp_shim_update_bits_unlocked(sst, SST_HMDC,
|
||||
SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff),
|
||||
SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff));
|
||||
|
||||
/* disable all clock gating */
|
||||
writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2);
|
||||
|
@ -313,9 +310,7 @@ static const struct sst_adsp_memregion lp_region[] = {
|
|||
|
||||
/* wild cat point ADSP mem regions */
|
||||
static const struct sst_adsp_memregion wpt_region[] = {
|
||||
{0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */
|
||||
{0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */
|
||||
{0x80000, 0xA0000, 4, SST_MEM_DRAM}, /* D-SRAM2 - 4 * 32kB */
|
||||
{0x00000, 0xA0000, 20, SST_MEM_DRAM}, /* D-SRAM0,D-SRAM1,D-SRAM2 - 20 * 32kB */
|
||||
{0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */
|
||||
};
|
||||
|
||||
|
@ -339,21 +334,40 @@ static int hsw_acpi_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct sst_sram_shift {
|
||||
u32 dev_id; /* SST Device IDs */
|
||||
u32 iram_shift;
|
||||
u32 dram_shift;
|
||||
};
|
||||
|
||||
static const struct sst_sram_shift sram_shift[] = {
|
||||
{SST_DEV_ID_LYNX_POINT, 6, 16}, /* lp */
|
||||
{SST_DEV_ID_WILDCAT_POINT, 2, 12}, /* wpt */
|
||||
};
|
||||
static u32 hsw_block_get_bit(struct sst_mem_block *block)
|
||||
{
|
||||
u32 bit = 0, shift = 0;
|
||||
u32 bit = 0, shift = 0, index;
|
||||
struct sst_dsp *sst = block->dsp;
|
||||
|
||||
switch (block->type) {
|
||||
case SST_MEM_DRAM:
|
||||
shift = 16;
|
||||
break;
|
||||
case SST_MEM_IRAM:
|
||||
shift = 6;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
for (index = 0; index < ARRAY_SIZE(sram_shift); index++) {
|
||||
if (sram_shift[index].dev_id == sst->id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (index < ARRAY_SIZE(sram_shift)) {
|
||||
switch (block->type) {
|
||||
case SST_MEM_DRAM:
|
||||
shift = sram_shift[index].dram_shift;
|
||||
break;
|
||||
case SST_MEM_IRAM:
|
||||
shift = sram_shift[index].iram_shift;
|
||||
break;
|
||||
default:
|
||||
shift = 0;
|
||||
}
|
||||
} else
|
||||
shift = 0;
|
||||
|
||||
bit = 1 << (block->index + shift);
|
||||
|
||||
return bit;
|
||||
|
@ -501,8 +515,9 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata)
|
|||
}
|
||||
}
|
||||
|
||||
/* set default power gating mask */
|
||||
writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL0);
|
||||
/* set default power gating control, enable power gating control for all blocks. that is,
|
||||
can't be accessed, please enable each block before accessing. */
|
||||
writel(0xffffffff, sst->addr.pci_cfg + SST_VDRTCTL0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ struct sst_hsw_ipc_fw_ready {
|
|||
u32 inbox_size;
|
||||
u32 outbox_size;
|
||||
u32 fw_info_size;
|
||||
u8 fw_info[1];
|
||||
u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ipc_message {
|
||||
|
@ -457,9 +457,10 @@ static void ipc_tx_msgs(struct kthread_work *work)
|
|||
return;
|
||||
}
|
||||
|
||||
/* if the DSP is busy we will TX messages after IRQ */
|
||||
/* if the DSP is busy, we will TX messages after IRQ.
|
||||
* also postpone if we are in the middle of procesing completion irq*/
|
||||
ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX);
|
||||
if (ipcx & SST_IPCX_BUSY) {
|
||||
if (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)) {
|
||||
spin_unlock_irqrestore(&hsw->dsp->spinlock, flags);
|
||||
return;
|
||||
}
|
||||
|
@ -502,6 +503,7 @@ static int tx_wait_done(struct sst_hsw *hsw, struct ipc_message *msg,
|
|||
ipc_shim_dbg(hsw, "message timeout");
|
||||
|
||||
trace_ipc_error("error message timeout for", msg->header);
|
||||
list_del(&msg->list);
|
||||
ret = -ETIMEDOUT;
|
||||
} else {
|
||||
|
||||
|
@ -569,6 +571,9 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header)
|
|||
{
|
||||
struct sst_hsw_ipc_fw_ready fw_ready;
|
||||
u32 offset;
|
||||
u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)];
|
||||
char *tmp[5], *pinfo;
|
||||
int i = 0;
|
||||
|
||||
offset = (header & 0x1FFFFFFF) << 3;
|
||||
|
||||
|
@ -589,6 +594,19 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header)
|
|||
fw_ready.inbox_offset, fw_ready.inbox_size);
|
||||
dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n",
|
||||
fw_ready.outbox_offset, fw_ready.outbox_size);
|
||||
if (fw_ready.fw_info_size < sizeof(fw_ready.fw_info)) {
|
||||
fw_ready.fw_info[fw_ready.fw_info_size] = 0;
|
||||
dev_dbg(hsw->dev, " Firmware info: %s \n", fw_ready.fw_info);
|
||||
|
||||
/* log the FW version info got from the mailbox here. */
|
||||
memcpy(fw_info, fw_ready.fw_info, fw_ready.fw_info_size);
|
||||
pinfo = &fw_info[0];
|
||||
for (i = 0; i < sizeof(tmp) / sizeof(char *); i++)
|
||||
tmp[i] = strsep(&pinfo, " ");
|
||||
dev_info(hsw->dev, "FW loaded, mailbox readback FW info: type %s, - "
|
||||
"version: %s.%s, build %s, source commit id: %s\n",
|
||||
tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]);
|
||||
}
|
||||
}
|
||||
|
||||
static void hsw_notification_work(struct work_struct *work)
|
||||
|
@ -671,7 +689,9 @@ static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg)
|
|||
switch (stream_msg) {
|
||||
case IPC_STR_STAGE_MESSAGE:
|
||||
case IPC_STR_NOTIFICATION:
|
||||
break;
|
||||
case IPC_STR_RESET:
|
||||
trace_ipc_notification("stream reset", stream->reply.stream_hw_id);
|
||||
break;
|
||||
case IPC_STR_PAUSE:
|
||||
stream->running = false;
|
||||
|
@ -762,7 +782,8 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header)
|
|||
}
|
||||
|
||||
/* update any stream states */
|
||||
hsw_stream_update(hsw, msg);
|
||||
if (msg_get_global_type(header) == IPC_GLB_STREAM_MESSAGE)
|
||||
hsw_stream_update(hsw, msg);
|
||||
|
||||
/* wake up and return the error if we have waiters on this message ? */
|
||||
list_del(&msg->list);
|
||||
|
@ -1628,7 +1649,7 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw,
|
|||
enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx)
|
||||
{
|
||||
u32 header, state_;
|
||||
int ret;
|
||||
int ret, item;
|
||||
|
||||
header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE);
|
||||
state_ = state;
|
||||
|
@ -1642,6 +1663,13 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw,
|
|||
return ret;
|
||||
}
|
||||
|
||||
for (item = 0; item < dx->entries_no; item++) {
|
||||
dev_dbg(hsw->dev,
|
||||
"Item[%d] offset[%x] - size[%x] - source[%x]\n",
|
||||
item, dx->mem_info[item].offset,
|
||||
dx->mem_info[item].size,
|
||||
dx->mem_info[item].source);
|
||||
}
|
||||
dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n",
|
||||
dx->entries_no, state);
|
||||
|
||||
|
@ -1775,8 +1803,6 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
|
|||
|
||||
/* get the FW version */
|
||||
sst_hsw_fw_get_version(hsw, &version);
|
||||
dev_info(hsw->dev, "FW loaded: type %d - version: %d.%d build %d\n",
|
||||
version.type, version.major, version.minor, version.build);
|
||||
|
||||
/* get the globalmixer */
|
||||
ret = sst_hsw_mixer_get_info(hsw);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
* sst_mfld_dsp.h - Intel SST Driver for audio engine
|
||||
*
|
||||
* Copyright (C) 2008-12 Intel Corporation
|
||||
* Copyright (C) 2008-14 Intel Corporation
|
||||
* Authors: Vinod Koul <vinod.koul@linux.intel.com>
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
|
@ -19,6 +19,142 @@
|
|||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
#define SST_MAX_BIN_BYTES 1024
|
||||
|
||||
#define MAX_DBG_RW_BYTES 80
|
||||
#define MAX_NUM_SCATTER_BUFFERS 8
|
||||
#define MAX_LOOP_BACK_DWORDS 8
|
||||
/* IPC base address and mailbox, timestamp offsets */
|
||||
#define SST_MAILBOX_SIZE 0x0400
|
||||
#define SST_MAILBOX_SEND 0x0000
|
||||
#define SST_TIME_STAMP 0x1800
|
||||
#define SST_TIME_STAMP_MRFLD 0x800
|
||||
#define SST_RESERVED_OFFSET 0x1A00
|
||||
#define SST_SCU_LPE_MAILBOX 0x1000
|
||||
#define SST_LPE_SCU_MAILBOX 0x1400
|
||||
#define SST_SCU_LPE_LOG_BUF (SST_SCU_LPE_MAILBOX+16)
|
||||
#define PROCESS_MSG 0x80
|
||||
|
||||
/* Message ID's for IPC messages */
|
||||
/* Bits B7: SST or IA/SC ; B6-B4: Msg Category; B3-B0: Msg Type */
|
||||
|
||||
/* I2L Firmware/Codec Download msgs */
|
||||
#define IPC_IA_PREP_LIB_DNLD 0x01
|
||||
#define IPC_IA_LIB_DNLD_CMPLT 0x02
|
||||
#define IPC_IA_GET_FW_VERSION 0x04
|
||||
#define IPC_IA_GET_FW_BUILD_INF 0x05
|
||||
#define IPC_IA_GET_FW_INFO 0x06
|
||||
#define IPC_IA_GET_FW_CTXT 0x07
|
||||
#define IPC_IA_SET_FW_CTXT 0x08
|
||||
#define IPC_IA_PREPARE_SHUTDOWN 0x31
|
||||
/* I2L Codec Config/control msgs */
|
||||
#define IPC_PREP_D3 0x10
|
||||
#define IPC_IA_SET_CODEC_PARAMS 0x10
|
||||
#define IPC_IA_GET_CODEC_PARAMS 0x11
|
||||
#define IPC_IA_SET_PPP_PARAMS 0x12
|
||||
#define IPC_IA_GET_PPP_PARAMS 0x13
|
||||
#define IPC_SST_PERIOD_ELAPSED_MRFLD 0xA
|
||||
#define IPC_IA_ALG_PARAMS 0x1A
|
||||
#define IPC_IA_TUNING_PARAMS 0x1B
|
||||
#define IPC_IA_SET_RUNTIME_PARAMS 0x1C
|
||||
#define IPC_IA_SET_PARAMS 0x1
|
||||
#define IPC_IA_GET_PARAMS 0x2
|
||||
|
||||
#define IPC_EFFECTS_CREATE 0xE
|
||||
#define IPC_EFFECTS_DESTROY 0xF
|
||||
|
||||
/* I2L Stream config/control msgs */
|
||||
#define IPC_IA_ALLOC_STREAM_MRFLD 0x2
|
||||
#define IPC_IA_ALLOC_STREAM 0x20 /* Allocate a stream ID */
|
||||
#define IPC_IA_FREE_STREAM_MRFLD 0x03
|
||||
#define IPC_IA_FREE_STREAM 0x21 /* Free the stream ID */
|
||||
#define IPC_IA_SET_STREAM_PARAMS 0x22
|
||||
#define IPC_IA_SET_STREAM_PARAMS_MRFLD 0x12
|
||||
#define IPC_IA_GET_STREAM_PARAMS 0x23
|
||||
#define IPC_IA_PAUSE_STREAM 0x24
|
||||
#define IPC_IA_PAUSE_STREAM_MRFLD 0x4
|
||||
#define IPC_IA_RESUME_STREAM 0x25
|
||||
#define IPC_IA_RESUME_STREAM_MRFLD 0x5
|
||||
#define IPC_IA_DROP_STREAM 0x26
|
||||
#define IPC_IA_DROP_STREAM_MRFLD 0x07
|
||||
#define IPC_IA_DRAIN_STREAM 0x27 /* Short msg with str_id */
|
||||
#define IPC_IA_DRAIN_STREAM_MRFLD 0x8
|
||||
#define IPC_IA_CONTROL_ROUTING 0x29
|
||||
#define IPC_IA_VTSV_UPDATE_MODULES 0x20
|
||||
#define IPC_IA_VTSV_DETECTED 0x21
|
||||
|
||||
#define IPC_IA_START_STREAM_MRFLD 0X06
|
||||
#define IPC_IA_START_STREAM 0x30 /* Short msg with str_id */
|
||||
|
||||
#define IPC_IA_SET_GAIN_MRFLD 0x21
|
||||
/* Debug msgs */
|
||||
#define IPC_IA_DBG_MEM_READ 0x40
|
||||
#define IPC_IA_DBG_MEM_WRITE 0x41
|
||||
#define IPC_IA_DBG_LOOP_BACK 0x42
|
||||
#define IPC_IA_DBG_LOG_ENABLE 0x45
|
||||
#define IPC_IA_DBG_SET_PROBE_PARAMS 0x47
|
||||
|
||||
/* L2I Firmware/Codec Download msgs */
|
||||
#define IPC_IA_FW_INIT_CMPLT 0x81
|
||||
#define IPC_IA_FW_INIT_CMPLT_MRFLD 0x01
|
||||
#define IPC_IA_FW_ASYNC_ERR_MRFLD 0x11
|
||||
|
||||
/* L2I Codec Config/control msgs */
|
||||
#define IPC_SST_FRAGMENT_ELPASED 0x90 /* Request IA more data */
|
||||
|
||||
#define IPC_SST_BUF_UNDER_RUN 0x92 /* PB Under run and stopped */
|
||||
#define IPC_SST_BUF_OVER_RUN 0x93 /* CAP Under run and stopped */
|
||||
#define IPC_SST_DRAIN_END 0x94 /* PB Drain complete and stopped */
|
||||
#define IPC_SST_CHNGE_SSP_PARAMS 0x95 /* PB SSP parameters changed */
|
||||
#define IPC_SST_STREAM_PROCESS_FATAL_ERR 0x96/* error in processing a stream */
|
||||
#define IPC_SST_PERIOD_ELAPSED 0x97 /* period elapsed */
|
||||
|
||||
#define IPC_SST_ERROR_EVENT 0x99 /* Buffer over run occurred */
|
||||
/* L2S messages */
|
||||
#define IPC_SC_DDR_LINK_UP 0xC0
|
||||
#define IPC_SC_DDR_LINK_DOWN 0xC1
|
||||
#define IPC_SC_SET_LPECLK_REQ 0xC2
|
||||
#define IPC_SC_SSP_BIT_BANG 0xC3
|
||||
|
||||
/* L2I Error reporting msgs */
|
||||
#define IPC_IA_MEM_ALLOC_FAIL 0xE0
|
||||
#define IPC_IA_PROC_ERR 0xE1 /* error in processing a
|
||||
stream can be used by playback and
|
||||
capture modules */
|
||||
|
||||
/* L2I Debug msgs */
|
||||
#define IPC_IA_PRINT_STRING 0xF0
|
||||
|
||||
/* Buffer under-run */
|
||||
#define IPC_IA_BUF_UNDER_RUN_MRFLD 0x0B
|
||||
|
||||
/* Mrfld specific defines:
|
||||
* For asynchronous messages(INIT_CMPLT, PERIOD_ELAPSED, ASYNC_ERROR)
|
||||
* received from FW, the format is:
|
||||
* - IPC High: pvt_id is set to zero. Always short message.
|
||||
* - msg_id is in lower 16-bits of IPC low payload.
|
||||
* - pipe_id is in higher 16-bits of IPC low payload for period_elapsed.
|
||||
* - error id is in higher 16-bits of IPC low payload for async errors.
|
||||
*/
|
||||
#define SST_ASYNC_DRV_ID 0
|
||||
|
||||
/* Command Response or Acknowledge message to any IPC message will have
|
||||
* same message ID and stream ID information which is sent.
|
||||
* There is no specific Ack message ID. The data field is used as response
|
||||
* meaning.
|
||||
*/
|
||||
enum ackData {
|
||||
IPC_ACK_SUCCESS = 0,
|
||||
IPC_ACK_FAILURE,
|
||||
};
|
||||
|
||||
enum ipc_ia_msg_id {
|
||||
IPC_CMD = 1, /*!< Task Control message ID */
|
||||
IPC_SET_PARAMS = 2,/*!< Task Set param message ID */
|
||||
IPC_GET_PARAMS = 3, /*!< Task Get param message ID */
|
||||
IPC_INVALID = 0xFF, /*!<Task Get param message ID */
|
||||
};
|
||||
|
||||
enum sst_codec_types {
|
||||
/* AUDIO/MUSIC CODEC Type Definitions */
|
||||
SST_CODEC_TYPE_UNKNOWN = 0,
|
||||
|
@ -35,14 +171,157 @@ enum stream_type {
|
|||
SST_STREAM_TYPE_MUSIC = 1,
|
||||
};
|
||||
|
||||
enum sst_error_codes {
|
||||
/* Error code,response to msgId: Description */
|
||||
/* Common error codes */
|
||||
SST_SUCCESS = 0, /* Success */
|
||||
SST_ERR_INVALID_STREAM_ID = 1,
|
||||
SST_ERR_INVALID_MSG_ID = 2,
|
||||
SST_ERR_INVALID_STREAM_OP = 3,
|
||||
SST_ERR_INVALID_PARAMS = 4,
|
||||
SST_ERR_INVALID_CODEC = 5,
|
||||
SST_ERR_INVALID_MEDIA_TYPE = 6,
|
||||
SST_ERR_STREAM_ERR = 7,
|
||||
|
||||
SST_ERR_STREAM_IN_USE = 15,
|
||||
};
|
||||
|
||||
struct ipc_dsp_hdr {
|
||||
u16 mod_index_id:8; /*!< DSP Command ID specific to tasks */
|
||||
u16 pipe_id:8; /*!< instance of the module in the pipeline */
|
||||
u16 mod_id; /*!< Pipe_id */
|
||||
u16 cmd_id; /*!< Module ID = lpe_algo_types_t */
|
||||
u16 length; /*!< Length of the payload only */
|
||||
} __packed;
|
||||
|
||||
union ipc_header_high {
|
||||
struct {
|
||||
u32 msg_id:8; /* Message ID - Max 256 Message Types */
|
||||
u32 task_id:4; /* Task ID associated with this comand */
|
||||
u32 drv_id:4; /* Identifier for the driver to track*/
|
||||
u32 rsvd1:8; /* Reserved */
|
||||
u32 result:4; /* Reserved */
|
||||
u32 res_rqd:1; /* Response rqd */
|
||||
u32 large:1; /* Large Message if large = 1 */
|
||||
u32 done:1; /* bit 30 - Done bit */
|
||||
u32 busy:1; /* bit 31 - busy bit*/
|
||||
} part;
|
||||
u32 full;
|
||||
} __packed;
|
||||
/* IPC header */
|
||||
union ipc_header_mrfld {
|
||||
struct {
|
||||
u32 header_low_payload;
|
||||
union ipc_header_high header_high;
|
||||
} p;
|
||||
u64 full;
|
||||
} __packed;
|
||||
/* CAUTION NOTE: All IPC message body must be multiple of 32 bits.*/
|
||||
|
||||
/* IPC Header */
|
||||
union ipc_header {
|
||||
struct {
|
||||
u32 msg_id:8; /* Message ID - Max 256 Message Types */
|
||||
u32 str_id:5;
|
||||
u32 large:1; /* Large Message if large = 1 */
|
||||
u32 reserved:2; /* Reserved for future use */
|
||||
u32 data:14; /* Ack/Info for msg, size of msg in Mailbox */
|
||||
u32 done:1; /* bit 30 */
|
||||
u32 busy:1; /* bit 31 */
|
||||
} part;
|
||||
u32 full;
|
||||
} __packed;
|
||||
|
||||
/* Firmware build info */
|
||||
struct sst_fw_build_info {
|
||||
unsigned char date[16]; /* Firmware build date */
|
||||
unsigned char time[16]; /* Firmware build time */
|
||||
} __packed;
|
||||
|
||||
/* Firmware Version info */
|
||||
struct snd_sst_fw_version {
|
||||
u8 build; /* build number*/
|
||||
u8 minor; /* minor number*/
|
||||
u8 major; /* major number*/
|
||||
u8 type; /* build type */
|
||||
};
|
||||
|
||||
struct ipc_header_fw_init {
|
||||
struct snd_sst_fw_version fw_version;/* Firmware version details */
|
||||
struct sst_fw_build_info build_info;
|
||||
u16 result; /* Fw init result */
|
||||
u8 module_id; /* Module ID in case of error */
|
||||
u8 debug_info; /* Debug info from Module ID in case of fail */
|
||||
} __packed;
|
||||
|
||||
struct snd_sst_tstamp {
|
||||
u64 ring_buffer_counter; /* PB/CP: Bytes copied from/to DDR. */
|
||||
u64 hardware_counter; /* PB/CP: Bytes DMAed to/from SSP. */
|
||||
u64 frames_decoded;
|
||||
u64 bytes_decoded;
|
||||
u64 bytes_copied;
|
||||
u32 sampling_frequency;
|
||||
u32 channel_peak[8];
|
||||
} __packed;
|
||||
|
||||
/* Stream type params struture for Alloc stream */
|
||||
struct snd_sst_str_type {
|
||||
u8 codec_type; /* Codec type */
|
||||
u8 str_type; /* 1 = voice 2 = music */
|
||||
u8 operation; /* Playback or Capture */
|
||||
u8 protected_str; /* 0=Non DRM, 1=DRM */
|
||||
u8 time_slots;
|
||||
u8 reserved; /* Reserved */
|
||||
u16 result; /* Result used for acknowledgment */
|
||||
} __packed;
|
||||
|
||||
/* Library info structure */
|
||||
struct module_info {
|
||||
u32 lib_version;
|
||||
u32 lib_type;/*TBD- KLOCKWORK u8 lib_type;*/
|
||||
u32 media_type;
|
||||
u8 lib_name[12];
|
||||
u32 lib_caps;
|
||||
unsigned char b_date[16]; /* Lib build date */
|
||||
unsigned char b_time[16]; /* Lib build time */
|
||||
} __packed;
|
||||
|
||||
/* Library slot info */
|
||||
struct lib_slot_info {
|
||||
u8 slot_num; /* 1 or 2 */
|
||||
u8 reserved1;
|
||||
u16 reserved2;
|
||||
u32 iram_size; /* slot size in IRAM */
|
||||
u32 dram_size; /* slot size in DRAM */
|
||||
u32 iram_offset; /* starting offset of slot in IRAM */
|
||||
u32 dram_offset; /* starting offset of slot in DRAM */
|
||||
} __packed;
|
||||
|
||||
struct snd_ppp_mixer_params {
|
||||
__u32 type; /*Type of the parameter */
|
||||
__u32 size;
|
||||
__u32 input_stream_bitmap; /*Input stream Bit Map*/
|
||||
} __packed;
|
||||
|
||||
struct snd_sst_lib_download {
|
||||
struct module_info lib_info; /* library info type, capabilities etc */
|
||||
struct lib_slot_info slot_info; /* slot info to be downloaded */
|
||||
u32 mod_entry_pt;
|
||||
};
|
||||
|
||||
struct snd_sst_lib_download_info {
|
||||
struct snd_sst_lib_download dload_lib;
|
||||
u16 result; /* Result used for acknowledgment */
|
||||
u8 pvt_id; /* Private ID */
|
||||
u8 reserved; /* for alignment */
|
||||
};
|
||||
struct snd_pcm_params {
|
||||
u8 num_chan; /* 1=Mono, 2=Stereo */
|
||||
u8 pcm_wd_sz; /* 16/24 - bit*/
|
||||
u32 reserved; /* Bitrate in bits per second */
|
||||
u32 sfreq; /* Sampling rate in Hz */
|
||||
u8 use_offload_path;
|
||||
u8 use_offload_path; /* 0-PCM using period elpased & ALSA interfaces
|
||||
1-PCM stream via compressed interface */
|
||||
u8 reserved2;
|
||||
u16 reserved3;
|
||||
u32 sfreq; /* Sampling rate in Hz */
|
||||
u8 channel_map[8];
|
||||
} __packed;
|
||||
|
||||
|
@ -76,6 +355,7 @@ struct snd_aac_params {
|
|||
struct snd_wma_params {
|
||||
u8 num_chan; /* 1=Mono, 2=Stereo */
|
||||
u8 pcm_wd_sz; /* 16/24 - bit*/
|
||||
u16 reserved1;
|
||||
u32 brate; /* Use the hard coded value. */
|
||||
u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */
|
||||
u32 channel_mask; /* Channel Mask */
|
||||
|
@ -101,26 +381,153 @@ struct sst_address_info {
|
|||
};
|
||||
|
||||
struct snd_sst_alloc_params_ext {
|
||||
struct sst_address_info ring_buf_info[8];
|
||||
u8 sg_count;
|
||||
u8 reserved;
|
||||
u16 reserved2;
|
||||
u32 frag_size; /*Number of samples after which period elapsed
|
||||
__u16 sg_count;
|
||||
__u16 reserved;
|
||||
__u32 frag_size; /*Number of samples after which period elapsed
|
||||
message is sent valid only if path = 0*/
|
||||
} __packed;
|
||||
struct sst_address_info ring_buf_info[8];
|
||||
};
|
||||
|
||||
struct snd_sst_stream_params {
|
||||
union snd_sst_codec_params uc;
|
||||
} __packed;
|
||||
|
||||
struct snd_sst_params {
|
||||
u32 result;
|
||||
u32 stream_id;
|
||||
u8 codec;
|
||||
u8 ops;
|
||||
u8 stream_type;
|
||||
u8 device_type;
|
||||
u8 task;
|
||||
struct snd_sst_stream_params sparams;
|
||||
struct snd_sst_alloc_params_ext aparams;
|
||||
};
|
||||
|
||||
struct snd_sst_alloc_mrfld {
|
||||
u16 codec_type;
|
||||
u8 operation;
|
||||
u8 sg_count;
|
||||
struct sst_address_info ring_buf_info[8];
|
||||
u32 frag_size;
|
||||
u32 ts;
|
||||
struct snd_sst_stream_params codec_params;
|
||||
} __packed;
|
||||
|
||||
/* Alloc stream params structure */
|
||||
struct snd_sst_alloc_params {
|
||||
struct snd_sst_str_type str_type;
|
||||
struct snd_sst_stream_params stream_params;
|
||||
struct snd_sst_alloc_params_ext alloc_params;
|
||||
} __packed;
|
||||
|
||||
/* Alloc stream response message */
|
||||
struct snd_sst_alloc_response {
|
||||
struct snd_sst_str_type str_type; /* Stream type for allocation */
|
||||
struct snd_sst_lib_download lib_dnld; /* Valid only for codec dnld */
|
||||
};
|
||||
|
||||
/* Drop response */
|
||||
struct snd_sst_drop_response {
|
||||
u32 result;
|
||||
u32 bytes;
|
||||
};
|
||||
|
||||
struct snd_sst_async_msg {
|
||||
u32 msg_id; /* Async msg id */
|
||||
u32 payload[0];
|
||||
};
|
||||
|
||||
struct snd_sst_async_err_msg {
|
||||
u32 fw_resp; /* Firmware Result */
|
||||
u32 lib_resp; /*Library result */
|
||||
} __packed;
|
||||
|
||||
struct snd_sst_vol {
|
||||
u32 stream_id;
|
||||
s32 volume;
|
||||
u32 ramp_duration;
|
||||
u32 ramp_type; /* Ramp type, default=0 */
|
||||
};
|
||||
|
||||
/* Gain library parameters for mrfld
|
||||
* based on DSP command spec v0.82
|
||||
*/
|
||||
struct snd_sst_gain_v2 {
|
||||
u16 gain_cell_num; /* num of gain cells to modify*/
|
||||
u8 cell_nbr_idx; /* instance index*/
|
||||
u8 cell_path_idx; /* pipe-id */
|
||||
u16 module_id; /*module id */
|
||||
u16 left_cell_gain; /* left gain value in dB*/
|
||||
u16 right_cell_gain; /* right gain value in dB*/
|
||||
u16 gain_time_const; /* gain time constant*/
|
||||
} __packed;
|
||||
|
||||
struct snd_sst_mute {
|
||||
u32 stream_id;
|
||||
u32 mute;
|
||||
};
|
||||
|
||||
struct snd_sst_runtime_params {
|
||||
u8 type;
|
||||
u8 str_id;
|
||||
u8 size;
|
||||
u8 rsvd;
|
||||
void *addr;
|
||||
} __packed;
|
||||
|
||||
enum stream_param_type {
|
||||
SST_SET_TIME_SLOT = 0,
|
||||
SST_SET_CHANNEL_INFO = 1,
|
||||
OTHERS = 2, /*reserved for future params*/
|
||||
};
|
||||
|
||||
/* CSV Voice call routing structure */
|
||||
struct snd_sst_control_routing {
|
||||
u8 control; /* 0=start, 1=Stop */
|
||||
u8 reserved[3]; /* Reserved- for 32 bit alignment */
|
||||
};
|
||||
|
||||
struct ipc_post {
|
||||
struct list_head node;
|
||||
union ipc_header header; /* driver specific */
|
||||
bool is_large;
|
||||
bool is_process_reply;
|
||||
union ipc_header_mrfld mrfld_header;
|
||||
char *mailbox_data;
|
||||
};
|
||||
|
||||
struct snd_sst_ctxt_params {
|
||||
u32 address; /* Physical Address in DDR where the context is stored */
|
||||
u32 size; /* size of the context */
|
||||
};
|
||||
|
||||
struct snd_sst_lpe_log_params {
|
||||
u8 dbg_type;
|
||||
u8 module_id;
|
||||
u8 log_level;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
enum snd_sst_bytes_type {
|
||||
SND_SST_BYTES_SET = 0x1,
|
||||
SND_SST_BYTES_GET = 0x2,
|
||||
};
|
||||
|
||||
struct snd_sst_bytes_v2 {
|
||||
u8 type;
|
||||
u8 ipc_msg;
|
||||
u8 block;
|
||||
u8 task_id;
|
||||
u8 pipe_id;
|
||||
u8 rsvd;
|
||||
u16 len;
|
||||
char bytes[0];
|
||||
};
|
||||
|
||||
#define MAX_VTSV_FILES 2
|
||||
struct snd_sst_vtsv_info {
|
||||
struct sst_address_info vfiles[MAX_VTSV_FILES];
|
||||
} __packed;
|
||||
|
||||
#endif /* __SST_MFLD_DSP_H__ */
|
||||
|
|
|
@ -100,14 +100,19 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
|
|||
int retval;
|
||||
struct snd_sst_params str_params;
|
||||
struct sst_compress_cb cb;
|
||||
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
|
||||
struct snd_soc_platform *platform = rtd->platform;
|
||||
struct sst_data *ctx = snd_soc_platform_get_drvdata(platform);
|
||||
|
||||
stream = cstream->runtime->private_data;
|
||||
/* construct fw structure for this*/
|
||||
memset(&str_params, 0, sizeof(str_params));
|
||||
|
||||
str_params.ops = STREAM_OPS_PLAYBACK;
|
||||
str_params.stream_type = SST_STREAM_TYPE_MUSIC;
|
||||
str_params.device_type = SND_SST_DEVICE_COMPRESS;
|
||||
/* fill the device type and stream id to pass to SST driver */
|
||||
retval = sst_fill_stream_params(cstream, ctx, &str_params, true);
|
||||
pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
switch (params->codec.id) {
|
||||
case SND_AUDIOCODEC_MP3: {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* sst_mfld_platform.c - Intel MID Platform driver
|
||||
*
|
||||
* Copyright (C) 2010-2013 Intel Corp
|
||||
* Copyright (C) 2010-2014 Intel Corp
|
||||
* Author: Vinod Koul <vinod.koul@intel.com>
|
||||
* Author: Harsha Priya <priya.harsha@intel.com>
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -27,7 +27,9 @@
|
|||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/compress_driver.h>
|
||||
#include <asm/platform_sst_audio.h>
|
||||
#include "sst-mfld-platform.h"
|
||||
#include "sst-atom-controls.h"
|
||||
|
||||
struct sst_device *sst;
|
||||
static DEFINE_MUTEX(sst_lock);
|
||||
|
@ -92,6 +94,13 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = {
|
|||
.fifo_size = SST_FIFO_SIZE,
|
||||
};
|
||||
|
||||
static struct sst_dev_stream_map dpcm_strm_map[] = {
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Reserved, not in use */
|
||||
{MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0},
|
||||
{MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0},
|
||||
{MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0},
|
||||
};
|
||||
|
||||
/* MFLD - MSIC */
|
||||
static struct snd_soc_dai_driver sst_platform_dai[] = {
|
||||
{
|
||||
|
@ -143,58 +152,142 @@ static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
|
|||
return state;
|
||||
}
|
||||
|
||||
static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
|
||||
struct sst_pcm_params *param)
|
||||
static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
|
||||
struct snd_sst_alloc_params_ext *alloc_param)
|
||||
{
|
||||
unsigned int channels;
|
||||
snd_pcm_uframes_t period_size;
|
||||
ssize_t periodbytes;
|
||||
ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
|
||||
u32 buffer_addr = virt_to_phys(substream->dma_buffer.area);
|
||||
|
||||
channels = substream->runtime->channels;
|
||||
period_size = substream->runtime->period_size;
|
||||
periodbytes = samples_to_bytes(substream->runtime, period_size);
|
||||
alloc_param->ring_buf_info[0].addr = buffer_addr;
|
||||
alloc_param->ring_buf_info[0].size = buffer_bytes;
|
||||
alloc_param->sg_count = 1;
|
||||
alloc_param->reserved = 0;
|
||||
alloc_param->frag_size = periodbytes * channels;
|
||||
|
||||
}
|
||||
static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
|
||||
struct snd_sst_stream_params *param)
|
||||
{
|
||||
param->uc.pcm_params.num_chan = (u8) substream->runtime->channels;
|
||||
param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
|
||||
param->uc.pcm_params.sfreq = substream->runtime->rate;
|
||||
|
||||
/* PCM stream via ALSA interface */
|
||||
param->uc.pcm_params.use_offload_path = 0;
|
||||
param->uc.pcm_params.reserved2 = 0;
|
||||
memset(param->uc.pcm_params.channel_map, 0, sizeof(u8));
|
||||
|
||||
param->num_chan = (u8) substream->runtime->channels;
|
||||
param->pcm_wd_sz = substream->runtime->sample_bits;
|
||||
param->reserved = 0;
|
||||
param->sfreq = substream->runtime->rate;
|
||||
param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream);
|
||||
param->period_count = substream->runtime->period_size;
|
||||
param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area);
|
||||
pr_debug("period_cnt = %d\n", param->period_count);
|
||||
pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz);
|
||||
}
|
||||
|
||||
static int sst_platform_alloc_stream(struct snd_pcm_substream *substream)
|
||||
static int sst_get_stream_mapping(int dev, int sdev, int dir,
|
||||
struct sst_dev_stream_map *map, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (map == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
/* index 0 is not used in stream map */
|
||||
for (i = 1; i < size; i++) {
|
||||
if ((map[i].dev_num == dev) && (map[i].direction == dir))
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sst_fill_stream_params(void *substream,
|
||||
const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress)
|
||||
{
|
||||
int map_size;
|
||||
int index;
|
||||
struct sst_dev_stream_map *map;
|
||||
struct snd_pcm_substream *pstream = NULL;
|
||||
struct snd_compr_stream *cstream = NULL;
|
||||
|
||||
map = ctx->pdata->pdev_strm_map;
|
||||
map_size = ctx->pdata->strm_map_size;
|
||||
|
||||
if (is_compress == true)
|
||||
cstream = (struct snd_compr_stream *)substream;
|
||||
else
|
||||
pstream = (struct snd_pcm_substream *)substream;
|
||||
|
||||
str_params->stream_type = SST_STREAM_TYPE_MUSIC;
|
||||
|
||||
/* For pcm streams */
|
||||
if (pstream) {
|
||||
index = sst_get_stream_mapping(pstream->pcm->device,
|
||||
pstream->number, pstream->stream,
|
||||
map, map_size);
|
||||
if (index <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
str_params->stream_id = index;
|
||||
str_params->device_type = map[index].device_id;
|
||||
str_params->task = map[index].task_id;
|
||||
|
||||
str_params->ops = (u8)pstream->stream;
|
||||
}
|
||||
|
||||
if (cstream) {
|
||||
index = sst_get_stream_mapping(cstream->device->device,
|
||||
0, cstream->direction,
|
||||
map, map_size);
|
||||
if (index <= 0)
|
||||
return -EINVAL;
|
||||
str_params->stream_id = index;
|
||||
str_params->device_type = map[index].device_id;
|
||||
str_params->task = map[index].task_id;
|
||||
|
||||
str_params->ops = (u8)cstream->direction;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sst_platform_alloc_stream(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_platform *platform)
|
||||
{
|
||||
struct sst_runtime_stream *stream =
|
||||
substream->runtime->private_data;
|
||||
struct sst_pcm_params param = {0};
|
||||
struct sst_stream_params str_params = {0};
|
||||
int ret_val;
|
||||
struct snd_sst_stream_params param = {{{0,},},};
|
||||
struct snd_sst_params str_params = {0};
|
||||
struct snd_sst_alloc_params_ext alloc_params = {0};
|
||||
int ret_val = 0;
|
||||
struct sst_data *ctx = snd_soc_platform_get_drvdata(platform);
|
||||
|
||||
/* set codec params and inform SST driver the same */
|
||||
sst_fill_pcm_params(substream, ¶m);
|
||||
sst_fill_alloc_params(substream, &alloc_params);
|
||||
substream->runtime->dma_area = substream->dma_buffer.area;
|
||||
str_params.sparams = param;
|
||||
str_params.codec = param.codec;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
str_params.ops = STREAM_OPS_PLAYBACK;
|
||||
str_params.device_type = substream->pcm->device + 1;
|
||||
pr_debug("Playbck stream,Device %d\n",
|
||||
substream->pcm->device);
|
||||
} else {
|
||||
str_params.ops = STREAM_OPS_CAPTURE;
|
||||
str_params.device_type = SND_SST_DEVICE_CAPTURE;
|
||||
pr_debug("Capture stream,Device %d\n",
|
||||
substream->pcm->device);
|
||||
}
|
||||
ret_val = stream->ops->open(&str_params);
|
||||
pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val);
|
||||
str_params.aparams = alloc_params;
|
||||
str_params.codec = SST_CODEC_TYPE_PCM;
|
||||
|
||||
/* fill the device type and stream id to pass to SST driver */
|
||||
ret_val = sst_fill_stream_params(substream, ctx, &str_params, false);
|
||||
if (ret_val < 0)
|
||||
return ret_val;
|
||||
|
||||
stream->stream_info.str_id = ret_val;
|
||||
pr_debug("str id : %d\n", stream->stream_info.str_id);
|
||||
stream->stream_info.str_id = str_params.stream_id;
|
||||
|
||||
ret_val = stream->ops->open(&str_params);
|
||||
if (ret_val <= 0)
|
||||
return ret_val;
|
||||
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static void sst_period_elapsed(void *mad_substream)
|
||||
static void sst_period_elapsed(void *arg)
|
||||
{
|
||||
struct snd_pcm_substream *substream = mad_substream;
|
||||
struct snd_pcm_substream *substream = arg;
|
||||
struct sst_runtime_stream *stream;
|
||||
int status;
|
||||
|
||||
|
@ -218,7 +311,7 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream)
|
|||
pr_debug("setting buffer ptr param\n");
|
||||
sst_set_stream_status(stream, SST_PLATFORM_INIT);
|
||||
stream->stream_info.period_elapsed = sst_period_elapsed;
|
||||
stream->stream_info.mad_substream = substream;
|
||||
stream->stream_info.arg = substream;
|
||||
stream->stream_info.buffer_ptr = 0;
|
||||
stream->stream_info.sfreq = substream->runtime->rate;
|
||||
ret_val = stream->ops->device_control(
|
||||
|
@ -230,19 +323,12 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream)
|
|||
}
|
||||
/* end -- helper functions */
|
||||
|
||||
static int sst_platform_open(struct snd_pcm_substream *substream)
|
||||
static int sst_media_open(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int ret_val = 0;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct sst_runtime_stream *stream;
|
||||
int ret_val;
|
||||
|
||||
pr_debug("sst_platform_open called\n");
|
||||
|
||||
snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw);
|
||||
ret_val = snd_pcm_hw_constraint_integer(runtime,
|
||||
SNDRV_PCM_HW_PARAM_PERIODS);
|
||||
if (ret_val < 0)
|
||||
return ret_val;
|
||||
|
||||
stream = kzalloc(sizeof(*stream), GFP_KERNEL);
|
||||
if (!stream)
|
||||
|
@ -251,50 +337,69 @@ static int sst_platform_open(struct snd_pcm_substream *substream)
|
|||
|
||||
/* get the sst ops */
|
||||
mutex_lock(&sst_lock);
|
||||
if (!sst) {
|
||||
if (!sst ||
|
||||
!try_module_get(sst->dev->driver->owner)) {
|
||||
pr_err("no device available to run\n");
|
||||
mutex_unlock(&sst_lock);
|
||||
kfree(stream);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!try_module_get(sst->dev->driver->owner)) {
|
||||
mutex_unlock(&sst_lock);
|
||||
kfree(stream);
|
||||
return -ENODEV;
|
||||
ret_val = -ENODEV;
|
||||
goto out_ops;
|
||||
}
|
||||
stream->ops = sst->ops;
|
||||
mutex_unlock(&sst_lock);
|
||||
|
||||
stream->stream_info.str_id = 0;
|
||||
sst_set_stream_status(stream, SST_PLATFORM_INIT);
|
||||
stream->stream_info.mad_substream = substream;
|
||||
|
||||
stream->stream_info.arg = substream;
|
||||
/* allocate memory for SST API set */
|
||||
runtime->private_data = stream;
|
||||
|
||||
return 0;
|
||||
/* Make sure, that the period size is always even */
|
||||
snd_pcm_hw_constraint_step(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_PERIODS, 2);
|
||||
|
||||
return snd_pcm_hw_constraint_integer(runtime,
|
||||
SNDRV_PCM_HW_PARAM_PERIODS);
|
||||
out_ops:
|
||||
kfree(stream);
|
||||
mutex_unlock(&sst_lock);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int sst_platform_close(struct snd_pcm_substream *substream)
|
||||
static void sst_media_close(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct sst_runtime_stream *stream;
|
||||
int ret_val = 0, str_id;
|
||||
|
||||
pr_debug("sst_platform_close called\n");
|
||||
stream = substream->runtime->private_data;
|
||||
str_id = stream->stream_info.str_id;
|
||||
if (str_id)
|
||||
ret_val = stream->ops->close(str_id);
|
||||
module_put(sst->dev->driver->owner);
|
||||
kfree(stream);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
static inline unsigned int get_current_pipe_id(struct snd_soc_platform *platform,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct sst_data *sst = snd_soc_platform_get_drvdata(platform);
|
||||
struct sst_dev_stream_map *map = sst->pdata->pdev_strm_map;
|
||||
struct sst_runtime_stream *stream =
|
||||
substream->runtime->private_data;
|
||||
u32 str_id = stream->stream_info.str_id;
|
||||
unsigned int pipe_id;
|
||||
pipe_id = map[str_id].device_id;
|
||||
|
||||
pr_debug("%s: got pipe_id = %#x for str_id = %d\n",
|
||||
__func__, pipe_id, str_id);
|
||||
return pipe_id;
|
||||
}
|
||||
|
||||
static int sst_media_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct sst_runtime_stream *stream;
|
||||
int ret_val = 0, str_id;
|
||||
|
||||
pr_debug("sst_platform_pcm_prepare called\n");
|
||||
stream = substream->runtime->private_data;
|
||||
str_id = stream->stream_info.str_id;
|
||||
if (stream->stream_info.str_id) {
|
||||
|
@ -303,8 +408,8 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
|
|||
return ret_val;
|
||||
}
|
||||
|
||||
ret_val = sst_platform_alloc_stream(substream);
|
||||
if (ret_val < 0)
|
||||
ret_val = sst_platform_alloc_stream(substream, dai->platform);
|
||||
if (ret_val <= 0)
|
||||
return ret_val;
|
||||
snprintf(substream->pcm->id, sizeof(substream->pcm->id),
|
||||
"%d", stream->stream_info.str_id);
|
||||
|
@ -316,6 +421,41 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
|
|||
return ret_val;
|
||||
}
|
||||
|
||||
static int sst_media_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
|
||||
memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sst_media_hw_free(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
return snd_pcm_lib_free_pages(substream);
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_ops sst_media_dai_ops = {
|
||||
.startup = sst_media_open,
|
||||
.shutdown = sst_media_close,
|
||||
.prepare = sst_media_prepare,
|
||||
.hw_params = sst_media_hw_params,
|
||||
.hw_free = sst_media_hw_free,
|
||||
};
|
||||
|
||||
static int sst_platform_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime;
|
||||
|
||||
if (substream->pcm->internal)
|
||||
return 0;
|
||||
|
||||
runtime = substream->runtime;
|
||||
runtime->hw = sst_platform_pcm_hw;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
|
||||
int cmd)
|
||||
{
|
||||
|
@ -331,7 +471,7 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
|
|||
pr_debug("sst: Trigger Start\n");
|
||||
str_cmd = SST_SND_START;
|
||||
status = SST_PLATFORM_RUNNING;
|
||||
stream->stream_info.mad_substream = substream;
|
||||
stream->stream_info.arg = substream;
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
pr_debug("sst: in stop\n");
|
||||
|
@ -377,32 +517,15 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer
|
|||
pr_err("sst: error code = %d\n", ret_val);
|
||||
return ret_val;
|
||||
}
|
||||
return stream->stream_info.buffer_ptr;
|
||||
}
|
||||
|
||||
static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
|
||||
memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
return snd_pcm_lib_free_pages(substream);
|
||||
substream->runtime->delay = str_info->pcm_delay;
|
||||
return str_info->buffer_ptr;
|
||||
}
|
||||
|
||||
static struct snd_pcm_ops sst_platform_ops = {
|
||||
.open = sst_platform_open,
|
||||
.close = sst_platform_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.prepare = sst_platform_pcm_prepare,
|
||||
.trigger = sst_platform_pcm_trigger,
|
||||
.pointer = sst_platform_pcm_pointer,
|
||||
.hw_params = sst_platform_pcm_hw_params,
|
||||
.hw_free = sst_platform_pcm_hw_free,
|
||||
};
|
||||
|
||||
static void sst_pcm_free(struct snd_pcm *pcm)
|
||||
|
@ -413,15 +536,15 @@ static void sst_pcm_free(struct snd_pcm *pcm)
|
|||
|
||||
static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_dai *dai = rtd->cpu_dai;
|
||||
struct snd_pcm *pcm = rtd->pcm;
|
||||
int retval = 0;
|
||||
|
||||
pr_debug("sst_pcm_new called\n");
|
||||
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream ||
|
||||
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
|
||||
if (dai->driver->playback.channels_min ||
|
||||
dai->driver->capture.channels_min) {
|
||||
retval = snd_pcm_lib_preallocate_pages_for_all(pcm,
|
||||
SNDRV_DMA_TYPE_CONTINUOUS,
|
||||
snd_dma_continuous_data(GFP_KERNEL),
|
||||
snd_dma_continuous_data(GFP_DMA),
|
||||
SST_MIN_BUFFER, SST_MAX_BUFFER);
|
||||
if (retval) {
|
||||
pr_err("dma buffer allocationf fail\n");
|
||||
|
@ -445,10 +568,28 @@ static const struct snd_soc_component_driver sst_component = {
|
|||
|
||||
static int sst_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sst_data *drv;
|
||||
int ret;
|
||||
struct sst_platform_data *pdata;
|
||||
|
||||
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
|
||||
if (drv == NULL) {
|
||||
pr_err("kzalloc failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (pdata == NULL) {
|
||||
pr_err("kzalloc failed for pdata\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pdata->pdev_strm_map = dpcm_strm_map;
|
||||
pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map);
|
||||
drv->pdata = pdata;
|
||||
mutex_init(&drv->lock);
|
||||
dev_set_drvdata(&pdev->dev, drv);
|
||||
|
||||
pr_debug("sst_platform_probe called\n");
|
||||
sst = NULL;
|
||||
ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
|
||||
if (ret) {
|
||||
pr_err("registering soc platform failed\n");
|
||||
|
|
|
@ -39,9 +39,10 @@ extern struct sst_device *sst;
|
|||
|
||||
struct pcm_stream_info {
|
||||
int str_id;
|
||||
void *mad_substream;
|
||||
void (*period_elapsed) (void *mad_substream);
|
||||
void *arg;
|
||||
void (*period_elapsed) (void *arg);
|
||||
unsigned long long buffer_ptr;
|
||||
unsigned long long pcm_delay;
|
||||
int sfreq;
|
||||
};
|
||||
|
||||
|
@ -62,7 +63,9 @@ enum sst_controls {
|
|||
SST_SND_BUFFER_POINTER = 0x05,
|
||||
SST_SND_STREAM_INIT = 0x06,
|
||||
SST_SND_START = 0x07,
|
||||
SST_MAX_CONTROLS = 0x07,
|
||||
SST_SET_BYTE_STREAM = 0x100A,
|
||||
SST_GET_BYTE_STREAM = 0x100B,
|
||||
SST_MAX_CONTROLS = SST_GET_BYTE_STREAM,
|
||||
};
|
||||
|
||||
enum sst_stream_ops {
|
||||
|
@ -124,8 +127,9 @@ struct compress_sst_ops {
|
|||
};
|
||||
|
||||
struct sst_ops {
|
||||
int (*open) (struct sst_stream_params *str_param);
|
||||
int (*open) (struct snd_sst_params *str_param);
|
||||
int (*device_control) (int cmd, void *arg);
|
||||
int (*set_generic_params)(enum sst_controls cmd, void *arg);
|
||||
int (*close) (unsigned int str_id);
|
||||
};
|
||||
|
||||
|
@ -143,10 +147,27 @@ struct sst_device {
|
|||
char *name;
|
||||
struct device *dev;
|
||||
struct sst_ops *ops;
|
||||
struct platform_device *pdev;
|
||||
struct compress_sst_ops *compr_ops;
|
||||
};
|
||||
|
||||
struct sst_data;
|
||||
void sst_set_stream_status(struct sst_runtime_stream *stream, int state);
|
||||
int sst_fill_stream_params(void *substream, const struct sst_data *ctx,
|
||||
struct snd_sst_params *str_params, bool is_compress);
|
||||
|
||||
struct sst_algo_int_control_v2 {
|
||||
struct soc_mixer_control mc;
|
||||
u16 module_id; /* module identifieer */
|
||||
u16 pipe_id; /* location info: pipe_id + instance_id */
|
||||
u16 instance_id;
|
||||
unsigned int value; /* Value received is stored here */
|
||||
};
|
||||
struct sst_data {
|
||||
struct platform_device *pdev;
|
||||
struct sst_platform_data *pdata;
|
||||
struct mutex lock;
|
||||
};
|
||||
int sst_register_dsp(struct sst_device *sst);
|
||||
int sst_unregister_dsp(struct sst_device *sst);
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
config SND_KIRKWOOD_SOC
|
||||
tristate "SoC Audio for the Marvell Kirkwood and Dove chips"
|
||||
depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU || MACH_KIRKWOOD || COMPILE_TEST
|
||||
depends on ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST
|
||||
help
|
||||
Say Y or M if you want to add support for codecs attached to
|
||||
the Kirkwood I2S interface. You will also need to select the
|
||||
|
@ -15,20 +15,3 @@ config SND_KIRKWOOD_SOC_ARMADA370_DB
|
|||
Say Y if you want to add support for SoC audio on
|
||||
the Armada 370 Development Board.
|
||||
|
||||
config SND_KIRKWOOD_SOC_OPENRD
|
||||
tristate "SoC Audio support for Kirkwood Openrd Client"
|
||||
depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST)
|
||||
depends on I2C
|
||||
select SND_SOC_CS42L51
|
||||
help
|
||||
Say Y if you want to add support for SoC audio on
|
||||
Openrd Client.
|
||||
|
||||
config SND_KIRKWOOD_SOC_T5325
|
||||
tristate "SoC Audio support for HP t5325"
|
||||
depends on SND_KIRKWOOD_SOC && (MACH_T5325 || COMPILE_TEST) && I2C
|
||||
select SND_SOC_ALC5623
|
||||
help
|
||||
Say Y if you want to add support for SoC audio on
|
||||
the HP t5325 thin client.
|
||||
|
||||
|
|
|
@ -2,10 +2,6 @@ snd-soc-kirkwood-objs := kirkwood-dma.o kirkwood-i2s.o
|
|||
|
||||
obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o
|
||||
|
||||
snd-soc-openrd-objs := kirkwood-openrd.o
|
||||
snd-soc-t5325-objs := kirkwood-t5325.o
|
||||
snd-soc-armada-370-db-objs := armada-370-db.o
|
||||
|
||||
obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o
|
||||
obj-$(CONFIG_SND_KIRKWOOD_SOC_OPENRD) += snd-soc-openrd.o
|
||||
obj-$(CONFIG_SND_KIRKWOOD_SOC_T5325) += snd-soc-t5325.o
|
||||
|
|
|
@ -28,11 +28,12 @@ static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs)
|
|||
}
|
||||
|
||||
static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
|
||||
.info = (SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_PAUSE),
|
||||
.info = SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_PAUSE |
|
||||
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
|
||||
.buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES,
|
||||
.period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES,
|
||||
.period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES,
|
||||
|
|
|
@ -212,7 +212,8 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
|
|||
KIRKWOOD_PLAYCTL_SIZE_MASK);
|
||||
priv->ctl_play |= ctl_play;
|
||||
} else {
|
||||
priv->ctl_rec &= ~KIRKWOOD_RECCTL_SIZE_MASK;
|
||||
priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK |
|
||||
KIRKWOOD_RECCTL_SIZE_MASK);
|
||||
priv->ctl_rec |= ctl_rec;
|
||||
}
|
||||
|
||||
|
@ -221,14 +222,24 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static unsigned kirkwood_i2s_play_mute(unsigned ctl)
|
||||
{
|
||||
if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN))
|
||||
ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE;
|
||||
if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN))
|
||||
ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE;
|
||||
return ctl;
|
||||
}
|
||||
|
||||
static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
|
||||
int cmd, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||
uint32_t ctl, value;
|
||||
|
||||
ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
|
||||
if (ctl & KIRKWOOD_PLAYCTL_PAUSE) {
|
||||
if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) {
|
||||
unsigned timeout = 5000;
|
||||
/*
|
||||
* The Armada510 spec says that if we enter pause mode, the
|
||||
|
@ -256,14 +267,16 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
|
|||
ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */
|
||||
else
|
||||
ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */
|
||||
|
||||
ctl = kirkwood_i2s_play_mute(ctl);
|
||||
value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
|
||||
writel(value, priv->io + KIRKWOOD_PLAYCTL);
|
||||
|
||||
/* enable interrupts */
|
||||
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
||||
value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
|
||||
writel(value, priv->io + KIRKWOOD_INT_MASK);
|
||||
if (!runtime->no_period_wakeup) {
|
||||
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
||||
value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
|
||||
writel(value, priv->io + KIRKWOOD_INT_MASK);
|
||||
}
|
||||
|
||||
/* enable playback */
|
||||
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
|
||||
|
@ -295,6 +308,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
|
|||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
|
||||
KIRKWOOD_PLAYCTL_SPDIF_MUTE);
|
||||
ctl = kirkwood_i2s_play_mute(ctl);
|
||||
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
|
||||
break;
|
||||
|
||||
|
@ -322,8 +336,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
|
|||
else
|
||||
ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */
|
||||
|
||||
value = ctl & ~(KIRKWOOD_RECCTL_I2S_EN |
|
||||
KIRKWOOD_RECCTL_SPDIF_EN);
|
||||
value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK;
|
||||
writel(value, priv->io + KIRKWOOD_RECCTL);
|
||||
|
||||
/* enable interrupts */
|
||||
|
@ -347,7 +360,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
|
|||
|
||||
/* disable all records */
|
||||
value = readl(priv->io + KIRKWOOD_RECCTL);
|
||||
value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN);
|
||||
value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
|
||||
writel(value, priv->io + KIRKWOOD_RECCTL);
|
||||
break;
|
||||
|
||||
|
@ -411,7 +424,7 @@ static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
|
|||
writel(value, priv->io + KIRKWOOD_PLAYCTL);
|
||||
|
||||
value = readl(priv->io + KIRKWOOD_RECCTL);
|
||||
value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN);
|
||||
value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
|
||||
writel(value, priv->io + KIRKWOOD_RECCTL);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* kirkwood-openrd.c
|
||||
*
|
||||
* (c) 2010 Arnaud Patard <apatard@mandriva.com>
|
||||
* (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/soc.h>
|
||||
#include <linux/platform_data/asoc-kirkwood.h>
|
||||
#include "../codecs/cs42l51.h"
|
||||
|
||||
static int openrd_client_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;
|
||||
unsigned int freq;
|
||||
|
||||
switch (params_rate(params)) {
|
||||
default:
|
||||
case 44100:
|
||||
freq = 11289600;
|
||||
break;
|
||||
case 48000:
|
||||
freq = 12288000;
|
||||
break;
|
||||
case 96000:
|
||||
freq = 24576000;
|
||||
break;
|
||||
}
|
||||
|
||||
return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN);
|
||||
|
||||
}
|
||||
|
||||
static struct snd_soc_ops openrd_client_ops = {
|
||||
.hw_params = openrd_client_hw_params,
|
||||
};
|
||||
|
||||
|
||||
static struct snd_soc_dai_link openrd_client_dai[] = {
|
||||
{
|
||||
.name = "CS42L51",
|
||||
.stream_name = "CS42L51 HiFi",
|
||||
.cpu_dai_name = "i2s",
|
||||
.platform_name = "mvebu-audio",
|
||||
.codec_dai_name = "cs42l51-hifi",
|
||||
.codec_name = "cs42l51-codec.0-004a",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
|
||||
.ops = &openrd_client_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
static struct snd_soc_card openrd_client = {
|
||||
.name = "OpenRD Client",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = openrd_client_dai,
|
||||
.num_links = ARRAY_SIZE(openrd_client_dai),
|
||||
};
|
||||
|
||||
static int openrd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = &openrd_client;
|
||||
int ret;
|
||||
|
||||
card->dev = &pdev->dev;
|
||||
|
||||
ret = snd_soc_register_card(card);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int openrd_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_unregister_card(card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver openrd_driver = {
|
||||
.driver = {
|
||||
.name = "openrd-client-audio",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = openrd_probe,
|
||||
.remove = openrd_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(openrd_driver);
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
|
||||
MODULE_DESCRIPTION("ALSA SoC OpenRD Client");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:openrd-client-audio");
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* kirkwood-t5325.c
|
||||
*
|
||||
* (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/soc.h>
|
||||
#include <linux/platform_data/asoc-kirkwood.h>
|
||||
#include "../codecs/alc5623.h"
|
||||
|
||||
static int t5325_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;
|
||||
unsigned int freq;
|
||||
|
||||
freq = params_rate(params) * 256;
|
||||
|
||||
return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN);
|
||||
|
||||
}
|
||||
|
||||
static struct snd_soc_ops t5325_ops = {
|
||||
.hw_params = t5325_hw_params,
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget t5325_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone Jack", NULL),
|
||||
SND_SOC_DAPM_SPK("Speaker", NULL),
|
||||
SND_SOC_DAPM_MIC("Mic Jack", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route t5325_route[] = {
|
||||
{ "Headphone Jack", NULL, "HPL" },
|
||||
{ "Headphone Jack", NULL, "HPR" },
|
||||
|
||||
{"Speaker", NULL, "SPKOUT"},
|
||||
{"Speaker", NULL, "SPKOUTN"},
|
||||
|
||||
{ "MIC1", NULL, "Mic Jack" },
|
||||
{ "MIC2", NULL, "Mic Jack" },
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_link t5325_dai[] = {
|
||||
{
|
||||
.name = "ALC5621",
|
||||
.stream_name = "ALC5621 HiFi",
|
||||
.cpu_dai_name = "i2s",
|
||||
.platform_name = "mvebu-audio",
|
||||
.codec_dai_name = "alc5621-hifi",
|
||||
.codec_name = "alc562x-codec.0-001a",
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
|
||||
.ops = &t5325_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static struct snd_soc_card t5325 = {
|
||||
.name = "t5325",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = t5325_dai,
|
||||
.num_links = ARRAY_SIZE(t5325_dai),
|
||||
|
||||
.dapm_widgets = t5325_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(t5325_dapm_widgets),
|
||||
.dapm_routes = t5325_route,
|
||||
.num_dapm_routes = ARRAY_SIZE(t5325_route),
|
||||
};
|
||||
|
||||
static int t5325_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = &t5325;
|
||||
int ret;
|
||||
|
||||
card->dev = &pdev->dev;
|
||||
|
||||
ret = snd_soc_register_card(card);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int t5325_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||
|
||||
snd_soc_unregister_card(card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver t5325_driver = {
|
||||
.driver = {
|
||||
.name = "t5325-audio",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = t5325_probe,
|
||||
.remove = t5325_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(t5325_driver);
|
||||
|
||||
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
|
||||
MODULE_DESCRIPTION("ALSA SoC t5325 audio client");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:t5325-audio");
|
|
@ -38,6 +38,9 @@
|
|||
#define KIRKWOOD_RECCTL_SIZE_24 (1<<0)
|
||||
#define KIRKWOOD_RECCTL_SIZE_32 (0<<0)
|
||||
|
||||
#define KIRKWOOD_RECCTL_ENABLE_MASK (KIRKWOOD_RECCTL_SPDIF_EN | \
|
||||
KIRKWOOD_RECCTL_I2S_EN)
|
||||
|
||||
#define KIRKWOOD_REC_BUF_ADDR 0x1004
|
||||
#define KIRKWOOD_REC_BUF_SIZE 0x1008
|
||||
#define KIRKWOOD_REC_BYTE_COUNT 0x100C
|
||||
|
@ -121,9 +124,9 @@
|
|||
|
||||
/* Theses values come from the marvell alsa driver */
|
||||
/* need to find where they come from */
|
||||
#define KIRKWOOD_SND_MIN_PERIODS 8
|
||||
#define KIRKWOOD_SND_MIN_PERIODS 2
|
||||
#define KIRKWOOD_SND_MAX_PERIODS 16
|
||||
#define KIRKWOOD_SND_MIN_PERIOD_BYTES 0x800
|
||||
#define KIRKWOOD_SND_MIN_PERIOD_BYTES 256
|
||||
#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x8000
|
||||
#define KIRKWOOD_SND_MAX_BUFFER_BYTES (KIRKWOOD_SND_MAX_PERIOD_BYTES \
|
||||
* KIRKWOOD_SND_MAX_PERIODS)
|
||||
|
|
Loading…
Reference in a new issue