Sound fixes for 3.9-rc6
This contains slightly more volumes than usual at this stage, mostly because of my vacation in the last week. Nothing to scare, all small and/or trivial fixes: - Fix loop path handling in ASoC DAPM - Some memory handling fixes in ASoC core - Fix spear_pcm to adapt to the updated API - HD-audio HDMI ELD handling fixes - Fix for CM6331 USB-audio SRC change bugs - Revert power_save_controller option change due to user-space usage - A few other small ASoC and HD-audio fixes -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJRXl85AAoJEGwxgFQ9KSmkDzAQALJU/3Bn/tRJMFDwmVPYbuoi /mJ8iTBLz7uvKTnGaOIPg+vrt2SOkpcfE/bkv2d8GL/YMbXC7RY2j+37D8LYlnZQ rhUlM7VbkFsmoXR9GtgeWdZyrQSVNi7KFCfNLSNZmZAkDkopq0VzW4Ll+q4wyPWQ taZDQ0g3fnbAegiri246cb8nKH8gTzKRG16I/5N1S7fxLinQ6u5W4IPu9jHxNhiW sOyQOXwYp7CpgmqKBbjES8oncbgwSnk55YPY3Si+vfYIHy18yR9yCNyGsrGN8M0W c4oTU8EoNzGrwE4/+MSvkWwA4qYBEqRkEwS8eL2QlcyNpeZq1mROWnEa1BZz3PJ/ uw4M5GrVYFD/w95XRX/hJmenQelSV5S2EfCmxAbMQwXX9je2q9RzM0AeaORNUPYT Iy8S4+d9KBWBcLxmAASLUPTk5nl4bTPW/yy/Cb5ICQdnhHGTmKnJjQdIbP9tiiDD jfnftPUDBONRnCe24AtxQzDmj2wfikkMkQoR/nENKKR+u56zy6Le+m4zmv7OlfLX lqcWHh/Sgsg+B960GUPZSEqpDaXA5hkpXTz/foWbeu8Go0JVQTV9/+HDomrfP0VE EoRrApZf35PBSo2rqC6lyKhAp+OgWKmXoWelzCY3//4kYXl2cEK1voa5zFhgVRGD tccXSAxPyW4HsIg+4hqF =L1Ya -----END PGP SIGNATURE----- Merge tag 'sound-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "This contains slightly more volumes than usual at this stage, mostly because of my vacation in the last week. Nothing to scare, all small and/or trivial fixes: - Fix loop path handling in ASoC DAPM - Some memory handling fixes in ASoC core - Fix spear_pcm to adapt to the updated API - HD-audio HDMI ELD handling fixes - Fix for CM6331 USB-audio SRC change bugs - Revert power_save_controller option change due to user-space usage - A few other small ASoC and HD-audio fixes" * tag 'sound-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: hda/generic - fix uninitialized variable Revert "ALSA: hda - Allow power_save_controller option override DCAPS" ALSA: hda - fix typo in proc output ALSA: hda - Enabling Realtek ALC 671 codec ALSA: usb: Work around CM6631 sample rate change bug ALSA: hda - bug fix on HDMI ELD debug message ALSA: hda - bug fix on return value when getting HDMI ELD info ASoC: dma-sh7760: Fix compile error ASoC: core: fix invalid free of devm_ allocated data ASoC: spear_pcm: Update to new pcm_new() API ASoC:: max98090: Remove executable bit ASoC: dapm: Fix pointer dereference in is_connected_output_ep() ASoC: pcm030 audio fabric: remove __init from probe ASoC: imx-ssi: Fix occasional AC97 reset failure ASoC: core: fix possible memory leak in snd_soc_bytes_put() ASoC: wm_adsp: fix possible memory leak in wm_adsp_load_coeff() ASoC: dapm: Fix handling of loops ASoC: si476x: Add missing break for SNDRV_PCM_FORMAT_S8 switch case
This commit is contained in:
commit
8f09aacfa6
20 changed files with 83 additions and 37 deletions
|
@ -890,9 +890,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||||
enable_msi - Enable Message Signaled Interrupt (MSI) (default = off)
|
enable_msi - Enable Message Signaled Interrupt (MSI) (default = off)
|
||||||
power_save - Automatic power-saving timeout (in second, 0 =
|
power_save - Automatic power-saving timeout (in second, 0 =
|
||||||
disable)
|
disable)
|
||||||
power_save_controller - Support runtime D3 of HD-audio controller
|
power_save_controller - Reset HD-audio controller in power-saving mode
|
||||||
(-1 = on for supported chip (default), false = off,
|
(default = on)
|
||||||
true = force to on even for unsupported hardware)
|
|
||||||
align_buffer_size - Force rounding of buffer/period sizes to multiples
|
align_buffer_size - Force rounding of buffer/period sizes to multiples
|
||||||
of 128 bytes. This is more efficient in terms of memory
|
of 128 bytes. This is more efficient in terms of memory
|
||||||
access but isn't required by the HDA spec and prevents
|
access but isn't required by the HDA spec and prevents
|
||||||
|
|
0
include/sound/max98090.h
Executable file → Normal file
0
include/sound/max98090.h
Executable file → Normal file
|
@ -488,6 +488,7 @@ struct snd_soc_dapm_path {
|
||||||
/* status */
|
/* status */
|
||||||
u32 connect:1; /* source and sink widgets are connected */
|
u32 connect:1; /* source and sink widgets are connected */
|
||||||
u32 walked:1; /* path has been walked */
|
u32 walked:1; /* path has been walked */
|
||||||
|
u32 walking:1; /* path is in the process of being walked */
|
||||||
u32 weak:1; /* path ignored for power management */
|
u32 weak:1; /* path ignored for power management */
|
||||||
|
|
||||||
int (*connected)(struct snd_soc_dapm_widget *source,
|
int (*connected)(struct snd_soc_dapm_widget *source,
|
||||||
|
|
|
@ -173,7 +173,7 @@ const char *snd_hda_get_jack_type(u32 cfg)
|
||||||
"Line Out", "Speaker", "HP Out", "CD",
|
"Line Out", "Speaker", "HP Out", "CD",
|
||||||
"SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
|
"SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
|
||||||
"Line In", "Aux", "Mic", "Telephony",
|
"Line In", "Aux", "Mic", "Telephony",
|
||||||
"SPDIF In", "Digitial In", "Reserved", "Other"
|
"SPDIF In", "Digital In", "Reserved", "Other"
|
||||||
};
|
};
|
||||||
|
|
||||||
return jack_types[(cfg & AC_DEFCFG_DEVICE)
|
return jack_types[(cfg & AC_DEFCFG_DEVICE)
|
||||||
|
|
|
@ -320,7 +320,7 @@ int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
|
||||||
unsigned char *buf, int *eld_size)
|
unsigned char *buf, int *eld_size)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret = 0;
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -740,7 +740,7 @@ EXPORT_SYMBOL_HDA(snd_hda_activate_path);
|
||||||
static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
|
static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
|
||||||
{
|
{
|
||||||
struct hda_gen_spec *spec = codec->spec;
|
struct hda_gen_spec *spec = codec->spec;
|
||||||
bool changed;
|
bool changed = false;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!spec->power_down_unused || path->active)
|
if (!spec->power_down_unused || path->active)
|
||||||
|
|
|
@ -134,8 +134,8 @@ MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
|
||||||
* this may give more power-saving, but will take longer time to
|
* this may give more power-saving, but will take longer time to
|
||||||
* wake up.
|
* wake up.
|
||||||
*/
|
*/
|
||||||
static int power_save_controller = -1;
|
static bool power_save_controller = 1;
|
||||||
module_param(power_save_controller, bint, 0644);
|
module_param(power_save_controller, bool, 0644);
|
||||||
MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
|
MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
|
@ -2931,8 +2931,6 @@ static int azx_runtime_idle(struct device *dev)
|
||||||
struct snd_card *card = dev_get_drvdata(dev);
|
struct snd_card *card = dev_get_drvdata(dev);
|
||||||
struct azx *chip = card->private_data;
|
struct azx *chip = card->private_data;
|
||||||
|
|
||||||
if (power_save_controller > 0)
|
|
||||||
return 0;
|
|
||||||
if (!power_save_controller ||
|
if (!power_save_controller ||
|
||||||
!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
|
!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
|
@ -1196,7 +1196,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
|
||||||
|
|
||||||
_snd_printd(SND_PR_VERBOSE,
|
_snd_printd(SND_PR_VERBOSE,
|
||||||
"HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
|
"HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
|
||||||
codec->addr, pin_nid, eld->monitor_present, eld->eld_valid);
|
codec->addr, pin_nid, pin_eld->monitor_present, eld->eld_valid);
|
||||||
|
|
||||||
if (eld->eld_valid) {
|
if (eld->eld_valid) {
|
||||||
if (snd_hdmi_get_eld(codec, pin_nid, eld->eld_buffer,
|
if (snd_hdmi_get_eld(codec, pin_nid, eld->eld_buffer,
|
||||||
|
|
|
@ -3440,7 +3440,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
|
||||||
const hda_nid_t *ssids;
|
const hda_nid_t *ssids;
|
||||||
|
|
||||||
if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
|
if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
|
||||||
codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
|
codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670 ||
|
||||||
|
codec->vendor_id == 0x10ec0671)
|
||||||
ssids = alc663_ssids;
|
ssids = alc663_ssids;
|
||||||
else
|
else
|
||||||
ssids = alc662_ssids;
|
ssids = alc662_ssids;
|
||||||
|
@ -3894,6 +3895,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
|
||||||
{ .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
|
{ .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
|
||||||
{ .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
|
{ .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
|
||||||
{ .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
|
{ .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
|
||||||
|
{ .id = 0x10ec0671, .name = "ALC671", .patch = patch_alc662 },
|
||||||
{ .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
|
{ .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
|
||||||
{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
|
{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
|
||||||
{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
|
{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
|
||||||
|
|
0
sound/soc/codecs/max98090.c
Executable file → Normal file
0
sound/soc/codecs/max98090.c
Executable file → Normal file
0
sound/soc/codecs/max98090.h
Executable file → Normal file
0
sound/soc/codecs/max98090.h
Executable file → Normal file
|
@ -159,6 +159,7 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
|
||||||
switch (params_format(params)) {
|
switch (params_format(params)) {
|
||||||
case SNDRV_PCM_FORMAT_S8:
|
case SNDRV_PCM_FORMAT_S8:
|
||||||
width = SI476X_PCM_FORMAT_S8;
|
width = SI476X_PCM_FORMAT_S8;
|
||||||
|
break;
|
||||||
case SNDRV_PCM_FORMAT_S16_LE:
|
case SNDRV_PCM_FORMAT_S16_LE:
|
||||||
width = SI476X_PCM_FORMAT_S16_LE;
|
width = SI476X_PCM_FORMAT_S16_LE;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -828,7 +828,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
|
||||||
&buf_list);
|
&buf_list);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
adsp_err(dsp, "Out of memory\n");
|
adsp_err(dsp, "Out of memory\n");
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto out_fw;
|
||||||
}
|
}
|
||||||
|
|
||||||
adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
|
adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
|
||||||
|
@ -865,7 +866,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
|
||||||
wm_adsp_buf_free(&buf_list);
|
wm_adsp_buf_free(&buf_list);
|
||||||
out:
|
out:
|
||||||
kfree(file);
|
kfree(file);
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wm_adsp1_init(struct wm_adsp *adsp)
|
int wm_adsp1_init(struct wm_adsp *adsp)
|
||||||
|
|
|
@ -496,6 +496,8 @@ static void imx_ssi_ac97_reset(struct snd_ac97 *ac97)
|
||||||
|
|
||||||
if (imx_ssi->ac97_reset)
|
if (imx_ssi->ac97_reset)
|
||||||
imx_ssi->ac97_reset(ac97);
|
imx_ssi->ac97_reset(ac97);
|
||||||
|
/* First read sometimes fails, do a dummy read */
|
||||||
|
imx_ssi_ac97_read(ac97, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)
|
static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)
|
||||||
|
@ -504,6 +506,9 @@ static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)
|
||||||
|
|
||||||
if (imx_ssi->ac97_warm_reset)
|
if (imx_ssi->ac97_warm_reset)
|
||||||
imx_ssi->ac97_warm_reset(ac97);
|
imx_ssi->ac97_warm_reset(ac97);
|
||||||
|
|
||||||
|
/* First read sometimes fails, do a dummy read */
|
||||||
|
imx_ssi_ac97_read(ac97, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct snd_ac97_bus_ops soc_ac97_ops = {
|
struct snd_ac97_bus_ops soc_ac97_ops = {
|
||||||
|
|
|
@ -51,7 +51,7 @@ static struct snd_soc_card pcm030_card = {
|
||||||
.num_links = ARRAY_SIZE(pcm030_fabric_dai),
|
.num_links = ARRAY_SIZE(pcm030_fabric_dai),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init pcm030_fabric_probe(struct platform_device *op)
|
static int pcm030_fabric_probe(struct platform_device *op)
|
||||||
{
|
{
|
||||||
struct device_node *np = op->dev.of_node;
|
struct device_node *np = op->dev.of_node;
|
||||||
struct device_node *platform_np;
|
struct device_node *platform_np;
|
||||||
|
|
|
@ -342,8 +342,8 @@ static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_soc_platform sh7760_soc_platform = {
|
static struct snd_soc_platform_driver sh7760_soc_platform = {
|
||||||
.pcm_ops = &camelot_pcm_ops,
|
.ops = &camelot_pcm_ops,
|
||||||
.pcm_new = camelot_pcm_new,
|
.pcm_new = camelot_pcm_new,
|
||||||
.pcm_free = camelot_pcm_free,
|
.pcm_free = camelot_pcm_free,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3140,7 +3140,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
|
||||||
if (params->mask) {
|
if (params->mask) {
|
||||||
ret = regmap_read(codec->control_data, params->base, &val);
|
ret = regmap_read(codec->control_data, params->base, &val);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
goto out;
|
||||||
|
|
||||||
val &= params->mask;
|
val &= params->mask;
|
||||||
|
|
||||||
|
@ -3158,13 +3158,15 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
|
||||||
((u32 *)data)[0] |= cpu_to_be32(val);
|
((u32 *)data)[0] |= cpu_to_be32(val);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_raw_write(codec->control_data, params->base,
|
ret = regmap_raw_write(codec->control_data, params->base,
|
||||||
data, len);
|
data, len);
|
||||||
|
|
||||||
|
out:
|
||||||
kfree(data);
|
kfree(data);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -4197,7 +4199,6 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
|
||||||
dev_err(card->dev,
|
dev_err(card->dev,
|
||||||
"ASoC: Property '%s' index %d could not be read: %d\n",
|
"ASoC: Property '%s' index %d could not be read: %d\n",
|
||||||
propname, 2 * i, ret);
|
propname, 2 * i, ret);
|
||||||
kfree(routes);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
ret = of_property_read_string_index(np, propname,
|
ret = of_property_read_string_index(np, propname,
|
||||||
|
@ -4206,7 +4207,6 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
|
||||||
dev_err(card->dev,
|
dev_err(card->dev,
|
||||||
"ASoC: Property '%s' index %d could not be read: %d\n",
|
"ASoC: Property '%s' index %d could not be read: %d\n",
|
||||||
propname, (2 * i) + 1, ret);
|
propname, (2 * i) + 1, ret);
|
||||||
kfree(routes);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -831,6 +831,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
|
||||||
if (path->weak)
|
if (path->weak)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (path->walking)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (path->walked)
|
if (path->walked)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -838,6 +841,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
|
||||||
|
|
||||||
if (path->sink && path->connect) {
|
if (path->sink && path->connect) {
|
||||||
path->walked = 1;
|
path->walked = 1;
|
||||||
|
path->walking = 1;
|
||||||
|
|
||||||
/* do we need to add this widget to the list ? */
|
/* do we need to add this widget to the list ? */
|
||||||
if (list) {
|
if (list) {
|
||||||
|
@ -847,11 +851,14 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
|
||||||
dev_err(widget->dapm->dev,
|
dev_err(widget->dapm->dev,
|
||||||
"ASoC: could not add widget %s\n",
|
"ASoC: could not add widget %s\n",
|
||||||
widget->name);
|
widget->name);
|
||||||
|
path->walking = 0;
|
||||||
return con;
|
return con;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
con += is_connected_output_ep(path->sink, list);
|
con += is_connected_output_ep(path->sink, list);
|
||||||
|
|
||||||
|
path->walking = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -931,6 +938,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
|
||||||
if (path->weak)
|
if (path->weak)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (path->walking)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (path->walked)
|
if (path->walked)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -938,6 +948,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
|
||||||
|
|
||||||
if (path->source && path->connect) {
|
if (path->source && path->connect) {
|
||||||
path->walked = 1;
|
path->walked = 1;
|
||||||
|
path->walking = 1;
|
||||||
|
|
||||||
/* do we need to add this widget to the list ? */
|
/* do we need to add this widget to the list ? */
|
||||||
if (list) {
|
if (list) {
|
||||||
|
@ -947,11 +958,14 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
|
||||||
dev_err(widget->dapm->dev,
|
dev_err(widget->dapm->dev,
|
||||||
"ASoC: could not add widget %s\n",
|
"ASoC: could not add widget %s\n",
|
||||||
widget->name);
|
widget->name);
|
||||||
|
path->walking = 0;
|
||||||
return con;
|
return con;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
con += is_connected_input_ep(path->source, list);
|
con += is_connected_input_ep(path->source, list);
|
||||||
|
|
||||||
|
path->walking = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -149,9 +149,9 @@ static void spear_pcm_free(struct snd_pcm *pcm)
|
||||||
|
|
||||||
static u64 spear_pcm_dmamask = DMA_BIT_MASK(32);
|
static u64 spear_pcm_dmamask = DMA_BIT_MASK(32);
|
||||||
|
|
||||||
static int spear_pcm_new(struct snd_card *card,
|
static int spear_pcm_new(struct snd_soc_pcm_runtime *rtd)
|
||||||
struct snd_soc_dai *dai, struct snd_pcm *pcm)
|
|
||||||
{
|
{
|
||||||
|
struct snd_card *card = rtd->card->snd_card;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!card->dev->dma_mask)
|
if (!card->dev->dma_mask)
|
||||||
|
@ -159,16 +159,16 @@ static int spear_pcm_new(struct snd_card *card,
|
||||||
if (!card->dev->coherent_dma_mask)
|
if (!card->dev->coherent_dma_mask)
|
||||||
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
|
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
|
||||||
|
|
||||||
if (dai->driver->playback.channels_min) {
|
if (rtd->cpu_dai->driver->playback.channels_min) {
|
||||||
ret = spear_pcm_preallocate_dma_buffer(pcm,
|
ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
|
||||||
SNDRV_PCM_STREAM_PLAYBACK,
|
SNDRV_PCM_STREAM_PLAYBACK,
|
||||||
spear_pcm_hardware.buffer_bytes_max);
|
spear_pcm_hardware.buffer_bytes_max);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dai->driver->capture.channels_min) {
|
if (rtd->cpu_dai->driver->capture.channels_min) {
|
||||||
ret = spear_pcm_preallocate_dma_buffer(pcm,
|
ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
|
||||||
SNDRV_PCM_STREAM_CAPTURE,
|
SNDRV_PCM_STREAM_CAPTURE,
|
||||||
spear_pcm_hardware.buffer_bytes_max);
|
spear_pcm_hardware.buffer_bytes_max);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
@ -253,7 +253,7 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
|
||||||
{
|
{
|
||||||
struct usb_device *dev = chip->dev;
|
struct usb_device *dev = chip->dev;
|
||||||
unsigned char data[4];
|
unsigned char data[4];
|
||||||
int err, crate;
|
int err, cur_rate, prev_rate;
|
||||||
int clock = snd_usb_clock_find_source(chip, fmt->clock);
|
int clock = snd_usb_clock_find_source(chip, fmt->clock);
|
||||||
|
|
||||||
if (clock < 0)
|
if (clock < 0)
|
||||||
|
@ -266,6 +266,19 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
|
||||||
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
|
||||||
|
UAC2_CS_CONTROL_SAM_FREQ << 8,
|
||||||
|
snd_usb_ctrl_intf(chip) | (clock << 8),
|
||||||
|
data, sizeof(data));
|
||||||
|
if (err < 0) {
|
||||||
|
snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
|
||||||
|
dev->devnum, iface, fmt->altsetting);
|
||||||
|
prev_rate = 0;
|
||||||
|
} else {
|
||||||
|
prev_rate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||||||
|
}
|
||||||
|
|
||||||
data[0] = rate;
|
data[0] = rate;
|
||||||
data[1] = rate >> 8;
|
data[1] = rate >> 8;
|
||||||
data[2] = rate >> 16;
|
data[2] = rate >> 16;
|
||||||
|
@ -280,19 +293,31 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
|
err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
|
||||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
|
||||||
UAC2_CS_CONTROL_SAM_FREQ << 8,
|
UAC2_CS_CONTROL_SAM_FREQ << 8,
|
||||||
snd_usb_ctrl_intf(chip) | (clock << 8),
|
snd_usb_ctrl_intf(chip) | (clock << 8),
|
||||||
data, sizeof(data))) < 0) {
|
data, sizeof(data));
|
||||||
|
if (err < 0) {
|
||||||
snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
|
snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
|
||||||
dev->devnum, iface, fmt->altsetting);
|
dev->devnum, iface, fmt->altsetting);
|
||||||
return err;
|
cur_rate = 0;
|
||||||
|
} else {
|
||||||
|
cur_rate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
if (cur_rate != rate) {
|
||||||
if (crate != rate)
|
snd_printd(KERN_WARNING
|
||||||
snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
|
"current rate %d is different from the runtime rate %d\n",
|
||||||
|
cur_rate, rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Some devices doesn't respond to sample rate changes while the
|
||||||
|
* interface is active. */
|
||||||
|
if (rate != prev_rate) {
|
||||||
|
usb_set_interface(dev, iface, 0);
|
||||||
|
usb_set_interface(dev, iface, fmt->altsetting);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue