Skip to content

Commit

Permalink
Merge remote-tracking branches 'asoc/topic/ak4613', 'asoc/topic/core'…
Browse files Browse the repository at this point in the history
…, 'asoc/topic/dmic' and 'asoc/topic/intel' into asoc-next
  • Loading branch information
Mark Brown committed Feb 7, 2018
5 parents 008a03c + 03bbf9f + 971da24 + 35b84bf + f7f61e0 commit 535b218
Show file tree
Hide file tree
Showing 28 changed files with 829 additions and 78 deletions.
41 changes: 34 additions & 7 deletions drivers/acpi/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -737,16 +737,17 @@ bool acpi_dev_found(const char *hid)
}
EXPORT_SYMBOL(acpi_dev_found);

struct acpi_dev_present_info {
struct acpi_dev_match_info {
const char *dev_name;
struct acpi_device_id hid[2];
const char *uid;
s64 hrv;
};

static int acpi_dev_present_cb(struct device *dev, void *data)
static int acpi_dev_match_cb(struct device *dev, void *data)
{
struct acpi_device *adev = to_acpi_device(dev);
struct acpi_dev_present_info *match = data;
struct acpi_dev_match_info *match = data;
unsigned long long hrv;
acpi_status status;

Expand All @@ -757,6 +758,8 @@ static int acpi_dev_present_cb(struct device *dev, void *data)
strcmp(adev->pnp.unique_id, match->uid)))
return 0;

match->dev_name = acpi_dev_name(adev);

if (match->hrv == -1)
return 1;

Expand Down Expand Up @@ -789,20 +792,44 @@ static int acpi_dev_present_cb(struct device *dev, void *data)
*/
bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
{
struct acpi_dev_present_info match = {};
struct acpi_dev_match_info match = {};
struct device *dev;

strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
match.uid = uid;
match.hrv = hrv;

dev = bus_find_device(&acpi_bus_type, NULL, &match,
acpi_dev_present_cb);

dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
return !!dev;
}
EXPORT_SYMBOL(acpi_dev_present);

/**
* acpi_dev_get_first_match_name - Return name of first match of ACPI device
* @hid: Hardware ID of the device.
* @uid: Unique ID of the device, pass NULL to not check _UID
* @hrv: Hardware Revision of the device, pass -1 to not check _HRV
*
* Return device name if a matching device was present
* at the moment of invocation, or NULL otherwise.
*
* See additional information in acpi_dev_present() as well.
*/
const char *
acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv)
{
struct acpi_dev_match_info match = {};
struct device *dev;

strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
match.uid = uid;
match.hrv = hrv;

dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
return dev ? match.dev_name : NULL;
}
EXPORT_SYMBOL(acpi_dev_get_first_match_name);

/*
* acpi_backlight= handling, this is done here rather then in video_detect.c
* because __setup cannot be used in modules.
Expand Down
11 changes: 10 additions & 1 deletion drivers/gpio/gpio-merrifield.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* published by the Free Software Foundation.
*/

#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
Expand Down Expand Up @@ -380,9 +381,16 @@ static void mrfld_irq_init_hw(struct mrfld_gpio *priv)
}
}

static const char *mrfld_gpio_get_pinctrl_dev_name(void)
{
const char *dev_name = acpi_dev_get_first_match_name("INTC1002", NULL, -1);
return dev_name ? dev_name : "pinctrl-merrifield";
}

static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
const struct mrfld_gpio_pinrange *range;
const char *pinctrl_dev_name;
struct mrfld_gpio *priv;
u32 gpio_base, irq_base;
void __iomem *base;
Expand Down Expand Up @@ -439,10 +447,11 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
return retval;
}

pinctrl_dev_name = mrfld_gpio_get_pinctrl_dev_name();
for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) {
range = &mrfld_gpio_ranges[i];
retval = gpiochip_add_pin_range(&priv->chip,
"pinctrl-merrifield",
pinctrl_dev_name,
range->gpio_base,
range->pin_base,
range->npins);
Expand Down
3 changes: 3 additions & 0 deletions include/acpi/acpi_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const guid_t *guid, u64 rev,
bool acpi_dev_found(const char *hid);
bool acpi_dev_present(const char *hid, const char *uid, s64 hrv);

const char *
acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv);

#ifdef CONFIG_ACPI

#include <linux/proc_fs.h>
Expand Down
6 changes: 6 additions & 0 deletions include/linux/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,12 @@ static inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
return false;
}

