diff options
Diffstat (limited to 'sound/pci/cmipci.c')
-rw-r--r-- | sound/pci/cmipci.c | 159 |
1 files changed, 139 insertions, 20 deletions
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 113208fbde1b..b4503385ea69 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -519,40 +519,50 @@ inline static unsigned char snd_cmipci_read_b(cmipci_t *cm, unsigned int cmd) | |||
519 | } | 519 | } |
520 | 520 | ||
521 | /* bit operations for dword register */ | 521 | /* bit operations for dword register */ |
522 | static void snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) | 522 | static int snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) |
523 | { | 523 | { |
524 | unsigned int val; | 524 | unsigned int val, oval; |
525 | val = inl(cm->iobase + cmd); | 525 | val = oval = inl(cm->iobase + cmd); |
526 | val |= flag; | 526 | val |= flag; |
527 | if (val == oval) | ||
528 | return 0; | ||
527 | outl(val, cm->iobase + cmd); | 529 | outl(val, cm->iobase + cmd); |
530 | return 1; | ||
528 | } | 531 | } |
529 | 532 | ||
530 | static void snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) | 533 | static int snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) |
531 | { | 534 | { |
532 | unsigned int val; | 535 | unsigned int val, oval; |
533 | val = inl(cm->iobase + cmd); | 536 | val = oval = inl(cm->iobase + cmd); |
534 | val &= ~flag; | 537 | val &= ~flag; |
538 | if (val == oval) | ||
539 | return 0; | ||
535 | outl(val, cm->iobase + cmd); | 540 | outl(val, cm->iobase + cmd); |
541 | return 1; | ||
536 | } | 542 | } |
537 | 543 | ||
538 | #if 0 // not used | ||
539 | /* bit operations for byte register */ | 544 | /* bit operations for byte register */ |
540 | static void snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) | 545 | static int snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) |
541 | { | 546 | { |
542 | unsigned char val; | 547 | unsigned char val, oval; |
543 | val = inb(cm->iobase + cmd); | 548 | val = oval = inb(cm->iobase + cmd); |
544 | val |= flag; | 549 | val |= flag; |
550 | if (val == oval) | ||
551 | return 0; | ||
545 | outb(val, cm->iobase + cmd); | 552 | outb(val, cm->iobase + cmd); |
553 | return 1; | ||
546 | } | 554 | } |
547 | 555 | ||
548 | static void snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) | 556 | static int snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) |
549 | { | 557 | { |
550 | unsigned char val; | 558 | unsigned char val, oval; |
551 | val = inb(cm->iobase + cmd); | 559 | val = oval = inb(cm->iobase + cmd); |
552 | val &= ~flag; | 560 | val &= ~flag; |
561 | if (val == oval) | ||
562 | return 0; | ||
553 | outb(val, cm->iobase + cmd); | 563 | outb(val, cm->iobase + cmd); |
564 | return 1; | ||
554 | } | 565 | } |
555 | #endif | ||
556 | 566 | ||
557 | 567 | ||
558 | /* | 568 | /* |
@@ -2250,8 +2260,8 @@ DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, 0, 0, 0); /* rever | |||
2250 | DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); | 2260 | DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); |
2251 | #endif | 2261 | #endif |
2252 | DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); | 2262 | DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); |
2253 | DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0); | 2263 | // DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0); |
2254 | DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0); | 2264 | // DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0); |
2255 | // DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */ | 2265 | // DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */ |
2256 | DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); | 2266 | DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); |
2257 | 2267 | ||
@@ -2300,10 +2310,114 @@ static int snd_cmipci_spdout_enable_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v | |||
2300 | } | 2310 | } |
2301 | 2311 | ||
2302 | 2312 | ||
2313 | static int snd_cmipci_line_in_mode_info(snd_kcontrol_t *kcontrol, | ||
2314 | snd_ctl_elem_info_t *uinfo) | ||
2315 | { | ||
2316 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2317 | static char *texts[3] = { "Line-In", "Rear Output", "Bass Output" }; | ||
2318 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2319 | uinfo->count = 1; | ||
2320 | uinfo->value.enumerated.items = cm->chip_version >= 39 ? 3 : 2; | ||
2321 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2322 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
2323 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
2324 | return 0; | ||
2325 | } | ||
2326 | |||
2327 | static inline unsigned int get_line_in_mode(cmipci_t *cm) | ||
2328 | { | ||
2329 | unsigned int val; | ||
2330 | if (cm->chip_version >= 39) { | ||
2331 | val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL); | ||
2332 | if (val & CM_LINE_AS_BASS) | ||
2333 | return 2; | ||
2334 | } | ||
2335 | val = snd_cmipci_read_b(cm, CM_REG_MIXER1); | ||
2336 | if (val & CM_SPK4) | ||
2337 | return 1; | ||
2338 | return 0; | ||
2339 | } | ||
2340 | |||
2341 | static int snd_cmipci_line_in_mode_get(snd_kcontrol_t *kcontrol, | ||
2342 | snd_ctl_elem_value_t *ucontrol) | ||
2343 | { | ||
2344 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2345 | |||
2346 | spin_lock_irq(&cm->reg_lock); | ||
2347 | ucontrol->value.enumerated.item[0] = get_line_in_mode(cm); | ||
2348 | spin_unlock_irq(&cm->reg_lock); | ||
2349 | return 0; | ||
2350 | } | ||
2351 | |||
2352 | static int snd_cmipci_line_in_mode_put(snd_kcontrol_t *kcontrol, | ||
2353 | snd_ctl_elem_value_t *ucontrol) | ||
2354 | { | ||
2355 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2356 | int change; | ||
2357 | |||
2358 | spin_lock_irq(&cm->reg_lock); | ||
2359 | if (ucontrol->value.enumerated.item[0] == 2) | ||
2360 | change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); | ||
2361 | else | ||
2362 | change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); | ||
2363 | if (ucontrol->value.enumerated.item[0] == 1) | ||
2364 | change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_SPK4); | ||
2365 | else | ||
2366 | change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_SPK4); | ||
2367 | spin_unlock_irq(&cm->reg_lock); | ||
2368 | return change; | ||
2369 | } | ||
2370 | |||
2371 | static int snd_cmipci_mic_in_mode_info(snd_kcontrol_t *kcontrol, | ||
2372 | snd_ctl_elem_info_t *uinfo) | ||
2373 | { | ||
2374 | static char *texts[2] = { "Mic-In", "Center/LFE Output" }; | ||
2375 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2376 | uinfo->count = 1; | ||
2377 | uinfo->value.enumerated.items = 2; | ||
2378 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2379 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
2380 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
2381 | return 0; | ||
2382 | } | ||
2383 | |||
2384 | static int snd_cmipci_mic_in_mode_get(snd_kcontrol_t *kcontrol, | ||
2385 | snd_ctl_elem_value_t *ucontrol) | ||
2386 | { | ||
2387 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2388 | /* same bit as spdi_phase */ | ||
2389 | spin_lock_irq(&cm->reg_lock); | ||
2390 | ucontrol->value.enumerated.item[0] = | ||
2391 | (snd_cmipci_read_b(cm, CM_REG_MISC) & CM_SPDIF_INVERSE) ? 1 : 0; | ||
2392 | spin_unlock_irq(&cm->reg_lock); | ||
2393 | return 0; | ||
2394 | } | ||
2395 | |||
2396 | static int snd_cmipci_mic_in_mode_put(snd_kcontrol_t *kcontrol, | ||
2397 | snd_ctl_elem_value_t *ucontrol) | ||
2398 | { | ||
2399 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2400 | int change; | ||
2401 | |||
2402 | spin_lock_irq(&cm->reg_lock); | ||
2403 | if (ucontrol->value.enumerated.item[0]) | ||
2404 | change = snd_cmipci_set_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE); | ||
2405 | else | ||
2406 | change = snd_cmipci_clear_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE); | ||
2407 | spin_unlock_irq(&cm->reg_lock); | ||
2408 | return change; | ||
2409 | } | ||
2410 | |||
2303 | /* both for CM8338/8738 */ | 2411 | /* both for CM8338/8738 */ |
2304 | static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = { | 2412 | static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = { |
2305 | DEFINE_MIXER_SWITCH("Four Channel Mode", fourch), | 2413 | DEFINE_MIXER_SWITCH("Four Channel Mode", fourch), |
2306 | DEFINE_MIXER_SWITCH("Line-In As Rear", line_rear), | 2414 | { |
2415 | .name = "Line-In Mode", | ||
2416 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2417 | .info = snd_cmipci_line_in_mode_info, | ||
2418 | .get = snd_cmipci_line_in_mode_get, | ||
2419 | .put = snd_cmipci_line_in_mode_put, | ||
2420 | }, | ||
2307 | }; | 2421 | }; |
2308 | 2422 | ||
2309 | /* for non-multichannel chips */ | 2423 | /* for non-multichannel chips */ |
@@ -2341,10 +2455,15 @@ static snd_kcontrol_new_t snd_cmipci_old_mixer_switches[] __devinitdata = { | |||
2341 | 2455 | ||
2342 | /* only for model 039 or later */ | 2456 | /* only for model 039 or later */ |
2343 | static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = { | 2457 | static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = { |
2344 | DEFINE_MIXER_SWITCH("Line-In As Bass", line_bass), | ||
2345 | DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2), | 2458 | DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2), |
2346 | DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2), | 2459 | DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2), |
2347 | DEFINE_MIXER_SWITCH("Mic As Center/LFE", spdi_phase), /* same bit as spdi_phase */ | 2460 | { |
2461 | .name = "Mic-In Mode", | ||
2462 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2463 | .info = snd_cmipci_mic_in_mode_info, | ||
2464 | .get = snd_cmipci_mic_in_mode_get, | ||
2465 | .put = snd_cmipci_mic_in_mode_put, | ||
2466 | } | ||
2348 | }; | 2467 | }; |
2349 | 2468 | ||
2350 | /* card control switches */ | 2469 | /* card control switches */ |
@@ -2944,7 +3063,7 @@ static struct pci_driver driver = { | |||
2944 | 3063 | ||
2945 | static int __init alsa_card_cmipci_init(void) | 3064 | static int __init alsa_card_cmipci_init(void) |
2946 | { | 3065 | { |
2947 | return pci_module_init(&driver); | 3066 | return pci_register_driver(&driver); |
2948 | } | 3067 | } |
2949 | 3068 | ||
2950 | static void __exit alsa_card_cmipci_exit(void) | 3069 | static void __exit alsa_card_cmipci_exit(void) |