mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 19:07:52 +00:00
sound fixes for 3.16-rc2
The significant part here is a few security fixes for ALSA core control API by Lars. Besides that, there are a few fixes for ASoC sigmadsp (again by Lars) for building properly, and small fixes for ASoC rsnd, MMP, PXA and FSL, in addition to a fix for bogus WARNING in i915/HD-audio binding. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJToaZXAAoJEGwxgFQ9KSmkOs4QAKhoVqWoyz5ZPKXAKqFvD5Ix JqWiuYgsoJYd3RENULQ5BdOY2pOXpi8j5a5YMfKFtePuZ4qJ6NNHLMSPiv9aYrcH cmp/ZPPqP8NgeHyQxlVe8VmW6A12myz43wR2XegzLQVyFPMXkU2IoDKcjBzYK1b0 L6sNzBEo7BE+DDCAhipbNjdjLLAadKVyCr9N4gFWCX7/AqKhYZR1HcHtz31JjS0d Krmz0eXVlSWM9wMCC/vl8cxSVzXmmu9Pir+tu7abfCLLRKCAeqZSdqcJcjsnm4wZ zAd6h/S7tqXKpIc9VIMmZFoKKgVOh2e1kFvWOJnrD0h/yv5p4JgWwu2QvqcFbzJT zMmn8Mm00bh9c+oo3Hr1k2Sn6muUBtW4IDGApWcttQb7asOROkDHwSG6hdhhrE8y 0TtV4mRHpxW/81+67MixVYSb6+LLZNEiSgm09wAVxzqtwpt4J+f2DWFAU+QeJVji SZj6pdsvn6ApC7o3tJ477+bfsplJX/ajZBbIykO3bDsfVXwwbJ90YchtFHIbzRf0 cZcqMLiJBLYrZ7S2rDfJLq9YePeoosOaV1dYiNk/jOV55WoLVdPJg12IQdWR04En Cfw2INma241thwXREwyXn4PZPL8D35x0tsJnm059fTfyXsQ3GgSmGn1LdmIrMXs7 3122r9ncyWXSK8w58Q04 =dWKL -----END PGP SIGNATURE----- Merge tag 'sound-3.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "The significant part here is a few security fixes for ALSA core control API by Lars. Besides that, there are a few fixes for ASoC sigmadsp (again by Lars) for building properly, and small fixes for ASoC rsnd, MMP, PXA and FSL, in addition to a fix for bogus WARNING in i915/HD-audio binding" * tag 'sound-3.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: control: Make sure that id->index does not overflow ALSA: control: Handle numid overflow ALSA: control: Don't access controls outside of protected regions ALSA: control: Fix replacing user controls ALSA: control: Protect user controls against concurrent access drm/i915, HD-audio: Don't continue probing when nomodeset is given ASoC: fsl: Fix build problem ASoC: rsnd: fixup index of src/dst mod when capture ASoC: fsl_spdif: Fix integer overflow when calculating divisors ASoC: fsl_spdif: Fix incorrect usage of regmap_read() ASoC: dapm: Make sure register value is in sync with DAPM kcontrol state ASoC: sigmadsp: Split regmap and I2C support into separate modules ASoC: MMP audio needs sram support ASoC: pxa: add I2C dependencies as needed
This commit is contained in:
commit
4ef61076f8
19 changed files with 212 additions and 132 deletions
|
@ -6019,30 +6019,32 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
|
||||||
static struct i915_power_domains *hsw_pwr;
|
static struct i915_power_domains *hsw_pwr;
|
||||||
|
|
||||||
/* Display audio driver power well request */
|
/* Display audio driver power well request */
|
||||||
void i915_request_power_well(void)
|
int i915_request_power_well(void)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv;
|
struct drm_i915_private *dev_priv;
|
||||||
|
|
||||||
if (WARN_ON(!hsw_pwr))
|
if (!hsw_pwr)
|
||||||
return;
|
return -ENODEV;
|
||||||
|
|
||||||
dev_priv = container_of(hsw_pwr, struct drm_i915_private,
|
dev_priv = container_of(hsw_pwr, struct drm_i915_private,
|
||||||
power_domains);
|
power_domains);
|
||||||
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
|
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(i915_request_power_well);
|
EXPORT_SYMBOL_GPL(i915_request_power_well);
|
||||||
|
|
||||||
/* Display audio driver power well release */
|
/* Display audio driver power well release */
|
||||||
void i915_release_power_well(void)
|
int i915_release_power_well(void)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv;
|
struct drm_i915_private *dev_priv;
|
||||||
|
|
||||||
if (WARN_ON(!hsw_pwr))
|
if (!hsw_pwr)
|
||||||
return;
|
return -ENODEV;
|
||||||
|
|
||||||
dev_priv = container_of(hsw_pwr, struct drm_i915_private,
|
dev_priv = container_of(hsw_pwr, struct drm_i915_private,
|
||||||
power_domains);
|
power_domains);
|
||||||
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
|
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(i915_release_power_well);
|
EXPORT_SYMBOL_GPL(i915_release_power_well);
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#define _I915_POWERWELL_H_
|
#define _I915_POWERWELL_H_
|
||||||
|
|
||||||
/* For use by hda_i915 driver */
|
/* For use by hda_i915 driver */
|
||||||
extern void i915_request_power_well(void);
|
extern int i915_request_power_well(void);
|
||||||
extern void i915_release_power_well(void);
|
extern int i915_release_power_well(void);
|
||||||
|
|
||||||
#endif /* _I915_POWERWELL_H_ */
|
#endif /* _I915_POWERWELL_H_ */
|
||||||
|
|
|
@ -116,6 +116,8 @@ struct snd_card {
|
||||||
int user_ctl_count; /* count of all user controls */
|
int user_ctl_count; /* count of all user controls */
|
||||||
struct list_head controls; /* all controls for this card */
|
struct list_head controls; /* all controls for this card */
|
||||||
struct list_head ctl_files; /* active control files */
|
struct list_head ctl_files; /* active control files */
|
||||||
|
struct mutex user_ctl_lock; /* protects user controls against
|
||||||
|
concurrent access */
|
||||||
|
|
||||||
struct snd_info_entry *proc_root; /* root for soundcard specific files */
|
struct snd_info_entry *proc_root; /* root for soundcard specific files */
|
||||||
struct snd_info_entry *proc_id; /* the card id */
|
struct snd_info_entry *proc_id; /* the card id */
|
||||||
|
|
|
@ -288,6 +288,10 @@ static bool snd_ctl_remove_numid_conflict(struct snd_card *card,
|
||||||
{
|
{
|
||||||
struct snd_kcontrol *kctl;
|
struct snd_kcontrol *kctl;
|
||||||
|
|
||||||
|
/* Make sure that the ids assigned to the control do not wrap around */
|
||||||
|
if (card->last_numid >= UINT_MAX - count)
|
||||||
|
card->last_numid = 0;
|
||||||
|
|
||||||
list_for_each_entry(kctl, &card->controls, list) {
|
list_for_each_entry(kctl, &card->controls, list) {
|
||||||
if (kctl->id.numid < card->last_numid + 1 + count &&
|
if (kctl->id.numid < card->last_numid + 1 + count &&
|
||||||
kctl->id.numid + kctl->count > card->last_numid + 1) {
|
kctl->id.numid + kctl->count > card->last_numid + 1) {
|
||||||
|
@ -330,6 +334,7 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
|
||||||
{
|
{
|
||||||
struct snd_ctl_elem_id id;
|
struct snd_ctl_elem_id id;
|
||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
|
unsigned int count;
|
||||||
int err = -EINVAL;
|
int err = -EINVAL;
|
||||||
|
|
||||||
if (! kcontrol)
|
if (! kcontrol)
|
||||||
|
@ -337,6 +342,9 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
|
||||||
if (snd_BUG_ON(!card || !kcontrol->info))
|
if (snd_BUG_ON(!card || !kcontrol->info))
|
||||||
goto error;
|
goto error;
|
||||||
id = kcontrol->id;
|
id = kcontrol->id;
|
||||||
|
if (id.index > UINT_MAX - kcontrol->count)
|
||||||
|
goto error;
|
||||||
|
|
||||||
down_write(&card->controls_rwsem);
|
down_write(&card->controls_rwsem);
|
||||||
if (snd_ctl_find_id(card, &id)) {
|
if (snd_ctl_find_id(card, &id)) {
|
||||||
up_write(&card->controls_rwsem);
|
up_write(&card->controls_rwsem);
|
||||||
|
@ -358,8 +366,9 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
|
||||||
card->controls_count += kcontrol->count;
|
card->controls_count += kcontrol->count;
|
||||||
kcontrol->id.numid = card->last_numid + 1;
|
kcontrol->id.numid = card->last_numid + 1;
|
||||||
card->last_numid += kcontrol->count;
|
card->last_numid += kcontrol->count;
|
||||||
|
count = kcontrol->count;
|
||||||
up_write(&card->controls_rwsem);
|
up_write(&card->controls_rwsem);
|
||||||
for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
|
for (idx = 0; idx < count; idx++, id.index++, id.numid++)
|
||||||
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
|
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -388,6 +397,7 @@ int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
|
||||||
bool add_on_replace)
|
bool add_on_replace)
|
||||||
{
|
{
|
||||||
struct snd_ctl_elem_id id;
|
struct snd_ctl_elem_id id;
|
||||||
|
unsigned int count;
|
||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
struct snd_kcontrol *old;
|
struct snd_kcontrol *old;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -423,8 +433,9 @@ int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
|
||||||
card->controls_count += kcontrol->count;
|
card->controls_count += kcontrol->count;
|
||||||
kcontrol->id.numid = card->last_numid + 1;
|
kcontrol->id.numid = card->last_numid + 1;
|
||||||
card->last_numid += kcontrol->count;
|
card->last_numid += kcontrol->count;
|
||||||
|
count = kcontrol->count;
|
||||||
up_write(&card->controls_rwsem);
|
up_write(&card->controls_rwsem);
|
||||||
for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
|
for (idx = 0; idx < count; idx++, id.index++, id.numid++)
|
||||||
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
|
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -897,9 +908,9 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
||||||
result = kctl->put(kctl, control);
|
result = kctl->put(kctl, control);
|
||||||
}
|
}
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
|
struct snd_ctl_elem_id id = control->id;
|
||||||
up_read(&card->controls_rwsem);
|
up_read(&card->controls_rwsem);
|
||||||
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
|
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
|
||||||
&control->id);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -991,6 +1002,7 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
|
||||||
|
|
||||||
struct user_element {
|
struct user_element {
|
||||||
struct snd_ctl_elem_info info;
|
struct snd_ctl_elem_info info;
|
||||||
|
struct snd_card *card;
|
||||||
void *elem_data; /* element data */
|
void *elem_data; /* element data */
|
||||||
unsigned long elem_data_size; /* size of element data in bytes */
|
unsigned long elem_data_size; /* size of element data in bytes */
|
||||||
void *tlv_data; /* TLV data */
|
void *tlv_data; /* TLV data */
|
||||||
|
@ -1034,7 +1046,9 @@ static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
struct user_element *ue = kcontrol->private_data;
|
struct user_element *ue = kcontrol->private_data;
|
||||||
|
|
||||||
|
mutex_lock(&ue->card->user_ctl_lock);
|
||||||
memcpy(&ucontrol->value, ue->elem_data, ue->elem_data_size);
|
memcpy(&ucontrol->value, ue->elem_data, ue->elem_data_size);
|
||||||
|
mutex_unlock(&ue->card->user_ctl_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1044,9 +1058,11 @@ static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
|
||||||
int change;
|
int change;
|
||||||
struct user_element *ue = kcontrol->private_data;
|
struct user_element *ue = kcontrol->private_data;
|
||||||
|
|
||||||
|
mutex_lock(&ue->card->user_ctl_lock);
|
||||||
change = memcmp(&ucontrol->value, ue->elem_data, ue->elem_data_size) != 0;
|
change = memcmp(&ucontrol->value, ue->elem_data, ue->elem_data_size) != 0;
|
||||||
if (change)
|
if (change)
|
||||||
memcpy(ue->elem_data, &ucontrol->value, ue->elem_data_size);
|
memcpy(ue->elem_data, &ucontrol->value, ue->elem_data_size);
|
||||||
|
mutex_unlock(&ue->card->user_ctl_lock);
|
||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1066,19 +1082,32 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
|
||||||
new_data = memdup_user(tlv, size);
|
new_data = memdup_user(tlv, size);
|
||||||
if (IS_ERR(new_data))
|
if (IS_ERR(new_data))
|
||||||
return PTR_ERR(new_data);
|
return PTR_ERR(new_data);
|
||||||
|
mutex_lock(&ue->card->user_ctl_lock);
|
||||||
change = ue->tlv_data_size != size;
|
change = ue->tlv_data_size != size;
|
||||||
if (!change)
|
if (!change)
|
||||||
change = memcmp(ue->tlv_data, new_data, size);
|
change = memcmp(ue->tlv_data, new_data, size);
|
||||||
kfree(ue->tlv_data);
|
kfree(ue->tlv_data);
|
||||||
ue->tlv_data = new_data;
|
ue->tlv_data = new_data;
|
||||||
ue->tlv_data_size = size;
|
ue->tlv_data_size = size;
|
||||||
|
mutex_unlock(&ue->card->user_ctl_lock);
|
||||||
} else {
|
} else {
|
||||||
if (! ue->tlv_data_size || ! ue->tlv_data)
|
int ret = 0;
|
||||||
return -ENXIO;
|
|
||||||
if (size < ue->tlv_data_size)
|
mutex_lock(&ue->card->user_ctl_lock);
|
||||||
return -ENOSPC;
|
if (!ue->tlv_data_size || !ue->tlv_data) {
|
||||||
|
ret = -ENXIO;
|
||||||
|
goto err_unlock;
|
||||||
|
}
|
||||||
|
if (size < ue->tlv_data_size) {
|
||||||
|
ret = -ENOSPC;
|
||||||
|
goto err_unlock;
|
||||||
|
}
|
||||||
if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size))
|
if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size))
|
||||||
return -EFAULT;
|
ret = -EFAULT;
|
||||||
|
err_unlock:
|
||||||
|
mutex_unlock(&ue->card->user_ctl_lock);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
|
@ -1136,8 +1165,6 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
||||||
struct user_element *ue;
|
struct user_element *ue;
|
||||||
int idx, err;
|
int idx, err;
|
||||||
|
|
||||||
if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS)
|
|
||||||
return -ENOMEM;
|
|
||||||
if (info->count < 1)
|
if (info->count < 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
|
access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
|
||||||
|
@ -1146,21 +1173,16 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
||||||
SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE));
|
SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE));
|
||||||
info->id.numid = 0;
|
info->id.numid = 0;
|
||||||
memset(&kctl, 0, sizeof(kctl));
|
memset(&kctl, 0, sizeof(kctl));
|
||||||
down_write(&card->controls_rwsem);
|
|
||||||
_kctl = snd_ctl_find_id(card, &info->id);
|
if (replace) {
|
||||||
err = 0;
|
err = snd_ctl_remove_user_ctl(file, &info->id);
|
||||||
if (_kctl) {
|
if (err)
|
||||||
if (replace)
|
|
||||||
err = snd_ctl_remove(card, _kctl);
|
|
||||||
else
|
|
||||||
err = -EBUSY;
|
|
||||||
} else {
|
|
||||||
if (replace)
|
|
||||||
err = -ENOENT;
|
|
||||||
}
|
|
||||||
up_write(&card->controls_rwsem);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (card->user_ctl_count >= MAX_USER_CONTROLS)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
memcpy(&kctl.id, &info->id, sizeof(info->id));
|
memcpy(&kctl.id, &info->id, sizeof(info->id));
|
||||||
kctl.count = info->owner ? info->owner : 1;
|
kctl.count = info->owner ? info->owner : 1;
|
||||||
access |= SNDRV_CTL_ELEM_ACCESS_USER;
|
access |= SNDRV_CTL_ELEM_ACCESS_USER;
|
||||||
|
@ -1210,6 +1232,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
||||||
ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL);
|
ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL);
|
||||||
if (ue == NULL)
|
if (ue == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
ue->card = card;
|
||||||
ue->info = *info;
|
ue->info = *info;
|
||||||
ue->info.access = 0;
|
ue->info.access = 0;
|
||||||
ue->elem_data = (char *)ue + sizeof(*ue);
|
ue->elem_data = (char *)ue + sizeof(*ue);
|
||||||
|
@ -1321,8 +1344,9 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
|
||||||
}
|
}
|
||||||
err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
|
err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
|
||||||
if (err > 0) {
|
if (err > 0) {
|
||||||
|
struct snd_ctl_elem_id id = kctl->id;
|
||||||
up_read(&card->controls_rwsem);
|
up_read(&card->controls_rwsem);
|
||||||
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id);
|
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &id);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -232,6 +232,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
|
||||||
INIT_LIST_HEAD(&card->devices);
|
INIT_LIST_HEAD(&card->devices);
|
||||||
init_rwsem(&card->controls_rwsem);
|
init_rwsem(&card->controls_rwsem);
|
||||||
rwlock_init(&card->ctl_files_rwlock);
|
rwlock_init(&card->ctl_files_rwlock);
|
||||||
|
mutex_init(&card->user_ctl_lock);
|
||||||
INIT_LIST_HEAD(&card->controls);
|
INIT_LIST_HEAD(&card->controls);
|
||||||
INIT_LIST_HEAD(&card->ctl_files);
|
INIT_LIST_HEAD(&card->ctl_files);
|
||||||
spin_lock_init(&card->files_lock);
|
spin_lock_init(&card->files_lock);
|
||||||
|
|
|
@ -22,20 +22,20 @@
|
||||||
#include <drm/i915_powerwell.h>
|
#include <drm/i915_powerwell.h>
|
||||||
#include "hda_i915.h"
|
#include "hda_i915.h"
|
||||||
|
|
||||||
static void (*get_power)(void);
|
static int (*get_power)(void);
|
||||||
static void (*put_power)(void);
|
static int (*put_power)(void);
|
||||||
|
|
||||||
void hda_display_power(bool enable)
|
int hda_display_power(bool enable)
|
||||||
{
|
{
|
||||||
if (!get_power || !put_power)
|
if (!get_power || !put_power)
|
||||||
return;
|
return -ENODEV;
|
||||||
|
|
||||||
pr_debug("HDA display power %s \n",
|
pr_debug("HDA display power %s \n",
|
||||||
enable ? "Enable" : "Disable");
|
enable ? "Enable" : "Disable");
|
||||||
if (enable)
|
if (enable)
|
||||||
get_power();
|
return get_power();
|
||||||
else
|
else
|
||||||
put_power();
|
return put_power();
|
||||||
}
|
}
|
||||||
|
|
||||||
int hda_i915_init(void)
|
int hda_i915_init(void)
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
#define __SOUND_HDA_I915_H
|
#define __SOUND_HDA_I915_H
|
||||||
|
|
||||||
#ifdef CONFIG_SND_HDA_I915
|
#ifdef CONFIG_SND_HDA_I915
|
||||||
void hda_display_power(bool enable);
|
int hda_display_power(bool enable);
|
||||||
int hda_i915_init(void);
|
int hda_i915_init(void);
|
||||||
int hda_i915_exit(void);
|
int hda_i915_exit(void);
|
||||||
#else
|
#else
|
||||||
static inline void hda_display_power(bool enable) {}
|
static inline int hda_display_power(bool enable) { return 0; }
|
||||||
static inline int hda_i915_init(void)
|
static inline int hda_i915_init(void)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
|
@ -1656,8 +1656,13 @@ static int azx_probe_continue(struct azx *chip)
|
||||||
"Error request power-well from i915\n");
|
"Error request power-well from i915\n");
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
err = hda_display_power(true);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(chip->card->dev,
|
||||||
|
"Cannot turn on display power on i915\n");
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
hda_display_power(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = azx_first_init(chip);
|
err = azx_first_init(chip);
|
||||||
|
|
|
@ -225,11 +225,11 @@ config SND_SOC_ADAU1373
|
||||||
config SND_SOC_ADAU1701
|
config SND_SOC_ADAU1701
|
||||||
tristate "Analog Devices ADAU1701 CODEC"
|
tristate "Analog Devices ADAU1701 CODEC"
|
||||||
depends on I2C
|
depends on I2C
|
||||||
select SND_SOC_SIGMADSP
|
select SND_SOC_SIGMADSP_I2C
|
||||||
|
|
||||||
config SND_SOC_ADAU17X1
|
config SND_SOC_ADAU17X1
|
||||||
tristate
|
tristate
|
||||||
select SND_SOC_SIGMADSP
|
select SND_SOC_SIGMADSP_REGMAP
|
||||||
|
|
||||||
config SND_SOC_ADAU1761
|
config SND_SOC_ADAU1761
|
||||||
tristate
|
tristate
|
||||||
|
@ -476,6 +476,14 @@ config SND_SOC_SIGMADSP
|
||||||
tristate
|
tristate
|
||||||
select CRC32
|
select CRC32
|
||||||
|
|
||||||
|
config SND_SOC_SIGMADSP_I2C
|
||||||
|
tristate
|
||||||
|
select SND_SOC_SIGMADSP
|
||||||
|
|
||||||
|
config SND_SOC_SIGMADSP_REGMAP
|
||||||
|
tristate
|
||||||
|
select SND_SOC_SIGMADSP
|
||||||
|
|
||||||
config SND_SOC_SIRF_AUDIO_CODEC
|
config SND_SOC_SIRF_AUDIO_CODEC
|
||||||
tristate "SiRF SoC internal audio codec"
|
tristate "SiRF SoC internal audio codec"
|
||||||
select REGMAP_MMIO
|
select REGMAP_MMIO
|
||||||
|
|
|
@ -77,6 +77,8 @@ snd-soc-sgtl5000-objs := sgtl5000.o
|
||||||
snd-soc-alc5623-objs := alc5623.o
|
snd-soc-alc5623-objs := alc5623.o
|
||||||
snd-soc-alc5632-objs := alc5632.o
|
snd-soc-alc5632-objs := alc5632.o
|
||||||
snd-soc-sigmadsp-objs := sigmadsp.o
|
snd-soc-sigmadsp-objs := sigmadsp.o
|
||||||
|
snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o
|
||||||
|
snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o
|
||||||
snd-soc-si476x-objs := si476x.o
|
snd-soc-si476x-objs := si476x.o
|
||||||
snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o
|
snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o
|
||||||
snd-soc-sn95031-objs := sn95031.o
|
snd-soc-sn95031-objs := sn95031.o
|
||||||
|
@ -240,6 +242,8 @@ obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o
|
||||||
obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o
|
obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o
|
||||||
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
|
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
|
||||||
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
|
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
|
||||||
|
obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o
|
||||||
|
obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o
|
||||||
obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o
|
obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o
|
||||||
obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
|
obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
|
||||||
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
|
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
|
||||||
|
|
35
sound/soc/codecs/sigmadsp-i2c.c
Normal file
35
sound/soc/codecs/sigmadsp-i2c.c
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Load Analog Devices SigmaStudio firmware files
|
||||||
|
*
|
||||||
|
* Copyright 2009-2011 Analog Devices Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the GPL-2 or later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
#include "sigmadsp.h"
|
||||||
|
|
||||||
|
static int sigma_action_write_i2c(void *control_data,
|
||||||
|
const struct sigma_action *sa, size_t len)
|
||||||
|
{
|
||||||
|
return i2c_master_send(control_data, (const unsigned char *)&sa->addr,
|
||||||
|
len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int process_sigma_firmware(struct i2c_client *client, const char *name)
|
||||||
|
{
|
||||||
|
struct sigma_firmware ssfw;
|
||||||
|
|
||||||
|
ssfw.control_data = client;
|
||||||
|
ssfw.write = sigma_action_write_i2c;
|
||||||
|
|
||||||
|
return _process_sigma_firmware(&client->dev, &ssfw, name);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(process_sigma_firmware);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
||||||
|
MODULE_DESCRIPTION("SigmaDSP I2C firmware loader");
|
||||||
|
MODULE_LICENSE("GPL");
|
36
sound/soc/codecs/sigmadsp-regmap.c
Normal file
36
sound/soc/codecs/sigmadsp-regmap.c
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Load Analog Devices SigmaStudio firmware files
|
||||||
|
*
|
||||||
|
* Copyright 2009-2011 Analog Devices Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the GPL-2 or later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
#include "sigmadsp.h"
|
||||||
|
|
||||||
|
static int sigma_action_write_regmap(void *control_data,
|
||||||
|
const struct sigma_action *sa, size_t len)
|
||||||
|
{
|
||||||
|
return regmap_raw_write(control_data, be16_to_cpu(sa->addr),
|
||||||
|
sa->payload, len - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
struct sigma_firmware ssfw;
|
||||||
|
|
||||||
|
ssfw.control_data = regmap;
|
||||||
|
ssfw.write = sigma_action_write_regmap;
|
||||||
|
|
||||||
|
return _process_sigma_firmware(dev, &ssfw, name);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(process_sigma_firmware_regmap);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
||||||
|
MODULE_DESCRIPTION("SigmaDSP regmap firmware loader");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -34,23 +34,6 @@ enum {
|
||||||
SIGMA_ACTION_END,
|
SIGMA_ACTION_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sigma_action {
|
|
||||||
u8 instr;
|
|
||||||
u8 len_hi;
|
|
||||||
__le16 len;
|
|
||||||
__be16 addr;
|
|
||||||
unsigned char payload[];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct sigma_firmware {
|
|
||||||
const struct firmware *fw;
|
|
||||||
size_t pos;
|
|
||||||
|
|
||||||
void *control_data;
|
|
||||||
int (*write)(void *control_data, const struct sigma_action *sa,
|
|
||||||
size_t len);
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline u32 sigma_action_len(struct sigma_action *sa)
|
static inline u32 sigma_action_len(struct sigma_action *sa)
|
||||||
{
|
{
|
||||||
return (sa->len_hi << 16) | le16_to_cpu(sa->len);
|
return (sa->len_hi << 16) | le16_to_cpu(sa->len);
|
||||||
|
@ -138,7 +121,7 @@ process_sigma_actions(struct sigma_firmware *ssfw)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _process_sigma_firmware(struct device *dev,
|
int _process_sigma_firmware(struct device *dev,
|
||||||
struct sigma_firmware *ssfw, const char *name)
|
struct sigma_firmware *ssfw, const char *name)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -197,50 +180,6 @@ static int _process_sigma_firmware(struct device *dev,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(_process_sigma_firmware);
|
||||||
#if IS_ENABLED(CONFIG_I2C)
|
|
||||||
|
|
||||||
static int sigma_action_write_i2c(void *control_data,
|
|
||||||
const struct sigma_action *sa, size_t len)
|
|
||||||
{
|
|
||||||
return i2c_master_send(control_data, (const unsigned char *)&sa->addr,
|
|
||||||
len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int process_sigma_firmware(struct i2c_client *client, const char *name)
|
|
||||||
{
|
|
||||||
struct sigma_firmware ssfw;
|
|
||||||
|
|
||||||
ssfw.control_data = client;
|
|
||||||
ssfw.write = sigma_action_write_i2c;
|
|
||||||
|
|
||||||
return _process_sigma_firmware(&client->dev, &ssfw, name);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(process_sigma_firmware);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_REGMAP)
|
|
||||||
|
|
||||||
static int sigma_action_write_regmap(void *control_data,
|
|
||||||
const struct sigma_action *sa, size_t len)
|
|
||||||
{
|
|
||||||
return regmap_raw_write(control_data, be16_to_cpu(sa->addr),
|
|
||||||
sa->payload, len - 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
struct sigma_firmware ssfw;
|
|
||||||
|
|
||||||
ssfw.control_data = regmap;
|
|
||||||
ssfw.write = sigma_action_write_regmap;
|
|
||||||
|
|
||||||
return _process_sigma_firmware(dev, &ssfw, name);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(process_sigma_firmware_regmap);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -12,6 +12,26 @@
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
|
struct sigma_action {
|
||||||
|
u8 instr;
|
||||||
|
u8 len_hi;
|
||||||
|
__le16 len;
|
||||||
|
__be16 addr;
|
||||||
|
unsigned char payload[];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct sigma_firmware {
|
||||||
|
const struct firmware *fw;
|
||||||
|
size_t pos;
|
||||||
|
|
||||||
|
void *control_data;
|
||||||
|
int (*write)(void *control_data, const struct sigma_action *sa,
|
||||||
|
size_t len);
|
||||||
|
};
|
||||||
|
|
||||||
|
int _process_sigma_firmware(struct device *dev,
|
||||||
|
struct sigma_firmware *ssfw, const char *name);
|
||||||
|
|
||||||
struct i2c_client;
|
struct i2c_client;
|
||||||
|
|
||||||
extern int process_sigma_firmware(struct i2c_client *client, const char *name);
|
extern int process_sigma_firmware(struct i2c_client *client, const char *name);
|
||||||
|
|
|
@ -923,8 +923,8 @@ static int fsl_soc_dma_probe(struct platform_device *pdev)
|
||||||
dma->dai.pcm_free = fsl_dma_free_dma_buffers;
|
dma->dai.pcm_free = fsl_dma_free_dma_buffers;
|
||||||
|
|
||||||
/* Store the SSI-specific information that we need */
|
/* Store the SSI-specific information that we need */
|
||||||
dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0);
|
dma->ssi_stx_phys = res.start + CCSR_SSI_STX0;
|
||||||
dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0);
|
dma->ssi_srx_phys = res.start + CCSR_SSI_SRX0;
|
||||||
|
|
||||||
iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL);
|
iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL);
|
||||||
if (iprop)
|
if (iprop)
|
||||||
|
|
|
@ -762,7 +762,7 @@ static int fsl_spdif_vbit_get(struct snd_kcontrol *kcontrol,
|
||||||
struct regmap *regmap = spdif_priv->regmap;
|
struct regmap *regmap = spdif_priv->regmap;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
val = regmap_read(regmap, REG_SPDIF_SIS, &val);
|
regmap_read(regmap, REG_SPDIF_SIS, &val);
|
||||||
ucontrol->value.integer.value[0] = (val & INT_VAL_NOGOOD) != 0;
|
ucontrol->value.integer.value[0] = (val & INT_VAL_NOGOOD) != 0;
|
||||||
regmap_write(regmap, REG_SPDIF_SIC, INT_VAL_NOGOOD);
|
regmap_write(regmap, REG_SPDIF_SIC, INT_VAL_NOGOOD);
|
||||||
|
|
||||||
|
@ -1076,7 +1076,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
|
||||||
goto out;
|
goto out;
|
||||||
} else if (arate / rate[index] == 1) {
|
} else if (arate / rate[index] == 1) {
|
||||||
/* A little bigger than expect */
|
/* A little bigger than expect */
|
||||||
sub = (arate - rate[index]) * 100000;
|
sub = (u64)(arate - rate[index]) * 100000;
|
||||||
do_div(sub, rate[index]);
|
do_div(sub, rate[index]);
|
||||||
if (sub >= savesub)
|
if (sub >= savesub)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1086,7 +1086,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
|
||||||
spdif_priv->txrate[index] = arate;
|
spdif_priv->txrate[index] = arate;
|
||||||
} else if (rate[index] / arate == 1) {
|
} else if (rate[index] / arate == 1) {
|
||||||
/* A little smaller than expect */
|
/* A little smaller than expect */
|
||||||
sub = (rate[index] - arate) * 100000;
|
sub = (u64)(rate[index] - arate) * 100000;
|
||||||
do_div(sub, rate[index]);
|
do_div(sub, rate[index]);
|
||||||
if (sub >= savesub)
|
if (sub >= savesub)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -11,6 +11,7 @@ config SND_PXA2XX_SOC
|
||||||
config SND_MMP_SOC
|
config SND_MMP_SOC
|
||||||
bool "Soc Audio for Marvell MMP chips"
|
bool "Soc Audio for Marvell MMP chips"
|
||||||
depends on ARCH_MMP
|
depends on ARCH_MMP
|
||||||
|
select MMP_SRAM
|
||||||
select SND_SOC_GENERIC_DMAENGINE_PCM
|
select SND_SOC_GENERIC_DMAENGINE_PCM
|
||||||
select SND_ARM
|
select SND_ARM
|
||||||
help
|
help
|
||||||
|
@ -40,7 +41,7 @@ config SND_MMP_SOC_SSPA
|
||||||
|
|
||||||
config SND_PXA2XX_SOC_CORGI
|
config SND_PXA2XX_SOC_CORGI
|
||||||
tristate "SoC Audio support for Sharp Zaurus SL-C7x0"
|
tristate "SoC Audio support for Sharp Zaurus SL-C7x0"
|
||||||
depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx
|
depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx && I2C
|
||||||
select SND_PXA2XX_SOC_I2S
|
select SND_PXA2XX_SOC_I2S
|
||||||
select SND_SOC_WM8731
|
select SND_SOC_WM8731
|
||||||
help
|
help
|
||||||
|
@ -49,7 +50,7 @@ config SND_PXA2XX_SOC_CORGI
|
||||||
|
|
||||||
config SND_PXA2XX_SOC_SPITZ
|
config SND_PXA2XX_SOC_SPITZ
|
||||||
tristate "SoC Audio support for Sharp Zaurus SL-Cxx00"
|
tristate "SoC Audio support for Sharp Zaurus SL-Cxx00"
|
||||||
depends on SND_PXA2XX_SOC && PXA_SHARP_Cxx00
|
depends on SND_PXA2XX_SOC && PXA_SHARP_Cxx00 && I2C
|
||||||
select SND_PXA2XX_SOC_I2S
|
select SND_PXA2XX_SOC_I2S
|
||||||
select SND_SOC_WM8750
|
select SND_SOC_WM8750
|
||||||
help
|
help
|
||||||
|
@ -58,7 +59,7 @@ config SND_PXA2XX_SOC_SPITZ
|
||||||
|
|
||||||
config SND_PXA2XX_SOC_Z2
|
config SND_PXA2XX_SOC_Z2
|
||||||
tristate "SoC Audio support for Zipit Z2"
|
tristate "SoC Audio support for Zipit Z2"
|
||||||
depends on SND_PXA2XX_SOC && MACH_ZIPIT2
|
depends on SND_PXA2XX_SOC && MACH_ZIPIT2 && I2C
|
||||||
select SND_PXA2XX_SOC_I2S
|
select SND_PXA2XX_SOC_I2S
|
||||||
select SND_SOC_WM8750
|
select SND_SOC_WM8750
|
||||||
help
|
help
|
||||||
|
@ -66,7 +67,7 @@ config SND_PXA2XX_SOC_Z2
|
||||||
|
|
||||||
config SND_PXA2XX_SOC_POODLE
|
config SND_PXA2XX_SOC_POODLE
|
||||||
tristate "SoC Audio support for Poodle"
|
tristate "SoC Audio support for Poodle"
|
||||||
depends on SND_PXA2XX_SOC && MACH_POODLE
|
depends on SND_PXA2XX_SOC && MACH_POODLE && I2C
|
||||||
select SND_PXA2XX_SOC_I2S
|
select SND_PXA2XX_SOC_I2S
|
||||||
select SND_SOC_WM8731
|
select SND_SOC_WM8731
|
||||||
help
|
help
|
||||||
|
@ -181,7 +182,7 @@ config SND_PXA2XX_SOC_HX4700
|
||||||
|
|
||||||
config SND_PXA2XX_SOC_MAGICIAN
|
config SND_PXA2XX_SOC_MAGICIAN
|
||||||
tristate "SoC Audio support for HTC Magician"
|
tristate "SoC Audio support for HTC Magician"
|
||||||
depends on SND_PXA2XX_SOC && MACH_MAGICIAN
|
depends on SND_PXA2XX_SOC && MACH_MAGICIAN && I2C
|
||||||
select SND_PXA2XX_SOC_I2S
|
select SND_PXA2XX_SOC_I2S
|
||||||
select SND_PXA_SOC_SSP
|
select SND_PXA_SOC_SSP
|
||||||
select SND_SOC_UDA1380
|
select SND_SOC_UDA1380
|
||||||
|
|
|
@ -315,7 +315,7 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
|
||||||
dst_mod = mod[index];
|
dst_mod = mod[index];
|
||||||
} else {
|
} else {
|
||||||
src_mod = mod[index];
|
src_mod = mod[index];
|
||||||
dst_mod = mod[index + 1];
|
dst_mod = mod[index - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
|
@ -2755,7 +2755,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
||||||
unsigned int mask = (1 << fls(max)) - 1;
|
unsigned int mask = (1 << fls(max)) - 1;
|
||||||
unsigned int invert = mc->invert;
|
unsigned int invert = mc->invert;
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
int connect, change;
|
int connect, change, reg_change = 0;
|
||||||
struct snd_soc_dapm_update update;
|
struct snd_soc_dapm_update update;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -2773,20 +2773,23 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
||||||
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
|
||||||
|
|
||||||
change = dapm_kcontrol_set_value(kcontrol, val);
|
change = dapm_kcontrol_set_value(kcontrol, val);
|
||||||
if (change) {
|
|
||||||
if (reg != SND_SOC_NOPM) {
|
if (reg != SND_SOC_NOPM) {
|
||||||
mask = mask << shift;
|
mask = mask << shift;
|
||||||
val = val << shift;
|
val = val << shift;
|
||||||
|
|
||||||
if (snd_soc_test_bits(codec, reg, mask, val)) {
|
reg_change = snd_soc_test_bits(codec, reg, mask, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change || reg_change) {
|
||||||
|
if (reg_change) {
|
||||||
update.kcontrol = kcontrol;
|
update.kcontrol = kcontrol;
|
||||||
update.reg = reg;
|
update.reg = reg;
|
||||||
update.mask = mask;
|
update.mask = mask;
|
||||||
update.val = val;
|
update.val = val;
|
||||||
card->update = &update;
|
card->update = &update;
|
||||||
}
|
}
|
||||||
|
change |= reg_change;
|
||||||
}
|
|
||||||
|
|
||||||
ret = soc_dapm_mixer_update_power(card, kcontrol, connect);
|
ret = soc_dapm_mixer_update_power(card, kcontrol, connect);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue