aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2008-09-22 03:12:11 -0400
committerClemens Ladisch <clemens@ladisch.de>2008-09-22 03:12:11 -0400
commit7407a2e4b9e1fb3528bb355a571ee3eb7e32c386 (patch)
treeb7c0bfcf1ac51083dae93df64da3566cbcb82a1f
parent79c50e23d4272404da7349010f514516976b447a (diff)
ALSA: virtuoso: add Xonar HDAV1.3 support
Add support for the Asus Xonar HDAV1.3 and the Xonar HDAV1.3 Deluxe. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt2
-rw-r--r--sound/pci/Kconfig3
-rw-r--r--sound/pci/oxygen/virtuoso.c251
3 files changed, 254 insertions, 2 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 30499cf77d56..e0e54a27fc10 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -2120,7 +2120,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
2120 ------------------- 2120 -------------------
2121 2121
2122 Module for sound cards based on the Asus AV100/AV200 chips, 2122 Module for sound cards based on the Asus AV100/AV200 chips,
2123 i.e., Xonar D1, DX, D2 and D2X. 2123 i.e., Xonar D1, DX, D2, D2X and HDAV1.3 (Deluxe).
2124 2124
2125 This module supports autoprobe and multiple cards. 2125 This module supports autoprobe and multiple cards.
2126 2126
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 4a7ebbc96762..1f8b7966a839 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -857,7 +857,8 @@ config SND_VIRTUOSO
857 select SND_OXYGEN_LIB 857 select SND_OXYGEN_LIB
858 help 858 help
859 Say Y here to include support for sound cards based on the 859 Say Y here to include support for sound cards based on the
860 Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2 and D2X. 860 Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X and
861 HDAV1.3 (Deluxe).
861 862
862 To compile this driver as a module, choose M here: the module 863 To compile this driver as a module, choose M here: the module
863 will be called snd-virtuoso. 864 will be called snd-virtuoso.
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 928283de6f37..98c6a8c65d81 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -62,14 +62,66 @@
62 * AD0 <- 0 62 * AD0 <- 0
63 */ 63 */
64 64
65/*
66 * Xonar HDAV1.3 (Deluxe)
67 * ----------------------
68 *
69 * CMI8788:
70 *
71 * I²C <-> PCM1796 (front)
72 *
73 * GPI 0 <- external power present
74 *
75 * GPIO 0 -> enable output to speakers
76 * GPIO 2 -> M0 of CS5381
77 * GPIO 3 -> M1 of CS5381
78 * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
79 *
80 * TXD -> HDMI controller
81 * RXD <- HDMI controller
82 *
83 * PCM1796 front: AD1,0 <- 0,0
84 *
85 * no daughterboard
86 * ----------------
87 *
88 * GPIO 4 <- 1
89 *
90 * H6 daughterboard
91 * ----------------
92 *
93 * GPIO 4 <- 0
94 * GPIO 5 <- 0
95 *
96 * I²C <-> PCM1796 (surround)
97 * <-> PCM1796 (center/LFE)
98 * <-> PCM1796 (back)
99 *
100 * PCM1796 surround: AD1,0 <- 0,1
101 * PCM1796 center/LFE: AD1,0 <- 1,0
102 * PCM1796 back: AD1,0 <- 1,1
103 *
104 * unknown daughterboard
105 * ---------------------
106 *
107 * GPIO 4 <- 0
108 * GPIO 5 <- 1
109 *
110 * I²C <-> CS4362A (surround, center/LFE, back)
111 *
112 * CS4362A: AD0 <- 0
113 */
114
65#include <linux/pci.h> 115#include <linux/pci.h>
66#include <linux/delay.h> 116#include <linux/delay.h>
67#include <linux/mutex.h> 117#include <linux/mutex.h>
68#include <sound/ac97_codec.h> 118#include <sound/ac97_codec.h>
119#include <sound/asoundef.h>
69#include <sound/control.h> 120#include <sound/control.h>
70#include <sound/core.h> 121#include <sound/core.h>
71#include <sound/initval.h> 122#include <sound/initval.h>
72#include <sound/pcm.h> 123#include <sound/pcm.h>
124#include <sound/pcm_params.h>
73#include <sound/tlv.h> 125#include <sound/tlv.h>
74#include "oxygen.h" 126#include "oxygen.h"
75#include "cm9780.h" 127#include "cm9780.h"
@@ -98,12 +150,15 @@ enum {
98 MODEL_D2X, 150 MODEL_D2X,
99 MODEL_D1, 151 MODEL_D1,
100 MODEL_DX, 152 MODEL_DX,
153 MODEL_HDAV, /* without daughterboard */
154 MODEL_HDAV_H6, /* with H6 daughterboard */
101}; 155};
102 156
103static struct pci_device_id xonar_ids[] __devinitdata = { 157static struct pci_device_id xonar_ids[] __devinitdata = {
104 { OXYGEN_PCI_SUBID(0x1043, 0x8269), .driver_data = MODEL_D2 }, 158 { OXYGEN_PCI_SUBID(0x1043, 0x8269), .driver_data = MODEL_D2 },
105 { OXYGEN_PCI_SUBID(0x1043, 0x8275), .driver_data = MODEL_DX }, 159 { OXYGEN_PCI_SUBID(0x1043, 0x8275), .driver_data = MODEL_DX },
106 { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X }, 160 { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X },
161 { OXYGEN_PCI_SUBID(0x1043, 0x8314), .driver_data = MODEL_HDAV },
107 { OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 }, 162 { OXYGEN_PCI_SUBID(0x1043, 0x834f), .driver_data = MODEL_D1 },
108 { } 163 { }
109}; 164};
@@ -124,6 +179,10 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
124#define GPIO_DX_FRONT_PANEL 0x0002 179#define GPIO_DX_FRONT_PANEL 0x0002
125#define GPIO_DX_INPUT_ROUTE 0x0100 180#define GPIO_DX_INPUT_ROUTE 0x0100
126 181
182#define GPIO_HDAV_DB_MASK 0x0030
183#define GPIO_HDAV_DB_H6 0x0000
184#define GPIO_HDAV_DB_XX 0x0020
185
127#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ADx=i, /W=0 */ 186#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ADx=i, /W=0 */
128#define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */ 187#define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */
129#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */ 188#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */
@@ -140,6 +199,7 @@ struct xonar_data {
140 u8 pcm1796_oversampling; 199 u8 pcm1796_oversampling;
141 u8 cs4398_fm; 200 u8 cs4398_fm;
142 u8 cs4362a_fm; 201 u8 cs4362a_fm;
202 u8 hdmi_params[5];
143}; 203};
144 204
145static void xonar_gpio_changed(struct oxygen *chip); 205static void xonar_gpio_changed(struct oxygen *chip);
@@ -185,6 +245,24 @@ static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value)
185 oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value); 245 oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value);
186} 246}
187 247
248static void hdmi_write_command(struct oxygen *chip, u8 command,
249 unsigned int count, const u8 *params)
250{
251 unsigned int i;
252 u8 checksum;
253
254 oxygen_write_uart(chip, 0xfb);
255 oxygen_write_uart(chip, 0xef);
256 oxygen_write_uart(chip, command);
257 oxygen_write_uart(chip, count);
258 for (i = 0; i < count; ++i)
259 oxygen_write_uart(chip, params[i]);
260 checksum = 0xfb + 0xef + command + count;
261 for (i = 0; i < count; ++i)
262 checksum += params[i];
263 oxygen_write_uart(chip, checksum);
264}
265
188static void xonar_enable_output(struct oxygen *chip) 266static void xonar_enable_output(struct oxygen *chip)
189{ 267{
190 struct xonar_data *data = chip->model_data; 268 struct xonar_data *data = chip->model_data;
@@ -369,6 +447,43 @@ static void xonar_d1_init(struct oxygen *chip)
369 snd_component_add(chip->card, "CS5361"); 447 snd_component_add(chip->card, "CS5361");
370} 448}
371 449
450static void xonar_hdav_init(struct oxygen *chip)
451{
452 struct xonar_data *data = chip->model_data;
453 u8 param;
454
455 oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
456 OXYGEN_2WIRE_LENGTH_8 |
457 OXYGEN_2WIRE_INTERRUPT_MASK |
458 OXYGEN_2WIRE_SPEED_FAST);
459
460 data->anti_pop_delay = 100;
461 data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
462 data->ext_power_reg = OXYGEN_GPI_DATA;
463 data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
464 data->ext_power_bit = GPI_DX_EXT_POWER;
465 data->pcm1796_oversampling = PCM1796_OS_64;
466
467 pcm1796_init(chip);
468
469 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DX_INPUT_ROUTE);
470 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DX_INPUT_ROUTE);
471
472 oxygen_reset_uart(chip);
473 param = 0;
474 hdmi_write_command(chip, 0x61, 1, &param);
475 param = 1;
476 hdmi_write_command(chip, 0x74, 1, &param);
477 data->hdmi_params[1] = IEC958_AES3_CON_FS_48000;
478 data->hdmi_params[4] = 1;
479 hdmi_write_command(chip, 0x54, 5, data->hdmi_params);
480
481 xonar_common_init(chip);
482
483 snd_component_add(chip->card, "PCM1796");
484 snd_component_add(chip->card, "CS5381");
485}
486
372static void xonar_disable_output(struct oxygen *chip) 487static void xonar_disable_output(struct oxygen *chip)
373{ 488{
374 struct xonar_data *data = chip->model_data; 489 struct xonar_data *data = chip->model_data;
@@ -388,6 +503,14 @@ static void xonar_d1_cleanup(struct oxygen *chip)
388 oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC); 503 oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
389} 504}
390 505
506static void xonar_hdav_cleanup(struct oxygen *chip)
507{
508 u8 param = 0;
509
510 hdmi_write_command(chip, 0x74, 1, &param);
511 xonar_disable_output(chip);
512}
513
391static void xonar_d2_suspend(struct oxygen *chip) 514static void xonar_d2_suspend(struct oxygen *chip)
392{ 515{
393 xonar_d2_cleanup(chip); 516 xonar_d2_cleanup(chip);
@@ -398,6 +521,12 @@ static void xonar_d1_suspend(struct oxygen *chip)
398 xonar_d1_cleanup(chip); 521 xonar_d1_cleanup(chip);
399} 522}
400 523
524static void xonar_hdav_suspend(struct oxygen *chip)
525{
526 xonar_hdav_cleanup(chip);
527 msleep(2);
528}
529
401static void xonar_d2_resume(struct oxygen *chip) 530static void xonar_d2_resume(struct oxygen *chip)
402{ 531{
403 pcm1796_init(chip); 532 pcm1796_init(chip);
@@ -410,6 +539,33 @@ static void xonar_d1_resume(struct oxygen *chip)
410 xonar_enable_output(chip); 539 xonar_enable_output(chip);
411} 540}
412 541
542static void xonar_hdav_resume(struct oxygen *chip)
543{
544 struct xonar_data *data = chip->model_data;
545 u8 param;
546
547 oxygen_reset_uart(chip);
548 param = 0;
549 hdmi_write_command(chip, 0x61, 1, &param);
550 param = 1;
551 hdmi_write_command(chip, 0x74, 1, &param);
552 hdmi_write_command(chip, 0x54, 5, data->hdmi_params);
553 pcm1796_init(chip);
554 xonar_enable_output(chip);
555}
556
557static void xonar_hdav_pcm_hardware_filter(unsigned int channel,
558 struct snd_pcm_hardware *hardware)
559{
560 if (channel == PCM_MULTICH) {
561 hardware->rates = SNDRV_PCM_RATE_44100 |
562 SNDRV_PCM_RATE_48000 |
563 SNDRV_PCM_RATE_96000 |
564 SNDRV_PCM_RATE_192000;
565 hardware->rate_min = 44100;
566 }
567}
568
413static void set_pcm1796_params(struct oxygen *chip, 569static void set_pcm1796_params(struct oxygen *chip,
414 struct snd_pcm_hw_params *params) 570 struct snd_pcm_hw_params *params)
415{ 571{
@@ -460,6 +616,42 @@ static void set_cs43xx_params(struct oxygen *chip,
460 cs4362a_write(chip, 0x0c, data->cs4362a_fm); 616 cs4362a_write(chip, 0x0c, data->cs4362a_fm);
461} 617}
462 618
619static void set_hdmi_params(struct oxygen *chip,
620 struct snd_pcm_hw_params *params)
621{
622 struct xonar_data *data = chip->model_data;
623
624 data->hdmi_params[0] = 0; /* 1 = non-audio */
625 switch (params_rate(params)) {
626 case 44100:
627 data->hdmi_params[1] = IEC958_AES3_CON_FS_44100;
628 break;
629 case 48000:
630 data->hdmi_params[1] = IEC958_AES3_CON_FS_48000;
631 break;
632 default: /* 96000 */
633 data->hdmi_params[1] = IEC958_AES3_CON_FS_96000;
634 break;
635 case 192000:
636 data->hdmi_params[1] = IEC958_AES3_CON_FS_192000;
637 break;
638 }
639 data->hdmi_params[2] = params_channels(params) / 2 - 1;
640 if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE)
641 data->hdmi_params[3] = 0;
642 else
643 data->hdmi_params[3] = 0xc0;
644 data->hdmi_params[4] = 1; /* ? */
645 hdmi_write_command(chip, 0x54, 5, data->hdmi_params);
646}
647
648static void set_hdav_params(struct oxygen *chip,
649 struct snd_pcm_hw_params *params)
650{
651 set_pcm1796_params(chip, params);
652 set_hdmi_params(chip, params);
653}
654
463static void xonar_gpio_changed(struct oxygen *chip) 655static void xonar_gpio_changed(struct oxygen *chip)
464{ 656{
465 struct xonar_data *data = chip->model_data; 657 struct xonar_data *data = chip->model_data;
@@ -479,6 +671,18 @@ static void xonar_gpio_changed(struct oxygen *chip)
479 } 671 }
480} 672}
481 673
674static void xonar_hdav_uart_input(struct oxygen *chip)
675{
676 if (chip->uart_input_count >= 2 &&
677 chip->uart_input[chip->uart_input_count - 2] == 'O' &&
678 chip->uart_input[chip->uart_input_count - 1] == 'K') {
679 printk(KERN_DEBUG "message from Xonar HDAV HDMI chip received:");
680 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
681 chip->uart_input, chip->uart_input_count);
682 chip->uart_input_count = 0;
683 }
684}
685
482static int gpio_bit_switch_get(struct snd_kcontrol *ctl, 686static int gpio_bit_switch_get(struct snd_kcontrol *ctl,
483 struct snd_ctl_elem_value *value) 687 struct snd_ctl_elem_value *value)
484{ 688{
@@ -576,16 +780,33 @@ static int xonar_model_probe(struct oxygen *chip, unsigned long driver_data)
576 [MODEL_DX] = "Xonar DX", 780 [MODEL_DX] = "Xonar DX",
577 [MODEL_D2] = "Xonar D2", 781 [MODEL_D2] = "Xonar D2",
578 [MODEL_D2X] = "Xonar D2X", 782 [MODEL_D2X] = "Xonar D2X",
783 [MODEL_HDAV] = "Xonar HDAV1.3",
784 [MODEL_HDAV_H6] = "Xonar HDAV1.3+H6",
579 }; 785 };
580 static const u8 dacs[] = { 786 static const u8 dacs[] = {
581 [MODEL_D1] = 2, 787 [MODEL_D1] = 2,
582 [MODEL_DX] = 2, 788 [MODEL_DX] = 2,
583 [MODEL_D2] = 4, 789 [MODEL_D2] = 4,
584 [MODEL_D2X] = 4, 790 [MODEL_D2X] = 4,
791 [MODEL_HDAV] = 1,
792 [MODEL_HDAV_H6] = 4,
585 }; 793 };
586 struct xonar_data *data = chip->model_data; 794 struct xonar_data *data = chip->model_data;
587 795
588 data->model = driver_data; 796 data->model = driver_data;
797 if (data->model == MODEL_HDAV) {
798 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
799 GPIO_HDAV_DB_MASK);
800 switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) &
801 GPIO_HDAV_DB_MASK) {
802 case GPIO_HDAV_DB_H6:
803 data->model = MODEL_HDAV_H6;
804 break;
805 case GPIO_HDAV_DB_XX:
806 snd_printk(KERN_ERR "unknown daughterboard\n");
807 return -ENODEV;
808 }
809 }
589 810
590 data->dacs = dacs[data->model]; 811 data->dacs = dacs[data->model];
591 chip->model.shortname = names[data->model]; 812 chip->model.shortname = names[data->model];
@@ -654,6 +875,35 @@ static const struct oxygen_model model_xonar_d1 = {
654 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 875 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
655}; 876};
656 877
878static const struct oxygen_model model_xonar_hdav = {
879 .longname = "Asus Virtuoso 200",
880 .chip = "AV200",
881 .owner = THIS_MODULE,
882 .probe = xonar_model_probe,
883 .init = xonar_hdav_init,
884 .cleanup = xonar_hdav_cleanup,
885 .suspend = xonar_hdav_suspend,
886 .resume = xonar_hdav_resume,
887 .pcm_hardware_filter = xonar_hdav_pcm_hardware_filter,
888 .set_dac_params = set_hdav_params,
889 .set_adc_params = set_cs53x1_params,
890 .update_dac_volume = update_pcm1796_volume,
891 .update_dac_mute = update_pcm1796_mute,
892 .uart_input = xonar_hdav_uart_input,
893 .ac97_switch = xonar_line_mic_ac97_switch,
894 .dac_tlv = pcm1796_db_scale,
895 .model_data_size = sizeof(struct xonar_data),
896 .device_config = PLAYBACK_0_TO_I2S |
897 PLAYBACK_1_TO_SPDIF |
898 CAPTURE_0_FROM_I2S_2,
899 .dac_channels = 8,
900 .dac_volume_min = 0x0f,
901 .dac_volume_max = 0xff,
902 .function_flags = OXYGEN_FUNCTION_2WIRE,
903 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
904 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
905};
906
657static int __devinit xonar_probe(struct pci_dev *pci, 907static int __devinit xonar_probe(struct pci_dev *pci,
658 const struct pci_device_id *pci_id) 908 const struct pci_device_id *pci_id)
659{ 909{
@@ -662,6 +912,7 @@ static int __devinit xonar_probe(struct pci_dev *pci,
662 [MODEL_DX] = &model_xonar_d1, 912 [MODEL_DX] = &model_xonar_d1,
663 [MODEL_D2] = &model_xonar_d2, 913 [MODEL_D2] = &model_xonar_d2,
664 [MODEL_D2X] = &model_xonar_d2, 914 [MODEL_D2X] = &model_xonar_d2,
915 [MODEL_HDAV] = &model_xonar_hdav,
665 }; 916 };
666 static int dev; 917 static int dev;
667 int err; 918 int err;