aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/cmipci.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/cmipci.c')
-rw-r--r--sound/pci/cmipci.c159
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 */
522static void snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) 522static 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
530static void snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) 533static 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 */
540static void snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) 545static 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
548static void snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) 556static 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
2250DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); 2260DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0);
2251#endif 2261#endif
2252DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); 2262DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0);
2253DEFINE_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);
2254DEFINE_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 */
2256DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); 2266DEFINE_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
2313static 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
2327static 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
2341static 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
2352static 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
2371static 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
2384static 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
2396static 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 */
2304static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = { 2412static 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 */
2343static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = { 2457static 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
2945static int __init alsa_card_cmipci_init(void) 3064static 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
2950static void __exit alsa_card_cmipci_exit(void) 3069static void __exit alsa_card_cmipci_exit(void)