Commit 041af768 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'for-linus' into for-next

parents f51ba114 ff878b40
......@@ -385,14 +385,14 @@ static bool elem_id_matches(const struct snd_kcontrol *kctl,
#define MULTIPLIER 37
static unsigned long get_ctl_id_hash(const struct snd_ctl_elem_id *id)
{
int i;
unsigned long h;
const unsigned char *p;
h = id->iface;
h = MULTIPLIER * h + id->device;
h = MULTIPLIER * h + id->subdevice;
for (p = id->name; *p; p++)
h = MULTIPLIER * h + *p;
for (i = 0; i < SNDRV_CTL_ELEM_ID_NAME_MAXLEN && id->name[i]; i++)
h = MULTIPLIER * h + id->name[i];
h = MULTIPLIER * h + id->index;
h &= LONG_MAX;
return h;
......
......@@ -4700,6 +4700,48 @@ static void alc236_fixup_hp_mute_led_micmute_vref(struct hda_codec *codec,
alc236_fixup_hp_micmute_led_vref(codec, fix, action);
}
static inline void alc298_samsung_write_coef_pack(struct hda_codec *codec,
const unsigned short coefs[2])
{
alc_write_coef_idx(codec, 0x23, coefs[0]);
alc_write_coef_idx(codec, 0x25, coefs[1]);
alc_write_coef_idx(codec, 0x26, 0xb011);
}
struct alc298_samsung_amp_desc {
unsigned char nid;
unsigned short init_seq[2][2];
};
static void alc298_fixup_samsung_amp(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
int i, j;
static const unsigned short init_seq[][2] = {
{ 0x19, 0x00 }, { 0x20, 0xc0 }, { 0x22, 0x44 }, { 0x23, 0x08 },
{ 0x24, 0x85 }, { 0x25, 0x41 }, { 0x35, 0x40 }, { 0x36, 0x01 },
{ 0x38, 0x81 }, { 0x3a, 0x03 }, { 0x3b, 0x81 }, { 0x40, 0x3e },
{ 0x41, 0x07 }, { 0x400, 0x1 }
};
static const struct alc298_samsung_amp_desc amps[] = {
{ 0x3a, { { 0x18, 0x1 }, { 0x26, 0x0 } } },
{ 0x39, { { 0x18, 0x2 }, { 0x26, 0x1 } } }
};
if (action != HDA_FIXUP_ACT_INIT)
return;
for (i = 0; i < ARRAY_SIZE(amps); i++) {
alc_write_coef_idx(codec, 0x22, amps[i].nid);
for (j = 0; j < ARRAY_SIZE(amps[i].init_seq); j++)
alc298_samsung_write_coef_pack(codec, amps[i].init_seq[j]);
for (j = 0; j < ARRAY_SIZE(init_seq); j++)
alc298_samsung_write_coef_pack(codec, init_seq[j]);
}
}
#if IS_REACHABLE(CONFIG_INPUT)
static void gpio2_mic_hotkey_event(struct hda_codec *codec,
struct hda_jack_callback *event)
......@@ -7030,6 +7072,7 @@ enum {
ALC236_FIXUP_HP_GPIO_LED,
ALC236_FIXUP_HP_MUTE_LED,
ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
ALC298_FIXUP_SAMSUNG_AMP,
ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
......@@ -8396,6 +8439,12 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc236_fixup_hp_mute_led_micmute_vref,
},
[ALC298_FIXUP_SAMSUNG_AMP] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc298_fixup_samsung_amp,
.chained = true,
.chain_id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET
},
[ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
......@@ -9342,13 +9391,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE),
SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
......@@ -9716,7 +9765,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{.id = ALC299_FIXUP_PREDATOR_SPK, .name = "predator-spk"},
{.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"},
{.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"},
{.id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc298-samsung-headphone"},
{.id = ALC298_FIXUP_SAMSUNG_AMP, .name = "alc298-samsung-amp"},
{.id = ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc256-samsung-headphone"},
{.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
{.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},
......
......@@ -699,7 +699,7 @@ static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface)
if (delayed_register[i] &&
sscanf(delayed_register[i], "%x:%x", &id, &inum) == 2 &&
id == chip->usb_id)
return inum != iface;
return iface < inum;
}
return false;
......
......@@ -758,7 +758,8 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
* The endpoint needs to be closed via snd_usb_endpoint_close() later.
*
* Note that this function doesn't configure the endpoint. The substream
* needs to set it up later via snd_usb_endpoint_configure().
* needs to set it up later via snd_usb_endpoint_set_params() and
* snd_usb_endpoint_prepare().
*/
struct snd_usb_endpoint *
snd_usb_endpoint_open(struct snd_usb_audio *chip,
......@@ -1290,12 +1291,13 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep)
/*
* snd_usb_endpoint_set_params: configure an snd_usb_endpoint
*
* It's called either from hw_params callback.
* Determine the number of URBs to be used on this endpoint.
* An endpoint must be configured before it can be started.
* An endpoint that is already running can not be reconfigured.
*/
static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
{
const struct audioformat *fmt = ep->cur_audiofmt;
int err;
......@@ -1378,18 +1380,18 @@ static int init_sample_rate(struct snd_usb_audio *chip,
}
/*
* snd_usb_endpoint_configure: Configure the endpoint
* snd_usb_endpoint_prepare: Prepare the endpoint
*
* This function sets up the EP to be fully usable state.
* It's called either from hw_params or prepare callback.
* It's called either from prepare callback.
* The function checks need_setup flag, and performs nothing unless needed,
* so it's safe to call this multiple times.
*
* This returns zero if unchanged, 1 if the configuration has changed,
* or a negative error code.
*/
int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
{
bool iface_first;
int err = 0;
......@@ -1410,9 +1412,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
if (err < 0)
goto unlock;
}
err = snd_usb_endpoint_set_params(chip, ep);
if (err < 0)
goto unlock;
goto done;
}
......@@ -1440,10 +1439,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
if (err < 0)
goto unlock;
err = snd_usb_endpoint_set_params(chip, ep);
if (err < 0)
goto unlock;
err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt);
if (err < 0)
goto unlock;
......
......@@ -17,8 +17,10 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
bool is_sync_ep);
void snd_usb_endpoint_close(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock);
bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
......
......@@ -443,17 +443,17 @@ static int configure_endpoints(struct snd_usb_audio *chip,
if (stop_endpoints(subs, false))
sync_pending_stops(subs);
if (subs->sync_endpoint) {
err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint);
if (err < 0)
return err;
}
err = snd_usb_endpoint_configure(chip, subs->data_endpoint);
err = snd_usb_endpoint_prepare(chip, subs->data_endpoint);
if (err < 0)
return err;
snd_usb_set_format_quirk(subs, subs->cur_audiofmt);
} else {
if (subs->sync_endpoint) {
err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint);
if (err < 0)
return err;
}
......@@ -551,7 +551,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
subs->cur_audiofmt = fmt;
mutex_unlock(&chip->mutex);
ret = configure_endpoints(chip, subs);
if (subs->sync_endpoint) {
ret = snd_usb_endpoint_set_params(chip, subs->sync_endpoint);
if (ret < 0)
goto unlock;
}
ret = snd_usb_endpoint_set_params(chip, subs->data_endpoint);
unlock:
if (ret < 0)
......
......@@ -2066,7 +2066,7 @@ bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface)
for (q = registration_quirks; q->usb_id; q++)
if (chip->usb_id == q->usb_id)
return iface != q->interface;
return iface < q->interface;
/* Register as normal */
return false;
......@@ -2205,6 +2205,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x2522, 0x0007, /* LH Labs Geek Out HD Audio 1V5 */
QUIRK_FLAG_SET_IFACE_FIRST),
DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */
QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
......
......@@ -495,6 +495,10 @@ static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
return 0;
}
}
if (chip->card->registered)
chip->need_delayed_register = true;
/* look for an empty stream */
list_for_each_entry(as, &chip->pcm_list, list) {
if (as->fmt_type != fp->fmt_type)
......@@ -502,9 +506,6 @@ static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
subs = &as->substream[stream];
if (subs->ep_num)
continue;
if (snd_device_get_state(chip->card, as->pcm) !=
SNDRV_DEV_BUILD)
chip->need_delayed_register = true;
err = snd_pcm_new_stream(as->pcm, stream, 1);
if (err < 0)
return err;
......
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