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