aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/pcxhr
diff options
context:
space:
mode:
authorMarkus Bollinger <bollinger@digigram.com>2009-01-23 08:45:41 -0500
committerTakashi Iwai <tiwai@suse.de>2009-01-23 08:45:41 -0500
commit55aef4508598d59c2baea7e2a3e6dfed415bbfc0 (patch)
tree933e5b7029b9471bab5c260b58f2293812e9d77c /sound/pci/pcxhr
parent1de9e8e70f5acc441550ca75433563d91b269bbe (diff)
ALSA: pcxhr - add support for gpio ports and minor bug fix
- add support for gpio ports (2 GPI, 2 GPO) of pcxhr stereo cards - minor bugfixes : allow setting clock to internal by the mixer even if there is no stream (but monitoring) Signed-off-by: Markus Bollinger <bollinger@digigram.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/pcxhr')
-rw-r--r--sound/pci/pcxhr/pcxhr.c41
-rw-r--r--sound/pci/pcxhr/pcxhr.h5
-rw-r--r--sound/pci/pcxhr/pcxhr_mix22.c40
-rw-r--r--sound/pci/pcxhr/pcxhr_mix22.h3
-rw-r--r--sound/pci/pcxhr/pcxhr_mixer.c8
5 files changed, 89 insertions, 8 deletions
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 27cf2c28d113..ca89106f8c5d 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -1334,6 +1334,40 @@ static void pcxhr_proc_sync(struct snd_info_entry *entry,
1334 snd_iprintf(buffer, "\n"); 1334 snd_iprintf(buffer, "\n");
1335} 1335}
1336 1336
1337static void pcxhr_proc_gpio_read(struct snd_info_entry *entry,
1338 struct snd_info_buffer *buffer)
1339{
1340 struct snd_pcxhr *chip = entry->private_data;
1341 struct pcxhr_mgr *mgr = chip->mgr;
1342 /* commands available when embedded DSP is running */
1343 if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
1344 /* gpio ports on stereo boards only available */
1345 int value = 0;
1346 hr222_read_gpio(mgr, 1, &value); /* GPI */
1347 snd_iprintf(buffer, "GPI: 0x%x\n", value);
1348 hr222_read_gpio(mgr, 0, &value); /* GP0 */
1349 snd_iprintf(buffer, "GPO: 0x%x\n", value);
1350 } else
1351 snd_iprintf(buffer, "no firmware loaded\n");
1352 snd_iprintf(buffer, "\n");
1353}
1354static void pcxhr_proc_gpo_write(struct snd_info_entry *entry,
1355 struct snd_info_buffer *buffer)
1356{
1357 struct snd_pcxhr *chip = entry->private_data;
1358 struct pcxhr_mgr *mgr = chip->mgr;
1359 char line[64];
1360 int value;
1361 /* commands available when embedded DSP is running */
1362 if (!(mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)))
1363 return;
1364 while (!snd_info_get_line(buffer, line, sizeof(line))) {
1365 if (sscanf(line, "GPO: 0x%x", &value) != 1)
1366 continue;
1367 hr222_write_gpo(mgr, value); /* GP0 */
1368 }
1369}
1370
1337static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) 1371static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip)
1338{ 1372{
1339 struct snd_info_entry *entry; 1373 struct snd_info_entry *entry;
@@ -1342,6 +1376,13 @@ static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip)
1342 snd_info_set_text_ops(entry, chip, pcxhr_proc_info); 1376 snd_info_set_text_ops(entry, chip, pcxhr_proc_info);
1343 if (! snd_card_proc_new(chip->card, "sync", &entry)) 1377 if (! snd_card_proc_new(chip->card, "sync", &entry))
1344 snd_info_set_text_ops(entry, chip, pcxhr_proc_sync); 1378 snd_info_set_text_ops(entry, chip, pcxhr_proc_sync);
1379 /* gpio available on stereo sound cards only */
1380 if (chip->mgr->is_hr_stereo &&
1381 !snd_card_proc_new(chip->card, "gpio", &entry)) {
1382 snd_info_set_text_ops(entry, chip, pcxhr_proc_gpio_read);
1383 entry->c.text.write = pcxhr_proc_gpo_write;
1384 entry->mode |= S_IWUSR;
1385 }
1345} 1386}
1346/* end of proc interface */ 1387/* end of proc interface */
1347 1388
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h
index 84131a916c92..ac9c3b3bb4e8 100644
--- a/sound/pci/pcxhr/pcxhr.h
+++ b/sound/pci/pcxhr/pcxhr.h
@@ -27,8 +27,8 @@
27#include <linux/mutex.h> 27#include <linux/mutex.h>
28#include <sound/pcm.h> 28#include <sound/pcm.h>
29 29
30#define PCXHR_DRIVER_VERSION 0x000905 /* 0.9.5 */ 30#define PCXHR_DRIVER_VERSION 0x000906 /* 0.9.6 */
31#define PCXHR_DRIVER_VERSION_STRING "0.9.5" /* 0.9.5 */ 31#define PCXHR_DRIVER_VERSION_STRING "0.9.6" /* 0.9.6 */
32 32
33 33
34#define PCXHR_MAX_CARDS 6 34#define PCXHR_MAX_CARDS 6
@@ -124,6 +124,7 @@ struct pcxhr_mgr {
124 124
125 unsigned char xlx_cfg; /* copy of PCXHR_XLX_CFG register */ 125 unsigned char xlx_cfg; /* copy of PCXHR_XLX_CFG register */
126 unsigned char xlx_selmic; /* copy of PCXHR_XLX_SELMIC register */ 126 unsigned char xlx_selmic; /* copy of PCXHR_XLX_SELMIC register */
127 unsigned char dsp_reset; /* copy of PCXHR_DSP_RESET register */
127}; 128};
128 129
129 130
diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c
index ff019126b672..1cb82c0a9cb3 100644
--- a/sound/pci/pcxhr/pcxhr_mix22.c
+++ b/sound/pci/pcxhr/pcxhr_mix22.c
@@ -53,6 +53,8 @@
53#define PCXHR_DSP_RESET_DSP 0x01 53#define PCXHR_DSP_RESET_DSP 0x01
54#define PCXHR_DSP_RESET_MUTE 0x02 54#define PCXHR_DSP_RESET_MUTE 0x02
55#define PCXHR_DSP_RESET_CODEC 0x08 55#define PCXHR_DSP_RESET_CODEC 0x08
56#define PCXHR_DSP_RESET_GPO_OFFSET 5
57#define PCXHR_DSP_RESET_GPO_MASK 0x60
56 58
57/* values for PCHR_XLX_CFG register */ 59/* values for PCHR_XLX_CFG register */
58#define PCXHR_CFG_SYNCDSP_MASK 0x80 60#define PCXHR_CFG_SYNCDSP_MASK 0x80
@@ -81,6 +83,8 @@
81/* values for PCHR_XLX_STATUS register - READ */ 83/* values for PCHR_XLX_STATUS register - READ */
82#define PCXHR_STAT_SRC_LOCK 0x01 84#define PCXHR_STAT_SRC_LOCK 0x01
83#define PCXHR_STAT_LEVEL_IN 0x02 85#define PCXHR_STAT_LEVEL_IN 0x02
86#define PCXHR_STAT_GPI_OFFSET 2
87#define PCXHR_STAT_GPI_MASK 0x0C
84#define PCXHR_STAT_MIC_CAPS 0x10 88#define PCXHR_STAT_MIC_CAPS 0x10
85/* values for PCHR_XLX_STATUS register - WRITE */ 89/* values for PCHR_XLX_STATUS register - WRITE */
86#define PCXHR_STAT_FREQ_SYNC_MASK 0x01 90#define PCXHR_STAT_FREQ_SYNC_MASK 0x01
@@ -291,10 +295,11 @@ int hr222_sub_init(struct pcxhr_mgr *mgr)
291 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, 295 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET,
292 PCXHR_DSP_RESET_DSP); 296 PCXHR_DSP_RESET_DSP);
293 msleep(5); 297 msleep(5);
294 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, 298 mgr->dsp_reset = PCXHR_DSP_RESET_DSP |
295 PCXHR_DSP_RESET_DSP | 299 PCXHR_DSP_RESET_MUTE |
296 PCXHR_DSP_RESET_MUTE | 300 PCXHR_DSP_RESET_CODEC;
297 PCXHR_DSP_RESET_CODEC); 301 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset);
302 /* hr222_write_gpo(mgr, 0); does the same */
298 msleep(5); 303 msleep(5);
299 304
300 /* config AKM */ 305 /* config AKM */
@@ -496,6 +501,33 @@ int hr222_get_external_clock(struct pcxhr_mgr *mgr,
496} 501}
497 502
498 503
504int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value)
505{
506 if (is_gpi) {
507 unsigned char reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS);
508 *value = (int)(reg & PCXHR_STAT_GPI_MASK) >>
509 PCXHR_STAT_GPI_OFFSET;
510 } else {
511 *value = (int)(mgr->dsp_reset & PCXHR_DSP_RESET_GPO_MASK) >>
512 PCXHR_DSP_RESET_GPO_OFFSET;
513 }
514 return 0;
515}
516
517
518int hr222_write_gpo(struct pcxhr_mgr *mgr, int value)
519{
520 unsigned char reg = mgr->dsp_reset & ~PCXHR_DSP_RESET_GPO_MASK;
521
522 reg |= (unsigned char)(value << PCXHR_DSP_RESET_GPO_OFFSET) &
523 PCXHR_DSP_RESET_GPO_MASK;
524
525 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, reg);
526 mgr->dsp_reset = reg;
527 return 0;
528}
529
530
499int hr222_update_analog_audio_level(struct snd_pcxhr *chip, 531int hr222_update_analog_audio_level(struct snd_pcxhr *chip,
500 int is_capture, int channel) 532 int is_capture, int channel)
501{ 533{
diff --git a/sound/pci/pcxhr/pcxhr_mix22.h b/sound/pci/pcxhr/pcxhr_mix22.h
index 6b318b2f0100..5a37a0007e8f 100644
--- a/sound/pci/pcxhr/pcxhr_mix22.h
+++ b/sound/pci/pcxhr/pcxhr_mix22.h
@@ -32,6 +32,9 @@ int hr222_get_external_clock(struct pcxhr_mgr *mgr,
32 enum pcxhr_clock_type clock_type, 32 enum pcxhr_clock_type clock_type,
33 int *sample_rate); 33 int *sample_rate);
34 34
35int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value);
36int hr222_write_gpo(struct pcxhr_mgr *mgr, int value);
37
35#define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */ 38#define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */
36#define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */ 39#define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */
37#define HR222_LINE_PLAYBACK_LEVEL_MAX 99 /* +24.0 dB */ 40#define HR222_LINE_PLAYBACK_LEVEL_MAX 99 /* +24.0 dB */
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c
index 2436e374586f..fec049344621 100644
--- a/sound/pci/pcxhr/pcxhr_mixer.c
+++ b/sound/pci/pcxhr/pcxhr_mixer.c
@@ -789,11 +789,15 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
789 if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) { 789 if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) {
790 mutex_lock(&mgr->setup_mutex); 790 mutex_lock(&mgr->setup_mutex);
791 mgr->use_clock_type = ucontrol->value.enumerated.item[0]; 791 mgr->use_clock_type = ucontrol->value.enumerated.item[0];
792 if (mgr->use_clock_type) 792 rate = 0;
793 if (mgr->use_clock_type != PCXHR_CLOCK_TYPE_INTERNAL) {
793 pcxhr_get_external_clock(mgr, mgr->use_clock_type, 794 pcxhr_get_external_clock(mgr, mgr->use_clock_type,
794 &rate); 795 &rate);
795 else 796 } else {
796 rate = mgr->sample_rate; 797 rate = mgr->sample_rate;
798 if (!rate)
799 rate = 48000;
800 }
797 if (rate) { 801 if (rate) {
798 pcxhr_set_clock(mgr, rate); 802 pcxhr_set_clock(mgr, rate);
799 if (mgr->sample_rate) 803 if (mgr->sample_rate)