UPSTREAM: ASoC: da7219: Remove support for 32KHz PLL mode
[firefly-linux-kernel-4.4.55.git] / sound / soc / codecs / rt5640_ioctl.c
1 /*
2  * rt5640_ioctl.h  --  RT5640 ALSA SoC audio driver IO control
3  *
4  * Copyright 2012 Realtek Microelectronics
5  * Author: Bard <bardliao@realtek.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11
12 #include <linux/spi/spi.h>
13 #include <sound/soc.h>
14 #include "rt56xx_ioctl.h"
15 #include "rt5640_ioctl.h"
16 #include "rt5640.h"
17 #if defined(CONFIG_SND_SOC_RT5642_MODULE) || defined(CONFIG_SND_SOC_RT5642)
18 #include "rt5640-dsp.h"
19 #endif
20
21 static hweq_t hweq_param[] = {
22         {/* NORMAL */
23                 {0},
24                 {0},
25                 0x0000,
26         },
27         {/* SPK */
28                 {0xa0,  0xa1,   0xa2,   0xa3,   0xa4,   0xa5,   0xa6,   0xa7,   0xa8,   0xa9,   0xaa,   0xab,   0xac,   0xad,   0xae,   0xaf,   0xb0,   0xb1,   0xb2},
29                 {0x1c10,0x01f4, 0xc5e9, 0x1a98, 0x1d2c, 0xc882, 0x1c10, 0x01f4, 0xe904, 0x1c10, 0x01f4, 0xe904, 0x1c10, 0x01f4, 0x1c10, 0x01f4, 0x2000, 0x0000, 0x2000},
30                 0x0000,
31         },
32         {/* HP */
33                 {0xa0,  0xa1,   0xa2,   0xa3,   0xa4,   0xa5,   0xa6,   0xa7,   0xa8,   0xa9,   0xaa,   0xab,   0xac,   0xad,   0xae,   0xaf,   0xb0,   0xb1,   0xb2},
34                 {0x1c10,0x01f4, 0xc5e9, 0x1a98, 0x1d2c, 0xc882, 0x1c10, 0x01f4, 0xe904, 0x1c10, 0x01f4, 0xe904, 0x1c10, 0x01f4, 0x1c10, 0x01f4, 0x2000, 0x0000, 0x2000},
35                 0x0000,
36         },
37 };
38 #define RT5640_HWEQ_LEN ARRAY_SIZE(hweq_param)
39
40 int rt5640_update_eqmode(
41         struct snd_soc_codec *codec, int mode)
42 {
43         struct rt56xx_ops *ioctl_ops = rt56xx_get_ioctl_ops();
44         int i;
45         static int eqmode;
46
47         if(codec == NULL ||  mode >= RT5640_HWEQ_LEN)
48                 return -EINVAL;
49
50         dev_dbg(codec->dev, "%s(): mode=%d\n", __func__, mode);
51         if(mode == eqmode)
52                 return 0;
53
54         for(i = 0; i <= EQ_REG_NUM; i++) {
55                 if(hweq_param[mode].reg[i])
56                         ioctl_ops->index_write(codec, hweq_param[mode].reg[i],
57                                         hweq_param[mode].value[i]);
58                 else
59                         break;
60         }
61         snd_soc_update_bits(codec, RT5640_EQ_CTRL2, RT5640_EQ_CTRL_MASK,
62                                         hweq_param[mode].ctrl);
63         snd_soc_update_bits(codec, RT5640_EQ_CTRL1,
64                 RT5640_EQ_UPD, RT5640_EQ_UPD);
65         snd_soc_update_bits(codec, RT5640_EQ_CTRL1, RT5640_EQ_UPD, 0);
66         
67         eqmode = mode;
68
69         return 0;
70 }
71
72 static void set_drc_agc_enable(struct snd_soc_codec *codec, int enable, int path)
73 {
74         snd_soc_update_bits(codec, RT5640_DRC_AGC_1, RT5640_DRC_AGC_P_MASK |
75                 RT5640_DRC_AGC_MASK | RT5640_DRC_AGC_UPD,
76                 enable << RT5640_DRC_AGC_SFT | path << RT5640_DRC_AGC_P_SFT |
77                 1 << RT5640_DRC_AGC_UPD_BIT);
78 }
79
80 static void set_drc_agc_parameters(struct snd_soc_codec *codec, int attack_rate,
81                         int sample_rate, int recovery_rate, int limit_level)
82 {
83         snd_soc_update_bits(codec, RT5640_DRC_AGC_3, RT5640_DRC_AGC_TAR_MASK,
84                                 limit_level << RT5640_DRC_AGC_TAR_SFT);
85         snd_soc_update_bits(codec, RT5640_DRC_AGC_1, RT5640_DRC_AGC_AR_MASK |
86                 RT5640_DRC_AGC_R_MASK | RT5640_DRC_AGC_UPD |
87                 RT5640_DRC_AGC_RC_MASK, attack_rate << RT5640_DRC_AGC_AR_SFT |
88                 sample_rate << RT5640_DRC_AGC_R_SFT |
89                 recovery_rate << RT5640_DRC_AGC_RC_SFT |
90                 0x1 << RT5640_DRC_AGC_UPD_BIT);
91 }
92
93 static void set_digital_boost_gain(struct snd_soc_codec *codec,
94                         int post_gain, int pre_gain)
95 {
96         snd_soc_update_bits(codec, RT5640_DRC_AGC_2,
97                 RT5640_DRC_AGC_POB_MASK | RT5640_DRC_AGC_PRB_MASK,
98                 post_gain << RT5640_DRC_AGC_POB_SFT |
99                 pre_gain << RT5640_DRC_AGC_PRB_SFT);
100         snd_soc_update_bits(codec, RT5640_DRC_AGC_1, 
101                 RT5640_DRC_AGC_UPD, 1 << RT5640_DRC_AGC_UPD_BIT);
102 }
103
104 static void set_noise_gate(struct snd_soc_codec *codec, int noise_gate_en,
105         int noise_gate_hold_en, int compression_gain, int noise_gate_th)
106 {
107         snd_soc_update_bits(codec, RT5640_DRC_AGC_3,
108                 RT5640_DRC_AGC_NGB_MASK | RT5640_DRC_AGC_NG_MASK |
109                 RT5640_DRC_AGC_NGH_MASK | RT5640_DRC_AGC_NGT_MASK,
110                 noise_gate_en << RT5640_DRC_AGC_NG_SFT |
111                 noise_gate_hold_en << RT5640_DRC_AGC_NGH_SFT |
112                 compression_gain << RT5640_DRC_AGC_NGB_SFT |
113                 noise_gate_th << RT5640_DRC_AGC_NGT_SFT);
114         snd_soc_update_bits(codec, RT5640_DRC_AGC_1,
115                 RT5640_DRC_AGC_UPD, 1 << RT5640_DRC_AGC_UPD_BIT);
116 }
117
118 static void set_drc_agc_compression(struct snd_soc_codec *codec,
119                 int compression_en, int compression_ratio)
120 {
121         snd_soc_update_bits(codec, RT5640_DRC_AGC_2,
122                 RT5640_DRC_AGC_CP_MASK | RT5640_DRC_AGC_CPR_MASK,
123                 compression_en << RT5640_DRC_AGC_CP_SFT |
124                 compression_ratio << RT5640_DRC_AGC_CPR_SFT);
125         snd_soc_update_bits(codec, RT5640_DRC_AGC_1,
126                 RT5640_DRC_AGC_UPD, 1 << RT5640_DRC_AGC_UPD_BIT);
127 }
128
129 static void get_drc_agc_enable(struct snd_soc_codec *codec, int *enable, int *path)
130 {
131         unsigned int reg = snd_soc_read(codec, RT5640_DRC_AGC_1);
132
133         *enable = (reg & RT5640_DRC_AGC_MASK) >> RT5640_DRC_AGC_SFT;
134         *path = (reg & RT5640_DRC_AGC_P_MASK) >> RT5640_DRC_AGC_P_SFT;
135 }
136
137 static void get_drc_agc_parameters(struct snd_soc_codec *codec, int *attack_rate,
138                 int *sample_rate, int *recovery_rate, int *limit_level)
139 {
140         unsigned int reg = snd_soc_read(codec, RT5640_DRC_AGC_3);
141
142         *limit_level = (reg & RT5640_DRC_AGC_TAR_MASK) >>
143                         RT5640_DRC_AGC_TAR_SFT;
144         reg = snd_soc_read(codec, RT5640_DRC_AGC_1);
145         *attack_rate = (reg & RT5640_DRC_AGC_AR_MASK) >> RT5640_DRC_AGC_AR_SFT;
146         *sample_rate = (reg & RT5640_DRC_AGC_R_MASK) >> RT5640_DRC_AGC_R_SFT;
147         *recovery_rate = (reg & RT5640_DRC_AGC_RC_MASK) >>
148                                 RT5640_DRC_AGC_RC_SFT;
149 }
150
151 static void get_digital_boost_gain(struct snd_soc_codec *codec,
152                         int *post_gain, int *pre_gain)
153 {
154         unsigned int reg = snd_soc_read(codec, RT5640_DRC_AGC_2);
155
156         *post_gain = (reg & RT5640_DRC_AGC_POB_MASK) >> RT5640_DRC_AGC_POB_SFT;
157         *pre_gain = (reg & RT5640_DRC_AGC_PRB_MASK) >> RT5640_DRC_AGC_PRB_SFT;
158 }
159
160 static void get_noise_gate(struct snd_soc_codec *codec, int *noise_gate_en,
161         int *noise_gate_hold_en, int *compression_gain, int *noise_gate_th)
162 {
163         unsigned int reg = snd_soc_read(codec, RT5640_DRC_AGC_3);
164
165         printk("get_noise_gate reg=0x%04x\n",reg);
166         *noise_gate_en = (reg & RT5640_DRC_AGC_NG_MASK) >>
167                                 RT5640_DRC_AGC_NG_SFT;
168         *noise_gate_hold_en = (reg & RT5640_DRC_AGC_NGH_MASK) >>
169                                 RT5640_DRC_AGC_NGH_SFT;
170         *compression_gain = (reg & RT5640_DRC_AGC_NGB_MASK) >>
171                                 RT5640_DRC_AGC_NGB_SFT;
172         *noise_gate_th = (reg & RT5640_DRC_AGC_NGT_MASK) >>
173                                 RT5640_DRC_AGC_NGT_SFT;
174 }
175
176 static void get_drc_agc_compression(struct snd_soc_codec *codec,
177                 int *compression_en, int *compression_ratio)
178 {
179         unsigned int reg = snd_soc_read(codec, RT5640_DRC_AGC_2);
180
181         *compression_en = (reg & RT5640_DRC_AGC_CP_MASK) >>
182                                 RT5640_DRC_AGC_CP_SFT;
183         *compression_ratio = (reg & RT5640_DRC_AGC_CPR_MASK) >>
184                                 RT5640_DRC_AGC_CPR_SFT;
185 }
186
187 int rt5640_ioctl_common(struct snd_hwdep *hw, struct file *file,
188                         unsigned int cmd, unsigned long arg)
189 {
190         struct snd_soc_codec *codec = hw->private_data;
191         struct rt56xx_cmd __user *_rt56xx = (struct rt56xx_cmd *)arg;
192         struct rt56xx_cmd rt56xx;
193         struct rt56xx_ops *ioctl_ops = rt56xx_get_ioctl_ops();
194         int *buf, mask1 = 0, mask2 = 0;
195         static int eq_mode;
196
197         if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx))) {
198                 dev_err(codec->dev,"copy_from_user faild\n");
199                 return -EFAULT;
200         }
201         dev_dbg(codec->dev, "%s(): rt56xx.number=%zu, cmd=%d\n",
202                 __func__, rt56xx.number, cmd);
203         buf = kmalloc(sizeof(*buf) * rt56xx.number, GFP_KERNEL);
204         if (buf == NULL)
205                 return -ENOMEM;
206         if (copy_from_user(buf, rt56xx.buf, sizeof(*buf) * rt56xx.number)) {
207                 goto err;
208         }
209         
210         switch (cmd) {
211         case RT_SET_CODEC_HWEQ_IOCTL:
212                 if (eq_mode == *buf)
213                         break;
214                 eq_mode = *buf;
215                 rt5640_update_eqmode(codec, eq_mode);
216                 break;
217
218         case RT_GET_CODEC_ID:
219                 *buf = snd_soc_read(codec, RT5640_VENDOR_ID2);
220                 if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
221                         goto err;
222                 break;
223
224         case RT_SET_CODEC_SPK_VOL_IOCTL:
225                 if(*(buf) <= 0x27) {
226                         snd_soc_update_bits(codec, RT5640_SPK_VOL,
227                                 RT5640_L_VOL_MASK | RT5640_R_VOL_MASK,
228                                 *(buf) << RT5640_L_VOL_SFT |
229                                 *(buf) << RT5640_R_VOL_SFT);
230                 }
231                 break;
232
233         case RT_SET_CODEC_MIC_GAIN_IOCTL:
234                 if(*(buf) <= 0x8) {
235                         snd_soc_update_bits(codec, RT5640_IN1_IN2,
236                                 RT5640_BST_MASK1, *(buf) << RT5640_BST_SFT1);
237                         snd_soc_update_bits(codec, RT5640_IN3_IN4,
238                                 RT5640_BST_MASK2, *(buf) << RT5640_BST_SFT2);
239                 }
240                 break;
241
242         case RT_SET_CODEC_3D_SPK_IOCTL:
243                 if(rt56xx.number < 4)
244                         break;
245                 if (NULL == ioctl_ops->index_update_bits)
246                         break;
247
248                 mask1 = 0;
249                 if(*buf != -1)
250                         mask1 |= RT5640_3D_SPK_MASK;
251                 if(*(buf + 1) != -1)
252                         mask1 |= RT5640_3D_SPK_M_MASK;
253                 if(*(buf + 2) != -1)
254                         mask1 |= RT5640_3D_SPK_CG_MASK;
255                 if(*(buf + 3) != -1)
256                         mask1 |= RT5640_3D_SPK_SG_MASK;
257                 ioctl_ops->index_update_bits(codec, RT5640_3D_SPK, mask1,
258                         *(buf) << RT5640_3D_SPK_SFT |
259                         *(buf + 1) << RT5640_3D_SPK_M_SFT |
260                         *(buf + 2) << RT5640_3D_SPK_CG_SFT |
261                         *(buf + 3) << RT5640_3D_SPK_SG_SFT);
262                 break;
263
264         case RT_SET_CODEC_MP3PLUS_IOCTL:
265                 if(rt56xx.number < 5)
266                         break;
267                 mask1 = mask2 = 0;
268                 if(*buf != -1)
269                         mask1 |= RT5640_M_MP3_MASK;
270                 if(*(buf + 1) != -1)
271                         mask1 |= RT5640_EG_MP3_MASK;
272                 if(*(buf + 2) != -1)
273                         mask2 |= RT5640_OG_MP3_MASK;
274                 if(*(buf + 3) != -1)
275                         mask2 |= RT5640_HG_MP3_MASK;
276                 if(*(buf + 4) != -1)
277                         mask2 |= RT5640_MP3_WT_MASK;
278                 
279                 snd_soc_update_bits(codec, RT5640_MP3_PLUS1, mask1,
280                         *(buf) << RT5640_M_MP3_SFT |
281                         *(buf + 1) << RT5640_EG_MP3_SFT);
282                 snd_soc_update_bits(codec, RT5640_MP3_PLUS2, mask2,
283                         *(buf + 2) << RT5640_OG_MP3_SFT |
284                         *(buf + 3) << RT5640_HG_MP3_SFT |
285                         *(buf + 4) << RT5640_MP3_WT_SFT);
286                 break;
287         case RT_SET_CODEC_3D_HEADPHONE_IOCTL:
288                 if(rt56xx.number < 4)
289                         break;
290                 if (NULL == ioctl_ops->index_update_bits)
291                         break;
292
293                 mask1 = 0;
294                 if(*buf != -1)
295                         mask1 |= RT5640_3D_HP_MASK;
296                 if(*(buf + 1) != -1)
297                         mask1 |= RT5640_3D_BT_MASK;
298                 if(*(buf + 2) != -1)
299                         mask1 |= RT5640_3D_1F_MIX_MASK;
300                 if(*(buf + 3) != -1)
301                         mask1 |= RT5640_3D_HP_M_MASK;
302
303                 snd_soc_update_bits(codec, RT5640_3D_HP, mask1,
304                         *(buf)<<RT5640_3D_HP_SFT |
305                         *(buf + 1) << RT5640_3D_BT_SFT |
306                         *(buf + 2) << RT5640_3D_1F_MIX_SFT |
307                         *(buf + 3) << RT5640_3D_HP_M_SFT);
308                 if(*(buf + 4) != -1)
309                         ioctl_ops->index_update_bits(codec,
310                                         0x59, 0x1f, *(buf+4));
311                 break;
312
313         case RT_SET_CODEC_BASS_BACK_IOCTL:
314                 if(rt56xx.number < 3)
315                         break;
316                 mask1 = 0;
317                 if(*buf != -1)
318                         mask1 |= RT5640_BB_MASK;
319                 if(*(buf + 1) != -1)
320                         mask1 |= RT5640_BB_CT_MASK;
321                 if(*(buf + 2) != -1)
322                         mask1 |= RT5640_G_BB_BST_MASK;
323                 
324                 snd_soc_update_bits(codec, RT5640_BASE_BACK, mask1,
325                         *(buf) << RT5640_BB_SFT |
326                         *(buf + 1) << RT5640_BB_CT_SFT |
327                         *(buf + 2) << RT5640_G_BB_BST_SFT);
328                 break;
329
330         case RT_SET_CODEC_DIPOLE_SPK_IOCTL:
331                 if(rt56xx.number < 2)
332                         break;
333                 if (NULL == ioctl_ops->index_update_bits)
334                         break;
335
336                 mask1 = 0;
337                 if(*buf != -1)
338                         mask1 |= RT5640_DP_SPK_MASK;
339                 if(*(buf + 1) != -1)
340                         mask1 |= RT5640_DP_ATT_MASK;
341                 
342                 ioctl_ops->index_update_bits(codec, RT5640_DIP_SPK_INF,
343                         mask1, *(buf) << RT5640_DP_SPK_SFT |
344                         *(buf + 1) << RT5640_DP_ATT_SFT );
345                 break;
346
347         case RT_SET_CODEC_DRC_AGC_ENABLE_IOCTL:
348                 if(rt56xx.number < 2)
349                         break;
350                 set_drc_agc_enable(codec, *(buf), *(buf + 1));
351                 break;
352
353         case RT_SET_CODEC_DRC_AGC_PAR_IOCTL:
354                 if(rt56xx.number < 4)
355                         break;
356                 set_drc_agc_parameters(codec, *(buf), *(buf + 1),
357                                 *(buf + 2), *(buf + 3));
358                 break;
359
360         case RT_SET_CODEC_DIGI_BOOST_GAIN_IOCTL:
361                 if(rt56xx.number < 2)
362                         break;
363                 set_digital_boost_gain(codec, *(buf), *(buf + 1));
364                 break;
365
366         case RT_SET_CODEC_NOISE_GATE_IOCTL:
367                 if(rt56xx.number < 4)
368                         break;
369                 set_noise_gate(codec, *(buf), *(buf + 1),
370                                 *(buf + 2), *(buf + 3));
371                 break;
372
373         case RT_SET_CODEC_DRC_AGC_COMP_IOCTL:
374                 if(rt56xx.number < 2)
375                         break;
376                 set_drc_agc_compression(codec, *(buf), *(buf + 1));
377                 break;
378
379         case RT_SET_CODEC_WNR_ENABLE_IOCTL:
380                 if (NULL == ioctl_ops->index_update_bits)
381                         break;
382
383                 ioctl_ops->index_update_bits(codec, RT5640_WND_1,
384                         RT5640_WND_MASK, *(buf) << RT5640_WND_SFT );
385                 break;
386
387         case RT_GET_CODEC_DRC_AGC_ENABLE_IOCTL:
388                 if(rt56xx.number < 2)
389                         break;
390                 get_drc_agc_enable(codec, (buf), (buf + 1));
391                 if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
392                         goto err;
393                 break;
394
395         case RT_GET_CODEC_DRC_AGC_PAR_IOCTL:
396                 if(rt56xx.number < 4)
397                         break;
398                 get_drc_agc_parameters(codec, (buf), (buf + 1),
399                                 (buf + 2), (buf + 3));
400                 if (copy_to_user(rt56xx.buf, buf,
401                         sizeof(*buf) * rt56xx.number))
402                         goto err;
403                 break;
404
405         case RT_GET_CODEC_DIGI_BOOST_GAIN_IOCTL:
406                 if(rt56xx.number < 2)
407                         break;
408                 get_digital_boost_gain(codec, (buf), (buf + 1));
409                 if (copy_to_user(rt56xx.buf, buf,
410                         sizeof(*buf) * rt56xx.number))
411                         goto err;
412                 break;
413
414         case RT_GET_CODEC_NOISE_GATE_IOCTL:
415                 if(rt56xx.number < 4)
416                         break;
417                 get_noise_gate(codec, (buf), (buf + 1), (buf + 2), (buf + 3));
418                 if (copy_to_user(rt56xx.buf, buf,
419                         sizeof(*buf) * rt56xx.number))
420                         goto err;
421                 break;
422
423         case RT_GET_CODEC_DRC_AGC_COMP_IOCTL:
424                 if(rt56xx.number < 2)
425                         break;
426                 get_drc_agc_compression(codec, (buf), (buf + 1));
427                 if (copy_to_user(rt56xx.buf, buf,
428                         sizeof(*buf) * rt56xx.number))
429                         goto err;
430                 break;
431
432         case RT_GET_CODEC_SPK_VOL_IOCTL:
433                 *buf = (snd_soc_read(codec, RT5640_SPK_VOL) & RT5640_L_VOL_MASK)
434                         >> RT5640_L_VOL_SFT;
435                 if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
436                         goto err;
437                 break;
438
439         case RT_GET_CODEC_MIC_GAIN_IOCTL:
440                 *buf = (snd_soc_read(codec, RT5640_IN1_IN2) & RT5640_BST_MASK1)
441                         >> RT5640_BST_SFT1;
442                 if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
443                         goto err;
444                 break;
445 #if defined(CONFIG_SND_SOC_RT5642_MODULE) || defined(CONFIG_SND_SOC_RT5642)
446         case RT_READ_CODEC_DSP_IOCTL:
447         case RT_WRITE_CODEC_DSP_IOCTL:
448         case RT_GET_CODEC_DSP_MODE_IOCTL:
449                 return rt56xx_dsp_ioctl_common(hw, file, cmd, arg);
450 #endif
451         case RT_GET_CODEC_HWEQ_IOCTL:
452         case RT_GET_CODEC_3D_SPK_IOCTL:
453         case RT_GET_CODEC_MP3PLUS_IOCTL:
454         case RT_GET_CODEC_3D_HEADPHONE_IOCTL:
455         case RT_GET_CODEC_BASS_BACK_IOCTL:
456         case RT_GET_CODEC_DIPOLE_SPK_IOCTL:
457         default:
458                 break;
459         }
460
461         kfree(buf);
462         return 0;
463
464 err:
465         kfree(buf);
466         return -EFAULT;
467 }
468 EXPORT_SYMBOL_GPL(rt5640_ioctl_common);