forked from Minki/linux
Merge branch 'for-linus' into for-next
This commit is contained in:
commit
041af76890
@ -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 @@ out_of_memory:
|
||||
/*
|
||||
* 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;
|
||||
|
Loading…
Reference in New Issue
Block a user