Date: Sat, 22 Jul 2006 14:24:01 +0200 From: Maxime Guillaud <bsd-ports@mguillaud.net> To: freebsd-multimedia@freebsd.org, freebsd-mobile@freebsd.org Subject: HDA sound driver hack for Acer Aspire 1641 Message-ID: <44C218E1.9020808@mguillaud.net>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------010607060808090609040802 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit After some tweaking of Andrea Bittau's code, I managed to get the sound (output only) working on my Acer Aspire 1641 WLMi. You can get the driver from http://www.mguillaud.net/acer1641/FreeBSD/hdac.tgz I also attach a diff against Andrea's original code, FYI. Maxime --------------010607060808090609040802 Content-Type: text/plain; name="diff-vs-andrea20060606" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="diff-vs-andrea20060606" diff -ur hdac-20060608/hda_reg.h /usr/src/sys/dev/hdac/hda_reg.h --- hdac-20060608/hda_reg.h Sun Jun 4 01:10:31 2006 +++ /usr/src/sys/dev/hdac/hda_reg.h Wed Jul 5 18:49:17 2006 @@ -1192,4 +1192,35 @@ (((param) & HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_MASK) >> \ HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_SHIFT) + +#define HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK 0x00000000f +#define HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK 0x0000000f0 +#define HDA_CONFIG_DEFAULTCONF_MISC_MASK 0x000000f00 +#define HDA_CONFIG_DEFAULTCONF_COLOR_MASK 0x00000f000 +#define HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK 0x000f00000 +#define HDA_CONFIG_DEFAULTCONF_DEVICE_MASK 0x000f00000 +#define HDA_CONFIG_DEFAULTCONF_LOCATION_MASK 0x03f000000 +#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK 0x0c0000000 + +#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK (0<<30) +#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE (1<<30) +#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED (2<<30) +#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_BOTH (3<<30) + +#define HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT (0<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER (1<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT (2<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_CD (3<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT (4<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT (5<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_LINE (6<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_HANDSET (7<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN (8<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_AUX (9<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN (10<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_TELEPHONY (11<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN (12<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN (13<<20) +#define HDA_CONFIG_DEFAULTCONF_DEVICE_OTHER (15<<20) + #endif diff -ur hdac-20060608/hdac.c /usr/src/sys/dev/hdac/hdac.c --- hdac-20060608/hdac.c Mon Jun 5 21:15:12 2006 +++ /usr/src/sys/dev/hdac/hdac.c Sat Jul 15 12:02:49 2006 @@ -54,6 +54,7 @@ #define INTEL_VENDORID 0x8086 +#define INTEL_82801F 0x2668 #define INTEL_82801G 0x27d8 @@ -62,6 +63,8 @@ uint16_t vendor; char *description; } hdac_devices[] = { + { INTEL_82801F, INTEL_VENDORID, + "Intel 82801F High Definition Audio Controller" }, { INTEL_82801G, INTEL_VENDORID, "Intel 82801G High Definition Audio Controller" } }; @@ -247,7 +250,8 @@ * Reset the controller. The reset must remain asserted for * a minimum of 100us. */ - HDAC_WRITE_4(&sc->mem, HDAC_GCTL, 0x0); + gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); + HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); count = 10000; while (count) { gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); @@ -260,11 +264,11 @@ return (ENXIO); } DELAY(100); - HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_GCTL_CRST); + gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); + HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST); count = 10000; while (count) { - gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL); - if ((gctl & HDAC_GCTL_CRST) == HDAC_GCTL_CRST) + if (HDAC_READ_4(&sc->mem, HDAC_GCTL) & HDAC_GCTL_CRST) break; count--; } @@ -785,7 +789,8 @@ devinfo->revision_id = HDA_PARAM_REVISION_ID_REVISION_ID(revisionid); devinfo->stepping_id = HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid); devinfo->node_type = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(fctgrptype); - + device_printf(sc->dev, "Vendor info: %x %x %x %x %x %x\n", vendorid, devinfo->vendor_id, devinfo->device_id, + devinfo->revision_id, devinfo->stepping_id, devinfo->node_type); hdac_add_child(sc, devinfo); } @@ -811,6 +816,40 @@ } static void +sorbo_print_conn(struct hdac_softc *sc, int cad, int nid) +{ + uint32_t rc,i,cll; + uint32_t l=0; + uint16_t payload; + char connection_list[1024]; + char connection_string[256]; + + cll = hdac_command_sendone_internal(sc, + HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); + + snprintf(connection_list, 1024, "node %d: %d connections, list: ", nid, cll); + for (i=0;i<cll;i++) + { + if ((i % 4)==0) + l = hdac_command_sendone_internal(sc, HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad); + + payload = (1 << 13) | i; /* left, input i*/ + rc = hdac_command_sendone_internal(sc, HDA_CMD_GET_AMP_GAIN_MUTE(cad, nid, payload), cad); + + snprintf(connection_string, 256, "input from node %d (input amp %d), ",(l>>8*(i%4)) & 0xff,rc); + strlcat(connection_list, connection_string, 1024); + } + + payload = (1 << 15) | (1 << 13); /* left, output */ + rc = hdac_command_sendone_internal(sc, HDA_CMD_GET_AMP_GAIN_MUTE(cad, nid, payload), cad); + + snprintf(connection_string,256, "output amp %d\n",rc); + strlcat(connection_list, connection_string, 1024); + device_printf(sc->dev, connection_list); + +} + +static void sorbo_conf_output(struct hdac_softc *sc, int cad, int nid) { uint32_t rc, sf, st; @@ -830,7 +869,7 @@ st = hdac_command_sendone_internal(sc, HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS), cad); - device_printf(sc->dev, "Cap %x sf %x st %x\n", rc, sf, st); + device_printf(sc->dev, "Output, Cap %x sf %x st %x\n", rc, sf, st); rc = hdac_command_sendone_internal(sc, HDA_CMD_GET_CONV_STREAM_CHAN(cad, nid), 0); @@ -854,12 +893,25 @@ } static void -sorbo_set_amp(struct hdac_softc *sc, int cda, int ni, int amp) +sorbo_set_amp(struct hdac_softc *sc, int cda, int ni, int left, int right) { - uint16_t pay = (1 << 15) | (3 << 12) | amp; + uint16_t pay = 0; - hdac_command_sendone_internal(sc, - HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, pay), cda); + if (left != right) { + pay = (1 << 15) | (1 << 13) | left; + hdac_command_sendone_internal(sc, + HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, pay), cda); + + pay = (1 << 15) | (1 << 12) | right; + + hdac_command_sendone_internal(sc, + HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, pay), cda); + } else { + pay = (1 << 15) | (3 << 12) | left; + + hdac_command_sendone_internal(sc, + HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, pay), cda); + } } static void @@ -871,6 +923,80 @@ uint32_t ct = 0; uint32_t capa = 0; uint32_t sense = 0; + char connection_type_string[32], device_string[32]; + int defaultconf; + + defaultconf=HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid); + switch (defaultconf & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) + { + case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK: + strncpy(connection_type_string,"jack", 32); + break; + case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE: + strncpy(connection_type_string,"none", 32); + break; + case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED: + strncpy(connection_type_string,"fixed", 32); + break; + case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_BOTH: + strncpy(connection_type_string,"jack and fixed", 32); + break; + default: + strncpy(connection_type_string,"unknown", 32); + break; + } + + switch (defaultconf & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) + { + case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT: + strncpy(device_string,"line out", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER: + strncpy(device_string,"speaker", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT: + strncpy(device_string,"headphones out", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_CD: + strncpy(device_string,"CD", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT: + strncpy(device_string,"SPDIF out", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT: + strncpy(device_string,"digital (other) out", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_LINE: + strncpy(device_string,"modem, line side", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_HANDSET: + strncpy(device_string,"modem, handset side", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN: + strncpy(device_string,"line in", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX: + strncpy(device_string,"AUX", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN: + strncpy(device_string,"Mic in", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_TELEPHONY: + strncpy(device_string,"telephony", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN: + strncpy(device_string,"SPDIF in", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN: + strncpy(device_string,"digital (other) in", 32); + break; + case HDA_CONFIG_DEFAULTCONF_DEVICE_OTHER: + strncpy(device_string,"other", 32); + break; + default: + strncpy(device_string,"unknown", 32); + break; + } rc = hdac_command_sendone_internal(sc, HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad); @@ -899,8 +1025,7 @@ sense = hdac_command_sendone_internal(sc, HDA_CMD_GET_PIN_SENSE(cad, nid), cad); - device_printf(sc->dev, "nid %d entries %x list %x cur %d ctr %x cap %x s %x\n", - nid, rc, l, p, ct, capa, sense); + device_printf(sc->dev, "node %d: entries %x list %x cur %d ctr %x cap %x s %x, default connectivity: %s, device type: %s\n", nid, rc, l, p, ct, capa, sense,connection_type_string,device_string); sorbo_get_amp(sc, cad, nid); } @@ -924,28 +1049,80 @@ static void sorbo_print_widget(struct hdac_softc *sc, int codecid, int nodeid) { - uint32_t rc; + uint32_t rc,p; int type; + char type_string[32]; rc = hdac_command_sendone_internal(sc, - HDA_CMD_GET_PARAMETER(0, nodeid, HDA_PARAM_AUDIO_WIDGET_CAP), 0); + HDA_CMD_GET_PARAMETER(0, nodeid, HDA_PARAM_AUDIO_WIDGET_CAP), codecid); type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(rc); - device_printf(sc->dev, "node %d type %x cap %x\n", nodeid, type, rc); + switch (type) + { + case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT: + strncpy(type_string,"audio output", 32); + break; + case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT: + strncpy(type_string,"audio input", 32); + break; + case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER: + strncpy(type_string,"audio mixer", 32); + break; + case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR: + strncpy(type_string,"audio selector", 32); + break; + case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX: + strncpy(type_string,"pin", 32); + break; + case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET: + strncpy(type_string,"power widget", 32); + break; + case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET: + strncpy(type_string,"volume widget", 32); + break; + case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET: + strncpy(type_string,"beep widget", 32); + break; + case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET: + strncpy(type_string,"vendor widget", 32); + break; + default: + strncpy(type_string,"unknown type", 32); + break; + } + + + device_printf(sc->dev, "node %d: type %x (%s), cap %x,\n", nodeid, type, type_string,rc); + + if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(rc)) { + hdac_command_sendone_internal(sc, + HDA_CMD_SET_POWER_STATE(codecid, nodeid, HDA_CMD_POWER_STATE_D0), codecid); + } - if (0) - sorbo_set_amp(sc, codecid, nodeid, 40); + if (0) + sorbo_set_amp(sc, codecid, nodeid, 40,40); if (0 && HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(rc)) { sorbo_own_proc(sc, codecid, nodeid); } - if (0 && type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) { + if (type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) { sorbo_conf_output(sc, codecid, nodeid); } - else if (0 && type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) + else if (type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) sorbo_conf_pin(sc, codecid, nodeid); + else if ((type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) || (type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER)) + sorbo_print_conn(sc, codecid, nodeid); + if (type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) + { + p = hdac_command_sendone_internal(sc, + HDA_CMD_GET_CONN_SELECT_CONTROL(codecid, nodeid), codecid); + device_printf(sc->dev, "current connection: %x\n",p); + } + + + } static void @@ -955,19 +1132,21 @@ int startnode; int endnode; int i; -// uint32_t pw; + uint32_t pw; subnode = hdac_command_sendone_internal(sc, HDA_CMD_GET_PARAMETER(0 , 1, HDA_PARAM_SUB_NODE_COUNT), 0); startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode); endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode); -#if 0 + hdac_command_sendone_internal(sc, + HDA_CMD_SET_POWER_STATE(0, 1, HDA_CMD_POWER_STATE_D0), 0); + pw = hdac_command_sendone_internal(sc, HDA_CMD_GET_POWER_STATE(0, 1), 0); device_printf(sc->dev, "PW %x\n", pw); -#endif + device_printf(sc->dev, "start: %d endnode: %d\n", startnode, endnode); for (i = startnode; i < endnode; i++) { sorbo_print_widget(sc, 0, i); @@ -1231,6 +1410,57 @@ } static void +sorbo_set_input_amp(struct hdac_softc *sc, int cda, int ni, int index, int mute, int left, int right) +{ + uint16_t payload = 0; + + if (left != right) { + payload = (1 << 14) | (1 << 13) | (index << 8) | (mute<<7) | left; + hdac_command_sendone_internal(sc, + HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, payload), cda); + + payload = (1 << 14) | (1 << 12) | (index << 8) | (mute<<7) | right; + hdac_command_sendone_internal(sc, + HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, payload), cda); + } else { + payload = (1 << 14) | (3 << 12) | (index << 8) | (mute<<7) | left; + hdac_command_sendone_internal(sc, + HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, payload), cda); + } + +} + + +static void +sorbo_set_output_amp(struct hdac_softc *sc, int cda, int ni, int mute, int left, int right) +{ + uint16_t payload = 0; + + if (left != right) { + payload = (1 << 15) | (1 << 13) | (mute<<7) | left; + hdac_command_sendone_internal(sc, + HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, payload), cda); + + payload = (1 << 15) | (1 << 12) | (mute<<7) | right; + hdac_command_sendone_internal(sc, + HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, payload), cda); + } else { + payload = (1 << 15) | (3 << 12) | (mute<<7) | left; + hdac_command_sendone_internal(sc, + HDA_CMD_SET_AMP_GAIN_MUTE(cda, ni, payload), cda); + } + +} + + +static void +sorbo_set_conn_select_control(struct hdac_softc *sc, int codecid, int nodeid, uint8_t index) +{ + hdac_command_sendone_internal(sc, HDA_CMD_SET_CONNECTION_SELECT_CONTROL(codecid, nodeid, index), codecid); +} + + +static void hdac_attach2(void *arg) { struct hdac_softc *sc; @@ -1248,15 +1478,71 @@ hdac_scan_codecs(sc); - if (0) +/* if (0) */ sorbo_enum(sc); + sorbo_stop_stream(sc); sorbo_reset_stream(sc); sorbo_stream_setid(sc); - sorbo_conf_output(sc, 0, 3); - sorbo_set_amp(sc, 0, 5, 40); + sorbo_conf_output(sc, 0, 2); + + sorbo_set_amp(sc, 0, 2, 40,40); + sorbo_set_amp(sc, 0, 3, 40,40); + sorbo_set_amp(sc, 0, 4, 40,40); + sorbo_set_amp(sc, 0, 5, 40,40); + sorbo_set_amp(sc, 0, 6, 40,40); + sorbo_set_amp(sc, 0, 7, 40,40); + sorbo_set_amp(sc, 0, 8, 40,40); + sorbo_set_amp(sc, 0, 9, 40,40); + sorbo_set_amp(sc, 0, 10, 40,40); + sorbo_set_amp(sc, 0, 11, 40,40); + sorbo_set_amp(sc, 0, 12, 40,40); + sorbo_set_amp(sc, 0, 13, 40,40); + sorbo_set_amp(sc, 0, 14, 40,40); + sorbo_set_amp(sc, 0, 15, 40,40); + sorbo_set_amp(sc, 0, 16, 40,40); + sorbo_set_amp(sc, 0, 17, 40,40); + sorbo_set_amp(sc, 0, 18, 40,40); + sorbo_set_amp(sc, 0, 19, 40,40); + sorbo_set_amp(sc, 0, 20, 40,40); + sorbo_set_amp(sc, 0, 21, 40,40); + sorbo_set_amp(sc, 0, 22, 40,40); + sorbo_set_amp(sc, 0, 23, 40,40); + sorbo_set_amp(sc, 0, 24, 40,40); + sorbo_set_amp(sc, 0, 25, 40,40); + sorbo_set_amp(sc, 0, 26, 40,40); + sorbo_set_amp(sc, 0, 27, 40,40); + + + sorbo_set_input_amp(sc, 0, 8, 0, 0, 41,41); + sorbo_set_output_amp(sc, 0, 8, 0, 42,43); + sorbo_set_input_amp(sc, 0, 9, 0, 0, 43,44); + sorbo_set_output_amp(sc, 0, 9, 0, 45,45); + sorbo_set_conn_select_control(sc, 0, 11, 0); /* select input from mixer 8 */ + sorbo_set_input_amp(sc, 0, 10, 0, 0, 45,45); + sorbo_set_output_amp(sc, 0, 10, 0, 46,46); + sorbo_set_input_amp(sc, 0, 11, 0, 0, 47,47); + sorbo_set_output_amp(sc, 0, 11, 0, 48,48); + +/* sorbo_set_amp(sc, 0, 8, 6); */ + + + sorbo_print_widget(sc, 0, 2); + sorbo_print_widget(sc, 0, 8); + sorbo_print_widget(sc, 0, 9); + sorbo_print_widget(sc, 0, 10); + sorbo_print_widget(sc, 0, 11); + sorbo_print_widget(sc, 0, 13); + sorbo_print_widget(sc, 0, 16); + sorbo_print_widget(sc, 0, 17); + sorbo_print_widget(sc, 0, 18); + + sorbo_print_widget(sc, 0, 20); + + + sorbo_alloc_bdl(sc, 256); sorbo_enable_stream_interrupts(sc); sc->lame = 1; @@ -1583,7 +1869,7 @@ hdacmix_init(struct snd_mixer *m) { mix_setrecdevs(m, 0); - mix_setdevs(m, SOUND_MASK_VOLUME); + mix_setdevs(m, SOUND_MASK_VOLUME | SOUND_MASK_PCM); return 0; } @@ -1591,21 +1877,32 @@ static int hdacmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) { - int vol = 0; - int max = 63; + int left_vol = 0, right_vol = 0; + int max = ((1<<6) - 1); struct hdac_softc *sc = mix_getdevinfo(m); - vol = (left*63)/100; - - if (left == 100 || vol > max) - vol = max; - -// printf("Vol = %d\n", vol); - if (sc->lame) - sorbo_set_amp(sc, 0, 5, vol); + + left_vol = (left * max) / 100; + if ((left == 100) || (left_vol > max)) + left_vol = max; + + right_vol = (right * max) / 100; + if ((right == 100) || (right_vol > max)) + right_vol = max; + + if (sc->lame) { + switch(dev) { + case SOUND_MIXER_VOLUME: + sorbo_set_output_amp(sc, 0, 8, 0, left_vol, right_vol); + break; + case SOUND_MIXER_PCM: + sorbo_set_input_amp(sc, 0, 8, 0, 0, left_vol, right_vol); + break; + } + } - vol = left | (left << 8); + left_vol = left | (right << 8); - return vol; + return left_vol; } static int --------------010607060808090609040802--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?44C218E1.9020808>