Loading Documentation/sound/alsa/soc/machine.txt +2 −4 Original line number Diff line number Diff line Loading @@ -50,8 +50,7 @@ Machine DAI Configuration The machine DAI configuration glues all the codec and CPU DAIs together. It can also be used to set up the DAI system clock and for any machine related DAI initialisation e.g. the machine audio map can be connected to the codec audio map, unconnected codec pins can be set as such. Please see corgi.c, spitz.c for examples. map, unconnected codec pins can be set as such. struct snd_soc_dai_link is used to set up each DAI in your machine. e.g. Loading Loading @@ -83,8 +82,7 @@ Machine Power Map The machine driver can optionally extend the codec power map and to become an audio power map of the audio subsystem. This allows for automatic power up/down of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for details. sockets in the machine init function. Machine Controls Loading drivers/firmware/sigma.c +58 −23 Original line number Diff line number Diff line Loading @@ -14,13 +14,34 @@ #include <linux/module.h> #include <linux/sigma.h> /* Return: 0==OK, <0==error, =1 ==no more actions */ static size_t sigma_action_size(struct sigma_action *sa) { size_t payload = 0; switch (sa->instr) { case SIGMA_ACTION_WRITEXBYTES: case SIGMA_ACTION_WRITESINGLE: case SIGMA_ACTION_WRITESAFELOAD: payload = sigma_action_len(sa); break; default: break; } payload = ALIGN(payload, 2); return payload + sizeof(struct sigma_action); } /* * Returns a negative error value in case of an error, 0 if processing of * the firmware should be stopped after this action, 1 otherwise. */ static int process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw) process_sigma_action(struct i2c_client *client, struct sigma_action *sa) { struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos); size_t len = sigma_action_len(sa); int ret = 0; int ret; pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__, sa->instr, sa->addr, len); Loading @@ -29,44 +50,50 @@ process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw) case SIGMA_ACTION_WRITEXBYTES: case SIGMA_ACTION_WRITESINGLE: case SIGMA_ACTION_WRITESAFELOAD: if (ssfw->fw->size < ssfw->pos + len) return -EINVAL; ret = i2c_master_send(client, (void *)&sa->addr, len); if (ret < 0) return -EINVAL; break; case SIGMA_ACTION_DELAY: ret = 0; udelay(len); len = 0; break; case SIGMA_ACTION_END: return 1; return 0; default: return -EINVAL; } /* when arrive here ret=0 or sent data */ ssfw->pos += sigma_action_size(sa, len); return ssfw->pos == ssfw->fw->size; return 1; } static int process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw) { pr_debug("%s: processing %p\n", __func__, ssfw); struct sigma_action *sa; size_t size; int ret; while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) { sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos); size = sigma_action_size(sa); ssfw->pos += size; if (ssfw->pos > ssfw->fw->size || size == 0) break; ret = process_sigma_action(client, sa); while (1) { int ret = process_sigma_action(client, ssfw); pr_debug("%s: action returned %i\n", __func__, ret); if (ret == 1) return 0; else if (ret) if (ret <= 0) return ret; } if (ssfw->pos != ssfw->fw->size) return -EINVAL; return 0; } int process_sigma_firmware(struct i2c_client *client, const char *name) Loading @@ -89,16 +116,24 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) /* then verify the header */ ret = -EINVAL; if (fw->size < sizeof(*ssfw_head)) /* * Reject too small or unreasonable large files. The upper limit has been * chosen a bit arbitrarily, but it should be enough for all practical * purposes and having the limit makes it easier to avoid integer * overflows later in the loading process. */ if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) goto done; ssfw_head = (void *)fw->data; if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) goto done; crc = crc32(0, fw->data, fw->size); crc = crc32(0, fw->data + sizeof(*ssfw_head), fw->size - sizeof(*ssfw_head)); pr_debug("%s: crc=%x\n", __func__, crc); if (crc != ssfw_head->crc) if (crc != le32_to_cpu(ssfw_head->crc)) goto done; ssfw.pos = sizeof(*ssfw_head); Loading include/linux/sigma.h +4 −9 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ struct sigma_firmware { struct sigma_firmware_header { unsigned char magic[7]; u8 version; u32 crc; __le32 crc; }; enum { Loading @@ -40,19 +40,14 @@ enum { struct sigma_action { u8 instr; u8 len_hi; u16 len; u16 addr; __le16 len; __be16 addr; unsigned char payload[]; }; static inline u32 sigma_action_len(struct sigma_action *sa) { return (sa->len_hi << 16) | sa->len; } static inline size_t sigma_action_size(struct sigma_action *sa, u32 payload_len) { return sizeof(*sa) + payload_len + (payload_len % 2); return (sa->len_hi << 16) | le16_to_cpu(sa->len); } extern int process_sigma_firmware(struct i2c_client *client, const char *name); Loading sound/pci/hda/patch_realtek.c +49 −16 Original line number Diff line number Diff line Loading @@ -300,6 +300,8 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, imux = &spec->input_mux[mux_idx]; if (!imux->num_items && mux_idx > 0) imux = &spec->input_mux[0]; if (!imux->num_items) return 0; if (idx >= imux->num_items) idx = imux->num_items - 1; Loading Loading @@ -2663,6 +2665,8 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, case AUTO_PIN_SPEAKER_OUT: if (cfg->line_outs == 1) return "Speaker"; if (cfg->line_outs == 2) return ch ? "Bass Speaker" : "Speaker"; break; case AUTO_PIN_HP_OUT: /* for multi-io case, only the primary out */ Loading Loading @@ -2974,7 +2978,7 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) if (!nid) continue; if (found_in_nid_list(nid, spec->multiout.dac_nids, spec->multiout.num_dacs)) ARRAY_SIZE(spec->private_dac_nids))) continue; if (found_in_nid_list(nid, spec->multiout.hp_out_nid, ARRAY_SIZE(spec->multiout.hp_out_nid))) Loading Loading @@ -3012,6 +3016,7 @@ static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) return 0; } /* return 0 if no possible DAC is found, 1 if one or more found */ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, const hda_nid_t *pins, hda_nid_t *dacs) { Loading @@ -3029,7 +3034,7 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, if (!dacs[i]) dacs[i] = alc_auto_look_for_dac(codec, pins[i]); } return 0; return 1; } static int alc_auto_fill_multi_ios(struct hda_codec *codec, Loading @@ -3039,7 +3044,7 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec, static int alc_auto_fill_dac_nids(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; const struct auto_pin_cfg *cfg = &spec->autocfg; struct auto_pin_cfg *cfg = &spec->autocfg; unsigned int location, defcfg; int num_pins; bool redone = false; Loading @@ -3052,6 +3057,7 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) spec->multiout.extra_out_nid[0] = 0; memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); spec->multiout.dac_nids = spec->private_dac_nids; spec->multi_ios = 0; /* fill hard-wired DACs first */ if (!redone) { Loading Loading @@ -3085,10 +3091,12 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) for (i = 0; i < cfg->line_outs; i++) { if (spec->private_dac_nids[i]) spec->multiout.num_dacs++; else else { memmove(spec->private_dac_nids + i, spec->private_dac_nids + i + 1, sizeof(hda_nid_t) * (cfg->line_outs - i - 1)); spec->private_dac_nids[cfg->line_outs - 1] = 0; } } if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { Loading @@ -3107,9 +3115,28 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) if (cfg->line_out_type != AUTO_PIN_HP_OUT) alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins, spec->multiout.hp_out_nid); if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins, if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins, spec->multiout.extra_out_nid); /* if no speaker volume is assigned, try again as the primary * output */ if (!err && cfg->speaker_outs > 0 && cfg->line_out_type == AUTO_PIN_HP_OUT) { cfg->hp_outs = cfg->line_outs; memcpy(cfg->hp_pins, cfg->line_out_pins, sizeof(cfg->hp_pins)); cfg->line_outs = cfg->speaker_outs; memcpy(cfg->line_out_pins, cfg->speaker_pins, sizeof(cfg->speaker_pins)); cfg->speaker_outs = 0; memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; redone = false; goto again; } } if (!spec->multi_ios && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && Loading Loading @@ -3287,7 +3314,8 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, } static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac, const char *pfx) hda_nid_t dac, const char *pfx, int cidx) { struct alc_spec *spec = codec->spec; hda_nid_t sw, vol; Loading @@ -3303,15 +3331,15 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, if (is_ctl_used(spec->sw_ctls, val)) return 0; /* already created */ mark_ctl_usage(spec->sw_ctls, val); return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val); return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, cidx, val); } sw = alc_look_for_out_mute_nid(codec, pin, dac); vol = alc_look_for_out_vol_nid(codec, pin, dac); err = alc_auto_add_stereo_vol(codec, pfx, 0, vol); err = alc_auto_add_stereo_vol(codec, pfx, cidx, vol); if (err < 0) return err; err = alc_auto_add_stereo_sw(codec, pfx, 0, sw); err = alc_auto_add_stereo_sw(codec, pfx, cidx, sw); if (err < 0) return err; return 0; Loading Loading @@ -3352,16 +3380,21 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, hda_nid_t dac = *dacs; if (!dac) dac = spec->multiout.dac_nids[0]; return alc_auto_create_extra_out(codec, *pins, dac, pfx); return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0); } if (dacs[num_pins - 1]) { /* OK, we have a multi-output system with individual volumes */ for (i = 0; i < num_pins; i++) { if (num_pins >= 3) { snprintf(name, sizeof(name), "%s %s", pfx, channel_name[i]); err = alc_auto_create_extra_out(codec, pins[i], dacs[i], name); name, 0); } else { err = alc_auto_create_extra_out(codec, pins[i], dacs[i], pfx, i); } if (err < 0) return err; } Loading sound/pci/hda/patch_sigmatel.c +25 −22 Original line number Diff line number Diff line Loading @@ -215,6 +215,7 @@ struct sigmatel_spec { unsigned int gpio_mute; unsigned int gpio_led; unsigned int gpio_led_polarity; unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */ unsigned int vref_led; /* stream */ Loading Loading @@ -4318,14 +4319,12 @@ static void stac_store_hints(struct hda_codec *codec) spec->eapd_switch = val; get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { if (spec->gpio_led <= 8) { spec->gpio_mask |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led; if (spec->gpio_led_polarity) spec->gpio_data |= spec->gpio_led; } } } static int stac92xx_init(struct hda_codec *codec) { Loading Loading @@ -4443,7 +4442,7 @@ static int stac92xx_init(struct hda_codec *codec) /* power on when no jack detection is available */ /* or when the VREF is used for controlling LED */ if (!spec->hp_detect || (spec->gpio_led > 8 && spec->gpio_led == nid)) { spec->vref_mute_led_nid == nid) { stac_toggle_power_map(codec, nid, 1); continue; } Loading Loading @@ -4915,8 +4914,14 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) if (sscanf(dev->name, "HP_Mute_LED_%d_%x", &spec->gpio_led_polarity, &spec->gpio_led) == 2) { if (spec->gpio_led < 4) unsigned int max_gpio; max_gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); max_gpio &= AC_GPIO_IO_COUNT; if (spec->gpio_led < max_gpio) spec->gpio_led = 1 << spec->gpio_led; else spec->vref_mute_led_nid = spec->gpio_led; return 1; } if (sscanf(dev->name, "HP_Mute_LED_%d", Loading Loading @@ -5045,15 +5050,12 @@ static int stac92xx_pre_resume(struct hda_codec *codec) struct sigmatel_spec *spec = codec->spec; /* sync mute LED */ if (spec->gpio_led) { if (spec->gpio_led <= 8) { if (spec->vref_mute_led_nid) stac_vrefout_set(codec, spec->vref_mute_led_nid, spec->vref_led); else if (spec->gpio_led) stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); } else { stac_vrefout_set(codec, spec->gpio_led, spec->vref_led); } } return 0; } Loading @@ -5064,7 +5066,7 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, struct sigmatel_spec *spec = codec->spec; if (power_state == AC_PWRST_D3) { if (spec->gpio_led > 8) { if (spec->vref_mute_led_nid) { /* with vref-out pin used for mute led control * codec AFG is prevented from D3 state */ Loading Loading @@ -5117,7 +5119,7 @@ static int stac92xx_update_led_status(struct hda_codec *codec) } } /*polarity defines *not* muted state level*/ if (spec->gpio_led <= 8) { if (!spec->vref_mute_led_nid) { if (muted) spec->gpio_data &= ~spec->gpio_led; /* orange */ else Loading @@ -5135,7 +5137,8 @@ static int stac92xx_update_led_status(struct hda_codec *codec) muted_lvl = spec->gpio_led_polarity ? AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; spec->vref_led = muted ? muted_lvl : notmtd_lvl; stac_vrefout_set(codec, spec->gpio_led, spec->vref_led); stac_vrefout_set(codec, spec->vref_mute_led_nid, spec->vref_led); } return 0; } Loading Loading @@ -5649,7 +5652,7 @@ again: #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { if (spec->gpio_led <= 8) { if (!spec->vref_mute_led_nid) { spec->gpio_mask |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led; spec->gpio_data |= spec->gpio_led; Loading Loading @@ -5962,7 +5965,7 @@ again: #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { if (spec->gpio_led <= 8) { if (!spec->vref_mute_led_nid) { spec->gpio_mask |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led; spec->gpio_data |= spec->gpio_led; Loading Loading
Documentation/sound/alsa/soc/machine.txt +2 −4 Original line number Diff line number Diff line Loading @@ -50,8 +50,7 @@ Machine DAI Configuration The machine DAI configuration glues all the codec and CPU DAIs together. It can also be used to set up the DAI system clock and for any machine related DAI initialisation e.g. the machine audio map can be connected to the codec audio map, unconnected codec pins can be set as such. Please see corgi.c, spitz.c for examples. map, unconnected codec pins can be set as such. struct snd_soc_dai_link is used to set up each DAI in your machine. e.g. Loading Loading @@ -83,8 +82,7 @@ Machine Power Map The machine driver can optionally extend the codec power map and to become an audio power map of the audio subsystem. This allows for automatic power up/down of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for details. sockets in the machine init function. Machine Controls Loading
drivers/firmware/sigma.c +58 −23 Original line number Diff line number Diff line Loading @@ -14,13 +14,34 @@ #include <linux/module.h> #include <linux/sigma.h> /* Return: 0==OK, <0==error, =1 ==no more actions */ static size_t sigma_action_size(struct sigma_action *sa) { size_t payload = 0; switch (sa->instr) { case SIGMA_ACTION_WRITEXBYTES: case SIGMA_ACTION_WRITESINGLE: case SIGMA_ACTION_WRITESAFELOAD: payload = sigma_action_len(sa); break; default: break; } payload = ALIGN(payload, 2); return payload + sizeof(struct sigma_action); } /* * Returns a negative error value in case of an error, 0 if processing of * the firmware should be stopped after this action, 1 otherwise. */ static int process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw) process_sigma_action(struct i2c_client *client, struct sigma_action *sa) { struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos); size_t len = sigma_action_len(sa); int ret = 0; int ret; pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__, sa->instr, sa->addr, len); Loading @@ -29,44 +50,50 @@ process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw) case SIGMA_ACTION_WRITEXBYTES: case SIGMA_ACTION_WRITESINGLE: case SIGMA_ACTION_WRITESAFELOAD: if (ssfw->fw->size < ssfw->pos + len) return -EINVAL; ret = i2c_master_send(client, (void *)&sa->addr, len); if (ret < 0) return -EINVAL; break; case SIGMA_ACTION_DELAY: ret = 0; udelay(len); len = 0; break; case SIGMA_ACTION_END: return 1; return 0; default: return -EINVAL; } /* when arrive here ret=0 or sent data */ ssfw->pos += sigma_action_size(sa, len); return ssfw->pos == ssfw->fw->size; return 1; } static int process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw) { pr_debug("%s: processing %p\n", __func__, ssfw); struct sigma_action *sa; size_t size; int ret; while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) { sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos); size = sigma_action_size(sa); ssfw->pos += size; if (ssfw->pos > ssfw->fw->size || size == 0) break; ret = process_sigma_action(client, sa); while (1) { int ret = process_sigma_action(client, ssfw); pr_debug("%s: action returned %i\n", __func__, ret); if (ret == 1) return 0; else if (ret) if (ret <= 0) return ret; } if (ssfw->pos != ssfw->fw->size) return -EINVAL; return 0; } int process_sigma_firmware(struct i2c_client *client, const char *name) Loading @@ -89,16 +116,24 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) /* then verify the header */ ret = -EINVAL; if (fw->size < sizeof(*ssfw_head)) /* * Reject too small or unreasonable large files. The upper limit has been * chosen a bit arbitrarily, but it should be enough for all practical * purposes and having the limit makes it easier to avoid integer * overflows later in the loading process. */ if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) goto done; ssfw_head = (void *)fw->data; if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) goto done; crc = crc32(0, fw->data, fw->size); crc = crc32(0, fw->data + sizeof(*ssfw_head), fw->size - sizeof(*ssfw_head)); pr_debug("%s: crc=%x\n", __func__, crc); if (crc != ssfw_head->crc) if (crc != le32_to_cpu(ssfw_head->crc)) goto done; ssfw.pos = sizeof(*ssfw_head); Loading
include/linux/sigma.h +4 −9 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ struct sigma_firmware { struct sigma_firmware_header { unsigned char magic[7]; u8 version; u32 crc; __le32 crc; }; enum { Loading @@ -40,19 +40,14 @@ enum { struct sigma_action { u8 instr; u8 len_hi; u16 len; u16 addr; __le16 len; __be16 addr; unsigned char payload[]; }; static inline u32 sigma_action_len(struct sigma_action *sa) { return (sa->len_hi << 16) | sa->len; } static inline size_t sigma_action_size(struct sigma_action *sa, u32 payload_len) { return sizeof(*sa) + payload_len + (payload_len % 2); return (sa->len_hi << 16) | le16_to_cpu(sa->len); } extern int process_sigma_firmware(struct i2c_client *client, const char *name); Loading
sound/pci/hda/patch_realtek.c +49 −16 Original line number Diff line number Diff line Loading @@ -300,6 +300,8 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, imux = &spec->input_mux[mux_idx]; if (!imux->num_items && mux_idx > 0) imux = &spec->input_mux[0]; if (!imux->num_items) return 0; if (idx >= imux->num_items) idx = imux->num_items - 1; Loading Loading @@ -2663,6 +2665,8 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, case AUTO_PIN_SPEAKER_OUT: if (cfg->line_outs == 1) return "Speaker"; if (cfg->line_outs == 2) return ch ? "Bass Speaker" : "Speaker"; break; case AUTO_PIN_HP_OUT: /* for multi-io case, only the primary out */ Loading Loading @@ -2974,7 +2978,7 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) if (!nid) continue; if (found_in_nid_list(nid, spec->multiout.dac_nids, spec->multiout.num_dacs)) ARRAY_SIZE(spec->private_dac_nids))) continue; if (found_in_nid_list(nid, spec->multiout.hp_out_nid, ARRAY_SIZE(spec->multiout.hp_out_nid))) Loading Loading @@ -3012,6 +3016,7 @@ static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) return 0; } /* return 0 if no possible DAC is found, 1 if one or more found */ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, const hda_nid_t *pins, hda_nid_t *dacs) { Loading @@ -3029,7 +3034,7 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, if (!dacs[i]) dacs[i] = alc_auto_look_for_dac(codec, pins[i]); } return 0; return 1; } static int alc_auto_fill_multi_ios(struct hda_codec *codec, Loading @@ -3039,7 +3044,7 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec, static int alc_auto_fill_dac_nids(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; const struct auto_pin_cfg *cfg = &spec->autocfg; struct auto_pin_cfg *cfg = &spec->autocfg; unsigned int location, defcfg; int num_pins; bool redone = false; Loading @@ -3052,6 +3057,7 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) spec->multiout.extra_out_nid[0] = 0; memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); spec->multiout.dac_nids = spec->private_dac_nids; spec->multi_ios = 0; /* fill hard-wired DACs first */ if (!redone) { Loading Loading @@ -3085,10 +3091,12 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) for (i = 0; i < cfg->line_outs; i++) { if (spec->private_dac_nids[i]) spec->multiout.num_dacs++; else else { memmove(spec->private_dac_nids + i, spec->private_dac_nids + i + 1, sizeof(hda_nid_t) * (cfg->line_outs - i - 1)); spec->private_dac_nids[cfg->line_outs - 1] = 0; } } if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { Loading @@ -3107,9 +3115,28 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) if (cfg->line_out_type != AUTO_PIN_HP_OUT) alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins, spec->multiout.hp_out_nid); if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins, if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins, spec->multiout.extra_out_nid); /* if no speaker volume is assigned, try again as the primary * output */ if (!err && cfg->speaker_outs > 0 && cfg->line_out_type == AUTO_PIN_HP_OUT) { cfg->hp_outs = cfg->line_outs; memcpy(cfg->hp_pins, cfg->line_out_pins, sizeof(cfg->hp_pins)); cfg->line_outs = cfg->speaker_outs; memcpy(cfg->line_out_pins, cfg->speaker_pins, sizeof(cfg->speaker_pins)); cfg->speaker_outs = 0; memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; redone = false; goto again; } } if (!spec->multi_ios && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && Loading Loading @@ -3287,7 +3314,8 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, } static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac, const char *pfx) hda_nid_t dac, const char *pfx, int cidx) { struct alc_spec *spec = codec->spec; hda_nid_t sw, vol; Loading @@ -3303,15 +3331,15 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, if (is_ctl_used(spec->sw_ctls, val)) return 0; /* already created */ mark_ctl_usage(spec->sw_ctls, val); return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val); return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, cidx, val); } sw = alc_look_for_out_mute_nid(codec, pin, dac); vol = alc_look_for_out_vol_nid(codec, pin, dac); err = alc_auto_add_stereo_vol(codec, pfx, 0, vol); err = alc_auto_add_stereo_vol(codec, pfx, cidx, vol); if (err < 0) return err; err = alc_auto_add_stereo_sw(codec, pfx, 0, sw); err = alc_auto_add_stereo_sw(codec, pfx, cidx, sw); if (err < 0) return err; return 0; Loading Loading @@ -3352,16 +3380,21 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, hda_nid_t dac = *dacs; if (!dac) dac = spec->multiout.dac_nids[0]; return alc_auto_create_extra_out(codec, *pins, dac, pfx); return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0); } if (dacs[num_pins - 1]) { /* OK, we have a multi-output system with individual volumes */ for (i = 0; i < num_pins; i++) { if (num_pins >= 3) { snprintf(name, sizeof(name), "%s %s", pfx, channel_name[i]); err = alc_auto_create_extra_out(codec, pins[i], dacs[i], name); name, 0); } else { err = alc_auto_create_extra_out(codec, pins[i], dacs[i], pfx, i); } if (err < 0) return err; } Loading
sound/pci/hda/patch_sigmatel.c +25 −22 Original line number Diff line number Diff line Loading @@ -215,6 +215,7 @@ struct sigmatel_spec { unsigned int gpio_mute; unsigned int gpio_led; unsigned int gpio_led_polarity; unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */ unsigned int vref_led; /* stream */ Loading Loading @@ -4318,14 +4319,12 @@ static void stac_store_hints(struct hda_codec *codec) spec->eapd_switch = val; get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { if (spec->gpio_led <= 8) { spec->gpio_mask |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led; if (spec->gpio_led_polarity) spec->gpio_data |= spec->gpio_led; } } } static int stac92xx_init(struct hda_codec *codec) { Loading Loading @@ -4443,7 +4442,7 @@ static int stac92xx_init(struct hda_codec *codec) /* power on when no jack detection is available */ /* or when the VREF is used for controlling LED */ if (!spec->hp_detect || (spec->gpio_led > 8 && spec->gpio_led == nid)) { spec->vref_mute_led_nid == nid) { stac_toggle_power_map(codec, nid, 1); continue; } Loading Loading @@ -4915,8 +4914,14 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) if (sscanf(dev->name, "HP_Mute_LED_%d_%x", &spec->gpio_led_polarity, &spec->gpio_led) == 2) { if (spec->gpio_led < 4) unsigned int max_gpio; max_gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); max_gpio &= AC_GPIO_IO_COUNT; if (spec->gpio_led < max_gpio) spec->gpio_led = 1 << spec->gpio_led; else spec->vref_mute_led_nid = spec->gpio_led; return 1; } if (sscanf(dev->name, "HP_Mute_LED_%d", Loading Loading @@ -5045,15 +5050,12 @@ static int stac92xx_pre_resume(struct hda_codec *codec) struct sigmatel_spec *spec = codec->spec; /* sync mute LED */ if (spec->gpio_led) { if (spec->gpio_led <= 8) { if (spec->vref_mute_led_nid) stac_vrefout_set(codec, spec->vref_mute_led_nid, spec->vref_led); else if (spec->gpio_led) stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); } else { stac_vrefout_set(codec, spec->gpio_led, spec->vref_led); } } return 0; } Loading @@ -5064,7 +5066,7 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, struct sigmatel_spec *spec = codec->spec; if (power_state == AC_PWRST_D3) { if (spec->gpio_led > 8) { if (spec->vref_mute_led_nid) { /* with vref-out pin used for mute led control * codec AFG is prevented from D3 state */ Loading Loading @@ -5117,7 +5119,7 @@ static int stac92xx_update_led_status(struct hda_codec *codec) } } /*polarity defines *not* muted state level*/ if (spec->gpio_led <= 8) { if (!spec->vref_mute_led_nid) { if (muted) spec->gpio_data &= ~spec->gpio_led; /* orange */ else Loading @@ -5135,7 +5137,8 @@ static int stac92xx_update_led_status(struct hda_codec *codec) muted_lvl = spec->gpio_led_polarity ? AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; spec->vref_led = muted ? muted_lvl : notmtd_lvl; stac_vrefout_set(codec, spec->gpio_led, spec->vref_led); stac_vrefout_set(codec, spec->vref_mute_led_nid, spec->vref_led); } return 0; } Loading Loading @@ -5649,7 +5652,7 @@ again: #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { if (spec->gpio_led <= 8) { if (!spec->vref_mute_led_nid) { spec->gpio_mask |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led; spec->gpio_data |= spec->gpio_led; Loading Loading @@ -5962,7 +5965,7 @@ again: #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { if (spec->gpio_led <= 8) { if (!spec->vref_mute_led_nid) { spec->gpio_mask |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led; spec->gpio_data |= spec->gpio_led; Loading