static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_card *card = codec->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); struct tegra_wm8903_platform_data *pdata = machine->pdata; int ret; machine->bias_level = SND_SOC_BIAS_STANDBY; machine->codec = codec; if (gpio_is_valid(pdata->gpio_spkr_en)) { ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); if (ret) { dev_err(card->dev, "cannot get spkr_en gpio\n"); return ret; } machine->gpio_requested |= GPIO_SPKR_EN; gpio_direction_output(pdata->gpio_spkr_en, 0); gpio_export(pdata->gpio_spkr_en, false); } if (gpio_is_valid(pdata->gpio_hp_mute)) { ret = gpio_request(pdata->gpio_hp_mute, "hp_mute"); if (ret) { dev_err(card->dev, "cannot get hp_mute gpio\n"); return ret; } machine->gpio_requested |= GPIO_HP_MUTE; gpio_direction_output(pdata->gpio_hp_mute, 0); } if (gpio_is_valid(pdata->gpio_int_mic_en)) { ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); if (ret) { dev_err(card->dev, "cannot get int_mic_en gpio\n"); return ret; } machine->gpio_requested |= GPIO_INT_MIC_EN; /* Disable int mic; enable signal is active-high */ gpio_direction_output(pdata->gpio_int_mic_en, 0); gpio_export(pdata->gpio_int_mic_en, false); } if (gpio_is_valid(pdata->gpio_ext_mic_en)) { ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); if (ret) { dev_err(card->dev, "cannot get ext_mic_en gpio\n"); return ret; } machine->gpio_requested |= GPIO_EXT_MIC_EN; /* Enable ext mic; enable signal is active-low */ gpio_direction_output(pdata->gpio_ext_mic_en, 1); gpio_export(pdata->gpio_ext_mic_en, false); } if (gpio_is_valid(pdata->gpio_ext_mic_det)) { ret = gpio_request(pdata->gpio_ext_mic_det, "ext_mic_det"); if (ret) { dev_err(card->dev, "cannot get ext_mic_det gpio\n"); return ret; } /* Detect ext mic; detect signal is active-low */ gpio_direction_input(pdata->gpio_ext_mic_det); gpio_export(pdata->gpio_ext_mic_det, false); } #if 0 if (machine_is_cardhu() || machine_is_ventana()) { ret = snd_soc_add_controls(codec, cardhu_controls, ARRAY_SIZE(cardhu_controls)); if (ret < 0) return ret; snd_soc_dapm_new_controls(dapm, cardhu_dapm_widgets, ARRAY_SIZE(cardhu_dapm_widgets)); } else { ret = snd_soc_add_controls(codec, tegra_wm8903_default_controls, ARRAY_SIZE(tegra_wm8903_default_controls)); if (ret < 0) return ret; snd_soc_dapm_new_controls(dapm, tegra_wm8903_default_dapm_widgets, ARRAY_SIZE(tegra_wm8903_default_dapm_widgets)); } if (machine_is_harmony()) { snd_soc_dapm_add_routes(dapm, harmony_audio_map, ARRAY_SIZE(harmony_audio_map)); } else if (machine_is_cardhu() || machine_is_ventana()) { snd_soc_dapm_add_routes(dapm, cardhu_audio_map, ARRAY_SIZE(cardhu_audio_map)); } else if (machine_is_seaboard()) { snd_soc_dapm_add_routes(dapm, seaboard_audio_map, ARRAY_SIZE(seaboard_audio_map)); } else if (machine_is_kaen()) { snd_soc_dapm_add_routes(dapm, kaen_audio_map, ARRAY_SIZE(kaen_audio_map)); } else { snd_soc_dapm_add_routes(dapm, aebl_audio_map, ARRAY_SIZE(aebl_audio_map)); } #endif ret = snd_soc_add_controls(codec, ast_controls, ARRAY_SIZE(ast_controls)); if (ret < 0) return ret; snd_soc_dapm_new_controls(dapm, ast_dapm_widgets, ARRAY_SIZE(ast_dapm_widgets)); snd_soc_dapm_add_routes(dapm, ast_audio_map, ARRAY_SIZE(ast_audio_map)); if (gpio_is_valid(pdata->gpio_lineout_det)) { tegra_wm8903_lineout_jack_gpio.gpio = pdata->gpio_lineout_det; snd_soc_jack_new(codec, "Lineout Jack", SND_JACK_LINEOUT, &tegra_wm8903_lineout_jack); #ifndef CONFIG_SWITCH snd_soc_jack_add_pins(&tegra_wm8903_lineout_jack, ARRAY_SIZE(tegra_wm8903_lineout_jack_pins), tegra_wm8903_lineout_jack_pins); #else snd_soc_jack_notifier_register(&tegra_wm8903_lineout_jack, &tegra_wm8903_jack_detect_nb); #endif snd_soc_jack_add_gpios(&tegra_wm8903_lineout_jack, 1, &tegra_wm8903_lineout_jack_gpio); machine->gpio_requested |= GPIO_LINEOUT_DET; } if (gpio_is_valid(pdata->gpio_hp_det)) { tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det; snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, &tegra_wm8903_hp_jack); #ifndef CONFIG_SWITCH snd_soc_jack_add_pins(&tegra_wm8903_hp_jack, ARRAY_SIZE(tegra_wm8903_hp_jack_pins), tegra_wm8903_hp_jack_pins); #else snd_soc_jack_notifier_register(&tegra_wm8903_hp_jack, &tegra_wm8903_jack_detect_nb); #endif snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, 1, &tegra_wm8903_hp_jack_gpio); machine->gpio_requested |= GPIO_HP_DET; } machine->ac_notifier.notifier_call = ac_notify; nvtec_ac_notifier_register(&machine->ac_notifier); #if 0 snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, &tegra_wm8903_mic_jack); #ifndef CONFIG_SWITCH snd_soc_jack_add_pins(&tegra_wm8903_mic_jack, ARRAY_SIZE(tegra_wm8903_mic_jack_pins), tegra_wm8903_mic_jack_pins); #else snd_soc_jack_notifier_register(&tegra_wm8903_mic_jack, &tegra_wm8903_jack_detect_nb); #endif wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE, machine_is_cardhu() ? SND_JACK_MICROPHONE : 0); snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); /* FIXME: Calculate automatically based on DAPM routes? */ if (!machine_is_harmony() && !machine_is_ventana() && !machine_is_cardhu()) snd_soc_dapm_nc_pin(dapm, "IN1L"); if (!machine_is_seaboard() && !machine_is_aebl() && !machine_is_cardhu()) snd_soc_dapm_nc_pin(dapm, "IN1R"); snd_soc_dapm_nc_pin(dapm, "IN2L"); if (!machine_is_kaen()) snd_soc_dapm_nc_pin(dapm, "IN2R"); snd_soc_dapm_nc_pin(dapm, "IN3L"); snd_soc_dapm_nc_pin(dapm, "IN3R"); if (machine_is_aebl()) { snd_soc_dapm_nc_pin(dapm, "LON"); snd_soc_dapm_nc_pin(dapm, "RON"); snd_soc_dapm_nc_pin(dapm, "ROP"); snd_soc_dapm_nc_pin(dapm, "LOP"); } else { snd_soc_dapm_nc_pin(dapm, "LINEOUTR"); snd_soc_dapm_nc_pin(dapm, "LINEOUTL"); } #endif snd_soc_dapm_disable_pin(dapm, "Int Spk"); snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin(dapm, "Line Out Jack"); snd_soc_dapm_disable_pin(dapm, "Mic Jack"); snd_soc_dapm_disable_pin(dapm, "Int Mic"); snd_soc_dapm_sync(dapm); return 0; }
static int __devinit gpio_keys_probe(struct platform_device *pdev) { const struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct gpio_keys_drvdata *ddata; struct device *dev = &pdev->dev; struct gpio_keys_platform_data alt_pdata; struct input_dev *input; int i, error; int wakeup = 0; if (!pdata) { error = gpio_keys_get_devtree_pdata(dev, &alt_pdata); if (error) return error; pdata = &alt_pdata; } ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + pdata->nbuttons * sizeof(struct gpio_button_data), GFP_KERNEL); input = input_allocate_device(); if (!ddata || !input) { dev_err(dev, "failed to allocate state\n"); error = -ENOMEM; goto fail1; } ddata->input = input; ddata->n_buttons = pdata->nbuttons; ddata->enable = pdata->enable; ddata->disable = pdata->disable; mutex_init(&ddata->disable_lock); switch_gpio_notifier.notifier_call = switch_gpio_notify; switch_gpio_notifier_register(&switch_gpio_notifier); platform_set_drvdata(pdev, ddata); input_set_drvdata(input, ddata); input->name = pdata->name ? : pdev->name; input->phys = "gpio-keys/input0"; input->dev.parent = &pdev->dev; input->open = gpio_keys_open; input->close = gpio_keys_close; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0100; /* Enable auto repeat feature of Linux input subsystem */ if (pdata->rep) __set_bit(EV_REP, input->evbit); for (i = 0; i < pdata->nbuttons; i++) { const struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_button_data *bdata = &ddata->data[i]; error = gpio_keys_setup_key(pdev, input, bdata, button); if (error) goto fail2; if (button->wakeup) wakeup = 1; } error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); if (error) { dev_err(dev, "Unable to export keys/switches, error: %d\n", error); goto fail2; } error = input_register_device(input); if (error) { dev_err(dev, "Unable to register input device, error: %d\n", error); goto fail3; } /* get current state of buttons that are connected to GPIOs */ for (i = 0; i < pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (gpio_is_valid(bdata->button->gpio)) gpio_keys_gpio_report_event(bdata); } input_sync(input); device_init_wakeup(&pdev->dev, wakeup); ddata->nb.notifier_call = &gpio_keys_ac_notifier; nvtec_ac_notifier_register(&ddata->nb); ddata->early_suspender.suspend = gpio_keys_early_suspend; ddata->early_suspender.resume = gpio_keys_late_resume; register_early_suspend(&ddata->early_suspender); return 0; fail3: sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); fail2: while (--i >= 0) gpio_remove_key(&ddata->data[i]); platform_set_drvdata(pdev, NULL); fail1: input_free_device(input); kfree(ddata); /* If we have no platform_data, we allocated buttons dynamically. */ if (!pdev->dev.platform_data) kfree(pdata->buttons); return error; }