aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-01-16 15:28:19 +0100
committerTakashi Iwai <tiwai@suse.de>2013-01-16 15:29:17 +0100
commit77b2b59ed61513fb339d5bdeb8100d2cc7d383f4 (patch)
tree370d28b7ff97b9801be02649549ae16c67142420
parent45e66120b51a92ddf99ea43432108e94e9828482 (diff)
downloadhda-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--README6
-rw-r--r--hda-ctlsh.c42
-rw-r--r--hda-emu.c61
-rw-r--r--hda-parse.c12
-rw-r--r--include/hda-log.h3
-rw-r--r--include/hda-types.h3
6 files changed, 122 insertions, 5 deletions
diff --git a/README b/README
index 0a098d7..e4aea41 100644
--- a/README
+++ b/README
@@ -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...",
diff --git a/hda-emu.c b/hda-emu.c
index bef7e82..c98a3ea 100644
--- a/hda-emu.c
+++ b/hda-emu.c
@@ -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];