blob: 6416e0a1ed6df78a334da01929e48c0d09f36b1a [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#include <linux/module.h>
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/platform_device.h>
17#include <linux/mfd/msm-adie-codec.h>
18#include <linux/mfd/marimba.h>
19#include <linux/debugfs.h>
20#include <linux/uaccess.h>
21#include <linux/string.h>
22
23#define MARIMBA_CDC_RX_CTL 0x81
24#define MARIMBA_CDC_RX_CTL_ST_EN_MASK 0x20
25#define MARIMBA_CDC_RX_CTL_ST_EN_SHFT 0x5
26#define MARIMBA_CODEC_CDC_LRXG 0x84
27#define MARIMBA_CODEC_CDC_RRXG 0x85
28#define MARIMBA_CODEC_CDC_LTXG 0x86
29#define MARIMBA_CODEC_CDC_RTXG 0x87
30
31#define MAX_MDELAY_US 2000
32#define MIN_MDELAY_US 1000
33
34struct adie_codec_path {
35 struct adie_codec_dev_profile *profile;
36 struct adie_codec_register_image img;
37 u32 hwsetting_idx;
38 u32 stage_idx;
39 u32 curr_stage;
40};
41
42static struct adie_codec_register adie_codec_tx_regs[] = {
43 { 0x04, 0xc0, 0x8C },
44 { 0x0D, 0xFF, 0x00 },
45 { 0x0E, 0xFF, 0x00 },
46 { 0x0F, 0xFF, 0x00 },
47 { 0x10, 0xF8, 0x68 },
48 { 0x11, 0xFE, 0x00 },
49 { 0x12, 0xFE, 0x00 },
50 { 0x13, 0xFF, 0x58 },
51 { 0x14, 0xFF, 0x00 },
52 { 0x15, 0xFE, 0x00 },
53 { 0x16, 0xFF, 0x00 },
54 { 0x1A, 0xFF, 0x00 },
55 { 0x80, 0x01, 0x00 },
56 { 0x82, 0x7F, 0x18 },
57 { 0x83, 0x1C, 0x00 },
58 { 0x86, 0xFF, 0xAC },
59 { 0x87, 0xFF, 0xAC },
60 { 0x89, 0xFF, 0xFF },
61 { 0x8A, 0xF0, 0x30 }
62};
63
64static struct adie_codec_register adie_codec_rx_regs[] = {
65 { 0x23, 0xF8, 0x00 },
66 { 0x24, 0x6F, 0x00 },
67 { 0x25, 0x7F, 0x00 },
68 { 0x26, 0xFC, 0x00 },
69 { 0x28, 0xFE, 0x00 },
70 { 0x29, 0xFE, 0x00 },
71 { 0x33, 0xFF, 0x00 },
72 { 0x34, 0xFF, 0x00 },
73 { 0x35, 0xFC, 0x00 },
74 { 0x36, 0xFE, 0x00 },
75 { 0x37, 0xFE, 0x00 },
76 { 0x38, 0xFE, 0x00 },
77 { 0x39, 0xF0, 0x00 },
78 { 0x3A, 0xFF, 0x0A },
79 { 0x3B, 0xFC, 0xAC },
80 { 0x3C, 0xFC, 0xAC },
81 { 0x3D, 0xFF, 0x55 },
82 { 0x3E, 0xFF, 0x55 },
83 { 0x3F, 0xCF, 0x00 },
84 { 0x40, 0x3F, 0x00 },
85 { 0x41, 0x3F, 0x00 },
86 { 0x42, 0xFF, 0x00 },
87 { 0x43, 0xF7, 0x00 },
88 { 0x43, 0xF7, 0x00 },
89 { 0x43, 0xF7, 0x00 },
90 { 0x43, 0xF7, 0x00 },
91 { 0x44, 0xF7, 0x00 },
92 { 0x45, 0xFF, 0x00 },
93 { 0x46, 0xFF, 0x00 },
94 { 0x47, 0xF7, 0x00 },
95 { 0x48, 0xF7, 0x00 },
96 { 0x49, 0xFF, 0x00 },
97 { 0x4A, 0xFF, 0x00 },
98 { 0x80, 0x02, 0x00 },
99 { 0x81, 0xFF, 0x4C },
100 { 0x83, 0x23, 0x00 },
101 { 0x84, 0xFF, 0xAC },
102 { 0x85, 0xFF, 0xAC },
103 { 0x88, 0xFF, 0xFF },
104 { 0x8A, 0x0F, 0x03 },
105 { 0x8B, 0xFF, 0xAC },
106 { 0x8C, 0x03, 0x01 },
107 { 0x8D, 0xFF, 0x00 },
108 { 0x8E, 0xFF, 0x00 }
109};
110
111static struct adie_codec_register adie_codec_lb_regs[] = {
112 { 0x2B, 0x8F, 0x02 },
113 { 0x2C, 0x8F, 0x02 }
114};
115
116struct adie_codec_state {
117 struct adie_codec_path path[ADIE_CODEC_MAX];
118 u32 ref_cnt;
119 struct marimba *pdrv_ptr;
120 struct marimba_codec_platform_data *codec_pdata;
121 struct mutex lock;
122};
123
124static struct adie_codec_state adie_codec;
125
126/* Array containing write details of Tx and RX Digital Volume
127 Tx and Rx and both the left and right channel use the same data
128*/
129u8 adie_codec_rx_tx_dig_vol_data[] = {
130 0x81, 0x82, 0x83, 0x84,
131 0x85, 0x86, 0x87, 0x88,
132 0x89, 0x8a, 0x8b, 0x8c,
133 0x8d, 0x8e, 0x8f, 0x90,
134 0x91, 0x92, 0x93, 0x94,
135 0x95, 0x96, 0x97, 0x98,
136 0x99, 0x9a, 0x9b, 0x9c,
137 0x9d, 0x9e, 0x9f, 0xa0,
138 0xa1, 0xa2, 0xa3, 0xa4,
139 0xa5, 0xa6, 0xa7, 0xa8,
140 0xa9, 0xaa, 0xab, 0xac,
141 0xad, 0xae, 0xaf, 0xb0,
142 0xb1, 0xb2, 0xb3, 0xb4,
143 0xb5, 0xb6, 0xb7, 0xb8,
144 0xb9, 0xba, 0xbb, 0xbc,
145 0xbd, 0xbe, 0xbf, 0xc0,
146 0xc1, 0xc2, 0xc3, 0xc4,
147 0xc5, 0xc6, 0xc7, 0xc8,
148 0xc9, 0xca, 0xcb, 0xcc,
149 0xcd, 0xce, 0xcf, 0xd0,
150 0xd1, 0xd2, 0xd3, 0xd4,
151 0xd5, 0xd6, 0xd7, 0xd8,
152 0xd9, 0xda, 0xdb, 0xdc,
153 0xdd, 0xde, 0xdf, 0xe0,
154 0xe1, 0xe2, 0xe3, 0xe4,
155 0xe5, 0xe6, 0xe7, 0xe8,
156 0xe9, 0xea, 0xeb, 0xec,
157 0xed, 0xee, 0xf0, 0xf1,
158 0xf2, 0xf3, 0xf4, 0xf5,
159 0xf6, 0xf7, 0xf8, 0xf9,
160 0xfa, 0xfb, 0xfc, 0xfd,
161 0xfe, 0xff, 0x00, 0x01,
162 0x02, 0x03, 0x04, 0x05,
163 0x06, 0x07, 0x08, 0x09,
164 0x0a, 0x0b, 0x0c, 0x0d,
165 0x0e, 0x0f, 0x10, 0x11,
166 0x12, 0x13, 0x14, 0x15,
167 0x16, 0x17, 0x18, 0x19,
168 0x1a, 0x1b, 0x1c, 0x1d,
169 0x1e, 0x1f, 0x20, 0x21,
170 0x22, 0x23, 0x24, 0x25,
171 0x26, 0x27, 0x28, 0x29,
172 0x2a, 0x2b, 0x2c, 0x2d,
173 0x2e, 0x2f, 0x30, 0x31,
174 0x32, 0x33, 0x34, 0x35,
175 0x36, 0x37, 0x38, 0x39,
176 0x3a, 0x3b, 0x3c, 0x3d,
177 0x3e, 0x3f, 0x40, 0x41,
178 0x42, 0x43, 0x44, 0x45,
179 0x46, 0x47, 0x48, 0x49,
180 0x4a, 0x4b, 0x4c, 0x4d,
181 0x4e, 0x4f, 0x50, 0x51,
182 0x52, 0x53, 0x54, 0x55,
183 0x56, 0x57, 0x58, 0x59,
184 0x5a, 0x5b, 0x5c, 0x5d,
185 0x5e, 0x5f, 0x60, 0x61,
186 0x62, 0x63, 0x64, 0x65,
187 0x66, 0x67, 0x68, 0x69,
188 0x6a, 0x6b, 0x6c, 0x6d,
189 0x6e, 0x6f, 0x70, 0x71,
190 0x72, 0x73, 0x74, 0x75,
191 0x76, 0x77, 0x78, 0x79,
192 0x7a, 0x7b, 0x7c, 0x7d,
193 0x7e, 0x7f
194};
195
196enum adie_vol_type {
197 ADIE_CODEC_RX_DIG_VOL,
198 ADIE_CODEC_TX_DIG_VOL,
199 ADIE_CODEC_VOL_TYPE_MAX
200};
201
202struct adie_codec_ch_vol_cntrl {
203 u8 codec_reg;
204 u8 codec_mask;
205 u8 *vol_cntrl_data;
206};
207
208struct adie_codec_vol_cntrl_data {
209
210 enum adie_vol_type vol_type;
211
212 /* Jump length used while doing writes in incremental fashion */
213 u32 jump_length;
214 s32 min_mb; /* Min Db applicable to the vol control */
215 s32 max_mb; /* Max Db applicable to the vol control */
216 u32 step_in_mb;
217 u32 steps; /* No of steps allowed for this vol type */
218
219 struct adie_codec_ch_vol_cntrl *ch_vol_cntrl_info;
220};
221
222static struct adie_codec_ch_vol_cntrl adie_codec_rx_vol_cntrl[] = {
223 {MARIMBA_CODEC_CDC_LRXG, 0xff, adie_codec_rx_tx_dig_vol_data},
224 {MARIMBA_CODEC_CDC_RRXG, 0xff, adie_codec_rx_tx_dig_vol_data}
225};
226
227static struct adie_codec_ch_vol_cntrl adie_codec_tx_vol_cntrl[] = {
228 {MARIMBA_CODEC_CDC_LTXG, 0xff, adie_codec_rx_tx_dig_vol_data},
229 {MARIMBA_CODEC_CDC_RTXG, 0xff, adie_codec_rx_tx_dig_vol_data}
230};
231
232static struct adie_codec_vol_cntrl_data adie_codec_vol_cntrl[] = {
233 {ADIE_CODEC_RX_DIG_VOL, 5100, -12700, 12700, 100, 255,
234 adie_codec_rx_vol_cntrl},
235
236 {ADIE_CODEC_TX_DIG_VOL, 5100, -12700, 12700, 100, 255,
237 adie_codec_tx_vol_cntrl}
238};
239
240static int adie_codec_write(u8 reg, u8 mask, u8 val)
241{
242 int rc;
243
244 rc = marimba_write_bit_mask(adie_codec.pdrv_ptr, reg, &val, 1, mask);
245 if (IS_ERR_VALUE(rc)) {
246 pr_err("%s: fail to write reg %x\n", __func__, reg);
247 return -EIO;
248 }
249
250 pr_debug("%s: write reg %x val %x\n", __func__, reg, val);
251
252 return 0;
253}
254
255static int adie_codec_read(u8 reg, u8 *val)
256{
257 return marimba_read(adie_codec.pdrv_ptr, reg, val, 1);
258}
259
260static int adie_codec_read_dig_vol(enum adie_vol_type vol_type, u32 chan_index,
261 u32 *cur_index)
262{
263 u32 counter;
264 u32 size;
265 u8 reg, mask, cur_val;
266 int rc;
267
268 reg =
269 adie_codec_vol_cntrl[vol_type].
270 ch_vol_cntrl_info[chan_index].codec_reg;
271
272 mask =
273 adie_codec_vol_cntrl[vol_type].
274 ch_vol_cntrl_info[chan_index].codec_mask;
275
276 rc = marimba_read(adie_codec.pdrv_ptr, reg, &cur_val, 1);
277
278 if (IS_ERR_VALUE(rc)) {
279 pr_err("%s: fail to read reg %x\n", __func__, reg);
280 return -EIO;
281 }
282
283 cur_val = cur_val & mask;
284
285 pr_debug("%s: reg 0x%x mask 0x%x reg_value = 0x%x"
286 "vol_type = %d\n", __func__, reg, mask, cur_val, vol_type);
287
288 size = adie_codec_vol_cntrl[vol_type].steps;
289
290 for (counter = 0; counter <= size; counter++) {
291
292 if (adie_codec_vol_cntrl[vol_type].ch_vol_cntrl_info
293 [chan_index].vol_cntrl_data[counter] == cur_val) {
294 *cur_index = counter;
295 return 0;
296 }
297 }
298
299 pr_err("%s: could not find 0x%x in reg 0x%x values array\n",
300 __func__, cur_val, reg);
301
302 return -EINVAL;;
303}
304
305static int adie_codec_set_dig_vol(enum adie_vol_type vol_type, u32 chan_index,
306 u32 cur_index, u32 target_index)
307{
308 u32 count;
309 u8 reg, mask, val;
310 u32 i;
311 u32 index;
312 u32 index_jump;
313
314 int rc;
315
316 index_jump = adie_codec_vol_cntrl[vol_type].jump_length;
317
318 reg =
319 adie_codec_vol_cntrl[vol_type].
320 ch_vol_cntrl_info[chan_index].codec_reg;
321
322 mask =
323 adie_codec_vol_cntrl[vol_type].
324 ch_vol_cntrl_info[chan_index].codec_mask;
325
326 /* compare the target index with current index */
327 if (cur_index < target_index) {
328
329 /* Volume is being increased loop and increase it in 4-5 steps
330 */
331 count = ((target_index - cur_index) * 100 / index_jump);
332 index = cur_index;
333
334 for (i = 1; i <= count; i++) {
335 index = index + (int)(index_jump / 100);
336
337 val =
338 adie_codec_vol_cntrl[vol_type].ch_vol_cntrl_info
339 [chan_index].vol_cntrl_data[index];
340
341 pr_debug("%s: write reg %x val 0x%x\n",
342 __func__, reg, val);
343
344 rc = adie_codec_write(reg, mask, val);
345 if (rc < 0) {
346 pr_err("%s: write reg %x val 0x%x failed\n",
347 __func__, reg, val);
348 return rc;
349 }
350 }
351
352 /*do one final write to take it to the target index level */
353 val =
354 adie_codec_vol_cntrl[vol_type].ch_vol_cntrl_info
355 [chan_index].vol_cntrl_data[target_index];
356
357 pr_debug("%s: write reg %x val 0x%x\n", __func__, reg, val);
358
359 rc = adie_codec_write(reg, mask, val);
360
361 if (rc < 0) {
362 pr_err("%s: write reg %x val 0x%x failed\n",
363 __func__, reg, val);
364 return rc;
365 }
366
367 } else {
368
369 /* Volume is being decreased from the current setting */
370 index = cur_index;
371 /* loop and decrease it in 4-5 steps */
372 count = ((cur_index - target_index) * 100 / index_jump);
373
374 for (i = 1; i <= count; i++) {
375 index = index - (int)(index_jump / 100);
376
377 val =
378 adie_codec_vol_cntrl[vol_type].ch_vol_cntrl_info
379 [chan_index].vol_cntrl_data[index];
380
381 pr_debug("%s: write reg %x val 0x%x\n",
382 __func__, reg, val);
383
384 rc = adie_codec_write(reg, mask, val);
385 if (rc < 0) {
386 pr_err("%s: write reg %x val 0x%x failed\n",
387 __func__, reg, val);
388 return rc;
389 }
390 }
391
392 /* do one final write to take it to the target index level */
393 val =
394 adie_codec_vol_cntrl[vol_type].ch_vol_cntrl_info
395 [chan_index].vol_cntrl_data[target_index];
396
397 pr_debug("%s: write reg %x val 0x%x\n", __func__, reg, val);
398
399 rc = adie_codec_write(reg, mask, val);
400
401 if (rc < 0) {
402 pr_err("%s: write reg %x val 0x%x failed\n",
403 __func__, reg, val);
404 return rc;
405 }
406 }
407 return 0;
408}
409
410static int marimba_adie_codec_set_device_digital_volume(
411 struct adie_codec_path *path_ptr,
412 u32 num_channels, u32 vol_percentage /* in percentage */)
413{
414 enum adie_vol_type vol_type;
415 s32 milli_bel;
416 u32 chan_index;
417 u32 step_index;
418 u32 cur_step_index = 0;
419
420 if (!path_ptr || (path_ptr->curr_stage !=
421 ADIE_CODEC_DIGITAL_ANALOG_READY)) {
422 pr_info("%s: Marimba codec not ready for volume control\n",
423 __func__);
424 return -EPERM;
425 }
426
427 if (num_channels > 2) {
428 pr_err("%s: Marimba codec only supports max two channels\n",
429 __func__);
430 return -EINVAL;
431 }
432
433 if (path_ptr->profile->path_type == ADIE_CODEC_RX)
434 vol_type = ADIE_CODEC_RX_DIG_VOL;
435 else if (path_ptr->profile->path_type == ADIE_CODEC_TX)
436 vol_type = ADIE_CODEC_TX_DIG_VOL;
437 else {
438 pr_err("%s: invalid device data neither RX nor TX\n",
439 __func__);
440 return -EINVAL;
441 }
442
443 milli_bel = ((adie_codec_vol_cntrl[vol_type].max_mb -
444 adie_codec_vol_cntrl[vol_type].min_mb) *
445 vol_percentage) / 100;
446
447 milli_bel = adie_codec_vol_cntrl[vol_type].min_mb + milli_bel;
448
449 pr_debug("%s: milli bell = %d vol_type = %d vol_percentage = %d"
450 " num_cha = %d \n",
451 __func__, milli_bel, vol_type, vol_percentage, num_channels);
452
453
454 step_index = ((milli_bel
455 - adie_codec_vol_cntrl[vol_type].min_mb
456 + (adie_codec_vol_cntrl[vol_type].step_in_mb / 2))
457 / adie_codec_vol_cntrl[vol_type].step_in_mb);
458
459
460 for (chan_index = 0; chan_index < num_channels; chan_index++) {
461 adie_codec_read_dig_vol(vol_type, chan_index, &cur_step_index);
462
463 pr_debug("%s: cur_step_index = %u current vol = 0x%x\n",
464 __func__, cur_step_index,
465 adie_codec_vol_cntrl[vol_type].ch_vol_cntrl_info
466 [chan_index].vol_cntrl_data[cur_step_index]);
467
468 pr_debug("%s: step index = %u new volume = 0x%x\n",
469 __func__, step_index,
470 adie_codec_vol_cntrl[vol_type].ch_vol_cntrl_info
471 [chan_index].vol_cntrl_data[step_index]);
472
473 adie_codec_set_dig_vol(vol_type, chan_index, cur_step_index,
474 step_index);
475
476 }
477 return 0;
478}
479
480static int marimba_adie_codec_setpath(struct adie_codec_path *path_ptr,
481 u32 freq_plan, u32 osr)
482{
483 int rc = 0;
484 u32 i, freq_idx = 0, freq = 0;
485
486 if ((path_ptr->curr_stage != ADIE_CODEC_DIGITAL_OFF) &&
487 (path_ptr->curr_stage != ADIE_CODEC_FLASH_IMAGE)) {
488 rc = -EBUSY;
489 goto error;
490 }
491
492 for (i = 0; i < path_ptr->profile->setting_sz; i++) {
493 if (path_ptr->profile->settings[i].osr == osr) {
494 if (path_ptr->profile->settings[i].freq_plan >=
495 freq_plan) {
496 if (freq == 0) {
497 freq = path_ptr->profile->settings[i].
498 freq_plan;
499 freq_idx = i;
500 } else if (path_ptr->profile->settings[i].
501 freq_plan < freq) {
502 freq = path_ptr->profile->settings[i].
503 freq_plan;
504 freq_idx = i;
505 }
506 }
507 }
508 }
509
510 if (freq_idx >= path_ptr->profile->setting_sz)
511 rc = -ENODEV;
512 else {
513 path_ptr->hwsetting_idx = freq_idx;
514 path_ptr->stage_idx = 0;
515 }
516
517error:
518 return rc;
519}
520
521static u32 marimba_adie_codec_freq_supported(
522 struct adie_codec_dev_profile *profile,
523 u32 requested_freq)
524{
525 u32 i, rc = -EINVAL;
526
527 for (i = 0; i < profile->setting_sz; i++) {
528 if (profile->settings[i].freq_plan >= requested_freq) {
529 rc = 0;
530 break;
531 }
532 }
533 return rc;
534}
535
536static int marimba_adie_codec_enable_sidetone(
537 struct adie_codec_path *rx_path_ptr,
538 u32 enable)
539{
540 int rc = 0;
541
542 pr_debug("%s()\n", __func__);
543
544 mutex_lock(&adie_codec.lock);
545
546 if (!rx_path_ptr || &adie_codec.path[ADIE_CODEC_RX] != rx_path_ptr) {
547 pr_err("%s: invalid path pointer\n", __func__);
548 rc = -EINVAL;
549 goto error;
550 } else if (rx_path_ptr->curr_stage !=
551 ADIE_CODEC_DIGITAL_ANALOG_READY) {
552 pr_err("%s: bad state\n", __func__);
553 rc = -EPERM;
554 goto error;
555 }
556
557 if (enable)
558 rc = adie_codec_write(MARIMBA_CDC_RX_CTL,
559 MARIMBA_CDC_RX_CTL_ST_EN_MASK,
560 (0x1 << MARIMBA_CDC_RX_CTL_ST_EN_SHFT));
561 else
562 rc = adie_codec_write(MARIMBA_CDC_RX_CTL,
563 MARIMBA_CDC_RX_CTL_ST_EN_MASK, 0);
564
565error:
566 mutex_unlock(&adie_codec.lock);
567 return rc;
568}
569
570static void adie_codec_reach_stage_action(struct adie_codec_path *path_ptr,
571 u32 stage)
572{
573 u32 iter;
574 struct adie_codec_register *reg_info;
575
576 if (stage == ADIE_CODEC_FLASH_IMAGE) {
577 /* perform reimage */
578 for (iter = 0; iter < path_ptr->img.img_sz; iter++) {
579 reg_info = &path_ptr->img.regs[iter];
580 adie_codec_write(reg_info->reg,
581 reg_info->mask, reg_info->val);
582 }
583 }
584}
585
586static int marimba_adie_codec_proceed_stage(struct adie_codec_path *path_ptr,
587 u32 state)
588{
589 int rc = 0, loop_exit = 0;
590 struct adie_codec_action_unit *curr_action;
591 struct adie_codec_hwsetting_entry *setting;
592 u8 reg, mask, val;
593
594 mutex_lock(&adie_codec.lock);
595 setting = &path_ptr->profile->settings[path_ptr->hwsetting_idx];
596 while (!loop_exit) {
597 curr_action = &setting->actions[path_ptr->stage_idx];
598 switch (curr_action->type) {
599 case ADIE_CODEC_ACTION_ENTRY:
600 ADIE_CODEC_UNPACK_ENTRY(curr_action->action,
601 reg, mask, val);
602 adie_codec_write(reg, mask, val);
603 break;
604 case ADIE_CODEC_ACTION_DELAY_WAIT:
605 if (curr_action->action > MAX_MDELAY_US)
606 msleep(curr_action->action/1000);
607 else if (curr_action->action < MIN_MDELAY_US)
608 udelay(curr_action->action);
609 else
610 mdelay(curr_action->action/1000);
611 break;
612 case ADIE_CODEC_ACTION_STAGE_REACHED:
613 adie_codec_reach_stage_action(path_ptr,
614 curr_action->action);
615 if (curr_action->action == state) {
616 path_ptr->curr_stage = state;
617 loop_exit = 1;
618 }
619 break;
620 default:
621 BUG();
622 }
623
624 path_ptr->stage_idx++;
625 if (path_ptr->stage_idx == setting->action_sz)
626 path_ptr->stage_idx = 0;
627 }
628 mutex_unlock(&adie_codec.lock);
629 return rc;
630}
631
632static void marimba_codec_bring_up(void)
633{
634 /* bring up sequence for Marimba codec core
635 * ensure RESET_N = 0 and GDFS_CLAMP_EN=1 -
636 * set GDFS_EN_FEW=1 then GDFS_EN_REST=1 then
637 * GDFS_CLAMP_EN = 0 and finally RESET_N = 1
638 * Marimba codec bring up should use the Marimba
639 * slave address after which the codec slave
640 * address can be used
641 */
642
643 /* Bring up codec */
644 adie_codec_write(0xFF, 0xFF, 0x08);
645
646 /* set GDFS_EN_FEW=1 */
647 adie_codec_write(0xFF, 0xFF, 0x0a);
648
649 /* set GDFS_EN_REST=1 */
650 adie_codec_write(0xFF, 0xFF, 0x0e);
651
652 /* set RESET_N=1 */
653 adie_codec_write(0xFF, 0xFF, 0x07);
654
655 adie_codec_write(0xFF, 0xFF, 0x17);
656
657 /* enable band gap */
658 adie_codec_write(0x03, 0xFF, 0x04);
659
660 /* dither delay selected and dmic gain stage bypassed */
661 adie_codec_write(0x8F, 0xFF, 0x44);
662}
663
664static void marimba_codec_bring_down(void)
665{
666 adie_codec_write(0xFF, 0xFF, 0x07);
667 adie_codec_write(0xFF, 0xFF, 0x06);
668 adie_codec_write(0xFF, 0xFF, 0x0e);
669 adie_codec_write(0xFF, 0xFF, 0x08);
670 adie_codec_write(0x03, 0xFF, 0x00);
671}
672
673static int marimba_adie_codec_open(struct adie_codec_dev_profile *profile,
674 struct adie_codec_path **path_pptr)
675{
676 int rc = 0;
677
678 mutex_lock(&adie_codec.lock);
679
680 if (!profile || !path_pptr) {
681 rc = -EINVAL;
682 goto error;
683 }
684
685 if (adie_codec.path[profile->path_type].profile) {
686 rc = -EBUSY;
687 goto error;
688 }
689
690 if (!adie_codec.ref_cnt) {
691
692 if (adie_codec.codec_pdata &&
693 adie_codec.codec_pdata->marimba_codec_power) {
694
695 rc = adie_codec.codec_pdata->marimba_codec_power(1);
696 if (rc) {
697 pr_err("%s: could not power up marimba "
698 "codec\n", __func__);
699 goto error;
700 }
701 }
702 marimba_codec_bring_up();
703 }
704
705 adie_codec.path[profile->path_type].profile = profile;
706 *path_pptr = (void *) &adie_codec.path[profile->path_type];
707 adie_codec.ref_cnt++;
708 adie_codec.path[profile->path_type].hwsetting_idx = 0;
709 adie_codec.path[profile->path_type].curr_stage = ADIE_CODEC_FLASH_IMAGE;
710 adie_codec.path[profile->path_type].stage_idx = 0;
711
712
713error:
714
715 mutex_unlock(&adie_codec.lock);
716 return rc;
717}
718
719static int marimba_adie_codec_close(struct adie_codec_path *path_ptr)
720{
721 int rc = 0;
722
723 mutex_lock(&adie_codec.lock);
724
725 if (!path_ptr) {
726 rc = -EINVAL;
727 goto error;
728 }
729 if (path_ptr->curr_stage != ADIE_CODEC_DIGITAL_OFF)
730 adie_codec_proceed_stage(path_ptr, ADIE_CODEC_DIGITAL_OFF);
731
732 BUG_ON(!adie_codec.ref_cnt);
733
734 path_ptr->profile = NULL;
735 adie_codec.ref_cnt--;
736
737 if (!adie_codec.ref_cnt) {
738
739 marimba_codec_bring_down();
740
741 if (adie_codec.codec_pdata &&
742 adie_codec.codec_pdata->marimba_codec_power) {
743
744 rc = adie_codec.codec_pdata->marimba_codec_power(0);
745 if (rc) {
746 pr_err("%s: could not power down marimba "
747 "codec\n", __func__);
748 goto error;
749 }
750 }
751 }
752
753error:
754 mutex_unlock(&adie_codec.lock);
755 return rc;
756}
757
758static const struct adie_codec_operations marimba_adie_ops = {
759 .codec_id = MARIMBA_ID,
760 .codec_open = marimba_adie_codec_open,
761 .codec_close = marimba_adie_codec_close,
762 .codec_setpath = marimba_adie_codec_setpath,
763 .codec_proceed_stage = marimba_adie_codec_proceed_stage,
764 .codec_freq_supported = marimba_adie_codec_freq_supported,
765 .codec_enable_sidetone = marimba_adie_codec_enable_sidetone,
766 .codec_set_device_digital_volume =
767 marimba_adie_codec_set_device_digital_volume,
768};
769
770#ifdef CONFIG_DEBUG_FS
771static struct dentry *debugfs_marimba_dent;
772static struct dentry *debugfs_peek;
773static struct dentry *debugfs_poke;
774static struct dentry *debugfs_power;
775
776static unsigned char read_data;
777
778static int codec_debug_open(struct inode *inode, struct file *file)
779{
780 file->private_data = inode->i_private;
781 return 0;
782}
783
784static int get_parameters(char *buf, long int *param1, int num_of_par)
785{
786 char *token;
787 int base, cnt;
788
789 token = strsep(&buf, " ");
790
791 for (cnt = 0; cnt < num_of_par; cnt++) {
792 if (token != NULL) {
793 if ((token[1] == 'x') || (token[1] == 'X'))
794 base = 16;
795 else
796 base = 10;
797
798 if (strict_strtoul(token, base, &param1[cnt]) != 0)
799 return -EINVAL;
800
801 token = strsep(&buf, " ");
802 }
803 else
804 return -EINVAL;
805 }
806 return 0;
807}
808
809static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
810 size_t count, loff_t *ppos)
811{
812 char lbuf[8];
813
814 snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
815 return simple_read_from_buffer(ubuf, count, ppos, lbuf, strlen(lbuf));
816}
817
818static ssize_t codec_debug_write(struct file *filp,
819 const char __user *ubuf, size_t cnt, loff_t *ppos)
820{
821 char *access_str = filp->private_data;
822 char lbuf[32];
823 int rc;
824 long int param[5];
825
826 if (cnt > sizeof(lbuf) - 1)
827 return -EINVAL;
828
829 rc = copy_from_user(lbuf, ubuf, cnt);
830 if (rc)
831 return -EFAULT;
832
833 lbuf[cnt] = '\0';
834
835 if (!strcmp(access_str, "power")) {
836 if (get_parameters(lbuf, param, 1) == 0) {
837 switch (param[0]) {
838 case 1:
839 adie_codec.codec_pdata->marimba_codec_power(1);
840 marimba_codec_bring_up();
841 break;
842 case 0:
843 marimba_codec_bring_down();
844 adie_codec.codec_pdata->marimba_codec_power(0);
845 break;
846 default:
847 rc = -EINVAL;
848 break;
849 }
850 } else
851 rc = -EINVAL;
852 } else if (!strcmp(access_str, "poke")) {
853 /* write */
854 rc = get_parameters(lbuf, param, 2);
855 if ((param[0] <= 0xFF) && (param[1] <= 0xFF) &&
856 (rc == 0))
857 adie_codec_write(param[0], 0xFF, param[1]);
858 else
859 rc = -EINVAL;
860 } else if (!strcmp(access_str, "peek")) {
861 /* read */
862 rc = get_parameters(lbuf, param, 1);
863 if ((param[0] <= 0xFF) && (rc == 0))
864 adie_codec_read(param[0], &read_data);
865 else
866 rc = -EINVAL;
867 }
868
869 if (rc == 0)
870 rc = cnt;
871 else
872 pr_err("%s: rc = %d\n", __func__, rc);
873
874 return rc;
875}
876
877static const struct file_operations codec_debug_ops = {
878 .open = codec_debug_open,
879 .write = codec_debug_write,
880 .read = codec_debug_read
881};
882#endif
883
884static int marimba_codec_probe(struct platform_device *pdev)
885{
886 int rc;
887
888 adie_codec.pdrv_ptr = platform_get_drvdata(pdev);
889 adie_codec.codec_pdata = pdev->dev.platform_data;
890
891 if (adie_codec.codec_pdata->snddev_profile_init)
892 adie_codec.codec_pdata->snddev_profile_init();
893
894 /* Register the marimba ADIE operations */
895 rc = adie_codec_register_codec_operations(&marimba_adie_ops);
896
897#ifdef CONFIG_DEBUG_FS
898 debugfs_marimba_dent = debugfs_create_dir("msm_adie_codec", 0);
899 if (!IS_ERR(debugfs_marimba_dent)) {
900 debugfs_peek = debugfs_create_file("peek",
901 S_IFREG | S_IRUGO, debugfs_marimba_dent,
902 (void *) "peek", &codec_debug_ops);
903
904 debugfs_poke = debugfs_create_file("poke",
905 S_IFREG | S_IRUGO, debugfs_marimba_dent,
906 (void *) "poke", &codec_debug_ops);
907
908 debugfs_power = debugfs_create_file("power",
909 S_IFREG | S_IRUGO, debugfs_marimba_dent,
910 (void *) "power", &codec_debug_ops);
911 }
912#endif
913 return rc;
914}
915
916static struct platform_driver marimba_codec_driver = {
917 .probe = marimba_codec_probe,
918 .driver = {
919 .name = "marimba_codec",
920 .owner = THIS_MODULE,
921 },
922};
923
924static int __init marimba_codec_init(void)
925{
926 s32 rc;
927
928 rc = platform_driver_register(&marimba_codec_driver);
929 if (IS_ERR_VALUE(rc))
930 goto error;
931
932 adie_codec.path[ADIE_CODEC_TX].img.regs = adie_codec_tx_regs;
933 adie_codec.path[ADIE_CODEC_TX].img.img_sz =
934 ARRAY_SIZE(adie_codec_tx_regs);
935 adie_codec.path[ADIE_CODEC_RX].img.regs = adie_codec_rx_regs;
936 adie_codec.path[ADIE_CODEC_RX].img.img_sz =
937 ARRAY_SIZE(adie_codec_rx_regs);
938 adie_codec.path[ADIE_CODEC_LB].img.regs = adie_codec_lb_regs;
939 adie_codec.path[ADIE_CODEC_LB].img.img_sz =
940 ARRAY_SIZE(adie_codec_lb_regs);
941 mutex_init(&adie_codec.lock);
942
943error:
944 return rc;
945}
946
947static void __exit marimba_codec_exit(void)
948{
949#ifdef CONFIG_DEBUG_FS
950 debugfs_remove(debugfs_peek);
951 debugfs_remove(debugfs_poke);
952 debugfs_remove(debugfs_power);
953 debugfs_remove(debugfs_marimba_dent);
954#endif
955 platform_driver_unregister(&marimba_codec_driver);
956}
957
958module_init(marimba_codec_init);
959module_exit(marimba_codec_exit);
960
961MODULE_DESCRIPTION("Marimba codec driver");
962MODULE_VERSION("1.0");
963MODULE_LICENSE("GPL v2");