static inline const char *
acpi_dev_get_first_match_name(const char *hid, const char *uid, s64 hrv)
{
return NULL;
}

static inline bool is_acpi_node(struct fwnode_handle *fwnode)
{
return false;
Expand Down
10 changes: 3 additions & 7 deletions include/sound/soc-acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,13 @@ struct snd_soc_acpi_package_context {
bool data_valid;
};

/* codec name is used in DAIs is i2c-<HID>:00 with HID being 8 chars */
#define SND_ACPI_I2C_ID_LEN (4 + ACPI_ID_LEN + 3 + 1)

#if IS_ENABLED(CONFIG_ACPI)
/* translation fron HID to I2C name, needed for DAI codec_name */
const char *snd_soc_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]);
bool snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
struct snd_soc_acpi_package_context *ctx);
#else
static inline const char *
snd_soc_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN])
{
return NULL;
}
static inline bool
snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
struct snd_soc_acpi_package_context *ctx)
Expand Down
3 changes: 3 additions & 0 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,9 @@ struct snd_soc_component_driver {
int (*suspend)(struct snd_soc_component *);
int (*resume)(struct snd_soc_component *);

unsigned int (*read)(struct snd_soc_component *, unsigned int);
int (*write)(struct snd_soc_component *, unsigned int, unsigned int);

/* pcm creation and destruction */
int (*pcm_new)(struct snd_soc_pcm_runtime *);
void (*pcm_free)(struct snd_pcm *);
Expand Down
78 changes: 78 additions & 0 deletions sound/soc/codecs/ak4613.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/of_device.h>
Expand Down Expand Up @@ -95,6 +96,9 @@ struct ak4613_priv {
struct mutex lock;
const struct ak4613_interface *iface;
struct snd_pcm_hw_constraint_list constraint;
struct work_struct dummy_write_work;
struct snd_soc_component *component;
unsigned int rate;
unsigned int sysclk;

unsigned int fmt;
Expand Down Expand Up @@ -392,6 +396,7 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
default:
return -EINVAL;
}
priv->rate = rate;

/*
* FIXME
Expand Down Expand Up @@ -467,11 +472,83 @@ static int ak4613_set_bias_level(struct snd_soc_codec *codec,
return 0;
}

static void ak4613_dummy_write(struct work_struct *work)
{
struct ak4613_priv *priv = container_of(work,
struct ak4613_priv,
dummy_write_work);
struct snd_soc_component *component = priv->component;
unsigned int mgmt1;
unsigned int mgmt3;

/*
* PW_MGMT1 / PW_MGMT3 needs dummy write at least after 5 LR clocks
*
* Note
*
* To avoid extra delay, we want to avoid preemption here,
* but we can't. Because it uses I2C access which is using IRQ
* and sleep. Thus, delay might be more than 5 LR clocks
* see also
* ak4613_dai_trigger()
*/
udelay(5000000 / priv->rate);

snd_soc_component_read(component, PW_MGMT1, &mgmt1);
snd_soc_component_read(component, PW_MGMT3, &mgmt3);

snd_soc_component_write(component, PW_MGMT1, mgmt1);
snd_soc_component_write(component, PW_MGMT3, mgmt3);
}

static int ak4613_dai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec);

/*
* FIXME
*
* PW_MGMT1 / PW_MGMT3 needs dummy write at least after 5 LR clocks
* from Power Down Release. Otherwise, Playback volume will be 0dB.
* To avoid complex multiple delay/dummy_write method from
* ak4613_set_bias_level() / SND_SOC_DAPM_DAC_E("DACx", ...),
* call it once here.
*
* But, unfortunately, we can't "write" here because here is atomic
* context (It uses I2C access for writing).
* Thus, use schedule_work() to switching to normal context
* immediately.
*
* Note
*
* Calling ak4613_dummy_write() function might be delayed.
* In such case, ak4613 volume might be temporarily 0dB when
* beggining of playback.
* see also
* ak4613_dummy_write()
*/

if ((cmd != SNDRV_PCM_TRIGGER_START) &&
(cmd != SNDRV_PCM_TRIGGER_RESUME))
return 0;

if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
return 0;

priv->component = &codec->component;
schedule_work(&priv->dummy_write_work);

return 0;
}

static const struct snd_soc_dai_ops ak4613_dai_ops = {
.startup = ak4613_dai_startup,
.shutdown = ak4613_dai_shutdown,
.set_sysclk = ak4613_dai_set_sysclk,
.set_fmt = ak4613_dai_set_fmt,
.trigger = ak4613_dai_trigger,
.hw_params = ak4613_dai_hw_params,
};

