Merge branch develop-3.10
[firefly-linux-kernel-4.4.55.git] / sound / soc / codecs / rt3261_ioctl.c
1 /*
2  * rt3261_ioctl.h  --  RT3261 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 "rt_codec_ioctl.h"
15 #include "rt3261_ioctl.h"
16 #include "rt3261.h"
17 #if defined (CONFIG_SND_SOC_RT3261)
18 #include "rt3261-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 RT3261_HWEQ_LEN ARRAY_SIZE(hweq_param)
39
40 int rt3261_update_eqmode(
41         struct snd_soc_codec *codec, int mode)
42 {
43         struct rt_codec_ops *ioctl_ops = rt_codec_get_ioctl_ops();
44         int i;
45         static int eq_mode;
46
47         if(codec == NULL ||  mode >= RT3261_HWEQ_LEN)
48                 return -EINVAL;
49
50         dev_dbg(codec->dev, "%s(): mode=%d\n", __func__, mode);
51
52         if(mode == eq_mode)
53                 return 0;
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, RT3261_EQ_CTRL2, RT3261_EQ_CTRL_MASK,
62                                         hweq_param[mode].ctrl);
63         snd_soc_update_bits(codec, RT3261_EQ_CTRL1,
64                 RT3261_EQ_UPD, RT3261_EQ_UPD);
65         snd_soc_update_bits(codec, RT3261_EQ_CTRL1, RT3261_EQ_UPD, 0);
66
67         eq_mode = mode;
68         return 0;
69 }
70
71 static void set_drc_agc_enable(struct snd_soc_codec *codec, int enable, int path)
72 {
73         snd_soc_update_bits(codec, RT3261_DRC_AGC_1, RT3261_DRC_AGC_P_MASK |
74                 RT3261_DRC_AGC_MASK | RT3261_DRC_AGC_UPD,
75                 enable << RT3261_DRC_AGC_SFT | path << RT3261_DRC_AGC_P_SFT |
76                 1 << RT3261_DRC_AGC_UPD_BIT);
77 }
78
79 static void set_drc_agc_parameters(struct snd_soc_codec *codec, int attack_rate,
80                         int sample_rate, int recovery_rate, int limit_level)
81 {
82         snd_soc_update_bits(codec, RT3261_DRC_AGC_3, RT3261_DRC_AGC_TAR_MASK,
83                                 limit_level << RT3261_DRC_AGC_TAR_SFT);
84         snd_soc_update_bits(codec, RT3261_DRC_AGC_1, RT3261_DRC_AGC_AR_MASK |
85                 RT3261_DRC_AGC_R_MASK | RT3261_DRC_AGC_UPD |
86                 RT3261_DRC_AGC_RC_MASK, attack_rate << RT3261_DRC_AGC_AR_SFT |
87                 sample_rate << RT3261_DRC_AGC_R_SFT |
88                 recovery_rate << RT3261_DRC_AGC_RC_SFT |
89                 0x1 << RT3261_DRC_AGC_UPD_BIT);
90 }
91
92 static void set_digital_boost_gain(struct snd_soc_codec *codec,
93                         int post_gain, int pre_gain)
94 {
95         snd_soc_update_bits(codec, RT3261_DRC_AGC_2,
96                 RT3261_DRC_AGC_POB_MASK | RT3261_DRC_AGC_PRB_MASK,
97                 post_gain << RT3261_DRC_AGC_POB_SFT |
98                 pre_gain << RT3261_DRC_AGC_PRB_SFT);
99         snd_soc_update_bits(codec, RT3261_DRC_AGC_1, 
100                 RT3261_DRC_AGC_UPD, 1 << RT3261_DRC_AGC_UPD_BIT);
101 }
102
103 static void set_noise_gate(struct snd_soc_codec *codec, int noise_gate_en,
104         int noise_gate_hold_en, int compression_gain, int noise_gate_th)
105 {
106         snd_soc_update_bits(codec, RT3261_DRC_AGC_3,
107                 RT3261_DRC_AGC_NGB_MASK | RT3261_DRC_AGC_NG_MASK |
108                 RT3261_DRC_AGC_NGH_MASK | RT3261_DRC_AGC_NGT_MASK,
109                 noise_gate_en << RT3261_DRC_AGC_NG_SFT |
110                 noise_gate_hold_en << RT3261_DRC_AGC_NGH_SFT |
111                 compression_gain << RT3261_DRC_AGC_NGB_SFT |
112                 noise_gate_th << RT3261_DRC_AGC_NGT_SFT);
113         snd_soc_update_bits(codec, RT3261_DRC_AGC_1,
114                 RT3261_DRC_AGC_UPD, 1 << RT3261_DRC_AGC_UPD_BIT);
115 }
116
117 static void set_drc_agc_compression(struct snd_soc_codec *codec,
118                 int compression_en, int compression_ratio)
119 {
120         snd_soc_update_bits(codec, RT3261_DRC_AGC_2,
121                 RT3261_DRC_AGC_CP_MASK | RT3261_DRC_AGC_CPR_MASK,
122                 compression_en << RT3261_DRC_AGC_CP_SFT |
123                 compression_ratio << RT3261_DRC_AGC_CPR_SFT);
124         snd_soc_update_bits(codec, RT3261_DRC_AGC_1,
125                 RT3261_DRC_AGC_UPD, 1 << RT3261_DRC_AGC_UPD_BIT);
126 }
127
128 static void get_drc_agc_enable(struct snd_soc_codec *codec, int *enable, int *path)
129 {
130         unsigned int reg = snd_soc_read(codec, RT3261_DRC_AGC_1);
131
132         *enable = (reg & RT3261_DRC_AGC_MASK) >> RT3261_DRC_AGC_SFT;
133         *path = (reg & RT3261_DRC_AGC_P_MASK) >> RT3261_DRC_AGC_P_SFT;
134 }
135
136 void get_drc_agc_parameters(struct snd_soc_codec *codec, int *attack_rate,
137                 int *sample_rate, int *recovery_rate, int *limit_level)
138 {
139         unsigned int reg = snd_soc_read(codec, RT3261_DRC_AGC_3);
140
141         *limit_level = (reg & RT3261_DRC_AGC_TAR_MASK) >>
142                         RT3261_DRC_AGC_TAR_SFT;
143         reg = snd_soc_read(codec, RT3261_DRC_AGC_1);
144         *attack_rate = (reg & RT3261_DRC_AGC_AR_MASK) >> RT3261_DRC_AGC_AR_SFT;
145         *sample_rate = (reg & RT3261_DRC_AGC_R_MASK) >> RT3261_DRC_AGC_R_SFT;
146         *recovery_rate = (reg & RT3261_DRC_AGC_RC_MASK) >>
147                                 RT3261_DRC_AGC_RC_SFT;
148 }
149
150 static void get_digital_boost_gain(struct snd_soc_codec *codec,
151                         int *post_gain, int *pre_gain)
152 {
153         unsigned int reg = snd_soc_read(codec, RT3261_DRC_AGC_2);
154
155         *post_gain = (reg & RT3261_DRC_AGC_POB_MASK) >> RT3261_DRC_AGC_POB_SFT;
156         *pre_gain = (reg & RT3261_DRC_AGC_PRB_MASK) >> RT3261_DRC_AGC_PRB_SFT;
157 }
158
159 static void get_noise_gate(struct snd_soc_codec *codec, int *noise_gate_en,
160         int *noise_gate_hold_en, int *compression_gain, int *noise_gate_th)
161 {
162         unsigned int reg = snd_soc_read(codec, RT3261_DRC_AGC_3);
163
164         printk("get_noise_gate reg=0x%04x\n",reg);
165         *noise_gate_en = (reg & RT3261_DRC_AGC_NG_MASK) >>
166                                 RT3261_DRC_AGC_NG_SFT;
167         *noise_gate_hold_en = (reg & RT3261_DRC_AGC_NGH_MASK) >>
168                                 RT3261_DRC_AGC_NGH_SFT;
169         *compression_gain = (reg & RT3261_DRC_AGC_NGB_MASK) >>
170                                 RT3261_DRC_AGC_NGB_SFT;
171         *noise_gate_th = (reg & RT3261_DRC_AGC_NGT_MASK) >>
172                                 RT3261_DRC_AGC_NGT_SFT;
173 }
174
175 static void get_drc_agc_compression(struct snd_soc_codec *codec,
176                 int *compression_en, int *compression_ratio)
177 {
178         unsigned int reg = snd_soc_read(codec, RT3261_DRC_AGC_2);
179
180         *compression_en = (reg & RT3261_DRC_AGC_CP_MASK) >>
181                                 RT3261_DRC_AGC_CP_SFT;
182         *compression_ratio = (reg & RT3261_DRC_AGC_CPR_MASK) >>
183                                 RT3261_DRC_AGC_CPR_SFT;
184 }
185
186 int rt3261_ioctl_common(struct snd_hwdep *hw, struct file *file,
187                         unsigned int cmd, unsigned long arg)
188 {
189         struct snd_soc_codec *codec = hw->private_data;
190         struct rt_codec_cmd __user *_rt_codec = (struct rt_codec_cmd *)arg;
191         struct rt_codec_cmd rt_codec;
192         struct rt_codec_ops *ioctl_ops = rt_codec_get_ioctl_ops();
193         int *buf, mask1 = 0, mask2 = 0;
194         static int eq_mode;
195
196         if (copy_from_user(&rt_codec, _rt_codec, sizeof(rt_codec))) {
197                 dev_err(codec->dev,"copy_from_user faild\n");
198                 return -EFAULT;
199         }
200         dev_dbg(codec->dev, "%s(): rt_codec.number=%zu, cmd=%d\n",
201                 __func__, rt_codec.number, cmd);
202         buf = kmalloc(sizeof(*buf) * rt_codec.number, GFP_KERNEL);
203         if (buf == NULL)
204                 return -ENOMEM;
205         if (copy_from_user(buf, rt_codec.buf, sizeof(*buf) * rt_codec.number)) {
206                 goto err;
207         }
208         
209         switch (cmd) {
210         case RT_SET_CODEC_HWEQ_IOCTL:
211                 if (eq_mode == *buf)
212                         break;
213                 eq_mode = *buf;
214                 rt3261_update_eqmode(codec, eq_mode);
215                 break;
216
217         case RT_GET_CODEC_ID:
218                 *buf = snd_soc_read(codec, RT3261_VENDOR_ID2);
219                 if (copy_to_user(rt_codec.buf, buf, sizeof(*buf) * rt_codec.number))
220                         goto err;
221                 break;
222
223         case RT_SET_CODEC_SPK_VOL_IOCTL:
224                 if(*(buf) <= 0x27) {
225                         snd_soc_update_bits(codec, RT3261_SPK_VOL,
226                                 RT3261_L_VOL_MASK | RT3261_R_VOL_MASK,
227                                 *(buf) << RT3261_L_VOL_SFT |
228                                 *(buf) << RT3261_R_VOL_SFT);
229                 }
230                 break;
231
232         case RT_SET_CODEC_MIC_GAIN_IOCTL:
233                 if(*(buf) <= 0x8) {
234                         snd_soc_update_bits(codec, RT3261_IN1_IN2,
235                                 RT3261_BST_MASK1, *(buf) << RT3261_BST_SFT1);
236                         snd_soc_update_bits(codec, RT3261_IN3_IN4,
237                                 RT3261_BST_MASK2, *(buf) << RT3261_BST_SFT2);
238                 }
239                 break;
240
241         case RT_SET_CODEC_3D_SPK_IOCTL:
242                 if(rt_codec.number < 4)
243                         break;
244                 if (NULL == ioctl_ops->index_update_bits)
245                         break;
246
247                 mask1 = 0;
248                 if(*buf != -1)
249                         mask1 |= RT3261_3D_SPK_MASK;
250                 if(*(buf + 1) != -1)
251                         mask1 |= RT3261_3D_SPK_M_MASK;
252                 if(*(buf + 2) != -1)
253                         mask1 |= RT3261_3D_SPK_CG_MASK;
254                 if(*(buf + 3) != -1)
255                         mask1 |= RT3261_3D_SPK_SG_MASK;
256                 ioctl_ops->index_update_bits(codec, RT3261_3D_SPK, mask1,
257                         *(buf) << RT3261_3D_SPK_SFT |
258                         *(buf + 1) << RT3261_3D_SPK_M_SFT |
259                         *(buf + 2) << RT3261_3D_SPK_CG_SFT |
260                         *(buf + 3) << RT3261_3D_SPK_SG_SFT);
261                 break;
262
263         case RT_SET_CODEC_MP3PLUS_IOCTL:
264                 if(rt_codec.number < 5)
265                         break;
266                 mask1 = mask2 = 0;
267                 if(*buf != -1)
268                         mask1 |= RT3261_M_MP3_MASK;
269                 if(*(buf + 1) != -1)
270                         mask1 |= RT3261_EG_MP3_MASK;
271                 if(*(buf + 2) != -1)
272                         mask2 |= RT3261_OG_MP3_MASK;
273                 if(*(buf + 3) != -1)
274                         mask2 |= RT3261_HG_MP3_MASK;
275                 if(*(buf + 4) != -1)
276                         mask2 |= RT3261_MP3_WT_MASK;
277                 
278                 snd_soc_update_bits(codec, RT3261_MP3_PLUS1, mask1,
279                         *(buf) << RT3261_M_MP3_SFT |
280                         *(buf + 1) << RT3261_EG_MP3_SFT);
281                 snd_soc_update_bits(codec, RT3261_MP3_PLUS2, mask2,
282                         *(buf + 2) << RT3261_OG_MP3_SFT |
283                         *(buf + 3) << RT3261_HG_MP3_SFT |
284                         *(buf + 4) << RT3261_MP3_WT_SFT);
285                 break;
286         case RT_SET_CODEC_3D_HEADPHONE_IOCTL:
287                 if(rt_codec.number < 4)
288                         break;
289                 if (NULL == ioctl_ops->index_update_bits)
290                         break;
291
292                 mask1 = 0;
293                 if(*buf != -1)
294                         mask1 |= RT3261_3D_HP_MASK;
295                 if(*(buf + 1) != -1)
296                         mask1 |= RT3261_3D_BT_MASK;
297                 if(*(buf + 2) != -1)
298                         mask1 |= RT3261_3D_1F_MIX_MASK;
299                 if(*(buf + 3) != -1)
300                         mask1 |= RT3261_3D_HP_M_MASK;
301
302                 snd_soc_update_bits(codec, RT3261_3D_HP, mask1,
303                         *(buf)<<RT3261_3D_HP_SFT |
304                         *(buf + 1) << RT3261_3D_BT_SFT |
305                         *(buf + 2) << RT3261_3D_1F_MIX_SFT |
306                         *(buf + 3) << RT3261_3D_HP_M_SFT);
307                 if(*(buf + 4) != -1)
308                         ioctl_ops->index_update_bits(codec,
309                                         0x59, 0x1f, *(buf+4));
310                 break;
311
312         case RT_SET_CODEC_BASS_BACK_IOCTL:
313                 if(rt_codec.number < 3)
314                         break;
315                 mask1 = 0;
316                 if(*buf != -1)
317                         mask1 |= RT3261_BB_MASK;
318                 if(*(buf + 1) != -1)
319                         mask1 |= RT3261_BB_CT_MASK;
320                 if(*(buf + 2) != -1)
321                         mask1 |= RT3261_G_BB_BST_MASK;
322                 
323                 snd_soc_update_bits(codec, RT3261_BASE_BACK, mask1,
324                         *(buf) << RT3261_BB_SFT |
325                         *(buf + 1) << RT3261_BB_CT_SFT |
326                         *(buf + 2) << RT3261_G_BB_BST_SFT);
327                 break;
328
329         case RT_SET_CODEC_DIPOLE_SPK_IOCTL:
330                 if(rt_codec.number < 2)
331                         break;
332                 if (NULL == ioctl_ops->index_update_bits)
333                         break;
334
335                 mask1 = 0;
336                 if(*buf != -1)
337                         mask1 |= RT3261_DP_SPK_MASK;
338                 if(*(buf + 1) != -1)
339                         mask1 |= RT3261_DP_ATT_MASK;
340                 
341                 ioctl_ops->index_update_bits(codec, RT3261_DIP_SPK_INF,
342                         mask1, *(buf) << RT3261_DP_SPK_SFT |
343                         *(buf + 1) << RT3261_DP_ATT_SFT );
344                 break;
345
346         case RT_SET_CODEC_DRC_AGC_ENABLE_IOCTL:
347                 if(rt_codec.number < 2)
348                         break;
349                 set_drc_agc_enable(codec, *(buf), *(buf + 1));
350                 break;
351
352         case RT_SET_CODEC_DRC_AGC_PAR_IOCTL:
353                 if(rt_codec.number < 4)
354                         break;
355                 set_drc_agc_parameters(codec, *(buf), *(buf + 1),
356                                 *(buf + 2), *(buf + 3));
357                 break;
358
359         case RT_SET_CODEC_DIGI_BOOST_GAIN_IOCTL:
360                 if(rt_codec.number < 2)
361                         break;
362                 set_digital_boost_gain(codec, *(buf), *(buf + 1));
363                 break;
364
365         case RT_SET_CODEC_NOISE_GATE_IOCTL:
366                 if(rt_codec.number < 4)
367                         break;
368                 set_noise_gate(codec, *(buf), *(buf + 1),
369                                 *(buf + 2), *(buf + 3));
370                 break;
371
372         case RT_SET_CODEC_DRC_AGC_COMP_IOCTL:
373                 if(rt_codec.number < 2)
374                         break;
375                 set_drc_agc_compression(codec, *(buf), *(buf + 1));
376                 break;
377
378         case RT_SET_CODEC_WNR_ENABLE_IOCTL:
379                 if (NULL == ioctl_ops->index_update_bits)
380                         break;
381
382                 ioctl_ops->index_update_bits(codec, RT3261_WND_1,
383                         RT3261_WND_MASK, *(buf) << RT3261_WND_SFT );
384                 break;
385
386         case RT_GET_CODEC_DRC_AGC_ENABLE_IOCTL:
387                 if(rt_codec.number < 2)
388                         break;
389                 get_drc_agc_enable(codec, (buf), (buf + 1));
390                 if (copy_to_user(rt_codec.buf, buf, sizeof(*buf) * rt_codec.number))
391                         goto err;
392                 break;
393
394         case RT_GET_CODEC_DRC_AGC_PAR_IOCTL:
395                 if(rt_codec.number < 4)
396                         break;
397                 get_drc_agc_parameters(codec, (buf), (buf + 1),
398                                 (buf + 2), (buf + 3));
399                 if (copy_to_user(rt_codec.buf, buf,
400                         sizeof(*buf) * rt_codec.number))
401                         goto err;
402                 break;
403
404         case RT_GET_CODEC_DIGI_BOOST_GAIN_IOCTL:
405                 if(rt_codec.number < 2)
406                         break;
407                 get_digital_boost_gain(codec, (buf), (buf + 1));
408                 if (copy_to_user(rt_codec.buf, buf,
409                         sizeof(*buf) * rt_codec.number))
410                         goto err;
411                 break;
412
413         case RT_GET_CODEC_NOISE_GATE_IOCTL:
414                 if(rt_codec.number < 4)
415                         break;
416                 get_noise_gate(codec, (buf), (buf + 1), (buf + 2), (buf + 3));
417                 if (copy_to_user(rt_codec.buf, buf,
418                         sizeof(*buf) * rt_codec.number))
419                         goto err;
420                 break;
421
422         case RT_GET_CODEC_DRC_AGC_COMP_IOCTL:
423                 if(rt_codec.number < 2)
424                         break;
425                 get_drc_agc_compression(codec, (buf), (buf + 1));
426                 if (copy_to_user(rt_codec.buf, buf,
427                         sizeof(*buf) * rt_codec.number))
428                         goto err;
429                 break;
430
431         case RT_GET_CODEC_SPK_VOL_IOCTL:
432                 *buf = (snd_soc_read(codec, RT3261_SPK_VOL) & RT3261_L_VOL_MASK)
433                         >> RT3261_L_VOL_SFT;
434                 if (copy_to_user(rt_codec.buf, buf, sizeof(*buf) * rt_codec.number))
435                         goto err;
436                 break;
437
438         case RT_GET_CODEC_MIC_GAIN_IOCTL:
439                 *buf = (snd_soc_read(codec, RT3261_IN1_IN2) & RT3261_BST_MASK1)
440                         >> RT3261_BST_SFT1;
441                 if (copy_to_user(rt_codec.buf, buf, sizeof(*buf) * rt_codec.number))
442                         goto err;
443                 break;
444 #if defined (CONFIG_SND_SOC_RT3261)
445         case RT_READ_CODEC_DSP_IOCTL:
446         case RT_WRITE_CODEC_DSP_IOCTL:
447         case RT_GET_CODEC_DSP_MODE_IOCTL:
448                 return rt_codec_dsp_ioctl_common(hw, file, cmd, arg);
449 #endif
450         case RT_GET_CODEC_HWEQ_IOCTL:
451         case RT_GET_CODEC_3D_SPK_IOCTL:
452         case RT_GET_CODEC_MP3PLUS_IOCTL:
453         case RT_GET_CODEC_3D_HEADPHONE_IOCTL:
454         case RT_GET_CODEC_BASS_BACK_IOCTL:
455         case RT_GET_CODEC_DIPOLE_SPK_IOCTL:
456         default:
457                 break;
458         }
459
460         kfree(buf);
461         return 0;
462
463 err:
464         kfree(buf);
465         return -EFAULT;
466 }
467 EXPORT_SYMBOL_GPL(rt3261_ioctl_common);