Commit 81ad969d authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/hda' into for-linus

* topic/hda: (51 commits)
  ALSA: hda - Fix the previous tagra-8ch patch
  ALSA: hda - Add 7.1 support for MSI GX620
  ALSA: support Sony Vaio TT
  ALSA: hda_intel: fix build error when !PM
  ALSA: hda - More Aspire 8930G fixes
  ALSA: hda - Acer Aspire 8930G support
  ALSA: hda - Limit codec-verb retry to limited hardwares
  ALSA: hda - Add codec bus reset and verb-retry at critical errors
  ALSA: hda - Reorder and clean-up ALC268 quirk table
  ALSA: hda - fix audio on LG R510
  ALSA: hda - Macbook[Pro] 5 6ch support
  ALSA: hda-intel: improve initialization for ALC262_HP_BPC model
  ALSA: hda - Jack Mode changes for Sigmatel boards
  ALSA: hda - Support NVIDIA 8 channel HDMI audio
  ALSA: hda - Fix a typo in the previous patch
  ALSA: hda - Fix reverted LED setup for HP
  ALSA: hda - Add more register bits definitions
  ALSA: hda - Always sync writes in single_cmd mode
  ALSA: hda - Support sync after writing a verb
  ALSA: hda - Allow concurrent RIRB access in single_cmd mode
  ...