Expand Down Expand Up @@ -590,6 +667,7 @@ static int ak4613_i2c_probe(struct i2c_client *i2c,
priv->iface = NULL;
priv->cnt = 0;
priv->sysclk = 0;
INIT_WORK(&priv->dummy_write_work, ak4613_dummy_write);

mutex_init(&priv->lock);

Expand Down
2 changes: 1 addition & 1 deletion sound/soc/codecs/dmic.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ static int dmic_dev_probe(struct platform_device *pdev)

if (pdev->dev.of_node) {
err = of_property_read_u32(pdev->dev.of_node, "num-channels", &chans);
if (err && (err != -ENOENT))
if (err && (err != -EINVAL))
return err;

if (!err) {
Expand Down
4 changes: 3 additions & 1 deletion sound/soc/intel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ config SND_SST_ATOM_HIFI2_PLATFORM_PCI
depends on X86 && PCI
select SND_SST_IPC_PCI
select SND_SOC_COMPRESS
select SND_SOC_INTEL_COMMON
help
If you have a Intel Medfield or Merrifield/Edison platform, then
enable this option by saying Y or m. Distros will typically not
Expand All @@ -98,6 +97,9 @@ config SND_SST_ATOM_HIFI2_PLATFORM
codec, then enable this option by saying Y or m. This is a
recommended option

config SND_SOC_INTEL_SKYLAKE_SSP_CLK
tristate

config SND_SOC_INTEL_SKYLAKE
tristate "SKL/BXT/KBL/GLK/CNL... Platforms"
depends on PCI && ACPI
Expand Down
2 changes: 2 additions & 0 deletions sound/soc/intel/boards/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ config SND_SOC_INTEL_BYT_CHT_DA7213_MACH
config SND_SOC_INTEL_BYT_CHT_ES8316_MACH
tristate "Baytrail & Cherrytrail with ES8316 codec"
depends on X86_INTEL_LPSS && I2C && ACPI
select SND_SOC_ACPI
select SND_SOC_ES8316
help
This adds support for ASoC machine driver for Intel(R) Baytrail &
Expand Down Expand Up @@ -234,6 +235,7 @@ config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH
select SND_SOC_MAX98927
select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
select SND_SOC_INTEL_SKYLAKE_SSP_CLK
help
This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for RT5663 + MAX98927.
Expand Down
4 changes: 2 additions & 2 deletions sound/soc/intel/boards/bytcht_da7213.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ static struct snd_soc_card bytcht_da7213_card = {
.num_dapm_routes = ARRAY_SIZE(audio_map),
};

static char codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
static char codec_name[SND_ACPI_I2C_ID_LEN];

static int bytcht_da7213_probe(struct platform_device *pdev)
{
Expand All @@ -243,7 +243,7 @@ static int bytcht_da7213_probe(struct platform_device *pdev)
}

/* fixup codec name based on HID */
i2c_name = snd_soc_acpi_find_name_from_hid(mach->id);
i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
if (i2c_name) {
snprintf(codec_name, sizeof(codec_name),
"%s%s", "i2c-", i2c_name);
Expand Down
26 changes: 25 additions & 1 deletion sound/soc/intel/boards/bytcht_es8316.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,15 +232,39 @@ static struct snd_soc_card byt_cht_es8316_card = {
.fully_routed = true,
};

static char codec_name[SND_ACPI_I2C_ID_LEN];

static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
{
int ret = 0;
struct byt_cht_es8316_private *priv;
struct snd_soc_acpi_mach *mach;
const char *i2c_name = NULL;
int dai_index = 0;
int i;
int ret = 0;

priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
if (!priv)
return -ENOMEM;

mach = (&pdev->dev)->platform_data;
/* fix index of codec dai */
for (i = 0; i < ARRAY_SIZE(byt_cht_es8316_dais); i++) {
if (!strcmp(byt_cht_es8316_dais[i].codec_name,
"i2c-ESSX8316:00")) {
dai_index = i;
break;
}
}

/* fixup codec name based on HID */
i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
if (i2c_name) {
snprintf(codec_name, sizeof(codec_name),
"%s%s", "i2c-", i2c_name);
byt_cht_es8316_dais[dai_index].codec_name = codec_name;
}

/* register the soc card */
byt_cht_es8316_card.dev = &pdev->dev;
snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv);
Expand Down
Loading

0 comments on commit 535b218

Please sign in to comment.