diff options
Diffstat (limited to 'sound/soc/intel/skylake/skl-messages.c')
-rw-r--r-- | sound/soc/intel/skylake/skl-messages.c | 124 |
1 files changed, 109 insertions, 15 deletions
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 4629372d7c8e..79c5089b85d6 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c | |||
@@ -72,17 +72,47 @@ static void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable) | |||
72 | skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask); | 72 | skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask); |
73 | } | 73 | } |
74 | 74 | ||
75 | static struct skl_dsp_loader_ops skl_get_loader_ops(void) | ||
76 | { | ||
77 | struct skl_dsp_loader_ops loader_ops; | ||
78 | |||
79 | memset(&loader_ops, 0, sizeof(struct skl_dsp_loader_ops)); | ||
80 | |||
81 | loader_ops.alloc_dma_buf = skl_alloc_dma_buf; | ||
82 | loader_ops.free_dma_buf = skl_free_dma_buf; | ||
83 | |||
84 | return loader_ops; | ||
85 | }; | ||
86 | |||
87 | static const struct skl_dsp_ops dsp_ops[] = { | ||
88 | { | ||
89 | .id = 0x9d70, | ||
90 | .loader_ops = skl_get_loader_ops, | ||
91 | .init = skl_sst_dsp_init, | ||
92 | .cleanup = skl_sst_dsp_cleanup | ||
93 | }, | ||
94 | }; | ||
95 | |||
96 | static int skl_get_dsp_ops(int pci_id) | ||
97 | { | ||
98 | int i; | ||
99 | |||
100 | for (i = 0; i < ARRAY_SIZE(dsp_ops); i++) { | ||
101 | if (dsp_ops[i].id == pci_id) | ||
102 | return i; | ||
103 | } | ||
104 | |||
105 | return -EINVAL; | ||
106 | } | ||
107 | |||
75 | int skl_init_dsp(struct skl *skl) | 108 | int skl_init_dsp(struct skl *skl) |
76 | { | 109 | { |
77 | void __iomem *mmio_base; | 110 | void __iomem *mmio_base; |
78 | struct hdac_ext_bus *ebus = &skl->ebus; | 111 | struct hdac_ext_bus *ebus = &skl->ebus; |
79 | struct hdac_bus *bus = ebus_to_hbus(ebus); | 112 | struct hdac_bus *bus = ebus_to_hbus(ebus); |
80 | int irq = bus->irq; | ||
81 | struct skl_dsp_loader_ops loader_ops; | 113 | struct skl_dsp_loader_ops loader_ops; |
82 | int ret; | 114 | int irq = bus->irq; |
83 | 115 | int ret, index; | |
84 | loader_ops.alloc_dma_buf = skl_alloc_dma_buf; | ||
85 | loader_ops.free_dma_buf = skl_free_dma_buf; | ||
86 | 116 | ||
87 | /* enable ppcap interrupt */ | 117 | /* enable ppcap interrupt */ |
88 | snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); | 118 | snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); |
@@ -95,8 +125,14 @@ int skl_init_dsp(struct skl *skl) | |||
95 | return -ENXIO; | 125 | return -ENXIO; |
96 | } | 126 | } |
97 | 127 | ||
98 | ret = skl_sst_dsp_init(bus->dev, mmio_base, irq, | 128 | index = skl_get_dsp_ops(skl->pci->device); |
129 | if (index < 0) | ||
130 | return -EINVAL; | ||
131 | |||
132 | loader_ops = dsp_ops[index].loader_ops(); | ||
133 | ret = dsp_ops[index].init(bus->dev, mmio_base, irq, | ||
99 | skl->fw_name, loader_ops, &skl->skl_sst); | 134 | skl->fw_name, loader_ops, &skl->skl_sst); |
135 | |||
100 | if (ret < 0) | 136 | if (ret < 0) |
101 | return ret; | 137 | return ret; |
102 | 138 | ||
@@ -106,18 +142,26 @@ int skl_init_dsp(struct skl *skl) | |||
106 | return ret; | 142 | return ret; |
107 | } | 143 | } |
108 | 144 | ||
109 | void skl_free_dsp(struct skl *skl) | 145 | int skl_free_dsp(struct skl *skl) |
110 | { | 146 | { |
111 | struct hdac_ext_bus *ebus = &skl->ebus; | 147 | struct hdac_ext_bus *ebus = &skl->ebus; |
112 | struct hdac_bus *bus = ebus_to_hbus(ebus); | 148 | struct hdac_bus *bus = ebus_to_hbus(ebus); |
113 | struct skl_sst *ctx = skl->skl_sst; | 149 | struct skl_sst *ctx = skl->skl_sst; |
150 | int index; | ||
114 | 151 | ||
115 | /* disable ppcap interrupt */ | 152 | /* disable ppcap interrupt */ |
116 | snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); | 153 | snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); |
117 | 154 | ||
118 | skl_sst_dsp_cleanup(bus->dev, ctx); | 155 | index = skl_get_dsp_ops(skl->pci->device); |
156 | if (index < 0) | ||
157 | return -EIO; | ||
158 | |||
159 | dsp_ops[index].cleanup(bus->dev, ctx); | ||
160 | |||
119 | if (ctx->dsp->addr.lpe) | 161 | if (ctx->dsp->addr.lpe) |
120 | iounmap(ctx->dsp->addr.lpe); | 162 | iounmap(ctx->dsp->addr.lpe); |
163 | |||
164 | return 0; | ||
121 | } | 165 | } |
122 | 166 | ||
123 | int skl_suspend_dsp(struct skl *skl) | 167 | int skl_suspend_dsp(struct skl *skl) |
@@ -238,9 +282,8 @@ static void skl_copy_copier_caps(struct skl_module_cfg *mconfig, | |||
238 | * Calculate the gatewat settings required for copier module, type of | 282 | * Calculate the gatewat settings required for copier module, type of |
239 | * gateway and index of gateway to use | 283 | * gateway and index of gateway to use |
240 | */ | 284 | */ |
241 | static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, | 285 | static u32 skl_get_node_id(struct skl_sst *ctx, |
242 | struct skl_module_cfg *mconfig, | 286 | struct skl_module_cfg *mconfig) |
243 | struct skl_cpr_cfg *cpr_mconfig) | ||
244 | { | 287 | { |
245 | union skl_connector_node_id node_id = {0}; | 288 | union skl_connector_node_id node_id = {0}; |
246 | union skl_ssp_dma_node ssp_node = {0}; | 289 | union skl_ssp_dma_node ssp_node = {0}; |
@@ -289,13 +332,24 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, | |||
289 | break; | 332 | break; |
290 | 333 | ||
291 | default: | 334 | default: |
292 | cpr_mconfig->gtw_cfg.node_id = SKL_NON_GATEWAY_CPR_NODE_ID; | 335 | node_id.val = 0xFFFFFFFF; |
336 | break; | ||
337 | } | ||
338 | |||
339 | return node_id.val; | ||
340 | } | ||
341 | |||
342 | static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, | ||
343 | struct skl_module_cfg *mconfig, | ||
344 | struct skl_cpr_cfg *cpr_mconfig) | ||
345 | { | ||
346 | cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); | ||
347 | |||
348 | if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) { | ||
293 | cpr_mconfig->cpr_feature_mask = 0; | 349 | cpr_mconfig->cpr_feature_mask = 0; |
294 | return; | 350 | return; |
295 | } | 351 | } |
296 | 352 | ||
297 | cpr_mconfig->gtw_cfg.node_id = node_id.val; | ||
298 | |||
299 | if (SKL_CONN_SOURCE == mconfig->hw_conn_type) | 353 | if (SKL_CONN_SOURCE == mconfig->hw_conn_type) |
300 | cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; | 354 | cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; |
301 | else | 355 | else |
@@ -307,6 +361,46 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, | |||
307 | skl_copy_copier_caps(mconfig, cpr_mconfig); | 361 | skl_copy_copier_caps(mconfig, cpr_mconfig); |
308 | } | 362 | } |
309 | 363 | ||
364 | #define DMA_CONTROL_ID 5 | ||
365 | |||
366 | int skl_dsp_set_dma_control(struct skl_sst *ctx, struct skl_module_cfg *mconfig) | ||
367 | { | ||
368 | struct skl_dma_control *dma_ctrl; | ||
369 | struct skl_i2s_config_blob config_blob; | ||
370 | struct skl_ipc_large_config_msg msg = {0}; | ||
371 | int err = 0; | ||
372 | |||
373 | |||
374 | /* | ||
375 | * if blob size is same as capablity size, then no dma control | ||
376 | * present so return | ||
377 | */ | ||
378 | if (mconfig->formats_config.caps_size == sizeof(config_blob)) | ||
379 | return 0; | ||
380 | |||
381 | msg.large_param_id = DMA_CONTROL_ID; | ||
382 | msg.param_data_size = sizeof(struct skl_dma_control) + | ||
383 | mconfig->formats_config.caps_size; | ||
384 | |||
385 | dma_ctrl = kzalloc(msg.param_data_size, GFP_KERNEL); | ||
386 | if (dma_ctrl == NULL) | ||
387 | return -ENOMEM; | ||
388 | |||
389 | dma_ctrl->node_id = skl_get_node_id(ctx, mconfig); | ||
390 | |||
391 | /* size in dwords */ | ||
392 | dma_ctrl->config_length = sizeof(config_blob) / 4; | ||
393 | |||
394 | memcpy(dma_ctrl->config_data, mconfig->formats_config.caps, | ||
395 | mconfig->formats_config.caps_size); | ||
396 | |||
397 | err = skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)dma_ctrl); | ||
398 | |||
399 | kfree(dma_ctrl); | ||
400 | |||
401 | return err; | ||
402 | } | ||
403 | |||
310 | static void skl_setup_out_format(struct skl_sst *ctx, | 404 | static void skl_setup_out_format(struct skl_sst *ctx, |
311 | struct skl_module_cfg *mconfig, | 405 | struct skl_module_cfg *mconfig, |
312 | struct skl_audio_data_format *out_fmt) | 406 | struct skl_audio_data_format *out_fmt) |