blob: f40b74b0479dc86d1baa8006ae0b1f2f8df39b19 [file] [log] [blame]
Meng Wang43bbb872018-12-10 12:32:05 +08001// SPDX-License-Identifier: GPL-2.0-only
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302/*
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08003 * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304 */
5
6#include <linux/err.h>
7#include <linux/module.h>
8#include <linux/bitops.h>
9#include <sound/control.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053010#include <dsp/q6adm-v2.h>
11#include <dsp/q6core.h>
Vignesh Kulothungan916967b2018-01-29 16:52:52 -080012#include <dsp/q6common.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053013
14#include "msm-ds2-dap-config.h"
15#include "msm-pcm-routing-v2.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053016
17
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053018/* ramp up/down for 30ms */
19#define DOLBY_SOFT_VOLUME_PERIOD 40
20/* Step value 0ms or 0us */
21#define DOLBY_SOFT_VOLUME_STEP 1000
22#define DOLBY_ADDITIONAL_RAMP_WAIT 10
23#define SOFT_VOLUME_PARAM_SIZE 3
24#define PARAM_PAYLOAD_SIZE 3
25
26enum {
27 DOLBY_SOFT_VOLUME_CURVE_LINEAR = 0,
28 DOLBY_SOFT_VOLUME_CURVE_EXP,
29 DOLBY_SOFT_VOLUME_CURVE_LOG,
30};
31
32#define VOLUME_ZERO_GAIN 0x0
33#define VOLUME_UNITY_GAIN 0x2000
34/* Wait time for module enable/disble */
35#define DOLBY_MODULE_ENABLE_PERIOD 50
36
37/* DOLBY device definitions end */
38enum {
39 DOLBY_OFF_CACHE = 0,
40 DOLBY_SPEAKER_CACHE,
41 DOLBY_HEADPHONE_CACHE,
42 DOLBY_HDMI_CACHE,
43 DOLBY_WFD_CACHE,
44 DOLBY_FM_CACHE,
45 DOLBY_MAX_CACHE,
46};
47
48enum {
49 DAP_SOFT_BYPASS = 0,
50 DAP_HARD_BYPASS,
51};
52
53enum {
54 MODULE_DISABLE = 0,
55 MODULE_ENABLE,
56};
57/* dolby param ids to/from dsp */
58static uint32_t ds2_dap_params_id[MAX_DS2_PARAMS] = {
59 DOLBY_PARAM_ID_VDHE, DOLBY_PARAM_ID_VSPE, DOLBY_PARAM_ID_DSSF,
60 DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLE,
61 DOLBY_PARAM_ID_DVMC, DOLBY_PARAM_ID_DVME, DOLBY_PARAM_ID_IENB,
62 DOLBY_PARAM_ID_IEBF, DOLBY_PARAM_ID_IEON, DOLBY_PARAM_ID_DEON,
63 DOLBY_PARAM_ID_NGON, DOLBY_PARAM_ID_GEON, DOLBY_PARAM_ID_GENB,
64 DOLBY_PARAM_ID_GEBF, DOLBY_PARAM_ID_AONB, DOLBY_PARAM_ID_AOBF,
65 DOLBY_PARAM_ID_AOBG, DOLBY_PARAM_ID_AOON, DOLBY_PARAM_ID_ARNB,
66 DOLBY_PARAM_ID_ARBF, DOLBY_PARAM_ID_PLB, DOLBY_PARAM_ID_PLMD,
67 DOLBY_PARAM_ID_DHSB, DOLBY_PARAM_ID_DHRG, DOLBY_PARAM_ID_DSSB,
68 DOLBY_PARAM_ID_DSSA, DOLBY_PARAM_ID_DVLA, DOLBY_PARAM_ID_IEBT,
69 DOLBY_PARAM_ID_IEA, DOLBY_PARAM_ID_DEA, DOLBY_PARAM_ID_DED,
70 DOLBY_PARAM_ID_GEBG, DOLBY_PARAM_ID_AOCC, DOLBY_PARAM_ID_ARBI,
71 DOLBY_PARAM_ID_ARBL, DOLBY_PARAM_ID_ARBH, DOLBY_PARAM_ID_AROD,
72 DOLBY_PARAM_ID_ARTP, DOLBY_PARAM_ID_VMON, DOLBY_PARAM_ID_VMB,
73 DOLBY_PARAM_ID_VCNB, DOLBY_PARAM_ID_VCBF, DOLBY_PARAM_ID_PREG,
74 DOLBY_PARAM_ID_VEN, DOLBY_PARAM_ID_PSTG, DOLBY_PARAM_ID_INIT_ENDP,
75};
76
77/* modifed state: 0x00000000 - Not updated
78 * > 0x00000000 && < 0x00010000
79 * Updated and not committed to DSP
80 * 0x00010001 - Updated and committed to DSP
81 * > 0x00010001 - Modified the committed value
82 */
83/* param offset */
84static uint32_t ds2_dap_params_offset[MAX_DS2_PARAMS] = {
85 DOLBY_PARAM_VDHE_OFFSET, DOLBY_PARAM_VSPE_OFFSET,
86 DOLBY_PARAM_DSSF_OFFSET, DOLBY_PARAM_DVLI_OFFSET,
87 DOLBY_PARAM_DVLO_OFFSET, DOLBY_PARAM_DVLE_OFFSET,
88 DOLBY_PARAM_DVMC_OFFSET, DOLBY_PARAM_DVME_OFFSET,
89 DOLBY_PARAM_IENB_OFFSET, DOLBY_PARAM_IEBF_OFFSET,
90 DOLBY_PARAM_IEON_OFFSET, DOLBY_PARAM_DEON_OFFSET,
91 DOLBY_PARAM_NGON_OFFSET, DOLBY_PARAM_GEON_OFFSET,
92 DOLBY_PARAM_GENB_OFFSET, DOLBY_PARAM_GEBF_OFFSET,
93 DOLBY_PARAM_AONB_OFFSET, DOLBY_PARAM_AOBF_OFFSET,
94 DOLBY_PARAM_AOBG_OFFSET, DOLBY_PARAM_AOON_OFFSET,
95 DOLBY_PARAM_ARNB_OFFSET, DOLBY_PARAM_ARBF_OFFSET,
96 DOLBY_PARAM_PLB_OFFSET, DOLBY_PARAM_PLMD_OFFSET,
97 DOLBY_PARAM_DHSB_OFFSET, DOLBY_PARAM_DHRG_OFFSET,
98 DOLBY_PARAM_DSSB_OFFSET, DOLBY_PARAM_DSSA_OFFSET,
99 DOLBY_PARAM_DVLA_OFFSET, DOLBY_PARAM_IEBT_OFFSET,
100 DOLBY_PARAM_IEA_OFFSET, DOLBY_PARAM_DEA_OFFSET,
101 DOLBY_PARAM_DED_OFFSET, DOLBY_PARAM_GEBG_OFFSET,
102 DOLBY_PARAM_AOCC_OFFSET, DOLBY_PARAM_ARBI_OFFSET,
103 DOLBY_PARAM_ARBL_OFFSET, DOLBY_PARAM_ARBH_OFFSET,
104 DOLBY_PARAM_AROD_OFFSET, DOLBY_PARAM_ARTP_OFFSET,
105 DOLBY_PARAM_VMON_OFFSET, DOLBY_PARAM_VMB_OFFSET,
106 DOLBY_PARAM_VCNB_OFFSET, DOLBY_PARAM_VCBF_OFFSET,
107 DOLBY_PARAM_PREG_OFFSET, DOLBY_PARAM_VEN_OFFSET,
108 DOLBY_PARAM_PSTG_OFFSET, DOLBY_PARAM_INT_ENDP_OFFSET,
109};
110/* param_length */
111static uint32_t ds2_dap_params_length[MAX_DS2_PARAMS] = {
112 DOLBY_PARAM_VDHE_LENGTH, DOLBY_PARAM_VSPE_LENGTH,
113 DOLBY_PARAM_DSSF_LENGTH, DOLBY_PARAM_DVLI_LENGTH,
114 DOLBY_PARAM_DVLO_LENGTH, DOLBY_PARAM_DVLE_LENGTH,
115 DOLBY_PARAM_DVMC_LENGTH, DOLBY_PARAM_DVME_LENGTH,
116 DOLBY_PARAM_IENB_LENGTH, DOLBY_PARAM_IEBF_LENGTH,
117 DOLBY_PARAM_IEON_LENGTH, DOLBY_PARAM_DEON_LENGTH,
118 DOLBY_PARAM_NGON_LENGTH, DOLBY_PARAM_GEON_LENGTH,
119 DOLBY_PARAM_GENB_LENGTH, DOLBY_PARAM_GEBF_LENGTH,
120 DOLBY_PARAM_AONB_LENGTH, DOLBY_PARAM_AOBF_LENGTH,
121 DOLBY_PARAM_AOBG_LENGTH, DOLBY_PARAM_AOON_LENGTH,
122 DOLBY_PARAM_ARNB_LENGTH, DOLBY_PARAM_ARBF_LENGTH,
123 DOLBY_PARAM_PLB_LENGTH, DOLBY_PARAM_PLMD_LENGTH,
124 DOLBY_PARAM_DHSB_LENGTH, DOLBY_PARAM_DHRG_LENGTH,
125 DOLBY_PARAM_DSSB_LENGTH, DOLBY_PARAM_DSSA_LENGTH,
126 DOLBY_PARAM_DVLA_LENGTH, DOLBY_PARAM_IEBT_LENGTH,
127 DOLBY_PARAM_IEA_LENGTH, DOLBY_PARAM_DEA_LENGTH,
128 DOLBY_PARAM_DED_LENGTH, DOLBY_PARAM_GEBG_LENGTH,
129 DOLBY_PARAM_AOCC_LENGTH, DOLBY_PARAM_ARBI_LENGTH,
130 DOLBY_PARAM_ARBL_LENGTH, DOLBY_PARAM_ARBH_LENGTH,
131 DOLBY_PARAM_AROD_LENGTH, DOLBY_PARAM_ARTP_LENGTH,
132 DOLBY_PARAM_VMON_LENGTH, DOLBY_PARAM_VMB_LENGTH,
133 DOLBY_PARAM_VCNB_LENGTH, DOLBY_PARAM_VCBF_LENGTH,
134 DOLBY_PARAM_PREG_LENGTH, DOLBY_PARAM_VEN_LENGTH,
135 DOLBY_PARAM_PSTG_LENGTH, DOLBY_PARAM_INT_ENDP_LENGTH,
136};
137
138struct ds2_dap_params_s {
139 int32_t params_val[TOTAL_LENGTH_DS2_PARAM];
140 int32_t dap_params_modified[MAX_DS2_PARAMS];
141};
142
143struct audio_rx_cal_data {
144 char aud_proc_data[AUD_PROC_BLOCK_SIZE];
145 int32_t aud_proc_size;
146 char aud_vol_data[AUD_VOL_BLOCK_SIZE];
147 int32_t aud_vol_size;
148};
149
150static struct ds2_dap_params_s ds2_dap_params[DOLBY_MAX_CACHE];
151
152struct ds2_device_mapping {
153 int32_t device_id; /* audio_out_... */
154 int port_id; /* afe port. constant for a target variant. routing-v2*/
155 /*Only one Dolby COPP for a specific port*/
156 int copp_idx; /* idx for the copp port on which ds2 is active */
157 int cache_dev; /* idx to a shared parameter array dependent on device*/
158 uint32_t stream_ref_count;
159 bool active;
160 void *cal_data;
161};
162
163static struct ds2_device_mapping dev_map[DS2_DEVICES_ALL];
164
165struct ds2_dap_params_states_s {
166 bool use_cache;
167 bool dap_bypass;
168 bool dap_bypass_type;
169 bool node_opened;
170 int32_t device;
171 bool custom_stereo_onoff;
172};
173
174static struct ds2_dap_params_states_s ds2_dap_params_states = {true, false,
175 false, DEVICE_NONE};
176
177static int all_supported_devices = EARPIECE|SPEAKER|WIRED_HEADSET|
178 WIRED_HEADPHONE|BLUETOOTH_SCO|AUX_DIGITAL|
179 ANLG_DOCK_HEADSET|DGTL_DOCK_HEADSET|
180 REMOTE_SUBMIX|ANC_HEADSET|ANC_HEADPHONE|
181 PROXY|FM|FM_TX|DEVICE_NONE|
182 BLUETOOTH_SCO_HEADSET|BLUETOOTH_SCO_CARKIT;
183
184
185static void msm_ds2_dap_check_and_update_ramp_wait(int port_id, int copp_idx,
186 int *ramp_wait)
187{
188
189 int32_t *update_params_value = NULL;
190 uint32_t params_length = SOFT_VOLUME_PARAM_SIZE * sizeof(uint32_t);
191 uint32_t param_payload_len = PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800192 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530193 int rc = 0;
194
195 update_params_value = kzalloc(params_length + param_payload_len,
196 GFP_KERNEL);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800197 if (!update_params_value) {
198 pr_err("%s: params memory alloc failed\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530199 goto end;
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800200 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530201
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800202 memset(&param_hdr, 0, sizeof(param_hdr));
203 param_hdr.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
204 param_hdr.instance_id = INSTANCE_ID_0;
205 param_hdr.param_id = AUDPROC_PARAM_ID_SOFT_VOL_STEPPING_PARAMETERS;
206 param_hdr.param_size = params_length + param_payload_len;
207 rc = adm_get_pp_params(port_id, copp_idx, ADM_CLIENT_ID_DEFAULT, NULL,
208 &param_hdr, (char *) update_params_value);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530209 if (rc == 0) {
210 pr_debug("%s: params_value [0x%x, 0x%x, 0x%x]\n",
211 __func__, update_params_value[0],
212 update_params_value[1],
213 update_params_value[2]);
214 *ramp_wait = update_params_value[0];
215 }
216end:
217 kfree(update_params_value);
218 /*
219 * No error returned as we do not need to error out from dap on/dap
220 * bypass. The default ramp parameter will be used to wait during
221 * ramp down.
222 */
223}
224
225static int msm_ds2_dap_set_vspe_vdhe(int dev_map_idx,
226 bool is_custom_stereo_enabled)
227{
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800228 u8 *packed_param_data = NULL;
229 u8 *param_data = NULL;
230 struct param_hdr_v3 param_hdr;
231 u32 packed_param_size = 0;
232 u32 param_size = 0;
233 int cdev;
234 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530235
236 if (dev_map_idx < 0 || dev_map_idx >= DS2_DEVICES_ALL) {
237 pr_err("%s: invalid dev map index %d\n", __func__, dev_map_idx);
238 rc = -EINVAL;
239 goto end;
240 }
241
242 if (dev_map[dev_map_idx].port_id == DOLBY_INVALID_PORT_ID) {
243 pr_err("%s: Invalid port id\n", __func__);
244 rc = -EINVAL;
245 goto end;
246 }
247
248 if ((dev_map[dev_map_idx].copp_idx < 0) ||
249 (dev_map[dev_map_idx].copp_idx >= MAX_COPPS_PER_PORT)) {
250 pr_err("%s: Invalid copp_idx\n", __func__);
251 rc = -EINVAL;
252 goto end;
253 }
254
255 if ((dev_map[dev_map_idx].port_id != SLIMBUS_0_RX) &&
256 (dev_map[dev_map_idx].port_id != RT_PROXY_PORT_001_RX)) {
257 pr_debug("%s:No Custom stereo for port:0x%x\n",
258 __func__, dev_map[dev_map_idx].port_id);
259 goto end;
260 }
261
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800262 /* Allocate the max space needed */
263 packed_param_size = (TOTAL_LENGTH_DOLBY_PARAM * sizeof(uint32_t)) +
264 (2 * sizeof(union param_hdrs));
265 packed_param_data = kzalloc(packed_param_size, GFP_KERNEL);
266 if (!packed_param_data)
267 return -ENOMEM;
268
269 packed_param_size = 0;
270 memset(&param_hdr, 0, sizeof(param_hdr));
271
272 /* Set common values */
273 cdev = dev_map[dev_map_idx].cache_dev;
274 param_hdr.module_id = DOLBY_BUNDLE_MODULE_ID;
275 param_hdr.instance_id = INSTANCE_ID_0;
276
277 /* Pack VDHE header + data */
278 param_hdr.param_id = DOLBY_PARAM_ID_VDHE;
279 param_size = DOLBY_PARAM_VDHE_LENGTH * sizeof(uint32_t);
280 param_hdr.param_size = param_size;
281
282 if (is_custom_stereo_enabled)
283 param_data = NULL;
284 else
285 param_data = (u8 *) &ds2_dap_params[cdev]
286 .params_val[DOLBY_PARAM_VDHE_OFFSET];
287
288 rc = q6common_pack_pp_params(packed_param_data, &param_hdr, param_data,
289 &param_size);
290 if (rc) {
291 pr_err("%s: Failed to pack params for dolby vdhe, error %d\n",
292 __func__, rc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530293 goto end;
294 }
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800295 packed_param_size += param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530296
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800297 /* Pack VSPE header + data */
298 param_hdr.param_id = DOLBY_PARAM_ID_VSPE;
299 param_size = DOLBY_PARAM_VSPE_LENGTH * sizeof(uint32_t);
300 param_hdr.param_size = param_size;
301
302 if (is_custom_stereo_enabled)
303 param_data = NULL;
304 else
305 param_data = (u8 *) &ds2_dap_params[cdev]
306 .params_val[DOLBY_PARAM_VSPE_OFFSET];
307
308 rc = q6common_pack_pp_params(packed_param_data + packed_param_size,
309 &param_hdr, param_data, &param_size);
310 if (rc) {
311 pr_err("%s: Failed to pack params for dolby vspe, error %d\n",
312 __func__, rc);
313 goto end;
314 }
315 packed_param_size += param_size;
316
317 rc = adm_set_pp_params(dev_map[dev_map_idx].port_id,
318 dev_map[dev_map_idx].copp_idx, NULL,
319 packed_param_data, packed_param_size);
320 if (rc) {
321 pr_err("%s: send vdhe/vspe params failed with rc=%d\n",
322 __func__, rc);
323 rc = -EINVAL;
324 goto end;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530325 }
326end:
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800327 kfree(packed_param_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530328 return rc;
329}
330
331int qti_set_custom_stereo_on(int port_id, int copp_idx,
332 bool is_custom_stereo_on)
333{
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800334 struct custom_stereo_param custom_stereo;
335 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530336 uint16_t op_FL_ip_FL_weight;
337 uint16_t op_FL_ip_FR_weight;
338 uint16_t op_FR_ip_FL_weight;
339 uint16_t op_FR_ip_FR_weight;
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800340 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530341
342 if ((port_id != SLIMBUS_0_RX) &&
343 (port_id != RT_PROXY_PORT_001_RX)) {
344 pr_debug("%s:No Custom stereo for port:0x%x\n",
345 __func__, port_id);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800346 return 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530347 }
348
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800349 memset(&custom_stereo, 0, sizeof(custom_stereo));
350 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530351 pr_debug("%s: port 0x%x, copp_idx %d, is_custom_stereo_on %d\n",
352 __func__, port_id, copp_idx, is_custom_stereo_on);
353 if (is_custom_stereo_on) {
354 op_FL_ip_FL_weight =
355 Q14_GAIN_ZERO_POINT_FIVE;
356 op_FL_ip_FR_weight =
357 Q14_GAIN_ZERO_POINT_FIVE;
358 op_FR_ip_FL_weight =
359 Q14_GAIN_ZERO_POINT_FIVE;
360 op_FR_ip_FR_weight =
361 Q14_GAIN_ZERO_POINT_FIVE;
362 } else {
363 op_FL_ip_FL_weight = Q14_GAIN_UNITY;
364 op_FL_ip_FR_weight = 0;
365 op_FR_ip_FL_weight = 0;
366 op_FR_ip_FR_weight = Q14_GAIN_UNITY;
367 }
368
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800369 param_hdr.module_id = MTMX_MODULE_ID_DEFAULT_CHMIXER;
370 param_hdr.instance_id = INSTANCE_ID_0;
371 param_hdr.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
372 param_hdr.param_size = sizeof(struct custom_stereo_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530373
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530374 /* index is 32-bit param in little endian*/
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800375 custom_stereo.index = CUSTOM_STEREO_INDEX_PARAM;
376 custom_stereo.reserved = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530377 /* for stereo mixing num out ch*/
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800378 custom_stereo.num_out_ch = CUSTOM_STEREO_NUM_OUT_CH;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530379 /* for stereo mixing num in ch*/
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800380 custom_stereo.num_in_ch = CUSTOM_STEREO_NUM_IN_CH;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530381
382 /* Out ch map FL/FR*/
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800383 custom_stereo.out_fl = PCM_CHANNEL_FL;
384 custom_stereo.out_fr = PCM_CHANNEL_FR;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530385
386 /* In ch map FL/FR*/
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800387 custom_stereo.in_fl = PCM_CHANNEL_FL;
388 custom_stereo.in_fr = PCM_CHANNEL_FR;
389
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530390 /* weighting coefficients as name suggests,
391 * mixing will be done according to these coefficients
392 */
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800393 custom_stereo.op_FL_ip_FL_weight = op_FL_ip_FL_weight;
394 custom_stereo.op_FL_ip_FR_weight = op_FL_ip_FR_weight;
395 custom_stereo.op_FR_ip_FL_weight = op_FR_ip_FL_weight;
396 custom_stereo.op_FR_ip_FR_weight = op_FR_ip_FR_weight;
397 rc = adm_pack_and_set_one_pp_param(port_id, copp_idx, param_hdr,
398 (u8 *) &custom_stereo);
399 if (rc) {
400 pr_err("%s: send params failed rc=%d\n", __func__, rc);
401 return -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530402 }
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800403
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530404 return 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530405}
406static int dap_set_custom_stereo_onoff(int dev_map_idx,
407 bool is_custom_stereo_enabled)
408{
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800409 uint32_t enable = is_custom_stereo_enabled ? 1 : 0;
410 struct param_hdr_v3 param_hdr;
411 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530412
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530413 if ((dev_map[dev_map_idx].port_id != SLIMBUS_0_RX) &&
414 (dev_map[dev_map_idx].port_id != RT_PROXY_PORT_001_RX)) {
415 pr_debug("%s:No Custom stereo for port:0x%x\n",
416 __func__, dev_map[dev_map_idx].port_id);
417 goto end;
418 }
419
420 if ((dev_map[dev_map_idx].copp_idx < 0) ||
421 (dev_map[dev_map_idx].copp_idx >= MAX_COPPS_PER_PORT)) {
422 rc = -EINVAL;
423 goto end;
424 }
425
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800426 memset(&param_hdr, 0, sizeof(param_hdr));
427
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530428 /* DAP custom stereo */
429 msm_ds2_dap_set_vspe_vdhe(dev_map_idx,
430 is_custom_stereo_enabled);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800431 param_hdr.module_id = DOLBY_BUNDLE_MODULE_ID;
432 param_hdr.instance_id = INSTANCE_ID_0;
433 param_hdr.param_id = DOLBY_ENABLE_CUSTOM_STEREO;
434 param_hdr.param_size = sizeof(enable);
435
436 rc = adm_pack_and_set_one_pp_param(dev_map[dev_map_idx].port_id,
437 dev_map[dev_map_idx].copp_idx,
438 param_hdr, (u8 *) &enable);
439 if (rc) {
440 pr_err("%s: set custom stereo enable failed with rc=%d\n",
441 __func__, rc);
442 rc = -EINVAL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530443 }
444end:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530445 return rc;
446
447}
448
449
450static int set_custom_stereo_onoff(int dev_map_idx,
451 bool is_custom_stereo_enabled)
452{
453 int rc = 0;
454
455 pr_debug("%s: map index %d, custom stereo %d\n", __func__, dev_map_idx,
456 is_custom_stereo_enabled);
457
458 if (dev_map_idx < 0 || dev_map_idx >= DS2_DEVICES_ALL) {
459 pr_err("%s: invalid dev map index %d\n", __func__, dev_map_idx);
460 rc = -EINVAL;
461 goto end;
462 }
463
464 if (dev_map[dev_map_idx].port_id == DOLBY_INVALID_PORT_ID) {
465 pr_err("%s: invalid port id\n", __func__);
466 rc = -EINVAL;
467 goto end;
468 }
469
470 if ((dev_map[dev_map_idx].copp_idx < 0) ||
471 (dev_map[dev_map_idx].copp_idx >= MAX_COPPS_PER_PORT)) {
472 pr_err("%s: invalid copp idx\n", __func__);
473 rc = -EINVAL;
474 goto end;
475 }
476
477 if (ds2_dap_params_states.dap_bypass == true &&
478 ds2_dap_params_states.dap_bypass_type == DAP_HARD_BYPASS) {
479
480 rc = qti_set_custom_stereo_on(dev_map[dev_map_idx].port_id,
481 dev_map[dev_map_idx].copp_idx,
482 is_custom_stereo_enabled);
483 if (rc < 0) {
484 pr_err("%s:qti_set_custom_stereo_on_copp failed C.S %d",
485 __func__, is_custom_stereo_enabled);
486 }
487 goto end;
488
489 }
490
491 if (ds2_dap_params_states.dap_bypass == false) {
492 rc = dap_set_custom_stereo_onoff(dev_map_idx,
493 is_custom_stereo_enabled);
494 if (rc < 0) {
495 pr_err("%s:qti_set_custom_stereo_on_copp failed C.S %d",
496 __func__, is_custom_stereo_enabled);
497 }
498 goto end;
499 }
500end:
501 return rc;
502}
503
504static int msm_ds2_dap_alloc_and_store_cal_data(int dev_map_idx, int path,
505 int perf_mode)
506{
507 int rc = 0;
508 struct audio_rx_cal_data *aud_cal_data;
509
510 pr_debug("%s: path %d, perf_mode %d, dev_map_idx %d\n",
511 __func__, path, perf_mode, dev_map_idx);
512
513 if (dev_map_idx < 0 || dev_map_idx >= DS2_DEVICES_ALL) {
514 pr_err("%s: invalid dev map index %d\n", __func__, dev_map_idx);
515 rc = -EINVAL;
516 goto end;
517 }
518
519 aud_cal_data = kzalloc(sizeof(struct audio_rx_cal_data), GFP_KERNEL);
520 if (!aud_cal_data) {
521 rc = -ENOMEM;
522 goto end;
523 }
524
525 rc = adm_store_cal_data(dev_map[dev_map_idx].port_id,
526 dev_map[dev_map_idx].copp_idx, path, perf_mode,
527 ADM_AUDPROC_CAL, aud_cal_data->aud_proc_data,
528 &aud_cal_data->aud_proc_size);
529 if (rc < 0) {
530 pr_err("%s: store cal data err %d\n", __func__, rc);
531 kfree(aud_cal_data);
532 goto end;
533 }
534
535 rc = adm_store_cal_data(dev_map[dev_map_idx].port_id,
536 dev_map[dev_map_idx].copp_idx, path, perf_mode,
537 ADM_AUDVOL_CAL, aud_cal_data->aud_vol_data,
538 &aud_cal_data->aud_vol_size);
539 if (rc < 0) {
540 pr_err("%s: store cal data err %d\n", __func__, rc);
541 kfree(aud_cal_data);
542 goto end;
543 }
544
545 dev_map[dev_map_idx].cal_data = (void *)aud_cal_data;
546
547end:
548 pr_debug("%s: ret %d\n", __func__, rc);
549 return rc;
550}
551
552static int msm_ds2_dap_free_cal_data(int dev_map_idx)
553{
554 int rc = 0;
555 struct audio_rx_cal_data *aud_cal_data;
556
557 pr_debug("%s: dev_map_idx %d\n", __func__, dev_map_idx);
558 if (dev_map_idx < 0 || dev_map_idx >= DS2_DEVICES_ALL) {
559 pr_err("%s: invalid dev map index %d\n", __func__, dev_map_idx);
560 rc = -EINVAL;
561 goto end;
562 }
563 aud_cal_data = (struct audio_rx_cal_data *)
564 dev_map[dev_map_idx].cal_data;
565 kfree(aud_cal_data);
566 dev_map[dev_map_idx].cal_data = NULL;
567
568end:
569 return rc;
570}
571
572static int msm_ds2_dap_send_cal_data(int dev_map_idx)
573{
574 int rc = 0;
575 struct audio_rx_cal_data *aud_cal_data = NULL;
576
577 pr_debug("%s: devmap index %d\n", __func__, dev_map_idx);
578 if (dev_map_idx < 0 || dev_map_idx >= DS2_DEVICES_ALL) {
579 pr_err("%s: invalid dev map index %d\n", __func__, dev_map_idx);
580 rc = -EINVAL;
581 goto end;
582 }
583
584 if (dev_map[dev_map_idx].cal_data == NULL) {
585 pr_err("%s: No valid calibration data stored for idx %d\n",
586 __func__, dev_map_idx);
587 rc = -EINVAL;
588 goto end;
589 }
590
591 /* send aud proc cal */
592 aud_cal_data = (struct audio_rx_cal_data *)
593 dev_map[dev_map_idx].cal_data;
594 rc = adm_send_calibration(dev_map[dev_map_idx].port_id,
595 dev_map[dev_map_idx].copp_idx,
596 ADM_PATH_PLAYBACK, 0,
597 ADM_AUDPROC_CAL,
598 aud_cal_data->aud_proc_data,
599 aud_cal_data->aud_proc_size);
600 if (rc < 0) {
601 pr_err("%s: adm_send_calibration failed %d\n", __func__, rc);
602 goto end;
603 }
604
605 /* send aud volume cal*/
606 rc = adm_send_calibration(dev_map[dev_map_idx].port_id,
607 dev_map[dev_map_idx].copp_idx,
608 ADM_PATH_PLAYBACK, 0,
609 ADM_AUDVOL_CAL,
610 aud_cal_data->aud_vol_data,
611 aud_cal_data->aud_vol_size);
612 if (rc < 0)
613 pr_err("%s: adm_send_calibration failed %d\n", __func__, rc);
614end:
615 pr_debug("%s: return %d\n", __func__, rc);
616 return rc;
617}
618
619static inline int msm_ds2_dap_can_enable_module(int32_t module_id)
620{
621 if (module_id == MTMX_MODULE_ID_DEFAULT_CHMIXER ||
622 module_id == AUDPROC_MODULE_ID_RESAMPLER ||
623 module_id == AUDPROC_MODULE_ID_VOL_CTRL) {
624 return false;
625 }
626 return true;
627}
628
629static int msm_ds2_dap_init_modules_in_topology(int dev_map_idx)
630{
631 int rc = 0, i = 0, port_id, copp_idx;
632 /* Account for 32 bit integer allocation */
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800633 int32_t param_sz =
634 (ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH / sizeof(uint32_t));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530635 int32_t *update_param_val = NULL;
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800636 struct module_instance_info mod_inst_info;
637 int mod_inst_info_sz = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530638
639 if (dev_map_idx < 0 || dev_map_idx >= DS2_DEVICES_ALL) {
640 pr_err("%s: invalid dev map index %d\n", __func__, dev_map_idx);
641 rc = -EINVAL;
642 goto end;
643 }
644
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800645 memset(&mod_inst_info, 0, sizeof(mod_inst_info));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530646 port_id = dev_map[dev_map_idx].port_id;
647 copp_idx = dev_map[dev_map_idx].copp_idx;
648 pr_debug("%s: port_id 0x%x copp_idx %d\n", __func__, port_id, copp_idx);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800649 update_param_val =
650 kzalloc(ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH, GFP_KERNEL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530651 if (!update_param_val) {
652 pr_err("%s, param memory alloc failed\n", __func__);
653 rc = -ENOMEM;
654 goto end;
655 }
656
657 if (!ds2_dap_params_states.dap_bypass) {
658 /* get modules from dsp */
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800659 rc = adm_get_pp_topo_module_list_v2(
660 port_id, copp_idx,
661 ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH,
662 update_param_val);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530663 if (rc < 0) {
664 pr_err("%s:topo list port %d, err %d,copp_idx %d\n",
665 __func__, port_id, copp_idx, rc);
666 goto end;
667 }
668
669 if (update_param_val[0] > (param_sz - 1)) {
670 pr_err("%s:max modules exp/ret [%d: %d]\n",
671 __func__, (param_sz - 1),
672 update_param_val[0]);
673 rc = -EINVAL;
674 goto end;
675 }
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800676
677 mod_inst_info_sz = sizeof(struct module_instance_info) /
678 sizeof(uint32_t);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530679 /* Turn off modules */
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800680 for (i = 1; i < update_param_val[0] * mod_inst_info_sz;
681 i += mod_inst_info_sz) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530682 if (!msm_ds2_dap_can_enable_module(
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800683 update_param_val[i]) ||
684 (update_param_val[i] == DS2_MODULE_ID)) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530685 pr_debug("%s: Do not enable/disable %d\n",
686 __func__, update_param_val[i]);
687 continue;
688 }
689
690 pr_debug("%s: param disable %d\n",
691 __func__, update_param_val[i]);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800692 memcpy(&mod_inst_info, &update_param_val[i],
693 sizeof(mod_inst_info));
694 adm_param_enable_v2(port_id, copp_idx,
695 mod_inst_info,
696 MODULE_DISABLE);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530697 }
698 } else {
699 msm_ds2_dap_send_cal_data(dev_map_idx);
700
701 }
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800702
703 mod_inst_info.module_id = DS2_MODULE_ID;
704 mod_inst_info.instance_id = INSTANCE_ID_0;
705 adm_param_enable_v2(port_id, copp_idx, mod_inst_info,
706 !ds2_dap_params_states.dap_bypass);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530707end:
708 kfree(update_param_val);
709 return rc;
710}
711
712static bool msm_ds2_dap_check_is_param_modified(int32_t *dap_params_modified,
713 int32_t idx, int32_t commit)
714{
715 if ((dap_params_modified[idx] == 0) ||
716 (commit &&
717 ((dap_params_modified[idx] & 0x00010000) &&
718 ((dap_params_modified[idx] & 0x0000FFFF) <= 1)))) {
719 pr_debug("%s: not modified at idx %d\n", __func__, idx);
720 return false;
721 }
722 pr_debug("%s: modified at idx %d\n", __func__, idx);
723 return true;
724}
725
726static int msm_ds2_dap_map_device_to_dolby_cache_devices(int32_t device_id)
727{
728 int32_t cache_dev = -1;
729
730 switch (device_id) {
731 case DEVICE_NONE:
732 cache_dev = DOLBY_OFF_CACHE;
733 break;
734 case EARPIECE:
735 case SPEAKER:
736 cache_dev = DOLBY_SPEAKER_CACHE;
737 break;
738 case WIRED_HEADSET:
739 case WIRED_HEADPHONE:
740 case ANLG_DOCK_HEADSET:
741 case DGTL_DOCK_HEADSET:
742 case ANC_HEADSET:
743 case ANC_HEADPHONE:
744 case BLUETOOTH_SCO:
745 case BLUETOOTH_SCO_HEADSET:
746 case BLUETOOTH_SCO_CARKIT:
747 cache_dev = DOLBY_HEADPHONE_CACHE;
748 break;
749 case FM:
750 case FM_TX:
751 cache_dev = DOLBY_FM_CACHE;
752 break;
753 case AUX_DIGITAL:
754 cache_dev = DOLBY_HDMI_CACHE;
755 break;
756 case PROXY:
757 case REMOTE_SUBMIX:
758 cache_dev = DOLBY_WFD_CACHE;
759 break;
760 default:
761 pr_err("%s: invalid cache device\n", __func__);
762 }
763 pr_debug("%s: cache device %d\n", __func__, cache_dev);
764 return cache_dev;
765}
766
767static int msm_ds2_dap_update_num_devices(struct dolby_param_data *dolby_data,
768 int32_t *num_device, int32_t *dev_arr,
769 int32_t array_size)
770{
771 int32_t idx = 0;
772 int supported_devices = 0;
773
774 if (!array_size) {
775 pr_err("%s: array size zero\n", __func__);
776 return -EINVAL;
777 }
778
779 if (dolby_data->device_id == DEVICE_OUT_ALL ||
780 dolby_data->device_id == DEVICE_OUT_DEFAULT)
781 supported_devices = all_supported_devices;
782 else
783 supported_devices = dolby_data->device_id;
784
785 if ((idx < array_size) && (supported_devices & EARPIECE))
786 dev_arr[idx++] = EARPIECE;
787 if ((idx < array_size) && (supported_devices & SPEAKER))
788 dev_arr[idx++] = SPEAKER;
789 if ((idx < array_size) && (supported_devices & WIRED_HEADSET))
790 dev_arr[idx++] = WIRED_HEADSET;
791 if ((idx < array_size) && (supported_devices & WIRED_HEADPHONE))
792 dev_arr[idx++] = WIRED_HEADPHONE;
793 if ((idx < array_size) && (supported_devices & BLUETOOTH_SCO))
794 dev_arr[idx++] = BLUETOOTH_SCO;
795 if ((idx < array_size) && (supported_devices & BLUETOOTH_SCO_CARKIT))
796 dev_arr[idx++] = BLUETOOTH_SCO_CARKIT;
797 if ((idx < array_size) && (supported_devices & BLUETOOTH_SCO_HEADSET))
798 dev_arr[idx++] = BLUETOOTH_SCO_HEADSET;
799 if ((idx < array_size) && (supported_devices & AUX_DIGITAL))
800 dev_arr[idx++] = AUX_DIGITAL;
801 if ((idx < array_size) && (supported_devices & ANLG_DOCK_HEADSET))
802 dev_arr[idx++] = ANLG_DOCK_HEADSET;
803 if ((idx < array_size) && (supported_devices & DGTL_DOCK_HEADSET))
804 dev_arr[idx++] = DGTL_DOCK_HEADSET;
805 if ((idx < array_size) && (supported_devices & REMOTE_SUBMIX))
806 dev_arr[idx++] = REMOTE_SUBMIX;
807 if ((idx < array_size) && (supported_devices & ANC_HEADSET))
808 dev_arr[idx++] = ANC_HEADSET;
809 if ((idx < array_size) && (supported_devices & ANC_HEADPHONE))
810 dev_arr[idx++] = ANC_HEADPHONE;
811 if ((idx < array_size) && (supported_devices & PROXY))
812 dev_arr[idx++] = PROXY;
813 if ((idx < array_size) && (supported_devices & FM))
814 dev_arr[idx++] = FM;
815 if ((idx < array_size) && (supported_devices & FM_TX))
816 dev_arr[idx++] = FM_TX;
817 /* CHECK device none separately */
818 if ((idx < array_size) && (supported_devices == DEVICE_NONE))
819 dev_arr[idx++] = DEVICE_NONE;
820 pr_debug("%s: dev id 0x%x, idx %d\n", __func__,
821 supported_devices, idx);
822 *num_device = idx;
823 return 0;
824}
825
826static int msm_ds2_dap_get_port_id(
827 int32_t device_id, int32_t be_id)
828{
829 struct msm_pcm_routing_bdai_data bedais;
830 int port_id = DOLBY_INVALID_PORT_ID;
831 int port_type = 0;
832
833 if (be_id < 0) {
834 port_id = -1;
835 goto end;
836 }
837
838 msm_pcm_routing_get_bedai_info(be_id, &bedais);
839 pr_debug("%s: be port_id %d\n", __func__, bedais.port_id);
840 port_id = bedais.port_id;
841 port_type = afe_get_port_type(bedais.port_id);
842 if (port_type != MSM_AFE_PORT_TYPE_RX)
843 port_id = DOLBY_INVALID_PORT_ID;
844end:
845 pr_debug("%s: device_id 0x%x, be_id %d, port_id %d\n",
846 __func__, device_id, be_id, port_id);
847 return port_id;
848}
849
850static int msm_ds2_dap_update_dev_map_port_id(int32_t device_id, int port_id)
851{
852 int i;
853
854 for (i = 0; i < DS2_DEVICES_ALL; i++) {
855 if (dev_map[i].device_id == device_id)
856 dev_map[i].port_id = port_id;
857 }
858 pr_debug("%s: port_id %d, device_id 0x%x\n",
859 __func__, port_id, device_id);
860 return 0;
861}
862
863static int msm_ds2_dap_handle_bypass_wait(int port_id, int copp_idx,
864 int wait_time)
865{
866 int ret = 0;
867
868 adm_set_wait_parameters(port_id, copp_idx);
869 msm_pcm_routing_release_lock();
870 ret = adm_wait_timeout(port_id, copp_idx, wait_time);
871 msm_pcm_routing_acquire_lock();
872 /* Reset the parameters if wait has timed out */
873 if (ret == 0)
874 adm_reset_wait_parameters(port_id, copp_idx);
875 return ret;
876}
877
878static int msm_ds2_dap_handle_bypass(struct dolby_param_data *dolby_data)
879{
880 int rc = 0, i = 0, j = 0;
881 /*Account for 32 bit integer allocation */
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800882 int32_t param_sz =
883 (ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH / sizeof(uint32_t));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530884 int32_t *mod_list = NULL;
885 int port_id = 0, copp_idx = -1;
886 bool cs_onoff = ds2_dap_params_states.custom_stereo_onoff;
887 int ramp_wait = DOLBY_SOFT_VOLUME_PERIOD;
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800888 struct module_instance_info mod_inst_info;
889 int mod_inst_info_sz = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530890
891 pr_debug("%s: bypass type %d bypass %d custom stereo %d\n", __func__,
892 ds2_dap_params_states.dap_bypass_type,
893 ds2_dap_params_states.dap_bypass,
894 ds2_dap_params_states.custom_stereo_onoff);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800895 memset(&mod_inst_info, 0, sizeof(mod_inst_info));
896 mod_list =
897 kzalloc(ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH, GFP_KERNEL);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530898 if (!mod_list) {
899 pr_err("%s: param memory alloc failed\n", __func__);
900 rc = -ENOMEM;
901 goto end;
902 }
903
904 for (i = 0; i < DS2_DEVICES_ALL; i++) {
905 pr_debug("%s: active dev %d\n", __func__, dev_map[i].active);
906 if (dev_map[i].active) {
907 port_id = dev_map[i].port_id;
908 copp_idx = dev_map[i].copp_idx;
909
910 if (port_id == DOLBY_INVALID_PORT_ID) {
911 pr_err("%s: invalid port\n", __func__);
912 rc = 0;
913 goto end;
914 }
915
916 if ((copp_idx < 0) ||
917 (copp_idx >= MAX_COPPS_PER_PORT)) {
918 pr_err("%s: Invalid copp_idx\n", __func__);
919 rc = 0;
920 goto end;
921 }
922
923 /* getmodules from dsp */
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800924 rc = adm_get_pp_topo_module_list_v2(
925 port_id, copp_idx,
926 ADM_GET_TOPO_MODULE_INSTANCE_LIST_LENGTH,
927 mod_list);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530928 if (rc < 0) {
929 pr_err("%s:adm get topo list port %d",
930 __func__, port_id);
931 pr_err("copp_idx %d, err %d\n",
932 copp_idx, rc);
933 goto end;
934 }
935 if (mod_list[0] > (param_sz - 1)) {
936 pr_err("%s:max modules exp/ret [%d: %d]\n",
937 __func__, (param_sz - 1),
938 mod_list[0]);
939 rc = -EINVAL;
940 goto end;
941 }
942 /*
943 * get ramp parameters
944 * check for change in ramp parameters
945 * update ramp wait
946 */
947 msm_ds2_dap_check_and_update_ramp_wait(port_id,
948 copp_idx,
949 &ramp_wait);
950
951 /* Mute before switching modules */
952 rc = adm_set_volume(port_id, copp_idx,
953 VOLUME_ZERO_GAIN);
954 if (rc < 0) {
955 /*
956 * Not Fatal can continue bypass operations.
957 * Do not need to block playback
958 */
959 pr_info("%s :Set volume port_id %d",
960 __func__, port_id);
961 pr_info("copp_idx %d, error %d\n",
962 copp_idx, rc);
963 }
964
965 rc = msm_ds2_dap_handle_bypass_wait(port_id, copp_idx,
966 (ramp_wait +
967 DOLBY_ADDITIONAL_RAMP_WAIT));
968 if (rc == -EINTR) {
969 pr_info("%s:bypass interrupted-ignore,port %d",
970 __func__, port_id);
971 pr_info("copp_idx %d\n", copp_idx);
972 rc = 0;
973 continue;
974 }
975
976 /* if dap bypass is set */
977 if (ds2_dap_params_states.dap_bypass) {
978 /* Turn off dap module */
Vignesh Kulothungan916967b2018-01-29 16:52:52 -0800979 mod_inst_info.module_id = DS2_MODULE_ID;
980 mod_inst_info.instance_id = INSTANCE_ID_0;
981 adm_param_enable_v2(port_id, copp_idx,
982 mod_inst_info,
983 MODULE_DISABLE);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530984 /*
985 * If custom stereo is on at the time of bypass,
986 * switch off custom stereo on dap and turn on
987 * custom stereo on qti channel mixer.
988 */
989 if (cs_onoff) {
990 rc = dap_set_custom_stereo_onoff(i,
991 !cs_onoff);
992 if (rc < 0) {
993 pr_info("%s:D_CS i %d,rc %d\n",
994 __func__, i, rc);
995 }
996 rc = qti_set_custom_stereo_on(port_id,
997 copp_idx,
998 cs_onoff);
999 if (rc < 0) {
1000 pr_info("%s:Q_CS port id 0x%x",
1001 __func__, port_id);
1002 pr_info("copp idx %d, rc %d\n",
1003 copp_idx, rc);
1004 }
1005 }
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001006
1007 mod_inst_info_sz =
1008 sizeof(struct module_instance_info) /
1009 sizeof(uint32_t);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301010 /* Turn on qti modules */
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001011 for (j = 1; j < mod_list[0] * mod_inst_info_sz;
1012 j += mod_inst_info_sz) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301013 if (!msm_ds2_dap_can_enable_module(
1014 mod_list[j]) ||
1015 mod_list[j] ==
1016 DS2_MODULE_ID)
1017 continue;
1018 pr_debug("%s: param enable %d\n",
1019 __func__, mod_list[j]);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001020 memcpy(&mod_inst_info, &mod_list[j],
1021 sizeof(mod_inst_info));
1022 adm_param_enable_v2(port_id, copp_idx,
1023 mod_inst_info,
1024 MODULE_ENABLE);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301025 }
1026
1027 /* Add adm api to resend calibration on port */
1028 rc = msm_ds2_dap_send_cal_data(i);
1029 if (rc < 0) {
1030 /*
1031 * Not fatal,continue bypass operations.
1032 * Do not need to block playback
1033 */
1034 pr_info("%s:send cal err %d index %d\n",
1035 __func__, rc, i);
1036 }
1037 } else {
1038 /* Turn off qti modules */
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001039 for (j = 1; j < mod_list[0] * mod_inst_info_sz;
1040 j += mod_inst_info_sz) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301041 if (!msm_ds2_dap_can_enable_module(
1042 mod_list[j]) ||
1043 mod_list[j] ==
1044 DS2_MODULE_ID)
1045 continue;
1046 pr_debug("%s: param disable %d\n",
1047 __func__, mod_list[j]);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001048 memcpy(&mod_inst_info, &mod_list[j],
1049 sizeof(mod_inst_info));
1050 adm_param_enable_v2(port_id, copp_idx,
1051 mod_inst_info,
1052 MODULE_DISABLE);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301053 }
1054
1055 /* Enable DAP modules */
1056 pr_debug("%s:DS2 param enable\n", __func__);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001057 mod_inst_info.module_id = DS2_MODULE_ID;
1058 mod_inst_info.instance_id = INSTANCE_ID_0;
1059 adm_param_enable_v2(port_id, copp_idx,
1060 mod_inst_info,
1061 MODULE_ENABLE);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301062 /*
1063 * If custom stereo is on at the time of dap on,
1064 * switch off custom stereo on qti channel mixer
1065 * and turn on custom stereo on DAP.
1066 * mixer(qti).
1067 */
1068 if (cs_onoff) {
1069 rc = qti_set_custom_stereo_on(port_id,
1070 copp_idx,
1071 !cs_onoff);
1072 if (rc < 0) {
1073 pr_info("%s:Q_CS port_id 0x%x",
1074 __func__, port_id);
1075 pr_info("copp_idx %d rc %d\n",
1076 copp_idx, rc);
1077 }
1078 rc = dap_set_custom_stereo_onoff(i,
1079 cs_onoff);
1080 if (rc < 0) {
1081 pr_info("%s:D_CS i %d,rc %d\n",
1082 __func__, i, rc);
1083 }
1084 }
1085 }
1086
1087 rc = msm_ds2_dap_handle_bypass_wait(port_id, copp_idx,
1088 DOLBY_MODULE_ENABLE_PERIOD);
1089 if (rc == -EINTR) {
1090 pr_info("%s:bypass interrupted port_id %d copp_idx %d\n",
1091 __func__, port_id, copp_idx);
1092 /* Interrupted ignore bypass */
1093 rc = 0;
1094 continue;
1095 }
1096
1097 /* set volume to unity gain after module on/off */
1098 rc = adm_set_volume(port_id, copp_idx,
1099 VOLUME_UNITY_GAIN);
1100 if (rc < 0) {
1101 /*
1102 * Not Fatal can continue bypass operations.
1103 * Do not need to block playback
1104 */
1105 pr_info("%s: Set vol port %d copp %d, rc %d\n",
1106 __func__, port_id, copp_idx, rc);
1107 rc = 0;
1108 }
1109 }
1110 }
1111
1112end:
1113 kfree(mod_list);
1114 pr_debug("%s:return rc=%d\n", __func__, rc);
1115 return rc;
1116}
1117
1118static int msm_ds2_dap_send_end_point(int dev_map_idx, int endp_idx)
1119{
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001120 uint32_t offset = 0;
1121 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301122 int cache_device = 0;
1123 struct ds2_dap_params_s *ds2_ap_params_obj = NULL;
1124 int32_t *modified_param = NULL;
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001125 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301126
1127 if (dev_map_idx < 0 || dev_map_idx >= DS2_DEVICES_ALL) {
1128 pr_err("%s: invalid dev map index %d\n", __func__, dev_map_idx);
1129 rc = -EINVAL;
1130 goto end;
1131 }
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001132 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301133 cache_device = dev_map[dev_map_idx].cache_dev;
1134
1135 ds2_ap_params_obj = &ds2_dap_params[cache_device];
1136 pr_debug("%s: cache dev %d, dev_map_idx %d\n", __func__,
1137 cache_device, dev_map_idx);
1138 pr_debug("%s: endp - %pK %pK\n", __func__,
1139 &ds2_dap_params[cache_device], ds2_ap_params_obj);
1140
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301141 if (dev_map[dev_map_idx].port_id == DOLBY_INVALID_PORT_ID) {
1142 pr_err("%s: invalid port\n", __func__);
1143 rc = -EINVAL;
1144 goto end;
1145 }
1146
1147 if ((dev_map[dev_map_idx].copp_idx < 0) ||
1148 (dev_map[dev_map_idx].copp_idx >= MAX_COPPS_PER_PORT)) {
1149 pr_err("%s: Invalid copp_idx\n", __func__);
1150 rc = -EINVAL;
1151 goto end;
1152 }
1153
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001154 param_hdr.module_id = DOLBY_BUNDLE_MODULE_ID;
1155 param_hdr.instance_id = INSTANCE_ID_0;
1156 param_hdr.param_id = DOLBY_PARAM_ID_INIT_ENDP;
1157 param_hdr.param_size = sizeof(offset);
1158 offset = ds2_ap_params_obj->params_val[ds2_dap_params_offset[endp_idx]];
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301159 pr_debug("%s: off %d, length %d\n", __func__,
1160 ds2_dap_params_offset[endp_idx],
1161 ds2_dap_params_length[endp_idx]);
1162 pr_debug("%s: param 0x%x, param val %d\n", __func__,
1163 ds2_dap_params_id[endp_idx], ds2_ap_params_obj->
1164 params_val[ds2_dap_params_offset[endp_idx]]);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001165 rc = adm_pack_and_set_one_pp_param(dev_map[dev_map_idx].port_id,
1166 dev_map[dev_map_idx].copp_idx,
1167 param_hdr, (u8 *) &offset);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301168 if (rc) {
1169 pr_err("%s: send dolby params failed rc %d\n", __func__, rc);
1170 rc = -EINVAL;
1171 }
1172 modified_param = ds2_ap_params_obj->dap_params_modified;
1173 if (modified_param == NULL) {
1174 pr_err("%s: modified param structure invalid\n",
1175 __func__);
1176 rc = -EINVAL;
1177 goto end;
1178 }
1179
1180 if (msm_ds2_dap_check_is_param_modified(modified_param, endp_idx, 0))
1181 ds2_ap_params_obj->dap_params_modified[endp_idx] = 0x00010001;
1182
1183end:
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301184 return rc;
1185}
1186
1187static int msm_ds2_dap_send_cached_params(int dev_map_idx,
1188 int commit)
1189{
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001190 uint8_t *packed_params = NULL;
1191 uint32_t packed_params_size = 0;
1192 uint32_t param_size = 0;
1193 struct param_hdr_v3 param_hdr;
1194 uint32_t idx, i, ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301195 int cache_device = 0;
1196 struct ds2_dap_params_s *ds2_ap_params_obj = NULL;
1197 int32_t *modified_param = NULL;
1198
1199 if (dev_map_idx < 0 || dev_map_idx >= DS2_DEVICES_ALL) {
1200 pr_err("%s: invalid dev map index %d\n", __func__, dev_map_idx);
1201 ret = -EINVAL;
1202 goto end;
1203 }
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001204 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301205 cache_device = dev_map[dev_map_idx].cache_dev;
1206
1207 /* Use off profile cache in only for soft bypass */
1208 if (ds2_dap_params_states.dap_bypass_type == DAP_SOFT_BYPASS &&
1209 ds2_dap_params_states.dap_bypass == true) {
1210 pr_debug("%s: use bypass cache 0\n", __func__);
1211 cache_device = dev_map[0].cache_dev;
1212 }
1213
1214 ds2_ap_params_obj = &ds2_dap_params[cache_device];
1215 pr_debug("%s: cached param - %pK %pK, cache_device %d\n", __func__,
1216 &ds2_dap_params[cache_device], ds2_ap_params_obj,
1217 cache_device);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001218
1219 /*
1220 * Allocate the max space needed. This is enough space to hold the
1221 * header for each param plus the total size of all the params.
1222 */
1223 packed_params_size = (sizeof(param_hdr) * (MAX_DS2_PARAMS - 1)) +
1224 (TOTAL_LENGTH_DOLBY_PARAM * sizeof(uint32_t));
1225 packed_params = kzalloc(packed_params_size, GFP_KERNEL);
1226 if (!packed_params)
1227 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301228
1229 if (dev_map[dev_map_idx].port_id == DOLBY_INVALID_PORT_ID) {
1230 pr_err("%s: invalid port id\n", __func__);
1231 ret = -EINVAL;
1232 goto end;
1233 }
1234
1235 if ((dev_map[dev_map_idx].copp_idx < 0) ||
1236 (dev_map[dev_map_idx].copp_idx >= MAX_COPPS_PER_PORT)) {
1237 pr_err("%s: Invalid copp_idx\n", __func__);
1238 ret = -EINVAL;
1239 goto end;
1240 }
1241
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001242 packed_params_size = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301243 for (i = 0; i < (MAX_DS2_PARAMS-1); i++) {
1244 /*get the pointer to the param modified array in the cache*/
1245 modified_param = ds2_ap_params_obj->dap_params_modified;
1246 if (modified_param == NULL) {
1247 pr_err("%s: modified param structure invalid\n",
1248 __func__);
1249 ret = -EINVAL;
1250 goto end;
1251 }
1252 if (!msm_ds2_dap_check_is_param_modified(modified_param, i,
1253 commit))
1254 continue;
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001255
1256 param_hdr.module_id = DOLBY_BUNDLE_MODULE_ID;
1257 param_hdr.instance_id = INSTANCE_ID_0;
1258 param_hdr.param_id = ds2_dap_params_id[i];
1259 param_hdr.param_size =
1260 ds2_dap_params_length[i] * sizeof(uint32_t);
1261
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301262 idx = ds2_dap_params_offset[i];
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001263 ret = q6common_pack_pp_params(
1264 packed_params + packed_params_size, &param_hdr,
1265 (u8 *) &ds2_ap_params_obj->params_val[idx],
1266 &param_size);
1267 if (ret) {
1268 pr_err("%s: Failed to pack params, error %d\n",
1269 __func__, ret);
1270 goto end;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301271 }
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001272
1273 packed_params_size += param_size;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301274 }
1275
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001276 pr_debug("%s: total packed param length: %d\n", __func__,
1277 packed_params_size);
1278 if (packed_params_size) {
1279 ret = adm_set_pp_params(dev_map[dev_map_idx].port_id,
1280 dev_map[dev_map_idx].copp_idx, NULL,
1281 packed_params, packed_params_size);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301282 if (ret) {
1283 pr_err("%s: send dolby params failed ret %d\n",
1284 __func__, ret);
1285 ret = -EINVAL;
1286 goto end;
1287 }
1288 for (i = 0; i < MAX_DS2_PARAMS-1; i++) {
1289 /*get pointer to the param modified array in the cache*/
1290 modified_param = ds2_ap_params_obj->dap_params_modified;
1291 if (modified_param == NULL) {
1292 pr_err("%s: modified param struct invalid\n",
1293 __func__);
1294 ret = -EINVAL;
1295 goto end;
1296 }
1297 if (!msm_ds2_dap_check_is_param_modified(
1298 modified_param, i, commit))
1299 continue;
1300 ds2_ap_params_obj->dap_params_modified[i] = 0x00010001;
1301 }
1302 }
1303end:
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001304 kfree(packed_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301305 return ret;
1306}
1307
1308static int msm_ds2_dap_commit_params(struct dolby_param_data *dolby_data,
1309 int commit)
1310{
1311 int ret = 0, i, idx;
1312 struct ds2_dap_params_s *ds2_ap_params_obj = NULL;
1313 int32_t *modified_param = NULL;
1314
1315 /* Do not commit params if in hard bypass */
1316 if (ds2_dap_params_states.dap_bypass_type == DAP_HARD_BYPASS &&
1317 ds2_dap_params_states.dap_bypass == true) {
1318 pr_debug("%s: called in bypass", __func__);
1319 ret = -EINVAL;
1320 goto end;
1321 }
1322 for (idx = 0; idx < MAX_DS2_PARAMS; idx++) {
1323 if (ds2_dap_params_id[idx] == DOLBY_PARAM_ID_INIT_ENDP)
1324 break;
1325 }
1326 if (idx >= MAX_DS2_PARAMS || idx < 0) {
1327 pr_err("%s: index of DS2 Param not found idx %d\n",
1328 __func__, idx);
1329 ret = -EINVAL;
1330 goto end;
1331 }
1332 pr_debug("%s: found endp - idx %d 0x%x\n", __func__, idx,
1333 ds2_dap_params_id[idx]);
1334 for (i = 0; i < DS2_DEVICES_ALL; i++) {
1335 pr_debug("%s:dev[0x%x,0x%x],i:%d,active:%d,bypass:%d,type:%d\n",
1336 __func__, dolby_data->device_id, dev_map[i].device_id,
1337 i, dev_map[i].active, ds2_dap_params_states.dap_bypass,
1338 ds2_dap_params_states.dap_bypass_type);
1339
1340 if (((dev_map[i].device_id & ds2_dap_params_states.device) ||
1341 ((ds2_dap_params_states.dap_bypass_type ==
1342 DAP_SOFT_BYPASS) &&
1343 (ds2_dap_params_states.dap_bypass == true))) &&
1344 (dev_map[i].active == true)) {
1345
1346 /*get ptr to the cache storing the params for device*/
1347 if ((ds2_dap_params_states.dap_bypass_type ==
1348 DAP_SOFT_BYPASS) &&
1349 (ds2_dap_params_states.dap_bypass == true))
1350 ds2_ap_params_obj =
1351 &ds2_dap_params[dev_map[0].cache_dev];
1352 else
1353 ds2_ap_params_obj =
1354 &ds2_dap_params[dev_map[i].cache_dev];
1355
1356 /*get the pointer to the param modified array in cache*/
1357 modified_param = ds2_ap_params_obj->dap_params_modified;
1358 if (modified_param == NULL) {
1359 pr_err("%s: modified_param NULL\n", __func__);
1360 ret = -EINVAL;
1361 goto end;
1362 }
1363
1364 /*
1365 * Send the endp param if use cache is set
1366 * or if param is modified
1367 */
1368 if (!commit || msm_ds2_dap_check_is_param_modified(
1369 modified_param, idx, commit)) {
1370 msm_ds2_dap_send_end_point(i, idx);
1371 commit = 0;
1372 }
1373 ret = msm_ds2_dap_send_cached_params(i, commit);
1374 if (ret < 0) {
1375 pr_err("%s: send cached param %d\n",
1376 __func__, ret);
1377 goto end;
1378 }
1379 }
1380 }
1381end:
1382 return ret;
1383}
1384
1385static int msm_ds2_dap_handle_commands(u32 cmd, void *arg)
1386{
1387 int ret = 0, port_id = 0;
1388 int32_t data;
1389 struct dolby_param_data *dolby_data = (struct dolby_param_data *)arg;
1390
1391 if (get_user(data, &dolby_data->data[0])) {
1392 pr_debug("%s error getting data\n", __func__);
1393 ret = -EFAULT;
1394 goto end;
1395 }
1396
1397 pr_debug("%s: param_id %d,be_id %d,device_id 0x%x,length %d,data %d\n",
1398 __func__, dolby_data->param_id, dolby_data->be_id,
1399 dolby_data->device_id, dolby_data->length, data);
1400
1401 switch (dolby_data->param_id) {
1402 case DAP_CMD_COMMIT_ALL:
1403 msm_ds2_dap_commit_params(dolby_data, 0);
1404 break;
1405
1406 case DAP_CMD_COMMIT_CHANGED:
1407 msm_ds2_dap_commit_params(dolby_data, 1);
1408 break;
1409
1410 case DAP_CMD_USE_CACHE_FOR_INIT:
1411 ds2_dap_params_states.use_cache = data;
1412 break;
1413
1414 case DAP_CMD_SET_BYPASS:
1415 pr_debug("%s: bypass %d bypass type %d, data %d\n", __func__,
1416 ds2_dap_params_states.dap_bypass,
1417 ds2_dap_params_states.dap_bypass_type,
1418 data);
1419 /* Do not perform bypass operation if bypass state is same*/
1420 if (ds2_dap_params_states.dap_bypass == data)
1421 break;
1422 ds2_dap_params_states.dap_bypass = data;
1423 /* hard bypass */
1424 if (ds2_dap_params_states.dap_bypass_type == DAP_HARD_BYPASS)
1425 msm_ds2_dap_handle_bypass(dolby_data);
1426 /* soft bypass */
1427 msm_ds2_dap_commit_params(dolby_data, 0);
1428 break;
1429
1430 case DAP_CMD_SET_BYPASS_TYPE:
1431 if (data == true)
1432 ds2_dap_params_states.dap_bypass_type =
1433 DAP_HARD_BYPASS;
1434 else
1435 ds2_dap_params_states.dap_bypass_type =
1436 DAP_SOFT_BYPASS;
1437 pr_debug("%s: bypass type %d", __func__,
1438 ds2_dap_params_states.dap_bypass_type);
1439 break;
1440
1441 case DAP_CMD_SET_ACTIVE_DEVICE:
1442 pr_debug("%s: DAP_CMD_SET_ACTIVE_DEVICE length %d\n",
1443 __func__, dolby_data->length);
1444 /* TODO: need to handle multiple instance*/
1445 ds2_dap_params_states.device |= dolby_data->device_id;
1446 port_id = msm_ds2_dap_get_port_id(
1447 dolby_data->device_id,
1448 dolby_data->be_id);
1449 pr_debug("%s: device id 0x%x all_dev 0x%x port_id %d\n",
1450 __func__, dolby_data->device_id,
1451 ds2_dap_params_states.device, port_id);
1452 msm_ds2_dap_update_dev_map_port_id(dolby_data->device_id,
1453 port_id);
1454 if (port_id == DOLBY_INVALID_PORT_ID) {
1455 pr_err("%s: invalid port id %d\n", __func__, port_id);
1456 ret = -EINVAL;
1457 goto end;
1458 }
1459 break;
1460 }
1461end:
1462 return ret;
1463
1464}
1465
1466static int msm_ds2_dap_set_param(u32 cmd, void *arg)
1467{
1468 int rc = 0, idx, i, j, off, port_id = 0, cdev = 0;
1469 int32_t num_device = 0;
1470 int32_t data = 0;
1471 int32_t dev_arr[DS2_DSP_SUPPORTED_ENDP_DEVICE] = {0};
1472 struct dolby_param_data *dolby_data = (struct dolby_param_data *)arg;
1473
1474 rc = msm_ds2_dap_update_num_devices(dolby_data, &num_device, dev_arr,
1475 DS2_DSP_SUPPORTED_ENDP_DEVICE);
1476 if (num_device == 0 || rc < 0) {
1477 pr_err("%s: num devices 0\n", __func__);
1478 rc = -EINVAL;
1479 goto end;
1480 }
1481 for (i = 0; i < num_device; i++) {
1482 port_id = msm_ds2_dap_get_port_id(dev_arr[i],
1483 dolby_data->be_id);
1484 if (port_id != DOLBY_INVALID_PORT_ID)
1485 msm_ds2_dap_update_dev_map_port_id(dev_arr[i], port_id);
1486
1487 cdev = msm_ds2_dap_map_device_to_dolby_cache_devices(
1488 dev_arr[i]);
1489 if (cdev < 0 || cdev >= DOLBY_MAX_CACHE) {
1490 pr_err("%s: Invalid cache device %d for device 0x%x\n",
1491 __func__, cdev, dev_arr[i]);
1492 rc = -EINVAL;
1493 goto end;
1494 }
1495 pr_debug("%s:port:%d,be:%d,dev:0x%x,cdev:%d,param:0x%x,len:%d\n"
1496 , __func__, port_id, dolby_data->be_id, dev_arr[i],
1497 cdev, dolby_data->param_id, dolby_data->length);
1498 for (idx = 0; idx < MAX_DS2_PARAMS; idx++) {
1499 /*paramid from user space*/
1500 if (dolby_data->param_id == ds2_dap_params_id[idx])
1501 break;
1502 }
1503 if (idx > MAX_DS2_PARAMS-1) {
1504 pr_err("%s: invalid param id 0x%x at idx %d\n",
1505 __func__, dolby_data->param_id, idx);
1506 rc = -EINVAL;
1507 goto end;
1508 }
1509
1510 off = ds2_dap_params_offset[idx];
1511 if ((dolby_data->length <= 0) ||
1512 (dolby_data->length > TOTAL_LENGTH_DS2_PARAM - off)) {
1513 pr_err("%s: invalid length %d at idx %d\n",
1514 __func__, dolby_data->length, idx);
1515 rc = -EINVAL;
1516 goto end;
1517 }
1518
1519 /* cache the parameters */
1520 ds2_dap_params[cdev].dap_params_modified[idx] += 1;
1521 for (j = 0; j < dolby_data->length; j++) {
1522 if (get_user(data, &dolby_data->data[j])) {
1523 pr_debug("%s:error getting data\n", __func__);
1524 rc = -EFAULT;
1525 goto end;
1526 }
1527 ds2_dap_params[cdev].params_val[off + j] = data;
1528 pr_debug("%s:off %d,val[i/p:o/p]-[%d / %d]\n",
1529 __func__, off, data,
1530 ds2_dap_params[cdev].
1531 params_val[off + j]);
1532 }
1533 }
1534end:
1535 return rc;
1536}
1537
1538static int msm_ds2_dap_get_param(u32 cmd, void *arg)
1539{
1540 int rc = 0, i, port_id = 0, copp_idx = -1;
1541 struct dolby_param_data *dolby_data = (struct dolby_param_data *)arg;
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001542 int32_t *params_value = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301543 uint32_t params_length = DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM *
1544 sizeof(uint32_t);
1545 uint32_t param_payload_len =
1546 DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001547 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301548
1549 /* Return error on get param in soft or hard bypass */
1550 if (ds2_dap_params_states.dap_bypass == true) {
1551 pr_err("%s: called in bypass_type %d bypass %d\n", __func__,
1552 ds2_dap_params_states.dap_bypass_type,
1553 ds2_dap_params_states.dap_bypass);
1554 rc = -EINVAL;
1555 goto end;
1556 }
1557
1558 /* Return if invalid length */
1559 if ((dolby_data->length >
1560 (DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM - DOLBY_PARAM_PAYLOAD_SIZE)) ||
1561 (dolby_data->length <= 0)) {
1562 pr_err("Invalid length %d", dolby_data->length);
1563 rc = -EINVAL;
1564 goto end;
1565 }
1566
1567 for (i = 0; i < DS2_DEVICES_ALL; i++) {
1568 if ((dev_map[i].active) &&
1569 (dev_map[i].device_id & dolby_data->device_id)) {
1570 port_id = dev_map[i].port_id;
1571 copp_idx = dev_map[i].copp_idx;
1572 break;
1573 }
1574 }
1575
1576 if (port_id == DOLBY_INVALID_PORT_ID) {
1577 pr_err("%s: Invalid port\n", __func__);
1578 rc = -EINVAL;
1579 goto end;
1580 }
1581
1582 if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
1583 pr_err("%s: Invalid copp_idx\n", __func__);
1584 rc = -EINVAL;
1585 goto end;
1586 }
1587
1588 pr_debug("%s: port_id 0x%x, copp_idx %d, dev_map[i].device_id %x\n",
1589 __func__, port_id, copp_idx, dev_map[i].device_id);
1590
1591 params_value = kzalloc(params_length + param_payload_len,
1592 GFP_KERNEL);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001593 if (!params_value)
1594 return -ENOMEM;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301595
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001596 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301597 if (dolby_data->param_id == DOLBY_PARAM_ID_VER) {
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001598 param_hdr.module_id = DOLBY_BUNDLE_MODULE_ID;
1599 param_hdr.instance_id = INSTANCE_ID_0;
1600 param_hdr.param_id = DOLBY_PARAM_ID_VER;
1601 param_hdr.param_size = params_length + param_payload_len;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301602 } else {
1603 for (i = 0; i < MAX_DS2_PARAMS; i++)
1604 if (ds2_dap_params_id[i] ==
1605 dolby_data->param_id)
1606 break;
1607 if (i > MAX_DS2_PARAMS-1) {
1608 pr_err("%s: invalid param id 0x%x at id %d\n", __func__,
1609 dolby_data->param_id, i);
1610 rc = -EINVAL;
1611 goto end;
1612 } else {
1613 params_length =
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001614 ds2_dap_params_length[i] * sizeof(uint32_t);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301615
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001616 param_hdr.module_id = DOLBY_BUNDLE_MODULE_ID;
1617 param_hdr.instance_id = INSTANCE_ID_0;
1618 param_hdr.param_id = ds2_dap_params_id[i];
1619 param_hdr.param_size =
1620 params_length + param_payload_len;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301621 }
1622 }
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001623 rc = adm_get_pp_params(port_id, copp_idx, ADM_CLIENT_ID_DEFAULT, NULL,
1624 &param_hdr, (u8 *) params_value);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301625 if (rc) {
1626 pr_err("%s: get parameters failed rc %d\n", __func__, rc);
1627 rc = -EINVAL;
1628 goto end;
1629 }
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001630 if (copy_to_user((void __user *) dolby_data->data,
1631 &params_value[DOLBY_PARAM_PAYLOAD_SIZE],
1632 (dolby_data->length * sizeof(uint32_t)))) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301633 pr_err("%s: error getting param\n", __func__);
1634 rc = -EFAULT;
1635 goto end;
1636 }
1637end:
1638 kfree(params_value);
1639 return rc;
1640}
1641
1642static int msm_ds2_dap_param_visualizer_control_get(u32 cmd, void *arg)
1643{
1644 int32_t *visualizer_data = NULL;
1645 int i = 0, ret = 0, port_id = -1, cache_dev = -1, copp_idx = -1;
1646 int32_t *update_visualizer_data = NULL;
1647 struct dolby_param_data *dolby_data = (struct dolby_param_data *)arg;
1648 uint32_t offset, length, params_length;
1649 uint32_t param_payload_len =
1650 DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001651 struct param_hdr_v3 param_hdr;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301652
1653 for (i = 0; i < DS2_DEVICES_ALL; i++) {
1654 if ((dev_map[i].active)) {
1655 port_id = dev_map[i].port_id;
1656 cache_dev = dev_map[i].cache_dev;
1657 copp_idx = dev_map[i].copp_idx;
1658 break;
1659 }
1660 }
1661
1662 if (port_id == DOLBY_INVALID_PORT_ID ||
1663 (copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) {
1664 ret = 0;
1665 dolby_data->length = 0;
1666 pr_err("%s: no device active\n", __func__);
1667 goto end;
1668 }
1669
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001670 memset(&param_hdr, 0, sizeof(param_hdr));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301671 length = ds2_dap_params[cache_dev].params_val[DOLBY_PARAM_VCNB_OFFSET];
1672
1673 if (length > DOLBY_PARAM_VCNB_MAX_LENGTH || length <= 0) {
1674 ret = 0;
1675 dolby_data->length = 0;
1676 pr_err("%s Incorrect VCNB length", __func__);
1677 return -EINVAL;
1678 }
1679
1680 params_length = (2*length + DOLBY_VIS_PARAM_HEADER_SIZE) *
1681 sizeof(uint32_t);
1682
1683 visualizer_data = kzalloc(params_length, GFP_KERNEL);
1684 if (!visualizer_data) {
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001685 pr_err("%s: params memory alloc failed\n", __func__);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301686 ret = -ENOMEM;
1687 dolby_data->length = 0;
1688 goto end;
1689 }
1690 memset(visualizer_data, 0x0, params_length);
1691
1692 /* Return error on get param in soft or hard bypass */
1693 if (ds2_dap_params_states.dap_bypass == true) {
1694 pr_debug("%s: visualizer called in bypass, return 0\n",
1695 __func__);
1696 ret = 0;
1697 dolby_data->length = 0;
1698 goto end;
1699 }
1700
1701 offset = 0;
1702 params_length = length * sizeof(uint32_t);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001703 param_hdr.module_id = DOLBY_BUNDLE_MODULE_ID;
1704 param_hdr.instance_id = INSTANCE_ID_0;
1705 param_hdr.param_id = DOLBY_PARAM_ID_VCBG;
1706 param_hdr.param_size = length * sizeof(uint32_t) + param_payload_len;
1707 ret = adm_get_pp_params(port_id, copp_idx, ADM_CLIENT_ID_DEFAULT, NULL,
1708 &param_hdr,
1709 (((char *) (visualizer_data)) + offset));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301710 if (ret) {
1711 pr_err("%s: get parameters failed ret %d\n", __func__, ret);
1712 ret = -EINVAL;
1713 dolby_data->length = 0;
1714 goto end;
1715 }
1716 offset = length * sizeof(uint32_t);
Vignesh Kulothungan916967b2018-01-29 16:52:52 -08001717 param_hdr.module_id = DOLBY_BUNDLE_MODULE_ID;
1718 param_hdr.instance_id = INSTANCE_ID_0;
1719 param_hdr.param_id = DOLBY_PARAM_ID_VCBE;
1720 param_hdr.param_size = length * sizeof(uint32_t) + param_payload_len;
1721 ret = adm_get_pp_params(port_id, copp_idx, ADM_CLIENT_ID_DEFAULT, NULL,
1722 &param_hdr,
1723 (((char *) (visualizer_data)) + offset));
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301724 if (ret) {
1725 pr_err("%s: get parameters failed ret %d\n", __func__, ret);
1726 ret = -EINVAL;
1727 dolby_data->length = 0;
1728 goto end;
1729 }
1730 update_visualizer_data = visualizer_data;
1731 dolby_data->length = 2 * length;
1732
1733 if (copy_to_user((void *)dolby_data->data,
1734 (void *)update_visualizer_data,
1735 (dolby_data->length * sizeof(uint32_t)))) {
1736 pr_err("%s: copy to user failed for data\n", __func__);
1737 dolby_data->length = 0;
1738 ret = -EFAULT;
1739 goto end;
1740 }
1741
1742end:
1743 kfree(visualizer_data);
1744 return ret;
1745}
1746
1747int msm_ds2_dap_set_security_control(u32 cmd, void *arg)
1748{
1749 struct dolby_param_license *dolby_license =
1750 ((struct dolby_param_license *)arg);
1751 pr_debug("%s: dmid %d license key %d\n", __func__,
1752 dolby_license->dmid, dolby_license->license_key);
1753 core_set_dolby_manufacturer_id(dolby_license->dmid);
1754 core_set_license(dolby_license->license_key, DOLBY_DS1_LICENSE_ID);
1755 return 0;
1756}
1757
1758int msm_ds2_dap_update_port_parameters(struct snd_hwdep *hw, struct file *file,
1759 bool open)
1760{
1761 int i = 0, dev_id = 0;
1762
1763 pr_debug("%s: open %d\n", __func__, open);
1764 ds2_dap_params_states.node_opened = open;
1765 ds2_dap_params_states.dap_bypass = true;
1766 ds2_dap_params_states.dap_bypass_type = 0;
1767 ds2_dap_params_states.use_cache = 0;
1768 ds2_dap_params_states.device = 0;
1769 ds2_dap_params_states.custom_stereo_onoff = 0;
1770 for (i = 0; i < DS2_DEVICES_ALL; i++) {
1771 if (i == 0)
1772 dev_map[i].device_id = 0;
1773 else {
1774 dev_id = (1 << (i-1));
1775 if (all_supported_devices & dev_id)
1776 dev_map[i].device_id = dev_id;
1777 else
1778 continue;
1779 }
1780 dev_map[i].cache_dev =
1781 msm_ds2_dap_map_device_to_dolby_cache_devices(
1782 dev_map[i].device_id);
1783 if (dev_map[i].cache_dev < 0 ||
1784 dev_map[i].cache_dev >= DOLBY_MAX_CACHE)
1785 pr_err("%s: Invalid cache device %d for device 0x%x\n",
1786 __func__,
1787 dev_map[i].cache_dev,
1788 dev_map[i].device_id);
1789 dev_map[i].port_id = -1;
1790 dev_map[i].active = false;
1791 dev_map[i].stream_ref_count = 0;
1792 dev_map[i].cal_data = NULL;
1793 dev_map[i].copp_idx = -1;
1794 pr_debug("%s: device_id 0x%x, cache_dev %d act %d\n", __func__,
1795 dev_map[i].device_id, dev_map[i].cache_dev,
1796 dev_map[i].active);
1797 }
1798 return 0;
1799
1800}
1801
1802int msm_ds2_dap_ioctl_shared(struct snd_hwdep *hw, struct file *file,
1803 u32 cmd, void *arg)
1804{
1805 int ret = 0;
1806
1807 pr_debug("%s: cmd: 0x%x\n", __func__, cmd);
1808 switch (cmd) {
1809 case SNDRV_DEVDEP_DAP_IOCTL_SET_PARAM:
1810 ret = msm_ds2_dap_set_param(cmd, arg);
1811 break;
1812 case SNDRV_DEVDEP_DAP_IOCTL_GET_PARAM:
1813 ret = msm_ds2_dap_get_param(cmd, arg);
1814 break;
1815 case SNDRV_DEVDEP_DAP_IOCTL_DAP_COMMAND:
1816 ret = msm_ds2_dap_handle_commands(cmd, arg);
1817 break;
1818 case SNDRV_DEVDEP_DAP_IOCTL_DAP_LICENSE:
1819 ret = msm_ds2_dap_set_security_control(cmd, arg);
1820 break;
1821 case SNDRV_DEVDEP_DAP_IOCTL_GET_VISUALIZER:
1822 ret = msm_ds2_dap_param_visualizer_control_get(cmd, arg);
1823 break;
1824 default:
1825 pr_err("%s: called with invalid control 0x%x\n", __func__, cmd);
1826 ret = -EINVAL;
1827 }
1828 return ret;
1829}
1830
1831int msm_ds2_dap_ioctl(struct snd_hwdep *hw, struct file *file,
1832 u32 cmd, void *arg)
1833{
1834
1835 int ret = 0;
1836
1837 pr_debug("%s: cmd: 0x%x\n", __func__, cmd);
1838 if (!arg) {
1839 pr_err("%s: Invalid params event status\n", __func__);
1840 ret = -EINVAL;
1841 goto end;
1842 }
1843 switch (cmd) {
1844 case SNDRV_DEVDEP_DAP_IOCTL_SET_PARAM:
1845 case SNDRV_DEVDEP_DAP_IOCTL_DAP_COMMAND: {
1846 struct dolby_param_data dolby_data;
1847
1848 if (copy_from_user((void *)&dolby_data, (void *)arg,
1849 sizeof(struct dolby_param_data))) {
1850 pr_err("%s: Copy from user failed\n", __func__);
1851 ret = -EFAULT;
1852 goto end;
1853 }
1854 ret = msm_ds2_dap_ioctl_shared(hw, file, cmd, &dolby_data);
1855 break;
1856 }
1857 case SNDRV_DEVDEP_DAP_IOCTL_DAP_LICENSE: {
1858 struct dolby_param_license dolby_license;
1859
1860 if (copy_from_user((void *)&dolby_license, (void *)arg,
1861 sizeof(struct dolby_param_license))) {
1862 pr_err("%s: Copy from user failed\n", __func__);
1863 ret = -EFAULT;
1864 goto end;
1865 }
1866 ret = msm_ds2_dap_ioctl_shared(hw, file, cmd, &dolby_license);
1867 break;
1868 }
1869 case SNDRV_DEVDEP_DAP_IOCTL_GET_PARAM:
1870 case SNDRV_DEVDEP_DAP_IOCTL_GET_VISUALIZER: {
1871 struct dolby_param_data dolby_data;
1872
1873 if (copy_from_user((void *)&dolby_data, (void *)arg,
1874 sizeof(struct dolby_param_data))) {
1875 pr_err("%s: Copy from user failed\n", __func__);
1876 ret = -EFAULT;
1877 goto end;
1878 }
1879 ret = msm_ds2_dap_ioctl_shared(hw, file, cmd, &dolby_data);
1880 if (ret < 0)
1881 pr_err("%s: ioctl cmd %d returned err %d\n",
1882 __func__, cmd, ret);
1883 if (copy_to_user((void *)arg, &dolby_data,
1884 sizeof(struct dolby_param_data))) {
1885 pr_err("%s: Copy to user failed\n", __func__);
1886 ret = -EFAULT;
1887 goto end;
1888 }
1889 break;
1890 }
1891 default:
1892 pr_err("%s: called with invalid control 0x%x\n", __func__, cmd);
1893 ret = -EINVAL;
1894 }
1895end:
1896 return ret;
1897
1898}
1899#ifdef CONFIG_COMPAT
1900int msm_ds2_dap_compat_ioctl(struct snd_hwdep *hw, struct file *file,
1901 u32 cmd, void *arg)
1902{
1903 int ret = 0;
1904
1905 pr_debug("%s: cmd: 0x%x\n", __func__, cmd);
1906 switch (cmd) {
1907 case SNDRV_DEVDEP_DAP_IOCTL_SET_PARAM32:
1908 cmd = SNDRV_DEVDEP_DAP_IOCTL_SET_PARAM;
1909 goto handle_set_ioctl;
1910 case SNDRV_DEVDEP_DAP_IOCTL_DAP_COMMAND32:
1911 cmd = SNDRV_DEVDEP_DAP_IOCTL_DAP_COMMAND;
1912handle_set_ioctl:
1913 {
1914 struct dolby_param_data32 dolby_data32;
1915 struct dolby_param_data dolby_data;
1916
1917 memset(&dolby_data32, 0, sizeof(dolby_data32));
1918 memset(&dolby_data, 0, sizeof(dolby_data));
1919 if (copy_from_user(&dolby_data32, (void *)arg,
1920 sizeof(struct dolby_param_data32))) {
1921 pr_err("%s: Copy from user failed\n", __func__);
1922 ret = -EFAULT;
1923 goto end;
1924 }
1925 dolby_data.version = dolby_data32.version;
1926 dolby_data.device_id = dolby_data32.device_id;
1927 dolby_data.be_id = dolby_data32.be_id;
1928 dolby_data.param_id = dolby_data32.param_id;
1929 dolby_data.length = dolby_data32.length;
1930 dolby_data.data = compat_ptr(dolby_data32.data);
1931
1932 ret = msm_ds2_dap_ioctl_shared(hw, file, cmd, &dolby_data);
1933 break;
1934 }
1935 case SNDRV_DEVDEP_DAP_IOCTL_GET_PARAM32:
1936 cmd = SNDRV_DEVDEP_DAP_IOCTL_GET_PARAM;
1937 goto handle_get_ioctl;
1938 case SNDRV_DEVDEP_DAP_IOCTL_GET_VISUALIZER32:
1939 cmd = SNDRV_DEVDEP_DAP_IOCTL_GET_VISUALIZER;
1940handle_get_ioctl:
1941 {
1942 struct dolby_param_data32 dolby_data32;
1943 struct dolby_param_data dolby_data;
1944
1945 memset(&dolby_data32, 0, sizeof(dolby_data32));
1946 memset(&dolby_data, 0, sizeof(dolby_data));
1947 if (copy_from_user(&dolby_data32, (void *)arg,
1948 sizeof(struct dolby_param_data32))) {
1949 pr_err("%s: Copy from user failed\n", __func__);
1950 ret = -EFAULT;
1951 goto end;
1952 }
1953 dolby_data.version = dolby_data32.version;
1954 dolby_data.device_id = dolby_data32.device_id;
1955 dolby_data.be_id = dolby_data32.be_id;
1956 dolby_data.param_id = dolby_data32.param_id;
1957 dolby_data.length = dolby_data32.length;
1958 dolby_data.data = compat_ptr(dolby_data32.data);
1959
1960 ret = msm_ds2_dap_ioctl_shared(hw, file, cmd, &dolby_data);
1961 if (ret < 0)
1962 pr_err("%s: ioctl cmd %d, returned err %d\n",
1963 __func__, cmd, ret);
1964 dolby_data32.length = dolby_data.length;
1965 if (copy_to_user((void *)arg, &dolby_data32,
1966 sizeof(struct dolby_param_data32))) {
1967 pr_err("%s: Copy to user failed\n", __func__);
1968 ret = -EFAULT;
1969 goto end;
1970 }
1971 break;
1972 }
1973 case SNDRV_DEVDEP_DAP_IOCTL_DAP_LICENSE32: {
1974 struct dolby_param_license32 dolby_license32;
1975 struct dolby_param_license dolby_license;
1976
1977 cmd = SNDRV_DEVDEP_DAP_IOCTL_DAP_LICENSE;
1978 if (copy_from_user((void *)&dolby_license32, (void *)arg,
1979 sizeof(struct dolby_param_license32))) {
1980 pr_err("%s: Copy from user failed\n", __func__);
1981 ret = -EFAULT;
1982 goto end;
1983 }
1984 dolby_license.dmid = dolby_license32.dmid;
1985 dolby_license.license_key = dolby_license32.license_key;
1986 ret = msm_ds2_dap_ioctl_shared(hw, file, cmd, &dolby_license);
1987 break;
1988 }
1989 default:
1990 pr_err("%s: called with invalid control 0x%x\n",
1991 __func__, cmd);
1992 ret = -EINVAL;
1993 }
1994end:
1995 return ret;
1996
1997}
1998#endif
1999
2000int msm_ds2_dap_init(int port_id, int copp_idx, int channels,
2001 bool is_custom_stereo_on)
2002{
2003 int ret = 0, idx = -1, i;
2004 struct dolby_param_data dolby_data;
2005
2006 struct audproc_softvolume_params softvol = {
2007 .period = DOLBY_SOFT_VOLUME_PERIOD,
2008 .step = DOLBY_SOFT_VOLUME_STEP,
2009 .rampingcurve = DOLBY_SOFT_VOLUME_CURVE_EXP,
2010 };
2011
2012 pr_debug("%s: port id %d, copp_idx %d\n", __func__, port_id, copp_idx);
2013
2014 if (port_id != DOLBY_INVALID_PORT_ID) {
2015 for (i = 0; i < DS2_DEVICES_ALL; i++) {
2016 if ((dev_map[i].port_id == port_id) &&
2017 /* device part of active device */
2018 (dev_map[i].device_id &
2019 ds2_dap_params_states.device)) {
2020 idx = i;
2021 /* Give priority to headset in case of
2022 * combo device
2023 */
2024 if (dev_map[i].device_id == SPEAKER)
2025 continue;
2026 else
2027 break;
2028 }
2029 }
2030 if (idx < 0) {
2031 pr_err("%s: invalid index for port %d\n",
2032 __func__, port_id);
2033 ret = -EINVAL;
2034 goto end;
2035 }
2036 pr_debug("%s:index %d, dev[0x%x,0x%x]\n", __func__, idx,
2037 dev_map[idx].device_id, ds2_dap_params_states.device);
2038 dev_map[idx].active = true;
2039 dev_map[idx].copp_idx = copp_idx;
2040 dolby_data.param_id = DOLBY_COMMIT_ALL_TO_DSP;
2041 dolby_data.length = 0;
2042 dolby_data.data = NULL;
2043 dolby_data.device_id = dev_map[idx].device_id;
2044 pr_debug("%s: idx %d, active %d, dev id 0x%x, ref count %d\n",
2045 __func__, idx, dev_map[idx].active,
2046 dev_map[idx].device_id,
2047 dev_map[idx].stream_ref_count);
2048 if (dev_map[idx].stream_ref_count == 0) {
2049 /*perform next 3 func only if hard bypass enabled*/
2050 if (ds2_dap_params_states.dap_bypass_type ==
2051 DAP_HARD_BYPASS) {
2052 ret = msm_ds2_dap_alloc_and_store_cal_data(idx,
2053 ADM_PATH_PLAYBACK, 0);
2054 if (ret < 0) {
2055 pr_err("%s: Failed to alloc and store cal data for idx %d, device %d, copp_idx %d",
2056 __func__,
2057 idx, dev_map[idx].device_id,
2058 dev_map[idx].copp_idx);
2059 dev_map[idx].active = false;
2060 dev_map[idx].copp_idx = -1;
2061 goto end;
2062 }
2063
2064 ret = adm_set_softvolume(port_id, copp_idx,
2065 &softvol);
2066 if (ret < 0) {
2067 pr_err("%s: Soft volume ret error %d\n",
2068 __func__, ret);
2069 dev_map[idx].active = false;
2070 dev_map[idx].copp_idx = -1;
2071 goto end;
2072 }
2073
2074 ret = msm_ds2_dap_init_modules_in_topology(
2075 idx);
2076 if (ret < 0) {
2077 pr_err("%s: Failed to init modules in topolofy for idx %d, device %d, copp_idx %d\n",
2078 __func__, idx,
2079 dev_map[idx].device_id,
2080 dev_map[idx].copp_idx);
2081 dev_map[idx].active = false;
2082 dev_map[idx].copp_idx = -1;
2083 goto end;
2084 }
2085 }
2086
2087 ret = msm_ds2_dap_commit_params(&dolby_data, 0);
2088 if (ret < 0) {
2089 pr_debug("%s: commit params ret %d\n",
2090 __func__, ret);
2091 ret = 0;
2092 }
2093 }
2094 dev_map[idx].stream_ref_count++;
2095 if (is_custom_stereo_on) {
2096 ds2_dap_params_states.custom_stereo_onoff =
2097 is_custom_stereo_on;
2098 set_custom_stereo_onoff(idx,
2099 is_custom_stereo_on);
2100 }
2101 }
2102
2103end:
2104 return ret;
2105}
2106
2107void msm_ds2_dap_deinit(int port_id)
2108{
2109 /*
2110 * Get the active port corrresponding to the active device
2111 * Check if this is same as incoming port
2112 * Set it to invalid
2113 */
2114 int idx = -1, i;
2115
2116 pr_debug("%s: port_id %d\n", __func__, port_id);
2117 if (port_id != DOLBY_INVALID_PORT_ID) {
2118 for (i = 0; i < DS2_DEVICES_ALL; i++) {
2119 /* Active port */
2120 if ((dev_map[i].port_id == port_id) &&
2121 /* device part of active device */
2122 (dev_map[i].device_id &
2123 ds2_dap_params_states.device) &&
2124 /*
2125 * Need this check to avoid race condition of
2126 * active device being set and playback
2127 * instance opened
2128 */
2129 /* active device*/
2130 dev_map[i].active) {
2131 idx = i;
2132 if (dev_map[i].device_id == SPEAKER)
2133 continue;
2134 else
2135 break;
2136 }
2137 }
2138 if (idx < 0) {
2139 pr_err("%s: invalid index for port %d\n",
2140 __func__, port_id);
2141 return;
2142 }
2143 pr_debug("%s:index %d, dev [0x%x, 0x%x]\n", __func__, idx,
2144 dev_map[idx].device_id, ds2_dap_params_states.device);
2145 dev_map[idx].stream_ref_count--;
2146 if (dev_map[idx].stream_ref_count == 0) {
2147 /*perform next func only if hard bypass enabled*/
2148 if (ds2_dap_params_states.dap_bypass_type ==
2149 DAP_HARD_BYPASS) {
2150 msm_ds2_dap_free_cal_data(idx);
2151 }
2152 ds2_dap_params_states.device &= ~dev_map[idx].device_id;
2153 dev_map[idx].active = false;
2154 dev_map[idx].copp_idx = -1;
2155 }
2156 pr_debug("%s:idx %d, active %d, dev id 0x%x ref count %d\n",
2157 __func__, idx, dev_map[idx].active,
2158 dev_map[idx].device_id, dev_map[idx].stream_ref_count);
2159 }
2160}
2161
2162int msm_ds2_dap_set_custom_stereo_onoff(int port_id, int copp_idx,
2163 bool is_custom_stereo_enabled)
2164{
2165 int idx = -1, rc = 0, i;
2166
2167 pr_debug("%s: port_id %d\n", __func__, port_id);
2168 if (port_id != DOLBY_INVALID_PORT_ID) {
2169 for (i = 0; i < DS2_DEVICES_ALL; i++) {
2170 if ((dev_map[i].port_id == port_id) &&
2171 /* device part of active device */
2172 (dev_map[i].device_id &
2173 ds2_dap_params_states.device)) {
2174 idx = i;
2175 if (dev_map[i].device_id == SPEAKER)
2176 continue;
2177 else
2178 break;
2179 }
2180 }
2181 if (idx < 0) {
2182 pr_err("%s: invalid index for port %d\n",
2183 __func__, port_id);
2184 return rc;
2185 }
2186 ds2_dap_params_states.custom_stereo_onoff =
2187 is_custom_stereo_enabled;
2188 rc = set_custom_stereo_onoff(idx,
2189 is_custom_stereo_enabled);
2190 if (rc < 0) {
2191 pr_err("%s: Custom stereo err %d on port %d\n",
2192 __func__, rc, port_id);
2193 }
2194 }
2195 return rc;
2196}