Merge "asoc: bolero: Fix compile errors on rx/tx macro"
diff --git a/asoc/codecs/wcd-irq.c b/asoc/codecs/wcd-irq.c
new file mode 100644
index 0000000..12bbf36
--- /dev/null
+++ b/asoc/codecs/wcd-irq.c
@@ -0,0 +1,191 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/irqdomain.h>
+#include <linux/regmap.h>
+#include <asoc/wcd-irq.h>
+
+static int wcd_map_irq(struct wcd_irq_info *irq_info, int irq)
+{
+ if (!irq_info) {
+ pr_err("%s: Null IRQ handle\n", __func__);
+ return -EINVAL;
+ }
+ return regmap_irq_get_virq(irq_info->irq_chip, irq);
+}
+
+/**
+ * wcd_request_irq: Request a thread handler for the given IRQ
+ * @irq_info: pointer to IRQ info structure
+ * @irq: irq number
+ * @name: name for the IRQ thread
+ * @handler: irq handler
+ * @data: data pointer
+ *
+ * Returns 0 on success or error on failure
+ */
+int wcd_request_irq(struct wcd_irq_info *irq_info, int irq, const char *name,
+ irq_handler_t handler, void *data)
+{
+ if (!irq_info) {
+ pr_err("%s: Null IRQ handle\n", __func__);
+ return -EINVAL;
+ }
+ irq = wcd_map_irq(irq_info, irq);
+ if (irq < 0)
+ return irq;
+
+ return request_threaded_irq(irq, NULL, handler,
+ IRQF_ONESHOT | IRQF_TRIGGER_RISING,
+ name, data);
+}
+EXPORT_SYMBOL(wcd_request_irq);
+
+/**
+ * wcd_free_irq: Free the IRQ resources allocated during request_irq
+ * @irq_info: pointer to IRQ info structure
+ * @irq: irq number
+ * @data: data pointer
+ */
+void wcd_free_irq(struct wcd_irq_info *irq_info, int irq, void *data)
+{
+ if (!irq_info) {
+ pr_err("%s: Null IRQ handle\n", __func__);
+ return;
+ }
+
+ irq = wcd_map_irq(irq_info, irq);
+ if (irq < 0)
+ return;
+
+ free_irq(irq, data);
+}
+EXPORT_SYMBOL(wcd_free_irq);
+
+/**
+ * wcd_enable_irq: Enable the given IRQ
+ * @irq_info: pointer to IRQ info structure
+ * @irq: irq number
+ */
+void wcd_enable_irq(struct wcd_irq_info *irq_info, int irq)
+{
+ if (!irq_info)
+ pr_err("%s: Null IRQ handle\n", __func__);
+ else
+ enable_irq(wcd_map_irq(irq_info, irq));
+}
+EXPORT_SYMBOL(wcd_enable_irq);
+
+/**
+ * wcd_disable_irq: Disable the given IRQ
+ * @irq_info: pointer to IRQ info structure
+ * @irq: irq number
+ */
+void wcd_disable_irq(struct wcd_irq_info *irq_info, int irq)
+{
+ if (!irq_info)
+ pr_err("%s: Null IRQ handle\n", __func__);
+ else
+ disable_irq(wcd_map_irq(irq_info, irq));
+}
+EXPORT_SYMBOL(wcd_disable_irq);
+
+static void wcd_irq_chip_disable(struct irq_data *data)
+{
+}
+
+static void wcd_irq_chip_enable(struct irq_data *data)
+{
+}
+
+static struct irq_chip wcd_irq_chip = {
+ .name = NULL,
+ .irq_disable = wcd_irq_chip_disable,
+ .irq_enable = wcd_irq_chip_enable,
+};
+
+static struct lock_class_key wcd_irq_lock_class;
+
+static int wcd_irq_chip_map(struct irq_domain *irqd, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(virq, &wcd_irq_chip, handle_simple_irq);
+ irq_set_lockdep_class(virq, &wcd_irq_lock_class);
+ irq_set_nested_thread(virq, 1);
+ irq_set_noprobe(virq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops wcd_domain_ops = {
+ .map = wcd_irq_chip_map,
+};
+
+/**
+ * wcd_irq_init: Initializes IRQ module
+ * @irq_info: pointer to IRQ info structure
+ *
+ * Returns 0 on success or error on failure
+ */
+int wcd_irq_init(struct wcd_irq_info *irq_info, struct irq_domain **virq)
+{
+ int ret = 0;
+
+ if (!irq_info) {
+ pr_err("%s: Null IRQ handle\n", __func__);
+ return -EINVAL;
+ }
+
+ wcd_irq_chip.name = irq_info->codec_name;
+
+ *virq = irq_domain_add_linear(NULL, 1, &wcd_domain_ops, NULL);
+ if (!(*virq)) {
+ pr_err("%s: Failed to add IRQ domain\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = devm_regmap_add_irq_chip(irq_info->dev, irq_info->regmap,
+ irq_create_mapping(*virq, 0),
+ IRQF_ONESHOT, 0, irq_info->wcd_regmap_irq_chip,
+ &irq_info->irq_chip);
+ if (ret)
+ pr_err("%s: Failed to add IRQs: %d\n",
+ __func__, ret);
+
+ return ret;
+}
+EXPORT_SYMBOL(wcd_irq_init);
+
+/**
+ * wcd_irq_exit: Uninitialize regmap IRQ and free IRQ resources
+ * @irq_info: pointer to IRQ info structure
+ *
+ * Returns 0 on success or error on failure
+ */
+int wcd_irq_exit(struct wcd_irq_info *irq_info, struct irq_domain *virq)
+{
+ if (!irq_info) {
+ pr_err("%s: Null pointer handle\n", __func__);
+ return -EINVAL;
+ }
+
+ regmap_del_irq_chip(irq_find_mapping(virq, 0), irq_info->irq_chip);
+
+ return 0;
+}
+EXPORT_SYMBOL(wcd_irq_exit);
diff --git a/asoc/codecs/wcd9xxx-irq.c b/asoc/codecs/wcd9xxx-irq.c
index b192e99..ad15470 100644
--- a/asoc/codecs/wcd9xxx-irq.c
+++ b/asoc/codecs/wcd9xxx-irq.c
@@ -295,6 +295,7 @@
static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 1);
struct wcd9xxx_core_resource *wcd9xxx_res = data;
int num_irq_regs = wcd9xxx_res->num_irq_regs;
+ struct wcd9xxx *wcd9xxx;
u8 status[4], status1[4] = {0}, unmask_status[4] = {0};
if (unlikely(wcd9xxx_lock_sleep(wcd9xxx_res) == false)) {
@@ -309,6 +310,23 @@
goto err_disable_irq;
}
+ wcd9xxx = (struct wcd9xxx *)wcd9xxx_res->parent;
+ if (!wcd9xxx) {
+ dev_err(wcd9xxx_res->dev,
+ "%s: Codec core not supplied\n", __func__);
+ goto err_disable_irq;
+ }
+
+ if (!wcd9xxx->dev_up) {
+ dev_info_ratelimited(wcd9xxx_res->dev, "wcd9xxx dev not up\n");
+ /*
+ * sleep to not block the core when device is
+ * not up (slimbus will not be available) to
+ * process interrupts.
+ */
+ msleep(10);
+ }
+
memset(status, 0, sizeof(status));
ret = regmap_bulk_read(wcd9xxx_res->wcd_core_regmap,
wcd9xxx_res->intr_reg[WCD9XXX_INTR_STATUS_BASE],
diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c
index 7f305cf..bc57787 100644
--- a/asoc/msm-dai-q6-v2.c
+++ b/asoc/msm-dai-q6-v2.c
@@ -206,7 +206,6 @@
u16 afe_in_bitformat;
struct afe_enc_config enc_config;
struct afe_dec_config dec_config;
- u32 island_enable;
union afe_port_config port_config;
u16 vi_feed_mono;
};
@@ -1138,36 +1137,32 @@
static int msm_dai_q6_island_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
int value = ucontrol->value.integer.value[0];
- u16 port_id = ((struct soc_enum *) kcontrol->private_value)->reg;
+ u16 port_id = (u16)kcontrol->private_value;
- dai_data->island_enable = value;
pr_debug("%s: island mode = %d\n", __func__, value);
- afe_set_island_mode_cfg(port_id, dai_data->island_enable);
+ afe_set_island_mode_cfg(port_id, value);
return 0;
}
static int msm_dai_q6_island_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+ int value;
+ u16 port_id = (u16)kcontrol->private_value;
- ucontrol->value.integer.value[0] = dai_data->island_enable;
+ afe_get_island_mode_cfg(port_id, &value);
+ ucontrol->value.integer.value[0] = value;
return 0;
}
-static struct snd_kcontrol_new island_config_controls[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "?",
- .info = snd_ctl_boolean_mono_info,
- .get = msm_dai_q6_island_mode_get,
- .put = msm_dai_q6_island_mode_put,
- .private_value = SOC_SINGLE_VALUE(0, 0, 1, 0, 0)
- },
-};
+static void island_mx_ctl_private_free(struct snd_kcontrol *kcontrol)
+{
+ struct snd_kcontrol_new *knew = snd_kcontrol_chip(kcontrol);
+
+ kfree(knew);
+}
static int msm_dai_q6_add_island_mx_ctls(struct snd_card *card,
const char *dai_name,
@@ -1177,6 +1172,8 @@
char *mixer_str = NULL;
int dai_str_len = 0, ctl_len = 0;
int rc = 0;
+ struct snd_kcontrol_new *knew = NULL;
+ struct snd_kcontrol *kctl = NULL;
dai_str_len = strlen(dai_name) + 1;
@@ -1187,12 +1184,26 @@
return -ENOMEM;
snprintf(mixer_str, ctl_len, "%s %s", dai_name, mx_ctl_name);
- island_config_controls[0].name = mixer_str;
- ((struct soc_enum *) island_config_controls[0].private_value)->reg
- = dai_id;
- rc = snd_ctl_add(card,
- snd_ctl_new1(&island_config_controls[0],
- dai_data));
+
+ knew = kzalloc(sizeof(struct snd_kcontrol_new), GFP_KERNEL);
+ if (!knew) {
+ kfree(mixer_str);
+ return -ENOMEM;
+ }
+ knew->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ knew->info = snd_ctl_boolean_mono_info;
+ knew->get = msm_dai_q6_island_mode_get;
+ knew->put = msm_dai_q6_island_mode_put;
+ knew->name = mixer_str;
+ knew->private_value = dai_id;
+ kctl = snd_ctl_new1(knew, knew);
+ if (!kctl) {
+ kfree(knew);
+ kfree(mixer_str);
+ return -ENOMEM;
+ }
+ kctl->private_free = island_mx_ctl_private_free;
+ rc = snd_ctl_add(card, kctl);
if (rc < 0)
pr_err("%s: err add config ctl, DAI = %s\n",
__func__, dai_name);
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index 1d3e6b9..31f86d6 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -3321,6 +3321,25 @@
EXPORT_SYMBOL(afe_set_vad_cfg);
/**
+ * afe_get_island_mode_cfg -
+ * get island mode configuration
+ *
+ * @port_id: AFE port id number
+ * @enable_flag: Enable or Disable
+ *
+ */
+void afe_get_island_mode_cfg(u16 port_id, u32 *enable_flag)
+{
+ uint16_t port_index;
+
+ if (enable_flag) {
+ port_index = afe_get_port_index(port_id);
+ *enable_flag = this_afe.island_mode[port_index];
+ }
+}
+EXPORT_SYMBOL(afe_get_island_mode_cfg);
+
+/**
* afe_set_island_mode_cfg -
* set island mode configuration
*
@@ -6551,6 +6570,13 @@
case AFE_PORT_ID_INT4_MI2S_TX:
case AFE_PORT_ID_INT5_MI2S_TX:
case AFE_PORT_ID_INT6_MI2S_TX:
+ case AFE_PORT_ID_WSA_CODEC_DMA_RX_0:
+ case AFE_PORT_ID_WSA_CODEC_DMA_TX_0:
+ case AFE_PORT_ID_WSA_CODEC_DMA_RX_1:
+ case AFE_PORT_ID_WSA_CODEC_DMA_TX_1:
+ case AFE_PORT_ID_WSA_CODEC_DMA_TX_2:
+ case AFE_PORT_ID_VA_CODEC_DMA_TX_0:
+ case AFE_PORT_ID_VA_CODEC_DMA_TX_1:
{
ret = 0;
break;
diff --git a/include/asoc/wcd-irq.h b/include/asoc/wcd-irq.h
new file mode 100644
index 0000000..63502f8
--- /dev/null
+++ b/include/asoc/wcd-irq.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __WCD_IRQ_H_
+#define __WCD_IRQ_H_
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+
+struct wcd_irq_info {
+ struct regmap_irq_chip *wcd_regmap_irq_chip;
+ char *codec_name;
+ struct regmap *regmap;
+ struct regmap_irq_chip_data *irq_chip;
+ struct device *dev;
+};
+
+#if IS_ENABLED(CONFIG_WCD9XXX_CODEC_CORE)
+int wcd_irq_init(struct wcd_irq_info *irq_info, struct irq_domain **virq);
+int wcd_irq_exit(struct wcd_irq_info *irq_info, struct irq_domain *virq);
+int wcd_request_irq(struct wcd_irq_info *irq_info, int irq, const char *name,
+ irq_handler_t handler, void *data);
+void wcd_free_irq(struct wcd_irq_info *irq_info, int irq, void *data);
+void wcd_enable_irq(struct wcd_irq_info *irq_info, int irq);
+void wcd_disable_irq(struct wcd_irq_info *irq_info, int irq);
+#else
+static inline int wcd_irq_init(struct wcd_irq_info *irq_info,
+ struct irq_domain **virq)
+{
+ return 0;
+};
+static inline int wcd_irq_exit(struct wcd_irq_info *irq_info,
+ struct irq_domain *virq)
+{
+ return 0;
+};
+static inline int wcd_request_irq(struct wcd_irq_info *irq,
+ int irq, const char *name,
+ irq_handler_t handler, void *data)
+{
+ return 0;
+};
+static inline void wcd_free_irq(struct wcd_irq_info *irq, int irq, void *data);
+{
+};
+static inline void wcd_enable_irq(struct wcd_irq_info *irq, int irq);
+{
+};
+static inline void wcd_disable_irq(struct wcd_irq_info *irq, int irq);
+{
+};
+#endif
+#endif /* __WCD_IRQ_H_ */
diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h
index a0074b4..ef1603f 100644
--- a/include/dsp/q6afe-v2.h
+++ b/include/dsp/q6afe-v2.h
@@ -360,6 +360,7 @@
void afe_set_vad_cfg(u32 vad_enable, u32 preroll_config,
u32 port_id);
void afe_set_island_mode_cfg(u16 port_id, u32 enable_flag);
+void afe_get_island_mode_cfg(u16 port_id, u32 *enable_flag);
int afe_port_start(u16 port_id, union afe_port_config *afe_config,
u32 rate);
int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,