mirror of
https://github.com/torvalds/linux.git
synced 2026-09-14 16:10:02 +02:00
Merge branch 'for-next' into for-linus
This commit is contained in:
commit
692719a9d4
|
|
@ -2401,6 +2401,11 @@ quirk_flags
|
|||
disabling GET_CUR instead of the whole mixer. The current volume will
|
||||
then be provided by the internal cache that stores the last set
|
||||
volume
|
||||
* bit 31: ``playback_urb_fixup``
|
||||
Some devices show the stuttering at playback, and this quirk
|
||||
works around it by enforcing the fixed max URBs (12) instead of
|
||||
the dynamic calculation from the buffer size, and passing the
|
||||
`URB_ISO_ASAP` URB flag.
|
||||
|
||||
This module supports multiple devices, autoprobe and hotplugging.
|
||||
|
||||
|
|
|
|||
|
|
@ -1752,6 +1752,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
|
|||
* by the drivers/platform/x86/serial-multi-instantiate.c driver, which
|
||||
* knows which client device id to use for each resource.
|
||||
*/
|
||||
{"AWDZ8399", },
|
||||
{"BSG1160", },
|
||||
{"BSG2150", },
|
||||
{"CSC3551", },
|
||||
|
|
|
|||
|
|
@ -307,6 +307,15 @@ static void smi_remove(struct platform_device *pdev)
|
|||
smi_devs_unregister(smi);
|
||||
}
|
||||
|
||||
static const struct smi_node aw88399_hda = {
|
||||
.instances = {
|
||||
{ "aw88399-hda", IRQ_RESOURCE_AUTO, 0 },
|
||||
{ "aw88399-hda", IRQ_RESOURCE_AUTO, 0 },
|
||||
{}
|
||||
},
|
||||
.bus_type = SMI_AUTO_DETECT,
|
||||
};
|
||||
|
||||
static const struct smi_node bsg1160_data = {
|
||||
.instances = {
|
||||
{ "bmc150_accel", IRQ_RESOURCE_GPIO, 0 },
|
||||
|
|
@ -405,6 +414,7 @@ static const struct smi_node tas2781_hda = {
|
|||
* drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
|
||||
*/
|
||||
static const struct acpi_device_id smi_acpi_ids[] = {
|
||||
{ "AWDZ8399", (unsigned long)&aw88399_hda },
|
||||
{ "BSG1160", (unsigned long)&bsg1160_data },
|
||||
{ "BSG2150", (unsigned long)&bsg2150_data },
|
||||
{ "CSC3551", (unsigned long)&cs35l41_hda },
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ struct ac97_id {
|
|||
};
|
||||
|
||||
/**
|
||||
* ac97_codec_device - a ac97 codec
|
||||
* struct ac97_codec_device - a ac97 codec
|
||||
* @dev: the core device
|
||||
* @vendor_id: the vendor_id of the codec, as sensed on the AC-link
|
||||
* @num: the codec number, 0 is primary, 1 is first slave, etc ...
|
||||
|
|
@ -53,7 +53,7 @@ struct ac97_codec_device {
|
|||
};
|
||||
|
||||
/**
|
||||
* ac97_codec_driver - a ac97 codec driver
|
||||
* struct ac97_codec_driver - a ac97 codec driver
|
||||
* @driver: the device driver structure
|
||||
* @probe: the function called when a ac97_codec_device is matched
|
||||
* @remove: the function called when the device is unbound/removed
|
||||
|
|
|
|||
|
|
@ -11,9 +11,6 @@
|
|||
#include <sound/asound.h>
|
||||
#include <uapi/sound/asequencer.h>
|
||||
|
||||
/* helper macro */
|
||||
#define snd_seq_event_bounce_ext_data(ev) ((void*)((char *)(ev)->data.ext.ptr + sizeof(struct snd_seq_event_bounce)))
|
||||
|
||||
/*
|
||||
* type check macros
|
||||
*/
|
||||
|
|
|
|||
621
include/sound/aw88399.h
Normal file
621
include/sound/aw88399.h
Normal file
|
|
@ -0,0 +1,621 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only
|
||||
*
|
||||
* linux/sound/aw88399.h -- Platform data for AW88399
|
||||
*
|
||||
* Copyright (c) 2023 AWINIC Technology CO., LTD
|
||||
*
|
||||
* Author: Weidong Wang <wangweidong.a@awinic.com>
|
||||
*/
|
||||
|
||||
#ifndef __SOUND_AW88399_H
|
||||
#define __SOUND_AW88399_H
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
/* registers list */
|
||||
#define AW88399_ID_REG (0x00)
|
||||
#define AW88399_SYSST_REG (0x01)
|
||||
#define AW88399_SYSINT_REG (0x02)
|
||||
#define AW88399_SYSINTM_REG (0x03)
|
||||
#define AW88399_SYSCTRL_REG (0x04)
|
||||
#define AW88399_SYSCTRL2_REG (0x05)
|
||||
#define AW88399_I2SCTRL1_REG (0x06)
|
||||
#define AW88399_I2SCTRL2_REG (0x07)
|
||||
#define AW88399_I2SCTRL3_REG (0x08)
|
||||
#define AW88399_DACCFG1_REG (0x09)
|
||||
#define AW88399_DACCFG2_REG (0x0A)
|
||||
#define AW88399_DACCFG3_REG (0x0B)
|
||||
#define AW88399_DACCFG4_REG (0x0C)
|
||||
#define AW88399_DACCFG5_REG (0x0D)
|
||||
#define AW88399_DACCFG6_REG (0x0E)
|
||||
#define AW88399_DACCFG7_REG (0x0F)
|
||||
#define AW88399_MPDCFG1_REG (0x10)
|
||||
#define AW88399_MPDCFG2_REG (0x11)
|
||||
#define AW88399_MPDCFG3_REG (0x12)
|
||||
#define AW88399_MPDCFG4_REG (0x13)
|
||||
#define AW88399_PWMCTRL1_REG (0x14)
|
||||
#define AW88399_PWMCTRL2_REG (0x15)
|
||||
#define AW88399_PWMCTRL3_REG (0x16)
|
||||
#define AW88399_I2SCFG1_REG (0x17)
|
||||
#define AW88399_DBGCTRL_REG (0x18)
|
||||
#define AW88399_HAGCST_REG (0x20)
|
||||
#define AW88399_VBAT_REG (0x21)
|
||||
#define AW88399_TEMP_REG (0x22)
|
||||
#define AW88399_PVDD_REG (0x23)
|
||||
#define AW88399_ISNDAT_REG (0x24)
|
||||
#define AW88399_VSNDAT_REG (0x25)
|
||||
#define AW88399_I2SINT_REG (0x26)
|
||||
#define AW88399_I2SCAPCNT_REG (0x27)
|
||||
#define AW88399_ANASTA1_REG (0x28)
|
||||
#define AW88399_ANASTA2_REG (0x29)
|
||||
#define AW88399_ANASTA3_REG (0x2A)
|
||||
#define AW88399_TESTDET_REG (0x2B)
|
||||
#define AW88399_DSMCFG1_REG (0x30)
|
||||
#define AW88399_DSMCFG2_REG (0x31)
|
||||
#define AW88399_DSMCFG3_REG (0x32)
|
||||
#define AW88399_DSMCFG4_REG (0x33)
|
||||
#define AW88399_DSMCFG5_REG (0x34)
|
||||
#define AW88399_DSMCFG6_REG (0x35)
|
||||
#define AW88399_DSMCFG7_REG (0x36)
|
||||
#define AW88399_DSMCFG8_REG (0x37)
|
||||
#define AW88399_TESTIN_REG (0x38)
|
||||
#define AW88399_TESTOUT_REG (0x39)
|
||||
#define AW88399_MEMTEST_REG (0x3A)
|
||||
#define AW88399_VSNCTRL1_REG (0x3B)
|
||||
#define AW88399_ISNCTRL1_REG (0x3C)
|
||||
#define AW88399_ISNCTRL2_REG (0x3D)
|
||||
#define AW88399_DSPMADD_REG (0x40)
|
||||
#define AW88399_DSPMDAT_REG (0x41)
|
||||
#define AW88399_WDT_REG (0x42)
|
||||
#define AW88399_ACR1_REG (0x43)
|
||||
#define AW88399_ACR2_REG (0x44)
|
||||
#define AW88399_ASR1_REG (0x45)
|
||||
#define AW88399_ASR2_REG (0x46)
|
||||
#define AW88399_DSPCFG_REG (0x47)
|
||||
#define AW88399_ASR3_REG (0x48)
|
||||
#define AW88399_ASR4_REG (0x49)
|
||||
#define AW88399_DSPVCALB_REG (0x4A)
|
||||
#define AW88399_CRCCTRL_REG (0x4B)
|
||||
#define AW88399_DSPDBG1_REG (0x4C)
|
||||
#define AW88399_DSPDBG2_REG (0x4D)
|
||||
#define AW88399_DSPDBG3_REG (0x4E)
|
||||
#define AW88399_PLLCTRL1_REG (0x50)
|
||||
#define AW88399_PLLCTRL2_REG (0x51)
|
||||
#define AW88399_PLLCTRL3_REG (0x52)
|
||||
#define AW88399_CDACTRL1_REG (0x53)
|
||||
#define AW88399_CDACTRL2_REG (0x54)
|
||||
#define AW88399_CDACTRL3_REG (0x55)
|
||||
#define AW88399_SADCCTRL1_REG (0x56)
|
||||
#define AW88399_SADCCTRL2_REG (0x57)
|
||||
#define AW88399_BOPCTRL1_REG (0x58)
|
||||
#define AW88399_BOPCTRL2_REG (0x5A)
|
||||
#define AW88399_BOPCTRL3_REG (0x5B)
|
||||
#define AW88399_BOPCTRL4_REG (0x5C)
|
||||
#define AW88399_BOPCTRL5_REG (0x5D)
|
||||
#define AW88399_BOPCTRL6_REG (0x5E)
|
||||
#define AW88399_BOPCTRL7_REG (0x5F)
|
||||
#define AW88399_BSTCTRL1_REG (0x60)
|
||||
#define AW88399_BSTCTRL2_REG (0x61)
|
||||
#define AW88399_BSTCTRL3_REG (0x62)
|
||||
#define AW88399_BSTCTRL4_REG (0x63)
|
||||
#define AW88399_BSTCTRL5_REG (0x64)
|
||||
#define AW88399_BSTCTRL6_REG (0x65)
|
||||
#define AW88399_BSTCTRL7_REG (0x66)
|
||||
#define AW88399_BSTCTRL8_REG (0x67)
|
||||
#define AW88399_BSTCTRL9_REG (0x68)
|
||||
#define AW88399_BSTCTRL10_REG (0x69)
|
||||
#define AW88399_CPCTRL_REG (0x6A)
|
||||
#define AW88399_EFWH_REG (0x6C)
|
||||
#define AW88399_EFWM2_REG (0x6D)
|
||||
#define AW88399_EFWM1_REG (0x6E)
|
||||
#define AW88399_EFWL_REG (0x6F)
|
||||
#define AW88399_TESTCTRL1_REG (0x70)
|
||||
#define AW88399_TESTCTRL2_REG (0x71)
|
||||
#define AW88399_EFCTRL1_REG (0x72)
|
||||
#define AW88399_EFCTRL2_REG (0x73)
|
||||
#define AW88399_EFRH4_REG (0x74)
|
||||
#define AW88399_EFRH3_REG (0x75)
|
||||
#define AW88399_EFRH2_REG (0x76)
|
||||
#define AW88399_EFRH1_REG (0x77)
|
||||
#define AW88399_EFRL4_REG (0x78)
|
||||
#define AW88399_EFRL3_REG (0x79)
|
||||
#define AW88399_EFRL2_REG (0x7A)
|
||||
#define AW88399_EFRL1_REG (0x7B)
|
||||
#define AW88399_TM_REG (0x7C)
|
||||
#define AW88399_TM2_REG (0x7D)
|
||||
|
||||
#define AW88399_REG_MAX (0x7E)
|
||||
#define AW88399_MUTE_VOL (1023)
|
||||
|
||||
#define AW88399_DSP_CFG_ADDR (0x9B00)
|
||||
#define AW88399_DSP_REG_CFG_ADPZ_RA (0x9B68)
|
||||
#define AW88399_DSP_FW_ADDR (0x8980)
|
||||
#define AW88399_DSP_ROM_CHECK_ADDR (0x1F40)
|
||||
#define AW88399_DSP_ROM_CHECK_DATA (0x4638)
|
||||
|
||||
#define AW88399_CALI_RE_HBITS_MASK (~(0xFFFF0000))
|
||||
#define AW88399_CALI_RE_HBITS_SHIFT (16)
|
||||
|
||||
#define AW88399_CALI_RE_LBITS_MASK (~(0xFFFF))
|
||||
#define AW88399_CALI_RE_LBITS_SHIFT (0)
|
||||
|
||||
#define AW88399_I2STXEN_START_BIT (9)
|
||||
#define AW88399_I2STXEN_BITS_LEN (1)
|
||||
#define AW88399_I2STXEN_MASK \
|
||||
(~(((1<<AW88399_I2STXEN_BITS_LEN)-1) << AW88399_I2STXEN_START_BIT))
|
||||
|
||||
#define AW88399_I2STXEN_DISABLE (0)
|
||||
#define AW88399_I2STXEN_DISABLE_VALUE \
|
||||
(AW88399_I2STXEN_DISABLE << AW88399_I2STXEN_START_BIT)
|
||||
|
||||
#define AW88399_I2STXEN_ENABLE (1)
|
||||
#define AW88399_I2STXEN_ENABLE_VALUE \
|
||||
(AW88399_I2STXEN_ENABLE << AW88399_I2STXEN_START_BIT)
|
||||
|
||||
#define AW88399_VOL_START_BIT (0)
|
||||
#define AW88399_VOL_BITS_LEN (10)
|
||||
#define AW88399_VOL_MASK \
|
||||
(~(((1<<AW88399_VOL_BITS_LEN)-1) << AW88399_VOL_START_BIT))
|
||||
|
||||
#define AW88399_PWDN_START_BIT (0)
|
||||
#define AW88399_PWDN_BITS_LEN (1)
|
||||
#define AW88399_PWDN_MASK \
|
||||
(~(((1<<AW88399_PWDN_BITS_LEN)-1) << AW88399_PWDN_START_BIT))
|
||||
|
||||
#define AW88399_PWDN_POWER_DOWN (1)
|
||||
#define AW88399_PWDN_POWER_DOWN_VALUE \
|
||||
(AW88399_PWDN_POWER_DOWN << AW88399_PWDN_START_BIT)
|
||||
|
||||
#define AW88399_PWDN_WORKING (0)
|
||||
#define AW88399_PWDN_WORKING_VALUE \
|
||||
(AW88399_PWDN_WORKING << AW88399_PWDN_START_BIT)
|
||||
|
||||
#define AW88399_DSPBY_START_BIT (2)
|
||||
#define AW88399_DSPBY_BITS_LEN (1)
|
||||
#define AW88399_DSPBY_MASK \
|
||||
(~(((1<<AW88399_DSPBY_BITS_LEN)-1) << AW88399_DSPBY_START_BIT))
|
||||
|
||||
#define AW88399_DSPBY_WORKING (0)
|
||||
#define AW88399_DSPBY_WORKING_VALUE \
|
||||
(AW88399_DSPBY_WORKING << AW88399_DSPBY_START_BIT)
|
||||
|
||||
#define AW88399_DSPBY_BYPASS (1)
|
||||
#define AW88399_DSPBY_BYPASS_VALUE \
|
||||
(AW88399_DSPBY_BYPASS << AW88399_DSPBY_START_BIT)
|
||||
|
||||
#define AW88399_MEM_CLKSEL_START_BIT (3)
|
||||
#define AW88399_MEM_CLKSEL_BITS_LEN (1)
|
||||
#define AW88399_MEM_CLKSEL_MASK \
|
||||
(~(((1<<AW88399_MEM_CLKSEL_BITS_LEN)-1) << AW88399_MEM_CLKSEL_START_BIT))
|
||||
|
||||
#define AW88399_MEM_CLKSEL_OSCCLK (0)
|
||||
#define AW88399_MEM_CLKSEL_OSCCLK_VALUE \
|
||||
(AW88399_MEM_CLKSEL_OSCCLK << AW88399_MEM_CLKSEL_START_BIT)
|
||||
|
||||
#define AW88399_MEM_CLKSEL_DAPHCLK (1)
|
||||
#define AW88399_MEM_CLKSEL_DAPHCLK_VALUE \
|
||||
(AW88399_MEM_CLKSEL_DAPHCLK << AW88399_MEM_CLKSEL_START_BIT)
|
||||
|
||||
#define AW88399_DITHER_EN_START_BIT (15)
|
||||
#define AW88399_DITHER_EN_BITS_LEN (1)
|
||||
#define AW88399_DITHER_EN_MASK \
|
||||
(~(((1<<AW88399_DITHER_EN_BITS_LEN)-1) << AW88399_DITHER_EN_START_BIT))
|
||||
|
||||
#define AW88399_DITHER_EN_DISABLE (0)
|
||||
#define AW88399_DITHER_EN_DISABLE_VALUE \
|
||||
(AW88399_DITHER_EN_DISABLE << AW88399_DITHER_EN_START_BIT)
|
||||
|
||||
#define AW88399_DITHER_EN_ENABLE (1)
|
||||
#define AW88399_DITHER_EN_ENABLE_VALUE \
|
||||
(AW88399_DITHER_EN_ENABLE << AW88399_DITHER_EN_START_BIT)
|
||||
|
||||
#define AW88399_HMUTE_START_BIT (8)
|
||||
#define AW88399_HMUTE_BITS_LEN (1)
|
||||
#define AW88399_HMUTE_MASK \
|
||||
(~(((1<<AW88399_HMUTE_BITS_LEN)-1) << AW88399_HMUTE_START_BIT))
|
||||
|
||||
#define AW88399_HMUTE_DISABLE (0)
|
||||
#define AW88399_HMUTE_DISABLE_VALUE \
|
||||
(AW88399_HMUTE_DISABLE << AW88399_HMUTE_START_BIT)
|
||||
|
||||
#define AW88399_HMUTE_ENABLE (1)
|
||||
#define AW88399_HMUTE_ENABLE_VALUE \
|
||||
(AW88399_HMUTE_ENABLE << AW88399_HMUTE_START_BIT)
|
||||
|
||||
#define AW88399_EF_DBMD_START_BIT (2)
|
||||
#define AW88399_EF_DBMD_BITS_LEN (1)
|
||||
#define AW88399_EF_DBMD_MASK \
|
||||
(~(((1<<AW88399_EF_DBMD_BITS_LEN)-1) << AW88399_EF_DBMD_START_BIT))
|
||||
|
||||
#define AW88399_EF_DBMD_OR (1)
|
||||
#define AW88399_EF_DBMD_OR_VALUE \
|
||||
(AW88399_EF_DBMD_OR << AW88399_EF_DBMD_START_BIT)
|
||||
|
||||
#define AW88399_VDSEL_START_BIT (5)
|
||||
#define AW88399_VDSEL_BITS_LEN (1)
|
||||
#define AW88399_VDSEL_MASK \
|
||||
(~(((1<<AW88399_VDSEL_BITS_LEN)-1) << AW88399_VDSEL_START_BIT))
|
||||
|
||||
#define AW88399_EF_ISN_GESLP_H_START_BIT (0)
|
||||
#define AW88399_EF_ISN_GESLP_H_BITS_LEN (10)
|
||||
#define AW88399_EF_ISN_GESLP_H_MASK \
|
||||
(~(((1<<AW88399_EF_ISN_GESLP_H_BITS_LEN)-1) << AW88399_EF_ISN_GESLP_H_START_BIT))
|
||||
|
||||
/* EF_VSN_GESLP_H bit 9:0 (EFRH3 0x75) */
|
||||
#define AW88399_EF_VSN_GESLP_H_START_BIT (0)
|
||||
#define AW88399_EF_VSN_GESLP_H_BITS_LEN (10)
|
||||
#define AW88399_EF_VSN_GESLP_H_MASK \
|
||||
(~(((1<<AW88399_EF_VSN_GESLP_H_BITS_LEN)-1) << AW88399_EF_VSN_GESLP_H_START_BIT))
|
||||
|
||||
#define AW88399_EF_ISN_GESLP_L_START_BIT (0)
|
||||
#define AW88399_EF_ISN_GESLP_L_BITS_LEN (10)
|
||||
#define AW88399_EF_ISN_GESLP_L_MASK \
|
||||
(~(((1<<AW88399_EF_ISN_GESLP_L_BITS_LEN)-1) << AW88399_EF_ISN_GESLP_L_START_BIT))
|
||||
|
||||
/* EF_VSN_GESLP_L bit 9:0 (EFRL3 0x79) */
|
||||
#define AW88399_EF_VSN_GESLP_L_START_BIT (0)
|
||||
#define AW88399_EF_VSN_GESLP_L_BITS_LEN (10)
|
||||
#define AW88399_EF_VSN_GESLP_L_MASK \
|
||||
(~(((1<<AW88399_EF_VSN_GESLP_L_BITS_LEN)-1) << AW88399_EF_VSN_GESLP_L_START_BIT))
|
||||
|
||||
#define AW88399_INTERNAL_VSN_TRIM_H_START_BIT (9)
|
||||
#define AW88399_INTERNAL_VSN_TRIM_H_BITS_LEN (6)
|
||||
#define AW88399_INTERNAL_VSN_TRIM_H_MASK \
|
||||
(~(((1<<AW88399_INTERNAL_VSN_TRIM_H_BITS_LEN)-1) << AW88399_INTERNAL_VSN_TRIM_H_START_BIT))
|
||||
|
||||
#define AW88399_INTERNAL_VSN_TRIM_L_START_BIT (9)
|
||||
#define AW88399_INTERNAL_VSN_TRIM_L_BITS_LEN (6)
|
||||
#define AW88399_INTERNAL_VSN_TRIM_L_MASK \
|
||||
(~(((1<<AW88399_INTERNAL_VSN_TRIM_L_BITS_LEN)-1) << AW88399_INTERNAL_VSN_TRIM_L_START_BIT))
|
||||
|
||||
#define AW88399_RCV_MODE_START_BIT (7)
|
||||
#define AW88399_RCV_MODE_BITS_LEN (1)
|
||||
#define AW88399_RCV_MODE_MASK \
|
||||
(~(((1<<AW88399_RCV_MODE_BITS_LEN)-1) << AW88399_RCV_MODE_START_BIT))
|
||||
|
||||
#define AW88399_CLKI_START_BIT (4)
|
||||
#define AW88399_NOCLKI_START_BIT (5)
|
||||
#define AW88399_PLLI_START_BIT (0)
|
||||
#define AW88399_PLLI_INT_VALUE (1)
|
||||
#define AW88399_PLLI_INT_INTERRUPT \
|
||||
(AW88399_PLLI_INT_VALUE << AW88399_PLLI_START_BIT)
|
||||
|
||||
#define AW88399_CLKI_INT_VALUE (1)
|
||||
#define AW88399_CLKI_INT_INTERRUPT \
|
||||
(AW88399_CLKI_INT_VALUE << AW88399_CLKI_START_BIT)
|
||||
|
||||
#define AW88399_NOCLKI_INT_VALUE (1)
|
||||
#define AW88399_NOCLKI_INT_INTERRUPT \
|
||||
(AW88399_NOCLKI_INT_VALUE << AW88399_NOCLKI_START_BIT)
|
||||
|
||||
#define AW88399_BIT_SYSINT_CHECK \
|
||||
(AW88399_PLLI_INT_INTERRUPT | \
|
||||
AW88399_CLKI_INT_INTERRUPT | \
|
||||
AW88399_NOCLKI_INT_INTERRUPT)
|
||||
|
||||
#define AW88399_CRC_CHECK_START_BIT (12)
|
||||
#define AW88399_CRC_CHECK_BITS_LEN (3)
|
||||
#define AW88399_CRC_CHECK_BITS_MASK \
|
||||
(~(((1<<AW88399_CRC_CHECK_BITS_LEN)-1) << AW88399_CRC_CHECK_START_BIT))
|
||||
|
||||
#define AW88399_RCV_MODE_RECEIVER (1)
|
||||
#define AW88399_RCV_MODE_RECEIVER_VALUE \
|
||||
(AW88399_RCV_MODE_RECEIVER << AW88399_RCV_MODE_START_BIT)
|
||||
|
||||
#define AW88399_AMPPD_START_BIT (1)
|
||||
#define AW88399_AMPPD_BITS_LEN (1)
|
||||
#define AW88399_AMPPD_MASK \
|
||||
(~(((1<<AW88399_AMPPD_BITS_LEN)-1) << AW88399_AMPPD_START_BIT))
|
||||
|
||||
#define AW88399_AMPPD_WORKING (0)
|
||||
#define AW88399_AMPPD_WORKING_VALUE \
|
||||
(AW88399_AMPPD_WORKING << AW88399_AMPPD_START_BIT)
|
||||
|
||||
#define AW88399_AMPPD_POWER_DOWN (1)
|
||||
#define AW88399_AMPPD_POWER_DOWN_VALUE \
|
||||
(AW88399_AMPPD_POWER_DOWN << AW88399_AMPPD_START_BIT)
|
||||
|
||||
#define AW88399_RAM_CG_BYP_START_BIT (0)
|
||||
#define AW88399_RAM_CG_BYP_BITS_LEN (1)
|
||||
#define AW88399_RAM_CG_BYP_MASK \
|
||||
(~(((1<<AW88399_RAM_CG_BYP_BITS_LEN)-1) << AW88399_RAM_CG_BYP_START_BIT))
|
||||
|
||||
#define AW88399_RAM_CG_BYP_WORK (0)
|
||||
#define AW88399_RAM_CG_BYP_WORK_VALUE \
|
||||
(AW88399_RAM_CG_BYP_WORK << AW88399_RAM_CG_BYP_START_BIT)
|
||||
|
||||
#define AW88399_RAM_CG_BYP_BYPASS (1)
|
||||
#define AW88399_RAM_CG_BYP_BYPASS_VALUE \
|
||||
(AW88399_RAM_CG_BYP_BYPASS << AW88399_RAM_CG_BYP_START_BIT)
|
||||
|
||||
#define AW88399_CRC_END_ADDR_START_BIT (0)
|
||||
#define AW88399_CRC_END_ADDR_BITS_LEN (12)
|
||||
#define AW88399_CRC_END_ADDR_MASK \
|
||||
(~(((1<<AW88399_CRC_END_ADDR_BITS_LEN)-1) << AW88399_CRC_END_ADDR_START_BIT))
|
||||
|
||||
#define AW88399_CRC_CODE_EN_START_BIT (13)
|
||||
#define AW88399_CRC_CODE_EN_BITS_LEN (1)
|
||||
#define AW88399_CRC_CODE_EN_MASK \
|
||||
(~(((1<<AW88399_CRC_CODE_EN_BITS_LEN)-1) << AW88399_CRC_CODE_EN_START_BIT))
|
||||
|
||||
#define AW88399_CRC_CODE_EN_DISABLE (0)
|
||||
#define AW88399_CRC_CODE_EN_DISABLE_VALUE \
|
||||
(AW88399_CRC_CODE_EN_DISABLE << AW88399_CRC_CODE_EN_START_BIT)
|
||||
|
||||
#define AW88399_CRC_CODE_EN_ENABLE (1)
|
||||
#define AW88399_CRC_CODE_EN_ENABLE_VALUE \
|
||||
(AW88399_CRC_CODE_EN_ENABLE << AW88399_CRC_CODE_EN_START_BIT)
|
||||
|
||||
#define AW88399_CRC_CFG_EN_START_BIT (12)
|
||||
#define AW88399_CRC_CFG_EN_BITS_LEN (1)
|
||||
#define AW88399_CRC_CFG_EN_MASK \
|
||||
(~(((1<<AW88399_CRC_CFG_EN_BITS_LEN)-1) << AW88399_CRC_CFG_EN_START_BIT))
|
||||
|
||||
#define AW88399_CRC_CFG_EN_DISABLE (0)
|
||||
#define AW88399_CRC_CFG_EN_DISABLE_VALUE \
|
||||
(AW88399_CRC_CFG_EN_DISABLE << AW88399_CRC_CFG_EN_START_BIT)
|
||||
|
||||
#define AW88399_CRC_CFG_EN_ENABLE (1)
|
||||
#define AW88399_CRC_CFG_EN_ENABLE_VALUE \
|
||||
(AW88399_CRC_CFG_EN_ENABLE << AW88399_CRC_CFG_EN_START_BIT)
|
||||
|
||||
#define AW88399_OCDS_START_BIT (3)
|
||||
#define AW88399_OCDS_OC (1)
|
||||
#define AW88399_OCDS_OC_VALUE \
|
||||
(AW88399_OCDS_OC << AW88399_OCDS_START_BIT)
|
||||
|
||||
#define AW88399_NOCLKS_START_BIT (5)
|
||||
#define AW88399_NOCLKS_NO_CLOCK (1)
|
||||
#define AW88399_NOCLKS_NO_CLOCK_VALUE \
|
||||
(AW88399_NOCLKS_NO_CLOCK << AW88399_NOCLKS_START_BIT)
|
||||
|
||||
#define AW88399_SWS_START_BIT (8)
|
||||
#define AW88399_SWS_SWITCHING (1)
|
||||
#define AW88399_SWS_SWITCHING_VALUE \
|
||||
(AW88399_SWS_SWITCHING << AW88399_SWS_START_BIT)
|
||||
|
||||
#define AW88399_BSTS_START_BIT (9)
|
||||
#define AW88399_BSTS_FINISHED (1)
|
||||
#define AW88399_BSTS_FINISHED_VALUE \
|
||||
(AW88399_BSTS_FINISHED << AW88399_BSTS_START_BIT)
|
||||
|
||||
#define AW88399_UVLS_START_BIT (14)
|
||||
#define AW88399_UVLS_NORMAL (0)
|
||||
#define AW88399_UVLS_NORMAL_VALUE \
|
||||
(AW88399_UVLS_NORMAL << AW88399_UVLS_START_BIT)
|
||||
|
||||
#define AW88399_BSTOCS_START_BIT (11)
|
||||
#define AW88399_BSTOCS_OVER_CURRENT (1)
|
||||
#define AW88399_BSTOCS_OVER_CURRENT_VALUE \
|
||||
(AW88399_BSTOCS_OVER_CURRENT << AW88399_BSTOCS_START_BIT)
|
||||
|
||||
#define AW88399_OTHS_START_BIT (1)
|
||||
#define AW88399_OTHS_OT (1)
|
||||
#define AW88399_OTHS_OT_VALUE \
|
||||
(AW88399_OTHS_OT << AW88399_OTHS_START_BIT)
|
||||
|
||||
#define AW88399_PLLS_START_BIT (0)
|
||||
#define AW88399_PLLS_LOCKED (1)
|
||||
#define AW88399_PLLS_LOCKED_VALUE \
|
||||
(AW88399_PLLS_LOCKED << AW88399_PLLS_START_BIT)
|
||||
|
||||
#define AW88399_CLKS_START_BIT (4)
|
||||
#define AW88399_CLKS_STABLE (1)
|
||||
#define AW88399_CLKS_STABLE_VALUE \
|
||||
(AW88399_CLKS_STABLE << AW88399_CLKS_START_BIT)
|
||||
|
||||
#define AW88399_BIT_PLL_CHECK \
|
||||
(AW88399_CLKS_STABLE_VALUE | \
|
||||
AW88399_PLLS_LOCKED_VALUE)
|
||||
|
||||
#define AW88399_BIT_SYSST_CHECK_MASK \
|
||||
(~(AW88399_UVLS_NORMAL_VALUE | \
|
||||
AW88399_BSTOCS_OVER_CURRENT_VALUE | \
|
||||
AW88399_BSTS_FINISHED_VALUE | \
|
||||
AW88399_SWS_SWITCHING_VALUE | \
|
||||
AW88399_NOCLKS_NO_CLOCK_VALUE | \
|
||||
AW88399_CLKS_STABLE_VALUE | \
|
||||
AW88399_OCDS_OC_VALUE | \
|
||||
AW88399_OTHS_OT_VALUE | \
|
||||
AW88399_PLLS_LOCKED_VALUE))
|
||||
|
||||
#define AW88399_BIT_SYSST_NOSWS_CHECK \
|
||||
(AW88399_BSTS_FINISHED_VALUE | \
|
||||
AW88399_CLKS_STABLE_VALUE | \
|
||||
AW88399_PLLS_LOCKED_VALUE)
|
||||
|
||||
#define AW88399_BIT_SYSST_SWS_CHECK \
|
||||
(AW88399_BSTS_FINISHED_VALUE | \
|
||||
AW88399_CLKS_STABLE_VALUE | \
|
||||
AW88399_PLLS_LOCKED_VALUE | \
|
||||
AW88399_SWS_SWITCHING_VALUE)
|
||||
|
||||
#define AW88399_CCO_MUX_START_BIT (14)
|
||||
#define AW88399_CCO_MUX_BITS_LEN (1)
|
||||
#define AW88399_CCO_MUX_MASK \
|
||||
(~(((1<<AW88399_CCO_MUX_BITS_LEN)-1) << AW88399_CCO_MUX_START_BIT))
|
||||
|
||||
#define AW88399_CCO_MUX_DIVIDED (0)
|
||||
#define AW88399_CCO_MUX_DIVIDED_VALUE \
|
||||
(AW88399_CCO_MUX_DIVIDED << AW88399_CCO_MUX_START_BIT)
|
||||
|
||||
#define AW88399_CCO_MUX_BYPASS (1)
|
||||
#define AW88399_CCO_MUX_BYPASS_VALUE \
|
||||
(AW88399_CCO_MUX_BYPASS << AW88399_CCO_MUX_START_BIT)
|
||||
|
||||
#define AW88399_NOISE_GATE_EN_START_BIT (13)
|
||||
#define AW88399_NOISE_GATE_EN_BITS_LEN (1)
|
||||
#define AW88399_NOISE_GATE_EN_MASK \
|
||||
(~(((1<<AW88399_NOISE_GATE_EN_BITS_LEN)-1) << AW88399_NOISE_GATE_EN_START_BIT))
|
||||
|
||||
#define AW88399_WDT_CNT_START_BIT (0)
|
||||
#define AW88399_WDT_CNT_BITS_LEN (8)
|
||||
#define AW88399_WDT_CNT_MASK \
|
||||
(~(((1<<AW88399_WDT_CNT_BITS_LEN)-1) << AW88399_WDT_CNT_START_BIT))
|
||||
|
||||
#define AW88399_REABS_START_BIT (3)
|
||||
#define AW88399_REABS_BITS_LEN (1)
|
||||
#define AW88399_REABS_MASK \
|
||||
(~(((1<<AW88399_REABS_BITS_LEN)-1) << AW88399_REABS_START_BIT))
|
||||
|
||||
#define AW88399_DSP_VOL_START_BIT (8)
|
||||
#define AW88399_DSP_VOL_BITS_LEN (8)
|
||||
#define AW88399_DSP_VOL_MASK \
|
||||
(~(((1<<AW88399_DSP_VOL_BITS_LEN)-1) << AW88399_DSP_VOL_START_BIT))
|
||||
|
||||
#define AW883XX_DSP_NG_EN_START (13)
|
||||
#define AW883XX_DSP_NG_EN_LEN (1)
|
||||
#define AW883XX_DSP_NG_EN_MASK \
|
||||
(~(((1 << AW883XX_DSP_NG_EN_LEN) - 1) << AW883XX_DSP_NG_EN_START))
|
||||
#define AW883XX_DSP_NG_EN_DISABLE (0)
|
||||
#define AW883XX_DSP_NG_EN_DISABLE_VALUE \
|
||||
(AW883XX_DSP_NG_EN_DISABLE << AW883XX_DSP_NG_EN_START)
|
||||
|
||||
#define AW88399_VOLUME_STEP_DB (64)
|
||||
#define AW88399_VOL_DEFAULT_VALUE (0)
|
||||
#define AW88399_DSP_ODD_NUM_BIT_TEST (0x5555)
|
||||
#define AW88399_EF_ISN_GESLP_SIGN_MASK (~(1 << 9))
|
||||
#define AW88399_EF_ISN_GESLP_SIGN_NEG (0xfe00)
|
||||
|
||||
#define AW88399_EF_VSN_GESLP_SIGN_MASK (~(1 << 9))
|
||||
#define AW88399_EF_VSN_GESLP_SIGN_NEG (0xfe00)
|
||||
|
||||
#define AW88399_TEM4_SIGN_MASK (~(1 << 5))
|
||||
#define AW88399_TEM4_SIGN_NEG (0xffc0)
|
||||
|
||||
#define AW88399_ICABLK_FACTOR (1)
|
||||
#define AW88399_VCABLK_FACTOR (1)
|
||||
#define AW88399_VCABLK_DAC_FACTOR (2)
|
||||
|
||||
#define AW88399_VCALB_ADJ_FACTOR (12)
|
||||
#define AW88399_VCALB_ACCURACY (1 << 12)
|
||||
|
||||
#define AW88399_ISCAL_FACTOR (3125)
|
||||
#define AW88399_VSCAL_FACTOR (18875)
|
||||
#define AW88399_ISCAL_DAC_FACTOR (3125)
|
||||
#define AW88399_VSCAL_DAC_FACTOR (12600)
|
||||
#define AW88399_CABL_BASE_VALUE (1000)
|
||||
|
||||
#define AW88399_DEV_DEFAULT_CH (0)
|
||||
#define AW88399_DEV_DSP_CHECK_MAX (5)
|
||||
#define AW88399_MAX_RAM_WRITE_BYTE_SIZE (128)
|
||||
#define AW88399_DSP_RE_SHIFT (12)
|
||||
#define AW88399_CALI_RE_MAX (15000)
|
||||
#define AW88399_CALI_RE_MIN (4000)
|
||||
#define AW_FW_ADDR_LEN (4)
|
||||
#define AW88399_DSP_RE_TO_SHOW_RE(re, shift) (((re) * (1000)) >> (shift))
|
||||
#define AW88399_SHOW_RE_TO_DSP_RE(re, shift) (((re) << shift) / (1000))
|
||||
#define AW88399_CRC_CHECK_PASS_VAL (0x4)
|
||||
|
||||
#define AW88399_CRC_CFG_BASE_ADDR (0xD80)
|
||||
#define AW88399_CRC_FW_BASE_ADDR (0x4C0)
|
||||
#define AW88399_ACF_FILE "aw88399_acf.bin"
|
||||
#define AW88399_DEV_SYSST_CHECK_MAX (10)
|
||||
#define AW88399_CHIP_ID 0x2183
|
||||
|
||||
#define AW88399_START_RETRIES (5)
|
||||
#define AW88399_START_WORK_DELAY_MS (0)
|
||||
|
||||
enum {
|
||||
AW_EF_AND_CHECK = 0,
|
||||
AW_EF_OR_CHECK,
|
||||
};
|
||||
|
||||
enum {
|
||||
AW88399_DEV_VDSEL_DAC = 0,
|
||||
AW88399_DEV_VDSEL_VSENSE = 32,
|
||||
};
|
||||
|
||||
enum {
|
||||
AW88399_DSP_CRC_NA = 0,
|
||||
AW88399_DSP_CRC_OK = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
AW88399_DSP_FW_UPDATE_OFF = 0,
|
||||
AW88399_DSP_FW_UPDATE_ON = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
AW88399_FORCE_UPDATE_OFF = 0,
|
||||
AW88399_FORCE_UPDATE_ON = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
AW88399_1000_US = 1000,
|
||||
AW88399_2000_US = 2000,
|
||||
AW88399_3000_US = 3000,
|
||||
AW88399_4000_US = 4000,
|
||||
};
|
||||
|
||||
enum AW88399_DEV_STATUS {
|
||||
AW88399_DEV_PW_OFF = 0,
|
||||
AW88399_DEV_PW_ON,
|
||||
};
|
||||
|
||||
enum AW88399_DEV_FW_STATUS {
|
||||
AW88399_DEV_FW_FAILED = 0,
|
||||
AW88399_DEV_FW_OK,
|
||||
};
|
||||
|
||||
enum AW88399_DEV_MEMCLK {
|
||||
AW88399_DEV_MEMCLK_OSC = 0,
|
||||
AW88399_DEV_MEMCLK_PLL = 1,
|
||||
};
|
||||
|
||||
enum AW88399_DEV_DSP_CFG {
|
||||
AW88399_DEV_DSP_WORK = 0,
|
||||
AW88399_DEV_DSP_BYPASS = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
AW88399_NOT_RCV_MODE = 0,
|
||||
AW88399_RCV_MODE = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
AW88399_SYNC_START = 0,
|
||||
AW88399_ASYNC_START,
|
||||
};
|
||||
|
||||
struct aw_device;
|
||||
struct aw_container;
|
||||
struct aw_cali_desc;
|
||||
struct gpio_desc;
|
||||
struct i2c_client;
|
||||
struct regmap;
|
||||
|
||||
struct aw88399 {
|
||||
struct aw_device *aw_pa;
|
||||
struct mutex lock;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct delayed_work start_work;
|
||||
struct regmap *regmap;
|
||||
struct aw_container *aw_cfg;
|
||||
|
||||
unsigned int check_val;
|
||||
unsigned int crc_init_val;
|
||||
unsigned int vcalb_init_val;
|
||||
unsigned int dither_st;
|
||||
bool bsts_unreliable;
|
||||
bool fw_needs_reload;
|
||||
};
|
||||
|
||||
int aw_dev_check_syspll(struct aw_device *aw_dev);
|
||||
void aw_dev_dsp_enable(struct aw_device *aw_dev, bool is_enable);
|
||||
int aw_dev_get_dsp_status(struct aw_device *aw_dev);
|
||||
int aw_dev_set_volume(struct aw_device *aw_dev, unsigned int value);
|
||||
int aw_dev_update_cali_re(struct aw_cali_desc *cali_desc);
|
||||
int aw88399_dev_get_prof_name(struct aw_device *aw_dev, int index, char **prof_name);
|
||||
void aw88399_dev_mute(struct aw_device *aw_dev, bool is_mute);
|
||||
void aw88399_dev_set_channel(struct aw88399 *aw88399, int channel);
|
||||
void aw88399_hw_reset(struct aw88399 *aw88399);
|
||||
int aw88399_init(struct aw88399 *aw88399, struct i2c_client *i2c, struct regmap *regmap);
|
||||
extern const struct regmap_config aw88399_remap_config;
|
||||
int aw88399_request_firmware_file(struct aw88399 *aw88399);
|
||||
void aw88399_start(struct aw88399 *aw88399, bool sync_start);
|
||||
void aw88399_startup_work(struct work_struct *work);
|
||||
int aw88399_stop(struct aw_device *aw_dev);
|
||||
|
||||
#endif /* __SOUND_AW88399_H */
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
* Copyright (c) by Jaroslav Kysela <perex@perex.cz>
|
||||
*/
|
||||
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <sound/asound.h>
|
||||
|
|
@ -167,6 +168,8 @@ snd_ctl_find_id_mixer(struct snd_card *card, const char *name)
|
|||
|
||||
int snd_ctl_create(struct snd_card *card);
|
||||
|
||||
extern struct rw_semaphore snd_ioctl_rwsem;
|
||||
|
||||
int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
|
||||
int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn);
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
|
|
|||
|
|
@ -108,8 +108,8 @@ struct snd_card {
|
|||
char longname[80]; /* name of this soundcard */
|
||||
char irq_descr[32]; /* Interrupt description */
|
||||
char mixername[80]; /* mixer name */
|
||||
char components[128]; /* card components delimited with
|
||||
space */
|
||||
char *components; /* card components, space-delimited */
|
||||
unsigned int components_alloc_size; /* current allocation size of components */
|
||||
struct module *module; /* top-level module */
|
||||
|
||||
void *private_data; /* private data for soundcard */
|
||||
|
|
|
|||
|
|
@ -256,6 +256,7 @@ struct hda_codec {
|
|||
unsigned int link_down_at_suspend:1; /* link down at runtime suspend */
|
||||
unsigned int relaxed_resume:1; /* don't resume forcibly for jack */
|
||||
unsigned int forced_resume:1; /* forced resume for jack */
|
||||
unsigned int acomp_requested_resume:1; /* resume requested by acomp */
|
||||
unsigned int no_stream_clean_at_suspend:1; /* do not clean streams at suspend */
|
||||
unsigned int ctl_dev_id:1; /* old control element id build behaviour */
|
||||
unsigned int eld_jack_detect:1; /* Machine jack-detection by ELD */
|
||||
|
|
|
|||
|
|
@ -69,11 +69,14 @@ void snd_hdac_regmap_sync(struct hdac_device *codec);
|
|||
|
||||
/**
|
||||
* snd_hdac_regmap_write - Write a verb with caching
|
||||
* @codec: HD-audio codec base device
|
||||
* @nid: codec NID
|
||||
* @reg: verb to write
|
||||
* @verb: verb to write
|
||||
* @val: value to write
|
||||
*
|
||||
* For writing an amp value, use snd_hdac_regmap_update_amp().
|
||||
*
|
||||
* Returns: %0 if successful or a negative error code.
|
||||
*/
|
||||
static inline int
|
||||
snd_hdac_regmap_write(struct hdac_device *codec, hda_nid_t nid,
|
||||
|
|
@ -85,13 +88,16 @@ snd_hdac_regmap_write(struct hdac_device *codec, hda_nid_t nid,
|
|||
}
|
||||
|
||||
/**
|
||||
* snd_hda_regmap_update - Update a verb value with caching
|
||||
* snd_hdac_regmap_update - Update a verb value with caching
|
||||
* @codec: HD-audio codec
|
||||
* @nid: codec NID
|
||||
* @verb: verb to update
|
||||
* @mask: bit mask to update
|
||||
* @val: value to update
|
||||
*
|
||||
* For updating an amp value, use snd_hdac_regmap_update_amp().
|
||||
*
|
||||
* Returns: %0 if successful or a negative error code.
|
||||
*/
|
||||
static inline int
|
||||
snd_hdac_regmap_update(struct hdac_device *codec, hda_nid_t nid,
|
||||
|
|
@ -104,12 +110,15 @@ snd_hdac_regmap_update(struct hdac_device *codec, hda_nid_t nid,
|
|||
}
|
||||
|
||||
/**
|
||||
* snd_hda_regmap_read - Read a verb with caching
|
||||
* snd_hdac_regmap_read - Read a verb with caching
|
||||
* @codec: HD-audio codec
|
||||
* @nid: codec NID
|
||||
* @verb: verb to read
|
||||
* @val: pointer to store the value
|
||||
*
|
||||
* For reading an amp value, use snd_hda_regmap_get_amp().
|
||||
*
|
||||
* Returns: %0 if successful or a negative error code.
|
||||
*/
|
||||
static inline int
|
||||
snd_hdac_regmap_read(struct hdac_device *codec, hda_nid_t nid,
|
||||
|
|
@ -125,12 +134,12 @@ snd_hdac_regmap_read(struct hdac_device *codec, hda_nid_t nid,
|
|||
* @codec: HD-audio codec
|
||||
* @nid: NID to read the AMP value
|
||||
* @ch: channel (left=0 or right=1)
|
||||
* @direction: #HDA_INPUT or #HDA_OUTPUT
|
||||
* @index: the index value (only for input direction)
|
||||
* @val: the pointer to store the value
|
||||
* @dir: #HDA_INPUT or #HDA_OUTPUT
|
||||
* @idx: the index value (only for input direction)
|
||||
*
|
||||
* Read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
|
||||
* Returns the value or a negative error.
|
||||
*
|
||||
* Returns: the value or a negative error.
|
||||
*/
|
||||
static inline int
|
||||
snd_hdac_regmap_get_amp(struct hdac_device *codec, hda_nid_t nid,
|
||||
|
|
@ -148,13 +157,14 @@ snd_hdac_regmap_get_amp(struct hdac_device *codec, hda_nid_t nid,
|
|||
* @codec: HD-audio codec
|
||||
* @nid: NID to read the AMP value
|
||||
* @ch: channel (left=0 or right=1)
|
||||
* @direction: #HDA_INPUT or #HDA_OUTPUT
|
||||
* @dir: #HDA_INPUT or #HDA_OUTPUT
|
||||
* @idx: the index value (only for input direction)
|
||||
* @mask: bit mask to set
|
||||
* @val: the bits value to set
|
||||
*
|
||||
* Update the AMP value with a bit mask.
|
||||
* Returns 0 if the value is unchanged, 1 if changed, or a negative error.
|
||||
*
|
||||
* Returns: 0 if the value is unchanged, 1 if changed, or a negative error.
|
||||
*/
|
||||
static inline int
|
||||
snd_hdac_regmap_update_amp(struct hdac_device *codec, hda_nid_t nid,
|
||||
|
|
@ -169,13 +179,12 @@ snd_hdac_regmap_update_amp(struct hdac_device *codec, hda_nid_t nid,
|
|||
* snd_hdac_regmap_get_amp_stereo - Read stereo AMP values
|
||||
* @codec: HD-audio codec
|
||||
* @nid: NID to read the AMP value
|
||||
* @ch: channel (left=0 or right=1)
|
||||
* @direction: #HDA_INPUT or #HDA_OUTPUT
|
||||
* @index: the index value (only for input direction)
|
||||
* @val: the pointer to store the value
|
||||
* @dir: #HDA_INPUT or #HDA_OUTPUT
|
||||
* @idx: the index value (only for input direction)
|
||||
*
|
||||
* Read stereo AMP values. The lower byte is left, the upper byte is right.
|
||||
* Returns the value or a negative error.
|
||||
*
|
||||
* Returns: the value or a negative error.
|
||||
*/
|
||||
static inline int
|
||||
snd_hdac_regmap_get_amp_stereo(struct hdac_device *codec, hda_nid_t nid,
|
||||
|
|
@ -192,14 +201,15 @@ snd_hdac_regmap_get_amp_stereo(struct hdac_device *codec, hda_nid_t nid,
|
|||
* snd_hdac_regmap_update_amp_stereo - update the stereo AMP value
|
||||
* @codec: HD-audio codec
|
||||
* @nid: NID to read the AMP value
|
||||
* @direction: #HDA_INPUT or #HDA_OUTPUT
|
||||
* @dir: #HDA_INPUT or #HDA_OUTPUT
|
||||
* @idx: the index value (only for input direction)
|
||||
* @mask: bit mask to set
|
||||
* @val: the bits value to set
|
||||
*
|
||||
* Update the stereo AMP value with a bit mask.
|
||||
* The lower byte is left, the upper byte is right.
|
||||
* Returns 0 if the value is unchanged, 1 if changed, or a negative error.
|
||||
*
|
||||
* Returns: 0 if the value is unchanged, 1 if changed, or a negative error.
|
||||
*/
|
||||
static inline int
|
||||
snd_hdac_regmap_update_amp_stereo(struct hdac_device *codec, hda_nid_t nid,
|
||||
|
|
|
|||
|
|
@ -145,61 +145,60 @@ struct snd_pcm_ops {
|
|||
#define SNDRV_PCM_RATE_8000_768000 (SNDRV_PCM_RATE_8000_384000|\
|
||||
SNDRV_PCM_RATE_705600|\
|
||||
SNDRV_PCM_RATE_768000)
|
||||
#define _SNDRV_PCM_FMTBIT(fmt) (1ULL << (__force int)SNDRV_PCM_FORMAT_##fmt)
|
||||
#define SNDRV_PCM_FMTBIT_S8 _SNDRV_PCM_FMTBIT(S8)
|
||||
#define SNDRV_PCM_FMTBIT_U8 _SNDRV_PCM_FMTBIT(U8)
|
||||
#define SNDRV_PCM_FMTBIT_S16_LE _SNDRV_PCM_FMTBIT(S16_LE)
|
||||
#define SNDRV_PCM_FMTBIT_S16_BE _SNDRV_PCM_FMTBIT(S16_BE)
|
||||
#define SNDRV_PCM_FMTBIT_U16_LE _SNDRV_PCM_FMTBIT(U16_LE)
|
||||
#define SNDRV_PCM_FMTBIT_U16_BE _SNDRV_PCM_FMTBIT(U16_BE)
|
||||
#define SNDRV_PCM_FMTBIT_S24_LE _SNDRV_PCM_FMTBIT(S24_LE)
|
||||
#define SNDRV_PCM_FMTBIT_S24_BE _SNDRV_PCM_FMTBIT(S24_BE)
|
||||
#define SNDRV_PCM_FMTBIT_U24_LE _SNDRV_PCM_FMTBIT(U24_LE)
|
||||
#define SNDRV_PCM_FMTBIT_U24_BE _SNDRV_PCM_FMTBIT(U24_BE)
|
||||
#define SNDRV_PCM_FMTBIT_S8 (1ULL << SNDRV_PCM_FORMAT_S8)
|
||||
#define SNDRV_PCM_FMTBIT_U8 (1ULL << SNDRV_PCM_FORMAT_U8)
|
||||
#define SNDRV_PCM_FMTBIT_S16_LE (1ULL << SNDRV_PCM_FORMAT_S16_LE)
|
||||
#define SNDRV_PCM_FMTBIT_S16_BE (1ULL << SNDRV_PCM_FORMAT_S16_BE)
|
||||
#define SNDRV_PCM_FMTBIT_U16_LE (1ULL << SNDRV_PCM_FORMAT_U16_LE)
|
||||
#define SNDRV_PCM_FMTBIT_U16_BE (1ULL << SNDRV_PCM_FORMAT_U16_BE)
|
||||
#define SNDRV_PCM_FMTBIT_S24_LE (1ULL << SNDRV_PCM_FORMAT_S24_LE)
|
||||
#define SNDRV_PCM_FMTBIT_S24_BE (1ULL << SNDRV_PCM_FORMAT_S24_BE)
|
||||
#define SNDRV_PCM_FMTBIT_U24_LE (1ULL << SNDRV_PCM_FORMAT_U24_LE)
|
||||
#define SNDRV_PCM_FMTBIT_U24_BE (1ULL << SNDRV_PCM_FORMAT_U24_BE)
|
||||
// For S32/U32 formats, 'msbits' hardware parameter is often used to deliver information about the
|
||||
// available bit count in most significant bit. It's for the case of so-called 'left-justified' or
|
||||
// `right-padding` sample which has less width than 32 bit.
|
||||
#define SNDRV_PCM_FMTBIT_S32_LE _SNDRV_PCM_FMTBIT(S32_LE)
|
||||
#define SNDRV_PCM_FMTBIT_S32_BE _SNDRV_PCM_FMTBIT(S32_BE)
|
||||
#define SNDRV_PCM_FMTBIT_U32_LE _SNDRV_PCM_FMTBIT(U32_LE)
|
||||
#define SNDRV_PCM_FMTBIT_U32_BE _SNDRV_PCM_FMTBIT(U32_BE)
|
||||
#define SNDRV_PCM_FMTBIT_FLOAT_LE _SNDRV_PCM_FMTBIT(FLOAT_LE)
|
||||
#define SNDRV_PCM_FMTBIT_FLOAT_BE _SNDRV_PCM_FMTBIT(FLOAT_BE)
|
||||
#define SNDRV_PCM_FMTBIT_FLOAT64_LE _SNDRV_PCM_FMTBIT(FLOAT64_LE)
|
||||
#define SNDRV_PCM_FMTBIT_FLOAT64_BE _SNDRV_PCM_FMTBIT(FLOAT64_BE)
|
||||
#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE _SNDRV_PCM_FMTBIT(IEC958_SUBFRAME_LE)
|
||||
#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE _SNDRV_PCM_FMTBIT(IEC958_SUBFRAME_BE)
|
||||
#define SNDRV_PCM_FMTBIT_MU_LAW _SNDRV_PCM_FMTBIT(MU_LAW)
|
||||
#define SNDRV_PCM_FMTBIT_A_LAW _SNDRV_PCM_FMTBIT(A_LAW)
|
||||
#define SNDRV_PCM_FMTBIT_IMA_ADPCM _SNDRV_PCM_FMTBIT(IMA_ADPCM)
|
||||
#define SNDRV_PCM_FMTBIT_MPEG _SNDRV_PCM_FMTBIT(MPEG)
|
||||
#define SNDRV_PCM_FMTBIT_GSM _SNDRV_PCM_FMTBIT(GSM)
|
||||
#define SNDRV_PCM_FMTBIT_S20_LE _SNDRV_PCM_FMTBIT(S20_LE)
|
||||
#define SNDRV_PCM_FMTBIT_U20_LE _SNDRV_PCM_FMTBIT(U20_LE)
|
||||
#define SNDRV_PCM_FMTBIT_S20_BE _SNDRV_PCM_FMTBIT(S20_BE)
|
||||
#define SNDRV_PCM_FMTBIT_U20_BE _SNDRV_PCM_FMTBIT(U20_BE)
|
||||
#define SNDRV_PCM_FMTBIT_SPECIAL _SNDRV_PCM_FMTBIT(SPECIAL)
|
||||
#define SNDRV_PCM_FMTBIT_S24_3LE _SNDRV_PCM_FMTBIT(S24_3LE)
|
||||
#define SNDRV_PCM_FMTBIT_U24_3LE _SNDRV_PCM_FMTBIT(U24_3LE)
|
||||
#define SNDRV_PCM_FMTBIT_S24_3BE _SNDRV_PCM_FMTBIT(S24_3BE)
|
||||
#define SNDRV_PCM_FMTBIT_U24_3BE _SNDRV_PCM_FMTBIT(U24_3BE)
|
||||
#define SNDRV_PCM_FMTBIT_S20_3LE _SNDRV_PCM_FMTBIT(S20_3LE)
|
||||
#define SNDRV_PCM_FMTBIT_U20_3LE _SNDRV_PCM_FMTBIT(U20_3LE)
|
||||
#define SNDRV_PCM_FMTBIT_S20_3BE _SNDRV_PCM_FMTBIT(S20_3BE)
|
||||
#define SNDRV_PCM_FMTBIT_U20_3BE _SNDRV_PCM_FMTBIT(U20_3BE)
|
||||
#define SNDRV_PCM_FMTBIT_S18_3LE _SNDRV_PCM_FMTBIT(S18_3LE)
|
||||
#define SNDRV_PCM_FMTBIT_U18_3LE _SNDRV_PCM_FMTBIT(U18_3LE)
|
||||
#define SNDRV_PCM_FMTBIT_S18_3BE _SNDRV_PCM_FMTBIT(S18_3BE)
|
||||
#define SNDRV_PCM_FMTBIT_U18_3BE _SNDRV_PCM_FMTBIT(U18_3BE)
|
||||
#define SNDRV_PCM_FMTBIT_G723_24 _SNDRV_PCM_FMTBIT(G723_24)
|
||||
#define SNDRV_PCM_FMTBIT_G723_24_1B _SNDRV_PCM_FMTBIT(G723_24_1B)
|
||||
#define SNDRV_PCM_FMTBIT_G723_40 _SNDRV_PCM_FMTBIT(G723_40)
|
||||
#define SNDRV_PCM_FMTBIT_G723_40_1B _SNDRV_PCM_FMTBIT(G723_40_1B)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U8 _SNDRV_PCM_FMTBIT(DSD_U8)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U16_LE _SNDRV_PCM_FMTBIT(DSD_U16_LE)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U32_LE _SNDRV_PCM_FMTBIT(DSD_U32_LE)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U16_BE _SNDRV_PCM_FMTBIT(DSD_U16_BE)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U32_BE _SNDRV_PCM_FMTBIT(DSD_U32_BE)
|
||||
#define SNDRV_PCM_FMTBIT_S32_LE (1ULL << SNDRV_PCM_FORMAT_S32_LE)
|
||||
#define SNDRV_PCM_FMTBIT_S32_BE (1ULL << SNDRV_PCM_FORMAT_S32_BE)
|
||||
#define SNDRV_PCM_FMTBIT_U32_LE (1ULL << SNDRV_PCM_FORMAT_U32_LE)
|
||||
#define SNDRV_PCM_FMTBIT_U32_BE (1ULL << SNDRV_PCM_FORMAT_U32_BE)
|
||||
#define SNDRV_PCM_FMTBIT_FLOAT_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT_LE)
|
||||
#define SNDRV_PCM_FMTBIT_FLOAT_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT_BE)
|
||||
#define SNDRV_PCM_FMTBIT_FLOAT64_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_LE)
|
||||
#define SNDRV_PCM_FMTBIT_FLOAT64_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_BE)
|
||||
#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE)
|
||||
#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE)
|
||||
#define SNDRV_PCM_FMTBIT_MU_LAW (1ULL << SNDRV_PCM_FORMAT_MU_LAW)
|
||||
#define SNDRV_PCM_FMTBIT_A_LAW (1ULL << SNDRV_PCM_FORMAT_A_LAW)
|
||||
#define SNDRV_PCM_FMTBIT_IMA_ADPCM (1ULL << SNDRV_PCM_FORMAT_IMA_ADPCM)
|
||||
#define SNDRV_PCM_FMTBIT_MPEG (1ULL << SNDRV_PCM_FORMAT_MPEG)
|
||||
#define SNDRV_PCM_FMTBIT_GSM (1ULL << SNDRV_PCM_FORMAT_GSM)
|
||||
#define SNDRV_PCM_FMTBIT_S20_LE (1ULL << SNDRV_PCM_FORMAT_S20_LE)
|
||||
#define SNDRV_PCM_FMTBIT_U20_LE (1ULL << SNDRV_PCM_FORMAT_U20_LE)
|
||||
#define SNDRV_PCM_FMTBIT_S20_BE (1ULL << SNDRV_PCM_FORMAT_S20_BE)
|
||||
#define SNDRV_PCM_FMTBIT_U20_BE (1ULL << SNDRV_PCM_FORMAT_U20_BE)
|
||||
#define SNDRV_PCM_FMTBIT_SPECIAL (1ULL << SNDRV_PCM_FORMAT_SPECIAL)
|
||||
#define SNDRV_PCM_FMTBIT_S24_3LE (1ULL << SNDRV_PCM_FORMAT_S24_3LE)
|
||||
#define SNDRV_PCM_FMTBIT_U24_3LE (1ULL << SNDRV_PCM_FORMAT_U24_3LE)
|
||||
#define SNDRV_PCM_FMTBIT_S24_3BE (1ULL << SNDRV_PCM_FORMAT_S24_3BE)
|
||||
#define SNDRV_PCM_FMTBIT_U24_3BE (1ULL << SNDRV_PCM_FORMAT_U24_3BE)
|
||||
#define SNDRV_PCM_FMTBIT_S20_3LE (1ULL << SNDRV_PCM_FORMAT_S20_3LE)
|
||||
#define SNDRV_PCM_FMTBIT_U20_3LE (1ULL << SNDRV_PCM_FORMAT_U20_3LE)
|
||||
#define SNDRV_PCM_FMTBIT_S20_3BE (1ULL << SNDRV_PCM_FORMAT_S20_3BE)
|
||||
#define SNDRV_PCM_FMTBIT_U20_3BE (1ULL << SNDRV_PCM_FORMAT_U20_3BE)
|
||||
#define SNDRV_PCM_FMTBIT_S18_3LE (1ULL << SNDRV_PCM_FORMAT_S18_3LE)
|
||||
#define SNDRV_PCM_FMTBIT_U18_3LE (1ULL << SNDRV_PCM_FORMAT_U18_3LE)
|
||||
#define SNDRV_PCM_FMTBIT_S18_3BE (1ULL << SNDRV_PCM_FORMAT_S18_3BE)
|
||||
#define SNDRV_PCM_FMTBIT_U18_3BE (1ULL << SNDRV_PCM_FORMAT_U18_3BE)
|
||||
#define SNDRV_PCM_FMTBIT_G723_24 (1ULL << SNDRV_PCM_FORMAT_G723_24)
|
||||
#define SNDRV_PCM_FMTBIT_G723_24_1B (1ULL << SNDRV_PCM_FORMAT_G723_24_1B)
|
||||
#define SNDRV_PCM_FMTBIT_G723_40 (1ULL << SNDRV_PCM_FORMAT_G723_40)
|
||||
#define SNDRV_PCM_FMTBIT_G723_40_1B (1ULL << SNDRV_PCM_FORMAT_G723_40_1B)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U8 (1ULL << SNDRV_PCM_FORMAT_DSD_U8)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U16_LE (1ULL << SNDRV_PCM_FORMAT_DSD_U16_LE)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U32_LE (1ULL << SNDRV_PCM_FORMAT_DSD_U32_LE)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U16_BE (1ULL << SNDRV_PCM_FORMAT_DSD_U16_BE)
|
||||
#define SNDRV_PCM_FMTBIT_DSD_U32_BE (1ULL << SNDRV_PCM_FORMAT_DSD_U32_BE)
|
||||
|
||||
#ifdef SNDRV_LITTLE_ENDIAN
|
||||
#define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE
|
||||
|
|
@ -228,11 +227,10 @@ struct snd_pcm_ops {
|
|||
#define SNDRV_PCM_FMTBIT_U20 SNDRV_PCM_FMTBIT_U20_BE
|
||||
#endif
|
||||
|
||||
#define _SNDRV_PCM_SUBFMTBIT(fmt) BIT((__force int)SNDRV_PCM_SUBFORMAT_##fmt)
|
||||
#define SNDRV_PCM_SUBFMTBIT_STD _SNDRV_PCM_SUBFMTBIT(STD)
|
||||
#define SNDRV_PCM_SUBFMTBIT_MSBITS_MAX _SNDRV_PCM_SUBFMTBIT(MSBITS_MAX)
|
||||
#define SNDRV_PCM_SUBFMTBIT_MSBITS_20 _SNDRV_PCM_SUBFMTBIT(MSBITS_20)
|
||||
#define SNDRV_PCM_SUBFMTBIT_MSBITS_24 _SNDRV_PCM_SUBFMTBIT(MSBITS_24)
|
||||
#define SNDRV_PCM_SUBFMTBIT_STD (1U << SNDRV_PCM_SUBFORMAT_STD)
|
||||
#define SNDRV_PCM_SUBFMTBIT_MSBITS_MAX (1U << SNDRV_PCM_SUBFORMAT_MSBITS_MAX)
|
||||
#define SNDRV_PCM_SUBFMTBIT_MSBITS_20 (1U << SNDRV_PCM_SUBFORMAT_MSBITS_20)
|
||||
#define SNDRV_PCM_SUBFMTBIT_MSBITS_24 (1U << SNDRV_PCM_SUBFORMAT_MSBITS_24)
|
||||
|
||||
struct snd_pcm_file {
|
||||
struct snd_pcm_substream *substream;
|
||||
|
|
@ -1515,7 +1513,7 @@ int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream,
|
|||
*/
|
||||
static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format)
|
||||
{
|
||||
return 1ULL << (__force int) pcm_format;
|
||||
return 1ULL << pcm_format;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1523,9 +1521,7 @@ static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format)
|
|||
* @f: the iterator variable in snd_pcm_format_t type
|
||||
*/
|
||||
#define pcm_for_each_format(f) \
|
||||
for ((f) = SNDRV_PCM_FORMAT_FIRST; \
|
||||
(__force int)(f) <= (__force int)SNDRV_PCM_FORMAT_LAST; \
|
||||
(f) = (__force snd_pcm_format_t)((__force int)(f) + 1))
|
||||
for ((f) = SNDRV_PCM_FORMAT_FIRST; (f) <= SNDRV_PCM_FORMAT_LAST; (f)++)
|
||||
|
||||
/* printk helpers */
|
||||
#define pcm_err(pcm, fmt, args...) \
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ static inline void snd_mask_set(struct snd_mask *mask, unsigned int val)
|
|||
static inline void snd_mask_set_format(struct snd_mask *mask,
|
||||
snd_pcm_format_t format)
|
||||
{
|
||||
snd_mask_set(mask, (__force unsigned int)format);
|
||||
snd_mask_set(mask, format);
|
||||
}
|
||||
|
||||
static inline void snd_mask_reset(struct snd_mask *mask, unsigned int val)
|
||||
|
|
@ -132,7 +132,7 @@ static inline int snd_mask_test(const struct snd_mask *mask, unsigned int val)
|
|||
static inline int snd_mask_test_format(const struct snd_mask *mask,
|
||||
snd_pcm_format_t format)
|
||||
{
|
||||
return snd_mask_test(mask, (__force unsigned int)format);
|
||||
return snd_mask_test(mask, format);
|
||||
}
|
||||
|
||||
static inline int snd_mask_single(const struct snd_mask *mask)
|
||||
|
|
@ -302,8 +302,7 @@ static inline int snd_interval_eq(const struct snd_interval *i1, const struct sn
|
|||
*/
|
||||
static inline snd_pcm_access_t params_access(const struct snd_pcm_hw_params *p)
|
||||
{
|
||||
return (__force snd_pcm_access_t)snd_mask_min(hw_param_mask_c(p,
|
||||
SNDRV_PCM_HW_PARAM_ACCESS));
|
||||
return snd_mask_min(hw_param_mask_c(p, SNDRV_PCM_HW_PARAM_ACCESS));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -312,8 +311,7 @@ static inline snd_pcm_access_t params_access(const struct snd_pcm_hw_params *p)
|
|||
*/
|
||||
static inline snd_pcm_format_t params_format(const struct snd_pcm_hw_params *p)
|
||||
{
|
||||
return (__force snd_pcm_format_t)snd_mask_min(hw_param_mask_c(p,
|
||||
SNDRV_PCM_HW_PARAM_FORMAT));
|
||||
return snd_mask_min(hw_param_mask_c(p, SNDRV_PCM_HW_PARAM_FORMAT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -323,8 +321,7 @@ static inline snd_pcm_format_t params_format(const struct snd_pcm_hw_params *p)
|
|||
static inline snd_pcm_subformat_t
|
||||
params_subformat(const struct snd_pcm_hw_params *p)
|
||||
{
|
||||
return (__force snd_pcm_subformat_t)snd_mask_min(hw_param_mask_c(p,
|
||||
SNDRV_PCM_HW_PARAM_SUBFORMAT));
|
||||
return snd_mask_min(hw_param_mask_c(p, SNDRV_PCM_HW_PARAM_SUBFORMAT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -176,8 +176,9 @@ int snd_rawmidi_proceed(struct snd_rawmidi_substream *substream);
|
|||
/* main midi functions */
|
||||
|
||||
int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info);
|
||||
int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, int subdevice,
|
||||
int mode, struct snd_rawmidi_file *rfile);
|
||||
int snd_rawmidi_kernel_open_nested(struct snd_rawmidi *rmidi, int subdevice,
|
||||
int mode, struct snd_rawmidi_file *rfile,
|
||||
int depth);
|
||||
int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile);
|
||||
int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
|
||||
struct snd_rawmidi_params *params);
|
||||
|
|
@ -191,6 +192,15 @@ long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream,
|
|||
long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream,
|
||||
const unsigned char *buf, long count);
|
||||
|
||||
/* non-nested version */
|
||||
static inline int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi,
|
||||
int subdevice,
|
||||
int mode,
|
||||
struct snd_rawmidi_file *rfile)
|
||||
{
|
||||
return snd_rawmidi_kernel_open_nested(rmidi, subdevice, mode, rfile, 0);
|
||||
}
|
||||
|
||||
/* set up the tied devices */
|
||||
static inline void snd_rawmidi_tie_devices(struct snd_rawmidi *r1,
|
||||
struct snd_rawmidi *r2)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ struct snd_virmidi_dev {
|
|||
int client; /* created/attached client */
|
||||
int port; /* created/attached port */
|
||||
unsigned int flags; /* SNDRV_VIRMIDI_* */
|
||||
rwlock_t filelist_lock;
|
||||
struct rw_semaphore filelist_sem;
|
||||
struct list_head filelist;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -308,16 +308,6 @@ struct snd_seq_ump_event {
|
|||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* bounce event - stored as variable size data
|
||||
*/
|
||||
struct snd_seq_event_bounce {
|
||||
int err;
|
||||
struct snd_seq_event event;
|
||||
/* external data follows here. */
|
||||
};
|
||||
|
||||
|
||||
/* system information */
|
||||
struct snd_seq_system_info {
|
||||
int queues; /* maximum queues count */
|
||||
|
|
@ -348,10 +338,10 @@ struct snd_seq_running_info {
|
|||
|
||||
|
||||
/* client types */
|
||||
typedef int __bitwise snd_seq_client_type_t;
|
||||
#define NO_CLIENT ((__force snd_seq_client_type_t) 0)
|
||||
#define USER_CLIENT ((__force snd_seq_client_type_t) 1)
|
||||
#define KERNEL_CLIENT ((__force snd_seq_client_type_t) 2)
|
||||
typedef int snd_seq_client_type_t;
|
||||
#define NO_CLIENT 0
|
||||
#define USER_CLIENT 1
|
||||
#define KERNEL_CLIENT 2
|
||||
|
||||
/* event filter flags */
|
||||
#define SNDRV_SEQ_FILTER_BROADCAST (1U<<0) /* accept broadcast messages */
|
||||
|
|
|
|||
|
|
@ -169,72 +169,72 @@ enum {
|
|||
SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
|
||||
};
|
||||
|
||||
typedef int __bitwise snd_pcm_access_t;
|
||||
#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0) /* interleaved mmap */
|
||||
#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
|
||||
#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2) /* complex mmap */
|
||||
#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3) /* readi/writei */
|
||||
#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4) /* readn/writen */
|
||||
typedef int snd_pcm_access_t;
|
||||
#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED 0 /* interleaved mmap */
|
||||
#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED 1 /* noninterleaved mmap */
|
||||
#define SNDRV_PCM_ACCESS_MMAP_COMPLEX 2 /* complex mmap */
|
||||
#define SNDRV_PCM_ACCESS_RW_INTERLEAVED 3 /* readi/writei */
|
||||
#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED 4 /* readn/writen */
|
||||
#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
|
||||
|
||||
typedef int __bitwise snd_pcm_format_t;
|
||||
#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
|
||||
#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
|
||||
#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
|
||||
#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
|
||||
#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
|
||||
#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
|
||||
#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */
|
||||
#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */
|
||||
typedef int snd_pcm_format_t;
|
||||
#define SNDRV_PCM_FORMAT_S8 0
|
||||
#define SNDRV_PCM_FORMAT_U8 1
|
||||
#define SNDRV_PCM_FORMAT_S16_LE 2
|
||||
#define SNDRV_PCM_FORMAT_S16_BE 3
|
||||
#define SNDRV_PCM_FORMAT_U16_LE 4
|
||||
#define SNDRV_PCM_FORMAT_U16_BE 5
|
||||
#define SNDRV_PCM_FORMAT_S24_LE 6 /* low three bytes */
|
||||
#define SNDRV_PCM_FORMAT_S24_BE 7 /* low three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U24_LE 8 /* low three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U24_BE 9 /* low three bytes */
|
||||
/*
|
||||
* For S32/U32 formats, 'msbits' hardware parameter is often used to deliver information about the
|
||||
* available bit count in most significant bit. It's for the case of so-called 'left-justified' or
|
||||
* `right-padding` sample which has less width than 32 bit.
|
||||
*/
|
||||
#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
|
||||
#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
|
||||
#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
|
||||
#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
|
||||
#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
|
||||
#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
|
||||
#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
|
||||
#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
|
||||
#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
|
||||
#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
|
||||
#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
|
||||
#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
|
||||
#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
|
||||
#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
|
||||
#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
|
||||
#define SNDRV_PCM_FORMAT_S20_LE ((__force snd_pcm_format_t) 25) /* in four bytes, LSB justified */
|
||||
#define SNDRV_PCM_FORMAT_S20_BE ((__force snd_pcm_format_t) 26) /* in four bytes, LSB justified */
|
||||
#define SNDRV_PCM_FORMAT_U20_LE ((__force snd_pcm_format_t) 27) /* in four bytes, LSB justified */
|
||||
#define SNDRV_PCM_FORMAT_U20_BE ((__force snd_pcm_format_t) 28) /* in four bytes, LSB justified */
|
||||
#define SNDRV_PCM_FORMAT_S32_LE 10
|
||||
#define SNDRV_PCM_FORMAT_S32_BE 11
|
||||
#define SNDRV_PCM_FORMAT_U32_LE 12
|
||||
#define SNDRV_PCM_FORMAT_U32_BE 13
|
||||
#define SNDRV_PCM_FORMAT_FLOAT_LE 14 /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
|
||||
#define SNDRV_PCM_FORMAT_FLOAT_BE 15 /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
|
||||
#define SNDRV_PCM_FORMAT_FLOAT64_LE 16 /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
|
||||
#define SNDRV_PCM_FORMAT_FLOAT64_BE 17 /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
|
||||
#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE 18 /* IEC-958 subframe, Little Endian */
|
||||
#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE 19 /* IEC-958 subframe, Big Endian */
|
||||
#define SNDRV_PCM_FORMAT_MU_LAW 20
|
||||
#define SNDRV_PCM_FORMAT_A_LAW 21
|
||||
#define SNDRV_PCM_FORMAT_IMA_ADPCM 22
|
||||
#define SNDRV_PCM_FORMAT_MPEG 23
|
||||
#define SNDRV_PCM_FORMAT_GSM 24
|
||||
#define SNDRV_PCM_FORMAT_S20_LE 25 /* in four bytes, LSB justified */
|
||||
#define SNDRV_PCM_FORMAT_S20_BE 26 /* in four bytes, LSB justified */
|
||||
#define SNDRV_PCM_FORMAT_U20_LE 27 /* in four bytes, LSB justified */
|
||||
#define SNDRV_PCM_FORMAT_U20_BE 28 /* in four bytes, LSB justified */
|
||||
/* gap in the numbering for a future standard linear format */
|
||||
#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
|
||||
#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34) /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35) /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36) /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37) /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38) /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39) /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40) /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
|
||||
#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
|
||||
#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
|
||||
#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U32_LE ((__force snd_pcm_format_t) 50) /* DSD, 4-byte samples DSD (x32), little endian */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U16_BE ((__force snd_pcm_format_t) 51) /* DSD, 2-byte samples DSD (x16), big endian */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U32_BE ((__force snd_pcm_format_t) 52) /* DSD, 4-byte samples DSD (x32), big endian */
|
||||
#define SNDRV_PCM_FORMAT_SPECIAL 31
|
||||
#define SNDRV_PCM_FORMAT_S24_3LE 32 /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_S24_3BE 33 /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U24_3LE 34 /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U24_3BE 35 /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_S20_3LE 36 /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_S20_3BE 37 /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U20_3LE 38 /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U20_3BE 39 /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_S18_3LE 40 /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_S18_3BE 41 /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U18_3LE 42 /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_U18_3BE 43 /* in three bytes */
|
||||
#define SNDRV_PCM_FORMAT_G723_24 44 /* 8 samples in 3 bytes */
|
||||
#define SNDRV_PCM_FORMAT_G723_24_1B 45 /* 1 sample in 1 byte */
|
||||
#define SNDRV_PCM_FORMAT_G723_40 46 /* 8 Samples in 5 bytes */
|
||||
#define SNDRV_PCM_FORMAT_G723_40_1B 47 /* 1 sample in 1 byte */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U8 48 /* DSD, 1-byte samples DSD (x8) */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U16_LE 49 /* DSD, 2-byte samples DSD (x16), little endian */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U32_LE 50 /* DSD, 4-byte samples DSD (x32), little endian */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U16_BE 51 /* DSD, 2-byte samples DSD (x16), big endian */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U32_BE 52 /* DSD, 4-byte samples DSD (x32), big endian */
|
||||
#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U32_BE
|
||||
#define SNDRV_PCM_FORMAT_FIRST SNDRV_PCM_FORMAT_S8
|
||||
|
||||
|
|
@ -265,11 +265,11 @@ typedef int __bitwise snd_pcm_format_t;
|
|||
#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_BE
|
||||
#endif
|
||||
|
||||
typedef int __bitwise snd_pcm_subformat_t;
|
||||
#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
|
||||
#define SNDRV_PCM_SUBFORMAT_MSBITS_MAX ((__force snd_pcm_subformat_t) 1)
|
||||
#define SNDRV_PCM_SUBFORMAT_MSBITS_20 ((__force snd_pcm_subformat_t) 2)
|
||||
#define SNDRV_PCM_SUBFORMAT_MSBITS_24 ((__force snd_pcm_subformat_t) 3)
|
||||
typedef int snd_pcm_subformat_t;
|
||||
#define SNDRV_PCM_SUBFORMAT_STD 0
|
||||
#define SNDRV_PCM_SUBFORMAT_MSBITS_MAX 1
|
||||
#define SNDRV_PCM_SUBFORMAT_MSBITS_20 2
|
||||
#define SNDRV_PCM_SUBFORMAT_MSBITS_24 3
|
||||
#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_MSBITS_24
|
||||
|
||||
#define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */
|
||||
|
|
@ -303,16 +303,16 @@ typedef int __bitwise snd_pcm_subformat_t;
|
|||
#define __SND_STRUCT_TIME64
|
||||
#endif
|
||||
|
||||
typedef int __bitwise snd_pcm_state_t;
|
||||
#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
|
||||
#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */
|
||||
#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2) /* stream is ready to start */
|
||||
#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3) /* stream is running */
|
||||
#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4) /* stream reached an xrun */
|
||||
#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5) /* stream is draining */
|
||||
#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */
|
||||
#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */
|
||||
#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
|
||||
typedef int snd_pcm_state_t;
|
||||
#define SNDRV_PCM_STATE_OPEN 0 /* stream is open */
|
||||
#define SNDRV_PCM_STATE_SETUP 1 /* stream has a setup */
|
||||
#define SNDRV_PCM_STATE_PREPARED 2 /* stream is ready to start */
|
||||
#define SNDRV_PCM_STATE_RUNNING 3 /* stream is running */
|
||||
#define SNDRV_PCM_STATE_XRUN 4 /* stream reached an xrun */
|
||||
#define SNDRV_PCM_STATE_DRAINING 5 /* stream is draining */
|
||||
#define SNDRV_PCM_STATE_PAUSED 6 /* stream is paused */
|
||||
#define SNDRV_PCM_STATE_SUSPENDED 7 /* hardware is suspended */
|
||||
#define SNDRV_PCM_STATE_DISCONNECTED 8 /* hardware is disconnected */
|
||||
#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
|
||||
|
||||
enum {
|
||||
|
|
@ -1058,7 +1058,7 @@ struct snd_timer_tread {
|
|||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 9)
|
||||
#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10)
|
||||
|
||||
struct snd_ctl_card_info {
|
||||
int card; /* card number */
|
||||
|
|
@ -1072,24 +1072,43 @@ struct snd_ctl_card_info {
|
|||
unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */
|
||||
};
|
||||
|
||||
typedef int __bitwise snd_ctl_elem_type_t;
|
||||
#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */
|
||||
#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */
|
||||
#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2) /* integer type */
|
||||
#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3) /* enumerated type */
|
||||
#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4) /* byte array */
|
||||
#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
|
||||
#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
|
||||
/*
|
||||
* Card components can exceed the fixed 128 bytes in snd_ctl_card_info.
|
||||
* Use SNDRV_CTL_IOCTL_CARD_BYTES with type SND_CTL_CARD_BTYPE_COMPONENTS
|
||||
* to retrieve the full string.
|
||||
*/
|
||||
|
||||
/* Type values for struct snd_ctl_card_bytes::type */
|
||||
enum {
|
||||
SND_CTL_CARD_BTYPE_COMPONENTS = 1, /* full card components string */
|
||||
};
|
||||
|
||||
struct snd_ctl_card_bytes {
|
||||
__u32 type; /* SND_CTL_CARD_BTYPE_* */
|
||||
__u32 data_allocated; /* size of @data buffer in bytes */
|
||||
__u32 data_len; /* in/out: actual data length in bytes */
|
||||
__u32 reserved; /* explicit pad */
|
||||
__u64 data; /* user buffer (pointer stored as __u64) */
|
||||
};
|
||||
|
||||
typedef int snd_ctl_elem_type_t;
|
||||
#define SNDRV_CTL_ELEM_TYPE_NONE 0 /* invalid */
|
||||
#define SNDRV_CTL_ELEM_TYPE_BOOLEAN 1 /* boolean type */
|
||||
#define SNDRV_CTL_ELEM_TYPE_INTEGER 2 /* integer type */
|
||||
#define SNDRV_CTL_ELEM_TYPE_ENUMERATED 3 /* enumerated type */
|
||||
#define SNDRV_CTL_ELEM_TYPE_BYTES 4 /* byte array */
|
||||
#define SNDRV_CTL_ELEM_TYPE_IEC958 5 /* IEC958 (S/PDIF) setup */
|
||||
#define SNDRV_CTL_ELEM_TYPE_INTEGER64 6 /* 64-bit integer type */
|
||||
#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
|
||||
|
||||
typedef int __bitwise snd_ctl_elem_iface_t;
|
||||
#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0) /* global control */
|
||||
#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
|
||||
#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
|
||||
#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3) /* PCM device */
|
||||
#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
|
||||
#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5) /* timer device */
|
||||
#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
|
||||
typedef int snd_ctl_elem_iface_t;
|
||||
#define SNDRV_CTL_ELEM_IFACE_CARD 0 /* global control */
|
||||
#define SNDRV_CTL_ELEM_IFACE_HWDEP 1 /* hardware dependent device */
|
||||
#define SNDRV_CTL_ELEM_IFACE_MIXER 2 /* virtual mixer device */
|
||||
#define SNDRV_CTL_ELEM_IFACE_PCM 3 /* PCM device */
|
||||
#define SNDRV_CTL_ELEM_IFACE_RAWMIDI 4 /* RawMidi device */
|
||||
#define SNDRV_CTL_ELEM_IFACE_TIMER 5 /* timer device */
|
||||
#define SNDRV_CTL_ELEM_IFACE_SEQUENCER 6 /* sequencer client */
|
||||
#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
|
||||
|
||||
#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
|
||||
|
|
@ -1198,6 +1217,7 @@ struct snd_ctl_tlv {
|
|||
|
||||
#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
|
||||
#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
|
||||
#define SNDRV_CTL_IOCTL_CARD_BYTES _IOWR('U', 0x02, struct snd_ctl_card_bytes)
|
||||
#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
|
||||
#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
|
||||
#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
|
||||
|
|
|
|||
|
|
@ -79,11 +79,12 @@ struct snd_firewire_event_motu_register_dsp_change {
|
|||
*
|
||||
* @type: Fixed to SNDRV_FIREWIRE_EVENT_FF400_MESSAGE.
|
||||
* @message_count: The number of messages.
|
||||
* @messages: Array of @message_count messages
|
||||
* @messages.message: The messages expressing hardware knob operation.
|
||||
* @messages.tstamp: The isochronous cycle at which the request subaction of asynchronous
|
||||
* transaction was sent to deliver the message. It has 16 bit unsigned integer
|
||||
* transaction was sent to deliver the message. It has 16-bit unsigned integer
|
||||
* value. The higher 3 bits of value expresses the lower three bits of second
|
||||
* field in the format of CYCLE_TIME, up to 7. The rest 13 bits expresses cycle
|
||||
* field in the format of CYCLE_TIME, up to 7. The remaining 13 bits express cycle
|
||||
* field up to 7999.
|
||||
*
|
||||
* The structure expresses message transmitted by Fireface 400 when operating hardware knob.
|
||||
|
|
@ -191,8 +192,9 @@ struct snd_firewire_motu_register_dsp_meter {
|
|||
#define SNDRV_FIREWIRE_MOTU_REGISTER_DSP_ALIGNED_INPUT_COUNT (SNDRV_FIREWIRE_MOTU_REGISTER_DSP_INPUT_COUNT + 2)
|
||||
|
||||
/**
|
||||
* snd_firewire_motu_register_dsp_parameter - the container for parameters of DSP controlled
|
||||
* by register access.
|
||||
* struct snd_firewire_motu_register_dsp_parameter - the container for parameters
|
||||
* of DSP controlled by register access.
|
||||
* @mixer: aggregate of @mixer.source and @mixer.output
|
||||
* @mixer.source.gain: The gain of source to mixer.
|
||||
* @mixer.source.pan: The L/R balance of source to mixer.
|
||||
* @mixer.source.flag: The flag of source to mixer, including mute, solo.
|
||||
|
|
@ -200,21 +202,25 @@ struct snd_firewire_motu_register_dsp_meter {
|
|||
* Audio Express.
|
||||
* @mixer.source.paired_width: The width of paired source to mixer, only for 4 pre and
|
||||
* Audio Express.
|
||||
* @mixer.output: FIXME
|
||||
* @mixer.output.paired_volume: The volume of paired output from mixer.
|
||||
* @mixer.output.paired_flag: The flag of paired output from mixer.
|
||||
* @output: output parameters
|
||||
* @output.main_paired_volume: The volume of paired main output.
|
||||
* @output.hp_paired_volume: The volume of paired hp output.
|
||||
* @output.hp_paired_assignment: The source assigned to paired hp output.
|
||||
* @output.reserved: Padding for 32 bit alignment for future extension.
|
||||
* @output.reserved: Padding for 32-bit alignment for future extension.
|
||||
* @line_input: line input parameters
|
||||
* @line_input.boost_flag: The flags of boost for line inputs, only for 828mk2 and Traveler.
|
||||
* @line_input.nominal_level_flag: The flags of nominal level for line inputs, only for 828mk2 and
|
||||
* Traveler.
|
||||
* @line_input.reserved: Padding for 32 bit alignment for future extension.
|
||||
* @line_input.reserved: Padding for 32-bit alignment for future extension.
|
||||
* @input: input parameters
|
||||
* @input.gain_and_invert: The value including gain and invert for input, only for Ultralite, 4 pre
|
||||
* and Audio Express.
|
||||
* @input.flag: The flag of input; e.g. jack detection, phantom power, and pad, only for Ultralite,
|
||||
* 4 pre and Audio express.
|
||||
* @reserved: Padding so that the size of structure is kept to 512 byte, but for future extension.
|
||||
* @reserved: Padding so that the size of structure is kept to 512 bytes, but for future extension.
|
||||
*
|
||||
* The structure expresses the set of parameters for DSP controlled by register access.
|
||||
*/
|
||||
|
|
@ -272,8 +278,8 @@ struct snd_firewire_motu_register_dsp_parameter {
|
|||
* controlled by command
|
||||
* @data: Signal level meters. The mapping between position and signal channel is model-dependent.
|
||||
*
|
||||
* The structure expresses the part of DSP status for hardware meter. The 32 bit storage is
|
||||
* estimated to include IEEE 764 32 bit single precision floating point (binary32) value. It is
|
||||
* The structure expresses the part of DSP status for hardware meter. The 32-bit storage is
|
||||
* estimated to include IEEE 764 32-bit single precision floating point (binary32) value. It is
|
||||
* expected to be linear value (not logarithm) for audio signal level between 0.0 and +1.0.
|
||||
*/
|
||||
struct snd_firewire_motu_command_dsp_meter {
|
||||
|
|
|
|||
|
|
@ -693,7 +693,7 @@ static int atmel_ac97c_probe(struct platform_device *pdev)
|
|||
struct device *dev = &pdev->dev;
|
||||
struct snd_card *card;
|
||||
struct atmel_ac97c *chip;
|
||||
struct resource *regs;
|
||||
void __iomem *regs;
|
||||
struct clk *pclk;
|
||||
static const struct snd_ac97_bus_ops ops = {
|
||||
.write = atmel_ac97c_write,
|
||||
|
|
@ -702,42 +702,34 @@ static int atmel_ac97c_probe(struct platform_device *pdev)
|
|||
int retval;
|
||||
int irq;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!regs) {
|
||||
dev_dbg(&pdev->dev, "no memory resource\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_dbg(&pdev->dev, "could not get irq: %d\n", irq);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
}
|
||||
|
||||
pclk = clk_get(&pdev->dev, "ac97_clk");
|
||||
pclk = devm_clk_get_enabled(&pdev->dev, "ac97_clk");
|
||||
if (IS_ERR(pclk)) {
|
||||
dev_dbg(&pdev->dev, "no peripheral clock\n");
|
||||
return PTR_ERR(pclk);
|
||||
}
|
||||
retval = clk_prepare_enable(pclk);
|
||||
if (retval)
|
||||
goto err_prepare_enable;
|
||||
|
||||
retval = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1,
|
||||
retval = snd_devm_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1,
|
||||
SNDRV_DEFAULT_STR1, THIS_MODULE,
|
||||
sizeof(struct atmel_ac97c), &card);
|
||||
if (retval) {
|
||||
dev_dbg(&pdev->dev, "could not create sound card device\n");
|
||||
goto err_snd_card_new;
|
||||
return retval;
|
||||
}
|
||||
|
||||
chip = get_chip(card);
|
||||
|
||||
retval = request_irq(irq, atmel_ac97c_interrupt, 0, "AC97C", chip);
|
||||
if (retval) {
|
||||
dev_dbg(&pdev->dev, "unable to request irq %d\n", irq);
|
||||
goto err_request_irq;
|
||||
}
|
||||
retval = devm_request_irq(&pdev->dev, irq, atmel_ac97c_interrupt, 0, "AC97C", chip);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
chip->irq = irq;
|
||||
|
||||
spin_lock_init(&chip->lock);
|
||||
|
|
@ -749,13 +741,7 @@ static int atmel_ac97c_probe(struct platform_device *pdev)
|
|||
chip->card = card;
|
||||
chip->pclk = pclk;
|
||||
chip->pdev = pdev;
|
||||
chip->regs = ioremap(regs->start, resource_size(regs));
|
||||
|
||||
if (!chip->regs) {
|
||||
dev_dbg(&pdev->dev, "could not remap register memory\n");
|
||||
retval = -ENOMEM;
|
||||
goto err_ioremap;
|
||||
}
|
||||
chip->regs = regs;
|
||||
|
||||
chip->reset_pin = devm_gpiod_get_index(dev, "ac97", 2, GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(chip->reset_pin))
|
||||
|
|
@ -770,25 +756,25 @@ static int atmel_ac97c_probe(struct platform_device *pdev)
|
|||
retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus);
|
||||
if (retval) {
|
||||
dev_dbg(&pdev->dev, "could not register on ac97 bus\n");
|
||||
goto err_ac97_bus;
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = atmel_ac97c_mixer_new(chip);
|
||||
if (retval) {
|
||||
dev_dbg(&pdev->dev, "could not register ac97 mixer\n");
|
||||
goto err_ac97_bus;
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = atmel_ac97c_pcm_new(chip);
|
||||
if (retval) {
|
||||
dev_dbg(&pdev->dev, "could not register ac97 pcm device\n");
|
||||
goto err_ac97_bus;
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = snd_card_register(card);
|
||||
if (retval) {
|
||||
dev_dbg(&pdev->dev, "could not register sound card\n");
|
||||
goto err_ac97_bus;
|
||||
return retval;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, card);
|
||||
|
|
@ -797,18 +783,6 @@ static int atmel_ac97c_probe(struct platform_device *pdev)
|
|||
chip->regs, irq);
|
||||
|
||||
return 0;
|
||||
|
||||
err_ac97_bus:
|
||||
iounmap(chip->regs);
|
||||
err_ioremap:
|
||||
free_irq(irq, chip);
|
||||
err_request_irq:
|
||||
snd_card_free(card);
|
||||
err_snd_card_new:
|
||||
clk_disable_unprepare(pclk);
|
||||
err_prepare_enable:
|
||||
clk_put(pclk);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int atmel_ac97c_suspend(struct device *pdev)
|
||||
|
|
@ -839,13 +813,6 @@ static void atmel_ac97c_remove(struct platform_device *pdev)
|
|||
ac97c_writel(chip, CAMR, 0);
|
||||
ac97c_writel(chip, COMR, 0);
|
||||
ac97c_writel(chip, MR, 0);
|
||||
|
||||
clk_disable_unprepare(chip->pclk);
|
||||
clk_put(chip->pclk);
|
||||
iounmap(chip->regs);
|
||||
free_irq(chip->irq, chip);
|
||||
|
||||
snd_card_free(card);
|
||||
}
|
||||
|
||||
static struct platform_driver atmel_ac97c_driver = {
|
||||
|
|
|
|||
|
|
@ -1393,17 +1393,17 @@ static long snd_compr_ioctl_compat(struct file *file, unsigned int cmd,
|
|||
#endif
|
||||
|
||||
static const struct file_operations snd_compr_file_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = snd_compr_open,
|
||||
.release = snd_compr_free,
|
||||
.write = snd_compr_write,
|
||||
.read = snd_compr_read,
|
||||
.unlocked_ioctl = snd_compr_ioctl,
|
||||
.owner = THIS_MODULE,
|
||||
.open = snd_compr_open,
|
||||
.release = snd_compr_free,
|
||||
.write = snd_compr_write,
|
||||
.read = snd_compr_read,
|
||||
.unlocked_ioctl = snd_compr_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = snd_compr_ioctl_compat,
|
||||
.compat_ioctl = snd_compr_ioctl_compat,
|
||||
#endif
|
||||
.mmap = snd_compr_mmap,
|
||||
.poll = snd_compr_poll,
|
||||
.mmap = snd_compr_mmap,
|
||||
.poll = snd_compr_poll,
|
||||
};
|
||||
|
||||
static int snd_compress_dev_register(struct snd_device *device)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ struct snd_kctl_ioctl {
|
|||
snd_kctl_ioctl_func_t fioctl;
|
||||
};
|
||||
|
||||
static DECLARE_RWSEM(snd_ioctl_rwsem);
|
||||
DECLARE_RWSEM(snd_ioctl_rwsem);
|
||||
static DECLARE_RWSEM(snd_ctl_layer_rwsem);
|
||||
static LIST_HEAD(snd_control_ioctls);
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
|
@ -55,9 +55,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
|
|||
struct snd_ctl_file *ctl;
|
||||
int i, err;
|
||||
|
||||
err = stream_open(inode, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
stream_open(inode, file);
|
||||
|
||||
card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);
|
||||
if (!card) {
|
||||
|
|
@ -65,12 +63,10 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
|
|||
goto __error1;
|
||||
}
|
||||
err = snd_card_file_add(card, file);
|
||||
if (err < 0) {
|
||||
err = -ENODEV;
|
||||
if (err < 0)
|
||||
goto __error1;
|
||||
}
|
||||
if (!try_module_get(card->module)) {
|
||||
err = -EFAULT;
|
||||
err = -ENODEV;
|
||||
goto __error2;
|
||||
}
|
||||
ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
|
||||
|
|
@ -876,23 +872,81 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
|
|||
{
|
||||
struct snd_ctl_card_info *info __free(kfree) =
|
||||
kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
ssize_t n;
|
||||
|
||||
if (! info)
|
||||
return -ENOMEM;
|
||||
|
||||
static_assert(sizeof(info->components) >= 2);
|
||||
|
||||
scoped_guard(rwsem_read, &snd_ioctl_rwsem) {
|
||||
const char *components = card->components;
|
||||
|
||||
if (!components)
|
||||
components = "";
|
||||
|
||||
info->card = card->number;
|
||||
strscpy(info->id, card->id, sizeof(info->id));
|
||||
strscpy(info->driver, card->driver, sizeof(info->driver));
|
||||
strscpy(info->name, card->shortname, sizeof(info->name));
|
||||
strscpy(info->longname, card->longname, sizeof(info->longname));
|
||||
strscpy(info->mixername, card->mixername, sizeof(info->mixername));
|
||||
strscpy(info->components, card->components, sizeof(info->components));
|
||||
n = strscpy(info->components, components, sizeof(info->components));
|
||||
if (n < 0) // mark the truncation with '>' before NULL terminator
|
||||
info->components[sizeof(info->components) - 2] = '>';
|
||||
}
|
||||
if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_ctl_card_bytes(struct snd_card *card,
|
||||
struct snd_ctl_card_bytes *info,
|
||||
unsigned int __user *data_len_out)
|
||||
{
|
||||
unsigned int data_len;
|
||||
|
||||
switch (info->type) {
|
||||
case SND_CTL_CARD_BTYPE_COMPONENTS:
|
||||
scoped_guard(rwsem_read, &snd_ioctl_rwsem) {
|
||||
const char *components = card->components;
|
||||
|
||||
if (!components)
|
||||
components = "";
|
||||
|
||||
data_len = strlen(components) + 1;
|
||||
|
||||
if (!info->data || info->data_allocated == 0)
|
||||
break;
|
||||
|
||||
if (info->data_allocated < data_len)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_to_user(u64_to_user_ptr(info->data), components, data_len))
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (put_user(data_len, data_len_out))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_ctl_card_bytes_user(struct snd_card *card,
|
||||
struct snd_ctl_card_bytes __user *_info)
|
||||
{
|
||||
struct snd_ctl_card_bytes info;
|
||||
|
||||
if (copy_from_user(&info, _info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
|
||||
return snd_ctl_card_bytes(card, &info, &_info->data_len);
|
||||
}
|
||||
|
||||
static int snd_ctl_elem_list(struct snd_card *card,
|
||||
struct snd_ctl_elem_list *list)
|
||||
{
|
||||
|
|
@ -1990,6 +2044,8 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
|
|||
return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0;
|
||||
case SNDRV_CTL_IOCTL_CARD_INFO:
|
||||
return snd_ctl_card_info(card, ctl, cmd, argp);
|
||||
case SNDRV_CTL_IOCTL_CARD_BYTES:
|
||||
return snd_ctl_card_bytes_user(card, argp);
|
||||
case SNDRV_CTL_IOCTL_ELEM_LIST:
|
||||
return snd_ctl_elem_list_user(card, argp);
|
||||
case SNDRV_CTL_IOCTL_ELEM_INFO:
|
||||
|
|
@ -2339,16 +2395,15 @@ EXPORT_SYMBOL_GPL(snd_ctl_disconnect_layer);
|
|||
* INIT PART
|
||||
*/
|
||||
|
||||
static const struct file_operations snd_ctl_f_ops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.read = snd_ctl_read,
|
||||
.open = snd_ctl_open,
|
||||
.release = snd_ctl_release,
|
||||
.poll = snd_ctl_poll,
|
||||
.unlocked_ioctl = snd_ctl_ioctl,
|
||||
.compat_ioctl = snd_ctl_ioctl_compat,
|
||||
.fasync = snd_ctl_fasync,
|
||||
static const struct file_operations snd_ctl_f_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = snd_ctl_read,
|
||||
.open = snd_ctl_open,
|
||||
.release = snd_ctl_release,
|
||||
.poll = snd_ctl_poll,
|
||||
.unlocked_ioctl = snd_ctl_ioctl,
|
||||
.compat_ioctl = snd_ctl_ioctl_compat,
|
||||
.fasync = snd_ctl_fasync,
|
||||
};
|
||||
|
||||
/* call lops under rwsems; called from snd_ctl_dev_*() below() */
|
||||
|
|
|
|||
|
|
@ -226,8 +226,8 @@ static int copy_ctl_value_from_user(struct snd_card *card,
|
|||
if (type < 0)
|
||||
return type;
|
||||
|
||||
if (type == (__force int)SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
|
||||
type == (__force int)SNDRV_CTL_ELEM_TYPE_INTEGER) {
|
||||
if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
|
||||
type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
|
||||
for (i = 0; i < count; i++) {
|
||||
s32 __user *intp = valuep;
|
||||
int val;
|
||||
|
|
@ -236,7 +236,7 @@ static int copy_ctl_value_from_user(struct snd_card *card,
|
|||
data->value.integer.value[i] = val;
|
||||
}
|
||||
} else {
|
||||
size = get_elem_size((__force snd_ctl_elem_type_t)type, count);
|
||||
size = get_elem_size(type, count);
|
||||
if (size < 0) {
|
||||
dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
|
||||
return -EINVAL;
|
||||
|
|
@ -259,8 +259,8 @@ static int copy_ctl_value_to_user(void __user *userdata,
|
|||
struct snd_ctl_elem_value32 __user *data32 = userdata;
|
||||
int i, size;
|
||||
|
||||
if (type == (__force int)SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
|
||||
type == (__force int)SNDRV_CTL_ELEM_TYPE_INTEGER) {
|
||||
if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
|
||||
type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
|
||||
for (i = 0; i < count; i++) {
|
||||
s32 __user *intp = valuep;
|
||||
int val;
|
||||
|
|
@ -269,7 +269,7 @@ static int copy_ctl_value_to_user(void __user *userdata,
|
|||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
size = get_elem_size((__force snd_ctl_elem_type_t)type, count);
|
||||
size = get_elem_size(type, count);
|
||||
if (copy_to_user(valuep, data->value.bytes.data, size))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
|
@ -417,7 +417,7 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
|
|||
break;
|
||||
}
|
||||
return snd_ctl_elem_add(file, data, replace);
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct snd_ctl_elem_list32),
|
||||
|
|
@ -446,6 +446,7 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns
|
|||
switch (cmd) {
|
||||
case SNDRV_CTL_IOCTL_PVERSION:
|
||||
case SNDRV_CTL_IOCTL_CARD_INFO:
|
||||
case SNDRV_CTL_IOCTL_CARD_BYTES:
|
||||
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
|
||||
case SNDRV_CTL_IOCTL_POWER:
|
||||
case SNDRV_CTL_IOCTL_POWER_STATE:
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
|
|||
|
||||
if (!try_module_get(hw->card->module)) {
|
||||
snd_card_unref(hw->card);
|
||||
return -EFAULT;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
|
|
@ -323,18 +323,17 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
|
|||
|
||||
*/
|
||||
|
||||
static const struct file_operations snd_hwdep_f_ops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = snd_hwdep_llseek,
|
||||
.read = snd_hwdep_read,
|
||||
.write = snd_hwdep_write,
|
||||
.open = snd_hwdep_open,
|
||||
.release = snd_hwdep_release,
|
||||
.poll = snd_hwdep_poll,
|
||||
.unlocked_ioctl = snd_hwdep_ioctl,
|
||||
.compat_ioctl = snd_hwdep_ioctl_compat,
|
||||
.mmap = snd_hwdep_mmap,
|
||||
static const struct file_operations snd_hwdep_f_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = snd_hwdep_llseek,
|
||||
.read = snd_hwdep_read,
|
||||
.write = snd_hwdep_write,
|
||||
.open = snd_hwdep_open,
|
||||
.release = snd_hwdep_release,
|
||||
.poll = snd_hwdep_poll,
|
||||
.unlocked_ioctl = snd_hwdep_ioctl,
|
||||
.compat_ioctl = snd_hwdep_ioctl_compat,
|
||||
.mmap = snd_hwdep_mmap,
|
||||
};
|
||||
|
||||
static void snd_hwdep_free(struct snd_hwdep *hwdep)
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ static int alloc_info_private(struct snd_info_entry *entry,
|
|||
if (!entry || !entry->p)
|
||||
return -ENODEV;
|
||||
if (!try_module_get(entry->module))
|
||||
return -EFAULT;
|
||||
return -ENODEV;
|
||||
data = kzalloc_obj(*data);
|
||||
if (!data) {
|
||||
module_put(entry->module);
|
||||
|
|
|
|||
|
|
@ -466,20 +466,19 @@ static int snd_disconnect_fasync(int fd, struct file *file, int on)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
static const struct file_operations snd_shutdown_f_ops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = snd_disconnect_llseek,
|
||||
.read = snd_disconnect_read,
|
||||
.write = snd_disconnect_write,
|
||||
.release = snd_disconnect_release,
|
||||
.poll = snd_disconnect_poll,
|
||||
.unlocked_ioctl = snd_disconnect_ioctl,
|
||||
static const struct file_operations snd_shutdown_f_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = snd_disconnect_llseek,
|
||||
.read = snd_disconnect_read,
|
||||
.write = snd_disconnect_write,
|
||||
.release = snd_disconnect_release,
|
||||
.poll = snd_disconnect_poll,
|
||||
.unlocked_ioctl = snd_disconnect_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = snd_disconnect_ioctl,
|
||||
.compat_ioctl = snd_disconnect_ioctl,
|
||||
#endif
|
||||
.mmap = snd_disconnect_mmap,
|
||||
.fasync = snd_disconnect_fasync
|
||||
.mmap = snd_disconnect_mmap,
|
||||
.fasync = snd_disconnect_fasync
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -584,12 +583,17 @@ EXPORT_SYMBOL_GPL(snd_card_disconnect_sync);
|
|||
|
||||
static int snd_card_do_free(struct snd_card *card)
|
||||
{
|
||||
bool managed = card->managed;
|
||||
|
||||
card->releasing = true;
|
||||
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
|
||||
if (snd_mixer_oss_notify_callback)
|
||||
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
|
||||
#endif
|
||||
snd_device_free_all(card);
|
||||
kfree(card->components);
|
||||
card->components = NULL;
|
||||
card->components_alloc_size = 0;
|
||||
if (card->private_free)
|
||||
card->private_free(card);
|
||||
#ifdef CONFIG_SND_CTL_DEBUG
|
||||
|
|
@ -601,7 +605,7 @@ static int snd_card_do_free(struct snd_card *card)
|
|||
}
|
||||
if (card->release_completion)
|
||||
complete(card->release_completion);
|
||||
if (!card->managed)
|
||||
if (!managed)
|
||||
kfree(card);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -722,7 +726,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
|
|||
int len, loops;
|
||||
bool is_default = false;
|
||||
char *id;
|
||||
|
||||
|
||||
copy_valid_id_string(card, src, nid);
|
||||
id = card->id;
|
||||
|
||||
|
|
@ -1031,21 +1035,44 @@ int __init snd_card_info_init(void)
|
|||
*
|
||||
* Return: Zero otherwise a negative error code.
|
||||
*/
|
||||
|
||||
|
||||
int snd_component_add(struct snd_card *card, const char *component)
|
||||
{
|
||||
char *ptr;
|
||||
int len = strlen(component);
|
||||
unsigned int cur_len, need_len;
|
||||
|
||||
ptr = strstr(card->components, component);
|
||||
if (ptr != NULL) {
|
||||
if (ptr[len] == '\0' || ptr[len] == ' ') /* already there */
|
||||
return 1;
|
||||
guard(rwsem_write)(&snd_ioctl_rwsem);
|
||||
|
||||
if (card->components) {
|
||||
ptr = strstr(card->components, component);
|
||||
if (ptr) {
|
||||
if (ptr[len] == '\0' || ptr[len] == ' ') /* already there */
|
||||
return 1;
|
||||
}
|
||||
cur_len = strlen(card->components) + 1;
|
||||
} else {
|
||||
cur_len = 0;
|
||||
}
|
||||
if (strlen(card->components) + 1 + len + 1 > sizeof(card->components)) {
|
||||
|
||||
need_len = cur_len + len + 1;
|
||||
if (need_len > 512) {
|
||||
snd_BUG();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (need_len > card->components_alloc_size) {
|
||||
unsigned int new_alloc = roundup(need_len, 32);
|
||||
|
||||
ptr = krealloc(card->components, new_alloc, GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
if (!card->components)
|
||||
ptr[0] = '\0';
|
||||
card->components = ptr;
|
||||
card->components_alloc_size = new_alloc;
|
||||
}
|
||||
|
||||
if (card->components[0] != '\0')
|
||||
strcat(card->components, " ");
|
||||
strcat(card->components, component);
|
||||
|
|
|
|||
|
|
@ -303,41 +303,41 @@ static ssize_t jack_type_read(struct file *file,
|
|||
}
|
||||
|
||||
static const struct file_operations jack_type_fops = {
|
||||
.open = simple_open,
|
||||
.read = jack_type_read,
|
||||
.llseek = default_llseek,
|
||||
.open = simple_open,
|
||||
.read = jack_type_read,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct file_operations sw_inject_enable_fops = {
|
||||
.open = simple_open,
|
||||
.read = sw_inject_enable_read,
|
||||
.write = sw_inject_enable_write,
|
||||
.llseek = default_llseek,
|
||||
.open = simple_open,
|
||||
.read = sw_inject_enable_read,
|
||||
.write = sw_inject_enable_write,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static const struct file_operations jackin_inject_fops = {
|
||||
.open = simple_open,
|
||||
.write = jackin_inject_write,
|
||||
.llseek = default_llseek,
|
||||
.open = simple_open,
|
||||
.write = jackin_inject_write,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static const struct file_operations jack_kctl_id_fops = {
|
||||
.open = simple_open,
|
||||
.read = jack_kctl_id_read,
|
||||
.llseek = default_llseek,
|
||||
.open = simple_open,
|
||||
.read = jack_kctl_id_read,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static const struct file_operations jack_kctl_mask_bits_fops = {
|
||||
.open = simple_open,
|
||||
.read = jack_kctl_mask_bits_read,
|
||||
.llseek = default_llseek,
|
||||
.open = simple_open,
|
||||
.read = jack_kctl_mask_bits_read,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static const struct file_operations jack_kctl_status_fops = {
|
||||
.open = simple_open,
|
||||
.read = jack_kctl_status_read,
|
||||
.llseek = default_llseek,
|
||||
.open = simple_open,
|
||||
.read = jack_kctl_status_read,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
|
||||
|
|
|
|||
|
|
@ -30,9 +30,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
|
|||
struct snd_mixer_oss_file *fmixer;
|
||||
int err;
|
||||
|
||||
err = nonseekable_open(inode, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
nonseekable_open(inode, file);
|
||||
|
||||
card = snd_lookup_oss_minor_data(iminor(inode),
|
||||
SNDRV_OSS_DEVICE_TYPE_MIXER);
|
||||
|
|
@ -60,7 +58,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
|
|||
kfree(fmixer);
|
||||
snd_card_file_remove(card, file);
|
||||
snd_card_unref(card);
|
||||
return -EFAULT;
|
||||
return -ENODEV;
|
||||
}
|
||||
snd_card_unref(card);
|
||||
return 0;
|
||||
|
|
@ -407,13 +405,12 @@ static long snd_mixer_oss_ioctl_compat(struct file *file, unsigned int cmd,
|
|||
* REGISTRATION PART
|
||||
*/
|
||||
|
||||
static const struct file_operations snd_mixer_oss_f_ops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.open = snd_mixer_oss_open,
|
||||
.release = snd_mixer_oss_release,
|
||||
.unlocked_ioctl = snd_mixer_oss_ioctl,
|
||||
.compat_ioctl = snd_mixer_oss_ioctl_compat,
|
||||
static const struct file_operations snd_mixer_oss_f_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = snd_mixer_oss_open,
|
||||
.release = snd_mixer_oss_release,
|
||||
.unlocked_ioctl = snd_mixer_oss_ioctl,
|
||||
.compat_ioctl = snd_mixer_oss_ioctl_compat,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -879,11 +879,11 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
|
|||
_snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0);
|
||||
snd_mask_none(&mask);
|
||||
if (atomic_read(&substream->mmap_count))
|
||||
snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
|
||||
snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
|
||||
else {
|
||||
snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED);
|
||||
snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (!direct)
|
||||
snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
|
||||
snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
|
||||
}
|
||||
err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask);
|
||||
if (err < 0) {
|
||||
|
|
@ -909,7 +909,7 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
|
|||
else
|
||||
sformat = snd_pcm_plug_slave_format(format, sformat_mask);
|
||||
|
||||
if ((__force int)sformat < 0 ||
|
||||
if (sformat < 0 ||
|
||||
!snd_mask_test_format(sformat_mask, sformat)) {
|
||||
pcm_for_each_format(sformat) {
|
||||
if (snd_mask_test_format(sformat_mask, sformat) &&
|
||||
|
|
@ -921,7 +921,7 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
|
|||
goto failure;
|
||||
}
|
||||
format_found:
|
||||
err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, (__force int)sformat, 0);
|
||||
err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, sformat, 0);
|
||||
if (err < 0)
|
||||
goto failure;
|
||||
|
||||
|
|
@ -930,9 +930,9 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
|
|||
} else {
|
||||
_snd_pcm_hw_params_any(params);
|
||||
_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS,
|
||||
(__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
|
||||
SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
|
||||
_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT,
|
||||
(__force int)snd_pcm_oss_format_from(runtime->oss.format), 0);
|
||||
snd_pcm_oss_format_from(runtime->oss.format), 0);
|
||||
_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
runtime->oss.channels, 0);
|
||||
_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE,
|
||||
|
|
@ -1875,7 +1875,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
|
|||
format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
for (fmt = 0; fmt < 32; ++fmt) {
|
||||
if (snd_mask_test(format_mask, fmt)) {
|
||||
int f = snd_pcm_oss_format_to((__force snd_pcm_format_t)fmt);
|
||||
int f = snd_pcm_oss_format_to(fmt);
|
||||
if (f >= 0)
|
||||
formats |= f;
|
||||
}
|
||||
|
|
@ -2495,9 +2495,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
|
|||
int nonblock;
|
||||
wait_queue_entry_t wait;
|
||||
|
||||
err = nonseekable_open(inode, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
nonseekable_open(inode, file);
|
||||
|
||||
pcm = snd_lookup_oss_minor_data(iminor(inode),
|
||||
SNDRV_OSS_DEVICE_TYPE_PCM);
|
||||
|
|
@ -2509,7 +2507,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
|
|||
if (err < 0)
|
||||
goto __error1;
|
||||
if (!try_module_get(pcm->card->module)) {
|
||||
err = -EFAULT;
|
||||
err = -ENODEV;
|
||||
goto __error2;
|
||||
}
|
||||
if (snd_task_name(current, task_name, sizeof(task_name)) < 0) {
|
||||
|
|
@ -3129,17 +3127,16 @@ static inline void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
|
|||
* ENTRY functions
|
||||
*/
|
||||
|
||||
static const struct file_operations snd_pcm_oss_f_reg =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.read = snd_pcm_oss_read,
|
||||
.write = snd_pcm_oss_write,
|
||||
.open = snd_pcm_oss_open,
|
||||
.release = snd_pcm_oss_release,
|
||||
.poll = snd_pcm_oss_poll,
|
||||
.unlocked_ioctl = snd_pcm_oss_ioctl,
|
||||
.compat_ioctl = snd_pcm_oss_ioctl_compat,
|
||||
.mmap = snd_pcm_oss_mmap,
|
||||
static const struct file_operations snd_pcm_oss_f_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = snd_pcm_oss_read,
|
||||
.write = snd_pcm_oss_write,
|
||||
.open = snd_pcm_oss_open,
|
||||
.release = snd_pcm_oss_release,
|
||||
.poll = snd_pcm_oss_poll,
|
||||
.unlocked_ioctl = snd_pcm_oss_ioctl,
|
||||
.compat_ioctl = snd_pcm_oss_ioctl_compat,
|
||||
.mmap = snd_pcm_oss_mmap,
|
||||
};
|
||||
|
||||
static void register_oss_dsp(struct snd_pcm *pcm, int index)
|
||||
|
|
|
|||
|
|
@ -272,13 +272,13 @@ static int snd_pcm_plug_formats(const struct snd_mask *mask,
|
|||
SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE |
|
||||
SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
|
||||
SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
|
||||
snd_mask_set(&formats, (__force int)SNDRV_PCM_FORMAT_MU_LAW);
|
||||
snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW);
|
||||
|
||||
if (formats.bits[0] & lower_32_bits(linfmts))
|
||||
formats.bits[0] |= lower_32_bits(linfmts);
|
||||
if (formats.bits[1] & upper_32_bits(linfmts))
|
||||
formats.bits[1] |= upper_32_bits(linfmts);
|
||||
return snd_mask_test(&formats, (__force int)format);
|
||||
return snd_mask_test(&formats, format);
|
||||
}
|
||||
|
||||
static const snd_pcm_format_t preferred_formats[] = {
|
||||
|
|
@ -307,20 +307,20 @@ snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
|
|||
{
|
||||
int i;
|
||||
|
||||
if (snd_mask_test(format_mask, (__force int)format))
|
||||
if (snd_mask_test(format_mask, format))
|
||||
return format;
|
||||
if (!snd_pcm_plug_formats(format_mask, format))
|
||||
return (__force snd_pcm_format_t)-EINVAL;
|
||||
return -EINVAL;
|
||||
if (snd_pcm_format_linear(format)) {
|
||||
unsigned int width = snd_pcm_format_width(format);
|
||||
int unsignd = snd_pcm_format_unsigned(format) > 0;
|
||||
int big = snd_pcm_format_big_endian(format) > 0;
|
||||
unsigned int badness, best = -1;
|
||||
snd_pcm_format_t best_format = (__force snd_pcm_format_t)-1;
|
||||
snd_pcm_format_t best_format = -1;
|
||||
for (i = 0; i < ARRAY_SIZE(preferred_formats); i++) {
|
||||
snd_pcm_format_t f = preferred_formats[i];
|
||||
unsigned int w;
|
||||
if (!snd_mask_test(format_mask, (__force int)f))
|
||||
if (!snd_mask_test(format_mask, f))
|
||||
continue;
|
||||
w = snd_pcm_format_width(f);
|
||||
if (w >= width)
|
||||
|
|
@ -334,21 +334,21 @@ snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
|
|||
best = badness;
|
||||
}
|
||||
}
|
||||
if ((__force int)best_format >= 0)
|
||||
if (best_format >= 0)
|
||||
return best_format;
|
||||
else
|
||||
return (__force snd_pcm_format_t)-EINVAL;
|
||||
return -EINVAL;
|
||||
} else {
|
||||
switch (format) {
|
||||
case SNDRV_PCM_FORMAT_MU_LAW:
|
||||
for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) {
|
||||
snd_pcm_format_t format1 = preferred_formats[i];
|
||||
if (snd_mask_test(format_mask, (__force int)format1))
|
||||
if (snd_mask_test(format_mask, format1))
|
||||
return format1;
|
||||
}
|
||||
fallthrough;
|
||||
default:
|
||||
return (__force snd_pcm_format_t)-EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,11 +211,9 @@ static const char * const snd_pcm_format_names[] = {
|
|||
*/
|
||||
const char *snd_pcm_format_name(snd_pcm_format_t format)
|
||||
{
|
||||
unsigned int format_num = (__force unsigned int)format;
|
||||
|
||||
if (format_num >= ARRAY_SIZE(snd_pcm_format_names) || !snd_pcm_format_names[format_num])
|
||||
if (format >= ARRAY_SIZE(snd_pcm_format_names) || !snd_pcm_format_names[format])
|
||||
return "Unknown";
|
||||
return snd_pcm_format_names[format_num];
|
||||
return snd_pcm_format_names[format];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_pcm_format_name);
|
||||
|
||||
|
|
@ -275,12 +273,12 @@ static const char *snd_pcm_stream_name(int stream)
|
|||
|
||||
static const char *snd_pcm_access_name(snd_pcm_access_t access)
|
||||
{
|
||||
return snd_pcm_access_names[(__force int)access];
|
||||
return snd_pcm_access_names[access];
|
||||
}
|
||||
|
||||
static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat)
|
||||
{
|
||||
return snd_pcm_subformat_names[(__force int)subformat];
|
||||
return snd_pcm_subformat_names[subformat];
|
||||
}
|
||||
|
||||
static const char *snd_pcm_tstamp_mode_name(int mode)
|
||||
|
|
@ -290,7 +288,7 @@ static const char *snd_pcm_tstamp_mode_name(int mode)
|
|||
|
||||
static const char *snd_pcm_state_name(snd_pcm_state_t state)
|
||||
{
|
||||
return snd_pcm_state_names[(__force int)state];
|
||||
return snd_pcm_state_names[state];
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
|
||||
|
|
|
|||
|
|
@ -24,15 +24,12 @@ struct pcm_format_data {
|
|||
unsigned char silence[8]; /* silence data to fill */
|
||||
};
|
||||
|
||||
/* we do lots of calculations on snd_pcm_format_t; shut up sparse */
|
||||
#define INT __force int
|
||||
|
||||
static bool valid_format(snd_pcm_format_t format)
|
||||
{
|
||||
return (INT)format >= 0 && (INT)format <= (INT)SNDRV_PCM_FORMAT_LAST;
|
||||
return format >= 0 && format <= SNDRV_PCM_FORMAT_LAST;
|
||||
}
|
||||
|
||||
static const struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
|
||||
static const struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
|
||||
[SNDRV_PCM_FORMAT_S8] = {
|
||||
.width = 8, .phys = 8, .le = -1, .signd = 1,
|
||||
.silence = {},
|
||||
|
|
@ -251,7 +248,7 @@ int snd_pcm_format_signed(snd_pcm_format_t format)
|
|||
int val;
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
val = pcm_formats[(INT)format].signd;
|
||||
val = pcm_formats[format].signd;
|
||||
if (val < 0)
|
||||
return -EINVAL;
|
||||
return val;
|
||||
|
|
@ -300,7 +297,7 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format)
|
|||
int val;
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
val = pcm_formats[(INT)format].le;
|
||||
val = pcm_formats[format].le;
|
||||
if (val < 0)
|
||||
return -EINVAL;
|
||||
return val;
|
||||
|
|
@ -337,7 +334,7 @@ int snd_pcm_format_width(snd_pcm_format_t format)
|
|||
int val;
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
val = pcm_formats[(INT)format].width;
|
||||
val = pcm_formats[format].width;
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
return val;
|
||||
|
|
@ -356,7 +353,7 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format)
|
|||
int val;
|
||||
if (!valid_format(format))
|
||||
return -EINVAL;
|
||||
val = pcm_formats[(INT)format].phys;
|
||||
val = pcm_formats[format].phys;
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
return val;
|
||||
|
|
@ -390,9 +387,9 @@ const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
|
|||
{
|
||||
if (!valid_format(format))
|
||||
return NULL;
|
||||
if (! pcm_formats[(INT)format].phys)
|
||||
if (! pcm_formats[format].phys)
|
||||
return NULL;
|
||||
return pcm_formats[(INT)format].silence;
|
||||
return pcm_formats[format].silence;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_pcm_format_silence_64);
|
||||
|
||||
|
|
@ -416,12 +413,12 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
|
|||
return -EINVAL;
|
||||
if (samples == 0)
|
||||
return 0;
|
||||
width = pcm_formats[(INT)format].phys; /* physical width */
|
||||
width = pcm_formats[format].phys; /* physical width */
|
||||
if (!width)
|
||||
return -EINVAL;
|
||||
pat = pcm_formats[(INT)format].silence;
|
||||
pat = pcm_formats[format].silence;
|
||||
/* signed or 1 byte data */
|
||||
if (pcm_formats[(INT)format].signd == 1 || width <= 8) {
|
||||
if (pcm_formats[format].signd == 1 || width <= 8) {
|
||||
unsigned int bytes = samples * width / 8;
|
||||
memset(data, *pat, bytes);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
|
|||
}
|
||||
|
||||
/* macro for simplified cast */
|
||||
#define PARAM_MASK_BIT(b) (1U << (__force int)(b))
|
||||
#define PARAM_MASK_BIT(b) (1U << (b))
|
||||
|
||||
static bool hw_support_mmap(struct snd_pcm_substream *substream)
|
||||
{
|
||||
|
|
@ -489,7 +489,7 @@ static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
|
|||
params->msbits = snd_interval_value(i);
|
||||
m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
if (snd_mask_single(m)) {
|
||||
snd_pcm_format_t format = (__force snd_pcm_format_t)snd_mask_min(m);
|
||||
snd_pcm_format_t format = snd_mask_min(m);
|
||||
params->msbits = snd_pcm_format_width(format);
|
||||
}
|
||||
}
|
||||
|
|
@ -497,13 +497,13 @@ static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
|
|||
if (params->msbits) {
|
||||
m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
if (snd_mask_single(m)) {
|
||||
snd_pcm_format_t format = (__force snd_pcm_format_t)snd_mask_min(m);
|
||||
snd_pcm_format_t format = snd_mask_min(m);
|
||||
|
||||
if (snd_pcm_format_linear(format) &&
|
||||
snd_pcm_format_width(format) != params->msbits) {
|
||||
m_rw = hw_param_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT);
|
||||
snd_mask_reset(m_rw,
|
||||
(__force unsigned)SNDRV_PCM_SUBFORMAT_MSBITS_MAX);
|
||||
SNDRV_PCM_SUBFORMAT_MSBITS_MAX);
|
||||
if (snd_mask_empty(m_rw))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1252,7 +1252,7 @@ static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
|
|||
runtime->trigger_master = NULL;
|
||||
}
|
||||
|
||||
#define ACTION_ARG_IGNORE (__force snd_pcm_state_t)0
|
||||
#define ACTION_ARG_IGNORE 0
|
||||
|
||||
struct action_ops {
|
||||
int (*pre_action)(struct snd_pcm_substream *substream,
|
||||
|
|
@ -1635,7 +1635,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun);
|
|||
/*
|
||||
* pause callbacks: pass boolean (to start pause or resume) as state argument
|
||||
*/
|
||||
#define pause_pushed(state) (__force bool)(state)
|
||||
#define pause_pushed(state) (bool)(state)
|
||||
|
||||
static int snd_pcm_pre_pause(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
|
|
@ -1707,14 +1707,14 @@ static const struct action_ops snd_pcm_action_pause = {
|
|||
static int snd_pcm_pause(struct snd_pcm_substream *substream, bool push)
|
||||
{
|
||||
return snd_pcm_action(&snd_pcm_action_pause, substream,
|
||||
(__force snd_pcm_state_t)push);
|
||||
(snd_pcm_state_t)push);
|
||||
}
|
||||
|
||||
static int snd_pcm_pause_lock_irq(struct snd_pcm_substream *substream,
|
||||
bool push)
|
||||
{
|
||||
return snd_pcm_action_lock_irq(&snd_pcm_action_pause, substream,
|
||||
(__force snd_pcm_state_t)push);
|
||||
(snd_pcm_state_t)push);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
|
@ -1982,7 +1982,7 @@ static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
|
|||
snd_pcm_state_t state)
|
||||
{
|
||||
snd_pcm_state_t cur_state = snd_pcm_get_state(substream);
|
||||
int f_flags = (__force int)state;
|
||||
int f_flags = state;
|
||||
|
||||
if (cur_state == SNDRV_PCM_STATE_OPEN ||
|
||||
cur_state == SNDRV_PCM_STATE_DISCONNECTED)
|
||||
|
|
@ -2050,7 +2050,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
|
|||
|
||||
return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
|
||||
substream,
|
||||
(__force snd_pcm_state_t)f_flags);
|
||||
(snd_pcm_state_t)f_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2461,7 +2461,7 @@ static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
|
|||
if (bits <= 0)
|
||||
continue; /* ignore invalid formats */
|
||||
if ((unsigned)bits < i->min || (unsigned)bits > i->max)
|
||||
snd_mask_reset(&m, (__force unsigned)k);
|
||||
snd_mask_reset(&m, k);
|
||||
}
|
||||
return snd_mask_refine(mask, &m);
|
||||
}
|
||||
|
|
@ -2543,16 +2543,16 @@ static int snd_pcm_hw_rule_subformats(struct snd_pcm_hw_params *params,
|
|||
|
||||
snd_mask_none(&m);
|
||||
/* All PCMs support at least the default STD subformat. */
|
||||
snd_mask_set(&m, (__force unsigned)SNDRV_PCM_SUBFORMAT_STD);
|
||||
snd_mask_set(&m, SNDRV_PCM_SUBFORMAT_STD);
|
||||
|
||||
pcm_for_each_format(f) {
|
||||
if (!snd_mask_test(fmask, (__force unsigned)f))
|
||||
if (!snd_mask_test(fmask, f))
|
||||
continue;
|
||||
|
||||
if (f == SNDRV_PCM_FORMAT_S32_LE && *subformats)
|
||||
m.bits[0] |= *subformats;
|
||||
else if (snd_pcm_format_linear(f))
|
||||
snd_mask_set(&m, (__force unsigned)SNDRV_PCM_SUBFORMAT_MSBITS_MAX);
|
||||
snd_mask_set(&m, SNDRV_PCM_SUBFORMAT_MSBITS_MAX);
|
||||
}
|
||||
|
||||
return snd_mask_refine(sfmask, &m);
|
||||
|
|
@ -2880,9 +2880,10 @@ static int snd_pcm_open_file(struct file *file,
|
|||
static int snd_pcm_playback_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct snd_pcm *pcm;
|
||||
int err = nonseekable_open(inode, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
int err;
|
||||
|
||||
nonseekable_open(inode, file);
|
||||
|
||||
pcm = snd_lookup_minor_data(iminor(inode),
|
||||
SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
|
||||
err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
|
||||
|
|
@ -2894,9 +2895,10 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file)
|
|||
static int snd_pcm_capture_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct snd_pcm *pcm;
|
||||
int err = nonseekable_open(inode, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
int err;
|
||||
|
||||
nonseekable_open(inode, file);
|
||||
|
||||
pcm = snd_lookup_minor_data(iminor(inode),
|
||||
SNDRV_DEVICE_TYPE_PCM_CAPTURE);
|
||||
err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
|
||||
|
|
@ -2918,7 +2920,7 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
|
|||
if (err < 0)
|
||||
goto __error1;
|
||||
if (!try_module_get(pcm->card->module)) {
|
||||
err = -EFAULT;
|
||||
err = -ENODEV;
|
||||
goto __error2;
|
||||
}
|
||||
init_waitqueue_entry(&wait, current);
|
||||
|
|
@ -3914,6 +3916,8 @@ static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf)
|
|||
if (substream == NULL)
|
||||
return VM_FAULT_SIGBUS;
|
||||
runtime = substream->runtime;
|
||||
if (runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
|
||||
return VM_FAULT_SIGBUS;
|
||||
offset = vmf->pgoff << PAGE_SHIFT;
|
||||
dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
|
||||
if (offset > dma_bytes - PAGE_SIZE)
|
||||
|
|
@ -4239,29 +4243,29 @@ static unsigned long snd_pcm_get_unmapped_area(struct file *file,
|
|||
|
||||
const struct file_operations snd_pcm_f_ops[2] = {
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.write = snd_pcm_write,
|
||||
.write_iter = snd_pcm_writev,
|
||||
.open = snd_pcm_playback_open,
|
||||
.release = snd_pcm_release,
|
||||
.poll = snd_pcm_poll,
|
||||
.unlocked_ioctl = snd_pcm_ioctl,
|
||||
.compat_ioctl = snd_pcm_ioctl_compat,
|
||||
.mmap = snd_pcm_mmap,
|
||||
.fasync = snd_pcm_fasync,
|
||||
.get_unmapped_area = snd_pcm_get_unmapped_area,
|
||||
.owner = THIS_MODULE,
|
||||
.write = snd_pcm_write,
|
||||
.write_iter = snd_pcm_writev,
|
||||
.open = snd_pcm_playback_open,
|
||||
.release = snd_pcm_release,
|
||||
.poll = snd_pcm_poll,
|
||||
.unlocked_ioctl = snd_pcm_ioctl,
|
||||
.compat_ioctl = snd_pcm_ioctl_compat,
|
||||
.mmap = snd_pcm_mmap,
|
||||
.fasync = snd_pcm_fasync,
|
||||
.get_unmapped_area = snd_pcm_get_unmapped_area,
|
||||
},
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.read = snd_pcm_read,
|
||||
.read_iter = snd_pcm_readv,
|
||||
.open = snd_pcm_capture_open,
|
||||
.release = snd_pcm_release,
|
||||
.poll = snd_pcm_poll,
|
||||
.unlocked_ioctl = snd_pcm_ioctl,
|
||||
.compat_ioctl = snd_pcm_ioctl_compat,
|
||||
.mmap = snd_pcm_mmap,
|
||||
.fasync = snd_pcm_fasync,
|
||||
.get_unmapped_area = snd_pcm_get_unmapped_area,
|
||||
.owner = THIS_MODULE,
|
||||
.read = snd_pcm_read,
|
||||
.read_iter = snd_pcm_readv,
|
||||
.open = snd_pcm_capture_open,
|
||||
.release = snd_pcm_release,
|
||||
.poll = snd_pcm_poll,
|
||||
.unlocked_ioctl = snd_pcm_ioctl,
|
||||
.compat_ioctl = snd_pcm_ioctl_compat,
|
||||
.mmap = snd_pcm_mmap,
|
||||
.fasync = snd_pcm_fasync,
|
||||
.get_unmapped_area = snd_pcm_get_unmapped_area,
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -408,9 +408,10 @@ static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* called from sound/core/seq/seq_midi.c */
|
||||
int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, int subdevice,
|
||||
int mode, struct snd_rawmidi_file *rfile)
|
||||
/* called from sound/core/seq/seq_midi.c and sound/core/ump.c */
|
||||
int snd_rawmidi_kernel_open_nested(struct snd_rawmidi *rmidi, int subdevice,
|
||||
int mode, struct snd_rawmidi_file *rfile,
|
||||
int depth)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
|
@ -419,13 +420,14 @@ int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, int subdevice,
|
|||
if (!try_module_get(rmidi->card->module))
|
||||
return -ENXIO;
|
||||
|
||||
guard(mutex)(&rmidi->open_mutex);
|
||||
mutex_lock_nested(&rmidi->open_mutex, depth);
|
||||
err = rawmidi_open_priv(rmidi, subdevice, mode, rfile);
|
||||
if (err < 0)
|
||||
module_put(rmidi->card->module);
|
||||
mutex_unlock(&rmidi->open_mutex);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_rawmidi_kernel_open);
|
||||
EXPORT_SYMBOL(snd_rawmidi_kernel_open_nested);
|
||||
|
||||
static int snd_rawmidi_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
|
|
@ -441,9 +443,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
|
|||
if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
|
||||
return -EINVAL; /* invalid combination */
|
||||
|
||||
err = stream_open(inode, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
stream_open(inode, file);
|
||||
|
||||
if (maj == snd_major) {
|
||||
rmidi = snd_lookup_minor_data(iminor(inode),
|
||||
|
|
@ -1784,14 +1784,14 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
|
|||
*/
|
||||
|
||||
static const struct file_operations snd_rawmidi_f_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = snd_rawmidi_read,
|
||||
.write = snd_rawmidi_write,
|
||||
.open = snd_rawmidi_open,
|
||||
.release = snd_rawmidi_release,
|
||||
.poll = snd_rawmidi_poll,
|
||||
.unlocked_ioctl = snd_rawmidi_ioctl,
|
||||
.compat_ioctl = snd_rawmidi_ioctl_compat,
|
||||
.owner = THIS_MODULE,
|
||||
.read = snd_rawmidi_read,
|
||||
.write = snd_rawmidi_write,
|
||||
.open = snd_rawmidi_open,
|
||||
.release = snd_rawmidi_release,
|
||||
.poll = snd_rawmidi_poll,
|
||||
.unlocked_ioctl = snd_rawmidi_ioctl,
|
||||
.compat_ioctl = snd_rawmidi_ioctl_compat,
|
||||
};
|
||||
|
||||
static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,
|
||||
|
|
|
|||
|
|
@ -206,17 +206,16 @@ odev_poll(struct file *file, poll_table * wait)
|
|||
* registration of sequencer minor device
|
||||
*/
|
||||
|
||||
static const struct file_operations seq_oss_f_ops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.read = odev_read,
|
||||
.write = odev_write,
|
||||
.open = odev_open,
|
||||
.release = odev_release,
|
||||
.poll = odev_poll,
|
||||
.unlocked_ioctl = odev_ioctl,
|
||||
.compat_ioctl = odev_ioctl_compat,
|
||||
.llseek = noop_llseek,
|
||||
static const struct file_operations seq_oss_f_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = odev_read,
|
||||
.write = odev_write,
|
||||
.open = odev_open,
|
||||
.release = odev_release,
|
||||
.poll = odev_poll,
|
||||
.unlocked_ioctl = odev_ioctl,
|
||||
.compat_ioctl = odev_ioctl_compat,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
|
||||
static int __init
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ static DEFINE_MUTEX(register_mutex);
|
|||
* client table
|
||||
*/
|
||||
static char clienttablock[SNDRV_SEQ_MAX_CLIENTS];
|
||||
static struct snd_seq_client *clienttab[SNDRV_SEQ_MAX_CLIENTS];
|
||||
static struct snd_seq_client __rcu *clienttab[SNDRV_SEQ_MAX_CLIENTS];
|
||||
static struct snd_seq_usage client_usage;
|
||||
|
||||
/*
|
||||
|
|
@ -95,15 +95,23 @@ static inline int snd_seq_write_pool_allocated(struct snd_seq_client *client)
|
|||
return snd_seq_total_cells(client->pool) > 0;
|
||||
}
|
||||
|
||||
/* return pointer to client structure for specified id */
|
||||
static struct snd_seq_client *clientptr(int clientid)
|
||||
/* return pointer to client structure for specified id; call under RCU read-lock */
|
||||
static struct snd_seq_client *__clientptr(int clientid)
|
||||
{
|
||||
if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) {
|
||||
pr_debug("ALSA: seq: oops. Trying to get pointer to client %d\n",
|
||||
clientid);
|
||||
return NULL;
|
||||
}
|
||||
return clienttab[clientid];
|
||||
return rcu_dereference_check(clienttab[clientid],
|
||||
lockdep_is_held(&clients_lock));
|
||||
}
|
||||
|
||||
/* return pointer to client structure for specified id */
|
||||
static struct snd_seq_client *clientptr(int clientid)
|
||||
{
|
||||
guard(rcu)();
|
||||
return __clientptr(clientid);
|
||||
}
|
||||
|
||||
static struct snd_seq_client *client_use_ptr(int clientid, bool load_module)
|
||||
|
|
@ -115,8 +123,8 @@ static struct snd_seq_client *client_use_ptr(int clientid, bool load_module)
|
|||
clientid);
|
||||
return NULL;
|
||||
}
|
||||
scoped_guard(spinlock_irqsave, &clients_lock) {
|
||||
client = clientptr(clientid);
|
||||
scoped_guard(rcu) {
|
||||
client = __clientptr(clientid);
|
||||
if (client)
|
||||
return snd_seq_client_ref(client);
|
||||
if (clienttablock[clientid])
|
||||
|
|
@ -150,8 +158,8 @@ static struct snd_seq_client *client_use_ptr(int clientid, bool load_module)
|
|||
snd_seq_device_load_drivers();
|
||||
}
|
||||
}
|
||||
scoped_guard(spinlock_irqsave, &clients_lock) {
|
||||
client = clientptr(clientid);
|
||||
scoped_guard(rcu) {
|
||||
client = __clientptr(clientid);
|
||||
if (client)
|
||||
return snd_seq_client_ref(client);
|
||||
}
|
||||
|
|
@ -212,7 +220,6 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
|
|||
}
|
||||
client->type = NO_CLIENT;
|
||||
snd_use_lock_init(&client->use_lock);
|
||||
rwlock_init(&client->ports_lock);
|
||||
mutex_init(&client->ports_mutex);
|
||||
INIT_LIST_HEAD(&client->ports_list_head);
|
||||
mutex_init(&client->ioctl_mutex);
|
||||
|
|
@ -224,14 +231,17 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
|
|||
for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN;
|
||||
c < SNDRV_SEQ_MAX_CLIENTS;
|
||||
c++) {
|
||||
if (clienttab[c] || clienttablock[c])
|
||||
if (rcu_access_pointer(clienttab[c]) || clienttablock[c])
|
||||
continue;
|
||||
clienttab[client->number = c] = client;
|
||||
client->number = c;
|
||||
rcu_assign_pointer(clienttab[c], client);
|
||||
return client;
|
||||
}
|
||||
} else {
|
||||
if (clienttab[client_index] == NULL && !clienttablock[client_index]) {
|
||||
clienttab[client->number = client_index] = client;
|
||||
if (rcu_access_pointer(clienttab[client_index]) == NULL &&
|
||||
!clienttablock[client_index]) {
|
||||
client->number = client_index;
|
||||
rcu_assign_pointer(clienttab[client_index], client);
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
|
@ -249,10 +259,16 @@ static int seq_free_client1(struct snd_seq_client *client)
|
|||
return 0;
|
||||
scoped_guard(spinlock_irq, &clients_lock) {
|
||||
clienttablock[client->number] = 1;
|
||||
clienttab[client->number] = NULL;
|
||||
rcu_assign_pointer(clienttab[client->number], NULL);
|
||||
}
|
||||
snd_seq_delete_all_ports(client);
|
||||
snd_seq_queue_client_leave(client->number);
|
||||
/* the client has been unpublished from the table; wait for a grace
|
||||
* period so that lockless readers (snd_seq_client_use_ptr()) that
|
||||
* observed the old pointer can no longer take a new use_lock
|
||||
* reference, then drain the outstanding references before freeing
|
||||
*/
|
||||
synchronize_rcu();
|
||||
snd_use_lock_sync(&client->use_lock);
|
||||
if (client->pool)
|
||||
snd_seq_pool_delete(&client->pool);
|
||||
|
|
@ -296,11 +312,8 @@ static int snd_seq_open(struct inode *inode, struct file *file)
|
|||
int c, mode; /* client id */
|
||||
struct snd_seq_client *client;
|
||||
struct snd_seq_user_client *user;
|
||||
int err;
|
||||
|
||||
err = stream_open(inode, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
stream_open(inode, file);
|
||||
|
||||
scoped_guard(mutex, ®ister_mutex) {
|
||||
client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS);
|
||||
|
|
@ -517,9 +530,8 @@ static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event)
|
|||
* Return the error event.
|
||||
*
|
||||
* If the receiver client is a user client, the original event is
|
||||
* encapsulated in SNDRV_SEQ_EVENT_BOUNCE as variable length event. If
|
||||
* the original event is also variable length, the external data is
|
||||
* copied after the event record.
|
||||
* encapsulated in SNDRV_SEQ_EVENT_BOUNCE as variable length event. The
|
||||
* external data of a variable length event is not copied along.
|
||||
* If the receiver client is a kernel client, the original event is
|
||||
* quoted in SNDRV_SEQ_EVENT_KERNEL_ERROR, since this requires no extra
|
||||
* kmalloc.
|
||||
|
|
@ -528,7 +540,7 @@ static int bounce_error_event(struct snd_seq_client *client,
|
|||
struct snd_seq_event *event,
|
||||
int err, int atomic, int hop)
|
||||
{
|
||||
struct snd_seq_event bounce_ev;
|
||||
struct snd_seq_event bounce_ev, quoted;
|
||||
int result;
|
||||
|
||||
if (client == NULL ||
|
||||
|
|
@ -548,15 +560,19 @@ static int bounce_error_event(struct snd_seq_client *client,
|
|||
* For user clients, send SNDRV_SEQ_EVENT_BOUNCE with the
|
||||
* original event embedded as variable-length data. This
|
||||
* avoids exposing data.quote.event (a kernel pointer) to
|
||||
* userspace. The variable-length path in snd_seq_event_dup()
|
||||
* copies the event data from data.ext.ptr into chained cells,
|
||||
* and snd_seq_expand_var_event() copies only the data content
|
||||
* -- never the pointer -- to userspace.
|
||||
* userspace. Sanitise the embedded copy too - a queued
|
||||
* variable-length event carries the address of its own
|
||||
* extension cell, and the payload goes out verbatim.
|
||||
*/
|
||||
quoted = *event;
|
||||
if (snd_seq_ev_is_variable("ed)) {
|
||||
quoted.data.ext.len &= ~SNDRV_SEQ_EXT_MASK;
|
||||
quoted.data.ext.ptr = NULL;
|
||||
}
|
||||
bounce_ev.type = SNDRV_SEQ_EVENT_BOUNCE;
|
||||
bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
|
||||
bounce_ev.data.ext.len = sizeof(struct snd_seq_event);
|
||||
bounce_ev.data.ext.ptr = (char *)event;
|
||||
bounce_ev.data.ext.ptr = (char *)"ed;
|
||||
} else {
|
||||
/*
|
||||
* For kernel clients, quote the event pointer directly.
|
||||
|
|
@ -720,10 +736,11 @@ static int __deliver_to_subscribers(struct snd_seq_client *client,
|
|||
|
||||
/* lock list */
|
||||
if (atomic)
|
||||
read_lock(&grp->list_lock);
|
||||
rcu_read_lock();
|
||||
else
|
||||
down_read_nested(&grp->list_mutex, hop);
|
||||
list_for_each_entry(subs, &grp->list_head, src_list) {
|
||||
hlist_for_each_entry_rcu(subs, &grp->list_head, src_list,
|
||||
lockdep_is_held(&grp->list_mutex)) {
|
||||
/* both ports ready? */
|
||||
if (atomic_read(&subs->ref_count) != 2)
|
||||
continue;
|
||||
|
|
@ -744,7 +761,7 @@ static int __deliver_to_subscribers(struct snd_seq_client *client,
|
|||
memcpy(event, &event_saved, saved_size);
|
||||
}
|
||||
if (atomic)
|
||||
read_unlock(&grp->list_lock);
|
||||
rcu_read_unlock();
|
||||
else
|
||||
up_read(&grp->list_mutex);
|
||||
memcpy(event, &event_saved, saved_size);
|
||||
|
|
@ -1941,7 +1958,7 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
|
|||
{
|
||||
struct snd_seq_query_subs *subs = arg;
|
||||
struct snd_seq_port_subs_info *group;
|
||||
struct list_head *p;
|
||||
struct hlist_node *p;
|
||||
int i;
|
||||
|
||||
struct snd_seq_client *cptr __free(snd_seq_client) =
|
||||
|
|
@ -1968,15 +1985,15 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
|
|||
/* search for the subscriber */
|
||||
subs->num_subs = group->count;
|
||||
i = 0;
|
||||
list_for_each(p, &group->list_head) {
|
||||
hlist_for_each(p, &group->list_head) {
|
||||
if (i++ == subs->index) {
|
||||
/* found! */
|
||||
struct snd_seq_subscribers *s;
|
||||
if (subs->type == SNDRV_SEQ_QUERY_SUBS_READ) {
|
||||
s = list_entry(p, struct snd_seq_subscribers, src_list);
|
||||
s = hlist_entry(p, struct snd_seq_subscribers, src_list);
|
||||
subs->addr = s->info.dest;
|
||||
} else {
|
||||
s = list_entry(p, struct snd_seq_subscribers, dest_list);
|
||||
s = hlist_entry(p, struct snd_seq_subscribers, dest_list);
|
||||
subs->addr = s->info.sender;
|
||||
}
|
||||
subs->flags = s->info.flags;
|
||||
|
|
@ -2532,19 +2549,19 @@ static void snd_seq_info_dump_subscribers(struct snd_info_buffer *buffer,
|
|||
struct snd_seq_port_subs_info *group,
|
||||
int is_src, char *msg)
|
||||
{
|
||||
struct list_head *p;
|
||||
struct hlist_node *p;
|
||||
struct snd_seq_subscribers *s;
|
||||
int count = 0;
|
||||
|
||||
guard(rwsem_read)(&group->list_mutex);
|
||||
if (list_empty(&group->list_head))
|
||||
if (hlist_empty(&group->list_head))
|
||||
return;
|
||||
snd_iprintf(buffer, msg);
|
||||
list_for_each(p, &group->list_head) {
|
||||
hlist_for_each(p, &group->list_head) {
|
||||
if (is_src)
|
||||
s = list_entry(p, struct snd_seq_subscribers, src_list);
|
||||
s = hlist_entry(p, struct snd_seq_subscribers, src_list);
|
||||
else
|
||||
s = list_entry(p, struct snd_seq_subscribers, dest_list);
|
||||
s = hlist_entry(p, struct snd_seq_subscribers, dest_list);
|
||||
if (count++)
|
||||
snd_iprintf(buffer, ", ");
|
||||
snd_iprintf(buffer, "%d:%d",
|
||||
|
|
@ -2666,16 +2683,15 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry,
|
|||
* REGISTRATION PART
|
||||
*/
|
||||
|
||||
static const struct file_operations snd_seq_f_ops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.read = snd_seq_read,
|
||||
.write = snd_seq_write,
|
||||
.open = snd_seq_open,
|
||||
.release = snd_seq_release,
|
||||
.poll = snd_seq_poll,
|
||||
.unlocked_ioctl = snd_seq_ioctl,
|
||||
.compat_ioctl = snd_seq_ioctl_compat,
|
||||
static const struct file_operations snd_seq_f_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = snd_seq_read,
|
||||
.write = snd_seq_write,
|
||||
.open = snd_seq_open,
|
||||
.release = snd_seq_release,
|
||||
.poll = snd_seq_poll,
|
||||
.unlocked_ioctl = snd_seq_ioctl,
|
||||
.compat_ioctl = snd_seq_ioctl_compat,
|
||||
};
|
||||
|
||||
static struct device *seq_dev;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ struct snd_seq_client {
|
|||
/* ports */
|
||||
int num_ports; /* number of ports */
|
||||
struct list_head ports_list_head;
|
||||
rwlock_t ports_lock;
|
||||
struct mutex ports_mutex;
|
||||
struct mutex ioctl_mutex;
|
||||
int convert32; /* convert 32->64bit */
|
||||
|
|
|
|||
|
|
@ -42,9 +42,11 @@ struct seq_midisynth {
|
|||
struct snd_rawmidi *rmidi;
|
||||
int device;
|
||||
int subdevice;
|
||||
struct snd_rawmidi_substream __rcu *input_substream;
|
||||
snd_use_lock_t input_use_lock; /* in-flight event_input users */
|
||||
struct snd_rawmidi_file input_rfile;
|
||||
spinlock_t output_lock; /* protects output_rfile publication */
|
||||
snd_use_lock_t output_use_lock; /* in-flight event_input users */
|
||||
struct snd_rawmidi_substream __rcu *output_substream;
|
||||
struct snd_rawmidi_file output_rfile;
|
||||
int seq_client;
|
||||
int seq_port;
|
||||
|
|
@ -76,6 +78,14 @@ static void snd_midi_input_event(struct snd_rawmidi_substream *substream)
|
|||
msynth = runtime->private_data;
|
||||
if (msynth == NULL)
|
||||
return;
|
||||
|
||||
scoped_guard(rcu) {
|
||||
if (rcu_dereference(msynth->input_substream) != substream)
|
||||
return;
|
||||
|
||||
snd_use_lock_use(&msynth->input_use_lock);
|
||||
}
|
||||
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
while (runtime->avail > 0) {
|
||||
res = snd_rawmidi_kernel_read(substream, buf, sizeof(buf));
|
||||
|
|
@ -95,6 +105,8 @@ static void snd_midi_input_event(struct snd_rawmidi_substream *substream)
|
|||
memset(&ev, 0, sizeof(ev));
|
||||
}
|
||||
}
|
||||
|
||||
snd_use_lock_free(&msynth->input_use_lock);
|
||||
}
|
||||
|
||||
static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, int count)
|
||||
|
|
@ -134,8 +146,8 @@ static int event_process_midi(struct snd_seq_event *ev, int direct,
|
|||
if (snd_BUG_ON(!msynth))
|
||||
return -EINVAL;
|
||||
|
||||
scoped_guard(spinlock_irqsave, &msynth->output_lock) {
|
||||
substream = msynth->output_rfile.output;
|
||||
scoped_guard(rcu) {
|
||||
substream = rcu_dereference(msynth->output_substream);
|
||||
if (!substream)
|
||||
return -ENODEV;
|
||||
snd_use_lock_use(&msynth->output_use_lock);
|
||||
|
|
@ -177,7 +189,7 @@ static int snd_seq_midisynth_new(struct seq_midisynth *msynth,
|
|||
msynth->card = card;
|
||||
msynth->device = device;
|
||||
msynth->subdevice = subdevice;
|
||||
spin_lock_init(&msynth->output_lock);
|
||||
snd_use_lock_init(&msynth->input_use_lock);
|
||||
snd_use_lock_init(&msynth->output_use_lock);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -188,28 +200,31 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe
|
|||
int err;
|
||||
struct seq_midisynth *msynth = private_data;
|
||||
struct snd_rawmidi_runtime *runtime;
|
||||
struct snd_rawmidi_file rfile = {};
|
||||
struct snd_rawmidi_params params;
|
||||
|
||||
/* open midi port */
|
||||
err = snd_rawmidi_kernel_open(msynth->rmidi, msynth->subdevice,
|
||||
SNDRV_RAWMIDI_LFLG_INPUT,
|
||||
&msynth->input_rfile);
|
||||
&rfile);
|
||||
if (err < 0) {
|
||||
pr_debug("ALSA: seq_midi: midi input open failed!!!\n");
|
||||
return err;
|
||||
}
|
||||
runtime = msynth->input_rfile.input->runtime;
|
||||
runtime = rfile.input->runtime;
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.avail_min = 1;
|
||||
params.buffer_size = input_buffer_size;
|
||||
err = snd_rawmidi_input_params(msynth->input_rfile.input, ¶ms);
|
||||
err = snd_rawmidi_input_params(rfile.input, ¶ms);
|
||||
if (err < 0) {
|
||||
snd_rawmidi_kernel_release(&msynth->input_rfile);
|
||||
snd_rawmidi_kernel_release(&rfile);
|
||||
return err;
|
||||
}
|
||||
snd_midi_event_reset_encode(msynth->parser);
|
||||
runtime->event = snd_midi_input_event;
|
||||
runtime->private_data = msynth;
|
||||
msynth->input_rfile = rfile;
|
||||
rcu_assign_pointer(msynth->input_substream, rfile.input);
|
||||
snd_rawmidi_kernel_read(msynth->input_rfile.input, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -219,10 +234,19 @@ static int midisynth_unsubscribe(void *private_data, struct snd_seq_port_subscri
|
|||
{
|
||||
int err;
|
||||
struct seq_midisynth *msynth = private_data;
|
||||
struct snd_rawmidi_file rfile;
|
||||
|
||||
if (snd_BUG_ON(!msynth->input_rfile.input))
|
||||
rcu_assign_pointer(msynth->input_substream, NULL);
|
||||
synchronize_rcu();
|
||||
snd_use_lock_sync(&msynth->input_use_lock);
|
||||
|
||||
rfile = msynth->input_rfile;
|
||||
msynth->input_rfile = (struct snd_rawmidi_file){};
|
||||
|
||||
if (snd_BUG_ON(!rfile.input))
|
||||
return -EINVAL;
|
||||
err = snd_rawmidi_kernel_release(&msynth->input_rfile);
|
||||
|
||||
err = snd_rawmidi_kernel_release(&rfile);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -252,8 +276,8 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
|
|||
return err;
|
||||
}
|
||||
snd_midi_event_reset_decode(msynth->parser);
|
||||
scoped_guard(spinlock_irqsave, &msynth->output_lock)
|
||||
msynth->output_rfile = rfile;
|
||||
msynth->output_rfile = rfile;
|
||||
rcu_assign_pointer(msynth->output_substream, rfile.output);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -261,17 +285,16 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
|
|||
static int midisynth_unuse(void *private_data, struct snd_seq_port_subscribe *info)
|
||||
{
|
||||
struct seq_midisynth *msynth = private_data;
|
||||
struct snd_rawmidi_file rfile = {};
|
||||
struct snd_rawmidi_file rfile;
|
||||
|
||||
scoped_guard(spinlock_irqsave, &msynth->output_lock) {
|
||||
rfile = msynth->output_rfile;
|
||||
msynth->output_rfile = (struct snd_rawmidi_file){};
|
||||
}
|
||||
rcu_assign_pointer(msynth->output_substream, NULL);
|
||||
synchronize_rcu();
|
||||
snd_use_lock_sync(&msynth->output_use_lock);
|
||||
rfile = msynth->output_rfile;
|
||||
msynth->output_rfile = (struct snd_rawmidi_file){};
|
||||
|
||||
if (snd_BUG_ON(!rfile.output))
|
||||
return -EINVAL;
|
||||
|
||||
snd_use_lock_sync(&msynth->output_use_lock);
|
||||
snd_rawmidi_drain_output(rfile.output);
|
||||
return snd_rawmidi_kernel_release(&rfile);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client,
|
|||
|
||||
if (client == NULL)
|
||||
return NULL;
|
||||
guard(read_lock)(&client->ports_lock);
|
||||
list_for_each_entry(port, &client->ports_list_head, list) {
|
||||
guard(rcu)();
|
||||
list_for_each_entry_rcu(port, &client->ports_list_head, list) {
|
||||
if (port->addr.port == num) {
|
||||
if (port->closing)
|
||||
break; /* deleting now */
|
||||
|
|
@ -71,8 +71,8 @@ struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *cl
|
|||
|
||||
num = pinfo->addr.port;
|
||||
found = NULL;
|
||||
guard(read_lock)(&client->ports_lock);
|
||||
list_for_each_entry(port, &client->ports_list_head, list) {
|
||||
guard(rcu)();
|
||||
list_for_each_entry_rcu(port, &client->ports_list_head, list) {
|
||||
if ((port->capability & SNDRV_SEQ_PORT_CAP_INACTIVE) &&
|
||||
!check_inactive)
|
||||
continue; /* skip inactive ports */
|
||||
|
|
@ -98,10 +98,9 @@ struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *cl
|
|||
/* initialize snd_seq_port_subs_info */
|
||||
static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
|
||||
{
|
||||
INIT_LIST_HEAD(&grp->list_head);
|
||||
INIT_HLIST_HEAD(&grp->list_head);
|
||||
grp->count = 0;
|
||||
grp->exclusive = 0;
|
||||
rwlock_init(&grp->list_lock);
|
||||
init_rwsem(&grp->list_mutex);
|
||||
grp->open = NULL;
|
||||
grp->close = NULL;
|
||||
|
|
@ -154,7 +153,6 @@ int snd_seq_insert_port(struct snd_seq_client *client, int port,
|
|||
|
||||
num = max(port, 0);
|
||||
guard(mutex)(&client->ports_mutex);
|
||||
guard(write_lock_irq)(&client->ports_lock);
|
||||
struct list_head *insert_before = &client->ports_list_head;
|
||||
list_for_each_entry(p, &client->ports_list_head, list) {
|
||||
if (p->addr.port == port)
|
||||
|
|
@ -166,12 +164,13 @@ int snd_seq_insert_port(struct snd_seq_client *client, int port,
|
|||
if (port < 0) /* auto-probe mode */
|
||||
num = p->addr.port + 1;
|
||||
}
|
||||
/* insert the new port */
|
||||
list_add_tail(&new_port->list, insert_before);
|
||||
client->num_ports++;
|
||||
/* finish initializing the port before publishing it to RCU readers */
|
||||
new_port->addr.port = num; /* store the port number in the port */
|
||||
if (!new_port->name[0])
|
||||
sprintf(new_port->name, "port-%d", num);
|
||||
/* insert the new port */
|
||||
list_add_tail_rcu(&new_port->list, insert_before);
|
||||
client->num_ports++;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
|
@ -202,12 +201,12 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client,
|
|||
bool is_src, bool ack);
|
||||
|
||||
static inline struct snd_seq_subscribers *
|
||||
get_subscriber(struct list_head *p, bool is_src)
|
||||
get_subscriber(struct hlist_node *p, bool is_src)
|
||||
{
|
||||
if (is_src)
|
||||
return list_entry(p, struct snd_seq_subscribers, src_list);
|
||||
return hlist_entry(p, struct snd_seq_subscribers, src_list);
|
||||
else
|
||||
return list_entry(p, struct snd_seq_subscribers, dest_list);
|
||||
return hlist_entry(p, struct snd_seq_subscribers, dest_list);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -219,9 +218,9 @@ static void clear_subscriber_list(struct snd_seq_client *client,
|
|||
struct snd_seq_port_subs_info *grp,
|
||||
int is_src)
|
||||
{
|
||||
struct list_head *p, *n;
|
||||
struct hlist_node *p, *n;
|
||||
|
||||
list_for_each_safe(p, n, &grp->list_head) {
|
||||
hlist_for_each_safe(p, n, &grp->list_head) {
|
||||
struct snd_seq_subscribers *subs;
|
||||
|
||||
subs = get_subscriber(p, is_src);
|
||||
|
|
@ -238,13 +237,13 @@ static void clear_subscriber_list(struct snd_seq_client *client,
|
|||
* remove the subscriber info
|
||||
*/
|
||||
if (atomic_dec_and_test(&subs->ref_count))
|
||||
kfree(subs);
|
||||
kfree_rcu(subs, rcu);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ok we got the connected port */
|
||||
delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
|
||||
kfree(subs);
|
||||
kfree_rcu(subs, rcu);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +253,13 @@ static int port_delete(struct snd_seq_client *client,
|
|||
{
|
||||
/* set closing flag and wait for all port access are gone */
|
||||
port->closing = 1;
|
||||
snd_use_lock_sync(&port->use_lock);
|
||||
/* the port has already been unlinked from the client's port list;
|
||||
* wait for a grace period so that RCU readers still traversing the
|
||||
* list can no longer take a new use_lock reference, then drain the
|
||||
* outstanding references before freeing
|
||||
*/
|
||||
synchronize_rcu();
|
||||
snd_use_lock_sync(&port->use_lock);
|
||||
|
||||
/* clear subscribers info */
|
||||
clear_subscriber_list(client, port, &port->c_src, true);
|
||||
|
|
@ -277,11 +282,10 @@ int snd_seq_delete_port(struct snd_seq_client *client, int port)
|
|||
struct snd_seq_client_port *found = NULL, *p;
|
||||
|
||||
scoped_guard(mutex, &client->ports_mutex) {
|
||||
guard(write_lock_irq)(&client->ports_lock);
|
||||
list_for_each_entry(p, &client->ports_list_head, list) {
|
||||
if (p->addr.port == port) {
|
||||
/* ok found. delete from the list at first */
|
||||
list_del(&p->list);
|
||||
list_del_rcu(&p->list);
|
||||
client->num_ports--;
|
||||
found = p;
|
||||
break;
|
||||
|
|
@ -297,26 +301,16 @@ int snd_seq_delete_port(struct snd_seq_client *client, int port)
|
|||
/* delete the all ports belonging to the given client */
|
||||
int snd_seq_delete_all_ports(struct snd_seq_client *client)
|
||||
{
|
||||
struct list_head deleted_list;
|
||||
struct snd_seq_client_port *port, *tmp;
|
||||
|
||||
/* move the port list to deleted_list, and
|
||||
* clear the port list in the client data.
|
||||
|
||||
/* unlink and delete each port; port_delete() waits for an RCU grace
|
||||
* period before draining the port, so concurrent lockless readers can
|
||||
* no longer take a new use_lock reference on it
|
||||
*/
|
||||
guard(mutex)(&client->ports_mutex);
|
||||
scoped_guard(write_lock_irq, &client->ports_lock) {
|
||||
if (!list_empty(&client->ports_list_head)) {
|
||||
list_add(&deleted_list, &client->ports_list_head);
|
||||
list_del_init(&client->ports_list_head);
|
||||
} else {
|
||||
INIT_LIST_HEAD(&deleted_list);
|
||||
}
|
||||
client->num_ports = 0;
|
||||
}
|
||||
|
||||
/* remove each port in deleted_list */
|
||||
list_for_each_entry_safe(port, tmp, &deleted_list, list) {
|
||||
list_del(&port->list);
|
||||
list_for_each_entry_safe(port, tmp, &client->ports_list_head, list) {
|
||||
list_del_rcu(&port->list);
|
||||
client->num_ports--;
|
||||
snd_seq_system_client_ev_port_exit(port->addr.client, port->addr.port);
|
||||
port_delete(client, port);
|
||||
}
|
||||
|
|
@ -499,20 +493,20 @@ static int check_and_subscribe_port(struct snd_seq_client *client,
|
|||
bool is_src, bool exclusive, bool ack)
|
||||
{
|
||||
struct snd_seq_port_subs_info *grp;
|
||||
struct list_head *p;
|
||||
struct hlist_node *p;
|
||||
struct snd_seq_subscribers *s;
|
||||
int err;
|
||||
|
||||
grp = is_src ? &port->c_src : &port->c_dest;
|
||||
guard(rwsem_write)(&grp->list_mutex);
|
||||
if (exclusive) {
|
||||
if (!list_empty(&grp->list_head))
|
||||
if (!hlist_empty(&grp->list_head))
|
||||
return -EBUSY;
|
||||
} else {
|
||||
if (grp->exclusive)
|
||||
return -EBUSY;
|
||||
/* check whether already exists */
|
||||
list_for_each(p, &grp->list_head) {
|
||||
hlist_for_each(p, &grp->list_head) {
|
||||
s = get_subscriber(p, is_src);
|
||||
if (match_subs_info(&subs->info, &s->info))
|
||||
return -EBUSY;
|
||||
|
|
@ -526,11 +520,10 @@ static int check_and_subscribe_port(struct snd_seq_client *client,
|
|||
}
|
||||
|
||||
/* add to list */
|
||||
guard(write_lock_irq)(&grp->list_lock);
|
||||
if (is_src)
|
||||
list_add_tail(&subs->src_list, &grp->list_head);
|
||||
hlist_add_tail_rcu(&subs->src_list, &grp->list_head);
|
||||
else
|
||||
list_add_tail(&subs->dest_list, &grp->list_head);
|
||||
hlist_add_tail_rcu(&subs->dest_list, &grp->list_head);
|
||||
grp->exclusive = exclusive;
|
||||
atomic_inc(&subs->ref_count);
|
||||
|
||||
|
|
@ -544,17 +537,15 @@ static void __delete_and_unsubscribe_port(struct snd_seq_client *client,
|
|||
bool is_src, bool ack)
|
||||
{
|
||||
struct snd_seq_port_subs_info *grp;
|
||||
struct list_head *list;
|
||||
struct hlist_node *list;
|
||||
bool empty;
|
||||
|
||||
grp = is_src ? &port->c_src : &port->c_dest;
|
||||
list = is_src ? &subs->src_list : &subs->dest_list;
|
||||
scoped_guard(write_lock_irq, &grp->list_lock) {
|
||||
empty = list_empty(list);
|
||||
if (!empty)
|
||||
list_del_init(list);
|
||||
grp->exclusive = 0;
|
||||
}
|
||||
empty = hlist_unhashed(list);
|
||||
if (!empty)
|
||||
hlist_del_init_rcu(list);
|
||||
grp->exclusive = 0;
|
||||
|
||||
if (!empty)
|
||||
unsubscribe_port(client, port, grp, &subs->info, ack);
|
||||
|
|
@ -590,8 +581,8 @@ int snd_seq_port_connect(struct snd_seq_client *connector,
|
|||
|
||||
subs->info = *info;
|
||||
atomic_set(&subs->ref_count, 0);
|
||||
INIT_LIST_HEAD(&subs->src_list);
|
||||
INIT_LIST_HEAD(&subs->dest_list);
|
||||
INIT_HLIST_NODE(&subs->src_list);
|
||||
INIT_HLIST_NODE(&subs->dest_list);
|
||||
|
||||
exclusive = !!(info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE);
|
||||
|
||||
|
|
@ -612,7 +603,7 @@ int snd_seq_port_connect(struct snd_seq_client *connector,
|
|||
delete_and_unsubscribe_port(src_client, src_port, subs, true,
|
||||
connector->number != src_client->number);
|
||||
error:
|
||||
kfree(subs);
|
||||
kfree_rcu(subs, rcu);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -633,7 +624,7 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
|
|||
*/
|
||||
scoped_guard(rwsem_write, &dest->list_mutex) {
|
||||
/* look for the connection */
|
||||
list_for_each_entry(subs, &dest->list_head, dest_list) {
|
||||
hlist_for_each_entry(subs, &dest->list_head, dest_list) {
|
||||
if (match_subs_info(info, &subs->info)) {
|
||||
__delete_and_unsubscribe_port(dest_client, dest_port,
|
||||
subs, false,
|
||||
|
|
@ -648,7 +639,7 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
|
|||
|
||||
delete_and_unsubscribe_port(src_client, src_port, subs, true,
|
||||
connector->number != src_client->number);
|
||||
kfree(subs);
|
||||
kfree_rcu(subs, rcu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -662,7 +653,7 @@ int snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
|
|||
int err = -ENOENT;
|
||||
|
||||
guard(rwsem_read)(&src_grp->list_mutex);
|
||||
list_for_each_entry(s, &src_grp->list_head, src_list) {
|
||||
hlist_for_each_entry(s, &src_grp->list_head, src_list) {
|
||||
if (addr_match(dest_addr, &s->info.dest)) {
|
||||
*subs = s->info;
|
||||
err = 0;
|
||||
|
|
|
|||
|
|
@ -28,17 +28,17 @@
|
|||
|
||||
struct snd_seq_subscribers {
|
||||
struct snd_seq_port_subscribe info; /* additional info */
|
||||
struct list_head src_list; /* link of sources */
|
||||
struct list_head dest_list; /* link of destinations */
|
||||
struct hlist_node src_list; /* link of sources */
|
||||
struct hlist_node dest_list; /* link of destinations */
|
||||
atomic_t ref_count;
|
||||
struct rcu_head rcu; /* for deferred free */
|
||||
};
|
||||
|
||||
struct snd_seq_port_subs_info {
|
||||
struct list_head list_head; /* list of subscribed ports */
|
||||
struct hlist_head list_head; /* list of subscribed ports */
|
||||
unsigned int count; /* count of subscribers */
|
||||
unsigned int exclusive: 1; /* exclusive mode */
|
||||
struct rw_semaphore list_mutex;
|
||||
rwlock_t list_lock;
|
||||
int (*open)(void *private_data, struct snd_seq_port_subscribe *info);
|
||||
int (*close)(void *private_data, struct snd_seq_port_subscribe *info);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -37,8 +37,11 @@ struct seq_ump_client {
|
|||
struct snd_ump_endpoint *ump; /* assigned endpoint */
|
||||
int seq_client; /* sequencer client id */
|
||||
int opened[2]; /* current opens for each direction */
|
||||
rwlock_t output_lock; /* protects out_rfile output access */
|
||||
struct snd_rawmidi_file out_rfile; /* rawmidi for output */
|
||||
/* RCU-protected shadow of out_rfile.output for the delivery hot path;
|
||||
* out_rfile itself is only touched by open/close under open_mutex
|
||||
*/
|
||||
struct snd_rawmidi_substream __rcu *out_substream;
|
||||
struct seq_ump_input_buffer input; /* input parser context */
|
||||
void *ump_info[SNDRV_UMP_MAX_BLOCKS + 1]; /* shadow of seq client ump_info */
|
||||
struct work_struct group_notify_work; /* FB change notification */
|
||||
|
|
@ -89,8 +92,8 @@ static int seq_ump_process_event(struct snd_seq_event *ev, int direct,
|
|||
unsigned char type;
|
||||
int len;
|
||||
|
||||
guard(read_lock_irqsave)(&client->output_lock);
|
||||
substream = client->out_rfile.output;
|
||||
guard(rcu)();
|
||||
substream = rcu_dereference(client->out_substream);
|
||||
if (!substream)
|
||||
return -ENODEV;
|
||||
if (!snd_seq_ev_is_ump(ev))
|
||||
|
|
@ -108,19 +111,22 @@ static int seq_ump_process_event(struct snd_seq_event *ev, int direct,
|
|||
static int seq_ump_client_open(struct seq_ump_client *client, int dir)
|
||||
{
|
||||
struct snd_ump_endpoint *ump = client->ump;
|
||||
struct snd_rawmidi_file rfile = {};
|
||||
int err;
|
||||
|
||||
guard(mutex)(&ump->open_mutex);
|
||||
if (dir == STR_OUT && !client->opened[dir]) {
|
||||
/* out_rfile is only accessed under open_mutex; the delivery
|
||||
* path reads out_substream via RCU, so open into out_rfile
|
||||
* directly and publish the substream afterwards
|
||||
*/
|
||||
err = snd_rawmidi_kernel_open(&ump->core, 0,
|
||||
SNDRV_RAWMIDI_LFLG_OUTPUT |
|
||||
SNDRV_RAWMIDI_LFLG_APPEND,
|
||||
&rfile);
|
||||
&client->out_rfile);
|
||||
if (err < 0)
|
||||
return err;
|
||||
scoped_guard(write_lock_irqsave, &client->output_lock)
|
||||
client->out_rfile = rfile;
|
||||
rcu_assign_pointer(client->out_substream,
|
||||
client->out_rfile.output);
|
||||
}
|
||||
client->opened[dir]++;
|
||||
return 0;
|
||||
|
|
@ -130,17 +136,18 @@ static int seq_ump_client_open(struct seq_ump_client *client, int dir)
|
|||
static int seq_ump_client_close(struct seq_ump_client *client, int dir)
|
||||
{
|
||||
struct snd_ump_endpoint *ump = client->ump;
|
||||
struct snd_rawmidi_file rfile = {};
|
||||
|
||||
guard(mutex)(&ump->open_mutex);
|
||||
if (!--client->opened[dir]) {
|
||||
if (dir == STR_OUT) {
|
||||
scoped_guard(write_lock_irqsave, &client->output_lock) {
|
||||
rfile = client->out_rfile;
|
||||
client->out_rfile = (struct snd_rawmidi_file){};
|
||||
}
|
||||
if (rfile.rmidi)
|
||||
snd_rawmidi_kernel_release(&rfile);
|
||||
if (dir == STR_OUT && client->out_rfile.rmidi) {
|
||||
rcu_assign_pointer(client->out_substream, NULL);
|
||||
/* wait for a grace period so that no reader in the
|
||||
* delivery path is still writing to the substream
|
||||
* before it is released
|
||||
*/
|
||||
synchronize_rcu();
|
||||
snd_rawmidi_kernel_release(&client->out_rfile);
|
||||
client->out_rfile = (struct snd_rawmidi_file){};
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -480,7 +487,6 @@ static int snd_seq_ump_probe(struct snd_seq_device *dev)
|
|||
|
||||
INIT_WORK(&client->group_notify_work, handle_group_notify);
|
||||
client->ump = ump;
|
||||
rwlock_init(&client->output_lock);
|
||||
|
||||
client->seq_client =
|
||||
snd_seq_create_kernel_client(card, ump->core.device,
|
||||
|
|
|
|||
|
|
@ -78,10 +78,11 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
|
|||
int len;
|
||||
|
||||
if (atomic)
|
||||
read_lock(&rdev->filelist_lock);
|
||||
rcu_read_lock();
|
||||
else
|
||||
down_read(&rdev->filelist_sem);
|
||||
list_for_each_entry(vmidi, &rdev->filelist, list) {
|
||||
list_for_each_entry_rcu(vmidi, &rdev->filelist, list,
|
||||
lockdep_is_held(&rdev->filelist_sem)) {
|
||||
if (!READ_ONCE(vmidi->trigger))
|
||||
continue;
|
||||
if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
|
||||
|
|
@ -96,7 +97,7 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
|
|||
}
|
||||
}
|
||||
if (atomic)
|
||||
read_unlock(&rdev->filelist_lock);
|
||||
rcu_read_unlock();
|
||||
else
|
||||
up_read(&rdev->filelist_sem);
|
||||
|
||||
|
|
@ -200,8 +201,7 @@ static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream)
|
|||
vmidi->port = rdev->port;
|
||||
runtime->private_data = vmidi;
|
||||
scoped_guard(rwsem_write, &rdev->filelist_sem) {
|
||||
guard(write_lock_irq)(&rdev->filelist_lock);
|
||||
list_add_tail(&vmidi->list, &rdev->filelist);
|
||||
list_add_tail_rcu(&vmidi->list, &rdev->filelist);
|
||||
}
|
||||
vmidi->rdev = rdev;
|
||||
return 0;
|
||||
|
|
@ -243,9 +243,13 @@ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
|
|||
struct snd_virmidi *vmidi = substream->runtime->private_data;
|
||||
|
||||
scoped_guard(rwsem_write, &rdev->filelist_sem) {
|
||||
guard(write_lock_irq)(&rdev->filelist_lock);
|
||||
list_del(&vmidi->list);
|
||||
list_del_rcu(&vmidi->list);
|
||||
}
|
||||
/* wait for a grace period so that lockless readers in the atomic
|
||||
* delivery path (snd_virmidi_dev_receive_event()) are no longer
|
||||
* traversing this entry before its parser and memory are freed
|
||||
*/
|
||||
synchronize_rcu();
|
||||
snd_midi_event_free(vmidi->parser);
|
||||
substream->runtime->private_data = NULL;
|
||||
kfree(vmidi);
|
||||
|
|
@ -508,7 +512,6 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi
|
|||
rdev->device = device;
|
||||
rdev->client = -1;
|
||||
init_rwsem(&rdev->filelist_sem);
|
||||
rwlock_init(&rdev->filelist_lock);
|
||||
INIT_LIST_HEAD(&rdev->filelist);
|
||||
rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH;
|
||||
rmidi->private_data = rdev;
|
||||
|
|
|
|||
|
|
@ -167,11 +167,10 @@ static int snd_open(struct inode *inode, struct file *file)
|
|||
return err;
|
||||
}
|
||||
|
||||
static const struct file_operations snd_fops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.open = snd_open,
|
||||
.llseek = noop_llseek,
|
||||
static const struct file_operations snd_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = snd_open,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SND_DYNAMIC_MINORS
|
||||
|
|
@ -358,7 +357,7 @@ static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_bu
|
|||
struct snd_minor *mptr;
|
||||
|
||||
guard(mutex)(&sound_mutex);
|
||||
for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) {
|
||||
for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) {
|
||||
mptr = snd_minors[minor];
|
||||
if (!mptr)
|
||||
continue;
|
||||
|
|
@ -395,15 +394,21 @@ int __init snd_minor_info_init(void)
|
|||
|
||||
static int __init alsa_sound_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
snd_major = major;
|
||||
snd_ecards_limit = cards_limit;
|
||||
if (register_chrdev(major, "alsa", &snd_fops)) {
|
||||
|
||||
err = register_chrdev(major, "alsa", &snd_fops);
|
||||
if (err < 0) {
|
||||
pr_err("ALSA core: unable to register native major device number %d\n", major);
|
||||
return -EIO;
|
||||
return err;
|
||||
}
|
||||
if (snd_info_init() < 0) {
|
||||
|
||||
err = snd_info_init();
|
||||
if (err < 0) {
|
||||
unregister_chrdev(major, "alsa");
|
||||
return -ENOMEM;
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_DEBUG
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
.name = #fmt, \
|
||||
}
|
||||
|
||||
#define WRONG_FORMAT_1 (__force snd_pcm_format_t)((__force int)SNDRV_PCM_FORMAT_LAST + 1)
|
||||
#define WRONG_FORMAT_2 (__force snd_pcm_format_t)-1
|
||||
#define WRONG_FORMAT_1 (SNDRV_PCM_FORMAT_LAST + 1)
|
||||
#define WRONG_FORMAT_2 -1
|
||||
|
||||
#define VALID_NAME "ValidName"
|
||||
#define NAME_W_SPEC_CHARS "In%v@1id name"
|
||||
|
|
|
|||
|
|
@ -1546,11 +1546,8 @@ static int realloc_user_queue(struct snd_timer_user *tu, int size)
|
|||
static int snd_timer_user_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct snd_timer_user *tu;
|
||||
int err;
|
||||
|
||||
err = stream_open(inode, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
stream_open(inode, file);
|
||||
|
||||
tu = kzalloc_obj(*tu);
|
||||
if (tu == NULL)
|
||||
|
|
@ -2176,9 +2173,9 @@ static long snd_utimer_ioctl(struct file *file, unsigned int ioctl, unsigned lon
|
|||
}
|
||||
|
||||
static const struct file_operations snd_utimer_fops = {
|
||||
.llseek = noop_llseek,
|
||||
.release = snd_utimer_release,
|
||||
.unlocked_ioctl = snd_utimer_ioctl,
|
||||
.llseek = noop_llseek,
|
||||
.release = snd_utimer_release,
|
||||
.unlocked_ioctl = snd_utimer_ioctl,
|
||||
};
|
||||
|
||||
static int snd_utimer_start(struct snd_timer *t)
|
||||
|
|
@ -2530,16 +2527,15 @@ static __poll_t snd_timer_user_poll(struct file *file, poll_table * wait)
|
|||
#define snd_timer_user_ioctl_compat NULL
|
||||
#endif
|
||||
|
||||
static const struct file_operations snd_timer_f_ops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.read = snd_timer_user_read,
|
||||
.open = snd_timer_user_open,
|
||||
.release = snd_timer_user_release,
|
||||
.poll = snd_timer_user_poll,
|
||||
.unlocked_ioctl = snd_timer_user_ioctl,
|
||||
.compat_ioctl = snd_timer_user_ioctl_compat,
|
||||
.fasync = snd_timer_user_fasync,
|
||||
static const struct file_operations snd_timer_f_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = snd_timer_user_read,
|
||||
.open = snd_timer_user_open,
|
||||
.release = snd_timer_user_release,
|
||||
.poll = snd_timer_user_poll,
|
||||
.unlocked_ioctl = snd_timer_user_ioctl,
|
||||
.compat_ioctl = snd_timer_user_ioctl_compat,
|
||||
.fasync = snd_timer_user_fasync,
|
||||
};
|
||||
|
||||
/* unregister the system timer */
|
||||
|
|
|
|||
|
|
@ -1157,10 +1157,11 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream)
|
|||
return -ENODEV;
|
||||
if (dir == SNDRV_RAWMIDI_STREAM_OUTPUT) {
|
||||
if (!ump->legacy_out_opens) {
|
||||
err = snd_rawmidi_kernel_open(&ump->core, 0,
|
||||
SNDRV_RAWMIDI_LFLG_OUTPUT |
|
||||
SNDRV_RAWMIDI_LFLG_APPEND,
|
||||
&ump->legacy_out_rfile);
|
||||
err = snd_rawmidi_kernel_open_nested(&ump->core, 0,
|
||||
SNDRV_RAWMIDI_LFLG_OUTPUT |
|
||||
SNDRV_RAWMIDI_LFLG_APPEND,
|
||||
&ump->legacy_out_rfile,
|
||||
SINGLE_DEPTH_NESTING);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -258,6 +258,7 @@ static int cvt_legacy_sysex_to_ump(struct ump_cvt_to_ump *cvt,
|
|||
else
|
||||
status = UMP_SYSEX_STATUS_CONTINUE;
|
||||
*data = ump_compose(UMP_MSG_TYPE_DATA, group, status, cvt->len);
|
||||
data[1] = 0;
|
||||
offset = 8;
|
||||
for (i = 0; i < cvt->len; i++) {
|
||||
*data |= cvt->buf[i] << offset;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/wait.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/pcm.h>
|
||||
|
|
@ -55,7 +56,7 @@ MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-8) for loopback driver.");
|
|||
module_param_array(pcm_notify, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(pcm_notify, "Break capture when PCM format/rate/channels changes.");
|
||||
module_param_array(timer_source, charp, NULL, 0444);
|
||||
MODULE_PARM_DESC(timer_source, "Sound card name or number and device/subdevice number of timer to be used. Empty string for jiffies timer [default].");
|
||||
MODULE_PARM_DESC(timer_source, "Sound card name or number and device/subdevice number of timer to be used. Empty string for jiffies timer [default], 'hrtimer' for high-resolution timer.");
|
||||
|
||||
#define NO_PITCH 100000
|
||||
|
||||
|
|
@ -161,8 +162,11 @@ struct loopback_pcm {
|
|||
unsigned int period_size_frac; /* period size in jiffies ticks */
|
||||
unsigned int last_drift;
|
||||
unsigned long last_jiffies;
|
||||
/* If jiffies timer is used */
|
||||
/* If jiffies / hrtimer is used */
|
||||
struct timer_list timer;
|
||||
#ifdef CONFIG_HIGH_RES_TIMERS
|
||||
struct hrtimer hrtimer;
|
||||
#endif
|
||||
|
||||
/* size of per channel buffer in case of non-interleaved access */
|
||||
unsigned int channel_buf_n;
|
||||
|
|
@ -232,6 +236,31 @@ static int loopback_jiffies_timer_start(struct loopback_pcm *dpcm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HIGH_RES_TIMERS
|
||||
/* call in cable->lock */
|
||||
static int loopback_hrtimer_start(struct loopback_pcm *dpcm)
|
||||
{
|
||||
unsigned long tick;
|
||||
unsigned int rate_shift = get_rate_shift(dpcm);
|
||||
|
||||
if (rate_shift != dpcm->pcm_rate_shift) {
|
||||
dpcm->pcm_rate_shift = rate_shift;
|
||||
dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size);
|
||||
}
|
||||
if (dpcm->period_size_frac <= dpcm->irq_pos) {
|
||||
dpcm->irq_pos %= dpcm->period_size_frac;
|
||||
dpcm->period_update_pending = 1;
|
||||
}
|
||||
tick = dpcm->period_size_frac - dpcm->irq_pos;
|
||||
tick = DIV_ROUND_UP(tick, dpcm->pcm_bps);
|
||||
hrtimer_start(&dpcm->hrtimer,
|
||||
ns_to_ktime(div_u64((u64)tick * NSEC_PER_SEC, HZ)),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* call in cable->lock */
|
||||
static int loopback_snd_timer_start(struct loopback_pcm *dpcm)
|
||||
{
|
||||
|
|
@ -270,6 +299,16 @@ static inline int loopback_jiffies_timer_stop(struct loopback_pcm *dpcm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HIGH_RES_TIMERS
|
||||
/* call in cable->lock */
|
||||
static inline int loopback_hrtimer_stop(struct loopback_pcm *dpcm)
|
||||
{
|
||||
hrtimer_try_to_cancel(&dpcm->hrtimer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* call in cable->lock */
|
||||
static int loopback_snd_timer_stop(struct loopback_pcm *dpcm)
|
||||
{
|
||||
|
|
@ -300,6 +339,15 @@ static inline int loopback_jiffies_timer_stop_sync(struct loopback_pcm *dpcm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HIGH_RES_TIMERS
|
||||
static inline int loopback_hrtimer_stop_sync(struct loopback_pcm *dpcm)
|
||||
{
|
||||
hrtimer_cancel(&dpcm->hrtimer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* call in loopback->cable_lock */
|
||||
static int loopback_snd_timer_close_cable(struct loopback_pcm *dpcm)
|
||||
{
|
||||
|
|
@ -734,6 +782,30 @@ static void loopback_jiffies_timer_function(struct timer_list *t)
|
|||
snd_pcm_period_elapsed(dpcm->substream);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HIGH_RES_TIMERS
|
||||
static enum hrtimer_restart loopback_hrtimer_function(struct hrtimer *t)
|
||||
{
|
||||
struct loopback_pcm *dpcm = container_of(t, struct loopback_pcm, hrtimer);
|
||||
bool period_elapsed = false;
|
||||
|
||||
scoped_guard(spinlock_irqsave, &dpcm->cable->lock) {
|
||||
if (loopback_jiffies_timer_pos_update(dpcm->cable) &
|
||||
(1 << dpcm->substream->stream)) {
|
||||
loopback_hrtimer_start(dpcm);
|
||||
if (dpcm->period_update_pending) {
|
||||
dpcm->period_update_pending = 0;
|
||||
period_elapsed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (period_elapsed)
|
||||
snd_pcm_period_elapsed(dpcm->substream);
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* call in cable->lock */
|
||||
static int loopback_snd_timer_check_resolution(struct snd_pcm_runtime *runtime,
|
||||
unsigned long resolution)
|
||||
|
|
@ -907,6 +979,21 @@ static void loopback_jiffies_timer_dpcm_info(struct loopback_pcm *dpcm,
|
|||
snd_iprintf(buffer, " timer_expires:\t%lu\n", dpcm->timer.expires);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HIGH_RES_TIMERS
|
||||
static void loopback_hrtimer_dpcm_info(struct loopback_pcm *dpcm,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
snd_iprintf(buffer, " update_pending:\t%u\n",
|
||||
dpcm->period_update_pending);
|
||||
snd_iprintf(buffer, " irq_pos:\t\t%u\n", dpcm->irq_pos);
|
||||
snd_iprintf(buffer, " period_frac:\t%u\n", dpcm->period_size_frac);
|
||||
snd_iprintf(buffer, " last_jiffies:\t%lu (%lu)\n",
|
||||
dpcm->last_jiffies, jiffies);
|
||||
snd_iprintf(buffer, " timer_expires:\t%llu\n",
|
||||
ktime_to_ns(hrtimer_get_expires(&dpcm->hrtimer)));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void loopback_snd_timer_dpcm_info(struct loopback_pcm *dpcm,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
|
|
@ -1097,6 +1184,26 @@ static const struct loopback_ops loopback_jiffies_timer_ops = {
|
|||
.dpcm_info = loopback_jiffies_timer_dpcm_info,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HIGH_RES_TIMERS
|
||||
static int loopback_hrtimer_open(struct loopback_pcm *dpcm)
|
||||
{
|
||||
hrtimer_setup(&dpcm->hrtimer, loopback_hrtimer_function,
|
||||
CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct loopback_ops loopback_hrtimer_ops = {
|
||||
.open = loopback_hrtimer_open,
|
||||
.start = loopback_hrtimer_start,
|
||||
.stop = loopback_hrtimer_stop,
|
||||
.stop_sync = loopback_hrtimer_stop_sync,
|
||||
.close_substream = loopback_hrtimer_stop_sync,
|
||||
.pos_update = loopback_jiffies_timer_pos_update,
|
||||
.dpcm_info = loopback_hrtimer_dpcm_info,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int loopback_parse_timer_id(const char *str,
|
||||
struct snd_timer_id *tid)
|
||||
{
|
||||
|
|
@ -1274,7 +1381,12 @@ static int loopback_open(struct snd_pcm_substream *substream)
|
|||
spin_lock_init(&cable->lock);
|
||||
snd_refcount_init(&cable->stop_count);
|
||||
cable->hw = loopback_pcm_hardware;
|
||||
if (loopback->timer_source)
|
||||
#ifdef CONFIG_HIGH_RES_TIMERS
|
||||
if (loopback->timer_source && !strcmp(loopback->timer_source, "hrtimer"))
|
||||
cable->ops = &loopback_hrtimer_ops;
|
||||
else
|
||||
#endif
|
||||
if (loopback->timer_source && loopback->timer_source[0])
|
||||
cable->ops = &loopback_snd_timer_ops;
|
||||
else
|
||||
cable->ops = &loopback_jiffies_timer_ops;
|
||||
|
|
@ -1491,7 +1603,7 @@ static int loopback_format_info(struct snd_kcontrol *kcontrol,
|
|||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->count = 1;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = (__force int)SNDRV_PCM_FORMAT_LAST;
|
||||
uinfo->value.integer.max = SNDRV_PCM_FORMAT_LAST;
|
||||
uinfo->value.integer.step = 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1502,7 +1614,7 @@ static int loopback_format_get(struct snd_kcontrol *kcontrol,
|
|||
struct loopback *loopback = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
ucontrol->value.integer.value[0] =
|
||||
(__force int)loopback->setup[kcontrol->id.subdevice]
|
||||
loopback->setup[kcontrol->id.subdevice]
|
||||
[kcontrol->id.device].format;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1556,7 +1668,7 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol,
|
|||
static int loopback_access_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
const char * const texts[] = {"Interleaved", "Non-interleaved"};
|
||||
static const char * const texts[] = {"Interleaved", "Non-interleaved"};
|
||||
|
||||
return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
|
||||
}
|
||||
|
|
@ -1802,6 +1914,12 @@ static int loopback_probe(struct platform_device *devptr)
|
|||
int dev = devptr->id;
|
||||
int err;
|
||||
|
||||
if (dev < 0 || dev >= SNDRV_CARDS) {
|
||||
dev_warn(&devptr->dev,
|
||||
"Invalid card index %d, using default 0\n", dev);
|
||||
dev = 0;
|
||||
}
|
||||
|
||||
err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
|
||||
sizeof(struct loopback), &card);
|
||||
if (err < 0)
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ struct dummy_timer_ops {
|
|||
int (*prepare)(struct snd_pcm_substream *);
|
||||
int (*start)(struct snd_pcm_substream *);
|
||||
int (*stop)(struct snd_pcm_substream *);
|
||||
int (*sync_stop)(struct snd_pcm_substream *);
|
||||
snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);
|
||||
};
|
||||
|
||||
|
|
@ -285,6 +286,14 @@ static int dummy_systimer_stop(struct snd_pcm_substream *substream)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_systimer_sync_stop(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;
|
||||
|
||||
timer_delete_sync(&dpcm->timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_systimer_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
|
|
@ -341,7 +350,10 @@ static int dummy_systimer_create(struct snd_pcm_substream *substream)
|
|||
|
||||
static void dummy_systimer_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
kfree(substream->runtime->private_data);
|
||||
struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;
|
||||
|
||||
timer_shutdown_sync(&dpcm->timer);
|
||||
kfree(dpcm);
|
||||
}
|
||||
|
||||
static const struct dummy_timer_ops dummy_systimer_ops = {
|
||||
|
|
@ -350,6 +362,7 @@ static const struct dummy_timer_ops dummy_systimer_ops = {
|
|||
.prepare = dummy_systimer_prepare,
|
||||
.start = dummy_systimer_start,
|
||||
.stop = dummy_systimer_stop,
|
||||
.sync_stop = dummy_systimer_sync_stop,
|
||||
.pointer = dummy_systimer_pointer,
|
||||
};
|
||||
|
||||
|
|
@ -407,9 +420,12 @@ static int dummy_hrtimer_stop(struct snd_pcm_substream *substream)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm)
|
||||
static int dummy_hrtimer_sync_stop(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;
|
||||
|
||||
hrtimer_cancel(&dpcm->timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static snd_pcm_uframes_t
|
||||
|
|
@ -435,7 +451,6 @@ static int dummy_hrtimer_prepare(struct snd_pcm_substream *substream)
|
|||
long sec;
|
||||
unsigned long nsecs;
|
||||
|
||||
dummy_hrtimer_sync(dpcm);
|
||||
period = runtime->period_size;
|
||||
rate = runtime->rate;
|
||||
sec = period / rate;
|
||||
|
|
@ -463,7 +478,7 @@ static int dummy_hrtimer_create(struct snd_pcm_substream *substream)
|
|||
static void dummy_hrtimer_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;
|
||||
dummy_hrtimer_sync(dpcm);
|
||||
|
||||
kfree(dpcm);
|
||||
}
|
||||
|
||||
|
|
@ -473,6 +488,7 @@ static const struct dummy_timer_ops dummy_hrtimer_ops = {
|
|||
.prepare = dummy_hrtimer_prepare,
|
||||
.start = dummy_hrtimer_start,
|
||||
.stop = dummy_hrtimer_stop,
|
||||
.sync_stop = dummy_hrtimer_sync_stop,
|
||||
.pointer = dummy_hrtimer_pointer,
|
||||
};
|
||||
|
||||
|
|
@ -495,6 +511,13 @@ static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dummy_pcm_sync_stop(struct snd_pcm_substream *substream)
|
||||
{
|
||||
if (get_dummy_ops(substream)->sync_stop)
|
||||
return get_dummy_ops(substream)->sync_stop(substream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
return get_dummy_ops(substream)->prepare(substream);
|
||||
|
|
@ -646,6 +669,7 @@ static const struct snd_pcm_ops dummy_pcm_ops = {
|
|||
.hw_params = dummy_pcm_hw_params,
|
||||
.prepare = dummy_pcm_prepare,
|
||||
.trigger = dummy_pcm_trigger,
|
||||
.sync_stop = dummy_pcm_sync_stop,
|
||||
.pointer = dummy_pcm_pointer,
|
||||
};
|
||||
|
||||
|
|
@ -655,6 +679,7 @@ static const struct snd_pcm_ops dummy_pcm_ops_no_buf = {
|
|||
.hw_params = dummy_pcm_hw_params,
|
||||
.prepare = dummy_pcm_prepare,
|
||||
.trigger = dummy_pcm_trigger,
|
||||
.sync_stop = dummy_pcm_sync_stop,
|
||||
.pointer = dummy_pcm_pointer,
|
||||
.copy = dummy_pcm_copy,
|
||||
.fill_silence = dummy_pcm_silence,
|
||||
|
|
@ -1017,6 +1042,12 @@ static int snd_dummy_probe(struct platform_device *devptr)
|
|||
int idx, err;
|
||||
int dev = devptr->id;
|
||||
|
||||
if (dev < 0 || dev >= SNDRV_CARDS) {
|
||||
dev_warn(&devptr->dev,
|
||||
"Invalid card index %d, using default 0\n", dev);
|
||||
dev = 0;
|
||||
}
|
||||
|
||||
err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
|
||||
sizeof(struct snd_dummy), &card);
|
||||
if (err < 0)
|
||||
|
|
|
|||
|
|
@ -89,6 +89,12 @@ static int snd_mpu401_probe(struct platform_device *devptr)
|
|||
int err;
|
||||
struct snd_card *card;
|
||||
|
||||
if (dev < 0 || dev >= SNDRV_CARDS) {
|
||||
dev_warn(&devptr->dev,
|
||||
"Invalid card index %d, using default 0\n", dev);
|
||||
dev = 0;
|
||||
}
|
||||
|
||||
if (port[dev] == SNDRV_AUTO_PORT) {
|
||||
dev_err(&devptr->dev, "specify port\n");
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -900,6 +900,12 @@ static int snd_mts64_probe(struct platform_device *pdev)
|
|||
p = platform_get_drvdata(pdev);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
if (dev < 0) {
|
||||
dev_warn(&pdev->dev,
|
||||
"Invalid card index %d, using default 0\n", dev);
|
||||
dev = 0;
|
||||
}
|
||||
|
||||
if (dev >= SNDRV_CARDS)
|
||||
return -ENODEV;
|
||||
if (!enable[dev])
|
||||
|
|
|
|||
|
|
@ -697,6 +697,12 @@ static int snd_portman_probe(struct platform_device *pdev)
|
|||
p = platform_get_drvdata(pdev);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
if (dev < 0) {
|
||||
dev_warn(&pdev->dev,
|
||||
"Invalid card index %d, using default 0\n", dev);
|
||||
dev = 0;
|
||||
}
|
||||
|
||||
if (dev >= SNDRV_CARDS)
|
||||
return -ENODEV;
|
||||
if (!enable[dev])
|
||||
|
|
|
|||
|
|
@ -846,6 +846,12 @@ static int snd_serial_probe(struct platform_device *devptr)
|
|||
int err;
|
||||
int dev = devptr->id;
|
||||
|
||||
if (dev < 0 || dev >= SNDRV_CARDS) {
|
||||
dev_warn(&devptr->dev,
|
||||
"Invalid card index %d, using default 0\n", dev);
|
||||
dev = 0;
|
||||
}
|
||||
|
||||
switch (adaptor[dev]) {
|
||||
case SNDRV_SERIAL_SOUNDCANVAS:
|
||||
ins[dev] = 1;
|
||||
|
|
|
|||
|
|
@ -75,6 +75,12 @@ static int snd_virmidi_probe(struct platform_device *devptr)
|
|||
int idx, err;
|
||||
int dev = devptr->id;
|
||||
|
||||
if (dev < 0 || dev >= SNDRV_CARDS) {
|
||||
dev_warn(&devptr->dev,
|
||||
"Invalid card index %d, using default 0\n", dev);
|
||||
dev = 0;
|
||||
}
|
||||
|
||||
err = snd_devm_card_new(&devptr->dev, index[dev], id[dev], THIS_MODULE,
|
||||
sizeof(struct snd_card_virmidi), &card);
|
||||
if (err < 0)
|
||||
|
|
|
|||
|
|
@ -5788,7 +5788,8 @@ static int ca0132_alt_mic_boost_info(struct snd_kcontrol *kcontrol,
|
|||
uinfo->value.enumerated.items = MIC_BOOST_NUM_OF_STEPS;
|
||||
if (uinfo->value.enumerated.item >= MIC_BOOST_NUM_OF_STEPS)
|
||||
uinfo->value.enumerated.item = MIC_BOOST_NUM_OF_STEPS - 1;
|
||||
sprintf(namestr, "%d %s", (uinfo->value.enumerated.item * 10), sfx);
|
||||
snprintf(namestr, sizeof(namestr), "%d %s",
|
||||
(uinfo->value.enumerated.item * 10), sfx);
|
||||
strscpy(uinfo->value.enumerated.name, namestr);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -5840,9 +5841,9 @@ static int ae5_headphone_gain_info(struct snd_kcontrol *kcontrol,
|
|||
uinfo->value.enumerated.items = AE5_HEADPHONE_GAIN_MAX;
|
||||
if (uinfo->value.enumerated.item >= AE5_HEADPHONE_GAIN_MAX)
|
||||
uinfo->value.enumerated.item = AE5_HEADPHONE_GAIN_MAX - 1;
|
||||
sprintf(namestr, "%s %s",
|
||||
ae5_headphone_gain_presets[uinfo->value.enumerated.item].name,
|
||||
sfx);
|
||||
snprintf(namestr, sizeof(namestr), "%s %s",
|
||||
ae5_headphone_gain_presets[uinfo->value.enumerated.item].name,
|
||||
sfx);
|
||||
strscpy(uinfo->value.enumerated.name, namestr);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -5894,8 +5895,8 @@ static int ae5_sound_filter_info(struct snd_kcontrol *kcontrol,
|
|||
uinfo->value.enumerated.items = AE5_SOUND_FILTER_MAX;
|
||||
if (uinfo->value.enumerated.item >= AE5_SOUND_FILTER_MAX)
|
||||
uinfo->value.enumerated.item = AE5_SOUND_FILTER_MAX - 1;
|
||||
sprintf(namestr, "%s",
|
||||
ae5_filter_presets[uinfo->value.enumerated.item].name);
|
||||
snprintf(namestr, sizeof(namestr), "%s",
|
||||
ae5_filter_presets[uinfo->value.enumerated.item].name);
|
||||
strscpy(uinfo->value.enumerated.name, namestr);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -6632,7 +6633,7 @@ static int ca0132_alt_add_effect_slider(struct hda_codec *codec, hda_nid_t nid,
|
|||
struct snd_kcontrol_new knew =
|
||||
HDA_CODEC_VOLUME_MONO(namestr, nid, 1, 0, type);
|
||||
|
||||
sprintf(namestr, "FX: %s %s Volume", pfx, dirstr[dir]);
|
||||
snprintf(namestr, sizeof(namestr), "FX: %s %s Volume", pfx, dirstr[dir]);
|
||||
|
||||
knew.tlv.c = NULL;
|
||||
|
||||
|
|
@ -6671,9 +6672,9 @@ static int add_fx_switch(struct hda_codec *codec, hda_nid_t nid,
|
|||
* prefix to OutFX or InFX enable controls.
|
||||
*/
|
||||
if (ca0132_use_alt_controls(spec) && (nid <= IN_EFFECT_END_NID))
|
||||
sprintf(namestr, "FX: %s %s Switch", pfx, dirstr[dir]);
|
||||
snprintf(namestr, sizeof(namestr), "FX: %s %s Switch", pfx, dirstr[dir]);
|
||||
else
|
||||
sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]);
|
||||
snprintf(namestr, sizeof(namestr), "%s %s Switch", pfx, dirstr[dir]);
|
||||
|
||||
return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
|
||||
}
|
||||
|
|
@ -8530,10 +8531,9 @@ static void ca0132_set_dsp_msr(struct hda_codec *codec, bool is96k)
|
|||
|
||||
static bool ca0132_download_dsp_images(struct hda_codec *codec)
|
||||
{
|
||||
bool dsp_loaded = false;
|
||||
struct ca0132_spec *spec = codec->spec;
|
||||
const struct dsp_image_seg *dsp_os_image;
|
||||
const struct firmware *fw_entry = NULL;
|
||||
const struct firmware *fw_entry __free(firmware) = NULL;
|
||||
/*
|
||||
* Alternate firmwares for different variants. The Recon3Di apparently
|
||||
* can use the default firmware, but I'll leave the option in case
|
||||
|
|
@ -8573,15 +8573,10 @@ static bool ca0132_download_dsp_images(struct hda_codec *codec)
|
|||
dsp_os_image = (struct dsp_image_seg *)(fw_entry->data);
|
||||
if (dspload_image(codec, dsp_os_image, 0, 0, true, 0)) {
|
||||
codec_err(codec, "ca0132 DSP load image failed\n");
|
||||
goto exit_download;
|
||||
return false;
|
||||
}
|
||||
|
||||
dsp_loaded = dspload_wait_loaded(codec);
|
||||
|
||||
exit_download:
|
||||
release_firmware(fw_entry);
|
||||
|
||||
return dsp_loaded;
|
||||
return dspload_wait_loaded(codec);
|
||||
}
|
||||
|
||||
static void ca0132_download_dsp(struct hda_codec *codec)
|
||||
|
|
@ -9634,6 +9629,7 @@ static void ca0132_free(struct hda_codec *codec)
|
|||
#endif
|
||||
kfree(spec->spec_init_verbs);
|
||||
kfree(codec->spec);
|
||||
codec->spec = NULL;
|
||||
}
|
||||
|
||||
static void dbpro_free(struct hda_codec *codec)
|
||||
|
|
@ -9644,6 +9640,7 @@ static void dbpro_free(struct hda_codec *codec)
|
|||
|
||||
kfree(spec->spec_init_verbs);
|
||||
kfree(codec->spec);
|
||||
codec->spec = NULL;
|
||||
}
|
||||
|
||||
static void ca0132_config(struct hda_codec *codec)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@
|
|||
|
||||
enum {
|
||||
QUIRK_CM_STD = 0x0,
|
||||
QUIRK_GENE_TWL7_SSID = 0x160dc000
|
||||
QUIRK_GENE_TWL7_SSID = 0x160dc000,
|
||||
QUIRK_IBP_SSID = 0x15bd3275
|
||||
};
|
||||
|
||||
/* CM9825 Offset Definitions */
|
||||
|
|
@ -40,13 +41,19 @@ enum {
|
|||
#define CM9825_VERB_SET_GAD 0x7b4
|
||||
#define CM9825_VERB_SET_TMOD 0x7b5
|
||||
#define CM9825_VERB_SET_SNR 0x7b6
|
||||
#define CM9825_VERB_SET_OMTP 0x7ef
|
||||
#define CM9825_VERB_READ_OMTP 0xfec
|
||||
|
||||
struct cmi_spec {
|
||||
struct hda_gen_spec gen;
|
||||
const struct hda_verb *chip_d0_verbs;
|
||||
const struct hda_verb *chip_d3_verbs;
|
||||
const struct hda_verb *chip_playback_start_verbs;
|
||||
const struct hda_verb *chip_playback_stop_verbs;
|
||||
const struct hda_verb *chip_hp_present_verbs;
|
||||
const struct hda_verb *chip_hp_remove_verbs;
|
||||
const struct hda_verb *chip_lineout_present_verbs;
|
||||
const struct hda_verb *chip_lineout_remove_verbs;
|
||||
struct hda_codec *codec;
|
||||
struct delayed_work unsol_inputs_work;
|
||||
struct delayed_work unsol_lineout_work;
|
||||
|
|
@ -193,6 +200,94 @@ static const struct hda_verb cm9825_gene_twl7_playback_stop_verbs[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* To save power, AD/CLK is turned off.
|
||||
*/
|
||||
static const struct hda_verb cm9825_ibp_d3_verbs[] = {
|
||||
{0x43, CM9825_VERB_SET_D2S, 0x62},
|
||||
{0x43, CM9825_VERB_SET_PLL, 0x01},
|
||||
{0x43, CM9825_VERB_SET_NEG, 0xc2},
|
||||
{0x43, CM9825_VERB_SET_ADCL, 0x00},
|
||||
{0x43, CM9825_VERB_SET_DACL, 0x02},
|
||||
{0x43, CM9825_VERB_SET_VNEG, 0x50},
|
||||
{0x43, CM9825_VERB_SET_MBIAS, 0x00},
|
||||
{0x43, CM9825_VERB_SET_PDNEG, 0x04},
|
||||
{0x43, CM9825_VERB_SET_CDALR, 0xf6},
|
||||
{0x43, CM9825_VERB_SET_OTP, 0xcd},
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* D0 configuration: enable PLL/CLK/ADC/DAC and optimize performance
|
||||
*/
|
||||
static const struct hda_verb cm9825_ibp_d0_verbs[] = {
|
||||
{0x34, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
|
||||
{0x43, CM9825_VERB_SET_SNR, 0x38},
|
||||
{0x43, CM9825_VERB_SET_PLL, 0x00},
|
||||
{0x43, CM9825_VERB_SET_ADCL, 0x00},
|
||||
{0x43, CM9825_VERB_SET_DACL, 0x02},
|
||||
{0x43, CM9825_VERB_SET_MBIAS, 0x00},
|
||||
{0x43, CM9825_VERB_SET_VNEG, 0x56},
|
||||
{0x43, CM9825_VERB_SET_D2S, 0x62},
|
||||
{0x43, CM9825_VERB_SET_DACTRL, 0x00},
|
||||
{0x43, CM9825_VERB_SET_PDNEG, 0x0c},
|
||||
{0x43, CM9825_VERB_SET_CDALR, 0xf4},
|
||||
{0x43, CM9825_VERB_SET_OTP, 0xcd},
|
||||
{0x43, CM9825_VERB_SET_MTCBA, 0x61},
|
||||
{0x43, CM9825_VERB_SET_OCP, 0x33},
|
||||
{0x43, CM9825_VERB_SET_GAD, 0x07},
|
||||
{0x43, CM9825_VERB_SET_TMOD, 0x26},
|
||||
{0x3c, AC_VERB_SET_AMP_GAIN_MUTE | 0xa0, 0x2d},
|
||||
{0x3c, AC_VERB_SET_AMP_GAIN_MUTE | 0x90, 0x2d},
|
||||
{0x43, CM9825_VERB_SET_HPF_1, 0x40},
|
||||
{0x43, CM9825_VERB_SET_HPF_2, 0x40},
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* Enable mbias, ADC.
|
||||
*/
|
||||
static const struct hda_verb cm9825_ibp_lineout_present_verbs[] = {
|
||||
{0x43, CM9825_VERB_SET_ADCL, 0x8c},
|
||||
{0x43, CM9825_VERB_SET_MBIAS, 0x10},
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* Disable mbias, ADC.
|
||||
*/
|
||||
static const struct hda_verb cm9825_ibp_lineout_remove_verbs[] = {
|
||||
{0x43, CM9825_VERB_SET_ADCL, 0x00},
|
||||
{0x43, CM9825_VERB_SET_MBIAS, 0x00},
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* Turn on the DAC (widget NID 0x43) in the playback path by writing
|
||||
* a sequence of vendor-specific verbs.
|
||||
*/
|
||||
static const struct hda_verb cm9825_ibp_playback_start_verbs[] = {
|
||||
{0x43, CM9825_VERB_SET_DACL, 0xaa},
|
||||
{0x43, CM9825_VERB_SET_D2S, 0xf2},
|
||||
{0x43, CM9825_VERB_SET_VDO, 0xc4},
|
||||
{0x43, CM9825_VERB_SET_SNR, 0x30},
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* Shut down the playback path. The order differs slightly from the
|
||||
* enable sequence, likely to avoid audible pop noise when powering
|
||||
* down the output stage.
|
||||
*/
|
||||
static const struct hda_verb cm9825_ibp_playback_stop_verbs[] = {
|
||||
{0x43, CM9825_VERB_SET_VDO, 0xc0},
|
||||
{0x43, CM9825_VERB_SET_DACL, 0x02},
|
||||
{0x43, CM9825_VERB_SET_D2S, 0x62},
|
||||
{0x43, CM9825_VERB_SET_VDO, 0x80},
|
||||
{0x43, CM9825_VERB_SET_SNR, 0x38},
|
||||
{}
|
||||
};
|
||||
|
||||
static void cm9825_update_jk_plug_status(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
struct cmi_spec *spec = codec->spec;
|
||||
|
|
@ -232,6 +327,23 @@ static void cm9825_unsol_lineout_delayed(struct work_struct *work)
|
|||
struct cmi_spec *spec =
|
||||
container_of(to_delayed_work(work), struct cmi_spec,
|
||||
unsol_lineout_work);
|
||||
hda_nid_t line_out_pin = spec->gen.autocfg.line_out_pins[0];
|
||||
bool line_out_jack_plugin = false;
|
||||
|
||||
line_out_jack_plugin = snd_hda_jack_detect(spec->codec, line_out_pin);
|
||||
|
||||
codec_dbg(spec->codec, "lineout_jack_plugin %d, lineout_pin 0x%X\n",
|
||||
(int)line_out_jack_plugin, line_out_pin);
|
||||
|
||||
if (!line_out_jack_plugin) {
|
||||
/* Jack plugout */
|
||||
snd_hda_sequence_write(spec->codec,
|
||||
spec->chip_lineout_remove_verbs);
|
||||
} else {
|
||||
/* Jack plugin */
|
||||
snd_hda_sequence_write(spec->codec,
|
||||
spec->chip_lineout_present_verbs);
|
||||
}
|
||||
|
||||
cm9825_update_jk_plug_status(spec->codec,
|
||||
spec->gen.autocfg.line_out_pins[0]);
|
||||
|
|
@ -362,12 +474,10 @@ static void cm9825_playback_pcm_hook(struct hda_pcm_stream *hinfo,
|
|||
|
||||
switch (action) {
|
||||
case HDA_GEN_PCM_ACT_PREPARE:
|
||||
snd_hda_sequence_write(spec->codec,
|
||||
cm9825_gene_twl7_playback_start_verbs);
|
||||
snd_hda_sequence_write(codec, spec->chip_playback_start_verbs);
|
||||
break;
|
||||
case HDA_GEN_PCM_ACT_CLEANUP:
|
||||
snd_hda_sequence_write(spec->codec,
|
||||
cm9825_gene_twl7_playback_stop_verbs);
|
||||
snd_hda_sequence_write(codec, spec->chip_playback_stop_verbs);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
|
@ -471,7 +581,8 @@ static int cm9825_resume(struct hda_codec *codec)
|
|||
|
||||
if (codec->core.subsystem_id == QUIRK_CM_STD)
|
||||
cm9825_cm_std_resume(codec);
|
||||
else if (codec->core.subsystem_id == QUIRK_GENE_TWL7_SSID) {
|
||||
else if (codec->core.subsystem_id == QUIRK_GENE_TWL7_SSID ||
|
||||
codec->core.subsystem_id == QUIRK_IBP_SSID) {
|
||||
snd_hda_codec_init(codec);
|
||||
snd_hda_sequence_write(codec, spec->chip_d0_verbs);
|
||||
}
|
||||
|
|
@ -487,6 +598,7 @@ static int cm9825_probe(struct hda_codec *codec, const struct hda_device_id *id)
|
|||
struct cmi_spec *spec;
|
||||
struct auto_pin_cfg *cfg;
|
||||
int err = 0;
|
||||
unsigned int val;
|
||||
|
||||
spec = kzalloc_obj(*spec);
|
||||
if (spec == NULL)
|
||||
|
|
@ -523,9 +635,33 @@ static int cm9825_probe(struct hda_codec *codec, const struct hda_device_id *id)
|
|||
spec->chip_d0_verbs = cm9825_gene_twl7_d0_verbs;
|
||||
spec->chip_d3_verbs = cm9825_gene_twl7_d3_verbs;
|
||||
spec->gen.pcm_playback_hook = cm9825_playback_pcm_hook;
|
||||
spec->chip_playback_start_verbs =
|
||||
cm9825_gene_twl7_playback_start_verbs;
|
||||
spec->chip_playback_stop_verbs =
|
||||
cm9825_gene_twl7_playback_stop_verbs;
|
||||
/* Internal fixed device, Rear, Mic-in, 3.5mm */
|
||||
snd_hda_codec_set_pincfg(codec, 0x37, 0x24A70100);
|
||||
break;
|
||||
case QUIRK_IBP_SSID:
|
||||
snd_hda_codec_set_name(codec, "CM9825 IBP");
|
||||
spec->chip_d0_verbs = cm9825_ibp_d0_verbs;
|
||||
spec->chip_d3_verbs = cm9825_ibp_d3_verbs;
|
||||
spec->gen.pcm_playback_hook = cm9825_playback_pcm_hook;
|
||||
spec->chip_lineout_present_verbs =
|
||||
cm9825_ibp_lineout_present_verbs;
|
||||
spec->chip_lineout_remove_verbs =
|
||||
cm9825_ibp_lineout_remove_verbs;
|
||||
spec->chip_playback_start_verbs =
|
||||
cm9825_ibp_playback_start_verbs;
|
||||
spec->chip_playback_stop_verbs = cm9825_ibp_playback_stop_verbs;
|
||||
|
||||
/* OMTP */
|
||||
val =
|
||||
snd_hda_codec_read(codec, 0x46, 0, CM9825_VERB_READ_OMTP,
|
||||
0x0);
|
||||
snd_hda_codec_write(codec, 0x46, 0, CM9825_VERB_SET_OMTP,
|
||||
(val >> 24) & 0x7f);
|
||||
break;
|
||||
default:
|
||||
err = -ENXIO;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -292,6 +292,7 @@ enum {
|
|||
CXT_PINCFG_TOP_SPEAKER,
|
||||
CXT_FIXUP_HP_A_U,
|
||||
CXT_FIXUP_ACER_SWIFT_HP,
|
||||
CXT_FIXUP_HUAWEI_MATEBOOK_HP,
|
||||
};
|
||||
|
||||
/* for hda_fixup_thinkpad_acpi() */
|
||||
|
|
@ -451,7 +452,8 @@ static void olpc_xo_update_mic_pins(struct hda_codec *codec)
|
|||
if (!spec->dc_enable) {
|
||||
/* disable DC bias path and pin for port F */
|
||||
update_mic_pin(codec, 0x1e, 0);
|
||||
snd_hda_activate_path(codec, spec->dc_mode_path, false, false);
|
||||
if (spec->dc_mode_path)
|
||||
snd_hda_activate_path(codec, spec->dc_mode_path, false, false);
|
||||
|
||||
/* update port B (ext mic) and C (int mic) */
|
||||
/* OLPC defers mic widget control until when capture is
|
||||
|
|
@ -487,7 +489,8 @@ static void olpc_xo_update_mic_pins(struct hda_codec *codec)
|
|||
update_mic_pin(codec, 0x1b, 0);
|
||||
/* enable DC bias path and pin */
|
||||
update_mic_pin(codec, 0x1e, spec->recording ? PIN_IN : 0);
|
||||
snd_hda_activate_path(codec, spec->dc_mode_path, true, false);
|
||||
if (spec->dc_mode_path)
|
||||
snd_hda_activate_path(codec, spec->dc_mode_path, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1033,6 +1036,13 @@ static const struct hda_fixup cxt_fixups[] = {
|
|||
{ }
|
||||
},
|
||||
},
|
||||
[CXT_FIXUP_HUAWEI_MATEBOOK_HP] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
{ 0x18, 0x03211020 }, /* Headphone */
|
||||
{ }
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct hda_quirk cxt5045_fixups[] = {
|
||||
|
|
@ -1097,6 +1107,7 @@ static const struct hda_quirk cxt5066_fixups[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x82b4, "HP ProDesk 600 G3", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x836e, "HP ProBook 455 G5", CXT_FIXUP_MUTE_LED_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x837b, "HP ProBook 440 G5", CXT_FIXUP_MUTE_LED_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x837f, "HP ProBook 470 G5", CXT_FIXUP_MUTE_LED_GPIO),
|
||||
SND_PCI_QUIRK(0x103c, 0x83b2, "HP EliteBook 840 G5", CXT_FIXUP_HP_DOCK),
|
||||
SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
|
||||
|
|
@ -1133,6 +1144,7 @@ static const struct hda_quirk cxt5066_fixups[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo G50-70", CXT_FIXUP_STEREO_DMIC),
|
||||
SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
|
||||
SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad/Ideapad", CXT_FIXUP_LENOVO_XPAD_ACPI),
|
||||
SND_PCI_QUIRK(0x19e5, 0x3289, "Huawei Matebook", CXT_FIXUP_HUAWEI_MATEBOOK_HP),
|
||||
SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
|
||||
SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
|
||||
SND_PCI_QUIRK(0x1d05, 0x3012, "MECHREVO Wujie 15X Pro", CXT_FIXUP_HEADSET_MIC),
|
||||
|
|
|
|||
|
|
@ -2695,30 +2695,13 @@ static const struct snd_kcontrol_new out_jack_mode_enum = {
|
|||
.put = out_jack_mode_put,
|
||||
};
|
||||
|
||||
static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
const struct snd_kcontrol_new *kctl;
|
||||
int i;
|
||||
|
||||
snd_array_for_each(&spec->kctls, i, kctl) {
|
||||
if (!strcmp(kctl->name, name) && kctl->index == idx)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
|
||||
char *name, size_t name_len)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
int idx = 0;
|
||||
|
||||
snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
|
||||
strlcat(name, " Jack Mode", name_len);
|
||||
|
||||
for (; find_kctl_name(codec, name, idx); idx++)
|
||||
;
|
||||
snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len);
|
||||
hda_append_suffix(name, " Jack Mode", name_len);
|
||||
}
|
||||
|
||||
static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
|
||||
|
|
@ -5695,7 +5678,7 @@ static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
|
|||
break;
|
||||
}
|
||||
}
|
||||
strlcat(str, sfx, len);
|
||||
hda_append_suffix(str, sfx, len);
|
||||
}
|
||||
|
||||
/* copy PCM stream info from @default_str, and override non-NULL entries
|
||||
|
|
|
|||
|
|
@ -2236,8 +2236,10 @@ void snd_hda_hdmi_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id)
|
|||
/* skip notification during system suspend (but not in runtime PM);
|
||||
* the state will be updated at resume
|
||||
*/
|
||||
if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
|
||||
if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND) {
|
||||
codec->acomp_requested_resume = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
snd_hda_hdmi_check_presence_and_report(codec, pin_nid, dev_id);
|
||||
}
|
||||
|
|
|
|||
820
sound/hda/codecs/helpers/razer_blade16_2025.c
Normal file
820
sound/hda/codecs/helpers/razer_blade16_2025.c
Normal file
|
|
@ -0,0 +1,820 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Razer Blade 16 (2025) external smart-amplifier programming and fixup,
|
||||
* to be included from the codec driver.
|
||||
*
|
||||
* The internal speakers are driven by an external smart amplifier whose
|
||||
* crossover, voicing and protection live in a DSP reached over a vendor
|
||||
* coef mailbox on NID 0x20. These tables hold the programming captured
|
||||
* from the Windows driver, reduced to the NID-0x20 traffic this machine
|
||||
* needs (everything else the HDA parser rebuilds).
|
||||
*
|
||||
* Each entry is either a plain codec coef write or a mailbox write:
|
||||
* strobe == 0: coef[addr] = lo
|
||||
* strobe != 0: amp[addr] = (hi << 16) | lo, with the bank selected on
|
||||
* port 0x89 and the write committed by the strobe opcode.
|
||||
*/
|
||||
|
||||
struct alc298_razer_blade16_2025_op {
|
||||
u16 bank; /* mailbox bank (port 0x89); unused for a plain coef */
|
||||
u16 addr; /* mailbox register, or plain coef index */
|
||||
u16 hi; /* mailbox high word; unused for a plain coef */
|
||||
u16 lo; /* mailbox low word, or plain coef value */
|
||||
u16 strobe; /* mailbox commit opcode; 0 marks a plain coef write */
|
||||
};
|
||||
|
||||
/* program the external DSP at init; the amp is woken/parked separately */
|
||||
static const struct alc298_razer_blade16_2025_op alc298_razer_blade16_2025_amp_init[] = {
|
||||
{ 0x0000, 0xf102, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xf103, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xc000, 0x0000, 0x0001, 0xb031 },
|
||||
{ 0x0000, 0xea00, 0x0000, 0x0047, 0xb031 },
|
||||
{ 0x0000, 0xf20d, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xf212, 0x0000, 0x003e, 0xb031 },
|
||||
{ 0x0000, 0xc001, 0x0000, 0x0002, 0xb031 },
|
||||
{ 0x0000, 0xc003, 0x0000, 0x0022, 0xb031 },
|
||||
{ 0x0000, 0xc004, 0x0000, 0x0044, 0xb031 },
|
||||
{ 0x0000, 0xc005, 0x0000, 0x0044, 0xb031 },
|
||||
{ 0x0000, 0xc007, 0x0000, 0x0064, 0xb031 },
|
||||
{ 0x0000, 0xc00e, 0x0000, 0x00e7, 0xb031 },
|
||||
{ 0x0000, 0xf223, 0x0000, 0x007f, 0xb031 },
|
||||
{ 0x0000, 0xf224, 0x0000, 0x00db, 0xb031 },
|
||||
{ 0x0000, 0xf225, 0x0000, 0x00ee, 0xb031 },
|
||||
{ 0x0000, 0xf226, 0x0000, 0x003f, 0xb031 },
|
||||
{ 0x0000, 0xf227, 0x0000, 0x000f, 0xb031 },
|
||||
{ 0x0000, 0xf21a, 0x0000, 0x0078, 0xb031 },
|
||||
{ 0x0000, 0xf242, 0x0000, 0x003c, 0xb031 },
|
||||
{ 0x0000, 0xc120, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xc125, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xc321, 0x0000, 0x000b, 0xb031 },
|
||||
{ 0x0000, 0xc200, 0x0000, 0x00d8, 0xb031 },
|
||||
{ 0x0000, 0xc201, 0x0000, 0x0027, 0xb031 },
|
||||
{ 0x0000, 0xc202, 0x0000, 0x000f, 0xb031 },
|
||||
{ 0x0000, 0xc400, 0x0000, 0x000e, 0xb031 },
|
||||
{ 0x0000, 0xc401, 0x0000, 0x0043, 0xb031 },
|
||||
{ 0x0000, 0xc402, 0x0000, 0x00e0, 0xb031 },
|
||||
{ 0x0000, 0xc403, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xc404, 0x0000, 0x004c, 0xb031 },
|
||||
{ 0x0000, 0xc406, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xc407, 0x0000, 0x0002, 0xb031 },
|
||||
{ 0x0000, 0xc408, 0x0000, 0x003f, 0xb031 },
|
||||
{ 0x0000, 0xc300, 0x0000, 0x0001, 0xb031 },
|
||||
{ 0x0000, 0xc125, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xdf00, 0x0000, 0x0010, 0xb031 },
|
||||
{ 0x0000, 0xdf5f, 0x0000, 0x0001, 0xb031 },
|
||||
{ 0x0000, 0xdf60, 0x0000, 0x00a7, 0xb031 },
|
||||
{ 0x0000, 0xc203, 0x0000, 0x0084, 0xb031 },
|
||||
{ 0x0000, 0xc206, 0x0000, 0x0078, 0xb031 },
|
||||
{ 0x0000, 0xf10a, 0x0000, 0x000b, 0xb031 },
|
||||
{ 0x0000, 0xf10b, 0x0000, 0x004c, 0xb031 },
|
||||
{ 0x0000, 0xf104, 0x0000, 0x00f4, 0xb031 },
|
||||
{ 0x0000, 0xf105, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xf109, 0x0000, 0x00e0, 0xb031 },
|
||||
{ 0x0000, 0xf10b, 0x0000, 0x005c, 0xb031 },
|
||||
{ 0x0000, 0xf104, 0x0000, 0x00f4, 0xb031 },
|
||||
{ 0x0000, 0xf105, 0x0000, 0x0004, 0xb031 },
|
||||
{ 0x0000, 0xf109, 0x0000, 0x0065, 0xb031 },
|
||||
{ 0x0000, 0xf10b, 0x0000, 0x005c, 0xb031 },
|
||||
{ 0x0000, 0xf104, 0x0000, 0x00f7, 0xb031 },
|
||||
{ 0x0000, 0xf105, 0x0000, 0x0030, 0xb031 },
|
||||
{ 0x0000, 0xf109, 0x0000, 0x0006, 0xb031 },
|
||||
{ 0x0000, 0xf10b, 0x0000, 0x005c, 0xb031 },
|
||||
{ 0x0000, 0xf104, 0x0000, 0x00f7, 0xb031 },
|
||||
{ 0x0000, 0xf105, 0x0000, 0x0031, 0xb031 },
|
||||
{ 0x0000, 0xf109, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xf10b, 0x0000, 0x005c, 0xb031 },
|
||||
{ 0x0000, 0xe706, 0x0000, 0x000f, 0xb031 },
|
||||
{ 0x0000, 0xe707, 0x0000, 0x0030, 0xb031 },
|
||||
{ 0x0000, 0xe806, 0x0000, 0x000f, 0xb031 },
|
||||
{ 0x0000, 0xe807, 0x0000, 0x0030, 0xb031 },
|
||||
{ 0x0000, 0xce04, 0x0000, 0x0002, 0xb031 },
|
||||
{ 0x0000, 0xce05, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xce06, 0x0000, 0x0031, 0xb031 },
|
||||
{ 0x0000, 0xce07, 0x0000, 0x00b4, 0xb031 },
|
||||
{ 0x0000, 0xcf04, 0x0000, 0x0002, 0xb031 },
|
||||
{ 0x0000, 0xcf05, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xcf06, 0x0000, 0x0031, 0xb031 },
|
||||
{ 0x0000, 0xcf07, 0x0000, 0x00b4, 0xb031 },
|
||||
{ 0x0000, 0xce60, 0x0000, 0x00e3, 0xb031 },
|
||||
{ 0x0000, 0xc130, 0x0000, 0x0051, 0xb031 },
|
||||
{ 0x0000, 0xe000, 0x0000, 0x00a8, 0xb031 },
|
||||
{ 0x4100, 0x1888, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xc121, 0x0000, 0x000b, 0xb031 },
|
||||
{ 0x0000, 0xea00, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xf800, 0x0000, 0x0020, 0xb031 },
|
||||
{ 0x0000, 0xca00, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xca10, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xca02, 0x0000, 0x0078, 0xb031 },
|
||||
{ 0x0000, 0xca12, 0x0000, 0x0078, 0xb031 },
|
||||
{ 0x0000, 0xed00, 0x0000, 0x0090, 0xb031 },
|
||||
{ 0x0000, 0xcc2c, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcc2d, 0x0000, 0x000e, 0xb031 },
|
||||
{ 0x0000, 0xcc2e, 0x0000, 0x0076, 0xb031 },
|
||||
{ 0x0000, 0xcc2f, 0x0000, 0x0043, 0xb031 },
|
||||
{ 0x0000, 0xcd2c, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcd2d, 0x0000, 0x000e, 0xb031 },
|
||||
{ 0x0000, 0xcd2e, 0x0000, 0x0076, 0xb031 },
|
||||
{ 0x0000, 0xcd2f, 0x0000, 0x0043, 0xb031 },
|
||||
{ 0x0000, 0xcc24, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcc25, 0x0000, 0x0051, 0xb031 },
|
||||
{ 0x0000, 0xcc26, 0x0000, 0x00eb, 0xb031 },
|
||||
{ 0x0000, 0xcc27, 0x0000, 0x0085, 0xb031 },
|
||||
{ 0x0000, 0xcd24, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcd25, 0x0000, 0x0051, 0xb031 },
|
||||
{ 0x0000, 0xcd26, 0x0000, 0x00eb, 0xb031 },
|
||||
{ 0x0000, 0xcd27, 0x0000, 0x0085, 0xb031 },
|
||||
{ 0x0000, 0xcc20, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcc21, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcc22, 0x0000, 0x0043, 0xb031 },
|
||||
{ 0x0000, 0xcd20, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcd21, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcd22, 0x0000, 0x0043, 0xb031 },
|
||||
{ 0x0000, 0xcc16, 0x0000, 0x000f, 0xb031 },
|
||||
{ 0x0000, 0xcc17, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcd16, 0x0000, 0x000f, 0xb031 },
|
||||
{ 0x0000, 0xcd17, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcc29, 0x0000, 0x005d, 0xb031 },
|
||||
{ 0x0000, 0xcc2a, 0x0000, 0x00c0, 0xb031 },
|
||||
{ 0x0000, 0xcd29, 0x0000, 0x005d, 0xb031 },
|
||||
{ 0x0000, 0xcd2a, 0x0000, 0x00c0, 0xb031 },
|
||||
{ 0x0000, 0xcc31, 0x0000, 0x0020, 0xb031 },
|
||||
{ 0x0000, 0xcc32, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcc33, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcc34, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcd31, 0x0000, 0x0020, 0xb031 },
|
||||
{ 0x0000, 0xcd32, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcd33, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcd34, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcc36, 0x0000, 0x0079, 0xb031 },
|
||||
{ 0x0000, 0xcc37, 0x0000, 0x0099, 0xb031 },
|
||||
{ 0x0000, 0xcc38, 0x0000, 0x0099, 0xb031 },
|
||||
{ 0x0000, 0xcc39, 0x0000, 0x0099, 0xb031 },
|
||||
{ 0x0000, 0xcd36, 0x0000, 0x0079, 0xb031 },
|
||||
{ 0x0000, 0xcd37, 0x0000, 0x0099, 0xb031 },
|
||||
{ 0x0000, 0xcd38, 0x0000, 0x0099, 0xb031 },
|
||||
{ 0x0000, 0xcd39, 0x0000, 0x0099, 0xb031 },
|
||||
{ 0x0000, 0xcc09, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcc0a, 0x0000, 0x000a, 0xb031 },
|
||||
{ 0x0000, 0xcc0b, 0x0000, 0x007c, 0xb031 },
|
||||
{ 0x0000, 0xcc0c, 0x0000, 0x005b, 0xb031 },
|
||||
{ 0x0000, 0xcd09, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcd0a, 0x0000, 0x000a, 0xb031 },
|
||||
{ 0x0000, 0xcd0b, 0x0000, 0x007c, 0xb031 },
|
||||
{ 0x0000, 0xcd0c, 0x0000, 0x005b, 0xb031 },
|
||||
{ 0x0000, 0xcc0e, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcc0f, 0x0000, 0x0005, 0xb031 },
|
||||
{ 0x0000, 0xcc10, 0x0000, 0x003e, 0xb031 },
|
||||
{ 0x0000, 0xcc11, 0x0000, 0x002d, 0xb031 },
|
||||
{ 0x0000, 0xcd0e, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcd0f, 0x0000, 0x0005, 0xb031 },
|
||||
{ 0x0000, 0xcd10, 0x0000, 0x003e, 0xb031 },
|
||||
{ 0x0000, 0xcd11, 0x0000, 0x002d, 0xb031 },
|
||||
{ 0x0000, 0xccd6, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xccd7, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xcdd6, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcdd7, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xccd8, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xccd9, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xcdd8, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcdd9, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xccda, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xccdb, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xcdda, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xcddb, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xc320, 0x0000, 0x0020, 0xb031 },
|
||||
{ 0x0000, 0xc321, 0x0000, 0x000a, 0xb031 },
|
||||
{ 0x0000, 0xe604, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xdb00, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xdd00, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xdc19, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xdc1a, 0x0000, 0x006a, 0xb031 },
|
||||
{ 0x0000, 0xdc1b, 0x0000, 0x00aa, 0xb031 },
|
||||
{ 0x0000, 0xdc1c, 0x0000, 0x00ab, 0xb031 },
|
||||
{ 0x0000, 0xdc1d, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xdc1e, 0x0000, 0x0027, 0xb031 },
|
||||
{ 0x0000, 0xdc1f, 0x0000, 0x0062, 0xb031 },
|
||||
{ 0x0000, 0xdc20, 0x0000, 0x0076, 0xb031 },
|
||||
{ 0x0000, 0xde19, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xde1a, 0x0000, 0x006a, 0xb031 },
|
||||
{ 0x0000, 0xde1b, 0x0000, 0x00aa, 0xb031 },
|
||||
{ 0x0000, 0xde1c, 0x0000, 0x00ab, 0xb031 },
|
||||
{ 0x0000, 0xde1d, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xde1e, 0x0000, 0x0027, 0xb031 },
|
||||
{ 0x0000, 0xde1f, 0x0000, 0x0062, 0xb031 },
|
||||
{ 0x0000, 0xde20, 0x0000, 0x0076, 0xb031 },
|
||||
{ 0x0000, 0xdb32, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xdd32, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xdb33, 0x0000, 0x000a, 0xb031 },
|
||||
{ 0x0000, 0xdd33, 0x0000, 0x000a, 0xb031 },
|
||||
{ 0x0000, 0xdb34, 0x0000, 0x001a, 0xb031 },
|
||||
{ 0x0000, 0xdd34, 0x0000, 0x001a, 0xb031 },
|
||||
{ 0x0000, 0xdb15, 0x0000, 0x00ef, 0xb031 },
|
||||
{ 0x0000, 0xdd15, 0x0000, 0x00ef, 0xb031 },
|
||||
{ 0x0000, 0xdb17, 0x0000, 0x003f, 0xb031 },
|
||||
{ 0x0000, 0xdd17, 0x0000, 0x003f, 0xb031 },
|
||||
{ 0x0000, 0xdb94, 0x0000, 0x0070, 0xb031 },
|
||||
{ 0x0000, 0xdd94, 0x0000, 0x0070, 0xb031 },
|
||||
{ 0x0000, 0xdb19, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xdd19, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xc203, 0x0000, 0x001c, 0xb031 },
|
||||
{ 0x0000, 0xdb00, 0x0000, 0x004c, 0xb031 },
|
||||
{ 0x0000, 0xdb04, 0x0000, 0x0005, 0xb031 },
|
||||
{ 0x0000, 0xdb05, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xdd04, 0x0000, 0x0005, 0xb031 },
|
||||
{ 0x0000, 0xdd05, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xdbbb, 0x0000, 0x0009, 0xb031 },
|
||||
{ 0x0000, 0xdbbc, 0x0000, 0x004c, 0xb031 },
|
||||
{ 0x0000, 0xdbbd, 0x0000, 0x00f3, 0xb031 },
|
||||
{ 0x0000, 0xdbbe, 0x0000, 0x00cf, 0xb031 },
|
||||
{ 0x0000, 0xddbb, 0x0000, 0x0009, 0xb031 },
|
||||
{ 0x0000, 0xddbc, 0x0000, 0x004c, 0xb031 },
|
||||
{ 0x0000, 0xddbd, 0x0000, 0x00f3, 0xb031 },
|
||||
{ 0x0000, 0xddbe, 0x0000, 0x00cf, 0xb031 },
|
||||
{ 0x0000, 0xdb01, 0x0000, 0x0079, 0xb031 },
|
||||
{ 0x0000, 0xdd01, 0x0000, 0x0079, 0xb031 },
|
||||
{ 0x0000, 0xdb08, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xdd08, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xdc52, 0x0000, 0x00ef, 0xb031 },
|
||||
{ 0x0000, 0xde52, 0x0000, 0x00ef, 0xb031 },
|
||||
{ 0x0000, 0xdb00, 0x0000, 0x00cc, 0xb031 },
|
||||
{ 0x0000, 0xc203, 0x0000, 0x009c, 0xb031 },
|
||||
{ 0x0000, 0xdf0a, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xdf0b, 0x0000, 0x007f, 0xb031 },
|
||||
{ 0x0000, 0xc851, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xc951, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xdf01, 0x0000, 0x0073, 0xb031 },
|
||||
{ 0x0000, 0xc203, 0x0000, 0x009c, 0xb031 },
|
||||
{ 0x0000, 0xf800, 0x0000, 0x0020, 0xb031 },
|
||||
{ 0x0000, 0xebcb, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xeb10, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xeb11, 0x0000, 0x00bb, 0xb031 },
|
||||
{ 0x0000, 0xeb12, 0x0000, 0x00ab, 0xb031 },
|
||||
{ 0x0000, 0xeb13, 0x0000, 0x0030, 0xb031 },
|
||||
{ 0x0000, 0xeb14, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xeb15, 0x0000, 0x004c, 0xb031 },
|
||||
{ 0x0000, 0xeb16, 0x0000, 0x0069, 0xb031 },
|
||||
{ 0x0000, 0xeb21, 0x0000, 0x0011, 0xb031 },
|
||||
{ 0x0000, 0xeb22, 0x0000, 0x00c2, 0xb031 },
|
||||
{ 0x0000, 0xeb23, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xeb24, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xeb25, 0x0000, 0x00bd, 0xb031 },
|
||||
{ 0x0000, 0xeb26, 0x0000, 0x0055, 0xb031 },
|
||||
{ 0x0000, 0xeb27, 0x0000, 0x00d0, 0xb031 },
|
||||
{ 0x0000, 0xeb28, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xeb29, 0x0000, 0x003c, 0xb031 },
|
||||
{ 0x0000, 0xeb2a, 0x0000, 0x0051, 0xb031 },
|
||||
{ 0x0000, 0xeb2b, 0x0000, 0x0018, 0xb031 },
|
||||
{ 0x0000, 0xeb30, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xeb31, 0x0000, 0x004f, 0xb031 },
|
||||
{ 0x0000, 0xeb32, 0x0000, 0x004a, 0xb031 },
|
||||
{ 0x0000, 0xeb33, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xeb34, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xeb35, 0x0000, 0x00bb, 0xb031 },
|
||||
{ 0x0000, 0xeb36, 0x0000, 0x0024, 0xb031 },
|
||||
{ 0x0000, 0xeb37, 0x0000, 0x0068, 0xb031 },
|
||||
{ 0x0000, 0xeb40, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xeb41, 0x0000, 0x00f5, 0xb031 },
|
||||
{ 0x0000, 0xeb42, 0x0000, 0x00f1, 0xb031 },
|
||||
{ 0x0000, 0xeb43, 0x0000, 0x00e8, 0xb031 },
|
||||
{ 0x0000, 0xeb44, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xeb45, 0x0000, 0x004f, 0xb031 },
|
||||
{ 0x0000, 0xeb46, 0x0000, 0x004a, 0xb031 },
|
||||
{ 0x0000, 0xeb47, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xeb48, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xeb49, 0x0000, 0x00c5, 0xb031 },
|
||||
{ 0x0000, 0xeb4a, 0x0000, 0x0032, 0xb031 },
|
||||
{ 0x0000, 0xeb4b, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xeb50, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xeb51, 0x0000, 0x008a, 0xb031 },
|
||||
{ 0x0000, 0xeb52, 0x0000, 0x00b4, 0xb031 },
|
||||
{ 0x0000, 0xeb53, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xeb54, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xeb55, 0x0000, 0x007d, 0xb031 },
|
||||
{ 0x0000, 0xeb56, 0x0000, 0x00d9, 0xb031 },
|
||||
{ 0x0000, 0xeb57, 0x0000, 0x0008, 0xb031 },
|
||||
{ 0x0000, 0xeb60, 0x0000, 0x0002, 0xb031 },
|
||||
{ 0x0000, 0xeb61, 0x0000, 0x00e7, 0xb031 },
|
||||
{ 0x0000, 0xeb62, 0x0000, 0x00b5, 0xb031 },
|
||||
{ 0x0000, 0xeb63, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xeb64, 0x0000, 0x00fa, 0xb031 },
|
||||
{ 0x0000, 0xeb65, 0x0000, 0x0086, 0xb031 },
|
||||
{ 0x0000, 0xeb66, 0x0000, 0x00a8, 0xb031 },
|
||||
{ 0x0000, 0xeb67, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xeb68, 0x0000, 0x0002, 0xb031 },
|
||||
{ 0x0000, 0xeb69, 0x0000, 0x009a, 0xb031 },
|
||||
{ 0x0000, 0xeb6a, 0x0000, 0x002f, 0xb031 },
|
||||
{ 0x0000, 0xeb6b, 0x0000, 0x0018, 0xb031 },
|
||||
{ 0x0000, 0xebb6, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xeb70, 0x0000, 0x00f5, 0xb031 },
|
||||
{ 0x0000, 0xeb71, 0x0000, 0x00e1, 0xb031 },
|
||||
{ 0x0000, 0xeb72, 0x0000, 0x0009, 0xb031 },
|
||||
{ 0x0000, 0xeb73, 0x0000, 0x00d0, 0xb031 },
|
||||
{ 0x0000, 0xeb74, 0x0000, 0x0006, 0xb031 },
|
||||
{ 0x0000, 0xeb75, 0x0000, 0x0050, 0xb031 },
|
||||
{ 0x0000, 0xeb76, 0x0000, 0x002c, 0xb031 },
|
||||
{ 0x0000, 0xeb77, 0x0000, 0x0050, 0xb031 },
|
||||
{ 0x0000, 0xeb80, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xeb81, 0x0000, 0x0028, 0xb031 },
|
||||
{ 0x0000, 0xeb82, 0x0000, 0x0016, 0xb031 },
|
||||
{ 0x0000, 0xeb83, 0x0000, 0x0028, 0xb031 },
|
||||
{ 0x0000, 0xeb84, 0x0000, 0x00f5, 0xb031 },
|
||||
{ 0x0000, 0xeb85, 0x0000, 0x00e1, 0xb031 },
|
||||
{ 0x0000, 0xeb86, 0x0000, 0x0009, 0xb031 },
|
||||
{ 0x0000, 0xeb87, 0x0000, 0x00d0, 0xb031 },
|
||||
{ 0x0000, 0xeb88, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xeb89, 0x0000, 0x0028, 0xb031 },
|
||||
{ 0x0000, 0xeb8a, 0x0000, 0x0016, 0xb031 },
|
||||
{ 0x0000, 0xeb8b, 0x0000, 0x0028, 0xb031 },
|
||||
{ 0x0000, 0xebb8, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xeb90, 0x0000, 0x00fc, 0xb031 },
|
||||
{ 0x0000, 0xeb91, 0x0000, 0x008b, 0xb031 },
|
||||
{ 0x0000, 0xeb92, 0x0000, 0x00bd, 0xb031 },
|
||||
{ 0x0000, 0xeb93, 0x0000, 0x0064, 0xb031 },
|
||||
{ 0x0000, 0xeb94, 0x0000, 0x0001, 0xb031 },
|
||||
{ 0x0000, 0xeb95, 0x0000, 0x0099, 0xb031 },
|
||||
{ 0x0000, 0xeb96, 0x0000, 0x00e7, 0xb031 },
|
||||
{ 0x0000, 0xeb97, 0x0000, 0x0094, 0xb031 },
|
||||
{ 0x0000, 0xeba0, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xeba1, 0x0000, 0x0091, 0xb031 },
|
||||
{ 0x0000, 0xeba2, 0x0000, 0x0078, 0xb031 },
|
||||
{ 0x0000, 0xeba3, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xeba4, 0x0000, 0x00f6, 0xb031 },
|
||||
{ 0x0000, 0xeba5, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xeba6, 0x0000, 0x0093, 0xb031 },
|
||||
{ 0x0000, 0xeba7, 0x0000, 0x0010, 0xb031 },
|
||||
{ 0x0000, 0xeba8, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xeba9, 0x0000, 0x0087, 0xb031 },
|
||||
{ 0x0000, 0xebaa, 0x0000, 0x0099, 0xb031 },
|
||||
{ 0x0000, 0xebab, 0x0000, 0x006c, 0xb031 },
|
||||
{ 0x0000, 0xebc3, 0x0000, 0x00ff, 0xb031 },
|
||||
{ 0x0000, 0xebc4, 0x0000, 0x00fc, 0xb031 },
|
||||
{ 0x0000, 0xeb00, 0x0000, 0x0005, 0xb031 },
|
||||
{ 0x0000, 0xeb01, 0x0000, 0x00a9, 0xb031 },
|
||||
{ 0x0000, 0xeb02, 0x0000, 0x00df, 0xb031 },
|
||||
{ 0x0000, 0xeb03, 0x0000, 0x007b, 0xb031 },
|
||||
{ 0x0000, 0xeb05, 0x0000, 0x0079, 0xb031 },
|
||||
{ 0x0000, 0xeb06, 0x0000, 0x005a, 0xb031 },
|
||||
{ 0x0000, 0xeb07, 0x0000, 0x0004, 0xb031 },
|
||||
{ 0x0000, 0xebc0, 0x0000, 0x00e3, 0xb031 },
|
||||
{ 0x0000, 0xd0cb, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xd0b0, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xd010, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd011, 0x0000, 0x0009, 0xb031 },
|
||||
{ 0x0000, 0xd012, 0x0000, 0x0092, 0xb031 },
|
||||
{ 0x0000, 0xd013, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd014, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xd015, 0x0000, 0x00f6, 0xb031 },
|
||||
{ 0x0000, 0xd016, 0x0000, 0x0072, 0xb031 },
|
||||
{ 0x0000, 0xd017, 0x0000, 0x00b0, 0xb031 },
|
||||
{ 0x0000, 0xd020, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xd021, 0x0000, 0x00fb, 0xb031 },
|
||||
{ 0x0000, 0xd022, 0x0000, 0x0037, 0xb031 },
|
||||
{ 0x0000, 0xd023, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd024, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd025, 0x0000, 0x0009, 0xb031 },
|
||||
{ 0x0000, 0xd026, 0x0000, 0x0090, 0xb031 },
|
||||
{ 0x0000, 0xd027, 0x0000, 0x0020, 0xb031 },
|
||||
{ 0x0000, 0xd028, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xd029, 0x0000, 0x00fb, 0xb031 },
|
||||
{ 0x0000, 0xd02a, 0x0000, 0x0037, 0xb031 },
|
||||
{ 0x0000, 0xd02b, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd0c3, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd0c4, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xd0c0, 0x0000, 0x00e3, 0xb031 },
|
||||
{ 0x0000, 0xce6a, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xce63, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xce64, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xce60, 0x0000, 0x00e3, 0xb031 },
|
||||
{ 0x0000, 0xdb00, 0x0000, 0x00cc, 0xb031 },
|
||||
{ 0x0000, 0xdb04, 0x0000, 0x0008, 0xb031 },
|
||||
{ 0x0000, 0xdb05, 0x0000, 0x0006, 0xb031 },
|
||||
{ 0x0000, 0xcc00, 0x0000, 0x00c1, 0xb031 },
|
||||
{ 0x0000, 0xca02, 0x0000, 0x000f, 0xb031 },
|
||||
{ 0x0000, 0xca00, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xca62, 0x0000, 0x0077, 0xb031 },
|
||||
{ 0x0000, 0xca65, 0x0000, 0x0082, 0xb031 },
|
||||
{ 0x0000, 0xca68, 0x0000, 0x00c2, 0xb031 },
|
||||
{ 0x0000, 0xca75, 0x0000, 0x003a, 0xb031 },
|
||||
{ 0x0000, 0xca7b, 0x0000, 0x006f, 0xb031 },
|
||||
{ 0x0000, 0xca00, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xca02, 0x0000, 0x0078, 0xb031 },
|
||||
{ 0x0000, 0xc860, 0x0000, 0x0078, 0xb031 },
|
||||
{ 0x0000, 0xc861, 0x0000, 0x00e5, 0xb031 },
|
||||
{ 0x0000, 0xc862, 0x0000, 0x00eb, 0xb031 },
|
||||
{ 0x0000, 0xc863, 0x0000, 0x00c6, 0xb031 },
|
||||
{ 0x0000, 0xc864, 0x0000, 0x00ba, 0xb031 },
|
||||
{ 0x0000, 0xc865, 0x0000, 0x0061, 0xb031 },
|
||||
{ 0x0000, 0xc867, 0x0000, 0x0017, 0xb031 },
|
||||
{ 0x0000, 0xc868, 0x0000, 0x00ed, 0xb031 },
|
||||
{ 0x0000, 0xc869, 0x0000, 0x003c, 0xb031 },
|
||||
{ 0x0000, 0xc86a, 0x0000, 0x008a, 0xb031 },
|
||||
{ 0x0000, 0xc86b, 0x0000, 0x00e2, 0xb031 },
|
||||
{ 0x0000, 0xc875, 0x0000, 0x003a, 0xb031 },
|
||||
{ 0x0000, 0xc87b, 0x0000, 0x006f, 0xb031 },
|
||||
{ 0x0000, 0xc836, 0x0000, 0x00f9, 0xb031 },
|
||||
{ 0x0000, 0xc8a0, 0x0000, 0x00f1, 0xb031 },
|
||||
{ 0x0000, 0xc833, 0x0000, 0x000b, 0xb031 },
|
||||
{ 0x0000, 0xc834, 0x0000, 0x0002, 0xb031 },
|
||||
{ 0x0000, 0xc83f, 0x0000, 0x0014, 0xb031 },
|
||||
{ 0x0000, 0xc83e, 0x0000, 0x0094, 0xb031 },
|
||||
{ 0x0000, 0xc83a, 0x0000, 0x0076, 0xb031 },
|
||||
{ 0x0000, 0xc83b, 0x0000, 0x0089, 0xb031 },
|
||||
{ 0x0000, 0xc830, 0x0000, 0x0013, 0xb031 },
|
||||
{ 0x0000, 0xc826, 0x0000, 0x00d1, 0xb031 },
|
||||
{ 0x0000, 0xc890, 0x0000, 0x00f1, 0xb031 },
|
||||
{ 0x0000, 0xc823, 0x0000, 0x0010, 0xb031 },
|
||||
{ 0x0000, 0xc824, 0x0000, 0x0004, 0xb031 },
|
||||
{ 0x0000, 0xc82f, 0x0000, 0x0018, 0xb031 },
|
||||
{ 0x0000, 0xc82e, 0x0000, 0x0094, 0xb031 },
|
||||
{ 0x0000, 0xc820, 0x0000, 0x0008, 0xb031 },
|
||||
{ 0x0000, 0xc816, 0x0000, 0x00f9, 0xb031 },
|
||||
{ 0x0000, 0xc880, 0x0000, 0x00e1, 0xb031 },
|
||||
{ 0x0000, 0xc813, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xc814, 0x0000, 0x0001, 0xb031 },
|
||||
{ 0x0000, 0xc81f, 0x0000, 0x0014, 0xb031 },
|
||||
{ 0x0000, 0xc81e, 0x0000, 0x0094, 0xb031 },
|
||||
{ 0x0000, 0xc81a, 0x0000, 0x0066, 0xb031 },
|
||||
{ 0x0000, 0xc81b, 0x0000, 0x0078, 0xb031 },
|
||||
{ 0x0000, 0xc810, 0x0000, 0x000d, 0xb031 },
|
||||
{ 0x0000, 0xc846, 0x0000, 0x00f9, 0xb031 },
|
||||
{ 0x0000, 0xc8d0, 0x0000, 0x00f1, 0xb031 },
|
||||
{ 0x0000, 0xc844, 0x0000, 0x0001, 0xb031 },
|
||||
{ 0x0000, 0xc84f, 0x0000, 0x0014, 0xb031 },
|
||||
{ 0x0000, 0xc84e, 0x0000, 0x0094, 0xb031 },
|
||||
{ 0x0000, 0xc84a, 0x0000, 0x0026, 0xb031 },
|
||||
{ 0x0000, 0xc84b, 0x0000, 0x0056, 0xb031 },
|
||||
{ 0x0000, 0xc800, 0x0000, 0x00b0, 0xb031 },
|
||||
{ 0x0000, 0xc851, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xc500, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xc501, 0x0000, 0x0026, 0xb031 },
|
||||
{ 0x0000, 0xc502, 0x0000, 0x004a, 0xb031 },
|
||||
{ 0x0000, 0xc503, 0x0000, 0x0010, 0xb031 },
|
||||
{ 0x0000, 0xc504, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xc505, 0x0000, 0x00da, 0xb031 },
|
||||
{ 0x0000, 0xc506, 0x0000, 0x000e, 0xb031 },
|
||||
{ 0x0000, 0xc507, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xc510, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xc511, 0x0000, 0x00da, 0xb031 },
|
||||
{ 0x0000, 0xc512, 0x0000, 0x000e, 0xb031 },
|
||||
{ 0x0000, 0xc513, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xc514, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xc515, 0x0000, 0x0026, 0xb031 },
|
||||
{ 0x0000, 0xc516, 0x0000, 0x004a, 0xb031 },
|
||||
{ 0x0000, 0xc517, 0x0000, 0x0010, 0xb031 },
|
||||
{ 0x0000, 0xc518, 0x0000, 0x0008, 0xb031 },
|
||||
{ 0x0000, 0xc541, 0x0000, 0x0030, 0xb031 },
|
||||
{ 0x0000, 0xd250, 0x0000, 0x0087, 0xb031 },
|
||||
{ 0x0000, 0xd251, 0x0000, 0x0030, 0xb031 },
|
||||
{ 0x0000, 0xd264, 0x0000, 0x00c0, 0xb031 },
|
||||
{ 0x0000, 0xc203, 0x0000, 0x009c, 0xb031 },
|
||||
{ 0x0000, 0xf800, 0x0000, 0x0020, 0xb031 },
|
||||
{ 0x0000, 0xecb0, 0x0000, 0x0008, 0xb031 },
|
||||
{ 0x0000, 0xec10, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xec11, 0x0000, 0x00bb, 0xb031 },
|
||||
{ 0x0000, 0xec12, 0x0000, 0x00ab, 0xb031 },
|
||||
{ 0x0000, 0xec13, 0x0000, 0x0030, 0xb031 },
|
||||
{ 0x0000, 0xec14, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xec15, 0x0000, 0x004c, 0xb031 },
|
||||
{ 0x0000, 0xec16, 0x0000, 0x0069, 0xb031 },
|
||||
{ 0x0000, 0xec21, 0x0000, 0x0011, 0xb031 },
|
||||
{ 0x0000, 0xec22, 0x0000, 0x00c2, 0xb031 },
|
||||
{ 0x0000, 0xec23, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xec24, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xec25, 0x0000, 0x00bd, 0xb031 },
|
||||
{ 0x0000, 0xec26, 0x0000, 0x0055, 0xb031 },
|
||||
{ 0x0000, 0xec27, 0x0000, 0x00d0, 0xb031 },
|
||||
{ 0x0000, 0xec28, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xec29, 0x0000, 0x003c, 0xb031 },
|
||||
{ 0x0000, 0xec2a, 0x0000, 0x0051, 0xb031 },
|
||||
{ 0x0000, 0xec2b, 0x0000, 0x0018, 0xb031 },
|
||||
{ 0x0000, 0xecb2, 0x0000, 0x0008, 0xb031 },
|
||||
{ 0x0000, 0xec30, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xec31, 0x0000, 0x004f, 0xb031 },
|
||||
{ 0x0000, 0xec32, 0x0000, 0x004a, 0xb031 },
|
||||
{ 0x0000, 0xec33, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xec34, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xec35, 0x0000, 0x00bb, 0xb031 },
|
||||
{ 0x0000, 0xec36, 0x0000, 0x0024, 0xb031 },
|
||||
{ 0x0000, 0xec37, 0x0000, 0x0068, 0xb031 },
|
||||
{ 0x0000, 0xec40, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xec41, 0x0000, 0x00f5, 0xb031 },
|
||||
{ 0x0000, 0xec42, 0x0000, 0x00f1, 0xb031 },
|
||||
{ 0x0000, 0xec43, 0x0000, 0x00e8, 0xb031 },
|
||||
{ 0x0000, 0xec44, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xec45, 0x0000, 0x004f, 0xb031 },
|
||||
{ 0x0000, 0xec46, 0x0000, 0x004a, 0xb031 },
|
||||
{ 0x0000, 0xec47, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xec48, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xec49, 0x0000, 0x00c5, 0xb031 },
|
||||
{ 0x0000, 0xec4a, 0x0000, 0x0032, 0xb031 },
|
||||
{ 0x0000, 0xec4b, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xecb4, 0x0000, 0x0008, 0xb031 },
|
||||
{ 0x0000, 0xec50, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xec51, 0x0000, 0x008a, 0xb031 },
|
||||
{ 0x0000, 0xec52, 0x0000, 0x00b4, 0xb031 },
|
||||
{ 0x0000, 0xec53, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xec54, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xec55, 0x0000, 0x007d, 0xb031 },
|
||||
{ 0x0000, 0xec56, 0x0000, 0x00d9, 0xb031 },
|
||||
{ 0x0000, 0xec57, 0x0000, 0x0008, 0xb031 },
|
||||
{ 0x0000, 0xec60, 0x0000, 0x0002, 0xb031 },
|
||||
{ 0x0000, 0xec61, 0x0000, 0x00e7, 0xb031 },
|
||||
{ 0x0000, 0xec62, 0x0000, 0x00b5, 0xb031 },
|
||||
{ 0x0000, 0xec63, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xec64, 0x0000, 0x00fa, 0xb031 },
|
||||
{ 0x0000, 0xec65, 0x0000, 0x0086, 0xb031 },
|
||||
{ 0x0000, 0xec66, 0x0000, 0x00a8, 0xb031 },
|
||||
{ 0x0000, 0xec67, 0x0000, 0x0040, 0xb031 },
|
||||
{ 0x0000, 0xec68, 0x0000, 0x0002, 0xb031 },
|
||||
{ 0x0000, 0xec69, 0x0000, 0x009a, 0xb031 },
|
||||
{ 0x0000, 0xec6a, 0x0000, 0x002f, 0xb031 },
|
||||
{ 0x0000, 0xec6b, 0x0000, 0x0018, 0xb031 },
|
||||
{ 0x0000, 0xecb6, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xec70, 0x0000, 0x00f5, 0xb031 },
|
||||
{ 0x0000, 0xec71, 0x0000, 0x00e1, 0xb031 },
|
||||
{ 0x0000, 0xec72, 0x0000, 0x0009, 0xb031 },
|
||||
{ 0x0000, 0xec73, 0x0000, 0x00d0, 0xb031 },
|
||||
{ 0x0000, 0xec74, 0x0000, 0x0006, 0xb031 },
|
||||
{ 0x0000, 0xec75, 0x0000, 0x0050, 0xb031 },
|
||||
{ 0x0000, 0xec76, 0x0000, 0x002c, 0xb031 },
|
||||
{ 0x0000, 0xec77, 0x0000, 0x0050, 0xb031 },
|
||||
{ 0x0000, 0xec80, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xec81, 0x0000, 0x0028, 0xb031 },
|
||||
{ 0x0000, 0xec82, 0x0000, 0x0016, 0xb031 },
|
||||
{ 0x0000, 0xec83, 0x0000, 0x0028, 0xb031 },
|
||||
{ 0x0000, 0xec84, 0x0000, 0x00f5, 0xb031 },
|
||||
{ 0x0000, 0xec85, 0x0000, 0x00e1, 0xb031 },
|
||||
{ 0x0000, 0xec86, 0x0000, 0x0009, 0xb031 },
|
||||
{ 0x0000, 0xec87, 0x0000, 0x00d0, 0xb031 },
|
||||
{ 0x0000, 0xec88, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xec89, 0x0000, 0x0028, 0xb031 },
|
||||
{ 0x0000, 0xec8a, 0x0000, 0x0016, 0xb031 },
|
||||
{ 0x0000, 0xec8b, 0x0000, 0x0028, 0xb031 },
|
||||
{ 0x0000, 0xecb8, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xec90, 0x0000, 0x00fc, 0xb031 },
|
||||
{ 0x0000, 0xec91, 0x0000, 0x008b, 0xb031 },
|
||||
{ 0x0000, 0xec92, 0x0000, 0x00bd, 0xb031 },
|
||||
{ 0x0000, 0xec93, 0x0000, 0x0064, 0xb031 },
|
||||
{ 0x0000, 0xec94, 0x0000, 0x0001, 0xb031 },
|
||||
{ 0x0000, 0xec95, 0x0000, 0x0099, 0xb031 },
|
||||
{ 0x0000, 0xec96, 0x0000, 0x00e7, 0xb031 },
|
||||
{ 0x0000, 0xec97, 0x0000, 0x0094, 0xb031 },
|
||||
{ 0x0000, 0xeca0, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xeca1, 0x0000, 0x0091, 0xb031 },
|
||||
{ 0x0000, 0xeca2, 0x0000, 0x0078, 0xb031 },
|
||||
{ 0x0000, 0xeca3, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xeca4, 0x0000, 0x00f6, 0xb031 },
|
||||
{ 0x0000, 0xeca5, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xeca6, 0x0000, 0x0093, 0xb031 },
|
||||
{ 0x0000, 0xeca7, 0x0000, 0x0010, 0xb031 },
|
||||
{ 0x0000, 0xeca8, 0x0000, 0x0003, 0xb031 },
|
||||
{ 0x0000, 0xeca9, 0x0000, 0x0087, 0xb031 },
|
||||
{ 0x0000, 0xecaa, 0x0000, 0x0099, 0xb031 },
|
||||
{ 0x0000, 0xecab, 0x0000, 0x006c, 0xb031 },
|
||||
{ 0x0000, 0xebc3, 0x0000, 0x00ff, 0xb031 },
|
||||
{ 0x0000, 0xebc4, 0x0000, 0x00fc, 0xb031 },
|
||||
{ 0x0000, 0xec00, 0x0000, 0x0005, 0xb031 },
|
||||
{ 0x0000, 0xec01, 0x0000, 0x00a9, 0xb031 },
|
||||
{ 0x0000, 0xec02, 0x0000, 0x00df, 0xb031 },
|
||||
{ 0x0000, 0xec03, 0x0000, 0x007b, 0xb031 },
|
||||
{ 0x0000, 0xec05, 0x0000, 0x0079, 0xb031 },
|
||||
{ 0x0000, 0xec06, 0x0000, 0x005a, 0xb031 },
|
||||
{ 0x0000, 0xec07, 0x0000, 0x0004, 0xb031 },
|
||||
{ 0x0000, 0xebc0, 0x0000, 0x00e3, 0xb031 },
|
||||
{ 0x0000, 0xd1b0, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xd110, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd111, 0x0000, 0x0009, 0xb031 },
|
||||
{ 0x0000, 0xd112, 0x0000, 0x0092, 0xb031 },
|
||||
{ 0x0000, 0xd113, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd114, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xd115, 0x0000, 0x00f6, 0xb031 },
|
||||
{ 0x0000, 0xd116, 0x0000, 0x0072, 0xb031 },
|
||||
{ 0x0000, 0xd117, 0x0000, 0x00b0, 0xb031 },
|
||||
{ 0x0000, 0xd120, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xd121, 0x0000, 0x00fb, 0xb031 },
|
||||
{ 0x0000, 0xd122, 0x0000, 0x0037, 0xb031 },
|
||||
{ 0x0000, 0xd123, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd124, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd125, 0x0000, 0x0009, 0xb031 },
|
||||
{ 0x0000, 0xd126, 0x0000, 0x0090, 0xb031 },
|
||||
{ 0x0000, 0xd127, 0x0000, 0x0020, 0xb031 },
|
||||
{ 0x0000, 0xd128, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xd129, 0x0000, 0x00fb, 0xb031 },
|
||||
{ 0x0000, 0xd12a, 0x0000, 0x0037, 0xb031 },
|
||||
{ 0x0000, 0xd12b, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd0c3, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd0c4, 0x0000, 0x000c, 0xb031 },
|
||||
{ 0x0000, 0xd0c0, 0x0000, 0x00e3, 0xb031 },
|
||||
{ 0x0000, 0xce63, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xce64, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xce60, 0x0000, 0x00e3, 0xb031 },
|
||||
{ 0x0000, 0xdb00, 0x0000, 0x00cc, 0xb031 },
|
||||
{ 0x0000, 0xdd04, 0x0000, 0x0008, 0xb031 },
|
||||
{ 0x0000, 0xdd05, 0x0000, 0x0006, 0xb031 },
|
||||
{ 0x0000, 0xca12, 0x0000, 0x000f, 0xb031 },
|
||||
{ 0x0000, 0xca10, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xca82, 0x0000, 0x0077, 0xb031 },
|
||||
{ 0x0000, 0xca85, 0x0000, 0x0082, 0xb031 },
|
||||
{ 0x0000, 0xca88, 0x0000, 0x00c2, 0xb031 },
|
||||
{ 0x0000, 0xca95, 0x0000, 0x003a, 0xb031 },
|
||||
{ 0x0000, 0xca9b, 0x0000, 0x006f, 0xb031 },
|
||||
{ 0x0000, 0xca10, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xca12, 0x0000, 0x0078, 0xb031 },
|
||||
{ 0x0000, 0xc960, 0x0000, 0x0078, 0xb031 },
|
||||
{ 0x0000, 0xc961, 0x0000, 0x00e5, 0xb031 },
|
||||
{ 0x0000, 0xc962, 0x0000, 0x00eb, 0xb031 },
|
||||
{ 0x0000, 0xc963, 0x0000, 0x00c6, 0xb031 },
|
||||
{ 0x0000, 0xc964, 0x0000, 0x00ba, 0xb031 },
|
||||
{ 0x0000, 0xc965, 0x0000, 0x0061, 0xb031 },
|
||||
{ 0x0000, 0xc967, 0x0000, 0x0017, 0xb031 },
|
||||
{ 0x0000, 0xc968, 0x0000, 0x00ed, 0xb031 },
|
||||
{ 0x0000, 0xc969, 0x0000, 0x003c, 0xb031 },
|
||||
{ 0x0000, 0xc96a, 0x0000, 0x008a, 0xb031 },
|
||||
{ 0x0000, 0xc96b, 0x0000, 0x00e2, 0xb031 },
|
||||
{ 0x0000, 0xc975, 0x0000, 0x003a, 0xb031 },
|
||||
{ 0x0000, 0xc97b, 0x0000, 0x006f, 0xb031 },
|
||||
{ 0x0000, 0xc936, 0x0000, 0x00f9, 0xb031 },
|
||||
{ 0x0000, 0xc9a0, 0x0000, 0x00f1, 0xb031 },
|
||||
{ 0x0000, 0xc933, 0x0000, 0x000b, 0xb031 },
|
||||
{ 0x0000, 0xc934, 0x0000, 0x0002, 0xb031 },
|
||||
{ 0x0000, 0xc93f, 0x0000, 0x0014, 0xb031 },
|
||||
{ 0x0000, 0xc93e, 0x0000, 0x0094, 0xb031 },
|
||||
{ 0x0000, 0xc93a, 0x0000, 0x0076, 0xb031 },
|
||||
{ 0x0000, 0xc93b, 0x0000, 0x0089, 0xb031 },
|
||||
{ 0x0000, 0xc930, 0x0000, 0x0013, 0xb031 },
|
||||
{ 0x0000, 0xc926, 0x0000, 0x00d1, 0xb031 },
|
||||
{ 0x0000, 0xc990, 0x0000, 0x00f1, 0xb031 },
|
||||
{ 0x0000, 0xc923, 0x0000, 0x0010, 0xb031 },
|
||||
{ 0x0000, 0xc924, 0x0000, 0x0004, 0xb031 },
|
||||
{ 0x0000, 0xc92f, 0x0000, 0x0018, 0xb031 },
|
||||
{ 0x0000, 0xc92e, 0x0000, 0x0094, 0xb031 },
|
||||
{ 0x0000, 0xc920, 0x0000, 0x0008, 0xb031 },
|
||||
{ 0x0000, 0xc916, 0x0000, 0x00f9, 0xb031 },
|
||||
{ 0x0000, 0xc980, 0x0000, 0x00e1, 0xb031 },
|
||||
{ 0x0000, 0xc913, 0x0000, 0x0000, 0xb031 },
|
||||
{ 0x0000, 0xc914, 0x0000, 0x0001, 0xb031 },
|
||||
{ 0x0000, 0xc91f, 0x0000, 0x0014, 0xb031 },
|
||||
{ 0x0000, 0xc91e, 0x0000, 0x0094, 0xb031 },
|
||||
{ 0x0000, 0xc91a, 0x0000, 0x0066, 0xb031 },
|
||||
{ 0x0000, 0xc91b, 0x0000, 0x0078, 0xb031 },
|
||||
{ 0x0000, 0xc910, 0x0000, 0x000d, 0xb031 },
|
||||
{ 0x0000, 0xc946, 0x0000, 0x00f9, 0xb031 },
|
||||
{ 0x0000, 0xc9d0, 0x0000, 0x00f1, 0xb031 },
|
||||
{ 0x0000, 0xc944, 0x0000, 0x0001, 0xb031 },
|
||||
{ 0x0000, 0xc94f, 0x0000, 0x0014, 0xb031 },
|
||||
{ 0x0000, 0xc94e, 0x0000, 0x0094, 0xb031 },
|
||||
{ 0x0000, 0xc94a, 0x0000, 0x0026, 0xb031 },
|
||||
{ 0x0000, 0xc94b, 0x0000, 0x0056, 0xb031 },
|
||||
{ 0x0000, 0xc951, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xc600, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xc601, 0x0000, 0x0026, 0xb031 },
|
||||
{ 0x0000, 0xc602, 0x0000, 0x004a, 0xb031 },
|
||||
{ 0x0000, 0xc603, 0x0000, 0x0010, 0xb031 },
|
||||
{ 0x0000, 0xc604, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xc605, 0x0000, 0x00da, 0xb031 },
|
||||
{ 0x0000, 0xc606, 0x0000, 0x000e, 0xb031 },
|
||||
{ 0x0000, 0xc607, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xc610, 0x0000, 0x0007, 0xb031 },
|
||||
{ 0x0000, 0xc611, 0x0000, 0x00da, 0xb031 },
|
||||
{ 0x0000, 0xc612, 0x0000, 0x000e, 0xb031 },
|
||||
{ 0x0000, 0xc613, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xc614, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xc615, 0x0000, 0x0026, 0xb031 },
|
||||
{ 0x0000, 0xc616, 0x0000, 0x004a, 0xb031 },
|
||||
{ 0x0000, 0xc617, 0x0000, 0x0010, 0xb031 },
|
||||
{ 0x0000, 0xc618, 0x0000, 0x0008, 0xb031 },
|
||||
{ 0x0000, 0xc541, 0x0000, 0x0030, 0xb031 },
|
||||
{ 0x0000, 0xc802, 0x0000, 0x00d2, 0xb031 },
|
||||
{ 0x0000, 0xc902, 0x0000, 0x00d2, 0xb031 },
|
||||
{ 0x0000, 0xc800, 0x0000, 0x00f0, 0xb031 },
|
||||
{ 0x0000, 0xd250, 0x0000, 0x0087, 0xb031 },
|
||||
{ 0x0000, 0xd252, 0x0000, 0x0030, 0xb031 },
|
||||
{ 0x0000, 0xd264, 0x0000, 0x00c0, 0xb031 },
|
||||
{ 0x0000, 0xce60, 0x0000, 0x00e3, 0xb031 },
|
||||
{ 0x0000, 0xdf00, 0x0000, 0x0010, 0xb031 },
|
||||
{ 0x0000, 0xdbb5, 0x0041, 0xd27f, 0xb037 },
|
||||
{ 0x0000, 0xddb5, 0x0040, 0x6e3b, 0xb037 },
|
||||
{ 0x0000, 0xdb93, 0x0000, 0x009e, 0xb033 },
|
||||
{ 0x0000, 0xdd93, 0x0000, 0x009e, 0xb033 },
|
||||
{ 0x0000, 0xdb12, 0x0000, 0x00c0, 0xb031 },
|
||||
{ 0x0000, 0xdd12, 0x0000, 0x00c0, 0xb031 },
|
||||
{ 0x0000, 0xdb08, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xdd08, 0x0000, 0x0080, 0xb031 },
|
||||
{ 0x0000, 0xdb00, 0x0000, 0x00cc, 0xb031 },
|
||||
{ 0x0000, 0xc203, 0x0000, 0x009c, 0xb031 },
|
||||
{ 0x0000, 0x0010, 0x0000, 0x0f21, 0x0000 },
|
||||
};
|
||||
|
||||
/* wake the amp (ea00=0x43, c121=0x0b, f109=0xe0) */
|
||||
static const struct alc298_razer_blade16_2025_op alc298_razer_blade16_2025_amp_wake[] = {
|
||||
{ 0x0000, 0xea00, 0x0000, 0x0043, 0xb031 },
|
||||
{ 0x0000, 0xc121, 0x0000, 0x000b, 0xb031 },
|
||||
{ 0x0000, 0xf109, 0x0000, 0x00e0, 0xb031 },
|
||||
};
|
||||
|
||||
/* park the amp (ea00=0x47, c121=0x0a, f109=0xa0) */
|
||||
static const struct alc298_razer_blade16_2025_op alc298_razer_blade16_2025_amp_sleep[] = {
|
||||
{ 0x0000, 0xea00, 0x0000, 0x0047, 0xb031 },
|
||||
{ 0x0000, 0xc121, 0x0000, 0x000a, 0xb031 },
|
||||
{ 0x0000, 0xf109, 0x0000, 0x00a0, 0xb031 },
|
||||
};
|
||||
|
||||
/*
|
||||
* Razer Blade 16 (2025): Realtek ALC298 driving an external smart amp.
|
||||
* Crossover, voicing and speaker protection live in an external DSP
|
||||
* reached over a vendor-coef mailbox on NID 0x20; the captured DSP
|
||||
* programming is in the tables above. NID 0x14, the BIOS-disabled
|
||||
* tweeter pin, is re-exposed via a pin-config override so the parser
|
||||
* drives it as a normal internal speaker (shared volume/mute, auto-mute
|
||||
* on headphone insertion).
|
||||
*
|
||||
* alc298_razer_blade16_2025_apply() runs one op-table: a plain coef write
|
||||
* (strobe == 0) goes through alc_write_coef_idx(), while a mailbox op
|
||||
* selects a bank and streams four PROC_COEF words (addr/hi/lo/commit)
|
||||
* into a single coef index (0x23) on NID 0x20 to reach the external DSP
|
||||
* -- that one-index/many-words form is why it cannot be expressed as an
|
||||
* alc_process_coef_fw() table (one value per index).
|
||||
*/
|
||||
static void alc298_razer_blade16_2025_apply(struct hda_codec *codec,
|
||||
const struct alc298_razer_blade16_2025_op *seq,
|
||||
int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (!seq[i].strobe) {
|
||||
alc_write_coef_idx(codec, seq[i].addr, seq[i].lo);
|
||||
continue;
|
||||
}
|
||||
alc_write_coef_idx(codec, 0x89, seq[i].bank);
|
||||
snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0x23);
|
||||
snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, seq[i].addr);
|
||||
snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, seq[i].hi);
|
||||
snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, seq[i].lo);
|
||||
snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, seq[i].strobe);
|
||||
}
|
||||
}
|
||||
|
||||
static void alc298_razer_blade16_2025_pcm_hook(struct hda_pcm_stream *hinfo,
|
||||
struct hda_codec *codec,
|
||||
struct snd_pcm_substream *substream,
|
||||
int action)
|
||||
{
|
||||
/* power the external amp only while a stream is running */
|
||||
switch (action) {
|
||||
case HDA_GEN_PCM_ACT_PREPARE:
|
||||
alc298_razer_blade16_2025_apply(codec, alc298_razer_blade16_2025_amp_wake,
|
||||
ARRAY_SIZE(alc298_razer_blade16_2025_amp_wake));
|
||||
break;
|
||||
case HDA_GEN_PCM_ACT_CLEANUP:
|
||||
alc298_razer_blade16_2025_apply(codec, alc298_razer_blade16_2025_amp_sleep,
|
||||
ARRAY_SIZE(alc298_razer_blade16_2025_amp_sleep));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc298_fixup_razer_blade16_2025(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
/*
|
||||
* Pin every output to a fixed converter so the routing does not
|
||||
* rely on the generic parser's DAC-allocation heuristics: without
|
||||
* a fixed assignment the parser brings up only one speaker pin and
|
||||
* leaves the other silent, and the allocation could change between
|
||||
* kernel versions. Both speaker pins share DAC 0x03 through mixer
|
||||
* 0x0d: that is the only converter that drives the woofer (NID
|
||||
* 0x17) on this machine -- feeding it from DAC 0x02 or the digital
|
||||
* converter 0x06 leaves the woofer silent. Both pins carry the
|
||||
* same stereo stream and the external amp does the crossover.
|
||||
* Headphone NID 0x21 keeps DAC 0x02.
|
||||
*/
|
||||
static const hda_nid_t preferred_pairs[] = {
|
||||
0x21, 0x02,
|
||||
0x14, 0x03,
|
||||
0x17, 0x03,
|
||||
0
|
||||
};
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
switch (action) {
|
||||
case HDA_FIXUP_ACT_PRE_PROBE:
|
||||
spec->gen.preferred_dacs = preferred_pairs;
|
||||
break;
|
||||
case HDA_FIXUP_ACT_PROBE:
|
||||
spec->gen.pcm_playback_hook = alc298_razer_blade16_2025_pcm_hook;
|
||||
break;
|
||||
case HDA_FIXUP_ACT_INIT:
|
||||
/*
|
||||
* Wake the amp, program its DSP at boot and on resume, then
|
||||
* park it. It is woken again for playback and parked
|
||||
* afterwards from the pcm_playback_hook.
|
||||
*/
|
||||
alc298_razer_blade16_2025_apply(codec, alc298_razer_blade16_2025_amp_wake,
|
||||
ARRAY_SIZE(alc298_razer_blade16_2025_amp_wake));
|
||||
alc298_razer_blade16_2025_apply(codec, alc298_razer_blade16_2025_amp_init,
|
||||
ARRAY_SIZE(alc298_razer_blade16_2025_amp_init));
|
||||
alc298_razer_blade16_2025_apply(codec, alc298_razer_blade16_2025_amp_sleep,
|
||||
ARRAY_SIZE(alc298_razer_blade16_2025_amp_sleep));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -296,7 +296,8 @@ static void alc282_init(struct hda_codec *codec)
|
|||
msleep(100);
|
||||
|
||||
/* Headphone capless set to normal mode */
|
||||
alc_write_coef_idx(codec, 0x78, coef78);
|
||||
if (coef78 != -1)
|
||||
alc_write_coef_idx(codec, 0x78, coef78);
|
||||
}
|
||||
|
||||
static void alc282_shutup(struct hda_codec *codec)
|
||||
|
|
@ -333,7 +334,8 @@ static void alc282_shutup(struct hda_codec *codec)
|
|||
|
||||
alc_auto_setup_eapd(codec, false);
|
||||
alc_shutup_pins(codec);
|
||||
alc_write_coef_idx(codec, 0x78, coef78);
|
||||
if (coef78 != -1)
|
||||
alc_write_coef_idx(codec, 0x78, coef78);
|
||||
}
|
||||
|
||||
static const struct coef_fw alc283_coefs[] = {
|
||||
|
|
@ -585,15 +587,19 @@ static void alc285_hp_init(struct hda_codec *codec)
|
|||
|
||||
alc_write_coefex_idx(codec, 0x58, 0x00, 0xf888); /* HP depop procedure start */
|
||||
val = alc_read_coefex_idx(codec, 0x58, 0x00);
|
||||
for (i = 0; i < 20 && val & 0x8000; i++) {
|
||||
for (i = 0; i < 20 && val != -1 && val & 0x8000; i++) {
|
||||
msleep(50);
|
||||
val = alc_read_coefex_idx(codec, 0x58, 0x00);
|
||||
} /* Wait for depop procedure finish */
|
||||
|
||||
alc_write_coefex_idx(codec, 0x58, 0x00, val); /* write back the result */
|
||||
alc_update_coef_idx(codec, 0x38, 1<<4, coef38);
|
||||
alc_update_coef_idx(codec, 0x0d, 0x110, coef0d);
|
||||
alc_update_coef_idx(codec, 0x36, 3<<13, coef36);
|
||||
if (val != -1)
|
||||
alc_write_coefex_idx(codec, 0x58, 0x00, val); /* write back the result */
|
||||
if (coef38 != -1)
|
||||
alc_update_coef_idx(codec, 0x38, 1<<4, coef38);
|
||||
if (coef0d != -1)
|
||||
alc_update_coef_idx(codec, 0x0d, 0x110, coef0d);
|
||||
if (coef36 != -1)
|
||||
alc_update_coef_idx(codec, 0x36, 3<<13, coef36);
|
||||
|
||||
msleep(50);
|
||||
alc_update_coef_idx(codec, 0x4a, 1<<15, 0);
|
||||
|
|
@ -858,7 +864,7 @@ static void alc294_hp_init(struct hda_codec *codec)
|
|||
|
||||
/* Wait for depop procedure finish */
|
||||
val = alc_read_coefex_idx(codec, 0x58, 0x01);
|
||||
for (i = 0; i < 20 && val & 0x0080; i++) {
|
||||
for (i = 0; i < 20 && val != -1 && val & 0x0080; i++) {
|
||||
msleep(50);
|
||||
val = alc_read_coefex_idx(codec, 0x58, 0x01);
|
||||
}
|
||||
|
|
@ -1392,6 +1398,15 @@ static void alc245_fixup_hp_gpio_led(struct hda_codec *codec,
|
|||
alc_fixup_hp_gpio_led(codec, action, 0, 0x04);
|
||||
}
|
||||
|
||||
static void alc245_fixup_minisforum_jack_detect(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix,
|
||||
int action)
|
||||
{
|
||||
if (action == HDA_FIXUP_ACT_INIT)
|
||||
/* Clear Reset HP JD while preserving the other coefficient bits. */
|
||||
alc_update_coef_idx(codec, 0x4a, BIT(15), 0);
|
||||
}
|
||||
|
||||
/* turn on/off mic-mute LED per capture hook via VREF change */
|
||||
static int vref_micmute_led_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
|
|
@ -2557,6 +2572,13 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec,
|
|||
}
|
||||
}
|
||||
|
||||
static void alc285_lenovo_dac_rename(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
if (action == HDA_FIXUP_ACT_BUILD)
|
||||
rename_ctl(codec, "Line Out Playback Volume",
|
||||
"Headphone Playback Volume");
|
||||
}
|
||||
static void alc290_fixup_mono_speakers(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
|
|
@ -3262,6 +3284,36 @@ static void find_cirrus_companion_amps(struct hda_codec *cdc)
|
|||
comp_generic_fixup(cdc, HDA_FIXUP_ACT_PRE_PROBE, bus, acpi_ids[i].hid, match, count);
|
||||
}
|
||||
|
||||
static void aw88399_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
|
||||
{
|
||||
comp_generic_fixup(cdc, action, "i2c", "AWDZ8399", "-%s:00-aw88399-hda.%d", 2);
|
||||
}
|
||||
|
||||
static void alc287_fixup_legion_16iax10h_aw88399(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
/*
|
||||
* Force DAC 0x02 for the bass speaker 0x17, as the default 0x06 lacks volume controls.
|
||||
*/
|
||||
static const hda_nid_t conn[] = { 0x02 };
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
alc269_fixup_limit_int_mic_boost(codec, fix, action);
|
||||
alc_fixup_headset_mode_no_hp_mic(codec, fix, action);
|
||||
alc_fixup_headset_jack(codec, fix, action);
|
||||
|
||||
switch (action) {
|
||||
case HDA_FIXUP_ACT_PRE_PROBE:
|
||||
spec->gen.suppress_auto_mic = 1;
|
||||
snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
|
||||
break;
|
||||
case HDA_FIXUP_ACT_BUILD:
|
||||
spec->gen.multiout.max_channels = 2;
|
||||
spec->gen.pcm_rec[0]->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
|
||||
{
|
||||
comp_generic_fixup(cdc, action, "i2c", "CSC3551", "-%s:00-cs35l41-hda.%d", 2);
|
||||
|
|
@ -3357,6 +3409,9 @@ static void alc287_fixup_acer_micmute_led(struct hda_codec *codec,
|
|||
/* for alc285_fixup_ideapad_s740_coef() */
|
||||
#include "../helpers/ideapad_s740.c"
|
||||
|
||||
/* for alc298_fixup_razer_blade16_2025() */
|
||||
#include "../helpers/razer_blade16_2025.c"
|
||||
|
||||
static const struct coef_fw alc256_fixup_set_coef_defaults_coefs[] = {
|
||||
WRITE_COEF(0x10, 0x0020), WRITE_COEF(0x24, 0x0000),
|
||||
WRITE_COEF(0x26, 0x0000), WRITE_COEF(0x29, 0x3000),
|
||||
|
|
@ -3524,6 +3579,16 @@ static void alc287_fixup_yoga9_14iap7_bass_spk_pin(struct hda_codec *codec,
|
|||
}
|
||||
}
|
||||
|
||||
static void alc_fixup_yoga_pro7_audio(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
/* Reuse the DAC routing selected for ThinkPad X1 Gen7 */
|
||||
alc285_fixup_thinkpad_x1_gen7(codec, fix, action);
|
||||
|
||||
/* Limit the internal mic boost to 0 or 1 to avoid noise */
|
||||
alc269_fixup_limit_int_mic_boost(codec, fix, action);
|
||||
}
|
||||
|
||||
static void alc295_fixup_dell_inspiron_top_speakers(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
|
|
@ -3929,6 +3994,7 @@ enum {
|
|||
ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572,
|
||||
ALC269_FIXUP_ACER_AC700,
|
||||
ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
|
||||
ALC269_FIXUP_THINKPAD_LIMIT_INT_MIC_BOOST,
|
||||
ALC269VB_FIXUP_ASUS_ZENBOOK,
|
||||
ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A,
|
||||
ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE,
|
||||
|
|
@ -3997,6 +4063,7 @@ enum {
|
|||
ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
|
||||
ALC295_FIXUP_DISABLE_DAC3,
|
||||
ALC285_FIXUP_SPEAKER2_TO_DAC1,
|
||||
ALC285_FIXUP_YOGA_SPEAKER2_TO_DAC1,
|
||||
ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1,
|
||||
ALC285_FIXUP_ASUS_HEADSET_MIC,
|
||||
ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS,
|
||||
|
|
@ -4066,7 +4133,6 @@ enum {
|
|||
ALC294_FIXUP_ASUS_ALLY,
|
||||
ALC294_FIXUP_ASUS_ALLY_PINS,
|
||||
ALC294_FIXUP_ASUS_ALLY_VERBS,
|
||||
ALC294_FIXUP_ASUS_ALLY_SPEAKER,
|
||||
ALC294_FIXUP_ASUS_HPE,
|
||||
ALC294_FIXUP_ASUS_COEF_1B,
|
||||
ALC294_FIXUP_ASUS_GX502_HP,
|
||||
|
|
@ -4091,6 +4157,8 @@ enum {
|
|||
ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS,
|
||||
ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS,
|
||||
ALC298_FIXUP_LG_GRAM_STYLE_14,
|
||||
ALC298_FIXUP_RAZER_BLADE16_2025_PINS,
|
||||
ALC298_FIXUP_RAZER_BLADE16_2025,
|
||||
ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
|
||||
ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
|
||||
ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
|
||||
|
|
@ -4108,7 +4176,6 @@ enum {
|
|||
ALC269_FIXUP_LEMOTE_A190X,
|
||||
ALC256_FIXUP_INTEL_NUC8_RUGGED,
|
||||
ALC233_FIXUP_INTEL_NUC8_DMIC,
|
||||
ALC233_FIXUP_INTEL_NUC8_BOOST,
|
||||
ALC256_FIXUP_INTEL_NUC10,
|
||||
ALC255_FIXUP_XIAOMI_HEADSET_MIC,
|
||||
ALC274_FIXUP_HP_MIC,
|
||||
|
|
@ -4139,6 +4206,7 @@ enum {
|
|||
ALC298_FIXUP_LENOVO_C940_DUET7,
|
||||
ALC287_FIXUP_LENOVO_YOGA_BOOK_9I,
|
||||
ALC287_FIXUP_LENOVO_YOGA_PRO7,
|
||||
ALC287_FIXUP_LENOVO_XPAD_HEADSET_JACK,
|
||||
ALC287_FIXUP_13S_GEN2_SPEAKERS,
|
||||
ALC256_FIXUP_SET_COEF_DEFAULTS,
|
||||
ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
|
||||
|
|
@ -4183,7 +4251,6 @@ enum {
|
|||
ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD,
|
||||
ALC2XX_FIXUP_HEADSET_MIC,
|
||||
ALC289_FIXUP_DELL_CS35L41_SPI_2,
|
||||
ALC294_FIXUP_CS35L41_I2C_2,
|
||||
ALC256_FIXUP_ACER_SFG16_MICMUTE_LED,
|
||||
ALC256_FIXUP_HEADPHONE_AMP_VOL,
|
||||
ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX,
|
||||
|
|
@ -4197,6 +4264,7 @@ enum {
|
|||
ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318,
|
||||
ALC256_FIXUP_CHROME_BOOK,
|
||||
ALC245_FIXUP_CLEVO_NOISY_MIC,
|
||||
ALC245_FIXUP_MINISFORUM_JACK_DETECT,
|
||||
ALC269_FIXUP_VAIO_VJFH52_MIC_NO_PRESENCE,
|
||||
ALC233_FIXUP_MEDION_MTL_SPK,
|
||||
ALC233_FIXUP_STARLABS_STARFIGHTER,
|
||||
|
|
@ -4206,7 +4274,6 @@ enum {
|
|||
ALC274_FIXUP_HP_AIO_BIND_DACS,
|
||||
ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2,
|
||||
ALC285_FIXUP_ASUS_GA605K_HEADSET_MIC,
|
||||
ALC285_FIXUP_ASUS_GA605K_I2C_SPEAKER2_TO_DAC1,
|
||||
ALC269_FIXUP_POSITIVO_P15X_HEADSET_MIC,
|
||||
ALC289_FIXUP_ASUS_ZEPHYRUS_DUAL_SPK,
|
||||
ALC256_FIXUP_VAIO_RPL_MIC_NO_PRESENCE,
|
||||
|
|
@ -4226,6 +4293,10 @@ enum {
|
|||
ALC236_FIXUP_DELL_HP_POP_NOISE,
|
||||
ALC274_FIXUP_HP_89E9_GPIO,
|
||||
ALC274_FIXUP_HP_VERBS,
|
||||
ALC287_FIXUP_AW88399_I2C_2,
|
||||
ALC287_FIXUP_LENOVO_LEGION_AW88399,
|
||||
ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN_HEADSET,
|
||||
ALC285_LENOVO_DAC_RENAME,
|
||||
};
|
||||
|
||||
/* A special fixup for Lenovo C940 and Yoga Duet 7;
|
||||
|
|
@ -4263,6 +4334,20 @@ static void alc287_fixup_lenovo_yoga_book_9i(struct hda_codec *codec,
|
|||
}
|
||||
|
||||
static const struct hda_fixup alc269_fixups[] = {
|
||||
[ALC298_FIXUP_RAZER_BLADE16_2025_PINS] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
{ 0x14, 0x90170121 }, /* tweeter as internal speaker, seq 1 */
|
||||
{ 0x17, 0x90170120 }, /* woofer as internal speaker, seq 0 */
|
||||
{ }
|
||||
},
|
||||
.chained = true,
|
||||
.chain_id = ALC298_FIXUP_RAZER_BLADE16_2025,
|
||||
},
|
||||
[ALC298_FIXUP_RAZER_BLADE16_2025] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc298_fixup_razer_blade16_2025,
|
||||
},
|
||||
[ALC233_FIXUP_WUJIE_SPEAKERS] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
|
|
@ -4703,6 +4788,10 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
.chain_id = ALC271_FIXUP_DMIC,
|
||||
},
|
||||
[ALC269_FIXUP_LIMIT_INT_MIC_BOOST] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc269_fixup_limit_int_mic_boost
|
||||
},
|
||||
[ALC269_FIXUP_THINKPAD_LIMIT_INT_MIC_BOOST] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc269_fixup_limit_int_mic_boost,
|
||||
.chained = true,
|
||||
|
|
@ -5078,11 +5167,7 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc_fixup_inv_dmic,
|
||||
.chained = true,
|
||||
.chain_id = ALC233_FIXUP_INTEL_NUC8_BOOST,
|
||||
},
|
||||
[ALC233_FIXUP_INTEL_NUC8_BOOST] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc269_fixup_limit_int_mic_boost
|
||||
.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
|
||||
},
|
||||
[ALC255_FIXUP_DELL_SPK_NOISE] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
|
|
@ -5143,6 +5228,10 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
[ALC285_FIXUP_SPEAKER2_TO_DAC1] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc285_fixup_speaker2_to_dac1,
|
||||
},
|
||||
[ALC285_FIXUP_YOGA_SPEAKER2_TO_DAC1] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc285_fixup_speaker2_to_dac1,
|
||||
.chained = true,
|
||||
.chain_id = ALC269_FIXUP_THINKPAD_ACPI
|
||||
},
|
||||
|
|
@ -5662,11 +5751,7 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
{ }
|
||||
},
|
||||
.chained = true,
|
||||
.chain_id = ALC294_FIXUP_ASUS_ALLY_SPEAKER
|
||||
},
|
||||
[ALC294_FIXUP_ASUS_ALLY_SPEAKER] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc285_fixup_speaker2_to_dac1,
|
||||
.chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1
|
||||
},
|
||||
[ALC285_FIXUP_THINKPAD_X1_GEN7] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
|
|
@ -6209,11 +6294,20 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
},
|
||||
[ALC287_FIXUP_LENOVO_YOGA_PRO7] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
/* Reuse the DAC routing selected for ThinkPad X1 Gen7 */
|
||||
.v.func = alc285_fixup_thinkpad_x1_gen7,
|
||||
.v.func = alc_fixup_yoga_pro7_audio,
|
||||
.chained = true,
|
||||
.chain_id = ALC269_FIXUP_LENOVO_XPAD_ACPI,
|
||||
},
|
||||
[ALC287_FIXUP_LENOVO_XPAD_HEADSET_JACK] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc_fixup_headset_jack,
|
||||
.chained = true,
|
||||
/* Same as ALC285_FIXUP_THINKPAD_HEADSET_JACK, except that the
|
||||
* mute LEDs are driven through ideapad_laptop rather than
|
||||
* thinkpad_acpi.
|
||||
*/
|
||||
.chain_id = ALC287_FIXUP_LENOVO_YOGA_PRO7,
|
||||
},
|
||||
[ALC623_FIXUP_LENOVO_THINKSTATION_P340] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc_fixup_no_shutup,
|
||||
|
|
@ -6653,10 +6747,6 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
.chained = true,
|
||||
.chain_id = ALC289_FIXUP_DUAL_SPK
|
||||
},
|
||||
[ALC294_FIXUP_CS35L41_I2C_2] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = cs35l41_fixup_i2c_two,
|
||||
},
|
||||
[ALC256_FIXUP_ACER_SFG16_MICMUTE_LED] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc256_fixup_acer_sfg16_micmute_led,
|
||||
|
|
@ -6729,6 +6819,10 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
.chained = true,
|
||||
.chain_id = ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
|
||||
},
|
||||
[ALC245_FIXUP_MINISFORUM_JACK_DETECT] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc245_fixup_minisforum_jack_detect,
|
||||
},
|
||||
[ALC269_FIXUP_VAIO_VJFH52_MIC_NO_PRESENCE] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
|
|
@ -6749,6 +6843,8 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
[ALC233_FIXUP_STARLABS_STARFIGHTER] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc233_fixup_starlabs_starfighter,
|
||||
.chained = true,
|
||||
.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
|
||||
},
|
||||
[ALC294_FIXUP_BASS_SPEAKER_15] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
|
|
@ -6776,11 +6872,7 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
{ }
|
||||
},
|
||||
.chained = true,
|
||||
.chain_id = ALC285_FIXUP_ASUS_GA605K_I2C_SPEAKER2_TO_DAC1
|
||||
},
|
||||
[ALC285_FIXUP_ASUS_GA605K_I2C_SPEAKER2_TO_DAC1] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc285_fixup_speaker2_to_dac1,
|
||||
.chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1
|
||||
},
|
||||
[ALC269_FIXUP_POSITIVO_P15X_HEADSET_MIC] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
|
|
@ -6898,6 +6990,26 @@ static const struct hda_fixup alc269_fixups[] = {
|
|||
.chained = true,
|
||||
.chain_id = ALC274_FIXUP_HP_89E9_GPIO,
|
||||
},
|
||||
[ALC287_FIXUP_AW88399_I2C_2] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = aw88399_fixup_i2c_two,
|
||||
},
|
||||
[ALC287_FIXUP_LENOVO_LEGION_AW88399] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc287_fixup_legion_16iax10h_aw88399,
|
||||
.chained = true,
|
||||
.chain_id = ALC287_FIXUP_AW88399_I2C_2,
|
||||
},
|
||||
[ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN_HEADSET] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc_fixup_headset_jack,
|
||||
.chained = true,
|
||||
.chain_id = ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN,
|
||||
},
|
||||
[ALC285_LENOVO_DAC_RENAME] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc285_lenovo_dac_rename,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct hda_quirk alc269_fixup_tbl[] = {
|
||||
|
|
@ -6953,6 +7065,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1025, 0x160e, "Acer PT316-51S", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x161f, "Acer S40-54", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1025, 0x1640, "Acer Aspire A315-44P", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
|
||||
SND_PCI_QUIRK(0x1025, 0x166c, "Acer Predator PH16-71", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x1679, "Acer Nitro 16 AN16-41", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
|
||||
SND_PCI_QUIRK(0x1025, 0x171e, "Acer Nitro ANV15-51", ALC245_FIXUP_ACER_MICMUTE_LED),
|
||||
|
|
@ -6961,6 +7074,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1025, 0x1826, "Acer Helios ZPC", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1025, 0x182c, "Acer Helios ZPD", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1025, 0x1844, "Acer Helios ZPS", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1025, 0x1909, "Acer Nitro ANV16-42", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
|
||||
SND_PCI_QUIRK(0x1028, 0x053c, "Dell Latitude E5430", ALC292_FIXUP_DELL_E7X),
|
||||
SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
|
||||
|
|
@ -7145,10 +7259,12 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x85c6, "HP Pavilion x360 Convertible 14-dy1xxx", ALC295_FIXUP_HP_MUTE_LED_COEFBIT11),
|
||||
SND_PCI_QUIRK(0x103c, 0x85de, "HP Envy x360 13-ar0xxx", ALC285_FIXUP_HP_ENVY_X360),
|
||||
SND_PCI_QUIRK(0x103c, 0x85f0, "HP Laptop 15-dw0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
SND_PCI_QUIRK(0x103c, 0x85f3, "HP 250 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8603, "HP Omen 17-cb0xxx", ALC285_FIXUP_HP_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x860c, "HP ZBook 17 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
||||
SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
||||
SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
||||
SND_PCI_QUIRK(0x103c, 0x864f, "HP Laptop 15-dy0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x86c1, "HP Laptop 15-da3001TU", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO),
|
||||
|
|
@ -7259,6 +7375,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x89e7, "HP Elite x2 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8a05, "HP Dragonfly Folio G3 2-in-1", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8a06, "HP Dragonfly Folio G3 2-in-1", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8a0e, "HP Pavilion Laptop 15-eh2xxx", ALC287_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8a0f, "HP Pavilion 14-ec1xxx", ALC287_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8a1b, "HP 255 15.6 inch G9 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8a1f, "HP Laptop 14s-dr5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
||||
|
|
@ -7350,7 +7467,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8c15, "HP Spectre x360 2-in-1 Laptop 14-eu0xxx", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
|
||||
SND_PCI_QUIRK(0x103c, 0x8c16, "HP Spectre x360 2-in-1 Laptop 16-aa0xxx", ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX),
|
||||
SND_PCI_QUIRK(0x103c, 0x8c17, "HP Spectre 16", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8c17, "HP Spectre x360 2-in-1 Laptop 16-aa0xxx", ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX),
|
||||
SND_PCI_QUIRK(0x103c, 0x8c21, "HP Pavilion Plus Laptop 14-ey0XXX", ALC245_FIXUP_HP_X360_MUTE_LEDS),
|
||||
SND_PCI_QUIRK(0x103c, 0x8c2d, "HP Victus 15-fa1xxx (MB 8C2D)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
|
||||
SND_PCI_QUIRK(0x103c, 0x8c30, "HP Victus 15-fb1xxx", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
|
||||
|
|
@ -7442,6 +7559,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x8dfc, "HP EliteBook 645 G12", ALC236_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8dfd, "HP EliteBook 6 G1a 16", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
||||
SND_PCI_QUIRK(0x103c, 0x8dfe, "HP EliteBook 665 G12", ALC236_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e0d, "HP EliteBook 6 G1a 14 (AD3Q9ET#UUG)", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e11, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e12, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8e13, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
|
|
@ -7501,6 +7619,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x8f42, "HP ZBook 8 G2a 14W", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8f57, "HP Trekker G7JC", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x103c, 0x8f62, "HP ZBook 8 G2a 16W", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8f7e, "HP Messi", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8f94, "HP ZBook 8 G2a 14", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED_INVERTED),
|
||||
SND_PCI_QUIRK(0x103c, 0x8f95, "HP ZBook 8 G2a 16", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED_INVERTED),
|
||||
SND_PCI_QUIRK(0x1043, 0x1024, "ASUS Zephyrus G14 2025", ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC),
|
||||
|
|
@ -7508,6 +7627,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1043, 0x1034, "ASUS GU605C", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
|
||||
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
|
||||
SND_PCI_QUIRK(0x1043, 0x1044, "ASUS GA403UM", ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1054, "ASUS G614FH/FM/FP", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x1043, 0x106f, "ASUS VivoBook X515UA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
|
|
@ -7515,16 +7635,15 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1043, 0x10a1, "ASUS UX391UA", ALC294_FIXUP_ASUS_SPK),
|
||||
SND_PCI_QUIRK(0x1043, 0x10a4, "ASUS TP3407SA", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x1043, 0x10c0, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x10c4, "ASUS Vivobook S14 S5406SA", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x10d3, "ASUS K6500ZC", ALC294_FIXUP_ASUS_SPK),
|
||||
SND_PCI_QUIRK(0x1043, 0x1154, "ASUS TP3607SH", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x1043, 0x1194, "ASUS UM3406KA", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
HDA_CODEC_QUIRK(0x1043, 0x1204, "ASUS Strix G16 G615JMR", ALC287_FIXUP_TXNW2781_I2C_ASUS),
|
||||
SND_PCI_QUIRK(0x1043, 0x1204, "ASUS Strix G615JHR_JMR_JPR", ALC287_FIXUP_TAS2781_I2C),
|
||||
HDA_CODEC_QUIRK(0x1043, 0x1214, "ASUS ROG Strix G615LP", ALC287_FIXUP_TXNW2781_I2C_ASUS),
|
||||
SND_PCI_QUIRK(0x1043, 0x1214, "ASUS Strix G615LH_LM_LP", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x1043, 0x1204, "ASUS Strix G615JHR_JMR_JPR", ALC287_FIXUP_TXNW2781_I2C_ASUS),
|
||||
SND_PCI_QUIRK(0x1043, 0x1214, "ASUS Strix G615LH_LM_LP", ALC287_FIXUP_TXNW2781_I2C_ASUS),
|
||||
SND_PCI_QUIRK(0x1043, 0x125e, "ASUS Q524UQK", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1271, "ASUS X430UN", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
|
||||
|
|
@ -7573,7 +7692,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1043, 0x1863, "ASUS UX6404VI/VV", ALC245_FIXUP_CS35L41_SPI_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
|
||||
SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC294_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1970, "ASUS UX550VE", ALC289_FIXUP_ASUS_GA401),
|
||||
|
|
@ -7584,7 +7703,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1043, 0x19f4, "ASUS UM3405GA", ALC294_FIXUP_ASUS_I2C_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
|
||||
SND_PCI_QUIRK(0x1043, 0x1a63, "ASUS UX3405MA", ALC294_FIXUP_ASUS_SPI_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1a83, "ASUS UM5302LA", ALC294_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x1a83, "ASUS UM5302LA", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x1a8e, "ASUS G712LWS", ALC294_FIXUP_LENOVO_MIC_LOCATION),
|
||||
SND_PCI_QUIRK(0x1043, 0x1a8f, "ASUS UX582ZS", ALC245_FIXUP_CS35L41_SPI_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x1b11, "ASUS UX431DA", ALC294_FIXUP_ASUS_COEF_1B),
|
||||
|
|
@ -7613,6 +7732,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1043, 0x1264, "ASUS UM5606KA", ALC294_FIXUP_BASS_SPEAKER_15),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e10, "ASUS VivoBook X507UAR", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e3e, "ASUS VivoBook M515DA/X515DAP", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x1e1f, "ASUS Vivobook 15 X1504VAP", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
|
|
@ -7624,8 +7744,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1043, 0x1e93, "ASUS ExpertBook B9403CVAR", ALC294_FIXUP_ASUS_HPE),
|
||||
SND_PCI_QUIRK(0x1043, 0x1eb3, "ASUS Ally RC72LA", ALC287_FIXUP_ASUS_ALLY_X),
|
||||
SND_PCI_QUIRK(0x1043, 0x1ed3, "ASUS HN7306W", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
HDA_CODEC_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC285_FIXUP_ASUS_I2C_SPEAKER2_TO_DAC1),
|
||||
SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC285_FIXUP_ASUS_I2C_SPEAKER2_TO_DAC1),
|
||||
SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401),
|
||||
SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
|
||||
SND_PCI_QUIRK(0x1043, 0x1f12, "ASUS UM5302", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
|
|
@ -7836,7 +7955,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x2211, "Thinkpad W541", ALC292_FIXUP_TPT440_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad X240", ALC292_FIXUP_TPT440_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_THINKPAD_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x2218, "Thinkpad X1 Carbon 2nd", ALC292_FIXUP_TPT440_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
|
||||
|
|
@ -7852,7 +7971,8 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x224b, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x225c, "Lenovo ThinkPad X1 Carbon 6th Gen", ALC285_LENOVO_DAC_RENAME),
|
||||
SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_THINKPAD_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x2288, "Thinkpad X390", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
|
||||
|
|
@ -7927,7 +8047,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x386a, "Lenovo Yoga 7 16IAP7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x386e, "Legion Y9000X 2022 IAH7", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x17aa, 0x386e, "Yoga Pro 7 14ARP8", ALC285_FIXUP_SPEAKER2_TO_DAC1),
|
||||
SND_PCI_QUIRK(0x17aa, 0x386e, "Yoga Pro 7 14ARP8", ALC285_FIXUP_YOGA_SPEAKER2_TO_DAC1),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x38a8, "Legion Pro 7 16ARX8H", ALC287_FIXUP_TAS2781_I2C), /* this must match before PCI SSID 17aa:386f below */
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x38a7, "Legion Pro 7 16ARX8H", ALC287_FIXUP_TAS2781_I2C), /* this must match before PCI SSID 17aa:386f below */
|
||||
SND_PCI_QUIRK(0x17aa, 0x386f, "Legion Pro 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
|
|
@ -7958,6 +8078,12 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x38b8, "Yoga S780-14.5 proX AMD YC Dual", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38b9, "Yoga S780-14.5 proX AMD LX Dual", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38ba, "Yoga S780-14.5 Air AMD quad YC", ALC287_FIXUP_TAS2781_I2C),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x3926, "Legion Pro 5 16ADR10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
|
||||
/* Legion R9000P ADR10 shares PCI SSID 17aa:38bb with Yoga S780-14.5 Air AMD quad AAC;
|
||||
* use codec SSID to distinguish them
|
||||
*/
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x3927, "Legion R9000P ADR10", ALC287_FIXUP_LENOVO_LEGION_AW88399),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x3928, "Legion R9000P ADR10", ALC287_FIXUP_LENOVO_LEGION_AW88399),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38bb, "Yoga S780-14.5 Air AMD quad AAC", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38be, "Yoga S980-14.5 proX YC Dual", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38bf, "Yoga S980-14.5 proX LX Dual", ALC287_FIXUP_TAS2781_I2C),
|
||||
|
|
@ -7975,7 +8101,6 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x38df, "Yoga Y990 Intel YC Dual", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38e0, "Yoga Y990 Intel VECO Dual", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38f8, "Yoga Book 9i", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38df, "Y990 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
|
||||
/* Legion 7 15ASH11 shares PCI SSID 17aa:38f9 with Thinkbook 16P Gen5;
|
||||
* use codec SSID to distinguish them
|
||||
*/
|
||||
|
|
@ -7985,7 +8110,9 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x38fc, "Lenovo Yoga Pro 7 15ASH11", ALC287_FIXUP_LENOVO_YOGA_PRO7),
|
||||
SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
|
||||
SND_PCI_QUIRK(0x17aa, 0x390d, "Lenovo Yoga Pro 7 14ASP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x3906, "Legion Pro 7i 16IAX10H / Y9000P IAX10", ALC287_FIXUP_LENOVO_LEGION_AW88399),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x3907, "Legion Pro 7i 16IAX10H / Y9000P IAX10", ALC287_FIXUP_LENOVO_LEGION_AW88399),
|
||||
SND_PCI_QUIRK(0x17aa, 0x390d, "Lenovo Yoga Pro 7 14ASP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN_HEADSET),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3911, "Lenovo Yoga Pro 7 14IAH10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3912, "Lenovo Xiaoxin 14 GT", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC),
|
||||
|
|
@ -7994,14 +8121,19 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x3920, "Yoga S990-16 pro Quad VECO Quad", ALC287_FIXUP_TXNW2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3929, "Thinkbook 13x Gen 5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
|
||||
SND_PCI_QUIRK(0x17aa, 0x392b, "Thinkbook 13x Gen 5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x3936, "Legion R9000P ADR10H", ALC287_FIXUP_LENOVO_LEGION_AW88399),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x3937, "Legion R9000P ADR10H", ALC287_FIXUP_LENOVO_LEGION_AW88399),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x3938, "Legion Pro 7 16AFR10H", ALC287_FIXUP_LENOVO_LEGION_AW88399),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x3939, "Legion Pro 7 16AFR10H", ALC287_FIXUP_LENOVO_LEGION_AW88399),
|
||||
SND_PCI_QUIRK(0x17aa, 0x393e, "Lenovo ThinkBook 14 G8+ IPH", ALC287_FIXUP_LENOVO_XPAD_HEADSET_JACK),
|
||||
HDA_CODEC_QUIRK(0x17aa, 0x394c, "Lenovo Yoga Slim 7 14AGP11", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
|
||||
SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_THINKPAD_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
|
||||
SND_PCI_QUIRK(0x17aa, 0x501e, "Thinkpad L440", ALC292_FIXUP_TPT440_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_THINKPAD_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x5034, "Thinkpad T450", ALC292_FIXUP_TPT440_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x5036, "Thinkpad T450s", ALC292_FIXUP_TPT440_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK),
|
||||
|
|
@ -8014,7 +8146,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17aa, 0x505f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x5062, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x508b, "Thinkpad X12 Gen 1", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
|
||||
SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_THINKPAD_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x17aa, 0x511e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x511f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
|
||||
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
|
||||
|
|
@ -8028,9 +8160,14 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1854, 0x0489, "LG gram 16 (16Z90R-A)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
|
||||
SND_PCI_QUIRK(0x1854, 0x048a, "LG gram 17 (17ZD90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
|
||||
SND_PCI_QUIRK(0x1854, 0x0490, "LG Gram Style 14 (14Z90RS)", ALC298_FIXUP_LG_GRAM_STYLE_14),
|
||||
SND_PCI_QUIRK(0x1854, 0x0554, "LG gram 16 (16Z90TR)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
|
||||
SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
|
||||
SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x19e5, 0x3212, "Huawei KLV-WX9 ", ALC256_FIXUP_ACER_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1a58, 0x2023, "Razer Blade 16 (2025)",
|
||||
ALC298_FIXUP_RAZER_BLADE16_2025_PINS),
|
||||
SND_PCI_QUIRK(0x1a58, 0x300e, "Razer Blade 16 (2025)",
|
||||
ALC298_FIXUP_RAZER_BLADE16_2025_PINS),
|
||||
SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20),
|
||||
SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI),
|
||||
SND_PCI_QUIRK(0x1b35, 0x1237, "CZC L101", ALC269_FIXUP_CZC_L101),
|
||||
|
|
@ -8064,13 +8201,17 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1e39, 0xca14, "MEDION NM14LNL", ALC233_FIXUP_MEDION_MTL_SPK),
|
||||
SND_PCI_QUIRK(0x1e50, 0x7007, "Positivo DN50E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x1e50, 0x7036, "Acer Gadget E10 ETBook", ALC233_FIXUP_WUJIE_SPEAKERS),
|
||||
SND_PCI_QUIRK(0x1e50, 0x7038, "Positivo DN140", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x1ee7, 0x2078, "HONOR BRB-X M1010", ALC2XX_FIXUP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1ee7, 0x2081, "HONOR MRB-XXX M1020", ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO),
|
||||
SND_PCI_QUIRK(0x1f4c, 0xb020, "Minisforum AI X1 Pro",
|
||||
ALC245_FIXUP_MINISFORUM_JACK_DETECT),
|
||||
SND_PCI_QUIRK(0x1f4c, 0xe001, "Minisforum V3 (SE)", ALC245_FIXUP_BASS_HP_DAC),
|
||||
SND_PCI_QUIRK(0x1f66, 0x0105, "Ayaneo Portable Game Player", ALC287_FIXUP_CS35L41_I2C_2),
|
||||
SND_PCI_QUIRK(0x2014, 0x800a, "Positivo ARN50", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x2039, 0x0001, "Inspur S14-G1", ALC295_FIXUP_CHROME_BOOK),
|
||||
SND_PCI_QUIRK(0x2145, 0x0001, "Star Labs StarFighter", ALC233_FIXUP_STARLABS_STARFIGHTER),
|
||||
SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x2782, 0x0228, "Infinix ZERO BOOK 13", ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13),
|
||||
SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO),
|
||||
|
|
@ -8081,6 +8222,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x2782, 0x1705, "MEDION E15433", ALC269VC_FIXUP_INFINIX_Y4_MAX),
|
||||
SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME),
|
||||
SND_PCI_QUIRK(0x2782, 0x4900, "MEDION E15443", ALC233_FIXUP_MEDION_MTL_SPK),
|
||||
SND_PCI_QUIRK(0x2782, 0xa128, "Positivo N15RPE-S", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
SND_PCI_QUIRK(0x2782, 0xa212, "Lunnen Ground 14", ALC269VC_FIXUP_LUNNEN_GROUND_14),
|
||||
SND_PCI_QUIRK(0x7017, 0x2014, "Star Labs StarFighter", ALC233_FIXUP_STARLABS_STARFIGHTER),
|
||||
SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
|
||||
|
|
@ -8154,6 +8296,7 @@ static const struct hda_quirk alc269_fixup_vendor_tbl[] = {
|
|||
SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
|
||||
SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo XPAD", ALC269_FIXUP_LENOVO_XPAD_ACPI),
|
||||
SND_PCI_QUIRK_VENDOR(0x19e5, "Huawei Matebook", ALC255_FIXUP_MIC_MUTE_LED),
|
||||
SND_PCI_QUIRK_VENDOR(0x2145, "Star Labs", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
@ -8293,6 +8436,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
|
|||
{.id = ALC2XX_FIXUP_HEADSET_MIC, .name = "alc2xx-fixup-headset-mic"},
|
||||
{.id = ALC245_FIXUP_BASS_HP_DAC, .name = "alc245-fixup-bass-hp-dac"},
|
||||
{.id = ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO, .name = "alc256-honor-mrb-xxx-m1020-audio"},
|
||||
{.id = ALC287_FIXUP_LENOVO_LEGION_AW88399, .name = "alc287-lenovo-legion-aw88399"},
|
||||
{}
|
||||
};
|
||||
#define ALC225_STANDARD_PINS \
|
||||
|
|
@ -8898,6 +9042,7 @@ static int alc269_probe(struct hda_codec *codec, const struct hda_device_id *id)
|
|||
spec->init_hook = alc256_init;
|
||||
spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */
|
||||
if (codec->core.vendor_id == 0x10ec0236 &&
|
||||
codec->bus->pci &&
|
||||
codec->bus->pci->vendor != PCI_VENDOR_ID_AMD)
|
||||
spec->en_3kpull_low = false;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -325,6 +325,7 @@ enum {
|
|||
ALC897_FIXUP_UNIS_H3C_X500S,
|
||||
ALC897_FIXUP_HEADSET_MIC_PIN3,
|
||||
ALC662_FIXUP_CSL_GPIO,
|
||||
ALC897_FIXUP_BEELINK_SER6_AMP,
|
||||
};
|
||||
|
||||
static const struct hda_fixup alc662_fixups[] = {
|
||||
|
|
@ -782,6 +783,10 @@ static const struct hda_fixup alc662_fixups[] = {
|
|||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc662_fixup_csl_amp,
|
||||
},
|
||||
[ALC897_FIXUP_BEELINK_SER6_AMP] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = alc_fixup_gpio4,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct hda_quirk alc662_fixup_tbl[] = {
|
||||
|
|
@ -852,6 +857,8 @@ static const struct hda_quirk alc662_fixup_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1b35, 0x1234, "CZC ET26", ALC662_FIXUP_CZC_ET26),
|
||||
SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
|
||||
SND_PCI_QUIRK(0x1c6c, 0x1239, "Compaq N14JP6-V2", ALC897_FIXUP_HP_HSMIC_VERB),
|
||||
SND_PCI_QUIRK(0x1e63, 0x6d9a, "F+ FLAPTOP r", ALC897_FIXUP_HP_HSMIC_VERB),
|
||||
SND_PCI_QUIRK(0x1f66, 0x0202, "Beelink SER6 Max 6900", ALC897_FIXUP_BEELINK_SER6_AMP),
|
||||
|
||||
#if 0
|
||||
/* Below is a quirk table taken from the old code.
|
||||
|
|
|
|||
|
|
@ -13,6 +13,24 @@ config SND_HDA_CIRRUS_SCODEC_KUNIT_TEST
|
|||
Documentation/dev-tools/kunit/.
|
||||
If in doubt, say "N".
|
||||
|
||||
config SND_HDA_SCODEC_AW88399
|
||||
tristate
|
||||
select SND_HDA_GENERIC
|
||||
|
||||
config SND_HDA_SCODEC_AW88399_I2C
|
||||
tristate "Build AW88399 HD-audio side codec support for I2C Bus"
|
||||
depends on I2C
|
||||
depends on ACPI
|
||||
depends on SND_SOC
|
||||
select SND_HDA_SCODEC_AW88399
|
||||
select SND_SOC_AW88399_LIB
|
||||
help
|
||||
Say Y or M here to include AW88399 I2C HD-audio side codec support
|
||||
in snd-hda-intel driver, such as ALC287.
|
||||
|
||||
comment "Set to Y if you want auto-loading the side codec driver"
|
||||
depends on SND_HDA=y && SND_HDA_SCODEC_AW88399_I2C=m
|
||||
|
||||
config SND_HDA_SCODEC_CS35L41
|
||||
tristate
|
||||
select SND_HDA_GENERIC
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ subdir-ccflags-y += -I$(src)/../../common
|
|||
|
||||
snd-hda-cirrus-scodec-y := cirrus_scodec.o
|
||||
snd-hda-cirrus-scodec-test-y := cirrus_scodec_test.o
|
||||
snd-hda-scodec-aw88399-y := aw88399_hda.o
|
||||
snd-hda-scodec-aw88399-i2c-y := aw88399_hda_i2c.o
|
||||
snd-hda-scodec-cs35l41-y := cs35l41_hda.o cs35l41_hda_property.o
|
||||
snd-hda-scodec-cs35l41-i2c-y := cs35l41_hda_i2c.o
|
||||
snd-hda-scodec-cs35l41-spi-y := cs35l41_hda_spi.o
|
||||
|
|
@ -16,6 +18,8 @@ snd-hda-scodec-tas2781-spi-y := tas2781_hda_spi.o
|
|||
|
||||
obj-$(CONFIG_SND_HDA_CIRRUS_SCODEC) += snd-hda-cirrus-scodec.o
|
||||
obj-$(CONFIG_SND_HDA_CIRRUS_SCODEC_KUNIT_TEST) += snd-hda-cirrus-scodec-test.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_AW88399) += snd-hda-scodec-aw88399.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_AW88399_I2C) += snd-hda-scodec-aw88399-i2c.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41) += snd-hda-scodec-cs35l41.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_I2C) += snd-hda-scodec-cs35l41-i2c.o
|
||||
obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_SPI) += snd-hda-scodec-cs35l41-spi.o
|
||||
|
|
|
|||
373
sound/hda/codecs/side-codecs/aw88399_hda.c
Normal file
373
sound/hda/codecs/side-codecs/aw88399_hda.c
Normal file
|
|
@ -0,0 +1,373 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// AW88399 HDA side codec driver
|
||||
//
|
||||
// Based on cs35l41_hda.c and aw88399.c
|
||||
//
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/string.h>
|
||||
#include <sound/hda_codec.h>
|
||||
#include "../generic.h"
|
||||
#include "hda_component.h"
|
||||
#include "aw88399_hda.h"
|
||||
|
||||
#define AW88399_HDA_I2C_BASE_ADDR 0x34
|
||||
|
||||
static void aw88399_hda_playback_hook(struct device *dev, int action)
|
||||
{
|
||||
struct aw88399_hda *aw88399 = dev_get_drvdata(dev);
|
||||
struct aw88399 *core = aw88399->core;
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(aw88399->dev, "Playback action: %d\n", action);
|
||||
|
||||
switch (action) {
|
||||
case HDA_GEN_PCM_ACT_OPEN:
|
||||
pm_runtime_get_sync(dev);
|
||||
aw88399->playing = true;
|
||||
break;
|
||||
case HDA_GEN_PCM_ACT_PREPARE:
|
||||
if (core)
|
||||
aw88399_start(core, AW88399_SYNC_START);
|
||||
break;
|
||||
case HDA_GEN_PCM_ACT_CLEANUP:
|
||||
if (aw88399->aw_dev)
|
||||
ret = aw88399_stop(aw88399->aw_dev);
|
||||
if (ret)
|
||||
dev_err(aw88399->dev, "Failed to stop amplifier: %d\n", ret);
|
||||
break;
|
||||
case HDA_GEN_PCM_ACT_CLOSE:
|
||||
if (aw88399->aw_dev)
|
||||
aw88399_stop(aw88399->aw_dev);
|
||||
aw88399->playing = false;
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
break;
|
||||
default:
|
||||
dev_warn(aw88399->dev, "Unsupported action: %d\n", action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int aw88399_hda_bind(struct device *dev, struct device *master, void *master_data)
|
||||
{
|
||||
struct aw88399_hda *aw88399 = dev_get_drvdata(dev);
|
||||
struct hda_component_parent *parent = master_data;
|
||||
struct hda_component *comp;
|
||||
|
||||
comp = hda_component_from_index(parent, aw88399->index);
|
||||
if (!comp)
|
||||
return -EINVAL;
|
||||
|
||||
if (comp->dev)
|
||||
return -EBUSY;
|
||||
|
||||
comp->dev = dev;
|
||||
|
||||
strscpy(comp->name, dev_name(dev), sizeof(comp->name));
|
||||
|
||||
comp->playback_hook = aw88399_hda_playback_hook;
|
||||
|
||||
dev_info(aw88399->dev,
|
||||
"AW88399 Bound - SSID: %s, channel: %d\n",
|
||||
aw88399->acpi_subsystem_id, aw88399->channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aw88399_hda_unbind(struct device *dev, struct device *master, void *master_data)
|
||||
{
|
||||
struct aw88399_hda *aw88399 = dev_get_drvdata(dev);
|
||||
struct hda_component_parent *parent = master_data;
|
||||
struct hda_component *comp;
|
||||
|
||||
comp = hda_component_from_index(parent, aw88399->index);
|
||||
if (comp && (comp->dev == dev))
|
||||
memset(comp, 0, sizeof(*comp));
|
||||
|
||||
dev_dbg(aw88399->dev, "Unbound from HDA codec\n");
|
||||
}
|
||||
|
||||
static const struct component_ops aw88399_hda_comp_ops = {
|
||||
.bind = aw88399_hda_bind,
|
||||
.unbind = aw88399_hda_unbind,
|
||||
};
|
||||
|
||||
static int aw88399_hda_index_from_i2c(struct aw88399_hda *aw88399)
|
||||
{
|
||||
return to_i2c_client(aw88399->dev)->addr - AW88399_HDA_I2C_BASE_ADDR;
|
||||
}
|
||||
|
||||
static int aw88399_hda_init(struct aw88399_hda *aw88399)
|
||||
{
|
||||
struct device *dev = aw88399->dev;
|
||||
struct i2c_client *i2c = to_i2c_client(dev);
|
||||
struct aw88399 *core;
|
||||
int ret;
|
||||
|
||||
core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL);
|
||||
if (!core)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&core->lock);
|
||||
core->reset_gpio = aw88399->reset_gpio;
|
||||
core->regmap = aw88399->regmap;
|
||||
core->bsts_unreliable = aw88399->bsts_unreliable;
|
||||
|
||||
aw88399_hw_reset(core);
|
||||
|
||||
ret = aw88399_init(core, i2c, aw88399->regmap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set channel BEFORE loading firmware so ACF parser sees correct value */
|
||||
if (core->aw_pa)
|
||||
aw88399_dev_set_channel(core, aw88399->channel);
|
||||
|
||||
ret = aw88399_request_firmware_file(core);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
aw88399->core = core;
|
||||
aw88399->aw_dev = core->aw_pa;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aw88399_swap_channels(struct aw88399_hda *aw88399)
|
||||
{
|
||||
/*
|
||||
* Certain Lenovo Legion laptops have their
|
||||
* I2C wiring reversed: 0x34 is physically the right speaker,
|
||||
* 0x35 is the left. Swap channels to correct L/R assignment.
|
||||
* This is a model-specific hardware wiring issue, not a driver bug.
|
||||
*/
|
||||
aw88399->channel = 1 - aw88399->channel;
|
||||
dev_dbg(aw88399->dev,
|
||||
"Channel swap applied: index %d -> channel %d\n",
|
||||
aw88399->index, aw88399->channel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aw88399_skip_bsts_check(struct aw88399_hda *aw88399)
|
||||
{
|
||||
/*
|
||||
* BSTS (boost-finished) status bit does not reliably report on
|
||||
* some hardware. On certain Lenovo Legion laptops, both amps
|
||||
* report BSTS=0 (boost not finished) during normal playback
|
||||
* despite clean audio output. Skip BSTS in the startup status
|
||||
* check to avoid false init failures.
|
||||
*/
|
||||
aw88399->bsts_unreliable = true;
|
||||
dev_dbg(aw88399->dev, "BSTS status check disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aw88399_apply_legion_quirks(struct aw88399_hda *aw88399)
|
||||
{
|
||||
aw88399_swap_channels(aw88399);
|
||||
aw88399_skip_bsts_check(aw88399);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct aw88399_prop_model {
|
||||
const char *ssid;
|
||||
int (*apply_prop)(struct aw88399_hda *aw88399);
|
||||
};
|
||||
|
||||
static const struct aw88399_prop_model aw88399_prop_model_table[] = {
|
||||
{ "17AA3906", aw88399_apply_legion_quirks },
|
||||
{ "17AA3907", aw88399_apply_legion_quirks },
|
||||
{ "17AA3927", aw88399_apply_legion_quirks },
|
||||
{ "17AA3928", aw88399_apply_legion_quirks },
|
||||
{ "17AA3936", aw88399_apply_legion_quirks },
|
||||
{ "17AA3937", aw88399_apply_legion_quirks },
|
||||
{ "17AA3938", aw88399_apply_legion_quirks },
|
||||
{ "17AA3939", aw88399_apply_legion_quirks },
|
||||
{ }
|
||||
};
|
||||
|
||||
static int aw88399_hda_acpi_probe(struct aw88399_hda *aw88399)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
const char *sub;
|
||||
const struct aw88399_prop_model *model;
|
||||
|
||||
aw88399->index = aw88399_hda_index_from_i2c(aw88399);
|
||||
aw88399->channel = aw88399->index;
|
||||
aw88399->acpi_subsystem_id = NULL;
|
||||
|
||||
adev = acpi_dev_get_first_match_dev("AWDZ8399", NULL, -1);
|
||||
if (!adev) {
|
||||
dev_err(aw88399->dev, "Failed to find an ACPI device for AWDZ8399\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
struct device *physdev __free(put_device) =
|
||||
get_device(acpi_get_first_physical_node(adev));
|
||||
acpi_dev_put(adev);
|
||||
if (!physdev)
|
||||
return -ENODEV;
|
||||
|
||||
sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
|
||||
if (IS_ERR_OR_NULL(sub))
|
||||
return 0;
|
||||
|
||||
aw88399->acpi_subsystem_id = devm_kstrdup(aw88399->dev, sub, GFP_KERNEL);
|
||||
kfree(sub);
|
||||
if (!aw88399->acpi_subsystem_id)
|
||||
return -ENOMEM;
|
||||
|
||||
for (model = aw88399_prop_model_table; model->ssid; model++) {
|
||||
if (!strcasecmp(model->ssid, aw88399->acpi_subsystem_id)) {
|
||||
dev_info(aw88399->dev,
|
||||
"Applying properties for SSID %s\n",
|
||||
aw88399->acpi_subsystem_id);
|
||||
return model->apply_prop(aw88399);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aw88399_hda_probe(struct device *dev, struct regmap *regmap)
|
||||
{
|
||||
struct aw88399_hda *aw88399;
|
||||
int ret;
|
||||
|
||||
aw88399 = devm_kzalloc(dev, sizeof(*aw88399), GFP_KERNEL);
|
||||
if (!aw88399)
|
||||
return -ENOMEM;
|
||||
|
||||
if (IS_ERR(regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(regmap), "Failed to obtain regmap\n");
|
||||
|
||||
aw88399->dev = dev;
|
||||
aw88399->regmap = regmap;
|
||||
dev_set_drvdata(dev, aw88399);
|
||||
|
||||
aw88399->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(aw88399->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(aw88399->reset_gpio),
|
||||
"Failed to get reset GPIO\n");
|
||||
|
||||
ret = aw88399_hda_acpi_probe(aw88399);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "ACPI probe failed\n");
|
||||
|
||||
ret = aw88399_hda_init(aw88399);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Chip initialization failed\n");
|
||||
|
||||
/* Enable runtime PM */
|
||||
pm_runtime_set_autosuspend_delay(dev, 3000);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
ret = component_add(dev, &aw88399_hda_comp_ops);
|
||||
if (ret) {
|
||||
pm_runtime_disable(dev);
|
||||
return dev_err_probe(dev, ret, "Failed to register component\n");
|
||||
}
|
||||
|
||||
dev_info(dev, "AW88399 HDA side codec registered successfully\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(aw88399_hda_probe, "SND_HDA_SCODEC_AW88399");
|
||||
|
||||
void aw88399_hda_remove(struct device *dev)
|
||||
{
|
||||
struct aw88399_hda *aw88399 = dev_get_drvdata(dev);
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
if (aw88399->aw_dev)
|
||||
aw88399_stop(aw88399->aw_dev);
|
||||
|
||||
component_del(dev, &aw88399_hda_comp_ops);
|
||||
|
||||
dev_dbg(aw88399->dev, "AW88399 HDA side codec removed\n");
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(aw88399_hda_remove, "SND_HDA_SCODEC_AW88399");
|
||||
|
||||
static int aw88399_hda_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct aw88399_hda *aw88399 = dev_get_drvdata(dev);
|
||||
|
||||
dev_dbg(aw88399->dev, "Runtime suspend\n");
|
||||
|
||||
if (aw88399->aw_dev && aw88399->playing)
|
||||
aw88399_stop(aw88399->aw_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aw88399_hda_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct aw88399_hda *aw88399 = dev_get_drvdata(dev);
|
||||
|
||||
dev_dbg(aw88399->dev, "Runtime resume\n");
|
||||
|
||||
if (aw88399->core && aw88399->aw_dev && aw88399->playing)
|
||||
aw88399_start(aw88399->core, AW88399_SYNC_START);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aw88399_hda_system_suspend(struct device *dev)
|
||||
{
|
||||
struct aw88399_hda *aw88399 = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
dev_dbg(aw88399->dev, "System suspend\n");
|
||||
|
||||
if (aw88399->aw_dev && aw88399->playing)
|
||||
aw88399_stop(aw88399->aw_dev);
|
||||
|
||||
if (aw88399->core)
|
||||
aw88399->core->fw_needs_reload = true;
|
||||
|
||||
ret = pm_runtime_force_suspend(dev);
|
||||
if (ret)
|
||||
dev_err(aw88399->dev, "Runtime force suspend failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aw88399_hda_system_resume(struct device *dev)
|
||||
{
|
||||
struct aw88399_hda *aw88399 = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
dev_dbg(aw88399->dev, "System resume\n");
|
||||
|
||||
if (aw88399->aw_dev)
|
||||
aw88399_hw_reset(aw88399->core);
|
||||
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret)
|
||||
dev_err(aw88399->dev, "Runtime force resume failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct dev_pm_ops aw88399_hda_pm_ops = {
|
||||
RUNTIME_PM_OPS(aw88399_hda_runtime_suspend, aw88399_hda_runtime_resume, NULL)
|
||||
SYSTEM_SLEEP_PM_OPS(aw88399_hda_system_suspend, aw88399_hda_system_resume)
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(aw88399_hda_pm_ops, "SND_HDA_SCODEC_AW88399");
|
||||
|
||||
MODULE_DESCRIPTION("AW88399 HDA driver");
|
||||
MODULE_AUTHOR("Yakov Till <yakov.till@gmail.com>");
|
||||
MODULE_AUTHOR("Marco Giunta <marco_giunta@outlook.it>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE("aw88399_acf.bin");
|
||||
36
sound/hda/codecs/side-codecs/aw88399_hda.h
Normal file
36
sound/hda/codecs/side-codecs/aw88399_hda.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only
|
||||
*
|
||||
* AW88399 HDA side codec driver
|
||||
*/
|
||||
|
||||
#ifndef __AW88399_HDA_H__
|
||||
#define __AW88399_HDA_H__
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <sound/aw88399.h>
|
||||
|
||||
struct aw88399;
|
||||
struct aw_device;
|
||||
|
||||
struct aw88399_hda {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct aw_device *aw_dev;
|
||||
struct aw88399 *core;
|
||||
bool bsts_unreliable;
|
||||
|
||||
const char *acpi_subsystem_id;
|
||||
int index;
|
||||
int channel;
|
||||
|
||||
bool playing;
|
||||
};
|
||||
|
||||
int aw88399_hda_probe(struct device *dev, struct regmap *regmap);
|
||||
void aw88399_hda_remove(struct device *dev);
|
||||
|
||||
extern const struct dev_pm_ops aw88399_hda_pm_ops;
|
||||
|
||||
#endif /* __AW88399_HDA_H__ */
|
||||
54
sound/hda/codecs/side-codecs/aw88399_hda_i2c.c
Normal file
54
sound/hda/codecs/side-codecs/aw88399_hda_i2c.c
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// AW88399 HDA I2C driver
|
||||
//
|
||||
// Based on cs35l41_hda_i2c.c
|
||||
//
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "aw88399_hda.h"
|
||||
|
||||
static int aw88399_hda_i2c_probe(struct i2c_client *clt)
|
||||
{
|
||||
if (!strstr(dev_name(&clt->dev), "AWDZ8399"))
|
||||
return -ENODEV;
|
||||
|
||||
return aw88399_hda_probe(&clt->dev,
|
||||
devm_regmap_init_i2c(clt, &aw88399_remap_config));
|
||||
}
|
||||
|
||||
static void aw88399_hda_i2c_remove(struct i2c_client *clt)
|
||||
{
|
||||
aw88399_hda_remove(&clt->dev);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id aw88399_hda_i2c_id[] = {
|
||||
{ .name = "aw88399-hda" },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct acpi_device_id aw88399_acpi_hda_match[] = {
|
||||
{ "AWDZ8399", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, aw88399_acpi_hda_match);
|
||||
|
||||
static struct i2c_driver aw88399_hda_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "aw88399-hda",
|
||||
.acpi_match_table = aw88399_acpi_hda_match,
|
||||
.pm = &aw88399_hda_pm_ops,
|
||||
},
|
||||
.probe = aw88399_hda_i2c_probe,
|
||||
.remove = aw88399_hda_i2c_remove,
|
||||
.id_table = aw88399_hda_i2c_id,
|
||||
};
|
||||
module_i2c_driver(aw88399_hda_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("HDA AW88399 I2C driver");
|
||||
MODULE_IMPORT_NS("SND_HDA_SCODEC_AW88399");
|
||||
MODULE_AUTHOR("Yakov Till <yakov.till@gmail.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -170,6 +170,7 @@ static int cs35l41_request_firmware_file(struct cs35l41_hda *cs35l41,
|
|||
char *s, c;
|
||||
int ret = 0;
|
||||
|
||||
*firmware = NULL;
|
||||
if (spkid > -1 && ssid && amp_name)
|
||||
*filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s-spkid%d-%s.%s", CS35L41_PART,
|
||||
dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],
|
||||
|
|
@ -528,8 +529,8 @@ static int cs35l41_read_tuning_params(struct cs35l41_hda *cs35l41, const struct
|
|||
|
||||
static int cs35l41_load_tuning_params(struct cs35l41_hda *cs35l41, char *tuning_filename)
|
||||
{
|
||||
const struct firmware *tuning_param_file = NULL;
|
||||
char *tuning_param_filename = NULL;
|
||||
const struct firmware *tuning_param_file __free(firmware) = NULL;
|
||||
char *tuning_param_filename __free(kfree) = NULL;
|
||||
int ret;
|
||||
|
||||
ret = cs35l41_request_tuning_param_file(cs35l41, tuning_filename, &tuning_param_file,
|
||||
|
|
@ -548,19 +549,16 @@ static int cs35l41_load_tuning_params(struct cs35l41_hda *cs35l41, char *tuning_
|
|||
cs35l41_set_default_tuning_params(cs35l41);
|
||||
}
|
||||
|
||||
release_firmware(tuning_param_file);
|
||||
kfree(tuning_param_filename);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs35l41_init_dsp(struct cs35l41_hda *cs35l41)
|
||||
{
|
||||
const struct firmware *coeff_firmware = NULL;
|
||||
const struct firmware *wmfw_firmware = NULL;
|
||||
const struct firmware *coeff_firmware __free(firmware) = NULL;
|
||||
const struct firmware *wmfw_firmware __free(firmware) = NULL;
|
||||
struct cs_dsp *dsp = &cs35l41->cs_dsp;
|
||||
char *coeff_filename = NULL;
|
||||
char *wmfw_filename = NULL;
|
||||
char *coeff_filename __free(kfree) = NULL;
|
||||
char *wmfw_filename __free(kfree) = NULL;
|
||||
int ret;
|
||||
|
||||
if (!cs35l41->halo_initialized) {
|
||||
|
|
@ -592,20 +590,13 @@ static int cs35l41_init_dsp(struct cs35l41_hda *cs35l41)
|
|||
|
||||
ret = cs_dsp_power_up(dsp, wmfw_firmware, wmfw_filename, coeff_firmware, coeff_filename,
|
||||
cs35l41_hda_fw_ids[cs35l41->firmware_type]);
|
||||
if (ret)
|
||||
goto err;
|
||||
if (ret) {
|
||||
cs35l41_set_default_tuning_params(cs35l41);
|
||||
return ret;
|
||||
}
|
||||
|
||||
cs35l41_hda_apply_calibration(cs35l41);
|
||||
|
||||
err:
|
||||
if (ret)
|
||||
cs35l41_set_default_tuning_params(cs35l41);
|
||||
release_firmware(wmfw_firmware);
|
||||
release_firmware(coeff_firmware);
|
||||
kfree(wmfw_filename);
|
||||
kfree(coeff_filename);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cs35l41_shutdown_dsp(struct cs35l41_hda *cs35l41)
|
||||
|
|
@ -1924,7 +1915,6 @@ int cs35l41_hda_parse_acpi(struct cs35l41_hda *cs35l41, struct device *physdev,
|
|||
static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
struct device *physdev;
|
||||
struct spi_device *spi;
|
||||
const char *sub;
|
||||
int ret;
|
||||
|
|
@ -1936,7 +1926,8 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
|
|||
}
|
||||
|
||||
cs35l41->dacpi = adev;
|
||||
physdev = get_device(acpi_get_first_physical_node(adev));
|
||||
struct device *physdev __free(put_device) =
|
||||
get_device(acpi_get_first_physical_node(adev));
|
||||
if (!physdev) {
|
||||
acpi_dev_put(adev);
|
||||
return -ENODEV;
|
||||
|
|
@ -1954,13 +1945,9 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
|
|||
}
|
||||
|
||||
ret = cs35l41_hda_parse_acpi(cs35l41, physdev, id);
|
||||
if (ret) {
|
||||
put_device(physdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
out:
|
||||
put_device(physdev);
|
||||
|
||||
cs35l41->bypass_fw = false;
|
||||
if (cs35l41->control_bus == SPI) {
|
||||
spi = to_spi_device(cs35l41->dev);
|
||||
|
|
|
|||
|
|
@ -527,18 +527,6 @@ static void cs35l56_hda_request_firmware_files(struct cs35l56_hda *cs35l56,
|
|||
base_name, NULL, NULL, "bin");
|
||||
}
|
||||
|
||||
static void cs35l56_hda_release_firmware_files(const struct firmware *wmfw_firmware,
|
||||
char *wmfw_filename,
|
||||
const struct firmware *coeff_firmware,
|
||||
char *coeff_filename)
|
||||
{
|
||||
release_firmware(wmfw_firmware);
|
||||
kfree(wmfw_filename);
|
||||
|
||||
release_firmware(coeff_firmware);
|
||||
kfree(coeff_filename);
|
||||
}
|
||||
|
||||
static int cs35l56_hda_apply_calibration(struct cs35l56_hda *cs35l56)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -561,10 +549,10 @@ static int cs35l56_hda_apply_calibration(struct cs35l56_hda *cs35l56)
|
|||
|
||||
static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)
|
||||
{
|
||||
const struct firmware *coeff_firmware = NULL;
|
||||
const struct firmware *wmfw_firmware = NULL;
|
||||
char *coeff_filename = NULL;
|
||||
char *wmfw_filename = NULL;
|
||||
const struct firmware *coeff_firmware __free(firmware) = NULL;
|
||||
const struct firmware *wmfw_firmware __free(firmware) = NULL;
|
||||
char *coeff_filename __free(kfree) = NULL;
|
||||
char *wmfw_filename __free(kfree) = NULL;
|
||||
unsigned int preloaded_fw_ver;
|
||||
bool firmware_missing;
|
||||
int ret;
|
||||
|
|
@ -606,14 +594,14 @@ static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)
|
|||
if (firmware_missing) {
|
||||
if (!wmfw_firmware) {
|
||||
dev_err(cs35l56->base.dev, ".%s file required but not found\n", "wmfw");
|
||||
goto err_fw_release;
|
||||
return;
|
||||
} else if (!coeff_firmware) {
|
||||
dev_err(cs35l56->base.dev, ".%s file required but not found\n", "bin");
|
||||
goto err_fw_release;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&cs35l56->base.irq_lock);
|
||||
guard(mutex)(&cs35l56->base.irq_lock);
|
||||
|
||||
/*
|
||||
* If the firmware hasn't been patched it must be shutdown before
|
||||
|
|
@ -624,14 +612,14 @@ static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)
|
|||
if (firmware_missing && (wmfw_firmware || coeff_firmware)) {
|
||||
ret = cs35l56_firmware_shutdown(&cs35l56->base);
|
||||
if (ret)
|
||||
goto err;
|
||||
return;
|
||||
}
|
||||
|
||||
ret = cs_dsp_power_up(&cs35l56->cs_dsp, wmfw_firmware, wmfw_filename,
|
||||
coeff_firmware, coeff_filename, "misc");
|
||||
if (ret) {
|
||||
dev_dbg(cs35l56->base.dev, "%s: cs_dsp_power_up ret %d\n", __func__, ret);
|
||||
goto err;
|
||||
return;
|
||||
}
|
||||
|
||||
if (wmfw_filename)
|
||||
|
|
@ -679,11 +667,6 @@ static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)
|
|||
err_powered_up:
|
||||
if (!cs35l56->base.fw_patched)
|
||||
cs_dsp_power_down(&cs35l56->cs_dsp);
|
||||
err:
|
||||
mutex_unlock(&cs35l56->base.irq_lock);
|
||||
err_fw_release:
|
||||
cs35l56_hda_release_firmware_files(wmfw_firmware, wmfw_filename,
|
||||
coeff_firmware, coeff_filename);
|
||||
}
|
||||
|
||||
static void cs35l56_hda_dsp_work(struct work_struct *work)
|
||||
|
|
|
|||
|
|
@ -88,7 +88,6 @@ static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid)
|
|||
{
|
||||
struct gpio_desc *speaker_id;
|
||||
struct acpi_device *adev;
|
||||
struct device *physdev;
|
||||
LIST_HEAD(resources);
|
||||
const char *sub;
|
||||
uint32_t subid;
|
||||
|
|
@ -101,7 +100,8 @@ static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
physdev = get_device(acpi_get_first_physical_node(adev));
|
||||
struct device *physdev __free(put_device) =
|
||||
get_device(acpi_get_first_physical_node(adev));
|
||||
ret = acpi_dev_get_resources(adev, &resources, tas2781_get_i2c_res, p);
|
||||
if (ret < 0) {
|
||||
dev_err(p->dev, "Failed to get ACPI resource.\n");
|
||||
|
|
@ -151,14 +151,12 @@ static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid)
|
|||
end_2563:
|
||||
acpi_dev_free_resource_list(&resources);
|
||||
strscpy(p->dev_name, hid, sizeof(p->dev_name));
|
||||
put_device(physdev);
|
||||
acpi_dev_put(adev);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dev_err(p->dev, "read acpi error, ret: %d\n", ret);
|
||||
put_device(physdev);
|
||||
acpi_dev_put(adev);
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -328,7 +328,6 @@ static int tas2781_read_acpi(struct tas2781_hda *tas_hda,
|
|||
{
|
||||
struct tasdevice_priv *p = tas_hda->priv;
|
||||
struct acpi_device *adev;
|
||||
struct device *physdev;
|
||||
u32 values[HDA_MAX_COMPONENTS];
|
||||
const char *property;
|
||||
size_t nval;
|
||||
|
|
@ -341,7 +340,9 @@ static int tas2781_read_acpi(struct tas2781_hda *tas_hda,
|
|||
}
|
||||
|
||||
strscpy(p->dev_name, hid, sizeof(p->dev_name));
|
||||
physdev = get_device(acpi_get_first_physical_node(adev));
|
||||
|
||||
struct device *physdev __free(put_device) =
|
||||
get_device(acpi_get_first_physical_node(adev));
|
||||
acpi_dev_put(adev);
|
||||
if (!physdev)
|
||||
return -ENODEV;
|
||||
|
|
@ -381,13 +382,11 @@ static int tas2781_read_acpi(struct tas2781_hda *tas_hda,
|
|||
goto err;
|
||||
}
|
||||
}
|
||||
put_device(physdev);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dev_err(p->dev, "read acpi error, ret: %d\n", ret);
|
||||
put_device(physdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -601,9 +601,9 @@ static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* get a unique suffix or an index number */
|
||||
/* get a unique suffix */
|
||||
static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins,
|
||||
int num_pins, int *indexp)
|
||||
int num_pins)
|
||||
{
|
||||
static const char * const channel_sfx[] = {
|
||||
" Front", " Surround", " CLFE", " Side"
|
||||
|
|
@ -615,11 +615,8 @@ static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins,
|
|||
return NULL;
|
||||
if (num_pins == 1)
|
||||
return "";
|
||||
if (num_pins > ARRAY_SIZE(channel_sfx)) {
|
||||
if (indexp)
|
||||
*indexp = i;
|
||||
if (num_pins > ARRAY_SIZE(channel_sfx))
|
||||
return "";
|
||||
}
|
||||
return channel_sfx[i];
|
||||
}
|
||||
|
||||
|
|
@ -638,27 +635,9 @@ static const char *check_output_pfx(struct hda_codec *codec, hda_nid_t nid)
|
|||
return "";
|
||||
}
|
||||
|
||||
static int get_hp_label_index(struct hda_codec *codec, hda_nid_t nid,
|
||||
const hda_nid_t *pins, int num_pins)
|
||||
{
|
||||
int i, j, idx = 0;
|
||||
|
||||
const char *pfx = check_output_pfx(codec, nid);
|
||||
|
||||
i = find_idx_in_nid_list(nid, pins, num_pins);
|
||||
if (i < 0)
|
||||
return -1;
|
||||
for (j = 0; j < i; j++)
|
||||
if (pfx == check_output_pfx(codec, pins[j]))
|
||||
idx++;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,
|
||||
const struct auto_pin_cfg *cfg,
|
||||
const char *name, char *label, int maxlen,
|
||||
int *indexp)
|
||||
const char *name, char *label, int maxlen)
|
||||
{
|
||||
unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
|
||||
int attr = snd_hda_get_input_pin_attr(def_conf);
|
||||
|
|
@ -671,19 +650,11 @@ static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,
|
|||
|
||||
if (cfg) {
|
||||
/* try to give a unique suffix if needed */
|
||||
sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs,
|
||||
indexp);
|
||||
sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs);
|
||||
if (!sfx)
|
||||
sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs);
|
||||
if (!sfx)
|
||||
sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs,
|
||||
indexp);
|
||||
if (!sfx) {
|
||||
/* don't add channel suffix for Headphone controls */
|
||||
int idx = get_hp_label_index(codec, nid, cfg->hp_pins,
|
||||
cfg->hp_outs);
|
||||
if (idx >= 0 && indexp)
|
||||
*indexp = idx;
|
||||
sfx = "";
|
||||
}
|
||||
}
|
||||
snprintf(label, maxlen, "%s%s%s", pfx, name, sfx);
|
||||
return 1;
|
||||
|
|
@ -699,7 +670,6 @@ static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,
|
|||
* @cfg: the parsed pin configuration
|
||||
* @label: the string buffer to store
|
||||
* @maxlen: the max length of string buffer (including termination)
|
||||
* @indexp: the pointer to return the index number (for multiple ctls)
|
||||
*
|
||||
* Get a label for the given pin. This function works for both input and
|
||||
* output pins. When @cfg is given as non-NULL, the function tries to get
|
||||
|
|
@ -708,47 +678,33 @@ static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,
|
|||
* This function tries to give a unique label string for the pin as much as
|
||||
* possible. For example, when the multiple line-outs are present, it adds
|
||||
* the channel suffix like "Front", "Surround", etc (only when @cfg is given).
|
||||
* If no unique name with a suffix is available and @indexp is non-NULL, the
|
||||
* index number is stored in the pointer.
|
||||
*/
|
||||
int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
|
||||
const struct auto_pin_cfg *cfg,
|
||||
char *label, int maxlen, int *indexp)
|
||||
char *label, int maxlen)
|
||||
{
|
||||
unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
|
||||
const char *name = NULL;
|
||||
int i;
|
||||
bool hdmi;
|
||||
|
||||
if (indexp)
|
||||
*indexp = 0;
|
||||
if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
|
||||
return 0;
|
||||
|
||||
switch (get_defcfg_device(def_conf)) {
|
||||
case AC_JACK_LINE_OUT:
|
||||
return fill_audio_out_name(codec, nid, cfg, "Line Out",
|
||||
label, maxlen, indexp);
|
||||
label, maxlen);
|
||||
case AC_JACK_SPEAKER:
|
||||
return fill_audio_out_name(codec, nid, cfg, "Speaker",
|
||||
label, maxlen, indexp);
|
||||
label, maxlen);
|
||||
case AC_JACK_HP_OUT:
|
||||
return fill_audio_out_name(codec, nid, cfg, "Headphone",
|
||||
label, maxlen, indexp);
|
||||
label, maxlen);
|
||||
case AC_JACK_SPDIF_OUT:
|
||||
case AC_JACK_DIG_OTHER_OUT:
|
||||
hdmi = is_hdmi_cfg(def_conf);
|
||||
name = hdmi ? "HDMI" : "SPDIF";
|
||||
if (cfg && indexp)
|
||||
for (i = 0; i < cfg->dig_outs; i++) {
|
||||
hda_nid_t pin = cfg->dig_out_pins[i];
|
||||
unsigned int c;
|
||||
if (pin == nid)
|
||||
break;
|
||||
c = snd_hda_codec_get_pincfg(codec, pin);
|
||||
if (hdmi == is_hdmi_cfg(c))
|
||||
(*indexp)++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (cfg) {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@ static int call_exec_verb(struct hda_bus *bus, struct hda_codec *codec,
|
|||
int err;
|
||||
|
||||
CLASS(snd_hda_power_pm, pm)(codec);
|
||||
if (pm.err < 0 && !bus->core.chip_init) {
|
||||
codec_warn(codec,
|
||||
"Failed to send cmd 0x%x ret=[%d], hda control stopped\n",
|
||||
cmd, pm.err);
|
||||
return pm.err;
|
||||
}
|
||||
guard(mutex)(&bus->core.cmd_mutex);
|
||||
if (flags & HDA_RW_NO_RESPONSE_FALLBACK)
|
||||
bus->no_response_fallback = 1;
|
||||
|
|
@ -2967,8 +2973,11 @@ static void hda_codec_pm_complete(struct device *dev)
|
|||
dev->power.power_state = PMSG_RESUME;
|
||||
|
||||
if (pm_runtime_suspended(dev) && (codec->jackpoll_interval ||
|
||||
hda_codec_need_resume(codec) || codec->forced_resume))
|
||||
hda_codec_need_resume(codec) || codec->forced_resume ||
|
||||
codec->acomp_requested_resume)) {
|
||||
codec->acomp_requested_resume = 0;
|
||||
pm_request_resume(dev);
|
||||
}
|
||||
}
|
||||
|
||||
static int hda_codec_pm_suspend(struct device *dev)
|
||||
|
|
@ -3370,7 +3379,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec,
|
|||
for (; knew->name; knew++) {
|
||||
struct snd_kcontrol *kctl;
|
||||
int addr = 0, idx = 0;
|
||||
if (knew->iface == (__force snd_ctl_elem_iface_t)-1)
|
||||
if (knew->iface == -1)
|
||||
continue; /* skip this codec private value */
|
||||
for (;;) {
|
||||
kctl = snd_ctl_new1(knew, codec);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ const char *hda_get_autocfg_input_label(struct hda_codec *codec,
|
|||
int input);
|
||||
int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
|
||||
const struct auto_pin_cfg *cfg,
|
||||
char *label, int maxlen, int *indexp);
|
||||
char *label, int maxlen);
|
||||
|
||||
enum {
|
||||
INPUT_PIN_ATTR_UNUSED, /* pin not connected */
|
||||
|
|
|
|||
|
|
@ -723,4 +723,11 @@ void snd_hda_codec_display_power(struct hda_codec *codec, bool enable);
|
|||
#define codec_dbg(codec, fmt, args...) \
|
||||
dev_dbg(hda_codec_dev(codec), fmt, ##args)
|
||||
|
||||
/* append a suffix string safely; equivalent with strlcat() */
|
||||
static inline void hda_append_suffix(char *str, const char *suffix, size_t size)
|
||||
{
|
||||
size_t len = strnlen(str, size);
|
||||
strscpy(str + len, suffix, size - len);
|
||||
}
|
||||
|
||||
#endif /* __SOUND_HDA_LOCAL_H */
|
||||
|
|
|
|||
|
|
@ -612,10 +612,10 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
|
|||
if (base_name)
|
||||
strscpy(name, base_name, sizeof(name));
|
||||
else
|
||||
snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), NULL);
|
||||
snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name));
|
||||
if (phantom_jack)
|
||||
/* Example final name: "Internal Mic Phantom Jack" */
|
||||
strncat(name, " Phantom", sizeof(name) - strlen(name) - 1);
|
||||
hda_append_suffix(name, " Phantom", sizeof(name));
|
||||
err = snd_hda_jack_add_kctl(codec, nid, name, phantom_jack, 0, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ config SND_HDA_TEGRA
|
|||
config SND_HDA_CIX_IPBLOQ
|
||||
tristate "CIX IPBLOQ HD Audio"
|
||||
depends on ARCH_CIX || COMPILE_TEST
|
||||
depends on ARCH_DMA_ADDR_T_64BIT
|
||||
select SND_HDA
|
||||
select SND_HDA_ALIGNED_MMIO
|
||||
help
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ enum {
|
|||
#define ATIHDMI_NUM_CAPTURE 0
|
||||
#define ATIHDMI_NUM_PLAYBACK 8
|
||||
|
||||
/* Hygon HD Audio controller */
|
||||
#define PCI_DEVICE_ID_HYGON_18H_M05H_HDA 0x14a9
|
||||
|
||||
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
|
||||
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
|
||||
|
|
@ -241,6 +243,7 @@ enum {
|
|||
AZX_DRIVER_ZHAOXIN,
|
||||
AZX_DRIVER_ZHAOXINHDMI,
|
||||
AZX_DRIVER_LOONGSON,
|
||||
AZX_DRIVER_HYGON,
|
||||
AZX_DRIVER_GENERIC,
|
||||
AZX_NUM_DRIVERS, /* keep this as last entry */
|
||||
};
|
||||
|
|
@ -360,6 +363,7 @@ static const char * const driver_short_names[] = {
|
|||
[AZX_DRIVER_ZHAOXIN] = "HDA Zhaoxin",
|
||||
[AZX_DRIVER_ZHAOXINHDMI] = "HDA Zhaoxin HDMI",
|
||||
[AZX_DRIVER_LOONGSON] = "HDA Loongson",
|
||||
[AZX_DRIVER_HYGON] = "HDA Hygon",
|
||||
[AZX_DRIVER_GENERIC] = "HD-Audio Generic",
|
||||
};
|
||||
|
||||
|
|
@ -1926,6 +1930,10 @@ static int azx_first_init(struct azx *chip)
|
|||
if (chip->driver_type == AZX_DRIVER_ZHAOXINHDMI)
|
||||
bus->polling_mode = 1;
|
||||
|
||||
if (chip->driver_type == AZX_DRIVER_HYGON &&
|
||||
chip->pci->device == PCI_DEVICE_ID_HYGON_18H_M05H_HDA)
|
||||
bus->access_sdnctl_in_dword = 1;
|
||||
|
||||
bus->remap_addr = pcim_iomap_region(pci, 0, "ICH HD audio");
|
||||
if (IS_ERR(bus->remap_addr))
|
||||
return PTR_ERR(bus->remap_addr);
|
||||
|
|
@ -2189,6 +2197,15 @@ static int azx_probe(struct pci_dev *pci,
|
|||
dev_warn(&pci->dev, "dmic_detect option is deprecated, pass snd-intel-dspcfg.dsp_driver=1 option instead\n");
|
||||
}
|
||||
|
||||
/* A sanity check against wild device binding;
|
||||
* here the range 0x200 is enough for the registers used at probe,
|
||||
* but it doesn't mean covering all HD-audio registers
|
||||
*/
|
||||
if (pci_resource_len(pci, 0) < 0x200) {
|
||||
dev_err(&pci->dev, "Too small PCI BAR0\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
|
||||
0, &card);
|
||||
if (err < 0) {
|
||||
|
|
@ -2381,7 +2398,7 @@ static int azx_probe_continue(struct azx *chip)
|
|||
|
||||
#ifdef CONFIG_SND_HDA_PATCH_LOADER
|
||||
if (patch[dev] && *patch[dev]) {
|
||||
const struct firmware *fw = NULL;
|
||||
const struct firmware *fw __free(firmware) = NULL;
|
||||
|
||||
dev_info(&pci->dev, "Applying patch firmware '%s'\n",
|
||||
patch[dev]);
|
||||
|
|
@ -2390,7 +2407,6 @@ static int azx_probe_continue(struct azx *chip)
|
|||
"Cannot load firmware, continue without patching\n");
|
||||
} else {
|
||||
err = snd_hda_load_patch(&chip->bus, fw->size, fw->data);
|
||||
release_firmware(fw);
|
||||
if (err < 0)
|
||||
goto out_free;
|
||||
}
|
||||
|
|
@ -2838,6 +2854,9 @@ static const struct pci_device_id azx_ids[] = {
|
|||
.driver_data = AZX_DRIVER_LOONGSON | AZX_DCAPS_NO_TCSEL },
|
||||
{ PCI_VDEVICE(LOONGSON, PCI_DEVICE_ID_LOONGSON_HDMI),
|
||||
.driver_data = AZX_DRIVER_LOONGSON | AZX_DCAPS_NO_TCSEL },
|
||||
/* Hygon HDAudio */
|
||||
{ PCI_VDEVICE(HYGON, PCI_DEVICE_ID_HYGON_18H_M05H_HDA),
|
||||
.driver_data = AZX_DRIVER_HYGON | AZX_DCAPS_POSFIX_LPIB | AZX_DCAPS_NO_MSI },
|
||||
{ 0, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, azx_ids);
|
||||
|
|
|
|||
|
|
@ -511,7 +511,10 @@ void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus)
|
|||
{
|
||||
unsigned long timeout;
|
||||
|
||||
snd_hdac_chip_updateb(bus, GCTL, AZX_GCTL_RESET, AZX_GCTL_RESET);
|
||||
if (bus->access_sdnctl_in_dword)
|
||||
snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_RESET, AZX_GCTL_RESET);
|
||||
else
|
||||
snd_hdac_chip_updateb(bus, GCTL, AZX_GCTL_RESET, AZX_GCTL_RESET);
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(100);
|
||||
while (!snd_hdac_chip_readb(bus, GCTL) && time_before(jiffies, timeout))
|
||||
|
|
@ -576,7 +579,10 @@ static void azx_int_disable(struct hdac_bus *bus)
|
|||
|
||||
/* disable interrupts in stream descriptor */
|
||||
list_for_each_entry(azx_dev, &bus->stream_list, list)
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0);
|
||||
if (bus->access_sdnctl_in_dword)
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL, SD_INT_MASK, 0);
|
||||
else
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0);
|
||||
|
||||
/* disable SIE for all streams & disable controller CIE and GIE */
|
||||
snd_hdac_chip_writel(bus, INTCTL, 0);
|
||||
|
|
@ -682,6 +688,11 @@ int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
|
|||
sd_status = snd_hdac_stream_readb(azx_dev, SD_STS);
|
||||
snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK);
|
||||
handled |= 1 << azx_dev->index;
|
||||
if (sd_status & (SD_INT_FIFO_ERR | SD_INT_DESC_ERR)) {
|
||||
dev_warn_ratelimited(bus->dev,
|
||||
"stream %u dma error: 0x%02x\n",
|
||||
azx_dev->index, sd_status);
|
||||
}
|
||||
if ((!azx_dev->substream && !azx_dev->cstream) ||
|
||||
!azx_dev->running || !(sd_status & SD_INT_COMPLETE))
|
||||
continue;
|
||||
|
|
@ -713,7 +724,7 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus)
|
|||
BDL_SIZE, &s->bdl);
|
||||
num_streams++;
|
||||
if (err < 0)
|
||||
return -ENOMEM;
|
||||
goto error_bdl;
|
||||
}
|
||||
|
||||
if (WARN_ON(!num_streams))
|
||||
|
|
@ -722,12 +733,24 @@ int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus)
|
|||
err = snd_dma_alloc_pages(dma_type, bus->dev,
|
||||
num_streams * 8, &bus->posbuf);
|
||||
if (err < 0)
|
||||
return -ENOMEM;
|
||||
goto error_bdl;
|
||||
list_for_each_entry(s, &bus->stream_list, list)
|
||||
s->posbuf = (__le32 *)(bus->posbuf.area + s->index * 8);
|
||||
|
||||
/* single page (at least 4096 bytes) must suffice for both ringbuffes */
|
||||
return snd_dma_alloc_pages(dma_type, bus->dev, PAGE_SIZE, &bus->rb);
|
||||
err = snd_dma_alloc_pages(dma_type, bus->dev, PAGE_SIZE, &bus->rb);
|
||||
if (err < 0)
|
||||
goto error_posbuf;
|
||||
return 0;
|
||||
|
||||
error_posbuf:
|
||||
snd_dma_free_pages(&bus->posbuf);
|
||||
error_bdl:
|
||||
list_for_each_entry(s, &bus->stream_list, list) {
|
||||
if (s->bdl.area)
|
||||
snd_dma_free_pages(&s->bdl);
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_bus_alloc_stream_pages);
|
||||
|
||||
|
|
|
|||
|
|
@ -765,7 +765,7 @@ unsigned int snd_hdac_stream_format_bits(snd_pcm_format_t format, snd_pcm_subfor
|
|||
|
||||
params_set_format(¶ms, snd_hdac_format_normalize(format));
|
||||
snd_mask_set(hw_param_mask(¶ms, SNDRV_PCM_HW_PARAM_SUBFORMAT),
|
||||
(__force unsigned int)subformat);
|
||||
subformat);
|
||||
|
||||
bits = snd_pcm_hw_params_bits(¶ms);
|
||||
if (maxbits)
|
||||
|
|
|
|||
|
|
@ -210,8 +210,8 @@ void snd_hdac_ext_stream_reset(struct hdac_ext_stream *hext_stream)
|
|||
break;
|
||||
udelay(3);
|
||||
} while (--timeout);
|
||||
val &= ~AZX_PPLCCTL_STRST;
|
||||
writel(val, hext_stream->pplc_addr + AZX_REG_PPLCCTL);
|
||||
snd_hdac_updatel(hext_stream->pplc_addr, AZX_REG_PPLCCTL,
|
||||
AZX_PPLCCTL_STRST, 0);
|
||||
udelay(3);
|
||||
|
||||
timeout = 50;
|
||||
|
|
|
|||
|
|
@ -39,10 +39,7 @@ EXPORT_SYMBOL_GPL(hdac_get_device_id);
|
|||
|
||||
static int hdac_codec_match(struct hdac_device *dev, const struct hdac_driver *drv)
|
||||
{
|
||||
if (hdac_get_device_id(dev, drv))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
return !!hdac_get_device_id(dev, drv);
|
||||
}
|
||||
|
||||
static int hda_bus_match(struct device *dev, const struct device_driver *drv)
|
||||
|
|
@ -59,9 +56,7 @@ static int hda_bus_match(struct device *dev, const struct device_driver *drv)
|
|||
*/
|
||||
if (hdrv->match)
|
||||
return hdrv->match(hdev, hdrv);
|
||||
else
|
||||
return hdac_codec_match(hdev, hdrv);
|
||||
return 1;
|
||||
return hdac_codec_match(hdev, hdrv);
|
||||
}
|
||||
|
||||
static int hda_uevent(const struct device *dev, struct kobj_uevent_env *env)
|
||||
|
|
|
|||
|
|
@ -146,8 +146,12 @@ void snd_hdac_stream_start(struct hdac_stream *azx_dev)
|
|||
stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream);
|
||||
else
|
||||
stripe_ctl = 0;
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK,
|
||||
stripe_ctl);
|
||||
if (bus->access_sdnctl_in_dword)
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK,
|
||||
stripe_ctl);
|
||||
else
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK,
|
||||
stripe_ctl);
|
||||
}
|
||||
/* set DMA start and interrupt mask */
|
||||
if (bus->access_sdnctl_in_dword)
|
||||
|
|
@ -166,11 +170,22 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_start);
|
|||
*/
|
||||
static void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
|
||||
{
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL,
|
||||
SD_CTL_DMA_START | SD_INT_MASK, 0);
|
||||
snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
|
||||
if (azx_dev->stripe)
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
|
||||
struct hdac_bus *bus = azx_dev->bus;
|
||||
|
||||
if (bus->access_sdnctl_in_dword) {
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL,
|
||||
SD_CTL_DMA_START | SD_INT_MASK, 0);
|
||||
snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
|
||||
if (azx_dev->stripe)
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
|
||||
} else {
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL,
|
||||
SD_CTL_DMA_START | SD_INT_MASK, 0);
|
||||
snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
|
||||
if (azx_dev->stripe)
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
|
||||
}
|
||||
|
||||
azx_dev->running = false;
|
||||
}
|
||||
|
||||
|
|
@ -225,12 +240,16 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
|
|||
{
|
||||
unsigned char val;
|
||||
int dma_run_state;
|
||||
struct hdac_bus *bus = azx_dev->bus;
|
||||
|
||||
snd_hdac_stream_clear(azx_dev);
|
||||
|
||||
dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START;
|
||||
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);
|
||||
if (bus->access_sdnctl_in_dword)
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);
|
||||
else
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);
|
||||
|
||||
/* wait for hardware to report that the stream entered reset */
|
||||
snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, (val & SD_CTL_STREAM_RESET), 3, 300);
|
||||
|
|
@ -238,7 +257,10 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
|
|||
if (azx_dev->bus->dma_stop_delay && dma_run_state)
|
||||
udelay(azx_dev->bus->dma_stop_delay);
|
||||
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0);
|
||||
if (bus->access_sdnctl_in_dword)
|
||||
snd_hdac_stream_updatel(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0);
|
||||
else
|
||||
snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0);
|
||||
|
||||
/* wait for hardware to report that the stream is out of reset */
|
||||
snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, !(val & SD_CTL_STREAM_RESET), 3, 300);
|
||||
|
|
|
|||
|
|
@ -367,7 +367,8 @@ static int snd_msnd_init_sma(struct snd_msnd *chip)
|
|||
static int upload_dsp_code(struct snd_card *card)
|
||||
{
|
||||
struct snd_msnd *chip = card->private_data;
|
||||
const struct firmware *init_fw = NULL, *perm_fw = NULL;
|
||||
const struct firmware *init_fw __free(firmware) = NULL;
|
||||
const struct firmware *perm_fw __free(firmware) = NULL;
|
||||
int err;
|
||||
|
||||
outb(HPBLKSEL_0, chip->io + HP_BLKS);
|
||||
|
|
@ -375,28 +376,21 @@ static int upload_dsp_code(struct snd_card *card)
|
|||
err = request_firmware(&init_fw, INITCODEFILE, card->dev);
|
||||
if (err < 0) {
|
||||
dev_err(card->dev, LOGNAME ": Error loading " INITCODEFILE);
|
||||
goto cleanup1;
|
||||
return err;
|
||||
}
|
||||
err = request_firmware(&perm_fw, PERMCODEFILE, card->dev);
|
||||
if (err < 0) {
|
||||
dev_err(card->dev, LOGNAME ": Error loading " PERMCODEFILE);
|
||||
goto cleanup;
|
||||
return err;
|
||||
}
|
||||
|
||||
memcpy_toio(chip->mappedbase, perm_fw->data, perm_fw->size);
|
||||
if (snd_msnd_upload_host(chip, init_fw->data, init_fw->size) < 0) {
|
||||
dev_warn(card->dev, LOGNAME ": Error uploading to DSP\n");
|
||||
err = -ENODEV;
|
||||
goto cleanup;
|
||||
return -ENODEV;
|
||||
}
|
||||
dev_info(card->dev, LOGNAME ": DSP firmware uploaded\n");
|
||||
err = 0;
|
||||
|
||||
cleanup:
|
||||
release_firmware(perm_fw);
|
||||
cleanup1:
|
||||
release_firmware(init_fw);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MSND_CLASSIC
|
||||
|
|
|
|||
|
|
@ -526,7 +526,7 @@ static int upload_dma_data(struct soundscape *s, const unsigned char *data,
|
|||
static int sscape_upload_bootblock(struct snd_card *card)
|
||||
{
|
||||
struct soundscape *sscape = get_card_soundscape(card);
|
||||
const struct firmware *init_fw = NULL;
|
||||
const struct firmware *init_fw __free(firmware) = NULL;
|
||||
int data = 0;
|
||||
int ret;
|
||||
|
||||
|
|
@ -537,8 +537,6 @@ static int sscape_upload_bootblock(struct snd_card *card)
|
|||
}
|
||||
ret = upload_dma_data(sscape, init_fw->data, init_fw->size);
|
||||
|
||||
release_firmware(init_fw);
|
||||
|
||||
guard(spinlock_irqsave)(&sscape->lock);
|
||||
if (ret == 0)
|
||||
data = host_read_ctrl_unsafe(sscape->io_base, 100);
|
||||
|
|
@ -562,7 +560,7 @@ static int sscape_upload_bootblock(struct snd_card *card)
|
|||
static int sscape_upload_microcode(struct snd_card *card, int version)
|
||||
{
|
||||
struct soundscape *sscape = get_card_soundscape(card);
|
||||
const struct firmware *init_fw = NULL;
|
||||
const struct firmware *init_fw __free(firmware) = NULL;
|
||||
char name[14];
|
||||
int err;
|
||||
|
||||
|
|
@ -579,8 +577,6 @@ static int sscape_upload_microcode(struct snd_card *card, int version)
|
|||
dev_info(card->dev, "sscape: MIDI firmware loaded %zu KBs\n",
|
||||
init_fw->size >> 10);
|
||||
|
||||
release_firmware(init_fw);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -232,41 +232,32 @@ snd_wavefront_fx_start (snd_wavefront_t *dev)
|
|||
{
|
||||
unsigned int i;
|
||||
int err;
|
||||
const struct firmware *firmware = NULL;
|
||||
const struct firmware *firmware __free(firmware) = NULL;
|
||||
|
||||
if (dev->fx_initialized)
|
||||
return 0;
|
||||
|
||||
err = request_firmware(&firmware, "yamaha/yss225_registers.bin",
|
||||
dev->card->dev);
|
||||
if (err < 0) {
|
||||
err = -1;
|
||||
goto out;
|
||||
}
|
||||
if (err < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i + 1 < firmware->size; i += 2) {
|
||||
if (firmware->data[i] >= 8 && firmware->data[i] < 16) {
|
||||
outb(firmware->data[i + 1],
|
||||
dev->base + firmware->data[i]);
|
||||
} else if (firmware->data[i] == WAIT_IDLE) {
|
||||
if (!wavefront_fx_idle(dev)) {
|
||||
err = -1;
|
||||
goto out;
|
||||
}
|
||||
if (!wavefront_fx_idle(dev))
|
||||
return -1;
|
||||
} else {
|
||||
dev_err(dev->card->dev,
|
||||
"invalid address in register data\n");
|
||||
err = -1;
|
||||
goto out;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
dev->fx_initialized = 1;
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
release_firmware(firmware);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_FIRMWARE("yamaha/yss225_registers.bin");
|
||||
|
|
|
|||
|
|
@ -2053,7 +2053,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
|
|||
const unsigned char *buf;
|
||||
int len, err;
|
||||
int section_cnt_downloaded = 0;
|
||||
const struct firmware *firmware;
|
||||
const struct firmware *firmware __free(firmware) = NULL;
|
||||
|
||||
err = request_firmware(&firmware, path, dev->card->dev);
|
||||
if (err < 0) {
|
||||
|
|
@ -2108,11 +2108,9 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
|
|||
section_cnt_downloaded++;
|
||||
}
|
||||
|
||||
release_firmware(firmware);
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
release_firmware(firmware);
|
||||
dev_err(dev->card->dev, "firmware download failed!!!\n");
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ static void print_hwparams(struct snd_pcm_substream *substream,
|
|||
snd_pcm_format_width(params_format(p)) / 8);
|
||||
}
|
||||
|
||||
#define INVALID_FORMAT (__force snd_pcm_format_t)(-1)
|
||||
#define INVALID_FORMAT -1
|
||||
|
||||
static const snd_pcm_format_t hpi_to_alsa_formats[] = {
|
||||
INVALID_FORMAT, /* INVALID */
|
||||
|
|
|
|||
|
|
@ -537,6 +537,11 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao,
|
|||
hr1.size = sizeof(hr1);
|
||||
|
||||
error = hpi6000_message_response_sequence(pao, 0, &hm, &hr0);
|
||||
if (error) {
|
||||
HPI_DEBUG_LOG(ERROR, "message transport error %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
if (hr0.error) {
|
||||
HPI_DEBUG_LOG(DEBUG, "message error %d\n", hr0.error);
|
||||
return hr0.error;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ struct dsp_code_private {
|
|||
short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
|
||||
u32 *os_error_code)
|
||||
{
|
||||
const struct firmware *firmware;
|
||||
const struct firmware *firmware __free(firmware) = NULL;
|
||||
struct pci_dev *dev = os_data;
|
||||
struct code_header header;
|
||||
char fw_name[20];
|
||||
|
|
@ -37,11 +37,11 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
|
|||
if (err || !firmware) {
|
||||
dev_err(&dev->dev, "%d, request_firmware failed for %s\n",
|
||||
err, fw_name);
|
||||
goto error1;
|
||||
goto error;
|
||||
}
|
||||
if (firmware->size < sizeof(header)) {
|
||||
dev_err(&dev->dev, "Header size too small %s\n", fw_name);
|
||||
goto error2;
|
||||
goto error;
|
||||
}
|
||||
memcpy(&header, firmware->data, sizeof(header));
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
|
|||
dev_err(&dev->dev,
|
||||
"Invalid firmware header size %d != file %zd\n",
|
||||
header.size, firmware->size);
|
||||
goto error2;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (HPI_VER_MAJOR(header.version) != HPI_VER_MAJOR(HPI_VER)) {
|
||||
|
|
@ -59,7 +59,7 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
|
|||
dev_err(&dev->dev,
|
||||
"Incompatible firmware version DSP image %X != Driver %X\n",
|
||||
header.version, HPI_VER);
|
||||
goto error2;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (header.version != HPI_VER) {
|
||||
|
|
@ -72,19 +72,17 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
|
|||
dsp_code->pvt = kmalloc_obj(*dsp_code->pvt);
|
||||
if (!dsp_code->pvt) {
|
||||
err_ret = HPI_ERROR_MEMORY_ALLOC;
|
||||
goto error2;
|
||||
goto error;
|
||||
}
|
||||
|
||||
dsp_code->pvt->dev = dev;
|
||||
dsp_code->pvt->firmware = firmware;
|
||||
dsp_code->pvt->firmware = no_free_ptr(firmware);
|
||||
dsp_code->header = header;
|
||||
dsp_code->block_length = header.size / sizeof(u32);
|
||||
dsp_code->word_count = sizeof(header) / sizeof(u32);
|
||||
return 0;
|
||||
|
||||
error2:
|
||||
release_firmware(firmware);
|
||||
error1:
|
||||
error:
|
||||
dsp_code->block_length = 0;
|
||||
return err_ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -385,8 +385,7 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev,
|
|||
if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) {
|
||||
memlen = pci_resource_len(pci_dev, idx);
|
||||
pci.ap_mem_base[idx] =
|
||||
ioremap(pci_resource_start(pci_dev, idx),
|
||||
memlen);
|
||||
pcim_iomap(pci_dev, idx, memlen);
|
||||
if (!pci.ap_mem_base[idx]) {
|
||||
HPI_DEBUG_LOG(ERROR,
|
||||
"ioremap failed, aborting\n");
|
||||
|
|
@ -509,13 +508,6 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev,
|
|||
return 0;
|
||||
|
||||
err:
|
||||
while (--idx >= 0) {
|
||||
if (pci.ap_mem_base[idx]) {
|
||||
iounmap(pci.ap_mem_base[idx]);
|
||||
pci.ap_mem_base[idx] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (adapter.p_buffer) {
|
||||
adapter.buffer_size = 0;
|
||||
vfree(adapter.p_buffer);
|
||||
|
|
@ -527,14 +519,11 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev,
|
|||
|
||||
void asihpi_adapter_remove(struct pci_dev *pci_dev)
|
||||
{
|
||||
int idx;
|
||||
struct hpi_message hm;
|
||||
struct hpi_response hr;
|
||||
struct hpi_adapter *pa;
|
||||
struct hpi_pci pci;
|
||||
|
||||
pa = pci_get_drvdata(pci_dev);
|
||||
pci = pa->adapter->pci;
|
||||
|
||||
/* Disable IRQ generation on DSP side */
|
||||
hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
|
||||
|
|
@ -550,10 +539,6 @@ void asihpi_adapter_remove(struct pci_dev *pci_dev)
|
|||
hm.adapter_index = pa->adapter->index;
|
||||
hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
|
||||
|
||||
/* unmap PCI memory space, mapped during device init. */
|
||||
for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; ++idx)
|
||||
iounmap(pci.ap_mem_base[idx]);
|
||||
|
||||
if (pa->irq)
|
||||
free_irq(pa->irq, pa);
|
||||
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@ static int load_firmware(struct snd_cs46xx *chip,
|
|||
unsigned int nums, fwlen, fwsize;
|
||||
const __le32 *fwdat;
|
||||
struct dsp_module_desc *module = NULL;
|
||||
const struct firmware *fw;
|
||||
const struct firmware *fw __free(firmware) = NULL;
|
||||
char fw_path[32];
|
||||
|
||||
sprintf(fw_path, "cs46xx/%s", fw_name);
|
||||
|
|
@ -395,10 +395,8 @@ static int load_firmware(struct snd_cs46xx *chip,
|
|||
if (err < 0)
|
||||
return err;
|
||||
fwsize = fw->size / 4;
|
||||
if (fwsize < 2) {
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
if (fwsize < 2)
|
||||
return -EINVAL;
|
||||
|
||||
err = -ENOMEM;
|
||||
module = kzalloc_obj(*module);
|
||||
|
|
@ -454,14 +452,12 @@ static int load_firmware(struct snd_cs46xx *chip,
|
|||
}
|
||||
|
||||
*module_ret = module;
|
||||
release_firmware(fw);
|
||||
return 0;
|
||||
|
||||
error_inval:
|
||||
err = -EINVAL;
|
||||
error:
|
||||
free_module_desc(module);
|
||||
release_firmware(fw);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -500,22 +496,18 @@ MODULE_FIRMWARE("cs46xx/ba1");
|
|||
|
||||
static int load_firmware(struct snd_cs46xx *chip)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
const struct firmware *fw __free(firmware) = NULL;
|
||||
int i, size, err;
|
||||
|
||||
err = request_firmware(&fw, "cs46xx/ba1", &chip->pci->dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (fw->size != sizeof(*chip->ba1)) {
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
if (fw->size != sizeof(*chip->ba1))
|
||||
return -EINVAL;
|
||||
|
||||
chip->ba1 = vmalloc(sizeof(*chip->ba1));
|
||||
if (!chip->ba1) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
if (!chip->ba1)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy_le32(chip->ba1, fw->data, sizeof(*chip->ba1));
|
||||
|
||||
|
|
@ -524,11 +516,9 @@ static int load_firmware(struct snd_cs46xx *chip)
|
|||
for (i = 0; i < BA1_MEMORY_COUNT; i++)
|
||||
size += chip->ba1->memory[i].size;
|
||||
if (size > BA1_DWORD_SIZE * 4)
|
||||
err = -EINVAL;
|
||||
return -EINVAL;
|
||||
|
||||
error:
|
||||
release_firmware(fw);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused int snd_cs46xx_download_image(struct snd_cs46xx *chip)
|
||||
|
|
|
|||
|
|
@ -990,7 +990,7 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
|
|||
i < icode->gpr_list_control_count) {
|
||||
memset(gctl, 0, sizeof(*gctl));
|
||||
id = &ctl->kcontrol->id;
|
||||
gctl->id.iface = (__force int)id->iface;
|
||||
gctl->id.iface = id->iface;
|
||||
strscpy(gctl->id.name, id->name, sizeof(gctl->id.name));
|
||||
gctl->id.index = id->index;
|
||||
gctl->id.device = id->device;
|
||||
|
|
@ -1156,7 +1156,7 @@ static void
|
|||
snd_emu10k1_init_mono_control2(struct snd_emu10k1_fx8010_control_gpr *ctl,
|
||||
const char *name, int gpr, int defval, int defval_hr)
|
||||
{
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strscpy(ctl->id.name, name);
|
||||
ctl->vcount = ctl->count = 1;
|
||||
if (high_res_gpr_volume) {
|
||||
|
|
@ -1180,7 +1180,7 @@ static void
|
|||
snd_emu10k1_init_stereo_control2(struct snd_emu10k1_fx8010_control_gpr *ctl,
|
||||
const char *name, int gpr, int defval, int defval_hr)
|
||||
{
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strscpy(ctl->id.name, name);
|
||||
ctl->vcount = ctl->count = 2;
|
||||
if (high_res_gpr_volume) {
|
||||
|
|
@ -1205,7 +1205,7 @@ static void
|
|||
snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
|
||||
const char *name, int gpr, int defval)
|
||||
{
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strscpy(ctl->id.name, name);
|
||||
ctl->vcount = ctl->count = 1;
|
||||
ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
|
||||
|
|
@ -1218,7 +1218,7 @@ static void
|
|||
snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
|
||||
const char *name, int gpr, int defval)
|
||||
{
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strscpy(ctl->id.name, name);
|
||||
ctl->vcount = ctl->count = 2;
|
||||
ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
|
||||
|
|
@ -1542,7 +1542,7 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
|
|||
* Process tone control
|
||||
*/
|
||||
ctl = &controls[nctl + 0];
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strscpy(ctl->id.name, "Tone Control - Bass");
|
||||
ctl->vcount = 2;
|
||||
ctl->count = 10;
|
||||
|
|
@ -1551,7 +1551,7 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
|
|||
ctl->value[0] = ctl->value[1] = 20;
|
||||
ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
|
||||
ctl = &controls[nctl + 1];
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strscpy(ctl->id.name, "Tone Control - Treble");
|
||||
ctl->vcount = 2;
|
||||
ctl->count = 10;
|
||||
|
|
@ -2137,7 +2137,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
|
|||
* Process tone control
|
||||
*/
|
||||
ctl = &controls[i + 0];
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strscpy(ctl->id.name, "Tone Control - Bass");
|
||||
ctl->vcount = 2;
|
||||
ctl->count = 10;
|
||||
|
|
@ -2147,7 +2147,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
|
|||
ctl->tlv = snd_emu10k1_bass_treble_db_scale;
|
||||
ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
|
||||
ctl = &controls[i + 1];
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strscpy(ctl->id.name, "Tone Control - Treble");
|
||||
ctl->vcount = 2;
|
||||
ctl->count = 10;
|
||||
|
|
|
|||
|
|
@ -1980,7 +1980,7 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci)
|
|||
__maybe_unused unsigned ioport_size;
|
||||
__maybe_unused unsigned iomem2_size;
|
||||
struct snd_korg1212 *korg1212 = card->private_data;
|
||||
const struct firmware *dsp_code;
|
||||
const struct firmware *dsp_code __free(firmware) = NULL;
|
||||
|
||||
err = pcim_enable_device(pci);
|
||||
if (err < 0)
|
||||
|
|
@ -2147,10 +2147,8 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci)
|
|||
|
||||
korg1212->dma_dsp = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
|
||||
dsp_code->size);
|
||||
if (!korg1212->dma_dsp) {
|
||||
release_firmware(dsp_code);
|
||||
if (!korg1212->dma_dsp)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
K1212_DEBUG_PRINTK("K1212_DEBUG: DSP Code area = 0x%p (0x%08x) %d bytes [%s]\n",
|
||||
korg1212->dma_dsp->area, korg1212->dma_dsp->addr, dsp_code->size,
|
||||
|
|
@ -2158,8 +2156,6 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci)
|
|||
|
||||
memcpy(korg1212->dma_dsp->area, dsp_code->data, dsp_code->size);
|
||||
|
||||
release_firmware(dsp_code);
|
||||
|
||||
rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_RebootCard, 0, 0, 0, 0);
|
||||
|
||||
if (rc)
|
||||
|
|
|
|||
|
|
@ -560,12 +560,11 @@ int snd_mixart_setup_firmware(struct mixart_mgr *mgr)
|
|||
"miXart8.xlx", "miXart8.elf", "miXart8AES.xlx"
|
||||
};
|
||||
char path[32];
|
||||
|
||||
const struct firmware *fw_entry;
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
sprintf(path, "mixart/%s", fw_files[i]);
|
||||
const struct firmware *fw_entry __free(firmware) = NULL;
|
||||
if (request_firmware(&fw_entry, path, &mgr->pci->dev)) {
|
||||
dev_err(&mgr->pci->dev,
|
||||
"miXart: can't load firmware %s\n", path);
|
||||
|
|
@ -573,7 +572,6 @@ int snd_mixart_setup_firmware(struct mixart_mgr *mgr)
|
|||
}
|
||||
/* fake hwdep dsp record */
|
||||
err = mixart_dsp_load(mgr, i, fw_entry);
|
||||
release_firmware(fw_entry);
|
||||
if (err < 0)
|
||||
return err;
|
||||
mgr->dsp_loaded |= 1 << i;
|
||||
|
|
|
|||
|
|
@ -367,7 +367,6 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
|
|||
};
|
||||
char path[32];
|
||||
|
||||
const struct firmware *fw_entry;
|
||||
int i, err;
|
||||
int fw_set = mgr->fw_file_set;
|
||||
|
||||
|
|
@ -375,6 +374,7 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
|
|||
if (!fw_files[fw_set][i])
|
||||
continue;
|
||||
sprintf(path, "pcxhr/%s", fw_files[fw_set][i]);
|
||||
const struct firmware *fw_entry __free(firmware) = NULL;
|
||||
if (request_firmware(&fw_entry, path, &mgr->pci->dev)) {
|
||||
dev_err(&mgr->pci->dev,
|
||||
"pcxhr: can't load firmware %s\n",
|
||||
|
|
@ -383,7 +383,6 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
|
|||
}
|
||||
/* fake hwdep dsp record */
|
||||
err = pcxhr_dsp_load(mgr, i, fw_entry);
|
||||
release_firmware(fw_entry);
|
||||
if (err < 0)
|
||||
return err;
|
||||
mgr->dsp_loaded |= 1 << i;
|
||||
|
|
|
|||
|
|
@ -1260,16 +1260,16 @@ static int sis_chip_create(struct snd_card *card,
|
|||
sis->irq = -1;
|
||||
sis->ioport = pci_resource_start(pci, 0);
|
||||
|
||||
rc = pcim_request_all_regions(pci, "SiS7019");
|
||||
rc = pcim_request_region(pci, 0, "SiS7019");
|
||||
if (rc) {
|
||||
dev_err(&pci->dev, "unable request regions\n");
|
||||
dev_err(&pci->dev, "unable request I/O region\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
sis->ioaddr = devm_ioremap(&pci->dev, pci_resource_start(pci, 1), 0x4000);
|
||||
if (!sis->ioaddr) {
|
||||
sis->ioaddr = pcim_iomap_region(pci, 1, "SiS7019");
|
||||
if (IS_ERR(sis->ioaddr)) {
|
||||
dev_err(&pci->dev, "unable to remap MMIO, aborting\n");
|
||||
return -EIO;
|
||||
return PTR_ERR(sis->ioaddr);
|
||||
}
|
||||
|
||||
rc = sis_alloc_suspend(sis);
|
||||
|
|
|
|||
|
|
@ -573,24 +573,18 @@ static inline unsigned int calc_linear_pos(struct via82xx_modem *chip,
|
|||
viadev->bufsize2, viadev->idx_table[idx].offset,
|
||||
viadev->idx_table[idx].size, count);
|
||||
#endif
|
||||
if (count && size < count) {
|
||||
if (! count)
|
||||
/* bogus count 0 on the DMA boundary? */
|
||||
res = viadev->idx_table[idx].offset;
|
||||
else
|
||||
/* count register returns full size
|
||||
* when end of buffer is reached
|
||||
*/
|
||||
res = viadev->idx_table[idx].offset + size;
|
||||
if (check_invalid_pos(viadev, res)) {
|
||||
dev_dbg(chip->card->dev,
|
||||
"invalid via82xx_cur_ptr, using last valid pointer\n");
|
||||
"invalid via82xx_cur_ptr (2), using last valid pointer\n");
|
||||
res = viadev->lastpos;
|
||||
} else {
|
||||
if (! count)
|
||||
/* bogus count 0 on the DMA boundary? */
|
||||
res = viadev->idx_table[idx].offset;
|
||||
else
|
||||
/* count register returns full size
|
||||
* when end of buffer is reached
|
||||
*/
|
||||
res = viadev->idx_table[idx].offset + size;
|
||||
if (check_invalid_pos(viadev, res)) {
|
||||
dev_dbg(chip->card->dev,
|
||||
"invalid via82xx_cur_ptr (2), using last valid pointer\n");
|
||||
res = viadev->lastpos;
|
||||
}
|
||||
}
|
||||
}
|
||||
viadev->lastpos = res; /* remember the last position */
|
||||
|
|
|
|||
|
|
@ -518,8 +518,9 @@ static const struct snd_kcontrol_new snd_aica_pcmvolume_control = {
|
|||
static int load_aica_firmware(void)
|
||||
{
|
||||
int err;
|
||||
const struct firmware *fw_entry;
|
||||
spu_reset();
|
||||
|
||||
const struct firmware *fw_entry __free(firmware) = NULL;
|
||||
err = request_firmware(&fw_entry, "aica_firmware.bin", &pd->dev);
|
||||
if (unlikely(err))
|
||||
return err;
|
||||
|
|
@ -527,7 +528,6 @@ static int load_aica_firmware(void)
|
|||
spu_disable();
|
||||
spu_memload(0, fw_entry->data, fw_entry->size);
|
||||
spu_enable();
|
||||
release_firmware(fw_entry);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -726,6 +726,10 @@ config SND_SOC_AW87390
|
|||
sound quality, which is a new high efficiency, low
|
||||
noise, constant large volume, 6th Smart K audio amplifier.
|
||||
|
||||
config SND_SOC_AW88399_LIB
|
||||
tristate
|
||||
select SND_SOC_AW88395_LIB
|
||||
|
||||
config SND_SOC_AW88399
|
||||
tristate "Soc Audio for awinic aw88399"
|
||||
depends on I2C
|
||||
|
|
@ -733,6 +737,7 @@ config SND_SOC_AW88399
|
|||
select REGMAP_I2C
|
||||
select GPIOLIB
|
||||
select SND_SOC_AW88395_LIB
|
||||
select SND_SOC_AW88399_LIB
|
||||
help
|
||||
This option enables support for aw88399 Smart PA.
|
||||
The awinic AW88399 is an I2S/TDM input, high efficiency
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ snd-soc-aw88395-y := aw88395/aw88395.o
|
|||
snd-soc-aw88166-y := aw88166.o
|
||||
snd-soc-aw88261-y := aw88261.o
|
||||
snd-soc-aw88399-y := aw88399.o
|
||||
snd-soc-aw88399-lib-y := aw88399-lib.o
|
||||
snd-soc-bd28623-y := bd28623.o
|
||||
snd-soc-bt-sco-y := bt-sco.o
|
||||
snd-soc-chv3-codec-y := chv3-codec.o
|
||||
|
|
@ -496,6 +497,7 @@ obj-$(CONFIG_SND_SOC_AW88395) +=snd-soc-aw88395.o
|
|||
obj-$(CONFIG_SND_SOC_AW88166) +=snd-soc-aw88166.o
|
||||
obj-$(CONFIG_SND_SOC_AW88261) +=snd-soc-aw88261.o
|
||||
obj-$(CONFIG_SND_SOC_AW88399) += snd-soc-aw88399.o
|
||||
obj-$(CONFIG_SND_SOC_AW88399_LIB) += snd-soc-aw88399-lib.o
|
||||
obj-$(CONFIG_SND_SOC_BD28623) += snd-soc-bd28623.o
|
||||
obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o
|
||||
obj-$(CONFIG_SND_SOC_CHV3_CODEC) += snd-soc-chv3-codec.o
|
||||
|
|
|
|||
1411
sound/soc/codecs/aw88399-lib.c
Normal file
1411
sound/soc/codecs/aw88399-lib.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user