2 * rt3261_ioctl.h -- RT3261 ALSA SoC audio driver IO control
4 * Copyright 2012 Realtek Microelectronics
5 * Author: Bard <bardliao@realtek.com>
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.
12 #include <linux/spi/spi.h>
13 #include <sound/soc.h>
14 #include "rt_codec_ioctl.h"
15 #include "rt3261_ioctl.h"
18 hweq_t hweq_param[] = {
25 {0xa0, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaf},
26 {0x1c10, 0xc1cc, 0x1e5d, 0x0699, 0xcd48, 0x188d, 0x0699, 0xc3b6, 0x1cd0, 0x0699, 0x0436},
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},
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},
40 {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa9, 0xaa, 0xae},
41 {0x1eb5, 0xfcb6, 0xc1d4, 0x1e5d, 0x0e23, 0xd92e, 0x16e6, 0xfcb6, 0x0969, 0xf988, 0x0436},
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},
50 {0xa2, 0xa3, 0xa4, 0xa5, 0xa6},
51 {0xca4a, 0x17f8, 0x0fec, 0xca4a, 0x17f8},
65 #define RT3261_HWEQ_LEN ARRAY_SIZE(hweq_param)
67 static int rt3261_update_eqmode(
68 struct snd_soc_codec *codec, int mode)
70 struct rt_codec_ops *ioctl_ops = rt_codec_get_ioctl_ops();
73 if(codec == NULL || mode >= RT3261_HWEQ_LEN)
76 dev_dbg(codec->dev, "%s(): mode=%d\n", __func__, mode);
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]);
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);
94 void set_drc_agc_enable(struct snd_soc_codec *codec, int enable, int path)
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);
102 void set_drc_agc_parameters(struct snd_soc_codec *codec, int attack_rate,
103 int sample_rate, int recovery_rate, int limit_level)
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);
115 void set_digital_boost_gain(struct snd_soc_codec *codec,
116 int post_gain, int pre_gain)
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);
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)
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);
140 void set_drc_agc_compression(struct snd_soc_codec *codec,
141 int compression_en, int compression_ratio)
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);
151 void get_drc_agc_enable(struct snd_soc_codec *codec, int *enable, int *path)
153 unsigned int reg = snd_soc_read(codec, RT3261_DRC_AGC_1);
155 *enable = (reg & RT3261_DRC_AGC_MASK) >> RT3261_DRC_AGC_SFT;
156 *path = (reg & RT3261_DRC_AGC_P_MASK) >> RT3261_DRC_AGC_P_SFT;
159 void get_drc_agc_parameters(struct snd_soc_codec *codec, int *attack_rate,
160 int *sample_rate, int *recovery_rate, int *limit_level)
162 unsigned int reg = snd_soc_read(codec, RT3261_DRC_AGC_3);
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;
173 void get_digital_boost_gain(struct snd_soc_codec *codec,
174 int *post_gain, int *pre_gain)
176 unsigned int reg = snd_soc_read(codec, RT3261_DRC_AGC_2);
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;
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)
185 unsigned int reg = snd_soc_read(codec, RT3261_DRC_AGC_3);
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;
198 void get_drc_agc_compression(struct snd_soc_codec *codec,
199 int *compression_en, int *compression_ratio)
201 unsigned int reg = snd_soc_read(codec, RT3261_DRC_AGC_2);
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;
209 int rt3261_ioctl_common(struct snd_hwdep *hw, struct file *file,
210 unsigned int cmd, unsigned long arg)
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;
219 if (copy_from_user(&rt_codec, _rt_codec, sizeof(rt_codec))) {
220 dev_err(codec->dev,"copy_from_user faild\n");
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);
228 if (copy_from_user(buf, rt_codec.buf, sizeof(*buf) * rt_codec.number)) {
233 case RT_SET_CODEC_HWEQ_IOCTL:
237 rt3261_update_eqmode(codec, eq_mode);
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))
246 case RT_SET_CODEC_SPK_VOL_IOCTL:
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);
255 case RT_SET_CODEC_MIC_GAIN_IOCTL:
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);
264 case RT_SET_CODEC_3D_SPK_IOCTL:
265 if(rt_codec.number < 4)
267 if (NULL == ioctl_ops->index_update_bits)
272 mask1 |= RT3261_3D_SPK_MASK;
274 mask1 |= RT3261_3D_SPK_M_MASK;
276 mask1 |= RT3261_3D_SPK_CG_MASK;
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);
286 case RT_SET_CODEC_MP3PLUS_IOCTL:
287 if(rt_codec.number < 5)
291 mask1 |= RT3261_M_MP3_MASK;
293 mask1 |= RT3261_EG_MP3_MASK;
295 mask2 |= RT3261_OG_MP3_MASK;
297 mask2 |= RT3261_HG_MP3_MASK;
299 mask2 |= RT3261_MP3_WT_MASK;
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);
309 case RT_SET_CODEC_3D_HEADPHONE_IOCTL:
310 if(rt_codec.number < 4)
312 if (NULL == ioctl_ops->index_update_bits)
317 mask1 |= RT3261_3D_HP_MASK;
319 mask1 |= RT3261_3D_BT_MASK;
321 mask1 |= RT3261_3D_1F_MIX_MASK;
323 mask1 |= RT3261_3D_HP_M_MASK;
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);
331 ioctl_ops->index_update_bits(codec,
332 0x59, 0x1f, *(buf+4));
335 case RT_SET_CODEC_BASS_BACK_IOCTL:
336 if(rt_codec.number < 3)
340 mask1 |= RT3261_BB_MASK;
342 mask1 |= RT3261_BB_CT_MASK;
344 mask1 |= RT3261_G_BB_BST_MASK;
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);
352 case RT_SET_CODEC_DIPOLE_SPK_IOCTL:
353 if(rt_codec.number < 2)
355 if (NULL == ioctl_ops->index_update_bits)
360 mask1 |= RT3261_DP_SPK_MASK;
362 mask1 |= RT3261_DP_ATT_MASK;
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 );
369 case RT_SET_CODEC_DRC_AGC_ENABLE_IOCTL:
370 if(rt_codec.number < 2)
372 set_drc_agc_enable(codec, *(buf), *(buf + 1));
375 case RT_SET_CODEC_DRC_AGC_PAR_IOCTL:
376 if(rt_codec.number < 4)
378 set_drc_agc_parameters(codec, *(buf), *(buf + 1),
379 *(buf + 2), *(buf + 3));
382 case RT_SET_CODEC_DIGI_BOOST_GAIN_IOCTL:
383 if(rt_codec.number < 2)
385 set_digital_boost_gain(codec, *(buf), *(buf + 1));
388 case RT_SET_CODEC_NOISE_GATE_IOCTL:
389 if(rt_codec.number < 4)
391 set_noise_gate(codec, *(buf), *(buf + 1),
392 *(buf + 2), *(buf + 3));
395 case RT_SET_CODEC_DRC_AGC_COMP_IOCTL:
396 if(rt_codec.number < 2)
398 set_drc_agc_compression(codec, *(buf), *(buf + 1));
401 case RT_SET_CODEC_WNR_ENABLE_IOCTL:
402 if (NULL == ioctl_ops->index_update_bits)
405 ioctl_ops->index_update_bits(codec, RT3261_WND_1,
406 RT3261_WND_MASK, *(buf) << RT3261_WND_SFT );
409 case RT_GET_CODEC_DRC_AGC_ENABLE_IOCTL:
410 if(rt_codec.number < 2)
412 get_drc_agc_enable(codec, (buf), (buf + 1));
413 if (copy_to_user(rt_codec.buf, buf, sizeof(*buf) * rt_codec.number))
417 case RT_GET_CODEC_DRC_AGC_PAR_IOCTL:
418 if(rt_codec.number < 4)
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))
427 case RT_GET_CODEC_DIGI_BOOST_GAIN_IOCTL:
428 if(rt_codec.number < 2)
430 get_digital_boost_gain(codec, (buf), (buf + 1));
431 if (copy_to_user(rt_codec.buf, buf,
432 sizeof(*buf) * rt_codec.number))
436 case RT_GET_CODEC_NOISE_GATE_IOCTL:
437 if(rt_codec.number < 4)
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))
445 case RT_GET_CODEC_DRC_AGC_COMP_IOCTL:
446 if(rt_codec.number < 2)
448 get_drc_agc_compression(codec, (buf), (buf + 1));
449 if (copy_to_user(rt_codec.buf, buf,
450 sizeof(*buf) * rt_codec.number))
454 case RT_GET_CODEC_SPK_VOL_IOCTL:
455 *buf = (snd_soc_read(codec, RT3261_SPK_VOL) & RT3261_L_VOL_MASK)
457 if (copy_to_user(rt_codec.buf, buf, sizeof(*buf) * rt_codec.number))
461 case RT_GET_CODEC_MIC_GAIN_IOCTL:
462 *buf = (snd_soc_read(codec, RT3261_IN1_IN2) & RT3261_BST_MASK1)
464 if (copy_to_user(rt_codec.buf, buf, sizeof(*buf) * rt_codec.number))
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:
485 EXPORT_SYMBOL_GPL(rt3261_ioctl_common);