Commit a6ce3052 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/intel', 'asoc/topic/kirkwood',...

Merge remote-tracking branches 'asoc/topic/intel', 'asoc/topic/kirkwood', 'asoc/topic/max98090' and 'asoc/topic/mc13783' into asoc-next
...@@ -4,7 +4,7 @@ This device supports I2C only. ...@@ -4,7 +4,7 @@ This device supports I2C only.
Required properties: Required properties:
- compatible : "maxim,max98090". - compatible : "maxim,max98090" or "maxim,max98091".
- reg : The I2C address of the device. - reg : The I2C address of the device.
......
/*
* 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
/*
* 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 ...@@ -75,6 +75,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_PCM3008 select SND_SOC_PCM3008
select SND_SOC_PCM512x_I2C if I2C select SND_SOC_PCM512x_I2C if I2C
select SND_SOC_PCM512x_SPI if SPI_MASTER select SND_SOC_PCM512x_SPI if SPI_MASTER
select SND_SOC_RT286 if I2C
select SND_SOC_RT5631 if I2C select SND_SOC_RT5631 if I2C
select SND_SOC_RT5640 if I2C select SND_SOC_RT5640 if I2C
select SND_SOC_RT5645 if I2C select SND_SOC_RT5645 if I2C
...@@ -455,6 +456,9 @@ config SND_SOC_RL6231 ...@@ -455,6 +456,9 @@ config SND_SOC_RL6231
default m if SND_SOC_RT5645=m default m if SND_SOC_RT5645=m
default m if SND_SOC_RT5651=m default m if SND_SOC_RT5651=m
config SND_SOC_RT286
tristate
config SND_SOC_RT5631 config SND_SOC_RT5631
tristate tristate
......
...@@ -69,6 +69,7 @@ snd-soc-pcm512x-objs := pcm512x.o ...@@ -69,6 +69,7 @@ snd-soc-pcm512x-objs := pcm512x.o
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
snd-soc-pcm512x-spi-objs := pcm512x-spi.o snd-soc-pcm512x-spi-objs := pcm512x-spi.o
snd-soc-rl6231-objs := rl6231.o snd-soc-rl6231-objs := rl6231.o
snd-soc-rt286-objs := rt286.o
snd-soc-rt5631-objs := rt5631.o snd-soc-rt5631-objs := rt5631.o
snd-soc-rt5640-objs := rt5640.o snd-soc-rt5640-objs := rt5640.o
snd-soc-rt5645-objs := rt5645.o snd-soc-rt5645-objs := rt5645.o
...@@ -237,6 +238,7 @@ obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.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_I2C) += snd-soc-pcm512x-i2c.o
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.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_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_RT5631) += snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o
......
...@@ -26,10 +26,6 @@ ...@@ -26,10 +26,6 @@
#include <sound/max98090.h> #include <sound/max98090.h>
#include "max98090.h" #include "max98090.h"
#define DEBUG
#define EXTMIC_METHOD
#define EXTMIC_METHOD_TEST
/* Allows for sparsely populated register maps */ /* Allows for sparsely populated register maps */
static struct reg_default max98090_reg[] = { static struct reg_default max98090_reg[] = {
{ 0x00, 0x00 }, /* 00 Software Reset */ { 0x00, 0x00 }, /* 00 Software Reset */
...@@ -820,7 +816,6 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w, ...@@ -820,7 +816,6 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
else else
val = (val & M98090_MIC_PA2EN_MASK) >> M98090_MIC_PA2EN_SHIFT; val = (val & M98090_MIC_PA2EN_MASK) >> M98090_MIC_PA2EN_SHIFT;
if (val >= 1) { if (val >= 1) {
if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) { if (w->reg == M98090_REG_MIC1_INPUT_LEVEL) {
max98090->pa1en = val - 1; /* Update for volatile */ max98090->pa1en = val - 1; /* Update for volatile */
...@@ -1140,7 +1135,6 @@ static const struct snd_kcontrol_new max98090_mixhprsel_mux = ...@@ -1140,7 +1135,6 @@ static const struct snd_kcontrol_new max98090_mixhprsel_mux =
SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum); SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum);
static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("MIC1"), SND_SOC_DAPM_INPUT("MIC1"),
SND_SOC_DAPM_INPUT("MIC2"), SND_SOC_DAPM_INPUT("MIC2"),
SND_SOC_DAPM_INPUT("DMICL"), SND_SOC_DAPM_INPUT("DMICL"),
...@@ -1304,7 +1298,6 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { ...@@ -1304,7 +1298,6 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
}; };
static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = { static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("DMIC3"), SND_SOC_DAPM_INPUT("DMIC3"),
SND_SOC_DAPM_INPUT("DMIC4"), SND_SOC_DAPM_INPUT("DMIC4"),
...@@ -1315,7 +1308,6 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = { ...@@ -1315,7 +1308,6 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
}; };
static const struct snd_soc_dapm_route max98090_dapm_routes[] = { static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
{"MIC1 Input", NULL, "MIC1"}, {"MIC1 Input", NULL, "MIC1"},
{"MIC2 Input", NULL, "MIC2"}, {"MIC2 Input", NULL, "MIC2"},
...@@ -1493,17 +1485,14 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { ...@@ -1493,17 +1485,14 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
{"SPKR", NULL, "SPK Right Out"}, {"SPKR", NULL, "SPK Right Out"},
{"RCVL", NULL, "RCV Left Out"}, {"RCVL", NULL, "RCV Left Out"},
{"RCVR", NULL, "RCV Right Out"}, {"RCVR", NULL, "RCV Right Out"},
}; };
static const struct snd_soc_dapm_route max98091_dapm_routes[] = { static const struct snd_soc_dapm_route max98091_dapm_routes[] = {
/* DMIC inputs */ /* DMIC inputs */
{"DMIC3", NULL, "DMIC3_ENA"}, {"DMIC3", NULL, "DMIC3_ENA"},
{"DMIC4", NULL, "DMIC4_ENA"}, {"DMIC4", NULL, "DMIC4_ENA"},
{"DMIC3", NULL, "AHPF"}, {"DMIC3", NULL, "AHPF"},
{"DMIC4", NULL, "AHPF"}, {"DMIC4", NULL, "AHPF"},
}; };
static int max98090_add_widgets(struct snd_soc_codec *codec) static int max98090_add_widgets(struct snd_soc_codec *codec)
...@@ -1531,7 +1520,6 @@ 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, snd_soc_dapm_add_routes(dapm, max98091_dapm_routes,
ARRAY_SIZE(max98091_dapm_routes)); ARRAY_SIZE(max98091_dapm_routes));
} }
return 0; return 0;
...@@ -2212,22 +2200,11 @@ static struct snd_soc_dai_driver max98090_dai[] = { ...@@ -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) static int max98090_probe(struct snd_soc_codec *codec)
{ {
struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
struct max98090_cdata *cdata; struct max98090_cdata *cdata;
enum max98090_type devtype;
int ret = 0; int ret = 0;
dev_dbg(codec->dev, "max98090_probe\n"); dev_dbg(codec->dev, "max98090_probe\n");
...@@ -2263,16 +2240,21 @@ static int max98090_probe(struct snd_soc_codec *codec) ...@@ -2263,16 +2240,21 @@ static int max98090_probe(struct snd_soc_codec *codec)
} }
if ((ret >= M98090_REVA) && (ret <= M98090_REVA + 0x0f)) { if ((ret >= M98090_REVA) && (ret <= M98090_REVA + 0x0f)) {
max98090->devtype = MAX98090; devtype = MAX98090;
dev_info(codec->dev, "MAX98090 REVID=0x%02x\n", ret); dev_info(codec->dev, "MAX98090 REVID=0x%02x\n", ret);
} else if ((ret >= M98091_REVA) && (ret <= M98091_REVA + 0x0f)) { } else if ((ret >= M98091_REVA) && (ret <= M98091_REVA + 0x0f)) {
max98090->devtype = MAX98091; devtype = MAX98091;
dev_info(codec->dev, "MAX98091 REVID=0x%02x\n", ret); dev_info(codec->dev, "MAX98091 REVID=0x%02x\n", ret);
} else { } else {
max98090->devtype = MAX98090; devtype = MAX98090;
dev_err(codec->dev, "Unrecognized revision 0x%02x\n", ret); 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; max98090->jack_state = M98090_JACK_STATE_NO_HEADSET;
INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work); INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work);
...@@ -2317,8 +2299,6 @@ static int max98090_probe(struct snd_soc_codec *codec) ...@@ -2317,8 +2299,6 @@ static int max98090_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE, snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE,
M98090_MBVSEL_MASK, M98090_MBVSEL_2V8); M98090_MBVSEL_MASK, M98090_MBVSEL_2V8);
max98090_handle_pdata(codec);
max98090_add_widgets(codec); max98090_add_widgets(codec);
err_access: err_access:
...@@ -2428,7 +2408,7 @@ static int max98090_runtime_suspend(struct device *dev) ...@@ -2428,7 +2408,7 @@ static int max98090_runtime_suspend(struct device *dev)
} }
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static int max98090_resume(struct device *dev) static int max98090_resume(struct device *dev)
{ {
struct max98090_priv *max98090 = dev_get_drvdata(dev); struct max98090_priv *max98090 = dev_get_drvdata(dev);
...@@ -2460,12 +2440,14 @@ static const struct dev_pm_ops max98090_pm = { ...@@ -2460,12 +2440,14 @@ static const struct dev_pm_ops max98090_pm = {
static const struct i2c_device_id max98090_i2c_id[] = { static const struct i2c_device_id max98090_i2c_id[] = {
{ "max98090", MAX98090 }, { "max98090", MAX98090 },
{ "max98091", MAX98091 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, max98090_i2c_id); MODULE_DEVICE_TABLE(i2c, max98090_i2c_id);
static const struct of_device_id max98090_of_match[] = { static const struct of_device_id max98090_of_match[] = {
{ .compatible = "maxim,max98090", }, { .compatible = "maxim,max98090", },
{ .compatible = "maxim,max98091", },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, max98090_of_match); MODULE_DEVICE_TABLE(of, max98090_of_match);
......
...@@ -766,11 +766,11 @@ static int __init mc13783_codec_probe(struct platform_device *pdev) ...@@ -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); ret = of_property_read_u32(np, "adc-port", &priv->adc_ssi_port);
if (ret) if (ret)
return ret; goto out;
ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port); ret = of_property_read_u32(np, "dac-port", &priv->dac_ssi_port);
if (ret) if (ret)
return ret; goto out;
} }
dev_set_drvdata(&pdev->dev, priv); dev_set_drvdata(&pdev->dev, priv);
...@@ -783,6 +783,8 @@ static int __init mc13783_codec_probe(struct platform_device *pdev) ...@@ -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, ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783,
mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async)); mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async));
out:
of_node_put(np);
return ret; return ret;
} }
......
This diff is collapsed.
/*
* 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 ...@@ -58,3 +58,15 @@ config SND_SOC_INTEL_BYT_MAX98090_MACH
help help
This adds audio driver for Intel Baytrail platform based boards This adds audio driver for Intel Baytrail platform based boards
with the MAX98090 audio codec. 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 ...@@ -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-haswell-objs := haswell.o
snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o
snd-soc-sst-byt-max98090-mach-objs := byt-max98090.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_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_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_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
/*
* 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(&params->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[] = { ...@@ -63,14 +63,6 @@ static struct snd_soc_jack_pin hs_jack_pins[] = {
.pin = "Headset Mic", .pin = "Headset Mic",
.mask = SND_JACK_MICROPHONE, .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[] = { static struct snd_soc_jack_gpio hs_jack_gpios[] = {
......
...@@ -34,6 +34,7 @@ static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { ...@@ -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[] = { static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
{"Headset Mic", NULL, "MICBIAS1"},
{"IN2P", NULL, "Headset Mic"}, {"IN2P", NULL, "Headset Mic"},
{"IN2N", NULL, "Headset Mic"}, {"IN2N", NULL, "Headset Mic"},
{"DMIC1", NULL, "Internal Mic"}, {"DMIC1", NULL, "Internal Mic"},
......
/*
* 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 { ...@@ -122,6 +122,26 @@ struct sst_byt_tstamp {
u32 channel_peak[8]; u32 channel_peak[8];
} __packed; } __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 */ /* driver internal IPC message structure */
struct ipc_message { struct ipc_message {
struct list_head list; struct list_head list;
...@@ -868,6 +888,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) ...@@ -868,6 +888,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
{ {
struct sst_byt *byt; struct sst_byt *byt;
struct sst_fw *byt_sst_fw; struct sst_fw *byt_sst_fw;
struct sst_byt_fw_init init;
int err; int err;
dev_dbg(dev, "initialising Byt DSP IPC\n"); dev_dbg(dev, "initialising Byt DSP IPC\n");
...@@ -929,6 +950,15 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) ...@@ -929,6 +950,15 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
goto boot_err; 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; pdata->dsp = byt;
byt->fw = byt_sst_fw; byt->fw = byt_sst_fw;
......
...@@ -224,19 +224,23 @@ EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64); ...@@ -224,19 +224,23 @@ EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64);
void sst_dsp_dump(struct sst_dsp *sst) 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); EXPORT_SYMBOL_GPL(sst_dsp_dump);
void sst_dsp_reset(struct sst_dsp *sst) 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); EXPORT_SYMBOL_GPL(sst_dsp_reset);
int sst_dsp_boot(struct sst_dsp *sst) int sst_dsp_boot(struct sst_dsp *sst)
{ {
sst->ops->boot(sst); if (sst->ops->boot)
sst->ops->boot(sst);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(sst_dsp_boot); EXPORT_SYMBOL_GPL(sst_dsp_boot);
......
...@@ -52,7 +52,11 @@ ...@@ -52,7 +52,11 @@
#define SST_CLKCTL 0x78 #define SST_CLKCTL 0x78
#define SST_CSR2 0x80 #define SST_CSR2 0x80
#define SST_LTRC 0xE0 #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_DBGO 0xF0
#define SST_SHIM_SIZE 0x100 #define SST_SHIM_SIZE 0x100
...@@ -73,6 +77,8 @@ ...@@ -73,6 +77,8 @@
#define SST_CSR_S0IOCS (0x1 << 21) #define SST_CSR_S0IOCS (0x1 << 21)
#define SST_CSR_S1IOCS (0x1 << 23) #define SST_CSR_S1IOCS (0x1 << 23)
#define SST_CSR_LPCS (0x1 << 31) #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_RST (0x1 << 0)
#define SST_BYT_CSR_VECTOR_SEL (0x1 << 1) #define SST_BYT_CSR_VECTOR_SEL (0x1 << 1)
#define SST_BYT_CSR_STALL (0x1 << 2) #define SST_BYT_CSR_STALL (0x1 << 2)
...@@ -92,6 +98,14 @@ ...@@ -92,6 +98,14 @@
#define SST_IMRX_DONE (0x1 << 0) #define SST_IMRX_DONE (0x1 << 0)
#define SST_BYT_IMRX_REQUEST (0x1 << 1) #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 */ /* IPCX / IPCC */
#define SST_IPCX_DONE (0x1 << 30) #define SST_IPCX_DONE (0x1 << 30)
#define SST_IPCX_BUSY (0x1 << 31) #define SST_IPCX_BUSY (0x1 << 31)
...@@ -118,9 +132,21 @@ ...@@ -118,9 +132,21 @@
/* LTRC */ /* LTRC */
#define SST_LTRC_VAL(x) (x << 0) #define SST_LTRC_VAL(x) (x << 0)
/* HDMC */ /* HMDC */
#define SST_HDMC_HDDA0(x) (x << 0) #define SST_HMDC_HDDA0(x) (x << 0)
#define SST_HDMC_HDDA1(x) (x << 7) #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 */ /* SST Vendor Defined Registers and bits */
...@@ -130,11 +156,16 @@ ...@@ -130,11 +156,16 @@
#define SST_VDRTCTL3 0xaC #define SST_VDRTCTL3 0xaC
/* VDRTCTL0 */ /* VDRTCTL0 */
#define SST_VDRTCL0_APLLSE_MASK 1
#define SST_VDRTCL0_DSRAMPGE_SHIFT 16 #define SST_VDRTCL0_DSRAMPGE_SHIFT 16
#define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT) #define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT)
#define SST_VDRTCL0_ISRAMPGE_SHIFT 6 #define SST_VDRTCL0_ISRAMPGE_SHIFT 6
#define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT) #define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT)
/* PMCS */
#define SST_PMCS 0x84
#define SST_PMCS_PS_MASK 0x3
struct sst_dsp; struct sst_dsp;
/* /*
......
...@@ -28,9 +28,6 @@ ...@@ -28,9 +28,6 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#include "sst-dsp.h" #include "sst-dsp.h"
#include "sst-dsp-priv.h" #include "sst-dsp-priv.h"
#include "sst-haswell-ipc.h" #include "sst-haswell-ipc.h"
...@@ -272,9 +269,9 @@ static void hsw_boot(struct sst_dsp *sst) ...@@ -272,9 +269,9 @@ static void hsw_boot(struct sst_dsp *sst)
SST_CSR2_SDFD_SSP1); SST_CSR2_SDFD_SSP1);
/* enable DMA engine 0,1 all channels to access host memory */ /* enable DMA engine 0,1 all channels to access host memory */
sst_dsp_shim_update_bits_unlocked(sst, SST_HDMC, sst_dsp_shim_update_bits_unlocked(sst, SST_HMDC,
SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff), SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff),
SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff)); SST_HMDC_HDDA1(0xff) | SST_HMDC_HDDA0(0xff));
/* disable all clock gating */ /* disable all clock gating */
writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2); writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2);
...@@ -313,9 +310,7 @@ static const struct sst_adsp_memregion lp_region[] = { ...@@ -313,9 +310,7 @@ static const struct sst_adsp_memregion lp_region[] = {
/* wild cat point ADSP mem regions */ /* wild cat point ADSP mem regions */
static const struct sst_adsp_memregion wpt_region[] = { static const struct sst_adsp_memregion wpt_region[] = {
{0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ {0x00000, 0xA0000, 20, SST_MEM_DRAM}, /* D-SRAM0,D-SRAM1,D-SRAM2 - 20 * 32kB */
{0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */
{0x80000, 0xA0000, 4, SST_MEM_DRAM}, /* D-SRAM2 - 4 * 32kB */
{0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 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) ...@@ -339,21 +334,40 @@ static int hsw_acpi_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata)
return 0; 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) 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) { for (index = 0; index < ARRAY_SIZE(sram_shift); index++) {
case SST_MEM_DRAM: if (sram_shift[index].dev_id == sst->id)
shift = 16; break;
break;
case SST_MEM_IRAM:
shift = 6;
break;
default:
return 0;
} }
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); bit = 1 << (block->index + shift);
return bit; return bit;
...@@ -501,8 +515,9 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) ...@@ -501,8 +515,9 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata)
} }
} }
/* set default power gating mask */ /* set default power gating control, enable power gating control for all blocks. that is,
writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL0); can't be accessed, please enable each block before accessing. */
writel(0xffffffff, sst->addr.pci_cfg + SST_VDRTCTL0);
return 0; return 0;
} }
......
...@@ -183,7 +183,7 @@ struct sst_hsw_ipc_fw_ready { ...@@ -183,7 +183,7 @@ struct sst_hsw_ipc_fw_ready {
u32 inbox_size; u32 inbox_size;
u32 outbox_size; u32 outbox_size;
u32 fw_info_size; u32 fw_info_size;
u8 fw_info[1]; u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)];
} __attribute__((packed)); } __attribute__((packed));
struct ipc_message { struct ipc_message {
...@@ -457,9 +457,10 @@ static void ipc_tx_msgs(struct kthread_work *work) ...@@ -457,9 +457,10 @@ static void ipc_tx_msgs(struct kthread_work *work)
return; 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); 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); spin_unlock_irqrestore(&hsw->dsp->spinlock, flags);
return; return;
} }
...@@ -502,6 +503,7 @@ static int tx_wait_done(struct sst_hsw *hsw, struct ipc_message *msg, ...@@ -502,6 +503,7 @@ static int tx_wait_done(struct sst_hsw *hsw, struct ipc_message *msg,
ipc_shim_dbg(hsw, "message timeout"); ipc_shim_dbg(hsw, "message timeout");
trace_ipc_error("error message timeout for", msg->header); trace_ipc_error("error message timeout for", msg->header);
list_del(&msg->list);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
} else { } else {
...@@ -569,6 +571,9 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) ...@@ -569,6 +571,9 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header)
{ {
struct sst_hsw_ipc_fw_ready fw_ready; struct sst_hsw_ipc_fw_ready fw_ready;
u32 offset; u32 offset;
u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)];
char *tmp[5], *pinfo;
int i = 0;
offset = (header & 0x1FFFFFFF) << 3; offset = (header & 0x1FFFFFFF) << 3;
...@@ -589,6 +594,19 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) ...@@ -589,6 +594,19 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header)
fw_ready.inbox_offset, fw_ready.inbox_size); fw_ready.inbox_offset, fw_ready.inbox_size);
dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n", dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n",
fw_ready.outbox_offset, fw_ready.outbox_size); 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) 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) ...@@ -671,7 +689,9 @@ static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg)
switch (stream_msg) { switch (stream_msg) {
case IPC_STR_STAGE_MESSAGE: case IPC_STR_STAGE_MESSAGE:
case IPC_STR_NOTIFICATION: case IPC_STR_NOTIFICATION:
break;
case IPC_STR_RESET: case IPC_STR_RESET:
trace_ipc_notification("stream reset", stream->reply.stream_hw_id);
break; break;
case IPC_STR_PAUSE: case IPC_STR_PAUSE:
stream->running = false; stream->running = false;
...@@ -762,7 +782,8 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header) ...@@ -762,7 +782,8 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header)
} }
/* update any stream states */ /* 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 ? */ /* wake up and return the error if we have waiters on this message ? */
list_del(&msg->list); list_del(&msg->list);
...@@ -1628,7 +1649,7 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw, ...@@ -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) enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx)
{ {
u32 header, state_; u32 header, state_;
int ret; int ret, item;
header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE);
state_ = state; state_ = state;
...@@ -1642,6 +1663,13 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw, ...@@ -1642,6 +1663,13 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw,
return ret; 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", dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n",
dx->entries_no, state); dx->entries_no, state);
...@@ -1775,8 +1803,6 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) ...@@ -1775,8 +1803,6 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
/* get the FW version */ /* get the FW version */
sst_hsw_fw_get_version(hsw, &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 */ /* get the globalmixer */
ret = sst_hsw_mixer_get_info(hsw); ret = sst_hsw_mixer_get_info(hsw);
......
This diff is collapsed.
...@@ -100,14 +100,19 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, ...@@ -100,14 +100,19 @@ static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
int retval; int retval;
struct snd_sst_params str_params; struct snd_sst_params str_params;
struct sst_compress_cb cb; 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; stream = cstream->runtime->private_data;
/* construct fw structure for this*/ /* construct fw structure for this*/
memset(&str_params, 0, sizeof(str_params)); memset(&str_params, 0, sizeof(str_params));
str_params.ops = STREAM_OPS_PLAYBACK; /* fill the device type and stream id to pass to SST driver */
str_params.stream_type = SST_STREAM_TYPE_MUSIC; retval = sst_fill_stream_params(cstream, ctx, &str_params, true);
str_params.device_type = SND_SST_DEVICE_COMPRESS; pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval);
if (retval < 0)
return retval;
switch (params->codec.id) { switch (params->codec.id) {
case SND_AUDIOCODEC_MP3: { case SND_AUDIOCODEC_MP3: {
......
This diff is collapsed.
...@@ -39,9 +39,10 @@ extern struct sst_device *sst; ...@@ -39,9 +39,10 @@ extern struct sst_device *sst;
struct pcm_stream_info { struct pcm_stream_info {
int str_id; int str_id;
void *mad_substream; void *arg;
void (*period_elapsed) (void *mad_substream); void (*period_elapsed) (void *arg);
unsigned long long buffer_ptr; unsigned long long buffer_ptr;
unsigned long long pcm_delay;
int sfreq; int sfreq;
}; };
...@@ -62,7 +63,9 @@ enum sst_controls { ...@@ -62,7 +63,9 @@ enum sst_controls {
SST_SND_BUFFER_POINTER = 0x05, SST_SND_BUFFER_POINTER = 0x05,
SST_SND_STREAM_INIT = 0x06, SST_SND_STREAM_INIT = 0x06,
SST_SND_START = 0x07, 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 { enum sst_stream_ops {
...@@ -124,8 +127,9 @@ struct compress_sst_ops { ...@@ -124,8 +127,9 @@ struct compress_sst_ops {
}; };
struct 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 (*device_control) (int cmd, void *arg);
int (*set_generic_params)(enum sst_controls cmd, void *arg);
int (*close) (unsigned int str_id); int (*close) (unsigned int str_id);
}; };
...@@ -143,10 +147,27 @@ struct sst_device { ...@@ -143,10 +147,27 @@ struct sst_device {
char *name; char *name;
struct device *dev; struct device *dev;
struct sst_ops *ops; struct sst_ops *ops;
struct platform_device *pdev;
struct compress_sst_ops *compr_ops; struct compress_sst_ops *compr_ops;
}; };
struct sst_data;
void sst_set_stream_status(struct sst_runtime_stream *stream, int state); 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_register_dsp(struct sst_device *sst);
int sst_unregister_dsp(struct sst_device *sst); int sst_unregister_dsp(struct sst_device *sst);
#endif #endif
config SND_KIRKWOOD_SOC config SND_KIRKWOOD_SOC
tristate "SoC Audio for the Marvell Kirkwood and Dove chips" 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 help
Say Y or M if you want to add support for codecs attached to 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 the Kirkwood I2S interface. You will also need to select the
...@@ -15,20 +15,3 @@ config SND_KIRKWOOD_SOC_ARMADA370_DB ...@@ -15,20 +15,3 @@ config SND_KIRKWOOD_SOC_ARMADA370_DB
Say Y if you want to add support for SoC audio on Say Y if you want to add support for SoC audio on
the Armada 370 Development Board. 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 ...@@ -2,10 +2,6 @@ snd-soc-kirkwood-objs := kirkwood-dma.o kirkwood-i2s.o
obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.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 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_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) ...@@ -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 = { static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
.info = (SNDRV_PCM_INFO_INTERLEAVED | .info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_PAUSE), SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
.buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES, .buffer_bytes_max = KIRKWOOD_SND_MAX_BUFFER_BYTES,
.period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES, .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES,
.period_bytes_max = KIRKWOOD_SND_MAX_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, ...@@ -212,7 +212,8 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
KIRKWOOD_PLAYCTL_SIZE_MASK); KIRKWOOD_PLAYCTL_SIZE_MASK);
priv->ctl_play |= ctl_play; priv->ctl_play |= ctl_play;
} else { } else {
priv->ctl_rec &= ~KIRKWOOD_RECCTL_SIZE_MASK; priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK |
KIRKWOOD_RECCTL_SIZE_MASK);
priv->ctl_rec |= ctl_rec; priv->ctl_rec |= ctl_rec;
} }
...@@ -221,14 +222,24 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -221,14 +222,24 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
return 0; 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, static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai) 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); struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
uint32_t ctl, value; uint32_t ctl, value;
ctl = readl(priv->io + KIRKWOOD_PLAYCTL); ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
if (ctl & KIRKWOOD_PLAYCTL_PAUSE) { if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) {
unsigned timeout = 5000; unsigned timeout = 5000;
/* /*
* The Armada510 spec says that if we enter pause mode, the * 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, ...@@ -256,14 +267,16 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */ ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN; /* i2s */
else else
ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */ ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN; /* spdif */
ctl = kirkwood_i2s_play_mute(ctl);
value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK; value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
writel(value, priv->io + KIRKWOOD_PLAYCTL); writel(value, priv->io + KIRKWOOD_PLAYCTL);
/* enable interrupts */ /* enable interrupts */
value = readl(priv->io + KIRKWOOD_INT_MASK); if (!runtime->no_period_wakeup) {
value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; value = readl(priv->io + KIRKWOOD_INT_MASK);
writel(value, priv->io + KIRKWOOD_INT_MASK); value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
writel(value, priv->io + KIRKWOOD_INT_MASK);
}
/* enable playback */ /* enable playback */
writel(ctl, priv->io + KIRKWOOD_PLAYCTL); writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
...@@ -295,6 +308,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, ...@@ -295,6 +308,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
KIRKWOOD_PLAYCTL_SPDIF_MUTE); KIRKWOOD_PLAYCTL_SPDIF_MUTE);
ctl = kirkwood_i2s_play_mute(ctl);
writel(ctl, priv->io + KIRKWOOD_PLAYCTL); writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
break; break;
...@@ -322,8 +336,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, ...@@ -322,8 +336,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
else else
ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */ ctl &= ~KIRKWOOD_RECCTL_I2S_EN; /* spdif */
value = ctl & ~(KIRKWOOD_RECCTL_I2S_EN | value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK;
KIRKWOOD_RECCTL_SPDIF_EN);
writel(value, priv->io + KIRKWOOD_RECCTL); writel(value, priv->io + KIRKWOOD_RECCTL);
/* enable interrupts */ /* enable interrupts */
...@@ -347,7 +360,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, ...@@ -347,7 +360,7 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
/* disable all records */ /* disable all records */
value = readl(priv->io + KIRKWOOD_RECCTL); 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); writel(value, priv->io + KIRKWOOD_RECCTL);
break; break;
...@@ -411,7 +424,7 @@ static int kirkwood_i2s_init(struct kirkwood_dma_data *priv) ...@@ -411,7 +424,7 @@ static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
writel(value, priv->io + KIRKWOOD_PLAYCTL); writel(value, priv->io + KIRKWOOD_PLAYCTL);
value = readl(priv->io + KIRKWOOD_RECCTL); 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); writel(value, priv->io + KIRKWOOD_RECCTL);
return 0; return 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");
/*
* 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 @@ ...@@ -38,6 +38,9 @@
#define KIRKWOOD_RECCTL_SIZE_24 (1<<0) #define KIRKWOOD_RECCTL_SIZE_24 (1<<0)
#define KIRKWOOD_RECCTL_SIZE_32 (0<<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_ADDR 0x1004
#define KIRKWOOD_REC_BUF_SIZE 0x1008 #define KIRKWOOD_REC_BUF_SIZE 0x1008
#define KIRKWOOD_REC_BYTE_COUNT 0x100C #define KIRKWOOD_REC_BYTE_COUNT 0x100C
...@@ -121,9 +124,9 @@ ...@@ -121,9 +124,9 @@
/* Theses values come from the marvell alsa driver */ /* Theses values come from the marvell alsa driver */
/* need to find where they come from */ /* 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_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_PERIOD_BYTES 0x8000
#define KIRKWOOD_SND_MAX_BUFFER_BYTES (KIRKWOOD_SND_MAX_PERIOD_BYTES \ #define KIRKWOOD_SND_MAX_BUFFER_BYTES (KIRKWOOD_SND_MAX_PERIOD_BYTES \
* KIRKWOOD_SND_MAX_PERIODS) * KIRKWOOD_SND_MAX_PERIODS)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment