Skip to content

Commit

Permalink
Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
Browse files Browse the repository at this point in the history
  • Loading branch information
broonie committed Dec 12, 2016
2 parents 14eec47 + c1aee1d commit 52708d0
Show file tree
Hide file tree
Showing 30 changed files with 750 additions and 98 deletions.
17 changes: 17 additions & 0 deletions Documentation/ABI/testing/sysfs-platform-sst-atom
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
What: /sys/devices/platform/8086%x:00/firmware_version
Date: November 2016
KernelVersion: 4.10
Contact: "Sebastien Guiriec" <[email protected]>
Description:
LPE Firmware version for SST driver on all atom
plaforms (BYT/CHT/Merrifield/BSW).
If the FW has never been loaded it will display:
"FW not yet loaded"
If FW has been loaded it will display:
"v01.aa.bb.cc"
aa: Major version is reflecting SoC version:
0d: BYT FW
0b: BSW FW
07: Merrifield FW
bb: Minor version
cc: Build version
8 changes: 7 additions & 1 deletion include/uapi/sound/snd_sst_tokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@
*
* %SKL_TKN_STR_LIB_NAME: Specifies the library name
*
* %SKL_TKN_U32_PMODE: Specifies the power mode for pipe
*
* %SKL_TKL_U32_D0I3_CAPS: Specifies the D0i3 capability for module
*
* module_id and loadable flags dont have tokens as these values will be
* read from the DSP FW manifest
*/
Expand Down Expand Up @@ -208,7 +212,9 @@ enum SKL_TKNS {
SKL_TKN_U32_PROC_DOMAIN,
SKL_TKN_U32_LIB_COUNT,
SKL_TKN_STR_LIB_NAME,
SKL_TKN_MAX = SKL_TKN_STR_LIB_NAME,
SKL_TKN_U32_PMODE,
SKL_TKL_U32_D0I3_CAPS,
SKL_TKN_MAX = SKL_TKL_U32_D0I3_CAPS,
};

#endif
2 changes: 1 addition & 1 deletion sound/soc/intel/atom/sst-atom-controls.c
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@ int send_ssp_cmd(struct snd_soc_dai *dai, const char *id, bool enable)
struct sst_data *drv = snd_soc_dai_get_drvdata(dai);
int ssp_id;

dev_info(dai->dev, "Enter: enable=%d port_name=%s\n", enable, id);
dev_dbg(dai->dev, "Enter: enable=%d port_name=%s\n", enable, id);

if (strcmp(id, "ssp0-port") == 0)
ssp_id = SSP_MODEM;
Expand Down
39 changes: 39 additions & 0 deletions sound/soc/intel/atom/sst/sst.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/pm_qos.h>
#include <linux/async.h>
#include <linux/acpi.h>
#include <linux/sysfs.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <asm/platform_sst_audio.h>
Expand Down Expand Up @@ -242,6 +243,32 @@ int sst_alloc_drv_context(struct intel_sst_drv **ctx,
}
EXPORT_SYMBOL_GPL(sst_alloc_drv_context);

static ssize_t firmware_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct intel_sst_drv *ctx = dev_get_drvdata(dev);

if (ctx->fw_version.type == 0 && ctx->fw_version.major == 0 &&
ctx->fw_version.minor == 0 && ctx->fw_version.build == 0)
return sprintf(buf, "FW not yet loaded\n");
else
return sprintf(buf, "v%02x.%02x.%02x.%02x\n",
ctx->fw_version.type, ctx->fw_version.major,
ctx->fw_version.minor, ctx->fw_version.build);

}

DEVICE_ATTR_RO(firmware_version);

static const struct attribute *sst_fw_version_attrs[] = {
&dev_attr_firmware_version.attr,
NULL,
};

static const struct attribute_group sst_fw_version_attr_group = {
.attrs = (struct attribute **)sst_fw_version_attrs,
};

int sst_context_init(struct intel_sst_drv *ctx)
{
int ret = 0, i;
Expand Down Expand Up @@ -315,8 +342,19 @@ int sst_context_init(struct intel_sst_drv *ctx)
dev_err(ctx->dev, "Firmware download failed:%d\n", ret);
goto do_free_mem;
}

ret = sysfs_create_group(&ctx->dev->kobj,
&sst_fw_version_attr_group);
if (ret) {
dev_err(ctx->dev,
"Unable to create sysfs\n");
goto err_sysfs;
}

sst_register(ctx->dev);
return 0;
err_sysfs:
sysfs_remove_group(&ctx->dev->kobj, &sst_fw_version_attr_group);

do_free_mem:
destroy_workqueue(ctx->post_msg_wq);
Expand All @@ -330,6 +368,7 @@ void sst_context_cleanup(struct intel_sst_drv *ctx)
pm_runtime_disable(ctx->dev);
sst_unregister(ctx->dev);
sst_set_fw_state_locked(ctx, SST_SHUTDOWN);
sysfs_remove_group(&ctx->dev->kobj, &sst_fw_version_attr_group);
flush_scheduled_work();
destroy_workqueue(ctx->post_msg_wq);
pm_qos_remove_request(ctx->qos);
Expand Down
1 change: 1 addition & 0 deletions sound/soc/intel/atom/sst/sst.h
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ struct intel_sst_drv {
*/
char firmware_name[FW_NAME_SIZE];

struct snd_sst_fw_version fw_version;
struct sst_fw_save *fw_save;
};

Expand Down
11 changes: 11 additions & 0 deletions sound/soc/intel/atom/sst/sst_ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,17 @@ static void process_fw_init(struct intel_sst_drv *sst_drv_ctx,
retval = init->result;
goto ret;
}
dev_info(sst_drv_ctx->dev, "FW Version %02x.%02x.%02x.%02x\n",
init->fw_version.type, init->fw_version.major,
init->fw_version.minor, init->fw_version.build);
dev_dbg(sst_drv_ctx->dev, "Build date %s Time %s\n",
init->build_info.date, init->build_info.time);

/* Save FW version */
sst_drv_ctx->fw_version.type = init->fw_version.type;
sst_drv_ctx->fw_version.major = init->fw_version.major;
sst_drv_ctx->fw_version.minor = init->fw_version.minor;
sst_drv_ctx->fw_version.build = init->fw_version.build;

ret:
sst_wake_up_block(sst_drv_ctx, retval, FW_DWNL_ID, 0 , NULL, 0);
Expand Down
4 changes: 2 additions & 2 deletions sound/soc/intel/atom/sst/sst_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
sst_init_stream(&sst_drv_ctx->streams[str_id], alloc_param.codec_type,
str_id, alloc_param.operation, 0);

dev_info(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n",
dev_dbg(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n",
str_id, pipe_id);
ret = sst_prepare_and_post_msg(sst_drv_ctx, task_id, IPC_CMD,
IPC_IA_ALLOC_STREAM_MRFLD, pipe_id, sizeof(alloc_param),
Expand Down Expand Up @@ -415,7 +415,7 @@ int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
str_info->status = STREAM_UN_INIT;
mutex_unlock(&str_info->lock);

dev_info(sst_drv_ctx->dev, "Free for str %d pipe %#x\n",
dev_dbg(sst_drv_ctx->dev, "Free for str %d pipe %#x\n",
str_id, str_info->pipe_id);
retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
IPC_IA_FREE_STREAM_MRFLD, str_info->pipe_id, 0,
Expand Down
3 changes: 1 addition & 2 deletions sound/soc/intel/baytrail/sst-baytrail-ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/kthread.h>
#include <linux/firmware.h>
#include <linux/io.h>
#include <asm/div64.h>
Expand Down Expand Up @@ -338,7 +337,7 @@ static irqreturn_t sst_byt_irq_thread(int irq, void *context)
spin_unlock_irqrestore(&sst->spinlock, flags);

/* continue to send any remaining messages... */
kthread_queue_work(&ipc->kworker, &ipc->kwork);
schedule_work(&ipc->kwork);

return IRQ_HANDLED;
}
Expand Down
2 changes: 1 addition & 1 deletion sound/soc/intel/boards/broadwell.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ static int broadwell_rt286_hw_params(struct snd_pcm_substream *substream,
return ret;
}

static struct snd_soc_ops broadwell_rt286_ops = {
static const struct snd_soc_ops broadwell_rt286_ops = {
.hw_params = broadwell_rt286_hw_params,
};

Expand Down
22 changes: 18 additions & 4 deletions sound/soc/intel/boards/bxt_da7219_max98357a.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#define BXT_DIALOG_CODEC_DAI "da7219-hifi"
#define BXT_MAXIM_CODEC_DAI "HiFi"
#define DUAL_CHANNEL 2
#define QUAD_CHANNEL 4

static struct snd_soc_jack broxton_headset;

Expand Down Expand Up @@ -182,6 +183,16 @@ static struct snd_pcm_hw_constraint_list constraints_channels = {
.mask = 0,
};

static unsigned int channels_quad[] = {
QUAD_CHANNEL,
};

static struct snd_pcm_hw_constraint_list constraints_channels_quad = {
.count = ARRAY_SIZE(channels_quad),
.list = channels_quad,
.mask = 0,
};

static int bxt_fe_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
Expand Down Expand Up @@ -258,7 +269,10 @@ static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
{
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
channels->min = channels->max = DUAL_CHANNEL;
if (params_channels(params) == 2)
channels->min = channels->max = 2;
else
channels->min = channels->max = 4;

return 0;
}
Expand All @@ -267,9 +281,9 @@ static int broxton_dmic_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;

runtime->hw.channels_max = DUAL_CHANNEL;
runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints_channels);
&constraints_channels_quad);

return snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
Expand Down Expand Up @@ -348,7 +362,7 @@ static struct snd_soc_dai_link broxton_dais[] = {
.dynamic = 1,
.ops = &broxton_refcap_ops,
},
[BXT_DPCM_AUDIO_DMIC_CP]
[BXT_DPCM_AUDIO_DMIC_CP] =
{
.name = "Bxt Audio DMIC cap",
.stream_name = "dmiccap",
Expand Down
64 changes: 59 additions & 5 deletions sound/soc/intel/boards/bytcr_rt5640.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ struct byt_rt5640_private {
struct clk *mclk;
};

static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP |
BYT_RT5640_DMIC_EN |
BYT_RT5640_MCLK_EN;
static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN;

static void log_quirks(struct device *dev)
{
Expand Down Expand Up @@ -689,6 +687,10 @@ static bool is_valleyview(void)
return true;
}

struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */
u64 aif_value; /* 1: AIF1, 2: AIF2 */
u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */
};

static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
{
Expand All @@ -698,6 +700,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
int i;
int dai_index;
struct byt_rt5640_private *priv;
bool is_bytcr = false;

priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
if (!priv)
Expand Down Expand Up @@ -734,10 +737,61 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
struct sst_platform_info *p_info = mach->pdata;
const struct sst_res_info *res_info = p_info->res_info;

/* TODO: use CHAN package info from BIOS to detect AIF1/AIF2 */
if (res_info->acpi_ipc_irq_index == 0) {
if (res_info->acpi_ipc_irq_index == 0)
is_bytcr = true;
}

if (is_bytcr) {
/*
* Baytrail CR platforms may have CHAN package in BIOS, try
* to find relevant routing quirk based as done on Windows
* platforms. We have to read the information directly from the
* BIOS, at this stage the card is not created and the links
* with the codec driver/pdata are non-existent
*/

struct acpi_chan_package chan_package;

/* format specified: 2 64-bit integers */
struct acpi_buffer format = {sizeof("NN"), "NN"};
struct acpi_buffer state = {0, NULL};
struct sst_acpi_package_context pkg_ctx;
bool pkg_found = false;

state.length = sizeof(chan_package);
state.pointer = &chan_package;

pkg_ctx.name = "CHAN";
pkg_ctx.length = 2;
pkg_ctx.format = &format;
pkg_ctx.state = &state;
pkg_ctx.data_valid = false;

pkg_found = sst_acpi_find_package_from_hid(mach->id, &pkg_ctx);
if (pkg_found) {
if (chan_package.aif_value == 1) {
dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1;
} else if (chan_package.aif_value == 2) {
dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
} else {
dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
pkg_found = false;
}
}

if (!pkg_found) {
/* no BIOS indications, assume SSP0-AIF2 connection */
byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
}

/* change defaults for Baytrail-CR capture */
byt_rt5640_quirk |= BYT_RT5640_IN1_MAP;
byt_rt5640_quirk |= BYT_RT5640_DIFF_MIC;
} else {
byt_rt5640_quirk |= (BYT_RT5640_DMIC1_MAP |
BYT_RT5640_DMIC_EN);
}

/* check quirks before creating card */
Expand Down
26 changes: 26 additions & 0 deletions sound/soc/intel/boards/cht_bsw_rt5672.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@
#include <sound/jack.h>
#include "../../codecs/rt5670.h"
#include "../atom/sst-atom-controls.h"
#include "../common/sst-acpi.h"

/* The platform clock #3 outputs 19.2Mhz clock to codec as I2S MCLK */
#define CHT_PLAT_CLK_3_HZ 19200000
#define CHT_CODEC_DAI "rt5670-aif1"

static struct snd_soc_jack cht_bsw_headset;
static char cht_bsw_codec_name[16];

/* Headset jack detection DAPM pins */
static struct snd_soc_jack_pin cht_bsw_headset_pins[] = {
Expand Down Expand Up @@ -339,9 +341,33 @@ static struct snd_soc_card snd_soc_card_cht = {
.resume_post = cht_resume_post,
};

#define RT5672_I2C_DEFAULT "i2c-10EC5670:00"

static int snd_cht_mc_probe(struct platform_device *pdev)
{
int ret_val = 0;
struct sst_acpi_mach *mach = pdev->dev.platform_data;
const char *i2c_name;
int i;

strcpy(cht_bsw_codec_name, RT5672_I2C_DEFAULT);

/* fixup codec name based on HID */
if (mach) {
i2c_name = sst_acpi_find_name_from_hid(mach->id);
if (i2c_name) {
snprintf(cht_bsw_codec_name, sizeof(cht_bsw_codec_name),
"i2c-%s", i2c_name);
for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) {
if (!strcmp(cht_dailink[i].codec_name,
RT5672_I2C_DEFAULT)) {
cht_dailink[i].codec_name =
cht_bsw_codec_name;
break;
}
}
}
}

/* register the soc card */
snd_soc_card_cht.dev = &pdev->dev;
Expand Down
Loading

0 comments on commit 52708d0

Please sign in to comment.