Compare commits
No commits in common. "linux5.14" and "master" have entirely different histories.
15 changed files with 7661 additions and 4544 deletions
11
Makefile
11
Makefile
|
@ -1,11 +1,10 @@
|
|||
snd-hda-codec-cirrus-objs := patch_cirrus.o
|
||||
obj-$(CONFIG_SND_HDA_CODEC_CIRRUS) += snd-hda-codec-cirrus.o
|
||||
snd-hda-codec-cs8409-objs := patch_cs8409.o patch_cs8409-tables.o
|
||||
obj-$(CONFIG_SND_HDA_CODEC_CS8409) += snd-hda-codec-cs8409.o
|
||||
|
||||
# debug build flags
|
||||
#KBUILD_EXTRA_CFLAGS = "-DCONFIG_SND_DEBUG=1 -DMYSOUNDDEBUGFULL -DCONFIG_SND_HDA_RECONFIG=1 -Wno-unused-variable -Wno-unused-function"
|
||||
#KBUILD_EXTRA_CFLAGS = "-DCONFIG_SND_DEBUG=1 -DMYSOUNDDEBUGFULL -DAPPLE_PINSENSE_FIXUP -DAPPLE_CODECS -DCONFIG_SND_HDA_RECONFIG=1 -Wno-unused-variable -Wno-unused-function"
|
||||
# normal build flags
|
||||
KBUILD_EXTRA_CFLAGS = "-DCONFIG_SND_HDA_RECONFIG=1 -Wno-unused-variable -Wno-unused-function"
|
||||
|
||||
KBUILD_EXTRA_CFLAGS = "-DAPPLE_PINSENSE_FIXUP -DAPPLE_CODECS -DCONFIG_SND_HDA_RECONFIG=1 -Wno-unused-variable -Wno-unused-function"
|
||||
|
||||
ifdef KVER
|
||||
KDIR := /lib/modules/$(KVER)
|
||||
|
@ -20,5 +19,5 @@ clean:
|
|||
|
||||
install:
|
||||
mkdir -p $(KDIR)/updates/
|
||||
cp snd-hda-codec-cirrus.ko $(KDIR)/updates/
|
||||
cp snd-hda-codec-cs8409.ko $(KDIR)/updates/
|
||||
depmod -a
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#ifndef __SOUND_HDA_AUTO_PARSER_H
|
||||
#define __SOUND_HDA_AUTO_PARSER_H
|
||||
|
||||
#include "hda_local.h"
|
||||
|
||||
/*
|
||||
* Helper for automatic pin configuration
|
||||
*/
|
||||
|
@ -35,6 +37,7 @@ struct auto_pin_cfg_item {
|
|||
unsigned int is_headset_mic:1;
|
||||
unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */
|
||||
unsigned int has_boost_on_pin:1;
|
||||
int order;
|
||||
};
|
||||
|
||||
struct auto_pin_cfg;
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#define __SOUND_HDA_GENERIC_H
|
||||
|
||||
#include <linux/leds.h>
|
||||
#include "hda_auto_parser.h"
|
||||
|
||||
struct hda_jack_callback;
|
||||
|
||||
/* table entry for multi-io paths */
|
||||
struct hda_multi_io {
|
||||
|
@ -183,7 +186,7 @@ struct hda_gen_spec {
|
|||
struct automic_entry am_entry[MAX_AUTO_MIC_PINS];
|
||||
|
||||
/* for pin sensing */
|
||||
/* current status; set in hda_geneic.c */
|
||||
/* current status; set in hda_generic.c */
|
||||
unsigned int hp_jack_present:1;
|
||||
unsigned int line_jack_present:1;
|
||||
unsigned int speaker_muted:1; /* current status of speaker mute */
|
||||
|
@ -229,7 +232,6 @@ struct hda_gen_spec {
|
|||
unsigned int power_down_unused:1; /* power down unused widgets */
|
||||
unsigned int dac_min_mute:1; /* minimal = mute for DACs */
|
||||
unsigned int suppress_vmaster:1; /* don't create vmaster kctls */
|
||||
unsigned int obey_preferred_dacs:1; /* obey preferred_dacs assignment */
|
||||
|
||||
/* other internal flags */
|
||||
unsigned int no_analog:1; /* digital I/O only */
|
||||
|
@ -294,6 +296,9 @@ struct hda_gen_spec {
|
|||
struct hda_jack_callback *cb);
|
||||
void (*mic_autoswitch_hook)(struct hda_codec *codec,
|
||||
struct hda_jack_callback *cb);
|
||||
|
||||
/* leds */
|
||||
struct led_classdev *led_cdevs[NUM_AUDIO_LEDS];
|
||||
};
|
||||
|
||||
/* values for add_stereo_mix_input flag */
|
||||
|
@ -324,7 +329,6 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
|
|||
struct auto_pin_cfg *cfg);
|
||||
int snd_hda_gen_build_controls(struct hda_codec *codec);
|
||||
int snd_hda_gen_build_pcms(struct hda_codec *codec);
|
||||
void snd_hda_gen_reboot_notify(struct hda_codec *codec);
|
||||
|
||||
/* standard jack event callbacks */
|
||||
void snd_hda_gen_hp_automute(struct hda_codec *codec,
|
||||
|
@ -335,9 +339,7 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
|
|||
struct hda_jack_callback *jack);
|
||||
void snd_hda_gen_update_outputs(struct hda_codec *codec);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid);
|
||||
#endif
|
||||
unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
|
||||
hda_nid_t nid,
|
||||
unsigned int power_state);
|
||||
|
@ -350,5 +352,6 @@ int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
|
|||
int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
|
||||
int (*callback)(struct led_classdev *,
|
||||
enum led_brightness));
|
||||
bool snd_hda_gen_shutup_speakers(struct hda_codec *codec);
|
||||
|
||||
#endif /* __SOUND_HDA_GENERIC_H */
|
||||
|
|
|
@ -69,6 +69,7 @@ struct hda_jack_tbl *
|
|||
snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec,
|
||||
unsigned char tag, int dev_id);
|
||||
|
||||
void snd_hda_jack_tbl_disconnect(struct hda_codec *codec);
|
||||
void snd_hda_jack_tbl_clear(struct hda_codec *codec);
|
||||
|
||||
void snd_hda_jack_set_dirty_all(struct hda_codec *codec);
|
||||
|
|
48
hda_local.h
48
hda_local.h
|
@ -135,8 +135,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
|
|||
#define snd_hda_add_vmaster(codec, name, tlv, followers, suffix, access) \
|
||||
__snd_hda_add_vmaster(codec, name, tlv, followers, suffix, true, access, NULL)
|
||||
int snd_hda_codec_reset(struct hda_codec *codec);
|
||||
void snd_hda_codec_register(struct hda_codec *codec);
|
||||
void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec);
|
||||
void snd_hda_codec_disconnect_pcms(struct hda_codec *codec);
|
||||
|
||||
#define snd_hda_regmap_sync(codec) snd_hdac_regmap_sync(&(codec)->core)
|
||||
|
||||
|
@ -293,6 +292,32 @@ struct hda_fixup {
|
|||
} v;
|
||||
};
|
||||
|
||||
/*
|
||||
* extended form of snd_pci_quirk:
|
||||
* for PCI SSID matching, use SND_PCI_QUIRK() like before;
|
||||
* for codec SSID matching, use the new HDA_CODEC_QUIRK() instead
|
||||
*/
|
||||
struct hda_quirk {
|
||||
unsigned short subvendor; /* PCI subvendor ID */
|
||||
unsigned short subdevice; /* PCI subdevice ID */
|
||||
unsigned short subdevice_mask; /* bitmask to match */
|
||||
bool match_codec_ssid; /* match only with codec SSID */
|
||||
int value; /* value */
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
const char *name; /* name of the device (optional) */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
#define HDA_CODEC_QUIRK(vend, dev, xname, val) \
|
||||
{ _SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname),\
|
||||
.match_codec_ssid = true }
|
||||
#else
|
||||
#define HDA_CODEC_QUIRK(vend, dev, xname, val) \
|
||||
{ _SND_PCI_QUIRK_ID(vend, dev), .value = (val), \
|
||||
.match_codec_ssid = true }
|
||||
#endif
|
||||
|
||||
struct snd_hda_pin_quirk {
|
||||
unsigned int codec; /* Codec vendor/device ID */
|
||||
unsigned short subvendor; /* PCI subvendor ID */
|
||||
|
@ -349,9 +374,10 @@ void snd_hda_apply_verbs(struct hda_codec *codec);
|
|||
void snd_hda_apply_pincfgs(struct hda_codec *codec,
|
||||
const struct hda_pintbl *cfg);
|
||||
void snd_hda_apply_fixup(struct hda_codec *codec, int action);
|
||||
void __snd_hda_apply_fixup(struct hda_codec *codec, int id, int action, int depth);
|
||||
void snd_hda_pick_fixup(struct hda_codec *codec,
|
||||
const struct hda_model_fixup *models,
|
||||
const struct snd_pci_quirk *quirk,
|
||||
const struct hda_quirk *quirk,
|
||||
const struct hda_fixup *fixlist);
|
||||
void snd_hda_pick_pin_fixup(struct hda_codec *codec,
|
||||
const struct snd_hda_pin_quirk *pin_quirk,
|
||||
|
@ -438,6 +464,15 @@ int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
|
|||
#define for_each_hda_codec_node(nid, codec) \
|
||||
for ((nid) = (codec)->core.start_nid; (nid) < (codec)->core.end_nid; (nid)++)
|
||||
|
||||
/* Set the codec power_state flag to indicate to allow unsol event handling;
|
||||
* see hda_codec_unsol_event() in hda_bind.c. Calling this might confuse the
|
||||
* state tracking, so use with care.
|
||||
*/
|
||||
static inline void snd_hda_codec_allow_unsol_events(struct hda_codec *codec)
|
||||
{
|
||||
codec->core.dev.power.power_state = PMSG_ON;
|
||||
}
|
||||
|
||||
/*
|
||||
* get widget capabilities
|
||||
*/
|
||||
|
@ -615,6 +650,8 @@ unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
|
|||
hda_nid_t nid,
|
||||
unsigned int power_state);
|
||||
|
||||
void snd_hda_codec_shutdown(struct hda_codec *codec);
|
||||
|
||||
/*
|
||||
* AMP control callbacks
|
||||
*/
|
||||
|
@ -701,7 +738,8 @@ int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid,
|
|||
|
||||
#ifdef CONFIG_SND_PROC_FS
|
||||
void snd_hdmi_print_eld_info(struct hdmi_eld *eld,
|
||||
struct snd_info_buffer *buffer);
|
||||
struct snd_info_buffer *buffer,
|
||||
hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid);
|
||||
void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
|
||||
struct snd_info_buffer *buffer);
|
||||
#endif
|
||||
|
@ -709,6 +747,8 @@ void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
|
|||
#define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
|
||||
void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen);
|
||||
|
||||
void snd_hda_codec_display_power(struct hda_codec *codec, bool enable);
|
||||
|
||||
/*
|
||||
*/
|
||||
#define codec_err(codec, fmt, args...) \
|
||||
|
|
3790
patch_cirrus.c
3790
patch_cirrus.c
File diff suppressed because it is too large
Load diff
3083
patch_cirrus_apple.h
Normal file
3083
patch_cirrus_apple.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1634,7 +1634,7 @@ static void setup_jack_pin_config(struct hda_codec *codec)
|
|||
{
|
||||
|
||||
//int retval;
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
|
||||
// this is likely some call of setPinConfigDefault
|
||||
// 0x45 -> 0x23 (macbook pro) is the line in path - so why does it say its a mike??
|
||||
|
@ -1753,7 +1753,7 @@ static void determine_speaker_id(struct hda_codec *codec)
|
|||
|
||||
// this is call AppleHDAFunctionGroup::setGPIOEnable in determineSpeakerID
|
||||
|
||||
if (codec->core.subsystem_id == 0x106b3900)
|
||||
if (codec->core.subsystem_id == 0x106b1000 || codec->core.subsystem_id == 0x106b0f00 || codec->core.subsystem_id == 0x106b0e00)
|
||||
{
|
||||
//snd_hda_codec_write(codec, codec->core.afg, 0, AC_VERB_SET_GPIO_MASK, 0x00000008); // 0x00171608
|
||||
// snd_hda: gpio enable 1 0x08
|
||||
|
@ -1771,13 +1771,13 @@ static void determine_speaker_id(struct hda_codec *codec)
|
|||
|
||||
retval = snd_hda_codec_read(codec, codec->core.afg, 0, AC_VERB_GET_GPIO_DATA, 0x00000000); // 0x001f1500
|
||||
|
||||
mycodec_info(codec, "command determine_speaker_id gpio data 0x%08x\n", retval);
|
||||
mycodec_info(codec, "command determine_speaker_id gpio mask 0x8 data 0x%08x\n", retval);
|
||||
|
||||
snd_hda_codec_write(codec, codec->core.afg, 0, AC_VERB_SET_GPIO_MASK, 0x0000000c); // 0x0017160c
|
||||
|
||||
retval = snd_hda_codec_read(codec, codec->core.afg, 0, AC_VERB_GET_GPIO_DATA, 0x00000000); // 0x001f1500
|
||||
|
||||
mycodec_info(codec, "command determine_speaker_id gpio data 0x%08x\n", retval);
|
||||
mycodec_info(codec, "command determine_speaker_id gpio mask 0xc data 0x%08x\n", retval);
|
||||
|
||||
}
|
||||
else
|
||||
|
@ -1792,7 +1792,7 @@ static void determine_speaker_id(struct hda_codec *codec)
|
|||
|
||||
retval = snd_hda_codec_read(codec, codec->core.afg, 0, AC_VERB_GET_GPIO_DATA, 0x00000000); // 0x001f1500
|
||||
|
||||
mycodec_info(codec, "command determine_speaker_id gpio data 0x%08x\n", retval);
|
||||
mycodec_info(codec, "command determine_speaker_id gpio mask 0x4 data 0x%08x\n", retval);
|
||||
|
||||
}
|
||||
|
||||
|
@ -2412,13 +2412,13 @@ static void cs42l83_mic_detect(struct hda_codec *codec)
|
|||
mycodec_info(codec, "command cs42l83_mic_detect end\n");
|
||||
}
|
||||
|
||||
static void cs42l83_tip_sense(struct hda_codec *codec)
|
||||
static void cs42l83_tip_sense(struct hda_codec *codec, int invert)
|
||||
{
|
||||
int retval;
|
||||
int newval1;
|
||||
int newval2;
|
||||
int newval;
|
||||
int flag = 0;
|
||||
//int invert = 0;
|
||||
|
||||
// likely in AppleHDAMikeyInternalCS8409::setupJackDetection
|
||||
// - only 0x73 readMikey/writeMikey calls seen
|
||||
|
@ -2431,15 +2431,20 @@ static void cs42l83_tip_sense(struct hda_codec *codec)
|
|||
|
||||
retval = cs_8409_vendor_i2cRead(codec, 0x90, 0x1b73, 1); // snd_hda
|
||||
|
||||
newval1 = (retval & 0x1c);
|
||||
// invert indicates inverted signal path for physical jack presence detect circuit
|
||||
|
||||
if (flag)
|
||||
// following code translated from assembler
|
||||
newval1 = (retval & 0x1c);
|
||||
if (invert)
|
||||
newval = (newval1 | 0xe0);
|
||||
else
|
||||
else
|
||||
newval = (newval1 | 0xc0);
|
||||
|
||||
|
||||
cs_8409_vendor_i2cWrite(codec, 0x90, 0x1b73, 0x00c0, 1); // snd_hda
|
||||
if (invert)
|
||||
cs_8409_vendor_i2cWrite(codec, 0x90, 0x1b73, 0x00e0, 1); // snd_hda
|
||||
else
|
||||
cs_8409_vendor_i2cWrite(codec, 0x90, 0x1b73, 0x00c0, 1); // snd_hda
|
||||
|
||||
mycodec_info(codec, "command cs42l83_tip_sense end\n");
|
||||
}
|
||||
|
|
|
@ -340,6 +340,8 @@ add_control(struct hda_gen_spec *spec, int type, const char *name,
|
|||
knew->index = cidx;
|
||||
if (get_amp_nid_(val))
|
||||
knew->subdevice = HDA_SUBDEV_AMP_FLAG;
|
||||
if (knew->access == 0)
|
||||
knew->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
|
||||
knew->private_value = val;
|
||||
return knew;
|
||||
}
|
||||
|
@ -350,7 +352,11 @@ static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
|
|||
const char *sfx, int cidx, unsigned long val)
|
||||
{
|
||||
char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
|
||||
snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
|
||||
int len;
|
||||
|
||||
len = snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
|
||||
if (snd_BUG_ON(len >= sizeof(name)))
|
||||
return -EINVAL;
|
||||
if (!add_control(spec, type, name, cidx, val))
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
|
|
|
@ -75,7 +75,7 @@ static unsigned int hda_set_node_power_state_dbg(struct hda_codec *codec, hda_ni
|
|||
}
|
||||
}
|
||||
else {
|
||||
dev_info(hda_codec_dev(codec), "hda_set_node_power_state ERROR!! 0x%04x\n",state);
|
||||
dev_info(hda_codec_dev(codec), "hda_set_node_power_state ERROR!! nid 0x%02x 0x%04x\n",nid, state);
|
||||
}
|
||||
if (dbgflg) mycodec_info(codec, "hda_set_node_power_state end power %d\n",state);
|
||||
|
||||
|
@ -118,15 +118,15 @@ static void hda_check_power_state(struct hda_codec *codec, hda_nid_t nid, int fl
|
|||
|
||||
static inline unsigned int cs_8409_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
unsigned int retval;
|
||||
snd_hda_codec_read(codec, spec->vendor_nid, 0,
|
||||
snd_hda_codec_read(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_GET_COEF_INDEX, 0);
|
||||
snd_hda_codec_write(codec, spec->vendor_nid, 0,
|
||||
snd_hda_codec_write(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_SET_COEF_INDEX, idx);
|
||||
retval = snd_hda_codec_read(codec, spec->vendor_nid, 0,
|
||||
retval = snd_hda_codec_read(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_GET_PROC_COEF, 0);
|
||||
snd_hda_codec_write(codec, spec->vendor_nid, 0,
|
||||
snd_hda_codec_write(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_SET_COEF_INDEX, 0);
|
||||
return retval;
|
||||
}
|
||||
|
@ -134,14 +134,14 @@ static inline unsigned int cs_8409_vendor_coef_get(struct hda_codec *codec, unsi
|
|||
static inline void cs_8409_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
|
||||
unsigned int coef)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
snd_hda_codec_read(codec, spec->vendor_nid, 0,
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
snd_hda_codec_read(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_GET_COEF_INDEX, 0);
|
||||
snd_hda_codec_write(codec, spec->vendor_nid, 0,
|
||||
snd_hda_codec_write(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_SET_COEF_INDEX, idx);
|
||||
snd_hda_codec_write(codec, spec->vendor_nid, 0,
|
||||
snd_hda_codec_write(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_SET_PROC_COEF, coef);
|
||||
snd_hda_codec_write(codec, spec->vendor_nid, 0,
|
||||
snd_hda_codec_write(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_SET_COEF_INDEX, 0);
|
||||
// appears to return 0
|
||||
}
|
||||
|
@ -150,16 +150,16 @@ static inline unsigned int cs_8409_vendor_coef_set_mask(struct hda_codec *codec,
|
|||
unsigned int coef, unsigned int mask, unsigned int srcval, int srcidx)
|
||||
{
|
||||
// for the moment hackily add srcidx argument while debugging
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
unsigned int retval;
|
||||
unsigned int mask_coef;
|
||||
snd_hda_codec_read(codec, spec->vendor_nid, 0,
|
||||
snd_hda_codec_read(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_GET_COEF_INDEX, 0);
|
||||
snd_hda_codec_write(codec, spec->vendor_nid, 0,
|
||||
snd_hda_codec_write(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_SET_COEF_INDEX, idx);
|
||||
retval = snd_hda_codec_read(codec, spec->vendor_nid, 0,
|
||||
retval = snd_hda_codec_read(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_GET_PROC_COEF, 0);
|
||||
snd_hda_codec_write(codec, spec->vendor_nid, 0,
|
||||
snd_hda_codec_write(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_SET_COEF_INDEX, idx);
|
||||
mask_coef = (retval & ~mask) | coef;
|
||||
if (srcval != 0)
|
||||
|
@ -172,9 +172,9 @@ static inline unsigned int cs_8409_vendor_coef_set_mask(struct hda_codec *codec,
|
|||
else
|
||||
//if (mask != 0xffff)
|
||||
myprintk_dbg("snd_hda_intel: cs_8409_vendor_coef_set_mask 0x%04x 0x%04x: 0x%04x (0x%04x 0x%04x 0x%04x) %d",idx,coef,mask_coef,retval,coef,mask,srcidx);
|
||||
snd_hda_codec_write(codec, spec->vendor_nid, 0,
|
||||
snd_hda_codec_write(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_SET_PROC_COEF, mask_coef);
|
||||
snd_hda_codec_write(codec, spec->vendor_nid, 0,
|
||||
snd_hda_codec_write(codec, CS8409_VENDOR_NID, 0,
|
||||
AC_VERB_SET_COEF_INDEX, 0);
|
||||
// appears to return 0
|
||||
// lets return the read value for checking
|
||||
|
@ -569,7 +569,7 @@ void snd_hda_double_reset(struct hda_codec *codec)
|
|||
|
||||
static void clear_pins(struct hda_codec *codec)
|
||||
{
|
||||
//struct cs_spec *spec = codec->spec;
|
||||
//struct cs8409_apple_spec *spec = codec->spec;
|
||||
hda_nid_t nid;
|
||||
|
||||
mycodec_info(codec, "start clear_pins\n");
|
||||
|
@ -585,7 +585,7 @@ static void clear_pins(struct hda_codec *codec)
|
|||
|
||||
static void read_coefs_all_loop(struct hda_codec *codec)
|
||||
{
|
||||
//struct cs_spec *spec = codec->spec;
|
||||
//struct cs8409_apple_spec *spec = codec->spec;
|
||||
int idx;
|
||||
mycodec_info(codec, "start read_coefs_all\n");
|
||||
for (idx = 0; idx < 130; idx++)
|
||||
|
@ -612,6 +612,9 @@ struct hda_cvt_setup {
|
|||
unsigned char dirty; /* setups should be cleared */
|
||||
};
|
||||
|
||||
// we now setup our local cache data in the spec structure
|
||||
// - cvt_setups is an opaque pointer type so we can see it here
|
||||
// but we dont know how to access the data - except by re-defining hda_cvt_setup as above
|
||||
|
||||
/* get or create a cache entry for the given audio converter NID */
|
||||
static struct hda_cvt_setup *
|
||||
|
@ -620,8 +623,7 @@ get_hda_cvt_setup_8409(struct hda_codec *codec, hda_nid_t nid)
|
|||
struct hda_cvt_setup *p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < codec->cvt_setups.used; i++) {
|
||||
p = snd_array_elem(&codec->cvt_setups, i);
|
||||
snd_array_for_each(&codec->cvt_setups, i, p) {
|
||||
if (p->nid == nid)
|
||||
return p;
|
||||
}
|
||||
|
@ -631,9 +633,41 @@ get_hda_cvt_setup_8409(struct hda_codec *codec, hda_nid_t nid)
|
|||
return p;
|
||||
}
|
||||
|
||||
|
||||
// so we actually need both versions - one using the hda_cvt_setup struct
|
||||
// and one using our local hda_cvt_setup_apple struct
|
||||
|
||||
static struct hda_cvt_setup_apple *
|
||||
get_hda_cvt_setup_apple_8409(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
|
||||
switch (nid)
|
||||
{
|
||||
case 0x02:
|
||||
return &spec->nid_0x02;
|
||||
case 0x03:
|
||||
return &spec->nid_0x03;
|
||||
case 0x0a:
|
||||
return &spec->nid_0x0a;
|
||||
case 0x22:
|
||||
return &spec->nid_0x22;
|
||||
case 0x23:
|
||||
return &spec->nid_0x23;
|
||||
case 0x1a:
|
||||
return &spec->nid_0x1a;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
codec_err(codec, "get_hda_cvt_setup_apple_8409: UNKNOWN NID!! 0x%02x\n", nid);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void cs_8409_dump_stream_format(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
struct hda_cvt_setup *p = NULL;
|
||||
struct hda_cvt_setup_apple *p = NULL;
|
||||
int i;
|
||||
|
||||
// use explicit search so we dont create one if doesnt exist
|
||||
|
@ -645,34 +679,45 @@ static void cs_8409_dump_stream_format(struct hda_codec *codec, hda_nid_t nid)
|
|||
}
|
||||
|
||||
if (p != NULL)
|
||||
codec_dbg(codec, "cs_8409_dump_stream_format: NID=0x%x, cached values: stream=0x%x, channel=%d, format=0x%x\n", nid, p->stream_tag, p->channel_id, p->format_id);
|
||||
mycodec_dbg(codec, "cs_8409_dump_stream_format: NID=0x%x, codec cached values: stream=0x%x, channel=%d, format=0x%x\n", nid, p->stream_tag, p->channel_id, p->format_id);
|
||||
else
|
||||
codec_dbg(codec, "cs_8409_dump_stream_format: NID=0x%x, cached values: NULL\n", nid);
|
||||
mycodec_dbg(codec, "cs_8409_dump_stream_format: NID=0x%x, codec cached values: NULL\n", nid);
|
||||
}
|
||||
|
||||
static void cs_8409_reset_stream_format(struct hda_codec *codec, hda_nid_t nid, int format, int doreset)
|
||||
{
|
||||
// note that this routine is currently not used
|
||||
|
||||
// this resets the cached stream format so that next
|
||||
// stream setup will actually rewrite the stream format and stream id
|
||||
// or if doreset set it will perform the stream update now
|
||||
// also allow for only updating the stream format and not stream id
|
||||
|
||||
// problem - the get_hda_cvt_setup function is local to hda_codec - so need our own copy above
|
||||
// NOTE we now save the stream format in our local cache as the hda_codec cache
|
||||
// is cleared at end of the prepare stage and we want to store it more permanently
|
||||
// really only the stream id is variable
|
||||
|
||||
struct hda_cvt_setup *p = NULL;
|
||||
struct hda_cvt_setup_apple *papl = NULL;
|
||||
u32 stream_tag_sv;
|
||||
int channel_id_sv;
|
||||
int format_id_sv;
|
||||
|
||||
p = get_hda_cvt_setup_8409(codec, nid);
|
||||
// problem - the get_hda_cvt_setup function is local to hda_codec - so need our own copy above
|
||||
|
||||
stream_tag_sv = p->stream_tag;
|
||||
channel_id_sv = p->channel_id;
|
||||
format_id_sv = p->format_id;
|
||||
papl = get_hda_cvt_setup_apple_8409(codec, nid);
|
||||
|
||||
stream_tag_sv = papl->stream_tag;
|
||||
channel_id_sv = papl->channel_id;
|
||||
format_id_sv = papl->format_id;
|
||||
|
||||
mycodec_info(codec, "cs_8409_reset_stream_format RESET for nid 0x%02x: 0x%08x id 0x%08x chan 0x%08x\n", nid, format_id_sv, stream_tag_sv, channel_id_sv);
|
||||
|
||||
// snd_hda_codec_setup_stream uses a caching system so only sends verbs when a change occurs
|
||||
// we want to force a send here so need to clear the cached data
|
||||
|
||||
p = get_hda_cvt_setup_8409(codec, nid);
|
||||
|
||||
p->stream_tag = 0;
|
||||
p->channel_id = 0;
|
||||
if (format)
|
||||
|
@ -683,11 +728,26 @@ static void cs_8409_reset_stream_format(struct hda_codec *codec, hda_nid_t nid,
|
|||
|
||||
}
|
||||
|
||||
// so what do I want this to do
|
||||
// the stream format will be stored in the hda_cvt_setup (at what stage is this valid??)
|
||||
// - we want to remove the Apple specific stream format/channel setup
|
||||
// and just call snd_hda_setup_stream - but we need the actual stream format for this
|
||||
// - hopefully getting from the hda_cvt_setup struct
|
||||
// so what do I want this to do
|
||||
// the stream format will be stored in the hda_cvt_setup (at what stage is this valid??)
|
||||
// - we want to remove the Apple specific stream format/channel setup
|
||||
// and just call snd_hda_setup_stream - but we need the actual stream format for this
|
||||
// - hopefully getting from the hda_cvt_setup struct
|
||||
// unfortunately this idea of storing in the hda_cvt_setup table turns out to be not useful
|
||||
// as at end of snd_hda_codec_prepare it clears out (ie zeros) all unused/inactive cache entries
|
||||
// so we have to store in a separate cache using our own copied definition for hda_cvt_setup
|
||||
// hda_cvt_setup_apple
|
||||
|
||||
|
||||
// the following 2 functions are used in the sync converter functions
|
||||
// where apple essentially disables streaming (set stream id to 0) updates some vendor nid parameters
|
||||
// then restores streaming
|
||||
// so we store the stream info in a local variable copy and set it to the unused stream id ie stream id of 0
|
||||
// then cs_8409_update_from_save_stream_format sets it back to what it was
|
||||
// note that the format is unchanged for these operations
|
||||
// the main reason for doing it this way is because of the caching used in snd_hda_codec_setup_stream
|
||||
// - if we just sent the hda verbs then the cached data in snd_hda_codec_setup_stream
|
||||
// would be inconsistent with the actual state of streaming on the nid
|
||||
|
||||
static void cs_8409_save_and_clear_stream_format(struct hda_codec *codec, hda_nid_t nid, struct hda_cvt_setup *savep)
|
||||
{
|
||||
|
@ -696,7 +756,7 @@ static void cs_8409_save_and_clear_stream_format(struct hda_codec *codec, hda_ni
|
|||
int channel_id_sv;
|
||||
int format_id_sv;
|
||||
|
||||
codec_dbg(codec, "cs_8409_save_and_clear_stream_format\n");
|
||||
mycodec_dbg(codec, "cs_8409_save_and_clear_stream_format nid 0x%02x\n", nid);
|
||||
|
||||
// use this to save the stream format and clear the stream id and channel
|
||||
|
||||
|
@ -713,7 +773,7 @@ static void cs_8409_update_from_save_stream_format(struct hda_codec *codec, hda_
|
|||
{
|
||||
struct hda_cvt_setup *p = NULL;
|
||||
|
||||
codec_dbg(codec, "cs_8409_update_from_save_stream_format\n");
|
||||
mycodec_dbg(codec, "cs_8409_update_from_save_stream_format nid 0x%02x\n", nid);
|
||||
|
||||
// so this will ensure the format is re-updated
|
||||
|
||||
|
@ -727,29 +787,52 @@ static void cs_8409_update_from_save_stream_format(struct hda_codec *codec, hda_
|
|||
if (update_format_id)
|
||||
p->format_id = 0;
|
||||
|
||||
mycodec_info(codec, "cs_8409_update_from_save_stream_format tag 0x%08x chnl 0x%08x fmt 0x%08x\n", savep->stream_tag, savep->channel_id, savep->format_id);
|
||||
|
||||
snd_hda_codec_setup_stream(codec, nid, savep->stream_tag, savep->channel_id, savep->format_id);
|
||||
}
|
||||
|
||||
|
||||
// so these are the crucial routines for setting our local cached copy of the stream info (in the spec structure)
|
||||
// we use a different struct definition (hda_cvt_setup_apple) to keep the re-definition of hda_cvt_setup more local
|
||||
// note that this stream info is only stored once per stream prepare function call
|
||||
// and this routine always updates from that initial data
|
||||
|
||||
static void cs_8409_really_update_stream_format(struct hda_codec *codec, hda_nid_t nid, int update_format_id, int update_stream_id, unsigned int new_channel_id)
|
||||
{
|
||||
struct hda_cvt_setup *p = NULL;
|
||||
u32 stream_tag_sv;
|
||||
int channel_id_sv;
|
||||
int format_id_sv;
|
||||
struct hda_cvt_setup_apple *papl = NULL;
|
||||
u32 stream_tag_sv = 0;
|
||||
int channel_id_sv = 0;
|
||||
int format_id_sv = 0;
|
||||
|
||||
codec_dbg(codec, "cs_8409_really_update_stream_format\n");
|
||||
mycodec_dbg(codec, "cs_8409_really_update_stream_format nid 0x%02x updfmt %d updstrmid %d nchnlid %d\n", nid, update_format_id, update_stream_id, new_channel_id);
|
||||
//dump_stack();
|
||||
|
||||
cs_8409_dump_stream_format(codec, nid);
|
||||
|
||||
// so here we take the cached format and save locally, clear out the cached values
|
||||
// so here we take our local cached format and save locally, clear out the cached values
|
||||
// then call snd_hda_codec_setup_stream with the cached values
|
||||
// this will ensure we update the HDA with the stream format
|
||||
|
||||
// maybe now we should just update from our local stored version??
|
||||
|
||||
papl = get_hda_cvt_setup_apple_8409(codec, nid);
|
||||
|
||||
if (papl != NULL)
|
||||
{
|
||||
stream_tag_sv = papl->stream_tag;
|
||||
channel_id_sv = papl->channel_id;
|
||||
format_id_sv = papl->format_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
codec_err(codec, "cs_8409_really_update_stream_format bad nid 0x%02x FAIL!!\n", nid);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
p = get_hda_cvt_setup_8409(codec, nid);
|
||||
|
||||
stream_tag_sv = p->stream_tag;
|
||||
channel_id_sv = p->channel_id;
|
||||
format_id_sv = p->format_id;
|
||||
mycodec_info(codec, "cs_8409_really_update_stream_format cached tag 0x%08x chnl 0x%08x fmt 0x%08x\n", papl->stream_tag, papl->channel_id, papl->format_id);
|
||||
|
||||
if (update_stream_id)
|
||||
{
|
||||
|
@ -759,17 +842,30 @@ static void cs_8409_really_update_stream_format(struct hda_codec *codec, hda_nid
|
|||
if (update_format_id)
|
||||
p->format_id = 0;
|
||||
|
||||
mycodec_info(codec, "cs_8409_really_update_stream_format to update tag 0x%08x chnl 0x%08x fmt 0x%08x\n", p->stream_tag, p->channel_id, p->format_id);
|
||||
|
||||
if (update_stream_id == 2)
|
||||
mycodec_info(codec, "cs_8409_really_update_stream_format new tag 0x%08x chnl 0x%08x fmt 0x%08x\n", stream_tag_sv, new_channel_id, format_id_sv);
|
||||
else
|
||||
mycodec_info(codec, "cs_8409_really_update_stream_format new tag 0x%08x chnl 0x%08x fmt 0x%08x\n", stream_tag_sv, channel_id_sv, format_id_sv);
|
||||
|
||||
cs_8409_dump_stream_format(codec, nid);
|
||||
|
||||
if (update_stream_id == 2)
|
||||
snd_hda_codec_setup_stream(codec, nid, stream_tag_sv, new_channel_id, format_id_sv);
|
||||
else
|
||||
snd_hda_codec_setup_stream(codec, nid, stream_tag_sv, channel_id_sv, format_id_sv);
|
||||
}
|
||||
|
||||
// remove function from compile so get error when building if use it
|
||||
#if 0
|
||||
static void cs_8409_setup_stream_format(struct hda_codec *codec, hda_nid_t nid, unsigned int stream_tag, unsigned int format)
|
||||
{
|
||||
struct hda_cvt_setup *p = NULL;
|
||||
|
||||
codec_dbg(codec, "cs_8409_setup_stream_format nid 0x%02x\n",nid);
|
||||
// NOTE - this function should no longer be used
|
||||
|
||||
mycodec_dbg(codec, "cs_8409_setup_stream_format nid 0x%02x\n",nid);
|
||||
|
||||
cs_8409_dump_stream_format(codec, nid);
|
||||
|
||||
|
@ -785,6 +881,40 @@ static void cs_8409_setup_stream_format(struct hda_codec *codec, hda_nid_t nid,
|
|||
p->channel_id = 0;
|
||||
p->format_id = format;
|
||||
|
||||
cs_8409_dump_stream_format(codec, nid);
|
||||
|
||||
mycodec_dbg(codec, "end cs_8409_setup_stream_format\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void cs_8409_store_stream_format(struct hda_codec *codec, hda_nid_t nid, unsigned int stream_tag, unsigned int format)
|
||||
{
|
||||
struct hda_cvt_setup_apple *papl = NULL;
|
||||
|
||||
mycodec_dbg(codec, "cs_8409_store_stream_format nid 0x%02x\n",nid);
|
||||
|
||||
cs_8409_dump_stream_format(codec, nid);
|
||||
|
||||
// this functions sets up our local cached stream save store
|
||||
// NOTA BENE we do not do the update here - we are relying that this will be done by a call to
|
||||
// cs_8409_really_update_stream_format now we have set the format correctly
|
||||
|
||||
papl = get_hda_cvt_setup_apple_8409(codec, nid);
|
||||
|
||||
if (papl != NULL)
|
||||
{
|
||||
// NOTA BENE - we do not set the channel id here - this will be done by cs_8409_really_update_stream_format
|
||||
|
||||
papl->stream_tag = stream_tag;
|
||||
papl->channel_id = 0;
|
||||
papl->format_id = format;
|
||||
|
||||
mycodec_info(codec, "cs_8409_store_stream_format cached tag 0x%08x chnl 0x%08x fmt 0x%08x\n", papl->stream_tag, papl->channel_id, papl->format_id);
|
||||
}
|
||||
else
|
||||
codec_err(codec, "cs_8409_store_stream_format bad nid 0x%02x FAIL!!\n", nid);
|
||||
|
||||
mycodec_dbg(codec, "end cs_8409_store_stream_format\n");
|
||||
}
|
||||
|
||||
|
||||
|
@ -800,40 +930,40 @@ static void switch_input_src(struct hda_codec *codec)
|
|||
struct hda_input_mux *imux = &spec->input_mux;
|
||||
struct nid_path *path;
|
||||
int i, c, nums;
|
||||
codec_dbg(codec, "switch_input_src enter\n");
|
||||
mycodec_dbg(codec, "switch_input_src enter\n");
|
||||
|
||||
nums = spec->num_adc_nids;
|
||||
|
||||
codec_dbg(codec, "switch_input_src num adc nids %d %d\n",nums,spec->dyn_adc_switch);
|
||||
mycodec_dbg(codec, "switch_input_src num adc nids %d %d\n",nums,spec->dyn_adc_switch);
|
||||
|
||||
for (c = 0; c < nums; c++) {
|
||||
codec_dbg(codec, "switch_input_src num_items %d\n",imux->num_items);
|
||||
mycodec_dbg(codec, "switch_input_src num_items %d\n",imux->num_items);
|
||||
for (i = 0; i < imux->num_items; i++) {
|
||||
//path = get_input_path(codec, c, i);
|
||||
path = snd_hda_get_path_from_idx(codec, spec->input_paths[i][c]);
|
||||
if (path) {
|
||||
int in;
|
||||
bool active = path->active;
|
||||
codec_dbg(codec, "switch_input_src path active %d\n",active);
|
||||
mycodec_dbg(codec, "switch_input_src path active %d\n",active);
|
||||
for (in = path->depth - 1; in >= 0; in--) {
|
||||
hda_nid_t tnid = path->path[in];
|
||||
codec_dbg(codec, "switch_input_src path nid %d: 0x%02x\n",in,tnid);
|
||||
mycodec_dbg(codec, "switch_input_src path nid %d: 0x%02x\n",in,tnid);
|
||||
}
|
||||
if (path->active) {
|
||||
codec_dbg(codec, "switch_input_src path nid 0x%02x deactivate\n",path->path[1]);
|
||||
mycodec_dbg(codec, "switch_input_src path nid 0x%02x deactivate\n",path->path[1]);
|
||||
snd_hda_activate_path(codec, path, false, false);
|
||||
} else {
|
||||
codec_dbg(codec, "switch_input_src path nid 0x%02x activate\n",path->path[1]);
|
||||
mycodec_dbg(codec, "switch_input_src path nid 0x%02x activate\n",path->path[1]);
|
||||
snd_hda_activate_path(codec, path, true, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
codec_dbg(codec, "switch_input_src path NULL\n");
|
||||
mycodec_dbg(codec, "switch_input_src path NULL\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codec_dbg(codec, "switch_input_src exit\n");
|
||||
mycodec_dbg(codec, "switch_input_src exit\n");
|
||||
}
|
||||
|
||||
|
||||
|
@ -929,6 +1059,8 @@ static void cs_8409_play_data_ssm3(struct hda_codec *codec)
|
|||
// 14,3 0x106b3900
|
||||
|
||||
// imac subsystem ids
|
||||
// 18,1 0x106b0e00
|
||||
// 18,2 0x106b0f00
|
||||
// 18,3 0x106b1000
|
||||
// 19,1 0x106b1000
|
||||
|
||||
|
@ -940,12 +1072,12 @@ static int cs_8409_real_config(struct hda_codec *codec);
|
|||
static int cs_8409_boot_setup(struct hda_codec *codec)
|
||||
{
|
||||
int err = 0;
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
|
||||
// so it appears we break up the subsystem_id into 2 parts
|
||||
// a codec vendor id (16 bits) and a subvendor id (8 bits) plus an assembly id
|
||||
// so here the codec vendor is 0x106b, the subvendor id is 0x39 and the assembly id is 0x00
|
||||
if (codec->core.subsystem_id == 0x106b3900 || codec->core.subsystem_id == 0x106b1000) {
|
||||
if (codec->core.subsystem_id == 0x106b3900) {
|
||||
if (spec->use_data) {
|
||||
myprintk("snd_hda_intel: cs_8409_boot_setup pre cs_8409_data_config\n");
|
||||
|
||||
|
@ -969,6 +1101,13 @@ static int cs_8409_boot_setup(struct hda_codec *codec)
|
|||
err = cs_8409_real_config(codec);
|
||||
}
|
||||
}
|
||||
else if (codec->core.subsystem_id == 0x106b1000 || codec->core.subsystem_id == 0x106b0f00 || codec->core.subsystem_id == 0x106b0e00) {
|
||||
if (spec->use_data) {
|
||||
printk("snd_hda_intel: cs_8409_boot_setup pre data not implemented for subsystem id 0x%08x",codec->core.subsystem_id);
|
||||
} else {
|
||||
err = cs_8409_real_config(codec);
|
||||
}
|
||||
}
|
||||
else {
|
||||
printk("snd_hda_intel: UNKNOWN subsystem id 0x%08x",codec->core.subsystem_id);
|
||||
err = -1;
|
||||
|
@ -979,8 +1118,9 @@ static int cs_8409_boot_setup(struct hda_codec *codec)
|
|||
|
||||
void cs_8409_play_setup(struct hda_codec *codec)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
if (codec->core.subsystem_id == 0x106b3900 || codec->core.subsystem_id == 0x106b1000) {
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
myprintk_dbg("snd_hda_intel: cs_8409_play_setup\n");
|
||||
if (codec->core.subsystem_id == 0x106b3900) {
|
||||
if (spec->use_data) {
|
||||
//cs_8409_unmute_data(codec);
|
||||
//cs_8409_volup_data(codec);
|
||||
|
@ -997,6 +1137,13 @@ void cs_8409_play_setup(struct hda_codec *codec)
|
|||
cs_8409_play_real(codec);
|
||||
}
|
||||
}
|
||||
else if (codec->core.subsystem_id == 0x106b1000 || codec->core.subsystem_id == 0x106b0f00 || codec->core.subsystem_id == 0x106b0e00) {
|
||||
if (spec->use_data) {
|
||||
printk("snd_hda_intel: cs_8409_play_setup data not implemented for subsystem id 0x%08x",codec->core.subsystem_id);
|
||||
} else {
|
||||
cs_8409_play_real(codec);
|
||||
}
|
||||
}
|
||||
else {
|
||||
printk("snd_hda_intel: UNKNOWN subsystem id 0x%08x",codec->core.subsystem_id);
|
||||
}
|
||||
|
@ -1007,24 +1154,32 @@ void cs_8409_play_setup(struct hda_codec *codec)
|
|||
|
||||
void cs_8409_play_cleanup(struct hda_codec *codec)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
if (codec->core.subsystem_id == 0x106b3900 || codec->core.subsystem_id == 0x106b1000) {
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
myprintk_dbg("snd_hda_intel: cs_8409_play_cleanup\n");
|
||||
if (codec->core.subsystem_id == 0x106b3900) {
|
||||
if (spec->use_data) {
|
||||
cs_8409_playstop_data(codec);
|
||||
cs_8409_playstop_data(codec);
|
||||
} else {
|
||||
cs_8409_playstop_real(codec);
|
||||
cs_8409_playstop_real(codec);
|
||||
}
|
||||
}
|
||||
else if (codec->core.subsystem_id == 0x106b3300 || codec->core.subsystem_id == 0x106b3600) {
|
||||
if (spec->use_data) {
|
||||
//cs_8409_playstop_data_ssm3(codec);
|
||||
//cs_8409_playstop_data_ssm3(codec);
|
||||
} else {
|
||||
//cs_8409_playstop_real_ssm3(codec);
|
||||
cs_8409_playstop_real(codec);
|
||||
//cs_8409_playstop_real_ssm3(codec);
|
||||
cs_8409_playstop_real(codec);
|
||||
}
|
||||
}
|
||||
else if (codec->core.subsystem_id == 0x106b1000 || codec->core.subsystem_id == 0x106b0f00 || codec->core.subsystem_id == 0x106b0e00) {
|
||||
if (spec->use_data) {
|
||||
printk("snd_hda_intel: cs_8409_play_cleanup data not implemented for subsystem id 0x%08x",codec->core.subsystem_id);
|
||||
} else {
|
||||
cs_8409_playstop_real(codec);
|
||||
}
|
||||
}
|
||||
else {
|
||||
printk("snd_hda_intel: UNKNOWN subsystem id 0x%08x",codec->core.subsystem_id);
|
||||
printk("snd_hda_intel: UNKNOWN subsystem id 0x%08x",codec->core.subsystem_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1035,9 +1190,9 @@ void cs_8409_play_cleanup(struct hda_codec *codec)
|
|||
|
||||
void cs_8409_capture_setup(struct hda_codec *codec)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
if (codec->core.subsystem_id == 0x106b3300 || codec->core.subsystem_id == 0x106b3600 || codec->core.subsystem_id == 0x106b3900
|
||||
|| codec->core.subsystem_id == 0x106b1000) {
|
||||
|| codec->core.subsystem_id == 0x106b1000 || codec->core.subsystem_id == 0x106b0f00 || codec->core.subsystem_id == 0x106b0e00) {
|
||||
if (spec->use_data) {
|
||||
//cs_8409_capture_data(codec);
|
||||
} else {
|
||||
|
@ -1053,9 +1208,9 @@ void cs_8409_capture_setup(struct hda_codec *codec)
|
|||
|
||||
void cs_8409_capture_cleanup(struct hda_codec *codec)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
if (codec->core.subsystem_id == 0x106b3300 || codec->core.subsystem_id == 0x106b3600 || codec->core.subsystem_id == 0x106b3900
|
||||
|| codec->core.subsystem_id == 0x106b1000) {
|
||||
|| codec->core.subsystem_id == 0x106b1000 || codec->core.subsystem_id == 0x106b0f00 || codec->core.subsystem_id == 0x106b0e00) {
|
||||
if (spec->use_data) {
|
||||
//cs_8409_capturestop_data(codec);
|
||||
} else {
|
||||
|
@ -1074,24 +1229,26 @@ static void cs_8409_cs42l83_unsolicited_response_finalize(struct hda_codec *code
|
|||
|
||||
static void cs_8409_perform_external_device_unsolicited_responses(struct hda_codec *codec)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
struct unsol_item *unsol_entry = NULL;
|
||||
struct unsol_item *unsol_temp = NULL;
|
||||
mycodec_info(codec, "cs_8409_perform_external_device_unsolicited_responses UNSOL start\n");
|
||||
list_for_each_entry_safe(unsol_entry, unsol_temp, &spec->unsol_list, list)
|
||||
{
|
||||
list_del_init(&unsol_entry->list);
|
||||
// pigs this gets complicated - these might issue other unsol responses
|
||||
cs_8409_cs42l83_unsolicited_response_finalize(codec, unsol_entry->res);
|
||||
spec->unsol_items_prealloc_used[unsol_entry->idx] = 0;
|
||||
memset(unsol_entry, 0, sizeof(struct unsol_item));
|
||||
if (!list_empty(&spec->unsol_list)) {
|
||||
codec_info(codec, "cs_8409_perform_external_device_unsolicited_responses UNSOL start\n");
|
||||
list_for_each_entry_safe(unsol_entry, unsol_temp, &spec->unsol_list, list)
|
||||
{
|
||||
list_del_init(&unsol_entry->list);
|
||||
// pigs this gets complicated - these might issue other unsol responses
|
||||
cs_8409_cs42l83_unsolicited_response_finalize(codec, unsol_entry->res);
|
||||
spec->unsol_items_prealloc_used[unsol_entry->idx] = 0;
|
||||
memset(unsol_entry, 0, sizeof(struct unsol_item));
|
||||
}
|
||||
codec_info(codec, "cs_8409_perform_external_device_unsolicited_responses UNSOL end\n");
|
||||
}
|
||||
mycodec_info(codec, "cs_8409_perform_external_device_unsolicited_responses UNSOL end\n");
|
||||
}
|
||||
|
||||
static void cs_8409_cs42l83_unsolicited_response(struct hda_codec *codec, unsigned int res)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
|
||||
// not clear if want to use the GPIO pins apparently passed in res to determine
|
||||
// if want to do interrupt checking here and if no interrupts then to do
|
||||
|
@ -1108,12 +1265,12 @@ static void cs_8409_cs42l83_unsolicited_response(struct hda_codec *codec, unsign
|
|||
{
|
||||
int itm;
|
||||
int new_itm = -1;
|
||||
mycodec_info(codec, "cs_8409_cs42l83_unsolicited_response - UNSOL BLOCKED\n");
|
||||
codec_info(codec, "cs_8409_cs42l83_unsolicited_response - UNSOL BLOCKED\n");
|
||||
for (itm=0; itm<10; itm++)
|
||||
if (spec->unsol_items_prealloc_used[itm] == 0) { new_itm = itm; break; }
|
||||
if (new_itm < 0)
|
||||
{
|
||||
mycodec_info(codec, "cs_8409_cs42l83_unsolicited_response - IGNORING UNSOL RESPONSE!!\n");
|
||||
codec_info(codec, "cs_8409_cs42l83_unsolicited_response - IGNORING UNSOL RESPONSE!!\n");
|
||||
return;
|
||||
}
|
||||
spec->unsol_items_prealloc_used[new_itm] = 1;
|
||||
|
@ -1121,11 +1278,11 @@ static void cs_8409_cs42l83_unsolicited_response(struct hda_codec *codec, unsign
|
|||
spec->unsol_items_prealloc[new_itm].res = res;
|
||||
spec->unsol_items_prealloc[new_itm].idx = new_itm;
|
||||
list_add_tail(&(spec->unsol_items_prealloc[new_itm].list), &spec->unsol_list);
|
||||
mycodec_info(codec, "cs_8409_cs42l83_unsolicited_response - UNSOL response stored\n");
|
||||
codec_info(codec, "cs_8409_cs42l83_unsolicited_response - UNSOL response stored\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
mycodec_info(codec, "cs_8409_cs42l83_unsolicited_response - NOT UNSOL BLOCKED\n");
|
||||
codec_info(codec, "cs_8409_cs42l83_unsolicited_response - NOT UNSOL BLOCKED\n");
|
||||
|
||||
// so it appears we need to block unsol responses while doing unsol responses
|
||||
// this is probably not the way to do this but still havent figured out how to use locking properly
|
||||
|
@ -1148,7 +1305,7 @@ static void cs_8409_cs42l83_unsolicited_response(struct hda_codec *codec, unsign
|
|||
|
||||
static void cs_8409_cs42l83_unsolicited_response_finalize(struct hda_codec *codec, unsigned int res)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
|
||||
if (spec->use_data)
|
||||
cs_8409_external_device_unsolicited_response_data(codec, res);
|
||||
|
@ -1170,7 +1327,7 @@ static void cs_8409_cs42l83_unsolicited_response_finalize(struct hda_codec *code
|
|||
|
||||
static void cs_8409_headset_mike_setup_nouse(struct hda_codec *codec)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
|
||||
cs_8409_intmike_linein_disable(codec);
|
||||
|
||||
|
@ -1181,8 +1338,8 @@ static void cs_8409_headset_mike_setup_nouse(struct hda_codec *codec)
|
|||
|
||||
void cs_8409_headplay_setup(struct hda_codec *codec)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
if (codec->core.subsystem_id == 0x106b3900 || codec->core.subsystem_id == 0x106b1000) {
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
if (codec->core.subsystem_id == 0x106b3900) {
|
||||
if (spec->use_data) {
|
||||
cs_8409_headplay_data(codec);
|
||||
} else {
|
||||
|
@ -1197,6 +1354,13 @@ void cs_8409_headplay_setup(struct hda_codec *codec)
|
|||
cs_8409_headplay_real(codec);
|
||||
}
|
||||
}
|
||||
else if (codec->core.subsystem_id == 0x106b1000 || codec->core.subsystem_id == 0x106b0f00 || codec->core.subsystem_id == 0x106b0e00) {
|
||||
if (spec->use_data) {
|
||||
printk("snd_hda_intel: cs_8409_headplay_setup data not implemented for subsystem id 0x%08x",codec->core.subsystem_id);
|
||||
} else {
|
||||
cs_8409_headplay_real(codec);
|
||||
}
|
||||
}
|
||||
else {
|
||||
printk("snd_hda_intel: UNKNOWN subsystem id 0x%08x",codec->core.subsystem_id);
|
||||
}
|
||||
|
@ -1206,7 +1370,7 @@ void cs_8409_headplay_setup(struct hda_codec *codec)
|
|||
|
||||
//if (!list_empty(&spec->unsol_list))
|
||||
//{
|
||||
// mycodec_info(codec, "cs_8409_headplay_setup - performing UNSOL responses\n");
|
||||
// codec_info(codec, "cs_8409_headplay_setup - performing UNSOL responses\n");
|
||||
// cs_8409_perform_external_device_unsolicited_responses(codec);
|
||||
//}
|
||||
}
|
||||
|
@ -1214,8 +1378,8 @@ void cs_8409_headplay_setup(struct hda_codec *codec)
|
|||
|
||||
void cs_8409_headplay_cleanup(struct hda_codec *codec)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
if (codec->core.subsystem_id == 0x106b3900 || codec->core.subsystem_id == 0x106b1000) {
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
if (codec->core.subsystem_id == 0x106b3900) {
|
||||
if (spec->use_data) {
|
||||
cs_8409_headplaystop_data(codec);
|
||||
} else {
|
||||
|
@ -1231,6 +1395,13 @@ void cs_8409_headplay_cleanup(struct hda_codec *codec)
|
|||
cs_8409_headplaystop_real(codec);
|
||||
}
|
||||
}
|
||||
else if (codec->core.subsystem_id == 0x106b1000 || codec->core.subsystem_id == 0x106b0f00 || codec->core.subsystem_id == 0x106b0e00) {
|
||||
if (spec->use_data) {
|
||||
printk("snd_hda_intel: cs_8409_headplay_cleanup data not implemented for subsystem id 0x%08x",codec->core.subsystem_id);
|
||||
} else {
|
||||
cs_8409_headplaystop_real(codec);
|
||||
}
|
||||
}
|
||||
else {
|
||||
printk("snd_hda_intel: UNKNOWN subsystem id 0x%08x",codec->core.subsystem_id);
|
||||
}
|
||||
|
@ -1240,7 +1411,7 @@ void cs_8409_headplay_cleanup(struct hda_codec *codec)
|
|||
|
||||
//if (!list_empty(&spec->unsol_list))
|
||||
//{
|
||||
// mycodec_info(codec, "cs_8409_headplay_cleanup - performing UNSOL responses\n");
|
||||
// codec_info(codec, "cs_8409_headplay_cleanup - performing UNSOL responses\n");
|
||||
// cs_8409_perform_external_device_unsolicited_responses(codec);
|
||||
//}
|
||||
}
|
||||
|
@ -1251,9 +1422,9 @@ void cs_8409_headplay_cleanup(struct hda_codec *codec)
|
|||
|
||||
void cs_8409_headcapture_setup(struct hda_codec *codec)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
if (codec->core.subsystem_id == 0x106b3300 || codec->core.subsystem_id == 0x106b3600 || codec->core.subsystem_id == 0x106b3900
|
||||
|| codec->core.subsystem_id == 0x106b1000) {
|
||||
|| codec->core.subsystem_id == 0x106b1000 || codec->core.subsystem_id == 0x106b0f00 || codec->core.subsystem_id == 0x106b0e00) {
|
||||
if (spec->use_data) {
|
||||
//cs_8409_headcapture_data(codec);
|
||||
} else {
|
||||
|
@ -1269,7 +1440,7 @@ void cs_8409_headcapture_setup(struct hda_codec *codec)
|
|||
|
||||
//if (!list_empty(&spec->unsol_list))
|
||||
//{
|
||||
// mycodec_info(codec, "cs_8409_headcapture_setup - performing UNSOL responses\n");
|
||||
// codec_info(codec, "cs_8409_headcapture_setup - performing UNSOL responses\n");
|
||||
// cs_8409_perform_external_device_unsolicited_responses(codec);
|
||||
//}
|
||||
}
|
||||
|
@ -1277,9 +1448,9 @@ void cs_8409_headcapture_setup(struct hda_codec *codec)
|
|||
|
||||
void cs_8409_headcapture_cleanup(struct hda_codec *codec)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
if (codec->core.subsystem_id == 0x106b3300 || codec->core.subsystem_id == 0x106b3600 || codec->core.subsystem_id == 0x106b3900
|
||||
|| codec->core.subsystem_id == 0x106b1000) {
|
||||
|| codec->core.subsystem_id == 0x106b1000 || codec->core.subsystem_id == 0x106b0f00 || codec->core.subsystem_id == 0x106b0e00) {
|
||||
if (spec->use_data) {
|
||||
//cs_8409_capturestop_data(codec);
|
||||
} else {
|
||||
|
@ -1296,7 +1467,7 @@ void cs_8409_headcapture_cleanup(struct hda_codec *codec)
|
|||
|
||||
//if (!list_empty(&spec->unsol_list))
|
||||
//{
|
||||
// mycodec_info(codec, "cs_8409_headcapturestop_cleanup - performing UNSOL responses\n");
|
||||
// codec_info(codec, "cs_8409_headcapturestop_cleanup - performing UNSOL responses\n");
|
||||
// cs_8409_perform_external_device_unsolicited_responses(codec);
|
||||
//}
|
||||
}
|
||||
|
@ -1306,15 +1477,19 @@ static void cs_8409_pcm_playback_pre_prepare_hook(struct hda_pcm_stream *hinfo,
|
|||
unsigned int stream_tag, unsigned int format, struct snd_pcm_substream *substream,
|
||||
int action)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
|
||||
if (action == HDA_GEN_PCM_ACT_PREPARE) {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
|
||||
struct timespec64 curtim;
|
||||
ktime_get_real_ts64(&curtim);
|
||||
myprintk("snd_hda_intel: command cs_8409_pcm_playback_pre_prepare_hook HOOK PREPARE init %d last %lld cur %lld",
|
||||
spec->play_init,spec->last_play_time.tv_sec,curtim.tv_sec);
|
||||
#else
|
||||
struct timespec curtim;
|
||||
getnstimeofday(&curtim);
|
||||
#endif
|
||||
myprintk("snd_hda_intel: command cs_8409_pcm_playback_pre_prepare_hook HOOK PREPARE init %d last %lld cur %lld",spec->play_init,spec->last_play_time.tv_sec,curtim.tv_sec);
|
||||
if (1) {
|
||||
struct hda_cvt_setup *p = NULL;
|
||||
struct hda_cvt_setup_apple *p = NULL;
|
||||
//int power_chk = 0;
|
||||
|
||||
// in the new way we set the stream up here using the passed data
|
||||
|
@ -1322,11 +1497,17 @@ static void cs_8409_pcm_playback_pre_prepare_hook(struct hda_pcm_stream *hinfo,
|
|||
// so the cs_8409_really_update_stream_format will cause the updates to occur
|
||||
// note we explicitly set the channel id - dont see another way yet
|
||||
|
||||
cs_8409_setup_stream_format(codec, 0x02, stream_tag, format);
|
||||
//cs_8409_setup_stream_format(codec, 0x02, stream_tag, format);
|
||||
cs_8409_store_stream_format(codec, 0x02, stream_tag, format);
|
||||
|
||||
cs_8409_setup_stream_format(codec, 0x03, stream_tag, format);
|
||||
//cs_8409_setup_stream_format(codec, 0x03, stream_tag, format);
|
||||
cs_8409_store_stream_format(codec, 0x03, stream_tag, format);
|
||||
|
||||
cs_8409_setup_stream_format(codec, 0x0a, stream_tag, format);
|
||||
//cs_8409_setup_stream_format(codec, 0x0a, stream_tag, format);
|
||||
cs_8409_store_stream_format(codec, 0x0a, stream_tag, format);
|
||||
|
||||
// save number of actual stream channels
|
||||
spec->stream_channels = substream->runtime->channels;
|
||||
|
||||
hda_check_power_state(codec, 0x1a, 1);
|
||||
hda_check_power_state(codec, 0x3c, 1);
|
||||
|
@ -1344,6 +1525,9 @@ static void cs_8409_pcm_playback_pre_prepare_hook(struct hda_pcm_stream *hinfo,
|
|||
// first on Linux and we dont know at that stage if we will be playing
|
||||
if (spec->have_mike)
|
||||
{
|
||||
// actually we always need to do cs_8409_headplay_setup - here we are about to play
|
||||
// - what this possibly would allow is the apple way of doing a pre-setup
|
||||
// so here we would switch between doing a full setup or a partial setup
|
||||
if (spec->headset_play_format_setup_needed)
|
||||
{
|
||||
cs_8409_headplay_setup(codec);
|
||||
|
@ -1361,9 +1545,10 @@ static void cs_8409_pcm_playback_pre_prepare_hook(struct hda_pcm_stream *hinfo,
|
|||
cs_8409_headplay_setup(codec);
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
cs_8409_play_setup(codec);
|
||||
myprintk("snd_hda_intel: command cs_8409_playback_pcm_hook setup play called");
|
||||
}
|
||||
myprintk("snd_hda_intel: command cs_8409_pcm_playback_pre_prepare_hook setup play called");
|
||||
|
||||
hda_check_power_state(codec, 0x1a, 2);
|
||||
hda_check_power_state(codec, 0x3c, 2);
|
||||
|
@ -1404,7 +1589,7 @@ static void cs_8409_pcm_playback_pre_prepare_hook(struct hda_pcm_stream *hinfo,
|
|||
static void cs_8409_playback_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream, int action)
|
||||
{
|
||||
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
|
||||
// so finally getting a handle on ordering here
|
||||
// we need to do the OSX setup in the OPEN section
|
||||
|
@ -1420,16 +1605,20 @@ static void cs_8409_playback_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_c
|
|||
|
||||
|
||||
if (action == HDA_GEN_PCM_ACT_OPEN) {
|
||||
//struct hda_cvt_setup *p = NULL;
|
||||
//struct hda_cvt_setup_apple *p = NULL;
|
||||
myprintk("snd_hda_intel: command cs_8409_playback_pcm_hook open");
|
||||
|
||||
myprintk("snd_hda_intel: command cs_8409_playback_pcm_hook open end");
|
||||
} else if (action == HDA_GEN_PCM_ACT_PREPARE) {
|
||||
// so this comes AFTER the stream format, frequency setup verbs are sent for the pcm stream
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
|
||||
struct timespec64 curtim;
|
||||
ktime_get_real_ts64(&curtim);
|
||||
myprintk("snd_hda_intel: command cs_8409_playback_pcm_hook HOOK PREPARE init %d last %lld cur %lld",
|
||||
spec->play_init,spec->last_play_time.tv_sec,curtim.tv_sec);
|
||||
#else
|
||||
struct timespec curtim;
|
||||
getnstimeofday(&curtim);
|
||||
#endif
|
||||
myprintk("snd_hda_intel: command cs_8409_playback_pcm_hook HOOK PREPARE init %d last %lld cur %lld",spec->play_init,spec->last_play_time.tv_sec,curtim.tv_sec);
|
||||
//int power_chk = 0;
|
||||
//power_chk = snd_hda_codec_read(codec, codec->core.afg, 0, AC_VERB_GET_POWER_STATE, 0);
|
||||
//myprintk("snd_hda_intel: command cs_8409_playback_pcm_hook power check 0x01 2 %d", power_chk);
|
||||
|
@ -1438,7 +1627,7 @@ static void cs_8409_playback_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_c
|
|||
spec->block_unsol = 0;
|
||||
if (!list_empty(&spec->unsol_list))
|
||||
{
|
||||
mycodec_info(codec, "cs_8409_playback_pcm_hook - performing UNSOL responses\n");
|
||||
codec_info(codec, "cs_8409_playback_pcm_hook - performing UNSOL responses\n");
|
||||
cs_8409_perform_external_device_unsolicited_responses(codec);
|
||||
}
|
||||
spec->playing = 1;
|
||||
|
@ -1457,11 +1646,8 @@ static void cs_8409_playback_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_c
|
|||
// note that so far only the headphone chip seems to generate unsol responses usually
|
||||
spec->block_unsol = 1;
|
||||
// so dont think need to anything about capturing here
|
||||
if (spec->headset_play_format_setup_needed == 0)
|
||||
{
|
||||
cs_8409_headplay_cleanup(codec);
|
||||
spec->headset_play_format_setup_needed = 1;
|
||||
}
|
||||
cs_8409_headplay_cleanup(codec);
|
||||
spec->headset_play_format_setup_needed = 1;
|
||||
}
|
||||
else
|
||||
cs_8409_play_cleanup(codec);
|
||||
|
@ -1469,7 +1655,7 @@ static void cs_8409_playback_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_c
|
|||
spec->block_unsol = 0;
|
||||
if (!list_empty(&spec->unsol_list))
|
||||
{
|
||||
mycodec_info(codec, "cs_8409_playback_pcm_hook - performing UNSOL responses\n");
|
||||
codec_info(codec, "cs_8409_playback_pcm_hook - performing UNSOL responses\n");
|
||||
cs_8409_perform_external_device_unsolicited_responses(codec);
|
||||
}
|
||||
// not sure of this position yet
|
||||
|
@ -1489,7 +1675,7 @@ static void cs_8409_pcm_capture_pre_prepare_hook(struct hda_pcm_stream *hinfo, s
|
|||
unsigned int stream_tag, unsigned int format, struct snd_pcm_substream *substream,
|
||||
int action)
|
||||
{
|
||||
struct cs_spec *spec = codec->spec;
|
||||
struct cs8409_apple_spec *spec = codec->spec;
|
||||
|
||||
if (action == HDA_GEN_PCM_ACT_PREPARE) {
|
||||
myprintk("snd_hda_intel: command cs_8409_pcm_capture_pre_prepare_hook HOOK PREPARE init %d",spec->capture_init);
|
||||
|
@ -1509,7 +1695,8 @@ static void cs_8409_pcm_capture_pre_prepare_hook(struct hda_pcm_stream *hinfo, s
|
|||
|
||||
|
||||
// I think this is the same for intmike or headset mike
|
||||
cs_8409_setup_stream_format(codec, hinfo->nid, stream_tag, format);
|
||||
//cs_8409_setup_stream_format(codec, hinfo->nid, stream_tag, format);
|
||||
cs_8409_store_stream_format(codec, hinfo->nid, stream_tag, format);
|
||||
|
||||
|
||||
// for the moment have junky test here
|
||||
|
@ -1549,13 +1736,46 @@ static void cs_8409_pcm_capture_pre_prepare_hook(struct hda_pcm_stream *hinfo, s
|
|||
static void cs_8409_capture_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream, int action)
|
||||
{
|
||||
|
||||
struct cs_spec *spec = codec->spec;
|
||||
//struct cs8409_apple_spec *spec = codec->spec;
|
||||
|
||||
struct cs8409_apple_spec *spec = NULL;
|
||||
|
||||
myprintk_dbg("snd_hda_intel: command cs_8409_capture_pcm_hook HOOK init called");
|
||||
|
||||
//dump_stack();
|
||||
|
||||
myprintk_dbg("snd_hda_intel: command cs_8409_capture_pcm_hook HOOK init post stack");
|
||||
|
||||
// - so this seems to be the critical issue - this can apparently be called with a NULL codec!!!
|
||||
// only thing to do seems to be to return!!
|
||||
if (codec == NULL) {
|
||||
struct hda_codec *badptr = NULL;
|
||||
printk("snd_hda_intel: command cs_8409_capture_pcm_hook HOOK init - CODEC NULL");
|
||||
// so if we are here it looks as tho we have been called from call_hp_automute
|
||||
// - in which the codec is the 1st arg
|
||||
badptr = (struct hda_codec *) hinfo;
|
||||
spec = badptr->spec;
|
||||
printk("snd_hda_intel: cs_8409_capture_pcm_hook - pcm_playback_hook %p", spec->gen.pcm_playback_hook);
|
||||
printk("snd_hda_intel: cs_8409_capture_pcm_hook - pcm_capture_hook %p", spec->gen.pcm_capture_hook);
|
||||
printk("snd_hda_intel: cs_8409_capture_pcm_hook - hp_automute_hook %p", spec->gen.hp_automute_hook);
|
||||
printk("snd_hda_intel: cs_8409_capture_pcm_hook - line_automute_hook %p", spec->gen.line_automute_hook);
|
||||
printk("snd_hda_intel: cs_8409_capture_pcm_hook - line_automute_hook %p", spec->gen.mic_autoswitch_hook);
|
||||
printk("snd_hda_intel: command cs_8409_capture_pcm_hook HOOK init - CODEC NULL exit");
|
||||
return;
|
||||
}
|
||||
else
|
||||
myprintk_dbg("snd_hda_intel: command cs_8409_capture_pcm_hook HOOK init - CODEC NOT NULL");
|
||||
|
||||
//dump_stack();
|
||||
|
||||
spec = codec->spec;
|
||||
|
||||
|
||||
// so now no setup is done here - we only check for unsolicited responses
|
||||
// - we do do cleanup for the CLEANUP action
|
||||
|
||||
if (action == HDA_GEN_PCM_ACT_OPEN) {
|
||||
//struct hda_cvt_setup *p = NULL;
|
||||
//struct hda_cvt_setup_apple *p = NULL;
|
||||
myprintk("snd_hda_intel: command cs_8409_capture_pcm_hook open");
|
||||
|
||||
myprintk("snd_hda_intel: command cs_8409_capture_pcm_hook open end");
|
||||
|
@ -1567,7 +1787,7 @@ static void cs_8409_capture_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_co
|
|||
spec->block_unsol = 0;
|
||||
if (!list_empty(&spec->unsol_list))
|
||||
{
|
||||
mycodec_info(codec, "cs_8409_capture_pcm_hook - performing UNSOL responses\n");
|
||||
codec_info(codec, "cs_8409_capture_pcm_hook - performing UNSOL responses\n");
|
||||
cs_8409_perform_external_device_unsolicited_responses(codec);
|
||||
}
|
||||
spec->capturing = 1;
|
||||
|
@ -1605,7 +1825,7 @@ static void cs_8409_capture_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_co
|
|||
spec->block_unsol = 0;
|
||||
if (!list_empty(&spec->unsol_list))
|
||||
{
|
||||
mycodec_info(codec, "cs_8409_capture_pcm_hook - performing UNSOL responses\n");
|
||||
codec_info(codec, "cs_8409_capture_pcm_hook - performing UNSOL responses\n");
|
||||
cs_8409_perform_external_device_unsolicited_responses(codec);
|
||||
}
|
||||
// not sure of this position yet
|
||||
|
@ -1624,7 +1844,7 @@ static void cs_8409_capture_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_co
|
|||
// this version runs all explicit commands as logged on OSX
|
||||
static int cs_8409_data_config(struct hda_codec *codec)
|
||||
{
|
||||
//struct cs_spec *spec = codec->spec;
|
||||
//struct cs8409_apple_spec *spec = codec->spec;
|
||||
//hda_nid_t beep_nid = spec->beep_nid;
|
||||
|
||||
unsigned int tmpstate1 = -1;
|
||||
|
@ -1656,7 +1876,7 @@ static int cs_8409_data_config(struct hda_codec *codec)
|
|||
// this version runs the setup using functions based on the setup using the logged data
|
||||
static int cs_8409_real_config(struct hda_codec *codec)
|
||||
{
|
||||
//struct cs_spec *spec = codec->spec;
|
||||
//struct cs8409_apple_spec *spec = codec->spec;
|
||||
//hda_nid_t beep_nid = spec->beep_nid;
|
||||
|
||||
unsigned int tmpstate1 = -1;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -546,6 +546,7 @@ static void cs42l83_power_hs_bias_off(struct hda_codec *codec)
|
|||
static void cs42l83_enable_hsbias_auto_clamp_on(struct hda_codec *codec)
|
||||
{
|
||||
|
||||
//int updval;
|
||||
//int retval;
|
||||
|
||||
mycodec_i2c_local_info(codec, "cs42l83_enable_hsbias_auto_clamp_on\n");
|
||||
|
@ -560,15 +561,22 @@ static void cs42l83_enable_hsbias_auto_clamp_on(struct hda_codec *codec)
|
|||
// snd_hda i2cPagedRead i2c address 0x90 i2c reg hi 0x1b lo 0x7000 i2c data 0x7003
|
||||
// snd_hda i2cPagedWrite i2c address 0x90 i2c reg hi 0x1b lo 0x7003 i2c data 0x0003
|
||||
|
||||
// explicit coding
|
||||
cs_8409_vendor_i2cRead(codec, 0x90, 0x1b70, 1); // snd_hda
|
||||
cs_8409_vendor_i2cWrite(codec, 0x90, 0x1b70, 0x0003, 1); // snd_hda
|
||||
|
||||
// bit coding
|
||||
//updval = cs_8409_vendor_i2cRead(codec, 0x90, 0x1b70, 1); // snd_hda
|
||||
//updval &= 0x3f;
|
||||
//cs_8409_vendor_i2cWrite(codec, 0x90, 0x1b70, updval, 1); // snd_hda
|
||||
|
||||
}
|
||||
|
||||
static void cs42l83_enable_hsbias_auto_clamp_off(struct hda_codec *codec)
|
||||
{
|
||||
|
||||
//int retval;
|
||||
int updval;
|
||||
int retval;
|
||||
|
||||
mycodec_i2c_local_info(codec, "cs42l83_enable_hsbias_auto_clamp_off\n");
|
||||
|
||||
|
@ -580,7 +588,45 @@ static void cs42l83_enable_hsbias_auto_clamp_off(struct hda_codec *codec)
|
|||
|
||||
// register 0x1b70 - HSBIAS Sense and Hi-Z Autocontrol
|
||||
// changed from 0x03 to 0x03 (HS Sense Bias trip 52 microamps
|
||||
// set to 0x46 (Tip Sense Enable (0x40) HS Sense Bias trip 93 microamps)
|
||||
// set to 0x46 (Tip Sense Enable (0x40) HS Sense Bias trip 93 microamps (0x03 -> 0x06) )
|
||||
|
||||
// snd_hda i2cPagedRead i2c address 0x90 i2c reg hi 0x1b lo 0x7000 i2c data 0x7003
|
||||
// snd_hda i2cPagedWrite i2c address 0x90 i2c reg hi 0x1b lo 0x7003 i2c data 0x0003
|
||||
// snd_hda i2cPagedWrite i2c address 0x90 i2c reg hi 0x1b lo 0x7046 i2c data 0x0046
|
||||
|
||||
// explicit coding
|
||||
//cs_8409_vendor_i2cRead(codec, 0x90, 0x1b70, 1); // snd_hda
|
||||
//cs_8409_vendor_i2cWrite(codec, 0x90, 0x1b70, 0x0003, 1); // snd_hda
|
||||
|
||||
//cs_8409_vendor_i2cWrite(codec, 0x90, 0x1b70, 0x0046, 1); // snd_hda
|
||||
|
||||
// bit coding
|
||||
retval = cs_8409_vendor_i2cRead(codec, 0x90, 0x1b70, 1); // snd_hda
|
||||
updval = retval & 0x3f;
|
||||
cs_8409_vendor_i2cWrite(codec, 0x90, 0x1b70, updval, 1); // snd_hda
|
||||
|
||||
updval = (retval & 0xb8) | 0x46;
|
||||
cs_8409_vendor_i2cWrite(codec, 0x90, 0x1b70, updval, 1); // snd_hda
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void cs42l83_enable_hsbias_auto_clamp_off0(struct hda_codec *codec)
|
||||
{
|
||||
|
||||
//int retval;
|
||||
|
||||
mycodec_i2c_local_info(codec, "cs42l83_enable_hsbias_auto_clamp_off0\n");
|
||||
|
||||
// in AppleHDAMikeyInternalCS4208::handleTypeDetectUR
|
||||
|
||||
// in AppleHDAMikeyInternalCS8409::setupButtonDetection
|
||||
|
||||
// AppleHDAMikeyInternalCS8409::enableHSBIASautoclamp
|
||||
|
||||
// register 0x1b70 - HSBIAS Sense and Hi-Z Autocontrol
|
||||
// changed from 0x03 to 0x03 (HS Sense Bias trip 52 microamps
|
||||
// set to 0x46 (Tip Sense Enable (0x40) HS Sense Bias trip 93 microamps (0x03 -> 0x06) )
|
||||
|
||||
// snd_hda i2cPagedRead i2c address 0x90 i2c reg hi 0x1b lo 0x7000 i2c data 0x7003
|
||||
// snd_hda i2cPagedWrite i2c address 0x90 i2c reg hi 0x1b lo 0x7003 i2c data 0x0003
|
||||
|
@ -702,7 +748,7 @@ static void cs42l83_enable_hsbias_auto_clamp_off1(struct hda_codec *codec)
|
|||
|
||||
// register 0x1b70 - HSBIAS Sense and Hi-Z Autocontrol
|
||||
// changed from 0x46 to 0x06
|
||||
// set to 0x46 (Tip Sense Enable (0x40) HS Sense Bias trip 93 microamps)
|
||||
// then set to 0x46 (Tip Sense Enable (0x40) HS Sense Bias trip 93 microamps (0x06 -> 0x06) )
|
||||
|
||||
// snd_hda i2cPagedRead i2c address 0x90 i2c reg hi 0x1b lo 0x7000 i2c data 0x7046
|
||||
// snd_hda i2cPagedWrite i2c address 0x90 i2c reg hi 0x1b lo 0x7006 i2c data 0x0006
|
||||
|
@ -904,6 +950,7 @@ static void cs42l83_configure_int_mclk(struct hda_codec *codec)
|
|||
|
||||
static void cs42l83_headset_power_on_on_nouse(struct hda_codec *codec)
|
||||
{
|
||||
// this function replaced by cs42l83_power_onoff
|
||||
|
||||
mycodec_i2c_local_info(codec, "cs42l83_headset_power_on_on_nouse\n");
|
||||
|
||||
|
@ -1131,6 +1178,8 @@ static void cs42l83_headset_rcv_enable_on(struct hda_codec *codec)
|
|||
{
|
||||
int retval;
|
||||
|
||||
// this function has been replaced by cs42l83_buffers_onoff
|
||||
|
||||
mycodec_i2c_local_info(codec, "cs42l83_headset_rcv_enable_on\n");
|
||||
|
||||
// AppleHDATDM_CS42L83::enable
|
||||
|
@ -1328,7 +1377,7 @@ static void cs42l83_enable_hsbias_auto_clamp_off3(struct hda_codec *codec)
|
|||
|
||||
// register 0x1b70 - HSBIAS Sense and Hi-Z Autocontrol
|
||||
// changed from 0xc6 to 0x06
|
||||
// set to 0x46 (Tip Sense Enable (0x40) HS Sense Bias trip 93 microamps)
|
||||
// then set to 0x46 (Tip Sense Enable (0x40) HS Sense Bias trip 93 microamps (0x06 ->0x06) )
|
||||
|
||||
// snd_hda i2cPagedRead i2c address 0x90 i2c reg hi 0x1b lo 0x7000 i2c data 0x70c6
|
||||
// snd_hda i2cPagedWrite i2c address 0x90 i2c reg hi 0x1b lo 0x7006 i2c data 0x0006
|
||||
|
@ -1538,6 +1587,7 @@ static void cs42l83_power_off_codec_input(struct hda_codec *codec)
|
|||
|
||||
static void cs42l83_headset_rcv_enable_off(struct hda_codec *codec)
|
||||
{
|
||||
// this function has been replaced by cs42l83_buffers_onoff
|
||||
|
||||
mycodec_i2c_local_info(codec, "cs42l83_headset_rcv_enable_off\n");
|
||||
|
||||
|
@ -1557,6 +1607,7 @@ static void cs42l83_headset_rcv_enable_off(struct hda_codec *codec)
|
|||
|
||||
static void cs42l83_headset_power_off(struct hda_codec *codec)
|
||||
{
|
||||
// this function replaced by cs42l83_power_onoff
|
||||
|
||||
mycodec_i2c_local_info(codec, "cs42l83_headset_power_off\n");
|
||||
|
||||
|
@ -1847,7 +1898,7 @@ static void cs42l83_enable_hsbias_auto_clamp_off2(struct hda_codec *codec)
|
|||
|
||||
// register 0x1b70 - HSBIAS Sense and Hi-Z Autocontrol
|
||||
// changed from 0x46 to 0x06
|
||||
// set to 0x46 (Tip Sense Enable (0x40) HS Sense Bias trip 93 microamps)
|
||||
// then set to 0x46 (Tip Sense Enable (0x40) HS Sense Bias trip 93 microamps (0x06 ->0x06) )
|
||||
|
||||
// snd_hda i2cPagedRead i2c address 0x90 i2c reg hi 0x1b lo 0x7000 i2c data 0x7046
|
||||
// snd_hda i2cPagedWrite i2c address 0x90 i2c reg hi 0x1b lo 0x7006 i2c data 0x0006
|
||||
|
@ -1860,25 +1911,31 @@ static void cs42l83_enable_hsbias_auto_clamp_off2(struct hda_codec *codec)
|
|||
|
||||
}
|
||||
|
||||
static void cs42l83_enable_hsbias_auto_clamp_on3(struct hda_codec *codec)
|
||||
static void cs42l83_hsbias_sense_on(struct hda_codec *codec)
|
||||
{
|
||||
|
||||
int updval;
|
||||
//int retval;
|
||||
|
||||
mycodec_i2c_local_info(codec, "cs42l83_enable_hsbias_auto_clamp_on3\n");
|
||||
mycodec_i2c_local_info(codec, "cs42l83_hsbias_sense_on\n");
|
||||
|
||||
// in AppleHDAMikeyInternalCS8409::setupButtonDetection
|
||||
|
||||
// AppleHDAMikeyInternalCS8409::enableHSBIASautoclamp
|
||||
// in AppleHDAMikeyInternalCS8409::handleButtonDetectUR
|
||||
|
||||
// register 0x1b70 - HSBIAS Sense and Hi-Z Autocontrol
|
||||
// changed from 0x46 to 0xc6
|
||||
// set to 0xc6 (HS Bias Sense Enable (0x80) Tip Sense Enable (0x40) HS Sense Bias trip 93 microamps (0x06 ->0x06) )
|
||||
|
||||
// snd_hda i2cPagedRead i2c address 0x90 i2c reg hi 0x1b lo 0x7000 i2c data 0x7046
|
||||
// snd_hda i2cPagedWrite i2c address 0x90 i2c reg hi 0x1b lo 0x70c6 i2c data 0x00c6
|
||||
|
||||
cs_8409_vendor_i2cRead(codec, 0x90, 0x1b70, 1); // snd_hda
|
||||
cs_8409_vendor_i2cWrite(codec, 0x90, 0x1b70, 0x00c6, 1); // snd_hda
|
||||
// explicit coding
|
||||
//cs_8409_vendor_i2cRead(codec, 0x90, 0x1b70, 1); // snd_hda
|
||||
//cs_8409_vendor_i2cWrite(codec, 0x90, 0x1b70, 0x00c6, 1); // snd_hda
|
||||
|
||||
// bit coding
|
||||
updval = cs_8409_vendor_i2cRead(codec, 0x90, 0x1b70, 1); // snd_hda
|
||||
updval |= 0x80;
|
||||
cs_8409_vendor_i2cWrite(codec, 0x90, 0x1b70, updval, 1); // snd_hda
|
||||
|
||||
}
|
||||
|
||||
|
|
623
patch_cs8409-tables.c
Normal file
623
patch_cs8409-tables.c
Normal file
|
@ -0,0 +1,623 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* patch_cs8409-tables.c -- HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
|
||||
*
|
||||
* Copyright (C) 2021 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*
|
||||
* Author: Lucas Tanure <tanureal@opensource.cirrus.com>
|
||||
*/
|
||||
|
||||
#include "patch_cs8409.h"
|
||||
|
||||
/******************************************************************************
|
||||
* CS42L42 Specific Data
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(cs42l42_dac_db_scale, CS42L42_HP_VOL_REAL_MIN * 100, 100, 1);
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(cs42l42_adc_db_scale, CS42L42_AMIC_VOL_REAL_MIN * 100, 100, 1);
|
||||
|
||||
const struct snd_kcontrol_new cs42l42_dac_volume_mixer = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.index = 0,
|
||||
.subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
|
||||
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
|
||||
.info = cs42l42_volume_info,
|
||||
.get = cs42l42_volume_get,
|
||||
.put = cs42l42_volume_put,
|
||||
.tlv = { .p = cs42l42_dac_db_scale },
|
||||
.private_value = HDA_COMPOSE_AMP_VAL_OFS(CS8409_PIN_ASP1_TRANSMITTER_A, 3, CS8409_CODEC0,
|
||||
HDA_OUTPUT, CS42L42_VOL_DAC) | HDA_AMP_VAL_MIN_MUTE
|
||||
};
|
||||
|
||||
const struct snd_kcontrol_new cs42l42_adc_volume_mixer = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.index = 0,
|
||||
.subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
|
||||
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
|
||||
.info = cs42l42_volume_info,
|
||||
.get = cs42l42_volume_get,
|
||||
.put = cs42l42_volume_put,
|
||||
.tlv = { .p = cs42l42_adc_db_scale },
|
||||
.private_value = HDA_COMPOSE_AMP_VAL_OFS(CS8409_PIN_ASP1_RECEIVER_A, 1, CS8409_CODEC0,
|
||||
HDA_INPUT, CS42L42_VOL_ADC) | HDA_AMP_VAL_MIN_MUTE
|
||||
};
|
||||
|
||||
const struct hda_pcm_stream cs42l42_48k_pcm_analog_playback = {
|
||||
.rates = SNDRV_PCM_RATE_48000, /* fixed rate */
|
||||
};
|
||||
|
||||
const struct hda_pcm_stream cs42l42_48k_pcm_analog_capture = {
|
||||
.rates = SNDRV_PCM_RATE_48000, /* fixed rate */
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* BULLSEYE / WARLOCK / CYBORG Specific Arrays
|
||||
* CS8409/CS42L42
|
||||
******************************************************************************/
|
||||
|
||||
const struct hda_verb cs8409_cs42l42_init_verbs[] = {
|
||||
{ CS8409_PIN_AFG, AC_VERB_SET_GPIO_WAKE_MASK, 0x0018 }, /* WAKE from GPIO 3,4 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_STATE, 0x0001 }, /* Enable VPW processing */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x0002 }, /* Configure GPIO 6,7 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF, 0x0080 }, /* I2C mode */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x005b }, /* Set I2C bus speed */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF, 0x0200 }, /* 100kHz I2C_STO = 2 */
|
||||
{} /* terminator */
|
||||
};
|
||||
|
||||
static const struct hda_pintbl cs8409_cs42l42_pincfgs[] = {
|
||||
{ CS8409_PIN_ASP1_TRANSMITTER_A, 0x042120f0 }, /* ASP-1-TX */
|
||||
{ CS8409_PIN_ASP1_RECEIVER_A, 0x04a12050 }, /* ASP-1-RX */
|
||||
{ CS8409_PIN_ASP2_TRANSMITTER_A, 0x901000f0 }, /* ASP-2-TX */
|
||||
{ CS8409_PIN_DMIC1_IN, 0x90a00090 }, /* DMIC-1 */
|
||||
{} /* terminator */
|
||||
};
|
||||
|
||||
static const struct hda_pintbl cs8409_cs42l42_pincfgs_no_dmic[] = {
|
||||
{ CS8409_PIN_ASP1_TRANSMITTER_A, 0x042120f0 }, /* ASP-1-TX */
|
||||
{ CS8409_PIN_ASP1_RECEIVER_A, 0x04a12050 }, /* ASP-1-RX */
|
||||
{ CS8409_PIN_ASP2_TRANSMITTER_A, 0x901000f0 }, /* ASP-2-TX */
|
||||
{} /* terminator */
|
||||
};
|
||||
|
||||
/* Vendor specific HW configuration for CS42L42 */
|
||||
static const struct cs8409_i2c_param cs42l42_init_reg_seq[] = {
|
||||
{ CS42L42_I2C_TIMEOUT, 0xB0 },
|
||||
{ CS42L42_ADC_CTL, 0x00 },
|
||||
{ 0x1D02, 0x06 },
|
||||
{ CS42L42_ADC_VOLUME, 0x9F },
|
||||
{ CS42L42_OSC_SWITCH, 0x01 },
|
||||
{ CS42L42_MCLK_CTL, 0x02 },
|
||||
{ CS42L42_SRC_CTL, 0x03 },
|
||||
{ CS42L42_MCLK_SRC_SEL, 0x00 },
|
||||
{ CS42L42_ASP_FRM_CFG, 0x13 },
|
||||
{ CS42L42_FSYNC_P_LOWER, 0xFF },
|
||||
{ CS42L42_FSYNC_P_UPPER, 0x00 },
|
||||
{ CS42L42_ASP_CLK_CFG, 0x20 },
|
||||
{ CS42L42_SPDIF_CLK_CFG, 0x0D },
|
||||
{ CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x02 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x00 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x02 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0x20 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH3_AP_RES, 0x02 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH3_BIT_MSB, 0x00 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH3_BIT_LSB, 0x80 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH4_AP_RES, 0x02 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH4_BIT_MSB, 0x00 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH4_BIT_LSB, 0xA0 },
|
||||
{ CS42L42_ASP_RX_DAI0_EN, 0x0C },
|
||||
{ CS42L42_ASP_TX_CH_EN, 0x01 },
|
||||
{ CS42L42_ASP_TX_CH_AP_RES, 0x02 },
|
||||
{ CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 },
|
||||
{ CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 },
|
||||
{ CS42L42_ASP_TX_SZ_EN, 0x01 },
|
||||
{ CS42L42_PWR_CTL1, 0x0A },
|
||||
{ CS42L42_PWR_CTL2, 0x84 },
|
||||
{ CS42L42_MIXER_CHA_VOL, 0x3F },
|
||||
{ CS42L42_MIXER_CHB_VOL, 0x3F },
|
||||
{ CS42L42_MIXER_ADC_VOL, 0x3f },
|
||||
{ CS42L42_HP_CTL, 0x0D },
|
||||
{ CS42L42_MIC_DET_CTL1, 0xB6 },
|
||||
{ CS42L42_TIPSENSE_CTL, 0xC2 },
|
||||
{ CS42L42_HS_CLAMP_DISABLE, 0x01 },
|
||||
{ CS42L42_HS_SWITCH_CTL, 0xF3 },
|
||||
{ CS42L42_PWR_CTL3, 0x20 },
|
||||
{ CS42L42_RSENSE_CTL2, 0x00 },
|
||||
{ CS42L42_RSENSE_CTL3, 0x00 },
|
||||
{ CS42L42_TSENSE_CTL, 0x80 },
|
||||
{ CS42L42_HS_BIAS_CTL, 0xC0 },
|
||||
{ CS42L42_PWR_CTL1, 0x02, 10000 },
|
||||
{ CS42L42_ADC_OVFL_INT_MASK, 0xff },
|
||||
{ CS42L42_MIXER_INT_MASK, 0xff },
|
||||
{ CS42L42_SRC_INT_MASK, 0xff },
|
||||
{ CS42L42_ASP_RX_INT_MASK, 0xff },
|
||||
{ CS42L42_ASP_TX_INT_MASK, 0xff },
|
||||
{ CS42L42_CODEC_INT_MASK, 0xff },
|
||||
{ CS42L42_SRCPL_INT_MASK, 0xff },
|
||||
{ CS42L42_VPMON_INT_MASK, 0xff },
|
||||
{ CS42L42_PLL_LOCK_INT_MASK, 0xff },
|
||||
{ CS42L42_TSRS_PLUG_INT_MASK, 0xff },
|
||||
{ CS42L42_DET_INT1_MASK, 0xff },
|
||||
{ CS42L42_DET_INT2_MASK, 0xff },
|
||||
};
|
||||
|
||||
/* Vendor specific hw configuration for CS8409 */
|
||||
const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[] = {
|
||||
/* +PLL1/2_EN, +I2C_EN */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0xb008 },
|
||||
/* ASP1/2_EN=0, ASP1_STP=1 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0002 },
|
||||
/* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG3, 0x0a80 },
|
||||
/* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL1, 0x0800 },
|
||||
/* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL2, 0x0820 },
|
||||
/* ASP2.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, ASP2_A_TX_CTRL1, 0x0800 },
|
||||
/* ASP2.A: TX.RAP=1, TX.RSZ=24 bits, TX.RCS=0 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, ASP2_A_TX_CTRL2, 0x2800 },
|
||||
/* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL1, 0x0800 },
|
||||
/* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL2, 0x0800 },
|
||||
/* ASP1: LCHI = 00h */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL1, 0x8000 },
|
||||
/* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL2, 0x28ff },
|
||||
/* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL3, 0x0062 },
|
||||
/* ASP2: LCHI=1Fh */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL1, 0x801f },
|
||||
/* ASP2: MC/SC_SRCSEL=PLL1, LCPR=3Fh */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL2, 0x283f },
|
||||
/* ASP2: 5050=1, MCEN=0, FSD=010, SCPOL_IN/OUT=1, SCDIV=1:16 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL3, 0x805c },
|
||||
/* DMIC1_MO=10b, DMIC1/2_SR=1 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DMIC_CFG, 0x0023 },
|
||||
/* ASP1/2_BEEP=0 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_BEEP_CFG, 0x0000 },
|
||||
/* ASP1/2_EN=1, ASP1_STP=1 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0062 },
|
||||
/* -PLL2_EN */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0x9008 },
|
||||
/* TX2.A: pre-scale att.=0 dB */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PRE_SCALE_ATTN2, 0x0000 },
|
||||
/* ASP1/2_xxx_EN=1, ASP1/2_MCLK_EN=0, DMIC1_SCL_EN=1 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PAD_CFG_SLW_RATE_CTRL, 0xfc03 },
|
||||
/* test mode on */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x9999 },
|
||||
/* GPIO hysteresis = 30 us */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, 0xc5, 0x0000 },
|
||||
/* test mode off */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x0000 },
|
||||
{} /* Terminator */
|
||||
};
|
||||
|
||||
const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[] = {
|
||||
/* EQ_SEL=1, EQ1/2_EN=0 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_CTRL1, 0x4000 },
|
||||
/* +EQ_ACC */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0x4000 },
|
||||
/* +EQ2_EN */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_CTRL1, 0x4010 },
|
||||
/* EQ_DATA_HI=0x0647 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x0647 },
|
||||
/* +EQ_WRT, +EQ_ACC, EQ_ADR=0, EQ_DATA_LO=0x67 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc0c7 },
|
||||
/* EQ_DATA_HI=0x0647 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x0647 },
|
||||
/* +EQ_WRT, +EQ_ACC, EQ_ADR=1, EQ_DATA_LO=0x67 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc1c7 },
|
||||
/* EQ_DATA_HI=0xf370 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xf370 },
|
||||
/* +EQ_WRT, +EQ_ACC, EQ_ADR=2, EQ_DATA_LO=0x71 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc271 },
|
||||
/* EQ_DATA_HI=0x1ef8 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1ef8 },
|
||||
/* +EQ_WRT, +EQ_ACC, EQ_ADR=3, EQ_DATA_LO=0x48 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc348 },
|
||||
/* EQ_DATA_HI=0xc110 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc110 },
|
||||
/* +EQ_WRT, +EQ_ACC, EQ_ADR=4, EQ_DATA_LO=0x5a */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc45a },
|
||||
/* EQ_DATA_HI=0x1f29 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1f29 },
|
||||
/* +EQ_WRT, +EQ_ACC, EQ_ADR=5, EQ_DATA_LO=0x74 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc574 },
|
||||
/* EQ_DATA_HI=0x1d7a */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1d7a },
|
||||
/* +EQ_WRT, +EQ_ACC, EQ_ADR=6, EQ_DATA_LO=0x53 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc653 },
|
||||
/* EQ_DATA_HI=0xc38c */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc38c },
|
||||
/* +EQ_WRT, +EQ_ACC, EQ_ADR=7, EQ_DATA_LO=0x14 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc714 },
|
||||
/* EQ_DATA_HI=0x1ca3 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1ca3 },
|
||||
/* +EQ_WRT, +EQ_ACC, EQ_ADR=8, EQ_DATA_LO=0xc7 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc8c7 },
|
||||
/* EQ_DATA_HI=0xc38c */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc38c },
|
||||
/* +EQ_WRT, +EQ_ACC, EQ_ADR=9, EQ_DATA_LO=0x14 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc914 },
|
||||
/* -EQ_ACC, -EQ_WRT */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0x0000 },
|
||||
{} /* Terminator */
|
||||
};
|
||||
|
||||
struct sub_codec cs8409_cs42l42_codec = {
|
||||
.addr = CS42L42_I2C_ADDR,
|
||||
.reset_gpio = CS8409_CS42L42_RESET,
|
||||
.irq_mask = CS8409_CS42L42_INT,
|
||||
.init_seq = cs42l42_init_reg_seq,
|
||||
.init_seq_num = ARRAY_SIZE(cs42l42_init_reg_seq),
|
||||
.hp_jack_in = 0,
|
||||
.mic_jack_in = 0,
|
||||
.paged = 1,
|
||||
.suspended = 1,
|
||||
.no_type_dect = 0,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Dolphin Specific Arrays
|
||||
* CS8409/ 2 X CS42L42
|
||||
******************************************************************************/
|
||||
|
||||
const struct hda_verb dolphin_init_verbs[] = {
|
||||
{ 0x01, AC_VERB_SET_GPIO_WAKE_MASK, DOLPHIN_WAKE }, /* WAKE from GPIO 0,4 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_STATE, 0x0001 }, /* Enable VPW processing */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x0002 }, /* Configure GPIO 6,7 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF, 0x0080 }, /* I2C mode */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x005b }, /* Set I2C bus speed */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF, 0x0200 }, /* 100kHz I2C_STO = 2 */
|
||||
{} /* terminator */
|
||||
};
|
||||
|
||||
static const struct hda_pintbl dolphin_pincfgs[] = {
|
||||
{ 0x24, 0x022210f0 }, /* ASP-1-TX-A */
|
||||
{ 0x25, 0x010240f0 }, /* ASP-1-TX-B */
|
||||
{ 0x34, 0x02a21050 }, /* ASP-1-RX */
|
||||
{} /* terminator */
|
||||
};
|
||||
|
||||
/* Vendor specific HW configuration for CS42L42 */
|
||||
static const struct cs8409_i2c_param dolphin_c0_init_reg_seq[] = {
|
||||
{ CS42L42_I2C_TIMEOUT, 0xB0 },
|
||||
{ CS42L42_ADC_CTL, 0x00 },
|
||||
{ 0x1D02, 0x06 },
|
||||
{ CS42L42_ADC_VOLUME, 0x9F },
|
||||
{ CS42L42_OSC_SWITCH, 0x01 },
|
||||
{ CS42L42_MCLK_CTL, 0x02 },
|
||||
{ CS42L42_SRC_CTL, 0x03 },
|
||||
{ CS42L42_MCLK_SRC_SEL, 0x00 },
|
||||
{ CS42L42_ASP_FRM_CFG, 0x13 },
|
||||
{ CS42L42_FSYNC_P_LOWER, 0xFF },
|
||||
{ CS42L42_FSYNC_P_UPPER, 0x00 },
|
||||
{ CS42L42_ASP_CLK_CFG, 0x20 },
|
||||
{ CS42L42_SPDIF_CLK_CFG, 0x0D },
|
||||
{ CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x02 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x00 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x02 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0x20 },
|
||||
{ CS42L42_ASP_RX_DAI0_EN, 0x0C },
|
||||
{ CS42L42_ASP_TX_CH_EN, 0x01 },
|
||||
{ CS42L42_ASP_TX_CH_AP_RES, 0x02 },
|
||||
{ CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 },
|
||||
{ CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 },
|
||||
{ CS42L42_ASP_TX_SZ_EN, 0x01 },
|
||||
{ CS42L42_PWR_CTL1, 0x0A },
|
||||
{ CS42L42_PWR_CTL2, 0x84 },
|
||||
{ CS42L42_HP_CTL, 0x0D },
|
||||
{ CS42L42_MIXER_CHA_VOL, 0x3F },
|
||||
{ CS42L42_MIXER_CHB_VOL, 0x3F },
|
||||
{ CS42L42_MIXER_ADC_VOL, 0x3f },
|
||||
{ CS42L42_MIC_DET_CTL1, 0xB6 },
|
||||
{ CS42L42_TIPSENSE_CTL, 0xC2 },
|
||||
{ CS42L42_HS_CLAMP_DISABLE, 0x01 },
|
||||
{ CS42L42_HS_SWITCH_CTL, 0xF3 },
|
||||
{ CS42L42_PWR_CTL3, 0x20 },
|
||||
{ CS42L42_RSENSE_CTL2, 0x00 },
|
||||
{ CS42L42_RSENSE_CTL3, 0x00 },
|
||||
{ CS42L42_TSENSE_CTL, 0x80 },
|
||||
{ CS42L42_HS_BIAS_CTL, 0xC0 },
|
||||
{ CS42L42_PWR_CTL1, 0x02, 10000 },
|
||||
{ CS42L42_ADC_OVFL_INT_MASK, 0xff },
|
||||
{ CS42L42_MIXER_INT_MASK, 0xff },
|
||||
{ CS42L42_SRC_INT_MASK, 0xff },
|
||||
{ CS42L42_ASP_RX_INT_MASK, 0xff },
|
||||
{ CS42L42_ASP_TX_INT_MASK, 0xff },
|
||||
{ CS42L42_CODEC_INT_MASK, 0xff },
|
||||
{ CS42L42_SRCPL_INT_MASK, 0xff },
|
||||
{ CS42L42_VPMON_INT_MASK, 0xff },
|
||||
{ CS42L42_PLL_LOCK_INT_MASK, 0xff },
|
||||
{ CS42L42_TSRS_PLUG_INT_MASK, 0xff },
|
||||
{ CS42L42_DET_INT1_MASK, 0xff },
|
||||
{ CS42L42_DET_INT2_MASK, 0xff }
|
||||
};
|
||||
|
||||
static const struct cs8409_i2c_param dolphin_c1_init_reg_seq[] = {
|
||||
{ CS42L42_I2C_TIMEOUT, 0xB0 },
|
||||
{ CS42L42_ADC_CTL, 0x00 },
|
||||
{ 0x1D02, 0x06 },
|
||||
{ CS42L42_ADC_VOLUME, 0x9F },
|
||||
{ CS42L42_OSC_SWITCH, 0x01 },
|
||||
{ CS42L42_MCLK_CTL, 0x02 },
|
||||
{ CS42L42_SRC_CTL, 0x03 },
|
||||
{ CS42L42_MCLK_SRC_SEL, 0x00 },
|
||||
{ CS42L42_ASP_FRM_CFG, 0x13 },
|
||||
{ CS42L42_FSYNC_P_LOWER, 0xFF },
|
||||
{ CS42L42_FSYNC_P_UPPER, 0x00 },
|
||||
{ CS42L42_ASP_CLK_CFG, 0x20 },
|
||||
{ CS42L42_SPDIF_CLK_CFG, 0x0D },
|
||||
{ CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x02 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x80 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x02 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 },
|
||||
{ CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0xA0 },
|
||||
{ CS42L42_ASP_RX_DAI0_EN, 0x0C },
|
||||
{ CS42L42_ASP_TX_CH_EN, 0x00 },
|
||||
{ CS42L42_ASP_TX_CH_AP_RES, 0x02 },
|
||||
{ CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 },
|
||||
{ CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 },
|
||||
{ CS42L42_ASP_TX_SZ_EN, 0x00 },
|
||||
{ CS42L42_PWR_CTL1, 0x0E },
|
||||
{ CS42L42_PWR_CTL2, 0x84 },
|
||||
{ CS42L42_HP_CTL, 0x0D },
|
||||
{ CS42L42_MIXER_CHA_VOL, 0x3F },
|
||||
{ CS42L42_MIXER_CHB_VOL, 0x3F },
|
||||
{ CS42L42_MIXER_ADC_VOL, 0x3f },
|
||||
{ CS42L42_MIC_DET_CTL1, 0xB6 },
|
||||
{ CS42L42_TIPSENSE_CTL, 0xC2 },
|
||||
{ CS42L42_HS_CLAMP_DISABLE, 0x01 },
|
||||
{ CS42L42_HS_SWITCH_CTL, 0xF3 },
|
||||
{ CS42L42_PWR_CTL3, 0x20 },
|
||||
{ CS42L42_RSENSE_CTL2, 0x00 },
|
||||
{ CS42L42_RSENSE_CTL3, 0x00 },
|
||||
{ CS42L42_TSENSE_CTL, 0x80 },
|
||||
{ CS42L42_HS_BIAS_CTL, 0xC0 },
|
||||
{ CS42L42_PWR_CTL1, 0x06, 10000 },
|
||||
{ CS42L42_ADC_OVFL_INT_MASK, 0xff },
|
||||
{ CS42L42_MIXER_INT_MASK, 0xff },
|
||||
{ CS42L42_SRC_INT_MASK, 0xff },
|
||||
{ CS42L42_ASP_RX_INT_MASK, 0xff },
|
||||
{ CS42L42_ASP_TX_INT_MASK, 0xff },
|
||||
{ CS42L42_CODEC_INT_MASK, 0xff },
|
||||
{ CS42L42_SRCPL_INT_MASK, 0xff },
|
||||
{ CS42L42_VPMON_INT_MASK, 0xff },
|
||||
{ CS42L42_PLL_LOCK_INT_MASK, 0xff },
|
||||
{ CS42L42_TSRS_PLUG_INT_MASK, 0xff },
|
||||
{ CS42L42_DET_INT1_MASK, 0xff },
|
||||
{ CS42L42_DET_INT2_MASK, 0xff }
|
||||
};
|
||||
|
||||
/* Vendor specific hw configuration for CS8409 */
|
||||
const struct cs8409_cir_param dolphin_hw_cfg[] = {
|
||||
/* +PLL1/2_EN, +I2C_EN */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0xb008 },
|
||||
/* ASP1_EN=0, ASP1_STP=1 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0002 },
|
||||
/* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG3, 0x0a80 },
|
||||
/* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL1, 0x0800 },
|
||||
/* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL2, 0x0820 },
|
||||
/* ASP1.B: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=128 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, ASP1_B_TX_CTRL1, 0x0880 },
|
||||
/* ASP1.B: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=160 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, ASP1_B_TX_CTRL2, 0x08a0 },
|
||||
/* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL1, 0x0800 },
|
||||
/* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL2, 0x0800 },
|
||||
/* ASP1: LCHI = 00h */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL1, 0x8000 },
|
||||
/* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL2, 0x28ff },
|
||||
/* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL3, 0x0062 },
|
||||
/* ASP1/2_BEEP=0 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_BEEP_CFG, 0x0000 },
|
||||
/* ASP1_EN=1, ASP1_STP=1 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0022 },
|
||||
/* -PLL2_EN */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0x9008 },
|
||||
/* ASP1_xxx_EN=1, ASP1_MCLK_EN=0 */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, CS8409_PAD_CFG_SLW_RATE_CTRL, 0x5400 },
|
||||
/* test mode on */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x9999 },
|
||||
/* GPIO hysteresis = 30 us */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, 0xc5, 0x0000 },
|
||||
/* test mode off */
|
||||
{ CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x0000 },
|
||||
{} /* Terminator */
|
||||
};
|
||||
|
||||
struct sub_codec dolphin_cs42l42_0 = {
|
||||
.addr = DOLPHIN_C0_I2C_ADDR,
|
||||
.reset_gpio = DOLPHIN_C0_RESET,
|
||||
.irq_mask = DOLPHIN_C0_INT,
|
||||
.init_seq = dolphin_c0_init_reg_seq,
|
||||
.init_seq_num = ARRAY_SIZE(dolphin_c0_init_reg_seq),
|
||||
.hp_jack_in = 0,
|
||||
.mic_jack_in = 0,
|
||||
.paged = 1,
|
||||
.suspended = 1,
|
||||
.no_type_dect = 0,
|
||||
};
|
||||
|
||||
struct sub_codec dolphin_cs42l42_1 = {
|
||||
.addr = DOLPHIN_C1_I2C_ADDR,
|
||||
.reset_gpio = DOLPHIN_C1_RESET,
|
||||
.irq_mask = DOLPHIN_C1_INT,
|
||||
.init_seq = dolphin_c1_init_reg_seq,
|
||||
.init_seq_num = ARRAY_SIZE(dolphin_c1_init_reg_seq),
|
||||
.hp_jack_in = 0,
|
||||
.mic_jack_in = 0,
|
||||
.paged = 1,
|
||||
.suspended = 1,
|
||||
.no_type_dect = 1,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* CS8409 Patch Driver Structs
|
||||
* Arrays Used for all projects using CS8409
|
||||
******************************************************************************/
|
||||
|
||||
const struct hda_quirk cs8409_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1028, 0x0A11, "Bullseye", CS8409_BULLSEYE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A12, "Bullseye", CS8409_BULLSEYE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A23, "Bullseye", CS8409_BULLSEYE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A24, "Bullseye", CS8409_BULLSEYE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A25, "Bullseye", CS8409_BULLSEYE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A29, "Bullseye", CS8409_BULLSEYE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A2A, "Bullseye", CS8409_BULLSEYE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A2B, "Bullseye", CS8409_BULLSEYE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A77, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A78, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A79, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A7A, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A7D, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A7E, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A7F, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0A80, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AB0, "Warlock", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AB2, "Warlock", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AB1, "Warlock", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AB3, "Warlock", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AB4, "Warlock", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AB5, "Warlock", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0ACF, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AD0, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AD1, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AD2, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AD3, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AD9, "Warlock", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0ADA, "Warlock", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0ADB, "Warlock", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0ADC, "Warlock", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0ADF, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AE0, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AE1, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AE2, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AE9, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AEA, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AEB, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AEC, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AED, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AEE, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AEF, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AF0, "Cyborg", CS8409_CYBORG),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AF4, "Warlock", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0AF5, "Warlock", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0B92, "Warlock MLK", CS8409_WARLOCK_MLK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0B93, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
|
||||
SND_PCI_QUIRK(0x1028, 0x0B94, "Warlock MLK", CS8409_WARLOCK_MLK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0B95, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
|
||||
SND_PCI_QUIRK(0x1028, 0x0B96, "Warlock MLK", CS8409_WARLOCK_MLK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0B97, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BA5, "Odin", CS8409_ODIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BA6, "Odin", CS8409_ODIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BA8, "Odin", CS8409_ODIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BAA, "Odin", CS8409_ODIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BAE, "Odin", CS8409_ODIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BB2, "Warlock MLK", CS8409_WARLOCK_MLK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BB3, "Warlock MLK", CS8409_WARLOCK_MLK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BB4, "Warlock MLK", CS8409_WARLOCK_MLK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BB5, "Warlock N3 15 TGL-U Nuvoton EC", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BB6, "Warlock V3 15 TGL-U Nuvoton EC", CS8409_WARLOCK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BB8, "Warlock MLK", CS8409_WARLOCK_MLK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BB9, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BBA, "Warlock MLK", CS8409_WARLOCK_MLK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BBB, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BBC, "Warlock MLK", CS8409_WARLOCK_MLK),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BBD, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BD4, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BD5, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BD6, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BD7, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0BD8, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0C43, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0C50, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0C51, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0C52, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0C73, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0C75, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0C7D, "Dolphin", CS8409_DOLPHIN),
|
||||
SND_PCI_QUIRK(0x1028, 0x0C7F, "Dolphin", CS8409_DOLPHIN),
|
||||
{} /* terminator */
|
||||
};
|
||||
|
||||
/* Dell Inspiron models with cs8409/cs42l42 */
|
||||
const struct hda_model_fixup cs8409_models[] = {
|
||||
{ .id = CS8409_BULLSEYE, .name = "bullseye" },
|
||||
{ .id = CS8409_WARLOCK, .name = "warlock" },
|
||||
{ .id = CS8409_WARLOCK_MLK, .name = "warlock mlk" },
|
||||
{ .id = CS8409_WARLOCK_MLK_DUAL_MIC, .name = "warlock mlk dual mic" },
|
||||
{ .id = CS8409_CYBORG, .name = "cyborg" },
|
||||
{ .id = CS8409_DOLPHIN, .name = "dolphin" },
|
||||
{ .id = CS8409_ODIN, .name = "odin" },
|
||||
{}
|
||||
};
|
||||
|
||||
const struct hda_fixup cs8409_fixups[] = {
|
||||
[CS8409_BULLSEYE] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = cs8409_cs42l42_pincfgs,
|
||||
.chained = true,
|
||||
.chain_id = CS8409_FIXUPS,
|
||||
},
|
||||
[CS8409_WARLOCK] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = cs8409_cs42l42_pincfgs,
|
||||
.chained = true,
|
||||
.chain_id = CS8409_FIXUPS,
|
||||
},
|
||||
[CS8409_WARLOCK_MLK] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = cs8409_cs42l42_pincfgs,
|
||||
.chained = true,
|
||||
.chain_id = CS8409_FIXUPS,
|
||||
},
|
||||
[CS8409_WARLOCK_MLK_DUAL_MIC] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = cs8409_cs42l42_pincfgs,
|
||||
.chained = true,
|
||||
.chain_id = CS8409_FIXUPS,
|
||||
},
|
||||
[CS8409_CYBORG] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = cs8409_cs42l42_pincfgs,
|
||||
.chained = true,
|
||||
.chain_id = CS8409_FIXUPS,
|
||||
},
|
||||
[CS8409_FIXUPS] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = cs8409_cs42l42_fixups,
|
||||
},
|
||||
[CS8409_DOLPHIN] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = dolphin_pincfgs,
|
||||
.chained = true,
|
||||
.chain_id = CS8409_DOLPHIN_FIXUPS,
|
||||
},
|
||||
[CS8409_DOLPHIN_FIXUPS] = {
|
||||
.type = HDA_FIXUP_FUNC,
|
||||
.v.func = dolphin_fixups,
|
||||
},
|
||||
[CS8409_ODIN] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = cs8409_cs42l42_pincfgs_no_dmic,
|
||||
.chained = true,
|
||||
.chain_id = CS8409_FIXUPS,
|
||||
},
|
||||
};
|
1503
patch_cs8409.c
Normal file
1503
patch_cs8409.c
Normal file
File diff suppressed because it is too large
Load diff
515
patch_cs8409.h
Normal file
515
patch_cs8409.h
Normal file
|
@ -0,0 +1,515 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
|
||||
*
|
||||
* Copyright (C) 2021 Cirrus Logic, Inc. and
|
||||
* Cirrus Logic International Semiconductor Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __CS8409_PATCH_H
|
||||
#define __CS8409_PATCH_H
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <sound/cs42l42.h>
|
||||
#include <sound/hda_codec.h>
|
||||
#include "hda_local.h"
|
||||
#include "hda_auto_parser.h"
|
||||
#include "hda_jack.h"
|
||||
#include "hda_generic.h"
|
||||
|
||||
/* CS8409 Specific Definitions */
|
||||
|
||||
enum cs8409_pins {
|
||||
CS8409_PIN_ROOT,
|
||||
CS8409_PIN_AFG,
|
||||
CS8409_PIN_ASP1_OUT_A,
|
||||
CS8409_PIN_ASP1_OUT_B,
|
||||
CS8409_PIN_ASP1_OUT_C,
|
||||
CS8409_PIN_ASP1_OUT_D,
|
||||
CS8409_PIN_ASP1_OUT_E,
|
||||
CS8409_PIN_ASP1_OUT_F,
|
||||
CS8409_PIN_ASP1_OUT_G,
|
||||
CS8409_PIN_ASP1_OUT_H,
|
||||
CS8409_PIN_ASP2_OUT_A,
|
||||
CS8409_PIN_ASP2_OUT_B,
|
||||
CS8409_PIN_ASP2_OUT_C,
|
||||
CS8409_PIN_ASP2_OUT_D,
|
||||
CS8409_PIN_ASP2_OUT_E,
|
||||
CS8409_PIN_ASP2_OUT_F,
|
||||
CS8409_PIN_ASP2_OUT_G,
|
||||
CS8409_PIN_ASP2_OUT_H,
|
||||
CS8409_PIN_ASP1_IN_A,
|
||||
CS8409_PIN_ASP1_IN_B,
|
||||
CS8409_PIN_ASP1_IN_C,
|
||||
CS8409_PIN_ASP1_IN_D,
|
||||
CS8409_PIN_ASP1_IN_E,
|
||||
CS8409_PIN_ASP1_IN_F,
|
||||
CS8409_PIN_ASP1_IN_G,
|
||||
CS8409_PIN_ASP1_IN_H,
|
||||
CS8409_PIN_ASP2_IN_A,
|
||||
CS8409_PIN_ASP2_IN_B,
|
||||
CS8409_PIN_ASP2_IN_C,
|
||||
CS8409_PIN_ASP2_IN_D,
|
||||
CS8409_PIN_ASP2_IN_E,
|
||||
CS8409_PIN_ASP2_IN_F,
|
||||
CS8409_PIN_ASP2_IN_G,
|
||||
CS8409_PIN_ASP2_IN_H,
|
||||
CS8409_PIN_DMIC1,
|
||||
CS8409_PIN_DMIC2,
|
||||
CS8409_PIN_ASP1_TRANSMITTER_A,
|
||||
CS8409_PIN_ASP1_TRANSMITTER_B,
|
||||
CS8409_PIN_ASP1_TRANSMITTER_C,
|
||||
CS8409_PIN_ASP1_TRANSMITTER_D,
|
||||
CS8409_PIN_ASP1_TRANSMITTER_E,
|
||||
CS8409_PIN_ASP1_TRANSMITTER_F,
|
||||
CS8409_PIN_ASP1_TRANSMITTER_G,
|
||||
CS8409_PIN_ASP1_TRANSMITTER_H,
|
||||
CS8409_PIN_ASP2_TRANSMITTER_A,
|
||||
CS8409_PIN_ASP2_TRANSMITTER_B,
|
||||
CS8409_PIN_ASP2_TRANSMITTER_C,
|
||||
CS8409_PIN_ASP2_TRANSMITTER_D,
|
||||
CS8409_PIN_ASP2_TRANSMITTER_E,
|
||||
CS8409_PIN_ASP2_TRANSMITTER_F,
|
||||
CS8409_PIN_ASP2_TRANSMITTER_G,
|
||||
CS8409_PIN_ASP2_TRANSMITTER_H,
|
||||
CS8409_PIN_ASP1_RECEIVER_A,
|
||||
CS8409_PIN_ASP1_RECEIVER_B,
|
||||
CS8409_PIN_ASP1_RECEIVER_C,
|
||||
CS8409_PIN_ASP1_RECEIVER_D,
|
||||
CS8409_PIN_ASP1_RECEIVER_E,
|
||||
CS8409_PIN_ASP1_RECEIVER_F,
|
||||
CS8409_PIN_ASP1_RECEIVER_G,
|
||||
CS8409_PIN_ASP1_RECEIVER_H,
|
||||
CS8409_PIN_ASP2_RECEIVER_A,
|
||||
CS8409_PIN_ASP2_RECEIVER_B,
|
||||
CS8409_PIN_ASP2_RECEIVER_C,
|
||||
CS8409_PIN_ASP2_RECEIVER_D,
|
||||
CS8409_PIN_ASP2_RECEIVER_E,
|
||||
CS8409_PIN_ASP2_RECEIVER_F,
|
||||
CS8409_PIN_ASP2_RECEIVER_G,
|
||||
CS8409_PIN_ASP2_RECEIVER_H,
|
||||
CS8409_PIN_DMIC1_IN,
|
||||
CS8409_PIN_DMIC2_IN,
|
||||
CS8409_PIN_BEEP_GEN,
|
||||
CS8409_PIN_VENDOR_WIDGET
|
||||
};
|
||||
|
||||
enum cs8409_coefficient_index_registers {
|
||||
CS8409_DEV_CFG1,
|
||||
CS8409_DEV_CFG2,
|
||||
CS8409_DEV_CFG3,
|
||||
CS8409_ASP1_CLK_CTRL1,
|
||||
CS8409_ASP1_CLK_CTRL2,
|
||||
CS8409_ASP1_CLK_CTRL3,
|
||||
CS8409_ASP2_CLK_CTRL1,
|
||||
CS8409_ASP2_CLK_CTRL2,
|
||||
CS8409_ASP2_CLK_CTRL3,
|
||||
CS8409_DMIC_CFG,
|
||||
CS8409_BEEP_CFG,
|
||||
ASP1_RX_NULL_INS_RMV,
|
||||
ASP1_Rx_RATE1,
|
||||
ASP1_Rx_RATE2,
|
||||
ASP1_Tx_NULL_INS_RMV,
|
||||
ASP1_Tx_RATE1,
|
||||
ASP1_Tx_RATE2,
|
||||
ASP2_Rx_NULL_INS_RMV,
|
||||
ASP2_Rx_RATE1,
|
||||
ASP2_Rx_RATE2,
|
||||
ASP2_Tx_NULL_INS_RMV,
|
||||
ASP2_Tx_RATE1,
|
||||
ASP2_Tx_RATE2,
|
||||
ASP1_SYNC_CTRL,
|
||||
ASP2_SYNC_CTRL,
|
||||
ASP1_A_TX_CTRL1,
|
||||
ASP1_A_TX_CTRL2,
|
||||
ASP1_B_TX_CTRL1,
|
||||
ASP1_B_TX_CTRL2,
|
||||
ASP1_C_TX_CTRL1,
|
||||
ASP1_C_TX_CTRL2,
|
||||
ASP1_D_TX_CTRL1,
|
||||
ASP1_D_TX_CTRL2,
|
||||
ASP1_E_TX_CTRL1,
|
||||
ASP1_E_TX_CTRL2,
|
||||
ASP1_F_TX_CTRL1,
|
||||
ASP1_F_TX_CTRL2,
|
||||
ASP1_G_TX_CTRL1,
|
||||
ASP1_G_TX_CTRL2,
|
||||
ASP1_H_TX_CTRL1,
|
||||
ASP1_H_TX_CTRL2,
|
||||
ASP2_A_TX_CTRL1,
|
||||
ASP2_A_TX_CTRL2,
|
||||
ASP2_B_TX_CTRL1,
|
||||
ASP2_B_TX_CTRL2,
|
||||
ASP2_C_TX_CTRL1,
|
||||
ASP2_C_TX_CTRL2,
|
||||
ASP2_D_TX_CTRL1,
|
||||
ASP2_D_TX_CTRL2,
|
||||
ASP2_E_TX_CTRL1,
|
||||
ASP2_E_TX_CTRL2,
|
||||
ASP2_F_TX_CTRL1,
|
||||
ASP2_F_TX_CTRL2,
|
||||
ASP2_G_TX_CTRL1,
|
||||
ASP2_G_TX_CTRL2,
|
||||
ASP2_H_TX_CTRL1,
|
||||
ASP2_H_TX_CTRL2,
|
||||
ASP1_A_RX_CTRL1,
|
||||
ASP1_A_RX_CTRL2,
|
||||
ASP1_B_RX_CTRL1,
|
||||
ASP1_B_RX_CTRL2,
|
||||
ASP1_C_RX_CTRL1,
|
||||
ASP1_C_RX_CTRL2,
|
||||
ASP1_D_RX_CTRL1,
|
||||
ASP1_D_RX_CTRL2,
|
||||
ASP1_E_RX_CTRL1,
|
||||
ASP1_E_RX_CTRL2,
|
||||
ASP1_F_RX_CTRL1,
|
||||
ASP1_F_RX_CTRL2,
|
||||
ASP1_G_RX_CTRL1,
|
||||
ASP1_G_RX_CTRL2,
|
||||
ASP1_H_RX_CTRL1,
|
||||
ASP1_H_RX_CTRL2,
|
||||
ASP2_A_RX_CTRL1,
|
||||
ASP2_A_RX_CTRL2,
|
||||
ASP2_B_RX_CTRL1,
|
||||
ASP2_B_RX_CTRL2,
|
||||
ASP2_C_RX_CTRL1,
|
||||
ASP2_C_RX_CTRL2,
|
||||
ASP2_D_RX_CTRL1,
|
||||
ASP2_D_RX_CTRL2,
|
||||
ASP2_E_RX_CTRL1,
|
||||
ASP2_E_RX_CTRL2,
|
||||
ASP2_F_RX_CTRL1,
|
||||
ASP2_F_RX_CTRL2,
|
||||
ASP2_G_RX_CTRL1,
|
||||
ASP2_G_RX_CTRL2,
|
||||
ASP2_H_RX_CTRL1,
|
||||
ASP2_H_RX_CTRL2,
|
||||
CS8409_I2C_ADDR,
|
||||
CS8409_I2C_DATA,
|
||||
CS8409_I2C_CTRL,
|
||||
CS8409_I2C_STS,
|
||||
CS8409_I2C_QWRITE,
|
||||
CS8409_I2C_QREAD,
|
||||
CS8409_SPI_CTRL,
|
||||
CS8409_SPI_TX_DATA,
|
||||
CS8409_SPI_RX_DATA,
|
||||
CS8409_SPI_STS,
|
||||
CS8409_PFE_COEF_W1, /* Parametric filter engine coefficient write 1*/
|
||||
CS8409_PFE_COEF_W2,
|
||||
CS8409_PFE_CTRL1,
|
||||
CS8409_PFE_CTRL2,
|
||||
CS8409_PRE_SCALE_ATTN1,
|
||||
CS8409_PRE_SCALE_ATTN2,
|
||||
CS8409_PFE_COEF_MON1, /* Parametric filter engine coefficient monitor 1*/
|
||||
CS8409_PFE_COEF_MON2,
|
||||
CS8409_ASP1_INTRN_STS,
|
||||
CS8409_ASP2_INTRN_STS,
|
||||
CS8409_ASP1_RX_SCLK_COUNT,
|
||||
CS8409_ASP1_TX_SCLK_COUNT,
|
||||
CS8409_ASP2_RX_SCLK_COUNT,
|
||||
CS8409_ASP2_TX_SCLK_COUNT,
|
||||
CS8409_ASP_UNS_RESP_MASK,
|
||||
CS8409_LOOPBACK_CTRL = 0x80,
|
||||
CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */
|
||||
};
|
||||
|
||||
/* CS42L42 Specific Definitions */
|
||||
|
||||
#define CS8409_MAX_CODECS 8
|
||||
#define CS42L42_VOLUMES (4U)
|
||||
#define CS42L42_HP_VOL_REAL_MIN (-63)
|
||||
#define CS42L42_HP_VOL_REAL_MAX (0)
|
||||
#define CS42L42_AMIC_VOL_REAL_MIN (-97)
|
||||
#define CS42L42_AMIC_VOL_REAL_MAX (12)
|
||||
#define CS42L42_REG_AMIC_VOL_MASK (0x00FF)
|
||||
#define CS42L42_HSTYPE_MASK (0x03)
|
||||
#define CS42L42_I2C_TIMEOUT_US (20000)
|
||||
#define CS42L42_I2C_SLEEP_US (2000)
|
||||
#define CS42L42_PDN_TIMEOUT_US (250000)
|
||||
#define CS42L42_PDN_SLEEP_US (2000)
|
||||
#define CS42L42_ANA_MUTE_AB (0x0C)
|
||||
#define CS42L42_FULL_SCALE_VOL_MASK (2)
|
||||
#define CS42L42_FULL_SCALE_VOL_0DB (0)
|
||||
#define CS42L42_FULL_SCALE_VOL_MINUS6DB (1)
|
||||
|
||||
/* Dell BULLSEYE / WARLOCK / CYBORG Specific Definitions */
|
||||
|
||||
#define CS42L42_I2C_ADDR (0x48 << 1)
|
||||
#define CS8409_CS42L42_RESET GENMASK(5, 5) /* CS8409_GPIO5 */
|
||||
#define CS8409_CS42L42_INT GENMASK(4, 4) /* CS8409_GPIO4 */
|
||||
#define CS8409_CYBORG_SPEAKER_PDN GENMASK(2, 2) /* CS8409_GPIO2 */
|
||||
#define CS8409_WARLOCK_SPEAKER_PDN GENMASK(1, 1) /* CS8409_GPIO1 */
|
||||
#define CS8409_CS42L42_HP_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_A
|
||||
#define CS8409_CS42L42_SPK_PIN_NID CS8409_PIN_ASP2_TRANSMITTER_A
|
||||
#define CS8409_CS42L42_AMIC_PIN_NID CS8409_PIN_ASP1_RECEIVER_A
|
||||
#define CS8409_CS42L42_DMIC_PIN_NID CS8409_PIN_DMIC1_IN
|
||||
#define CS8409_CS42L42_DMIC_ADC_PIN_NID CS8409_PIN_DMIC1
|
||||
|
||||
/* Dolphin */
|
||||
|
||||
#define DOLPHIN_C0_I2C_ADDR (0x48 << 1)
|
||||
#define DOLPHIN_C1_I2C_ADDR (0x49 << 1)
|
||||
#define DOLPHIN_HP_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_A
|
||||
#define DOLPHIN_LO_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_B
|
||||
#define DOLPHIN_AMIC_PIN_NID CS8409_PIN_ASP1_RECEIVER_A
|
||||
|
||||
#define DOLPHIN_C0_INT GENMASK(4, 4)
|
||||
#define DOLPHIN_C1_INT GENMASK(0, 0)
|
||||
#define DOLPHIN_C0_RESET GENMASK(5, 5)
|
||||
#define DOLPHIN_C1_RESET GENMASK(1, 1)
|
||||
#define DOLPHIN_WAKE (DOLPHIN_C0_INT | DOLPHIN_C1_INT)
|
||||
|
||||
enum {
|
||||
CS8409_BULLSEYE,
|
||||
CS8409_WARLOCK,
|
||||
CS8409_WARLOCK_MLK,
|
||||
CS8409_WARLOCK_MLK_DUAL_MIC,
|
||||
CS8409_CYBORG,
|
||||
CS8409_FIXUPS,
|
||||
CS8409_DOLPHIN,
|
||||
CS8409_DOLPHIN_FIXUPS,
|
||||
CS8409_ODIN,
|
||||
};
|
||||
|
||||
enum {
|
||||
CS8409_CODEC0,
|
||||
CS8409_CODEC1
|
||||
};
|
||||
|
||||
enum {
|
||||
CS42L42_VOL_ADC,
|
||||
CS42L42_VOL_DAC,
|
||||
};
|
||||
|
||||
#define CS42L42_ADC_VOL_OFFSET (CS42L42_VOL_ADC)
|
||||
#define CS42L42_DAC_CH0_VOL_OFFSET (CS42L42_VOL_DAC)
|
||||
#define CS42L42_DAC_CH1_VOL_OFFSET (CS42L42_VOL_DAC + 1)
|
||||
|
||||
struct cs8409_i2c_param {
|
||||
unsigned int addr;
|
||||
unsigned int value;
|
||||
unsigned int delay;
|
||||
};
|
||||
|
||||
struct cs8409_cir_param {
|
||||
unsigned int nid;
|
||||
unsigned int cir;
|
||||
unsigned int coeff;
|
||||
};
|
||||
|
||||
|
||||
#ifdef APPLE_CODECS
|
||||
struct unsol_item {
|
||||
struct list_head list;
|
||||
unsigned int idx;
|
||||
unsigned int res;
|
||||
};
|
||||
struct hda_cvt_setup_apple {
|
||||
hda_nid_t nid;
|
||||
u8 stream_tag;
|
||||
u8 channel_id;
|
||||
u16 format_id;
|
||||
unsigned char active; /* cvt is currently used */
|
||||
unsigned char dirty; /* setups should be cleared */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct sub_codec {
|
||||
struct hda_codec *codec;
|
||||
unsigned int addr;
|
||||
unsigned int reset_gpio;
|
||||
unsigned int irq_mask;
|
||||
const struct cs8409_i2c_param *init_seq;
|
||||
unsigned int init_seq_num;
|
||||
|
||||
unsigned int hp_jack_in:1;
|
||||
unsigned int mic_jack_in:1;
|
||||
#ifdef APPLE_CODECS
|
||||
unsigned int linein_jack_in:1;
|
||||
#endif
|
||||
unsigned int suspended:1;
|
||||
unsigned int paged:1;
|
||||
unsigned int last_page;
|
||||
unsigned int hsbias_hiz;
|
||||
unsigned int full_scale_vol:1;
|
||||
unsigned int no_type_dect:1;
|
||||
|
||||
s8 vol[CS42L42_VOLUMES];
|
||||
};
|
||||
|
||||
struct cs8409_spec {
|
||||
struct hda_gen_spec gen;
|
||||
struct hda_codec *codec;
|
||||
|
||||
struct sub_codec *scodecs[CS8409_MAX_CODECS];
|
||||
unsigned int num_scodecs;
|
||||
|
||||
unsigned int gpio_mask;
|
||||
unsigned int gpio_dir;
|
||||
unsigned int gpio_data;
|
||||
|
||||
int speaker_pdn_gpio;
|
||||
|
||||
struct mutex i2c_mux;
|
||||
unsigned int i2c_clck_enabled;
|
||||
unsigned int dev_addr;
|
||||
struct delayed_work i2c_clk_work;
|
||||
|
||||
unsigned int playback_started:1;
|
||||
unsigned int capture_started:1;
|
||||
unsigned int init_done:1;
|
||||
unsigned int build_ctrl_done:1;
|
||||
|
||||
#ifdef APPLE_CODECS
|
||||
|
||||
// additional data for Apple 8409 system
|
||||
|
||||
unsigned int spdif_detect:1;
|
||||
unsigned int spdif_present:1;
|
||||
unsigned int sense_b:1;
|
||||
hda_nid_t vendor_nid;
|
||||
|
||||
/* digital beep */
|
||||
hda_nid_t beep_nid;
|
||||
|
||||
/* for MBP SPDIF control */
|
||||
int (*spdif_sw_put)(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
// so it appears we have "concurrency" in the linux HDA code
|
||||
// in that if unsolicited responses occur which perform extensive verbs
|
||||
// the hda verbs are intermixed with eg extensive start playback verbs
|
||||
// on OSX we appear to have blocks of verbs during which unsolicited responses
|
||||
// are logged but the unsolicited verbs occur after the verb block
|
||||
// this flag is used to flag such verb blocks and the list will store the
|
||||
// responses
|
||||
// we use a pre-allocated list - if we have more than 10 outstanding unsols
|
||||
// we will drop
|
||||
// not clear if mutexes would be the way to go
|
||||
int block_unsol;
|
||||
struct list_head unsol_list;
|
||||
struct unsol_item unsol_items_prealloc[10];
|
||||
int unsol_items_prealloc_used[10];
|
||||
|
||||
// add in specific nids for the intmike and linein as they seem to swap
|
||||
// between macbook pros (14,3) and imacs (18,3)
|
||||
int intmike_nid;
|
||||
int linein_nid;
|
||||
int intmike_adc_nid;
|
||||
int linein_amp_nid;
|
||||
|
||||
// the following flag bits also need swapping
|
||||
int reg9_intmike_dmic_mo;
|
||||
int reg9_linein_dmic_mo;
|
||||
int reg82_intmike_dmic_scl;
|
||||
int reg82_linein_dmic_scl;
|
||||
|
||||
|
||||
// add explicit stream format store entries as per hda_codec using a local definition
|
||||
// of hda_cvt_setup (which is local to hda_codec.c)
|
||||
// also use explicit nid versions
|
||||
// (except that means either need explicit functions for each nid or have to lookup
|
||||
// nid each time want to use in a generic function with nid argument)
|
||||
struct hda_cvt_setup_apple nid_0x02;
|
||||
struct hda_cvt_setup_apple nid_0x03;
|
||||
struct hda_cvt_setup_apple nid_0x0a;
|
||||
struct hda_cvt_setup_apple nid_0x22;
|
||||
struct hda_cvt_setup_apple nid_0x23;
|
||||
struct hda_cvt_setup_apple nid_0x1a;
|
||||
|
||||
|
||||
// new item to deal with jack presence as Apple (and now Dell) seems to have barfed
|
||||
// the HDA spec by using a separate headphone chip
|
||||
int jack_present;
|
||||
|
||||
// save the type of headphone connected
|
||||
int headset_type;
|
||||
|
||||
// if headphone has mike or not
|
||||
int have_mike;
|
||||
|
||||
// if headphone has buttons or not
|
||||
int have_buttons;
|
||||
|
||||
// current stream channel count
|
||||
int stream_channels;
|
||||
|
||||
// set when playing for plug/unplug events while playing
|
||||
int playing;
|
||||
|
||||
// set when capturing for plug/unplug events while capturing
|
||||
int capturing;
|
||||
|
||||
// changing coding - OSX sets up the format on plugin
|
||||
// then does some minimal setup when start play
|
||||
// initial coding delayed any format setup till actually play
|
||||
// this works for no mike but not for mike - we need to initialize
|
||||
// the mike on plugin
|
||||
// this flag will be set when we have done the format setup
|
||||
// so know if need to do it on play or not
|
||||
// now need 2 flags - one for play and one for capture
|
||||
int headset_play_format_setup_needed;
|
||||
int headset_capture_format_setup_needed;
|
||||
|
||||
int headset_presetup_done;
|
||||
|
||||
|
||||
int use_data;
|
||||
|
||||
|
||||
// this is new item for dealing with headset plugins
|
||||
// so can distinguish which phase we are in if have multiple interrupts
|
||||
// not really used now have analyzed interrupts properly
|
||||
int headset_phase;
|
||||
|
||||
// another dirty hack item to manage the different headset enable codes
|
||||
int headset_enable;
|
||||
|
||||
int play_init;
|
||||
int capture_init;
|
||||
|
||||
|
||||
// new item to limit times we redo unmute/play
|
||||
struct timespec64 last_play_time;
|
||||
// record the first play time - we have a problem there
|
||||
// some initial plays that I dont understand - so skip any setup
|
||||
// till sometime after the first play
|
||||
struct timespec64 first_play_time;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* verb exec op override */
|
||||
int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
|
||||
unsigned int *res);
|
||||
};
|
||||
|
||||
extern const struct snd_kcontrol_new cs42l42_dac_volume_mixer;
|
||||
extern const struct snd_kcontrol_new cs42l42_adc_volume_mixer;
|
||||
|
||||
int cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo);
|
||||
int cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl);
|
||||
int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl);
|
||||
|
||||
extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_playback;
|
||||
extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_capture;
|
||||
extern const struct hda_quirk cs8409_fixup_tbl[];
|
||||
extern const struct hda_model_fixup cs8409_models[];
|
||||
extern const struct hda_fixup cs8409_fixups[];
|
||||
extern const struct hda_verb cs8409_cs42l42_init_verbs[];
|
||||
extern const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[];
|
||||
extern const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[];
|
||||
extern struct sub_codec cs8409_cs42l42_codec;
|
||||
|
||||
extern const struct hda_verb dolphin_init_verbs[];
|
||||
extern const struct cs8409_cir_param dolphin_hw_cfg[];
|
||||
extern struct sub_codec dolphin_cs42l42_0;
|
||||
extern struct sub_codec dolphin_cs42l42_1;
|
||||
|
||||
void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action);
|
||||
void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue