diff options
author | Markus Bollinger <bollinger@digigram.com> | 2012-06-20 02:34:40 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-06-20 02:35:37 -0400 |
commit | fdfbaf69e0b9d6843c0da6501caf4ecacec0f775 (patch) | |
tree | d8d8104c9b310f87d18d5995ce6da12908211054 /sound/pci | |
parent | d7dc9e32ae64b5db777017344da61a285c2347f8 (diff) |
ALSA: pcxhr: Add LTC support
add LTC (linear timecode) read function via proc interface to the pcxhr driver
Signed-off-by: Markus Bollinger <bollinger@digigram.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/pcxhr/pcxhr.c | 63 | ||||
-rw-r--r-- | sound/pci/pcxhr/pcxhr.h | 1 | ||||
-rw-r--r-- | sound/pci/pcxhr/pcxhr_core.c | 4 | ||||
-rw-r--r-- | sound/pci/pcxhr/pcxhr_core.h | 4 | ||||
-rw-r--r-- | sound/pci/pcxhr/pcxhr_mix22.c | 11 | ||||
-rw-r--r-- | sound/pci/pcxhr/pcxhr_mix22.h | 1 |
6 files changed, 83 insertions, 1 deletions
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 0435f45e9513..e3ac1f768ff6 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
@@ -1368,6 +1368,67 @@ static void pcxhr_proc_gpo_write(struct snd_info_entry *entry, | |||
1368 | } | 1368 | } |
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | /* Access to the results of the CMD_GET_TIME_CODE RMH */ | ||
1372 | #define TIME_CODE_VALID_MASK 0x00800000 | ||
1373 | #define TIME_CODE_NEW_MASK 0x00400000 | ||
1374 | #define TIME_CODE_BACK_MASK 0x00200000 | ||
1375 | #define TIME_CODE_WAIT_MASK 0x00100000 | ||
1376 | |||
1377 | /* Values for the CMD_MANAGE_SIGNAL RMH */ | ||
1378 | #define MANAGE_SIGNAL_TIME_CODE 0x01 | ||
1379 | #define MANAGE_SIGNAL_MIDI 0x02 | ||
1380 | |||
1381 | /* linear time code read proc*/ | ||
1382 | static void pcxhr_proc_ltc(struct snd_info_entry *entry, | ||
1383 | struct snd_info_buffer *buffer) | ||
1384 | { | ||
1385 | struct snd_pcxhr *chip = entry->private_data; | ||
1386 | struct pcxhr_mgr *mgr = chip->mgr; | ||
1387 | struct pcxhr_rmh rmh; | ||
1388 | unsigned int ltcHrs, ltcMin, ltcSec, ltcFrm; | ||
1389 | int err; | ||
1390 | /* commands available when embedded DSP is running */ | ||
1391 | if (!(mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))) { | ||
1392 | snd_iprintf(buffer, "no firmware loaded\n"); | ||
1393 | return; | ||
1394 | } | ||
1395 | if (!mgr->capture_ltc) { | ||
1396 | pcxhr_init_rmh(&rmh, CMD_MANAGE_SIGNAL); | ||
1397 | rmh.cmd[0] |= MANAGE_SIGNAL_TIME_CODE; | ||
1398 | err = pcxhr_send_msg(mgr, &rmh); | ||
1399 | if (err) { | ||
1400 | snd_iprintf(buffer, "ltc not activated (%d)\n", err); | ||
1401 | return; | ||
1402 | } | ||
1403 | if (mgr->is_hr_stereo) | ||
1404 | hr222_manage_timecode(mgr, 1); | ||
1405 | else | ||
1406 | pcxhr_write_io_num_reg_cont(mgr, REG_CONT_VALSMPTE, | ||
1407 | REG_CONT_VALSMPTE, NULL); | ||
1408 | mgr->capture_ltc = 1; | ||
1409 | } | ||
1410 | pcxhr_init_rmh(&rmh, CMD_GET_TIME_CODE); | ||
1411 | err = pcxhr_send_msg(mgr, &rmh); | ||
1412 | if (err) { | ||
1413 | snd_iprintf(buffer, "ltc read error (err=%d)\n", err); | ||
1414 | return ; | ||
1415 | } | ||
1416 | ltcHrs = 10*((rmh.stat[0] >> 8) & 0x3) + (rmh.stat[0] & 0xf); | ||
1417 | ltcMin = 10*((rmh.stat[1] >> 16) & 0x7) + ((rmh.stat[1] >> 8) & 0xf); | ||
1418 | ltcSec = 10*(rmh.stat[1] & 0x7) + ((rmh.stat[2] >> 16) & 0xf); | ||
1419 | ltcFrm = 10*((rmh.stat[2] >> 8) & 0x3) + (rmh.stat[2] & 0xf); | ||
1420 | |||
1421 | snd_iprintf(buffer, "timecode: %02u:%02u:%02u-%02u\n", | ||
1422 | ltcHrs, ltcMin, ltcSec, ltcFrm); | ||
1423 | snd_iprintf(buffer, "raw: 0x%04x%06x%06x\n", rmh.stat[0] & 0x00ffff, | ||
1424 | rmh.stat[1] & 0xffffff, rmh.stat[2] & 0xffffff); | ||
1425 | /*snd_iprintf(buffer, "dsp ref time: 0x%06x%06x\n", | ||
1426 | rmh.stat[3] & 0xffffff, rmh.stat[4] & 0xffffff);*/ | ||
1427 | if (!(rmh.stat[0] & TIME_CODE_VALID_MASK)) { | ||
1428 | snd_iprintf(buffer, "warning: linear timecode not valid\n"); | ||
1429 | } | ||
1430 | } | ||
1431 | |||
1371 | static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) | 1432 | static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) |
1372 | { | 1433 | { |
1373 | struct snd_info_entry *entry; | 1434 | struct snd_info_entry *entry; |
@@ -1383,6 +1444,8 @@ static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) | |||
1383 | entry->c.text.write = pcxhr_proc_gpo_write; | 1444 | entry->c.text.write = pcxhr_proc_gpo_write; |
1384 | entry->mode |= S_IWUSR; | 1445 | entry->mode |= S_IWUSR; |
1385 | } | 1446 | } |
1447 | if (!snd_card_proc_new(chip->card, "ltc", &entry)) | ||
1448 | snd_info_set_text_ops(entry, chip, pcxhr_proc_ltc); | ||
1386 | } | 1449 | } |
1387 | /* end of proc interface */ | 1450 | /* end of proc interface */ |
1388 | 1451 | ||
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h index bda776c49884..a4c602c45173 100644 --- a/sound/pci/pcxhr/pcxhr.h +++ b/sound/pci/pcxhr/pcxhr.h | |||
@@ -103,6 +103,7 @@ struct pcxhr_mgr { | |||
103 | unsigned int board_has_mic:1; /* if 1 the board has microphone input */ | 103 | unsigned int board_has_mic:1; /* if 1 the board has microphone input */ |
104 | unsigned int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */ | 104 | unsigned int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */ |
105 | unsigned int mono_capture:1; /* if 1 the board does mono capture */ | 105 | unsigned int mono_capture:1; /* if 1 the board does mono capture */ |
106 | unsigned int capture_ltc:1; /* if 1 the board captures LTC input */ | ||
106 | 107 | ||
107 | struct snd_dma_buffer hostport; | 108 | struct snd_dma_buffer hostport; |
108 | 109 | ||
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index 841703b5c52a..b33db1e006e7 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c | |||
@@ -504,6 +504,8 @@ static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = { | |||
504 | [CMD_FORMAT_STREAM_IN] = { 0x870000, 0, RMH_SSIZE_FIXED }, | 504 | [CMD_FORMAT_STREAM_IN] = { 0x870000, 0, RMH_SSIZE_FIXED }, |
505 | [CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED }, | 505 | [CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED }, |
506 | [CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED }, | 506 | [CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED }, |
507 | [CMD_GET_TIME_CODE] = { 0x060000, 5, RMH_SSIZE_FIXED }, | ||
508 | [CMD_MANAGE_SIGNAL] = { 0x0f0000, 0, RMH_SSIZE_FIXED }, | ||
507 | }; | 509 | }; |
508 | 510 | ||
509 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 511 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
@@ -533,6 +535,8 @@ static char* cmd_names[] = { | |||
533 | [CMD_FORMAT_STREAM_IN] = "CMD_FORMAT_STREAM_IN", | 535 | [CMD_FORMAT_STREAM_IN] = "CMD_FORMAT_STREAM_IN", |
534 | [CMD_STREAM_SAMPLE_COUNT] = "CMD_STREAM_SAMPLE_COUNT", | 536 | [CMD_STREAM_SAMPLE_COUNT] = "CMD_STREAM_SAMPLE_COUNT", |
535 | [CMD_AUDIO_LEVEL_ADJUST] = "CMD_AUDIO_LEVEL_ADJUST", | 537 | [CMD_AUDIO_LEVEL_ADJUST] = "CMD_AUDIO_LEVEL_ADJUST", |
538 | [CMD_GET_TIME_CODE] = "CMD_GET_TIME_CODE", | ||
539 | [CMD_MANAGE_SIGNAL] = "CMD_MANAGE_SIGNAL", | ||
536 | }; | 540 | }; |
537 | #endif | 541 | #endif |
538 | 542 | ||
diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h index be0173796cdb..a81ab6b811e7 100644 --- a/sound/pci/pcxhr/pcxhr_core.h +++ b/sound/pci/pcxhr/pcxhr_core.h | |||
@@ -79,6 +79,8 @@ enum { | |||
79 | CMD_FORMAT_STREAM_IN, /* cmd_len >= 4 stat_len = 0 */ | 79 | CMD_FORMAT_STREAM_IN, /* cmd_len >= 4 stat_len = 0 */ |
80 | CMD_STREAM_SAMPLE_COUNT, /* cmd_len = 2 stat_len = (2 * nb_stream) */ | 80 | CMD_STREAM_SAMPLE_COUNT, /* cmd_len = 2 stat_len = (2 * nb_stream) */ |
81 | CMD_AUDIO_LEVEL_ADJUST, /* cmd_len = 3 stat_len = 0 */ | 81 | CMD_AUDIO_LEVEL_ADJUST, /* cmd_len = 3 stat_len = 0 */ |
82 | CMD_GET_TIME_CODE, /* cmd_len = 1 stat_len = 5 */ | ||
83 | CMD_MANAGE_SIGNAL, /* cmd_len = 1 stat_len = 0 */ | ||
82 | CMD_LAST_INDEX | 84 | CMD_LAST_INDEX |
83 | }; | 85 | }; |
84 | 86 | ||
@@ -116,7 +118,7 @@ int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh); | |||
116 | #define IO_NUM_REG_OUT_ANA_LEVEL 20 | 118 | #define IO_NUM_REG_OUT_ANA_LEVEL 20 |
117 | #define IO_NUM_REG_IN_ANA_LEVEL 21 | 119 | #define IO_NUM_REG_IN_ANA_LEVEL 21 |
118 | 120 | ||
119 | 121 | #define REG_CONT_VALSMPTE 0x000800 | |
120 | #define REG_CONT_UNMUTE_INPUTS 0x020000 | 122 | #define REG_CONT_UNMUTE_INPUTS 0x020000 |
121 | 123 | ||
122 | /* parameters used with register IO_NUM_REG_STATUS */ | 124 | /* parameters used with register IO_NUM_REG_STATUS */ |
diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c index 1cb82c0a9cb3..84fe57626eba 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.c +++ b/sound/pci/pcxhr/pcxhr_mix22.c | |||
@@ -53,6 +53,7 @@ | |||
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_SMPTE 0x10 | ||
56 | #define PCXHR_DSP_RESET_GPO_OFFSET 5 | 57 | #define PCXHR_DSP_RESET_GPO_OFFSET 5 |
57 | #define PCXHR_DSP_RESET_GPO_MASK 0x60 | 58 | #define PCXHR_DSP_RESET_GPO_MASK 0x60 |
58 | 59 | ||
@@ -527,6 +528,16 @@ int hr222_write_gpo(struct pcxhr_mgr *mgr, int value) | |||
527 | return 0; | 528 | return 0; |
528 | } | 529 | } |
529 | 530 | ||
531 | int hr222_manage_timecode(struct pcxhr_mgr *mgr, int enable) | ||
532 | { | ||
533 | if (enable) | ||
534 | mgr->dsp_reset |= PCXHR_DSP_RESET_SMPTE; | ||
535 | else | ||
536 | mgr->dsp_reset &= ~PCXHR_DSP_RESET_SMPTE; | ||
537 | |||
538 | PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset); | ||
539 | return 0; | ||
540 | } | ||
530 | 541 | ||
531 | int hr222_update_analog_audio_level(struct snd_pcxhr *chip, | 542 | int hr222_update_analog_audio_level(struct snd_pcxhr *chip, |
532 | int is_capture, int channel) | 543 | int is_capture, int channel) |
diff --git a/sound/pci/pcxhr/pcxhr_mix22.h b/sound/pci/pcxhr/pcxhr_mix22.h index 5a37a0007e8f..5971b9933f41 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.h +++ b/sound/pci/pcxhr/pcxhr_mix22.h | |||
@@ -34,6 +34,7 @@ int hr222_get_external_clock(struct pcxhr_mgr *mgr, | |||
34 | 34 | ||
35 | int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value); | 35 | int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value); |
36 | int hr222_write_gpo(struct pcxhr_mgr *mgr, int value); | 36 | int hr222_write_gpo(struct pcxhr_mgr *mgr, int value); |
37 | int hr222_manage_timecode(struct pcxhr_mgr *mgr, int enable); | ||
37 | 38 | ||
38 | #define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */ | 39 | #define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */ |
39 | #define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */ | 40 | #define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */ |