diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-01-16 15:28:19 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-01-16 15:29:17 +0100 |
commit | 77b2b59ed61513fb339d5bdeb8100d2cc7d383f4 (patch) | |
tree | 370d28b7ff97b9801be02649549ae16c67142420 | |
parent | 45e66120b51a92ddf99ea43432108e94e9828482 (diff) | |
download | hda-emu-77b2b59ed61513fb339d5bdeb8100d2cc7d383f4.tar.gz |
Add -i and -r options to pm command
Add options to initialize/randomize pinctls and amps before resume so
that we can check the resume procedure more intensively.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | README | 6 | ||||
-rw-r--r-- | hda-ctlsh.c | 42 | ||||
-rw-r--r-- | hda-emu.c | 61 | ||||
-rw-r--r-- | hda-parse.c | 12 | ||||
-rw-r--r-- | include/hda-log.h | 3 | ||||
-rw-r--r-- | include/hda-types.h | 3 |
6 files changed, 122 insertions, 5 deletions
@@ -298,6 +298,12 @@ BASIC COMMANDS Simulate suspend/resume cycle. + When option -i is given, the pin control values and the in/out amp + values are reset to the initial state before resume. When option -r + is given, the pin control values and the in/out amp values are set + randomly before resume. These options are useful to check whether + the resume procedure properly restores the values. + * quit Quit the shell. diff --git a/hda-ctlsh.c b/hda-ctlsh.c index 2b53530..9093b07 100644 --- a/hda-ctlsh.c +++ b/hda-ctlsh.c @@ -508,10 +508,48 @@ static int get_pcm_substream(char *id) return strtoul(id + 1, NULL, 0); } +enum { + TEST_PM_NORMAL, + TEST_PM_RANDOMIZE, + TEST_PM_REINIT, +}; + static void test_pm(char *line) { + char *token; + int mode = TEST_PM_NORMAL; + + while ((token = gettoken(&line))) { + if (*token == '-') { + switch (token[1]) { + case 'r': + mode = TEST_PM_RANDOMIZE; + break; + case 'i': + mode = TEST_PM_REINIT; + break; + default: + usage("pm"); + return; + } + } else { + usage("pm"); + return; + } + } + hda_log(HDA_LOG_INFO, "** SUSPENDING **\n"); hda_test_suspend(); + switch (mode) { + case TEST_PM_RANDOMIZE: + hda_log(HDA_LOG_INFO, "** randomize **\n"); + hda_test_pm_randomize(); + break; + case TEST_PM_REINIT: + hda_log(HDA_LOG_INFO, "** init **\n"); + hda_test_pm_reinit(); + break; + } hda_log(HDA_LOG_INFO, "** RESUMING **\n"); hda_test_resume(); hda_log(HDA_LOG_INFO, "** TEST_PM DONE **\n"); @@ -811,8 +849,8 @@ static struct usage_table usage_str[] = { { "PCM", "PCM [-s|-e] [pcm-id dir [rate [channels [format-bits]]]]", "List PCM streams or test the given PCM stream", test_pcm }, - { "pm", "pm", - "Test suspend/resume cycle", + { "pm", "pm [-i|-r]", + "Test suspend/resume cycle; -i = re-init pins/amps, -r = randomize pins/amps", test_pm }, #ifdef CONFIG_SND_HDA_RECONFIG { "fs", "fs {get|set|list} file args...", @@ -29,6 +29,7 @@ #include <errno.h> #include <signal.h> #include <unistd.h> +#include <time.h> #include "hda-types.h" #include "hda-log.h" @@ -415,6 +416,64 @@ void hda_test_resume(void) snd_hda_resume(bus); } +static inline unsigned int random_bit(unsigned int pincap, unsigned int mask, + unsigned int bit) +{ + if (pincap & mask) { + if (random() & 1) + return bit; + } + return 0; +} + +static void randomize_amp(struct xhda_amp_caps *caps, + struct xhda_amp_vals *vals, int nums) +{ + int i, c; + + for (i = 0; i < nums; i++) + for (c = 0; c < 2; c++) { + if (caps->nsteps) + vals->vals[i][c] = random() % caps->nsteps; + else + vals->vals[i][c] = 0; + if (caps->mute && (random() & 1)) + vals->vals[i][c] |= 0x80; + } +} + +void hda_test_pm_randomize(void) +{ + struct xhda_node *node; + for (node = proc.afg.next; node; node = node->next) { + unsigned int type; + type = (node->wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; + + if (type == AC_WID_PIN) + node->pinctl = random() & 0xff; + if (node->wcaps & AC_WCAP_IN_AMP) + randomize_amp(node->amp_in_caps.override ? + &node->amp_in_caps : + &proc.afg.amp_in_caps, + &node->amp_in_vals, node->num_nodes); + if (node->wcaps & AC_WCAP_OUT_AMP) + randomize_amp(node->amp_out_caps.override ? + &node->amp_out_caps : + &proc.afg.amp_out_caps, + &node->amp_out_vals, 1); + } +} + +void hda_test_pm_reinit(void) +{ + struct xhda_node *node; + for (node = proc.afg.next; node; node = node->next) { + node->pinctl = node->orig_pinctl; + node->amp_in_vals = node->orig_amp_in_vals; + node->amp_out_vals = node->orig_amp_out_vals; + } +} + /* * unsol even handling */ @@ -1067,6 +1126,8 @@ int main(int argc, char **argv) return 1; } + srandom((unsigned int)time(NULL)); + hda_log_init(logfile, log_flags); /* ignore SIGTRAP as default; gdb will override anyway... */ diff --git a/hda-parse.c b/hda-parse.c index bbe9935..c75b03b 100644 --- a/hda-parse.c +++ b/hda-parse.c @@ -139,7 +139,8 @@ static int parse_amp_caps(const char *buf, struct xhda_amp_caps *caps) return 0; } -static int parse_amp_vals(const char *buf, struct xhda_amp_vals *vals) +static int parse_amp_vals(const char *buf, struct xhda_amp_vals *vals, + struct xhda_amp_vals *orig_vals) { while (*buf && isspace(*buf)) buf++; @@ -167,6 +168,8 @@ static int parse_amp_vals(const char *buf, struct xhda_amp_vals *vals) vals->vals[0][0] = strtoul(p, &p, 0); vals->vals[0][1] = strtoul(p, &p, 0); } + if (orig_vals) + *orig_vals = *vals; return 0; } @@ -230,11 +233,14 @@ static int parse_node_items(const char *buf) } else if ((p = strmatch(head, "Amp-Out caps: "))) { return parse_amp_caps(p, &node->amp_out_caps); } else if ((p = strmatch(head, "Amp-In vals: "))) { - return parse_amp_vals(p, &node->amp_in_vals); + return parse_amp_vals(p, &node->amp_in_vals, + &node->orig_amp_in_vals); } else if ((p = strmatch(head, "Amp-Out vals: "))) { - return parse_amp_vals(p, &node->amp_out_vals); + return parse_amp_vals(p, &node->amp_out_vals, + &node->orig_amp_out_vals); } else if ((p = strmatch(head, "Pin-ctls: "))) { node->pinctl = strtoul(p, NULL, 0); + node->orig_pinctl = node->pinctl; } else if ((p = strmatch(head, "Pincap "))) { const char *end; /* a special hack to avoid the old bug */ diff --git a/include/hda-log.h b/include/hda-log.h index 59e8c75..3bcaaf6 100644 --- a/include/hda-log.h +++ b/include/hda-log.h @@ -33,6 +33,9 @@ void hda_log_issue_unsol(int nid); void hda_test_suspend(void); void hda_test_resume(void); +void hda_test_pm_randomize(void); +void hda_test_pm_reinit(void); + void hda_exec_verb(int nid, int verb, int parm); void hda_codec_reset(void); diff --git a/include/hda-types.h b/include/hda-types.h index 3a06745..3754bca 100644 --- a/include/hda-types.h +++ b/include/hda-types.h @@ -33,6 +33,7 @@ struct xhda_node { unsigned int nid; unsigned int wcaps; unsigned int pinctl; + unsigned int orig_pinctl; unsigned int pincap; unsigned int pin_default; struct xhda_pcm_info pcm; @@ -40,6 +41,8 @@ struct xhda_node { struct xhda_amp_caps amp_out_caps; struct xhda_amp_vals amp_in_vals; struct xhda_amp_vals amp_out_vals; + struct xhda_amp_vals orig_amp_in_vals; + struct xhda_amp_vals orig_amp_out_vals; unsigned int num_nodes; unsigned int curr_conn; unsigned int node[HDA_MAX_NUM_CONNS]; |