linux/sound/soc/qcom/qdsp6/q6afe.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
   3// Copyright (c) 2018, Linaro Limited
   4
   5#include <linux/slab.h>
   6#include <linux/kernel.h>
   7#include <linux/uaccess.h>
   8#include <linux/wait.h>
   9#include <linux/jiffies.h>
  10#include <linux/sched.h>
  11#include <linux/module.h>
  12#include <linux/kref.h>
  13#include <linux/of.h>
  14#include <linux/of_platform.h>
  15#include <linux/spinlock.h>
  16#include <linux/delay.h>
  17#include <linux/soc/qcom/apr.h>
  18#include <sound/soc.h>
  19#include <sound/soc-dai.h>
  20#include <sound/pcm.h>
  21#include <sound/pcm_params.h>
  22#include "q6dsp-errno.h"
  23#include "q6core.h"
  24#include "q6afe.h"
  25
  26/* AFE CMDs */
  27#define AFE_PORT_CMD_DEVICE_START       0x000100E5
  28#define AFE_PORT_CMD_DEVICE_STOP        0x000100E6
  29#define AFE_PORT_CMD_SET_PARAM_V2       0x000100EF
  30#define AFE_SVC_CMD_SET_PARAM           0x000100f3
  31#define AFE_PORT_CMDRSP_GET_PARAM_V2    0x00010106
  32#define AFE_PARAM_ID_HDMI_CONFIG        0x00010210
  33#define AFE_MODULE_AUDIO_DEV_INTERFACE  0x0001020C
  34#define AFE_MODULE_TDM                  0x0001028A
  35
  36#define AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG 0x00010235
  37
  38#define AFE_PARAM_ID_LPAIF_CLK_CONFIG   0x00010238
  39#define AFE_PARAM_ID_INT_DIGITAL_CDC_CLK_CONFIG 0x00010239
  40
  41#define AFE_PARAM_ID_SLIMBUS_CONFIG    0x00010212
  42#define AFE_PARAM_ID_I2S_CONFIG 0x0001020D
  43#define AFE_PARAM_ID_TDM_CONFIG 0x0001029D
  44#define AFE_PARAM_ID_PORT_SLOT_MAPPING_CONFIG   0x00010297
  45
  46/* I2S config specific */
  47#define AFE_API_VERSION_I2S_CONFIG      0x1
  48#define AFE_PORT_I2S_SD0                0x1
  49#define AFE_PORT_I2S_SD1                0x2
  50#define AFE_PORT_I2S_SD2                0x3
  51#define AFE_PORT_I2S_SD3                0x4
  52#define AFE_PORT_I2S_SD0_MASK           BIT(0x0)
  53#define AFE_PORT_I2S_SD1_MASK           BIT(0x1)
  54#define AFE_PORT_I2S_SD2_MASK           BIT(0x2)
  55#define AFE_PORT_I2S_SD3_MASK           BIT(0x3)
  56#define AFE_PORT_I2S_SD0_1_MASK         GENMASK(1, 0)
  57#define AFE_PORT_I2S_SD2_3_MASK         GENMASK(3, 2)
  58#define AFE_PORT_I2S_SD0_1_2_MASK       GENMASK(2, 0)
  59#define AFE_PORT_I2S_SD0_1_2_3_MASK     GENMASK(3, 0)
  60#define AFE_PORT_I2S_QUAD01             0x5
  61#define AFE_PORT_I2S_QUAD23             0x6
  62#define AFE_PORT_I2S_6CHS               0x7
  63#define AFE_PORT_I2S_8CHS               0x8
  64#define AFE_PORT_I2S_MONO               0x0
  65#define AFE_PORT_I2S_STEREO             0x1
  66#define AFE_PORT_CONFIG_I2S_WS_SRC_EXTERNAL     0x0
  67#define AFE_PORT_CONFIG_I2S_WS_SRC_INTERNAL     0x1
  68#define AFE_LINEAR_PCM_DATA                             0x0
  69
  70
  71/* Port IDs */
  72#define AFE_API_VERSION_HDMI_CONFIG     0x1
  73#define AFE_PORT_ID_MULTICHAN_HDMI_RX   0x100E
  74#define AFE_PORT_ID_HDMI_OVER_DP_RX     0x6020
  75
  76#define AFE_API_VERSION_SLIMBUS_CONFIG 0x1
  77/* Clock set API version */
  78#define AFE_API_VERSION_CLOCK_SET 1
  79#define Q6AFE_LPASS_CLK_CONFIG_API_VERSION      0x1
  80#define AFE_MODULE_CLOCK_SET            0x0001028F
  81#define AFE_PARAM_ID_CLOCK_SET          0x00010290
  82
  83/* SLIMbus Rx port on channel 0. */
  84#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_RX      0x4000
  85/* SLIMbus Tx port on channel 0. */
  86#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_TX      0x4001
  87/* SLIMbus Rx port on channel 1. */
  88#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX      0x4002
  89/* SLIMbus Tx port on channel 1. */
  90#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_TX      0x4003
  91/* SLIMbus Rx port on channel 2. */
  92#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_RX      0x4004
  93/* SLIMbus Tx port on channel 2. */
  94#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_TX      0x4005
  95/* SLIMbus Rx port on channel 3. */
  96#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_RX      0x4006
  97/* SLIMbus Tx port on channel 3. */
  98#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_TX      0x4007
  99/* SLIMbus Rx port on channel 4. */
 100#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_RX      0x4008
 101/* SLIMbus Tx port on channel 4. */
 102#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX      0x4009
 103/* SLIMbus Rx port on channel 5. */
 104#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_RX      0x400a
 105/* SLIMbus Tx port on channel 5. */
 106#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_TX      0x400b
 107/* SLIMbus Rx port on channel 6. */
 108#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_RX      0x400c
 109/* SLIMbus Tx port on channel 6. */
 110#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_TX      0x400d
 111#define AFE_PORT_ID_PRIMARY_MI2S_RX         0x1000
 112#define AFE_PORT_ID_PRIMARY_MI2S_TX         0x1001
 113#define AFE_PORT_ID_SECONDARY_MI2S_RX       0x1002
 114#define AFE_PORT_ID_SECONDARY_MI2S_TX       0x1003
 115#define AFE_PORT_ID_TERTIARY_MI2S_RX        0x1004
 116#define AFE_PORT_ID_TERTIARY_MI2S_TX        0x1005
 117#define AFE_PORT_ID_QUATERNARY_MI2S_RX      0x1006
 118#define AFE_PORT_ID_QUATERNARY_MI2S_TX      0x1007
 119
 120/* Start of the range of port IDs for TDM devices. */
 121#define AFE_PORT_ID_TDM_PORT_RANGE_START        0x9000
 122
 123/* End of the range of port IDs for TDM devices. */
 124#define AFE_PORT_ID_TDM_PORT_RANGE_END \
 125        (AFE_PORT_ID_TDM_PORT_RANGE_START+0x50-1)
 126
 127/* Size of the range of port IDs for TDM ports. */
 128#define AFE_PORT_ID_TDM_PORT_RANGE_SIZE \
 129        (AFE_PORT_ID_TDM_PORT_RANGE_END - \
 130        AFE_PORT_ID_TDM_PORT_RANGE_START+1)
 131
 132#define AFE_PORT_ID_PRIMARY_TDM_RX \
 133        (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x00)
 134#define AFE_PORT_ID_PRIMARY_TDM_RX_1 \
 135        (AFE_PORT_ID_PRIMARY_TDM_RX + 0x02)
 136#define AFE_PORT_ID_PRIMARY_TDM_RX_2 \
 137        (AFE_PORT_ID_PRIMARY_TDM_RX + 0x04)
 138#define AFE_PORT_ID_PRIMARY_TDM_RX_3 \
 139        (AFE_PORT_ID_PRIMARY_TDM_RX + 0x06)
 140#define AFE_PORT_ID_PRIMARY_TDM_RX_4 \
 141        (AFE_PORT_ID_PRIMARY_TDM_RX + 0x08)
 142#define AFE_PORT_ID_PRIMARY_TDM_RX_5 \
 143        (AFE_PORT_ID_PRIMARY_TDM_RX + 0x0A)
 144#define AFE_PORT_ID_PRIMARY_TDM_RX_6 \
 145        (AFE_PORT_ID_PRIMARY_TDM_RX + 0x0C)
 146#define AFE_PORT_ID_PRIMARY_TDM_RX_7 \
 147        (AFE_PORT_ID_PRIMARY_TDM_RX + 0x0E)
 148
 149#define AFE_PORT_ID_PRIMARY_TDM_TX \
 150        (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x01)
 151#define AFE_PORT_ID_PRIMARY_TDM_TX_1 \
 152        (AFE_PORT_ID_PRIMARY_TDM_TX + 0x02)
 153#define AFE_PORT_ID_PRIMARY_TDM_TX_2 \
 154        (AFE_PORT_ID_PRIMARY_TDM_TX + 0x04)
 155#define AFE_PORT_ID_PRIMARY_TDM_TX_3 \
 156        (AFE_PORT_ID_PRIMARY_TDM_TX + 0x06)
 157#define AFE_PORT_ID_PRIMARY_TDM_TX_4 \
 158        (AFE_PORT_ID_PRIMARY_TDM_TX + 0x08)
 159#define AFE_PORT_ID_PRIMARY_TDM_TX_5 \
 160        (AFE_PORT_ID_PRIMARY_TDM_TX + 0x0A)
 161#define AFE_PORT_ID_PRIMARY_TDM_TX_6 \
 162        (AFE_PORT_ID_PRIMARY_TDM_TX + 0x0C)
 163#define AFE_PORT_ID_PRIMARY_TDM_TX_7 \
 164        (AFE_PORT_ID_PRIMARY_TDM_TX + 0x0E)
 165
 166#define AFE_PORT_ID_SECONDARY_TDM_RX \
 167        (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x10)
 168#define AFE_PORT_ID_SECONDARY_TDM_RX_1 \
 169        (AFE_PORT_ID_SECONDARY_TDM_RX + 0x02)
 170#define AFE_PORT_ID_SECONDARY_TDM_RX_2 \
 171        (AFE_PORT_ID_SECONDARY_TDM_RX + 0x04)
 172#define AFE_PORT_ID_SECONDARY_TDM_RX_3 \
 173        (AFE_PORT_ID_SECONDARY_TDM_RX + 0x06)
 174#define AFE_PORT_ID_SECONDARY_TDM_RX_4 \
 175        (AFE_PORT_ID_SECONDARY_TDM_RX + 0x08)
 176#define AFE_PORT_ID_SECONDARY_TDM_RX_5 \
 177        (AFE_PORT_ID_SECONDARY_TDM_RX + 0x0A)
 178#define AFE_PORT_ID_SECONDARY_TDM_RX_6 \
 179        (AFE_PORT_ID_SECONDARY_TDM_RX + 0x0C)
 180#define AFE_PORT_ID_SECONDARY_TDM_RX_7 \
 181        (AFE_PORT_ID_SECONDARY_TDM_RX + 0x0E)
 182
 183#define AFE_PORT_ID_SECONDARY_TDM_TX \
 184        (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x11)
 185#define AFE_PORT_ID_SECONDARY_TDM_TX_1 \
 186        (AFE_PORT_ID_SECONDARY_TDM_TX + 0x02)
 187#define AFE_PORT_ID_SECONDARY_TDM_TX_2 \
 188        (AFE_PORT_ID_SECONDARY_TDM_TX + 0x04)
 189#define AFE_PORT_ID_SECONDARY_TDM_TX_3 \
 190        (AFE_PORT_ID_SECONDARY_TDM_TX + 0x06)
 191#define AFE_PORT_ID_SECONDARY_TDM_TX_4 \
 192        (AFE_PORT_ID_SECONDARY_TDM_TX + 0x08)
 193#define AFE_PORT_ID_SECONDARY_TDM_TX_5 \
 194        (AFE_PORT_ID_SECONDARY_TDM_TX + 0x0A)
 195#define AFE_PORT_ID_SECONDARY_TDM_TX_6 \
 196        (AFE_PORT_ID_SECONDARY_TDM_TX + 0x0C)
 197#define AFE_PORT_ID_SECONDARY_TDM_TX_7 \
 198        (AFE_PORT_ID_SECONDARY_TDM_TX + 0x0E)
 199
 200#define AFE_PORT_ID_TERTIARY_TDM_RX \
 201        (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x20)
 202#define AFE_PORT_ID_TERTIARY_TDM_RX_1 \
 203        (AFE_PORT_ID_TERTIARY_TDM_RX + 0x02)
 204#define AFE_PORT_ID_TERTIARY_TDM_RX_2 \
 205        (AFE_PORT_ID_TERTIARY_TDM_RX + 0x04)
 206#define AFE_PORT_ID_TERTIARY_TDM_RX_3 \
 207        (AFE_PORT_ID_TERTIARY_TDM_RX + 0x06)
 208#define AFE_PORT_ID_TERTIARY_TDM_RX_4 \
 209        (AFE_PORT_ID_TERTIARY_TDM_RX + 0x08)
 210#define AFE_PORT_ID_TERTIARY_TDM_RX_5 \
 211        (AFE_PORT_ID_TERTIARY_TDM_RX + 0x0A)
 212#define AFE_PORT_ID_TERTIARY_TDM_RX_6 \
 213        (AFE_PORT_ID_TERTIARY_TDM_RX + 0x0C)
 214#define AFE_PORT_ID_TERTIARY_TDM_RX_7 \
 215        (AFE_PORT_ID_TERTIARY_TDM_RX + 0x0E)
 216
 217#define AFE_PORT_ID_TERTIARY_TDM_TX \
 218        (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x21)
 219#define AFE_PORT_ID_TERTIARY_TDM_TX_1 \
 220        (AFE_PORT_ID_TERTIARY_TDM_TX + 0x02)
 221#define AFE_PORT_ID_TERTIARY_TDM_TX_2 \
 222        (AFE_PORT_ID_TERTIARY_TDM_TX + 0x04)
 223#define AFE_PORT_ID_TERTIARY_TDM_TX_3 \
 224        (AFE_PORT_ID_TERTIARY_TDM_TX + 0x06)
 225#define AFE_PORT_ID_TERTIARY_TDM_TX_4 \
 226        (AFE_PORT_ID_TERTIARY_TDM_TX + 0x08)
 227#define AFE_PORT_ID_TERTIARY_TDM_TX_5 \
 228        (AFE_PORT_ID_TERTIARY_TDM_TX + 0x0A)
 229#define AFE_PORT_ID_TERTIARY_TDM_TX_6 \
 230        (AFE_PORT_ID_TERTIARY_TDM_TX + 0x0C)
 231#define AFE_PORT_ID_TERTIARY_TDM_TX_7 \
 232        (AFE_PORT_ID_TERTIARY_TDM_TX + 0x0E)
 233
 234#define AFE_PORT_ID_QUATERNARY_TDM_RX \
 235        (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x30)
 236#define AFE_PORT_ID_QUATERNARY_TDM_RX_1 \
 237        (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x02)
 238#define AFE_PORT_ID_QUATERNARY_TDM_RX_2 \
 239        (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x04)
 240#define AFE_PORT_ID_QUATERNARY_TDM_RX_3 \
 241        (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x06)
 242#define AFE_PORT_ID_QUATERNARY_TDM_RX_4 \
 243        (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x08)
 244#define AFE_PORT_ID_QUATERNARY_TDM_RX_5 \
 245        (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x0A)
 246#define AFE_PORT_ID_QUATERNARY_TDM_RX_6 \
 247        (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x0C)
 248#define AFE_PORT_ID_QUATERNARY_TDM_RX_7 \
 249        (AFE_PORT_ID_QUATERNARY_TDM_RX + 0x0E)
 250
 251#define AFE_PORT_ID_QUATERNARY_TDM_TX \
 252        (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x31)
 253#define AFE_PORT_ID_QUATERNARY_TDM_TX_1 \
 254        (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x02)
 255#define AFE_PORT_ID_QUATERNARY_TDM_TX_2 \
 256        (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x04)
 257#define AFE_PORT_ID_QUATERNARY_TDM_TX_3 \
 258        (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x06)
 259#define AFE_PORT_ID_QUATERNARY_TDM_TX_4 \
 260        (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x08)
 261#define AFE_PORT_ID_QUATERNARY_TDM_TX_5 \
 262        (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x0A)
 263#define AFE_PORT_ID_QUATERNARY_TDM_TX_6 \
 264        (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x0C)
 265#define AFE_PORT_ID_QUATERNARY_TDM_TX_7 \
 266        (AFE_PORT_ID_QUATERNARY_TDM_TX + 0x0E)
 267
 268#define AFE_PORT_ID_QUINARY_TDM_RX \
 269        (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x40)
 270#define AFE_PORT_ID_QUINARY_TDM_RX_1 \
 271        (AFE_PORT_ID_QUINARY_TDM_RX + 0x02)
 272#define AFE_PORT_ID_QUINARY_TDM_RX_2 \
 273        (AFE_PORT_ID_QUINARY_TDM_RX + 0x04)
 274#define AFE_PORT_ID_QUINARY_TDM_RX_3 \
 275        (AFE_PORT_ID_QUINARY_TDM_RX + 0x06)
 276#define AFE_PORT_ID_QUINARY_TDM_RX_4 \
 277        (AFE_PORT_ID_QUINARY_TDM_RX + 0x08)
 278#define AFE_PORT_ID_QUINARY_TDM_RX_5 \
 279        (AFE_PORT_ID_QUINARY_TDM_RX + 0x0A)
 280#define AFE_PORT_ID_QUINARY_TDM_RX_6 \
 281        (AFE_PORT_ID_QUINARY_TDM_RX + 0x0C)
 282#define AFE_PORT_ID_QUINARY_TDM_RX_7 \
 283        (AFE_PORT_ID_QUINARY_TDM_RX + 0x0E)
 284
 285#define AFE_PORT_ID_QUINARY_TDM_TX \
 286        (AFE_PORT_ID_TDM_PORT_RANGE_START + 0x41)
 287#define AFE_PORT_ID_QUINARY_TDM_TX_1 \
 288        (AFE_PORT_ID_QUINARY_TDM_TX + 0x02)
 289#define AFE_PORT_ID_QUINARY_TDM_TX_2 \
 290        (AFE_PORT_ID_QUINARY_TDM_TX + 0x04)
 291#define AFE_PORT_ID_QUINARY_TDM_TX_3 \
 292        (AFE_PORT_ID_QUINARY_TDM_TX + 0x06)
 293#define AFE_PORT_ID_QUINARY_TDM_TX_4 \
 294        (AFE_PORT_ID_QUINARY_TDM_TX + 0x08)
 295#define AFE_PORT_ID_QUINARY_TDM_TX_5 \
 296        (AFE_PORT_ID_QUINARY_TDM_TX + 0x0A)
 297#define AFE_PORT_ID_QUINARY_TDM_TX_6 \
 298        (AFE_PORT_ID_QUINARY_TDM_TX + 0x0C)
 299#define AFE_PORT_ID_QUINARY_TDM_TX_7 \
 300        (AFE_PORT_ID_QUINARY_TDM_TX + 0x0E)
 301
 302#define Q6AFE_LPASS_MODE_CLK1_VALID 1
 303#define Q6AFE_LPASS_MODE_CLK2_VALID 2
 304#define Q6AFE_LPASS_CLK_SRC_INTERNAL 1
 305#define Q6AFE_LPASS_CLK_ROOT_DEFAULT 0
 306#define AFE_API_VERSION_TDM_CONFIG              1
 307#define AFE_API_VERSION_SLOT_MAPPING_CONFIG     1
 308
 309#define TIMEOUT_MS 1000
 310#define AFE_CMD_RESP_AVAIL      0
 311#define AFE_CMD_RESP_NONE       1
 312
 313struct q6afe {
 314        struct apr_device *apr;
 315        struct device *dev;
 316        struct q6core_svc_api_info ainfo;
 317        struct mutex lock;
 318        struct list_head port_list;
 319        spinlock_t port_list_lock;
 320};
 321
 322struct afe_port_cmd_device_start {
 323        u16 port_id;
 324        u16 reserved;
 325} __packed;
 326
 327struct afe_port_cmd_device_stop {
 328        u16 port_id;
 329        u16 reserved;
 330/* Reserved for 32-bit alignment. This field must be set to 0.*/
 331} __packed;
 332
 333struct afe_port_param_data_v2 {
 334        u32 module_id;
 335        u32 param_id;
 336        u16 param_size;
 337        u16 reserved;
 338} __packed;
 339
 340struct afe_svc_cmd_set_param {
 341        uint32_t payload_size;
 342        uint32_t payload_address_lsw;
 343        uint32_t payload_address_msw;
 344        uint32_t mem_map_handle;
 345} __packed;
 346
 347struct afe_port_cmd_set_param_v2 {
 348        u16 port_id;
 349        u16 payload_size;
 350        u32 payload_address_lsw;
 351        u32 payload_address_msw;
 352        u32 mem_map_handle;
 353} __packed;
 354
 355struct afe_param_id_hdmi_multi_chan_audio_cfg {
 356        u32 hdmi_cfg_minor_version;
 357        u16 datatype;
 358        u16 channel_allocation;
 359        u32 sample_rate;
 360        u16 bit_width;
 361        u16 reserved;
 362} __packed;
 363
 364struct afe_param_id_slimbus_cfg {
 365        u32                  sb_cfg_minor_version;
 366/* Minor version used for tracking the version of the SLIMBUS
 367 * configuration interface.
 368 * Supported values: #AFE_API_VERSION_SLIMBUS_CONFIG
 369 */
 370
 371        u16                  slimbus_dev_id;
 372/* SLIMbus hardware device ID, which is required to handle
 373 * multiple SLIMbus hardware blocks.
 374 * Supported values: - #AFE_SLIMBUS_DEVICE_1 - #AFE_SLIMBUS_DEVICE_2
 375 */
 376        u16                  bit_width;
 377/* Bit width of the sample.
 378 * Supported values: 16, 24
 379 */
 380        u16                  data_format;
 381/* Data format supported by the SLIMbus hardware. The default is
 382 * 0 (#AFE_SB_DATA_FORMAT_NOT_INDICATED), which indicates the
 383 * hardware does not perform any format conversions before the data
 384 * transfer.
 385 */
 386        u16                  num_channels;
 387/* Number of channels.
 388 * Supported values: 1 to #AFE_PORT_MAX_AUDIO_CHAN_CNT
 389 */
 390        u8  shared_ch_mapping[AFE_PORT_MAX_AUDIO_CHAN_CNT];
 391/* Mapping of shared channel IDs (128 to 255) to which the
 392 * master port is to be connected.
 393 * Shared_channel_mapping[i] represents the shared channel assigned
 394 * for audio channel i in multichannel audio data.
 395 */
 396        u32              sample_rate;
 397/* Sampling rate of the port.
 398 * Supported values:
 399 * - #AFE_PORT_SAMPLE_RATE_8K
 400 * - #AFE_PORT_SAMPLE_RATE_16K
 401 * - #AFE_PORT_SAMPLE_RATE_48K
 402 * - #AFE_PORT_SAMPLE_RATE_96K
 403 * - #AFE_PORT_SAMPLE_RATE_192K
 404 */
 405} __packed;
 406
 407struct afe_clk_cfg {
 408        u32                  i2s_cfg_minor_version;
 409        u32                  clk_val1;
 410        u32                  clk_val2;
 411        u16                  clk_src;
 412        u16                  clk_root;
 413        u16                  clk_set_mode;
 414        u16                  reserved;
 415} __packed;
 416
 417struct afe_digital_clk_cfg {
 418        u32                  i2s_cfg_minor_version;
 419        u32                  clk_val;
 420        u16                  clk_root;
 421        u16                  reserved;
 422} __packed;
 423
 424struct afe_param_id_i2s_cfg {
 425        u32     i2s_cfg_minor_version;
 426        u16     bit_width;
 427        u16     channel_mode;
 428        u16     mono_stereo;
 429        u16     ws_src;
 430        u32     sample_rate;
 431        u16     data_format;
 432        u16     reserved;
 433} __packed;
 434
 435struct afe_param_id_tdm_cfg {
 436        u32     tdm_cfg_minor_version;
 437        u32     num_channels;
 438        u32     sample_rate;
 439        u32     bit_width;
 440        u16     data_format;
 441        u16     sync_mode;
 442        u16     sync_src;
 443        u16     nslots_per_frame;
 444        u16     ctrl_data_out_enable;
 445        u16     ctrl_invert_sync_pulse;
 446        u16     ctrl_sync_data_delay;
 447        u16     slot_width;
 448        u32     slot_mask;
 449} __packed;
 450
 451union afe_port_config {
 452        struct afe_param_id_hdmi_multi_chan_audio_cfg hdmi_multi_ch;
 453        struct afe_param_id_slimbus_cfg           slim_cfg;
 454        struct afe_param_id_i2s_cfg     i2s_cfg;
 455        struct afe_param_id_tdm_cfg     tdm_cfg;
 456} __packed;
 457
 458
 459struct afe_clk_set {
 460        uint32_t clk_set_minor_version;
 461        uint32_t clk_id;
 462        uint32_t clk_freq_in_hz;
 463        uint16_t clk_attri;
 464        uint16_t clk_root;
 465        uint32_t enable;
 466};
 467
 468struct afe_param_id_slot_mapping_cfg {
 469        u32     minor_version;
 470        u16     num_channels;
 471        u16     bitwidth;
 472        u32     data_align_type;
 473        u16     ch_mapping[AFE_PORT_MAX_AUDIO_CHAN_CNT];
 474} __packed;
 475
 476struct q6afe_port {
 477        wait_queue_head_t wait;
 478        union afe_port_config port_cfg;
 479        struct afe_param_id_slot_mapping_cfg *scfg;
 480        struct aprv2_ibasic_rsp_result_t result;
 481        int token;
 482        int id;
 483        int cfg_type;
 484        struct q6afe *afe;
 485        struct kref refcount;
 486        struct list_head node;
 487};
 488
 489struct afe_port_map {
 490        int port_id;
 491        int token;
 492        int is_rx;
 493        int is_dig_pcm;
 494};
 495
 496/*
 497 * Mapping between Virtual Port IDs to DSP AFE Port ID
 498 * On B Family SoCs DSP Port IDs are consistent across multiple SoCs
 499 * on A Family SoCs DSP port IDs are same as virtual Port IDs.
 500 */
 501
 502static struct afe_port_map port_maps[AFE_PORT_MAX] = {
 503        [HDMI_RX] = { AFE_PORT_ID_MULTICHAN_HDMI_RX, HDMI_RX, 1, 1},
 504        [SLIMBUS_0_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_RX,
 505                                SLIMBUS_0_RX, 1, 1},
 506        [SLIMBUS_1_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX,
 507                                SLIMBUS_1_RX, 1, 1},
 508        [SLIMBUS_2_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_RX,
 509                                SLIMBUS_2_RX, 1, 1},
 510        [SLIMBUS_3_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_RX,
 511                                SLIMBUS_3_RX, 1, 1},
 512        [SLIMBUS_4_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_RX,
 513                                SLIMBUS_4_RX, 1, 1},
 514        [SLIMBUS_5_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_RX,
 515                                SLIMBUS_5_RX, 1, 1},
 516        [SLIMBUS_6_RX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_RX,
 517                                SLIMBUS_6_RX, 1, 1},
 518        [SLIMBUS_0_TX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_TX,
 519                                SLIMBUS_0_TX, 0, 1},
 520        [SLIMBUS_1_TX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_TX,
 521                                SLIMBUS_1_TX, 0, 1},
 522        [SLIMBUS_2_TX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_TX,
 523                                SLIMBUS_2_TX, 0, 1},
 524        [SLIMBUS_3_TX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_TX,
 525                                SLIMBUS_3_TX, 0, 1},
 526        [SLIMBUS_4_TX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX,
 527                                SLIMBUS_4_TX, 0, 1},
 528        [SLIMBUS_5_TX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_TX,
 529                                SLIMBUS_5_TX, 0, 1},
 530        [SLIMBUS_6_TX] = { AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_TX,
 531                                SLIMBUS_6_TX, 0, 1},
 532        [PRIMARY_MI2S_RX] = { AFE_PORT_ID_PRIMARY_MI2S_RX,
 533                                PRIMARY_MI2S_RX, 1, 1},
 534        [PRIMARY_MI2S_TX] = { AFE_PORT_ID_PRIMARY_MI2S_TX,
 535                                PRIMARY_MI2S_RX, 0, 1},
 536        [SECONDARY_MI2S_RX] = { AFE_PORT_ID_SECONDARY_MI2S_RX,
 537                                SECONDARY_MI2S_RX, 1, 1},
 538        [SECONDARY_MI2S_TX] = { AFE_PORT_ID_SECONDARY_MI2S_TX,
 539                                SECONDARY_MI2S_TX, 0, 1},
 540        [TERTIARY_MI2S_RX] = { AFE_PORT_ID_TERTIARY_MI2S_RX,
 541                                TERTIARY_MI2S_RX, 1, 1},
 542        [TERTIARY_MI2S_TX] = { AFE_PORT_ID_TERTIARY_MI2S_TX,
 543                                TERTIARY_MI2S_TX, 0, 1},
 544        [QUATERNARY_MI2S_RX] = { AFE_PORT_ID_QUATERNARY_MI2S_RX,
 545                                QUATERNARY_MI2S_RX, 1, 1},
 546        [QUATERNARY_MI2S_TX] = { AFE_PORT_ID_QUATERNARY_MI2S_TX,
 547                                QUATERNARY_MI2S_TX, 0, 1},
 548        [PRIMARY_TDM_RX_0] =  { AFE_PORT_ID_PRIMARY_TDM_RX,
 549                                PRIMARY_TDM_RX_0, 1, 1},
 550        [PRIMARY_TDM_TX_0] =  { AFE_PORT_ID_PRIMARY_TDM_TX,
 551                                PRIMARY_TDM_TX_0, 0, 1},
 552        [PRIMARY_TDM_RX_1] =  { AFE_PORT_ID_PRIMARY_TDM_RX_1,
 553                                PRIMARY_TDM_RX_1, 1, 1},
 554        [PRIMARY_TDM_TX_1] =  { AFE_PORT_ID_PRIMARY_TDM_TX_1,
 555                                PRIMARY_TDM_TX_1, 0, 1},
 556        [PRIMARY_TDM_RX_2] =  { AFE_PORT_ID_PRIMARY_TDM_RX_2,
 557                                PRIMARY_TDM_RX_2, 1, 1},
 558        [PRIMARY_TDM_TX_2] =  { AFE_PORT_ID_PRIMARY_TDM_TX_2,
 559                                PRIMARY_TDM_TX_2, 0, 1},
 560        [PRIMARY_TDM_RX_3] =  { AFE_PORT_ID_PRIMARY_TDM_RX_3,
 561                                PRIMARY_TDM_RX_3, 1, 1},
 562        [PRIMARY_TDM_TX_3] =  { AFE_PORT_ID_PRIMARY_TDM_TX_3,
 563                                PRIMARY_TDM_TX_3, 0, 1},
 564        [PRIMARY_TDM_RX_4] =  { AFE_PORT_ID_PRIMARY_TDM_RX_4,
 565                                PRIMARY_TDM_RX_4, 1, 1},
 566        [PRIMARY_TDM_TX_4] =  { AFE_PORT_ID_PRIMARY_TDM_TX_4,
 567                                PRIMARY_TDM_TX_4, 0, 1},
 568        [PRIMARY_TDM_RX_5] =  { AFE_PORT_ID_PRIMARY_TDM_RX_5,
 569                                PRIMARY_TDM_RX_5, 1, 1},
 570        [PRIMARY_TDM_TX_5] =  { AFE_PORT_ID_PRIMARY_TDM_TX_5,
 571                                PRIMARY_TDM_TX_5, 0, 1},
 572        [PRIMARY_TDM_RX_6] =  { AFE_PORT_ID_PRIMARY_TDM_RX_6,
 573                                PRIMARY_TDM_RX_6, 1, 1},
 574        [PRIMARY_TDM_TX_6] =  { AFE_PORT_ID_PRIMARY_TDM_TX_6,
 575                                PRIMARY_TDM_TX_6, 0, 1},
 576        [PRIMARY_TDM_RX_7] =  { AFE_PORT_ID_PRIMARY_TDM_RX_7,
 577                                PRIMARY_TDM_RX_7, 1, 1},
 578        [PRIMARY_TDM_TX_7] =  { AFE_PORT_ID_PRIMARY_TDM_TX_7,
 579                                PRIMARY_TDM_TX_7, 0, 1},
 580        [SECONDARY_TDM_RX_0] =  { AFE_PORT_ID_SECONDARY_TDM_RX,
 581                                SECONDARY_TDM_RX_0, 1, 1},
 582        [SECONDARY_TDM_TX_0] =  { AFE_PORT_ID_SECONDARY_TDM_TX,
 583                                SECONDARY_TDM_TX_0, 0, 1},
 584        [SECONDARY_TDM_RX_1] =  { AFE_PORT_ID_SECONDARY_TDM_RX_1,
 585                                SECONDARY_TDM_RX_1, 1, 1},
 586        [SECONDARY_TDM_TX_1] =  { AFE_PORT_ID_SECONDARY_TDM_TX_1,
 587                                SECONDARY_TDM_TX_1, 0, 1},
 588        [SECONDARY_TDM_RX_2] =  { AFE_PORT_ID_SECONDARY_TDM_RX_2,
 589                                SECONDARY_TDM_RX_2, 1, 1},
 590        [SECONDARY_TDM_TX_2] =  { AFE_PORT_ID_SECONDARY_TDM_TX_2,
 591                                SECONDARY_TDM_TX_2, 0, 1},
 592        [SECONDARY_TDM_RX_3] =  { AFE_PORT_ID_SECONDARY_TDM_RX_3,
 593                                SECONDARY_TDM_RX_3, 1, 1},
 594        [SECONDARY_TDM_TX_3] =  { AFE_PORT_ID_SECONDARY_TDM_TX_3,
 595                                SECONDARY_TDM_TX_3, 0, 1},
 596        [SECONDARY_TDM_RX_4] =  { AFE_PORT_ID_SECONDARY_TDM_RX_4,
 597                                SECONDARY_TDM_RX_4, 1, 1},
 598        [SECONDARY_TDM_TX_4] =  { AFE_PORT_ID_SECONDARY_TDM_TX_4,
 599                                SECONDARY_TDM_TX_4, 0, 1},
 600        [SECONDARY_TDM_RX_5] =  { AFE_PORT_ID_SECONDARY_TDM_RX_5,
 601                                SECONDARY_TDM_RX_5, 1, 1},
 602        [SECONDARY_TDM_TX_5] =  { AFE_PORT_ID_SECONDARY_TDM_TX_5,
 603                                SECONDARY_TDM_TX_5, 0, 1},
 604        [SECONDARY_TDM_RX_6] =  { AFE_PORT_ID_SECONDARY_TDM_RX_6,
 605                                SECONDARY_TDM_RX_6, 1, 1},
 606        [SECONDARY_TDM_TX_6] =  { AFE_PORT_ID_SECONDARY_TDM_TX_6,
 607                                SECONDARY_TDM_TX_6, 0, 1},
 608        [SECONDARY_TDM_RX_7] =  { AFE_PORT_ID_SECONDARY_TDM_RX_7,
 609                                SECONDARY_TDM_RX_7, 1, 1},
 610        [SECONDARY_TDM_TX_7] =  { AFE_PORT_ID_SECONDARY_TDM_TX_7,
 611                                SECONDARY_TDM_TX_7, 0, 1},
 612        [TERTIARY_TDM_RX_0] =  { AFE_PORT_ID_TERTIARY_TDM_RX,
 613                                TERTIARY_TDM_RX_0, 1, 1},
 614        [TERTIARY_TDM_TX_0] =  { AFE_PORT_ID_TERTIARY_TDM_TX,
 615                                TERTIARY_TDM_TX_0, 0, 1},
 616        [TERTIARY_TDM_RX_1] =  { AFE_PORT_ID_TERTIARY_TDM_RX_1,
 617                                TERTIARY_TDM_RX_1, 1, 1},
 618        [TERTIARY_TDM_TX_1] =  { AFE_PORT_ID_TERTIARY_TDM_TX_1,
 619                                TERTIARY_TDM_TX_1, 0, 1},
 620        [TERTIARY_TDM_RX_2] =  { AFE_PORT_ID_TERTIARY_TDM_RX_2,
 621                                TERTIARY_TDM_RX_2, 1, 1},
 622        [TERTIARY_TDM_TX_2] =  { AFE_PORT_ID_TERTIARY_TDM_TX_2,
 623                                TERTIARY_TDM_TX_2, 0, 1},
 624        [TERTIARY_TDM_RX_3] =  { AFE_PORT_ID_TERTIARY_TDM_RX_3,
 625                                TERTIARY_TDM_RX_3, 1, 1},
 626        [TERTIARY_TDM_TX_3] =  { AFE_PORT_ID_TERTIARY_TDM_TX_3,
 627                                TERTIARY_TDM_TX_3, 0, 1},
 628        [TERTIARY_TDM_RX_4] =  { AFE_PORT_ID_TERTIARY_TDM_RX_4,
 629                                TERTIARY_TDM_RX_4, 1, 1},
 630        [TERTIARY_TDM_TX_4] =  { AFE_PORT_ID_TERTIARY_TDM_TX_4,
 631                                TERTIARY_TDM_TX_4, 0, 1},
 632        [TERTIARY_TDM_RX_5] =  { AFE_PORT_ID_TERTIARY_TDM_RX_5,
 633                                TERTIARY_TDM_RX_5, 1, 1},
 634        [TERTIARY_TDM_TX_5] =  { AFE_PORT_ID_TERTIARY_TDM_TX_5,
 635                                TERTIARY_TDM_TX_5, 0, 1},
 636        [TERTIARY_TDM_RX_6] =  { AFE_PORT_ID_TERTIARY_TDM_RX_6,
 637                                TERTIARY_TDM_RX_6, 1, 1},
 638        [TERTIARY_TDM_TX_6] =  { AFE_PORT_ID_TERTIARY_TDM_TX_6,
 639                                TERTIARY_TDM_TX_6, 0, 1},
 640        [TERTIARY_TDM_RX_7] =  { AFE_PORT_ID_TERTIARY_TDM_RX_7,
 641                                TERTIARY_TDM_RX_7, 1, 1},
 642        [TERTIARY_TDM_TX_7] =  { AFE_PORT_ID_TERTIARY_TDM_TX_7,
 643                                TERTIARY_TDM_TX_7, 0, 1},
 644        [QUATERNARY_TDM_RX_0] =  { AFE_PORT_ID_QUATERNARY_TDM_RX,
 645                                QUATERNARY_TDM_RX_0, 1, 1},
 646        [QUATERNARY_TDM_TX_0] =  { AFE_PORT_ID_QUATERNARY_TDM_TX,
 647                                QUATERNARY_TDM_TX_0, 0, 1},
 648        [QUATERNARY_TDM_RX_1] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_1,
 649                                QUATERNARY_TDM_RX_1, 1, 1},
 650        [QUATERNARY_TDM_TX_1] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_1,
 651                                QUATERNARY_TDM_TX_1, 0, 1},
 652        [QUATERNARY_TDM_RX_2] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_2,
 653                                QUATERNARY_TDM_RX_2, 1, 1},
 654        [QUATERNARY_TDM_TX_2] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_2,
 655                                QUATERNARY_TDM_TX_2, 0, 1},
 656        [QUATERNARY_TDM_RX_3] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_3,
 657                                QUATERNARY_TDM_RX_3, 1, 1},
 658        [QUATERNARY_TDM_TX_3] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_3,
 659                                QUATERNARY_TDM_TX_3, 0, 1},
 660        [QUATERNARY_TDM_RX_4] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_4,
 661                                QUATERNARY_TDM_RX_4, 1, 1},
 662        [QUATERNARY_TDM_TX_4] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_4,
 663                                QUATERNARY_TDM_TX_4, 0, 1},
 664        [QUATERNARY_TDM_RX_5] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_5,
 665                                QUATERNARY_TDM_RX_5, 1, 1},
 666        [QUATERNARY_TDM_TX_5] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_5,
 667                                QUATERNARY_TDM_TX_5, 0, 1},
 668        [QUATERNARY_TDM_RX_6] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_6,
 669                                QUATERNARY_TDM_RX_6, 1, 1},
 670        [QUATERNARY_TDM_TX_6] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_6,
 671                                QUATERNARY_TDM_TX_6, 0, 1},
 672        [QUATERNARY_TDM_RX_7] =  { AFE_PORT_ID_QUATERNARY_TDM_RX_7,
 673                                QUATERNARY_TDM_RX_7, 1, 1},
 674        [QUATERNARY_TDM_TX_7] =  { AFE_PORT_ID_QUATERNARY_TDM_TX_7,
 675                                QUATERNARY_TDM_TX_7, 0, 1},
 676        [QUINARY_TDM_RX_0] =  { AFE_PORT_ID_QUINARY_TDM_RX,
 677                                QUINARY_TDM_RX_0, 1, 1},
 678        [QUINARY_TDM_TX_0] =  { AFE_PORT_ID_QUINARY_TDM_TX,
 679                                QUINARY_TDM_TX_0, 0, 1},
 680        [QUINARY_TDM_RX_1] =  { AFE_PORT_ID_QUINARY_TDM_RX_1,
 681                                QUINARY_TDM_RX_1, 1, 1},
 682        [QUINARY_TDM_TX_1] =  { AFE_PORT_ID_QUINARY_TDM_TX_1,
 683                                QUINARY_TDM_TX_1, 0, 1},
 684        [QUINARY_TDM_RX_2] =  { AFE_PORT_ID_QUINARY_TDM_RX_2,
 685                                QUINARY_TDM_RX_2, 1, 1},
 686        [QUINARY_TDM_TX_2] =  { AFE_PORT_ID_QUINARY_TDM_TX_2,
 687                                QUINARY_TDM_TX_2, 0, 1},
 688        [QUINARY_TDM_RX_3] =  { AFE_PORT_ID_QUINARY_TDM_RX_3,
 689                                QUINARY_TDM_RX_3, 1, 1},
 690        [QUINARY_TDM_TX_3] =  { AFE_PORT_ID_QUINARY_TDM_TX_3,
 691                                QUINARY_TDM_TX_3, 0, 1},
 692        [QUINARY_TDM_RX_4] =  { AFE_PORT_ID_QUINARY_TDM_RX_4,
 693                                QUINARY_TDM_RX_4, 1, 1},
 694        [QUINARY_TDM_TX_4] =  { AFE_PORT_ID_QUINARY_TDM_TX_4,
 695                                QUINARY_TDM_TX_4, 0, 1},
 696        [QUINARY_TDM_RX_5] =  { AFE_PORT_ID_QUINARY_TDM_RX_5,
 697                                QUINARY_TDM_RX_5, 1, 1},
 698        [QUINARY_TDM_TX_5] =  { AFE_PORT_ID_QUINARY_TDM_TX_5,
 699                                QUINARY_TDM_TX_5, 0, 1},
 700        [QUINARY_TDM_RX_6] =  { AFE_PORT_ID_QUINARY_TDM_RX_6,
 701                                QUINARY_TDM_RX_6, 1, 1},
 702        [QUINARY_TDM_TX_6] =  { AFE_PORT_ID_QUINARY_TDM_TX_6,
 703                                QUINARY_TDM_TX_6, 0, 1},
 704        [QUINARY_TDM_RX_7] =  { AFE_PORT_ID_QUINARY_TDM_RX_7,
 705                                QUINARY_TDM_RX_7, 1, 1},
 706        [QUINARY_TDM_TX_7] =  { AFE_PORT_ID_QUINARY_TDM_TX_7,
 707                                QUINARY_TDM_TX_7, 0, 1},
 708        [DISPLAY_PORT_RX] = { AFE_PORT_ID_HDMI_OVER_DP_RX,
 709                                DISPLAY_PORT_RX, 1, 1},
 710};
 711
 712static void q6afe_port_free(struct kref *ref)
 713{
 714        struct q6afe_port *port;
 715        struct q6afe *afe;
 716        unsigned long flags;
 717
 718        port = container_of(ref, struct q6afe_port, refcount);
 719        afe = port->afe;
 720        spin_lock_irqsave(&afe->port_list_lock, flags);
 721        list_del(&port->node);
 722        spin_unlock_irqrestore(&afe->port_list_lock, flags);
 723        kfree(port->scfg);
 724        kfree(port);
 725}
 726
 727static struct q6afe_port *q6afe_find_port(struct q6afe *afe, int token)
 728{
 729        struct q6afe_port *p = NULL;
 730        struct q6afe_port *ret = NULL;
 731        unsigned long flags;
 732
 733        spin_lock_irqsave(&afe->port_list_lock, flags);
 734        list_for_each_entry(p, &afe->port_list, node)
 735                if (p->token == token) {
 736                        ret = p;
 737                        kref_get(&p->refcount);
 738                        break;
 739                }
 740
 741        spin_unlock_irqrestore(&afe->port_list_lock, flags);
 742        return ret;
 743}
 744
 745static int q6afe_callback(struct apr_device *adev, struct apr_resp_pkt *data)
 746{
 747        struct q6afe *afe = dev_get_drvdata(&adev->dev);
 748        struct aprv2_ibasic_rsp_result_t *res;
 749        struct apr_hdr *hdr = &data->hdr;
 750        struct q6afe_port *port;
 751
 752        if (!data->payload_size)
 753                return 0;
 754
 755        res = data->payload;
 756        switch (hdr->opcode) {
 757        case APR_BASIC_RSP_RESULT: {
 758                if (res->status) {
 759                        dev_err(afe->dev, "cmd = 0x%x returned error = 0x%x\n",
 760                                res->opcode, res->status);
 761                }
 762                switch (res->opcode) {
 763                case AFE_PORT_CMD_SET_PARAM_V2:
 764                case AFE_PORT_CMD_DEVICE_STOP:
 765                case AFE_PORT_CMD_DEVICE_START:
 766                case AFE_SVC_CMD_SET_PARAM:
 767                        port = q6afe_find_port(afe, hdr->token);
 768                        if (port) {
 769                                port->result = *res;
 770                                wake_up(&port->wait);
 771                                kref_put(&port->refcount, q6afe_port_free);
 772                        }
 773                        break;
 774                default:
 775                        dev_err(afe->dev, "Unknown cmd 0x%x\n", res->opcode);
 776                        break;
 777                }
 778        }
 779                break;
 780        default:
 781                break;
 782        }
 783
 784        return 0;
 785}
 786
 787/**
 788 * q6afe_get_port_id() - Get port id from a given port index
 789 *
 790 * @index: port index
 791 *
 792 * Return: Will be an negative on error or valid port_id on success
 793 */
 794int q6afe_get_port_id(int index)
 795{
 796        if (index < 0 || index >= AFE_PORT_MAX)
 797                return -EINVAL;
 798
 799        return port_maps[index].port_id;
 800}
 801EXPORT_SYMBOL_GPL(q6afe_get_port_id);
 802
 803static int afe_apr_send_pkt(struct q6afe *afe, struct apr_pkt *pkt,
 804                            struct q6afe_port *port)
 805{
 806        wait_queue_head_t *wait = &port->wait;
 807        struct apr_hdr *hdr = &pkt->hdr;
 808        int ret;
 809
 810        mutex_lock(&afe->lock);
 811        port->result.opcode = 0;
 812        port->result.status = 0;
 813
 814        ret = apr_send_pkt(afe->apr, pkt);
 815        if (ret < 0) {
 816                dev_err(afe->dev, "packet not transmitted (%d)\n", ret);
 817                ret = -EINVAL;
 818                goto err;
 819        }
 820
 821        ret = wait_event_timeout(*wait, (port->result.opcode == hdr->opcode),
 822                                 msecs_to_jiffies(TIMEOUT_MS));
 823        if (!ret) {
 824                ret = -ETIMEDOUT;
 825        } else if (port->result.status > 0) {
 826                dev_err(afe->dev, "DSP returned error[%x]\n",
 827                        port->result.status);
 828                ret = -EINVAL;
 829        } else {
 830                ret = 0;
 831        }
 832
 833err:
 834        mutex_unlock(&afe->lock);
 835
 836        return ret;
 837}
 838
 839static int q6afe_port_set_param(struct q6afe_port *port, void *data,
 840                                int param_id, int module_id, int psize)
 841{
 842        struct afe_svc_cmd_set_param *param;
 843        struct afe_port_param_data_v2 *pdata;
 844        struct q6afe *afe = port->afe;
 845        struct apr_pkt *pkt;
 846        u16 port_id = port->id;
 847        int ret, pkt_size;
 848        void *p, *pl;
 849
 850        pkt_size = APR_HDR_SIZE + sizeof(*param) + sizeof(*pdata) + psize;
 851        p = kzalloc(pkt_size, GFP_KERNEL);
 852        if (!p)
 853                return -ENOMEM;
 854
 855        pkt = p;
 856        param = p + APR_HDR_SIZE;
 857        pdata = p + APR_HDR_SIZE + sizeof(*param);
 858        pl = p + APR_HDR_SIZE + sizeof(*param) + sizeof(*pdata);
 859        memcpy(pl, data, psize);
 860
 861        pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 862                                           APR_HDR_LEN(APR_HDR_SIZE),
 863                                           APR_PKT_VER);
 864        pkt->hdr.pkt_size = pkt_size;
 865        pkt->hdr.src_port = 0;
 866        pkt->hdr.dest_port = 0;
 867        pkt->hdr.token = port->token;
 868        pkt->hdr.opcode = AFE_SVC_CMD_SET_PARAM;
 869
 870        param->payload_size = sizeof(*pdata) + psize;
 871        param->payload_address_lsw = 0x00;
 872        param->payload_address_msw = 0x00;
 873        param->mem_map_handle = 0x00;
 874        pdata->module_id = module_id;
 875        pdata->param_id = param_id;
 876        pdata->param_size = psize;
 877
 878        ret = afe_apr_send_pkt(afe, pkt, port);
 879        if (ret)
 880                dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
 881                       port_id, ret);
 882
 883        kfree(pkt);
 884        return ret;
 885}
 886
 887static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data,
 888                                   int param_id, int module_id, int psize)
 889{
 890        struct afe_port_cmd_set_param_v2 *param;
 891        struct afe_port_param_data_v2 *pdata;
 892        struct q6afe *afe = port->afe;
 893        struct apr_pkt *pkt;
 894        u16 port_id = port->id;
 895        int ret, pkt_size;
 896        void *p, *pl;
 897
 898        pkt_size = APR_HDR_SIZE + sizeof(*param) + sizeof(*pdata) + psize;
 899        p = kzalloc(pkt_size, GFP_KERNEL);
 900        if (!p)
 901                return -ENOMEM;
 902
 903        pkt = p;
 904        param = p + APR_HDR_SIZE;
 905        pdata = p + APR_HDR_SIZE + sizeof(*param);
 906        pl = p + APR_HDR_SIZE + sizeof(*param) + sizeof(*pdata);
 907        memcpy(pl, data, psize);
 908
 909        pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 910                                           APR_HDR_LEN(APR_HDR_SIZE),
 911                                           APR_PKT_VER);
 912        pkt->hdr.pkt_size = pkt_size;
 913        pkt->hdr.src_port = 0;
 914        pkt->hdr.dest_port = 0;
 915        pkt->hdr.token = port->token;
 916        pkt->hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
 917
 918        param->port_id = port_id;
 919        param->payload_size = sizeof(*pdata) + psize;
 920        param->payload_address_lsw = 0x00;
 921        param->payload_address_msw = 0x00;
 922        param->mem_map_handle = 0x00;
 923        pdata->module_id = module_id;
 924        pdata->param_id = param_id;
 925        pdata->param_size = psize;
 926
 927        ret = afe_apr_send_pkt(afe, pkt, port);
 928        if (ret)
 929                dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
 930                       port_id, ret);
 931
 932        kfree(pkt);
 933        return ret;
 934}
 935
 936static int q6afe_set_lpass_clock(struct q6afe_port *port,
 937                                 struct afe_clk_cfg *cfg)
 938{
 939        return q6afe_port_set_param_v2(port, cfg,
 940                                       AFE_PARAM_ID_LPAIF_CLK_CONFIG,
 941                                       AFE_MODULE_AUDIO_DEV_INTERFACE,
 942                                       sizeof(*cfg));
 943}
 944
 945static int q6afe_set_lpass_clock_v2(struct q6afe_port *port,
 946                                 struct afe_clk_set *cfg)
 947{
 948        return q6afe_port_set_param(port, cfg, AFE_PARAM_ID_CLOCK_SET,
 949                                    AFE_MODULE_CLOCK_SET, sizeof(*cfg));
 950}
 951
 952static int q6afe_set_digital_codec_core_clock(struct q6afe_port *port,
 953                                              struct afe_digital_clk_cfg *cfg)
 954{
 955        return q6afe_port_set_param_v2(port, cfg,
 956                                       AFE_PARAM_ID_INT_DIGITAL_CDC_CLK_CONFIG,
 957                                       AFE_MODULE_AUDIO_DEV_INTERFACE,
 958                                       sizeof(*cfg));
 959}
 960
 961int q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id,
 962                          int clk_src, int clk_root,
 963                          unsigned int freq, int dir)
 964{
 965        struct afe_clk_cfg ccfg = {0,};
 966        struct afe_clk_set cset = {0,};
 967        struct afe_digital_clk_cfg dcfg = {0,};
 968        int ret;
 969
 970        switch (clk_id) {
 971        case LPAIF_DIG_CLK:
 972                dcfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG;
 973                dcfg.clk_val = freq;
 974                dcfg.clk_root = clk_root;
 975                ret = q6afe_set_digital_codec_core_clock(port, &dcfg);
 976                break;
 977        case LPAIF_BIT_CLK:
 978                ccfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG;
 979                ccfg.clk_val1 = freq;
 980                ccfg.clk_src = clk_src;
 981                ccfg.clk_root = clk_root;
 982                ccfg.clk_set_mode = Q6AFE_LPASS_MODE_CLK1_VALID;
 983                ret = q6afe_set_lpass_clock(port, &ccfg);
 984                break;
 985
 986        case LPAIF_OSR_CLK:
 987                ccfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG;
 988                ccfg.clk_val2 = freq;
 989                ccfg.clk_src = clk_src;
 990                ccfg.clk_root = clk_root;
 991                ccfg.clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID;
 992                ret = q6afe_set_lpass_clock(port, &ccfg);
 993                break;
 994        case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT ... Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR:
 995        case Q6AFE_LPASS_CLK_ID_MCLK_1 ... Q6AFE_LPASS_CLK_ID_INT_MCLK_1:
 996        case Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT ... Q6AFE_LPASS_CLK_ID_QUIN_TDM_EBIT:
 997                cset.clk_set_minor_version = AFE_API_VERSION_CLOCK_SET;
 998                cset.clk_id = clk_id;
 999                cset.clk_freq_in_hz = freq;
1000                cset.clk_attri = clk_src;
1001                cset.clk_root = clk_root;
1002                cset.enable = !!freq;
1003                ret = q6afe_set_lpass_clock_v2(port, &cset);
1004                break;
1005        default:
1006                ret = -EINVAL;
1007                break;
1008        }
1009
1010        return ret;
1011}
1012EXPORT_SYMBOL_GPL(q6afe_port_set_sysclk);
1013
1014/**
1015 * q6afe_port_stop() - Stop a afe port
1016 *
1017 * @port: Instance of port to stop
1018 *
1019 * Return: Will be an negative on packet size on success.
1020 */
1021int q6afe_port_stop(struct q6afe_port *port)
1022{
1023        struct afe_port_cmd_device_stop *stop;
1024        struct q6afe *afe = port->afe;
1025        struct apr_pkt *pkt;
1026        int port_id = port->id;
1027        int ret = 0;
1028        int index, pkt_size;
1029        void *p;
1030
1031        port_id = port->id;
1032        index = port->token;
1033        if (index < 0 || index >= AFE_PORT_MAX) {
1034                dev_err(afe->dev, "AFE port index[%d] invalid!\n", index);
1035                return -EINVAL;
1036        }
1037
1038        pkt_size = APR_HDR_SIZE + sizeof(*stop);
1039        p = kzalloc(pkt_size, GFP_KERNEL);
1040        if (!p)
1041                return -ENOMEM;
1042
1043        pkt = p;
1044        stop = p + APR_HDR_SIZE;
1045
1046        pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1047                                           APR_HDR_LEN(APR_HDR_SIZE),
1048                                           APR_PKT_VER);
1049        pkt->hdr.pkt_size = pkt_size;
1050        pkt->hdr.src_port = 0;
1051        pkt->hdr.dest_port = 0;
1052        pkt->hdr.token = index;
1053        pkt->hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
1054        stop->port_id = port_id;
1055        stop->reserved = 0;
1056
1057        ret = afe_apr_send_pkt(afe, pkt, port);
1058        if (ret)
1059                dev_err(afe->dev, "AFE close failed %d\n", ret);
1060
1061        kfree(pkt);
1062        return ret;
1063}
1064EXPORT_SYMBOL_GPL(q6afe_port_stop);
1065
1066/**
1067 * q6afe_slim_port_prepare() - Prepare slim afe port.
1068 *
1069 * @port: Instance of afe port
1070 * @cfg: SLIM configuration for the afe port
1071 *
1072 */
1073void q6afe_slim_port_prepare(struct q6afe_port *port,
1074                             struct q6afe_slim_cfg *cfg)
1075{
1076        union afe_port_config *pcfg = &port->port_cfg;
1077
1078        pcfg->slim_cfg.sb_cfg_minor_version = AFE_API_VERSION_SLIMBUS_CONFIG;
1079        pcfg->slim_cfg.sample_rate = cfg->sample_rate;
1080        pcfg->slim_cfg.bit_width = cfg->bit_width;
1081        pcfg->slim_cfg.num_channels = cfg->num_channels;
1082        pcfg->slim_cfg.data_format = cfg->data_format;
1083        pcfg->slim_cfg.shared_ch_mapping[0] = cfg->ch_mapping[0];
1084        pcfg->slim_cfg.shared_ch_mapping[1] = cfg->ch_mapping[1];
1085        pcfg->slim_cfg.shared_ch_mapping[2] = cfg->ch_mapping[2];
1086        pcfg->slim_cfg.shared_ch_mapping[3] = cfg->ch_mapping[3];
1087
1088}
1089EXPORT_SYMBOL_GPL(q6afe_slim_port_prepare);
1090
1091/**
1092 * q6afe_tdm_port_prepare() - Prepare tdm afe port.
1093 *
1094 * @port: Instance of afe port
1095 * @cfg: TDM configuration for the afe port
1096 *
1097 */
1098void q6afe_tdm_port_prepare(struct q6afe_port *port,
1099                             struct q6afe_tdm_cfg *cfg)
1100{
1101        union afe_port_config *pcfg = &port->port_cfg;
1102
1103        pcfg->tdm_cfg.tdm_cfg_minor_version = AFE_API_VERSION_TDM_CONFIG;
1104        pcfg->tdm_cfg.num_channels = cfg->num_channels;
1105        pcfg->tdm_cfg.sample_rate = cfg->sample_rate;
1106        pcfg->tdm_cfg.bit_width = cfg->bit_width;
1107        pcfg->tdm_cfg.data_format = cfg->data_format;
1108        pcfg->tdm_cfg.sync_mode = cfg->sync_mode;
1109        pcfg->tdm_cfg.sync_src = cfg->sync_src;
1110        pcfg->tdm_cfg.nslots_per_frame = cfg->nslots_per_frame;
1111
1112        pcfg->tdm_cfg.slot_width = cfg->slot_width;
1113        pcfg->tdm_cfg.slot_mask = cfg->slot_mask;
1114        port->scfg = kzalloc(sizeof(*port->scfg), GFP_KERNEL);
1115        if (!port->scfg)
1116                return;
1117
1118        port->scfg->minor_version = AFE_API_VERSION_SLOT_MAPPING_CONFIG;
1119        port->scfg->num_channels = cfg->num_channels;
1120        port->scfg->bitwidth = cfg->bit_width;
1121        port->scfg->data_align_type = cfg->data_align_type;
1122        memcpy(port->scfg->ch_mapping, cfg->ch_mapping,
1123                        sizeof(u16) * AFE_PORT_MAX_AUDIO_CHAN_CNT);
1124}
1125EXPORT_SYMBOL_GPL(q6afe_tdm_port_prepare);
1126
1127/**
1128 * q6afe_hdmi_port_prepare() - Prepare hdmi afe port.
1129 *
1130 * @port: Instance of afe port
1131 * @cfg: HDMI configuration for the afe port
1132 *
1133 */
1134void q6afe_hdmi_port_prepare(struct q6afe_port *port,
1135                             struct q6afe_hdmi_cfg *cfg)
1136{
1137        union afe_port_config *pcfg = &port->port_cfg;
1138
1139        pcfg->hdmi_multi_ch.hdmi_cfg_minor_version =
1140                                        AFE_API_VERSION_HDMI_CONFIG;
1141        pcfg->hdmi_multi_ch.datatype = cfg->datatype;
1142        pcfg->hdmi_multi_ch.channel_allocation = cfg->channel_allocation;
1143        pcfg->hdmi_multi_ch.sample_rate = cfg->sample_rate;
1144        pcfg->hdmi_multi_ch.bit_width = cfg->bit_width;
1145}
1146EXPORT_SYMBOL_GPL(q6afe_hdmi_port_prepare);
1147
1148/**
1149 * q6afe_i2s_port_prepare() - Prepare i2s afe port.
1150 *
1151 * @port: Instance of afe port
1152 * @cfg: I2S configuration for the afe port
1153 * Return: Will be an negative on error and zero on success.
1154 */
1155int q6afe_i2s_port_prepare(struct q6afe_port *port, struct q6afe_i2s_cfg *cfg)
1156{
1157        union afe_port_config *pcfg = &port->port_cfg;
1158        struct device *dev = port->afe->dev;
1159        int num_sd_lines;
1160
1161        pcfg->i2s_cfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG;
1162        pcfg->i2s_cfg.sample_rate = cfg->sample_rate;
1163        pcfg->i2s_cfg.bit_width = cfg->bit_width;
1164        pcfg->i2s_cfg.data_format = AFE_LINEAR_PCM_DATA;
1165
1166        switch (cfg->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1167        case SND_SOC_DAIFMT_CBS_CFS:
1168                pcfg->i2s_cfg.ws_src = AFE_PORT_CONFIG_I2S_WS_SRC_INTERNAL;
1169                break;
1170        case SND_SOC_DAIFMT_CBM_CFM:
1171                /* CPU is slave */
1172                pcfg->i2s_cfg.ws_src = AFE_PORT_CONFIG_I2S_WS_SRC_EXTERNAL;
1173                break;
1174        default:
1175                break;
1176        }
1177
1178        num_sd_lines = hweight_long(cfg->sd_line_mask);
1179
1180        switch (num_sd_lines) {
1181        case 0:
1182                dev_err(dev, "no line is assigned\n");
1183                return -EINVAL;
1184        case 1:
1185                switch (cfg->sd_line_mask) {
1186                case AFE_PORT_I2S_SD0_MASK:
1187                        pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD0;
1188                        break;
1189                case AFE_PORT_I2S_SD1_MASK:
1190                        pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD1;
1191                        break;
1192                case AFE_PORT_I2S_SD2_MASK:
1193                        pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD2;
1194                        break;
1195                case AFE_PORT_I2S_SD3_MASK:
1196                        pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD3;
1197                        break;
1198                default:
1199                        dev_err(dev, "Invalid SD lines\n");
1200                        return -EINVAL;
1201                }
1202                break;
1203        case 2:
1204                switch (cfg->sd_line_mask) {
1205                case AFE_PORT_I2S_SD0_1_MASK:
1206                        pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_QUAD01;
1207                        break;
1208                case AFE_PORT_I2S_SD2_3_MASK:
1209                        pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_QUAD23;
1210                        break;
1211                default:
1212                        dev_err(dev, "Invalid SD lines\n");
1213                        return -EINVAL;
1214                }
1215                break;
1216        case 3:
1217                switch (cfg->sd_line_mask) {
1218                case AFE_PORT_I2S_SD0_1_2_MASK:
1219                        pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_6CHS;
1220                        break;
1221                default:
1222                        dev_err(dev, "Invalid SD lines\n");
1223                        return -EINVAL;
1224                }
1225                break;
1226        case 4:
1227                switch (cfg->sd_line_mask) {
1228                case AFE_PORT_I2S_SD0_1_2_3_MASK:
1229                        pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_8CHS;
1230
1231                        break;
1232                default:
1233                        dev_err(dev, "Invalid SD lines\n");
1234                        return -EINVAL;
1235                }
1236                break;
1237        default:
1238                dev_err(dev, "Invalid SD lines\n");
1239                return -EINVAL;
1240        }
1241
1242        switch (cfg->num_channels) {
1243        case 1:
1244        case 2:
1245                switch (pcfg->i2s_cfg.channel_mode) {
1246                case AFE_PORT_I2S_QUAD01:
1247                case AFE_PORT_I2S_6CHS:
1248                case AFE_PORT_I2S_8CHS:
1249                        pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD0;
1250                        break;
1251                case AFE_PORT_I2S_QUAD23:
1252                                pcfg->i2s_cfg.channel_mode = AFE_PORT_I2S_SD2;
1253                        break;
1254                }
1255
1256                if (cfg->num_channels == 2)
1257                        pcfg->i2s_cfg.mono_stereo = AFE_PORT_I2S_STEREO;
1258                else
1259                        pcfg->i2s_cfg.mono_stereo = AFE_PORT_I2S_MONO;
1260
1261                break;
1262        case 3:
1263        case 4:
1264                if (pcfg->i2s_cfg.channel_mode < AFE_PORT_I2S_QUAD01) {
1265                        dev_err(dev, "Invalid Channel mode\n");
1266                        return -EINVAL;
1267                }
1268                break;
1269        case 5:
1270        case 6:
1271                if (pcfg->i2s_cfg.channel_mode < AFE_PORT_I2S_6CHS) {
1272                        dev_err(dev, "Invalid Channel mode\n");
1273                        return -EINVAL;
1274                }
1275                break;
1276        case 7:
1277        case 8:
1278                if (pcfg->i2s_cfg.channel_mode < AFE_PORT_I2S_8CHS) {
1279                        dev_err(dev, "Invalid Channel mode\n");
1280                        return -EINVAL;
1281                }
1282                break;
1283        default:
1284                break;
1285        }
1286
1287        return 0;
1288}
1289EXPORT_SYMBOL_GPL(q6afe_i2s_port_prepare);
1290
1291/**
1292 * q6afe_port_start() - Start a afe port
1293 *
1294 * @port: Instance of port to start
1295 *
1296 * Return: Will be an negative on packet size on success.
1297 */
1298int q6afe_port_start(struct q6afe_port *port)
1299{
1300        struct afe_port_cmd_device_start *start;
1301        struct q6afe *afe = port->afe;
1302        int port_id = port->id;
1303        int ret, param_id = port->cfg_type;
1304        struct apr_pkt *pkt;
1305        int pkt_size;
1306        void *p;
1307
1308        ret  = q6afe_port_set_param_v2(port, &port->port_cfg, param_id,
1309                                       AFE_MODULE_AUDIO_DEV_INTERFACE,
1310                                       sizeof(port->port_cfg));
1311        if (ret) {
1312                dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
1313                        port_id, ret);
1314                return ret;
1315        }
1316
1317        if (port->scfg) {
1318                ret  = q6afe_port_set_param_v2(port, port->scfg,
1319                                        AFE_PARAM_ID_PORT_SLOT_MAPPING_CONFIG,
1320                                        AFE_MODULE_TDM, sizeof(*port->scfg));
1321                if (ret) {
1322                        dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
1323                        port_id, ret);
1324                        return ret;
1325                }
1326        }
1327
1328        pkt_size = APR_HDR_SIZE + sizeof(*start);
1329        p = kzalloc(pkt_size, GFP_KERNEL);
1330        if (!p)
1331                return -ENOMEM;
1332
1333        pkt = p;
1334        start = p + APR_HDR_SIZE;
1335
1336        pkt->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1337                                            APR_HDR_LEN(APR_HDR_SIZE),
1338                                            APR_PKT_VER);
1339        pkt->hdr.pkt_size = pkt_size;
1340        pkt->hdr.src_port = 0;
1341        pkt->hdr.dest_port = 0;
1342        pkt->hdr.token = port->token;
1343        pkt->hdr.opcode = AFE_PORT_CMD_DEVICE_START;
1344
1345        start->port_id = port_id;
1346
1347        ret = afe_apr_send_pkt(afe, pkt, port);
1348        if (ret)
1349                dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",
1350                        port_id, ret);
1351
1352        kfree(pkt);
1353        return ret;
1354}
1355EXPORT_SYMBOL_GPL(q6afe_port_start);
1356
1357/**
1358 * q6afe_port_get_from_id() - Get port instance from a port id
1359 *
1360 * @dev: Pointer to afe child device.
1361 * @id: port id
1362 *
1363 * Return: Will be an error pointer on error or a valid afe port
1364 * on success.
1365 */
1366struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id)
1367{
1368        int port_id;
1369        struct q6afe *afe = dev_get_drvdata(dev->parent);
1370        struct q6afe_port *port;
1371        unsigned long flags;
1372        int cfg_type;
1373
1374        if (id < 0 || id >= AFE_PORT_MAX) {
1375                dev_err(dev, "AFE port token[%d] invalid!\n", id);
1376                return ERR_PTR(-EINVAL);
1377        }
1378
1379        /* if port is multiple times bind/unbind before callback finishes */
1380        port = q6afe_find_port(afe, id);
1381        if (port) {
1382                dev_err(dev, "AFE Port already open\n");
1383                return port;
1384        }
1385
1386        port_id = port_maps[id].port_id;
1387
1388        switch (port_id) {
1389        case AFE_PORT_ID_MULTICHAN_HDMI_RX:
1390        case AFE_PORT_ID_HDMI_OVER_DP_RX:
1391                cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
1392                break;
1393        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_TX:
1394        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_TX:
1395        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_TX:
1396        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_TX:
1397        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX:
1398        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_TX:
1399        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_TX:
1400        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_RX:
1401        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX:
1402        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_RX:
1403        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_RX:
1404        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_RX:
1405        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_RX:
1406        case AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_RX:
1407                cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
1408                break;
1409
1410        case AFE_PORT_ID_PRIMARY_MI2S_RX:
1411        case AFE_PORT_ID_PRIMARY_MI2S_TX:
1412        case AFE_PORT_ID_SECONDARY_MI2S_RX:
1413        case AFE_PORT_ID_SECONDARY_MI2S_TX:
1414        case AFE_PORT_ID_TERTIARY_MI2S_RX:
1415        case AFE_PORT_ID_TERTIARY_MI2S_TX:
1416        case AFE_PORT_ID_QUATERNARY_MI2S_RX:
1417        case AFE_PORT_ID_QUATERNARY_MI2S_TX:
1418                cfg_type = AFE_PARAM_ID_I2S_CONFIG;
1419                break;
1420        case AFE_PORT_ID_PRIMARY_TDM_RX ... AFE_PORT_ID_QUINARY_TDM_TX_7:
1421                cfg_type = AFE_PARAM_ID_TDM_CONFIG;
1422                break;
1423
1424        default:
1425                dev_err(dev, "Invalid port id 0x%x\n", port_id);
1426                return ERR_PTR(-EINVAL);
1427        }
1428
1429        port = kzalloc(sizeof(*port), GFP_KERNEL);
1430        if (!port)
1431                return ERR_PTR(-ENOMEM);
1432
1433        init_waitqueue_head(&port->wait);
1434
1435        port->token = id;
1436        port->id = port_id;
1437        port->afe = afe;
1438        port->cfg_type = cfg_type;
1439        kref_init(&port->refcount);
1440
1441        spin_lock_irqsave(&afe->port_list_lock, flags);
1442        list_add_tail(&port->node, &afe->port_list);
1443        spin_unlock_irqrestore(&afe->port_list_lock, flags);
1444
1445        return port;
1446
1447}
1448EXPORT_SYMBOL_GPL(q6afe_port_get_from_id);
1449
1450/**
1451 * q6afe_port_put() - Release port reference
1452 *
1453 * @port: Instance of port to put
1454 */
1455void q6afe_port_put(struct q6afe_port *port)
1456{
1457        kref_put(&port->refcount, q6afe_port_free);
1458}
1459EXPORT_SYMBOL_GPL(q6afe_port_put);
1460
1461static int q6afe_probe(struct apr_device *adev)
1462{
1463        struct q6afe *afe;
1464        struct device *dev = &adev->dev;
1465
1466        afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL);
1467        if (!afe)
1468                return -ENOMEM;
1469
1470        q6core_get_svc_api_info(adev->svc_id, &afe->ainfo);
1471        afe->apr = adev;
1472        mutex_init(&afe->lock);
1473        afe->dev = dev;
1474        INIT_LIST_HEAD(&afe->port_list);
1475        spin_lock_init(&afe->port_list_lock);
1476
1477        dev_set_drvdata(dev, afe);
1478
1479        return of_platform_populate(dev->of_node, NULL, NULL, dev);
1480}
1481
1482static int q6afe_remove(struct apr_device *adev)
1483{
1484        of_platform_depopulate(&adev->dev);
1485
1486        return 0;
1487}
1488
1489static const struct of_device_id q6afe_device_id[]  = {
1490        { .compatible = "qcom,q6afe" },
1491        {},
1492};
1493MODULE_DEVICE_TABLE(of, q6afe_device_id);
1494
1495static struct apr_driver qcom_q6afe_driver = {
1496        .probe = q6afe_probe,
1497        .remove = q6afe_remove,
1498        .callback = q6afe_callback,
1499        .driver = {
1500                .name = "qcom-q6afe",
1501                .of_match_table = of_match_ptr(q6afe_device_id),
1502
1503        },
1504};
1505
1506module_apr_driver(qcom_q6afe_driver);
1507MODULE_DESCRIPTION("Q6 Audio Front End");
1508MODULE_LICENSE("GPL v2");
1509