diff options
Diffstat (limited to 'sound/pci/rme9652/hdsp.c')
-rw-r--r-- | sound/pci/rme9652/hdsp.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 849ffe4aa5ca..89b3c7ff5037 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -80,6 +80,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," | |||
80 | /* Write registers. These are defined as byte-offsets from the iobase value. | 80 | /* Write registers. These are defined as byte-offsets from the iobase value. |
81 | */ | 81 | */ |
82 | #define HDSP_resetPointer 0 | 82 | #define HDSP_resetPointer 0 |
83 | #define HDSP_freqReg 0 | ||
83 | #define HDSP_outputBufferAddress 32 | 84 | #define HDSP_outputBufferAddress 32 |
84 | #define HDSP_inputBufferAddress 36 | 85 | #define HDSP_inputBufferAddress 36 |
85 | #define HDSP_controlRegister 64 | 86 | #define HDSP_controlRegister 64 |
@@ -469,6 +470,7 @@ struct hdsp { | |||
469 | struct pci_dev *pci; | 470 | struct pci_dev *pci; |
470 | struct snd_kcontrol *spdif_ctl; | 471 | struct snd_kcontrol *spdif_ctl; |
471 | unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE]; | 472 | unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE]; |
473 | unsigned int dds_value; /* last value written to freq register */ | ||
472 | }; | 474 | }; |
473 | 475 | ||
474 | /* These tables map the ALSA channels 1..N to the channels that we | 476 | /* These tables map the ALSA channels 1..N to the channels that we |
@@ -940,6 +942,11 @@ static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp) | |||
940 | static void hdsp_reset_hw_pointer(struct hdsp *hdsp) | 942 | static void hdsp_reset_hw_pointer(struct hdsp *hdsp) |
941 | { | 943 | { |
942 | hdsp_write (hdsp, HDSP_resetPointer, 0); | 944 | hdsp_write (hdsp, HDSP_resetPointer, 0); |
945 | if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152) | ||
946 | /* HDSP_resetPointer = HDSP_freqReg, which is strange and | ||
947 | * requires (?) to write again DDS value after a reset pointer | ||
948 | * (at least, it works like this) */ | ||
949 | hdsp_write (hdsp, HDSP_freqReg, hdsp->dds_value); | ||
943 | } | 950 | } |
944 | 951 | ||
945 | static void hdsp_start_audio(struct hdsp *s) | 952 | static void hdsp_start_audio(struct hdsp *s) |
@@ -984,6 +991,30 @@ static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames) | |||
984 | return 0; | 991 | return 0; |
985 | } | 992 | } |
986 | 993 | ||
994 | static void hdsp_set_dds_value(struct hdsp *hdsp, int rate) | ||
995 | { | ||
996 | u64 n; | ||
997 | u32 r; | ||
998 | |||
999 | if (rate >= 112000) | ||
1000 | rate /= 4; | ||
1001 | else if (rate >= 56000) | ||
1002 | rate /= 2; | ||
1003 | |||
1004 | /* RME says n = 104857600000000, but in the windows MADI driver, I see: | ||
1005 | // return 104857600000000 / rate; // 100 MHz | ||
1006 | return 110100480000000 / rate; // 105 MHz | ||
1007 | */ | ||
1008 | n = 104857600000000ULL; /* = 2^20 * 10^8 */ | ||
1009 | div64_32(&n, rate, &r); | ||
1010 | /* n should be less than 2^32 for being written to FREQ register */ | ||
1011 | snd_assert((n >> 32) == 0); | ||
1012 | /* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS | ||
1013 | value to write it after a reset */ | ||
1014 | hdsp->dds_value = n; | ||
1015 | hdsp_write(hdsp, HDSP_freqReg, hdsp->dds_value); | ||
1016 | } | ||
1017 | |||
987 | static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) | 1018 | static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) |
988 | { | 1019 | { |
989 | int reject_if_open = 0; | 1020 | int reject_if_open = 0; |
@@ -1092,6 +1123,10 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) | |||
1092 | hdsp->control_register |= rate_bits; | 1123 | hdsp->control_register |= rate_bits; |
1093 | hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); | 1124 | hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); |
1094 | 1125 | ||
1126 | /* For HDSP9632 rev 152, need to set DDS value in FREQ register */ | ||
1127 | if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152) | ||
1128 | hdsp_set_dds_value(hdsp, rate); | ||
1129 | |||
1095 | if (rate >= 128000) { | 1130 | if (rate >= 128000) { |
1096 | hdsp->channel_map = channel_map_H9632_qs; | 1131 | hdsp->channel_map = channel_map_H9632_qs; |
1097 | } else if (rate > 48000) { | 1132 | } else if (rate > 48000) { |
@@ -4945,6 +4980,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card, | |||
4945 | hdsp->irq = pci->irq; | 4980 | hdsp->irq = pci->irq; |
4946 | hdsp->precise_ptr = 0; | 4981 | hdsp->precise_ptr = 0; |
4947 | hdsp->use_midi_tasklet = 1; | 4982 | hdsp->use_midi_tasklet = 1; |
4983 | hdsp->dds_value = 0; | ||
4948 | 4984 | ||
4949 | if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) | 4985 | if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) |
4950 | return err; | 4986 | return err; |