parents 2f0dabcc f03ecf50
...@@ -36,6 +36,7 @@ ALC260 ...@@ -36,6 +36,7 @@ ALC260
acer Acer TravelMate acer Acer TravelMate
will Will laptops (PB V7900) will Will laptops (PB V7900)
replacer Replacer 672V replacer Replacer 672V
favorit100 Maxdata Favorit 100XS
basic fixed pin assignment (old default model) basic fixed pin assignment (old default model)
test for testing/debugging purpose, almost all controls can test for testing/debugging purpose, almost all controls can
adjusted. Appearing only when compiled with adjusted. Appearing only when compiled with
...@@ -85,10 +86,11 @@ ALC269 ...@@ -85,10 +86,11 @@ ALC269
eeepc-p703 ASUS Eeepc P703 P900A eeepc-p703 ASUS Eeepc P703 P900A
eeepc-p901 ASUS Eeepc P901 S101 eeepc-p901 ASUS Eeepc P901 S101
fujitsu FSC Amilo fujitsu FSC Amilo
lifebook Fujitsu Lifebook S6420
auto auto-config reading BIOS (default) auto auto-config reading BIOS (default)
ALC662/663 ALC662/663/272
========== ==============
3stack-dig 3-stack (2-channel) with SPDIF 3stack-dig 3-stack (2-channel) with SPDIF
3stack-6ch 3-stack (6-channel) 3stack-6ch 3-stack (6-channel)
3stack-6ch-dig 3-stack (6-channel) with SPDIF 3stack-6ch-dig 3-stack (6-channel) with SPDIF
...@@ -107,6 +109,9 @@ ALC662/663 ...@@ -107,6 +109,9 @@ ALC662/663
asus-mode4 ASUS asus-mode4 ASUS
asus-mode5 ASUS asus-mode5 ASUS
asus-mode6 ASUS asus-mode6 ASUS
dell Dell with ALC272
dell-zm1 Dell ZM1 with ALC272
samsung-nc10 Samsung NC10 mini notebook
auto auto-config reading BIOS (default) auto auto-config reading BIOS (default)
ALC882/885 ALC882/885
...@@ -118,6 +123,7 @@ ALC882/885 ...@@ -118,6 +123,7 @@ ALC882/885
asus-a7j ASUS A7J asus-a7j ASUS A7J
asus-a7m ASUS A7M asus-a7m ASUS A7M
macpro MacPro support macpro MacPro support
mb5 Macbook 5,1
mbp3 Macbook Pro rev3 mbp3 Macbook Pro rev3
imac24 iMac 24'' with jack detection imac24 iMac 24'' with jack detection
w2jc ASUS W2JC w2jc ASUS W2JC
...@@ -133,10 +139,12 @@ ALC883/888 ...@@ -133,10 +139,12 @@ ALC883/888
acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc) acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
acer-aspire Acer Aspire 9810 acer-aspire Acer Aspire 9810
acer-aspire-4930g Acer Aspire 4930G acer-aspire-4930g Acer Aspire 4930G
acer-aspire-8930g Acer Aspire 8930G
medion Medion Laptops medion Medion Laptops
medion-md2 Medion MD2 medion-md2 Medion MD2
targa-dig Targa/MSI targa-dig Targa/MSI
targa-2ch-dig Targs/MSI with 2-channel targa-2ch-dig Targa/MSI with 2-channel
targa-8ch-dig Targa/MSI with 8-channel (MSI GX620)
laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE) laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
lenovo-101e Lenovo 101E lenovo-101e Lenovo 101E
lenovo-nb0763 Lenovo NB0763 lenovo-nb0763 Lenovo NB0763
...@@ -150,6 +158,9 @@ ALC883/888 ...@@ -150,6 +158,9 @@ ALC883/888
fujitsu-pi2515 Fujitsu AMILO Pi2515 fujitsu-pi2515 Fujitsu AMILO Pi2515
fujitsu-xa3530 Fujitsu AMILO XA3530 fujitsu-xa3530 Fujitsu AMILO XA3530
3stack-6ch-intel Intel DG33* boards 3stack-6ch-intel Intel DG33* boards
asus-p5q ASUS P5Q-EM boards
mb31 MacBook 3,1
sony-vaio-tt Sony VAIO TT
auto auto-config reading BIOS (default) auto auto-config reading BIOS (default)
ALC861/660 ALC861/660
...@@ -348,6 +359,7 @@ STAC92HD71B* ...@@ -348,6 +359,7 @@ STAC92HD71B*
hp-m4 HP mini 1000 hp-m4 HP mini 1000
hp-dv5 HP dv series hp-dv5 HP dv series
hp-hdx HP HDX series hp-hdx HP HDX series
hp-dv4-1222nr HP dv4-1222nr (with LED support)
auto BIOS setup (default) auto BIOS setup (default)
STAC92HD73* STAC92HD73*
......
...@@ -139,6 +139,19 @@ config SND_HDA_CODEC_CONEXANT ...@@ -139,6 +139,19 @@ config SND_HDA_CODEC_CONEXANT
snd-hda-codec-conexant. snd-hda-codec-conexant.
This module is automatically loaded at probing. This module is automatically loaded at probing.
config SND_HDA_CODEC_CA0110
bool "Build Creative CA0110-IBG codec support"
depends on SND_HDA_INTEL
default y
help
Say Y here to include Creative CA0110-IBG codec support in
snd-hda-intel driver, found on some Creative X-Fi cards.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
snd-hda-codec-ca0110.
This module is automatically loaded at probing.
config SND_HDA_CODEC_CMEDIA config SND_HDA_CODEC_CMEDIA
bool "Build C-Media HD-audio codec support" bool "Build C-Media HD-audio codec support"
default y default y
......
...@@ -13,6 +13,7 @@ snd-hda-codec-analog-objs := patch_analog.o ...@@ -13,6 +13,7 @@ snd-hda-codec-analog-objs := patch_analog.o
snd-hda-codec-idt-objs := patch_sigmatel.o snd-hda-codec-idt-objs := patch_sigmatel.o
snd-hda-codec-si3054-objs := patch_si3054.o snd-hda-codec-si3054-objs := patch_si3054.o
snd-hda-codec-atihdmi-objs := patch_atihdmi.o snd-hda-codec-atihdmi-objs := patch_atihdmi.o
snd-hda-codec-ca0110-objs := patch_ca0110.o
snd-hda-codec-conexant-objs := patch_conexant.o snd-hda-codec-conexant-objs := patch_conexant.o
snd-hda-codec-via-objs := patch_via.o snd-hda-codec-via-objs := patch_via.o
snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o
...@@ -40,6 +41,9 @@ endif ...@@ -40,6 +41,9 @@ endif
ifdef CONFIG_SND_HDA_CODEC_ATIHDMI ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-atihdmi.o obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-atihdmi.o
endif endif
ifdef CONFIG_SND_HDA_CODEC_CA0110
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-ca0110.o
endif
ifdef CONFIG_SND_HDA_CODEC_CONEXANT ifdef CONFIG_SND_HDA_CODEC_CONEXANT
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-conexant.o obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-conexant.o
endif endif
......
...@@ -45,16 +45,15 @@ static void snd_hda_generate_beep(struct work_struct *work) ...@@ -45,16 +45,15 @@ static void snd_hda_generate_beep(struct work_struct *work)
AC_VERB_SET_BEEP_CONTROL, beep->tone); AC_VERB_SET_BEEP_CONTROL, beep->tone);
} }
static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, /* (non-standard) Linear beep tone calculation for IDT/STAC codecs
unsigned int code, int hz) *
* The tone frequency of beep generator on IDT/STAC codecs is
* defined from the 8bit tone parameter, in Hz,
* freq = 48000 * (257 - tone) / 1024
* that is from 12kHz to 93.75kHz in step of 46.875 hz
*/
static int beep_linear_tone(struct hda_beep *beep, int hz)
{ {
struct hda_beep *beep = input_get_drvdata(dev);
switch (code) {
case SND_BELL:
if (hz)
hz = 1000;
case SND_TONE:
hz *= 1000; /* fixed point */ hz *= 1000; /* fixed point */
hz = hz - DIGBEEP_HZ_MIN; hz = hz - DIGBEEP_HZ_MIN;
if (hz < 0) if (hz < 0)
...@@ -65,11 +64,45 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, ...@@ -65,11 +64,45 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
hz /= DIGBEEP_HZ_STEP; hz /= DIGBEEP_HZ_STEP;
hz++; hz++;
} }
return hz;
}
/* HD-audio standard beep tone parameter calculation
*
* The tone frequency in Hz is calculated as
* freq = 48000 / (tone * 4)
* from 47Hz to 12kHz
*/
static int beep_standard_tone(struct hda_beep *beep, int hz)
{
if (hz <= 0)
return 0; /* disabled */
hz = 12000 / hz;
if (hz > 0xff)
return 0xff;
if (hz <= 0)
return 1;
return hz;
}
static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
unsigned int code, int hz)
{
struct hda_beep *beep = input_get_drvdata(dev);
switch (code) {
case SND_BELL:
if (hz)
hz = 1000;
case SND_TONE:
if (beep->linear_tone)
beep->tone = beep_linear_tone(beep, hz);
else
beep->tone = beep_standard_tone(beep, hz);
break; break;
default: default:
return -1; return -1;
} }
beep->tone = hz;
/* schedule beep event */ /* schedule beep event */
schedule_work(&beep->beep_work); schedule_work(&beep->beep_work);
......
...@@ -30,8 +30,9 @@ struct hda_beep { ...@@ -30,8 +30,9 @@ struct hda_beep {
struct hda_codec *codec; struct hda_codec *codec;
char phys[32]; char phys[32];
int tone; int tone;
int nid; hda_nid_t nid;
int enabled; unsigned int enabled:1;
unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
struct work_struct beep_work; /* scheduled task for beep event */ struct work_struct beep_work; /* scheduled task for beep event */
}; };
......
This diff is collapsed.
...@@ -574,6 +574,8 @@ struct hda_bus_ops { ...@@ -574,6 +574,8 @@ struct hda_bus_ops {
/* attach a PCM stream */ /* attach a PCM stream */
int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec, int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec,
struct hda_pcm *pcm); struct hda_pcm *pcm);
/* reset bus for retry verb */
void (*bus_reset)(struct hda_bus *bus);
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
/* notify power-up/down from codec to controller */ /* notify power-up/down from codec to controller */
void (*pm_notify)(struct hda_bus *bus); void (*pm_notify)(struct hda_bus *bus);
...@@ -622,7 +624,13 @@ struct hda_bus { ...@@ -622,7 +624,13 @@ struct hda_bus {
/* misc op flags */ /* misc op flags */
unsigned int needs_damn_long_delay :1; unsigned int needs_damn_long_delay :1;
unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */
unsigned int sync_write:1; /* sync after verb write */
/* status for codec/controller */
unsigned int shutdown :1; /* being unloaded */ unsigned int shutdown :1; /* being unloaded */
unsigned int rirb_error:1; /* error in codec communication */
unsigned int response_reset:1; /* controller was reset */
unsigned int in_reset:1; /* during reset operation */
}; };
/* /*
...@@ -747,7 +755,8 @@ struct hda_codec { ...@@ -747,7 +755,8 @@ struct hda_codec {
/* detected preset */ /* detected preset */
const struct hda_codec_preset *preset; const struct hda_codec_preset *preset;
struct module *owner; struct module *owner;
const char *name; /* codec name */ const char *vendor_name; /* codec vendor name */
const char *chip_name; /* codec chip name */
const char *modelname; /* model name for preset */ const char *modelname; /* model name for preset */
/* set by patch */ /* set by patch */
...@@ -905,7 +914,7 @@ void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen); ...@@ -905,7 +914,7 @@ void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen);
* power management * power management
*/ */
#ifdef CONFIG_PM #ifdef CONFIG_PM
int snd_hda_suspend(struct hda_bus *bus, pm_message_t state); int snd_hda_suspend(struct hda_bus *bus);
int snd_hda_resume(struct hda_bus *bus); int snd_hda_resume(struct hda_bus *bus);
#endif #endif
......
...@@ -242,7 +242,8 @@ CODEC_INFO_SHOW(subsystem_id); ...@@ -242,7 +242,8 @@ CODEC_INFO_SHOW(subsystem_id);
CODEC_INFO_SHOW(revision_id); CODEC_INFO_SHOW(revision_id);
CODEC_INFO_SHOW(afg); CODEC_INFO_SHOW(afg);
CODEC_INFO_SHOW(mfg); CODEC_INFO_SHOW(mfg);
CODEC_INFO_STR_SHOW(name); CODEC_INFO_STR_SHOW(vendor_name);
CODEC_INFO_STR_SHOW(chip_name);
CODEC_INFO_STR_SHOW(modelname); CODEC_INFO_STR_SHOW(modelname);
#define CODEC_INFO_STORE(type) \ #define CODEC_INFO_STORE(type) \
...@@ -275,7 +276,8 @@ static ssize_t type##_store(struct device *dev, \ ...@@ -275,7 +276,8 @@ static ssize_t type##_store(struct device *dev, \
CODEC_INFO_STORE(vendor_id); CODEC_INFO_STORE(vendor_id);
CODEC_INFO_STORE(subsystem_id); CODEC_INFO_STORE(subsystem_id);
CODEC_INFO_STORE(revision_id); CODEC_INFO_STORE(revision_id);
CODEC_INFO_STR_STORE(name); CODEC_INFO_STR_STORE(vendor_name);
CODEC_INFO_STR_STORE(chip_name);
CODEC_INFO_STR_STORE(modelname); CODEC_INFO_STR_STORE(modelname);
#define CODEC_ACTION_STORE(type) \ #define CODEC_ACTION_STORE(type) \
...@@ -499,7 +501,8 @@ static struct device_attribute codec_attrs[] = { ...@@ -499,7 +501,8 @@ static struct device_attribute codec_attrs[] = {
CODEC_ATTR_RW(revision_id), CODEC_ATTR_RW(revision_id),
CODEC_ATTR_RO(afg), CODEC_ATTR_RO(afg),
CODEC_ATTR_RO(mfg), CODEC_ATTR_RO(mfg),
CODEC_ATTR_RW(name), CODEC_ATTR_RW(vendor_name),
CODEC_ATTR_RW(chip_name),
CODEC_ATTR_RW(modelname), CODEC_ATTR_RW(modelname),
CODEC_ATTR_RW(init_verbs), CODEC_ATTR_RW(init_verbs),
CODEC_ATTR_RW(hints), CODEC_ATTR_RW(hints),
......
This diff is collapsed.
...@@ -466,8 +466,12 @@ static void print_codec_info(struct snd_info_entry *entry, ...@@ -466,8 +466,12 @@ static void print_codec_info(struct snd_info_entry *entry,
hda_nid_t nid; hda_nid_t nid;
int i, nodes; int i, nodes;
snd_iprintf(buffer, "Codec: %s\n", snd_iprintf(buffer, "Codec: ");
codec->name ? codec->name : "Not Set"); if (codec->vendor_name && codec->chip_name)
snd_iprintf(buffer, "%s %s\n",
codec->vendor_name, codec->chip_name);
else
snd_iprintf(buffer, "Not Set\n");
snd_iprintf(buffer, "Address: %d\n", codec->addr); snd_iprintf(buffer, "Address: %d\n", codec->addr);
snd_iprintf(buffer, "Function Id: 0x%x\n", codec->function_id); snd_iprintf(buffer, "Function Id: 0x%x\n", codec->function_id);
snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id); snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id);
......
This diff is collapsed.
...@@ -35,9 +35,28 @@ struct nvhdmi_spec { ...@@ -35,9 +35,28 @@ struct nvhdmi_spec {
struct hda_pcm pcm_rec; struct hda_pcm pcm_rec;
}; };
#define Nv_VERB_SET_Channel_Allocation 0xF79
#define Nv_VERB_SET_Info_Frame_Checksum 0xF7A
#define Nv_VERB_SET_Audio_Protection_On 0xF98
#define Nv_VERB_SET_Audio_Protection_Off 0xF99
#define Nv_Master_Convert_nid 0x04
#define Nv_Master_Pin_nid 0x05
static hda_nid_t nvhdmi_convert_nids[4] = {
/*front, rear, clfe, rear_surr */
0x6, 0x8, 0xa, 0xc,
};
static struct hda_verb nvhdmi_basic_init[] = { static struct hda_verb nvhdmi_basic_init[] = {
/* set audio protect on */
{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
/* enable digital output on pin widget */ /* enable digital output on pin widget */
{ 0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
{ 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
{ 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
{ 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
{ 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
{} /* terminator */ {} /* terminator */
}; };
...@@ -73,7 +92,28 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, ...@@ -73,7 +92,28 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
return snd_hda_multi_out_dig_open(codec, &spec->multiout); return snd_hda_multi_out_dig_open(codec, &spec->multiout);
} }
static int nvhdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream)
{
struct nvhdmi_spec *spec = codec->spec;
int i;
snd_hda_codec_write(codec, Nv_Master_Convert_nid,
0, AC_VERB_SET_CHANNEL_STREAMID, 0);
for (i = 0; i < 4; i++) {
/* set the stream id */
snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
AC_VERB_SET_CHANNEL_STREAMID, 0);
/* set the stream format */
snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
AC_VERB_SET_STREAM_FORMAT, 0);
}
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
}
static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo,
struct hda_codec *codec, struct hda_codec *codec,
struct snd_pcm_substream *substream) struct snd_pcm_substream *substream)
{ {
...@@ -81,7 +121,128 @@ static int nvhdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, ...@@ -81,7 +121,128 @@ static int nvhdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
return snd_hda_multi_out_dig_close(codec, &spec->multiout); return snd_hda_multi_out_dig_close(codec, &spec->multiout);
} }
static int nvhdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
struct snd_pcm_substream *substream)
{
int chs;
unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id;
int i;
mutex_lock(&codec->spdif_mutex);
chs = substream->runtime->channels;
chan = chs ? (chs - 1) : 1;
switch (chs) {
default:
case 0:
case 2:
chanmask = 0x00;
break;
case 4:
chanmask = 0x08;
break;
case 6:
chanmask = 0x0b;
break;
case 8:
chanmask = 0x13;
break;
}
dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
dataDCC2 = 0x2;
/* set the Audio InforFrame Channel Allocation */
snd_hda_codec_write(codec, 0x1, 0,
Nv_VERB_SET_Channel_Allocation, chanmask);
/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
snd_hda_codec_write(codec,
Nv_Master_Convert_nid,
0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
/* set the stream id */
snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
/* set the stream format */
snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
AC_VERB_SET_STREAM_FORMAT, format);
/* turn on again (if needed) */
/* enable and set the channel status audio/data flag */
if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
snd_hda_codec_write(codec,
Nv_Master_Convert_nid,
0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & 0xff);
snd_hda_codec_write(codec,
Nv_Master_Convert_nid,
0,
AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
}
for (i = 0; i < 4; i++) {
if (chs == 2)
channel_id = 0;
else
channel_id = i * 2;
/* turn off SPDIF once;
*otherwise the IEC958 bits won't be updated
*/
if (codec->spdif_status_reset &&
(codec->spdif_ctls & AC_DIG1_ENABLE))
snd_hda_codec_write(codec,
nvhdmi_convert_nids[i],
0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
/* set the stream id */
snd_hda_codec_write(codec,
nvhdmi_convert_nids[i],
0,
AC_VERB_SET_CHANNEL_STREAMID,
(stream_tag << 4) | channel_id);
/* set the stream format */
snd_hda_codec_write(codec,
nvhdmi_convert_nids[i],
0,
AC_VERB_SET_STREAM_FORMAT,
format);
/* turn on again (if needed) */
/* enable and set the channel status audio/data flag */
if (codec->spdif_status_reset &&
(codec->spdif_ctls & AC_DIG1_ENABLE)) {
snd_hda_codec_write(codec,
nvhdmi_convert_nids[i],
0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & 0xff);
snd_hda_codec_write(codec,
nvhdmi_convert_nids[i],
0,
AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
}
}
/* set the Audio Info Frame Checksum */
snd_hda_codec_write(codec, 0x1, 0,
Nv_VERB_SET_Info_Frame_Checksum,
(0x71 - chan - chanmask));
mutex_unlock(&codec->spdif_mutex);
return 0;
}
static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
struct hda_codec *codec, struct hda_codec *codec,
unsigned int stream_tag, unsigned int stream_tag,
unsigned int format, unsigned int format,
...@@ -92,22 +253,37 @@ static int nvhdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, ...@@ -92,22 +253,37 @@ static int nvhdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
format, substream); format, substream);
} }
static struct hda_pcm_stream nvhdmi_pcm_digital_playback = { static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = {
.substreams = 1,
.channels_min = 2,
.channels_max = 8,
.nid = Nv_Master_Convert_nid,
.rates = SNDRV_PCM_RATE_48000,
.maxbps = 16,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.ops = {
.open = nvhdmi_dig_playback_pcm_open,
.close = nvhdmi_dig_playback_pcm_close_8ch,
.prepare = nvhdmi_dig_playback_pcm_prepare_8ch
},
};
static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
.substreams = 1, .substreams = 1,
.channels_min = 2, .channels_min = 2,
.channels_max = 2, .channels_max = 2,
.nid = 0x4, /* NID to query formats and rates and setup streams */ .nid = Nv_Master_Convert_nid,
.rates = SNDRV_PCM_RATE_48000, .rates = SNDRV_PCM_RATE_48000,
.maxbps = 16, .maxbps = 16,
.formats = SNDRV_PCM_FMTBIT_S16_LE, .formats = SNDRV_PCM_FMTBIT_S16_LE,
.ops = { .ops = {
.open = nvhdmi_dig_playback_pcm_open, .open = nvhdmi_dig_playback_pcm_open,
.close = nvhdmi_dig_playback_pcm_close, .close = nvhdmi_dig_playback_pcm_close_2ch,
.prepare = nvhdmi_dig_playback_pcm_prepare .prepare = nvhdmi_dig_playback_pcm_prepare_2ch
}, },
}; };
static int nvhdmi_build_pcms(struct hda_codec *codec) static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
{ {
struct nvhdmi_spec *spec = codec->spec; struct nvhdmi_spec *spec = codec->spec;
struct hda_pcm *info = &spec->pcm_rec; struct hda_pcm *info = &spec->pcm_rec;
...@@ -117,7 +293,24 @@ static int nvhdmi_build_pcms(struct hda_codec *codec) ...@@ -117,7 +293,24 @@ static int nvhdmi_build_pcms(struct hda_codec *codec)
info->name = "NVIDIA HDMI"; info->name = "NVIDIA HDMI";
info->pcm_type = HDA_PCM_TYPE_HDMI; info->pcm_type = HDA_PCM_TYPE_HDMI;
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = nvhdmi_pcm_digital_playback; info->stream[SNDRV_PCM_STREAM_PLAYBACK]
= nvhdmi_pcm_digital_playback_8ch;
return 0;
}
static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
{
struct nvhdmi_spec *spec = codec->spec;
struct hda_pcm *info = &spec->pcm_rec;
codec->num_pcms = 1;
codec->pcm_info = info;
info->name = "NVIDIA HDMI";
info->pcm_type = HDA_PCM_TYPE_HDMI;
info->stream[SNDRV_PCM_STREAM_PLAYBACK]
= nvhdmi_pcm_digital_playback_2ch;
return 0; return 0;
} }
...@@ -127,14 +320,40 @@ static void nvhdmi_free(struct hda_codec *codec) ...@@ -127,14 +320,40 @@ static void nvhdmi_free(struct hda_codec *codec)
kfree(codec->spec); kfree(codec->spec);
} }
static struct hda_codec_ops nvhdmi_patch_ops = { static struct hda_codec_ops nvhdmi_patch_ops_8ch = {
.build_controls = nvhdmi_build_controls,
.build_pcms = nvhdmi_build_pcms_8ch,
.init = nvhdmi_init,
.free = nvhdmi_free,
};
static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
.build_controls = nvhdmi_build_controls, .build_controls = nvhdmi_build_controls,
.build_pcms = nvhdmi_build_pcms, .build_pcms = nvhdmi_build_pcms_2ch,
.init = nvhdmi_init, .init = nvhdmi_init,
.free = nvhdmi_free, .free = nvhdmi_free,
}; };
static int patch_nvhdmi(struct hda_codec *codec) static int patch_nvhdmi_8ch(struct hda_codec *codec)
{
struct nvhdmi_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 = 8;
spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
codec->patch_ops = nvhdmi_patch_ops_8ch;
return 0;
}
static int patch_nvhdmi_2ch(struct hda_codec *codec)
{ {
struct nvhdmi_spec *spec; struct nvhdmi_spec *spec;
...@@ -146,11 +365,9 @@ static int patch_nvhdmi(struct hda_codec *codec) ...@@ -146,11 +365,9 @@ static int patch_nvhdmi(struct hda_codec *codec)
spec->multiout.num_dacs = 0; /* no analog */ spec->multiout.num_dacs = 0; /* no analog */
spec->multiout.max_channels = 2; spec->multiout.max_channels = 2;
spec->multiout.dig_out_nid = 0x4; /* NID for copying analog to digital, spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
* seems to be unused in pure-digital
* case. */
codec->patch_ops = nvhdmi_patch_ops; codec->patch_ops = nvhdmi_patch_ops_2ch;
return 0; return 0;
} }
...@@ -159,11 +376,11 @@ static int patch_nvhdmi(struct hda_codec *codec) ...@@ -159,11 +376,11 @@ static int patch_nvhdmi(struct hda_codec *codec)
* patch entries * patch entries
*/ */
static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
{ .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi }, { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
{ .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi }, { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
{ .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi }, { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch },
{ .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi }, { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
{ .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi }, { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
{} /* terminator */ {} /* terminator */
}; };
......
This diff is collapsed.
This diff is collapsed.
...@@ -205,7 +205,7 @@ struct via_spec { ...@@ -205,7 +205,7 @@ struct via_spec {
/* playback */ /* playback */
struct hda_multi_out multiout; struct hda_multi_out multiout;
hda_nid_t extra_dig_out_nid; hda_nid_t slave_dig_outs[2];
/* capture */ /* capture */
unsigned int num_adc_nids; unsigned int num_adc_nids;
...@@ -731,21 +731,6 @@ static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, ...@@ -731,21 +731,6 @@ static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
return snd_hda_multi_out_dig_close(codec, &spec->multiout); return snd_hda_multi_out_dig_close(codec, &spec->multiout);
} }
/* setup SPDIF output stream */
static void setup_dig_playback_stream(struct hda_codec *codec, hda_nid_t nid,
unsigned int stream_tag, unsigned int format)
{
/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
if (codec->spdif_ctls & AC_DIG1_ENABLE)
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
/* turn on again (if needed) */
if (codec->spdif_ctls & AC_DIG1_ENABLE)
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & 0xff);
}
static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec, struct hda_codec *codec,
unsigned int stream_tag, unsigned int stream_tag,
...@@ -753,19 +738,16 @@ static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, ...@@ -753,19 +738,16 @@ static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream) struct snd_pcm_substream *substream)
{ {
struct via_spec *spec = codec->spec; struct via_spec *spec = codec->spec;
hda_nid_t nid; return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
stream_tag, format, substream);
/* 1st or 2nd S/PDIF */ }
if (substream->number == 0)
nid = spec->multiout.dig_out_nid;
else if (substream->number == 1)
nid = spec->extra_dig_out_nid;
else
return -1;
mutex_lock(&codec->spdif_mutex); static int via_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
setup_dig_playback_stream(codec, nid, stream_tag, format); struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex); struct snd_pcm_substream *substream)
{
struct via_spec *spec = codec->spec;
snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
return 0; return 0;
} }
...@@ -842,7 +824,8 @@ static struct hda_pcm_stream vt1708_pcm_digital_playback = { ...@@ -842,7 +824,8 @@ static struct hda_pcm_stream vt1708_pcm_digital_playback = {
.ops = { .ops = {
.open = via_dig_playback_pcm_open, .open = via_dig_playback_pcm_open,
.close = via_dig_playback_pcm_close, .close = via_dig_playback_pcm_close,
.prepare = via_dig_playback_pcm_prepare .prepare = via_dig_playback_pcm_prepare,
.cleanup = via_dig_playback_pcm_cleanup
}, },
}; };
...@@ -874,13 +857,6 @@ static int via_build_controls(struct hda_codec *codec) ...@@ -874,13 +857,6 @@ static int via_build_controls(struct hda_codec *codec)
if (err < 0) if (err < 0)
return err; return err;
spec->multiout.share_spdif = 1; spec->multiout.share_spdif = 1;
if (spec->extra_dig_out_nid) {
err = snd_hda_create_spdif_out_ctls(codec,
spec->extra_dig_out_nid);
if (err < 0)
return err;
}
} }
if (spec->dig_in_nid) { if (spec->dig_in_nid) {
err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
...@@ -1013,10 +989,6 @@ static void via_unsol_event(struct hda_codec *codec, ...@@ -1013,10 +989,6 @@ static void via_unsol_event(struct hda_codec *codec,
via_gpio_control(codec); via_gpio_control(codec);
} }
static hda_nid_t slave_dig_outs[] = {
0,
};
static int via_init(struct hda_codec *codec) static int via_init(struct hda_codec *codec)
{ {
struct via_spec *spec = codec->spec; struct via_spec *spec = codec->spec;
...@@ -1051,8 +1023,9 @@ static int via_init(struct hda_codec *codec) ...@@ -1051,8 +1023,9 @@ static int via_init(struct hda_codec *codec)
snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0, snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN); AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
/* no slave outs */ /* assign slave outs */
codec->slave_dig_outs = slave_dig_outs; if (spec->slave_dig_outs[0])
codec->slave_dig_outs = spec->slave_dig_outs;
return 0; return 0;
} }
...@@ -2134,7 +2107,8 @@ static struct hda_pcm_stream vt1708B_pcm_digital_playback = { ...@@ -2134,7 +2107,8 @@ static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
.ops = { .ops = {
.open = via_dig_playback_pcm_open, .open = via_dig_playback_pcm_open,
.close = via_dig_playback_pcm_close, .close = via_dig_playback_pcm_close,
.prepare = via_dig_playback_pcm_prepare .prepare = via_dig_playback_pcm_prepare,
.cleanup = via_dig_playback_pcm_cleanup
}, },
}; };
...@@ -2589,14 +2563,15 @@ static struct hda_pcm_stream vt1708S_pcm_analog_capture = { ...@@ -2589,14 +2563,15 @@ static struct hda_pcm_stream vt1708S_pcm_analog_capture = {
}; };
static struct hda_pcm_stream vt1708S_pcm_digital_playback = { static struct hda_pcm_stream vt1708S_pcm_digital_playback = {
.substreams = 2, .substreams = 1,
.channels_min = 2, .channels_min = 2,
.channels_max = 2, .channels_max = 2,
/* NID is set in via_build_pcms */ /* NID is set in via_build_pcms */
.ops = { .ops = {
.open = via_dig_playback_pcm_open, .open = via_dig_playback_pcm_open,
.close = via_dig_playback_pcm_close, .close = via_dig_playback_pcm_close,
.prepare = via_dig_playback_pcm_prepare .prepare = via_dig_playback_pcm_prepare,
.cleanup = via_dig_playback_pcm_cleanup
}, },
}; };
...@@ -2805,14 +2780,37 @@ static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec, ...@@ -2805,14 +2780,37 @@ static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec,
return 0; return 0;
} }
/* fill out digital output widgets; one for master and one for slave outputs */
static void fill_dig_outs(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
int i;
for (i = 0; i < spec->autocfg.dig_outs; i++) {
hda_nid_t nid;
int conn;
nid = spec->autocfg.dig_out_pins[i];
if (!nid)
continue;
conn = snd_hda_get_connections(codec, nid, &nid, 1);
if (conn < 1)
continue;
if (!spec->multiout.dig_out_nid)
spec->multiout.dig_out_nid = nid;
else {
spec->slave_dig_outs[0] = nid;
break; /* at most two dig outs */
}
}
}
static int vt1708S_parse_auto_config(struct hda_codec *codec) static int vt1708S_parse_auto_config(struct hda_codec *codec)
{ {
struct via_spec *spec = codec->spec; struct via_spec *spec = codec->spec;
int err; int err;
static hda_nid_t vt1708s_ignore[] = {0x21, 0};
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
vt1708s_ignore);
if (err < 0) if (err < 0)
return err; return err;
err = vt1708S_auto_fill_dac_nids(spec, &spec->autocfg); err = vt1708S_auto_fill_dac_nids(spec, &spec->autocfg);
...@@ -2833,10 +2831,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) ...@@ -2833,10 +2831,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2; spec->multiout.max_channels = spec->multiout.num_dacs * 2;
if (spec->autocfg.dig_outs) fill_dig_outs(codec);
spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID;
spec->extra_dig_out_nid = 0x15;
if (spec->kctls.list) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctls.list; spec->mixers[spec->num_mixers++] = spec->kctls.list;
...@@ -3000,7 +2995,8 @@ static struct hda_pcm_stream vt1702_pcm_digital_playback = { ...@@ -3000,7 +2995,8 @@ static struct hda_pcm_stream vt1702_pcm_digital_playback = {
.ops = { .ops = {
.open = via_dig_playback_pcm_open, .open = via_dig_playback_pcm_open,
.close = via_dig_playback_pcm_close, .close = via_dig_playback_pcm_close,
.prepare = via_dig_playback_pcm_prepare .prepare = via_dig_playback_pcm_prepare,
.cleanup = via_dig_playback_pcm_cleanup
}, },
}; };
...@@ -3128,10 +3124,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) ...@@ -3128,10 +3124,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
{ {
struct via_spec *spec = codec->spec; struct via_spec *spec = codec->spec;
int err; int err;
static hda_nid_t vt1702_ignore[] = {0x1C, 0};
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
vt1702_ignore);
if (err < 0) if (err < 0)
return err; return err;
err = vt1702_auto_fill_dac_nids(spec, &spec->autocfg); err = vt1702_auto_fill_dac_nids(spec, &spec->autocfg);
...@@ -3152,10 +3146,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) ...@@ -3152,10 +3146,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2; spec->multiout.max_channels = spec->multiout.num_dacs * 2;
if (spec->autocfg.dig_outs) fill_dig_outs(codec);
spec->multiout.dig_out_nid = VT1702_DIGOUT_NID;
spec->extra_dig_out_nid = 0x1B;
if (spec->kctls.list) if (spec->kctls.list)
spec->mixers[spec->num_mixers++] = spec->kctls.list; spec->mixers[spec->num_mixers++] = spec->kctls.list;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment