qcom,smmu-enabled;
};
+ qcom,hab {
+ compatible = "qcom,hab";
+ vmid = <2>;
+
+ mmidgrp100: mmidgrp100 {
+ grp-start-id = <100>;
+ role = "fe";
+ remote-vmids = <0>;
+ };
+
+ mmidgrp200: mmidgrp200 {
+ grp-start-id = <200>;
+ role = "fe";
+ remote-vmids = <0>;
+ };
+
+ mmidgrp300: mmidgrp300 {
+ grp-start-id = <300>;
+ role = "fe";
+ remote-vmids = <0>;
+ };
+
+ mmidgrp400: mmidgrp400 {
+ grp-start-id = <400>;
+ role = "fe";
+ remote-vmids = <0>;
+ };
+
+ mmidgrp500: mmidgrp500 {
+ grp-start-id = <500>;
+ role = "fe";
+ remote-vmids = <0>;
+ };
+
+ mmidgrp600: mmidgrp600 {
+ grp-start-id = <600>;
+ role = "fe";
+ remote-vmids = <0>;
+ };
+
+ mmidgrp700: mmidgrp700 {
+ grp-start-id = <700>;
+ role = "fe";
+ remote-vmids = <0>;
+ };
+
+ mmidgrp800: mmidgrp800 {
+ grp-start-id = <800>;
+ role = "fe";
+ remote-vmids = <0>;
+ };
+
+ mmidgrp900: mmidgrp900 {
+ grp-start-id = <900>;
+ role = "fe";
+ remote-vmids = <0>;
+ };
+
+ mmidgrp1000: mmidgrp1000 {
+ grp-start-id = <1000>;
+ role = "fe";
+ remote-vmids = <0>;
+ };
+ };
+
qcom,cnss {
compatible = "qcom,cnss";
wlan-bootstrap-gpio = <&tlmm 46 0>;
CONFIG_USB_STORAGE=y
CONFIG_USB_DWC3=y
CONFIG_USB_ISP1760=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_USB_QTI_KS_BRIDGE=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_MSM_SSPHY_QMP=y
CONFIG_USB_STORAGE=y
CONFIG_USB_DWC3=y
CONFIG_USB_ISP1760=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_USB_QTI_KS_BRIDGE=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_MSM_SSPHY_QMP=y
if (sde_kms->splash_info.handoff)
sde_splash_clean_up_exit_lk(kms);
-
- sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
+ else
+ sde_power_resource_enable(&priv->phandle,
+ sde_kms->core_client, true);
}
static void sde_kms_commit(struct msm_kms *kms,
#define ONE_MHZ_TO_HZ 1000000
#define I2C_BLOCK_WRITE_SIZE 1024
+#define ADV_REG_STABLE_DELAY 70 /* ms*/
enum adv7481_gpio_t {
struct adv7481_state *state = dev;
schedule_delayed_work(&state->irq_delayed_work,
- msecs_to_jiffies(0));
+ msecs_to_jiffies(ADV_REG_STABLE_DELAY));
return IRQ_HANDLED;
}
return rc;
}
- if (new_early_cam_dev->pdev->dev.of_node)
- of_property_read_u32((&new_early_cam_dev->pdev->dev)->of_node,
- "cell-index", &new_early_cam_dev->pdev->id);
-
- rc = msm_camera_get_clk_info_and_rates(new_early_cam_dev->pdev,
- &new_early_cam_dev->early_cam_clk_info,
- &new_early_cam_dev->early_cam_clk,
- &new_early_cam_dev->early_cam_clk_rates,
- &new_early_cam_dev->num_clk_cases,
- &new_early_cam_dev->num_clk);
- if (rc < 0) {
- pr_err("%s: msm_early_cam_get_clk_info() failed", __func__);
- return -EFAULT;
- }
-
- rc = msm_camera_get_dt_vreg_data(
- new_early_cam_dev->pdev->dev.of_node,
- &(new_early_cam_dev->early_cam_vreg),
- &(new_early_cam_dev->regulator_count));
- if (rc < 0) {
- pr_err("%s: msm_camera_get_dt_vreg_data fail\n", __func__);
- rc = -EFAULT;
- return rc;
- }
-
- if ((new_early_cam_dev->regulator_count < 0) ||
- (new_early_cam_dev->regulator_count > MAX_REGULATOR)) {
- pr_err("%s: invalid reg count = %d, max is %d\n", __func__,
- new_early_cam_dev->regulator_count, MAX_REGULATOR);
- rc = -EFAULT;
- return rc;
- }
-
- rc = msm_camera_config_vreg(&new_early_cam_dev->pdev->dev,
- new_early_cam_dev->early_cam_vreg,
- new_early_cam_dev->regulator_count,
- NULL,
- 0,
- &new_early_cam_dev->early_cam_reg_ptr[0], 1);
- if (rc < 0)
- pr_err("%s:%d early_cam config_vreg failed\n", __func__,
- __LINE__);
-
- rc = msm_camera_enable_vreg(&new_early_cam_dev->pdev->dev,
- new_early_cam_dev->early_cam_vreg,
- new_early_cam_dev->regulator_count,
- NULL,
- 0,
- &new_early_cam_dev->early_cam_reg_ptr[0], 1);
- if (rc < 0)
- pr_err("%s:%d early_cam enable_vreg failed\n", __func__,
- __LINE__);
-
rc = msm_camera_clk_enable(&new_early_cam_dev->pdev->dev,
new_early_cam_dev->early_cam_clk_info,
new_early_cam_dev->early_cam_clk,
of_property_read_u32((&pdev->dev)->of_node,
"cell-index", &pdev->id);
- rc = msm_camera_get_clk_info_and_rates(pdev,
- &new_early_cam_dev->early_cam_clk_info,
- &new_early_cam_dev->early_cam_clk,
- &new_early_cam_dev->early_cam_clk_rates,
- &new_early_cam_dev->num_clk_cases,
- &new_early_cam_dev->num_clk);
+ rc = msm_camera_get_clk_info(pdev,
+ &new_early_cam_dev->early_cam_clk_info,
+ &new_early_cam_dev->early_cam_clk,
+ &new_early_cam_dev->num_clk);
if (rc < 0) {
pr_err("%s: msm_early_cam_get_clk_info() failed", __func__);
kfree(new_early_cam_dev);
#define DRIVER_MODE_RAW_FRAMES 0
#define DRIVER_MODE_PROPERTIES 1
#define DRIVER_MODE_AMB 2
-#define QUERY_FIRMWARE_TIMEOUT_MS 20
+#define QUERY_FIRMWARE_TIMEOUT_MS 100
struct qti_can {
struct net_device **netdev;
config CNSS2
tristate "CNSS2 Platform Driver for Wi-Fi Module"
- depends on !CNSS && PCI_MSM
+ depends on !CNSS && (PCI_MSM || PCI_HOST_GENERIC)
select CNSS_UTILS
---help---
This module adds the support for Connectivity Subsystem (CNSS) used
for PCIe based Wi-Fi devices with QCA6174/QCA6290 chipsets.
+ This module in metal case depends on PCI_MSM, while in GVM case
+ depends on PCI_HOST_GENERIC.
This driver also adds support to integrate WLAN module to subsystem
restart framework.
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-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
u32 flags, void *data);
int cnss_get_vreg(struct cnss_plat_data *plat_priv);
int cnss_get_pinctrl(struct cnss_plat_data *plat_priv);
+
+#ifndef CONFIG_MSM_GVM_QUIN
int cnss_power_on_device(struct cnss_plat_data *plat_priv);
void cnss_power_off_device(struct cnss_plat_data *plat_priv);
+#else /* CONFIG_MSM_GVM_QUIN */
+static inline int cnss_power_on_device(struct cnss_plat_data *plat_priv)
+{
+ return 0;
+}
+
+static inline void cnss_power_off_device(struct cnss_plat_data *plat_priv)
+{
+}
+#endif /* CONFIG_MSM_GVM_QUIN */
+
int cnss_register_subsys(struct cnss_plat_data *plat_priv);
void cnss_unregister_subsys(struct cnss_plat_data *plat_priv);
int cnss_register_ramdump(struct cnss_plat_data *plat_priv);
#define MAX_M3_FILE_NAME_LENGTH 13
#define DEFAULT_M3_FILE_NAME "m3.bin"
+#ifdef CONFIG_PCI_MSM
static DEFINE_SPINLOCK(pci_link_down_lock);
+#endif
static unsigned int pci_link_down_panic;
module_param(pci_link_down_panic, uint, 0600);
return 0;
}
+#ifdef CONFIG_PCI_MSM
static int cnss_set_pci_link(struct cnss_pci_data *pci_priv, bool link_up)
{
int ret = 0;
}
EXPORT_SYMBOL(cnss_pci_link_down);
+#else /* CONFIG_PCI_MSM */
+static int cnss_set_pci_link(struct cnss_pci_data *pci_priv, bool link_up)
+{
+ return 0;
+}
+#endif /* CONFIG_PCI_MSM */
+
static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv)
{
int ret = 0;
pci_priv->smmu_mapping = NULL;
}
+#ifdef CONFIG_PCI_MSM
static void cnss_pci_event_cb(struct msm_pcie_notify *notify)
{
unsigned long flags;
}
EXPORT_SYMBOL(cnss_wlan_pm_control);
+#else /* CONFIG_PCI_MSM */
+static int cnss_reg_pci_event(struct cnss_pci_data *pci_priv)
+{
+ return 0;
+}
+
+static void cnss_dereg_pci_event(struct cnss_pci_data *pci_priv)
+{
+}
+#endif /* CONFIG_PCI_MSM */
+
int cnss_auto_suspend(struct device *dev)
{
int ret = 0;
}
EXPORT_SYMBOL(cnss_get_msi_address);
+#ifdef CONFIG_PCI_MSM
+static inline int cnss_pci_set_dma_mask(struct pci_dev *pci_dev)
+{
+ int ret;
+
+ ret = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(PCI_DMA_MASK));
+ if (ret) {
+ cnss_pr_err("PCI DMA mask: %d, err: %d\n", PCI_DMA_MASK, ret);
+ return ret;
+ }
+
+ ret = pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(PCI_DMA_MASK));
+ if (ret)
+ cnss_pr_err("PCI consistent DMA mask: %d, err: %d\n",
+ PCI_DMA_MASK, ret);
+
+ return ret;
+}
+#else /* CONFIG_PCI_MSM */
+static inline int cnss_pci_set_dma_mask(struct pci_dev *pci_dev)
+{
+ return 0;
+}
+#endif /* CONFIG_PCI_MSM */
+
static int cnss_pci_enable_bus(struct cnss_pci_data *pci_priv)
{
int ret = 0;
goto disable_device;
}
- ret = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(PCI_DMA_MASK));
- if (ret) {
- cnss_pr_err("Failed to set PCI DMA mask (%d), err = %d\n",
- ret, PCI_DMA_MASK);
- goto release_region;
- }
-
- ret = pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(PCI_DMA_MASK));
- if (ret) {
- cnss_pr_err("Failed to set PCI consistent DMA mask (%d), err = %d\n",
- ret, PCI_DMA_MASK);
+ ret = cnss_pci_set_dma_mask(pci_dev);
+ if (ret)
goto release_region;
- }
pci_set_master(pci_dev);
};
MODULE_DEVICE_TABLE(pci, cnss_pci_id_table);
+#ifdef CONFIG_PCI_MSM
static const struct dev_pm_ops cnss_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(cnss_pci_suspend, cnss_pci_resume)
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(cnss_pci_suspend_noirq,
SET_RUNTIME_PM_OPS(cnss_pci_runtime_suspend, cnss_pci_runtime_resume,
cnss_pci_runtime_idle)
};
+#endif
struct pci_driver cnss_pci_driver = {
.name = "cnss_pci",
.id_table = cnss_pci_id_table,
.probe = cnss_pci_probe,
.remove = cnss_pci_remove,
+#ifdef CONFIG_PCI_MSM
.driver = {
.pm = &cnss_pm_ops,
},
+#endif
};
-int cnss_pci_init(struct cnss_plat_data *plat_priv)
+#ifdef CONFIG_PCI_MSM
+static inline int cnss_msm_pcie_enumerate(struct cnss_plat_data *plat_priv)
{
- int ret = 0;
+ int ret;
struct device *dev = &plat_priv->plat_dev->dev;
u32 rc_num;
goto out;
}
+ return 0;
+out:
+ return ret;
+}
+#else /* CONFIG_PCI_MSM */
+static inline int cnss_msm_pcie_enumerate(struct cnss_plat_data *plat_priv)
+{
+ return 0;
+}
+#endif /* CONFIG_PCI_MSM */
+
+int cnss_pci_init(struct cnss_plat_data *plat_priv)
+{
+ int ret;
+
+ ret = cnss_msm_pcie_enumerate(plat_priv);
+ if (ret)
+ goto out;
+
ret = pci_register_driver(&cnss_pci_driver);
if (ret) {
cnss_pr_err("Failed to register to PCI framework, err = %d\n",
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-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
return atomic_read(&pci_priv->auto_suspended);
}
+#ifdef CONFIG_PCI_MSM
int cnss_suspend_pci_link(struct cnss_pci_data *pci_priv);
int cnss_resume_pci_link(struct cnss_pci_data *pci_priv);
+#else /* CONFIG_PCI_MSM */
+static inline int cnss_suspend_pci_link(struct cnss_pci_data *pci_priv)
+{
+ return 0;
+}
+
+static inline int cnss_resume_pci_link(struct cnss_pci_data *pci_priv)
+{
+ return 0;
+}
+#endif /* CONFIG_PCI_MSM */
+
int cnss_pci_init(struct cnss_plat_data *plat_priv);
void cnss_pci_deinit(struct cnss_plat_data *plat_priv);
int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv);
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-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
return ret;
}
+#ifndef CONFIG_MSM_GVM_QUIN
static int cnss_vreg_on(struct cnss_plat_data *plat_priv)
{
int ret = 0;
return ret;
}
+#endif /* CONFIG_MSM_GVM_QUIN */
int cnss_get_pinctrl(struct cnss_plat_data *plat_priv)
{
return ret;
}
+#ifndef CONFIG_MSM_GVM_QUIN
static int cnss_select_pinctrl_state(struct cnss_plat_data *plat_priv,
bool state)
{
cnss_select_pinctrl_state(plat_priv, false);
cnss_vreg_off(plat_priv);
}
+#endif /* CONFIG_MSM_GVM_QUIN */
void cnss_set_pin_connect_status(struct cnss_plat_data *plat_priv)
{
uint32_t write_index = einfo->tx_ch_desc->write_index;
len = fifo_write_body(einfo, data, len, &write_index);
+
+ /* All data writes need to be flushed to memory before the write index
+ * is updated. This protects against a race condition where the remote
+ * reads stale data because the write index was written before the data.
+ */
+ wmb();
einfo->tx_ch_desc->write_index = write_index;
send_irq(einfo);
len1 = fifo_write_body(einfo, data1, len1, &write_index);
len2 = fifo_write_body(einfo, data2, len2, &write_index);
len3 = fifo_write_body(einfo, data3, len3, &write_index);
+
+ /* All data writes need to be flushed to memory before the write index
+ * is updated. This protects against a race condition where the remote
+ * reads stale data because the write index was written before the data.
+ */
+ wmb();
einfo->tx_ch_desc->write_index = write_index;
send_irq(einfo);
/*
- * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, 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
#define TEST_SINGLE_STEP_GET_DEV_DESC 0x0107
#define TEST_SINGLE_STEP_SET_FEATURE 0x0108
-static int ehset_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
+static u8 numPorts;
+
+static int ehset_get_port_num(struct device *dev, const char *buf,
+ unsigned long *val)
+{
+ int ret;
+
+ ret = kstrtoul(buf, 10, val);
+ if (ret < 0) {
+ dev_err(dev, "couldn't parse string %d\n", ret);
+ return ret;
+ }
+
+ if (!*val || *val > numPorts) {
+ dev_err(dev, "Invalid port num entered\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ehset_clear_port_feature(struct usb_device *udev, int feature,
+ int port1)
+{
+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1,
+ NULL, 0, 1000);
+}
+
+static int ehset_set_port_feature(struct usb_device *udev, int feature,
+ int port1, int timeout)
+{
+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port1,
+ NULL, 0, timeout);
+}
+
+static int ehset_set_testmode(struct device *dev, struct usb_device *child_udev,
+ struct usb_device *hub_udev, int test_id, int port)
{
- int ret = -EINVAL;
- struct usb_device *dev = interface_to_usbdev(intf);
- struct usb_device *hub_udev = dev->parent;
struct usb_device_descriptor *buf;
- u8 portnum = dev->portnum;
- u16 test_pid = le16_to_cpu(dev->descriptor.idProduct);
+ int ret = -EINVAL;
- switch (test_pid) {
+ switch (test_id) {
case TEST_SE0_NAK_PID:
- ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
- USB_REQ_SET_FEATURE, USB_RT_PORT,
- USB_PORT_FEAT_TEST,
- (TEST_SE0_NAK << 8) | portnum,
- NULL, 0, 1000);
+ ret = ehset_set_port_feature(hub_udev, USB_PORT_FEAT_TEST,
+ (TEST_SE0_NAK << 8) | port, 1000);
break;
case TEST_J_PID:
- ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
- USB_REQ_SET_FEATURE, USB_RT_PORT,
- USB_PORT_FEAT_TEST,
- (TEST_J << 8) | portnum,
- NULL, 0, 1000);
+ ret = ehset_set_port_feature(hub_udev, USB_PORT_FEAT_TEST,
+ (TEST_J << 8) | port, 1000);
break;
case TEST_K_PID:
- ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
- USB_REQ_SET_FEATURE, USB_RT_PORT,
- USB_PORT_FEAT_TEST,
- (TEST_K << 8) | portnum,
- NULL, 0, 1000);
+ ret = ehset_set_port_feature(hub_udev, USB_PORT_FEAT_TEST,
+ (TEST_K << 8) | port, 1000);
break;
case TEST_PACKET_PID:
- ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
- USB_REQ_SET_FEATURE, USB_RT_PORT,
- USB_PORT_FEAT_TEST,
- (TEST_PACKET << 8) | portnum,
- NULL, 0, 1000);
+ ret = ehset_set_port_feature(hub_udev, USB_PORT_FEAT_TEST,
+ (TEST_PACKET << 8) | port, 1000);
break;
case TEST_HS_HOST_PORT_SUSPEND_RESUME:
/* Test: wait for 15secs -> suspend -> 15secs delay -> resume */
msleep(15 * 1000);
- ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
- USB_REQ_SET_FEATURE, USB_RT_PORT,
- USB_PORT_FEAT_SUSPEND, portnum,
- NULL, 0, 1000);
- if (ret < 0)
+ ret = ehset_set_port_feature(hub_udev, USB_PORT_FEAT_SUSPEND,
+ port, 1000);
+ if (ret)
break;
msleep(15 * 1000);
- ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RT_PORT,
- USB_PORT_FEAT_SUSPEND, portnum,
- NULL, 0, 1000);
+ ret = ehset_clear_port_feature(hub_udev, USB_PORT_FEAT_SUSPEND,
+ port);
break;
case TEST_SINGLE_STEP_GET_DEV_DESC:
/* Test: wait for 15secs -> GetDescriptor request */
msleep(15 * 1000);
buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
+ if (!buf) {
+ ret = -ENOMEM;
+ break;
+ }
- ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ ret = usb_control_msg(child_udev,
+ usb_rcvctrlpipe(child_udev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
USB_DT_DEVICE << 8, 0,
buf, USB_DT_DEVICE_SIZE,
* SetPortFeature handling can only be done inside the HCD's
* hub_control callback function.
*/
- if (hub_udev != dev->bus->root_hub) {
- dev_err(&intf->dev, "SINGLE_STEP_SET_FEATURE test only supported on root hub\n");
+ if (hub_udev != child_udev->bus->root_hub) {
+ dev_err(dev, "SINGLE_STEP_SET_FEATURE test only supported on root hub\n");
break;
}
- ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0),
- USB_REQ_SET_FEATURE, USB_RT_PORT,
- USB_PORT_FEAT_TEST,
- (6 << 8) | portnum,
- NULL, 0, 60 * 1000);
+ ret = ehset_set_port_feature(hub_udev, USB_PORT_FEAT_TEST,
+ (6 << 8) | port, 60 * 1000);
break;
default:
- dev_err(&intf->dev, "%s: unsupported PID: 0x%x\n",
- __func__, test_pid);
+ dev_err(dev, "%s: unsupported test ID: 0x%x\n",
+ __func__, test_id);
+ }
+
+ return ret;
+}
+
+static ssize_t test_se0_nak_portnum_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_device *udev = interface_to_usbdev(intf);
+ unsigned long portnum;
+ int ret;
+
+ ret = ehset_get_port_num(dev, buf, &portnum);
+ if (ret)
+ return ret;
+
+ usb_lock_device(udev);
+ ret = ehset_set_testmode(dev, NULL, udev, TEST_SE0_NAK_PID, portnum);
+ usb_unlock_device(udev);
+ if (ret) {
+ dev_err(dev, "Error %d while SE0_NAK test\n", ret);
+ return ret;
}
+ return count;
+}
+static DEVICE_ATTR_WO(test_se0_nak_portnum);
+
+static ssize_t test_j_portnum_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_device *udev = interface_to_usbdev(intf);
+ unsigned long portnum;
+ int ret;
+
+ ret = ehset_get_port_num(dev, buf, &portnum);
+ if (ret)
+ return ret;
+
+ usb_lock_device(udev);
+ ret = ehset_set_testmode(dev, NULL, udev, TEST_J_PID, portnum);
+ usb_unlock_device(udev);
+ if (ret) {
+ dev_err(dev, "Error %d while J state test\n", ret);
+ return ret;
+ }
+
+ return count;
+}
+static DEVICE_ATTR_WO(test_j_portnum);
+
+static ssize_t test_k_portnum_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_device *udev = interface_to_usbdev(intf);
+ unsigned long portnum;
+ int ret;
+
+ ret = ehset_get_port_num(dev, buf, &portnum);
+ if (ret)
+ return ret;
+
+ usb_lock_device(udev);
+ ret = ehset_set_testmode(dev, NULL, udev, TEST_K_PID, portnum);
+ usb_unlock_device(udev);
+ if (ret) {
+ dev_err(dev, "Error %d while K state test\n", ret);
+ return ret;
+ }
+
+ return count;
+}
+static DEVICE_ATTR_WO(test_k_portnum);
+
+static ssize_t test_packet_portnum_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_device *udev = interface_to_usbdev(intf);
+ unsigned long portnum;
+ int ret;
+
+ ret = ehset_get_port_num(dev, buf, &portnum);
+ if (ret)
+ return ret;
+
+ usb_lock_device(udev);
+ ret = ehset_set_testmode(dev, NULL, udev, TEST_PACKET_PID, portnum);
+ usb_unlock_device(udev);
+ if (ret) {
+ dev_err(dev, "Error %d while sending test packets\n", ret);
+ return ret;
+ }
+
+ return count;
+}
+static DEVICE_ATTR_WO(test_packet_portnum);
+
+static ssize_t test_port_susp_resume_portnum_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_device *udev = interface_to_usbdev(intf);
+ unsigned long portnum;
+ int ret;
+
+ ret = ehset_get_port_num(dev, buf, &portnum);
+ if (ret)
+ return ret;
+
+ usb_lock_device(udev);
+ ret = ehset_set_testmode(dev, NULL, udev,
+ TEST_HS_HOST_PORT_SUSPEND_RESUME, portnum);
+ usb_unlock_device(udev);
+ if (ret) {
+ dev_err(dev, "Error %d while port suspend resume test\n", ret);
+ return ret;
+ }
+
+ return count;
+}
+static DEVICE_ATTR_WO(test_port_susp_resume_portnum);
+
+static struct attribute *ehset_attributes[] = {
+ &dev_attr_test_se0_nak_portnum.attr,
+ &dev_attr_test_j_portnum.attr,
+ &dev_attr_test_k_portnum.attr,
+ &dev_attr_test_packet_portnum.attr,
+ &dev_attr_test_port_susp_resume_portnum.attr,
+ NULL
+};
+
+static const struct attribute_group ehset_attr_group = {
+ .attrs = ehset_attributes,
+};
+
+static int ehset_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ int ret = -EINVAL;
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct usb_device *hub_udev = dev->parent;
+ u8 portnum = dev->portnum;
+ u16 test_pid = le16_to_cpu(dev->descriptor.idProduct);
+
+ /*
+ * If an external hub does not support the EHSET test fixture, then user
+ * can forcefully unbind the external hub from the hub driver (to which
+ * an external hub gets bound by default) and bind it to this driver, so
+ * as to send test signals on any downstream port of the hub.
+ */
+ if (dev->descriptor.bDeviceClass == USB_CLASS_HUB) {
+ struct usb_hub_descriptor *descriptor;
+
+ descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL);
+ if (!descriptor)
+ return -ENOMEM;
+
+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
+ USB_DT_HUB << 8, 0, descriptor,
+ USB_DT_HUB_NONVAR_SIZE, USB_CTRL_GET_TIMEOUT);
+ if (ret < 0) {
+ dev_err(&intf->dev, "%s: Failed to get hub desc %d\n",
+ __func__, ret);
+ kfree(descriptor);
+ return ret;
+ }
+
+ numPorts = descriptor->bNbrPorts;
+ ret = sysfs_create_group(&intf->dev.kobj, &ehset_attr_group);
+ if (ret < 0)
+ dev_err(&intf->dev, "%s: Failed to create sysfs nodes %d\n",
+ __func__, ret);
+
+ kfree(descriptor);
+ return ret;
+ }
+
+ ret = ehset_set_testmode(&intf->dev, dev, hub_udev, test_pid, portnum);
+
return (ret < 0) ? ret : 0;
}
static void ehset_disconnect(struct usb_interface *intf)
{
+ struct usb_device *dev = interface_to_usbdev(intf);
+
+ numPorts = 0;
+ if (dev->descriptor.bDeviceClass == USB_CLASS_HUB)
+ sysfs_remove_group(&intf->dev.kobj, &ehset_attr_group);
}
static const struct usb_device_id ehset_id_table[] = {
struct msm_ext_disp_audio_edid_blk *blk);
static int hdmi_tx_get_cable_status(struct platform_device *pdev, u32 vote);
static int hdmi_tx_update_ppm(struct hdmi_tx_ctrl *hdmi_ctrl, s32 ppm);
+static int hdmi_tx_enable_pll_update(struct hdmi_tx_ctrl *hdmi_ctrl,
+ int enable);
static struct mdss_hw hdmi_tx_hw = {
.hw_ndx = MDSS_HW_HDMI,
return ret;
}
+static ssize_t hdmi_tx_sysfs_rda_pll_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+ struct hdmi_tx_ctrl *hdmi_ctrl =
+ hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+ if (!hdmi_ctrl) {
+ pr_err("invalid input\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&hdmi_ctrl->tx_lock);
+ ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ hdmi_ctrl->pll_update_enable);
+ pr_debug("HDMI PLL update: %s\n",
+ hdmi_ctrl->pll_update_enable ? "enable" : "disable");
+
+ mutex_unlock(&hdmi_ctrl->tx_lock);
+
+ return ret;
+} /* hdmi_tx_sysfs_rda_pll_enable */
+
+
+static ssize_t hdmi_tx_sysfs_wta_pll_enable(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int enable, rc;
+ struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+
+ hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&hdmi_ctrl->tx_lock);
+
+ rc = kstrtoint(buf, 10, &enable);
+ if (rc) {
+ DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc);
+ goto end;
+ }
+
+ hdmi_tx_enable_pll_update(hdmi_ctrl, enable);
+
+ rc = strnlen(buf, PAGE_SIZE);
+end:
+ mutex_unlock(&hdmi_ctrl->tx_lock);
+ return rc;
+} /* hdmi_tx_sysfs_wta_pll_enable */
+
static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL);
static DEVICE_ATTR(hot_plug, S_IWUSR, NULL, hdmi_tx_sysfs_wta_hot_plug);
static DEVICE_ATTR(sim_mode, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_sim_mode,
static DEVICE_ATTR(hdr_stream, S_IWUSR, NULL, hdmi_tx_sysfs_wta_hdr_stream);
static DEVICE_ATTR(hdmi_ppm, S_IRUGO | S_IWUSR, NULL,
hdmi_tx_sysfs_wta_hdmi_ppm);
+static DEVICE_ATTR(pll_enable, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_pll_enable,
+ hdmi_tx_sysfs_wta_pll_enable);
+
static struct attribute *hdmi_tx_fs_attrs[] = {
&dev_attr_connected.attr,
&dev_attr_5v.attr,
&dev_attr_hdr_stream.attr,
&dev_attr_hdmi_ppm.attr,
+ &dev_attr_pll_enable.attr,
NULL,
};
static struct attribute_group hdmi_tx_fs_attrs_group = {
rc = hdmi_tx_config_avmute(hdmi_ctrl, false);
}
- if (hdmi_ctrl->hdcp1_use_sw_keys && hdmi_ctrl->hdcp14_present)
- hdcp1_set_enc(true);
+ if (hdmi_ctrl->hdcp1_use_sw_keys && hdmi_ctrl->hdcp14_present) {
+ if (!hdmi_ctrl->hdcp22_present)
+ hdcp1_set_enc(true);
+ }
break;
case HDCP_STATE_AUTH_FAIL:
if (hdmi_ctrl->hdcp1_use_sw_keys && hdmi_ctrl->hdcp14_present) {
- if (hdmi_ctrl->auth_state)
+ if (hdmi_ctrl->auth_state && !hdmi_ctrl->hdcp22_present)
hdcp1_set_enc(false);
}
hdmi_ctrl->hpd_state = false;
hdmi_ctrl->hpd_initialized = false;
hdmi_ctrl->hpd_off_pending = false;
+ hdmi_ctrl->pll_update_enable = false;
init_completion(&hdmi_ctrl->hpd_int_done);
INIT_WORK(&hdmi_ctrl->hpd_int_work, hdmi_tx_hpd_int_work);
return -EINVAL;
}
+ if (!hdmi_ctrl->pll_update_enable) {
+ pr_err("PLL update feature not enabled\n");
+ return -EINVAL;
+ }
+
/* get current pclk */
cur_pclk = pinfo->clk_rate;
/* get desired pclk */
return rc;
}
+static int hdmi_tx_enable_pll_update(struct hdmi_tx_ctrl *hdmi_ctrl,
+ int enable)
+{
+ struct mdss_panel_info *pinfo = NULL;
+ int rc = 0;
+
+ if (!hdmi_ctrl) {
+ pr_err("invalid input\n");
+ return -EINVAL;
+ }
+
+ /* only available in case HDMI is up */
+ if (!hdmi_tx_is_panel_on(hdmi_ctrl)) {
+ pr_err("hdmi is not on\n");
+ return -EINVAL;
+ }
+
+ enable = !!enable;
+ if (hdmi_ctrl->pll_update_enable == enable) {
+ pr_warn("HDMI PLL update already %s\n",
+ hdmi_ctrl->pll_update_enable ? "enabled" : "disabled");
+ return -EINVAL;
+ }
+
+ pinfo = &hdmi_ctrl->panel_data.panel_info;
+
+ if (!enable && hdmi_ctrl->actual_clk_rate != pinfo->clk_rate) {
+ if (hdmi_ctrl->actual_clk_rate) {
+ /* reset pixel clock when disable */
+ pinfo->clk_rate = hdmi_ctrl->actual_clk_rate;
+ rc = hdmi_tx_update_pixel_clk(hdmi_ctrl);
+ }
+ }
+
+ hdmi_ctrl->actual_clk_rate = pinfo->clk_rate;
+ hdmi_ctrl->pll_update_enable = enable;
+
+ pr_debug("HDMI PLL update: %s\n",
+ hdmi_ctrl->pll_update_enable ? "enable" : "disable");
+
+ return rc;
+}
+
static int hdmi_tx_evt_handle_register(struct hdmi_tx_ctrl *hdmi_ctrl)
{
int rc = 0;
}
hdmi_ctrl->timing_gen_on = false;
+ hdmi_ctrl->pll_update_enable = false;
end:
return rc;
}
char disp_switch_name[MAX_SWITCH_NAME_SIZE];
+ u64 actual_clk_rate;
+ bool pll_update_enable;
+
/* pre/post is done in the context without tx_lock */
hdmi_tx_evt_handler pre_evt_handler[MDSS_EVENT_MAX - 1];
hdmi_tx_evt_handler evt_handler[MDSS_EVENT_MAX - 1];
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-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
extern int cnss_wlan_register_driver(struct cnss_wlan_driver *driver);
extern void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver);
extern void cnss_device_crashed(struct device *dev);
+#ifdef CONFIG_PCI_MSM
extern int cnss_pci_link_down(struct device *dev);
+extern int cnss_wlan_pm_control(struct device *dev, bool vote);
+#else /* CONFIG_PCI_MSM */
+static inline int cnss_pci_link_down(struct device *dev)
+{
+ return 0;
+}
+static inline int cnss_wlan_pm_control(struct device *dev, bool vote)
+{
+ return 0;
+}
+#endif /* CONFIG_PCI_MSM */
extern void cnss_schedule_recovery(struct device *dev,
enum cnss_recovery_reason reason);
extern int cnss_self_recovery(struct device *dev,
extern void cnss_remove_pm_qos(struct device *dev);
extern void cnss_lock_pm_sem(struct device *dev);
extern void cnss_release_pm_sem(struct device *dev);
-extern int cnss_wlan_pm_control(struct device *dev, bool vote);
extern int cnss_auto_suspend(struct device *dev);
extern int cnss_auto_resume(struct device *dev);
extern int cnss_get_user_msi_assignment(struct device *dev, char *user_name,
*/
} __packed;
+/* ADM device open endpoint payload the
+* #ADM_CMD_DEVICE_OPEN_V8 command.
+*/
+struct adm_device_endpoint_payload {
+ u16 dev_num_channel;
+ /* Number of channels the audio COPP sends to/receives from
+ * the endpoint.
+ * Supported values: 1 to 32.
+ * The value is ignored for the voice processor Tx block,
+ * where channel
+ * configuration is derived from the topology ID.
+ */
+
+ u16 bit_width;
+ /* Bit width (in bits) that the audio COPP sends to/receives
+ * from the
+ * endpoint. The value is ignored for the voice processing
+ * Tx block,
+ * where the PCM width is 16 bits.
+ */
+
+ u32 sample_rate;
+ /* Sampling rate at which the audio COPP/voice processor
+ * Tx block
+ * interfaces with the endpoint.
+ * Supported values for voice processor Tx: 8000, 16000,
+ * 48000 Hz
+ * Supported values for audio COPP: >0 and <=192 kHz
+ */
+
+ u8 dev_channel_mapping[32];
+} __packed;
+
/* ADM device open command payload of the
* #ADM_CMD_DEVICE_OPEN_V8 command.
*/
*/
u16 endpoint_id_3;
u16 reserved;
-
- u16 dev_num_channel;
-/* Number of channels the audio COPP sends to/receives from
- * the endpoint.
- * Supported values: 1 to 32.
- * The value is ignored for the voice processor Tx block,
- * where channel
- * configuration is derived from the topology ID.
- */
-
- u16 bit_width;
-/* Bit width (in bits) that the audio COPP sends to/receives
- * from the
- * endpoint. The value is ignored for the voice processing
- * Tx block,
- * where the PCM width is 16 bits.
- */
-
- u32 sample_rate;
-/* Sampling rate at which the audio COPP/voice processor
- * Tx block
- * interfaces with the endpoint.
- * Supported values for voice processor Tx: 8000, 16000,
- * 48000 Hz
- * Supported values for audio COPP: >0 and <=192 kHz
- */
-
- u8 dev_channel_mapping[32];
-/* Array of channel mapping of buffers that the audio COPP
- * sends to the endpoint. Channel[i] mapping describes channel
- * I inside the buffer, where 0 < i < dev_num_channel.
- * This value is relevant only for an audio Rx COPP.
- * For the voice processor block and Tx audio block, this field
- * is set to zero and is ignored.
- */
-
- u16 dev_num_channel_eid2;
-/* Number of channels the audio COPP sends to/receives from
- * the endpoint.
- * Supported values: 1 to 32.
- * The value is ignored for the voice processor Tx block,
- * where channel
- * configuration is derived from the topology ID.
- */
-
- u16 bit_width_eid2;
-/* Bit width (in bits) that the audio COPP sends to/receives
- * from the
- * endpoint. The value is ignored for the voice processing
- * Tx block,
- * where the PCM width is 16 bits.
- */
-
- u32 sample_rate_eid2;
-/* Sampling rate at which the audio COPP/voice processor
- * Tx block
- * interfaces with the endpoint.
- * Supported values for voice processor Tx: 8000, 16000,
- * 48000 Hz
- * Supported values for audio COPP: >0 and <=192 kHz
- */
-
- u8 dev_channel_mapping_eid2[32];
-/* Array of channel mapping of buffers that the audio COPP
- * sends to the endpoint. Channel[i] mapping describes channel
- * I inside the buffer, where 0 < i < dev_num_channel.
- * This value is relevant only for an audio Rx COPP.
- * For the voice processor block and Tx audio block, this field
- * is set to zero and is ignored.
- */
-
- u16 dev_num_channel_eid3;
-/* Number of channels the audio COPP sends to/receives from
- * the endpoint.
- * Supported values: 1 to 32.
- * The value is ignored for the voice processor Tx block,
- * where channel
- * configuration is derived from the topology ID.
- */
-
- u16 bit_width_eid3;
-/* Bit width (in bits) that the audio COPP sends to/receives
- * from the
- * endpoint. The value is ignored for the voice processing
- * Tx block,
- * where the PCM width is 16 bits.
- */
-
- u32 sample_rate_eid3;
-/* Sampling rate at which the audio COPP/voice processor
- * Tx block
- * interfaces with the endpoint.
- * Supported values for voice processor Tx: 8000, 16000,
- * 48000 Hz
- * Supported values for audio COPP: >0 and <=192 kHz
- */
-
- u8 dev_channel_mapping_eid3[32];
-/* Array of channel mapping of buffers that the audio COPP
- * sends to the endpoint. Channel[i] mapping describes channel
- * I inside the buffer, where 0 < i < dev_num_channel.
- * This value is relevant only for an audio Rx COPP.
- * For the voice processor block and Tx audio block, this field
- * is set to zero and is ignored.
- */
} __packed;
/*
};
#define MAX_COPPS_PER_PORT 0x8
-#define ADM_MAX_CHANNELS 8
+#define ADM_MAX_CHANNELS 32
/* multiple copp per stream. */
struct route_payload {
int session_type,
struct msm_pcm_channel_mixer *ch_mixer,
int channel_index);
+void adm_set_native_mode(int mode);
#endif /* __Q6_ADM_V2_H__ */
PCM_MEDIA_FORMAT_V2 = 0,
PCM_MEDIA_FORMAT_V3,
PCM_MEDIA_FORMAT_V4,
+ PCM_MEDIA_FORMAT_V5,
};
/* PCM format modes in DSP */
int q6asm_open_read_v4(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample, bool ts_mode);
+int q6asm_open_read_v5(struct audio_client *ac, uint32_t format,
+ uint16_t bits_per_sample, bool ts_mode);
+
int q6asm_open_write(struct audio_client *ac, uint32_t format
/*, uint16_t bits_per_sample*/);
int q6asm_open_write_v4(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample);
+int q6asm_open_write_v5(struct audio_client *ac, uint32_t format,
+ uint16_t bits_per_sample);
int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample, int32_t stream_id,
bool is_gapless_mode);
uint16_t endianness,
uint16_t mode);
+int q6asm_enc_cfg_blk_pcm_format_support_v5(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ uint16_t bits_per_sample,
+ uint16_t sample_word_size,
+ uint16_t endianness,
+ uint16_t mode);
+
int q6asm_set_encdec_chan_map(struct audio_client *ac,
uint32_t num_channels);
uint16_t endianness,
uint16_t mode);
+int q6asm_media_format_block_multi_ch_pcm_v5(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ bool use_default_chmap,
+ char *channel_map,
+ uint16_t bits_per_sample,
+ uint16_t sample_word_size,
+ uint16_t endianness,
+ uint16_t mode);
+
int q6asm_media_format_block_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg);
int q6asm_adjust_session_clock(struct audio_client *ac,
uint32_t adjust_time_lsw,
uint32_t adjust_time_msw);
+int q6asm_get_svc_version(uint32_t service_id);
#endif /* __Q6_ASM_H__ */
static inline void lockdep_softirq_end(bool in_hardirq) { }
#endif
-#define long_softirq_pending() (local_softirq_pending() & LONG_SOFTIRQ_MASK)
-#define defer_for_rt() (long_softirq_pending() && cpupri_check_rt())
+#define softirq_deferred_for_rt(pending) \
+({ \
+ __u32 deferred = 0; \
+ if (cpupri_check_rt()) { \
+ deferred = pending & LONG_SOFTIRQ_MASK; \
+ pending &= ~LONG_SOFTIRQ_MASK; \
+ } \
+ deferred; \
+})
+
asmlinkage __visible void __softirq_entry __do_softirq(void)
{
unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
int max_restart = MAX_SOFTIRQ_RESTART;
struct softirq_action *h;
bool in_hardirq;
+ __u32 deferred;
__u32 pending;
int softirq_bit;
current->flags &= ~PF_MEMALLOC;
pending = local_softirq_pending();
+ deferred = softirq_deferred_for_rt(pending);
account_irq_enter_time(current);
-
__local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
in_hardirq = lockdep_softirq_start();
restart:
/* Reset the pending bitmask before enabling irqs */
- set_softirq_pending(0);
+ set_softirq_pending(deferred);
__this_cpu_write(active_softirqs, pending);
local_irq_enable();
local_irq_disable();
pending = local_softirq_pending();
+ deferred = softirq_deferred_for_rt(pending);
+
if (pending) {
if (time_before(jiffies, end) && !need_resched() &&
- !defer_for_rt() &&
--max_restart)
goto restart;
-
- wakeup_softirqd();
}
+ if (pending | deferred)
+ wakeup_softirqd();
lockdep_softirq_end(in_hardirq);
account_irq_exit_time(current);
__local_bh_enable(SOFTIRQ_OFFSET);
static inline void invoke_softirq(void)
{
- if (!force_irqthreads && !defer_for_rt()) {
+ if (!force_irqthreads) {
#ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK
/*
* We can safely execute softirq on the current stack if
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 48000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 48000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 6,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 48000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 48000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 48000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 48000,
},
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S24_3LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_RATE_KNOT),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 48000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 48000,
},
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S24_3LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 192000,
},
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S24_3LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 192000,
},
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S24_3LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 192000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 48000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 48000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_3LE |
SNDRV_PCM_FMTBIT_S32_LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 384000,
},
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S24_3LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 192000,
},
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S24_3LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 192000,
},
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S24_3LE),
.channels_min = 1,
- .channels_max = 8,
+ .channels_max = 32,
.rate_min = 8000,
.rate_max = 192000,
},
#include <linux/of_device.h>
#include <sound/tlv.h>
#include <sound/pcm_params.h>
+#include <sound/q6core.h>
#include "msm-pcm-q6-v2.h"
#include "msm-pcm-routing-v2.h"
return -ENOMEM;
}
} else {
- ret = q6asm_open_write_v4(prtd->audio_client,
- fmt_type, bits_per_sample);
+ if (q6asm_get_svc_version(APR_SVC_ASM) >=
+ ADSP_ASM_API_VERSION_V2)
+ ret = q6asm_open_write_v5(prtd->audio_client,
+ fmt_type, bits_per_sample);
+ else
+ ret = q6asm_open_write_v4(prtd->audio_client,
+ fmt_type, bits_per_sample);
if (ret < 0) {
pr_err("%s: q6asm_open_write_v4 failed (%d)\n",
runtime->channels, !prtd->set_channel_map,
prtd->channel_map, bits_per_sample);
} else {
- ret = q6asm_media_format_block_multi_ch_pcm_v4(
+ if (q6asm_get_svc_version(APR_SVC_ASM) >=
+ ADSP_ASM_API_VERSION_V2)
+ ret = q6asm_media_format_block_multi_ch_pcm_v5(
+ prtd->audio_client, runtime->rate,
+ runtime->channels, !prtd->set_channel_map,
+ prtd->channel_map, bits_per_sample,
+ sample_word_size, ASM_LITTLE_ENDIAN,
+ DEFAULT_QF);
+ else
+ ret = q6asm_media_format_block_multi_ch_pcm_v4(
prtd->audio_client, runtime->rate,
runtime->channels, !prtd->set_channel_map,
prtd->channel_map, bits_per_sample,
__func__, params_channels(params),
prtd->audio_client->perf_mode);
- ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM,
- bits_per_sample, false);
+ if (q6asm_get_svc_version(APR_SVC_ASM) >=
+ ADSP_ASM_API_VERSION_V2)
+ ret = q6asm_open_read_v5(prtd->audio_client,
+ FORMAT_LINEAR_PCM,
+ bits_per_sample, false);
+ else
+ ret = q6asm_open_read_v4(prtd->audio_client,
+ FORMAT_LINEAR_PCM,
+ bits_per_sample, false);
if (ret < 0) {
pr_err("%s: q6asm_open_read failed\n", __func__);
q6asm_audio_client_free(prtd->audio_client);
pr_debug("%s: Samp_rate = %d Channel = %d bit width = %d, word size = %d\n",
__func__, prtd->samp_rate, prtd->channel_mode,
bits_per_sample, sample_word_size);
- ret = q6asm_enc_cfg_blk_pcm_format_support_v4(prtd->audio_client,
- prtd->samp_rate,
- prtd->channel_mode,
- bits_per_sample,
- sample_word_size,
- ASM_LITTLE_ENDIAN,
- DEFAULT_QF);
+ if (q6asm_get_svc_version(APR_SVC_ASM) >=
+ ADSP_ASM_API_VERSION_V2)
+ ret = q6asm_enc_cfg_blk_pcm_format_support_v5(
+ prtd->audio_client,
+ prtd->samp_rate,
+ prtd->channel_mode,
+ bits_per_sample,
+ sample_word_size,
+ ASM_LITTLE_ENDIAN,
+ DEFAULT_QF);
+ else
+ ret = q6asm_enc_cfg_blk_pcm_format_support_v4(
+ prtd->audio_client,
+ prtd->samp_rate,
+ prtd->channel_mode,
+ bits_per_sample,
+ sample_word_size,
+ ASM_LITTLE_ENDIAN,
+ DEFAULT_QF);
if (ret < 0)
pr_debug("%s: cmd cfg pcm was block failed", __func__);
int mmap_flag;
atomic_t pending_buffer;
bool set_channel_map;
- char channel_map[8];
+ char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL_V2];
int cmd_interrupt;
bool meta_data_mode;
uint32_t volume;
static bool is_custom_stereo_on;
static bool is_ds2_on;
static bool swap_ch;
+static int msm_native_mode;
#define WEIGHT_0_DB 0x4000
/* all the FEs which can support channel mixer */
.private_value = (unsigned long)&(mm1_ch8_enum)
},
};
+
+static int msm_native_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ switch (msm_native_mode) {
+ case 3:
+ case 2:
+ case 1:
+ ucontrol->value.integer.value[0] = msm_native_mode;
+ break;
+ default:
+ ucontrol->value.integer.value[0] = 0;
+ break;
+ }
+
+ pr_debug("%s: msm_native_mode = %d ucontrol value %ld\n",
+ __func__, msm_native_mode,
+ ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int msm_native_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ /* native flag shift from bit 11 in flags when open adm
+ * 1 << 11: use bit width native mode
+ * 2 << 11: use channel native mode
+ * 3 << 11: use bit width and channel native mode
+ */
+ switch (ucontrol->value.integer.value[0]) {
+ case 3:
+ case 2:
+ case 1:
+ msm_native_mode = ucontrol->value.integer.value[0];
+ break;
+ default:
+ msm_native_mode = 0;
+ break;
+ }
+
+ pr_debug("%s: msm_native_mode = %d ucontrol value %ld\n",
+ __func__, msm_native_mode,
+ ucontrol->value.integer.value[0]);
+ adm_set_native_mode(msm_native_mode);
+ return 0;
+}
+
+static const char *const native_mode_text[] = {"NonNative", "NativeBit",
+ "NativeCh", "NativeChBit"};
+
+static const struct soc_enum native_mode_enum[] = {
+ SOC_ENUM_SINGLE_EXT(4, native_mode_text),
+};
+
+static const struct snd_kcontrol_new native_mode_controls[] = {
+ SOC_ENUM_EXT("Native Mode Config", native_mode_enum[0],
+ msm_native_mode_get, msm_native_mode_put),
+};
+
static int msm_ec_ref_ch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
snd_soc_add_platform_controls(platform, channel_mixer_controls,
ARRAY_SIZE(channel_mixer_controls));
+ snd_soc_add_platform_controls(platform, native_mode_controls,
+ ARRAY_SIZE(native_mode_controls));
+
msm_qti_pp_add_controls(platform);
msm_dts_srs_tm_add_controls(platform);
#include <sound/q6common.h>
#include <sound/audio_cal_utils.h>
#include <sound/asound.h>
+#include <sound/q6core.h>
#include "msm-dts-srs-tm-config.h"
#include <sound/adsp_err.h>
int num_ec_ref_rx_chans;
int ec_ref_rx_bit_width;
int ec_ref_rx_sampling_rate;
+
+ int native_mode;
};
static struct adm_ctl this_adm;
return idx;
}
+static int adm_get_svc_version(uint32_t service_id)
+{
+ int ret = 0;
+ static int adm_cached_version;
+ size_t ver_size;
+ struct avcs_fwk_ver_info *ver_info = NULL;
+
+ if (service_id == AVCS_SERVICE_ID_ALL) {
+ pr_err("%s: Invalid service id: %d", __func__,
+ AVCS_SERVICE_ID_ALL);
+ return -EINVAL;
+ }
+
+ if (adm_cached_version != 0)
+ return adm_cached_version;
+
+ ver_size = sizeof(struct avcs_get_fwk_version) +
+ sizeof(struct avs_svc_api_info);
+ ver_info = kzalloc(ver_size, GFP_KERNEL);
+ if (ver_info == NULL)
+ return -ENOMEM;
+
+ ret = q6core_get_service_version(service_id, ver_info, ver_size);
+ if (ret < 0)
+ goto done;
+
+ ret = ver_info->services[0].api_version;
+ adm_cached_version = ret;
+done:
+ kfree(ver_info);
+ return ret;
+}
int srs_trumedia_open(int port_id, int copp_idx, __s32 srs_tech_id,
void *srs_params)
{
case ADM_CMD_DEVICE_OPEN_V5:
case ADM_CMD_DEVICE_CLOSE_V5:
case ADM_CMD_DEVICE_OPEN_V6:
+ case ADM_CMD_DEVICE_OPEN_V8:
case ADM_CMD_SET_MTMX_STRTR_DEV_PARAMS_V1:
pr_debug("%s: Basic callback received, wake up.\n",
__func__);
switch (data->opcode) {
case ADM_CMDRSP_DEVICE_OPEN_V5:
- case ADM_CMDRSP_DEVICE_OPEN_V6: {
+ case ADM_CMDRSP_DEVICE_OPEN_V6:
+ case ADM_CMDRSP_DEVICE_OPEN_V8: {
struct adm_cmd_rsp_device_open_v5 *open =
(struct adm_cmd_rsp_device_open_v5 *)data->payload;
return rc;
}
-int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
- int perf_mode, uint16_t bit_width, int app_type, int acdb_id)
+static int adm_arrange_mch_map_v8(
+ struct adm_device_endpoint_payload *ep_payload,
+ int path,
+ int channel_mode)
{
+ int rc = 0, idx;
+
+ memset(ep_payload->dev_channel_mapping,
+ 0, PCM_FORMAT_MAX_NUM_CHANNEL_V2);
+ switch (path) {
+ case ADM_PATH_PLAYBACK:
+ idx = ADM_MCH_MAP_IDX_PLAYBACK;
+ break;
+ case ADM_PATH_LIVE_REC:
+ case ADM_PATH_NONLIVE_REC:
+ idx = ADM_MCH_MAP_IDX_REC;
+ break;
+ default:
+ goto non_mch_path;
+ };
+
+ if ((ep_payload->dev_num_channel > 2) &&
+ multi_ch_maps[idx].set_channel_map) {
+ memcpy(ep_payload->dev_channel_mapping,
+ multi_ch_maps[idx].channel_mapping,
+ PCM_FORMAT_MAX_NUM_CHANNEL);
+ } else {
+ if (channel_mode == 1) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
+ } else if (channel_mode == 2) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ } else if (channel_mode == 3) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
+ } else if (channel_mode == 4) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
+ } else if (channel_mode == 5) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
+ } else if (channel_mode == 6) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+ } else if (channel_mode == 7) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LFE;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LB;
+ ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RB;
+ ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_CS;
+ } else if (channel_mode == 8) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+ ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+ ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+ } else if (channel_mode == 10) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+ ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+ ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+ ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
+ ep_payload->dev_channel_mapping[9] = PCM_CHANNELS;
+ } else if (channel_mode == 16) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+ ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+ ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+ ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
+ ep_payload->dev_channel_mapping[9] = PCM_CHANNELS;
+ ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
+ ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
+ ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
+ ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
+ ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
+ ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
+ } else if (channel_mode == 32) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+ ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+ ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+ ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
+ ep_payload->dev_channel_mapping[9] = PCM_CHANNELS;
+ ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
+ ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
+ ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
+ ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
+ ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
+ ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
+ ep_payload->dev_channel_mapping[16] = PCM_CHANNEL_LFE2;
+ ep_payload->dev_channel_mapping[17] = PCM_CHANNEL_SL;
+ ep_payload->dev_channel_mapping[18] = PCM_CHANNEL_SR;
+ ep_payload->dev_channel_mapping[19] = PCM_CHANNEL_TFL;
+ ep_payload->dev_channel_mapping[20] = PCM_CHANNEL_TFR;
+ ep_payload->dev_channel_mapping[21] = PCM_CHANNEL_TC;
+ ep_payload->dev_channel_mapping[22] = PCM_CHANNEL_TBL;
+ ep_payload->dev_channel_mapping[23] = PCM_CHANNEL_TBR;
+ ep_payload->dev_channel_mapping[24] = PCM_CHANNEL_TSL;
+ ep_payload->dev_channel_mapping[25] = PCM_CHANNEL_TSR;
+ ep_payload->dev_channel_mapping[26] = PCM_CHANNEL_TBC;
+ ep_payload->dev_channel_mapping[27] = PCM_CHANNEL_BFC;
+ ep_payload->dev_channel_mapping[28] = PCM_CHANNEL_BFL;
+ ep_payload->dev_channel_mapping[29] = PCM_CHANNEL_BFR;
+ ep_payload->dev_channel_mapping[30] = PCM_CHANNEL_LW;
+ ep_payload->dev_channel_mapping[31] = PCM_CHANNEL_RW;
+ } else {
+ pr_err("%s: invalid num_chan %d\n", __func__,
+ channel_mode);
+ rc = -EINVAL;
+ goto inval_ch_mod;
+ }
+ }
+
+non_mch_path:
+inval_ch_mod:
+ return rc;
+}
+
+static int adm_arrange_mch_ep2_map_v8(
+ struct adm_device_endpoint_payload *ep_payload,
+ int channel_mode)
+{
+ int rc = 0;
+
+ memset(ep_payload->dev_channel_mapping, 0,
+ PCM_FORMAT_MAX_NUM_CHANNEL_V2);
+
+ if (channel_mode == 1) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FC;
+ } else if (channel_mode == 2) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ } else if (channel_mode == 3) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
+ } else if (channel_mode == 4) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_RS;
+ } else if (channel_mode == 5) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_RS;
+ } else if (channel_mode == 6) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+ } else if (channel_mode == 8) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+ ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+ ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+ } else if (channel_mode == 10) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+ ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+ ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+ ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
+ ep_payload->dev_channel_mapping[9] = PCM_CHANNELS;
+ } else if (channel_mode == 16) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+ ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+ ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+ ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
+ ep_payload->dev_channel_mapping[9] = PCM_CHANNELS;
+ ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
+ ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
+ ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
+ ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
+ ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
+ ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
+ } else if (channel_mode == 32) {
+ ep_payload->dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ ep_payload->dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ ep_payload->dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ ep_payload->dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ ep_payload->dev_channel_mapping[4] = PCM_CHANNEL_LS;
+ ep_payload->dev_channel_mapping[5] = PCM_CHANNEL_RS;
+ ep_payload->dev_channel_mapping[6] = PCM_CHANNEL_LB;
+ ep_payload->dev_channel_mapping[7] = PCM_CHANNEL_RB;
+ ep_payload->dev_channel_mapping[8] = PCM_CHANNEL_CS;
+ ep_payload->dev_channel_mapping[9] = PCM_CHANNELS;
+ ep_payload->dev_channel_mapping[10] = PCM_CHANNEL_CVH;
+ ep_payload->dev_channel_mapping[11] = PCM_CHANNEL_MS;
+ ep_payload->dev_channel_mapping[12] = PCM_CHANNEL_FLC;
+ ep_payload->dev_channel_mapping[13] = PCM_CHANNEL_FRC;
+ ep_payload->dev_channel_mapping[14] = PCM_CHANNEL_RLC;
+ ep_payload->dev_channel_mapping[15] = PCM_CHANNEL_RRC;
+ ep_payload->dev_channel_mapping[16] = PCM_CHANNEL_LFE2;
+ ep_payload->dev_channel_mapping[17] = PCM_CHANNEL_SL;
+ ep_payload->dev_channel_mapping[18] = PCM_CHANNEL_SR;
+ ep_payload->dev_channel_mapping[19] = PCM_CHANNEL_TFL;
+ ep_payload->dev_channel_mapping[20] = PCM_CHANNEL_TFR;
+ ep_payload->dev_channel_mapping[21] = PCM_CHANNEL_TC;
+ ep_payload->dev_channel_mapping[22] = PCM_CHANNEL_TBL;
+ ep_payload->dev_channel_mapping[23] = PCM_CHANNEL_TBR;
+ ep_payload->dev_channel_mapping[24] = PCM_CHANNEL_TSL;
+ ep_payload->dev_channel_mapping[25] = PCM_CHANNEL_TSR;
+ ep_payload->dev_channel_mapping[26] = PCM_CHANNEL_TBC;
+ ep_payload->dev_channel_mapping[27] = PCM_CHANNEL_BFC;
+ ep_payload->dev_channel_mapping[28] = PCM_CHANNEL_BFL;
+ ep_payload->dev_channel_mapping[29] = PCM_CHANNEL_BFR;
+ ep_payload->dev_channel_mapping[30] = PCM_CHANNEL_LW;
+ ep_payload->dev_channel_mapping[31] = PCM_CHANNEL_RW;
+ } else {
+ pr_err("%s: invalid num_chan %d\n", __func__,
+ channel_mode);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+static int adm_open_v8(int tmp_port, int port_idx, int copp_idx,
+ int flags, int path,
+ int channel_mode, uint16_t bit_width,
+ int rate, int topology,
+ int perf_mode)
+{
+ int ret = 0;
+ struct adm_cmd_device_open_v8 open_v8;
+ struct adm_device_endpoint_payload ep1_payload;
+ struct adm_device_endpoint_payload ep2_payload;
+ int ep1_payload_size = 0;
+ int ep2_payload_size = 0;
+ void *adm_params = NULL;
+ int param_size;
+
+ if (channel_mode < 0 || channel_mode > 32) {
+ pr_err("%s: Invalid channel number 0x%x\n",
+ __func__, channel_mode);
+ return -EINVAL;
+ }
+
+ memset(&open_v8, 0, sizeof(open_v8));
+ memset(&ep1_payload, 0, sizeof(ep1_payload));
+ memset(&ep2_payload, 0, sizeof(ep2_payload));
+
+ open_v8.hdr.hdr_field = APR_HDR_FIELD(
+ APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ open_v8.hdr.src_svc = APR_SVC_ADM;
+ open_v8.hdr.src_domain = APR_DOMAIN_APPS;
+ open_v8.hdr.src_port = tmp_port;
+ open_v8.hdr.dest_svc = APR_SVC_ADM;
+ open_v8.hdr.dest_domain = APR_DOMAIN_ADSP;
+ open_v8.hdr.dest_port = tmp_port;
+ open_v8.hdr.token = port_idx << 16 | copp_idx;
+ open_v8.hdr.opcode = ADM_CMD_DEVICE_OPEN_V8;
+
+ if (this_adm.native_mode != 0) {
+ open_v8.flags = flags |
+ (this_adm.native_mode << 11);
+ this_adm.native_mode = 0;
+ } else {
+ open_v8.flags = flags;
+ }
+
+ open_v8.mode_of_operation = path;
+ open_v8.endpoint_id_1 = tmp_port;
+ open_v8.endpoint_id_2 = 0xFFFF;
+ open_v8.endpoint_id_3 = 0xFFFF;
+
+ if (this_adm.ec_ref_rx && (path != 1)) {
+ open_v8.endpoint_id_2 = this_adm.ec_ref_rx;
+ this_adm.ec_ref_rx = -1;
+ }
+
+ open_v8.topology_id = topology;
+ open_v8.reserved = 0;
+
+ /*variable endpoint payload*/
+ ep1_payload.dev_num_channel = channel_mode & 0x00FF;
+ ep1_payload.bit_width = bit_width;
+ ep1_payload.sample_rate = rate;
+ ret = adm_arrange_mch_map_v8(&ep1_payload, path,
+ channel_mode);
+ if (ret)
+ return ret;
+
+ pr_debug("%s: port_id=0x%x %x %x topology_id=0x%X flags %x ref_ch %x\n",
+ __func__, open_v8.endpoint_id_1,
+ open_v8.endpoint_id_2,
+ open_v8.endpoint_id_3,
+ open_v8.topology_id,
+ open_v8.flags,
+ this_adm.num_ec_ref_rx_chans);
+
+ ep1_payload_size = 8 +
+ roundup(ep1_payload.dev_num_channel, 4);
+ param_size = sizeof(struct adm_cmd_device_open_v8)
+ + ep1_payload_size;
+
+ atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
+
+ if ((this_adm.num_ec_ref_rx_chans != 0) && (path != 1)
+ && (open_v8.endpoint_id_2 != 0xFFFF)) {
+ ep2_payload.dev_num_channel =
+ this_adm.num_ec_ref_rx_chans;
+ this_adm.num_ec_ref_rx_chans = 0;
+
+ if (this_adm.ec_ref_rx_bit_width != 0) {
+ ep2_payload.bit_width =
+ this_adm.ec_ref_rx_bit_width;
+ this_adm.ec_ref_rx_bit_width = 0;
+ } else {
+ ep2_payload.bit_width = bit_width;
+ }
+
+ if (this_adm.ec_ref_rx_sampling_rate != 0) {
+ ep2_payload.sample_rate =
+ this_adm.ec_ref_rx_sampling_rate;
+ this_adm.ec_ref_rx_sampling_rate = 0;
+ } else {
+ ep2_payload.sample_rate = rate;
+ }
+
+ pr_debug("%s: adm open_v8 eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
+ __func__,
+ ep2_payload.dev_num_channel,
+ ep2_payload.bit_width,
+ ep2_payload.sample_rate);
+
+ ret = adm_arrange_mch_ep2_map_v8(&ep2_payload,
+ ep2_payload.dev_num_channel);
+
+ if (ret)
+ return ret;
+ ep2_payload_size = 8 +
+ roundup(ep2_payload.dev_num_channel, 4);
+ param_size += ep2_payload_size;
+ }
+
+ adm_params = kzalloc(param_size, GFP_KERNEL);
+ if (!adm_params)
+ return -ENOMEM;
+ open_v8.hdr.pkt_size = param_size;
+ memcpy(adm_params, &open_v8, sizeof(open_v8));
+ memcpy(adm_params + sizeof(open_v8),
+ (void *)&ep1_payload,
+ ep1_payload_size);
+ memcpy(adm_params + sizeof(open_v8)
+ + ep1_payload_size,
+ (void *)&ep2_payload,
+ ep2_payload_size);
+
+ ret = apr_send_pkt(this_adm.apr,
+ (uint32_t *)adm_params);
+ kfree(adm_params);
+ return ret;
+}
+
+static int adm_open_v5_v6(int tmp_port, int port_idx, int copp_idx,
+ int flags, int path,
+ int channel_mode, uint16_t bit_width,
+ int rate, int topology,
+ int perf_mode)
+{
+ int ret = 0;
struct adm_cmd_device_open_v5 open;
struct adm_cmd_device_open_v6 open_v6;
+
+ memset(&open, 0, sizeof(open));
+ memset(&open_v6, 0, sizeof(open_v6));
+
+ open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ open.hdr.pkt_size = sizeof(open);
+ open.hdr.src_svc = APR_SVC_ADM;
+ open.hdr.src_domain = APR_DOMAIN_APPS;
+ open.hdr.src_port = tmp_port;
+ open.hdr.dest_svc = APR_SVC_ADM;
+ open.hdr.dest_domain = APR_DOMAIN_ADSP;
+ open.hdr.dest_port = tmp_port;
+ open.hdr.token = port_idx << 16 | copp_idx;
+ open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
+ open.flags = flags;
+ open.mode_of_operation = path;
+ open.endpoint_id_1 = tmp_port;
+ open.endpoint_id_2 = 0xFFFF;
+
+ if (this_adm.ec_ref_rx && (path != 1)) {
+ open.endpoint_id_2 = this_adm.ec_ref_rx;
+ this_adm.ec_ref_rx = -1;
+ }
+
+ open.topology_id = topology;
+
+ open.dev_num_channel = channel_mode & 0x00FF;
+ open.bit_width = bit_width;
+ WARN_ON((perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) &&
+ (rate != ULL_SUPPORTED_SAMPLE_RATE));
+ open.sample_rate = rate;
+
+ ret = adm_arrange_mch_map(&open, path, channel_mode);
+
+ if (ret)
+ return ret;
+
+ pr_debug("%s: port_id=0x%x rate=%d topology_id=0x%X\n",
+ __func__, open.endpoint_id_1, open.sample_rate,
+ open.topology_id);
+
+ atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
+
+ if ((this_adm.num_ec_ref_rx_chans != 0) && (path != 1) &&
+ (open.endpoint_id_2 != 0xFFFF)) {
+ memset(&open_v6, 0,
+ sizeof(struct adm_cmd_device_open_v6));
+ memcpy(&open_v6, &open,
+ sizeof(struct adm_cmd_device_open_v5));
+ open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
+ open_v6.hdr.pkt_size = sizeof(open_v6);
+ open_v6.dev_num_channel_eid2 =
+ this_adm.num_ec_ref_rx_chans;
+ this_adm.num_ec_ref_rx_chans = 0;
+
+ if (this_adm.ec_ref_rx_bit_width != 0) {
+ open_v6.bit_width_eid2 =
+ this_adm.ec_ref_rx_bit_width;
+ this_adm.ec_ref_rx_bit_width = 0;
+ } else {
+ open_v6.bit_width_eid2 = bit_width;
+ }
+
+ if (this_adm.ec_ref_rx_sampling_rate != 0) {
+ open_v6.sample_rate_eid2 =
+ this_adm.ec_ref_rx_sampling_rate;
+ this_adm.ec_ref_rx_sampling_rate = 0;
+ } else {
+ open_v6.sample_rate_eid2 = rate;
+ }
+
+ pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
+ __func__, open_v6.dev_num_channel_eid2,
+ open_v6.bit_width_eid2,
+ open_v6.sample_rate_eid2);
+
+ ret = adm_arrange_mch_ep2_map(&open_v6,
+ open_v6.dev_num_channel_eid2);
+
+ if (ret)
+ return ret;
+
+ ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open_v6);
+ } else {
+ ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
+ }
+
+ return ret;
+}
+
+int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
+ int perf_mode, uint16_t bit_width, int app_type, int acdb_id)
+{
int ret = 0;
int port_idx, flags;
int copp_idx = -1;
(uint32_t)this_adm.outband_memmap.size);
}
}
- open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE),
- APR_PKT_VER);
- open.hdr.pkt_size = sizeof(open);
- open.hdr.src_svc = APR_SVC_ADM;
- open.hdr.src_domain = APR_DOMAIN_APPS;
- open.hdr.src_port = tmp_port;
- open.hdr.dest_svc = APR_SVC_ADM;
- open.hdr.dest_domain = APR_DOMAIN_ADSP;
- open.hdr.dest_port = tmp_port;
- open.hdr.token = port_idx << 16 | copp_idx;
- open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
- open.flags = flags;
- open.mode_of_operation = path;
- open.endpoint_id_1 = tmp_port;
- open.endpoint_id_2 = 0xFFFF;
-
- if (this_adm.ec_ref_rx && (path != 1)) {
- open.endpoint_id_2 = this_adm.ec_ref_rx;
- this_adm.ec_ref_rx = -1;
- }
- open.topology_id = topology;
-
- open.dev_num_channel = channel_mode & 0x00FF;
- open.bit_width = bit_width;
- WARN_ON((perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) &&
- (rate != ULL_SUPPORTED_SAMPLE_RATE));
- open.sample_rate = rate;
-
- ret = adm_arrange_mch_map(&open, path, channel_mode);
-
- if (ret)
- return ret;
-
- pr_debug("%s: port_id=0x%x rate=%d topology_id=0x%X\n",
- __func__, open.endpoint_id_1, open.sample_rate,
- open.topology_id);
-
- atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
-
- if ((this_adm.num_ec_ref_rx_chans != 0) && (path != 1) &&
- (open.endpoint_id_2 != 0xFFFF)) {
- memset(&open_v6, 0,
- sizeof(struct adm_cmd_device_open_v6));
- memcpy(&open_v6, &open,
- sizeof(struct adm_cmd_device_open_v5));
- open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6;
- open_v6.hdr.pkt_size = sizeof(open_v6);
- open_v6.dev_num_channel_eid2 =
- this_adm.num_ec_ref_rx_chans;
- this_adm.num_ec_ref_rx_chans = 0;
-
- if (this_adm.ec_ref_rx_bit_width != 0) {
- open_v6.bit_width_eid2 =
- this_adm.ec_ref_rx_bit_width;
- this_adm.ec_ref_rx_bit_width = 0;
- } else {
- open_v6.bit_width_eid2 = bit_width;
- }
-
- if (this_adm.ec_ref_rx_sampling_rate != 0) {
- open_v6.sample_rate_eid2 =
- this_adm.ec_ref_rx_sampling_rate;
- this_adm.ec_ref_rx_sampling_rate = 0;
- } else {
- open_v6.sample_rate_eid2 = rate;
- }
-
- pr_debug("%s: eid2_channels=%d eid2_bit_width=%d eid2_rate=%d\n",
- __func__, open_v6.dev_num_channel_eid2,
- open_v6.bit_width_eid2,
- open_v6.sample_rate_eid2);
-
- ret = adm_arrange_mch_ep2_map(&open_v6,
- open_v6.dev_num_channel_eid2);
-
- if (ret)
- return ret;
-
- ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open_v6);
+ if (adm_get_svc_version(APR_SVC_ADM) >=
+ ADSP_ADM_API_VERSION_V3) {
+ ret = adm_open_v8(tmp_port, port_idx, copp_idx,
+ flags, path,
+ channel_mode, bit_width,
+ rate, topology,
+ perf_mode);
} else {
- ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
+ ret = adm_open_v5_v6(tmp_port, port_idx, copp_idx,
+ flags, path,
+ channel_mode, bit_width,
+ rate, topology,
+ perf_mode);
}
if (ret < 0) {
pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
__func__, this_adm.ec_ref_rx_sampling_rate);
}
+void adm_set_native_mode(int mode)
+{
+ this_adm.native_mode = mode;
+ pr_debug("%s: enable native_mode :%d\n",
+ __func__, this_adm.native_mode);
+}
+
int adm_close(int port_id, int perf_mode, int copp_idx)
{
struct apr_hdr close;
return -EINVAL;
}
+int q6asm_get_svc_version(uint32_t service_id)
+{
+ int ret = 0;
+ static int asm_cached_version;
+ size_t ver_size;
+ struct avcs_fwk_ver_info *ver_info = NULL;
+
+ if (service_id == AVCS_SERVICE_ID_ALL) {
+ pr_err("%s: Invalid service id: %d", __func__,
+ AVCS_SERVICE_ID_ALL);
+ return -EINVAL;
+ }
+
+ if (asm_cached_version != 0)
+ return asm_cached_version;
+
+ ver_size = sizeof(struct avcs_get_fwk_version) +
+ sizeof(struct avs_svc_api_info);
+ ver_info = kzalloc(ver_size, GFP_KERNEL);
+ if (ver_info == NULL)
+ return -ENOMEM;
+
+ ret = q6core_get_service_version(service_id, ver_info, ver_size);
+ if (ret < 0)
+ goto done;
+
+ ret = ver_info->services[0].api_version;
+ asm_cached_version = ret;
+done:
+ kfree(ver_info);
+ return ret;
+}
+
static inline void q6asm_set_flag_in_token(union asm_token_struct *asm_token,
int flag, int flag_offset)
{
uint32_t pcm_format_id;
switch (media_format_block_ver) {
+ case PCM_MEDIA_FORMAT_V5:
+ pcm_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V5;
+ break;
case PCM_MEDIA_FORMAT_V4:
pcm_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V4;
break;
}
EXPORT_SYMBOL(q6asm_open_read_v4);
+/*
+ * asm_open_read_v5 - Opens audio capture session
+ *
+ * @ac: Client session handle
+ * @format: encoder format
+ * @bits_per_sample: bit width of capture session
+ * @ts_mode: timestamp mode
+ */
+int q6asm_open_read_v5(struct audio_client *ac, uint32_t format,
+ uint16_t bits_per_sample, bool ts_mode)
+{
+ return __q6asm_open_read(ac, format, bits_per_sample,
+ PCM_MEDIA_FORMAT_V5 /*media fmt block ver*/,
+ ts_mode);
+}
+EXPORT_SYMBOL(q6asm_open_read_v5);
+
int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format,
uint32_t passthrough_flag)
{
}
EXPORT_SYMBOL(q6asm_open_write_v4);
+/*
+ * q6asm_open_write_v5 - Opens audio playback session
+ *
+ * @ac: Client session handle
+ * @format: decoder format
+ * @bits_per_sample: bit width of playback session
+ */
+int q6asm_open_write_v5(struct audio_client *ac, uint32_t format,
+ uint16_t bits_per_sample)
+{
+ return __q6asm_open_write(ac, format, bits_per_sample,
+ ac->stream_id, false /*gapless*/,
+ PCM_MEDIA_FORMAT_V5 /*pcm_format_block_ver*/);
+}
+EXPORT_SYMBOL(q6asm_open_write_v5);
+
int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample, int32_t stream_id,
bool is_gapless_mode)
}
/*
+ * q6asm_enc_cfg_blk_pcm_v5 - sends encoder configuration parameters
+ *
+ * @ac: Client session handle
+ * @rate: sample rate
+ * @channels: number of channels
+ * @bits_per_sample: bit width of encoder session
+ * @use_default_chmap: true if default channel map to be used
+ * @use_back_flavor: to configure back left and right channel
+ * @channel_map: input channel map
+ * @sample_word_size: Size in bits of the word that holds a sample of a channel
+ * @endianness: endianness of the pcm data
+ * @mode: Mode to provide additional info about the pcm input data
+ */
+static int q6asm_enc_cfg_blk_pcm_v5(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ uint16_t bits_per_sample, bool use_default_chmap,
+ bool use_back_flavor, u8 *channel_map,
+ uint16_t sample_word_size, uint16_t endianness,
+ uint16_t mode)
+{
+ struct asm_multi_channel_pcm_enc_cfg_v5 enc_cfg;
+ struct asm_enc_cfg_blk_param_v2 enc_fg_blk;
+ u8 *channel_mapping;
+ u32 frames_per_buf = 0;
+ int rc;
+
+ if (!use_default_chmap && (channel_map == NULL)) {
+ pr_err("%s: No valid chan map and can't use default\n",
+ __func__);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
+ pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
+ ac->session, rate, channels,
+ bits_per_sample, sample_word_size);
+
+ memset(&enc_cfg, 0, sizeof(enc_cfg));
+ q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
+ atomic_set(&ac->cmd_state, -1);
+ enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+ enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
+ enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) -
+ sizeof(enc_cfg.encdec);
+ enc_cfg.encblk.frames_per_buf = frames_per_buf;
+ enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
+ sizeof(enc_fg_blk);
+ enc_cfg.num_channels = channels;
+ enc_cfg.bits_per_sample = bits_per_sample;
+ enc_cfg.sample_rate = rate;
+ enc_cfg.is_signed = 1;
+ enc_cfg.sample_word_size = sample_word_size;
+ enc_cfg.endianness = endianness;
+ enc_cfg.mode = mode;
+ channel_mapping = enc_cfg.channel_mapping;
+
+ memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V2);
+
+ if (use_default_chmap) {
+ pr_debug("%s: setting default channel map for %d channels",
+ __func__, channels);
+ if (q6asm_map_channels(channel_mapping, channels,
+ use_back_flavor)) {
+ pr_err("%s: map channels failed %d\n",
+ __func__, channels);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ } else {
+ pr_debug("%s: Using pre-defined channel map", __func__);
+ memcpy(channel_mapping, channel_map,
+ PCM_FORMAT_MAX_NUM_CHANNEL_V2);
+ }
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
+ if (rc < 0) {
+ pr_err("%s: Command open failed %d\n", __func__, rc);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout opcode[0x%x]\n",
+ __func__, enc_cfg.hdr.opcode);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s]\n",
+ __func__, adsp_err_get_err_str(
+ atomic_read(&ac->cmd_state)));
+ rc = adsp_err_get_lnx_err_code(
+ atomic_read(&ac->cmd_state));
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return rc;
+}
+EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v5);
+
+/*
* q6asm_enc_cfg_blk_pcm_v4 - sends encoder configuration parameters
*
* @ac: Client session handle
return rc;
}
+static int __q6asm_enc_cfg_blk_pcm_v5(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ uint16_t bits_per_sample,
+ uint16_t sample_word_size,
+ uint16_t endianness,
+ uint16_t mode)
+{
+ return q6asm_enc_cfg_blk_pcm_v5(ac, rate, channels,
+ bits_per_sample, true, false, NULL,
+ sample_word_size, endianness, mode);
+}
+
static int __q6asm_enc_cfg_blk_pcm_v4(struct audio_client *ac,
uint32_t rate, uint32_t channels,
uint16_t bits_per_sample,
}
EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v4);
+/*
+ * q6asm_enc_cfg_blk_pcm_format_support_v5 - sends encoder configuration
+ * parameters
+ *
+ * @ac: Client session handle
+ * @rate: sample rate
+ * @channels: number of channels
+ * @bits_per_sample: bit width of encoder session
+ * @sample_word_size: Size in bits of the word that holds a sample of a channel
+ * @endianness: endianness of the pcm data
+ * @mode: Mode to provide additional info about the pcm input data
+ */
+int q6asm_enc_cfg_blk_pcm_format_support_v5(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ uint16_t bits_per_sample,
+ uint16_t sample_word_size,
+ uint16_t endianness,
+ uint16_t mode)
+{
+ return __q6asm_enc_cfg_blk_pcm_v5(ac, rate, channels,
+ bits_per_sample, sample_word_size,
+ endianness, mode);
+}
+EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v5);
+
int q6asm_enc_cfg_blk_pcm_native(struct audio_client *ac,
uint32_t rate, uint32_t channels)
{
lchannel_mapping[5] = PCM_CHANNEL_RB;
lchannel_mapping[6] = PCM_CHANNEL_LS;
lchannel_mapping[7] = PCM_CHANNEL_RS;
+ } else if (channels == 10) {
+ lchannel_mapping[0] = PCM_CHANNEL_FL;
+ lchannel_mapping[1] = PCM_CHANNEL_FR;
+ lchannel_mapping[2] = PCM_CHANNEL_LFE;
+ lchannel_mapping[3] = PCM_CHANNEL_FC;
+ lchannel_mapping[4] = PCM_CHANNEL_LS;
+ lchannel_mapping[5] = PCM_CHANNEL_RS;
+ lchannel_mapping[6] = PCM_CHANNEL_LB;
+ lchannel_mapping[7] = PCM_CHANNEL_RB;
+ lchannel_mapping[8] = PCM_CHANNEL_CS;
+ lchannel_mapping[9] = PCM_CHANNELS;
+ } else if (channels == 16) {
+ lchannel_mapping[0] = PCM_CHANNEL_FL;
+ lchannel_mapping[1] = PCM_CHANNEL_FR;
+ lchannel_mapping[2] = PCM_CHANNEL_LFE;
+ lchannel_mapping[3] = PCM_CHANNEL_FC;
+ lchannel_mapping[4] = PCM_CHANNEL_LS;
+ lchannel_mapping[5] = PCM_CHANNEL_RS;
+ lchannel_mapping[6] = PCM_CHANNEL_LB;
+ lchannel_mapping[7] = PCM_CHANNEL_RB;
+ lchannel_mapping[8] = PCM_CHANNEL_CS;
+ lchannel_mapping[9] = PCM_CHANNELS;
+ lchannel_mapping[10] = PCM_CHANNEL_CVH;
+ lchannel_mapping[11] = PCM_CHANNEL_MS;
+ lchannel_mapping[12] = PCM_CHANNEL_FLC;
+ lchannel_mapping[13] = PCM_CHANNEL_FRC;
+ lchannel_mapping[14] = PCM_CHANNEL_RLC;
+ lchannel_mapping[15] = PCM_CHANNEL_RRC;
+ } else if (channels == 32) {
+ lchannel_mapping[0] = PCM_CHANNEL_FL;
+ lchannel_mapping[1] = PCM_CHANNEL_FR;
+ lchannel_mapping[2] = PCM_CHANNEL_LFE;
+ lchannel_mapping[3] = PCM_CHANNEL_FC;
+ lchannel_mapping[4] = PCM_CHANNEL_LS;
+ lchannel_mapping[5] = PCM_CHANNEL_RS;
+ lchannel_mapping[6] = PCM_CHANNEL_LB;
+ lchannel_mapping[7] = PCM_CHANNEL_RB;
+ lchannel_mapping[8] = PCM_CHANNEL_CS;
+ lchannel_mapping[9] = PCM_CHANNELS;
+ lchannel_mapping[10] = PCM_CHANNEL_CVH;
+ lchannel_mapping[11] = PCM_CHANNEL_MS;
+ lchannel_mapping[12] = PCM_CHANNEL_FLC;
+ lchannel_mapping[13] = PCM_CHANNEL_FRC;
+ lchannel_mapping[14] = PCM_CHANNEL_RLC;
+ lchannel_mapping[15] = PCM_CHANNEL_RRC;
+ lchannel_mapping[16] = PCM_CHANNEL_LFE2;
+ lchannel_mapping[17] = PCM_CHANNEL_SL;
+ lchannel_mapping[18] = PCM_CHANNEL_SR;
+ lchannel_mapping[19] = PCM_CHANNEL_TFL;
+ lchannel_mapping[20] = PCM_CHANNEL_TFR;
+ lchannel_mapping[21] = PCM_CHANNEL_TC;
+ lchannel_mapping[22] = PCM_CHANNEL_TBL;
+ lchannel_mapping[23] = PCM_CHANNEL_TBR;
+ lchannel_mapping[24] = PCM_CHANNEL_TSL;
+ lchannel_mapping[25] = PCM_CHANNEL_TSR;
+ lchannel_mapping[26] = PCM_CHANNEL_TBC;
+ lchannel_mapping[27] = PCM_CHANNEL_BFC;
+ lchannel_mapping[28] = PCM_CHANNEL_BFL;
+ lchannel_mapping[29] = PCM_CHANNEL_BFR;
+ lchannel_mapping[30] = PCM_CHANNEL_LW;
+ lchannel_mapping[31] = PCM_CHANNEL_RW;
} else {
pr_err("%s: ERROR.unsupported num_ch = %u\n",
__func__, channels);
return rc;
}
+static int __q6asm_media_format_block_multi_ch_pcm_v5(struct audio_client *ac,
+ uint32_t rate,
+ uint32_t channels,
+ bool use_default_chmap,
+ char *channel_map,
+ uint16_t bits_per_sample,
+ uint16_t sample_word_size,
+ uint16_t endianness,
+ uint16_t mode)
+{
+ struct asm_multi_channel_pcm_fmt_blk_param_v5 fmt;
+ u8 *channel_mapping;
+ int rc;
+
+ pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
+ ac->session, rate, channels,
+ bits_per_sample, sample_word_size);
+
+ memset(&fmt, 0, sizeof(fmt));
+ q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
+ atomic_set(&ac->cmd_state, -1);
+
+ fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
+ fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
+ sizeof(fmt.fmt_blk);
+ fmt.param.num_channels = channels;
+ fmt.param.bits_per_sample = bits_per_sample;
+ fmt.param.sample_rate = rate;
+ fmt.param.is_signed = 1;
+ fmt.param.sample_word_size = sample_word_size;
+ fmt.param.endianness = endianness;
+ fmt.param.mode = mode;
+ channel_mapping = fmt.param.channel_mapping;
+
+ memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V2);
+
+ if (use_default_chmap) {
+ if (q6asm_map_channels(channel_mapping, channels, false)) {
+ pr_err("%s: map channels failed %d\n",
+ __func__, channels);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ } else {
+ memcpy(channel_mapping, channel_map,
+ PCM_FORMAT_MAX_NUM_CHANNEL_V2);
+ }
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+ if (rc < 0) {
+ pr_err("%s: Comamnd open failed %d\n", __func__, rc);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout. waited for format update\n", __func__);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s]\n",
+ __func__, adsp_err_get_err_str(
+ atomic_read(&ac->cmd_state)));
+ rc = adsp_err_get_lnx_err_code(
+ atomic_read(&ac->cmd_state));
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return rc;
+}
+
int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
uint32_t rate, uint32_t channels,
bool use_default_chmap, char *channel_map)
EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v4);
/*
+ * q6asm_media_format_block_multi_ch_pcm_v5 - sends pcm decoder configuration
+ * parameters
+ *
+ * @ac: Client session handle
+ * @rate: sample rate
+ * @channels: number of channels
+ * @bits_per_sample: bit width of encoder session
+ * @use_default_chmap: true if default channel map to be used
+ * @channel_map: input channel map
+ * @sample_word_size: Size in bits of the word that holds a sample of a channel
+ * @endianness: endianness of the pcm data
+ * @mode: Mode to provide additional info about the pcm input data
+ */
+int q6asm_media_format_block_multi_ch_pcm_v5(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ bool use_default_chmap,
+ char *channel_map,
+ uint16_t bits_per_sample,
+ uint16_t sample_word_size,
+ uint16_t endianness,
+ uint16_t mode)
+{
+ return __q6asm_media_format_block_multi_ch_pcm_v5(ac, rate, channels,
+ use_default_chmap,
+ channel_map,
+ bits_per_sample,
+ sample_word_size,
+ endianness,
+ mode);
+}
+EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v5);
+
+
+/*
* q6asm_media_format_block_gen_compr - set up generic compress format params
*
* @ac: Client session handle
*/
ver_size = sizeof(struct avcs_get_fwk_version) +
num_services * sizeof(struct avs_svc_api_info);
- if (q6core_lcl.q6core_avcs_ver_info.ver_info != NULL)
- pr_warn("%s: Version info is not NULL\n", __func__);
+
q6core_lcl.q6core_avcs_ver_info.ver_info =
kzalloc(ver_size, GFP_ATOMIC);
if (q6core_lcl.q6core_avcs_ver_info.ver_info == NULL)
pr_debug("%s: Received AVCS_CMDRSP_GET_FWK_VERSION\n",
__func__);
payload1 = data->payload;
- q6core_lcl.q6core_avcs_ver_info.status = VER_QUERY_SUPPORTED;
- q6core_lcl.avcs_fwk_ver_resp_received = 1;
ret = parse_fwk_version_info(payload1);
- if (ret < 0)
+ if (ret < 0) {
+ q6core_lcl.adsp_status = ret;
pr_err("%s: Failed to parse payload:%d\n",
__func__, ret);
+ } else {
+ q6core_lcl.q6core_avcs_ver_info.status =
+ VER_QUERY_SUPPORTED;
+ }
+ q6core_lcl.avcs_fwk_ver_resp_received = 1;
wake_up(&q6core_lcl.avcs_fwk_ver_req_wait);
break;
default:
if (ret)
goto done;
- num_services = q6core_lcl.q6core_avcs_ver_info.ver_info
- ->avcs_fwk_version.num_services;
+ if (q6core_lcl.q6core_avcs_ver_info.ver_info != NULL) {
+ num_services = q6core_lcl.q6core_avcs_ver_info.ver_info
+ ->avcs_fwk_version.num_services;
+ } else {
+ pr_err("%s: ver_info is NULL\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
ret = sizeof(struct avcs_get_fwk_version);
if (service_id == AVCS_SERVICE_ID_ALL)