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