diff options
author | Kailang Yang <kailang@realtek.com> | 2010-03-19 06:23:45 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-03-19 06:38:53 -0400 |
commit | da00c24493bf6ae3772dfe7343dca033ebc75955 (patch) | |
tree | 05019a7555bd1406fef9c95df1ac98a5acc191a9 /sound | |
parent | 6ff86a3f33e84c430aeb8ff3b7f68b1c052ec1e9 (diff) |
ALSA: hda - Add parse customize define function for Realtek codecs
Added alc_auto_parse_customize_define() to parse the Realtek-specific
attributes from SKU. Also enable beep controls only when the proper
attribute bit is set.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 112 |
1 files changed, 96 insertions, 16 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4ec57633af88..245e1afa5896 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -275,6 +275,18 @@ struct alc_mic_route { | |||
275 | 275 | ||
276 | #define MUX_IDX_UNDEF ((unsigned char)-1) | 276 | #define MUX_IDX_UNDEF ((unsigned char)-1) |
277 | 277 | ||
278 | struct alc_customize_define { | ||
279 | unsigned int sku_cfg; | ||
280 | unsigned char port_connectivity; | ||
281 | unsigned char check_sum; | ||
282 | unsigned char customization; | ||
283 | unsigned char external_amp; | ||
284 | unsigned int enable_pcbeep:1; | ||
285 | unsigned int platform_type:1; | ||
286 | unsigned int swap:1; | ||
287 | unsigned int override:1; | ||
288 | }; | ||
289 | |||
278 | struct alc_spec { | 290 | struct alc_spec { |
279 | /* codec parameterization */ | 291 | /* codec parameterization */ |
280 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ | 292 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ |
@@ -332,6 +344,7 @@ struct alc_spec { | |||
332 | 344 | ||
333 | /* dynamic controls, init_verbs and input_mux */ | 345 | /* dynamic controls, init_verbs and input_mux */ |
334 | struct auto_pin_cfg autocfg; | 346 | struct auto_pin_cfg autocfg; |
347 | struct alc_customize_define cdefine; | ||
335 | struct snd_array kctls; | 348 | struct snd_array kctls; |
336 | struct hda_input_mux private_imux[3]; | 349 | struct hda_input_mux private_imux[3]; |
337 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 350 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
@@ -1247,6 +1260,62 @@ static void alc_init_auto_mic(struct hda_codec *codec) | |||
1247 | spec->unsol_event = alc_sku_unsol_event; | 1260 | spec->unsol_event = alc_sku_unsol_event; |
1248 | } | 1261 | } |
1249 | 1262 | ||
1263 | static int alc_auto_parse_customize_define(struct hda_codec *codec) | ||
1264 | { | ||
1265 | unsigned int ass, tmp, i; | ||
1266 | unsigned nid; | ||
1267 | struct alc_spec *spec = codec->spec; | ||
1268 | |||
1269 | ass = codec->subsystem_id & 0xffff; | ||
1270 | if (ass != codec->bus->pci->subsystem_device && (ass & 1)) | ||
1271 | goto do_sku; | ||
1272 | |||
1273 | nid = 0x1d; | ||
1274 | if (codec->vendor_id == 0x10ec0260) | ||
1275 | nid = 0x17; | ||
1276 | ass = snd_hda_codec_get_pincfg(codec, nid); | ||
1277 | |||
1278 | if (!(ass & 1)) { | ||
1279 | printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n", | ||
1280 | codec->chip_name, ass); | ||
1281 | return -1; | ||
1282 | } | ||
1283 | |||
1284 | /* check sum */ | ||
1285 | tmp = 0; | ||
1286 | for (i = 1; i < 16; i++) { | ||
1287 | if ((ass >> i) & 1) | ||
1288 | tmp++; | ||
1289 | } | ||
1290 | if (((ass >> 16) & 0xf) != tmp) | ||
1291 | return -1; | ||
1292 | |||
1293 | spec->cdefine.port_connectivity = ass >> 30; | ||
1294 | spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20; | ||
1295 | spec->cdefine.check_sum = (ass >> 16) & 0xf; | ||
1296 | spec->cdefine.customization = ass >> 8; | ||
1297 | do_sku: | ||
1298 | spec->cdefine.sku_cfg = ass; | ||
1299 | spec->cdefine.external_amp = (ass & 0x38) >> 3; | ||
1300 | spec->cdefine.platform_type = (ass & 0x4) >> 2; | ||
1301 | spec->cdefine.swap = (ass & 0x2) >> 1; | ||
1302 | spec->cdefine.override = ass & 0x1; | ||
1303 | |||
1304 | snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n", | ||
1305 | nid, spec->cdefine.sku_cfg); | ||
1306 | snd_printd("SKU: port_connectivity=0x%x\n", | ||
1307 | spec->cdefine.port_connectivity); | ||
1308 | snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep); | ||
1309 | snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum); | ||
1310 | snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization); | ||
1311 | snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp); | ||
1312 | snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type); | ||
1313 | snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap); | ||
1314 | snd_printd("SKU: override=0x%x\n", spec->cdefine.override); | ||
1315 | |||
1316 | return 0; | ||
1317 | } | ||
1318 | |||
1250 | /* check subsystem ID and set up device-specific initialization; | 1319 | /* check subsystem ID and set up device-specific initialization; |
1251 | * return 1 if initialized, 0 if invalid SSID | 1320 | * return 1 if initialized, 0 if invalid SSID |
1252 | */ | 1321 | */ |
@@ -3779,7 +3848,6 @@ static struct hda_codec_ops alc_patch_ops = { | |||
3779 | .reboot_notify = alc_shutup, | 3848 | .reboot_notify = alc_shutup, |
3780 | }; | 3849 | }; |
3781 | 3850 | ||
3782 | |||
3783 | /* | 3851 | /* |
3784 | * Test configuration for debugging | 3852 | * Test configuration for debugging |
3785 | * | 3853 | * |
@@ -10267,6 +10335,8 @@ static int patch_alc882(struct hda_codec *codec) | |||
10267 | 10335 | ||
10268 | codec->spec = spec; | 10336 | codec->spec = spec; |
10269 | 10337 | ||
10338 | alc_auto_parse_customize_define(codec); | ||
10339 | |||
10270 | switch (codec->vendor_id) { | 10340 | switch (codec->vendor_id) { |
10271 | case 0x10ec0882: | 10341 | case 0x10ec0882: |
10272 | case 0x10ec0885: | 10342 | case 0x10ec0885: |
@@ -10362,7 +10432,9 @@ static int patch_alc882(struct hda_codec *codec) | |||
10362 | } | 10432 | } |
10363 | 10433 | ||
10364 | set_capture_mixer(codec); | 10434 | set_capture_mixer(codec); |
10365 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 10435 | |
10436 | if (spec->cdefine.enable_pcbeep) | ||
10437 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
10366 | 10438 | ||
10367 | spec->vmaster_nid = 0x0c; | 10439 | spec->vmaster_nid = 0x0c; |
10368 | 10440 | ||
@@ -12146,6 +12218,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
12146 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80); | 12218 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80); |
12147 | } | 12219 | } |
12148 | #endif | 12220 | #endif |
12221 | alc_auto_parse_customize_define(codec); | ||
12149 | 12222 | ||
12150 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); | 12223 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); |
12151 | 12224 | ||
@@ -12224,7 +12297,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
12224 | } | 12297 | } |
12225 | if (!spec->cap_mixer && !spec->no_analog) | 12298 | if (!spec->cap_mixer && !spec->no_analog) |
12226 | set_capture_mixer(codec); | 12299 | set_capture_mixer(codec); |
12227 | if (!spec->no_analog) | 12300 | if (!spec->no_analog && spec->cdefine.enable_pcbeep) |
12228 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 12301 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
12229 | 12302 | ||
12230 | spec->vmaster_nid = 0x0c; | 12303 | spec->vmaster_nid = 0x0c; |
@@ -14094,6 +14167,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
14094 | 14167 | ||
14095 | codec->spec = spec; | 14168 | codec->spec = spec; |
14096 | 14169 | ||
14170 | alc_auto_parse_customize_define(codec); | ||
14171 | |||
14097 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | 14172 | alc_fix_pll_init(codec, 0x20, 0x04, 15); |
14098 | 14173 | ||
14099 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ | 14174 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ |
@@ -14164,7 +14239,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
14164 | 14239 | ||
14165 | if (!spec->cap_mixer) | 14240 | if (!spec->cap_mixer) |
14166 | set_capture_mixer(codec); | 14241 | set_capture_mixer(codec); |
14167 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 14242 | if (spec->cdefine.enable_pcbeep) |
14243 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | ||
14168 | 14244 | ||
14169 | spec->vmaster_nid = 0x02; | 14245 | spec->vmaster_nid = 0x02; |
14170 | 14246 | ||
@@ -18314,6 +18390,8 @@ static int patch_alc662(struct hda_codec *codec) | |||
18314 | 18390 | ||
18315 | codec->spec = spec; | 18391 | codec->spec = spec; |
18316 | 18392 | ||
18393 | alc_auto_parse_customize_define(codec); | ||
18394 | |||
18317 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | 18395 | alc_fix_pll_init(codec, 0x20, 0x04, 15); |
18318 | 18396 | ||
18319 | if (alc_read_coef_idx(codec, 0)==0x8020){ | 18397 | if (alc_read_coef_idx(codec, 0)==0x8020){ |
@@ -18373,18 +18451,20 @@ static int patch_alc662(struct hda_codec *codec) | |||
18373 | if (!spec->cap_mixer) | 18451 | if (!spec->cap_mixer) |
18374 | set_capture_mixer(codec); | 18452 | set_capture_mixer(codec); |
18375 | 18453 | ||
18376 | switch (codec->vendor_id) { | 18454 | if (spec->cdefine.enable_pcbeep) { |
18377 | case 0x10ec0662: | 18455 | switch (codec->vendor_id) { |
18378 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 18456 | case 0x10ec0662: |
18379 | break; | 18457 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
18380 | case 0x10ec0272: | 18458 | break; |
18381 | case 0x10ec0663: | 18459 | case 0x10ec0272: |
18382 | case 0x10ec0665: | 18460 | case 0x10ec0663: |
18383 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 18461 | case 0x10ec0665: |
18384 | break; | 18462 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); |
18385 | case 0x10ec0273: | 18463 | break; |
18386 | set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); | 18464 | case 0x10ec0273: |
18387 | break; | 18465 | set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); |
18466 | break; | ||
18467 | } | ||
18388 | } | 18468 | } |
18389 | spec->vmaster_nid = 0x02; | 18469 | spec->vmaster_nid = 0x02; |
18390 | 18470 | ||