/* Searches the audio group for a node that supports beeping. */ static uint32_t find_beep_node_in_group(uint32_t base, uint32_t group_nid) { int rc; uint32_t node_count = 0; uint32_t current_nid = 0; uint32_t end_nid; uint32_t response; rc = get_subnode_info(base, group_nid, &node_count, ¤t_nid); if (rc < 0) return 0; end_nid = current_nid + node_count; while (current_nid < end_nid) { rc = exec_one_verb(base, HDA_VERB(current_nid, HDA_VERB_GET_PARAMS, GET_PARAMS_AUDIO_WIDGET_CAPS), &response); if (rc < 0) { printf("Audio: Error reading widget caps.\n"); return 0; } if(AUDIO_WIDGET_TYPE(response) == AUDIO_WIDGET_TYPE_BEEP) return current_nid; current_nid++; } return 0; /* no beep node found. */ }
static void lfe_initialize(int fd) { struct hda_verb_ioctl val = { 0 }; const int verbs_init[] = { HDA_VERB(0x17, AC_VERB_SET_POWER_STATE, 0), HDA_VERB(0x1a, AC_VERB_SET_POWER_STATE, 0), HDA_VERB(0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000), HDA_VERB(0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40), 0 }; for (int i = 0; verbs_init[i] > 0; ++i) { val.verb = verbs_init[i]; if (ioctl(fd, HDA_IOCTL_VERB_WRITE, &val) < 0) { perror("ioctl"); return; } } }
/* Sets the beep generator with the given divisor. pass 0 to disable beep. */ static void set_beep_divisor(uint8_t divider) { uint32_t base; uint32_t beep_nid; base = get_hda_base(); beep_nid = get_hda_beep_nid(base); if (beep_nid <= 0) { printf("Audio: Failed to find a beep-capable node.\n"); return; } write_one_verb(base, HDA_VERB(beep_nid, HDA_VERB_SET_BEEP, divider)); }
static void set_lfe_volume(int fd, long volume) { char lfe_volume = Y50_LFE_VOLUME_MAX * volume / 100; struct hda_verb_ioctl val = { 0 }; const int verbs[] = { HDA_VERB(0x03, AC_VERB_SET_AMP_GAIN_MUTE, (lfe_volume > 0) ? (0xa0 << 8) | lfe_volume : 0), HDA_VERB(0x03, AC_VERB_SET_AMP_GAIN_MUTE, (lfe_volume > 0) ? (0x90 << 8) | lfe_volume : 0), HDA_VERB(0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, (lfe_volume > 0) ? 0x25 : 0), 0 }; for (int i = 0; verbs[i] > 0; ++i) { val.verb = verbs[i]; if (ioctl(fd, HDA_IOCTL_VERB_WRITE, &val) < 0) { perror("ioctl"); return; } } }
/* Checks if the given audio group contains a beep generator. */ static int audio_group_has_beep_node(uint32_t base, uint32_t nid) { int rc; uint32_t response; rc = exec_one_verb(base, HDA_VERB(nid, HDA_VERB_GET_PARAMS, GET_PARAMS_AUDIO_GROUP_CAPS), &response); if (rc < 0) { printf("Audio: Error reading audio group caps %d.\n", nid); return 0; } return !!(response & AUDIO_GROUP_CAPS_BEEP_GEN); }
/* Gets the count of sub-nodes and node id they start at for the given * super-node. */ static uint32_t get_subnode_info(uint32_t base, uint32_t nid, uint32_t *num_sub_nodes, uint32_t *start_sub_node_nid) { int rc; uint32_t response; rc = exec_one_verb(base, HDA_VERB(nid, HDA_VERB_GET_PARAMS, GET_PARAMS_NODE_COUNT), &response); if (rc < 0) { printf("Audio: Error reading sub-node info %d.\n", nid); return rc; } *num_sub_nodes = AUDIO_NODE_NUM_SUB_NODES(response); *start_sub_node_nid = AUDIO_NODE_FIRST_SUB_NODE(response); return 0; }
int main(int argc, char **argv) { long nid, verb, param; int c; char **p; bool quiet = false; while ((c = getopt(argc, argv, "qlL")) >= 0) { switch (c) { case 'l': list_verbs(0); return 0; case 'L': list_verbs(1); return 0; case 'q': quiet = true; break; default: usage(); return 1; } } if (argc - optind < 3) { usage(); return 1; } p = argv + optind; nid = strtol(*p, NULL, 0); if (nid < 0 || nid > 0xff) { fprintf(stderr, "invalid nid %s\n", *p); return 1; } p++; if (!isdigit(**p)) { strtoupper(*p); verb = lookup_str(hda_verbs, *p); if (verb < 0) return 1; } else { verb = strtol(*p, NULL, 0); if (verb < 0 || verb > 0xfff) { fprintf(stderr, "invalid verb %s\n", *p); return 1; } } p++; if (!isdigit(**p)) { strtoupper(*p); param = lookup_str(hda_params, *p); if (param < 0) return 1; } else { param = strtol(*p, NULL, 0); if (param < 0 || param > 0xffff) { fprintf(stderr, "invalid param %s\n", *p); return 1; } } if (!quiet) printf("nid = 0x%lx, verb = 0x%lx, param = 0x%lx\n", nid, verb, param); UInt32 command = (UInt32)HDA_VERB(nid, verb, param); // Execute command UInt32 result = execute_command(command, 0x10ec0892, 0x0, 0x01); // Print result if (quiet) printf("0x%08x\n", result); else printf("command 0x%08x --> result = 0x%08x\n", command, result); return 0; }