Lines Matching +full:codec +full:- +full:irq

2  * Rockchip machine ASoC driver for Rockchip Multi-codecs audio
6 * Authors: Sugar Zhang <sugar.zhang@rock-chips.com>,
22 #include <linux/extcon-provider.h>
28 #include <linux/irq.h>
39 #include <sound/soc-dapm.h>
41 #define DRV_NAME "rk-multicodecs"
42 #define WAIT_CARDS (SNDRV_CARDS - 1)
87 poller->poll_interval_ms = interval; in mc_set_poll_interval()
94 delay = msecs_to_jiffies(poller->poll_interval_ms); in mc_keys_poller_queue_work()
98 queue_delayed_work(system_freezable_wq, &poller->work, delay); in mc_keys_poller_queue_work()
106 poller->poll(poller->input); in mc_keys_poller_work()
112 if (poller->poll_interval_ms > 0) { in mc_keys_poller_start()
113 poller->poll(poller->input); in mc_keys_poller_start()
120 cancel_delayed_work_sync(&poller->work); in mc_keys_poller_stop()
128 poller = devm_kzalloc(mc_data->snd_card.dev, sizeof(*poller), GFP_KERNEL); in mc_keys_setup_polling()
130 return -ENOMEM; in mc_keys_setup_polling()
132 INIT_DELAYED_WORK(&poller->work, mc_keys_poller_work); in mc_keys_setup_polling()
133 poller->input = mc_data->input; in mc_keys_setup_polling()
134 poller->poll = poll_fn; in mc_keys_setup_polling()
135 mc_data->poller = poller; in mc_keys_setup_polling()
147 ret = iio_read_channel_processed(mc_data->adc, &value); in mc_keys_poll()
150 value = mc_data->keyup_voltage; in mc_keys_poll()
152 for (i = 0; i < mc_data->num_keys; i++) { in mc_keys_poll()
153 diff = abs(mc_data->map[i].voltage - value); in mc_keys_poll()
156 keycode = mc_data->map[i].keycode; in mc_keys_poll()
161 if (abs(mc_data->keyup_voltage - value) < closest) in mc_keys_poll()
164 if (mc_data->last_key && mc_data->last_key != keycode) in mc_keys_poll()
165 input_report_key(input, mc_data->last_key, 0); in mc_keys_poll()
171 mc_data->last_key = keycode; in mc_keys_poll()
181 mc_data->num_keys = device_get_child_node_count(dev); in mc_keys_load_keymap()
182 if (mc_data->num_keys == 0) { in mc_keys_load_keymap()
184 return -EINVAL; in mc_keys_load_keymap()
187 map = devm_kmalloc_array(dev, mc_data->num_keys, sizeof(*map), GFP_KERNEL); in mc_keys_load_keymap()
189 return -ENOMEM; in mc_keys_load_keymap()
192 if (fwnode_property_read_u32(child, "press-threshold-microvolt", in mc_keys_load_keymap()
196 return -EINVAL; in mc_keys_load_keymap()
204 return -EINVAL; in mc_keys_load_keymap()
209 mc_data->map = map; in mc_keys_load_keymap()
218 struct snd_soc_jack *jack_headset = mc_data->jack_headset; in adc_jack_handler()
221 if (!gpiod_get_value(mc_data->hp_det_gpio)) { in adc_jack_handler()
223 extcon_set_state_sync(mc_data->extcon, in adc_jack_handler()
225 extcon_set_state_sync(mc_data->extcon, in adc_jack_handler()
227 if (mc_data->poller) in adc_jack_handler()
228 mc_keys_poller_stop(mc_data->poller); in adc_jack_handler()
232 if (!mc_data->adc) { in adc_jack_handler()
235 extcon_set_state_sync(mc_data->extcon, EXTCON_JACK_HEADPHONE, true); in adc_jack_handler()
236 extcon_set_state_sync(mc_data->extcon, EXTCON_JACK_MICROPHONE, false); in adc_jack_handler()
239 ret = iio_read_channel_processed(mc_data->adc, &adc); in adc_jack_handler()
243 extcon_set_state_sync(mc_data->extcon, EXTCON_JACK_HEADPHONE, true); in adc_jack_handler()
244 extcon_set_state_sync(mc_data->extcon, EXTCON_JACK_MICROPHONE, false); in adc_jack_handler()
250 extcon_set_state_sync(mc_data->extcon, EXTCON_JACK_HEADPHONE, true); in adc_jack_handler()
253 extcon_set_state_sync(mc_data->extcon, EXTCON_JACK_MICROPHONE, true); in adc_jack_handler()
254 if (mc_data->poller) in adc_jack_handler()
255 mc_keys_poller_start(mc_data->poller); in adc_jack_handler()
260 static irqreturn_t headset_det_irq_thread(int irq, void *data) in headset_det_irq_thread() argument
264 queue_delayed_work(system_power_efficient_wq, &mc_data->handler, msecs_to_jiffies(200)); in headset_det_irq_thread()
272 struct snd_soc_card *card = w->dapm->card; in mc_hp_event()
277 gpiod_set_value_cansleep(mc_data->hp_ctl_gpio, 1); in mc_hp_event()
280 gpiod_set_value_cansleep(mc_data->hp_ctl_gpio, 0); in mc_hp_event()
293 struct snd_soc_card *card = w->dapm->card; in mc_spk_event()
298 gpiod_set_value_cansleep(mc_data->spk_ctl_gpio, 1); in mc_spk_event()
301 gpiod_set_value_cansleep(mc_data->spk_ctl_gpio, 0); in mc_spk_event()
342 struct multicodecs_data *mc_data = snd_soc_card_get_drvdata(rtd->card); in rk_multicodecs_hw_params()
346 mclk = params_rate(params) * mc_data->mclk_fs; in rk_multicodecs_hw_params()
349 ret = snd_soc_dai_set_sysclk(codec_dai, substream->stream, mclk, in rk_multicodecs_hw_params()
351 if (ret && ret != -ENOTSUPP) { in rk_multicodecs_hw_params()
357 ret = snd_soc_dai_set_sysclk(cpu_dai, substream->stream, mclk, in rk_multicodecs_hw_params()
359 if (ret && ret != -ENOTSUPP) { in rk_multicodecs_hw_params()
372 struct multicodecs_data *mc_data = snd_soc_card_get_drvdata(rtd->card); in rk_dailink_init()
373 struct snd_soc_card *card = rtd->card; in rk_dailink_init()
375 int ret, irq; in rk_dailink_init() local
403 if ((!mc_data->codec_hp_det) && (gpiod_to_irq(mc_data->hp_det_gpio) < 0)) { in rk_dailink_init()
404 dev_info(card->dev, "Don't need to map headset detect gpio to irq\n"); in rk_dailink_init()
408 jack_headset = devm_kzalloc(card->dev, sizeof(*jack_headset), GFP_KERNEL); in rk_dailink_init()
410 return -ENOMEM; in rk_dailink_init()
412 pins = devm_kmemdup(card->dev, jack_pins, in rk_dailink_init()
415 return -ENOMEM; in rk_dailink_init()
417 zones = devm_kmemdup(card->dev, headset_zones, in rk_dailink_init()
420 return -ENOMEM; in rk_dailink_init()
432 mc_data->jack_headset = jack_headset; in rk_dailink_init()
434 if (mc_data->codec_hp_det) { in rk_dailink_init()
440 ret = snd_soc_component_set_jack(codec_dai->component, in rk_dailink_init()
446 irq = gpiod_to_irq(mc_data->hp_det_gpio); in rk_dailink_init()
447 if (irq >= 0) { in rk_dailink_init()
448 ret = devm_request_threaded_irq(card->dev, irq, NULL, in rk_dailink_init()
456 dev_err(card->dev, "Failed to request headset detect irq"); in rk_dailink_init()
461 &mc_data->handler, msecs_to_jiffies(50)); in rk_dailink_init()
469 struct device_node *codec, in rk_multicodecs_parse_daifmt() argument
473 struct snd_soc_dai_link *dai_link = &mc_data->dai_link; in rk_multicodecs_parse_daifmt()
485 * No dai-link level and master setting was not found from in rk_multicodecs_parse_daifmt()
487 * take the settings from codec node. in rk_multicodecs_parse_daifmt()
491 daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) | in rk_multicodecs_parse_daifmt()
494 if (codec == bitclkmaster) in rk_multicodecs_parse_daifmt()
495 daifmt |= (codec == framemaster) ? in rk_multicodecs_parse_daifmt()
498 daifmt |= (codec == framemaster) ? in rk_multicodecs_parse_daifmt()
509 dai_link->dai_fmt = daifmt; in rk_multicodecs_parse_daifmt()
519 char *propname = "rockchip,wait-card-locked"; in wait_locked_card()
529 if (ret == -EINVAL) { in wait_locked_card()
531 * -EINVAL means the property does not exist, this is in wait_locked_card()
548 if (ret == -EINVAL) { in wait_locked_card()
550 * -EINVAL means the property does not exist, this is in wait_locked_card()
565 dev_warn(dev, "card: %d has not been locked, re-probe again\n", in wait_locked_card()
567 ret = -EPROBE_DEFER; in wait_locked_card()
583 struct device_node *np = pdev->dev.of_node; in rk_multicodecs_probe()
597 ret = wait_locked_card(np, &pdev->dev); in rk_multicodecs_probe()
599 dev_err(&pdev->dev, "check_lock_card failed: %d\n", ret); in rk_multicodecs_probe()
603 mc_data = devm_kzalloc(&pdev->dev, sizeof(*mc_data), GFP_KERNEL); in rk_multicodecs_probe()
605 return -ENOMEM; in rk_multicodecs_probe()
607 cpus = devm_kzalloc(&pdev->dev, sizeof(*cpus), GFP_KERNEL); in rk_multicodecs_probe()
609 return -ENOMEM; in rk_multicodecs_probe()
611 platforms = devm_kzalloc(&pdev->dev, sizeof(*platforms), GFP_KERNEL); in rk_multicodecs_probe()
613 return -ENOMEM; in rk_multicodecs_probe()
615 card = &mc_data->snd_card; in rk_multicodecs_probe()
616 card->dev = &pdev->dev; in rk_multicodecs_probe()
619 ret = snd_soc_of_parse_card_name(card, "rockchip,card-name"); in rk_multicodecs_probe()
623 link = &mc_data->dai_link; in rk_multicodecs_probe()
624 link->name = "dailink-multicodecs"; in rk_multicodecs_probe()
625 link->stream_name = link->name; in rk_multicodecs_probe()
626 link->init = rk_dailink_init; in rk_multicodecs_probe()
627 link->ops = &rk_ops; in rk_multicodecs_probe()
628 link->cpus = cpus; in rk_multicodecs_probe()
629 link->platforms = platforms; in rk_multicodecs_probe()
630 link->num_cpus = 1; in rk_multicodecs_probe()
631 link->num_platforms = 1; in rk_multicodecs_probe()
632 link->ignore_pmdown_time = 1; in rk_multicodecs_probe()
634 card->dai_link = link; in rk_multicodecs_probe()
635 card->num_links = 1; in rk_multicodecs_probe()
636 card->dapm_widgets = mc_dapm_widgets; in rk_multicodecs_probe()
637 card->num_dapm_widgets = ARRAY_SIZE(mc_dapm_widgets); in rk_multicodecs_probe()
638 card->controls = mc_controls; in rk_multicodecs_probe()
639 card->num_controls = ARRAY_SIZE(mc_controls); in rk_multicodecs_probe()
640 card->num_aux_devs = 0; in rk_multicodecs_probe()
642 count = of_count_phandle_with_args(np, "rockchip,codec", NULL); in rk_multicodecs_probe()
644 return -EINVAL; in rk_multicodecs_probe()
648 node = of_parse_phandle(np, "rockchip,codec", i); in rk_multicodecs_probe()
650 return -ENODEV; in rk_multicodecs_probe()
656 return -ENODEV; in rk_multicodecs_probe()
658 codecs = devm_kcalloc(&pdev->dev, idx, in rk_multicodecs_probe()
661 return -ENOMEM; in rk_multicodecs_probe()
663 link->codecs = codecs; in rk_multicodecs_probe()
664 link->num_codecs = idx; in rk_multicodecs_probe()
667 node = of_parse_phandle(np, "rockchip,codec", i); in rk_multicodecs_probe()
669 return -ENODEV; in rk_multicodecs_probe()
673 ret = of_parse_phandle_with_fixed_args(np, "rockchip,codec", in rk_multicodecs_probe()
688 link->cpus->of_node = of_parse_phandle(np, "rockchip,cpu", 0); in rk_multicodecs_probe()
689 if (!link->cpus->of_node) in rk_multicodecs_probe()
690 return -ENODEV; in rk_multicodecs_probe()
692 link->platforms->of_node = link->cpus->of_node; in rk_multicodecs_probe()
694 mc_data->mclk_fs = DEFAULT_MCLK_FS; in rk_multicodecs_probe()
695 if (!of_property_read_u32(np, "rockchip,mclk-fs", &val)) in rk_multicodecs_probe()
696 mc_data->mclk_fs = val; in rk_multicodecs_probe()
698 mc_data->codec_hp_det = in rk_multicodecs_probe()
699 of_property_read_bool(np, "rockchip,codec-hp-det"); in rk_multicodecs_probe()
701 mc_data->adc = devm_iio_channel_get(&pdev->dev, "adc-detect"); in rk_multicodecs_probe()
703 if (IS_ERR(mc_data->adc)) { in rk_multicodecs_probe()
704 if (PTR_ERR(mc_data->adc) != -EPROBE_DEFER) { in rk_multicodecs_probe()
705 mc_data->adc = NULL; in rk_multicodecs_probe()
706 dev_warn(&pdev->dev, "Failed to get ADC channel"); in rk_multicodecs_probe()
709 if (mc_data->adc->channel->type != IIO_VOLTAGE) in rk_multicodecs_probe()
710 return -EINVAL; in rk_multicodecs_probe()
712 if (device_property_read_u32(&pdev->dev, "keyup-threshold-microvolt", in rk_multicodecs_probe()
713 &mc_data->keyup_voltage)) { in rk_multicodecs_probe()
714 dev_warn(&pdev->dev, "Invalid or missing keyup voltage\n"); in rk_multicodecs_probe()
715 return -EINVAL; in rk_multicodecs_probe()
717 mc_data->keyup_voltage /= 1000; in rk_multicodecs_probe()
719 ret = mc_keys_load_keymap(&pdev->dev, mc_data); in rk_multicodecs_probe()
723 input = devm_input_allocate_device(&pdev->dev); in rk_multicodecs_probe()
725 dev_err(&pdev->dev, "failed to allocate input device\n"); in rk_multicodecs_probe()
731 input->name = "headset-keys"; in rk_multicodecs_probe()
732 input->phys = "headset-keys/input0"; in rk_multicodecs_probe()
733 input->id.bustype = BUS_HOST; in rk_multicodecs_probe()
734 input->id.vendor = 0x0001; in rk_multicodecs_probe()
735 input->id.product = 0x0001; in rk_multicodecs_probe()
736 input->id.version = 0x0100; in rk_multicodecs_probe()
738 __set_bit(EV_KEY, input->evbit); in rk_multicodecs_probe()
739 for (i = 0; i < mc_data->num_keys; i++) in rk_multicodecs_probe()
740 __set_bit(mc_data->map[i].keycode, input->keybit); in rk_multicodecs_probe()
742 if (device_property_read_bool(&pdev->dev, "autorepeat")) in rk_multicodecs_probe()
743 __set_bit(EV_REP, input->evbit); in rk_multicodecs_probe()
745 mc_data->input = input; in rk_multicodecs_probe()
748 dev_err(&pdev->dev, "Unable to set up polling: %d\n", ret); in rk_multicodecs_probe()
752 if (!device_property_read_u32(&pdev->dev, "poll-interval", &value)) in rk_multicodecs_probe()
753 mc_set_poll_interval(mc_data->poller, value); in rk_multicodecs_probe()
755 ret = input_register_device(mc_data->input); in rk_multicodecs_probe()
757 dev_err(&pdev->dev, "Unable to register input device: %d\n", ret); in rk_multicodecs_probe()
762 INIT_DEFERRABLE_WORK(&mc_data->handler, adc_jack_handler); in rk_multicodecs_probe()
764 mc_data->spk_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, in rk_multicodecs_probe()
765 "spk-con", in rk_multicodecs_probe()
767 if (IS_ERR(mc_data->spk_ctl_gpio)) in rk_multicodecs_probe()
768 return PTR_ERR(mc_data->spk_ctl_gpio); in rk_multicodecs_probe()
770 mc_data->hp_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, in rk_multicodecs_probe()
771 "hp-con", in rk_multicodecs_probe()
773 if (IS_ERR(mc_data->hp_ctl_gpio)) in rk_multicodecs_probe()
774 return PTR_ERR(mc_data->hp_ctl_gpio); in rk_multicodecs_probe()
776 mc_data->hp_det_gpio = devm_gpiod_get_optional(&pdev->dev, "hp-det", GPIOD_IN); in rk_multicodecs_probe()
777 if (IS_ERR(mc_data->hp_det_gpio)) in rk_multicodecs_probe()
778 return PTR_ERR(mc_data->hp_det_gpio); in rk_multicodecs_probe()
780 mc_data->extcon = devm_extcon_dev_allocate(&pdev->dev, headset_extcon_cable); in rk_multicodecs_probe()
781 if (IS_ERR(mc_data->extcon)) { in rk_multicodecs_probe()
782 dev_err(&pdev->dev, "allocate extcon failed\n"); in rk_multicodecs_probe()
783 return PTR_ERR(mc_data->extcon); in rk_multicodecs_probe()
786 ret = devm_extcon_dev_register(&pdev->dev, mc_data->extcon); in rk_multicodecs_probe()
788 dev_err(&pdev->dev, "failed to register extcon: %d\n", ret); in rk_multicodecs_probe()
792 ret = snd_soc_of_parse_audio_routing(card, "rockchip,audio-routing"); in rk_multicodecs_probe()
794 dev_warn(&pdev->dev, "Audio routing invalid/unspecified\n"); in rk_multicodecs_probe()
798 ret = devm_snd_soc_register_card(&pdev->dev, card); in rk_multicodecs_probe()
799 if (ret == -EPROBE_DEFER) in rk_multicodecs_probe()
800 return -EPROBE_DEFER; in rk_multicodecs_probe()
802 dev_err(&pdev->dev, "card register failed %d\n", ret); in rk_multicodecs_probe()
812 { .compatible = "rockchip,multicodecs-card", },
829 MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");