From ce63f3ba256a48023b425a4a6792f8da03d00948 Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Wed, 6 Jun 2012 13:49:44 +0800 Subject: ALSA: hda - add power states information in proc add more power states information: - reset status - clock stop ok - power states error Output like: Power: setting=D0, actual=D0, Error, Clock-stop-OK, Setting-reset Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.h | 3 +++ sound/pci/hda/hda_proc.c | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 4fc3960c8591..71864cddcb9d 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -323,6 +323,9 @@ enum { #define AC_PWRST_D1 0x01 #define AC_PWRST_D2 0x02 #define AC_PWRST_D3 0x03 +#define AC_PWRST_ERROR (1<<8) +#define AC_PWRST_CLK_STOP_OK (1<<9) +#define AC_PWRST_SETTING_RESET (1<<10) /* Processing capabilies */ #define AC_PCAP_BENIGN (1<<0) diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index e59e2f059b6e..fb9ef132f13b 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -455,10 +455,17 @@ static void print_power_state(struct snd_info_buffer *buffer, snd_iprintf(buffer, " Power states: %s\n", bits_names(sup, names, ARRAY_SIZE(names))); - snd_iprintf(buffer, " Power: setting=%s, actual=%s\n", + snd_iprintf(buffer, " Power: setting=%s, actual=%s", get_pwr_state(pwr & AC_PWRST_SETTING), get_pwr_state((pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT)); + if (pwr & AC_PWRST_ERROR) + snd_iprintf(buffer, ", Error"); + if (pwr & AC_PWRST_CLK_STOP_OK) + snd_iprintf(buffer, ", Clock-stop-OK"); + if (pwr & AC_PWRST_SETTING_RESET) + snd_iprintf(buffer, ", Setting-reset"); + snd_iprintf(buffer, "\n"); } static void print_unsol_cap(struct snd_info_buffer *buffer, -- cgit v1.2.3 From 167d2d55bfb4628169a57e3adbb1e5b097dca0f5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 6 Jun 2012 12:17:20 +0200 Subject: ALSA: hda - Show D3cold state in proc files Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_proc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index fb9ef132f13b..1dd9dbeeef6e 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -426,10 +426,10 @@ static void print_digital_conv(struct snd_info_buffer *buffer, static const char *get_pwr_state(u32 state) { - static const char * const buf[4] = { - "D0", "D1", "D2", "D3" + static const char * const buf[] = { + "D0", "D1", "D2", "D3", "D3cold" }; - if (state < 4) + if (state < ARRAY_SIZE(buf)) return buf[state]; return "UNKNOWN"; } -- cgit v1.2.3 From 0c7f46ad927cbd29965d4971730de713b478d270 Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Wed, 6 Jun 2012 22:02:48 +0800 Subject: ALSA: hda - check supported power states Add function to check whether power states supported by specific codec node. Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 41ca803a1fff..b89c8ecc819a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3504,6 +3504,22 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, } EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); +/* + * supported power states check + */ +static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg, + unsigned int power_state) +{ + int sup = snd_hda_param_read(codec, fg, AC_PAR_POWER_STATE); + + if (sup < 0) + return false; + if (sup & power_state) + return true; + else + return false; +} + /* * set power state of the codec */ -- cgit v1.2.3 From 0f4ccbb02533276ab750961e150aeee06492ed7c Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Thu, 7 Jun 2012 16:51:33 +0800 Subject: ALSA: hda - reduce msleep time if EPSS power states supported if EPSS supported, transition from D3 state to D0 state in less than 10ms Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b89c8ecc819a..fedbfae978af 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3532,8 +3532,11 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, } /* this delay seems necessary to avoid click noise at power-down */ - if (power_state == AC_PWRST_D3) - msleep(100); + if (power_state == AC_PWRST_D3) { + /* transition time less than 10ms for power down */ + bool epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS); + msleep(epss ? 10 : 100); + } snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, power_state); snd_hda_codec_set_power_to_all(codec, fg, power_state, true); -- cgit v1.2.3 From e076eb5c952c0f724980b44a77902a2ff93d098c Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Thu, 7 Jun 2012 16:52:07 +0800 Subject: ALSA: hda - check proper return value snd_hda_param_read() return value -1 means error, others are responses Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 1dd9dbeeef6e..7e46258fc700 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -451,7 +451,7 @@ static void print_power_state(struct snd_info_buffer *buffer, int sup = snd_hda_param_read(codec, nid, AC_PAR_POWER_STATE); int pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0); - if (sup) + if (sup != -1) snd_iprintf(buffer, " Power states: %s\n", bits_names(sup, names, ARRAY_SIZE(names))); -- cgit v1.2.3 From 09617ce4774ebf30a55b8451f4b35031f626f763 Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Fri, 8 Jun 2012 10:26:08 +0800 Subject: ALSA: hda - power setting error check codec may reject power state transition requests(reporting PS-ERROR set), in that case we re-issue a power state setting and check error bit again. Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index fedbfae978af..851e6ecfa011 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3526,6 +3526,9 @@ static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, unsigned int power_state) { + int count; + unsigned int state; + if (codec->patch_ops.set_power_state) { codec->patch_ops.set_power_state(codec, fg, power_state); return; @@ -3537,9 +3540,17 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, bool epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS); msleep(epss ? 10 : 100); } - snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, - power_state); - snd_hda_codec_set_power_to_all(codec, fg, power_state, true); + + /* repeat power states setting at most 10 times*/ + for (count = 0; count < 10; count++) { + snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, + power_state); + snd_hda_codec_set_power_to_all(codec, fg, power_state, true); + state = snd_hda_codec_read(codec, fg, 0, + AC_VERB_GET_POWER_STATE, 0); + if (!(state & AC_PWRST_ERROR)) + break; + } } #ifdef CONFIG_SND_HDA_HWDEP -- cgit v1.2.3 From 754fdff86f956a91834887ad56ea292f5d2fa114 Mon Sep 17 00:00:00 2001 From: Annie Liu Date: Fri, 8 Jun 2012 19:18:39 +0800 Subject: ALSA: hda - add support for HD-Audio of VIA HDMI GFX Cards This is patch supporting HD-Audio function of VIA GFX cards which support HDMI. Those are integrated graphics of chipsets VX900 and VX11 separately. Signed-off-by: Annie Liu Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 2b6392be451c..d49926e4d19f 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -3338,6 +3338,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* VIA VT8251/VT8237A */ { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, + /* VIA GFX VT7122/VX900 */ + { PCI_DEVICE(0x1106, 0x9170), .driver_data = AZX_DRIVER_GENERIC }, + /* VIA GFX VT6122/VX11 */ + { PCI_DEVICE(0x1106, 0x9140), .driver_data = AZX_DRIVER_GENERIC }, /* SIS966 */ { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS }, /* ULI M5461 */ -- cgit v1.2.3 From 3de5ff88773d9f106b668937da2f36c97801b332 Mon Sep 17 00:00:00 2001 From: Annie Liu Date: Fri, 8 Jun 2012 19:18:42 +0800 Subject: ALSA: hda - add support for HD-Audio CODECes of VIA HDMI GFX Cards This is patch supporting the CODECes of HD-Audio function of VIA GFX cards which support HDMI. For CODECes 0x9f80/0x9f81, which belong to VX900, since the hardware is not fully compliant to HD-Audio 1.3, simple_i*() is adopted temporarily. Signed-off-by: Annie Liu Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index ad319d4dc32f..696681826b01 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1863,6 +1863,62 @@ static int patch_atihdmi(struct hda_codec *codec) return 0; } +/* VIA HDMI Implementation */ +#define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ +#define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ + +static struct hda_verb viahdmi_basic_init[] = { + /* enable digital output on pin widget */ + { VIAHDMI_PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + {} /* terminator */ +}; + +static int via_hdmi_init(struct hda_codec *codec) +{ + snd_hda_sequence_write(codec, viahdmi_basic_init); + return 0; +} + +static const struct hda_codec_ops via_hdmi_patch_ops = { + .build_controls = simple_playback_build_controls, + .build_pcms = simple_playback_build_pcms, + .init = via_hdmi_init, + .free = simple_playback_free, +}; + +static struct hda_pcm_stream via_hdmi_digital_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + .nid = VIAHDMI_CVT_NID, /* NID to query formats and rates*/ + .ops = { + .open = simple_playback_pcm_open, + .close = simple_playback_pcm_close, + .prepare = simple_playback_pcm_prepare + }, +}; + +static int patch_via_hdmi(struct hda_codec *codec) +{ + struct hdmi_spec *spec; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + spec->multiout.num_dacs = 0; /* no analog */ + spec->multiout.max_channels = 2; + spec->multiout.dig_out_nid = VIAHDMI_CVT_NID; /* pure-digital case */ + spec->num_cvts = 1; + spec->cvts[0].cvt_nid = VIAHDMI_CVT_NID; + spec->pins[0].pin_nid = VIAHDMI_PIN_NID; + spec->pcm_playback = &via_hdmi_digital_playback; + + codec->spec = spec; + codec->patch_ops = via_hdmi_patch_ops; + + return 0; +} /* * patch entries @@ -1904,6 +1960,10 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, +{ .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, +{ .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, +{ .id = 0x11069f84, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, +{ .id = 0x11069f85, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, @@ -1950,6 +2010,10 @@ MODULE_ALIAS("snd-hda-codec-id:10de0043"); MODULE_ALIAS("snd-hda-codec-id:10de0044"); MODULE_ALIAS("snd-hda-codec-id:10de0067"); MODULE_ALIAS("snd-hda-codec-id:10de8001"); +MODULE_ALIAS("snd-hda-codec-id:11069f80"); +MODULE_ALIAS("snd-hda-codec-id:11069f81"); +MODULE_ALIAS("snd-hda-codec-id:11069f84"); +MODULE_ALIAS("snd-hda-codec-id:11069f85"); MODULE_ALIAS("snd-hda-codec-id:17e80047"); MODULE_ALIAS("snd-hda-codec-id:80860054"); MODULE_ALIAS("snd-hda-codec-id:80862801"); -- cgit v1.2.3 From 0875eb755b66a6766be117133dbb6d8157ace337 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 18 May 2012 15:01:36 -0300 Subject: [media] snd_tea575x: Report correct frequency range for EU/US versus JA models My EU/US 5757 cannot tune below approx 86 Mhz, that is below that it does not even generate the standard not tuned to anything radio noise anymore, so clearly the 5757 cannot tune to the Japanese frequencies. This patch assumes that likewise the 5759 cannot tune to the EU/US frequencies. Signed-off-by: Hans de Goede CC: Ondrej Zary Signed-off-by: Mauro Carvalho Chehab --- sound/i2c/other/tea575x-tuner.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index 582aace20ea3..aa9900dff6e9 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c @@ -37,8 +37,8 @@ MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); MODULE_LICENSE("GPL"); -#define FREQ_LO (76U * 16000) -#define FREQ_HI (108U * 16000) +#define FREQ_LO ((tea->tea5759 ? 760 : 875) * 1600U) +#define FREQ_HI ((tea->tea5759 ? 910 : 1080) * 1600U) /* * definitions -- cgit v1.2.3 From 5daf53a6eb5c54c618c9def388d81c2769fd11a0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 19 May 2012 07:57:03 -0300 Subject: [media] snd_tea575x: Make the module using snd_tea575x the fops owner Before this patch the owner field of the /dev/radio# device fops was set to the snd-tea575x-tuner module itself. Meaning that the module which was using it could be rmmod-ed while the device is open, and then BAD things happen. I know, as I found out the hard way :) Note that there is no need to also somehow increase the refcount of the snd-tea575x-tuner module itself, since any drivers using it will have symbolic references to it. Signed-off-by: Hans de Goede CC: Ondrej Zary Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-maxiradio.c | 2 +- drivers/media/radio/radio-sf16fmr2.c | 2 +- include/sound/tea575x-tuner.h | 3 ++- sound/i2c/other/tea575x-tuner.c | 7 ++++--- sound/pci/es1968.c | 2 +- sound/pci/fm801.c | 4 ++-- 6 files changed, 11 insertions(+), 9 deletions(-) (limited to 'sound') diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 740a3d5520c7..b415211d0c4b 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -157,7 +157,7 @@ static int __devinit maxiradio_probe(struct pci_dev *pdev, const struct pci_devi goto err_out_free_region; dev->io = pci_resource_start(pdev, 0); - if (snd_tea575x_init(&dev->tea)) { + if (snd_tea575x_init(&dev->tea, THIS_MODULE)) { printk(KERN_ERR "radio-maxiradio: Unable to detect TEA575x tuner\n"); goto err_out_free_region; } diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 52b8011f1b23..4efcbec74c52 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -238,7 +238,7 @@ static int __devinit fmr2_probe(struct fmr2 *fmr2, struct device *pdev, int io) snprintf(fmr2->tea.bus_info, sizeof(fmr2->tea.bus_info), "%s:%s", fmr2->is_fmd2 ? "PnP" : "ISA", dev_name(pdev)); - if (snd_tea575x_init(&fmr2->tea)) { + if (snd_tea575x_init(&fmr2->tea, THIS_MODULE)) { printk(KERN_ERR "radio-sf16fmr2: Unable to detect TEA575x tuner\n"); release_region(fmr2->io, 2); return -ENODEV; diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h index ec3f910aa40b..0c3c2fb0f939 100644 --- a/include/sound/tea575x-tuner.h +++ b/include/sound/tea575x-tuner.h @@ -44,6 +44,7 @@ struct snd_tea575x_ops { struct snd_tea575x { struct v4l2_device *v4l2_dev; + struct v4l2_file_operations fops; struct video_device vd; /* video device */ int radio_nr; /* radio_nr */ bool tea5759; /* 5759 chip is present */ @@ -62,7 +63,7 @@ struct snd_tea575x { int (*ext_init)(struct snd_tea575x *tea); }; -int snd_tea575x_init(struct snd_tea575x *tea); +int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner); void snd_tea575x_exit(struct snd_tea575x *tea); #endif /* __SOUND_TEA575X_TUNER_H */ diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index aa9900dff6e9..ac62ee791a60 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c @@ -317,7 +317,6 @@ static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) } static const struct v4l2_file_operations tea575x_fops = { - .owner = THIS_MODULE, .unlocked_ioctl = video_ioctl2, .open = v4l2_fh_open, .release = v4l2_fh_release, @@ -337,7 +336,6 @@ static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { }; static const struct video_device tea575x_radio = { - .fops = &tea575x_fops, .ioctl_ops = &tea575x_ioctl_ops, .release = video_device_release_empty, }; @@ -349,7 +347,7 @@ static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { /* * initialize all the tea575x chips */ -int snd_tea575x_init(struct snd_tea575x *tea) +int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) { int retval; @@ -374,6 +372,9 @@ int snd_tea575x_init(struct snd_tea575x *tea) tea->vd.lock = &tea->mutex; tea->vd.v4l2_dev = tea->v4l2_dev; tea->vd.ctrl_handler = &tea->ctrl_handler; + tea->fops = tea575x_fops; + tea->fops.owner = owner; + tea->vd.fops = &tea->fops; set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags); /* disable hw_freq_seek if we can't use it */ if (tea->cannot_read_data) diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index a8faae1c85e4..0f2811eeeebd 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -2769,7 +2769,7 @@ static int __devinit snd_es1968_create(struct snd_card *card, chip->tea.ops = &snd_es1968_tea_ops; strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card)); sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); - if (!snd_tea575x_init(&chip->tea)) + if (!snd_tea575x_init(&chip->tea, THIS_MODULE)) printk(KERN_INFO "es1968: detected TEA575x radio\n"); #endif diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index a416ea8af3e9..5265c576a26a 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -1254,7 +1254,7 @@ static int __devinit snd_fm801_create(struct snd_card *card, sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 && (tea575x_tuner & TUNER_TYPE_MASK) < 4) { - if (snd_tea575x_init(&chip->tea)) { + if (snd_tea575x_init(&chip->tea, THIS_MODULE)) { snd_printk(KERN_ERR "TEA575x radio not found\n"); snd_fm801_free(chip); return -ENODEV; @@ -1263,7 +1263,7 @@ static int __devinit snd_fm801_create(struct snd_card *card, /* autodetect tuner connection */ for (tea575x_tuner = 1; tea575x_tuner <= 3; tea575x_tuner++) { chip->tea575x_tuner = tea575x_tuner; - if (!snd_tea575x_init(&chip->tea)) { + if (!snd_tea575x_init(&chip->tea, THIS_MODULE)) { snd_printk(KERN_INFO "detected TEA575x radio type %s\n", get_tea575x_gpio(chip)->name); break; -- cgit v1.2.3 From 40e006aea811afb15e56164383b914cff7a078c7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 19 May 2012 11:19:06 -0300 Subject: [media] snd_tea575x: set_freq: update cached freq to the actual achieved frequency Signed-off-by: Hans de Goede CC: Ondrej Zary Signed-off-by: Mauro Carvalho Chehab --- sound/i2c/other/tea575x-tuner.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index ac62ee791a60..7eca25fae413 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c @@ -120,9 +120,9 @@ static u32 snd_tea575x_read(struct snd_tea575x *tea) return data; } -static u32 snd_tea575x_get_freq(struct snd_tea575x *tea) +static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val) { - u32 freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK; + u32 freq = val & TEA575X_BIT_FREQ_MASK; if (freq == 0) return freq; @@ -139,6 +139,11 @@ static u32 snd_tea575x_get_freq(struct snd_tea575x *tea) return clamp(freq * 16, FREQ_LO, FREQ_HI); /* from kHz */ } +static u32 snd_tea575x_get_freq(struct snd_tea575x *tea) +{ + return snd_tea575x_val_to_freq(tea, snd_tea575x_read(tea)); +} + static void snd_tea575x_set_freq(struct snd_tea575x *tea) { u32 freq = tea->freq; @@ -156,6 +161,7 @@ static void snd_tea575x_set_freq(struct snd_tea575x *tea) tea->val &= ~TEA575X_BIT_FREQ_MASK; tea->val |= freq & TEA575X_BIT_FREQ_MASK; snd_tea575x_write(tea, tea->val); + tea->freq = snd_tea575x_val_to_freq(tea, tea->val); } /* -- cgit v1.2.3 From 80c8bfbe76869bfd6bdf3d260d316e7a32f318c3 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 4 Jun 2012 09:33:51 +0200 Subject: ALSA: HDA: Create phantom jacks for fixed inputs and outputs PulseAudio sometimes have difficulties knowing that there is a "Speaker" or "Internal Mic", if they have no individual volume controls or selectors. As a result, only e g "Headphone" might be created for a laptop, but no "Speaker". To help out, create phantom jacks (that are always present, at least for now) for "Speaker", "Internal Mic" etc, in case we detect them. The naming convention is e g "Speaker Phantom Jack". In order not to pollute the /dev/input namespace with even more devices, these are added to the kcontrols only, not the input devices. Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_jack.c | 59 +++++++++++++++++++++++++++++++++--------------- sound/pci/hda/hda_jack.h | 1 + 2 files changed, 42 insertions(+), 18 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 2dd1c113a4c1..60c976f06280 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -127,10 +127,15 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec) static void jack_detect_update(struct hda_codec *codec, struct hda_jack_tbl *jack) { - if (jack->jack_dirty || !jack->jack_detect) { + if (!jack->jack_dirty) + return; + + if (jack->phantom_jack) + jack->pin_sense = AC_PINSENSE_PRESENCE; + else jack->pin_sense = read_pin_sense(codec, jack->nid); - jack->jack_dirty = 0; - } + + jack->jack_dirty = 0; } /** @@ -264,8 +269,8 @@ static void hda_free_jack_priv(struct snd_jack *jack) * This assigns a jack-detection kctl to the given pin. The kcontrol * will have the given name and index. */ -int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, - const char *name, int idx) +static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, + const char *name, int idx, bool phantom_jack) { struct hda_jack_tbl *jack; struct snd_kcontrol *kctl; @@ -283,19 +288,30 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, if (err < 0) return err; jack->kctl = kctl; + jack->phantom_jack = !!phantom_jack; + state = snd_hda_jack_detect(codec, nid); snd_kctl_jack_report(codec->bus->card, kctl, state); #ifdef CONFIG_SND_HDA_INPUT_JACK - jack->type = get_input_jack_type(codec, nid); - err = snd_jack_new(codec->bus->card, name, jack->type, &jack->jack); - if (err < 0) - return err; - jack->jack->private_data = jack; - jack->jack->private_free = hda_free_jack_priv; - snd_jack_report(jack->jack, state ? jack->type : 0); + if (!phantom_jack) { + jack->type = get_input_jack_type(codec, nid); + err = snd_jack_new(codec->bus->card, name, jack->type, + &jack->jack); + if (err < 0) + return err; + jack->jack->private_data = jack; + jack->jack->private_free = hda_free_jack_priv; + snd_jack_report(jack->jack, state ? jack->type : 0); + } #endif return 0; } + +int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, + const char *name, int idx) +{ + return __snd_hda_jack_add_kctl(codec, nid, name, idx, false); +} EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, @@ -305,25 +321,32 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, unsigned int def_conf, conn; char name[44]; int idx, err; + bool phantom_jack; if (!nid) return 0; - if (!is_jack_detectable(codec, nid)) - return 0; def_conf = snd_hda_codec_get_pincfg(codec, nid); conn = get_defcfg_connect(def_conf); - if (conn != AC_JACK_PORT_COMPLEX) + if (conn == AC_JACK_PORT_NONE) return 0; + phantom_jack = (conn != AC_JACK_PORT_COMPLEX) || + !is_jack_detectable(codec, nid); snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); + if (phantom_jack) + /* Example final name: "Internal Mic Phantom Jack" */ + strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); if (!strcmp(name, lastname) && idx == *lastidx) idx++; - strncpy(lastname, name, 44); + strncpy(lastname, name, sizeof(name)); *lastidx = idx; - err = snd_hda_jack_add_kctl(codec, nid, name, idx); + err = __snd_hda_jack_add_kctl(codec, nid, name, idx, phantom_jack); if (err < 0) return err; - return snd_hda_jack_detect_enable(codec, nid, 0); + + if (!phantom_jack) + return snd_hda_jack_detect_enable(codec, nid, 0); + return 0; } /** diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index 8ae52465ec5d..a9803da633c0 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h @@ -23,6 +23,7 @@ struct hda_jack_tbl { unsigned int pin_sense; /* cached pin-sense value */ unsigned int jack_detect:1; /* capable of jack-detection? */ unsigned int jack_dirty:1; /* needs to update? */ + unsigned int phantom_jack:1; /* a fixed, always present port? */ struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ #ifdef CONFIG_SND_HDA_INPUT_JACK int type; -- cgit v1.2.3 From c20c5a841cbe47f5b7812b57bd25397497e5fbc0 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Thu, 14 Jun 2012 14:23:53 -0700 Subject: ALSA: hda_intel: activate COMBO mode for Intel client chipsets This patch activates the COMBO position_fix for recent Intel client chipsets. COMBO mode is the recommended setting for Intel chipsets and eliminates HD audio warnings in dmesg. This patch has been tested on Lynx Point, Panther Point, and Cougar Pont. Signed-off-by: Seth Heasley Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d49926e4d19f..1a07d2188dd7 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -535,6 +535,7 @@ enum { #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ +#define AZX_DCAPS_POSFIX_COMBO (1 << 24) /* Use COMBO as default */ /* quirks for ATI SB / AMD Hudson */ #define AZX_DCAPS_PRESET_ATI_SB \ @@ -2728,6 +2729,10 @@ static int __devinit check_position_fix(struct azx *chip, int fix) snd_printd(SFX "Using LPIB position fix\n"); return POS_FIX_LPIB; } + if (chip->driver_caps & AZX_DCAPS_POSFIX_COMBO) { + snd_printd(SFX "Using COMBO position fix\n"); + return POS_FIX_COMBO; + } return POS_FIX_AUTO; } @@ -3240,7 +3245,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* CPT */ { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE }, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, /* PBG */ { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | @@ -3248,11 +3253,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* Panther Point */ { PCI_DEVICE(0x8086, 0x1e20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE}, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, /* Lynx Point */ { PCI_DEVICE(0x8086, 0x8c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE}, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, /* SCH */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | -- cgit v1.2.3 From 4b6ace9e7176d93f819cec9df47faadaaceead4b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jun 2012 11:53:32 +0200 Subject: ALSA: hda - Add the support for VIA HDMI pin detection This patch adds the hotplug unsol event handling to simple_hdmi*(). It works on VIA VX900. If AMD or Nvidia chips support the pin-detection similarly, it can be added easily, too. Reported-by: Annie Liu Tested-by: Annie Liu Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 696681826b01..8e7333b07b58 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1377,6 +1377,19 @@ static int simple_playback_build_pcms(struct hda_codec *codec) return 0; } +/* unsolicited event for jack sensing */ +static void simple_hdmi_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + snd_hda_jack_get_action(codec, res >> AC_UNSOL_RES_TAG_SHIFT); + snd_hda_jack_report_sync(codec); +} + +/* generic_hdmi_build_jack can be used for simple_hdmi, too, + * as long as spec->pins[] is set correctly + */ +#define simple_hdmi_build_jack generic_hdmi_build_jack + static int simple_playback_build_controls(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; @@ -1389,6 +1402,11 @@ static int simple_playback_build_controls(struct hda_codec *codec) spec->cvts[i].cvt_nid); if (err < 0) return err; + if (codec->patch_ops.unsol_event) { + err = simple_hdmi_build_jack(codec, i); + if (err < 0) + return err; + } } return 0; @@ -1876,6 +1894,7 @@ static struct hda_verb viahdmi_basic_init[] = { static int via_hdmi_init(struct hda_codec *codec) { snd_hda_sequence_write(codec, viahdmi_basic_init); + snd_hda_jack_report_sync(codec); return 0; } @@ -1884,6 +1903,7 @@ static const struct hda_codec_ops via_hdmi_patch_ops = { .build_pcms = simple_playback_build_pcms, .init = via_hdmi_init, .free = simple_playback_free, + .unsol_event = simple_hdmi_unsol_event, }; static struct hda_pcm_stream via_hdmi_digital_playback = { -- cgit v1.2.3 From 4f0110ced1b5d61e6df4871f6f800a9d3678bf26 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jun 2012 12:45:43 +0200 Subject: ALSA: hda - Merge ATI/VIA HDMI simple init functions Just a minor code cleanup to use the same function for both AMD and VIA simple_hdmi*(). Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 56 ++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 34 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8e7333b07b58..c9d0c98bbe86 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1412,6 +1412,24 @@ static int simple_playback_build_controls(struct hda_codec *codec) return 0; } +static int simple_playback_init(struct hda_codec *codec) +{ + struct hdmi_spec *spec = codec->spec; + int i; + + for (i = 0; i < spec->num_pins; i++) { + snd_hda_codec_write(codec, spec->pins[i].pin_nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + /* some codecs require to unmute the pin */ + if (get_wcaps(codec, spec->pins[i].pin_nid) & AC_WCAP_OUT_AMP) + snd_hda_codec_write(codec, spec->pins[i].pin_nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_UNMUTE); + } + snd_hda_jack_report_sync(codec); + return 0; +} + static void simple_playback_free(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; @@ -1831,29 +1849,10 @@ static const struct hda_pcm_stream atihdmi_pcm_digital_playback = { }, }; -static const struct hda_verb atihdmi_basic_init[] = { - /* enable digital output on pin widget */ - { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - {} /* terminator */ -}; - -static int atihdmi_init(struct hda_codec *codec) -{ - struct hdmi_spec *spec = codec->spec; - - snd_hda_sequence_write(codec, atihdmi_basic_init); - /* SI codec requires to unmute the pin */ - if (get_wcaps(codec, spec->pins[0].pin_nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, spec->pins[0].pin_nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_UNMUTE); - return 0; -} - static const struct hda_codec_ops atihdmi_patch_ops = { .build_controls = simple_playback_build_controls, .build_pcms = simple_playback_build_pcms, - .init = atihdmi_init, + .init = simple_playback_init, .free = simple_playback_free, }; @@ -1872,6 +1871,7 @@ static int patch_atihdmi(struct hda_codec *codec) spec->multiout.max_channels = 2; spec->multiout.dig_out_nid = ATIHDMI_CVT_NID; spec->num_cvts = 1; + spec->num_pins = 1; spec->cvts[0].cvt_nid = ATIHDMI_CVT_NID; spec->pins[0].pin_nid = ATIHDMI_PIN_NID; spec->pcm_playback = &atihdmi_pcm_digital_playback; @@ -1885,23 +1885,10 @@ static int patch_atihdmi(struct hda_codec *codec) #define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ #define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ -static struct hda_verb viahdmi_basic_init[] = { - /* enable digital output on pin widget */ - { VIAHDMI_PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - {} /* terminator */ -}; - -static int via_hdmi_init(struct hda_codec *codec) -{ - snd_hda_sequence_write(codec, viahdmi_basic_init); - snd_hda_jack_report_sync(codec); - return 0; -} - static const struct hda_codec_ops via_hdmi_patch_ops = { .build_controls = simple_playback_build_controls, .build_pcms = simple_playback_build_pcms, - .init = via_hdmi_init, + .init = simple_playback_init, .free = simple_playback_free, .unsol_event = simple_hdmi_unsol_event, }; @@ -1930,6 +1917,7 @@ static int patch_via_hdmi(struct hda_codec *codec) spec->multiout.max_channels = 2; spec->multiout.dig_out_nid = VIAHDMI_CVT_NID; /* pure-digital case */ spec->num_cvts = 1; + spec->num_pins = 1; spec->cvts[0].cvt_nid = VIAHDMI_CVT_NID; spec->pins[0].pin_nid = VIAHDMI_PIN_NID; spec->pcm_playback = &via_hdmi_digital_playback; -- cgit v1.2.3 From d0b1252dd11549103a97a13aca25737b084c5618 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jun 2012 14:34:42 +0200 Subject: ALSA: hda - Use common codes for ATI, Nvidia and VIA simple codecs The code refactoring using the same helper functions for sharing the codes among ATI, Nvidia and VIA simple_hdmi* stuff. Except for that spec->pcm_playback is no longer pointer, the functionality doesn't change. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 191 +++++++++++++++------------------------------ 1 file changed, 65 insertions(+), 126 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index c9d0c98bbe86..6bf784fc8d6d 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -85,7 +85,7 @@ struct hdmi_spec { * Non-generic ATI/NVIDIA specific */ struct hda_multi_out multiout; - const struct hda_pcm_stream *pcm_playback; + struct hda_pcm_stream pcm_playback; }; @@ -1367,8 +1367,7 @@ static int simple_playback_build_pcms(struct hda_codec *codec) info->name = get_hdmi_pcm_name(i); info->pcm_type = HDA_PCM_TYPE_HDMI; pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; - snd_BUG_ON(!spec->pcm_playback); - *pstr = *spec->pcm_playback; + *pstr = spec->pcm_playback; pstr->nid = spec->cvts[i].cvt_nid; if (pstr->channels_max <= 2 && chans && chans <= 16) pstr->channels_max = chans; @@ -1560,6 +1559,49 @@ static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, stream_tag, format, substream); } +static const struct hda_pcm_stream simple_pcm_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + .ops = { + .open = simple_playback_pcm_open, + .close = simple_playback_pcm_close, + .prepare = simple_playback_pcm_prepare + }, +}; + +static const struct hda_codec_ops simple_hdmi_patch_ops = { + .build_controls = simple_playback_build_controls, + .build_pcms = simple_playback_build_pcms, + .init = simple_playback_init, + .free = simple_playback_free, +}; + +static int patch_simple_hdmi(struct hda_codec *codec, + hda_nid_t cvt_nid, hda_nid_t pin_nid) +{ + struct hdmi_spec *spec; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + codec->spec = spec; + + spec->multiout.num_dacs = 0; /* no analog */ + spec->multiout.max_channels = 2; + spec->multiout.dig_out_nid = cvt_nid; + spec->num_cvts = 1; + spec->num_pins = 1; + spec->cvts[0].cvt_nid = cvt_nid; + spec->cvts[0].cvt_nid = pin_nid; + spec->pcm_playback = simple_pcm_playback; + + codec->patch_ops = simple_hdmi_patch_ops; + + return 0; +} + static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, int channels) { @@ -1732,54 +1774,20 @@ static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { }, }; -static const struct hda_pcm_stream nvhdmi_pcm_playback_2ch = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = nvhdmi_master_con_nid_7x, - .rates = SUPPORTED_RATES, - .maxbps = SUPPORTED_MAXBPS, - .formats = SUPPORTED_FORMATS, - .ops = { - .open = simple_playback_pcm_open, - .close = simple_playback_pcm_close, - .prepare = simple_playback_pcm_prepare - }, -}; - -static const struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { - .build_controls = simple_playback_build_controls, - .build_pcms = simple_playback_build_pcms, - .init = nvhdmi_7x_init, - .free = simple_playback_free, -}; - -static const struct hda_codec_ops nvhdmi_patch_ops_2ch = { - .build_controls = simple_playback_build_controls, - .build_pcms = simple_playback_build_pcms, - .init = nvhdmi_7x_init, - .free = simple_playback_free, -}; - static int patch_nvhdmi_2ch(struct hda_codec *codec) { struct hdmi_spec *spec; + int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x, + nvhdmi_master_pin_nid_7x); + if (err < 0) + return err; - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->multiout.num_dacs = 0; /* no analog */ - spec->multiout.max_channels = 2; - spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; - spec->num_cvts = 1; - spec->cvts[0].cvt_nid = nvhdmi_master_con_nid_7x; - spec->pcm_playback = &nvhdmi_pcm_playback_2ch; - - codec->patch_ops = nvhdmi_patch_ops_2ch; - + codec->patch_ops.init = nvhdmi_7x_init; + /* override the PCM rates, etc, as the codec doesn't give full list */ + spec = codec->spec; + spec->pcm_playback.rates = SUPPORTED_RATES; + spec->pcm_playback.maxbps = SUPPORTED_MAXBPS; + spec->pcm_playback.formats = SUPPORTED_FORMATS; return 0; } @@ -1787,13 +1795,11 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) { struct hdmi_spec *spec; int err = patch_nvhdmi_2ch(codec); - if (err < 0) return err; spec = codec->spec; spec->multiout.max_channels = 8; - spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x; - codec->patch_ops = nvhdmi_patch_ops_8ch_7x; + spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; /* Initialize the audio infoframe channel mask and checksum to something * valid */ @@ -1837,47 +1843,14 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, return 0; } -static const struct hda_pcm_stream atihdmi_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = ATIHDMI_CVT_NID, - .ops = { - .open = simple_playback_pcm_open, - .close = simple_playback_pcm_close, - .prepare = atihdmi_playback_pcm_prepare - }, -}; - -static const struct hda_codec_ops atihdmi_patch_ops = { - .build_controls = simple_playback_build_controls, - .build_pcms = simple_playback_build_pcms, - .init = simple_playback_init, - .free = simple_playback_free, -}; - - static int patch_atihdmi(struct hda_codec *codec) { struct hdmi_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->multiout.num_dacs = 0; /* no analog */ - spec->multiout.max_channels = 2; - spec->multiout.dig_out_nid = ATIHDMI_CVT_NID; - spec->num_cvts = 1; - spec->num_pins = 1; - spec->cvts[0].cvt_nid = ATIHDMI_CVT_NID; - spec->pins[0].pin_nid = ATIHDMI_PIN_NID; - spec->pcm_playback = &atihdmi_pcm_digital_playback; - - codec->patch_ops = atihdmi_patch_ops; - + int err = patch_simple_hdmi(codec, ATIHDMI_CVT_NID, ATIHDMI_PIN_NID); + if (err < 0) + return err; + spec = codec->spec; + spec->pcm_playback.ops.prepare = atihdmi_playback_pcm_prepare; return 0; } @@ -1885,46 +1858,12 @@ static int patch_atihdmi(struct hda_codec *codec) #define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ #define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ -static const struct hda_codec_ops via_hdmi_patch_ops = { - .build_controls = simple_playback_build_controls, - .build_pcms = simple_playback_build_pcms, - .init = simple_playback_init, - .free = simple_playback_free, - .unsol_event = simple_hdmi_unsol_event, -}; - -static struct hda_pcm_stream via_hdmi_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = VIAHDMI_CVT_NID, /* NID to query formats and rates*/ - .ops = { - .open = simple_playback_pcm_open, - .close = simple_playback_pcm_close, - .prepare = simple_playback_pcm_prepare - }, -}; - static int patch_via_hdmi(struct hda_codec *codec) { - struct hdmi_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - spec->multiout.num_dacs = 0; /* no analog */ - spec->multiout.max_channels = 2; - spec->multiout.dig_out_nid = VIAHDMI_CVT_NID; /* pure-digital case */ - spec->num_cvts = 1; - spec->num_pins = 1; - spec->cvts[0].cvt_nid = VIAHDMI_CVT_NID; - spec->pins[0].pin_nid = VIAHDMI_PIN_NID; - spec->pcm_playback = &via_hdmi_digital_playback; - - codec->spec = spec; - codec->patch_ops = via_hdmi_patch_ops; - + int err = patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); + if (err < 0) + return err; + codec->patch_ops.unsol_event = simple_hdmi_unsol_event; return 0; } -- cgit v1.2.3 From ceaa86ba2ed90780617be76526de975521374595 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jun 2012 14:38:31 +0200 Subject: ALSA: hda - Remove invalid init verbs for Nvidia 2ch codecs Nvidia 2ch codecs have no NIDs greather than 0x05. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 6bf784fc8d6d..f51a0b5bfcb2 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1453,7 +1453,15 @@ static const hda_nid_t nvhdmi_con_nids_7x[4] = { 0x6, 0x8, 0xa, 0xc, }; -static const struct hda_verb nvhdmi_basic_init_7x[] = { +static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = { + /* set audio protect on */ + { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, + /* enable digital output on pin widget */ + { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, + {} /* terminator */ +}; + +static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = { /* set audio protect on */ { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, /* enable digital output on pin widget */ @@ -1481,9 +1489,15 @@ static const struct hda_verb nvhdmi_basic_init_7x[] = { (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) #endif -static int nvhdmi_7x_init(struct hda_codec *codec) +static int nvhdmi_7x_init_2ch(struct hda_codec *codec) +{ + snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch); + return 0; +} + +static int nvhdmi_7x_init_8ch(struct hda_codec *codec) { - snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); + snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch); return 0; } @@ -1782,7 +1796,7 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) if (err < 0) return err; - codec->patch_ops.init = nvhdmi_7x_init; + codec->patch_ops.init = nvhdmi_7x_init_2ch; /* override the PCM rates, etc, as the codec doesn't give full list */ spec = codec->spec; spec->pcm_playback.rates = SUPPORTED_RATES; @@ -1800,6 +1814,7 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) spec = codec->spec; spec->multiout.max_channels = 8; spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; + codec->patch_ops.init = nvhdmi_7x_init_8ch; /* Initialize the audio infoframe channel mask and checksum to something * valid */ -- cgit v1.2.3 From 250e41ac9f31216db1b592bfd77c6a097f10503d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 15 Jun 2012 14:40:21 +0200 Subject: ALSA: hda - Enable unsol event for ATI and Nvidia HDMI codecs too ATI and Nvidia HDMI codecs have also the pin-detection capability, so let's enable the jack-detecion for them, too. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index f51a0b5bfcb2..8891fa658382 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1401,11 +1401,9 @@ static int simple_playback_build_controls(struct hda_codec *codec) spec->cvts[i].cvt_nid); if (err < 0) return err; - if (codec->patch_ops.unsol_event) { - err = simple_hdmi_build_jack(codec, i); - if (err < 0) - return err; - } + err = simple_hdmi_build_jack(codec, i); + if (err < 0) + return err; } return 0; @@ -1589,6 +1587,7 @@ static const struct hda_codec_ops simple_hdmi_patch_ops = { .build_pcms = simple_playback_build_pcms, .init = simple_playback_init, .free = simple_playback_free, + .unsol_event = simple_hdmi_unsol_event, }; static int patch_simple_hdmi(struct hda_codec *codec, @@ -1875,11 +1874,7 @@ static int patch_atihdmi(struct hda_codec *codec) static int patch_via_hdmi(struct hda_codec *codec) { - int err = patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); - if (err < 0) - return err; - codec->patch_ops.unsol_event = simple_hdmi_unsol_event; - return 0; + return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); } /* -- cgit v1.2.3 From 21cd683d318041c63876b4acbebb3f6d9d80597b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jun 2012 09:19:32 +0200 Subject: ALSA: hda - Fix the pin nid assignment in patch_hdmi.c This fixes the regression introduced by the commit d0b1252d for refactoring simple_hdmi*(). The pin NID wasn't assigned correctly. Reported-by: Annie Liu Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8891fa658382..72a3b26736ae 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1607,7 +1607,7 @@ static int patch_simple_hdmi(struct hda_codec *codec, spec->num_cvts = 1; spec->num_pins = 1; spec->cvts[0].cvt_nid = cvt_nid; - spec->cvts[0].cvt_nid = pin_nid; + spec->pins[0].pin_nid = pin_nid; spec->pcm_playback = simple_pcm_playback; codec->patch_ops = simple_hdmi_patch_ops; -- cgit v1.2.3 From ccfcf7d151c01969133b5555eed635537c41c944 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jun 2012 09:30:42 +0200 Subject: ALSA: hda - Add missing snd_hda_jack_detect_enable() for simple_hdmi*() Reported-by: Annie Liu Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 72a3b26736ae..db8f6928f839 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1415,13 +1415,15 @@ static int simple_playback_init(struct hda_codec *codec) int i; for (i = 0; i < spec->num_pins; i++) { - snd_hda_codec_write(codec, spec->pins[i].pin_nid, 0, + hda_nid_t pin = spec->pins[i].pin_nid; + snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); /* some codecs require to unmute the pin */ - if (get_wcaps(codec, spec->pins[i].pin_nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, spec->pins[i].pin_nid, 0, + if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) + snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + snd_hda_jack_detect_enable(codec, pin, pin); } snd_hda_jack_report_sync(codec); return 0; -- cgit v1.2.3 From 8b8d654b55648561287bd8baca0f75f964a17038 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jun 2012 16:32:22 +0200 Subject: ALSA: hda - Move one-time init codes from generic_hdmi_init() The codes to initialize work struct or create a proc interface should be called only once and never although it's called many times through the init callback. Move that stuff into patch_generic_hdmi() so that it's called only once. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index db8f6928f839..64f1fedfd535 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1277,23 +1277,34 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) return 0; } -static int generic_hdmi_init(struct hda_codec *codec) +static int generic_hdmi_init_per_pins(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; int pin_idx; for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; - hda_nid_t pin_nid = per_pin->pin_nid; struct hdmi_eld *eld = &per_pin->sink_eld; - hdmi_init_pin(codec, pin_nid); - snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); - per_pin->codec = codec; INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); snd_hda_eld_proc_new(codec, eld, pin_idx); } + return 0; +} + +static int generic_hdmi_init(struct hda_codec *codec) +{ + struct hdmi_spec *spec = codec->spec; + int pin_idx; + + for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { + struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; + hda_nid_t pin_nid = per_pin->pin_nid; + + hdmi_init_pin(codec, pin_nid); + snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); + } snd_hda_jack_report_sync(codec); return 0; } @@ -1338,6 +1349,7 @@ static int patch_generic_hdmi(struct hda_codec *codec) return -EINVAL; } codec->patch_ops = generic_hdmi_patch_ops; + generic_hdmi_init_per_pins(codec); init_channel_allocations(); -- cgit v1.2.3 From 8ceb332df46863ac8f74114a2b1805719cf49dcc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 21 Jun 2012 08:23:27 +0200 Subject: ALSA: hda - Remove loop from simple_hdmi*() The simple_hdmi stuff is designed only for a single pin and a single converter (thus a single PCM stream), and no need for loops. Let's flatten the code. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 69 ++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 42 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 64f1fedfd535..0a87a1f2988e 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1364,26 +1364,22 @@ static int simple_playback_build_pcms(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; struct hda_pcm *info = spec->pcm_rec; - int i; + unsigned int chans; + struct hda_pcm_stream *pstr; - codec->num_pcms = spec->num_cvts; + codec->num_pcms = 1; codec->pcm_info = info; - for (i = 0; i < codec->num_pcms; i++, info++) { - unsigned int chans; - struct hda_pcm_stream *pstr; + chans = get_wcaps(codec, spec->cvts[0].cvt_nid); + chans = get_wcaps_channels(chans); - chans = get_wcaps(codec, spec->cvts[i].cvt_nid); - chans = get_wcaps_channels(chans); - - info->name = get_hdmi_pcm_name(i); - info->pcm_type = HDA_PCM_TYPE_HDMI; - pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; - *pstr = spec->pcm_playback; - pstr->nid = spec->cvts[i].cvt_nid; - if (pstr->channels_max <= 2 && chans && chans <= 16) - pstr->channels_max = chans; - } + info->name = get_hdmi_pcm_name(0); + info->pcm_type = HDA_PCM_TYPE_HDMI; + pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; + *pstr = spec->pcm_playback; + pstr->nid = spec->cvts[0].cvt_nid; + if (pstr->channels_max <= 2 && chans && chans <= 16) + pstr->channels_max = chans; return 0; } @@ -1405,38 +1401,27 @@ static int simple_playback_build_controls(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; int err; - int i; - - for (i = 0; i < codec->num_pcms; i++) { - err = snd_hda_create_spdif_out_ctls(codec, - spec->cvts[i].cvt_nid, - spec->cvts[i].cvt_nid); - if (err < 0) - return err; - err = simple_hdmi_build_jack(codec, i); - if (err < 0) - return err; - } - return 0; + err = snd_hda_create_spdif_out_ctls(codec, + spec->cvts[0].cvt_nid, + spec->cvts[0].cvt_nid); + if (err < 0) + return err; + return simple_hdmi_build_jack(codec, 0); } static int simple_playback_init(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->num_pins; i++) { - hda_nid_t pin = spec->pins[i].pin_nid; - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); - /* some codecs require to unmute the pin */ - if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_UNMUTE); - snd_hda_jack_detect_enable(codec, pin, pin); - } + hda_nid_t pin = spec->pins[0].pin_nid; + + snd_hda_codec_write(codec, pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + /* some codecs require to unmute the pin */ + if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) + snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_UNMUTE); + snd_hda_jack_detect_enable(codec, pin, pin); snd_hda_jack_report_sync(codec); return 0; } -- cgit v1.2.3 From 9dd8cf125d27742a25219bfdf82026e7efed27d9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 21 Jun 2012 10:43:15 +0200 Subject: ALSA: hda - Don't rely on event tag for simple_hdmi VIA codecs seem not returning the event tag in the unsolicited events, thus the current code relying on the tag value doesn't work. Since simple_hdmi stuff has only a single pin, we can use simply snd_hda_jack_set_dirty_all() to activate the pin-detection independently from the tag value. Tested-by: Annie Liu Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 0a87a1f2988e..75ad1a10646b 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1388,7 +1388,7 @@ static int simple_playback_build_pcms(struct hda_codec *codec) static void simple_hdmi_unsol_event(struct hda_codec *codec, unsigned int res) { - snd_hda_jack_get_action(codec, res >> AC_UNSOL_RES_TAG_SHIFT); + snd_hda_jack_set_dirty_all(codec); snd_hda_jack_report_sync(codec); } -- cgit v1.2.3 From e9ea8e8f229f4963bf01658e79c1c01780de25dd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 21 Jun 2012 11:41:05 +0200 Subject: ALSA: hda - Correct info print in HDMI non-intrinsic unsol event In the recent code, the value shown there is a tag number, and it's no longer same as the pin nid. Correct the message to avoid confusion. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 75ad1a10646b..d6a8260a6f74 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -787,7 +787,7 @@ static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); printk(KERN_INFO - "HDMI CP event: CODEC=%d PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", + "HDMI CP event: CODEC=%d TAG=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", codec->addr, tag, subtag, -- cgit v1.2.3 From b43d224767e426cf1a8b6622d1d172f2b2b0e857 Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Thu, 21 Jun 2012 21:51:22 -0700 Subject: ALSA: hda - Don't power up when not powered down. After cancel_delayed_work_sync returns, the power down work either never started (power_on == 1) or finished (power_on == 0). In the former case there is no need to power up again. Signed-off-by: Dylan Reid Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 604699cf85f5..045b5e7b8245 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4444,6 +4444,13 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) cancel_delayed_work_sync(&codec->power_work); spin_lock(&codec->power_lock); + /* If the power down delayed work was cancelled above before starting, + * then there is no need to go through power up here. + */ + if (codec->power_on) { + spin_unlock(&codec->power_lock); + return; + } trace_hda_power_up(codec); snd_hda_update_power_acct(codec); codec->power_on = 1; -- cgit v1.2.3 From 125821ae539ab60f432b5e10dadfd7bbf069ca7a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 22 Jun 2012 14:30:29 +0200 Subject: ALSA: hda - Add the inverted digital mic workaround to Realtek codecs Some laptops are equipped with ForteMedia digital mics that give the differential input. With such devices, summing stereo streams into a mono (like PulseAudio does) results in almost silence. This patch provides a workaround for this bug by adding a new mixer switch to turn on/off the right channel of digital mic, just like a similar fix for Conexant codecs. When the new switch "Inverted Internal Mic Capture Switch" is off and the current input source is the digital mic, the right channel of the recording stream is muted. When another input source is selected, the right channel is restored. Tested-by: Eliot Blennerhassett Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 127 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f8f4906e498d..a0a3cf956503 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -170,6 +170,7 @@ struct alc_spec { hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */ + hda_nid_t inv_dmic_pin; /* hooks */ void (*init_hook)(struct hda_codec *codec); @@ -201,6 +202,8 @@ struct alc_spec { unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ + unsigned int inv_dmic_fixup:1; /* has inverted digital-mic workaround */ + unsigned int inv_dmic_muted:1; /* R-ch of inv d-mic is muted? */ /* auto-mute control */ int automute_mode; @@ -298,6 +301,7 @@ static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx) } static void call_update_outputs(struct hda_codec *codec); +static void alc_inv_dmic_sync(struct hda_codec *codec, bool force); /* select the given imux item; either unmute exclusively or select the route */ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, @@ -368,6 +372,7 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, AC_VERB_SET_CONNECT_SEL, imux->items[idx].index); } + alc_inv_dmic_sync(codec, true); return 1; } @@ -1556,14 +1561,14 @@ typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol, static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol, - getput_call_t func, bool check_adc_switch) + getput_call_t func, bool is_put) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; int i, err = 0; mutex_lock(&codec->control_mutex); - if (check_adc_switch && spec->dyn_adc_switch) { + if (is_put && spec->dyn_adc_switch) { for (i = 0; i < spec->num_adc_nids; i++) { kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[i], @@ -1584,6 +1589,8 @@ static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, 3, 0, HDA_INPUT); err = func(kcontrol, ucontrol); } + if (err >= 0 && is_put) + alc_inv_dmic_sync(codec, false); error: mutex_unlock(&codec->control_mutex); return err; @@ -1675,6 +1682,108 @@ DEFINE_CAPMIX_NOSRC(1); DEFINE_CAPMIX_NOSRC(2); DEFINE_CAPMIX_NOSRC(3); +/* + * Inverted digital-mic handling + * + * First off, it's a bit tricky. The "Inverted Internal Mic Capture Switch" + * gives the additional mute only to the right channel of the digital mic + * capture stream. This is a workaround for avoiding the almost silence + * by summing the stereo stream from some (known to be ForteMedia) + * digital mic unit. + * + * The logic is to call alc_inv_dmic_sync() after each action (possibly) + * modifying ADC amp. When the mute flag is set, it mutes the R-channel + * without caching so that the cache can still keep the original value. + * The cached value is then restored when the flag is set off or any other + * than d-mic is used as the current input source. + */ +static void alc_inv_dmic_sync(struct hda_codec *codec, bool force) +{ + struct alc_spec *spec = codec->spec; + int i; + + if (!spec->inv_dmic_fixup) + return; + if (!spec->inv_dmic_muted && !force) + return; + for (i = 0; i < spec->num_adc_nids; i++) { + int src = spec->dyn_adc_switch ? 0 : i; + bool dmic_fixup = false; + hda_nid_t nid; + int parm, dir, v; + + if (spec->inv_dmic_muted && + spec->imux_pins[spec->cur_mux[src]] == spec->inv_dmic_pin) + dmic_fixup = true; + if (!dmic_fixup && !force) + continue; + if (spec->vol_in_capsrc) { + nid = spec->capsrc_nids[i]; + parm = AC_AMP_SET_RIGHT | AC_AMP_SET_OUTPUT; + dir = HDA_OUTPUT; + } else { + nid = spec->adc_nids[i]; + parm = AC_AMP_SET_RIGHT | AC_AMP_SET_INPUT; + dir = HDA_INPUT; + } + /* we care only right channel */ + v = snd_hda_codec_amp_read(codec, nid, 1, dir, 0); + if (v & 0x80) /* if already muted, we don't need to touch */ + continue; + if (dmic_fixup) /* add mute for d-mic */ + v |= 0x80; + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, + parm | v); + } +} + +static int alc_inv_dmic_sw_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct alc_spec *spec = codec->spec; + + ucontrol->value.integer.value[0] = !spec->inv_dmic_muted; + return 0; +} + +static int alc_inv_dmic_sw_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct alc_spec *spec = codec->spec; + unsigned int val = !ucontrol->value.integer.value[0]; + + if (val == spec->inv_dmic_muted) + return 0; + spec->inv_dmic_muted = val; + alc_inv_dmic_sync(codec, true); + return 0; +} + +static const struct snd_kcontrol_new alc_inv_dmic_sw = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .info = snd_ctl_boolean_mono_info, + .get = alc_inv_dmic_sw_get, + .put = alc_inv_dmic_sw_put, +}; + +static int alc_add_inv_dmic_mixer(struct hda_codec *codec, hda_nid_t nid) +{ + struct alc_spec *spec = codec->spec; + struct snd_kcontrol_new *knew = alc_kcontrol_new(spec); + if (!knew) + return -ENOMEM; + *knew = alc_inv_dmic_sw; + knew->name = kstrdup("Inverted Internal Mic Capture Switch", GFP_KERNEL); + if (!knew->name) + return -ENOMEM; + spec->inv_dmic_fixup = 1; + spec->inv_dmic_muted = 0; + spec->inv_dmic_pin = nid; + return 0; +} + /* * virtual master controls */ @@ -2316,6 +2425,7 @@ static int alc_resume(struct hda_codec *codec) codec->patch_ops.init(codec); snd_hda_codec_resume_amp(codec); snd_hda_codec_resume_cache(codec); + alc_inv_dmic_sync(codec, true); hda_call_check_power_status(codec, 0x01); return 0; } @@ -6424,6 +6534,13 @@ static void alc272_fixup_mario(struct hda_codec *codec, "hda_codec: failed to override amp caps for NID 0x2\n"); } +static void alc662_fixup_inv_dmic(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + if (action == ALC_FIXUP_ACT_PROBE) + alc_add_inv_dmic_mixer(codec, 0x12); +} + enum { ALC662_FIXUP_ASPIRE, ALC662_FIXUP_IDEAPAD, @@ -6441,6 +6558,7 @@ enum { ALC662_FIXUP_ASUS_MODE8, ALC662_FIXUP_NO_JACK_DETECT, ALC662_FIXUP_ZOTAC_Z68, + ALC662_FIXUP_INV_DMIC, }; static const struct alc_fixup alc662_fixups[] = { @@ -6597,12 +6715,17 @@ static const struct alc_fixup alc662_fixups[] = { { } } }, + [ALC662_FIXUP_INV_DMIC] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc662_fixup_inv_dmic, + }, }; static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2), SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), -- cgit v1.2.3 From 693b613dc4657e3f9af2625e0097b1870c78bf8c Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Fri, 22 Jun 2012 19:12:10 +0200 Subject: ALSA: hda - Add inverted mic quirks for Asus U41SV, Acer 1810TZ and AOD260 These machines have inverted phase on right channel for their internal mics. BugLink: https://bugs.launchpad.net/bugs/997227 BugLink: https://bugs.launchpad.net/bugs/996611 BugLink: https://bugs.launchpad.net/bugs/1006089 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a0a3cf956503..d11fd0160748 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5918,6 +5918,14 @@ static void alc269_fixup_mic2_mute(struct hda_codec *codec, } } +static void alc269_fixup_inv_dmic(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + if (action == ALC_FIXUP_ACT_PROBE) + alc_add_inv_dmic_mixer(codec, 0x12); +} + + enum { ALC269_FIXUP_SONY_VAIO, ALC275_FIXUP_SONY_VAIO_GPIO2, @@ -5936,6 +5944,7 @@ enum { ALC269VB_FIXUP_AMIC, ALC269VB_FIXUP_DMIC, ALC269_FIXUP_MIC2_MUTE_LED, + ALC269_FIXUP_INV_DMIC, }; static const struct alc_fixup alc269_fixups[] = { @@ -6060,12 +6069,19 @@ static const struct alc_fixup alc269_fixups[] = { .type = ALC_FIXUP_FUNC, .v.func = alc269_fixup_mic2_mute, }, + [ALC269_FIXUP_INV_DMIC] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc269_fixup_inv_dmic, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), + SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), @@ -6534,12 +6550,7 @@ static void alc272_fixup_mario(struct hda_codec *codec, "hda_codec: failed to override amp caps for NID 0x2\n"); } -static void alc662_fixup_inv_dmic(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - if (action == ALC_FIXUP_ACT_PROBE) - alc_add_inv_dmic_mixer(codec, 0x12); -} +#define alc662_fixup_inv_dmic alc269_fixup_inv_dmic enum { ALC662_FIXUP_ASPIRE, -- cgit v1.2.3 From 6e72aa5f511daa2ffbd333ea99635c551b86013b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 25 Jun 2012 10:52:25 +0200 Subject: ALSA: hda - Add inv-dmic model to possible Realtek codecs For convenience, add "inv-dmic" model string for enabling the inverted internal mic workaround to possible Realtek codecs, so far, ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants. Also, the model strings for hardware inv-dmic workarounds, "alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271 codecs as well. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 64 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d11fd0160748..3e698e239dd8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1784,6 +1784,14 @@ static int alc_add_inv_dmic_mixer(struct hda_codec *codec, hda_nid_t nid) return 0; } +/* typically the digital mic is put at node 0x12 */ +static void alc_fixup_inv_dmic_0x12(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + if (action == ALC_FIXUP_ACT_PROBE) + alc_add_inv_dmic_mixer(codec, 0x12); +} + /* * virtual master controls */ @@ -5017,6 +5025,7 @@ enum { ALC889_FIXUP_DAC_ROUTE, ALC889_FIXUP_MBP_VREF, ALC889_FIXUP_IMAC91_VREF, + ALC882_FIXUP_INV_DMIC, }; static void alc889_fixup_coef(struct hda_codec *codec, @@ -5320,6 +5329,10 @@ static const struct alc_fixup alc882_fixups[] = { .chained = true, .chain_id = ALC882_FIXUP_GPIO1, }, + [ALC882_FIXUP_INV_DMIC] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc_fixup_inv_dmic_0x12, + }, }; static const struct snd_pci_quirk alc882_fixup_tbl[] = { @@ -5394,6 +5407,7 @@ static const struct alc_model_fixup alc882_fixup_models[] = { {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"}, {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"}, {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"}, + {.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"}, {} }; @@ -5481,6 +5495,7 @@ enum { ALC262_FIXUP_LENOVO_3000, ALC262_FIXUP_BENQ, ALC262_FIXUP_BENQ_T31, + ALC262_FIXUP_INV_DMIC, }; static const struct alc_fixup alc262_fixups[] = { @@ -5532,6 +5547,10 @@ static const struct alc_fixup alc262_fixups[] = { {} } }, + [ALC262_FIXUP_INV_DMIC] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc_fixup_inv_dmic_0x12, + }, }; static const struct snd_pci_quirk alc262_fixup_tbl[] = { @@ -5546,6 +5565,10 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = { {} }; +static const struct alc_model_fixup alc262_fixup_models[] = { + {.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"}, + {} +}; /* */ @@ -5574,7 +5597,8 @@ static int patch_alc262(struct hda_codec *codec) #endif alc_fix_pll_init(codec, 0x20, 0x0a, 10); - alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups); + alc_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl, + alc262_fixups); alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); alc_auto_parse_customize_define(codec); @@ -5630,6 +5654,22 @@ static const struct hda_verb alc268_beep_init_verbs[] = { { } }; +enum { + ALC268_FIXUP_INV_DMIC, +}; + +static const struct alc_fixup alc268_fixups[] = { + [ALC268_FIXUP_INV_DMIC] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc_fixup_inv_dmic_0x12, + }, +}; + +static const struct alc_model_fixup alc268_fixup_models[] = { + {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"}, + {} +}; + /* * BIOS auto configuration */ @@ -5661,6 +5701,9 @@ static int patch_alc268(struct hda_codec *codec) spec = codec->spec; + alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups); + alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); + /* automatic parse from the BIOS config */ err = alc268_parse_auto_config(codec); if (err < 0) @@ -5690,6 +5733,8 @@ static int patch_alc268(struct hda_codec *codec) codec->patch_ops = alc_patch_ops; spec->shutup = alc_eapd_shutup; + alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); + return 0; error: @@ -5918,13 +5963,6 @@ static void alc269_fixup_mic2_mute(struct hda_codec *codec, } } -static void alc269_fixup_inv_dmic(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - if (action == ALC_FIXUP_ACT_PROBE) - alc_add_inv_dmic_mixer(codec, 0x12); -} - enum { ALC269_FIXUP_SONY_VAIO, @@ -6071,7 +6109,7 @@ static const struct alc_fixup alc269_fixups[] = { }, [ALC269_FIXUP_INV_DMIC] = { .type = ALC_FIXUP_FUNC, - .v.func = alc269_fixup_inv_dmic, + .v.func = alc_fixup_inv_dmic_0x12, }, }; @@ -6157,6 +6195,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { static const struct alc_model_fixup alc269_fixup_models[] = { {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, + {.id = ALC269_FIXUP_STEREO_DMIC, .name = "alc269-dmic"}, + {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"}, + {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"}, {} }; @@ -6550,8 +6591,6 @@ static void alc272_fixup_mario(struct hda_codec *codec, "hda_codec: failed to override amp caps for NID 0x2\n"); } -#define alc662_fixup_inv_dmic alc269_fixup_inv_dmic - enum { ALC662_FIXUP_ASPIRE, ALC662_FIXUP_IDEAPAD, @@ -6728,7 +6767,7 @@ static const struct alc_fixup alc662_fixups[] = { }, [ALC662_FIXUP_INV_DMIC] = { .type = ALC_FIXUP_FUNC, - .v.func = alc662_fixup_inv_dmic, + .v.func = alc_fixup_inv_dmic_0x12, }, }; @@ -6817,6 +6856,7 @@ static const struct alc_model_fixup alc662_fixup_models[] = { {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"}, {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"}, {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"}, + {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"}, {} }; -- cgit v1.2.3 From e6656369da73f8a4206a72ea6fb0e35247f42364 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 25 Jun 2012 11:03:12 +0200 Subject: ALSA: hda - Remove suprefluous EAPD init verbs for ALC660vd The EAPD on nodes 0x14 and 0x15 are initialized in alc_auto_setup_eapd(). Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3e698e239dd8..4377a9539735 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6494,12 +6494,6 @@ static const struct snd_pci_quirk alc861vd_fixup_tbl[] = { {} }; -static const struct hda_verb alc660vd_eapd_verbs[] = { - {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, - {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, - { } -}; - /* */ static int patch_alc861vd(struct hda_codec *codec) @@ -6521,11 +6515,6 @@ static int patch_alc861vd(struct hda_codec *codec) if (err < 0) goto error; - if (codec->vendor_id == 0x10ec0660) { - /* always turn on EAPD */ - snd_hda_gen_add_verbs(&spec->gen, alc660vd_eapd_verbs); - } - if (!spec->no_analog) { err = snd_hda_attach_beep_device(codec, 0x23); if (err < 0) -- cgit v1.2.3 From 00227f15a0ad8401d2b0b67905da63e75b544895 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 27 Jun 2012 18:45:44 +0200 Subject: ALSA: HDA: Support single 3-pin jack without VREF on the actual pin Some ASUS device has a single 3-pin jack that can either be a mic or a headphone, but the pin does not have VREF capabilities. We've been told by Realtek to instead enable VREF on pin 0x18 in that case. BugLink: https://bugs.launchpad.net/bugs/1018262 Tested-by: Chih-Hsyuan Ho Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 49 ++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 15 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5c81ee95d7f0..40dda2a83774 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -303,6 +303,38 @@ static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx) static void call_update_outputs(struct hda_codec *codec); static void alc_inv_dmic_sync(struct hda_codec *codec, bool force); +/* for shared I/O, change the pin-control accordingly */ +static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic) +{ + struct alc_spec *spec = codec->spec; + unsigned int val; + hda_nid_t pin = spec->autocfg.inputs[1].pin; + /* NOTE: this assumes that there are only two inputs, the + * first is the real internal mic and the second is HP/mic jack. + */ + + val = snd_hda_get_default_vref(codec, pin); + + /* This pin does not have vref caps - let's enable vref on pin 0x18 + instead, as suggested by Realtek */ + if (val == AC_PINCTL_VREF_HIZ) { + const hda_nid_t vref_pin = 0x18; + /* Sanity check pin 0x18 */ + if (get_wcaps_type(get_wcaps(codec, vref_pin)) == AC_WID_PIN && + get_defcfg_connect(snd_hda_codec_get_pincfg(codec, vref_pin)) == AC_JACK_PORT_NONE) { + unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin); + if (vref_val != AC_PINCTL_VREF_HIZ) + snd_hda_set_pin_ctl(codec, vref_pin, PIN_IN | (set_as_mic ? vref_val : 0)); + } + } + + val = set_as_mic ? val | PIN_IN : PIN_HP; + snd_hda_set_pin_ctl(codec, pin, val); + + spec->automute_speaker = !set_as_mic; + call_update_outputs(codec); +} + /* select the given imux item; either unmute exclusively or select the route */ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, unsigned int idx, bool force) @@ -329,21 +361,8 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, return 0; spec->cur_mux[adc_idx] = idx; - /* for shared I/O, change the pin-control accordingly */ - if (spec->shared_mic_hp) { - unsigned int val; - hda_nid_t pin = spec->autocfg.inputs[1].pin; - /* NOTE: this assumes that there are only two inputs, the - * first is the real internal mic and the second is HP jack. - */ - if (spec->cur_mux[adc_idx]) - val = snd_hda_get_default_vref(codec, pin) | PIN_IN; - else - val = PIN_HP; - snd_hda_set_pin_ctl(codec, pin, val); - spec->automute_speaker = !spec->cur_mux[adc_idx]; - call_update_outputs(codec); - } + if (spec->shared_mic_hp) + update_shared_mic_hp(codec, spec->cur_mux[adc_idx]); if (spec->dyn_adc_switch) { alc_dyn_adc_pcm_resetup(codec, idx); -- cgit v1.2.3 From 5780b627e24113323427c102175296ae43dfb9d7 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 27 Jun 2012 18:45:45 +0200 Subject: ALSA: hda - give 3-pin jack the name "Headphone Mic Jack" This 3-pin jack was labeled "Headphone Jack", but it could also be used as a mic jack just by switching "Input Source". Therefore we need to call the jack something else, to make sure PulseAudio can use the speaker together with the external mic. (PulseAudio might mute the speaker if it detects a headphone being plugged in.) Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 40dda2a83774..f912d74438a6 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2001,13 +2001,31 @@ static int __alc_build_controls(struct hda_codec *codec) return 0; } -static int alc_build_controls(struct hda_codec *codec) +static int alc_build_jacks(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + + if (spec->shared_mic_hp) { + int err; + int nid = spec->autocfg.inputs[1].pin; + err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0); + if (err < 0) + return err; + err = snd_hda_jack_detect_enable(codec, nid, 0); + if (err < 0) + return err; + } + + return snd_hda_jack_add_kctls(codec, &spec->autocfg); +} + +static int alc_build_controls(struct hda_codec *codec) +{ int err = __alc_build_controls(codec); if (err < 0) return err; - err = snd_hda_jack_add_kctls(codec, &spec->autocfg); + + err = alc_build_jacks(codec); if (err < 0) return err; alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD); -- cgit v1.2.3 From 0920c9b4c4d896025a560e4510d473dfd41c3dcd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 3 Jul 2012 16:58:48 +0200 Subject: ALSA: hda - Remove beep_mode=2 The beep_mode=2 option was introduced to make the beep mixer controlling the beep input allocation/deallocation dynamically, so that a user can switch between HD-audio codec digital beep and the system beep only via mixer API. This was necessary because the keyboard driver took only the first input beep instance at that time. However, the recent keyboard driver already processes the multiple input instances, thus there is no point to keep this mode. Let's remove it. Acked-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 3 +- sound/pci/hda/Kconfig | 7 ++--- sound/pci/hda/hda_beep.c | 37 +------------------------ sound/pci/hda/hda_beep.h | 4 --- sound/pci/hda/hda_intel.c | 6 ++-- 5 files changed, 8 insertions(+), 49 deletions(-) (limited to 'sound') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 221b81016dba..4e4d0bc9816f 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -875,8 +875,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. setup before initializing the codecs. This option is available only when CONFIG_SND_HDA_PATCH_LOADER=y is set. See HD-Audio.txt for details. - beep_mode - Selects the beep registration mode (0=off, 1=on, 2= - dynamic registration via mute switch on/off); the default + beep_mode - Selects the beep registration mode (0=off, 1=on); default value is set via CONFIG_SND_HDA_INPUT_BEEP_MODE kconfig. [Single (global) options] diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index d03079764189..194d625c1f83 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -53,15 +53,14 @@ config SND_HDA_INPUT_BEEP driver. This interface is used to generate digital beeps. config SND_HDA_INPUT_BEEP_MODE - int "Digital beep registration mode (0=off, 1=on, 2=mute sw on/off)" + int "Digital beep registration mode (0=off, 1=on)" depends on SND_HDA_INPUT_BEEP=y default "1" - range 0 2 + range 0 1 help Set 0 to disable the digital beep interface for HD-audio by default. Set 1 to always enable the digital beep interface for HD-audio by - default. Set 2 to control the beep device registration to input - layer using a "Beep Switch" in mixer applications. + default. config SND_HDA_INPUT_JACK bool "Support jack plugging notification via input layer" diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 60738e52b8f9..662de6e58b6f 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -162,28 +162,6 @@ static int snd_hda_do_attach(struct hda_beep *beep) return 0; } -static void snd_hda_do_register(struct work_struct *work) -{ - struct hda_beep *beep = - container_of(work, struct hda_beep, register_work); - - mutex_lock(&beep->mutex); - if (beep->enabled && !beep->dev) - snd_hda_do_attach(beep); - mutex_unlock(&beep->mutex); -} - -static void snd_hda_do_unregister(struct work_struct *work) -{ - struct hda_beep *beep = - container_of(work, struct hda_beep, unregister_work.work); - - mutex_lock(&beep->mutex); - if (!beep->enabled && beep->dev) - snd_hda_do_detach(beep); - mutex_unlock(&beep->mutex); -} - int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) { struct hda_beep *beep = codec->beep; @@ -197,15 +175,6 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) snd_hda_codec_write(beep->codec, beep->nid, 0, AC_VERB_SET_BEEP_CONTROL, 0); } - if (beep->mode == HDA_BEEP_MODE_SWREG) { - if (enable) { - cancel_delayed_work(&beep->unregister_work); - schedule_work(&beep->register_work); - } else { - schedule_delayed_work(&beep->unregister_work, - HZ); - } - } return 1; } return 0; @@ -235,12 +204,10 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) beep->mode = codec->beep_mode; codec->beep = beep; - INIT_WORK(&beep->register_work, &snd_hda_do_register); - INIT_DELAYED_WORK(&beep->unregister_work, &snd_hda_do_unregister); INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); mutex_init(&beep->mutex); - if (beep->mode == HDA_BEEP_MODE_ON) { + if (beep->mode) { int err = snd_hda_do_attach(beep); if (err < 0) { kfree(beep); @@ -257,8 +224,6 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) { struct hda_beep *beep = codec->beep; if (beep) { - cancel_work_sync(&beep->register_work); - cancel_delayed_work(&beep->unregister_work); if (beep->dev) snd_hda_do_detach(beep); codec->beep = NULL; diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index 55f0647458c7..30e79d16f9f8 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -26,7 +26,6 @@ #define HDA_BEEP_MODE_OFF 0 #define HDA_BEEP_MODE_ON 1 -#define HDA_BEEP_MODE_SWREG 2 /* beep information */ struct hda_beep { @@ -37,10 +36,7 @@ struct hda_beep { int tone; hda_nid_t nid; unsigned int enabled:1; - unsigned int request_enable:1; unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ - struct work_struct register_work; /* registration work */ - struct delayed_work unregister_work; /* unregistration work */ struct work_struct beep_work; /* scheduled task for beep event */ struct mutex mutex; }; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 7757536b9d5f..334c0ba7d04b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -72,7 +72,7 @@ static int enable_msi = -1; static char *patch[SNDRV_CARDS]; #endif #ifdef CONFIG_SND_HDA_INPUT_BEEP -static int beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = +static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = CONFIG_SND_HDA_INPUT_BEEP_MODE}; #endif @@ -103,9 +103,9 @@ module_param_array(patch, charp, NULL, 0444); MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface."); #endif #ifdef CONFIG_SND_HDA_INPUT_BEEP -module_param_array(beep_mode, int, NULL, 0444); +module_param_array(beep_mode, bool, NULL, 0444); MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " - "(0=off, 1=on, 2=mute switch on/off) (default=1)."); + "(0=off, 1=on) (default=1)."); #endif #ifdef CONFIG_SND_HDA_POWER_SAVE -- cgit v1.2.3 From 0401e8548eace5bdb8adfa3e82f56165982cb3ad Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 3 Jul 2012 17:27:57 +0200 Subject: ALSA: hda - Move beep helper functions to hda_beep.c Move snd_hda_mixer_amp_switch_put_beep() to hda_beep.c as a clean up to remove one more ifdef. Also add the corresponding get callback to return consistently the digital beep state independently from the mixer amp value. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.c | 28 ++++++++++++++++++++++++++++ sound/pci/hda/hda_codec.c | 19 ------------------- sound/pci/hda/hda_local.h | 4 +++- 3 files changed, 31 insertions(+), 20 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 662de6e58b6f..336b4b3a80b9 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -231,3 +231,31 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) } } EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); + +/* get/put callbacks for beep mute mixer switches */ +int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct hda_beep *beep = codec->beep; + if (beep) { + ucontrol->value.integer.value[0] = + ucontrol->value.integer.value[1] = + beep->enabled; + return 0; + } + return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); +} +EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get_beep); + +int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct hda_beep *beep = codec->beep; + if (beep) + snd_hda_enable_beep_device(codec, + *ucontrol->value.integer.value); + return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); +} +EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 51cb2a2e4fce..ddac4288615d 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2676,25 +2676,6 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put); -#ifdef CONFIG_SND_HDA_INPUT_BEEP -/** - * snd_hda_mixer_amp_switch_put_beep - Put callback for a beep AMP switch - * - * This function calls snd_hda_enable_beep_device(), which behaves differently - * depending on beep_mode option. - */ -int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - long *valp = ucontrol->value.integer.value; - - snd_hda_enable_beep_device(codec, *valp); - return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep); -#endif /* CONFIG_SND_HDA_INPUT_BEEP */ - /* * bound volume controls * diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 9a096a8e0fc5..1b4c12941baa 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -89,7 +89,7 @@ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ .subdevice = HDA_SUBDEV_AMP_FLAG, \ .info = snd_hda_mixer_amp_switch_info, \ - .get = snd_hda_mixer_amp_switch_get, \ + .get = snd_hda_mixer_amp_switch_get_beep, \ .put = snd_hda_mixer_amp_switch_put_beep, \ .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } #else @@ -121,6 +121,8 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); #ifdef CONFIG_SND_HDA_INPUT_BEEP +int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); #endif -- cgit v1.2.3 From 257dfb410070b48e377c7894222b73ca41d662e0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 3 Jul 2012 17:35:05 +0200 Subject: ALSA: hda - Get rid of superfluous beep->mode field It's no longer necessary since beep_mode=2 option was dropped. It can be checked simply via codec->beep != NULL. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.c | 14 ++++++-------- sound/pci/hda/hda_beep.h | 1 - 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 336b4b3a80b9..e6cf2a22c407 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -184,6 +184,7 @@ EXPORT_SYMBOL_HDA(snd_hda_enable_beep_device); int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) { struct hda_beep *beep; + int err; if (!snd_hda_get_bool_hint(codec, "beep")) return 0; /* disabled explicitly by hints */ @@ -201,19 +202,16 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) beep->nid = nid; beep->codec = codec; - beep->mode = codec->beep_mode; codec->beep = beep; INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); mutex_init(&beep->mutex); - if (beep->mode) { - int err = snd_hda_do_attach(beep); - if (err < 0) { - kfree(beep); - codec->beep = NULL; - return err; - } + err = snd_hda_do_attach(beep); + if (err < 0) { + kfree(beep); + codec->beep = NULL; + return err; } return 0; diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index 30e79d16f9f8..4dc6933bc655 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -31,7 +31,6 @@ struct hda_beep { struct input_dev *dev; struct hda_codec *codec; - unsigned int mode; char phys[32]; int tone; hda_nid_t nid; -- cgit v1.2.3 From 3fd877d32cac31292628fb8f443543fc1989b49b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 3 Jul 2012 17:36:35 +0200 Subject: ALSA: hda - Avoid possible race of beep on/off Call cancel_work_sync() when turning off the beep switch so that the mute call is executed in a proper order. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index e6cf2a22c407..0bc2315b181d 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -165,12 +165,13 @@ static int snd_hda_do_attach(struct hda_beep *beep) int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) { struct hda_beep *beep = codec->beep; - enable = !!enable; - if (beep == NULL) + if (!beep) return 0; + enable = !!enable; if (beep->enabled != enable) { beep->enabled = enable; if (!enable) { + cancel_work_sync(&beep->beep_work); /* turn off beep */ snd_hda_codec_write(beep->codec, beep->nid, 0, AC_VERB_SET_BEEP_CONTROL, 0); -- cgit v1.2.3 From a7a0a64daba5105215b79fe27b2d1ebbdcf5eebb Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Thu, 5 Jul 2012 12:00:12 +0200 Subject: ALSA: hda - Always call standard unsolicited event for Realtek codecs With the model parsers out of the way, we have no custom unsol events to worry about, we can therefore simplify the code. In addition, this fixes a bug on the ASUS TC710, which has only a headphone jack and a mic jack, but no internal mic or speakers. Therefore the unsol_event pointer was not set, and as a result, the jack kcontrols were not correctly updated. BugLink: https://bugs.launchpad.net/bugs/1021192 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f912d74438a6..a5b0b50b6a92 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -174,7 +174,6 @@ struct alc_spec { /* hooks */ void (*init_hook)(struct hda_codec *codec); - void (*unsol_event)(struct hda_codec *codec, unsigned int res); #ifdef CONFIG_SND_HDA_POWER_SAVE void (*power_hook)(struct hda_codec *codec); #endif @@ -688,7 +687,7 @@ static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid) } /* unsolicited event for HP jack sensing */ -static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) +static void alc_unsol_event(struct hda_codec *codec, unsigned int res) { int action; @@ -1024,11 +1023,9 @@ static void alc_init_automute(struct hda_codec *codec) spec->automute_lo = spec->automute_lo_possible; spec->automute_speaker = spec->automute_speaker_possible; - if (spec->automute_speaker_possible || spec->automute_lo_possible) { + if (spec->automute_speaker_possible || spec->automute_lo_possible) /* create a control for automute mode */ alc_add_automute_mode_enum(codec); - spec->unsol_event = alc_sku_unsol_event; - } } /* return the position of NID in the list, or -1 if not found */ @@ -1191,7 +1188,6 @@ static void alc_init_auto_mic(struct hda_codec *codec) snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n", ext, fixed, dock); - spec->unsol_event = alc_sku_unsol_event; } /* check the availabilities of auto-mute and auto-mic switches */ @@ -2062,14 +2058,6 @@ static int alc_init(struct hda_codec *codec) return 0; } -static void alc_unsol_event(struct hda_codec *codec, unsigned int res) -{ - struct alc_spec *spec = codec->spec; - - if (spec->unsol_event) - spec->unsol_event(codec, res); -} - #ifdef CONFIG_SND_HDA_POWER_SAVE static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid) { @@ -4271,14 +4259,12 @@ static void set_capture_mixer(struct hda_codec *codec) */ static void alc_auto_init_std(struct hda_codec *codec) { - struct alc_spec *spec = codec->spec; alc_auto_init_multi_out(codec); alc_auto_init_extra_out(codec); alc_auto_init_analog_input(codec); alc_auto_init_input_src(codec); alc_auto_init_digital(codec); - if (spec->unsol_event) - alc_inithook(codec); + alc_inithook(codec); } /* @@ -4879,7 +4865,6 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, spec->automute_speaker = 1; spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT); - spec->unsol_event = alc_sku_unsol_event; snd_hda_gen_add_verbs(&spec->gen, alc_gpio1_init_verbs); } } -- cgit v1.2.3 From e926f2c850c472f813f9bab486c68a3fe0b03ae4 Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Wed, 13 Jun 2012 10:23:51 +0800 Subject: ALSA: hda - Add DeviceID for Haswell HDA this patch add proper id for Haswell HDA Controller. [Added AZX_DCAPS_POSFIX_COMBO flag by tiwai] Signed-off-by: Wang Xingchao Acked-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 796472d1ff5a..238653d55868 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -151,6 +151,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{Intel, CPT}," "{Intel, PPT}," "{Intel, LPT}," + "{Intel, HPT}," "{Intel, PBG}," "{Intel, SCH}," "{ATI, SB450}," @@ -3261,6 +3262,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(0x8086, 0x8c20), .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, + /* Haswell */ + { PCI_DEVICE(0x8086, 0x0c0c), + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, /* SCH */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | -- cgit v1.2.3 From 1c76684d2752b3a24bb7da183cc18e5d126dbcc9 Mon Sep 17 00:00:00 2001 From: Wang Xingchao Date: Wed, 13 Jun 2012 10:23:52 +0800 Subject: ALSA: hda - add Haswell HDMI codec id 0x80862807 is HDMI id for Haswell HDA. Signed-off-by: Wang Xingchao Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index d6a8260a6f74..a57cf3665df9 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1927,6 +1927,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, +{ .id = 0x80862807, .name = "Haswell HDMI", .patch = patch_generic_hdmi }, { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, {} /* terminator */ @@ -1978,6 +1979,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862803"); MODULE_ALIAS("snd-hda-codec-id:80862804"); MODULE_ALIAS("snd-hda-codec-id:80862805"); MODULE_ALIAS("snd-hda-codec-id:80862806"); +MODULE_ALIAS("snd-hda-codec-id:80862807"); MODULE_ALIAS("snd-hda-codec-id:80862880"); MODULE_ALIAS("snd-hda-codec-id:808629fb"); -- cgit v1.2.3 From bdbe34dece4942f4d8df9865dba7785bb813366a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 16 Jul 2012 16:17:10 +0200 Subject: ALSA: hda - Fix driver type of Haswell controller to AZX_DRIVER_SCH According to Xingchao, This works for HDMI audio, otherwise there's blocking issue. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 238653d55868..b4f3c7295a53 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -3264,7 +3264,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, /* Haswell */ { PCI_DEVICE(0x8086, 0x0c0c), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, /* SCH */ { PCI_DEVICE(0x8086, 0x811b), -- cgit v1.2.3 From 7ae48b56f8d9c836259bc02f3e2ea4962d6b5d1b Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Mon, 16 Jul 2012 17:10:04 -0700 Subject: ALSA: hda - Add new GPU codec ID to snd-hda Vendor ID 0x10de0051 is used by a yet-to-be-named GPU chip. Signed-off-by: Aaron Plattner Acked-by: Andy Ritger Reviewed-by: Daniel Dadap Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index a57cf3665df9..0b4a1ea147c6 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1914,6 +1914,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_generic_hdmi }, { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_generic_hdmi }, { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, +{ .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_generic_hdmi }, { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, @@ -1965,6 +1966,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0041"); MODULE_ALIAS("snd-hda-codec-id:10de0042"); MODULE_ALIAS("snd-hda-codec-id:10de0043"); MODULE_ALIAS("snd-hda-codec-id:10de0044"); +MODULE_ALIAS("snd-hda-codec-id:10de0051"); MODULE_ALIAS("snd-hda-codec-id:10de0067"); MODULE_ALIAS("snd-hda-codec-id:10de8001"); MODULE_ALIAS("snd-hda-codec-id:11069f80"); -- cgit v1.2.3 From f46c329644b1f7144d336fce037dd9f84ee1995f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Jul 2012 16:48:27 +0200 Subject: ALSA: hda - Fix index number conflicts of phantom jacks Since some jack controls may be renamed as phantom jacks, the existing check for index conflicts doesn't work because it simply compares the name with the last used name, assuming that the controls with the same name continue. Thus, it would result in the duplicated controls when two or more phantom jacks with the very same type exist, and the driver gives up with an error. This patch fixes the problem by checking the index number conflicts more intensively (but dumbly). Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_jack.c | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 60c976f06280..aaccc0236bda 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -314,9 +314,28 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, } EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); +/* get the unique index number for the given kctl name */ +static int get_unique_index(struct hda_codec *codec, const char *name, int idx) +{ + struct hda_jack_tbl *jack; + int i, len = strlen(name); + again: + jack = codec->jacktbl.list; + for (i = 0; i < codec->jacktbl.used; i++, jack++) { + /* jack->kctl.id contains "XXX Jack" name string with index */ + if (jack->kctl && + !strncmp(name, jack->kctl->id.name, len) && + !strcmp(" Jack", jack->kctl->id.name + len) && + jack->kctl->id.index == idx) { + idx++; + goto again; + } + } + return idx; +} + static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, - const struct auto_pin_cfg *cfg, - char *lastname, int *lastidx) + const struct auto_pin_cfg *cfg) { unsigned int def_conf, conn; char name[44]; @@ -336,10 +355,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, if (phantom_jack) /* Example final name: "Internal Mic Phantom Jack" */ strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); - if (!strcmp(name, lastname) && idx == *lastidx) - idx++; - strncpy(lastname, name, sizeof(name)); - *lastidx = idx; + idx = get_unique_index(codec, name, idx); err = __snd_hda_jack_add_kctl(codec, nid, name, idx, phantom_jack); if (err < 0) return err; @@ -356,42 +372,41 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { const hda_nid_t *p; - int i, err, lastidx = 0; - char lastname[44] = ""; + int i, err; for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { - err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); + err = add_jack_kctl(codec, *p, cfg); if (err < 0) return err; } for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { if (*p == *cfg->line_out_pins) /* might be duplicated */ break; - err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); + err = add_jack_kctl(codec, *p, cfg); if (err < 0) return err; } for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { if (*p == *cfg->line_out_pins) /* might be duplicated */ break; - err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); + err = add_jack_kctl(codec, *p, cfg); if (err < 0) return err; } for (i = 0; i < cfg->num_inputs; i++) { - err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx); + err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg); if (err < 0) return err; } for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { - err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); + err = add_jack_kctl(codec, *p, cfg); if (err < 0) return err; } - err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx); + err = add_jack_kctl(codec, cfg->dig_in_pin, cfg); if (err < 0) return err; - err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx); + err = add_jack_kctl(codec, cfg->mono_out_pin, cfg); if (err < 0) return err; return 0; -- cgit v1.2.3 From 4e01ec636e64707d202a1ca21a47bbc6d53085b7 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 18 Jul 2012 07:38:46 +0200 Subject: ALSA: hda - Add support for Realtek ALC282 This codec has a separate dmic path (separate dmic only ADC), and thus it looks mostly like ALC275. Cc: stable@kernel.org BugLink: https://bugs.launchpad.net/bugs/1025377 Tested-by: Ray Chen Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a5b0b50b6a92..aef31392aee1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6988,6 +6988,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 }, { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 }, { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, + { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", .patch = patch_alc861 }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, -- cgit v1.2.3